From 747781b2d51925cb9d906e16f2d74d7dcc3e714e Mon Sep 17 00:00:00 2001 From: morph <82043364+morph-dev@users.noreply.github.com> Date: Wed, 31 Jul 2024 17:49:48 +0300 Subject: [PATCH] feat: use objects from portal-verkle-primitives and delete duplicates --- Cargo.lock | 1 + portal-verkle/Cargo.toml | 1 + portal-verkle/src/beacon_block_fetcher.rs | 2 +- .../src/bin/fetch_state_from_portal.rs | 2 +- portal-verkle/src/bin/gossip_to_portal.rs | 134 +++++++------ portal-verkle/src/evm/error.rs | 3 +- portal-verkle/src/evm/verkle_evm.rs | 58 +++--- portal-verkle/src/lib.rs | 2 - portal-verkle/src/paths.rs | 16 -- portal-verkle/src/state_trie_fetcher.rs | 45 ++--- portal-verkle/src/types/genesis.rs | 99 ---------- portal-verkle/src/types/mod.rs | 4 +- portal-verkle/src/types/state_write.rs | 71 ------- portal-verkle/src/types/witness.rs | 26 ++- portal-verkle/src/utils.rs | 52 +++-- portal-verkle/src/verkle_trie/error.rs | 18 -- portal-verkle/src/verkle_trie/mod.rs | 6 - portal-verkle/src/verkle_trie/nodes/branch.rs | 186 ------------------ .../src/verkle_trie/nodes/commitment.rs | 50 ----- portal-verkle/src/verkle_trie/nodes/leaf.rs | 186 ------------------ portal-verkle/src/verkle_trie/nodes/mod.rs | 35 ---- portal-verkle/src/verkle_trie/trie.rs | 94 --------- portal-verkle/src/verkle_trie/trie_printer.rs | 144 -------------- 23 files changed, 170 insertions(+), 1065 deletions(-) delete mode 100644 portal-verkle/src/paths.rs delete mode 100644 portal-verkle/src/types/genesis.rs delete mode 100644 portal-verkle/src/types/state_write.rs delete mode 100644 portal-verkle/src/verkle_trie/error.rs delete mode 100644 portal-verkle/src/verkle_trie/mod.rs delete mode 100644 portal-verkle/src/verkle_trie/nodes/branch.rs delete mode 100644 portal-verkle/src/verkle_trie/nodes/commitment.rs delete mode 100644 portal-verkle/src/verkle_trie/nodes/leaf.rs delete mode 100644 portal-verkle/src/verkle_trie/nodes/mod.rs delete mode 100644 portal-verkle/src/verkle_trie/trie.rs delete mode 100644 portal-verkle/src/verkle_trie/trie_printer.rs diff --git a/Cargo.lock b/Cargo.lock index 3abc7f5..05f398d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2964,6 +2964,7 @@ dependencies = [ "clap", "derive_more", "ethportal-api", + "itertools 0.13.0", "jsonrpsee", "portal-verkle-primitives", "reqwest", diff --git a/portal-verkle/Cargo.toml b/portal-verkle/Cargo.toml index c1b2e59..c5ea55b 100644 --- a/portal-verkle/Cargo.toml +++ b/portal-verkle/Cargo.toml @@ -12,6 +12,7 @@ anyhow = "1" clap = { version = "4", features = ["derive"] } derive_more = "0.99" ethportal-api = { git = "https://github.com/morph-dev/trin.git", rev = "d1b4f4cbf8ac1d93753a7fa39e08ecd70139bb3f" } +itertools = "0.13" jsonrpsee = { version = "0.20", features = ["async-client", "client"] } portal-verkle-primitives = { git = "https://github.com/morph-dev/portal-verkle-primitives.git", rev = "65ce73011fd2636733271219057c9dc194800ded" } reqwest = { version = "0.12", features = ["json"] } diff --git a/portal-verkle/src/beacon_block_fetcher.rs b/portal-verkle/src/beacon_block_fetcher.rs index 6b76484..8c1893c 100644 --- a/portal-verkle/src/beacon_block_fetcher.rs +++ b/portal-verkle/src/beacon_block_fetcher.rs @@ -8,8 +8,8 @@ use reqwest::{Client, Url}; use serde::Deserialize; use crate::{ - paths::beacon_slot_path, types::{beacon::SignedBeaconBlock, JsonResponseMessage}, + utils::beacon_slot_path, }; const BEACON_BLOCK_URL_PATH: &str = "eth/v2/beacon/blocks/"; diff --git a/portal-verkle/src/bin/fetch_state_from_portal.rs b/portal-verkle/src/bin/fetch_state_from_portal.rs index 752d1b7..1040ca8 100644 --- a/portal-verkle/src/bin/fetch_state_from_portal.rs +++ b/portal-verkle/src/bin/fetch_state_from_portal.rs @@ -2,8 +2,8 @@ use anyhow::bail; use clap::Parser; use portal_verkle::{ beacon_block_fetcher::BeaconBlockFetcher, state_trie_fetcher::StateTrieFetcher, - types::genesis::GenesisConfig, }; +use portal_verkle_primitives::verkle::genesis_config::GenesisConfig; const LOCALHOST_BEACON_RPC_URL: &str = "http://localhost:9596/"; const LOCALHOST_PORTAL_RPC_URL: &str = "http://localhost:8545/"; diff --git a/portal-verkle/src/bin/gossip_to_portal.rs b/portal-verkle/src/bin/gossip_to_portal.rs index 8c4cf88..dc921a2 100644 --- a/portal-verkle/src/bin/gossip_to_portal.rs +++ b/portal-verkle/src/bin/gossip_to_portal.rs @@ -5,18 +5,15 @@ use std::{ use alloy_primitives::B256; use clap::Parser; -use ethportal_api::{ - types::content_key::verkle::LeafFragmentKey, VerkleContentKey, VerkleContentValue, - VerkleNetworkApiClient, -}; +use ethportal_api::{VerkleContentKey, VerkleContentValue, VerkleNetworkApiClient}; use jsonrpsee::http_client::{HttpClient, HttpClientBuilder}; use portal_verkle::{ - beacon_block_fetcher::BeaconBlockFetcher, - evm::VerkleEvm, - types::{genesis::GenesisConfig, state_write::StateWrites}, - utils::read_genesis, + beacon_block_fetcher::BeaconBlockFetcher, evm::VerkleEvm, utils::read_genesis, +}; +use portal_verkle_primitives::{ + ssz::TriePath, + verkle::{genesis_config::GenesisConfig, StateWrites}, }; -use portal_verkle_primitives::{constants::PORTAL_NETWORK_NODE_WIDTH, ssz::TriePath}; const LOCALHOST_BEACON_RPC_URL: &str = "http://localhost:9596/"; const LOCALHOST_PORTAL_RPC_URL: &str = "http://localhost:8545/"; @@ -45,7 +42,7 @@ impl Gossiper { let portal_client = HttpClientBuilder::new() .request_timeout(Duration::from_secs(60)) .build(&args.portal_rpc_url)?; - let evm = VerkleEvm::new(&read_genesis()?)?; + let evm = VerkleEvm::new(read_genesis()?)?; Ok(Self { block_fetcher, @@ -55,8 +52,7 @@ impl Gossiper { } async fn gossip_genesis(&mut self) -> anyhow::Result<()> { - let genesis_config = read_genesis()?; - let state_writes = genesis_config.generate_state_diff().into(); + let state_writes = read_genesis()?.into_state_writes(); println!("Gossiping genesis..."); self.gossip_state_writes( GenesisConfig::DEVNET6_BLOCK_HASH, @@ -99,11 +95,11 @@ impl Gossiper { for stem_state_write in state_writes.iter() { let stem = &stem_state_write.stem; let path_to_leaf = self.evm.state_trie().traverse_to_leaf(stem)?; - for (depth, branch) in path_to_leaf.branches.iter().enumerate() { + for (depth, (branch, _)) in path_to_leaf.trie_path.iter().enumerate() { let trie_path = TriePath::from(stem[..depth].to_vec()); // Branch bundle - let content_key = VerkleContentKey::Bundle(branch.commitment().clone()); + let content_key = VerkleContentKey::Bundle(branch.commitment().to_point()); if new_branch_nodes.contains(&trie_path) && content_to_gossip.contains_key(&content_key) { @@ -123,39 +119,40 @@ impl Gossiper { todo!() }); - let fragment_indices = if new_branch_nodes.contains(&trie_path) { - 0..PORTAL_NETWORK_NODE_WIDTH - } else { - let fragment_index = stem[depth] as usize / PORTAL_NETWORK_NODE_WIDTH; - fragment_index..fragment_index + 1 - }; + // let fragment_indices = if new_branch_nodes.contains(&trie_path) { + // 0..PORTAL_NETWORK_NODE_WIDTH + // } else { + // let fragment_index = stem[depth] as usize / PORTAL_NETWORK_NODE_WIDTH; + // fragment_index..fragment_index + 1 + // }; // Branch fragment - for fragment_index in fragment_indices { - let (fragment_commitment, _fragment) = - branch.extract_fragment_node(fragment_index); - if fragment_commitment.is_zero() { - continue; - } - let content_key = VerkleContentKey::BranchFragment(fragment_commitment); - content_to_gossip.entry(content_key).or_insert_with(|| { - // VerkleContentValue::NodeWithProof( - // PortalVerkleNodeWithProof::BranchFragment( - // BranchFragmentNodeWithProof { - // node: fragment, - // block_hash, - // path: trie_path.clone(), - // proof: trie_proof, - // }, - // ), - // ) - todo!() - }); - } + // for fragment_index in fragment_indices { + // let (fragment_commitment, _fragment) = + // branch.extract_fragment_node(fragment_index); + // if fragment_commitment.is_zero() { + // continue; + // } + // let content_key = VerkleContentKey::BranchFragment(fragment_commitment); + // content_to_gossip.entry(content_key).or_insert_with(|| { + // // VerkleContentValue::NodeWithProof( + // // PortalVerkleNodeWithProof::BranchFragment( + // // BranchFragmentNodeWithProof { + // // node: fragment, + // // block_hash, + // // path: trie_path.clone(), + // // proof: trie_proof, + // // }, + // // ), + // // ) + // todo!() + // }); + // } + todo!() } // Leaf bundle let bundle_commitment = path_to_leaf.leaf.commitment(); - let content_key = VerkleContentKey::Bundle(bundle_commitment.clone()); + let content_key = VerkleContentKey::Bundle(bundle_commitment.to_point()); content_to_gossip.entry(content_key).or_insert_with(|| { // VerkleContentValue::NodeWithProof(PortalVerkleNodeWithProof::LeafBundle( // LeafBundleNodeWithProof { @@ -168,32 +165,33 @@ impl Gossiper { }); // Leaf Fragments - let mut modified_fragments = stem_state_write - .suffix_writes - .iter() - .map(|suffix_write| suffix_write.suffix as usize / PORTAL_NETWORK_NODE_WIDTH) - .collect::>(); - modified_fragments.sort(); - modified_fragments.dedup(); - for fragment_index in modified_fragments { - let (fragment_commitment, _fragment_node) = - path_to_leaf.leaf.extract_fragment_node(fragment_index); - let content_key = VerkleContentKey::LeafFragment(LeafFragmentKey { - stem: *stem, - commitment: fragment_commitment, - }); - - content_to_gossip.entry(content_key).or_insert_with(|| { - // VerkleContentValue::NodeWithProof(PortalVerkleNodeWithProof::LeafFragment( - // LeafFragmentNodeWithProof { - // node: fragment_node, - // block_hash, - // proof: trie_proof, - // }, - // )) - todo!() - }); - } + // let mut modified_fragments = stem_state_write + // .writes + // .iter() + // .map(|(suffix, _value)| *suffix as usize / PORTAL_NETWORK_NODE_WIDTH) + // .collect::>(); + // modified_fragments.sort(); + // modified_fragments.dedup(); + // for fragment_index in modified_fragments { + // let (fragment_commitment, _fragment_node) = + // path_to_leaf.leaf.extract_fragment_node(fragment_index); + // let content_key = VerkleContentKey::LeafFragment(LeafFragmentKey { + // stem: *stem, + // commitment: fragment_commitment, + // }); + + // content_to_gossip.entry(content_key).or_insert_with(|| { + // // VerkleContentValue::NodeWithProof(PortalVerkleNodeWithProof::LeafFragment( + // // LeafFragmentNodeWithProof { + // // node: fragment_node, + // // block_hash, + // // proof: trie_proof, + // // }, + // // )) + // todo!() + // }); + // } + todo!() } for (key, value) in content_to_gossip { diff --git a/portal-verkle/src/evm/error.rs b/portal-verkle/src/evm/error.rs index 79092b1..47641af 100644 --- a/portal-verkle/src/evm/error.rs +++ b/portal-verkle/src/evm/error.rs @@ -1,8 +1,7 @@ use alloy_primitives::B256; +use portal_verkle_primitives::verkle::error::VerkleTrieError; use thiserror::Error; -use crate::verkle_trie::error::VerkleTrieError; - #[derive(Debug, Error)] pub enum EvmError { #[error("Expected block {expected}, but received {actual}")] diff --git a/portal-verkle/src/evm/verkle_evm.rs b/portal-verkle/src/evm/verkle_evm.rs index e175cc7..11520e0 100644 --- a/portal-verkle/src/evm/verkle_evm.rs +++ b/portal-verkle/src/evm/verkle_evm.rs @@ -4,19 +4,16 @@ use alloy_primitives::{address, keccak256, U8}; use portal_verkle_primitives::{ constants::{BALANCE_LEAF_KEY, CODE_KECCAK_LEAF_KEY, NONCE_LEAF_KEY, VERSION_LEAF_KEY}, ssz::TriePath, - verkle::storage::AccountStorageLayout, + verkle::{ + genesis_config::GenesisConfig, storage::AccountStorageLayout, StateWrites, VerkleTrie, + }, TrieValue, }; use super::error::EvmError; -use crate::{ - types::{ - beacon::ExecutionPayload, - genesis::GenesisConfig, - state_write::StateWrites, - witness::{StateDiff, SuffixStateDiff}, - }, - verkle_trie::VerkleTrie, +use crate::types::{ + beacon::ExecutionPayload, + witness::{StateDiff, StemStateDiff, SuffixStateDiff}, }; pub struct VerkleEvm { @@ -30,11 +27,9 @@ pub struct ProcessBlockResult { } impl VerkleEvm { - pub fn new(genesis_config: &GenesisConfig) -> Result { + pub fn new(genesis_config: GenesisConfig) -> Result { let mut state_trie = VerkleTrie::new(); - state_trie - .update(&genesis_config.generate_state_diff().into()) - .map_err(EvmError::TrieError)?; + state_trie.update(&genesis_config.into_state_writes()); Ok(Self { block: 0, state_trie, @@ -66,12 +61,14 @@ impl VerkleEvm { update_state_diff_for_eip2935(&mut state_diff); } - let state_writes = StateWrites::from(state_diff); + let state_writes = StateWrites::new( + state_diff + .into_iter() + .filter_map(StemStateDiff::into_stem_state_write) + .collect(), + ); - let new_branch_nodes = self - .state_trie - .update(&state_writes) - .map_err(EvmError::TrieError)?; + let new_branch_nodes = self.state_trie.update(&state_writes); self.block += 1; if self.state_trie.root() != execution_payload.state_root { @@ -115,15 +112,18 @@ fn update_state_diff_for_eip2935(state_diff: &mut StateDiff) { #[cfg(test)] mod tests { - use std::{fs::File, io::BufReader}; + use std::{ + fs::File, + io::{stdout, BufReader}, + }; use alloy_primitives::{b256, B256}; - use anyhow::Result; + use anyhow::{bail, Result}; + use portal_verkle_primitives::verkle::trie_printer::TriePrinter; use crate::{ - paths::{beacon_slot_path, test_path}, types::SuccessMessage, - utils::read_genesis_for_test, + utils::{beacon_slot_path, read_genesis_for_test, test_path}, }; use super::*; @@ -133,7 +133,7 @@ mod tests { const STATE_ROOT: B256 = b256!("1fbf85345a3cbba9a6d44f991b721e55620a22397c2a93ee8d5011136ac300ee"); - let evm = VerkleEvm::new(&read_genesis_for_test()?)?; + let evm = VerkleEvm::new(read_genesis_for_test()?)?; assert_eq!(evm.state_trie.root(), STATE_ROOT); Ok(()) @@ -141,7 +141,7 @@ mod tests { #[test] fn process_block_1() -> Result<()> { - let mut evm = VerkleEvm::new(&read_genesis_for_test()?)?; + let mut evm = VerkleEvm::new(read_genesis_for_test()?)?; let reader = BufReader::new(File::open(test_path(beacon_slot_path(1)))?); let response: SuccessMessage = serde_json::from_reader(reader)?; @@ -153,7 +153,7 @@ mod tests { #[test] fn process_block_1000() -> Result<()> { - let mut evm = VerkleEvm::new(&read_genesis_for_test()?)?; + let mut evm = VerkleEvm::new(read_genesis_for_test()?)?; for block in 1..=1000 { let path = test_path(beacon_slot_path(block)); @@ -163,7 +163,13 @@ mod tests { let reader = BufReader::new(File::open(path)?); let response: SuccessMessage = serde_json::from_reader(reader)?; let execution_payload = response.data.message.body.execution_payload; - evm.process_block(&execution_payload)?; + if let Err(err) = evm.process_block(&execution_payload) { + println!("Failed at block {block}"); + evm.state_trie.print_state(&mut stdout())?; + evm.state_trie + .print_trie_with_identation(&mut stdout(), 0)?; + bail!(err); + } } Ok(()) } diff --git a/portal-verkle/src/lib.rs b/portal-verkle/src/lib.rs index a940477..fb56095 100644 --- a/portal-verkle/src/lib.rs +++ b/portal-verkle/src/lib.rs @@ -1,7 +1,5 @@ pub mod beacon_block_fetcher; pub mod evm; -pub mod paths; pub mod state_trie_fetcher; pub mod types; pub mod utils; -pub mod verkle_trie; diff --git a/portal-verkle/src/paths.rs b/portal-verkle/src/paths.rs deleted file mode 100644 index 772eb49..0000000 --- a/portal-verkle/src/paths.rs +++ /dev/null @@ -1,16 +0,0 @@ -use std::path::PathBuf; - -pub const TESTNET_DATA_PATH: &str = "data/verkle-devnet-6/"; - -pub fn beacon_slot_path(slot: u64) -> PathBuf { - PathBuf::from(TESTNET_DATA_PATH).join(format!("beacon/slot.{slot}.json")) -} - -pub fn genesis_path() -> PathBuf { - PathBuf::from(TESTNET_DATA_PATH).join("genesis.json") -} - -#[cfg(test)] -pub fn test_path>(path: P) -> PathBuf { - PathBuf::from("..").join(path) -} diff --git a/portal-verkle/src/state_trie_fetcher.rs b/portal-verkle/src/state_trie_fetcher.rs index a0bd471..3ba04c5 100644 --- a/portal-verkle/src/state_trie_fetcher.rs +++ b/portal-verkle/src/state_trie_fetcher.rs @@ -8,12 +8,10 @@ use ethportal_api::{ }; use jsonrpsee::http_client::{HttpClient, HttpClientBuilder}; use portal_verkle_primitives::{ - constants::PORTAL_NETWORK_NODE_WIDTH, portal::PortalVerkleNode, Point, -}; - -use crate::{ - types::state_write::{StateWrites, StemStateWrite, SuffixStateWrite}, - verkle_trie::VerkleTrie, + constants::PORTAL_NETWORK_NODE_WIDTH, + portal::PortalVerkleNode, + verkle::{StateWrites, StemStateWrite, VerkleTrie}, + Point, }; pub struct StateTrieFetcher { @@ -36,29 +34,29 @@ impl StateTrieFetcher { let value = self.fetch_content(&key).await?; match &value { VerkleContentValue::Node(PortalVerkleNode::BranchBundle(node)) => { - let VerkleContentKey::Bundle(_key_commitment) = &key else { + let VerkleContentKey::Bundle(key_commitment) = &key else { bail!( "Invalid BranchBundle value received! key: {}, value: {}", key.to_hex(), value.to_hex() ) }; - // TODO check that commitment match - // TODO check that bundle proof is valid + node.verify(key_commitment)?; + for commitment in node.fragments().iter_set_items() { stack.push(VerkleContentKey::BranchFragment(commitment.clone())); } } VerkleContentValue::Node(PortalVerkleNode::LeafBundle(node)) => { - let VerkleContentKey::Bundle(_key_commitment) = &key else { + let VerkleContentKey::Bundle(key_commitment) = &key else { bail!( "Invalid LeafBundle value received! key: {}, value: {}", key.to_hex(), value.to_hex() ) }; - // TODO check that commitment match - // TODO check that bundle proof is valid + node.verify(key_commitment)?; + for commitment in node.fragments().iter_set_items() { stack.push(VerkleContentKey::LeafFragment(LeafFragmentKey { stem: *node.stem(), @@ -67,14 +65,15 @@ impl StateTrieFetcher { } } VerkleContentValue::Node(PortalVerkleNode::BranchFragment(node)) => { - let VerkleContentKey::BranchFragment(_key_commitment) = &key else { + let VerkleContentKey::BranchFragment(key_commitment) = &key else { bail!( "Invalid BranchFragment value received! key: {}, value: {}", key.to_hex(), value.to_hex() ) }; - // TODO check that commitment match + node.verify(key_commitment)?; + for commitment in node.children().iter_set_items() { stack.push(VerkleContentKey::Bundle(commitment.clone())); } @@ -87,24 +86,18 @@ impl StateTrieFetcher { value.to_hex() ) }; - // TODO check that commitment match + node.verify(&leaf_fragment_key.commitment)?; + let start_index = node.fragment_index() as usize * PORTAL_NETWORK_NODE_WIDTH; let stem_state_write = StemStateWrite { stem: leaf_fragment_key.stem, - suffix_writes: node + writes: node .children() - .into_iter() - .enumerate() - .filter_map(|(index, opt_value)| { - opt_value.map(|value| SuffixStateWrite { - suffix: (start_index + index) as u8, - old_value: None, - new_value: value, - }) - }) + .iter_enumerated_set_items() + .map(|(child_index, value)| ((start_index + child_index) as u8, *value)) .collect(), }; - trie.update(&StateWrites::new(vec![stem_state_write]))?; + trie.update(&StateWrites::new(vec![stem_state_write])); } _ => bail!("Invalid content value received: {}", value.to_hex()), } diff --git a/portal-verkle/src/types/genesis.rs b/portal-verkle/src/types/genesis.rs deleted file mode 100644 index f9d8255..0000000 --- a/portal-verkle/src/types/genesis.rs +++ /dev/null @@ -1,99 +0,0 @@ -use std::collections::{BTreeMap, HashMap}; - -use alloy_primitives::{b256, keccak256, Address, Bytes, B256, U256, U8}; -use portal_verkle_primitives::{verkle::storage::AccountStorageLayout, Stem, TrieKey, TrieValue}; -use serde::{Deserialize, Serialize}; - -use super::witness::{StateDiff, StemStateDiff, SuffixStateDiff}; - -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -#[serde(deny_unknown_fields)] -pub struct AccountAlloc { - pub balance: U256, - pub nonce: Option, - pub code: Option, - pub storage: Option>, -} - -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct GenesisConfig { - pub alloc: HashMap, -} - -impl GenesisConfig { - pub const DEVNET6_BLOCK_HASH: B256 = - b256!("3fe165c03e7a77d1e3759362ebeeb16fd964cb411ce11fbe35c7032fab5b9a8a"); - pub const DEVNET6_STATE_ROOT: B256 = - b256!("1fbf85345a3cbba9a6d44f991b721e55620a22397c2a93ee8d5011136ac300ee"); - - pub fn generate_state_diff(&self) -> StateDiff { - let mut state_diffs = BTreeMap::::new(); - let mut insert_state_diff = |key: TrieKey, value: TrieValue| { - let suffix_state_diff = SuffixStateDiff { - suffix: U8::from(key.suffix()), - current_value: None, - new_value: Some(value), - }; - - let stem = key.stem(); - match state_diffs.get_mut(&stem) { - Some(state_diff) => state_diff.suffix_diffs.push(suffix_state_diff), - None => { - state_diffs.insert( - stem, - StemStateDiff { - stem, - suffix_diffs: vec![suffix_state_diff], - }, - ); - } - } - }; - - for (address, account_alloc) in &self.alloc { - let storage_layout = AccountStorageLayout::new(*address); - insert_state_diff(storage_layout.version_key(), U256::ZERO.into()); - insert_state_diff(storage_layout.balance_key(), account_alloc.balance.into()); - insert_state_diff( - storage_layout.nonce_key(), - account_alloc.nonce.unwrap_or(U256::ZERO).into(), - ); - - match &account_alloc.code { - None => insert_state_diff(storage_layout.code_hash_key(), keccak256([]).into()), - Some(code) => { - insert_state_diff(storage_layout.code_hash_key(), keccak256(code).into()); - insert_state_diff( - storage_layout.code_size_key(), - U256::from(code.len()).into(), - ); - for (key, value) in storage_layout.chunkify_code(code) { - insert_state_diff(key, value); - } - } - } - - if let Some(storage) = &account_alloc.storage { - for (storage_key, value) in storage { - insert_state_diff(storage_layout.storage_slot_key(*storage_key), *value); - } - } - } - - state_diffs.into_values().collect() - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::utils::read_genesis_for_test; - - #[test] - fn parse_genesis() -> anyhow::Result<()> { - let genesis_config: GenesisConfig = read_genesis_for_test()?; - let alloc = genesis_config.alloc; - assert_eq!(alloc.len(), 278); - Ok(()) - } -} diff --git a/portal-verkle/src/types/mod.rs b/portal-verkle/src/types/mod.rs index 5e5a53a..fb58ffc 100644 --- a/portal-verkle/src/types/mod.rs +++ b/portal-verkle/src/types/mod.rs @@ -3,8 +3,6 @@ use serde::{Deserialize, Serialize}; use self::beacon::SignedBeaconBlock; pub mod beacon; -pub mod genesis; -pub mod state_write; pub mod witness; #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] @@ -34,7 +32,7 @@ mod tests { io::BufReader, }; - use crate::paths::{test_path, TESTNET_DATA_PATH}; + use crate::utils::{test_path, TESTNET_DATA_PATH}; use super::*; diff --git a/portal-verkle/src/types/state_write.rs b/portal-verkle/src/types/state_write.rs deleted file mode 100644 index 007aab1..0000000 --- a/portal-verkle/src/types/state_write.rs +++ /dev/null @@ -1,71 +0,0 @@ -use derive_more::{Constructor, Deref, Index, IndexMut}; -use portal_verkle_primitives::{Stem, TrieValue}; - -use super::witness::{StateDiff, StemStateDiff, SuffixStateDiff}; - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct SuffixStateWrite { - pub suffix: u8, - pub old_value: Option, - pub new_value: TrieValue, -} - -impl SuffixStateWrite { - pub fn from(suffix_state_diff: SuffixStateDiff) -> Option { - let SuffixStateDiff { - suffix, - current_value: old_value, - new_value, - } = suffix_state_diff; - - if old_value == new_value { - return None; - } - - new_value.map(|new_value| Self { - suffix: suffix.to(), - old_value, - new_value, - }) - } -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct StemStateWrite { - pub stem: Stem, - pub suffix_writes: Vec, -} - -impl StemStateWrite { - pub fn from(stem_state_diff: StemStateDiff) -> Option { - let StemStateDiff { stem, suffix_diffs } = stem_state_diff; - - let suffix_writes = suffix_diffs - .into_iter() - .filter_map(SuffixStateWrite::from) - .collect::>(); - - if suffix_writes.is_empty() { - None - } else { - Some(Self { - stem, - suffix_writes, - }) - } - } -} - -#[derive(Debug, Clone, Constructor, Deref, Index, IndexMut)] -pub struct StateWrites(Vec); - -impl From for StateWrites { - fn from(state_diff: StateDiff) -> Self { - Self( - state_diff - .into_iter() - .filter_map(StemStateWrite::from) - .collect(), - ) - } -} diff --git a/portal-verkle/src/types/witness.rs b/portal-verkle/src/types/witness.rs index a160166..cce0bff 100644 --- a/portal-verkle/src/types/witness.rs +++ b/portal-verkle/src/types/witness.rs @@ -1,5 +1,7 @@ +use std::collections::HashMap; + use alloy_primitives::{Bytes, U8}; -use portal_verkle_primitives::{proof::IpaProof, Point, Stem, TrieValue}; +use portal_verkle_primitives::{proof::IpaProof, verkle::StemStateWrite, Point, Stem, TrieValue}; use serde::{Deserialize, Serialize}; use serde_nested_with::serde_nested; @@ -46,3 +48,25 @@ pub struct ExecutionWitness { #[serde(alias = "verkleProof")] pub verkle_proof: VerkleProof, } + +impl StemStateDiff { + pub fn into_stem_state_write(self) -> Option { + let writes = self + .suffix_diffs + .into_iter() + .flat_map(|suffix_state_diff| { + suffix_state_diff + .new_value + .map(|value| (suffix_state_diff.suffix.byte(0), value)) + }) + .collect::>(); + if writes.is_empty() { + None + } else { + Some(StemStateWrite { + stem: self.stem, + writes, + }) + } + } +} diff --git a/portal-verkle/src/utils.rs b/portal-verkle/src/utils.rs index cab7506..abe396a 100644 --- a/portal-verkle/src/utils.rs +++ b/portal-verkle/src/utils.rs @@ -1,24 +1,26 @@ -use std::{fs::File, io::BufReader, path::Path}; - -use portal_verkle_primitives::{ - constants::PORTAL_NETWORK_NODE_WIDTH, - proof::{BundleProof, IpaProof, MultiProof}, - ssz::SparseVector, - Point, ScalarField, +use std::{ + fs::File, + io::BufReader, + path::{Path, PathBuf}, }; -use ssz_types::FixedVector; -use crate::{paths::genesis_path, types::genesis::GenesisConfig}; +use portal_verkle_primitives::verkle::genesis_config::GenesisConfig; -pub fn read_genesis() -> anyhow::Result { - read_genesis_from_file(genesis_path()) -} +pub const TESTNET_DATA_PATH: &str = "data/verkle-devnet-6/"; #[cfg(test)] -pub fn read_genesis_for_test() -> anyhow::Result { - use crate::paths::test_path; +pub fn test_path>(path: P) -> PathBuf { + PathBuf::from("..").join(path) +} - read_genesis_from_file(test_path(genesis_path())) +pub fn beacon_slot_path(slot: u64) -> PathBuf { + PathBuf::from(TESTNET_DATA_PATH).join(format!("beacon/slot.{slot}.json")) +} + +// Genesis + +fn genesis_path() -> PathBuf { + PathBuf::from(TESTNET_DATA_PATH).join("genesis.json") } fn read_genesis_from_file>(path: P) -> anyhow::Result { @@ -26,21 +28,11 @@ fn read_genesis_from_file>(path: P) -> anyhow::Result, -) -> BundleProof { - // TODO: add implementation - BundleProof::new(dummy_multiproof()) +pub fn read_genesis() -> anyhow::Result { + read_genesis_from_file(genesis_path()) } -pub fn dummy_multiproof() -> MultiProof { - // TODO: add implementation - MultiProof { - ipa_proof: IpaProof { - cl: FixedVector::from_elem(Point::zero()), - cr: FixedVector::from_elem(Point::zero()), - final_evaluation: ScalarField::zero(), - }, - g_commitment: Point::zero(), - } +#[cfg(test)] +pub fn read_genesis_for_test() -> anyhow::Result { + read_genesis_from_file(test_path(genesis_path())) } diff --git a/portal-verkle/src/verkle_trie/error.rs b/portal-verkle/src/verkle_trie/error.rs deleted file mode 100644 index 68958a7..0000000 --- a/portal-verkle/src/verkle_trie/error.rs +++ /dev/null @@ -1,18 +0,0 @@ -use portal_verkle_primitives::{Stem, TrieValue}; -use thiserror::Error; - -#[derive(Debug, Error)] -pub enum VerkleTrieError { - #[error("Expected stem {expected}, but received {actual}")] - UnexpectedStem { expected: Stem, actual: Stem }, - #[error( - "Wrong old value for stem {stem} at index {index}. Expected {expected:?}, received {actual:?}" )] - WrongOldValue { - stem: Stem, - index: u8, - expected: Option, - actual: Option, - }, - #[error("Node not found during the trie traversal")] - NodeNotFound, -} diff --git a/portal-verkle/src/verkle_trie/mod.rs b/portal-verkle/src/verkle_trie/mod.rs deleted file mode 100644 index 7e7c63a..0000000 --- a/portal-verkle/src/verkle_trie/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub mod error; -pub mod nodes; -mod trie; -pub mod trie_printer; - -pub use trie::{PathToLeaf, VerkleTrie}; diff --git a/portal-verkle/src/verkle_trie/nodes/branch.rs b/portal-verkle/src/verkle_trie/nodes/branch.rs deleted file mode 100644 index 7c97092..0000000 --- a/portal-verkle/src/verkle_trie/nodes/branch.rs +++ /dev/null @@ -1,186 +0,0 @@ -use std::{array, mem}; - -use portal_verkle_primitives::{ - constants::{PORTAL_NETWORK_NODE_WIDTH, VERKLE_NODE_WIDTH}, - portal::{BranchBundleNode, BranchFragmentNode}, - ssz::{SparseVector, TriePath}, - Point, ScalarField, Stem, TrieKey, TrieValue, CRS, -}; - -use crate::{ - types::state_write::StemStateWrite, utils::bundle_proof, verkle_trie::error::VerkleTrieError, -}; - -use super::{commitment::Commitment, leaf::LeafNode, Node}; - -pub struct BranchNode { - depth: usize, - commitment: Commitment, - children: [Node; VERKLE_NODE_WIDTH], -} - -impl BranchNode { - pub fn new(depth: usize) -> Self { - if depth >= Stem::len_bytes() { - panic!("Invalid branch depth!") - } - Self { - depth, - commitment: Commitment::zero(), - children: array::from_fn(|_| Node::Empty), - } - } - - pub fn commitment(&self) -> &Point { - self.commitment.commitment() - } - - pub fn commitment_hash(&mut self) -> ScalarField { - self.commitment.commitment_hash() - } - - pub fn get(&self, key: &TrieKey) -> Option<&TrieValue> { - let index = key[self.depth] as usize; - match &self.children[index] { - Node::Empty => None, - Node::Branch(branch_node) => branch_node.get(key), - Node::Leaf(leaf_node) => { - if key.starts_with_stem(leaf_node.stem()) { - leaf_node.get(key.suffix() as usize) - } else { - None - } - } - } - } - - pub fn insert(&mut self, key: &TrieKey, value: TrieValue) { - let index = key[self.depth] as usize; - let child = &mut self.children[index]; - let old_commitment_hash = child.commitment_hash(); - match child { - Node::Empty => { - let mut leaf_node = Box::new(LeafNode::new(key.stem())); - leaf_node.set(key.suffix() as usize, value); - *child = Node::Leaf(leaf_node); - } - Node::Branch(branch_node) => branch_node.insert(key, value), - Node::Leaf(leaf_node) => { - if leaf_node.stem() == &key.stem() { - leaf_node.set(key.suffix() as usize, value); - } else { - let old_child_index_in_new_branch = leaf_node.stem()[self.depth + 1] as usize; - let old_child = mem::replace(child, Node::Empty); - - let mut branch_node = Box::new(Self::new(self.depth + 1)); - branch_node.set_child(old_child_index_in_new_branch, old_child); - branch_node.insert(key, value); - - *child = Node::Branch(branch_node); - } - } - } - self.commitment += CRS::commit_single( - index as u8, - &(child.commitment_hash() - old_commitment_hash), - ); - } - - pub fn get_child(&self, index: usize) -> &Node { - &self.children[index] - } - - fn set_child(&mut self, index: usize, mut child: Node) { - self.commitment += CRS::commit_single( - index as u8, - &(child.commitment_hash() - self.children[index].commitment_hash()), - ); - self.children[index] = child; - } - - /// Returns the path to the new branch node if one was created. - pub fn update( - &mut self, - state_write: &StemStateWrite, - ) -> Result, VerkleTrieError> { - let index = state_write.stem[self.depth] as usize; - let child = &mut self.children[index]; - let old_commitment_hash = child.commitment_hash(); - let mut path_to_created_branch = None; - match child { - Node::Empty => { - let mut leaf_node = Box::new(LeafNode::new(state_write.stem)); - leaf_node.update(state_write)?; - *child = Node::Leaf(leaf_node); - } - Node::Branch(branch_node) => { - path_to_created_branch = branch_node.update(state_write)?; - } - Node::Leaf(leaf_node) => { - if leaf_node.stem() == &state_write.stem { - leaf_node.update(state_write)?; - } else { - let old_child_index_in_new_branch = leaf_node.stem()[self.depth + 1] as usize; - let old_child = mem::replace(child, Node::Empty); - - let mut branch_node = Box::new(Self::new(self.depth + 1)); - branch_node.set_child(old_child_index_in_new_branch, old_child); - branch_node.update(state_write)?; - - path_to_created_branch = Some(TriePath::from( - state_write.stem[..branch_node.depth].to_vec(), - )); - *child = Node::Branch(branch_node); - } - } - }; - self.commitment += CRS::commit_single( - index as u8, - &(child.commitment_hash() - old_commitment_hash), - ); - Ok(path_to_created_branch) - } - - fn get_fragment_commitment(&self, fragment_index: usize) -> Option { - let start_index = fragment_index * PORTAL_NETWORK_NODE_WIDTH; - let mut commitment = Point::zero(); - for fragment_child_index in 0..PORTAL_NETWORK_NODE_WIDTH { - let index = start_index + fragment_child_index; - let child_commitment = self.children[index].commitment(); - if !child_commitment.is_zero() { - commitment += - CRS::commit_single(index as u8, &child_commitment.map_to_scalar_field()); - } - } - if commitment.is_zero() { - None - } else { - Some(commitment) - } - } - - pub fn extract_bundle_node(&self) -> BranchBundleNode { - let fragment_commitments = SparseVector::new(array::from_fn(|fragment_index| { - self.get_fragment_commitment(fragment_index) - })); - let bundle_proof = bundle_proof(&fragment_commitments); - BranchBundleNode::new(fragment_commitments, bundle_proof) - } - - pub fn extract_fragment_node(&self, fragment_index: usize) -> (Point, BranchFragmentNode) { - let fragment_commitment = self - .get_fragment_commitment(fragment_index) - .unwrap_or_else(Point::zero); - let children = SparseVector::new(array::from_fn(|fragment_child_index| { - let child_index = fragment_index * PORTAL_NETWORK_NODE_WIDTH + fragment_child_index; - let commitment = self.children[child_index].commitment(); - if commitment.is_zero() { - None - } else { - Some(commitment) - } - })); - let fragment_node = BranchFragmentNode::new(fragment_index as u8, children); - (fragment_commitment, fragment_node) - } -} diff --git a/portal-verkle/src/verkle_trie/nodes/commitment.rs b/portal-verkle/src/verkle_trie/nodes/commitment.rs deleted file mode 100644 index 6418c09..0000000 --- a/portal-verkle/src/verkle_trie/nodes/commitment.rs +++ /dev/null @@ -1,50 +0,0 @@ -use std::ops::{Add, AddAssign}; - -use portal_verkle_primitives::{Point, ScalarField}; - -pub struct Commitment { - commitment: Point, - commitment_hash: Option, -} - -impl Commitment { - pub fn new(commitment: Point) -> Self { - Self { - commitment, - commitment_hash: None, - } - } - - pub fn commitment(&self) -> &Point { - &self.commitment - } - - pub fn commitment_hash(&mut self) -> ScalarField { - self.commitment_hash - .get_or_insert_with(|| self.commitment.map_to_scalar_field()) - .clone() - } - - pub fn zero() -> Self { - Self::new(Point::zero()) - } - - pub fn is_zero(&self) -> bool { - self.commitment.is_zero() - } -} - -impl Add for Commitment { - type Output = Self; - - fn add(self, rhs: Self) -> Self::Output { - Self::new(self.commitment + rhs.commitment) - } -} - -impl AddAssign for Commitment { - fn add_assign(&mut self, rhs: Point) { - self.commitment += rhs; - self.commitment_hash = None; - } -} diff --git a/portal-verkle/src/verkle_trie/nodes/leaf.rs b/portal-verkle/src/verkle_trie/nodes/leaf.rs deleted file mode 100644 index 5d035be..0000000 --- a/portal-verkle/src/verkle_trie/nodes/leaf.rs +++ /dev/null @@ -1,186 +0,0 @@ -use std::array; - -use portal_verkle_primitives::{ - constants::{ - LEAF_C1_INDEX, LEAF_C2_INDEX, LEAF_MARKER_INDEX, LEAF_STEM_INDEX, - PORTAL_NETWORK_NODE_WIDTH, VERKLE_NODE_WIDTH, - }, - portal::{LeafBundleNode, LeafFragmentNode}, - ssz::SparseVector, - Point, ScalarField, Stem, TrieValue, TrieValueSplit, CRS, -}; - -use crate::{ - types::state_write::StemStateWrite, utils::bundle_proof, verkle_trie::error::VerkleTrieError, -}; - -use super::commitment::Commitment; - -pub struct LeafNode { - marker: u64, - stem: Stem, - commitment: Commitment, - pub c1: Commitment, - pub c2: Commitment, - values: [Option; VERKLE_NODE_WIDTH], -} - -impl LeafNode { - pub fn new(stem: Stem) -> Self { - let marker = 1; - - let commitment = CRS::commit_sparse(&[ - (LEAF_MARKER_INDEX, ScalarField::from(marker)), - (LEAF_STEM_INDEX, ScalarField::from(&stem)), - ]); - - Self { - marker, - stem, - commitment: Commitment::new(commitment), - c1: Commitment::zero(), - c2: Commitment::zero(), - values: array::from_fn(|_| None), - } - } - - pub fn marker(&self) -> u64 { - self.marker - } - - pub fn stem(&self) -> &Stem { - &self.stem - } - - pub fn commitment(&self) -> &Point { - self.commitment.commitment() - } - - pub fn commitment_hash(&mut self) -> ScalarField { - self.commitment.commitment_hash() - } - - pub fn get(&self, index: usize) -> Option<&TrieValue> { - self.values[index].as_ref() - } - - pub fn set(&mut self, index: usize, value: TrieValue) { - let (new_low_value, new_high_value) = value.split(); - let old_value = self.values[index].replace(value); - let (old_low_value, old_high_value) = old_value.split(); - - let suffix_index = (index % (VERKLE_NODE_WIDTH / 2)) as u8; - let suffix_commitment_diff = - CRS::commit_single(2 * suffix_index, &(new_low_value - old_low_value)) - + CRS::commit_single(2 * suffix_index + 1, &(new_high_value - old_high_value)); - - if index < VERKLE_NODE_WIDTH / 2 { - let old_c1_commitment_hash = self.c1.commitment_hash(); - self.c1 += suffix_commitment_diff; - self.commitment += CRS::commit_single( - LEAF_C1_INDEX, - &(self.c1.commitment_hash() - old_c1_commitment_hash), - ); - } else { - let old_c2_commitment_hash = self.c2.commitment_hash(); - self.c2 += suffix_commitment_diff; - self.commitment += CRS::commit_single( - LEAF_C2_INDEX, - &(self.c2.commitment_hash() - old_c2_commitment_hash), - ); - } - } - - pub fn update(&mut self, state_write: &StemStateWrite) -> Result<(), VerkleTrieError> { - if self.stem != state_write.stem { - return Err(VerkleTrieError::UnexpectedStem { - expected: self.stem, - actual: state_write.stem, - }); - } - let old_c1_commitment_hash = self.c1.commitment_hash(); - let old_c2_commitment_hash = self.c2.commitment_hash(); - for suffix_write in state_write.suffix_writes.iter() { - let index = suffix_write.suffix as usize; - let old_value = suffix_write.old_value; - if self.values[index] != old_value { - return Err(VerkleTrieError::WrongOldValue { - stem: self.stem, - index: index as u8, - expected: self.values[index], - actual: old_value, - }); - } - let new_value = suffix_write.new_value; - let (new_low_value, new_high_value) = new_value.split(); - let old_value = self.values[index].replace(new_value); - let (old_low_value, old_high_value) = old_value.split(); - - let suffix_index = (index % (VERKLE_NODE_WIDTH / 2)) as u8; - let suffix_commitment_diff = CRS::commit_sparse(&[ - (2 * suffix_index, new_low_value - old_low_value), - (2 * suffix_index + 1, new_high_value - old_high_value), - ]); - - if index < VERKLE_NODE_WIDTH / 2 { - self.c1 += suffix_commitment_diff; - } else { - self.c2 += suffix_commitment_diff; - } - } - self.commitment += CRS::commit_single( - LEAF_C1_INDEX, - &(self.c1.commitment_hash() - old_c1_commitment_hash), - ); - self.commitment += CRS::commit_single( - LEAF_C2_INDEX, - &(self.c2.commitment_hash() - old_c2_commitment_hash), - ); - Ok(()) - } - - fn get_fragment_commitment(&self, fragment_index: usize) -> Option { - let start_index = fragment_index * PORTAL_NETWORK_NODE_WIDTH; - let mut commitment = Point::zero(); - for fragment_child_index in 0..PORTAL_NETWORK_NODE_WIDTH { - let index = start_index + fragment_child_index; - if let Some(value) = &self.values[index] { - let (low_value, high_value) = value.split(); - - let suffix_index = (index % (VERKLE_NODE_WIDTH / 2)) as u8; - commitment += CRS::commit_single(2 * suffix_index, &low_value); - commitment += CRS::commit_single(2 * suffix_index + 1, &high_value); - } - } - if commitment.is_zero() { - None - } else { - Some(commitment) - } - } - - pub fn extract_bundle_node(&self) -> LeafBundleNode { - let fragment_commitments = SparseVector::new(array::from_fn(|fragment_index| { - self.get_fragment_commitment(fragment_index) - })); - let bundle_proof = bundle_proof(&fragment_commitments); - LeafBundleNode::new( - self.marker, - *self.stem(), - fragment_commitments, - bundle_proof, - ) - } - - pub fn extract_fragment_node(&self, fragment_index: usize) -> (Point, LeafFragmentNode) { - let fragment_commitment = self - .get_fragment_commitment(fragment_index) - .unwrap_or_else(Point::zero); - let children = SparseVector::new(array::from_fn(|fragment_child_index| { - let child_index = fragment_index * PORTAL_NETWORK_NODE_WIDTH + fragment_child_index; - self.values[child_index] - })); - let fragment_node = LeafFragmentNode::new(fragment_index as u8, children); - (fragment_commitment, fragment_node) - } -} diff --git a/portal-verkle/src/verkle_trie/nodes/mod.rs b/portal-verkle/src/verkle_trie/nodes/mod.rs deleted file mode 100644 index 838a1f4..0000000 --- a/portal-verkle/src/verkle_trie/nodes/mod.rs +++ /dev/null @@ -1,35 +0,0 @@ -use branch::BranchNode; -use leaf::LeafNode; -use portal_verkle_primitives::{Point, ScalarField}; - -pub mod branch; -pub mod commitment; -pub mod leaf; - -pub enum Node { - Empty, - Branch(Box), - Leaf(Box), -} - -impl Node { - pub fn commitment(&self) -> Point { - match self { - Node::Empty => Point::zero(), - Node::Branch(branch_node) => branch_node.commitment().clone(), - Node::Leaf(leaf_node) => leaf_node.commitment().clone(), - } - } - - pub fn commitment_hash(&mut self) -> ScalarField { - match self { - Node::Empty => ScalarField::zero(), - Node::Branch(branch_node) => branch_node.commitment_hash(), - Node::Leaf(leaf_node) => leaf_node.commitment_hash(), - } - } - - pub fn is_empty(&self) -> bool { - matches!(self, Node::Empty) - } -} diff --git a/portal-verkle/src/verkle_trie/trie.rs b/portal-verkle/src/verkle_trie/trie.rs deleted file mode 100644 index 5648986..0000000 --- a/portal-verkle/src/verkle_trie/trie.rs +++ /dev/null @@ -1,94 +0,0 @@ -use std::collections::HashSet; - -use alloy_primitives::B256; -use portal_verkle_primitives::{ssz::TriePath, Stem, TrieKey, TrieValue}; - -use super::{ - error::VerkleTrieError, - nodes::{branch::BranchNode, leaf::LeafNode, Node}, -}; -use crate::types::state_write::StateWrites; - -/// Fully in memory implementation of the Verkle Trie. -/// -/// Primary use case is to update the trie based on the `ExecutionWitness`. -pub struct VerkleTrie { - root_node: BranchNode, -} - -pub struct PathToLeaf<'a> { - pub branches: Vec<&'a BranchNode>, - pub leaf: &'a LeafNode, -} - -impl VerkleTrie { - pub fn new() -> Self { - Self { - root_node: BranchNode::new(/* depth= */ 0), - } - } - - pub(super) fn root_node(&self) -> &BranchNode { - &self.root_node - } - - pub fn root(&self) -> B256 { - self.root_node.commitment().into() - } - - pub fn get(&self, key: &TrieKey) -> Option<&TrieValue> { - self.root_node.get(key) - } - - pub fn insert(&mut self, key: &TrieKey, value: TrieValue) { - self.root_node.insert(key, value) - } - - pub fn update( - &mut self, - state_writes: &StateWrites, - ) -> Result, VerkleTrieError> { - let mut created_branches = HashSet::new(); - for stem_state_write in state_writes.iter() { - if let Some(created_branch) = self.root_node.update(stem_state_write)? { - created_branches.insert(created_branch); - } - } - Ok(created_branches) - } - - pub fn traverse_to_leaf<'me>( - &'me self, - stem: &Stem, - ) -> Result, VerkleTrieError> { - let mut branches = vec![]; - - let mut node = &self.root_node; - let mut depth = 0; - - loop { - branches.push(node); - node = match node.get_child(stem[depth] as usize) { - Node::Empty => return Err(VerkleTrieError::NodeNotFound), - Node::Branch(next_node) => next_node, - Node::Leaf(leaf) => { - if leaf.stem() == stem { - return Ok(PathToLeaf { branches, leaf }); - } else { - return Err(VerkleTrieError::UnexpectedStem { - expected: *stem, - actual: *leaf.stem(), - }); - } - } - }; - depth += 1; - } - } -} - -impl Default for VerkleTrie { - fn default() -> Self { - Self::new() - } -} diff --git a/portal-verkle/src/verkle_trie/trie_printer.rs b/portal-verkle/src/verkle_trie/trie_printer.rs deleted file mode 100644 index bc7556f..0000000 --- a/portal-verkle/src/verkle_trie/trie_printer.rs +++ /dev/null @@ -1,144 +0,0 @@ -use std::io::Write; - -use alloy_primitives::hex::{encode, encode_prefixed}; -use portal_verkle_primitives::constants::VERKLE_NODE_WIDTH; - -use super::{ - nodes::{branch::BranchNode, leaf::LeafNode, Node}, - VerkleTrie, -}; - -pub trait TriePrinter { - fn print_state(&self, writer: &mut W) -> std::io::Result<()>; - - fn print_trie(&self, writer: &mut W) -> anyhow::Result<()> { - self.print_trie_with_identation(writer, 0) - } - - fn print_trie_with_identation( - &self, - writer: &mut W, - identation: usize, - ) -> anyhow::Result<()>; -} - -impl TriePrinter for VerkleTrie { - fn print_state(&self, writer: &mut W) -> std::io::Result<()> { - self.root_node().print_state(writer)?; - writer.flush() - } - - fn print_trie_with_identation( - &self, - writer: &mut W, - identation: usize, - ) -> anyhow::Result<()> { - writeln!(writer, "{:identation$}root - {}", "", self.root())?; - self.root_node() - .print_trie_with_identation(writer, identation + 2) - } -} - -impl TriePrinter for Node { - fn print_state(&self, writer: &mut W) -> std::io::Result<()> { - match self { - Node::Empty => Ok(()), - Node::Branch(branch_node) => branch_node.print_state(writer), - Node::Leaf(leaf_node) => leaf_node.print_state(writer), - } - } - - fn print_trie_with_identation( - &self, - writer: &mut W, - identation: usize, - ) -> anyhow::Result<()> { - match self { - Node::Empty => Ok(()), - Node::Branch(branch_node) => branch_node.print_trie_with_identation(writer, identation), - Node::Leaf(leaf_node) => leaf_node.print_trie_with_identation(writer, identation), - } - } -} - -impl TriePrinter for BranchNode { - fn print_state(&self, writer: &mut W) -> std::io::Result<()> { - for index in 0..VERKLE_NODE_WIDTH { - self.get_child(index).print_state(writer)?; - } - Ok(()) - } - - fn print_trie_with_identation( - &self, - writer: &mut W, - identation: usize, - ) -> anyhow::Result<()> { - for index in 0..VERKLE_NODE_WIDTH { - let child = self.get_child(index); - if child.is_empty() { - continue; - } - writeln!( - writer, - "{:identation$}{index:02x} - {:?}", - "", - child.commitment() - )?; - child.print_trie_with_identation(writer, identation + 2)?; - } - Ok(()) - } -} - -impl TriePrinter for LeafNode { - fn print_state(&self, writer: &mut W) -> std::io::Result<()> { - for index in 0..VERKLE_NODE_WIDTH { - if let Some(value) = self.get(index) { - writeln!( - writer, - "{}{index:02x}: {}", - encode(self.stem()), - encode(value.as_slice()), - )?; - } - } - Ok(()) - } - - fn print_trie_with_identation( - &self, - writer: &mut W, - identation: usize, - ) -> anyhow::Result<()> { - writeln!(writer, "{:identation$}stem - {}", "", self.stem())?; - - writeln!(writer, "{:identation$}C1 - {:?}", "", self.c1.commitment())?; - for index in 0..(VERKLE_NODE_WIDTH / 2) { - if let Some(value) = self.get(index) { - writeln!( - writer, - "{:identation$}{index:02x} - {}", - "", - encode_prefixed(value.as_slice()), - identation = identation + 2, - )?; - } - } - - writeln!(writer, "{:identation$}C2 - {:?}", "", self.c2.commitment())?; - for index in (VERKLE_NODE_WIDTH / 2)..VERKLE_NODE_WIDTH { - if let Some(value) = self.get(index) { - writeln!( - writer, - "{:identation$}{index:02x} - {}", - "", - encode_prefixed(value.as_slice()), - identation = identation + 2, - )?; - } - } - - Ok(()) - } -}