Skip to content

Commit 062eee5

Browse files
authored
Merge pull request #124 from decipherhub/fix/block-hash-computation
fix(rpc): return computed block hash from execute_cut
2 parents 8786e34 + c380f0d commit 062eee5

2 files changed

Lines changed: 51 additions & 33 deletions

File tree

crates/node/src/execution_bridge.rs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,22 @@ use std::sync::RwLock as StdRwLock;
1616
use tokio::sync::RwLock;
1717
use tracing::{debug, info, warn};
1818

19+
/// Result of block execution with computed block hash and parent hash.
20+
///
21+
/// This extends `ExecutionResult` with the properly computed block hash
22+
/// and parent hash needed for RPC responses and chain connectivity.
23+
#[derive(Debug, Clone)]
24+
pub struct BlockExecutionResult {
25+
/// The underlying execution result
26+
pub execution_result: ExecutionResult,
27+
/// The computed block hash (keccak256 of block header fields)
28+
pub block_hash: B256,
29+
/// The parent block hash (hash of the previous block)
30+
pub parent_hash: B256,
31+
/// The block timestamp
32+
pub timestamp: u64,
33+
}
34+
1935
/// Bridge between consensus and execution layers
2036
///
2137
/// Maintains the connection between the consensus layer and the execution layer,
@@ -173,11 +189,12 @@ impl ExecutionBridge {
173189
///
174190
/// # Returns
175191
///
176-
/// Returns execution result with state root and receipts.
192+
/// Returns `BlockExecutionResult` containing execution result with properly computed
193+
/// block hash and parent hash for RPC responses.
177194
pub async fn execute_cut(
178195
&self,
179196
consensus_cut: cipherbft_data_chain::Cut,
180-
) -> anyhow::Result<ExecutionResult> {
197+
) -> anyhow::Result<BlockExecutionResult> {
181198
debug!(
182199
height = consensus_cut.height,
183200
cars = consensus_cut.cars.len(),
@@ -234,7 +251,12 @@ impl ExecutionBridge {
234251
"Block hash updated"
235252
);
236253

237-
Ok(result)
254+
Ok(BlockExecutionResult {
255+
execution_result: result,
256+
block_hash: new_block_hash,
257+
parent_hash,
258+
timestamp,
259+
})
238260
}
239261

240262
/// Convert a consensus Cut to an execution Cut

crates/node/src/node.rs

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
//! 5. Exit
1717
1818
use crate::config::NodeConfig;
19-
use crate::execution_bridge::ExecutionBridge;
19+
use crate::execution_bridge::{BlockExecutionResult, ExecutionBridge};
2020
use crate::network::{TcpPrimaryNetwork, TcpWorkerNetwork};
2121
use crate::supervisor::NodeSupervisor;
2222
use anyhow::{Context, Result};
@@ -32,7 +32,7 @@ use cipherbft_data_chain::{
3232
Cut, DclMessage, WorkerMessage,
3333
};
3434
use cipherbft_execution::{
35-
keccak256, ChainConfig, ExecutionResult, InMemoryProvider, Log as ExecutionLog,
35+
keccak256, ChainConfig, InMemoryProvider, Log as ExecutionLog,
3636
TransactionReceipt as ExecutionReceipt,
3737
};
3838
use cipherbft_storage::{
@@ -920,11 +920,12 @@ impl Node {
920920
// Then store the block to MDBX for RPC queries
921921
if let Some(ref bridge) = execution_bridge {
922922
match bridge.execute_cut(cut).await {
923-
Ok(result) => {
923+
Ok(block_result) => {
924924
info!(
925-
"Cut executed successfully - state_root: {}, gas_used: {}",
926-
result.state_root,
927-
result.gas_used
925+
"Cut executed successfully - state_root: {}, gas_used: {}, block_hash: {}",
926+
block_result.execution_result.state_root,
927+
block_result.execution_result.gas_used,
928+
block_result.block_hash
928929
);
929930

930931
// Store the block to MDBX for eth_getBlockByNumber queries
@@ -934,16 +935,17 @@ impl Node {
934935
debug!("Updated RPC block number to {}", height.0);
935936

936937
// Create and store the block
937-
let block = Self::execution_result_to_block(height.0, &result);
938+
let block = Self::execution_result_to_block(height.0, &block_result);
938939
if let Err(e) = storage.block_store().put_block(&block).await {
939940
error!("Failed to store block {} to MDBX: {}", height.0, e);
940941
} else {
941-
debug!("Stored block {} to MDBX", height.0);
942+
debug!("Stored block {} to MDBX with hash {}", height.0, block_result.block_hash);
942943
}
943944

944945
// Store receipts for eth_getBlockReceipts queries
945-
if !result.receipts.is_empty() {
946-
let storage_receipts: Vec<StorageReceipt> = result
946+
if !block_result.execution_result.receipts.is_empty() {
947+
let storage_receipts: Vec<StorageReceipt> = block_result
948+
.execution_result
947949
.receipts
948950
.iter()
949951
.map(Self::execution_receipt_to_storage)
@@ -977,40 +979,34 @@ impl Node {
977979
self.validator_id
978980
}
979981

980-
/// Convert an ExecutionResult to a storage Block for MDBX persistence.
982+
/// Convert a BlockExecutionResult to a storage Block for MDBX persistence.
981983
///
982984
/// This creates a Block struct suitable for storage from the execution result.
983-
/// The block hash is derived from the execution result's block_hash field.
984-
fn execution_result_to_block(block_number: u64, result: &ExecutionResult) -> Block {
985-
// Get current timestamp
986-
let timestamp = std::time::SystemTime::now()
987-
.duration_since(std::time::UNIX_EPOCH)
988-
.unwrap_or_default()
989-
.as_secs();
985+
/// The block hash and parent hash are properly computed by the ExecutionBridge.
986+
fn execution_result_to_block(block_number: u64, result: &BlockExecutionResult) -> Block {
987+
let exec = &result.execution_result;
990988

991989
// Extract transaction hashes from receipts
992-
let transaction_hashes: Vec<[u8; 32]> = result
993-
.receipts
994-
.iter()
995-
.map(|r| r.transaction_hash.0)
996-
.collect();
990+
let transaction_hashes: Vec<[u8; 32]> =
991+
exec.receipts.iter().map(|r| r.transaction_hash.0).collect();
997992
let transaction_count = transaction_hashes.len() as u32;
998993

999994
// Create the block with execution results
995+
// Use the properly computed block_hash and parent_hash from BlockExecutionResult
1000996
Block {
1001997
hash: result.block_hash.0,
1002998
number: block_number,
1003-
parent_hash: [0u8; 32], // TODO: Track parent hash from previous block
999+
parent_hash: result.parent_hash.0,
10041000
ommers_hash: [0u8; 32], // Always empty in PoS
10051001
beneficiary: [0u8; 20], // TODO: Set to validator address
1006-
state_root: result.state_root.0,
1007-
transactions_root: result.transactions_root.0,
1008-
receipts_root: result.receipts_root.0,
1009-
logs_bloom: result.logs_bloom.0.to_vec(),
1002+
state_root: exec.state_root.0,
1003+
transactions_root: exec.transactions_root.0,
1004+
receipts_root: exec.receipts_root.0,
1005+
logs_bloom: exec.logs_bloom.0.to_vec(),
10101006
difficulty: [0u8; 32], // Always zero in PoS
10111007
gas_limit: 30_000_000, // TODO: Get from config
1012-
gas_used: result.gas_used,
1013-
timestamp,
1008+
gas_used: exec.gas_used,
1009+
timestamp: result.timestamp,
10141010
extra_data: Vec::new(),
10151011
mix_hash: [0u8; 32], // prevrandao in PoS
10161012
nonce: [0u8; 8], // Always zero in PoS

0 commit comments

Comments
 (0)