def mk_genesis_state_and_block(pubkeys): c = CrystallizedState( active_validators=[ ValidatorRecord(pubkey=pub, return_shard=0, return_address=blake(pub.to_bytes(32, 'big'))[-20:], randao_commitment=b'\x55' * 32, balance=DEFAULT_BALANCE, switch_dynasty=9999999999999999999) for pub in pubkeys ], queued_validators=[], exited_validators=[], current_shuffling=get_shuffling(b'\x35' * 32, len(pubkeys)), current_epoch=1, last_justified_epoch=0, last_finalized_epoch=0, dynasty=1, next_shard=0, current_checkpoint=blake(b'insert EOS constitution here'), crosslink_records=[ CrosslinkRecord(hash=b'\x00' * 32, epoch=0) for i in range(SHARD_COUNT) ], total_deposits=DEFAULT_BALANCE * len(pubkeys)) a = ActiveState(height=1, randao=b'\x45' * 32, ffg_voter_bitmask=bytearray( (len(c.active_validators) + 7) // 8), balance_deltas=[], checkpoints=[], total_skip_count=0) b = Block(parent_hash=b'\x00' * 32, skip_count=0, randao_reveal=b'\x00' * 32, attestation_bitmask=b'', attestation_aggregate_sig=[0, 0], shard_aggregate_votes=[], main_chain_ref=b'\x00' * 32, state_hash=blake(serialize(c)) + blake(serialize(a)), sig=[0, 0]) return c, a, b
sig = sign(msg, x) pub = privtopub(x) assert verify(msg, pub, sig) print('Testing signature aggregation') msg = b'cow' keys = [1, 5, 124, 735, 127409812145, 90768492698215092512159, 0] sigs = [sign(msg, k) for k in keys] pubs = [privtopub(k) for k in keys] aggsig = aggregate_sigs(sigs) aggpub = aggregate_pubs(pubs) assert verify(msg, aggpub, aggsig) print('Testing basic serialization') assert serialize(5, 'int8') == b'\x05' assert deserialize(b'\x05', 'int8') == 5 assert serialize(2**32 - 3, 'int40') == b'\x00\xff\xff\xff\xfd' assert deserialize(b'\x00\xff\xff\xff\xfd', 'int40') == 2**32 - 3 assert serialize(b'\x35' * 20, 'address') == b'\x35' * 20 assert deserialize(b'\x35' * 20, 'address') == b'\x35' * 20 assert serialize(b'\x35' * 32, 'hash32') == b'\x35' * 32 assert deserialize(b'\x35' * 32, 'hash32') == b'\x35' * 32 assert serialize(b'cow', 'bytes') == b'\x00\x00\x00\x03cow' assert deserialize(b'\x00\x00\x00\x03cow', 'bytes') == b'cow' print('Testing advanced serialization') s = ActiveState() ds = deserialize(serialize(s, type(s)), type(s)) assert eq(s, ds)
def mock_make_child(parent_state, parent, skips, attester_share=0.8, crosslink_shards=[]): crystallized_state, active_state = parent_state parent_attestation = serialize(parent) validator_count = len(crystallized_state.active_validators) 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
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 c, a, block = mk_genesis_state_and_block(keymap.keys()) print('Generated genesis state') print('Crystallized state length:', len(serialize(c))) print('Active state length:', len(serialize(a))) print('Block size:', len(serialize(block))) block2, c2, a2 = mock_make_child((c, a), block, 0, 0.8, []) t = time.time() assert compute_state_transition((c, a), block, block2) print("Normal block (basic attestation only) processed in %.4f sec" % (time.time() - t)) print('Verified a block!') block3, c3, a3 = mock_make_child((c2, a2), block2, 0, 0.8, [(0, 0.75)]) print('Verified a block with a committee!') while a3.height % SHARD_COUNT > 0: block3, c3, a3 = mock_make_child((c3, a3), block3, 0, 0.8, [(a3.height, 0.6 + 0.02 * a3.height)]) print('Height: %d' % a3.height) print('FFG bitmask:', bin(int.from_bytes(a3.ffg_voter_bitmask, 'big')))
def hash(self): return blake(serialize(self))
def verify(self, pub): zig = self.sig self.sig = [0, 0] o = verify(serialize(self), pub, tuple(zig)) self.sig = zig return o
def sign(self, key): self.sig = [0, 0] self.sig = list(sign(serialize(self), key))
def compute_state_transition(parent_state, parent_block, block, verify_sig=True): crystallized_state, active_state = parent_state # Initialize a new epoch if needed if active_state.height % SHARD_COUNT == 0: print('Processing epoch transition') # Process rewards from FFG/crosslink votes new_validator_records = deepcopy(crystallized_state.active_validators) # Who voted in the last epoch ffg_voter_bitmask = bytearray(active_state.ffg_voter_bitmask) # Balance changes, and total vote counts for FFG deltas1, total_vote_count, total_vote_deposits, justify, finalize = \ process_ffg_deposits(crystallized_state, ffg_voter_bitmask) # Balance changes, and total vote counts for crosslinks deltas2, new_crosslink_records = process_crosslinks(crystallized_state, active_state.partial_crosslinks) # Process other balance deltas deltas3 = process_balance_deltas(crystallized_state, active_state.balance_deltas) for i, v in enumerate(new_validator_records): v.balance += deltas1[i] + deltas2[i] + deltas3[i] total_deposits = crystallized_state.total_deposits + sum(deltas1 + deltas2 + deltas3) print('New total deposits: %d' % total_deposits) if finalize: new_queued_validators, new_active_validators, new_exited_validators = \ get_incremented_validator_sets(crystallized_state, new_validator_records) else: new_queued_validators, new_active_validators, new_exited_validators = \ crystallized_state.queued_validators, crystallized_state.active_validators, crystallized_state.exited_validators crystallized_state = CrystallizedState( queued_validators=new_queued_validators, active_validators=new_active_validators, exited_validators=new_exited_validators, current_shuffling=get_shuffling(active_state.randao, len(new_active_validators)), last_justified_epoch = crystallized_state.current_epoch if justify else crystallized_state.last_justified_epoch, last_finalized_epoch = crystallized_state.current_epoch-1 if finalize else crystallized_state.last_finalized_epoch, dynasty = crystallized_state.dynasty + (1 if finalize else 0), next_shard = 0, current_epoch = crystallized_state.current_epoch + 1, crosslink_records = new_crosslink_records, total_deposits = total_deposits ) # Reset the active state active_state = ActiveState(height=active_state.height, randao=active_state.randao, ffg_voter_bitmask=bytearray((len(crystallized_state.active_validators) + 7) // 8), balance_deltas=[], partial_crosslinks=[], total_skip_count=active_state.total_skip_count) # Process the block-by-block stuff # Determine who the attesters and the main signer are attestation_indices, main_signer = \ get_attesters_and_signer(crystallized_state, active_state, block.skip_count) # Verify attestations balance_deltas = process_attestations(crystallized_state.active_validators, attestation_indices, block.attestation_bitmask, serialize(parent_block), block.attestation_aggregate_sig) # Reward main signer balance_deltas.append((main_signer << 24) + len(balance_deltas)) # Verify main signature if verify_sig: assert block.verify(crystallized_state.active_validators[main_signer].pubkey) print('Verified main sig') # Update crosslink records new_crosslink_records, new_ffg_bitmask, voters = \ update_ffg_and_crosslink_progress(crystallized_state, active_state.partial_crosslinks, active_state.ffg_voter_bitmask, block.shard_aggregate_votes) balance_deltas.append((main_signer << 24) + voters) o = ActiveState(height=active_state.height + 1, randao=(int.from_bytes(active_state.randao, 'big') ^ int.from_bytes(block.randao_reveal, 'big')).to_bytes(32, 'big'), total_skip_count=active_state.total_skip_count + block.skip_count, partial_crosslinks=new_crosslink_records, ffg_voter_bitmask=new_ffg_bitmask, balance_deltas=active_state.balance_deltas + balance_deltas) return crystallized_state, o