From f3a5386281a1bb907eb8cffa73b1dff5c1e5b665 Mon Sep 17 00:00:00 2001 From: Angelo Capossele Date: Thu, 3 Oct 2024 20:38:03 +0100 Subject: [PATCH 1/5] WEB3-165: Add `JournalSeal` struct to encode `ffi` `prove` output (#278) This PR fixes an Abu encoding/decoding issue on the ffi prove command by replacing the tuple `(Bytes, Bytes)` with a `JournalSeal` struct --- contracts/src/test/RiscZeroCheats.sol | 9 ++++++++- ffi/src/lib.rs | 22 ++++++++++++++++++++++ ffi/src/main.rs | 8 ++++++-- ffi/tests/basic.rs | 11 ++++++++--- 4 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 ffi/src/lib.rs diff --git a/contracts/src/test/RiscZeroCheats.sol b/contracts/src/test/RiscZeroCheats.sol index b08fdbc4..b4cc4afc 100644 --- a/contracts/src/test/RiscZeroCheats.sol +++ b/contracts/src/test/RiscZeroCheats.sol @@ -30,6 +30,12 @@ import {Strings2} from "./utils/Strings2.sol"; abstract contract RiscZeroCheats is CommonBase { using Strings2 for bytes; + /// @dev Journal and Seal struct used to decode the journal and seal from the `risc0-forge-ffi` `prove` command. + struct JournalSeal { + bytes journal; + bytes seal; + } + /// @notice Returns whether we are using the prover and verifier in dev-mode, or fully verifying. /// @dev This environment variable, along with the respective options in the zkVM, are controlled /// with the `RISC0_DEV_MODE` environment variable. @@ -64,7 +70,8 @@ abstract contract RiscZeroCheats is CommonBase { imageRunnerInput[i++] = "prove"; imageRunnerInput[i++] = elf_path; imageRunnerInput[i++] = input.toHexString(); - return abi.decode(vm.ffi(imageRunnerInput), (bytes, bytes)); + JournalSeal memory journalSeal = abi.decode(vm.ffi(imageRunnerInput), (JournalSeal)); + return (journalSeal.journal, journalSeal.seal); } /// @notice Deploy either a test or fully verifying `RiscZeroGroth16Verifier` depending on `devMode()`. diff --git a/ffi/src/lib.rs b/ffi/src/lib.rs new file mode 100644 index 00000000..c3a7e117 --- /dev/null +++ b/ffi/src/lib.rs @@ -0,0 +1,22 @@ +// Copyright 2024 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +alloy::sol! { + /// Journal and Seal as returned by the `prove` command. + #[sol(all_derives)] + struct JournalSeal { + bytes journal; + bytes seal; + } +} diff --git a/ffi/src/main.rs b/ffi/src/main.rs index 04903a25..59c0ff1a 100644 --- a/ffi/src/main.rs +++ b/ffi/src/main.rs @@ -19,10 +19,11 @@ use std::{ os::unix::io::{AsRawFd, FromRawFd}, }; -use alloy::{primitives::Bytes, sol_types::SolValue}; +use alloy::sol_types::SolValue; use anyhow::{ensure, Context, Result}; use clap::Parser; use risc0_ethereum_contracts::encode_seal; +use risc0_forge_ffi::JournalSeal; use risc0_zkvm::{default_prover, ExecutorEnv, ProverOpts, VerifierContext}; #[derive(Parser, Debug)] @@ -64,7 +65,10 @@ pub fn main() -> Result<()> { fn prove_ffi(elf_path: String, input: Vec) -> Result> { let elf = std::fs::read(elf_path).expect("failed to read guest ELF"); let (journal, seal) = prove(&elf, &input)?; - let calldata = (Bytes(journal.into()), Bytes(seal.into())); + let calldata = JournalSeal { + journal: journal.into(), + seal: seal.into(), + }; Ok(calldata.abi_encode()) } diff --git a/ffi/tests/basic.rs b/ffi/tests/basic.rs index 9c39a6b3..c0f7335f 100644 --- a/ffi/tests/basic.rs +++ b/ffi/tests/basic.rs @@ -14,9 +14,10 @@ use std::process::Command; -use alloy::{primitives::Bytes, sol_types::SolValue}; +use alloy::sol_types::SolValue; use ffi_guests::{ECHO_ID, ECHO_PATH}; use risc0_ethereum_contracts::encode_seal; +use risc0_forge_ffi::JournalSeal; use risc0_zkvm::{FakeReceipt, InnerReceipt, Receipt, ReceiptClaim}; #[test] @@ -36,7 +37,9 @@ fn basic_usage() { println!("{:#?}", &output); let output_bytes = hex::decode(output.stdout).unwrap(); - let (journal, seal) = <(Bytes, Bytes)>::abi_decode(&output_bytes, true).unwrap(); + let journal_seal = ::abi_decode(&output_bytes, true).unwrap(); + let journal = journal_seal.journal; + let seal = journal_seal.seal; assert_eq!(journal, hex::decode("deadbeef").unwrap()); let expected_receipt = Receipt::new( @@ -70,7 +73,9 @@ fn basic_usage_with_rust_log() { println!("{:#?}", &output); let output_bytes = hex::decode(output.stdout).unwrap(); - let (journal, seal) = <(Bytes, Bytes)>::abi_decode(&output_bytes, true).unwrap(); + let journal_seal = ::abi_decode(&output_bytes, true).unwrap(); + let journal = journal_seal.journal; + let seal = journal_seal.seal; assert_eq!(journal, hex::decode("deadbeef").unwrap()); let expected_receipt = Receipt::new( From ee1c4552ec2049d55808dd738b08ad8f7c4537c3 Mon Sep 17 00:00:00 2001 From: Wolfgang Welz Date: Thu, 3 Oct 2024 23:34:50 +0200 Subject: [PATCH 2/5] WEB3-162: Fix broken links (#277) Fixes #271 Fixes WEB3-162 --- README.md | 2 +- examples/README.md | 2 +- examples/erc20-counter/README.md | 2 +- examples/erc20-counter/apps/README.md | 2 +- examples/erc20-counter/methods/README.md | 4 ++-- examples/erc20/README.md | 2 +- examples/governance/README.md | 2 +- examples/token-stats/README.md | 2 +- ffi/README.md | 2 -- 9 files changed, 9 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index e324d72b..7044952f 100644 --- a/README.md +++ b/README.md @@ -28,5 +28,5 @@ You can install [Steel] with `cargo add risc0-steel`, check out the examples in [template]: https://github.com/risc0/bonsai-foundry-template [dev.risczero.com]: https://dev.risczero.com [risc0-quickstart]: https://dev.risczero.com/api/zkvm/quickstart -[bonsai-quickstart]: https://dev.risczero.com/api/bonsai/quickstart +[bonsai-quickstart]: https://dev.risczero.com/bonsai [alloy]: https://github.com/alloy-rs diff --git a/examples/README.md b/examples/README.md index 18c0e779..06f59ef7 100644 --- a/examples/README.md +++ b/examples/README.md @@ -16,6 +16,6 @@ Explore a more advanced interaction between [Steel] and a custom Ethereum smart This example shows how the [Steel] library can be used to call multiple view functions of a contract. This example generates a proof of a [Compound] cToken's APR (Annual Percentage Rate), showcasing the potential for on-chain verification of complex financial metrics. -[coprocessor]: https://www.risczero.com/news/a-guide-to-zk-coprocessors-for-scalability +[coprocessor]: https://risczero.com/blog/a-guide-to-zk-coprocessors-for-scalability [Steel]: ../steel [Compound]: https://compound.finance/ diff --git a/examples/erc20-counter/README.md b/examples/erc20-counter/README.md index 8df768ae..c1d68e39 100644 --- a/examples/erc20-counter/README.md +++ b/examples/erc20-counter/README.md @@ -62,5 +62,5 @@ When you're ready, follow the [deployment guide] to get your application running [Sepolia]: https://www.alchemy.com/overviews/sepolia-testnet [deployment guide]: ./deployment-guide.md [Rust]: https://doc.rust-lang.org/cargo/getting-started/installation.html -[Counter]: ./contracts/Counter.sol +[Counter]: ./contracts/src/Counter.sol [Steel]: https://www.risczero.com/blog/introducing-steel diff --git a/examples/erc20-counter/apps/README.md b/examples/erc20-counter/apps/README.md index 4e280a89..a38581d8 100644 --- a/examples/erc20-counter/apps/README.md +++ b/examples/erc20-counter/apps/README.md @@ -49,4 +49,4 @@ Options: ``` [publisher]: ./src/bin/publisher.rs -[Counter]: ../contracts/Counter.sol +[Counter]: ../contracts/src/Counter.sol diff --git a/examples/erc20-counter/methods/README.md b/examples/erc20-counter/methods/README.md index 98e32535..1eba1a86 100644 --- a/examples/erc20-counter/methods/README.md +++ b/examples/erc20-counter/methods/README.md @@ -27,5 +27,5 @@ Each will have a corresponding image ID, which is a hash identifying the program [guest programs]: https://dev.risczero.com/terminology#guest-program [on-chain logic]: ../contracts/ [guest/src/bin]: ./guest/src/bin/ -[Guest Code 101]: https://dev.risczero.com/zkvm/developer-guide/guest-code-101 -[RISC Zero examples]: https://github.com/risc0/tree/v0.18.0/examples \ No newline at end of file +[Guest Code 101]: https://dev.risczero.com/api/zkvm/guest-code-101 +[RISC Zero examples]: https://github.com/risc0/risc0/tree/main/examples \ No newline at end of file diff --git a/examples/erc20/README.md b/examples/erc20/README.md index f8c485a2..9724eaa1 100644 --- a/examples/erc20/README.md +++ b/examples/erc20/README.md @@ -8,7 +8,7 @@ To get started, you need to have Rust installed. If you haven't done so, follow Next, you will also need to have the `cargo-risczero` tool installed following the instructions [here][install-risczero]. -You'll also need access to an Ethereum Sepolia RPC endpoint. You can for example use [ethereum-sepolia-rpc.publicnode.com](https://ethereum-sepolia-rpc.publicnode.com) or a commercial RPC provider like [Alchemy](www.alchemy.com). +You'll also need access to an Ethereum Sepolia RPC endpoint. You can for example use [ethereum-sepolia-rpc.publicnode.com](https://ethereum-sepolia-rpc.publicnode.com) or a commercial RPC provider like [Alchemy](https://www.alchemy.com/). ## Run the example diff --git a/examples/governance/README.md b/examples/governance/README.md index ac8d7709..19edaf4c 100644 --- a/examples/governance/README.md +++ b/examples/governance/README.md @@ -68,7 +68,7 @@ This hash accumulator (`ballotHash`) is a commitment that allows offchain voting [Governor]: https://docs.openzeppelin.com/contracts/4.x/governance [instructions]: ./instructions.md [journal]: https://dev.risczero.com/terminology#journal -[RiscZeroGovernor.sol]: ./contracts/RiscZeroGovernor.sol +[RiscZeroGovernor.sol]: ./contracts/src/RiscZeroGovernor.sol [verifier contract]: https://dev.risczero.com/api/blockchain-integration/contracts/verifier [What does Risc Zero enable]: https://dev.risczero.com/api/use-cases [zkVM]: https://dev.risczero.com/zkvm diff --git a/examples/token-stats/README.md b/examples/token-stats/README.md index 45a336b8..8627791f 100644 --- a/examples/token-stats/README.md +++ b/examples/token-stats/README.md @@ -8,7 +8,7 @@ To get started, you need to have Rust installed. If you haven't done so, follow Next, you will also need to have the `cargo-risczero` tool installed following the instructions [here][install-risczero]. -You'll also need access to an Ethereum Mainnet RPC endpoint. You can for example use [ethereum-rpc.publicnode.com](https://ethereum-rpc.publicnode.com/) or a commercial RPC provider like [Alchemy](www.alchemy.com). +You'll also need access to an Ethereum Mainnet RPC endpoint. You can for example use [ethereum-rpc.publicnode.com](https://ethereum-rpc.publicnode.com/) or a commercial RPC provider like [Alchemy](https://www.alchemy.com/). ## Run the example diff --git a/ffi/README.md b/ffi/README.md index 2dc61dfc..a2770746 100644 --- a/ffi/README.md +++ b/ffi/README.md @@ -1,5 +1,3 @@ # RISC Zero Forge FFI This tool provides a Command Line Interface (CLI) enabling the communication between the [Foundry Forge ffi cheatcode](https://book.getfoundry.sh/cheatcodes/ffi) and the RISC Zero zkVM. - -The [BonsaiCheat](../contracts/src/BonsaiCheats.sol) contract shows an example of how to integrate this tool. \ No newline at end of file From 36434833a8a5a3eb79609322ffd0975df0c38012 Mon Sep 17 00:00:00 2001 From: Wolfgang Welz Date: Fri, 4 Oct 2024 22:30:45 +0200 Subject: [PATCH 3/5] WEB3-163: Adds `try_call()` method to `CallBuilder` for explicit error handling (#273) This PR introduces a new method, `try_call()`, to the `CallBuilder` API. This method returns a `Result` to allow users to handle potential errors during call execution. The existing `call()` method is retained for situations where panicking on failure is acceptable. Documentation has been updated to reflect these changes. --- .../methods/guest/src/bin/balance_of.rs | 5 +---- examples/erc20/README.md | 2 +- examples/erc20/methods/guest/src/main.rs | 2 +- examples/token-stats/methods/guest/src/main.rs | 2 -- steel/CHANGELOG.md | 2 +- steel/src/contract.rs | 17 +++++++++++++---- steel/tests/common/mod.rs | 2 +- steel/tests/corruption.rs | 12 ++++-------- 8 files changed, 22 insertions(+), 22 deletions(-) diff --git a/examples/erc20-counter/methods/guest/src/bin/balance_of.rs b/examples/erc20-counter/methods/guest/src/bin/balance_of.rs index 5bde0da1..6f1ce2c7 100644 --- a/examples/erc20-counter/methods/guest/src/bin/balance_of.rs +++ b/examples/erc20-counter/methods/guest/src/bin/balance_of.rs @@ -55,10 +55,7 @@ fn main() { // Execute the view call; it returns the result in the type generated by the `sol!` macro. let call = IERC20::balanceOfCall { account }; - let returns = Contract::new(contract, &env) - .call_builder(&call) - .call() - .unwrap(); + let returns = Contract::new(contract, &env).call_builder(&call).call(); // Check that the given account holds at least 1 token. assert!(returns._0 >= U256::from(1)); diff --git a/examples/erc20/README.md b/examples/erc20/README.md index 9724eaa1..5942c947 100644 --- a/examples/erc20/README.md +++ b/examples/erc20/README.md @@ -70,7 +70,7 @@ fn main() { // Execute the view call; it returns the result in the type generated by the `sol!` macro. let contract = Contract::new(CONTRACT, &env); - let returns = contract.call_builder(&CALL).from(CALLER).call().unwrap(); + let returns = contract.call_builder(&CALL).from(CALLER).call(); println!("View call result: {}", returns._0); } ``` diff --git a/examples/erc20/methods/guest/src/main.rs b/examples/erc20/methods/guest/src/main.rs index 80cdb45c..4f4a89ac 100644 --- a/examples/erc20/methods/guest/src/main.rs +++ b/examples/erc20/methods/guest/src/main.rs @@ -57,6 +57,6 @@ fn main() { // Execute the view call; it returns the result in the type generated by the `sol!` macro. let contract = Contract::new(CONTRACT, &env); - let returns = contract.call_builder(&CALL).from(CALLER).call().unwrap(); + let returns = contract.call_builder(&CALL).from(CALLER).call(); println!("View call result: {}", returns._0); } diff --git a/examples/token-stats/methods/guest/src/main.rs b/examples/token-stats/methods/guest/src/main.rs index 2c64a449..86403326 100644 --- a/examples/token-stats/methods/guest/src/main.rs +++ b/examples/token-stats/methods/guest/src/main.rs @@ -36,12 +36,10 @@ fn main() { let utilization = contract .call_builder(&CometMainInterface::getUtilizationCall {}) .call() - .unwrap() ._0; let supply_rate = contract .call_builder(&CometMainInterface::getSupplyRateCall { utilization }) .call() - .unwrap() ._0; // The formula for APR in percentage is the following: diff --git a/steel/CHANGELOG.md b/steel/CHANGELOG.md index 27c320e4..9e05a78e 100644 --- a/steel/CHANGELOG.md +++ b/steel/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file. ### ⚡️ Features +- Add `try_call()` method to `CallBuilder` when explicit error handling is necessary. - Make `BeaconInput`, `BlockInput` and `StateDb` public. - Implement custom `Debug` formatter for `Commitment`. - Implement `Deref` for `RlpHeader`. @@ -18,7 +19,6 @@ All notable changes to this project will be documented in this file. ### 🚨 Breaking Changes - Introduce the `ComposeInput` as a generalized type to represent different commitments. The `BeaconInput` is now a `ComposeInput`. This changes the binary input data, but does not require any code changes. -- `CallBuilder::call` in the guest now returns an error that needs to be handled, before it just panicked. ## [0.13.0](https://github.com/risc0/risc0-ethereum/releases/tag/steel-v0.13.0) - 2024-09-10 diff --git a/steel/src/contract.rs b/steel/src/contract.rs index 8079ebb4..0dc7e50d 100644 --- a/steel/src/contract.rs +++ b/steel/src/contract.rs @@ -63,7 +63,7 @@ use revm::{ /// // Guest: /// let evm_env = evm_input.into_env(); /// let contract = Contract::new(contract_address, &evm_env); -/// contract.call_builder(&get_balance).call().unwrap(); +/// contract.call_builder(&get_balance).call(); /// /// # Ok(()) /// # } @@ -278,10 +278,11 @@ where C: SolCall, H: EvmBlockHeader, { - /// Executes the call with a [EvmEnv] constructed with [Contract::new]. + /// Executes the call and returns an error if the call fails. /// - /// [EvmEnv]: crate::EvmEnv - pub fn call(self) -> Result { + /// In general, it's recommended to use [CallBuilder::call] unless explicit error handling is + /// required. + pub fn try_call(self) -> Result { let mut evm = new_evm::<_, H>( WrapStateDb::new(self.env.db()), self.env.cfg_env.clone(), @@ -289,6 +290,14 @@ where ); self.tx.transact(&mut evm) } + + /// Executes the call and panics on failure. + /// + /// A convenience wrapper for [CallBuilder::try_call], panicking if the call fails. Useful when + /// success is expected. + pub fn call(self) -> C::Return { + self.try_call().unwrap() + } } /// Transaction data to be used with [CallBuilder] for an execution. diff --git a/steel/tests/common/mod.rs b/steel/tests/common/mod.rs index cc87650d..9c340b69 100644 --- a/steel/tests/common/mod.rs +++ b/steel/tests/common/mod.rs @@ -70,7 +70,7 @@ where let result = { let contract = Contract::new(address, &env); - options.apply(contract.call_builder(&call)).call().unwrap() + options.apply(contract.call_builder(&call)).call() }; assert_eq!( result, preflight_result, diff --git a/steel/tests/corruption.rs b/steel/tests/corruption.rs index 7233c47f..f825f889 100644 --- a/steel/tests/corruption.rs +++ b/steel/tests/corruption.rs @@ -114,12 +114,10 @@ fn mock_anvil_guest(input: EthEvmInput) -> Commitment { let env = input.into_env().with_chain_spec(&ANVIL_CHAIN_SPEC); Contract::new(ANVIL_CONTRACT_ADDRESS, &env) .call_builder(&sol::Pair::aCall {}) - .call() - .unwrap(); + .call(); Contract::new(ANVIL_CONTRACT_ADDRESS, &env) .call_builder(&sol::Pair::bCall {}) - .call() - .unwrap(); + .call(); env.into_commitment() } @@ -365,8 +363,7 @@ async fn corrupt_header_beacon_commitment() { let env = input.into_env().with_chain_spec(Ð_SEPOLIA_CHAIN_SPEC); Contract::new(USDT_ADDRESS, &env) .call_builder(&USDT_CALL) - .call() - .unwrap(); + .call(); let commit = env.into_commitment(); assert_eq!(commit.blockID, exp_commit.blockID, "Changed commitment"); assert_eq!( @@ -397,8 +394,7 @@ async fn corrupt_beacon_proof() { let env = input.into_env().with_chain_spec(Ð_SEPOLIA_CHAIN_SPEC); Contract::new(USDT_ADDRESS, &env) .call_builder(&USDT_CALL) - .call() - .unwrap(); + .call(); let commit = env.into_commitment(); assert_eq!(commit.blockID, exp_commit.blockID, "Commitment changed"); assert_eq!( From e833bdd8e9301323c8bd762035262ebc3d4d57f8 Mon Sep 17 00:00:00 2001 From: Wolfgang Welz Date: Mon, 7 Oct 2024 11:47:10 +0200 Subject: [PATCH 4/5] WEB3-152: Generalized beacon commits (#265) This PR changes two aspects of how beacon block root commits are implemented: - Instead of having a `const` specifying the generalized Merkle index, we introduce a const generic for the index to make it part of the struct. This makes the code more robust against future protocol upgrades, and would also allow us to verify fields other than the `block_hash` in the future. - Instead of committing to the root of a beacon block referenced by its timestamp, we commit to the root of a beacon block referenced by its child timestamp, or equivalently, we commit to the root of the parent beacon block referenced by its timestamp. While this may sound counterintuitive, this is exactly how the [EIP-4788](https://eips.ethereum.org/EIPS/eip-4788) beacon root contract stores its data. This makes the verification side in Solidity much easier and less expensive, and gets rid of the weird code that was necessary to query the child of a beacon block during creation. This PR also adds much more documentation explaining that beacon commitment creation is currently only implemented for Daneb, and that the library needs to be updated to support future versions. It also introduces a wrapper around the Eth RPC block number tags, making it more convenient to specify the last block in the chain that still has a child. Resolves #258, resolves #260, resolves #262 Resolves WEB3-150, resolves WEB3-152, resolves WEB3-154 This PR also resolves #242 and resolves WEB3-123, as without the need to query for the child beacon node that api is not needed. --- contracts/src/steel/Steel.sol | 30 +-- .../erc20-counter/apps/src/bin/publisher.rs | 24 +- .../contracts/test/Counter.t.sol | 4 +- examples/erc20-counter/e2e-test.sh | 7 +- steel/CHANGELOG.md | 1 + steel/src/beacon.rs | 250 ++++++++++-------- steel/src/host/mod.rs | 65 ++++- steel/src/lib.rs | 5 +- steel/src/merkle.rs | 36 +-- steel/testdata/corrupt_beacon_proof.json | 2 +- .../corrupt_header_beacon_commitment.json | 2 +- steel/tests/corruption.rs | 7 +- 12 files changed, 234 insertions(+), 199 deletions(-) diff --git a/contracts/src/steel/Steel.sol b/contracts/src/steel/Steel.sol index 0cd6ef0a..826de4a6 100644 --- a/contracts/src/steel/Steel.sol +++ b/contracts/src/steel/Steel.sol @@ -59,14 +59,14 @@ library Steel { } /// @notice Validates if the provided beacon commitment matches the block root of the given timestamp. - /// @param blockTimestamp The timestamp to compare against. + /// @param timestamp The timestamp to compare against. /// @param blockRoot The block root to validate. /// @return True if the block's block root matches the block root, false otherwise. - function validateBeaconCommitment(uint256 blockTimestamp, bytes32 blockRoot) internal view returns (bool) { - if (block.timestamp - blockTimestamp > 12 * 8191) { + function validateBeaconCommitment(uint256 timestamp, bytes32 blockRoot) internal view returns (bool) { + if (block.timestamp - timestamp > 12 * 8191) { revert CommitmentTooOld(); } - return blockRoot == Beacon.blockRoot(blockTimestamp); + return blockRoot == Beacon.parentBlockRoot(timestamp); } } @@ -76,22 +76,12 @@ library Beacon { /// @dev https://eips.ethereum.org/EIPS/eip-4788 address internal constant BEACON_ROOTS_ADDRESS = 0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02; - /// @notice The Beacon block root could not be found as the next block has not been issued yet. - error NoParentBeaconBlock(); - - /// @notice Attempts to find the root of the Beacon block with the given timestamp. - /// @dev Since the Beacon roots contract only returns the parent Beacon block’s root, we need to find the next - /// Beacon block instead. This is done by adding the block time of 12s until a value is returned. - function blockRoot(uint256 timestamp) internal view returns (bytes32 root) { - uint256 blockTimestamp = block.timestamp; - while (true) { - timestamp += 12; // Beacon block time is 12 seconds - if (timestamp > blockTimestamp) revert NoParentBeaconBlock(); - - (bool success, bytes memory result) = BEACON_ROOTS_ADDRESS.staticcall(abi.encode(timestamp)); - if (success) { - return abi.decode(result, (bytes32)); - } + /// @notice Find the root of the Beacon block corresponding to the parent of the execution block with the given timestamp. + /// @return root Returns the corresponding Beacon block root or null, if no such block exists. + function parentBlockRoot(uint256 timestamp) internal view returns (bytes32 root) { + (bool success, bytes memory result) = BEACON_ROOTS_ADDRESS.staticcall(abi.encode(timestamp)); + if (success) { + return abi.decode(result, (bytes32)); } } } diff --git a/examples/erc20-counter/apps/src/bin/publisher.rs b/examples/erc20-counter/apps/src/bin/publisher.rs index 2315fa9e..222d44a3 100644 --- a/examples/erc20-counter/apps/src/bin/publisher.rs +++ b/examples/erc20-counter/apps/src/bin/publisher.rs @@ -18,7 +18,7 @@ use alloy::{ network::EthereumWallet, - providers::{Provider, ProviderBuilder}, + providers::ProviderBuilder, signers::local::PrivateKeySigner, sol_types::{SolCall, SolValue}, }; @@ -29,13 +29,11 @@ use erc20_counter_methods::{BALANCE_OF_ELF, BALANCE_OF_ID}; use risc0_ethereum_contracts::encode_seal; use risc0_steel::{ ethereum::{EthEvmEnv, ETH_SEPOLIA_CHAIN_SPEC}, - Commitment, Contract, EvmBlockHeader, + host::BlockNumberOrTag, + Commitment, Contract, }; use risc0_zkvm::{default_prover, sha::Digest, ExecutorEnv, ProverOpts, VerifierContext}; -use tokio::{ - task, - time::{sleep, Duration}, -}; +use tokio::task; use tracing_subscriber::EnvFilter; use url::Url; @@ -104,17 +102,15 @@ async fn main() -> Result<()> { .wallet(wallet) .on_http(args.eth_rpc_url); - // Create an EVM environment from that provider defaulting to the latest block. + // Create an EVM environment from that provider for the block latest - 1. let mut env = EthEvmEnv::builder() .provider(provider.clone()) + .block_number_or_tag(BlockNumberOrTag::Parent) .build() .await?; // The `with_chain_spec` method is used to specify the chain configuration. env = env.with_chain_spec(Ð_SEPOLIA_CHAIN_SPEC); - // Get the block that the EVM environment is based on. - let block_number = env.header().number(); - // Prepare the function call let call = IERC20::balanceOfCall { account: args.account, @@ -170,14 +166,6 @@ async fn main() -> Result<()> { let contract_image_id = Digest::from(contract.imageID().call().await?._0.0); ensure!(contract_image_id == Digest::from(BALANCE_OF_ID)); - // Make sure there is at least one child block. (Unless the node is anvil) - if !provider.get_client_version().await?.starts_with("anvil") { - log::info!("Waiting for committed block to have one child"); - while provider.get_block_number().await? <= block_number { - sleep(Duration::from_secs(3)).await; - } - } - // Call the increment function of the contract and wait for confirmation. log::info!( "Sending Tx calling {} Function of {:#}...", diff --git a/examples/erc20-counter/contracts/test/Counter.t.sol b/examples/erc20-counter/contracts/test/Counter.t.sol index f104b562..11447d8b 100644 --- a/examples/erc20-counter/contracts/test/Counter.t.sol +++ b/examples/erc20-counter/contracts/test/Counter.t.sol @@ -72,8 +72,8 @@ contract CounterTest is Test { function testEIP4788Commitment() public { // get the root of a previous Beacon block - uint240 beaconTimestamp = uint240(block.timestamp - 60); - bytes32 beaconRoot = Beacon.blockRoot(beaconTimestamp); + uint240 beaconTimestamp = uint240(block.timestamp); + bytes32 beaconRoot = Beacon.parentBlockRoot(beaconTimestamp); // mock the Journal Counter.Journal memory journal = Counter.Journal({ diff --git a/examples/erc20-counter/e2e-test.sh b/examples/erc20-counter/e2e-test.sh index 784a20cb..e54c5a0b 100755 --- a/examples/erc20-counter/e2e-test.sh +++ b/examples/erc20-counter/e2e-test.sh @@ -20,9 +20,14 @@ echo "ERC20 Toyken Address: $TOYKEN_ADDRESS" COUNTER_ADDRESS=$(jq -re '.transactions[] | select(.contractName == "Counter") | .contractAddress' ./broadcast/DeployCounter.s.sol/$CHAIN_ID/run-latest.json) echo "Counter Address: $COUNTER_ADDRESS" +# Extract the block in which the Toyken contract has been deployed and wait for the next block +BLOCK_NUMBER=$(jq --arg ADDRESS "$TOYKEN_ADDRESS" -re '.receipts[] | select(.contractAddress == $ADDRESS) | .blockNumber' ./broadcast/DeployCounter.s.sol/$CHAIN_ID/run-latest.json) +echo "Waiting for block $BLOCK_NUMBER to have one confirmation..." +while [ $(cast rpc --rpc-url ${ETH_RPC_URL:?} eth_blockNumber | jq -re) == "$BLOCK_NUMBER" ]; do sleep 3; done + # Publish a new state echo "Publishing a new state..." -RUST_LOG=info,risc0_steel=debug cargo run --bin publisher -- \ +RUST_LOG=${RUST_LOG:-info,risc0_steel=debug} cargo run --bin publisher -- \ --eth-wallet-private-key=${ETH_WALLET_PRIVATE_KEY:?} \ --eth-rpc-url=${ETH_RPC_URL:?} \ --counter-address=${COUNTER_ADDRESS:?} \ diff --git a/steel/CHANGELOG.md b/steel/CHANGELOG.md index 9e05a78e..e0b38e55 100644 --- a/steel/CHANGELOG.md +++ b/steel/CHANGELOG.md @@ -18,6 +18,7 @@ All notable changes to this project will be documented in this file. ### 🚨 Breaking Changes +- Instead of committing to the root of a beacon block referenced by its timestamp, we commit to the root of a beacon block referenced by its child timestamp, or equivalently, we commit to the root of the parent beacon block referenced by its timestamp. While this may sound counterintuitive, this is exactly how the [EIP-4788](https://eips.ethereum.org/EIPS/eip-4788) beacon root contract stores its data. This makes the verification side in Solidity much easier and less expensive, and gets rid of the weird code that was necessary to query the child of a beacon block during creation. - Introduce the `ComposeInput` as a generalized type to represent different commitments. The `BeaconInput` is now a `ComposeInput`. This changes the binary input data, but does not require any code changes. ## [0.13.0](https://github.com/risc0/risc0-ethereum/releases/tag/steel-v0.13.0) - 2024-09-10 diff --git a/steel/src/beacon.rs b/steel/src/beacon.rs index b591f2f9..776e9435 100644 --- a/steel/src/beacon.rs +++ b/steel/src/beacon.rs @@ -19,43 +19,83 @@ use crate::{ use alloy_primitives::{Sealed, B256}; use serde::{Deserialize, Serialize}; -/// The generalized Merkle tree index of the `block_hash` field in the `BeaconBlock` -pub const BLOCK_HASH_LEAF_INDEX: merkle::GeneralizedIndex = merkle::GeneralizedIndex::new(6444); +/// The generalized Merkle tree index of the `block_hash` field in the `BeaconBlock`. +pub const BLOCK_HASH_LEAF_INDEX: usize = 6444; /// Input committing to the corresponding Beacon Chain block root. pub type BeaconInput = ComposeInput; -/// Links the execution block hash to the Beacon block root. +/// Provides verifiable proof that an execution block hash is included in a specific beacon block on +/// the Ethereum blockchain. +/// +/// This type represents a commitment that proves the inclusion of an execution block's hash within +/// a particular beacon block on the Ethereum beacon chain. It relies on a Merkle proof to establish +/// this link, ensuring the integrity and verifiability of the connection between the execution +/// block and the beacon chain. +/// +/// **Important:** This type currently relies on an underlying implementation that only supports the +/// Deneb fork of the beacon chain. If the beacon chain undergoes a future upgrade, this type's +/// functionality may be affected, potentially requiring updates to handle new block structures or +/// proof generation mechanisms. +/// +/// Users should monitor for beacon chain upgrades and ensure they are using a compatible version of +/// this library. +pub type BeaconCommit = GeneralizedBeaconCommit; + +/// A commitment to a field of the Beacon block at a specific index in a Merkle tree, along with a +/// timestamp. +/// +/// The constant generic parameter `LEAF_INDEX` specifies the generalized Merkle tree index of the +/// leaf node in the Merkle tree corresponding to the field. #[derive(Clone, Serialize, Deserialize)] -pub struct BeaconCommit { +pub struct GeneralizedBeaconCommit { proof: Vec, timestamp: u64, } -impl BeaconCommit { - /// Creates a new `BeaconCommit`. +impl GeneralizedBeaconCommit { + /// Creates a new `GeneralizedBeaconCommit`. + /// + /// It panics if `LEAF_INDEX` is zero, because a Merkle tree cannot have a leaf at index 0. #[must_use] #[inline] pub const fn new(proof: Vec, timestamp: u64) -> Self { + assert!(LEAF_INDEX > 0); Self { proof, timestamp } } - /// Disassembles this `BeaconCommit`, returning the underlying Merkle proof and block timestamp. + /// Disassembles this `GeneralizedBeaconCommit`, returning the underlying Merkle proof and block + /// timestamp. #[inline] pub fn into_parts(self) -> (Vec, u64) { (self.proof, self.timestamp) } - /// Processes the `BeaconCommit`. + /// Calculates the root of the Merkle tree containing the given `leaf` hash at `LEAF_INDEX`, + /// using the provided Merkle proof. + #[inline] + pub fn process_proof(&self, leaf: B256) -> Result { + merkle::process_proof(leaf, &self.proof, LEAF_INDEX) + } + + /// Verifies that the given `leaf` hash is present at the `LEAF_INDEX` in the Merkle tree + /// represented by the `root` hash. + #[inline] + pub fn verify(&self, leaf: B256, root: B256) -> Result<(), merkle::InvalidProofError> { + merkle::verify(leaf, &self.proof, LEAF_INDEX, root) + } + fn into_commit(self, leaf: B256) -> (u64, B256) { - let beacon_root = merkle::process_proof(leaf, &self.proof, BLOCK_HASH_LEAF_INDEX) + let beacon_root = self + .process_proof(leaf) .expect("Invalid beacon inclusion proof"); (self.timestamp, beacon_root) } } -impl BlockHeaderCommit for BeaconCommit { - #[inline] +impl BlockHeaderCommit + for GeneralizedBeaconCommit +{ fn commit(self, header: &Sealed) -> Commitment { let (timestamp, beacon_root) = self.into_commit(header.seal()); Commitment::new(CommitmentVersion::Beacon as u16, timestamp, beacon_root) @@ -63,7 +103,7 @@ impl BlockHeaderCommit for BeaconCommit { } #[cfg(feature = "host")] -mod host { +pub(crate) mod host { use super::*; use crate::{ ethereum::EthBlockHeader, @@ -71,11 +111,11 @@ mod host { BlockInput, }; use alloy::{network::Ethereum, providers::Provider, transports::Transport}; - use alloy_primitives::{Sealable, B256}; + use alloy_primitives::B256; use anyhow::{bail, ensure, Context}; - use client::{BeaconClient, GetBlockHeaderResponse}; + use client::BeaconClient; + use ethereum_consensus::ssz::prelude::proofs::Proof; use ethereum_consensus::{ssz::prelude::*, types::SignedBeaconBlock, Fork}; - use log::info; use proofs::ProofAndWitness; use url::Url; @@ -89,33 +129,24 @@ mod host { T: Transport + Clone, P: Provider, { - let block_hash = env.header().hash_slow(); - let block_ts = env.header().timestamp(); - let parent_beacon_block_root = env - .header() - .parent_beacon_block_root - .context("parent_beacon_block_root missing in execution header")?; + let client = BeaconClient::new(url).context("invalid URL")?; + let (commit, beacon_root) = + create_beacon_commit(env.header(), "block_hash".into(), env.provider(), &client) + .await?; + let block_hash = env.header().seal(); + commit + .verify(block_hash, beacon_root) + .context("proof derived from API does not verify")?; let input = BlockInput::from_env(env) .await .context("failed to derive block input")?; - let client = BeaconClient::new(url).context("invalid URL")?; - let (proof, beacon_root) = create_proof(parent_beacon_block_root, client).await?; - merkle::verify(block_hash, &proof, BLOCK_HASH_LEAF_INDEX, beacon_root) - .context("proof derived from API does not verify")?; - let commit = BeaconCommit::new(proof, block_ts); - - info!( - "Commitment to beacon block root {} at {}", - beacon_root, block_ts - ); - Ok(BeaconInput::new(input, commit)) } } - mod client { + pub(crate) mod client { use ethereum_consensus::{ phase0::SignedBeaconBlockHeader, primitives::Root, types::mainnet::SignedBeaconBlock, Fork, @@ -186,16 +217,6 @@ mod host { Ok(value) } - /// Retrieves block header for given block id. - pub async fn get_block_header( - &self, - block_id: impl Display, - ) -> Result { - let path = format!("eth/v1/beacon/headers/{block_id}"); - let result: Response = self.http_get(&path).await?; - Ok(result.data) - } - /// Retrieves block details for given block id. pub async fn get_block( &self, @@ -211,87 +232,90 @@ mod host { } } - /// Creates the [MerkleProof] of `block_hash` in the `BeaconBlock` with the given - /// `parent_beacon_block_root`. - async fn create_proof( - parent_root: B256, - client: BeaconClient, - ) -> anyhow::Result<(Vec, B256)> { - // first get the header of the parent and then the actual block header - let parent_beacon_header = client - .get_block_header(parent_root) - .await - .with_context(|| format!("failed to get block header {}", parent_root))?; - let beacon_header = get_child_beacon_header(&client, parent_beacon_header) - .await - .with_context(|| format!("failed to get child of block {}", parent_root))?; + /// Creates a beacon commitment that `field` is contained in the `ExecutionPayload` of the + /// beacon block corresponding to `header`. + async fn create_beacon_commit( + header: &Sealed, + field: PathElement, + rpc_provider: P, + beacon_client: &BeaconClient, + ) -> anyhow::Result<(GeneralizedBeaconCommit, B256)> + where + T: Transport + Clone, + P: Provider, + H: EvmBlockHeader, + { + let child = { + let child_number = header.number() + 1; + let block_res = rpc_provider + .get_block_by_number(child_number.into(), false) + .await + .context("eth_getBlockByNumber failed")?; + let block = block_res.with_context(|| { + format!( + "beacon block commitment cannot be created for the most recent block; \ + use `parent` tag instead: block {} does not have a child", + header.number() + ) + })?; + block.header + }; + ensure!( + child.parent_hash == header.seal(), + "API returned invalid child block" + ); + + let beacon_root = child + .parent_beacon_block_root + .context("parent_beacon_block_root missing in execution header")?; + let proof = create_execution_payload_proof(field, beacon_root, beacon_client).await?; + ensure!(proof.index == LEAF_INDEX, "field has the wrong leaf index"); + + let commit = GeneralizedBeaconCommit::new( + proof.branch.iter().map(|n| n.0.into()).collect(), + child.timestamp, + ); - // get the entire block + Ok((commit, beacon_root)) + } + + /// Creates the Merkle inclusion proof of the element `field` in the `ExecutionPayload` of the + /// beacon block with the given `beacon_root`. + async fn create_execution_payload_proof( + field: PathElement, + beacon_root: B256, + client: &BeaconClient, + ) -> anyhow::Result { let signed_beacon_block = client - .get_block(beacon_header.root) + .get_block(beacon_root) .await - .with_context(|| format!("failed to get block {}", beacon_header.root))?; + .with_context(|| format!("failed to get block {}", beacon_root))?; // create the inclusion proof of the execution block hash depending on the fork version - let (proof, beacon_root) = match signed_beacon_block { - SignedBeaconBlock::Deneb(signed_block) => prove_block_hash(signed_block.message)?, + let (proof, _) = match signed_beacon_block { + SignedBeaconBlock::Deneb(signed_block) => { + prove_execution_payload_field(signed_block.message, field)? + } _ => { bail!( "invalid version of block {}: expected {}; got {}", - beacon_header.root, + beacon_root, Fork::Deneb, signed_beacon_block.version() ); } }; - Ok(( - proof.branch.iter().map(|n| n.0.into()).collect(), - beacon_root.0.into(), - )) - } - - /// Returns the header, with `parent_root` equal to `parent.root`. - /// - /// It iteratively tries to fetch headers of successive slots until success. - // TODO(#242): use `eth/v1/beacon/headers?parent_root` when more clients support it. - async fn get_child_beacon_header( - client: &BeaconClient, - parent: GetBlockHeaderResponse, - ) -> anyhow::Result { - let parent_slot = parent.header.message.slot; - let mut request_error = None; - for slot in (parent_slot + 1)..=(parent_slot + 32) { - match client.get_block_header(slot).await { - Err(err) => request_error = Some(err), - Ok(resp) => { - let header = &resp.header.message; - ensure!( - header.parent_root == parent.root, - "block {} has wrong parent_root: expected {}; got {}", - resp.root, - parent.root, - header.parent_root - ); - return Ok(resp); - } - } - } - // return the last error, if all calls failed - // safe unwrap: there must have been at least one error when we reach this line - let err = anyhow::Error::from(request_error.unwrap()); - Err(err.context("no valid response received for the 32 consecutive slots")) + Ok(proof) } - /// Returns the inclusion proof of `block_hash` in the given `BeaconBlock`. - fn prove_block_hash( + /// Creates the Merkle inclusion proof of the element `field` in the `ExecutionPayload` in the + /// given `BeaconBlock`. + fn prove_execution_payload_field( beacon_block: T, + field: PathElement, ) -> Result { - // the `block_hash` is in the ExecutionPayload in the BeaconBlockBody in the BeaconBlock - beacon_block.prove(&[ - "body".into(), - "execution_payload".into(), - "block_hash".into(), - ]) + // the field is in the ExecutionPayload in the BeaconBlockBody in the BeaconBlock + beacon_block.prove(&["body".into(), "execution_payload".into(), field]) } #[cfg(test)] @@ -309,16 +333,18 @@ mod host { let cl = BeaconClient::new(CL_URL).unwrap(); let block = el - .get_block_by_number(BlockNumberOrTag::Finalized, false) + .get_block_by_number(BlockNumberOrTag::Latest, false) .await .expect("eth_getBlockByNumber failed") .unwrap(); - let header = block.header(); + let beacon_root = block.header().parent_beacon_block_root.unwrap(); - let (proof, beacon_root) = create_proof(header.parent_beacon_block_root.unwrap(), cl) + let block_hash = block.header().parent_hash; + let proof = create_execution_payload_proof("block_hash".into(), beacon_root, &cl) .await - .expect("proving failed"); - merkle::verify(header.hash, &proof, BLOCK_HASH_LEAF_INDEX, beacon_root).unwrap(); + .expect("proving 'block_hash' failed"); + let branch: Vec = proof.branch.iter().map(|n| n.0.into()).collect(); + merkle::verify(block_hash, &branch, BLOCK_HASH_LEAF_INDEX, beacon_root).unwrap(); } } } diff --git a/steel/src/host/mod.rs b/steel/src/host/mod.rs index bbb2d98e..1613f099 100644 --- a/steel/src/host/mod.rs +++ b/steel/src/host/mod.rs @@ -19,24 +19,66 @@ use crate::{ beacon::BeaconInput, block::BlockInput, ethereum::{EthBlockHeader, EthEvmEnv}, + host::db::ProviderDb, EvmBlockHeader, EvmEnv, EvmInput, }; use alloy::{ network::{BlockResponse, Ethereum, Network}, providers::{Provider, ProviderBuilder, ReqwestProvider, RootProvider}, + rpc::types::BlockNumberOrTag as AlloyBlockNumberOrTag, transports::{ http::{Client, Http}, Transport, }, }; -use anyhow::{anyhow, Context, Result}; +use anyhow::{anyhow, ensure, Context, Result}; use db::{AlloyDb, ProofDb, ProviderConfig}; use url::Url; pub mod db; -/// A block number (or tag - "latest", "earliest", "pending"). -pub type BlockNumberOrTag = alloy::rpc::types::BlockNumberOrTag; +/// A block number (or tag - "latest", "safe", "finalized"). +/// This enum is used to specify which block to query when interacting with the blockchain. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] +pub enum BlockNumberOrTag { + /// The most recent block in the canonical chain observed by the client. + #[default] + Latest, + /// The parent of the most recent block in the canonical chain observed by the client. + /// This is equivalent to `Latest - 1`. + Parent, + /// The most recent block considered "safe" by the client. This typically refers to a block + /// that is sufficiently deep in the chain to be considered irreversible. + Safe, + /// The most recent finalized block in the chain. Finalized blocks are guaranteed to be + /// part of the canonical chain. + Finalized, + /// A specific block number in the canonical chain. + Number(u64), +} + +impl BlockNumberOrTag { + /// Converts the `BlockNumberOrTag` into the corresponding RPC type. + async fn into_rpc_type(self, provider: P) -> Result + where + T: Transport + Clone, + N: Network, + P: Provider, + { + let number = match self { + BlockNumberOrTag::Latest => AlloyBlockNumberOrTag::Latest, + BlockNumberOrTag::Parent => { + let latest = provider.get_block_number().await?; + ensure!(latest > 0, "genesis does not have a parent"); + AlloyBlockNumberOrTag::Number(latest - 1) + } + BlockNumberOrTag::Safe => AlloyBlockNumberOrTag::Safe, + BlockNumberOrTag::Finalized => AlloyBlockNumberOrTag::Finalized, + BlockNumberOrTag::Number(n) => AlloyBlockNumberOrTag::Number(n), + }; + Ok(number) + } +} /// Alias for readability, do not make public. pub(crate) type HostEvmEnv = EvmEnv, H>; @@ -75,6 +117,11 @@ where pub async fn into_input(self) -> Result> { Ok(EvmInput::Block(BlockInput::from_env(self).await?)) } + + /// Returns the provider of the underlying [AlloyDb]. + pub(crate) fn provider(&self) -> &P { + self.db().inner().provider() + } } impl HostEvmEnv, EthBlockHeader> @@ -130,7 +177,6 @@ impl EvmEnv<(), H> { /// # Ok(()) /// # } /// ``` - #[must_use] pub fn builder() -> EvmEnvBuilder<(), H> { EvmEnvBuilder { provider: (), @@ -208,12 +254,13 @@ impl EvmEnvBuilder { H: EvmBlockHeader + TryFrom<::HeaderResponse>, ::HeaderResponse>>::Error: Display, { - let rpc_block = self - .provider - .get_block_by_number(self.block, false) + let provider = self.provider; + let number = self.block.into_rpc_type(&provider).await?; + let rpc_block = provider + .get_block_by_number(number, false) .await .context("eth_getBlockByNumber failed")? - .with_context(|| format!("block {} not found", self.block))?; + .with_context(|| format!("block {} not found", number))?; let header = rpc_block.header().clone(); let header: H = header .try_into() @@ -222,7 +269,7 @@ impl EvmEnvBuilder { log::info!("Environment initialized for block {}", sealed_header.seal()); let db = ProofDb::new(AlloyDb::new( - self.provider, + provider, self.provider_config, sealed_header.seal(), )); diff --git a/steel/src/lib.rs b/steel/src/lib.rs index e2eabc48..8ed072cd 100644 --- a/steel/src/lib.rs +++ b/steel/src/lib.rs @@ -27,7 +27,7 @@ mod contract; pub mod ethereum; #[cfg(feature = "host")] pub mod host; -pub mod merkle; +mod merkle; mod mpt; pub mod serde; mod state; @@ -78,14 +78,11 @@ pub struct ComposeInput { impl> ComposeInput { /// Creates a new composed input from a [BlockInput] and a [BlockHeaderCommit]. - #[must_use] - #[inline] pub const fn new(input: BlockInput, commit: C) -> Self { Self { input, commit } } /// Disassembles this `ComposeInput`, returning the underlying input and commitment creator. - #[inline] pub fn into_parts(self) -> (BlockInput, C) { (self.input, self.commit) } diff --git a/steel/src/merkle.rs b/steel/src/merkle.rs index 2196ce62..28d85dea 100644 --- a/steel/src/merkle.rs +++ b/steel/src/merkle.rs @@ -15,7 +15,6 @@ //! Helpers for verifying Merkle proofs. use alloy_primitives::B256; use sha2::{Digest, Sha256}; -use std::num::NonZeroUsize; use thiserror::Error as ThisError; /// Error returned when verifying Merkle proofs. @@ -23,36 +22,12 @@ use thiserror::Error as ThisError; #[error("proof verification failed")] pub struct InvalidProofError; -/// Represents a "generalized Merkle tree index" from the SSZ spec, i.e. `2**depth + index`. -#[derive(Copy, Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)] -pub struct GeneralizedIndex(NonZeroUsize); - -impl GeneralizedIndex { - /// Creates a generalized index from the given value. It panics if the value is zero. - #[must_use] - #[inline] - pub const fn new(index: usize) -> Self { - match NonZeroUsize::new(index) { - None => panic!("invalid generalized index"), - Some(index) => GeneralizedIndex(index), - } - } - - /// Splits the generalized index into `depth` and `index`. - #[inline] - pub const fn split(self) -> (u32, usize) { - let depth = self.0.ilog2(); - (depth, self.0.get() - (1 << depth)) - } -} - /// Returns an error if `leaf` cannot be proven to occupy the `index` in the Merkle tree. #[inline] -#[cfg(feature = "host")] pub fn verify( leaf: B256, branch: &[B256], - generalized_index: GeneralizedIndex, + generalized_index: usize, root: B256, ) -> Result<(), InvalidProofError> { if process_proof(leaf, branch, generalized_index)? != root { @@ -68,9 +43,10 @@ pub fn verify( pub fn process_proof( leaf: B256, branch: &[B256], - generalized_index: GeneralizedIndex, + generalized_index: usize, ) -> Result { - let (depth, mut index) = generalized_index.split(); + let depth = generalized_index.ilog2(); + let mut index = generalized_index - (1 << depth); if !usize::try_from(depth) .map(|depth| branch.len() == depth) .unwrap_or(false) @@ -106,7 +82,7 @@ mod tests { b256!("f8c2ed25e9c31399d4149dcaa48c51f394043a6a1297e65780a5979e3d7bb77c"), b256!("382ba9638ce263e802593b387538faefbaed106e9f51ce793d405f161b105ee6"), ]; - const INDEX: GeneralizedIndex = GeneralizedIndex::new((1 << BRANCH.len()) + 2); + const INDEX: usize = (1 << BRANCH.len()) + 2; const ROOT: B256 = b256!("27097c728aade54ff1376d5954681f6d45c282a81596ef19183148441b754abb"); #[test] @@ -124,7 +100,7 @@ mod tests { #[test] fn invalid_index() { - let index = GeneralizedIndex::new(1 << BRANCH.len()); + let index: usize = 1 << BRANCH.len(); assert_ne!(process_proof(LEAF, &BRANCH, index).unwrap(), ROOT); verify(LEAF, &BRANCH, index, ROOT).unwrap_err(); } diff --git a/steel/testdata/corrupt_beacon_proof.json b/steel/testdata/corrupt_beacon_proof.json index cafb967e..b49577aa 100644 --- a/steel/testdata/corrupt_beacon_proof.json +++ b/steel/testdata/corrupt_beacon_proof.json @@ -1 +1 @@ -{"Beacon":{"input":{"header":"0xf90251a0f565af85fc1b8f48ea962eb40da64a51a4a97900ea47e8dbf35e83ca6cd9e237a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347941102e22ff1f6f56ed1b2e042959b5ee90c62a29ca0fb8c3b7efa0c5c578d57be9f9ec5b3e376375e00b8ba38ae5f2f321e4006763da0fc31b3313ef6f68b774aa3c555ff1bb983a9b1c1ded17e8180bee241d7c9376ba0eb7c0cf0a899811f7413fdbcd49ca392eff92a77c9e8af5d3413924feadd5bfeb90100c0010a1c096060088a1a249a4d1020070501c1210407a03043800c0c48820f8a0502e118408002940429102090142390479000100000266630221084402963841001484009ae0a274811262a0002404805040806020003a660038812884825a3424302001638a4490104866014200d060e0801c000440880041418185021c8004a2a27c00c98758fe0096000812104422050a501840480100a53a04804619120b32828130140ed460a44c09e0134006e240023d9b800025084f18402320a4281a1005c021000123c551106a58e06285250041002c01d8201010704105084621800540c05434020303a8a107020024a58041800004858024445210a0488013106808367a6b78401c9c38083cbf0908466fba84c856c616d6564a0fb4ed57d247c487289b506521f4f0672ade191cb7f469248cab1412caf4b83c5880000000000000000854f1d827829a03ba0c9436d3a1a40d4ec87057d5836e1cf5627743a357bde28269730fc37ec958304000084056e0000a034057321ab98a1d72a4c94631a7d04532f45de7893b6b60423cdd8ef548edc0a","state_trie":{"Branch":[{"Digest":"0x7c145cb7825aae7bf86d86420403faf0395f2d9af07519cf3c13672f9605484c"},{"Digest":"0xfa22a1090a6d81ced3d6868089e01b227f79740804d86b6bb213170cde21d332"},{"Branch":[{"Digest":"0xc5188383a259a0a14f37c295c8eebfb2bac841525ae34d5c17047b8782276f1a"},{"Digest":"0xaa3f3fa1ac9b60ab0b8225608d8da1ebbe8724b3a61e1a6670bfb908f28c8519"},{"Digest":"0x0517e7f63f1476498600124fee2d6a366b66285ebf01794448ad7e012a5f1f04"},{"Digest":"0x9ec9733ef0c9ba5e2fdb5c3a28c306117380765bc5938fbe9e3af3735293ceb9"},{"Branch":[{"Digest":"0xda6933a333a5d49ad5b89c9f043014afc77b86397be0798d5572a07e27902ebf"},{"Digest":"0x4d76980c2d51e20b6458f2a328ed615738800deb761a34555e77171cc3b87964"},{"Digest":"0xbbd17c46cf24bb2907b620fea1f9976e41b53f08d6382bf3e2b0970d5048af3c"},{"Digest":"0x779bd2e0e610fe38ea326abbe53bdc01d27f4b037348ade97f423757741ea6f2"},{"Digest":"0xa3e59ad51326d36add622f74f3d2174e00737dcae7e15b6ea5381d7974d317cd"},{"Digest":"0x818acbf6242f9eb099a0ad112b9e28c71100383482c573945676d849b4c61edb"},{"Digest":"0x47460468328d5d3614817d2c624b14299fa250e21911cf3280825c7e603e97ed"},{"Digest":"0x0934bf754a58694309deb24bdb95e88970daea0b6f320012e36bfa69e87d6005"},{"Digest":"0x38b95388ee5153f4eaa54dc91ee9ccffe1b50b67926f891075701dc91d614300"},{"Digest":"0x230af1125641692ddec8d4f5c4dfff36830d571c38c24dc3df4f53ba8a0d0a81"},{"Digest":"0x069eb5b2719ef3170d7c1fb5dfab3f317757a61e96c20dfcbbda7588e99ae21a"},{"Digest":"0xe403f3f6cbd7af30f292736030aeb8b734c6b1826902b543b914f6a6832cda28"},{"Digest":"0x75ab6daa631d5c3a66ec9e3652dbbbf40f37dc0aa7e640523bd6cb0e58260316"},{"Digest":"0xf0110f9b8bd8bbcc2ae8a4f3551f2da40d7fe2c58e59a13316504b46bb94ff03"},{"Digest":"0x52d02f7471ff137c0374bba43653562961a9752ce0c7298fb631fbc5fd192110"},{"Branch":[{"Digest":"0x05874ea022ba901c2d3bc4a24144b3f45991770d239620e85fca0846310d498f"},{"Digest":"0xbda332d0cf6544dc89b63a3b96d1980a00072e1c2407f5c151ff1dc61f94f215"},{"Digest":"0xe6548c4af231f8a84ece91fe09443fa167b6afa586298aa44f5c9de1d42f84d0"},{"Digest":"0xd79d1dd14d46778105a5abff292506caf027736cce07afc11e17898c7ed39a88"},{"Digest":"0xe85139c8ed7d2b120c17a53fedf8eaaff295412b3bebb3cd131004fcfeed24d2"},{"Digest":"0xff8cd7a7fc94ce410a001fb178a88f2f79a827aba693091209de5241d00f9bc6"},{"Digest":"0x3551497a0439f640571c034fc777fba7f6d64c536f4ada7eacc5fab53cb8574c"},{"Digest":"0x3515948c7d7ddb11ecd4eda0b326f70864ff485bf3e31478d952ef444c157196"},{"Digest":"0x28cff3351737e92436aa9ccc4fc5bbca341513157aa4885645bbb838ba6c419a"},{"Digest":"0x297e852d803fea4691bd25ae28f5cc82f21bf44d364a80220fb44c8cc8398993"},{"Branch":[{"Branch":[{"Digest":"0xdb28048328251e31b2d3328dc517f370e4661cf8ce1d5fa345faa9f51ce94f9d"},{"Digest":"0x35292568f46d6bb85536804d457243974a5ef9557fd02fdd9c414150039dd570"},{"Digest":"0x547adead9dca2a0a5a68a59b0a9e15e76e03c267aa1bade08bb046f2bd4eb073"},{"Digest":"0x27d35383b43d2bd596638fd20e8dd09a6ab63c96f90ec11c6a5249bb4f4dc2eb"},{"Digest":"0x406a49a5b08edc39727921ccee69f2d8585f1658b581cc21f65349a13be8b129"},{"Digest":"0x8e3c6433db2e2b9bb76200119bf51313cb82d97200d633f988c2222980901f9a"},{"Digest":"0x1e379c0cbf9b976f7917e8dd9cd6e59314a75cff480f6a476984321794bde9d0"},{"Digest":"0x3432854290ecfba5f449eeef9f941897a935694aad97592e7b7d9d681437620f"},{"Digest":"0x644f86d76acd1f8bb5a55119608f0fa73493b2694ef0950f1a5f673e8a7e6753"},{"Digest":"0xdf89fb84a1f4d3a48d788b242de27b80ef31b634c1321f5506a6e6158bb8dcff"},{"Digest":"0x2cf4721a99a7be43a6ed31637c001960276b54518ee3541e349aa47776752196"},{"Branch":[{"Digest":"0x8b92b40f358d29115172a38e36adc284772b7c2440b55e199e31f6d79dc52ab5"},null,null,{"Digest":"0x32e92fce0570631395ec05c62413a521ed320db25bd4a95992ccfc47c4c74a39"},null,null,{"Digest":"0xac2a299a9f99e6f0b275d38efb601ee9d1d95199b9441d46058781dd915fafe4"},null,null,null,null,{"Leaf":[[6,12,6,8,5,3,5,0,5,7,9,13,11,0,5,7,3,3,4,7,14,6,12,10,13,2,1,6,0,15,6,12,15,15,13,1,5,10,1,4,13,15,10,14,15,11,4,11,3,15,1,8,10,14,13,11,0],[248,68,1,128,160,103,110,5,68,138,220,242,138,231,10,154,43,183,126,53,138,156,104,218,216,109,165,179,226,101,51,240,54,135,15,129,195,160,173,162,122,66,135,249,23,26,77,35,164,213,151,124,154,88,61,113,137,6,246,170,45,109,127,36,115,156,57,115,6,242]]},null,null,null,null]},{"Digest":"0x924c1290a02b6550560de2f36ee20c66a31e4e2e1997333f3a8642403bbc1b9a"},{"Digest":"0xd6a2b5a75d24772a9e6c35cdccc8f51ac75818870ab706fef68c0e53b4aa5e40"},{"Digest":"0x2d6bae5f11cf0d8c8aa8858af8caa1a125595e8112eca81d2ca618d2d4758ec3"},{"Digest":"0x96066747f61459591574c48f97d9af2793f04d8258fe6eb7f4c1260cb2a9ed8a"}]},{"Digest":"0x3959262eab0df5cb0ff6ce4bb34ff9af758a35bbcbee37abe5990294e0562fc2"},{"Digest":"0xafac905211b114f21670e002795d86542bd89851a38a5aabd7face23feecf318"},{"Digest":"0x5067f564588be95a99e2f468d72b96462f212bf91b58b69e790c0199bfabb031"},{"Digest":"0xf5bd14502ac3ffb3c931e67fcdee688df840196a89e9bfc7c96fcb3f52058341"},{"Digest":"0xfec9be1378be2a793ece6049f8a10766d4289af8ee1e6aff8e748b74fb95cf16"},{"Digest":"0x4fd7ecbe4c1f9958c6da124c59d0bbea0160c56bf32bd6eb72c672f9abc44a92"},{"Digest":"0x96891f3a45ee91d99cf3e168a61019c3d8ddfa00dddd11b83a3e81c7e5e35589"},{"Digest":"0xeb6bf0cf183778116004b698ef0f5e70995dfa9478bb3255f0b29208d5f92808"},{"Digest":"0xc3caef74fad501cd0ec832b44fd6d19474b9fd2a2153b908e3e8063229b5a6d7"},{"Digest":"0xaf327e16ecc2b46b9eb8560b73410d573daef3486c108b7d4e50aec6fdd8f546"},{"Digest":"0x21fe976c00067f58fcfe4ff5aa689f7a263cf97a879debcfa88ce119a52e5d7d"},{"Digest":"0x66fd5a9d629a870d36e270e332c6bce939ed7fc2a9f2e2f334c65a630ca3ba0d"},{"Digest":"0x5e7d45a26dc6c2a9875a2d6b87710a5eebcfc5b76ff5eb6624c72bb574070dac"},{"Digest":"0x1c3f804db6dc200cd23518a4be871857ac04b8e1bcd87f743bb86a459c6c2c22"},{"Digest":"0xe18a3df3e569acca09459d2ef00b1e4fb3e8d1513cde0e83fdccd25db5d57c73"}]},{"Digest":"0xc366671e6d92e680ef4a210a57bf64f5ec14a6734eebccb548e0764dfb510f77"},{"Digest":"0xae055c2ad055a21614f87feb9de5b98dd47505c4fcdf7b2e21c2df56ec3cf21f"},{"Digest":"0xf95acfb1cf14e4a461ae9d3b1d0fb69e5d66ae663f6c0630ff618ac076be530e"},{"Digest":"0x683d9927ce5db8dc2e645132f672f1aafc98b33492b5651eb899c1dbf24eef6b"},{"Digest":"0xdb58eb782462c4b917eca16ce13ee0864835dc1b4b7350e23e75c8425b7f6c7c"}]}]},{"Digest":"0xad9e11a9e3701f33b01ae9d8e77e7398311eb0bf06cc3c5e88b9d95982ef6463"},{"Digest":"0x93c454b885f23cd9bf1c510ad242e29fad9eb479fb3d9138d5b56b3048319273"},{"Digest":"0xff977e315ebb23db12788b43dfd61cbaf638a70924828ea54145b6e0e47f90d5"},{"Digest":"0xa90f8aeaab76bca37f919e2116935261db761ead1e077aaa6b777c12569f584b"},{"Branch":[{"Digest":"0x78a51a98a939dfac3ef54e1572230e0803c297dc3526e58f93e8d6400af983af"},{"Digest":"0x57e829d9c21be34752dbcdeb90994f7d3041a02a40a7a772ce7578200d434a11"},{"Digest":"0x7d39d89a71ba761224f95b54ce82dc791d6f688dfa208527176f4e09e0cdc092"},{"Digest":"0xc1394f74cb150871a9eb904897cb9be245d4b240d70280cca48a9e86501e5494"},{"Digest":"0xdef9314b6d5a5ec58f4b349070e8c77be41e30dbced326aa6f120e1c5fc9198e"},{"Digest":"0x52dfaa5578d5164f3bd23bde2618f522f5ad2bb7001e542318fb09091299ccc2"},{"Digest":"0x7cda00aa77cd99719f80426de664e74b3e321a6aae4f15d858921fc904dd930b"},{"Digest":"0x338a4718b319d7bf8bff6cbe15ac70baf1234f45b9978bcca4ef5524871b64ad"},{"Digest":"0x354d8e86498a01ed6fdd7c8565b95434cc0d76be1e93bfc7e6e340dca2651082"},{"Digest":"0x854f7ffb29c2d34f1d43e8028ce965636734ec7e1adea268acf8de339b2e66ff"},{"Digest":"0x72231de65deb76d26846fedcf208f18e508198b38a22168c5da52ffee42e5605"},{"Digest":"0xc41e55b2aa11df1ffbd77b8f0f4bdb96aca56adf4f6511930bf1d3da276f898d"},{"Digest":"0x4bc0cedfa0d7f328c0992f388dc1fed34eafa005d77f02fb296d609376a7a4b4"},{"Digest":"0x44f7bcb6a73e0f151ccbe24922a48c113f36744f2d88b2f4e48f54f770d0ac9a"},{"Digest":"0x656b5f2d56ac96deff96c8b3a25467524a5fe2833c70ac56e8f7f60e66850636"},{"Branch":[{"Digest":"0xc39ec523f8542f0084a6e65b885a03dd5a5fe475e7cb5450e207fe4977152c70"},{"Digest":"0x74fca0b8a1f554d0fe2576468cd2dd20647e62bd1c80a1549d41365b970b6050"},{"Digest":"0x7fc12c21fbc5e4d727ce552720da3e288f4f09b57e273d98c7872236f525fe5a"},{"Digest":"0x100ae54659a98a66d90edc8204ac461af7526e2a3c303563dcb55f027ac6e84f"},{"Digest":"0x961ae97d4b456700bc496b5b6405e8f58097cf2bdf529e213cb7e80533d2a5b7"},{"Digest":"0x0d91302a9a48437a6eb5b795e15bfb3aec78c7361a676720e25c75cb05f743f7"},{"Branch":[{"Digest":"0x89f89128182d3674093ae3f197cfb83f33657b8a30d1b2a91cbdb93c4d9aafe6"},{"Branch":[{"Digest":"0x347c03ff92d9c3e6fbb7dbbca0b37e473f893f009e316f82a5d335c87908fc08"},{"Digest":"0xa5bc6a596176027b0fd39bf8d9bad3630cabf35c20e02c3fe105f3f9a351470a"},{"Digest":"0xc60952ce285759951d7182dc640e1666bd8bff64bbfcd63c138cd1fb1a8bcf0d"},{"Digest":"0xc248743cff607ebc8901d09ad2db1d64ccbdb926cd1ca70abbb065c7fb3aa1db"},null,{"Digest":"0x229f9dfb8922aaab5c9aeaa8511ee3ed84889de7632daa257615834a62578c1d"},{"Digest":"0x5e88c447ed7093cf393fb93bcf17696c7ece03fc75364ba3b653937cd2418a15"},null,{"Digest":"0x7768f73b73de0a46bacac3f3e10aa876d732ea59729a016a6811ce74e3c6f025"},{"Digest":"0xb4ae06aba30beb5c97b55fdd25f82ab988f382c5d05be7525964d94bafb1a856"},{"Digest":"0x63a6ce8d8efa5b57b1d071636ee65a9b7e9805f9510d6cb17259281ff3e3a030"},{"Digest":"0x9fb3eb7594e42b4fdb0b50de6def1d8d76f151db330fa818f7c42c1041a1148d"},{"Digest":"0x1137b42985bdf9d6f34ab51ef1f6e0da66833f31ee63230d650779e512d87ed3"},{"Digest":"0x2626491ebb0eb4413ad79e4b47da9113262e9463d11587a04012e8c8d4c9ac6d"},{"Branch":[{"Leaf":[[11,4,4,7,8,0,2,9,10,7,14,14,9,2,0,15,2,11,0,8,6,7,15,7,13,4,13,3,3,11,3,3,9,10,1,15,7,10,7,14,10,8,9,10,13,9,7,6,8,8,0,2,6,8,9,0,6],[248,79,130,26,116,137,1,149,233,64,88,159,170,64,11,160,86,232,31,23,27,204,85,166,255,131,69,230,146,192,248,110,91,72,224,27,153,108,173,192,1,98,47,181,227,99,180,33,160,197,210,70,1,134,247,35,60,146,126,125,178,220,199,3,192,229,0,182,83,202,130,39,59,123,250,216,4,93,133,164,112]]},null,null,null,null,{"Digest":"0x76a199fdb84a7d3216593844ab7691d6a8571d6088911150a3679b9a36487ca0"},null,null,null,null,null,null,null,null,null,{"Digest":"0x8330bc24c00b152e54d9364a775b6ecab5c829c59272fd84d7bb351366d15739"}]},{"Digest":"0xd1da7c3b76a704b6af19637a7b7d7a8f895f043faf477fb20660c28c92b6e53a"}]},{"Digest":"0x2000582e987ddfadb55de9d8c04a5ea108d2ee6615153cbcc23477f9998231fb"},{"Digest":"0xc94bccd6d668430e7e9e14c9941b294b1c0bf7dd8fae2dc01ea454a5a7e2b553"},{"Digest":"0x4378656a5fd08c32889daa18e0282e2434918d05233a35837548a4faaf537e1f"},{"Digest":"0x3b34e2a5f10fd91e2ac7cd9e31889615e66ed96ba99417901f21bbc7c01059d9"},{"Digest":"0xa350c5edcc4088c9f5b3ef71f7c1bd38530814783281bfd88f8dde5fe578122b"},{"Digest":"0x5c5c3b541e9373d714ecc721a903f4a8c1ea7614985d87941168fcc4d587f3bc"},{"Digest":"0xaf1802f2c3f4fcc023f7fa4623586913289ec1473fc0ff8f8dfbc7d8f4381669"},{"Digest":"0xfae84ae20bba66affacc94a39410ad201ef5fa4e2a56b227bc42ecbe6a5c3c81"},{"Digest":"0x63d03e9a9e7d25fad2c7c7ea35932f4180f5735b6a693ceea9f605d1d255a111"},{"Digest":"0x7ac67eeda06ed2a288d992628286bb5028d69478e036757f219f5d5ac9f0c6c3"},{"Digest":"0x7e47876ecff71deefb6671ef4677301f99cea5943fe656678c2669da92483b20"},{"Digest":"0x729453751305a0b80e61ac794db9771711a6df554dfd46984e11f76e9240c89f"},{"Digest":"0x32ff8091ec1c7b0c62848bdce8f23645ba4beca4ccf03f4dfcd9a34529423b74"},{"Digest":"0x9b5d3c6d1b6fb58ec6e25cf23d0650bdb43503fc06595907f928e37e4058ac54"}]},{"Digest":"0x9db80b716c41af63978020d30017d5c87dd23f56e1783ec28cb29d085f36aaa4"},{"Digest":"0x41be2fbfb195d2c9cb4d5a395be88bc09089444fdc1dbfc6a531367c39e52262"},{"Digest":"0x5e9e354c187ccad5087ac65778a476a38e35da7240ddcebeb89e3ca5ec87ebec"},{"Digest":"0x5ccd77692b3b02d187a4eb9cbf09c2569b6737eb8e2f777245cca2cdcb226616"},{"Digest":"0xf9f6c3ad585ddc478d7209d876a986b4a5f85b52706f56e1dbaa924170e8ec18"},{"Digest":"0xa5e58ebf4af2adcb42a3fabbef52f67ffb8b6d608272498b33c7049826367d35"},{"Digest":"0x1581534c0932c031ff5c5aac8ffe5df9015e8f90b6607b0c655038345a8c4fab"},{"Digest":"0x3cf619dd52e7e6a7bdcd72eba4f0bb6262d3054ce665f1a78b41d82856353c03"},{"Digest":"0xfc41d88ac0eb6e10eb873050e35231517ad8de23685b3573e63033ac524977dc"}]}]},{"Digest":"0x8ffe09039a6cc5fb2ada11cc8179ae50ade9455b1d7de08302c17952b209b23a"},{"Digest":"0x5b910b6c4391bdc271b954feabb97f4229fca3f7e2466aaaf2895518a6f63790"},{"Digest":"0x0f3ffe264ba37c65e7072406ce189abda66dfd2ab53b005c3c664c54bad48b59"},{"Digest":"0xcf9c35cf6264f17b6981449d07379ffbf9ee25098881833ed4167bcfb4d1aa5a"},{"Digest":"0x97875850aa2e9f068f90d6aa3c9d8ab87a69db1816295edf2f5907bdb919af0a"},{"Digest":"0xad5866a1ecf73b25eabfd0678a1956dd445131be0cf45d5931e19ed400244fae"}]},{"Digest":"0xc5843a3a1052ae5e1bc51cb2e73941f56f3d8b24343c18b575bcb56b9b8678c6"},{"Digest":"0xab73a5d5c21e0313ddad0dc2aa93c616b51fa7dfaab86c20c9314b518e13a195"},{"Digest":"0x93c921c8ef533cf1309d27b2d233525a99fa251f3aa8c7999e69b30f6068166d"},{"Digest":"0xadd979abb22b9fa820382ea30a55515e016f120fa086d21f9b314761c8bee050"},{"Digest":"0x302a09465fee8c6bf6bd08690514d3d27a07e10b0b3893a40bfda48b3655b562"},{"Digest":"0x659122f87f9203f1c3c6d8617bcb037d439c4be5c9e9f7ebed2bdd8c880c7db7"},{"Digest":"0x67088b4c822e5b042d9bd979e50df8db54ee14bec74d23bc1b44c9aa9319cc24"},{"Digest":"0xadc2256d6257c8b78dce1849aba8adcad7982ab760739c4887f899509bc59be7"},{"Digest":"0x2693733d79837e1f389f414765695eb15c7dac14727b9322fcd296eca9c66285"},{"Digest":"0x9892ade3e482b102da4dae2e9cd5587ec56a9151415e15cc97a0e9f467c75b11"},{"Digest":"0x7095969b630f20e41826a749d33bb129073dd1fcb34de2d8fd90ebcd9b8289a9"},{"Digest":"0xef9ace4adf41f11fc21eeff47df3d153b02b83e3ed8293d4d4ff10b3529ee3ca"},{"Digest":"0xabceabfb09dc73334f5daef1130025c0d55b5af70410ce4a6c1b4b9d8f615ecc"}]},"storage_tries":[{"Branch":[{"Digest":"0xc2126fb735c8c71bb2f27b27c6ead32d39e02affcfa9c313bbc0a4a5c87b75fc"},{"Digest":"0x48386d60a0d14fd8bea4eef30dc7d7e83b22c7aaa12b838fc10f5918ac47044b"},{"Digest":"0x9b31862f2d3a7a6a6b4a99ad4866a399025eb4eedf0c91283a9bcbd6b0c99bbe"},{"Digest":"0x44e386d0e34dc700119be1832672ea8fc9fac8f4ec4cfc112a2f1a91c888561e"},{"Digest":"0x654d5160bfb920c1f5b0783351ed306bef6b59bcd2a3626ec341296acc6a21b8"},{"Digest":"0x04ff11d369a90aea17562c849d80ef296ab227e86d00f974ea18461dfdbd7f4e"},{"Digest":"0x8333e2094021bddda38790656beac10fb121018fb4a76bed4a1c8bb9ed707c0f"},{"Digest":"0xad82d053fd257e249fd76918213cfe321654ed4f4db2b452ba3704565a14d364"},{"Digest":"0x2a2c2976b51f14a611f1f3a9f52ffa6c3ba547f5c049f00151b6328fe313a546"},{"Digest":"0xa0a1060c8ab9168bfc0fbfd1889f8c290828f37718fa50c5578f1526ec57bf48"},{"Digest":"0x7d70a6bfbcf857cdf18d82200704ff7bae7cf12d94f06c12b26c6c8f740b2b6a"},{"Digest":"0xde7deb8da1df8f9790af9dacea7e3acd712eff247636cf2dd27e30586925e1a0"},{"Digest":"0x4e02539b91f81a211d2282c1c30252c3c8b2a22ccca29d6bfb7cc367b8e8eb68"},{"Digest":"0x0e5e55ceb0e52ab3b1688c24c1dc330671d11a86468811d309c1dffe2b3f4558"},{"Digest":"0x5355113258dd5fb285357a62f6ab2713c057523884f616631fb8245ef000f672"},{"Branch":[{"Branch":[{"Digest":"0x02073d18333e691bddb8642ca82b732db6415c9f84a1149b3bb710824214ceb2"},{"Digest":"0x31d5bc9659e75a99e973418b4794c0d9241a3482d6359cb11b0753d0e460a269"},{"Digest":"0xe79421201d09eeb52b36e427967ed621d245fb04769487d7ebdc5cf7d44b17b4"},{"Digest":"0x18ef63217fc35b0ec780d2427113b6e35a714c4c17b27993cf6227b551912f58"},{"Digest":"0xa53a1b7d3f70c40201345314bf7fb4446bcf79dde781102143705d6b66486e53"},{"Digest":"0x007a444b6e07e59e910751aca367d5fb2d4db3126fe9b9bfae05a7f652cac56f"},{"Digest":"0x460db8fc9fcb2d58cc58997614c5a6545b8c4ea7342fef05768a5691ca7fe5ca"},{"Digest":"0x35ec4099628336dd7f3a13caa20a54d2611b4d8b97a112ff357e0eb0541f189f"},{"Digest":"0x49355ad2e8f7bf8b6ce8084088aa894c07ded44b315695aa1b3fb3551d35d4fb"},{"Digest":"0x83638c0eed723390afd17ac07ad64aa3f298affe5078a3ec49e9b7b463c12fed"},{"Digest":"0x90424abf55dbe91f187e2eab0a91771c4909ee989dddd2263c5ffd8353e44a91"},{"Digest":"0xf708a9096c48c1baed6a8cd3f9409b1863eae8276801a89a6152806947f90a7d"},{"Digest":"0x467c6d27ad319df67a07e54aa5ba51d914c1191c6f179e045ba5e4b1362e1265"},{"Branch":[{"Digest":"0x957c5ebf39508dce06b519f3357407ce9b0c7e325a5b5baf20356802119e2a1d"},{"Digest":"0xdcdcda02bab51aee6cec341859880c7d3a74b2a708c6837a283e9140d742ae71"},{"Digest":"0xfe878f6d7851d2c4a89a747005f6ec12211eea53845502d577358c38d99b0540"},{"Digest":"0xba01139006d0b39ceae595d8736eeb0614536ec331df968bb7a87726d663619e"},{"Digest":"0xd835f0fb96ed233d45a950b9374600896dce6e9f9e9f415e16f56d58db6328ea"},{"Digest":"0x763bc0283a452d3e45a3c40bc33ace9c3bf8327a4f98f3939b6fb10797692ea9"},{"Digest":"0x926a4be03b7bfb0176a0a07d1737c8bf6d7a73d1d02744a1bf26736c3a853227"},{"Digest":"0xbff83b63f63ff94b661fb0a7c3cce98b8407f55097a90e1af5351b21f649d32c"},{"Digest":"0xe0e716a063b31091e183787523f5532b2dc7ab69a1dd66cc90cfb116ad477d20"},{"Digest":"0xfe7d2af4a9f50363f9fc87756d737bd5ea2ce08079a592af54285923e44cbedd"},null,{"Digest":"0xb883893ad62f19b1ade0ead65ab810ea10bc653dc37b2d6e9536ddffab16c44b"},{"Digest":"0x1a578cb4375a74230fc289891bc27480edb2b7b162f8d0636ffd9cffa155cb06"},null,{"Digest":"0x1ab003882db00b52c3298b9f8e5377e64facdbd98d8a31376d7f4b4f7014e11b"},{"Branch":[null,null,null,null,null,null,null,null,{"Digest":"0xf0ec532af391e6dc77f2c9867afce87e39293059a5f8ddf2b21b38d8e4dd23b6"},null,null,null,null,null,{"Digest":"0xb92295774b00d67bfc53715b07b142a21c554b7f1cce914aefc2157459fc289c"},null]}]},{"Digest":"0x45b01213c9e56a5527cbb6ac2dee8cff756ebbec4f9a4106794a62d73e95bddb"},{"Digest":"0xb00a95f416324179cea6c4a2af4bfb813a2925aeb02da845510630a1ecab965d"}]},{"Digest":"0x8d05de705dfe8953c26d2632fcbc546eba89a253c55338907829e83581aa6379"},{"Digest":"0xdbdede52331ae902f3687223b04ee66d8cb09e0fc669b3d848cc3a3d2e2085c6"},{"Digest":"0xccc8214fcaa44a224ba014057dc73757d3c871d6462f799e0c5afb754427f0ac"},{"Digest":"0x1c8a2128b24aaf149e8299fda27f8b16c6a8f000ddbf2068bfd13de59eb80042"},{"Digest":"0xe709cdb4462cd15de1afb1ab1717d86bb43b727b64669cce6f7a599dfa3bea5c"},{"Digest":"0x02ee4a0d06036c8c0419d43192a5645480aba0f0c0315b5765c6b5b349fa277c"},{"Digest":"0xfabd3487cff148ab8e6a020cbfef3ce255a81fd130de42a06c9dce4ea342d305"},{"Digest":"0xfaeb4665c5248c94460f0f6acdaeef0230abbc35fa39ffb39f8aeaabe6bb1440"},{"Digest":"0xb7455579aa6ad32b71a8235d3da8e2617b408c9656166c68a16e47a56e4098a0"},{"Digest":"0xdfc0e498d31274948b0bca730702c519208471c0b9bd3cdb992b89bc0517f1df"},{"Digest":"0x16e332f3f25f9b4e128ce4a1f84425ccb01010dd6fdcdd1d6623b085887ed578"},{"Digest":"0x2671ddb8e1c7f06687941285e09f3dfdc59f0b10ecf2b6519175fdb88c232a29"},{"Digest":"0xc51c210305336706d9e14799b45ca38cf015518ca5aed8698eefdbd46f00a7b0"},{"Digest":"0x2dc386782547d6080728215427f6f9f46b5dfef1bae23a7c593634cf54481183"},{"Digest":"0x205aaad1146099e8dbc170d6c46e758f310d84e3df5b3bc71df122902a47f7ef"}]}]}],"contracts":["0x608060405234801561001057600080fd5b50600436106101775760003560e01c8063715018a6116100d8578063a0712d681161008c578063d505accf11610066578063d505accf14610383578063dd62ed3e14610396578063f2fde38b146103dc57600080fd5b8063a0712d681461034a578063a457c2d71461035d578063a9059cbb1461037057600080fd5b80637ecebe00116100bd5780637ecebe00146102c95780638da5cb5b146102ff57806395d89b411461034257600080fd5b8063715018a614610283578063781603761461028d57600080fd5b8063313ce5671161012f5780633950935111610114578063395093511461022757806340c10f191461023a57806370a082311461024d57600080fd5b8063313ce567146102095780633644e5151461021e57600080fd5b806318160ddd1161016057806318160ddd146101bd57806323b872dd146101cf57806330adf81f146101e257600080fd5b806306fdde031461017c578063095ea7b31461019a575b600080fd5b6101846103ef565b604051610191919061129c565b60405180910390f35b6101ad6101a83660046112da565b610481565b6040519015158152602001610191565b6002545b604051908152602001610191565b6101ad6101dd366004611304565b610498565b6101c17f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60055460405160ff9091168152602001610191565b6101c160075481565b6101ad6102353660046112da565b61050e565b6101ad6102483660046112da565b610551565b6101c161025b366004611340565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b61028b6105ea565b005b6101846040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b6101c16102d7366004611340565b73ffffffffffffffffffffffffffffffffffffffff1660009081526006602052604090205490565b600554610100900473ffffffffffffffffffffffffffffffffffffffff1660405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610191565b6101846106e5565b6101ad61035836600461135b565b6106f4565b6101ad61036b3660046112da565b610791565b6101ad61037e3660046112da565b6107ed565b61028b610391366004611374565b6107fa565b6101c16103a43660046113e7565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b61028b6103ea366004611340565b610b1b565b6060600380546103fe9061141a565b80601f016020809104026020016040519081016040528092919081815260200182805461042a9061141a565b80156104775780601f1061044c57610100808354040283529160200191610477565b820191906000526020600020905b81548152906001019060200180831161045a57829003601f168201915b5050505050905090565b600061048e338484610cdd565b5060015b92915050565b60006104a5848484610e91565b61050484336104ff856040518060600160405280602881526020016114d46028913973ffffffffffffffffffffffffffffffffffffffff8a16600090815260016020908152604080832033845290915290205491906110bb565b610cdd565b5060019392505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152812054909161048e9185906104ff9086611102565b60055460009073ffffffffffffffffffffffffffffffffffffffff6101009091041633146105e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b61048e8383611112565b60055473ffffffffffffffffffffffffffffffffffffffff610100909104163314610671576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105d7565b600554604051600091610100900473ffffffffffffffffffffffffffffffffffffffff16907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff169055565b6060600480546103fe9061141a565b60055460009073ffffffffffffffffffffffffffffffffffffffff61010090910416331461077e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105d7565b6107883383611112565b5060015b919050565b600061048e33846104ff856040518060600160405280602581526020016114fc6025913933600090815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8d16845290915290205491906110bb565b600061048e338484610e91565b73ffffffffffffffffffffffffffffffffffffffff8716610877576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f494e56414c49445f4f574e45520000000000000000000000000000000000000060448201526064016105d7565b834211156108e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f494e56414c49445f45585049524154494f4e000000000000000000000000000060448201526064016105d7565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526006602090815260408083205460075482517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98186015280840196909652958c166060860152608085018b905260a0850181905260c08086018b90528251808703909101815260e08601909252815191909201207f19010000000000000000000000000000000000000000000000000000000000006101008501526101028401949094526101228301939093529061014201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206000845290830180835281905260ff8816918301919091526060820186905260808201859052915060019060a0016020604051602081039080840390855afa158015610a36573d6000803e3d6000fd5b5050506020604051035173ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614610ad4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f494e56414c49445f5349474e415455524500000000000000000000000000000060448201526064016105d7565b610adf82600161146e565b73ffffffffffffffffffffffffffffffffffffffff8a16600090815260066020526040902055610b10898989610cdd565b505050505050505050565b60055473ffffffffffffffffffffffffffffffffffffffff610100909104163314610ba2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105d7565b73ffffffffffffffffffffffffffffffffffffffff8116610c45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016105d7565b60055460405173ffffffffffffffffffffffffffffffffffffffff80841692610100900416907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36005805473ffffffffffffffffffffffffffffffffffffffff909216610100027fffffffffffffffffffffff0000000000000000000000000000000000000000ff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff8316610d7f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016105d7565b73ffffffffffffffffffffffffffffffffffffffff8216610e22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016105d7565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8316610f34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016105d7565b73ffffffffffffffffffffffffffffffffffffffff8216610fd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016105d7565b611021816040518060600160405280602681526020016114ae6026913973ffffffffffffffffffffffffffffffffffffffff861660009081526020819052604090205491906110bb565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220939093559084168152205461105d9082611102565b73ffffffffffffffffffffffffffffffffffffffff8381166000818152602081815260409182902094909455518481529092918616917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610e84565b81830381848211156110fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d7919061129c565b509392505050565b8082018281101561049257600080fd5b73ffffffffffffffffffffffffffffffffffffffff821661118f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016105d7565b60025461119c9082611102565b60025573ffffffffffffffffffffffffffffffffffffffff82166000908152602081905260409020546111cf9082611102565b73ffffffffffffffffffffffffffffffffffffffff8316600081815260208181526040808320949094559251848152919290917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b6000815180845260005b818110156112575760208185018101518683018201520161123b565b81811115611269576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006112af6020830184611231565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461078c57600080fd5b600080604083850312156112ed57600080fd5b6112f6836112b6565b946020939093013593505050565b60008060006060848603121561131957600080fd5b611322846112b6565b9250611330602085016112b6565b9150604084013590509250925092565b60006020828403121561135257600080fd5b6112af826112b6565b60006020828403121561136d57600080fd5b5035919050565b600080600080600080600060e0888a03121561138f57600080fd5b611398886112b6565b96506113a6602089016112b6565b95506040880135945060608801359350608088013560ff811681146113ca57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b600080604083850312156113fa57600080fd5b611403836112b6565b9150611411602084016112b6565b90509250929050565b600181811c9082168061142e57607f821691505b60208210811415611468577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600082198211156114a8577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50019056fe45524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220eabef41c79e988bbef5573106f3825656f6522b0a2771b005adfc744729606a364736f6c634300080a0033"],"ancestors":[]},"commit":{"proof":["0xb979a30a31cdf9bfe333a07eb94543825923801272b16a7b3907eb42427894fe","0xb1bf77f5b627010f983c127b5f3fb327489c3f432720c1747efdcaae217b3043","0xba7770e93801db137159e000011b6eb4e689beadd8e05ab6d295f4a2e8187777","0xcabd362cf637094f4872dab4abd5b217b5b025570dac723c1538f9239b117db1","0x476ee052cfcbba0973a3bde4222138868b206778ac968fdd751ba5e254904a5c","0x77142bc813666d24f36813478e8e5468058ba0cd88fe0f682ba381291f334a07","0x3ab69ac96adf0d67fa7cc929f3d3b4614efe4423f53cb27bf97f47310fbd2482","0xdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71","0xd2a36965fcbc29b76e16a79397e7a8f695876e3c47684ff3d112d418fb3a11dc","0x0000000000000000000000000000000000000000000000000000000000000000","0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b","0x52eacb6cd14c0c72f7d07ecab8959723e116ecb4c1da956f6325d68861f1bc6a"],"timestamp":1727768652}}} \ No newline at end of file +{"Beacon":{"input":{"header":"0xf9025ea085ff12048f99eafed21668fe41e3f5c32ab58a0da3c9ef4e3057f1718fefeabba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794c6e2459991bfe27cca6d86722f35da23a1e4cb97a0fdba945fc701521d1d780cc3678e9b0d117440c90ba8924b098f96d3e06385aca0f648b484e108d7ac90d9cae783b88f6963f76bb3d38ba13b22b3af8fc25aeb0aa0b7e4b4073748dcc9f35e6a1dcd90fe28fa1c5bd899fd55f823b97d746eaa8473b90100854118088109428d121218b70084219a00a14094064d80002e5029c088c2010200bc81cd012248142002d8072b151688461204128804c4807072fa5cca7402103200500808043882c688294b900ec0902400130202844060010c4409b1108213008102401e01a0411910873144000871800828c4488108c1082000deca29200303a6714911ae74067c0291640561007d05012e301021120894073bc42580050c0e0a02021481480448c90044922a488c12893a498a442b06818082331112eacd492472821c13922418631211bf0242104814429011098d00c112945c00006210afb10a0677580060010361a62102411c80c2040afe12020404056c1c19039206808367a88d8401c9c3808401205ba78466fbc16091726574682f76312e302e352f6c696e7578a0fc22b74c7a6fe4da0844b6da8e8b84ec50ec14eb1efd0aba40dee26ddf8dfe2d8800000000000000008536d318f68ba0d9f1e567661d214eb0af52916c44a49d3174a1dd6d3275ce480ea169ea8f0378830200008404e80000a03fe210a5d884689e9e507297f08be690843161fbc9efcfeb759ffa6573b2836c","state_trie":{"Branch":[{"Digest":"0x4ab8e184e859f9525a865a3d856b3a841109ec5fa01ad7d050c9bf806493c2bc"},{"Digest":"0x6baa7c1834ea673d6ff7b3d0bd05eac6d058a847dd1cfe6db9f483c4e4fa2917"},{"Branch":[{"Digest":"0xde08bf2764058279f0c2c1c779bc75bc9acd4e55f2fb77d6f80beae7b2beaa33"},{"Digest":"0x75e81861e9cf5a98289ca56b6772253ea68c276f56c7969203e4329aedd5b61e"},{"Digest":"0x4b2cac4164968696908dde9b9abd146989212dab27116dff683b1a0269ff317c"},{"Digest":"0x50b1bc361040ec568f975843620162aa8d5359469c8941401c18037f8c3fe57a"},{"Branch":[{"Digest":"0x8ca170a85cfa4821f2466ec1e5299ced318c0d16f77c127908776be11fc5bda4"},{"Digest":"0xe4fe157ea19687abd5fe0d1bb8fd359b748fe8df1d81ee928938b2f1ed988876"},{"Digest":"0x0b40acf13e3e5efe1710b9159996f7c232a655a2441b3f983fa6c42993c675aa"},{"Digest":"0xfb03fd41f144fffa0e491271bea438fb75d80f13a6ea3e08e3b1fc93652a93ae"},{"Digest":"0xbd9d56520af043fecd7d94da59fc7c5768d15ae176c39ef1abac9d8a93aac27a"},{"Digest":"0xd192b1f87aa126664dfa2c97a59c6ff4bd713d821f5270a53e5f103ea72d338c"},{"Digest":"0x19f0e8a05d3f09e588db469d5126b87b4a640de66f3283b52802c4c9bca17e1f"},{"Digest":"0x3a581b6357bb523197dafa2e79997d1ae0584d8604455ea0cb0da7c3a76e55f1"},{"Digest":"0x8f9f3748f51e6ec0dd996a0b147c1acbe8bfaad8e43bfa2134c9cad4e45d53c8"},{"Digest":"0xf9df6993333d4e8dbcba4fd62dadc1ecb0b0feadcc1002890a367841c81fad8c"},{"Digest":"0x7477e778ef99466fb75a4a7efcce294ecb6c6a671ad9d29b8c947abf347debbd"},{"Digest":"0x3bd58ef14ca7b688016c4ec9b96011587939c35820186c453e3f06d40e7a3549"},{"Digest":"0x2dc623a5a7f0016b502c0c15ea2c8b12d7aeef3a1f882a44d2dd7821028445ba"},{"Digest":"0x540fc9aeda3525fd4c3bdcf72642e0ab41e165a4829fb1678f909514096c8aee"},{"Digest":"0x52d02f7471ff137c0374bba43653562961a9752ce0c7298fb631fbc5fd192110"},{"Branch":[{"Digest":"0x05874ea022ba901c2d3bc4a24144b3f45991770d239620e85fca0846310d498f"},{"Digest":"0xbda332d0cf6544dc89b63a3b96d1980a00072e1c2407f5c151ff1dc61f94f215"},{"Digest":"0xe6548c4af231f8a84ece91fe09443fa167b6afa586298aa44f5c9de1d42f84d0"},{"Digest":"0xd79d1dd14d46778105a5abff292506caf027736cce07afc11e17898c7ed39a88"},{"Digest":"0xe85139c8ed7d2b120c17a53fedf8eaaff295412b3bebb3cd131004fcfeed24d2"},{"Digest":"0xff8cd7a7fc94ce410a001fb178a88f2f79a827aba693091209de5241d00f9bc6"},{"Digest":"0x3551497a0439f640571c034fc777fba7f6d64c536f4ada7eacc5fab53cb8574c"},{"Digest":"0x3515948c7d7ddb11ecd4eda0b326f70864ff485bf3e31478d952ef444c157196"},{"Digest":"0xd3e25ac5e646b7175a4a8bde80ecd686713a92695b9e3f2c4b9acc260040fd73"},{"Digest":"0x297e852d803fea4691bd25ae28f5cc82f21bf44d364a80220fb44c8cc8398993"},{"Branch":[{"Branch":[{"Digest":"0xdb28048328251e31b2d3328dc517f370e4661cf8ce1d5fa345faa9f51ce94f9d"},{"Digest":"0x35292568f46d6bb85536804d457243974a5ef9557fd02fdd9c414150039dd570"},{"Digest":"0x547adead9dca2a0a5a68a59b0a9e15e76e03c267aa1bade08bb046f2bd4eb073"},{"Digest":"0x27d35383b43d2bd596638fd20e8dd09a6ab63c96f90ec11c6a5249bb4f4dc2eb"},{"Digest":"0x406a49a5b08edc39727921ccee69f2d8585f1658b581cc21f65349a13be8b129"},{"Digest":"0x8e3c6433db2e2b9bb76200119bf51313cb82d97200d633f988c2222980901f9a"},{"Digest":"0x1e379c0cbf9b976f7917e8dd9cd6e59314a75cff480f6a476984321794bde9d0"},{"Digest":"0x3432854290ecfba5f449eeef9f941897a935694aad97592e7b7d9d681437620f"},{"Digest":"0x644f86d76acd1f8bb5a55119608f0fa73493b2694ef0950f1a5f673e8a7e6753"},{"Digest":"0xdf89fb84a1f4d3a48d788b242de27b80ef31b634c1321f5506a6e6158bb8dcff"},{"Digest":"0x2cf4721a99a7be43a6ed31637c001960276b54518ee3541e349aa47776752196"},{"Branch":[{"Digest":"0x8b92b40f358d29115172a38e36adc284772b7c2440b55e199e31f6d79dc52ab5"},null,null,{"Digest":"0x32e92fce0570631395ec05c62413a521ed320db25bd4a95992ccfc47c4c74a39"},null,null,{"Digest":"0xac2a299a9f99e6f0b275d38efb601ee9d1d95199b9441d46058781dd915fafe4"},null,null,null,null,{"Leaf":[[6,12,6,8,5,3,5,0,5,7,9,13,11,0,5,7,3,3,4,7,14,6,12,10,13,2,1,6,0,15,6,12,15,15,13,1,5,10,1,4,13,15,10,14,15,11,4,11,3,15,1,8,10,14,13,11,0],[248,68,1,128,160,230,193,154,246,15,58,46,205,228,200,169,39,165,222,29,111,88,180,121,74,112,127,111,57,245,32,5,244,60,157,186,100,160,173,162,122,66,135,249,23,26,77,35,164,213,151,124,154,88,61,113,137,6,246,170,45,109,127,36,115,156,57,115,6,242]]},null,null,null,null]},{"Digest":"0x924c1290a02b6550560de2f36ee20c66a31e4e2e1997333f3a8642403bbc1b9a"},{"Digest":"0xd6a2b5a75d24772a9e6c35cdccc8f51ac75818870ab706fef68c0e53b4aa5e40"},{"Digest":"0x2d6bae5f11cf0d8c8aa8858af8caa1a125595e8112eca81d2ca618d2d4758ec3"},{"Digest":"0x96066747f61459591574c48f97d9af2793f04d8258fe6eb7f4c1260cb2a9ed8a"}]},{"Digest":"0x3959262eab0df5cb0ff6ce4bb34ff9af758a35bbcbee37abe5990294e0562fc2"},{"Digest":"0xafac905211b114f21670e002795d86542bd89851a38a5aabd7face23feecf318"},{"Digest":"0x5067f564588be95a99e2f468d72b96462f212bf91b58b69e790c0199bfabb031"},{"Digest":"0xf5bd14502ac3ffb3c931e67fcdee688df840196a89e9bfc7c96fcb3f52058341"},{"Digest":"0xfec9be1378be2a793ece6049f8a10766d4289af8ee1e6aff8e748b74fb95cf16"},{"Digest":"0x4fd7ecbe4c1f9958c6da124c59d0bbea0160c56bf32bd6eb72c672f9abc44a92"},{"Digest":"0x96891f3a45ee91d99cf3e168a61019c3d8ddfa00dddd11b83a3e81c7e5e35589"},{"Digest":"0xeb6bf0cf183778116004b698ef0f5e70995dfa9478bb3255f0b29208d5f92808"},{"Digest":"0xc3caef74fad501cd0ec832b44fd6d19474b9fd2a2153b908e3e8063229b5a6d7"},{"Digest":"0xaf327e16ecc2b46b9eb8560b73410d573daef3486c108b7d4e50aec6fdd8f546"},{"Digest":"0x21fe976c00067f58fcfe4ff5aa689f7a263cf97a879debcfa88ce119a52e5d7d"},{"Digest":"0x66fd5a9d629a870d36e270e332c6bce939ed7fc2a9f2e2f334c65a630ca3ba0d"},{"Digest":"0x5e7d45a26dc6c2a9875a2d6b87710a5eebcfc5b76ff5eb6624c72bb574070dac"},{"Digest":"0x1c3f804db6dc200cd23518a4be871857ac04b8e1bcd87f743bb86a459c6c2c22"},{"Digest":"0xe18a3df3e569acca09459d2ef00b1e4fb3e8d1513cde0e83fdccd25db5d57c73"}]},{"Digest":"0xc366671e6d92e680ef4a210a57bf64f5ec14a6734eebccb548e0764dfb510f77"},{"Digest":"0xae055c2ad055a21614f87feb9de5b98dd47505c4fcdf7b2e21c2df56ec3cf21f"},{"Digest":"0xf95acfb1cf14e4a461ae9d3b1d0fb69e5d66ae663f6c0630ff618ac076be530e"},{"Digest":"0x683d9927ce5db8dc2e645132f672f1aafc98b33492b5651eb899c1dbf24eef6b"},{"Digest":"0xdb58eb782462c4b917eca16ce13ee0864835dc1b4b7350e23e75c8425b7f6c7c"}]}]},{"Digest":"0x6ea2065a22b9e4a28743909410af4e84438df3b30c65d5c6551b3daa23c03ddf"},{"Digest":"0xa90bb4ec2c14e5d97e73e4df945c70b48aff67bd883d4df40d27d6c6264ead2c"},{"Digest":"0x848517f50326c1310c81a8b21296d573663463aec5fefc4d9e982271e7ec6fb8"},{"Digest":"0x74f77d27ebf4443499625dc739201ebe485990c6f5d37cd372fdb4d4703aed60"},{"Digest":"0x9fd417c65f3999120d0f58de80bfc0823c2c903bc119c7c8e7c0dbb9dd492949"},{"Digest":"0x95ed9e9d6dcf821db4b371244e10a84de3074271034ed73dc6c39fc9209275f0"},{"Digest":"0xffad330d236e351e102d0491dd113c806acd75626efdc2482b99de37d9d9f935"},{"Digest":"0xd0810f4d6a130ba0488108eb439529a918e53898a7baa93961d73b50d8343733"},{"Digest":"0xd39a688579fc36f7d587a1818e3370722227c36417d064b3cb5f30894469fa1c"},{"Digest":"0xead73f4b6ff4f085735d27d3768f6633e55e77fdb95e65f3735466ad49fa75fe"},{"Digest":"0xd8766327db36de0ae5355848f8a6b67f0c2213b26945eb57aebc92b84f9f7922"}]},{"Digest":"0x53eed6185fe16f83d1cc83783df4c29d73f7c3327e947146516b80ecc298146d"},{"Digest":"0x9f222f105a27afbe7c7fcb3bbedb8d52bdb4d4c7620f7075335f8dbc2e3a7437"},{"Digest":"0x33ffc48352b5e1e49054a975817d65e3be60dd5540432a5c50e3a135ddbaf88d"},{"Digest":"0x2c00f8ce67a24be43f6bdef97b39da14235e5a467de13f73cbf271095212fb4e"},{"Digest":"0x148b3dc05ccc87f13ae340fb1c96766ba61db098a59f01f7eb5fd8485d8bfa08"},{"Digest":"0x8e07175d8e23ecf080bb4e0d93767b7f02aedca250a3e12f445f1081746dd715"},{"Digest":"0xa66346535aa2a93f1831efc876d3796ab4ee3024244a8a62f7a12b924fca57fe"},{"Digest":"0x686e4ca194cf710671223265d74805f409c8f546d05bd0b0c71d6a5fe1a6b2aa"},{"Digest":"0xa9ecf52d4d2a4fab791318aa1409d7dd6141b19bdc970b7dac518a38a36c557f"},{"Branch":[{"Digest":"0x5c9f0bf4f2c06981edc6726008470b40711fbf8caef652ad150134abe1db85f3"},{"Digest":"0x92c89262729b12c1ad9515f62b79ffc0dc3d94ff1ad9d5f7ad953721010ff60f"},{"Digest":"0xe72c0df3b4806f3ec32f6eb248bd6113546f406320adf76839dd643ea8f71087"},{"Digest":"0xeb2282087cbdb101b85a521159cefcf423cc5e2df2aa11cf9ecfbeaf8a50d63c"},{"Digest":"0x7b7399185826ba84e492985cae6b946017d71558d2cc95d5454aa4e58c13c5a9"},{"Digest":"0x4b2dcbac57108c17416e192460f88eb7abbeb80373e3ec22fa64196f66dee0dc"},{"Branch":[{"Digest":"0xa2d06fa9013378cd05f3d1f88c92d456222a3b1212883b17f9c352cd534937a6"},{"Digest":"0x13d2d4f767964c5163ff602f6878d742ec6bb5d7e2076696eb90630481346b29"},{"Digest":"0xe65b669649ddcba1f7ecb4499c7405587c8d2e8d7a0fab5fd4857ee290e9e87d"},{"Digest":"0x60a3751002055113465ce0873be8ba2f94305fc17c154636491dde2b57b13817"},{"Branch":[{"Digest":"0x3ad4b46e8ffeadd54a43f06d253c1af449f3f4fab55c586860e58574ef83c7de"},{"Digest":"0xd9f0c4f3eb048641b60da40bb3e04698ef4024259a6272d3a585106a112d7947"},{"Digest":"0xbcdb27f8ee5854b9c9dbb78fecb8b5a366e60aa8e5449cdbcd15478b42ff6ba7"},{"Digest":"0xbcea6fb35f13a0cb2e3c1ced578e447f245efe8c8cd460b91d40a2b75acfccff"},{"Digest":"0xe902c889bfce1a86a498c2b0fef7bb45e6e7351fbc0a1e80636bade5c19fcbf0"},{"Digest":"0xb15fdd031140fbff9543923ae6a943377b8ba839805c81887374e0284d7bee28"},{"Digest":"0x976bb7896182ca32d84e7ed1c0372a232bfc6fd7ea35f05509b4b7f13d61eea2"},{"Digest":"0xe824221567f42b24961e5b65f49951f75a99d684e6fbc765d49f53d85417d6cf"},{"Digest":"0xd12969ecd48c615cc17bd62920d1cae02c25222462bb8fd9b01b4d4738e8af72"},{"Digest":"0x46c867a53cbc216bdfb29760376ac91f7ab4216e3436a3293341a3be1a4b3f43"},{"Digest":"0x298e88aaaacfdc530341649bdde25072c7e22c13e1820328a8b0103078d5a407"},{"Digest":"0x8b9636614cf742beb60eaadc927be79cc69c23d9c12ec849dcf4a1925f471f00"},{"Digest":"0x0f399e9f72189558470f7650857b8011bc223d8c29812500fbbbde45ce0bd696"},{"Digest":"0x6b71232f57e38f8274bd82eef71920adb37722dab561844301f0d6d180af86e1"},{"Digest":"0x5d957b95e9ac7c5c603c8b42d747fb48623e88b738cb6337def740712f7e07c9"},{"Branch":[{"Digest":"0xc43d6fc9fea0f239880c36a1b147291287782f11affdab45b7e1afe690c3dd1b"},{"Digest":"0xc65bd105ecfd3bfeadff306567e1cf55c750a9e264fc47dd3e2debf472a4b6fc"},{"Digest":"0xad446ff8fb40b2dec6f173f39b99c02572bb53077a4bca461a52d4c374fbae21"},{"Digest":"0xcb77197c7ac1cd16630d91d250fe37cb6128551695e887fc2d57dea9e5274bcf"},{"Digest":"0x0bc75102a1546274bcb2ee4c28eda640c30ee349ef9ce1809d4cfcecbe8f7eec"},{"Digest":"0x1c6ba636d6a225178396da9a0a8fae8112accd1ac985da7ac9c638f80910cac7"},{"Digest":"0xedd01ef6be9c454d5189b94d26c6bf06e743a737d1525c27e359b5663fcdf1fc"},{"Digest":"0xd9111dd948d64be0b7afc654a538efa142ea32373e3ecec5aa77de9fd51902bc"},{"Branch":[{"Digest":"0x079cdf83dc79847fb2c4283aef06f28d36094f487bdb60435e087b09ee526789"},{"Digest":"0x34c966c91c89c91a0313fe3a258574c8f9b08959e3fa43e40351b4d4bab3848e"},{"Digest":"0x5ffd98f00d0b954d49b39a9cef21efece0ddfd3b62a32bdead8bd131714d7179"},{"Digest":"0x13683ced6ab57daa01993d7c98d0ca12006177c009076434762cdfd98ec0fe39"},{"Digest":"0xa47cc0a8e6b4256fcd929350dfd550e31009a2242203d0b5750625d7cd8f2051"},{"Digest":"0xea61a70cb09f7f5edb51de22253a11d3d987fb7e8f7912555c045d1c466db038"},{"Digest":"0xdbca5b81410deb3cacc46da378cdaec0d269beaa14370f511aee9da7830942f7"},{"Digest":"0x3af98cdd656e7c6575b205b86537b025fcb6acf75a474fc5ba47658b1a7f3545"},{"Digest":"0x601727bfe573710324b2cbc9d34708979870423adca4ec7ec7f6c34c63c5ee13"},{"Digest":"0xd502230a431bc09ce667db68ec89bc81a8234be75fcb5594c5480910548f737b"},{"Digest":"0x3a37c1ad7341c2bdab8ce15ae3bbc1e8f5983493f6eee5578c3df12eee5bfd3a"},{"Digest":"0x679906dd758da0848ec54a7e1a1560e6f7bc2437a96c0b74115f4ad79df6d8f3"},{"Digest":"0xe81236712d30704c3c8e97761bb155d338df6536cc5c1f376bbb505d0365c738"},{"Branch":[{"Digest":"0x132b7ea0c3174dd15a631d5d3acf7846149f8e2b0df7daf9f153a8cabb881941"},null,null,{"Branch":[null,null,null,{"Branch":[null,null,null,null,{"Branch":[null,null,null,null,null,null,null,null,null,null,null,{"Digest":"0xb85f4322dc70cb69433f1011cd7d86681e5fb3a8b8471220ebfe6ab99680e907"},null,{"Leaf":[[1,14,7,3,14,1,12,5,1,3,8,4,0,0,15,0,9,13,6,12,14,9,0,12,1,9,2,0,14,9,0,3,6,0,9,8,12,5,1,11,1,9,3,6,12,7,11,9,8,10,7,13,14,2],[248,78,1,138,2,43,218,16,14,178,56,8,171,111,160,86,232,31,23,27,204,85,166,255,131,69,230,146,192,248,110,91,72,224,27,153,108,173,192,1,98,47,181,227,99,180,33,160,197,210,70,1,134,247,35,60,146,126,125,178,220,199,3,192,229,0,182,83,202,130,39,59,123,250,216,4,93,133,164,112]]},null,null]},null,null,{"Digest":"0xaa9a1c9a362e7f26b92c7cc6bf0e260746a1f0282706486f28dec3b5ad2244a9"},null,null,null,null,null,null,null,null]},null,null,null,null,null,{"Digest":"0x324af29be87648f1e74281dfc338648b6919080973f4ad9b8fec7c4ad0266f20"},null,null,null,null,null,null]},null,{"Digest":"0xbe175a9602770eb28e02cd034e27395299c64ade95df0e07ce20b61106c6397d"},null,null,null,null,null,null,{"Digest":"0x8e4f92b107a3210fdf7c69a4004eb409bd7c5123dc04bb0e184110adc24e25c9"},null,null,null]},null,{"Digest":"0x6349fe57d19d7918d2f608fadd892f99d9c0f9244d3a048968034ae3639af0b3"}]},{"Digest":"0xd8562444dc649316b670625cedea8fb000fd929eca8d51ca9ade15d67b020b9c"},{"Digest":"0x10fa9fac3eab7a2d80440a7a99370a9c277e0773fff1fe40906c43517e9d2ca4"},{"Digest":"0x41fb7dea82b2310e064566f4f5dfdcbd8ba9ee925b3edb03b90db08fdbb9f6cd"},{"Digest":"0xb1c8c3fd9456a2e63f6092f5b1d8327812036619481386b0dd42ac2b316ff2cb"},{"Digest":"0x09d1c11b0b02ad95148037ae40fe8969b729743f680635b2b5fc09a9da8aac0a"},{"Digest":"0xf9bb7ec6cf362e2bb5700357e6d07aabfa89d9430d6cf3d9d7a82a161712800d"},{"Digest":"0xd49ef7e7667ec1b0cfc1ca1112927759f6ec7844c563e7620d65e72b14c5346d"}]}]},{"Digest":"0xe49f3e2e5231dc89cd93886ec80e191ea3f796f00b6b63986669e9f2e6891d6a"},{"Digest":"0xad268ceb7b99c464ddcd285272ec172f8478a850cc622815370dd113183dd13b"},{"Digest":"0xf6c59ac04e1d9c65c7f45273a451000d75565996bd7cbda145b134bf727c00b2"},{"Digest":"0x6b3655472e24d9f758bc15455b7c847a6d778632ac9845e3abc9c8de92ebe6fd"},{"Digest":"0xa0ba645ae6280c832fbf24d19cbeb1e7f647606551b5ec587b4940408a2ad9df"},{"Digest":"0x4ad8b330f32bbb7698204b8265447ecb2d439de315dab029b638052cce48eb81"},{"Digest":"0x9adb650231bc464e56a148cd7b8a4a2c541c23574b943d20d8ed18d80f951ba4"},{"Digest":"0x1e6a8f9877462faddd7bb90b51347751aa7a80cb1e970cfef78b106d351c3072"},{"Digest":"0x5d3caaa7ddf8e955dd9910496d9a35f059ba165e223ec3139e7e312dbdfe0050"},{"Digest":"0xdb462a19ddfdea24451f5a4e27a5594b583d8ee41bf6a0b78e80ee671bb3cf38"},{"Digest":"0x1c4f97704727e4bd58ce52a433c7b10b6527533d2aefe75e774d3e73b5b34f97"}]},{"Digest":"0x302d9354b573a429d22d0c486aec9cf7de7500b4bcf98e73c3ac697543d2490f"},{"Digest":"0xa57d3b9733b3df7dda1967622638a84bea14a65f04fd11a0ab8afb25256770fd"},{"Digest":"0x0ab81d4576fa942bb6a84bab248ff6e45c2360b3c38f0705ccb02c47486c657c"},{"Digest":"0x513866db1cbcb67bb09e4568ee3334725c5d835b74225396488f1775f687760a"},{"Digest":"0x4e5ec4495d7e6adad9077d30ccb3d480721ec9b74e5a0561cb91c610e6f0989b"},{"Digest":"0x260c9262f5d66c4f57ee841d26ddc9080681467b5a4d95d23c0d8b4a46ac7b09"},{"Digest":"0xb811b7ee8dd06b4d996f07f1923877235432b9eb7e817211d78ee671b0d1ebbc"},{"Digest":"0x3fb08c49ff0564b3305e4554996e0129296773ad62545673ce2e2607992b40d1"},{"Digest":"0x04be653bc9aefc3dba9fa1cd73efb7c4b945b00ca184410e956e4f091abc46cb"}]},{"Digest":"0x8f020a1a1c3cae0a59ad231da00345ae089cf235d42665b232699abf9f14a49e"},{"Digest":"0xd5fc482fe9cf579960cfa7e737640e77a33b7ca5c8d84f5948df8d89ac361373"},{"Digest":"0x175571d3e3ad1606f1df4051d0030b16cbd569493c32eb2bcf134600c4fba39e"}]},"storage_tries":[{"Branch":[{"Digest":"0x56544afefeed5e361e4df3e2d663bb228daf6f3a073afd6c995327f7bee32cb7"},{"Digest":"0x591c9d0acd182840738019fedc864367512620f91ec23bcedbed07f99a476923"},{"Digest":"0xbd4273a3fc00e2a5c700caf4a2775197a5bd17bad1abbfd74d0c87f904a44976"},{"Digest":"0x4e45197d666cd89f175f4eb83d79d2d0a3d51c4d9ba623fc2b0fa1989f1e3a31"},{"Digest":"0x32cf5aa9660540fb95834497a5bd687c45c287de74c7d188152e52e1d7946c18"},{"Digest":"0x4062f7f555550a5035f6651105bbbd665671f33c9309bf2dc6c8b67b8168141e"},{"Digest":"0x7939f313928fee8b56cd07d57974f4d55e1f340d93f25197ed354a578acf9d7a"},{"Digest":"0x35afb0b9306eb976575d65789e19510628f9405a8f36daac79a6c8f037de5a5a"},{"Digest":"0x9097fea8996befb8a4126d3798cf79a6c7e0d1336f5ac36bfbe652137b305f82"},{"Digest":"0x8d857ba6ee988703b647ac79283cad8d382b4754c60be47d2ab80db2e1aaa377"},{"Digest":"0x3d7d2abf687c278ca3c9fa351f2e6bbed471a412b59b578e75e789988797b09a"},{"Digest":"0xb72f8830126db2e2b254db43a787c85e94bb449585447a0523344fcb4c6f2836"},{"Digest":"0x32562672655a89e13bfded3af8f56ece0e4ac753e60ce7172d84b4fbf8cc40bd"},{"Digest":"0xc33c225e5e9ecb7b02c074d758e2500674ea0a02534433dcdeb0a137d96be176"},{"Digest":"0x46c6e2573d95970c5068685b56eebb28b5d6506eb486235c010198af9d474fb9"},{"Branch":[{"Branch":[{"Digest":"0x02073d18333e691bddb8642ca82b732db6415c9f84a1149b3bb710824214ceb2"},{"Digest":"0x31d5bc9659e75a99e973418b4794c0d9241a3482d6359cb11b0753d0e460a269"},{"Digest":"0xe79421201d09eeb52b36e427967ed621d245fb04769487d7ebdc5cf7d44b17b4"},{"Digest":"0x18ef63217fc35b0ec780d2427113b6e35a714c4c17b27993cf6227b551912f58"},{"Digest":"0xa53a1b7d3f70c40201345314bf7fb4446bcf79dde781102143705d6b66486e53"},{"Digest":"0x007a444b6e07e59e910751aca367d5fb2d4db3126fe9b9bfae05a7f652cac56f"},{"Digest":"0x460db8fc9fcb2d58cc58997614c5a6545b8c4ea7342fef05768a5691ca7fe5ca"},{"Digest":"0x35ec4099628336dd7f3a13caa20a54d2611b4d8b97a112ff357e0eb0541f189f"},{"Digest":"0x49355ad2e8f7bf8b6ce8084088aa894c07ded44b315695aa1b3fb3551d35d4fb"},{"Digest":"0x83638c0eed723390afd17ac07ad64aa3f298affe5078a3ec49e9b7b463c12fed"},{"Digest":"0x90424abf55dbe91f187e2eab0a91771c4909ee989dddd2263c5ffd8353e44a91"},{"Digest":"0xf708a9096c48c1baed6a8cd3f9409b1863eae8276801a89a6152806947f90a7d"},{"Digest":"0x467c6d27ad319df67a07e54aa5ba51d914c1191c6f179e045ba5e4b1362e1265"},{"Branch":[{"Digest":"0x957c5ebf39508dce06b519f3357407ce9b0c7e325a5b5baf20356802119e2a1d"},{"Digest":"0xdcdcda02bab51aee6cec341859880c7d3a74b2a708c6837a283e9140d742ae71"},{"Digest":"0xfe878f6d7851d2c4a89a747005f6ec12211eea53845502d577358c38d99b0540"},{"Digest":"0xba01139006d0b39ceae595d8736eeb0614536ec331df968bb7a87726d663619e"},{"Digest":"0xd835f0fb96ed233d45a950b9374600896dce6e9f9e9f415e16f56d58db6328ea"},{"Digest":"0x763bc0283a452d3e45a3c40bc33ace9c3bf8327a4f98f3939b6fb10797692ea9"},{"Digest":"0x926a4be03b7bfb0176a0a07d1737c8bf6d7a73d1d02744a1bf26736c3a853227"},{"Digest":"0xbff83b63f63ff94b661fb0a7c3cce98b8407f55097a90e1af5351b21f649d32c"},{"Digest":"0xe0e716a063b31091e183787523f5532b2dc7ab69a1dd66cc90cfb116ad477d20"},{"Digest":"0xfe7d2af4a9f50363f9fc87756d737bd5ea2ce08079a592af54285923e44cbedd"},null,{"Digest":"0xb883893ad62f19b1ade0ead65ab810ea10bc653dc37b2d6e9536ddffab16c44b"},{"Digest":"0x1a578cb4375a74230fc289891bc27480edb2b7b162f8d0636ffd9cffa155cb06"},null,{"Digest":"0x1ab003882db00b52c3298b9f8e5377e64facdbd98d8a31376d7f4b4f7014e11b"},{"Branch":[null,null,null,null,null,null,null,null,{"Digest":"0xf0ec532af391e6dc77f2c9867afce87e39293059a5f8ddf2b21b38d8e4dd23b6"},null,null,null,null,null,{"Digest":"0xb92295774b00d67bfc53715b07b142a21c554b7f1cce914aefc2157459fc289c"},null]}]},{"Digest":"0x45b01213c9e56a5527cbb6ac2dee8cff756ebbec4f9a4106794a62d73e95bddb"},{"Digest":"0xb00a95f416324179cea6c4a2af4bfb813a2925aeb02da845510630a1ecab965d"}]},{"Digest":"0xd2b6f5aa79e4367be1acedfb774fb31ff72d741d7ba63f0fd54057125c6bd4d4"},{"Digest":"0x6d8c5078e4f7cd7313e3a7e93313158a1eb2f61178b4a3a7e955fff12d92bffb"},{"Digest":"0x89eb39899f8e94c8fc33d97a00bd24c9d9b8291595724ec90f94ca777fb5140f"},{"Digest":"0xc24898b9b1d020be564e759e1a8e6ab071685d8f0f6ddedf7dc40f57d5769c74"},{"Digest":"0x54dfd5d63e4d92ae013b4cc1bf1d9cc1bc275a5b23341424a003b24d9bf80ec8"},{"Digest":"0xa71719c64486e2adab39b2ad208f08d3f5775b8daa5cd2c06ec1f9d6903655ab"},{"Digest":"0xdef3321462d8cb9948d0c4d4de63e604b11cb352b70781051b33f5ac02453ca0"},{"Digest":"0xda0b890c9c5ca63b53939d3fcaf8f663a16d0c64866f0730dafc061273030532"},{"Digest":"0x83780e60779372f92ba09f2008d94dd81d1e61703de74d3e2de72ab475ee4a18"},{"Digest":"0x3875c5b603e498fe47a7dc24ecba5fffc29492d74a453ea6bb80a82c3de6e2b1"},{"Digest":"0x21fbc721597b9e854b0f29ae0e5ee78c039bcbe2bc954d9a2f2f7b80659700d6"},{"Digest":"0x4ddf483433da88aca29480ee15efb5ed56468717f55be6f811f55f3b720ff5b1"},{"Digest":"0xc51c210305336706d9e14799b45ca38cf015518ca5aed8698eefdbd46f00a7b0"},{"Digest":"0xd530cfea8782e19146a8865daae4f1a3c6ddb6e23fbb0cddb0a7131fbdd5eccc"},{"Digest":"0x45e57bb66f6807562ca3a128a38bdb69e6a736f9d0216e76912eb0f2fcef21ee"}]}]}],"contracts":["0x608060405234801561001057600080fd5b50600436106101775760003560e01c8063715018a6116100d8578063a0712d681161008c578063d505accf11610066578063d505accf14610383578063dd62ed3e14610396578063f2fde38b146103dc57600080fd5b8063a0712d681461034a578063a457c2d71461035d578063a9059cbb1461037057600080fd5b80637ecebe00116100bd5780637ecebe00146102c95780638da5cb5b146102ff57806395d89b411461034257600080fd5b8063715018a614610283578063781603761461028d57600080fd5b8063313ce5671161012f5780633950935111610114578063395093511461022757806340c10f191461023a57806370a082311461024d57600080fd5b8063313ce567146102095780633644e5151461021e57600080fd5b806318160ddd1161016057806318160ddd146101bd57806323b872dd146101cf57806330adf81f146101e257600080fd5b806306fdde031461017c578063095ea7b31461019a575b600080fd5b6101846103ef565b604051610191919061129c565b60405180910390f35b6101ad6101a83660046112da565b610481565b6040519015158152602001610191565b6002545b604051908152602001610191565b6101ad6101dd366004611304565b610498565b6101c17f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60055460405160ff9091168152602001610191565b6101c160075481565b6101ad6102353660046112da565b61050e565b6101ad6102483660046112da565b610551565b6101c161025b366004611340565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b61028b6105ea565b005b6101846040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b6101c16102d7366004611340565b73ffffffffffffffffffffffffffffffffffffffff1660009081526006602052604090205490565b600554610100900473ffffffffffffffffffffffffffffffffffffffff1660405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610191565b6101846106e5565b6101ad61035836600461135b565b6106f4565b6101ad61036b3660046112da565b610791565b6101ad61037e3660046112da565b6107ed565b61028b610391366004611374565b6107fa565b6101c16103a43660046113e7565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b61028b6103ea366004611340565b610b1b565b6060600380546103fe9061141a565b80601f016020809104026020016040519081016040528092919081815260200182805461042a9061141a565b80156104775780601f1061044c57610100808354040283529160200191610477565b820191906000526020600020905b81548152906001019060200180831161045a57829003601f168201915b5050505050905090565b600061048e338484610cdd565b5060015b92915050565b60006104a5848484610e91565b61050484336104ff856040518060600160405280602881526020016114d46028913973ffffffffffffffffffffffffffffffffffffffff8a16600090815260016020908152604080832033845290915290205491906110bb565b610cdd565b5060019392505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152812054909161048e9185906104ff9086611102565b60055460009073ffffffffffffffffffffffffffffffffffffffff6101009091041633146105e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b61048e8383611112565b60055473ffffffffffffffffffffffffffffffffffffffff610100909104163314610671576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105d7565b600554604051600091610100900473ffffffffffffffffffffffffffffffffffffffff16907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff169055565b6060600480546103fe9061141a565b60055460009073ffffffffffffffffffffffffffffffffffffffff61010090910416331461077e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105d7565b6107883383611112565b5060015b919050565b600061048e33846104ff856040518060600160405280602581526020016114fc6025913933600090815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8d16845290915290205491906110bb565b600061048e338484610e91565b73ffffffffffffffffffffffffffffffffffffffff8716610877576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f494e56414c49445f4f574e45520000000000000000000000000000000000000060448201526064016105d7565b834211156108e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f494e56414c49445f45585049524154494f4e000000000000000000000000000060448201526064016105d7565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526006602090815260408083205460075482517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98186015280840196909652958c166060860152608085018b905260a0850181905260c08086018b90528251808703909101815260e08601909252815191909201207f19010000000000000000000000000000000000000000000000000000000000006101008501526101028401949094526101228301939093529061014201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206000845290830180835281905260ff8816918301919091526060820186905260808201859052915060019060a0016020604051602081039080840390855afa158015610a36573d6000803e3d6000fd5b5050506020604051035173ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614610ad4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f494e56414c49445f5349474e415455524500000000000000000000000000000060448201526064016105d7565b610adf82600161146e565b73ffffffffffffffffffffffffffffffffffffffff8a16600090815260066020526040902055610b10898989610cdd565b505050505050505050565b60055473ffffffffffffffffffffffffffffffffffffffff610100909104163314610ba2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105d7565b73ffffffffffffffffffffffffffffffffffffffff8116610c45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016105d7565b60055460405173ffffffffffffffffffffffffffffffffffffffff80841692610100900416907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36005805473ffffffffffffffffffffffffffffffffffffffff909216610100027fffffffffffffffffffffff0000000000000000000000000000000000000000ff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff8316610d7f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016105d7565b73ffffffffffffffffffffffffffffffffffffffff8216610e22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016105d7565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8316610f34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016105d7565b73ffffffffffffffffffffffffffffffffffffffff8216610fd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016105d7565b611021816040518060600160405280602681526020016114ae6026913973ffffffffffffffffffffffffffffffffffffffff861660009081526020819052604090205491906110bb565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220939093559084168152205461105d9082611102565b73ffffffffffffffffffffffffffffffffffffffff8381166000818152602081815260409182902094909455518481529092918616917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610e84565b81830381848211156110fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d7919061129c565b509392505050565b8082018281101561049257600080fd5b73ffffffffffffffffffffffffffffffffffffffff821661118f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016105d7565b60025461119c9082611102565b60025573ffffffffffffffffffffffffffffffffffffffff82166000908152602081905260409020546111cf9082611102565b73ffffffffffffffffffffffffffffffffffffffff8316600081815260208181526040808320949094559251848152919290917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b6000815180845260005b818110156112575760208185018101518683018201520161123b565b81811115611269576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006112af6020830184611231565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461078c57600080fd5b600080604083850312156112ed57600080fd5b6112f6836112b6565b946020939093013593505050565b60008060006060848603121561131957600080fd5b611322846112b6565b9250611330602085016112b6565b9150604084013590509250925092565b60006020828403121561135257600080fd5b6112af826112b6565b60006020828403121561136d57600080fd5b5035919050565b600080600080600080600060e0888a03121561138f57600080fd5b611398886112b6565b96506113a6602089016112b6565b95506040880135945060608801359350608088013560ff811681146113ca57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b600080604083850312156113fa57600080fd5b611403836112b6565b9150611411602084016112b6565b90509250929050565b600181811c9082168061142e57607f821691505b60208210811415611468577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600082198211156114a8577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50019056fe45524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220eabef41c79e988bbef5573106f3825656f6522b0a2771b005adfc744729606a364736f6c634300080a0033"],"ancestors":[]},"commit":{"proof":["0x77935a302d194a1262ae6923113ae86db0e6e19ce213f5617d9d4cc2f626110c","0x3090bafc416d3cc1a56b97d38a63efea01ba1eba02242b606525baa463529002","0x749c8ed86568b30f9629d0172e0e7fe26f58413cb83c871b6c48a41fb11131d4","0x246945f975282f5ec2e8f59581df1897c3e419d5b4110bd6268b0286b5e5dd96","0x91dc9f8f1e388ec93c8d3b2176d5587aed5fa9643b121f2d0d5e4cb08d3cd188","0x948527f1b9cf52bbcb126333f05a197a1720b0e5c795cd5355210148737ed7d0","0x7e58387dc24ef528448144386ea433a8ce1d476a98fb225c054c5a54d526729d","0xdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71","0x5838724cb04e7784e11f296abfe83c4ea9cb7588dc627b62fca673e2a65c6645","0x0000000000000000000000000000000000000000000000000000000000000000","0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b","0x191fef23877fcdda042451463bb3c0356c9e9cf3ffa92bd6d4be44ddcdb45a01"],"timestamp":1727775084}}} \ No newline at end of file diff --git a/steel/testdata/corrupt_header_beacon_commitment.json b/steel/testdata/corrupt_header_beacon_commitment.json index cafb967e..b49577aa 100644 --- a/steel/testdata/corrupt_header_beacon_commitment.json +++ b/steel/testdata/corrupt_header_beacon_commitment.json @@ -1 +1 @@ -{"Beacon":{"input":{"header":"0xf90251a0f565af85fc1b8f48ea962eb40da64a51a4a97900ea47e8dbf35e83ca6cd9e237a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347941102e22ff1f6f56ed1b2e042959b5ee90c62a29ca0fb8c3b7efa0c5c578d57be9f9ec5b3e376375e00b8ba38ae5f2f321e4006763da0fc31b3313ef6f68b774aa3c555ff1bb983a9b1c1ded17e8180bee241d7c9376ba0eb7c0cf0a899811f7413fdbcd49ca392eff92a77c9e8af5d3413924feadd5bfeb90100c0010a1c096060088a1a249a4d1020070501c1210407a03043800c0c48820f8a0502e118408002940429102090142390479000100000266630221084402963841001484009ae0a274811262a0002404805040806020003a660038812884825a3424302001638a4490104866014200d060e0801c000440880041418185021c8004a2a27c00c98758fe0096000812104422050a501840480100a53a04804619120b32828130140ed460a44c09e0134006e240023d9b800025084f18402320a4281a1005c021000123c551106a58e06285250041002c01d8201010704105084621800540c05434020303a8a107020024a58041800004858024445210a0488013106808367a6b78401c9c38083cbf0908466fba84c856c616d6564a0fb4ed57d247c487289b506521f4f0672ade191cb7f469248cab1412caf4b83c5880000000000000000854f1d827829a03ba0c9436d3a1a40d4ec87057d5836e1cf5627743a357bde28269730fc37ec958304000084056e0000a034057321ab98a1d72a4c94631a7d04532f45de7893b6b60423cdd8ef548edc0a","state_trie":{"Branch":[{"Digest":"0x7c145cb7825aae7bf86d86420403faf0395f2d9af07519cf3c13672f9605484c"},{"Digest":"0xfa22a1090a6d81ced3d6868089e01b227f79740804d86b6bb213170cde21d332"},{"Branch":[{"Digest":"0xc5188383a259a0a14f37c295c8eebfb2bac841525ae34d5c17047b8782276f1a"},{"Digest":"0xaa3f3fa1ac9b60ab0b8225608d8da1ebbe8724b3a61e1a6670bfb908f28c8519"},{"Digest":"0x0517e7f63f1476498600124fee2d6a366b66285ebf01794448ad7e012a5f1f04"},{"Digest":"0x9ec9733ef0c9ba5e2fdb5c3a28c306117380765bc5938fbe9e3af3735293ceb9"},{"Branch":[{"Digest":"0xda6933a333a5d49ad5b89c9f043014afc77b86397be0798d5572a07e27902ebf"},{"Digest":"0x4d76980c2d51e20b6458f2a328ed615738800deb761a34555e77171cc3b87964"},{"Digest":"0xbbd17c46cf24bb2907b620fea1f9976e41b53f08d6382bf3e2b0970d5048af3c"},{"Digest":"0x779bd2e0e610fe38ea326abbe53bdc01d27f4b037348ade97f423757741ea6f2"},{"Digest":"0xa3e59ad51326d36add622f74f3d2174e00737dcae7e15b6ea5381d7974d317cd"},{"Digest":"0x818acbf6242f9eb099a0ad112b9e28c71100383482c573945676d849b4c61edb"},{"Digest":"0x47460468328d5d3614817d2c624b14299fa250e21911cf3280825c7e603e97ed"},{"Digest":"0x0934bf754a58694309deb24bdb95e88970daea0b6f320012e36bfa69e87d6005"},{"Digest":"0x38b95388ee5153f4eaa54dc91ee9ccffe1b50b67926f891075701dc91d614300"},{"Digest":"0x230af1125641692ddec8d4f5c4dfff36830d571c38c24dc3df4f53ba8a0d0a81"},{"Digest":"0x069eb5b2719ef3170d7c1fb5dfab3f317757a61e96c20dfcbbda7588e99ae21a"},{"Digest":"0xe403f3f6cbd7af30f292736030aeb8b734c6b1826902b543b914f6a6832cda28"},{"Digest":"0x75ab6daa631d5c3a66ec9e3652dbbbf40f37dc0aa7e640523bd6cb0e58260316"},{"Digest":"0xf0110f9b8bd8bbcc2ae8a4f3551f2da40d7fe2c58e59a13316504b46bb94ff03"},{"Digest":"0x52d02f7471ff137c0374bba43653562961a9752ce0c7298fb631fbc5fd192110"},{"Branch":[{"Digest":"0x05874ea022ba901c2d3bc4a24144b3f45991770d239620e85fca0846310d498f"},{"Digest":"0xbda332d0cf6544dc89b63a3b96d1980a00072e1c2407f5c151ff1dc61f94f215"},{"Digest":"0xe6548c4af231f8a84ece91fe09443fa167b6afa586298aa44f5c9de1d42f84d0"},{"Digest":"0xd79d1dd14d46778105a5abff292506caf027736cce07afc11e17898c7ed39a88"},{"Digest":"0xe85139c8ed7d2b120c17a53fedf8eaaff295412b3bebb3cd131004fcfeed24d2"},{"Digest":"0xff8cd7a7fc94ce410a001fb178a88f2f79a827aba693091209de5241d00f9bc6"},{"Digest":"0x3551497a0439f640571c034fc777fba7f6d64c536f4ada7eacc5fab53cb8574c"},{"Digest":"0x3515948c7d7ddb11ecd4eda0b326f70864ff485bf3e31478d952ef444c157196"},{"Digest":"0x28cff3351737e92436aa9ccc4fc5bbca341513157aa4885645bbb838ba6c419a"},{"Digest":"0x297e852d803fea4691bd25ae28f5cc82f21bf44d364a80220fb44c8cc8398993"},{"Branch":[{"Branch":[{"Digest":"0xdb28048328251e31b2d3328dc517f370e4661cf8ce1d5fa345faa9f51ce94f9d"},{"Digest":"0x35292568f46d6bb85536804d457243974a5ef9557fd02fdd9c414150039dd570"},{"Digest":"0x547adead9dca2a0a5a68a59b0a9e15e76e03c267aa1bade08bb046f2bd4eb073"},{"Digest":"0x27d35383b43d2bd596638fd20e8dd09a6ab63c96f90ec11c6a5249bb4f4dc2eb"},{"Digest":"0x406a49a5b08edc39727921ccee69f2d8585f1658b581cc21f65349a13be8b129"},{"Digest":"0x8e3c6433db2e2b9bb76200119bf51313cb82d97200d633f988c2222980901f9a"},{"Digest":"0x1e379c0cbf9b976f7917e8dd9cd6e59314a75cff480f6a476984321794bde9d0"},{"Digest":"0x3432854290ecfba5f449eeef9f941897a935694aad97592e7b7d9d681437620f"},{"Digest":"0x644f86d76acd1f8bb5a55119608f0fa73493b2694ef0950f1a5f673e8a7e6753"},{"Digest":"0xdf89fb84a1f4d3a48d788b242de27b80ef31b634c1321f5506a6e6158bb8dcff"},{"Digest":"0x2cf4721a99a7be43a6ed31637c001960276b54518ee3541e349aa47776752196"},{"Branch":[{"Digest":"0x8b92b40f358d29115172a38e36adc284772b7c2440b55e199e31f6d79dc52ab5"},null,null,{"Digest":"0x32e92fce0570631395ec05c62413a521ed320db25bd4a95992ccfc47c4c74a39"},null,null,{"Digest":"0xac2a299a9f99e6f0b275d38efb601ee9d1d95199b9441d46058781dd915fafe4"},null,null,null,null,{"Leaf":[[6,12,6,8,5,3,5,0,5,7,9,13,11,0,5,7,3,3,4,7,14,6,12,10,13,2,1,6,0,15,6,12,15,15,13,1,5,10,1,4,13,15,10,14,15,11,4,11,3,15,1,8,10,14,13,11,0],[248,68,1,128,160,103,110,5,68,138,220,242,138,231,10,154,43,183,126,53,138,156,104,218,216,109,165,179,226,101,51,240,54,135,15,129,195,160,173,162,122,66,135,249,23,26,77,35,164,213,151,124,154,88,61,113,137,6,246,170,45,109,127,36,115,156,57,115,6,242]]},null,null,null,null]},{"Digest":"0x924c1290a02b6550560de2f36ee20c66a31e4e2e1997333f3a8642403bbc1b9a"},{"Digest":"0xd6a2b5a75d24772a9e6c35cdccc8f51ac75818870ab706fef68c0e53b4aa5e40"},{"Digest":"0x2d6bae5f11cf0d8c8aa8858af8caa1a125595e8112eca81d2ca618d2d4758ec3"},{"Digest":"0x96066747f61459591574c48f97d9af2793f04d8258fe6eb7f4c1260cb2a9ed8a"}]},{"Digest":"0x3959262eab0df5cb0ff6ce4bb34ff9af758a35bbcbee37abe5990294e0562fc2"},{"Digest":"0xafac905211b114f21670e002795d86542bd89851a38a5aabd7face23feecf318"},{"Digest":"0x5067f564588be95a99e2f468d72b96462f212bf91b58b69e790c0199bfabb031"},{"Digest":"0xf5bd14502ac3ffb3c931e67fcdee688df840196a89e9bfc7c96fcb3f52058341"},{"Digest":"0xfec9be1378be2a793ece6049f8a10766d4289af8ee1e6aff8e748b74fb95cf16"},{"Digest":"0x4fd7ecbe4c1f9958c6da124c59d0bbea0160c56bf32bd6eb72c672f9abc44a92"},{"Digest":"0x96891f3a45ee91d99cf3e168a61019c3d8ddfa00dddd11b83a3e81c7e5e35589"},{"Digest":"0xeb6bf0cf183778116004b698ef0f5e70995dfa9478bb3255f0b29208d5f92808"},{"Digest":"0xc3caef74fad501cd0ec832b44fd6d19474b9fd2a2153b908e3e8063229b5a6d7"},{"Digest":"0xaf327e16ecc2b46b9eb8560b73410d573daef3486c108b7d4e50aec6fdd8f546"},{"Digest":"0x21fe976c00067f58fcfe4ff5aa689f7a263cf97a879debcfa88ce119a52e5d7d"},{"Digest":"0x66fd5a9d629a870d36e270e332c6bce939ed7fc2a9f2e2f334c65a630ca3ba0d"},{"Digest":"0x5e7d45a26dc6c2a9875a2d6b87710a5eebcfc5b76ff5eb6624c72bb574070dac"},{"Digest":"0x1c3f804db6dc200cd23518a4be871857ac04b8e1bcd87f743bb86a459c6c2c22"},{"Digest":"0xe18a3df3e569acca09459d2ef00b1e4fb3e8d1513cde0e83fdccd25db5d57c73"}]},{"Digest":"0xc366671e6d92e680ef4a210a57bf64f5ec14a6734eebccb548e0764dfb510f77"},{"Digest":"0xae055c2ad055a21614f87feb9de5b98dd47505c4fcdf7b2e21c2df56ec3cf21f"},{"Digest":"0xf95acfb1cf14e4a461ae9d3b1d0fb69e5d66ae663f6c0630ff618ac076be530e"},{"Digest":"0x683d9927ce5db8dc2e645132f672f1aafc98b33492b5651eb899c1dbf24eef6b"},{"Digest":"0xdb58eb782462c4b917eca16ce13ee0864835dc1b4b7350e23e75c8425b7f6c7c"}]}]},{"Digest":"0xad9e11a9e3701f33b01ae9d8e77e7398311eb0bf06cc3c5e88b9d95982ef6463"},{"Digest":"0x93c454b885f23cd9bf1c510ad242e29fad9eb479fb3d9138d5b56b3048319273"},{"Digest":"0xff977e315ebb23db12788b43dfd61cbaf638a70924828ea54145b6e0e47f90d5"},{"Digest":"0xa90f8aeaab76bca37f919e2116935261db761ead1e077aaa6b777c12569f584b"},{"Branch":[{"Digest":"0x78a51a98a939dfac3ef54e1572230e0803c297dc3526e58f93e8d6400af983af"},{"Digest":"0x57e829d9c21be34752dbcdeb90994f7d3041a02a40a7a772ce7578200d434a11"},{"Digest":"0x7d39d89a71ba761224f95b54ce82dc791d6f688dfa208527176f4e09e0cdc092"},{"Digest":"0xc1394f74cb150871a9eb904897cb9be245d4b240d70280cca48a9e86501e5494"},{"Digest":"0xdef9314b6d5a5ec58f4b349070e8c77be41e30dbced326aa6f120e1c5fc9198e"},{"Digest":"0x52dfaa5578d5164f3bd23bde2618f522f5ad2bb7001e542318fb09091299ccc2"},{"Digest":"0x7cda00aa77cd99719f80426de664e74b3e321a6aae4f15d858921fc904dd930b"},{"Digest":"0x338a4718b319d7bf8bff6cbe15ac70baf1234f45b9978bcca4ef5524871b64ad"},{"Digest":"0x354d8e86498a01ed6fdd7c8565b95434cc0d76be1e93bfc7e6e340dca2651082"},{"Digest":"0x854f7ffb29c2d34f1d43e8028ce965636734ec7e1adea268acf8de339b2e66ff"},{"Digest":"0x72231de65deb76d26846fedcf208f18e508198b38a22168c5da52ffee42e5605"},{"Digest":"0xc41e55b2aa11df1ffbd77b8f0f4bdb96aca56adf4f6511930bf1d3da276f898d"},{"Digest":"0x4bc0cedfa0d7f328c0992f388dc1fed34eafa005d77f02fb296d609376a7a4b4"},{"Digest":"0x44f7bcb6a73e0f151ccbe24922a48c113f36744f2d88b2f4e48f54f770d0ac9a"},{"Digest":"0x656b5f2d56ac96deff96c8b3a25467524a5fe2833c70ac56e8f7f60e66850636"},{"Branch":[{"Digest":"0xc39ec523f8542f0084a6e65b885a03dd5a5fe475e7cb5450e207fe4977152c70"},{"Digest":"0x74fca0b8a1f554d0fe2576468cd2dd20647e62bd1c80a1549d41365b970b6050"},{"Digest":"0x7fc12c21fbc5e4d727ce552720da3e288f4f09b57e273d98c7872236f525fe5a"},{"Digest":"0x100ae54659a98a66d90edc8204ac461af7526e2a3c303563dcb55f027ac6e84f"},{"Digest":"0x961ae97d4b456700bc496b5b6405e8f58097cf2bdf529e213cb7e80533d2a5b7"},{"Digest":"0x0d91302a9a48437a6eb5b795e15bfb3aec78c7361a676720e25c75cb05f743f7"},{"Branch":[{"Digest":"0x89f89128182d3674093ae3f197cfb83f33657b8a30d1b2a91cbdb93c4d9aafe6"},{"Branch":[{"Digest":"0x347c03ff92d9c3e6fbb7dbbca0b37e473f893f009e316f82a5d335c87908fc08"},{"Digest":"0xa5bc6a596176027b0fd39bf8d9bad3630cabf35c20e02c3fe105f3f9a351470a"},{"Digest":"0xc60952ce285759951d7182dc640e1666bd8bff64bbfcd63c138cd1fb1a8bcf0d"},{"Digest":"0xc248743cff607ebc8901d09ad2db1d64ccbdb926cd1ca70abbb065c7fb3aa1db"},null,{"Digest":"0x229f9dfb8922aaab5c9aeaa8511ee3ed84889de7632daa257615834a62578c1d"},{"Digest":"0x5e88c447ed7093cf393fb93bcf17696c7ece03fc75364ba3b653937cd2418a15"},null,{"Digest":"0x7768f73b73de0a46bacac3f3e10aa876d732ea59729a016a6811ce74e3c6f025"},{"Digest":"0xb4ae06aba30beb5c97b55fdd25f82ab988f382c5d05be7525964d94bafb1a856"},{"Digest":"0x63a6ce8d8efa5b57b1d071636ee65a9b7e9805f9510d6cb17259281ff3e3a030"},{"Digest":"0x9fb3eb7594e42b4fdb0b50de6def1d8d76f151db330fa818f7c42c1041a1148d"},{"Digest":"0x1137b42985bdf9d6f34ab51ef1f6e0da66833f31ee63230d650779e512d87ed3"},{"Digest":"0x2626491ebb0eb4413ad79e4b47da9113262e9463d11587a04012e8c8d4c9ac6d"},{"Branch":[{"Leaf":[[11,4,4,7,8,0,2,9,10,7,14,14,9,2,0,15,2,11,0,8,6,7,15,7,13,4,13,3,3,11,3,3,9,10,1,15,7,10,7,14,10,8,9,10,13,9,7,6,8,8,0,2,6,8,9,0,6],[248,79,130,26,116,137,1,149,233,64,88,159,170,64,11,160,86,232,31,23,27,204,85,166,255,131,69,230,146,192,248,110,91,72,224,27,153,108,173,192,1,98,47,181,227,99,180,33,160,197,210,70,1,134,247,35,60,146,126,125,178,220,199,3,192,229,0,182,83,202,130,39,59,123,250,216,4,93,133,164,112]]},null,null,null,null,{"Digest":"0x76a199fdb84a7d3216593844ab7691d6a8571d6088911150a3679b9a36487ca0"},null,null,null,null,null,null,null,null,null,{"Digest":"0x8330bc24c00b152e54d9364a775b6ecab5c829c59272fd84d7bb351366d15739"}]},{"Digest":"0xd1da7c3b76a704b6af19637a7b7d7a8f895f043faf477fb20660c28c92b6e53a"}]},{"Digest":"0x2000582e987ddfadb55de9d8c04a5ea108d2ee6615153cbcc23477f9998231fb"},{"Digest":"0xc94bccd6d668430e7e9e14c9941b294b1c0bf7dd8fae2dc01ea454a5a7e2b553"},{"Digest":"0x4378656a5fd08c32889daa18e0282e2434918d05233a35837548a4faaf537e1f"},{"Digest":"0x3b34e2a5f10fd91e2ac7cd9e31889615e66ed96ba99417901f21bbc7c01059d9"},{"Digest":"0xa350c5edcc4088c9f5b3ef71f7c1bd38530814783281bfd88f8dde5fe578122b"},{"Digest":"0x5c5c3b541e9373d714ecc721a903f4a8c1ea7614985d87941168fcc4d587f3bc"},{"Digest":"0xaf1802f2c3f4fcc023f7fa4623586913289ec1473fc0ff8f8dfbc7d8f4381669"},{"Digest":"0xfae84ae20bba66affacc94a39410ad201ef5fa4e2a56b227bc42ecbe6a5c3c81"},{"Digest":"0x63d03e9a9e7d25fad2c7c7ea35932f4180f5735b6a693ceea9f605d1d255a111"},{"Digest":"0x7ac67eeda06ed2a288d992628286bb5028d69478e036757f219f5d5ac9f0c6c3"},{"Digest":"0x7e47876ecff71deefb6671ef4677301f99cea5943fe656678c2669da92483b20"},{"Digest":"0x729453751305a0b80e61ac794db9771711a6df554dfd46984e11f76e9240c89f"},{"Digest":"0x32ff8091ec1c7b0c62848bdce8f23645ba4beca4ccf03f4dfcd9a34529423b74"},{"Digest":"0x9b5d3c6d1b6fb58ec6e25cf23d0650bdb43503fc06595907f928e37e4058ac54"}]},{"Digest":"0x9db80b716c41af63978020d30017d5c87dd23f56e1783ec28cb29d085f36aaa4"},{"Digest":"0x41be2fbfb195d2c9cb4d5a395be88bc09089444fdc1dbfc6a531367c39e52262"},{"Digest":"0x5e9e354c187ccad5087ac65778a476a38e35da7240ddcebeb89e3ca5ec87ebec"},{"Digest":"0x5ccd77692b3b02d187a4eb9cbf09c2569b6737eb8e2f777245cca2cdcb226616"},{"Digest":"0xf9f6c3ad585ddc478d7209d876a986b4a5f85b52706f56e1dbaa924170e8ec18"},{"Digest":"0xa5e58ebf4af2adcb42a3fabbef52f67ffb8b6d608272498b33c7049826367d35"},{"Digest":"0x1581534c0932c031ff5c5aac8ffe5df9015e8f90b6607b0c655038345a8c4fab"},{"Digest":"0x3cf619dd52e7e6a7bdcd72eba4f0bb6262d3054ce665f1a78b41d82856353c03"},{"Digest":"0xfc41d88ac0eb6e10eb873050e35231517ad8de23685b3573e63033ac524977dc"}]}]},{"Digest":"0x8ffe09039a6cc5fb2ada11cc8179ae50ade9455b1d7de08302c17952b209b23a"},{"Digest":"0x5b910b6c4391bdc271b954feabb97f4229fca3f7e2466aaaf2895518a6f63790"},{"Digest":"0x0f3ffe264ba37c65e7072406ce189abda66dfd2ab53b005c3c664c54bad48b59"},{"Digest":"0xcf9c35cf6264f17b6981449d07379ffbf9ee25098881833ed4167bcfb4d1aa5a"},{"Digest":"0x97875850aa2e9f068f90d6aa3c9d8ab87a69db1816295edf2f5907bdb919af0a"},{"Digest":"0xad5866a1ecf73b25eabfd0678a1956dd445131be0cf45d5931e19ed400244fae"}]},{"Digest":"0xc5843a3a1052ae5e1bc51cb2e73941f56f3d8b24343c18b575bcb56b9b8678c6"},{"Digest":"0xab73a5d5c21e0313ddad0dc2aa93c616b51fa7dfaab86c20c9314b518e13a195"},{"Digest":"0x93c921c8ef533cf1309d27b2d233525a99fa251f3aa8c7999e69b30f6068166d"},{"Digest":"0xadd979abb22b9fa820382ea30a55515e016f120fa086d21f9b314761c8bee050"},{"Digest":"0x302a09465fee8c6bf6bd08690514d3d27a07e10b0b3893a40bfda48b3655b562"},{"Digest":"0x659122f87f9203f1c3c6d8617bcb037d439c4be5c9e9f7ebed2bdd8c880c7db7"},{"Digest":"0x67088b4c822e5b042d9bd979e50df8db54ee14bec74d23bc1b44c9aa9319cc24"},{"Digest":"0xadc2256d6257c8b78dce1849aba8adcad7982ab760739c4887f899509bc59be7"},{"Digest":"0x2693733d79837e1f389f414765695eb15c7dac14727b9322fcd296eca9c66285"},{"Digest":"0x9892ade3e482b102da4dae2e9cd5587ec56a9151415e15cc97a0e9f467c75b11"},{"Digest":"0x7095969b630f20e41826a749d33bb129073dd1fcb34de2d8fd90ebcd9b8289a9"},{"Digest":"0xef9ace4adf41f11fc21eeff47df3d153b02b83e3ed8293d4d4ff10b3529ee3ca"},{"Digest":"0xabceabfb09dc73334f5daef1130025c0d55b5af70410ce4a6c1b4b9d8f615ecc"}]},"storage_tries":[{"Branch":[{"Digest":"0xc2126fb735c8c71bb2f27b27c6ead32d39e02affcfa9c313bbc0a4a5c87b75fc"},{"Digest":"0x48386d60a0d14fd8bea4eef30dc7d7e83b22c7aaa12b838fc10f5918ac47044b"},{"Digest":"0x9b31862f2d3a7a6a6b4a99ad4866a399025eb4eedf0c91283a9bcbd6b0c99bbe"},{"Digest":"0x44e386d0e34dc700119be1832672ea8fc9fac8f4ec4cfc112a2f1a91c888561e"},{"Digest":"0x654d5160bfb920c1f5b0783351ed306bef6b59bcd2a3626ec341296acc6a21b8"},{"Digest":"0x04ff11d369a90aea17562c849d80ef296ab227e86d00f974ea18461dfdbd7f4e"},{"Digest":"0x8333e2094021bddda38790656beac10fb121018fb4a76bed4a1c8bb9ed707c0f"},{"Digest":"0xad82d053fd257e249fd76918213cfe321654ed4f4db2b452ba3704565a14d364"},{"Digest":"0x2a2c2976b51f14a611f1f3a9f52ffa6c3ba547f5c049f00151b6328fe313a546"},{"Digest":"0xa0a1060c8ab9168bfc0fbfd1889f8c290828f37718fa50c5578f1526ec57bf48"},{"Digest":"0x7d70a6bfbcf857cdf18d82200704ff7bae7cf12d94f06c12b26c6c8f740b2b6a"},{"Digest":"0xde7deb8da1df8f9790af9dacea7e3acd712eff247636cf2dd27e30586925e1a0"},{"Digest":"0x4e02539b91f81a211d2282c1c30252c3c8b2a22ccca29d6bfb7cc367b8e8eb68"},{"Digest":"0x0e5e55ceb0e52ab3b1688c24c1dc330671d11a86468811d309c1dffe2b3f4558"},{"Digest":"0x5355113258dd5fb285357a62f6ab2713c057523884f616631fb8245ef000f672"},{"Branch":[{"Branch":[{"Digest":"0x02073d18333e691bddb8642ca82b732db6415c9f84a1149b3bb710824214ceb2"},{"Digest":"0x31d5bc9659e75a99e973418b4794c0d9241a3482d6359cb11b0753d0e460a269"},{"Digest":"0xe79421201d09eeb52b36e427967ed621d245fb04769487d7ebdc5cf7d44b17b4"},{"Digest":"0x18ef63217fc35b0ec780d2427113b6e35a714c4c17b27993cf6227b551912f58"},{"Digest":"0xa53a1b7d3f70c40201345314bf7fb4446bcf79dde781102143705d6b66486e53"},{"Digest":"0x007a444b6e07e59e910751aca367d5fb2d4db3126fe9b9bfae05a7f652cac56f"},{"Digest":"0x460db8fc9fcb2d58cc58997614c5a6545b8c4ea7342fef05768a5691ca7fe5ca"},{"Digest":"0x35ec4099628336dd7f3a13caa20a54d2611b4d8b97a112ff357e0eb0541f189f"},{"Digest":"0x49355ad2e8f7bf8b6ce8084088aa894c07ded44b315695aa1b3fb3551d35d4fb"},{"Digest":"0x83638c0eed723390afd17ac07ad64aa3f298affe5078a3ec49e9b7b463c12fed"},{"Digest":"0x90424abf55dbe91f187e2eab0a91771c4909ee989dddd2263c5ffd8353e44a91"},{"Digest":"0xf708a9096c48c1baed6a8cd3f9409b1863eae8276801a89a6152806947f90a7d"},{"Digest":"0x467c6d27ad319df67a07e54aa5ba51d914c1191c6f179e045ba5e4b1362e1265"},{"Branch":[{"Digest":"0x957c5ebf39508dce06b519f3357407ce9b0c7e325a5b5baf20356802119e2a1d"},{"Digest":"0xdcdcda02bab51aee6cec341859880c7d3a74b2a708c6837a283e9140d742ae71"},{"Digest":"0xfe878f6d7851d2c4a89a747005f6ec12211eea53845502d577358c38d99b0540"},{"Digest":"0xba01139006d0b39ceae595d8736eeb0614536ec331df968bb7a87726d663619e"},{"Digest":"0xd835f0fb96ed233d45a950b9374600896dce6e9f9e9f415e16f56d58db6328ea"},{"Digest":"0x763bc0283a452d3e45a3c40bc33ace9c3bf8327a4f98f3939b6fb10797692ea9"},{"Digest":"0x926a4be03b7bfb0176a0a07d1737c8bf6d7a73d1d02744a1bf26736c3a853227"},{"Digest":"0xbff83b63f63ff94b661fb0a7c3cce98b8407f55097a90e1af5351b21f649d32c"},{"Digest":"0xe0e716a063b31091e183787523f5532b2dc7ab69a1dd66cc90cfb116ad477d20"},{"Digest":"0xfe7d2af4a9f50363f9fc87756d737bd5ea2ce08079a592af54285923e44cbedd"},null,{"Digest":"0xb883893ad62f19b1ade0ead65ab810ea10bc653dc37b2d6e9536ddffab16c44b"},{"Digest":"0x1a578cb4375a74230fc289891bc27480edb2b7b162f8d0636ffd9cffa155cb06"},null,{"Digest":"0x1ab003882db00b52c3298b9f8e5377e64facdbd98d8a31376d7f4b4f7014e11b"},{"Branch":[null,null,null,null,null,null,null,null,{"Digest":"0xf0ec532af391e6dc77f2c9867afce87e39293059a5f8ddf2b21b38d8e4dd23b6"},null,null,null,null,null,{"Digest":"0xb92295774b00d67bfc53715b07b142a21c554b7f1cce914aefc2157459fc289c"},null]}]},{"Digest":"0x45b01213c9e56a5527cbb6ac2dee8cff756ebbec4f9a4106794a62d73e95bddb"},{"Digest":"0xb00a95f416324179cea6c4a2af4bfb813a2925aeb02da845510630a1ecab965d"}]},{"Digest":"0x8d05de705dfe8953c26d2632fcbc546eba89a253c55338907829e83581aa6379"},{"Digest":"0xdbdede52331ae902f3687223b04ee66d8cb09e0fc669b3d848cc3a3d2e2085c6"},{"Digest":"0xccc8214fcaa44a224ba014057dc73757d3c871d6462f799e0c5afb754427f0ac"},{"Digest":"0x1c8a2128b24aaf149e8299fda27f8b16c6a8f000ddbf2068bfd13de59eb80042"},{"Digest":"0xe709cdb4462cd15de1afb1ab1717d86bb43b727b64669cce6f7a599dfa3bea5c"},{"Digest":"0x02ee4a0d06036c8c0419d43192a5645480aba0f0c0315b5765c6b5b349fa277c"},{"Digest":"0xfabd3487cff148ab8e6a020cbfef3ce255a81fd130de42a06c9dce4ea342d305"},{"Digest":"0xfaeb4665c5248c94460f0f6acdaeef0230abbc35fa39ffb39f8aeaabe6bb1440"},{"Digest":"0xb7455579aa6ad32b71a8235d3da8e2617b408c9656166c68a16e47a56e4098a0"},{"Digest":"0xdfc0e498d31274948b0bca730702c519208471c0b9bd3cdb992b89bc0517f1df"},{"Digest":"0x16e332f3f25f9b4e128ce4a1f84425ccb01010dd6fdcdd1d6623b085887ed578"},{"Digest":"0x2671ddb8e1c7f06687941285e09f3dfdc59f0b10ecf2b6519175fdb88c232a29"},{"Digest":"0xc51c210305336706d9e14799b45ca38cf015518ca5aed8698eefdbd46f00a7b0"},{"Digest":"0x2dc386782547d6080728215427f6f9f46b5dfef1bae23a7c593634cf54481183"},{"Digest":"0x205aaad1146099e8dbc170d6c46e758f310d84e3df5b3bc71df122902a47f7ef"}]}]}],"contracts":["0x608060405234801561001057600080fd5b50600436106101775760003560e01c8063715018a6116100d8578063a0712d681161008c578063d505accf11610066578063d505accf14610383578063dd62ed3e14610396578063f2fde38b146103dc57600080fd5b8063a0712d681461034a578063a457c2d71461035d578063a9059cbb1461037057600080fd5b80637ecebe00116100bd5780637ecebe00146102c95780638da5cb5b146102ff57806395d89b411461034257600080fd5b8063715018a614610283578063781603761461028d57600080fd5b8063313ce5671161012f5780633950935111610114578063395093511461022757806340c10f191461023a57806370a082311461024d57600080fd5b8063313ce567146102095780633644e5151461021e57600080fd5b806318160ddd1161016057806318160ddd146101bd57806323b872dd146101cf57806330adf81f146101e257600080fd5b806306fdde031461017c578063095ea7b31461019a575b600080fd5b6101846103ef565b604051610191919061129c565b60405180910390f35b6101ad6101a83660046112da565b610481565b6040519015158152602001610191565b6002545b604051908152602001610191565b6101ad6101dd366004611304565b610498565b6101c17f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60055460405160ff9091168152602001610191565b6101c160075481565b6101ad6102353660046112da565b61050e565b6101ad6102483660046112da565b610551565b6101c161025b366004611340565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b61028b6105ea565b005b6101846040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b6101c16102d7366004611340565b73ffffffffffffffffffffffffffffffffffffffff1660009081526006602052604090205490565b600554610100900473ffffffffffffffffffffffffffffffffffffffff1660405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610191565b6101846106e5565b6101ad61035836600461135b565b6106f4565b6101ad61036b3660046112da565b610791565b6101ad61037e3660046112da565b6107ed565b61028b610391366004611374565b6107fa565b6101c16103a43660046113e7565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b61028b6103ea366004611340565b610b1b565b6060600380546103fe9061141a565b80601f016020809104026020016040519081016040528092919081815260200182805461042a9061141a565b80156104775780601f1061044c57610100808354040283529160200191610477565b820191906000526020600020905b81548152906001019060200180831161045a57829003601f168201915b5050505050905090565b600061048e338484610cdd565b5060015b92915050565b60006104a5848484610e91565b61050484336104ff856040518060600160405280602881526020016114d46028913973ffffffffffffffffffffffffffffffffffffffff8a16600090815260016020908152604080832033845290915290205491906110bb565b610cdd565b5060019392505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152812054909161048e9185906104ff9086611102565b60055460009073ffffffffffffffffffffffffffffffffffffffff6101009091041633146105e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b61048e8383611112565b60055473ffffffffffffffffffffffffffffffffffffffff610100909104163314610671576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105d7565b600554604051600091610100900473ffffffffffffffffffffffffffffffffffffffff16907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff169055565b6060600480546103fe9061141a565b60055460009073ffffffffffffffffffffffffffffffffffffffff61010090910416331461077e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105d7565b6107883383611112565b5060015b919050565b600061048e33846104ff856040518060600160405280602581526020016114fc6025913933600090815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8d16845290915290205491906110bb565b600061048e338484610e91565b73ffffffffffffffffffffffffffffffffffffffff8716610877576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f494e56414c49445f4f574e45520000000000000000000000000000000000000060448201526064016105d7565b834211156108e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f494e56414c49445f45585049524154494f4e000000000000000000000000000060448201526064016105d7565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526006602090815260408083205460075482517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98186015280840196909652958c166060860152608085018b905260a0850181905260c08086018b90528251808703909101815260e08601909252815191909201207f19010000000000000000000000000000000000000000000000000000000000006101008501526101028401949094526101228301939093529061014201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206000845290830180835281905260ff8816918301919091526060820186905260808201859052915060019060a0016020604051602081039080840390855afa158015610a36573d6000803e3d6000fd5b5050506020604051035173ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614610ad4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f494e56414c49445f5349474e415455524500000000000000000000000000000060448201526064016105d7565b610adf82600161146e565b73ffffffffffffffffffffffffffffffffffffffff8a16600090815260066020526040902055610b10898989610cdd565b505050505050505050565b60055473ffffffffffffffffffffffffffffffffffffffff610100909104163314610ba2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105d7565b73ffffffffffffffffffffffffffffffffffffffff8116610c45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016105d7565b60055460405173ffffffffffffffffffffffffffffffffffffffff80841692610100900416907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36005805473ffffffffffffffffffffffffffffffffffffffff909216610100027fffffffffffffffffffffff0000000000000000000000000000000000000000ff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff8316610d7f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016105d7565b73ffffffffffffffffffffffffffffffffffffffff8216610e22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016105d7565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8316610f34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016105d7565b73ffffffffffffffffffffffffffffffffffffffff8216610fd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016105d7565b611021816040518060600160405280602681526020016114ae6026913973ffffffffffffffffffffffffffffffffffffffff861660009081526020819052604090205491906110bb565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220939093559084168152205461105d9082611102565b73ffffffffffffffffffffffffffffffffffffffff8381166000818152602081815260409182902094909455518481529092918616917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610e84565b81830381848211156110fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d7919061129c565b509392505050565b8082018281101561049257600080fd5b73ffffffffffffffffffffffffffffffffffffffff821661118f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016105d7565b60025461119c9082611102565b60025573ffffffffffffffffffffffffffffffffffffffff82166000908152602081905260409020546111cf9082611102565b73ffffffffffffffffffffffffffffffffffffffff8316600081815260208181526040808320949094559251848152919290917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b6000815180845260005b818110156112575760208185018101518683018201520161123b565b81811115611269576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006112af6020830184611231565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461078c57600080fd5b600080604083850312156112ed57600080fd5b6112f6836112b6565b946020939093013593505050565b60008060006060848603121561131957600080fd5b611322846112b6565b9250611330602085016112b6565b9150604084013590509250925092565b60006020828403121561135257600080fd5b6112af826112b6565b60006020828403121561136d57600080fd5b5035919050565b600080600080600080600060e0888a03121561138f57600080fd5b611398886112b6565b96506113a6602089016112b6565b95506040880135945060608801359350608088013560ff811681146113ca57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b600080604083850312156113fa57600080fd5b611403836112b6565b9150611411602084016112b6565b90509250929050565b600181811c9082168061142e57607f821691505b60208210811415611468577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600082198211156114a8577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50019056fe45524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220eabef41c79e988bbef5573106f3825656f6522b0a2771b005adfc744729606a364736f6c634300080a0033"],"ancestors":[]},"commit":{"proof":["0xb979a30a31cdf9bfe333a07eb94543825923801272b16a7b3907eb42427894fe","0xb1bf77f5b627010f983c127b5f3fb327489c3f432720c1747efdcaae217b3043","0xba7770e93801db137159e000011b6eb4e689beadd8e05ab6d295f4a2e8187777","0xcabd362cf637094f4872dab4abd5b217b5b025570dac723c1538f9239b117db1","0x476ee052cfcbba0973a3bde4222138868b206778ac968fdd751ba5e254904a5c","0x77142bc813666d24f36813478e8e5468058ba0cd88fe0f682ba381291f334a07","0x3ab69ac96adf0d67fa7cc929f3d3b4614efe4423f53cb27bf97f47310fbd2482","0xdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71","0xd2a36965fcbc29b76e16a79397e7a8f695876e3c47684ff3d112d418fb3a11dc","0x0000000000000000000000000000000000000000000000000000000000000000","0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b","0x52eacb6cd14c0c72f7d07ecab8959723e116ecb4c1da956f6325d68861f1bc6a"],"timestamp":1727768652}}} \ No newline at end of file +{"Beacon":{"input":{"header":"0xf9025ea085ff12048f99eafed21668fe41e3f5c32ab58a0da3c9ef4e3057f1718fefeabba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794c6e2459991bfe27cca6d86722f35da23a1e4cb97a0fdba945fc701521d1d780cc3678e9b0d117440c90ba8924b098f96d3e06385aca0f648b484e108d7ac90d9cae783b88f6963f76bb3d38ba13b22b3af8fc25aeb0aa0b7e4b4073748dcc9f35e6a1dcd90fe28fa1c5bd899fd55f823b97d746eaa8473b90100854118088109428d121218b70084219a00a14094064d80002e5029c088c2010200bc81cd012248142002d8072b151688461204128804c4807072fa5cca7402103200500808043882c688294b900ec0902400130202844060010c4409b1108213008102401e01a0411910873144000871800828c4488108c1082000deca29200303a6714911ae74067c0291640561007d05012e301021120894073bc42580050c0e0a02021481480448c90044922a488c12893a498a442b06818082331112eacd492472821c13922418631211bf0242104814429011098d00c112945c00006210afb10a0677580060010361a62102411c80c2040afe12020404056c1c19039206808367a88d8401c9c3808401205ba78466fbc16091726574682f76312e302e352f6c696e7578a0fc22b74c7a6fe4da0844b6da8e8b84ec50ec14eb1efd0aba40dee26ddf8dfe2d8800000000000000008536d318f68ba0d9f1e567661d214eb0af52916c44a49d3174a1dd6d3275ce480ea169ea8f0378830200008404e80000a03fe210a5d884689e9e507297f08be690843161fbc9efcfeb759ffa6573b2836c","state_trie":{"Branch":[{"Digest":"0x4ab8e184e859f9525a865a3d856b3a841109ec5fa01ad7d050c9bf806493c2bc"},{"Digest":"0x6baa7c1834ea673d6ff7b3d0bd05eac6d058a847dd1cfe6db9f483c4e4fa2917"},{"Branch":[{"Digest":"0xde08bf2764058279f0c2c1c779bc75bc9acd4e55f2fb77d6f80beae7b2beaa33"},{"Digest":"0x75e81861e9cf5a98289ca56b6772253ea68c276f56c7969203e4329aedd5b61e"},{"Digest":"0x4b2cac4164968696908dde9b9abd146989212dab27116dff683b1a0269ff317c"},{"Digest":"0x50b1bc361040ec568f975843620162aa8d5359469c8941401c18037f8c3fe57a"},{"Branch":[{"Digest":"0x8ca170a85cfa4821f2466ec1e5299ced318c0d16f77c127908776be11fc5bda4"},{"Digest":"0xe4fe157ea19687abd5fe0d1bb8fd359b748fe8df1d81ee928938b2f1ed988876"},{"Digest":"0x0b40acf13e3e5efe1710b9159996f7c232a655a2441b3f983fa6c42993c675aa"},{"Digest":"0xfb03fd41f144fffa0e491271bea438fb75d80f13a6ea3e08e3b1fc93652a93ae"},{"Digest":"0xbd9d56520af043fecd7d94da59fc7c5768d15ae176c39ef1abac9d8a93aac27a"},{"Digest":"0xd192b1f87aa126664dfa2c97a59c6ff4bd713d821f5270a53e5f103ea72d338c"},{"Digest":"0x19f0e8a05d3f09e588db469d5126b87b4a640de66f3283b52802c4c9bca17e1f"},{"Digest":"0x3a581b6357bb523197dafa2e79997d1ae0584d8604455ea0cb0da7c3a76e55f1"},{"Digest":"0x8f9f3748f51e6ec0dd996a0b147c1acbe8bfaad8e43bfa2134c9cad4e45d53c8"},{"Digest":"0xf9df6993333d4e8dbcba4fd62dadc1ecb0b0feadcc1002890a367841c81fad8c"},{"Digest":"0x7477e778ef99466fb75a4a7efcce294ecb6c6a671ad9d29b8c947abf347debbd"},{"Digest":"0x3bd58ef14ca7b688016c4ec9b96011587939c35820186c453e3f06d40e7a3549"},{"Digest":"0x2dc623a5a7f0016b502c0c15ea2c8b12d7aeef3a1f882a44d2dd7821028445ba"},{"Digest":"0x540fc9aeda3525fd4c3bdcf72642e0ab41e165a4829fb1678f909514096c8aee"},{"Digest":"0x52d02f7471ff137c0374bba43653562961a9752ce0c7298fb631fbc5fd192110"},{"Branch":[{"Digest":"0x05874ea022ba901c2d3bc4a24144b3f45991770d239620e85fca0846310d498f"},{"Digest":"0xbda332d0cf6544dc89b63a3b96d1980a00072e1c2407f5c151ff1dc61f94f215"},{"Digest":"0xe6548c4af231f8a84ece91fe09443fa167b6afa586298aa44f5c9de1d42f84d0"},{"Digest":"0xd79d1dd14d46778105a5abff292506caf027736cce07afc11e17898c7ed39a88"},{"Digest":"0xe85139c8ed7d2b120c17a53fedf8eaaff295412b3bebb3cd131004fcfeed24d2"},{"Digest":"0xff8cd7a7fc94ce410a001fb178a88f2f79a827aba693091209de5241d00f9bc6"},{"Digest":"0x3551497a0439f640571c034fc777fba7f6d64c536f4ada7eacc5fab53cb8574c"},{"Digest":"0x3515948c7d7ddb11ecd4eda0b326f70864ff485bf3e31478d952ef444c157196"},{"Digest":"0xd3e25ac5e646b7175a4a8bde80ecd686713a92695b9e3f2c4b9acc260040fd73"},{"Digest":"0x297e852d803fea4691bd25ae28f5cc82f21bf44d364a80220fb44c8cc8398993"},{"Branch":[{"Branch":[{"Digest":"0xdb28048328251e31b2d3328dc517f370e4661cf8ce1d5fa345faa9f51ce94f9d"},{"Digest":"0x35292568f46d6bb85536804d457243974a5ef9557fd02fdd9c414150039dd570"},{"Digest":"0x547adead9dca2a0a5a68a59b0a9e15e76e03c267aa1bade08bb046f2bd4eb073"},{"Digest":"0x27d35383b43d2bd596638fd20e8dd09a6ab63c96f90ec11c6a5249bb4f4dc2eb"},{"Digest":"0x406a49a5b08edc39727921ccee69f2d8585f1658b581cc21f65349a13be8b129"},{"Digest":"0x8e3c6433db2e2b9bb76200119bf51313cb82d97200d633f988c2222980901f9a"},{"Digest":"0x1e379c0cbf9b976f7917e8dd9cd6e59314a75cff480f6a476984321794bde9d0"},{"Digest":"0x3432854290ecfba5f449eeef9f941897a935694aad97592e7b7d9d681437620f"},{"Digest":"0x644f86d76acd1f8bb5a55119608f0fa73493b2694ef0950f1a5f673e8a7e6753"},{"Digest":"0xdf89fb84a1f4d3a48d788b242de27b80ef31b634c1321f5506a6e6158bb8dcff"},{"Digest":"0x2cf4721a99a7be43a6ed31637c001960276b54518ee3541e349aa47776752196"},{"Branch":[{"Digest":"0x8b92b40f358d29115172a38e36adc284772b7c2440b55e199e31f6d79dc52ab5"},null,null,{"Digest":"0x32e92fce0570631395ec05c62413a521ed320db25bd4a95992ccfc47c4c74a39"},null,null,{"Digest":"0xac2a299a9f99e6f0b275d38efb601ee9d1d95199b9441d46058781dd915fafe4"},null,null,null,null,{"Leaf":[[6,12,6,8,5,3,5,0,5,7,9,13,11,0,5,7,3,3,4,7,14,6,12,10,13,2,1,6,0,15,6,12,15,15,13,1,5,10,1,4,13,15,10,14,15,11,4,11,3,15,1,8,10,14,13,11,0],[248,68,1,128,160,230,193,154,246,15,58,46,205,228,200,169,39,165,222,29,111,88,180,121,74,112,127,111,57,245,32,5,244,60,157,186,100,160,173,162,122,66,135,249,23,26,77,35,164,213,151,124,154,88,61,113,137,6,246,170,45,109,127,36,115,156,57,115,6,242]]},null,null,null,null]},{"Digest":"0x924c1290a02b6550560de2f36ee20c66a31e4e2e1997333f3a8642403bbc1b9a"},{"Digest":"0xd6a2b5a75d24772a9e6c35cdccc8f51ac75818870ab706fef68c0e53b4aa5e40"},{"Digest":"0x2d6bae5f11cf0d8c8aa8858af8caa1a125595e8112eca81d2ca618d2d4758ec3"},{"Digest":"0x96066747f61459591574c48f97d9af2793f04d8258fe6eb7f4c1260cb2a9ed8a"}]},{"Digest":"0x3959262eab0df5cb0ff6ce4bb34ff9af758a35bbcbee37abe5990294e0562fc2"},{"Digest":"0xafac905211b114f21670e002795d86542bd89851a38a5aabd7face23feecf318"},{"Digest":"0x5067f564588be95a99e2f468d72b96462f212bf91b58b69e790c0199bfabb031"},{"Digest":"0xf5bd14502ac3ffb3c931e67fcdee688df840196a89e9bfc7c96fcb3f52058341"},{"Digest":"0xfec9be1378be2a793ece6049f8a10766d4289af8ee1e6aff8e748b74fb95cf16"},{"Digest":"0x4fd7ecbe4c1f9958c6da124c59d0bbea0160c56bf32bd6eb72c672f9abc44a92"},{"Digest":"0x96891f3a45ee91d99cf3e168a61019c3d8ddfa00dddd11b83a3e81c7e5e35589"},{"Digest":"0xeb6bf0cf183778116004b698ef0f5e70995dfa9478bb3255f0b29208d5f92808"},{"Digest":"0xc3caef74fad501cd0ec832b44fd6d19474b9fd2a2153b908e3e8063229b5a6d7"},{"Digest":"0xaf327e16ecc2b46b9eb8560b73410d573daef3486c108b7d4e50aec6fdd8f546"},{"Digest":"0x21fe976c00067f58fcfe4ff5aa689f7a263cf97a879debcfa88ce119a52e5d7d"},{"Digest":"0x66fd5a9d629a870d36e270e332c6bce939ed7fc2a9f2e2f334c65a630ca3ba0d"},{"Digest":"0x5e7d45a26dc6c2a9875a2d6b87710a5eebcfc5b76ff5eb6624c72bb574070dac"},{"Digest":"0x1c3f804db6dc200cd23518a4be871857ac04b8e1bcd87f743bb86a459c6c2c22"},{"Digest":"0xe18a3df3e569acca09459d2ef00b1e4fb3e8d1513cde0e83fdccd25db5d57c73"}]},{"Digest":"0xc366671e6d92e680ef4a210a57bf64f5ec14a6734eebccb548e0764dfb510f77"},{"Digest":"0xae055c2ad055a21614f87feb9de5b98dd47505c4fcdf7b2e21c2df56ec3cf21f"},{"Digest":"0xf95acfb1cf14e4a461ae9d3b1d0fb69e5d66ae663f6c0630ff618ac076be530e"},{"Digest":"0x683d9927ce5db8dc2e645132f672f1aafc98b33492b5651eb899c1dbf24eef6b"},{"Digest":"0xdb58eb782462c4b917eca16ce13ee0864835dc1b4b7350e23e75c8425b7f6c7c"}]}]},{"Digest":"0x6ea2065a22b9e4a28743909410af4e84438df3b30c65d5c6551b3daa23c03ddf"},{"Digest":"0xa90bb4ec2c14e5d97e73e4df945c70b48aff67bd883d4df40d27d6c6264ead2c"},{"Digest":"0x848517f50326c1310c81a8b21296d573663463aec5fefc4d9e982271e7ec6fb8"},{"Digest":"0x74f77d27ebf4443499625dc739201ebe485990c6f5d37cd372fdb4d4703aed60"},{"Digest":"0x9fd417c65f3999120d0f58de80bfc0823c2c903bc119c7c8e7c0dbb9dd492949"},{"Digest":"0x95ed9e9d6dcf821db4b371244e10a84de3074271034ed73dc6c39fc9209275f0"},{"Digest":"0xffad330d236e351e102d0491dd113c806acd75626efdc2482b99de37d9d9f935"},{"Digest":"0xd0810f4d6a130ba0488108eb439529a918e53898a7baa93961d73b50d8343733"},{"Digest":"0xd39a688579fc36f7d587a1818e3370722227c36417d064b3cb5f30894469fa1c"},{"Digest":"0xead73f4b6ff4f085735d27d3768f6633e55e77fdb95e65f3735466ad49fa75fe"},{"Digest":"0xd8766327db36de0ae5355848f8a6b67f0c2213b26945eb57aebc92b84f9f7922"}]},{"Digest":"0x53eed6185fe16f83d1cc83783df4c29d73f7c3327e947146516b80ecc298146d"},{"Digest":"0x9f222f105a27afbe7c7fcb3bbedb8d52bdb4d4c7620f7075335f8dbc2e3a7437"},{"Digest":"0x33ffc48352b5e1e49054a975817d65e3be60dd5540432a5c50e3a135ddbaf88d"},{"Digest":"0x2c00f8ce67a24be43f6bdef97b39da14235e5a467de13f73cbf271095212fb4e"},{"Digest":"0x148b3dc05ccc87f13ae340fb1c96766ba61db098a59f01f7eb5fd8485d8bfa08"},{"Digest":"0x8e07175d8e23ecf080bb4e0d93767b7f02aedca250a3e12f445f1081746dd715"},{"Digest":"0xa66346535aa2a93f1831efc876d3796ab4ee3024244a8a62f7a12b924fca57fe"},{"Digest":"0x686e4ca194cf710671223265d74805f409c8f546d05bd0b0c71d6a5fe1a6b2aa"},{"Digest":"0xa9ecf52d4d2a4fab791318aa1409d7dd6141b19bdc970b7dac518a38a36c557f"},{"Branch":[{"Digest":"0x5c9f0bf4f2c06981edc6726008470b40711fbf8caef652ad150134abe1db85f3"},{"Digest":"0x92c89262729b12c1ad9515f62b79ffc0dc3d94ff1ad9d5f7ad953721010ff60f"},{"Digest":"0xe72c0df3b4806f3ec32f6eb248bd6113546f406320adf76839dd643ea8f71087"},{"Digest":"0xeb2282087cbdb101b85a521159cefcf423cc5e2df2aa11cf9ecfbeaf8a50d63c"},{"Digest":"0x7b7399185826ba84e492985cae6b946017d71558d2cc95d5454aa4e58c13c5a9"},{"Digest":"0x4b2dcbac57108c17416e192460f88eb7abbeb80373e3ec22fa64196f66dee0dc"},{"Branch":[{"Digest":"0xa2d06fa9013378cd05f3d1f88c92d456222a3b1212883b17f9c352cd534937a6"},{"Digest":"0x13d2d4f767964c5163ff602f6878d742ec6bb5d7e2076696eb90630481346b29"},{"Digest":"0xe65b669649ddcba1f7ecb4499c7405587c8d2e8d7a0fab5fd4857ee290e9e87d"},{"Digest":"0x60a3751002055113465ce0873be8ba2f94305fc17c154636491dde2b57b13817"},{"Branch":[{"Digest":"0x3ad4b46e8ffeadd54a43f06d253c1af449f3f4fab55c586860e58574ef83c7de"},{"Digest":"0xd9f0c4f3eb048641b60da40bb3e04698ef4024259a6272d3a585106a112d7947"},{"Digest":"0xbcdb27f8ee5854b9c9dbb78fecb8b5a366e60aa8e5449cdbcd15478b42ff6ba7"},{"Digest":"0xbcea6fb35f13a0cb2e3c1ced578e447f245efe8c8cd460b91d40a2b75acfccff"},{"Digest":"0xe902c889bfce1a86a498c2b0fef7bb45e6e7351fbc0a1e80636bade5c19fcbf0"},{"Digest":"0xb15fdd031140fbff9543923ae6a943377b8ba839805c81887374e0284d7bee28"},{"Digest":"0x976bb7896182ca32d84e7ed1c0372a232bfc6fd7ea35f05509b4b7f13d61eea2"},{"Digest":"0xe824221567f42b24961e5b65f49951f75a99d684e6fbc765d49f53d85417d6cf"},{"Digest":"0xd12969ecd48c615cc17bd62920d1cae02c25222462bb8fd9b01b4d4738e8af72"},{"Digest":"0x46c867a53cbc216bdfb29760376ac91f7ab4216e3436a3293341a3be1a4b3f43"},{"Digest":"0x298e88aaaacfdc530341649bdde25072c7e22c13e1820328a8b0103078d5a407"},{"Digest":"0x8b9636614cf742beb60eaadc927be79cc69c23d9c12ec849dcf4a1925f471f00"},{"Digest":"0x0f399e9f72189558470f7650857b8011bc223d8c29812500fbbbde45ce0bd696"},{"Digest":"0x6b71232f57e38f8274bd82eef71920adb37722dab561844301f0d6d180af86e1"},{"Digest":"0x5d957b95e9ac7c5c603c8b42d747fb48623e88b738cb6337def740712f7e07c9"},{"Branch":[{"Digest":"0xc43d6fc9fea0f239880c36a1b147291287782f11affdab45b7e1afe690c3dd1b"},{"Digest":"0xc65bd105ecfd3bfeadff306567e1cf55c750a9e264fc47dd3e2debf472a4b6fc"},{"Digest":"0xad446ff8fb40b2dec6f173f39b99c02572bb53077a4bca461a52d4c374fbae21"},{"Digest":"0xcb77197c7ac1cd16630d91d250fe37cb6128551695e887fc2d57dea9e5274bcf"},{"Digest":"0x0bc75102a1546274bcb2ee4c28eda640c30ee349ef9ce1809d4cfcecbe8f7eec"},{"Digest":"0x1c6ba636d6a225178396da9a0a8fae8112accd1ac985da7ac9c638f80910cac7"},{"Digest":"0xedd01ef6be9c454d5189b94d26c6bf06e743a737d1525c27e359b5663fcdf1fc"},{"Digest":"0xd9111dd948d64be0b7afc654a538efa142ea32373e3ecec5aa77de9fd51902bc"},{"Branch":[{"Digest":"0x079cdf83dc79847fb2c4283aef06f28d36094f487bdb60435e087b09ee526789"},{"Digest":"0x34c966c91c89c91a0313fe3a258574c8f9b08959e3fa43e40351b4d4bab3848e"},{"Digest":"0x5ffd98f00d0b954d49b39a9cef21efece0ddfd3b62a32bdead8bd131714d7179"},{"Digest":"0x13683ced6ab57daa01993d7c98d0ca12006177c009076434762cdfd98ec0fe39"},{"Digest":"0xa47cc0a8e6b4256fcd929350dfd550e31009a2242203d0b5750625d7cd8f2051"},{"Digest":"0xea61a70cb09f7f5edb51de22253a11d3d987fb7e8f7912555c045d1c466db038"},{"Digest":"0xdbca5b81410deb3cacc46da378cdaec0d269beaa14370f511aee9da7830942f7"},{"Digest":"0x3af98cdd656e7c6575b205b86537b025fcb6acf75a474fc5ba47658b1a7f3545"},{"Digest":"0x601727bfe573710324b2cbc9d34708979870423adca4ec7ec7f6c34c63c5ee13"},{"Digest":"0xd502230a431bc09ce667db68ec89bc81a8234be75fcb5594c5480910548f737b"},{"Digest":"0x3a37c1ad7341c2bdab8ce15ae3bbc1e8f5983493f6eee5578c3df12eee5bfd3a"},{"Digest":"0x679906dd758da0848ec54a7e1a1560e6f7bc2437a96c0b74115f4ad79df6d8f3"},{"Digest":"0xe81236712d30704c3c8e97761bb155d338df6536cc5c1f376bbb505d0365c738"},{"Branch":[{"Digest":"0x132b7ea0c3174dd15a631d5d3acf7846149f8e2b0df7daf9f153a8cabb881941"},null,null,{"Branch":[null,null,null,{"Branch":[null,null,null,null,{"Branch":[null,null,null,null,null,null,null,null,null,null,null,{"Digest":"0xb85f4322dc70cb69433f1011cd7d86681e5fb3a8b8471220ebfe6ab99680e907"},null,{"Leaf":[[1,14,7,3,14,1,12,5,1,3,8,4,0,0,15,0,9,13,6,12,14,9,0,12,1,9,2,0,14,9,0,3,6,0,9,8,12,5,1,11,1,9,3,6,12,7,11,9,8,10,7,13,14,2],[248,78,1,138,2,43,218,16,14,178,56,8,171,111,160,86,232,31,23,27,204,85,166,255,131,69,230,146,192,248,110,91,72,224,27,153,108,173,192,1,98,47,181,227,99,180,33,160,197,210,70,1,134,247,35,60,146,126,125,178,220,199,3,192,229,0,182,83,202,130,39,59,123,250,216,4,93,133,164,112]]},null,null]},null,null,{"Digest":"0xaa9a1c9a362e7f26b92c7cc6bf0e260746a1f0282706486f28dec3b5ad2244a9"},null,null,null,null,null,null,null,null]},null,null,null,null,null,{"Digest":"0x324af29be87648f1e74281dfc338648b6919080973f4ad9b8fec7c4ad0266f20"},null,null,null,null,null,null]},null,{"Digest":"0xbe175a9602770eb28e02cd034e27395299c64ade95df0e07ce20b61106c6397d"},null,null,null,null,null,null,{"Digest":"0x8e4f92b107a3210fdf7c69a4004eb409bd7c5123dc04bb0e184110adc24e25c9"},null,null,null]},null,{"Digest":"0x6349fe57d19d7918d2f608fadd892f99d9c0f9244d3a048968034ae3639af0b3"}]},{"Digest":"0xd8562444dc649316b670625cedea8fb000fd929eca8d51ca9ade15d67b020b9c"},{"Digest":"0x10fa9fac3eab7a2d80440a7a99370a9c277e0773fff1fe40906c43517e9d2ca4"},{"Digest":"0x41fb7dea82b2310e064566f4f5dfdcbd8ba9ee925b3edb03b90db08fdbb9f6cd"},{"Digest":"0xb1c8c3fd9456a2e63f6092f5b1d8327812036619481386b0dd42ac2b316ff2cb"},{"Digest":"0x09d1c11b0b02ad95148037ae40fe8969b729743f680635b2b5fc09a9da8aac0a"},{"Digest":"0xf9bb7ec6cf362e2bb5700357e6d07aabfa89d9430d6cf3d9d7a82a161712800d"},{"Digest":"0xd49ef7e7667ec1b0cfc1ca1112927759f6ec7844c563e7620d65e72b14c5346d"}]}]},{"Digest":"0xe49f3e2e5231dc89cd93886ec80e191ea3f796f00b6b63986669e9f2e6891d6a"},{"Digest":"0xad268ceb7b99c464ddcd285272ec172f8478a850cc622815370dd113183dd13b"},{"Digest":"0xf6c59ac04e1d9c65c7f45273a451000d75565996bd7cbda145b134bf727c00b2"},{"Digest":"0x6b3655472e24d9f758bc15455b7c847a6d778632ac9845e3abc9c8de92ebe6fd"},{"Digest":"0xa0ba645ae6280c832fbf24d19cbeb1e7f647606551b5ec587b4940408a2ad9df"},{"Digest":"0x4ad8b330f32bbb7698204b8265447ecb2d439de315dab029b638052cce48eb81"},{"Digest":"0x9adb650231bc464e56a148cd7b8a4a2c541c23574b943d20d8ed18d80f951ba4"},{"Digest":"0x1e6a8f9877462faddd7bb90b51347751aa7a80cb1e970cfef78b106d351c3072"},{"Digest":"0x5d3caaa7ddf8e955dd9910496d9a35f059ba165e223ec3139e7e312dbdfe0050"},{"Digest":"0xdb462a19ddfdea24451f5a4e27a5594b583d8ee41bf6a0b78e80ee671bb3cf38"},{"Digest":"0x1c4f97704727e4bd58ce52a433c7b10b6527533d2aefe75e774d3e73b5b34f97"}]},{"Digest":"0x302d9354b573a429d22d0c486aec9cf7de7500b4bcf98e73c3ac697543d2490f"},{"Digest":"0xa57d3b9733b3df7dda1967622638a84bea14a65f04fd11a0ab8afb25256770fd"},{"Digest":"0x0ab81d4576fa942bb6a84bab248ff6e45c2360b3c38f0705ccb02c47486c657c"},{"Digest":"0x513866db1cbcb67bb09e4568ee3334725c5d835b74225396488f1775f687760a"},{"Digest":"0x4e5ec4495d7e6adad9077d30ccb3d480721ec9b74e5a0561cb91c610e6f0989b"},{"Digest":"0x260c9262f5d66c4f57ee841d26ddc9080681467b5a4d95d23c0d8b4a46ac7b09"},{"Digest":"0xb811b7ee8dd06b4d996f07f1923877235432b9eb7e817211d78ee671b0d1ebbc"},{"Digest":"0x3fb08c49ff0564b3305e4554996e0129296773ad62545673ce2e2607992b40d1"},{"Digest":"0x04be653bc9aefc3dba9fa1cd73efb7c4b945b00ca184410e956e4f091abc46cb"}]},{"Digest":"0x8f020a1a1c3cae0a59ad231da00345ae089cf235d42665b232699abf9f14a49e"},{"Digest":"0xd5fc482fe9cf579960cfa7e737640e77a33b7ca5c8d84f5948df8d89ac361373"},{"Digest":"0x175571d3e3ad1606f1df4051d0030b16cbd569493c32eb2bcf134600c4fba39e"}]},"storage_tries":[{"Branch":[{"Digest":"0x56544afefeed5e361e4df3e2d663bb228daf6f3a073afd6c995327f7bee32cb7"},{"Digest":"0x591c9d0acd182840738019fedc864367512620f91ec23bcedbed07f99a476923"},{"Digest":"0xbd4273a3fc00e2a5c700caf4a2775197a5bd17bad1abbfd74d0c87f904a44976"},{"Digest":"0x4e45197d666cd89f175f4eb83d79d2d0a3d51c4d9ba623fc2b0fa1989f1e3a31"},{"Digest":"0x32cf5aa9660540fb95834497a5bd687c45c287de74c7d188152e52e1d7946c18"},{"Digest":"0x4062f7f555550a5035f6651105bbbd665671f33c9309bf2dc6c8b67b8168141e"},{"Digest":"0x7939f313928fee8b56cd07d57974f4d55e1f340d93f25197ed354a578acf9d7a"},{"Digest":"0x35afb0b9306eb976575d65789e19510628f9405a8f36daac79a6c8f037de5a5a"},{"Digest":"0x9097fea8996befb8a4126d3798cf79a6c7e0d1336f5ac36bfbe652137b305f82"},{"Digest":"0x8d857ba6ee988703b647ac79283cad8d382b4754c60be47d2ab80db2e1aaa377"},{"Digest":"0x3d7d2abf687c278ca3c9fa351f2e6bbed471a412b59b578e75e789988797b09a"},{"Digest":"0xb72f8830126db2e2b254db43a787c85e94bb449585447a0523344fcb4c6f2836"},{"Digest":"0x32562672655a89e13bfded3af8f56ece0e4ac753e60ce7172d84b4fbf8cc40bd"},{"Digest":"0xc33c225e5e9ecb7b02c074d758e2500674ea0a02534433dcdeb0a137d96be176"},{"Digest":"0x46c6e2573d95970c5068685b56eebb28b5d6506eb486235c010198af9d474fb9"},{"Branch":[{"Branch":[{"Digest":"0x02073d18333e691bddb8642ca82b732db6415c9f84a1149b3bb710824214ceb2"},{"Digest":"0x31d5bc9659e75a99e973418b4794c0d9241a3482d6359cb11b0753d0e460a269"},{"Digest":"0xe79421201d09eeb52b36e427967ed621d245fb04769487d7ebdc5cf7d44b17b4"},{"Digest":"0x18ef63217fc35b0ec780d2427113b6e35a714c4c17b27993cf6227b551912f58"},{"Digest":"0xa53a1b7d3f70c40201345314bf7fb4446bcf79dde781102143705d6b66486e53"},{"Digest":"0x007a444b6e07e59e910751aca367d5fb2d4db3126fe9b9bfae05a7f652cac56f"},{"Digest":"0x460db8fc9fcb2d58cc58997614c5a6545b8c4ea7342fef05768a5691ca7fe5ca"},{"Digest":"0x35ec4099628336dd7f3a13caa20a54d2611b4d8b97a112ff357e0eb0541f189f"},{"Digest":"0x49355ad2e8f7bf8b6ce8084088aa894c07ded44b315695aa1b3fb3551d35d4fb"},{"Digest":"0x83638c0eed723390afd17ac07ad64aa3f298affe5078a3ec49e9b7b463c12fed"},{"Digest":"0x90424abf55dbe91f187e2eab0a91771c4909ee989dddd2263c5ffd8353e44a91"},{"Digest":"0xf708a9096c48c1baed6a8cd3f9409b1863eae8276801a89a6152806947f90a7d"},{"Digest":"0x467c6d27ad319df67a07e54aa5ba51d914c1191c6f179e045ba5e4b1362e1265"},{"Branch":[{"Digest":"0x957c5ebf39508dce06b519f3357407ce9b0c7e325a5b5baf20356802119e2a1d"},{"Digest":"0xdcdcda02bab51aee6cec341859880c7d3a74b2a708c6837a283e9140d742ae71"},{"Digest":"0xfe878f6d7851d2c4a89a747005f6ec12211eea53845502d577358c38d99b0540"},{"Digest":"0xba01139006d0b39ceae595d8736eeb0614536ec331df968bb7a87726d663619e"},{"Digest":"0xd835f0fb96ed233d45a950b9374600896dce6e9f9e9f415e16f56d58db6328ea"},{"Digest":"0x763bc0283a452d3e45a3c40bc33ace9c3bf8327a4f98f3939b6fb10797692ea9"},{"Digest":"0x926a4be03b7bfb0176a0a07d1737c8bf6d7a73d1d02744a1bf26736c3a853227"},{"Digest":"0xbff83b63f63ff94b661fb0a7c3cce98b8407f55097a90e1af5351b21f649d32c"},{"Digest":"0xe0e716a063b31091e183787523f5532b2dc7ab69a1dd66cc90cfb116ad477d20"},{"Digest":"0xfe7d2af4a9f50363f9fc87756d737bd5ea2ce08079a592af54285923e44cbedd"},null,{"Digest":"0xb883893ad62f19b1ade0ead65ab810ea10bc653dc37b2d6e9536ddffab16c44b"},{"Digest":"0x1a578cb4375a74230fc289891bc27480edb2b7b162f8d0636ffd9cffa155cb06"},null,{"Digest":"0x1ab003882db00b52c3298b9f8e5377e64facdbd98d8a31376d7f4b4f7014e11b"},{"Branch":[null,null,null,null,null,null,null,null,{"Digest":"0xf0ec532af391e6dc77f2c9867afce87e39293059a5f8ddf2b21b38d8e4dd23b6"},null,null,null,null,null,{"Digest":"0xb92295774b00d67bfc53715b07b142a21c554b7f1cce914aefc2157459fc289c"},null]}]},{"Digest":"0x45b01213c9e56a5527cbb6ac2dee8cff756ebbec4f9a4106794a62d73e95bddb"},{"Digest":"0xb00a95f416324179cea6c4a2af4bfb813a2925aeb02da845510630a1ecab965d"}]},{"Digest":"0xd2b6f5aa79e4367be1acedfb774fb31ff72d741d7ba63f0fd54057125c6bd4d4"},{"Digest":"0x6d8c5078e4f7cd7313e3a7e93313158a1eb2f61178b4a3a7e955fff12d92bffb"},{"Digest":"0x89eb39899f8e94c8fc33d97a00bd24c9d9b8291595724ec90f94ca777fb5140f"},{"Digest":"0xc24898b9b1d020be564e759e1a8e6ab071685d8f0f6ddedf7dc40f57d5769c74"},{"Digest":"0x54dfd5d63e4d92ae013b4cc1bf1d9cc1bc275a5b23341424a003b24d9bf80ec8"},{"Digest":"0xa71719c64486e2adab39b2ad208f08d3f5775b8daa5cd2c06ec1f9d6903655ab"},{"Digest":"0xdef3321462d8cb9948d0c4d4de63e604b11cb352b70781051b33f5ac02453ca0"},{"Digest":"0xda0b890c9c5ca63b53939d3fcaf8f663a16d0c64866f0730dafc061273030532"},{"Digest":"0x83780e60779372f92ba09f2008d94dd81d1e61703de74d3e2de72ab475ee4a18"},{"Digest":"0x3875c5b603e498fe47a7dc24ecba5fffc29492d74a453ea6bb80a82c3de6e2b1"},{"Digest":"0x21fbc721597b9e854b0f29ae0e5ee78c039bcbe2bc954d9a2f2f7b80659700d6"},{"Digest":"0x4ddf483433da88aca29480ee15efb5ed56468717f55be6f811f55f3b720ff5b1"},{"Digest":"0xc51c210305336706d9e14799b45ca38cf015518ca5aed8698eefdbd46f00a7b0"},{"Digest":"0xd530cfea8782e19146a8865daae4f1a3c6ddb6e23fbb0cddb0a7131fbdd5eccc"},{"Digest":"0x45e57bb66f6807562ca3a128a38bdb69e6a736f9d0216e76912eb0f2fcef21ee"}]}]}],"contracts":["0x608060405234801561001057600080fd5b50600436106101775760003560e01c8063715018a6116100d8578063a0712d681161008c578063d505accf11610066578063d505accf14610383578063dd62ed3e14610396578063f2fde38b146103dc57600080fd5b8063a0712d681461034a578063a457c2d71461035d578063a9059cbb1461037057600080fd5b80637ecebe00116100bd5780637ecebe00146102c95780638da5cb5b146102ff57806395d89b411461034257600080fd5b8063715018a614610283578063781603761461028d57600080fd5b8063313ce5671161012f5780633950935111610114578063395093511461022757806340c10f191461023a57806370a082311461024d57600080fd5b8063313ce567146102095780633644e5151461021e57600080fd5b806318160ddd1161016057806318160ddd146101bd57806323b872dd146101cf57806330adf81f146101e257600080fd5b806306fdde031461017c578063095ea7b31461019a575b600080fd5b6101846103ef565b604051610191919061129c565b60405180910390f35b6101ad6101a83660046112da565b610481565b6040519015158152602001610191565b6002545b604051908152602001610191565b6101ad6101dd366004611304565b610498565b6101c17f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60055460405160ff9091168152602001610191565b6101c160075481565b6101ad6102353660046112da565b61050e565b6101ad6102483660046112da565b610551565b6101c161025b366004611340565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b61028b6105ea565b005b6101846040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b6101c16102d7366004611340565b73ffffffffffffffffffffffffffffffffffffffff1660009081526006602052604090205490565b600554610100900473ffffffffffffffffffffffffffffffffffffffff1660405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610191565b6101846106e5565b6101ad61035836600461135b565b6106f4565b6101ad61036b3660046112da565b610791565b6101ad61037e3660046112da565b6107ed565b61028b610391366004611374565b6107fa565b6101c16103a43660046113e7565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b61028b6103ea366004611340565b610b1b565b6060600380546103fe9061141a565b80601f016020809104026020016040519081016040528092919081815260200182805461042a9061141a565b80156104775780601f1061044c57610100808354040283529160200191610477565b820191906000526020600020905b81548152906001019060200180831161045a57829003601f168201915b5050505050905090565b600061048e338484610cdd565b5060015b92915050565b60006104a5848484610e91565b61050484336104ff856040518060600160405280602881526020016114d46028913973ffffffffffffffffffffffffffffffffffffffff8a16600090815260016020908152604080832033845290915290205491906110bb565b610cdd565b5060019392505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152812054909161048e9185906104ff9086611102565b60055460009073ffffffffffffffffffffffffffffffffffffffff6101009091041633146105e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b61048e8383611112565b60055473ffffffffffffffffffffffffffffffffffffffff610100909104163314610671576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105d7565b600554604051600091610100900473ffffffffffffffffffffffffffffffffffffffff16907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff169055565b6060600480546103fe9061141a565b60055460009073ffffffffffffffffffffffffffffffffffffffff61010090910416331461077e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105d7565b6107883383611112565b5060015b919050565b600061048e33846104ff856040518060600160405280602581526020016114fc6025913933600090815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8d16845290915290205491906110bb565b600061048e338484610e91565b73ffffffffffffffffffffffffffffffffffffffff8716610877576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f494e56414c49445f4f574e45520000000000000000000000000000000000000060448201526064016105d7565b834211156108e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f494e56414c49445f45585049524154494f4e000000000000000000000000000060448201526064016105d7565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526006602090815260408083205460075482517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98186015280840196909652958c166060860152608085018b905260a0850181905260c08086018b90528251808703909101815260e08601909252815191909201207f19010000000000000000000000000000000000000000000000000000000000006101008501526101028401949094526101228301939093529061014201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206000845290830180835281905260ff8816918301919091526060820186905260808201859052915060019060a0016020604051602081039080840390855afa158015610a36573d6000803e3d6000fd5b5050506020604051035173ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614610ad4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f494e56414c49445f5349474e415455524500000000000000000000000000000060448201526064016105d7565b610adf82600161146e565b73ffffffffffffffffffffffffffffffffffffffff8a16600090815260066020526040902055610b10898989610cdd565b505050505050505050565b60055473ffffffffffffffffffffffffffffffffffffffff610100909104163314610ba2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105d7565b73ffffffffffffffffffffffffffffffffffffffff8116610c45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016105d7565b60055460405173ffffffffffffffffffffffffffffffffffffffff80841692610100900416907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36005805473ffffffffffffffffffffffffffffffffffffffff909216610100027fffffffffffffffffffffff0000000000000000000000000000000000000000ff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff8316610d7f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016105d7565b73ffffffffffffffffffffffffffffffffffffffff8216610e22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016105d7565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8316610f34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016105d7565b73ffffffffffffffffffffffffffffffffffffffff8216610fd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016105d7565b611021816040518060600160405280602681526020016114ae6026913973ffffffffffffffffffffffffffffffffffffffff861660009081526020819052604090205491906110bb565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220939093559084168152205461105d9082611102565b73ffffffffffffffffffffffffffffffffffffffff8381166000818152602081815260409182902094909455518481529092918616917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610e84565b81830381848211156110fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d7919061129c565b509392505050565b8082018281101561049257600080fd5b73ffffffffffffffffffffffffffffffffffffffff821661118f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016105d7565b60025461119c9082611102565b60025573ffffffffffffffffffffffffffffffffffffffff82166000908152602081905260409020546111cf9082611102565b73ffffffffffffffffffffffffffffffffffffffff8316600081815260208181526040808320949094559251848152919290917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b6000815180845260005b818110156112575760208185018101518683018201520161123b565b81811115611269576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006112af6020830184611231565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461078c57600080fd5b600080604083850312156112ed57600080fd5b6112f6836112b6565b946020939093013593505050565b60008060006060848603121561131957600080fd5b611322846112b6565b9250611330602085016112b6565b9150604084013590509250925092565b60006020828403121561135257600080fd5b6112af826112b6565b60006020828403121561136d57600080fd5b5035919050565b600080600080600080600060e0888a03121561138f57600080fd5b611398886112b6565b96506113a6602089016112b6565b95506040880135945060608801359350608088013560ff811681146113ca57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b600080604083850312156113fa57600080fd5b611403836112b6565b9150611411602084016112b6565b90509250929050565b600181811c9082168061142e57607f821691505b60208210811415611468577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600082198211156114a8577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50019056fe45524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220eabef41c79e988bbef5573106f3825656f6522b0a2771b005adfc744729606a364736f6c634300080a0033"],"ancestors":[]},"commit":{"proof":["0x77935a302d194a1262ae6923113ae86db0e6e19ce213f5617d9d4cc2f626110c","0x3090bafc416d3cc1a56b97d38a63efea01ba1eba02242b606525baa463529002","0x749c8ed86568b30f9629d0172e0e7fe26f58413cb83c871b6c48a41fb11131d4","0x246945f975282f5ec2e8f59581df1897c3e419d5b4110bd6268b0286b5e5dd96","0x91dc9f8f1e388ec93c8d3b2176d5587aed5fa9643b121f2d0d5e4cb08d3cd188","0x948527f1b9cf52bbcb126333f05a197a1720b0e5c795cd5355210148737ed7d0","0x7e58387dc24ef528448144386ea433a8ce1d476a98fb225c054c5a54d526729d","0xdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71","0x5838724cb04e7784e11f296abfe83c4ea9cb7588dc627b62fca673e2a65c6645","0x0000000000000000000000000000000000000000000000000000000000000000","0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b","0x191fef23877fcdda042451463bb3c0356c9e9cf3ffa92bd6d4be44ddcdb45a01"],"timestamp":1727775084}}} \ No newline at end of file diff --git a/steel/tests/corruption.rs b/steel/tests/corruption.rs index f825f889..7124926a 100644 --- a/steel/tests/corruption.rs +++ b/steel/tests/corruption.rs @@ -29,6 +29,7 @@ use alloy_primitives::{address, Address, Bytes, B256, U256}; use anyhow::Context; use risc0_steel::{ ethereum::{EthBlockHeader, EthEvmEnv, EthEvmInput, ETH_SEPOLIA_CHAIN_SPEC}, + host::BlockNumberOrTag, Commitment, Contract, StateAccount, }; use serde_json::{from_value, to_value, Value}; @@ -124,7 +125,11 @@ fn mock_anvil_guest(input: EthEvmInput) -> Commitment { /// Creates an `EthEvmInput` using live RPC nodes preflighting `IERC20(USDT).balanceOf(0x0)`. async fn rpc_usdt_input() -> anyhow::Result { - let mut env = EthEvmEnv::builder().rpc(RPC_URL.parse()?).build().await?; + let mut env = EthEvmEnv::builder() + .rpc(RPC_URL.parse()?) + .block_number_or_tag(BlockNumberOrTag::Parent) + .build() + .await?; env = env.with_chain_spec(Ð_SEPOLIA_CHAIN_SPEC); Contract::preflight(USDT_ADDRESS, &mut env) .call_builder(&USDT_CALL) From 82a0ddff9aa7d9037f67f5865b995ac4561eebe9 Mon Sep 17 00:00:00 2001 From: Wolfgang Welz Date: Fri, 4 Oct 2024 16:56:02 +0200 Subject: [PATCH 5/5] move beacon API into builder --- examples/erc20/host/src/main.rs | 11 +- examples/token-stats/host/src/main.rs | 5 +- steel/src/beacon.rs | 62 +++--- steel/src/block.rs | 41 ++-- steel/src/contract.rs | 56 +++--- steel/src/ethereum.rs | 2 +- steel/src/host/builder.rs | 272 ++++++++++++++++++++++++++ steel/src/host/mod.rs | 191 ++++-------------- steel/src/lib.rs | 41 ++-- steel/tests/corruption.rs | 3 +- 10 files changed, 410 insertions(+), 274 deletions(-) create mode 100644 steel/src/host/builder.rs diff --git a/examples/erc20/host/src/main.rs b/examples/erc20/host/src/main.rs index 9b45fea8..d9c14d18 100644 --- a/examples/erc20/host/src/main.rs +++ b/examples/erc20/host/src/main.rs @@ -19,7 +19,7 @@ use clap::Parser; use erc20_methods::ERC20_GUEST_ELF; use risc0_steel::{ ethereum::{EthEvmEnv, ETH_SEPOLIA_CHAIN_SPEC}, - Contract, + Commitment, Contract, }; use risc0_zkvm::{default_executor, ExecutorEnv}; use tracing_subscriber::EnvFilter; @@ -77,8 +77,6 @@ async fn main() -> Result<()> { CONTRACT, returns._0 ); - // Get the commitment to verify execution later. - let commitment = env.commitment().clone(); // Finally, construct the input from the environment. let input = env.into_input().await?; @@ -95,9 +93,10 @@ async fn main() -> Result<()> { .context("failed to run executor")? }; - // The commitment in the journal should match. - let bytes = session_info.journal.as_ref(); - assert!(bytes.starts_with(&commitment.abi_encode())); + // The journal should be the ABI encoded commitment. + let commitment = Commitment::abi_decode(session_info.journal.as_ref(), true) + .context("failed to decode journal")?; + println!("{:?}", commitment); Ok(()) } diff --git a/examples/token-stats/host/src/main.rs b/examples/token-stats/host/src/main.rs index 52c23d82..eed3f774 100644 --- a/examples/token-stats/host/src/main.rs +++ b/examples/token-stats/host/src/main.rs @@ -73,8 +73,6 @@ async fn main() -> Result<()> { CONTRACT, rate ); - // Get the commitment to verify execution later. - let commitment = env.commitment().clone(); // Finally, construct the input from the environment. let input = env.into_input().await?; @@ -91,9 +89,10 @@ async fn main() -> Result<()> { .context("failed to run executor")? }; + // The journal should be the ABI encoded commitment. let apr_commit = APRCommitment::abi_decode(&session_info.journal.bytes, true) .context("failed to decode journal")?; - assert_eq!(apr_commit.commitment, commitment); + println!("{:?}", apr_commit.commitment); // Calculation is handling `/ 10^18 * 100` to match precision for a percentage. let apr = apr_commit.annualSupplyRate as f64 / 10f64.powi(16); diff --git a/steel/src/beacon.rs b/steel/src/beacon.rs index 776e9435..af6f2ef0 100644 --- a/steel/src/beacon.rs +++ b/steel/src/beacon.rs @@ -105,11 +105,7 @@ impl BlockHeaderCommit #[cfg(feature = "host")] pub(crate) mod host { use super::*; - use crate::{ - ethereum::EthBlockHeader, - host::{db::AlloyDb, HostEvmEnv}, - BlockInput, - }; + use crate::ethereum::EthBlockHeader; use alloy::{network::Ethereum, providers::Provider, transports::Transport}; use alloy_primitives::B256; use anyhow::{bail, ensure, Context}; @@ -119,33 +115,6 @@ pub(crate) mod host { use proofs::ProofAndWitness; use url::Url; - impl BeaconInput { - /// Derives the verifiable input from a [HostEvmEnv] and a Beacon API endpoint. - pub(crate) async fn from_env_and_endpoint( - env: HostEvmEnv, EthBlockHeader>, - url: Url, - ) -> anyhow::Result - where - T: Transport + Clone, - P: Provider, - { - let client = BeaconClient::new(url).context("invalid URL")?; - let (commit, beacon_root) = - create_beacon_commit(env.header(), "block_hash".into(), env.provider(), &client) - .await?; - let block_hash = env.header().seal(); - commit - .verify(block_hash, beacon_root) - .context("proof derived from API does not verify")?; - - let input = BlockInput::from_env(env) - .await - .context("failed to derive block input")?; - - Ok(BeaconInput::new(input, commit)) - } - } - pub(crate) mod client { use ethereum_consensus::{ phase0::SignedBeaconBlockHeader, primitives::Root, types::mainnet::SignedBeaconBlock, @@ -232,6 +201,35 @@ pub(crate) mod host { } } + impl BeaconCommit { + /// Creates a new `BeaconCommit` for the provided header which proofs the inclusion of the + /// corresponding block hash in the referenced beacon block. + pub(crate) async fn from_header( + header: &Sealed, + rpc_provider: P, + beacon_url: Url, + ) -> anyhow::Result + where + T: Transport + Clone, + P: Provider, + { + let client = BeaconClient::new(beacon_url).context("invalid URL")?; + let (commit, beacon_root) = + create_beacon_commit(header, "block_hash".into(), rpc_provider, &client).await?; + commit + .verify(header.seal(), beacon_root) + .context("proof derived from API does not verify")?; + + log::info!( + "Committing to parent beacon block: root={},timestamp={}", + beacon_root, + commit.timestamp + ); + + Ok(commit) + } + } + /// Creates a beacon commitment that `field` is contained in the `ExecutionPayload` of the /// beacon block corresponding to `header`. async fn create_beacon_commit( diff --git a/steel/src/block.rs b/steel/src/block.rs index 38203d0b..c16822a0 100644 --- a/steel/src/block.rs +++ b/steel/src/block.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{state::StateDb, EvmBlockHeader, EvmEnv, GuestEvmEnv, MerkleTrie}; +use crate::{state::StateDb, Commitment, EvmBlockHeader, EvmEnv, GuestEvmEnv, MerkleTrie}; use ::serde::{Deserialize, Serialize}; use alloy_primitives::{map::HashMap, Bytes}; @@ -61,8 +61,9 @@ impl BlockInput { self.contracts, block_hashes, ); + let commit = Commitment::from_block_header(&header); - EvmEnv::new(db, header) + EvmEnv::new(db, header, commit) } } @@ -72,20 +73,20 @@ pub mod host { use super::BlockInput; use crate::{ - host::{ - db::{AlloyDb, ProviderDb}, - HostEvmEnv, - }, + host::db::{AlloyDb, ProofDb, ProviderDb}, EvmBlockHeader, }; use alloy::{network::Network, providers::Provider, transports::Transport}; + use alloy_primitives::Sealed; use anyhow::{anyhow, ensure}; - use log::{debug, info}; + use log::debug; impl BlockInput { - /// Derives the verifiable input from a [HostEvmEnv]. - pub(crate) async fn from_env( - env: HostEvmEnv, H>, + /// Creates the `BlockInput` containing the necessary EVM state that can be verified against + /// the block hash. + pub(crate) async fn from_proof_db( + mut db: ProofDb>, + header: Sealed, ) -> anyhow::Result where T: Transport + Clone, @@ -94,17 +95,11 @@ pub mod host { H: EvmBlockHeader + TryFrom<::HeaderResponse>, ::HeaderResponse>>::Error: Display, { - // safe unwrap: env is never returned without a DB - let mut db = env.db.unwrap(); - assert_eq!( - db.inner().block_hash(), - env.header.seal(), - "DB block mismatch" - ); + assert_eq!(db.inner().block_hash(), header.seal(), "DB block mismatch"); let (state_trie, storage_tries) = db.state_proof().await?; ensure!( - env.header.state_root() == &state_trie.hash_slow(), + header.state_root() == &state_trie.hash_slow(), "accountProof root does not match header's stateRoot" ); @@ -113,7 +108,7 @@ pub mod host { // retrieve ancestor block headers let mut ancestors = Vec::new(); - for rlp_header in db.ancestor_proof(env.header.number()).await? { + for rlp_header in db.ancestor_proof(header.number()).await? { let header: H = rlp_header .try_into() .map_err(|err| anyhow!("header invalid: {}", err))?; @@ -129,14 +124,8 @@ pub mod host { debug!("contracts: {}", contracts.len()); debug!("ancestor blocks: {}", ancestors.len()); - info!( - "Commitment to block hash {} at {}", - env.header.seal(), - env.header.number() - ); - let input = BlockInput { - header: env.header.into_inner(), + header: header.into_inner(), state_trie, storage_tries, contracts, diff --git a/steel/src/contract.rs b/steel/src/contract.rs index 0dc7e50d..f110adfe 100644 --- a/steel/src/contract.rs +++ b/steel/src/contract.rs @@ -84,7 +84,7 @@ impl<'a, H> Contract<&'a GuestEvmEnv> { } /// Initializes a call builder to execute a call on the contract. - pub fn call_builder(&self, call: &C) -> CallBuilder> { + pub fn call_builder(&self, call: &S) -> CallBuilder> { CallBuilder::new(self.env, self.address, call) } } @@ -94,19 +94,19 @@ impl<'a, H> Contract<&'a GuestEvmEnv> { /// Once configured, call with [CallBuilder::call]. #[derive(Debug, Clone)] #[must_use] -pub struct CallBuilder { - tx: CallTxData, +pub struct CallBuilder { + tx: CallTxData, env: E, } -impl CallBuilder { +impl CallBuilder { /// The default gas limit for function calls. const DEFAULT_GAS_LIMIT: u64 = 30_000_000; /// Creates a new builder for the given contract call. - fn new(env: E, address: Address, call: &C) -> Self + fn new(env: E, address: Address, call: &S) -> Self where - C: SolCall, + S: SolCall, { let tx = CallTxData { caller: address, // by default the contract calls itself @@ -160,7 +160,7 @@ mod host { }; use anyhow::{anyhow, Context, Result}; - impl<'a, D: Database, H> Contract<&'a mut HostEvmEnv> { + impl<'a, D: Database, H, C> Contract<&'a mut HostEvmEnv> { /// Constructor for preflighting calls to an Ethereum contract on the host. /// /// Initializes the environment for calling functions on the Ethereum contract, fetching @@ -169,26 +169,26 @@ mod host { /// /// [EvmEnv::into_input]: crate::EvmEnv::into_input /// [EvmEnv]: crate::EvmEnv - pub fn preflight(address: Address, env: &'a mut HostEvmEnv) -> Self { + pub fn preflight(address: Address, env: &'a mut HostEvmEnv) -> Self { Self { address, env } } /// Initializes a call builder to execute a call on the contract. - pub fn call_builder( + pub fn call_builder( &mut self, - call: &C, - ) -> CallBuilder> { + call: &S, + ) -> CallBuilder> { CallBuilder::new(self.env, self.address, call) } } - impl<'a, C, T, N, P, H> CallBuilder, H>> + impl<'a, S, T, N, P, H, C> CallBuilder, H, C>> where T: Transport + Clone, N: Network, P: Provider + Send + 'static, - C: SolCall + Send + 'static, - ::Return: Send, + S: SolCall + Send + 'static, + ::Return: Send, H: EvmBlockHeader + Clone + Send + 'static, { /// Fetches all the EIP-1186 storage proofs from the `access_list`. This can help to @@ -208,10 +208,10 @@ mod host { /// This uses [tokio::task::spawn_blocking] to run the blocking revm execution. /// /// [EvmEnv]: crate::EvmEnv - pub async fn call(self) -> Result { + pub async fn call(self) -> Result { log::info!( "Executing preflight calling '{}' on {}", - C::SIGNATURE, + S::SIGNATURE, self.tx.to ); @@ -233,7 +233,7 @@ mod host { // restore the DB before handling errors, so that we never return an env without a DB self.env.db = Some(db); - result.map_err(|err| anyhow!("call '{}' failed: {}", C::SIGNATURE, err)) + result.map_err(|err| anyhow!("call '{}' failed: {}", S::SIGNATURE, err)) } /// Automatically prefetches the access list before executing the call using an [EvmEnv] @@ -244,7 +244,7 @@ mod host { /// [CallBuilder::call]. See the corresponding methods for more information. /// /// [EvmEnv]: crate::EvmEnv - pub async fn call_with_prefetch(self) -> Result { + pub async fn call_with_prefetch(self) -> Result { let access_list = { let tx = ::TransactionRequest::default() .with_from(self.tx.caller) @@ -273,16 +273,16 @@ mod host { } } -impl<'a, C, H> CallBuilder> +impl<'a, S, H> CallBuilder> where - C: SolCall, + S: SolCall, H: EvmBlockHeader, { /// Executes the call and returns an error if the call fails. /// /// In general, it's recommended to use [CallBuilder::call] unless explicit error handling is /// required. - pub fn try_call(self) -> Result { + pub fn try_call(self) -> Result { let mut evm = new_evm::<_, H>( WrapStateDb::new(self.env.db()), self.env.cfg_env.clone(), @@ -302,25 +302,25 @@ where /// Transaction data to be used with [CallBuilder] for an execution. #[derive(Debug, Clone)] -struct CallTxData { +struct CallTxData { caller: Address, gas_limit: u64, gas_price: U256, to: Address, value: U256, data: Vec, - phantom: PhantomData, + phantom: PhantomData, } -impl CallTxData { +impl CallTxData { /// Compile-time assertion that the call C has a return value. const RETURNS: () = assert!( - mem::size_of::() > 0, + mem::size_of::() > 0, "Function call must have a return value" ); /// Executes the call in the provided [Evm]. - fn transact(self, evm: &mut Evm<'_, EXT, DB>) -> Result + fn transact(self, evm: &mut Evm<'_, EXT, DB>) -> Result where DB: Database, ::Error: std::error::Error + Send + Sync + 'static, @@ -351,10 +351,10 @@ impl CallTxData { ExecutionResult::Revert { output, .. } => Err(format!("reverted: {}", output)), ExecutionResult::Halt { reason, .. } => Err(format!("halted: {:?}", reason)), }?; - let returns = C::abi_decode_returns(&output.into_data(), true).map_err(|err| { + let returns = S::abi_decode_returns(&output.into_data(), true).map_err(|err| { format!( "return type invalid; expected '{}': {}", - as SolType>::SOL_NAME, + as SolType>::SOL_NAME, err ) })?; diff --git a/steel/src/ethereum.rs b/steel/src/ethereum.rs index 37c160f1..6e65c38b 100644 --- a/steel/src/ethereum.rs +++ b/steel/src/ethereum.rs @@ -55,7 +55,7 @@ pub static ETH_MAINNET_CHAIN_SPEC: Lazy = Lazy::new(|| ChainSpec { }); /// [EvmEnv] for Ethereum. -pub type EthEvmEnv = EvmEnv; +pub type EthEvmEnv = EvmEnv; /// [EvmInput] for Ethereum. pub type EthEvmInput = EvmInput; diff --git a/steel/src/host/builder.rs b/steel/src/host/builder.rs new file mode 100644 index 00000000..eacc751d --- /dev/null +++ b/steel/src/host/builder.rs @@ -0,0 +1,272 @@ +// Copyright 2024 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::{ + beacon::BeaconCommit, + ethereum::EthBlockHeader, + host::{ + db::{AlloyDb, ProofDb, ProviderConfig}, + BlockNumberOrTag, EthHostEvmEnv, HostEvmEnv, + }, + EvmBlockHeader, EvmEnv, +}; +use alloy::{ + network::{BlockResponse, Ethereum, Network}, + providers::{Provider, ProviderBuilder, ReqwestProvider}, + transports::Transport, +}; +use alloy_primitives::Sealable; +use anyhow::{anyhow, Context, Result}; +use std::{fmt::Display, marker::PhantomData}; +use url::Url; + +impl EvmEnv<(), H, ()> { + /// Creates a builder for building an environment. + /// + /// Create an Ethereum environment bast on the latest block: + /// ```rust,no_run + /// # use risc0_steel::ethereum::EthEvmEnv; + /// # use url::Url; + /// # #[tokio::main(flavor = "current_thread")] + /// # async fn main() -> anyhow::Result<()> { + /// # let url = Url::parse("https://ethereum-rpc.publicnode.com")?; + /// let env = EthEvmEnv::builder().rpc(url).build().await?; + /// # Ok(()) + /// # } + /// ``` + pub fn builder() -> EvmEnvBuilder<(), H, ()> { + EvmEnvBuilder { + provider: (), + provider_config: ProviderConfig::default(), + block: BlockNumberOrTag::Latest, + beacon_config: (), + phantom: PhantomData, + } + } +} + +/// Builder for constructing an [EvmEnv] instance on the host. +/// +/// The [EvmEnvBuilder] is used to configure and create an [EvmEnv], which is the environment in +/// which the Ethereum Virtual Machine (EVM) operates. This builder provides flexibility in setting +/// up the EVM environment by allowing configuration of RPC endpoints, block numbers, and other +/// parameters. +/// +/// # Usage +/// The builder can be created using [EvmEnv::builder()]. Various configurations can be chained to +/// customize the environment before calling the `build` function to create the final [EvmEnv]. +/// +/// # Type Parameters +/// - `P`: The type of the RPC provider that interacts with the blockchain. +/// - `H`: The type of the block header. +/// - `B`: The type of the configuration to access the Beacon API. +#[derive(Clone, Debug)] +pub struct EvmEnvBuilder { + provider: P, + provider_config: ProviderConfig, + block: BlockNumberOrTag, + beacon_config: B, + phantom: PhantomData, +} + +impl EvmEnvBuilder<(), EthBlockHeader, ()> { + /// Sets the Ethereum HTTP RPC endpoint that will be used by the [EvmEnv]. + pub fn rpc(self, url: Url) -> EvmEnvBuilder, EthBlockHeader, ()> { + self.provider(ProviderBuilder::new().on_http(url)) + } +} + +impl EvmEnvBuilder<(), H, ()> { + /// Sets a custom [Provider] that will be used by the [EvmEnv]. + pub fn provider(self, provider: P) -> EvmEnvBuilder + where + T: Transport + Clone, + N: Network, + P: Provider, + H: EvmBlockHeader + TryFrom<::HeaderResponse>, + ::HeaderResponse>>::Error: Display, + { + EvmEnvBuilder { + provider, + provider_config: self.provider_config, + block: self.block, + beacon_config: self.beacon_config, + phantom: self.phantom, + } + } +} + +impl

EvmEnvBuilder { + /// Sets the Beacon API URL for retrieving Ethereum Beacon block root commitments. + /// + /// This function configures the [EvmEnv] to interact with an Ethereum Beacon chain. + /// It assumes the use of the [mainnet](https://github.com/ethereum/consensus-specs/blob/v1.4.0/configs/mainnet.yaml) preset for consensus specs. + pub fn beacon_api(self, url: Url) -> EvmEnvBuilder { + EvmEnvBuilder { + provider: self.provider, + provider_config: self.provider_config, + block: self.block, + beacon_config: url, + phantom: self.phantom, + } + } +} + +impl EvmEnvBuilder { + /// Sets the block number to be used for the EVM execution. + pub fn block_number(self, number: u64) -> Self { + self.block_number_or_tag(BlockNumberOrTag::Number(number)) + } + + /// Sets the block number or block tag ("latest", "earliest", "pending") to be used for the EVM + /// execution. + pub fn block_number_or_tag(mut self, block: BlockNumberOrTag) -> Self { + self.block = block; + self + } + + /// Sets the chunk size for `eth_getProof` calls (EIP-1186). + /// + /// This configures the number of storage keys to request in a single call. + /// The default is 1000, but this can be adjusted based on the RPC node configuration. + pub fn eip1186_proof_chunk_size(mut self, chunk_size: usize) -> Self { + assert_ne!(chunk_size, 0, "chunk size must be non-zero"); + self.provider_config.eip1186_proof_chunk_size = chunk_size; + self + } + + /// Retrieves the block header based on the current builder configuration. + async fn get_header(&self) -> Result + where + T: Transport + Clone, + N: Network, + P: Provider, + H: EvmBlockHeader + TryFrom<::HeaderResponse>, + ::HeaderResponse>>::Error: Display, + { + let number = self.block.into_rpc_type(&self.provider).await?; + let rpc_block = self + .provider + .get_block_by_number(number, false) + .await + .context("eth_getBlockByNumber failed")? + .with_context(|| format!("block {} not found", number))?; + let header = rpc_block.header().clone(); + header + .try_into() + .map_err(|err| anyhow!("header invalid: {}", err)) + } +} + +impl EvmEnvBuilder { + /// Builds and returns an [EvmEnv] with the configured settings that commits to a block hash. + pub async fn build(self) -> Result, H, ()>> + where + T: Transport + Clone, + N: Network, + P: Provider, + H: EvmBlockHeader + TryFrom<::HeaderResponse>, + ::HeaderResponse>>::Error: Display, + { + let header = self.get_header().await?.seal_slow(); + log::info!( + "Environment initialized with block {} ({})", + header.number(), + header.seal() + ); + + let db = ProofDb::new(AlloyDb::new( + self.provider, + self.provider_config, + header.seal(), + )); + + Ok(EvmEnv::new(db, header, ())) + } +} + +impl

EvmEnvBuilder { + /// Builds and returns an [EvmEnv] with the configured settings that commits to a beacon root. + pub async fn build(self) -> Result, BeaconCommit>> + where + T: Transport + Clone, + P: Provider, + { + let header = self.get_header().await?.seal_slow(); + log::info!( + "Environment initialized with block {} ({})", + header.number(), + header.seal() + ); + + let commitment = + BeaconCommit::from_header(&header, &self.provider, self.beacon_config).await?; + let db = ProofDb::new(AlloyDb::new( + self.provider, + self.provider_config, + header.seal(), + )); + + Ok(EvmEnv::new(db, header, commitment)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{ethereum::EthEvmEnv, BlockHeaderCommit, Commitment, CommitmentVersion}; + use test_log::test; + + const EL_URL: &str = "https://ethereum-rpc.publicnode.com"; + const CL_URL: &str = "https://ethereum-beacon-api.publicnode.com"; + + #[test(tokio::test)] + #[ignore] // This queries actual RPC nodes, running only on demand. + async fn build_block_env() { + EthEvmEnv::builder() + .rpc(EL_URL.parse().unwrap()) + .build() + .await + .unwrap(); + } + + #[test(tokio::test)] + #[ignore] // This queries actual RPC nodes, running only on demand. + async fn build_beacon_env() { + let provider = ProviderBuilder::new().on_builtin(EL_URL).await.unwrap(); + let env = EthEvmEnv::builder() + .provider(&provider) + .beacon_api(CL_URL.parse().unwrap()) + .block_number_or_tag(BlockNumberOrTag::Parent) + .build() + .await + .unwrap(); + let commit = env.commit.commit(&env.header); + + // the commitment should verify against the parent_beacon_block_root of the child + let child_block = provider + .get_block_by_number((env.header.number() + 1).into(), false) + .await + .unwrap(); + let header_block = child_block.unwrap().header; + assert_eq!( + commit, + Commitment::new( + CommitmentVersion::Beacon as u16, + header_block.timestamp, + header_block.parent_beacon_block_root.unwrap() + ) + ); + } +} diff --git a/steel/src/host/mod.rs b/steel/src/host/mod.rs index 1613f099..ce484c85 100644 --- a/steel/src/host/mod.rs +++ b/steel/src/host/mod.rs @@ -13,28 +13,29 @@ // limitations under the License. //! Functionality that is only needed for the host and not the guest. -use std::{fmt::Display, marker::PhantomData}; +use std::fmt::Display; use crate::{ - beacon::BeaconInput, + beacon::BeaconCommit, block::BlockInput, ethereum::{EthBlockHeader, EthEvmEnv}, host::db::ProviderDb, - EvmBlockHeader, EvmEnv, EvmInput, + ComposeInput, EvmBlockHeader, EvmEnv, EvmInput, }; use alloy::{ - network::{BlockResponse, Ethereum, Network}, - providers::{Provider, ProviderBuilder, ReqwestProvider, RootProvider}, + network::{Ethereum, Network}, + providers::{Provider, RootProvider}, rpc::types::BlockNumberOrTag as AlloyBlockNumberOrTag, transports::{ http::{Client, Http}, Transport, }, }; -use anyhow::{anyhow, ensure, Context, Result}; -use db::{AlloyDb, ProofDb, ProviderConfig}; +use anyhow::{ensure, Result}; +use db::{AlloyDb, ProofDb}; use url::Url; +mod builder; pub mod db; /// A block number (or tag - "latest", "safe", "finalized"). @@ -81,9 +82,10 @@ impl BlockNumberOrTag { } /// Alias for readability, do not make public. -pub(crate) type HostEvmEnv = EvmEnv, H>; +pub(crate) type HostEvmEnv = EvmEnv, H, C>; +type EthHostEvmEnv = EthEvmEnv, C>; -impl EthEvmEnv, Ethereum, RootProvider>>>> { +impl EthHostEvmEnv, Ethereum, RootProvider>>, ()> { /// Creates a new provable [EvmEnv] for Ethereum from an HTTP RPC endpoint. #[deprecated(since = "0.12.0", note = "use `EthEvmEnv::builder().rpc()` instead")] pub async fn from_rpc(url: Url, number: BlockNumberOrTag) -> Result { @@ -95,7 +97,7 @@ impl EthEvmEnv, Ethereum, RootProvider } } -impl HostEvmEnv, H> +impl HostEvmEnv, H, ()> where T: Transport + Clone, N: Network, @@ -115,165 +117,40 @@ where /// Converts the environment into a [EvmInput] committing to a block hash. pub async fn into_input(self) -> Result> { - Ok(EvmInput::Block(BlockInput::from_env(self).await?)) - } + let input = BlockInput::from_proof_db(self.db.unwrap(), self.header).await?; - /// Returns the provider of the underlying [AlloyDb]. - pub(crate) fn provider(&self) -> &P { - self.db().inner().provider() + Ok(EvmInput::Block(input)) } } -impl HostEvmEnv, EthBlockHeader> +impl EthHostEvmEnv, BeaconCommit> where T: Transport + Clone, P: Provider, { - /// Converts the environment into a [EvmInput] committing to an Ethereum Beacon block root. - /// - /// This function assumes that the - /// [mainnet](https://github.com/ethereum/consensus-specs/blob/v1.4.0/configs/mainnet.yaml) - /// preset of the consensus specs is used. - /// - /// ```rust,no_run - /// # use alloy_primitives::{address, Address}; - /// # use risc0_steel::{Contract, ethereum::EthEvmEnv}; - /// # use url::Url; - /// # #[tokio::main(flavor = "current_thread")] - /// # async fn main() -> anyhow::Result<()> { - /// // Create an environment. - /// let rpc_url = Url::parse("https://ethereum-rpc.publicnode.com")?; - /// let mut env = EthEvmEnv::builder().rpc(rpc_url).build().await?; - /// - /// // Preflight some contract calls... - /// # let address = address!("dAC17F958D2ee523a2206206994597C13D831ec7"); - /// # alloy::sol!( function balanceOf(address account) external view returns (uint); ); - /// # let call = balanceOfCall{ account: Address::ZERO }; - /// Contract::preflight(address, &mut env).call_builder(&call).call().await?; - /// - /// // Use EIP-4788 beacon commitments. - /// let beacon_api_url = Url::parse("https://ethereum-beacon-api.publicnode.com")?; - /// let input = env.into_beacon_input(beacon_api_url).await?; - /// # Ok(()) - /// # } - pub async fn into_beacon_input(self, url: Url) -> Result> { - Ok(EvmInput::Beacon( - BeaconInput::from_env_and_endpoint(self, url).await?, - )) - } -} - -impl EvmEnv<(), H> { - /// Creates a builder for building an environment. - /// - /// Create an Ethereum environment bast on the latest block: - /// ```rust,no_run - /// # use risc0_steel::ethereum::EthEvmEnv; - /// # use url::Url; - /// # #[tokio::main(flavor = "current_thread")] - /// # async fn main() -> anyhow::Result<()> { - /// # let url = Url::parse("https://ethereum-rpc.publicnode.com")?; - /// let env = EthEvmEnv::builder().rpc(url).build().await?; - /// # Ok(()) - /// # } - /// ``` - pub fn builder() -> EvmEnvBuilder<(), H> { - EvmEnvBuilder { - provider: (), - provider_config: ProviderConfig::default(), - block: BlockNumberOrTag::Latest, - phantom: PhantomData, - } - } -} - -/// Builder for building an [EvmEnv] on the host. -/// -/// The builder can be created using [EvmEnv::builder()]. -#[derive(Clone, Debug)] -pub struct EvmEnvBuilder { - provider: P, - provider_config: ProviderConfig, - block: BlockNumberOrTag, - phantom: PhantomData, -} - -impl EvmEnvBuilder<(), EthBlockHeader> { - /// Sets the Ethereum HTTP RPC endpoint that will be used by the [EvmEnv]. - pub fn rpc(self, url: Url) -> EvmEnvBuilder, EthBlockHeader> { - self.provider(ProviderBuilder::new().on_http(url)) - } -} + /// Converts the environment into a [EvmInput] committing to a block hash. + pub async fn into_input(self) -> Result> { + let input = BlockInput::from_proof_db(self.db.unwrap(), self.header).await?; -impl EvmEnvBuilder<(), H> { - /// Sets the [Provider] that will be used by the [EvmEnv]. - pub fn provider(self, provider: P) -> EvmEnvBuilder - where - T: Transport + Clone, - N: Network, - P: Provider, - H: EvmBlockHeader + TryFrom<::HeaderResponse>, - ::HeaderResponse>>::Error: Display, - { - EvmEnvBuilder { - provider, - provider_config: self.provider_config, - block: self.block, - phantom: self.phantom, - } + Ok(EvmInput::Beacon(ComposeInput::new(input, self.commit))) } } -impl EvmEnvBuilder { - /// Sets the block number. - pub fn block_number(self, number: u64) -> Self { - self.block_number_or_tag(BlockNumberOrTag::Number(number)) - } - - /// Sets the block number (or tag - "latest", "earliest", "pending"). - pub fn block_number_or_tag(mut self, block: BlockNumberOrTag) -> Self { - self.block = block; - self - } - - /// Sets the max number of storage keys to request in a single `eth_getProof` call. - /// - /// The optimal number depends on the RPC node and its configuration, but the default is 1000. - pub fn eip1186_proof_chunk_size(mut self, chunk_size: usize) -> Self { - assert_ne!(chunk_size, 0, "chunk size must be non-zero"); - self.provider_config.eip1186_proof_chunk_size = chunk_size; - self - } - - /// Builds the new provable [EvmEnv]. - pub async fn build(self) -> Result>, H>> - where - T: Transport + Clone, - N: Network, - P: Provider, - H: EvmBlockHeader + TryFrom<::HeaderResponse>, - ::HeaderResponse>>::Error: Display, - { - let provider = self.provider; - let number = self.block.into_rpc_type(&provider).await?; - let rpc_block = provider - .get_block_by_number(number, false) - .await - .context("eth_getBlockByNumber failed")? - .with_context(|| format!("block {} not found", number))?; - let header = rpc_block.header().clone(); - let header: H = header - .try_into() - .map_err(|err| anyhow!("header invalid: {}", err))?; - let sealed_header = header.seal_slow(); - log::info!("Environment initialized for block {}", sealed_header.seal()); - - let db = ProofDb::new(AlloyDb::new( - provider, - self.provider_config, - sealed_header.seal(), - )); +impl EthHostEvmEnv, ()> +where + T: Transport + Clone, + P: Provider, +{ + /// Converts the environment into a [EvmInput] committing to an Ethereum Beacon block root. + #[deprecated( + since = "0.14.0", + note = "use `EvmEnv::builder().beacon_api()` instead" + )] + pub async fn into_beacon_input(self, url: Url) -> Result> { + let commit = + BeaconCommit::from_header(self.header(), self.db().inner().provider(), url).await?; + let input = BlockInput::from_proof_db(self.db.unwrap(), self.header).await?; - Ok(EvmEnv::new(db, sealed_header)) + Ok(EvmInput::Beacon(ComposeInput::new(input, commit))) } } diff --git a/steel/src/lib.rs b/steel/src/lib.rs index 8ed072cd..6ee562c5 100644 --- a/steel/src/lib.rs +++ b/steel/src/lib.rs @@ -90,36 +90,35 @@ impl> ComposeInput { /// Converts the input into a [EvmEnv] for verifiable state access in the guest. pub fn into_env(self) -> GuestEvmEnv { let mut env = self.input.into_env(); - env.commitment = self.commit.commit(&env.header); + env.commit = self.commit.commit(&env.header); env } } /// Alias for readability, do not make public. -pub(crate) type GuestEvmEnv = EvmEnv; +pub(crate) type GuestEvmEnv = EvmEnv; /// The environment to execute the contract calls in. -pub struct EvmEnv { +pub struct EvmEnv { db: Option, cfg_env: CfgEnvWithHandlerCfg, header: Sealed, - commitment: Commitment, + commit: C, } -impl EvmEnv { +impl EvmEnv { /// Creates a new environment. /// /// It uses the default configuration for the latest specification. - pub(crate) fn new(db: D, header: Sealed) -> Self { + pub(crate) fn new(db: D, header: Sealed, commit: C) -> Self { let cfg_env = CfgEnvWithHandlerCfg::new_with_spec_id(Default::default(), SpecId::LATEST); - let commitment = Commitment::from_block_header(&header); Self { db: Some(db), cfg_env, header, - commitment, + commit, } } @@ -140,18 +139,6 @@ impl EvmEnv { &self.header } - /// Returns the [Commitment] used to validate the environment. - #[inline] - pub fn commitment(&self) -> &Commitment { - &self.commitment - } - - /// Consumes and returns the [Commitment] used to validate the environment. - #[inline] - pub fn into_commitment(self) -> Commitment { - self.commitment - } - fn db(&self) -> &D { // safe unwrap: self cannot be borrowed without a DB self.db.as_ref().unwrap() @@ -164,6 +151,20 @@ impl EvmEnv { } } +impl EvmEnv { + /// Returns the [Commitment] used to validate the environment. + #[inline] + pub fn commitment(&self) -> &Commitment { + &self.commit + } + + /// Consumes and returns the [Commitment] used to validate the environment. + #[inline] + pub fn into_commitment(self) -> Commitment { + self.commit + } +} + /// An EVM abstraction of a block header. pub trait EvmBlockHeader: Sealable { /// Returns the hash of the parent block's header. diff --git a/steel/tests/corruption.rs b/steel/tests/corruption.rs index 7124926a..e162c761 100644 --- a/steel/tests/corruption.rs +++ b/steel/tests/corruption.rs @@ -127,6 +127,7 @@ fn mock_anvil_guest(input: EthEvmInput) -> Commitment { async fn rpc_usdt_input() -> anyhow::Result { let mut env = EthEvmEnv::builder() .rpc(RPC_URL.parse()?) + .beacon_api(BEACON_API_URL.parse()?) .block_number_or_tag(BlockNumberOrTag::Parent) .build() .await?; @@ -136,7 +137,7 @@ async fn rpc_usdt_input() -> anyhow::Result { .call() .await?; - env.into_beacon_input(BEACON_API_URL.parse()?).await + env.into_input().await } /// Loads the data from an existing JSON file, or creates it.