Skip to content

Block Types

TicketEnvelope dataclass

Bases: Serializable

GP-0.7.2-eq:6.29 (bold_E_T) | Single item in the tickets extrinsic. Manages selection of validators for permissioning of block authoring

Attributes:

Name Type Description
attempt U8

GP-0.7.2-eq:6.29 (e) | An entry index

signature Array(U8, 784)

GP-0.7.2-eq:6.29 (p) | Proof of a ticket's validity

Source code in pyjamaz/models/block.py
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
@dataclass
class TicketEnvelope(Serializable):
    """
    GP-0.7.2-eq:6.29 (bold_E_T) | Single item in the tickets extrinsic. Manages selection of validators for
    permissioning of block authoring

    Attributes
    ----------
    attempt: U8
        GP-0.7.2-eq:6.29 (e) | An entry index
    signature: Array(U8,784)
        GP-0.7.2-eq:6.29 (p) | Proof of a ticket's validity
    """
    attempt: int = field(metadata={'codec': U8})
    signature: bytes = field(metadata={'codec': Array(U8, 784)})

    def __post_init__(self):
        # Validate that attempt is a valid U8 integer
        if not isinstance(self.attempt, int) or not (0 <= self.attempt <= 255):
            raise BlockValidationError("Attempt must be an integer between 0 and 255")

        # Validate that signature is a valid ByteArray784
        if not isinstance(self.signature, (bytes, bytearray)) or len(self.signature) != 784:
            raise BlockValidationError("Signature must be a bytes object of length 784")

    def generate_vrf_input(self, entropy: bytes) -> bytes:
        """
        GP-0.7.2-eq:6.31

        Parameters
        ----------
        entropy

        Returns
        -------
        bytes
        """

        return vrf_input_ticket_seal(entropy, self.attempt)

generate_vrf_input(entropy: bytes) -> bytes

GP-0.7.2-eq:6.31

Parameters:

Name Type Description Default
entropy bytes
required

Returns:

Type Description
bytes
Source code in pyjamaz/models/block.py
64
65
66
67
68
69
70
71
72
73
74
75
76
77
def generate_vrf_input(self, entropy: bytes) -> bytes:
    """
    GP-0.7.2-eq:6.31

    Parameters
    ----------
    entropy

    Returns
    -------
    bytes
    """

    return vrf_input_ticket_seal(entropy, self.attempt)

Judgement dataclass

Bases: Serializable

GP-0.7.2-eq:10.2 (third element of the tuple in bold_E_V) | An individual judgements coming from a validator

Attributes:

Name Type Description
vote Bool

GP-0.7.2-eq:10.2 ({T/F}) | A vote

index U16

GP-0.7.2-eq:10.2 (blackboard_N_V) | A validator index

signature H512

GP-0.7.2-eq:10.2 (blackboard_V_-) | A valid Ed25519 signature corresponding to the validator index

Source code in pyjamaz/models/block.py
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
@dataclass
class Judgement(Serializable):
    """
    GP-0.7.2-eq:10.2 (third element of the tuple in bold_E_V) | An individual judgements coming from a validator

    Attributes
    ----------
    vote: Bool
        GP-0.7.2-eq:10.2 ({T/F}) | A vote
    index: U16
        GP-0.7.2-eq:10.2 (blackboard_N_V) | A validator index
    signature: H512
        GP-0.7.2-eq:10.2 (blackboard_V_-) | A valid Ed25519 signature corresponding to the validator index
    """
    vote: bool = field(metadata={'codec': Bool()})
    index: int = field(metadata={'codec': U16})
    signature: bytes = field(metadata={'codec': H512})

    def get_signing_context(self) -> bytes:
        """
        GP-0.7.2-eq:10.4

        Returns
        -------
        bytes
        """
        return b'jam_valid' if self.vote else b'jam_invalid'

get_signing_context() -> bytes

GP-0.7.2-eq:10.4

Returns:

Type Description
bytes
Source code in pyjamaz/models/block.py
 98
 99
100
101
102
103
104
105
106
def get_signing_context(self) -> bytes:
    """
    GP-0.7.2-eq:10.4

    Returns
    -------
    bytes
    """
    return b'jam_valid' if self.vote else b'jam_invalid'

Verdict dataclass

Bases: Serializable

GP-0.7.2-eq:10.2 (bold_E_V) | A compilation of judgements coming from exactly two-thirds plus one of either the active validator set or the previous epoch's validator set

Attributes:

Name Type Description
target H256

GP-0.7.2-eq:10.2 (blackboard_H in bold_E_V) | A work-report hash

age U32

GP-0.7.2-eq:10.2 (second element of the tuple in bold_E_V) | Determines whether the current or the previous validator set applies to this verdict

votes Vec(fault)

GP-0.7.2-eq:10.2 (third element of the tuple in bold_E_V) | A set of judgements by two-thirds plus one of either the current or the previous validator set

Source code in pyjamaz/models/block.py
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
@dataclass
class Verdict(Serializable):
    """
    GP-0.7.2-eq:10.2 (bold_E_V) | A compilation of judgements coming from exactly two-thirds plus one of either the
    active validator set or the previous epoch's validator set

    Attributes
    ----------
    target: H256
        GP-0.7.2-eq:10.2 (blackboard_H in bold_E_V) | A work-report hash
    age: U32
        GP-0.7.2-eq:10.2 (second element of the tuple in bold_E_V) | Determines whether the current or the previous
        validator set applies to this verdict
    votes: Vec(fault)
        GP-0.7.2-eq:10.2 (third element of the tuple in bold_E_V) | A set of judgements by two-thirds plus one of
        either the current or the previous validator set
    """
    target: bytes = field(metadata={'codec': H256})
    age: int = field(metadata={'codec': U32})
    # Todo: change array size to use constants: 1+(floor(VALIDATOR_COUNT/3)*2)
    votes: List[Judgement] = field(metadata={'codec': Array(Judgement.to_codec_def(), 1+(floor(VALIDATOR_COUNT/3)*2))})

    @cached_property
    def total_positive_votes(self) -> int:
        """
        GP-0.7.2-eq:10.12

        Parameters
        ----------

        Returns
        -------
        int
        """
        return sum([v.vote for v in self.votes])

    def is_good(self) -> bool:
        return self.total_positive_votes == VALIDATOR_COUNT * 2 / 3 + 1

    def is_bad(self) -> bool:
        return self.total_positive_votes == 0

    def is_wonky(self) -> bool:
        return self.total_positive_votes == VALIDATOR_COUNT / 3

total_positive_votes: int cached property

GP-0.7.2-eq:10.12

Parameters:

Name Type Description Default
Returns
required
int
required

Culprit dataclass

Bases: Serializable

GP-0.7.2-eq:10.2 (bold_E_C) | Proof of misbehaviour of one or more validators by guaranteeing a work-report found to be invalid. This is considered an offence.

Attributes:

Name Type Description
target H256

GP-0.7.2-eq:10.2 (blackboard_H) | A work-report hash

key H256

GP-0.7.2-eq:10.2 (blackboard_H_-) | A validator Ed25519 public key

signature H512

GP-0.7.2-eq:10.2 (blackboard_V_-) | A valid Ed25519 signature corresponding to the validator's Ed25519 public key

Source code in pyjamaz/models/block.py
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
@dataclass
class Culprit(Serializable):
    """
    GP-0.7.2-eq:10.2 (bold_E_C) | Proof of misbehaviour of one or more validators by guaranteeing a work-report found
    to be invalid. This is considered an offence.

    Attributes
    ----------
    target: H256
        GP-0.7.2-eq:10.2 (blackboard_H) | A work-report hash
    key: H256
        GP-0.7.2-eq:10.2 (blackboard_H_-) | A validator Ed25519 public key
    signature: H512
        GP-0.7.2-eq:10.2 (blackboard_V_-) | A valid Ed25519 signature corresponding to the validator's Ed25519 public
        key
    """
    target: bytes = field(metadata={'codec': H256})
    key: bytes = field(metadata={'codec': H256})
    signature: bytes = field(metadata={'codec': H512})

    def has_valid_signature(self) -> bool:
        keypair = Ed25519Keypair.from_public_key(self.key)
        return keypair.verify(b'jam_guarantee' + self.target, self.signature)

Fault dataclass

Bases: Serializable

GP-0.7.2-eq:10.2 (bold_E_F) | Proof of misbehaviour of one or more validators by signing a judgement found to be contradiction to a work-report's validity. This is considered an offence.

Attributes:

Name Type Description
target H256

GP-0.7.2-eq:10.2 (blackboard_H) | A work-report hash

vote Bool

GP-0.7.2-eq:10.2 ({T/F}) | A vote

key H256

GP-0.7.2-eq:10.2 (blackboard_H_-) | A validator Ed25519 public key

signature H512

GP-0.7.2-eq:10.2 (blackboard_V_-) | A valid Ed25519 signature corresponding to the validator's Ed25519 public key

Source code in pyjamaz/models/block.py
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
@dataclass
class Fault(Serializable):
    """
    GP-0.7.2-eq:10.2 (bold_E_F) | Proof of misbehaviour of one or more validators by signing a judgement found to be
    contradiction to a work-report's validity. This is considered an offence.

    Attributes
    ----------
    target: H256
        GP-0.7.2-eq:10.2 (blackboard_H) | A work-report hash
    vote: Bool
        GP-0.7.2-eq:10.2 ({T/F}) | A vote
    key: H256
        GP-0.7.2-eq:10.2 (blackboard_H_-) | A validator Ed25519 public key
    signature: H512
        GP-0.7.2-eq:10.2 (blackboard_V_-) | A valid Ed25519 signature corresponding to the validator's Ed25519 public
        key
    """
    target: bytes = field(metadata={'codec': H256})
    vote: bool = field(metadata={'codec': Bool()})
    key: bytes = field(metadata={'codec': H256})
    signature: bytes = field(metadata={'codec': H512})

    def has_valid_signature(self) -> bool:
        keypair = Ed25519Keypair.from_public_key(self.key)
        return keypair.verify(b'jam_valid' if self.vote else b'jam_invalid' + self.target, self.signature)

ExtrinsicDisputes dataclass

Bases: Serializable

GP-0.7.2-eq:10.2 (bold_E_D) | judgements by validators on disputes.

Attributes:

Name Type Description
verdicts Vec(verdict)

GP-0.7.2-eq:10.2 (bold_E_V) | Compilations of judgements coming from exactly two-thirds plus one of either the active validator set or the previous epoch's validator set.

culprits Vec(culprit)

GP-0.7.2-eq:10.2 (bold_E_C) | Proofs of misbehaviour of one or more validators by guaranteeing a work-report found to be invalid. This is considered an offence.

faults Vec(fault)

GP-0.7.2-eq:10.2 (bold_E_F) | Proofs of misbehaviour of one or more validators by signing a judgement found to be contradiction to a work-report's validity. This is considered an offence.

Source code in pyjamaz/models/block.py
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
@dataclass
class ExtrinsicDisputes(Serializable):
    """
    GP-0.7.2-eq:10.2 (bold_E_D) | judgements by validators on disputes.

    Attributes
    ----------
    verdicts: Vec(verdict)
        GP-0.7.2-eq:10.2 (bold_E_V) | Compilations of judgements coming from exactly two-thirds plus one of either the
        active validator set or the previous epoch's validator set.
    culprits: Vec(culprit)
        GP-0.7.2-eq:10.2 (bold_E_C) | Proofs of misbehaviour of one or more validators by guaranteeing a work-report
        found to be invalid. This is considered an offence.
    faults: Vec(fault)
        GP-0.7.2-eq:10.2 (bold_E_F) | Proofs of misbehaviour of one or more validators by signing a judgement found to
        be contradiction to a work-report's validity. This is considered an offence.
    """
    verdicts: List[Verdict] = field(metadata={'codec': Vec(Verdict.to_codec_def())})
    culprits: List[Culprit] = field(metadata={'codec': Vec(Culprit.to_codec_def())})
    faults: List[Fault] = field(metadata={'codec': Vec(Fault.to_codec_def())})

Preimage dataclass

Bases: Serializable

GP-0.7.2-eq:12.35 (bold_E_P) | Single item in the preimages extrinsic. A preimage is a pair of service indices and data.

Attributes:

Name Type Description
requester U32

GP-0.7.2-eq:12.35 (blackboard_N_S) | A service index.

blob Bytes

GP-0.7.2-eq:12.35 (blackboard_B) | Arbitrary length data.

Source code in pyjamaz/models/block.py
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
@dataclass
class Preimage(Serializable):
    """
    GP-0.7.2-eq:12.35 (bold_E_P) | Single item in the preimages extrinsic. A preimage is a pair of service indices and
    data.

    Attributes
    ----------
    requester: U32
        GP-0.7.2-eq:12.35 (blackboard_N_S) | A service index.
    blob: Bytes
        GP-0.7.2-eq:12.35 (blackboard_B) | Arbitrary length data.
    """
    requester: int = field(metadata={'codec': U32})
    blob: bytes = field(metadata={'codec': Bytes})

    def hash(self):
        return blake2b_256_hash(self.blob)

    def length(self):
        return len(self.blob)

    def sort_key(self):
        return int(self.requester).to_bytes(4, byteorder="big") + self.blob

Assurance dataclass

Bases: Serializable

GP-0.7.2-eq:11.10 (bold_E_A) | Single item in the assurances extrinsic. Assurance by individual validator concerning which of the input data of workloads they have correctly received and are storing locally.

Attributes:

Name Type Description
anchor H256

GP-0.7.2-eq:11.10 (a) | Anchor to the parent_hash of the block.

bitfield BitArray(constant_C)

GP-0.7.2-eq:11.10 (f) | A sequence of binary values (bitstring) one per core.

validator_index U16

GP-0.7.2-eq:11.10 (v) | A validator index.

signature H512

GP-0.7.2-eq:11.10 (s) | A Ed25519 signature corresponding to the validator index.

Source code in pyjamaz/models/block.py
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
@dataclass
class Assurance(Serializable):
    """
    GP-0.7.2-eq:11.10 (bold_E_A) | Single item in the assurances extrinsic. Assurance by individual validator concerning
    which of the input data of workloads they have correctly received and are storing locally.

    Attributes
    ----------
    anchor: H256
        GP-0.7.2-eq:11.10 (a) | Anchor to the parent_hash of the block.
    bitfield: BitArray(constant_C)
        GP-0.7.2-eq:11.10 (f) | A sequence of binary values (bitstring) one per core.
    validator_index: U16
        GP-0.7.2-eq:11.10 (v) | A validator index.
    signature: H512
        GP-0.7.2-eq:11.10 (s) | A Ed25519 signature corresponding to the validator index.
    """
    anchor: bytes = field(metadata={'codec': H256})
    bitfield: List[bool] = field(metadata={'codec': BitArray(CORE_COUNT)})
    validator_index: int = field(metadata={'codec': U16})
    signature: bytes = field(metadata={'codec': H512})

    @property
    def bitfield_bytes(self) -> bytes:
        return BitArray(CORE_COUNT).encode(self.bitfield).to_bytes()

    @property
    def cores_engaged(self) -> list:
        return [c for c, e in enumerate(self.bitfield) if e == True]

Credential dataclass

Bases: Serializable

GP-0.7.2-eq:11.22 (a) | Single item in the signatures attribute of a guarantee comprising a validator index and its Ed25519 signature.

Attributes:

Name Type Description
validator_index U16

GP-0.7.2-eq:11.22 (blackboard_N_V) | A validator index.

signature H512

GP-0.7.2-eq:11.22 (blackboard_V_-) | A valid Ed25519 signature corresponding to the validator index.

Source code in pyjamaz/models/block.py
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
@dataclass
class Credential(Serializable):
    """
    GP-0.7.2-eq:11.22 (a) | Single item in the signatures attribute of a guarantee comprising a validator index and its
    Ed25519 signature.

    Attributes
    ----------
    validator_index: U16
        GP-0.7.2-eq:11.22 (blackboard_N_V) | A validator index.
    signature: H512
        GP-0.7.2-eq:11.22 (blackboard_V_-) | A valid Ed25519 signature corresponding to the validator index.
    """
    validator_index: int = field(metadata={'codec': U16})
    signature: bytes = field(metadata={'codec': H512})

Guarantee dataclass

Bases: Serializable

GP-0.7.2-eq:11.23 (bold_E_G) | Single item in the guarantees extrinsic. Report of newly completed workload whose accuracy is guaranteed by specific validators.

Attributes:

Name Type Description
report WorkReport

GP-0.7.2-eq:11.23 (bold_r) | A work report.

slot U32

GP-0.7.2-eq:11.23 (t) | A timeslot.

signatures Vec(Credential)

GP-0.7.2-eq:11.23 (a) | A set of credentials.

Source code in pyjamaz/models/block.py
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
@dataclass
class Guarantee(Serializable):
    """
    GP-0.7.2-eq:11.23 (bold_E_G) | Single item in the guarantees extrinsic. Report of newly completed workload whose
    accuracy is guaranteed by specific validators.

    Attributes
    ----------
    report: pyjamaz.models.common.WorkReport
        GP-0.7.2-eq:11.23 (bold_r) | A work report.
    slot: U32
        GP-0.7.2-eq:11.23 (t) | A timeslot.
    signatures: Vec(Credential)
        GP-0.7.2-eq:11.23 (a) | A set of credentials.
    """
    report: WorkReport = field(metadata={'codec': WorkReport.to_codec_def()})
    slot: int = field(metadata={'codec': U32})
    # Todo: consider renaming to 'credentials'
    signatures: List[Credential] = field(metadata={'codec': Vec(Credential.to_codec_def())})

Header dataclass

Bases: Serializable

GP-0.7.2-eq:5.1 (bold_H) | The header is a collection of metadata primarily concerned with cryptographic references to the blockchain ancestors and the operands and results of the present transition.

Serialization: GP-0.7.2-eq:C.22,23

Attributes:

Name Type Description
parent H256

GP-0.7.2-eq:5.2 (bold_H_P) | Hash of the header of the block's parent

parent_state_root H256

GP-0.7.2-eq:5.8 (bold_H_R) | Merkle root of the block's parent posterior state

extrinsic_hash H256

GP-0.7.2-eq:5.4 (bold_H_X) | Hash of the block's extrinsic data

timeslot U32

GP-0.7.2-eq:5.7,6.1 (bold_H_T,blackboard_N=U32) | Block's timeslot

epoch_marker EpochMark

GP-0.7.2-eq:5.10 (bold_H_E) | Optional block's epoch marker; fallback keys and entropy for next epoch

tickets_marker Option(Array(TicketBody, EPOCH_TIMESLOTS))

GP-0.7.2-eq:5.10 (bold_H_W) | Optional block's winning tickets marker; provides a series of 600 slot sealing tickets for the next epoch

author_index U16

GP-0.7.2-eq:5.9 (bold_H_I) | Index to identify the block author into the posterior state of the current validator set (kappa)

entropy_source Array(U8, 96)

GP-0.7.2-eq:6.17 (bold_H_V) | Entropy-yielding VRF signature

offenders_marker Vec(H256)

GP-0.7.2-eq:5.10 (bold_H_O) | List of Ed25519 keys for offenders

seal Array(U8, 96)

GP-0.7.2-eq:6.15,6.16 (bold_H_S) | Seal signature

Source code in pyjamaz/models/block.py
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
@dataclass
class Header(Serializable):
    """
    GP-0.7.2-eq:5.1 (bold_H) | The header is a collection of metadata primarily concerned with cryptographic references
    to the blockchain ancestors and the operands and results of the present transition.

    Serialization: GP-0.7.2-eq:C.22,23

    Attributes
    ----------
    parent: H256
        GP-0.7.2-eq:5.2 (bold_H_P) |
        Hash of the header of the block's parent
    parent_state_root: H256
        GP-0.7.2-eq:5.8 (bold_H_R) |
        Merkle root of the block's parent posterior state
    extrinsic_hash: H256
        GP-0.7.2-eq:5.4 (bold_H_X) |
        Hash of the block's extrinsic data
    timeslot: U32
        GP-0.7.2-eq:5.7,6.1 (bold_H_T,blackboard_N=U32) |
        Block's timeslot
    epoch_marker: EpochMark
        GP-0.7.2-eq:5.10 (bold_H_E) |
        Optional block's epoch marker; fallback keys and entropy for next epoch
    tickets_marker: Option(Array(TicketBody,EPOCH_TIMESLOTS))
        GP-0.7.2-eq:5.10 (bold_H_W) |
        Optional block's winning tickets marker; provides a series of 600 slot sealing tickets for the next epoch
    author_index: U16
        GP-0.7.2-eq:5.9 (bold_H_I) |
        Index to identify the block author into the posterior state of the current validator set (kappa)
    entropy_source: Array(U8, 96)
        GP-0.7.2-eq:6.17 (bold_H_V) |
        Entropy-yielding VRF signature
    offenders_marker: Vec(H256)
        GP-0.7.2-eq:5.10 (bold_H_O) |
        List of Ed25519 keys for offenders
    seal: Array(U8, 96)
        GP-0.7.2-eq:6.15,6.16 (bold_H_S) |
        Seal signature
    """
    parent: bytes = field(metadata={'codec': H256})
    parent_state_root: bytes = field(metadata={'codec': H256})
    extrinsic_hash: bytes = field(metadata={'codec': H256})
    timeslot: int = field(metadata={'codec': U32})
    epoch_marker: Optional[EpochMark] = field(metadata={'codec': Option(EpochMark.to_codec_def())})
    tickets_marker: Optional[List[TicketBody]] = field(
        metadata={'codec': Option(Array(TicketBody.to_codec_def(), EPOCH_TIMESLOTS))}
    )
    author_index: int = field(metadata={'codec': U16})
    entropy_source: bytes = field(metadata={'codec': Array(U8, 96)})
    offenders_marker: List[bytes] = field(metadata={'codec': Vec(H256)})
    seal: bytes = field(metadata={'codec': Array(U8, 96)})

    @property
    def hash(self) -> bytes:
        """
        Generates a hash of the header. GP-0.7.2-eq:5.2 E_U(H)

        Returns
        -------
        bytes
        """
        if getattr(self, '_hash', None) is not None:
            return getattr(self, '_hash')

        return blake2b_256_hash(self.to_jam_bytes().to_bytes())

    def get_unsigned_payload(self) -> bytes:
        """
        Payload to create seal signature GP-0.7.2-eq:6.15,6.16 E_U(H)

        Serialization: GP-0.7.2-eq:C.23

        Returns
        -------
        bytes
        """
        return self.to_jam_bytes().to_bytes()[:-96]

    @hash.setter
    def hash(self, value: bytes) -> None:
        setattr(self, '_hash', value)

    @property
    def slot_phase_index(self) -> int:
        """
        GP-0.7.2-eq:6.2 (m) | Function that returns the phase index into the epoch of the timeslot.

        Returns
        -------
        number: int
            Phase index into the epoch of the timeslot.

        """
        return self.timeslot % EPOCH_TIMESLOTS

    def verify_ticket_seal(self, bandersnatch_key: bytes, ticket_body: TicketBody, entropy: bytes) -> bytes:
        return ietf_vrf_verify(
            bytes(bandersnatch_key),
            vrf_input_ticket_seal(entropy, ticket_body.attempt),
            self.get_unsigned_payload(),
            bytes(self.seal)
        )

    def verify_fallback_seal(self, sealer_key: bytes, entropy: bytes) -> bytes:
        return ietf_vrf_verify(
            bytes(sealer_key),
            vrf_input_fallback_seal(entropy),
            self.get_unsigned_payload(),
            bytes(self.seal)
        )

    def generate_ticket_seal(self, bandersnatch_priv_key: bytes, entropy: bytes, ticket_attempt: int) -> bytes:
        """
        GP-0.7.2-eq:6.15 (bold_H_S) | Generate block seal using tickets

        Parameters
        ----------
        bandersnatch_priv_key
        entropy
        ticket_attempt

        Returns
        -------
        bytes
        """
        return ietf_vrf_sign(
            bandersnatch_priv_key,
            vrf_input_ticket_seal(entropy, ticket_attempt),
            self.get_unsigned_payload()
        )

    def generate_fallback_seal(self, bandersnatch_priv_key: bytes, entropy: bytes) -> bytes:
        """
        GP-0.7.2-eq:6.16 (bold_H_S) | Generate block seal using fallback method

        Parameters
        ----------
        bandersnatch_priv_key
        entropy

        Returns
        -------
        bytes
        """
        return ietf_vrf_sign(
            bandersnatch_priv_key,
            vrf_input_fallback_seal(entropy),
            self.get_unsigned_payload()
        )

    @classmethod
    def default(cls) -> 'Header':
        """
        GP-0.7.2-section:5 | We already presume consensus over this genesis header H^0 and the state it represents
        defined as σ^0. TODO make configurable
        """
        return Header(
                parent=bytes(32),
                parent_state_root=bytes(32),
                extrinsic_hash=bytes(32),
                timeslot=0,
                epoch_marker=None,
                tickets_marker=None,
                offenders_marker=[],
                author_index=0,
                entropy_source=bytes(96),
                seal=bytes(96)
            )

    @classmethod
    def genesis(cls, validators: List[ValidatorData]) -> 'Header':
        """
        Genesis header (Bold_H_0)

        Parameters
        ----------
        validators: List[ValidatorData]

        Returns
        -------
        Header
        """
        return Header(
            parent=bytes(32),
            parent_state_root=bytes(32),
            extrinsic_hash=bytes(32),
            timeslot=0,
            epoch_marker=EpochMark(
                entropy=bytes(32),
                tickets_entropy=bytes(32),
                validators=[
                    EpochMarkValidatorKeys(
                        bandersnatch=v.bandersnatch,
                        ed25519=v.ed25519
                    ) for v in validators
                ],
            ),
            tickets_marker=None,
            offenders_marker=[],
            author_index=65535,
            entropy_source=bytes(96),
            seal=bytes(96)
        )

    @property
    def author_bandersnatch_key(self) -> Optional[bytes]:
        """
        GP-0.7.2-eq:5.9 (bold_H_A) Derived author bandersnatch key from author index
        Returns
        -------
        Optional[bytes]
        """
        return getattr(self, '_author_bandersnatch_key', None)

    def set_author_bandersnatch_key(self, post_state_validator_pool: 'ValidatorPoolState'):
        """
        GP-0.7.2-eq:5.9 (bold_H_A) | Derive author bandersnatch key from validator pool (κ')

        Parameters
        ----------
        post_state_validator_pool: ValidatorPoolState

        Returns
        -------

        """
        if self.author_index >= len(post_state_validator_pool.validators):
            raise BlockValidationError("Invalid author index")

        setattr(self, '_author_bandersnatch_key', post_state_validator_pool.validators[self.author_index].bandersnatch)

hash: bytes property writable

Generates a hash of the header. GP-0.7.2-eq:5.2 E_U(H)

Returns:

Type Description
bytes

slot_phase_index: int property

GP-0.7.2-eq:6.2 (m) | Function that returns the phase index into the epoch of the timeslot.

Returns:

Name Type Description
number int

Phase index into the epoch of the timeslot.

author_bandersnatch_key: Optional[bytes] property

GP-0.7.2-eq:5.9 (bold_H_A) Derived author bandersnatch key from author index

Returns:

Type Description
Optional[bytes]

get_unsigned_payload() -> bytes

Payload to create seal signature GP-0.7.2-eq:6.15,6.16 E_U(H)

Serialization: GP-0.7.2-eq:C.23

Returns:

Type Description
bytes
Source code in pyjamaz/models/block.py
393
394
395
396
397
398
399
400
401
402
403
def get_unsigned_payload(self) -> bytes:
    """
    Payload to create seal signature GP-0.7.2-eq:6.15,6.16 E_U(H)

    Serialization: GP-0.7.2-eq:C.23

    Returns
    -------
    bytes
    """
    return self.to_jam_bytes().to_bytes()[:-96]

generate_ticket_seal(bandersnatch_priv_key: bytes, entropy: bytes, ticket_attempt: int) -> bytes

GP-0.7.2-eq:6.15 (bold_H_S) | Generate block seal using tickets

Parameters:

Name Type Description Default
bandersnatch_priv_key bytes
required
entropy bytes
required
ticket_attempt int
required

Returns:

Type Description
bytes
Source code in pyjamaz/models/block.py
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
def generate_ticket_seal(self, bandersnatch_priv_key: bytes, entropy: bytes, ticket_attempt: int) -> bytes:
    """
    GP-0.7.2-eq:6.15 (bold_H_S) | Generate block seal using tickets

    Parameters
    ----------
    bandersnatch_priv_key
    entropy
    ticket_attempt

    Returns
    -------
    bytes
    """
    return ietf_vrf_sign(
        bandersnatch_priv_key,
        vrf_input_ticket_seal(entropy, ticket_attempt),
        self.get_unsigned_payload()
    )

generate_fallback_seal(bandersnatch_priv_key: bytes, entropy: bytes) -> bytes

GP-0.7.2-eq:6.16 (bold_H_S) | Generate block seal using fallback method

Parameters:

Name Type Description Default
bandersnatch_priv_key bytes
required
entropy bytes
required

Returns:

Type Description
bytes
Source code in pyjamaz/models/block.py
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
def generate_fallback_seal(self, bandersnatch_priv_key: bytes, entropy: bytes) -> bytes:
    """
    GP-0.7.2-eq:6.16 (bold_H_S) | Generate block seal using fallback method

    Parameters
    ----------
    bandersnatch_priv_key
    entropy

    Returns
    -------
    bytes
    """
    return ietf_vrf_sign(
        bandersnatch_priv_key,
        vrf_input_fallback_seal(entropy),
        self.get_unsigned_payload()
    )

default() -> Header classmethod

GP-0.7.2-section:5 | We already presume consensus over this genesis header H^0 and the state it represents defined as σ^0. TODO make configurable

Source code in pyjamaz/models/block.py
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
@classmethod
def default(cls) -> 'Header':
    """
    GP-0.7.2-section:5 | We already presume consensus over this genesis header H^0 and the state it represents
    defined as σ^0. TODO make configurable
    """
    return Header(
            parent=bytes(32),
            parent_state_root=bytes(32),
            extrinsic_hash=bytes(32),
            timeslot=0,
            epoch_marker=None,
            tickets_marker=None,
            offenders_marker=[],
            author_index=0,
            entropy_source=bytes(96),
            seal=bytes(96)
        )

genesis(validators: List[ValidatorData]) -> Header classmethod

Genesis header (Bold_H_0)

Parameters:

Name Type Description Default
validators List[ValidatorData]
required

Returns:

Type Description
Header
Source code in pyjamaz/models/block.py
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
@classmethod
def genesis(cls, validators: List[ValidatorData]) -> 'Header':
    """
    Genesis header (Bold_H_0)

    Parameters
    ----------
    validators: List[ValidatorData]

    Returns
    -------
    Header
    """
    return Header(
        parent=bytes(32),
        parent_state_root=bytes(32),
        extrinsic_hash=bytes(32),
        timeslot=0,
        epoch_marker=EpochMark(
            entropy=bytes(32),
            tickets_entropy=bytes(32),
            validators=[
                EpochMarkValidatorKeys(
                    bandersnatch=v.bandersnatch,
                    ed25519=v.ed25519
                ) for v in validators
            ],
        ),
        tickets_marker=None,
        offenders_marker=[],
        author_index=65535,
        entropy_source=bytes(96),
        seal=bytes(96)
    )

set_author_bandersnatch_key(post_state_validator_pool: ValidatorPoolState)

GP-0.7.2-eq:5.9 (bold_H_A) | Derive author bandersnatch key from validator pool (κ')

Parameters:

Name Type Description Default
post_state_validator_pool ValidatorPoolState
required
Source code in pyjamaz/models/block.py
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
def set_author_bandersnatch_key(self, post_state_validator_pool: 'ValidatorPoolState'):
    """
    GP-0.7.2-eq:5.9 (bold_H_A) | Derive author bandersnatch key from validator pool (κ')

    Parameters
    ----------
    post_state_validator_pool: ValidatorPoolState

    Returns
    -------

    """
    if self.author_index >= len(post_state_validator_pool.validators):
        raise BlockValidationError("Invalid author index")

    setattr(self, '_author_bandersnatch_key', post_state_validator_pool.validators[self.author_index].bandersnatch)

Extrinsic dataclass

Bases: Serializable

GP-0.7.2-eq:4.3 (bold_E) | Extrinsic data is input data external to the system. Extrinsic data is split into several discrete portions.

Serialization: GP-0.7.2-eq:C.16

Attributes:

Name Type Description
tickets Vec(TicketEnvelope)

GP-0.7.2-eq:6.29 (bold_E_T) | Manages selection of validators for permissioning of block authoring

preimages Vec(Preimage)

GP-0.7.2-eq:12.35 (bold_E_P) | Static data presently being requested to be available for workloads to be able to fetch on demand

guarantees Vec(Guarantee)

GP-0.7.2-eq:11.22 (bold_E_G) | Reports of newly completed workloads whose accuracy is guaranteed by specific validators

assurances Vec(Assurance)

GP-0.7.2-eq:11.8 (bold_E_A) | Assurances by each validator concerning which of the input data of workloads they have correctly received and are storing locally

disputes ExtrinsicDisputes

GP-0.7.2-eq:10.2 (bold_E_D) | Votes by validators on disputes

Source code in pyjamaz/models/block.py
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
@dataclass
class Extrinsic(Serializable):
    """
    GP-0.7.2-eq:4.3 (bold_E) | Extrinsic data is input data external to the system.
    Extrinsic data is split into several discrete portions.

    Serialization: GP-0.7.2-eq:C.16

    Attributes
    ----------
    tickets: Vec(TicketEnvelope)
        GP-0.7.2-eq:6.29 (bold_E_T) |
        Manages selection of validators for permissioning of block authoring
    preimages: Vec(Preimage)
        GP-0.7.2-eq:12.35 (bold_E_P) |
        Static data presently being requested to be available for workloads to be able to fetch on demand
    guarantees: Vec(Guarantee)
        GP-0.7.2-eq:11.22 (bold_E_G) |
        Reports of newly completed workloads whose accuracy is guaranteed by specific validators
    assurances: Vec(Assurance)
        GP-0.7.2-eq:11.8 (bold_E_A) |
        Assurances by each validator concerning which of the input data of workloads they have correctly received and
        are storing locally
    disputes: ExtrinsicDisputes
        GP-0.7.2-eq:10.2 (bold_E_D) |
        Votes by validators on disputes
    """
    tickets: List[TicketEnvelope] = field(metadata={'codec': Vec(TicketEnvelope.to_codec_def())})
    preimages: List[Preimage] = field(metadata={'codec': Vec(Preimage.to_codec_def())})
    guarantees: List[Guarantee] = field(metadata={'codec': Vec(Guarantee.to_codec_def())})
    assurances: List[Assurance] = field(metadata={'codec': Vec(Assurance.to_codec_def())})
    disputes: ExtrinsicDisputes = field(metadata={'codec': ExtrinsicDisputes.to_codec_def()})

    def generate_extrinsic_hash(self) -> bytes:
        """
        GP-0.7.2-eq:5.4,5.5,5.6

        Returns
        -------
        bytes
        """

        # GP-0.7.2-eq:5.5
        extrinsic_hash = blake2b_256_hash(bytes(Vec(TicketEnvelope.to_codec_def()).encode([
            t.to_jam_bytes() for t in self.tickets
        ])))

        extrinsic_hash += blake2b_256_hash(bytes(Vec(Preimage.to_codec_def()).encode([
            p.to_jam_bytes() for p in self.preimages
        ])))

        hashed_guarantees = Vec(Tuple(H256, U32, Vec(Credential.to_codec_def()))).encode(
            [
                (blake2b_256_hash(bytes(g.report.to_jam_bytes())), g.slot, [s.to_jam_bytes() for s in g.signatures])
                for g in self.guarantees
            ]
        )

        extrinsic_hash += blake2b_256_hash(bytes(hashed_guarantees))
        extrinsic_hash += blake2b_256_hash(bytes(Vec(Assurance.to_codec_def()).encode([
            a.to_jam_bytes() for a in self.assurances
        ])))
        extrinsic_hash += blake2b_256_hash(bytes(self.disputes.to_jam_bytes()))

        # GP-0.7.2-eq:5.4
        return blake2b_256_hash(extrinsic_hash)

    @classmethod
    def default(cls) -> "Extrinsic":
        return cls(
            tickets=[],
            preimages=[],
            guarantees=[],
            assurances=[],
            disputes=ExtrinsicDisputes(
                verdicts=[],
                culprits=[],
                faults=[]
            )
        )

generate_extrinsic_hash() -> bytes

GP-0.7.2-eq:5.4,5.5,5.6

Returns:

Type Description
bytes
Source code in pyjamaz/models/block.py
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
def generate_extrinsic_hash(self) -> bytes:
    """
    GP-0.7.2-eq:5.4,5.5,5.6

    Returns
    -------
    bytes
    """

    # GP-0.7.2-eq:5.5
    extrinsic_hash = blake2b_256_hash(bytes(Vec(TicketEnvelope.to_codec_def()).encode([
        t.to_jam_bytes() for t in self.tickets
    ])))

    extrinsic_hash += blake2b_256_hash(bytes(Vec(Preimage.to_codec_def()).encode([
        p.to_jam_bytes() for p in self.preimages
    ])))

    hashed_guarantees = Vec(Tuple(H256, U32, Vec(Credential.to_codec_def()))).encode(
        [
            (blake2b_256_hash(bytes(g.report.to_jam_bytes())), g.slot, [s.to_jam_bytes() for s in g.signatures])
            for g in self.guarantees
        ]
    )

    extrinsic_hash += blake2b_256_hash(bytes(hashed_guarantees))
    extrinsic_hash += blake2b_256_hash(bytes(Vec(Assurance.to_codec_def()).encode([
        a.to_jam_bytes() for a in self.assurances
    ])))
    extrinsic_hash += blake2b_256_hash(bytes(self.disputes.to_jam_bytes()))

    # GP-0.7.2-eq:5.4
    return blake2b_256_hash(extrinsic_hash)

Block dataclass

Bases: Serializable

GP-0.7.2-eq:4.2 (bold_B) | The header is a collection of metadata primarily concerned with cryptographic references to the blockchain ancestors and the operands and results of the present transition.

Attributes:

Name Type Description
header Header

GP-0.7.2-eq:5.1 (bold_H) | Collection of metadata primarily concerned with cryptographic references to the blockchain ancestors and the operands and results of the present transition

extrinsic Extrinsic

GP-0.7.2-eq:4.3 (bold_E) | Extrinsic data is input data external to the system

Source code in pyjamaz/models/block.py
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
@dataclass
class Block(Serializable):
    """
    GP-0.7.2-eq:4.2 (bold_B) | The header is a collection of metadata primarily concerned with cryptographic references
    to the blockchain ancestors and the operands and results of the present transition.

    Attributes
    ----------
    header: Header
        GP-0.7.2-eq:5.1 (bold_H) | Collection of metadata primarily concerned with cryptographic references to the
        blockchain ancestors and the operands and results of the present transition
    extrinsic: Extrinsic
        GP-0.7.2-eq:4.3 (bold_E) |
        Extrinsic data is input data external to the system
    """
    header: Header = field(metadata={'codec': Header.to_codec_def()})
    extrinsic: Extrinsic = field(metadata={'codec': Extrinsic.to_codec_def()})