def create_mock_signed_attestation(state, shard_committee, voting_committee_indices, attestation_data): message = hash_eth2( rlp.encode(attestation_data) + (0).to_bytes(1, "big")) # participants sign message signatures = [ bls.sign(message, privkeys[shard_committee.committee[committee_index]], domain=get_domain( fork_data=state.fork_data, slot=attestation_data.slot, domain_type=SignatureDomain.DOMAIN_ATTESTATION, )) for committee_index in voting_committee_indices ] # aggregate signatures and construct participant bitfield participation_bitfield, aggregate_signature = aggregate_votes( bitfield=get_empty_bitfield(len(shard_committee.committee)), sigs=(), voting_sigs=signatures, voting_committee_indices=voting_committee_indices, ) # create attestation from attestation_data, particpipant_bitfield, and signature return Attestation( data=attestation_data, participation_bitfield=participation_bitfield, custody_bitfield=b'', aggregate_signature=aggregate_signature, )
def _corrupt_signature(params): params = copy.deepcopy(params) message = bytes.fromhex("deadbeefcafe") privkey = 42 domain = SignatureDomain.DOMAIN_ATTESTATION params["aggregate_signature"] = bls.sign(message, privkey, domain) return params
def sign_proof_of_possession(deposit_input, privkey, fork_data, slot): domain = get_domain( fork_data, slot, SignatureDomain.DOMAIN_DEPOSIT, ) return bls.sign(deposit_input.root, privkey, domain)
def test_signature_aggregation(msg, privkeys): domain = 0 sigs = [sign(msg, k, domain=domain) for k in privkeys] pubs = [privtopub(k) for k in privkeys] aggsig = aggregate_signatures(sigs) aggpub = aggregate_pubkeys(pubs) assert verify(msg, aggpub, aggsig, domain=domain)
def _get_indices_and_signatures(num_validators, message, privkeys): num_indices = 5 assert num_validators >= num_indices indices = random.sample(range(num_validators), num_indices) privkeys = [privkeys[i] for i in indices] domain = SignatureDomain.DOMAIN_ATTESTATION signatures = tuple( map(lambda key: bls.sign(message, key, domain), privkeys)) return (indices, signatures)
def test_validate_proposer_signature( proposer_privkey, proposer_pubkey, is_valid_signature, sample_beacon_block_params, sample_beacon_state_params, sample_shard_committee_params, beacon_chain_shard_number, epoch_length): state = BeaconState(**sample_beacon_state_params).copy( validator_registry=[ mock_validator_record(proposer_pubkey) for _ in range(10) ], shard_committees_at_slots=get_sample_shard_committees_at_slots( num_slot=128, num_shard_committee_per_slot=10, sample_shard_committee_params=sample_shard_committee_params, ), ) default_block = BaseBeaconBlock(**sample_beacon_block_params) empty_signature_block_root = default_block.block_without_signature_root proposal_root = ProposalSignedData( state.slot, beacon_chain_shard_number, empty_signature_block_root, ).root proposed_block = BaseBeaconBlock(**sample_beacon_block_params).copy( signature=bls.sign( message=proposal_root, privkey=proposer_privkey, domain=SignatureDomain.DOMAIN_PROPOSAL, ), ) if is_valid_signature: validate_proposer_signature( state, proposed_block, beacon_chain_shard_number, epoch_length, ) else: with pytest.raises(ValidationError): validate_proposer_signature( state, proposed_block, beacon_chain_shard_number, epoch_length, )
def _corrupt_signature(params, fork_data): message = bytes.fromhex("deadbeefcafe") privkey = 42 domain_type = SignatureDomain.DOMAIN_ATTESTATION domain = get_domain( fork_data=fork_data, slot=params["data"].slot, domain_type=domain_type, ) corrupt_signature = bls.sign(message, privkey, domain) return assoc(params, "aggregate_signature", corrupt_signature)
def test_bls_core(privkey): domain = 0 p1 = multiply(G1, privkey) p2 = multiply(G2, privkey) msg = str(privkey).encode('utf-8') msghash = hash_to_G2(msg, domain=domain) assert normalize(decompress_G1(compress_G1(p1))) == normalize(p1) assert normalize(decompress_G2(compress_G2(p2))) == normalize(p2) assert normalize(decompress_G2(compress_G2(msghash))) == normalize(msghash) sig = sign(msg, privkey, domain=domain) pub = privtopub(privkey) assert verify(msg, pub, sig, domain=domain)
def test_multi_aggregation(msg_1, msg_2, privkeys_1, privkeys_2): domain = 0 sigs_1 = [sign(msg_1, k, domain=domain) for k in privkeys_1] pubs_1 = [privtopub(k) for k in privkeys_1] aggsig_1 = aggregate_signatures(sigs_1) aggpub_1 = aggregate_pubkeys(pubs_1) sigs_2 = [sign(msg_2, k, domain=domain) for k in privkeys_2] pubs_2 = [privtopub(k) for k in privkeys_2] aggsig_2 = aggregate_signatures(sigs_2) aggpub_2 = aggregate_pubkeys(pubs_2) msgs = [msg_1, msg_2] pubs = [aggpub_1, aggpub_2] aggsig = aggregate_signatures([aggsig_1, aggsig_2]) assert verify_multiple( pubkeys=pubs, messages=msgs, signature=aggsig, domain=domain, )
def test_demo(base_db, sample_beacon_block_params, genesis_state, fixture_sm_class, config, privkeys, pubkeys): chaindb = BeaconChainDB(base_db) state = genesis_state block = SerenityBeaconBlock(**sample_beacon_block_params).copy( slot=state.slot + 2, state_root=state.root, ) # Sign block beacon_proposer_index = get_beacon_proposer_index( state, block.slot, config.EPOCH_LENGTH, ) index_in_privkeys = pubkeys.index( state.validator_registry[beacon_proposer_index].pubkey ) beacon_proposer_privkey = privkeys[index_in_privkeys] empty_signature_block_root = block.block_without_signature_root proposal_root = ProposalSignedData( block.slot, config.BEACON_CHAIN_SHARD_NUMBER, empty_signature_block_root, ).root block = block.copy( signature=bls.sign( message=proposal_root, privkey=beacon_proposer_privkey, domain=SignatureDomain.DOMAIN_PROPOSAL, ), ) # Store in chaindb chaindb.persist_block(block, SerenityBeaconBlock) chaindb.persist_state(state) # Get state machine instance sm = fixture_sm_class(chaindb, block.root, SerenityBeaconBlock) result_state, _ = sm.import_block(block) assert state.slot == 0 assert result_state.slot == block.slot assert isinstance(sm.block, SerenityBeaconBlock)
def test_aggregate_votes(votes_count, random, privkeys, pubkeys): bit_count = 10 pre_bitfield = get_empty_bitfield(bit_count) pre_sigs = () domain = 0 random_votes = random.sample(range(bit_count), votes_count) message = b'hello' # Get votes: (committee_index, sig, public_key) votes = [( committee_index, bls.sign(message, privkeys[committee_index], domain), pubkeys[committee_index], ) for committee_index in random_votes] # Verify sigs, committee_indices = verify_votes(message, votes, domain) # Aggregate the votes bitfield, sigs = aggregate_votes( bitfield=pre_bitfield, sigs=pre_sigs, voting_sigs=sigs, voting_committee_indices=committee_indices) try: _, _, pubs = zip(*votes) except ValueError: pubs = () voted_index = [ committee_index for committee_index in random_votes if has_voted(bitfield, committee_index) ] assert len(voted_index) == len(votes) aggregated_pubs = bls.aggregate_pubkeys(pubs) assert bls.verify(message, aggregated_pubs, sigs, domain)
def sign_proof_of_possession(deposit_input, privkey, domain): return bls.sign(deposit_input.root, privkey, domain)