def create_mock_genesis_validator_deposits(num_validators, deposit_data_leaves=None): if not deposit_data_leaves: deposit_data_leaves = [] signature = b'\x33' * 96 deposit_data_list = [] for i in range(num_validators): pubkey = pubkeys[i] deposit_data = DepositData( pubkey=pubkey, # insecurely use pubkey as withdrawal key as well withdrawal_credentials=spec.BLS_WITHDRAWAL_PREFIX_BYTE + hash(pubkey)[1:], amount=spec.MAX_EFFECTIVE_BALANCE, signature=signature, ) item = deposit_data.hash_tree_root() deposit_data_leaves.append(item) tree = calc_merkle_tree_from_leaves(tuple(deposit_data_leaves)) root = get_merkle_root((tuple(deposit_data_leaves))) proof = list(get_merkle_proof(tree, item_index=i)) assert verify_merkle_branch(item, proof, spec.DEPOSIT_CONTRACT_TREE_DEPTH, i, root) deposit_data_list.append(deposit_data) genesis_validator_deposits = [] for i in range(num_validators): genesis_validator_deposits.append(Deposit( proof=list(get_merkle_proof(tree, item_index=i)), index=i, data=deposit_data_list[i] )) return genesis_validator_deposits, root
def test_deposit_event_log(registration_contract, a0, w3): log_filter = registration_contract.events.DepositEvent.createFilter( fromBlock='latest', ) deposit_amount_list = [ randint(MIN_DEPOSIT_AMOUNT, FULL_DEPOSIT_AMOUNT * 2) for _ in range(3) ] for i in range(3): deposit_input = ( SAMPLE_PUBKEY, SAMPLE_WITHDRAWAL_CREDENTIALS, SAMPLE_VALID_SIGNATURE, hash_tree_root( DepositData( pubkey=SAMPLE_PUBKEY, withdrawal_credentials=SAMPLE_WITHDRAWAL_CREDENTIALS, amount=deposit_amount_list[i], signature=SAMPLE_VALID_SIGNATURE, ), )) registration_contract.functions.deposit(*deposit_input, ).transact( {"value": deposit_amount_list[i] * eth_utils.denoms.gwei}) logs = log_filter.get_new_entries() assert len(logs) == 1 log = logs[0]['args'] assert log['pubkey'] == deposit_input[0] assert log['withdrawal_credentials'] == deposit_input[1] assert log['amount'] == deposit_amount_list[i].to_bytes(8, 'little') assert log['signature'] == deposit_input[2] assert log['index'] == i.to_bytes(8, 'little')
def to_deposit_data(self) -> DepositData: return DepositData( pubkey=self.pubkey, withdrawal_credentials=self.withdrawal_credentials, amount=self.amount, signature=self.signature, )
def test_deposit_tree(registration_contract, w3, assert_tx_failed, deposit_input): log_filter = registration_contract.events.DepositEvent.createFilter( fromBlock='latest', ) deposit_amount_list = [randint(MIN_DEPOSIT_AMOUNT, FULL_DEPOSIT_AMOUNT * 2) for _ in range(10)] deposit_data_list = [] for i in range(0, 10): tx_hash = registration_contract.functions.deposit( *deposit_input, ).transact({"value": deposit_amount_list[i] * eth_utils.denoms.gwei}) receipt = w3.eth.getTransactionReceipt(tx_hash) print("deposit transaction consumes %d gas" % receipt['gasUsed']) logs = log_filter.get_new_entries() assert len(logs) == 1 log = logs[0]['args'] assert log["index"] == i.to_bytes(8, 'little') deposit_data_list.append(DepositData( pubkey=deposit_input[0], withdrawal_credentials=deposit_input[1], amount=deposit_amount_list[i], signature=deposit_input[2], )) root = hash_tree_root(List[DepositData, 2**32](*deposit_data_list)) assert root == registration_contract.functions.get_hash_tree_root().call()
def test_deposit_inputs(registration_contract, w3, assert_tx_failed, amount, invalid_pubkey, invalid_withdrawal_credentials, invalid_signature, success): pubkey = SAMPLE_PUBKEY[2:] if invalid_pubkey else SAMPLE_PUBKEY withdrawal_credentials = (SAMPLE_WITHDRAWAL_CREDENTIALS[2:] if invalid_withdrawal_credentials else SAMPLE_WITHDRAWAL_CREDENTIALS) signature = SAMPLE_VALID_SIGNATURE[ 2:] if invalid_signature else SAMPLE_VALID_SIGNATURE call = registration_contract.functions.deposit( pubkey, withdrawal_credentials, signature, hash_tree_root( DepositData( pubkey=SAMPLE_PUBKEY if invalid_pubkey else pubkey, withdrawal_credentials=(SAMPLE_WITHDRAWAL_CREDENTIALS if invalid_withdrawal_credentials else withdrawal_credentials), amount=amount, signature=SAMPLE_VALID_SIGNATURE if invalid_signature else signature, ), )) if success: assert call.transact({"value": amount * eth_utils.denoms.gwei}) else: assert_tx_failed( lambda: call.transact({"value": amount * eth_utils.denoms.gwei}))
def build_deposit_data(state, pubkey, privkey, amount): deposit_data = DepositData( pubkey=pubkey, # insecurely use pubkey as withdrawal key as well withdrawal_credentials=spec.BLS_WITHDRAWAL_PREFIX_BYTE + hash(pubkey)[1:], amount=amount, ) signature = bls.sign(message_hash=signing_root(deposit_data), privkey=privkey, domain=get_domain( state, spec.DOMAIN_DEPOSIT, )) deposit_data.signature = signature return deposit_data
def deposit_data_root(deposit_message, signature): deposit_data = DepositData( pubkey=deposit_message.pubkey, withdrawal_credentials=deposit_message.withdrawal_credentials, amount=deposit_message.amount, signature=signature, ) root = hash_tree_root(deposit_data) return root
def build_deposit_data(state, pubkey, privkey, amount, signed=False): deposit_data = DepositData( pubkey=pubkey, # insecurely use pubkey as withdrawal key as well withdrawal_credentials=spec.BLS_WITHDRAWAL_PREFIX_BYTE + spec.hash(pubkey)[1:], amount=amount, ) if signed: sign_deposit_data(state, deposit_data, privkey) return deposit_data
def deposit_input(amount): """ pubkey: bytes[48] withdrawal_credentials: bytes[32] signature: bytes[96] deposit_data_root: bytes[32] """ return (SAMPLE_PUBKEY, SAMPLE_WITHDRAWAL_CREDENTIALS, SAMPLE_VALID_SIGNATURE, hash_tree_root( DepositData( pubkey=SAMPLE_PUBKEY, withdrawal_credentials=SAMPLE_WITHDRAWAL_CREDENTIALS, amount=amount, signature=SAMPLE_VALID_SIGNATURE, ), ))
def test_deposit_tree(registration_contract, w3, assert_tx_failed): log_filter = registration_contract.events.DepositEvent.createFilter( fromBlock='latest', ) deposit_amount_list = [ randint(MIN_DEPOSIT_AMOUNT, FULL_DEPOSIT_AMOUNT * 2) for _ in range(10) ] deposit_data_list = [] for i in range(0, 10): deposit_data = DepositData( pubkey=SAMPLE_PUBKEY, withdrawal_credentials=SAMPLE_WITHDRAWAL_CREDENTIALS, amount=deposit_amount_list[i], signature=SAMPLE_VALID_SIGNATURE, ) deposit_input = ( SAMPLE_PUBKEY, SAMPLE_WITHDRAWAL_CREDENTIALS, SAMPLE_VALID_SIGNATURE, hash_tree_root(deposit_data), ) deposit_data_list.append(deposit_data) tx_hash = registration_contract.functions.deposit( *deposit_input, ).transact( {"value": deposit_amount_list[i] * eth_utils.denoms.gwei}) receipt = w3.eth.getTransactionReceipt(tx_hash) print("deposit transaction consumes %d gas" % receipt['gasUsed']) logs = log_filter.get_new_entries() assert len(logs) == 1 log = logs[0]['args'] assert log["index"] == i.to_bytes(8, 'little') # Check deposit count and root count = len(deposit_data_list).to_bytes(8, 'little') assert count == registration_contract.functions.get_deposit_count( ).call() root = hash_tree_root(List[DepositData, 2**32](*deposit_data_list)) assert root == registration_contract.functions.get_deposit_root().call( )
'b12af968a0f2b6f55b448dd395a3cc2a88b07f902cbddc1ec735dde573c6cad67c099241c50ce9e856a7a2c6ef3f8f08105d3ed5227bcee0356d3a471748bcd445c4f4471d540b3049fa324d519b0bd13e16dbcb340ebc90f165f005fa81ff7d' ) deposit_root = Root( 'ba066d557b3b27a55ae129f01c569dff5daa9ca8a3e45f13188dcb1ac01cb1c5') fork_version = Version('0x00000001') deposit_message = DepositMessage( pubkey=pubkey, withdrawal_credentials=withdrawal_creds, amount=amount, ) domain = compute_domain(domain_type=DOMAIN_DEPOSIT, fork_version=fork_version) signing_root = compute_signing_root(deposit_message, domain) if bls.Verify(pubkey, signing_root, signature): print("GOOD signature") else: print("BAD signature") deposit_data = DepositData( pubkey=pubkey, withdrawal_credentials=withdrawal_creds, amount=amount, signature=signature, ) if deposit_data.hash_tree_root() == deposit_root: print("GOOD deposit root") else: print("BAD deposit root")