Skip to content

Commit cde6936

Browse files
committed
Merge branch 'main' into fix/eth-subscribe
2 parents d3a47fb + 062eee5 commit cde6936

3 files changed

Lines changed: 54 additions & 35 deletions

File tree

Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,11 @@ tower-http = { version = "0.6", features = ["full"] }
8383
dashmap = "6.1"
8484

8585
# Alloy types (v1.x for reth v1.10.0 compatibility)
86+
# IMPORTANT: serde feature required for proper hex serialization in JSON-RPC responses
8687
alloy-primitives = { version = "1", features = ["serde", "rlp"] }
8788
alloy-rpc-types = { version = "1" }
88-
alloy-rpc-types-eth = { version = "1" }
89-
alloy-consensus = { version = "1" }
89+
alloy-rpc-types-eth = { version = "1", features = ["serde"] }
90+
alloy-consensus = { version = "1", features = ["serde"] }
9091

9192
# Networking
9293
futures = "0.3"

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::{
@@ -941,11 +941,12 @@ impl Node {
941941
// Then store the block to MDBX for RPC queries
942942
if let Some(ref bridge) = execution_bridge {
943943
match bridge.execute_cut(cut).await {
944-
Ok(result) => {
944+
Ok(block_result) => {
945945
info!(
946-
"Cut executed successfully - state_root: {}, gas_used: {}",
947-
result.state_root,
948-
result.gas_used
946+
"Cut executed successfully - state_root: {}, gas_used: {}, block_hash: {}",
947+
block_result.execution_result.state_root,
948+
block_result.execution_result.gas_used,
949+
block_result.block_hash
949950
);
950951

951952
// Store the block to MDBX for eth_getBlockByNumber queries
@@ -955,11 +956,11 @@ impl Node {
955956
debug!("Updated RPC block number to {}", height.0);
956957

957958
// Create and store the block
958-
let block = Self::execution_result_to_block(height.0, &result);
959+
let block = Self::execution_result_to_block(height.0, &block_result);
959960
if let Err(e) = storage.block_store().put_block(&block).await {
960961
error!("Failed to store block {} to MDBX: {}", height.0, e);
961962
} else {
962-
debug!("Stored block {} to MDBX", height.0);
963+
debug!("Stored block {} to MDBX with hash {}", height.0, block_result.block_hash);
963964

964965
// Broadcast to WebSocket subscribers (eth_subscribe("newHeads"))
965966
if let Some(ref sub_mgr) = subscription_manager {
@@ -971,8 +972,9 @@ impl Node {
971972
}
972973

973974
// Store receipts for eth_getBlockReceipts queries
974-
if !result.receipts.is_empty() {
975-
let storage_receipts: Vec<StorageReceipt> = result
975+
if !block_result.execution_result.receipts.is_empty() {
976+
let storage_receipts: Vec<StorageReceipt> = block_result
977+
.execution_result
976978
.receipts
977979
.iter()
978980
.map(Self::execution_receipt_to_storage)
@@ -1006,40 +1008,34 @@ impl Node {
10061008
self.validator_id
10071009
}
10081010

1009-
/// Convert an ExecutionResult to a storage Block for MDBX persistence.
1011+
/// Convert a BlockExecutionResult to a storage Block for MDBX persistence.
10101012
///
10111013
/// This creates a Block struct suitable for storage from the execution result.
1012-
/// The block hash is derived from the execution result's block_hash field.
1013-
fn execution_result_to_block(block_number: u64, result: &ExecutionResult) -> Block {
1014-
// Get current timestamp
1015-
let timestamp = std::time::SystemTime::now()
1016-
.duration_since(std::time::UNIX_EPOCH)
1017-
.unwrap_or_default()
1018-
.as_secs();
1014+
/// The block hash and parent hash are properly computed by the ExecutionBridge.
1015+
fn execution_result_to_block(block_number: u64, result: &BlockExecutionResult) -> Block {
1016+
let exec = &result.execution_result;
10191017

10201018
// Extract transaction hashes from receipts
1021-
let transaction_hashes: Vec<[u8; 32]> = result
1022-
.receipts
1023-
.iter()
1024-
.map(|r| r.transaction_hash.0)
1025-
.collect();
1019+
let transaction_hashes: Vec<[u8; 32]> =
1020+
exec.receipts.iter().map(|r| r.transaction_hash.0).collect();
10261021
let transaction_count = transaction_hashes.len() as u32;
10271022

10281023
// Create the block with execution results
1024+
// Use the properly computed block_hash and parent_hash from BlockExecutionResult
10291025
Block {
10301026
hash: result.block_hash.0,
10311027
number: block_number,
1032-
parent_hash: [0u8; 32], // TODO: Track parent hash from previous block
1028+
parent_hash: result.parent_hash.0,
10331029
ommers_hash: [0u8; 32], // Always empty in PoS
10341030
beneficiary: [0u8; 20], // TODO: Set to validator address
1035-
state_root: result.state_root.0,
1036-
transactions_root: result.transactions_root.0,
1037-
receipts_root: result.receipts_root.0,
1038-
logs_bloom: result.logs_bloom.0.to_vec(),
1031+
state_root: exec.state_root.0,
1032+
transactions_root: exec.transactions_root.0,
1033+
receipts_root: exec.receipts_root.0,
1034+
logs_bloom: exec.logs_bloom.0.to_vec(),
10391035
difficulty: [0u8; 32], // Always zero in PoS
10401036
gas_limit: 30_000_000, // TODO: Get from config
1041-
gas_used: result.gas_used,
1042-
timestamp,
1037+
gas_used: exec.gas_used,
1038+
timestamp: result.timestamp,
10431039
extra_data: Vec::new(),
10441040
mix_hash: [0u8; 32], // prevrandao in PoS
10451041
nonce: [0u8; 8], // Always zero in PoS

0 commit comments

Comments
 (0)