def mock_make_child(parent_state, parent, slot_number, attestations=None): if attestations is None: attestations = [] crystallized_state, active_state = parent_state block = Block(parent_hash=parent.hash, slot_number=slot_number, randao_reveal=blake( str(random.random()).encode('utf-8')), attestations=attestations, pow_chain_ref=b'\x00' * 32, active_state_root=b'\x00' * 32, crystallized_state_root=b'\x00' * 32) print('Generated preliminary block header') new_crystallized_state, new_active_state = compute_state_transition( (crystallized_state, active_state), parent, block, config=config) print('Calculated state transition') if crystallized_state == new_crystallized_state: block.crystallized_state_root = parent.crystallized_state_root else: block.crystallized_state_root = blake( serialize(crystallized_state)) block.active_state_root = blake(serialize(active_state)) return block, new_crystallized_state, new_active_state
def test_block_hash(): block = Block() original_block_hash = block.hash assert original_block_hash != b'\x00' * 32 assert len(original_block_hash) == 32 block = Block(slot_number=1) assert block.hash != original_block_hash
def test_chain(): block = None parent_hash = ZERO_HASH32 blocks = [] for slot_number in range(1, 10): block = Block(slot_number=slot_number, parent_hash=parent_hash) blocks.append(block) parent_hash = block.hash extra_block = Block(slot_number=1000000) chain = Chain(head=block, blocks=blocks + [extra_block]) assert len(chain.chain) == len(blocks) for block in blocks: assert block in chain assert extra_block not in chain
def explain_default_size(): attestation_record = AttestationRecord() block = Block() crosslink_record = CrosslinkRecord() shard_and_committee = ShardAndCommittee() crystallized_state = CrystallizedState() attestation_record_bytes = pickle.dumps(attestation_record) block_bytes = pickle.dumps(block) crosslink_record_bytes = pickle.dumps(crosslink_record) shard_and_committee_bytes = pickle.dumps(shard_and_committee) crystallized_state_bytes = pickle.dumps(crystallized_state) if (verbose): print('{} | {}'.format(len(attestation_record_bytes), attestation_record_bytes)) print('{} | {}'.format(len(block_bytes), block_bytes)) print('{} | {}'.format(len(shard_and_committee_bytes), shard_and_committee_bytes)) print('{} | {}'.format(len(crosslink_record_bytes), crosslink_record_bytes)) print('{} | {}'.format(len(crystallized_state_bytes), crystallized_state_bytes)) return { 'attestationRecord': len(attestation_record_bytes), 'block': len(block_bytes), 'shardAndCommittee': len(shard_and_committee_bytes), 'crosslinkRecord': len(crosslink_record_bytes), 'validatorRecord': "N/A", 'crystallizedState': len(crystallized_state_bytes), }
def test_block_by_slot_number(slot_number): block = Block(slot_number=slot_number) chain = Chain(head=block, blocks=[block]) assert chain.get_block_by_slot_number(block.slot_number) == block assert chain.get_block_by_slot_number(block.slot_number + 1) is None assert chain.get_block_by_slot_number(-1) is None
def explain_default_size(): attestation_record = AttestationRecord() block = Block() crosslink_record = CrosslinkRecord() shard_and_committee = ShardAndCommittee() crystallized_state = CrystallizedState() attestation_record_bytes = msgpack.packb(attestation_record, default=messages.encode_attestation) block_bytes = msgpack.packb(block, default=messages.encode_block) crosslink_record_bytes = msgpack.packb(crosslink_record, default=messages.encode_crosslink) validator_record_bytes = 0 shard_and_committee_bytes = msgpack.packb(shard_and_committee, default=messages.encode_shard_and_committee) crystallized_state_bytes = msgpack.packb(crystallized_state, default=messages.encode_crystallized_state) if (verbose): print('{} | {}'.format(len(attestation_record_bytes), attestation_record_bytes)) print('{} | {}'.format(len(block_bytes), block_bytes)) print('{} | {}'.format(len(shard_and_committee_bytes), shard_and_committee_bytes)) print('{} | {}'.format(len(crosslink_record_bytes), crosslink_record_bytes)) print('{} | {}'.format(len(validator_record_bytes), validator_record_bytes)) print('{} | {}'.format(len(crystallized_state_bytes), crystallized_state_bytes)) return { 'attestationRecord': len(attestation_record_bytes), 'block': len(block_bytes), 'shardAndCommittee': len(shard_and_committee_bytes), 'crosslinkRecord': len(crosslink_record_bytes), 'validatorRecord': "N/A", 'crystallizedState': len(crystallized_state_bytes), }
def explain_default_size(): """ Show the size of the serialized object with defaults Note: ValidatorRecord omitted (has no defaults) """ attestation_record = AttestationRecord() block = Block() crosslink_record = CrosslinkRecord() shard_and_committee = ShardAndCommittee() crystallized_state = CrystallizedState() attestation_record_bytes = serialize(attestation_record, type(attestation_record)) block_bytes = serialize(block, type(block)) crosslink_record_bytes = serialize(crosslink_record, type(crosslink_record)) shard_and_committee_bytes = serialize(shard_and_committee, type(shard_and_committee)) crystallized_state_bytes = serialize(crystallized_state, type(crystallized_state)) if (verbose): print('{} | {}'.format(len(attestation_record_bytes), attestation_record_bytes)) print('{} | {}'.format(len(block_bytes), block_bytes)) print('{} | {}'.format(len(shard_and_committee_bytes), shard_and_committee_bytes)) print('{} | {}'.format(len(crosslink_record_bytes), crosslink_record_bytes)) print('{} | {}'.format(len(crystallized_state_bytes), crystallized_state_bytes)) return { 'attestationRecord': len(attestation_record_bytes), 'block': len(block_bytes), 'shardAndCommittee': len(shard_and_committee_bytes), 'crosslinkRecord': len(crosslink_record_bytes), 'validatorRecord': "N/A", 'crystallizedState': len(crystallized_state_bytes), }
def test_num_attestations(expected): attestations = [AttestationRecord() for i in range(expected)] block = Block( attestations=attestations, ) assert block.num_attestations == expected
def genesis_block(): return Block( parent_hash=b'\x00' * 32, slot_number=0, randao_reveal=b'\x00' * 32, attestations=[], pow_chain_ref=b'\x00' * 32, active_state_root=b'\x00' * 32, crystallized_state_root=b'\x00' * 32, )
def test_num_properties(): aggregate_vote = AggregateVote() block = Block( attestation_aggregate_sig=list(range(2)), shard_aggregate_votes=[aggregate_vote], sig=list(range(3)), ) assert block.num_attestation_aggregate_sig == 2 assert block.num_shard_aggregate_votes == 1 assert block.num_sig == 3
def genesis_block(genesis_crystallized_state, genesis_active_state): return Block(parent_hash=b'\x00' * 32, skip_count=0, randao_reveal=b'\x00' * 32, attestation_bitfield=b'', attestation_aggregate_sig=[0, 0], shard_aggregate_votes=[], main_chain_ref=b'\x00' * 32, state_hash=state_hash(genesis_crystallized_state, genesis_active_state), sig=[0, 0])
def mock_make_child(parent_state, parent, skips, attester_share=0.8, crosslink_shards=[]): crystallized_state, active_state = parent_state parent_attestation = serialize(parent) indices, main_signer = get_attesters_and_signer(crystallized_state, active_state, skips) print('Selected indices: %r' % indices) print('Selected main signer: %d' % main_signer) # Randomly pick indices to include bitfield = [1 if random.random() < attester_share else 0 for i in indices] # Attestations sigs = [bls.sign(parent_attestation, keymap[crystallized_state.active_validators[indices[i]].pubkey]) for i in range(len(indices)) if bitfield[i]] attestation_aggregate_sig = bls.aggregate_sigs(sigs) print('Aggregated sig') attestation_bitmask = bytearray((len(bitfield)-1) // 8 + 1) for i, b in enumerate(bitfield): attestation_bitmask[i//8] ^= (128 >> (i % 8)) * b print('Aggregate bitmask:', bin(int.from_bytes(attestation_bitmask, 'big'))) # Randomly pick indices to include for crosslinks shard_aggregate_votes = [] for shard, crosslinker_share in crosslink_shards: print('Making crosslink in shard %d' % shard) indices = get_shard_attesters(crystallized_state, shard) print('Indices: %r' % indices) bitfield = [1 if random.random() < crosslinker_share else 0 for i in indices] bitmask = bytearray((len(bitfield)+7) // 8) for i, b in enumerate(bitfield): bitmask[i//8] ^= (128 >> (i % 8)) * b print('Bitmask:', bin(int.from_bytes(bitmask, 'big'))) shard_block_hash = blake(bytes([shard])) crosslink_attestation_hash = get_crosslink_aggvote_msg(shard, shard_block_hash, crystallized_state) sigs = [bls.sign(crosslink_attestation_hash, keymap[crystallized_state.active_validators[indices[i]].pubkey]) for i in range(len(indices)) if bitfield[i]] v = AggregateVote(shard_id=shard, shard_block_hash=shard_block_hash, signer_bitmask=bitmask, aggregate_sig=list(bls.aggregate_sigs(sigs))) shard_aggregate_votes.append(v) print('Added %d shard aggregate votes' % len(crosslink_shards)) # State calculations o = Block(parent_hash=blake(parent_attestation), skip_count=skips, randao_reveal=blake(str(random.random()).encode('utf-8')), attestation_bitmask=attestation_bitmask, attestation_aggregate_sig=list(attestation_aggregate_sig), shard_aggregate_votes=shard_aggregate_votes, main_chain_ref=b'\x00'*32, state_hash=b'\x00'*64) print('Generated preliminary block header') new_crystallized_state, new_active_state = \ compute_state_transition((crystallized_state, active_state), parent, o, verify_sig=False) print('Calculated state transition') if crystallized_state == new_crystallized_state: o.state_hash = blake(parent.state_hash[:32] + blake(serialize(new_active_state))) else: o.state_hash = blake(blake(serialize(new_crystallized_state)) + blake(serialize(new_active_state))) # Main signature o.sign(keymap[crystallized_state.active_validators[main_signer].pubkey]) print('Signed') return o, new_crystallized_state, new_active_state
def get_pseudo_chain(length): """Get a pseudo chain, only slot_number and parent_hash are valid. """ blocks = [] for slot in range(length * 3): blocks.append( Block( slot_number=slot, parent_hash=blocks[slot - 1].hash if slot > 0 else ZERO_HASH32 ) ) return blocks
def test_block_hash(): block = Block() original_block_hash = block.hash assert original_block_hash != b'\x00' * 32 assert len(original_block_hash) == 32 block.sign(1) signed_block_hash_1 = block.hash assert signed_block_hash_1 != original_block_hash block.sign(2) signed_block_hash_2 = block.hash assert signed_block_hash_2 != original_block_hash assert signed_block_hash_2 != signed_block_hash_1 block = Block(skip_count=1) assert block.hash != original_block_hash assert block.hash != signed_block_hash_1 assert block.hash != signed_block_hash_2
def test_block_by_hash(): block = Block() chain = Chain(head=block, blocks=[block]) assert chain.get_block_by_hash(block.hash) == block assert chain.get_block_by_hash(b'\x35' * 32) is None
def make_unfinished_block(parent_state, parent, skips, attester_share=0.8, crosslink_shards_and_shares=None): if crosslink_shards_and_shares is None: crosslink_shards_and_shares = [] crystallized_state, active_state = parent_state parent_attestation = serialize(parent) indices, proposer = get_attesters_and_proposer( crystallized_state, active_state, skips, config ) print('Selected indices: %r' % indices) print('Selected block proposer: %d' % proposer) # Randomly pick indices to include is_attesting = [random.random() < attester_share for _ in indices] # Attestations sigs = [ bls.sign( parent_attestation, keymap[crystallized_state.active_validators[indices[i]].pubkey] ) for i, attesting in enumerate(is_attesting) if attesting ] attestation_aggregate_sig = bls.aggregate_sigs(sigs) print('Aggregated sig') attestation_bitfield = get_empty_bitfield(len(indices)) for i, attesting in enumerate(is_attesting): if attesting: attestation_bitfield = set_voted(attestation_bitfield, i) print('Aggregate bitfield:', bin(int.from_bytes(attestation_bitfield, 'big'))) # Randomly pick indices to include for crosslinks shard_aggregate_votes = [] # The shards that are selected to be crosslinking crosslink_shards = get_crosslink_shards(crystallized_state, config=config) for shard, crosslinker_share in crosslink_shards_and_shares: # Check if this shard is in the crosslink shards list assert shard in crosslink_shards print('Making crosslink in shard %d' % shard) indices = get_crosslink_notaries(crystallized_state, shard, crosslink_shards=crosslink_shards, config=config) print('Indices: %r' % indices) is_notarizing = [random.random() < attester_share for _ in indices] notary_bitfield = get_empty_bitfield(len(indices)) for i, notarizing in enumerate(is_notarizing): if notarizing: notary_bitfield = set_voted(notary_bitfield, i) print('Bitfield:', bin(int.from_bytes(notary_bitfield, 'big'))) shard_block_hash = blake(bytes([shard])) crosslink_attestation_hash = get_crosslink_aggvote_msg( shard, shard_block_hash, crystallized_state ) sigs = [ bls.sign( crosslink_attestation_hash, keymap[crystallized_state.active_validators[indices[i]].pubkey] ) for i, notarizing in enumerate(is_notarizing) if notarizing ] v = AggregateVote( shard_id=shard, shard_block_hash=shard_block_hash, notary_bitfield=notary_bitfield, aggregate_sig=list(bls.aggregate_sigs(sigs)) ) shard_aggregate_votes.append(v) print('Added %d shard aggregate votes' % len(crosslink_shards_and_shares)) block = Block( parent_hash=blake(parent_attestation), skip_count=skips, randao_reveal=blake(str(random.random()).encode('utf-8')), attestation_bitfield=attestation_bitfield, attestation_aggregate_sig=list(attestation_aggregate_sig), shard_aggregate_votes=shard_aggregate_votes, main_chain_ref=b'\x00'*32, state_hash=b'\x00'*64 ) return block, proposer
def test_block_signing(): block = Block() privkey = 1 pubkey = privtopub(privkey) assert not block.verify(pubkey) block.sign(1) assert block.sig != [0, 0] assert block.verify(privtopub(1)) block.sign(2) assert not block.verify(privtopub(1)) assert block.verify(privtopub(2)) block.skip_count = 1 assert not block.verify(privtopub(2))
def test_head(): block = Block() chain = Chain(head=block) assert chain.head == block
def explain_maxval_size(): # Attestation Record # TODO replace oblique hash loop with correct size obl_hashes = [] for i in range(0, 64): obl_hashes.append(helpers.MAX_BYTES) attestation_record = AttestationRecord( slot=helpers.MAX_I64, shard_id=helpers.MAX_I16, oblique_parent_hashes=obl_hashes, shard_block_hash=helpers.MAX_BYTES, attester_bitfield=helpers.MAX_BYTES, aggregate_sig=[helpers.MAX_256, helpers.MAX_256] ) # Blocks # TODO: provide realistic number for attestations attestations = [] for i in range(0, helpers.MAX_ATTESTATIONS): attestations.append(attestation_record) block = Block( parent_hash=helpers.MAX_BYTES, slot_number=helpers.MAX_I64, randao_reveal=helpers.MAX_BYTES, attestations=attestations, pow_chain_ref=helpers.MAX_BYTES, active_state_root=helpers.MAX_BYTES, crystallized_state_root=helpers.MAX_BYTES, ) # Crosslink Record crosslink_record = CrosslinkRecord( hash=helpers.MAX_BYTES, dynasty=helpers.MAX_I64, ) # Validator Record validator_record = ValidatorRecord( pubkey=helpers.MAX_256, withdrawal_shard=helpers.MAX_I16, withdrawal_address=helpers.ADDRESS_BYTES, randao_commitment=helpers.MAX_BYTES, balance=helpers.MAX_I64, start_dynasty=helpers.MAX_I64, end_dynasty=helpers.MAX_I64, ) # Shard and Committee # TODO: replace placeholder committees = [] for i in range(0, helpers.PLACEHOLDER): committees.append(helpers.MAX_I16) shard_and_committee = ShardAndCommittee( shard_id=helpers.MAX_I16, committee=committees, ) # Crystallized State validatorlist = [] for i in range(0, helpers.MAX_VALIDATORS): validatorlist.append(validator_record) # TODO: replace placeholder crosslinklist = [] for i in range(0, helpers.PLACEHOLDER): crosslinklist.append(crosslink_record) # TODO: replace placeholder indices_heights = [] for i in range(0, helpers.PLACEHOLDER): tmp = [] for j in range(0, 10): tmp.append(shard_and_committee) indices_heights.append(tmp) crystallized_state = CrystallizedState( validators=validatorlist, indices_for_heights=indices_heights, last_justified_slot=helpers.MAX_I64, justified_streak=helpers.MAX_I64, last_finalized_slot=helpers.MAX_I64, current_dynasty=helpers.MAX_I64, crosslinking_start_shard=helpers.MAX_I16, crosslink_records=crosslinklist, total_deposits=helpers.MAX_256, dynasty_seed=helpers.MAX_BYTES, dynasty_seed_last_reset=helpers.MAX_I64, last_state_recalc=helpers.MAX_I64, ) attestation_record_bytes = msgpack.packb(attestation_record, default=messages.encode_attestation) block_bytes = msgpack.packb(block, default=messages.encode_block) crosslink_record_bytes = msgpack.packb(crosslink_record, default=messages.encode_crosslink) validator_record_bytes = msgpack.packb(validator_record, default=messages.encode_validator_record) shard_and_committee_bytes = msgpack.packb(shard_and_committee, default=messages.encode_shard_and_committee) crystallized_state_bytes = msgpack.packb(crystallized_state, default=messages.encode_crystallized_state) if (verbose): print('{} | {}'.format(len(attestation_record_bytes), attestation_record_bytes)) print('{} | {}'.format(len(block_bytes), block_bytes)) print('{} | {}'.format(len(shard_and_committee_bytes), shard_and_committee_bytes)) print('{} | {}'.format(len(crosslink_record_bytes), crosslink_record_bytes)) print('{} | {}'.format(len(validator_record_bytes), validator_record_bytes)) print('{} | {}'.format(len(crystallized_state_bytes), crystallized_state_bytes)) return { 'attestationRecord': len(attestation_record_bytes), 'block': len(block_bytes), 'shardAndCommittee': len(shard_and_committee_bytes), 'crosslinkRecord': len(crosslink_record_bytes), 'validatorRecord': len(validator_record_bytes), 'crystallizedState': len(crystallized_state_bytes), }
def make_unfinished_block(parent_state, parent, skips, attester_share=0.8, crosslink_shards_and_shares=None): if crosslink_shards_and_shares is None: crosslink_shards_and_shares = [] crystallized_state, active_state = parent_state parent_attestation = serialize(parent) indices, proposer = get_attesters_and_proposer(crystallized_state, active_state, skips, config) print('Selected indices: %r' % indices) print('Selected block proposer: %d' % proposer) # Randomly pick indices to include bitfield = [ 1 if random.random() < attester_share else 0 for i in indices ] # Attestations sigs = [ bls.sign( parent_attestation, keymap[ crystallized_state.active_validators[indices[i]].pubkey]) for i in range(len(indices)) if bitfield[i] ] attestation_aggregate_sig = bls.aggregate_sigs(sigs) print('Aggregated sig') attestation_bitfield = bytearray((len(bitfield) - 1) // 8 + 1) for i, b in enumerate(bitfield): attestation_bitfield[i // 8] ^= (128 >> (i % 8)) * b print('Aggregate bitfield:', bin(int.from_bytes(attestation_bitfield, 'big'))) # Randomly pick indices to include for crosslinks shard_aggregate_votes = [] # The shards that are selected to be crosslinking crosslink_shards = get_crosslink_shards(crystallized_state, config=config) for shard, crosslinker_share in crosslink_shards_and_shares: # Check if this shard is in the crosslink shards list assert shard in crosslink_shards print('Making crosslink in shard %d' % shard) indices = get_crosslink_notaries(crystallized_state, shard, crosslink_shards=crosslink_shards, config=config) print('Indices: %r' % indices) bitfield = [ 1 if random.random() < crosslinker_share else 0 for i in indices ] bitmask = bytearray((len(bitfield) + 7) // 8) for i, b in enumerate(bitfield): bitmask[i // 8] ^= (128 >> (i % 8)) * b print('Bitmask:', bin(int.from_bytes(bitmask, 'big'))) shard_block_hash = blake(bytes([shard])) crosslink_attestation_hash = get_crosslink_aggvote_msg( shard, shard_block_hash, crystallized_state) sigs = [ bls.sign( crosslink_attestation_hash, keymap[crystallized_state.active_validators[ indices[i]].pubkey]) for i in range(len(indices)) if bitfield[i] ] v = AggregateVote(shard_id=shard, shard_block_hash=shard_block_hash, signer_bitmask=bitmask, aggregate_sig=list(bls.aggregate_sigs(sigs))) shard_aggregate_votes.append(v) print('Added %d shard aggregate votes' % len(crosslink_shards_and_shares)) block = Block( parent_hash=blake(parent_attestation), skip_count=skips, randao_reveal=blake(str(random.random()).encode('utf-8')), attestation_bitfield=attestation_bitfield, attestation_aggregate_sig=list(attestation_aggregate_sig), shard_aggregate_votes=shard_aggregate_votes, main_chain_ref=b'\x00' * 32, state_hash=b'\x00' * 64) return block, proposer