def mock_make_attestations(parent_state, block, attester_share=0.8): crystallized_state, active_state = parent_state cycle_length = config['cycle_length'] in_cycle_slot_height = block.slot_number % cycle_length indices = crystallized_state.indices_for_slots[cycle_length + in_cycle_slot_height] print("Generating attestations for shards: %s" % len(indices)) attestations = [] for shard_and_committee in indices: shard_id = shard_and_committee.shard_id committee_indices = shard_and_committee.committee print("Generating attestation for shard %s" % shard_id) print("Committee size %s" % len(committee_indices)) # Create attestation attestation = AttestationRecord( slot=block.slot_number, shard_id=shard_and_committee.shard_id, oblique_parent_hashes=[], shard_block_hash=blake(bytes(str(shard_id), 'utf-8')), attester_bitfield=get_empty_bitfield(len(committee_indices))) # Randomly pick indices to include is_attesting = [ random.random() < attester_share for _ in range(len(committee_indices)) ] # Proposer always attests is_attesting[0] = True # Generating signatures and aggregating result parent_hashes = get_hashes_to_sign(active_state, block, config) message = blake( attestation.slot.to_bytes(8, byteorder='big') + b''.join(parent_hashes) + shard_id.to_bytes(2, byteorder='big') + attestation.shard_block_hash) sigs = [ bls.sign(message, keymap[crystallized_state.validators[indice].pubkey]) for i, indice in enumerate(committee_indices) if is_attesting[i] ] attestation.aggregate_sig = bls.aggregate_sigs(sigs) print('Aggregated sig') attestation_bitfield = get_empty_bitfield(len(committee_indices)) for i, attesting in enumerate(is_attesting): if attesting: attestation_bitfield = set_voted(attestation_bitfield, i) attestation.attester_bitfield = attestation_bitfield print('Aggregate bitfield:', bin(int.from_bytes(attestation_bitfield, 'big'))) attestations.append(attestation) return attestations
def genesis_crystallized_state(init_validator_keys, init_shuffling_seed, config): return CrystallizedState( active_validators=[ValidatorRecord( pubkey=pub, withdrawal_shard=0, withdrawal_address=blake(pub.to_bytes(32, 'big'))[-20:], randao_commitment=b'\x55'*32, balance=DEFAULT_BALANCE, switch_dynasty=DEFAULT_SWITCH_DYNASTY ) for pub in init_validator_keys], queued_validators=[], exited_validators=[], current_shuffling=get_shuffling(init_shuffling_seed, len(init_validator_keys), config=config), 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(init_validator_keys) )
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 mock_make_child(parent_state, parent, skips, attester_share=0.8, crosslink_shards=[]): crystallized_state, active_state = parent_state block, proposer = make_unfinished_block(parent_state, parent, skips, attester_share, crosslink_shards) print('Generated preliminary block header') new_crystallized_state, new_active_state = compute_state_transition( (crystallized_state, active_state), parent, block, verify_sig=False, config=config) print('Calculated state transition') if crystallized_state == new_crystallized_state: block.state_hash = blake(parent.state_hash[:32] + blake(serialize(new_active_state))) else: block.state_hash = blake( blake(serialize(new_crystallized_state)) + blake(serialize(new_active_state))) # Main signature block.sign( keymap[crystallized_state.active_validators[proposer].pubkey]) print('Signed') return block, new_crystallized_state, new_active_state
def genesis_block(genesis_active_state, genesis_crystallized_state): active_state_root = blake(serialize(genesis_active_state)) crystallized_state_root = blake(serialize(genesis_crystallized_state)) return get_genesis_block( active_state_root=active_state_root, crystallized_state_root=crystallized_state_root, )
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 validate_attestation(crystallized_state: CrystallizedState, active_state: ActiveState, attestation: 'AttestationRecord', block: 'Block', config: Dict[str, Any]=DEFAULT_CONFIG) -> None: if not attestation.slot < block.slot_number: raise Exception("Attestation slot number too high") if not (attestation.slot > block.slot_number - config['cycle_length']): raise Exception( "Attestation slot number too low:\n" "\tFound: %s, Needed greater than: %s" % (attestation.slot, block.slot_number - config['cycle_length']) ) parent_hashes = get_signed_parent_hashes( active_state, block, attestation, config ) attestation_indices = get_attestation_indices( crystallized_state, attestation, config ) # # validate bitfield # if not (len(attestation.attester_bitfield) == get_bitfield_length(len(attestation_indices))): raise Exception( "Attestation has incorrect bitfield length. Found: %s, Expected: %s" % (len(attestation.attester_bitfield), get_bitfield_length(len(attestation_indices))) ) # check if end bits are zero last_bit = len(attestation_indices) if last_bit % 8 != 0: for i in range(8 - last_bit % 8): if has_voted(attestation.attester_bitfield, last_bit + i): raise Exception("Attestation has non-zero trailing bits") # # validate aggregate_sig # in_cycle_slot_height = attestation.slot % config['cycle_length'] pub_keys = [ crystallized_state.validators[index].pubkey for i, index in enumerate(attestation_indices) if has_voted(attestation.attester_bitfield, i) ] message = blake( in_cycle_slot_height.to_bytes(8, byteorder='big') + b''.join(parent_hashes) + attestation.shard_id.to_bytes(2, byteorder='big') + attestation.shard_block_hash ) if not bls.verify(message, bls.aggregate_pubs(pub_keys), attestation.aggregate_sig): raise Exception("Attestation aggregate signature fails")
def test_get_genesis_block(genesis_active_state, genesis_crystallized_state): active_state_root = blake(serialize(genesis_active_state)) crystallized_state_root = blake(serialize(genesis_crystallized_state)) block = get_genesis_block( active_state_root=active_state_root, crystallized_state_root=crystallized_state_root, ) assert block.parent_hash == ZERO_HASH32 assert block.slot_number == 0 assert block.randao_reveal == ZERO_HASH32 assert block.num_attestations == 0 assert block.pow_chain_ref == ZERO_HASH32 assert block.active_state_root == active_state_root assert block.crystallized_state_root == crystallized_state_root
def genesis_validators(init_validator_keys, config): current_dynasty = 1 return [ ValidatorRecord(pubkey=pub, withdrawal_shard=0, withdrawal_address=blake(pub.to_bytes(32, 'big'))[-20:], randao_commitment=b'\x55' * 32, balance=config['deposit_size'], start_dynasty=current_dynasty, end_dynasty=config['default_end_dynasty']) for pub in init_validator_keys ]
def get_hashes_to_sign( active_state: 'ActiveState', block: 'Block', config: Dict[str, Any] = DEFAULT_CONFIG) -> List[Hash32]: cycle_length = config['cycle_length'] hashes = get_hashes_from_active_state( active_state, block, from_slot=block.slot_number - cycle_length + 1, to_slot=block.slot_number - 1, config=config, ) + [blake(serialize(block))] return hashes
def get_shuffling(seed, validator_count, sample=None): assert validator_count <= MAX_VALIDATORS rand_max = MAX_VALIDATORS - MAX_VALIDATORS % validator_count o = list(range(validator_count)) source = seed i = 0 maxvalue = sample if sample is not None else validator_count while i < maxvalue: source = blake(source) for pos in range(0, 30, 3): m = int.from_bytes(source[pos:pos + 3], 'big') remaining = validator_count - i if remaining == 0: break if validator_count < rand_max: replacement_pos = (m % remaining) + i o[i], o[replacement_pos] = o[replacement_pos], o[i] i += 1 return o[:maxvalue]
def shuffle(lst, seed, config=DEFAULT_CONFIG): lst_count = len(lst) assert lst_count <= 16777216 o = [x for x in lst] source = seed i = 0 while i < lst_count: source = blake(source) for pos in range(0, 30, 3): m = int.from_bytes(source[pos:pos + 3], 'big') remaining = lst_count - i if remaining == 0: break rand_max = 16777216 - 16777216 % remaining if m < rand_max: replacement_pos = (m % remaining) + i o[i], o[replacement_pos] = o[replacement_pos], o[i] i += 1 return o
def get_shuffling(seed, validator_count, sample=None, config=DEFAULT_CONFIG): max_validators = config['max_validators'] assert validator_count <= max_validators rand_max = max_validators - max_validators % validator_count o = list(range(validator_count)) source = seed i = 0 maxvalue = sample if sample is not None else validator_count while i < maxvalue: source = blake(source) for pos in range(0, 30, 3): m = int.from_bytes(source[pos:pos + 3], 'big') remaining = validator_count - i if remaining == 0: break if validator_count < rand_max: replacement_pos = (m % remaining) + i o[i], o[replacement_pos] = o[replacement_pos], o[i] i += 1 return o[:maxvalue]
def test_initialize_new_cycle( genesis_crystallized_state, genesis_active_state, genesis_block, last_state_recalc, last_justified_slot, justified_streak, last_finalized_slot, fraction_voted, result_last_state_recalc, result_justified_streak, result_last_finalized_slot, config): # Fill the parent_crystallized_state with parematers parent_crystallized_state = genesis_crystallized_state parent_crystallized_state.last_state_recalc = last_state_recalc parent_crystallized_state.last_justified_slot = last_justified_slot parent_crystallized_state.justified_streak = justified_streak parent_crystallized_state.last_finalized_slot = last_finalized_slot parent_active_state = genesis_active_state parent_block = genesis_block block = copy.deepcopy(genesis_block) block.slot_number = 258 block.parent_hash = blake(serialize(parent_block)) active_state = fill_recent_block_hashes(parent_active_state, parent_block, block) fraction_voted *= 1.01 # add margin for rounding error # Fill the total_voter_deposits to simulate the different committee results active_state.block_vote_cache[block.parent_hash] = { 'voter_indices': set(), 'total_voter_deposits': int(parent_crystallized_state.total_deposits * fraction_voted) } crystallized_state, active_state = initialize_new_cycle( parent_crystallized_state, active_state, block, config=config, ) assert crystallized_state.last_state_recalc == result_last_state_recalc assert crystallized_state.justified_streak == result_justified_streak assert crystallized_state.last_finalized_slot == result_last_finalized_slot
def hash(self): return blake(serialize(self))
def validate_attestation(crystallized_state: CrystallizedState, active_state: ActiveState, attestation: 'AttestationRecord', block: 'Block', parent_block: 'Block', config: Dict[str, Any] = DEFAULT_CONFIG) -> bool: # # validate slot number # if not attestation.slot <= parent_block.slot_number: raise ValidationError("Attestation slot number too high:\n" "\tFound: %s Needed less than or equal to %s" % (attestation.slot, parent_block.slot_number)) if not (attestation.slot >= max( parent_block.slot_number - config['cycle_length'] + 1, 0)): raise ValidationError( "Attestation slot number too low:\n" "\tFound: %s, Needed greater than or equalt to: %s" % (attestation.slot, max(parent_block.slot_number - config['cycle_length'] + 1, 0))) # # validate justified_slot and justified_block_hash # if attestation.justified_slot > crystallized_state.last_justified_slot: raise ValidationError( "attestation.justified_slot %s should be equal to or earlier than" " crystallized_state.last_justified_slot %s" % ( attestation.justified_slot, crystallized_state.last_justified_slot, )) justified_block = active_state.chain.get_block_by_hash( attestation.justified_block_hash) if justified_block is None: raise ValidationError( "justified_block_hash %s is not in the canonical chain" % attestation.justified_block_hash) if justified_block.slot_number != attestation.justified_slot: raise ValidationError( "justified_slot %s doesn't match justified_block_hash" % attestation.justified_slot) parent_hashes = get_signed_parent_hashes(active_state, block, attestation, config) attestation_indices = get_attestation_indices(crystallized_state, attestation, config) # # validate bitfield # if not (len(attestation.attester_bitfield) == get_bitfield_length( len(attestation_indices))): raise ValidationError( "Attestation has incorrect bitfield length. Found: %s, Expected: %s" % (len(attestation.attester_bitfield), get_bitfield_length(len(attestation_indices)))) # check if end bits are zero last_bit = len(attestation_indices) if last_bit % 8 != 0: for i in range(8 - last_bit % 8): if has_voted(attestation.attester_bitfield, last_bit + i): raise ValidationError("Attestation has non-zero trailing bits") # # validate aggregate_sig # pub_keys = [ crystallized_state.validators[validator_index].pubkey for committee_index, validator_index in enumerate(attestation_indices) if has_voted(attestation.attester_bitfield, committee_index) ] message = blake( attestation.slot.to_bytes(8, byteorder='big') + b''.join(parent_hashes) + attestation.shard_id.to_bytes(2, byteorder='big') + attestation.shard_block_hash + attestation.justified_slot.to_bytes(8, 'big')) if not bls.verify(message, bls.aggregate_pubs(pub_keys), attestation.aggregate_sig): raise ValidationError("Attestation aggregate signature fails") return True
def mock_make_attestations(parent_state, block, attester_share=0.8): crystallized_state, active_state = parent_state cycle_length = config['cycle_length'] in_cycle_slot_height = block.slot_number % cycle_length indices = crystallized_state.shard_and_committee_for_slots[ cycle_length + in_cycle_slot_height] print("Generating attestations for shards: %s" % len(indices)) proposer_index_in_committee, proposer_shard_id = get_proposer_position( block, crystallized_state, config=config, ) attestations = [] for shard_and_committee in indices: shard_id = shard_and_committee.shard_id committee_indices = shard_and_committee.committee print("Generating attestation for shard %s" % shard_id) print("Committee size %s" % len(committee_indices)) justified_slot = crystallized_state.last_justified_slot justified_block_hash = active_state.chain.get_block_by_slot_number( justified_slot).hash # Create attestation attestation = AttestationRecord( slot=block.slot_number, shard_id=shard_and_committee.shard_id, oblique_parent_hashes=[], shard_block_hash=blake(bytes(str(shard_id), 'utf-8')), attester_bitfield=get_empty_bitfield(len(committee_indices)), justified_slot=justified_slot, justified_block_hash=justified_block_hash, ) # fill with roughly attester share fraction of voters is_attesting = [ i < attester_share * len(committee_indices) for i in range(len(committee_indices)) ] # Proposer always attests if shard_id == proposer_shard_id: is_attesting[proposer_index_in_committee] = True # Generating signatures and aggregating result parent_hashes = get_hashes_to_sign(active_state, block, config) message = blake( attestation.slot.to_bytes(8, byteorder='big') + b''.join(parent_hashes) + shard_id.to_bytes(2, byteorder='big') + attestation.shard_block_hash + attestation.justified_slot.to_bytes(8, byteorder='big')) sigs = [ bls.sign(message, keymap[crystallized_state.validators[indice].pubkey]) for i, indice in enumerate(committee_indices) if is_attesting[i] ] attestation.aggregate_sig = bls.aggregate_sigs(sigs) print('Aggregated sig') attestation_bitfield = get_empty_bitfield(len(committee_indices)) for i, attesting in enumerate(is_attesting): if attesting: attestation_bitfield = set_voted(attestation_bitfield, i) attestation.attester_bitfield = attestation_bitfield print('Aggregate bitfield:', bin(int.from_bytes(attestation_bitfield, 'big'))) attestations.append(attestation) return attestations
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
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 validate_attestation(crystallized_state: CrystallizedState, active_state: ActiveState, attestation: 'AttestationRecord', block: 'Block', parent_block: 'Block', config: Dict[str, Any] = DEFAULT_CONFIG) -> None: # Verify attestation.slot_number if not attestation.slot <= parent_block.slot_number: raise Exception("Attestation slot number too high:\n" "\tFound: %s Needed less than or equal to %s" % (attestation.slot, parent_block.slot_number)) if not (attestation.slot >= max( parent_block.slot_number - config['cycle_length'] + 1, 0)): raise Exception( "Attestation slot number too low:\n" "\tFound: %s, Needed greater than or equalt to: %s" % (attestation.slot, max(parent_block.slot_number - config['cycle_length'] + 1, 0))) # TODO: Verify that the justified_slot and justified_block_hash given are in # the chain and are equal to or earlier than the last_justified_slot # in the crystallized state. parent_hashes = get_signed_parent_hashes(active_state, block, attestation, config) attestation_indices = get_attestation_indices(crystallized_state, attestation, config) # # validate bitfield # if not (len(attestation.attester_bitfield) == get_bitfield_length( len(attestation_indices))): raise Exception( "Attestation has incorrect bitfield length. Found: %s, Expected: %s" % (len(attestation.attester_bitfield), get_bitfield_length(len(attestation_indices)))) # check if end bits are zero last_bit = len(attestation_indices) if last_bit % 8 != 0: for i in range(8 - last_bit % 8): if has_voted(attestation.attester_bitfield, last_bit + i): raise Exception("Attestation has non-zero trailing bits") # # validate aggregate_sig # pub_keys = [ crystallized_state.validators[index].pubkey for i, index in enumerate(attestation_indices) if has_voted(attestation.attester_bitfield, i) ] message = blake( attestation.slot.to_bytes(8, byteorder='big') + b''.join(parent_hashes) + attestation.shard_id.to_bytes(2, byteorder='big') + attestation.shard_block_hash + attestation.justified_slot.to_bytes(8, 'big')) if not bls.verify(message, bls.aggregate_pubs(pub_keys), attestation.aggregate_sig): raise Exception("Attestation aggregate signature fails")
def state_hash(crystallized_state, active_state): return blake(serialize(crystallized_state)) + blake( serialize(active_state))
def privkeys(): return [int.from_bytes(blake(str(i).encode('utf-8'))[:4], 'big') for i in range(1000)]