From 288289896d6a71536006964ef20a9d3c58667f6b Mon Sep 17 00:00:00 2001 From: Dimo99 Date: Thu, 29 Jun 2023 14:15:15 +0300 Subject: [PATCH] feat(solidity): Add ValidatorsAccumulator.sol --- .github/workflows/ci.yml | 3 + Makefile | 4 + .../scripts/validator_balances/get_input.ts | 5 +- .../validator_accumulator_description.md | 158 ++- .../ValidatorsAccumulator.sol | 122 ++ .../solidity/hardhat.config.ts | 33 +- .../test/ValidatorAccumulator.test.ts | 1038 +++++++++++++++++ libs/typescript/ts-utils/ssz-utils.ts | 34 +- 8 files changed, 1334 insertions(+), 63 deletions(-) create mode 100644 beacon-light-client/solidity/contracts/validators_accumulator/ValidatorsAccumulator.sol create mode 100644 beacon-light-client/solidity/test/ValidatorAccumulator.test.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 43e67335d..98ce1ce70 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,6 +64,9 @@ jobs: - name: Run Verifier in Cosmos - Relayer test run: nix develop -c yarn test './tests/cosmosLightClient/test-verifier-in-cosmos-relay.ts' + - name: Run Solidity Validators accumulator tests + run: nix develop -c make test-validator-accumulator + # - name: Run Verifier in EOS test # run: nix develop -c yarn test './tests/eosLightClient/test-verifier-in-EOS.ts' diff --git a/Makefile b/Makefile index dd36a302c..cca5dd35b 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,10 @@ build-relay-image: docker build -t relayimage -f Dockerfile.relay . +test-validator-accumulator: yarn-check + cd beacon-light-client/solidity && \ + yarn hardhat test test/ValidatorAccumulator.test.ts + evm-simulation: yarn-check cd beacon-light-client/solidity && \ yarn hardhat test test/BeaconLightClientReadyProofs.test.ts diff --git a/beacon-light-client/circom/scripts/validator_balances/get_input.ts b/beacon-light-client/circom/scripts/validator_balances/get_input.ts index d6e0a58d9..909439428 100644 --- a/beacon-light-client/circom/scripts/validator_balances/get_input.ts +++ b/beacon-light-client/circom/scripts/validator_balances/get_input.ts @@ -23,7 +23,8 @@ function getValidatorTree(validator, ssz): Tree { return new Tree(validatorView.node); } -function calculateValidatorsAccumulator( +// TODO: fix so it matches the test in beacon-light-client/solidity +export function calculateValidatorsAccumulator( validatorsPubkeys: Uint8Array[], eth1DepositIndexes: BigInt[], ) { @@ -41,7 +42,7 @@ function calculateValidatorsAccumulator( ); } - const validatorsAccumulator = hexToBytes(hashTreeRoot(leaves)); + const validatorsAccumulator = hexToBytes(hashTreeRoot(leaves, leaves.length)); return bytesToBinaryArray(validatorsAccumulator); } diff --git a/beacon-light-client/circom/scripts/validator_balances/validator_accumulator_description.md b/beacon-light-client/circom/scripts/validator_balances/validator_accumulator_description.md index db0ce4709..2ded291dd 100644 --- a/beacon-light-client/circom/scripts/validator_balances/validator_accumulator_description.md +++ b/beacon-light-client/circom/scripts/validator_balances/validator_accumulator_description.md @@ -6,69 +6,129 @@ A Merkle tree accumulator is a binary tree of hashes, which is used for efficien This is a sample solidity implementation of the `validatorsAccumulator` ``` -// The depth of the validator accumulator tree -uint constant VALIDATOR_ACCUMULATOR_TREE_DEPTH = 32; +// SPDX-License-Identifier: MIT +pragma solidity 0.8.18; + +// This interface is designed to be compatible with the Vyper version. +/// @notice This is the Ethereum 2.0 deposit contract interface. +/// For more information see the Phase 0 specification under https://github.com/ethereum/eth2.0-specs +interface IDepositContract { + /// @notice A processed deposit event. + event DepositEvent( + bytes pubkey, + bytes withdrawal_credentials, + bytes amount, + bytes signature, + bytes index + ); + + /// @notice Submit a Phase 0 DepositData object. + /// @param pubkey A BLS12-381 public key. + /// @param withdrawal_credentials Commitment to a public key for withdrawals. + /// @param signature A BLS12-381 signature. + /// @param deposit_data_root The SHA-256 hash of the SSZ-encoded DepositData object. + /// Used as a protection against malformed input. + function deposit( + bytes calldata pubkey, + bytes calldata withdrawal_credentials, + bytes calldata signature, + bytes32 deposit_data_root + ) external payable; + + /// @notice Query the current deposit root hash. + /// @return The deposit root hash. + function get_deposit_root() external view returns (bytes32); + + /// @notice Query the current deposit count. + /// @return The deposit count encoded as a little endian 64-bit number. + function get_deposit_count() external view returns (bytes memory); +} -// An array to hold the branch hashes for the Merkle tree -bytes32[VALIDATOR_ACCUMULATOR_TREE_DEPTH] branch; +contract ValidatorsAccumulator { + address depositAddress; -// A counter for the total number of validators -uint validators_count; + // The depth of the validator accumulator tree + uint constant VALIDATOR_ACCUMULATOR_TREE_DEPTH = 32; -constructor() { - // Compute hashes in empty Merkle tree - for (uint height = 0; height < DEPOSIT_CONTRACT_TREE_DEPTH - 1; height++) - zero_hashes[height + 1] = sha256(abi.encodePacked(zero_hashes[height], zero_hashes[height])); -} + // An array to hold the branch hashes for the Merkle tree + bytes32[VALIDATOR_ACCUMULATOR_TREE_DEPTH] branch; + + bytes32[VALIDATOR_ACCUMULATOR_TREE_DEPTH] zero_hashes; + + // A counter for the total number of validators + uint validators_count; + + constructor(address _depositAddress) { + depositAddress = _depositAddress; -// Function to calculate and return the Merkle accumulator root of the validators -function get_validators_accumulator() override external view returns (bytes32) { + // Compute hashes in empty Merkle tree + for ( + uint height = 0; + height < VALIDATOR_ACCUMULATOR_TREE_DEPTH - 1; + height++ + ) + zero_hashes[height + 1] = sha256( + abi.encodePacked(zero_hashes[height], zero_hashes[height]) + ); + } + + // Function to calculate and return the Merkle accumulator root of the validators + function get_validators_accumulator() external view returns (bytes32) { bytes32 node; uint size = validators_count; // Calculate the Merkle accumulator root for (uint height = 0; height < VALIDATOR_ACCUMULATOR_TREE_DEPTH; height++) { - // This if-else structure supports tree balancing - // If size is odd, the new node will be hashed with the previous node on this level - // If size is even, the new node will be hashed with a predefined zero hash - if ((size & 1) == 1) - node = sha256(abi.encodePacked(branch[height], node)); - else - node = sha256(abi.encodePacked(node, zero_hashes[height])); - - size /= 2; + // This if-else structure supports tree balancing + // If size is odd, the new node will be hashed with the previous node on this level + // If size is even, the new node will be hashed with a predefined zero hash + if ((size & 1) == 1) + node = sha256(abi.encodePacked(branch[height], node)); + else node = sha256(abi.encodePacked(node, zero_hashes[height])); + + size /= 2; } return node; -} - -// Function to handle deposits from validators -function deposit( - bytes calldata pubkey, - bytes calldata withdrawal_credentials, - bytes calldata signature, - bytes32 deposit_data_root) { - // Perform the deposit using the DepositContract - IDepositContract(depositAddress).deposit(pubkey, withdrawal_credentials, signature, deposit_data_root); - - // Get the deposit count and increase the validator count - bytes deposit_index = IDepositContract(depositAddress).get_deposit_count(); - validators_count += 1; - - // Create a node for the validator - bytes32 node = sha256(abi.encodePacked(pubkey, deposit_index)); - - // Insert the node into the Merkle accumulator tree - uint size = validators_count; - for(uint height = 0; height < VALIDATOR_ACCUMULATOR_TREE_DEPTH; height++) { - if ((size & 1) == 1) { - branch[height] = node; - return; + } + + // Function to handle deposits from validators + function deposit( + bytes calldata pubkey, + bytes calldata withdrawal_credentials, + bytes calldata signature, + bytes32 deposit_data_root + ) public payable { + // Perform the deposit using the DepositContract + + IDepositContract(depositAddress).deposit{value: msg.value}( + pubkey, + withdrawal_credentials, + signature, + deposit_data_root + ); + + // Get the deposit count and increase the validator count + bytes memory deposit_index = IDepositContract(depositAddress) + .get_deposit_count(); + validators_count += 1; + + // Create a node for the validator + bytes32 node = sha256(abi.encodePacked(pubkey, deposit_index)); + + // Insert the node into the Merkle accumulator tree + uint size = validators_count; + for (uint height = 0; height < VALIDATOR_ACCUMULATOR_TREE_DEPTH; height++) { + if ((size & 1) == 1) { + branch[height] = node; + return; + } + node = sha256(abi.encodePacked(branch[height], node)); + size /= 2; } - node = sha256(abi.encodePacked(branch[height], node)); - size /= 2; - } + } } + ``` In the deposit function, each validator's public key and their Eth1 deposit index are packed together and hashed to form a node. This node represents the validator in the Merkle tree. diff --git a/beacon-light-client/solidity/contracts/validators_accumulator/ValidatorsAccumulator.sol b/beacon-light-client/solidity/contracts/validators_accumulator/ValidatorsAccumulator.sol new file mode 100644 index 000000000..da5fb4516 --- /dev/null +++ b/beacon-light-client/solidity/contracts/validators_accumulator/ValidatorsAccumulator.sol @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.18; + +// This interface is designed to be compatible with the Vyper version. +/// @notice This is the Ethereum 2.0 deposit contract interface. +/// For more information see the Phase 0 specification under https://github.com/ethereum/eth2.0-specs +interface IDepositContract { + /// @notice A processed deposit event. + event DepositEvent( + bytes pubkey, + bytes withdrawal_credentials, + bytes amount, + bytes signature, + bytes index + ); + + /// @notice Submit a Phase 0 DepositData object. + /// @param pubkey A BLS12-381 public key. + /// @param withdrawal_credentials Commitment to a public key for withdrawals. + /// @param signature A BLS12-381 signature. + /// @param deposit_data_root The SHA-256 hash of the SSZ-encoded DepositData object. + /// Used as a protection against malformed input. + function deposit( + bytes calldata pubkey, + bytes calldata withdrawal_credentials, + bytes calldata signature, + bytes32 deposit_data_root + ) external payable; + + /// @notice Query the current deposit root hash. + /// @return The deposit root hash. + function get_deposit_root() external view returns (bytes32); + + /// @notice Query the current deposit count. + /// @return The deposit count encoded as a little endian 64-bit number. + function get_deposit_count() external view returns (bytes memory); +} + +contract ValidatorsAccumulator { + address depositAddress; + + // The depth of the validator accumulator tree + uint constant VALIDATOR_ACCUMULATOR_TREE_DEPTH = 32; + + // An array to hold the branch hashes for the Merkle tree + bytes32[VALIDATOR_ACCUMULATOR_TREE_DEPTH] branch; + + bytes32[VALIDATOR_ACCUMULATOR_TREE_DEPTH] zero_hashes; + + // A counter for the total number of validators + uint validators_count; + + constructor(address _depositAddress) { + depositAddress = _depositAddress; + + // Compute hashes in empty Merkle tree + for ( + uint height = 0; + height < VALIDATOR_ACCUMULATOR_TREE_DEPTH - 1; + height++ + ) + zero_hashes[height + 1] = sha256( + abi.encodePacked(zero_hashes[height], zero_hashes[height]) + ); + } + + // Function to calculate and return the Merkle accumulator root of the validators + function get_validators_accumulator() external view returns (bytes32) { + bytes32 node; + uint size = validators_count; + + // Calculate the Merkle accumulator root + for (uint height = 0; height < VALIDATOR_ACCUMULATOR_TREE_DEPTH; height++) { + // This if-else structure supports tree balancing + // If size is odd, the new node will be hashed with the previous node on this level + // If size is even, the new node will be hashed with a predefined zero hash + if ((size & 1) == 1) + node = sha256(abi.encodePacked(branch[height], node)); + else node = sha256(abi.encodePacked(node, zero_hashes[height])); + + size /= 2; + } + + return node; + } + + // Function to handle deposits from validators + function deposit( + bytes calldata pubkey, + bytes calldata withdrawal_credentials, + bytes calldata signature, + bytes32 deposit_data_root + ) public payable { + // Perform the deposit using the DepositContract + + IDepositContract(depositAddress).deposit{value: msg.value}( + pubkey, + withdrawal_credentials, + signature, + deposit_data_root + ); + + // Get the deposit count and increase the validator count + bytes memory deposit_index = IDepositContract(depositAddress) + .get_deposit_count(); + validators_count += 1; + + // Create a node for the validator + bytes32 node = sha256(abi.encodePacked(pubkey, deposit_index)); + + // Insert the node into the Merkle accumulator tree + uint size = validators_count; + for (uint height = 0; height < VALIDATOR_ACCUMULATOR_TREE_DEPTH; height++) { + if ((size & 1) == 1) { + branch[height] = node; + return; + } + node = sha256(abi.encodePacked(branch[height], node)); + size /= 2; + } + } +} diff --git a/beacon-light-client/solidity/hardhat.config.ts b/beacon-light-client/solidity/hardhat.config.ts index 0e9c88cc0..b887426e6 100644 --- a/beacon-light-client/solidity/hardhat.config.ts +++ b/beacon-light-client/solidity/hardhat.config.ts @@ -39,13 +39,26 @@ if (!/^0x[0-9a-fA-F]{64}$/.test(conf.USER_PRIVATE_KEY ?? '')) { export default { solidity: { - version: '0.8.9', - settings: { - optimizer: { - enabled: true, - runs: 200, + compilers: [ + { + version: '0.8.9', + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, }, - }, + { + version: '0.8.18', + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, + }, + ], }, defaultNetwork: 'hardhat', networks: { @@ -54,8 +67,10 @@ export default { accounts: [conf.LOCAL_HARDHAT_PRIVATE_KEY], }, hardhat: { - blockGasLimit: 30000000, - allowUnlimitedContractSize: true, + forking: { + url: 'https://eth.llamarpc.com', + blockNumber: 17578101, + }, }, ropsten: { url: `https://ropsten.infura.io/v3/${conf.INFURA_API_KEY}`, @@ -118,7 +133,7 @@ export default { accounts: [conf.USER_PRIVATE_KEY], }, gnosis: { - url: `https://gnosis.api.onfinality.io/public`, + url: `https://rpc.gnosis.gateway.fm`, accounts: [conf.USER_PRIVATE_KEY], }, }, diff --git a/beacon-light-client/solidity/test/ValidatorAccumulator.test.ts b/beacon-light-client/solidity/test/ValidatorAccumulator.test.ts new file mode 100644 index 000000000..0e1df6900 --- /dev/null +++ b/beacon-light-client/solidity/test/ValidatorAccumulator.test.ts @@ -0,0 +1,1038 @@ +import * as path from 'path'; +import { ethers } from 'hardhat'; +import { getFilesInDir, Proof } from './utils'; +import { convertProofToSolidityCalldata } from '../../../libs/typescript/ts-utils/zk-utils'; +import INITIAL_UPDATE from '../../../vendor/eth2-light-client-updates/prater/capella-updates-94/update_5601823_5609044.json'; +import { Contract } from 'ethers'; +import { sha256 } from 'ethers/lib/utils'; +import { hashTreeRoot } from '../../../libs/typescript/ts-utils/ssz-utils'; +import { + bytesToHex, + formatHex, + hexToBytes, +} from '../../../libs/typescript/ts-utils/bls'; +import { expect } from 'chai'; + +const depositContractAbi = [ + { inputs: [], stateMutability: 'nonpayable', type: 'constructor' }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: 'bytes', name: 'pubkey', type: 'bytes' }, + { + indexed: false, + internalType: 'bytes', + name: 'withdrawal_credentials', + type: 'bytes', + }, + { indexed: false, internalType: 'bytes', name: 'amount', type: 'bytes' }, + { + indexed: false, + internalType: 'bytes', + name: 'signature', + type: 'bytes', + }, + { indexed: false, internalType: 'bytes', name: 'index', type: 'bytes' }, + ], + name: 'DepositEvent', + type: 'event', + }, + { + inputs: [ + { internalType: 'bytes', name: 'pubkey', type: 'bytes' }, + { internalType: 'bytes', name: 'withdrawal_credentials', type: 'bytes' }, + { internalType: 'bytes', name: 'signature', type: 'bytes' }, + { internalType: 'bytes32', name: 'deposit_data_root', type: 'bytes32' }, + ], + name: 'deposit', + outputs: [], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [], + name: 'get_deposit_count', + outputs: [{ internalType: 'bytes', name: '', type: 'bytes' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'get_deposit_root', + outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'bytes4', name: 'interfaceId', type: 'bytes4' }], + name: 'supportsInterface', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'pure', + type: 'function', + }, +]; + +const depositItems = [ + { + pubkey: + '0x89bcf22c91a560d95d09c1192664eea1baab0780b6d4441ca39d1cb5094b177b17f47a67b16fb972bfd3b78b602ffeee', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xaf92ccc88c4b1eca2f7dffb7c9288c014b2dc358d4846037a71f22a7ebab387795fd88fd29ab6304e25021fae7d99e320b8f9cbf6a5809a9b61e6612a2c838cea8f90a2e90172f111d17c429215d61452ee341ab17915c415696531ff9a69fe8', + depositDataRoot: + '0x757b092b9157a2a946ebf5209660433a71ccabe15b50dbf0cfcc21b9f090e1b5', + }, + { + pubkey: + '0x957882961f53250f9b2b0ca1ad5b5f4fc1a89c3a55cd2dbba3df9e851f06c93e9fe2e691971884a269d4e40f3d054604', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x90b6e69502e7cf0bf1f385d121d1f60bd57d83081fcf96e130a7abc2beac046e1e28ec360e5455d226602d6ddd2eb39c162f09bc9420271eb8199c891d7bb52984a09fe416807ff7ed0eddd5eeeb2c07b13b38afafad77ec4f109828c8a73587', + depositDataRoot: + '0xe3d15b9aaa074aac4a55583a13f463d6b565ed8e4b1366c203616e75642ab2db', + }, + { + pubkey: + '0x92d0fcb9349a39352519c9f3930916d7c36ca3e4f8610dc41698622becddb39ea0bf27173a56233474ef95cb7f035f80', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xaafeee8adaf0b486d14c7eefc9164b0e0adab47fd9014c604bf629955185e111863797a8e9a6ade9c387f79daaaaf8530faa8cfd6d4d6e9964e206fc02618f5b0bb8a497f5271d0e542cb5d3bb27701cb5a38b1d65d278ff931ed1057f65b684', + depositDataRoot: + '0xc4bfe4fadc951bdd1ce9d63d9c65c9189670c19c6d535be5ca121070b7138855', + }, + { + pubkey: + '0x965e2f75c43c93fc7b5efbc03649f13b5bd18bd1fd02a6294a6941b314989c9a5ba729276c2f3981a763d008f1957fe4', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xb792cb5952280a52a23b14d39158911016214fda575b6884fbaa8b66d29a7fa55d8909380021a38410f4a2b25edb47cd0222bb9d175ddfe4e6545b58d5bcd0b099d6193db5e8d161fac6c0292ae24aac0e24fa2a17484e2112e89ef505b25a46', + depositDataRoot: + '0xc004a0e0c4a536077caacf346c1a868d6ba5a605a40f80d9e4d0e786d3324bef', + }, + { + pubkey: + '0xa7a3e154aed45c46b01953f74695bf4a0ee50b15ad0f89157dddd7d8783fd3bafb1ad7c279b2e57e2c58071162c35e81', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x8ae6a82e2a51cf69dc962c08b65a5c6d769ecdc47bc518a6d3d8f65525237e03e09f154159183831296f65bdeae47be506f0ac5bfaa9f8f95c081c2d9318d55a84f580b2dd3ee8b35a84d849eaa01324065cd32785ea89850ce761bb91cb107f', + depositDataRoot: + '0x9713ebfa939e06f42066ddc605a0a866eb75c4d7bb78091588273a8c8c70afbc', + }, + { + pubkey: + '0x90e25c49b32bda80d9d07738f01f7550f0adbbedf598fc34c5bb7b084fad6f38cebf39046d79f51a1ab99526e1cbfebd', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x88411327903f1f341524e671284a9c5b0df540b5915515710e51bf3f82b254abba36d110b3571ccccdd5d0fe3921ad4512f1fc63b493d5afe746cbe349440dceebee8a6a6cc13607be82bf1c93e94beebefde23cb078515a4f575eebb80f4bb7', + depositDataRoot: + '0xd462d74e6425e06ca174ad3ed805a5742c1b87404c6ef17dd8dcd810e3fd6fa9', + }, + { + pubkey: + '0x81d30decfd9ef8fdebc115998be6f6d36ad48d29defb31a19d7f4eca9501f2bb467a843203aaa4a0a9df25cd2e1de9f8', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x8dc3b898805de91fe98da49f3937cbed88b8fc1450734870e792082873346de2e976683bc7a02e81f0d5e8afc625c54a00a697acbcfcc1ad61c8577dc3e26a647806abcc8c11ad327c3b6382887d8537b28e17673e74e5692257c16ef318ed4f', + depositDataRoot: + '0x5878b7d122477ecd4c30cfa69ac6f6ae3131435b17a9244f15d1c09c7ca9b618', + }, + { + pubkey: + '0xb08620c051d972e6e74613f3491933a32c6fb7244de106d004eaee230299bd019164874ea5df124560a467f8888e43f1', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xb61357a9a275eb09c1c00f3edf69d18d3a54c0ea9073a500a242113fffb59b0da579bc65f48580a5969e45c53352ebcd02d6e8240960b89f8da39b338a5a5a851e6156ef8510a9ca2facd6f274745f73ec80349ebbd8248a13afd5362f26c4ed', + depositDataRoot: + '0x2e60d40c133d6e8e159787089936c392b3018c09bb861d45dd0ef883fe2097ac', + }, + { + pubkey: + '0xad6ba9d6b7e87373568b42cc3b8df4717812092c6f5ea91dbd72b59c827623bafe3999ca7fec5f1c4af8b66b305c9b13', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xa09cb7d15872bbd62409dcc96e04c92fa7419098ed7108a1d7b9d6bcf8cdb9f8c27123b9d20ede944eeef47c01bab2180dfdd6cb3381259135100a57d8de48a2f70d5f681a13f1cf98e2b1a78c6420910132096713dadbcca17cf9004bf97052', + depositDataRoot: + '0xca97880108c27ab520daee9298aa04abcbbfb5111d3d7588b39af2eabfbd0b96', + }, + { + pubkey: + '0xb79c926fb0e5dff048b2a8a89506c87a317d0fc7318c8723f67b6518617692df0ca02a3679db65c34f6a8041da4ae961', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x9815aec7424bc1918c1e0e3b2fa1d1e77ea5609e3c29485a281b6d83812a7d023d703e061d4cffa78171d360544e361811e1746bb90fbc010d16310e330103c8fd8378b5f9f692a1a5153d69459e3955a97fb170f3b4ba47d3acae2e471a7d4a', + depositDataRoot: + '0x5c1643e2c735ad3e493efdc154192106d442db19b5b9b8c5b87e62b327e50637', + }, + { + pubkey: + '0xa3f714a37e0fa87a96256bf58a0ab29c156148131c87fdfefee1c8201025ce3fafbb97a3fff67f77e454df622e2a9bee', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x8fd9712c371b18aa5d868bf191576d5cd1da84f07994086ca15374d400d5f4349c0547d303852663371eb547b0e44dfd0b3c6dcec44d64fd709e990a48cb03c3228e46fa4e5c272608ba6d73411c44b31d20a4edce78991c0b07c08875fb587a', + depositDataRoot: + '0xa11bbce086b7d3394a87d9f0a7a4836d317033eedda55cb099d969d4fea31b76', + }, + { + pubkey: + '0x94767f1d73c4cd2e0588c2fdbcede391ca26977f78522fc9cdf9dbb519244df7381783c54bf822aef872a59f73e3dcd4', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x98c4039ea7f696aeb8a2e8d941fde3fd779522dd42af56a149fa8629d276639ea446f2ad1bae8e18543e1ccf54afdb360911958d9d96749a5c3af6fecd687c99bd2579adc00c6b2fbde9aedbf93e50062c7dfb5238dfdaad0a35503afb921c8c', + depositDataRoot: + '0xcf9613088b05c0420f02432c380f9f234eef3ab5f6f17a42b1152a6b17479ff1', + }, + { + pubkey: + '0x900ac4c458401824a12023d1cbc71684230de02cf5e86369657f7de083079d54080bbb6a22c46e11b77a2a8ed80c4798', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x8cd1c985e861a18113f8c76b36947ad3b56b0b72368c6d739d7081a804aa0b23d6d5af53af65e7b4401814c6a012288f145fea62c55d143bdd4a823158790ea131db415ea31807c0e14e45ea6bd9ee9bc672e24a4a13636e5e5eaf021f3d04e6', + depositDataRoot: + '0x69cb6592f039ea2cc27d2350e98beeb5a5f895b301c3cbda4cd213cbf85fd193', + }, + { + pubkey: + '0x89f36f1f4f86ba98a899ab021ef39f10e9ac761e8e770e99be1b90b215a14d9409f946cc93d1b1e21b00b6de2a79445b', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x95bfd017dea1ec956310461f0bb846f094d8aea6d9111ead55f16269bc25257cec31e5bf561ca2b6aba26cfd5fca67010fe2d32a7bfb6cc69b68d49625a3038d7a46d4eb053f7a75bd2ce3ffd9dd48ff651e0956e5270330a88d6d3eb7e04bbe', + depositDataRoot: + '0xcff086cff1f83727b7e135b7a133755cf67277fa32beaf65c67ebb0f94cbfd96', + }, + { + pubkey: + '0x8b85c0e1ebcf9a8e6980ef94fd3933db8144916fac01eec83f7f7de74df9ad90923b6c57cc9744da2f2e078a230cf708', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x93e4c6b4f3eb4181036b6c43d9f0a7ecb64f590497c75d5add9c7be92da68a5918e9521666cefac59d4e3bcb8e4059eb07b57144f6803ac732a75fbc61388f34f5680c2edbe427ee85b23bcdf4467868a1fb87fba5c613289555765731b44ace', + depositDataRoot: + '0xb35b88b53cd8d73ae68a20856f0a03719efd59da21c627c08346a547c29d5b2f', + }, + { + pubkey: + '0x9175495df91ea6bce297e1e8b6fd3dedf4d38b68ad3098ad741e495abcb592a24becee47e75048ce43fc6dd9ca8c4c0d', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xa3bb7be5f60b6e1df64cd0d3b63afd280f59849515c96b52bf48a0fda0c75897ac812a395e4cec6fd3590adedd99a8dd164cc6b5d39b4f4c95e69893f02ff07764976cd5ab0317e1b050b6e69db241bc06be42244d204edb265756d46f48e5b4', + depositDataRoot: + '0x19f5b694738e77a29b9f6bdfbb25c14be12a853fb8b891efcb8ed32cd8994ac1', + }, + { + pubkey: + '0xa462be8b2b9b616991ac4ebea15cabe09de067c76ad85fd81a771f34e56efbb30cc7742f80464edce56b0e738df67f7a', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x830c823669d2f3b0834a03c864dcc4cc80173d41025dc61fb9d4ea908afd03895fa4712d94b64d1e2be04124ddadfefc0e7edc4abc74b3cbcf5b9486c12533748ac824381b3a60c74bddb927a7941fcc422456af6b8dc4a09f7ef60e4716bc3a', + depositDataRoot: + '0x749ede17afb7414cbaf413d2c5c439220be90cf0b751a6334337493247131762', + }, + { + pubkey: + '0xb13902f76467bf13710a77f8c8b0028beef845823426237b91cc066b462794a8b70785002475900844bdd9b820608cd5', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xa1450df77809a48b24d7ecdda42c936268cd6540a595beefb54784db1e38d9cb76c41fbb7d23c29b76666f3b9d1756191578dd67aae5679d5d3f6c50e583a6b39bd1de7bd7865ec18c2c1a8e75ed3524dd7ece8ace9026ac75f5c57fed7c70df', + depositDataRoot: + '0xa2dc07230095c4506ca4851cf595f8a197cc27a2fb8704059ff69d3191c6d40a', + }, + { + pubkey: + '0x966e99e202db09cfa407cedb176fc692ad620474ec37c2bce23fdb1c565b1f50bff989245200e3b7dd33edc8c204c938', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xb39521083226d7b13c4bbbe5f749f6fac5104de6742c9088f256d5e4048b9910042e097c5846dff50327593ee9e4324f0295426ee43972ca9bf261e1932bb020ed3b4bf66e495b5fb9ef854e11f159fe53cf601923f5360e80efffd235c816c5', + depositDataRoot: + '0xe5e380e59ef85764ebb7837ba1133e50f6fa25e050deaaba078b62a68a9c4dbc', + }, + { + pubkey: + '0x8373ace9d9201e08f0e424722ed4b68f2b236c0ccde0f82cfa9e87fa5fcfdd09eeb057d0da88a10cbd07f187a888c073', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xb849fad5b877a8bd1176f4a0b313b0ea6cb4ce38b1267525c5c0b338fed1416130e0501a68edc0520f6baa71d9cef9610f399a645f8f6d5611d77eb8229f2892a5994eb4331026f2c957fedad26e26a58164ea6c896ba9c3f279f01d2ccf6e6c', + depositDataRoot: + '0xe8743c77286dc9a3cd373b20d703cf2d9714949788d6fd3ae482d1c29da12702', + }, + { + pubkey: + '0xb4e215f7e7dca63ec0cfa8309e1f852892f50f2c90873082c04cc2b73b4b968abb9dce1930e1888e8fd949312768a517', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xa73c20b1bce035a81dfb0118896b2ea795e01c114fff464731dd14c29e5aa37e200fe8816a5b71922dc820f42312be6c0befb90717750bcea2165fcad71d47ad15db84c85cff0c3b43d5ae176ef2b555aedeacff62a0aa54b09f382cb42351ff', + depositDataRoot: + '0xd1be80ab0a2c9f6cc1b45555c8cfcc25fa1f9c8d26ed0a37c8673201aa0afa8b', + }, + { + pubkey: + '0x8bb50657366de1bbd904b53763cebae471d171888c887cf769a823d88704e413b4b0f59921e313c291f05aaf092d343b', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x84922c523d337ea189210fbb9ae6af79af61d2eaa9e2f6b2c875e31c97ee617ccc304e7f98782b312fecdd0fd86b60c70b3458dea5ce892b5c2d037d6f02601976fdebd22e4fe9c46182347da6f92fe82ae0b027541a89d1573b2d34f5fd7fcb', + depositDataRoot: + '0x51036d18c80d4a7c6c680582ed98d267081b3920103252f599f6398490b3587b', + }, + { + pubkey: + '0xa00f9d801ef265436ad251c33895667bab7e5e0098d945ad5ba99eb576dff65adc8295d2ad44c78827ad911bf2bc3d86', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x86528f09304a2c87b41cd8812cc6b4a44ebcb079549331f3723c353bdd87a35ff62b587520fb0d6fb3d6cf34dfa2103205cef4bbb1d49b488464e1a43c0d2bd11c5385a4d7adc352ab67abb6fa0135f93d429cddd39695c3c7a192af38898e44', + depositDataRoot: + '0xfc409460d51d097e7b55edf8b42ed7964623d152a19e851bad26cb0b0c190f3d', + }, + { + pubkey: + '0x8c08481744bf74828f368a583bdc2d8dd6d0d1335a4397c23e73ff19e8a871eda607df33ebe3fcdacd8ed6cf9c1abee9', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x8c1ac6dba7fa04fd6a93214096ac7d952b1ad3dad749da9b594964974dda82911b9508bfcd0ec753641e45072c627f750da0d039e2896c71f908904f2bc50840871f420eedfada10c491c78f24bc9f698f9fbfa51b930e1fa74963d2c4f01a25', + depositDataRoot: + '0x7bb8e59bd9c15e25e07dcbc1d2eac1216a88c9706a9364f2b465821a3cd53eed', + }, + { + pubkey: + '0xa6e9c962abca48b0fd81564bc0f62007ad0f71964c29759ce2ebe7d106e2d10bac08f585ec9459ef275e5e1c5c528049', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x939073b9cd70affe327a1fbc7a208a6ab9e3c33d2fa0bc723eb54843e391c6954c9a0e49056ff9c465247bad7fc8c8bf0ef12e11a7c6dbd144b553757044a17d3703f35ecfdcc51fc4cfb6f971bd186c9995085cdc87d377d6b11931acc3d572', + depositDataRoot: + '0x479a777dab71194b694390d6545f95c5d57294bd86ee8b2f7642966ab57f73d1', + }, + { + pubkey: + '0xb4f7fa7be9751c7aee510d5fad843a93114178fc21155f611c6fb53ac4ff712f1ff8815dc2440e44510405b55277ae19', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xb984f363e279f735b9cfdb9ff92f0338261c2adb42f0d4fee9626d8f58266089ec0f2d3b9da6074819bf4e4d9f6b754a0d3994a819480f2f1a0370a1dfc4013ccb114423bb6057ddd5c0dbed6ab2231233f78ab19b0955f56a9048b2c9bd119e', + depositDataRoot: + '0xbd6243636dd89abe2c9982829091c7dbef74f99df1ae424da05b0b5fce3eb895', + }, + { + pubkey: + '0xa4d8b3541d2230e6add4cc860784a7b82f06742c1136668d79a46186f527cf557e45c51189a41c21d7c54a97c1a55c59', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xb5bcfb34deb16c034883824325e527b32838f5232b2f6a3dc7d04eb65ab1daab8059496e63378503581c5db8e6ee723b07f7cecb2e5271d3d0cf2f809d098f30dd660acf6328aba64fed760e2a8e0a9fa911685977f07eb138c9a4ffbf587a06', + depositDataRoot: + '0x738166674190e18fe4ff7eca6fba2cc9be7796326ca02c49ce15c66a7ac46e6e', + }, + { + pubkey: + '0xa624973ae52339f139105250b68f1aeea61dabd818ddd43471f820003eb97129cd279a27ca109e903f536c104faa17a5', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x93647af0d8d2584ffb228219cdd2c560eef8f5b76bcc42b12cb81eff6a41b609f9af20e5df49d22c1132705b41f7e04606cb7df3ce27b8713a01d20bd1ca00a2deb750d08e691e8278559b2a5a0090587c07d5c5c92e30081dc77ad374fbd059', + depositDataRoot: + '0xdd35f76017f1879040211a386203d6ea4589b49b3c0c64b5bbc6634a6c49c716', + }, + { + pubkey: + '0xb6c098d6f05550ec1f215409d6f684b488927f13a26d2397710c792c9221ded1f9ac5f588434b01726e10581ad6f3c4a', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x8c28a9851aecca30b577fa15e03504ae8d079ece9f3231299976162c9c80c6ef4acfa2bb0a164b6765a6cbb9ecae1b2a12c4fcbac9d3c375c512377126b64dbba74d8000282c816edb7c7e660e427b1d63ee6604b6ecfb59461ed5aba663652f', + depositDataRoot: + '0x73ee8d5c8692567357114fe958a663792b134309fc98751fc2ad95b9e8201dd3', + }, + { + pubkey: + '0xa0d6f34abe5c9df47d36410d3a8f6b68d517d3d2bbcac4aaa4f17d29cd8b618a326cd7eb14fe13af2f4c7927075a9e0f', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x938ebe82a9314597fbaf60c1aa507aa3899f2e62479d3b086b8e481431df0a49fcfcc16fc0a4cd9f48106ffb52b8302115ba5c554a39b54f8fc9a97c2bbd5bbd23c239764d294f830888de1e6195db61f46fe9e101c9a6439e26176578e0f085', + depositDataRoot: + '0xf509089de47badce14105966188e5c9a420f2c377e7d56d2aa9b04f06678a764', + }, + { + pubkey: + '0xa1a374b55950cd4ce36fd7a423a50bdab1246896224859239f920ccd0356cc69eb4598dbfeb15517d8d14c511bc3474b', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xacae5f159a98e3fdae448fd8a2bf7a8cce7f197c0e99cc83176fcd4f77e9e361a42c70a8314da0c203e57983b591e8a7037789cffa86b8e5b71e1aef123aba17c576153c4f688e742cbe49ebf36de3f62eb2556b973e2b1db4d11f8535cbd695', + depositDataRoot: + '0x4d3aec5be99856efd078b8e11c02a807baf6a47ed5b1cd8469b64478d6806c69', + }, + { + pubkey: + '0x9049ba59d8c58c6afaae3ba9dd4520a21433a4b640d3e21fb8ac01bf76db0da7b4a0e503b57cacb33faa8d91e4f6fc15', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xa0ec2ef54400491dccc126b95ccd7ba1c2977dd91dc929c080aa4d7dffdd96853813b6e2f455cf7ce0d2b9cd078f0ff2158d068bf13fb6cc4a982106cc79c37c250fb23150c5431dffeda300e3dacbebe45b7e9d6bac02a7461c93f6cb625480', + depositDataRoot: + '0x7821d47452510ebdf759f096ff3cdd6c70d9fdb0f1902889c9446775519e6b08', + }, + { + pubkey: + '0x972ef891ac655333bc1cf99543dfd0cdc09e10abcf5fee635fb4457553549a07be6fd96ca75418b3c761952775837b23', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xa25d9ad3a4fa2bb96e774be9c1ad47bad90c4d1f61b197d8a756d40cfcb8abd56894e61c4a7e06b100b39c5d614c56c2056cc80f5b25c9996e473d90f384b5ffbfa05a525a9c9694dfc13128df45bab7ef867252655ddfc5f967ab57f1177def', + depositDataRoot: + '0xcef875096ddfd5d018dab7459d7a9e7d2bdbe7416109e118e49383494732bfa3', + }, + { + pubkey: + '0x83201635b83797c4b600306f6c469497d126d71257910314ffff972f827c766fc2552da554ff64c7685c740b5ba4afb6', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x92e67ab1bf26ace00783c026b6154ecf0da7a7f9ac52f872732a07aa609cb7418f06d332c850932009d3289b8f1c8d430369ece513145a3b68b560bbc26020b157f85df265eb175f08958d13f9c88dce698804030c5981967b50cb11941b776c', + depositDataRoot: + '0xb620b3f0938cc03b9047fdeb47e6693f132779443e9c495031691bb7b67cacbc', + }, + { + pubkey: + '0xaf30664280a679cf3205b034dd825f297881bd1e5e4ff7003048dd54fd58dd5983f2e7867a83d27129e84ab97c2ff977', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xa5af3844a980f76e9d02eb0e22025dd60723056138e2e30a120ce6c00d18d21dfb641a5fe314d85f7a0a8e90c3f51b430eef2935c73f3e8814f149e79b9cd71e494c0a8c2100a871e3cd7472446fbaf217a04cb1ead459bd8d78b0b5d7bcd3b1', + depositDataRoot: + '0xde1aad0e6148a1efe85763a24cd90254beb78814dcd736acd77d130207d83f25', + }, + { + pubkey: + '0xa4f3745b1bafb0805c12c227010688956598c5c5178778de34ba400b2fa276fcdecf2fc4179300c500e047e8e02d8d41', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xa772ad562fccda797c80f51189eab3ef1363387f5b4e285b49b42720becb6d13726a7d4287035dded03416cc346056b713eac3664d72e4a5ebe333161684c38882e389d798ba7b8cdbbd1fe84bacbc95952f9f7a0252c480d3db0c4a38177396', + depositDataRoot: + '0xa1ab0ac4aafee4d60fefa44bcbcbc47628159dd0424fcfcec9b517f2be67fd28', + }, + { + pubkey: + '0xa24e76f2e77d5bc884e34c4bc866db378a777e104d8b2ee1243e8f4c9c09d97df784fd317bb3448d1d44b30482c2cc4f', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x8c247b51a8bf443236616ebf01631a50800cd470eb556f97d95ab6c3a0a8d0161eaa049ad0562b9291b84f8c21f651810d756bfbc187a59edaa6898fea39996c778079d7c9188d14e82c6d164b31fe28ade18aac8b1d8798276ea23ea2696bcd', + depositDataRoot: + '0xba84eb151ad0a0dc23acb2c6b845e5a2e8c1011d582103121bd4281c5017eb8b', + }, + { + pubkey: + '0x84aa94f113104113b7b02732cef95911bdcf7bef99010c272f3f605310b11fba01a7305c7e7ba11fc8f87a2f44e1ac31', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x812480b17cdeaf305edc72ff5dcb13d1a9d2d750f052348da9e760f0d89c7a0b7084c47bb21ee921dcea1912c47ac2551563fbfedca768389d4ca3a8b3fb88516b038205045ca29658b7e983f8ebb3169c31f7cb10fe54e7282f00cd7953bb6c', + depositDataRoot: + '0xc4e8504874a426e85d5e4063bea82534e8cfe9aaf0ccebf61eac1099ca76926e', + }, + { + pubkey: + '0x928c6475e450b8b8d70cae68189229bf35bf5c7b0ac72a72eaa1657f82fd5dc9adbdf5b060f41575aa9698976e16ec9e', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xa897534b779899129579aacd0e787ac8118c724cc92f3ae7723616a859bcfe8d70353c74d2e65377d1fffa06205879fb0860f5d29c6beea742867f09c83359a934dec704aae142bbc77dafda164978782a99195312a7e1991904ccd4b9ed5de6', + depositDataRoot: + '0x3d7eee2804b993b96e875abbdacfbcfae91e3d0402259fc28a608b07654c68e4', + }, + { + pubkey: + '0x867bfa6fee3a93fed71b7ff065e465d33f332502b083899603ba7ee38977e91037b6efd08fe0bed0ee19c9391eacc0c5', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x99ddbffeaf6d317b600698da67e1bc9903cc6c9c3813c633d03052ce4d248b63841eb526add836e95aa95f62fc0a5d170ab14717f9b3504a6fd273fa046b9ea791c08e10148a711150f606b4777dceac00f2973c70749be91b50aee4ae71533a', + depositDataRoot: + '0xfc8b953f60c8f46afef6ed40c06dbffbe4808300de5fb7738ccce2df9adeb832', + }, + { + pubkey: + '0xb996325d00142b292d7496ab394b9daf4a639b7c5328f13a1a806c94510839694ca2868843fc9afe4f2830111c781458', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xa6f70902d8efa72dddb767314fc4359765a2cd7eb3785c39d2f5de37b58ed1cd3fe9e9347f38c0978c72cc4342192ee202153c841137845aa64f09a32e2b55154f7bf790423554df697c7115e638354cfb8d0747e1ef94b976ca1b4414335333', + depositDataRoot: + '0x3e19cfad789fb293b412ad27704f709d92437d9d7b26174e02d96658d5c12a2e', + }, + { + pubkey: + '0x8c3c12979805edd47672325d71abe668f41af144add0207184d662762f2dd02b2081cf373b7dd805e4ed2167e456a44c', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x83725eb631b8e4aedb19b5f933ed77a1c7df16f6bfc81914ca5b150c5d788e720514898445a0dbb114a779a0cb2dcb1c0c388400a2f908edf2fa7d9783d1524445b9eb40a211d522698dbf1b808aaae55a4a0943566c7662b6f1515e1ce02e3d', + depositDataRoot: + '0x84db6f103e56f587275b602faa0716e511981f6dc398a2737ba08aad8574c578', + }, + { + pubkey: + '0xb0843a4c9c43fdc96b6c819b6a9ddc16a9175ab405278381c20830b62409b14e61c42fd07855fca886b4b51142a5b649', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x9290077b1f20b1bfc25920ad9b9d83c673366efb744cde3d09005c5e0ad6955b8e89f91ca3da929cc27923a02f34c44e0ce3974155a5709ba0071d03b97173a5f150ab2726cee2ab0240f6c1f68338bed1d0e2a08a1bcc9f4bf78c7d25e9dcb2', + depositDataRoot: + '0x2c85b3df635819ad21fd8297b6ad453c729f3f4011d0d6444c70237f57fbf5e6', + }, + { + pubkey: + '0x90d4d4d5b3180c14305a07a7ed8e418a1a1a6169de93a11b38011b80735ce6546e33825ca2aaf6d7fde36c30a47db28b', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x9451f9cf00ebe8e705dcc83d86c269a1510037c44fa80bcf526a6541143fb5d858487445397e026e6184987ef9c801e10fcdf32f316af34f9581a54d6207a7dd47349ac73d224e0c4dc9302b0f5793fc26e29d2c0cfbec4c9f6edc02654a30f4', + depositDataRoot: + '0x5e3fffcabfb9f97388bc47f81df6d1850080867f616d6a3722f15c469860e33e', + }, + { + pubkey: + '0x98e1f977d2261ddabc3d281627f8b7f36b973b0d66ac9723c243da6cdc2c408d53cba8a6b8dfe298a5d396d19596ecd7', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x98c480eb2508dced8e41b68c7427d6ccae3481e79ab7f54e267faa1f10637978f810b84c879362dd7ec5cac9920c857c123cf09092ca9960c15e52b87fc38e5249f61b7b7b998d87beb8569f580e131842b1f531a811e068db06593d5e534a9e', + depositDataRoot: + '0xe859beb3ac42a3caa9fc4f4a75aff4698554309f32ea0a44284a7d0284dabd76', + }, + { + pubkey: + '0x9348651b6582f78775be8afa4e94ee564089a1da640e5347060f6a4b54e30ef8c3c7b024a51e2d9b8c8a557abf724640', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xa8992f24c3e349714ff0211a966ed07f9bf81803d6a6b5dc372c15d5bf55fe913c7e78c1ade9c40dd45baa65906bd42f087656b83f490a0f50d43e95a62d7cb04c6b2df4e4e31886a0d8408bf72764c397221e2c771a3e150db52738c67893f9', + depositDataRoot: + '0xd376c75c38641b4c40bf8cda170ea9b0c6f7bc653375804ebc23802388ac93ac', + }, + { + pubkey: + '0x80d88b1861724839b0f88d27205c1d58705855726d6b46a2cd4b7b2f4dc1e3293285681353c87b6ebfa08a3dc284e218', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xa53106415008c640232b99f4c5c21acd9c83695b73a5f6c6a96abf16bce3d0b675b94c9dee3c2c83dc15002c856150da093c2f4bbe904c290c26b9591bf116f17b93a65fe621898d1a8ef7267070059660e8561fe2e98ec8b03974f872ec14cd', + depositDataRoot: + '0xe84a2020d96aa25bc32eb3880ba4ec961d42b2c6e0cbebe6a199df87ed28c06f', + }, + { + pubkey: + '0xb9a72268e4a40088e8d86f591420b0fe898c0c9c0e9da2e2dab94511ebd03ae665e7b91e450183393f1b1d085939aeac', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xb44c3597cfb1164941176e18ee22719b030fa0ce7983d9d67342180f93103f34bd4e39349cde131d950ca670c9010fb00179f71d797211063a9ddf0863aa3533aca92004dbd276d0bd04d0f169d04a351e5abd141c6bbcaae379db3446a2715c', + depositDataRoot: + '0x8f5b2d6989564ff8698d946d8071939de9f27267f99f1dc33213b57d25721e14', + }, + { + pubkey: + '0x97a8972ec398ca98a239744df60dcc3696ad5baf0f71df51c1994e37d4e3853e7ea54895d95503e773c4b1a6588c7d9c', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x81aea62e0778ad25da5fcdcfe084cb60c1f64aac68467db6869a0694356307bb7c046c42fcfb73de4eba52dea6a184180218db535b389aa548780c7d2dbff357f8f70d6fa9b7b08e3d445910bbf87307c4b40638e9fad8275ec86ee4b2d005bf', + depositDataRoot: + '0xfc73c98d151beaaa70457f76ab515d8ae213f57aaabe6dbfd2fcf642807a0ce8', + }, + { + pubkey: + '0x85f56d7ccdca63a3b30118d49314d3adef4001f3730bbb2454863b0f072c6549872c47978f89bd2c1bc5ac5e0843a495', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x83a7aae322e41bcb5aa9dffe8c8ef7ade3760c3af657ab7d780b4e998981b66f311c8e42f0ff9c3c9943d5f9184d95dd0475819100704d70a3f126830b89170680dfc353e24b0714438cbe3db42e19845a4ddff3f050f9f35b181f2405b42721', + depositDataRoot: + '0x57394d0d6e84ff8c2f85eb4392bda59faa4d4d4a2ef3d2aa42c2034da728baa3', + }, + { + pubkey: + '0xb977442770e725d38d62ebf5a179c3f3a35a3c97318b127b85ca5a7c0eb375796ee94499f50fae6deb05bc203f877648', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x9658daf44cbf9ed63293ac2dbc8904df40c4604816bf6125bd8f548a90871264c355908878b7e4ddb8472e8de07e9cfd11623a3a857a417b7c7d76d3b23b7e02ab335add818db9244e4fa6ed1ba9a9a5e0d1e141ddc36641476df79c27591f6d', + depositDataRoot: + '0xd6d7dce52b979ca8d520b8d7ba379071736d37530a782d03e127f31241cbffa2', + }, + { + pubkey: + '0xa98ad562baf8c5b358fffc5a38ac2a1c31a40ad1fdefcb1b855481e5fd24d4796b5097165724e3ddec6db057104d68fc', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x903ff98eefda4f22e3477fd801d6af87e67e0b36629edddf88b6988d27f7629ac44a75e2bf9132ddb0c45a8ecd1f68dc000d9959d88ee9592a8d72797610d3dd11016bc4833c8d9db19bc6e806e116547741dcb8445d6580eb1530e4d837af75', + depositDataRoot: + '0x4e664e7af54a16170b003f702c1c4e1f530b3de02f5c1c5413a66b62e5a41015', + }, + { + pubkey: + '0x9680290d285945351569b9e80c1c517e6a21dca20cd890c762562b5376d282a29ae5db15c6100f406a9829fae0103ff2', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x834009e22c4684978d36762b3aa3873e447de33530ec73e8244307cc60aab8bd2ba61f8ae69c55963dc6642c66fa6a6d1159d119c377d8021b25bd65fa351b3cd13b0bca1453fac94476ab419cfff02f9fcc49a95a12e98276611ae1075f0165', + depositDataRoot: + '0xf0d60e0a87abe9a55908c6ce95d450430ac120e32d470c4d902d2aacae30fa41', + }, + { + pubkey: + '0x90a6dc52c9be3ea6c4760ce1bd8852924bfb2a16a7458aac1574868e8bf6262ead93f7bd5abc0c28eb21276007871dc4', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xa8c274bc21a1df15c32f7fbdc19776b9a6541358cc36cdb044f4e9ac8e2bcd0b45479714b9f6affbdb4e1468eeacaec203c4b30daf4d8f78713a3fc5fca15b30b81e301432edba90a9053a52136a26459ab98b384a5953fe22c25eb6acbbf52b', + depositDataRoot: + '0x8002a17ca41644cc57c8d7583468366ee44abaeae8aed37e007a6188034aa8ff', + }, + { + pubkey: + '0xb0279fc59acd376123f9a4de9330ccc1c330ae820d5ac0d17443f98617e86963bb02fc78f60c6deb4dda808c52e4d513', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x82ee29eb29f5c19ecf0dd0cebf308a9ad1b1a70aa76007875041ec89e3cd2fd6b3bc457f3554806e5fd135452fa537b915c0ce7ea9b614e10c2b05ae9c0de1ed44bb274a25814e5eaea3314e0e24fd869963e48ba32873c0827fe452853b418d', + depositDataRoot: + '0x6301918a55b3e7423e785a50c984359b2138ba1cbfb5a4b3afa2746421f27c1a', + }, + { + pubkey: + '0x8283a2a3fac680fff115303eddc823edf42766050ecbfe3bfa5d8e7ef2759692c85b63becae97966839d407f0df2658b', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xac8340e401493fac6c3c871d0bbccb3133843d0d3c58458073c0ac894f16d5034b0e507eeeab52f61e39b158c2d97e9c0f1a0dd920726a366524601712bf7f54d193ba0e569c8c4bf5dd3d849554ad15f5005a9049579dc157b37b360410e9e1', + depositDataRoot: + '0x12f303d5e7e147e42dd8c9b2d44cffdae26db58f071dce41b6de8f43b0ef8679', + }, + { + pubkey: + '0x93ff1812acac88e8795ed99aec46171efee197ca4af0025364741a194c0d6a0f0bb7d01810b5f7a5c77f7be8f59bcef4', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xb73d5e94e047c0a2150b8a8a04807320b35edb2bf11d8b84de60260f6f988414ea0a05fece79c557cd16274107ea4924123c47e0b7955c2faf375ed1bcab54a4a003bdec526ae19467823e5977e313d19ad5952953dce045d3087af3cf907265', + depositDataRoot: + '0x14ab450ab5452b812e57ca7b2b45a50447b5d20a5b0f541bc991c31a2ec5c64d', + }, + { + pubkey: + '0xb977357369b95d9f7f364cf0236c4389a478a1e86592ffff54f6afd6e579798457a3c9c4aff64296a0b034cf2d9b264e', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x8403452eaba03118156e4a9010e5e6592752c93499e2c93367f66f62055485e0429c3233db251656f5c2eed0c46db36701f37ca905441e2e5a76e96a92340d8e724f8e11a235cf3cd435719d1e4036fe6a67bf8626a1402fb32bcf8723b8e66a', + depositDataRoot: + '0xc7cc1d35f029795df31f4c8071eb841d7e548be0963ab00f26dcd47f31d8787d', + }, + { + pubkey: + '0xa8bed576dcb4c4019ab975826bfee4590056aa61a868134bd51458c5d74324633709e5432fe193d3e1ee0405e0a645bc', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x9845e03c7f2e608f085056731db11eaf8cc2c05c57ed9e9ffaf6c26b3f0ca286dd69bc0a9b3468b8554ae9e4b6d5c67f00b1ca25398af88a5f6cf2994c839a3d8fe53dfd11af45748305a3a91398772fb5eb296ab2e87da2328e593d0b319bbb', + depositDataRoot: + '0xabe0081caeccdbab39eb1a60298f06adaa5f9e5519606ee6156a73b516ba8062', + }, + { + pubkey: + '0x8f97d11db5658a2c13ab427ab75b7d080b7199b978d1df4fa8efe88fa58153bb873e85de306877df5f32eada58faa345', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xa10127f0e14159b2ad5c685c6461272a6e720fc2abe45d15d3b01ca2aeef2ee44e932fe6d1473607808dd028739432c0006b2ec50f13a0f433273b6f08d5759d44d8277aad9663fe80f373630b6c487333f5a57cd7b0310dd858f05de32d8079', + depositDataRoot: + '0xb8010334d99364ce959077fd143be39c7e9e7a26cae42c983ab9f5122f3dd67c', + }, + { + pubkey: + '0xa51521ecc49a47f8124b9514bff1108a412bcb91fb68d665b4e99fe1021e8d5c7b9ae9c12f7053944384b593868c6946', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x877682114673b230fedcc758fc0a2388b3c1e118ab41d906fad0fcc4bd74b145f1f19defe32f6fac9bfc54491ebf0622091587dc0d2f2f3b6ff95a3c2e060f3a66385b9c1dee7af4950c5453f0f4d54e8c87de6ceb828bb1f90a5aac20af9f3b', + depositDataRoot: + '0x65804da937127af18df81788d7736e7bb7a53b387751615665307812bd55d59e', + }, + { + pubkey: + '0x9411b3579efdec6fe865d6d78dc564063a81a6c85b39cd5f0141fed8c590081d5538afe9eb2e29d725974397feb98bb4', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x994931c679fd0542cd0d8cc6f391e1f88830f365f2756c55888254b94be3fa23dfed4d2c0b38681dcb3603f5245462f30f0b69168999a5c32faed2f4b2e44f886030f643bd3e32e6f4e217477f640d90e8cc79e48dcbb6111276b28c73c41d71', + depositDataRoot: + '0x2cbe6a69bbd4606588a707ff0599d4001e15da5d79c22800ea29cc60b1a0f230', + }, + { + pubkey: + '0x8ae257ec2f4e1cc3ec5b7160f09f294c5b78c14b2dcfca5e905c25ad1ddaa0071f4ed0df0f96889ca34da7308d2335d7', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x86effb8be7ba32715bd68cddd5f4554c1446898f15886ed1dc6e413aeb15356fc0d8649f9f1aa5a0b6475efaf23fa7450b883118d536712addc34c5fe2b4e4545f6c14a662ae1cd13ab9c53631aed38ef48e9fd9e3e232c0e06b00ca9dd6410e', + depositDataRoot: + '0x12d45588d5b0f20cc34f94e2bbf4af748813cd4f8b6fc86b0d2596e55a7a11e0', + }, + { + pubkey: + '0xaf2d528d7f12e180334658baf63272725f2012ce5476990bc82eced85ecbe89e01e7ee47e02cb8db9d16c48c5fda6b69', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xa596a04c4d1bc721e6cbbfcf68488580162a644ce0a57c195560137fc4aa17eeca7aecc296843bd8e636aa99d84f0d0a02ca31f0f8e5d57c8373ad6c0b76180b82d27ac208ec75957da52c87fbb17cebf20aec02ff7caf383a6cb37e9f4911b7', + depositDataRoot: + '0x7bb13dccffb958b107ef5a8e56f20e3d4d91e35505e247b3fdc3a31f44dcc7a1', + }, + { + pubkey: + '0xa82295a10363818d8360d014f6cc0d1a6817ad9689dabb5d344418ae7487087c95abde42ec9ae5d91b869cc8d3c97d21', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x988ac3c6713e78b497d6fea053cbff226d7df1f03f8455aceb43cbcd78b734b15cef128b23c1881db3f0c12fa8c2c9a6121e4d336ed2f148ebf918fac7cd8dacb2e9db94252b7c373586e6c480fc854218066a210e836625d27f3bd1b5803920', + depositDataRoot: + '0xfe00d823213e9a456ba8afd5c487101e1387def0b70502d54dd1695376f07e51', + }, + { + pubkey: + '0xa4bbef25dd5aa10d5663fd7dde738f50c2dd026ab2b52e28a5390af11e0baeab8db9e64017d13be84478b4a9e71be99d', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xac8b7f0b2e74f5a6d0c1c27d88b45496560372d5fc1635f503a53d62a44d261c346af0bdad1567c520161d45fb0a33660fb4aa8a6659a0a085b45460f3220f623ab301ab32a2a6dffd191423f2a3ed8a66308eade87e68ffa8b520d1b4c5b271', + depositDataRoot: + '0xe6c8838960eb553b5ca1a819ff8e093b0ec05f2fa7fa43928833a9b8d02784c5', + }, + { + pubkey: + '0x8245a537e592e1e1d01686c5bfaa730327b84e827a18b891db37437f1c1c6e6e27e5bfd3703e00fe4f4e9ff06e5d9cfe', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x8f5928ffe56f11260ea1411ad025de7652aa8d89a7b164b1a8f66bd4f84b2b50cf078921dc0ecdc559994297bf3a250a19b1adfd8745381e641c3c262181434ecd3c4f073810d509662959f2793900d364e2375022b61ea58ed9d19a2f3479d2', + depositDataRoot: + '0x998cef58a606d1e088a73a977c2b746b557ebdab2e1da2be227200583164d23c', + }, + { + pubkey: + '0xafa99b5577d57bf0a0b955a621b017b60593bbcd17e40a70b90d3009a944c405c2b199928642dd6b0541c23df5a09977', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xb21d43931e79a4efb850433f66b1db56610cca17ef05ee4f65a26f2d609042c04c31bd1be37ea75d5fe0a8ee7e5ed09308cee1bcd9a5341f2a3a46d618ba9e47bb56525f4aad955f91d38a45c9b443f3cb282288e3b958b5617dcc3282bb8721', + depositDataRoot: + '0x40adae5add2557c8ed4d0163ba017dd27baedcc2220a6eef8e11eb766775022a', + }, + { + pubkey: + '0x8548f2e2f1b2fdf6b1033b5bf6bd9fa7c2017de000c5f85d0103e16133f3f38e194f303293933123d0ba4fe9744cce92', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x8ec2fba70324d991efc784ee2082bf4a4ec271525927435ed8b0674544628b3fecdd0f46069d69a3055438f4b36f49da0c5537eff0a0c076db003e00fde1198ad527d2d456c1a9443b1a132bf6541a6bea481cd8f2590373ee573996197c4283', + depositDataRoot: + '0x5cdfe6f4099fdf6d12d7202dc930dfdec9d2efccef076ac42b8a0e9f49ccee65', + }, + { + pubkey: + '0x8c74c9742f8c464a8469cb3802b354c05622090bc84272b10be268baaf3762c8d6fa607a6cefc8d3d5f304750439d968', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x803e030f80c219f47cb1d79729b107bd81bf67a50fe146dafaaeb02506fc5a3e5b74f295836dbcc500a79cf26c9f1f521590627b511c915020408100280470323a127f9bd3662eb000e23ef176454b55d1261879b04ba94b6a640e24e054a2f6', + depositDataRoot: + '0x4aabf0c232c3104b2f1627cd5f8e4566dbd87f5e2a5af096bb1ef3a4036145db', + }, + { + pubkey: + '0x82029b3a16aed0b1b58c37f2252b4d7415614cd1ee444f4b9a9b1b1e7a4d8bd2a019414b66d46b63b625f7f5c96d4256', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x854cb318106f29b49f4cced38d7848e460cf0a992ffb5438d03d23c01625c63c45b224d74d79edb9bc1d89402a1266430f6833f30985067cf203158fdc296a6a0598fa8965c3e7bd28463f2418a583de1ec81d960e8d5c568fb88ba189e9570f', + depositDataRoot: + '0x5821fc19effb5a536be7399f21a7ff057a1497341a3db4f11dec76f0bc28378a', + }, + { + pubkey: + '0x8b1ba3b72dcefef5a18082e127dbf5297f971d12f01dc8a58bfb2296826b40fb2687b8acbfc8c3d893e9b1a1f04ad323', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xa2b4349fe7e7aec14f697ba82a62a4c47b6c65b1a4a8dd476a5296aad59787f10083608cf3a6deb70dd8b6d5abb286fe0864b26b3347ad36484dbb7986d763ba992397f70276dd37ea7b1cc738eb799c5892c6c233c9f4431a00520072826a43', + depositDataRoot: + '0x4464a121c10bdb13c75392e166c3f1a0f5f640d90d8f3df26b2d3333b00fa580', + }, + { + pubkey: + '0x856be8761baaae096b0473eddc93e1e99910bf0c1b850d22f30881dafbf7ae74eebf6dc7cc6d4f70f01bf00e202475fa', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x912365d4aed2bddcfc533d9d9587606f2cac7e1c48bac8a9eafcbe218eb1f09a7fc35d17fb3ed64eeec4d2e4c022a93801bbaadfcbae52b859ff2d032577b98bb98c7d374092f706e7b2f8399616932b16cb9ab7bb43d8df585fe1fe7a1c0124', + depositDataRoot: + '0x0ac97ced8ecc2237fd301e69894feeb85de71da08d40e21ee31529d4d9d7835b', + }, + { + pubkey: + '0x8794f2a3ccf056ac37e00cb840c25c1b60416fbf36ff7618d76403c6975096baeeb8ce3899f38bf605e747e30de7aab4', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xabbbfe9b867b51f38f62ee73595d3b33fae281d064e5a3af9b9a4ee47c33d413e328cd3f43181de5a60a6c69dde312f519db98d865cd52e942207e7de040b9db858161f85b33d57732a8abb540b9073ca409cb4a52e5b50634e9e5e445ef916a', + depositDataRoot: + '0xf69b17a90b44ec1bc5329ea51d6b59f879d3b97dbbb5dbb4371e3d24704c9fe5', + }, + { + pubkey: + '0xa0efa257a4181b195440dc3a1a12b734d32fe7a5a9bd2530fc06d438f56742cb3b979d1b181a674052abc8b16ec0caf6', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x8c6b16f8ff0827524fe288ab9a26b9a93bb693db8783420d03b4b5ca569a12cde66ef7e5879a84b4d374af940a5fe0df1379c09fedaa7a00229edfdc3d7a4ccf2aa7c1a80fa273782854b4303e3bd21fe2daa97f37bf97db6e2328b47b4cbbea', + depositDataRoot: + '0x1ae1232267d1fe813ff6a1d551e53386ba8c68d8107982a5e987af9609750fc6', + }, + { + pubkey: + '0x883ca1959878c4fb8ec57d91e8c4620973374411c5a2aa8071ebcc29f9310a5840768cb2efae5382ab82ac7d109f13b9', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xa05c551e30ad904cfd49b78fe4e8609123f6161c4b9738c2c606ebc111594ff569f33e3849684124dbc4e94ea9b104df020ddd885786b482487619bde3c51d55f376e8a77f17b9157a7bba4c7f5098746d615e207e7963b80bf49025eff07ed5', + depositDataRoot: + '0x876f11b5e5965237a8359ea937806e80360fae3b295b15bb997b9194701a22ea', + }, + { + pubkey: + '0xb6397284a5218013fe98172d27be3723d247d6c9f7f117cc250900fe560f7b5c20311c80264ceaac415c8f254c4f40dc', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x83f118e22e2b042eb83e91400eb624bdc85936c7c25dbebd82f20b98a5597a1a5d391e3dd71f9bd0d90bcb456ddfc62a064bbe65f29e18e6ae72535e7130c6878d420f8611e41c286e0454c2c4a4c0fc57b0909b435496934f25c336a9dea5e8', + depositDataRoot: + '0xe846507ab8b2a1f3233d0197576234ff447eb3d75e60a0911f51c403b9350260', + }, + { + pubkey: + '0x9107618fb9ef426c532b27bbc7f61cc8f7c36b4de0a34f18a116eed1a15ce159b11fdc5deaa7092a66b7debc029883a0', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x9032d242f173f1bf1428bfa34dfc017e32b6a8b085f628acba9d91c0035115b5c54d6663b433880682b93da263accc6212ed2c999e3471c63848199366c5facf026a82920aefa4b3b45503eaf09ad99fd2a4c51f7fc074864f2ea3655994721b', + depositDataRoot: + '0xae47feb399f1c4dcd580c72577c971cbb0cb4cbfbfb35c29d0e31736fcdd52c9', + }, + { + pubkey: + '0x97f4675c8b33872d70e9189f89aacbfc6a2a2b0033f2b1a4d02b422fe9dd4dd01fdd16efb391e03763b69c69b91e41bb', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x83f95fda2e90ef217bbda7c1125247357d7bcd08a2052f22e25e8ace4f3305f4385b466f6abffba68afa01e64ae1342712f64a5786c9e0d89f00db7aef8b666ce9a2583a188b352bfaf375bdfeb6af0d0b5f363fb118590972889e223666eb19', + depositDataRoot: + '0x996a78cc473784011ff167bf7c4a831b52923e9b4144361e87d91bf07d075696', + }, + { + pubkey: + '0x94c9d809a78def0a7542f995a2e30915f6f09576b1c99a503eac1a40f31266994ea331bee6e9e787172852282b24cf99', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x835411a188ab9be5d61375879cb191aaf9e158814e9f0ec8c8d32068f3cba678b0d842f010a1712a2e96836480adbf4918e5fd6c3f080dc3a86318f6c308d12636c7fdc3fffbdfb95812728af593f382060ea89276facd840c615f47a3fa2bd2', + depositDataRoot: + '0x36d3bc7d9ab0f7aee133e93f074925bd23bb23444771b953d230e893af487865', + }, + { + pubkey: + '0x881466c4ede19c0cd04b57d735d19143edf6141f67f8422478a161a3aaf1b9294f53ff2931184bb005d6ffef723e55c4', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x85a8959210b3126ec116d751113725eaaf74f2d611041facfccdc67ac92b8f1c666a649d717271da8fded95fb9b4230801d450a8cb087c25928e3936709bcdccf1f36916df2ca9b342ad9734480f6cb7309e8f26dd489bbd6139dfdd965c2c1e', + depositDataRoot: + '0xcf55c58cd8963413e9a10243a2514fb77dee565c01ed1acd4d05e7bd8ab850a9', + }, + { + pubkey: + '0x958937c1059860821de619e6ee61a647ff33523d670806ab1aec8edfeb13faca944a612ebfe0a359fdc596d70e0b2516', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x8041f8a26e76cbac8e3d53330968a80bca2cf2b3e05aac369a5819b34a9c1ddd041f57667655dc1660a8f79c53c2fe80166cc4859ab783b81705d43306699dce3b3bb997b1b5bcd09c3900057b38b945036f292976a607001125c805d1215bc3', + depositDataRoot: + '0xb40f33b765d67893ac8149caf5a15ff804c17ef4dfca3ce298030394080e7e18', + }, + { + pubkey: + '0x801f5200ccd592053ba6e8fc442309c7bf5d5a7c89b4ae0813fdd0d75e30939c77c108445cfc50598fd9d0eb29207a56', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xb5decddd9dddacea83e74f17db3bd35695d843019de63c9b30da4d95fc235fe90ffb1d50eaa980d8abcb96b6862c7855084ac22798537b44ad8610750c5fd145e9fb9b6c9d621cc93d8c83aa0d7643aecf58b6ea930df2b4be17072b0204f05f', + depositDataRoot: + '0x292f86f3ff84574a016f7c61003be70648865df6c1c6d929047517eab13c2661', + }, + { + pubkey: + '0xb4976ac8f9755cb85cdfd791f636511bd87244e5c93afcb7b69b75b888ea767910e5a4522b5a3aa81a2da51ba166aefb', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xb063a33cdd922d8da9279c27ac6914c24ed289f882cdba0595dc06be44c9acfad657f9e6b24b7e4986f415cad38883220b39d6670cdb7c1aff89f68d2cc3209c5b4dc929ecacb2484bd5c725863752a30f9f12a43f9c3ac5c4b01108323a6501', + depositDataRoot: + '0xfd575b934098cf01c7f16b7b8790d63af68ff0e94bc85e17774d3aed62656864', + }, + { + pubkey: + '0xb997141bd45fa4edc4246d6facebe8608ca4df46d1cb095ee09278ce4b1ce55e3f04a2d8fe8dcdb85416474dabfea915', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x84cd71555c729d91f2c2c241ef6e0a1c38683b10ff811f49b0fb9cfec31796c96f50eb4a585f95f6dccf7990d04f758a05493eb94e11c85964b0cdb57986636ee6405bece464a8d6e790de9af1e3bd84df784c2a742aaca37a725e6929bdab22', + depositDataRoot: + '0xdd62ae2901dfb98fbc7a18eedd5d9e6e3d40df52094d65cafdd9fc3df0f94048', + }, + { + pubkey: + '0xa5fadae6fae0d2eb3709e18741c4804acaafe6f685c49e598d2be523381fda8678ebdcf905417e32e007bb36bdfeab68', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x865423fb473e67849cd0d439886ea4be2236c596051c7b96d0b0f921d459f066b1d4b089754f4fdf72f0c4e6b83c49ab0d6e515c7a729c355ac881c237bf11ed1853d9ff45cb57c652b928fc7260b197a81b5d0875aef73f2a133bcdee1fd4f9', + depositDataRoot: + '0xfaa6aca095138a8fa1449bbc9cc2b0aba95a0a3d9644c262972a82f8d41e5ef4', + }, + { + pubkey: + '0xae8c6be869d23bf14a0f85e28ba3b94fed089bc85f83cf2cd87280ba8defa9bf2ae9bea8d8ff8bb96133b9529986960d', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0xadd9f35acf6996a2ea4f660539620bacb5930522be05a3c70e6805bffbf4cc5a59e3aa0b961c99b1f644e1d7f187c25114b6299cc557b28ebc2dd82f348b791d7669fbfcf1763e74a91d4771a55c79d28069b88453d0143d4297ff0cb0cc7224', + depositDataRoot: + '0x6a29310647900458320294dc8174009c98e0af148070743bd9bcb425936b8097', + }, + { + pubkey: + '0xb4338229a52cc05475f0c286a313b37e1ab9ed83c774d3daceaa6c63f815062e8d31bf2b9593999ce168b0a544807825', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x93147471ecdd8f41b7c9c8070858698a8340c90582fb884bfed3cae5d3e09cf2b3755d455a13ac374b664ba183b181440dcb3f23c70c8ebd3247cac14b2fe8afff9d8fcee59f4b1988a189c502904d0f81db0068d37c5a347b4096ee8bd71da7', + depositDataRoot: + '0xe09b81f2a711303bdc0a8da62cbb54858d2a707b0a6879b944d067d9fc50c2a5', + }, + { + pubkey: + '0xa0da8aff80f7cb0ce0b5e0ca03edc292d89588624c4d62862bc3f1fa33f46d84071b7ff67266c8608d67699020e8b0bf', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x869a8831db5591eb49a0c0215f56231afcc141c54165c6375f68ed2d19fae96a2b0d2208c938a02c7e2148c4d590095000a5f8a00ed19732e3c4aaadefba5e55d06ece2609616bf8ec4fef914db47a360effd7a313a581e7b6bb14db7a93b82d', + depositDataRoot: + '0xe338702fdf04d583b23d94f70ff23146caa7d2527debcf3e7bc70f00e3381e87', + }, + { + pubkey: + '0x8498a47d75b9c4a37f8867496f37655465f5fa687cf217382fe8f6c118d3265f3f512deca2629b2286b8ea01cacae30a', + withdrawalCredentials: + '0x0100000000000000000000008ead0e8fec8319fd62c8508c71a90296efd4f042', + signature: + '0x8af164af59caa4ced3eeaf0c5e43f20011ebef30da4ae16be6bf0484e0881f3d835f26ba353e017ece16db3e4e24d4f11605e0d7b1ec513a33298e56f608af0e21636933a42f84d09a503793bac4762a2b69ed67d474c28adfe2b023c830ae5d', + depositDataRoot: + '0xce19f076205d248e29bf11b450f8c02305d87109e5be64e056fba8366f38e6de', + }, +]; + +export function calculateValidatorsAccumulator( + validatorsPubkeys: Uint8Array[], + eth1DepositIndexes: Uint8Array[], +): string { + const leaves = validatorsPubkeys.map((pubkey, i) => { + const validatorPubkey = bytesToHex(pubkey).padStart(96, '0'); + const eth1DepositIndex = bytesToHex(eth1DepositIndexes[i]).padStart(16, '0'); + + return sha256('0x' + formatHex(validatorPubkey) + formatHex(eth1DepositIndex)); + }); + + return hashTreeRoot(leaves, 32); +} + +describe.only('ValidatorsAccumulator tests', async function () { + let blc: Contract; + let depositContract: Contract; + let pubkeys: Uint8Array[] = []; + let eth1DepositIndexes: Uint8Array[] = []; + + beforeEach(async function () { + const [signer] = await ethers.getSigners(); + + depositContract = new Contract( + '0x00000000219ab540356cBB839Cbe05303d7705Fa', + depositContractAbi, + signer, + ); + + const contractFactory = await ethers.getContractFactory('ValidatorsAccumulator'); + blc = await contractFactory.deploy('0x00000000219ab540356cBB839Cbe05303d7705Fa'); + }); + + async function deposit(depositItem) { + console.log('Deposit', depositItem); + await ( + await blc.deposit( + depositItem.pubkey, + depositItem.withdrawalCredentials, + depositItem.signature, + depositItem.depositDataRoot, + { value: ethers.utils.parseEther('32').toString() }, + ) + ).wait(); + + const pubkey = hexToBytes(depositItem.pubkey); + const eth1DepositIndex = await depositContract.get_deposit_count(); + + pubkeys.push(pubkey); + eth1DepositIndexes.push(hexToBytes(eth1DepositIndex)); + } + + it('Deposit', async function () { + for (const depositItem of depositItems) { + await deposit(depositItem); + expect(await blc.get_validators_accumulator()).to.equal( + calculateValidatorsAccumulator(pubkeys, eth1DepositIndexes), + ); + } + }); +}); diff --git a/libs/typescript/ts-utils/ssz-utils.ts b/libs/typescript/ts-utils/ssz-utils.ts index 0f37f1d00..dcc684615 100644 --- a/libs/typescript/ts-utils/ssz-utils.ts +++ b/libs/typescript/ts-utils/ssz-utils.ts @@ -25,8 +25,28 @@ export function verifyMerkleProof( return formatHex(hash) === formatHex(hashTreeRoot); } -export function hashTreeRoot(_leaves: string[]) { - const leaves = [..._leaves]; +function nearestUpperPowerOfTwo(num) { + let power = Math.ceil(Math.log2(num)); + return Math.pow(2, power); +} + +export function hashTreeRoot(_leaves: string[], treeDepth: number): string { + const zero_hashes: string[] = []; + + zero_hashes[0] = '0x' + '0'.repeat(64); + + for (let height = 0; height < treeDepth - 1; height++) { + zero_hashes[height + 1] = sha256( + '0x' + formatHex(zero_hashes[height]) + formatHex(zero_hashes[height]), + ); + } + + const leavesLength = _leaves.length; + const treeLeaves = nearestUpperPowerOfTwo(leavesLength); + const leaves = [ + ..._leaves, + ...Array(treeLeaves - leavesLength).fill('0x' + '0'.repeat(64)), + ]; const UPPER_SIZE = leaves.length; let n = 2; @@ -41,7 +61,15 @@ export function hashTreeRoot(_leaves: string[]) { n *= 2; } - return leaves[0]; + let subtreeRoot = leaves[0]; + + for (let i = Math.log2(treeLeaves); i < treeDepth; i++) { + subtreeRoot = sha256( + '0x' + formatHex(subtreeRoot) + formatHex(zero_hashes[i]), + ); + } + + return subtreeRoot; } export async function jsonToSerializedBase64(