From 023c777123c148d790057905f58597e5f9c133f5 Mon Sep 17 00:00:00 2001 From: Peter Zhang Date: Wed, 19 Nov 2025 21:51:14 +0800 Subject: [PATCH] add node hash rpc --- Cargo.lock | 1 + common/append_merkle/src/lib.rs | 6 ++++++ node/rpc/src/zgs/api.rs | 6 ++++++ node/rpc/src/zgs/impl.rs | 13 +++++++++++++ node/storage-async/Cargo.toml | 1 + node/storage-async/src/lib.rs | 2 ++ node/storage/src/log_store/log_manager.rs | 10 ++++++++++ node/storage/src/log_store/mod.rs | 3 +++ 8 files changed, 42 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 35a912e..e4ac131 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7747,6 +7747,7 @@ name = "storage-async" version = "0.1.0" dependencies = [ "anyhow", + "append_merkle", "backtrace", "eth2_ssz", "shared_types", diff --git a/common/append_merkle/src/lib.rs b/common/append_merkle/src/lib.rs index 361b550..ddf4c25 100644 --- a/common/append_merkle/src/lib.rs +++ b/common/append_merkle/src/lib.rs @@ -309,6 +309,8 @@ impl> AppendMerkleTree { /// Panics if the leaf is already set and different or the index is out of range. /// TODO: Batch computing intermediate nodes. pub fn fill_leaf(&mut self, index: usize, leaf: E) { + // print node leaf at 12288 index + if leaf.is_null() { // fill leaf with null is not allowed. } else if self.node(0, index).is_null() { @@ -425,6 +427,10 @@ impl> AppendMerkleTree { self.root_to_tx_seq_map.contains_key(root) } + pub fn get_node_hash_by_index(&self, index: usize) -> Result> { + Ok(Some(self.node(0, index))) + } + pub fn leaf_at(&self, position: usize) -> Result> { if position >= self.leaves() { bail!("Out of bound: position={} end={}", position, self.leaves()); diff --git a/node/rpc/src/zgs/api.rs b/node/rpc/src/zgs/api.rs index a922da5..8862777 100644 --- a/node/rpc/src/zgs/api.rs +++ b/node/rpc/src/zgs/api.rs @@ -82,6 +82,12 @@ pub trait Rpc { flow_root: Option, ) -> RpcResult; + #[method(name = "getHashAtNodeIndex")] + async fn get_hash_at_node_index( + &self, + node_index: u64, + ) -> RpcResult>; + #[method(name = "getFlowContext")] async fn get_flow_context(&self) -> RpcResult<(H256, u64)>; } diff --git a/node/rpc/src/zgs/impl.rs b/node/rpc/src/zgs/impl.rs index d1440a5..bc44b9a 100644 --- a/node/rpc/src/zgs/impl.rs +++ b/node/rpc/src/zgs/impl.rs @@ -225,6 +225,19 @@ impl RpcServer for RpcServerImpl { Ok(proof.right_proof) } + async fn get_hash_at_node_index( + &self, + node_index: u64, + ) -> RpcResult> { + debug!(%node_index, "zgs_getHashAtNodeIndex"); + let hash = self + .ctx + .log_store + .get_node_hash_by_index(node_index) + .await?; + Ok(hash.0) + } + async fn get_flow_context(&self) -> RpcResult<(H256, u64)> { Ok(self.ctx.log_store.get_context().await?) } diff --git a/node/storage-async/Cargo.toml b/node/storage-async/Cargo.toml index 01a693f..8341b97 100644 --- a/node/storage-async/Cargo.toml +++ b/node/storage-async/Cargo.toml @@ -8,6 +8,7 @@ anyhow = { version = "1.0.58", features = ["backtrace"] } shared_types = { path = "../shared_types" } storage = { path = "../storage" } task_executor = { path = "../../common/task_executor" } +append_merkle = { path = "../../common/append_merkle" } tokio = { version = "1.19.2", features = ["sync"] } tracing = "0.1.35" eth2_ssz = "0.4.0" diff --git a/node/storage-async/src/lib.rs b/node/storage-async/src/lib.rs index 57de0e2..ca9b528 100644 --- a/node/storage-async/src/lib.rs +++ b/node/storage-async/src/lib.rs @@ -10,6 +10,7 @@ use std::sync::Arc; use storage::{error, error::Result, log_store::Store as LogStore, H256}; use task_executor::TaskExecutor; use tokio::sync::oneshot; +use append_merkle::OptionalHash; pub use storage::config::ShardConfig; use storage::log_store::config::ConfigurableExt; @@ -57,6 +58,7 @@ impl Store { delegate!(fn prune_tx(tx_seq: u64) -> Result<()>); delegate!(fn finalize_tx_with_hash(tx_seq: u64, tx_hash: H256) -> Result); delegate!(fn get_proof_at_root(root: Option, index: u64, length: u64) -> Result); + delegate!(fn get_node_hash_by_index(index: u64) -> Result); delegate!(fn get_context() -> Result<(DataRoot, u64)>); pub async fn get_tx_seq_by_data_root( diff --git a/node/storage/src/log_store/log_manager.rs b/node/storage/src/log_store/log_manager.rs index f22c887..767af16 100644 --- a/node/storage/src/log_store/log_manager.rs +++ b/node/storage/src/log_store/log_manager.rs @@ -564,6 +564,14 @@ impl LogStoreRead for LogManager { self.tx_store.get_tx_by_seq_number(seq) } + fn get_node_hash_by_index(&self, index:u64) -> crate::error::Result { + let merkle = self.merkle.read(); + let opt = merkle + .pora_chunks_merkle + .get_node_hash_by_index(index as usize)?; + opt.ok_or_else(|| anyhow!("node hash not found at index {}", index)) + } + fn get_tx_seq_by_data_root( &self, data_root: &DataRoot, @@ -1115,7 +1123,9 @@ impl LogManager { .pora_chunks_merkle .update_last(merkle.last_chunk_merkle.root()); } + let chunk_roots = self.flow_store.append_entries(flow_entry_array)?; + debug!("fill leaf for pora_chunks_merkle"); for (chunk_index, chunk_root) in chunk_roots { if chunk_index < merkle.pora_chunks_merkle.leaves() as u64 { merkle diff --git a/node/storage/src/log_store/mod.rs b/node/storage/src/log_store/mod.rs index 593f6b3..45b7622 100644 --- a/node/storage/src/log_store/mod.rs +++ b/node/storage/src/log_store/mod.rs @@ -1,5 +1,6 @@ use crate::config::ShardConfig; +use append_merkle::OptionalHash; use ethereum_types::H256; use flow_store::PadPair; use shared_types::{ @@ -30,6 +31,8 @@ pub trait LogStoreRead: LogStoreChunkRead { /// Get a transaction by its global log sequence number. fn get_tx_by_seq_number(&self, seq: u64) -> Result>; + fn get_node_hash_by_index(&self, index:u64) -> Result; + /// Get a transaction by the data root of its data. /// If all txs are not finalized, return the first one if need available is false. /// Otherwise, return the first finalized tx.