From 3c06f9f9afed37f277f8722f7fd9209de41ac86b Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Wed, 22 Oct 2025 23:21:07 +0800 Subject: [PATCH 01/81] feat: add withdrawal credentials to genesis --- example_genesis.toml | 4 ++++ node/src/args.rs | 28 +++++++++++++++------------- types/src/genesis.rs | 7 +++++-- 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/example_genesis.toml b/example_genesis.toml index 0f5441fc..fd1cdc48 100644 --- a/example_genesis.toml +++ b/example_genesis.toml @@ -10,15 +10,19 @@ namespace = "_SEISMIC_BFT" [[validators]] public_key = "1be3cb06d7cc347602421fb73838534e4b54934e28959de98906d120d0799ef2" ip_address = "127.0.0.1:26600" +withdrawal_credentials = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" [[validators]] public_key = "32efa16e3cd62292db529e8f4babd27724b13b397edcf2b1dbe48f416ce40f0d" ip_address = "127.0.0.1:26610" +withdrawal_credentials = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" [[validators]] public_key = "ce9b314ac9d55d28bedf543164120eecf737380015c977eaa78d59894bbccf52" ip_address = "127.0.0.1:26620" +withdrawal_credentials = "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC" [[validators]] public_key = "f205c8c88d5d1753843dd0fc9810390efd00d6f752dd555c0ad4000bfcac2226" ip_address = "127.0.0.1:26630" +withdrawal_credentials = "0x90F79bf6EB2c4f870365E785982E1f101E93b906" diff --git a/node/src/args.rs b/node/src/args.rs index 7472eb13..9ce05322 100644 --- a/node/src/args.rs +++ b/node/src/args.rs @@ -196,7 +196,7 @@ impl Command { let genesis = Genesis::load_from_file(&flags.genesis_path).expect("Can not find genesis file"); - let mut committee: Vec<(PublicKey, SocketAddr)> = genesis + let mut committee: Vec<(PublicKey, SocketAddr, Address)> = genesis .validators .iter() .map(|v| v.try_into().expect("Invalid validator in genesis")) @@ -269,10 +269,11 @@ impl Command { .expect("This node is not on the committee") }; + let mut network_committee: Vec<(PublicKey, SocketAddr)> = committee.into_iter().map(|(key, ip, _)| (key, ip)).collect(); let our_public_key = signer.public_key(); - if !committee.iter().any(|(key, _)| key == &our_public_key) { - committee.push((our_public_key, our_ip)); - committee.sort(); + if !network_committee.iter().any(|(key, _)| key == &our_public_key) { + network_committee.push((our_public_key, our_ip)); + network_committee.sort(); } // Configure telemetry @@ -314,7 +315,7 @@ impl Command { genesis.namespace.as_bytes(), SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), flags.port), our_ip, - committee.clone(), + network_committee.clone(), genesis.max_message_size_bytes as usize, ); p2p_cfg.mailbox_size = MAILBOX_SIZE; @@ -418,7 +419,7 @@ pub fn run_node_with_runtime( let genesis = Genesis::load_from_file(&flags.genesis_path).expect("Can not find genesis file"); - let mut committee: Vec<(PublicKey, SocketAddr)> = genesis + let mut committee: Vec<(PublicKey, SocketAddr, Address)> = genesis .validators .iter() .map(|v| v.try_into().expect("Invalid validator in genesis")) @@ -488,10 +489,11 @@ pub fn run_node_with_runtime( .expect("This node is not on the committee") }; + let mut network_committee: Vec<(PublicKey, SocketAddr)> = committee.into_iter().map(|(key, ip, _)| (key, ip)).collect(); let our_public_key = signer.public_key(); - if !committee.iter().any(|(key, _)| key == &our_public_key) { - committee.push((our_public_key, our_ip)); - committee.sort(); + if !network_committee.iter().any(|(key, _)| key == &our_public_key) { + network_committee.push((our_public_key, our_ip)); + network_committee.sort(); } // configure network @@ -500,7 +502,7 @@ pub fn run_node_with_runtime( genesis.namespace.as_bytes(), SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), flags.port), our_ip, - committee, + network_committee, genesis.max_message_size_bytes as usize, ); p2p_cfg.mailbox_size = MAILBOX_SIZE; @@ -589,7 +591,7 @@ pub fn run_node_with_runtime( fn get_initial_state( genesis: &Genesis, - committee: &Vec<(PublicKey, SocketAddr)>, + committee: &Vec<(PublicKey, SocketAddr, Address)>, checkpoint: Option, ) -> ConsensusState { let genesis_hash: [u8; 32] = from_hex_formatted(&genesis.eth_genesis_hash) @@ -605,14 +607,14 @@ fn get_initial_state( }; let mut state = ConsensusState::new(forkchoice); // Add the genesis nodes to the consensus state with the minimum stake balance. - for (pubkey, _) in committee { + for (pubkey, _, address) in committee { let pubkey_bytes: [u8; 32] = pubkey .as_ref() .try_into() .expect("Public key must be 32 bytes"); let account = ValidatorAccount { // TODO(matthias): we have to add a withdrawal address to the genesis - withdrawal_credentials: Address::ZERO, + withdrawal_credentials: *address, balance: VALIDATOR_MINIMUM_STAKE, pending_withdrawal_amount: 0, status: ValidatorStatus::Active, diff --git a/types/src/genesis.rs b/types/src/genesis.rs index 5ed18b83..f797a325 100644 --- a/types/src/genesis.rs +++ b/types/src/genesis.rs @@ -3,6 +3,7 @@ use commonware_codec::DecodeExt; use commonware_utils::from_hex_formatted; use serde::{Deserialize, Serialize}; use std::net::SocketAddr; +use alloy_primitives::Address; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Genesis { @@ -41,17 +42,19 @@ pub struct Genesis { pub struct Validator { pub public_key: String, pub ip_address: String, + pub withdrawal_credentials: String, } -impl TryInto<(PublicKey, SocketAddr)> for &Validator { +impl TryInto<(PublicKey, SocketAddr, Address)> for &Validator { type Error = String; - fn try_into(self) -> Result<(PublicKey, SocketAddr), Self::Error> { + fn try_into(self) -> Result<(PublicKey, SocketAddr, Address), Self::Error> { let pub_key_bytes = from_hex_formatted(&self.public_key).ok_or("PublicKey bad format")?; Ok(( PublicKey::decode(&*pub_key_bytes).map_err(|_| "Unable to decode Public Key")?, self.ip_address.parse().map_err(|_| "Invalid ip address")?, + self.withdrawal_credentials.parse().map_err(|_| "Invalid withdrawal credentials")?, )) } } From 2231efe4d414429a541ba58a7be4a7edbc3ff682 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Thu, 23 Oct 2025 04:58:48 +0800 Subject: [PATCH 02/81] chore: set different VALIDATOR_WITHDRAWAL_PERIOD for e2e feature --- node/src/args.rs | 20 ++++++++++++++++---- node/src/engine.rs | 6 ++++-- types/src/genesis.rs | 6 ++++-- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/node/src/args.rs b/node/src/args.rs index 9ce05322..09acaf7b 100644 --- a/node/src/args.rs +++ b/node/src/args.rs @@ -269,9 +269,15 @@ impl Command { .expect("This node is not on the committee") }; - let mut network_committee: Vec<(PublicKey, SocketAddr)> = committee.into_iter().map(|(key, ip, _)| (key, ip)).collect(); + let mut network_committee: Vec<(PublicKey, SocketAddr)> = committee + .into_iter() + .map(|(key, ip, _)| (key, ip)) + .collect(); let our_public_key = signer.public_key(); - if !network_committee.iter().any(|(key, _)| key == &our_public_key) { + if !network_committee + .iter() + .any(|(key, _)| key == &our_public_key) + { network_committee.push((our_public_key, our_ip)); network_committee.sort(); } @@ -489,9 +495,15 @@ pub fn run_node_with_runtime( .expect("This node is not on the committee") }; - let mut network_committee: Vec<(PublicKey, SocketAddr)> = committee.into_iter().map(|(key, ip, _)| (key, ip)).collect(); + let mut network_committee: Vec<(PublicKey, SocketAddr)> = committee + .into_iter() + .map(|(key, ip, _)| (key, ip)) + .collect(); let our_public_key = signer.public_key(); - if !network_committee.iter().any(|(key, _)| key == &our_public_key) { + if !network_committee + .iter() + .any(|(key, _)| key == &our_public_key) + { network_committee.push((our_public_key, our_ip)); network_committee.sort(); } diff --git a/node/src/engine.rs b/node/src/engine.rs index daab1e6f..03ccb167 100644 --- a/node/src/engine.rs +++ b/node/src/engine.rs @@ -35,9 +35,11 @@ const BUFFER_POOL_CAPACITY: NonZero = NZUsize!(8_192); // 32MB const VALIDATOR_ONBOARDING_LIMIT_PER_BLOCK: usize = 3; pub const VALIDATOR_MINIMUM_STAKE: u64 = 32_000_000_000; // in gwei -#[cfg(debug_assertions)] +#[cfg(feature = "e2e")] +pub const VALIDATOR_WITHDRAWAL_PERIOD: u64 = 10; +#[cfg(all(debug_assertions, not(feature = "e2e")))] pub const VALIDATOR_WITHDRAWAL_PERIOD: u64 = 5; -#[cfg(not(debug_assertions))] +#[cfg(all(not(debug_assertions), not(feature = "e2e")))] const VALIDATOR_WITHDRAWAL_PERIOD: u64 = 100; #[cfg(all(feature = "e2e", not(debug_assertions)))] pub const EPOCH_NUM_BLOCKS: u64 = 50; diff --git a/types/src/genesis.rs b/types/src/genesis.rs index f797a325..13f2c674 100644 --- a/types/src/genesis.rs +++ b/types/src/genesis.rs @@ -1,9 +1,9 @@ use crate::PublicKey; +use alloy_primitives::Address; use commonware_codec::DecodeExt; use commonware_utils::from_hex_formatted; use serde::{Deserialize, Serialize}; use std::net::SocketAddr; -use alloy_primitives::Address; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Genesis { @@ -54,7 +54,9 @@ impl TryInto<(PublicKey, SocketAddr, Address)> for &Validator { Ok(( PublicKey::decode(&*pub_key_bytes).map_err(|_| "Unable to decode Public Key")?, self.ip_address.parse().map_err(|_| "Invalid ip address")?, - self.withdrawal_credentials.parse().map_err(|_| "Invalid withdrawal credentials")?, + self.withdrawal_credentials + .parse() + .map_err(|_| "Invalid withdrawal credentials")?, )) } } From 7eef25fa66832f496d3dc0a49d15fbb8d1eb1589 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Thu, 23 Oct 2025 20:50:29 +0800 Subject: [PATCH 03/81] feat: add binary to test withdraw and exit --- finalizer/src/actor.rs | 2 +- node/Cargo.toml | 5 + node/src/bin/stake_and_checkpoint.rs | 2 +- node/src/bin/withdraw_and_exit.rs | 382 +++++++++++++++++++++++++++ 4 files changed, 389 insertions(+), 2 deletions(-) create mode 100644 node/src/bin/withdraw_and_exit.rs diff --git a/finalizer/src/actor.rs b/finalizer/src/actor.rs index d9680e5f..94b4c7a4 100644 --- a/finalizer/src/actor.rs +++ b/finalizer/src/actor.rs @@ -138,6 +138,7 @@ impl< let mut last_committed_timestamp: Option = None; let mut signal = self.context.stopped().fuse(); + loop { select! { msg = rx_finalize_blocks.next() => { @@ -461,7 +462,6 @@ impl< { continue; // Skip this withdrawal request } - // If after this withdrawal the validator balance would be less than the // minimum stake, then the full validator balance is withdrawn. if account.balance diff --git a/node/Cargo.toml b/node/Cargo.toml index 5e67b04b..fbea0f93 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -16,6 +16,11 @@ name = "stake-and-checkpoint" path = "src/bin/stake_and_checkpoint.rs" required-features = ["e2e"] +[[bin]] +name = "withdraw-and-exit" +path = "src/bin/withdraw_and_exit.rs" +required-features = ["e2e"] + [[bin]] name = "block-fetcher" path = "src/bin/block_fetcher.rs" diff --git a/node/src/bin/stake_and_checkpoint.rs b/node/src/bin/stake_and_checkpoint.rs index 1cb8baf7..266cfe06 100644 --- a/node/src/bin/stake_and_checkpoint.rs +++ b/node/src/bin/stake_and_checkpoint.rs @@ -314,7 +314,7 @@ fn main() -> Result<(), Box> { println!("Error querying height: {}", e); } } - context.sleep(std::time::Duration::from_secs(1)).await; + context.sleep(Duration::from_secs(1)).await; } // Retrieve checkpoint from first node diff --git a/node/src/bin/withdraw_and_exit.rs b/node/src/bin/withdraw_and_exit.rs new file mode 100644 index 00000000..d90de256 --- /dev/null +++ b/node/src/bin/withdraw_and_exit.rs @@ -0,0 +1,382 @@ +/* +This bin will start 4 reth nodes with an instance of consensus for each and keep running so you can run other tests or submit transactions + +Their rpc endpoints are localhost:8545-node_number +node0_port = 8545 +node1_port = 8544 +... +node3_port = 8542 + + +*/ +use alloy::network::{EthereumWallet, TransactionBuilder}; +use alloy::providers::{Provider, ProviderBuilder, WalletProvider}; +use alloy::rpc::types::TransactionRequest; +use alloy::signers::local::PrivateKeySigner; +use alloy_primitives::{Address, U256}; +use clap::Parser; +use commonware_codec::DecodeExt; +use commonware_runtime::{Clock, Metrics as _, Runner as _, Spawner as _, tokio as cw_tokio}; +use commonware_utils::from_hex_formatted; +use futures::{FutureExt, pin_mut}; +use std::collections::VecDeque; +use std::time::Duration; +use std::{ + fs, + io::{BufRead as _, BufReader, Write as _}, + net::{IpAddr, Ipv4Addr, SocketAddr}, + path::PathBuf, + str::FromStr as _, + thread::JoinHandle, +}; +use summit::args::{RunFlags, run_node_with_runtime}; +use summit::engine::{EPOCH_NUM_BLOCKS, VALIDATOR_MINIMUM_STAKE}; +use summit_types::PublicKey; +use summit_types::reth::Reth; +use tokio::sync::mpsc; +use tracing::Level; + +const NUM_NODES: u16 = 4; + +#[allow(unused)] +struct NodeRuntime { + thread: JoinHandle<()>, + stop_tx: mpsc::UnboundedSender<()>, +} + +#[derive(Parser, Debug)] +struct Args { + /// Path to the directory containing historical blocks for benchmarking + #[cfg(any(feature = "base-bench", feature = "bench"))] + #[arg(long)] + pub bench_block_dir: Option, + /// Path to the log directory + #[arg(long)] + pub log_dir: Option, + /// Path to the data directory for test + #[arg(long, default_value = "/tmp/summit_withdraw_test")] + pub data_dir: String, + /// Height at which the joining node will download the checkpoint + #[arg(long, default_value_t = 1000)] + pub checkpoint_height: u64, + /// Height that all nodes must reach for the test to succeed + #[arg(long, default_value_t = 2000)] + pub stop_height: u64, +} + +fn main() -> Result<(), Box> { + let args = Args::parse(); + + // Remove data_dir if it exists to start fresh + let data_dir_path = PathBuf::from(&args.data_dir); + if data_dir_path.exists() { + fs::remove_dir_all(&data_dir_path)?; + } + + // Create log directory if specified + if let Some(ref log_dir) = args.log_dir { + fs::remove_dir_all(log_dir)?; + fs::create_dir_all(log_dir)?; + } + + let storage_dir = data_dir_path.join("stores"); + + let cfg = cw_tokio::Config::default() + .with_tcp_nodelay(Some(true)) + .with_worker_threads(16) + .with_storage_directory(storage_dir) + .with_catch_panics(false); + let executor = cw_tokio::Runner::new(cfg); + + executor.start(|context| { + async move { + // Configure telemetry + let log_level = Level::from_str("info").expect("Invalid log level"); + cw_tokio::telemetry::init( + context.with_label("metrics"), + cw_tokio::telemetry::Logging { + level: log_level, + // todo: dont know what this does + json: false, + }, + Some(SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 6969)), + None, + ); + + // Vec to hold all the join handles + let mut handles = VecDeque::new(); + let mut node_runtimes: Vec = Vec::new(); + // let mut read_threads = Vec::new(); + + // Start all nodes at the beginning + for x in 0..NUM_NODES { + // Start Reth + println!("******* STARTING RETH FOR NODE {x}"); + + // Create data directory if it doesn't exist + let data_dir = format!("{}/node{}/data/reth_db", args.data_dir, x); + fs::create_dir_all(&data_dir).expect("Failed to create data directory"); + + // Build and spawn reth instance + let reth_builder = Reth::new() + .instance(x + 1) + .keep_stdout() + // .genesis(serde_json::from_str(&genesis_str).expect("invalid genesis")) + .data_dir(data_dir) + .arg("--enclave.mock-server") + .arg("--enclave.endpoint-port") + .arg(format!("1744{x}")) + .arg("--auth-ipc") + .arg("--auth-ipc.path") + .arg(format!("/tmp/reth_engine_api{x}.ipc")) + .arg("--metrics") + .arg(format!("0.0.0.0:{}", 9001 + x)); + + let mut reth = reth_builder.spawn(); + + // Get stdout handle + let stdout = reth.stdout().expect("Failed to get stdout"); + + let log_dir = args.log_dir.clone(); + context.clone().spawn(async move |_| { + let reader = BufReader::new(stdout); + let mut log_file = log_dir.as_ref().map(|dir| { + fs::File::create(format!("{}/node{}.log", dir, x)) + .expect("Failed to create log file") + }); + + for line in reader.lines() { + match line { + Ok(line) => { + if let Some(ref mut file) = log_file { + writeln!(file, "[Node {}] {}", x, line) + .expect("Failed to write to log file"); + } + } + Err(_e) => { + // eprintln!("[Node {}] Error reading line: {}", x, e); + } + } + } + }); + + let _auth_port = reth.auth_port().unwrap(); + + println!("Node {} rpc address: {}", x, reth.http_port()); + + handles.push_back(reth); + + #[allow(unused_mut)] + let mut flags = get_node_flags(x.into()); + + #[cfg(any(feature = "base-bench", feature = "bench"))] + { + flags.bench_block_dir = args.bench_block_dir.clone(); + } + + // Start our consensus engine in its own runtime/thread + let (stop_tx, mut stop_rx) = mpsc::unbounded_channel(); + let data_dir_clone = args.data_dir.clone(); + let thread = std::thread::spawn(move || { + let storage_dir = PathBuf::from(&data_dir_clone).join("stores").join(format!("node{}", x)); + let cfg = cw_tokio::Config::default() + .with_tcp_nodelay(Some(true)) + .with_worker_threads(4) + .with_storage_directory(storage_dir) + .with_catch_panics(true); + let executor = cw_tokio::Runner::new(cfg); + + executor.start(|node_context| async move { + let node_handle = node_context.clone().spawn(|ctx| async move { + run_node_with_runtime(ctx, flags, None).await.unwrap(); + }); + + // Wait for stop signal or node completion + let stop_fut = stop_rx.recv().fuse(); + pin_mut!(stop_fut); + futures::select! { + _ = stop_fut => { + println!("Node {} received stop signal, shutting down runtime...", x); + node_context.stop(0, Some(Duration::from_secs(30))).await.unwrap(); + } + _ = node_handle.fuse() => { + println!("Node {} handle completed", x); + } + } + }); + }); + + node_runtimes.push(NodeRuntime { thread, stop_tx }); + } + + // Wait a bit for nodes to be ready + context.sleep(Duration::from_secs(2)).await; + + // Send a withdrawal transaction to one of the Reth instances + println!("Sending deposit transaction to node 1"); + let node0_http_port = handles[1].http_port(); + let node0_url = format!("http://localhost:{}", node0_http_port); + + // Create a test private key and signer + let private_key = "0x7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6"; + let signer = PrivateKeySigner::from_str(private_key).expect("Failed to create signer"); + let wallet = EthereumWallet::from(signer); + + // Create provider with wallet + let provider = ProviderBuilder::new() + .wallet(wallet) + .connect_http(node0_url.parse().expect("Invalid URL")); + + let withdrawal_contract_address = Address::from_str("0x00000961Ef480Eb55e80D19ad83579A64c007002").unwrap(); + let pub_key_bytes = from_hex_formatted("f205c8c88d5d1753843dd0fc9810390efd00d6f752dd555c0ad4000bfcac2226").ok_or("PublicKey bad format").unwrap(); + let pub_key_bytes_ar: [u8; 32] = pub_key_bytes.try_into().unwrap(); + let _public_key = PublicKey::decode(&pub_key_bytes_ar[..]).map_err(|_| "Unable to decode Public Key").unwrap(); + let withdrawal_amount = VALIDATOR_MINIMUM_STAKE; + let withdrawal_fee = U256::from(1000000000000000u64); // 0.001 ETH fee + + // Check balance before withdrawal + let withdrawal_credentials = Address::from_str("0x90F79bf6EB2c4f870365E785982E1f101E93b906").unwrap(); + let balance_before = provider.get_balance(withdrawal_credentials).await.expect("Failed to get balance before withdrawal"); + println!("Withdrawal credentials balance before: {} wei", balance_before); + + send_withdrawal_transaction(&provider, withdrawal_contract_address, &pub_key_bytes_ar, withdrawal_amount, withdrawal_fee, 0) + .await + .expect("failed to send deposit transaction"); + + // Wait for all nodes to continue making progress + let epoch_end = EPOCH_NUM_BLOCKS; + println!( + "Waiting for all {} nodes to reach height {}", + NUM_NODES, epoch_end + ); + loop { + let mut all_ready = true; + for idx in 0..NUM_NODES { + let rpc_port = get_node_flags(idx as usize).rpc_port; + match get_latest_height(rpc_port).await { + Ok(height) => { + if height < epoch_end { + all_ready = false; + println!("Node {} at height {}", idx, height); + } + } + Err(e) => { + all_ready = false; + println!("Node {} error: {}", idx, e); + } + } + } + if all_ready { + println!("All nodes have reached height {}", epoch_end); + break; + } + context.sleep(Duration::from_secs(2)).await; + } + + context.sleep(Duration::from_secs(3)).await; + + // Check that the balance was incremented on the execution layer (Reth) + let node0_http_port = handles[0].http_port(); + let node0_url = format!("http://localhost:{}", node0_http_port); + let node0_provider = ProviderBuilder::new().connect_http(node0_url.parse().expect("Invalid URL")); + + let balance_after = node0_provider.get_balance(withdrawal_credentials).await.expect("Failed to get balance after withdrawal"); + println!("Withdrawal credentials balance after: {} wei", balance_after); + + println!("balance before: {}", balance_before); + println!("balance after: {}", balance_after); + + // The withdrawal amount was VALIDATOR_MINIMUM_STAKE (32 ETH in gwei) + // Converting to wei: 32_000_000_000 gwei * 10^9 = 32 * 10^18 wei + let expected_difference = U256::from(VALIDATOR_MINIMUM_STAKE) * U256::from(1_000_000_000u64); + let actual_difference = balance_after - balance_before; + println!("actual_difference: {}", actual_difference); + + // Allow tolerance for gas fees (0.01 ETH = 10^16 wei) + let tolerance = U256::from(10_000_000_000_000_000u64); + let lower_bound = expected_difference - tolerance; + let upper_bound = expected_difference + tolerance; + assert!(actual_difference >= lower_bound && actual_difference <= upper_bound, + "Balance difference {} is outside expected range [{}, {}]", + actual_difference, lower_bound, upper_bound); + println!("Withdrawal successful: balance increased by {} wei (expected ~{})", + actual_difference, expected_difference); + + Ok(()) + } + }) +} + +async fn send_withdrawal_transaction

( + provider: &P, + withdrawal_contract_address: Address, + //validator_pubkey: &[u8; 48], + ed25519_pubkey: &[u8; 32], + withdrawal_amount: u64, // Amount in gwei + withdrawal_fee: U256, // Current fee required by the contract + nonce: u64, +) -> Result<(), Box> +where + P: Provider + WalletProvider, +{ + // Left-pad ed25519 key to 48 bytes for the contract (prepend zeros) + let mut padded_pubkey = [0u8; 48]; + padded_pubkey[16..48].copy_from_slice(ed25519_pubkey); + + // EIP-7002: Input is exactly 56 bytes: validator_pubkey (48 bytes) + amount (8 bytes, big-endian uint64) + let mut call_data = Vec::with_capacity(56); + + // Add validator pubkey (48 bytes) + call_data.extend_from_slice(&padded_pubkey); + + // Add withdrawal amount (8 bytes, big-endian uint64) + call_data.extend_from_slice(&withdrawal_amount.to_be_bytes()); + + let tx_request = TransactionRequest::default() + .to(withdrawal_contract_address) + .value(withdrawal_fee) // Must send enough ETH to cover withdrawal request fee + .input(call_data.into()) + .with_gas_limit(500_000) // Lower gas limit for simpler operation + .with_gas_price(1_000_000_000) // 1 gwei + .with_nonce(nonce); + + match provider.send_transaction(tx_request).await { + Ok(pending) => { + println!("Transaction sent: {}", pending.tx_hash()); + match pending.get_receipt().await { + Ok(receipt) => { + println!("Receipt: {:?}", receipt); + Ok(()) + } + Err(e) => panic!("Transaction failed: {e}"), + } + } + Err(e) => panic!("Error sending transaction: {}", e), + } +} + +async fn get_latest_height(rpc_port: u16) -> Result> { + let url = format!("http://localhost:{}/get_latest_height", rpc_port); + let response = reqwest::get(&url).await?.text().await?; + Ok(response.parse()?) +} + +fn get_node_flags(node: usize) -> RunFlags { + let path = format!("testnet/node{node}/"); + + RunFlags { + key_path: format!("{path}key.pem"), + store_path: format!("{path}db"), + port: (26600 + (node * 10)) as u16, + prom_port: (28600 + (node * 10)) as u16, + rpc_port: (3030 + (node * 10)) as u16, + worker_threads: 2, + log_level: "debug".into(), + db_prefix: format!("{node}-quarts"), + genesis_path: "./example_genesis.toml".into(), + engine_ipc_path: format!("/tmp/reth_engine_api{node}.ipc"), + #[cfg(any(feature = "base-bench", feature = "bench"))] + bench_block_dir: None, + ip: None, + } +} From ad2622d0aeb6c42c9ecdef2c1bc8d750ba232016 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Thu, 23 Oct 2025 23:24:30 +0800 Subject: [PATCH 04/81] feat: shut down runtime if validator is removed from committee --- finalizer/src/actor.rs | 26 +++++++++++++++++++++++++- finalizer/src/config.rs | 2 ++ node/src/bin/withdraw_and_exit.rs | 2 +- node/src/engine.rs | 1 + 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/finalizer/src/actor.rs b/finalizer/src/actor.rs index 94b4c7a4..246f4761 100644 --- a/finalizer/src/actor.rs +++ b/finalizer/src/actor.rs @@ -20,7 +20,7 @@ use prometheus_client::metrics::gauge::Gauge; use rand::Rng; use std::collections::BTreeMap; use std::num::NonZero; -use std::time::Instant; +use std::time::{Duration, Instant}; use summit_syncer::Orchestrator; use summit_types::account::{ValidatorAccount, ValidatorStatus}; use summit_types::checkpoint::Checkpoint; @@ -56,6 +56,8 @@ pub struct Finalizer< validator_withdrawal_period: u64, // in blocks validator_onboarding_limit_per_block: usize, oracle: O, + public_key: PublicKey, + validator_exit: bool, } impl< @@ -106,6 +108,8 @@ impl< validator_minimum_stake: cfg.validator_minimum_stake, validator_withdrawal_period: cfg.validator_withdrawal_period, validator_onboarding_limit_per_block: cfg.validator_onboarding_limit_per_block, + public_key: cfg.public_key, + validator_exit: false, }, FinalizerMailbox::new(tx), ) @@ -140,6 +144,15 @@ impl< let mut signal = self.context.stopped().fuse(); loop { + if self.validator_exit { + // If the validator was removed from the committee, try to shut down the runtime + info!("Validator no longer on the committee, shutting down"); + self.context + .stop(0, None) + .await + .expect("failed to stop runtime"); + break; + } select! { msg = rx_finalize_blocks.next() => { let Some((envelope, notifier)) = msg else { @@ -342,6 +355,17 @@ impl< account.status = ValidatorStatus::Active; } + // If the node's public key is contained in the removed validator list, + // trigger an exit + if self + .state + .removed_validators + .iter() + .any(|pk| pk == &self.public_key) + { + self.validator_exit = true; + } + // TODO(matthias): remove keys in removed_validators from state or set inactive? self.registry.update_registry( // We add a delta to the view because the views are initialized with fixed-size diff --git a/finalizer/src/config.rs b/finalizer/src/config.rs index 351170d0..2442faa5 100644 --- a/finalizer/src/config.rs +++ b/finalizer/src/config.rs @@ -21,4 +21,6 @@ pub struct FinalizerConfig> { pub initial_state: ConsensusState, /// Protocol version for the consensus protocol pub protocol_version: u32, + /// The node's own public key + pub public_key: PublicKey, } diff --git a/node/src/bin/withdraw_and_exit.rs b/node/src/bin/withdraw_and_exit.rs index d90de256..fb5ab238 100644 --- a/node/src/bin/withdraw_and_exit.rs +++ b/node/src/bin/withdraw_and_exit.rs @@ -251,7 +251,7 @@ fn main() -> Result<(), Box> { ); loop { let mut all_ready = true; - for idx in 0..NUM_NODES { + for idx in 0..(NUM_NODES - 1) { let rpc_port = get_node_flags(idx as usize).rpc_port; match get_latest_height(rpc_port).await { Ok(height) => { diff --git a/node/src/engine.rs b/node/src/engine.rs index 03ccb167..dbbdedf3 100644 --- a/node/src/engine.rs +++ b/node/src/engine.rs @@ -145,6 +145,7 @@ impl< genesis_hash: cfg.genesis_hash, initial_state: cfg.initial_state, protocol_version: PROTOCOL_VERSION, + public_key: cfg.signer.public_key(), }, ) .await; From f78ebf352918508146809e2eef42d1d3ed3b99bd Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Fri, 24 Oct 2025 01:30:12 +0800 Subject: [PATCH 05/81] feat: implement Drop for application, syncer, and finalizer to coordinate shutdown --- Cargo.lock | 3 +++ application/Cargo.toml | 1 + application/src/actor.rs | 18 +++++++++++++++++- application/src/config.rs | 3 +++ finalizer/Cargo.toml | 1 + finalizer/src/actor.rs | 30 +++++++++++++++++++++++------- finalizer/src/config.rs | 2 ++ node/src/engine.rs | 38 ++++++++++++++++++++++++++++++-------- syncer/Cargo.toml | 1 + syncer/src/actor.rs | 15 ++++++++++++++- syncer/src/lib.rs | 3 +++ 11 files changed, 98 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0656bdc5..211e4f8e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5586,6 +5586,7 @@ dependencies = [ "summit-finalizer", "summit-syncer", "summit-types", + "tokio-util", "tracing", ] @@ -5611,6 +5612,7 @@ dependencies = [ "rand 0.8.5", "summit-syncer", "summit-types", + "tokio-util", "tracing", ] @@ -5655,6 +5657,7 @@ dependencies = [ "metrics", "rand 0.8.5", "summit-types", + "tokio-util", "tracing", ] diff --git a/application/Cargo.toml b/application/Cargo.toml index eefe5e27..6ce9a5b8 100644 --- a/application/Cargo.toml +++ b/application/Cargo.toml @@ -24,6 +24,7 @@ alloy-eips.workspace = true alloy-primitives.workspace = true governor.workspace = true rand.workspace = true +tokio-util.workspace = true alloy-transport-ipc.workspace = true # For metrics - activate with `prom` feature diff --git a/application/src/actor.rs b/application/src/actor.rs index d3f067da..22756587 100644 --- a/application/src/actor.rs +++ b/application/src/actor.rs @@ -12,6 +12,7 @@ use futures::{ future::{self, Either, try_join}, }; use rand::Rng; +use tokio_util::sync::CancellationToken; use commonware_consensus::simplex::types::View; use futures::task::{Context, Poll}; @@ -59,6 +60,7 @@ pub struct Actor< engine_client: C, built_block: Arc>>, genesis_hash: [u8; 32], + cancellation_token: CancellationToken, } impl @@ -76,6 +78,7 @@ impl { @@ -195,8 +199,12 @@ impl { + info!("application received cancellation signal, exiting"); + break; + }, sig = &mut signal => { - info!("application terminated: {}", sig.unwrap()); + info!("runtime terminated, shutting down application: {}", sig.unwrap()); break; } } @@ -346,6 +354,14 @@ impl Drop + for Actor +{ + fn drop(&mut self) { + self.cancellation_token.cancel(); + } +} + fn handle_verify(block: &Block, parent: Block) -> bool { if block.eth_parent_hash() != parent.eth_block_hash() { return false; diff --git a/application/src/config.rs b/application/src/config.rs index 9f18f034..1d596397 100644 --- a/application/src/config.rs +++ b/application/src/config.rs @@ -1,4 +1,5 @@ use summit_types::EngineClient; +use tokio_util::sync::CancellationToken; #[derive(Clone)] pub struct ApplicationConfig { @@ -11,4 +12,6 @@ pub struct ApplicationConfig { pub partition_prefix: String, pub genesis_hash: [u8; 32], + + pub cancellation_token: CancellationToken, } diff --git a/finalizer/Cargo.toml b/finalizer/Cargo.toml index 5a4aab11..3eaf0762 100644 --- a/finalizer/Cargo.toml +++ b/finalizer/Cargo.toml @@ -22,6 +22,7 @@ bytes.workspace = true futures.workspace = true governor.workspace = true rand.workspace = true +tokio-util.workspace = true tracing.workspace = true diff --git a/finalizer/src/actor.rs b/finalizer/src/actor.rs index 246f4761..78deea9f 100644 --- a/finalizer/src/actor.rs +++ b/finalizer/src/actor.rs @@ -20,7 +20,7 @@ use prometheus_client::metrics::gauge::Gauge; use rand::Rng; use std::collections::BTreeMap; use std::num::NonZero; -use std::time::{Duration, Instant}; +use std::time::Instant; use summit_syncer::Orchestrator; use summit_types::account::{ValidatorAccount, ValidatorStatus}; use summit_types::checkpoint::Checkpoint; @@ -31,6 +31,7 @@ use summit_types::registry::Registry; use summit_types::utils::{is_last_block_of_epoch, is_penultimate_block_of_epoch}; use summit_types::{Block, BlockAuxData, Digest, FinalizedHeader, PublicKey, Signature}; use summit_types::{BlockEnvelope, EngineClient, consensus_state::ConsensusState}; +use tokio_util::sync::CancellationToken; use tracing::{info, warn}; const WRITE_BUFFER: NonZero = NZUsize!(1024 * 1024); @@ -58,6 +59,7 @@ pub struct Finalizer< oracle: O, public_key: PublicKey, validator_exit: bool, + cancellation_token: CancellationToken, } impl< @@ -110,6 +112,7 @@ impl< validator_onboarding_limit_per_block: cfg.validator_onboarding_limit_per_block, public_key: cfg.public_key, validator_exit: false, + cancellation_token: cfg.cancellation_token, }, FinalizerMailbox::new(tx), ) @@ -142,15 +145,13 @@ impl< let mut last_committed_timestamp: Option = None; let mut signal = self.context.stopped().fuse(); + let cancellation_token = self.cancellation_token.clone(); loop { if self.validator_exit { - // If the validator was removed from the committee, try to shut down the runtime + // If the validator was removed from the committee, trigger coordinated shutdown info!("Validator no longer on the committee, shutting down"); - self.context - .stop(0, None) - .await - .expect("failed to stop runtime"); + self.cancellation_token.cancel(); break; } select! { @@ -182,8 +183,12 @@ impl< }, } } + _ = cancellation_token.cancelled().fuse() => { + info!("finalizer received cancellation signal, exiting"); + break; + }, sig = &mut signal => { - info!("finalizer terminated: {}", sig.unwrap()); + info!("runtime terminated, shutting down finalizer: {}", sig.unwrap()); break; } } @@ -740,3 +745,14 @@ impl< } } } + +impl< + R: Storage + Metrics + Clock + Spawner + governor::clock::Clock + Rng, + C: EngineClient, + O: NetworkOracle, +> Drop for Finalizer +{ + fn drop(&mut self) { + self.cancellation_token.cancel(); + } +} diff --git a/finalizer/src/config.rs b/finalizer/src/config.rs index 2442faa5..d64718e6 100644 --- a/finalizer/src/config.rs +++ b/finalizer/src/config.rs @@ -2,6 +2,7 @@ use commonware_runtime::buffer::PoolRef; use summit_types::network_oracle::NetworkOracle; use summit_types::registry::Registry; use summit_types::{EngineClient, PublicKey, consensus_state::ConsensusState}; +use tokio_util::sync::CancellationToken; pub struct FinalizerConfig> { pub mailbox_size: usize, @@ -23,4 +24,5 @@ pub struct FinalizerConfig> { pub protocol_version: u32, /// The node's own public key pub public_key: PublicKey, + pub cancellation_token: CancellationToken, } diff --git a/node/src/engine.rs b/node/src/engine.rs index dbbdedf3..d652064c 100644 --- a/node/src/engine.rs +++ b/node/src/engine.rs @@ -6,6 +6,7 @@ use commonware_p2p::{Receiver, Sender}; use commonware_runtime::buffer::PoolRef; use commonware_runtime::{Clock, Handle, Metrics, Spawner, Storage}; use commonware_utils::NZUsize; +use futures::FutureExt; use futures::channel::mpsc; use futures::future::try_join_all; use governor::clock::Clock as GClock; @@ -18,7 +19,8 @@ use summit_syncer::Orchestrator; use summit_types::network_oracle::NetworkOracle; use summit_types::registry::Registry; use summit_types::{Block, Digest, EngineClient, PrivateKey, PublicKey}; -use tracing::{error, warn}; +use tokio_util::sync::CancellationToken; +use tracing::{error, info, warn}; pub const PROTOCOL_VERSION: u32 = 1; @@ -75,6 +77,7 @@ pub struct Engine< >, sync_height: u64, + cancellation_token: CancellationToken, } impl< @@ -89,6 +92,8 @@ impl< let sync_height = cfg.initial_state.latest_height; + let cancellation_token = CancellationToken::new(); + // create application let (application, application_mailbox) = summit_application::Actor::new( context.with_label("application"), @@ -97,6 +102,7 @@ impl< mailbox_size: cfg.mailbox_size, partition_prefix: cfg.partition_prefix.clone(), genesis_hash: cfg.genesis_hash, + cancellation_token: cancellation_token.clone(), }, ) .await; @@ -123,6 +129,7 @@ impl< activity_timeout: cfg.activity_timeout, namespace: cfg.namespace.clone(), buffer_pool: buffer_pool.clone(), + cancellation_token: cancellation_token.clone(), }; let (syncer, syncer_mailbox, orchestrator) = summit_syncer::Actor::new(context.with_label("syncer"), syncer_config).await; @@ -146,6 +153,7 @@ impl< initial_state: cfg.initial_state, protocol_version: PROTOCOL_VERSION, public_key: cfg.signer.public_key(), + cancellation_token: cancellation_token.clone(), }, ) .await; @@ -190,6 +198,7 @@ impl< finalizer_mailbox, orchestrator, sync_height, + cancellation_token, } } @@ -264,19 +273,32 @@ impl< // start simplex let simplex_handle = self.simplex.start(voter_network, resolver_network); - // Wait for any actor to finish - if let Err(e) = try_join_all(vec![ + // Wait for either all actors to finish or cancellation signal + let actors_fut = try_join_all(vec![ app_handle, buffer_handle, finalizer_handle, syncer_handle, simplex_handle, ]) - .await - { - error!(?e, "engine failed"); - } else { - warn!("engine stopped"); + .fuse(); + let cancellation_fut = self.cancellation_token.cancelled().fuse(); + futures::pin_mut!(actors_fut, cancellation_fut); + + futures::select! { + result = actors_fut => { + if let Err(e) = result { + error!(?e, "engine failed"); + } else { + warn!("engine stopped"); + } + } + _ = cancellation_fut => { + info!("cancellation triggered, waiting for actors to finish"); + if let Err(e) = actors_fut.await { + error!(?e, "engine failed during graceful shutdown"); + } + } } } } diff --git a/syncer/Cargo.toml b/syncer/Cargo.toml index 91506a17..9bb04450 100644 --- a/syncer/Cargo.toml +++ b/syncer/Cargo.toml @@ -21,6 +21,7 @@ bytes.workspace = true futures.workspace = true governor.workspace = true rand.workspace = true +tokio-util.workspace = true tracing.workspace = true # For metrics - activate with `prom` feature diff --git a/syncer/src/actor.rs b/syncer/src/actor.rs index be461f9f..9e885aa7 100644 --- a/syncer/src/actor.rs +++ b/syncer/src/actor.rs @@ -29,6 +29,7 @@ use metrics::histogram; use rand::Rng; use summit_types::registry::Registry; use summit_types::{Block, Digest, Finalized, Notarized, PublicKey, Signature}; +use tokio_util::sync::CancellationToken; use tracing::{debug, info, warn}; const PRUNABLE_ITEMS_PER_SECTION: NonZero = NZU64!(4_096); @@ -62,6 +63,7 @@ pub struct Actor Actor { @@ -162,6 +164,7 @@ impl Acto activity_timeout: config.activity_timeout, namespace: config.namespace, orchestrator_mailbox, + cancellation_token: config.cancellation_token, }, Mailbox::new(tx), Orchestrator::new(orchestrator_sender), @@ -744,11 +747,21 @@ impl Acto }, } }, + _ = self.cancellation_token.cancelled() => { + info!("syncer received cancellation signal, exiting"); + break; + }, sig = &mut signal => { - info!("syncer terminated: {}", sig.unwrap()); + info!("runtime terminated terminated, shutting down syncer: {}", sig.unwrap()); break; } } } } } + +impl Drop for Actor { + fn drop(&mut self) { + self.cancellation_token.cancel(); + } +} diff --git a/syncer/src/lib.rs b/syncer/src/lib.rs index f639d89c..0df91469 100644 --- a/syncer/src/lib.rs +++ b/syncer/src/lib.rs @@ -5,6 +5,7 @@ use commonware_runtime::buffer::PoolRef; pub use ingress::*; use summit_types::PublicKey; use summit_types::registry::Registry; +use tokio_util::sync::CancellationToken; pub mod coordinator; pub mod handler; @@ -28,4 +29,6 @@ pub struct Config { pub namespace: String, pub buffer_pool: PoolRef, + + pub cancellation_token: CancellationToken, } From 019dd57c7e2fe4aea759c0dde7292bf9f554a0c8 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Fri, 24 Oct 2025 02:07:50 +0800 Subject: [PATCH 06/81] chore: remove unused CLI args from withdraw and exit bin --- node/src/bin/withdraw_and_exit.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/node/src/bin/withdraw_and_exit.rs b/node/src/bin/withdraw_and_exit.rs index fb5ab238..bb3fa570 100644 --- a/node/src/bin/withdraw_and_exit.rs +++ b/node/src/bin/withdraw_and_exit.rs @@ -56,12 +56,6 @@ struct Args { /// Path to the data directory for test #[arg(long, default_value = "/tmp/summit_withdraw_test")] pub data_dir: String, - /// Height at which the joining node will download the checkpoint - #[arg(long, default_value_t = 1000)] - pub checkpoint_height: u64, - /// Height that all nodes must reach for the test to succeed - #[arg(long, default_value_t = 2000)] - pub stop_height: u64, } fn main() -> Result<(), Box> { From 4a1edead89e4a6c07a107aadf30222d060200e01 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Fri, 24 Oct 2025 02:32:09 +0800 Subject: [PATCH 07/81] feat: add get validator valance route to rpc --- finalizer/src/actor.rs | 11 ++++++++++ finalizer/src/ingress.rs | 21 +++++++++++++++++- rpc/src/routes.rs | 35 ++++++++++++++++++++++++++++-- types/src/consensus_state_query.rs | 17 +++++++++++++++ 4 files changed, 81 insertions(+), 3 deletions(-) diff --git a/finalizer/src/actor.rs b/finalizer/src/actor.rs index 78deea9f..cd23a7d5 100644 --- a/finalizer/src/actor.rs +++ b/finalizer/src/actor.rs @@ -742,6 +742,17 @@ impl< let height = self.state.get_latest_height(); let _ = sender.send(ConsensusStateResponse::LatestHeight(height)); } + ConsensusStateRequest::GetValidatorBalance(public_key) => { + let mut key_bytes = [0u8; 32]; + key_bytes.copy_from_slice(&public_key); + + let balance = self + .state + .validator_accounts + .get(&key_bytes) + .map(|account| account.balance); + let _ = sender.send(ConsensusStateResponse::ValidatorBalance(balance)); + } } } } diff --git a/finalizer/src/ingress.rs b/finalizer/src/ingress.rs index 85a99f57..7cd7bc69 100644 --- a/finalizer/src/ingress.rs +++ b/finalizer/src/ingress.rs @@ -3,11 +3,12 @@ use futures::{ channel::{mpsc, oneshot}, }; use summit_types::{ - BlockAuxData, + BlockAuxData, PublicKey, checkpoint::Checkpoint, consensus_state_query::{ConsensusStateRequest, ConsensusStateResponse}, }; +#[allow(clippy::large_enum_variant)] pub enum FinalizerMessage { NotifyAtHeight { height: u64, @@ -89,4 +90,22 @@ impl FinalizerMailbox { }; height } + + pub async fn get_validator_balance(&self, public_key: PublicKey) -> Option { + let (response, rx) = oneshot::channel(); + let request = ConsensusStateRequest::GetValidatorBalance(public_key); + let _ = self + .sender + .clone() + .send(FinalizerMessage::QueryState { request, response }) + .await; + + let res = rx + .await + .expect("consensus state query response sender dropped"); + let ConsensusStateResponse::ValidatorBalance(balance) = res else { + unreachable!("request and response variants must match"); + }; + balance + } } diff --git a/rpc/src/routes.rs b/rpc/src/routes.rs index 3c877880..25d607f5 100644 --- a/rpc/src/routes.rs +++ b/rpc/src/routes.rs @@ -2,17 +2,23 @@ use std::sync::Arc; use axum::{ Router, - extract::State, + extract::{Query, State}, routing::{get, post}, }; use commonware_codec::DecodeExt as _; use commonware_cryptography::Signer; use commonware_utils::{from_hex_formatted, hex}; +use serde::Deserialize; use ssz::Encode; -use summit_types::{PrivateKey, utils::get_expanded_path}; +use summit_types::{PrivateKey, PublicKey, utils::get_expanded_path}; use crate::{GenesisRpcState, PathSender, RpcState}; +#[derive(Deserialize)] +struct ValidatorBalanceQuery { + public_key: String, +} + pub(crate) struct RpcRoutes; impl RpcRoutes { @@ -25,6 +31,10 @@ impl RpcRoutes { .route("/get_public_key", get(Self::handle_get_pub_key)) .route("/get_checkpoint", get(Self::handle_get_checkpoint)) .route("/get_latest_height", get(Self::handle_latest_height)) + .route( + "/get_validator_balance", + get(Self::handle_get_validator_balance), + ) .with_state(state) } @@ -80,6 +90,27 @@ impl RpcRoutes { .to_string()) } + async fn handle_get_validator_balance( + State(state): State>, + Query(params): Query, + ) -> Result { + // Parse the public key from hex string + let key_bytes = + from_hex_formatted(¶ms.public_key).ok_or("Invalid hex format for public key")?; + let public_key = + PublicKey::decode(&*key_bytes).map_err(|_| "Unable to decode public key")?; + + let balance = state + .finalizer_mailbox + .get_validator_balance(public_key) + .await; + + match balance { + Some(balance) => Ok(balance.to_string()), + None => Err("Validator not found".to_string()), + } + } + async fn handle_send_genesis( State(state): State>, body: String, diff --git a/types/src/consensus_state_query.rs b/types/src/consensus_state_query.rs index a8f1d3a0..fc5a5edf 100644 --- a/types/src/consensus_state_query.rs +++ b/types/src/consensus_state_query.rs @@ -1,3 +1,4 @@ +use crate::PublicKey; use crate::checkpoint::Checkpoint; use futures::SinkExt; use futures::channel::{mpsc, oneshot}; @@ -5,11 +6,13 @@ use futures::channel::{mpsc, oneshot}; pub enum ConsensusStateRequest { GetCheckpoint, GetLatestHeight, + GetValidatorBalance(PublicKey), } pub enum ConsensusStateResponse { Checkpoint(Option), LatestHeight(u64), + ValidatorBalance(Option), } /// Used to send queries to the application finalizer to query the consensus state. @@ -76,4 +79,18 @@ impl ConsensusStateQuery { }; height } + + pub async fn get_validator_balance(&self, public_key: PublicKey) -> Option { + let (tx, rx) = oneshot::channel(); + let req = ConsensusStateRequest::GetValidatorBalance(public_key); + let _ = self.sender.clone().send((req, tx)).await; + + let res = rx + .await + .expect("consensus state query response sender dropped"); + let ConsensusStateResponse::ValidatorBalance(balance) = res else { + unreachable!("request and response variants must match"); + }; + balance + } } From 69237c2251d43d40016bed74cab7e5f72f21d9bb Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Fri, 24 Oct 2025 02:52:00 +0800 Subject: [PATCH 08/81] feat: verify that validator that withdrew is no longer on consensus state --- node/src/bin/withdraw_and_exit.rs | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/node/src/bin/withdraw_and_exit.rs b/node/src/bin/withdraw_and_exit.rs index bb3fa570..c1bd21d5 100644 --- a/node/src/bin/withdraw_and_exit.rs +++ b/node/src/bin/withdraw_and_exit.rs @@ -274,17 +274,15 @@ fn main() -> Result<(), Box> { let node0_url = format!("http://localhost:{}", node0_http_port); let node0_provider = ProviderBuilder::new().connect_http(node0_url.parse().expect("Invalid URL")); + // Check + let balance_after = node0_provider.get_balance(withdrawal_credentials).await.expect("Failed to get balance after withdrawal"); println!("Withdrawal credentials balance after: {} wei", balance_after); - println!("balance before: {}", balance_before); - println!("balance after: {}", balance_after); - // The withdrawal amount was VALIDATOR_MINIMUM_STAKE (32 ETH in gwei) // Converting to wei: 32_000_000_000 gwei * 10^9 = 32 * 10^18 wei let expected_difference = U256::from(VALIDATOR_MINIMUM_STAKE) * U256::from(1_000_000_000u64); let actual_difference = balance_after - balance_before; - println!("actual_difference: {}", actual_difference); // Allow tolerance for gas fees (0.01 ETH = 10^16 wei) let tolerance = U256::from(10_000_000_000_000_000u64); @@ -296,6 +294,16 @@ fn main() -> Result<(), Box> { println!("Withdrawal successful: balance increased by {} wei (expected ~{})", actual_difference, expected_difference); + // Check that the validator was removed from the consensus state + let rpc_port = get_node_flags(0).rpc_port; + let validator_balance = get_validator_balance(rpc_port, "f205c8c88d5d1753843dd0fc9810390efd00d6f752dd555c0ad4000bfcac2226".to_string()).await; + if let Err(msg) = validator_balance { + assert_eq!(msg.to_string(), "Validator not found"); + println!("Validator that withdrew is not on the consensus state anymore"); + } else { + panic!("Validator should not be on the consensus state anymore"); + } + Ok(()) } }) @@ -355,6 +363,21 @@ async fn get_latest_height(rpc_port: u16) -> Result Result> { + let url = format!( + "http://localhost:{}/get_validator_balance?public_key={}", + rpc_port, public_key + ); + let response = reqwest::get(&url).await?.text().await?; + let Ok(balance) = response.parse() else { + return Err(response.into()); + }; + Ok(balance) +} + fn get_node_flags(node: usize) -> RunFlags { let path = format!("testnet/node{node}/"); From 17ab5696c44ba6b1270d587d540e379bd640c7b5 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Fri, 24 Oct 2025 04:03:51 +0800 Subject: [PATCH 09/81] feat: add cli argument to pass optional checkpoint --- node/src/args.rs | 36 +++++++++++++++++++++------- node/src/bin/stake_and_checkpoint.rs | 1 + node/src/bin/testnet.rs | 1 + node/src/bin/withdraw_and_exit.rs | 1 + types/src/consensus_state_query.rs | 1 + 5 files changed, 31 insertions(+), 9 deletions(-) diff --git a/node/src/args.rs b/node/src/args.rs index 09acaf7b..6eecf333 100644 --- a/node/src/args.rs +++ b/node/src/args.rs @@ -35,6 +35,7 @@ use crate::engine::VALIDATOR_MINIMUM_STAKE; #[cfg(not(any(feature = "bench", feature = "base-bench")))] use summit_types::RethEngineClient; use summit_types::account::{ValidatorAccount, ValidatorStatus}; +use summit_types::checkpoint::Checkpoint; use summit_types::consensus_state::ConsensusState; use summit_types::network_oracle::DiscoveryOracle; use summit_types::{Genesis, PublicKey, utils::get_expanded_path}; @@ -116,6 +117,9 @@ pub struct RunFlags { default_value_t = String::from("./example_genesis.toml") )] pub genesis_path: String, + /// Path to a checkpoint file + #[arg(long)] + pub checkpoint_path: Option, /// IP address for this node (optional, will use genesis if not provided) #[arg(long)] pub ip: Option, @@ -157,6 +161,16 @@ impl Command { console_subscriber::init(); } + let maybe_checkpoint = flags.checkpoint_path.as_ref().map(|path| { + // TODO(matthias): verify the checkpoint + let checkpoint_bytes: Vec = + std::fs::read(path).expect("failed to read checkpoint from disk"); + let checkpoint = Checkpoint::read(&mut checkpoint_bytes.as_ref()) + .expect("failed to parse checkpoint"); + ConsensusState::try_from(checkpoint) + .expect("failed to create consensus state from checkpoint") + }); + let store_path = get_expanded_path(&flags.store_path).expect("Invalid store path"); let signer = expect_signer(&flags.key_path); @@ -203,7 +217,11 @@ impl Command { .collect(); committee.sort(); - let initial_state = get_initial_state(&genesis, &committee, None); + let genesis_hash: [u8; 32] = from_hex_formatted(&genesis.eth_genesis_hash) + .map(|hash_bytes| hash_bytes.try_into()) + .expect("bad eth_genesis_hash") + .expect("bad eth_genesis_hash"); + let initial_state = get_initial_state(genesis_hash, &committee, maybe_checkpoint); let mut peers: Vec = initial_state .validator_accounts .iter() @@ -432,7 +450,11 @@ pub fn run_node_with_runtime( .collect(); committee.sort(); - let initial_state = get_initial_state(&genesis, &committee, checkpoint); + let genesis_hash: [u8; 32] = from_hex_formatted(&genesis.eth_genesis_hash) + .map(|hash_bytes| hash_bytes.try_into()) + .expect("bad eth_genesis_hash") + .expect("bad eth_genesis_hash"); + let initial_state = get_initial_state(genesis_hash, &committee, checkpoint); let mut peers: Vec = initial_state .validator_accounts .iter() @@ -602,14 +624,10 @@ pub fn run_node_with_runtime( } fn get_initial_state( - genesis: &Genesis, - committee: &Vec<(PublicKey, SocketAddr, Address)>, + genesis_hash: [u8; 32], + genesis_committee: &Vec<(PublicKey, SocketAddr, Address)>, checkpoint: Option, ) -> ConsensusState { - let genesis_hash: [u8; 32] = from_hex_formatted(&genesis.eth_genesis_hash) - .map(|hash_bytes| hash_bytes.try_into()) - .expect("bad eth_genesis_hash") - .expect("bad eth_genesis_hash"); let genesis_hash: B256 = genesis_hash.into(); checkpoint.unwrap_or_else(|| { let forkchoice = ForkchoiceState { @@ -619,7 +637,7 @@ fn get_initial_state( }; let mut state = ConsensusState::new(forkchoice); // Add the genesis nodes to the consensus state with the minimum stake balance. - for (pubkey, _, address) in committee { + for (pubkey, _, address) in genesis_committee { let pubkey_bytes: [u8; 32] = pubkey .as_ref() .try_into() diff --git a/node/src/bin/stake_and_checkpoint.rs b/node/src/bin/stake_and_checkpoint.rs index 266cfe06..3e951e49 100644 --- a/node/src/bin/stake_and_checkpoint.rs +++ b/node/src/bin/stake_and_checkpoint.rs @@ -810,6 +810,7 @@ fn get_node_flags(node: usize) -> RunFlags { engine_ipc_path: format!("/tmp/reth_engine_api{node}.ipc"), #[cfg(any(feature = "base-bench", feature = "bench"))] bench_block_dir: None, + checkpoint_path: None, ip: None, } } diff --git a/node/src/bin/testnet.rs b/node/src/bin/testnet.rs index 9c6501d4..8351f6b7 100644 --- a/node/src/bin/testnet.rs +++ b/node/src/bin/testnet.rs @@ -205,6 +205,7 @@ fn get_node_flags(node: usize) -> RunFlags { engine_ipc_path: format!("/tmp/reth_engine_api{node}.ipc"), #[cfg(any(feature = "base-bench", feature = "bench"))] bench_block_dir: None, + checkpoint_path: None, ip: None, } } diff --git a/node/src/bin/withdraw_and_exit.rs b/node/src/bin/withdraw_and_exit.rs index c1bd21d5..e64e1896 100644 --- a/node/src/bin/withdraw_and_exit.rs +++ b/node/src/bin/withdraw_and_exit.rs @@ -394,6 +394,7 @@ fn get_node_flags(node: usize) -> RunFlags { engine_ipc_path: format!("/tmp/reth_engine_api{node}.ipc"), #[cfg(any(feature = "base-bench", feature = "bench"))] bench_block_dir: None, + checkpoint_path: None, ip: None, } } diff --git a/types/src/consensus_state_query.rs b/types/src/consensus_state_query.rs index fc5a5edf..669b0d94 100644 --- a/types/src/consensus_state_query.rs +++ b/types/src/consensus_state_query.rs @@ -3,6 +3,7 @@ use crate::checkpoint::Checkpoint; use futures::SinkExt; use futures::channel::{mpsc, oneshot}; +#[allow(clippy::large_enum_variant)] pub enum ConsensusStateRequest { GetCheckpoint, GetLatestHeight, From 2fb35fce770777483033071120829d2e3cfaeeef Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Sat, 25 Oct 2025 04:15:37 +0800 Subject: [PATCH 10/81] feat: load checkpoint with ssz encoding --- node/src/args.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/node/src/args.rs b/node/src/args.rs index 6eecf333..a39044ad 100644 --- a/node/src/args.rs +++ b/node/src/args.rs @@ -24,6 +24,7 @@ use std::{ num::NonZeroU32, str::FromStr as _, }; +use ssz::Decode; #[cfg(feature = "base-bench")] use summit_types::engine_client::base_benchmarking::HistoricalEngineClient; @@ -165,7 +166,7 @@ impl Command { // TODO(matthias): verify the checkpoint let checkpoint_bytes: Vec = std::fs::read(path).expect("failed to read checkpoint from disk"); - let checkpoint = Checkpoint::read(&mut checkpoint_bytes.as_ref()) + let checkpoint = Checkpoint::from_ssz_bytes(&checkpoint_bytes) .expect("failed to parse checkpoint"); ConsensusState::try_from(checkpoint) .expect("failed to create consensus state from checkpoint") From 5769f6a23343cd61dd41da5fc5db31ee73b2d240 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Sat, 25 Oct 2025 04:21:33 +0800 Subject: [PATCH 11/81] chore: fmt --- node/src/args.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/node/src/args.rs b/node/src/args.rs index a39044ad..b028b46a 100644 --- a/node/src/args.rs +++ b/node/src/args.rs @@ -19,12 +19,12 @@ use commonware_codec::ReadExt; use commonware_utils::from_hex_formatted; use futures::{channel::oneshot, future::try_join_all}; use governor::Quota; +use ssz::Decode; use std::{ net::{IpAddr, Ipv4Addr, SocketAddr}, num::NonZeroU32, str::FromStr as _, }; -use ssz::Decode; #[cfg(feature = "base-bench")] use summit_types::engine_client::base_benchmarking::HistoricalEngineClient; @@ -166,8 +166,8 @@ impl Command { // TODO(matthias): verify the checkpoint let checkpoint_bytes: Vec = std::fs::read(path).expect("failed to read checkpoint from disk"); - let checkpoint = Checkpoint::from_ssz_bytes(&checkpoint_bytes) - .expect("failed to parse checkpoint"); + let checkpoint = + Checkpoint::from_ssz_bytes(&checkpoint_bytes).expect("failed to parse checkpoint"); ConsensusState::try_from(checkpoint) .expect("failed to create consensus state from checkpoint") }); From c2511b85207f806f6227d1201d9eba3f9630249a Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Wed, 29 Oct 2025 23:41:16 +0800 Subject: [PATCH 12/81] chore: switch p2p network config to recommended --- node/src/args.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/node/src/args.rs b/node/src/args.rs index b028b46a..dca3bdb0 100644 --- a/node/src/args.rs +++ b/node/src/args.rs @@ -335,7 +335,7 @@ impl Command { } // configure network - let mut p2p_cfg = authenticated::discovery::Config::aggressive( + let mut p2p_cfg = authenticated::discovery::Config::recommended( signer.clone(), genesis.namespace.as_bytes(), SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), flags.port), @@ -532,7 +532,7 @@ pub fn run_node_with_runtime( } // configure network - let mut p2p_cfg = authenticated::discovery::Config::aggressive( + let mut p2p_cfg = authenticated::discovery::Config::recommended( signer.clone(), genesis.namespace.as_bytes(), SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), flags.port), From 7798dd55da75ac7c95ee892680bdc0f3b14f05e6 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Thu, 30 Oct 2025 02:50:14 +0800 Subject: [PATCH 13/81] fix: clear added and removed validators only after writing to disk --- finalizer/src/actor.rs | 12 +++++++-- types/src/registry.rs | 56 ++++++++++++++++++++++++++---------------- 2 files changed, 45 insertions(+), 23 deletions(-) diff --git a/finalizer/src/actor.rs b/finalizer/src/actor.rs index cd23a7d5..228d31bc 100644 --- a/finalizer/src/actor.rs +++ b/finalizer/src/actor.rs @@ -378,8 +378,8 @@ impl< // out-of-bounds array access. view + REGISTRY_CHANGE_VIEW_DELTA, //view, - std::mem::take(&mut self.state.added_validators), - std::mem::take(&mut self.state.removed_validators), + &self.state.added_validators, + &self.state.removed_validators, ); let participants = self.registry.peers().clone(); // TODO(matthias): should we wait until view `view + REGISTRY_CHANGE_VIEW_DELTA` @@ -406,6 +406,14 @@ impl< histogram!("database_operations_duration_millis").record(db_operations_duration); } + // Only clear the added and removed validators after saving the state to disk + if !self.state.added_validators.is_empty() { + self.state.added_validators.clear(); + } + if !self.state.removed_validators.is_empty() { + self.state.removed_validators.clear(); + } + #[cfg(debug_assertions)] { let gauge: Gauge = Gauge::default(); diff --git a/types/src/registry.rs b/types/src/registry.rs index 093eeae8..0cabd75e 100644 --- a/types/src/registry.rs +++ b/types/src/registry.rs @@ -38,7 +38,7 @@ impl Registry { registry } - pub fn update_registry(&self, index: View, add: Vec, remove: Vec) { + pub fn update_registry(&self, index: View, add: &[PublicKey], remove: &[PublicKey]) { let mut views = self.views.write().unwrap(); let mut participants = if let Some((latest_view, view_data)) = views.last_key_value() { @@ -57,7 +57,7 @@ impl Registry { participants.participants.push(participant.clone()); participants .participants_map - .insert(participant, (participants.participants.len() as u32) - 1); + .insert(participant.clone(), (participants.participants.len() as u32) - 1); } for participant in remove { @@ -211,7 +211,9 @@ mod tests { let new_participant = crate::PrivateKey::from_seed(99).public_key(); // Add participant to view 1 - registry.update_registry(1, vec![new_participant.clone()], vec![]); + let add = vec![new_participant.clone()]; + let remove = vec![]; + registry.update_registry(1, &add, &remove); // Verify participant was added let view_1_participants = registry.participants(1); @@ -230,7 +232,9 @@ mod tests { let existing_participant = registry.participants(0).unwrap()[0].clone(); // Try to add existing participant - should log warning but not fail - registry.update_registry(1, vec![existing_participant.clone()], vec![]); + let add = vec![existing_participant.clone()]; + let remove = vec![]; + registry.update_registry(1, &add, &remove); // Verify participant count didn't increase (duplicate was ignored) let view_1_participants = registry.participants(1); @@ -244,7 +248,9 @@ mod tests { let participant_to_remove = registry.participants(0).unwrap()[1].clone(); // Remove participant from view 1 - registry.update_registry(1, vec![], vec![participant_to_remove.clone()]); + let add = vec![]; + let remove = vec![participant_to_remove.clone()]; + registry.update_registry(1, &add, &remove); // Verify participant was removed let view_1_participants = registry.participants(1); @@ -266,7 +272,9 @@ mod tests { let nonexistent_participant = crate::PrivateKey::from_seed(999).public_key(); // Try to remove non-existent participant - should log warning but not fail - registry.update_registry(1, vec![], vec![nonexistent_participant]); + let add = vec![]; + let remove = vec![nonexistent_participant]; + registry.update_registry(1, &add, &remove); // Verify participant count didn't change (remove was ignored) let view_1_participants = registry.participants(1); @@ -308,7 +316,9 @@ mod tests { // Add participant to create view 3 let new_participant = crate::PrivateKey::from_seed(100).public_key(); - registry.update_registry(3, vec![new_participant.clone()], vec![]); + let add = vec![new_participant.clone()]; + let remove = vec![]; + registry.update_registry(3, &add, &remove); // Views 0, 1, 2 should still use original participants (largest view <= requested) assert_eq!(registry.participants(0).unwrap(), original_participants); @@ -374,7 +384,9 @@ mod tests { // Add participant to create view 1 let new_participant = crate::PrivateKey::from_seed(100).public_key(); - registry.update_registry(1, vec![new_participant], vec![]); + let add = vec![new_participant]; + let remove = vec![]; + registry.update_registry(1, &add, &remove); // Peer set ID should now be 1 assert_eq!(registry.peer_set_id(), 1); @@ -390,7 +402,9 @@ mod tests { // Add participant let new_participant = crate::PrivateKey::from_seed(100).public_key(); - registry.update_registry(1, vec![new_participant.clone()], vec![]); + let add = vec![new_participant.clone()]; + let remove = vec![]; + registry.update_registry(1, &add, &remove); // Peers should now reflect the latest view let updated_peers = registry.peers(); @@ -407,8 +421,8 @@ mod tests { let participant_a = crate::PrivateKey::from_seed(100).public_key(); let participant_b = crate::PrivateKey::from_seed(101).public_key(); - registry.update_registry(3, vec![participant_a.clone()], vec![]); - registry.update_registry(7, vec![participant_b.clone()], vec![]); + registry.update_registry(3, &[participant_a.clone()], &[]); + registry.update_registry(7, &[participant_b.clone()], &[]); // Test participants for each view (largest view <= requested) assert_eq!(registry.participants(0).unwrap().len(), 2); // view 0 @@ -432,7 +446,7 @@ mod tests { // Add participant to view 1 let new_participant = crate::PrivateKey::from_seed(100).public_key(); - registry.update_registry(1, vec![new_participant.clone()], vec![]); + registry.update_registry(1, &[new_participant.clone()], &[]); // Original view should remain unchanged assert_eq!(registry.participants(0).unwrap(), &original_participants); @@ -520,8 +534,8 @@ mod tests { let participant_a = crate::PrivateKey::from_seed(100).public_key(); let participant_b = crate::PrivateKey::from_seed(101).public_key(); - registry.update_registry(3, vec![participant_a.clone()], vec![]); - registry.update_registry(7, vec![participant_b.clone()], vec![]); + registry.update_registry(3, &[participant_a.clone()], &[]); + registry.update_registry(7, &[participant_b.clone()], &[]); // Test that we get the largest view <= requested view // Views available: 0 (2 participants), 3 (3 participants), 7 (4 participants) @@ -556,7 +570,7 @@ mod tests { // Add participant at view 2 let new_participant = crate::PrivateKey::from_seed(100).public_key(); - registry.update_registry(2, vec![new_participant.clone()], vec![]); + registry.update_registry(2, &[new_participant.clone()], &[]); // Leader for view 0-1 should use 4-participant set from view 0 let leader_0 = Su::leader(®istry, 0); @@ -591,7 +605,7 @@ mod tests { // Add participant at view 3 let new_participant = crate::PrivateKey::from_seed(100).public_key(); - registry.update_registry(3, vec![new_participant.clone()], vec![]); + registry.update_registry(3, &[new_participant.clone()], &[]); // Original participants should be found in all views assert_eq!( @@ -634,10 +648,10 @@ mod tests { let participant_a = crate::PrivateKey::from_seed(100).public_key(); let participant_b = crate::PrivateKey::from_seed(101).public_key(); - registry.update_registry(5, vec![participant_a], vec![]); + registry.update_registry(5, &[participant_a], &[]); assert_eq!(registry.peer_set_id(), 5); - registry.update_registry(10, vec![participant_b], vec![]); + registry.update_registry(10, &[participant_b], &[]); assert_eq!(registry.peer_set_id(), 10); } @@ -648,7 +662,7 @@ mod tests { let participant_to_remove = original_participants[1].clone(); // Remove participant at view 2 - registry.update_registry(2, vec![], vec![participant_to_remove.clone()]); + registry.update_registry(2, &[], &[participant_to_remove.clone()]); // Views 0-1 should still have original participants assert_eq!(registry.participants(0).unwrap().len(), 3); @@ -696,8 +710,8 @@ mod tests { // Add two participants and remove one in a single operation registry.update_registry( 1, - vec![new_participant_a.clone(), new_participant_b.clone()], - vec![participant_to_remove.clone()], + &[new_participant_a.clone(), new_participant_b.clone()], + &[participant_to_remove.clone()], ); // Verify the result From b4bf7cfa453b559e9dd5cd3b3f28042404efafce Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Thu, 30 Oct 2025 04:44:14 +0800 Subject: [PATCH 14/81] chore: use height for oracle instead of view --- finalizer/src/actor.rs | 2 +- node/src/args.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/finalizer/src/actor.rs b/finalizer/src/actor.rs index 228d31bc..45d79946 100644 --- a/finalizer/src/actor.rs +++ b/finalizer/src/actor.rs @@ -384,7 +384,7 @@ impl< let participants = self.registry.peers().clone(); // TODO(matthias): should we wait until view `view + REGISTRY_CHANGE_VIEW_DELTA` // to update the oracle? - self.oracle.register(view, participants).await; + self.oracle.register(new_height, participants).await; } #[cfg(feature = "prom")] diff --git a/node/src/args.rs b/node/src/args.rs index dca3bdb0..b7f99c1b 100644 --- a/node/src/args.rs +++ b/node/src/args.rs @@ -350,7 +350,7 @@ impl Command { authenticated::discovery::Network::new(context.with_label("network"), p2p_cfg); // Provide authorized peers - oracle.register(0, peers.clone()).await; + oracle.register(initial_state.latest_height, peers.clone()).await; let oracle = DiscoveryOracle::new(oracle); let config = EngineConfig::get_engine_config( @@ -547,7 +547,7 @@ pub fn run_node_with_runtime( authenticated::discovery::Network::new(context.with_label("network"), p2p_cfg); // Provide authorized peers - oracle.register(0, peers.clone()).await; + oracle.register(initial_state.latest_height, peers.clone()).await; let oracle = DiscoveryOracle::new(oracle); From e4686456b1de80daac80ab30c19429da1933c0ce Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Sat, 1 Nov 2025 00:04:35 +0800 Subject: [PATCH 15/81] chore: use aggressive networking config when e2e flag is enabled --- node/src/args.rs | 18 ++++++++++++++++-- types/src/registry.rs | 7 ++++--- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/node/src/args.rs b/node/src/args.rs index b7f99c1b..8672d005 100644 --- a/node/src/args.rs +++ b/node/src/args.rs @@ -350,7 +350,9 @@ impl Command { authenticated::discovery::Network::new(context.with_label("network"), p2p_cfg); // Provide authorized peers - oracle.register(initial_state.latest_height, peers.clone()).await; + oracle + .register(initial_state.latest_height, peers.clone()) + .await; let oracle = DiscoveryOracle::new(oracle); let config = EngineConfig::get_engine_config( @@ -532,6 +534,16 @@ pub fn run_node_with_runtime( } // configure network + #[cfg(feature = "e2e")] + let mut p2p_cfg = authenticated::discovery::Config::aggressive( + signer.clone(), + genesis.namespace.as_bytes(), + SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), flags.port), + our_ip, + network_committee, + genesis.max_message_size_bytes as usize, + ); + #[cfg(not(feature = "e2e"))] let mut p2p_cfg = authenticated::discovery::Config::recommended( signer.clone(), genesis.namespace.as_bytes(), @@ -547,7 +559,9 @@ pub fn run_node_with_runtime( authenticated::discovery::Network::new(context.with_label("network"), p2p_cfg); // Provide authorized peers - oracle.register(initial_state.latest_height, peers.clone()).await; + oracle + .register(initial_state.latest_height, peers.clone()) + .await; let oracle = DiscoveryOracle::new(oracle); diff --git a/types/src/registry.rs b/types/src/registry.rs index 0cabd75e..22d1c9d4 100644 --- a/types/src/registry.rs +++ b/types/src/registry.rs @@ -55,9 +55,10 @@ impl Registry { continue; } participants.participants.push(participant.clone()); - participants - .participants_map - .insert(participant.clone(), (participants.participants.len() as u32) - 1); + participants.participants_map.insert( + participant.clone(), + (participants.participants.len() as u32) - 1, + ); } for participant in remove { From 03e3f002572d3b134f69a9d7ebed7eb2b6422883 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Sat, 1 Nov 2025 01:29:35 +0800 Subject: [PATCH 16/81] feat: add epoch to consensus state --- types/src/consensus_state.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/types/src/consensus_state.rs b/types/src/consensus_state.rs index e8469f46..81a5192a 100644 --- a/types/src/consensus_state.rs +++ b/types/src/consensus_state.rs @@ -11,6 +11,7 @@ use std::collections::{HashMap, VecDeque}; #[derive(Clone, Debug, Default)] pub struct ConsensusState { + pub epoch: u64, pub latest_height: u64, pub next_withdrawal_index: u64, pub deposit_queue: VecDeque, @@ -118,7 +119,8 @@ impl ConsensusState { impl EncodeSize for ConsensusState { fn encode_size(&self) -> usize { - 8 // latest_height + 8 // epoch + + 8 // latest_height + 8 // next_withdrawal_index + 4 // deposit_queue length + self.deposit_queue.iter().map(|req| req.encode_size()).sum::() @@ -142,6 +144,7 @@ impl Read for ConsensusState { type Cfg = (); fn read_cfg(buf: &mut impl Buf, _cfg: &Self::Cfg) -> Result { + let epoch = buf.get_u64(); let latest_height = buf.get_u64(); let next_withdrawal_index = buf.get_u64(); @@ -203,6 +206,7 @@ impl Read for ConsensusState { }; Ok(Self { + epoch, latest_height, next_withdrawal_index, deposit_queue, @@ -218,6 +222,7 @@ impl Read for ConsensusState { impl Write for ConsensusState { fn write(&self, buf: &mut impl BufMut) { + buf.put_u64(self.epoch); buf.put_u64(self.latest_height); buf.put_u64(self.next_withdrawal_index); @@ -334,6 +339,7 @@ mod tests { let mut encoded = original_state.encode(); let decoded_state = ConsensusState::decode(&mut encoded).expect("Failed to decode"); + assert_eq!(decoded_state.epoch, original_state.epoch); assert_eq!(decoded_state.latest_height, original_state.latest_height); assert_eq!( decoded_state.next_withdrawal_index, @@ -357,6 +363,7 @@ mod tests { fn test_serialization_deserialization_populated() { let mut original_state = ConsensusState::default(); + original_state.epoch = 7; original_state.set_latest_height(42); original_state.next_withdrawal_index = 5; @@ -380,6 +387,7 @@ mod tests { let mut encoded = original_state.encode(); let decoded_state = ConsensusState::decode(&mut encoded).expect("Failed to decode"); + assert_eq!(decoded_state.epoch, original_state.epoch); assert_eq!(decoded_state.latest_height, original_state.latest_height); assert_eq!( decoded_state.next_withdrawal_index, @@ -411,6 +419,7 @@ mod tests { fn test_encode_size_accuracy() { let mut state = ConsensusState::default(); + state.epoch = 3; state.set_latest_height(42); state.next_withdrawal_index = 5; @@ -463,6 +472,7 @@ mod tests { fn test_try_from_checkpoint() { // Create a populated ConsensusState let mut original_state = ConsensusState::default(); + original_state.epoch = 5; original_state.set_latest_height(100); original_state.next_withdrawal_index = 42; @@ -486,6 +496,7 @@ mod tests { .expect("Failed to convert checkpoint back to ConsensusState"); // Verify the data matches + assert_eq!(restored_state.epoch, original_state.epoch); assert_eq!(restored_state.latest_height, original_state.latest_height); assert_eq!( restored_state.next_withdrawal_index, From cf50e86da7898dae377e6567e4aa58e5854fc0b8 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Sat, 1 Nov 2025 05:14:03 +0800 Subject: [PATCH 17/81] feat: update registry --- types/src/registry.rs | 894 ++++++++++++------------------------------ 1 file changed, 245 insertions(+), 649 deletions(-) diff --git a/types/src/registry.rs b/types/src/registry.rs index 22d1c9d4..6774de23 100644 --- a/types/src/registry.rs +++ b/types/src/registry.rs @@ -1,176 +1,190 @@ use crate::PublicKey; -use commonware_consensus::{Supervisor as Su, simplex::types::View}; -use commonware_resolver::p2p; -use std::collections::BTreeMap; +use commonware_consensus::types::View; +use commonware_p2p::Manager; +use std::collections::{BTreeMap, HashSet}; use std::sync::{Arc, RwLock}; -use tracing::warn; +use commonware_utils::set::Ordered; +use futures::channel::mpsc::{UnboundedReceiver, UnboundedSender}; #[derive(Default, Clone, Debug)] -struct Participants { - participants: Vec, - participants_map: BTreeMap, +struct Inner { + sets: BTreeMap>, + subscribers: Vec, Ordered)>>, } -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct Registry { // Map from View -> immutable participant data // Once a view is added, it never changes - views: Arc>>>, + inner: Arc>, } impl Registry { - pub fn new(participants: Vec) -> Self { - let participants_map = participants - .iter() - .enumerate() - .map(|(i, pk)| (pk.clone(), i as u32)) - .collect(); - - let participants = Box::new(Participants { - participants, - participants_map, - }); - let registry = Self { - views: Arc::new(RwLock::new(BTreeMap::new())), - }; - - registry.views.write().unwrap().insert(0, participants); - registry + pub fn new(id: u64, participants: Vec) -> Self { + let mut sets = BTreeMap::new(); + sets.insert(id, Ordered::from(participants)); + let inner = Inner { sets, subscribers: vec![] }; + Self { + inner: Arc::new(RwLock::new(inner)), + } } - pub fn update_registry(&self, index: View, add: &[PublicKey], remove: &[PublicKey]) { - let mut views = self.views.write().unwrap(); - - let mut participants = if let Some((latest_view, view_data)) = views.last_key_value() { - // TODO(matthias): is it possible that `index` is smaller or equal to the latest view? - assert!(*latest_view < index); - view_data.clone() - } else { - Box::new(Participants::default()) - }; - - for participant in add { - if participants.participants_map.contains_key(&participant) { - warn!("Public key {} already exists in current set", participant); - continue; - } - participants.participants.push(participant.clone()); - participants.participants_map.insert( - participant.clone(), - (participants.participants.len() as u32) - 1, - ); - } + pub fn update_registry(&self, id: u64, add: &[PublicKey], remove: &[PublicKey]) { + let mut inner = self.inner.write().unwrap(); + + // TODO(matthias): we should also consider enforcing that the previous id must exist, + // and do something like inner.sets.get(id - 1) + let (_last_id, old_set) = inner.sets.last_key_value().expect("registry was initialized with an id"); - for participant in remove { - let Some(participant_index) = participants.participants_map.get(&participant).copied() - else { - warn!("Public key {} doesn't exist in current set", participant); - continue; - }; - participants - .participants - .swap_remove(participant_index as usize); - participants.participants_map.remove(&participant); - - // re-calculate the index of the swapped public key - if let Some(swapped_key) = participants.participants.get(participant_index as usize) { - participants - .participants_map - .insert(swapped_key.clone(), participant_index); + let mut new_set = Vec::with_capacity((old_set.len() + add.len()).saturating_sub(remove.len())); + let remove: HashSet = HashSet::from_iter(remove.iter().cloned()); + for key in old_set { + if !remove.contains(key) { + new_set.push(key.clone()); } } - views.insert(index, participants); - } -} + for key in add { + new_set.push(key.clone()); + } -impl p2p::Coordinator for Registry { - type PublicKey = PublicKey; + let old_set = old_set.clone(); + inner.sets.insert(id, Ordered::from(new_set.clone())); - fn peers(&self) -> &Vec { - // SAFETY: This is safe because: - // 1. Views are never removed once added (append-only guarantee) - // 2. Box has a stable address that doesn't change - // 3. The data inside Participants is immutable after creation - // 4. We only return references to data that we know exists - // 5. The registry lives as long as any references to it - // - // The unsafe extends the lifetime from the RwLock guard to 'self, - // which is valid because the data actually lives as long as 'self - let views = self.views.read().unwrap(); - - // Use the list of participants that is associated with the largest index - if let Some((_view, view_data)) = views.last_key_value() { - let ptr = &view_data.participants as *const Vec; - // Drop the guard explicitly - drop(views); - // SAFETY: The Box ensures the data has a stable address - // Views are never removed, so this pointer remains valid - unsafe { &*ptr } - } else { - static EMPTY: Vec = Vec::new(); - &EMPTY - } - } + // Notify all subscribers + let notification = (id, old_set, Ordered::from(new_set)); + inner.subscribers.retain(|tx| { + tx.unbounded_send(notification.clone()).is_ok() + }); - fn peer_set_id(&self) -> u64 { - let views = self.views.read().unwrap(); - let (view, _view_data) = views - .last_key_value() - .expect("at least one views exists because it is set in the `new` function"); - *view + // TODO(matthias): consider garbage collection for old IDs } } -impl Su for Registry { - type Index = View; - +impl Manager for Registry { type PublicKey = PublicKey; - fn leader(&self, index: Self::Index) -> Option { - let views = self.views.read().unwrap(); + type Peers = Vec; + fn update(&mut self, id: u64, peers: Self::Peers) -> impl Future + Send { + let mut inner = self.inner.write().unwrap(); - // Find the largest view that is <= the requested view - let (_max_view, view_data) = views.range(..=index).next_back()?; + // Since IDs are monotonically increasing, the old set is the last one in the map + let old_set = inner.sets.last_key_value() + .map(|(_, set)| set.clone()) + .unwrap_or_else(|| Ordered::from(Vec::new())); - if view_data.participants.is_empty() { - return None; - } + let new_set = Ordered::from(peers); + inner.sets.insert(id, new_set.clone()); - let leader_index = (index as usize) % view_data.participants.len(); - Some(view_data.participants[leader_index].clone()) - } - - fn participants(&self, index: Self::Index) -> Option<&Vec> { - // SAFETY: Same safety reasoning as peers() method above - let views = self.views.read().unwrap(); - - // Find the largest view that is <= the requested view - let (_max_view, view_data) = views.range(..=index).next_back()?; - - if view_data.participants.is_empty() { - return None; - } + // Notify all subscribers + let notification = (id, old_set, new_set); + inner.subscribers.retain(|tx| { + tx.unbounded_send(notification.clone()).is_ok() + }); - let ptr = &view_data.participants as *const Vec; - drop(views); - Some(unsafe { &*ptr }) + async {} } - fn is_participant(&self, index: Self::Index, candidate: &Self::PublicKey) -> Option { - let views = self.views.read().unwrap(); + fn peer_set(&mut self, id: u64) -> impl Future>> + Send { + let inner = self.inner.write().unwrap(); + let set = inner.sets.get(&id).map(|s| s.clone()); + async move { set } + } - // Find the largest view that is <= the requested view - let (_max_view, view_data) = views.range(..=index).next_back()?; - view_data.participants_map.get(candidate).cloned() + fn subscribe(&mut self) -> impl Future, Ordered)>> + Send { + let (tx, rx) = futures::channel::mpsc::unbounded(); + let mut inner = self.inner.write().unwrap(); + inner.subscribers.push(tx); + async move { rx } } } +//impl p2p::Coordinator for Registry { +// type PublicKey = PublicKey; +// +// fn peers(&self) -> &Vec { +// // SAFETY: This is safe because: +// // 1. Views are never removed once added (append-only guarantee) +// // 2. Box has a stable address that doesn't change +// // 3. The data inside Participants is immutable after creation +// // 4. We only return references to data that we know exists +// // 5. The registry lives as long as any references to it +// // +// // The unsafe extends the lifetime from the RwLock guard to 'self, +// // which is valid because the data actually lives as long as 'self +// let views = self.views.read().unwrap(); +// +// // Use the list of participants that is associated with the largest index +// if let Some((_view, view_data)) = views.last_key_value() { +// let ptr = &view_data.participants as *const Vec; +// // Drop the guard explicitly +// drop(views); +// // SAFETY: The Box ensures the data has a stable address +// // Views are never removed, so this pointer remains valid +// unsafe { &*ptr } +// } else { +// static EMPTY: Vec = Vec::new(); +// &EMPTY +// } +// } +// +// fn peer_set_id(&self) -> u64 { +// let views = self.views.read().unwrap(); +// let (view, _view_data) = views +// .last_key_value() +// .expect("at least one views exists because it is set in the `new` function"); +// *view +// } +//} + +//impl Su for Registry { +// type Index = View; +// +// type PublicKey = PublicKey; +// +// //fn leader(&self, index: Self::Index) -> Option { +// // let views = self.views.read().unwrap(); +// +// // // Find the largest view that is <= the requested view +// // let (_max_view, view_data) = views.range(..=index).next_back()?; +// +// // if view_data.participants.is_empty() { +// // return None; +// // } +// +// // let leader_index = (index as usize) % view_data.participants.len(); +// // Some(view_data.participants[leader_index].clone()) +// //} +// +// fn participants(&self, index: Self::Index) -> Option<&Vec> { +// // SAFETY: Same safety reasoning as peers() method above +// let views = self.views.read().unwrap(); +// +// // Find the largest view that is <= the requested view +// let (_max_view, view_data) = views.range(..=index).next_back()?; +// +// if view_data.participants.is_empty() { +// return None; +// } +// +// let ptr = &view_data.participants as *const Vec; +// drop(views); +// Some(unsafe { &*ptr }) +// } +// +// fn is_participant(&self, index: Self::Index, candidate: &Self::PublicKey) -> Option { +// let views = self.views.read().unwrap(); +// +// // Find the largest view that is <= the requested view +// let (_max_view, view_data) = views.range(..=index).next_back()?; +// view_data.participants_map.get(candidate).cloned() +// } +//} + #[cfg(test)] mod tests { use super::*; - use commonware_consensus::Supervisor as Su; use commonware_cryptography::{PrivateKeyExt, Signer}; - use commonware_resolver::p2p::Coordinator; + use commonware_runtime::{Runner as _, deterministic::Runner}; /// Helper function to create deterministic test public keys fn create_test_pubkeys(count: usize) -> Vec { @@ -185,546 +199,128 @@ mod tests { /// Helper function to create a test registry with specified number of participants fn create_test_registry(participant_count: usize) -> Registry { let participants = create_test_pubkeys(participant_count); - Registry::new(participants) + Registry::new(0, participants) } #[test] fn test_new_registry() { - let participant_count = 3; - let participants = create_test_pubkeys(participant_count); - let expected_participants = participants.clone(); - - let registry = Registry::new(participants); - - // Test that participants are correctly stored in view 0 - let view_0_participants = registry.participants(0); - assert!(view_0_participants.is_some()); - assert_eq!(view_0_participants.unwrap(), &expected_participants); - - // Test that registry is not empty - assert!(!registry.participants(0).unwrap().is_empty()); - assert_eq!(registry.participants(0).unwrap().len(), participant_count); + let cfg = commonware_runtime::deterministic::Config::default().with_seed(0); + let executor = Runner::from(cfg); + executor.start(|_context| async move { + let participant_count = 3; + let participants = create_test_pubkeys(participant_count); + let expected_participants = Ordered::from(participants.clone()); + + let mut registry = Registry::new(0, participants); + + // Test that participants are correctly stored in id 0 + let peer_set_0 = registry.peer_set(0).await.unwrap(); + assert_eq!(peer_set_0.len(), participant_count); + assert_eq!(peer_set_0, expected_participants); + }); } #[test] fn test_update_registry_add_participant() { - let registry = create_test_registry(2); - let new_participant = crate::PrivateKey::from_seed(99).public_key(); - - // Add participant to view 1 - let add = vec![new_participant.clone()]; - let remove = vec![]; - registry.update_registry(1, &add, &remove); - - // Verify participant was added - let view_1_participants = registry.participants(1); - assert!(view_1_participants.is_some()); - assert_eq!(view_1_participants.unwrap().len(), 3); - assert!(view_1_participants.unwrap().contains(&new_participant)); - - // Original view should remain unchanged - let view_0_participants = registry.participants(0); - assert_eq!(view_0_participants.unwrap().len(), 2); - } - - #[test] - fn test_update_registry_add_duplicate_participant() { - let registry = create_test_registry(2); - let existing_participant = registry.participants(0).unwrap()[0].clone(); - - // Try to add existing participant - should log warning but not fail - let add = vec![existing_participant.clone()]; - let remove = vec![]; - registry.update_registry(1, &add, &remove); - - // Verify participant count didn't increase (duplicate was ignored) - let view_1_participants = registry.participants(1); - assert_eq!(view_1_participants.unwrap().len(), 2); - assert!(view_1_participants.unwrap().contains(&existing_participant)); + let cfg = commonware_runtime::deterministic::Config::default().with_seed(0); + let executor = Runner::from(cfg); + executor.start(|_context| async move { + let mut registry = create_test_registry(2); + let new_participant = crate::PrivateKey::from_seed(99).public_key(); + + // Add participant to id 1 + let add = vec![new_participant.clone()]; + let remove = vec![]; + registry.update_registry(1, &add, &remove); + + // Verify participant was added + let set_1 = registry.peer_set(1).await.unwrap(); + assert_eq!(set_1.len(), 3); + assert!(set_1.iter().any(|p| p == &new_participant)); + + // Original set should remain unchanged + let set_0 = registry.peer_set(0).await; + assert_eq!(set_0.unwrap().len(), 2); + }); } #[test] fn test_update_registry_remove_participant() { - let registry = create_test_registry(3); - let participant_to_remove = registry.participants(0).unwrap()[1].clone(); - - // Remove participant from view 1 - let add = vec![]; - let remove = vec![participant_to_remove.clone()]; - registry.update_registry(1, &add, &remove); - - // Verify participant was removed - let view_1_participants = registry.participants(1); - assert!(view_1_participants.is_some()); - assert_eq!(view_1_participants.unwrap().len(), 2); - assert!( - !view_1_participants - .unwrap() - .contains(&participant_to_remove) - ); - - // Original view should remain unchanged - assert_eq!(registry.participants(0).unwrap().len(), 3); - } - - #[test] - fn test_update_registry_remove_nonexistent_participant() { - let registry = create_test_registry(2); - let nonexistent_participant = crate::PrivateKey::from_seed(999).public_key(); - - // Try to remove non-existent participant - should log warning but not fail - let add = vec![]; - let remove = vec![nonexistent_participant]; - registry.update_registry(1, &add, &remove); - - // Verify participant count didn't change (remove was ignored) - let view_1_participants = registry.participants(1); - assert_eq!(view_1_participants.unwrap().len(), 2); - } - - // Supervisor trait implementation tests - #[test] - fn test_supervisor_leader_selection() { - let registry = create_test_registry(5); - let participants = registry.participants(0).unwrap(); - - // Test round-robin leader selection - for view in 0..10 { - let leader = Su::leader(®istry, view); - assert!(leader.is_some()); - let expected_leader = &participants[view as usize % participants.len()]; - assert_eq!(leader.unwrap(), *expected_leader); - } - } - - #[test] - fn test_supervisor_leader_empty_participants() { - let participants = Vec::new(); - let registry = Registry::new(participants); - - // Should return None for empty participant set - let leader = Su::leader(®istry, 0); - assert!(leader.is_none()); - } - - #[test] - fn test_supervisor_participants_by_view() { - let registry = create_test_registry(3); - let original_participants = registry.participants(0).unwrap(); - - // View 0 should have original participants - assert_eq!(registry.participants(0).unwrap(), original_participants); - - // Add participant to create view 3 - let new_participant = crate::PrivateKey::from_seed(100).public_key(); - let add = vec![new_participant.clone()]; - let remove = vec![]; - registry.update_registry(3, &add, &remove); - - // Views 0, 1, 2 should still use original participants (largest view <= requested) - assert_eq!(registry.participants(0).unwrap(), original_participants); - assert_eq!(registry.participants(1).unwrap(), original_participants); - assert_eq!(registry.participants(2).unwrap(), original_participants); - - // View 3 and beyond should have updated participants - let view_3_participants = registry.participants(3).unwrap(); - assert_eq!(view_3_participants.len(), 4); - assert!(view_3_participants.contains(&new_participant)); - - // Future views should use latest available view (view 3) - assert_eq!(registry.participants(4), registry.participants(3)); - assert_eq!(registry.participants(100), registry.participants(3)); - } - - #[test] - fn test_supervisor_is_participant() { - let registry = create_test_registry(4); - let participants = registry.participants(0).unwrap(); - - // Test existing participants - for (i, participant) in participants.iter().enumerate() { - let result = registry.is_participant(0, participant); - assert_eq!(result, Some(i as u32)); - } - - // Test non-existing participant - let non_participant = crate::PrivateKey::from_seed(999).public_key(); - assert_eq!(registry.is_participant(0, &non_participant), None); - - // Test with view that uses latest available participants - assert_eq!(registry.is_participant(100, &participants[0]), Some(0)); - } - - #[test] - fn test_supervisor_participants_none() { - let participants = Vec::new(); - let registry = Registry::new(participants); - - // Should return None for views with no participants - assert!(registry.participants(0).is_none()); - assert!(registry.participants(1).is_none()); - } - - // p2p::Coordinator trait implementation tests - #[test] - fn test_p2p_coordinator_peers() { - let registry = create_test_registry(4); - let expected_peers = registry.participants(0).unwrap(); - - let peers = registry.peers(); - assert_eq!(peers, expected_peers); - assert_eq!(peers.len(), 4); - } - - #[test] - fn test_p2p_coordinator_peer_set_id() { - let registry = create_test_registry(3); - - // Initial peer set ID should be 0 - assert_eq!(registry.peer_set_id(), 0); - - // Add participant to create view 1 - let new_participant = crate::PrivateKey::from_seed(100).public_key(); - let add = vec![new_participant]; - let remove = vec![]; - registry.update_registry(1, &add, &remove); - - // Peer set ID should now be 1 - assert_eq!(registry.peer_set_id(), 1); - } - - #[test] - fn test_p2p_coordinator_peers_with_updates() { - let registry = create_test_registry(2); - - // Initial peers - let initial_peers = registry.peers(); - assert_eq!(initial_peers.len(), 2); - - // Add participant - let new_participant = crate::PrivateKey::from_seed(100).public_key(); - let add = vec![new_participant.clone()]; - let remove = vec![]; - registry.update_registry(1, &add, &remove); - - // Peers should now reflect the latest view - let updated_peers = registry.peers(); - assert_eq!(updated_peers.len(), 3); - assert!(updated_peers.contains(&new_participant)); - } - - // Multi-view operations and edge cases - #[test] - fn test_multiple_views() { - let registry = create_test_registry(2); - - // Add participants to different views - let participant_a = crate::PrivateKey::from_seed(100).public_key(); - let participant_b = crate::PrivateKey::from_seed(101).public_key(); - - registry.update_registry(3, &[participant_a.clone()], &[]); - registry.update_registry(7, &[participant_b.clone()], &[]); - - // Test participants for each view (largest view <= requested) - assert_eq!(registry.participants(0).unwrap().len(), 2); // view 0 - assert_eq!(registry.participants(1).unwrap().len(), 2); // view 0 - assert_eq!(registry.participants(2).unwrap().len(), 2); // view 0 - assert_eq!(registry.participants(3).unwrap().len(), 3); // view 3 - assert_eq!(registry.participants(4).unwrap().len(), 3); // view 3 - assert_eq!(registry.participants(5).unwrap().len(), 3); // view 3 - assert_eq!(registry.participants(6).unwrap().len(), 3); // view 3 - assert_eq!(registry.participants(7).unwrap().len(), 4); // view 7 - - // Test that future views use the latest available view - assert_eq!(registry.participants(8), registry.participants(7)); - assert_eq!(registry.participants(100), registry.participants(7)); - } - - #[test] - fn test_view_persistence() { - let registry = create_test_registry(2); - let original_participants = registry.participants(0).unwrap().clone(); - - // Add participant to view 1 - let new_participant = crate::PrivateKey::from_seed(100).public_key(); - registry.update_registry(1, &[new_participant.clone()], &[]); - - // Original view should remain unchanged - assert_eq!(registry.participants(0).unwrap(), &original_participants); - - // New view should have additional participant - assert_eq!(registry.participants(1).unwrap().len(), 3); - assert!(registry.participants(1).unwrap().contains(&new_participant)); - } - - #[test] - fn test_large_participant_sets() { - let large_registry = create_test_registry(100); - let participants = large_registry.participants(0).unwrap(); - - // Test basic operations with large set - assert_eq!(participants.len(), 100); - - // Test leader selection works with large sets - let leader = Su::leader(&large_registry, 0); - assert!(leader.is_some()); - assert!(participants.contains(&leader.unwrap())); - - // Test is_participant works with large sets - for (i, participant) in participants.iter().enumerate() { - assert_eq!( - large_registry.is_participant(0, participant), - Some(i as u32) - ); - } - } - - #[test] - fn test_concurrent_access() { - use std::sync::Arc; - use std::thread; - - let registry = Arc::new(create_test_registry(5)); - let mut handles = vec![]; - - // Spawn multiple threads to access registry concurrently - for i in 0..10 { - let registry_clone = Arc::clone(®istry); - let handle = thread::spawn(move || { - // Test concurrent reads - let participants = registry_clone.participants(0); - assert!(participants.is_some()); - assert_eq!(participants.unwrap().len(), 5); - - // Test leader selection - let leader = Su::leader(&*registry_clone, i); - assert!(leader.is_some()); - - // Test is_participant - let first_participant = &participants.unwrap()[0]; - assert_eq!(registry_clone.is_participant(0, first_participant), Some(0)); - }); - handles.push(handle); - } - - // Wait for all threads to complete - for handle in handles { - handle.join().unwrap(); - } - } - - #[test] - fn test_edge_case_view_zero_with_operations() { - let registry = create_test_registry(1); - - // Test operations on view 0 - let participants = registry.participants(0).unwrap(); - assert_eq!(participants.len(), 1); - - let leader = Su::leader(®istry, 0); - assert_eq!(leader, Some(participants[0].clone())); - - assert_eq!(registry.is_participant(0, &participants[0]), Some(0)); + let cfg = commonware_runtime::deterministic::Config::default().with_seed(0); + let executor = Runner::from(cfg); + executor.start(|_context| async move { + let mut registry = create_test_registry(3); + + let set_0 = registry.peer_set(0).await.unwrap(); + let participant_to_remove = set_0.iter().nth(1).unwrap().clone(); + + // Remove participant from id 1 + let add = vec![]; + let remove = vec![participant_to_remove.clone()]; + registry.update_registry(1, &add, &remove); + + // Verify participant was removed + let set_1 = registry.peer_set(1).await.unwrap(); + assert_eq!(set_1.len(), 2); + assert!(!set_1.iter().any(|p| p == &participant_to_remove)); + + // Original set should remain unchanged + assert_eq!(set_0.len(), 3); + }); } #[test] - fn test_view_selection_logic() { - let registry = create_test_registry(2); - - // Add participants to sparse views: 0, 3, 7 - let participant_a = crate::PrivateKey::from_seed(100).public_key(); - let participant_b = crate::PrivateKey::from_seed(101).public_key(); - - registry.update_registry(3, &[participant_a.clone()], &[]); - registry.update_registry(7, &[participant_b.clone()], &[]); - - // Test that we get the largest view <= requested view - // Views available: 0 (2 participants), 3 (3 participants), 7 (4 participants) - - // Requests for views 0-2 should return view 0 - assert_eq!(registry.participants(0).unwrap().len(), 2); - assert_eq!(registry.participants(1).unwrap().len(), 2); - assert_eq!(registry.participants(2).unwrap().len(), 2); - - // Requests for views 3-6 should return view 3 - assert_eq!(registry.participants(3).unwrap().len(), 3); - assert_eq!(registry.participants(4).unwrap().len(), 3); - assert_eq!(registry.participants(5).unwrap().len(), 3); - assert_eq!(registry.participants(6).unwrap().len(), 3); - - // Requests for view 7+ should return view 7 - assert_eq!(registry.participants(7).unwrap().len(), 4); - assert_eq!(registry.participants(8).unwrap().len(), 4); - assert_eq!(registry.participants(100).unwrap().len(), 4); - - // Verify participants contain expected members - assert!(registry.participants(3).unwrap().contains(&participant_a)); - assert!(!registry.participants(3).unwrap().contains(&participant_b)); - - assert!(registry.participants(7).unwrap().contains(&participant_a)); - assert!(registry.participants(7).unwrap().contains(&participant_b)); + fn test_subscribe() { + let cfg = commonware_runtime::deterministic::Config::default().with_seed(0); + let executor = Runner::from(cfg); + executor.start(|_context| async move { + let mut registry = create_test_registry(2); + + // Subscribe to updates + let _rx = registry.subscribe().await; + + // Verify subscription was registered + let inner = registry.inner.read().unwrap(); + assert_eq!(inner.subscribers.len(), 1); + }); } #[test] - fn test_leader_selection_across_views() { - let registry = create_test_registry(4); - - // Add participant at view 2 - let new_participant = crate::PrivateKey::from_seed(100).public_key(); - registry.update_registry(2, &[new_participant.clone()], &[]); - - // Leader for view 0-1 should use 4-participant set from view 0 - let leader_0 = Su::leader(®istry, 0); - let leader_1 = Su::leader(®istry, 1); - let participants_view_0 = registry.participants(0).unwrap(); - - assert_eq!(leader_0, Some(participants_view_0[0].clone())); - assert_eq!( - leader_1, - Some(participants_view_0[1 % participants_view_0.len()].clone()) - ); - - // Leader for view 2+ should use 5-participant set from view 2 - let leader_2 = Su::leader(®istry, 2); - let leader_3 = Su::leader(®istry, 3); - let participants_view_2 = registry.participants(2).unwrap(); - - assert_eq!( - leader_2, - Some(participants_view_2[2 % participants_view_2.len()].clone()) - ); - assert_eq!( - leader_3, - Some(participants_view_2[3 % participants_view_2.len()].clone()) - ); - } + fn test_subscribers_receive_updates() { + let cfg = commonware_runtime::deterministic::Config::default().with_seed(0); + let executor = Runner::from(cfg); + executor.start(|_context| async move { + use futures::StreamExt; - #[test] - fn test_is_participant_across_views() { - let registry = create_test_registry(2); - let original_participants = registry.participants(0).unwrap().clone(); - - // Add participant at view 3 - let new_participant = crate::PrivateKey::from_seed(100).public_key(); - registry.update_registry(3, &[new_participant.clone()], &[]); - - // Original participants should be found in all views - assert_eq!( - registry.is_participant(0, &original_participants[0]), - Some(0) - ); - assert_eq!( - registry.is_participant(1, &original_participants[0]), - Some(0) - ); - assert_eq!( - registry.is_participant(2, &original_participants[0]), - Some(0) - ); - assert_eq!( - registry.is_participant(3, &original_participants[0]), - Some(0) - ); - assert_eq!( - registry.is_participant(10, &original_participants[0]), - Some(0) - ); - - // New participant should only be found from view 3 onwards - assert_eq!(registry.is_participant(0, &new_participant), None); - assert_eq!(registry.is_participant(1, &new_participant), None); - assert_eq!(registry.is_participant(2, &new_participant), None); - assert_eq!(registry.is_participant(3, &new_participant), Some(2)); - assert_eq!(registry.is_participant(10, &new_participant), Some(2)); - } + let mut registry = create_test_registry(2); - #[test] - fn test_peer_set_id_reflects_latest_view() { - let registry = create_test_registry(2); + // Subscribe to updates + let mut rx = registry.subscribe().await; - // Initially should be view 0 - assert_eq!(registry.peer_set_id(), 0); + // Get the initial peer set + let set_0 = registry.peer_set(0).await.unwrap(); - // Add participants to different views - let participant_a = crate::PrivateKey::from_seed(100).public_key(); - let participant_b = crate::PrivateKey::from_seed(101).public_key(); + // Use the Manager trait's update method to trigger notifications + let new_participant = crate::PrivateKey::from_seed(99).public_key(); + let mut new_peers = set_0.iter().cloned().collect::>(); + new_peers.push(new_participant.clone()); - registry.update_registry(5, &[participant_a], &[]); - assert_eq!(registry.peer_set_id(), 5); + registry.update(1, new_peers.clone()).await; - registry.update_registry(10, &[participant_b], &[]); - assert_eq!(registry.peer_set_id(), 10); - } + // Verify the update was applied + let set_1 = registry.peer_set(1).await.unwrap(); + assert_eq!(set_1.len(), 3); + assert!(set_1.iter().any(|p| p == &new_participant)); - #[test] - fn test_remove_participant_view_selection() { - let registry = create_test_registry(3); - let original_participants = registry.participants(0).unwrap().clone(); - let participant_to_remove = original_participants[1].clone(); - - // Remove participant at view 2 - registry.update_registry(2, &[], &[participant_to_remove.clone()]); - - // Views 0-1 should still have original participants - assert_eq!(registry.participants(0).unwrap().len(), 3); - assert_eq!(registry.participants(1).unwrap().len(), 3); - assert!( - registry - .participants(0) - .unwrap() - .contains(&participant_to_remove) - ); - assert!( - registry - .participants(1) - .unwrap() - .contains(&participant_to_remove) - ); - - // View 2+ should have participant removed - assert_eq!(registry.participants(2).unwrap().len(), 2); - assert_eq!(registry.participants(10).unwrap().len(), 2); - assert!( - !registry - .participants(2) - .unwrap() - .contains(&participant_to_remove) - ); - assert!( - !registry - .participants(10) - .unwrap() - .contains(&participant_to_remove) - ); - } + // Verify subscribers received the notification + let notification = rx.next().await; + assert!(notification.is_some()); - #[test] - fn test_update_registry_add_and_remove_combined() { - let registry = create_test_registry(3); - let original_participants = registry.participants(0).unwrap().clone(); - - // Create new participants to add and remove existing ones - let new_participant_a = crate::PrivateKey::from_seed(200).public_key(); - let new_participant_b = crate::PrivateKey::from_seed(201).public_key(); - let participant_to_remove = original_participants[0].clone(); - - // Add two participants and remove one in a single operation - registry.update_registry( - 1, - &[new_participant_a.clone(), new_participant_b.clone()], - &[participant_to_remove.clone()], - ); - - // Verify the result - let view_1_participants = registry.participants(1).unwrap(); - assert_eq!(view_1_participants.len(), 4); // 3 - 1 + 2 = 4 - assert!(view_1_participants.contains(&new_participant_a)); - assert!(view_1_participants.contains(&new_participant_b)); - assert!(!view_1_participants.contains(&participant_to_remove)); - - // Original view should remain unchanged - let view_0_participants = registry.participants(0).unwrap(); - assert_eq!(view_0_participants.len(), 3); - assert!(view_0_participants.contains(&participant_to_remove)); + let (id, old_set, new_set) = notification.unwrap(); + assert_eq!(id, 1); + assert_eq!(old_set, set_0); + assert_eq!(new_set, set_1); + }); } } + From 5a58921f1737f0f37b85e7ea35952e9077d10532 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Sat, 1 Nov 2025 05:14:32 +0800 Subject: [PATCH 18/81] feat: update block and header --- types/src/block.rs | 20 ++++++++--------- types/src/header.rs | 54 +++++++++++++++++++++++++++++++++++---------- 2 files changed, 52 insertions(+), 22 deletions(-) diff --git a/types/src/block.rs b/types/src/block.rs index bcf0b518..7a461bf8 100644 --- a/types/src/block.rs +++ b/types/src/block.rs @@ -1,4 +1,4 @@ -use crate::{Header, PublicKey, Signature}; +use crate::{Header, PublicKey}; use alloy_consensus::{Block as AlloyBlock, TxEnvelope}; use alloy_primitives::{Bytes as AlloyBytes, U256}; use alloy_rpc_types_engine::ExecutionPayloadV3; @@ -8,7 +8,7 @@ use commonware_codec::{EncodeSize, Error, Read, ReadExt as _, Write}; use commonware_consensus::Block as Bl; use commonware_consensus::{ Viewable, - simplex::types::{Finalization, Notarization}, + simplex::{signing_scheme::ed25519::Scheme, types::{Finalization, Notarization}}, }; use commonware_cryptography::{Committable, Digestible, Hasher, Sha256, sha256::Digest}; use ssz::Encode as _; @@ -183,7 +183,7 @@ impl Bl for Block { impl Viewable for Block { type View = u64; - fn view(&self) -> commonware_consensus::simplex::types::View { + fn view(&self) -> commonware_consensus::types::View { self.header.view } } @@ -283,12 +283,12 @@ impl Committable for Block { #[derive(Clone, Debug, PartialEq, Eq)] pub struct Notarized { - pub proof: Notarization, + pub proof: Notarization, pub block: Block, } impl Notarized { - pub fn new(proof: Notarization, block: Block) -> Self { + pub fn new(proof: Notarization, block: Block) -> Self { Self { proof, block } } } @@ -304,7 +304,7 @@ impl Read for Notarized { type Cfg = (); fn read_cfg(buf: &mut impl Buf, _: &Self::Cfg) -> Result { - let proof = Notarization::::read_cfg(buf, &buf.remaining())?; // todo: get a test on this to make sure buf.remaining is safe + let proof = Notarization::::read_cfg(buf, &buf.remaining())?; // todo: get a test on this to make sure buf.remaining is safe let block = Block::read(buf)?; // Ensure the proof is for the block @@ -326,12 +326,12 @@ impl EncodeSize for Notarized { #[derive(Clone, Debug, PartialEq, Eq)] pub struct Finalized { - pub proof: Finalization, + pub proof: Finalization, pub block: Block, } impl Finalized { - pub fn new(proof: Finalization, block: Block) -> Self { + pub fn new(proof: Finalization, block: Block) -> Self { Self { proof, block } } } @@ -347,7 +347,7 @@ impl Read for Finalized { type Cfg = (); fn read_cfg(buf: &mut impl Buf, _: &Self::Cfg) -> Result { - let proof = Finalization::::read_cfg(buf, &buf.remaining())?; + let proof = Finalization::::read_cfg(buf, &buf.remaining())?; let block = Block::read(buf)?; // Ensure the proof is for the block @@ -370,7 +370,7 @@ impl EncodeSize for Finalized { #[derive(Clone, Debug, PartialEq, Eq)] pub struct BlockEnvelope { pub block: Block, - pub finalized: Option>, + pub finalized: Option>, } #[cfg(test)] diff --git a/types/src/header.rs b/types/src/header.rs index 0c45ab11..81f11e3f 100644 --- a/types/src/header.rs +++ b/types/src/header.rs @@ -1,10 +1,10 @@ use std::ops::Deref as _; -use crate::{PublicKey, Signature}; +use crate::PublicKey; use alloy_primitives::U256; use bytes::{Buf, BufMut}; use commonware_codec::{EncodeSize, Error, Read, Write}; -use commonware_consensus::simplex::types::Finalization; +use commonware_consensus::simplex::{signing_scheme::ed25519::Scheme, types::Finalization}; use commonware_cryptography::{Hasher, Sha256, sha256::Digest}; use ssz::Encode as _; @@ -258,11 +258,11 @@ impl Read for Header { #[derive(Clone, Debug, PartialEq, Eq)] pub struct FinalizedHeader { pub header: Header, - pub finalized: Finalization, + pub finalized: Finalization, } impl FinalizedHeader { - pub fn new(header: Header, finalized: Finalization) -> Self { + pub fn new(header: Header, finalized: Finalization) -> Self { Self { header, finalized } } } @@ -365,7 +365,9 @@ mod test { use super::*; use alloy_primitives::{U256, hex}; use commonware_codec::{DecodeExt as _, Encode as _}; - use commonware_consensus::simplex::types::{Finalization, Proposal}; + use commonware_consensus::{simplex::{signing_scheme::{ed25519::Certificate, utils::Signers}, types::{Finalization, Proposal}}, types::Round}; + use commonware_cryptography::ed25519::PrivateKey; + use commonware_cryptography::{PrivateKeyExt, Signer}; use ssz::Decode; fn create_test_public_key(seed: u8) -> PublicKey { @@ -432,14 +434,24 @@ mod test { ); let proposal = Proposal { - view: header.view, + round: Round::new(0, header.view), parent: header.height, payload: header.digest, }; + // Create valid signatures for the certificate + let signer1 = PrivateKey::from_seed(0); + let sig1 = signer1.sign(None, header.digest.as_ref()); + + let signer2 = PrivateKey::from_seed(1); + let sig2 = signer2.sign(None, header.digest.as_ref()); + let finalized = Finalization { proposal, - signatures: Vec::new(), + certificate: Certificate { + signers: Signers::from(3, [0, 2]), // 2 signers out of 3 participants + signatures: vec![sig1, sig2], + }, }; let finalized_header = FinalizedHeader::new(header.clone(), finalized); @@ -469,15 +481,29 @@ mod test { ); // Create a finalization with wrong payload + let dummy_digest = [99u8; 32]; let wrong_proposal = Proposal { - view: header.view, + round: Round::new(0, header.view), parent: header.height, - payload: [99u8; 32].into(), // Wrong digest + payload: dummy_digest.into(), // Wrong digest }; + // Create some dummy signatures for the certificate + let signer1 = PrivateKey::from_seed(0); + let sig1 = signer1.sign(None, &dummy_digest); + + let signer2 = PrivateKey::from_seed(1); + let sig2 = signer2.sign(None, &dummy_digest); + + let signer3 = PrivateKey::from_seed(2); + let sig3 = signer3.sign(None, &dummy_digest); + let wrong_finalized = Finalization { proposal: wrong_proposal, - signatures: Vec::new(), + certificate: Certificate { + signers: Signers::from(5, [0, 2, 4]), // 3 signers out of 5 participants + signatures: vec![sig1, sig2, sig3], + }, }; let finalized_header = FinalizedHeader { @@ -489,6 +515,7 @@ mod test { let result = FinalizedHeader::from_ssz_bytes(&encoded); assert!(result.is_err()); + println!("{:?}", result); assert!( matches!(result.unwrap_err(), ssz::DecodeError::BytesInvalid(msg) if msg.contains("Finalization payload does not match header digest")) ); @@ -512,14 +539,17 @@ mod test { ); let proposal = Proposal { - view: header.view, + round: Round::new(0, header.view), parent: header.height, payload: header.digest, }; let finalized = Finalization { proposal, - signatures: Vec::new(), + certificate: Certificate { + signers: Signers::from(0, []), + signatures: Vec::new(), + }, }; let finalized_header = FinalizedHeader::new(header, finalized); From 2895b30ce1e033c82d1e731cd53321e935f15fad Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Sat, 1 Nov 2025 05:14:54 +0800 Subject: [PATCH 19/81] feat: update checkpoint --- types/src/checkpoint.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/types/src/checkpoint.rs b/types/src/checkpoint.rs index a4f8db2c..7751d121 100644 --- a/types/src/checkpoint.rs +++ b/types/src/checkpoint.rs @@ -145,6 +145,7 @@ mod tests { #[test] fn test_checkpoint_ssz_encode_decode_empty() { let state = ConsensusState { + epoch: 0, latest_height: 10, next_withdrawal_index: 100, deposit_queue: VecDeque::new(), @@ -237,6 +238,7 @@ mod tests { validator_accounts.insert([11u8; 32], validator_account2); let state = ConsensusState { + epoch: 0, latest_height: 1000, next_withdrawal_index: 200, deposit_queue, @@ -269,6 +271,7 @@ mod tests { use std::collections::{HashMap, VecDeque}; let state = ConsensusState { + epoch: 0, latest_height: 42, next_withdrawal_index: 99, deposit_queue: VecDeque::new(), @@ -368,6 +371,7 @@ mod tests { validator_accounts.insert([11u8; 32], validator_account2); let state = ConsensusState { + epoch: 0, latest_height: 2000, next_withdrawal_index: 300, deposit_queue, @@ -405,6 +409,7 @@ mod tests { use std::collections::{HashMap, VecDeque}; let state = ConsensusState { + epoch: 0, latest_height: 42, next_withdrawal_index: 99, deposit_queue: VecDeque::new(), @@ -448,6 +453,7 @@ mod tests { use std::collections::{HashMap, VecDeque}; let original_state = ConsensusState { + epoch: 0, latest_height: 42, next_withdrawal_index: 99, deposit_queue: VecDeque::new(), @@ -462,6 +468,7 @@ mod tests { let checkpoint = Checkpoint::new(&original_state); let converted_state = ConsensusState::try_from(&checkpoint).unwrap(); + assert_eq!(converted_state.epoch, original_state.epoch); assert_eq!(converted_state.latest_height, original_state.latest_height); assert_eq!( converted_state.next_withdrawal_index, @@ -486,6 +493,7 @@ mod tests { use std::collections::{HashMap, VecDeque}; let original_state = ConsensusState { + epoch: 0, latest_height: 42, next_withdrawal_index: 99, deposit_queue: VecDeque::new(), @@ -561,6 +569,7 @@ mod tests { validator_accounts.insert([10u8; 32], validator_account1); let original_state = ConsensusState { + epoch: 0, latest_height: 1000, next_withdrawal_index: 200, deposit_queue, @@ -576,6 +585,7 @@ mod tests { let converted_state = ConsensusState::try_from(&checkpoint).unwrap(); // Verify all fields match + assert_eq!(converted_state.epoch, original_state.epoch); assert_eq!(converted_state.latest_height, original_state.latest_height); assert_eq!( converted_state.next_withdrawal_index, From 453f675a614f718d187e9a8a227df1cc944c88b2 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Sat, 1 Nov 2025 05:15:06 +0800 Subject: [PATCH 20/81] feat: update network oracle --- types/src/network_oracle.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/types/src/network_oracle.rs b/types/src/network_oracle.rs index 8ad0d39d..f7d58151 100644 --- a/types/src/network_oracle.rs +++ b/types/src/network_oracle.rs @@ -1,23 +1,23 @@ use commonware_cryptography::PublicKey; -use commonware_p2p::authenticated::discovery::Oracle; -use commonware_runtime::{Metrics, Spawner}; +use commonware_p2p::{Manager, authenticated::discovery::Oracle}; +use commonware_utils::set::Ordered; pub trait NetworkOracle: Send + Sync + 'static { fn register(&mut self, index: u64, peers: Vec) -> impl Future + Send; } -pub struct DiscoveryOracle { - oracle: Oracle, +pub struct DiscoveryOracle { + oracle: Oracle, } -impl DiscoveryOracle { - pub fn new(oracle: Oracle) -> Self { +impl DiscoveryOracle { + pub fn new(oracle: Oracle) -> Self { Self { oracle } } } -impl NetworkOracle for DiscoveryOracle { +impl NetworkOracle for DiscoveryOracle { async fn register(&mut self, index: u64, peers: Vec) { - self.oracle.register(index, peers).await; + self.oracle.update(index, Ordered::from(peers)).await; } } From 51e5e63af0d7abef4b355f6e7bc909d39626f817 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Tue, 4 Nov 2025 18:21:54 -0500 Subject: [PATCH 21/81] feat: switch to BLS multisig and make generic over signer --- types/src/block.rs | 92 ++++++++++++++++++++++++++-------------------- 1 file changed, 52 insertions(+), 40 deletions(-) diff --git a/types/src/block.rs b/types/src/block.rs index 7a461bf8..57ae65ca 100644 --- a/types/src/block.rs +++ b/types/src/block.rs @@ -1,3 +1,4 @@ +use std::marker::PhantomData; use crate::{Header, PublicKey}; use alloy_consensus::{Block as AlloyBlock, TxEnvelope}; use alloy_primitives::{Bytes as AlloyBytes, U256}; @@ -5,22 +6,25 @@ use alloy_rpc_types_engine::ExecutionPayloadV3; use anyhow::{Result, anyhow}; use bytes::{Buf, BufMut}; use commonware_codec::{EncodeSize, Error, Read, ReadExt as _, Write}; -use commonware_consensus::Block as Bl; +use commonware_consensus::Block as ConsensusBlock; use commonware_consensus::{ Viewable, - simplex::{signing_scheme::ed25519::Scheme, types::{Finalization, Notarization}}, + simplex::{signing_scheme::bls12381_multisig::Scheme, types::{Finalization, Notarization}}, }; -use commonware_cryptography::{Committable, Digestible, Hasher, Sha256, sha256::Digest}; +use commonware_cryptography::{Committable, Digestible, Hasher, Sha256, sha256::Digest, Signer, ed25519}; +use commonware_cryptography::bls12381::primitives::variant::{MinPk, Variant}; use ssz::Encode as _; #[derive(Clone, Debug, PartialEq, Eq)] -pub struct Block { +pub struct Block { pub header: Header, pub payload: ExecutionPayloadV3, pub execution_requests: Vec, + pub _signer_type: PhantomData, + pub _variant: PhantomData, } -impl Block { +impl Block { pub fn eth_block_hash(&self) -> [u8; 32] { // if genesis return your own digest if self.header.height == 0 { @@ -86,6 +90,8 @@ impl Block { header, payload, execution_requests, + _signer_type: PhantomData, + _variant: PhantomData, } } @@ -118,6 +124,8 @@ impl Block { header, payload, execution_requests, + _signer_type: PhantomData, + _variant: PhantomData, }) } @@ -146,6 +154,8 @@ impl Block { header, payload: ExecutionPayloadV3::from_block_slow(&AlloyBlock::::default()), execution_requests: Default::default(), + _signer_type: PhantomData, + _variant: PhantomData, } } @@ -170,7 +180,7 @@ impl Block { } } -impl Bl for Block { +impl ConsensusBlock for Block { fn height(&self) -> u64 { self.header.height } @@ -180,7 +190,7 @@ impl Bl for Block { } } -impl Viewable for Block { +impl Viewable for Block { type View = u64; fn view(&self) -> commonware_consensus::types::View { @@ -188,7 +198,7 @@ impl Viewable for Block { } } -impl ssz::Encode for Block { +impl ssz::Encode for Block { fn is_ssz_fixed_len() -> bool { false } @@ -213,7 +223,7 @@ impl ssz::Encode for Block { } } -impl ssz::Decode for Block { +impl ssz::Decode for Block { fn is_ssz_fixed_len() -> bool { false } @@ -235,13 +245,13 @@ impl ssz::Decode for Block { } } -impl EncodeSize for Block { +impl EncodeSize for Block { fn encode_size(&self) -> usize { self.ssz_bytes_len() + ssz::BYTES_PER_LENGTH_OFFSET } } -impl Write for Block { +impl Write for Block { fn write(&self, buf: &mut impl BufMut) { let ssz_bytes = &*self.as_ssz_bytes(); let bytes_len = ssz_bytes.len() as u32; @@ -251,7 +261,7 @@ impl Write for Block { } } -impl Read for Block { +impl Read for Block { type Cfg = (); fn read_cfg(buf: &mut impl Buf, _cfg: &Self::Cfg) -> Result { @@ -265,7 +275,7 @@ impl Read for Block { } } -impl Digestible for Block { +impl Digestible for Block { type Digest = Digest; fn digest(&self) -> Digest { @@ -273,7 +283,7 @@ impl Digestible for Block { } } -impl Committable for Block { +impl Committable for Block { type Commitment = Digest; fn commitment(&self) -> Digest { @@ -282,29 +292,29 @@ impl Committable for Block { } #[derive(Clone, Debug, PartialEq, Eq)] -pub struct Notarized { - pub proof: Notarization, - pub block: Block, +pub struct Notarized { + pub proof: Notarization, Digest>, + pub block: Block, } -impl Notarized { - pub fn new(proof: Notarization, block: Block) -> Self { +impl Notarized { + pub fn new(proof: Notarization, Digest>, block: Block) -> Self { Self { proof, block } } } -impl Write for Notarized { +impl Write for Notarized { fn write(&self, buf: &mut impl BufMut) { self.proof.write(buf); self.block.write(buf); } } -impl Read for Notarized { +impl Read for Notarized { type Cfg = (); fn read_cfg(buf: &mut impl Buf, _: &Self::Cfg) -> Result { - let proof = Notarization::::read_cfg(buf, &buf.remaining())?; // todo: get a test on this to make sure buf.remaining is safe + let proof = Notarization::, Digest>::read_cfg(buf, &buf.remaining())?; // todo: get a test on this to make sure buf.remaining is safe let block = Block::read(buf)?; // Ensure the proof is for the block @@ -318,36 +328,36 @@ impl Read for Notarized { } } -impl EncodeSize for Notarized { +impl EncodeSize for Notarized { fn encode_size(&self) -> usize { self.proof.encode_size() + self.block.encode_size() } } #[derive(Clone, Debug, PartialEq, Eq)] -pub struct Finalized { - pub proof: Finalization, - pub block: Block, +pub struct Finalized { + pub proof: Finalization, Digest>, + pub block: Block, } -impl Finalized { - pub fn new(proof: Finalization, block: Block) -> Self { +impl Finalized { + pub fn new(proof: Finalization, Digest>, block: Block) -> Self { Self { proof, block } } } -impl Write for Finalized { +impl Write for Finalized { fn write(&self, buf: &mut impl BufMut) { self.proof.write(buf); self.block.write(buf); } } -impl Read for Finalized { +impl Read for Finalized { type Cfg = (); fn read_cfg(buf: &mut impl Buf, _: &Self::Cfg) -> Result { - let proof = Finalization::::read_cfg(buf, &buf.remaining())?; + let proof = Finalization::, Digest>::read_cfg(buf, &buf.remaining())?; let block = Block::read(buf)?; // Ensure the proof is for the block @@ -361,16 +371,16 @@ impl Read for Finalized { } } -impl EncodeSize for Finalized { +impl EncodeSize for Finalized { fn encode_size(&self) -> usize { self.proof.encode_size() + self.block.encode_size() } } #[derive(Clone, Debug, PartialEq, Eq)] -pub struct BlockEnvelope { - pub block: Block, - pub finalized: Option>, +pub struct BlockEnvelope { + pub block: Block, + pub finalized: Option, Digest>>, } #[cfg(test)] @@ -379,6 +389,8 @@ mod test { use alloy_primitives::{Bytes as AlloyBytes, U256, hex}; use alloy_rpc_types_engine::{ExecutionPayloadV1, ExecutionPayloadV2}; use commonware_codec::{DecodeExt as _, Encode as _}; + use commonware_cryptography::ed25519; + use commonware_cryptography::bls12381::primitives::variant::MinPk; fn create_test_public_key(seed: u8) -> PublicKey { let test_keys = [ @@ -435,7 +447,7 @@ mod test { }; let (added_validators, removed_validators) = create_test_validators(); - let block = Block::compute_digest( + let block = Block::::compute_digest( [27u8; 32].into(), 27, 2727, @@ -499,23 +511,23 @@ mod test { let encoded = block.encode(); - let decoded = Block::decode(encoded).unwrap(); + let decoded = Block::::decode(encoded).unwrap(); assert_eq!(block, decoded); } #[test] fn test_serialization() { - let block = Block::genesis([0; 32]); + let block = Block::::genesis([0; 32]); let bytes = block.encode(); - Block::decode(bytes).unwrap(); + Block::::decode(bytes).unwrap(); } #[test] fn test_block_encode_size() { - let block = Block::genesis([0; 32]); + let block = Block::::genesis([0; 32]); let ssz_len = block.ssz_bytes_len(); let encode_len = block.encode_size(); From c7d7f6f007c545829988198e58fb34311cc24b26 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Tue, 4 Nov 2025 19:08:40 -0500 Subject: [PATCH 22/81] feat: add orchestrator --- orchestrator/Cargo.toml | 28 +++ orchestrator/src/actor.rs | 383 ++++++++++++++++++++++++++++++++++++ orchestrator/src/ingress.rs | 39 ++++ orchestrator/src/lib.rs | 7 + 4 files changed, 457 insertions(+) create mode 100644 orchestrator/Cargo.toml create mode 100644 orchestrator/src/actor.rs create mode 100644 orchestrator/src/ingress.rs create mode 100644 orchestrator/src/lib.rs diff --git a/orchestrator/Cargo.toml b/orchestrator/Cargo.toml new file mode 100644 index 00000000..cb2ecb96 --- /dev/null +++ b/orchestrator/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "summit-orchestrator" +version.workspace = true +edition.workspace = true + +[dependencies] +summit-types.workspace = true +summit-syncer.workspace = true + +commonware-broadcast.workspace = true +commonware-codec.workspace = true +commonware-consensus.workspace = true +commonware-cryptography.workspace = true +commonware-macros.workspace = true +commonware-resolver.workspace = true +commonware-runtime.workspace = true +commonware-storage.workspace = true +commonware-p2p.workspace = true +commonware-utils.workspace = true + +bytes.workspace = true +futures.workspace = true +governor.workspace = true +rand.workspace = true +tokio-util.workspace = true +tracing.workspace = true + + diff --git a/orchestrator/src/actor.rs b/orchestrator/src/actor.rs new file mode 100644 index 00000000..560cb10f --- /dev/null +++ b/orchestrator/src/actor.rs @@ -0,0 +1,383 @@ +//! Consensus engine orchestrator for epoch transitions. +use summit_types::{Block, scheme::SummitSchemeProvider, Digest}; +use crate::{Mailbox, Message}; + +use commonware_codec::{varint::UInt, DecodeExt, Encode}; +use commonware_consensus::{ + simplex::{ + self, + types::{Context, Voter}, + }, + types::Epoch, + utils::last_block_in_epoch, + Automaton, Relay, +}; +use commonware_cryptography::{bls12381::primitives::variant::Variant, Signer}; +use commonware_macros::select; +use commonware_p2p::{ + utils::mux::{Builder, MuxHandle, Muxer}, + Blocker, Receiver, Recipients, Sender, +}; +use commonware_runtime::{ + buffer::PoolRef, spawn_cell, Clock, ContextCell, Handle, Metrics, Network, Spawner, Storage, +}; +use commonware_utils::{NZUsize, NZU32}; +use futures::{channel::mpsc, StreamExt}; +use governor::{clock::Clock as GClock, Quota, RateLimiter}; +use rand::{CryptoRng, Rng}; +use std::{collections::BTreeMap, time::Duration}; +use tracing::{debug, info, warn}; +use summit_types::scheme::{EpochSchemeProvider, MultisigScheme}; + +/// Configuration for the orchestrator. +pub struct Config +where + B: Blocker, + V: Variant, + C: Signer, + A: Automaton, Digest = Digest> + + Relay, +{ + pub oracle: B, + pub application: A, + pub scheme_provider: SummitSchemeProvider, + pub syncer_mailbox: summit_syncer::Mailbox, Block>, + + pub namespace: Vec, + pub muxer_size: usize, + pub mailbox_size: usize, + pub rate_limit: governor::Quota, + + pub blocks_per_epoch: u64, + + // Partition prefix used for orchestrator metadata persistence + pub partition_prefix: String, +} + +pub struct Actor +where + E: Spawner + Metrics + Rng + CryptoRng + Clock + GClock + Storage + Network, + B: Blocker, + V: Variant, + C: Signer, + A: Automaton, Digest = Digest> + + Relay, +{ + context: ContextCell, + mailbox: mpsc::Receiver>, + application: A, + + oracle: B, + syncer_mailbox: summit_syncer::Mailbox, Block>, + scheme_provider: SummitSchemeProvider, + + namespace: Vec, + muxer_size: usize, + partition_prefix: String, + rate_limit: governor::Quota, + pool_ref: PoolRef, + blocks_per_epoch: u64, +} + +impl Actor +where + E: Spawner + Metrics + Rng + CryptoRng + Clock + GClock + Storage + Network, + B: Blocker, + V: Variant, + C: Signer, + A: Automaton, Digest = Digest> + + Relay, +{ + pub fn new(context: E, config: Config) -> (Self, Mailbox) { + let (sender, mailbox) = mpsc::channel(config.mailbox_size); + let pool_ref = PoolRef::new(NZUsize!(16_384), NZUsize!(10_000)); + + ( + Self { + context: ContextCell::new(context), + mailbox, + application: config.application, + oracle: config.oracle, + syncer_mailbox: config.syncer_mailbox, + scheme_provider: config.scheme_provider, + namespace: config.namespace, + muxer_size: config.muxer_size, + partition_prefix: config.partition_prefix, + rate_limit: config.rate_limit, + pool_ref, + blocks_per_epoch: config.blocks_per_epoch, + }, + Mailbox::new(sender), + ) + } + + pub fn start( + mut self, + pending: ( + impl Sender, + impl Receiver, + ), + recovered: ( + impl Sender, + impl Receiver, + ), + resolver: ( + impl Sender, + impl Receiver, + ), + orchestrator: ( + impl Sender, + impl Receiver, + ), + ) -> Handle<()> { + spawn_cell!( + self.context, + self.run(pending, recovered, resolver, orchestrator).await + ) + } + + async fn run( + mut self, + (pending_sender, pending_receiver): ( + impl Sender, + impl Receiver, + ), + (recovered_sender, recovered_receiver): ( + impl Sender, + impl Receiver, + ), + (resolver_sender, resolver_receiver): ( + impl Sender, + impl Receiver, + ), + (mut orchestrator_sender, mut orchestrator_receiver): ( + impl Sender, + impl Receiver, + ), + ) { + // Start muxers for each physical channel used by consensus + let (mux, mut pending_mux, mut pending_backup) = Muxer::builder( + self.context.with_label("pending_mux"), + pending_sender, + pending_receiver, + self.muxer_size, + ) + .with_backup() + .build(); + mux.start(); + let (mux, mut recovered_mux, mut recovered_global_sender) = Muxer::builder( + self.context.with_label("recovered_mux"), + recovered_sender, + recovered_receiver, + self.muxer_size, + ) + .with_global_sender() + .build(); + mux.start(); + let (mux, mut resolver_mux) = Muxer::new( + self.context.with_label("resolver_mux"), + resolver_sender, + resolver_receiver, + self.muxer_size, + ); + mux.start(); + + // Create rate limiter for orchestrators + let rate_limiter = RateLimiter::hashmap_with_clock(self.rate_limit, &self.context); + + // Wait for instructions to transition epochs. + let mut engines = BTreeMap::new(); + loop { + select! { + message = pending_backup.next() => { + // If a message is received in an unregistered sub-channel in the pending network, + // attempt to forward the orchestrator for the epoch. + let Some((their_epoch, (from, _))) = message else { + warn!("pending mux backup channel closed, shutting down orchestrator"); + break; + }; + let Some(our_epoch) = engines.keys().last().copied() else { + debug!(their_epoch, ?from, "received message from unregistered epoch with no known epochs"); + continue; + }; + if their_epoch <= our_epoch { + debug!(their_epoch, our_epoch, ?from, "received message from past epoch"); + continue; + } + + // If we're not in the committee of the latest epoch we know about and we observe another + // participant that is ahead of us, send a message on the orchestrator channel to prompt + // them to send us the finalization of the epoch boundary block for our latest known epoch. + if rate_limiter.check_key(&from).is_err() { + continue; + } + let boundary_height = last_block_in_epoch(self.blocks_per_epoch, our_epoch); + if self.syncer_mailbox.get_finalization(boundary_height).await.is_some() { + // Only request the orchestrator if we don't already have it. + continue; + }; + debug!( + their_epoch, + ?from, + "received backup message from future epoch, requesting orchestrator" + ); + + // Send the request to the orchestrator. This operation is best-effort. + if orchestrator_sender.send( + Recipients::One(from), + UInt(our_epoch).encode().freeze(), + true + ).await.is_err() { + warn!("failed to send orchestrator request, shutting down orchestrator"); + break; + } + }, + message = orchestrator_receiver.recv() => { + let Ok((from, bytes)) = message else { + warn!("orchestrator channel closed, shutting down orchestrator"); + break; + }; + let epoch = match UInt::::decode(bytes.as_ref()) { + Ok(epoch) => epoch.0, + Err(err) => { + debug!(?err, ?from, "failed to decode epoch from orchestrator request"); + self.oracle.block(from).await; + continue; + } + }; + + // Fetch the finalization certificate for the last block within the subchannel's epoch. + // If the node is state synced, marshal may not have the finalization locally, and the + // peer will need to fetch it from another node on the network. + let boundary_height = last_block_in_epoch(self.blocks_per_epoch, epoch); + let Some(finalization) = self.syncer_mailbox.get_finalization(boundary_height).await else { + debug!(epoch, ?from, "missing finalization for old epoch"); + continue; + }; + debug!( + epoch, + boundary_height, + ?from, + "received message on pending network from old epoch. forwarding orchestrator" + ); + + // Forward the finalization to the sender. This operation is best-effort. + // + // TODO (#2032): Send back to orchestrator for direct insertion into marshal. + let message = Voter::, Digest>::Finalization(finalization); + if recovered_global_sender + .send( + epoch, + Recipients::One(from), + message.encode().freeze(), + false, + ) + .await.is_err() { + warn!("failed to forward finalization, shutting down orchestrator"); + break; + } + }, + transition = self.mailbox.next() => { + let Some(transition) = transition else { + warn!("mailbox closed, shutting down orchestrator"); + break; + }; + + match transition { + Message::Enter(transition) => { + // If the epoch is already in the map, ignore. + if engines.contains_key(&transition.epoch) { + warn!(epoch = transition.epoch, "entered existing epoch"); + continue; + } + + // Register the new signing scheme with the scheme provider. + let scheme = self.scheme_provider.scheme_for_epoch(&transition); + assert!(self.scheme_provider.register(transition.epoch, scheme.clone())); + + // Enter the new epoch. + let engine = self + .enter_epoch( + transition.epoch, + scheme, + &mut pending_mux, + &mut recovered_mux, + &mut resolver_mux, + ) + .await; + engines.insert(transition.epoch, engine); + + info!(epoch = transition.epoch, "entered epoch"); + } + Message::Exit(epoch) => { + // Remove the engine and abort it. + let Some(engine) = engines.remove(&epoch) else { + warn!(epoch, "exited non-existent epoch"); + continue; + }; + engine.abort(); + + // Unregister the signing scheme for the epoch. + assert!(self.scheme_provider.unregister(&epoch)); + + info!(epoch, "exited epoch"); + } + } + }, + } + } + } + + async fn enter_epoch( + &mut self, + epoch: Epoch, + scheme: MultisigScheme, + pending_mux: &mut MuxHandle< + impl Sender, + impl Receiver, + >, + recovered_mux: &mut MuxHandle< + impl Sender, + impl Receiver, + >, + resolver_mux: &mut MuxHandle< + impl Sender, + impl Receiver, + >, + ) -> Handle<()> { + // Start the new engine + let engine = simplex::Engine::new( + self.context.with_label("consensus_engine"), + simplex::Config { + scheme, + blocker: self.oracle.clone(), + automaton: self.application.clone(), + relay: self.application.clone(), + reporter: self.syncer_mailbox.clone(), + partition: format!("{}_consensus_{}", self.partition_prefix, epoch), + mailbox_size: 1024, + epoch, + namespace: self.namespace.clone(), + replay_buffer: NZUsize!(1024 * 1024), + write_buffer: NZUsize!(1024 * 1024), + leader_timeout: Duration::from_secs(1), + notarization_timeout: Duration::from_secs(2), + nullify_retry: Duration::from_secs(10), + fetch_timeout: Duration::from_secs(1), + activity_timeout: 256, + skip_timeout: 10, + max_fetch_count: 32, + fetch_concurrent: 2, + fetch_rate_per_peer: Quota::per_second(NZU32!(1)), + buffer_pool: self.pool_ref.clone(), + }, + ); + + // Create epoch-specific subchannels + let pending_sc = pending_mux.register(epoch).await.unwrap(); + let recovered_sc = recovered_mux.register(epoch).await.unwrap(); + let resolver_sc = resolver_mux.register(epoch).await.unwrap(); + + engine.start(pending_sc, recovered_sc, resolver_sc) + } +} diff --git a/orchestrator/src/ingress.rs b/orchestrator/src/ingress.rs new file mode 100644 index 00000000..127c96c1 --- /dev/null +++ b/orchestrator/src/ingress.rs @@ -0,0 +1,39 @@ +//! Inbound communication channel for epoch transitions. + +use commonware_consensus::{types::Epoch, Reporter}; +use commonware_cryptography::{ + bls12381::primitives::variant::Variant, + PublicKey, +}; +use futures::{channel::mpsc, SinkExt}; +use summit_types::scheme::EpochTransition; + +/// Messages that can be sent to the orchestrator. +pub enum Message { + Enter(EpochTransition), + Exit(Epoch), +} + +/// Inbound communication channel for epoch transitions. +#[derive(Debug, Clone)] +pub struct Mailbox { + sender: mpsc::Sender>, +} + +impl Mailbox { + /// Create a new [Mailbox]. + pub fn new(sender: mpsc::Sender>) -> Self { + Self { sender } + } +} + +impl Reporter for Mailbox { + type Activity = Message; + + async fn report(&mut self, activity: Self::Activity) { + self.sender + .send(activity) + .await + .expect("failed to send epoch transition") + } +} diff --git a/orchestrator/src/lib.rs b/orchestrator/src/lib.rs new file mode 100644 index 00000000..e6a90340 --- /dev/null +++ b/orchestrator/src/lib.rs @@ -0,0 +1,7 @@ +//! Consensus engine orchestrator for epoch transitions. + +mod actor; +pub use actor::{Actor, Config}; + +mod ingress; +pub use ingress::{Mailbox, Message}; From 9b972274a499148c82d06943e5ec9891417bfeeb Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Wed, 5 Nov 2025 11:10:41 -0500 Subject: [PATCH 23/81] feat: add keystore --- types/src/keystore.rs | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 types/src/keystore.rs diff --git a/types/src/keystore.rs b/types/src/keystore.rs new file mode 100644 index 00000000..6cae28fd --- /dev/null +++ b/types/src/keystore.rs @@ -0,0 +1,9 @@ +use commonware_cryptography::bls12381::PrivateKey; +use commonware_cryptography::Signer; +use zeroize::{Zeroize, ZeroizeOnDrop}; + +#[derive(Zeroize, ZeroizeOnDrop)] +pub struct KeyStore { + pub node_key: C, + pub consensus_key: PrivateKey, +} \ No newline at end of file From cf2744d44b80b77bc6c325adee532265e55b0dd4 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Wed, 5 Nov 2025 11:11:33 -0500 Subject: [PATCH 24/81] feat: refactor CLI to include BLS key --- node/src/args.rs | 26 ++++++----- node/src/config.rs | 43 +++++++++++------- node/src/keys.rs | 107 +++++++++++++++++++++++++++++---------------- 3 files changed, 109 insertions(+), 67 deletions(-) diff --git a/node/src/args.rs b/node/src/args.rs index 8672d005..29a8a294 100644 --- a/node/src/args.rs +++ b/node/src/args.rs @@ -1,7 +1,7 @@ use crate::{ config::{ BACKFILLER_CHANNEL, BROADCASTER_CHANNEL, EngineConfig, MESSAGE_BACKLOG, PENDING_CHANNEL, - RESOLVER_CHANNEL, expect_signer, + RESOLVER_CHANNEL, expect_key_store, }, engine::Engine, keys::KeySubCmd, @@ -73,9 +73,9 @@ pub enum Command { #[derive(Args, Debug, Clone)] pub struct RunFlags { - /// Path to your private key or where you want it generated - #[arg(long, default_value_t = DEFAULT_KEY_PATH.into())] - pub key_path: String, + /// Path to your keystore directory containing node_key.pem and consensus_key.pem + #[arg(long, default_value_t = "~/.seismic/consensus/keys".into())] + pub key_store_path: String, /// Path to the folder we will keep the consensus DB #[arg(long, default_value_t = DEFAULT_DB_FOLDER.into())] pub store_path: String, @@ -173,7 +173,8 @@ impl Command { }); let store_path = get_expanded_path(&flags.store_path).expect("Invalid store path"); - let signer = expect_signer(&flags.key_path); + let key_store = expect_key_store(&flags.key_store_path); + let signer = key_store.node_key; // Initialize runtime let cfg = tokio::Config::default() @@ -358,7 +359,7 @@ impl Command { let config = EngineConfig::get_engine_config( engine_client, oracle, - signer, + key_store, peers, flags.db_prefix.clone(), &genesis, @@ -393,12 +394,12 @@ impl Command { let engine = engine.start(pending, resolver, broadcaster, backfiller); // Start RPC server - let key_path = flags.key_path.clone(); + let key_store_path = flags.key_store_path.clone(); let rpc_port = flags.rpc_port; let stop_signal = context.stopped(); let rpc_handle = context.with_label("rpc").spawn(move |_context| async move { if let Err(e) = - start_rpc_server(finalizer_mailbox, key_path, rpc_port, stop_signal).await + start_rpc_server(finalizer_mailbox, key_store_path, rpc_port, stop_signal).await { error!("RPC server failed: {}", e); } @@ -418,7 +419,8 @@ pub fn run_node_with_runtime( checkpoint: Option, ) -> Handle<()> { context.spawn(async move |context| { - let signer = expect_signer(&flags.key_path); + let key_store = expect_key_store(&flags.key_store_path); + let signer = key_store.node_key; let (genesis_tx, genesis_rx) = oneshot::channel(); @@ -568,7 +570,7 @@ pub fn run_node_with_runtime( let config = EngineConfig::get_engine_config( engine_client, oracle, - signer, + key_store, peers, flags.db_prefix.clone(), &genesis, @@ -618,14 +620,14 @@ pub fn run_node_with_runtime( } // Start RPC server - let key_path = flags.key_path.clone(); + let key_store_path = flags.key_store_path.clone(); let rpc_port = flags.rpc_port; let stop_signal = context.stopped(); let rpc_handle = context .with_label("rpc_genesis") .spawn(move |_context| async move { if let Err(e) = - start_rpc_server(finalizer_mailbox, key_path, rpc_port, stop_signal).await + start_rpc_server(finalizer_mailbox, key_store_path, rpc_port, stop_signal).await { error!("RPC server failed: {}", e); } diff --git a/node/src/config.rs b/node/src/config.rs index a27f6d28..f5c0b0f8 100644 --- a/node/src/config.rs +++ b/node/src/config.rs @@ -1,12 +1,16 @@ use std::{num::NonZeroU32, time::Duration}; -use crate::keys::read_ed_key_from_path; +use crate::keys::read_keys_from_keystore; use anyhow::{Context, Result}; +use commonware_cryptography::bls12381::{self, primitives::group}; +use commonware_cryptography::bls12381::primitives::variant::Variant; +use commonware_cryptography::Signer; use commonware_utils::from_hex_formatted; use governor::Quota; use summit_types::consensus_state::ConsensusState; use summit_types::network_oracle::NetworkOracle; use summit_types::{EngineClient, Genesis, PrivateKey, PublicKey}; +use summit_types::keystore::KeyStore; /* DEFAULTS */ pub const PENDING_CHANNEL: u32 = 0; pub const RESOLVER_CHANNEL: u32 = 1; @@ -23,11 +27,11 @@ pub const MESSAGE_BACKLOG: usize = 16384; const BACKFILL_QUOTA: u32 = 10; // in seconds const FETCH_RATE_P2P: u32 = 128; // in seconds -pub struct EngineConfig> { +pub struct EngineConfig> { pub engine_client: C, pub partition_prefix: String, - pub signer: PrivateKey, - pub participants: Vec, + pub key_store: KeyStore, + //pub participants: Vec, pub mailbox_size: usize, pub backfill_quota: Quota, pub deque_size: usize, @@ -51,11 +55,11 @@ pub struct EngineConfig> { pub initial_state: ConsensusState, } -impl> EngineConfig { +impl> EngineConfig { pub fn get_engine_config( engine_client: C, oracle: O, - signer: PrivateKey, + key_store: KeyStore, participants: Vec, db_prefix: String, genesis: &Genesis, @@ -64,8 +68,8 @@ impl> EngineConfig { Ok(Self { engine_client, partition_prefix: db_prefix, - signer, - participants, + key_store, + //participants, oracle, mailbox_size: MAILBOX_SIZE, backfill_quota: Quota::per_second(NonZeroU32::new(BACKFILL_QUOTA).unwrap()), @@ -90,14 +94,19 @@ impl> EngineConfig { } } -pub(crate) fn load_signer(key_path: &str) -> anyhow::Result { - read_ed_key_from_path(key_path).context("failed to load signer key") +pub(crate) fn load_key_store(key_store_path: &str) -> Result> { + match read_keys_from_keystore(key_store_path).context("failed to load key store") { + Ok((node_key, consensus_key)) => { + Ok(KeyStore { node_key, consensus_key }) + } + Err(e) => Err(e) + } } -pub(crate) fn expect_signer(key_path: &str) -> PrivateKey { - match load_signer(key_path) { - Ok(signer) => signer, - Err(e) => panic!("Signer error @ path {key_path}: {e}\n"), +pub(crate) fn expect_key_store(key_store_path: &str) -> KeyStore { + match load_key_store(key_store_path) { + Ok(key_store) => key_store, + Err(e) => panic!("Key store error @ path {key_store_path}: {e}\n"), } } @@ -105,7 +114,7 @@ pub(crate) fn expect_signer(key_path: &str) -> PrivateKey { mod tests { use std::path::PathBuf; - use crate::config::expect_signer; + use crate::config::expect_key_store; #[test] fn test_expect_keys_node0() { @@ -114,12 +123,12 @@ mod tests { let repo_root = node_crate_dir.parent().unwrap(); repo_root.join("testnet/node0") }; - expect_signer(&keys_dir.join("key.pem").to_string_lossy()); + expect_key_store(&keys_dir.join("key.pem").to_string_lossy()); } #[test] #[should_panic] fn test_expect_keys_error_msg() { - expect_signer("missing-signer.pem"); + expect_key_store("missing-key-store.pem"); } } diff --git a/node/src/keys.rs b/node/src/keys.rs index 8bfe0fa8..534d1e10 100644 --- a/node/src/keys.rs +++ b/node/src/keys.rs @@ -1,13 +1,17 @@ use crate::args::DEFAULT_KEY_PATH; use anyhow::{Context as _, Result}; use clap::{Args, Subcommand}; -use commonware_codec::extensions::DecodeExt; +use commonware_codec::{extensions::DecodeExt, Encode}; use std::io::{self, Write}; use commonware_cryptography::{PrivateKeyExt as _, Signer}; +use commonware_cryptography::bls12381::PrivateKey as BlsPrivateKey; use commonware_utils::from_hex_formatted; use summit_types::{PrivateKey, utils::get_expanded_path}; +const NODE_KEY_FILENAME: &str = "node_key.pem"; +const CONSENSUS_KEY_FILENAME: &str = "consensus_key.pem"; + #[derive(Subcommand, PartialEq, Eq, Debug, Clone)] pub enum KeySubCmd { /// Print the node's public keys. @@ -25,9 +29,9 @@ pub enum KeySubCmd { #[derive(Args, Debug, Clone, PartialEq, Eq)] pub struct KeyFlags { - /// Path to your private key or where you want it generated - #[arg(long, default_value_t = DEFAULT_KEY_PATH.into())] - pub key_path: String, + /// Path to your keystore directory containing node_key.pem and consensus_key.pem + #[arg(long, default_value_t = "~/.seismic/consensus/keys".into())] + pub key_store_path: String, #[arg(short = 'n', long, conflicts_with = "yes_overwrite")] pub no_overwrite: bool, #[arg(short = 'y', long, conflicts_with = "no_overwrite")] @@ -55,22 +59,25 @@ impl KeySubCmd { } fn generate_keys(&self, flags: &KeyFlags) { - let path = get_expanded_path(&flags.key_path).expect("Invalid path"); + let keystore_dir = get_expanded_path(&flags.key_store_path).expect("Invalid path"); + let node_key_path = keystore_dir.join(NODE_KEY_FILENAME); + let consensus_key_path = keystore_dir.join(CONSENSUS_KEY_FILENAME); - // Check if key file already exists - if path.exists() { + // Check if key files already exist + let keys_exist = node_key_path.exists() || consensus_key_path.exists(); + if keys_exist { match flags.overwrite() { Some(true) => { - println!("Overwriting existing key at {}", path.display()); + println!("Overwriting existing keys at {}", keystore_dir.display()); } Some(false) => { - println!("Key already exists at {}", path.display()); + println!("Keys already exist at {}", keystore_dir.display()); return; } None => { print!( - "Key file already exists at {}. Overwrite? (y/N): ", - path.display() + "Keys already exist at {}. Overwrite? (y/N): ", + keystore_dir.display() ); io::stdout().flush().expect("Failed to flush stdout"); @@ -88,43 +95,67 @@ impl KeySubCmd { } } - std::fs::create_dir_all(path.parent().expect("Invalid file path")) - .expect("Unable to create file path to generate key"); - - let private_key = PrivateKey::from_rng(&mut rand::thread_rng()); - let pub_key = private_key.public_key(); - - let encoded_priv_key = private_key.to_string(); - std::fs::write(path, encoded_priv_key).expect("Unable to write private key to disk"); - - println!("Key generated:"); - println!("Public Key: {pub_key}"); + // Create keystore directory + std::fs::create_dir_all(&keystore_dir) + .expect("Unable to create keystore directory"); + + // Generate ed25519 node key + let node_private_key = PrivateKey::from_rng(&mut rand::thread_rng()); + let node_pub_key = node_private_key.public_key(); + let encoded_node_key = node_private_key.to_string(); + std::fs::write(&node_key_path, encoded_node_key) + .expect("Unable to write node key to disk"); + + // Generate BLS consensus key + let consensus_private_key = BlsPrivateKey::from_rng(&mut rand::thread_rng()); + let consensus_pub_key = consensus_private_key.public_key(); + let encoded_consensus_key = consensus_private_key.to_string(); + std::fs::write(&consensus_key_path, encoded_consensus_key) + .expect("Unable to write consensus key to disk"); + + println!("Keys generated at {}:", keystore_dir.display()); + println!("Node Public Key (ed25519): {}", node_pub_key); + println!("Consensus Public Key (BLS): {}", consensus_pub_key); } fn show_key(&self, flags: &KeyFlags) { - let pk = - read_ed_key_from_path(&flags.key_path).expect("Unable to read private key from disk"); + let keystore_dir = get_expanded_path(&flags.key_store_path).expect("Invalid path"); + let node_key_path = keystore_dir.join(NODE_KEY_FILENAME); + let consensus_key_path = keystore_dir.join(CONSENSUS_KEY_FILENAME); + + let node_pk = read_ed_key_from_file(&node_key_path) + .expect("Unable to read node key from disk"); + let consensus_pk = read_bls_key_from_file(&consensus_key_path) + .expect("Unable to read consensus key from disk"); - println!("Your nodes public key is : {}", pk.public_key()); + + println!("Node Public Key (ed25519): {}", node_pk.public_key()); + println!("Consensus Public Key (BLS): {}", consensus_pk.public_key()); } } -// pub fn read_bls_key_from_path(key_path: &str) -> Result { -// let path = get_expanded_path(key_path)?; -// let encoded_pk = std::fs::read_to_string(path)?; - -// let key = from_hex_formatted(&encoded_pk).context("Invalid pk format")?; -// let pk = PrivateKey::decode(&*key)?; +pub fn read_bls_key_from_file(path: &std::path::Path) -> Result { + let encoded_pk = std::fs::read_to_string(path)?; + let key = from_hex_formatted(&encoded_pk).context("Invalid BLS key format")?; + let pk = BlsPrivateKey::decode(&*key)?; + Ok(pk) +} -// Ok(pk) -// } +pub fn read_ed_key_from_file(path: &std::path::Path) -> Result { + let encoded_pk = std::fs::read_to_string(path)?; + let key = from_hex_formatted(&encoded_pk).context("Invalid ed25519 key format")?; + let pk = PrivateKey::decode(&*key)?; + Ok(pk) +} pub fn read_ed_key_from_path(key_path: &str) -> Result { let path = get_expanded_path(key_path)?; - let encoded_pk = std::fs::read_to_string(path)?; - - let key = from_hex_formatted(&encoded_pk).context("Invalid pk format")?; - let pk = PrivateKey::decode(&*key)?; + read_ed_key_from_file(&path) +} - Ok(pk) +pub fn read_keys_from_keystore(keystore_path: &str) -> Result<(PrivateKey, BlsPrivateKey)> { + let keystore_dir = get_expanded_path(keystore_path)?; + let node_key = read_ed_key_from_file(&keystore_dir.join(NODE_KEY_FILENAME))?; + let consensus_key = read_bls_key_from_file(&keystore_dir.join(CONSENSUS_KEY_FILENAME))?; + Ok((node_key, consensus_key)) } From 2ad6df6cd3392f76e8f456fea38f0efbf8aeba73 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Wed, 5 Nov 2025 11:12:40 -0500 Subject: [PATCH 25/81] feat: update syncer (WIP) --- syncer/Cargo.toml | 4 +- syncer/src/actor.rs | 1395 +++++++++++++++------------- syncer/src/cache.rs | 396 ++++++++ syncer/src/config.rs | 74 ++ syncer/src/coordinator.rs | 25 - syncer/src/finalizer.rs | 128 +++ syncer/src/handler.rs | 67 -- syncer/src/ingress.rs | 219 ----- syncer/src/ingress/handler.rs | 524 +++++++++++ syncer/src/ingress/mailbox.rs | 282 ++++++ syncer/src/ingress/mod.rs | 3 + syncer/src/ingress/orchestrator.rs | 87 ++ syncer/src/key.rs | 127 --- syncer/src/lib.rs | 1033 +++++++++++++++++++- syncer/src/mocks/application.rs | 49 + syncer/src/mocks/block.rs | 101 ++ syncer/src/mocks/mod.rs | 3 + syncer/src/mocks/resolver.rs | 27 + syncer/src/resolver/mod.rs | 3 + syncer/src/resolver/p2p.rs | 72 ++ 20 files changed, 3510 insertions(+), 1109 deletions(-) create mode 100644 syncer/src/cache.rs create mode 100644 syncer/src/config.rs delete mode 100644 syncer/src/coordinator.rs create mode 100644 syncer/src/finalizer.rs delete mode 100644 syncer/src/handler.rs delete mode 100644 syncer/src/ingress.rs create mode 100644 syncer/src/ingress/handler.rs create mode 100644 syncer/src/ingress/mailbox.rs create mode 100644 syncer/src/ingress/mod.rs create mode 100644 syncer/src/ingress/orchestrator.rs delete mode 100644 syncer/src/key.rs create mode 100644 syncer/src/mocks/application.rs create mode 100644 syncer/src/mocks/block.rs create mode 100644 syncer/src/mocks/mod.rs create mode 100644 syncer/src/mocks/resolver.rs create mode 100644 syncer/src/resolver/mod.rs create mode 100644 syncer/src/resolver/p2p.rs diff --git a/syncer/Cargo.toml b/syncer/Cargo.toml index 9bb04450..634f0f98 100644 --- a/syncer/Cargo.toml +++ b/syncer/Cargo.toml @@ -27,6 +27,8 @@ tracing.workspace = true # For metrics - activate with `prom` feature metrics = { version = "0.24.0", optional = true } +[dev-dependencies] +tracing-subscriber = "0.3.19" + [features] prom = ["metrics"] - diff --git a/syncer/src/actor.rs b/syncer/src/actor.rs index 9e885aa7..ee5495eb 100644 --- a/syncer/src/actor.rs +++ b/syncer/src/actor.rs @@ -1,767 +1,866 @@ -use std::{collections::BTreeSet, num::NonZero, time::Duration}; - -use crate::{ - Orchestration, Orchestrator, - handler::Handler, - ingress::{Mailbox, Message}, - key::{MultiIndex, Value}, +use super::{ + cache, + config::Config, + finalizer::Finalizer, + ingress::{ + handler::{self, Request}, + mailbox::{Mailbox, Message}, + orchestrator::{Orchestration, Orchestrator}, + }, }; -use commonware_broadcast::{Broadcaster as _, buffered}; -use commonware_codec::{DecodeExt as _, Encode as _}; -use commonware_consensus::simplex::types::Finalization; -use commonware_consensus::{Supervisor, Viewable as _}; +use crate::{ingress::mailbox::Identifier as BlockID, Update}; +use commonware_broadcast::{buffered, Broadcaster}; +use commonware_codec::{Decode, Encode}; +use commonware_cryptography::PublicKey; use commonware_macros::select; -use commonware_p2p::{Receiver, Recipients, Sender, utils::requester}; -use commonware_resolver::{Resolver as _, p2p}; -use commonware_runtime::{Clock, Handle, Metrics, Spawner, Storage}; -use commonware_storage::{ - archive::{ - self, Archive as _, Identifier, immutable::Archive as ImmutableArchive, - prunable::Archive as PrunableArchive, - }, - translator::TwoCap, +use commonware_p2p::Recipients; +use commonware_resolver::Resolver; +use commonware_runtime::{spawn_cell, Clock, ContextCell, Handle, Metrics, Spawner, Storage}; +use commonware_storage::archive::{immutable, Archive as _, Identifier as ArchiveID}; +use commonware_utils::futures::{AbortablePool, Aborter}; +use futures::{ + channel::{mpsc, oneshot}, + try_join, StreamExt, }; -use commonware_utils::NZU64; -use futures::{FutureExt, StreamExt as _, channel::mpsc}; -use governor::Quota; +use governor::clock::Clock as GClock; #[cfg(feature = "prom")] -use metrics::histogram; -use rand::Rng; -use summit_types::registry::Registry; -use summit_types::{Block, Digest, Finalized, Notarized, PublicKey, Signature}; -use tokio_util::sync::CancellationToken; +use metrics::gauge::Gauge; +use rand::{CryptoRng, Rng}; +use std::{ + collections::{btree_map::Entry, BTreeMap}, + time::Instant, +}; +use commonware_consensus::{utils, Block, Reporter}; +use commonware_consensus::simplex::signing_scheme::Scheme; +use commonware_consensus::simplex::types::{Finalization, Notarization}; +use commonware_consensus::types::Round; use tracing::{debug, info, warn}; -const PRUNABLE_ITEMS_PER_SECTION: NonZero = NZU64!(4_096); -const IMMUTABLE_ITEMS_PER_SECTION: NonZero = NZU64!(262_144); -const FREEZER_INITIAL_SIZE: u32 = 65_536; // todo(dalton): Check this default -const FREEZER_TABLE_RESIZE_FREQUENCY: u8 = 4; -const FREEZER_TABLE_RESIZE_CHUNK_SIZE: u32 = 2u32.pow(16); // 3MB -const FREEZER_JOURNAL_TARGET_SIZE: u64 = 1024 * 1024 * 1024; // 1GB +use summit_types::scheme::SchemeProvider; -const REPLAY_BUFFER: usize = 8 * 1024 * 1024; -const WRITE_BUFFER: usize = 1024 * 1024; - -pub struct Actor { - context: R, - mailbox: mpsc::Receiver, - // Blocks verified stored by view<>digest - verified: PrunableArchive, - // Blocks notarized stored by view<>digest - notarized: PrunableArchive, +/// A struct that holds multiple subscriptions for a block. +struct BlockSubscription { + // The subscribers that are waiting for the block + subscribers: Vec>, + // Aborter that aborts the waiter future when dropped + _aborter: Aborter, +} - // Finalizations stored by height - finalized: ImmutableArchive>, - // Blocks finalized stored by height - // - // We store this separately because we may not have the finalization for a block - blocks: ImmutableArchive, - orchestrator_mailbox: mpsc::Receiver, - public_key: PublicKey, - registry: Registry, +/// The [Actor] is responsible for receiving uncertified blocks from the broadcast mechanism, +/// receiving notarizations and finalizations from consensus, and reconstructing a total order +/// of blocks. +/// +/// The actor is designed to be used in a view-based model. Each view corresponds to a +/// potential block in the chain. The actor will only finalize a block if it has a +/// corresponding finalization. +/// +/// The actor also provides a backfill mechanism for missing blocks. If the actor receives a +/// finalization for a block that is ahead of its current view, it will request the missing blocks +/// from its peers. This ensures that the actor can catch up to the rest of the network if it falls +/// behind. +pub struct Actor< + E: Rng + CryptoRng + Spawner + Metrics + Clock + GClock + Storage, + B: Block, + P: SchemeProvider, + S: Scheme, +> { + // ---------- Context ---------- + context: ContextCell, + + // ---------- Message Passing ---------- + // Mailbox + mailbox: mpsc::Receiver>, + + // ---------- Configuration ---------- + // Provider for epoch-specific signing schemes + scheme_provider: P, + // Epoch length (in blocks) + epoch_length: u64, + // Mailbox size mailbox_size: usize, - backfill_quota: Quota, - activity_timeout: u64, - namespace: String, - cancellation_token: CancellationToken, + // Unique application namespace + namespace: Vec, + // Minimum number of views to retain temporary data after the application processes a block + view_retention_timeout: u64, + // Maximum number of blocks to repair at once + max_repair: u64, + // Codec configuration for block type + block_codec_config: B::Cfg, + // Partition prefix + partition_prefix: String, + + // ---------- State ---------- + // Last view processed + last_processed_round: Round, + // Highest known finalized height + tip: u64, + // Outstanding subscriptions for blocks + block_subscriptions: BTreeMap>, + + // ---------- Storage ---------- + // Prunable cache + cache: cache::Manager, + // Finalizations stored by height + finalizations_by_height: immutable::Archive>, + // Finalized blocks stored by height + finalized_blocks: immutable::Archive, + + // ---------- Metrics ---------- + // Latest height metric + #[cfg(feature = "prom")] + finalized_height: Gauge, + // Latest processed height + #[cfg(feature = "prom")] + processed_height: Gauge, } -impl Actor { - pub async fn new(context: R, config: crate::Config) -> (Self, Mailbox, Orchestrator) { - let (tx, rx) = mpsc::channel(config.mailbox_size); - - // todo: mess with these defaults - let verified_archive = PrunableArchive::init( - context.with_label("verified_archive"), - archive::prunable::Config { - translator: TwoCap, - partition: format!("{}-verified-archive", config.partition_prefix), - compression: None, - codec_config: (), - items_per_section: PRUNABLE_ITEMS_PER_SECTION, - write_buffer: NonZero::new(WRITE_BUFFER).expect("not zero"), - replay_buffer: NonZero::new(REPLAY_BUFFER).expect("not zero"), - buffer_pool: config.buffer_pool.clone(), - }, - ) - .await - .expect("failed to init verified archive"); - - let notarized_archive = PrunableArchive::init( - context.with_label("notarized_archive"), - archive::prunable::Config { - translator: TwoCap, - partition: format!("{}-notarized-archive", config.partition_prefix), - compression: None, - codec_config: (), - items_per_section: PRUNABLE_ITEMS_PER_SECTION, - write_buffer: NonZero::new(WRITE_BUFFER).expect("not zero"), - replay_buffer: NonZero::new(REPLAY_BUFFER).expect("not zero"), - buffer_pool: config.buffer_pool.clone(), - }, +impl< + E: Rng + CryptoRng + Spawner + Metrics + Clock + GClock + Storage, + B: Block, + P: SchemeProvider, + S: Scheme, + > Actor +{ + /// Create a new application actor. + pub async fn init(context: E, config: Config) -> (Self, Mailbox) { + // Initialize cache + let prunable_config = cache::Config { + partition_prefix: format!("{}-cache", config.partition_prefix.clone()), + prunable_items_per_section: config.prunable_items_per_section, + replay_buffer: config.replay_buffer, + write_buffer: config.write_buffer, + freezer_journal_buffer_pool: config.freezer_journal_buffer_pool.clone(), + }; + let cache = cache::Manager::init( + context.with_label("cache"), + prunable_config, + config.block_codec_config.clone(), + config.scheme_provider.clone(), ) - .await - .expect("failed to init verified archive"); - - let finalized_archive = ImmutableArchive::init( - context.with_label("finalized_archive"), - archive::immutable::Config { - metadata_partition: format!("{}-finalized-metadata", config.partition_prefix), - freezer_table_partition: format!("{}-finalized-table", config.partition_prefix), - freezer_table_initial_size: FREEZER_INITIAL_SIZE, - freezer_table_resize_frequency: FREEZER_TABLE_RESIZE_FREQUENCY, - freezer_table_resize_chunk_size: FREEZER_TABLE_RESIZE_CHUNK_SIZE, - freezer_journal_partition: format!("{}-finalized-journal", config.partition_prefix), - freezer_journal_target_size: FREEZER_JOURNAL_TARGET_SIZE, - freezer_journal_compression: Some(3), - freezer_journal_buffer_pool: config.buffer_pool.clone(), - ordinal_partition: format!("{}-finalized-ordinal", config.partition_prefix), - items_per_section: IMMUTABLE_ITEMS_PER_SECTION, - write_buffer: NonZero::new(WRITE_BUFFER).expect("not zero"), - replay_buffer: NonZero::new(REPLAY_BUFFER).expect("not zero"), - codec_config: usize::MAX, + .await; + + // Initialize finalizations by height + let start = Instant::now(); + let finalizations_by_height = immutable::Archive::init( + context.with_label("finalizations_by_height"), + immutable::Config { + metadata_partition: format!( + "{}-finalizations-by-height-metadata", + config.partition_prefix + ), + freezer_table_partition: format!( + "{}-finalizations-by-height-freezer-table", + config.partition_prefix + ), + freezer_table_initial_size: config.freezer_table_initial_size, + freezer_table_resize_frequency: config.freezer_table_resize_frequency, + freezer_table_resize_chunk_size: config.freezer_table_resize_chunk_size, + freezer_journal_partition: format!( + "{}-finalizations-by-height-freezer-journal", + config.partition_prefix + ), + freezer_journal_target_size: config.freezer_journal_target_size, + freezer_journal_compression: config.freezer_journal_compression, + freezer_journal_buffer_pool: config.freezer_journal_buffer_pool.clone(), + ordinal_partition: format!( + "{}-finalizations-by-height-ordinal", + config.partition_prefix + ), + items_per_section: config.immutable_items_per_section, + codec_config: S::certificate_codec_config_unbounded(), + replay_buffer: config.replay_buffer, + write_buffer: config.write_buffer, }, ) .await - .expect("failed to init verified archive"); - - let block_archive = ImmutableArchive::init( - context.with_label("block_archive"), - archive::immutable::Config { - metadata_partition: format!("{}-block-metadata", config.partition_prefix), - freezer_table_partition: format!("{}-block-table", config.partition_prefix), - freezer_table_initial_size: FREEZER_INITIAL_SIZE, - freezer_table_resize_frequency: FREEZER_TABLE_RESIZE_FREQUENCY, - freezer_table_resize_chunk_size: FREEZER_TABLE_RESIZE_CHUNK_SIZE, - freezer_journal_partition: format!("{}-block-journal", config.partition_prefix), - freezer_journal_target_size: FREEZER_JOURNAL_TARGET_SIZE, - freezer_journal_compression: Some(3), - freezer_journal_buffer_pool: config.buffer_pool, - ordinal_partition: format!("{}-block-ordinal", config.partition_prefix), - items_per_section: IMMUTABLE_ITEMS_PER_SECTION, - write_buffer: NonZero::new(WRITE_BUFFER).expect("not zero"), - replay_buffer: NonZero::new(REPLAY_BUFFER).expect("not zero"), - codec_config: (), + .expect("failed to initialize finalizations by height archive"); + info!(elapsed = ?start.elapsed(), "restored finalizations by height archive"); + + // Initialize finalized blocks + let start = Instant::now(); + let finalized_blocks = immutable::Archive::init( + context.with_label("finalized_blocks"), + immutable::Config { + metadata_partition: format!( + "{}-finalized_blocks-metadata", + config.partition_prefix + ), + freezer_table_partition: format!( + "{}-finalized_blocks-freezer-table", + config.partition_prefix + ), + freezer_table_initial_size: config.freezer_table_initial_size, + freezer_table_resize_frequency: config.freezer_table_resize_frequency, + freezer_table_resize_chunk_size: config.freezer_table_resize_chunk_size, + freezer_journal_partition: format!( + "{}-finalized_blocks-freezer-journal", + config.partition_prefix + ), + freezer_journal_target_size: config.freezer_journal_target_size, + freezer_journal_compression: config.freezer_journal_compression, + freezer_journal_buffer_pool: config.freezer_journal_buffer_pool, + ordinal_partition: format!("{}-finalized_blocks-ordinal", config.partition_prefix), + items_per_section: config.immutable_items_per_section, + codec_config: config.block_codec_config.clone(), + replay_buffer: config.replay_buffer, + write_buffer: config.write_buffer, }, ) .await - .expect("failed to init verified archive"); - - let (orchestrator_sender, orchestrator_mailbox) = mpsc::channel(2); // buffer to send processed while moving forward - - ( - Self { - context, - mailbox: rx, - verified: verified_archive, - notarized: notarized_archive, - finalized: finalized_archive, - blocks: block_archive, - public_key: config.public_key, - registry: config.registry, - mailbox_size: config.mailbox_size, - backfill_quota: config.backfill_quota, - activity_timeout: config.activity_timeout, - namespace: config.namespace, - orchestrator_mailbox, - cancellation_token: config.cancellation_token, - }, - Mailbox::new(tx), - Orchestrator::new(orchestrator_sender), - ) + .expect("failed to initialize finalized blocks archive"); + info!(elapsed = ?start.elapsed(), "restored finalized blocks archive"); + + // Create metrics + #[cfg(feature = "prom")] + { + let finalized_height = Gauge::default(); + context.register( + "finalized_height", + "Finalized height of application", + finalized_height.clone(), + ); + let processed_height = Gauge::default(); + context.register( + "processed_height", + "Processed height of application", + processed_height.clone(), + ); + + // Initialize mailbox + let (sender, mailbox) = mpsc::channel(config.mailbox_size); + ( + Self { + context: ContextCell::new(context), + mailbox, + scheme_provider: config.scheme_provider, + epoch_length: config.epoch_length, + mailbox_size: config.mailbox_size, + namespace: config.namespace, + view_retention_timeout: config.view_retention_timeout, + max_repair: config.max_repair, + block_codec_config: config.block_codec_config, + partition_prefix: config.partition_prefix, + last_processed_round: Round::new(0, 0), + tip: 0, + block_subscriptions: BTreeMap::new(), + cache, + finalizations_by_height, + finalized_blocks, + finalized_height, + processed_height, + }, + Mailbox::new(sender), + ) + } + #[cfg(not(feature = "prom"))] + { + // Initialize mailbox + let (sender, mailbox) = mpsc::channel(config.mailbox_size); + ( + Self { + context: ContextCell::new(context), + mailbox, + scheme_provider: config.scheme_provider, + epoch_length: config.epoch_length, + mailbox_size: config.mailbox_size, + namespace: config.namespace, + view_retention_timeout: config.view_retention_timeout, + max_repair: config.max_repair, + block_codec_config: config.block_codec_config, + partition_prefix: config.partition_prefix, + last_processed_round: Round::new(0, 0), + tip: 0, + block_subscriptions: BTreeMap::new(), + cache, + finalizations_by_height, + finalized_blocks, + }, + Mailbox::new(sender), + ) + } } - pub fn start( + /// Start the actor. + pub fn start( mut self, - buffer: buffered::Mailbox, - backfill: ( - impl Sender, - impl Receiver, - ), - tx_finalizer: mpsc::Sender<()>, - ) -> Handle<()> { - self.context.spawn_ref()(self.run(buffer, backfill, tx_finalizer)) + application: impl Reporter>, + buffer: buffered::Mailbox, + resolver: (mpsc::Receiver>, R), + ) -> Handle<()> + where + R: Resolver>, + K: PublicKey, + { + spawn_cell!(self.context, self.run(application, buffer, resolver).await) } - pub async fn run( + /// Run the application actor. + async fn run( mut self, - mut buffer: buffered::Mailbox, - backfill: ( - impl Sender, - impl Receiver, - ), - mut tx_finalizer: mpsc::Sender<()>, - ) { - let (handler_sender, mut handler_receiver) = mpsc::channel(self.mailbox_size); - let handler = Handler::new(handler_sender); - - let (resolver_engine, mut resolver) = p2p::Engine::new( - self.context.with_label("resolver"), - p2p::Config { - coordinator: self.registry.clone(), - consumer: handler.clone(), - producer: handler, - mailbox_size: self.mailbox_size, - requester_config: requester::Config { - public_key: self.public_key.clone(), - rate_limit: self.backfill_quota, - initial: Duration::from_secs(1), - timeout: Duration::from_secs(2), - }, - fetch_retry_timeout: Duration::from_millis(100), // prevent busy loop - priority_requests: false, - priority_responses: false, - }, - ); - - resolver_engine.start(backfill); + mut application: impl Reporter>, + mut buffer: buffered::Mailbox, + (mut resolver_rx, mut resolver): (mpsc::Receiver>, R), + ) where + R: Resolver>, + K: PublicKey, + { + // Process all finalized blocks in order (fetching any that are missing) + let (mut notifier_tx, notifier_rx) = mpsc::channel::<()>(1); + let (orchestrator_sender, mut orchestrator_receiver) = mpsc::channel(self.mailbox_size); + let orchestrator = Orchestrator::new(orchestrator_sender); + let finalizer = Finalizer::new( + self.context.with_label("finalizer"), + format!("{}-finalizer", self.partition_prefix.clone()), + application.clone(), + orchestrator, + notifier_rx, + ) + .await; + finalizer.start(); + + // Create a local pool for waiter futures + let mut waiters = AbortablePool::<(B::Commitment, B)>::default(); + + // Get tip and send to application + let tip = self.get_latest().await; + if let Some((height, commitment)) = tip { + application.report(Update::Tip(height, commitment)).await; + self.tip = height; + #[cfg(feature = "prom")] + self.finalized_height.set(height as i64); + } - let mut latest_view = 0; - let mut requested_blocks = BTreeSet::new(); - let mut last_view_processed: u64 = 0; - let mut outstanding_notarize = BTreeSet::new(); - let mut signal = self.context.stopped().fuse(); + // Handle messages loop { - // Cancel useless requests - let mut to_cancel = Vec::new(); - outstanding_notarize.retain(|view| { - if *view < latest_view { - to_cancel.push(MultiIndex::new(Value::Notarized(*view))); - false - } else { - true - } + // Remove any dropped subscribers. If all subscribers dropped, abort the waiter. + self.block_subscriptions.retain(|_, bs| { + bs.subscribers.retain(|tx| !tx.is_canceled()); + !bs.subscribers.is_empty() }); - for view in to_cancel { - resolver.cancel(view).await; - } + // Select messages select! { + // Handle waiter completions first + result = waiters.next_completed() => { + let Ok((commitment, block)) = result else { + continue; // Aborted future + }; + self.notify_subscribers(commitment, &block).await; + }, + // Handle consensus before finalizer or backfiller mailbox_message = self.mailbox.next() => { - let message = mailbox_message.expect("Mailbox closed"); + let Some(message) = mailbox_message else { + info!("mailbox closed, shutting down"); + return; + }; match message { - Message::Get { - view, - payload, - response, - } => { - #[cfg(feature = "prom")] - let get_start = std::time::Instant::now(); - - #[cfg(feature = "prom")] - let buffer_lookup_start = std::time::Instant::now(); - - // Check if in buffer - if let Some(buffered) = buffer - .get(None, payload, Some(payload)) - .await - .into_iter() - .next() - { - debug!(height = buffered.height(), "found block in buffer"); - let _ = response.send(buffered); - - #[cfg(feature = "prom")] - { - let buffer_lookup_duration = buffer_lookup_start.elapsed().as_micros() as f64; - histogram!("syncer_get_buffer_lookup_micros").record(buffer_lookup_duration); - histogram!("syncer_get_total_micros").record(get_start.elapsed().as_micros() as f64); - histogram!("syncer_get_location").record(0.0); // 0 = buffer - } - - continue; - } - - #[cfg(feature = "prom")] - { - let buffer_lookup_duration = buffer_lookup_start.elapsed().as_micros() as f64; - histogram!("syncer_get_buffer_lookup_micros").record(buffer_lookup_duration); + Message::GetInfo { identifier, response } => { + let info = match identifier { + // TODO: Instead of pulling out the entire block, determine the + // height directly from the archive by mapping the commitment to + // the index, which is the same as the height. + BlockID::Commitment(commitment) => self + .finalized_blocks + .get(ArchiveID::Key(&commitment)) + .await + .ok() + .flatten() + .map(|b| (b.height(), commitment)), + BlockID::Height(height) => self + .finalizations_by_height + .get(ArchiveID::Index(height)) + .await + .ok() + .flatten() + .map(|f| (height, f.proposal.payload)), + BlockID::Latest => self.get_latest().await, + }; + let _ = response.send(info); } - - #[cfg(feature = "prom")] - let verified_lookup_start = std::time::Instant::now(); - - // check verified blocks - if let Some(block) = self - .verified - .get(Identifier::Key(&payload)) - .await - .expect("Failed to read verified block store") - { - debug!(height = block.height(), "found block in verified"); - let _ = response.send(block); - - #[cfg(feature = "prom")] - { - let verified_lookup_duration = verified_lookup_start.elapsed().as_micros() as f64; - histogram!("syncer_get_verified_lookup_micros").record(verified_lookup_duration); - histogram!("syncer_get_total_micros").record(get_start.elapsed().as_micros() as f64); - histogram!("syncer_get_location").record(1.0); // 1 = verified - } - - continue; + Message::Broadcast { block } => { + let _peers = buffer.broadcast(Recipients::All, block).await; } - - #[cfg(feature = "prom")] - { - let verified_lookup_duration = verified_lookup_start.elapsed().as_micros() as f64; - histogram!("syncer_get_verified_lookup_micros").record(verified_lookup_duration); + Message::Verified { round, block } => { + self.cache_verified(round, block.commitment(), block).await; } + Message::Notarization { notarization } => { + let round = notarization.round(); + let commitment = notarization.proposal.payload; - #[cfg(feature = "prom")] - let notarized_lookup_start = std::time::Instant::now(); - - // check notarized blocks - if let Some(notarization) = self.notarized.get(Identifier::Key(&payload)).await.expect("Failed to get notarized block"){ - let block = notarization.block; - debug!(height = block.height(), "found block in notarized"); - let _ = response.send(block); + // Store notarization by view + self.cache.put_notarization(round, commitment, notarization.clone()).await; - #[cfg(feature = "prom")] - { - let notarized_lookup_duration = notarized_lookup_start.elapsed().as_micros() as f64; - histogram!("syncer_get_notarized_lookup_micros").record(notarized_lookup_duration); - histogram!("syncer_get_total_micros").record(get_start.elapsed().as_micros() as f64); - histogram!("syncer_get_location").record(2.0); // 2 = notarized + // Search for block locally, otherwise fetch it remotely + if let Some(block) = self.find_block(&mut buffer, commitment).await { + // If found, persist the block + self.cache_block(round, commitment, block).await; + } else { + debug!(?round, "notarized block missing"); + resolver.fetch(Request::::Notarized { round }).await; } - - continue; - } - - #[cfg(feature = "prom")] - { - let notarized_lookup_duration = notarized_lookup_start.elapsed().as_micros() as f64; - histogram!("syncer_get_notarized_lookup_micros").record(notarized_lookup_duration); + Message::Finalization { finalization } => { + // Cache finalization by round + let round = finalization.round(); + let commitment = finalization.proposal.payload; + self.cache.put_finalization(round, commitment, finalization.clone()).await; + + // Search for block locally, otherwise fetch it remotely + if let Some(block) = self.find_block(&mut buffer, commitment).await { + // If found, persist the block + let height = block.height(); + self.finalize(height, commitment, block, Some(finalization), &mut notifier_tx, &mut application).await; + debug!(?round, height, "finalized block stored"); + } else { + // Otherwise, fetch the block from the network. + debug!(?round, ?commitment, "finalized block missing"); + resolver.fetch(Request::::Block(commitment)).await; + } } - - #[cfg(feature = "prom")] - let finalized_lookup_start = std::time::Instant::now(); - - // check finalized blocks - if let Some(block) = self.blocks.get(Identifier::Key(&payload)).await.expect("Failed to get finalized block") { - debug!(height = block.height(), "found block in finalized"); - let _ = response.send(block); - - #[cfg(feature = "prom")] - { - let finalized_lookup_duration = finalized_lookup_start.elapsed().as_micros() as f64; - histogram!("syncer_get_finalized_lookup_micros").record(finalized_lookup_duration); - histogram!("syncer_get_total_micros").record(get_start.elapsed().as_micros() as f64); - histogram!("syncer_get_location").record(3.0); // 3 = finalized + Message::GetBlock { identifier, response } => { + match identifier { + BlockID::Commitment(commitment) => { + let result = self.find_block(&mut buffer, commitment).await; + let _ = response.send(result); + } + BlockID::Height(height) => { + let result = self.get_finalized_block(height).await; + let _ = response.send(result); + } + BlockID::Latest => { + let block = match self.get_latest().await { + Some((_, commitment)) => self.find_block(&mut buffer, commitment).await, + None => None, + }; + let _ = response.send(block); + } } - - continue; } - - #[cfg(feature = "prom")] - { - let finalized_lookup_duration = finalized_lookup_start.elapsed().as_micros() as f64; - histogram!("syncer_get_finalized_lookup_micros").record(finalized_lookup_duration); - histogram!("syncer_get_location").record(4.0); // 4 = not found + Message::GetFinalization { height, response } => { + let finalization = self.get_finalization_by_height(height).await; + let _ = response.send(finalization); } - - // Fetch from network if notarized (view is non-nil) - if let Some(view) = view { - debug!(view, ?payload, "required block missing"); - - #[cfg(feature = "prom")] - let resolver_fetch_start = std::time::Instant::now(); - - resolver.fetch(MultiIndex::new(Value::Notarized(view))).await; - - #[cfg(feature = "prom")] - { - let resolver_fetch_duration = resolver_fetch_start.elapsed().as_micros() as f64; - histogram!("syncer_resolver_fetch_micros").record(resolver_fetch_duration); + Message::Subscribe { round, commitment, response } => { + // Check for block locally + if let Some(block) = self.find_block(&mut buffer, commitment).await { + let _ = response.send(block); + continue; } - } - - buffer - .subscribe_prepared(None, payload, Some(payload), response) - .await; - } - Message::Broadcast { payload } => { - let ack = buffer.broadcast(Recipients::All, payload).await; - drop(ack); - } - Message::StoreVerified { view, payload } => { - match self.verified.put_sync(view, payload.digest(), payload).await { - Ok(_) => { - debug!(view, "verified block stored"); - } - Err(archive::Error::AlreadyPrunedTo(_)) => { - debug!(view, "verified block already pruned"); - } - Err(e) => { - panic!("Failed to insert verified block: {e}"); + // We don't have the block locally, so fetch the block from the network + // if we have an associated view. If we only have the digest, don't make + // the request as we wouldn't know when to drop it, and the request may + // never complete if the block is not finalized. + if let Some(round) = round { + if round < self.last_processed_round { + // At this point, we have failed to find the block locally, and + // we know that its round is less than the last processed round. + // This means that something else was finalized in that round, + // so we drop the response to indicate that the block may never + // be available. + continue; + } + // Attempt to fetch the block (with notarization) from the resolver. + // If this is a valid view, this request should be fine to keep open + // until resolution or pruning (even if the oneshot is canceled). + debug!(?round, ?commitment, "requested block missing"); + resolver.fetch(Request::::Notarized { round }).await; } - } - } - Message::Finalize {finalization} => { - let view = finalization.view(); - // Check if in buffer - let proposal = &finalization.proposal; - let mut block = buffer.get(None, proposal.payload, Some(proposal.payload)).await.into_iter().next(); - - // Check if in verified - if block.is_none() { - block = self.verified.get(Identifier::Key(&proposal.payload)).await.expect("Failed to get verified block"); - } - // Check if in notarized - if block.is_none() { - block = self.notarized.get(Identifier::Key(&proposal.payload)).await.expect("Failed to get notarized block").map(|notarized| notarized.block); - } - - if let Some(block) = block { - let digest = proposal.payload; - let height = block.height(); - - // persist the finalization - self.finalized.put_sync(height, digest, finalization).await.expect("Failed to insert into finalization store"); - self.blocks.put_sync(height, digest,block).await.expect("failed to insert into block store"); - - // prune blocks - let min_view = last_view_processed.saturating_sub(self.activity_timeout); - self.verified.prune(min_view).await.expect("Failed to prune verified blocks"); - self.notarized.prune(min_view).await.expect("Failed to prune notarized blocks"); - - // notify finalizer - let _ = tx_finalizer.try_send(()); - - // update latest - latest_view = view; - - continue; - } - - // Fetch from network - warn!(view, digest = ?proposal.payload, "finalized block missing"); - resolver.fetch(MultiIndex::new(Value::Digest(proposal.payload))).await; - } - Message::Notarize{notarization} => { - let view = notarization.view(); - // Check if in buffer - let proposal = ¬arization.proposal; - let mut block = buffer.get(None, proposal.payload, Some(proposal.payload)).await.into_iter().next(); - - // Check if in verified blocks - if block.is_none() { - block = self.verified.get(Identifier::Key(&proposal.payload)).await.expect("Failed to get verified block"); - } - - if let Some(block) = block { - let height = block.height(); - let digest = proposal.payload; - let notarization = Notarized::new(notarization, block); - - // Persist the notarization - match self.notarized.put_sync(view,digest,notarization).await { - Ok(_) => { - debug!(view,height, "notarized block stored") - } - Err(archive::Error::AlreadyPrunedTo(_)) => { - debug!(view, "notarized already pruned"); + // Register subscriber + debug!(?round, ?commitment, "registering subscriber"); + match self.block_subscriptions.entry(commitment) { + Entry::Occupied(mut entry) => { + entry.get_mut().subscribers.push(response); } - Err(e) => { - panic!("Failed to insert notarized block: {e}"); + Entry::Vacant(entry) => { + let (tx, rx) = oneshot::channel(); + buffer.subscribe_prepared(None, commitment, None, tx).await; + let aborter = waiters.push(async move { + (commitment, rx.await.expect("buffer subscriber closed")) + }); + entry.insert(BlockSubscription { + subscribers: vec![response], + _aborter: aborter, + }); } - }; - continue; - } - - debug!(view, "notarized block missing"); - outstanding_notarize.insert(view); - - #[cfg(feature = "prom")] - let resolver_fetch_start = std::time::Instant::now(); - - resolver.fetch(MultiIndex::new(Value::Notarized(view))).await; - - #[cfg(feature = "prom")] - { - let resolver_fetch_duration = resolver_fetch_start.elapsed().as_micros() as f64; - histogram!("syncer_resolver_fetch_micros").record(resolver_fetch_duration); + } } - } - } }, - orchestrator_message = self.orchestrator_mailbox.next() => { - let orchestrator_message = orchestrator_message.expect("Orchestrator closed"); - match orchestrator_message { - Orchestration::Get { next, result } => { + // Handle finalizer messages next + message = orchestrator_receiver.next() => { + let Some(message) = message else { + info!("orchestrator closed, shutting down"); + return; + }; + match message { + Orchestration::Get { height, result } => { // Check if in blocks - let block = self.blocks.get(Identifier::Index(next)).await.expect("Failed to get finalized block"); - result.send(block).expect("Failed to send block"); - }, - Orchestration::GetWithFinalization { next, result } => { - let block = self.blocks.get(Identifier::Index(next)).await.expect("Failed to get finalized block"); - let finalized = self.finalized.get(Identifier::Index(next)).await.expect("Failed to get finalized block"); - result.send((block, finalized)).expect("Failed to send block with finalized"); - }, - Orchestration::Processed { next, digest } => { + let block = self.get_finalized_block(height).await; + result.send(block).unwrap_or_else(|_| warn!(?height, "Failed to send block to orchestrator")); + } + Orchestration::Processed { height, digest } => { + // Update metrics + #[cfg(feature = "prom")] + self.processed_height.set(height as i64); + // Cancel any outstanding requests (by height and by digest) - resolver.cancel(MultiIndex::new(Value::Finalized(next))).await; - resolver.cancel(MultiIndex::new(Value::Digest(digest))).await; + resolver.cancel(Request::::Block(digest)).await; + resolver.retain(Request::::Finalized { height }.predicate()).await; - // If finalization exists, mark as last_view_processed - let finalization = self.finalized.get(Identifier::Index(next)).await.expect("Failed to get finalized block"); - if let Some(finalization) = finalization { - last_view_processed = finalization.view(); - } + // If finalization exists, prune the archives + if let Some(finalization) = self.get_finalization_by_height(height).await { + // Trail the previous processed finalized block by the timeout + let lpr = self.last_processed_round; + let prune_round = Round::new(lpr.epoch(), lpr.view().saturating_sub(self.view_retention_timeout)); - // Drain requested blocks less than next - requested_blocks.retain(|height| *height > next); - }, - Orchestration::Repair { next, result } => { - // While this should never happen, if the height is less than the sync - // height, then we don't need to repair. - // todo(dalton) make sure this is an okay check to remove now that we are not aware of sync_height in syncer - // if next < sync_height { - // continue; - // } - - // Find next gap - let (_, start_next) = self.blocks.next_gap(next); - let start_next = if let Some(start_next) = start_next { - start_next - } else { - // No gap found by next_gap, but block might still be missing (empty db case) - next - }; + // Prune archives + self.cache.prune(prune_round).await; - // If we are at some height greater than genesis and start_next > next, - // attempt to repair the parent of the gapped block - if next > 0 && start_next > next { - // Get gapped block (the first block after the gap) - let gapped_block = self.blocks.get(Identifier::Index(start_next)).await.expect("Failed to get finalized block").expect("Gapped block missing"); - - // Attempt to repair one block from other sources - let target_block = gapped_block.parent(); - let verified = self.verified.get(Identifier::Key(&target_block)).await.expect("Failed to get verified block"); - if let Some(verified) = verified { - let height = verified.height(); - self.blocks.put_sync(height, target_block, verified).await.expect("Failed to insert finalized block"); - debug!(height, "repaired block from verified"); - result.send(true).expect("Failed to send repair result"); - continue; - } - let notarization = self.notarized.get(Identifier::Key(&target_block)).await.expect("Failed to get notarized block"); - if let Some(notarization) = notarization { - let height = notarization.block.height(); - self.blocks.put_sync(height, target_block, notarization.block).await.expect("Failed to insert finalized block"); - debug!(height, "repaired block from notarizations"); - result.send(true).expect("Failed to send repair result"); - continue; - } + // Update the last processed round + let round = finalization.round(); + self.last_processed_round = round; - // Request the parent block digest - resolver.fetch(MultiIndex::new(Value::Digest(target_block))).await; + // Cancel useless requests + resolver.retain(Request::::Notarized { round }.predicate()).await; } + } + Orchestration::Repair { height } => { + // Find the end of the "gap" of missing blocks, starting at `height` + let (_, Some(gap_end)) = self.finalized_blocks.next_gap(height) else { + // No gap found; height-1 is the last known finalized block + continue; + }; + assert!(gap_end > height, "gap end must be greater than height"); - // Enqueue next items (by index) - let range_end = if start_next == next { - next + 1 - } else { - std::cmp::min(start_next, next + 20) + // Attempt to repair the gap backwards from the end of the gap, using + // blocks from our local storage. + let Some(mut cursor) = self.get_finalized_block(gap_end).await else { + panic!("gapped block missing that should exist: {gap_end}"); }; - let range = next..range_end; - for height in range { - // Check if we've already requested - if requested_blocks.contains(&height) { - continue; + + // Iterate backwards, repairing blocks as we go. + while cursor.height() > height { + let commitment = cursor.parent(); + if let Some(block) = self.find_block(&mut buffer, commitment).await { + let finalization = self.cache.get_finalization_for(commitment).await; + self.finalize(block.height(), commitment, block.clone(), finalization, &mut notifier_tx, &mut application).await; + debug!(height = block.height(), "repaired block"); + cursor = block; + } else { + // Request the next missing block digest + resolver.fetch(Request::::Block(commitment)).await; + break; } + } - // Request the block - let key = MultiIndex::new(Value::Finalized(height)); - resolver.fetch(key).await; - requested_blocks.insert(height); + // If we haven't fully repaired the gap, then also request any possible + // finalizations for the blocks in the remaining gap. This may help + // shrink the size of the gap if finalizations for the requests heights + // exist. If not, we rely on the recursive digest fetch above. + let gap_start = height; + let gap_end = std::cmp::min(cursor.height(), gap_start.saturating_add(self.max_repair)); + debug!(gap_start, gap_end, "requesting any finalized blocks"); + for height in gap_start..gap_end { + resolver.fetch(Request::::Finalized { height }).await; } - result.send(false).expect("Failed to send repair result"); - }, + } } }, // Handle resolver messages last - handler_message = handler_receiver.next() => { - let message = handler_message.expect("Handler closed"); + message = resolver_rx.next() => { + let Some(message) = message else { + info!("handler closed, shutting down"); + return; + }; match message { - crate::handler::Message::Deliver { key, value, response } => { - match key.to_value() { - Value::Notarized(view) => { - // Parse notarization - let Ok(notarization) = Notarized::decode(value.as_ref()) else { - let _ = response.send(false); + handler::Message::Produce { key, response } => { + match key { + Request::Block(commitment) => { + // Check for block locally + let Some(block) = self.find_block(&mut buffer, commitment).await else { + debug!(?commitment, "block missing on request"); + continue; + }; + let _ = response.send(block.encode().into()); + } + Request::Finalized { height } => { + // Get finalization + let Some(finalization) = self.get_finalization_by_height(height).await else { + debug!(height, "finalization missing on request"); continue; }; - let participants = self.registry.participants(view).expect("registry cannot be empty"); - if !notarization.proof.verify(self.namespace.as_bytes(), participants) { - let _ = response.send(false); + // Get block + let Some(block) = self.get_finalized_block(height).await else { + debug!(height, "finalized block missing on request"); continue; - } + }; - // Ensure the received payload is for the correct view - if notarization.proof.view() != view { - let _ = response.send(false); + // Send finalization + let _ = response.send((finalization, block).encode().into()); + } + Request::Notarized { round } => { + // Get notarization + let Some(notarization) = self.cache.get_notarization(round).await else { + debug!(?round, "notarization missing on request"); continue; - } + }; - // Persist the notarization - let _ = response.send(true); - match self.notarized - .put_sync(view, notarization.block.digest(), notarization) - .await { - Ok(_) => { - debug!(view, "notarized stored"); - }, - Err(archive::Error::AlreadyPrunedTo(_)) => { - debug!(view, "notarized already pruned"); - - } - Err(e) => { - panic!("Failed to insert notarized block: {e}"); - } + // Get block + let commitment = notarization.proposal.payload; + let Some(block) = self.find_block(&mut buffer, commitment).await else { + debug!(?commitment, "block missing on request"); + continue; }; + let _ = response.send((notarization, block).encode().into()); } - Value::Finalized(height) => { - // Parse finalization - let Ok(finalization) = Finalized::decode(value.as_ref()) else { + } + }, + handler::Message::Deliver { key, value, response } => { + match key { + Request::Block(commitment) => { + // Parse block + let Ok(block) = B::decode_cfg(value.as_ref(), &self.block_codec_config) else { let _ = response.send(false); continue; }; - let view = finalization.proof.proposal.view; - let participants = self.registry.participants(view).expect("registry cannot be empty"); - if !finalization.proof.verify(self.namespace.as_bytes(), participants) { - let _ = response.send(false); - continue; - } - // Ensure the received payload is for the correct height - if finalization.block.height() != height { + // Validation + if block.commitment() != commitment { let _ = response.send(false); continue; } - // Indicate the finalization was valid - debug!(height, "received finalization"); + // Persist the block, also persisting the finalization if we have it + let height = block.height(); + let finalization = self.cache.get_finalization_for(commitment).await; + self.finalize(height, commitment, block, finalization, &mut notifier_tx, &mut application).await; + debug!(?commitment, height, "received block"); let _ = response.send(true); - - // Persist the finalization - self.finalized - .put_sync(height, finalization.block.digest(), finalization.proof ) - .await - .expect("Failed to insert finalization"); - - // Persist the block - self.blocks - .put_sync(height, finalization.block.digest(), finalization.block) - .await - .expect("Failed to insert finalized block"); - - let _ = tx_finalizer.try_send(()); }, - Value::Digest(digest) => { - // Parse block - let Ok(block) = Block::decode(value.as_ref()) else { + Request::Finalized { height } => { + let epoch = utils::epoch(self.epoch_length, height); + let Some(scheme) = self.scheme_provider.scheme(epoch) else { let _ = response.send(false); continue; }; - // Ensure the received payload is for the correct digest - if block.digest() != digest { + // Parse finalization + let Ok((finalization, block)) = + <(Finalization, B)>::decode_cfg( + value, + &(scheme.certificate_codec_config(), self.block_codec_config.clone()), + ) + else { + let _ = response.send(false); + continue; + }; + + // Validation + if block.height() != height + || finalization.proposal.payload != block.commitment() + || !finalization.verify(&mut self.context, &scheme, &self.namespace) + { let _ = response.send(false); continue; } - // Persist the block - debug!(?digest, height = block.height(), "received block"); + // Valid finalization received + debug!(height, "received finalization"); let _ = response.send(true); - self.blocks - .put_sync(block.height(), digest, block) - .await - .expect("Failed to insert finalized block"); - - let _ = tx_finalizer.try_send(()); + self.finalize(height, block.commitment(), block, Some(finalization), &mut notifier_tx, &mut application).await; }, - } - } - crate::handler::Message::Produce { key, response } => { - match key.to_value() { - Value::Notarized(view) => { - if let Some(notarized) = self.notarized.get(Identifier::Index(view)).await.expect("Failed to get notarized block") { - let _ = response.send(notarized.encode().into()); - } else { - debug!("{view} notarization missing on request"); - } - } - Value::Finalized(height) => { - // get finalization - let Some(finalization) = self.finalized.get(Identifier::Index(height)).await.expect("Failed to get finalization")else { - debug!(height, "Finalization missing on request"); + Request::Notarized { round } => { + let Some(scheme) = self.scheme_provider.scheme(round.epoch()) else { + let _ = response.send(false); continue; }; - // get block - let Some(block)= self.blocks.get(Identifier::Index(height)).await.expect("Failed to get finalized block") else { - debug!(height, "finalized block missing on request"); + // Parse notarization + let Ok((notarization, block)) = + <(Notarization, B)>::decode_cfg( + value, + &(scheme.certificate_codec_config(), self.block_codec_config.clone()), + ) + else { + let _ = response.send(false); continue; }; - // send finalization - let payload = Finalized::new(finalization, block); - let _ = response.send(payload.encode().into()); - } - Value::Digest(digest) => { - // try buffer - if let Some(block) = buffer.get(None, digest, Some(digest)).await.into_iter().next() { - let bytes = block.encode(); - let _ = response.send(bytes.into()); - continue; - } - - // try verified blocks - if let Some(block) = self.verified.get(Identifier::Key(&digest)).await.expect("Failed to get verified block") { - let _ = response.send(block.encode().into()); - continue; - } - - // try notarized blocks - if let Some(notarized) = self.notarized.get(Identifier::Key(&digest)).await.expect("Failed to get notarized block") { - let _ = response.send(notarized.block.encode().into()); + // Validation + if notarization.round() != round + || notarization.proposal.payload != block.commitment() + || !notarization.verify(&mut self.context, &scheme, &self.namespace) + { + let _ = response.send(false); continue; } - // try blocks - if let Some(block) = self.blocks.get(Identifier::Key(&digest)).await.expect("Failed to get finalized block") { - let _ = response.send(block.encode().into()); - continue; + // Valid notarization received + let _ = response.send(true); + let commitment = block.commitment(); + debug!(?round, ?commitment, "received notarization"); + + // If there exists a finalization certificate for this block, we + // should finalize it. While not necessary, this could finalize + // the block faster in the case where a notarization then a + // finalization is received via the consensus engine and we + // resolve the request for the notarization before we resolve + // the request for the block. + let height = block.height(); + if let Some(finalization) = self.cache.get_finalization_for(commitment).await { + self.finalize(height, commitment, block.clone(), Some(finalization), &mut notifier_tx, &mut application).await; } - // No record of block - debug!(?digest, "block missing on request"); + // Cache the notarization and block + self.cache_block(round, commitment, block).await; + self.cache.put_notarization(round, commitment, notarization).await; }, } }, } }, - _ = self.cancellation_token.cancelled() => { - info!("syncer received cancellation signal, exiting"); - break; - }, - sig = &mut signal => { - info!("runtime terminated terminated, shutting down syncer: {}", sig.unwrap()); - break; + } + } + } + + // -------------------- Waiters -------------------- + + /// Notify any subscribers for the given commitment with the provided block. + async fn notify_subscribers(&mut self, commitment: B::Commitment, block: &B) { + if let Some(mut bs) = self.block_subscriptions.remove(&commitment) { + for subscriber in bs.subscribers.drain(..) { + let _ = subscriber.send(block.clone()); + } + } + } + + // -------------------- Prunable Storage -------------------- + + /// Add a verified block to the prunable archive. + async fn cache_verified(&mut self, round: Round, commitment: B::Commitment, block: B) { + self.notify_subscribers(commitment, &block).await; + self.cache.put_verified(round, commitment, block).await; + } + + /// Add a notarized block to the prunable archive. + async fn cache_block(&mut self, round: Round, commitment: B::Commitment, block: B) { + self.notify_subscribers(commitment, &block).await; + self.cache.put_block(round, commitment, block).await; + } + + // -------------------- Immutable Storage -------------------- + + /// Get a finalized block from the immutable archive. + async fn get_finalized_block(&self, height: u64) -> Option { + match self.finalized_blocks.get(ArchiveID::Index(height)).await { + Ok(block) => block, + Err(e) => panic!("failed to get block: {e}"), + } + } + + /// Get a finalization from the archive by height. + async fn get_finalization_by_height( + &self, + height: u64, + ) -> Option> { + match self + .finalizations_by_height + .get(ArchiveID::Index(height)) + .await + { + Ok(finalization) => finalization, + Err(e) => panic!("failed to get finalization: {e}"), + } + } + + /// Add a finalized block, and optionally a finalization, to the archive. + /// + /// At the end of the method, the notifier is notified to indicate that there has been an update + /// to the archive of finalized blocks. + async fn finalize( + &mut self, + height: u64, + commitment: B::Commitment, + block: B, + finalization: Option>, + notifier: &mut mpsc::Sender<()>, + application: &mut impl Reporter>, + ) { + self.notify_subscribers(commitment, &block).await; + + // In parallel, update the finalized blocks and finalizations archives + if let Err(e) = try_join!( + // Update the finalized blocks archive + self.finalized_blocks.put_sync(height, commitment, block), + // Update the finalizations archive (if provided) + async { + if let Some(finalization) = finalization { + self.finalizations_by_height + .put_sync(height, commitment, finalization) + .await?; } + Ok::<_, _>(()) } + ) { + panic!("failed to finalize: {e}"); + } + + // Notify the finalizer + let _ = notifier.try_send(()); + + // Update metrics and send tip update to application + if height > self.tip { + application.report(Update::Tip(height, commitment)).await; + self.tip = height; + #[cfg(feature = "prom")] + self.finalized_height.set(height as i64); } } -} -impl Drop for Actor { - fn drop(&mut self) { - self.cancellation_token.cancel(); + /// Get the latest finalized block information (height and commitment tuple). + /// + /// Blocks are only finalized directly with a finalization or indirectly via a descendant + /// block's finalization. Thus, the highest known finalized block must itself have a direct + /// finalization. + /// + /// We return the height and commitment using the highest known finalization that we know the + /// block height for. While it's possible that we have a later finalization, if we do not have + /// the full block for that finalization, we do not know it's height and therefore it would not + /// yet be found in the `finalizations_by_height` archive. While not checked explicitly, we + /// should have the associated block (in the `finalized_blocks` archive) for the information + /// returned. + async fn get_latest(&mut self) -> Option<(u64, B::Commitment)> { + let height = self.finalizations_by_height.last_index()?; + let finalization = self + .get_finalization_by_height(height) + .await + .expect("finalization missing"); + Some((height, finalization.proposal.payload)) + } + + // -------------------- Mixed Storage -------------------- + + /// Looks for a block anywhere in local storage. + async fn find_block( + &mut self, + buffer: &mut buffered::Mailbox, + commitment: B::Commitment, + ) -> Option { + // Check buffer. + if let Some(block) = buffer.get(None, commitment, None).await.into_iter().next() { + return Some(block); + } + // Check verified / notarized blocks via cache manager. + if let Some(block) = self.cache.find_block(commitment).await { + return Some(block); + } + // Check finalized blocks. + match self.finalized_blocks.get(ArchiveID::Key(&commitment)).await { + Ok(block) => block, // may be None + Err(e) => panic!("failed to get block: {e}"), + } } } diff --git a/syncer/src/cache.rs b/syncer/src/cache.rs new file mode 100644 index 00000000..83022bb6 --- /dev/null +++ b/syncer/src/cache.rs @@ -0,0 +1,396 @@ +use commonware_consensus::{ + simplex::{ + signing_scheme::Scheme, + types::{Finalization, Notarization}, + }, + types::{Epoch, Round, View}, + Block, +}; +use commonware_codec::Codec; +use commonware_runtime::{buffer::PoolRef, Clock, Metrics, Spawner, Storage}; +use commonware_storage::{ + archive::{self, prunable, Archive as _, Identifier}, + metadata::{self, Metadata}, + translator::TwoCap, +}; +use commonware_utils::{fixed_bytes, sequence::FixedBytes}; +use governor::clock::Clock as GClock; +use rand::Rng; +use std::{ + cmp::max, + collections::BTreeMap, + num::{NonZero, NonZeroUsize}, + time::Instant, +}; +use tracing::{debug, info}; + +use summit_types::scheme::SchemeProvider; + +// The key used to store the current epoch in the metadata store. +const CACHED_EPOCHS_KEY: FixedBytes<1> = fixed_bytes!("0x00"); + +/// Configuration parameters for prunable archives. +pub(crate) struct Config { + pub partition_prefix: String, + pub prunable_items_per_section: NonZero, + pub replay_buffer: NonZeroUsize, + pub write_buffer: NonZeroUsize, + pub freezer_journal_buffer_pool: PoolRef, +} + +/// Prunable archives for a single epoch. +struct Cache { + /// Verified blocks stored by view + verified_blocks: prunable::Archive, + /// Notarized blocks stored by view + notarized_blocks: prunable::Archive, + /// Notarizations stored by view + notarizations: prunable::Archive>, + /// Finalizations stored by view + finalizations: prunable::Archive>, +} + +impl Cache { + /// Prune the archives to the given view. + async fn prune(&mut self, min_view: View) { + match futures::try_join!( + self.verified_blocks.prune(min_view), + self.notarized_blocks.prune(min_view), + self.notarizations.prune(min_view), + self.finalizations.prune(min_view), + ) { + Ok(_) => debug!(min_view, "pruned archives"), + Err(e) => panic!("failed to prune archives: {e}"), + } + } +} + +/// Manages prunable caches and their metadata. +pub(crate) struct Manager< + R: Rng + Spawner + Metrics + Clock + GClock + Storage, + B: Block, + P: SchemeProvider, + S: Scheme, +> { + /// Context + context: R, + + /// Provider for epoch-specific signing schemes. + scheme_provider: P, + + /// Configuration for underlying prunable archives + cfg: Config, + + /// Codec configuration for block type + block_codec_config: B::Cfg, + + /// Metadata store for recording which epochs may have data. The value is a tuple of the floor + /// and ceiling, the minimum and maximum epochs (inclusive) that may have data. + metadata: Metadata, (Epoch, Epoch)>, + + /// A map from epoch to its cache + caches: BTreeMap>, +} + +impl< + R: Rng + Spawner + Metrics + Clock + GClock + Storage, + B: Block, + P: SchemeProvider, + S: Scheme, + > Manager +{ + /// Initialize the cache manager and its metadata store. + pub(crate) async fn init( + context: R, + cfg: Config, + block_codec_config: B::Cfg, + scheme_provider: P, + ) -> Self { + // Initialize metadata + let metadata = Metadata::init( + context.with_label("metadata"), + metadata::Config { + partition: format!("{}-metadata", cfg.partition_prefix), + codec_config: ((), ()), + }, + ) + .await + .expect("failed to initialize metadata"); + + // We don't eagerly initialize any epoch caches here, they will be + // initialized on demand, otherwise there could be coordination issues + // around the scheme provider. + Self { + context, + scheme_provider, + cfg, + block_codec_config, + metadata, + caches: BTreeMap::new(), + } + } + + /// Retrieve the epoch range that may have data. + fn get_metadata(&self) -> (Epoch, Epoch) { + self.metadata + .get(&CACHED_EPOCHS_KEY) + .cloned() + .unwrap_or((0, 0)) + } + + /// Set the epoch range that may have data. + async fn set_metadata(&mut self, floor: Epoch, ceiling: Epoch) { + self.metadata + .put_sync(CACHED_EPOCHS_KEY, (floor, ceiling)) + .await + .expect("failed to write metadata"); + } + + /// Get the cache for the given epoch, initializing it if it doesn't exist. + /// + /// If the epoch is less than the minimum cached epoch, then it has already been pruned, + /// and this will return `None`. + async fn get_or_init_epoch(&mut self, epoch: Epoch) -> Option<&mut Cache> { + // If the cache exists, return it + if self.caches.contains_key(&epoch) { + return self.caches.get_mut(&epoch); + } + + // If the epoch is less than the epoch floor, then it has already been pruned + let (floor, ceiling) = self.get_metadata(); + if epoch < floor { + return None; + } + + // Update the metadata (metadata-first is safe; init is idempotent) + if epoch > ceiling { + self.set_metadata(floor, epoch).await; + } + + // Initialize and return the epoch + self.init_epoch(epoch).await; + self.caches.get_mut(&epoch) // Should always be Some + } + + /// Helper to initialize the cache for a given epoch. + async fn init_epoch(&mut self, epoch: Epoch) { + let scheme = self + .scheme_provider + .scheme(epoch) + .unwrap_or_else(|| panic!("failed to get signing scheme for epoch: {epoch}")); + + let verified_blocks = self + .init_archive(epoch, "verified", self.block_codec_config.clone()) + .await; + let notarized_blocks = self + .init_archive(epoch, "notarized", self.block_codec_config.clone()) + .await; + let notarizations = self + .init_archive(epoch, "notarizations", scheme.certificate_codec_config()) + .await; + let finalizations = self + .init_archive(epoch, "finalizations", scheme.certificate_codec_config()) + .await; + let existing = self.caches.insert( + epoch, + Cache { + verified_blocks, + notarized_blocks, + notarizations, + finalizations, + }, + ); + assert!(existing.is_none(), "cache already exists for epoch {epoch}"); + } + + /// Helper to initialize an archive. + async fn init_archive( + &self, + epoch: Epoch, + name: &str, + codec_config: T::Cfg, + ) -> prunable::Archive { + let start = Instant::now(); + let cfg = prunable::Config { + partition: format!("{}-cache-{epoch}-{name}", self.cfg.partition_prefix), + translator: TwoCap, + items_per_section: self.cfg.prunable_items_per_section, + compression: None, + codec_config, + buffer_pool: self.cfg.freezer_journal_buffer_pool.clone(), + replay_buffer: self.cfg.replay_buffer, + write_buffer: self.cfg.write_buffer, + }; + let archive = prunable::Archive::init(self.context.with_label(name), cfg) + .await + .unwrap_or_else(|_| panic!("failed to initialize {name} archive")); + info!(elapsed = ?start.elapsed(), "restored {name} archive"); + archive + } + + /// Add a verified block to the prunable archive. + pub(crate) async fn put_verified(&mut self, round: Round, commitment: B::Commitment, block: B) { + let Some(cache) = self.get_or_init_epoch(round.epoch()).await else { + return; + }; + let result = cache + .verified_blocks + .put_sync(round.view(), commitment, block) + .await; + Self::handle_result(result, round, "verified"); + } + + /// Add a notarized block to the prunable archive. + pub(crate) async fn put_block(&mut self, round: Round, commitment: B::Commitment, block: B) { + let Some(cache) = self.get_or_init_epoch(round.epoch()).await else { + return; + }; + let result = cache + .notarized_blocks + .put_sync(round.view(), commitment, block) + .await; + Self::handle_result(result, round, "notarized"); + } + + /// Add a notarization to the prunable archive. + pub(crate) async fn put_notarization( + &mut self, + round: Round, + commitment: B::Commitment, + notarization: Notarization, + ) { + let Some(cache) = self.get_or_init_epoch(round.epoch()).await else { + return; + }; + let result = cache + .notarizations + .put_sync(round.view(), commitment, notarization) + .await; + Self::handle_result(result, round, "notarization"); + } + + /// Add a finalization to the prunable archive. + pub(crate) async fn put_finalization( + &mut self, + round: Round, + commitment: B::Commitment, + finalization: Finalization, + ) { + let Some(cache) = self.get_or_init_epoch(round.epoch()).await else { + return; + }; + let result = cache + .finalizations + .put_sync(round.view(), commitment, finalization) + .await; + Self::handle_result(result, round, "finalization"); + } + + /// Helper to debug cache results. + fn handle_result(result: Result<(), archive::Error>, round: Round, name: &str) { + match result { + Ok(_) => { + debug!(?round, name, "cached"); + } + Err(archive::Error::AlreadyPrunedTo(_)) => { + debug!(?round, name, "already pruned"); + } + Err(e) => { + panic!("failed to insert {name}: {e}"); + } + } + } + + /// Get a notarization from the prunable archive by round. + pub(crate) async fn get_notarization( + &self, + round: Round, + ) -> Option> { + let cache = self.caches.get(&round.epoch())?; + cache + .notarizations + .get(Identifier::Index(round.view())) + .await + .expect("failed to get notarization") + } + + /// Get a finalization from the prunable archive by commitment. + pub(crate) async fn get_finalization_for( + &self, + commitment: B::Commitment, + ) -> Option> { + for cache in self.caches.values().rev() { + match cache.finalizations.get(Identifier::Key(&commitment)).await { + Ok(Some(finalization)) => return Some(finalization), + Ok(None) => continue, + Err(e) => panic!("failed to get cached finalization: {e}"), + } + } + None + } + + /// Looks for a block (verified or notarized). + pub(crate) async fn find_block(&self, commitment: B::Commitment) -> Option { + // Check in reverse order + for cache in self.caches.values().rev() { + // Check verified blocks + if let Some(block) = cache + .verified_blocks + .get(Identifier::Key(&commitment)) + .await + .expect("failed to get verified block") + { + return Some(block); + } + + // Check notarized blocks + if let Some(block) = cache + .notarized_blocks + .get(Identifier::Key(&commitment)) + .await + .expect("failed to get notarized block") + { + return Some(block); + } + } + None + } + + /// Prune the caches below the given round. + pub(crate) async fn prune(&mut self, round: Round) { + // Remove and close prunable archives from older epochs + let new_floor = round.epoch(); + let old_epochs: Vec = self + .caches + .keys() + .copied() + .filter(|epoch| *epoch < new_floor) + .collect(); + for epoch in old_epochs.iter() { + let Cache:: { + verified_blocks: vb, + notarized_blocks: nb, + notarizations: nv, + finalizations: fv, + .. + } = self.caches.remove(epoch).unwrap(); + vb.destroy().await.expect("failed to destroy vb"); + nb.destroy().await.expect("failed to destroy nb"); + nv.destroy().await.expect("failed to destroy nv"); + fv.destroy().await.expect("failed to destroy fv"); + } + + // Update metadata if necessary + let (floor, ceiling) = self.get_metadata(); + if new_floor > floor { + let new_ceiling = max(ceiling, new_floor); + self.set_metadata(new_floor, new_ceiling).await; + } + + // Prune archives for the given epoch + let min_view = round.view(); + if let Some(prunable) = self.caches.get_mut(&round.epoch()) { + prunable.prune(min_view).await; + } + } +} diff --git a/syncer/src/config.rs b/syncer/src/config.rs new file mode 100644 index 00000000..66f022a8 --- /dev/null +++ b/syncer/src/config.rs @@ -0,0 +1,74 @@ +use commonware_consensus::{simplex::signing_scheme::Scheme, Block}; +use commonware_runtime::buffer::PoolRef; +use std::{ + marker::PhantomData, + num::{NonZeroU64, NonZeroUsize}, +}; +use summit_types::scheme::SchemeProvider; + +/// Marshal configuration. +pub struct Config +where + B: Block, + P: SchemeProvider, + S: Scheme, +{ + /// Provider for epoch-specific signing schemes. + pub scheme_provider: P, + + /// The length of an epoch in number of blocks. + pub epoch_length: u64, + + /// The prefix to use for all partitions. + pub partition_prefix: String, + + /// Size of backfill request/response mailbox. + pub mailbox_size: usize, + + /// Minimum number of views to retain temporary data after the application processes a block. + /// + /// Useful for keeping around information that peers may desire to have. + pub view_retention_timeout: u64, + + /// Namespace for proofs. + pub namespace: Vec, + + /// Prunable archive partition prefix. + pub prunable_items_per_section: NonZeroU64, + + /// The number of items to store per section in immutable archives. + pub immutable_items_per_section: NonZeroU64, + + /// The initial size of the freezer table. + pub freezer_table_initial_size: u32, + + /// The frequency (in number of resizes) at which to check if the freezer table + /// should be resized. + pub freezer_table_resize_frequency: u8, + + /// The number of items to add to the freezer table when resizing. + pub freezer_table_resize_chunk_size: u32, + + /// The target size of the freezer journal. + pub freezer_journal_target_size: u64, + + /// The compression level to use for the freezer journal. + pub freezer_journal_compression: Option, + + /// The buffer pool to use for the freezer journal. + pub freezer_journal_buffer_pool: PoolRef, + + /// The size of the replay buffer for storage archives. + pub replay_buffer: NonZeroUsize, + + /// The size of the write buffer for storage archives. + pub write_buffer: NonZeroUsize, + + /// Codec configuration for block type. + pub block_codec_config: B::Cfg, + + /// Maximum number of blocks to repair at once + pub max_repair: u64, + + pub _marker: PhantomData, +} diff --git a/syncer/src/coordinator.rs b/syncer/src/coordinator.rs deleted file mode 100644 index 2fa90f13..00000000 --- a/syncer/src/coordinator.rs +++ /dev/null @@ -1,25 +0,0 @@ -use commonware_resolver::p2p; -use commonware_utils::Array; - -#[derive(Clone)] -pub struct Coordinator { - participants: Vec

, -} - -impl Coordinator

{ - pub fn new(participants: Vec

) -> Self { - Self { participants } - } -} - -impl p2p::Coordinator for Coordinator

{ - type PublicKey = P; - - fn peers(&self) -> &Vec { - &self.participants - } - - fn peer_set_id(&self) -> u64 { - 0 - } -} diff --git a/syncer/src/finalizer.rs b/syncer/src/finalizer.rs new file mode 100644 index 00000000..7ca2caec --- /dev/null +++ b/syncer/src/finalizer.rs @@ -0,0 +1,128 @@ +use commonware_consensus::{ + Block, Reporter, +}; +use crate::{ingress::orchestrator::Orchestrator, Update}; +use commonware_runtime::{spawn_cell, Clock, ContextCell, Handle, Metrics, Spawner, Storage}; +use commonware_storage::metadata::{self, Metadata}; +use commonware_utils::{fixed_bytes, sequence::FixedBytes}; +use futures::{channel::mpsc, StreamExt}; +use tracing::{debug, error}; + +// The key used to store the last indexed height in the metadata store. +const LATEST_KEY: FixedBytes<1> = fixed_bytes!("00"); + +/// Requests the finalized blocks (in order) from the orchestrator, sends them to the application, +/// waits for confirmation that the application has processed the block. +/// +/// Stores the highest height for which the application has processed. This allows resuming +/// processing from the last processed height after a restart. +pub struct Finalizer< + B: Block, + R: Spawner + Clock + Metrics + Storage, + Z: Reporter>, +> { + context: ContextCell, + + // Application that processes the finalized blocks. + application: Z, + + // Orchestrator that stores the finalized blocks. + orchestrator: Orchestrator, + + // Notifier to indicate that the finalized blocks have been updated and should be re-queried. + notifier_rx: mpsc::Receiver<()>, + + // Metadata store that stores the last indexed height. + metadata: Metadata, u64>, +} + +impl>> + Finalizer +{ + /// Initialize the finalizer. + pub async fn new( + context: R, + partition_prefix: String, + application: Z, + orchestrator: Orchestrator, + notifier_rx: mpsc::Receiver<()>, + ) -> Self { + // Initialize metadata + let metadata = Metadata::init( + context.with_label("metadata"), + metadata::Config { + partition: format!("{partition_prefix}-metadata"), + codec_config: (), + }, + ) + .await + .expect("failed to initialize metadata"); + + Self { + context: ContextCell::new(context), + application, + orchestrator, + notifier_rx, + metadata, + } + } + + /// Start the finalizer. + pub fn start(mut self) -> Handle<()> { + spawn_cell!(self.context, self.run().await) + } + + /// Run the finalizer, which continuously fetches and processes finalized blocks. + async fn run(mut self) { + // Initialize last indexed from metadata store. + // If the key does not exist, we assume the genesis block (height 0) has been indexed. + let mut latest = *self.metadata.get(&LATEST_KEY).unwrap_or(&0); + + // The main loop to process finalized blocks. This loop will hot-spin until a block is + // available, at which point it will process it and continue. If a block is not available, + // it will request a repair and wait for a notification of an update before retrying. + loop { + // The next height to process is the next height after the last processed height. + let height = latest + 1; + + // Attempt to get the next block from the orchestrator. + if let Some(block) = self.orchestrator.get(height).await { + // Sanity-check that the block height is the one we expect. + assert!(block.height() == height, "block height mismatch"); + + // Send the block to the application. + // + // After an unclean shutdown (where the finalizer metadata is not synced after some + // height is processed by the application), it is possible that the application may + // be asked to process a block it has already seen (which it can simply ignore). + let commitment = block.commitment(); + self.application.report(Update::Block(block)).await; + + // Record that we have processed up through this height. + latest = height; + if let Err(e) = self.metadata.put_sync(LATEST_KEY.clone(), latest).await { + error!("failed to update metadata: {e}"); + return; + } + + // Notify the orchestrator that the block has been processed. + self.orchestrator.processed(height, commitment).await; + + // Loop again without waiting for a notification (there may be more to process). + continue; + } + + // We've reached a height at which we have no (finalized) block. + // It may be the case that the block is not finalized yet, or that there is a gap. + // Notify the orchestrator that we're trying to access this block. + self.orchestrator.repair(height).await; + + // Wait for a notification from the orchestrator that new blocks are available. + debug!(height, "waiting to index finalized block"); + let Some(()) = self.notifier_rx.next().await else { + error!("orchestrator closed, shutting down"); + return; + }; + } + } +} diff --git a/syncer/src/handler.rs b/syncer/src/handler.rs deleted file mode 100644 index 55afcdae..00000000 --- a/syncer/src/handler.rs +++ /dev/null @@ -1,67 +0,0 @@ -use crate::key::MultiIndex; -use bytes::Bytes; -use commonware_resolver::{Consumer, p2p::Producer}; -use futures::{ - SinkExt, - channel::{mpsc, oneshot}, -}; - -pub enum Message { - Deliver { - key: MultiIndex, - value: Bytes, - response: oneshot::Sender, - }, - Produce { - key: MultiIndex, - response: oneshot::Sender, - }, -} - -/// Mailbox for resolver -#[derive(Clone)] -pub struct Handler { - sender: mpsc::Sender, -} - -impl Handler { - pub(super) fn new(sender: mpsc::Sender) -> Self { - Self { sender } - } -} - -impl Consumer for Handler { - type Key = MultiIndex; - type Value = Bytes; - type Failure = (); - - async fn deliver(&mut self, key: Self::Key, value: Self::Value) -> bool { - let (response, receiver) = oneshot::channel(); - self.sender - .send(Message::Deliver { - key, - value, - response, - }) - .await - .expect("Failed to send deliver"); - receiver.await.expect("Failed to receive deliver") - } - - async fn failed(&mut self, _: Self::Key, _: Self::Failure) { - // Ignore any failure - } -} - -impl Producer for Handler { - type Key = MultiIndex; - - async fn produce(&mut self, key: Self::Key) -> oneshot::Receiver { - let (response, receiver) = oneshot::channel(); - self.sender - .send(Message::Produce { key, response }) - .await - .expect("Failed to send produce"); - receiver - } -} diff --git a/syncer/src/ingress.rs b/syncer/src/ingress.rs deleted file mode 100644 index b5040385..00000000 --- a/syncer/src/ingress.rs +++ /dev/null @@ -1,219 +0,0 @@ -use commonware_consensus::{ - Reporter, - simplex::types::{Finalization, Notarization}, -}; -use futures::{ - SinkExt as _, - channel::{mpsc, oneshot}, -}; -use summit_types::{Activity, Block, Digest, Signature}; -use tracing::debug; - -pub(crate) type BlockWithFinalization = (Option, Option>); - -pub enum Message { - Get { - view: Option, - payload: Digest, - response: oneshot::Sender, - }, - - Broadcast { - payload: Block, - }, - - StoreVerified { - view: u64, - payload: Block, - }, - - Finalize { - finalization: Finalization, - }, - - Notarize { - notarization: Notarization, - }, -} - -#[derive(Clone)] -pub struct Mailbox { - sender: mpsc::Sender, -} - -impl Mailbox { - pub fn new(sender: mpsc::Sender) -> Self { - Self { sender } - } - - pub async fn get(&mut self, view: Option, payload: Digest) -> oneshot::Receiver { - let (response, receiver) = oneshot::channel(); - self.sender - .send(Message::Get { - view, - payload, - response, - }) - .await - .expect("Failed to send get"); - receiver - } - - pub async fn broadcast(&mut self, payload: Block) { - self.sender - .send(Message::Broadcast { payload }) - .await - .expect("Failed to send broadcast"); - } - - pub async fn store_verified(&mut self, view: u64, payload: Block) { - self.sender - .send(Message::StoreVerified { view, payload }) - .await - .expect("Failed to send lock"); - } -} - -impl Reporter for Mailbox { - type Activity = Activity; - - async fn report(&mut self, activity: Self::Activity) { - // leaving all possible activity branches just for now. I think the only one we need to care about is finalization - // we possibly might need to care about notarization but I will need to look into simplex a bit more to know for sure - match activity { - Activity::Notarize(notarize) => { - // When a single node notarizes a proposal - debug!("Notarize Activity for view {}", notarize.proposal.view); - } - Activity::Notarization(notarization) => { - // when a quorum of nodes nortarized a proposal - debug!( - "Notarization Activity for view {}", - notarization.proposal.view - ); - - let _ = self.sender.send(Message::Notarize { notarization }).await; - } - Activity::Nullify(nullify) => { - // single node votes to skip a view - debug!("Nullify Activity for view {}", nullify.view); - } - Activity::Nullification(nullification) => { - // a quorum of nodes vote to skip a view - debug!("Nullification Activity for view {}", nullification.view); - } - Activity::Finalize(finalize) => { - // a single validator finalizes a proposal - debug!("Finalize Activity for view {}", finalize.proposal.view); - } - Activity::Finalization(finalization) => { - // a quorum of validators finalize a proposal - debug!( - "Finalization Activity for view {}", - finalization.proposal.view - ); - - // Simplex checks the signature before here so we shouldnt have to - let _ = self.sender.send(Message::Finalize { finalization }).await; - } - Activity::ConflictingNotarize(conflicting_notarize) => { - // Evidence byzantine behavior - debug!( - "Conflicting Notarize Activity for view {}", - conflicting_notarize.view - ); - } - Activity::ConflictingFinalize(conflicting_finalize) => { - // evidence of byzantine behavior - debug!( - "Conflicting Finalize Activity for view {}", - conflicting_finalize.view - ); - } - Activity::NullifyFinalize(nullify_finalize) => { - // evidence of byzantine behavior - debug!( - "Nullify Finalize Activity for view {}", - nullify_finalize.proposal.view - ); - } - } - } -} - -/// Enum representing the different types of messages that the `Finalizer` loop -/// can send to the inner actor loop. -/// -/// We break this into a separate enum to establish a separate priority for consensus messages. -pub enum Orchestration { - Get { - next: u64, - result: oneshot::Sender>, - }, - GetWithFinalization { - next: u64, - result: oneshot::Sender, - }, - Processed { - next: u64, - digest: Digest, - }, - Repair { - next: u64, - result: oneshot::Sender, - }, -} - -#[derive(Clone)] -pub struct Orchestrator { - sender: mpsc::Sender, -} - -impl Orchestrator { - pub fn new(sender: mpsc::Sender) -> Self { - Self { sender } - } - - pub async fn get(&mut self, next: u64) -> Option { - let (response, receiver) = oneshot::channel(); - self.sender - .send(Orchestration::Get { - next, - result: response, - }) - .await - .expect("Failed to send get"); - receiver.await.unwrap() - } - - pub async fn get_with_finalized(&mut self, next: u64) -> BlockWithFinalization { - let (response, receiver) = oneshot::channel(); - self.sender - .send(Orchestration::GetWithFinalization { - next, - result: response, - }) - .await - .expect("Failed to send get with finalized"); - receiver.await.unwrap() - } - - pub async fn processed(&mut self, next: u64, digest: Digest) { - self.sender - .send(Orchestration::Processed { next, digest }) - .await - .expect("Failed to send processed"); - } - - pub async fn repair(&mut self, next: u64) -> bool { - let (response, receiver) = oneshot::channel(); - self.sender - .send(Orchestration::Repair { - next, - result: response, - }) - .await - .expect("Failed to send repair"); - receiver.await.unwrap() - } -} diff --git a/syncer/src/ingress/handler.rs b/syncer/src/ingress/handler.rs new file mode 100644 index 00000000..a15280a4 --- /dev/null +++ b/syncer/src/ingress/handler.rs @@ -0,0 +1,524 @@ +use commonware_consensus::{types::Round, Block}; +use bytes::{Buf, BufMut, Bytes}; +use commonware_codec::{EncodeSize, Error as CodecError, Read, ReadExt, Write}; +use commonware_resolver::{p2p::Producer, Consumer}; +use commonware_utils::Span; +use futures::{ + channel::{mpsc, oneshot}, + SinkExt, +}; +use std::{ + fmt::{Debug, Display}, + hash::{Hash, Hasher}, +}; +use tracing::error; + +/// The subject of a backfill request. +const BLOCK_REQUEST: u8 = 0; +const FINALIZED_REQUEST: u8 = 1; +const NOTARIZED_REQUEST: u8 = 2; + +/// Messages sent from the resolver's [Consumer]/[Producer] implementation +/// to the marshal [Actor](super::super::actor::Actor). +pub enum Message { + /// A request to deliver a value for a given key. + Deliver { + /// The key of the value being delivered. + key: Request, + /// The value being delivered. + value: Bytes, + /// A channel to send the result of the delivery (true for success). + response: oneshot::Sender, + }, + /// A request to produce a value for a given key. + Produce { + /// The key of the value to produce. + key: Request, + /// A channel to send the produced value. + response: oneshot::Sender, + }, +} + +/// A handler that forwards requests from the resolver to the marshal actor. +/// +/// This struct implements the [Consumer] and [Producer] traits from the +/// resolver, and acts as a bridge to the main actor loop. +#[derive(Clone)] +pub struct Handler { + sender: mpsc::Sender>, +} + +impl Handler { + /// Creates a new handler. + pub fn new(sender: mpsc::Sender>) -> Self { + Self { sender } + } +} + +impl Consumer for Handler { + type Key = Request; + type Value = Bytes; + type Failure = (); + + async fn deliver(&mut self, key: Self::Key, value: Self::Value) -> bool { + let (response, receiver) = oneshot::channel(); + if self + .sender + .send(Message::Deliver { + key, + value, + response, + }) + .await + .is_err() + { + error!("failed to send deliver message to actor: receiver dropped"); + return false; + } + receiver.await.unwrap_or(false) + } + + async fn failed(&mut self, _: Self::Key, _: Self::Failure) { + // We don't need to do anything on failure, the resolver will retry. + } +} + +impl Producer for Handler { + type Key = Request; + + async fn produce(&mut self, key: Self::Key) -> oneshot::Receiver { + let (response, receiver) = oneshot::channel(); + if self + .sender + .send(Message::Produce { key, response }) + .await + .is_err() + { + error!("failed to send produce message to actor: receiver dropped"); + } + receiver + } +} + +/// A request for backfilling data. +#[derive(Clone)] +pub enum Request { + Block(B::Commitment), + Finalized { height: u64 }, + Notarized { round: Round }, +} + +impl Request { + /// The subject of the request. + fn subject(&self) -> u8 { + match self { + Self::Block(_) => BLOCK_REQUEST, + Self::Finalized { .. } => FINALIZED_REQUEST, + Self::Notarized { .. } => NOTARIZED_REQUEST, + } + } + + /// The predicate to use when pruning subjects related to this subject. + /// + /// Specifically, any subjects unrelated will be left unmodified. Any related + /// subjects will be pruned if they are "less than or equal to" this subject. + pub fn predicate(&self) -> impl Fn(&Request) -> bool + Send + 'static { + let cloned = self.clone(); + move |s| match (&cloned, &s) { + (Self::Block(_), _) => unreachable!("we should never retain by block"), + (Self::Finalized { height: mine }, Self::Finalized { height: theirs }) => { + *theirs > *mine + } + (Self::Finalized { .. }, _) => true, + (Self::Notarized { round: mine }, Self::Notarized { round: theirs }) => *theirs > *mine, + (Self::Notarized { .. }, _) => true, + } + } +} + +impl Write for Request { + fn write(&self, buf: &mut impl BufMut) { + self.subject().write(buf); + match self { + Self::Block(commitment) => commitment.write(buf), + Self::Finalized { height } => height.write(buf), + Self::Notarized { round } => round.write(buf), + } + } +} + +impl Read for Request { + type Cfg = (); + + fn read_cfg(buf: &mut impl Buf, _: &()) -> Result { + let request = match u8::read(buf)? { + BLOCK_REQUEST => Self::Block(B::Commitment::read(buf)?), + FINALIZED_REQUEST => Self::Finalized { + height: u64::read(buf)?, + }, + NOTARIZED_REQUEST => Self::Notarized { + round: Round::read(buf)?, + }, + i => return Err(CodecError::InvalidEnum(i)), + }; + Ok(request) + } +} + +impl EncodeSize for Request { + fn encode_size(&self) -> usize { + 1 + match self { + Self::Block(block) => block.encode_size(), + Self::Finalized { height } => height.encode_size(), + Self::Notarized { round } => round.encode_size(), + } + } +} + +impl Span for Request {} + +impl PartialEq for Request { + fn eq(&self, other: &Self) -> bool { + match (&self, &other) { + (Self::Block(a), Self::Block(b)) => a == b, + (Self::Finalized { height: a }, Self::Finalized { height: b }) => a == b, + (Self::Notarized { round: a }, Self::Notarized { round: b }) => a == b, + _ => false, + } + } +} + +impl Eq for Request {} + +impl Ord for Request { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + match (&self, &other) { + (Self::Block(a), Self::Block(b)) => a.cmp(b), + (Self::Finalized { height: a }, Self::Finalized { height: b }) => a.cmp(b), + (Self::Notarized { round: a }, Self::Notarized { round: b }) => a.cmp(b), + (a, b) => a.subject().cmp(&b.subject()), + } + } +} + +impl PartialOrd for Request { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Hash for Request { + fn hash(&self, state: &mut H) { + match self { + Self::Block(commitment) => commitment.hash(state), + Self::Finalized { height } => height.hash(state), + Self::Notarized { round } => round.hash(state), + } + } +} + +impl Display for Request { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Block(commitment) => write!(f, "Block({commitment:?})"), + Self::Finalized { height } => write!(f, "Finalized({height:?})"), + Self::Notarized { round } => write!(f, "Notarized({round:?})"), + } + } +} + +impl Debug for Request { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Block(commitment) => write!(f, "Block({commitment:?})"), + Self::Finalized { height } => write!(f, "Finalized({height:?})"), + Self::Notarized { round } => write!(f, "Notarized({round:?})"), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mocks::block::Block as TestBlock; + use commonware_codec::{Encode, ReadExt}; + use commonware_cryptography::{ + sha256::{Digest as Sha256Digest, Sha256}, + Hasher as _, + }; + use std::collections::BTreeSet; + + type B = TestBlock; + + #[test] + fn test_subject_block_encoding() { + let commitment = Sha256::hash(b"test"); + let request = Request::::Block(commitment); + + // Test encoding + let encoded = request.encode(); + assert_eq!(encoded.len(), 33); // 1 byte for enum variant + 32 bytes for commitment + assert_eq!(encoded[0], 0); // Block variant + + // Test decoding + let mut buf = encoded.as_ref(); + let decoded = Request::::read(&mut buf).unwrap(); + assert_eq!(request, decoded); + assert_eq!(decoded, Request::Block(commitment)); + } + + #[test] + fn test_subject_finalized_encoding() { + let height = 12345u64; + let request = Request::::Finalized { height }; + + // Test encoding + let encoded = request.encode(); + assert_eq!(encoded[0], 1); // Finalized variant + + // Test decoding + let mut buf = encoded.as_ref(); + let decoded = Request::::read(&mut buf).unwrap(); + assert_eq!(request, decoded); + assert_eq!(decoded, Request::Finalized { height }); + } + + #[test] + fn test_subject_notarized_encoding() { + let round = Round::from((67890, 12345)); + let request = Request::::Notarized { round }; + + // Test encoding + let encoded = request.encode(); + assert_eq!(encoded[0], 2); // Notarized variant + + // Test decoding + let mut buf = encoded.as_ref(); + let decoded = Request::::read(&mut buf).unwrap(); + assert_eq!(request, decoded); + assert_eq!(decoded, Request::Notarized { round }); + } + + #[test] + fn test_subject_hash() { + use std::collections::HashSet; + + let r1 = Request::::Finalized { height: 100 }; + let r2 = Request::::Finalized { height: 100 }; + let r3 = Request::::Finalized { height: 200 }; + + let mut set = HashSet::new(); + set.insert(r1); + assert!(!set.insert(r2)); // Should not insert duplicate + assert!(set.insert(r3)); // Should insert different value + } + + #[test] + fn test_subject_predicate() { + let r1 = Request::::Finalized { height: 100 }; + let r2 = Request::::Finalized { height: 200 }; + let r3 = Request::::Notarized { + round: Round::from((333, 150)), + }; + + let predicate = r1.predicate(); + assert!(predicate(&r2)); // r2.height > r1.height + assert!(predicate(&r3)); // Different variant (notarized) + + let r1_same = Request::::Finalized { height: 100 }; + assert!(!predicate(&r1_same)); // Same height, should not pass + } + + #[test] + fn test_encode_size() { + let commitment = Sha256::hash(&[0u8; 32]); + let r1 = Request::::Block(commitment); + let r2 = Request::::Finalized { height: u64::MAX }; + let r3 = Request::::Notarized { + round: Round::from((333, 0)), + }; + + // Verify encode_size matches actual encoded length + assert_eq!(r1.encode_size(), r1.encode().len()); + assert_eq!(r2.encode_size(), r2.encode().len()); + assert_eq!(r3.encode_size(), r3.encode().len()); + } + + #[test] + fn test_request_ord_same_variant() { + // Test ordering within the same variant + let commitment1 = Sha256::hash(b"test1"); + let commitment2 = Sha256::hash(b"test2"); + let block1 = Request::::Block(commitment1); + let block2 = Request::::Block(commitment2); + + // Block ordering depends on commitment ordering + if commitment1 < commitment2 { + assert!(block1 < block2); + assert!(block2 > block1); + } else { + assert!(block1 > block2); + assert!(block2 < block1); + } + + // Finalized ordering by height + let fin1 = Request::::Finalized { height: 100 }; + let fin2 = Request::::Finalized { height: 200 }; + let fin3 = Request::::Finalized { height: 200 }; + + assert!(fin1 < fin2); + assert!(fin2 > fin1); + assert_eq!(fin2.cmp(&fin3), std::cmp::Ordering::Equal); + + // Notarized ordering by view + let not1 = Request::::Notarized { + round: Round::from((333, 50)), + }; + let not2 = Request::::Notarized { + round: Round::from((333, 150)), + }; + let not3 = Request::::Notarized { + round: Round::from((333, 150)), + }; + + assert!(not1 < not2); + assert!(not2 > not1); + assert_eq!(not2.cmp(¬3), std::cmp::Ordering::Equal); + } + + #[test] + fn test_request_ord_cross_variant() { + let commitment = Sha256::hash(b"test"); + let block = Request::::Block(commitment); + let finalized = Request::::Finalized { height: 100 }; + let notarized = Request::::Notarized { + round: Round::from((333, 200)), + }; + + // Block < Finalized < Notarized + assert!(block < finalized); + assert!(block < notarized); + assert!(finalized < notarized); + + assert!(finalized > block); + assert!(notarized > block); + assert!(notarized > finalized); + + // Test all combinations + assert_eq!(block.cmp(&finalized), std::cmp::Ordering::Less); + assert_eq!(block.cmp(¬arized), std::cmp::Ordering::Less); + assert_eq!(finalized.cmp(¬arized), std::cmp::Ordering::Less); + assert_eq!(finalized.cmp(&block), std::cmp::Ordering::Greater); + assert_eq!(notarized.cmp(&block), std::cmp::Ordering::Greater); + assert_eq!(notarized.cmp(&finalized), std::cmp::Ordering::Greater); + } + + #[test] + fn test_request_partial_ord() { + let commitment1 = Sha256::hash(b"test1"); + let commitment2 = Sha256::hash(b"test2"); + let block1 = Request::::Block(commitment1); + let block2 = Request::::Block(commitment2); + let finalized = Request::::Finalized { height: 100 }; + let notarized = Request::::Notarized { + round: Round::from((333, 200)), + }; + + // PartialOrd should always return Some + assert!(block1.partial_cmp(&block2).is_some()); + assert!(block1.partial_cmp(&finalized).is_some()); + assert!(finalized.partial_cmp(¬arized).is_some()); + + // Verify consistency with Ord + assert_eq!( + block1.partial_cmp(&finalized), + Some(std::cmp::Ordering::Less) + ); + assert_eq!( + finalized.partial_cmp(¬arized), + Some(std::cmp::Ordering::Less) + ); + assert_eq!( + notarized.partial_cmp(&block1), + Some(std::cmp::Ordering::Greater) + ); + } + + #[test] + fn test_request_ord_sorting() { + let commitment1 = Sha256::hash(b"a"); + let commitment2 = Sha256::hash(b"b"); + let commitment3 = Sha256::hash(b"c"); + + let requests = vec![ + Request::::Notarized { + round: Round::from((333, 300)), + }, + Request::::Block(commitment2), + Request::::Finalized { height: 200 }, + Request::::Block(commitment1), + Request::::Notarized { + round: Round::from((333, 250)), + }, + Request::::Finalized { height: 100 }, + Request::::Block(commitment3), + ]; + + // Sort using BTreeSet (uses Ord) + let sorted: Vec<_> = requests + .into_iter() + .collect::>() + .into_iter() + .collect(); + + // Verify order: all Blocks first (sorted by commitment), then Finalized (by height), then Notarized (by view) + assert_eq!(sorted.len(), 7); + + // Check that all blocks come first + assert!(matches!(sorted[0], Request::::Block(_))); + assert!(matches!(sorted[1], Request::::Block(_))); + assert!(matches!(sorted[2], Request::::Block(_))); + + // Check that finalized come next + assert_eq!(sorted[3], Request::::Finalized { height: 100 }); + assert_eq!(sorted[4], Request::::Finalized { height: 200 }); + + // Check that notarized come last + assert_eq!( + sorted[5], + Request::::Notarized { + round: Round::from((333, 250)) + } + ); + assert_eq!( + sorted[6], + Request::::Notarized { + round: Round::from((333, 300)) + } + ); + } + + #[test] + fn test_request_ord_edge_cases() { + // Test with extreme values + let min_finalized = Request::::Finalized { height: 0 }; + let max_finalized = Request::::Finalized { height: u64::MAX }; + let min_notarized = Request::::Notarized { + round: Round::from((333, 0)), + }; + let max_notarized = Request::::Notarized { + round: Round::from((333, u64::MAX)), + }; + + assert!(min_finalized < max_finalized); + assert!(min_notarized < max_notarized); + assert!(max_finalized < min_notarized); + + // Test self-comparison + let commitment = Sha256::hash(b"self"); + let block = Request::::Block(commitment); + assert_eq!(block.cmp(&block), std::cmp::Ordering::Equal); + assert_eq!(min_finalized.cmp(&min_finalized), std::cmp::Ordering::Equal); + assert_eq!(max_notarized.cmp(&max_notarized), std::cmp::Ordering::Equal); + } +} diff --git a/syncer/src/ingress/mailbox.rs b/syncer/src/ingress/mailbox.rs new file mode 100644 index 00000000..4097b25c --- /dev/null +++ b/syncer/src/ingress/mailbox.rs @@ -0,0 +1,282 @@ +use commonware_consensus::{ + simplex::{ + signing_scheme::Scheme, + types::{Activity, Finalization, Notarization}, + }, + types::Round, + Block, Reporter, +}; +use commonware_cryptography::Digest; +use commonware_storage::archive; +use futures::{ + channel::{mpsc, oneshot}, + SinkExt, +}; +use tracing::error; + +/// An identifier for a block request. +pub enum Identifier { + /// The height of the block to retrieve. + Height(u64), + /// The commitment of the block to retrieve. + Commitment(D), + /// The highest finalized block. It may be the case that marshal does not have some of the + /// blocks below this height. + Latest, +} + +// Allows using u64 directly for convenience. +impl From for Identifier { + fn from(src: u64) -> Self { + Self::Height(src) + } +} + +// Allows using &Digest directly for convenience. +impl From<&D> for Identifier { + fn from(src: &D) -> Self { + Self::Commitment(*src) + } +} + +// Allows using archive identifiers directly for convenience. +impl From> for Identifier { + fn from(src: archive::Identifier<'_, D>) -> Self { + match src { + archive::Identifier::Index(index) => Self::Height(index), + archive::Identifier::Key(key) => Self::Commitment(*key), + } + } +} + +/// Messages sent to the marshal [Actor](super::super::actor::Actor). +/// +/// These messages are sent from the consensus engine and other parts of the +/// system to drive the state of the marshal. +pub(crate) enum Message { + // -------------------- Application Messages -------------------- + /// A request to retrieve the (height, commitment) of a block by its identifier. + /// The block must be finalized; returns `None` if the block is not finalized. + GetInfo { + /// The identifier of the block to get the information of. + identifier: Identifier, + /// A channel to send the retrieved (height, commitment). + response: oneshot::Sender>, + }, + /// A request to retrieve a block by its identifier. + /// + /// Requesting by [Identifier::Height] or [Identifier::Latest] will only return finalized + /// blocks, whereas requesting by commitment may return non-finalized or even unverified blocks. + GetBlock { + /// The identifier of the block to retrieve. + identifier: Identifier, + /// A channel to send the retrieved block. + response: oneshot::Sender>, + }, + /// A request to retrieve a finalization by height. + GetFinalization { + /// The height of the finalization to retrieve. + height: u64, + /// A channel to send the retrieved finalization. + response: oneshot::Sender>>, + }, + /// A request to retrieve a block by its commitment. + Subscribe { + /// The view in which the block was notarized. This is an optimization + /// to help locate the block. + round: Option, + /// The commitment of the block to retrieve. + commitment: B::Commitment, + /// A channel to send the retrieved block. + response: oneshot::Sender, + }, + /// A request to broadcast a block to all peers. + Broadcast { + /// The block to broadcast. + block: B, + }, + /// A notification that a block has been verified by the application. + Verified { + /// The round in which the block was verified. + round: Round, + /// The verified block. + block: B, + }, + + // -------------------- Consensus Engine Messages -------------------- + /// A notarization from the consensus engine. + Notarization { + /// The notarization. + notarization: Notarization, + }, + /// A finalization from the consensus engine. + Finalization { + /// The finalization. + finalization: Finalization, + }, +} + +/// A mailbox for sending messages to the marshal [Actor](super::super::actor::Actor). +#[derive(Clone)] +pub struct Mailbox { + sender: mpsc::Sender>, +} + +impl Mailbox { + /// Creates a new mailbox. + pub(crate) fn new(sender: mpsc::Sender>) -> Self { + Self { sender } + } + + /// A request to retrieve the information about the highest finalized block. + pub async fn get_info( + &mut self, + identifier: impl Into>, + ) -> Option<(u64, B::Commitment)> { + let (tx, rx) = oneshot::channel(); + if self + .sender + .send(Message::GetInfo { + identifier: identifier.into(), + response: tx, + }) + .await + .is_err() + { + error!("failed to send get info message to actor: receiver dropped"); + } + match rx.await { + Ok(result) => result, + Err(_) => { + error!("failed to get info: receiver dropped"); + None + } + } + } + + /// A best-effort attempt to retrieve a given block from local + /// storage. It is not an indication to go fetch the block from the network. + pub async fn get_block( + &mut self, + identifier: impl Into>, + ) -> Option { + let (tx, rx) = oneshot::channel(); + if self + .sender + .send(Message::GetBlock { + identifier: identifier.into(), + response: tx, + }) + .await + .is_err() + { + error!("failed to send get block message to actor: receiver dropped"); + } + match rx.await { + Ok(result) => result, + Err(_) => { + error!("failed to get block: receiver dropped"); + None + } + } + } + + /// A best-effort attempt to retrieve a given [Finalization] from local + /// storage. It is not an indication to go fetch the [Finalization] from the network. + pub async fn get_finalization( + &mut self, + height: u64, + ) -> Option> { + let (tx, rx) = oneshot::channel(); + if self + .sender + .send(Message::GetFinalization { + height, + response: tx, + }) + .await + .is_err() + { + error!("failed to send get finalization message to actor: receiver dropped"); + } + match rx.await { + Ok(result) => result, + Err(_) => { + error!("failed to get finalization: receiver dropped"); + None + } + } + } + + /// A request to retrieve a block by its commitment. + /// + /// If the block is found available locally, the block will be returned immediately. + /// + /// If the block is not available locally, the request will be registered and the caller will + /// be notified when the block is available. If the block is not finalized, it's possible that + /// it may never become available. + /// + /// The oneshot receiver should be dropped to cancel the subscription. + pub async fn subscribe( + &mut self, + round: Option, + commitment: B::Commitment, + ) -> oneshot::Receiver { + let (tx, rx) = oneshot::channel(); + if self + .sender + .send(Message::Subscribe { + round, + commitment, + response: tx, + }) + .await + .is_err() + { + error!("failed to send subscribe message to actor: receiver dropped"); + } + rx + } + + /// Broadcast indicates that a block should be sent to all peers. + pub async fn broadcast(&mut self, block: B) { + if self + .sender + .send(Message::Broadcast { block }) + .await + .is_err() + { + error!("failed to send broadcast message to actor: receiver dropped"); + } + } + + /// Notifies the actor that a block has been verified. + pub async fn verified(&mut self, round: Round, block: B) { + if self + .sender + .send(Message::Verified { round, block }) + .await + .is_err() + { + error!("failed to send verified message to actor: receiver dropped"); + } + } +} + +impl Reporter for Mailbox { + type Activity = Activity; + + async fn report(&mut self, activity: Self::Activity) { + let message = match activity { + Activity::Notarization(notarization) => Message::Notarization { notarization }, + Activity::Finalization(finalization) => Message::Finalization { finalization }, + _ => { + // Ignore other activity types + return; + } + }; + if self.sender.send(message).await.is_err() { + error!("failed to report activity to actor: receiver dropped"); + } + } +} diff --git a/syncer/src/ingress/mod.rs b/syncer/src/ingress/mod.rs new file mode 100644 index 00000000..c4f47e60 --- /dev/null +++ b/syncer/src/ingress/mod.rs @@ -0,0 +1,3 @@ +pub mod handler; +pub mod mailbox; +pub(crate) mod orchestrator; diff --git a/syncer/src/ingress/orchestrator.rs b/syncer/src/ingress/orchestrator.rs new file mode 100644 index 00000000..efaa8266 --- /dev/null +++ b/syncer/src/ingress/orchestrator.rs @@ -0,0 +1,87 @@ +use crate::Block; +use futures::{ + channel::{mpsc, oneshot}, + SinkExt, +}; +use tracing::error; + +/// Messages sent from the finalizer task to the main actor loop. +/// +/// We break this into a separate enum to establish a separate priority for +/// finalizer messages over consensus messages. +pub enum Orchestration { + /// A request to get the next finalized block. + Get { + /// The height of the block to get. + height: u64, + /// A channel to send the block, if found. + result: oneshot::Sender>, + }, + /// A notification that a block has been processed by the application. + Processed { + /// The height of the processed block. + height: u64, + /// The digest of the processed block. + digest: B::Commitment, + }, + /// A request to repair a gap in the finalized block sequence. + Repair { + /// The height at which to start repairing. + height: u64, + }, +} + +/// A handle for the finalizer to communicate with the main actor loop. +#[derive(Clone)] +pub struct Orchestrator { + sender: mpsc::Sender>, +} + +impl Orchestrator { + /// Creates a new orchestrator. + pub fn new(sender: mpsc::Sender>) -> Self { + Self { sender } + } + + /// Gets the finalized block at the given height. + pub async fn get(&mut self, height: u64) -> Option { + let (response, receiver) = oneshot::channel(); + if self + .sender + .send(Orchestration::Get { + height, + result: response, + }) + .await + .is_err() + { + error!("failed to send get message to actor: receiver dropped"); + return None; + } + receiver.await.unwrap_or(None) + } + + /// Notifies the actor that a block has been processed. + pub async fn processed(&mut self, height: u64, digest: B::Commitment) { + if self + .sender + .send(Orchestration::Processed { height, digest }) + .await + .is_err() + { + error!("failed to send processed message to actor: receiver dropped"); + } + } + + /// Attempts to repair a gap in the block sequence. + pub async fn repair(&mut self, height: u64) { + if self + .sender + .send(Orchestration::Repair { height }) + .await + .is_err() + { + error!("failed to send repair message to actor: receiver dropped"); + } + } +} diff --git a/syncer/src/key.rs b/syncer/src/key.rs deleted file mode 100644 index 8971d2fb..00000000 --- a/syncer/src/key.rs +++ /dev/null @@ -1,127 +0,0 @@ -use bytes::{Buf, BufMut}; -use commonware_codec::{Error, FixedSize, Read, ReadExt, Write}; -use commonware_utils::{Array, Span}; -use std::{ - cmp::{Ord, PartialOrd}, - fmt::{Debug, Display}, - hash::Hash, - ops::Deref, -}; -use summit_types::Digest; - -const SIZE: usize = u8::SIZE + Digest::SIZE; - -pub enum Value { - Notarized(u64), - Finalized(u64), - Digest(Digest), -} - -#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] -#[repr(transparent)] -pub struct MultiIndex([u8; SIZE]); - -impl MultiIndex { - pub fn new(value: Value) -> Self { - let mut bytes = [0; SIZE]; - match value { - Value::Notarized(value) => { - bytes[0] = 0; - bytes[1..9].copy_from_slice(&value.to_be_bytes()); - } - Value::Finalized(value) => { - bytes[0] = 1; - bytes[1..9].copy_from_slice(&value.to_be_bytes()); - } - Value::Digest(digest) => { - bytes[0] = 2; - bytes[1..].copy_from_slice(&digest); - } - } - Self(bytes) - } - - pub fn to_value(&self) -> Value { - match self.0[0] { - 0 => { - let bytes: [u8; u64::SIZE] = self.0[1..9].try_into().unwrap(); - let value = u64::from_be_bytes(bytes); - Value::Notarized(value) - } - 1 => { - let bytes: [u8; u64::SIZE] = self.0[1..9].try_into().unwrap(); - let value = u64::from_be_bytes(bytes); - Value::Finalized(value) - } - 2 => { - let bytes: [u8; Digest::SIZE] = self.0[1..].try_into().unwrap(); - let digest = Digest::from(bytes); - Value::Digest(digest) - } - _ => unreachable!(), - } - } -} - -impl Span for MultiIndex {} - -impl Array for MultiIndex {} - -impl Write for MultiIndex { - fn write(&self, writer: &mut impl BufMut) { - writer.put_slice(&self.0); - } -} - -impl Read for MultiIndex { - type Cfg = (); - - fn read_cfg(reader: &mut impl Buf, _: &Self::Cfg) -> Result { - let bytes = <[u8; SIZE]>::read(reader)?; - Ok(Self(bytes)) - } -} - -impl FixedSize for MultiIndex { - const SIZE: usize = SIZE; -} - -impl Debug for MultiIndex { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self.0[0] { - 0 => { - let bytes: [u8; u64::SIZE] = self.0[1..9].try_into().unwrap(); - write!(f, "notarized({})", u64::from_be_bytes(bytes)) - } - 1 => { - let bytes: [u8; u64::SIZE] = self.0[1..9].try_into().unwrap(); - write!(f, "finalized({})", u64::from_be_bytes(bytes)) - } - 2 => { - let bytes: [u8; Digest::SIZE] = self.0[1..].try_into().unwrap(); - write!(f, "digest({})", Digest::from(bytes)) - } - _ => unreachable!(), - } - } -} - -impl Display for MultiIndex { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - Debug::fmt(self, f) - } -} - -impl AsRef<[u8]> for MultiIndex { - fn as_ref(&self) -> &[u8] { - &self.0 - } -} - -impl Deref for MultiIndex { - type Target = [u8]; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} diff --git a/syncer/src/lib.rs b/syncer/src/lib.rs index 0df91469..9ddc4eaf 100644 --- a/syncer/src/lib.rs +++ b/syncer/src/lib.rs @@ -1,34 +1,1023 @@ +//! Ordered delivery of finalized blocks. +//! +//! # Architecture +//! +//! The core of the module is the [actor::Actor]. It marshals the finalized blocks into order by: +//! +//! - Receiving uncertified blocks from a broadcast mechanism +//! - Receiving notarizations and finalizations from consensus +//! - Reconstructing a total order of finalized blocks +//! - Providing a backfill mechanism for missing blocks +//! +//! The actor interacts with four main components: +//! - [crate::Reporter]: Receives ordered, finalized blocks at-least-once +//! - [crate::simplex]: Provides consensus messages +//! - Application: Provides verified blocks +//! - [commonware_broadcast::buffered]: Provides uncertified blocks received from the network +//! - [commonware_resolver::Resolver]: Provides a backfill mechanism for missing blocks +//! +//! # Design +//! +//! ## Delivery +//! +//! The actor will deliver a block to the reporter at-least-once. The reporter should be prepared to +//! handle duplicate deliveries. However the blocks will be in order. +//! +//! ## Finalization +//! +//! The actor uses a view-based model to track the state of the chain. Each view corresponds +//! to a potential block in the chain. The actor will only finalize a block (and its ancestors) +//! if it has a corresponding finalization from consensus. +//! +//! ## Backfill +//! +//! The actor provides a backfill mechanism for missing blocks. If the actor notices a gap in its +//! knowledge of finalized blocks, it will request the missing blocks from its peers. This ensures +//! that the actor can catch up to the rest of the network if it falls behind. +//! +//! ## Storage +//! +//! The actor uses a combination of prunable and immutable storage to store blocks and +//! finalizations. Prunable storage is used to store data that is only needed for a short +//! period of time, such as unverified blocks or notarizations. Immutable storage is used to +//! store data that needs to be persisted indefinitely, such as finalized blocks. This allows +//! the actor to keep its storage footprint small while still providing a full history of the +//! chain. +//! +//! ## Limitations and Future Work +//! +//! - Only works with [crate::simplex] rather than general consensus. +//! - Assumes at-most one notarization per view, incompatible with some consensus protocols. +//! - No state sync supported. Will attempt to sync every block in the history of the chain. +//! - Stores the entire history of the chain, which requires indefinite amounts of disk space. +//! - Uses [`broadcast::buffered`](`commonware_broadcast::buffered`) for broadcasting and receiving +//! uncertified blocks from the network. + pub mod actor; -pub use actor::*; +pub use actor::Actor; +pub mod cache; +pub mod config; +pub use config::Config; +pub mod finalizer; +pub use finalizer::Finalizer; pub mod ingress; -use commonware_runtime::buffer::PoolRef; -pub use ingress::*; -use summit_types::PublicKey; -use summit_types::registry::Registry; -use tokio_util::sync::CancellationToken; +pub use ingress::mailbox::Mailbox; +pub mod resolver; + +use commonware_consensus::Block; + +/// An update reported to the application, either a new finalized tip or a finalized block. +/// +/// Finalized tips are reported as soon as known, whether or not we hold all blocks up to that height. +/// Finalized blocks are reported to the application in monotonically increasing order (no gaps permitted). +#[derive(Clone, Debug)] +pub enum Update { + /// A new finalized tip. + Tip(u64, B::Commitment), + /// A new finalized block. + Block(B), +} + +#[cfg(test)] +pub mod mocks; + +#[cfg(test)] +mod tests { + use super::{ + actor, + config::Config, + mocks::{application::Application, block::Block}, + resolver::p2p as resolver, + }; + use summit_types::scheme::SchemeProvider; + use commonware_broadcast::buffered; + use commonware_cryptography::{ + bls12381::primitives::variant::MinPk, + ed25519::PublicKey, + sha256::{Digest as Sha256Digest, Sha256}, + Digestible, Hasher as _, + }; + use commonware_macros::test_traced; + use commonware_p2p::{ + simulated::{self, Link, Network, Oracle}, + utils::requester, + Manager, + }; + use commonware_runtime::{buffer::PoolRef, deterministic, Clock, Metrics, Runner}; + use commonware_utils::{NZUsize, NZU64}; + use governor::Quota; + use rand::{seq::SliceRandom, Rng}; + use std::{ + collections::BTreeMap, + marker::PhantomData, + num::{NonZeroU32, NonZeroUsize}, + sync::Arc, + time::Duration, + }; + use commonware_consensus::simplex::mocks::fixtures::{bls12381_threshold, Fixture}; + use commonware_consensus::simplex::signing_scheme::bls12381_threshold; + use commonware_consensus::simplex::types::{Activity, Finalization, Finalize, Notarization, Notarize, Proposal}; + use commonware_consensus::types::{Epoch, Round}; + use commonware_consensus::{utils, Block as _, Reporter}; + use crate::ingress::mailbox::Identifier; + + type D = Sha256Digest; + type B = Block; + type K = PublicKey; + type V = MinPk; + type S = bls12381_threshold::Scheme; + type P = ConstantSchemeProvider; + + #[derive(Clone)] + struct ConstantSchemeProvider(Arc); + impl SchemeProvider for ConstantSchemeProvider { + type Scheme = S; + + fn scheme(&self, _: Epoch) -> Option> { + Some(self.0.clone()) + } + } + impl From for ConstantSchemeProvider { + fn from(scheme: S) -> Self { + Self(Arc::new(scheme)) + } + } + + const PAGE_SIZE: NonZeroUsize = NZUsize!(1024); + const PAGE_CACHE_SIZE: NonZeroUsize = NZUsize!(10); + const NAMESPACE: &[u8] = b"test"; + const NUM_VALIDATORS: u32 = 4; + const QUORUM: u32 = 3; + const NUM_BLOCKS: u64 = 160; + const BLOCKS_PER_EPOCH: u64 = 20; + const LINK: Link = Link { + latency: Duration::from_millis(10), + jitter: Duration::from_millis(1), + success_rate: 1.0, + }; + const UNRELIABLE_LINK: Link = Link { + latency: Duration::from_millis(200), + jitter: Duration::from_millis(50), + success_rate: 0.7, + }; + + async fn setup_validator( + context: deterministic::Context, + oracle: &mut Oracle, + validator: K, + scheme_provider: P, + ) -> ( + Application, + crate::ingress::mailbox::Mailbox, + ) { + let config = Config { + scheme_provider, + epoch_length: BLOCKS_PER_EPOCH, + mailbox_size: 100, + namespace: NAMESPACE.to_vec(), + view_retention_timeout: 10, + max_repair: 10, + block_codec_config: (), + partition_prefix: format!("validator-{}", validator.clone()), + prunable_items_per_section: NZU64!(10), + replay_buffer: NZUsize!(1024), + write_buffer: NZUsize!(1024), + freezer_table_initial_size: 64, + freezer_table_resize_frequency: 10, + freezer_table_resize_chunk_size: 10, + freezer_journal_target_size: 1024, + freezer_journal_compression: None, + freezer_journal_buffer_pool: PoolRef::new(PAGE_SIZE, PAGE_CACHE_SIZE), + immutable_items_per_section: NZU64!(10), + _marker: PhantomData, + }; + + // Create the resolver + let mut control = oracle.control(validator.clone()); + let backfill = control.register(1).await.unwrap(); + let resolver_cfg = resolver::Config { + public_key: validator.clone(), + manager: oracle.clone(), + mailbox_size: config.mailbox_size, + requester_config: requester::Config { + me: Some(validator.clone()), + rate_limit: Quota::per_second(NonZeroU32::new(5).unwrap()), + initial: Duration::from_secs(1), + timeout: Duration::from_secs(2), + }, + fetch_retry_timeout: Duration::from_millis(100), + priority_requests: false, + priority_responses: false, + }; + let resolver = resolver::init(&context, resolver_cfg, backfill); + + // Create a buffered broadcast engine and get its mailbox + let broadcast_config = buffered::Config { + public_key: validator.clone(), + mailbox_size: config.mailbox_size, + deque_size: 10, + priority: false, + codec_config: (), + }; + let (broadcast_engine, buffer) = buffered::Engine::new(context.clone(), broadcast_config); + let network = control.register(2).await.unwrap(); + broadcast_engine.start(network); + + let (actor, mailbox) = actor::Actor::init(context.clone(), config).await; + let application = Application::::default(); + + // Start the application + actor.start(application.clone(), buffer, resolver); + + (application, mailbox) + } + + fn make_finalization(proposal: Proposal, schemes: &[S], quorum: u32) -> Finalization { + // Generate proposal signature + let finalizes: Vec<_> = schemes + .iter() + .take(quorum as usize) + .map(|scheme| Finalize::sign(scheme, NAMESPACE, proposal.clone()).unwrap()) + .collect(); + + // Generate certificate signatures + Finalization::from_finalizes(&schemes[0], &finalizes).unwrap() + } + + fn make_notarization(proposal: Proposal, schemes: &[S], quorum: u32) -> Notarization { + // Generate proposal signature + let notarizes: Vec<_> = schemes + .iter() + .take(quorum as usize) + .map(|scheme| Notarize::sign(scheme, NAMESPACE, proposal.clone()).unwrap()) + .collect(); + + // Generate certificate signatures + Notarization::from_notarizes(&schemes[0], ¬arizes).unwrap() + } + + fn setup_network( + context: deterministic::Context, + tracked_peer_sets: Option, + ) -> Oracle { + let (network, oracle) = Network::new( + context.with_label("network"), + simulated::Config { + max_size: 1024 * 1024, + disconnect_on_block: true, + tracked_peer_sets, + }, + ); + network.start(); + oracle + } + + async fn setup_network_links(oracle: &mut Oracle, peers: &[K], link: Link) { + for p1 in peers.iter() { + for p2 in peers.iter() { + if p2 == p1 { + continue; + } + oracle + .add_link(p1.clone(), p2.clone(), link.clone()) + .await + .unwrap(); + } + } + } + + #[test_traced("WARN")] + fn test_finalize_good_links() { + for seed in 0..5 { + let result1 = finalize(seed, LINK); + let result2 = finalize(seed, LINK); + + // Ensure determinism + assert_eq!(result1, result2); + } + } + + #[test_traced("WARN")] + fn test_finalize_bad_links() { + for seed in 0..5 { + let result1 = finalize(seed, UNRELIABLE_LINK); + let result2 = finalize(seed, UNRELIABLE_LINK); + + // Ensure determinism + assert_eq!(result1, result2); + } + } + + fn finalize(seed: u64, link: Link) -> String { + let runner = deterministic::Runner::new( + deterministic::Config::new() + .with_seed(seed) + .with_timeout(Some(Duration::from_secs(300))), + ); + runner.start(|mut context| async move { + let mut oracle = setup_network(context.clone(), Some(3)); + let Fixture { + participants, + schemes, + .. + } = bls12381_threshold::(&mut context, NUM_VALIDATORS); + + // Initialize applications and actors + let mut applications = BTreeMap::new(); + let mut actors = Vec::new(); + + // Register the initial peer set. + oracle.update(0, participants.clone().into()).await; + for (i, validator) in participants.iter().enumerate() { + let (application, actor) = setup_validator( + context.with_label(&format!("validator-{i}")), + &mut oracle, + validator.clone(), + schemes[i].clone().into(), + ) + .await; + applications.insert(validator.clone(), application); + actors.push(actor); + } + + // Add links between all peers + setup_network_links(&mut oracle, &participants, link.clone()).await; + + // Generate blocks, skipping the genesis block. + let mut blocks = Vec::::new(); + let mut parent = Sha256::hash(b""); + for i in 1..=NUM_BLOCKS { + let block = B::new::(parent, i, i); + parent = block.digest(); + blocks.push(block); + } + + // Broadcast and finalize blocks in random order + blocks.shuffle(&mut context); + for block in blocks.iter() { + // Skip genesis block + let height = block.height(); + assert!(height > 0, "genesis block should not have been generated"); + + // Calculate the epoch and round for the block + let epoch = utils::epoch(BLOCKS_PER_EPOCH, height); + let round = Round::new(epoch, height); + + // Broadcast block by one validator + let actor_index: usize = (height % (NUM_VALIDATORS as u64)) as usize; + let mut actor = actors[actor_index].clone(); + actor.broadcast(block.clone()).await; + actor.verified(round, block.clone()).await; + + // Wait for the block to be broadcast, but due to jitter, we may or may not receive + // the block before continuing. + context.sleep(link.latency).await; + + // Notarize block by the validator that broadcasted it + let proposal = Proposal { + round, + parent: height.checked_sub(1).unwrap(), + payload: block.digest(), + }; + let notarization = make_notarization(proposal.clone(), &schemes, QUORUM); + actor + .report(Activity::Notarization(notarization.clone())) + .await; + + // Finalize block by all validators + let fin = make_finalization(proposal, &schemes, QUORUM); + for actor in actors.iter_mut() { + // Always finalize 1) the last block in each epoch 2) the last block in the chain. + // Otherwise, finalize randomly. + if height == NUM_BLOCKS + || utils::is_last_block_in_epoch(BLOCKS_PER_EPOCH, epoch).is_some() + || context.gen_bool(0.2) + // 20% chance to finalize randomly + { + actor.report(Activity::Finalization(fin.clone())).await; + } + } + } + + // Check that all applications received all blocks. + let mut finished = false; + while !finished { + // Avoid a busy loop + context.sleep(Duration::from_secs(1)).await; + + // If not all validators have finished, try again + if applications.len() != NUM_VALIDATORS as usize { + continue; + } + finished = true; + for app in applications.values() { + if app.blocks().len() != NUM_BLOCKS as usize { + finished = false; + break; + } + let Some((height, _)) = app.tip() else { + finished = false; + break; + }; + if height < NUM_BLOCKS { + finished = false; + break; + } + } + } + + // Return state + context.auditor().state() + }) + } + + #[test_traced("WARN")] + fn test_subscribe_basic_block_delivery() { + let runner = deterministic::Runner::timed(Duration::from_secs(60)); + runner.start(|mut context| async move { + let mut oracle = setup_network(context.clone(), None); + let Fixture { + participants, + schemes, + .. + } = bls12381_threshold::(&mut context, NUM_VALIDATORS); + + let mut actors = Vec::new(); + for (i, validator) in participants.iter().enumerate() { + let (_application, actor) = setup_validator( + context.with_label(&format!("validator-{i}")), + &mut oracle, + validator.clone(), + schemes[i].clone().into(), + ) + .await; + actors.push(actor); + } + let mut actor = actors[0].clone(); + + setup_network_links(&mut oracle, &participants, LINK).await; + + let parent = Sha256::hash(b""); + let block = B::new::(parent, 1, 1); + let commitment = block.digest(); + + let subscription_rx = actor.subscribe(Some(Round::from((0, 1))), commitment).await; + + actor.verified(Round::from((0, 1)), block.clone()).await; + + let proposal = Proposal { + round: Round::new(0, 1), + parent: 0, + payload: commitment, + }; + let notarization = make_notarization(proposal.clone(), &schemes, QUORUM); + actor.report(Activity::Notarization(notarization)).await; + + let finalization = make_finalization(proposal, &schemes, QUORUM); + actor.report(Activity::Finalization(finalization)).await; + + let received_block = subscription_rx.await.unwrap(); + assert_eq!(received_block.digest(), block.digest()); + assert_eq!(received_block.height(), 1); + }) + } + + #[test_traced("WARN")] + fn test_subscribe_multiple_subscriptions() { + let runner = deterministic::Runner::timed(Duration::from_secs(60)); + runner.start(|mut context| async move { + let mut oracle = setup_network(context.clone(), None); + let Fixture { + participants, + schemes, + .. + } = bls12381_threshold::(&mut context, NUM_VALIDATORS); + + let mut actors = Vec::new(); + for (i, validator) in participants.iter().enumerate() { + let (_application, actor) = setup_validator( + context.with_label(&format!("validator-{i}")), + &mut oracle, + validator.clone(), + schemes[i].clone().into(), + ) + .await; + actors.push(actor); + } + let mut actor = actors[0].clone(); + + setup_network_links(&mut oracle, &participants, LINK).await; + + let parent = Sha256::hash(b""); + let block1 = B::new::(parent, 1, 1); + let block2 = B::new::(block1.digest(), 2, 2); + let commitment1 = block1.digest(); + let commitment2 = block2.digest(); + + let sub1_rx = actor + .subscribe(Some(Round::from((0, 1))), commitment1) + .await; + let sub2_rx = actor + .subscribe(Some(Round::from((0, 2))), commitment2) + .await; + let sub3_rx = actor + .subscribe(Some(Round::from((0, 1))), commitment1) + .await; + + actor.verified(Round::from((0, 1)), block1.clone()).await; + actor.verified(Round::from((0, 2)), block2.clone()).await; + + for (view, block) in [(1, block1.clone()), (2, block2.clone())] { + let proposal = Proposal { + round: Round::new(0, view), + parent: view.checked_sub(1).unwrap(), + payload: block.digest(), + }; + let notarization = make_notarization(proposal.clone(), &schemes, QUORUM); + actor.report(Activity::Notarization(notarization)).await; + + let finalization = make_finalization(proposal, &schemes, QUORUM); + actor.report(Activity::Finalization(finalization)).await; + } + + let received1_sub1 = sub1_rx.await.unwrap(); + let received2 = sub2_rx.await.unwrap(); + let received1_sub3 = sub3_rx.await.unwrap(); + + assert_eq!(received1_sub1.digest(), block1.digest()); + assert_eq!(received2.digest(), block2.digest()); + assert_eq!(received1_sub3.digest(), block1.digest()); + assert_eq!(received1_sub1.height(), 1); + assert_eq!(received2.height(), 2); + assert_eq!(received1_sub3.height(), 1); + }) + } + + #[test_traced("WARN")] + fn test_subscribe_canceled_subscriptions() { + let runner = deterministic::Runner::timed(Duration::from_secs(60)); + runner.start(|mut context| async move { + let mut oracle = setup_network(context.clone(), None); + let Fixture { + participants, + schemes, + .. + } = bls12381_threshold::(&mut context, NUM_VALIDATORS); + + let mut actors = Vec::new(); + for (i, validator) in participants.iter().enumerate() { + let (_application, actor) = setup_validator( + context.with_label(&format!("validator-{i}")), + &mut oracle, + validator.clone(), + schemes[i].clone().into(), + ) + .await; + actors.push(actor); + } + let mut actor = actors[0].clone(); + + setup_network_links(&mut oracle, &participants, LINK).await; + + let parent = Sha256::hash(b""); + let block1 = B::new::(parent, 1, 1); + let block2 = B::new::(block1.digest(), 2, 2); + let commitment1 = block1.digest(); + let commitment2 = block2.digest(); + + let sub1_rx = actor + .subscribe(Some(Round::from((0, 1))), commitment1) + .await; + let sub2_rx = actor + .subscribe(Some(Round::from((0, 2))), commitment2) + .await; + + drop(sub1_rx); + + actor.verified(Round::from((0, 1)), block1.clone()).await; + actor.verified(Round::from((0, 2)), block2.clone()).await; + + for (view, block) in [(1, block1.clone()), (2, block2.clone())] { + let proposal = Proposal { + round: Round::new(0, view), + parent: view.checked_sub(1).unwrap(), + payload: block.digest(), + }; + let notarization = make_notarization(proposal.clone(), &schemes, QUORUM); + actor.report(Activity::Notarization(notarization)).await; + + let finalization = make_finalization(proposal, &schemes, QUORUM); + actor.report(Activity::Finalization(finalization)).await; + } + + let received2 = sub2_rx.await.unwrap(); + assert_eq!(received2.digest(), block2.digest()); + assert_eq!(received2.height(), 2); + }) + } + + #[test_traced("WARN")] + fn test_subscribe_blocks_from_different_sources() { + let runner = deterministic::Runner::timed(Duration::from_secs(60)); + runner.start(|mut context| async move { + let mut oracle = setup_network(context.clone(), None); + let Fixture { + participants, + schemes, + .. + } = bls12381_threshold::(&mut context, NUM_VALIDATORS); + + let mut actors = Vec::new(); + for (i, validator) in participants.iter().enumerate() { + let (_application, actor) = setup_validator( + context.with_label(&format!("validator-{i}")), + &mut oracle, + validator.clone(), + schemes[i].clone().into(), + ) + .await; + actors.push(actor); + } + let mut actor = actors[0].clone(); + + setup_network_links(&mut oracle, &participants, LINK).await; + + let parent = Sha256::hash(b""); + let block1 = B::new::(parent, 1, 1); + let block2 = B::new::(block1.digest(), 2, 2); + let block3 = B::new::(block2.digest(), 3, 3); + let block4 = B::new::(block3.digest(), 4, 4); + let block5 = B::new::(block4.digest(), 5, 5); + + let sub1_rx = actor.subscribe(None, block1.digest()).await; + let sub2_rx = actor.subscribe(None, block2.digest()).await; + let sub3_rx = actor.subscribe(None, block3.digest()).await; + let sub4_rx = actor.subscribe(None, block4.digest()).await; + let sub5_rx = actor.subscribe(None, block5.digest()).await; + + // Block1: Broadcasted by the actor + actor.broadcast(block1.clone()).await; + context.sleep(Duration::from_millis(20)).await; + + // Block1: delivered + let received1 = sub1_rx.await.unwrap(); + assert_eq!(received1.digest(), block1.digest()); + assert_eq!(received1.height(), 1); + + // Block2: Verified by the actor + actor.verified(Round::from((0, 2)), block2.clone()).await; + + // Block2: delivered + let received2 = sub2_rx.await.unwrap(); + assert_eq!(received2.digest(), block2.digest()); + assert_eq!(received2.height(), 2); + + // Block3: Notarized by the actor + let proposal3 = Proposal { + round: Round::new(0, 3), + parent: 2, + payload: block3.digest(), + }; + let notarization3 = make_notarization(proposal3.clone(), &schemes, QUORUM); + actor.report(Activity::Notarization(notarization3)).await; + actor.verified(Round::from((0, 3)), block3.clone()).await; + + // Block3: delivered + let received3 = sub3_rx.await.unwrap(); + assert_eq!(received3.digest(), block3.digest()); + assert_eq!(received3.height(), 3); + + // Block4: Finalized by the actor + let finalization4 = make_finalization( + Proposal { + round: Round::new(0, 4), + parent: 3, + payload: block4.digest(), + }, + &schemes, + QUORUM, + ); + actor.report(Activity::Finalization(finalization4)).await; + actor.verified(Round::from((0, 4)), block4.clone()).await; + + // Block4: delivered + let received4 = sub4_rx.await.unwrap(); + assert_eq!(received4.digest(), block4.digest()); + assert_eq!(received4.height(), 4); + + // Block5: Broadcasted by a remote node (different actor) + let remote_actor = &mut actors[1].clone(); + remote_actor.broadcast(block5.clone()).await; + context.sleep(Duration::from_millis(20)).await; + + // Block5: delivered + let received5 = sub5_rx.await.unwrap(); + assert_eq!(received5.digest(), block5.digest()); + assert_eq!(received5.height(), 5); + }) + } + + #[test_traced("WARN")] + fn test_get_info_basic_queries_present_and_missing() { + let runner = deterministic::Runner::timed(Duration::from_secs(60)); + runner.start(|mut context| async move { + let mut oracle = setup_network(context.clone(), None); + let Fixture { + participants, + schemes, + .. + } = bls12381_threshold::(&mut context, NUM_VALIDATORS); + + // Single validator actor + let me = participants[0].clone(); + let (_application, mut actor) = setup_validator( + context.with_label("validator-0"), + &mut oracle, + me, + schemes[0].clone().into(), + ) + .await; + + // Initially, no latest + assert!(actor.get_info(Identifier::Latest).await.is_none()); + + // Before finalization, specific height returns None + assert!(actor.get_info(1).await.is_none()); + + // Create and verify a block, then finalize it + let parent = Sha256::hash(b""); + let block = B::new::(parent, 1, 1); + let digest = block.digest(); + let round = Round::new(0, 1); + actor.verified(round, block.clone()).await; + + let proposal = Proposal { + round, + parent: 0, + payload: digest, + }; + let finalization = make_finalization(proposal, &schemes, QUORUM); + actor.report(Activity::Finalization(finalization)).await; + + // Latest should now be the finalized block + assert_eq!(actor.get_info(Identifier::Latest).await, Some((1, digest))); + + // Height 1 now present + assert_eq!(actor.get_info(1).await, Some((1, digest))); + + // Commitment should map to its height + assert_eq!(actor.get_info(&digest).await, Some((1, digest))); + + // Missing height + assert!(actor.get_info(2).await.is_none()); + + // Missing commitment + let missing = Sha256::hash(b"missing"); + assert!(actor.get_info(&missing).await.is_none()); + }) + } + + #[test_traced("WARN")] + fn test_get_info_latest_progression_multiple_finalizations() { + let runner = deterministic::Runner::timed(Duration::from_secs(60)); + runner.start(|mut context| async move { + let mut oracle = setup_network(context.clone(), None); + let Fixture { + participants, + schemes, + .. + } = bls12381_threshold::(&mut context, NUM_VALIDATORS); + + // Single validator actor + let me = participants[0].clone(); + let (_application, mut actor) = setup_validator( + context.with_label("validator-0"), + &mut oracle, + me, + schemes[0].clone().into(), + ) + .await; + + // Initially none + assert!(actor.get_info(Identifier::Latest).await.is_none()); + + // Build and finalize heights 1..=3 + let parent0 = Sha256::hash(b""); + let block1 = B::new::(parent0, 1, 1); + let d1 = block1.digest(); + actor.verified(Round::new(0, 1), block1.clone()).await; + let f1 = make_finalization( + Proposal { + round: Round::new(0, 1), + parent: 0, + payload: d1, + }, + &schemes, + QUORUM, + ); + actor.report(Activity::Finalization(f1)).await; + let latest = actor.get_info(Identifier::Latest).await; + assert_eq!(latest, Some((1, d1))); + + let block2 = B::new::(d1, 2, 2); + let d2 = block2.digest(); + actor.verified(Round::new(0, 2), block2.clone()).await; + let f2 = make_finalization( + Proposal { + round: Round::new(0, 2), + parent: 1, + payload: d2, + }, + &schemes, + QUORUM, + ); + actor.report(Activity::Finalization(f2)).await; + let latest = actor.get_info(Identifier::Latest).await; + assert_eq!(latest, Some((2, d2))); + + let block3 = B::new::(d2, 3, 3); + let d3 = block3.digest(); + actor.verified(Round::new(0, 3), block3.clone()).await; + let f3 = make_finalization( + Proposal { + round: Round::new(0, 3), + parent: 2, + payload: d3, + }, + &schemes, + QUORUM, + ); + actor.report(Activity::Finalization(f3)).await; + let latest = actor.get_info(Identifier::Latest).await; + assert_eq!(latest, Some((3, d3))); + }) + } + + #[test_traced("WARN")] + fn test_get_block_by_height_and_latest() { + let runner = deterministic::Runner::timed(Duration::from_secs(60)); + runner.start(|mut context| async move { + let mut oracle = setup_network(context.clone(), None); + let Fixture { + participants, + schemes, + .. + } = bls12381_threshold::(&mut context, NUM_VALIDATORS); + + let me = participants[0].clone(); + let (application, mut actor) = setup_validator( + context.with_label("validator-0"), + &mut oracle, + me, + schemes[0].clone().into(), + ) + .await; + + // Before any finalization, GetBlock::Latest should be None + let latest_block = actor.get_block(Identifier::Latest).await; + assert!(latest_block.is_none()); + assert!(application.tip().is_none()); + + // Finalize a block at height 1 + let parent = Sha256::hash(b""); + let block = B::new::(parent, 1, 1); + let commitment = block.digest(); + let round = Round::new(0, 1); + actor.verified(round, block.clone()).await; + let proposal = Proposal { + round, + parent: 0, + payload: commitment, + }; + let finalization = make_finalization(proposal, &schemes, QUORUM); + actor.report(Activity::Finalization(finalization)).await; + + // Get by height + let by_height = actor.get_block(1).await.expect("missing block by height"); + assert_eq!(by_height.height(), 1); + assert_eq!(by_height.digest(), commitment); + assert_eq!(application.tip(), Some((1, commitment))); + + // Get by latest + let by_latest = actor + .get_block(Identifier::Latest) + .await + .expect("missing block by latest"); + assert_eq!(by_latest.height(), 1); + assert_eq!(by_latest.digest(), commitment); + + // Missing height + let by_height = actor.get_block(2).await; + assert!(by_height.is_none()); + }) + } + + #[test_traced("WARN")] + fn test_get_block_by_commitment_from_sources_and_missing() { + let runner = deterministic::Runner::timed(Duration::from_secs(60)); + runner.start(|mut context| async move { + let mut oracle = setup_network(context.clone(), None); + let Fixture { + participants, + schemes, + .. + } = bls12381_threshold::(&mut context, NUM_VALIDATORS); + + let me = participants[0].clone(); + let (_application, mut actor) = setup_validator( + context.with_label("validator-0"), + &mut oracle, + me, + schemes[0].clone().into(), + ) + .await; -pub mod coordinator; -pub mod handler; -pub mod key; + // 1) From cache via verified + let parent = Sha256::hash(b""); + let ver_block = B::new::(parent, 1, 1); + let ver_commitment = ver_block.digest(); + let round1 = Round::new(0, 1); + actor.verified(round1, ver_block.clone()).await; + let got = actor + .get_block(&ver_commitment) + .await + .expect("missing block from cache"); + assert_eq!(got.digest(), ver_commitment); -/// Configuration for the syncer. -pub struct Config { - pub partition_prefix: String, + // 2) From finalized archive + let fin_block = B::new::(ver_commitment, 2, 2); + let fin_commitment = fin_block.digest(); + let round2 = Round::new(0, 2); + actor.verified(round2, fin_block.clone()).await; + let proposal = Proposal { + round: round2, + parent: 1, + payload: fin_commitment, + }; + let finalization = make_finalization(proposal, &schemes, QUORUM); + actor.report(Activity::Finalization(finalization)).await; + let got = actor + .get_block(&fin_commitment) + .await + .expect("missing block from finalized archive"); + assert_eq!(got.digest(), fin_commitment); + assert_eq!(got.height(), 2); - pub public_key: PublicKey, + // 3) Missing commitment + let missing = Sha256::hash(b"definitely-missing"); + let missing_block = actor.get_block(&missing).await; + assert!(missing_block.is_none()); + }) + } - pub registry: Registry, + #[test_traced("WARN")] + fn test_get_finalization_by_height() { + let runner = deterministic::Runner::timed(Duration::from_secs(60)); + runner.start(|mut context| async move { + let mut oracle = setup_network(context.clone(), None); + let Fixture { + participants, + schemes, + .. + } = bls12381_threshold::(&mut context, NUM_VALIDATORS); - /// Number of messages from consensus to hold in our backlog - /// before blocking. - pub mailbox_size: usize, + let me = participants[0].clone(); + let (_application, mut actor) = setup_validator( + context.with_label("validator-0"), + &mut oracle, + me, + schemes[0].clone().into(), + ) + .await; - pub backfill_quota: governor::Quota, - pub activity_timeout: u64, + // Before any finalization, get_finalization should be None + let finalization = actor.get_finalization(1).await; + assert!(finalization.is_none()); - pub namespace: String, + // Finalize a block at height 1 + let parent = Sha256::hash(b""); + let block = B::new::(parent, 1, 1); + let commitment = block.digest(); + let round = Round::new(0, 1); + actor.verified(round, block.clone()).await; + let proposal = Proposal { + round, + parent: 0, + payload: commitment, + }; + let finalization = make_finalization(proposal, &schemes, QUORUM); + actor.report(Activity::Finalization(finalization)).await; - pub buffer_pool: PoolRef, + // Get finalization by height + let finalization = actor + .get_finalization(1) + .await + .expect("missing finalization by height"); + assert_eq!(finalization.proposal.parent, 0); + assert_eq!(finalization.proposal.round, Round::new(0, 1)); + assert_eq!(finalization.proposal.payload, commitment); - pub cancellation_token: CancellationToken, + assert!(actor.get_finalization(2).await.is_none()); + }) + } } diff --git a/syncer/src/mocks/application.rs b/syncer/src/mocks/application.rs new file mode 100644 index 00000000..9ca80a0c --- /dev/null +++ b/syncer/src/mocks/application.rs @@ -0,0 +1,49 @@ +use commonware_consensus::{marshal::Update, Block, Reporter}; +use std::{ + collections::BTreeMap, + sync::{Arc, Mutex}, +}; + +/// A mock application that stores finalized blocks. +#[derive(Clone)] +pub struct Application { + blocks: Arc>>, + #[allow(clippy::type_complexity)] + tip: Arc>>, +} + +impl Default for Application { + fn default() -> Self { + Self { + blocks: Default::default(), + tip: Default::default(), + } + } +} + +impl Application { + /// Returns the finalized blocks. + pub fn blocks(&self) -> BTreeMap { + self.blocks.lock().unwrap().clone() + } + + /// Returns the tip. + pub fn tip(&self) -> Option<(u64, B::Commitment)> { + *self.tip.lock().unwrap() + } +} + +impl Reporter for Application { + type Activity = Update; + + async fn report(&mut self, activity: Self::Activity) { + match activity { + Update::Block(block) => { + self.blocks.lock().unwrap().insert(block.height(), block); + } + Update::Tip(height, commitment) => { + *self.tip.lock().unwrap() = Some((height, commitment)); + } + } + } +} diff --git a/syncer/src/mocks/block.rs b/syncer/src/mocks/block.rs new file mode 100644 index 00000000..7c43d8cd --- /dev/null +++ b/syncer/src/mocks/block.rs @@ -0,0 +1,101 @@ +use bytes::{Buf, BufMut}; +use commonware_codec::{varint::UInt, EncodeSize, Error, Read, ReadExt, Write}; +use commonware_cryptography::{Committable, Digest, Digestible, Hasher}; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Block { + /// The parent block's digest. + pub parent: D, + + /// The height of the block in the blockchain. + pub height: u64, + + /// The timestamp of the block (in milliseconds since the Unix epoch). + pub timestamp: u64, + + /// Pre-computed digest of the block. + digest: D, +} + +impl Block { + fn compute_digest>(parent: &D, height: u64, timestamp: u64) -> D { + let mut hasher = H::new(); + hasher.update(parent); + hasher.update(&height.to_be_bytes()); + hasher.update(×tamp.to_be_bytes()); + hasher.finalize() + } + + pub fn new>(parent: D, height: u64, timestamp: u64) -> Self { + let digest = Self::compute_digest::(&parent, height, timestamp); + Self { + parent, + height, + timestamp, + digest, + } + } +} + +impl Write for Block { + fn write(&self, writer: &mut impl BufMut) { + self.parent.write(writer); + UInt(self.height).write(writer); + UInt(self.timestamp).write(writer); + self.digest.write(writer); + } +} + +impl Read for Block { + type Cfg = (); + + fn read_cfg(reader: &mut impl Buf, _: &Self::Cfg) -> Result { + let parent = D::read(reader)?; + let height = UInt::read(reader)?.into(); + let timestamp = UInt::read(reader)?.into(); + let digest = D::read(reader)?; + + // Pre-compute the digest + Ok(Self { + parent, + height, + timestamp, + digest, + }) + } +} + +impl EncodeSize for Block { + fn encode_size(&self) -> usize { + self.parent.encode_size() + + UInt(self.height).encode_size() + + UInt(self.timestamp).encode_size() + + self.digest.encode_size() + } +} + +impl Digestible for Block { + type Digest = D; + + fn digest(&self) -> D { + self.digest + } +} + +impl Committable for Block { + type Commitment = D; + + fn commitment(&self) -> D { + self.digest + } +} + +impl crate::Block for Block { + fn height(&self) -> u64 { + self.height + } + + fn parent(&self) -> Self::Commitment { + self.parent + } +} diff --git a/syncer/src/mocks/mod.rs b/syncer/src/mocks/mod.rs new file mode 100644 index 00000000..ad006ac6 --- /dev/null +++ b/syncer/src/mocks/mod.rs @@ -0,0 +1,3 @@ +pub mod application; +pub mod block; +pub mod resolver; diff --git a/syncer/src/mocks/resolver.rs b/syncer/src/mocks/resolver.rs new file mode 100644 index 00000000..b3c0c18f --- /dev/null +++ b/syncer/src/mocks/resolver.rs @@ -0,0 +1,27 @@ +use std::{ + collections::HashMap, + sync::{Arc, Mutex}, +}; + +#[derive(Clone)] +pub struct Resolver { + data: Arc>>, +} + +impl Default for Resolver { + fn default() -> Self { + Self { + data: Arc::new(Mutex::new(HashMap::new())), + } + } +} + +impl Resolver { + pub fn get(&self, key: K) -> V { + self.data.lock().unwrap().get(&key).unwrap().clone() + } + + pub fn put(&self, key: K, value: V) { + self.data.lock().unwrap().insert(key, value); + } +} diff --git a/syncer/src/resolver/mod.rs b/syncer/src/resolver/mod.rs new file mode 100644 index 00000000..ab85b4f7 --- /dev/null +++ b/syncer/src/resolver/mod.rs @@ -0,0 +1,3 @@ +//! Default resolvers available for the [Actor](super::actor::Actor). + +pub mod p2p; diff --git a/syncer/src/resolver/p2p.rs b/syncer/src/resolver/p2p.rs new file mode 100644 index 00000000..5a2c1091 --- /dev/null +++ b/syncer/src/resolver/p2p.rs @@ -0,0 +1,72 @@ +//! P2P resolver initialization and config. + +use crate::Block; +use crate::ingress::handler::{self, Handler}; +use commonware_cryptography::PublicKey; +use commonware_p2p::{utils::requester, Manager, Receiver, Sender}; +use commonware_resolver::p2p; +use commonware_runtime::{Clock, Metrics, Spawner}; +use futures::channel::mpsc; +use governor::clock::Clock as GClock; +use rand::Rng; +use std::time::Duration; + +/// Configuration for the P2P [Resolver](commonware_resolver::Resolver). +pub struct Config> { + /// The public key to identify this node. + pub public_key: P, + + /// The provider of peers that can be consulted for fetching data. + pub manager: C, + + /// The size of the request mailbox backlog. + pub mailbox_size: usize, + + /// The requester configuration. + pub requester_config: requester::Config

, + + /// Retry timeout for the fetcher. + pub fetch_retry_timeout: Duration, + + /// Whether requests are sent with priority over other network messages + pub priority_requests: bool, + + /// Whether responses are sent with priority over other network messages + pub priority_responses: bool, +} + +/// Initialize a P2P resolver. +pub fn init( + ctx: &E, + config: Config, + backfill: (S, R), +) -> ( + mpsc::Receiver>, + p2p::Mailbox>, +) +where + E: Rng + Spawner + Clock + GClock + Metrics, + C: Manager, + B: Block, + S: Sender, + R: Receiver, + P: PublicKey, +{ + let (handler, receiver) = mpsc::channel(config.mailbox_size); + let handler = Handler::new(handler); + let (resolver_engine, resolver) = p2p::Engine::new( + ctx.with_label("resolver"), + p2p::Config { + manager: config.manager, + consumer: handler.clone(), + producer: handler, + mailbox_size: config.mailbox_size, + requester_config: config.requester_config, + fetch_retry_timeout: config.fetch_retry_timeout, + priority_requests: config.priority_requests, + priority_responses: config.priority_responses, + }, + ); + resolver_engine.start(backfill); + (receiver, resolver) +} From 346061bb52cc25b8684e0cc3f719c9b2c45fc767 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Wed, 5 Nov 2025 13:45:39 -0500 Subject: [PATCH 26/81] feat: add consensus key to genesis --- example_genesis.toml | 12 ++-- types/src/genesis.rs | 148 ++++++++++++++++++++++++++++++++----------- 2 files changed, 118 insertions(+), 42 deletions(-) diff --git a/example_genesis.toml b/example_genesis.toml index fd1cdc48..aa244bc0 100644 --- a/example_genesis.toml +++ b/example_genesis.toml @@ -8,21 +8,25 @@ max_message_size_bytes = 104857600 namespace = "_SEISMIC_BFT" [[validators]] -public_key = "1be3cb06d7cc347602421fb73838534e4b54934e28959de98906d120d0799ef2" +node_public_key = "1be3cb06d7cc347602421fb73838534e4b54934e28959de98906d120d0799ef2" +consensus_public_key = "a6f61154ae7be4fd38cd43cf69adfd4896c57473cacb389702bb83f8adf923eecf4854c745e064c0a2db79db5674332b" ip_address = "127.0.0.1:26600" withdrawal_credentials = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" [[validators]] -public_key = "32efa16e3cd62292db529e8f4babd27724b13b397edcf2b1dbe48f416ce40f0d" +node_public_key = "32efa16e3cd62292db529e8f4babd27724b13b397edcf2b1dbe48f416ce40f0d" +consensus_public_key = "b82eaa7fbc7f9cf9d60826e5155ca8ccc46e13d87f64f7bcdcaa2972c370766b87635334bfc49b8fba7fb784e763d44e" ip_address = "127.0.0.1:26610" withdrawal_credentials = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" [[validators]] -public_key = "ce9b314ac9d55d28bedf543164120eecf737380015c977eaa78d59894bbccf52" +node_public_key = "ce9b314ac9d55d28bedf543164120eecf737380015c977eaa78d59894bbccf52" +consensus_public_key = "b806a3638975b2c33ccdda9cc55231e1328a0d1f70a3dde804e473e22ec21d5703ee34264c702b971cd0f9d5892434e8" ip_address = "127.0.0.1:26620" withdrawal_credentials = "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC" [[validators]] -public_key = "f205c8c88d5d1753843dd0fc9810390efd00d6f752dd555c0ad4000bfcac2226" +node_public_key = "f205c8c88d5d1753843dd0fc9810390efd00d6f752dd555c0ad4000bfcac2226" +consensus_public_key = "83c50f2fa828c5e132a2ac00792ef9c892372976ff26400711b7061bdb045f0751559b4a04cfd7399555a2aed5b54f3f" ip_address = "127.0.0.1:26630" withdrawal_credentials = "0x90F79bf6EB2c4f870365E785982E1f101E93b906" diff --git a/types/src/genesis.rs b/types/src/genesis.rs index 13f2c674..7194f545 100644 --- a/types/src/genesis.rs +++ b/types/src/genesis.rs @@ -1,14 +1,16 @@ use crate::PublicKey; use alloy_primitives::Address; use commonware_codec::DecodeExt; +use commonware_cryptography::bls12381; use commonware_utils::from_hex_formatted; use serde::{Deserialize, Serialize}; use std::net::SocketAddr; +use anyhow::Context; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Genesis { /// List of all validators at genesis block - pub validators: Vec, + pub validators: Vec, /// The hash of the genesis file used for the EVM client pub eth_genesis_hash: String, /// Amount of time to wait for a leader to propose a payload @@ -39,26 +41,39 @@ pub struct Genesis { } #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Validator { - pub public_key: String, +pub struct GenesisValidator { + pub node_public_key: String, + pub consensus_public_key: String, pub ip_address: String, pub withdrawal_credentials: String, } -impl TryInto<(PublicKey, SocketAddr, Address)> for &Validator { - type Error = String; +#[derive(Debug, Clone)] +pub struct Validator { + pub node_public_key: PublicKey, + pub consensus_public_key: bls12381::PublicKey, + pub ip_address: SocketAddr, + pub withdrawal_credentials: Address, +} + +impl TryFrom<&GenesisValidator> for Validator { + type Error = anyhow::Error; + + fn try_from(value: &GenesisValidator) -> Result { + let node_key_bytes = from_hex_formatted(&value.node_public_key).context("Node PublicKey bad format")?; + let node_public_key = PublicKey::decode(&*node_key_bytes)?; - fn try_into(self) -> Result<(PublicKey, SocketAddr, Address), Self::Error> { - let pub_key_bytes = from_hex_formatted(&self.public_key).ok_or("PublicKey bad format")?; + let consensus_key_bytes = from_hex_formatted(&value.consensus_public_key).context("Consensus PublicKey bad format")?; + let consensus_public_key = bls12381::PublicKey::decode(&*consensus_key_bytes)?; - Ok(( - PublicKey::decode(&*pub_key_bytes).map_err(|_| "Unable to decode Public Key")?, - self.ip_address.parse().map_err(|_| "Invalid ip address")?, - self.withdrawal_credentials - .parse() - .map_err(|_| "Invalid withdrawal credentials")?, - )) + Ok(Validator { + node_public_key, + consensus_public_key, + ip_address: value.ip_address.parse()?, + withdrawal_credentials: value.withdrawal_credentials.parse()? + }) } + } impl Genesis { @@ -68,26 +83,9 @@ impl Genesis { Ok(genesis) } - pub fn get_validator_addresses( - &self, - ) -> Result, Box> { - let mut validators = Vec::new(); - - for validator in &self.validators { - let public_key_bytes = from_hex_formatted(&validator.public_key) - .ok_or("Invalid hex format for public key")?; - let pub_key = PublicKey::decode(&*public_key_bytes)?; - let socket_addr: SocketAddr = validator.ip_address.parse()?; - - validators.push((pub_key, socket_addr)); - } - - Ok(validators) - } - pub fn ip_of(&self, target_public_key: &PublicKey) -> Option { for validator in &self.validators { - if let Some(public_key_bytes) = from_hex_formatted(&validator.public_key) { + if let Some(public_key_bytes) = from_hex_formatted(&validator.node_public_key) { if let Ok(pub_key) = PublicKey::decode(&*public_key_bytes) { if &pub_key == target_public_key { if let Ok(socket_addr) = validator.ip_address.parse() { @@ -103,10 +101,46 @@ impl Genesis { pub fn validator_count(&self) -> usize { self.validators.len() } + + pub fn get_validators(&self) -> Result, anyhow::Error> { + let mut validators = Vec::with_capacity(self.validators.len()); + for validator in &self.validators { + validators.push(validator.try_into()?); + } + Ok(validators) + } + + pub fn get_consensus_keys(&self) -> Result, Box> { + let mut keys = Vec::new(); + for validator in &self.validators { + let key_bytes = from_hex_formatted(&validator.consensus_public_key) + .ok_or("Invalid hex format for consensus public key")?; + let key = bls12381::PublicKey::decode(&*key_bytes)?; + keys.push(key); + } + Ok(keys) + } + + pub fn get_validator_keys(&self) -> Result, Box> { + let mut keys = Vec::new(); + for validator in &self.validators { + let node_key_bytes = from_hex_formatted(&validator.node_public_key) + .ok_or("Invalid hex format for node public key")?; + let node_key = PublicKey::decode(&*node_key_bytes)?; + + let consensus_key_bytes = from_hex_formatted(&validator.consensus_public_key) + .ok_or("Invalid hex format for consensus public key")?; + let consensus_key = bls12381::PublicKey::decode(&*consensus_key_bytes)?; + + keys.push((node_key, consensus_key)); + } + Ok(keys) + } } #[cfg(test)] mod tests { + use std::path::PathBuf; use super::*; #[test] @@ -114,19 +148,57 @@ mod tests { let genesis = Genesis::load_from_file("../example_genesis.toml").unwrap(); assert_eq!(genesis.validator_count(), 4); - let addresses = genesis.get_validator_addresses().unwrap(); - assert_eq!(addresses.len(), 4); + let keys = genesis.get_validator_keys().unwrap(); + assert_eq!(keys.len(), 4); } #[test] fn test_validator_lookup() { let genesis = Genesis::load_from_file("../example_genesis.toml").unwrap(); - let addresses = genesis.get_validator_addresses().unwrap(); // Test that we can find the IP for each validator - for (pub_key, expected_addr) in &addresses { - let found_addr = genesis.ip_of(pub_key); - assert_eq!(found_addr, Some(*expected_addr)); + let validators = &genesis.get_validators().unwrap(); + for validator in validators { + let found_addr = genesis.ip_of(&validator.node_public_key); + assert_eq!(found_addr, Some(validator.ip_address)); } } + + #[test] +fn test_generate_and_save_bls_keys() { + use commonware_cryptography::{bls12381, PrivateKeyExt, Signer}; + use commonware_codec::Encode; + use std::fs; + use std::path::Path; + + let temp_dir = PathBuf::from("testnet"); + fs::create_dir_all(&temp_dir).unwrap(); + + println!("\nGenerating 4 BLS key pairs:"); + println!("Keys saved to: {}\n", temp_dir.display()); + + for i in 0..4 { + let private_key = bls12381::PrivateKey::from_seed(i); + let public_key = private_key.public_key(); + + // Save private key to disk + fs::create_dir_all(&temp_dir.join(format!("node{}", i))).unwrap(); + let private_key_path = temp_dir.join(format!("node{}", i)).join("consensus.pem"); + let private_key_bytes = private_key.encode(); + fs::write(&private_key_path, &private_key_bytes).unwrap(); + + // Print public key in hex format + let public_key_hex = public_key.to_string(); + println!("Validator {}: {}", i, public_key_hex); + } + + // Verify we can read the keys back + for i in 0..4 { + let private_key_path = temp_dir.join(format!("node{}", i)).join("consensus.pem"); + assert!(Path::new(&private_key_path).exists()); + } + + // Cleanup + //fs::remove_dir_all(&temp_dir).unwrap(); + } } From 1d6a9e76b1c2663e10a0e94c88a3f3c24ca7847f Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Wed, 5 Nov 2025 14:02:26 -0500 Subject: [PATCH 27/81] feat: add consensus key to validator account --- types/Cargo.toml | 2 +- types/src/account.rs | 92 ++++++++++++++++++++---------- types/src/checkpoint.rs | 11 ++++ types/src/consensus_state.rs | 23 +++++++- types/src/genesis.rs | 39 ------------- types/src/keystore.rs | 4 +- types/src/lib.rs | 2 + types/src/registry.rs | 3 +- types/src/scheme.rs | 105 +++++++++++++++++++++++++++++++++++ 9 files changed, 208 insertions(+), 73 deletions(-) create mode 100644 types/src/scheme.rs diff --git a/types/Cargo.toml b/types/Cargo.toml index 3a166b06..a5b0d7fc 100644 --- a/types/Cargo.toml +++ b/types/Cargo.toml @@ -20,7 +20,7 @@ alloy-provider.workspace = true alloy-transport-ipc.workspace = true futures.workspace = true - +zeroize.workspace = true # for reth.rs module (e2e feature only) alloy-genesis = { workspace = true, optional = true } rand = { workspace = true, optional = true } diff --git a/types/src/account.rs b/types/src/account.rs index 85a2429d..1ef96369 100644 --- a/types/src/account.rs +++ b/types/src/account.rs @@ -1,6 +1,7 @@ use alloy_primitives::Address; use bytes::{Buf, BufMut}; -use commonware_codec::{Error, FixedSize, Read, Write}; +use commonware_codec::{DecodeExt, Encode, Error, FixedSize, Read, Write}; +use commonware_cryptography::bls12381; #[derive(Debug, Clone, PartialEq)] pub enum ValidatorStatus { @@ -30,52 +31,61 @@ impl ValidatorStatus { #[derive(Debug, Clone, PartialEq)] pub struct ValidatorAccount { - pub withdrawal_credentials: Address, // Ethereum address - pub balance: u64, // Balance in gwei - pub pending_withdrawal_amount: u64, // Sum of pending withdrawals in gwei + pub consensus_public_key: bls12381::PublicKey, // BLS public key for consensus + pub withdrawal_credentials: Address, // Ethereum address + pub balance: u64, // Balance in gwei + pub pending_withdrawal_amount: u64, // Sum of pending withdrawals in gwei pub status: ValidatorStatus, - pub last_deposit_index: u64, // Last deposit request index + pub last_deposit_index: u64, // Last deposit request index } impl TryFrom<&[u8]> for ValidatorAccount { type Error = &'static str; fn try_from(bytes: &[u8]) -> Result { - // ValidatorAccount data is exactly 77 bytes - // Format: withdrawal_credentials(20) + balance(8) + pending_withdrawal_amount(8) + status(1) + last_deposit_index(8) = 77 bytes + // ValidatorAccount data is exactly 93 bytes + // Format: consensus_public_key(48) + withdrawal_credentials(20) + balance(8) + pending_withdrawal_amount(8) + status(1) + last_deposit_index(8) = 93 bytes - if bytes.len() != 45 { - return Err("ValidatorAccount must be exactly 45 bytes"); + if bytes.len() != 93 { + return Err("ValidatorAccount must be exactly 93 bytes"); } + // Extract consensus_public_key (48 bytes) + let consensus_key_bytes: [u8; 48] = bytes[0..48] + .try_into() + .map_err(|_| "Failed to parse consensus_public_key")?; + let consensus_public_key = bls12381::PublicKey::decode(&consensus_key_bytes[..]) + .map_err(|_| "Failed to decode consensus_public_key")?; + // Extract withdrawal_credentials (20 bytes) - let withdrawal_credentials_bytes: [u8; 20] = bytes[0..20] + let withdrawal_credentials_bytes: [u8; 20] = bytes[48..68] .try_into() .map_err(|_| "Failed to parse withdrawal_credentials")?; let withdrawal_credentials = Address::from(withdrawal_credentials_bytes); // Extract balance (8 bytes, little-endian u64) - let balance_bytes: [u8; 8] = bytes[20..28] + let balance_bytes: [u8; 8] = bytes[68..76] .try_into() .map_err(|_| "Failed to parse balance")?; let balance = u64::from_le_bytes(balance_bytes); // Extract pending_withdrawal_amount (8 bytes, little-endian u64) - let pending_withdrawal_amount_bytes: [u8; 8] = bytes[28..36] + let pending_withdrawal_amount_bytes: [u8; 8] = bytes[76..84] .try_into() .map_err(|_| "Failed to parse pending_withdrawal_amount")?; let pending_withdrawal_amount = u64::from_le_bytes(pending_withdrawal_amount_bytes); // Extract status (1 byte) - let status = ValidatorStatus::from_u8(bytes[36])?; + let status = ValidatorStatus::from_u8(bytes[84])?; // Extract last_deposit_index (8 bytes, little-endian u64) - let last_deposit_index_bytes: [u8; 8] = bytes[37..45] + let last_deposit_index_bytes: [u8; 8] = bytes[85..93] .try_into() .map_err(|_| "Failed to parse last_deposit_index")?; let last_deposit_index = u64::from_le_bytes(last_deposit_index_bytes); Ok(ValidatorAccount { + consensus_public_key, withdrawal_credentials, balance, pending_withdrawal_amount, @@ -87,6 +97,7 @@ impl TryFrom<&[u8]> for ValidatorAccount { impl Write for ValidatorAccount { fn write(&self, buf: &mut impl BufMut) { + buf.put(&self.consensus_public_key.encode()[..]); buf.put(&self.withdrawal_credentials.0[..]); buf.put(&self.balance.to_le_bytes()[..]); buf.put(&self.pending_withdrawal_amount.to_le_bytes()[..]); @@ -96,17 +107,22 @@ impl Write for ValidatorAccount { } impl FixedSize for ValidatorAccount { - const SIZE: usize = 45; // 20 + 8 + 8 + 1 + 8 + const SIZE: usize = 93; // 48 + 20 + 8 + 8 + 1 + 8 } impl Read for ValidatorAccount { type Cfg = (); fn read_cfg(buf: &mut impl Buf, _cfg: &Self::Cfg) -> Result { - if buf.remaining() < 45 { + if buf.remaining() < 93 { return Err(Error::Invalid("ValidatorAccount", "Insufficient bytes")); } + let mut consensus_key_bytes = [0u8; 48]; + buf.copy_to_slice(&mut consensus_key_bytes); + let consensus_public_key = bls12381::PublicKey::decode(&consensus_key_bytes[..]) + .map_err(|_| Error::Invalid("ValidatorAccount", "Invalid consensus public key"))?; + let mut withdrawal_credentials_bytes = [0u8; 20]; buf.copy_to_slice(&mut withdrawal_credentials_bytes); let withdrawal_credentials = Address::from(withdrawal_credentials_bytes); @@ -128,6 +144,7 @@ impl Read for ValidatorAccount { let last_deposit_index = u64::from_le_bytes(last_deposit_index_bytes); Ok(ValidatorAccount { + consensus_public_key, withdrawal_credentials, balance, pending_withdrawal_amount, @@ -142,10 +159,13 @@ mod tests { use super::*; use bytes::BytesMut; use commonware_codec::{ReadExt, Write}; + use commonware_cryptography::{PrivateKeyExt, Signer}; #[test] fn test_validator_account_codec() { + let consensus_key = bls12381::PrivateKey::from_seed(1); let account = ValidatorAccount { + consensus_public_key: consensus_key.public_key(), withdrawal_credentials: Address::from([2u8; 20]), balance: 32000000000u64, // 32 ETH in gwei pending_withdrawal_amount: 1000000000u64, // 1 ETH in gwei @@ -156,7 +176,7 @@ mod tests { // Test Write let mut buf = BytesMut::new(); account.write(&mut buf); - assert_eq!(buf.len(), ValidatorAccount::SIZE); // 20 + 8 + 8 + 1 + 8 + assert_eq!(buf.len(), ValidatorAccount::SIZE); // 48 + 20 + 8 + 8 + 1 + 8 // Test Read let decoded = ValidatorAccount::read(&mut buf.as_ref()).unwrap(); @@ -165,7 +185,9 @@ mod tests { #[test] fn test_validator_account_try_from() { + let consensus_key = bls12381::PrivateKey::from_seed(1); let account = ValidatorAccount { + consensus_public_key: consensus_key.public_key(), withdrawal_credentials: Address::from([4u8; 20]), balance: 64000000000u64, // 64 ETH in gwei pending_withdrawal_amount: 2000000000u64, // 2 ETH in gwei @@ -185,7 +207,7 @@ mod tests { #[test] fn test_validator_account_insufficient_bytes() { let mut buf = BytesMut::new(); - buf.put(&[0u8; 44][..]); // One byte short + buf.put(&[0u8; 92][..]); // One byte short let result = ValidatorAccount::read(&mut buf.as_ref()); assert!(result.is_err()); @@ -199,30 +221,32 @@ mod tests { #[test] fn test_validator_account_try_from_insufficient_bytes() { - let buf = [0u8; 76]; // One byte short + let buf = [0u8; 92]; // One byte short let result = ValidatorAccount::try_from(buf.as_ref()); assert!(result.is_err()); assert_eq!( result.unwrap_err(), - "ValidatorAccount must be exactly 45 bytes" + "ValidatorAccount must be exactly 93 bytes" ); } #[test] fn test_validator_account_try_from_too_many_bytes() { - let buf = [0u8; 78]; // One byte too many + let buf = [0u8; 94]; // One byte too many let result = ValidatorAccount::try_from(buf.as_ref()); assert!(result.is_err()); assert_eq!( result.unwrap_err(), - "ValidatorAccount must be exactly 45 bytes" + "ValidatorAccount must be exactly 93 bytes" ); } #[test] fn test_validator_account_roundtrip_compatibility() { // Test that our Codec implementation is compatible with TryFrom<&[u8]> + let consensus_key = bls12381::PrivateKey::from_seed(1); let account = ValidatorAccount { + consensus_public_key: consensus_key.public_key(), withdrawal_credentials: Address::from([6u8; 20]), balance: 128000000000u64, // 128 ETH in gwei pending_withdrawal_amount: 4000000000u64, // 4 ETH in gwei @@ -246,9 +270,11 @@ mod tests { #[test] fn test_validator_account_fixed_size() { - assert_eq!(ValidatorAccount::SIZE, 45); + assert_eq!(ValidatorAccount::SIZE, 93); + let consensus_key = bls12381::PrivateKey::from_seed(1); let account = ValidatorAccount { + consensus_public_key: consensus_key.public_key(), withdrawal_credentials: Address::ZERO, balance: 0, pending_withdrawal_amount: 0, @@ -264,7 +290,10 @@ mod tests { #[test] fn test_validator_account_field_ordering() { // Test that fields are encoded/decoded in the correct order + let consensus_key = bls12381::PrivateKey::from_seed(1); + let consensus_public_key = consensus_key.public_key(); let account = ValidatorAccount { + consensus_public_key: consensus_public_key.clone(), withdrawal_credentials: Address::from([ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, @@ -280,9 +309,12 @@ mod tests { let bytes = buf.as_ref(); - // Check withdrawal_credentials (first 20 bytes) + // Check consensus_public_key (first 48 bytes) + assert_eq!(&bytes[0..48], &consensus_public_key.encode()); + + // Check withdrawal_credentials (next 20 bytes) assert_eq!( - &bytes[0..20], + &bytes[48..68], &[ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04 @@ -290,16 +322,16 @@ mod tests { ); // Check balance (next 8 bytes, little-endian) - assert_eq!(&bytes[20..28], &0x0123456789abcdefu64.to_le_bytes()); + assert_eq!(&bytes[68..76], &0x0123456789abcdefu64.to_le_bytes()); // Check pending_withdrawal_amount (next 8 bytes, little-endian) - assert_eq!(&bytes[28..36], &0xfedcba9876543210u64.to_le_bytes()); + assert_eq!(&bytes[76..84], &0xfedcba9876543210u64.to_le_bytes()); // Check status (next 1 byte) - assert_eq!(bytes[36], 2); // SubmittedExitRequest = 2 + assert_eq!(bytes[84], 2); // SubmittedExitRequest = 2 // Check last_deposit_index (last 8 bytes, little-endian) - assert_eq!(&bytes[37..45], &0xa1b2c3d4e5f60708u64.to_le_bytes()); + assert_eq!(&bytes[85..93], &0xa1b2c3d4e5f60708u64.to_le_bytes()); // Verify roundtrip let decoded = ValidatorAccount::read(&mut buf.as_ref()).unwrap(); @@ -336,6 +368,8 @@ mod tests { let mut buf = BytesMut::new(); // Create a buffer with valid data except for an invalid status byte + let consensus_key = bls12381::PrivateKey::from_seed(1); + buf.put(&consensus_key.public_key().encode()[..]); // consensus_public_key buf.put(&[2u8; 20][..]); // withdrawal_credentials buf.put(&1000u64.to_le_bytes()[..]); // balance buf.put(&100u64.to_le_bytes()[..]); // pending_withdrawal_amount diff --git a/types/src/checkpoint.rs b/types/src/checkpoint.rs index 7751d121..016197bc 100644 --- a/types/src/checkpoint.rs +++ b/types/src/checkpoint.rs @@ -132,6 +132,7 @@ mod tests { use commonware_codec::DecodeExt; use ssz::{Decode, Encode}; use std::collections::{HashMap, VecDeque}; + use commonware_cryptography::{bls12381, PrivateKeyExt, Signer}; fn parse_public_key(public_key: &str) -> commonware_cryptography::ed25519::PublicKey { commonware_cryptography::ed25519::PublicKey::decode( @@ -209,7 +210,9 @@ mod tests { pubkey: [5u8; 32], }; + let consensus_key1 = bls12381::PrivateKey::from_seed(1); let validator_account1 = ValidatorAccount { + consensus_public_key: consensus_key1.public_key(), withdrawal_credentials: Address::from([7u8; 20]), balance: 32_000_000_000, // 32 ETH pending_withdrawal_amount: 0, @@ -217,7 +220,9 @@ mod tests { last_deposit_index: 100, }; + let consensus_key2 = bls12381::PrivateKey::from_seed(2); let validator_account2 = ValidatorAccount { + consensus_public_key: consensus_key2.public_key(), withdrawal_credentials: Address::from([8u8; 20]), balance: 16_000_000_000, // 16 ETH pending_withdrawal_amount: 8_000_000_000, // 8 ETH pending @@ -342,7 +347,9 @@ mod tests { pubkey: [5u8; 32], }; + let consensus_key1 = bls12381::PrivateKey::from_seed(1); let validator_account1 = ValidatorAccount { + consensus_public_key: consensus_key1.public_key(), withdrawal_credentials: Address::from([7u8; 20]), balance: 32_000_000_000, // 32 ETH pending_withdrawal_amount: 0, @@ -350,7 +357,9 @@ mod tests { last_deposit_index: 100, }; + let consensus_key2 = bls12381::PrivateKey::from_seed(2); let validator_account2 = ValidatorAccount { + consensus_public_key: consensus_key2.public_key(), withdrawal_credentials: Address::from([8u8; 20]), balance: 16_000_000_000, // 16 ETH pending_withdrawal_amount: 8_000_000_000, // 8 ETH pending @@ -550,7 +559,9 @@ mod tests { pubkey: [5u8; 32], }; + let consensus_key1 = bls12381::PrivateKey::from_seed(1); let validator_account1 = ValidatorAccount { + consensus_public_key: consensus_key1.public_key(), withdrawal_credentials: Address::from([7u8; 20]), balance: 32_000_000_000, // 32 ETH pending_withdrawal_amount: 0, diff --git a/types/src/consensus_state.rs b/types/src/consensus_state.rs index 81a5192a..bd9b8dbb 100644 --- a/types/src/consensus_state.rs +++ b/types/src/consensus_state.rs @@ -1,13 +1,14 @@ use crate::PublicKey; -use crate::account::ValidatorAccount; +use crate::account::{ValidatorAccount, ValidatorStatus}; use crate::checkpoint::Checkpoint; use crate::execution_request::{DepositRequest, WithdrawalRequest}; use crate::withdrawal::PendingWithdrawal; use alloy_eips::eip4895::Withdrawal; use alloy_rpc_types_engine::ForkchoiceState; use bytes::{Buf, BufMut}; -use commonware_codec::{DecodeExt, EncodeSize, Error, Read, Write}; +use commonware_codec::{DecodeExt, EncodeSize, Error, Read, ReadExt, Write}; use std::collections::{HashMap, VecDeque}; +use commonware_cryptography::bls12381; #[derive(Clone, Debug, Default)] pub struct ConsensusState { @@ -115,6 +116,21 @@ impl ConsensusState { .cloned() .collect() } + + pub fn get_validator_keys(&self) -> Vec<(PublicKey, bls12381::PublicKey)> { + let mut peers: Vec<(PublicKey, bls12381::PublicKey)> = self.validator_accounts + .iter() + .filter(|(_, acc)| !(acc.status == ValidatorStatus::Inactive)) + .map(|(v, acc)| { + let mut key_bytes = &v[..]; + let node_public_key = PublicKey::read(&mut key_bytes).expect("failed to parse public key"); + let consensus_public_key = acc.consensus_public_key.clone(); + (node_public_key, consensus_public_key) + }) + .collect(); + peers.sort_by(|lhs, rhs| lhs.0.cmp(&rhs.0)); + peers + } } impl EncodeSize for ConsensusState { @@ -288,6 +304,7 @@ mod tests { use alloy_eips::eip4895::Withdrawal; use alloy_primitives::Address; use commonware_codec::{DecodeExt, Encode}; + use commonware_cryptography::{bls12381, PrivateKeyExt, Signer}; fn create_test_deposit_request(index: u64, amount: u64) -> DepositRequest { let mut withdrawal_credentials = [0u8; 32]; @@ -323,7 +340,9 @@ mod tests { } fn create_test_validator_account(index: u64, balance: u64) -> ValidatorAccount { + let consensus_key = bls12381::PrivateKey::from_seed(1); ValidatorAccount { + consensus_public_key: consensus_key.public_key(), withdrawal_credentials: Address::from([index as u8; 20]), balance, pending_withdrawal_amount: 0, diff --git a/types/src/genesis.rs b/types/src/genesis.rs index 7194f545..c4a06eca 100644 --- a/types/src/genesis.rs +++ b/types/src/genesis.rs @@ -140,7 +140,6 @@ impl Genesis { #[cfg(test)] mod tests { - use std::path::PathBuf; use super::*; #[test] @@ -163,42 +162,4 @@ mod tests { assert_eq!(found_addr, Some(validator.ip_address)); } } - - #[test] -fn test_generate_and_save_bls_keys() { - use commonware_cryptography::{bls12381, PrivateKeyExt, Signer}; - use commonware_codec::Encode; - use std::fs; - use std::path::Path; - - let temp_dir = PathBuf::from("testnet"); - fs::create_dir_all(&temp_dir).unwrap(); - - println!("\nGenerating 4 BLS key pairs:"); - println!("Keys saved to: {}\n", temp_dir.display()); - - for i in 0..4 { - let private_key = bls12381::PrivateKey::from_seed(i); - let public_key = private_key.public_key(); - - // Save private key to disk - fs::create_dir_all(&temp_dir.join(format!("node{}", i))).unwrap(); - let private_key_path = temp_dir.join(format!("node{}", i)).join("consensus.pem"); - let private_key_bytes = private_key.encode(); - fs::write(&private_key_path, &private_key_bytes).unwrap(); - - // Print public key in hex format - let public_key_hex = public_key.to_string(); - println!("Validator {}: {}", i, public_key_hex); - } - - // Verify we can read the keys back - for i in 0..4 { - let private_key_path = temp_dir.join(format!("node{}", i)).join("consensus.pem"); - assert!(Path::new(&private_key_path).exists()); - } - - // Cleanup - //fs::remove_dir_all(&temp_dir).unwrap(); - } } diff --git a/types/src/keystore.rs b/types/src/keystore.rs index 6cae28fd..0c3167d1 100644 --- a/types/src/keystore.rs +++ b/types/src/keystore.rs @@ -6,4 +6,6 @@ use zeroize::{Zeroize, ZeroizeOnDrop}; pub struct KeyStore { pub node_key: C, pub consensus_key: PrivateKey, -} \ No newline at end of file +} + +// TODO(matthias): do we have to explicitly call zeroize() on the members? \ No newline at end of file diff --git a/types/src/lib.rs b/types/src/lib.rs index 64173205..fb12af3d 100644 --- a/types/src/lib.rs +++ b/types/src/lib.rs @@ -13,6 +13,8 @@ pub mod registry; pub mod reth; pub mod utils; pub mod withdrawal; +pub mod scheme; +pub mod keystore; use alloy_rpc_types_engine::ForkchoiceState; pub use block::*; diff --git a/types/src/registry.rs b/types/src/registry.rs index 6774de23..b5c0e0ac 100644 --- a/types/src/registry.rs +++ b/types/src/registry.rs @@ -9,6 +9,7 @@ use futures::channel::mpsc::{UnboundedReceiver, UnboundedSender}; #[derive(Default, Clone, Debug)] struct Inner { sets: BTreeMap>, + #[allow(clippy::type_complexity)] subscribers: Vec, Ordered)>>, } @@ -86,7 +87,7 @@ impl Manager for Registry { fn peer_set(&mut self, id: u64) -> impl Future>> + Send { let inner = self.inner.write().unwrap(); - let set = inner.sets.get(&id).map(|s| s.clone()); + let set = inner.sets.get(&id).cloned(); async move { set } } diff --git a/types/src/scheme.rs b/types/src/scheme.rs new file mode 100644 index 00000000..b6b0d7e4 --- /dev/null +++ b/types/src/scheme.rs @@ -0,0 +1,105 @@ +use std::collections::HashMap; +use std::sync::{Arc, Mutex}; +use commonware_consensus::simplex::signing_scheme::{self, Scheme}; +use commonware_consensus::types::Epoch; +use commonware_cryptography::bls12381::primitives::variant::Variant; +use commonware_cryptography::{PublicKey, Signer}; +use commonware_cryptography::bls12381::primitives::group; +use commonware_utils::set::{Ordered, OrderedAssociated}; + +pub type MultisigScheme = signing_scheme::bls12381_multisig::Scheme<::PublicKey, V>; + +/// Supplies the signing scheme the marshal should use for a given epoch. +pub trait SchemeProvider: Clone + Send + Sync + 'static { + /// The signing scheme to provide. + type Scheme: Scheme; + + /// Return the signing scheme that corresponds to `epoch`. + fn scheme(&self, epoch: Epoch) -> Option>; +} + +#[derive(Clone)] +pub struct SummitSchemeProvider { + #[allow(clippy::type_complexity)] + schemes: Arc>>>>, + signer: C, + bls_private_key: group::Private, +} + +impl SummitSchemeProvider { + pub fn new(signer: C, bls_private_key: group::Private) -> Self { + Self { + schemes: Arc::new(Mutex::new(HashMap::new())), + signer, + bls_private_key, + } + } + + /// Registers a new signing scheme for the given epoch. + /// + /// Returns `false` if a scheme was already registered for the epoch. + pub fn register(&self, epoch: Epoch, scheme: MultisigScheme) -> bool { + let mut schemes = self.schemes.lock().unwrap(); + schemes.insert(epoch, Arc::new(scheme)).is_none() + } + + /// Unregisters the signing scheme for the given epoch. + /// + /// Returns `false` if no scheme was registered for the epoch. + pub fn unregister(&self, epoch: &Epoch) -> bool { + let mut schemes = self.schemes.lock().unwrap(); + schemes.remove(epoch).is_some() + } +} + +pub trait EpochSchemeProvider { + type Variant: Variant; + type PublicKey: PublicKey; + type Scheme: Scheme; + + /// Returns a [Scheme] for the given [EpochTransition]. + fn scheme_for_epoch( + &self, + transition: &EpochTransition, + ) -> Self::Scheme; +} + +impl SchemeProvider for SummitSchemeProvider { + type Scheme = MultisigScheme; + + fn scheme(&self, epoch: Epoch) -> Option>> { + let schemes = self.schemes.lock().unwrap(); + schemes.get(&epoch).cloned() + } +} + +impl EpochSchemeProvider for SummitSchemeProvider { + type Variant = V; + type PublicKey = C::PublicKey; + type Scheme = MultisigScheme; + + fn scheme_for_epoch( + &self, + transition: &EpochTransition, + ) -> Self::Scheme { + let participants: OrderedAssociated = + transition.dealers + .iter() + .cloned() + .zip(transition.bls_keys.iter().cloned()) + .collect(); + + MultisigScheme::::new(participants, self.bls_private_key.clone()) + } +} + +/// A notification of an epoch transition. +pub struct EpochTransition { + /// The epoch to transition to. + pub epoch: Epoch, + /// The dealers for the epoch (identity keys). + pub dealers: Ordered

, + /// The BLS public keys for the epoch. + /// Contains the BLS public keys corresponding to each dealer. + pub bls_keys: Vec, +} \ No newline at end of file From 6e6400c79f51589382a4ae81b36c1d9f471286dd Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Thu, 6 Nov 2025 15:18:06 -0500 Subject: [PATCH 28/81] feat: add epoch to header and block --- types/src/block.rs | 24 ++++++++++++++++++------ types/src/header.rs | 23 ++++++++++++++++++++--- 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/types/src/block.rs b/types/src/block.rs index 57ae65ca..0212c638 100644 --- a/types/src/block.rs +++ b/types/src/block.rs @@ -1,4 +1,3 @@ -use std::marker::PhantomData; use crate::{Header, PublicKey}; use alloy_consensus::{Block as AlloyBlock, TxEnvelope}; use alloy_primitives::{Bytes as AlloyBytes, U256}; @@ -9,11 +8,17 @@ use commonware_codec::{EncodeSize, Error, Read, ReadExt as _, Write}; use commonware_consensus::Block as ConsensusBlock; use commonware_consensus::{ Viewable, - simplex::{signing_scheme::bls12381_multisig::Scheme, types::{Finalization, Notarization}}, + simplex::{ + signing_scheme::bls12381_multisig::Scheme, + types::{Finalization, Notarization}, + }, }; -use commonware_cryptography::{Committable, Digestible, Hasher, Sha256, sha256::Digest, Signer, ed25519}; use commonware_cryptography::bls12381::primitives::variant::{MinPk, Variant}; +use commonware_cryptography::{ + Committable, Digestible, Hasher, Sha256, Signer, ed25519, sha256::Digest, +}; use ssz::Encode as _; +use std::marker::PhantomData; #[derive(Clone, Debug, PartialEq, Eq)] pub struct Block { @@ -46,6 +51,7 @@ impl Block { payload: ExecutionPayloadV3, execution_requests: Vec, block_value: U256, + epoch: u64, view: u64, checkpoint_hash: Option, prev_epoch_header_hash: Digest, @@ -76,6 +82,7 @@ impl Block { parent, height, timestamp, + epoch, view, payload_hash, execution_request_hash, @@ -140,6 +147,7 @@ impl Block { parent: genesis_hash.into(), height: 0, timestamp: 0, + epoch: 0, view: 1, payload_hash, execution_request_hash: [0; 32].into(), @@ -314,7 +322,8 @@ impl Read for Notarized { type Cfg = (); fn read_cfg(buf: &mut impl Buf, _: &Self::Cfg) -> Result { - let proof = Notarization::, Digest>::read_cfg(buf, &buf.remaining())?; // todo: get a test on this to make sure buf.remaining is safe + let proof = + Notarization::, Digest>::read_cfg(buf, &buf.remaining())?; // todo: get a test on this to make sure buf.remaining is safe let block = Block::read(buf)?; // Ensure the proof is for the block @@ -357,7 +366,8 @@ impl Read for Finalized { type Cfg = (); fn read_cfg(buf: &mut impl Buf, _: &Self::Cfg) -> Result { - let proof = Finalization::, Digest>::read_cfg(buf, &buf.remaining())?; + let proof = + Finalization::, Digest>::read_cfg(buf, &buf.remaining())?; let block = Block::read(buf)?; // Ensure the proof is for the block @@ -389,8 +399,8 @@ mod test { use alloy_primitives::{Bytes as AlloyBytes, U256, hex}; use alloy_rpc_types_engine::{ExecutionPayloadV1, ExecutionPayloadV2}; use commonware_codec::{DecodeExt as _, Encode as _}; - use commonware_cryptography::ed25519; use commonware_cryptography::bls12381::primitives::variant::MinPk; + use commonware_cryptography::ed25519; fn create_test_public_key(seed: u8) -> PublicKey { let test_keys = [ @@ -455,6 +465,7 @@ mod test { vec![Default::default()], U256::ZERO, 42, + 1, Some([0u8; 32].into()), [0u8; 32].into(), added_validators, @@ -503,6 +514,7 @@ mod test { Vec::new(), U256::ZERO, 42, + 1, Some([0u8; 32].into()), [0u8; 32].into(), added_validators, diff --git a/types/src/header.rs b/types/src/header.rs index 81f11e3f..1761db3e 100644 --- a/types/src/header.rs +++ b/types/src/header.rs @@ -13,6 +13,7 @@ pub struct Header { pub parent: Digest, pub height: u64, pub timestamp: u64, + pub epoch: u64, pub view: u64, pub payload_hash: Digest, pub execution_request_hash: Digest, @@ -31,6 +32,7 @@ impl Header { parent: Digest, height: u64, timestamp: u64, + epoch: u64, view: u64, payload_hash: Digest, execution_request_hash: Digest, @@ -67,6 +69,7 @@ impl Header { parent, height, timestamp, + epoch, view, payload_hash, execution_request_hash, @@ -87,7 +90,7 @@ impl ssz::Encode for Header { fn ssz_append(&self, buf: &mut Vec) { let offset = <[u8; 32] as ssz::Encode>::ssz_fixed_len() * 5 // parent, payload_hash, execution_request_hash, checkpoint_hash, prev_epoch_header_hash - + ::ssz_fixed_len() * 3 // height, timestamp, view + + ::ssz_fixed_len() * 4 // height, timestamp, epoch, view + ::ssz_fixed_len() // block_value + as ssz::Encode>::ssz_fixed_len() * 2; // added_validators, removed_validators offsets @@ -130,6 +133,7 @@ impl ssz::Encode for Header { encoder.append(&parent); encoder.append(&self.height); encoder.append(&self.timestamp); + encoder.append(&self.epoch); encoder.append(&self.view); encoder.append(&payload_hash); encoder.append(&execution_request_hash); @@ -143,7 +147,7 @@ impl ssz::Encode for Header { fn ssz_bytes_len(&self) -> usize { let fixed_size = <[u8; 32] as ssz::Encode>::ssz_fixed_len() * 5 // parent, payload_hash, execution_request_hash, checkpoint_hash, prev_epoch_header_hash - + ::ssz_fixed_len() * 3 // height, timestamp, view + + ::ssz_fixed_len() * 4 // height, timestamp, epoch, view + ::ssz_fixed_len(); // block_value // Calculate length as if they were Vec<[u8; 32]> @@ -167,6 +171,7 @@ impl ssz::Decode for Header { builder.register_type::<[u8; 32]>()?; // parent builder.register_type::()?; // height builder.register_type::()?; // timestamp + builder.register_type::()?; // epoch builder.register_type::()?; // view builder.register_type::<[u8; 32]>()?; // payload_hash builder.register_type::<[u8; 32]>()?; // execution_request_hash @@ -181,6 +186,7 @@ impl ssz::Decode for Header { let parent: [u8; 32] = decoder.decode_next()?; let height: u64 = decoder.decode_next()?; let timestamp: u64 = decoder.decode_next()?; + let epoch: u64 = decoder.decode_next()?; let view: u64 = decoder.decode_next()?; let payload_hash: [u8; 32] = decoder.decode_next()?; let execution_request_hash: [u8; 32] = decoder.decode_next()?; @@ -213,6 +219,7 @@ impl ssz::Decode for Header { parent.into(), height, timestamp, + epoch, view, payload_hash.into(), execution_request_hash.into(), @@ -365,7 +372,13 @@ mod test { use super::*; use alloy_primitives::{U256, hex}; use commonware_codec::{DecodeExt as _, Encode as _}; - use commonware_consensus::{simplex::{signing_scheme::{ed25519::Certificate, utils::Signers}, types::{Finalization, Proposal}}, types::Round}; + use commonware_consensus::{ + simplex::{ + signing_scheme::{ed25519::Certificate, utils::Signers}, + types::{Finalization, Proposal}, + }, + types::Round, + }; use commonware_cryptography::ed25519::PrivateKey; use commonware_cryptography::{PrivateKeyExt, Signer}; use ssz::Decode; @@ -401,6 +414,7 @@ mod test { 27, 2727, 42, + 1, [1u8; 32].into(), [2u8; 32].into(), [3u8; 32].into(), @@ -424,6 +438,7 @@ mod test { 27, 2727, 42, + 1, [1u8; 32].into(), [2u8; 32].into(), [3u8; 32].into(), @@ -471,6 +486,7 @@ mod test { 27, 2727, 42, + 1, [1u8; 32].into(), [2u8; 32].into(), [3u8; 32].into(), @@ -529,6 +545,7 @@ mod test { 27, 2727, 42, + 1, [1u8; 32].into(), [2u8; 32].into(), [3u8; 32].into(), From 230677951763ecc1424d51617f393651b5d5796c Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Thu, 6 Nov 2025 15:21:16 -0500 Subject: [PATCH 29/81] feat: update application --- application/src/actor.rs | 58 ++++++++++++++++++++++---------------- application/src/ingress.rs | 34 +++++++++++----------- application/src/lib.rs | 1 + 3 files changed, 52 insertions(+), 41 deletions(-) diff --git a/application/src/actor.rs b/application/src/actor.rs index 22756587..09d671d4 100644 --- a/application/src/actor.rs +++ b/application/src/actor.rs @@ -14,19 +14,22 @@ use futures::{ use rand::Rng; use tokio_util::sync::CancellationToken; -use commonware_consensus::simplex::types::View; +use commonware_consensus::types::View; use futures::task::{Context, Poll}; use std::{ pin::Pin, sync::{Arc, Mutex}, time::Duration, }; +use commonware_consensus::simplex::signing_scheme::Scheme; +use commonware_consensus::types::Round; +use commonware_cryptography::Signer; use summit_finalizer::FinalizerMailbox; use tracing::{error, info, warn}; #[cfg(feature = "prom")] use metrics::histogram; -use summit_syncer::ingress::Mailbox as SyncerMailbox; +use summit_syncer::ingress::mailbox::Mailbox as SyncerMailbox; use summit_types::{Block, Digest, EngineClient}; // Define a future that checks if the oneshot channel is closed using a mutable reference @@ -54,6 +57,8 @@ fn oneshot_closed_future(sender: &mut oneshot::Sender) -> ChannelClosedFut pub struct Actor< R: Storage + Metrics + Clock + Spawner + governor::clock::Clock + Rng, C: EngineClient, + S: Scheme, + K: Signer, > { context: R, mailbox: mpsc::Receiver, @@ -63,10 +68,10 @@ pub struct Actor< cancellation_token: CancellationToken, } -impl - Actor +impl + Actor { - pub async fn new(context: R, cfg: ApplicationConfig) -> (Self, Mailbox) { + pub async fn new(context: R, cfg: ApplicationConfig) -> (Self, Mailbox) { let (tx, rx) = mpsc::channel(cfg.mailbox_size); let genesis_hash = cfg.genesis_hash; @@ -84,11 +89,11 @@ impl Handle<()> { + pub fn start(mut self, syncer: SyncerMailbox, finalizer: FinalizerMailbox) -> Handle<()> { self.context.spawn_ref()(self.run(syncer, finalizer)) } - pub async fn run(mut self, mut syncer: SyncerMailbox, mut finalizer: FinalizerMailbox) { + pub async fn run(mut self, mut syncer: SyncerMailbox, mut finalizer: FinalizerMailbox) { let rand_id: u8 = rand::random(); let mut signal = self.context.stopped().fuse(); let cancellation_token = self.cancellation_token.clone(); @@ -99,20 +104,23 @@ impl { - info!("Handling message Genesis"); - let _ = response.send(self.genesis_hash.into()); + Message::Genesis { response, epoch } => { + if epoch == 0 { + let _ = response.send(self.genesis_hash.into()); + } else { + todo!("TODO(matthias): for later epochs, this has to be the hash of the last block from the prev epoch"); + } } Message::Propose { - view, + round, parent, mut response, } => { - info!("{rand_id} Handling message Propose view: {}", view); + info!("{rand_id} Handling message Propose round: {}", round); let built = self.built_block.clone(); select! { - res = self.handle_proposal(parent, &mut syncer,&mut finalizer, view) => { + res = self.handle_proposal(parent, &mut syncer,&mut finalizer, round) => { match res { Ok(block) => { // store block @@ -125,12 +133,12 @@ impl warn!("Failed to create a block for height {view}: {e}") + Err(e) => warn!("Failed to create a block for round {round}: {e}") } }, _ = oneshot_closed_future(&mut response) => { // simplex dropped receiver - warn!(view, "proposal aborted"); + warn!(round, "proposal aborted"); } } } @@ -153,12 +161,12 @@ impl { - info!("{rand_id} Handling message Verify view: {}", view); + info!("{rand_id} Handling message Verify round: {}", round); // Get the parent block let parent_request = if parent.1 == self.genesis_hash.into() { Either::Left(future::ready(Ok(Block::genesis(self.genesis_hash)))) @@ -179,9 +187,8 @@ impl { - warn!(view, "verify aborted"); + warn!(round, "verify aborted"); } } } @@ -214,9 +221,9 @@ impl, finalizer: &mut FinalizerMailbox, - view: View, + round: Round, ) -> Result { #[cfg(feature = "prom")] let proposal_start = std::time::Instant::now(); @@ -324,6 +331,8 @@ impl Drop - for Actor +impl Drop + for Actor { fn drop(&mut self) { self.cancellation_token.cancel(); diff --git a/application/src/ingress.rs b/application/src/ingress.rs index 79fe04a0..e32437fd 100644 --- a/application/src/ingress.rs +++ b/application/src/ingress.rs @@ -1,8 +1,7 @@ -use commonware_consensus::{ - Automaton, Relay, - simplex::types::{Context, View}, -}; +use commonware_consensus::{Automaton, Relay, simplex::types::Context, types::View, Epochable}; +use commonware_consensus::types::{Epoch, Round}; use commonware_cryptography::sha256::Digest; +use commonware_cryptography::Signer; use futures::{ SinkExt, channel::{mpsc, oneshot}, @@ -10,10 +9,11 @@ use futures::{ pub enum Message { Genesis { + epoch: Epoch, response: oneshot::Sender, }, Propose { - view: View, + round: Round, parent: (View, Digest), response: oneshot::Sender, }, @@ -21,7 +21,7 @@ pub enum Message { payload: Digest, }, Verify { - view: View, + round: Round, parent: (View, Digest), payload: Digest, response: oneshot::Sender, @@ -29,36 +29,36 @@ pub enum Message { } #[derive(Clone)] -pub struct Mailbox { +pub struct Mailbox { sender: mpsc::Sender, } -impl Mailbox { +impl Mailbox { pub fn new(sender: mpsc::Sender) -> Self { Self { sender } } } -impl Automaton for Mailbox { +impl Automaton for Mailbox { + type Context = Context; type Digest = Digest; - type Context = Context; - async fn genesis(&mut self) -> Self::Digest { + async fn genesis(&mut self, epoch: ::Epoch) -> Self::Digest { let (response, receiver) = oneshot::channel(); self.sender - .send(Message::Genesis { response }) + .send(Message::Genesis { response, epoch }) .await .expect("Failed to send genesis"); receiver.await.expect("Failed to receive genesis") } - async fn propose(&mut self, context: Context) -> oneshot::Receiver { + async fn propose(&mut self, context: Context) -> oneshot::Receiver { // If we linked payloads to their parent, we would include // the parent in the `Context` in the payload. let (response, receiver) = oneshot::channel(); self.sender .send(Message::Propose { - view: context.view, + round: context.round, parent: context.parent, response, }) @@ -69,7 +69,7 @@ impl Automaton for Mailbox { async fn verify( &mut self, - context: Context, + context: Context, payload: Self::Digest, ) -> oneshot::Receiver { // If we linked payloads to their parent, we would verify @@ -77,7 +77,7 @@ impl Automaton for Mailbox { let (response, receiver) = oneshot::channel(); self.sender .send(Message::Verify { - view: context.view, + round: context.round, parent: context.parent, payload, response, @@ -88,7 +88,7 @@ impl Automaton for Mailbox { } } -impl Relay for Mailbox { +impl Relay for Mailbox { type Digest = Digest; async fn broadcast(&mut self, digest: Self::Digest) { diff --git a/application/src/lib.rs b/application/src/lib.rs index cf6cd277..a905d774 100644 --- a/application/src/lib.rs +++ b/application/src/lib.rs @@ -5,4 +5,5 @@ pub mod ingress; pub use ingress::Mailbox; pub mod config; + pub use config::*; From 2ecb81b7b088d53fc680419ad7cfaa9743aaa302 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Thu, 6 Nov 2025 16:24:38 -0500 Subject: [PATCH 30/81] feat: make finalized header generic over scheme --- types/src/header.rs | 45 ++++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/types/src/header.rs b/types/src/header.rs index 1761db3e..9f29a540 100644 --- a/types/src/header.rs +++ b/types/src/header.rs @@ -4,7 +4,8 @@ use crate::PublicKey; use alloy_primitives::U256; use bytes::{Buf, BufMut}; use commonware_codec::{EncodeSize, Error, Read, Write}; -use commonware_consensus::simplex::{signing_scheme::ed25519::Scheme, types::Finalization}; +use commonware_consensus::simplex::signing_scheme::Scheme; +use commonware_consensus::simplex::types::Finalization; use commonware_cryptography::{Hasher, Sha256, sha256::Digest}; use ssz::Encode as _; @@ -263,18 +264,18 @@ impl Read for Header { } #[derive(Clone, Debug, PartialEq, Eq)] -pub struct FinalizedHeader { +pub struct FinalizedHeader { pub header: Header, - pub finalized: Finalization, + pub finalized: Finalization, } -impl FinalizedHeader { - pub fn new(header: Header, finalized: Finalization) -> Self { +impl FinalizedHeader { + pub fn new(header: Header, finalized: Finalization) -> Self { Self { header, finalized } } } -impl ssz::Encode for FinalizedHeader { +impl ssz::Encode for FinalizedHeader { fn is_ssz_fixed_len() -> bool { false } @@ -301,7 +302,10 @@ impl ssz::Encode for FinalizedHeader { } } -impl ssz::Decode for FinalizedHeader { +impl ssz::Decode for FinalizedHeader +where + ::Cfg: From, +{ fn is_ssz_fixed_len() -> bool { false } @@ -319,7 +323,8 @@ impl ssz::Decode for FinalizedHeader { .map_err(|e| ssz::DecodeError::BytesInvalid(format!("{e:?}")))?; let mut finalized_buf = finalized_bytes.as_slice(); - let finalized = Finalization::read_cfg(&mut finalized_buf, &finalized_bytes.len()) + let cfg = ::Cfg::from(finalized_buf.remaining()); + let finalized = Finalization::::read_cfg(&mut finalized_buf, &cfg) .map_err(|e| ssz::DecodeError::BytesInvalid(format!("{e:?}")))?; // Ensure the finalization is for the header @@ -333,13 +338,13 @@ impl ssz::Decode for FinalizedHeader { } } -impl EncodeSize for FinalizedHeader { +impl EncodeSize for FinalizedHeader { fn encode_size(&self) -> usize { self.ssz_bytes_len() + ssz::BYTES_PER_LENGTH_OFFSET } } -impl Write for FinalizedHeader { +impl Write for FinalizedHeader { fn write(&self, buf: &mut impl BufMut) { let ssz_bytes = &*self.as_ssz_bytes(); let bytes_len = ssz_bytes.len() as u32; @@ -349,7 +354,10 @@ impl Write for FinalizedHeader { } } -impl Read for FinalizedHeader { +impl Read for FinalizedHeader +where + ::Cfg: From, +{ type Cfg = (); fn read_cfg(buf: &mut impl Buf, _cfg: &Self::Cfg) -> Result { @@ -379,6 +387,7 @@ mod test { }, types::Round, }; + use commonware_consensus::simplex::signing_scheme::ed25519; use commonware_cryptography::ed25519::PrivateKey; use commonware_cryptography::{PrivateKeyExt, Signer}; use ssz::Decode; @@ -469,12 +478,14 @@ mod test { }, }; - let finalized_header = FinalizedHeader::new(header.clone(), finalized); + let finalized_header = FinalizedHeader::::new(header.clone(), finalized); let encoded = finalized_header.encode(); - let decoded = FinalizedHeader::decode(encoded).unwrap(); + let decoded = FinalizedHeader::::decode(encoded).unwrap(); + + assert_eq!(finalized_header.finalized, decoded.finalized); + assert_eq!(finalized_header.header, decoded.header); - assert_eq!(finalized_header, decoded); assert_eq!(finalized_header.header, header); } @@ -522,13 +533,13 @@ mod test { }, }; - let finalized_header = FinalizedHeader { + let finalized_header: FinalizedHeader = FinalizedHeader { header, finalized: wrong_finalized, }; let encoded = finalized_header.as_ssz_bytes(); - let result = FinalizedHeader::from_ssz_bytes(&encoded); + let result = FinalizedHeader::::from_ssz_bytes(&encoded); assert!(result.is_err()); println!("{:?}", result); @@ -569,7 +580,7 @@ mod test { }, }; - let finalized_header = FinalizedHeader::new(header, finalized); + let finalized_header = FinalizedHeader::::new(header, finalized); let ssz_len = finalized_header.ssz_bytes_len(); let encode_len = finalized_header.encode_size(); From 702faa19ad6f3d8ca716162f7bb636b0bba2525f Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Fri, 7 Nov 2025 12:04:13 -0500 Subject: [PATCH 31/81] feat: implement consensus block trait for BlockEnvelope --- types/src/block.rs | 152 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 144 insertions(+), 8 deletions(-) diff --git a/types/src/block.rs b/types/src/block.rs index 0212c638..8af21ce4 100644 --- a/types/src/block.rs +++ b/types/src/block.rs @@ -25,8 +25,8 @@ pub struct Block { pub header: Header, pub payload: ExecutionPayloadV3, pub execution_requests: Vec, - pub _signer_type: PhantomData, - pub _variant: PhantomData, + pub _signer_marker: PhantomData, + pub _variant_marker: PhantomData, } impl Block { @@ -97,8 +97,8 @@ impl Block { header, payload, execution_requests, - _signer_type: PhantomData, - _variant: PhantomData, + _signer_marker: PhantomData, + _variant_marker: PhantomData, } } @@ -131,8 +131,8 @@ impl Block { header, payload, execution_requests, - _signer_type: PhantomData, - _variant: PhantomData, + _signer_marker: PhantomData, + _variant_marker: PhantomData, }) } @@ -162,8 +162,8 @@ impl Block { header, payload: ExecutionPayloadV3::from_block_slow(&AlloyBlock::::default()), execution_requests: Default::default(), - _signer_type: PhantomData, - _variant: PhantomData, + _signer_marker: PhantomData, + _variant_marker: PhantomData, } } @@ -393,6 +393,72 @@ pub struct BlockEnvelope { pub finalized: Option, Digest>>, } +impl Digestible for BlockEnvelope { + type Digest = Digest; + + fn digest(&self) -> Digest { + self.block.header.digest + } +} + +impl Committable for BlockEnvelope { + type Commitment = Digest; + + fn commitment(&self) -> Digest { + self.block.header.digest + } +} + +impl ConsensusBlock for BlockEnvelope { + fn height(&self) -> u64 { + self.block.header.height + } + + fn parent(&self) -> Self::Commitment { + self.block.header.parent + } +} + +impl Read for BlockEnvelope { + type Cfg = (); + + fn read_cfg(buf: &mut impl Buf, _: &Self::Cfg) -> Result { + let block = Block::::read(buf)?; + let has_finalized = buf.get_u8(); + let finalized = if has_finalized == 1 { + Some(Finalization::, Digest>::read_cfg( + buf, + &buf.remaining(), + )?) + } else { + None + }; + Ok(Self { block, finalized }) + } +} + +impl Write for BlockEnvelope { + fn write(&self, buf: &mut impl BufMut) { + self.block.write(buf); + if let Some(ref finalized) = self.finalized { + buf.put_u8(1u8); + finalized.write(buf); + } else { + buf.put_u8(0u8); + } + } +} + +impl EncodeSize for BlockEnvelope { + fn encode_size(&self) -> usize { + let mut size = self.block.encode_size() + 1; // +1 for the has_finalized flag + if let Some(ref finalized) = self.finalized { + size += finalized.encode_size(); + } + size + } +} + #[cfg(test)] mod test { use super::*; @@ -557,4 +623,74 @@ mod test { assert_eq!(actual_encoded.len(), pure_ssz.len() + 4); assert_eq!(actual_encoded.len(), encode_len); } + + #[test] + fn test_block_envelope_without_finalization() { + let block = Block::::genesis([0; 32]); + let envelope = BlockEnvelope { + block: block.clone(), + finalized: None, + }; + + // Test encoding and decoding + let encoded = envelope.encode(); + let decoded = BlockEnvelope::::decode(encoded.clone()).unwrap(); + + // Verify round-trip: encode the decoded value and compare bytes + let re_encoded = decoded.encode(); + assert_eq!( + encoded, re_encoded, + "Round-trip encoding should be identical" + ); + + // Verify structure + assert!(decoded.finalized.is_none()); + assert_eq!(envelope.block.header.height, decoded.block.header.height); + assert_eq!( + envelope.block.header.timestamp, + decoded.block.header.timestamp + ); + } + + #[test] + fn test_block_envelope_encode_size_without_finalization() { + let block = Block::::genesis([0; 32]); + let envelope = BlockEnvelope { + block: block.clone(), + finalized: None, + }; + + let encode_size = envelope.encode_size(); + let actual_encoded = envelope.encode(); + + // Size should be block size + 1 byte for the flag + assert_eq!(actual_encoded.len(), encode_size); + assert_eq!(encode_size, block.encode_size() + 1); + } + + #[test] + fn test_block_envelope_digestible() { + let block = Block::::genesis([0; 32]); + let envelope = BlockEnvelope { + block: block.clone(), + finalized: None, + }; + + // BlockEnvelope digest should match the underlying block digest + assert_eq!(envelope.digest(), block.digest()); + assert_eq!(envelope.commitment(), block.commitment()); + } + + #[test] + fn test_block_envelope_consensus_block() { + let block = Block::::genesis([0; 32]); + let envelope = BlockEnvelope { + block: block.clone(), + finalized: None, + }; + + // BlockEnvelope should expose the same ConsensusBlock properties as the underlying block + assert_eq!(envelope.height(), block.height()); + assert_eq!(envelope.parent(), block.parent()); + } } From e968f2f7e28ad2e19f4b2ad2a06a892ffbebe7d1 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Fri, 7 Nov 2025 17:07:46 -0500 Subject: [PATCH 32/81] feat: receive finalized blocks via finalizer mailbox --- finalizer/Cargo.toml | 4 +- finalizer/src/actor.rs | 158 +++++++++++++++++++++++++-------------- finalizer/src/config.rs | 8 +- finalizer/src/db.rs | 127 +++++++++++++++++++++---------- finalizer/src/ingress.rs | 30 ++++++-- finalizer/src/lib.rs | 2 +- 6 files changed, 224 insertions(+), 105 deletions(-) diff --git a/finalizer/Cargo.toml b/finalizer/Cargo.toml index 3eaf0762..03fc1209 100644 --- a/finalizer/Cargo.toml +++ b/finalizer/Cargo.toml @@ -6,13 +6,14 @@ edition.workspace = true [dependencies] summit-types.workspace = true summit-syncer.workspace = true +summit-orchestrator.workspace = true commonware-codec.workspace = true commonware-consensus.workspace = true commonware-cryptography.workspace = true commonware-runtime.workspace = true commonware-storage.workspace = true -commonware-resolver.workspace = true +commonware-p2p.workspace = true commonware-utils.workspace = true alloy-eips.workspace = true @@ -24,6 +25,7 @@ governor.workspace = true rand.workspace = true tokio-util.workspace = true tracing.workspace = true +hex.workspace = true # Only used for tests, but it cannot be in dep-dependencies, because diff --git a/finalizer/src/actor.rs b/finalizer/src/actor.rs index 45d79946..2abdf74d 100644 --- a/finalizer/src/actor.rs +++ b/finalizer/src/actor.rs @@ -1,14 +1,18 @@ use crate::db::{Config as StateConfig, FinalizerState}; -use crate::{FinalizerConfig, FinalizerMailbox, FinalizerMessage, block_fetcher::BlockFetcher}; +use crate::{FinalizerConfig, FinalizerMailbox, FinalizerMessage}; use alloy_eips::eip4895::Withdrawal; use alloy_primitives::Address; #[cfg(debug_assertions)] -use alloy_primitives::hex; use alloy_rpc_types_engine::ForkchoiceState; use commonware_codec::{DecodeExt as _, ReadExt as _}; -use commonware_cryptography::{Hasher, Sha256, Verifier as _}; -use commonware_resolver::p2p::Coordinator; -use commonware_runtime::{Clock, Handle, Metrics, Spawner, Storage}; +use commonware_consensus::simplex::signing_scheme::{Scheme, bls12381_multisig}; +use commonware_consensus::simplex::types::Finalization; +use commonware_cryptography::bls12381::primitives::variant::Variant; +use commonware_cryptography::{ + Digestible, Hasher, PrivateKeyExt, Sha256, Signer, Verifier as _, bls12381, +}; +use commonware_p2p::Manager; +use commonware_runtime::{Clock, ContextCell, Handle, Metrics, Spawner, Storage, spawn_cell}; use commonware_storage::translator::TwoCap; use commonware_utils::{NZU64, NZUsize, hex}; use futures::channel::{mpsc, oneshot}; @@ -17,11 +21,12 @@ use futures::{FutureExt, StreamExt as _, select}; use metrics::{counter, histogram}; #[cfg(debug_assertions)] use prometheus_client::metrics::gauge::Gauge; -use rand::Rng; +use rand::{CryptoRng, Rng}; use std::collections::BTreeMap; +use std::marker::PhantomData; use std::num::NonZero; use std::time::Instant; -use summit_syncer::Orchestrator; +use summit_syncer::Update; use summit_types::account::{ValidatorAccount, ValidatorStatus}; use summit_types::checkpoint::Checkpoint; use summit_types::consensus_state_query::{ConsensusStateRequest, ConsensusStateResponse}; @@ -41,13 +46,16 @@ pub struct Finalizer< R: Storage + Metrics + Clock + Spawner + governor::clock::Clock + Rng, C: EngineClient, O: NetworkOracle, + S: Signer, + Z: Scheme, + V: Variant, > { - mailbox: mpsc::Receiver, + mailbox: mpsc::Receiver>>, pending_height_notifys: BTreeMap>>, - context: R, + context: ContextCell, engine_client: C, registry: Registry, - db: FinalizerState, + db: FinalizerState, state: ConsensusState, genesis_hash: [u8; 32], validator_max_withdrawals_per_block: usize, @@ -57,18 +65,27 @@ pub struct Finalizer< validator_withdrawal_period: u64, // in blocks validator_onboarding_limit_per_block: usize, oracle: O, - public_key: PublicKey, + orchestrator_mailbox: summit_orchestrator::Mailbox, + node_public_key: PublicKey, validator_exit: bool, cancellation_token: CancellationToken, + _signer_marker: PhantomData, + _variant_marker: PhantomData, } impl< R: Storage + Metrics + Clock + Spawner + governor::clock::Clock + Rng, C: EngineClient, O: NetworkOracle, -> Finalizer + S: Signer, + Z: Scheme, + V: Variant, +> Finalizer { - pub async fn new(context: R, cfg: FinalizerConfig) -> (Self, FinalizerMailbox) { + pub async fn new( + context: R, + cfg: FinalizerConfig, + ) -> (Self, FinalizerMailbox>) { let (tx, rx) = mpsc::channel(cfg.mailbox_size); // todo(dalton) pull mailbox size from config let state_cfg = StateConfig { log_journal_partition: format!("{}-finalizer_state-log", cfg.db_prefix), @@ -82,7 +99,8 @@ impl< buffer_pool: cfg.buffer_pool, }; - let db = FinalizerState::new(context.with_label("finalizer_state"), state_cfg).await; + let db = + FinalizerState::::new(context.with_label("finalizer_state"), state_cfg).await; // Check if the state exists in the database. Otherwise, use the initial state. // The initial state could be from the genesis or a checkpoint. @@ -95,10 +113,11 @@ impl< ( Self { - context, + context: ContextCell::new(context), mailbox: rx, engine_client: cfg.engine_client, oracle: cfg.oracle, + orchestrator_mailbox: cfg.orchestrator_mailbox, pending_height_notifys: BTreeMap::new(), registry: cfg.registry, epoch_num_of_blocks: cfg.epoch_num_of_blocks, @@ -110,38 +129,35 @@ impl< validator_minimum_stake: cfg.validator_minimum_stake, validator_withdrawal_period: cfg.validator_withdrawal_period, validator_onboarding_limit_per_block: cfg.validator_onboarding_limit_per_block, - public_key: cfg.public_key, + node_public_key: cfg.node_public_key, validator_exit: false, cancellation_token: cfg.cancellation_token, + _signer_marker: PhantomData, + _variant_marker: PhantomData, }, FinalizerMailbox::new(tx), ) } - pub fn start( - mut self, - orchestrator: Orchestrator, - sync_height: u64, - finalization_notify: mpsc::Receiver<()>, - ) -> Handle<()> { - self.context.spawn_ref()(self.run(orchestrator, sync_height, finalization_notify)) + pub fn start(mut self, sync_height: u64) -> Handle<()> { + spawn_cell!(self.context, self.run(sync_height).await) } pub async fn run( mut self, - orchestrator: Orchestrator, + //orchestrator: Orchestrator, sync_height: u64, - finalization_notify: mpsc::Receiver<()>, + //finalization_notify: mpsc::Receiver<()>, ) { - let (block_fetcher, mut rx_finalize_blocks) = BlockFetcher::new( - orchestrator, - finalization_notify, - self.epoch_num_of_blocks, - sync_height, - ); - self.context - .with_label("block-fetcher") - .spawn(|_| block_fetcher.run()); + //let (block_fetcher, mut rx_finalize_blocks) = BlockFetcher::new( + // orchestrator, + // finalization_notify, + // self.epoch_num_of_blocks, + // sync_height, + //); + //self.context + // .with_label("block-fetcher") + // .spawn(|_| block_fetcher.run()); let mut last_committed_timestamp: Option = None; let mut signal = self.context.stopped().fuse(); @@ -155,17 +171,30 @@ impl< break; } select! { - msg = rx_finalize_blocks.next() => { - let Some((envelope, notifier)) = msg else { - warn!("All senders to finalizer dropped"); - break; - }; - self.handle_execution_block(notifier,envelope, &mut last_committed_timestamp).await; - - } + //msg = rx_finalize_blocks.next() => { + // let Some((envelope, notifier)) = msg else { + // warn!("All senders to finalizer dropped"); + // break; + // }; + // self.handle_execution_block(notifier,envelope, &mut last_committed_timestamp).await; + + //} mailbox_message = self.mailbox.next() => { let mail = mailbox_message.expect("Finalizer mailbox closed"); match mail { + FinalizerMessage::SyncerUpdate { update } => { + match update { + Update::Tip(height, digest) => { + + } + Update::Block(block, ack_tx) => { + self.handle_execution_block(ack_tx, block, None, &mut last_committed_timestamp).await; + } + Update::BlockWithFinalization(block, finalization, ack_tx) => { + + } + } + }, FinalizerMessage::NotifyAtHeight { height, response } => { let last_indexed = self.state.get_latest_height(); if last_indexed >= height { @@ -197,14 +226,14 @@ impl< async fn handle_execution_block( &mut self, - notifier: oneshot::Sender<()>, - envelope: BlockEnvelope, + ack_tx: oneshot::Sender<()>, + block: Block, + finalization: Option as Digestible>::Digest>>, #[allow(unused_variables)] last_committed_timestamp: &mut Option, ) { #[cfg(feature = "prom")] let block_processing_start = Instant::now(); - let BlockEnvelope { block, finalized } = envelope; // check the payload #[cfg(feature = "prom")] let payload_check_start = Instant::now(); @@ -316,22 +345,28 @@ impl< // Store finalizes checkpoint to database if is_last_block_of_epoch(new_height, self.epoch_num_of_blocks) { let view = block.view(); - if let Some(finalized) = finalized { + if let Some(finalization) = finalization { // The finalized signatures should always be included on the last block // of the epoch. However, there is an edge case, where the block after // last block of the epoch arrived out of order. // This is not critical and will likely never happen on all validators // at the same time. // TODO(matthias): figure out a good solution for making checkpoints available - debug_assert!(block.header.digest == finalized.proposal.payload); + debug_assert!(block.header.digest == finalization.proposal.payload); // Store the finalized block header in the database + // Convert to concrete BLS scheme type by encoding and decoding let finalized_header = FinalizedHeader { - header: block.header, - finalized, + header: block.header.clone(), + finalization, }; + use commonware_codec::{Read as CodecRead, Write as CodecWrite}; + let mut buf = Vec::new(); + finalized_header.write(&mut buf); + let concrete_header = > as CodecRead>::read_cfg(&mut buf.as_slice(), &()) + .expect("failed to convert finalized header to concrete type"); self.db - .store_finalized_header(new_height, &finalized_header) + .store_finalized_header(new_height, &concrete_header) .await; #[cfg(debug_assertions)] @@ -366,7 +401,7 @@ impl< .state .removed_validators .iter() - .any(|pk| pk == &self.public_key) + .any(|pk| pk == &self.node_public_key) { self.validator_exit = true; } @@ -381,10 +416,13 @@ impl< &self.state.added_validators, &self.state.removed_validators, ); - let participants = self.registry.peers().clone(); + // TODO(matthias): update peers properly + let participants = self.registry.peer_set(1).await.unwrap(); // TODO(matthias): should we wait until view `view + REGISTRY_CHANGE_VIEW_DELTA` // to update the oracle? - self.oracle.register(new_height, participants).await; + self.oracle + .register(new_height, participants.into_iter().collect()) + .await; } #[cfg(feature = "prom")] @@ -433,11 +471,11 @@ impl< } self.height_notify_up_to(new_height); - let _ = notifier.send(()); + let _ = ack_tx.send(()); info!(new_height, "finalized block"); } - async fn parse_execution_requests(&mut self, block: &Block, new_height: u64) { + async fn parse_execution_requests(&mut self, block: &Block, new_height: u64) { for request_bytes in &block.execution_requests { match ExecutionRequest::try_from_eth_bytes(request_bytes.as_ref()) { Ok(execution_request) => { @@ -531,7 +569,7 @@ impl< } } - async fn process_execution_requests(&mut self, block: &Block, new_height: u64) { + async fn process_execution_requests(&mut self, block: &Block, new_height: u64) { if is_penultimate_block_of_epoch(new_height, self.epoch_num_of_blocks) { for _ in 0..self.validator_onboarding_limit_per_block { if let Some(request) = self.state.pop_deposit() { @@ -586,7 +624,10 @@ impl< } // Create new ValidatorAccount from DepositRequest + // TODO(matthias): use the actual BLS key + let dummy_key = bls12381::PrivateKey::from_seed(0); let new_account = ValidatorAccount { + consensus_public_key: dummy_key.public_key(), withdrawal_credentials: Address::from_slice( &request.withdrawal_credentials[12..32], ), // Take last 20 bytes @@ -769,7 +810,10 @@ impl< R: Storage + Metrics + Clock + Spawner + governor::clock::Clock + Rng, C: EngineClient, O: NetworkOracle, -> Drop for Finalizer + S: Signer, + Z: Scheme, + V: Variant, +> Drop for Finalizer { fn drop(&mut self) { self.cancellation_token.cancel(); diff --git a/finalizer/src/config.rs b/finalizer/src/config.rs index d64718e6..16d6edfa 100644 --- a/finalizer/src/config.rs +++ b/finalizer/src/config.rs @@ -1,15 +1,19 @@ +use commonware_cryptography::Signer; +use commonware_cryptography::bls12381::primitives::variant::Variant; use commonware_runtime::buffer::PoolRef; +use summit_orchestrator::Mailbox as OrchestratorMailbox; use summit_types::network_oracle::NetworkOracle; use summit_types::registry::Registry; use summit_types::{EngineClient, PublicKey, consensus_state::ConsensusState}; use tokio_util::sync::CancellationToken; -pub struct FinalizerConfig> { +pub struct FinalizerConfig, S: Signer, V: Variant> { pub mailbox_size: usize, pub db_prefix: String, pub engine_client: C, pub registry: Registry, pub oracle: O, + pub orchestrator_mailbox: OrchestratorMailbox, pub epoch_num_of_blocks: u64, pub validator_max_withdrawals_per_block: usize, pub validator_minimum_stake: u64, // in gwei @@ -23,6 +27,6 @@ pub struct FinalizerConfig> { /// Protocol version for the consensus protocol pub protocol_version: u32, /// The node's own public key - pub public_key: PublicKey, + pub node_public_key: PublicKey, pub cancellation_token: CancellationToken, } diff --git a/finalizer/src/db.rs b/finalizer/src/db.rs index 8363e972..7f6bc18d 100644 --- a/finalizer/src/db.rs +++ b/finalizer/src/db.rs @@ -1,14 +1,19 @@ use bytes::{Buf, BufMut}; use commonware_codec::{EncodeSize, Error, Read, Write}; +use commonware_consensus::simplex::signing_scheme::bls12381_multisig; +use commonware_cryptography::bls12381::primitives::variant::{MinPk, Variant}; +use commonware_cryptography::ed25519::PublicKey; use commonware_runtime::{Clock, Metrics, Storage}; -use commonware_storage::store::{self, Store}; +use commonware_storage::adb::store::{self, Store}; use commonware_storage::translator::TwoCap; use commonware_utils::sequence::FixedBytes; -pub use store::Config; +use std::marker::PhantomData; use summit_types::FinalizedHeader; use summit_types::checkpoint::Checkpoint; use summit_types::consensus_state::ConsensusState; +pub use store::Config; + // Key prefixes for different data types const STATE_PREFIX: u8 = 0x01; const CONSENSUS_STATE_PREFIX: u8 = 0x05; @@ -20,13 +25,13 @@ const LATEST_CONSENSUS_STATE_HEIGHT_KEY: [u8; 2] = [STATE_PREFIX, 0]; const LATEST_FINALIZED_HEADER_HEIGHT_KEY: [u8; 2] = [STATE_PREFIX, 1]; const FINALIZED_CHECKPOINT_KEY: [u8; 2] = [CHECKPOINT_PREFIX, 1]; -pub struct FinalizerState { - store: Store, Value, TwoCap>, +pub struct FinalizerState { + store: Store, Value, TwoCap>, } -impl FinalizerState { +impl FinalizerState { pub async fn new(context: E, cfg: Config) -> Self { - let store = Store::<_, FixedBytes<64>, Value, TwoCap>::init(context, cfg) + let store = Store::<_, FixedBytes<64>, Value, TwoCap>::init(context, cfg) .await .expect("failed to initialize unified store"); @@ -170,7 +175,11 @@ impl FinalizerState { } // FinalizedHeader operations - pub async fn store_finalized_header(&mut self, height: u64, header: &FinalizedHeader) { + pub async fn store_finalized_header( + &mut self, + height: u64, + header: &FinalizedHeader>, + ) { let key = Self::make_finalized_header_key(height); self.store .update(key, Value::FinalizedHeader(Box::new(header.clone()))) @@ -185,7 +194,10 @@ impl FinalizerState { } #[allow(unused)] - pub async fn get_finalized_header(&self, height: u64) -> Option { + pub async fn get_finalized_header( + &self, + height: u64, + ) -> Option>> { let key = Self::make_finalized_header_key(height); if let Some(Value::FinalizedHeader(header)) = self .store @@ -199,7 +211,9 @@ impl FinalizerState { } } - pub async fn get_most_recent_finalized_header(&self) -> Option { + pub async fn get_most_recent_finalized_header( + &self, + ) -> Option>> { let latest_height = self.get_latest_finalized_header_height().await; if latest_height > 0 { self.get_finalized_header(latest_height).await @@ -218,14 +232,14 @@ impl FinalizerState { } #[derive(Clone)] -enum Value { +enum Value { U64(u64), ConsensusState(Box), Checkpoint(Checkpoint), - FinalizedHeader(Box), + FinalizedHeader(Box>>), } -impl EncodeSize for Value { +impl EncodeSize for Value { fn encode_size(&self) -> usize { 1 + match self { Self::U64(_) => 8, @@ -236,7 +250,7 @@ impl EncodeSize for Value { } } -impl Read for Value { +impl Read for Value { type Cfg = (); fn read_cfg(buf: &mut impl Buf, _cfg: &Self::Cfg) -> Result { @@ -248,16 +262,17 @@ impl Read for Value { &(), )?))), 0x06 => Ok(Self::Checkpoint(Checkpoint::read_cfg(buf, &())?)), - 0x07 => Ok(Self::FinalizedHeader(Box::new(FinalizedHeader::read_cfg( - buf, - &(), + 0x07 => Ok(Self::FinalizedHeader(Box::new(FinalizedHeader::< + bls12381_multisig::Scheme, + >::read_cfg( + buf, &() )?))), byte => Err(Error::InvalidVarint(byte as usize)), } } } -impl Write for Value { +impl Write for Value { fn write(&self, buf: &mut impl BufMut) { match self { Self::U64(val) => { @@ -283,14 +298,25 @@ impl Write for Value { #[cfg(test)] mod tests { use super::*; + use commonware_consensus::simplex::signing_scheme::bls12381_multisig::Certificate as BlsCertificate; + use commonware_consensus::simplex::signing_scheme::utils::Signers; + use commonware_consensus::simplex::types::{Finalization, Proposal}; + use commonware_consensus::types::Round; + use commonware_cryptography::bls12381::{ + self, + primitives::{ + group::{Element, G2}, + variant::MinPk, + }, + }; use commonware_runtime::buffer::PoolRef; use commonware_runtime::{Runner as _, deterministic::Runner}; use commonware_utils::{NZU64, NZUsize}; - async fn create_test_db_with_context( + async fn create_test_db_with_context( partition: &str, context: E, - ) -> FinalizerState { + ) -> FinalizerState { let config = Config { log_journal_partition: format!("{}-log", partition), log_write_buffer: NZUsize!(64 * 1024), @@ -302,7 +328,7 @@ mod tests { translator: TwoCap, buffer_pool: PoolRef::new(NZUsize!(77), NZUsize!(9)), }; - FinalizerState::new(context, config).await + FinalizerState::::new(context, config).await } #[test] @@ -310,7 +336,8 @@ mod tests { let cfg = commonware_runtime::deterministic::Config::default().with_seed(1); let executor = Runner::from(cfg); executor.start(|context| async move { - let mut db = create_test_db_with_context("test_consensus_state", context).await; + let mut db = + create_test_db_with_context::<_, MinPk>("test_consensus_state", context).await; // Create a test consensus state let mut consensus_state = ConsensusState::default(); @@ -360,13 +387,15 @@ mod tests { let cfg = commonware_runtime::deterministic::Config::default().with_seed(3); let executor = Runner::from(cfg); executor.start(|context| async move { - let mut db = create_test_db_with_context("test_finalized_header", context).await; + let mut db = + create_test_db_with_context::<_, MinPk>("test_finalized_header", context).await; // Create a test header let header = summit_types::Header::compute_digest( [1u8; 32].into(), // parent 100, // height 1234567890, // timestamp + 0, // epoch 1, // view [2u8; 32].into(), // payload_hash [3u8; 32].into(), // execution_request_hash @@ -378,15 +407,17 @@ mod tests { ); // Create finalization proof - use commonware_consensus::simplex::types::{Finalization, Proposal}; let proposal = Proposal { - view: header.view, + round: Round::new(header.epoch, header.view), parent: header.height, payload: header.digest, }; let finalized = Finalization { proposal, - signatures: Vec::new(), + certificate: BlsCertificate { + signers: Signers::from(3, [0, 1, 2]), + signature: G2::zero(), + }, }; let finalized_header = summit_types::FinalizedHeader::new(header.clone(), finalized); @@ -413,6 +444,7 @@ mod tests { [5u8; 32].into(), // parent 200, // height 1234567900, // timestamp + 0, // epoch 2, // view [6u8; 32].into(), // payload_hash [7u8; 32].into(), // execution_request_hash @@ -423,13 +455,16 @@ mod tests { Vec::new(), // removed_validators ); let proposal2 = Proposal { - view: header2.view, + round: Round::new(header2.epoch, header2.view), parent: header2.height, payload: header2.digest, }; let finalized2 = Finalization { proposal: proposal2, - signatures: Vec::new(), + certificate: BlsCertificate { + signers: Signers::from(3, [0, 1, 2]), + signature: G2::zero(), + }, }; let finalized_header2 = summit_types::FinalizedHeader::new(header2.clone(), finalized2); db.store_finalized_header(200, &finalized_header2).await; @@ -456,19 +491,21 @@ mod tests { let cfg = commonware_runtime::deterministic::Config::default().with_seed(5); let executor = Runner::from(cfg); executor.start(|context| async move { - let mut db = - create_test_db_with_context("test_most_recent_finalized_header", context).await; + let mut db = create_test_db_with_context::<_, MinPk>( + "test_most_recent_finalized_header", + context, + ) + .await; // Test that no most recent header exists initially assert!(db.get_most_recent_finalized_header().await.is_none()); - use commonware_consensus::simplex::types::{Finalization, Proposal}; - // Store headers out of order let header1 = summit_types::Header::compute_digest( [1u8; 32].into(), // parent 100, // height 1234567890, // timestamp + 0, // epoch 1, // view [2u8; 32].into(), // payload_hash [3u8; 32].into(), // execution_request_hash @@ -479,13 +516,17 @@ mod tests { Vec::new(), // removed_validators ); let proposal1 = Proposal { - view: header1.view, + round: Round::new(header1.epoch, header1.view), parent: header1.height, payload: header1.digest, }; + let finalized1 = Finalization { proposal: proposal1, - signatures: Vec::new(), + certificate: BlsCertificate { + signers: Signers::from(3, [0, 1, 2]), + signature: G2::zero(), + }, }; let finalized_header1 = summit_types::FinalizedHeader::new(header1.clone(), finalized1); @@ -493,6 +534,7 @@ mod tests { [7u8; 32].into(), // parent 300, // height 1234567920, // timestamp + 0, // epoch 3, // view [8u8; 32].into(), // payload_hash [9u8; 32].into(), // execution_request_hash @@ -503,13 +545,17 @@ mod tests { Vec::new(), // removed_validators ); let proposal3 = Proposal { - view: header3.view, + round: Round::new(header3.epoch, header3.view), parent: header3.height, payload: header3.digest, }; + let finalized3 = Finalization { proposal: proposal3, - signatures: Vec::new(), + certificate: BlsCertificate { + signers: Signers::from(3, [0, 1, 2]), + signature: G2::zero(), + }, }; let finalized_header3 = summit_types::FinalizedHeader::new(header3.clone(), finalized3); @@ -517,6 +563,7 @@ mod tests { [5u8; 32].into(), // parent 200, // height 1234567900, // timestamp + 0, // epoch 2, // view [6u8; 32].into(), // payload_hash [7u8; 32].into(), // execution_request_hash @@ -527,13 +574,17 @@ mod tests { Vec::new(), // removed_validators ); let proposal2 = Proposal { - view: header2.view, + round: Round::new(header2.epoch, header2.view), parent: header2.height, payload: header2.digest, }; + let finalized2 = Finalization { proposal: proposal2, - signatures: Vec::new(), + certificate: BlsCertificate { + signers: Signers::from(3, [0, 1, 2]), + signature: G2::zero(), + }, }; let finalized_header2 = summit_types::FinalizedHeader::new(header2.clone(), finalized2); @@ -579,7 +630,7 @@ mod tests { let cfg = commonware_runtime::deterministic::Config::default().with_seed(4); let executor = Runner::from(cfg); executor.start(|context| async move { - let mut db = create_test_db_with_context("test_checkpoint", context).await; + let mut db = create_test_db_with_context::<_, MinPk>("test_checkpoint", context).await; // Create test consensus states with different heights to ensure different digests let mut finalized_state1 = ConsensusState::default(); diff --git a/finalizer/src/ingress.rs b/finalizer/src/ingress.rs index 7cd7bc69..c4bd7358 100644 --- a/finalizer/src/ingress.rs +++ b/finalizer/src/ingress.rs @@ -1,15 +1,19 @@ +use commonware_consensus::simplex::signing_scheme::Scheme; +use commonware_consensus::{Block as ConsensusBlock, Reporter}; +use commonware_cryptography::Committable; use futures::{ SinkExt as _, channel::{mpsc, oneshot}, }; +use summit_syncer::Update; use summit_types::{ - BlockAuxData, PublicKey, + Block, BlockAuxData, PublicKey, checkpoint::Checkpoint, consensus_state_query::{ConsensusStateRequest, ConsensusStateResponse}, }; #[allow(clippy::large_enum_variant)] -pub enum FinalizerMessage { +pub enum FinalizerMessage { NotifyAtHeight { height: u64, response: oneshot::Sender<()>, @@ -22,15 +26,18 @@ pub enum FinalizerMessage { request: ConsensusStateRequest, response: oneshot::Sender, }, + SyncerUpdate { + update: Update, + }, } #[derive(Clone)] -pub struct FinalizerMailbox { - sender: mpsc::Sender, +pub struct FinalizerMailbox { + sender: mpsc::Sender>, } -impl FinalizerMailbox { - pub fn new(sender: mpsc::Sender) -> Self { +impl FinalizerMailbox { + pub fn new(sender: mpsc::Sender>) -> Self { Self { sender } } @@ -109,3 +116,14 @@ impl FinalizerMailbox { balance } } + +impl Reporter for FinalizerMailbox { + type Activity = Update; + + async fn report(&mut self, activity: Self::Activity) { + self.sender + .send(FinalizerMessage::SyncerUpdate { update: activity }) + .await + .expect("Unable to send syncer update to Finalizer"); + } +} diff --git a/finalizer/src/lib.rs b/finalizer/src/lib.rs index 1c28c52f..3fed91d7 100644 --- a/finalizer/src/lib.rs +++ b/finalizer/src/lib.rs @@ -3,5 +3,5 @@ pub use ingress::*; pub mod config; pub use config::*; pub mod actor; -pub mod block_fetcher; +//pub mod block_fetcher; pub mod db; From d40c3619352eed5c3b1d8e112c6426061dfcb8ea Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Fri, 7 Nov 2025 17:08:46 -0500 Subject: [PATCH 33/81] feat: add sync_height and response channel for finalized blocks --- syncer/Cargo.toml | 1 + syncer/src/actor.rs | 46 +++++++++++++----------- syncer/src/cache.rs | 18 +++++----- syncer/src/config.rs | 2 +- syncer/src/finalizer.rs | 57 ++++++++++++++---------------- syncer/src/ingress/handler.rs | 8 ++--- syncer/src/ingress/mailbox.rs | 4 +-- syncer/src/ingress/orchestrator.rs | 2 +- syncer/src/lib.rs | 55 ++++++++++++++++------------ syncer/src/mocks/application.rs | 27 +++++++++----- syncer/src/mocks/block.rs | 2 +- syncer/src/resolver/p2p.rs | 2 +- 12 files changed, 122 insertions(+), 102 deletions(-) diff --git a/syncer/Cargo.toml b/syncer/Cargo.toml index 634f0f98..a2c6a855 100644 --- a/syncer/Cargo.toml +++ b/syncer/Cargo.toml @@ -32,3 +32,4 @@ tracing-subscriber = "0.3.19" [features] prom = ["metrics"] +test-mocks = [] diff --git a/syncer/src/actor.rs b/syncer/src/actor.rs index ee5495eb..386c12d2 100644 --- a/syncer/src/actor.rs +++ b/syncer/src/actor.rs @@ -8,32 +8,33 @@ use super::{ orchestrator::{Orchestration, Orchestrator}, }, }; -use crate::{ingress::mailbox::Identifier as BlockID, Update}; -use commonware_broadcast::{buffered, Broadcaster}; +use crate::{Update, ingress::mailbox::Identifier as BlockID}; +use commonware_broadcast::{Broadcaster, buffered}; use commonware_codec::{Decode, Encode}; +use commonware_consensus::simplex::signing_scheme::Scheme; +use commonware_consensus::simplex::types::{Finalization, Notarization}; +use commonware_consensus::types::Round; +use commonware_consensus::{Block, Reporter, utils}; use commonware_cryptography::PublicKey; use commonware_macros::select; use commonware_p2p::Recipients; use commonware_resolver::Resolver; -use commonware_runtime::{spawn_cell, Clock, ContextCell, Handle, Metrics, Spawner, Storage}; -use commonware_storage::archive::{immutable, Archive as _, Identifier as ArchiveID}; +use commonware_runtime::{Clock, ContextCell, Handle, Metrics, Spawner, Storage, spawn_cell}; +use commonware_storage::archive::{Archive as _, Identifier as ArchiveID, immutable}; use commonware_utils::futures::{AbortablePool, Aborter}; use futures::{ + StreamExt, channel::{mpsc, oneshot}, - try_join, StreamExt, + try_join, }; use governor::clock::Clock as GClock; #[cfg(feature = "prom")] use metrics::gauge::Gauge; use rand::{CryptoRng, Rng}; use std::{ - collections::{btree_map::Entry, BTreeMap}, + collections::{BTreeMap, btree_map::Entry}, time::Instant, }; -use commonware_consensus::{utils, Block, Reporter}; -use commonware_consensus::simplex::signing_scheme::Scheme; -use commonware_consensus::simplex::types::{Finalization, Notarization}; -use commonware_consensus::types::Round; use tracing::{debug, info, warn}; use summit_types::scheme::SchemeProvider; @@ -115,11 +116,11 @@ pub struct Actor< } impl< - E: Rng + CryptoRng + Spawner + Metrics + Clock + GClock + Storage, - B: Block, - P: SchemeProvider, - S: Scheme, - > Actor + E: Rng + CryptoRng + Spawner + Metrics + Clock + GClock + Storage, + B: Block, + P: SchemeProvider, + S: Scheme, +> Actor { /// Create a new application actor. pub async fn init(context: E, config: Config) -> (Self, Mailbox) { @@ -283,23 +284,28 @@ impl< /// Start the actor. pub fn start( mut self, - application: impl Reporter>, + application: impl Reporter>, buffer: buffered::Mailbox, resolver: (mpsc::Receiver>, R), + sync_height: u64, ) -> Handle<()> where R: Resolver>, K: PublicKey, { - spawn_cell!(self.context, self.run(application, buffer, resolver).await) + spawn_cell!( + self.context, + self.run(application, buffer, resolver, sync_height).await + ) } /// Run the application actor. async fn run( mut self, - mut application: impl Reporter>, + mut application: impl Reporter>, mut buffer: buffered::Mailbox, (mut resolver_rx, mut resolver): (mpsc::Receiver>, R), + sync_height: u64, ) where R: Resolver>, K: PublicKey, @@ -310,10 +316,10 @@ impl< let orchestrator = Orchestrator::new(orchestrator_sender); let finalizer = Finalizer::new( self.context.with_label("finalizer"), - format!("{}-finalizer", self.partition_prefix.clone()), application.clone(), orchestrator, notifier_rx, + sync_height, ) .await; finalizer.start(); @@ -787,7 +793,7 @@ impl< block: B, finalization: Option>, notifier: &mut mpsc::Sender<()>, - application: &mut impl Reporter>, + application: &mut impl Reporter>, ) { self.notify_subscribers(commitment, &block).await; diff --git a/syncer/src/cache.rs b/syncer/src/cache.rs index 83022bb6..27e6cc5d 100644 --- a/syncer/src/cache.rs +++ b/syncer/src/cache.rs @@ -1,15 +1,15 @@ +use commonware_codec::Codec; use commonware_consensus::{ + Block, simplex::{ signing_scheme::Scheme, types::{Finalization, Notarization}, }, types::{Epoch, Round, View}, - Block, }; -use commonware_codec::Codec; -use commonware_runtime::{buffer::PoolRef, Clock, Metrics, Spawner, Storage}; +use commonware_runtime::{Clock, Metrics, Spawner, Storage, buffer::PoolRef}; use commonware_storage::{ - archive::{self, prunable, Archive as _, Identifier}, + archive::{self, Archive as _, Identifier, prunable}, metadata::{self, Metadata}, translator::TwoCap, }; @@ -93,11 +93,11 @@ pub(crate) struct Manager< } impl< - R: Rng + Spawner + Metrics + Clock + GClock + Storage, - B: Block, - P: SchemeProvider, - S: Scheme, - > Manager + R: Rng + Spawner + Metrics + Clock + GClock + Storage, + B: Block, + P: SchemeProvider, + S: Scheme, +> Manager { /// Initialize the cache manager and its metadata store. pub(crate) async fn init( diff --git a/syncer/src/config.rs b/syncer/src/config.rs index 66f022a8..e67a6cbd 100644 --- a/syncer/src/config.rs +++ b/syncer/src/config.rs @@ -1,4 +1,4 @@ -use commonware_consensus::{simplex::signing_scheme::Scheme, Block}; +use commonware_consensus::{Block, simplex::signing_scheme::Scheme}; use commonware_runtime::buffer::PoolRef; use std::{ marker::PhantomData, diff --git a/syncer/src/finalizer.rs b/syncer/src/finalizer.rs index 7ca2caec..bea1cb98 100644 --- a/syncer/src/finalizer.rs +++ b/syncer/src/finalizer.rs @@ -1,15 +1,14 @@ -use commonware_consensus::{ - Block, Reporter, -}; -use crate::{ingress::orchestrator::Orchestrator, Update}; -use commonware_runtime::{spawn_cell, Clock, ContextCell, Handle, Metrics, Spawner, Storage}; +use crate::{Update, ingress::orchestrator::Orchestrator}; +use commonware_consensus::simplex::signing_scheme::Scheme; +use commonware_consensus::{Block, Reporter}; +use commonware_runtime::{Clock, ContextCell, Handle, Metrics, Spawner, Storage, spawn_cell}; use commonware_storage::metadata::{self, Metadata}; use commonware_utils::{fixed_bytes, sequence::FixedBytes}; -use futures::{channel::mpsc, StreamExt}; +use futures::channel::oneshot; +use futures::{StreamExt, channel::mpsc}; use tracing::{debug, error}; // The key used to store the last indexed height in the metadata store. -const LATEST_KEY: FixedBytes<1> = fixed_bytes!("00"); /// Requests the finalized blocks (in order) from the orchestrator, sends them to the application, /// waits for confirmation that the application has processed the block. @@ -18,8 +17,9 @@ const LATEST_KEY: FixedBytes<1> = fixed_bytes!("00"); /// processing from the last processed height after a restart. pub struct Finalizer< B: Block, + S: Scheme, R: Spawner + Clock + Metrics + Storage, - Z: Reporter>, + Z: Reporter>, > { context: ContextCell, @@ -32,38 +32,31 @@ pub struct Finalizer< // Notifier to indicate that the finalized blocks have been updated and should be re-queried. notifier_rx: mpsc::Receiver<()>, - // Metadata store that stores the last indexed height. - metadata: Metadata, u64>, + // The lowest height from which to begin syncing + sync_height: u64, } -impl>> - Finalizer +impl< + B: Block, + S: Scheme, + R: Spawner + Clock + Metrics + Storage, + Z: Reporter>, +> Finalizer { /// Initialize the finalizer. pub async fn new( context: R, - partition_prefix: String, application: Z, orchestrator: Orchestrator, notifier_rx: mpsc::Receiver<()>, + sync_height: u64, ) -> Self { - // Initialize metadata - let metadata = Metadata::init( - context.with_label("metadata"), - metadata::Config { - partition: format!("{partition_prefix}-metadata"), - codec_config: (), - }, - ) - .await - .expect("failed to initialize metadata"); - Self { context: ContextCell::new(context), application, orchestrator, notifier_rx, - metadata, + sync_height, } } @@ -76,7 +69,7 @@ impl { +#[derive(Debug)] +pub enum Update { /// A new finalized tip. Tip(u64, B::Commitment), - /// A new finalized block. - Block(B), + /// A new finalized block and a channel to acknowledge the update. + /// + /// To ensure all blocks are delivered at least once, marshal waits to mark + /// a block as delivered until the application explicitly acknowledges the update. + /// If the sender is dropped before acknowledgement, marshal will exit (assuming + /// the application is shutting down). + Block(B, oneshot::Sender<()>), + /// A new finalized block with finalization + BlockWithFinalization(B, Finalization, oneshot::Sender<()>), } #[cfg(test)] pub mod mocks; -#[cfg(test)] +#[cfg(all(test, feature = "test-mocks"))] mod tests { use super::{ actor, @@ -89,24 +99,31 @@ mod tests { mocks::{application::Application, block::Block}, resolver::p2p as resolver, }; - use summit_types::scheme::SchemeProvider; + use crate::ingress::mailbox::Identifier; use commonware_broadcast::buffered; + use commonware_consensus::simplex::mocks::fixtures::{Fixture, bls12381_threshold}; + use commonware_consensus::simplex::signing_scheme::bls12381_threshold; + use commonware_consensus::simplex::types::{ + Activity, Finalization, Finalize, Notarization, Notarize, Proposal, + }; + use commonware_consensus::types::{Epoch, Round}; + use commonware_consensus::{Block as _, Reporter, utils}; use commonware_cryptography::{ + Digestible, Hasher as _, bls12381::primitives::variant::MinPk, ed25519::PublicKey, sha256::{Digest as Sha256Digest, Sha256}, - Digestible, Hasher as _, }; use commonware_macros::test_traced; use commonware_p2p::{ + Manager, simulated::{self, Link, Network, Oracle}, utils::requester, - Manager, }; - use commonware_runtime::{buffer::PoolRef, deterministic, Clock, Metrics, Runner}; - use commonware_utils::{NZUsize, NZU64}; + use commonware_runtime::{Clock, Metrics, Runner, buffer::PoolRef, deterministic}; + use commonware_utils::{NZU64, NZUsize}; use governor::Quota; - use rand::{seq::SliceRandom, Rng}; + use rand::{Rng, seq::SliceRandom}; use std::{ collections::BTreeMap, marker::PhantomData, @@ -114,12 +131,7 @@ mod tests { sync::Arc, time::Duration, }; - use commonware_consensus::simplex::mocks::fixtures::{bls12381_threshold, Fixture}; - use commonware_consensus::simplex::signing_scheme::bls12381_threshold; - use commonware_consensus::simplex::types::{Activity, Finalization, Finalize, Notarization, Notarize, Proposal}; - use commonware_consensus::types::{Epoch, Round}; - use commonware_consensus::{utils, Block as _, Reporter}; - use crate::ingress::mailbox::Identifier; + use summit_types::scheme::SchemeProvider; type D = Sha256Digest; type B = Block; @@ -166,10 +178,7 @@ mod tests { oracle: &mut Oracle, validator: K, scheme_provider: P, - ) -> ( - Application, - crate::ingress::mailbox::Mailbox, - ) { + ) -> (Application, crate::ingress::mailbox::Mailbox) { let config = Config { scheme_provider, epoch_length: BLOCKS_PER_EPOCH, @@ -224,10 +233,10 @@ mod tests { broadcast_engine.start(network); let (actor, mailbox) = actor::Actor::init(context.clone(), config).await; - let application = Application::::default(); + let application = Application::::default(); // Start the application - actor.start(application.clone(), buffer, resolver); + actor.start(application.clone(), buffer, resolver, 0); (application, mailbox) } diff --git a/syncer/src/mocks/application.rs b/syncer/src/mocks/application.rs index 9ca80a0c..e87ece2a 100644 --- a/syncer/src/mocks/application.rs +++ b/syncer/src/mocks/application.rs @@ -1,4 +1,6 @@ -use commonware_consensus::{marshal::Update, Block, Reporter}; +use crate::Update; +use commonware_consensus::simplex::signing_scheme::Scheme; +use commonware_consensus::{Block, Reporter}; use std::{ collections::BTreeMap, sync::{Arc, Mutex}, @@ -6,22 +8,24 @@ use std::{ /// A mock application that stores finalized blocks. #[derive(Clone)] -pub struct Application { +pub struct Application { blocks: Arc>>, #[allow(clippy::type_complexity)] tip: Arc>>, + _phantom: std::marker::PhantomData, } -impl Default for Application { +impl Default for Application { fn default() -> Self { Self { blocks: Default::default(), tip: Default::default(), + _phantom: std::marker::PhantomData, } } } -impl Application { +impl Application { /// Returns the finalized blocks. pub fn blocks(&self) -> BTreeMap { self.blocks.lock().unwrap().clone() @@ -33,17 +37,22 @@ impl Application { } } -impl Reporter for Application { - type Activity = Update; +impl Reporter for Application { + type Activity = Update; async fn report(&mut self, activity: Self::Activity) { match activity { - Update::Block(block) => { - self.blocks.lock().unwrap().insert(block.height(), block); - } Update::Tip(height, commitment) => { *self.tip.lock().unwrap() = Some((height, commitment)); } + Update::Block(block, ack_tx) => { + self.blocks.lock().unwrap().insert(block.height(), block); + let _ = ack_tx.send(()); + } + Update::BlockWithFinalization(block, _finalization, ack_tx) => { + self.blocks.lock().unwrap().insert(block.height(), block); + let _ = ack_tx.send(()); + } } } } diff --git a/syncer/src/mocks/block.rs b/syncer/src/mocks/block.rs index 7c43d8cd..d55a7820 100644 --- a/syncer/src/mocks/block.rs +++ b/syncer/src/mocks/block.rs @@ -1,5 +1,5 @@ use bytes::{Buf, BufMut}; -use commonware_codec::{varint::UInt, EncodeSize, Error, Read, ReadExt, Write}; +use commonware_codec::{EncodeSize, Error, Read, ReadExt, Write, varint::UInt}; use commonware_cryptography::{Committable, Digest, Digestible, Hasher}; #[derive(Clone, Debug, PartialEq, Eq)] diff --git a/syncer/src/resolver/p2p.rs b/syncer/src/resolver/p2p.rs index 5a2c1091..4a8ae930 100644 --- a/syncer/src/resolver/p2p.rs +++ b/syncer/src/resolver/p2p.rs @@ -3,7 +3,7 @@ use crate::Block; use crate::ingress::handler::{self, Handler}; use commonware_cryptography::PublicKey; -use commonware_p2p::{utils::requester, Manager, Receiver, Sender}; +use commonware_p2p::{Manager, Receiver, Sender, utils::requester}; use commonware_resolver::p2p; use commonware_runtime::{Clock, Metrics, Spawner}; use futures::channel::mpsc; From a7ee55ff7a1110df24bcee92c6b4400484d8ffdc Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Fri, 7 Nov 2025 17:09:13 -0500 Subject: [PATCH 34/81] chore: update finalizer mailbox signature --- rpc/Cargo.toml | 1 + rpc/src/lib.rs | 15 +++++++++------ rpc/src/routes.rs | 35 ++++++++++++++++++++++++----------- 3 files changed, 34 insertions(+), 17 deletions(-) diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index de5c57f1..aa85758b 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -15,6 +15,7 @@ tokio-util.workspace = true futures.workspace = true axum = { version = "0.8.4"} summit-types = { workspace = true } +commonware-consensus = { workspace = true } commonware-cryptography = { workspace = true } commonware-utils = { workspace = true } commonware-codec = { workspace = true } diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 79a73937..5f7309b5 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -1,5 +1,8 @@ pub mod routes; use crate::routes::RpcRoutes; +use commonware_consensus::Block as ConsensusBlock; +use commonware_consensus::simplex::signing_scheme::Scheme; +use commonware_cryptography::Committable; use commonware_runtime::signal::Signal; use futures::channel::oneshot; use std::sync::Mutex; @@ -7,13 +10,13 @@ use summit_finalizer::FinalizerMailbox; use tokio::net::TcpListener; use tokio_util::sync::CancellationToken; -pub struct RpcState { +pub struct RpcState { key_path: String, - finalizer_mailbox: FinalizerMailbox, + finalizer_mailbox: FinalizerMailbox, } -impl RpcState { - pub fn new(key_path: String, finalizer_mailbox: FinalizerMailbox) -> Self { +impl RpcState { + pub fn new(key_path: String, finalizer_mailbox: FinalizerMailbox) -> Self { Self { key_path, finalizer_mailbox, @@ -21,8 +24,8 @@ impl RpcState { } } -pub async fn start_rpc_server( - finalizer_mailbox: FinalizerMailbox, +pub async fn start_rpc_server( + finalizer_mailbox: FinalizerMailbox, key_path: String, port: u16, stop_signal: Signal, diff --git a/rpc/src/routes.rs b/rpc/src/routes.rs index 25d607f5..4b628632 100644 --- a/rpc/src/routes.rs +++ b/rpc/src/routes.rs @@ -6,7 +6,9 @@ use axum::{ routing::{get, post}, }; use commonware_codec::DecodeExt as _; -use commonware_cryptography::Signer; +use commonware_consensus::Block as ConsensusBlock; +use commonware_consensus::simplex::signing_scheme::Scheme; +use commonware_cryptography::{Committable, Signer}; use commonware_utils::{from_hex_formatted, hex}; use serde::Deserialize; use ssz::Encode; @@ -22,18 +24,23 @@ struct ValidatorBalanceQuery { pub(crate) struct RpcRoutes; impl RpcRoutes { - pub fn mount(state: RpcState) -> Router { + pub fn mount( + state: RpcState, + ) -> Router { // todo(dalton): Add cors let state = Arc::new(state); Router::new() .route("/health", get(Self::handle_health_check)) - .route("/get_public_key", get(Self::handle_get_pub_key)) - .route("/get_checkpoint", get(Self::handle_get_checkpoint)) - .route("/get_latest_height", get(Self::handle_latest_height)) + .route("/get_public_key", get(Self::handle_get_pub_key::)) + .route("/get_checkpoint", get(Self::handle_get_checkpoint::)) + .route( + "/get_latest_height", + get(Self::handle_latest_height::), + ) .route( "/get_validator_balance", - get(Self::handle_get_validator_balance), + get(Self::handle_get_validator_balance::), ) .with_state(state) } @@ -51,7 +58,9 @@ impl RpcRoutes { "Ok" } - async fn handle_get_pub_key(State(state): State>) -> Result { + async fn handle_get_pub_key( + State(state): State>>, + ) -> Result { let private_key = Self::read_ed_key_from_path(&state.key_path)?; Ok(private_key.public_key().to_string()) @@ -68,7 +77,9 @@ impl RpcRoutes { Ok(pk) } - async fn handle_get_checkpoint(State(state): State>) -> Result { + async fn handle_get_checkpoint( + State(state): State>>, + ) -> Result { let maybe_checkpoint = state .finalizer_mailbox .clone() @@ -82,7 +93,9 @@ impl RpcRoutes { Ok(hex(&encoded)) } - async fn handle_latest_height(State(state): State>) -> Result { + async fn handle_latest_height( + State(state): State>>, + ) -> Result { Ok(state .finalizer_mailbox .get_latest_height() @@ -90,8 +103,8 @@ impl RpcRoutes { .to_string()) } - async fn handle_get_validator_balance( - State(state): State>, + async fn handle_get_validator_balance( + State(state): State>>, Query(params): Query, ) -> Result { // Parse the public key from hex string From 44ac39f773c7c05e8584678c3fda0f88198f020c Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Fri, 7 Nov 2025 17:09:50 -0500 Subject: [PATCH 35/81] chore: update trait bounds --- orchestrator/src/actor.rs | 31 ++++++++++++++----------------- orchestrator/src/ingress.rs | 9 +++------ 2 files changed, 17 insertions(+), 23 deletions(-) diff --git a/orchestrator/src/actor.rs b/orchestrator/src/actor.rs index 560cb10f..63d04ba7 100644 --- a/orchestrator/src/actor.rs +++ b/orchestrator/src/actor.rs @@ -1,33 +1,33 @@ //! Consensus engine orchestrator for epoch transitions. -use summit_types::{Block, scheme::SummitSchemeProvider, Digest}; use crate::{Mailbox, Message}; +use summit_types::{Block, Digest, scheme::SummitSchemeProvider}; -use commonware_codec::{varint::UInt, DecodeExt, Encode}; +use commonware_codec::{DecodeExt, Encode, varint::UInt}; use commonware_consensus::{ + Automaton, Relay, simplex::{ self, types::{Context, Voter}, }, types::Epoch, utils::last_block_in_epoch, - Automaton, Relay, }; -use commonware_cryptography::{bls12381::primitives::variant::Variant, Signer}; +use commonware_cryptography::{Signer, bls12381::primitives::variant::Variant}; use commonware_macros::select; use commonware_p2p::{ - utils::mux::{Builder, MuxHandle, Muxer}, Blocker, Receiver, Recipients, Sender, + utils::mux::{Builder, MuxHandle, Muxer}, }; use commonware_runtime::{ - buffer::PoolRef, spawn_cell, Clock, ContextCell, Handle, Metrics, Network, Spawner, Storage, + Clock, ContextCell, Handle, Metrics, Network, Spawner, Storage, buffer::PoolRef, spawn_cell, }; -use commonware_utils::{NZUsize, NZU32}; -use futures::{channel::mpsc, StreamExt}; -use governor::{clock::Clock as GClock, Quota, RateLimiter}; +use commonware_utils::{NZU32, NZUsize}; +use futures::{StreamExt, channel::mpsc}; +use governor::{Quota, RateLimiter, clock::Clock as GClock}; use rand::{CryptoRng, Rng}; use std::{collections::BTreeMap, time::Duration}; -use tracing::{debug, info, warn}; use summit_types::scheme::{EpochSchemeProvider, MultisigScheme}; +use tracing::{debug, info, warn}; /// Configuration for the orchestrator. pub struct Config @@ -35,8 +35,7 @@ where B: Blocker, V: Variant, C: Signer, - A: Automaton, Digest = Digest> - + Relay, + A: Automaton, Digest = Digest> + Relay, { pub oracle: B, pub application: A, @@ -46,7 +45,7 @@ where pub namespace: Vec, pub muxer_size: usize, pub mailbox_size: usize, - pub rate_limit: governor::Quota, + pub rate_limit: Quota, pub blocks_per_epoch: u64, @@ -60,8 +59,7 @@ where B: Blocker, V: Variant, C: Signer, - A: Automaton, Digest = Digest> - + Relay, + A: Automaton, Digest = Digest> + Relay, { context: ContextCell, mailbox: mpsc::Receiver>, @@ -85,8 +83,7 @@ where B: Blocker, V: Variant, C: Signer, - A: Automaton, Digest = Digest> - + Relay, + A: Automaton, Digest = Digest> + Relay, { pub fn new(context: E, config: Config) -> (Self, Mailbox) { let (sender, mailbox) = mpsc::channel(config.mailbox_size); diff --git a/orchestrator/src/ingress.rs b/orchestrator/src/ingress.rs index 127c96c1..6d9cade8 100644 --- a/orchestrator/src/ingress.rs +++ b/orchestrator/src/ingress.rs @@ -1,11 +1,8 @@ //! Inbound communication channel for epoch transitions. -use commonware_consensus::{types::Epoch, Reporter}; -use commonware_cryptography::{ - bls12381::primitives::variant::Variant, - PublicKey, -}; -use futures::{channel::mpsc, SinkExt}; +use commonware_consensus::{Reporter, types::Epoch}; +use commonware_cryptography::{PublicKey, bls12381::primitives::variant::Variant}; +use futures::{SinkExt, channel::mpsc}; use summit_types::scheme::EpochTransition; /// Messages that can be sent to the orchestrator. From 0ca165804215b84f79a2a7f7a3d4a854afb2b0ef Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Fri, 7 Nov 2025 17:19:50 -0500 Subject: [PATCH 36/81] chore: update network oracle --- types/src/network_oracle.rs | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/types/src/network_oracle.rs b/types/src/network_oracle.rs index f7d58151..d1e6c8a6 100644 --- a/types/src/network_oracle.rs +++ b/types/src/network_oracle.rs @@ -1,11 +1,13 @@ use commonware_cryptography::PublicKey; -use commonware_p2p::{Manager, authenticated::discovery::Oracle}; +use commonware_p2p::{Blocker, Manager, authenticated::discovery::Oracle}; use commonware_utils::set::Ordered; +use std::future::Future; pub trait NetworkOracle: Send + Sync + 'static { fn register(&mut self, index: u64, peers: Vec) -> impl Future + Send; } +#[derive(Clone, Debug)] pub struct DiscoveryOracle { oracle: Oracle, } @@ -21,3 +23,34 @@ impl NetworkOracle for DiscoveryOracle { self.oracle.update(index, Ordered::from(peers)).await; } } + +impl Blocker for DiscoveryOracle { + type PublicKey = C; + + async fn block(&mut self, public_key: Self::PublicKey) { + self.oracle.block(public_key).await + } +} + +impl Manager for DiscoveryOracle { + type PublicKey = C; + type Peers = Ordered; + + fn update(&mut self, id: u64, peers: Self::Peers) -> impl Future + Send { + self.oracle.update(id, peers) + } + + async fn peer_set(&mut self, id: u64) -> Option> { + self.oracle.peer_set(id).await + } + + async fn subscribe( + &mut self, + ) -> futures::channel::mpsc::UnboundedReceiver<( + u64, + Ordered, + Ordered, + )> { + self.oracle.subscribe().await + } +} From 27885241add8bf0f001b45fe110cb06a44d21629 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Fri, 7 Nov 2025 17:20:24 -0500 Subject: [PATCH 37/81] chore: update trait bounds and use context cell --- application/src/actor.rs | 108 ++++++++++++++++++++++++------------- application/src/ingress.rs | 28 ++++++---- 2 files changed, 89 insertions(+), 47 deletions(-) diff --git a/application/src/actor.rs b/application/src/actor.rs index 09d671d4..c98c2583 100644 --- a/application/src/actor.rs +++ b/application/src/actor.rs @@ -2,9 +2,9 @@ use crate::{ ApplicationConfig, ingress::{Mailbox, Message}, }; -use anyhow::{Result, anyhow}; +use anyhow::{Context, Result, anyhow}; use commonware_macros::select; -use commonware_runtime::{Clock, Handle, Metrics, Spawner, Storage}; +use commonware_runtime::{Clock, ContextCell, Handle, Metrics, Spawner, Storage, spawn_cell}; use commonware_utils::SystemTimeExt; use futures::{ FutureExt, StreamExt as _, @@ -14,22 +14,23 @@ use futures::{ use rand::Rng; use tokio_util::sync::CancellationToken; -use commonware_consensus::types::View; -use futures::task::{Context, Poll}; +use commonware_consensus::simplex::signing_scheme::Scheme; +use commonware_consensus::types::Round; +use commonware_cryptography::bls12381::primitives::variant::Variant; +use commonware_cryptography::{PublicKey, Signer}; +use futures::task::Poll; +use std::marker::PhantomData; use std::{ pin::Pin, sync::{Arc, Mutex}, time::Duration, }; -use commonware_consensus::simplex::signing_scheme::Scheme; -use commonware_consensus::types::Round; -use commonware_cryptography::Signer; use summit_finalizer::FinalizerMailbox; use tracing::{error, info, warn}; #[cfg(feature = "prom")] use metrics::histogram; -use summit_syncer::ingress::mailbox::Mailbox as SyncerMailbox; +use summit_syncer::ingress::mailbox::{Identifier, Mailbox as SyncerMailbox}; use summit_types::{Block, Digest, EngineClient}; // Define a future that checks if the oneshot channel is closed using a mutable reference @@ -40,7 +41,7 @@ struct ChannelClosedFuture<'a, T> { impl Future for ChannelClosedFuture<'_, T> { type Output = (); - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + fn poll(mut self: Pin<&mut Self>, cx: &mut futures::task::Context<'_>) -> Poll { // Use poll_canceled to check if the receiver has dropped the channel match self.sender.poll_canceled(cx) { Poll::Ready(()) => Poll::Ready(()), // Receiver dropped, channel closed @@ -58,42 +59,66 @@ pub struct Actor< R: Storage + Metrics + Clock + Spawner + governor::clock::Clock + Rng, C: EngineClient, S: Scheme, + P: PublicKey, K: Signer, + V: Variant, > { - context: R, + context: ContextCell, mailbox: mpsc::Receiver, engine_client: C, - built_block: Arc>>, + built_block: Arc>>>, genesis_hash: [u8; 32], cancellation_token: CancellationToken, + _scheme_marker: PhantomData, + _key_marker: PhantomData

, + _signer_marker: PhantomData, + _variant_marker: PhantomData, } -impl - Actor +impl< + R: Storage + Metrics + Clock + Spawner + governor::clock::Clock + Rng, + C: EngineClient, + S: Scheme, + P: PublicKey, + K: Signer, + V: Variant, +> Actor { - pub async fn new(context: R, cfg: ApplicationConfig) -> (Self, Mailbox) { + pub async fn new(context: R, cfg: ApplicationConfig) -> (Self, Mailbox

) { let (tx, rx) = mpsc::channel(cfg.mailbox_size); let genesis_hash = cfg.genesis_hash; ( Self { - context, + context: ContextCell::new(context), mailbox: rx, engine_client: cfg.engine_client, built_block: Arc::new(Mutex::new(None)), genesis_hash, cancellation_token: cfg.cancellation_token, + _scheme_marker: PhantomData, + _key_marker: PhantomData, + _signer_marker: PhantomData, + _variant_marker: PhantomData, }, Mailbox::new(tx), ) } - pub fn start(mut self, syncer: SyncerMailbox, finalizer: FinalizerMailbox) -> Handle<()> { - self.context.spawn_ref()(self.run(syncer, finalizer)) + pub fn start( + mut self, + syncer: SyncerMailbox>, + finalizer: FinalizerMailbox>, + ) -> Handle<()> { + spawn_cell!(self.context, self.run(syncer, finalizer).await) } - pub async fn run(mut self, mut syncer: SyncerMailbox, mut finalizer: FinalizerMailbox) { + pub async fn run( + mut self, + mut syncer: SyncerMailbox>, + mut finalizer: FinalizerMailbox>, + ) { let rand_id: u8 = rand::random(); let mut signal = self.context.stopped().fuse(); let cancellation_token = self.cancellation_token.clone(); @@ -120,7 +145,7 @@ impl { + res = self.handle_proposal(parent, &mut syncer, &mut finalizer, round) => { match res { Ok(block) => { // store block @@ -138,7 +163,7 @@ impl { // simplex dropped receiver - warn!(round, "proposal aborted"); + warn!("proposal aborted for round {round}"); } } } @@ -167,17 +192,18 @@ impl { info!("{rand_id} Handling message Verify round: {}", round); - // Get the parent block + + // Subscribe to blocks (will wait for them if not available) let parent_request = if parent.1 == self.genesis_hash.into() { Either::Left(future::ready(Ok(Block::genesis(self.genesis_hash)))) } else { - Either::Right(syncer.get(Some(parent.0), parent.1).await) + Either::Right(syncer.subscribe(None, parent.1).await) }; - - let block_request = syncer.get(None, payload).await; + let block_request = syncer.subscribe(Some(round), payload).await; // Wait for the blocks to be available or the request to be cancelled in a separate task (to // continue processing other messages) + self.context.with_label("verify").spawn({ let mut syncer = syncer.clone(); move |_| async move { @@ -193,12 +219,12 @@ impl { - warn!(round, "verify aborted"); + warn!("verify aborted for round {round}"); } } } @@ -221,10 +247,10 @@ impl, - finalizer: &mut FinalizerMailbox, + syncer: &mut SyncerMailbox>, + finalizer: &mut FinalizerMailbox>, round: Round, - ) -> Result { + ) -> Result> { #[cfg(feature = "prom")] let proposal_start = std::time::Instant::now(); @@ -234,9 +260,12 @@ impl Drop - for Actor +impl< + R: Storage + Metrics + Clock + Spawner + governor::clock::Clock + Rng, + C: EngineClient, + S: Scheme, + P: PublicKey, + K: Signer, + V: Variant, +> Drop for Actor { fn drop(&mut self) { self.cancellation_token.cancel(); } } -fn handle_verify(block: &Block, parent: Block) -> bool { +fn handle_verify(block: &Block, parent: Block) -> bool { if block.eth_parent_hash() != parent.eth_block_hash() { return false; } diff --git a/application/src/ingress.rs b/application/src/ingress.rs index e32437fd..e8f45a15 100644 --- a/application/src/ingress.rs +++ b/application/src/ingress.rs @@ -1,11 +1,12 @@ -use commonware_consensus::{Automaton, Relay, simplex::types::Context, types::View, Epochable}; use commonware_consensus::types::{Epoch, Round}; +use commonware_consensus::{Automaton, Epochable, Relay, simplex::types::Context, types::View}; +use commonware_cryptography::PublicKey; use commonware_cryptography::sha256::Digest; -use commonware_cryptography::Signer; use futures::{ SinkExt, channel::{mpsc, oneshot}, }; +use std::marker::PhantomData; pub enum Message { Genesis { @@ -29,18 +30,22 @@ pub enum Message { } #[derive(Clone)] -pub struct Mailbox { +pub struct Mailbox { sender: mpsc::Sender, + _signer_marker: PhantomData

, } -impl Mailbox { +impl Mailbox

{ pub fn new(sender: mpsc::Sender) -> Self { - Self { sender } + Self { + sender, + _signer_marker: PhantomData, + } } } -impl Automaton for Mailbox { - type Context = Context; +impl Automaton for Mailbox

{ + type Context = Context; type Digest = Digest; async fn genesis(&mut self, epoch: ::Epoch) -> Self::Digest { @@ -52,7 +57,10 @@ impl Automaton for Mailbox { receiver.await.expect("Failed to receive genesis") } - async fn propose(&mut self, context: Context) -> oneshot::Receiver { + async fn propose( + &mut self, + context: Context, + ) -> oneshot::Receiver { // If we linked payloads to their parent, we would include // the parent in the `Context` in the payload. let (response, receiver) = oneshot::channel(); @@ -69,7 +77,7 @@ impl Automaton for Mailbox { async fn verify( &mut self, - context: Context, + context: Context, payload: Self::Digest, ) -> oneshot::Receiver { // If we linked payloads to their parent, we would verify @@ -88,7 +96,7 @@ impl Automaton for Mailbox { } } -impl Relay for Mailbox { +impl Relay for Mailbox

{ type Digest = Digest; async fn broadcast(&mut self, digest: Self::Digest) { From 7de3f724a08115d6c0205c432210643f9d1a11de Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Fri, 7 Nov 2025 17:23:48 -0500 Subject: [PATCH 38/81] chore: update types --- finalizer/src/block_fetcher.rs | 112 --------------------------------- types/src/account.rs | 2 +- types/src/checkpoint.rs | 2 +- types/src/consensus_state.rs | 10 +-- types/src/engine_client.rs | 17 +++-- types/src/genesis.rs | 19 +++--- types/src/header.rs | 41 ++++++++---- types/src/keystore.rs | 4 +- types/src/lib.rs | 4 +- types/src/registry.rs | 47 +++++++++----- types/src/scheme.rs | 23 +++---- 11 files changed, 109 insertions(+), 172 deletions(-) delete mode 100644 finalizer/src/block_fetcher.rs diff --git a/finalizer/src/block_fetcher.rs b/finalizer/src/block_fetcher.rs deleted file mode 100644 index 53d740e6..00000000 --- a/finalizer/src/block_fetcher.rs +++ /dev/null @@ -1,112 +0,0 @@ -/* -Requests the finalized blocks (in order) from the orchestrator, sends them to the finalizer to be executed, -waits for confirmation that the finalizer has processed the block. - -Gets the highest height for which the application has processed from the finalizer. This allows resuming -processing from the last processed height after a restart. -*/ - -use commonware_cryptography::Committable as _; -use futures::{ - SinkExt as _, StreamExt as _, - channel::{mpsc, oneshot}, -}; -use summit_syncer::Orchestrator; -use summit_types::{BlockEnvelope, utils::is_last_block_of_epoch}; -use tracing::{debug, error}; -pub struct BlockFetcher { - // Orchestrator that stores the finalized blocks. - orchestrator: Orchestrator, - - // Notifier to indicate that the finalized blocks have been updated and should be re-queried. - notifier_rx: mpsc::Receiver<()>, - - // Number of blocks per epoch - epoch_num_blocks: u64, - - // The lowest height from which to begin syncing - sync_height: u64, - - finalizer_mailbox: mpsc::Sender<(BlockEnvelope, oneshot::Sender<()>)>, -} - -impl BlockFetcher { - /// Initialize the finalizer. - pub fn new( - orchestrator: Orchestrator, - notifier_rx: mpsc::Receiver<()>, - epoch_num_blocks: u64, - sync_height: u64, - ) -> (Self, mpsc::Receiver<(BlockEnvelope, oneshot::Sender<()>)>) { - let (finalizer_mailbox, finalized_block_envelopes) = mpsc::channel(100); // todo(dalton) take channel size from a config - ( - Self { - orchestrator, - notifier_rx, - epoch_num_blocks, - sync_height, - finalizer_mailbox, - }, - finalized_block_envelopes, - ) - } - - /// Run the block_fetcher, which continuously fetches and sends finalized blocks to finalizer. - pub async fn run(mut self) { - let mut latest = self.sync_height; - - // The main loop to process finalized blocks. This loop will hot-spin until a block is - // available, at which point it will process it and continue. If a block is not available, - // it will request a repair and wait for a notification of an update before retrying. - loop { - // The next height to process is the next height after the last processed height. - let height = latest + 1; - - let (block, finalized) = if is_last_block_of_epoch(height, self.epoch_num_blocks) { - self.orchestrator.get_with_finalized(height).await - } else { - (self.orchestrator.get(height).await, None) - }; - - // Attempt to get the next block from the orchestrator. - if let Some(block) = block { - // Sanity-check that the block height is the one we expect. - assert_eq!(block.height(), height, "block height mismatch"); - - // Send the block to the finalizer. - // - // After an unclean shutdown (where the finalizer metadata is not synced after some - // height is processed by the application), it is possible that the application may - // be asked to process a block it has already seen (which it can simply ignore). - let commitment = block.commitment(); - let envelope = BlockEnvelope { block, finalized }; - let (tx, rx) = oneshot::channel(); - self.finalizer_mailbox - .send((envelope, tx)) - .await - .expect("BlockFetcher->Finalizer channel closed"); - rx.await.expect("Unable to get response from finalizer"); - // Record that we have processed up through this height. - latest = height; - - // Notify the orchestrator that the block has been processed. - self.orchestrator.processed(height, commitment).await; - - // Loop again without waiting for a notification (there may be more to process). - continue; - } - - // We've reached a height at which we have no (finalized) block. - // It may be the case that the block is not finalized yet, or that there is a gap. - // Notify the orchestrator that we're trying to access this block. - self.orchestrator.repair(height).await; - - // Wait for a notification from the orchestrator that new blocks are available. - debug!(height, "waiting to index finalized block"); - let Some(()) = self.notifier_rx.next().await else { - error!("orchestrator closed, shutting down"); - return; - }; - } - } -} diff --git a/types/src/account.rs b/types/src/account.rs index 1ef96369..fc0db2e1 100644 --- a/types/src/account.rs +++ b/types/src/account.rs @@ -36,7 +36,7 @@ pub struct ValidatorAccount { pub balance: u64, // Balance in gwei pub pending_withdrawal_amount: u64, // Sum of pending withdrawals in gwei pub status: ValidatorStatus, - pub last_deposit_index: u64, // Last deposit request index + pub last_deposit_index: u64, // Last deposit request index } impl TryFrom<&[u8]> for ValidatorAccount { diff --git a/types/src/checkpoint.rs b/types/src/checkpoint.rs index 016197bc..88c37fed 100644 --- a/types/src/checkpoint.rs +++ b/types/src/checkpoint.rs @@ -130,9 +130,9 @@ mod tests { use crate::checkpoint::Checkpoint; use crate::consensus_state::ConsensusState; use commonware_codec::DecodeExt; + use commonware_cryptography::{PrivateKeyExt, Signer, bls12381}; use ssz::{Decode, Encode}; use std::collections::{HashMap, VecDeque}; - use commonware_cryptography::{bls12381, PrivateKeyExt, Signer}; fn parse_public_key(public_key: &str) -> commonware_cryptography::ed25519::PublicKey { commonware_cryptography::ed25519::PublicKey::decode( diff --git a/types/src/consensus_state.rs b/types/src/consensus_state.rs index bd9b8dbb..aae56b64 100644 --- a/types/src/consensus_state.rs +++ b/types/src/consensus_state.rs @@ -7,8 +7,8 @@ use alloy_eips::eip4895::Withdrawal; use alloy_rpc_types_engine::ForkchoiceState; use bytes::{Buf, BufMut}; use commonware_codec::{DecodeExt, EncodeSize, Error, Read, ReadExt, Write}; -use std::collections::{HashMap, VecDeque}; use commonware_cryptography::bls12381; +use std::collections::{HashMap, VecDeque}; #[derive(Clone, Debug, Default)] pub struct ConsensusState { @@ -118,12 +118,14 @@ impl ConsensusState { } pub fn get_validator_keys(&self) -> Vec<(PublicKey, bls12381::PublicKey)> { - let mut peers: Vec<(PublicKey, bls12381::PublicKey)> = self.validator_accounts + let mut peers: Vec<(PublicKey, bls12381::PublicKey)> = self + .validator_accounts .iter() .filter(|(_, acc)| !(acc.status == ValidatorStatus::Inactive)) .map(|(v, acc)| { let mut key_bytes = &v[..]; - let node_public_key = PublicKey::read(&mut key_bytes).expect("failed to parse public key"); + let node_public_key = + PublicKey::read(&mut key_bytes).expect("failed to parse public key"); let consensus_public_key = acc.consensus_public_key.clone(); (node_public_key, consensus_public_key) }) @@ -304,7 +306,7 @@ mod tests { use alloy_eips::eip4895::Withdrawal; use alloy_primitives::Address; use commonware_codec::{DecodeExt, Encode}; - use commonware_cryptography::{bls12381, PrivateKeyExt, Signer}; + use commonware_cryptography::{PrivateKeyExt, Signer, bls12381}; fn create_test_deposit_request(index: u64, amount: u64) -> DepositRequest { let mut withdrawal_credentials = [0u8; 32]; diff --git a/types/src/engine_client.rs b/types/src/engine_client.rs index 4d535b02..3cc38403 100644 --- a/types/src/engine_client.rs +++ b/types/src/engine_client.rs @@ -26,6 +26,8 @@ use tracing::{error, warn}; use crate::Block; use alloy_transport_ipc::IpcConnect; +use commonware_cryptography::Signer; +use commonware_cryptography::bls12381::primitives::variant::Variant; use std::future::Future; pub trait EngineClient: Clone + Send + Sync + 'static { @@ -42,7 +44,10 @@ pub trait EngineClient: Clone + Send + Sync + 'static { payload_id: PayloadId, ) -> impl Future + Send; - fn check_payload(&self, block: &Block) -> impl Future + Send; + fn check_payload( + &self, + block: &Block, + ) -> impl Future + Send; fn commit_hash(&self, fork_choice_state: ForkchoiceState) -> impl Future + Send; } @@ -97,7 +102,7 @@ impl EngineClient for RethEngineClient { self.provider.get_payload_v4(payload_id).await.unwrap() } - async fn check_payload(&self, block: &Block) -> PayloadStatus { + async fn check_payload(&self, block: &Block) -> PayloadStatus { self.provider .new_payload_v4( block.payload.clone(), @@ -131,6 +136,8 @@ pub mod base_benchmarking { ForkchoiceState, PayloadId, PayloadStatus, }; use alloy_transport_ipc::IpcConnect; + use commonware_cryptography::Signer; + use commonware_cryptography::bls12381::primitives::variant::Variant; use op_alloy_network::Optimism; use serde::{Deserialize, Serialize}; use std::fs; @@ -214,7 +221,7 @@ pub mod base_benchmarking { } } - async fn check_payload(&self, block: &Block) -> PayloadStatus { + async fn check_payload(&self, block: &Block) -> PayloadStatus { let timestamp = block.payload.payload_inner.payload_inner.timestamp; let canyon_activation = 1704992401u64; // January 11, 2024 - Canyon activation on Base @@ -328,6 +335,8 @@ pub mod benchmarking { ForkchoiceState, PayloadId, PayloadStatus, }; use alloy_transport_ipc::IpcConnect; + use commonware_cryptography::Signer; + use commonware_cryptography::bls12381::primitives::variant::Variant; use serde::{Deserialize, Serialize}; use std::fs; use std::path::PathBuf; @@ -388,7 +397,7 @@ pub mod benchmarking { } } - async fn check_payload(&self, block: &Block) -> PayloadStatus { + async fn check_payload(&self, block: &Block) -> PayloadStatus { // For Ethereum, use standard engine_newPayloadV4 without Optimism-specific logic self.provider .new_payload_v4( diff --git a/types/src/genesis.rs b/types/src/genesis.rs index c4a06eca..445cc74d 100644 --- a/types/src/genesis.rs +++ b/types/src/genesis.rs @@ -1,11 +1,11 @@ use crate::PublicKey; use alloy_primitives::Address; +use anyhow::Context; use commonware_codec::DecodeExt; use commonware_cryptography::bls12381; use commonware_utils::from_hex_formatted; use serde::{Deserialize, Serialize}; use std::net::SocketAddr; -use anyhow::Context; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Genesis { @@ -60,20 +60,21 @@ impl TryFrom<&GenesisValidator> for Validator { type Error = anyhow::Error; fn try_from(value: &GenesisValidator) -> Result { - let node_key_bytes = from_hex_formatted(&value.node_public_key).context("Node PublicKey bad format")?; + let node_key_bytes = + from_hex_formatted(&value.node_public_key).context("Node PublicKey bad format")?; let node_public_key = PublicKey::decode(&*node_key_bytes)?; - let consensus_key_bytes = from_hex_formatted(&value.consensus_public_key).context("Consensus PublicKey bad format")?; + let consensus_key_bytes = from_hex_formatted(&value.consensus_public_key) + .context("Consensus PublicKey bad format")?; let consensus_public_key = bls12381::PublicKey::decode(&*consensus_key_bytes)?; Ok(Validator { node_public_key, consensus_public_key, ip_address: value.ip_address.parse()?, - withdrawal_credentials: value.withdrawal_credentials.parse()? + withdrawal_credentials: value.withdrawal_credentials.parse()?, }) } - } impl Genesis { @@ -110,7 +111,9 @@ impl Genesis { Ok(validators) } - pub fn get_consensus_keys(&self) -> Result, Box> { + pub fn get_consensus_keys( + &self, + ) -> Result, Box> { let mut keys = Vec::new(); for validator in &self.validators { let key_bytes = from_hex_formatted(&validator.consensus_public_key) @@ -121,7 +124,9 @@ impl Genesis { Ok(keys) } - pub fn get_validator_keys(&self) -> Result, Box> { + pub fn get_validator_keys( + &self, + ) -> Result, Box> { let mut keys = Vec::new(); for validator in &self.validators { let node_key_bytes = from_hex_formatted(&validator.node_public_key) diff --git a/types/src/header.rs b/types/src/header.rs index 9f29a540..58ed89f5 100644 --- a/types/src/header.rs +++ b/types/src/header.rs @@ -266,12 +266,15 @@ impl Read for Header { #[derive(Clone, Debug, PartialEq, Eq)] pub struct FinalizedHeader { pub header: Header, - pub finalized: Finalization, + pub finalization: Finalization, } impl FinalizedHeader { - pub fn new(header: Header, finalized: Finalization) -> Self { - Self { header, finalized } + pub fn new(header: Header, finalization: Finalization) -> Self { + Self { + header, + finalization, + } } } @@ -284,7 +287,7 @@ impl ssz::Encode for FinalizedHeader { // For simplicity, encode header first, then finalized proof using commonware encoding let header_bytes = self.header.as_ssz_bytes(); let mut finalized_bytes = Vec::new(); - self.finalized.write(&mut finalized_bytes); + self.finalization.write(&mut finalized_bytes); let offset = 8; // Two 4-byte length prefixes let mut encoder = ssz::SszEncoder::container(buf, offset); @@ -296,7 +299,7 @@ impl ssz::Encode for FinalizedHeader { fn ssz_bytes_len(&self) -> usize { let header_bytes = self.header.as_ssz_bytes(); let mut finalized_bytes = Vec::new(); - self.finalized.write(&mut finalized_bytes); + self.finalization.write(&mut finalized_bytes); header_bytes.len() + finalized_bytes.len() + 8 // Two 4-byte length prefixes } @@ -322,19 +325,33 @@ where let header = Header::from_ssz_bytes(&header_bytes) .map_err(|e| ssz::DecodeError::BytesInvalid(format!("{e:?}")))?; + // The certificate config needs to be derived from the buffer size (participant count) + // This works because we know bls12381_multisig::Certificate::Cfg = usize + // We construct it here where we have the concrete type information let mut finalized_buf = finalized_bytes.as_slice(); - let cfg = ::Cfg::from(finalized_buf.remaining()); - let finalized = Finalization::::read_cfg(&mut finalized_buf, &cfg) + + // For BLS multisig, the Cfg is the participant count, which we derive from buffer size + // This is a limitation of the SSZ decode not having access to external config + // The actual participant count should ideally come from the registry/validator set + let participant_count_bytes = finalized_buf.remaining(); + + // We need to convert usize to Cfg type, but can't use From without the bound + // So we're stuck needing the From bound here for SSZ compatibility + let cfg = ::Cfg::from(participant_count_bytes); + let finalization = Finalization::::read_cfg(&mut finalized_buf, &cfg) .map_err(|e| ssz::DecodeError::BytesInvalid(format!("{e:?}")))?; // Ensure the finalization is for the header - if finalized.proposal.payload != header.digest { + if finalization.proposal.payload != header.digest { return Err(ssz::DecodeError::BytesInvalid( "Finalization payload does not match header digest".to_string(), )); } - Ok(Self { header, finalized }) + Ok(Self { + header, + finalization, + }) } } @@ -380,6 +397,7 @@ mod test { use super::*; use alloy_primitives::{U256, hex}; use commonware_codec::{DecodeExt as _, Encode as _}; + use commonware_consensus::simplex::signing_scheme::ed25519; use commonware_consensus::{ simplex::{ signing_scheme::{ed25519::Certificate, utils::Signers}, @@ -387,7 +405,6 @@ mod test { }, types::Round, }; - use commonware_consensus::simplex::signing_scheme::ed25519; use commonware_cryptography::ed25519::PrivateKey; use commonware_cryptography::{PrivateKeyExt, Signer}; use ssz::Decode; @@ -483,7 +500,7 @@ mod test { let encoded = finalized_header.encode(); let decoded = FinalizedHeader::::decode(encoded).unwrap(); - assert_eq!(finalized_header.finalized, decoded.finalized); + assert_eq!(finalized_header.finalization, decoded.finalization); assert_eq!(finalized_header.header, decoded.header); assert_eq!(finalized_header.header, header); @@ -535,7 +552,7 @@ mod test { let finalized_header: FinalizedHeader = FinalizedHeader { header, - finalized: wrong_finalized, + finalization: wrong_finalized, }; let encoded = finalized_header.as_ssz_bytes(); diff --git a/types/src/keystore.rs b/types/src/keystore.rs index 0c3167d1..99669c02 100644 --- a/types/src/keystore.rs +++ b/types/src/keystore.rs @@ -1,5 +1,5 @@ -use commonware_cryptography::bls12381::PrivateKey; use commonware_cryptography::Signer; +use commonware_cryptography::bls12381::PrivateKey; use zeroize::{Zeroize, ZeroizeOnDrop}; #[derive(Zeroize, ZeroizeOnDrop)] @@ -8,4 +8,4 @@ pub struct KeyStore { pub consensus_key: PrivateKey, } -// TODO(matthias): do we have to explicitly call zeroize() on the members? \ No newline at end of file +// TODO(matthias): do we have to explicitly call zeroize() on the members? diff --git a/types/src/lib.rs b/types/src/lib.rs index fb12af3d..616e58ed 100644 --- a/types/src/lib.rs +++ b/types/src/lib.rs @@ -7,14 +7,14 @@ pub mod engine_client; pub mod execution_request; pub mod genesis; pub mod header; +pub mod keystore; pub mod network_oracle; pub mod registry; #[cfg(feature = "e2e")] pub mod reth; +pub mod scheme; pub mod utils; pub mod withdrawal; -pub mod scheme; -pub mod keystore; use alloy_rpc_types_engine::ForkchoiceState; pub use block::*; diff --git a/types/src/registry.rs b/types/src/registry.rs index b5c0e0ac..fd33806f 100644 --- a/types/src/registry.rs +++ b/types/src/registry.rs @@ -1,10 +1,10 @@ use crate::PublicKey; use commonware_consensus::types::View; use commonware_p2p::Manager; -use std::collections::{BTreeMap, HashSet}; -use std::sync::{Arc, RwLock}; use commonware_utils::set::Ordered; use futures::channel::mpsc::{UnboundedReceiver, UnboundedSender}; +use std::collections::{BTreeMap, HashSet}; +use std::sync::{Arc, RwLock}; #[derive(Default, Clone, Debug)] struct Inner { @@ -24,7 +24,10 @@ impl Registry { pub fn new(id: u64, participants: Vec) -> Self { let mut sets = BTreeMap::new(); sets.insert(id, Ordered::from(participants)); - let inner = Inner { sets, subscribers: vec![] }; + let inner = Inner { + sets, + subscribers: vec![], + }; Self { inner: Arc::new(RwLock::new(inner)), } @@ -35,9 +38,13 @@ impl Registry { // TODO(matthias): we should also consider enforcing that the previous id must exist, // and do something like inner.sets.get(id - 1) - let (_last_id, old_set) = inner.sets.last_key_value().expect("registry was initialized with an id"); + let (_last_id, old_set) = inner + .sets + .last_key_value() + .expect("registry was initialized with an id"); - let mut new_set = Vec::with_capacity((old_set.len() + add.len()).saturating_sub(remove.len())); + let mut new_set = + Vec::with_capacity((old_set.len() + add.len()).saturating_sub(remove.len())); let remove: HashSet = HashSet::from_iter(remove.iter().cloned()); for key in old_set { if !remove.contains(key) { @@ -53,9 +60,9 @@ impl Registry { // Notify all subscribers let notification = (id, old_set, Ordered::from(new_set)); - inner.subscribers.retain(|tx| { - tx.unbounded_send(notification.clone()).is_ok() - }); + inner + .subscribers + .retain(|tx| tx.unbounded_send(notification.clone()).is_ok()); // TODO(matthias): consider garbage collection for old IDs } @@ -65,11 +72,13 @@ impl Manager for Registry { type PublicKey = PublicKey; type Peers = Vec; - fn update(&mut self, id: u64, peers: Self::Peers) -> impl Future + Send { + fn update(&mut self, id: u64, peers: Self::Peers) -> impl Future + Send { let mut inner = self.inner.write().unwrap(); // Since IDs are monotonically increasing, the old set is the last one in the map - let old_set = inner.sets.last_key_value() + let old_set = inner + .sets + .last_key_value() .map(|(_, set)| set.clone()) .unwrap_or_else(|| Ordered::from(Vec::new())); @@ -78,20 +87,27 @@ impl Manager for Registry { // Notify all subscribers let notification = (id, old_set, new_set); - inner.subscribers.retain(|tx| { - tx.unbounded_send(notification.clone()).is_ok() - }); + inner + .subscribers + .retain(|tx| tx.unbounded_send(notification.clone()).is_ok()); async {} } - fn peer_set(&mut self, id: u64) -> impl Future>> + Send { + fn peer_set( + &mut self, + id: u64, + ) -> impl Future>> + Send { let inner = self.inner.write().unwrap(); let set = inner.sets.get(&id).cloned(); async move { set } } - fn subscribe(&mut self) -> impl Future, Ordered)>> + Send { + fn subscribe( + &mut self, + ) -> impl Future< + Output = UnboundedReceiver<(u64, Ordered, Ordered)>, + > + Send { let (tx, rx) = futures::channel::mpsc::unbounded(); let mut inner = self.inner.write().unwrap(); inner.subscribers.push(tx); @@ -324,4 +340,3 @@ mod tests { }); } } - diff --git a/types/src/scheme.rs b/types/src/scheme.rs index b6b0d7e4..48693f59 100644 --- a/types/src/scheme.rs +++ b/types/src/scheme.rs @@ -1,13 +1,14 @@ -use std::collections::HashMap; -use std::sync::{Arc, Mutex}; use commonware_consensus::simplex::signing_scheme::{self, Scheme}; use commonware_consensus::types::Epoch; +use commonware_cryptography::bls12381::primitives::group; use commonware_cryptography::bls12381::primitives::variant::Variant; use commonware_cryptography::{PublicKey, Signer}; -use commonware_cryptography::bls12381::primitives::group; use commonware_utils::set::{Ordered, OrderedAssociated}; +use std::collections::HashMap; +use std::sync::{Arc, Mutex}; -pub type MultisigScheme = signing_scheme::bls12381_multisig::Scheme<::PublicKey, V>; +pub type MultisigScheme = + signing_scheme::bls12381_multisig::Scheme<::PublicKey, V>; /// Supplies the signing scheme the marshal should use for a given epoch. pub trait SchemeProvider: Clone + Send + Sync + 'static { @@ -82,12 +83,12 @@ impl EpochSchemeProvider for SummitSchemeProvider { &self, transition: &EpochTransition, ) -> Self::Scheme { - let participants: OrderedAssociated = - transition.dealers - .iter() - .cloned() - .zip(transition.bls_keys.iter().cloned()) - .collect(); + let participants: OrderedAssociated = transition + .dealers + .iter() + .cloned() + .zip(transition.bls_keys.iter().cloned()) + .collect(); MultisigScheme::::new(participants, self.bls_private_key.clone()) } @@ -102,4 +103,4 @@ pub struct EpochTransition { /// The BLS public keys for the epoch. /// Contains the BLS public keys corresponding to each dealer. pub bls_keys: Vec, -} \ No newline at end of file +} From fa62267ef064b8c23e02fdf5966c5ca8a14b53a5 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Fri, 7 Nov 2025 17:25:07 -0500 Subject: [PATCH 39/81] feat: orchestrator and update syncer --- node/src/config.rs | 39 ++++---- node/src/engine.rs | 240 +++++++++++++++++++++++++++------------------ 2 files changed, 168 insertions(+), 111 deletions(-) diff --git a/node/src/config.rs b/node/src/config.rs index f5c0b0f8..a95af67b 100644 --- a/node/src/config.rs +++ b/node/src/config.rs @@ -1,21 +1,20 @@ -use std::{num::NonZeroU32, time::Duration}; - use crate::keys::read_keys_from_keystore; use anyhow::{Context, Result}; -use commonware_cryptography::bls12381::{self, primitives::group}; -use commonware_cryptography::bls12381::primitives::variant::Variant; use commonware_cryptography::Signer; +use commonware_cryptography::bls12381; use commonware_utils::from_hex_formatted; use governor::Quota; +use std::{num::NonZeroU32, time::Duration}; use summit_types::consensus_state::ConsensusState; +use summit_types::keystore::KeyStore; use summit_types::network_oracle::NetworkOracle; use summit_types::{EngineClient, Genesis, PrivateKey, PublicKey}; -use summit_types::keystore::KeyStore; +use zeroize::ZeroizeOnDrop; /* DEFAULTS */ -pub const PENDING_CHANNEL: u32 = 0; -pub const RESOLVER_CHANNEL: u32 = 1; -pub const BROADCASTER_CHANNEL: u32 = 2; -pub const BACKFILLER_CHANNEL: u32 = 3; +pub const PENDING_CHANNEL: u64 = 0; +pub const RESOLVER_CHANNEL: u64 = 1; +pub const BROADCASTER_CHANNEL: u64 = 2; +pub const BACKFILLER_CHANNEL: u64 = 3; pub const MAILBOX_SIZE: usize = 16384; const FETCH_TIMEOUT: Duration = Duration::from_secs(5); @@ -27,11 +26,12 @@ pub const MESSAGE_BACKLOG: usize = 16384; const BACKFILL_QUOTA: u32 = 10; // in seconds const FETCH_RATE_P2P: u32 = 128; // in seconds -pub struct EngineConfig> { +pub struct EngineConfig> +{ pub engine_client: C, pub partition_prefix: String, pub key_store: KeyStore, - //pub participants: Vec, + pub participants: Vec<(PublicKey, bls12381::PublicKey)>, pub mailbox_size: usize, pub backfill_quota: Quota, pub deque_size: usize, @@ -55,12 +55,14 @@ pub struct EngineConfig> EngineConfig { +impl> + EngineConfig +{ pub fn get_engine_config( engine_client: C, oracle: O, key_store: KeyStore, - participants: Vec, + participants: Vec<(PublicKey, bls12381::PublicKey)>, db_prefix: String, genesis: &Genesis, initial_state: ConsensusState, @@ -69,7 +71,7 @@ impl> Eng engine_client, partition_prefix: db_prefix, key_store, - //participants, + participants, oracle, mailbox_size: MAILBOX_SIZE, backfill_quota: Quota::per_second(NonZeroU32::new(BACKFILL_QUOTA).unwrap()), @@ -96,10 +98,11 @@ impl> Eng pub(crate) fn load_key_store(key_store_path: &str) -> Result> { match read_keys_from_keystore(key_store_path).context("failed to load key store") { - Ok((node_key, consensus_key)) => { - Ok(KeyStore { node_key, consensus_key }) - } - Err(e) => Err(e) + Ok((node_key, consensus_key)) => Ok(KeyStore { + node_key, + consensus_key, + }), + Err(e) => Err(e), } } diff --git a/node/src/engine.rs b/node/src/engine.rs index d652064c..6f6cd61d 100644 --- a/node/src/engine.rs +++ b/node/src/engine.rs @@ -1,26 +1,35 @@ use crate::config::EngineConfig; use commonware_broadcast::buffered; +use commonware_codec::{DecodeExt, Encode}; +use commonware_consensus::simplex::signing_scheme::Scheme; +use commonware_consensus::simplex::signing_scheme::bls12381_multisig; use commonware_consensus::simplex::{self, Engine as Simplex}; -use commonware_cryptography::Signer as _; -use commonware_p2p::{Receiver, Sender}; +use commonware_consensus::{Automaton, Relay}; +use commonware_cryptography::bls12381::primitives::group; +use commonware_cryptography::bls12381::primitives::variant::Variant; +use commonware_cryptography::{Signer as _, Signer}; +use commonware_p2p::{Blocker, Manager, Receiver, Sender, utils::requester}; use commonware_runtime::buffer::PoolRef; -use commonware_runtime::{Clock, Handle, Metrics, Spawner, Storage}; -use commonware_utils::NZUsize; +use commonware_runtime::{Clock, Handle, Metrics, Network, Spawner, Storage}; +use commonware_utils::{NZU64, NZUsize}; use futures::FutureExt; -use futures::channel::mpsc; +use futures::channel::{mpsc, oneshot}; use futures::future::try_join_all; -use governor::clock::Clock as GClock; +use governor::{Quota, clock::Clock as GClock}; use rand::{CryptoRng, Rng}; -use std::num::NonZero; +use std::marker::PhantomData; +use std::num::{NonZero, NonZeroU32}; +use std::time::Duration; use summit_application::ApplicationConfig; use summit_finalizer::actor::Finalizer; use summit_finalizer::{FinalizerConfig, FinalizerMailbox}; -use summit_syncer::Orchestrator; use summit_types::network_oracle::NetworkOracle; use summit_types::registry::Registry; +use summit_types::scheme::{MultisigScheme, SummitSchemeProvider}; use summit_types::{Block, Digest, EngineClient, PrivateKey, PublicKey}; use tokio_util::sync::CancellationToken; use tracing::{error, info, warn}; +use zeroize::ZeroizeOnDrop; pub const PROTOCOL_VERSION: u32 = 1; @@ -31,6 +40,18 @@ const WRITE_BUFFER: NonZero = NZUsize!(1024 * 1024); const BUFFER_POOL_PAGE_SIZE: NonZero = NZUsize!(4_096); // 4KB const BUFFER_POOL_CAPACITY: NonZero = NZUsize!(8_192); // 32MB +const DEQUE_SIZE: usize = 10; +const ACTIVITY_TIMEOUT: u64 = 256; +const SYNCER_ACTIVITY_TIMEOUT_MULTIPLIER: u64 = 10; +const PRUNABLE_ITEMS_PER_SECTION: NonZero = NZU64!(4_096); +const IMMUTABLE_ITEMS_PER_SECTION: NonZero = NZU64!(262_144); +const FREEZER_TABLE_RESIZE_FREQUENCY: u8 = 4; +const FREEZER_TABLE_RESIZE_CHUNK_SIZE: u32 = 2u32.pow(16); // 3MB +const FREEZER_JOURNAL_TARGET_SIZE: u64 = 1024 * 1024 * 1024; // 1GB +const FREEZER_JOURNAL_COMPRESSION: Option = Some(3); +const FREEZER_TABLE_INITIAL_SIZE: u32 = 1024 * 1024; // 100mb +const MAX_REPAIR: u64 = 50; + // // Onboarding config (set arbitrarily for now) @@ -44,52 +65,64 @@ pub const VALIDATOR_WITHDRAWAL_PERIOD: u64 = 5; #[cfg(all(not(debug_assertions), not(feature = "e2e")))] const VALIDATOR_WITHDRAWAL_PERIOD: u64 = 100; #[cfg(all(feature = "e2e", not(debug_assertions)))] -pub const EPOCH_NUM_BLOCKS: u64 = 50; +pub const BLOCKS_PER_EPOCH: u64 = 50; #[cfg(debug_assertions)] -pub const EPOCH_NUM_BLOCKS: u64 = 10; +pub const BLOCKS_PER_EPOCH: u64 = 10; #[cfg(all(not(debug_assertions), not(feature = "e2e")))] -const EPOCH_NUM_BLOCKS: u64 = 1000; +const BLOCKS_PER_EPOCH: u64 = 1000; const VALIDATOR_MAX_WITHDRAWALS_PER_BLOCK: usize = 16; // pub struct Engine< - E: Clock + GClock + Rng + CryptoRng + Spawner + Storage + Metrics, + E: Clock + GClock + Rng + CryptoRng + Spawner + Storage + Metrics + Network, C: EngineClient, - O: NetworkOracle, + O: NetworkOracle + Blocker + Manager, + S: Signer, + V: Variant, > { context: E, - application: summit_application::Actor, - buffer: buffered::Engine, - buffer_mailbox: buffered::Mailbox, - syncer: summit_syncer::Actor, - syncer_mailbox: summit_syncer::Mailbox, - finalizer: Finalizer, - pub finalizer_mailbox: FinalizerMailbox, - orchestrator: Orchestrator, - simplex: Simplex< - E, - PrivateKey, - Digest, - summit_application::Mailbox, - summit_application::Mailbox, - summit_syncer::Mailbox, - Registry, - >, - + application: summit_application::Actor, S::PublicKey, S, V>, + application_mailbox: summit_application::Mailbox, + buffer: buffered::Engine>, + buffer_mailbox: buffered::Mailbox>, + syncer: summit_syncer::Actor, SummitSchemeProvider, MultisigScheme>, + syncer_mailbox: summit_syncer::Mailbox, Block>, + finalizer: Finalizer, V>, + pub finalizer_mailbox: FinalizerMailbox, Block>, + orchestrator: summit_orchestrator::Actor>, + oracle: O, + node_public_key: PublicKey, + mailbox_size: usize, sync_height: u64, cancellation_token: CancellationToken, } impl< - E: Clock + GClock + Rng + CryptoRng + Spawner + Storage + Metrics, + E: Clock + GClock + Rng + CryptoRng + Spawner + Storage + Metrics + Network, C: EngineClient, - O: NetworkOracle, -> Engine + O: NetworkOracle + Blocker + Manager, + S: Signer + ZeroizeOnDrop, + V: Variant, +> Engine +where + MultisigScheme: Scheme, { - pub async fn new(context: E, cfg: EngineConfig) -> Self { - let registry = Registry::new(cfg.participants.clone()); + pub async fn new(context: E, cfg: EngineConfig) -> Self { + let node_keys: Vec<_> = cfg + .participants + .iter() + .map(|(node_key, _)| node_key.clone()) + .collect(); + let registry = Registry::new(cfg.initial_state.epoch, node_keys); let buffer_pool = PoolRef::new(BUFFER_POOL_PAGE_SIZE, BUFFER_POOL_CAPACITY); + //let threshold = registry. + let encoded = cfg.key_store.consensus_key.encode(); + let private_scalar = group::Private::decode(&mut encoded.as_ref()) + .expect("failed to extract scalar from private key"); + let scheme_provider = + SummitSchemeProvider::new(cfg.key_store.node_key.clone(), private_scalar); + let sync_height = cfg.initial_state.latest_height; let cancellation_token = CancellationToken::new(); @@ -111,7 +144,7 @@ impl< let (buffer, buffer_mailbox) = buffered::Engine::new( context.with_label("buffer"), buffered::Config { - public_key: cfg.signer.public_key(), + public_key: cfg.key_store.node_key.public_key(), mailbox_size: cfg.mailbox_size, deque_size: cfg.deque_size, priority: true, @@ -121,18 +154,47 @@ impl< // create the syncer let syncer_config = summit_syncer::Config { + scheme_provider: scheme_provider.clone(), + epoch_length: BLOCKS_PER_EPOCH, partition_prefix: cfg.partition_prefix.clone(), - public_key: cfg.signer.public_key(), - registry: registry.clone(), mailbox_size: cfg.mailbox_size, - backfill_quota: cfg.backfill_quota, - activity_timeout: cfg.activity_timeout, - namespace: cfg.namespace.clone(), - buffer_pool: buffer_pool.clone(), - cancellation_token: cancellation_token.clone(), + view_retention_timeout: cfg.activity_timeout, + namespace: cfg.namespace.as_bytes().to_vec(), + + prunable_items_per_section: PRUNABLE_ITEMS_PER_SECTION, + immutable_items_per_section: IMMUTABLE_ITEMS_PER_SECTION, + freezer_table_initial_size: FREEZER_TABLE_INITIAL_SIZE, + freezer_table_resize_frequency: FREEZER_TABLE_RESIZE_FREQUENCY, + freezer_table_resize_chunk_size: FREEZER_TABLE_RESIZE_CHUNK_SIZE, + freezer_journal_target_size: FREEZER_JOURNAL_TARGET_SIZE, + freezer_journal_compression: FREEZER_JOURNAL_COMPRESSION, + freezer_journal_buffer_pool: buffer_pool.clone(), + replay_buffer: REPLAY_BUFFER, + write_buffer: WRITE_BUFFER, + block_codec_config: (), + max_repair: MAX_REPAIR, + _marker: PhantomData, }; - let (syncer, syncer_mailbox, orchestrator) = - summit_syncer::Actor::new(context.with_label("syncer"), syncer_config).await; + + let (syncer, syncer_mailbox) = + summit_syncer::Actor::init(context.with_label("syncer"), syncer_config).await; + + // create orchestrator + let (orchestrator, orchestrator_mailbox) = summit_orchestrator::Actor::new( + context.with_label("orchestrator"), + summit_orchestrator::Config { + oracle: cfg.oracle.clone(), + application: application_mailbox.clone(), + scheme_provider: scheme_provider.clone(), + syncer_mailbox: syncer_mailbox.clone(), + namespace: cfg.namespace.as_bytes().to_vec(), + muxer_size: cfg.mailbox_size, + mailbox_size: cfg.mailbox_size, + rate_limit: cfg.fetch_rate_per_peer, + blocks_per_epoch: BLOCKS_PER_EPOCH, + partition_prefix: cfg.partition_prefix.clone(), + }, + ); // create finalizer let (finalizer, finalizer_mailbox) = Finalizer::new( @@ -142,8 +204,9 @@ impl< db_prefix: cfg.partition_prefix.clone(), engine_client: cfg.engine_client, registry: registry.clone(), - oracle: cfg.oracle, - epoch_num_of_blocks: EPOCH_NUM_BLOCKS, + oracle: cfg.oracle.clone(), + orchestrator_mailbox, + epoch_num_of_blocks: BLOCKS_PER_EPOCH, validator_max_withdrawals_per_block: VALIDATOR_MAX_WITHDRAWALS_PER_BLOCK, validator_minimum_stake: VALIDATOR_MINIMUM_STAKE, validator_withdrawal_period: VALIDATOR_WITHDRAWAL_PERIOD, @@ -152,51 +215,26 @@ impl< genesis_hash: cfg.genesis_hash, initial_state: cfg.initial_state, protocol_version: PROTOCOL_VERSION, - public_key: cfg.signer.public_key(), + node_public_key: cfg.key_store.node_key.public_key().clone(), cancellation_token: cancellation_token.clone(), }, ) .await; - // create simplex - let simplex = Simplex::new( - context.with_label("simplex"), - simplex::Config { - crypto: cfg.signer, - automaton: application_mailbox.clone(), - relay: application_mailbox.clone(), - reporter: syncer_mailbox.clone(), - supervisor: registry, - partition: format!("{}-summit", cfg.partition_prefix), - mailbox_size: cfg.mailbox_size, - namespace: cfg.namespace.clone().as_bytes().to_vec(), - replay_buffer: REPLAY_BUFFER, - write_buffer: WRITE_BUFFER, - leader_timeout: cfg.leader_timeout, - notarization_timeout: cfg.notarization_timeout, - nullify_retry: cfg.nullify_retry, - activity_timeout: cfg.activity_timeout, - max_participants: 10_000, // todo(dalton): get rid of this magic number - skip_timeout: cfg.skip_timeout, - fetch_timeout: cfg.fetch_timeout, - max_fetch_count: cfg.max_fetch_count, - fetch_rate_per_peer: cfg.fetch_rate_per_peer, - fetch_concurrent: cfg.fetch_concurrent, - buffer_pool, - }, - ); - Self { context, application, + application_mailbox, buffer, buffer_mailbox, syncer, syncer_mailbox, - simplex, finalizer, finalizer_mailbox, orchestrator, + oracle: cfg.oracle, + node_public_key: cfg.key_store.node_key.public_key(), + mailbox_size: cfg.mailbox_size, sync_height, cancellation_token, } @@ -216,8 +254,8 @@ impl< impl Receiver, ), broadcast_network: ( - impl Sender, - impl Receiver, + impl Sender, + impl Receiver, ), backfill_network: ( impl Sender, @@ -248,8 +286,8 @@ impl< impl Receiver, ), broadcast_network: ( - impl Sender, - impl Receiver, + impl Sender, + impl Receiver, ), backfill_network: ( impl Sender, @@ -259,19 +297,36 @@ impl< // start the application let app_handle = self .application - .start(self.syncer_mailbox, self.finalizer_mailbox); + .start(self.syncer_mailbox, self.finalizer_mailbox.clone()); // start the buffer let buffer_handle = self.buffer.start(broadcast_network); - let (tx_finalizer_notify, rx_finalizer_notify) = mpsc::channel(2); - let finalizer_handle = - self.finalizer - .start(self.orchestrator, self.sync_height, rx_finalizer_notify); + + // Initialize resolver for backfill + let resolver_config = summit_syncer::resolver::p2p::Config { + public_key: self.node_public_key.clone(), + manager: self.oracle.clone(), + mailbox_size: self.mailbox_size, + requester_config: requester::Config { + me: Some(self.node_public_key.clone()), + rate_limit: Quota::per_second(NonZeroU32::new(5).unwrap()), + initial: Duration::from_secs(1), + timeout: Duration::from_secs(2), + }, + fetch_retry_timeout: Duration::from_millis(100), + priority_requests: false, + priority_responses: false, + }; + let (resolver_rx, resolver) = + summit_syncer::resolver::p2p::init(&self.context, resolver_config, backfill_network); + + let finalizer_handle = self.finalizer.start(self.sync_height); // start the syncer - let syncer_handle = - self.syncer - .start(self.buffer_mailbox, backfill_network, tx_finalizer_notify); - // start simplex - let simplex_handle = self.simplex.start(voter_network, resolver_network); + let syncer_handle = self.syncer.start( + self.finalizer_mailbox.clone(), + self.buffer_mailbox.clone(), + (resolver_rx, resolver), + self.sync_height, + ); // Wait for either all actors to finish or cancellation signal let actors_fut = try_join_all(vec![ @@ -279,7 +334,6 @@ impl< buffer_handle, finalizer_handle, syncer_handle, - simplex_handle, ]) .fuse(); let cancellation_fut = self.cancellation_token.cancelled().fuse(); From baba4ea5e962e6ac47625adc880c0d686b8963f0 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Fri, 7 Nov 2025 17:26:08 -0500 Subject: [PATCH 40/81] chore: fmt --- Cargo.lock | 261 ++++++++++++++------------ Cargo.toml | 28 +-- finalizer/src/lib.rs | 1 - node/Cargo.toml | 2 + node/src/args.rs | 150 +++++++-------- node/src/bin/stake_and_checkpoint.rs | 2 +- node/src/bin/testnet.rs | 2 +- node/src/bin/withdraw_and_exit.rs | 4 +- node/src/keys.rs | 17 +- node/src/test_harness/common.rs | 46 +++-- node/src/tests/checkpointing.rs | 197 ++++++++++++-------- node/src/tests/execution_requests.rs | 262 ++++++++++++++++----------- node/src/tests/syncer.rs | 82 +++++---- 13 files changed, 595 insertions(+), 459 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 211e4f8e..71c73aa7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -90,9 +90,9 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "1.0.30" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d213580c17d239ae83c0d897ac3315db7cda83d2d4936a9823cc3517552f2e24" +checksum = "b9b151e38e42f1586a01369ec52a6934702731d07e8509a7307331b09f6c46dc" dependencies = [ "alloy-eips", "alloy-primitives", @@ -109,6 +109,7 @@ dependencies = [ "rand 0.8.5", "secp256k1", "serde", + "serde_json", "serde_with", "thiserror 2.0.12", ] @@ -216,9 +217,9 @@ dependencies = [ [[package]] name = "alloy-eips" -version = "1.0.30" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a15b4b0f6bab47aae017d52bb5a739bda381553c09fb9918b7172721ef5f5de" +checksum = "e5434834adaf64fa20a6fb90877bc1d33214c41b055cc49f82189c98614368cc" dependencies = [ "alloy-eip2124", "alloy-eip2930", @@ -365,7 +366,7 @@ dependencies = [ "derive_more", "foldhash", "hashbrown 0.15.4", - "indexmap 2.10.0", + "indexmap 2.12.0", "itoa", "k256", "keccak-asm", @@ -556,9 +557,9 @@ dependencies = [ [[package]] name = "alloy-serde" -version = "1.0.30" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1b3b1078b8775077525bc9fe9f6577e815ceaecd6c412a4f3b4d8aa2836e8f6" +checksum = "64600fc6c312b7e0ba76f73a381059af044f4f21f43e07f51f1fa76c868fe302" dependencies = [ "alloy-primitives", "serde", @@ -620,7 +621,7 @@ dependencies = [ "alloy-sol-macro-input", "const-hex", "heck", - "indexmap 2.10.0", + "indexmap 2.12.0", "proc-macro-error2", "proc-macro2", "quote", @@ -750,11 +751,10 @@ dependencies = [ [[package]] name = "alloy-tx-macros" -version = "1.0.30" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b5becb9c269a7d05a2f28d549f86df5a5dbc923e2667eff84fdecac8cda534c" +checksum = "ab54221eccefa254ce9f65b079c097b1796e48c21c7ce358230f8988d75392fb" dependencies = [ - "alloy-primitives", "darling 0.21.3", "proc-macro2", "quote", @@ -1516,9 +1516,9 @@ checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "commonware-broadcast" -version = "0.0.62" +version = "0.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc71e670241b8b07840cbb01d0d9521ae68bc2195f620adaeb57f76c51584bd5" +checksum = "98d0d0909a8323c69cc0f5090cac4b2eb546f4cc29a60dc0dcfe238e75f79c19" dependencies = [ "bytes", "commonware-codec", @@ -1535,9 +1535,9 @@ dependencies = [ [[package]] name = "commonware-codec" -version = "0.0.62" +version = "0.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881d86d9cc88835dac1774701cfc296f8485acbbeb6c50d0c04246e066f3a169" +checksum = "d473c9be55b1143abebd3fa6a748fe9d35151df4614ea7f68b314e504559af08" dependencies = [ "bytes", "paste", @@ -1546,9 +1546,9 @@ dependencies = [ [[package]] name = "commonware-consensus" -version = "0.0.62" +version = "0.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f8ba91ccb78397634c478b1199a3d3ff20eaa5dc637a1a657450fa3eafbc0ae" +checksum = "82b3b1dd7e0596b23a50ef69a290d0ed4e187a3f16a6aa6f317af188cd8b2bb5" dependencies = [ "bytes", "cfg-if", @@ -1572,14 +1572,15 @@ dependencies = [ [[package]] name = "commonware-cryptography" -version = "0.0.62" +version = "0.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e97eba4685c332ae24a5842893f37c839371c33647645c314a124a7e4ee9ba60" +checksum = "e7157f6e4a84b7a70108f15bf402f539b48d52adf727b9938fe59f752efc5b3e" dependencies = [ "blake3", "blst", "bytes", "cfg-if", + "chacha20poly1305", "commonware-codec", "commonware-utils", "ed25519-consensus", @@ -1591,16 +1592,18 @@ dependencies = [ "rayon", "sha2 0.10.9", "thiserror 2.0.12", + "x25519-dalek", "zeroize", ] [[package]] name = "commonware-macros" -version = "0.0.62" +version = "0.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25989115bb59d92b1b7f79018792b31882dbe08e3ecaa6fd4ade5c4244f0d4e3" +checksum = "ff368ef4db2d10686c1a89b7f4a3f1e7dddd9641a96cac42b72bf71a10360291" dependencies = [ "futures", + "proc-macro-crate", "proc-macro2", "quote", "syn 1.0.109", @@ -1610,9 +1613,9 @@ dependencies = [ [[package]] name = "commonware-p2p" -version = "0.0.62" +version = "0.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e25f8905f151ae133e13866b208d485f4fb17121bf73a57f6587ffaaac2c9a0" +checksum = "657c7a971cf269411914e2a32a77815d5990ae111f2804d6b15f5952f75270c6" dependencies = [ "bytes", "commonware-codec", @@ -1624,6 +1627,10 @@ dependencies = [ "either", "futures", "governor", + "num-bigint", + "num-integer", + "num-rational", + "num-traits", "prometheus-client", "rand 0.8.5", "rand_distr", @@ -1633,9 +1640,9 @@ dependencies = [ [[package]] name = "commonware-resolver" -version = "0.0.62" +version = "0.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c778ccaea860de1fd11305cb51f2ef1de085eafd707adbf48a533afdd8742004" +checksum = "5e72ea84c5b43939cde251fba17627065d45cd9cedcb67f673c58291c5454e8f" dependencies = [ "bimap", "bytes", @@ -1656,9 +1663,9 @@ dependencies = [ [[package]] name = "commonware-runtime" -version = "0.0.62" +version = "0.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb9485b85b504ae6ae37c49a94050b1d3eafe222778e46d354ed0ca65259575" +checksum = "de4d08e6e11088ed5b42e5ad93b18ffd745cbcc04c6ef7f723f5d237e146abc8" dependencies = [ "async-lock", "axum 0.8.4", @@ -1688,11 +1695,12 @@ dependencies = [ [[package]] name = "commonware-storage" -version = "0.0.62" +version = "0.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ac3dfa058a662ce951500abebb865608afc68bfbde206d23a591b6aa3b235f9" +checksum = "b3116985d7a761aa7bf26d5226d51b8de0eaa6458277963f3c5d903f4078d504" dependencies = [ "bytes", + "cfg-if", "commonware-codec", "commonware-cryptography", "commonware-macros", @@ -1710,9 +1718,9 @@ dependencies = [ [[package]] name = "commonware-stream" -version = "0.0.62" +version = "0.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d7599a9b3b015b9eebe87a4cc572c223843eb281e06262ea13c92db5b29f9a5" +checksum = "260076055c2a5eb1b734641603a9bc6bcd439bd6525055480c7d149e2a8dad70" dependencies = [ "bytes", "chacha20poly1305", @@ -1722,8 +1730,8 @@ dependencies = [ "commonware-runtime", "commonware-utils", "futures", - "hkdf", "rand 0.8.5", + "rand_core 0.6.4", "thiserror 2.0.12", "x25519-dalek", "zeroize", @@ -1731,14 +1739,19 @@ dependencies = [ [[package]] name = "commonware-utils" -version = "0.0.62" +version = "0.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b052e7cbeed6ba05dee34b82434dd4e76ed5dd3b1c4585eafab08233e4033f9" +checksum = "209c03e7057e9d4d5f0bade24685e2bc8845471b89e4ab54684f1af8c287ad3b" dependencies = [ "bytes", + "cfg-if", "commonware-codec", "futures", "getrandom 0.2.16", + "num-bigint", + "num-integer", + "num-rational", + "num-traits", "rand 0.8.5", "thiserror 2.0.12", ] @@ -2352,7 +2365,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.52.0", ] [[package]] @@ -2728,7 +2741,7 @@ dependencies = [ "futures-core", "futures-sink", "http", - "indexmap 2.10.0", + "indexmap 2.12.0", "slab", "tokio", "tokio-util", @@ -2769,6 +2782,12 @@ dependencies = [ "serde", ] +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" + [[package]] name = "hdrhistogram" version = "7.5.4" @@ -2812,15 +2831,6 @@ dependencies = [ "arrayvec", ] -[[package]] -name = "hkdf" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" -dependencies = [ - "hmac", -] - [[package]] name = "hmac" version = "0.12.1" @@ -2987,7 +2997,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core 0.61.2", + "windows-core 0.57.0", ] [[package]] @@ -3151,13 +3161,14 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.10.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" dependencies = [ "equivalent", - "hashbrown 0.15.4", + "hashbrown 0.16.0", "serde", + "serde_core", ] [[package]] @@ -3219,7 +3230,7 @@ checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -3412,7 +3423,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.53.2", + "windows-targets 0.48.5", ] [[package]] @@ -3567,7 +3578,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd7399781913e5393588a8d8c6a2867bf85fb38eaf2502fdce465aad2dc6f034" dependencies = [ "base64 0.22.1", - "indexmap 2.10.0", + "indexmap 2.12.0", "metrics", "metrics-util", "quanta", @@ -3721,6 +3732,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -4259,9 +4281,9 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" dependencies = [ "toml_edit", ] @@ -4505,7 +4527,7 @@ dependencies = [ "once_cell", "socket2 0.6.0", "tracing", - "windows-sys 0.60.2", + "windows-sys 0.52.0", ] [[package]] @@ -4954,7 +4976,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.4.15", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -4967,7 +4989,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.9.4", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -5162,18 +5184,28 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.219" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -5233,7 +5265,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.10.0", + "indexmap 2.12.0", "schemars 0.9.0", "schemars 1.0.4", "serde", @@ -5550,6 +5582,7 @@ dependencies = [ "socket2 0.6.0", "summit-application", "summit-finalizer", + "summit-orchestrator", "summit-rpc", "summit-syncer", "summit-types", @@ -5560,6 +5593,7 @@ dependencies = [ "tower 0.5.2", "tracing", "tracing-subscriber", + "zeroize", ] [[package]] @@ -5601,15 +5635,41 @@ dependencies = [ "commonware-codec", "commonware-consensus", "commonware-cryptography", - "commonware-resolver", + "commonware-p2p", "commonware-runtime", "commonware-storage", "commonware-utils", "futures", "governor", + "hex", "metrics", "prometheus-client", "rand 0.8.5", + "summit-orchestrator", + "summit-syncer", + "summit-types", + "tokio-util", + "tracing", +] + +[[package]] +name = "summit-orchestrator" +version = "0.0.0" +dependencies = [ + "bytes", + "commonware-broadcast", + "commonware-codec", + "commonware-consensus", + "commonware-cryptography", + "commonware-macros", + "commonware-p2p", + "commonware-resolver", + "commonware-runtime", + "commonware-storage", + "commonware-utils", + "futures", + "governor", + "rand 0.8.5", "summit-syncer", "summit-types", "tokio-util", @@ -5623,6 +5683,7 @@ dependencies = [ "anyhow", "axum 0.8.4", "commonware-codec", + "commonware-consensus", "commonware-cryptography", "commonware-runtime", "commonware-utils", @@ -5659,6 +5720,7 @@ dependencies = [ "summit-types", "tokio-util", "tracing", + "tracing-subscriber", ] [[package]] @@ -5693,6 +5755,7 @@ dependencies = [ "toml", "tracing", "url", + "zeroize", ] [[package]] @@ -5800,7 +5863,7 @@ dependencies = [ "getrandom 0.3.3", "once_cell", "rustix 1.0.7", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -6041,10 +6104,10 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed0aee96c12fa71097902e0bb061a5e1ebd766a6636bb605ba401c45c1650eac" dependencies = [ - "indexmap 2.10.0", + "indexmap 2.12.0", "serde", "serde_spanned", - "toml_datetime 0.7.0", + "toml_datetime", "toml_parser", "toml_writer", "winnow", @@ -6052,35 +6115,30 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" - -[[package]] -name = "toml_datetime" -version = "0.7.0" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bade1c3e902f58d73d3f294cd7f20391c1cb2fbcb643b73566bc773971df91e3" +checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" dependencies = [ - "serde", + "serde_core", ] [[package]] name = "toml_edit" -version = "0.22.27" +version = "0.23.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d" dependencies = [ - "indexmap 2.10.0", - "toml_datetime 0.6.11", + "indexmap 2.12.0", + "toml_datetime", + "toml_parser", "winnow", ] [[package]] name = "toml_parser" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97200572db069e74c512a14117b296ba0a80a30123fbbb5aa1f4a348f639ca30" +checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" dependencies = [ "winnow", ] @@ -6580,7 +6638,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.48.0", ] [[package]] @@ -6634,19 +6692,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-core" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" -dependencies = [ - "windows-implement 0.60.0", - "windows-interface 0.59.1", - "windows-link", - "windows-result 0.3.4", - "windows-strings 0.4.2", -] - [[package]] name = "windows-implement" version = "0.57.0" @@ -6669,17 +6714,6 @@ dependencies = [ "syn 2.0.104", ] -[[package]] -name = "windows-implement" -version = "0.60.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.104", -] - [[package]] name = "windows-interface" version = "0.57.0" @@ -6702,17 +6736,6 @@ dependencies = [ "syn 2.0.104", ] -[[package]] -name = "windows-interface" -version = "0.59.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.104", -] - [[package]] name = "windows-link" version = "0.1.3" @@ -6999,9 +7022,9 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] name = "winnow" -version = "0.7.11" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" dependencies = [ "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index 759bef28..c2c2f88c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = [ "application", "node", "rpc", "types", "syncer", "finalizer"] +members = [ "application", "node", "rpc", "types", "finalizer", "orchestrator", "syncer"] resolver = "3" [workspace.package] @@ -10,20 +10,22 @@ edition = "2024" # Our crates summit-types = { path = "types" } summit-application = { path = "application" } -summit-syncer = {path = "syncer"} +summit-syncer = {path = "syncer" } +summit-syncer-old = {path = "syncer_old" } summit-finalizer = {path = "finalizer"} summit-rpc = {path = "rpc"} +summit-orchestrator = {path = "orchestrator"} -commonware-consensus = "0.0.62" -commonware-cryptography = "0.0.62" -commonware-storage = "0.0.62" -commonware-runtime = "0.0.62" -commonware-codec = "0.0.62" -commonware-p2p = "0.0.62" -commonware-broadcast = "0.0.62" -commonware-utils = "0.0.62" -commonware-resolver = "0.0.62" -commonware-macros = "0.0.62" +commonware-consensus = "0.0.63" +commonware-cryptography = "0.0.63" +commonware-storage = "0.0.63" +commonware-runtime = "0.0.63" +commonware-codec = "0.0.63" +commonware-p2p = "0.0.63" +commonware-broadcast = "0.0.63" +commonware-utils = "0.0.63" +commonware-resolver = "0.0.63" +commonware-macros = "0.0.63" alloy-consensus = "1.0.12" alloy-eips = { version = "1.0.19", features = ["ssz"] } @@ -46,6 +48,7 @@ url = "2.5" futures = "0.3.31" http = "1.0" +hex = "0.4" http-body-util = "0.1.3" reqwest = "0.12" socket2 = "0.6" @@ -59,6 +62,7 @@ ethereum_ssz_derive = "0.9.0" serde = { version = "1.0.219", features = ["derive"] } serde_json = "1.0.140" toml = "0.9" +zeroize = "1.8" anyhow = "1.0.98" eyre = "0.6" diff --git a/finalizer/src/lib.rs b/finalizer/src/lib.rs index 3fed91d7..d92c2416 100644 --- a/finalizer/src/lib.rs +++ b/finalizer/src/lib.rs @@ -3,5 +3,4 @@ pub use ingress::*; pub mod config; pub use config::*; pub mod actor; -//pub mod block_fetcher; pub mod db; diff --git a/node/Cargo.toml b/node/Cargo.toml index fbea0f93..1f5a6b00 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -37,6 +37,7 @@ summit-application = { workspace = true, features = [] } summit-rpc.workspace = true summit-syncer.workspace = true summit-finalizer.workspace = true +summit-orchestrator.workspace = true commonware-broadcast.workspace = true commonware-codec.workspace = true @@ -75,6 +76,7 @@ serde.workspace = true serde_json.workspace = true toml.workspace = true +zeroize.workspace = true futures.workspace = true governor.workspace = true http = { workspace = true, optional = true } diff --git a/node/src/args.rs b/node/src/args.rs index 29a8a294..7402a2c5 100644 --- a/node/src/args.rs +++ b/node/src/args.rs @@ -7,16 +7,17 @@ use crate::{ keys::KeySubCmd, }; use clap::{Args, Parser, Subcommand}; -use commonware_cryptography::Signer; -use commonware_p2p::authenticated; +use commonware_cryptography::{Signer, bls12381, ed25519}; +use commonware_p2p::{Manager, authenticated}; use commonware_runtime::{Handle, Metrics as _, Runner, Spawner as _, tokio}; use summit_rpc::{PathSender, start_rpc_server, start_rpc_server_for_genesis}; use tokio_util::sync::CancellationToken; use alloy_primitives::{Address, B256}; use alloy_rpc_types_engine::ForkchoiceState; -use commonware_codec::ReadExt; +use commonware_codec::{DecodeExt, ReadExt}; use commonware_utils::from_hex_formatted; +use commonware_utils::set::Ordered; use futures::{channel::oneshot, future::try_join_all}; use governor::Quota; use ssz::Decode; @@ -38,8 +39,9 @@ use summit_types::RethEngineClient; use summit_types::account::{ValidatorAccount, ValidatorStatus}; use summit_types::checkpoint::Checkpoint; use summit_types::consensus_state::ConsensusState; +use summit_types::keystore::KeyStore; use summit_types::network_oracle::DiscoveryOracle; -use summit_types::{Genesis, PublicKey, utils::get_expanded_path}; +use summit_types::{Genesis, PrivateKey, PublicKey, Validator, utils::get_expanded_path}; use tracing::{Level, error}; pub const DEFAULT_KEY_PATH: &str = "~/.seismic/consensus/key.pem"; @@ -74,7 +76,7 @@ pub enum Command { #[derive(Args, Debug, Clone)] pub struct RunFlags { /// Path to your keystore directory containing node_key.pem and consensus_key.pem - #[arg(long, default_value_t = "~/.seismic/consensus/keys".into())] + #[arg(long, default_value_t = String::from("~/.seismic/consensus/keys"))] pub key_store_path: String, /// Path to the folder we will keep the consensus DB #[arg(long, default_value_t = DEFAULT_DB_FOLDER.into())] @@ -174,7 +176,7 @@ impl Command { let store_path = get_expanded_path(&flags.store_path).expect("Invalid store path"); let key_store = expect_key_store(&flags.key_store_path); - let signer = key_store.node_key; + let signer = key_store.node_key.clone(); // Initialize runtime let cfg = tokio::Config::default() @@ -212,28 +214,16 @@ impl Command { let genesis = Genesis::load_from_file(&flags.genesis_path).expect("Can not find genesis file"); - let mut committee: Vec<(PublicKey, SocketAddr, Address)> = genesis - .validators - .iter() - .map(|v| v.try_into().expect("Invalid validator in genesis")) - .collect(); - committee.sort(); + let mut committee: Vec = + genesis.get_validators().expect("Failed to get validators"); + committee.sort_by(|lhs, rhs| lhs.node_public_key.cmp(&rhs.node_public_key)); let genesis_hash: [u8; 32] = from_hex_formatted(&genesis.eth_genesis_hash) .map(|hash_bytes| hash_bytes.try_into()) .expect("bad eth_genesis_hash") .expect("bad eth_genesis_hash"); let initial_state = get_initial_state(genesis_hash, &committee, maybe_checkpoint); - let mut peers: Vec = initial_state - .validator_accounts - .iter() - .filter(|(_, acc)| !(acc.status == ValidatorStatus::Inactive)) - .map(|(v, _)| { - let mut key_bytes = &v[..]; - PublicKey::read(&mut key_bytes).expect("failed to parse public key") - }) - .collect(); - peers.sort(); + let peers = initial_state.get_validator_keys(); let engine_ipc_path = get_expanded_path(&flags.engine_ipc_path) .expect("failed to expand engine ipc path"); @@ -272,27 +262,13 @@ impl Command { let engine_client = RethEngineClient::new(engine_ipc_path.to_string_lossy().to_string()).await; - let our_ip = if let Some(ref ip_str) = flags.ip { - ip_str - .parse::() - .expect("Invalid IP address format") - } else { - committee - .iter() - .find_map(|v| { - if v.0 == signer.public_key() { - Some(v.1) - } else { - None - } - }) - .expect("This node is not on the committee") - }; + let our_ip = get_node_ip(&flags, &key_store, &committee); let mut network_committee: Vec<(PublicKey, SocketAddr)> = committee .into_iter() - .map(|(key, ip, _)| (key, ip)) + .map(|v| (v.node_public_key, v.ip_address)) .collect(); + let our_public_key = signer.public_key(); if !network_committee .iter() @@ -352,7 +328,10 @@ impl Command { // Provide authorized peers oracle - .register(initial_state.latest_height, peers.clone()) + .update( + initial_state.latest_height, + Ordered::from_iter(peers.iter().map(|(node_key, _)| node_key.clone())), + ) .await; let oracle = DiscoveryOracle::new(oracle); @@ -386,7 +365,8 @@ impl Command { // Create network let p2p = network.start(); // create engine - let engine = Engine::new(context.with_label("engine"), config).await; + let engine: Engine<_, _, _, _, bls12381::primitives::variant::MinPk> = + Engine::new(context.with_label("engine"), config).await; let finalizer_mailbox = engine.finalizer_mailbox.clone(); @@ -420,7 +400,6 @@ pub fn run_node_with_runtime( ) -> Handle<()> { context.spawn(async move |context| { let key_store = expect_key_store(&flags.key_store_path); - let signer = key_store.node_key; let (genesis_tx, genesis_rx) = oneshot::channel(); @@ -448,28 +427,16 @@ pub fn run_node_with_runtime( let genesis = Genesis::load_from_file(&flags.genesis_path).expect("Can not find genesis file"); - let mut committee: Vec<(PublicKey, SocketAddr, Address)> = genesis - .validators - .iter() - .map(|v| v.try_into().expect("Invalid validator in genesis")) - .collect(); - committee.sort(); + let mut committee: Vec = + genesis.get_validators().expect("Failed to get validators"); + committee.sort_by(|lhs, rhs| lhs.node_public_key.cmp(&rhs.node_public_key)); let genesis_hash: [u8; 32] = from_hex_formatted(&genesis.eth_genesis_hash) .map(|hash_bytes| hash_bytes.try_into()) .expect("bad eth_genesis_hash") .expect("bad eth_genesis_hash"); let initial_state = get_initial_state(genesis_hash, &committee, checkpoint); - let mut peers: Vec = initial_state - .validator_accounts - .iter() - .filter(|(_, acc)| !(acc.status == ValidatorStatus::Inactive)) - .map(|(v, _)| { - let mut key_bytes = &v[..]; - PublicKey::read(&mut key_bytes).expect("failed to parse public key") - }) - .collect(); - peers.sort(); + let peers = initial_state.get_validator_keys(); let engine_ipc_path = get_expanded_path(&flags.engine_ipc_path).expect("failed to expand engine ipc path"); @@ -505,28 +472,13 @@ pub fn run_node_with_runtime( let engine_client = RethEngineClient::new(engine_ipc_path.to_string_lossy().to_string()).await; - let our_ip = if let Some(ref ip_str) = flags.ip { - ip_str - .parse::() - .expect("Invalid IP address format") - } else { - committee - .iter() - .find_map(|v| { - if v.0 == signer.public_key() { - Some(v.1) - } else { - None - } - }) - .expect("This node is not on the committee") - }; + let our_ip = get_node_ip(&flags, &key_store, &committee); let mut network_committee: Vec<(PublicKey, SocketAddr)> = committee .into_iter() - .map(|(key, ip, _)| (key, ip)) + .map(|v| (v.node_public_key, v.ip_address)) .collect(); - let our_public_key = signer.public_key(); + let our_public_key = key_store.node_key.public_key(); if !network_committee .iter() .any(|(key, _)| key == &our_public_key) @@ -538,7 +490,7 @@ pub fn run_node_with_runtime( // configure network #[cfg(feature = "e2e")] let mut p2p_cfg = authenticated::discovery::Config::aggressive( - signer.clone(), + key_store.node_key.clone(), genesis.namespace.as_bytes(), SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), flags.port), our_ip, @@ -547,7 +499,7 @@ pub fn run_node_with_runtime( ); #[cfg(not(feature = "e2e"))] let mut p2p_cfg = authenticated::discovery::Config::recommended( - signer.clone(), + key_store.node_key.clone(), genesis.namespace.as_bytes(), SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), flags.port), our_ip, @@ -562,7 +514,10 @@ pub fn run_node_with_runtime( // Provide authorized peers oracle - .register(initial_state.latest_height, peers.clone()) + .update( + initial_state.latest_height, + Ordered::from_iter(peers.iter().map(|(node_key, _)| node_key.clone())), + ) .await; let oracle = DiscoveryOracle::new(oracle); @@ -596,7 +551,8 @@ pub fn run_node_with_runtime( // Create network let p2p = network.start(); // create engine - let engine = Engine::new(context.with_label("engine"), config).await; + let engine: Engine<_, _, _, _, bls12381::primitives::variant::MinPk> = + Engine::new(context.with_label("engine"), config).await; let finalizer_mailbox = engine.finalizer_mailbox.clone(); // Start engine @@ -642,7 +598,7 @@ pub fn run_node_with_runtime( fn get_initial_state( genesis_hash: [u8; 32], - genesis_committee: &Vec<(PublicKey, SocketAddr, Address)>, + genesis_committee: &Vec, checkpoint: Option, ) -> ConsensusState { let genesis_hash: B256 = genesis_hash.into(); @@ -654,14 +610,15 @@ fn get_initial_state( }; let mut state = ConsensusState::new(forkchoice); // Add the genesis nodes to the consensus state with the minimum stake balance. - for (pubkey, _, address) in genesis_committee { - let pubkey_bytes: [u8; 32] = pubkey + for validator in genesis_committee { + let pubkey_bytes: [u8; 32] = validator + .node_public_key .as_ref() .try_into() .expect("Public key must be 32 bytes"); let account = ValidatorAccount { - // TODO(matthias): we have to add a withdrawal address to the genesis - withdrawal_credentials: *address, + consensus_public_key: validator.consensus_public_key.clone(), + withdrawal_credentials: validator.withdrawal_credentials.clone(), balance: VALIDATOR_MINIMUM_STAKE, pending_withdrawal_amount: 0, status: ValidatorStatus::Active, @@ -677,3 +634,26 @@ fn get_initial_state( state }) } + +fn get_node_ip( + flags: &RunFlags, + key_store: &KeyStore, + committee: &Vec, +) -> SocketAddr { + if let Some(ref ip_str) = flags.ip { + ip_str + .parse::() + .expect("Invalid IP address format") + } else { + committee + .iter() + .find_map(|v| { + if v.node_public_key == key_store.node_key.public_key() { + Some(v.ip_address) + } else { + None + } + }) + .expect("This node is not on the committee") + } +} diff --git a/node/src/bin/stake_and_checkpoint.rs b/node/src/bin/stake_and_checkpoint.rs index 3e951e49..840e525d 100644 --- a/node/src/bin/stake_and_checkpoint.rs +++ b/node/src/bin/stake_and_checkpoint.rs @@ -798,7 +798,7 @@ fn get_node_flags(node: usize) -> RunFlags { let path = format!("testnet/node{node}/"); RunFlags { - key_path: format!("{path}key.pem"), + key_store_path: format!("{path}keys"), store_path: format!("{path}db"), port: (26600 + (node * 10)) as u16, prom_port: (28600 + (node * 10)) as u16, diff --git a/node/src/bin/testnet.rs b/node/src/bin/testnet.rs index 8351f6b7..5a6fb985 100644 --- a/node/src/bin/testnet.rs +++ b/node/src/bin/testnet.rs @@ -193,7 +193,7 @@ fn get_node_flags(node: usize) -> RunFlags { let path = format!("testnet/node{node}/"); RunFlags { - key_path: format!("{path}key.pem"), + key_store_path: format!("{path}keys"), store_path: format!("{path}db"), port: (26600 + (node * 10)) as u16, prom_port: (28600 + (node * 10)) as u16, diff --git a/node/src/bin/withdraw_and_exit.rs b/node/src/bin/withdraw_and_exit.rs index e64e1896..29186f38 100644 --- a/node/src/bin/withdraw_and_exit.rs +++ b/node/src/bin/withdraw_and_exit.rs @@ -30,7 +30,7 @@ use std::{ thread::JoinHandle, }; use summit::args::{RunFlags, run_node_with_runtime}; -use summit::engine::{EPOCH_NUM_BLOCKS, VALIDATOR_MINIMUM_STAKE}; +use summit::engine::{BLOCKS_PER_EPOCH, VALIDATOR_MINIMUM_STAKE}; use summit_types::PublicKey; use summit_types::reth::Reth; use tokio::sync::mpsc; @@ -238,7 +238,7 @@ fn main() -> Result<(), Box> { .expect("failed to send deposit transaction"); // Wait for all nodes to continue making progress - let epoch_end = EPOCH_NUM_BLOCKS; + let epoch_end = BLOCKS_PER_EPOCH; println!( "Waiting for all {} nodes to reach height {}", NUM_NODES, epoch_end diff --git a/node/src/keys.rs b/node/src/keys.rs index 534d1e10..0c574aaa 100644 --- a/node/src/keys.rs +++ b/node/src/keys.rs @@ -1,11 +1,11 @@ use crate::args::DEFAULT_KEY_PATH; use anyhow::{Context as _, Result}; use clap::{Args, Subcommand}; -use commonware_codec::{extensions::DecodeExt, Encode}; +use commonware_codec::{Encode, extensions::DecodeExt}; use std::io::{self, Write}; -use commonware_cryptography::{PrivateKeyExt as _, Signer}; use commonware_cryptography::bls12381::PrivateKey as BlsPrivateKey; +use commonware_cryptography::{PrivateKeyExt as _, Signer}; use commonware_utils::from_hex_formatted; use summit_types::{PrivateKey, utils::get_expanded_path}; @@ -30,7 +30,7 @@ pub enum KeySubCmd { #[derive(Args, Debug, Clone, PartialEq, Eq)] pub struct KeyFlags { /// Path to your keystore directory containing node_key.pem and consensus_key.pem - #[arg(long, default_value_t = "~/.seismic/consensus/keys".into())] + #[arg(long, default_value_t = String::from("~/.seismic/consensus/keys"))] pub key_store_path: String, #[arg(short = 'n', long, conflicts_with = "yes_overwrite")] pub no_overwrite: bool, @@ -96,15 +96,13 @@ impl KeySubCmd { } // Create keystore directory - std::fs::create_dir_all(&keystore_dir) - .expect("Unable to create keystore directory"); + std::fs::create_dir_all(&keystore_dir).expect("Unable to create keystore directory"); // Generate ed25519 node key let node_private_key = PrivateKey::from_rng(&mut rand::thread_rng()); let node_pub_key = node_private_key.public_key(); let encoded_node_key = node_private_key.to_string(); - std::fs::write(&node_key_path, encoded_node_key) - .expect("Unable to write node key to disk"); + std::fs::write(&node_key_path, encoded_node_key).expect("Unable to write node key to disk"); // Generate BLS consensus key let consensus_private_key = BlsPrivateKey::from_rng(&mut rand::thread_rng()); @@ -123,12 +121,11 @@ impl KeySubCmd { let node_key_path = keystore_dir.join(NODE_KEY_FILENAME); let consensus_key_path = keystore_dir.join(CONSENSUS_KEY_FILENAME); - let node_pk = read_ed_key_from_file(&node_key_path) - .expect("Unable to read node key from disk"); + let node_pk = + read_ed_key_from_file(&node_key_path).expect("Unable to read node key from disk"); let consensus_pk = read_bls_key_from_file(&consensus_key_path) .expect("Unable to read consensus key from disk"); - println!("Node Public Key (ed25519): {}", node_pk.public_key()); println!("Consensus Public Key (BLS): {}", consensus_pk.public_key()); } diff --git a/node/src/test_harness/common.rs b/node/src/test_harness/common.rs index 35dd87c1..5869a2ce 100644 --- a/node/src/test_harness/common.rs +++ b/node/src/test_harness/common.rs @@ -1,4 +1,4 @@ -use commonware_cryptography::{Hasher, PrivateKeyExt, Sha256, Signer}; +use commonware_cryptography::{Hasher, PrivateKeyExt, Sha256, Signer, bls12381}; use crate::engine::{PROTOCOL_VERSION, VALIDATOR_MINIMUM_STAKE}; use crate::test_harness::mock_engine_client::MockEngineNetwork; @@ -7,6 +7,7 @@ use alloy_eips::eip7685::Requests; use alloy_primitives::{Address, B256, Bytes}; use alloy_rpc_types_engine::ForkchoiceState; use commonware_codec::Write; +use commonware_cryptography::bls12381::primitives::variant::Variant; use commonware_p2p::simulated::{self, Link, Network, Oracle, Receiver, Sender}; use commonware_runtime::{ Clock, Metrics, Runner as _, @@ -22,6 +23,7 @@ use std::{ use summit_types::account::{ValidatorAccount, ValidatorStatus}; use summit_types::consensus_state::ConsensusState; use summit_types::execution_request::{DepositRequest, ExecutionRequest, WithdrawalRequest}; +use summit_types::keystore::KeyStore; use summit_types::network_oracle::NetworkOracle; use summit_types::{Digest, EngineClient, PrivateKey, PublicKey}; @@ -131,6 +133,8 @@ pub fn run_until_height( context.with_label("network"), simulated::Config { max_size: 1024 * 1024, + disconnect_on_block: true, + tracked_peer_sets: Some(n as usize * 2), }, ); @@ -138,16 +142,24 @@ pub fn run_until_height( network.start(); // Register participants - let mut signers = Vec::new(); + let mut key_stores = Vec::new(); let mut validators = Vec::new(); for i in 0..n { - let signer = PrivateKey::from_seed(i as u64); - let pk = signer.public_key(); - signers.push(signer); - validators.push(pk); + let node_key = PrivateKey::from_seed(i as u64); + let node_public_key = node_key.public_key(); + let consensus_key = bls12381::PrivateKey::from_seed(i as u64); + let consensus_public_key = consensus_key.public_key(); + let key_store = KeyStore { + node_key, + consensus_key, + }; + key_stores.push(key_store); + validators.push((node_public_key, consensus_public_key)); } - validators.sort(); - signers.sort_by_key(|s| s.public_key()); + validators.sort_by_key(|lhs, rhs| lhs.0.cmp(&rhs.0)); + key_stores + .sort_by_key(|lhs, rhs| lhs.node_key.public_key().cmp(&rhs.node_key.public_key())); + let mut registrations = register_validators(&mut oracle, &validators).await; // Link all validators @@ -170,9 +182,9 @@ pub fn run_until_height( // Create instances let mut public_keys = HashSet::new(); let mut consensus_state_queries = HashMap::new(); - for (idx, signer) in signers.into_iter().enumerate() { + for (idx, key_store) in key_stores.into_iter().enumerate() { // Create signer context - let public_key = signer.public_key(); + let public_key = key_store.node_key.public_key(); public_keys.insert(public_key.clone()); // Configure engine @@ -187,7 +199,7 @@ pub fn run_until_height( uid.clone(), genesis_hash, namespace, - signer, + key_store, validators.clone(), initial_state.clone(), ); @@ -462,23 +474,25 @@ pub fn execution_requests_to_requests(execution_requests: Vec) /// /// # Returns /// * `EngineConfig` - A fully configured engine config with sensible defaults for testing -pub fn get_default_engine_config>( +pub fn get_default_engine_config>( engine_client: C, oracle: O, partition_prefix: String, genesis_hash: [u8; 32], namespace: String, - signer: PrivateKey, - participants: Vec, + key_store: KeyStore, + participants: Vec<(PublicKey, bls12381::PublicKey)>, initial_state: ConsensusState, -) -> EngineConfig { +) -> EngineConfig { + // For tests, generate a dummy BLS key + EngineConfig { engine_client, oracle, partition_prefix, genesis_hash, namespace, - signer, + key_store, participants, mailbox_size: 1024, deque_size: 10, diff --git a/node/src/tests/checkpointing.rs b/node/src/tests/checkpointing.rs index dbdffabf..3bc489a8 100644 --- a/node/src/tests/checkpointing.rs +++ b/node/src/tests/checkpointing.rs @@ -1,7 +1,8 @@ -use crate::engine::{EPOCH_NUM_BLOCKS, Engine, VALIDATOR_MINIMUM_STAKE}; +use crate::engine::{BLOCKS_PER_EPOCH, Engine, VALIDATOR_MINIMUM_STAKE}; use crate::test_harness::common; use crate::test_harness::common::{DummyOracle, get_default_engine_config, get_initial_state}; use crate::test_harness::mock_engine_client::MockEngineNetworkBuilder; +use commonware_cryptography::bls12381; use commonware_cryptography::{PrivateKeyExt, Signer}; use commonware_macros::test_traced; use commonware_p2p::simulated; @@ -13,6 +14,7 @@ use std::collections::{HashMap, HashSet}; use std::time::Duration; use summit_types::PrivateKey; use summit_types::consensus_state::ConsensusState; +use summit_types::keystore::KeyStore; #[test_traced("INFO")] fn test_checkpoint_created() { @@ -38,20 +40,28 @@ fn test_checkpoint_created() { // Start network network.start(); // Register participants - let mut signers = Vec::new(); + let mut key_stores = Vec::new(); let mut validators = Vec::new(); for i in 0..n { - let signer = PrivateKey::from_seed(i as u64); - let pk = signer.public_key(); - signers.push(signer); - validators.push(pk); + let node_key = PrivateKey::from_seed(i as u64); + let node_public_key = node_key.public_key(); + let consensus_key = bls12381::PrivateKey::from_seed(i as u64); + let consensus_public_key = consensus_key.public_key(); + let key_store = KeyStore { + node_key, + consensus_key, + }; + key_stores.push(key_store); + validators.push((node_public_key, consensus_public_key)); } - validators.sort(); - signers.sort_by_key(|s| s.public_key()); - let mut registrations = common::register_validators(&mut oracle, &validators).await; + validators.sort_by_key(|(lhs, _)| *lhs); + key_stores.sort_by_key(|ks| ks.node_key.public_key()); + + let node_public_keys: Vec<_> = validators.iter().map(|(pk, _)| pk.clone()).collect(); + let mut registrations = common::register_validators(&mut oracle, &node_public_keys).await; // Link all validators - common::link_validators(&mut oracle, &validators, link, None).await; + common::link_validators(&mut oracle, &node_public_keys, link, None).await; // Create the engine clients let genesis_hash = from_hex_formatted(common::GENESIS_HASH).expect("failed to decode genesis hash"); @@ -59,7 +69,7 @@ fn test_checkpoint_created() { .try_into() .expect("failed to convert genesis hash"); - let stop_height = EPOCH_NUM_BLOCKS + 1; + let stop_height = BLOCKS_PER_EPOCH + 1; let engine_client_network = MockEngineNetworkBuilder::new(genesis_hash).build(); let initial_state = get_initial_state( @@ -73,9 +83,9 @@ fn test_checkpoint_created() { // Create instances let mut public_keys = HashSet::new(); let mut consensus_state_queries = HashMap::new(); - for (idx, signer) in signers.into_iter().enumerate() { + for (idx, key_store) in key_stores.into_iter().enumerate() { // Create signer context - let public_key = signer.public_key(); + let public_key = key_store.node_key.public_key(); public_keys.insert(public_key.clone()); // Configure engine @@ -90,7 +100,7 @@ fn test_checkpoint_created() { uid.clone(), genesis_hash, namespace, - signer, + key_store, validators.clone(), initial_state.clone(), ); @@ -131,13 +141,13 @@ fn test_checkpoint_created() { if metric.ends_with("consensus_state_stored") { let height = value.parse::().unwrap(); - assert_eq!(height, EPOCH_NUM_BLOCKS); + assert_eq!(height, BLOCKS_PER_EPOCH); state_stored.insert(metric.to_string()); } if metric.ends_with("finalized_header_stored") { let height = value.parse::().unwrap(); - assert_eq!(height, EPOCH_NUM_BLOCKS); + assert_eq!(height, BLOCKS_PER_EPOCH); header_stored.insert(metric.to_string()); } if header_stored.len() as u32 >= n && state_stored.len() as u32 == n { @@ -198,20 +208,28 @@ fn test_previous_header_hash_matches() { // Start network network.start(); // Register participants - let mut signers = Vec::new(); + let mut key_stores = Vec::new(); let mut validators = Vec::new(); for i in 0..n { - let signer = PrivateKey::from_seed(i as u64); - let pk = signer.public_key(); - signers.push(signer); - validators.push(pk); + let node_key = PrivateKey::from_seed(i as u64); + let node_public_key = node_key.public_key(); + let consensus_key = bls12381::PrivateKey::from_seed(i as u64); + let consensus_public_key = consensus_key.public_key(); + let key_store = KeyStore { + node_key, + consensus_key, + }; + key_stores.push(key_store); + validators.push((node_public_key, consensus_public_key)); } - validators.sort(); - signers.sort_by_key(|s| s.public_key()); - let mut registrations = common::register_validators(&mut oracle, &validators).await; + validators.sort_by_key(|(lhs, _)| *lhs); + key_stores.sort_by_key(|ks| ks.node_key.public_key()); + + let node_public_keys: Vec<_> = validators.iter().map(|(pk, _)| pk.clone()).collect(); + let mut registrations = common::register_validators(&mut oracle, &node_public_keys).await; // Link all validators - common::link_validators(&mut oracle, &validators, link, None).await; + common::link_validators(&mut oracle, &node_public_keys, link, None).await; // Create the engine clients let genesis_hash = from_hex_formatted(common::GENESIS_HASH).expect("failed to decode genesis hash"); @@ -219,7 +237,7 @@ fn test_previous_header_hash_matches() { .try_into() .expect("failed to convert genesis hash"); - let stop_height = EPOCH_NUM_BLOCKS + 1; + let stop_height = BLOCKS_PER_EPOCH + 1; let engine_client_network = MockEngineNetworkBuilder::new(genesis_hash).build(); let initial_state = get_initial_state( @@ -233,9 +251,9 @@ fn test_previous_header_hash_matches() { // Create instances let mut public_keys = HashSet::new(); let mut consensus_state_queries = HashMap::new(); - for (idx, signer) in signers.into_iter().enumerate() { + for (idx, key_store) in key_stores.into_iter().enumerate() { // Create signer context - let public_key = signer.public_key(); + let public_key = key_store.node_key.public_key(); public_keys.insert(public_key.clone()); // Configure engine @@ -250,7 +268,7 @@ fn test_previous_header_hash_matches() { uid.clone(), genesis_hash, namespace, - signer, + key_store, validators.clone(), initial_state.clone(), ); @@ -298,10 +316,10 @@ fn test_previous_header_hash_matches() { let validator_id = common::extract_validator_id(metric).expect("failed to parse validator id"); - if height == EPOCH_NUM_BLOCKS { + if height == BLOCKS_PER_EPOCH { // This is the first time the finalized header is written to disk first_header_stored.insert(validator_id, header); - } else if height == 2 * EPOCH_NUM_BLOCKS { + } else if height == 2 * BLOCKS_PER_EPOCH { // This is the second time the finalized header is written to disk if let Some(header_from_prev_epoch) = first_header_stored.get(&validator_id) { @@ -310,7 +328,7 @@ fn test_previous_header_hash_matches() { second_header_stored.insert(validator_id); } } else { - assert_eq!(height % EPOCH_NUM_BLOCKS, 0); + assert_eq!(height % BLOCKS_PER_EPOCH, 0); } } // There is an edge case where not all validators write a finalized header to disk. @@ -372,12 +390,20 @@ fn test_single_engine_with_checkpoint() { network.start(); // Create a single validator - let signer = PrivateKey::from_seed(100); - let validators = vec![signer.public_key()]; - let mut registrations = common::register_validators(&mut oracle, &validators).await; + let node_key = PrivateKey::from_seed(100); + let node_public_key = node_key.public_key(); + let consensus_key = bls12381::PrivateKey::from_seed(100); + let consensus_public_key = consensus_key.public_key(); + let key_store = KeyStore { + node_key, + consensus_key, + }; + let validators = vec![(node_public_key.clone(), consensus_public_key)]; + let node_public_keys = vec![node_public_key.clone()]; + let mut registrations = common::register_validators(&mut oracle, &node_public_keys).await; // Link validator - common::link_validators(&mut oracle, &validators, link, None).await; + common::link_validators(&mut oracle, &node_public_keys, link, None).await; let genesis_hash = from_hex_formatted(common::GENESIS_HASH).expect("failed to decode genesis hash"); @@ -392,7 +418,7 @@ fn test_single_engine_with_checkpoint() { consensus_state.set_latest_height(50); // Set a specific height // Configure engine with the checkpoint - let public_key = signer.public_key(); + let public_key = key_store.node_key.public_key(); let uid = format!("validator-{public_key}"); let namespace = String::from("_SEISMIC_BFT"); let engine_client = engine_client_network.create_client(uid.clone()); @@ -405,7 +431,7 @@ fn test_single_engine_with_checkpoint() { uid.clone(), genesis_hash, namespace, - signer, + key_store, validators.clone(), consensus_state, ); @@ -462,23 +488,32 @@ fn test_node_joins_later_with_checkpoint() { // Start network network.start(); // Register participants - let mut signers = Vec::new(); + let mut key_stores = Vec::new(); let mut validators = Vec::new(); for i in 0..n { - let signer = PrivateKey::from_seed(i as u64); - let pk = signer.public_key(); - signers.push(signer); - validators.push(pk); + let node_key = PrivateKey::from_seed(i as u64); + let node_public_key = node_key.public_key(); + let consensus_key = bls12381::PrivateKey::from_seed(i as u64); + let consensus_public_key = consensus_key.public_key(); + let key_store = KeyStore { + node_key, + consensus_key, + }; + key_stores.push(key_store); + validators.push((node_public_key, consensus_public_key)); } - validators.sort(); - signers.sort_by_key(|s| s.public_key()); + validators.sort_by_key(|(lhs, _)| *lhs); + key_stores.sort_by_key(|ks| ks.node_key.public_key()); + + let node_public_keys: Vec<_> = validators.iter().map(|(pk, _)| pk.clone()).collect(); // Separate initial validators from late joiner - let initial_validators = &validators[..validators.len() - 1]; + let initial_node_public_keys = &node_public_keys[..node_public_keys.len() - 1]; // Register and link only initial validators - let mut registrations = common::register_validators(&mut oracle, initial_validators).await; - common::link_validators(&mut oracle, initial_validators, link.clone(), None).await; + let mut registrations = + common::register_validators(&mut oracle, initial_node_public_keys).await; + common::link_validators(&mut oracle, initial_node_public_keys, link.clone(), None).await; // Create the engine clients let genesis_hash = from_hex_formatted(common::GENESIS_HASH).expect("failed to decode genesis hash"); @@ -500,11 +535,11 @@ fn test_node_joins_later_with_checkpoint() { let mut consensus_state_queries = HashMap::new(); // Start all the engines, except for one - let signer_joining_later = signers.pop().unwrap(); + let key_store_joining_later = key_stores.pop().unwrap(); - for (idx, signer) in signers.into_iter().enumerate() { + for (idx, key_store) in key_stores.into_iter().enumerate() { // Create signer context - let public_key = signer.public_key(); + let public_key = key_store.node_key.public_key(); public_keys.insert(public_key.clone()); // Configure engine @@ -519,7 +554,7 @@ fn test_node_joins_later_with_checkpoint() { uid.clone(), genesis_hash, namespace, - signer, + key_store, validators.clone(), initial_state.clone(), ); @@ -551,14 +586,14 @@ fn test_node_joins_later_with_checkpoint() { } // Now register and join the final validator to the network - let public_key = signer_joining_later.public_key(); + let public_key = key_store_joining_later.node_key.public_key(); // Register the late joining validator let late_registrations = common::register_validators(&mut oracle, &[public_key.clone()]).await; // Join the validator to the network - common::join_validator(&mut oracle, &public_key, initial_validators, link).await; + common::join_validator(&mut oracle, &public_key, initial_node_public_keys, link).await; // Allow p2p connections to establish before starting engine context.sleep(Duration::from_millis(100)).await; @@ -584,7 +619,7 @@ fn test_node_joins_later_with_checkpoint() { uid.clone(), genesis_hash, namespace, - signer_joining_later, + key_store_joining_later, validators.clone(), consensus_state, ); @@ -598,7 +633,7 @@ fn test_node_joins_later_with_checkpoint() { engine.start(pending, resolver, broadcast, backfill); // Poll metrics - let stop_height = 3 * EPOCH_NUM_BLOCKS; + let stop_height = 3 * BLOCKS_PER_EPOCH; let mut nodes_finished = HashSet::new(); loop { let metrics = context.encode(); @@ -683,23 +718,33 @@ fn test_node_joins_later_with_checkpoint_not_in_genesis() { // Start network network.start(); // Register participants - let mut signers = Vec::new(); + let mut key_stores = Vec::new(); let mut validators = Vec::new(); for i in 0..n { - let signer = PrivateKey::from_seed(i as u64); - let pk = signer.public_key(); - signers.push(signer); - validators.push(pk); + let node_key = PrivateKey::from_seed(i as u64); + let node_public_key = node_key.public_key(); + let consensus_key = bls12381::PrivateKey::from_seed(i as u64); + let consensus_public_key = consensus_key.public_key(); + let key_store = KeyStore { + node_key, + consensus_key, + }; + key_stores.push(key_store); + validators.push((node_public_key, consensus_public_key)); } - validators.sort(); - signers.sort_by_key(|s| s.public_key()); + validators.sort_by_key(|(lhs, _)| *lhs); + key_stores.sort_by_key(|ks| ks.node_key.public_key()); + + let node_public_keys: Vec<_> = validators.iter().map(|(pk, _)| pk.clone()).collect(); // Separate initial validators from late joiner - let initial_validators = &validators[..validators.len() - 1]; + let initial_validators = validators[..validators.len() - 1].to_vec(); + let initial_node_public_keys = &node_public_keys[..node_public_keys.len() - 1]; // Register and link only initial validators - let mut registrations = common::register_validators(&mut oracle, initial_validators).await; - common::link_validators(&mut oracle, initial_validators, link.clone(), None).await; + let mut registrations = + common::register_validators(&mut oracle, initial_node_public_keys).await; + common::link_validators(&mut oracle, initial_node_public_keys, link.clone(), None).await; // Create the engine clients let genesis_hash = from_hex_formatted(common::GENESIS_HASH).expect("failed to decode genesis hash"); @@ -721,11 +766,11 @@ fn test_node_joins_later_with_checkpoint_not_in_genesis() { let mut consensus_state_queries = HashMap::new(); // Start all the engines, except for one - let signer_joining_later = signers.pop().unwrap(); + let key_store_joining_later = key_stores.pop().unwrap(); - for (idx, signer) in signers.into_iter().enumerate() { + for (idx, key_store) in key_stores.into_iter().enumerate() { // Create signer context - let public_key = signer.public_key(); + let public_key = key_store.node_key.public_key(); public_keys.insert(public_key.clone()); // Configure engine @@ -740,8 +785,8 @@ fn test_node_joins_later_with_checkpoint_not_in_genesis() { uid.clone(), genesis_hash, namespace, - signer, - initial_validators.to_vec(), + key_store, + initial_validators.clone(), initial_state.clone(), ); let engine = Engine::new(context.with_label(&uid), config).await; @@ -772,14 +817,14 @@ fn test_node_joins_later_with_checkpoint_not_in_genesis() { } // Now register and join the final validator to the network - let public_key = signer_joining_later.public_key(); + let public_key = key_store_joining_later.node_key.public_key(); // Register the late joining validator let late_registrations = common::register_validators(&mut oracle, &[public_key.clone()]).await; // Join the validator to the network - common::join_validator(&mut oracle, &public_key, initial_validators, link).await; + common::join_validator(&mut oracle, &public_key, initial_node_public_keys, link).await; // Allow p2p connections to establish before starting engine context.sleep(Duration::from_millis(100)).await; @@ -805,8 +850,8 @@ fn test_node_joins_later_with_checkpoint_not_in_genesis() { uid.clone(), genesis_hash, namespace, - signer_joining_later, - initial_validators.to_vec(), + key_store_joining_later, + initial_validators, consensus_state, ); let engine = Engine::new(context.with_label(&uid), config).await; @@ -819,7 +864,7 @@ fn test_node_joins_later_with_checkpoint_not_in_genesis() { engine.start(pending, resolver, broadcast, backfill); // Poll metrics - let stop_height = 3 * EPOCH_NUM_BLOCKS; + let stop_height = 3 * BLOCKS_PER_EPOCH; let mut nodes_finished = HashSet::new(); loop { let metrics = context.encode(); diff --git a/node/src/tests/execution_requests.rs b/node/src/tests/execution_requests.rs index 11999284..1390af97 100644 --- a/node/src/tests/execution_requests.rs +++ b/node/src/tests/execution_requests.rs @@ -1,8 +1,9 @@ -use crate::engine::{EPOCH_NUM_BLOCKS, Engine, VALIDATOR_MINIMUM_STAKE}; +use crate::engine::{BLOCKS_PER_EPOCH, Engine, VALIDATOR_MINIMUM_STAKE}; use crate::test_harness::common; use crate::test_harness::common::{DummyOracle, get_default_engine_config, get_initial_state}; use crate::test_harness::mock_engine_client::MockEngineNetworkBuilder; use alloy_primitives::{Address, hex}; +use commonware_cryptography::bls12381; use commonware_cryptography::{PrivateKeyExt, Signer}; use commonware_macros::test_traced; use commonware_p2p::simulated; @@ -14,6 +15,7 @@ use std::collections::{HashMap, HashSet}; use std::time::Duration; use summit_types::PrivateKey; use summit_types::execution_request::ExecutionRequest; +use summit_types::keystore::KeyStore; use crate::engine::VALIDATOR_WITHDRAWAL_PERIOD; @@ -42,20 +44,28 @@ fn test_deposit_request_single() { // Start network network.start(); // Register participants - let mut signers = Vec::new(); + let mut key_stores = Vec::new(); let mut validators = Vec::new(); for i in 0..n { - let signer = PrivateKey::from_seed(i as u64); - let pk = signer.public_key(); - signers.push(signer); - validators.push(pk); + let node_key = PrivateKey::from_seed(i as u64); + let node_public_key = node_key.public_key(); + let consensus_key = bls12381::PrivateKey::from_seed(i as u64); + let consensus_public_key = consensus_key.public_key(); + let key_store = KeyStore { + node_key, + consensus_key, + }; + key_stores.push(key_store); + validators.push((node_public_key, consensus_public_key)); } - validators.sort(); - signers.sort_by_key(|s| s.public_key()); - let mut registrations = common::register_validators(&mut oracle, &validators).await; + validators.sort_by_key(|(lhs, _)| *lhs); + key_stores.sort_by_key(|ks| ks.node_key.public_key()); + + let node_public_keys: Vec<_> = validators.iter().map(|(pk, _)| pk.clone()).collect(); + let mut registrations = common::register_validators(&mut oracle, &node_public_keys).await; // Link all validators - common::link_validators(&mut oracle, &validators, link, None).await; + common::link_validators(&mut oracle, &node_public_keys, link, None).await; // Create the engine clients let genesis_hash = from_hex_formatted(common::GENESIS_HASH).expect("failed to decode genesis hash"); @@ -90,9 +100,9 @@ fn test_deposit_request_single() { // Create instances let mut public_keys = HashSet::new(); let mut consensus_state_queries = HashMap::new(); - for (idx, signer) in signers.into_iter().enumerate() { + for (idx, key_store) in key_stores.into_iter().enumerate() { // Create signer context - let public_key = signer.public_key(); + let public_key = key_store.node_key.public_key(); public_keys.insert(public_key.clone()); // Configure engine @@ -107,7 +117,7 @@ fn test_deposit_request_single() { uid.clone(), genesis_hash, namespace, - signer, + key_store, validators.clone(), initial_state.clone(), ); @@ -217,20 +227,28 @@ fn test_deposit_request_top_up() { network.start(); // Register participants - let mut signers = Vec::new(); + let mut key_stores = Vec::new(); let mut validators = Vec::new(); for i in 0..n { - let signer = PrivateKey::from_seed(i as u64); - let pk = signer.public_key(); - signers.push(signer); - validators.push(pk); + let node_key = PrivateKey::from_seed(i as u64); + let node_public_key = node_key.public_key(); + let consensus_key = bls12381::PrivateKey::from_seed(i as u64); + let consensus_public_key = consensus_key.public_key(); + let key_store = KeyStore { + node_key, + consensus_key, + }; + key_stores.push(key_store); + validators.push((node_public_key, consensus_public_key)); } - validators.sort(); - signers.sort_by_key(|s| s.public_key()); - let mut registrations = common::register_validators(&mut oracle, &validators).await; + validators.sort_by_key(|(lhs, _)| *lhs); + key_stores.sort_by_key(|ks| ks.node_key.public_key()); + + let node_public_keys: Vec<_> = validators.iter().map(|(pk, _)| pk.clone()).collect(); + let mut registrations = common::register_validators(&mut oracle, &node_public_keys).await; // Link all validators - common::link_validators(&mut oracle, &validators, link, None).await; + common::link_validators(&mut oracle, &node_public_keys, link, None).await; // Create the engine clients let genesis_hash = @@ -279,9 +297,9 @@ fn test_deposit_request_top_up() { // Create instances let mut public_keys = HashSet::new(); let mut consensus_state_queries = HashMap::new(); - for (idx, signer) in signers.into_iter().enumerate() { + for (idx, key_store) in key_stores.into_iter().enumerate() { // Create signer context - let public_key = signer.public_key(); + let public_key = key_store.node_key.public_key(); public_keys.insert(public_key.clone()); // Configure engine @@ -296,7 +314,7 @@ fn test_deposit_request_top_up() { uid.clone(), genesis_hash, namespace, - signer, + key_store, validators.clone(), initial_state.clone(), ); @@ -414,20 +432,28 @@ fn test_deposit_and_withdrawal_request_single() { network.start(); // Register participants - let mut signers = Vec::new(); + let mut key_stores = Vec::new(); let mut validators = Vec::new(); for i in 0..n { - let signer = PrivateKey::from_seed(i as u64); - let pk = signer.public_key(); - signers.push(signer); - validators.push(pk); + let node_key = PrivateKey::from_seed(i as u64); + let node_public_key = node_key.public_key(); + let consensus_key = bls12381::PrivateKey::from_seed(i as u64); + let consensus_public_key = consensus_key.public_key(); + let key_store = KeyStore { + node_key, + consensus_key, + }; + key_stores.push(key_store); + validators.push((node_public_key, consensus_public_key)); } - validators.sort(); - signers.sort_by_key(|s| s.public_key()); - let mut registrations = common::register_validators(&mut oracle, &validators).await; + validators.sort_by_key(|(lhs, _)| *lhs); + key_stores.sort_by_key(|ks| ks.node_key.public_key()); + + let node_public_keys: Vec<_> = validators.iter().map(|(pk, _)| pk.clone()).collect(); + let mut registrations = common::register_validators(&mut oracle, &node_public_keys).await; // Link all validators - common::link_validators(&mut oracle, &validators, link, None).await; + common::link_validators(&mut oracle, &node_public_keys, link, None).await; // Create the engine clients let genesis_hash = @@ -460,13 +486,13 @@ fn test_deposit_and_withdrawal_request_single() { let requests2 = common::execution_requests_to_requests(execution_requests2); // Create execution requests map (add deposit to block 5) - // The deposit request will be processed after 10 blocks because `EPOCH_NUM_BLOCKS` + // The deposit request will be processed after 10 blocks because `BLOCKS_PER_EPOCH` // is set to 10 in debug mode. // The withdrawal request should be added after block 10, otherwise it will be ignored, because // the account doesn't exist yet. let deposit_block_height = 5; let withdrawal_block_height = 11; - let stop_height = withdrawal_block_height + EPOCH_NUM_BLOCKS + 1; + let stop_height = withdrawal_block_height + BLOCKS_PER_EPOCH + 1; let mut execution_requests_map = HashMap::new(); execution_requests_map.insert(deposit_block_height, requests1); execution_requests_map.insert(withdrawal_block_height, requests2); @@ -479,9 +505,9 @@ fn test_deposit_and_withdrawal_request_single() { // Create instances let mut public_keys = HashSet::new(); let mut consensus_state_queries = HashMap::new(); - for (idx, signer) in signers.into_iter().enumerate() { + for (idx, key_store) in key_stores.into_iter().enumerate() { // Create signer context - let public_key = signer.public_key(); + let public_key = key_store.node_key.public_key(); public_keys.insert(public_key.clone()); // Configure engine @@ -496,7 +522,7 @@ fn test_deposit_and_withdrawal_request_single() { uid.clone(), genesis_hash, namespace, - signer, + key_store, validators.clone(), initial_state.clone(), ); @@ -572,9 +598,9 @@ fn test_deposit_and_withdrawal_request_single() { let withdrawals = engine_client_network.get_withdrawals(); assert_eq!(withdrawals.len(), 1); let withdrawal_epoch = - (withdrawal_block_height + VALIDATOR_WITHDRAWAL_PERIOD + EPOCH_NUM_BLOCKS - 1) - / EPOCH_NUM_BLOCKS; - let withdrawal_height = withdrawal_epoch * EPOCH_NUM_BLOCKS; + (withdrawal_block_height + VALIDATOR_WITHDRAWAL_PERIOD + BLOCKS_PER_EPOCH - 1) + / BLOCKS_PER_EPOCH; + let withdrawal_height = withdrawal_epoch * BLOCKS_PER_EPOCH; let withdrawals = withdrawals .get(&(withdrawal_height)) .expect("missing withdrawal"); @@ -622,20 +648,28 @@ fn test_partial_withdrawal_balance_below_minimum_stake() { network.start(); // Register participants - let mut signers = Vec::new(); + let mut key_stores = Vec::new(); let mut validators = Vec::new(); for i in 0..n { - let signer = PrivateKey::from_seed(i as u64); - let pk = signer.public_key(); - signers.push(signer); - validators.push(pk); + let node_key = PrivateKey::from_seed(i as u64); + let node_public_key = node_key.public_key(); + let consensus_key = bls12381::PrivateKey::from_seed(i as u64); + let consensus_public_key = consensus_key.public_key(); + let key_store = KeyStore { + node_key, + consensus_key, + }; + key_stores.push(key_store); + validators.push((node_public_key, consensus_public_key)); } - validators.sort(); - signers.sort_by_key(|s| s.public_key()); - let mut registrations = common::register_validators(&mut oracle, &validators).await; + validators.sort_by_key(|(lhs, _)| *lhs); + key_stores.sort_by_key(|ks| ks.node_key.public_key()); + + let node_public_keys: Vec<_> = validators.iter().map(|(pk, _)| pk.clone()).collect(); + let mut registrations = common::register_validators(&mut oracle, &node_public_keys).await; // Link all validators - common::link_validators(&mut oracle, &validators, link, None).await; + common::link_validators(&mut oracle, &node_public_keys, link, None).await; // Create the engine clients let genesis_hash = @@ -673,13 +707,13 @@ fn test_partial_withdrawal_balance_below_minimum_stake() { let requests3 = common::execution_requests_to_requests(execution_requests3); // Create execution requests map (add deposit to block 5) - // The deposit request will processed after 10 blocks because `EPOCH_NUM_BLOCKS` + // The deposit request will processed after 10 blocks because `BLOCKS_PER_EPOCH` // is set to 10 in debug mode. // The withdrawal request should be added after block 10, otherwise it will be ignored, because // the account doesn't exist yet. let deposit_block_height = 5; let withdrawal_block_height = 11; - let stop_height = withdrawal_block_height + EPOCH_NUM_BLOCKS + 1; + let stop_height = withdrawal_block_height + BLOCKS_PER_EPOCH + 1; let mut execution_requests_map = HashMap::new(); execution_requests_map.insert(deposit_block_height, requests1); execution_requests_map.insert(withdrawal_block_height, requests2); @@ -699,9 +733,9 @@ fn test_partial_withdrawal_balance_below_minimum_stake() { // Create instances let mut public_keys = HashSet::new(); let mut consensus_state_queries = HashMap::new(); - for (idx, signer) in signers.into_iter().enumerate() { + for (idx, key_store) in key_stores.into_iter().enumerate() { // Create signer context - let public_key = signer.public_key(); + let public_key = key_store.node_key.public_key(); public_keys.insert(public_key.clone()); // Configure engine @@ -716,7 +750,7 @@ fn test_partial_withdrawal_balance_below_minimum_stake() { uid.clone(), genesis_hash, namespace, - signer, + key_store, validators.clone(), initial_state.clone(), ); @@ -795,9 +829,9 @@ fn test_partial_withdrawal_balance_below_minimum_stake() { // to the execution layer. assert_eq!(withdrawals.len(), 1); let withdrawal_epoch = - (withdrawal_block_height + VALIDATOR_WITHDRAWAL_PERIOD + EPOCH_NUM_BLOCKS - 1) - / EPOCH_NUM_BLOCKS; - let withdrawal_height = withdrawal_epoch * EPOCH_NUM_BLOCKS; + (withdrawal_block_height + VALIDATOR_WITHDRAWAL_PERIOD + BLOCKS_PER_EPOCH - 1) + / BLOCKS_PER_EPOCH; + let withdrawal_height = withdrawal_epoch * BLOCKS_PER_EPOCH; let withdrawals = withdrawals .get(&withdrawal_height) .expect("missing withdrawal"); @@ -846,20 +880,28 @@ fn test_deposit_less_than_min_stake_and_withdrawal() { network.start(); // Register participants - let mut signers = Vec::new(); + let mut key_stores = Vec::new(); let mut validators = Vec::new(); for i in 0..n { - let signer = PrivateKey::from_seed(i as u64); - let pk = signer.public_key(); - signers.push(signer); - validators.push(pk); + let node_key = PrivateKey::from_seed(i as u64); + let node_public_key = node_key.public_key(); + let consensus_key = bls12381::PrivateKey::from_seed(i as u64); + let consensus_public_key = consensus_key.public_key(); + let key_store = KeyStore { + node_key, + consensus_key, + }; + key_stores.push(key_store); + validators.push((node_public_key, consensus_public_key)); } - validators.sort(); - signers.sort_by_key(|s| s.public_key()); - let mut registrations = common::register_validators(&mut oracle, &validators).await; + validators.sort_by_key(|(lhs, _)| *lhs); + key_stores.sort_by_key(|ks| ks.node_key.public_key()); + + let node_public_keys: Vec<_> = validators.iter().map(|(pk, _)| pk.clone()).collect(); + let mut registrations = common::register_validators(&mut oracle, &node_public_keys).await; // Link all validators - common::link_validators(&mut oracle, &validators, link, None).await; + common::link_validators(&mut oracle, &node_public_keys, link, None).await; // Create the engine clients let genesis_hash = @@ -892,13 +934,13 @@ fn test_deposit_less_than_min_stake_and_withdrawal() { let requests2 = common::execution_requests_to_requests(execution_requests2); // Create execution requests map (add deposit to block 5) - // The deposit request will be processed after 10 blocks because `EPOCH_NUM_BLOCKS` + // The deposit request will be processed after 10 blocks because `BLOCKS_PER_EPOCH` // is set to 10 in debug mode. // The withdrawal request should be added after block 10, otherwise it will be ignored, because // the account doesn't exist yet. let deposit_block_height = 5; let withdrawal_block_height = 11; - let stop_height = withdrawal_block_height + EPOCH_NUM_BLOCKS + 1; + let stop_height = withdrawal_block_height + BLOCKS_PER_EPOCH + 1; let mut execution_requests_map = HashMap::new(); execution_requests_map.insert(deposit_block_height, requests1); execution_requests_map.insert(withdrawal_block_height, requests2); @@ -912,9 +954,9 @@ fn test_deposit_less_than_min_stake_and_withdrawal() { // Create instances let mut public_keys = HashSet::new(); let mut consensus_state_queries = HashMap::new(); - for (idx, signer) in signers.into_iter().enumerate() { + for (idx, key_store) in key_stores.into_iter().enumerate() { // Create signer context - let public_key = signer.public_key(); + let public_key = key_store.node_key.public_key(); public_keys.insert(public_key.clone()); // Configure engine @@ -929,7 +971,7 @@ fn test_deposit_less_than_min_stake_and_withdrawal() { uid.clone(), genesis_hash, namespace, - signer, + key_store, validators.clone(), initial_state.clone(), ); @@ -1013,9 +1055,9 @@ fn test_deposit_less_than_min_stake_and_withdrawal() { let withdrawals = engine_client_network.get_withdrawals(); assert_eq!(withdrawals.len(), 1); let withdrawal_epoch = - (withdrawal_block_height + VALIDATOR_WITHDRAWAL_PERIOD + EPOCH_NUM_BLOCKS - 1) - / EPOCH_NUM_BLOCKS; - let withdrawal_height = withdrawal_epoch * EPOCH_NUM_BLOCKS; + (withdrawal_block_height + VALIDATOR_WITHDRAWAL_PERIOD + BLOCKS_PER_EPOCH - 1) + / BLOCKS_PER_EPOCH; + let withdrawal_height = withdrawal_epoch * BLOCKS_PER_EPOCH; let withdrawals = withdrawals .get(&withdrawal_height) .expect("missing withdrawal"); @@ -1060,20 +1102,28 @@ fn test_deposit_and_withdrawal_request_multiple() { network.start(); // Register participants - let mut signers = Vec::new(); + let mut key_stores = Vec::new(); let mut validators = Vec::new(); for i in 0..n { - let signer = PrivateKey::from_seed(i as u64); - let pk = signer.public_key(); - signers.push(signer); - validators.push(pk); + let node_key = PrivateKey::from_seed(i as u64); + let node_public_key = node_key.public_key(); + let consensus_key = bls12381::PrivateKey::from_seed(i as u64); + let consensus_public_key = consensus_key.public_key(); + let key_store = KeyStore { + node_key, + consensus_key, + }; + key_stores.push(key_store); + validators.push((node_public_key, consensus_public_key)); } - validators.sort(); - signers.sort_by_key(|s| s.public_key()); - let mut registrations = common::register_validators(&mut oracle, &validators).await; + validators.sort_by_key(|(lhs, _)| *lhs); + key_stores.sort_by_key(|ks| ks.node_key.public_key()); + + let node_public_keys: Vec<_> = validators.iter().map(|(pk, _)| pk.clone()).collect(); + let mut registrations = common::register_validators(&mut oracle, &node_public_keys).await; // Link all validators - common::link_validators(&mut oracle, &validators, link, None).await; + common::link_validators(&mut oracle, &node_public_keys, link, None).await; // Create the engine clients let genesis_hash = @@ -1124,7 +1174,7 @@ fn test_deposit_and_withdrawal_request_multiple() { // Create execution requests map (add deposit to block 5) let deposit_block_height = 5; let withdrawal_block_height = 11; - let stop_height = withdrawal_block_height + EPOCH_NUM_BLOCKS + 1; + let stop_height = withdrawal_block_height + BLOCKS_PER_EPOCH + 1; let mut execution_requests_map = HashMap::new(); execution_requests_map.insert(deposit_block_height, requests1); execution_requests_map.insert(withdrawal_block_height, requests2); @@ -1138,9 +1188,9 @@ fn test_deposit_and_withdrawal_request_multiple() { // Create instances let mut public_keys = HashSet::new(); let mut consensus_state_queries = HashMap::new(); - for (idx, signer) in signers.into_iter().enumerate() { + for (idx, key_store) in key_stores.into_iter().enumerate() { // Create signer context - let public_key = signer.public_key(); + let public_key = key_store.node_key.public_key(); public_keys.insert(public_key.clone()); // Configure engine @@ -1155,7 +1205,7 @@ fn test_deposit_and_withdrawal_request_multiple() { uid.clone(), genesis_hash, namespace, - signer, + key_store, validators.clone(), initial_state.clone(), ); @@ -1294,20 +1344,28 @@ fn test_deposit_request_invalid_signature() { // Start network network.start(); // Register participants - let mut signers = Vec::new(); + let mut key_stores = Vec::new(); let mut validators = Vec::new(); for i in 0..n { - let signer = PrivateKey::from_seed(i as u64); - let pk = signer.public_key(); - signers.push(signer); - validators.push(pk); + let node_key = PrivateKey::from_seed(i as u64); + let node_public_key = node_key.public_key(); + let consensus_key = bls12381::PrivateKey::from_seed(i as u64); + let consensus_public_key = consensus_key.public_key(); + let key_store = KeyStore { + node_key, + consensus_key, + }; + key_stores.push(key_store); + validators.push((node_public_key, consensus_public_key)); } - validators.sort(); - signers.sort_by_key(|s| s.public_key()); - let mut registrations = common::register_validators(&mut oracle, &validators).await; + validators.sort_by_key(|(lhs, _)| *lhs); + key_stores.sort_by_key(|ks| ks.node_key.public_key()); + + let node_public_keys: Vec<_> = validators.iter().map(|(pk, _)| pk.clone()).collect(); + let mut registrations = common::register_validators(&mut oracle, &node_public_keys).await; // Link all validators - common::link_validators(&mut oracle, &validators, link, None).await; + common::link_validators(&mut oracle, &node_public_keys, link, None).await; // Create the engine clients let genesis_hash = from_hex_formatted(common::GENESIS_HASH).expect("failed to decode genesis hash"); @@ -1340,7 +1398,7 @@ fn test_deposit_request_invalid_signature() { // Create execution requests map (add deposit to block 5) let deposit_block_height = 5; - let stop_height = deposit_block_height + EPOCH_NUM_BLOCKS + 1; + let stop_height = deposit_block_height + BLOCKS_PER_EPOCH + 1; let mut execution_requests_map = HashMap::new(); execution_requests_map.insert(deposit_block_height, requests); @@ -1353,9 +1411,9 @@ fn test_deposit_request_invalid_signature() { // Create instances let mut public_keys = HashSet::new(); let mut consensus_state_queries = HashMap::new(); - for (idx, signer) in signers.into_iter().enumerate() { + for (idx, key_store) in key_stores.into_iter().enumerate() { // Create signer context - let public_key = signer.public_key(); + let public_key = key_store.node_key.public_key(); public_keys.insert(public_key.clone()); // Configure engine @@ -1370,7 +1428,7 @@ fn test_deposit_request_invalid_signature() { uid.clone(), genesis_hash, namespace, - signer, + key_store, validators.clone(), initial_state.clone(), ); diff --git a/node/src/tests/syncer.rs b/node/src/tests/syncer.rs index c8b6314f..ed0b5bfb 100644 --- a/node/src/tests/syncer.rs +++ b/node/src/tests/syncer.rs @@ -1,8 +1,8 @@ -use crate::engine::{EPOCH_NUM_BLOCKS, Engine, VALIDATOR_MINIMUM_STAKE}; +use crate::engine::{BLOCKS_PER_EPOCH, Engine, VALIDATOR_MINIMUM_STAKE}; use crate::test_harness::common; use crate::test_harness::common::{DummyOracle, get_default_engine_config, get_initial_state}; use crate::test_harness::mock_engine_client::MockEngineNetworkBuilder; -use commonware_cryptography::{PrivateKeyExt, Signer}; +use commonware_cryptography::{PrivateKeyExt, Signer, bls12381}; use commonware_macros::test_traced; use commonware_p2p::simulated; use commonware_p2p::simulated::{Link, Network}; @@ -11,13 +11,13 @@ use commonware_runtime::{Clock, Metrics, Runner as _, deterministic}; use commonware_utils::from_hex_formatted; use std::collections::{HashMap, HashSet}; use std::time::Duration; -use summit_types::PrivateKey; +use summit_types::{PrivateKey, keystore::KeyStore}; #[test_traced("INFO")] fn test_node_joins_later_no_checkpoint() { // Creates a network of 5 nodes, and starts only 4 of them. // The last node starts after 10 blocks, to ensure that the block backfilling - // in the syncer works. + // in the syncer_old works. let n = 5; let link = Link { latency: Duration::from_millis(80), @@ -38,16 +38,23 @@ fn test_node_joins_later_no_checkpoint() { // Start network network.start(); // Register participants - let mut signers = Vec::new(); + let mut key_stores = Vec::new(); let mut validators = Vec::new(); for i in 0..n { - let signer = PrivateKey::from_seed(i as u64); - let pk = signer.public_key(); - signers.push(signer); - validators.push(pk); + let node_key = PrivateKey::from_seed(i as u64); + let node_public_key = node_key.public_key(); + let consensus_key = bls12381::PrivateKey::from_seed(i as u64); + let consensus_public_key = consensus_key.public_key(); + let key_store = KeyStore { + node_key, + consensus_key, + }; + key_stores.push(key_store); + validators.push((node_public_key, consensus_public_key)); } - validators.sort(); - signers.sort_by_key(|s| s.public_key()); + validators.sort_by_key(|lhs, rhs| lhs.0.cmp(&rhs.0)); + key_stores + .sort_by_key(|lhs, rhs| lhs.node_key.public_key().cmp(&rhs.node_key.public_key())); // Separate initial validators from late joiner let initial_validators = &validators[..validators.len() - 1]; @@ -76,11 +83,11 @@ fn test_node_joins_later_no_checkpoint() { let mut consensus_state_queries = HashMap::new(); // Start all the engines, except for one - let signer_joining_later = signers.pop().unwrap(); + let key_store_joining_later = key_stores.pop().unwrap(); - for (idx, signer) in signers.into_iter().enumerate() { + for (idx, key_store) in key_stores.into_iter().enumerate() { // Create signer context - let public_key = signer.public_key(); + let public_key = key_store.node_key.public_key(); public_keys.insert(public_key.clone()); // Configure engine @@ -95,7 +102,7 @@ fn test_node_joins_later_no_checkpoint() { uid.clone(), genesis_hash, namespace, - signer, + key_store, validators.clone(), initial_state.clone(), ); @@ -120,7 +127,7 @@ fn test_node_joins_later_no_checkpoint() { }; // Now register and join the final validator to the network - let public_key = signer_joining_later.public_key(); + let public_key = key_store_joining_later.node_key.public_key(); // Register the late joining validator let late_registrations = @@ -146,7 +153,7 @@ fn test_node_joins_later_no_checkpoint() { uid.clone(), genesis_hash, namespace, - signer_joining_later, + key_store_joining_later, validators.clone(), initial_state, // pass initial state (start from genesis) ); @@ -160,7 +167,7 @@ fn test_node_joins_later_no_checkpoint() { engine.start(pending, resolver, broadcast, backfill); // Poll metrics - let stop_height = 2 * EPOCH_NUM_BLOCKS; + let stop_height = 2 * BLOCKS_PER_EPOCH; let mut nodes_finished = HashSet::new(); loop { let metrics = context.encode(); @@ -223,7 +230,7 @@ fn test_node_joins_later_no_checkpoint() { fn test_node_joins_later_no_checkpoint_not_in_genesis() { // Creates a network of 5 nodes, and starts only 4 of them. // The last node starts after 10 blocks, to ensure that the block backfilling - // in the syncer works. + // in the syncer_old works. // In this test the joining node is not included in the list of peers that is passed to the engine. let n = 5; let link = Link { @@ -245,16 +252,23 @@ fn test_node_joins_later_no_checkpoint_not_in_genesis() { // Start network network.start(); // Register participants - let mut signers = Vec::new(); + let mut key_stores = Vec::new(); let mut validators = Vec::new(); for i in 0..n { - let signer = PrivateKey::from_seed(i as u64); - let pk = signer.public_key(); - signers.push(signer); - validators.push(pk); + let node_key = PrivateKey::from_seed(i as u64); + let node_public_key = node_key.public_key(); + let consensus_key = bls12381::PrivateKey::from_seed(i as u64); + let consensus_public_key = consensus_key.public_key(); + let key_store = KeyStore { + node_key, + consensus_key, + }; + key_stores.push(key_store); + validators.push((node_public_key, consensus_public_key)); } - validators.sort(); - signers.sort_by_key(|s| s.public_key()); + validators.sort_by_key(|lhs, rhs| lhs.0.cmp(&rhs.0)); + key_stores + .sort_by_key(|lhs, rhs| lhs.node_key.public_key().cmp(&rhs.node_key.public_key())); // Separate initial validators from late joiner let initial_validators = &validators[..validators.len() - 1]; @@ -283,11 +297,11 @@ fn test_node_joins_later_no_checkpoint_not_in_genesis() { let mut consensus_state_queries = HashMap::new(); // Start all the engines, except for one - let signer_joining_later = signers.pop().unwrap(); + let key_store_joining_later = key_stores.pop().unwrap(); - for (idx, signer) in signers.into_iter().enumerate() { + for (idx, key_store) in key_stores.into_iter().enumerate() { // Create signer context - let public_key = signer.public_key(); + let public_key = key_store.node_key.public_key(); public_keys.insert(public_key.clone()); // Configure engine @@ -302,7 +316,7 @@ fn test_node_joins_later_no_checkpoint_not_in_genesis() { uid.clone(), genesis_hash, namespace, - signer, + key_store, initial_validators.to_vec(), initial_state.clone(), ); @@ -327,7 +341,7 @@ fn test_node_joins_later_no_checkpoint_not_in_genesis() { }; // Now register and join the final validator to the network - let public_key = signer_joining_later.public_key(); + let public_key = key_store_joining_later.node_key.public_key(); // Register the late joining validator let late_registrations = @@ -347,7 +361,7 @@ fn test_node_joins_later_no_checkpoint_not_in_genesis() { let engine_client = engine_client_network.create_client(uid.clone()); - // Joining node uses initial_validators for syncer verification + // Joining node uses initial_validators for syncer_old verification // since historical blocks were finalized by only those 4 validators let config = get_default_engine_config( engine_client, @@ -355,7 +369,7 @@ fn test_node_joins_later_no_checkpoint_not_in_genesis() { uid.clone(), genesis_hash, namespace, - signer_joining_later, + key_store_joining_later, initial_validators.to_vec(), initial_state, // pass initial state (start from genesis) ); @@ -369,7 +383,7 @@ fn test_node_joins_later_no_checkpoint_not_in_genesis() { engine.start(pending, resolver, broadcast, backfill); // Poll metrics - let stop_height = 2 * EPOCH_NUM_BLOCKS; + let stop_height = 2 * BLOCKS_PER_EPOCH; let mut nodes_finished = HashSet::new(); loop { let metrics = context.encode(); From c7bbf4529c97b5e9f9b93777b36e0f119429835d Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Fri, 7 Nov 2025 21:26:07 -0500 Subject: [PATCH 41/81] feat: send new validator list to orchestrator from finalizer --- Cargo.lock | 1 + finalizer/src/actor.rs | 89 ++++++++++++---------------- finalizer/src/db.rs | 3 +- node/src/args.rs | 36 +++-------- node/src/bin/execute_blocks.rs | 9 +-- node/src/bin/stake_and_checkpoint.rs | 6 +- node/src/bin/withdraw_and_exit.rs | 2 +- node/src/config.rs | 6 +- node/src/engine.rs | 40 +++---------- node/src/keys.rs | 3 +- syncer/Cargo.toml | 3 +- syncer/src/actor.rs | 6 +- syncer/src/finalizer.rs | 2 - types/src/consensus_state.rs | 17 ++++++ types/src/engine_client.rs | 18 +++--- types/src/scheme.rs | 7 +-- 16 files changed, 101 insertions(+), 147 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 71c73aa7..2a871d6b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5716,6 +5716,7 @@ dependencies = [ "futures", "governor", "metrics", + "prometheus-client", "rand 0.8.5", "summit-types", "tokio-util", diff --git a/finalizer/src/actor.rs b/finalizer/src/actor.rs index 2abdf74d..cc1c67e6 100644 --- a/finalizer/src/actor.rs +++ b/finalizer/src/actor.rs @@ -5,6 +5,7 @@ use alloy_primitives::Address; #[cfg(debug_assertions)] use alloy_rpc_types_engine::ForkchoiceState; use commonware_codec::{DecodeExt as _, ReadExt as _}; +use commonware_consensus::Reporter; use commonware_consensus::simplex::signing_scheme::{Scheme, bls12381_multisig}; use commonware_consensus::simplex::types::Finalization; use commonware_cryptography::bls12381::primitives::variant::Variant; @@ -21,11 +22,12 @@ use futures::{FutureExt, StreamExt as _, select}; use metrics::{counter, histogram}; #[cfg(debug_assertions)] use prometheus_client::metrics::gauge::Gauge; -use rand::{CryptoRng, Rng}; +use rand::Rng; use std::collections::BTreeMap; use std::marker::PhantomData; use std::num::NonZero; use std::time::Instant; +use summit_orchestrator::Message; use summit_syncer::Update; use summit_types::account::{ValidatorAccount, ValidatorStatus}; use summit_types::checkpoint::Checkpoint; @@ -33,9 +35,10 @@ use summit_types::consensus_state_query::{ConsensusStateRequest, ConsensusStateR use summit_types::execution_request::ExecutionRequest; use summit_types::network_oracle::NetworkOracle; use summit_types::registry::Registry; +use summit_types::scheme::EpochTransition; use summit_types::utils::{is_last_block_of_epoch, is_penultimate_block_of_epoch}; use summit_types::{Block, BlockAuxData, Digest, FinalizedHeader, PublicKey, Signature}; -use summit_types::{BlockEnvelope, EngineClient, consensus_state::ConsensusState}; +use summit_types::{EngineClient, consensus_state::ConsensusState}; use tokio_util::sync::CancellationToken; use tracing::{info, warn}; @@ -139,26 +142,11 @@ impl< ) } - pub fn start(mut self, sync_height: u64) -> Handle<()> { - spawn_cell!(self.context, self.run(sync_height).await) + pub fn start(mut self) -> Handle<()> { + spawn_cell!(self.context, self.run().await) } - pub async fn run( - mut self, - //orchestrator: Orchestrator, - sync_height: u64, - //finalization_notify: mpsc::Receiver<()>, - ) { - //let (block_fetcher, mut rx_finalize_blocks) = BlockFetcher::new( - // orchestrator, - // finalization_notify, - // self.epoch_num_of_blocks, - // sync_height, - //); - //self.context - // .with_label("block-fetcher") - // .spawn(|_| block_fetcher.run()); - + pub async fn run(mut self) { let mut last_committed_timestamp: Option = None; let mut signal = self.context.stopped().fuse(); let cancellation_token = self.cancellation_token.clone(); @@ -171,27 +159,19 @@ impl< break; } select! { - //msg = rx_finalize_blocks.next() => { - // let Some((envelope, notifier)) = msg else { - // warn!("All senders to finalizer dropped"); - // break; - // }; - // self.handle_execution_block(notifier,envelope, &mut last_committed_timestamp).await; - - //} mailbox_message = self.mailbox.next() => { let mail = mailbox_message.expect("Finalizer mailbox closed"); match mail { FinalizerMessage::SyncerUpdate { update } => { match update { - Update::Tip(height, digest) => { - + Update::Tip(_height, _digest) => { + // I don't think we need this } Update::Block(block, ack_tx) => { self.handle_execution_block(ack_tx, block, None, &mut last_committed_timestamp).await; } Update::BlockWithFinalization(block, finalization, ack_tx) => { - + self.handle_execution_block(ack_tx, block, Some(finalization), &mut last_committed_timestamp).await; } } }, @@ -201,7 +181,6 @@ impl< let _ = response.send(()); continue; } - self.pending_height_notifys.entry(height).or_default().push(response); }, FinalizerMessage::GetAuxData { height, response } => { @@ -345,6 +324,10 @@ impl< // Store finalizes checkpoint to database if is_last_block_of_epoch(new_height, self.epoch_num_of_blocks) { let view = block.view(); + + // Increment epoch + self.state.epoch += 1; + if let Some(finalization) = finalization { // The finalized signatures should always be included on the last block // of the epoch. However, there is an edge case, where the block after @@ -395,6 +378,14 @@ impl< account.status = ValidatorStatus::Active; } + for key in self.state.removed_validators.iter() { + // TODO(matthias): I think this is not necessary. Inactive accounts will be removed after withdrawing. + let key_bytes: [u8; 32] = key.as_ref().try_into().unwrap(); + if let Some(mut account) = self.state.validator_accounts.get_mut(&key_bytes) { + account.status = ValidatorStatus::Inactive; + } + } + // If the node's public key is contained in the removed validator list, // trigger an exit if self @@ -405,26 +396,24 @@ impl< { self.validator_exit = true; } - - // TODO(matthias): remove keys in removed_validators from state or set inactive? - self.registry.update_registry( - // We add a delta to the view because the views are initialized with fixed-size - // arrays in Simplex. Adding a validator to an ongoing view can cause an - // out-of-bounds array access. - view + REGISTRY_CHANGE_VIEW_DELTA, - //view, - &self.state.added_validators, - &self.state.removed_validators, - ); - // TODO(matthias): update peers properly - let participants = self.registry.peer_set(1).await.unwrap(); - // TODO(matthias): should we wait until view `view + REGISTRY_CHANGE_VIEW_DELTA` - // to update the oracle? - self.oracle - .register(new_height, participants.into_iter().collect()) - .await; } + // Create the list of validators for the new epoch + let active_validators = self.state.get_active_validators(); + let network_keys = active_validators + .iter() + .map(|(node_key, _)| node_key.clone()) + .collect(); + self.oracle.register(self.state.epoch, network_keys).await; + + // Send the new validator list to the orchestrator + self.orchestrator_mailbox + .report(Message::Enter(EpochTransition { + epoch: self.state.epoch, + validator_keys: active_validators, + })) + .await; + #[cfg(feature = "prom")] let db_operations_start = Instant::now(); // This pending checkpoint should always exist, because it was created at the previous height. diff --git a/finalizer/src/db.rs b/finalizer/src/db.rs index 7f6bc18d..3caa0a68 100644 --- a/finalizer/src/db.rs +++ b/finalizer/src/db.rs @@ -1,13 +1,12 @@ use bytes::{Buf, BufMut}; use commonware_codec::{EncodeSize, Error, Read, Write}; use commonware_consensus::simplex::signing_scheme::bls12381_multisig; -use commonware_cryptography::bls12381::primitives::variant::{MinPk, Variant}; +use commonware_cryptography::bls12381::primitives::variant::Variant; use commonware_cryptography::ed25519::PublicKey; use commonware_runtime::{Clock, Metrics, Storage}; use commonware_storage::adb::store::{self, Store}; use commonware_storage::translator::TwoCap; use commonware_utils::sequence::FixedBytes; -use std::marker::PhantomData; use summit_types::FinalizedHeader; use summit_types::checkpoint::Checkpoint; use summit_types::consensus_state::ConsensusState; diff --git a/node/src/args.rs b/node/src/args.rs index 7402a2c5..faf4312c 100644 --- a/node/src/args.rs +++ b/node/src/args.rs @@ -1,21 +1,19 @@ use crate::{ config::{ - BACKFILLER_CHANNEL, BROADCASTER_CHANNEL, EngineConfig, MESSAGE_BACKLOG, PENDING_CHANNEL, - RESOLVER_CHANNEL, expect_key_store, + BACKFILLER_CHANNEL, BROADCASTER_CHANNEL, EngineConfig, MESSAGE_BACKLOG, expect_key_store, }, engine::Engine, keys::KeySubCmd, }; use clap::{Args, Parser, Subcommand}; -use commonware_cryptography::{Signer, bls12381, ed25519}; +use commonware_cryptography::{Signer, bls12381}; use commonware_p2p::{Manager, authenticated}; use commonware_runtime::{Handle, Metrics as _, Runner, Spawner as _, tokio}; use summit_rpc::{PathSender, start_rpc_server, start_rpc_server_for_genesis}; use tokio_util::sync::CancellationToken; -use alloy_primitives::{Address, B256}; +use alloy_primitives::B256; use alloy_rpc_types_engine::ForkchoiceState; -use commonware_codec::{DecodeExt, ReadExt}; use commonware_utils::from_hex_formatted; use commonware_utils::set::Ordered; use futures::{channel::oneshot, future::try_join_all}; @@ -262,7 +260,7 @@ impl Command { let engine_client = RethEngineClient::new(engine_ipc_path.to_string_lossy().to_string()).await; - let our_ip = get_node_ip(&flags, &key_store, &committee); + let our_ip = get_node_ip(flags, &key_store, &committee); let mut network_committee: Vec<(PublicKey, SocketAddr)> = committee .into_iter() @@ -346,14 +344,6 @@ impl Command { ) .unwrap(); - // Register pending channel - let pending_limit = Quota::per_second(NonZeroU32::new(128).unwrap()); - let pending = network.register(PENDING_CHANNEL, pending_limit, MESSAGE_BACKLOG); - - // Register resolver channel - let resolver_limit = Quota::per_second(NonZeroU32::new(128).unwrap()); - let resolver = network.register(RESOLVER_CHANNEL, resolver_limit, MESSAGE_BACKLOG); - // Register broadcast channel let broadcaster_limit = Quota::per_second(NonZeroU32::new(8).unwrap()); let broadcaster = @@ -371,7 +361,7 @@ impl Command { let finalizer_mailbox = engine.finalizer_mailbox.clone(); // Start engine - let engine = engine.start(pending, resolver, broadcaster, backfiller); + let engine = engine.start(broadcaster, backfiller); // Start RPC server let key_store_path = flags.key_store_path.clone(); @@ -489,7 +479,7 @@ pub fn run_node_with_runtime( // configure network #[cfg(feature = "e2e")] - let mut p2p_cfg = authenticated::discovery::Config::aggressive( + let mut p2p_cfg = authenticated::discovery::Config::local( key_store.node_key.clone(), genesis.namespace.as_bytes(), SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), flags.port), @@ -533,14 +523,6 @@ pub fn run_node_with_runtime( ) .unwrap(); - // Register pending channel - let pending_limit = Quota::per_second(NonZeroU32::new(128).unwrap()); - let pending = network.register(PENDING_CHANNEL, pending_limit, MESSAGE_BACKLOG); - - // Register resolver channel - let resolver_limit = Quota::per_second(NonZeroU32::new(128).unwrap()); - let resolver = network.register(RESOLVER_CHANNEL, resolver_limit, MESSAGE_BACKLOG); - // Register broadcast channel let broadcaster_limit = Quota::per_second(NonZeroU32::new(8).unwrap()); let broadcaster = network.register(BROADCASTER_CHANNEL, broadcaster_limit, MESSAGE_BACKLOG); @@ -556,7 +538,7 @@ pub fn run_node_with_runtime( let finalizer_mailbox = engine.finalizer_mailbox.clone(); // Start engine - let engine = engine.start(pending, resolver, broadcaster, backfiller); + let engine = engine.start(broadcaster, backfiller); // Start prometheus endpoint #[cfg(feature = "prom")] @@ -618,7 +600,7 @@ fn get_initial_state( .expect("Public key must be 32 bytes"); let account = ValidatorAccount { consensus_public_key: validator.consensus_public_key.clone(), - withdrawal_credentials: validator.withdrawal_credentials.clone(), + withdrawal_credentials: validator.withdrawal_credentials, balance: VALIDATOR_MINIMUM_STAKE, pending_withdrawal_amount: 0, status: ValidatorStatus::Active, @@ -638,7 +620,7 @@ fn get_initial_state( fn get_node_ip( flags: &RunFlags, key_store: &KeyStore, - committee: &Vec, + committee: &[Validator], ) -> SocketAddr { if let Some(ref ip_str) = flags.ip { ip_str diff --git a/node/src/bin/execute_blocks.rs b/node/src/bin/execute_blocks.rs index 80cffefb..136c1d6d 100644 --- a/node/src/bin/execute_blocks.rs +++ b/node/src/bin/execute_blocks.rs @@ -168,11 +168,12 @@ fn execution_payload_envelope_to_block( execution_payload, execution_requests, payload.envelope_inner.block_value, + 0, // epoch view, - None, - [0u8; 32].into(), - Vec::new(), // added_validators - Vec::new(), // removed_validators + None, // checkpoint_hash + Digest::from([0u8; 32]), // prev_epoch_header_hash + Vec::new(), // added_validators + Vec::new(), // removed_validators ) } diff --git a/node/src/bin/stake_and_checkpoint.rs b/node/src/bin/stake_and_checkpoint.rs index 840e525d..be897418 100644 --- a/node/src/bin/stake_and_checkpoint.rs +++ b/node/src/bin/stake_and_checkpoint.rs @@ -354,7 +354,7 @@ fn main() -> Result<(), Box> { // Send stop signal and wait for runtime to shut down gracefully node0_runtime.stop_tx.send(()).expect("Failed to send stop signal"); println!("Waiting for node{} runtime to shut down...", source_node); - let _ = context.clone().spawn_blocking(false, move |_| { + let _ = tokio::task::spawn_blocking(move || { node0_runtime.thread.join().expect("Failed to join node0 thread"); }).await; @@ -487,7 +487,7 @@ fn main() -> Result<(), Box> { let signer_path = format!("{}/node{}/data/key.pem", args.data_dir, x); let encoded_priv_key = ed25519_private_key.to_string(); fs::write(&signer_path, encoded_priv_key).expect("Unable to write private key to disk"); - flags.key_path = signer_path; + flags.key_store_path = signer_path; flags.ip = Some("127.0.0.1:26640".to_string()); println!( @@ -573,7 +573,7 @@ fn main() -> Result<(), Box> { println!("Waiting for all nodes to shut down..."); for (idx, node_runtime) in node_runtimes.into_iter().enumerate() { println!("Waiting for node index {} to join...", idx); - let _ = context.clone().spawn_blocking(false, move |_| { + let _ = tokio::task::spawn_blocking(move || { match node_runtime.thread.join() { Ok(_) => println!("Node index {} thread joined successfully", idx), Err(e) => println!("Node index {} thread join failed: {:?}", idx, e), diff --git a/node/src/bin/withdraw_and_exit.rs b/node/src/bin/withdraw_and_exit.rs index 29186f38..68345409 100644 --- a/node/src/bin/withdraw_and_exit.rs +++ b/node/src/bin/withdraw_and_exit.rs @@ -382,7 +382,7 @@ fn get_node_flags(node: usize) -> RunFlags { let path = format!("testnet/node{node}/"); RunFlags { - key_path: format!("{path}key.pem"), + key_store_path: format!("{path}key.pem"), store_path: format!("{path}db"), port: (26600 + (node * 10)) as u16, prom_port: (28600 + (node * 10)) as u16, diff --git a/node/src/config.rs b/node/src/config.rs index a95af67b..7a50a35e 100644 --- a/node/src/config.rs +++ b/node/src/config.rs @@ -11,10 +11,8 @@ use summit_types::network_oracle::NetworkOracle; use summit_types::{EngineClient, Genesis, PrivateKey, PublicKey}; use zeroize::ZeroizeOnDrop; /* DEFAULTS */ -pub const PENDING_CHANNEL: u64 = 0; -pub const RESOLVER_CHANNEL: u64 = 1; -pub const BROADCASTER_CHANNEL: u64 = 2; -pub const BACKFILLER_CHANNEL: u64 = 3; +pub const BROADCASTER_CHANNEL: u64 = 0; +pub const BACKFILLER_CHANNEL: u64 = 1; pub const MAILBOX_SIZE: usize = 16384; const FETCH_TIMEOUT: Duration = Duration::from_secs(5); diff --git a/node/src/engine.rs b/node/src/engine.rs index 6f6cd61d..d246a35e 100644 --- a/node/src/engine.rs +++ b/node/src/engine.rs @@ -2,18 +2,14 @@ use crate::config::EngineConfig; use commonware_broadcast::buffered; use commonware_codec::{DecodeExt, Encode}; use commonware_consensus::simplex::signing_scheme::Scheme; -use commonware_consensus::simplex::signing_scheme::bls12381_multisig; -use commonware_consensus::simplex::{self, Engine as Simplex}; -use commonware_consensus::{Automaton, Relay}; +use commonware_cryptography::Signer; use commonware_cryptography::bls12381::primitives::group; use commonware_cryptography::bls12381::primitives::variant::Variant; -use commonware_cryptography::{Signer as _, Signer}; use commonware_p2p::{Blocker, Manager, Receiver, Sender, utils::requester}; use commonware_runtime::buffer::PoolRef; use commonware_runtime::{Clock, Handle, Metrics, Network, Spawner, Storage}; use commonware_utils::{NZU64, NZUsize}; use futures::FutureExt; -use futures::channel::{mpsc, oneshot}; use futures::future::try_join_all; use governor::{Quota, clock::Clock as GClock}; use rand::{CryptoRng, Rng}; @@ -26,7 +22,7 @@ use summit_finalizer::{FinalizerConfig, FinalizerMailbox}; use summit_types::network_oracle::NetworkOracle; use summit_types::registry::Registry; use summit_types::scheme::{MultisigScheme, SummitSchemeProvider}; -use summit_types::{Block, Digest, EngineClient, PrivateKey, PublicKey}; +use summit_types::{Block, EngineClient, PublicKey}; use tokio_util::sync::CancellationToken; use tracing::{error, info, warn}; use zeroize::ZeroizeOnDrop; @@ -82,9 +78,9 @@ pub struct Engine< > { context: E, application: summit_application::Actor, S::PublicKey, S, V>, - application_mailbox: summit_application::Mailbox, buffer: buffered::Engine>, buffer_mailbox: buffered::Mailbox>, + #[allow(clippy::type_complexity)] syncer: summit_syncer::Actor, SummitSchemeProvider, MultisigScheme>, syncer_mailbox: summit_syncer::Mailbox, Block>, finalizer: Finalizer, V>, @@ -224,7 +220,6 @@ where Self { context, application, - application_mailbox, buffer, buffer_mailbox, syncer, @@ -245,14 +240,6 @@ where /// This will also rebuild the state of the engine from provided `Journal`. pub fn start( self, - voter_network: ( - impl Sender, - impl Receiver, - ), - resolver_network: ( - impl Sender, - impl Receiver, - ), broadcast_network: ( impl Sender, impl Receiver, @@ -262,14 +249,9 @@ where impl Receiver, ), ) -> Handle<()> { - self.context.clone().spawn(|_| { - self.run( - voter_network, - resolver_network, - broadcast_network, - backfill_network, - ) - }) + self.context + .clone() + .spawn(|_| self.run(broadcast_network, backfill_network)) } /// Start the `simplex` consensus engine. @@ -277,14 +259,6 @@ where /// This will also rebuild the state of the engine from provided `Journal`. async fn run( self, - voter_network: ( - impl Sender, - impl Receiver, - ), - resolver_network: ( - impl Sender, - impl Receiver, - ), broadcast_network: ( impl Sender, impl Receiver, @@ -319,7 +293,7 @@ where let (resolver_rx, resolver) = summit_syncer::resolver::p2p::init(&self.context, resolver_config, backfill_network); - let finalizer_handle = self.finalizer.start(self.sync_height); + let finalizer_handle = self.finalizer.start(); // start the syncer let syncer_handle = self.syncer.start( self.finalizer_mailbox.clone(), diff --git a/node/src/keys.rs b/node/src/keys.rs index 0c574aaa..6a836671 100644 --- a/node/src/keys.rs +++ b/node/src/keys.rs @@ -1,7 +1,6 @@ -use crate::args::DEFAULT_KEY_PATH; use anyhow::{Context as _, Result}; use clap::{Args, Subcommand}; -use commonware_codec::{Encode, extensions::DecodeExt}; +use commonware_codec::extensions::DecodeExt; use std::io::{self, Write}; use commonware_cryptography::bls12381::PrivateKey as BlsPrivateKey; diff --git a/syncer/Cargo.toml b/syncer/Cargo.toml index a2c6a855..40ec7cdc 100644 --- a/syncer/Cargo.toml +++ b/syncer/Cargo.toml @@ -26,10 +26,11 @@ tracing.workspace = true # For metrics - activate with `prom` feature metrics = { version = "0.24.0", optional = true } +prometheus-client = { version = "0.22.3", optional = true } [dev-dependencies] tracing-subscriber = "0.3.19" [features] -prom = ["metrics"] +prom = ["metrics", "prometheus-client"] test-mocks = [] diff --git a/syncer/src/actor.rs b/syncer/src/actor.rs index 386c12d2..976d5315 100644 --- a/syncer/src/actor.rs +++ b/syncer/src/actor.rs @@ -29,7 +29,7 @@ use futures::{ }; use governor::clock::Clock as GClock; #[cfg(feature = "prom")] -use metrics::gauge::Gauge; +use prometheus_client::metrics::gauge::Gauge; use rand::{CryptoRng, Rng}; use std::{ collections::{BTreeMap, btree_map::Entry}, @@ -87,8 +87,6 @@ pub struct Actor< max_repair: u64, // Codec configuration for block type block_codec_config: B::Cfg, - // Partition prefix - partition_prefix: String, // ---------- State ---------- // Last view processed @@ -240,7 +238,6 @@ impl< view_retention_timeout: config.view_retention_timeout, max_repair: config.max_repair, block_codec_config: config.block_codec_config, - partition_prefix: config.partition_prefix, last_processed_round: Round::new(0, 0), tip: 0, block_subscriptions: BTreeMap::new(), @@ -268,7 +265,6 @@ impl< view_retention_timeout: config.view_retention_timeout, max_repair: config.max_repair, block_codec_config: config.block_codec_config, - partition_prefix: config.partition_prefix, last_processed_round: Round::new(0, 0), tip: 0, block_subscriptions: BTreeMap::new(), diff --git a/syncer/src/finalizer.rs b/syncer/src/finalizer.rs index bea1cb98..eff2507a 100644 --- a/syncer/src/finalizer.rs +++ b/syncer/src/finalizer.rs @@ -2,8 +2,6 @@ use crate::{Update, ingress::orchestrator::Orchestrator}; use commonware_consensus::simplex::signing_scheme::Scheme; use commonware_consensus::{Block, Reporter}; use commonware_runtime::{Clock, ContextCell, Handle, Metrics, Spawner, Storage, spawn_cell}; -use commonware_storage::metadata::{self, Metadata}; -use commonware_utils::{fixed_bytes, sequence::FixedBytes}; use futures::channel::oneshot; use futures::{StreamExt, channel::mpsc}; use tracing::{debug, error}; diff --git a/types/src/consensus_state.rs b/types/src/consensus_state.rs index aae56b64..5dc0efe4 100644 --- a/types/src/consensus_state.rs +++ b/types/src/consensus_state.rs @@ -133,6 +133,23 @@ impl ConsensusState { peers.sort_by(|lhs, rhs| lhs.0.cmp(&rhs.0)); peers } + + pub fn get_active_validators(&self) -> Vec<(PublicKey, bls12381::PublicKey)> { + let mut peers: Vec<(PublicKey, bls12381::PublicKey)> = self + .validator_accounts + .iter() + .filter(|(_, acc)| acc.status == ValidatorStatus::Active) + .map(|(v, acc)| { + let mut key_bytes = &v[..]; + let node_public_key = + PublicKey::read(&mut key_bytes).expect("failed to parse public key"); + let consensus_public_key = acc.consensus_public_key.clone(); + (node_public_key, consensus_public_key) + }) + .collect(); + peers.sort_by(|lhs, rhs| lhs.0.cmp(&rhs.0)); + peers + } } impl EncodeSize for ConsensusState { diff --git a/types/src/engine_client.rs b/types/src/engine_client.rs index 3cc38403..2c29dcc3 100644 --- a/types/src/engine_client.rs +++ b/types/src/engine_client.rs @@ -312,11 +312,12 @@ pub mod base_benchmarking { self.payload, execution_requests, U256::ZERO, // block_value + 0, // epoch view, - None, - [0u8; 32].into(), - Vec::new(), // added_validators - Vec::new(), // removed_validators + None, // checkpoint_hash + Digest::from([0u8; 32]), // prev_epoch_header_hash + Vec::new(), // added_validators + Vec::new(), // removed_validators ) } } @@ -446,11 +447,12 @@ pub mod benchmarking { self.payload, execution_requests, U256::ZERO, // block_value + 0, // epoch view, - None, // checkpoint_hash - [0u8; 32].into(), // prev_epoch_header_hash - Vec::new(), // added_validators - Vec::new(), // removed_validators + None, // checkpoint_hash + Digest::from([0u8; 32]), // prev_epoch_header_hash + Vec::new(), // added_validators + Vec::new(), // removed_validators ) } } diff --git a/types/src/scheme.rs b/types/src/scheme.rs index 48693f59..01050372 100644 --- a/types/src/scheme.rs +++ b/types/src/scheme.rs @@ -98,9 +98,6 @@ impl EpochSchemeProvider for SummitSchemeProvider { pub struct EpochTransition { /// The epoch to transition to. pub epoch: Epoch, - /// The dealers for the epoch (identity keys). - pub dealers: Ordered

, - /// The BLS public keys for the epoch. - /// Contains the BLS public keys corresponding to each dealer. - pub bls_keys: Vec, + /// The public keys of the validator set + pub validator_keys: Vec<(P, V::Public)>, } From e36898ac24688aa29ebd4fddbb866176dbcfd4fb Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Sun, 9 Nov 2025 16:25:42 -0500 Subject: [PATCH 42/81] feat: finalizer notifies orchestrator to shutdown simplex from last epoch --- application/src/actor.rs | 12 +++++++++++- finalizer/src/actor.rs | 27 ++++++++++++++++++++------- finalizer/src/config.rs | 6 ++++-- node/src/args.rs | 4 ++-- node/src/engine.rs | 29 ++++++++++++++--------------- orchestrator/src/actor.rs | 11 ++++++----- orchestrator/src/ingress.rs | 7 +++++-- types/src/consensus_state.rs | 10 ++++++++++ types/src/lib.rs | 2 ++ types/src/scheme.rs | 24 +++++++++++++++--------- 10 files changed, 89 insertions(+), 43 deletions(-) diff --git a/application/src/actor.rs b/application/src/actor.rs index c98c2583..2c1e453e 100644 --- a/application/src/actor.rs +++ b/application/src/actor.rs @@ -26,7 +26,7 @@ use std::{ time::Duration, }; use summit_finalizer::FinalizerMailbox; -use tracing::{error, info, warn}; +use tracing::{debug, error, info, warn}; #[cfg(feature = "prom")] use metrics::histogram; @@ -303,6 +303,16 @@ impl< histogram!("handle_proposal_aux_data_duration_millis").record(aux_data_duration); } + if aux_data.epoch != round.epoch() { + // This might happen because the finalizer notifies the orchestrator at the end of an + // epoch to shut down Simplex. While Simplex is being shutdown, it will still continue to produce blocks. + return Err(anyhow!( + "Aborting block proposal for epoch {}. Current epoch is {}", + aux_data.epoch, + aux_data.epoch + )); + } + let pending_withdrawals = aux_data.withdrawals; let checkpoint_hash = aux_data.checkpoint_hash; diff --git a/finalizer/src/actor.rs b/finalizer/src/actor.rs index cc1c67e6..687aec1e 100644 --- a/finalizer/src/actor.rs +++ b/finalizer/src/actor.rs @@ -8,7 +8,7 @@ use commonware_codec::{DecodeExt as _, ReadExt as _}; use commonware_consensus::Reporter; use commonware_consensus::simplex::signing_scheme::{Scheme, bls12381_multisig}; use commonware_consensus::simplex::types::Finalization; -use commonware_cryptography::bls12381::primitives::variant::Variant; +use commonware_cryptography::bls12381::primitives::variant::{MinPk, Variant}; use commonware_cryptography::{ Digestible, Hasher, PrivateKeyExt, Sha256, Signer, Verifier as _, bls12381, }; @@ -49,7 +49,7 @@ pub struct Finalizer< R: Storage + Metrics + Clock + Spawner + governor::clock::Clock + Rng, C: EngineClient, O: NetworkOracle, - S: Signer, + S: Signer, Z: Scheme, V: Variant, > { @@ -68,7 +68,7 @@ pub struct Finalizer< validator_withdrawal_period: u64, // in blocks validator_onboarding_limit_per_block: usize, oracle: O, - orchestrator_mailbox: summit_orchestrator::Mailbox, + orchestrator_mailbox: summit_orchestrator::Mailbox, node_public_key: PublicKey, validator_exit: bool, cancellation_token: CancellationToken, @@ -80,7 +80,7 @@ impl< R: Storage + Metrics + Clock + Spawner + governor::clock::Clock + Rng, C: EngineClient, O: NetworkOracle, - S: Signer, + S: Signer, Z: Scheme, V: Variant, > Finalizer @@ -321,7 +321,7 @@ impl< } } - // Store finalizes checkpoint to database + let mut epoch_change = false; // Store finalizes checkpoint to database if is_last_block_of_epoch(new_height, self.epoch_num_of_blocks) { let view = block.view(); @@ -406,13 +406,16 @@ impl< .collect(); self.oracle.register(self.state.epoch, network_keys).await; - // Send the new validator list to the orchestrator + // Send the new validator list to the orchestrator amd start the Simplex engine + // for the new epoch + let active_validators = self.state.get_active_validators(); self.orchestrator_mailbox .report(Message::Enter(EpochTransition { epoch: self.state.epoch, validator_keys: active_validators, })) .await; + epoch_change = true; #[cfg(feature = "prom")] let db_operations_start = Instant::now(); @@ -462,6 +465,14 @@ impl< self.height_notify_up_to(new_height); let _ = ack_tx.send(()); info!(new_height, "finalized block"); + + if epoch_change { + // Shut down the Simplex engine for the old epoch + self.orchestrator_mailbox + .report(Message::Exit(self.state.epoch - 1)) + .await; + epoch_change = false; + } } async fn parse_execution_requests(&mut self, block: &Block, new_height: u64) { @@ -746,6 +757,7 @@ impl< .state .get_next_ready_withdrawals(height, self.validator_max_withdrawals_per_block); BlockAuxData { + epoch: self.state.epoch, withdrawals: ready_withdrawals, checkpoint_hash: Some(checkpoint_hash), header_hash: prev_header_hash, @@ -755,6 +767,7 @@ impl< } } else { BlockAuxData { + epoch: self.state.epoch, withdrawals: vec![], checkpoint_hash: None, header_hash: [0; 32].into(), @@ -799,7 +812,7 @@ impl< R: Storage + Metrics + Clock + Spawner + governor::clock::Clock + Rng, C: EngineClient, O: NetworkOracle, - S: Signer, + S: Signer, Z: Scheme, V: Variant, > Drop for Finalizer diff --git a/finalizer/src/config.rs b/finalizer/src/config.rs index 16d6edfa..4d134deb 100644 --- a/finalizer/src/config.rs +++ b/finalizer/src/config.rs @@ -1,6 +1,7 @@ use commonware_cryptography::Signer; -use commonware_cryptography::bls12381::primitives::variant::Variant; +use commonware_cryptography::bls12381::primitives::variant::{MinPk, Variant}; use commonware_runtime::buffer::PoolRef; +use std::marker::PhantomData; use summit_orchestrator::Mailbox as OrchestratorMailbox; use summit_types::network_oracle::NetworkOracle; use summit_types::registry::Registry; @@ -13,7 +14,7 @@ pub struct FinalizerConfig, S: Sign pub engine_client: C, pub registry: Registry, pub oracle: O, - pub orchestrator_mailbox: OrchestratorMailbox, + pub orchestrator_mailbox: OrchestratorMailbox, pub epoch_num_of_blocks: u64, pub validator_max_withdrawals_per_block: usize, pub validator_minimum_stake: u64, // in gwei @@ -29,4 +30,5 @@ pub struct FinalizerConfig, S: Sign /// The node's own public key pub node_public_key: PublicKey, pub cancellation_token: CancellationToken, + pub _variant_marker: PhantomData, } diff --git a/node/src/args.rs b/node/src/args.rs index faf4312c..ccba3eba 100644 --- a/node/src/args.rs +++ b/node/src/args.rs @@ -355,7 +355,7 @@ impl Command { // Create network let p2p = network.start(); // create engine - let engine: Engine<_, _, _, _, bls12381::primitives::variant::MinPk> = + let engine: Engine<_, _, _, _> = Engine::new(context.with_label("engine"), config).await; let finalizer_mailbox = engine.finalizer_mailbox.clone(); @@ -533,7 +533,7 @@ pub fn run_node_with_runtime( // Create network let p2p = network.start(); // create engine - let engine: Engine<_, _, _, _, bls12381::primitives::variant::MinPk> = + let engine: Engine<_, _, _, _> = Engine::new(context.with_label("engine"), config).await; let finalizer_mailbox = engine.finalizer_mailbox.clone(); diff --git a/node/src/engine.rs b/node/src/engine.rs index d246a35e..c139331c 100644 --- a/node/src/engine.rs +++ b/node/src/engine.rs @@ -2,9 +2,9 @@ use crate::config::EngineConfig; use commonware_broadcast::buffered; use commonware_codec::{DecodeExt, Encode}; use commonware_consensus::simplex::signing_scheme::Scheme; -use commonware_cryptography::Signer; +use commonware_cryptography::{Signer, bls12381}; use commonware_cryptography::bls12381::primitives::group; -use commonware_cryptography::bls12381::primitives::variant::Variant; +use commonware_cryptography::bls12381::primitives::variant::{MinPk, Variant}; use commonware_p2p::{Blocker, Manager, Receiver, Sender, utils::requester}; use commonware_runtime::buffer::PoolRef; use commonware_runtime::{Clock, Handle, Metrics, Network, Spawner, Storage}; @@ -74,18 +74,17 @@ pub struct Engine< C: EngineClient, O: NetworkOracle + Blocker + Manager, S: Signer, - V: Variant, > { context: E, - application: summit_application::Actor, S::PublicKey, S, V>, - buffer: buffered::Engine>, - buffer_mailbox: buffered::Mailbox>, + application: summit_application::Actor, S::PublicKey, S, MinPk>, + buffer: buffered::Engine>, + buffer_mailbox: buffered::Mailbox>, #[allow(clippy::type_complexity)] - syncer: summit_syncer::Actor, SummitSchemeProvider, MultisigScheme>, - syncer_mailbox: summit_syncer::Mailbox, Block>, - finalizer: Finalizer, V>, - pub finalizer_mailbox: FinalizerMailbox, Block>, - orchestrator: summit_orchestrator::Actor>, + syncer: summit_syncer::Actor, SummitSchemeProvider, MultisigScheme>, + syncer_mailbox: summit_syncer::Mailbox, Block>, + finalizer: Finalizer, MinPk>, + pub finalizer_mailbox: FinalizerMailbox, Block>, + orchestrator: summit_orchestrator::Actor>, oracle: O, node_public_key: PublicKey, mailbox_size: usize, @@ -98,10 +97,9 @@ impl< C: EngineClient, O: NetworkOracle + Blocker + Manager, S: Signer + ZeroizeOnDrop, - V: Variant, -> Engine +> Engine where - MultisigScheme: Scheme, + MultisigScheme: Scheme, { pub async fn new(context: E, cfg: EngineConfig) -> Self { let node_keys: Vec<_> = cfg @@ -116,7 +114,7 @@ where let encoded = cfg.key_store.consensus_key.encode(); let private_scalar = group::Private::decode(&mut encoded.as_ref()) .expect("failed to extract scalar from private key"); - let scheme_provider = + let scheme_provider: SummitSchemeProvider = SummitSchemeProvider::new(cfg.key_store.node_key.clone(), private_scalar); let sync_height = cfg.initial_state.latest_height; @@ -213,6 +211,7 @@ where protocol_version: PROTOCOL_VERSION, node_public_key: cfg.key_store.node_key.public_key().clone(), cancellation_token: cancellation_token.clone(), + _variant_marker: PhantomData, }, ) .await; diff --git a/orchestrator/src/actor.rs b/orchestrator/src/actor.rs index 63d04ba7..e1424079 100644 --- a/orchestrator/src/actor.rs +++ b/orchestrator/src/actor.rs @@ -12,7 +12,7 @@ use commonware_consensus::{ types::Epoch, utils::last_block_in_epoch, }; -use commonware_cryptography::{Signer, bls12381::primitives::variant::Variant}; +use commonware_cryptography::{Signer, bls12381::primitives::variant::{MinPk, Variant}}; use commonware_macros::select; use commonware_p2p::{ Blocker, Receiver, Recipients, Sender, @@ -58,11 +58,11 @@ where E: Spawner + Metrics + Rng + CryptoRng + Clock + GClock + Storage + Network, B: Blocker, V: Variant, - C: Signer, + C: Signer, A: Automaton, Digest = Digest> + Relay, { context: ContextCell, - mailbox: mpsc::Receiver>, + mailbox: mpsc::Receiver>, application: A, oracle: B, @@ -82,10 +82,10 @@ where E: Spawner + Metrics + Rng + CryptoRng + Clock + GClock + Storage + Network, B: Blocker, V: Variant, - C: Signer, + C: Signer, A: Automaton, Digest = Digest> + Relay, { - pub fn new(context: E, config: Config) -> (Self, Mailbox) { + pub fn new(context: E, config: Config) -> (Self, Mailbox) { let (sender, mailbox) = mpsc::channel(config.mailbox_size); let pool_ref = PoolRef::new(NZUsize!(16_384), NZUsize!(10_000)); @@ -319,6 +319,7 @@ where info!(epoch, "exited epoch"); } + Message::_Phantom(_, _) => unreachable!(), } }, } diff --git a/orchestrator/src/ingress.rs b/orchestrator/src/ingress.rs index 6d9cade8..996c1d06 100644 --- a/orchestrator/src/ingress.rs +++ b/orchestrator/src/ingress.rs @@ -7,8 +7,9 @@ use summit_types::scheme::EpochTransition; /// Messages that can be sent to the orchestrator. pub enum Message { - Enter(EpochTransition), + Enter(EpochTransition), Exit(Epoch), + _Phantom(std::marker::PhantomData, std::marker::PhantomData

), } /// Inbound communication channel for epoch transitions. @@ -20,7 +21,9 @@ pub struct Mailbox { impl Mailbox { /// Create a new [Mailbox]. pub fn new(sender: mpsc::Sender>) -> Self { - Self { sender } + Self { + sender, + } } } diff --git a/types/src/consensus_state.rs b/types/src/consensus_state.rs index 5dc0efe4..d67c3ce9 100644 --- a/types/src/consensus_state.rs +++ b/types/src/consensus_state.rs @@ -150,6 +150,16 @@ impl ConsensusState { peers.sort_by(|lhs, rhs| lhs.0.cmp(&rhs.0)); peers } + + pub fn get_active_validators_as(&self) -> Vec<(PublicKey, BLS)> + where + bls12381::PublicKey: Into, + { + self.get_active_validators() + .into_iter() + .map(|(pk, bls_pk)| (pk, bls_pk.into())) + .collect() + } } impl EncodeSize for ConsensusState { diff --git a/types/src/lib.rs b/types/src/lib.rs index 616e58ed..eb05f11c 100644 --- a/types/src/lib.rs +++ b/types/src/lib.rs @@ -31,6 +31,7 @@ pub type Activity = CActivity; /// Auxiliary data needed for block construction #[derive(Debug, Clone)] pub struct BlockAuxData { + pub epoch: u64, pub withdrawals: Vec, pub checkpoint_hash: Option, pub header_hash: Digest, @@ -39,6 +40,7 @@ pub struct BlockAuxData { pub forkchoice: ForkchoiceState, } +pub use commonware_cryptography::bls12381; pub type PublicKey = commonware_cryptography::ed25519::PublicKey; pub type PrivateKey = commonware_cryptography::ed25519::PrivateKey; pub type Signature = commonware_cryptography::ed25519::Signature; diff --git a/types/src/scheme.rs b/types/src/scheme.rs index 01050372..3b89b4b4 100644 --- a/types/src/scheme.rs +++ b/types/src/scheme.rs @@ -1,7 +1,8 @@ +use commonware_codec::{DecodeExt, Encode}; use commonware_consensus::simplex::signing_scheme::{self, Scheme}; use commonware_consensus::types::Epoch; use commonware_cryptography::bls12381::primitives::group; -use commonware_cryptography::bls12381::primitives::variant::Variant; +use commonware_cryptography::bls12381::primitives::variant::{MinPk, Variant}; use commonware_cryptography::{PublicKey, Signer}; use commonware_utils::set::{Ordered, OrderedAssociated}; use std::collections::HashMap; @@ -61,7 +62,7 @@ pub trait EpochSchemeProvider { /// Returns a [Scheme] for the given [EpochTransition]. fn scheme_for_epoch( &self, - transition: &EpochTransition, + transition: &EpochTransition, ) -> Self::Scheme; } @@ -74,20 +75,25 @@ impl SchemeProvider for SummitSchemeProvider { } } -impl EpochSchemeProvider for SummitSchemeProvider { +impl, V: Variant> EpochSchemeProvider for SummitSchemeProvider +{ type Variant = V; type PublicKey = C::PublicKey; type Scheme = MultisigScheme; fn scheme_for_epoch( &self, - transition: &EpochTransition, + transition: &EpochTransition, ) -> Self::Scheme { let participants: OrderedAssociated = transition - .dealers + .validator_keys .iter() - .cloned() - .zip(transition.bls_keys.iter().cloned()) + .map(|(pk, bls_pk)| { + let minpk_public: &::Public = bls_pk.as_ref(); + let encoded = minpk_public.encode(); + let variant_pk = V::Public::decode(&mut encoded.as_ref()).expect("failed to decode BLS public key"); + (pk.clone(), variant_pk) + }) .collect(); MultisigScheme::::new(participants, self.bls_private_key.clone()) @@ -95,9 +101,9 @@ impl EpochSchemeProvider for SummitSchemeProvider { } /// A notification of an epoch transition. -pub struct EpochTransition { +pub struct EpochTransition { /// The epoch to transition to. pub epoch: Epoch, /// The public keys of the validator set - pub validator_keys: Vec<(P, V::Public)>, + pub validator_keys: Vec<(crate::PublicKey, BLS)>, } From 824a08a352ee16e90af4fc0114861f21ed724009 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Mon, 10 Nov 2025 14:08:47 -0500 Subject: [PATCH 43/81] feat: update DepositRequest type to include both keys and sigs --- finalizer/src/actor.rs | 1 - types/src/checkpoint.rs | 35 ++++-- types/src/consensus_state.rs | 7 +- types/src/execution_request.rs | 191 ++++++++++++++++++++++----------- types/src/scheme.rs | 16 ++- 5 files changed, 162 insertions(+), 88 deletions(-) diff --git a/finalizer/src/actor.rs b/finalizer/src/actor.rs index 687aec1e..af842ca0 100644 --- a/finalizer/src/actor.rs +++ b/finalizer/src/actor.rs @@ -471,7 +471,6 @@ impl< self.orchestrator_mailbox .report(Message::Exit(self.state.epoch - 1)) .await; - epoch_change = false; } } diff --git a/types/src/checkpoint.rs b/types/src/checkpoint.rs index 88c37fed..0f877ae1 100644 --- a/types/src/checkpoint.rs +++ b/types/src/checkpoint.rs @@ -179,23 +179,29 @@ mod tests { use ssz::{Decode, Encode}; // Create sample data for the populated state + let consensus_key1 = bls12381::PrivateKey::from_seed(100); let deposit1 = DepositRequest { - pubkey: parse_public_key( + node_pubkey: parse_public_key( "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a", ), + consensus_pubkey: consensus_key1.public_key(), withdrawal_credentials: [1u8; 32], amount: 32_000_000_000, // 32 ETH in gwei - signature: [42u8; 64], + node_signature: [42u8; 64], + consensus_signature: [1u8; 96], index: 100, }; + let consensus_key2 = bls12381::PrivateKey::from_seed(101); let deposit2 = DepositRequest { - pubkey: parse_public_key( + node_pubkey: parse_public_key( "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c", ), + consensus_pubkey: consensus_key2.public_key(), withdrawal_credentials: [2u8; 32], amount: 16_000_000_000, // 16 ETH in gwei - signature: [43u8; 64], + node_signature: [43u8; 64], + consensus_signature: [2u8; 96], index: 101, }; @@ -316,23 +322,29 @@ mod tests { use commonware_codec::{EncodeSize, ReadExt, Write}; // Create sample data for the populated state + let consensus_key1 = bls12381::PrivateKey::from_seed(100); let deposit1 = DepositRequest { - pubkey: parse_public_key( + node_pubkey: parse_public_key( "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a", ), + consensus_pubkey: consensus_key1.public_key(), withdrawal_credentials: [1u8; 32], amount: 32_000_000_000, // 32 ETH in gwei - signature: [42u8; 64], + node_signature: [42u8; 64], + consensus_signature: [1u8; 96], index: 100, }; + let consensus_key2 = bls12381::PrivateKey::from_seed(101); let deposit2 = DepositRequest { - pubkey: parse_public_key( + node_pubkey: parse_public_key( "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c", ), + consensus_pubkey: consensus_key2.public_key(), withdrawal_credentials: [2u8; 32], amount: 16_000_000_000, // 16 ETH in gwei - signature: [43u8; 64], + node_signature: [43u8; 64], + consensus_signature: [2u8; 96], index: 101, }; @@ -538,13 +550,16 @@ mod tests { use alloy_primitives::Address; // Create sample data for the populated state + let consensus_key1 = bls12381::PrivateKey::from_seed(100); let deposit1 = DepositRequest { - pubkey: parse_public_key( + node_pubkey: parse_public_key( "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a", ), + consensus_pubkey: consensus_key1.public_key(), withdrawal_credentials: [1u8; 32], amount: 32_000_000_000, // 32 ETH in gwei - signature: [42u8; 64], + node_signature: [42u8; 64], + consensus_signature: [1u8; 96], index: 100, }; diff --git a/types/src/consensus_state.rs b/types/src/consensus_state.rs index d67c3ce9..977081ad 100644 --- a/types/src/consensus_state.rs +++ b/types/src/consensus_state.rs @@ -342,11 +342,14 @@ mod tests { withdrawal_credentials[12 + i] = index as u8; } + let consensus_key = bls12381::PrivateKey::from_seed(index); DepositRequest { - pubkey: PublicKey::decode(&[1u8; 32][..]).unwrap(), + node_pubkey: PublicKey::decode(&[1u8; 32][..]).unwrap(), + consensus_pubkey: consensus_key.public_key(), withdrawal_credentials, amount, - signature: [index as u8; 64], + node_signature: [index as u8; 64], + consensus_signature: [index as u8; 96], index, } } diff --git a/types/src/execution_request.rs b/types/src/execution_request.rs index 8a8c313e..974d469d 100644 --- a/types/src/execution_request.rs +++ b/types/src/execution_request.rs @@ -2,7 +2,7 @@ use crate::{Digest, PublicKey}; use alloy_primitives::Address; use bytes::{Buf, BufMut}; use commonware_codec::{DecodeExt, Encode, Error, FixedSize, Read, Write}; -use commonware_cryptography::{Hasher, Sha256}; +use commonware_cryptography::{Hasher, Sha256, bls12381}; #[allow(clippy::large_enum_variant)] #[derive(Debug, Clone, PartialEq)] @@ -40,7 +40,7 @@ impl ExecutionRequest { #[derive(Debug, Clone, PartialEq)] pub struct WithdrawalRequest { pub source_address: Address, // Address that initiated the withdrawal - pub validator_pubkey: [u8; 32], // Validator BLS public key + pub validator_pubkey: [u8; 32], // Validator ed25519 public key pub amount: u64, // Amount in gwei } @@ -83,87 +83,135 @@ impl WithdrawalRequest { // https://eth2book.info/latest/part2/deposits-withdrawals/withdrawal-processing/ #[derive(Debug, Clone, PartialEq)] pub struct DepositRequest { - pub pubkey: PublicKey, // Validator ED25519 public key - pub withdrawal_credentials: [u8; 32], // Either hash of the BLS pubkey, or Ethereum address - pub amount: u64, // Amount in gwei - pub signature: [u8; 64], // ED signature + pub node_pubkey: PublicKey, // Node ED25519 public key + pub consensus_pubkey: bls12381::PublicKey, // Consensus BLS public key + pub withdrawal_credentials: [u8; 32], // Either hash of the BLS pubkey, or Ethereum address + pub amount: u64, // Amount in gwei + pub node_signature: [u8; 64], // ED25519 signature + pub consensus_signature: [u8; 96], // BLS signature pub index: u64, } impl DepositRequest { - /// This function is used to parse DepositRequest type off of an Eth block. This is different than from_bytes because the ethereum event assumes BLS - /// signature so the signature field has an extra 32 bytes and the public key has an extra 16 bytes. The ed signature and public key are left padded and put in this field instead + /// This function is used to parse the DepositRequest event from the execution layer. pub fn try_from_eth_bytes(bytes: &[u8]) -> Result { - // EIP-6110: Deposit request data is exactly 144 bytes (without leading type byte) - // Format: ed25519_pubkey(48) + withdrawal_credentials(32) + amount(8) + signature(96) + index(8) = 192 bytes + // EIP-6110 (modified): Deposit request data is exactly 288 bytes (without leading type byte) + // Format: node_pubkey(32) + consensus_pubkey(48) + withdrawal_credentials(32) + amount(8) + node_signature(64) + consensus_signature(96) + index(8) = 288 bytes - if bytes.len() != 192 { - return Err("DepositRequest must be exactly 192 bytes"); + if bytes.len() != 288 { + return Err("DepositRequest must be exactly 288 bytes"); } - // Extract ed25519_pubkey (32 bytes) left padded - let ed25519_pubkey_bytes: [u8; 32] = bytes[16..48] + // Extract node_pubkey (32 bytes ed25519) + let node_pubkey_bytes: [u8; 32] = bytes[0..32] .try_into() - .map_err(|_| "Failed to parse ed25519_pubkey")?; - let pubkey = PublicKey::decode(&ed25519_pubkey_bytes[..]) - .map_err(|_| "Invalid ed25519 public key")?; + .map_err(|_| "Failed to parse node_pubkey")?; + let node_pubkey = + PublicKey::decode(&node_pubkey_bytes[..]).map_err(|_| "Invalid ed25519 public key")?; + + // Extract consensus_pubkey (48 bytes BLS) + let consensus_pubkey_bytes: [u8; 48] = bytes[32..80] + .try_into() + .map_err(|_| "Failed to parse consensus_pubkey")?; + let consensus_pubkey = bls12381::PublicKey::decode(&consensus_pubkey_bytes[..]) + .map_err(|_| "Invalid BLS public key")?; // Extract withdrawal_credentials (32 bytes) - let withdrawal_credentials: [u8; 32] = bytes[48..80] + let withdrawal_credentials: [u8; 32] = bytes[80..112] .try_into() .map_err(|_| "Failed to parse withdrawal_credentials")?; // Extract amount (8 bytes, little-endian u64) - let amount_bytes: [u8; 8] = bytes[80..88] + let amount_bytes: [u8; 8] = bytes[112..120] .try_into() .map_err(|_| "Failed to parse amount")?; let amount = u64::from_le_bytes(amount_bytes); - // Extract signature (64 bytes left padded) - let signature: [u8; 64] = bytes[120..184] + // Extract node_signature (64 bytes ed25519) + let node_signature: [u8; 64] = bytes[120..184] .try_into() - .map_err(|_| "Failed to parse signature")?; + .map_err(|_| "Failed to parse node_signature")?; + + // Extract consensus_signature (96 bytes BLS) + let consensus_signature: [u8; 96] = bytes[184..280] + .try_into() + .map_err(|_| "Failed to parse consensus_signature")?; // Extract index (8 bytes, little-endian u64) - let index_bytes: [u8; 8] = bytes[184..192] + let index_bytes: [u8; 8] = bytes[280..288] .try_into() .map_err(|_| "Failed to parse index")?; let index = u64::from_le_bytes(index_bytes); Ok(DepositRequest { - pubkey, + node_pubkey, + consensus_pubkey, withdrawal_credentials, amount, - signature, + node_signature, + consensus_signature, index, }) } pub fn as_message(&self, domain: Digest) -> Digest { - let mut pubkey = [0u8; 32]; - pubkey.copy_from_slice(&self.pubkey); + // Hash consensus_pubkey with 16-byte padding + let mut hasher = Sha256::default(); + hasher.update(&self.consensus_pubkey.encode()); + hasher.update(&[0u8; 16]); + let consensus_pubkey_hash = hasher.finalize(); - let mut left = Vec::with_capacity(64); - left.extend_from_slice(&pubkey); - left.extend_from_slice(&self.withdrawal_credentials); + // Hash node_pubkey with consensus_pubkey_hash to get pubkey_root let mut hasher = Sha256::default(); - hasher.update(&left); + hasher.update(&self.node_pubkey.encode()); + hasher.update(&consensus_pubkey_hash); + let pubkey_root = hasher.finalize(); + + // Hash first 64 bytes of consensus_signature + let mut hasher = Sha256::default(); + hasher.update(&self.consensus_signature[0..64]); + let consensus_sig_part1 = hasher.finalize(); + + // Hash last 32 bytes of consensus_signature with 32-byte padding + let mut hasher = Sha256::default(); + hasher.update(&self.consensus_signature[64..96]); + hasher.update(&[0u8; 32]); + let consensus_sig_part2 = hasher.finalize(); + + // Combine both parts to get bls_signature_hash + let mut hasher = Sha256::default(); + hasher.update(&consensus_sig_part1); + hasher.update(&consensus_sig_part2); + let bls_signature_hash = hasher.finalize(); + + // Hash node_signature with bls_signature_hash to get signature_root + let mut hasher = Sha256::default(); + hasher.update(&self.node_signature); + hasher.update(&bls_signature_hash); + let signature_root = hasher.finalize(); + + // Hash pubkey_root with withdrawal_credentials + let mut hasher = Sha256::default(); + hasher.update(&pubkey_root); + hasher.update(&self.withdrawal_credentials); let left_hash = hasher.finalize(); - let mut right = Vec::with_capacity(64); - right.extend_from_slice(&self.amount.to_le_bytes()); - right.extend_from_slice(&[0; 56]); + // Hash amount with 24-byte padding and signature_root let mut hasher = Sha256::default(); - hasher.update(&right); + hasher.update(&self.amount.to_le_bytes()); + hasher.update(&[0u8; 24]); + hasher.update(&signature_root); let right_hash = hasher.finalize(); + // Combine to get node hash let mut hasher = Sha256::default(); hasher.update(&left_hash); hasher.update(&right_hash); - let root_hash = hasher.finalize(); + let node_hash = hasher.finalize(); + // Final hash with domain let mut hasher = Sha256::default(); - hasher.update(&root_hash); + hasher.update(&node_hash); hasher.update(&domain); hasher.finalize() } @@ -252,37 +300,38 @@ impl Read for WithdrawalRequest { impl Write for DepositRequest { fn write(&self, buf: &mut impl BufMut) { - // padding for pubkey since eth puts pub key as 48 bytes in event - buf.put(&[0; 16][..]); - buf.put(&self.pubkey.encode()[..]); + buf.put(&self.node_pubkey.encode()[..]); + buf.put(&self.consensus_pubkey.encode()[..]); buf.put(&self.withdrawal_credentials[..]); buf.put(&self.amount.to_le_bytes()[..]); - // padding for sig - buf.put(&[0; 32][..]); - buf.put(&self.signature[..]); + buf.put(&self.node_signature[..]); + buf.put(&self.consensus_signature[..]); buf.put(&self.index.to_le_bytes()[..]) } } impl FixedSize for DepositRequest { - const SIZE: usize = 192; // 48 + 32 + 8 + 96 + 8 + const SIZE: usize = 288; // 32 + 48 + 32 + 8 + 64 + 96 + 8 } impl Read for DepositRequest { type Cfg = (); fn read_cfg(buf: &mut impl Buf, _cfg: &Self::Cfg) -> Result { - if buf.remaining() < 192 { + if buf.remaining() < 288 { return Err(Error::Invalid("DepositRequest", "Insufficient bytes")); } - // account for padding on pub key - buf.advance(16); - let mut ed25519_pubkey_bytes = [0u8; 32]; - buf.copy_to_slice(&mut ed25519_pubkey_bytes); - let pubkey = PublicKey::decode(&ed25519_pubkey_bytes[..]) + let mut node_pubkey_bytes = [0u8; 32]; + buf.copy_to_slice(&mut node_pubkey_bytes); + let node_pubkey = PublicKey::decode(&node_pubkey_bytes[..]) .map_err(|_| Error::Invalid("DepositRequest", "Invalid ed25519 public key"))?; + let mut consensus_pubkey_bytes = [0u8; 48]; + buf.copy_to_slice(&mut consensus_pubkey_bytes); + let consensus_pubkey = bls12381::PublicKey::decode(&consensus_pubkey_bytes[..]) + .map_err(|_| Error::Invalid("DepositRequest", "Invalid BLS public key"))?; + let mut withdrawal_credentials = [0u8; 32]; buf.copy_to_slice(&mut withdrawal_credentials); @@ -290,21 +339,23 @@ impl Read for DepositRequest { buf.copy_to_slice(&mut amount_bytes); let amount = u64::from_le_bytes(amount_bytes); - // account for padding on signature - buf.advance(32); + let mut node_signature = [0u8; 64]; + buf.copy_to_slice(&mut node_signature); - let mut signature = [0u8; 64]; - buf.copy_to_slice(&mut signature); + let mut consensus_signature = [0u8; 96]; + buf.copy_to_slice(&mut consensus_signature); let mut index_bytes = [0u8; 8]; buf.copy_to_slice(&mut index_bytes); let index = u64::from_le_bytes(index_bytes); Ok(DepositRequest { - pubkey, + node_pubkey, + consensus_pubkey, withdrawal_credentials, amount, - signature, + node_signature, + consensus_signature, index, }) } @@ -315,21 +366,25 @@ mod tests { use super::*; use bytes::BytesMut; use commonware_codec::{ReadExt, Write}; + use commonware_cryptography::{PrivateKeyExt, Signer}; #[test] fn test_deposit_request_codec() { + let consensus_private_key = bls12381::PrivateKey::from_seed(1); let deposit = DepositRequest { - pubkey: PublicKey::decode(&[1u8; 32][..]).unwrap(), + node_pubkey: PublicKey::decode(&[1u8; 32][..]).unwrap(), + consensus_pubkey: consensus_private_key.public_key(), withdrawal_credentials: [3u8; 32], amount: 32000000000u64, // 32 ETH in gwei - signature: [4u8; 64], + node_signature: [4u8; 64], + consensus_signature: [5u8; 96], index: 42u64, }; // Test Write let mut buf = BytesMut::new(); deposit.write(&mut buf); - assert_eq!(buf.len(), 192); // 48 + 32 + 8 + 96 + 8 + assert_eq!(buf.len(), 288); // 32 + 48 + 32 + 8 + 64 + 96 + 8 // Test Read let decoded = DepositRequest::read(&mut buf.as_ref()).unwrap(); @@ -356,11 +411,14 @@ mod tests { #[test] fn test_execution_request_deposit_codec() { + let consensus_private_key = bls12381::PrivateKey::from_seed(2); let deposit = DepositRequest { - pubkey: PublicKey::decode(&[6u8; 32][..]).unwrap(), + node_pubkey: PublicKey::decode(&[6u8; 32][..]).unwrap(), + consensus_pubkey: consensus_private_key.public_key(), withdrawal_credentials: [8u8; 32], amount: 32000000000u64, - signature: [9u8; 64], + node_signature: [9u8; 64], + consensus_signature: [10u8; 96], index: 123u64, }; let exec_request = ExecutionRequest::Deposit(deposit.clone()); @@ -368,7 +426,7 @@ mod tests { // Test Write let mut buf = BytesMut::new(); exec_request.write(&mut buf); - assert_eq!(buf.len(), 193); // 1 (type) + 192 (deposit) + assert_eq!(buf.len(), 289); // 1 (type) + 288 (deposit) assert_eq!(buf[0], 0x00); // Deposit type byte // Test Read @@ -438,7 +496,7 @@ mod tests { #[test] fn test_deposit_request_insufficient_bytes() { let mut buf = BytesMut::new(); - buf.put(&[0u8; 191][..]); // One byte short + buf.put(&[0u8; 287][..]); // One byte short let result = DepositRequest::read(&mut buf.as_ref()); assert!(result.is_err()); @@ -468,11 +526,14 @@ mod tests { #[test] fn test_roundtrip_compatibility_with_try_from() { // Test that our Codec implementation is compatible with existing TryFrom<&[u8]> + let consensus_private_key = bls12381::PrivateKey::from_seed(3); let deposit = DepositRequest { - pubkey: PublicKey::decode(&[11u8; 32][..]).unwrap(), + node_pubkey: PublicKey::decode(&[11u8; 32][..]).unwrap(), + consensus_pubkey: consensus_private_key.public_key(), withdrawal_credentials: [13u8; 32], amount: 64000000000u64, - signature: [14u8; 64], + node_signature: [14u8; 64], + consensus_signature: [15u8; 96], index: 999u64, }; let exec_request = ExecutionRequest::Deposit(deposit); diff --git a/types/src/scheme.rs b/types/src/scheme.rs index 3b89b4b4..9ac91a73 100644 --- a/types/src/scheme.rs +++ b/types/src/scheme.rs @@ -60,10 +60,7 @@ pub trait EpochSchemeProvider { type Scheme: Scheme; /// Returns a [Scheme] for the given [EpochTransition]. - fn scheme_for_epoch( - &self, - transition: &EpochTransition, - ) -> Self::Scheme; + fn scheme_for_epoch(&self, transition: &EpochTransition) -> Self::Scheme; } impl SchemeProvider for SummitSchemeProvider { @@ -75,23 +72,22 @@ impl SchemeProvider for SummitSchemeProvider { } } -impl, V: Variant> EpochSchemeProvider for SummitSchemeProvider +impl, V: Variant> EpochSchemeProvider + for SummitSchemeProvider { type Variant = V; type PublicKey = C::PublicKey; type Scheme = MultisigScheme; - fn scheme_for_epoch( - &self, - transition: &EpochTransition, - ) -> Self::Scheme { + fn scheme_for_epoch(&self, transition: &EpochTransition) -> Self::Scheme { let participants: OrderedAssociated = transition .validator_keys .iter() .map(|(pk, bls_pk)| { let minpk_public: &::Public = bls_pk.as_ref(); let encoded = minpk_public.encode(); - let variant_pk = V::Public::decode(&mut encoded.as_ref()).expect("failed to decode BLS public key"); + let variant_pk = V::Public::decode(&mut encoded.as_ref()) + .expect("failed to decode BLS public key"); (pk.clone(), variant_pk) }) .collect(); From af8052f1e1cb72491172ee128a5df1441207dcbf Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Mon, 10 Nov 2025 14:57:13 -0500 Subject: [PATCH 44/81] feat: store BLS pubkey from deposit req and verify sig --- finalizer/src/actor.rs | 57 ++++++++++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/finalizer/src/actor.rs b/finalizer/src/actor.rs index af842ca0..d926ea95 100644 --- a/finalizer/src/actor.rs +++ b/finalizer/src/actor.rs @@ -4,7 +4,7 @@ use alloy_eips::eip4895::Withdrawal; use alloy_primitives::Address; #[cfg(debug_assertions)] use alloy_rpc_types_engine::ForkchoiceState; -use commonware_codec::{DecodeExt as _, ReadExt as _}; +use commonware_codec::{DecodeExt as _, Encode, ReadExt as _}; use commonware_consensus::Reporter; use commonware_consensus::simplex::signing_scheme::{Scheme, bls12381_multisig}; use commonware_consensus::simplex::types::Finalization; @@ -482,29 +482,56 @@ impl< ExecutionRequest::Deposit(deposit_request) => { let message = deposit_request.as_message(self.protocol_version_digest); - let mut signature_bytes = &deposit_request.signature[..]; - let Ok(signature) = Signature::read(&mut signature_bytes) else { + let mut node_signature_bytes = &deposit_request.node_signature[..]; + let Ok(node_signature) = Signature::read(&mut node_signature_bytes) else { info!( - "Failed to parse signature from deposit request: {deposit_request:?}" + "Failed to parse node signature from deposit request: {deposit_request:?}" ); continue; // Skip this deposit request }; - if !deposit_request.pubkey.verify(None, &message, &signature) { + if !deposit_request.node_pubkey.verify(None, &message, &node_signature) { #[cfg(debug_assertions)] { let gauge: Gauge = Gauge::default(); gauge.set(new_height as i64); self.context.register( format!( - "{}_deposit_request_invalid_sig", - hex::encode(&deposit_request.pubkey) + "{}_deposit_request_invalid_node_sig", + hex::encode(&deposit_request.node_pubkey) ), "height", gauge, ); } info!( - "Failed to verify signature from deposit request: {deposit_request:?}" + "Failed to verify node signature from deposit request: {deposit_request:?}" + ); + continue; // Skip this deposit request + } + + let mut consensus_signature_bytes = &deposit_request.consensus_signature[..]; + let Ok(consensus_signature) = bls12381::Signature::read(&mut consensus_signature_bytes) else { + info!( + "Failed to parse consensus signature from deposit request: {deposit_request:?}" + ); + continue; // Skip this deposit request + }; + if !deposit_request.consensus_pubkey.verify(None, &message, &consensus_signature) { + #[cfg(debug_assertions)] + { + let gauge: Gauge = Gauge::default(); + gauge.set(new_height as i64); + self.context.register( + format!( + "{}_deposit_request_invalid_consensus_sig", + hex::encode(&deposit_request.consensus_pubkey) + ), + "height", + gauge, + ); + } + info!( + "Failed to verify consensus signature from deposit request: {deposit_request:?}" ); continue; // Skip this deposit request } @@ -576,7 +603,7 @@ impl< let mut account_exists = false; if let Some(mut account) = self .state - .get_account(request.pubkey.as_ref().try_into().unwrap()) + .get_account(request.node_pubkey.as_ref().try_into().unwrap()) .cloned() { if request.index > account.last_deposit_index { @@ -590,7 +617,7 @@ impl< account.last_deposit_index = request.index; validator_balance = account.balance; self.state - .set_account(request.pubkey.as_ref().try_into().unwrap(), account); + .set_account(request.node_pubkey.as_ref().try_into().unwrap(), account); account_exists = true; } } else { @@ -623,10 +650,8 @@ impl< } // Create new ValidatorAccount from DepositRequest - // TODO(matthias): use the actual BLS key - let dummy_key = bls12381::PrivateKey::from_seed(0); let new_account = ValidatorAccount { - consensus_public_key: dummy_key.public_key(), + consensus_public_key: request.consensus_pubkey.clone(), withdrawal_credentials: Address::from_slice( &request.withdrawal_credentials[12..32], ), // Take last 20 bytes @@ -636,13 +661,13 @@ impl< last_deposit_index: request.index, }; self.state - .set_account(request.pubkey.as_ref().try_into().unwrap(), new_account); + .set_account(request.node_pubkey.as_ref().try_into().unwrap(), new_account); validator_balance = request.amount; } if !account_exists && validator_balance >= self.validator_minimum_stake { // If the node shuts down, before the account changes are committed, // then everything should work normally, because the registry is not persisted to disk - self.state.added_validators.push(request.pubkey.clone()); + self.state.added_validators.push(request.node_pubkey.clone()); } #[cfg(debug_assertions)] { @@ -651,7 +676,7 @@ impl< self.context.register( format!("{}{}{}_deposit_validator_balance", !account_exists && validator_balance >= self.validator_minimum_stake, - hex::encode(request.withdrawal_credentials), hex::encode(request.pubkey)), + hex::encode(request.withdrawal_credentials), hex::encode(request.node_pubkey.encode())), "Validator balance", gauge ); From 6bd60609cf814529d795ea87ac24084eb24788ab Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Mon, 10 Nov 2025 15:53:35 -0500 Subject: [PATCH 45/81] chore: fix compile issues in binaries --- node/src/bin/stake_and_checkpoint.rs | 179 +++++++++++++++++---------- 1 file changed, 116 insertions(+), 63 deletions(-) diff --git a/node/src/bin/stake_and_checkpoint.rs b/node/src/bin/stake_and_checkpoint.rs index be897418..7a2c5d97 100644 --- a/node/src/bin/stake_and_checkpoint.rs +++ b/node/src/bin/stake_and_checkpoint.rs @@ -17,7 +17,7 @@ use alloy::signers::local::PrivateKeySigner; use alloy_primitives::{Address, U256, keccak256}; use clap::Parser; use commonware_cryptography::Sha256; -use commonware_cryptography::{Hasher, PrivateKeyExt, Signer, ed25519::PrivateKey}; +use commonware_cryptography::{Hasher, PrivateKeyExt, Signer, bls12381, ed25519::PrivateKey}; use commonware_runtime::{Clock, Metrics as _, Runner as _, Spawner as _, tokio as cw_tokio}; use commonware_utils::from_hex_formatted; use futures::{FutureExt, pin_mut}; @@ -237,10 +237,15 @@ fn main() -> Result<(), Box> { // Create test deposit parameters // Generate a deterministic ed25519 key pair and get the public key + // Generate node (ed25519) keys let ed25519_private_key = PrivateKey::from_seed(100); let ed25519_public_key = ed25519_private_key.public_key(); let ed25519_pubkey_bytes: [u8; 32] = ed25519_public_key.to_vec().try_into().unwrap(); + // Generate consensus (BLS) keys + let bls_private_key = bls12381::PrivateKey::from_seed(100); + let bls_public_key = bls_private_key.public_key(); + // Withdrawal credentials (32 bytes) - 0x01 prefix for execution address withdrawal // Format: 0x01 || 0x00...00 (11 bytes) || execution_address (20 bytes) let mut withdrawal_credentials = [0u8; 32]; @@ -251,45 +256,47 @@ fn main() -> Result<(), Box> { Address::from_hex("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266").unwrap(); withdrawal_credentials[12..32].copy_from_slice(withdrawal_address.as_slice()); - // Generate a random BLS signature (96 bytes) - for testing purposes only - let amount = VALIDATOR_MINIMUM_STAKE; let deposit_request = DepositRequest { - pubkey: ed25519_public_key, + node_pubkey: ed25519_public_key, + consensus_pubkey: bls_public_key.clone(), withdrawal_credentials, amount, - signature: [0; 64], + node_signature: [0; 64], + consensus_signature: [0; 96], index: 0, // not included in the signature }; let protocol_version_digest = Sha256::hash(&PROTOCOL_VERSION.to_le_bytes()); let message = deposit_request.as_message(protocol_version_digest); - //let signature: [u8; 64] = ed25519_private_key.sign(None, &message).as_ref().try_into().unwrap(); - let signature = ed25519_private_key.sign(None, &message); - let mut padded_signature = [0u8; 96]; - padded_signature[32..96].copy_from_slice(signature.as_ref()); - - /* - pub struct DepositRequest { - pub pubkey: PublicKey, // Validator ED25519 public key - pub withdrawal_credentials: [u8; 32], // Either hash of the BLS pubkey, or Ethereum address - pub amount: u64, // Amount in gwei - pub signature: [u8; 64], // ED signature - pub index: u64, - } - */ + + // Sign with node (ed25519) key + let node_signature = ed25519_private_key.sign(None, &message); + let mut padded_node_signature = [0u8; 96]; + padded_node_signature[32..96].copy_from_slice(node_signature.as_ref()); + + // Sign with consensus (BLS) key + let consensus_signature = bls_private_key.sign(None, &message); + let mut padded_consensus_signature = [0u8; 96]; + padded_consensus_signature[..96].copy_from_slice(consensus_signature.as_ref()); // Convert VALIDATOR_MINIMUM_STAKE (in gwei) to wei let deposit_amount = U256::from(amount) * U256::from(1_000_000_000u64); // gwei to wei + // Get BLS public key bytes + use commonware_codec::Encode; + let bls_pubkey_bytes: [u8; 48] = bls_public_key.encode().as_ref()[..48].try_into().unwrap(); + send_deposit_transaction( &provider, deposit_contract, deposit_amount, &ed25519_pubkey_bytes, + &bls_pubkey_bytes, &withdrawal_credentials, - &padded_signature, + &padded_node_signature, + &padded_consensus_signature, 0, // nonce ) .await @@ -629,43 +636,54 @@ async fn get_checkpoint(rpc_port: u16) -> Result, Box( provider: &P, deposit_contract_address: Address, deposit_amount: U256, - ed25519_pubkey: &[u8; 32], + node_pubkey: &[u8; 32], + consensus_pubkey: &[u8; 48], withdrawal_credentials: &[u8; 32], - signature: &[u8; 96], + node_signature: &[u8; 96], + consensus_signature: &[u8; 96], nonce: u64, ) -> Result<(), Box> where P: Provider + WalletProvider, { - // Left-pad ed25519 key to 48 bytes for the contract (prepend zeros) - let mut padded_pubkey = [0u8; 48]; - padded_pubkey[16..48].copy_from_slice(ed25519_pubkey); - // Compute the correct deposit data root for this transaction let deposit_data_root = compute_deposit_data_root( - ed25519_pubkey, + node_pubkey, + consensus_pubkey, withdrawal_credentials, deposit_amount, - signature, + node_signature, + consensus_signature, ); - // Create deposit function call data: deposit(bytes,bytes,bytes,bytes32) - let function_selector = &keccak256("deposit(bytes,bytes,bytes,bytes32)")[0..4]; + // Create deposit function call data: deposit(bytes,bytes,bytes,bytes,bytes,bytes32) + let function_selector = &keccak256("deposit(bytes,bytes,bytes,bytes,bytes,bytes32)")[0..4]; let mut call_data = function_selector.to_vec(); - // ABI encode parameters - calculate offsets for 4 parameters (3 dynamic + 1 fixed) - let offset_to_pubkey = 4 * 32; - let offset_to_withdrawal_creds = offset_to_pubkey + 32 + padded_pubkey.len().div_ceil(32) * 32; - let offset_to_signature = + // ABI encode parameters - calculate offsets for 6 parameters (5 dynamic + 1 fixed) + // Offsets start after the 6 parameter slots (6 * 32 bytes) + let offset_to_node_pubkey = 6 * 32; + let offset_to_consensus_pubkey = + offset_to_node_pubkey + 32 + node_pubkey.len().div_ceil(32) * 32; + let offset_to_withdrawal_creds = + offset_to_consensus_pubkey + 32 + consensus_pubkey.len().div_ceil(32) * 32; + let offset_to_node_signature = offset_to_withdrawal_creds + 32 + withdrawal_credentials.len().div_ceil(32) * 32; + let offset_to_consensus_signature = + offset_to_node_signature + 32 + node_signature.len().div_ceil(32) * 32; // Add parameter offsets let mut offset_bytes = vec![0u8; 32]; - offset_bytes[28..32].copy_from_slice(&(offset_to_pubkey as u32).to_be_bytes()); + offset_bytes[28..32].copy_from_slice(&(offset_to_node_pubkey as u32).to_be_bytes()); + call_data.extend_from_slice(&offset_bytes); + + offset_bytes.fill(0); + offset_bytes[28..32].copy_from_slice(&(offset_to_consensus_pubkey as u32).to_be_bytes()); call_data.extend_from_slice(&offset_bytes); offset_bytes.fill(0); @@ -673,7 +691,11 @@ where call_data.extend_from_slice(&offset_bytes); offset_bytes.fill(0); - offset_bytes[28..32].copy_from_slice(&(offset_to_signature as u32).to_be_bytes()); + offset_bytes[28..32].copy_from_slice(&(offset_to_node_signature as u32).to_be_bytes()); + call_data.extend_from_slice(&offset_bytes); + + offset_bytes.fill(0); + offset_bytes[28..32].copy_from_slice(&(offset_to_consensus_signature as u32).to_be_bytes()); call_data.extend_from_slice(&offset_bytes); // Add the fixed bytes32 parameter (deposit_data_root) @@ -682,23 +704,35 @@ where // Add dynamic data let mut length_bytes = [0u8; 32]; - // Padded pubkey (48 bytes) - already padded to 48, need to pad to next 32-byte boundary (64) - length_bytes[28..32].copy_from_slice(&(padded_pubkey.len() as u32).to_be_bytes()); + // Node pubkey (32 bytes ed25519) + length_bytes[28..32].copy_from_slice(&(node_pubkey.len() as u32).to_be_bytes()); call_data.extend_from_slice(&length_bytes); - call_data.extend_from_slice(&padded_pubkey); + call_data.extend_from_slice(node_pubkey); + + // Consensus pubkey (48 bytes BLS) + length_bytes.fill(0); + length_bytes[28..32].copy_from_slice(&(consensus_pubkey.len() as u32).to_be_bytes()); + call_data.extend_from_slice(&length_bytes); + call_data.extend_from_slice(consensus_pubkey); call_data.extend_from_slice(&[0u8; 16]); // Pad 48 to 64 bytes (next 32-byte boundary) - // Withdrawal credentials (32 bytes) - already aligned + // Withdrawal credentials (32 bytes) length_bytes.fill(0); length_bytes[28..32].copy_from_slice(&(withdrawal_credentials.len() as u32).to_be_bytes()); call_data.extend_from_slice(&length_bytes); call_data.extend_from_slice(withdrawal_credentials); - // Signature (96 bytes) - already aligned to 32-byte boundary + // Node signature (96 bytes ed25519 padded) + length_bytes.fill(0); + length_bytes[28..32].copy_from_slice(&(node_signature.len() as u32).to_be_bytes()); + call_data.extend_from_slice(&length_bytes); + call_data.extend_from_slice(node_signature); + + // Consensus signature (96 bytes BLS) length_bytes.fill(0); - length_bytes[28..32].copy_from_slice(&(signature.len() as u32).to_be_bytes()); + length_bytes[28..32].copy_from_slice(&(consensus_signature.len() as u32).to_be_bytes()); call_data.extend_from_slice(&length_bytes); - call_data.extend_from_slice(signature); + call_data.extend_from_slice(consensus_signature); let tx_request = TransactionRequest::default() .with_to(deposit_contract_address) @@ -724,46 +758,65 @@ where } fn compute_deposit_data_root( - ed25519_pubkey: &[u8; 32], + node_pubkey: &[u8; 32], + consensus_pubkey: &[u8; 48], withdrawal_credentials: &[u8; 32], amount: U256, - signature: &[u8; 96], + node_signature: &[u8; 96], + consensus_signature: &[u8; 96], ) -> [u8; 32] { /* - bytes32 pubkey_root = sha256(abi.encodePacked(pubkey, bytes16(0))); - bytes32 signature_root = sha256(abi.encodePacked( - sha256(abi.encodePacked(signature[:64])), - sha256(abi.encodePacked(signature[64:], bytes32(0))) + Solidity computation: + bytes32 consensus_pubkey_hash = sha256(abi.encodePacked(consensus_pubkey, bytes16(0))); + bytes32 pubkey_root = sha256(abi.encodePacked(node_pubkey, consensus_pubkey_hash)); + bytes32 node_signature_hash = sha256(node_signature); + bytes32 consensus_signature_hash = sha256(abi.encodePacked( + sha256(abi.encodePacked(consensus_signature[:64])), + sha256(abi.encodePacked(consensus_signature[64:], bytes32(0))) )); + bytes32 signature_root = sha256(abi.encodePacked(node_signature_hash, consensus_signature_hash)); bytes32 node = sha256(abi.encodePacked( sha256(abi.encodePacked(pubkey_root, withdrawal_credentials)), sha256(abi.encodePacked(amount, bytes24(0), signature_root)) )); - */ - - // Left-pad ed25519 key to 48 bytes (prepend zeros) - let mut padded_pubkey = [0u8; 48]; - padded_pubkey[16..48].copy_from_slice(ed25519_pubkey); + */ - // 1. pubkey_root = sha256(padded_pubkey || bytes16(0)) + // 1. consensus_pubkey_hash = sha256(consensus_pubkey || bytes16(0)) let mut hasher = Sha256::new(); - hasher.update(&padded_pubkey); + hasher.update(consensus_pubkey); hasher.update(&[0u8; 16]); // bytes16(0) + let consensus_pubkey_hash = hasher.finalize(); + + // 2. pubkey_root = sha256(node_pubkey || consensus_pubkey_hash) + let mut hasher = Sha256::new(); + hasher.update(node_pubkey); + hasher.update(&consensus_pubkey_hash); let pubkey_root = hasher.finalize(); - // 2. signature_root = sha256(sha256(signature[0:64]) || sha256(signature[64:96] || bytes32(0))) + // 3. node_signature_hash = sha256(node_signature) + let mut hasher = Sha256::new(); + hasher.update(node_signature); + let node_signature_hash = hasher.finalize(); + + // 4. consensus_signature_hash = sha256(sha256(consensus_signature[0:64]) || sha256(consensus_signature[64:96] || bytes32(0))) let mut hasher = Sha256::new(); - hasher.update(&signature[0..64]); - let sig_part1 = hasher.finalize(); + hasher.update(&consensus_signature[0..64]); + let consensus_sig_part1 = hasher.finalize(); let mut hasher = Sha256::new(); - hasher.update(&signature[64..96]); + hasher.update(&consensus_signature[64..96]); hasher.update(&[0u8; 32]); // bytes32(0) - let sig_part2 = hasher.finalize(); + let consensus_sig_part2 = hasher.finalize(); + + let mut hasher = Sha256::new(); + hasher.update(&consensus_sig_part1); + hasher.update(&consensus_sig_part2); + let consensus_signature_hash = hasher.finalize(); + // 5. signature_root = sha256(node_signature_hash || consensus_signature_hash) let mut hasher = Sha256::new(); - hasher.update(&sig_part1); - hasher.update(&sig_part2); + hasher.update(&node_signature_hash); + hasher.update(&consensus_signature_hash); let signature_root = hasher.finalize(); // 3. Convert amount to 8-byte little-endian (gwei) From 2a2d011ff1340dd4102cd9ec9ab4543cebe52fc9 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Mon, 10 Nov 2025 15:53:53 -0500 Subject: [PATCH 46/81] chore: clippy --- application/src/actor.rs | 2 +- finalizer/src/actor.rs | 50 +++++++------ finalizer/src/config.rs | 2 - node/src/args.rs | 61 ++++++++++++++-- node/src/config.rs | 8 +- node/src/engine.rs | 81 ++++++++++++++++----- node/src/keys.rs | 5 -- node/src/prom/recorder.rs | 1 - node/src/test_harness/common.rs | 25 +++++-- node/src/test_harness/mock_engine_client.rs | 3 + node/src/tests/checkpointing.rs | 78 ++++++++++++++++---- node/src/tests/execution_requests.rs | 79 ++++++++++++++++---- node/src/tests/syncer.rs | 44 +++++++++-- orchestrator/src/actor.rs | 5 +- orchestrator/src/ingress.rs | 4 +- types/src/execution_request.rs | 63 ++++++---------- types/src/genesis.rs | 1 + types/src/reth.rs | 4 + types/src/scheme.rs | 6 +- 19 files changed, 372 insertions(+), 150 deletions(-) diff --git a/application/src/actor.rs b/application/src/actor.rs index 2c1e453e..b4f00d0b 100644 --- a/application/src/actor.rs +++ b/application/src/actor.rs @@ -26,7 +26,7 @@ use std::{ time::Duration, }; use summit_finalizer::FinalizerMailbox; -use tracing::{debug, error, info, warn}; +use tracing::{error, info, warn}; #[cfg(feature = "prom")] use metrics::histogram; diff --git a/finalizer/src/actor.rs b/finalizer/src/actor.rs index d926ea95..cab7903f 100644 --- a/finalizer/src/actor.rs +++ b/finalizer/src/actor.rs @@ -9,10 +9,7 @@ use commonware_consensus::Reporter; use commonware_consensus::simplex::signing_scheme::{Scheme, bls12381_multisig}; use commonware_consensus::simplex::types::Finalization; use commonware_cryptography::bls12381::primitives::variant::{MinPk, Variant}; -use commonware_cryptography::{ - Digestible, Hasher, PrivateKeyExt, Sha256, Signer, Verifier as _, bls12381, -}; -use commonware_p2p::Manager; +use commonware_cryptography::{Digestible, Hasher, Sha256, Signer, Verifier as _, bls12381}; use commonware_runtime::{Clock, ContextCell, Handle, Metrics, Spawner, Storage, spawn_cell}; use commonware_storage::translator::TwoCap; use commonware_utils::{NZU64, NZUsize, hex}; @@ -34,7 +31,6 @@ use summit_types::checkpoint::Checkpoint; use summit_types::consensus_state_query::{ConsensusStateRequest, ConsensusStateResponse}; use summit_types::execution_request::ExecutionRequest; use summit_types::network_oracle::NetworkOracle; -use summit_types::registry::Registry; use summit_types::scheme::EpochTransition; use summit_types::utils::{is_last_block_of_epoch, is_penultimate_block_of_epoch}; use summit_types::{Block, BlockAuxData, Digest, FinalizedHeader, PublicKey, Signature}; @@ -43,7 +39,6 @@ use tokio_util::sync::CancellationToken; use tracing::{info, warn}; const WRITE_BUFFER: NonZero = NZUsize!(1024 * 1024); -const REGISTRY_CHANGE_VIEW_DELTA: u64 = 5; pub struct Finalizer< R: Storage + Metrics + Clock + Spawner + governor::clock::Clock + Rng, @@ -57,7 +52,6 @@ pub struct Finalizer< pending_height_notifys: BTreeMap>>, context: ContextCell, engine_client: C, - registry: Registry, db: FinalizerState, state: ConsensusState, genesis_hash: [u8; 32], @@ -122,7 +116,6 @@ impl< oracle: cfg.oracle, orchestrator_mailbox: cfg.orchestrator_mailbox, pending_height_notifys: BTreeMap::new(), - registry: cfg.registry, epoch_num_of_blocks: cfg.epoch_num_of_blocks, db, state, @@ -323,8 +316,6 @@ impl< let mut epoch_change = false; // Store finalizes checkpoint to database if is_last_block_of_epoch(new_height, self.epoch_num_of_blocks) { - let view = block.view(); - // Increment epoch self.state.epoch += 1; @@ -381,7 +372,7 @@ impl< for key in self.state.removed_validators.iter() { // TODO(matthias): I think this is not necessary. Inactive accounts will be removed after withdrawing. let key_bytes: [u8; 32] = key.as_ref().try_into().unwrap(); - if let Some(mut account) = self.state.validator_accounts.get_mut(&key_bytes) { + if let Some(account) = self.state.validator_accounts.get_mut(&key_bytes) { account.status = ValidatorStatus::Inactive; } } @@ -483,13 +474,17 @@ impl< let message = deposit_request.as_message(self.protocol_version_digest); let mut node_signature_bytes = &deposit_request.node_signature[..]; - let Ok(node_signature) = Signature::read(&mut node_signature_bytes) else { + let Ok(node_signature) = Signature::read(&mut node_signature_bytes) + else { info!( "Failed to parse node signature from deposit request: {deposit_request:?}" ); continue; // Skip this deposit request }; - if !deposit_request.node_pubkey.verify(None, &message, &node_signature) { + if !deposit_request + .node_pubkey + .verify(None, &message, &node_signature) + { #[cfg(debug_assertions)] { let gauge: Gauge = Gauge::default(); @@ -509,14 +504,21 @@ impl< continue; // Skip this deposit request } - let mut consensus_signature_bytes = &deposit_request.consensus_signature[..]; - let Ok(consensus_signature) = bls12381::Signature::read(&mut consensus_signature_bytes) else { + let mut consensus_signature_bytes = + &deposit_request.consensus_signature[..]; + let Ok(consensus_signature) = + bls12381::Signature::read(&mut consensus_signature_bytes) + else { info!( "Failed to parse consensus signature from deposit request: {deposit_request:?}" ); continue; // Skip this deposit request }; - if !deposit_request.consensus_pubkey.verify(None, &message, &consensus_signature) { + if !deposit_request.consensus_pubkey.verify( + None, + &message, + &consensus_signature, + ) { #[cfg(debug_assertions)] { let gauge: Gauge = Gauge::default(); @@ -616,8 +618,10 @@ impl< } account.last_deposit_index = request.index; validator_balance = account.balance; - self.state - .set_account(request.node_pubkey.as_ref().try_into().unwrap(), account); + self.state.set_account( + request.node_pubkey.as_ref().try_into().unwrap(), + account, + ); account_exists = true; } } else { @@ -660,14 +664,18 @@ impl< status: ValidatorStatus::Inactive, last_deposit_index: request.index, }; - self.state - .set_account(request.node_pubkey.as_ref().try_into().unwrap(), new_account); + self.state.set_account( + request.node_pubkey.as_ref().try_into().unwrap(), + new_account, + ); validator_balance = request.amount; } if !account_exists && validator_balance >= self.validator_minimum_stake { // If the node shuts down, before the account changes are committed, // then everything should work normally, because the registry is not persisted to disk - self.state.added_validators.push(request.node_pubkey.clone()); + self.state + .added_validators + .push(request.node_pubkey.clone()); } #[cfg(debug_assertions)] { diff --git a/finalizer/src/config.rs b/finalizer/src/config.rs index 4d134deb..942798a4 100644 --- a/finalizer/src/config.rs +++ b/finalizer/src/config.rs @@ -4,7 +4,6 @@ use commonware_runtime::buffer::PoolRef; use std::marker::PhantomData; use summit_orchestrator::Mailbox as OrchestratorMailbox; use summit_types::network_oracle::NetworkOracle; -use summit_types::registry::Registry; use summit_types::{EngineClient, PublicKey, consensus_state::ConsensusState}; use tokio_util::sync::CancellationToken; @@ -12,7 +11,6 @@ pub struct FinalizerConfig, S: Sign pub mailbox_size: usize, pub db_prefix: String, pub engine_client: C, - pub registry: Registry, pub oracle: O, pub orchestrator_mailbox: OrchestratorMailbox, pub epoch_num_of_blocks: u64, diff --git a/node/src/args.rs b/node/src/args.rs index ccba3eba..f37a1cc9 100644 --- a/node/src/args.rs +++ b/node/src/args.rs @@ -1,12 +1,14 @@ use crate::{ config::{ - BACKFILLER_CHANNEL, BROADCASTER_CHANNEL, EngineConfig, MESSAGE_BACKLOG, expect_key_store, + BACKFILLER_CHANNEL, BROADCASTER_CHANNEL, EngineConfig, MESSAGE_BACKLOG, + ORCHESTRATOR_CHANNEL, PENDING_CHANNEL, RECOVERED_CHANNEL, RESOLVER_CHANNEL, + expect_key_store, }, engine::Engine, keys::KeySubCmd, }; use clap::{Args, Parser, Subcommand}; -use commonware_cryptography::{Signer, bls12381}; +use commonware_cryptography::Signer; use commonware_p2p::{Manager, authenticated}; use commonware_runtime::{Handle, Metrics as _, Runner, Spawner as _, tokio}; use summit_rpc::{PathSender, start_rpc_server, start_rpc_server_for_genesis}; @@ -344,6 +346,23 @@ impl Command { ) .unwrap(); + // Register pending channel + let pending_limit = Quota::per_second(NonZeroU32::new(8).unwrap()); + let pending = network.register(PENDING_CHANNEL, pending_limit, MESSAGE_BACKLOG); + + // Register recovered channel + let recovered_limit = Quota::per_second(NonZeroU32::new(8).unwrap()); + let recovered = network.register(RECOVERED_CHANNEL, recovered_limit, MESSAGE_BACKLOG); + + // Register resolver channel + let resolver_limit = Quota::per_second(NonZeroU32::new(8).unwrap()); + let resolver = network.register(RESOLVER_CHANNEL, resolver_limit, MESSAGE_BACKLOG); + + // Register orchestrator channel + let orchestrator_limit = Quota::per_second(NonZeroU32::new(8).unwrap()); + let orchestrator = + network.register(ORCHESTRATOR_CHANNEL, orchestrator_limit, MESSAGE_BACKLOG); + // Register broadcast channel let broadcaster_limit = Quota::per_second(NonZeroU32::new(8).unwrap()); let broadcaster = @@ -361,7 +380,14 @@ impl Command { let finalizer_mailbox = engine.finalizer_mailbox.clone(); // Start engine - let engine = engine.start(broadcaster, backfiller); + let engine = engine.start( + pending, + recovered, + resolver, + orchestrator, + broadcaster, + backfiller, + ); // Start RPC server let key_store_path = flags.key_store_path.clone(); @@ -523,6 +549,23 @@ pub fn run_node_with_runtime( ) .unwrap(); + // Register pending channel + let pending_limit = Quota::per_second(NonZeroU32::new(8).unwrap()); + let pending = network.register(PENDING_CHANNEL, pending_limit, MESSAGE_BACKLOG); + + // Register recovered channel + let recovered_limit = Quota::per_second(NonZeroU32::new(8).unwrap()); + let recovered = network.register(RECOVERED_CHANNEL, recovered_limit, MESSAGE_BACKLOG); + + // Register resolver channel + let resolver_limit = Quota::per_second(NonZeroU32::new(8).unwrap()); + let resolver = network.register(RESOLVER_CHANNEL, resolver_limit, MESSAGE_BACKLOG); + + // Register orchestrator channel + let orchestrator_limit = Quota::per_second(NonZeroU32::new(8).unwrap()); + let orchestrator = + network.register(ORCHESTRATOR_CHANNEL, orchestrator_limit, MESSAGE_BACKLOG); + // Register broadcast channel let broadcaster_limit = Quota::per_second(NonZeroU32::new(8).unwrap()); let broadcaster = network.register(BROADCASTER_CHANNEL, broadcaster_limit, MESSAGE_BACKLOG); @@ -533,12 +576,18 @@ pub fn run_node_with_runtime( // Create network let p2p = network.start(); // create engine - let engine: Engine<_, _, _, _> = - Engine::new(context.with_label("engine"), config).await; + let engine: Engine<_, _, _, _> = Engine::new(context.with_label("engine"), config).await; let finalizer_mailbox = engine.finalizer_mailbox.clone(); // Start engine - let engine = engine.start(broadcaster, backfiller); + let engine = engine.start( + pending, + recovered, + resolver, + orchestrator, + broadcaster, + backfiller, + ); // Start prometheus endpoint #[cfg(feature = "prom")] diff --git a/node/src/config.rs b/node/src/config.rs index 7a50a35e..99088b11 100644 --- a/node/src/config.rs +++ b/node/src/config.rs @@ -11,8 +11,12 @@ use summit_types::network_oracle::NetworkOracle; use summit_types::{EngineClient, Genesis, PrivateKey, PublicKey}; use zeroize::ZeroizeOnDrop; /* DEFAULTS */ -pub const BROADCASTER_CHANNEL: u64 = 0; -pub const BACKFILLER_CHANNEL: u64 = 1; +pub const PENDING_CHANNEL: u64 = 0; +pub const RECOVERED_CHANNEL: u64 = 1; +pub const RESOLVER_CHANNEL: u64 = 2; +pub const ORCHESTRATOR_CHANNEL: u64 = 3; +pub const BROADCASTER_CHANNEL: u64 = 4; +pub const BACKFILLER_CHANNEL: u64 = 5; pub const MAILBOX_SIZE: usize = 16384; const FETCH_TIMEOUT: Duration = Duration::from_secs(5); diff --git a/node/src/engine.rs b/node/src/engine.rs index c139331c..d76dc1d8 100644 --- a/node/src/engine.rs +++ b/node/src/engine.rs @@ -2,9 +2,9 @@ use crate::config::EngineConfig; use commonware_broadcast::buffered; use commonware_codec::{DecodeExt, Encode}; use commonware_consensus::simplex::signing_scheme::Scheme; -use commonware_cryptography::{Signer, bls12381}; +use commonware_cryptography::Signer; use commonware_cryptography::bls12381::primitives::group; -use commonware_cryptography::bls12381::primitives::variant::{MinPk, Variant}; +use commonware_cryptography::bls12381::primitives::variant::MinPk; use commonware_p2p::{Blocker, Manager, Receiver, Sender, utils::requester}; use commonware_runtime::buffer::PoolRef; use commonware_runtime::{Clock, Handle, Metrics, Network, Spawner, Storage}; @@ -20,7 +20,6 @@ use summit_application::ApplicationConfig; use summit_finalizer::actor::Finalizer; use summit_finalizer::{FinalizerConfig, FinalizerMailbox}; use summit_types::network_oracle::NetworkOracle; -use summit_types::registry::Registry; use summit_types::scheme::{MultisigScheme, SummitSchemeProvider}; use summit_types::{Block, EngineClient, PublicKey}; use tokio_util::sync::CancellationToken; @@ -36,9 +35,6 @@ const WRITE_BUFFER: NonZero = NZUsize!(1024 * 1024); const BUFFER_POOL_PAGE_SIZE: NonZero = NZUsize!(4_096); // 4KB const BUFFER_POOL_CAPACITY: NonZero = NZUsize!(8_192); // 32MB -const DEQUE_SIZE: usize = 10; -const ACTIVITY_TIMEOUT: u64 = 256; -const SYNCER_ACTIVITY_TIMEOUT_MULTIPLIER: u64 = 10; const PRUNABLE_ITEMS_PER_SECTION: NonZero = NZU64!(4_096); const IMMUTABLE_ITEMS_PER_SECTION: NonZero = NZU64!(262_144); const FREEZER_TABLE_RESIZE_FREQUENCY: u8 = 4; @@ -80,11 +76,17 @@ pub struct Engine< buffer: buffered::Engine>, buffer_mailbox: buffered::Mailbox>, #[allow(clippy::type_complexity)] - syncer: summit_syncer::Actor, SummitSchemeProvider, MultisigScheme>, + syncer: summit_syncer::Actor< + E, + Block, + SummitSchemeProvider, + MultisigScheme, + >, syncer_mailbox: summit_syncer::Mailbox, Block>, finalizer: Finalizer, MinPk>, pub finalizer_mailbox: FinalizerMailbox, Block>, - orchestrator: summit_orchestrator::Actor>, + orchestrator: + summit_orchestrator::Actor>, oracle: O, node_public_key: PublicKey, mailbox_size: usize, @@ -102,20 +104,13 @@ where MultisigScheme: Scheme, { pub async fn new(context: E, cfg: EngineConfig) -> Self { - let node_keys: Vec<_> = cfg - .participants - .iter() - .map(|(node_key, _)| node_key.clone()) - .collect(); - let registry = Registry::new(cfg.initial_state.epoch, node_keys); let buffer_pool = PoolRef::new(BUFFER_POOL_PAGE_SIZE, BUFFER_POOL_CAPACITY); - //let threshold = registry. let encoded = cfg.key_store.consensus_key.encode(); let private_scalar = group::Private::decode(&mut encoded.as_ref()) .expect("failed to extract scalar from private key"); let scheme_provider: SummitSchemeProvider = - SummitSchemeProvider::new(cfg.key_store.node_key.clone(), private_scalar); + SummitSchemeProvider::new(private_scalar); let sync_height = cfg.initial_state.latest_height; @@ -197,7 +192,6 @@ where mailbox_size: cfg.mailbox_size, db_prefix: cfg.partition_prefix.clone(), engine_client: cfg.engine_client, - registry: registry.clone(), oracle: cfg.oracle.clone(), orchestrator_mailbox, epoch_num_of_blocks: BLOCKS_PER_EPOCH, @@ -239,6 +233,22 @@ where /// This will also rebuild the state of the engine from provided `Journal`. pub fn start( self, + pending_network: ( + impl Sender, + impl Receiver, + ), + recovered_network: ( + impl Sender, + impl Receiver, + ), + resolver_network: ( + impl Sender, + impl Receiver, + ), + orchestrator_network: ( + impl Sender, + impl Receiver, + ), broadcast_network: ( impl Sender, impl Receiver, @@ -248,9 +258,16 @@ where impl Receiver, ), ) -> Handle<()> { - self.context - .clone() - .spawn(|_| self.run(broadcast_network, backfill_network)) + self.context.clone().spawn(|_| { + self.run( + pending_network, + recovered_network, + resolver_network, + orchestrator_network, + broadcast_network, + backfill_network, + ) + }) } /// Start the `simplex` consensus engine. @@ -258,6 +275,22 @@ where /// This will also rebuild the state of the engine from provided `Journal`. async fn run( self, + pending_network: ( + impl Sender, + impl Receiver, + ), + recovered_network: ( + impl Sender, + impl Receiver, + ), + resolver_network: ( + impl Sender, + impl Receiver, + ), + orchestrator_network: ( + impl Sender, + impl Receiver, + ), broadcast_network: ( impl Sender, impl Receiver, @@ -300,6 +333,13 @@ where (resolver_rx, resolver), self.sync_height, ); + // start the orchestrator + let orchestrator_handle = self.orchestrator.start( + pending_network, + recovered_network, + resolver_network, + orchestrator_network, + ); // Wait for either all actors to finish or cancellation signal let actors_fut = try_join_all(vec![ @@ -307,6 +347,7 @@ where buffer_handle, finalizer_handle, syncer_handle, + orchestrator_handle, ]) .fuse(); let cancellation_fut = self.cancellation_token.cancelled().fuse(); diff --git a/node/src/keys.rs b/node/src/keys.rs index 6a836671..e21c3b9d 100644 --- a/node/src/keys.rs +++ b/node/src/keys.rs @@ -144,11 +144,6 @@ pub fn read_ed_key_from_file(path: &std::path::Path) -> Result { Ok(pk) } -pub fn read_ed_key_from_path(key_path: &str) -> Result { - let path = get_expanded_path(key_path)?; - read_ed_key_from_file(&path) -} - pub fn read_keys_from_keystore(keystore_path: &str) -> Result<(PrivateKey, BlsPrivateKey)> { let keystore_dir = get_expanded_path(keystore_path)?; let node_key = read_ed_key_from_file(&keystore_dir.join(NODE_KEY_FILENAME))?; diff --git a/node/src/prom/recorder.rs b/node/src/prom/recorder.rs index 8f3e6d74..f16386e8 100644 --- a/node/src/prom/recorder.rs +++ b/node/src/prom/recorder.rs @@ -24,7 +24,6 @@ static PROMETHEUS_RECORDER_HANDLE: LazyLock = /// /// This is intended to be used as the global recorder. /// Callers must ensure that [`PrometheusRecorder::spawn_upkeep`] is called once. - #[allow(unused)] #[derive(Debug)] pub struct PrometheusRecorder { diff --git a/node/src/test_harness/common.rs b/node/src/test_harness/common.rs index 5869a2ce..a3addcbe 100644 --- a/node/src/test_harness/common.rs +++ b/node/src/test_harness/common.rs @@ -92,23 +92,31 @@ pub async fn register_validators( (Sender, Receiver), (Sender, Receiver), (Sender, Receiver), + (Sender, Receiver), + (Sender, Receiver), ), > { let mut registrations = HashMap::new(); for validator in validators.iter() { let (pending_sender, pending_receiver) = oracle.register(validator.clone(), 0).await.unwrap(); - let (resolver_sender, resolver_receiver) = + let (recovered_sender, recovered_receiver) = oracle.register(validator.clone(), 1).await.unwrap(); - let (broadcast_sender, broadcast_receiver) = + let (resolver_sender, resolver_receiver) = oracle.register(validator.clone(), 2).await.unwrap(); - let (backfill_sender, backfill_receiver) = + let (orchestrator_sender, orchestrator_receiver) = oracle.register(validator.clone(), 3).await.unwrap(); + let (broadcast_sender, broadcast_receiver) = + oracle.register(validator.clone(), 4).await.unwrap(); + let (backfill_sender, backfill_receiver) = + oracle.register(validator.clone(), 5).await.unwrap(); registrations.insert( validator.clone(), ( (pending_sender, pending_receiver), + (recovered_sender, recovered_receiver), (resolver_sender, resolver_receiver), + (orchestrator_sender, orchestrator_receiver), (broadcast_sender, broadcast_receiver), (backfill_sender, backfill_receiver), ), @@ -208,11 +216,18 @@ pub fn run_until_height( consensus_state_queries.insert(idx, engine.finalizer_mailbox.clone()); // Get networking - let (pending, resolver, broadcast, backfill) = + let (pending, recovered, resolver, orchestrator, broadcast, backfill) = registrations.remove(&public_key).unwrap(); // Start engine - engine.start(pending, resolver, broadcast, backfill); + engine.start( + pending, + recovered, + resolver, + orchestrator, + broadcast, + backfill, + ); } // Poll metrics diff --git a/node/src/test_harness/mock_engine_client.rs b/node/src/test_harness/mock_engine_client.rs index ebd144db..a85e0c63 100644 --- a/node/src/test_harness/mock_engine_client.rs +++ b/node/src/test_harness/mock_engine_client.rs @@ -746,6 +746,7 @@ mod tests { block1.clone(), Vec::new(), alloy_primitives::U256::from(1_000_000_000_000_000_000u64), + 0, 1, None, [0u8; 32].into(), @@ -826,6 +827,7 @@ mod tests { Vec::new(), U256::from(1_000_000_000_000_000_000u64), 1, + round as u64, None, [0u8; 32].into(), Vec::new(), // added_validators @@ -923,6 +925,7 @@ mod tests { block.clone(), Vec::new(), alloy_primitives::U256::from(1_000_000_000_000_000_000u64), + 0, 1, None, [0u8; 32].into(), diff --git a/node/src/tests/checkpointing.rs b/node/src/tests/checkpointing.rs index 3bc489a8..a6308f7e 100644 --- a/node/src/tests/checkpointing.rs +++ b/node/src/tests/checkpointing.rs @@ -108,11 +108,18 @@ fn test_checkpoint_created() { consensus_state_queries.insert(idx, engine.finalizer_mailbox.clone()); // Get networking - let (pending, resolver, broadcast, backfill) = + let (pending, recovered, resolver, orchestrator, broadcast, backfill) = registrations.remove(&public_key).unwrap(); // Start engine - engine.start(pending, resolver, broadcast, backfill); + engine.start( + pending, + recovered, + resolver, + orchestrator, + broadcast, + backfill, + ); } // Poll metrics let mut state_stored = HashSet::new(); @@ -276,11 +283,18 @@ fn test_previous_header_hash_matches() { consensus_state_queries.insert(idx, engine.finalizer_mailbox.clone()); // Get networking - let (pending, resolver, broadcast, backfill) = + let (pending, recovered, resolver, orchestrator, broadcast, backfill) = registrations.remove(&public_key).unwrap(); // Start engine - engine.start(pending, resolver, broadcast, backfill); + engine.start( + pending, + recovered, + resolver, + orchestrator, + broadcast, + backfill, + ); } // Poll metrics let mut first_header_stored = HashMap::new(); @@ -439,10 +453,18 @@ fn test_single_engine_with_checkpoint() { let engine = Engine::new(context.with_label(&uid), config).await; let finalizer_mailbox = engine.finalizer_mailbox.clone(); // Get networking - let (pending, resolver, broadcast, backfill) = registrations.remove(&public_key).unwrap(); + let (pending, recovered, resolver, orchestrator, broadcast, backfill) = + registrations.remove(&public_key).unwrap(); // Start engine - engine.start(pending, resolver, broadcast, backfill); + engine.start( + pending, + recovered, + resolver, + orchestrator, + broadcast, + backfill, + ); // Wait a bit for initialization context.sleep(Duration::from_millis(500)).await; @@ -562,11 +584,18 @@ fn test_node_joins_later_with_checkpoint() { consensus_state_queries.insert(idx, engine.finalizer_mailbox.clone()); // Get networking - let (pending, resolver, broadcast, backfill) = + let (pending, recovered, resolver, orchestrator, broadcast, backfill) = registrations.remove(&public_key).unwrap(); // Start engine - engine.start(pending, resolver, broadcast, backfill); + engine.start( + pending, + recovered, + resolver, + orchestrator, + broadcast, + backfill, + ); } // Wait for the validators to checkpoint @@ -626,11 +655,18 @@ fn test_node_joins_later_with_checkpoint() { let engine = Engine::new(context.with_label(&uid), config).await; // Get networking from late registrations - let (pending, resolver, broadcast, backfill) = + let (pending, recovered, resolver, orchestrator, broadcast, backfill) = late_registrations.into_iter().next().unwrap().1; // Start engine - engine.start(pending, resolver, broadcast, backfill); + engine.start( + pending, + recovered, + resolver, + orchestrator, + broadcast, + backfill, + ); // Poll metrics let stop_height = 3 * BLOCKS_PER_EPOCH; @@ -793,11 +829,18 @@ fn test_node_joins_later_with_checkpoint_not_in_genesis() { consensus_state_queries.insert(idx, engine.finalizer_mailbox.clone()); // Get networking - let (pending, resolver, broadcast, backfill) = + let (pending, recovered, resolver, orchestrator, broadcast, backfill) = registrations.remove(&public_key).unwrap(); // Start engine - engine.start(pending, resolver, broadcast, backfill); + engine.start( + pending, + recovered, + resolver, + orchestrator, + broadcast, + backfill, + ); } // Wait for the validators to checkpoint @@ -857,11 +900,18 @@ fn test_node_joins_later_with_checkpoint_not_in_genesis() { let engine = Engine::new(context.with_label(&uid), config).await; // Get networking from late registrations - let (pending, resolver, broadcast, backfill) = + let (pending, recovered, resolver, orchestrator, broadcast, backfill) = late_registrations.into_iter().next().unwrap().1; // Start engine - engine.start(pending, resolver, broadcast, backfill); + engine.start( + pending, + recovered, + resolver, + orchestrator, + broadcast, + backfill, + ); // Poll metrics let stop_height = 3 * BLOCKS_PER_EPOCH; diff --git a/node/src/tests/execution_requests.rs b/node/src/tests/execution_requests.rs index 1390af97..5b79d12a 100644 --- a/node/src/tests/execution_requests.rs +++ b/node/src/tests/execution_requests.rs @@ -125,11 +125,18 @@ fn test_deposit_request_single() { consensus_state_queries.insert(idx, engine.finalizer_mailbox.clone()); // Get networking - let (pending, resolver, broadcast, backfill) = + let (pending, recovered, resolver, orchestrator, broadcast, backfill) = registrations.remove(&public_key).unwrap(); // Start engine - engine.start(pending, resolver, broadcast, backfill); + engine.start( + pending, + recovered, + resolver, + orchestrator, + broadcast, + backfill, + ); } // Poll metrics let mut height_reached = HashSet::new(); @@ -322,11 +329,18 @@ fn test_deposit_request_top_up() { consensus_state_queries.insert(idx, engine.finalizer_mailbox.clone()); // Get networking - let (pending, resolver, broadcast, backfill) = + let (pending, recovered, resolver, orchestrator, broadcast, backfill) = registrations.remove(&public_key).unwrap(); // Start engine - engine.start(pending, resolver, broadcast, backfill); + engine.start( + pending, + recovered, + resolver, + orchestrator, + broadcast, + backfill, + ); } // Poll metrics @@ -530,11 +544,18 @@ fn test_deposit_and_withdrawal_request_single() { consensus_state_queries.insert(idx, engine.finalizer_mailbox.clone()); // Get networking - let (pending, resolver, broadcast, backfill) = + let (pending, recovered, resolver, orchestrator, broadcast, backfill) = registrations.remove(&public_key).unwrap(); // Start engine - engine.start(pending, resolver, broadcast, backfill); + engine.start( + pending, + recovered, + resolver, + orchestrator, + broadcast, + backfill, + ); } // Poll metrics @@ -758,11 +779,18 @@ fn test_partial_withdrawal_balance_below_minimum_stake() { consensus_state_queries.insert(idx, engine.finalizer_mailbox.clone()); // Get networking - let (pending, resolver, broadcast, backfill) = + let (pending, recovered, resolver, orchestrator, broadcast, backfill) = registrations.remove(&public_key).unwrap(); // Start engine - engine.start(pending, resolver, broadcast, backfill); + engine.start( + pending, + recovered, + resolver, + orchestrator, + broadcast, + backfill, + ); } // Poll metrics @@ -979,11 +1007,18 @@ fn test_deposit_less_than_min_stake_and_withdrawal() { consensus_state_queries.insert(idx, engine.finalizer_mailbox.clone()); // Get networking - let (pending, resolver, broadcast, backfill) = + let (pending, recovered, resolver, orchestrator, broadcast, backfill) = registrations.remove(&public_key).unwrap(); // Start engine - engine.start(pending, resolver, broadcast, backfill); + engine.start( + pending, + recovered, + resolver, + orchestrator, + broadcast, + backfill, + ); } // Poll metrics @@ -1213,11 +1248,18 @@ fn test_deposit_and_withdrawal_request_multiple() { consensus_state_queries.insert(idx, engine.finalizer_mailbox.clone()); // Get networking - let (pending, resolver, broadcast, backfill) = + let (pending, recovered, resolver, orchestrator, broadcast, backfill) = registrations.remove(&public_key).unwrap(); // Start engine - engine.start(pending, resolver, broadcast, backfill); + engine.start( + pending, + recovered, + resolver, + orchestrator, + broadcast, + backfill, + ); } // Poll metrics @@ -1436,11 +1478,18 @@ fn test_deposit_request_invalid_signature() { consensus_state_queries.insert(idx, engine.finalizer_mailbox.clone()); // Get networking - let (pending, resolver, broadcast, backfill) = + let (pending, recovered, resolver, orchestrator, broadcast, backfill) = registrations.remove(&public_key).unwrap(); // Start engine - engine.start(pending, resolver, broadcast, backfill); + engine.start( + pending, + recovered, + resolver, + orchestrator, + broadcast, + backfill, + ); } // Poll metrics let mut processed_requests = HashSet::new(); @@ -1466,7 +1515,7 @@ fn test_deposit_request_invalid_signature() { assert_eq!(value, 0); } - if metric.ends_with("deposit_request_invalid_sig") { + if metric.ends_with("deposit_request_invalid_node_sig") { let value = value.parse::().unwrap(); // Parse the pubkey from the metric name using helper function if let Some(pubkey_hex) = common::parse_metric_substring(metric, "pubkey") { diff --git a/node/src/tests/syncer.rs b/node/src/tests/syncer.rs index ed0b5bfb..33b0be17 100644 --- a/node/src/tests/syncer.rs +++ b/node/src/tests/syncer.rs @@ -110,11 +110,18 @@ fn test_node_joins_later_no_checkpoint() { consensus_state_queries.insert(idx, engine.finalizer_mailbox.clone()); // Get networking - let (pending, resolver, broadcast, backfill) = + let (pending, recovered, resolver, orchestrator, broadcast, backfill) = registrations.remove(&public_key).unwrap(); // Start engine - engine.start(pending, resolver, broadcast, backfill); + engine.start( + pending, + recovered, + resolver, + orchestrator, + broadcast, + backfill, + ); } // Wait for the validators to checkpoint @@ -160,11 +167,18 @@ fn test_node_joins_later_no_checkpoint() { let engine = Engine::new(context.with_label(&uid), config).await; // Get networking from late registrations - let (pending, resolver, broadcast, backfill) = + let (pending, recovered, resolver, orchestrator, broadcast, backfill) = late_registrations.into_iter().next().unwrap().1; // Start engine - engine.start(pending, resolver, broadcast, backfill); + engine.start( + pending, + recovered, + resolver, + orchestrator, + broadcast, + backfill, + ); // Poll metrics let stop_height = 2 * BLOCKS_PER_EPOCH; @@ -324,11 +338,18 @@ fn test_node_joins_later_no_checkpoint_not_in_genesis() { consensus_state_queries.insert(idx, engine.finalizer_mailbox.clone()); // Get networking - let (pending, resolver, broadcast, backfill) = + let (pending, recovered, resolver, orchestrator, broadcast, backfill) = registrations.remove(&public_key).unwrap(); // Start engine - engine.start(pending, resolver, broadcast, backfill); + engine.start( + pending, + recovered, + resolver, + orchestrator, + broadcast, + backfill, + ); } // Wait for the validators to checkpoint @@ -376,11 +397,18 @@ fn test_node_joins_later_no_checkpoint_not_in_genesis() { let engine = Engine::new(context.with_label(&uid), config).await; // Get networking from late registrations - let (pending, resolver, broadcast, backfill) = + let (pending, recovered, resolver, orchestrator, broadcast, backfill) = late_registrations.into_iter().next().unwrap().1; // Start engine - engine.start(pending, resolver, broadcast, backfill); + engine.start( + pending, + recovered, + resolver, + orchestrator, + broadcast, + backfill, + ); // Poll metrics let stop_height = 2 * BLOCKS_PER_EPOCH; diff --git a/orchestrator/src/actor.rs b/orchestrator/src/actor.rs index e1424079..fd5ad071 100644 --- a/orchestrator/src/actor.rs +++ b/orchestrator/src/actor.rs @@ -12,7 +12,10 @@ use commonware_consensus::{ types::Epoch, utils::last_block_in_epoch, }; -use commonware_cryptography::{Signer, bls12381::primitives::variant::{MinPk, Variant}}; +use commonware_cryptography::{ + Signer, + bls12381::primitives::variant::{MinPk, Variant}, +}; use commonware_macros::select; use commonware_p2p::{ Blocker, Receiver, Recipients, Sender, diff --git a/orchestrator/src/ingress.rs b/orchestrator/src/ingress.rs index 996c1d06..68ca6b4f 100644 --- a/orchestrator/src/ingress.rs +++ b/orchestrator/src/ingress.rs @@ -21,9 +21,7 @@ pub struct Mailbox { impl Mailbox { /// Create a new [Mailbox]. pub fn new(sender: mpsc::Sender>) -> Self { - Self { - sender, - } + Self { sender } } } diff --git a/types/src/execution_request.rs b/types/src/execution_request.rs index 974d469d..fa33f0f1 100644 --- a/types/src/execution_request.rs +++ b/types/src/execution_request.rs @@ -155,63 +155,42 @@ impl DepositRequest { } pub fn as_message(&self, domain: Digest) -> Digest { - // Hash consensus_pubkey with 16-byte padding - let mut hasher = Sha256::default(); - hasher.update(&self.consensus_pubkey.encode()); - hasher.update(&[0u8; 16]); - let consensus_pubkey_hash = hasher.finalize(); - - // Hash node_pubkey with consensus_pubkey_hash to get pubkey_root - let mut hasher = Sha256::default(); - hasher.update(&self.node_pubkey.encode()); - hasher.update(&consensus_pubkey_hash); - let pubkey_root = hasher.finalize(); - - // Hash first 64 bytes of consensus_signature - let mut hasher = Sha256::default(); - hasher.update(&self.consensus_signature[0..64]); - let consensus_sig_part1 = hasher.finalize(); - - // Hash last 32 bytes of consensus_signature with 32-byte padding - let mut hasher = Sha256::default(); - hasher.update(&self.consensus_signature[64..96]); - hasher.update(&[0u8; 32]); - let consensus_sig_part2 = hasher.finalize(); - - // Combine both parts to get bls_signature_hash - let mut hasher = Sha256::default(); - hasher.update(&consensus_sig_part1); - hasher.update(&consensus_sig_part2); - let bls_signature_hash = hasher.finalize(); + let mut node_pubkey_bytes = [0u8; 32]; + node_pubkey_bytes.copy_from_slice(&self.node_pubkey.encode()); - // Hash node_signature with bls_signature_hash to get signature_root + // Hash node_pubkey and consensus_pubkey together + let mut left = Vec::with_capacity(80); + left.extend_from_slice(&node_pubkey_bytes); + left.extend_from_slice(&self.consensus_pubkey.encode()); let mut hasher = Sha256::default(); - hasher.update(&self.node_signature); - hasher.update(&bls_signature_hash); - let signature_root = hasher.finalize(); + hasher.update(&left); + let pubkeys_hash = hasher.finalize(); - // Hash pubkey_root with withdrawal_credentials + // Hash pubkeys_hash with withdrawal_credentials + let mut left = Vec::with_capacity(64); + left.extend_from_slice(&pubkeys_hash); + left.extend_from_slice(&self.withdrawal_credentials); let mut hasher = Sha256::default(); - hasher.update(&pubkey_root); - hasher.update(&self.withdrawal_credentials); + hasher.update(&left); let left_hash = hasher.finalize(); - // Hash amount with 24-byte padding and signature_root + // Hash amount with padding + let mut right = Vec::with_capacity(64); + right.extend_from_slice(&self.amount.to_le_bytes()); + right.extend_from_slice(&[0; 56]); let mut hasher = Sha256::default(); - hasher.update(&self.amount.to_le_bytes()); - hasher.update(&[0u8; 24]); - hasher.update(&signature_root); + hasher.update(&right); let right_hash = hasher.finalize(); - // Combine to get node hash + // Combine left and right let mut hasher = Sha256::default(); hasher.update(&left_hash); hasher.update(&right_hash); - let node_hash = hasher.finalize(); + let root_hash = hasher.finalize(); // Final hash with domain let mut hasher = Sha256::default(); - hasher.update(&node_hash); + hasher.update(&root_hash); hasher.update(&domain); hasher.finalize() } diff --git a/types/src/genesis.rs b/types/src/genesis.rs index 445cc74d..3b7f1145 100644 --- a/types/src/genesis.rs +++ b/types/src/genesis.rs @@ -86,6 +86,7 @@ impl Genesis { pub fn ip_of(&self, target_public_key: &PublicKey) -> Option { for validator in &self.validators { + #[allow(clippy::collapsible_if)] if let Some(public_key_bytes) = from_hex_formatted(&validator.node_public_key) { if let Ok(pub_key) = PublicKey::decode(&*public_key_bytes) { if &pub_key == target_public_key { diff --git a/types/src/reth.rs b/types/src/reth.rs index 2fe211fc..a4304c28 100644 --- a/types/src/reth.rs +++ b/types/src/reth.rs @@ -581,18 +581,21 @@ impl Reth { .read_line(&mut line) .map_err(NodeError::ReadLineError)?; + #[allow(clippy::collapsible_if)] if line.contains("RPC HTTP server started") { if let Some(addr) = extract_endpoint("url=", &line) { http_port = addr.port(); } } + #[allow(clippy::collapsible_if)] if line.contains("RPC WS server started") { if let Some(addr) = extract_endpoint("url=", &line) { ws_port = addr.port(); } } + #[allow(clippy::collapsible_if)] if line.contains("RPC auth server started") { if let Some(addr) = extract_endpoint("url=", &line) { auth_port = addr.port(); @@ -609,6 +612,7 @@ impl Reth { ports_started = true; } + #[allow(clippy::collapsible_if)] if self.discovery_enabled { if line.contains("Updated local ENR") { if let Some(port) = extract_endpoint("IpV4 UDP Socket", &line) { diff --git a/types/src/scheme.rs b/types/src/scheme.rs index 9ac91a73..0409265c 100644 --- a/types/src/scheme.rs +++ b/types/src/scheme.rs @@ -4,7 +4,7 @@ use commonware_consensus::types::Epoch; use commonware_cryptography::bls12381::primitives::group; use commonware_cryptography::bls12381::primitives::variant::{MinPk, Variant}; use commonware_cryptography::{PublicKey, Signer}; -use commonware_utils::set::{Ordered, OrderedAssociated}; +use commonware_utils::set::OrderedAssociated; use std::collections::HashMap; use std::sync::{Arc, Mutex}; @@ -24,15 +24,13 @@ pub trait SchemeProvider: Clone + Send + Sync + 'static { pub struct SummitSchemeProvider { #[allow(clippy::type_complexity)] schemes: Arc>>>>, - signer: C, bls_private_key: group::Private, } impl SummitSchemeProvider { - pub fn new(signer: C, bls_private_key: group::Private) -> Self { + pub fn new(bls_private_key: group::Private) -> Self { Self { schemes: Arc::new(Mutex::new(HashMap::new())), - signer, bls_private_key, } } From f2fec24163673fcce37f2e45f03312b9efae7563 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Mon, 10 Nov 2025 18:38:03 -0500 Subject: [PATCH 47/81] chore: implement Manager and Blocker traits for dummy network --- finalizer/src/actor.rs | 3 - node/src/args.rs | 1 - node/src/bin/stake_and_checkpoint.rs | 2 +- node/src/bin/withdraw_and_exit.rs | 2 +- node/src/config.rs | 2 +- node/src/keys.rs | 48 ++++++++ node/src/test_harness/common.rs | 125 +++++++++++++------- node/src/test_harness/mock_engine_client.rs | 12 +- node/src/tests/checkpointing.rs | 18 ++- node/src/tests/execution_requests.rs | 77 +++++++----- node/src/tests/syncer.rs | 28 +++-- testnet/node0/key.pem | 1 - testnet/node1/key.pem | 1 - testnet/node2/key.pem | 1 - testnet/node3/key.pem | 1 - 15 files changed, 218 insertions(+), 104 deletions(-) delete mode 100644 testnet/node0/key.pem delete mode 100644 testnet/node1/key.pem delete mode 100644 testnet/node2/key.pem delete mode 100644 testnet/node3/key.pem diff --git a/finalizer/src/actor.rs b/finalizer/src/actor.rs index cab7903f..a8836d6e 100644 --- a/finalizer/src/actor.rs +++ b/finalizer/src/actor.rs @@ -760,9 +760,6 @@ impl< height: u64, sender: oneshot::Sender, ) { - // TODO(matthias): the height notify should take care of the synchronization, but verify this - // Get ready withdrawals at the current height - // Create checkpoint if we're at an epoch boundary. // The consensus state is saved every `epoch_num_blocks` blocks. // The proposed block will contain the checkpoint that was saved at the previous height. diff --git a/node/src/args.rs b/node/src/args.rs index f37a1cc9..4ac806de 100644 --- a/node/src/args.rs +++ b/node/src/args.rs @@ -44,7 +44,6 @@ use summit_types::network_oracle::DiscoveryOracle; use summit_types::{Genesis, PrivateKey, PublicKey, Validator, utils::get_expanded_path}; use tracing::{Level, error}; -pub const DEFAULT_KEY_PATH: &str = "~/.seismic/consensus/key.pem"; pub const DEFAULT_DB_FOLDER: &str = "~/.seismic/consensus/store"; pub const DEFAULT_ENGINE_IPC_PATH: &str = "/tmp/reth_engine_api.ipc"; diff --git a/node/src/bin/stake_and_checkpoint.rs b/node/src/bin/stake_and_checkpoint.rs index 7a2c5d97..7201a932 100644 --- a/node/src/bin/stake_and_checkpoint.rs +++ b/node/src/bin/stake_and_checkpoint.rs @@ -491,7 +491,7 @@ fn main() -> Result<(), Box> { flags.bench_block_dir = args.bench_block_dir.clone(); } - let signer_path = format!("{}/node{}/data/key.pem", args.data_dir, x); + let signer_path = format!("{}/node{}/data/node_key.pem", args.data_dir, x); let encoded_priv_key = ed25519_private_key.to_string(); fs::write(&signer_path, encoded_priv_key).expect("Unable to write private key to disk"); flags.key_store_path = signer_path; diff --git a/node/src/bin/withdraw_and_exit.rs b/node/src/bin/withdraw_and_exit.rs index 68345409..befa622c 100644 --- a/node/src/bin/withdraw_and_exit.rs +++ b/node/src/bin/withdraw_and_exit.rs @@ -382,7 +382,7 @@ fn get_node_flags(node: usize) -> RunFlags { let path = format!("testnet/node{node}/"); RunFlags { - key_store_path: format!("{path}key.pem"), + key_store_path: format!("{path}node_key.pem"), store_path: format!("{path}db"), port: (26600 + (node * 10)) as u16, prom_port: (28600 + (node * 10)) as u16, diff --git a/node/src/config.rs b/node/src/config.rs index 99088b11..dc5b897a 100644 --- a/node/src/config.rs +++ b/node/src/config.rs @@ -128,7 +128,7 @@ mod tests { let repo_root = node_crate_dir.parent().unwrap(); repo_root.join("testnet/node0") }; - expect_key_store(&keys_dir.join("key.pem").to_string_lossy()); + expect_key_store(&keys_dir.to_string_lossy()); } #[test] diff --git a/node/src/keys.rs b/node/src/keys.rs index e21c3b9d..7789a9f7 100644 --- a/node/src/keys.rs +++ b/node/src/keys.rs @@ -131,9 +131,18 @@ impl KeySubCmd { } pub fn read_bls_key_from_file(path: &std::path::Path) -> Result { + println!("Read BLS key: {}", path.display()); + + if let Err(e) = std::fs::read_to_string(path) { + println!("Failed to read BLS key: {}", e); + } + let encoded_pk = std::fs::read_to_string(path)?; + println!("Read BLS key 1"); let key = from_hex_formatted(&encoded_pk).context("Invalid BLS key format")?; + println!("Read BLS key 2"); let pk = BlsPrivateKey::decode(&*key)?; + println!("Read BLS key 3"); Ok(pk) } @@ -146,7 +155,46 @@ pub fn read_ed_key_from_file(path: &std::path::Path) -> Result { pub fn read_keys_from_keystore(keystore_path: &str) -> Result<(PrivateKey, BlsPrivateKey)> { let keystore_dir = get_expanded_path(keystore_path)?; + println!("Keystore directory: {}", keystore_dir.display()); let node_key = read_ed_key_from_file(&keystore_dir.join(NODE_KEY_FILENAME))?; let consensus_key = read_bls_key_from_file(&keystore_dir.join(CONSENSUS_KEY_FILENAME))?; Ok((node_key, consensus_key)) } + +//#[cfg(test)] +//mod tests { +// use super::*; +// use commonware_cryptography::Signer; +// +// #[test] +// fn test_generate_testnet_keys() { +// // Generate 4 BLS private keys for testnet nodes +// for i in 0..4 { +// let node_dir = format!("../testnet/node{}", i); +// +// // Create directory +// std::fs::create_dir_all(&node_dir).expect("Unable to create testnet directory"); +// +// // Generate BLS consensus key deterministically from seed +// let consensus_private_key = BlsPrivateKey::from_seed(i as u64); +// let consensus_pub_key = consensus_private_key.public_key(); +// +// // Save consensus key +// let consensus_key_path = format!("{}/{}", node_dir, CONSENSUS_KEY_FILENAME); +// let encoded_consensus_key = consensus_private_key.to_string(); +// std::fs::write(&consensus_key_path, encoded_consensus_key) +// .expect("Unable to write consensus key to disk"); +// +// println!("Generated keys for node{} at {consensus_key_path}:", i); +// println!(" Consensus Public Key (BLS): {}", consensus_pub_key); +// +// // Verify we can read the key back +// let read_consensus_key = read_bls_key_from_file(std::path::Path::new(&consensus_key_path)) +// .expect("Unable to read consensus key"); +// +// assert_eq!(consensus_pub_key, read_consensus_key.public_key()); +// } +// +// println!("\nSuccessfully generated and verified BLS keys for 4 testnet nodes"); +// } +//} diff --git a/node/src/test_harness/common.rs b/node/src/test_harness/common.rs index a3addcbe..0e4012dd 100644 --- a/node/src/test_harness/common.rs +++ b/node/src/test_harness/common.rs @@ -7,7 +7,6 @@ use alloy_eips::eip7685::Requests; use alloy_primitives::{Address, B256, Bytes}; use alloy_rpc_types_engine::ForkchoiceState; use commonware_codec::Write; -use commonware_cryptography::bls12381::primitives::variant::Variant; use commonware_p2p::simulated::{self, Link, Network, Oracle, Receiver, Sender}; use commonware_runtime::{ Clock, Metrics, Runner as _, @@ -20,6 +19,8 @@ use std::{ collections::{HashMap, HashSet}, num::NonZeroU32, }; +use commonware_p2p::{Blocker, Manager}; +use commonware_utils::set::Ordered; use summit_types::account::{ValidatorAccount, ValidatorStatus}; use summit_types::consensus_state::ConsensusState; use summit_types::execution_request::{DepositRequest, ExecutionRequest, WithdrawalRequest}; @@ -83,7 +84,7 @@ pub async fn join_validator( } pub async fn register_validators( - oracle: &mut Oracle, + oracle: &Oracle, validators: &[PublicKey], ) -> HashMap< PublicKey, @@ -98,18 +99,13 @@ pub async fn register_validators( > { let mut registrations = HashMap::new(); for validator in validators.iter() { - let (pending_sender, pending_receiver) = - oracle.register(validator.clone(), 0).await.unwrap(); - let (recovered_sender, recovered_receiver) = - oracle.register(validator.clone(), 1).await.unwrap(); - let (resolver_sender, resolver_receiver) = - oracle.register(validator.clone(), 2).await.unwrap(); - let (orchestrator_sender, orchestrator_receiver) = - oracle.register(validator.clone(), 3).await.unwrap(); - let (broadcast_sender, broadcast_receiver) = - oracle.register(validator.clone(), 4).await.unwrap(); - let (backfill_sender, backfill_receiver) = - oracle.register(validator.clone(), 5).await.unwrap(); + let mut control = oracle.control(validator.clone()); + let (pending_sender, pending_receiver) = control.register(0).await.unwrap(); + let (recovered_sender, recovered_receiver) = control.register(1).await.unwrap(); + let (resolver_sender, resolver_receiver) = control.register(2).await.unwrap(); + let (orchestrator_sender, orchestrator_receiver) = control.register(3).await.unwrap(); + let (broadcast_sender, broadcast_receiver) = control.register(4).await.unwrap(); + let (backfill_sender, backfill_receiver) = control.register(5).await.unwrap(); registrations.insert( validator.clone(), ( @@ -164,14 +160,14 @@ pub fn run_until_height( key_stores.push(key_store); validators.push((node_public_key, consensus_public_key)); } - validators.sort_by_key(|lhs, rhs| lhs.0.cmp(&rhs.0)); - key_stores - .sort_by_key(|lhs, rhs| lhs.node_key.public_key().cmp(&rhs.node_key.public_key())); + validators.sort_by(|lhs, rhs| lhs.0.cmp(&rhs.0)); + key_stores.sort_by(|lhs, rhs| lhs.node_key.public_key().cmp(&rhs.node_key.public_key())); - let mut registrations = register_validators(&mut oracle, &validators).await; + let node_public_keys: Vec = validators.iter().map(|(pk, _)| pk.clone()).collect(); + let mut registrations = register_validators(&oracle, &node_public_keys).await; // Link all validators - link_validators(&mut oracle, &validators, link, None).await; + link_validators(&mut oracle, &node_public_keys, link, None).await; // Create the engine clients let genesis_hash = from_hex_formatted(GENESIS_HASH).expect("failed to decode genesis hash"); @@ -293,7 +289,7 @@ pub fn get_domain() -> Digest { pub fn get_initial_state( genesis_hash: [u8; 32], - committee: &Vec, + committee: &Vec<(PublicKey, bls12381::PublicKey)>, withdrawal_credentials: Option<&Vec

>, checkpoint: Option, balance: u64, @@ -309,12 +305,13 @@ pub fn get_initial_state( }; let mut state = ConsensusState::new(forkchoice); // Add the genesis nodes to the consensus state with the minimum stake balance. - for (pubkey, address) in committee.iter().zip(addresses.iter()) { - let pubkey_bytes: [u8; 32] = pubkey + for ((node_pubkey, consensus_pubkey), address) in committee.iter().zip(addresses.iter()) { + let pubkey_bytes: [u8; 32] = node_pubkey .as_ref() .try_into() .expect("Public key must be 32 bytes"); let account = ValidatorAccount { + consensus_public_key: consensus_pubkey.clone(), // TODO(matthias): we have to add a withdrawal address to the genesis withdrawal_credentials: *address, balance, @@ -333,6 +330,7 @@ pub fn get_initial_state( }) } + /// Parse a substring from a metric name using XML-like tags /// /// # Arguments @@ -373,29 +371,30 @@ pub fn extract_validator_id(metric: &str) -> Option { Some(metric[..end].to_string()) } -/// Create a single DepositRequest for testing with a valid ED25519 signature +/// Create a single DepositRequest for testing with valid ED25519 and BLS signatures /// /// This function creates a test deposit request with all required fields, including -/// a cryptographically valid signature that can be verified against the deposit message. +/// cryptographically valid signatures that can be verified against the deposit message. /// /// # Arguments /// * `index` - The deposit index value used for generating deterministic keys and in the signature -/// * `amount` - The deposit amount in gwei +/// * `amount` - The deposit amount in gwei /// * `domain` - The domain value used in the signature (typically genesis hash) /// * `private_key` - Optional ED25519 private key to use; if None, generates deterministic key from index /// * `withdrawal_credentials` - Optional withdrawal credentials; if None, generates Eth1 format credentials /// /// # Returns -/// * `(DepositRequest, PrivateKey)` - A tuple containing: -/// - `DepositRequest` - A complete deposit request with valid signature -/// - `PrivateKey` - The private key used to sign the request (for further testing) +/// * `(DepositRequest, PrivateKey, bls12381::PrivateKey)` - A tuple containing: +/// - `DepositRequest` - A complete deposit request with valid signatures +/// - `PrivateKey` - The ED25519 private key used to sign the request +/// - `bls12381::PrivateKey` - The BLS private key used to sign the request pub fn create_deposit_request( index: u64, amount: u64, domain: Digest, private_key: Option, withdrawal_credentials: Option<[u8; 32]>, -) -> (DepositRequest, PrivateKey) { +) -> (DepositRequest, PrivateKey, bls12381::PrivateKey) { let withdrawal_credentials = if let Some(withdrawal_credentials) = withdrawal_credentials { withdrawal_credentials } else { @@ -409,31 +408,39 @@ pub fn create_deposit_request( withdrawal_credentials }; + // Generate node (ED25519) key let ed25519_private_key = if let Some(private_key) = private_key { private_key } else { - // Create deterministic but seed-based keys - // Generate a valid ED25519 private key using the seed PrivateKey::from_seed(index) }; + let node_pubkey = ed25519_private_key.public_key(); - let pubkey = ed25519_private_key.public_key(); + // Generate consensus (BLS) key + let bls_private_key = bls12381::PrivateKey::from_seed(index); + let consensus_pubkey = bls_private_key.public_key(); let mut deposit = DepositRequest { - pubkey, + node_pubkey, + consensus_pubkey, withdrawal_credentials, amount, - signature: [0u8; 64], + node_signature: [0u8; 64], + consensus_signature: [0u8; 96], index, }; - // Create the message to sign: hash of pubkey + withdrawal_credentials + amount + // Create the message to sign let message = deposit.as_message(domain); - //// Generate a valid ED25519 signature - let signature_bytes = ed25519_private_key.sign(None, &message); - deposit.signature.copy_from_slice(&signature_bytes); - (deposit, ed25519_private_key) + // Generate both signatures + let node_signature_bytes = ed25519_private_key.sign(None, &message); + deposit.node_signature.copy_from_slice(&node_signature_bytes); + + let consensus_signature_bytes = bls_private_key.sign(None, &message); + deposit.consensus_signature.copy_from_slice(&consensus_signature_bytes); + + (deposit, ed25519_private_key, bls_private_key) } /// Create a single WithdrawalRequest for testing @@ -489,7 +496,7 @@ pub fn execution_requests_to_requests(execution_requests: Vec) /// /// # Returns /// * `EngineConfig` - A fully configured engine config with sensible defaults for testing -pub fn get_default_engine_config>( +pub fn get_default_engine_config>( engine_client: C, oracle: O, partition_prefix: String, @@ -498,7 +505,7 @@ pub fn get_default_engine_config, participants: Vec<(PublicKey, bls12381::PublicKey)>, initial_state: ConsensusState, -) -> EngineConfig { +) -> EngineConfig { // For tests, generate a dummy BLS key EngineConfig { @@ -526,6 +533,7 @@ pub fn get_default_engine_config NetworkOracle for DummyOracle { async fn register(&mut self, _index: u64, _peers: Vec) {} } + +impl Manager for DummyOracle { + type PublicKey = PublicKey; + type Peers = Ordered; + + fn update(&mut self, _id: u64, _peers: Self::Peers) -> impl Future + Send { + //self.oracle.update(id, peers) + async {} + } + + async fn peer_set(&mut self, _id: u64) -> Option> { + //self.oracle.peer_set(id).await + todo!() + } + + async fn subscribe( + &mut self, + ) -> futures::channel::mpsc::UnboundedReceiver<( + u64, + Ordered, + Ordered, + )> { + //self.oracle.subscribe().await + let (_sender, receiver) = futures::channel::mpsc::unbounded(); + receiver + } +} + +impl Blocker for DummyOracle { + type PublicKey = PublicKey; + + fn block(&mut self, _peer: Self::PublicKey) -> impl Future + Send { + async {} + } +} diff --git a/node/src/test_harness/mock_engine_client.rs b/node/src/test_harness/mock_engine_client.rs index a85e0c63..4d21a64b 100644 --- a/node/src/test_harness/mock_engine_client.rs +++ b/node/src/test_harness/mock_engine_client.rs @@ -10,6 +10,8 @@ use alloy_rpc_types_engine::{ use rand::RngCore; use std::collections::HashMap; use std::sync::{Arc, Mutex}; +use commonware_cryptography::{ed25519, Signer}; +use commonware_cryptography::bls12381::primitives::variant::{MinPk, Variant}; use summit_types::{Block, EngineClient}; #[derive(Clone)] @@ -375,7 +377,7 @@ impl EngineClient for MockEngineClient { .expect("Payload ID not found") } - async fn check_payload(&self, block: &Block) -> PayloadStatus { + async fn check_payload(&self, block: &Block) -> PayloadStatus { let mut state = self.state.lock().unwrap(); if state.force_invalid { @@ -739,13 +741,13 @@ mod tests { // Simulate consensus: client2 receives the block through Engine API // First, client2 validates the block (like receiving it from network) - let block_for_validation = Block::compute_digest( + let block_for_validation = Block::::compute_digest( summit_types::Digest::from([0u8; 32]), // Genesis digest 1, 1000, block1.clone(), Vec::new(), - alloy_primitives::U256::from(1_000_000_000_000_000_000u64), + U256::from(1_000_000_000_000_000_000u64), 0, 1, None, @@ -819,7 +821,7 @@ mod tests { for client in [&client1, &client2, &client3] { if client.client_id() != producer.client_id() { // Each client validates the block (like receiving it from network) - let block_for_validation = summit_types::Block::compute_digest( + let block_for_validation = Block::::compute_digest( summit_types::Digest::from([(round - 1) as u8; 32]), // Parent digest round as u64, (round * 1000) as u64, @@ -918,7 +920,7 @@ mod tests { client1.commit_hash(new_fork_choice).await; // Simulate network propagation to client2 - let block_for_validation = Block::compute_digest( + let block_for_validation = Block::::compute_digest( summit_types::Digest::from([0u8; 32]), 1, 1000, diff --git a/node/src/tests/checkpointing.rs b/node/src/tests/checkpointing.rs index a6308f7e..978ec73e 100644 --- a/node/src/tests/checkpointing.rs +++ b/node/src/tests/checkpointing.rs @@ -35,6 +35,8 @@ fn test_checkpoint_created() { context.with_label("network"), simulated::Config { max_size: 1024 * 1024, + disconnect_on_block: false, + tracked_peer_sets: None, }, ); // Start network @@ -54,7 +56,7 @@ fn test_checkpoint_created() { key_stores.push(key_store); validators.push((node_public_key, consensus_public_key)); } - validators.sort_by_key(|(lhs, _)| *lhs); + validators.sort_by(|lhs, rhs| lhs.0.cmp(&rhs.0)); key_stores.sort_by_key(|ks| ks.node_key.public_key()); let node_public_keys: Vec<_> = validators.iter().map(|(pk, _)| pk.clone()).collect(); @@ -210,6 +212,8 @@ fn test_previous_header_hash_matches() { context.with_label("network"), simulated::Config { max_size: 1024 * 1024, + disconnect_on_block: false, + tracked_peer_sets: None, }, ); // Start network @@ -229,7 +233,7 @@ fn test_previous_header_hash_matches() { key_stores.push(key_store); validators.push((node_public_key, consensus_public_key)); } - validators.sort_by_key(|(lhs, _)| *lhs); + validators.sort_by(|lhs, rhs| lhs.0.cmp(&rhs.0)); key_stores.sort_by_key(|ks| ks.node_key.public_key()); let node_public_keys: Vec<_> = validators.iter().map(|(pk, _)| pk.clone()).collect(); @@ -398,6 +402,8 @@ fn test_single_engine_with_checkpoint() { context.with_label("network"), simulated::Config { max_size: 1024 * 1024, + disconnect_on_block: false, + tracked_peer_sets: None, }, ); // Start network @@ -505,6 +511,8 @@ fn test_node_joins_later_with_checkpoint() { context.with_label("network"), simulated::Config { max_size: 1024 * 1024, + disconnect_on_block: false, + tracked_peer_sets: None, }, ); // Start network @@ -524,7 +532,7 @@ fn test_node_joins_later_with_checkpoint() { key_stores.push(key_store); validators.push((node_public_key, consensus_public_key)); } - validators.sort_by_key(|(lhs, _)| *lhs); + validators.sort_by(|lhs, rhs| lhs.0.cmp(&rhs.0)); key_stores.sort_by_key(|ks| ks.node_key.public_key()); let node_public_keys: Vec<_> = validators.iter().map(|(pk, _)| pk.clone()).collect(); @@ -749,6 +757,8 @@ fn test_node_joins_later_with_checkpoint_not_in_genesis() { context.with_label("network"), simulated::Config { max_size: 1024 * 1024, + disconnect_on_block: false, + tracked_peer_sets: None, }, ); // Start network @@ -768,7 +778,7 @@ fn test_node_joins_later_with_checkpoint_not_in_genesis() { key_stores.push(key_store); validators.push((node_public_key, consensus_public_key)); } - validators.sort_by_key(|(lhs, _)| *lhs); + validators.sort_by(|lhs, rhs| lhs.0.cmp(&rhs.0)); key_stores.sort_by_key(|ks| ks.node_key.public_key()); let node_public_keys: Vec<_> = validators.iter().map(|(pk, _)| pk.clone()).collect(); diff --git a/node/src/tests/execution_requests.rs b/node/src/tests/execution_requests.rs index 5b79d12a..6fdb12dc 100644 --- a/node/src/tests/execution_requests.rs +++ b/node/src/tests/execution_requests.rs @@ -39,6 +39,8 @@ fn test_deposit_request_single() { context.with_label("network"), simulated::Config { max_size: 1024 * 1024, + disconnect_on_block: false, + tracked_peer_sets: None, }, ); // Start network @@ -58,7 +60,7 @@ fn test_deposit_request_single() { key_stores.push(key_store); validators.push((node_public_key, consensus_public_key)); } - validators.sort_by_key(|(lhs, _)| *lhs); + validators.sort_by(|lhs, rhs| lhs.0.cmp(&rhs.0)); key_stores.sort_by_key(|ks| ks.node_key.public_key()); let node_public_keys: Vec<_> = validators.iter().map(|(pk, _)| pk.clone()).collect(); @@ -74,7 +76,7 @@ fn test_deposit_request_single() { .expect("failed to convert genesis hash"); // Create a single deposit request using the helper - let (test_deposit, _) = common::create_deposit_request( + let (test_deposit, _, _) = common::create_deposit_request( 1, VALIDATOR_MINIMUM_STAKE, common::get_domain(), @@ -177,7 +179,7 @@ fn test_deposit_request_single() { let creds = common::parse_metric_substring(metric, "creds").expect("creds missing"); assert_eq!(creds, hex::encode(test_deposit.withdrawal_credentials)); - assert_eq!(pubkey_hex, test_deposit.pubkey.to_string()); + assert_eq!(pubkey_hex, test_deposit.node_pubkey.to_string()); assert_eq!(value, test_deposit.amount); processed_requests.insert(metric.to_string()); } else { @@ -227,6 +229,8 @@ fn test_deposit_request_top_up() { context.with_label("network"), simulated::Config { max_size: 1024 * 1024, + disconnect_on_block: false, + tracked_peer_sets: None, }, ); @@ -248,7 +252,7 @@ fn test_deposit_request_top_up() { key_stores.push(key_store); validators.push((node_public_key, consensus_public_key)); } - validators.sort_by_key(|(lhs, _)| *lhs); + validators.sort_by(|lhs, rhs| lhs.0.cmp(&rhs.0)); key_stores.sort_by_key(|ks| ks.node_key.public_key()); let node_public_keys: Vec<_> = validators.iter().map(|(pk, _)| pk.clone()).collect(); @@ -265,14 +269,14 @@ fn test_deposit_request_top_up() { .expect("failed to convert genesis hash"); // Create a single deposit request using the helper - let (test_deposit1, private_key) = common::create_deposit_request( + let (test_deposit1, private_key, _) = common::create_deposit_request( 1, VALIDATOR_MINIMUM_STAKE, common::get_domain(), None, None, ); - let (test_deposit2, _) = common::create_deposit_request( + let (test_deposit2, _, _) = common::create_deposit_request( 2, 10_000_000_000, common::get_domain(), @@ -385,7 +389,7 @@ fn test_deposit_request_top_up() { let creds = common::parse_metric_substring(metric, "creds").expect("creds missing"); assert_eq!(creds, hex::encode(test_deposit1.withdrawal_credentials)); - assert_eq!(ed_pubkey_hex, test_deposit1.pubkey.to_string()); + assert_eq!(ed_pubkey_hex, test_deposit1.node_pubkey.to_string()); // The amount from both deposits should be added to the validator balance assert_eq!(balance, test_deposit1.amount + test_deposit2.amount); processed_requests.insert(metric.to_string()); @@ -439,6 +443,8 @@ fn test_deposit_and_withdrawal_request_single() { context.with_label("network"), simulated::Config { max_size: 1024 * 1024, + disconnect_on_block: false, + tracked_peer_sets: None, }, ); @@ -460,7 +466,7 @@ fn test_deposit_and_withdrawal_request_single() { key_stores.push(key_store); validators.push((node_public_key, consensus_public_key)); } - validators.sort_by_key(|(lhs, _)| *lhs); + validators.sort_by(|lhs, rhs| lhs.0.cmp(&rhs.0)); key_stores.sort_by_key(|ks| ks.node_key.public_key()); let node_public_keys: Vec<_> = validators.iter().map(|(pk, _)| pk.clone()).collect(); @@ -477,7 +483,7 @@ fn test_deposit_and_withdrawal_request_single() { .expect("failed to convert genesis hash"); // Create a single deposit request using the helper - let (test_deposit, _) = common::create_deposit_request( + let (test_deposit, _, _) = common::create_deposit_request( n as u64, // use a private key seed that doesn't exist on the consensus state VALIDATOR_MINIMUM_STAKE, common::get_domain(), @@ -488,7 +494,7 @@ fn test_deposit_and_withdrawal_request_single() { let withdrawal_address = Address::from_slice(&test_deposit.withdrawal_credentials[12..32]); let test_withdrawal = common::create_withdrawal_request( withdrawal_address, - test_deposit.pubkey.as_ref().try_into().unwrap(), + test_deposit.node_pubkey.as_ref().try_into().unwrap(), test_deposit.amount, ); @@ -596,7 +602,7 @@ fn test_deposit_and_withdrawal_request_single() { let creds = common::parse_metric_substring(metric, "creds").expect("creds missing"); assert_eq!(creds, hex::encode(test_withdrawal.source_address)); - assert_eq!(ed_pubkey_hex, test_deposit.pubkey.to_string()); + assert_eq!(ed_pubkey_hex, test_deposit.node_pubkey.to_string()); assert_eq!(balance, test_deposit.amount - test_withdrawal.amount); processed_requests.insert(metric.to_string()); } else { @@ -662,6 +668,8 @@ fn test_partial_withdrawal_balance_below_minimum_stake() { context.with_label("network"), simulated::Config { max_size: 1024 * 1024, + disconnect_on_block: false, + tracked_peer_sets: None, }, ); @@ -683,7 +691,7 @@ fn test_partial_withdrawal_balance_below_minimum_stake() { key_stores.push(key_store); validators.push((node_public_key, consensus_public_key)); } - validators.sort_by_key(|(lhs, _)| *lhs); + validators.sort_by(|lhs, rhs| lhs.0.cmp(&rhs.0)); key_stores.sort_by_key(|ks| ks.node_key.public_key()); let node_public_keys: Vec<_> = validators.iter().map(|(pk, _)| pk.clone()).collect(); @@ -700,7 +708,7 @@ fn test_partial_withdrawal_balance_below_minimum_stake() { .expect("failed to convert genesis hash"); // Create a single deposit request using the helper - let (test_deposit, _) = common::create_deposit_request( + let (test_deposit, _, _) = common::create_deposit_request( n as u64, VALIDATOR_MINIMUM_STAKE, common::get_domain(), @@ -711,7 +719,7 @@ fn test_partial_withdrawal_balance_below_minimum_stake() { let withdrawal_address = Address::from_slice(&test_deposit.withdrawal_credentials[12..32]); let test_withdrawal1 = common::create_withdrawal_request( withdrawal_address, - test_deposit.pubkey.as_ref().try_into().unwrap(), + test_deposit.node_pubkey.as_ref().try_into().unwrap(), test_deposit.amount / 2, ); let mut test_withdrawal2 = test_withdrawal1.clone(); @@ -832,7 +840,7 @@ fn test_partial_withdrawal_balance_below_minimum_stake() { let creds = common::parse_metric_substring(metric, "creds").expect("creds missing"); assert_eq!(creds, hex::encode(test_withdrawal1.source_address)); - assert_eq!(ed_pubkey_hex, test_deposit.pubkey.to_string()); + assert_eq!(ed_pubkey_hex, test_deposit.node_pubkey.to_string()); assert_eq!(balance, 0); processed_requests.insert(metric.to_string()); } else { @@ -901,6 +909,8 @@ fn test_deposit_less_than_min_stake_and_withdrawal() { context.with_label("network"), simulated::Config { max_size: 1024 * 1024, + disconnect_on_block: false, + tracked_peer_sets: None, }, ); @@ -922,7 +932,7 @@ fn test_deposit_less_than_min_stake_and_withdrawal() { key_stores.push(key_store); validators.push((node_public_key, consensus_public_key)); } - validators.sort_by_key(|(lhs, _)| *lhs); + validators.sort_by(|lhs, rhs| lhs.0.cmp(&rhs.0)); key_stores.sort_by_key(|ks| ks.node_key.public_key()); let node_public_keys: Vec<_> = validators.iter().map(|(pk, _)| pk.clone()).collect(); @@ -939,7 +949,7 @@ fn test_deposit_less_than_min_stake_and_withdrawal() { .expect("failed to convert genesis hash"); // Create a single deposit request using the helper - let (test_deposit, _) = common::create_deposit_request( + let (test_deposit, _, _) = common::create_deposit_request( n as u64, VALIDATOR_MINIMUM_STAKE / 2, common::get_domain(), @@ -950,7 +960,7 @@ fn test_deposit_less_than_min_stake_and_withdrawal() { let withdrawal_address = Address::from_slice(&test_deposit.withdrawal_credentials[12..32]); let test_withdrawal = common::create_withdrawal_request( withdrawal_address, - test_deposit.pubkey.as_ref().try_into().unwrap(), + test_deposit.node_pubkey.as_ref().try_into().unwrap(), test_deposit.amount, ); @@ -1070,7 +1080,7 @@ fn test_deposit_less_than_min_stake_and_withdrawal() { let creds = common::parse_metric_substring(metric, "creds").expect("creds missing"); assert_eq!(creds, hex::encode(test_withdrawal.source_address)); - assert_eq!(ed_pubkey_hex, test_deposit.pubkey.to_string()); + assert_eq!(ed_pubkey_hex, test_deposit.node_pubkey.to_string()); assert_eq!(balance, test_deposit.amount - test_withdrawal.amount); processed_requests.insert(metric.to_string()); } @@ -1130,6 +1140,8 @@ fn test_deposit_and_withdrawal_request_multiple() { context.with_label("network"), simulated::Config { max_size: 1024 * 1024, + disconnect_on_block: false, + tracked_peer_sets: None, }, ); @@ -1151,7 +1163,7 @@ fn test_deposit_and_withdrawal_request_multiple() { key_stores.push(key_store); validators.push((node_public_key, consensus_public_key)); } - validators.sort_by_key(|(lhs, _)| *lhs); + validators.sort_by(|lhs, rhs| lhs.0.cmp(&rhs.0)); key_stores.sort_by_key(|ks| ks.node_key.public_key()); let node_public_keys: Vec<_> = validators.iter().map(|(pk, _)| pk.clone()).collect(); @@ -1171,7 +1183,7 @@ fn test_deposit_and_withdrawal_request_multiple() { let mut deposit_reqs = HashMap::new(); let mut withdrawal_reqs = HashMap::new(); for i in 0..deposit_reqs.len() { - let (test_deposit, _) = common::create_deposit_request( + let (test_deposit, _, _) = common::create_deposit_request( i as u64, VALIDATOR_MINIMUM_STAKE, common::get_domain(), @@ -1183,10 +1195,10 @@ fn test_deposit_and_withdrawal_request_multiple() { Address::from_slice(&test_deposit.withdrawal_credentials[12..32]); let test_withdrawal = common::create_withdrawal_request( withdrawal_address, - test_deposit.pubkey.as_ref().try_into().unwrap(), + test_deposit.node_pubkey.as_ref().try_into().unwrap(), test_deposit.amount, ); - deposit_reqs.insert(hex::encode(test_deposit.pubkey.clone()), test_deposit); + deposit_reqs.insert(hex::encode(test_deposit.node_pubkey.clone()), test_deposit); withdrawal_reqs.insert( hex::encode(test_withdrawal.validator_pubkey), test_withdrawal, @@ -1303,7 +1315,7 @@ fn test_deposit_and_withdrawal_request_multiple() { let creds = common::parse_metric_substring(metric, "creds").expect("creds missing"); assert_eq!(creds, hex::encode(deposit_req.withdrawal_credentials)); - assert_eq!(ed_pubkey_hex, deposit_req.pubkey.to_string()); + assert_eq!(ed_pubkey_hex, deposit_req.node_pubkey.to_string()); assert_eq!(balance, deposit_req.amount); } @@ -1319,7 +1331,7 @@ fn test_deposit_and_withdrawal_request_multiple() { let balance = value.parse::().unwrap(); assert_eq!(creds, hex::encode(withdrawal_req.source_address)); - assert_eq!(ed_pubkey_hex, deposit_req.pubkey.to_string()); + assert_eq!(ed_pubkey_hex, deposit_req.node_pubkey.to_string()); assert_eq!(balance, deposit_req.amount - withdrawal_req.amount); } if height_reached.len() as u32 >= n { @@ -1381,6 +1393,8 @@ fn test_deposit_request_invalid_signature() { context.with_label("network"), simulated::Config { max_size: 1024 * 1024, + disconnect_on_block: false, + tracked_peer_sets: None, }, ); // Start network @@ -1400,7 +1414,7 @@ fn test_deposit_request_invalid_signature() { key_stores.push(key_store); validators.push((node_public_key, consensus_public_key)); } - validators.sort_by_key(|(lhs, _)| *lhs); + validators.sort_by(|lhs, rhs| lhs.0.cmp(&rhs.0)); key_stores.sort_by_key(|ks| ks.node_key.public_key()); let node_public_keys: Vec<_> = validators.iter().map(|(pk, _)| pk.clone()).collect(); @@ -1416,7 +1430,7 @@ fn test_deposit_request_invalid_signature() { .expect("failed to convert genesis hash"); // Create a single deposit request using the helper - let (mut test_deposit, _) = common::create_deposit_request( + let (mut test_deposit, _, _) = common::create_deposit_request( 1, VALIDATOR_MINIMUM_STAKE, common::get_domain(), @@ -1424,15 +1438,16 @@ fn test_deposit_request_invalid_signature() { None, ); - let (test_deposit2, _) = common::create_deposit_request( + let (test_deposit2, _, _) = common::create_deposit_request( 2, VALIDATOR_MINIMUM_STAKE, common::get_domain(), None, None, ); - // Use signature from another private key - test_deposit.signature = test_deposit2.signature; + // Use signatures from another private key (to make it invalid) + test_deposit.node_signature = test_deposit2.node_signature; + test_deposit.consensus_signature = test_deposit2.consensus_signature; // Convert to ExecutionRequest and then to Requests let execution_requests = vec![ExecutionRequest::Deposit(test_deposit.clone())]; @@ -1521,7 +1536,7 @@ fn test_deposit_request_invalid_signature() { if let Some(pubkey_hex) = common::parse_metric_substring(metric, "pubkey") { let validator_id = common::extract_validator_id(metric) .expect("failed to parse validator id"); - assert_eq!(pubkey_hex, test_deposit.pubkey.to_string()); + assert_eq!(pubkey_hex, test_deposit.node_pubkey.to_string()); processed_requests.insert(validator_id); } else { println!("{}: {} (failed to parse pubkey)", metric, value); diff --git a/node/src/tests/syncer.rs b/node/src/tests/syncer.rs index 33b0be17..99ef29db 100644 --- a/node/src/tests/syncer.rs +++ b/node/src/tests/syncer.rs @@ -33,6 +33,8 @@ fn test_node_joins_later_no_checkpoint() { context.with_label("network"), simulated::Config { max_size: 1024 * 1024, + disconnect_on_block: false, + tracked_peer_sets: None, }, ); // Start network @@ -52,16 +54,16 @@ fn test_node_joins_later_no_checkpoint() { key_stores.push(key_store); validators.push((node_public_key, consensus_public_key)); } - validators.sort_by_key(|lhs, rhs| lhs.0.cmp(&rhs.0)); - key_stores - .sort_by_key(|lhs, rhs| lhs.node_key.public_key().cmp(&rhs.node_key.public_key())); + validators.sort_by(|lhs, rhs| lhs.0.cmp(&rhs.0)); + key_stores.sort_by(|lhs, rhs| lhs.node_key.public_key().cmp(&rhs.node_key.public_key())); // Separate initial validators from late joiner let initial_validators = &validators[..validators.len() - 1]; + let initial_node_public_keys: Vec<_> = initial_validators.iter().map(|(pk, _)| pk.clone()).collect(); // Register and link only initial validators - let mut registrations = common::register_validators(&mut oracle, initial_validators).await; - common::link_validators(&mut oracle, initial_validators, link.clone(), None).await; + let mut registrations = common::register_validators(&oracle, &initial_node_public_keys).await; + common::link_validators(&mut oracle, &initial_node_public_keys, link.clone(), None).await; // Create the engine clients let genesis_hash = from_hex_formatted(common::GENESIS_HASH).expect("failed to decode genesis hash"); @@ -141,7 +143,7 @@ fn test_node_joins_later_no_checkpoint() { common::register_validators(&mut oracle, &[public_key.clone()]).await; // Join the validator to the network - common::join_validator(&mut oracle, &public_key, initial_validators, link).await; + common::join_validator(&mut oracle, &public_key, &initial_node_public_keys, link).await; // Allow p2p connections to establish before starting engine context.sleep(Duration::from_millis(100)).await; @@ -261,6 +263,8 @@ fn test_node_joins_later_no_checkpoint_not_in_genesis() { context.with_label("network"), simulated::Config { max_size: 1024 * 1024, + disconnect_on_block: false, + tracked_peer_sets: None, }, ); // Start network @@ -280,16 +284,16 @@ fn test_node_joins_later_no_checkpoint_not_in_genesis() { key_stores.push(key_store); validators.push((node_public_key, consensus_public_key)); } - validators.sort_by_key(|lhs, rhs| lhs.0.cmp(&rhs.0)); - key_stores - .sort_by_key(|lhs, rhs| lhs.node_key.public_key().cmp(&rhs.node_key.public_key())); + validators.sort_by(|lhs, rhs| lhs.0.cmp(&rhs.0)); + key_stores.sort_by(|lhs, rhs| lhs.node_key.public_key().cmp(&rhs.node_key.public_key())); // Separate initial validators from late joiner let initial_validators = &validators[..validators.len() - 1]; + let initial_node_public_keys: Vec<_> = initial_validators.iter().map(|(pk, _)| pk.clone()).collect(); // Register and link only initial validators - let mut registrations = common::register_validators(&mut oracle, initial_validators).await; - common::link_validators(&mut oracle, initial_validators, link.clone(), None).await; + let mut registrations = common::register_validators(&oracle, &initial_node_public_keys).await; + common::link_validators(&mut oracle, &initial_node_public_keys, link.clone(), None).await; // Create the engine clients let genesis_hash = from_hex_formatted(common::GENESIS_HASH).expect("failed to decode genesis hash"); @@ -369,7 +373,7 @@ fn test_node_joins_later_no_checkpoint_not_in_genesis() { common::register_validators(&mut oracle, &[public_key.clone()]).await; // Join the validator to the network - common::join_validator(&mut oracle, &public_key, initial_validators, link).await; + common::join_validator(&mut oracle, &public_key, &initial_node_public_keys, link).await; // Allow p2p connections to establish before starting engine context.sleep(Duration::from_millis(100)).await; diff --git a/testnet/node0/key.pem b/testnet/node0/key.pem deleted file mode 100644 index f67a873f..00000000 --- a/testnet/node0/key.pem +++ /dev/null @@ -1 +0,0 @@ -19887e80c3ebb397ef2167b52beb89eab9208699f918dfb311c9a44cb52f8b25 \ No newline at end of file diff --git a/testnet/node1/key.pem b/testnet/node1/key.pem deleted file mode 100644 index f2909f0d..00000000 --- a/testnet/node1/key.pem +++ /dev/null @@ -1 +0,0 @@ -73e4378f96542f5f114783015018a4b2b4fd05bd0350a902453fe0c9aec04ae5 \ No newline at end of file diff --git a/testnet/node2/key.pem b/testnet/node2/key.pem deleted file mode 100644 index dd2659c0..00000000 --- a/testnet/node2/key.pem +++ /dev/null @@ -1 +0,0 @@ -a6bc4b7c0777a7b5a0c20e457458a56e69ad8e66cefe604d1d6a92809acb1857 \ No newline at end of file diff --git a/testnet/node3/key.pem b/testnet/node3/key.pem deleted file mode 100644 index 33e10019..00000000 --- a/testnet/node3/key.pem +++ /dev/null @@ -1 +0,0 @@ -79c344fb0ee59419c73669acc0ac4e437e19c2bb71f63899015862d78497a298 \ No newline at end of file From e77617e23e2584bddbc857e8442890d3f1a36ba3 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Mon, 10 Nov 2025 20:07:06 -0500 Subject: [PATCH 48/81] feat: start initial simplex instance from finalizer --- finalizer/src/actor.rs | 16 ++++ node/src/args.rs | 23 +---- node/src/bin/testnet.rs | 2 +- node/src/engine.rs | 3 +- node/src/test_harness/common.rs | 100 +++++++++++++++++--- node/src/test_harness/mock_engine_client.rs | 4 +- node/src/tests/syncer.rs | 16 +++- syncer/src/resolver/p2p.rs | 5 +- 8 files changed, 124 insertions(+), 45 deletions(-) diff --git a/finalizer/src/actor.rs b/finalizer/src/actor.rs index a8836d6e..97307818 100644 --- a/finalizer/src/actor.rs +++ b/finalizer/src/actor.rs @@ -144,6 +144,22 @@ impl< let mut signal = self.context.stopped().fuse(); let cancellation_token = self.cancellation_token.clone(); + // Initialize the current epoch with the validator set + // This ensures the orchestrator can start consensus immediately + let active_validators = self.state.get_active_validators(); + let network_keys: Vec<_> = active_validators + .iter() + .map(|(node_key, _)| node_key.clone()) + .collect(); + self.oracle.register(self.state.epoch, network_keys).await; + + self.orchestrator_mailbox + .report(Message::Enter(EpochTransition { + epoch: self.state.epoch, + validator_keys: active_validators, + })) + .await; + loop { if self.validator_exit { // If the validator was removed from the committee, trigger coordinated shutdown diff --git a/node/src/args.rs b/node/src/args.rs index 4ac806de..410870e2 100644 --- a/node/src/args.rs +++ b/node/src/args.rs @@ -9,7 +9,7 @@ use crate::{ }; use clap::{Args, Parser, Subcommand}; use commonware_cryptography::Signer; -use commonware_p2p::{Manager, authenticated}; +use commonware_p2p::authenticated; use commonware_runtime::{Handle, Metrics as _, Runner, Spawner as _, tokio}; use summit_rpc::{PathSender, start_rpc_server, start_rpc_server_for_genesis}; use tokio_util::sync::CancellationToken; @@ -17,7 +17,6 @@ use tokio_util::sync::CancellationToken; use alloy_primitives::B256; use alloy_rpc_types_engine::ForkchoiceState; use commonware_utils::from_hex_formatted; -use commonware_utils::set::Ordered; use futures::{channel::oneshot, future::try_join_all}; use governor::Quota; use ssz::Decode; @@ -322,17 +321,9 @@ impl Command { p2p_cfg.mailbox_size = MAILBOX_SIZE; // Start p2p - let (mut network, mut oracle) = + let (mut network, oracle) = authenticated::discovery::Network::new(context.with_label("network"), p2p_cfg); - // Provide authorized peers - oracle - .update( - initial_state.latest_height, - Ordered::from_iter(peers.iter().map(|(node_key, _)| node_key.clone())), - ) - .await; - let oracle = DiscoveryOracle::new(oracle); let config = EngineConfig::get_engine_config( engine_client, @@ -524,17 +515,9 @@ pub fn run_node_with_runtime( p2p_cfg.mailbox_size = MAILBOX_SIZE; // Start p2p - let (mut network, mut oracle) = + let (mut network, oracle) = authenticated::discovery::Network::new(context.with_label("network"), p2p_cfg); - // Provide authorized peers - oracle - .update( - initial_state.latest_height, - Ordered::from_iter(peers.iter().map(|(node_key, _)| node_key.clone())), - ) - .await; - let oracle = DiscoveryOracle::new(oracle); let config = EngineConfig::get_engine_config( diff --git a/node/src/bin/testnet.rs b/node/src/bin/testnet.rs index 5a6fb985..c5268aba 100644 --- a/node/src/bin/testnet.rs +++ b/node/src/bin/testnet.rs @@ -193,7 +193,7 @@ fn get_node_flags(node: usize) -> RunFlags { let path = format!("testnet/node{node}/"); RunFlags { - key_store_path: format!("{path}keys"), + key_store_path: path.clone(), store_path: format!("{path}db"), port: (26600 + (node * 10)) as u16, prom_port: (28600 + (node * 10)) as u16, diff --git a/node/src/engine.rs b/node/src/engine.rs index d76dc1d8..d21c34ee 100644 --- a/node/src/engine.rs +++ b/node/src/engine.rs @@ -322,7 +322,7 @@ where priority_requests: false, priority_responses: false, }; - let (resolver_rx, resolver) = + let (resolver_rx, resolver, resolver_handle) = summit_syncer::resolver::p2p::init(&self.context, resolver_config, backfill_network); let finalizer_handle = self.finalizer.start(); @@ -348,6 +348,7 @@ where finalizer_handle, syncer_handle, orchestrator_handle, + resolver_handle, ]) .fuse(); let cancellation_fut = self.cancellation_token.cancelled().fuse(); diff --git a/node/src/test_harness/common.rs b/node/src/test_harness/common.rs index 0e4012dd..4021bd3d 100644 --- a/node/src/test_harness/common.rs +++ b/node/src/test_harness/common.rs @@ -8,19 +8,20 @@ use alloy_primitives::{Address, B256, Bytes}; use alloy_rpc_types_engine::ForkchoiceState; use commonware_codec::Write; use commonware_p2p::simulated::{self, Link, Network, Oracle, Receiver, Sender}; +use commonware_p2p::{Blocker, Manager}; use commonware_runtime::{ Clock, Metrics, Runner as _, deterministic::{self, Runner}, }; use commonware_utils::from_hex_formatted; +use commonware_utils::set::Ordered; use governor::Quota; +use std::future::Future; use std::time::Duration; use std::{ collections::{HashMap, HashSet}, num::NonZeroU32, }; -use commonware_p2p::{Blocker, Manager}; -use commonware_utils::set::Ordered; use summit_types::account::{ValidatorAccount, ValidatorStatus}; use summit_types::consensus_state::ConsensusState; use summit_types::execution_request::{DepositRequest, ExecutionRequest, WithdrawalRequest}; @@ -138,7 +139,7 @@ pub fn run_until_height( simulated::Config { max_size: 1024 * 1024, disconnect_on_block: true, - tracked_peer_sets: Some(n as usize * 2), + tracked_peer_sets: Some(n as usize * 10), // Each engine may subscribe multiple times }, ); @@ -163,7 +164,8 @@ pub fn run_until_height( validators.sort_by(|lhs, rhs| lhs.0.cmp(&rhs.0)); key_stores.sort_by(|lhs, rhs| lhs.node_key.public_key().cmp(&rhs.node_key.public_key())); - let node_public_keys: Vec = validators.iter().map(|(pk, _)| pk.clone()).collect(); + let node_public_keys: Vec = + validators.iter().map(|(pk, _)| pk.clone()).collect(); let mut registrations = register_validators(&oracle, &node_public_keys).await; // Link all validators @@ -199,7 +201,7 @@ pub fn run_until_height( let config = get_default_engine_config( engine_client, - DummyOracle::default(), + SimulatedOracle::new(oracle.clone()), uid.clone(), genesis_hash, namespace, @@ -330,7 +332,6 @@ pub fn get_initial_state( }) } - /// Parse a substring from a metric name using XML-like tags /// /// # Arguments @@ -435,10 +436,14 @@ pub fn create_deposit_request( // Generate both signatures let node_signature_bytes = ed25519_private_key.sign(None, &message); - deposit.node_signature.copy_from_slice(&node_signature_bytes); + deposit + .node_signature + .copy_from_slice(&node_signature_bytes); let consensus_signature_bytes = bls_private_key.sign(None, &message); - deposit.consensus_signature.copy_from_slice(&consensus_signature_bytes); + deposit + .consensus_signature + .copy_from_slice(&consensus_signature_bytes); (deposit, ed25519_private_key, bls_private_key) } @@ -496,7 +501,10 @@ pub fn execution_requests_to_requests(execution_requests: Vec) /// /// # Returns /// * `EngineConfig` - A fully configured engine config with sensible defaults for testing -pub fn get_default_engine_config>( +pub fn get_default_engine_config< + C: EngineClient, + O: NetworkOracle + Blocker + Manager, +>( engine_client: C, oracle: O, partition_prefix: String, @@ -533,12 +541,75 @@ pub fn get_default_engine_config>( } } +#[derive(Clone, Debug)] +pub struct SimulatedOracle { + oracle: Oracle, +} + +impl SimulatedOracle { + pub fn new(oracle: Oracle) -> Self { + Self { oracle } + } +} + +impl NetworkOracle for SimulatedOracle { + async fn register(&mut self, index: u64, peers: Vec) { + self.oracle.update(index, Ordered::from(peers)).await; + } +} + +impl Blocker for SimulatedOracle { + type PublicKey = PublicKey; + + async fn block(&mut self, _public_key: Self::PublicKey) { + // Simulated oracle doesn't support blocking individual peers + // This is only used in production for misbehaving peers + } +} + +impl Manager for SimulatedOracle { + type PublicKey = PublicKey; + type Peers = Ordered; + + fn update(&mut self, id: u64, peers: Self::Peers) -> impl Future + Send { + self.oracle.update(id, peers) + } + + async fn peer_set(&mut self, id: u64) -> Option> { + self.oracle.peer_set(id).await + } + + async fn subscribe( + &mut self, + ) -> futures::channel::mpsc::UnboundedReceiver<( + u64, + Ordered, + Ordered, + )> { + self.oracle.subscribe().await + } +} + #[derive(Debug, Clone)] -pub struct DummyOracle {} +pub struct DummyOracle { + sender: std::sync::Arc< + std::sync::Mutex< + Option< + futures::channel::mpsc::UnboundedSender<( + u64, + Ordered, + Ordered, + )>, + >, + >, + >, +} impl Default for DummyOracle { fn default() -> Self { - Self {} + Self { + sender: std::sync::Arc::new(std::sync::Mutex::new(None)), + } } } @@ -551,12 +622,10 @@ impl Manager for DummyOracle { type Peers = Ordered; fn update(&mut self, _id: u64, _peers: Self::Peers) -> impl Future + Send { - //self.oracle.update(id, peers) async {} } async fn peer_set(&mut self, _id: u64) -> Option> { - //self.oracle.peer_set(id).await todo!() } @@ -567,8 +636,9 @@ impl Manager for DummyOracle { Ordered, Ordered, )> { - //self.oracle.subscribe().await - let (_sender, receiver) = futures::channel::mpsc::unbounded(); + let (sender, receiver) = futures::channel::mpsc::unbounded(); + // Store sender to keep channel alive + *self.sender.lock().unwrap() = Some(sender); receiver } } diff --git a/node/src/test_harness/mock_engine_client.rs b/node/src/test_harness/mock_engine_client.rs index 4d21a64b..f37cd2b8 100644 --- a/node/src/test_harness/mock_engine_client.rs +++ b/node/src/test_harness/mock_engine_client.rs @@ -7,11 +7,11 @@ use alloy_rpc_types_engine::{ ExecutionPayloadV2, ExecutionPayloadV3, ForkchoiceState, PayloadId, PayloadStatus, PayloadStatusEnum, }; +use commonware_cryptography::bls12381::primitives::variant::{MinPk, Variant}; +use commonware_cryptography::{Signer, ed25519}; use rand::RngCore; use std::collections::HashMap; use std::sync::{Arc, Mutex}; -use commonware_cryptography::{ed25519, Signer}; -use commonware_cryptography::bls12381::primitives::variant::{MinPk, Variant}; use summit_types::{Block, EngineClient}; #[derive(Clone)] diff --git a/node/src/tests/syncer.rs b/node/src/tests/syncer.rs index 99ef29db..1e9678f2 100644 --- a/node/src/tests/syncer.rs +++ b/node/src/tests/syncer.rs @@ -59,10 +59,14 @@ fn test_node_joins_later_no_checkpoint() { // Separate initial validators from late joiner let initial_validators = &validators[..validators.len() - 1]; - let initial_node_public_keys: Vec<_> = initial_validators.iter().map(|(pk, _)| pk.clone()).collect(); + let initial_node_public_keys: Vec<_> = initial_validators + .iter() + .map(|(pk, _)| pk.clone()) + .collect(); // Register and link only initial validators - let mut registrations = common::register_validators(&oracle, &initial_node_public_keys).await; + let mut registrations = + common::register_validators(&oracle, &initial_node_public_keys).await; common::link_validators(&mut oracle, &initial_node_public_keys, link.clone(), None).await; // Create the engine clients let genesis_hash = @@ -289,10 +293,14 @@ fn test_node_joins_later_no_checkpoint_not_in_genesis() { // Separate initial validators from late joiner let initial_validators = &validators[..validators.len() - 1]; - let initial_node_public_keys: Vec<_> = initial_validators.iter().map(|(pk, _)| pk.clone()).collect(); + let initial_node_public_keys: Vec<_> = initial_validators + .iter() + .map(|(pk, _)| pk.clone()) + .collect(); // Register and link only initial validators - let mut registrations = common::register_validators(&oracle, &initial_node_public_keys).await; + let mut registrations = + common::register_validators(&oracle, &initial_node_public_keys).await; common::link_validators(&mut oracle, &initial_node_public_keys, link.clone(), None).await; // Create the engine clients let genesis_hash = diff --git a/syncer/src/resolver/p2p.rs b/syncer/src/resolver/p2p.rs index 4a8ae930..65dc6a2e 100644 --- a/syncer/src/resolver/p2p.rs +++ b/syncer/src/resolver/p2p.rs @@ -43,6 +43,7 @@ pub fn init( ) -> ( mpsc::Receiver>, p2p::Mailbox>, + commonware_runtime::Handle<()>, ) where E: Rng + Spawner + Clock + GClock + Metrics, @@ -67,6 +68,6 @@ where priority_responses: config.priority_responses, }, ); - resolver_engine.start(backfill); - (receiver, resolver) + let handle = resolver_engine.start(backfill); + (receiver, resolver, handle) } From 37da8438fe420cf18b3933cf36f76d94d85bcab5 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Mon, 10 Nov 2025 20:40:32 -0500 Subject: [PATCH 49/81] feat: add epoch genesis hash to consensus state --- types/src/checkpoint.rs | 8 ++++++++ types/src/consensus_state.rs | 23 +++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/types/src/checkpoint.rs b/types/src/checkpoint.rs index 0f877ae1..84873082 100644 --- a/types/src/checkpoint.rs +++ b/types/src/checkpoint.rs @@ -156,6 +156,7 @@ mod tests { added_validators: Vec::new(), removed_validators: Vec::new(), forkchoice: Default::default(), + epoch_genesis_hash: [0u8; 32], }; let checkpoint = Checkpoint::new(&state); @@ -259,6 +260,7 @@ mod tests { added_validators: Vec::new(), removed_validators: Vec::new(), forkchoice: Default::default(), + epoch_genesis_hash: [0u8; 32], }; let checkpoint = Checkpoint::new(&state); @@ -292,6 +294,7 @@ mod tests { added_validators: Vec::new(), removed_validators: Vec::new(), forkchoice: Default::default(), + epoch_genesis_hash: [0u8; 32], }; let checkpoint = Checkpoint::new(&state); @@ -402,6 +405,7 @@ mod tests { added_validators: Vec::new(), removed_validators: Vec::new(), forkchoice: Default::default(), + epoch_genesis_hash: [0u8; 32], }; let checkpoint = Checkpoint::new(&state); @@ -440,6 +444,7 @@ mod tests { added_validators: Vec::new(), removed_validators: Vec::new(), forkchoice: Default::default(), + epoch_genesis_hash: [0u8; 32], }; let checkpoint = Checkpoint::new(&state); @@ -484,6 +489,7 @@ mod tests { added_validators: Vec::new(), removed_validators: Vec::new(), forkchoice: Default::default(), + epoch_genesis_hash: [0u8; 32], }; let checkpoint = Checkpoint::new(&original_state); @@ -524,6 +530,7 @@ mod tests { added_validators: Vec::new(), removed_validators: Vec::new(), forkchoice: Default::default(), + epoch_genesis_hash: [0u8; 32], }; let mut checkpoint = Checkpoint::new(&original_state); @@ -605,6 +612,7 @@ mod tests { added_validators: Vec::new(), removed_validators: Vec::new(), forkchoice: Default::default(), + epoch_genesis_hash: [0u8; 32], }; let checkpoint = Checkpoint::new(&original_state); diff --git a/types/src/consensus_state.rs b/types/src/consensus_state.rs index 977081ad..044193b3 100644 --- a/types/src/consensus_state.rs +++ b/types/src/consensus_state.rs @@ -22,6 +22,7 @@ pub struct ConsensusState { pub added_validators: Vec, pub removed_validators: Vec, pub forkchoice: ForkchoiceState, + pub epoch_genesis_hash: [u8; 32], } impl ConsensusState { @@ -182,6 +183,7 @@ impl EncodeSize for ConsensusState { + 32 // forkchoice.head_block_hash + 32 // forkchoice.safe_block_hash + 32 // forkchoice.finalized_block_hash + + 32 // epoch_genesis_hash } } @@ -250,6 +252,9 @@ impl Read for ConsensusState { finalized_block_hash: finalized_block_hash.into(), }; + let mut epoch_genesis_hash = [0u8; 32]; + buf.copy_to_slice(&mut epoch_genesis_hash); + Ok(Self { epoch, latest_height, @@ -261,6 +266,7 @@ impl Read for ConsensusState { added_validators, removed_validators, forkchoice, + epoch_genesis_hash, }) } } @@ -311,6 +317,9 @@ impl Write for ConsensusState { buf.put_slice(self.forkchoice.head_block_hash.as_slice()); buf.put_slice(self.forkchoice.safe_block_hash.as_slice()); buf.put_slice(self.forkchoice.finalized_block_hash.as_slice()); + + // Write epoch_genesis_hash + buf.put_slice(&self.epoch_genesis_hash); } } @@ -408,6 +417,10 @@ mod tests { decoded_state.validator_accounts.len(), original_state.validator_accounts.len() ); + assert_eq!( + decoded_state.epoch_genesis_hash, + original_state.epoch_genesis_hash + ); } #[test] @@ -417,6 +430,7 @@ mod tests { original_state.epoch = 7; original_state.set_latest_height(42); original_state.next_withdrawal_index = 5; + original_state.epoch_genesis_hash = [42u8; 32]; let deposit1 = create_test_deposit_request(1, 32000000000); let deposit2 = create_test_deposit_request(2, 16000000000); @@ -444,6 +458,10 @@ mod tests { decoded_state.next_withdrawal_index, original_state.next_withdrawal_index ); + assert_eq!( + decoded_state.epoch_genesis_hash, + original_state.epoch_genesis_hash + ); assert_eq!(decoded_state.deposit_queue.len(), 2); assert_eq!(decoded_state.deposit_queue[0].amount, 32000000000); @@ -526,6 +544,7 @@ mod tests { original_state.epoch = 5; original_state.set_latest_height(100); original_state.next_withdrawal_index = 42; + original_state.epoch_genesis_hash = [99u8; 32]; // Add some data let deposit = create_test_deposit_request(1, 32000000000); @@ -553,6 +572,10 @@ mod tests { restored_state.next_withdrawal_index, original_state.next_withdrawal_index ); + assert_eq!( + restored_state.epoch_genesis_hash, + original_state.epoch_genesis_hash + ); assert_eq!( restored_state.deposit_queue.len(), original_state.deposit_queue.len() From b8999c0b7dd3cbfbe5610bfc1d210854ec2c6b79 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Mon, 10 Nov 2025 20:58:19 -0500 Subject: [PATCH 50/81] feat: request epoch genesis hash from finalizer --- application/src/actor.rs | 7 ++++++- finalizer/src/actor.rs | 7 +++++++ finalizer/src/db.rs | 9 +++------ finalizer/src/ingress.rs | 14 ++++++++++++++ types/src/consensus_state.rs | 1 + 5 files changed, 31 insertions(+), 7 deletions(-) diff --git a/application/src/actor.rs b/application/src/actor.rs index b4f00d0b..c6c0a0b3 100644 --- a/application/src/actor.rs +++ b/application/src/actor.rs @@ -133,7 +133,12 @@ impl< if epoch == 0 { let _ = response.send(self.genesis_hash.into()); } else { - todo!("TODO(matthias): for later epochs, this has to be the hash of the last block from the prev epoch"); + let epoch_genesis_hash = finalizer + .get_epoch_genesis_hash(epoch) + .await + .await + .expect("failed to get epoch genesis hash from finalizer"); + let _ = response.send(epoch_genesis_hash.into()); } } Message::Propose { diff --git a/finalizer/src/actor.rs b/finalizer/src/actor.rs index 97307818..4d6c0840 100644 --- a/finalizer/src/actor.rs +++ b/finalizer/src/actor.rs @@ -195,6 +195,11 @@ impl< FinalizerMessage::GetAuxData { height, response } => { self.handle_aux_data_mailbox(height, response).await; }, + FinalizerMessage::GetEpochGenesisHash { epoch, response } => { + // TODO(matthias): verify that this can never happen + assert_eq!(epoch, self.state.epoch); + let _ = response.send(self.state.epoch_genesis_hash); + }, FinalizerMessage::QueryState { request, response } => { self.handle_consensus_state_query(request, response).await; }, @@ -334,6 +339,8 @@ impl< if is_last_block_of_epoch(new_height, self.epoch_num_of_blocks) { // Increment epoch self.state.epoch += 1; + // Set the epoch genesis hash for the next epoch + self.state.epoch_genesis_hash = self.state.forkchoice.head_block_hash.into(); if let Some(finalization) = finalization { // The finalized signatures should always be included on the last block diff --git a/finalizer/src/db.rs b/finalizer/src/db.rs index 3caa0a68..65b136a6 100644 --- a/finalizer/src/db.rs +++ b/finalizer/src/db.rs @@ -301,12 +301,9 @@ mod tests { use commonware_consensus::simplex::signing_scheme::utils::Signers; use commonware_consensus::simplex::types::{Finalization, Proposal}; use commonware_consensus::types::Round; - use commonware_cryptography::bls12381::{ - self, - primitives::{ - group::{Element, G2}, - variant::MinPk, - }, + use commonware_cryptography::bls12381::primitives::{ + group::{Element, G2}, + variant::MinPk, }; use commonware_runtime::buffer::PoolRef; use commonware_runtime::{Runner as _, deterministic::Runner}; diff --git a/finalizer/src/ingress.rs b/finalizer/src/ingress.rs index c4bd7358..2df53861 100644 --- a/finalizer/src/ingress.rs +++ b/finalizer/src/ingress.rs @@ -22,6 +22,10 @@ pub enum FinalizerMessage { height: u64, response: oneshot::Sender, }, + GetEpochGenesisHash { + epoch: u64, + response: oneshot::Sender<[u8; 32]>, + }, QueryState { request: ConsensusStateRequest, response: oneshot::Sender, @@ -61,6 +65,16 @@ impl FinalizerMailbox { receiver } + pub async fn get_epoch_genesis_hash(&mut self, epoch: u64) -> oneshot::Receiver<[u8; 32]> { + let (response, receiver) = oneshot::channel(); + self.sender + .send(FinalizerMessage::GetEpochGenesisHash { epoch, response }) + .await + .expect("Unable to send to main Finalizer loop"); + + receiver + } + pub async fn get_latest_checkpoint(&mut self) -> Option { let (response, rx) = oneshot::channel(); let request = ConsensusStateRequest::GetCheckpoint; diff --git a/types/src/consensus_state.rs b/types/src/consensus_state.rs index 044193b3..d0f24ada 100644 --- a/types/src/consensus_state.rs +++ b/types/src/consensus_state.rs @@ -29,6 +29,7 @@ impl ConsensusState { pub fn new(forkchoice: ForkchoiceState) -> Self { Self { forkchoice, + epoch_genesis_hash: forkchoice.head_block_hash.into(), ..Default::default() } } From ac1d2fa3728d2d96fc7c35cbdc5e3fb08219b810 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Tue, 11 Nov 2025 14:32:14 -0500 Subject: [PATCH 51/81] chore: remove generics from orchestrator message --- finalizer/src/actor.rs | 6 +++--- finalizer/src/config.rs | 7 +++---- orchestrator/src/actor.rs | 7 +++---- orchestrator/src/ingress.rs | 16 +++++++--------- 4 files changed, 16 insertions(+), 20 deletions(-) diff --git a/finalizer/src/actor.rs b/finalizer/src/actor.rs index 4d6c0840..f42395c7 100644 --- a/finalizer/src/actor.rs +++ b/finalizer/src/actor.rs @@ -8,7 +8,7 @@ use commonware_codec::{DecodeExt as _, Encode, ReadExt as _}; use commonware_consensus::Reporter; use commonware_consensus::simplex::signing_scheme::{Scheme, bls12381_multisig}; use commonware_consensus::simplex::types::Finalization; -use commonware_cryptography::bls12381::primitives::variant::{MinPk, Variant}; +use commonware_cryptography::bls12381::primitives::variant::Variant; use commonware_cryptography::{Digestible, Hasher, Sha256, Signer, Verifier as _, bls12381}; use commonware_runtime::{Clock, ContextCell, Handle, Metrics, Spawner, Storage, spawn_cell}; use commonware_storage::translator::TwoCap; @@ -62,7 +62,7 @@ pub struct Finalizer< validator_withdrawal_period: u64, // in blocks validator_onboarding_limit_per_block: usize, oracle: O, - orchestrator_mailbox: summit_orchestrator::Mailbox, + orchestrator_mailbox: summit_orchestrator::Mailbox, node_public_key: PublicKey, validator_exit: bool, cancellation_token: CancellationToken, @@ -81,7 +81,7 @@ impl< { pub async fn new( context: R, - cfg: FinalizerConfig, + cfg: FinalizerConfig, ) -> (Self, FinalizerMailbox>) { let (tx, rx) = mpsc::channel(cfg.mailbox_size); // todo(dalton) pull mailbox size from config let state_cfg = StateConfig { diff --git a/finalizer/src/config.rs b/finalizer/src/config.rs index 942798a4..c3c2ffe4 100644 --- a/finalizer/src/config.rs +++ b/finalizer/src/config.rs @@ -1,5 +1,4 @@ -use commonware_cryptography::Signer; -use commonware_cryptography::bls12381::primitives::variant::{MinPk, Variant}; +use commonware_cryptography::bls12381::primitives::variant::Variant; use commonware_runtime::buffer::PoolRef; use std::marker::PhantomData; use summit_orchestrator::Mailbox as OrchestratorMailbox; @@ -7,12 +6,12 @@ use summit_types::network_oracle::NetworkOracle; use summit_types::{EngineClient, PublicKey, consensus_state::ConsensusState}; use tokio_util::sync::CancellationToken; -pub struct FinalizerConfig, S: Signer, V: Variant> { +pub struct FinalizerConfig, V: Variant> { pub mailbox_size: usize, pub db_prefix: String, pub engine_client: C, pub oracle: O, - pub orchestrator_mailbox: OrchestratorMailbox, + pub orchestrator_mailbox: OrchestratorMailbox, pub epoch_num_of_blocks: u64, pub validator_max_withdrawals_per_block: usize, pub validator_minimum_stake: u64, // in gwei diff --git a/orchestrator/src/actor.rs b/orchestrator/src/actor.rs index fd5ad071..243a7cb9 100644 --- a/orchestrator/src/actor.rs +++ b/orchestrator/src/actor.rs @@ -14,7 +14,7 @@ use commonware_consensus::{ }; use commonware_cryptography::{ Signer, - bls12381::primitives::variant::{MinPk, Variant}, + bls12381::primitives::variant::Variant, }; use commonware_macros::select; use commonware_p2p::{ @@ -65,7 +65,7 @@ where A: Automaton, Digest = Digest> + Relay, { context: ContextCell, - mailbox: mpsc::Receiver>, + mailbox: mpsc::Receiver, application: A, oracle: B, @@ -88,7 +88,7 @@ where C: Signer, A: Automaton, Digest = Digest> + Relay, { - pub fn new(context: E, config: Config) -> (Self, Mailbox) { + pub fn new(context: E, config: Config) -> (Self, Mailbox) { let (sender, mailbox) = mpsc::channel(config.mailbox_size); let pool_ref = PoolRef::new(NZUsize!(16_384), NZUsize!(10_000)); @@ -322,7 +322,6 @@ where info!(epoch, "exited epoch"); } - Message::_Phantom(_, _) => unreachable!(), } }, } diff --git a/orchestrator/src/ingress.rs b/orchestrator/src/ingress.rs index 68ca6b4f..4073a85e 100644 --- a/orchestrator/src/ingress.rs +++ b/orchestrator/src/ingress.rs @@ -1,32 +1,30 @@ //! Inbound communication channel for epoch transitions. use commonware_consensus::{Reporter, types::Epoch}; -use commonware_cryptography::{PublicKey, bls12381::primitives::variant::Variant}; use futures::{SinkExt, channel::mpsc}; use summit_types::scheme::EpochTransition; /// Messages that can be sent to the orchestrator. -pub enum Message { +pub enum Message { Enter(EpochTransition), Exit(Epoch), - _Phantom(std::marker::PhantomData, std::marker::PhantomData

), } /// Inbound communication channel for epoch transitions. #[derive(Debug, Clone)] -pub struct Mailbox { - sender: mpsc::Sender>, +pub struct Mailbox { + sender: mpsc::Sender, } -impl Mailbox { +impl Mailbox { /// Create a new [Mailbox]. - pub fn new(sender: mpsc::Sender>) -> Self { + pub fn new(sender: mpsc::Sender) -> Self { Self { sender } } } -impl Reporter for Mailbox { - type Activity = Message; +impl Reporter for Mailbox { + type Activity = Message; async fn report(&mut self, activity: Self::Activity) { self.sender From 84ede8689095a66895a0591b462a16ff67e4a5cd Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Tue, 11 Nov 2025 16:11:12 -0500 Subject: [PATCH 52/81] fix: use subscribe instead of get_block to get the parent block --- Cargo.lock | 6 ------ application/Cargo.toml | 6 ------ application/src/actor.rs | 12 ++++++++++-- finalizer/src/actor.rs | 2 +- orchestrator/src/actor.rs | 5 +---- 5 files changed, 12 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2a871d6b..91adfa2f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5600,13 +5600,7 @@ dependencies = [ name = "summit-application" version = "0.0.0" dependencies = [ - "alloy-eips", - "alloy-primitives", - "alloy-provider", - "alloy-rpc-types-engine", - "alloy-transport-ipc", "anyhow", - "bytes", "commonware-consensus", "commonware-cryptography", "commonware-macros", diff --git a/application/Cargo.toml b/application/Cargo.toml index 6ce9a5b8..9afa4231 100644 --- a/application/Cargo.toml +++ b/application/Cargo.toml @@ -7,7 +7,6 @@ edition.workspace = true summit-types.workspace = true summit-syncer.workspace = true summit-finalizer.workspace = true -bytes.workspace = true anyhow.workspace = true tracing.workspace = true @@ -18,14 +17,9 @@ commonware-macros.workspace = true commonware-utils.workspace = true futures.workspace = true -alloy-provider.workspace = true -alloy-rpc-types-engine.workspace = true -alloy-eips.workspace = true -alloy-primitives.workspace = true governor.workspace = true rand.workspace = true tokio-util.workspace = true -alloy-transport-ipc.workspace = true # For metrics - activate with `prom` feature metrics = { version = "0.24.0", optional = true } diff --git a/application/src/actor.rs b/application/src/actor.rs index c6c0a0b3..81e365b9 100644 --- a/application/src/actor.rs +++ b/application/src/actor.rs @@ -30,7 +30,7 @@ use tracing::{error, info, warn}; #[cfg(feature = "prom")] use metrics::histogram; -use summit_syncer::ingress::mailbox::{Identifier, Mailbox as SyncerMailbox}; +use summit_syncer::ingress::mailbox::Mailbox as SyncerMailbox; use summit_types::{Block, Digest, EngineClient}; // Define a future that checks if the oneshot channel is closed using a mutable reference @@ -265,9 +265,17 @@ impl< let parent_request = if parent.1 == self.genesis_hash.into() { Either::Left(future::ready(Ok(Block::genesis(self.genesis_hash)))) } else { + let parent_round = if parent.0 == 0 { + // Parent view is 0, which means that this is the first block of the epoch + // TODO(matthias): verify that the parent view of the first block is always 0 (nullify) + None + } else { + Some(Round::new(round.epoch(), parent.0)) + }; Either::Right( syncer - .get_block(Identifier::Commitment(parent.1)) + .subscribe(parent_round, parent.1) + .await .map(|x| x.context("")), ) }; diff --git a/finalizer/src/actor.rs b/finalizer/src/actor.rs index f42395c7..c9a6abd3 100644 --- a/finalizer/src/actor.rs +++ b/finalizer/src/actor.rs @@ -340,7 +340,7 @@ impl< // Increment epoch self.state.epoch += 1; // Set the epoch genesis hash for the next epoch - self.state.epoch_genesis_hash = self.state.forkchoice.head_block_hash.into(); + self.state.epoch_genesis_hash = block.digest().0; if let Some(finalization) = finalization { // The finalized signatures should always be included on the last block diff --git a/orchestrator/src/actor.rs b/orchestrator/src/actor.rs index 243a7cb9..79f64e69 100644 --- a/orchestrator/src/actor.rs +++ b/orchestrator/src/actor.rs @@ -12,10 +12,7 @@ use commonware_consensus::{ types::Epoch, utils::last_block_in_epoch, }; -use commonware_cryptography::{ - Signer, - bls12381::primitives::variant::Variant, -}; +use commonware_cryptography::{Signer, bls12381::primitives::variant::Variant}; use commonware_macros::select; use commonware_p2p::{ Blocker, Receiver, Recipients, Sender, From 302f872a161e6a3512241089d2df7ce640cbec6b Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Tue, 11 Nov 2025 18:05:10 -0500 Subject: [PATCH 53/81] feat: send block + finalization on last block of epoch to finalizer --- application/src/actor.rs | 2 +- finalizer/src/actor.rs | 7 ++---- syncer/src/actor.rs | 6 +++++ syncer/src/finalizer.rs | 23 ++++++++++++++---- syncer/src/ingress/orchestrator.rs | 39 ++++++++++++++++++++++++++---- syncer/src/lib.rs | 7 +++--- syncer/src/mocks/application.rs | 6 +---- types/src/block.rs | 25 ++++++++++--------- 8 files changed, 79 insertions(+), 36 deletions(-) diff --git a/application/src/actor.rs b/application/src/actor.rs index 81e365b9..0c9a8806 100644 --- a/application/src/actor.rs +++ b/application/src/actor.rs @@ -279,7 +279,7 @@ impl< .map(|x| x.context("")), ) }; - let parent = parent_request.await.unwrap(); + let parent = parent_request.await.expect("sender dropped"); #[cfg(feature = "prom")] { diff --git a/finalizer/src/actor.rs b/finalizer/src/actor.rs index c9a6abd3..ac2e9f77 100644 --- a/finalizer/src/actor.rs +++ b/finalizer/src/actor.rs @@ -176,11 +176,8 @@ impl< Update::Tip(_height, _digest) => { // I don't think we need this } - Update::Block(block, ack_tx) => { - self.handle_execution_block(ack_tx, block, None, &mut last_committed_timestamp).await; - } - Update::BlockWithFinalization(block, finalization, ack_tx) => { - self.handle_execution_block(ack_tx, block, Some(finalization), &mut last_committed_timestamp).await; + Update::Block((block, finalization), ack_tx) => { + self.handle_execution_block(ack_tx, block, finalization, &mut last_committed_timestamp).await; } } }, diff --git a/syncer/src/actor.rs b/syncer/src/actor.rs index 976d5315..1ff518bf 100644 --- a/syncer/src/actor.rs +++ b/syncer/src/actor.rs @@ -316,6 +316,7 @@ impl< orchestrator, notifier_rx, sync_height, + self.epoch_length, ) .await; finalizer.start(); @@ -502,6 +503,11 @@ impl< let block = self.get_finalized_block(height).await; result.send(block).unwrap_or_else(|_| warn!(?height, "Failed to send block to orchestrator")); } + Orchestration::GetWithFinalization { height, result } => { + let block = self.get_finalized_block(height).await; + let finalization = self.get_finalization_by_height(height).await; + result.send((block, finalization)).unwrap_or_else(|_| warn!(?height, "Failed to send block and finalization to orchestrator")); + } Orchestration::Processed { height, digest } => { // Update metrics #[cfg(feature = "prom")] diff --git a/syncer/src/finalizer.rs b/syncer/src/finalizer.rs index eff2507a..6dfba99f 100644 --- a/syncer/src/finalizer.rs +++ b/syncer/src/finalizer.rs @@ -4,8 +4,8 @@ use commonware_consensus::{Block, Reporter}; use commonware_runtime::{Clock, ContextCell, Handle, Metrics, Spawner, Storage, spawn_cell}; use futures::channel::oneshot; use futures::{StreamExt, channel::mpsc}; +use summit_types::utils::is_last_block_of_epoch; use tracing::{debug, error}; - // The key used to store the last indexed height in the metadata store. /// Requests the finalized blocks (in order) from the orchestrator, sends them to the application, @@ -25,13 +25,16 @@ pub struct Finalizer< application: Z, // Orchestrator that stores the finalized blocks. - orchestrator: Orchestrator, + orchestrator: Orchestrator, // Notifier to indicate that the finalized blocks have been updated and should be re-queried. notifier_rx: mpsc::Receiver<()>, // The lowest height from which to begin syncing sync_height: u64, + + // Number of blocks per epoch + epoch_length: u64, } impl< @@ -45,9 +48,10 @@ impl< pub async fn new( context: R, application: Z, - orchestrator: Orchestrator, + orchestrator: Orchestrator, notifier_rx: mpsc::Receiver<()>, sync_height: u64, + epoch_length: u64, ) -> Self { Self { context: ContextCell::new(context), @@ -55,6 +59,7 @@ impl< orchestrator, notifier_rx, sync_height, + epoch_length, } } @@ -76,8 +81,14 @@ impl< // The next height to process is the next height after the last processed height. let height = latest + 1; + let (block, finalized) = if is_last_block_of_epoch(height, self.epoch_length) { + self.orchestrator.get_with_finalization(height).await + } else { + (self.orchestrator.get(height).await, None) + }; + // Attempt to get the next block from the orchestrator. - if let Some(block) = self.orchestrator.get(height).await { + if let Some(block) = block { // Sanity-check that the block height is the one we expect. assert!(block.height() == height, "block height mismatch"); @@ -89,7 +100,9 @@ impl< let commitment = block.commitment(); let (ack_tx, ack_rx) = oneshot::channel(); - self.application.report(Update::Block(block, ack_tx)).await; + self.application + .report(Update::Block((block, finalized), ack_tx)) + .await; if let Err(e) = ack_rx.await { error!(?e, height, "application did not acknowledge block"); return; diff --git a/syncer/src/ingress/orchestrator.rs b/syncer/src/ingress/orchestrator.rs index da711ff8..32afc7da 100644 --- a/syncer/src/ingress/orchestrator.rs +++ b/syncer/src/ingress/orchestrator.rs @@ -1,4 +1,6 @@ use crate::Block; +use commonware_consensus::simplex::signing_scheme::Scheme; +use commonware_consensus::simplex::types::Finalization; use futures::{ SinkExt, channel::{mpsc, oneshot}, @@ -9,7 +11,7 @@ use tracing::error; /// /// We break this into a separate enum to establish a separate priority for /// finalizer messages over consensus messages. -pub enum Orchestration { +pub enum Orchestration { /// A request to get the next finalized block. Get { /// The height of the block to get. @@ -17,6 +19,12 @@ pub enum Orchestration { /// A channel to send the block, if found. result: oneshot::Sender>, }, + /// A request to get the next finalized block together with the finalization. + GetWithFinalization { + height: u64, + #[allow(clippy::type_complexity)] + result: oneshot::Sender<(Option, Option>)>, + }, /// A notification that a block has been processed by the application. Processed { /// The height of the processed block. @@ -33,13 +41,13 @@ pub enum Orchestration { /// A handle for the finalizer to communicate with the main actor loop. #[derive(Clone)] -pub struct Orchestrator { - sender: mpsc::Sender>, +pub struct Orchestrator { + sender: mpsc::Sender>, } -impl Orchestrator { +impl Orchestrator { /// Creates a new orchestrator. - pub fn new(sender: mpsc::Sender>) -> Self { + pub fn new(sender: mpsc::Sender>) -> Self { Self { sender } } @@ -61,6 +69,27 @@ impl Orchestrator { receiver.await.unwrap_or(None) } + /// Gets the finalized block at the given height together with the finalization. + pub async fn get_with_finalization( + &mut self, + height: u64, + ) -> (Option, Option>) { + let (response, receiver) = oneshot::channel(); + if self + .sender + .send(Orchestration::GetWithFinalization { + height, + result: response, + }) + .await + .is_err() + { + error!("failed to send get_with_finalization message to actor: receiver dropped"); + return (None, None); + } + receiver.await.unwrap_or((None, None)) + } + /// Notifies the actor that a block has been processed. pub async fn processed(&mut self, height: u64, digest: B::Commitment) { if self diff --git a/syncer/src/lib.rs b/syncer/src/lib.rs index 1892c833..c8a07039 100644 --- a/syncer/src/lib.rs +++ b/syncer/src/lib.rs @@ -83,9 +83,10 @@ pub enum Update { /// a block as delivered until the application explicitly acknowledges the update. /// If the sender is dropped before acknowledgement, marshal will exit (assuming /// the application is shutting down). - Block(B, oneshot::Sender<()>), - /// A new finalized block with finalization - BlockWithFinalization(B, Finalization, oneshot::Sender<()>), + Block( + (B, Option>), + oneshot::Sender<()>, + ), } #[cfg(test)] diff --git a/syncer/src/mocks/application.rs b/syncer/src/mocks/application.rs index e87ece2a..c40e1afa 100644 --- a/syncer/src/mocks/application.rs +++ b/syncer/src/mocks/application.rs @@ -45,11 +45,7 @@ impl Reporter for Application { Update::Tip(height, commitment) => { *self.tip.lock().unwrap() = Some((height, commitment)); } - Update::Block(block, ack_tx) => { - self.blocks.lock().unwrap().insert(block.height(), block); - let _ = ack_tx.send(()); - } - Update::BlockWithFinalization(block, _finalization, ack_tx) => { + Update::Block((block, _), ack_tx) => { self.blocks.lock().unwrap().insert(block.height(), block); let _ = ack_tx.send(()); } diff --git a/types/src/block.rs b/types/src/block.rs index 8af21ce4..190e2fa3 100644 --- a/types/src/block.rs +++ b/types/src/block.rs @@ -388,12 +388,12 @@ impl EncodeSize for Finalized { } #[derive(Clone, Debug, PartialEq, Eq)] -pub struct BlockEnvelope { +pub struct BlockWithFinalization { pub block: Block, pub finalized: Option, Digest>>, } -impl Digestible for BlockEnvelope { +impl Digestible for BlockWithFinalization { type Digest = Digest; fn digest(&self) -> Digest { @@ -401,7 +401,7 @@ impl Digestible for BlockEnvelope { } } -impl Committable for BlockEnvelope { +impl Committable for BlockWithFinalization { type Commitment = Digest; fn commitment(&self) -> Digest { @@ -409,7 +409,7 @@ impl Committable for BlockEnvelope { } } -impl ConsensusBlock for BlockEnvelope { +impl ConsensusBlock for BlockWithFinalization { fn height(&self) -> u64 { self.block.header.height } @@ -419,7 +419,7 @@ impl ConsensusBlock for BlockEnvelope { } } -impl Read for BlockEnvelope { +impl Read for BlockWithFinalization { type Cfg = (); fn read_cfg(buf: &mut impl Buf, _: &Self::Cfg) -> Result { @@ -437,7 +437,7 @@ impl Read for BlockEnvelope { } } -impl Write for BlockEnvelope { +impl Write for BlockWithFinalization { fn write(&self, buf: &mut impl BufMut) { self.block.write(buf); if let Some(ref finalized) = self.finalized { @@ -449,7 +449,7 @@ impl Write for BlockEnvelope { } } -impl EncodeSize for BlockEnvelope { +impl EncodeSize for BlockWithFinalization { fn encode_size(&self) -> usize { let mut size = self.block.encode_size() + 1; // +1 for the has_finalized flag if let Some(ref finalized) = self.finalized { @@ -627,14 +627,15 @@ mod test { #[test] fn test_block_envelope_without_finalization() { let block = Block::::genesis([0; 32]); - let envelope = BlockEnvelope { + let envelope = BlockWithFinalization { block: block.clone(), finalized: None, }; // Test encoding and decoding let encoded = envelope.encode(); - let decoded = BlockEnvelope::::decode(encoded.clone()).unwrap(); + let decoded = + BlockWithFinalization::::decode(encoded.clone()).unwrap(); // Verify round-trip: encode the decoded value and compare bytes let re_encoded = decoded.encode(); @@ -655,7 +656,7 @@ mod test { #[test] fn test_block_envelope_encode_size_without_finalization() { let block = Block::::genesis([0; 32]); - let envelope = BlockEnvelope { + let envelope = BlockWithFinalization { block: block.clone(), finalized: None, }; @@ -671,7 +672,7 @@ mod test { #[test] fn test_block_envelope_digestible() { let block = Block::::genesis([0; 32]); - let envelope = BlockEnvelope { + let envelope = BlockWithFinalization { block: block.clone(), finalized: None, }; @@ -684,7 +685,7 @@ mod test { #[test] fn test_block_envelope_consensus_block() { let block = Block::::genesis([0; 32]); - let envelope = BlockEnvelope { + let envelope = BlockWithFinalization { block: block.clone(), finalized: None, }; From e5ba1d9a51f049b364f8fd44f1749f6f75fe942a Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Tue, 11 Nov 2025 18:07:55 -0500 Subject: [PATCH 54/81] chore: remove registry --- types/src/lib.rs | 1 - types/src/registry.rs | 342 ------------------------------------------ 2 files changed, 343 deletions(-) delete mode 100644 types/src/registry.rs diff --git a/types/src/lib.rs b/types/src/lib.rs index eb05f11c..b5d80c12 100644 --- a/types/src/lib.rs +++ b/types/src/lib.rs @@ -9,7 +9,6 @@ pub mod genesis; pub mod header; pub mod keystore; pub mod network_oracle; -pub mod registry; #[cfg(feature = "e2e")] pub mod reth; pub mod scheme; diff --git a/types/src/registry.rs b/types/src/registry.rs deleted file mode 100644 index fd33806f..00000000 --- a/types/src/registry.rs +++ /dev/null @@ -1,342 +0,0 @@ -use crate::PublicKey; -use commonware_consensus::types::View; -use commonware_p2p::Manager; -use commonware_utils::set::Ordered; -use futures::channel::mpsc::{UnboundedReceiver, UnboundedSender}; -use std::collections::{BTreeMap, HashSet}; -use std::sync::{Arc, RwLock}; - -#[derive(Default, Clone, Debug)] -struct Inner { - sets: BTreeMap>, - #[allow(clippy::type_complexity)] - subscribers: Vec, Ordered)>>, -} - -#[derive(Clone, Debug)] -pub struct Registry { - // Map from View -> immutable participant data - // Once a view is added, it never changes - inner: Arc>, -} - -impl Registry { - pub fn new(id: u64, participants: Vec) -> Self { - let mut sets = BTreeMap::new(); - sets.insert(id, Ordered::from(participants)); - let inner = Inner { - sets, - subscribers: vec![], - }; - Self { - inner: Arc::new(RwLock::new(inner)), - } - } - - pub fn update_registry(&self, id: u64, add: &[PublicKey], remove: &[PublicKey]) { - let mut inner = self.inner.write().unwrap(); - - // TODO(matthias): we should also consider enforcing that the previous id must exist, - // and do something like inner.sets.get(id - 1) - let (_last_id, old_set) = inner - .sets - .last_key_value() - .expect("registry was initialized with an id"); - - let mut new_set = - Vec::with_capacity((old_set.len() + add.len()).saturating_sub(remove.len())); - let remove: HashSet = HashSet::from_iter(remove.iter().cloned()); - for key in old_set { - if !remove.contains(key) { - new_set.push(key.clone()); - } - } - for key in add { - new_set.push(key.clone()); - } - - let old_set = old_set.clone(); - inner.sets.insert(id, Ordered::from(new_set.clone())); - - // Notify all subscribers - let notification = (id, old_set, Ordered::from(new_set)); - inner - .subscribers - .retain(|tx| tx.unbounded_send(notification.clone()).is_ok()); - - // TODO(matthias): consider garbage collection for old IDs - } -} - -impl Manager for Registry { - type PublicKey = PublicKey; - - type Peers = Vec; - fn update(&mut self, id: u64, peers: Self::Peers) -> impl Future + Send { - let mut inner = self.inner.write().unwrap(); - - // Since IDs are monotonically increasing, the old set is the last one in the map - let old_set = inner - .sets - .last_key_value() - .map(|(_, set)| set.clone()) - .unwrap_or_else(|| Ordered::from(Vec::new())); - - let new_set = Ordered::from(peers); - inner.sets.insert(id, new_set.clone()); - - // Notify all subscribers - let notification = (id, old_set, new_set); - inner - .subscribers - .retain(|tx| tx.unbounded_send(notification.clone()).is_ok()); - - async {} - } - - fn peer_set( - &mut self, - id: u64, - ) -> impl Future>> + Send { - let inner = self.inner.write().unwrap(); - let set = inner.sets.get(&id).cloned(); - async move { set } - } - - fn subscribe( - &mut self, - ) -> impl Future< - Output = UnboundedReceiver<(u64, Ordered, Ordered)>, - > + Send { - let (tx, rx) = futures::channel::mpsc::unbounded(); - let mut inner = self.inner.write().unwrap(); - inner.subscribers.push(tx); - async move { rx } - } -} - -//impl p2p::Coordinator for Registry { -// type PublicKey = PublicKey; -// -// fn peers(&self) -> &Vec { -// // SAFETY: This is safe because: -// // 1. Views are never removed once added (append-only guarantee) -// // 2. Box has a stable address that doesn't change -// // 3. The data inside Participants is immutable after creation -// // 4. We only return references to data that we know exists -// // 5. The registry lives as long as any references to it -// // -// // The unsafe extends the lifetime from the RwLock guard to 'self, -// // which is valid because the data actually lives as long as 'self -// let views = self.views.read().unwrap(); -// -// // Use the list of participants that is associated with the largest index -// if let Some((_view, view_data)) = views.last_key_value() { -// let ptr = &view_data.participants as *const Vec; -// // Drop the guard explicitly -// drop(views); -// // SAFETY: The Box ensures the data has a stable address -// // Views are never removed, so this pointer remains valid -// unsafe { &*ptr } -// } else { -// static EMPTY: Vec = Vec::new(); -// &EMPTY -// } -// } -// -// fn peer_set_id(&self) -> u64 { -// let views = self.views.read().unwrap(); -// let (view, _view_data) = views -// .last_key_value() -// .expect("at least one views exists because it is set in the `new` function"); -// *view -// } -//} - -//impl Su for Registry { -// type Index = View; -// -// type PublicKey = PublicKey; -// -// //fn leader(&self, index: Self::Index) -> Option { -// // let views = self.views.read().unwrap(); -// -// // // Find the largest view that is <= the requested view -// // let (_max_view, view_data) = views.range(..=index).next_back()?; -// -// // if view_data.participants.is_empty() { -// // return None; -// // } -// -// // let leader_index = (index as usize) % view_data.participants.len(); -// // Some(view_data.participants[leader_index].clone()) -// //} -// -// fn participants(&self, index: Self::Index) -> Option<&Vec> { -// // SAFETY: Same safety reasoning as peers() method above -// let views = self.views.read().unwrap(); -// -// // Find the largest view that is <= the requested view -// let (_max_view, view_data) = views.range(..=index).next_back()?; -// -// if view_data.participants.is_empty() { -// return None; -// } -// -// let ptr = &view_data.participants as *const Vec; -// drop(views); -// Some(unsafe { &*ptr }) -// } -// -// fn is_participant(&self, index: Self::Index, candidate: &Self::PublicKey) -> Option { -// let views = self.views.read().unwrap(); -// -// // Find the largest view that is <= the requested view -// let (_max_view, view_data) = views.range(..=index).next_back()?; -// view_data.participants_map.get(candidate).cloned() -// } -//} - -#[cfg(test)] -mod tests { - use super::*; - use commonware_cryptography::{PrivateKeyExt, Signer}; - use commonware_runtime::{Runner as _, deterministic::Runner}; - - /// Helper function to create deterministic test public keys - fn create_test_pubkeys(count: usize) -> Vec { - (0..count) - .map(|i| { - let private_key = crate::PrivateKey::from_seed(i as u64); - private_key.public_key() - }) - .collect() - } - - /// Helper function to create a test registry with specified number of participants - fn create_test_registry(participant_count: usize) -> Registry { - let participants = create_test_pubkeys(participant_count); - Registry::new(0, participants) - } - - #[test] - fn test_new_registry() { - let cfg = commonware_runtime::deterministic::Config::default().with_seed(0); - let executor = Runner::from(cfg); - executor.start(|_context| async move { - let participant_count = 3; - let participants = create_test_pubkeys(participant_count); - let expected_participants = Ordered::from(participants.clone()); - - let mut registry = Registry::new(0, participants); - - // Test that participants are correctly stored in id 0 - let peer_set_0 = registry.peer_set(0).await.unwrap(); - assert_eq!(peer_set_0.len(), participant_count); - assert_eq!(peer_set_0, expected_participants); - }); - } - - #[test] - fn test_update_registry_add_participant() { - let cfg = commonware_runtime::deterministic::Config::default().with_seed(0); - let executor = Runner::from(cfg); - executor.start(|_context| async move { - let mut registry = create_test_registry(2); - let new_participant = crate::PrivateKey::from_seed(99).public_key(); - - // Add participant to id 1 - let add = vec![new_participant.clone()]; - let remove = vec![]; - registry.update_registry(1, &add, &remove); - - // Verify participant was added - let set_1 = registry.peer_set(1).await.unwrap(); - assert_eq!(set_1.len(), 3); - assert!(set_1.iter().any(|p| p == &new_participant)); - - // Original set should remain unchanged - let set_0 = registry.peer_set(0).await; - assert_eq!(set_0.unwrap().len(), 2); - }); - } - - #[test] - fn test_update_registry_remove_participant() { - let cfg = commonware_runtime::deterministic::Config::default().with_seed(0); - let executor = Runner::from(cfg); - executor.start(|_context| async move { - let mut registry = create_test_registry(3); - - let set_0 = registry.peer_set(0).await.unwrap(); - let participant_to_remove = set_0.iter().nth(1).unwrap().clone(); - - // Remove participant from id 1 - let add = vec![]; - let remove = vec![participant_to_remove.clone()]; - registry.update_registry(1, &add, &remove); - - // Verify participant was removed - let set_1 = registry.peer_set(1).await.unwrap(); - assert_eq!(set_1.len(), 2); - assert!(!set_1.iter().any(|p| p == &participant_to_remove)); - - // Original set should remain unchanged - assert_eq!(set_0.len(), 3); - }); - } - - #[test] - fn test_subscribe() { - let cfg = commonware_runtime::deterministic::Config::default().with_seed(0); - let executor = Runner::from(cfg); - executor.start(|_context| async move { - let mut registry = create_test_registry(2); - - // Subscribe to updates - let _rx = registry.subscribe().await; - - // Verify subscription was registered - let inner = registry.inner.read().unwrap(); - assert_eq!(inner.subscribers.len(), 1); - }); - } - - #[test] - fn test_subscribers_receive_updates() { - let cfg = commonware_runtime::deterministic::Config::default().with_seed(0); - let executor = Runner::from(cfg); - executor.start(|_context| async move { - use futures::StreamExt; - - let mut registry = create_test_registry(2); - - // Subscribe to updates - let mut rx = registry.subscribe().await; - - // Get the initial peer set - let set_0 = registry.peer_set(0).await.unwrap(); - - // Use the Manager trait's update method to trigger notifications - let new_participant = crate::PrivateKey::from_seed(99).public_key(); - let mut new_peers = set_0.iter().cloned().collect::>(); - new_peers.push(new_participant.clone()); - - registry.update(1, new_peers.clone()).await; - - // Verify the update was applied - let set_1 = registry.peer_set(1).await.unwrap(); - assert_eq!(set_1.len(), 3); - assert!(set_1.iter().any(|p| p == &new_participant)); - - // Verify subscribers received the notification - let notification = rx.next().await; - assert!(notification.is_some()); - - let (id, old_set, new_set) = notification.unwrap(); - assert_eq!(id, 1); - assert_eq!(old_set, set_0); - assert_eq!(new_set, set_1); - }); - } -} From b1714252a4d7824902245a925aa3760c4967605d Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Tue, 11 Nov 2025 19:22:53 -0500 Subject: [PATCH 55/81] fix: use SimulatedOracle for e2e tests --- node/src/test_harness/common.rs | 61 ---------------------------- node/src/tests/checkpointing.rs | 26 ++++++------ node/src/tests/execution_requests.rs | 54 ++++++++++++------------ node/src/tests/syncer.rs | 14 +++---- 4 files changed, 48 insertions(+), 107 deletions(-) diff --git a/node/src/test_harness/common.rs b/node/src/test_harness/common.rs index 4021bd3d..2531943b 100644 --- a/node/src/test_harness/common.rs +++ b/node/src/test_harness/common.rs @@ -589,64 +589,3 @@ impl Manager for SimulatedOracle { self.oracle.subscribe().await } } - -#[derive(Debug, Clone)] -pub struct DummyOracle { - sender: std::sync::Arc< - std::sync::Mutex< - Option< - futures::channel::mpsc::UnboundedSender<( - u64, - Ordered, - Ordered, - )>, - >, - >, - >, -} - -impl Default for DummyOracle { - fn default() -> Self { - Self { - sender: std::sync::Arc::new(std::sync::Mutex::new(None)), - } - } -} - -impl NetworkOracle for DummyOracle { - async fn register(&mut self, _index: u64, _peers: Vec) {} -} - -impl Manager for DummyOracle { - type PublicKey = PublicKey; - type Peers = Ordered; - - fn update(&mut self, _id: u64, _peers: Self::Peers) -> impl Future + Send { - async {} - } - - async fn peer_set(&mut self, _id: u64) -> Option> { - todo!() - } - - async fn subscribe( - &mut self, - ) -> futures::channel::mpsc::UnboundedReceiver<( - u64, - Ordered, - Ordered, - )> { - let (sender, receiver) = futures::channel::mpsc::unbounded(); - // Store sender to keep channel alive - *self.sender.lock().unwrap() = Some(sender); - receiver - } -} - -impl Blocker for DummyOracle { - type PublicKey = PublicKey; - - fn block(&mut self, _peer: Self::PublicKey) -> impl Future + Send { - async {} - } -} diff --git a/node/src/tests/checkpointing.rs b/node/src/tests/checkpointing.rs index 978ec73e..c39e8a09 100644 --- a/node/src/tests/checkpointing.rs +++ b/node/src/tests/checkpointing.rs @@ -1,6 +1,6 @@ use crate::engine::{BLOCKS_PER_EPOCH, Engine, VALIDATOR_MINIMUM_STAKE}; use crate::test_harness::common; -use crate::test_harness::common::{DummyOracle, get_default_engine_config, get_initial_state}; +use crate::test_harness::common::{SimulatedOracle, get_default_engine_config, get_initial_state}; use crate::test_harness::mock_engine_client::MockEngineNetworkBuilder; use commonware_cryptography::bls12381; use commonware_cryptography::{PrivateKeyExt, Signer}; @@ -36,7 +36,7 @@ fn test_checkpoint_created() { simulated::Config { max_size: 1024 * 1024, disconnect_on_block: false, - tracked_peer_sets: None, + tracked_peer_sets: Some(n as usize * 10), // Each engine may subscribe multiple times }, ); // Start network @@ -98,7 +98,7 @@ fn test_checkpoint_created() { let config = get_default_engine_config( engine_client, - DummyOracle::default(), + SimulatedOracle::new(oracle.clone()), uid.clone(), genesis_hash, namespace, @@ -213,7 +213,7 @@ fn test_previous_header_hash_matches() { simulated::Config { max_size: 1024 * 1024, disconnect_on_block: false, - tracked_peer_sets: None, + tracked_peer_sets: Some(n as usize * 10), // Each engine may subscribe multiple times }, ); // Start network @@ -275,7 +275,7 @@ fn test_previous_header_hash_matches() { let config = get_default_engine_config( engine_client, - DummyOracle::default(), + SimulatedOracle::new(oracle.clone()), uid.clone(), genesis_hash, namespace, @@ -403,7 +403,7 @@ fn test_single_engine_with_checkpoint() { simulated::Config { max_size: 1024 * 1024, disconnect_on_block: false, - tracked_peer_sets: None, + tracked_peer_sets: Some(10), }, ); // Start network @@ -447,7 +447,7 @@ fn test_single_engine_with_checkpoint() { let config = get_default_engine_config( engine_client, - DummyOracle::default(), + SimulatedOracle::new(oracle.clone()), uid.clone(), genesis_hash, namespace, @@ -512,7 +512,7 @@ fn test_node_joins_later_with_checkpoint() { simulated::Config { max_size: 1024 * 1024, disconnect_on_block: false, - tracked_peer_sets: None, + tracked_peer_sets: Some(n as usize * 10), // Each engine may subscribe multiple times }, ); // Start network @@ -580,7 +580,7 @@ fn test_node_joins_later_with_checkpoint() { let config = get_default_engine_config( engine_client, - DummyOracle::default(), + SimulatedOracle::new(oracle.clone()), uid.clone(), genesis_hash, namespace, @@ -652,7 +652,7 @@ fn test_node_joins_later_with_checkpoint() { let config = get_default_engine_config( engine_client, - DummyOracle::default(), + SimulatedOracle::new(oracle.clone()), uid.clone(), genesis_hash, namespace, @@ -758,7 +758,7 @@ fn test_node_joins_later_with_checkpoint_not_in_genesis() { simulated::Config { max_size: 1024 * 1024, disconnect_on_block: false, - tracked_peer_sets: None, + tracked_peer_sets: Some(n as usize * 10), // Each engine may subscribe multiple times }, ); // Start network @@ -827,7 +827,7 @@ fn test_node_joins_later_with_checkpoint_not_in_genesis() { let config = get_default_engine_config( engine_client, - DummyOracle::default(), + SimulatedOracle::new(oracle.clone()), uid.clone(), genesis_hash, namespace, @@ -899,7 +899,7 @@ fn test_node_joins_later_with_checkpoint_not_in_genesis() { let config = get_default_engine_config( engine_client, - DummyOracle::default(), + SimulatedOracle::new(oracle.clone()), uid.clone(), genesis_hash, namespace, diff --git a/node/src/tests/execution_requests.rs b/node/src/tests/execution_requests.rs index 6fdb12dc..f78e82d7 100644 --- a/node/src/tests/execution_requests.rs +++ b/node/src/tests/execution_requests.rs @@ -1,6 +1,6 @@ use crate::engine::{BLOCKS_PER_EPOCH, Engine, VALIDATOR_MINIMUM_STAKE}; use crate::test_harness::common; -use crate::test_harness::common::{DummyOracle, get_default_engine_config, get_initial_state}; +use crate::test_harness::common::{SimulatedOracle, get_default_engine_config, get_initial_state}; use crate::test_harness::mock_engine_client::MockEngineNetworkBuilder; use alloy_primitives::{Address, hex}; use commonware_cryptography::bls12381; @@ -39,8 +39,8 @@ fn test_deposit_request_single() { context.with_label("network"), simulated::Config { max_size: 1024 * 1024, - disconnect_on_block: false, - tracked_peer_sets: None, + disconnect_on_block: true, + tracked_peer_sets: Some(n as usize * 10), // Each engine may subscribe multiple times }, ); // Start network @@ -115,7 +115,7 @@ fn test_deposit_request_single() { let config = get_default_engine_config( engine_client, - DummyOracle::default(), + SimulatedOracle::new(oracle.clone()), uid.clone(), genesis_hash, namespace, @@ -168,23 +168,25 @@ fn test_deposit_request_single() { if metric.ends_with("finalizer_height") { let height = value.parse::().unwrap(); if height == stop_height { + println!("############################"); + println!("{metric}: {}", height_reached.len()); height_reached.insert(metric.to_string()); } } if metric.ends_with("validator_balance") { let value = value.parse::().unwrap(); + //println!("*********************************"); + //println!("{metric}: size: {}", processed_requests.len()); // Parse the pubkey from the metric name using helper function - if let Some(pubkey_hex) = common::parse_metric_substring(metric, "pubkey") { - let creds = - common::parse_metric_substring(metric, "creds").expect("creds missing"); - assert_eq!(creds, hex::encode(test_deposit.withdrawal_credentials)); - assert_eq!(pubkey_hex, test_deposit.node_pubkey.to_string()); - assert_eq!(value, test_deposit.amount); - processed_requests.insert(metric.to_string()); - } else { - println!("{}: {} (failed to parse pubkey)", metric, value); - } + let pubkey_hex = + common::parse_metric_substring(metric, "pubkey").expect("pubkey missing"); + let creds = + common::parse_metric_substring(metric, "creds").expect("creds missing"); + assert_eq!(creds, hex::encode(test_deposit.withdrawal_credentials)); + assert_eq!(pubkey_hex, test_deposit.node_pubkey.to_string()); + assert_eq!(value, test_deposit.amount); + processed_requests.insert(metric.to_string()); } if processed_requests.len() as u32 >= n && height_reached.len() as u32 == n { success = true; @@ -230,7 +232,7 @@ fn test_deposit_request_top_up() { simulated::Config { max_size: 1024 * 1024, disconnect_on_block: false, - tracked_peer_sets: None, + tracked_peer_sets: Some(n as usize * 10), // Each engine may subscribe multiple times }, ); @@ -321,7 +323,7 @@ fn test_deposit_request_top_up() { let config = get_default_engine_config( engine_client, - DummyOracle::default(), + SimulatedOracle::new(oracle.clone()), uid.clone(), genesis_hash, namespace, @@ -444,7 +446,7 @@ fn test_deposit_and_withdrawal_request_single() { simulated::Config { max_size: 1024 * 1024, disconnect_on_block: false, - tracked_peer_sets: None, + tracked_peer_sets: Some(n as usize * 10), // Each engine may subscribe multiple times }, ); @@ -538,7 +540,7 @@ fn test_deposit_and_withdrawal_request_single() { let config = get_default_engine_config( engine_client, - DummyOracle::default(), + SimulatedOracle::new(oracle.clone()), uid.clone(), genesis_hash, namespace, @@ -669,7 +671,7 @@ fn test_partial_withdrawal_balance_below_minimum_stake() { simulated::Config { max_size: 1024 * 1024, disconnect_on_block: false, - tracked_peer_sets: None, + tracked_peer_sets: Some(n as usize * 10), // Each engine may subscribe multiple times }, ); @@ -775,7 +777,7 @@ fn test_partial_withdrawal_balance_below_minimum_stake() { let config = get_default_engine_config( engine_client, - DummyOracle::default(), + SimulatedOracle::new(oracle.clone()), uid.clone(), genesis_hash, namespace, @@ -910,7 +912,7 @@ fn test_deposit_less_than_min_stake_and_withdrawal() { simulated::Config { max_size: 1024 * 1024, disconnect_on_block: false, - tracked_peer_sets: None, + tracked_peer_sets: Some(n as usize * 10), // Each engine may subscribe multiple times }, ); @@ -1005,7 +1007,7 @@ fn test_deposit_less_than_min_stake_and_withdrawal() { let config = get_default_engine_config( engine_client, - DummyOracle::default(), + SimulatedOracle::new(oracle.clone()), uid.clone(), genesis_hash, namespace, @@ -1141,7 +1143,7 @@ fn test_deposit_and_withdrawal_request_multiple() { simulated::Config { max_size: 1024 * 1024, disconnect_on_block: false, - tracked_peer_sets: None, + tracked_peer_sets: Some(n as usize * 10), // Each engine may subscribe multiple times }, ); @@ -1248,7 +1250,7 @@ fn test_deposit_and_withdrawal_request_multiple() { let config = get_default_engine_config( engine_client, - DummyOracle::default(), + SimulatedOracle::new(oracle.clone()), uid.clone(), genesis_hash, namespace, @@ -1394,7 +1396,7 @@ fn test_deposit_request_invalid_signature() { simulated::Config { max_size: 1024 * 1024, disconnect_on_block: false, - tracked_peer_sets: None, + tracked_peer_sets: Some(n as usize * 10), // Each engine may subscribe multiple times }, ); // Start network @@ -1481,7 +1483,7 @@ fn test_deposit_request_invalid_signature() { let config = get_default_engine_config( engine_client, - DummyOracle::default(), + SimulatedOracle::new(oracle.clone()), uid.clone(), genesis_hash, namespace, diff --git a/node/src/tests/syncer.rs b/node/src/tests/syncer.rs index 1e9678f2..898a716c 100644 --- a/node/src/tests/syncer.rs +++ b/node/src/tests/syncer.rs @@ -1,6 +1,6 @@ use crate::engine::{BLOCKS_PER_EPOCH, Engine, VALIDATOR_MINIMUM_STAKE}; use crate::test_harness::common; -use crate::test_harness::common::{DummyOracle, get_default_engine_config, get_initial_state}; +use crate::test_harness::common::{SimulatedOracle, get_default_engine_config, get_initial_state}; use crate::test_harness::mock_engine_client::MockEngineNetworkBuilder; use commonware_cryptography::{PrivateKeyExt, Signer, bls12381}; use commonware_macros::test_traced; @@ -34,7 +34,7 @@ fn test_node_joins_later_no_checkpoint() { simulated::Config { max_size: 1024 * 1024, disconnect_on_block: false, - tracked_peer_sets: None, + tracked_peer_sets: Some(n as usize * 10), // Each engine may subscribe multiple times }, ); // Start network @@ -104,7 +104,7 @@ fn test_node_joins_later_no_checkpoint() { let config = get_default_engine_config( engine_client, - DummyOracle::default(), + SimulatedOracle::new(oracle.clone()), uid.clone(), genesis_hash, namespace, @@ -162,7 +162,7 @@ fn test_node_joins_later_no_checkpoint() { let config = get_default_engine_config( engine_client, - DummyOracle::default(), + SimulatedOracle::new(oracle.clone()), uid.clone(), genesis_hash, namespace, @@ -268,7 +268,7 @@ fn test_node_joins_later_no_checkpoint_not_in_genesis() { simulated::Config { max_size: 1024 * 1024, disconnect_on_block: false, - tracked_peer_sets: None, + tracked_peer_sets: Some(n as usize * 10), // Each engine may subscribe multiple times }, ); // Start network @@ -338,7 +338,7 @@ fn test_node_joins_later_no_checkpoint_not_in_genesis() { let config = get_default_engine_config( engine_client, - DummyOracle::default(), + SimulatedOracle::new(oracle.clone()), uid.clone(), genesis_hash, namespace, @@ -398,7 +398,7 @@ fn test_node_joins_later_no_checkpoint_not_in_genesis() { // since historical blocks were finalized by only those 4 validators let config = get_default_engine_config( engine_client, - DummyOracle::default(), + SimulatedOracle::new(oracle.clone()), uid.clone(), genesis_hash, namespace, From b498654c2e41933aacb76627bcea31e497a9dd54 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Wed, 12 Nov 2025 09:20:10 -0500 Subject: [PATCH 56/81] fix: fix test_single_engine_with_checkpoint --- node/src/tests/checkpointing.rs | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/node/src/tests/checkpointing.rs b/node/src/tests/checkpointing.rs index c39e8a09..06c9f601 100644 --- a/node/src/tests/checkpointing.rs +++ b/node/src/tests/checkpointing.rs @@ -126,6 +126,7 @@ fn test_checkpoint_created() { // Poll metrics let mut state_stored = HashSet::new(); let mut header_stored = HashSet::new(); + let mut height_reached = HashSet::new(); loop { let metrics = context.encode(); @@ -154,12 +155,19 @@ fn test_checkpoint_created() { state_stored.insert(metric.to_string()); } + if metric.ends_with("finalizer_height") { + let height = value.parse::().unwrap(); + if height == stop_height { + height_reached.insert(metric.to_string()); + } + } + if metric.ends_with("finalized_header_stored") { let height = value.parse::().unwrap(); assert_eq!(height, BLOCKS_PER_EPOCH); header_stored.insert(metric.to_string()); } - if header_stored.len() as u32 >= n && state_stored.len() as u32 == n { + if header_stored.len() as u32 >= n && state_stored.len() as u32 == n && height_reached.len() as u32 >= n { success = true; break; } @@ -303,6 +311,7 @@ fn test_previous_header_hash_matches() { // Poll metrics let mut first_header_stored = HashMap::new(); let mut second_header_stored = HashSet::new(); + let mut height_reached = HashSet::new(); loop { let metrics = context.encode(); @@ -325,6 +334,13 @@ fn test_previous_header_hash_matches() { assert_eq!(value, 0); } + if metric.ends_with("finalizer_height") { + let height = value.parse::().unwrap(); + if height == stop_height { + height_reached.insert(metric.to_string()); + } + } + if metric.ends_with("finalized_header_stored") { let height = value.parse::().unwrap(); let header = @@ -351,7 +367,7 @@ fn test_previous_header_hash_matches() { } // There is an edge case where not all validators write a finalized header to disk. // That's why we only enforce n - 1 validators to reach this checkpoint to avoid a flaky test. - if second_header_stored.len() as u32 == n - 1 { + if second_header_stored.len() as u32 == n - 1 && height_reached.len() as u32 >= n { success = true; break; } @@ -434,7 +450,13 @@ fn test_single_engine_with_checkpoint() { let engine_client_network = MockEngineNetworkBuilder::new(genesis_hash).build(); // Create and populate a consensus state - let mut consensus_state = ConsensusState::default(); + let mut consensus_state = common::get_initial_state( + genesis_hash, + &validators, + None, + None, + VALIDATOR_MINIMUM_STAKE, + ); consensus_state.set_latest_height(50); // Set a specific height // Configure engine with the checkpoint From 00e9a1da107fc719e6ebff869800a799875b4da2 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Wed, 12 Nov 2025 16:59:43 -0500 Subject: [PATCH 57/81] feat: apply marshal update (Fills Gaps Before Processing) --- Cargo.lock | 60 ++-- Cargo.toml | 24 +- application/src/ingress.rs | 4 +- finalizer/src/actor.rs | 4 +- finalizer/src/db.rs | 4 +- node/src/engine.rs | 4 +- node/src/test_harness/common.rs | 30 +- node/src/tests/checkpointing.rs | 5 +- syncer/Cargo.toml | 2 +- syncer/src/actor.rs | 482 +++++++++++++++++++++-------- syncer/src/config.rs | 2 +- syncer/src/finalizer.rs | 134 -------- syncer/src/ingress/mod.rs | 1 - syncer/src/ingress/orchestrator.rs | 116 ------- syncer/src/lib.rs | 2 - types/src/block.rs | 2 - 16 files changed, 421 insertions(+), 455 deletions(-) delete mode 100644 syncer/src/finalizer.rs delete mode 100644 syncer/src/ingress/orchestrator.rs diff --git a/Cargo.lock b/Cargo.lock index 91adfa2f..61d8e913 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -834,9 +834,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.98" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "ark-ff" @@ -1517,8 +1517,7 @@ checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "commonware-broadcast" version = "0.0.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98d0d0909a8323c69cc0f5090cac4b2eb546f4cc29a60dc0dcfe238e75f79c19" +source = "git+https://github.com/commonwarexyz/monorepo.git?rev=f395c9e#f395c9ef1009b764e4358b6df0c8e03ba61d125d" dependencies = [ "bytes", "commonware-codec", @@ -1536,8 +1535,7 @@ dependencies = [ [[package]] name = "commonware-codec" version = "0.0.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d473c9be55b1143abebd3fa6a748fe9d35151df4614ea7f68b314e504559af08" +source = "git+https://github.com/commonwarexyz/monorepo.git?rev=f395c9e#f395c9ef1009b764e4358b6df0c8e03ba61d125d" dependencies = [ "bytes", "paste", @@ -1547,8 +1545,7 @@ dependencies = [ [[package]] name = "commonware-consensus" version = "0.0.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b3b1dd7e0596b23a50ef69a290d0ed4e187a3f16a6aa6f317af188cd8b2bb5" +source = "git+https://github.com/commonwarexyz/monorepo.git?rev=f395c9e#f395c9ef1009b764e4358b6df0c8e03ba61d125d" dependencies = [ "bytes", "cfg-if", @@ -1563,6 +1560,7 @@ dependencies = [ "commonware-utils", "futures", "governor", + "pin-project", "prometheus-client", "rand 0.8.5", "rand_distr", @@ -1573,8 +1571,7 @@ dependencies = [ [[package]] name = "commonware-cryptography" version = "0.0.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7157f6e4a84b7a70108f15bf402f539b48d52adf727b9938fe59f752efc5b3e" +source = "git+https://github.com/commonwarexyz/monorepo.git?rev=f395c9e#f395c9ef1009b764e4358b6df0c8e03ba61d125d" dependencies = [ "blake3", "blst", @@ -1599,8 +1596,7 @@ dependencies = [ [[package]] name = "commonware-macros" version = "0.0.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff368ef4db2d10686c1a89b7f4a3f1e7dddd9641a96cac42b72bf71a10360291" +source = "git+https://github.com/commonwarexyz/monorepo.git?rev=f395c9e#f395c9ef1009b764e4358b6df0c8e03ba61d125d" dependencies = [ "futures", "proc-macro-crate", @@ -1614,8 +1610,7 @@ dependencies = [ [[package]] name = "commonware-p2p" version = "0.0.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "657c7a971cf269411914e2a32a77815d5990ae111f2804d6b15f5952f75270c6" +source = "git+https://github.com/commonwarexyz/monorepo.git?rev=f395c9e#f395c9ef1009b764e4358b6df0c8e03ba61d125d" dependencies = [ "bytes", "commonware-codec", @@ -1641,8 +1636,7 @@ dependencies = [ [[package]] name = "commonware-resolver" version = "0.0.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e72ea84c5b43939cde251fba17627065d45cd9cedcb67f673c58291c5454e8f" +source = "git+https://github.com/commonwarexyz/monorepo.git?rev=f395c9e#f395c9ef1009b764e4358b6df0c8e03ba61d125d" dependencies = [ "bimap", "bytes", @@ -1664,8 +1658,7 @@ dependencies = [ [[package]] name = "commonware-runtime" version = "0.0.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de4d08e6e11088ed5b42e5ad93b18ffd745cbcc04c6ef7f723f5d237e146abc8" +source = "git+https://github.com/commonwarexyz/monorepo.git?rev=f395c9e#f395c9ef1009b764e4358b6df0c8e03ba61d125d" dependencies = [ "async-lock", "axum 0.8.4", @@ -1696,9 +1689,9 @@ dependencies = [ [[package]] name = "commonware-storage" version = "0.0.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3116985d7a761aa7bf26d5226d51b8de0eaa6458277963f3c5d903f4078d504" +source = "git+https://github.com/commonwarexyz/monorepo.git?rev=f395c9e#f395c9ef1009b764e4358b6df0c8e03ba61d125d" dependencies = [ + "anyhow", "bytes", "cfg-if", "commonware-codec", @@ -1719,8 +1712,7 @@ dependencies = [ [[package]] name = "commonware-stream" version = "0.0.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "260076055c2a5eb1b734641603a9bc6bcd439bd6525055480c7d149e2a8dad70" +source = "git+https://github.com/commonwarexyz/monorepo.git?rev=f395c9e#f395c9ef1009b764e4358b6df0c8e03ba61d125d" dependencies = [ "bytes", "chacha20poly1305", @@ -1740,8 +1732,7 @@ dependencies = [ [[package]] name = "commonware-utils" version = "0.0.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "209c03e7057e9d4d5f0bade24685e2bc8845471b89e4ab54684f1af8c287ad3b" +source = "git+https://github.com/commonwarexyz/monorepo.git?rev=f395c9e#f395c9ef1009b764e4358b6df0c8e03ba61d125d" dependencies = [ "bytes", "cfg-if", @@ -1752,6 +1743,7 @@ dependencies = [ "num-integer", "num-rational", "num-traits", + "pin-project", "rand 0.8.5", "thiserror 2.0.12", ] @@ -2365,7 +2357,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] @@ -2997,7 +2989,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core 0.57.0", + "windows-core 0.58.0", ] [[package]] @@ -3230,7 +3222,7 @@ checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3423,7 +3415,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.53.2", ] [[package]] @@ -4527,7 +4519,7 @@ dependencies = [ "once_cell", "socket2 0.6.0", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] @@ -4976,7 +4968,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.4.15", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -4989,7 +4981,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.9.4", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -5710,10 +5702,10 @@ dependencies = [ "futures", "governor", "metrics", + "pin-project", "prometheus-client", "rand 0.8.5", "summit-types", - "tokio-util", "tracing", "tracing-subscriber", ] @@ -5858,7 +5850,7 @@ dependencies = [ "getrandom 0.3.3", "once_cell", "rustix 1.0.7", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -6633,7 +6625,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index c2c2f88c..ce63dfe3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,21 +11,20 @@ edition = "2024" summit-types = { path = "types" } summit-application = { path = "application" } summit-syncer = {path = "syncer" } -summit-syncer-old = {path = "syncer_old" } summit-finalizer = {path = "finalizer"} summit-rpc = {path = "rpc"} summit-orchestrator = {path = "orchestrator"} -commonware-consensus = "0.0.63" -commonware-cryptography = "0.0.63" -commonware-storage = "0.0.63" -commonware-runtime = "0.0.63" -commonware-codec = "0.0.63" -commonware-p2p = "0.0.63" -commonware-broadcast = "0.0.63" -commonware-utils = "0.0.63" -commonware-resolver = "0.0.63" -commonware-macros = "0.0.63" +commonware-consensus = { git = "https://github.com/commonwarexyz/monorepo.git", rev = "f395c9e" } +commonware-cryptography = { git = "https://github.com/commonwarexyz/monorepo.git", rev = "f395c9e" } +commonware-storage = { git = "https://github.com/commonwarexyz/monorepo.git", rev = "f395c9e" } +commonware-runtime = { git = "https://github.com/commonwarexyz/monorepo.git", rev = "f395c9e" } +commonware-codec = { git = "https://github.com/commonwarexyz/monorepo.git", rev = "f395c9e" } +commonware-p2p = { git = "https://github.com/commonwarexyz/monorepo.git", rev = "f395c9e" } +commonware-broadcast = { git = "https://github.com/commonwarexyz/monorepo.git", rev = "f395c9e" } +commonware-utils = { git = "https://github.com/commonwarexyz/monorepo.git", rev = "f395c9e" } +commonware-resolver = { git = "https://github.com/commonwarexyz/monorepo.git", rev = "f395c9e" } +commonware-macros = { git = "https://github.com/commonwarexyz/monorepo.git", rev = "f395c9e" } alloy-consensus = "1.0.12" alloy-eips = { version = "1.0.19", features = ["ssz"] } @@ -56,6 +55,7 @@ tower = "0.5.2" tokio = "1.46.0" tokio-util = "0.7.16" console-subscriber = "0.4" +pin-project = "1.1.10" ethereum_ssz = "0.9.0" ethereum_ssz_derive = "0.9.0" @@ -64,7 +64,7 @@ serde_json = "1.0.140" toml = "0.9" zeroize = "1.8" -anyhow = "1.0.98" +anyhow = "1.0.99" eyre = "0.6" bytes = "1.10.1" diff --git a/application/src/ingress.rs b/application/src/ingress.rs index e8f45a15..b00e08b2 100644 --- a/application/src/ingress.rs +++ b/application/src/ingress.rs @@ -1,5 +1,5 @@ use commonware_consensus::types::{Epoch, Round}; -use commonware_consensus::{Automaton, Epochable, Relay, simplex::types::Context, types::View}; +use commonware_consensus::{Automaton, Relay, simplex::types::Context, types::View}; use commonware_cryptography::PublicKey; use commonware_cryptography::sha256::Digest; use futures::{ @@ -48,7 +48,7 @@ impl Automaton for Mailbox

{ type Context = Context; type Digest = Digest; - async fn genesis(&mut self, epoch: ::Epoch) -> Self::Digest { + async fn genesis(&mut self, epoch: Epoch) -> Self::Digest { let (response, receiver) = oneshot::channel(); self.sender .send(Message::Genesis { response, epoch }) diff --git a/finalizer/src/actor.rs b/finalizer/src/actor.rs index ac2e9f77..dae72c78 100644 --- a/finalizer/src/actor.rs +++ b/finalizer/src/actor.rs @@ -85,13 +85,11 @@ impl< ) -> (Self, FinalizerMailbox>) { let (tx, rx) = mpsc::channel(cfg.mailbox_size); // todo(dalton) pull mailbox size from config let state_cfg = StateConfig { - log_journal_partition: format!("{}-finalizer_state-log", cfg.db_prefix), + log_partition: format!("{}-finalizer_state-log", cfg.db_prefix), log_write_buffer: WRITE_BUFFER, log_compression: None, log_codec_config: (), log_items_per_section: NZU64!(262_144), - locations_journal_partition: format!("{}-finalizer_state-locations", cfg.db_prefix), - locations_items_per_blob: NZU64!(262_144), // todo: No reference for this config option look into this translator: TwoCap, buffer_pool: cfg.buffer_pool, }; diff --git a/finalizer/src/db.rs b/finalizer/src/db.rs index 65b136a6..3b3ff576 100644 --- a/finalizer/src/db.rs +++ b/finalizer/src/db.rs @@ -314,13 +314,11 @@ mod tests { context: E, ) -> FinalizerState { let config = Config { - log_journal_partition: format!("{}-log", partition), + log_partition: format!("{}-log", partition), log_write_buffer: NZUsize!(64 * 1024), log_compression: None, log_codec_config: (), log_items_per_section: NZU64!(4), - locations_journal_partition: format!("{}-locations", partition), - locations_items_per_blob: NZU64!(4), translator: TwoCap, buffer_pool: PoolRef::new(NZUsize!(77), NZUsize!(9)), }; diff --git a/node/src/engine.rs b/node/src/engine.rs index d21c34ee..02c5d4a4 100644 --- a/node/src/engine.rs +++ b/node/src/engine.rs @@ -14,7 +14,7 @@ use futures::future::try_join_all; use governor::{Quota, clock::Clock as GClock}; use rand::{CryptoRng, Rng}; use std::marker::PhantomData; -use std::num::{NonZero, NonZeroU32}; +use std::num::{NonZero, NonZeroU32, NonZeroU64}; use std::time::Duration; use summit_application::ApplicationConfig; use summit_finalizer::actor::Finalizer; @@ -42,7 +42,7 @@ const FREEZER_TABLE_RESIZE_CHUNK_SIZE: u32 = 2u32.pow(16); // 3MB const FREEZER_JOURNAL_TARGET_SIZE: u64 = 1024 * 1024 * 1024; // 1GB const FREEZER_JOURNAL_COMPRESSION: Option = Some(3); const FREEZER_TABLE_INITIAL_SIZE: u32 = 1024 * 1024; // 100mb -const MAX_REPAIR: u64 = 50; +const MAX_REPAIR: NonZeroU64 = NonZeroU64::new(50).unwrap(); // // Onboarding config (set arbitrarily for now) diff --git a/node/src/test_harness/common.rs b/node/src/test_harness/common.rs index 2531943b..91852d9f 100644 --- a/node/src/test_harness/common.rs +++ b/node/src/test_harness/common.rs @@ -14,9 +14,7 @@ use commonware_runtime::{ deterministic::{self, Runner}, }; use commonware_utils::from_hex_formatted; -use commonware_utils::set::Ordered; use governor::Quota; -use std::future::Future; use std::time::Duration; use std::{ collections::{HashMap, HashSet}, @@ -543,18 +541,22 @@ pub fn get_default_engine_config< #[derive(Clone, Debug)] pub struct SimulatedOracle { - oracle: Oracle, + inner: simulated::Manager, } impl SimulatedOracle { pub fn new(oracle: Oracle) -> Self { - Self { oracle } + Self { + inner: oracle.manager(), + } } } impl NetworkOracle for SimulatedOracle { async fn register(&mut self, index: u64, peers: Vec) { - self.oracle.update(index, Ordered::from(peers)).await; + self.inner + .update(index, commonware_utils::set::Ordered::from(peers)) + .await } } @@ -569,23 +571,19 @@ impl Blocker for SimulatedOracle { impl Manager for SimulatedOracle { type PublicKey = PublicKey; - type Peers = Ordered; + type Peers = commonware_utils::set::Ordered; - fn update(&mut self, id: u64, peers: Self::Peers) -> impl Future + Send { - self.oracle.update(id, peers) + async fn update(&mut self, id: u64, peers: Self::Peers) { + self.inner.update(id, peers).await } - async fn peer_set(&mut self, id: u64) -> Option> { - self.oracle.peer_set(id).await + async fn peer_set(&mut self, id: u64) -> Option { + self.inner.peer_set(id).await } async fn subscribe( &mut self, - ) -> futures::channel::mpsc::UnboundedReceiver<( - u64, - Ordered, - Ordered, - )> { - self.oracle.subscribe().await + ) -> futures::channel::mpsc::UnboundedReceiver<(u64, Self::Peers, Self::Peers)> { + self.inner.subscribe().await } } diff --git a/node/src/tests/checkpointing.rs b/node/src/tests/checkpointing.rs index 06c9f601..718deb3f 100644 --- a/node/src/tests/checkpointing.rs +++ b/node/src/tests/checkpointing.rs @@ -167,7 +167,10 @@ fn test_checkpoint_created() { assert_eq!(height, BLOCKS_PER_EPOCH); header_stored.insert(metric.to_string()); } - if header_stored.len() as u32 >= n && state_stored.len() as u32 == n && height_reached.len() as u32 >= n { + if header_stored.len() as u32 >= n + && state_stored.len() as u32 == n + && height_reached.len() as u32 >= n + { success = true; break; } diff --git a/syncer/Cargo.toml b/syncer/Cargo.toml index 40ec7cdc..cbc6523e 100644 --- a/syncer/Cargo.toml +++ b/syncer/Cargo.toml @@ -21,8 +21,8 @@ bytes.workspace = true futures.workspace = true governor.workspace = true rand.workspace = true -tokio-util.workspace = true tracing.workspace = true +pin-project.workspace = true # For metrics - activate with `prom` feature metrics = { version = "0.24.0", optional = true } diff --git a/syncer/src/actor.rs b/syncer/src/actor.rs index 1ff518bf..0b6d49ef 100644 --- a/syncer/src/actor.rs +++ b/syncer/src/actor.rs @@ -1,11 +1,9 @@ use super::{ cache, config::Config, - finalizer::Finalizer, ingress::{ handler::{self, Request}, mailbox::{Mailbox, Message}, - orchestrator::{Orchestration, Orchestrator}, }, }; use crate::{Update, ingress::mailbox::Identifier as BlockID}; @@ -21,7 +19,15 @@ use commonware_p2p::Recipients; use commonware_resolver::Resolver; use commonware_runtime::{Clock, ContextCell, Handle, Metrics, Spawner, Storage, spawn_cell}; use commonware_storage::archive::{Archive as _, Identifier as ArchiveID, immutable}; -use commonware_utils::futures::{AbortablePool, Aborter}; +use commonware_utils::{ + futures::{AbortablePool, Aborter}, + sequence::U64, +}; +use pin_project::pin_project; + +use commonware_storage::metadata; +use commonware_storage::metadata::Metadata; +use commonware_utils::futures::OptionFuture; use futures::{ StreamExt, channel::{mpsc, oneshot}, @@ -32,13 +38,41 @@ use governor::clock::Clock as GClock; use prometheus_client::metrics::gauge::Gauge; use rand::{CryptoRng, Rng}; use std::{ - collections::{BTreeMap, btree_map::Entry}, + collections::{BTreeMap, BTreeSet, btree_map::Entry}, + future::Future, + num::NonZeroU64, time::Instant, }; -use tracing::{debug, info, warn}; +use tracing::{debug, error, info}; use summit_types::scheme::SchemeProvider; +/// The key used to store the last processed height in the metadata store. +const LATEST_KEY: U64 = U64::new(0xFF); + +/// The first block height that is present in the [immutable::Archive] of finalized blocks. +const FIRST_HEIGHT_IN_ARCHIVE: u64 = 1; + +/// A pending acknowledgement from the application for processing a block at the contained height/commitment. +#[pin_project] +struct PendingAck { + height: u64, + commitment: B::Commitment, + #[pin] + receiver: oneshot::Receiver<()>, +} + +impl Future for PendingAck { + type Output = as Future>::Output; + + fn poll( + self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll { + self.project().receiver.poll(cx) + } +} + /// A struct that holds multiple subscriptions for a block. struct BlockSubscription { // The subscribers that are waiting for the block @@ -77,28 +111,36 @@ pub struct Actor< scheme_provider: P, // Epoch length (in blocks) epoch_length: u64, - // Mailbox size - mailbox_size: usize, // Unique application namespace namespace: Vec, // Minimum number of views to retain temporary data after the application processes a block view_retention_timeout: u64, // Maximum number of blocks to repair at once - max_repair: u64, + max_repair: NonZeroU64, // Codec configuration for block type block_codec_config: B::Cfg, // ---------- State ---------- // Last view processed last_processed_round: Round, + // Last height processed by the application + last_processed_height: u64, + // Pending application acknowledgement, if any + pending_ack: OptionFuture>, // Highest known finalized height tip: u64, // Outstanding subscriptions for blocks block_subscriptions: BTreeMap>, + // Outstanding requests for blocks + waiting_blocks: BTreeSet, + // Outstanding requests for finalized blocks + waiting_finalized: BTreeSet, // ---------- Storage ---------- // Prunable cache cache: cache::Manager, + // Metadata tracking application progress + application_metadata: Metadata, // Finalizations stored by height finalizations_by_height: immutable::Archive>, // Finalized blocks stored by height @@ -209,6 +251,18 @@ impl< .expect("failed to initialize finalized blocks archive"); info!(elapsed = ?start.elapsed(), "restored finalized blocks archive"); + // Initialize metadata tracking application progress + let application_metadata = Metadata::init( + context.with_label("application_metadata"), + metadata::Config { + partition: format!("{}-application-metadata", config.partition_prefix), + codec_config: (), + }, + ) + .await + .expect("failed to initialize application metadata"); + let last_processed_height = *application_metadata.get(&LATEST_KEY).unwrap_or(&0); + // Create metrics #[cfg(feature = "prom")] { @@ -224,6 +278,7 @@ impl< "Processed height of application", processed_height.clone(), ); + let _ = processed_height.try_set(last_processed_height); // Initialize mailbox let (sender, mailbox) = mpsc::channel(config.mailbox_size); @@ -234,14 +289,18 @@ impl< scheme_provider: config.scheme_provider, epoch_length: config.epoch_length, mailbox_size: config.mailbox_size, - namespace: config.namespace, view_retention_timeout: config.view_retention_timeout, max_repair: config.max_repair, block_codec_config: config.block_codec_config, last_processed_round: Round::new(0, 0), + last_processed_height, + pending_ack: None.into(), tip: 0, block_subscriptions: BTreeMap::new(), + waiting_blocks: BTreeSet::new(), + waiting_finalized: BTreeSet::new(), cache, + application_metadata, finalizations_by_height, finalized_blocks, finalized_height, @@ -260,15 +319,19 @@ impl< mailbox, scheme_provider: config.scheme_provider, epoch_length: config.epoch_length, - mailbox_size: config.mailbox_size, namespace: config.namespace, view_retention_timeout: config.view_retention_timeout, max_repair: config.max_repair, block_codec_config: config.block_codec_config, last_processed_round: Round::new(0, 0), + last_processed_height, + pending_ack: None.into(), tip: 0, block_subscriptions: BTreeMap::new(), + waiting_blocks: BTreeSet::new(), + waiting_finalized: BTreeSet::new(), cache, + application_metadata, finalizations_by_height, finalized_blocks, }, @@ -306,22 +369,7 @@ impl< R: Resolver>, K: PublicKey, { - // Process all finalized blocks in order (fetching any that are missing) - let (mut notifier_tx, notifier_rx) = mpsc::channel::<()>(1); - let (orchestrator_sender, mut orchestrator_receiver) = mpsc::channel(self.mailbox_size); - let orchestrator = Orchestrator::new(orchestrator_sender); - let finalizer = Finalizer::new( - self.context.with_label("finalizer"), - application.clone(), - orchestrator, - notifier_rx, - sync_height, - self.epoch_length, - ) - .await; - finalizer.start(); - - // Create a local pool for waiter futures + // Create a local pool for waiter futures. let mut waiters = AbortablePool::<(B::Commitment, B)>::default(); // Get tip and send to application @@ -333,7 +381,13 @@ impl< self.finalized_height.set(height as i64); } - // Handle messages + // Attempt to dispatch the next finalized block to the application, if it is ready. + self.try_dispatch_block(&mut application).await; + + // Attempt to repair any gaps in the finalized blocks archive, if there are any. + self.try_repair_gaps(&mut buffer, &mut resolver, &mut application) + .await; + loop { // Remove any dropped subscribers. If all subscribers dropped, abort the waiter. self.block_subscriptions.retain(|_, bs| { @@ -350,7 +404,28 @@ impl< }; self.notify_subscribers(commitment, &block).await; }, - // Handle consensus before finalizer or backfiller + // Handle application acknowledgements next + ack = &mut self.pending_ack => { + let PendingAck { height, commitment, .. } = self.pending_ack.take().expect("ack state must be present"); + + match ack { + Ok(()) => { + if let Err(e) = self + .handle_block_processed(height, commitment, &mut resolver) + .await + { + error!(?e, height, "failed to update application progress"); + return; + } + self.try_dispatch_block(&mut application).await; + } + Err(e) => { + error!(?e, height, "application did not acknowledge block"); + return; + } + } + }, + // Handle consensus inputs before backfill or resolver traffic mailbox_message = self.mailbox.next() => { let Some(message) = mailbox_message else { info!("mailbox closed, shutting down"); @@ -412,7 +487,16 @@ impl< if let Some(block) = self.find_block(&mut buffer, commitment).await { // If found, persist the block let height = block.height(); - self.finalize(height, commitment, block, Some(finalization), &mut notifier_tx, &mut application).await; + self.finalize( + height, + commitment, + block, + Some(finalization), + &mut application, + &mut buffer, + &mut resolver, + ) + .await; debug!(?round, height, "finalized block stored"); } else { // Otherwise, fetch the block from the network. @@ -491,91 +575,6 @@ impl< } } }, - // Handle finalizer messages next - message = orchestrator_receiver.next() => { - let Some(message) = message else { - info!("orchestrator closed, shutting down"); - return; - }; - match message { - Orchestration::Get { height, result } => { - // Check if in blocks - let block = self.get_finalized_block(height).await; - result.send(block).unwrap_or_else(|_| warn!(?height, "Failed to send block to orchestrator")); - } - Orchestration::GetWithFinalization { height, result } => { - let block = self.get_finalized_block(height).await; - let finalization = self.get_finalization_by_height(height).await; - result.send((block, finalization)).unwrap_or_else(|_| warn!(?height, "Failed to send block and finalization to orchestrator")); - } - Orchestration::Processed { height, digest } => { - // Update metrics - #[cfg(feature = "prom")] - self.processed_height.set(height as i64); - - // Cancel any outstanding requests (by height and by digest) - resolver.cancel(Request::::Block(digest)).await; - resolver.retain(Request::::Finalized { height }.predicate()).await; - - // If finalization exists, prune the archives - if let Some(finalization) = self.get_finalization_by_height(height).await { - // Trail the previous processed finalized block by the timeout - let lpr = self.last_processed_round; - let prune_round = Round::new(lpr.epoch(), lpr.view().saturating_sub(self.view_retention_timeout)); - - // Prune archives - self.cache.prune(prune_round).await; - - // Update the last processed round - let round = finalization.round(); - self.last_processed_round = round; - - // Cancel useless requests - resolver.retain(Request::::Notarized { round }.predicate()).await; - } - } - Orchestration::Repair { height } => { - // Find the end of the "gap" of missing blocks, starting at `height` - let (_, Some(gap_end)) = self.finalized_blocks.next_gap(height) else { - // No gap found; height-1 is the last known finalized block - continue; - }; - assert!(gap_end > height, "gap end must be greater than height"); - - // Attempt to repair the gap backwards from the end of the gap, using - // blocks from our local storage. - let Some(mut cursor) = self.get_finalized_block(gap_end).await else { - panic!("gapped block missing that should exist: {gap_end}"); - }; - - // Iterate backwards, repairing blocks as we go. - while cursor.height() > height { - let commitment = cursor.parent(); - if let Some(block) = self.find_block(&mut buffer, commitment).await { - let finalization = self.cache.get_finalization_for(commitment).await; - self.finalize(block.height(), commitment, block.clone(), finalization, &mut notifier_tx, &mut application).await; - debug!(height = block.height(), "repaired block"); - cursor = block; - } else { - // Request the next missing block digest - resolver.fetch(Request::::Block(commitment)).await; - break; - } - } - - // If we haven't fully repaired the gap, then also request any possible - // finalizations for the blocks in the remaining gap. This may help - // shrink the size of the gap if finalizations for the requests heights - // exist. If not, we rely on the recursive digest fetch above. - let gap_start = height; - let gap_end = std::cmp::min(cursor.height(), gap_start.saturating_add(self.max_repair)); - debug!(gap_start, gap_end, "requesting any finalized blocks"); - for height in gap_start..gap_end { - resolver.fetch(Request::::Finalized { height }).await; - } - } - } - }, // Handle resolver messages last message = resolver_rx.next() => { let Some(message) = message else { @@ -644,7 +643,17 @@ impl< // Persist the block, also persisting the finalization if we have it let height = block.height(); let finalization = self.cache.get_finalization_for(commitment).await; - self.finalize(height, commitment, block, finalization, &mut notifier_tx, &mut application).await; + + self.finalize( + height, + commitment, + block, + finalization, + &mut application, + &mut buffer, + &mut resolver, + ) + .await; debug!(?commitment, height, "received block"); let _ = response.send(true); }, @@ -678,7 +687,16 @@ impl< // Valid finalization received debug!(height, "received finalization"); let _ = response.send(true); - self.finalize(height, block.commitment(), block, Some(finalization), &mut notifier_tx, &mut application).await; + self.finalize( + height, + block.commitment(), + block, + Some(finalization), + &mut application, + &mut buffer, + &mut resolver, + ) + .await; }, Request::Notarized { round } => { let Some(scheme) = self.scheme_provider.scheme(round.epoch()) else { @@ -719,7 +737,16 @@ impl< // the request for the block. let height = block.height(); if let Some(finalization) = self.cache.get_finalization_for(commitment).await { - self.finalize(height, commitment, block.clone(), Some(finalization), &mut notifier_tx, &mut application).await; + self.finalize( + height, + commitment, + block.clone(), + Some(finalization), + &mut application, + &mut buffer, + &mut resolver, + ) + .await; } // Cache the notarization and block @@ -745,6 +772,91 @@ impl< } } + // -------------------- Application Dispatch -------------------- + + /// Attempt to dispatch the next finalized block to the application if ready. + async fn try_dispatch_block( + &mut self, + application: &mut impl Reporter>, + ) { + if self.pending_ack.is_some() { + return; + } + + let next_height = self.last_processed_height.saturating_add(1); + let Some(block) = self.get_finalized_block(next_height).await else { + return; + }; + assert_eq!( + block.height(), + next_height, + "finalized block height mismatch" + ); + + let (height, commitment) = (block.height(), block.commitment()); + let (ack_tx, ack_rx) = oneshot::channel(); + + if utils::is_last_block_in_epoch(next_height, self.epoch_length).is_some() { + let finalize = self.get_finalization_by_height(next_height).await; + application + .report(Update::Block((block, finalize), ack_tx)) + .await; + } else { + application + .report(Update::Block((block, None), ack_tx)) + .await; + } + + self.pending_ack.replace(PendingAck { + height, + commitment, + receiver: ack_rx, + }); + } + + /// Handle acknowledgement from the application that a block has been processed. + async fn handle_block_processed( + &mut self, + height: u64, + commitment: B::Commitment, + resolver: &mut impl Resolver>, + ) -> Result<(), metadata::Error> { + #[cfg(feature = "prom")] + { + let _ = self.processed_height.try_set(height); + } + self.last_processed_height = height; + self.application_metadata + .put_sync(LATEST_KEY.clone(), height) + .await?; + + resolver.cancel(Request::::Block(commitment)).await; + self.waiting_blocks.remove(&commitment); + + if let Some(finalization) = self.get_finalization_by_height(height).await { + // Trail the previous processed finalized block by the timeout + let lpr = self.last_processed_round; + let prune_round = Round::new( + lpr.epoch(), + lpr.view().saturating_sub(self.view_retention_timeout), + ); + + // Prune archives + self.cache.prune(prune_round).await; + + // Update the last processed round + let round = finalization.round(); + self.last_processed_round = round; + + // Cancel useless requests + resolver + .retain(Request::::Notarized { round }.predicate()) + .await; + } + + Ok(()) + } + // -------------------- Prunable Storage -------------------- /// Add a verified block to the prunable archive. @@ -784,17 +896,35 @@ impl< } } + /// Add a finalized block, and optionally a finalization, to the archive, and + /// attempt to identify + repair any gaps in the archive. + #[allow(clippy::too_many_arguments)] + async fn finalize( + &mut self, + height: u64, + commitment: B::Commitment, + block: B, + finalization: Option>, + application: &mut impl Reporter>, + buffer: &mut buffered::Mailbox, + resolver: &mut impl Resolver>, + ) { + self.store_finalization(height, commitment, block, finalization, application) + .await; + + self.try_repair_gaps(buffer, resolver, application).await; + } + /// Add a finalized block, and optionally a finalization, to the archive. /// - /// At the end of the method, the notifier is notified to indicate that there has been an update - /// to the archive of finalized blocks. - async fn finalize( + /// After persisting the block, attempt to dispatch the next contiguous block to the + /// application. + async fn store_finalization( &mut self, height: u64, commitment: B::Commitment, block: B, finalization: Option>, - notifier: &mut mpsc::Sender<()>, application: &mut impl Reporter>, ) { self.notify_subscribers(commitment, &block).await; @@ -816,16 +946,17 @@ impl< panic!("failed to finalize: {e}"); } - // Notify the finalizer - let _ = notifier.try_send(()); - // Update metrics and send tip update to application if height > self.tip { application.report(Update::Tip(height, commitment)).await; self.tip = height; #[cfg(feature = "prom")] - self.finalized_height.set(height as i64); + { + let _ = self.finalized_height.try_set(height); + } } + + self.try_dispatch_block(application).await; } /// Get the latest finalized block information (height and commitment tuple). @@ -871,4 +1002,105 @@ impl< Err(e) => panic!("failed to get block: {e}"), } } + + /// Attempt to repair any identified gaps in the finalized blocks archive. The total + /// number of missing heights that can be repaired at once is bounded by `self.max_repair`, + /// though multiple gaps may be spanned. + async fn try_repair_gaps( + &mut self, + buffer: &mut buffered::Mailbox, + resolver: &mut impl Resolver>, + application: &mut impl Reporter>, + ) { + let gaps = self.identify_gaps(); + + // Cancel any outstanding requests by height that sit outside of identified gaps. + // These requests are no longer needed, and clog up the resolver. + let predicate = { + let gaps = gaps.clone(); + move |height: &u64| { + gaps.iter() + .any(|(gap_start, gap_end)| (gap_start..gap_end).contains(&height)) + } + }; + self.waiting_finalized.retain(&predicate); + resolver + .retain(move |key| match key { + Request::Finalized { height } => predicate(height), + _ => true, + }) + .await; + + for (gap_start, gap_end) in gaps { + // Attempt to repair the gap backwards from the end of the gap, using + // blocks from our local storage. + let Some(mut cursor) = self.get_finalized_block(gap_end).await else { + panic!("gapped block missing that should exist: {gap_end}"); + }; + + // Iterate backwards, repairing blocks as we go. + while cursor.height() > gap_start { + let commitment = cursor.parent(); + if let Some(block) = self.find_block(buffer, commitment).await { + let finalization = self.cache.get_finalization_for(commitment).await; + self.store_finalization( + block.height(), + commitment, + block.clone(), + finalization, + application, + ) + .await; + debug!(height = block.height(), "repaired block"); + cursor = block; + } else { + // Request the next missing block digest + if self.waiting_blocks.insert(commitment) { + resolver.fetch(Request::::Block(commitment)).await; + } + break; + } + } + + // If we haven't fully repaired the gap, then also request any possible + // finalizations for the blocks in the remaining gap. This may help + // shrink the size of the gap if finalizations for the requests heights + // exist. If not, we rely on the recursive digest fetch above. + let gap_end = std::cmp::max(cursor.height(), gap_start); + debug!(gap_start, gap_end, "requesting any finalized blocks"); + for height in gap_start..gap_end { + if self.waiting_finalized.insert(height) { + resolver.fetch(Request::::Finalized { height }).await; + } + } + } + } + + /// Identifies one or more of the earliest gaps in the finalized blocks archive. The gaps + /// returned are half-open ranges, where `start` is inclusive and `end` is exclusive. The total + /// number of missing heights covered by the returned gaps is bounded by `self.max_repair`. + fn identify_gaps(&self) -> Vec<(u64, u64)> { + let mut remaining = self.max_repair.get(); + let mut gaps = Vec::new(); + let mut previous_end = FIRST_HEIGHT_IN_ARCHIVE.saturating_sub(1); + + for (range_start, range_end) in self.finalized_blocks.ranges() { + if remaining == 0 { + break; + } + + let next_expected = previous_end.saturating_add(1); + if range_start > next_expected { + let gap_size = range_start - next_expected; + let take = gap_size.min(remaining); + let gap_start = range_start.saturating_sub(take); + gaps.push((gap_start, range_start)); + remaining -= take; + } + + previous_end = range_end; + } + + gaps + } } diff --git a/syncer/src/config.rs b/syncer/src/config.rs index e67a6cbd..e981e585 100644 --- a/syncer/src/config.rs +++ b/syncer/src/config.rs @@ -68,7 +68,7 @@ where pub block_codec_config: B::Cfg, /// Maximum number of blocks to repair at once - pub max_repair: u64, + pub max_repair: NonZeroU64, pub _marker: PhantomData, } diff --git a/syncer/src/finalizer.rs b/syncer/src/finalizer.rs deleted file mode 100644 index 6dfba99f..00000000 --- a/syncer/src/finalizer.rs +++ /dev/null @@ -1,134 +0,0 @@ -use crate::{Update, ingress::orchestrator::Orchestrator}; -use commonware_consensus::simplex::signing_scheme::Scheme; -use commonware_consensus::{Block, Reporter}; -use commonware_runtime::{Clock, ContextCell, Handle, Metrics, Spawner, Storage, spawn_cell}; -use futures::channel::oneshot; -use futures::{StreamExt, channel::mpsc}; -use summit_types::utils::is_last_block_of_epoch; -use tracing::{debug, error}; -// The key used to store the last indexed height in the metadata store. - -/// Requests the finalized blocks (in order) from the orchestrator, sends them to the application, -/// waits for confirmation that the application has processed the block. -/// -/// Stores the highest height for which the application has processed. This allows resuming -/// processing from the last processed height after a restart. -pub struct Finalizer< - B: Block, - S: Scheme, - R: Spawner + Clock + Metrics + Storage, - Z: Reporter>, -> { - context: ContextCell, - - // Application that processes the finalized blocks. - application: Z, - - // Orchestrator that stores the finalized blocks. - orchestrator: Orchestrator, - - // Notifier to indicate that the finalized blocks have been updated and should be re-queried. - notifier_rx: mpsc::Receiver<()>, - - // The lowest height from which to begin syncing - sync_height: u64, - - // Number of blocks per epoch - epoch_length: u64, -} - -impl< - B: Block, - S: Scheme, - R: Spawner + Clock + Metrics + Storage, - Z: Reporter>, -> Finalizer -{ - /// Initialize the finalizer. - pub async fn new( - context: R, - application: Z, - orchestrator: Orchestrator, - notifier_rx: mpsc::Receiver<()>, - sync_height: u64, - epoch_length: u64, - ) -> Self { - Self { - context: ContextCell::new(context), - application, - orchestrator, - notifier_rx, - sync_height, - epoch_length, - } - } - - /// Start the finalizer. - pub fn start(mut self) -> Handle<()> { - spawn_cell!(self.context, self.run().await) - } - - /// Run the finalizer, which continuously fetches and processes finalized blocks. - async fn run(mut self) { - // Initialize last indexed from metadata store. - // If the key does not exist, we assume the genesis block (height 0) has been indexed. - let mut latest = self.sync_height; - - // The main loop to process finalized blocks. This loop will hot-spin until a block is - // available, at which point it will process it and continue. If a block is not available, - // it will request a repair and wait for a notification of an update before retrying. - loop { - // The next height to process is the next height after the last processed height. - let height = latest + 1; - - let (block, finalized) = if is_last_block_of_epoch(height, self.epoch_length) { - self.orchestrator.get_with_finalization(height).await - } else { - (self.orchestrator.get(height).await, None) - }; - - // Attempt to get the next block from the orchestrator. - if let Some(block) = block { - // Sanity-check that the block height is the one we expect. - assert!(block.height() == height, "block height mismatch"); - - // Send the block to the application. - // - // After an unclean shutdown (where the finalizer metadata is not synced after some - // height is processed by the application), it is possible that the application may - // be asked to process a block it has already seen (which it can simply ignore). - - let commitment = block.commitment(); - let (ack_tx, ack_rx) = oneshot::channel(); - self.application - .report(Update::Block((block, finalized), ack_tx)) - .await; - if let Err(e) = ack_rx.await { - error!(?e, height, "application did not acknowledge block"); - return; - } - - // Record that we have processed up through this height. - latest = height; - - // Notify the orchestrator that the block has been processed. - self.orchestrator.processed(height, commitment).await; - - // Loop again without waiting for a notification (there may be more to process). - continue; - } - - // We've reached a height at which we have no (finalized) block. - // It may be the case that the block is not finalized yet, or that there is a gap. - // Notify the orchestrator that we're trying to access this block. - self.orchestrator.repair(height).await; - - // Wait for a notification from the orchestrator that new blocks are available. - debug!(height, "waiting to index finalized block"); - let Some(()) = self.notifier_rx.next().await else { - error!("orchestrator closed, shutting down"); - return; - }; - } - } -} diff --git a/syncer/src/ingress/mod.rs b/syncer/src/ingress/mod.rs index c4f47e60..0de561ee 100644 --- a/syncer/src/ingress/mod.rs +++ b/syncer/src/ingress/mod.rs @@ -1,3 +1,2 @@ pub mod handler; pub mod mailbox; -pub(crate) mod orchestrator; diff --git a/syncer/src/ingress/orchestrator.rs b/syncer/src/ingress/orchestrator.rs deleted file mode 100644 index 32afc7da..00000000 --- a/syncer/src/ingress/orchestrator.rs +++ /dev/null @@ -1,116 +0,0 @@ -use crate::Block; -use commonware_consensus::simplex::signing_scheme::Scheme; -use commonware_consensus::simplex::types::Finalization; -use futures::{ - SinkExt, - channel::{mpsc, oneshot}, -}; -use tracing::error; - -/// Messages sent from the finalizer task to the main actor loop. -/// -/// We break this into a separate enum to establish a separate priority for -/// finalizer messages over consensus messages. -pub enum Orchestration { - /// A request to get the next finalized block. - Get { - /// The height of the block to get. - height: u64, - /// A channel to send the block, if found. - result: oneshot::Sender>, - }, - /// A request to get the next finalized block together with the finalization. - GetWithFinalization { - height: u64, - #[allow(clippy::type_complexity)] - result: oneshot::Sender<(Option, Option>)>, - }, - /// A notification that a block has been processed by the application. - Processed { - /// The height of the processed block. - height: u64, - /// The digest of the processed block. - digest: B::Commitment, - }, - /// A request to repair a gap in the finalized block sequence. - Repair { - /// The height at which to start repairing. - height: u64, - }, -} - -/// A handle for the finalizer to communicate with the main actor loop. -#[derive(Clone)] -pub struct Orchestrator { - sender: mpsc::Sender>, -} - -impl Orchestrator { - /// Creates a new orchestrator. - pub fn new(sender: mpsc::Sender>) -> Self { - Self { sender } - } - - /// Gets the finalized block at the given height. - pub async fn get(&mut self, height: u64) -> Option { - let (response, receiver) = oneshot::channel(); - if self - .sender - .send(Orchestration::Get { - height, - result: response, - }) - .await - .is_err() - { - error!("failed to send get message to actor: receiver dropped"); - return None; - } - receiver.await.unwrap_or(None) - } - - /// Gets the finalized block at the given height together with the finalization. - pub async fn get_with_finalization( - &mut self, - height: u64, - ) -> (Option, Option>) { - let (response, receiver) = oneshot::channel(); - if self - .sender - .send(Orchestration::GetWithFinalization { - height, - result: response, - }) - .await - .is_err() - { - error!("failed to send get_with_finalization message to actor: receiver dropped"); - return (None, None); - } - receiver.await.unwrap_or((None, None)) - } - - /// Notifies the actor that a block has been processed. - pub async fn processed(&mut self, height: u64, digest: B::Commitment) { - if self - .sender - .send(Orchestration::Processed { height, digest }) - .await - .is_err() - { - error!("failed to send processed message to actor: receiver dropped"); - } - } - - /// Attempts to repair a gap in the block sequence. - pub async fn repair(&mut self, height: u64) { - if self - .sender - .send(Orchestration::Repair { height }) - .await - .is_err() - { - error!("failed to send repair message to actor: receiver dropped"); - } - } -} diff --git a/syncer/src/lib.rs b/syncer/src/lib.rs index c8a07039..42d37eba 100644 --- a/syncer/src/lib.rs +++ b/syncer/src/lib.rs @@ -58,8 +58,6 @@ pub use actor::Actor; pub mod cache; pub mod config; pub use config::Config; -pub mod finalizer; -pub use finalizer::Finalizer; pub mod ingress; pub use ingress::mailbox::Mailbox; pub mod resolver; diff --git a/types/src/block.rs b/types/src/block.rs index 190e2fa3..0822821c 100644 --- a/types/src/block.rs +++ b/types/src/block.rs @@ -199,8 +199,6 @@ impl ConsensusBlock for Block { } impl Viewable for Block { - type View = u64; - fn view(&self) -> commonware_consensus::types::View { self.header.view } From 69876e39050a49c1e8abcfffc5e46aefa94143d0 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Wed, 12 Nov 2025 20:32:20 -0500 Subject: [PATCH 58/81] feat: use commonware's epoch boundries --- types/src/utils.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/types/src/utils.rs b/types/src/utils.rs index 62c8f09f..bb4cb3c7 100644 --- a/types/src/utils.rs +++ b/types/src/utils.rs @@ -19,11 +19,11 @@ pub fn get_expanded_path(path: &str) -> Result { } pub fn is_last_block_of_epoch(height: u64, epoch_num_blocks: u64) -> bool { - height > 0 && height % epoch_num_blocks == 0 + commonware_consensus::utils::is_last_block_in_epoch(epoch_num_blocks, height).is_some() } pub fn is_penultimate_block_of_epoch(height: u64, epoch_num_blocks: u64) -> bool { - height > 0 && (height + 1) % epoch_num_blocks == 0 + is_last_block_of_epoch(height + 1, epoch_num_blocks) } #[cfg(any(feature = "base-bench", feature = "bench"))] From bafe399f691f841538cf9e351864430b5d520dd0 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Wed, 12 Nov 2025 20:37:39 -0500 Subject: [PATCH 59/81] chore: reduce max_repair to 10 --- node/src/engine.rs | 2 +- node/src/tests/syncer.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/node/src/engine.rs b/node/src/engine.rs index 02c5d4a4..84e04909 100644 --- a/node/src/engine.rs +++ b/node/src/engine.rs @@ -42,7 +42,7 @@ const FREEZER_TABLE_RESIZE_CHUNK_SIZE: u32 = 2u32.pow(16); // 3MB const FREEZER_JOURNAL_TARGET_SIZE: u64 = 1024 * 1024 * 1024; // 1GB const FREEZER_JOURNAL_COMPRESSION: Option = Some(3); const FREEZER_TABLE_INITIAL_SIZE: u32 = 1024 * 1024; // 100mb -const MAX_REPAIR: NonZeroU64 = NonZeroU64::new(50).unwrap(); +const MAX_REPAIR: NonZeroU64 = NonZeroU64::new(10).unwrap(); // // Onboarding config (set arbitrarily for now) diff --git a/node/src/tests/syncer.rs b/node/src/tests/syncer.rs index 898a716c..3b77cc29 100644 --- a/node/src/tests/syncer.rs +++ b/node/src/tests/syncer.rs @@ -14,7 +14,7 @@ use std::time::Duration; use summit_types::{PrivateKey, keystore::KeyStore}; #[test_traced("INFO")] -fn test_node_joins_later_no_checkpoint() { +fn test_node_joins_later_no_checkpoint_in_genesis() { // Creates a network of 5 nodes, and starts only 4 of them. // The last node starts after 10 blocks, to ensure that the block backfilling // in the syncer_old works. From 50b52a2188d8ddb2bc290cbdf163ba75fa706a8d Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Wed, 12 Nov 2025 21:12:18 -0500 Subject: [PATCH 60/81] test: don't remove execution requests in test harness --- node/src/test_harness/mock_engine_client.rs | 2 +- node/src/tests/execution_requests.rs | 29 +++++++++------------ 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/node/src/test_harness/mock_engine_client.rs b/node/src/test_harness/mock_engine_client.rs index f37cd2b8..feb1092b 100644 --- a/node/src/test_harness/mock_engine_client.rs +++ b/node/src/test_harness/mock_engine_client.rs @@ -350,7 +350,7 @@ impl EngineClient for MockEngineClient { // Wrap in envelope let block_num = state.next_block_number; - let execution_requests = self.execution_requests.lock().unwrap().remove(&block_num); + let execution_requests = self.execution_requests.lock().unwrap().get(&block_num).cloned(); let envelope = ExecutionPayloadEnvelopeV4 { envelope_inner: ExecutionPayloadEnvelopeV3 { execution_payload: new_block, diff --git a/node/src/tests/execution_requests.rs b/node/src/tests/execution_requests.rs index f78e82d7..b6686e43 100644 --- a/node/src/tests/execution_requests.rs +++ b/node/src/tests/execution_requests.rs @@ -294,12 +294,12 @@ fn test_deposit_request_top_up() { let requests2 = common::execution_requests_to_requests(execution_requests2); // Create execution requests map (add deposit to block 5) - let deposit_block_height = 5; - let withdrawal_block_height = 10; - let stop_height = withdrawal_block_height + VALIDATOR_WITHDRAWAL_PERIOD + 5; + let deposit_block_height1 = 5; + let deposit_block_height2 = 10; + let stop_height = deposit_block_height2 + VALIDATOR_WITHDRAWAL_PERIOD + 5; let mut execution_requests_map = HashMap::new(); - execution_requests_map.insert(deposit_block_height, requests1); - execution_requests_map.insert(withdrawal_block_height, requests2); + execution_requests_map.insert(deposit_block_height1, requests1); + execution_requests_map.insert(deposit_block_height2, requests2); let engine_client_network = MockEngineNetworkBuilder::new(genesis_hash) .with_execution_requests(execution_requests_map) @@ -387,17 +387,14 @@ fn test_deposit_request_top_up() { continue; } // Parse the pubkey from the metric name using helper function - if let Some(ed_pubkey_hex) = common::parse_metric_substring(metric, "pubkey") { - let creds = - common::parse_metric_substring(metric, "creds").expect("creds missing"); - assert_eq!(creds, hex::encode(test_deposit1.withdrawal_credentials)); - assert_eq!(ed_pubkey_hex, test_deposit1.node_pubkey.to_string()); - // The amount from both deposits should be added to the validator balance - assert_eq!(balance, test_deposit1.amount + test_deposit2.amount); - processed_requests.insert(metric.to_string()); - } else { - println!("{}: {} (failed to parse pubkey)", metric, value); - } + let ed_pubkey_hex = common::parse_metric_substring(metric, "pubkey").expect("pubkey missing"); + let creds = + common::parse_metric_substring(metric, "creds").expect("creds missing"); + assert_eq!(creds, hex::encode(test_deposit1.withdrawal_credentials)); + assert_eq!(ed_pubkey_hex, test_deposit1.node_pubkey.to_string()); + // The amount from both deposits should be added to the validator balance + assert_eq!(balance, test_deposit1.amount + test_deposit2.amount); + processed_requests.insert(metric.to_string()); } if processed_requests.len() as u32 >= n && height_reached.len() as u32 == n { success = true; From 301af5f59a05df2e9ac8d512f9699589bcd0410f Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Wed, 12 Nov 2025 21:18:19 -0500 Subject: [PATCH 61/81] test: fix execution request e2e tests --- node/src/tests/execution_requests.rs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/node/src/tests/execution_requests.rs b/node/src/tests/execution_requests.rs index b6686e43..694db001 100644 --- a/node/src/tests/execution_requests.rs +++ b/node/src/tests/execution_requests.rs @@ -624,9 +624,8 @@ fn test_deposit_and_withdrawal_request_single() { let withdrawals = engine_client_network.get_withdrawals(); assert_eq!(withdrawals.len(), 1); let withdrawal_epoch = - (withdrawal_block_height + VALIDATOR_WITHDRAWAL_PERIOD + BLOCKS_PER_EPOCH - 1) - / BLOCKS_PER_EPOCH; - let withdrawal_height = withdrawal_epoch * BLOCKS_PER_EPOCH; + (withdrawal_block_height + VALIDATOR_WITHDRAWAL_PERIOD) / BLOCKS_PER_EPOCH; + let withdrawal_height = (withdrawal_epoch + 1) * BLOCKS_PER_EPOCH - 1; let withdrawals = withdrawals .get(&(withdrawal_height)) .expect("missing withdrawal"); @@ -864,9 +863,8 @@ fn test_partial_withdrawal_balance_below_minimum_stake() { // to the execution layer. assert_eq!(withdrawals.len(), 1); let withdrawal_epoch = - (withdrawal_block_height + VALIDATOR_WITHDRAWAL_PERIOD + BLOCKS_PER_EPOCH - 1) - / BLOCKS_PER_EPOCH; - let withdrawal_height = withdrawal_epoch * BLOCKS_PER_EPOCH; + (withdrawal_block_height + VALIDATOR_WITHDRAWAL_PERIOD) / BLOCKS_PER_EPOCH; + let withdrawal_height = (withdrawal_epoch + 1) * BLOCKS_PER_EPOCH - 1; let withdrawals = withdrawals .get(&withdrawal_height) .expect("missing withdrawal"); @@ -1099,9 +1097,8 @@ fn test_deposit_less_than_min_stake_and_withdrawal() { let withdrawals = engine_client_network.get_withdrawals(); assert_eq!(withdrawals.len(), 1); let withdrawal_epoch = - (withdrawal_block_height + VALIDATOR_WITHDRAWAL_PERIOD + BLOCKS_PER_EPOCH - 1) - / BLOCKS_PER_EPOCH; - let withdrawal_height = withdrawal_epoch * BLOCKS_PER_EPOCH; + (withdrawal_block_height + VALIDATOR_WITHDRAWAL_PERIOD) / BLOCKS_PER_EPOCH; + let withdrawal_height = (withdrawal_epoch + 1) * BLOCKS_PER_EPOCH - 1; let withdrawals = withdrawals .get(&withdrawal_height) .expect("missing withdrawal"); From b1c20bc4c19635551aa20108569f8a45c663d421 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Thu, 13 Nov 2025 10:21:29 -0500 Subject: [PATCH 62/81] test: fix test_single_engine_with_checkpoint --- finalizer/src/actor.rs | 8 ++++---- node/src/tests/checkpointing.rs | 24 ++++++++++++++++-------- syncer/src/actor.rs | 2 +- types/src/utils.rs | 6 +++--- 4 files changed, 24 insertions(+), 16 deletions(-) diff --git a/finalizer/src/actor.rs b/finalizer/src/actor.rs index dae72c78..881305f0 100644 --- a/finalizer/src/actor.rs +++ b/finalizer/src/actor.rs @@ -12,6 +12,7 @@ use commonware_cryptography::bls12381::primitives::variant::Variant; use commonware_cryptography::{Digestible, Hasher, Sha256, Signer, Verifier as _, bls12381}; use commonware_runtime::{Clock, ContextCell, Handle, Metrics, Spawner, Storage, spawn_cell}; use commonware_storage::translator::TwoCap; +use commonware_codec::{Read as CodecRead, Write as CodecWrite}; use commonware_utils::{NZU64, NZUsize, hex}; use futures::channel::{mpsc, oneshot}; use futures::{FutureExt, StreamExt as _, select}; @@ -237,7 +238,7 @@ impl< // Verify withdrawal requests that were included in the block // Make sure that the included withdrawals match the expected withdrawals let expected_withdrawals: Vec = - if is_last_block_of_epoch(new_height, self.epoch_num_of_blocks) { + if is_last_block_of_epoch(self.epoch_num_of_blocks, new_height) { let pending_withdrawals = self.state.get_next_ready_withdrawals( new_height, self.validator_max_withdrawals_per_block, @@ -331,7 +332,7 @@ impl< } let mut epoch_change = false; // Store finalizes checkpoint to database - if is_last_block_of_epoch(new_height, self.epoch_num_of_blocks) { + if is_last_block_of_epoch(self.epoch_num_of_blocks, new_height) { // Increment epoch self.state.epoch += 1; // Set the epoch genesis hash for the next epoch @@ -352,7 +353,6 @@ impl< header: block.header.clone(), finalization, }; - use commonware_codec::{Read as CodecRead, Write as CodecWrite}; let mut buf = Vec::new(); finalized_header.write(&mut buf); let concrete_header = > as CodecRead>::read_cfg(&mut buf.as_slice(), &()) @@ -781,7 +781,7 @@ impl< // Create checkpoint if we're at an epoch boundary. // The consensus state is saved every `epoch_num_blocks` blocks. // The proposed block will contain the checkpoint that was saved at the previous height. - let aux_data = if is_last_block_of_epoch(height, self.epoch_num_of_blocks) { + let aux_data = if is_last_block_of_epoch(self.epoch_num_of_blocks, height) { // TODO(matthias): revisit this expect when the ckpt isn't in the DB let checkpoint_hash = if let Some(checkpoint) = &self.state.pending_checkpoint { checkpoint.digest diff --git a/node/src/tests/checkpointing.rs b/node/src/tests/checkpointing.rs index 718deb3f..c3c6a949 100644 --- a/node/src/tests/checkpointing.rs +++ b/node/src/tests/checkpointing.rs @@ -12,7 +12,7 @@ use commonware_runtime::{Clock, Metrics, Runner as _, deterministic}; use commonware_utils::from_hex_formatted; use std::collections::{HashMap, HashSet}; use std::time::Duration; -use summit_types::PrivateKey; +use summit_types::{utils, PrivateKey}; use summit_types::consensus_state::ConsensusState; use summit_types::keystore::KeyStore; @@ -71,7 +71,7 @@ fn test_checkpoint_created() { .try_into() .expect("failed to convert genesis hash"); - let stop_height = BLOCKS_PER_EPOCH + 1; + let stop_height = BLOCKS_PER_EPOCH; let engine_client_network = MockEngineNetworkBuilder::new(genesis_hash).build(); let initial_state = get_initial_state( @@ -151,7 +151,7 @@ fn test_checkpoint_created() { if metric.ends_with("consensus_state_stored") { let height = value.parse::().unwrap(); - assert_eq!(height, BLOCKS_PER_EPOCH); + assert_eq!(height, BLOCKS_PER_EPOCH - 1); state_stored.insert(metric.to_string()); } @@ -164,7 +164,7 @@ fn test_checkpoint_created() { if metric.ends_with("finalized_header_stored") { let height = value.parse::().unwrap(); - assert_eq!(height, BLOCKS_PER_EPOCH); + assert_eq!(height, BLOCKS_PER_EPOCH - 1); header_stored.insert(metric.to_string()); } if header_stored.len() as u32 >= n @@ -353,10 +353,10 @@ fn test_previous_header_hash_matches() { let validator_id = common::extract_validator_id(metric).expect("failed to parse validator id"); - if height == BLOCKS_PER_EPOCH { + if utils::is_last_block_of_epoch(BLOCKS_PER_EPOCH, height) && height <= BLOCKS_PER_EPOCH { // This is the first time the finalized header is written to disk first_header_stored.insert(validator_id, header); - } else if height == 2 * BLOCKS_PER_EPOCH { + } else if utils::is_last_block_of_epoch(BLOCKS_PER_EPOCH, height) { // This is the second time the finalized header is written to disk if let Some(header_from_prev_epoch) = first_header_stored.get(&validator_id) { @@ -365,7 +365,8 @@ fn test_previous_header_hash_matches() { second_header_stored.insert(validator_id); } } else { - assert_eq!(height % BLOCKS_PER_EPOCH, 0); + assert!(utils::is_last_block_of_epoch(BLOCKS_PER_EPOCH, height)); + } } // There is an edge case where not all validators write a finalized header to disk. @@ -437,7 +438,14 @@ fn test_single_engine_with_checkpoint() { node_key, consensus_key, }; - let validators = vec![(node_public_key.clone(), consensus_public_key)]; + + // Create a second set of keys to stop the single engine from producing blocks. + let node_key2 = PrivateKey::from_seed(101); + let node_public_key2 = node_key2.public_key(); + let consensus_key2 = bls12381::PrivateKey::from_seed(101); + let consensus_public_key2 = consensus_key2.public_key(); + + let validators = vec![(node_public_key.clone(), consensus_public_key), (node_public_key2, consensus_public_key2)]; let node_public_keys = vec![node_public_key.clone()]; let mut registrations = common::register_validators(&mut oracle, &node_public_keys).await; diff --git a/syncer/src/actor.rs b/syncer/src/actor.rs index 0b6d49ef..71f9edfe 100644 --- a/syncer/src/actor.rs +++ b/syncer/src/actor.rs @@ -796,7 +796,7 @@ impl< let (height, commitment) = (block.height(), block.commitment()); let (ack_tx, ack_rx) = oneshot::channel(); - if utils::is_last_block_in_epoch(next_height, self.epoch_length).is_some() { + if utils::is_last_block_in_epoch(self.epoch_length, next_height).is_some() { let finalize = self.get_finalization_by_height(next_height).await; application .report(Update::Block((block, finalize), ack_tx)) diff --git a/types/src/utils.rs b/types/src/utils.rs index bb4cb3c7..70bc3cab 100644 --- a/types/src/utils.rs +++ b/types/src/utils.rs @@ -18,12 +18,12 @@ pub fn get_expanded_path(path: &str) -> Result { Ok(path_buf) } -pub fn is_last_block_of_epoch(height: u64, epoch_num_blocks: u64) -> bool { +pub fn is_last_block_of_epoch(epoch_num_blocks: u64, height: u64) -> bool { commonware_consensus::utils::is_last_block_in_epoch(epoch_num_blocks, height).is_some() } -pub fn is_penultimate_block_of_epoch(height: u64, epoch_num_blocks: u64) -> bool { - is_last_block_of_epoch(height + 1, epoch_num_blocks) +pub fn is_penultimate_block_of_epoch(epoch_num_blocks: u64, height: u64) -> bool { + is_last_block_of_epoch(epoch_num_blocks, height + 1) } #[cfg(any(feature = "base-bench", feature = "bench"))] From b606ddc7653c5e7a67ebf2b14d477b65b9dfc1e2 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Thu, 13 Nov 2025 14:31:33 -0500 Subject: [PATCH 63/81] feat: remove generic scheme from finalizer and use bls --- finalizer/src/actor.rs | 35 +++--- finalizer/src/db.rs | 24 ++-- node/src/engine.rs | 2 +- node/src/test_harness/mock_engine_client.rs | 7 +- node/src/tests/checkpointing.rs | 12 +- node/src/tests/execution_requests.rs | 3 +- syncer/src/actor.rs | 4 +- types/src/header.rs | 115 +++++++++++--------- 8 files changed, 116 insertions(+), 86 deletions(-) diff --git a/finalizer/src/actor.rs b/finalizer/src/actor.rs index 881305f0..19392da3 100644 --- a/finalizer/src/actor.rs +++ b/finalizer/src/actor.rs @@ -5,14 +5,14 @@ use alloy_primitives::Address; #[cfg(debug_assertions)] use alloy_rpc_types_engine::ForkchoiceState; use commonware_codec::{DecodeExt as _, Encode, ReadExt as _}; +use commonware_codec::{Read as CodecRead, Write as CodecWrite}; use commonware_consensus::Reporter; -use commonware_consensus::simplex::signing_scheme::{Scheme, bls12381_multisig}; +use commonware_consensus::simplex::signing_scheme::bls12381_multisig; use commonware_consensus::simplex::types::Finalization; use commonware_cryptography::bls12381::primitives::variant::Variant; use commonware_cryptography::{Digestible, Hasher, Sha256, Signer, Verifier as _, bls12381}; use commonware_runtime::{Clock, ContextCell, Handle, Metrics, Spawner, Storage, spawn_cell}; use commonware_storage::translator::TwoCap; -use commonware_codec::{Read as CodecRead, Write as CodecWrite}; use commonware_utils::{NZU64, NZUsize, hex}; use futures::channel::{mpsc, oneshot}; use futures::{FutureExt, StreamExt as _, select}; @@ -46,10 +46,9 @@ pub struct Finalizer< C: EngineClient, O: NetworkOracle, S: Signer, - Z: Scheme, V: Variant, > { - mailbox: mpsc::Receiver>>, + mailbox: mpsc::Receiver, Block>>, pending_height_notifys: BTreeMap>>, context: ContextCell, engine_client: C, @@ -76,14 +75,16 @@ impl< C: EngineClient, O: NetworkOracle, S: Signer, - Z: Scheme, V: Variant, -> Finalizer +> Finalizer { pub async fn new( context: R, cfg: FinalizerConfig, - ) -> (Self, FinalizerMailbox>) { + ) -> ( + Self, + FinalizerMailbox, Block>, + ) { let (tx, rx) = mpsc::channel(cfg.mailbox_size); // todo(dalton) pull mailbox size from config let state_cfg = StateConfig { log_partition: format!("{}-finalizer_state-log", cfg.db_prefix), @@ -213,11 +214,17 @@ impl< } } + #[allow(clippy::type_complexity)] async fn handle_execution_block( &mut self, ack_tx: oneshot::Sender<()>, block: Block, - finalization: Option as Digestible>::Digest>>, + finalization: Option< + Finalization< + bls12381_multisig::Scheme, + as Digestible>::Digest, + >, + >, #[allow(unused_variables)] last_committed_timestamp: &mut Option, ) { #[cfg(feature = "prom")] @@ -347,12 +354,13 @@ impl< // TODO(matthias): figure out a good solution for making checkpoints available debug_assert!(block.header.digest == finalization.proposal.payload); + // Get participant count from the certificate signers + let participant_count = finalization.certificate.signers.len(); + // Store the finalized block header in the database // Convert to concrete BLS scheme type by encoding and decoding - let finalized_header = FinalizedHeader { - header: block.header.clone(), - finalization, - }; + let finalized_header = + FinalizedHeader::new(block.header.clone(), finalization, participant_count); let mut buf = Vec::new(); finalized_header.write(&mut buf); let concrete_header = > as CodecRead>::read_cfg(&mut buf.as_slice(), &()) @@ -860,9 +868,8 @@ impl< C: EngineClient, O: NetworkOracle, S: Signer, - Z: Scheme, V: Variant, -> Drop for Finalizer +> Drop for Finalizer { fn drop(&mut self) { self.cancellation_token.cancel(); diff --git a/finalizer/src/db.rs b/finalizer/src/db.rs index 3b3ff576..cd67b57f 100644 --- a/finalizer/src/db.rs +++ b/finalizer/src/db.rs @@ -410,10 +410,10 @@ mod tests { proposal, certificate: BlsCertificate { signers: Signers::from(3, [0, 1, 2]), - signature: G2::zero(), + signature: G2::one(), // Use one/generator instead of zero/infinity }, }; - let finalized_header = summit_types::FinalizedHeader::new(header.clone(), finalized); + let finalized_header = summit_types::FinalizedHeader::new(header.clone(), finalized, 3); // Test that no header exists initially assert!(db.get_finalized_header(100).await.is_none()); @@ -457,10 +457,11 @@ mod tests { proposal: proposal2, certificate: BlsCertificate { signers: Signers::from(3, [0, 1, 2]), - signature: G2::zero(), + signature: G2::one(), }, }; - let finalized_header2 = summit_types::FinalizedHeader::new(header2.clone(), finalized2); + let finalized_header2 = + summit_types::FinalizedHeader::new(header2.clone(), finalized2, 3); db.store_finalized_header(200, &finalized_header2).await; db.commit().await; @@ -519,10 +520,11 @@ mod tests { proposal: proposal1, certificate: BlsCertificate { signers: Signers::from(3, [0, 1, 2]), - signature: G2::zero(), + signature: G2::one(), }, }; - let finalized_header1 = summit_types::FinalizedHeader::new(header1.clone(), finalized1); + let finalized_header1 = + summit_types::FinalizedHeader::new(header1.clone(), finalized1, 3); let header3 = summit_types::Header::compute_digest( [7u8; 32].into(), // parent @@ -548,10 +550,11 @@ mod tests { proposal: proposal3, certificate: BlsCertificate { signers: Signers::from(3, [0, 1, 2]), - signature: G2::zero(), + signature: G2::one(), }, }; - let finalized_header3 = summit_types::FinalizedHeader::new(header3.clone(), finalized3); + let finalized_header3 = + summit_types::FinalizedHeader::new(header3.clone(), finalized3, 3); let header2 = summit_types::Header::compute_digest( [5u8; 32].into(), // parent @@ -577,10 +580,11 @@ mod tests { proposal: proposal2, certificate: BlsCertificate { signers: Signers::from(3, [0, 1, 2]), - signature: G2::zero(), + signature: G2::one(), }, }; - let finalized_header2 = summit_types::FinalizedHeader::new(header2.clone(), finalized2); + let finalized_header2 = + summit_types::FinalizedHeader::new(header2.clone(), finalized2, 3); // Store headers in non-sequential order: 100, 300, 200 db.store_finalized_header(100, &finalized_header1).await; diff --git a/node/src/engine.rs b/node/src/engine.rs index 84e04909..0a8dd1ed 100644 --- a/node/src/engine.rs +++ b/node/src/engine.rs @@ -83,7 +83,7 @@ pub struct Engine< MultisigScheme, >, syncer_mailbox: summit_syncer::Mailbox, Block>, - finalizer: Finalizer, MinPk>, + finalizer: Finalizer, pub finalizer_mailbox: FinalizerMailbox, Block>, orchestrator: summit_orchestrator::Actor>, diff --git a/node/src/test_harness/mock_engine_client.rs b/node/src/test_harness/mock_engine_client.rs index feb1092b..eb389bb7 100644 --- a/node/src/test_harness/mock_engine_client.rs +++ b/node/src/test_harness/mock_engine_client.rs @@ -350,7 +350,12 @@ impl EngineClient for MockEngineClient { // Wrap in envelope let block_num = state.next_block_number; - let execution_requests = self.execution_requests.lock().unwrap().get(&block_num).cloned(); + let execution_requests = self + .execution_requests + .lock() + .unwrap() + .get(&block_num) + .cloned(); let envelope = ExecutionPayloadEnvelopeV4 { envelope_inner: ExecutionPayloadEnvelopeV3 { execution_payload: new_block, diff --git a/node/src/tests/checkpointing.rs b/node/src/tests/checkpointing.rs index c3c6a949..7c4b6790 100644 --- a/node/src/tests/checkpointing.rs +++ b/node/src/tests/checkpointing.rs @@ -12,9 +12,9 @@ use commonware_runtime::{Clock, Metrics, Runner as _, deterministic}; use commonware_utils::from_hex_formatted; use std::collections::{HashMap, HashSet}; use std::time::Duration; -use summit_types::{utils, PrivateKey}; use summit_types::consensus_state::ConsensusState; use summit_types::keystore::KeyStore; +use summit_types::{PrivateKey, utils}; #[test_traced("INFO")] fn test_checkpoint_created() { @@ -353,7 +353,9 @@ fn test_previous_header_hash_matches() { let validator_id = common::extract_validator_id(metric).expect("failed to parse validator id"); - if utils::is_last_block_of_epoch(BLOCKS_PER_EPOCH, height) && height <= BLOCKS_PER_EPOCH { + if utils::is_last_block_of_epoch(BLOCKS_PER_EPOCH, height) + && height <= BLOCKS_PER_EPOCH + { // This is the first time the finalized header is written to disk first_header_stored.insert(validator_id, header); } else if utils::is_last_block_of_epoch(BLOCKS_PER_EPOCH, height) { @@ -366,7 +368,6 @@ fn test_previous_header_hash_matches() { } } else { assert!(utils::is_last_block_of_epoch(BLOCKS_PER_EPOCH, height)); - } } // There is an edge case where not all validators write a finalized header to disk. @@ -445,7 +446,10 @@ fn test_single_engine_with_checkpoint() { let consensus_key2 = bls12381::PrivateKey::from_seed(101); let consensus_public_key2 = consensus_key2.public_key(); - let validators = vec![(node_public_key.clone(), consensus_public_key), (node_public_key2, consensus_public_key2)]; + let validators = vec![ + (node_public_key.clone(), consensus_public_key), + (node_public_key2, consensus_public_key2), + ]; let node_public_keys = vec![node_public_key.clone()]; let mut registrations = common::register_validators(&mut oracle, &node_public_keys).await; diff --git a/node/src/tests/execution_requests.rs b/node/src/tests/execution_requests.rs index 694db001..dc52ca97 100644 --- a/node/src/tests/execution_requests.rs +++ b/node/src/tests/execution_requests.rs @@ -387,7 +387,8 @@ fn test_deposit_request_top_up() { continue; } // Parse the pubkey from the metric name using helper function - let ed_pubkey_hex = common::parse_metric_substring(metric, "pubkey").expect("pubkey missing"); + let ed_pubkey_hex = + common::parse_metric_substring(metric, "pubkey").expect("pubkey missing"); let creds = common::parse_metric_substring(metric, "creds").expect("creds missing"); assert_eq!(creds, hex::encode(test_deposit1.withdrawal_credentials)); diff --git a/syncer/src/actor.rs b/syncer/src/actor.rs index 71f9edfe..55473521 100644 --- a/syncer/src/actor.rs +++ b/syncer/src/actor.rs @@ -25,6 +25,8 @@ use commonware_utils::{ }; use pin_project::pin_project; +#[cfg(feature = "prom")] +use commonware_runtime::telemetry::metrics::status::GaugeExt; use commonware_storage::metadata; use commonware_storage::metadata::Metadata; use commonware_utils::futures::OptionFuture; @@ -288,7 +290,7 @@ impl< mailbox, scheme_provider: config.scheme_provider, epoch_length: config.epoch_length, - mailbox_size: config.mailbox_size, + namespace: config.namespace, view_retention_timeout: config.view_retention_timeout, max_repair: config.max_repair, block_codec_config: config.block_codec_config, diff --git a/types/src/header.rs b/types/src/header.rs index 58ed89f5..9bb86a49 100644 --- a/types/src/header.rs +++ b/types/src/header.rs @@ -267,13 +267,19 @@ impl Read for Header { pub struct FinalizedHeader { pub header: Header, pub finalization: Finalization, + pub participant_count: usize, } impl FinalizedHeader { - pub fn new(header: Header, finalization: Finalization) -> Self { + pub fn new( + header: Header, + finalization: Finalization, + participant_count: usize, + ) -> Self { Self { header, finalization, + participant_count, } } } @@ -284,14 +290,15 @@ impl ssz::Encode for FinalizedHeader { } fn ssz_append(&self, buf: &mut Vec) { - // For simplicity, encode header first, then finalized proof using commonware encoding + // Encode header, participant count, and finalization let header_bytes = self.header.as_ssz_bytes(); let mut finalized_bytes = Vec::new(); self.finalization.write(&mut finalized_bytes); - let offset = 8; // Two 4-byte length prefixes + let offset = 8 + 4; // Two 4-byte offsets (for variable fields) + 4 bytes for u32 let mut encoder = ssz::SszEncoder::container(buf, offset); encoder.append(&header_bytes); + encoder.append(&(self.participant_count as u32)); encoder.append(&finalized_bytes); encoder.finalize(); } @@ -301,7 +308,7 @@ impl ssz::Encode for FinalizedHeader { let mut finalized_bytes = Vec::new(); self.finalization.write(&mut finalized_bytes); - header_bytes.len() + finalized_bytes.len() + 8 // Two 4-byte length prefixes + 12 + header_bytes.len() + finalized_bytes.len() // Fixed part: 2 offsets + u32 = 12 bytes } } @@ -316,28 +323,20 @@ where fn from_ssz_bytes(bytes: &[u8]) -> Result { let mut builder = ssz::SszDecoderBuilder::new(bytes); builder.register_type::>()?; // header bytes + builder.register_type::()?; // participant count builder.register_type::>()?; // finalized bytes let mut decoder = builder.build()?; let header_bytes: Vec = decoder.decode_next()?; + let participant_count: u32 = decoder.decode_next()?; let finalized_bytes: Vec = decoder.decode_next()?; let header = Header::from_ssz_bytes(&header_bytes) .map_err(|e| ssz::DecodeError::BytesInvalid(format!("{e:?}")))?; - // The certificate config needs to be derived from the buffer size (participant count) - // This works because we know bls12381_multisig::Certificate::Cfg = usize - // We construct it here where we have the concrete type information + // Decode the finalization using the stored participant count let mut finalized_buf = finalized_bytes.as_slice(); - - // For BLS multisig, the Cfg is the participant count, which we derive from buffer size - // This is a limitation of the SSZ decode not having access to external config - // The actual participant count should ideally come from the registry/validator set - let participant_count_bytes = finalized_buf.remaining(); - - // We need to convert usize to Cfg type, but can't use From without the bound - // So we're stuck needing the From bound here for SSZ compatibility - let cfg = ::Cfg::from(participant_count_bytes); + let cfg = ::Cfg::from(participant_count as usize); let finalization = Finalization::::read_cfg(&mut finalized_buf, &cfg) .map_err(|e| ssz::DecodeError::BytesInvalid(format!("{e:?}")))?; @@ -351,6 +350,7 @@ where Ok(Self { header, finalization, + participant_count: participant_count as usize, }) } } @@ -397,16 +397,18 @@ mod test { use super::*; use alloy_primitives::{U256, hex}; use commonware_codec::{DecodeExt as _, Encode as _}; - use commonware_consensus::simplex::signing_scheme::ed25519; + use commonware_consensus::simplex::signing_scheme::bls12381_multisig; use commonware_consensus::{ simplex::{ - signing_scheme::{ed25519::Certificate, utils::Signers}, + signing_scheme::utils::Signers, types::{Finalization, Proposal}, }, types::Round, }; - use commonware_cryptography::ed25519::PrivateKey; - use commonware_cryptography::{PrivateKeyExt, Signer}; + use commonware_cryptography::bls12381::primitives::{ + group::{Element, G2}, + variant::MinPk, + }; use ssz::Decode; fn create_test_public_key(seed: u8) -> PublicKey { @@ -480,28 +482,33 @@ mod test { payload: header.digest, }; - // Create valid signatures for the certificate - let signer1 = PrivateKey::from_seed(0); - let sig1 = signer1.sign(None, header.digest.as_ref()); - - let signer2 = PrivateKey::from_seed(1); - let sig2 = signer2.sign(None, header.digest.as_ref()); - + // Use BLS certificate + type BlsCertificate = bls12381_multisig::Certificate; let finalized = Finalization { proposal, - certificate: Certificate { - signers: Signers::from(3, [0, 2]), // 2 signers out of 3 participants - signatures: vec![sig1, sig2], + certificate: BlsCertificate { + signers: Signers::from(3, [0, 1, 2]), + signature: G2::one(), }, }; - let finalized_header = FinalizedHeader::::new(header.clone(), finalized); + let finalized_header = FinalizedHeader::>::new( + header.clone(), + finalized, + 3, + ); let encoded = finalized_header.encode(); - let decoded = FinalizedHeader::::decode(encoded).unwrap(); + let decoded = + FinalizedHeader::>::decode(encoded) + .unwrap(); assert_eq!(finalized_header.finalization, decoded.finalization); assert_eq!(finalized_header.header, decoded.header); + assert_eq!( + finalized_header.participant_count, + decoded.participant_count + ); assert_eq!(finalized_header.header, header); } @@ -532,31 +539,27 @@ mod test { payload: dummy_digest.into(), // Wrong digest }; - // Create some dummy signatures for the certificate - let signer1 = PrivateKey::from_seed(0); - let sig1 = signer1.sign(None, &dummy_digest); - - let signer2 = PrivateKey::from_seed(1); - let sig2 = signer2.sign(None, &dummy_digest); - - let signer3 = PrivateKey::from_seed(2); - let sig3 = signer3.sign(None, &dummy_digest); - + // Use BLS certificate with wrong payload + type BlsCertificate = bls12381_multisig::Certificate; let wrong_finalized = Finalization { proposal: wrong_proposal, - certificate: Certificate { - signers: Signers::from(5, [0, 2, 4]), // 3 signers out of 5 participants - signatures: vec![sig1, sig2, sig3], + certificate: BlsCertificate { + signers: Signers::from(5, [0, 2, 4]), + signature: G2::one(), }, }; - let finalized_header: FinalizedHeader = FinalizedHeader { - header, - finalization: wrong_finalized, - }; + let finalized_header: FinalizedHeader> = + FinalizedHeader { + header, + finalization: wrong_finalized, + participant_count: 5, + }; let encoded = finalized_header.as_ssz_bytes(); - let result = FinalizedHeader::::from_ssz_bytes(&encoded); + let result = FinalizedHeader::>::from_ssz_bytes( + &encoded, + ); assert!(result.is_err()); println!("{:?}", result); @@ -589,15 +592,19 @@ mod test { payload: header.digest, }; + // Use BLS certificate + type BlsCertificate = bls12381_multisig::Certificate; let finalized = Finalization { proposal, - certificate: Certificate { - signers: Signers::from(0, []), - signatures: Vec::new(), + certificate: BlsCertificate { + signers: Signers::from(4, [0, 1, 2, 3]), + signature: G2::one(), }, }; - let finalized_header = FinalizedHeader::::new(header, finalized); + let finalized_header = FinalizedHeader::>::new( + header, finalized, 4, + ); let ssz_len = finalized_header.ssz_bytes_len(); let encode_len = finalized_header.encode_size(); From 1de394d4f76f0d24a8837e8fe948333bb9d82e3e Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Thu, 13 Nov 2025 20:55:21 +0000 Subject: [PATCH 64/81] allow get_public_key and health check before getting genesis --- node/src/args.rs | 6 ++++-- rpc/src/lib.rs | 8 +++++--- rpc/src/routes.rs | 8 ++++++++ 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/node/src/args.rs b/node/src/args.rs index 7472eb13..abb63991 100644 --- a/node/src/args.rs +++ b/node/src/args.rs @@ -176,13 +176,14 @@ impl Command { // use the context async move to spawn a new runtime let genesis_path = flags.genesis_path.clone(); + let key_path = flags.key_path.clone(); let rpc_port = flags.rpc_port; let _rpc_handle = context .with_label("rpc_genesis") .spawn(move |_context| async move { let genesis_sender = Command::check_sender(genesis_path, genesis_tx); if let Err(e) = - start_rpc_server_for_genesis(genesis_sender, rpc_port, cloned_token).await + start_rpc_server_for_genesis(genesis_sender, key_path, rpc_port, cloned_token).await { error!("RPC server failed: {}", e); } @@ -399,12 +400,13 @@ pub fn run_node_with_runtime( // use the context async move to spawn a new runtime let rpc_port = flags.rpc_port; let genesis_path = flags.genesis_path.clone(); + let key_path = flags.key_path.clone(); let _rpc_handle = context .with_label("rpc_genesis") .spawn(move |_context| async move { let genesis_sender = Command::check_sender(genesis_path, genesis_tx); if let Err(e) = - start_rpc_server_for_genesis(genesis_sender, rpc_port, cloned_token).await + start_rpc_server_for_genesis(genesis_sender, key_path, rpc_port, cloned_token).await { error!("RPC server failed: {}", e); } diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 79a73937..e3ab1660 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -60,20 +60,22 @@ impl PathSender { pub struct GenesisRpcState { genesis: PathSender, + key_path: String, } impl GenesisRpcState { - pub fn new(genesis: PathSender) -> Self { - Self { genesis } + pub fn new(genesis: PathSender, key_path: String) -> Self { + Self { genesis, key_path } } } pub async fn start_rpc_server_for_genesis( genesis: PathSender, + key_path: String, port: u16, cancel_token: CancellationToken, ) -> anyhow::Result<()> { - let state = GenesisRpcState::new(genesis); + let state = GenesisRpcState::new(genesis, key_path); let server = RpcRoutes::mount_for_genesis(state); diff --git a/rpc/src/routes.rs b/rpc/src/routes.rs index 3c877880..9e12ec72 100644 --- a/rpc/src/routes.rs +++ b/rpc/src/routes.rs @@ -33,6 +33,8 @@ impl RpcRoutes { let state = Arc::new(state); Router::new() + .route("/health", get(Self::handle_health_check)) + .route("/get_public_key", get(Self::handle_get_pub_key_genesis)) .route("/send_genesis", post(Self::handle_send_genesis)) .with_state(state) } @@ -47,6 +49,12 @@ impl RpcRoutes { Ok(private_key.public_key().to_string()) } + async fn handle_get_pub_key_genesis(State(state): State>) -> Result { + let private_key = Self::read_ed_key_from_path(&state.key_path)?; + + Ok(private_key.public_key().to_string()) + } + fn read_ed_key_from_path(key_path: &str) -> Result { let path = get_expanded_path(key_path).map_err(|_| "unable to get key_path")?; let encoded_pk = From 07645def99623fef946cb5ba4e5d76eb22ee82dd Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Thu, 13 Nov 2025 16:24:21 -0500 Subject: [PATCH 65/81] chore: update testnet keys --- testnet/node0/consensus_key.pem | 1 + testnet/node0/node_key.pem | 1 + testnet/node0/share.pem | 1 - testnet/node1/consensus_key.pem | 1 + testnet/node1/node_key.pem | 1 + testnet/node1/share.pem | 1 - testnet/node2/consensus_key.pem | 1 + testnet/node2/node_key.pem | 1 + testnet/node2/share.pem | 1 - testnet/node3/consensus_key.pem | 1 + testnet/node3/node_key.pem | 1 + testnet/node3/share.pem | 1 - 12 files changed, 8 insertions(+), 4 deletions(-) create mode 100644 testnet/node0/consensus_key.pem create mode 100644 testnet/node0/node_key.pem delete mode 100644 testnet/node0/share.pem create mode 100644 testnet/node1/consensus_key.pem create mode 100644 testnet/node1/node_key.pem delete mode 100644 testnet/node1/share.pem create mode 100644 testnet/node2/consensus_key.pem create mode 100644 testnet/node2/node_key.pem delete mode 100644 testnet/node2/share.pem create mode 100644 testnet/node3/consensus_key.pem create mode 100644 testnet/node3/node_key.pem delete mode 100644 testnet/node3/share.pem diff --git a/testnet/node0/consensus_key.pem b/testnet/node0/consensus_key.pem new file mode 100644 index 00000000..09fb5919 --- /dev/null +++ b/testnet/node0/consensus_key.pem @@ -0,0 +1 @@ +0097b3521bf678203a7fb449b3d5e4870ce56cac94c837b6a116a78f902a891f \ No newline at end of file diff --git a/testnet/node0/node_key.pem b/testnet/node0/node_key.pem new file mode 100644 index 00000000..f67a873f --- /dev/null +++ b/testnet/node0/node_key.pem @@ -0,0 +1 @@ +19887e80c3ebb397ef2167b52beb89eab9208699f918dfb311c9a44cb52f8b25 \ No newline at end of file diff --git a/testnet/node0/share.pem b/testnet/node0/share.pem deleted file mode 100644 index 80de6f85..00000000 --- a/testnet/node0/share.pem +++ /dev/null @@ -1 +0,0 @@ -00518410b582e2b746014ed3c495f97d8b2e8aa0b76af6d924e743438377e59e3c \ No newline at end of file diff --git a/testnet/node1/consensus_key.pem b/testnet/node1/consensus_key.pem new file mode 100644 index 00000000..251c50c6 --- /dev/null +++ b/testnet/node1/consensus_key.pem @@ -0,0 +1 @@ +52492c2b86e7945d968261ea45e7ed76e668334cb2cd65c330e2fa30858947e9 \ No newline at end of file diff --git a/testnet/node1/node_key.pem b/testnet/node1/node_key.pem new file mode 100644 index 00000000..f2909f0d --- /dev/null +++ b/testnet/node1/node_key.pem @@ -0,0 +1 @@ +73e4378f96542f5f114783015018a4b2b4fd05bd0350a902453fe0c9aec04ae5 \ No newline at end of file diff --git a/testnet/node1/share.pem b/testnet/node1/share.pem deleted file mode 100644 index bcb2bbd9..00000000 --- a/testnet/node1/share.pem +++ /dev/null @@ -1 +0,0 @@ -015f1c08c898945a1b5a5cb0a27da46f302166fea561901fb3c5b4a740995e6fda \ No newline at end of file diff --git a/testnet/node2/consensus_key.pem b/testnet/node2/consensus_key.pem new file mode 100644 index 00000000..92b9e11b --- /dev/null +++ b/testnet/node2/consensus_key.pem @@ -0,0 +1 @@ +57143daea8555989051a247149395a09139e7c60549b021a3585229e76daacab \ No newline at end of file diff --git a/testnet/node2/node_key.pem b/testnet/node2/node_key.pem new file mode 100644 index 00000000..dd2659c0 --- /dev/null +++ b/testnet/node2/node_key.pem @@ -0,0 +1 @@ +a6bc4b7c0777a7b5a0c20e457458a56e69ad8e66cefe604d1d6a92809acb1857 \ No newline at end of file diff --git a/testnet/node2/share.pem b/testnet/node2/share.pem deleted file mode 100644 index 8fc3b29c..00000000 --- a/testnet/node2/share.pem +++ /dev/null @@ -1 +0,0 @@ -02315d6d277dccbe5a85143eebe8617cb21972ad7152a13354571aa0672f610db7 \ No newline at end of file diff --git a/testnet/node3/consensus_key.pem b/testnet/node3/consensus_key.pem new file mode 100644 index 00000000..28403b45 --- /dev/null +++ b/testnet/node3/consensus_key.pem @@ -0,0 +1 @@ +6f6d0f26da2e5766bf66e370f06e5f4619ce1ef1d0578753f564e49fb6fd46ee \ No newline at end of file diff --git a/testnet/node3/node_key.pem b/testnet/node3/node_key.pem new file mode 100644 index 00000000..33e10019 --- /dev/null +++ b/testnet/node3/node_key.pem @@ -0,0 +1 @@ +79c344fb0ee59419c73669acc0ac4e437e19c2bb71f63899015862d78497a298 \ No newline at end of file diff --git a/testnet/node3/share.pem b/testnet/node3/share.pem deleted file mode 100644 index c2fbb45a..00000000 --- a/testnet/node3/share.pem +++ /dev/null @@ -1 +0,0 @@ -033c35e5255c29614bb4af56a8dfd27e166a6b511e3e2870059b752ef639ed77d4 \ No newline at end of file From d0bf2c8a88f2ca25b00d2738a63c1fd1be97ac44 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Thu, 13 Nov 2025 16:44:49 -0500 Subject: [PATCH 66/81] chore: pass in timeouts to orchestrator from config --- finalizer/src/actor.rs | 5 +++-- node/src/args.rs | 2 +- node/src/bin/testnet.rs | 6 ++---- node/src/engine.rs | 6 ++++++ orchestrator/src/actor.rs | 34 ++++++++++++++++++++++++++++------ 5 files changed, 40 insertions(+), 13 deletions(-) diff --git a/finalizer/src/actor.rs b/finalizer/src/actor.rs index 19392da3..73570fd6 100644 --- a/finalizer/src/actor.rs +++ b/finalizer/src/actor.rs @@ -2,9 +2,9 @@ use crate::db::{Config as StateConfig, FinalizerState}; use crate::{FinalizerConfig, FinalizerMailbox, FinalizerMessage}; use alloy_eips::eip4895::Withdrawal; use alloy_primitives::Address; -#[cfg(debug_assertions)] use alloy_rpc_types_engine::ForkchoiceState; -use commonware_codec::{DecodeExt as _, Encode, ReadExt as _}; +#[allow(unused)] +use commonware_codec::{DecodeExt as _, ReadExt as _}; use commonware_codec::{Read as CodecRead, Write as CodecWrite}; use commonware_consensus::Reporter; use commonware_consensus::simplex::signing_scheme::bls12381_multisig; @@ -705,6 +705,7 @@ impl< } #[cfg(debug_assertions)] { + use commonware_codec::Encode; let gauge: Gauge = Gauge::default(); gauge.set(validator_balance as i64); self.context.register( diff --git a/node/src/args.rs b/node/src/args.rs index 410870e2..ca6af1eb 100644 --- a/node/src/args.rs +++ b/node/src/args.rs @@ -593,7 +593,7 @@ pub fn run_node_with_runtime( let rpc_port = flags.rpc_port; let stop_signal = context.stopped(); let rpc_handle = context - .with_label("rpc_genesis") + .with_label("rpc") .spawn(move |_context| async move { if let Err(e) = start_rpc_server(finalizer_mailbox, key_store_path, rpc_port, stop_signal).await diff --git a/node/src/bin/testnet.rs b/node/src/bin/testnet.rs index c5268aba..c292477c 100644 --- a/node/src/bin/testnet.rs +++ b/node/src/bin/testnet.rs @@ -95,8 +95,6 @@ fn main() -> Result<(), Box> { .keep_stdout() // .genesis(serde_json::from_str(&genesis_str).expect("invalid genesis")) .data_dir(format!("testnet/node{x}/data/reth_db")) - .arg("--authrpc.jwtsecret") - .arg("testnet/jwt.hex") .arg("--enclave.mock-server") .arg("--enclave.endpoint-port") .arg(format!("1744{x}")) @@ -127,8 +125,8 @@ fn main() -> Result<(), Box> { .expect("Failed to write to log file"); } } - Err(_e) => { - // eprintln!("[Node {}] Error reading line: {}", x, e); + Err(e) => { + eprintln!("[Node {}] Error reading line: {}", x, e); } } } diff --git a/node/src/engine.rs b/node/src/engine.rs index 0a8dd1ed..826d20b3 100644 --- a/node/src/engine.rs +++ b/node/src/engine.rs @@ -182,6 +182,12 @@ where rate_limit: cfg.fetch_rate_per_peer, blocks_per_epoch: BLOCKS_PER_EPOCH, partition_prefix: cfg.partition_prefix.clone(), + leader_timeout: cfg.leader_timeout, + notarization_timeout: cfg.notarization_timeout, + nullify_retry: cfg.nullify_retry, + fetch_timeout: cfg.fetch_timeout, + activity_timeout: cfg.activity_timeout, + skip_timeout: cfg.skip_timeout, }, ); diff --git a/orchestrator/src/actor.rs b/orchestrator/src/actor.rs index 79f64e69..cd511fa4 100644 --- a/orchestrator/src/actor.rs +++ b/orchestrator/src/actor.rs @@ -51,6 +51,14 @@ where // Partition prefix used for orchestrator metadata persistence pub partition_prefix: String, + + // Consensus timeouts + pub leader_timeout: Duration, + pub notarization_timeout: Duration, + pub nullify_retry: Duration, + pub fetch_timeout: Duration, + pub activity_timeout: u64, + pub skip_timeout: u64, } pub struct Actor @@ -75,6 +83,14 @@ where rate_limit: governor::Quota, pool_ref: PoolRef, blocks_per_epoch: u64, + + // Consensus timeouts + leader_timeout: Duration, + notarization_timeout: Duration, + nullify_retry: Duration, + fetch_timeout: Duration, + activity_timeout: u64, + skip_timeout: u64, } impl Actor @@ -103,6 +119,12 @@ where rate_limit: config.rate_limit, pool_ref, blocks_per_epoch: config.blocks_per_epoch, + leader_timeout: config.leader_timeout, + notarization_timeout: config.notarization_timeout, + nullify_retry: config.nullify_retry, + fetch_timeout: config.fetch_timeout, + activity_timeout: config.activity_timeout, + skip_timeout: config.skip_timeout, }, Mailbox::new(sender), ) @@ -357,12 +379,12 @@ where namespace: self.namespace.clone(), replay_buffer: NZUsize!(1024 * 1024), write_buffer: NZUsize!(1024 * 1024), - leader_timeout: Duration::from_secs(1), - notarization_timeout: Duration::from_secs(2), - nullify_retry: Duration::from_secs(10), - fetch_timeout: Duration::from_secs(1), - activity_timeout: 256, - skip_timeout: 10, + leader_timeout: self.leader_timeout, + notarization_timeout: self.notarization_timeout, + nullify_retry: self.nullify_retry, + fetch_timeout: self.fetch_timeout, + activity_timeout: self.activity_timeout, + skip_timeout: self.skip_timeout, max_fetch_count: 32, fetch_concurrent: 2, fetch_rate_per_peer: Quota::per_second(NZU32!(1)), From 9060e7138b506671c1df659b9b28ac4d41dbac17 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Thu, 13 Nov 2025 17:36:18 -0500 Subject: [PATCH 67/81] chore: use local network config for binary tests --- node/src/args.rs | 12 +----------- node/src/bin/stake_and_checkpoint.rs | 4 ++-- node/src/bin/testnet.rs | 4 ++-- node/src/bin/withdraw_and_exit.rs | 4 ++-- 4 files changed, 7 insertions(+), 17 deletions(-) diff --git a/node/src/args.rs b/node/src/args.rs index ca6af1eb..7138ef44 100644 --- a/node/src/args.rs +++ b/node/src/args.rs @@ -399,7 +399,7 @@ impl Command { } } -pub fn run_node_with_runtime( +pub fn run_node_local( context: tokio::Context, flags: RunFlags, checkpoint: Option, @@ -494,7 +494,6 @@ pub fn run_node_with_runtime( } // configure network - #[cfg(feature = "e2e")] let mut p2p_cfg = authenticated::discovery::Config::local( key_store.node_key.clone(), genesis.namespace.as_bytes(), @@ -503,15 +502,6 @@ pub fn run_node_with_runtime( network_committee, genesis.max_message_size_bytes as usize, ); - #[cfg(not(feature = "e2e"))] - let mut p2p_cfg = authenticated::discovery::Config::recommended( - key_store.node_key.clone(), - genesis.namespace.as_bytes(), - SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), flags.port), - our_ip, - network_committee, - genesis.max_message_size_bytes as usize, - ); p2p_cfg.mailbox_size = MAILBOX_SIZE; // Start p2p diff --git a/node/src/bin/stake_and_checkpoint.rs b/node/src/bin/stake_and_checkpoint.rs index 7201a932..71cf0212 100644 --- a/node/src/bin/stake_and_checkpoint.rs +++ b/node/src/bin/stake_and_checkpoint.rs @@ -32,7 +32,7 @@ use std::{ str::FromStr as _, thread::JoinHandle, }; -use summit::args::{RunFlags, run_node_with_runtime}; +use summit::args::{RunFlags, run_node_local}; use summit::engine::{PROTOCOL_VERSION, VALIDATOR_MINIMUM_STAKE}; use summit_types::checkpoint::Checkpoint; use summit_types::consensus_state::ConsensusState; @@ -192,7 +192,7 @@ fn main() -> Result<(), Box> { executor.start(|node_context| async move { let node_handle = node_context.clone().spawn(|ctx| async move { - run_node_with_runtime(ctx, flags, None).await.unwrap(); + run_node_local(ctx, flags, None).await.unwrap(); }); // Wait for stop signal or node completion diff --git a/node/src/bin/testnet.rs b/node/src/bin/testnet.rs index c292477c..89317e82 100644 --- a/node/src/bin/testnet.rs +++ b/node/src/bin/testnet.rs @@ -18,7 +18,7 @@ use std::{ use alloy_node_bindings::Reth; use clap::Parser; use commonware_runtime::{Metrics as _, Runner as _, Spawner as _, tokio}; -use summit::args::{RunFlags, run_node_with_runtime}; +use summit::args::{RunFlags, run_node_local}; #[derive(Parser, Debug)] struct Args { @@ -166,7 +166,7 @@ fn main() -> Result<(), Box> { // Start our consensus engine let handle = - run_node_with_runtime(context.with_label(&format!("node{x}")), flags, None); + run_node_local(context.with_label(&format!("node{x}")), flags, None); consensus_handles.push(handle); } diff --git a/node/src/bin/withdraw_and_exit.rs b/node/src/bin/withdraw_and_exit.rs index befa622c..d674675c 100644 --- a/node/src/bin/withdraw_and_exit.rs +++ b/node/src/bin/withdraw_and_exit.rs @@ -29,7 +29,7 @@ use std::{ str::FromStr as _, thread::JoinHandle, }; -use summit::args::{RunFlags, run_node_with_runtime}; +use summit::args::{RunFlags, run_node_with_runtime, run_node_local}; use summit::engine::{BLOCKS_PER_EPOCH, VALIDATOR_MINIMUM_STAKE}; use summit_types::PublicKey; use summit_types::reth::Reth; @@ -182,7 +182,7 @@ fn main() -> Result<(), Box> { executor.start(|node_context| async move { let node_handle = node_context.clone().spawn(|ctx| async move { - run_node_with_runtime(ctx, flags, None).await.unwrap(); + run_node_local(ctx, flags, None).await.unwrap(); }); // Wait for stop signal or node completion From 0a61e6d6c1aaa87f3c813dce0880116f6179a2b7 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Thu, 13 Nov 2025 17:37:37 -0500 Subject: [PATCH 68/81] chore: remove block fetcher bin --- node/Cargo.toml | 5 - node/src/bin/block_fetcher.rs | 294 ---------------------------------- 2 files changed, 299 deletions(-) delete mode 100644 node/src/bin/block_fetcher.rs diff --git a/node/Cargo.toml b/node/Cargo.toml index 1f5a6b00..76556bd2 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -21,11 +21,6 @@ name = "withdraw-and-exit" path = "src/bin/withdraw_and_exit.rs" required-features = ["e2e"] -[[bin]] -name = "block-fetcher" -path = "src/bin/block_fetcher.rs" -required-features = ["bench"] - [[bin]] name = "execute-blocks" path = "src/bin/execute_blocks.rs" diff --git a/node/src/bin/block_fetcher.rs b/node/src/bin/block_fetcher.rs deleted file mode 100644 index 2f553ac6..00000000 --- a/node/src/bin/block_fetcher.rs +++ /dev/null @@ -1,294 +0,0 @@ -use alloy_network::AnyRpcBlock; -use alloy_primitives::{B256, BlockNumber, FixedBytes}; -use alloy_provider::{Provider, RootProvider, network::AnyNetwork}; -use alloy_rpc_client::ClientBuilder; -use alloy_rpc_types_engine::{ExecutionPayload, ExecutionPayloadV3}; -use anyhow::{Result, anyhow}; -use clap::{Arg, Command, Subcommand}; -use serde::{Deserialize, Serialize}; -use std::fs; -use std::path::PathBuf; -use summit_types::utils::benchmarking::BlockIndex; -use tokio::time::{Duration, sleep}; -use tracing::{error, info}; - -#[derive(Subcommand)] -enum Commands { - /// Fetch blocks from RPC endpoint - Fetch { - /// RPC endpoint URL - #[arg(long)] - rpc_url: String, - /// Starting block number - #[arg(long)] - start_block: u64, - /// Ending block number - #[arg(long)] - end_block: u64, - /// Output directory for block files - #[arg(long, default_value = "./blocks")] - output_dir: String, - /// Number of blocks to process in parallel - #[arg(long, default_value = "10")] - batch_size: usize, - /// Delay between batches in milliseconds - #[arg(long, default_value = "100")] - delay_ms: u64, - }, - /// Verify the block index - Verify { - /// Directory containing block files - #[arg(long)] - block_dir: String, - }, -} - -#[derive(Debug, Serialize, Deserialize)] -struct BlockData { - pub block_number: u64, - pub payload: ExecutionPayloadV3, - pub requests: FixedBytes<32>, - pub parent_beacon_block_root: B256, - pub versioned_hashes: Vec, -} - -#[tokio::main] -async fn main() -> Result<()> { - tracing_subscriber::fmt::init(); - - let cli = Command::new("Block Fetcher") - .version("1.0") - .about("Fetches historical blocks and creates zip archives") - .subcommand_required(true) - .subcommand( - Command::new("fetch") - .about("Fetch blocks from RPC endpoint") - .arg(Arg::new("rpc-url").long("rpc-url").required(true)) - .arg(Arg::new("start-block").long("start-block").required(true)) - .arg(Arg::new("end-block").long("end-block").required(true)) - .arg( - Arg::new("output-dir") - .long("output-dir") - .default_value("./blocks"), - ) - .arg( - Arg::new("batch-size") - .long("batch-size") - .default_value("10"), - ) - .arg(Arg::new("delay-ms").long("delay-ms").default_value("100")), - ) - .subcommand( - Command::new("verify") - .about("Build a zip file from block directory") - .arg(Arg::new("block-dir").long("block-dir").required(true)), - ); - - let matches = cli.get_matches(); - - match matches.subcommand() { - Some(("fetch", sub_matches)) => { - let rpc_url = sub_matches.get_one::("rpc-url").unwrap(); - let start_block: u64 = sub_matches - .get_one::("start-block") - .unwrap() - .parse()?; - let end_block: u64 = sub_matches - .get_one::("end-block") - .unwrap() - .parse()?; - let output_dir = PathBuf::from(sub_matches.get_one::("output-dir").unwrap()); - let batch_size: usize = sub_matches - .get_one::("batch-size") - .unwrap() - .parse()?; - let delay_ms: u64 = sub_matches.get_one::("delay-ms").unwrap().parse()?; - - if start_block > end_block { - return Err(anyhow!( - "Start block must be less than or equal to end block" - )); - } - - fetch_blocks( - rpc_url, - start_block, - end_block, - output_dir, - batch_size, - delay_ms, - ) - .await - } - Some(("verify", sub_matches)) => { - let block_dir = sub_matches.get_one::("block-dir").unwrap(); - - verify(block_dir).await - } - _ => unreachable!(), - } -} - -async fn fetch_blocks( - rpc_url: &str, - start_block: u64, - end_block: u64, - output_dir: PathBuf, - batch_size: usize, - delay_ms: u64, -) -> Result<()> { - // Create output directory - fs::create_dir_all(&output_dir)?; - - // Initialize block index - let index_path = output_dir.join("index.json"); - let mut block_index = BlockIndex::load_from_file(&index_path)?; - - info!("Connecting to RPC at {}", rpc_url); - let client = ClientBuilder::default().http(rpc_url.parse()?); - let provider = RootProvider::::new(client); - - info!("Fetching blocks from {} to {}", start_block, end_block); - info!("Output directory: {}", output_dir.display()); - info!("Batch size: {}, delay: {}ms", batch_size, delay_ms); - - let total_blocks = end_block - start_block + 1; - let mut processed = 0; - - for chunk_start in (start_block..=end_block).step_by(batch_size) { - let chunk_end = (chunk_start + batch_size as u64 - 1).min(end_block); - - info!("Processing batch: {} to {}", chunk_start, chunk_end); - - let mut tasks = Vec::new(); - - for block_num in chunk_start..=chunk_end { - // Skip if block already exists - if block_index.get_block_file(block_num).is_some() { - info!("Block {} already exists, skipping", block_num); - processed += 1; - continue; - } - - let provider_clone = provider.clone(); - let task = - tokio::spawn( - async move { fetch_and_serialize_block(provider_clone, block_num).await }, - ); - tasks.push((block_num, task)); - } - - // Wait for all tasks in this batch to complete - for (block_num, task) in tasks { - match task.await? { - Ok(block_data) => { - let filename = format!("block_{}.json", block_num); - let file_path = output_dir.join(&filename); - - let block_hash = block_data.payload.payload_inner.payload_inner.block_hash; - - // Save block data to file - let json = serde_json::to_string_pretty(&block_data)?; - - let temp_file = output_dir.join("block.temp"); - fs::write(&temp_file, json)?; - fs::rename(&temp_file, file_path)?; - - // Update index - block_index.add_block(block_num, block_hash, filename); - - processed += 1; - info!("Saved block {} ({}/{})", block_num, processed, total_blocks); - } - Err(e) => { - error!("Failed to fetch block {}: {}", block_num, e); - } - } - } - - // Save index periodically - block_index.save_to_file(&index_path)?; - - // Add delay between batches to be nice to the RPC endpoint - if chunk_end < end_block { - sleep(Duration::from_millis(delay_ms)).await; - } - } - - // Final save of index - block_index.save_to_file(&index_path)?; - info!("Completed! Processed {} blocks", processed); - info!("Block index saved to: {}", index_path.display()); - - Ok(()) -} - -async fn fetch_and_serialize_block( - provider: impl Provider, - block_number: u64, -) -> Result { - let block_id = BlockNumber::from(block_number).into(); - - // Fetch full block with transactions - let block: AnyRpcBlock = provider - .get_block(block_id) - .full() - .await? - .ok_or_else(|| anyhow!("Block {} not found", block_number))?; - - let block = block - .into_inner() - .map_header(|header| header.map(|h| h.into_header_with_defaults())) - .try_map_transactions(|tx| { - // try to convert unknowns into op type so that we can also support optimism - tx.try_into_either::() - })? - .into_consensus(); - - // Extract parent beacon block root - //let parent_beacon_block_root = block.header.parent_beacon_block_root; - - // Extract blob versioned hashes - let versioned_hashes = block - .body - .blob_versioned_hashes_iter() - .copied() - .collect::>(); - - // Convert to execution payload - let (payload, sidecar) = ExecutionPayload::from_block_slow(&block); - - // Convert payload to V3 format, handling V1/V2 payloads - let payload_v3 = match payload { - ExecutionPayload::V1(v1) => ExecutionPayloadV3 { - payload_inner: alloy_rpc_types_engine::ExecutionPayloadV2 { - payload_inner: v1, - withdrawals: Vec::new(), // V1 doesn't have withdrawals - }, - blob_gas_used: 0, // V1 doesn't have blob gas - excess_blob_gas: 0, - }, - ExecutionPayload::V2(v2) => ExecutionPayloadV3 { - payload_inner: v2, - blob_gas_used: 0, // V2 doesn't have blob gas - excess_blob_gas: 0, - }, - ExecutionPayload::V3(v3) => v3, - }; - - Ok(BlockData { - block_number, - payload: payload_v3, - requests: sidecar.requests_hash().unwrap_or_default(), - parent_beacon_block_root: block.header.parent_beacon_block_root.unwrap_or_default(), - versioned_hashes, - }) -} - -async fn verify(block_dir: &str) -> Result<()> { - let block_dir = PathBuf::from(block_dir); - - let index_path = block_dir.join("index.json"); - let block_index = BlockIndex::load_from_file(&index_path)?; - block_index.verify(&block_dir) -} From ba570821dee9a240fd0cee2882aca55dc3c52557 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Thu, 13 Nov 2025 21:20:04 -0500 Subject: [PATCH 69/81] test: fix stake and checkpoint binary test --- application/src/actor.rs | 14 ++++++++++- node/src/bin/stake_and_checkpoint.rs | 37 +++++++++++++++++----------- node/src/bin/withdraw_and_exit.rs | 2 +- node/src/keys.rs | 5 ---- 4 files changed, 36 insertions(+), 22 deletions(-) diff --git a/application/src/actor.rs b/application/src/actor.rs index 0c9a8806..9940216b 100644 --- a/application/src/actor.rs +++ b/application/src/actor.rs @@ -202,7 +202,19 @@ impl< let parent_request = if parent.1 == self.genesis_hash.into() { Either::Left(future::ready(Ok(Block::genesis(self.genesis_hash)))) } else { - Either::Right(syncer.subscribe(None, parent.1).await) + let parent_round = if parent.0 == 0 { + // Parent view is 0, which means that this is the first block of the epoch + // TODO(matthias): verify that the parent view of the first block is always 0 (nullify) + None + } else { + Some(Round::new(round.epoch(), parent.0)) + }; + Either::Right( + syncer + .subscribe(parent_round, parent.1) + .await, + ) + //Either::Right(syncer.subscribe(None, parent.1).await) }; let block_request = syncer.subscribe(Some(round), payload).await; diff --git a/node/src/bin/stake_and_checkpoint.rs b/node/src/bin/stake_and_checkpoint.rs index 71cf0212..d96e6130 100644 --- a/node/src/bin/stake_and_checkpoint.rs +++ b/node/src/bin/stake_and_checkpoint.rs @@ -273,13 +273,12 @@ fn main() -> Result<(), Box> { // Sign with node (ed25519) key let node_signature = ed25519_private_key.sign(None, &message); - let mut padded_node_signature = [0u8; 96]; - padded_node_signature[32..96].copy_from_slice(node_signature.as_ref()); + let node_signature_bytes: [u8; 64] = node_signature.as_ref().try_into().unwrap(); // Sign with consensus (BLS) key let consensus_signature = bls_private_key.sign(None, &message); - let mut padded_consensus_signature = [0u8; 96]; - padded_consensus_signature[..96].copy_from_slice(consensus_signature.as_ref()); + let consensus_signature_slice: &[u8] = consensus_signature.as_ref(); + let consensus_signature_bytes: [u8; 96] = consensus_signature_slice.try_into().unwrap(); // Convert VALIDATOR_MINIMUM_STAKE (in gwei) to wei let deposit_amount = U256::from(amount) * U256::from(1_000_000_000u64); // gwei to wei @@ -295,8 +294,8 @@ fn main() -> Result<(), Box> { &ed25519_pubkey_bytes, &bls_pubkey_bytes, &withdrawal_credentials, - &padded_node_signature, - &padded_consensus_signature, + &node_signature_bytes, + &consensus_signature_bytes, 0, // nonce ) .await @@ -491,10 +490,18 @@ fn main() -> Result<(), Box> { flags.bench_block_dir = args.bench_block_dir.clone(); } - let signer_path = format!("{}/node{}/data/node_key.pem", args.data_dir, x); - let encoded_priv_key = ed25519_private_key.to_string(); - fs::write(&signer_path, encoded_priv_key).expect("Unable to write private key to disk"); - flags.key_store_path = signer_path; + let node_key_path = format!("{}/node{}/data/node_key.pem", args.data_dir, x); + let consensus_key_path = format!("{}/node{}/data/consensus_key.pem", args.data_dir, x); + + // Write node key + let encoded_node_key = ed25519_private_key.to_string(); + fs::write(&node_key_path, encoded_node_key).expect("Unable to write node key to disk"); + + // Write consensus key + let encoded_consensus_key = bls_private_key.to_string(); + fs::write(&consensus_key_path, encoded_consensus_key).expect("Unable to write consensus key to disk"); + + flags.key_store_path = format!("{}/node{}/data", args.data_dir, x); flags.ip = Some("127.0.0.1:26640".to_string()); println!( @@ -516,7 +523,7 @@ fn main() -> Result<(), Box> { executor.start(|node_context| async move { let node_handle = node_context.clone().spawn(|ctx| async move { - run_node_with_runtime(ctx, flags, Some(checkpoint_state)).await.unwrap(); + run_node_local(ctx, flags, Some(checkpoint_state)).await.unwrap(); }); // Wait for stop signal or node completion @@ -644,7 +651,7 @@ async fn send_deposit_transaction

( node_pubkey: &[u8; 32], consensus_pubkey: &[u8; 48], withdrawal_credentials: &[u8; 32], - node_signature: &[u8; 96], + node_signature: &[u8; 64], consensus_signature: &[u8; 96], nonce: u64, ) -> Result<(), Box> @@ -722,7 +729,7 @@ where call_data.extend_from_slice(&length_bytes); call_data.extend_from_slice(withdrawal_credentials); - // Node signature (96 bytes ed25519 padded) + // Node signature (64 bytes ed25519) length_bytes.fill(0); length_bytes[28..32].copy_from_slice(&(node_signature.len() as u32).to_be_bytes()); call_data.extend_from_slice(&length_bytes); @@ -762,7 +769,7 @@ fn compute_deposit_data_root( consensus_pubkey: &[u8; 48], withdrawal_credentials: &[u8; 32], amount: U256, - node_signature: &[u8; 96], + node_signature: &[u8; 64], consensus_signature: &[u8; 96], ) -> [u8; 32] { /* @@ -851,7 +858,7 @@ fn get_node_flags(node: usize) -> RunFlags { let path = format!("testnet/node{node}/"); RunFlags { - key_store_path: format!("{path}keys"), + key_store_path: path.clone(), store_path: format!("{path}db"), port: (26600 + (node * 10)) as u16, prom_port: (28600 + (node * 10)) as u16, diff --git a/node/src/bin/withdraw_and_exit.rs b/node/src/bin/withdraw_and_exit.rs index d674675c..e0d031d0 100644 --- a/node/src/bin/withdraw_and_exit.rs +++ b/node/src/bin/withdraw_and_exit.rs @@ -29,7 +29,7 @@ use std::{ str::FromStr as _, thread::JoinHandle, }; -use summit::args::{RunFlags, run_node_with_runtime, run_node_local}; +use summit::args::{RunFlags, run_node_local}; use summit::engine::{BLOCKS_PER_EPOCH, VALIDATOR_MINIMUM_STAKE}; use summit_types::PublicKey; use summit_types::reth::Reth; diff --git a/node/src/keys.rs b/node/src/keys.rs index 7789a9f7..31787094 100644 --- a/node/src/keys.rs +++ b/node/src/keys.rs @@ -131,18 +131,13 @@ impl KeySubCmd { } pub fn read_bls_key_from_file(path: &std::path::Path) -> Result { - println!("Read BLS key: {}", path.display()); - if let Err(e) = std::fs::read_to_string(path) { println!("Failed to read BLS key: {}", e); } let encoded_pk = std::fs::read_to_string(path)?; - println!("Read BLS key 1"); let key = from_hex_formatted(&encoded_pk).context("Invalid BLS key format")?; - println!("Read BLS key 2"); let pk = BlsPrivateKey::decode(&*key)?; - println!("Read BLS key 3"); Ok(pk) } From 03acf43c3abaad8173ebb1266eca56ea8b3f81d5 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Fri, 14 Nov 2025 09:05:00 -0500 Subject: [PATCH 70/81] test: fix withdraw and exit binary --- node/src/bin/withdraw_and_exit.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/src/bin/withdraw_and_exit.rs b/node/src/bin/withdraw_and_exit.rs index e0d031d0..5c2f42d0 100644 --- a/node/src/bin/withdraw_and_exit.rs +++ b/node/src/bin/withdraw_and_exit.rs @@ -382,7 +382,7 @@ fn get_node_flags(node: usize) -> RunFlags { let path = format!("testnet/node{node}/"); RunFlags { - key_store_path: format!("{path}node_key.pem"), + key_store_path: path.clone(), store_path: format!("{path}db"), port: (26600 + (node * 10)) as u16, prom_port: (28600 + (node * 10)) as u16, From 50e56930196ffd064b4e1c92d0a06fc611097519 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Fri, 14 Nov 2025 10:23:36 -0500 Subject: [PATCH 71/81] chore: add latest view to the consensus state --- finalizer/src/actor.rs | 2 + node/src/args.rs | 16 ++++---- node/src/bin/testnet.rs | 3 +- types/src/block.rs | 4 ++ types/src/checkpoint.rs | 8 ++++ types/src/consensus_state.rs | 75 ++++++++++++++++++++++++++++++++++++ 6 files changed, 97 insertions(+), 11 deletions(-) diff --git a/finalizer/src/actor.rs b/finalizer/src/actor.rs index 73570fd6..3727a6b7 100644 --- a/finalizer/src/actor.rs +++ b/finalizer/src/actor.rs @@ -317,6 +317,8 @@ impl< self.context.register("height", "chain height", gauge); } self.state.set_latest_height(new_height); + self.state.set_view(block.view()); + assert_eq!(block.epoch(), self.state.epoch); // Periodically persist state to database as a blob // We build the checkpoint one height before the epoch end which diff --git a/node/src/args.rs b/node/src/args.rs index 7138ef44..15ddcb70 100644 --- a/node/src/args.rs +++ b/node/src/args.rs @@ -582,15 +582,13 @@ pub fn run_node_local( let key_store_path = flags.key_store_path.clone(); let rpc_port = flags.rpc_port; let stop_signal = context.stopped(); - let rpc_handle = context - .with_label("rpc") - .spawn(move |_context| async move { - if let Err(e) = - start_rpc_server(finalizer_mailbox, key_store_path, rpc_port, stop_signal).await - { - error!("RPC server failed: {}", e); - } - }); + let rpc_handle = context.with_label("rpc").spawn(move |_context| async move { + if let Err(e) = + start_rpc_server(finalizer_mailbox, key_store_path, rpc_port, stop_signal).await + { + error!("RPC server failed: {}", e); + } + }); // Wait for any task to error if let Err(e) = try_join_all(vec![p2p, engine, rpc_handle]).await { diff --git a/node/src/bin/testnet.rs b/node/src/bin/testnet.rs index 89317e82..7eeb0aed 100644 --- a/node/src/bin/testnet.rs +++ b/node/src/bin/testnet.rs @@ -165,8 +165,7 @@ fn main() -> Result<(), Box> { } // Start our consensus engine - let handle = - run_node_local(context.with_label(&format!("node{x}")), flags, None); + let handle = run_node_local(context.with_label(&format!("node{x}")), flags, None); consensus_handles.push(handle); } diff --git a/types/src/block.rs b/types/src/block.rs index 0822821c..ba271a5a 100644 --- a/types/src/block.rs +++ b/types/src/block.rs @@ -186,6 +186,10 @@ impl Block { pub fn view(&self) -> u64 { self.header.view } + + pub fn epoch(&self) -> u64 { + self.header.epoch + } } impl ConsensusBlock for Block { diff --git a/types/src/checkpoint.rs b/types/src/checkpoint.rs index 84873082..dc743c1f 100644 --- a/types/src/checkpoint.rs +++ b/types/src/checkpoint.rs @@ -147,6 +147,7 @@ mod tests { fn test_checkpoint_ssz_encode_decode_empty() { let state = ConsensusState { epoch: 0, + view: 0, latest_height: 10, next_withdrawal_index: 100, deposit_queue: VecDeque::new(), @@ -251,6 +252,7 @@ mod tests { let state = ConsensusState { epoch: 0, + view: 0, latest_height: 1000, next_withdrawal_index: 200, deposit_queue, @@ -285,6 +287,7 @@ mod tests { let state = ConsensusState { epoch: 0, + view: 0, latest_height: 42, next_withdrawal_index: 99, deposit_queue: VecDeque::new(), @@ -396,6 +399,7 @@ mod tests { let state = ConsensusState { epoch: 0, + view: 0, latest_height: 2000, next_withdrawal_index: 300, deposit_queue, @@ -435,6 +439,7 @@ mod tests { let state = ConsensusState { epoch: 0, + view: 0, latest_height: 42, next_withdrawal_index: 99, deposit_queue: VecDeque::new(), @@ -480,6 +485,7 @@ mod tests { let original_state = ConsensusState { epoch: 0, + view: 0, latest_height: 42, next_withdrawal_index: 99, deposit_queue: VecDeque::new(), @@ -521,6 +527,7 @@ mod tests { let original_state = ConsensusState { epoch: 0, + view: 0, latest_height: 42, next_withdrawal_index: 99, deposit_queue: VecDeque::new(), @@ -603,6 +610,7 @@ mod tests { let original_state = ConsensusState { epoch: 0, + view: 0, latest_height: 1000, next_withdrawal_index: 200, deposit_queue, diff --git a/types/src/consensus_state.rs b/types/src/consensus_state.rs index d0f24ada..f36d5109 100644 --- a/types/src/consensus_state.rs +++ b/types/src/consensus_state.rs @@ -13,6 +13,7 @@ use std::collections::{HashMap, VecDeque}; #[derive(Clone, Debug, Default)] pub struct ConsensusState { pub epoch: u64, + pub view: u64, pub latest_height: u64, pub next_withdrawal_index: u64, pub deposit_queue: VecDeque, @@ -35,6 +36,22 @@ impl ConsensusState { } // State variable operations + pub fn get_epoch(&self) -> u64 { + self.epoch + } + + pub fn set_epoch(&mut self, epoch: u64) { + self.epoch = epoch; + } + + pub fn get_view(&self) -> u64 { + self.view + } + + pub fn set_view(&mut self, view: u64) { + self.view = view; + } + pub fn get_latest_height(&self) -> u64 { self.latest_height } @@ -43,12 +60,60 @@ impl ConsensusState { self.latest_height = height; } + pub fn get_next_withdrawal_index(&self) -> u64 { + self.next_withdrawal_index + } + + pub fn set_next_withdrawal_index(&mut self, index: u64) { + self.next_withdrawal_index = index; + } + fn get_and_increment_withdrawal_index(&mut self) -> u64 { let current = self.next_withdrawal_index; self.next_withdrawal_index += 1; current } + pub fn get_pending_checkpoint(&self) -> Option<&Checkpoint> { + self.pending_checkpoint.as_ref() + } + + pub fn set_pending_checkpoint(&mut self, checkpoint: Option) { + self.pending_checkpoint = checkpoint; + } + + pub fn get_added_validators(&self) -> &Vec { + &self.added_validators + } + + pub fn set_added_validators(&mut self, validators: Vec) { + self.added_validators = validators; + } + + pub fn get_removed_validators(&self) -> &Vec { + &self.removed_validators + } + + pub fn set_removed_validators(&mut self, validators: Vec) { + self.removed_validators = validators; + } + + pub fn get_forkchoice(&self) -> &ForkchoiceState { + &self.forkchoice + } + + pub fn set_forkchoice(&mut self, forkchoice: ForkchoiceState) { + self.forkchoice = forkchoice; + } + + pub fn get_epoch_genesis_hash(&self) -> [u8; 32] { + self.epoch_genesis_hash + } + + pub fn set_epoch_genesis_hash(&mut self, hash: [u8; 32]) { + self.epoch_genesis_hash = hash; + } + // Account operations pub fn get_account(&self, pubkey: &[u8; 32]) -> Option<&ValidatorAccount> { self.validator_accounts.get(pubkey) @@ -167,6 +232,7 @@ impl ConsensusState { impl EncodeSize for ConsensusState { fn encode_size(&self) -> usize { 8 // epoch + + 8 // view + 8 // latest_height + 8 // next_withdrawal_index + 4 // deposit_queue length @@ -193,6 +259,7 @@ impl Read for ConsensusState { fn read_cfg(buf: &mut impl Buf, _cfg: &Self::Cfg) -> Result { let epoch = buf.get_u64(); + let view = buf.get_u64(); let latest_height = buf.get_u64(); let next_withdrawal_index = buf.get_u64(); @@ -258,6 +325,7 @@ impl Read for ConsensusState { Ok(Self { epoch, + view, latest_height, next_withdrawal_index, deposit_queue, @@ -275,6 +343,7 @@ impl Read for ConsensusState { impl Write for ConsensusState { fn write(&self, buf: &mut impl BufMut) { buf.put_u64(self.epoch); + buf.put_u64(self.view); buf.put_u64(self.latest_height); buf.put_u64(self.next_withdrawal_index); @@ -401,6 +470,7 @@ mod tests { let decoded_state = ConsensusState::decode(&mut encoded).expect("Failed to decode"); assert_eq!(decoded_state.epoch, original_state.epoch); + assert_eq!(decoded_state.view, original_state.view); assert_eq!(decoded_state.latest_height, original_state.latest_height); assert_eq!( decoded_state.next_withdrawal_index, @@ -429,6 +499,7 @@ mod tests { let mut original_state = ConsensusState::default(); original_state.epoch = 7; + original_state.view = 123; original_state.set_latest_height(42); original_state.next_withdrawal_index = 5; original_state.epoch_genesis_hash = [42u8; 32]; @@ -454,6 +525,7 @@ mod tests { let decoded_state = ConsensusState::decode(&mut encoded).expect("Failed to decode"); assert_eq!(decoded_state.epoch, original_state.epoch); + assert_eq!(decoded_state.view, original_state.view); assert_eq!(decoded_state.latest_height, original_state.latest_height); assert_eq!( decoded_state.next_withdrawal_index, @@ -490,6 +562,7 @@ mod tests { let mut state = ConsensusState::default(); state.epoch = 3; + state.view = 456; state.set_latest_height(42); state.next_withdrawal_index = 5; @@ -543,6 +616,7 @@ mod tests { // Create a populated ConsensusState let mut original_state = ConsensusState::default(); original_state.epoch = 5; + original_state.view = 789; original_state.set_latest_height(100); original_state.next_withdrawal_index = 42; original_state.epoch_genesis_hash = [99u8; 32]; @@ -568,6 +642,7 @@ mod tests { // Verify the data matches assert_eq!(restored_state.epoch, original_state.epoch); + assert_eq!(restored_state.view, original_state.view); assert_eq!(restored_state.latest_height, original_state.latest_height); assert_eq!( restored_state.next_withdrawal_index, From 7d942d69b4e5212e95f167977274c381c934feda Mon Sep 17 00:00:00 2001 From: cdrappi Date: Fri, 14 Nov 2025 10:57:52 -0500 Subject: [PATCH 72/81] fmt --- node/src/args.rs | 12 +++++++++--- rpc/src/routes.rs | 4 +++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/node/src/args.rs b/node/src/args.rs index abb63991..9ecfe4ff 100644 --- a/node/src/args.rs +++ b/node/src/args.rs @@ -182,8 +182,13 @@ impl Command { .with_label("rpc_genesis") .spawn(move |_context| async move { let genesis_sender = Command::check_sender(genesis_path, genesis_tx); - if let Err(e) = - start_rpc_server_for_genesis(genesis_sender, key_path, rpc_port, cloned_token).await + if let Err(e) = start_rpc_server_for_genesis( + genesis_sender, + key_path, + rpc_port, + cloned_token, + ) + .await { error!("RPC server failed: {}", e); } @@ -406,7 +411,8 @@ pub fn run_node_with_runtime( .spawn(move |_context| async move { let genesis_sender = Command::check_sender(genesis_path, genesis_tx); if let Err(e) = - start_rpc_server_for_genesis(genesis_sender, key_path, rpc_port, cloned_token).await + start_rpc_server_for_genesis(genesis_sender, key_path, rpc_port, cloned_token) + .await { error!("RPC server failed: {}", e); } diff --git a/rpc/src/routes.rs b/rpc/src/routes.rs index 9e12ec72..4699de5c 100644 --- a/rpc/src/routes.rs +++ b/rpc/src/routes.rs @@ -49,7 +49,9 @@ impl RpcRoutes { Ok(private_key.public_key().to_string()) } - async fn handle_get_pub_key_genesis(State(state): State>) -> Result { + async fn handle_get_pub_key_genesis( + State(state): State>, + ) -> Result { let private_key = Self::read_ed_key_from_path(&state.key_path)?; Ok(private_key.public_key().to_string()) From 42fc0ee13f66fa032a171b2eb35cc88a52fa8a27 Mon Sep 17 00:00:00 2001 From: daltoncoder Date: Fri, 14 Nov 2025 12:36:56 -0500 Subject: [PATCH 73/81] Only check if building on proper eth block in finalizer --- application/src/actor.rs | 3 --- finalizer/src/actor.rs | 8 ++++++++ node/src/test_harness/mock_engine_client.rs | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/application/src/actor.rs b/application/src/actor.rs index 9940216b..b6bf032e 100644 --- a/application/src/actor.rs +++ b/application/src/actor.rs @@ -442,9 +442,6 @@ impl< } fn handle_verify(block: &Block, parent: Block) -> bool { - if block.eth_parent_hash() != parent.eth_block_hash() { - return false; - } if block.parent() != parent.digest() { return false; } diff --git a/finalizer/src/actor.rs b/finalizer/src/actor.rs index 3727a6b7..1ae8a7d0 100644 --- a/finalizer/src/actor.rs +++ b/finalizer/src/actor.rs @@ -257,6 +257,10 @@ impl< if payload_status.is_valid() && block.payload.payload_inner.withdrawals == expected_withdrawals + && self.state.forkchoice.head_block_hash + == payload_status + .latest_valid_hash + .expect("All valid payloads have this") { let eth_hash = block.eth_block_hash(); info!( @@ -308,6 +312,10 @@ impl< histogram!("process_execution_requests_duration_millis") .record(process_requests_duration); } + } else { + warn!( + "Height: {new_height} contains invalid eth payload. Not executing but keeping part of chain" + ); } #[cfg(debug_assertions)] diff --git a/node/src/test_harness/mock_engine_client.rs b/node/src/test_harness/mock_engine_client.rs index eb389bb7..00da37e0 100644 --- a/node/src/test_harness/mock_engine_client.rs +++ b/node/src/test_harness/mock_engine_client.rs @@ -410,7 +410,7 @@ impl EngineClient for MockEngineClient { } // Block is valid - store both status and block data - let status = PayloadStatus::new(PayloadStatusEnum::Valid, Some(block_hash)); + let status = PayloadStatus::new(PayloadStatusEnum::Valid, Some(parent_hash)); state.known_blocks.insert(block_hash, status.clone()); state .validated_blocks From 1ee5da7a1496e2414ce3949b33efd67fc479f04e Mon Sep 17 00:00:00 2001 From: daltoncoder Date: Fri, 14 Nov 2025 15:07:42 -0500 Subject: [PATCH 74/81] fix finalizer --- finalizer/src/actor.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/finalizer/src/actor.rs b/finalizer/src/actor.rs index 1ae8a7d0..251ae27c 100644 --- a/finalizer/src/actor.rs +++ b/finalizer/src/actor.rs @@ -257,10 +257,7 @@ impl< if payload_status.is_valid() && block.payload.payload_inner.withdrawals == expected_withdrawals - && self.state.forkchoice.head_block_hash - == payload_status - .latest_valid_hash - .expect("All valid payloads have this") + && self.state.forkchoice.head_block_hash == block.eth_parent_hash() { let eth_hash = block.eth_block_hash(); info!( From d564702582a998d91c4d52a2f2016eb33d0dd139 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Fri, 14 Nov 2025 13:39:57 -0500 Subject: [PATCH 75/81] feat: set last_processed_height and last_processed_round according to consensus state in syncer --- application/src/actor.rs | 8 +- finalizer/src/actor.rs | 12 +- node/src/engine.rs | 8 + orchestrator/src/actor.rs | 1 + summit.log | 6766 +++++++++++++++++++++++++++++++++++++ syncer/src/actor.rs | 42 +- 6 files changed, 6820 insertions(+), 17 deletions(-) create mode 100644 summit.log diff --git a/application/src/actor.rs b/application/src/actor.rs index b6bf032e..8f923cf6 100644 --- a/application/src/actor.rs +++ b/application/src/actor.rs @@ -26,7 +26,7 @@ use std::{ time::Duration, }; use summit_finalizer::FinalizerMailbox; -use tracing::{error, info, warn}; +use tracing::{debug, error, info, warn}; #[cfg(feature = "prom")] use metrics::histogram; @@ -146,7 +146,8 @@ impl< parent, mut response, } => { - info!("{rand_id} Handling message Propose round: {}", round); + debug!("{rand_id} application: Handling message Propose for round {} (epoch {}, view {}), parent height: {}", + round, round.epoch(), round.view(), parent.0); let built = self.built_block.clone(); select! { @@ -196,7 +197,8 @@ impl< payload, mut response, } => { - info!("{rand_id} Handling message Verify round: {}", round); + debug!("{rand_id} application: Handling message Verify for round {} (epoch {}, view {}), parent height: {}", + round, round.epoch(), round.view(), parent.0); // Subscribe to blocks (will wait for them if not available) let parent_request = if parent.1 == self.genesis_hash.into() { diff --git a/finalizer/src/actor.rs b/finalizer/src/actor.rs index 251ae27c..918fbc09 100644 --- a/finalizer/src/actor.rs +++ b/finalizer/src/actor.rs @@ -103,8 +103,16 @@ impl< // The initial state could be from the genesis or a checkpoint. // If we want to load a checkpoint, we have to make sure that the DB is cleared. let state = if let Some(state) = db.get_latest_consensus_state().await { + info!( + "Loading consensus state from database at epoch {} and height {}", + state.epoch, state.latest_height + ); state } else { + info!( + "Consensus state not found in database, using provided state with epoch {} and height {} - epoch_num_of_blocks: {}", + cfg.initial_state.epoch, cfg.initial_state.latest_height, cfg.epoch_num_of_blocks + ); cfg.initial_state }; @@ -329,7 +337,7 @@ impl< // We build the checkpoint one height before the epoch end which // allows the validators to sign the checkpoint hash in the last block // of the epoch - if is_penultimate_block_of_epoch(new_height, self.epoch_num_of_blocks) { + if is_penultimate_block_of_epoch(self.epoch_num_of_blocks, new_height) { #[cfg(feature = "prom")] let checkpoint_creation_start = Instant::now(); @@ -631,7 +639,7 @@ impl< } async fn process_execution_requests(&mut self, block: &Block, new_height: u64) { - if is_penultimate_block_of_epoch(new_height, self.epoch_num_of_blocks) { + if is_penultimate_block_of_epoch(self.epoch_num_of_blocks, new_height) { for _ in 0..self.validator_onboarding_limit_per_block { if let Some(request) = self.state.pop_deposit() { let mut validator_balance = 0; diff --git a/node/src/engine.rs b/node/src/engine.rs index 826d20b3..aa92c60c 100644 --- a/node/src/engine.rs +++ b/node/src/engine.rs @@ -91,6 +91,8 @@ pub struct Engine< node_public_key: PublicKey, mailbox_size: usize, sync_height: u64, + sync_epoch: u64, + sync_view: u64, cancellation_token: CancellationToken, } @@ -113,6 +115,8 @@ where SummitSchemeProvider::new(private_scalar); let sync_height = cfg.initial_state.latest_height; + let sync_epoch = cfg.initial_state.epoch; + let sync_view = cfg.initial_state.view; let cancellation_token = CancellationToken::new(); @@ -230,6 +234,8 @@ where node_public_key: cfg.key_store.node_key.public_key(), mailbox_size: cfg.mailbox_size, sync_height, + sync_epoch, + sync_view, cancellation_token, } } @@ -338,6 +344,8 @@ where self.buffer_mailbox.clone(), (resolver_rx, resolver), self.sync_height, + self.sync_epoch, + self.sync_view, ); // start the orchestrator let orchestrator_handle = self.orchestrator.start( diff --git a/orchestrator/src/actor.rs b/orchestrator/src/actor.rs index cd511fa4..38f4ce92 100644 --- a/orchestrator/src/actor.rs +++ b/orchestrator/src/actor.rs @@ -397,6 +397,7 @@ where let recovered_sc = recovered_mux.register(epoch).await.unwrap(); let resolver_sc = resolver_mux.register(epoch).await.unwrap(); + info!("orchestrator: starting Simplex engine for epoch {}", epoch); engine.start(pending_sc, recovered_sc, resolver_sc) } } diff --git a/summit.log b/summit.log new file mode 100644 index 00000000..1df6fcc6 --- /dev/null +++ b/summit.log @@ -0,0 +1,6766 @@ +******* STARTING RETH FOR NODE 0 +Node 0 rpc address: 8545 +******* STARTING RETH FOR NODE 1 +Keystore directory: testnet/node0/ +Genesis RPC Server listening on http://0.0.0.0:3030 +Genesis RPC server stopped +2025-11-14T18:24:25.739183Z  INFO ThreadId(36) commonware_p2p::authenticated::discovery::network: /home/matthias/.cargo/git/checkouts/monorepo-9732103c47eb4665/f395c9e/p2p/src/authenticated/discovery/network.rs:189: network started +2025-11-14T18:24:25.741312Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:220: restored finalizations by height archive elapsed=1.880468ms +2025-11-14T18:24:25.741636Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:254: restored finalized blocks archive elapsed=309.286µs +################################################ +################################################ +2025-11-14T18:24:25.743702Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:116: Consensus state not found in database, using provided state with epoch 0 and height 0 - epoch_num_of_blocks: 50 +RPC Server listening on http://0.0.0.0:3030 +2025-11-14T18:24:25.743872Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:389: syncer: starting from checkpoint at height 0, epoch 0, view 0 +2025-11-14T18:24:25.743884Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 1 not found (last_processed=0, tip=0) +2025-11-14T18:24:25.743890Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [], last_processed_height: 0, tip: 0 +2025-11-14T18:24:25.743892Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:25.743895Z  INFO ThreadId(38) summit_orchestrator::actor: orchestrator/src/actor.rs:307: orchestrator: received Enter message for epoch 0 with 4 validators +2025-11-14T18:24:25.744234Z  INFO ThreadId(38) summit_orchestrator::actor: orchestrator/src/actor.rs:406: orchestrator: starting Simplex engine for epoch 0 +2025-11-14T18:24:25.744255Z  INFO ThreadId(38) summit_orchestrator::actor: orchestrator/src/actor.rs:335: entered epoch epoch=0 +2025-11-14T18:24:25.744372Z  INFO ThreadId(37) commonware_consensus::simplex::actors::voter::actor: /home/matthias/.cargo/git/checkouts/monorepo-9732103c47eb4665/f395c9e/consensus/src/simplex/actors/voter/actor.rs:1688: consensus initialized current_view=1 elapsed=4.929µs +Node 1 rpc address: 8544 +******* STARTING RETH FOR NODE 2 +Keystore directory: testnet/node1/ +Genesis RPC Server listening on http://0.0.0.0:3040 +Genesis RPC server stopped +2025-11-14T18:24:25.845658Z  INFO ThreadId(43) commonware_p2p::authenticated::discovery::network: /home/matthias/.cargo/git/checkouts/monorepo-9732103c47eb4665/f395c9e/p2p/src/authenticated/discovery/network.rs:189: network started +2025-11-14T18:24:25.846306Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:220: restored finalizations by height archive elapsed=441.627µs +2025-11-14T18:24:25.869634Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:254: restored finalized blocks archive elapsed=23.306909ms +################################################ +################################################ +2025-11-14T18:24:25.870228Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:116: Consensus state not found in database, using provided state with epoch 0 and height 0 - epoch_num_of_blocks: 50 +RPC Server listening on http://0.0.0.0:3040 +2025-11-14T18:24:25.870370Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:389: syncer: starting from checkpoint at height 0, epoch 0, view 0 +2025-11-14T18:24:25.870376Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 1 not found (last_processed=0, tip=0) +2025-11-14T18:24:25.870379Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [], last_processed_height: 0, tip: 0 +2025-11-14T18:24:25.870381Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:25.870389Z  INFO ThreadId(43) summit_orchestrator::actor: orchestrator/src/actor.rs:307: orchestrator: received Enter message for epoch 0 with 4 validators +2025-11-14T18:24:25.870703Z  INFO ThreadId(43) summit_orchestrator::actor: orchestrator/src/actor.rs:406: orchestrator: starting Simplex engine for epoch 0 +2025-11-14T18:24:25.870717Z  INFO ThreadId(43) summit_orchestrator::actor: orchestrator/src/actor.rs:335: entered epoch epoch=0 +2025-11-14T18:24:25.870796Z  INFO ThreadId(46) commonware_consensus::simplex::actors::voter::actor: /home/matthias/.cargo/git/checkouts/monorepo-9732103c47eb4665/f395c9e/consensus/src/simplex/actors/voter/actor.rs:1688: consensus initialized current_view=1 elapsed=1.373µs +2025-11-14T18:24:25.870826Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:149: 15 application: Handling message Propose for round Round(0, 1) (epoch 0, view 1), parent height: 0 +2025-11-14T18:24:25.923146Z  WARN ThreadId(43) commonware_consensus::simplex::actors::voter::actor: /home/matthias/.cargo/git/checkouts/monorepo-9732103c47eb4665/f395c9e/consensus/src/simplex/actors/voter/actor.rs:1800: failed to record our container round=Round(0, 1) +Node 2 rpc address: 8543 +******* STARTING RETH FOR NODE 3 +Keystore directory: testnet/node2/ +Genesis RPC Server listening on http://0.0.0.0:3050 +Genesis RPC server stopped +2025-11-14T18:24:26.080829Z  INFO ThreadId(49) commonware_p2p::authenticated::discovery::network: /home/matthias/.cargo/git/checkouts/monorepo-9732103c47eb4665/f395c9e/p2p/src/authenticated/discovery/network.rs:189: network started +2025-11-14T18:24:26.082697Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:220: restored finalizations by height archive elapsed=1.691322ms +2025-11-14T18:24:26.083159Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:254: restored finalized blocks archive elapsed=445.024µs +################################################ +################################################ +2025-11-14T18:24:26.083966Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:116: Consensus state not found in database, using provided state with epoch 0 and height 0 - epoch_num_of_blocks: 50 +RPC Server listening on http://0.0.0.0:3050 +2025-11-14T18:24:26.085025Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:389: syncer: starting from checkpoint at height 0, epoch 0, view 0 +2025-11-14T18:24:26.085079Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 1 not found (last_processed=0, tip=0) +2025-11-14T18:24:26.085103Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [], last_processed_height: 0, tip: 0 +2025-11-14T18:24:26.085124Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:26.085213Z  INFO ThreadId(50) summit_orchestrator::actor: orchestrator/src/actor.rs:307: orchestrator: received Enter message for epoch 0 with 4 validators +2025-11-14T18:24:26.085616Z  INFO ThreadId(50) summit_orchestrator::actor: orchestrator/src/actor.rs:406: orchestrator: starting Simplex engine for epoch 0 +2025-11-14T18:24:26.085646Z  INFO ThreadId(50) summit_orchestrator::actor: orchestrator/src/actor.rs:335: entered epoch epoch=0 +2025-11-14T18:24:26.085756Z  INFO ThreadId(49) commonware_consensus::simplex::actors::voter::actor: /home/matthias/.cargo/git/checkouts/monorepo-9732103c47eb4665/f395c9e/consensus/src/simplex/actors/voter/actor.rs:1688: consensus initialized current_view=1 elapsed=1.602µs +Node 3 rpc address: 8542 +Keystore directory: testnet/node3/ +Genesis RPC Server listening on http://0.0.0.0:3060 +Genesis RPC server stopped +2025-11-14T18:24:26.355835Z  INFO ThreadId(55) commonware_p2p::authenticated::discovery::network: /home/matthias/.cargo/git/checkouts/monorepo-9732103c47eb4665/f395c9e/p2p/src/authenticated/discovery/network.rs:189: network started +2025-11-14T18:24:26.356319Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:220: restored finalizations by height archive elapsed=288.808µs +2025-11-14T18:24:26.356733Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:254: restored finalized blocks archive elapsed=405.592µs +################################################ +################################################ +2025-11-14T18:24:26.357069Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:116: Consensus state not found in database, using provided state with epoch 0 and height 0 - epoch_num_of_blocks: 50 +RPC Server listening on http://0.0.0.0:3060 +2025-11-14T18:24:26.357305Z  INFO ThreadId(58) summit_orchestrator::actor: orchestrator/src/actor.rs:307: orchestrator: received Enter message for epoch 0 with 4 validators +2025-11-14T18:24:26.357428Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:389: syncer: starting from checkpoint at height 0, epoch 0, view 0 +2025-11-14T18:24:26.357436Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 1 not found (last_processed=0, tip=0) +2025-11-14T18:24:26.357440Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [], last_processed_height: 0, tip: 0 +2025-11-14T18:24:26.357443Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:26.357668Z  INFO ThreadId(58) summit_orchestrator::actor: orchestrator/src/actor.rs:406: orchestrator: starting Simplex engine for epoch 0 +2025-11-14T18:24:26.357683Z  INFO ThreadId(58) summit_orchestrator::actor: orchestrator/src/actor.rs:335: entered epoch epoch=0 +2025-11-14T18:24:26.357769Z  INFO ThreadId(55) commonware_consensus::simplex::actors::voter::actor: /home/matthias/.cargo/git/checkouts/monorepo-9732103c47eb4665/f395c9e/consensus/src/simplex/actors/voter/actor.rs:1688: consensus initialized current_view=1 elapsed=1.683µs +2025-11-14T18:24:29.876338Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:149: 139 application: Handling message Propose for round Round(0, 2) (epoch 0, view 2), parent height: 0 +2025-11-14T18:24:29.928590Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:177: 139 Handling message Broadcast +2025-11-14T18:24:29.931142Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 2) (epoch 0, view 2), parent height: 0 +2025-11-14T18:24:29.931295Z  INFO ThreadId(44) summit_syncer::cache: syncer/src/cache.rs:227: restored verified archive elapsed=98.46µs +2025-11-14T18:24:29.931384Z  INFO ThreadId(44) summit_syncer::cache: syncer/src/cache.rs:227: restored notarized archive elapsed=75.468µs +2025-11-14T18:24:29.931443Z  INFO ThreadId(44) summit_syncer::cache: syncer/src/cache.rs:227: restored notarizations archive elapsed=51.875µs +2025-11-14T18:24:29.931488Z  INFO ThreadId(45) summit_syncer::cache: syncer/src/cache.rs:227: restored finalizations archive elapsed=39.121µs +2025-11-14T18:24:29.931863Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 2) (epoch 0, view 2), parent height: 0 +2025-11-14T18:24:29.931941Z  INFO ThreadId(37) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 2) (epoch 0, view 2), parent height: 0 +2025-11-14T18:24:29.932001Z  INFO ThreadId(55) summit_syncer::cache: syncer/src/cache.rs:227: restored verified archive elapsed=73.915µs +2025-11-14T18:24:29.932086Z  INFO ThreadId(37) summit_syncer::cache: syncer/src/cache.rs:227: restored verified archive elapsed=57.725µs +2025-11-14T18:24:29.932090Z  INFO ThreadId(55) summit_syncer::cache: syncer/src/cache.rs:227: restored notarized archive elapsed=78.724µs +2025-11-14T18:24:29.932132Z  INFO ThreadId(55) summit_syncer::cache: syncer/src/cache.rs:227: restored notarizations archive elapsed=33.732µs +2025-11-14T18:24:29.932165Z  INFO ThreadId(55) summit_syncer::cache: syncer/src/cache.rs:227: restored finalizations archive elapsed=30.366µs +2025-11-14T18:24:29.932213Z  INFO ThreadId(37) summit_syncer::cache: syncer/src/cache.rs:227: restored notarized archive elapsed=116.814µs +2025-11-14T18:24:29.932276Z  INFO ThreadId(37) summit_syncer::cache: syncer/src/cache.rs:227: restored notarizations archive elapsed=54.84µs +2025-11-14T18:24:29.932331Z  INFO ThreadId(37) summit_syncer::cache: syncer/src/cache.rs:227: restored finalizations archive elapsed=50.592µs +2025-11-14T18:24:29.935252Z  INFO ThreadId(51) summit_syncer::cache: syncer/src/cache.rs:227: restored verified archive elapsed=68.555µs +2025-11-14T18:24:29.935382Z  INFO ThreadId(51) summit_syncer::cache: syncer/src/cache.rs:227: restored notarized archive elapsed=112.716µs +2025-11-14T18:24:29.935446Z  INFO ThreadId(51) summit_syncer::cache: syncer/src/cache.rs:227: restored notarizations archive elapsed=52.937µs +2025-11-14T18:24:29.935509Z  INFO ThreadId(51) summit_syncer::cache: syncer/src/cache.rs:227: restored finalizations archive elapsed=55.632µs +2025-11-14T18:24:29.935741Z  INFO ThreadId(57) summit_application::actor: application/src/actor.rs:149: 55 application: Handling message Propose for round Round(0, 3) (epoch 0, view 3), parent height: 2 +2025-11-14T18:24:29.936720Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 2) (last_processed_height=0, tip=0) +2025-11-14T18:24:29.937517Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 1 (previous tip: 0) +2025-11-14T18:24:29.937521Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 1 (last_processed_height: 0, tip: 1) +2025-11-14T18:24:29.937571Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 1)], last_processed_height: 0, tip: 1 +2025-11-14T18:24:29.937575Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:29.937589Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 2) (last_processed_height=0, tip=0) +2025-11-14T18:24:29.938211Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 2) (last_processed_height=0, tip=0) +2025-11-14T18:24:29.938219Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 2) (last_processed_height=0, tip=0) +2025-11-14T18:24:29.938710Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 1 (previous tip: 0) +2025-11-14T18:24:29.938716Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 1 (last_processed_height: 0, tip: 1) +2025-11-14T18:24:29.938779Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 1)], last_processed_height: 0, tip: 1 +2025-11-14T18:24:29.938784Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:29.939480Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 1 (previous tip: 0) +2025-11-14T18:24:29.939487Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 1 (last_processed_height: 0, tip: 1) +2025-11-14T18:24:29.939490Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 1 (previous tip: 0) +2025-11-14T18:24:29.939502Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 1 (last_processed_height: 0, tip: 1) +2025-11-14T18:24:29.939529Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 1)], last_processed_height: 0, tip: 1 +2025-11-14T18:24:29.939532Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:29.939543Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 1)], last_processed_height: 0, tip: 1 +2025-11-14T18:24:29.939545Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:29.940273Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd10b9460f8d7b4eb3f7dd06702b64d5db7d98560f7aaa8eee52205278da72b83 for height 1 +2025-11-14T18:24:29.940952Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd10b9460f8d7b4eb3f7dd06702b64d5db7d98560f7aaa8eee52205278da72b83 for height 1 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 1 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 1, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 1, is last block: false +2025-11-14T18:24:29.941139Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=1 +2025-11-14T18:24:29.941326Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 2 not found (last_processed=1, tip=1) +2025-11-14T18:24:29.942043Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd10b9460f8d7b4eb3f7dd06702b64d5db7d98560f7aaa8eee52205278da72b83 for height 1 +2025-11-14T18:24:29.942098Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd10b9460f8d7b4eb3f7dd06702b64d5db7d98560f7aaa8eee52205278da72b83 for height 1 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 1 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 1, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 1, is last block: false +2025-11-14T18:24:29.942260Z  INFO ThreadId(36) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=1 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 1 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 1, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +üüüüüüüüüüüüüüüüüüüüüüüüü +epoch_num_of_blocks: 50, new_height: 1, is last block: false +COMMITING BLOCK 1 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 1, is penultimate block: false +2025-11-14T18:24:29.942289Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=1 +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 1, is last block: false +2025-11-14T18:24:29.942301Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=1 +2025-11-14T18:24:29.942442Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 2 not found (last_processed=1, tip=1) +2025-11-14T18:24:29.942460Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 2 not found (last_processed=1, tip=1) +2025-11-14T18:24:29.942464Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 2 not found (last_processed=1, tip=1) +2025-11-14T18:24:29.994423Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:177: 55 Handling message Broadcast +2025-11-14T18:24:29.996816Z  INFO ThreadId(36) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 3) (epoch 0, view 3), parent height: 2 +2025-11-14T18:24:29.996885Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 3) (epoch 0, view 3), parent height: 2 +2025-11-14T18:24:29.997580Z  INFO ThreadId(49) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 3) (epoch 0, view 3), parent height: 2 +2025-11-14T18:24:30.000407Z  INFO ThreadId(36) summit_application::actor: application/src/actor.rs:149: 209 application: Handling message Propose for round Round(0, 4) (epoch 0, view 4), parent height: 3 +2025-11-14T18:24:30.002129Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 3) (last_processed_height=1, tip=1) +2025-11-14T18:24:30.002237Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 3) (last_processed_height=1, tip=1) +2025-11-14T18:24:30.002504Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 2 (previous tip: 1) +2025-11-14T18:24:30.002510Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 2 (last_processed_height: 1, tip: 2) +2025-11-14T18:24:30.002544Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 2)], last_processed_height: 1, tip: 2 +2025-11-14T18:24:30.002547Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:30.002635Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 2 (previous tip: 1) +2025-11-14T18:24:30.002638Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 3) (last_processed_height=1, tip=1) +2025-11-14T18:24:30.002640Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 2 (last_processed_height: 1, tip: 2) +2025-11-14T18:24:30.002675Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 2)], last_processed_height: 1, tip: 2 +2025-11-14T18:24:30.002678Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:30.002996Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 2 (previous tip: 1) +2025-11-14T18:24:30.003001Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 2 (last_processed_height: 1, tip: 2) +2025-11-14T18:24:30.003041Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 2)], last_processed_height: 1, tip: 2 +2025-11-14T18:24:30.003045Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:30.003299Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 3) (last_processed_height=1, tip=1) +2025-11-14T18:24:30.003878Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 2 (previous tip: 1) +2025-11-14T18:24:30.003887Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 2 (last_processed_height: 1, tip: 2) +2025-11-14T18:24:30.004031Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 2)], last_processed_height: 1, tip: 2 +2025-11-14T18:24:30.004080Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:30.004102Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x559c97eb1c7e097f9eceef1b6014ac1573ad38d43b31dd30c1cb9ceed112ded6 for height 2 +2025-11-14T18:24:30.004134Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x559c97eb1c7e097f9eceef1b6014ac1573ad38d43b31dd30c1cb9ceed112ded6 for height 2 +üüüüüüüüüüüüüüüüüüüüüüüüü +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 2 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 2, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 2, is last block: false +COMMITING BLOCK 2 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 2, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +2025-11-14T18:24:30.004392Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=2 +epoch_num_of_blocks: 50, new_height: 2, is last block: false +2025-11-14T18:24:30.004400Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=2 +2025-11-14T18:24:30.004596Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 3 not found (last_processed=2, tip=2) +2025-11-14T18:24:30.004607Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 3 not found (last_processed=2, tip=2) +2025-11-14T18:24:30.004768Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x559c97eb1c7e097f9eceef1b6014ac1573ad38d43b31dd30c1cb9ceed112ded6 for height 2 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 2 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 2, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 2, is last block: false +2025-11-14T18:24:30.004924Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=2 +2025-11-14T18:24:30.005105Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 3 not found (last_processed=2, tip=2) +2025-11-14T18:24:30.005274Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x559c97eb1c7e097f9eceef1b6014ac1573ad38d43b31dd30c1cb9ceed112ded6 for height 2 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 2 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 2, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 2, is last block: false +2025-11-14T18:24:30.005405Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=2 +2025-11-14T18:24:30.005541Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 3 not found (last_processed=2, tip=2) +2025-11-14T18:24:30.055742Z  INFO ThreadId(37) summit_application::actor: application/src/actor.rs:177: 209 Handling message Broadcast +2025-11-14T18:24:30.058299Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 4) (epoch 0, view 4), parent height: 3 +2025-11-14T18:24:30.058506Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 4) (epoch 0, view 4), parent height: 3 +2025-11-14T18:24:30.058555Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 4) (epoch 0, view 4), parent height: 3 +2025-11-14T18:24:30.060916Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:149: 15 application: Handling message Propose for round Round(0, 5) (epoch 0, view 5), parent height: 4 +2025-11-14T18:24:30.062779Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 4) (last_processed_height=2, tip=2) +2025-11-14T18:24:30.063284Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 4) (last_processed_height=2, tip=2) +2025-11-14T18:24:30.063537Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 4) (last_processed_height=2, tip=2) +2025-11-14T18:24:30.063819Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 3 (previous tip: 2) +2025-11-14T18:24:30.063829Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 3 (last_processed_height: 2, tip: 3) +2025-11-14T18:24:30.063906Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 3)], last_processed_height: 2, tip: 3 +2025-11-14T18:24:30.063915Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:30.064264Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 3 (previous tip: 2) +2025-11-14T18:24:30.064271Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 3 (last_processed_height: 2, tip: 3) +2025-11-14T18:24:30.064303Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 4) (last_processed_height=2, tip=2) +2025-11-14T18:24:30.064314Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 3)], last_processed_height: 2, tip: 3 +2025-11-14T18:24:30.064317Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:30.064535Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 3 (previous tip: 2) +2025-11-14T18:24:30.064552Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 3 (last_processed_height: 2, tip: 3) +2025-11-14T18:24:30.064617Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 3)], last_processed_height: 2, tip: 3 +2025-11-14T18:24:30.064626Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:30.064971Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 3 (previous tip: 2) +2025-11-14T18:24:30.064980Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 3 (last_processed_height: 2, tip: 3) +2025-11-14T18:24:30.065023Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 3)], last_processed_height: 2, tip: 3 +2025-11-14T18:24:30.065026Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:30.065646Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x4b7cd6c681fbe0421f36b4c1818895ffec90e04b637d40672a2bf95812b2578d for height 3 +2025-11-14T18:24:30.065889Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x4b7cd6c681fbe0421f36b4c1818895ffec90e04b637d40672a2bf95812b2578d for height 3 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 3 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 3, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 3, is last block: false +2025-11-14T18:24:30.065969Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=3 +2025-11-14T18:24:30.066007Z  INFO ThreadId(37) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x4b7cd6c681fbe0421f36b4c1818895ffec90e04b637d40672a2bf95812b2578d for height 3 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 3 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 3, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 3, is last block: false +2025-11-14T18:24:30.066109Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=3 +2025-11-14T18:24:30.066140Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 4 not found (last_processed=3, tip=3) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 3 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +2025-11-14T18:24:30.066288Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 4 not found (last_processed=3, tip=3) +epoch_num_of_blocks: 50, new_height: 3, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 3, is last block: false +2025-11-14T18:24:30.066297Z  INFO ThreadId(36) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=3 +2025-11-14T18:24:30.066400Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x4b7cd6c681fbe0421f36b4c1818895ffec90e04b637d40672a2bf95812b2578d for height 3 +2025-11-14T18:24:30.066458Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 4 not found (last_processed=3, tip=3) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 3 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 3, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 3, is last block: false +2025-11-14T18:24:30.066542Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=3 +2025-11-14T18:24:30.066679Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 4 not found (last_processed=3, tip=3) +2025-11-14T18:24:30.118092Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:177: 15 Handling message Broadcast +2025-11-14T18:24:30.120533Z  INFO ThreadId(49) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 5) (epoch 0, view 5), parent height: 4 +2025-11-14T18:24:30.120538Z  INFO ThreadId(36) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 5) (epoch 0, view 5), parent height: 4 +2025-11-14T18:24:30.120547Z  INFO ThreadId(57) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 5) (epoch 0, view 5), parent height: 4 +2025-11-14T18:24:30.122669Z  INFO ThreadId(49) summit_application::actor: application/src/actor.rs:149: 139 application: Handling message Propose for round Round(0, 6) (epoch 0, view 6), parent height: 5 +2025-11-14T18:24:30.124268Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 5) (last_processed_height=3, tip=3) +2025-11-14T18:24:30.124283Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 5) (last_processed_height=3, tip=3) +2025-11-14T18:24:30.124529Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 5) (last_processed_height=3, tip=3) +2025-11-14T18:24:30.124793Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 4 (previous tip: 3) +2025-11-14T18:24:30.124798Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 4 (last_processed_height: 3, tip: 4) +2025-11-14T18:24:30.124800Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 4 (previous tip: 3) +2025-11-14T18:24:30.124810Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 4 (last_processed_height: 3, tip: 4) +2025-11-14T18:24:30.124841Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 4)], last_processed_height: 3, tip: 4 +2025-11-14T18:24:30.124844Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:30.124864Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 4)], last_processed_height: 3, tip: 4 +2025-11-14T18:24:30.124870Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:30.125160Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 4 (previous tip: 3) +2025-11-14T18:24:30.125167Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 4 (last_processed_height: 3, tip: 4) +2025-11-14T18:24:30.125209Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 5) (last_processed_height=3, tip=3) +2025-11-14T18:24:30.125218Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 4)], last_processed_height: 3, tip: 4 +2025-11-14T18:24:30.125222Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:30.126013Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 4 (previous tip: 3) +2025-11-14T18:24:30.126021Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 4 (last_processed_height: 3, tip: 4) +2025-11-14T18:24:30.126028Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x538ade1559c4a7290e04e84ad42b0847e9fddebc2afcc6edcb11facb2723077c for height 4 +2025-11-14T18:24:30.126045Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x538ade1559c4a7290e04e84ad42b0847e9fddebc2afcc6edcb11facb2723077c for height 4 +2025-11-14T18:24:30.126070Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 4)], last_processed_height: 3, tip: 4 +2025-11-14T18:24:30.126076Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 4 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 4, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 4, is last block: false +2025-11-14T18:24:30.126226Z  INFO ThreadId(36) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=4 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 4 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 4, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 4, is last block: false +2025-11-14T18:24:30.126257Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=4 +2025-11-14T18:24:30.126362Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x538ade1559c4a7290e04e84ad42b0847e9fddebc2afcc6edcb11facb2723077c for height 4 +2025-11-14T18:24:30.126449Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 5 not found (last_processed=4, tip=4) +2025-11-14T18:24:30.126450Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 5 not found (last_processed=4, tip=4) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 4 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 4, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 4, is last block: false +2025-11-14T18:24:30.126940Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x538ade1559c4a7290e04e84ad42b0847e9fddebc2afcc6edcb11facb2723077c for height 4 +2025-11-14T18:24:30.126942Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=4 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 4 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 4, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 4, is last block: false +2025-11-14T18:24:30.127079Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=4 +2025-11-14T18:24:30.127082Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 5 not found (last_processed=4, tip=4) +2025-11-14T18:24:30.127192Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 5 not found (last_processed=4, tip=4) +2025-11-14T18:24:30.178551Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:177: 139 Handling message Broadcast +2025-11-14T18:24:30.181461Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 6) (epoch 0, view 6), parent height: 5 +2025-11-14T18:24:30.181535Z  INFO ThreadId(57) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 6) (epoch 0, view 6), parent height: 5 +2025-11-14T18:24:30.181955Z  INFO ThreadId(36) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 6) (epoch 0, view 6), parent height: 5 +2025-11-14T18:24:30.183876Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:149: 55 application: Handling message Propose for round Round(0, 7) (epoch 0, view 7), parent height: 6 +2025-11-14T18:24:30.185608Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 6) (last_processed_height=4, tip=4) +2025-11-14T18:24:30.185784Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 6) (last_processed_height=4, tip=4) +2025-11-14T18:24:30.186258Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 6) (last_processed_height=4, tip=4) +2025-11-14T18:24:30.186337Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 5 (previous tip: 4) +2025-11-14T18:24:30.186343Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 5 (last_processed_height: 4, tip: 5) +2025-11-14T18:24:30.186386Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 5)], last_processed_height: 4, tip: 5 +2025-11-14T18:24:30.186390Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:30.186620Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 5 (previous tip: 4) +2025-11-14T18:24:30.186642Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 5 (last_processed_height: 4, tip: 5) +2025-11-14T18:24:30.186690Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 5)], last_processed_height: 4, tip: 5 +2025-11-14T18:24:30.186693Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:30.186893Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 5 (previous tip: 4) +2025-11-14T18:24:30.186898Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 5 (last_processed_height: 4, tip: 5) +2025-11-14T18:24:30.186939Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 5)], last_processed_height: 4, tip: 5 +2025-11-14T18:24:30.186942Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:30.187471Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xbbe0532445f496e78a0116f72e8d146052867406c4f99769ac4836b8bfa5062d for height 5 +2025-11-14T18:24:30.187636Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xbbe0532445f496e78a0116f72e8d146052867406c4f99769ac4836b8bfa5062d for height 5 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 5 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 5, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 5, is last block: false +2025-11-14T18:24:30.187656Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=5 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 5 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 5, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 5, is last block: false +2025-11-14T18:24:30.187791Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=5 +2025-11-14T18:24:30.187896Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 6 not found (last_processed=5, tip=5) +2025-11-14T18:24:30.187991Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 6 not found (last_processed=5, tip=5) +2025-11-14T18:24:30.188135Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xbbe0532445f496e78a0116f72e8d146052867406c4f99769ac4836b8bfa5062d for height 5 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 5 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 5, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 5, is last block: false +2025-11-14T18:24:30.188241Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=5 +2025-11-14T18:24:30.188363Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 6 not found (last_processed=5, tip=5) +2025-11-14T18:24:30.239947Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:177: 55 Handling message Broadcast +2025-11-14T18:24:30.254431Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 6) (last_processed_height=4, tip=4) +2025-11-14T18:24:30.255237Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 5 (previous tip: 4) +2025-11-14T18:24:30.255248Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 5 (last_processed_height: 4, tip: 5) +2025-11-14T18:24:30.255306Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 5)], last_processed_height: 4, tip: 5 +2025-11-14T18:24:30.255311Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:30.256443Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xbbe0532445f496e78a0116f72e8d146052867406c4f99769ac4836b8bfa5062d for height 5 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 5 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 5, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 5, is last block: false +2025-11-14T18:24:30.256621Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=5 +2025-11-14T18:24:30.256923Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 6 not found (last_processed=5, tip=5) +2025-11-14T18:24:30.310928Z  INFO ThreadId(52) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 7) (epoch 0, view 7), parent height: 6 +2025-11-14T18:24:30.311192Z  INFO ThreadId(37) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 7) (epoch 0, view 7), parent height: 6 +2025-11-14T18:24:30.311311Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 7) (epoch 0, view 7), parent height: 6 +2025-11-14T18:24:30.313763Z  INFO ThreadId(35) summit_application::actor: application/src/actor.rs:149: 209 application: Handling message Propose for round Round(0, 8) (epoch 0, view 8), parent height: 7 +2025-11-14T18:24:30.375872Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 7) (last_processed_height=5, tip=5) +2025-11-14T18:24:30.376526Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 7) (last_processed_height=5, tip=5) +2025-11-14T18:24:30.376794Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 6 (previous tip: 5) +2025-11-14T18:24:30.376807Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 6 (last_processed_height: 5, tip: 6) +2025-11-14T18:24:30.376903Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 6)], last_processed_height: 5, tip: 6 +2025-11-14T18:24:30.376911Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:30.377477Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 6 (previous tip: 5) +2025-11-14T18:24:30.377484Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 6 (last_processed_height: 5, tip: 6) +2025-11-14T18:24:30.377516Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 6)], last_processed_height: 5, tip: 6 +2025-11-14T18:24:30.377519Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:30.377947Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7a5a92996ccc764107898018aa9863b1eb7dfb6809d724bd84facf933d0e68c8 for height 6 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 6 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 6, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 6, is last block: false +2025-11-14T18:24:30.378168Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=6 +2025-11-14T18:24:30.378417Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 7 not found (last_processed=6, tip=6) +2025-11-14T18:24:30.378441Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7a5a92996ccc764107898018aa9863b1eb7dfb6809d724bd84facf933d0e68c8 for height 6 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 6 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 6, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 6, is last block: false +2025-11-14T18:24:30.378552Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=6 +2025-11-14T18:24:30.378708Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 7 not found (last_processed=6, tip=6) +2025-11-14T18:24:30.379594Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 7) (last_processed_height=5, tip=5) +2025-11-14T18:24:30.380084Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 6 (previous tip: 5) +2025-11-14T18:24:30.380090Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 6 (last_processed_height: 5, tip: 6) +2025-11-14T18:24:30.380115Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 6)], last_processed_height: 5, tip: 6 +2025-11-14T18:24:30.380118Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:30.381812Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 7) (last_processed_height=5, tip=5) +2025-11-14T18:24:30.382601Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7a5a92996ccc764107898018aa9863b1eb7dfb6809d724bd84facf933d0e68c8 for height 6 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 6 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 6, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 6, is last block: false +2025-11-14T18:24:30.382779Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=6 +2025-11-14T18:24:30.382911Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 7 not found (last_processed=6, tip=6) +2025-11-14T18:24:30.383050Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 6 (previous tip: 5) +2025-11-14T18:24:30.383057Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 6 (last_processed_height: 5, tip: 6) +2025-11-14T18:24:30.383110Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 6)], last_processed_height: 5, tip: 6 +2025-11-14T18:24:30.383117Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:30.384215Z  INFO ThreadId(37) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7a5a92996ccc764107898018aa9863b1eb7dfb6809d724bd84facf933d0e68c8 for height 6 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 6 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 6, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 6, is last block: false +2025-11-14T18:24:30.384371Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=6 +2025-11-14T18:24:30.384516Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 7 not found (last_processed=6, tip=6) +2025-11-14T18:24:30.435769Z  INFO ThreadId(38) summit_application::actor: application/src/actor.rs:177: 209 Handling message Broadcast +2025-11-14T18:24:30.439171Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 8) (epoch 0, view 8), parent height: 7 +2025-11-14T18:24:30.439289Z  INFO ThreadId(49) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 8) (epoch 0, view 8), parent height: 7 +2025-11-14T18:24:30.439397Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 8) (epoch 0, view 8), parent height: 7 +2025-11-14T18:24:30.444087Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:149: 15 application: Handling message Propose for round Round(0, 9) (epoch 0, view 9), parent height: 8 +2025-11-14T18:24:30.504749Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 8) (last_processed_height=6, tip=6) +2025-11-14T18:24:30.505582Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 7 (previous tip: 6) +2025-11-14T18:24:30.505589Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 7 (last_processed_height: 6, tip: 7) +2025-11-14T18:24:30.505641Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 7)], last_processed_height: 6, tip: 7 +2025-11-14T18:24:30.505644Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:30.505895Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 8) (last_processed_height=6, tip=6) +2025-11-14T18:24:30.506449Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 7 (previous tip: 6) +2025-11-14T18:24:30.506459Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 7 (last_processed_height: 6, tip: 7) +2025-11-14T18:24:30.506531Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 7)], last_processed_height: 6, tip: 7 +2025-11-14T18:24:30.506545Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:30.506812Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x910194f4dd99d1c392d20edbdb62134e75acf2a6a34a6ef09f5e163743ba7531 for height 7 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 7 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 7, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 7, is last block: false +2025-11-14T18:24:30.506948Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=7 +2025-11-14T18:24:30.507113Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 8 not found (last_processed=7, tip=7) +2025-11-14T18:24:30.507426Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x910194f4dd99d1c392d20edbdb62134e75acf2a6a34a6ef09f5e163743ba7531 for height 7 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 7 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 7, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 7, is last block: false +2025-11-14T18:24:30.507552Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=7 +2025-11-14T18:24:30.507671Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 8 not found (last_processed=7, tip=7) +2025-11-14T18:24:30.558322Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 8) (last_processed_height=6, tip=6) +2025-11-14T18:24:30.559019Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 8) (last_processed_height=6, tip=6) +2025-11-14T18:24:30.559080Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 7 (previous tip: 6) +2025-11-14T18:24:30.559093Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 7 (last_processed_height: 6, tip: 7) +2025-11-14T18:24:30.559175Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 7)], last_processed_height: 6, tip: 7 +2025-11-14T18:24:30.559182Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:30.559559Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 7 (previous tip: 6) +2025-11-14T18:24:30.559572Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 7 (last_processed_height: 6, tip: 7) +2025-11-14T18:24:30.559612Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 7)], last_processed_height: 6, tip: 7 +2025-11-14T18:24:30.559618Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:30.560177Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x910194f4dd99d1c392d20edbdb62134e75acf2a6a34a6ef09f5e163743ba7531 for height 7 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 7 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 7, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 7, is last block: false +2025-11-14T18:24:30.560335Z  INFO ThreadId(37) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=7 +2025-11-14T18:24:30.560474Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x910194f4dd99d1c392d20edbdb62134e75acf2a6a34a6ef09f5e163743ba7531 for height 7 +2025-11-14T18:24:30.560494Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 8 not found (last_processed=7, tip=7) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 7 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 7, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 7, is last block: false +2025-11-14T18:24:30.560638Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=7 +2025-11-14T18:24:30.560777Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 8 not found (last_processed=7, tip=7) +2025-11-14T18:24:30.612520Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:177: 15 Handling message Broadcast +2025-11-14T18:24:30.627498Z  INFO ThreadId(56) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 9) (epoch 0, view 9), parent height: 8 +2025-11-14T18:24:30.627517Z  INFO ThreadId(37) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 9) (epoch 0, view 9), parent height: 8 +2025-11-14T18:24:30.627646Z  INFO ThreadId(49) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 9) (epoch 0, view 9), parent height: 8 +2025-11-14T18:24:30.629665Z  INFO ThreadId(52) summit_application::actor: application/src/actor.rs:149: 139 application: Handling message Propose for round Round(0, 10) (epoch 0, view 10), parent height: 9 +2025-11-14T18:24:30.683140Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 9) (last_processed_height=7, tip=7) +2025-11-14T18:24:30.683162Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 9) (last_processed_height=7, tip=7) +2025-11-14T18:24:30.684063Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 9) (last_processed_height=7, tip=7) +2025-11-14T18:24:30.684222Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 8 (previous tip: 7) +2025-11-14T18:24:30.684234Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 8 (last_processed_height: 7, tip: 8) +2025-11-14T18:24:30.684283Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 8)], last_processed_height: 7, tip: 8 +2025-11-14T18:24:30.684289Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:30.684311Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 8 (previous tip: 7) +2025-11-14T18:24:30.684325Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 8 (last_processed_height: 7, tip: 8) +2025-11-14T18:24:30.684380Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 8)], last_processed_height: 7, tip: 8 +2025-11-14T18:24:30.684387Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:30.684816Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 8 (previous tip: 7) +2025-11-14T18:24:30.684824Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 8 (last_processed_height: 7, tip: 8) +2025-11-14T18:24:30.684869Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 8)], last_processed_height: 7, tip: 8 +2025-11-14T18:24:30.684873Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:30.685046Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 9) (last_processed_height=7, tip=7) +2025-11-14T18:24:30.685424Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd6e3783e09279197ea981905651448706fe0249c292cec4b1a837c8c9fdbd426 for height 8 +2025-11-14T18:24:30.685524Z  INFO ThreadId(37) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd6e3783e09279197ea981905651448706fe0249c292cec4b1a837c8c9fdbd426 for height 8 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 8 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 8, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 8, is last block: false +2025-11-14T18:24:30.685600Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=8 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 8 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 8, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 8, is last block: false +2025-11-14T18:24:30.685750Z  INFO ThreadId(37) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=8 +2025-11-14T18:24:30.685809Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 9 not found (last_processed=8, tip=8) +2025-11-14T18:24:30.685908Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 9 not found (last_processed=8, tip=8) +2025-11-14T18:24:30.685991Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd6e3783e09279197ea981905651448706fe0249c292cec4b1a837c8c9fdbd426 for height 8 +2025-11-14T18:24:30.686015Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 8 (previous tip: 7) +2025-11-14T18:24:30.686021Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 8 (last_processed_height: 7, tip: 8) +2025-11-14T18:24:30.686054Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 8)], last_processed_height: 7, tip: 8 +2025-11-14T18:24:30.686058Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 8 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 8, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 8, is last block: false +2025-11-14T18:24:30.686160Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=8 +2025-11-14T18:24:30.686342Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 9 not found (last_processed=8, tip=8) +2025-11-14T18:24:30.686888Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd6e3783e09279197ea981905651448706fe0249c292cec4b1a837c8c9fdbd426 for height 8 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 8 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 8, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 8, is last block: false +2025-11-14T18:24:30.686989Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=8 +2025-11-14T18:24:30.687138Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 9 not found (last_processed=8, tip=8) +2025-11-14T18:24:30.737800Z  INFO ThreadId(49) summit_application::actor: application/src/actor.rs:177: 139 Handling message Broadcast +2025-11-14T18:24:30.755153Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 10) (epoch 0, view 10), parent height: 9 +2025-11-14T18:24:30.755276Z  INFO ThreadId(56) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 10) (epoch 0, view 10), parent height: 9 +2025-11-14T18:24:30.755684Z  INFO ThreadId(38) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 10) (epoch 0, view 10), parent height: 9 +2025-11-14T18:24:30.758637Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:149: 55 application: Handling message Propose for round Round(0, 11) (epoch 0, view 11), parent height: 10 +2025-11-14T18:24:30.809518Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 10) (last_processed_height=8, tip=8) +2025-11-14T18:24:30.809838Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 10) (last_processed_height=8, tip=8) +2025-11-14T18:24:30.810275Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 9 (previous tip: 8) +2025-11-14T18:24:30.810288Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 9 (last_processed_height: 8, tip: 9) +2025-11-14T18:24:30.810359Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 9)], last_processed_height: 8, tip: 9 +2025-11-14T18:24:30.810366Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:30.810847Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 9 (previous tip: 8) +2025-11-14T18:24:30.810854Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 9 (last_processed_height: 8, tip: 9) +2025-11-14T18:24:30.810903Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 9)], last_processed_height: 8, tip: 9 +2025-11-14T18:24:30.810907Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:30.811369Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x692bbb1d7d55f6ee906704d1d9b8d456ddb7838d58b3055735fe9424450b4029 for height 9 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 9 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 9, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 9, is last block: false +2025-11-14T18:24:30.811524Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=9 +2025-11-14T18:24:30.811669Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 10 not found (last_processed=9, tip=9) +2025-11-14T18:24:30.811828Z  INFO ThreadId(37) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x692bbb1d7d55f6ee906704d1d9b8d456ddb7838d58b3055735fe9424450b4029 for height 9 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 9 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 9, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 9, is last block: false +2025-11-14T18:24:30.811928Z  INFO ThreadId(37) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=9 +2025-11-14T18:24:30.812093Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 10 not found (last_processed=9, tip=9) +2025-11-14T18:24:30.876740Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 10) (last_processed_height=8, tip=8) +2025-11-14T18:24:30.876810Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 10) (last_processed_height=8, tip=8) +2025-11-14T18:24:30.877721Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 9 (previous tip: 8) +2025-11-14T18:24:30.877727Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 9 (last_processed_height: 8, tip: 9) +2025-11-14T18:24:30.877768Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 9)], last_processed_height: 8, tip: 9 +2025-11-14T18:24:30.877773Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:30.877793Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 9 (previous tip: 8) +2025-11-14T18:24:30.877799Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 9 (last_processed_height: 8, tip: 9) +2025-11-14T18:24:30.877827Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 9)], last_processed_height: 8, tip: 9 +2025-11-14T18:24:30.877830Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:30.878715Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x692bbb1d7d55f6ee906704d1d9b8d456ddb7838d58b3055735fe9424450b4029 for height 9 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 9 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 9, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 9, is last block: false +2025-11-14T18:24:30.878889Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=9 +2025-11-14T18:24:30.879032Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 10 not found (last_processed=9, tip=9) +2025-11-14T18:24:30.880735Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x692bbb1d7d55f6ee906704d1d9b8d456ddb7838d58b3055735fe9424450b4029 for height 9 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 9 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 9, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 9, is last block: false +2025-11-14T18:24:30.880846Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=9 +2025-11-14T18:24:30.880985Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 10 not found (last_processed=9, tip=9) +2025-11-14T18:24:30.931134Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:177: 55 Handling message Broadcast +2025-11-14T18:24:30.933711Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 11) (epoch 0, view 11), parent height: 10 +2025-11-14T18:24:30.933836Z  INFO ThreadId(36) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 11) (epoch 0, view 11), parent height: 10 +2025-11-14T18:24:30.933911Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 11) (epoch 0, view 11), parent height: 10 +2025-11-14T18:24:30.936266Z  INFO ThreadId(35) summit_application::actor: application/src/actor.rs:149: 209 application: Handling message Propose for round Round(0, 12) (epoch 0, view 12), parent height: 11 +2025-11-14T18:24:31.001499Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 11) (last_processed_height=9, tip=9) +2025-11-14T18:24:31.001946Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 11) (last_processed_height=9, tip=9) +2025-11-14T18:24:31.001956Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 11) (last_processed_height=9, tip=9) +2025-11-14T18:24:31.002555Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 10 (previous tip: 9) +2025-11-14T18:24:31.002562Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 10 (last_processed_height: 9, tip: 10) +2025-11-14T18:24:31.002602Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 10)], last_processed_height: 9, tip: 10 +2025-11-14T18:24:31.002606Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:31.002733Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 10 (previous tip: 9) +2025-11-14T18:24:31.002739Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 10 (last_processed_height: 9, tip: 10) +2025-11-14T18:24:31.002770Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 10)], last_processed_height: 9, tip: 10 +2025-11-14T18:24:31.002774Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:31.002781Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 10 (previous tip: 9) +2025-11-14T18:24:31.002787Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 10 (last_processed_height: 9, tip: 10) +2025-11-14T18:24:31.002818Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 10)], last_processed_height: 9, tip: 10 +2025-11-14T18:24:31.002821Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:31.003830Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xf9586933212624f99dfa37d40e4e59272d190acc624a0373f2b31a3512edbde8 for height 10 +2025-11-14T18:24:31.003845Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xf9586933212624f99dfa37d40e4e59272d190acc624a0373f2b31a3512edbde8 for height 10 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 10 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 10, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 10, is last block: false +üüüüüüüüüüüüüüüüüüüüüüüüü +2025-11-14T18:24:31.004020Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=10 +COMMITING BLOCK 10 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 10, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 10, is last block: false +2025-11-14T18:24:31.004028Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xf9586933212624f99dfa37d40e4e59272d190acc624a0373f2b31a3512edbde8 for height 10 +2025-11-14T18:24:31.004035Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=10 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 10 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 10, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 10, is last block: false +2025-11-14T18:24:31.004172Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=10 +2025-11-14T18:24:31.004210Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 11 not found (last_processed=10, tip=10) +2025-11-14T18:24:31.004232Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 11 not found (last_processed=10, tip=10) +2025-11-14T18:24:31.004339Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 11 not found (last_processed=10, tip=10) +2025-11-14T18:24:31.004379Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 11) (last_processed_height=9, tip=9) +2025-11-14T18:24:31.005022Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 10 (previous tip: 9) +2025-11-14T18:24:31.005029Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 10 (last_processed_height: 9, tip: 10) +2025-11-14T18:24:31.005072Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 10)], last_processed_height: 9, tip: 10 +2025-11-14T18:24:31.005076Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:31.005824Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xf9586933212624f99dfa37d40e4e59272d190acc624a0373f2b31a3512edbde8 for height 10 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 10 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 10, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 10, is last block: false +2025-11-14T18:24:31.005957Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=10 +2025-11-14T18:24:31.006079Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 11 not found (last_processed=10, tip=10) +2025-11-14T18:24:31.056434Z  INFO ThreadId(38) summit_application::actor: application/src/actor.rs:177: 209 Handling message Broadcast +2025-11-14T18:24:31.058888Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 12) (epoch 0, view 12), parent height: 11 +2025-11-14T18:24:31.058964Z  INFO ThreadId(56) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 12) (epoch 0, view 12), parent height: 11 +2025-11-14T18:24:31.059041Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 12) (epoch 0, view 12), parent height: 11 +2025-11-14T18:24:31.060829Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:149: 15 application: Handling message Propose for round Round(0, 13) (epoch 0, view 13), parent height: 12 +2025-11-14T18:24:31.130118Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 12) (last_processed_height=10, tip=10) +2025-11-14T18:24:31.130238Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 12) (last_processed_height=10, tip=10) +2025-11-14T18:24:31.131070Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 11 (previous tip: 10) +2025-11-14T18:24:31.131084Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 11 (last_processed_height: 10, tip: 11) +2025-11-14T18:24:31.131156Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 11)], last_processed_height: 10, tip: 11 +2025-11-14T18:24:31.131165Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:31.131287Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 11 (previous tip: 10) +2025-11-14T18:24:31.131294Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 11 (last_processed_height: 10, tip: 11) +2025-11-14T18:24:31.131329Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 11)], last_processed_height: 10, tip: 11 +2025-11-14T18:24:31.131332Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:31.132177Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x31d2fe8e8f88158717c362f2724cc88d530495f877b5826cb04d77079bec3f9d for height 11 +2025-11-14T18:24:31.132307Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x31d2fe8e8f88158717c362f2724cc88d530495f877b5826cb04d77079bec3f9d for height 11 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 11 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 11, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 11, is last block: false +2025-11-14T18:24:31.132371Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=11 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 11 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 11, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 11, is last block: false +2025-11-14T18:24:31.132439Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=11 +2025-11-14T18:24:31.132518Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 12 not found (last_processed=11, tip=11) +2025-11-14T18:24:31.132567Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 12 not found (last_processed=11, tip=11) +2025-11-14T18:24:31.182499Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 12) (last_processed_height=10, tip=10) +2025-11-14T18:24:31.183066Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 12) (last_processed_height=10, tip=10) +2025-11-14T18:24:31.183212Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 11 (previous tip: 10) +2025-11-14T18:24:31.183228Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 11 (last_processed_height: 10, tip: 11) +2025-11-14T18:24:31.183293Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 11)], last_processed_height: 10, tip: 11 +2025-11-14T18:24:31.183300Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:31.183700Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 11 (previous tip: 10) +2025-11-14T18:24:31.183706Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 11 (last_processed_height: 10, tip: 11) +2025-11-14T18:24:31.183750Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 11)], last_processed_height: 10, tip: 11 +2025-11-14T18:24:31.183753Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:31.184211Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x31d2fe8e8f88158717c362f2724cc88d530495f877b5826cb04d77079bec3f9d for height 11 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 11 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 11, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 11, is last block: false +2025-11-14T18:24:31.184361Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=11 +2025-11-14T18:24:31.184506Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 12 not found (last_processed=11, tip=11) +2025-11-14T18:24:31.184584Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x31d2fe8e8f88158717c362f2724cc88d530495f877b5826cb04d77079bec3f9d for height 11 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 11 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 11, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 11, is last block: false +2025-11-14T18:24:31.184711Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=11 +2025-11-14T18:24:31.184836Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 12 not found (last_processed=11, tip=11) +2025-11-14T18:24:31.236030Z  INFO ThreadId(43) summit_application::actor: application/src/actor.rs:177: 15 Handling message Broadcast +2025-11-14T18:24:31.251963Z  INFO ThreadId(37) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 13) (epoch 0, view 13), parent height: 12 +2025-11-14T18:24:31.252123Z  INFO ThreadId(52) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 13) (epoch 0, view 13), parent height: 12 +2025-11-14T18:24:31.252771Z  INFO ThreadId(57) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 13) (epoch 0, view 13), parent height: 12 +2025-11-14T18:24:31.254925Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:149: 139 application: Handling message Propose for round Round(0, 14) (epoch 0, view 14), parent height: 13 +2025-11-14T18:24:31.255989Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 13) (last_processed_height=11, tip=11) +2025-11-14T18:24:31.256411Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 13) (last_processed_height=11, tip=11) +2025-11-14T18:24:31.257239Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 12 (previous tip: 11) +2025-11-14T18:24:31.257262Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 12 (last_processed_height: 11, tip: 12) +2025-11-14T18:24:31.257420Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 12)], last_processed_height: 11, tip: 12 +2025-11-14T18:24:31.257433Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:31.258060Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 12 (previous tip: 11) +2025-11-14T18:24:31.258068Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 12 (last_processed_height: 11, tip: 12) +2025-11-14T18:24:31.258205Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 12)], last_processed_height: 11, tip: 12 +2025-11-14T18:24:31.258208Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:31.259294Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x82fda567635697f8db64e90c46d014090eb6d82035a4f896590d10bd25663edf for height 12 +2025-11-14T18:24:31.259402Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x82fda567635697f8db64e90c46d014090eb6d82035a4f896590d10bd25663edf for height 12 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 12 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 12, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 12, is last block: false +2025-11-14T18:24:31.259500Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=12 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 12 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 12, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 12, is last block: false +2025-11-14T18:24:31.259574Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=12 +2025-11-14T18:24:31.259647Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 13 not found (last_processed=12, tip=12) +2025-11-14T18:24:31.259738Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 13 not found (last_processed=12, tip=12) +2025-11-14T18:24:31.308432Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 13) (last_processed_height=11, tip=11) +2025-11-14T18:24:31.308990Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 13) (last_processed_height=11, tip=11) +2025-11-14T18:24:31.309237Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 12 (previous tip: 11) +2025-11-14T18:24:31.309251Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 12 (last_processed_height: 11, tip: 12) +2025-11-14T18:24:31.309333Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 12)], last_processed_height: 11, tip: 12 +2025-11-14T18:24:31.309340Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:31.309912Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 12 (previous tip: 11) +2025-11-14T18:24:31.309918Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 12 (last_processed_height: 11, tip: 12) +2025-11-14T18:24:31.309957Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 12)], last_processed_height: 11, tip: 12 +2025-11-14T18:24:31.309961Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:31.310257Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x82fda567635697f8db64e90c46d014090eb6d82035a4f896590d10bd25663edf for height 12 +2025-11-14T18:24:31.310317Z  INFO ThreadId(49) summit_application::actor: application/src/actor.rs:177: 139 Handling message Broadcast +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 12 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 12, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 12, is last block: false +2025-11-14T18:24:31.310421Z  INFO ThreadId(36) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=12 +2025-11-14T18:24:31.310562Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 13 not found (last_processed=12, tip=12) +2025-11-14T18:24:31.310810Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x82fda567635697f8db64e90c46d014090eb6d82035a4f896590d10bd25663edf for height 12 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 12 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 12, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 12, is last block: false +2025-11-14T18:24:31.310917Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=12 +2025-11-14T18:24:31.311052Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 13 not found (last_processed=12, tip=12) +Sending deposit transaction to node 0 +Transaction sent: 0x988d51d886f24322621e259bb6fa99622ab6d99623572a043c728eab165007a7 +2025-11-14T18:24:31.379788Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 14) (epoch 0, view 14), parent height: 13 +2025-11-14T18:24:31.380007Z  INFO ThreadId(56) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 14) (epoch 0, view 14), parent height: 13 +2025-11-14T18:24:31.380056Z  INFO ThreadId(38) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 14) (epoch 0, view 14), parent height: 13 +2025-11-14T18:24:31.382187Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:149: 55 application: Handling message Propose for round Round(0, 15) (epoch 0, view 15), parent height: 14 +2025-11-14T18:24:31.434889Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 14) (last_processed_height=12, tip=12) +2025-11-14T18:24:31.435694Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 14) (last_processed_height=12, tip=12) +2025-11-14T18:24:31.436164Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 13 (previous tip: 12) +2025-11-14T18:24:31.436184Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 13 (last_processed_height: 12, tip: 13) +2025-11-14T18:24:31.436239Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 13)], last_processed_height: 12, tip: 13 +2025-11-14T18:24:31.436246Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:31.436414Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 13 (previous tip: 12) +2025-11-14T18:24:31.436419Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 13 (last_processed_height: 12, tip: 13) +2025-11-14T18:24:31.436454Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 13)], last_processed_height: 12, tip: 13 +2025-11-14T18:24:31.436456Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:31.437347Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x8c44a4cf0958aca16e18efe529eefed8751d91c59b0eea82119f3da5163ca2cd for height 13 +2025-11-14T18:24:31.437458Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x8c44a4cf0958aca16e18efe529eefed8751d91c59b0eea82119f3da5163ca2cd for height 13 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 13 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 13, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 13, is last block: false +2025-11-14T18:24:31.437495Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=13 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 13 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 13, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 13, is last block: false +2025-11-14T18:24:31.437577Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=13 +2025-11-14T18:24:31.437669Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 14 not found (last_processed=13, tip=13) +2025-11-14T18:24:31.437706Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 14 not found (last_processed=13, tip=13) +2025-11-14T18:24:31.501291Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 14) (last_processed_height=12, tip=12) +2025-11-14T18:24:31.501334Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 14) (last_processed_height=12, tip=12) +2025-11-14T18:24:31.502033Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 13 (previous tip: 12) +2025-11-14T18:24:31.502046Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 13 (last_processed_height: 12, tip: 13) +2025-11-14T18:24:31.502091Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 13)], last_processed_height: 12, tip: 13 +2025-11-14T18:24:31.502100Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:31.502426Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 13 (previous tip: 12) +2025-11-14T18:24:31.502439Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 13 (last_processed_height: 12, tip: 13) +2025-11-14T18:24:31.502527Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 13)], last_processed_height: 12, tip: 13 +2025-11-14T18:24:31.502536Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:31.503370Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x8c44a4cf0958aca16e18efe529eefed8751d91c59b0eea82119f3da5163ca2cd for height 13 +2025-11-14T18:24:31.503409Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x8c44a4cf0958aca16e18efe529eefed8751d91c59b0eea82119f3da5163ca2cd for height 13 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 13 to reth +üüüüüüüüüüüüüüüüüüüüüüüüü +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +COMMITING BLOCK 13 to reth +epoch_num_of_blocks: 50, new_height: 13, is penultimate block: false +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 13, is penultimate block: false +epoch_num_of_blocks: 50, new_height: 13, is last block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 13, is last block: false +2025-11-14T18:24:31.503542Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=13 +2025-11-14T18:24:31.503545Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=13 +2025-11-14T18:24:31.503724Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 14 not found (last_processed=13, tip=13) +2025-11-14T18:24:31.503724Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 14 not found (last_processed=13, tip=13) +2025-11-14T18:24:31.555410Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:177: 55 Handling message Broadcast +2025-11-14T18:24:31.557982Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 15) (epoch 0, view 15), parent height: 14 +2025-11-14T18:24:31.558000Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 15) (epoch 0, view 15), parent height: 14 +2025-11-14T18:24:31.558520Z  INFO ThreadId(38) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 15) (epoch 0, view 15), parent height: 14 +2025-11-14T18:24:31.562580Z  INFO ThreadId(37) summit_application::actor: application/src/actor.rs:149: 209 application: Handling message Propose for round Round(0, 16) (epoch 0, view 16), parent height: 15 +2025-11-14T18:24:31.563619Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 15) (last_processed_height=13, tip=13) +2025-11-14T18:24:31.564474Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 14 (previous tip: 13) +2025-11-14T18:24:31.564485Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 14 (last_processed_height: 13, tip: 14) +2025-11-14T18:24:31.564553Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 14)], last_processed_height: 13, tip: 14 +2025-11-14T18:24:31.564559Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:31.565746Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x28aec05ff930de746d6df6b745bc7c362dbdd5f3ea54916d3e652f70901e0f10 for height 14 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 14 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 14, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 14, is last block: false +2025-11-14T18:24:31.565917Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=14 +2025-11-14T18:24:31.566189Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 15 not found (last_processed=14, tip=14) +2025-11-14T18:24:31.626154Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 15) (last_processed_height=13, tip=13) +2025-11-14T18:24:31.626531Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 15) (last_processed_height=13, tip=13) +2025-11-14T18:24:31.627266Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 14 (previous tip: 13) +2025-11-14T18:24:31.627279Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 14 (last_processed_height: 13, tip: 14) +2025-11-14T18:24:31.627296Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 15) (last_processed_height=13, tip=13) +2025-11-14T18:24:31.627335Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 14)], last_processed_height: 13, tip: 14 +2025-11-14T18:24:31.627342Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:31.627583Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 14 (previous tip: 13) +2025-11-14T18:24:31.627595Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 14 (last_processed_height: 13, tip: 14) +2025-11-14T18:24:31.627671Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 14)], last_processed_height: 13, tip: 14 +2025-11-14T18:24:31.627678Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:31.627791Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 14 (previous tip: 13) +2025-11-14T18:24:31.627798Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 14 (last_processed_height: 13, tip: 14) +2025-11-14T18:24:31.627830Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 14)], last_processed_height: 13, tip: 14 +2025-11-14T18:24:31.627833Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:31.628711Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x28aec05ff930de746d6df6b745bc7c362dbdd5f3ea54916d3e652f70901e0f10 for height 14 +2025-11-14T18:24:31.628791Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x28aec05ff930de746d6df6b745bc7c362dbdd5f3ea54916d3e652f70901e0f10 for height 14 +2025-11-14T18:24:31.628861Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x28aec05ff930de746d6df6b745bc7c362dbdd5f3ea54916d3e652f70901e0f10 for height 14 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 14 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 14, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 14, is last block: false +2025-11-14T18:24:31.628919Z  INFO ThreadId(36) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=14 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 14 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 14, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 14, is last block: false +2025-11-14T18:24:31.628932Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=14 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 14 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 14, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 14, is last block: false +2025-11-14T18:24:31.629028Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=14 +2025-11-14T18:24:31.629108Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 15 not found (last_processed=14, tip=14) +2025-11-14T18:24:31.629115Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 15 not found (last_processed=14, tip=14) +2025-11-14T18:24:31.629181Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 15 not found (last_processed=14, tip=14) +2025-11-14T18:24:31.680847Z  INFO ThreadId(38) summit_application::actor: application/src/actor.rs:177: 209 Handling message Broadcast +2025-11-14T18:24:31.683197Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 16) (epoch 0, view 16), parent height: 15 +2025-11-14T18:24:31.683204Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 16) (epoch 0, view 16), parent height: 15 +2025-11-14T18:24:31.683389Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 16) (epoch 0, view 16), parent height: 15 +2025-11-14T18:24:31.686687Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:149: 15 application: Handling message Propose for round Round(0, 17) (epoch 0, view 17), parent height: 16 +2025-11-14T18:24:31.751794Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 16) (last_processed_height=14, tip=14) +2025-11-14T18:24:31.751967Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 16) (last_processed_height=14, tip=14) +2025-11-14T18:24:31.753013Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 15 (previous tip: 14) +2025-11-14T18:24:31.753020Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 15 (last_processed_height: 14, tip: 15) +2025-11-14T18:24:31.753040Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 15 (previous tip: 14) +2025-11-14T18:24:31.753052Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 15 (last_processed_height: 14, tip: 15) +2025-11-14T18:24:31.753076Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 15)], last_processed_height: 14, tip: 15 +2025-11-14T18:24:31.753080Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:31.753157Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 15)], last_processed_height: 14, tip: 15 +2025-11-14T18:24:31.753165Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:31.754524Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x06e2d0eb376c1a236325ba954f90ed336830915381b0aa17f35357a77d277153 for height 15 +2025-11-14T18:24:31.754531Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x06e2d0eb376c1a236325ba954f90ed336830915381b0aa17f35357a77d277153 for height 15 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 15 to reth +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 15 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 15, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 15, is last block: false +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 15, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 15, is last block: false +2025-11-14T18:24:31.755574Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=15 +2025-11-14T18:24:31.755578Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=15 +2025-11-14T18:24:31.755709Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 16 not found (last_processed=15, tip=15) +2025-11-14T18:24:31.755709Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 16 not found (last_processed=15, tip=15) +2025-11-14T18:24:31.808467Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 16) (last_processed_height=14, tip=14) +2025-11-14T18:24:31.808560Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 16) (last_processed_height=14, tip=14) +2025-11-14T18:24:31.809082Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 15 (previous tip: 14) +2025-11-14T18:24:31.809094Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 15 (previous tip: 14) +2025-11-14T18:24:31.809094Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 15 (last_processed_height: 14, tip: 15) +2025-11-14T18:24:31.809099Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 15 (last_processed_height: 14, tip: 15) +2025-11-14T18:24:31.809147Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 15)], last_processed_height: 14, tip: 15 +2025-11-14T18:24:31.809150Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:31.809172Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 15)], last_processed_height: 14, tip: 15 +2025-11-14T18:24:31.809177Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:31.810420Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x06e2d0eb376c1a236325ba954f90ed336830915381b0aa17f35357a77d277153 for height 15 +2025-11-14T18:24:31.810461Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x06e2d0eb376c1a236325ba954f90ed336830915381b0aa17f35357a77d277153 for height 15 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 15 to reth +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 15 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 15, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 15, is last block: false +2025-11-14T18:24:31.811484Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=15 +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 15, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 15, is last block: false +2025-11-14T18:24:31.811515Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=15 +2025-11-14T18:24:31.811636Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 16 not found (last_processed=15, tip=15) +2025-11-14T18:24:31.811662Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 16 not found (last_processed=15, tip=15) +2025-11-14T18:24:31.863439Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:177: 15 Handling message Broadcast +2025-11-14T18:24:31.865989Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 17) (epoch 0, view 17), parent height: 16 +2025-11-14T18:24:31.866144Z  INFO ThreadId(35) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 17) (epoch 0, view 17), parent height: 16 +2025-11-14T18:24:31.866228Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 17) (epoch 0, view 17), parent height: 16 +2025-11-14T18:24:31.870226Z  INFO ThreadId(49) summit_application::actor: application/src/actor.rs:149: 139 application: Handling message Propose for round Round(0, 18) (epoch 0, view 18), parent height: 17 +Receipt: TransactionReceipt { inner: Legacy(ReceiptWithBloom { receipt: Receipt { status: Eip658(true), cumulative_gas_used: 106377, logs: [Log { inner: Log { address: 0x00000000219ab540356cbb839cbe05303d7705fa, data: LogData { topics: [0x0cff1634a9a72df9d813ea7e3a3874a76086e081904ad3cf81e12e43f4d4c87a], data: 0x00000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000020ae3a9bc6eb721b7b8a34d23aa0d5b1623e89bc6f092815ea13b92f79a39c7d380000000000000000000000000000000000000000000000000000000000000030a14001719d5b45c5552452779faf655b380f821fb0949de004dd4745383480ffa3a7b8e0a1ff70605e886af77411976e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020010000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb922660000000000000000000000000000000000000000000000000000000000000008004059730700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000402ee35498aadd0256319acae9ce9515720f2ea9fcae2f8cae0cf45032fd550b66331e79f19aeaa730ea5a1087a44f0a9ff91b35dc23244ecad12b9a65287c650b0000000000000000000000000000000000000000000000000000000000000060ae4b19ad6b1b073940c7f97cc6a58ad17c2a204f3be06a91928bfca3108f4fa183422e33e6747986be6a482713e0ff21154c9fe319e68cec0908ecb6dfe34ac5cc43737eb0b909e98b0005be83396bc9d476b925e989d004abd36937f70fe27d00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000 } }, block_hash: Some(0x06e2d0eb376c1a236325ba954f90ed336830915381b0aa17f35357a77d277153), block_number: Some(15), block_timestamp: Some(1763144671628), transaction_hash: Some(0x988d51d886f24322621e259bb6fa99622ab6d99623572a043c728eab165007a7), transaction_index: Some(0), log_index: Some(0), removed: false }] }, logs_bloom: 0x00000000000000000000400000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 }), transaction_hash: 0x988d51d886f24322621e259bb6fa99622ab6d99623572a043c728eab165007a7, transaction_index: Some(0), block_hash: Some(0x06e2d0eb376c1a236325ba954f90ed336830915381b0aa17f35357a77d277153), block_number: Some(15), gas_used: 106377, effective_gas_price: 1000000000, blob_gas_used: None, blob_gas_price: None, from: 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266, to: Some(0x00000000219ab540356cbb839cbe05303d7705fa), contract_address: None } +Waiting for nodes to reach checkpoint height 50 +2025-11-14T18:24:31.880230Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 17) (last_processed_height=15, tip=15) +2025-11-14T18:24:31.880714Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 16 (previous tip: 15) +2025-11-14T18:24:31.880720Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 16 (last_processed_height: 15, tip: 16) +2025-11-14T18:24:31.880761Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 16)], last_processed_height: 15, tip: 16 +2025-11-14T18:24:31.880765Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:31.881477Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 17) (last_processed_height=15, tip=15) +2025-11-14T18:24:31.881914Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xb7a5dd9d5f84be5319b1c03d432e3bd55bb7d1989db6f55bec2b29375b9ae3c8 for height 16 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 16 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 16, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 16, is last block: false +2025-11-14T18:24:31.882078Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=16 +2025-11-14T18:24:31.882224Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 17 not found (last_processed=16, tip=16) +2025-11-14T18:24:31.882261Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 16 (previous tip: 15) +2025-11-14T18:24:31.882268Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 16 (last_processed_height: 15, tip: 16) +2025-11-14T18:24:31.882304Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 16)], last_processed_height: 15, tip: 16 +2025-11-14T18:24:31.882307Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +Node 0 at height 15 +2025-11-14T18:24:31.883082Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xb7a5dd9d5f84be5319b1c03d432e3bd55bb7d1989db6f55bec2b29375b9ae3c8 for height 16 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 16 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 16, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 16, is last block: false +2025-11-14T18:24:31.883201Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=16 +2025-11-14T18:24:31.883327Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 17 not found (last_processed=16, tip=16) +2025-11-14T18:24:31.933082Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 17) (last_processed_height=15, tip=15) +2025-11-14T18:24:31.933186Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 17) (last_processed_height=15, tip=15) +2025-11-14T18:24:31.933888Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 16 (previous tip: 15) +2025-11-14T18:24:31.933895Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 16 (last_processed_height: 15, tip: 16) +2025-11-14T18:24:31.933927Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 16)], last_processed_height: 15, tip: 16 +2025-11-14T18:24:31.933933Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:31.933980Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 16 (previous tip: 15) +2025-11-14T18:24:31.933985Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 16 (last_processed_height: 15, tip: 16) +2025-11-14T18:24:31.934028Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 16)], last_processed_height: 15, tip: 16 +2025-11-14T18:24:31.934030Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:31.934514Z  INFO ThreadId(49) summit_application::actor: application/src/actor.rs:177: 139 Handling message Broadcast +2025-11-14T18:24:31.935052Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xb7a5dd9d5f84be5319b1c03d432e3bd55bb7d1989db6f55bec2b29375b9ae3c8 for height 16 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 16 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 16, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 16, is last block: false +2025-11-14T18:24:31.935997Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=16 +2025-11-14T18:24:31.936005Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xb7a5dd9d5f84be5319b1c03d432e3bd55bb7d1989db6f55bec2b29375b9ae3c8 for height 16 +2025-11-14T18:24:31.936063Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 18) (epoch 0, view 18), parent height: 17 +2025-11-14T18:24:31.936132Z  INFO ThreadId(36) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 18) (epoch 0, view 18), parent height: 17 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 16 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 16, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 16, is last block: false +2025-11-14T18:24:31.936156Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=16 +2025-11-14T18:24:31.936158Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 17 not found (last_processed=16, tip=16) +2025-11-14T18:24:31.936178Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 18) (epoch 0, view 18), parent height: 17 +2025-11-14T18:24:31.936339Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 17 not found (last_processed=16, tip=16) +2025-11-14T18:24:32.000599Z  INFO ThreadId(56) summit_application::actor: application/src/actor.rs:149: 55 application: Handling message Propose for round Round(0, 19) (epoch 0, view 19), parent height: 18 +2025-11-14T18:24:32.006367Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 18) (last_processed_height=16, tip=16) +2025-11-14T18:24:32.007037Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 18) (last_processed_height=16, tip=16) +2025-11-14T18:24:32.007228Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 17 (previous tip: 16) +2025-11-14T18:24:32.007234Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 17 (last_processed_height: 16, tip: 17) +2025-11-14T18:24:32.007279Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 17)], last_processed_height: 16, tip: 17 +2025-11-14T18:24:32.007285Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:32.008301Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 17 (previous tip: 16) +2025-11-14T18:24:32.008307Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 17 (last_processed_height: 16, tip: 17) +2025-11-14T18:24:32.008349Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 17)], last_processed_height: 16, tip: 17 +2025-11-14T18:24:32.008353Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:32.008829Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xb968553d74de341f8309764205b9a1e4dcbf0bf9d6ba14a89cb6b963bd3f0c43 for height 17 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 17 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 17, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 17, is last block: false +2025-11-14T18:24:32.009007Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=17 +2025-11-14T18:24:32.009181Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 18 not found (last_processed=17, tip=17) +2025-11-14T18:24:32.009281Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xb968553d74de341f8309764205b9a1e4dcbf0bf9d6ba14a89cb6b963bd3f0c43 for height 17 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 17 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 17, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 17, is last block: false +2025-11-14T18:24:32.009414Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=17 +2025-11-14T18:24:32.009570Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 18 not found (last_processed=17, tip=17) +2025-11-14T18:24:32.058177Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 18) (last_processed_height=16, tip=16) +2025-11-14T18:24:32.058865Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 18) (last_processed_height=16, tip=16) +2025-11-14T18:24:32.059180Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 17 (previous tip: 16) +2025-11-14T18:24:32.059193Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 17 (last_processed_height: 16, tip: 17) +2025-11-14T18:24:32.059277Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 17)], last_processed_height: 16, tip: 17 +2025-11-14T18:24:32.059285Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:32.059802Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 17 (previous tip: 16) +2025-11-14T18:24:32.059809Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 17 (last_processed_height: 16, tip: 17) +2025-11-14T18:24:32.059838Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 17)], last_processed_height: 16, tip: 17 +2025-11-14T18:24:32.059841Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:32.060232Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xb968553d74de341f8309764205b9a1e4dcbf0bf9d6ba14a89cb6b963bd3f0c43 for height 17 +üüüüüüüüüüüüüüüüüüüüüüüüü +2025-11-14T18:24:32.060370Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:177: 55 Handling message Broadcast +COMMITING BLOCK 17 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 17, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 17, is last block: false +2025-11-14T18:24:32.060384Z  INFO ThreadId(37) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=17 +2025-11-14T18:24:32.060526Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 18 not found (last_processed=17, tip=17) +2025-11-14T18:24:32.060771Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xb968553d74de341f8309764205b9a1e4dcbf0bf9d6ba14a89cb6b963bd3f0c43 for height 17 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 17 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 17, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 17, is last block: false +2025-11-14T18:24:32.060884Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=17 +2025-11-14T18:24:32.061021Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 18 not found (last_processed=17, tip=17) +2025-11-14T18:24:32.061875Z  INFO ThreadId(35) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 19) (epoch 0, view 19), parent height: 18 +2025-11-14T18:24:32.061902Z  INFO ThreadId(52) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 19) (epoch 0, view 19), parent height: 18 +2025-11-14T18:24:32.061976Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 19) (epoch 0, view 19), parent height: 18 +2025-11-14T18:24:32.064162Z  INFO ThreadId(38) summit_application::actor: application/src/actor.rs:149: 209 application: Handling message Propose for round Round(0, 20) (epoch 0, view 20), parent height: 19 +2025-11-14T18:24:32.130831Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 19) (last_processed_height=17, tip=17) +2025-11-14T18:24:32.131078Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 19) (last_processed_height=17, tip=17) +2025-11-14T18:24:32.131312Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 18 (previous tip: 17) +2025-11-14T18:24:32.131318Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 18 (last_processed_height: 17, tip: 18) +2025-11-14T18:24:32.131370Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 18)], last_processed_height: 17, tip: 18 +2025-11-14T18:24:32.131373Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:32.131675Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 18 (previous tip: 17) +2025-11-14T18:24:32.131687Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 18 (last_processed_height: 17, tip: 18) +2025-11-14T18:24:32.131726Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 18)], last_processed_height: 17, tip: 18 +2025-11-14T18:24:32.131733Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:32.132463Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xaa28a0c6fec97826321761967e82f787ff77eb070f9457d03d3a4ffececb553d for height 18 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 18 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 18, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 18, is last block: false +2025-11-14T18:24:32.132693Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=18 +2025-11-14T18:24:32.132810Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xaa28a0c6fec97826321761967e82f787ff77eb070f9457d03d3a4ffececb553d for height 18 +2025-11-14T18:24:32.132887Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 19 not found (last_processed=18, tip=18) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 18 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 18, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 18, is last block: false +2025-11-14T18:24:32.132927Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=18 +2025-11-14T18:24:32.133043Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 19 not found (last_processed=18, tip=18) +2025-11-14T18:24:32.182810Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 19) (last_processed_height=17, tip=17) +2025-11-14T18:24:32.183374Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 18 (previous tip: 17) +2025-11-14T18:24:32.183380Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 18 (last_processed_height: 17, tip: 18) +2025-11-14T18:24:32.183418Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 18)], last_processed_height: 17, tip: 18 +2025-11-14T18:24:32.183422Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:32.183632Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 19) (last_processed_height=17, tip=17) +2025-11-14T18:24:32.184399Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 18 (previous tip: 17) +2025-11-14T18:24:32.184405Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 18 (last_processed_height: 17, tip: 18) +2025-11-14T18:24:32.184407Z  INFO ThreadId(37) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xaa28a0c6fec97826321761967e82f787ff77eb070f9457d03d3a4ffececb553d for height 18 +2025-11-14T18:24:32.184440Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 18)], last_processed_height: 17, tip: 18 +2025-11-14T18:24:32.184443Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 18 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 18, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 18, is last block: false +2025-11-14T18:24:32.184541Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=18 +2025-11-14T18:24:32.184695Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 19 not found (last_processed=18, tip=18) +2025-11-14T18:24:32.185175Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xaa28a0c6fec97826321761967e82f787ff77eb070f9457d03d3a4ffececb553d for height 18 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 18 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 18, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 18, is last block: false +2025-11-14T18:24:32.185283Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=18 +2025-11-14T18:24:32.185416Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 19 not found (last_processed=18, tip=18) +2025-11-14T18:24:32.236374Z  INFO ThreadId(35) summit_application::actor: application/src/actor.rs:177: 209 Handling message Broadcast +2025-11-14T18:24:32.250132Z  INFO ThreadId(57) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 20) (epoch 0, view 20), parent height: 19 +2025-11-14T18:24:32.250132Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 20) (epoch 0, view 20), parent height: 19 +2025-11-14T18:24:32.252262Z  INFO ThreadId(52) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 20) (epoch 0, view 20), parent height: 19 +2025-11-14T18:24:32.253045Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:149: 15 application: Handling message Propose for round Round(0, 21) (epoch 0, view 21), parent height: 20 +2025-11-14T18:24:32.310921Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 20) (last_processed_height=18, tip=18) +2025-11-14T18:24:32.311856Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 19 (previous tip: 18) +2025-11-14T18:24:32.311863Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 19 (last_processed_height: 18, tip: 19) +2025-11-14T18:24:32.311915Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 19)], last_processed_height: 18, tip: 19 +2025-11-14T18:24:32.311922Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:32.313057Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xf3ac40b49e2ac2e0aee163f3e7d10426cbdc3733c698975bdbd3fc8fb80ad74f for height 19 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 19 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 19, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 19, is last block: false +2025-11-14T18:24:32.313194Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=19 +2025-11-14T18:24:32.313337Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 20 not found (last_processed=19, tip=19) +2025-11-14T18:24:32.365427Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:177: 15 Handling message Broadcast +2025-11-14T18:24:32.377096Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 20) (last_processed_height=18, tip=18) +2025-11-14T18:24:32.377341Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 20) (last_processed_height=18, tip=18) +2025-11-14T18:24:32.377398Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 20) (last_processed_height=18, tip=18) +2025-11-14T18:24:32.377821Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 19 (previous tip: 18) +2025-11-14T18:24:32.377833Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 19 (last_processed_height: 18, tip: 19) +2025-11-14T18:24:32.377895Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 19)], last_processed_height: 18, tip: 19 +2025-11-14T18:24:32.377904Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:32.377930Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 19 (previous tip: 18) +2025-11-14T18:24:32.377941Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 19 (last_processed_height: 18, tip: 19) +2025-11-14T18:24:32.377945Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 19 (previous tip: 18) +2025-11-14T18:24:32.377958Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 19 (last_processed_height: 18, tip: 19) +2025-11-14T18:24:32.377981Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 19)], last_processed_height: 18, tip: 19 +2025-11-14T18:24:32.377984Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:32.378010Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 19)], last_processed_height: 18, tip: 19 +2025-11-14T18:24:32.378016Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:32.378340Z  INFO ThreadId(56) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 21) (epoch 0, view 21), parent height: 20 +2025-11-14T18:24:32.379412Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xf3ac40b49e2ac2e0aee163f3e7d10426cbdc3733c698975bdbd3fc8fb80ad74f for height 19 +2025-11-14T18:24:32.379460Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 21) (epoch 0, view 21), parent height: 20 +2025-11-14T18:24:32.379526Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xf3ac40b49e2ac2e0aee163f3e7d10426cbdc3733c698975bdbd3fc8fb80ad74f for height 19 +2025-11-14T18:24:32.379555Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xf3ac40b49e2ac2e0aee163f3e7d10426cbdc3733c698975bdbd3fc8fb80ad74f for height 19 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 19 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 19, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 19, is last block: false +2025-11-14T18:24:32.379592Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=19 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 19 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 19, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 19, is last block: false +2025-11-14T18:24:32.379723Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=19 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 19 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 19, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 19, is last block: false +2025-11-14T18:24:32.379779Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=19 +2025-11-14T18:24:32.379807Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 20 not found (last_processed=19, tip=19) +2025-11-14T18:24:32.379922Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 20 not found (last_processed=19, tip=19) +2025-11-14T18:24:32.379949Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 20 not found (last_processed=19, tip=19) +2025-11-14T18:24:32.380207Z  INFO ThreadId(38) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 21) (epoch 0, view 21), parent height: 20 +2025-11-14T18:24:32.381578Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:149: 139 application: Handling message Propose for round Round(0, 22) (epoch 0, view 22), parent height: 21 +2025-11-14T18:24:32.501825Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 21) (last_processed_height=19, tip=19) +2025-11-14T18:24:32.503024Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 20 (previous tip: 19) +2025-11-14T18:24:32.503038Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 20 (last_processed_height: 19, tip: 20) +2025-11-14T18:24:32.503042Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 21) (last_processed_height=19, tip=19) +2025-11-14T18:24:32.503113Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 20)], last_processed_height: 19, tip: 20 +2025-11-14T18:24:32.503121Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:32.503922Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 21) (last_processed_height=19, tip=19) +2025-11-14T18:24:32.503953Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 20 (previous tip: 19) +2025-11-14T18:24:32.503960Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 20 (last_processed_height: 19, tip: 20) +2025-11-14T18:24:32.504036Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 20)], last_processed_height: 19, tip: 20 +2025-11-14T18:24:32.504042Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:32.504064Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 21) (last_processed_height=19, tip=19) +2025-11-14T18:24:32.504434Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x959f4204cd55c00e1ba21dce1945ba0636e8df52430ebf3a6415ba0814f2349f for height 20 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 20 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 20, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 20, is last block: false +2025-11-14T18:24:32.504613Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=20 +2025-11-14T18:24:32.504646Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 20 (previous tip: 19) +2025-11-14T18:24:32.504652Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 20 (last_processed_height: 19, tip: 20) +2025-11-14T18:24:32.504680Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 20 (previous tip: 19) +2025-11-14T18:24:32.504687Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 20 (last_processed_height: 19, tip: 20) +2025-11-14T18:24:32.504716Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 20)], last_processed_height: 19, tip: 20 +2025-11-14T18:24:32.504721Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:32.504743Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 20)], last_processed_height: 19, tip: 20 +2025-11-14T18:24:32.504746Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:32.504822Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 21 not found (last_processed=20, tip=20) +2025-11-14T18:24:32.505127Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x959f4204cd55c00e1ba21dce1945ba0636e8df52430ebf3a6415ba0814f2349f for height 20 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 20 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 20, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 20, is last block: false +2025-11-14T18:24:32.505306Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=20 +2025-11-14T18:24:32.505480Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 21 not found (last_processed=20, tip=20) +2025-11-14T18:24:32.505762Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x959f4204cd55c00e1ba21dce1945ba0636e8df52430ebf3a6415ba0814f2349f for height 20 +2025-11-14T18:24:32.505858Z  INFO ThreadId(37) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x959f4204cd55c00e1ba21dce1945ba0636e8df52430ebf3a6415ba0814f2349f for height 20 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 20 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 20, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 20, is last block: false +2025-11-14T18:24:32.505893Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=20 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 20 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 20, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 20, is last block: false +2025-11-14T18:24:32.505983Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=20 +2025-11-14T18:24:32.506028Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 21 not found (last_processed=20, tip=20) +2025-11-14T18:24:32.506131Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 21 not found (last_processed=20, tip=20) +2025-11-14T18:24:32.556515Z  INFO ThreadId(49) summit_application::actor: application/src/actor.rs:177: 139 Handling message Broadcast +2025-11-14T18:24:32.559513Z  INFO ThreadId(57) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 22) (epoch 0, view 22), parent height: 21 +2025-11-14T18:24:32.559630Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 22) (epoch 0, view 22), parent height: 21 +2025-11-14T18:24:32.560103Z  INFO ThreadId(36) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 22) (epoch 0, view 22), parent height: 21 +2025-11-14T18:24:32.561861Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:149: 55 application: Handling message Propose for round Round(0, 23) (epoch 0, view 23), parent height: 22 +2025-11-14T18:24:32.630338Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 22) (last_processed_height=20, tip=20) +2025-11-14T18:24:32.630501Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 22) (last_processed_height=20, tip=20) +2025-11-14T18:24:32.631227Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 22) (last_processed_height=20, tip=20) +2025-11-14T18:24:32.631393Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 21 (previous tip: 20) +2025-11-14T18:24:32.631405Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 21 (last_processed_height: 20, tip: 21) +2025-11-14T18:24:32.631471Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 21)], last_processed_height: 20, tip: 21 +2025-11-14T18:24:32.631477Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:32.631543Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 22) (last_processed_height=20, tip=20) +2025-11-14T18:24:32.631598Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 21 (previous tip: 20) +2025-11-14T18:24:32.631629Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 21 (last_processed_height: 20, tip: 21) +2025-11-14T18:24:32.631727Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 21)], last_processed_height: 20, tip: 21 +2025-11-14T18:24:32.631743Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:32.631756Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 21 (previous tip: 20) +2025-11-14T18:24:32.631762Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 21 (last_processed_height: 20, tip: 21) +2025-11-14T18:24:32.631807Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 21)], last_processed_height: 20, tip: 21 +2025-11-14T18:24:32.631810Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:32.632258Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 21 (previous tip: 20) +2025-11-14T18:24:32.632266Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 21 (last_processed_height: 20, tip: 21) +2025-11-14T18:24:32.632314Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 21)], last_processed_height: 20, tip: 21 +2025-11-14T18:24:32.632320Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:32.632734Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7be2886dedd167f7c4a3cb2d2bb48b80bb7ccb7c1fe323296e3e03579408c8dc for height 21 +2025-11-14T18:24:32.632823Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7be2886dedd167f7c4a3cb2d2bb48b80bb7ccb7c1fe323296e3e03579408c8dc for height 21 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 21 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 21, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 21, is last block: false +2025-11-14T18:24:32.632925Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=21 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 21 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 21, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 21, is last block: false +2025-11-14T18:24:32.633008Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=21 +2025-11-14T18:24:32.633101Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 22 not found (last_processed=21, tip=21) +2025-11-14T18:24:32.633259Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7be2886dedd167f7c4a3cb2d2bb48b80bb7ccb7c1fe323296e3e03579408c8dc for height 21 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 21 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 21, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 21, is last block: false +2025-11-14T18:24:32.633411Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=21 +2025-11-14T18:24:32.633417Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 22 not found (last_processed=21, tip=21) +2025-11-14T18:24:32.633489Z  INFO ThreadId(36) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7be2886dedd167f7c4a3cb2d2bb48b80bb7ccb7c1fe323296e3e03579408c8dc for height 21 +2025-11-14T18:24:32.633565Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 22 not found (last_processed=21, tip=21) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 21 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 21, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 21, is last block: false +2025-11-14T18:24:32.633610Z  INFO ThreadId(36) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=21 +2025-11-14T18:24:32.633784Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 22 not found (last_processed=21, tip=21) +2025-11-14T18:24:32.684566Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:177: 55 Handling message Broadcast +2025-11-14T18:24:32.686704Z  INFO ThreadId(38) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 23) (epoch 0, view 23), parent height: 22 +2025-11-14T18:24:32.686984Z  INFO ThreadId(49) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 23) (epoch 0, view 23), parent height: 22 +2025-11-14T18:24:32.687006Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 23) (epoch 0, view 23), parent height: 22 +2025-11-14T18:24:32.689324Z  INFO ThreadId(37) summit_application::actor: application/src/actor.rs:149: 209 application: Handling message Propose for round Round(0, 24) (epoch 0, view 24), parent height: 23 +2025-11-14T18:24:32.755834Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 23) (last_processed_height=21, tip=21) +2025-11-14T18:24:32.755985Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 23) (last_processed_height=21, tip=21) +2025-11-14T18:24:32.756807Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 22 (previous tip: 21) +2025-11-14T18:24:32.756820Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 22 (last_processed_height: 21, tip: 22) +2025-11-14T18:24:32.756862Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 22)], last_processed_height: 21, tip: 22 +2025-11-14T18:24:32.756869Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:32.756929Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 22 (previous tip: 21) +2025-11-14T18:24:32.756935Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 22 (last_processed_height: 21, tip: 22) +2025-11-14T18:24:32.756981Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 22)], last_processed_height: 21, tip: 22 +2025-11-14T18:24:32.756983Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:32.757909Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x911e4e1e62d37eff29983c36e42b17de84ea8f3756ce8639c213d777b0eec365 for height 22 +2025-11-14T18:24:32.757909Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x911e4e1e62d37eff29983c36e42b17de84ea8f3756ce8639c213d777b0eec365 for height 22 +üüüüüüüüüüüüüüüüüüüüüüüüü +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 22 to reth +COMMITING BLOCK 22 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 22, is penultimate block: false +epoch_num_of_blocks: 50, new_height: 22, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 22, is last block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 22, is last block: false +2025-11-14T18:24:32.758049Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=22 +2025-11-14T18:24:32.758054Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=22 +2025-11-14T18:24:32.758188Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 23 not found (last_processed=22, tip=22) +2025-11-14T18:24:32.758197Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 23 not found (last_processed=22, tip=22) +2025-11-14T18:24:32.808231Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 23) (last_processed_height=21, tip=21) +2025-11-14T18:24:32.808684Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 23) (last_processed_height=21, tip=21) +2025-11-14T18:24:32.809260Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 22 (previous tip: 21) +2025-11-14T18:24:32.809274Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 22 (last_processed_height: 21, tip: 22) +2025-11-14T18:24:32.809332Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 22)], last_processed_height: 21, tip: 22 +2025-11-14T18:24:32.809339Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:32.809782Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 22 (previous tip: 21) +2025-11-14T18:24:32.809788Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 22 (last_processed_height: 21, tip: 22) +2025-11-14T18:24:32.809824Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 22)], last_processed_height: 21, tip: 22 +2025-11-14T18:24:32.809828Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:32.810227Z  INFO ThreadId(36) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x911e4e1e62d37eff29983c36e42b17de84ea8f3756ce8639c213d777b0eec365 for height 22 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 22 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 22, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 22, is last block: false +2025-11-14T18:24:32.810388Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=22 +2025-11-14T18:24:32.810547Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 23 not found (last_processed=22, tip=22) +2025-11-14T18:24:32.810691Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x911e4e1e62d37eff29983c36e42b17de84ea8f3756ce8639c213d777b0eec365 for height 22 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 22 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 22, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 22, is last block: false +2025-11-14T18:24:32.810805Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=22 +2025-11-14T18:24:32.810954Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 23 not found (last_processed=22, tip=22) +2025-11-14T18:24:32.861306Z  INFO ThreadId(38) summit_application::actor: application/src/actor.rs:177: 209 Handling message Broadcast +2025-11-14T18:24:32.875749Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 24) (epoch 0, view 24), parent height: 23 +2025-11-14T18:24:32.875887Z  INFO ThreadId(56) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 24) (epoch 0, view 24), parent height: 23 +2025-11-14T18:24:32.876287Z  INFO ThreadId(52) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 24) (epoch 0, view 24), parent height: 23 +2025-11-14T18:24:32.879850Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:149: 15 application: Handling message Propose for round Round(0, 25) (epoch 0, view 25), parent height: 24 +Node 0 at height 22 +2025-11-14T18:24:32.933619Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 24) (last_processed_height=22, tip=22) +2025-11-14T18:24:32.933797Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 24) (last_processed_height=22, tip=22) +2025-11-14T18:24:32.934302Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 24) (last_processed_height=22, tip=22) +2025-11-14T18:24:32.934663Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 23 (previous tip: 22) +2025-11-14T18:24:32.934674Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 23 (previous tip: 22) +2025-11-14T18:24:32.934675Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 23 (last_processed_height: 22, tip: 23) +2025-11-14T18:24:32.934679Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 23 (last_processed_height: 22, tip: 23) +2025-11-14T18:24:32.934719Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 23)], last_processed_height: 22, tip: 23 +2025-11-14T18:24:32.934722Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:32.934776Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 23)], last_processed_height: 22, tip: 23 +2025-11-14T18:24:32.934783Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:32.934872Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 24) (last_processed_height=22, tip=22) +2025-11-14T18:24:32.935004Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 23 (previous tip: 22) +2025-11-14T18:24:32.935010Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 23 (last_processed_height: 22, tip: 23) +2025-11-14T18:24:32.935046Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 23)], last_processed_height: 22, tip: 23 +2025-11-14T18:24:32.935049Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:32.935365Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 23 (previous tip: 22) +2025-11-14T18:24:32.935374Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 23 (last_processed_height: 22, tip: 23) +2025-11-14T18:24:32.935427Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 23)], last_processed_height: 22, tip: 23 +2025-11-14T18:24:32.935439Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:32.935926Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd8212bc5ba451deefe41d8b8fe1b7a0534b439cc58d2553a01a6423af4d944e2 for height 23 +2025-11-14T18:24:32.935972Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd8212bc5ba451deefe41d8b8fe1b7a0534b439cc58d2553a01a6423af4d944e2 for height 23 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 23 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 23, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 23, is last block: false +2025-11-14T18:24:32.936154Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=23 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 23 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 23, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 23, is last block: false +2025-11-14T18:24:32.936179Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=23 +2025-11-14T18:24:32.936325Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 24 not found (last_processed=23, tip=23) +2025-11-14T18:24:32.936437Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 24 not found (last_processed=23, tip=23) +2025-11-14T18:24:32.936562Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd8212bc5ba451deefe41d8b8fe1b7a0534b439cc58d2553a01a6423af4d944e2 for height 23 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 23 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 23, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 23, is last block: false +2025-11-14T18:24:32.936703Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=23 +2025-11-14T18:24:32.936743Z  INFO ThreadId(37) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd8212bc5ba451deefe41d8b8fe1b7a0534b439cc58d2553a01a6423af4d944e2 for height 23 +2025-11-14T18:24:32.936847Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 24 not found (last_processed=23, tip=23) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 23 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 23, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 23, is last block: false +2025-11-14T18:24:32.936877Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=23 +2025-11-14T18:24:32.937026Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 24 not found (last_processed=23, tip=23) +2025-11-14T18:24:32.988121Z  INFO ThreadId(43) summit_application::actor: application/src/actor.rs:177: 15 Handling message Broadcast +2025-11-14T18:24:33.005401Z  INFO ThreadId(56) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 25) (epoch 0, view 25), parent height: 24 +2025-11-14T18:24:33.005740Z  INFO ThreadId(38) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 25) (epoch 0, view 25), parent height: 24 +2025-11-14T18:24:33.007433Z  INFO ThreadId(52) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 25) (epoch 0, view 25), parent height: 24 +2025-11-14T18:24:33.007668Z  INFO ThreadId(52) summit_application::actor: application/src/actor.rs:149: 139 application: Handling message Propose for round Round(0, 26) (epoch 0, view 26), parent height: 25 +2025-11-14T18:24:33.126508Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 25) (last_processed_height=23, tip=23) +2025-11-14T18:24:33.126605Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 25) (last_processed_height=23, tip=23) +2025-11-14T18:24:33.127218Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 25) (last_processed_height=23, tip=23) +2025-11-14T18:24:33.127305Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 24 (previous tip: 23) +2025-11-14T18:24:33.127311Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 24 (last_processed_height: 23, tip: 24) +2025-11-14T18:24:33.127365Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 24)], last_processed_height: 23, tip: 24 +2025-11-14T18:24:33.127369Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:33.127387Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 24 (previous tip: 23) +2025-11-14T18:24:33.127396Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 24 (last_processed_height: 23, tip: 24) +2025-11-14T18:24:33.127446Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 24)], last_processed_height: 23, tip: 24 +2025-11-14T18:24:33.127450Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:33.127520Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 25) (last_processed_height=23, tip=23) +2025-11-14T18:24:33.127881Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 24 (previous tip: 23) +2025-11-14T18:24:33.127887Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 24 (last_processed_height: 23, tip: 24) +2025-11-14T18:24:33.127961Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 24)], last_processed_height: 23, tip: 24 +2025-11-14T18:24:33.127968Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:33.128142Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 24 (previous tip: 23) +2025-11-14T18:24:33.128149Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 24 (last_processed_height: 23, tip: 24) +2025-11-14T18:24:33.128191Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 24)], last_processed_height: 23, tip: 24 +2025-11-14T18:24:33.128196Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:33.128629Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7d84f44c4d56ad326d971cae8df539ef9f85727d41afd27a6a7d787f4389a708 for height 24 +2025-11-14T18:24:33.128734Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7d84f44c4d56ad326d971cae8df539ef9f85727d41afd27a6a7d787f4389a708 for height 24 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 24 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 24, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 24, is last block: false +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 24 to reth +2025-11-14T18:24:33.128906Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=24 +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 24, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 24, is last block: false +2025-11-14T18:24:33.128917Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=24 +2025-11-14T18:24:33.129224Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7d84f44c4d56ad326d971cae8df539ef9f85727d41afd27a6a7d787f4389a708 for height 24 +2025-11-14T18:24:33.129243Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 25 not found (last_processed=24, tip=24) +2025-11-14T18:24:33.129267Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7d84f44c4d56ad326d971cae8df539ef9f85727d41afd27a6a7d787f4389a708 for height 24 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 24 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 24, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 24, is last block: false +2025-11-14T18:24:33.129391Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=24 +2025-11-14T18:24:33.129444Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 25 not found (last_processed=24, tip=24) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 24 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 24, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 24, is last block: false +2025-11-14T18:24:33.129462Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=24 +2025-11-14T18:24:33.129587Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 25 not found (last_processed=24, tip=24) +2025-11-14T18:24:33.129619Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 25 not found (last_processed=24, tip=24) +2025-11-14T18:24:33.180900Z  INFO ThreadId(52) summit_application::actor: application/src/actor.rs:177: 139 Handling message Broadcast +2025-11-14T18:24:33.183550Z  INFO ThreadId(37) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 26) (epoch 0, view 26), parent height: 25 +2025-11-14T18:24:33.183870Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 26) (epoch 0, view 26), parent height: 25 +2025-11-14T18:24:33.184512Z  INFO ThreadId(57) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 26) (epoch 0, view 26), parent height: 25 +2025-11-14T18:24:33.187673Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:149: 55 application: Handling message Propose for round Round(0, 27) (epoch 0, view 27), parent height: 26 +2025-11-14T18:24:33.252368Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 26) (last_processed_height=24, tip=24) +2025-11-14T18:24:33.252506Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 26) (last_processed_height=24, tip=24) +2025-11-14T18:24:33.253561Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 25 (previous tip: 24) +2025-11-14T18:24:33.253575Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 25 (last_processed_height: 24, tip: 25) +2025-11-14T18:24:33.253655Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 25)], last_processed_height: 24, tip: 25 +2025-11-14T18:24:33.253659Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:33.253702Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 25 (previous tip: 24) +2025-11-14T18:24:33.253707Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 25 (last_processed_height: 24, tip: 25) +2025-11-14T18:24:33.253742Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 25)], last_processed_height: 24, tip: 25 +2025-11-14T18:24:33.253745Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:33.254056Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 26) (last_processed_height=24, tip=24) +2025-11-14T18:24:33.254282Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 26) (last_processed_height=24, tip=24) +2025-11-14T18:24:33.254682Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 25 (previous tip: 24) +2025-11-14T18:24:33.254688Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 25 (last_processed_height: 24, tip: 25) +2025-11-14T18:24:33.254705Z  INFO ThreadId(37) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd819f3d88cb19bb49d5a9adf1b232acb1a3746141c7a762728b2f331a822f9a3 for height 25 +2025-11-14T18:24:33.254726Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 25)], last_processed_height: 24, tip: 25 +2025-11-14T18:24:33.254729Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:33.254838Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd819f3d88cb19bb49d5a9adf1b232acb1a3746141c7a762728b2f331a822f9a3 for height 25 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 25 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 25, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 25, is last block: false +2025-11-14T18:24:33.254878Z  INFO ThreadId(36) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=25 +2025-11-14T18:24:33.254963Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 25 (previous tip: 24) +2025-11-14T18:24:33.254970Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 25 (last_processed_height: 24, tip: 25) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 25 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 25, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 25, is last block: false +2025-11-14T18:24:33.254992Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=25 +2025-11-14T18:24:33.255016Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 25)], last_processed_height: 24, tip: 25 +2025-11-14T18:24:33.255021Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:33.255031Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 26 not found (last_processed=25, tip=25) +2025-11-14T18:24:33.255126Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 26 not found (last_processed=25, tip=25) +2025-11-14T18:24:33.255777Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd819f3d88cb19bb49d5a9adf1b232acb1a3746141c7a762728b2f331a822f9a3 for height 25 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 25 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 25, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 25, is last block: false +2025-11-14T18:24:33.255928Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=25 +2025-11-14T18:24:33.256015Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd819f3d88cb19bb49d5a9adf1b232acb1a3746141c7a762728b2f331a822f9a3 for height 25 +2025-11-14T18:24:33.256085Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 26 not found (last_processed=25, tip=25) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 25 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 25, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 25, is last block: false +2025-11-14T18:24:33.256129Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=25 +2025-11-14T18:24:33.256255Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 26 not found (last_processed=25, tip=25) +2025-11-14T18:24:33.308147Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:177: 55 Handling message Broadcast +2025-11-14T18:24:33.310650Z  INFO ThreadId(49) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 27) (epoch 0, view 27), parent height: 26 +2025-11-14T18:24:33.311203Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 27) (epoch 0, view 27), parent height: 26 +2025-11-14T18:24:33.311717Z  INFO ThreadId(37) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 27) (epoch 0, view 27), parent height: 26 +2025-11-14T18:24:33.313666Z  INFO ThreadId(36) summit_application::actor: application/src/actor.rs:149: 209 application: Handling message Propose for round Round(0, 28) (epoch 0, view 28), parent height: 27 +2025-11-14T18:24:33.379936Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 27) (last_processed_height=25, tip=25) +2025-11-14T18:24:33.380080Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 27) (last_processed_height=25, tip=25) +2025-11-14T18:24:33.380462Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 26 (previous tip: 25) +2025-11-14T18:24:33.380467Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 26 (last_processed_height: 25, tip: 26) +2025-11-14T18:24:33.380505Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 26)], last_processed_height: 25, tip: 26 +2025-11-14T18:24:33.380509Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:33.380523Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 26 (previous tip: 25) +2025-11-14T18:24:33.380528Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 26 (last_processed_height: 25, tip: 26) +2025-11-14T18:24:33.380552Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 26)], last_processed_height: 25, tip: 26 +2025-11-14T18:24:33.380555Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:33.380914Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 27) (last_processed_height=25, tip=25) +2025-11-14T18:24:33.381552Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 27) (last_processed_height=25, tip=25) +2025-11-14T18:24:33.381556Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x94df031dbbe62e1069a9e1d8f38264c5583a5953411681d4c0a1c394b32e8627 for height 26 +2025-11-14T18:24:33.381644Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 26 (previous tip: 25) +2025-11-14T18:24:33.381650Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 26 (last_processed_height: 25, tip: 26) +2025-11-14T18:24:33.381697Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 26)], last_processed_height: 25, tip: 26 +2025-11-14T18:24:33.381702Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 26 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 26, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 26, is last block: false +2025-11-14T18:24:33.381775Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=26 +2025-11-14T18:24:33.381828Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x94df031dbbe62e1069a9e1d8f38264c5583a5953411681d4c0a1c394b32e8627 for height 26 +2025-11-14T18:24:33.381936Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 27 not found (last_processed=26, tip=26) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 26 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 26, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 26, is last block: false +2025-11-14T18:24:33.381962Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=26 +2025-11-14T18:24:33.382109Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 27 not found (last_processed=26, tip=26) +2025-11-14T18:24:33.382165Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 26 (previous tip: 25) +2025-11-14T18:24:33.382173Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 26 (last_processed_height: 25, tip: 26) +2025-11-14T18:24:33.382215Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 26)], last_processed_height: 25, tip: 26 +2025-11-14T18:24:33.382218Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:33.382510Z  INFO ThreadId(37) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x94df031dbbe62e1069a9e1d8f38264c5583a5953411681d4c0a1c394b32e8627 for height 26 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 26 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 26, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 26, is last block: false +2025-11-14T18:24:33.382639Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=26 +2025-11-14T18:24:33.382803Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 27 not found (last_processed=26, tip=26) +2025-11-14T18:24:33.382998Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x94df031dbbe62e1069a9e1d8f38264c5583a5953411681d4c0a1c394b32e8627 for height 26 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 26 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 26, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 26, is last block: false +2025-11-14T18:24:33.383118Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=26 +2025-11-14T18:24:33.383277Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 27 not found (last_processed=26, tip=26) +2025-11-14T18:24:33.434488Z  INFO ThreadId(37) summit_application::actor: application/src/actor.rs:177: 209 Handling message Broadcast +2025-11-14T18:24:33.509932Z  INFO ThreadId(57) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 28) (epoch 0, view 28), parent height: 27 +2025-11-14T18:24:33.510153Z  INFO ThreadId(43) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 28) (epoch 0, view 28), parent height: 27 +2025-11-14T18:24:33.510181Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 28) (epoch 0, view 28), parent height: 27 +2025-11-14T18:24:33.512746Z  INFO ThreadId(43) summit_application::actor: application/src/actor.rs:149: 15 application: Handling message Propose for round Round(0, 29) (epoch 0, view 29), parent height: 28 +2025-11-14T18:24:33.558145Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 28) (last_processed_height=26, tip=26) +2025-11-14T18:24:33.558383Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 28) (last_processed_height=26, tip=26) +2025-11-14T18:24:33.559400Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 27 (previous tip: 26) +2025-11-14T18:24:33.559415Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 27 (last_processed_height: 26, tip: 27) +2025-11-14T18:24:33.559458Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 27 (previous tip: 26) +2025-11-14T18:24:33.559499Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 27)], last_processed_height: 26, tip: 27 +2025-11-14T18:24:33.559507Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:33.559508Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 27 (last_processed_height: 26, tip: 27) +2025-11-14T18:24:33.559569Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 27)], last_processed_height: 26, tip: 27 +2025-11-14T18:24:33.559576Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:33.559932Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 28) (last_processed_height=26, tip=26) +2025-11-14T18:24:33.560244Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 28) (last_processed_height=26, tip=26) +2025-11-14T18:24:33.560634Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xf031cee2f8370b972a723b5ad86b15df3ab9b50f505ea04dbd41eaba385a5b99 for height 27 +2025-11-14T18:24:33.560634Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xf031cee2f8370b972a723b5ad86b15df3ab9b50f505ea04dbd41eaba385a5b99 for height 27 +2025-11-14T18:24:33.560640Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 27 (previous tip: 26) +2025-11-14T18:24:33.560651Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 27 (last_processed_height: 26, tip: 27) +2025-11-14T18:24:33.560697Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 27)], last_processed_height: 26, tip: 27 +2025-11-14T18:24:33.560700Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 27 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 27, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 27, is last block: false +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 27 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 27, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 27, is last block: false +2025-11-14T18:24:33.560801Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=27 +2025-11-14T18:24:33.560804Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=27 +2025-11-14T18:24:33.560870Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 27 (previous tip: 26) +2025-11-14T18:24:33.560876Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 27 (last_processed_height: 26, tip: 27) +2025-11-14T18:24:33.560917Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 27)], last_processed_height: 26, tip: 27 +2025-11-14T18:24:33.560921Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:33.560961Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 28 not found (last_processed=27, tip=27) +2025-11-14T18:24:33.560976Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 28 not found (last_processed=27, tip=27) +2025-11-14T18:24:33.561920Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xf031cee2f8370b972a723b5ad86b15df3ab9b50f505ea04dbd41eaba385a5b99 for height 27 +2025-11-14T18:24:33.561931Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xf031cee2f8370b972a723b5ad86b15df3ab9b50f505ea04dbd41eaba385a5b99 for height 27 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 27 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 27, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 27, is last block: false +üüüüüüüüüüüüüüüüüüüüüüüüü +2025-11-14T18:24:33.562051Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=27 +COMMITING BLOCK 27 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 27, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 27, is last block: false +2025-11-14T18:24:33.562062Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=27 +2025-11-14T18:24:33.562207Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 28 not found (last_processed=27, tip=27) +2025-11-14T18:24:33.562210Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 28 not found (last_processed=27, tip=27) +2025-11-14T18:24:33.611976Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:177: 15 Handling message Broadcast +2025-11-14T18:24:33.631394Z  INFO ThreadId(57) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 29) (epoch 0, view 29), parent height: 28 +2025-11-14T18:24:33.631478Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 29) (epoch 0, view 29), parent height: 28 +2025-11-14T18:24:33.631496Z  INFO ThreadId(35) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 29) (epoch 0, view 29), parent height: 28 +2025-11-14T18:24:33.633919Z  INFO ThreadId(52) summit_application::actor: application/src/actor.rs:149: 139 application: Handling message Propose for round Round(0, 30) (epoch 0, view 30), parent height: 29 +2025-11-14T18:24:33.684530Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 29) (last_processed_height=27, tip=27) +2025-11-14T18:24:33.685236Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 29) (last_processed_height=27, tip=27) +2025-11-14T18:24:33.685757Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 28 (previous tip: 27) +2025-11-14T18:24:33.685763Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 28 (last_processed_height: 27, tip: 28) +2025-11-14T18:24:33.685806Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 28)], last_processed_height: 27, tip: 28 +2025-11-14T18:24:33.685810Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:33.686343Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 28 (previous tip: 27) +2025-11-14T18:24:33.686355Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 28 (last_processed_height: 27, tip: 28) +2025-11-14T18:24:33.686404Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 28)], last_processed_height: 27, tip: 28 +2025-11-14T18:24:33.686414Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:33.686816Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x385ea2bd92930c13deb1898f1aca845611d84e39ec30ae101a172d1c7d65df7f for height 28 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 28 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 28, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 28, is last block: false +2025-11-14T18:24:33.686971Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=28 +2025-11-14T18:24:33.687153Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 29 not found (last_processed=28, tip=28) +2025-11-14T18:24:33.687289Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x385ea2bd92930c13deb1898f1aca845611d84e39ec30ae101a172d1c7d65df7f for height 28 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 28 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 28, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 28, is last block: false +2025-11-14T18:24:33.687407Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=28 +2025-11-14T18:24:33.687522Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 29 not found (last_processed=28, tip=28) +2025-11-14T18:24:33.751011Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 29) (last_processed_height=27, tip=27) +2025-11-14T18:24:33.751140Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 29) (last_processed_height=27, tip=27) +2025-11-14T18:24:33.751852Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 28 (previous tip: 27) +2025-11-14T18:24:33.751859Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 28 (last_processed_height: 27, tip: 28) +2025-11-14T18:24:33.751895Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 28)], last_processed_height: 27, tip: 28 +2025-11-14T18:24:33.751903Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:33.752348Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 28 (previous tip: 27) +2025-11-14T18:24:33.752362Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 28 (last_processed_height: 27, tip: 28) +2025-11-14T18:24:33.752411Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 28)], last_processed_height: 27, tip: 28 +2025-11-14T18:24:33.752423Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:33.752916Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x385ea2bd92930c13deb1898f1aca845611d84e39ec30ae101a172d1c7d65df7f for height 28 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 28 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 28, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 28, is last block: false +2025-11-14T18:24:33.753061Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=28 +2025-11-14T18:24:33.753225Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 29 not found (last_processed=28, tip=28) +2025-11-14T18:24:33.753491Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x385ea2bd92930c13deb1898f1aca845611d84e39ec30ae101a172d1c7d65df7f for height 28 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 28 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 28, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 28, is last block: false +2025-11-14T18:24:33.753603Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=28 +2025-11-14T18:24:33.753734Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 29 not found (last_processed=28, tip=28) +2025-11-14T18:24:33.804922Z  INFO ThreadId(49) summit_application::actor: application/src/actor.rs:177: 139 Handling message Broadcast +2025-11-14T18:24:33.807771Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 30) (epoch 0, view 30), parent height: 29 +2025-11-14T18:24:33.808360Z  INFO ThreadId(38) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 30) (epoch 0, view 30), parent height: 29 +2025-11-14T18:24:33.808366Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 30) (epoch 0, view 30), parent height: 29 +2025-11-14T18:24:33.811445Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:149: 55 application: Handling message Propose for round Round(0, 31) (epoch 0, view 31), parent height: 30 +2025-11-14T18:24:33.813489Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 30) (last_processed_height=28, tip=28) +2025-11-14T18:24:33.813601Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 30) (last_processed_height=28, tip=28) +2025-11-14T18:24:33.814037Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 29 (previous tip: 28) +2025-11-14T18:24:33.814044Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 29 (last_processed_height: 28, tip: 29) +2025-11-14T18:24:33.814044Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 29 (previous tip: 28) +2025-11-14T18:24:33.814050Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 29 (last_processed_height: 28, tip: 29) +2025-11-14T18:24:33.814082Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 29)], last_processed_height: 28, tip: 29 +2025-11-14T18:24:33.814079Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 29)], last_processed_height: 28, tip: 29 +2025-11-14T18:24:33.814084Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:33.814085Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:33.815353Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xee652a30f017807599d6a54dfce2c993a0145310bcd6874525cf8b85e571c60e for height 29 +2025-11-14T18:24:33.815465Z  INFO ThreadId(37) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xee652a30f017807599d6a54dfce2c993a0145310bcd6874525cf8b85e571c60e for height 29 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 29 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 29, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 29, is last block: false +2025-11-14T18:24:33.815618Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=29 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 29 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 29, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 29, is last block: false +2025-11-14T18:24:33.815658Z  INFO ThreadId(37) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=29 +2025-11-14T18:24:33.815821Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 30 not found (last_processed=29, tip=29) +2025-11-14T18:24:33.815845Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 30 not found (last_processed=29, tip=29) +2025-11-14T18:24:33.876245Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 30) (last_processed_height=28, tip=28) +2025-11-14T18:24:33.876776Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 30) (last_processed_height=28, tip=28) +2025-11-14T18:24:33.877461Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 29 (previous tip: 28) +2025-11-14T18:24:33.877477Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 29 (last_processed_height: 28, tip: 29) +2025-11-14T18:24:33.877553Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 29)], last_processed_height: 28, tip: 29 +2025-11-14T18:24:33.877560Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:33.877733Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 29 (previous tip: 28) +2025-11-14T18:24:33.877738Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 29 (last_processed_height: 28, tip: 29) +2025-11-14T18:24:33.877771Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 29)], last_processed_height: 28, tip: 29 +2025-11-14T18:24:33.877774Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:33.878618Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xee652a30f017807599d6a54dfce2c993a0145310bcd6874525cf8b85e571c60e for height 29 +2025-11-14T18:24:33.878667Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xee652a30f017807599d6a54dfce2c993a0145310bcd6874525cf8b85e571c60e for height 29 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 29 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 29, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 29, is last block: false +2025-11-14T18:24:33.878762Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=29 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 29 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 29, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 29, is last block: false +2025-11-14T18:24:33.878810Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=29 +2025-11-14T18:24:33.878922Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 30 not found (last_processed=29, tip=29) +2025-11-14T18:24:33.878958Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 30 not found (last_processed=29, tip=29) +Node 0 at height 29 +2025-11-14T18:24:33.930523Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:177: 55 Handling message Broadcast +2025-11-14T18:24:33.934743Z  INFO ThreadId(36) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 31) (epoch 0, view 31), parent height: 30 +2025-11-14T18:24:33.934743Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 31) (epoch 0, view 31), parent height: 30 +2025-11-14T18:24:33.935711Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 31) (epoch 0, view 31), parent height: 30 +2025-11-14T18:24:33.937744Z  INFO ThreadId(37) summit_application::actor: application/src/actor.rs:149: 209 application: Handling message Propose for round Round(0, 32) (epoch 0, view 32), parent height: 31 +2025-11-14T18:24:34.000883Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 31) (last_processed_height=29, tip=29) +2025-11-14T18:24:34.001019Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 31) (last_processed_height=29, tip=29) +2025-11-14T18:24:34.001593Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 30 (previous tip: 29) +2025-11-14T18:24:34.001600Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 30 (last_processed_height: 29, tip: 30) +2025-11-14T18:24:34.001650Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 30)], last_processed_height: 29, tip: 30 +2025-11-14T18:24:34.001654Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:34.001906Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 30 (previous tip: 29) +2025-11-14T18:24:34.001919Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 30 (last_processed_height: 29, tip: 30) +2025-11-14T18:24:34.001970Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 30)], last_processed_height: 29, tip: 30 +2025-11-14T18:24:34.001977Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:34.002295Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 31) (last_processed_height=29, tip=29) +2025-11-14T18:24:34.002790Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 31) (last_processed_height=29, tip=29) +2025-11-14T18:24:34.003147Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x386520c0a37a2cfff715cf56cbcb311a3e21606cdb87f75e3ab77eaf1fbe0aa4 for height 30 +2025-11-14T18:24:34.003153Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x386520c0a37a2cfff715cf56cbcb311a3e21606cdb87f75e3ab77eaf1fbe0aa4 for height 30 +2025-11-14T18:24:34.003169Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 30 (previous tip: 29) +2025-11-14T18:24:34.003175Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 30 (last_processed_height: 29, tip: 30) +2025-11-14T18:24:34.003268Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 30)], last_processed_height: 29, tip: 30 +2025-11-14T18:24:34.003274Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 30 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 30, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 30, is last block: false +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 30 to reth +2025-11-14T18:24:34.003312Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=30 +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 30, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 30, is last block: false +2025-11-14T18:24:34.003320Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=30 +2025-11-14T18:24:34.003379Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 30 (previous tip: 29) +2025-11-14T18:24:34.003384Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 30 (last_processed_height: 29, tip: 30) +2025-11-14T18:24:34.003414Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 30)], last_processed_height: 29, tip: 30 +2025-11-14T18:24:34.003417Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:34.003472Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 31 not found (last_processed=30, tip=30) +2025-11-14T18:24:34.003479Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 31 not found (last_processed=30, tip=30) +2025-11-14T18:24:34.004201Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x386520c0a37a2cfff715cf56cbcb311a3e21606cdb87f75e3ab77eaf1fbe0aa4 for height 30 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 30 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 30, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 30, is last block: false +2025-11-14T18:24:34.004352Z  INFO ThreadId(36) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x386520c0a37a2cfff715cf56cbcb311a3e21606cdb87f75e3ab77eaf1fbe0aa4 for height 30 +2025-11-14T18:24:34.004352Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=30 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 30 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 30, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 30, is last block: false +2025-11-14T18:24:34.004479Z  INFO ThreadId(37) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=30 +2025-11-14T18:24:34.004495Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 31 not found (last_processed=30, tip=30) +2025-11-14T18:24:34.004632Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 31 not found (last_processed=30, tip=30) +2025-11-14T18:24:34.056345Z  INFO ThreadId(38) summit_application::actor: application/src/actor.rs:177: 209 Handling message Broadcast +2025-11-14T18:24:34.058913Z  INFO ThreadId(52) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 32) (epoch 0, view 32), parent height: 31 +2025-11-14T18:24:34.059457Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 32) (epoch 0, view 32), parent height: 31 +2025-11-14T18:24:34.059502Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 32) (epoch 0, view 32), parent height: 31 +2025-11-14T18:24:34.061103Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:149: 15 application: Handling message Propose for round Round(0, 33) (epoch 0, view 33), parent height: 32 +2025-11-14T18:24:34.129951Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 32) (last_processed_height=30, tip=30) +2025-11-14T18:24:34.130269Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 32) (last_processed_height=30, tip=30) +2025-11-14T18:24:34.130683Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 31 (previous tip: 30) +2025-11-14T18:24:34.130705Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 31 (last_processed_height: 30, tip: 31) +2025-11-14T18:24:34.130768Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 31)], last_processed_height: 30, tip: 31 +2025-11-14T18:24:34.130772Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:34.130921Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 31 (previous tip: 30) +2025-11-14T18:24:34.130926Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 31 (last_processed_height: 30, tip: 31) +2025-11-14T18:24:34.130959Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 31)], last_processed_height: 30, tip: 31 +2025-11-14T18:24:34.130962Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:34.131989Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd4656db24d743f49eadb9189c8542943b0b5ea9172a3ab06cbf0817bfa002b02 for height 31 +2025-11-14T18:24:34.131989Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd4656db24d743f49eadb9189c8542943b0b5ea9172a3ab06cbf0817bfa002b02 for height 31 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 31 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 31, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 31, is last block: false +2025-11-14T18:24:34.132129Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=31 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 31 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 31, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 31, is last block: false +2025-11-14T18:24:34.132140Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=31 +2025-11-14T18:24:34.132280Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 32 not found (last_processed=31, tip=31) +2025-11-14T18:24:34.132284Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 32 not found (last_processed=31, tip=31) +2025-11-14T18:24:34.183434Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 32) (last_processed_height=30, tip=30) +2025-11-14T18:24:34.183517Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 32) (last_processed_height=30, tip=30) +2025-11-14T18:24:34.183992Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 31 (previous tip: 30) +2025-11-14T18:24:34.183997Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 31 (last_processed_height: 30, tip: 31) +2025-11-14T18:24:34.184034Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 31)], last_processed_height: 30, tip: 31 +2025-11-14T18:24:34.184037Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:34.184217Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 31 (previous tip: 30) +2025-11-14T18:24:34.184228Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 31 (last_processed_height: 30, tip: 31) +2025-11-14T18:24:34.184291Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 31)], last_processed_height: 30, tip: 31 +2025-11-14T18:24:34.184297Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:34.185134Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd4656db24d743f49eadb9189c8542943b0b5ea9172a3ab06cbf0817bfa002b02 for height 31 +2025-11-14T18:24:34.185194Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd4656db24d743f49eadb9189c8542943b0b5ea9172a3ab06cbf0817bfa002b02 for height 31 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 31 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 31, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 31, is last block: false +2025-11-14T18:24:34.185283Z  INFO ThreadId(36) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=31 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 31 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 31, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 31, is last block: false +2025-11-14T18:24:34.185320Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=31 +2025-11-14T18:24:34.185451Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 32 not found (last_processed=31, tip=31) +2025-11-14T18:24:34.185451Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 32 not found (last_processed=31, tip=31) +2025-11-14T18:24:34.237252Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:177: 15 Handling message Broadcast +2025-11-14T18:24:34.239887Z  INFO ThreadId(56) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 33) (epoch 0, view 33), parent height: 32 +2025-11-14T18:24:34.239888Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 33) (epoch 0, view 33), parent height: 32 +2025-11-14T18:24:34.240812Z  INFO ThreadId(37) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 33) (epoch 0, view 33), parent height: 32 +2025-11-14T18:24:34.241842Z  INFO ThreadId(49) summit_application::actor: application/src/actor.rs:149: 139 application: Handling message Propose for round Round(0, 34) (epoch 0, view 34), parent height: 33 +2025-11-14T18:24:34.256041Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 33) (last_processed_height=31, tip=31) +2025-11-14T18:24:34.256156Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 33) (last_processed_height=31, tip=31) +2025-11-14T18:24:34.256973Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 32 (previous tip: 31) +2025-11-14T18:24:34.256985Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 32 (last_processed_height: 31, tip: 32) +2025-11-14T18:24:34.257039Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 32 (previous tip: 31) +2025-11-14T18:24:34.257049Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 32)], last_processed_height: 31, tip: 32 +2025-11-14T18:24:34.257052Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 32 (last_processed_height: 31, tip: 32) +2025-11-14T18:24:34.257055Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:34.257090Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 32)], last_processed_height: 31, tip: 32 +2025-11-14T18:24:34.257095Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:34.258188Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x8a4f8c3956350d633e3df89ad58bfa332b6f9acfbedb7c62a7cc6dee4f0d20d9 for height 32 +2025-11-14T18:24:34.258236Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x8a4f8c3956350d633e3df89ad58bfa332b6f9acfbedb7c62a7cc6dee4f0d20d9 for height 32 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 32 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 32, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 32, is last block: false +2025-11-14T18:24:34.258339Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=32 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 32 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 32, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 32, is last block: false +2025-11-14T18:24:34.258363Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=32 +2025-11-14T18:24:34.258534Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 33 not found (last_processed=32, tip=32) +2025-11-14T18:24:34.258543Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 33 not found (last_processed=32, tip=32) +2025-11-14T18:24:34.308200Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 33) (last_processed_height=31, tip=31) +2025-11-14T18:24:34.308924Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 33) (last_processed_height=31, tip=31) +2025-11-14T18:24:34.308950Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 32 (previous tip: 31) +2025-11-14T18:24:34.308955Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 32 (last_processed_height: 31, tip: 32) +2025-11-14T18:24:34.309047Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 32)], last_processed_height: 31, tip: 32 +2025-11-14T18:24:34.309060Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:34.309178Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:177: 139 Handling message Broadcast +2025-11-14T18:24:34.309773Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 32 (previous tip: 31) +2025-11-14T18:24:34.309782Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 32 (last_processed_height: 31, tip: 32) +2025-11-14T18:24:34.309829Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 32)], last_processed_height: 31, tip: 32 +2025-11-14T18:24:34.309833Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:34.310922Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x8a4f8c3956350d633e3df89ad58bfa332b6f9acfbedb7c62a7cc6dee4f0d20d9 for height 32 +2025-11-14T18:24:34.310922Z  INFO ThreadId(36) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x8a4f8c3956350d633e3df89ad58bfa332b6f9acfbedb7c62a7cc6dee4f0d20d9 for height 32 +2025-11-14T18:24:34.311012Z  INFO ThreadId(35) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 34) (epoch 0, view 34), parent height: 33 +2025-11-14T18:24:34.311032Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 34) (epoch 0, view 34), parent height: 33 +2025-11-14T18:24:34.311069Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 34) (epoch 0, view 34), parent height: 33 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 32 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 32, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 32, is last block: false +2025-11-14T18:24:34.311090Z  INFO ThreadId(36) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=32 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 32 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 32, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 32, is last block: false +2025-11-14T18:24:34.311157Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=32 +2025-11-14T18:24:34.311284Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 33 not found (last_processed=32, tip=32) +2025-11-14T18:24:34.311338Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 33 not found (last_processed=32, tip=32) +2025-11-14T18:24:34.376941Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:149: 55 application: Handling message Propose for round Round(0, 35) (epoch 0, view 35), parent height: 34 +2025-11-14T18:24:34.381274Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 34) (last_processed_height=32, tip=32) +2025-11-14T18:24:34.382779Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 34) (last_processed_height=32, tip=32) +2025-11-14T18:24:34.383105Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 33 (previous tip: 32) +2025-11-14T18:24:34.383116Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 33 (last_processed_height: 32, tip: 33) +2025-11-14T18:24:34.383189Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 33)], last_processed_height: 32, tip: 33 +2025-11-14T18:24:34.383195Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:34.383449Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 33 (previous tip: 32) +2025-11-14T18:24:34.383458Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 33 (last_processed_height: 32, tip: 33) +2025-11-14T18:24:34.383495Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 33)], last_processed_height: 32, tip: 33 +2025-11-14T18:24:34.383497Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:34.384786Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xcdfde64e3fb8d2a3a58e3b091e771b34434b62d0ac8743c1e5316ca2dd43a070 for height 33 +2025-11-14T18:24:34.384786Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xcdfde64e3fb8d2a3a58e3b091e771b34434b62d0ac8743c1e5316ca2dd43a070 for height 33 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 33 to reth +üüüüüüüüüüüüüüüüüüüüüüüüü +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +COMMITING BLOCK 33 to reth +epoch_num_of_blocks: 50, new_height: 33, is penultimate block: false +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 33, is penultimate block: false +epoch_num_of_blocks: 50, new_height: 33, is last block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 33, is last block: false +2025-11-14T18:24:34.384951Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=33 +2025-11-14T18:24:34.384955Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=33 +2025-11-14T18:24:34.385081Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 34 not found (last_processed=33, tip=33) +2025-11-14T18:24:34.385114Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 34 not found (last_processed=33, tip=33) +2025-11-14T18:24:34.432586Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 34) (last_processed_height=32, tip=32) +2025-11-14T18:24:34.433084Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 34) (last_processed_height=32, tip=32) +2025-11-14T18:24:34.433740Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 33 (previous tip: 32) +2025-11-14T18:24:34.433748Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 33 (last_processed_height: 32, tip: 33) +2025-11-14T18:24:34.433748Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 33 (previous tip: 32) +2025-11-14T18:24:34.433758Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 33 (last_processed_height: 32, tip: 33) +2025-11-14T18:24:34.433784Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 33)], last_processed_height: 32, tip: 33 +2025-11-14T18:24:34.433788Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:34.433795Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 33)], last_processed_height: 32, tip: 33 +2025-11-14T18:24:34.433800Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:34.434898Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xcdfde64e3fb8d2a3a58e3b091e771b34434b62d0ac8743c1e5316ca2dd43a070 for height 33 +2025-11-14T18:24:34.435045Z  INFO ThreadId(37) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xcdfde64e3fb8d2a3a58e3b091e771b34434b62d0ac8743c1e5316ca2dd43a070 for height 33 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 33 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 33, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 33, is last block: false +2025-11-14T18:24:34.435075Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=33 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 33 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 33, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 33, is last block: false +2025-11-14T18:24:34.435175Z  INFO ThreadId(36) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=33 +2025-11-14T18:24:34.435224Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 34 not found (last_processed=33, tip=33) +2025-11-14T18:24:34.435360Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 34 not found (last_processed=33, tip=33) +2025-11-14T18:24:34.437580Z  INFO ThreadId(57) summit_application::actor: application/src/actor.rs:177: 55 Handling message Broadcast +2025-11-14T18:24:34.504166Z  INFO ThreadId(36) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 35) (epoch 0, view 35), parent height: 34 +2025-11-14T18:24:34.504457Z  INFO ThreadId(43) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 35) (epoch 0, view 35), parent height: 34 +2025-11-14T18:24:34.504567Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 35) (epoch 0, view 35), parent height: 34 +2025-11-14T18:24:34.506772Z  INFO ThreadId(37) summit_application::actor: application/src/actor.rs:149: 209 application: Handling message Propose for round Round(0, 36) (epoch 0, view 36), parent height: 35 +2025-11-14T18:24:34.560520Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 35) (last_processed_height=33, tip=33) +2025-11-14T18:24:34.560698Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 35) (last_processed_height=33, tip=33) +2025-11-14T18:24:34.561711Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 34 (previous tip: 33) +2025-11-14T18:24:34.561718Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 34 (last_processed_height: 33, tip: 34) +2025-11-14T18:24:34.561737Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 34 (previous tip: 33) +2025-11-14T18:24:34.561743Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 34 (last_processed_height: 33, tip: 34) +2025-11-14T18:24:34.561761Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 34)], last_processed_height: 33, tip: 34 +2025-11-14T18:24:34.561765Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:34.561773Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 34)], last_processed_height: 33, tip: 34 +2025-11-14T18:24:34.561776Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:34.562672Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xc3c9644c1d3139bb6f34a59549b18e374fcf6e03325ce6d6bb757c6f3c2a8a19 for height 34 +2025-11-14T18:24:34.562674Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xc3c9644c1d3139bb6f34a59549b18e374fcf6e03325ce6d6bb757c6f3c2a8a19 for height 34 +üüüüüüüüüüüüüüüüüüüüüüüüü +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 34 to reth +COMMITING BLOCK 34 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 34, is penultimate block: false +epoch_num_of_blocks: 50, new_height: 34, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 34, is last block: false +epoch_num_of_blocks: 50, new_height: 34, is last block: false +2025-11-14T18:24:34.562831Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=34 +2025-11-14T18:24:34.562832Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=34 +2025-11-14T18:24:34.562980Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 35 not found (last_processed=34, tip=34) +2025-11-14T18:24:34.562999Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 35 not found (last_processed=34, tip=34) +2025-11-14T18:24:34.614785Z  INFO ThreadId(35) summit_application::actor: application/src/actor.rs:177: 209 Handling message Broadcast +2025-11-14T18:24:34.626184Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 35) (last_processed_height=33, tip=33) +2025-11-14T18:24:34.626250Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 35) (last_processed_height=33, tip=33) +2025-11-14T18:24:34.627283Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 34 (previous tip: 33) +2025-11-14T18:24:34.627293Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 34 (last_processed_height: 33, tip: 34) +2025-11-14T18:24:34.627344Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 34)], last_processed_height: 33, tip: 34 +2025-11-14T18:24:34.627349Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:34.627846Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 34 (previous tip: 33) +2025-11-14T18:24:34.627867Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 34 (last_processed_height: 33, tip: 34) +2025-11-14T18:24:34.627964Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 34)], last_processed_height: 33, tip: 34 +2025-11-14T18:24:34.627974Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:34.630156Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 36) (epoch 0, view 36), parent height: 35 +2025-11-14T18:24:34.630232Z  INFO ThreadId(49) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 36) (epoch 0, view 36), parent height: 35 +2025-11-14T18:24:34.631092Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xc3c9644c1d3139bb6f34a59549b18e374fcf6e03325ce6d6bb757c6f3c2a8a19 for height 34 +2025-11-14T18:24:34.631149Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xc3c9644c1d3139bb6f34a59549b18e374fcf6e03325ce6d6bb757c6f3c2a8a19 for height 34 +2025-11-14T18:24:34.631294Z  INFO ThreadId(57) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 36) (epoch 0, view 36), parent height: 35 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 34 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 34, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 34, is last block: false +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 34 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 34, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 34, is last block: false +2025-11-14T18:24:34.631360Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=34 +2025-11-14T18:24:34.631364Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=34 +2025-11-14T18:24:34.631539Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 35 not found (last_processed=34, tip=34) +2025-11-14T18:24:34.631601Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 35 not found (last_processed=34, tip=34) +2025-11-14T18:24:34.632532Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:149: 15 application: Handling message Propose for round Round(0, 37) (epoch 0, view 37), parent height: 36 +2025-11-14T18:24:34.684123Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 36) (last_processed_height=34, tip=34) +2025-11-14T18:24:34.685210Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 35 (previous tip: 34) +2025-11-14T18:24:34.685224Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 35 (last_processed_height: 34, tip: 35) +2025-11-14T18:24:34.685320Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 35)], last_processed_height: 34, tip: 35 +2025-11-14T18:24:34.685326Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:34.685702Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 36) (last_processed_height=34, tip=34) +2025-11-14T18:24:34.686318Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xc6872b22585bfe00160a6aecc321e8d4421c7ea46ff9de8cbd3a74088fb249b2 for height 35 +2025-11-14T18:24:34.686426Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 35 (previous tip: 34) +2025-11-14T18:24:34.686447Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 35 (last_processed_height: 34, tip: 35) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 35 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 35, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 35, is last block: false +2025-11-14T18:24:34.686488Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 35)], last_processed_height: 34, tip: 35 +2025-11-14T18:24:34.686491Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:34.686488Z  INFO ThreadId(36) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=35 +2025-11-14T18:24:34.686655Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 36 not found (last_processed=35, tip=35) +2025-11-14T18:24:34.687241Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xc6872b22585bfe00160a6aecc321e8d4421c7ea46ff9de8cbd3a74088fb249b2 for height 35 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 35 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 35, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 35, is last block: false +2025-11-14T18:24:34.687365Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=35 +2025-11-14T18:24:34.687482Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 36 not found (last_processed=35, tip=35) +2025-11-14T18:24:34.739277Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:177: 15 Handling message Broadcast +2025-11-14T18:24:34.750181Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 36) (last_processed_height=34, tip=34) +2025-11-14T18:24:34.750703Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 36) (last_processed_height=34, tip=34) +2025-11-14T18:24:34.751356Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 35 (previous tip: 34) +2025-11-14T18:24:34.751361Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 35 (last_processed_height: 34, tip: 35) +2025-11-14T18:24:34.751404Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 35)], last_processed_height: 34, tip: 35 +2025-11-14T18:24:34.751407Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:34.751535Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 35 (previous tip: 34) +2025-11-14T18:24:34.751540Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 35 (last_processed_height: 34, tip: 35) +2025-11-14T18:24:34.751570Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 35)], last_processed_height: 34, tip: 35 +2025-11-14T18:24:34.751573Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:34.752470Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xc6872b22585bfe00160a6aecc321e8d4421c7ea46ff9de8cbd3a74088fb249b2 for height 35 +2025-11-14T18:24:34.752459Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xc6872b22585bfe00160a6aecc321e8d4421c7ea46ff9de8cbd3a74088fb249b2 for height 35 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 35 to reth +üüüüüüüüüüüüüüüüüüüüüüüüü +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +COMMITING BLOCK 35 to reth +epoch_num_of_blocks: 50, new_height: 35, is penultimate block: false +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 35, is penultimate block: false +epoch_num_of_blocks: 50, new_height: 35, is last block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 35, is last block: false +2025-11-14T18:24:34.752620Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=35 +2025-11-14T18:24:34.752625Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=35 +2025-11-14T18:24:34.752765Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 36 not found (last_processed=35, tip=35) +2025-11-14T18:24:34.752769Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 36 not found (last_processed=35, tip=35) +2025-11-14T18:24:34.754814Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 37) (epoch 0, view 37), parent height: 36 +2025-11-14T18:24:34.754958Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 37) (epoch 0, view 37), parent height: 36 +2025-11-14T18:24:34.755957Z  INFO ThreadId(37) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 37) (epoch 0, view 37), parent height: 36 +2025-11-14T18:24:34.759106Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:149: 139 application: Handling message Propose for round Round(0, 38) (epoch 0, view 38), parent height: 37 +2025-11-14T18:24:34.809672Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 37) (last_processed_height=35, tip=35) +2025-11-14T18:24:34.810294Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 37) (last_processed_height=35, tip=35) +2025-11-14T18:24:34.810871Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 36 (previous tip: 35) +2025-11-14T18:24:34.810885Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 36 (last_processed_height: 35, tip: 36) +2025-11-14T18:24:34.810966Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 36)], last_processed_height: 35, tip: 36 +2025-11-14T18:24:34.810983Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:34.811327Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 36 (previous tip: 35) +2025-11-14T18:24:34.811330Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 36 (last_processed_height: 35, tip: 36) +2025-11-14T18:24:34.811370Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 36)], last_processed_height: 35, tip: 36 +2025-11-14T18:24:34.811372Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:34.812013Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xae9607939d5f215be140d9a83963bc01b44c9673e4c9871a71c2deb7fb27d49b for height 36 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 36 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 36, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 36, is last block: false +2025-11-14T18:24:34.812192Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=36 +2025-11-14T18:24:34.812235Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xae9607939d5f215be140d9a83963bc01b44c9673e4c9871a71c2deb7fb27d49b for height 36 +2025-11-14T18:24:34.812331Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 37 not found (last_processed=36, tip=36) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 36 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 36, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 36, is last block: false +2025-11-14T18:24:34.812346Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=36 +2025-11-14T18:24:34.812486Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 37 not found (last_processed=36, tip=36) +2025-11-14T18:24:34.875787Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 37) (last_processed_height=35, tip=35) +2025-11-14T18:24:34.876568Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 36 (previous tip: 35) +2025-11-14T18:24:34.876583Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 36 (last_processed_height: 35, tip: 36) +2025-11-14T18:24:34.876637Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 36)], last_processed_height: 35, tip: 36 +2025-11-14T18:24:34.876641Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:34.876665Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 37) (last_processed_height=35, tip=35) +2025-11-14T18:24:34.877193Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 36 (previous tip: 35) +2025-11-14T18:24:34.877199Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 36 (last_processed_height: 35, tip: 36) +2025-11-14T18:24:34.877244Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 36)], last_processed_height: 35, tip: 36 +2025-11-14T18:24:34.877247Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:34.877760Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xae9607939d5f215be140d9a83963bc01b44c9673e4c9871a71c2deb7fb27d49b for height 36 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 36 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 36, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 36, is last block: false +2025-11-14T18:24:34.877938Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=36 +2025-11-14T18:24:34.878102Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 37 not found (last_processed=36, tip=36) +2025-11-14T18:24:34.878142Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xae9607939d5f215be140d9a83963bc01b44c9673e4c9871a71c2deb7fb27d49b for height 36 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 36 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 36, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 36, is last block: false +2025-11-14T18:24:34.878258Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=36 +2025-11-14T18:24:34.878427Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 37 not found (last_processed=36, tip=36) +Node 0 at height 36 +2025-11-14T18:24:34.930266Z  INFO ThreadId(49) summit_application::actor: application/src/actor.rs:177: 139 Handling message Broadcast +2025-11-14T18:24:34.932897Z  INFO ThreadId(56) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 38) (epoch 0, view 38), parent height: 37 +2025-11-14T18:24:34.933442Z  INFO ThreadId(36) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 38) (epoch 0, view 38), parent height: 37 +2025-11-14T18:24:34.933473Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 38) (epoch 0, view 38), parent height: 37 +2025-11-14T18:24:34.935832Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:149: 55 application: Handling message Propose for round Round(0, 39) (epoch 0, view 39), parent height: 38 +2025-11-14T18:24:34.937791Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 38) (last_processed_height=36, tip=36) +2025-11-14T18:24:34.938357Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 37 (previous tip: 36) +2025-11-14T18:24:34.938361Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 37 (last_processed_height: 36, tip: 37) +2025-11-14T18:24:34.938402Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 37)], last_processed_height: 36, tip: 37 +2025-11-14T18:24:34.938406Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:34.939530Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x1bf0c1a2ae25d506e0025ec394633b3f1b4783f0e651fc0e11999447413306d2 for height 37 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 37 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 37, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 37, is last block: false +2025-11-14T18:24:34.939721Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=37 +2025-11-14T18:24:34.939903Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 38 not found (last_processed=37, tip=37) +2025-11-14T18:24:35.000816Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 38) (last_processed_height=36, tip=36) +2025-11-14T18:24:35.001378Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 38) (last_processed_height=36, tip=36) +2025-11-14T18:24:35.001647Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 38) (last_processed_height=36, tip=36) +2025-11-14T18:24:35.002025Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 37 (previous tip: 36) +2025-11-14T18:24:35.002039Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 37 (last_processed_height: 36, tip: 37) +2025-11-14T18:24:35.002114Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 37)], last_processed_height: 36, tip: 37 +2025-11-14T18:24:35.002119Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:35.002282Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 37 (previous tip: 36) +2025-11-14T18:24:35.002289Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 37 (last_processed_height: 36, tip: 37) +2025-11-14T18:24:35.002319Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 37)], last_processed_height: 36, tip: 37 +2025-11-14T18:24:35.002323Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:35.002345Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 37 (previous tip: 36) +2025-11-14T18:24:35.002352Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 37 (last_processed_height: 36, tip: 37) +2025-11-14T18:24:35.002395Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 37)], last_processed_height: 36, tip: 37 +2025-11-14T18:24:35.002399Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:35.003447Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x1bf0c1a2ae25d506e0025ec394633b3f1b4783f0e651fc0e11999447413306d2 for height 37 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 37 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 37, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 37, is last block: false +2025-11-14T18:24:35.003646Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=37 +2025-11-14T18:24:35.003679Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x1bf0c1a2ae25d506e0025ec394633b3f1b4783f0e651fc0e11999447413306d2 for height 37 +2025-11-14T18:24:35.003761Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x1bf0c1a2ae25d506e0025ec394633b3f1b4783f0e651fc0e11999447413306d2 for height 37 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 37 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 37, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 37, is last block: false +2025-11-14T18:24:35.003835Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=37 +2025-11-14T18:24:35.003838Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 38 not found (last_processed=37, tip=37) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 37 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 37, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 37, is last block: false +2025-11-14T18:24:35.003939Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=37 +2025-11-14T18:24:35.004014Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 38 not found (last_processed=37, tip=37) +2025-11-14T18:24:35.004095Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 38 not found (last_processed=37, tip=37) +2025-11-14T18:24:35.055700Z  INFO ThreadId(56) summit_application::actor: application/src/actor.rs:177: 55 Handling message Broadcast +2025-11-14T18:24:35.060299Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 39) (epoch 0, view 39), parent height: 38 +2025-11-14T18:24:35.060345Z  INFO ThreadId(38) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 39) (epoch 0, view 39), parent height: 38 +2025-11-14T18:24:35.060369Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 39) (epoch 0, view 39), parent height: 38 +2025-11-14T18:24:35.063688Z  INFO ThreadId(35) summit_application::actor: application/src/actor.rs:149: 209 application: Handling message Propose for round Round(0, 40) (epoch 0, view 40), parent height: 39 +2025-11-14T18:24:35.127511Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 39) (last_processed_height=37, tip=37) +2025-11-14T18:24:35.127652Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 39) (last_processed_height=37, tip=37) +2025-11-14T18:24:35.128604Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 39) (last_processed_height=37, tip=37) +2025-11-14T18:24:35.128728Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 38 (previous tip: 37) +2025-11-14T18:24:35.128743Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 38 (last_processed_height: 37, tip: 38) +2025-11-14T18:24:35.128778Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 38 (previous tip: 37) +2025-11-14T18:24:35.128792Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 38 (last_processed_height: 37, tip: 38) +2025-11-14T18:24:35.128849Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 38)], last_processed_height: 37, tip: 38 +2025-11-14T18:24:35.128857Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:35.128878Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 38)], last_processed_height: 37, tip: 38 +2025-11-14T18:24:35.128886Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:35.129318Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 39) (last_processed_height=37, tip=37) +2025-11-14T18:24:35.129399Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 38 (previous tip: 37) +2025-11-14T18:24:35.129405Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 38 (last_processed_height: 37, tip: 38) +2025-11-14T18:24:35.129437Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 38)], last_processed_height: 37, tip: 38 +2025-11-14T18:24:35.129442Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:35.129988Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 38 (previous tip: 37) +2025-11-14T18:24:35.129995Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 38 (last_processed_height: 37, tip: 38) +2025-11-14T18:24:35.130043Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 38)], last_processed_height: 37, tip: 38 +2025-11-14T18:24:35.130047Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:35.130341Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x3f8bc42541ccd74fdcdeefc25bf52914bfcb4843c58f0fbd819ce7adde0dcea7 for height 38 +2025-11-14T18:24:35.130342Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x3f8bc42541ccd74fdcdeefc25bf52914bfcb4843c58f0fbd819ce7adde0dcea7 for height 38 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 38 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 38, is penultimate block: false +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 38 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 38, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 38, is last block: false +2025-11-14T18:24:35.130543Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=38 +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 38, is last block: false +2025-11-14T18:24:35.130564Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=38 +2025-11-14T18:24:35.130759Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 39 not found (last_processed=38, tip=38) +2025-11-14T18:24:35.130759Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 39 not found (last_processed=38, tip=38) +2025-11-14T18:24:35.130838Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x3f8bc42541ccd74fdcdeefc25bf52914bfcb4843c58f0fbd819ce7adde0dcea7 for height 38 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 38 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 38, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 38, is last block: false +2025-11-14T18:24:35.130984Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=38 +2025-11-14T18:24:35.131148Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 39 not found (last_processed=38, tip=38) +2025-11-14T18:24:35.131189Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x3f8bc42541ccd74fdcdeefc25bf52914bfcb4843c58f0fbd819ce7adde0dcea7 for height 38 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 38 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 38, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 38, is last block: false +2025-11-14T18:24:35.131319Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=38 +2025-11-14T18:24:35.131476Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 39 not found (last_processed=38, tip=38) +2025-11-14T18:24:35.182768Z  INFO ThreadId(35) summit_application::actor: application/src/actor.rs:177: 209 Handling message Broadcast +2025-11-14T18:24:35.184661Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 40) (epoch 0, view 40), parent height: 39 +2025-11-14T18:24:35.185170Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 40) (epoch 0, view 40), parent height: 39 +2025-11-14T18:24:35.185210Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 40) (epoch 0, view 40), parent height: 39 +2025-11-14T18:24:35.186912Z  INFO ThreadId(43) summit_application::actor: application/src/actor.rs:149: 15 application: Handling message Propose for round Round(0, 41) (epoch 0, view 41), parent height: 40 +2025-11-14T18:24:35.254953Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 40) (last_processed_height=38, tip=38) +2025-11-14T18:24:35.255770Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 40) (last_processed_height=38, tip=38) +2025-11-14T18:24:35.255916Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 39 (previous tip: 38) +2025-11-14T18:24:35.255936Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 39 (last_processed_height: 38, tip: 39) +2025-11-14T18:24:35.256021Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 39)], last_processed_height: 38, tip: 39 +2025-11-14T18:24:35.256033Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:35.256325Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 39 (previous tip: 38) +2025-11-14T18:24:35.256331Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 39 (last_processed_height: 38, tip: 39) +2025-11-14T18:24:35.256371Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 39)], last_processed_height: 38, tip: 39 +2025-11-14T18:24:35.256374Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:35.257011Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x8a80c87647cedcce11736cfb1d0defa050a11a4ac2d936042a92f10971b1ac8a for height 39 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 39 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 39, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 39, is last block: false +2025-11-14T18:24:35.257226Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=39 +2025-11-14T18:24:35.257390Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x8a80c87647cedcce11736cfb1d0defa050a11a4ac2d936042a92f10971b1ac8a for height 39 +2025-11-14T18:24:35.257393Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 40 not found (last_processed=39, tip=39) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 39 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 39, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 39, is last block: false +2025-11-14T18:24:35.257513Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=39 +2025-11-14T18:24:35.257650Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 40 not found (last_processed=39, tip=39) +2025-11-14T18:24:35.308556Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 40) (last_processed_height=38, tip=38) +2025-11-14T18:24:35.308603Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 40) (last_processed_height=38, tip=38) +2025-11-14T18:24:35.309229Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 39 (previous tip: 38) +2025-11-14T18:24:35.309243Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 39 (last_processed_height: 38, tip: 39) +2025-11-14T18:24:35.309322Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 39)], last_processed_height: 38, tip: 39 +2025-11-14T18:24:35.309329Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:35.309559Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 39 (previous tip: 38) +2025-11-14T18:24:35.309572Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 39 (last_processed_height: 38, tip: 39) +2025-11-14T18:24:35.309661Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 39)], last_processed_height: 38, tip: 39 +2025-11-14T18:24:35.309669Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:35.310472Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x8a80c87647cedcce11736cfb1d0defa050a11a4ac2d936042a92f10971b1ac8a for height 39 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 39 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 39, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 39, is last block: false +2025-11-14T18:24:35.310652Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=39 +2025-11-14T18:24:35.310809Z  INFO ThreadId(36) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x8a80c87647cedcce11736cfb1d0defa050a11a4ac2d936042a92f10971b1ac8a for height 39 +2025-11-14T18:24:35.310835Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 40 not found (last_processed=39, tip=39) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 39 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 39, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 39, is last block: false +2025-11-14T18:24:35.310930Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=39 +2025-11-14T18:24:35.311064Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 40 not found (last_processed=39, tip=39) +2025-11-14T18:24:35.362573Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:177: 15 Handling message Broadcast +2025-11-14T18:24:35.377185Z  INFO ThreadId(36) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 41) (epoch 0, view 41), parent height: 40 +2025-11-14T18:24:35.377506Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 41) (epoch 0, view 41), parent height: 40 +2025-11-14T18:24:35.378257Z  INFO ThreadId(56) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 41) (epoch 0, view 41), parent height: 40 +2025-11-14T18:24:35.380647Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:149: 139 application: Handling message Propose for round Round(0, 42) (epoch 0, view 42), parent height: 41 +2025-11-14T18:24:35.431657Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 41) (last_processed_height=39, tip=39) +2025-11-14T18:24:35.432422Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 41) (last_processed_height=39, tip=39) +2025-11-14T18:24:35.432548Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 40 (previous tip: 39) +2025-11-14T18:24:35.432563Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 40 (last_processed_height: 39, tip: 40) +2025-11-14T18:24:35.432664Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 40)], last_processed_height: 39, tip: 40 +2025-11-14T18:24:35.432672Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:35.433244Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 40 (previous tip: 39) +2025-11-14T18:24:35.433251Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 40 (last_processed_height: 39, tip: 40) +2025-11-14T18:24:35.433299Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 40)], last_processed_height: 39, tip: 40 +2025-11-14T18:24:35.433302Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:35.433553Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x446048fe0b617fac11603a86d4e4dbd30fdeb0198be8a8d94c0c9ba3169c670e for height 40 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 40 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 40, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 40, is last block: false +2025-11-14T18:24:35.433690Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=40 +2025-11-14T18:24:35.433851Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 41 not found (last_processed=40, tip=40) +2025-11-14T18:24:35.434256Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x446048fe0b617fac11603a86d4e4dbd30fdeb0198be8a8d94c0c9ba3169c670e for height 40 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 40 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 40, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 40, is last block: false +2025-11-14T18:24:35.434370Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=40 +2025-11-14T18:24:35.434499Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 41 not found (last_processed=40, tip=40) +2025-11-14T18:24:35.434510Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 41) (last_processed_height=39, tip=39) +2025-11-14T18:24:35.434597Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 41) (last_processed_height=39, tip=39) +2025-11-14T18:24:35.435162Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 40 (previous tip: 39) +2025-11-14T18:24:35.435168Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 40 (last_processed_height: 39, tip: 40) +2025-11-14T18:24:35.435204Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 40 (previous tip: 39) +2025-11-14T18:24:35.435208Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 40 (last_processed_height: 39, tip: 40) +2025-11-14T18:24:35.435209Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 40)], last_processed_height: 39, tip: 40 +2025-11-14T18:24:35.435213Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:35.435242Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 40)], last_processed_height: 39, tip: 40 +2025-11-14T18:24:35.435245Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:35.436108Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x446048fe0b617fac11603a86d4e4dbd30fdeb0198be8a8d94c0c9ba3169c670e for height 40 +2025-11-14T18:24:35.436180Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x446048fe0b617fac11603a86d4e4dbd30fdeb0198be8a8d94c0c9ba3169c670e for height 40 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 40 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 40, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 40, is last block: false +2025-11-14T18:24:35.436260Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=40 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 40 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 40, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 40, is last block: false +2025-11-14T18:24:35.436318Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=40 +2025-11-14T18:24:35.436407Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 41 not found (last_processed=40, tip=40) +2025-11-14T18:24:35.436503Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 41 not found (last_processed=40, tip=40) +2025-11-14T18:24:35.487834Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:177: 139 Handling message Broadcast +2025-11-14T18:24:35.504513Z  INFO ThreadId(57) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 42) (epoch 0, view 42), parent height: 41 +2025-11-14T18:24:35.504739Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 42) (epoch 0, view 42), parent height: 41 +2025-11-14T18:24:35.504828Z  INFO ThreadId(38) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 42) (epoch 0, view 42), parent height: 41 +2025-11-14T18:24:35.506711Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:149: 55 application: Handling message Propose for round Round(0, 43) (epoch 0, view 43), parent height: 42 +2025-11-14T18:24:35.561019Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 42) (last_processed_height=40, tip=40) +2025-11-14T18:24:35.561037Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 42) (last_processed_height=40, tip=40) +2025-11-14T18:24:35.561841Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 41 (previous tip: 40) +2025-11-14T18:24:35.561855Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 41 (last_processed_height: 40, tip: 41) +2025-11-14T18:24:35.561931Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 41)], last_processed_height: 40, tip: 41 +2025-11-14T18:24:35.561938Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:35.562136Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 41 (previous tip: 40) +2025-11-14T18:24:35.562148Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 41 (last_processed_height: 40, tip: 41) +2025-11-14T18:24:35.562236Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 41)], last_processed_height: 40, tip: 41 +2025-11-14T18:24:35.562242Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:35.563052Z  INFO ThreadId(37) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x253be5a4294ecd896f1ff6c6d6c59cdd3b2b9adcb16bd53536ee030fa5b79bfc for height 41 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 41 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 41, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 41, is last block: false +2025-11-14T18:24:35.563220Z  INFO ThreadId(36) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=41 +2025-11-14T18:24:35.563226Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x253be5a4294ecd896f1ff6c6d6c59cdd3b2b9adcb16bd53536ee030fa5b79bfc for height 41 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 41 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 41, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 41, is last block: false +2025-11-14T18:24:35.563356Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 42 not found (last_processed=41, tip=41) +2025-11-14T18:24:35.563359Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=41 +2025-11-14T18:24:35.563510Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 42 not found (last_processed=41, tip=41) +2025-11-14T18:24:35.625991Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 42) (last_processed_height=40, tip=40) +2025-11-14T18:24:35.626546Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 42) (last_processed_height=40, tip=40) +2025-11-14T18:24:35.627324Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 41 (previous tip: 40) +2025-11-14T18:24:35.627331Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 41 (last_processed_height: 40, tip: 41) +2025-11-14T18:24:35.627374Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 41)], last_processed_height: 40, tip: 41 +2025-11-14T18:24:35.627378Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:35.627457Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 41 (previous tip: 40) +2025-11-14T18:24:35.627463Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 41 (last_processed_height: 40, tip: 41) +2025-11-14T18:24:35.627499Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 41)], last_processed_height: 40, tip: 41 +2025-11-14T18:24:35.627502Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:35.628361Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x253be5a4294ecd896f1ff6c6d6c59cdd3b2b9adcb16bd53536ee030fa5b79bfc for height 41 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 41 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 41, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 41, is last block: false +2025-11-14T18:24:35.628518Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x253be5a4294ecd896f1ff6c6d6c59cdd3b2b9adcb16bd53536ee030fa5b79bfc for height 41 +2025-11-14T18:24:35.628521Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=41 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 41 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 41, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 41, is last block: false +2025-11-14T18:24:35.628665Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=41 +2025-11-14T18:24:35.628678Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 42 not found (last_processed=41, tip=41) +2025-11-14T18:24:35.628795Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 42 not found (last_processed=41, tip=41) +2025-11-14T18:24:35.680339Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:177: 55 Handling message Broadcast +2025-11-14T18:24:35.683052Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 43) (epoch 0, view 43), parent height: 42 +2025-11-14T18:24:35.683536Z  INFO ThreadId(38) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 43) (epoch 0, view 43), parent height: 42 +2025-11-14T18:24:35.684055Z  INFO ThreadId(43) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 43) (epoch 0, view 43), parent height: 42 +2025-11-14T18:24:35.687575Z  INFO ThreadId(35) summit_application::actor: application/src/actor.rs:149: 209 application: Handling message Propose for round Round(0, 44) (epoch 0, view 44), parent height: 43 +2025-11-14T18:24:35.688666Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 43) (last_processed_height=41, tip=41) +2025-11-14T18:24:35.689262Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 42 (previous tip: 41) +2025-11-14T18:24:35.689268Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 42 (last_processed_height: 41, tip: 42) +2025-11-14T18:24:35.689303Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 42)], last_processed_height: 41, tip: 42 +2025-11-14T18:24:35.689306Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:35.690435Z  INFO ThreadId(37) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xf96ce96e85337efb67d0c558775c8711d98bf20e2cf69555c333f59565be409e for height 42 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 42 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 42, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 42, is last block: false +2025-11-14T18:24:35.690661Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=42 +2025-11-14T18:24:35.690896Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 43 not found (last_processed=42, tip=42) +2025-11-14T18:24:35.742657Z  INFO ThreadId(36) summit_application::actor: application/src/actor.rs:177: 209 Handling message Broadcast +2025-11-14T18:24:35.749930Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 43) (last_processed_height=41, tip=41) +2025-11-14T18:24:35.750912Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 42 (previous tip: 41) +2025-11-14T18:24:35.750918Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 42 (last_processed_height: 41, tip: 42) +2025-11-14T18:24:35.750952Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 42)], last_processed_height: 41, tip: 42 +2025-11-14T18:24:35.750955Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:35.751451Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 43) (last_processed_height=41, tip=41) +2025-11-14T18:24:35.752021Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xf96ce96e85337efb67d0c558775c8711d98bf20e2cf69555c333f59565be409e for height 42 +2025-11-14T18:24:35.752075Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 42 (previous tip: 41) +2025-11-14T18:24:35.752081Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 42 (last_processed_height: 41, tip: 42) +2025-11-14T18:24:35.752116Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 42)], last_processed_height: 41, tip: 42 +2025-11-14T18:24:35.752119Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 42 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 42, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 42, is last block: false +2025-11-14T18:24:35.752221Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=42 +2025-11-14T18:24:35.752482Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 43 not found (last_processed=42, tip=42) +2025-11-14T18:24:35.752697Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 43) (last_processed_height=41, tip=41) +2025-11-14T18:24:35.753063Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xf96ce96e85337efb67d0c558775c8711d98bf20e2cf69555c333f59565be409e for height 42 +2025-11-14T18:24:35.753261Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 42 (previous tip: 41) +2025-11-14T18:24:35.753266Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 42 (last_processed_height: 41, tip: 42) +2025-11-14T18:24:35.753297Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 42)], last_processed_height: 41, tip: 42 +2025-11-14T18:24:35.753300Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 42 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 42, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 42, is last block: false +2025-11-14T18:24:35.753362Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=42 +2025-11-14T18:24:35.753514Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 43 not found (last_processed=42, tip=42) +2025-11-14T18:24:35.753979Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 44) (epoch 0, view 44), parent height: 43 +2025-11-14T18:24:35.754283Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xf96ce96e85337efb67d0c558775c8711d98bf20e2cf69555c333f59565be409e for height 42 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 42 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 42, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 42, is last block: false +2025-11-14T18:24:35.754394Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=42 +2025-11-14T18:24:35.754536Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 43 not found (last_processed=42, tip=42) +2025-11-14T18:24:35.754544Z  INFO ThreadId(57) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 44) (epoch 0, view 44), parent height: 43 +2025-11-14T18:24:35.755122Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 44) (epoch 0, view 44), parent height: 43 +2025-11-14T18:24:35.809580Z  INFO ThreadId(43) summit_application::actor: application/src/actor.rs:149: 15 application: Handling message Propose for round Round(0, 45) (epoch 0, view 45), parent height: 44 +2025-11-14T18:24:35.875690Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 44) (last_processed_height=42, tip=42) +2025-11-14T18:24:35.876357Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 43 (previous tip: 42) +2025-11-14T18:24:35.876362Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 43 (last_processed_height: 42, tip: 43) +2025-11-14T18:24:35.876405Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 43)], last_processed_height: 42, tip: 43 +2025-11-14T18:24:35.876409Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:35.876532Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 44) (last_processed_height=42, tip=42) +2025-11-14T18:24:35.876629Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 44) (last_processed_height=42, tip=42) +2025-11-14T18:24:35.877166Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 43 (previous tip: 42) +2025-11-14T18:24:35.877181Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 43 (last_processed_height: 42, tip: 43) +2025-11-14T18:24:35.877260Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 43)], last_processed_height: 42, tip: 43 +2025-11-14T18:24:35.877269Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:35.877423Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 43 (previous tip: 42) +2025-11-14T18:24:35.877441Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 43 (last_processed_height: 42, tip: 43) +2025-11-14T18:24:35.877488Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 43)], last_processed_height: 42, tip: 43 +2025-11-14T18:24:35.877497Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:35.877763Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xb853aba983e5bd52773262056c0a51c55a0dd41fcaf46f5c28dfd6694a411cd8 for height 43 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 43 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 43, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 43, is last block: false +2025-11-14T18:24:35.878024Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=43 +2025-11-14T18:24:35.878221Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 44 not found (last_processed=43, tip=43) +2025-11-14T18:24:35.878369Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xb853aba983e5bd52773262056c0a51c55a0dd41fcaf46f5c28dfd6694a411cd8 for height 43 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 43 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 43, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 43, is last block: false +2025-11-14T18:24:35.878506Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=43 +2025-11-14T18:24:35.878555Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xb853aba983e5bd52773262056c0a51c55a0dd41fcaf46f5c28dfd6694a411cd8 for height 43 +2025-11-14T18:24:35.878691Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 44 not found (last_processed=43, tip=43) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 43 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 43, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 43, is last block: false +2025-11-14T18:24:35.878704Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=43 +2025-11-14T18:24:35.878851Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 44 not found (last_processed=43, tip=43) +2025-11-14T18:24:35.879156Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 44) (last_processed_height=42, tip=42) +2025-11-14T18:24:35.879627Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 43 (previous tip: 42) +2025-11-14T18:24:35.879633Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 43 (last_processed_height: 42, tip: 43) +2025-11-14T18:24:35.879703Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 43)], last_processed_height: 42, tip: 43 +2025-11-14T18:24:35.879708Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:35.880413Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xb853aba983e5bd52773262056c0a51c55a0dd41fcaf46f5c28dfd6694a411cd8 for height 43 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 43 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 43, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 43, is last block: false +2025-11-14T18:24:35.880534Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=43 +2025-11-14T18:24:35.880685Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 44 not found (last_processed=43, tip=43) +Node 0 at height 43 +2025-11-14T18:24:35.932249Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:177: 15 Handling message Broadcast +2025-11-14T18:24:35.934610Z  INFO ThreadId(37) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 45) (epoch 0, view 45), parent height: 44 +2025-11-14T18:24:35.935126Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 45) (epoch 0, view 45), parent height: 44 +2025-11-14T18:24:35.935202Z  INFO ThreadId(52) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 45) (epoch 0, view 45), parent height: 44 +2025-11-14T18:24:35.937101Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:149: 139 application: Handling message Propose for round Round(0, 46) (epoch 0, view 46), parent height: 45 +2025-11-14T18:24:36.005202Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 45) (last_processed_height=43, tip=43) +2025-11-14T18:24:36.005311Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 45) (last_processed_height=43, tip=43) +2025-11-14T18:24:36.005788Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 44 (previous tip: 43) +2025-11-14T18:24:36.005794Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 44 (last_processed_height: 43, tip: 44) +2025-11-14T18:24:36.005845Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 44)], last_processed_height: 43, tip: 44 +2025-11-14T18:24:36.005848Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:36.006097Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 44 (previous tip: 43) +2025-11-14T18:24:36.006108Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 44 (last_processed_height: 43, tip: 44) +2025-11-14T18:24:36.006159Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 44)], last_processed_height: 43, tip: 44 +2025-11-14T18:24:36.006165Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:36.006915Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7b5d2ca1470c254dad011a098e9876cf6c2c9c102169badb7c7edef5e11c1b7a for height 44 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 44 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 44, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 44, is last block: false +2025-11-14T18:24:36.007083Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=44 +2025-11-14T18:24:36.007094Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7b5d2ca1470c254dad011a098e9876cf6c2c9c102169badb7c7edef5e11c1b7a for height 44 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 44 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 44, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 44, is last block: false +2025-11-14T18:24:36.007214Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=44 +2025-11-14T18:24:36.007234Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 45 not found (last_processed=44, tip=44) +2025-11-14T18:24:36.007358Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 45 not found (last_processed=44, tip=44) +2025-11-14T18:24:36.058708Z  INFO ThreadId(49) summit_application::actor: application/src/actor.rs:177: 139 Handling message Broadcast +2025-11-14T18:24:36.058866Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 45) (last_processed_height=43, tip=43) +2025-11-14T18:24:36.059240Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 45) (last_processed_height=43, tip=43) +2025-11-14T18:24:36.059592Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 44 (previous tip: 43) +2025-11-14T18:24:36.059599Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 44 (last_processed_height: 43, tip: 44) +2025-11-14T18:24:36.059639Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 44)], last_processed_height: 43, tip: 44 +2025-11-14T18:24:36.059643Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:36.059753Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 44 (previous tip: 43) +2025-11-14T18:24:36.059759Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 44 (last_processed_height: 43, tip: 44) +2025-11-14T18:24:36.059795Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 44)], last_processed_height: 43, tip: 44 +2025-11-14T18:24:36.059799Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:36.060418Z  INFO ThreadId(35) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 46) (epoch 0, view 46), parent height: 45 +2025-11-14T18:24:36.060472Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 46) (epoch 0, view 46), parent height: 45 +2025-11-14T18:24:36.060535Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 46) (epoch 0, view 46), parent height: 45 +2025-11-14T18:24:36.060772Z  INFO ThreadId(36) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7b5d2ca1470c254dad011a098e9876cf6c2c9c102169badb7c7edef5e11c1b7a for height 44 +2025-11-14T18:24:36.060932Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7b5d2ca1470c254dad011a098e9876cf6c2c9c102169badb7c7edef5e11c1b7a for height 44 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 44 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 44, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 44, is last block: false +2025-11-14T18:24:36.060987Z  INFO ThreadId(37) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=44 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 44 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 44, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 44, is last block: false +2025-11-14T18:24:36.061112Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=44 +2025-11-14T18:24:36.061185Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 45 not found (last_processed=44, tip=44) +2025-11-14T18:24:36.061240Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 45 not found (last_processed=44, tip=44) +2025-11-14T18:24:36.062231Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:149: 55 application: Handling message Propose for round Round(0, 47) (epoch 0, view 47), parent height: 46 +2025-11-14T18:24:36.130695Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 46) (last_processed_height=44, tip=44) +2025-11-14T18:24:36.130869Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 46) (last_processed_height=44, tip=44) +2025-11-14T18:24:36.131407Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 45 (previous tip: 44) +2025-11-14T18:24:36.131413Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 45 (last_processed_height: 44, tip: 45) +2025-11-14T18:24:36.131459Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 45)], last_processed_height: 44, tip: 45 +2025-11-14T18:24:36.131462Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:36.131897Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 45 (previous tip: 44) +2025-11-14T18:24:36.131909Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 45 (last_processed_height: 44, tip: 45) +2025-11-14T18:24:36.131965Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 45)], last_processed_height: 44, tip: 45 +2025-11-14T18:24:36.131971Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:36.132710Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x0819f13be395651e1deaaa0a0ae1a922e1032ce553bdbf316286f5b5bd04e8c8 for height 45 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 45 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 45, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 45, is last block: false +2025-11-14T18:24:36.132888Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=45 +2025-11-14T18:24:36.132992Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x0819f13be395651e1deaaa0a0ae1a922e1032ce553bdbf316286f5b5bd04e8c8 for height 45 +2025-11-14T18:24:36.133109Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 46 not found (last_processed=45, tip=45) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 45 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 45, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 45, is last block: false +2025-11-14T18:24:36.133130Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=45 +2025-11-14T18:24:36.133392Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 46 not found (last_processed=45, tip=45) +2025-11-14T18:24:36.183714Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 46) (last_processed_height=44, tip=44) +2025-11-14T18:24:36.184087Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:177: 55 Handling message Broadcast +2025-11-14T18:24:36.184307Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 46) (last_processed_height=44, tip=44) +2025-11-14T18:24:36.184762Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 45 (previous tip: 44) +2025-11-14T18:24:36.184775Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 45 (last_processed_height: 44, tip: 45) +2025-11-14T18:24:36.184814Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 45 (previous tip: 44) +2025-11-14T18:24:36.184826Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 45 (last_processed_height: 44, tip: 45) +2025-11-14T18:24:36.184838Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 45)], last_processed_height: 44, tip: 45 +2025-11-14T18:24:36.184846Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:36.184876Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 45)], last_processed_height: 44, tip: 45 +2025-11-14T18:24:36.184882Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:36.186271Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x0819f13be395651e1deaaa0a0ae1a922e1032ce553bdbf316286f5b5bd04e8c8 for height 45 +2025-11-14T18:24:36.186316Z  INFO ThreadId(37) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x0819f13be395651e1deaaa0a0ae1a922e1032ce553bdbf316286f5b5bd04e8c8 for height 45 +2025-11-14T18:24:36.186364Z  INFO ThreadId(43) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 47) (epoch 0, view 47), parent height: 46 +2025-11-14T18:24:36.186368Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 47) (epoch 0, view 47), parent height: 46 +2025-11-14T18:24:36.186408Z  INFO ThreadId(35) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 47) (epoch 0, view 47), parent height: 46 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 45 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 45, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 45, is last block: false +2025-11-14T18:24:36.186429Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=45 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 45 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 45, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 45, is last block: false +2025-11-14T18:24:36.186460Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=45 +2025-11-14T18:24:36.186633Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 46 not found (last_processed=45, tip=45) +2025-11-14T18:24:36.186638Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 46 not found (last_processed=45, tip=45) +2025-11-14T18:24:36.188056Z  INFO ThreadId(35) summit_application::actor: application/src/actor.rs:149: 209 application: Handling message Propose for round Round(0, 48) (epoch 0, view 48), parent height: 47 +2025-11-14T18:24:36.254602Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 47) (last_processed_height=45, tip=45) +2025-11-14T18:24:36.255654Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 46 (previous tip: 45) +2025-11-14T18:24:36.255667Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 46 (last_processed_height: 45, tip: 46) +2025-11-14T18:24:36.255712Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 47) (last_processed_height=45, tip=45) +2025-11-14T18:24:36.255732Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 46)], last_processed_height: 45, tip: 46 +2025-11-14T18:24:36.255739Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:36.256239Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 46 (previous tip: 45) +2025-11-14T18:24:36.256246Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 46 (last_processed_height: 45, tip: 46) +2025-11-14T18:24:36.256288Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 46)], last_processed_height: 45, tip: 46 +2025-11-14T18:24:36.256292Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:36.256979Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x8dd36be15750b50fdbd944e9bc5dd3ce1acedbd24228dac54b0041c1b898158e for height 46 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 46 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 46, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 46, is last block: false +2025-11-14T18:24:36.257251Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=46 +2025-11-14T18:24:36.257385Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x8dd36be15750b50fdbd944e9bc5dd3ce1acedbd24228dac54b0041c1b898158e for height 46 +2025-11-14T18:24:36.257422Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 47 not found (last_processed=46, tip=46) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 46 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 46, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 46, is last block: false +2025-11-14T18:24:36.257487Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=46 +2025-11-14T18:24:36.257609Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 47 not found (last_processed=46, tip=46) +2025-11-14T18:24:36.308183Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 47) (last_processed_height=45, tip=45) +2025-11-14T18:24:36.308452Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 47) (last_processed_height=45, tip=45) +2025-11-14T18:24:36.308753Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 46 (previous tip: 45) +2025-11-14T18:24:36.308759Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 46 (last_processed_height: 45, tip: 46) +2025-11-14T18:24:36.308793Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 46)], last_processed_height: 45, tip: 46 +2025-11-14T18:24:36.308796Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:36.309335Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 46 (previous tip: 45) +2025-11-14T18:24:36.309348Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 46 (last_processed_height: 45, tip: 46) +2025-11-14T18:24:36.309406Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 46)], last_processed_height: 45, tip: 46 +2025-11-14T18:24:36.309413Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:36.309813Z  INFO ThreadId(36) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x8dd36be15750b50fdbd944e9bc5dd3ce1acedbd24228dac54b0041c1b898158e for height 46 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 46 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 46, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 46, is last block: false +2025-11-14T18:24:36.309949Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=46 +2025-11-14T18:24:36.310149Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 47 not found (last_processed=46, tip=46) +2025-11-14T18:24:36.310419Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x8dd36be15750b50fdbd944e9bc5dd3ce1acedbd24228dac54b0041c1b898158e for height 46 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 46 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 46, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 46, is last block: false +2025-11-14T18:24:36.310535Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=46 +2025-11-14T18:24:36.310701Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 47 not found (last_processed=46, tip=46) +2025-11-14T18:24:36.361659Z  INFO ThreadId(35) summit_application::actor: application/src/actor.rs:177: 209 Handling message Broadcast +2025-11-14T18:24:36.374963Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 48) (epoch 0, view 48), parent height: 47 +2025-11-14T18:24:36.375930Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 48) (epoch 0, view 48), parent height: 47 +2025-11-14T18:24:36.376179Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 48) (epoch 0, view 48), parent height: 47 +2025-11-14T18:24:36.378044Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:149: 15 application: Handling message Propose for round Round(0, 49) (epoch 0, view 49), parent height: 48 +2025-11-14T18:24:36.433269Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 48) (last_processed_height=46, tip=46) +2025-11-14T18:24:36.433833Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 48) (last_processed_height=46, tip=46) +2025-11-14T18:24:36.434034Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 48) (last_processed_height=46, tip=46) +2025-11-14T18:24:36.434262Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 48) (last_processed_height=46, tip=46) +2025-11-14T18:24:36.434405Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 47 (previous tip: 46) +2025-11-14T18:24:36.434417Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 47 (last_processed_height: 46, tip: 47) +2025-11-14T18:24:36.434508Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 47)], last_processed_height: 46, tip: 47 +2025-11-14T18:24:36.434515Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:36.434868Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 47 (previous tip: 46) +2025-11-14T18:24:36.434873Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 47 (last_processed_height: 46, tip: 47) +2025-11-14T18:24:36.434904Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 47)], last_processed_height: 46, tip: 47 +2025-11-14T18:24:36.434907Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:36.434997Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 47 (previous tip: 46) +2025-11-14T18:24:36.435003Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 47 (last_processed_height: 46, tip: 47) +2025-11-14T18:24:36.435043Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 47)], last_processed_height: 46, tip: 47 +2025-11-14T18:24:36.435049Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:36.435105Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 47 (previous tip: 46) +2025-11-14T18:24:36.435113Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 47 (last_processed_height: 46, tip: 47) +2025-11-14T18:24:36.435159Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 47)], last_processed_height: 46, tip: 47 +2025-11-14T18:24:36.435163Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:36.435552Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xfe93706c3db6c859be552d841fa635db97c118876a6087b57d4cca2a9b309acd for height 47 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 47 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 47, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 47, is last block: false +2025-11-14T18:24:36.435803Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=47 +2025-11-14T18:24:36.435994Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 48 not found (last_processed=47, tip=47) +2025-11-14T18:24:36.436040Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xfe93706c3db6c859be552d841fa635db97c118876a6087b57d4cca2a9b309acd for height 47 +2025-11-14T18:24:36.436229Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xfe93706c3db6c859be552d841fa635db97c118876a6087b57d4cca2a9b309acd for height 47 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 47 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 47, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 47, is last block: false +2025-11-14T18:24:36.436244Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=47 +2025-11-14T18:24:36.436296Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xfe93706c3db6c859be552d841fa635db97c118876a6087b57d4cca2a9b309acd for height 47 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 47 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 47, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 47, is last block: false +2025-11-14T18:24:36.436377Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=47 +2025-11-14T18:24:36.436422Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 48 not found (last_processed=47, tip=47) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 47 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 47, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 47, is last block: false +2025-11-14T18:24:36.436437Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=47 +2025-11-14T18:24:36.436574Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 48 not found (last_processed=47, tip=47) +2025-11-14T18:24:36.436735Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 48 not found (last_processed=47, tip=47) +2025-11-14T18:24:36.488121Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:177: 15 Handling message Broadcast +2025-11-14T18:24:36.501648Z  INFO ThreadId(49) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(0, 49) (epoch 0, view 49), parent height: 48 +2025-11-14T18:24:36.501731Z  INFO ThreadId(35) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 49) (epoch 0, view 49), parent height: 48 +2025-11-14T18:24:36.502090Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 49) (epoch 0, view 49), parent height: 48 +2025-11-14T18:24:36.504074Z  INFO ThreadId(52) summit_application::actor: application/src/actor.rs:149: 139 application: Handling message Propose for round Round(0, 50) (epoch 0, view 50), parent height: 49 +2025-11-14T18:24:36.560145Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 49) (last_processed_height=47, tip=47) +2025-11-14T18:24:36.560243Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 49) (last_processed_height=47, tip=47) +2025-11-14T18:24:36.561081Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 48 (previous tip: 47) +2025-11-14T18:24:36.561092Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 48 (last_processed_height: 47, tip: 48) +2025-11-14T18:24:36.561153Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 48)], last_processed_height: 47, tip: 48 +2025-11-14T18:24:36.561160Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:36.561331Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 48 (previous tip: 47) +2025-11-14T18:24:36.561344Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 48 (last_processed_height: 47, tip: 48) +2025-11-14T18:24:36.561427Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 48)], last_processed_height: 47, tip: 48 +2025-11-14T18:24:36.561433Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:36.562270Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x72bf63f6e562b7249d23e8d889dedfa9885b51bb00d86c0d2f527288f13b3b91 for height 48 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 48 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 48, is penultimate block: true +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 48, is last block: false +2025-11-14T18:24:36.562482Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=48 +2025-11-14T18:24:36.562577Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x72bf63f6e562b7249d23e8d889dedfa9885b51bb00d86c0d2f527288f13b3b91 for height 48 +2025-11-14T18:24:36.562648Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 49 not found (last_processed=48, tip=48) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 48 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 48, is penultimate block: true +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 48, is last block: false +2025-11-14T18:24:36.562697Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=48 +2025-11-14T18:24:36.562838Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 49 not found (last_processed=48, tip=48) +2025-11-14T18:24:36.626220Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 49) (last_processed_height=47, tip=47) +2025-11-14T18:24:36.626274Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 49) (last_processed_height=47, tip=47) +2025-11-14T18:24:36.627033Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 48 (previous tip: 47) +2025-11-14T18:24:36.627041Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 48 (last_processed_height: 47, tip: 48) +2025-11-14T18:24:36.627044Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 48 (previous tip: 47) +2025-11-14T18:24:36.627057Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 48 (last_processed_height: 47, tip: 48) +2025-11-14T18:24:36.627078Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 48)], last_processed_height: 47, tip: 48 +2025-11-14T18:24:36.627082Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:36.627120Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 48)], last_processed_height: 47, tip: 48 +2025-11-14T18:24:36.627128Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:36.628125Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x72bf63f6e562b7249d23e8d889dedfa9885b51bb00d86c0d2f527288f13b3b91 for height 48 +2025-11-14T18:24:36.628176Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x72bf63f6e562b7249d23e8d889dedfa9885b51bb00d86c0d2f527288f13b3b91 for height 48 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 48 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 48, is penultimate block: true +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 48, is last block: false +2025-11-14T18:24:36.628280Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=48 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 48 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 48, is penultimate block: true +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 48, is last block: false +2025-11-14T18:24:36.628351Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=48 +2025-11-14T18:24:36.628413Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 49 not found (last_processed=48, tip=48) +2025-11-14T18:24:36.628569Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 49 not found (last_processed=48, tip=48) +2025-11-14T18:24:36.679361Z  INFO ThreadId(52) summit_application::actor: application/src/actor.rs:177: 139 Handling message Broadcast +2025-11-14T18:24:36.681935Z  INFO ThreadId(56) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(0, 50) (epoch 0, view 50), parent height: 49 +2025-11-14T18:24:36.682014Z  INFO ThreadId(36) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(0, 50) (epoch 0, view 50), parent height: 49 +2025-11-14T18:24:36.682027Z  INFO ThreadId(43) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(0, 50) (epoch 0, view 50), parent height: 49 +2025-11-14T18:24:36.685191Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:149: 55 application: Handling message Propose for round Round(0, 51) (epoch 0, view 51), parent height: 50 +2025-11-14T18:24:36.750227Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 50) (last_processed_height=48, tip=48) +2025-11-14T18:24:36.751096Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 50) (last_processed_height=48, tip=48) +2025-11-14T18:24:36.751466Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 49 (previous tip: 48) +2025-11-14T18:24:36.751476Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 49 (last_processed_height: 48, tip: 49) +2025-11-14T18:24:36.751723Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 49)], last_processed_height: 48, tip: 49 +2025-11-14T18:24:36.751729Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:36.751843Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 49 (previous tip: 48) +2025-11-14T18:24:36.751849Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 49 (last_processed_height: 48, tip: 49) +2025-11-14T18:24:36.751968Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 49)], last_processed_height: 48, tip: 49 +2025-11-14T18:24:36.751970Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:36.752049Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 50) (last_processed_height=48, tip=48) +2025-11-14T18:24:36.752065Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 50) (last_processed_height=48, tip=48) +2025-11-14T18:24:36.752554Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 49 (previous tip: 48) +2025-11-14T18:24:36.752562Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 49 (last_processed_height: 48, tip: 49) +2025-11-14T18:24:36.752705Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 49)], last_processed_height: 48, tip: 49 +2025-11-14T18:24:36.752709Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:36.752765Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 49 (previous tip: 48) +2025-11-14T18:24:36.752773Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 49 (last_processed_height: 48, tip: 49) +2025-11-14T18:24:36.752952Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 49)], last_processed_height: 48, tip: 49 +2025-11-14T18:24:36.752958Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:36.753093Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x69312bb9acb0fe8a22c47e121a7e86bfa6cca54adeb1b033668f40c20b85d68e for height 49 +2025-11-14T18:24:36.753116Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x69312bb9acb0fe8a22c47e121a7e86bfa6cca54adeb1b033668f40c20b85d68e for height 49 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 49 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 49, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 49, is last block: true +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 49 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 49, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 49, is last block: true +2025-11-14T18:24:36.753712Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:451: finalizer: epoch transition to epoch 1 with 5 validators at height 49 ++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++ +2025-11-14T18:24:36.753777Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x69312bb9acb0fe8a22c47e121a7e86bfa6cca54adeb1b033668f40c20b85d68e for height 49 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 49 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 49, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 49, is last block: true +Created checkpoint at epoch 0, height 48, view 49 +2025-11-14T18:24:36.754042Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:451: finalizer: epoch transition to epoch 1 with 5 validators at height 49 ++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++ +2025-11-14T18:24:36.754112Z  INFO ThreadId(50) summit_orchestrator::actor: orchestrator/src/actor.rs:307: orchestrator: received Enter message for epoch 1 with 5 validators +2025-11-14T18:24:36.754136Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x69312bb9acb0fe8a22c47e121a7e86bfa6cca54adeb1b033668f40c20b85d68e for height 49 +2025-11-14T18:24:36.754149Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=49 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 49 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 49, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 49, is last block: true +2025-11-14T18:24:36.754296Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 50 not found (last_processed=49, tip=49) +Created checkpoint at epoch 0, height 48, view 49 +2025-11-14T18:24:36.754407Z  INFO ThreadId(46) summit_orchestrator::actor: orchestrator/src/actor.rs:307: orchestrator: received Enter message for epoch 1 with 5 validators +2025-11-14T18:24:36.754448Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=49 +2025-11-14T18:24:36.754471Z  INFO ThreadId(50) summit_orchestrator::actor: orchestrator/src/actor.rs:406: orchestrator: starting Simplex engine for epoch 1 +2025-11-14T18:24:36.754481Z  INFO ThreadId(50) summit_orchestrator::actor: orchestrator/src/actor.rs:335: entered epoch epoch=1 +2025-11-14T18:24:36.754487Z  INFO ThreadId(50) summit_orchestrator::actor: orchestrator/src/actor.rs:348: exited epoch epoch=0 +2025-11-14T18:24:36.754546Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:451: finalizer: epoch transition to epoch 1 with 5 validators at height 49 ++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++ +2025-11-14T18:24:36.754565Z  INFO ThreadId(49) commonware_consensus::simplex::actors::voter::actor: /home/matthias/.cargo/git/checkouts/monorepo-9732103c47eb4665/f395c9e/consensus/src/simplex/actors/voter/actor.rs:1688: consensus initialized current_view=1 elapsed=1.453µs +2025-11-14T18:24:36.754612Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 50 not found (last_processed=49, tip=49) +2025-11-14T18:24:36.754692Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:451: finalizer: epoch transition to epoch 1 with 5 validators at height 49 ++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++ +2025-11-14T18:24:36.754774Z  INFO ThreadId(46) summit_orchestrator::actor: orchestrator/src/actor.rs:406: orchestrator: starting Simplex engine for epoch 1 +2025-11-14T18:24:36.754783Z  INFO ThreadId(46) summit_orchestrator::actor: orchestrator/src/actor.rs:335: entered epoch epoch=1 +2025-11-14T18:24:36.754786Z  INFO ThreadId(46) summit_orchestrator::actor: orchestrator/src/actor.rs:348: exited epoch epoch=0 +Created checkpoint at epoch 0, height 48, view 49 +2025-11-14T18:24:36.754855Z  INFO ThreadId(43) commonware_consensus::simplex::actors::voter::actor: /home/matthias/.cargo/git/checkouts/monorepo-9732103c47eb4665/f395c9e/consensus/src/simplex/actors/voter/actor.rs:1688: consensus initialized current_view=1 elapsed=541ns +2025-11-14T18:24:36.754922Z  INFO ThreadId(55) summit_orchestrator::actor: orchestrator/src/actor.rs:307: orchestrator: received Enter message for epoch 1 with 5 validators +Created checkpoint at epoch 0, height 48, view 49 +2025-11-14T18:24:36.754957Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=49 +2025-11-14T18:24:36.754970Z  WARN ThreadId(56) summit_application::actor: application/src/actor.rs:167: Failed to create a block for round Round(0, 51): Aborting block proposal for epoch 1. Current epoch is 1 +2025-11-14T18:24:36.755080Z  INFO ThreadId(35) summit_orchestrator::actor: orchestrator/src/actor.rs:307: orchestrator: received Enter message for epoch 1 with 5 validators +2025-11-14T18:24:36.755107Z  INFO ThreadId(37) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=49 +2025-11-14T18:24:36.755128Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 50 not found (last_processed=49, tip=49) +2025-11-14T18:24:36.755238Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 50 not found (last_processed=49, tip=49) +2025-11-14T18:24:36.755264Z  INFO ThreadId(55) summit_orchestrator::actor: orchestrator/src/actor.rs:406: orchestrator: starting Simplex engine for epoch 1 +2025-11-14T18:24:36.755271Z  INFO ThreadId(55) summit_orchestrator::actor: orchestrator/src/actor.rs:335: entered epoch epoch=1 +2025-11-14T18:24:36.755274Z  INFO ThreadId(55) summit_orchestrator::actor: orchestrator/src/actor.rs:348: exited epoch epoch=0 +2025-11-14T18:24:36.755318Z  INFO ThreadId(56) commonware_consensus::simplex::actors::voter::actor: /home/matthias/.cargo/git/checkouts/monorepo-9732103c47eb4665/f395c9e/consensus/src/simplex/actors/voter/actor.rs:1688: consensus initialized current_view=1 elapsed=400ns +2025-11-14T18:24:36.755441Z  INFO ThreadId(35) summit_orchestrator::actor: orchestrator/src/actor.rs:406: orchestrator: starting Simplex engine for epoch 1 +2025-11-14T18:24:36.755449Z  INFO ThreadId(35) summit_orchestrator::actor: orchestrator/src/actor.rs:335: entered epoch epoch=1 +2025-11-14T18:24:36.755452Z  INFO ThreadId(35) summit_orchestrator::actor: orchestrator/src/actor.rs:348: exited epoch epoch=0 +2025-11-14T18:24:36.755508Z  INFO ThreadId(36) commonware_consensus::simplex::actors::voter::actor: /home/matthias/.cargo/git/checkouts/monorepo-9732103c47eb4665/f395c9e/consensus/src/simplex/actors/voter/actor.rs:1688: consensus initialized current_view=1 elapsed=451ns +2025-11-14T18:24:36.809809Z  INFO ThreadId(52) summit_application::actor: application/src/actor.rs:149: 139 application: Handling message Propose for round Round(1, 2) (epoch 1, view 2), parent height: 0 +2025-11-14T18:24:36.862089Z  INFO ThreadId(52) summit_application::actor: application/src/actor.rs:177: 139 Handling message Broadcast +2025-11-14T18:24:36.865434Z  INFO ThreadId(35) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(1, 2) (epoch 1, view 2), parent height: 0 +2025-11-14T18:24:36.865720Z  INFO ThreadId(37) summit_syncer::cache: syncer/src/cache.rs:227: restored verified archive elapsed=96.928µs +2025-11-14T18:24:36.865827Z  INFO ThreadId(37) summit_syncer::cache: syncer/src/cache.rs:227: restored notarized archive elapsed=93.601µs +2025-11-14T18:24:36.865896Z  INFO ThreadId(37) summit_syncer::cache: syncer/src/cache.rs:227: restored notarizations archive elapsed=62.024µs +2025-11-14T18:24:36.866001Z  INFO ThreadId(36) summit_syncer::cache: syncer/src/cache.rs:227: restored finalizations archive elapsed=96.667µs +2025-11-14T18:24:36.879446Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 2) (epoch 1, view 2), parent height: 0 +2025-11-14T18:24:36.879635Z  INFO ThreadId(43) summit_syncer::cache: syncer/src/cache.rs:227: restored verified archive elapsed=53.237µs +2025-11-14T18:24:36.879694Z  INFO ThreadId(43) summit_syncer::cache: syncer/src/cache.rs:227: restored notarized archive elapsed=51.094µs +2025-11-14T18:24:36.879723Z  INFO ThreadId(43) summit_syncer::cache: syncer/src/cache.rs:227: restored notarizations archive elapsed=26.448µs +2025-11-14T18:24:36.879794Z  INFO ThreadId(44) summit_syncer::cache: syncer/src/cache.rs:227: restored finalizations archive elapsed=69.006µs +2025-11-14T18:24:36.879902Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 2) (epoch 1, view 2), parent height: 0 +2025-11-14T18:24:36.880085Z  INFO ThreadId(57) summit_syncer::cache: syncer/src/cache.rs:227: restored verified archive elapsed=49.371µs +2025-11-14T18:24:36.880155Z  INFO ThreadId(57) summit_syncer::cache: syncer/src/cache.rs:227: restored notarized archive elapsed=58.587µs +2025-11-14T18:24:36.880227Z  INFO ThreadId(57) summit_syncer::cache: syncer/src/cache.rs:227: restored notarizations archive elapsed=65.48µs +2025-11-14T18:24:36.880276Z  INFO ThreadId(57) summit_syncer::cache: syncer/src/cache.rs:227: restored finalizations archive elapsed=43.81µs +2025-11-14T18:24:36.882051Z  INFO ThreadId(52) summit_syncer::cache: syncer/src/cache.rs:227: restored verified archive elapsed=57.015µs +2025-11-14T18:24:36.882086Z  INFO ThreadId(52) summit_syncer::cache: syncer/src/cache.rs:227: restored notarized archive elapsed=29.794µs +2025-11-14T18:24:36.882119Z  INFO ThreadId(52) summit_syncer::cache: syncer/src/cache.rs:227: restored notarizations archive elapsed=28.031µs +2025-11-14T18:24:36.882147Z  INFO ThreadId(52) summit_syncer::cache: syncer/src/cache.rs:227: restored finalizations archive elapsed=23.082µs +2025-11-14T18:24:36.882497Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:149: 55 application: Handling message Propose for round Round(1, 3) (epoch 1, view 3), parent height: 2 +Node 0 at height 49 +2025-11-14T18:24:36.934783Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 2) (last_processed_height=49, tip=49) +2025-11-14T18:24:36.936144Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 50 (previous tip: 49) +2025-11-14T18:24:36.936162Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 50 (last_processed_height: 49, tip: 50) +2025-11-14T18:24:36.936224Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 50)], last_processed_height: 49, tip: 50 +2025-11-14T18:24:36.936230Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:36.938135Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x05635d16b013b603bb6adf35759261f5357aaf2ded8f813800e1f9da4c400d1e for height 50 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 50 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 50, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 50, is last block: false +2025-11-14T18:24:36.939208Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=50 +2025-11-14T18:24:36.939583Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 51 not found (last_processed=50, tip=50) +2025-11-14T18:24:37.001491Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 2) (last_processed_height=49, tip=49) +2025-11-14T18:24:37.002124Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 2) (last_processed_height=49, tip=49) +2025-11-14T18:24:37.002493Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 2) (last_processed_height=49, tip=49) +2025-11-14T18:24:37.002932Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 50 (previous tip: 49) +2025-11-14T18:24:37.002947Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 50 (last_processed_height: 49, tip: 50) +2025-11-14T18:24:37.003017Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 50)], last_processed_height: 49, tip: 50 +2025-11-14T18:24:37.003026Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:37.003041Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 50 (previous tip: 49) +2025-11-14T18:24:37.003047Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 50 (last_processed_height: 49, tip: 50) +2025-11-14T18:24:37.003085Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 50)], last_processed_height: 49, tip: 50 +2025-11-14T18:24:37.003087Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:37.003854Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 50 (previous tip: 49) +2025-11-14T18:24:37.003862Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 50 (last_processed_height: 49, tip: 50) +2025-11-14T18:24:37.003917Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 50)], last_processed_height: 49, tip: 50 +2025-11-14T18:24:37.003924Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:37.004427Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x05635d16b013b603bb6adf35759261f5357aaf2ded8f813800e1f9da4c400d1e for height 50 +2025-11-14T18:24:37.004428Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x05635d16b013b603bb6adf35759261f5357aaf2ded8f813800e1f9da4c400d1e for height 50 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 50 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 50, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 50, is last block: false +2025-11-14T18:24:37.004583Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=50 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 50 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 50, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 50, is last block: false +2025-11-14T18:24:37.004646Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=50 +2025-11-14T18:24:37.004758Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 51 not found (last_processed=50, tip=50) +2025-11-14T18:24:37.004929Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 51 not found (last_processed=50, tip=50) +2025-11-14T18:24:37.005253Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x05635d16b013b603bb6adf35759261f5357aaf2ded8f813800e1f9da4c400d1e for height 50 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 50 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 50, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 50, is last block: false +2025-11-14T18:24:37.005433Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=50 +2025-11-14T18:24:37.005603Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 51 not found (last_processed=50, tip=50) +2025-11-14T18:24:37.057208Z  INFO ThreadId(56) summit_application::actor: application/src/actor.rs:177: 55 Handling message Broadcast +2025-11-14T18:24:37.059756Z  INFO ThreadId(38) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(1, 3) (epoch 1, view 3), parent height: 2 +2025-11-14T18:24:37.059835Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 3) (epoch 1, view 3), parent height: 2 +2025-11-14T18:24:37.060432Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 3) (epoch 1, view 3), parent height: 2 +2025-11-14T18:24:37.062950Z  INFO ThreadId(38) summit_application::actor: application/src/actor.rs:149: 209 application: Handling message Propose for round Round(1, 4) (epoch 1, view 4), parent height: 3 +2025-11-14T18:24:37.128672Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 3) (last_processed_height=50, tip=50) +2025-11-14T18:24:37.129381Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 51 (previous tip: 50) +2025-11-14T18:24:37.129389Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 51 (last_processed_height: 50, tip: 51) +2025-11-14T18:24:37.129438Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 51)], last_processed_height: 50, tip: 51 +2025-11-14T18:24:37.129443Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:37.129612Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 3) (last_processed_height=50, tip=50) +2025-11-14T18:24:37.129705Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 3) (last_processed_height=50, tip=50) +2025-11-14T18:24:37.129775Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 3) (last_processed_height=50, tip=50) +2025-11-14T18:24:37.130188Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 51 (previous tip: 50) +2025-11-14T18:24:37.130197Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 51 (last_processed_height: 50, tip: 51) +2025-11-14T18:24:37.130239Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 51)], last_processed_height: 50, tip: 51 +2025-11-14T18:24:37.130243Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:37.130265Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 51 (previous tip: 50) +2025-11-14T18:24:37.130270Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 51 (last_processed_height: 50, tip: 51) +2025-11-14T18:24:37.130307Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 51)], last_processed_height: 50, tip: 51 +2025-11-14T18:24:37.130311Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:37.130325Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 51 (previous tip: 50) +2025-11-14T18:24:37.130331Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 51 (last_processed_height: 50, tip: 51) +2025-11-14T18:24:37.130380Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 51)], last_processed_height: 50, tip: 51 +2025-11-14T18:24:37.130383Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:37.130634Z  INFO ThreadId(36) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7864fb19307bd2d6219815712c0b995a0febe14d611e9af7084e8f7b1ed19f73 for height 51 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 51 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 51, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 51, is last block: false +2025-11-14T18:24:37.130942Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=51 +2025-11-14T18:24:37.131537Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7864fb19307bd2d6219815712c0b995a0febe14d611e9af7084e8f7b1ed19f73 for height 51 +2025-11-14T18:24:37.131704Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7864fb19307bd2d6219815712c0b995a0febe14d611e9af7084e8f7b1ed19f73 for height 51 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 51 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 51, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 51, is last block: false +2025-11-14T18:24:37.131721Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=51 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 51 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 51, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 51, is last block: false +2025-11-14T18:24:37.131847Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=51 +2025-11-14T18:24:37.132170Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7864fb19307bd2d6219815712c0b995a0febe14d611e9af7084e8f7b1ed19f73 for height 51 +2025-11-14T18:24:37.132179Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 52 not found (last_processed=51, tip=51) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 51 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 51, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 51, is last block: false +2025-11-14T18:24:37.132310Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=51 +2025-11-14T18:24:37.132702Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 52 not found (last_processed=51, tip=51) +2025-11-14T18:24:37.133356Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 52 not found (last_processed=51, tip=51) +2025-11-14T18:24:37.133373Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 52 not found (last_processed=51, tip=51) +2025-11-14T18:24:37.182609Z  INFO ThreadId(36) summit_application::actor: application/src/actor.rs:177: 209 Handling message Broadcast +2025-11-14T18:24:37.184957Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 4) (epoch 1, view 4), parent height: 3 +2025-11-14T18:24:37.185654Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 4) (epoch 1, view 4), parent height: 3 +2025-11-14T18:24:37.249608Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 4) (epoch 1, view 4), parent height: 3 +2025-11-14T18:24:37.251566Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:149: 15 application: Handling message Propose for round Round(1, 5) (epoch 1, view 5), parent height: 4 +2025-11-14T18:24:37.307743Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 4) (last_processed_height=51, tip=51) +2025-11-14T18:24:37.308780Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 52 (previous tip: 51) +2025-11-14T18:24:37.308800Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 52 (last_processed_height: 51, tip: 52) +2025-11-14T18:24:37.308894Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 52)], last_processed_height: 51, tip: 52 +2025-11-14T18:24:37.308903Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:37.309134Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 4) (last_processed_height=51, tip=51) +2025-11-14T18:24:37.309219Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 4) (last_processed_height=51, tip=51) +2025-11-14T18:24:37.309869Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 52 (previous tip: 51) +2025-11-14T18:24:37.309877Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 52 (last_processed_height: 51, tip: 52) +2025-11-14T18:24:37.309930Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 52)], last_processed_height: 51, tip: 52 +2025-11-14T18:24:37.309937Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:37.310014Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 4) (last_processed_height=51, tip=51) +2025-11-14T18:24:37.310087Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 52 (previous tip: 51) +2025-11-14T18:24:37.310095Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 52 (last_processed_height: 51, tip: 52) +2025-11-14T18:24:37.310130Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 52)], last_processed_height: 51, tip: 52 +2025-11-14T18:24:37.310135Z  INFO ThreadId(36) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:37.310543Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x70ab1810346119550aa5f68655fcf401135790f2127703c36751330bcb63cddd for height 52 +2025-11-14T18:24:37.310607Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 52 (previous tip: 51) +2025-11-14T18:24:37.310614Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 52 (last_processed_height: 51, tip: 52) +2025-11-14T18:24:37.310643Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 52)], last_processed_height: 51, tip: 52 +2025-11-14T18:24:37.310647Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 52 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 52, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 52, is last block: false +2025-11-14T18:24:37.310782Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=52 +2025-11-14T18:24:37.310973Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 53 not found (last_processed=52, tip=52) +2025-11-14T18:24:37.311351Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x70ab1810346119550aa5f68655fcf401135790f2127703c36751330bcb63cddd for height 52 +2025-11-14T18:24:37.311375Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x70ab1810346119550aa5f68655fcf401135790f2127703c36751330bcb63cddd for height 52 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 52 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 52, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 52, is last block: false +2025-11-14T18:24:37.311522Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=52 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 52 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 52, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 52, is last block: false +2025-11-14T18:24:37.311581Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=52 +2025-11-14T18:24:37.311767Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 53 not found (last_processed=52, tip=52) +2025-11-14T18:24:37.311786Z  INFO ThreadId(35) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 53 not found (last_processed=52, tip=52) +2025-11-14T18:24:37.311932Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x70ab1810346119550aa5f68655fcf401135790f2127703c36751330bcb63cddd for height 52 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 52 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 52, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 52, is last block: false +2025-11-14T18:24:37.312067Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=52 +2025-11-14T18:24:37.312239Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 53 not found (last_processed=52, tip=52) +2025-11-14T18:24:37.363864Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:177: 15 Handling message Broadcast +2025-11-14T18:24:37.377260Z  INFO ThreadId(49) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 5) (epoch 1, view 5), parent height: 4 +2025-11-14T18:24:37.377421Z  INFO ThreadId(35) summit_application::actor: application/src/actor.rs:200: 209 application: Handling message Verify for round Round(1, 5) (epoch 1, view 5), parent height: 4 +2025-11-14T18:24:37.378316Z  INFO ThreadId(56) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 5) (epoch 1, view 5), parent height: 4 +2025-11-14T18:24:37.434165Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 5) (last_processed_height=52, tip=52) +2025-11-14T18:24:37.435406Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 53 (previous tip: 52) +2025-11-14T18:24:37.435419Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 53 (last_processed_height: 52, tip: 53) +2025-11-14T18:24:37.435482Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 53)], last_processed_height: 52, tip: 53 +2025-11-14T18:24:37.435489Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:37.436509Z  INFO ThreadId(38) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x80a96b1c970b93446950f3c8b8ce282cbc20f284025412c93f391e758363cccb for height 53 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 53 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 53, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 53, is last block: false +2025-11-14T18:24:37.436664Z  INFO ThreadId(36) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=53 +2025-11-14T18:24:37.436851Z  INFO ThreadId(38) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 54 not found (last_processed=53, tip=53) +2025-11-14T18:24:37.500964Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 5) (last_processed_height=52, tip=52) +2025-11-14T18:24:37.501080Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 5) (last_processed_height=52, tip=52) +2025-11-14T18:24:37.501118Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 5) (last_processed_height=52, tip=52) +2025-11-14T18:24:37.501838Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 53 (previous tip: 52) +2025-11-14T18:24:37.501846Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 53 (last_processed_height: 52, tip: 53) +2025-11-14T18:24:37.501881Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 53)], last_processed_height: 52, tip: 53 +2025-11-14T18:24:37.501885Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:37.502089Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 53 (previous tip: 52) +2025-11-14T18:24:37.502101Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 53 (last_processed_height: 52, tip: 53) +2025-11-14T18:24:37.502171Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 53)], last_processed_height: 52, tip: 53 +2025-11-14T18:24:37.502178Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:37.502327Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 53 (previous tip: 52) +2025-11-14T18:24:37.502337Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 53 (last_processed_height: 52, tip: 53) +2025-11-14T18:24:37.502397Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 53)], last_processed_height: 52, tip: 53 +2025-11-14T18:24:37.502404Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:37.503462Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x80a96b1c970b93446950f3c8b8ce282cbc20f284025412c93f391e758363cccb for height 53 +2025-11-14T18:24:37.503500Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x80a96b1c970b93446950f3c8b8ce282cbc20f284025412c93f391e758363cccb for height 53 +2025-11-14T18:24:37.503590Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x80a96b1c970b93446950f3c8b8ce282cbc20f284025412c93f391e758363cccb for height 53 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 53 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 53, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 53, is last block: false +2025-11-14T18:24:37.503634Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=53 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 53 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 53, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 53, is last block: false +2025-11-14T18:24:37.503696Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=53 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 53 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 53, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 53, is last block: false +2025-11-14T18:24:37.503743Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=53 +2025-11-14T18:24:37.503823Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 54 not found (last_processed=53, tip=53) +2025-11-14T18:24:37.503843Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 54 not found (last_processed=53, tip=53) +2025-11-14T18:24:37.503849Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 54 not found (last_processed=53, tip=53) +Nodes reached checkpoint height 53 +Retrieving checkpoint from node 0 +Retrieved checkpoint at height 48 +******* STARTING RETH FOR NODE 4 (joining node) +Stopping node0 consensus engine... +Waiting for node0 runtime to shut down... +Node 0 received stop signal, shutting down runtime... +2025-11-14T18:24:37.953784Z  INFO ThreadId(38) summit_application::actor: application/src/actor.rs:259: runtime terminated, shutting down application: 0 +2025-11-14T18:24:37.953780Z  INFO ThreadId(36) summit::prom::server: node/src/prom/server.rs:102: Metrics server shutting down: 0 +2025-11-14T18:24:37.953798Z  INFO ThreadId(38) summit::engine: node/src/engine.rs:380: cancellation triggered, waiting for actors to finish +RPC server stopped: 0 +2025-11-14T18:24:37.953803Z  INFO ThreadId(37) summit_syncer::actor: syncer/src/actor.rs:611: handler closed, shutting down +2025-11-14T18:24:37.953832Z  INFO ThreadId(35) summit_finalizer::actor: finalizer/src/actor.rs:218: finalizer received cancellation signal, exiting +2025-11-14T18:24:37.954044Z  WARN ThreadId(38) summit_orchestrator::actor: orchestrator/src/actor.rs:301: mailbox closed, shutting down orchestrator +2025-11-14T18:24:37.954044Z  INFO ThreadId(35) alloy_pubsub::service: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-pubsub-1.0.30/src/service.rs:256: Pubsub service request channel closed. Shutting down. +Waiting for ports to be released... +Sending SIGTERM to node0 Reth and waiting for shutdown... +Node0 shut down successfully +Copying db from node0 to node4 +2025-11-14T18:24:41.182995Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:41.435391Z ERROR ThreadId(15) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:41.686865Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +Copying static_files from node0 to node4 +2025-11-14T18:24:41.939085Z ERROR ThreadId(15) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:42.191488Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:42.442454Z ERROR ThreadId(15) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +Node 4 rpc address: 8541 +Starting consensus engine for node ae3a9bc6eb721b7b8a34d23aa0d5b1623e89bc6f092815ea13b92f79a39c7d38 with checkpoint +Waiting for all 5 nodes to reach height 100 +Keystore directory: /tmp/summit_checkpointing_test/node4/data +Genesis RPC Server listening on http://0.0.0.0:3070 +Genesis RPC server stopped +2025-11-14T18:24:42.662036Z  INFO ThreadId(88) commonware_p2p::authenticated::discovery::network: /home/matthias/.cargo/git/checkouts/monorepo-9732103c47eb4665/f395c9e/p2p/src/authenticated/discovery/network.rs:189: network started +2025-11-14T18:24:42.663921Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:220: restored finalizations by height archive elapsed=1.688746ms +2025-11-14T18:24:42.664412Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:254: restored finalized blocks archive elapsed=478.317µs +################################################ +################################################ +2025-11-14T18:24:42.665313Z  INFO ThreadId(89) summit_finalizer::actor: finalizer/src/actor.rs:116: Consensus state not found in database, using provided state with epoch 0 and height 48 - epoch_num_of_blocks: 50 +RPC Server listening on http://0.0.0.0:3070 +2025-11-14T18:24:42.666348Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:389: syncer: starting from checkpoint at height 48, epoch 0, view 49 +2025-11-14T18:24:42.666402Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 49 not found (last_processed=48, tip=48) +2025-11-14T18:24:42.666421Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [], last_processed_height: 48, tip: 48 +2025-11-14T18:24:42.666437Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:42.666466Z  INFO ThreadId(91) summit_orchestrator::actor: orchestrator/src/actor.rs:307: orchestrator: received Enter message for epoch 0 with 4 validators +2025-11-14T18:24:42.667105Z  INFO ThreadId(91) summit_orchestrator::actor: orchestrator/src/actor.rs:406: orchestrator: starting Simplex engine for epoch 0 +2025-11-14T18:24:42.667120Z  INFO ThreadId(91) summit_orchestrator::actor: orchestrator/src/actor.rs:335: entered epoch epoch=0 +2025-11-14T18:24:42.667200Z  INFO ThreadId(91) commonware_consensus::simplex::actors::voter::actor: /home/matthias/.cargo/git/checkouts/monorepo-9732103c47eb4665/f395c9e/consensus/src/simplex/actors/voter/actor.rs:1688: consensus initialized current_view=1 elapsed=1.573µs +Node 1 at height 53 +Node 2 at height 53 +Node 3 at height 53 +2025-11-14T18:24:42.693827Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +Node 4 at height 48 +2025-11-14T18:24:42.946762Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:43.199657Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:43.385980Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(0, 50) (last_processed_height=48, tip=48) +2025-11-14T18:24:43.386036Z  INFO ThreadId(89) summit_syncer::cache: syncer/src/cache.rs:227: restored verified archive elapsed=43.34µs +2025-11-14T18:24:43.386076Z  INFO ThreadId(89) summit_syncer::cache: syncer/src/cache.rs:227: restored notarized archive elapsed=34.213µs +2025-11-14T18:24:43.386103Z  INFO ThreadId(89) summit_syncer::cache: syncer/src/cache.rs:227: restored notarizations archive elapsed=22.621µs +2025-11-14T18:24:43.386124Z  INFO ThreadId(89) summit_syncer::cache: syncer/src/cache.rs:227: restored finalizations archive elapsed=18.754µs +2025-11-14T18:24:43.452511Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:43.704297Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:43.956880Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:44.209596Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:44.462448Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +Node 1 at height 53 +2025-11-14T18:24:44.714292Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +Node 2 at height 53 +Node 3 at height 53 +Node 4 at height 48 +2025-11-14T18:24:44.966356Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:45.218009Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:45.390465Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 49 (previous tip: 48) +2025-11-14T18:24:45.390476Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 49 (last_processed_height: 48, tip: 49) +2025-11-14T18:24:45.390598Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 49)], last_processed_height: 48, tip: 49 +2025-11-14T18:24:45.390602Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:45.391081Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x69312bb9acb0fe8a22c47e121a7e86bfa6cca54adeb1b033668f40c20b85d68e for height 49 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 49 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 49, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 49, is last block: true +2025-11-14T18:24:45.391571Z  INFO ThreadId(90) summit_finalizer::actor: finalizer/src/actor.rs:451: finalizer: epoch transition to epoch 1 with 5 validators at height 49 +2025-11-14T18:24:45.391746Z  INFO ThreadId(90) summit_orchestrator::actor: orchestrator/src/actor.rs:307: orchestrator: received Enter message for epoch 1 with 5 validators +2025-11-14T18:24:45.391800Z  INFO ThreadId(88) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=49 +2025-11-14T18:24:45.391928Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 50 not found (last_processed=49, tip=49) +2025-11-14T18:24:45.392520Z  INFO ThreadId(90) summit_orchestrator::actor: orchestrator/src/actor.rs:406: orchestrator: starting Simplex engine for epoch 1 +2025-11-14T18:24:45.392542Z  INFO ThreadId(90) summit_orchestrator::actor: orchestrator/src/actor.rs:335: entered epoch epoch=1 +2025-11-14T18:24:45.392550Z  INFO ThreadId(90) summit_orchestrator::actor: orchestrator/src/actor.rs:348: exited epoch epoch=0 +2025-11-14T18:24:45.392646Z  INFO ThreadId(89) commonware_consensus::simplex::actors::voter::actor: /home/matthias/.cargo/git/checkouts/monorepo-9732103c47eb4665/f395c9e/consensus/src/simplex/actors/voter/actor.rs:1688: consensus initialized current_view=1 elapsed=2.144µs +2025-11-14T18:24:45.392697Z  INFO ThreadId(89) summit_application::actor: application/src/actor.rs:149: 143 application: Handling message Propose for round Round(1, 1) (epoch 1, view 1), parent height: 0 +2025-11-14T18:24:45.392884Z  WARN ThreadId(89) summit_application::actor: application/src/actor.rs:167: Failed to create a block for round Round(1, 1): Unable to build payload +2025-11-14T18:24:45.470791Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:45.723736Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:45.976386Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:46.227923Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:46.480451Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:46.731834Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +Node 1 at height 53 +Node 2 at height 53 +Node 3 at height 53 +Node 4 at height 49 +2025-11-14T18:24:46.985106Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:47.237511Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:47.388087Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 5) (last_processed_height=49, tip=49) +2025-11-14T18:24:47.388225Z  INFO ThreadId(90) summit_application::actor: application/src/actor.rs:149: 143 application: Handling message Propose for round Round(1, 6) (epoch 1, view 6), parent height: 5 +2025-11-14T18:24:47.388233Z  INFO ThreadId(88) summit_syncer::cache: syncer/src/cache.rs:227: restored verified archive elapsed=67.094µs +2025-11-14T18:24:47.388293Z  INFO ThreadId(88) summit_syncer::cache: syncer/src/cache.rs:227: restored notarized archive elapsed=53.268µs +2025-11-14T18:24:47.388326Z  INFO ThreadId(88) summit_syncer::cache: syncer/src/cache.rs:227: restored notarizations archive elapsed=27.821µs +2025-11-14T18:24:47.388377Z  INFO ThreadId(88) summit_syncer::cache: syncer/src/cache.rs:227: restored finalizations archive elapsed=45.363µs +2025-11-14T18:24:47.389578Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 53 (previous tip: 49) +2025-11-14T18:24:47.389584Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 53 (last_processed_height: 49, tip: 53) +2025-11-14T18:24:47.389586Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 50 not found (last_processed=49, tip=53) +2025-11-14T18:24:47.389589Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 49), (53, 53)], last_processed_height: 49, tip: 53 +2025-11-14T18:24:47.389592Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [(50, 53)] +2025-11-14T18:24:47.389649Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1115: syncer: requesting finalized blocks in range 50..53 (last_processed_height: 49, tip: 53) +2025-11-14T18:24:47.390853Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 53 (last_processed_height: 49, tip: 53) +2025-11-14T18:24:47.390856Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 50 not found (last_processed=49, tip=53) +2025-11-14T18:24:47.390858Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 49), (53, 53)], last_processed_height: 49, tip: 53 +2025-11-14T18:24:47.390859Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [(50, 53)] +2025-11-14T18:24:47.390906Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1115: syncer: requesting finalized blocks in range 50..53 (last_processed_height: 49, tip: 53) +2025-11-14T18:24:47.391527Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 52 (last_processed_height: 49, tip: 53) +2025-11-14T18:24:47.391531Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 50 not found (last_processed=49, tip=53) +2025-11-14T18:24:47.391533Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 49), (52, 53)], last_processed_height: 49, tip: 53 +2025-11-14T18:24:47.391535Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [(50, 52)] +2025-11-14T18:24:47.391580Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1115: syncer: requesting finalized blocks in range 50..52 (last_processed_height: 49, tip: 53) +2025-11-14T18:24:47.393860Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:718: syncer: received finalized block 50 via resolver (last_processed_height: 49, tip: 53) +2025-11-14T18:24:47.395277Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 50 (last_processed_height: 49, tip: 53) +2025-11-14T18:24:47.395345Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 50), (52, 53)], last_processed_height: 49, tip: 53 +2025-11-14T18:24:47.395350Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [(51, 52)] +2025-11-14T18:24:47.395457Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1115: syncer: requesting finalized blocks in range 51..52 (last_processed_height: 49, tip: 53) +2025-11-14T18:24:47.395880Z  INFO ThreadId(90) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x05635d16b013b603bb6adf35759261f5357aaf2ded8f813800e1f9da4c400d1e for height 50 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 50 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 50, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 50, is last block: false +2025-11-14T18:24:47.396093Z  INFO ThreadId(88) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=50 +2025-11-14T18:24:47.396584Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:718: syncer: received finalized block 51 via resolver (last_processed_height: 49, tip: 53) +2025-11-14T18:24:47.397045Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 51 (last_processed_height: 49, tip: 53) +2025-11-14T18:24:47.397048Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 53)], last_processed_height: 49, tip: 53 +2025-11-14T18:24:47.397050Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:24:47.397310Z  INFO ThreadId(90) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7864fb19307bd2d6219815712c0b995a0febe14d611e9af7084e8f7b1ed19f73 for height 51 +2025-11-14T18:24:47.397359Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 51 (last_processed_height: 50, tip: 53) +2025-11-14T18:24:47.397362Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 53)], last_processed_height: 50, tip: 53 +2025-11-14T18:24:47.397364Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 51 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 51, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 51, is last block: false +2025-11-14T18:24:47.397436Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=51 +2025-11-14T18:24:47.400037Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x70ab1810346119550aa5f68655fcf401135790f2127703c36751330bcb63cddd for height 52 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 52 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 52, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 52, is last block: false +2025-11-14T18:24:47.400198Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=52 +2025-11-14T18:24:47.400797Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x80a96b1c970b93446950f3c8b8ce282cbc20f284025412c93f391e758363cccb for height 53 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 53 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 53, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 53, is last block: false +2025-11-14T18:24:47.400882Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=53 +2025-11-14T18:24:47.401018Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 54 not found (last_processed=53, tip=53) +2025-11-14T18:24:47.452939Z  INFO ThreadId(90) summit_application::actor: application/src/actor.rs:177: 143 Handling message Broadcast +2025-11-14T18:24:47.489210Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:47.741521Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:47.993071Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:48.245576Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:48.496578Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:48.747923Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +Node 1 at height 53 +Node 2 at height 53 +Node 3 at height 53 +Node 4 at height 53 +2025-11-14T18:24:49.000876Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:49.253399Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:49.505115Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:49.757806Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:50.010162Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:50.262180Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:50.515058Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:50.767992Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +Node 1 at height 53 +Node 2 at height 53 +Node 3 at height 53 +Node 4 at height 53 +2025-11-14T18:24:51.019898Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:51.272828Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:51.390858Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:149: 139 application: Handling message Propose for round Round(1, 7) (epoch 1, view 7), parent height: 5 +2025-11-14T18:24:51.442938Z  INFO ThreadId(52) summit_application::actor: application/src/actor.rs:177: 139 Handling message Broadcast +2025-11-14T18:24:51.445158Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 7) (epoch 1, view 7), parent height: 5 +2025-11-14T18:24:51.445316Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 7) (epoch 1, view 7), parent height: 5 +2025-11-14T18:24:51.525119Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:51.777472Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:52.028665Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:52.281092Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:52.533881Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:52.786507Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +Node 1 at height 53 +Node 2 at height 53 +Node 3 at height 53 +Node 4 at height 53 +2025-11-14T18:24:53.038657Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:53.291456Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:53.543193Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:53.795825Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:54.048449Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:54.300250Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:54.551946Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:54.804605Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +Node 1 at height 53 +Node 2 at height 53 +Node 3 at height 53 +Node 4 at height 53 +2025-11-14T18:24:55.056984Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:55.309590Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:55.394446Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:149: 55 application: Handling message Propose for round Round(1, 8) (epoch 1, view 8), parent height: 5 +2025-11-14T18:24:55.445885Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:177: 55 Handling message Broadcast +2025-11-14T18:24:55.448079Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 8) (epoch 1, view 8), parent height: 5 +2025-11-14T18:24:55.448352Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 8) (epoch 1, view 8), parent height: 5 +2025-11-14T18:24:55.561648Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:55.814158Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:56.067180Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:56.319783Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:56.572550Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:56.824252Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +Node 1 at height 53 +Node 2 at height 53 +Node 3 at height 53 +Node 4 at height 53 +2025-11-14T18:24:57.076686Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:57.329498Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:57.581234Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:57.833706Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:58.086641Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:58.339443Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:58.591223Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:58.844030Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +Node 1 at height 53 +Node 2 at height 53 +Node 3 at height 53 +Node 4 at height 53 +2025-11-14T18:24:59.096146Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:59.349060Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:59.601916Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:24:59.854727Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:00.107125Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:00.359751Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:00.612120Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:00.864747Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +Node 1 at height 53 +Node 2 at height 53 +Node 3 at height 53 +Node 4 at height 53 +2025-11-14T18:25:01.116833Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:01.369508Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:01.402806Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:149: 15 application: Handling message Propose for round Round(1, 10) (epoch 1, view 10), parent height: 5 +2025-11-14T18:25:01.455031Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:177: 15 Handling message Broadcast +2025-11-14T18:25:01.458821Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 10) (epoch 1, view 10), parent height: 5 +2025-11-14T18:25:01.458833Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 10) (epoch 1, view 10), parent height: 5 +2025-11-14T18:25:01.620761Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:01.872697Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:02.125094Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:02.377783Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:02.630404Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:02.882198Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +Node 1 at height 53 +Node 2 at height 53 +Node 3 at height 53 +Node 4 at height 53 +2025-11-14T18:25:03.134575Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:03.386284Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:03.638237Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:03.891211Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:04.143970Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:04.396838Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:04.649858Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:04.902666Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +Node 1 at height 53 +Node 2 at height 53 +Node 3 at height 53 +Node 4 at height 53 +2025-11-14T18:25:05.155321Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:05.406961Z  INFO ThreadId(91) summit_application::actor: application/src/actor.rs:149: 143 application: Handling message Propose for round Round(1, 11) (epoch 1, view 11), parent height: 5 +2025-11-14T18:25:05.407236Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:05.459347Z  INFO ThreadId(91) summit_application::actor: application/src/actor.rs:177: 143 Handling message Broadcast +2025-11-14T18:25:05.462186Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 11) (epoch 1, view 11), parent height: 5 +2025-11-14T18:25:05.462227Z  INFO ThreadId(52) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 11) (epoch 1, view 11), parent height: 5 +2025-11-14T18:25:05.462315Z  INFO ThreadId(57) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 11) (epoch 1, view 11), parent height: 5 +2025-11-14T18:25:05.465864Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 11) (last_processed_height=53, tip=53) +2025-11-14T18:25:05.466526Z  INFO ThreadId(52) summit_application::actor: application/src/actor.rs:149: 139 application: Handling message Propose for round Round(1, 12) (epoch 1, view 12), parent height: 11 +2025-11-14T18:25:05.466583Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 11) (last_processed_height=53, tip=53) +2025-11-14T18:25:05.466586Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 54 (previous tip: 53) +2025-11-14T18:25:05.466596Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 54 (last_processed_height: 53, tip: 54) +2025-11-14T18:25:05.466705Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 54)], last_processed_height: 53, tip: 54 +2025-11-14T18:25:05.466711Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:05.467046Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 11) (last_processed_height=53, tip=53) +2025-11-14T18:25:05.467132Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 54 (previous tip: 53) +2025-11-14T18:25:05.467137Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 54 (last_processed_height: 53, tip: 54) +2025-11-14T18:25:05.467177Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 54)], last_processed_height: 53, tip: 54 +2025-11-14T18:25:05.467182Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:05.467236Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 11) (last_processed_height=53, tip=53) +2025-11-14T18:25:05.467733Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 54 (previous tip: 53) +2025-11-14T18:25:05.467742Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 54 (last_processed_height: 53, tip: 54) +2025-11-14T18:25:05.467813Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 54)], last_processed_height: 53, tip: 54 +2025-11-14T18:25:05.467818Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:05.468137Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 54 (previous tip: 53) +2025-11-14T18:25:05.468143Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 54 (last_processed_height: 53, tip: 54) +2025-11-14T18:25:05.468188Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 54)], last_processed_height: 53, tip: 54 +2025-11-14T18:25:05.468191Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:05.468291Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x86dc221b973435675923134bbe7ed5533566ca98ccad58be3408f469954921a8 for height 54 +2025-11-14T18:25:05.468354Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x86dc221b973435675923134bbe7ed5533566ca98ccad58be3408f469954921a8 for height 54 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 54 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 54, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 54, is last block: false +2025-11-14T18:25:05.468470Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=54 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 54 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 54, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 54, is last block: false +2025-11-14T18:25:05.468570Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=54 +2025-11-14T18:25:05.468741Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 55 not found (last_processed=54, tip=54) +2025-11-14T18:25:05.468905Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 55 not found (last_processed=54, tip=54) +2025-11-14T18:25:05.469130Z  INFO ThreadId(88) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x86dc221b973435675923134bbe7ed5533566ca98ccad58be3408f469954921a8 for height 54 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 54 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 54, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 54, is last block: false +2025-11-14T18:25:05.469436Z  INFO ThreadId(88) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=54 +2025-11-14T18:25:05.469512Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x86dc221b973435675923134bbe7ed5533566ca98ccad58be3408f469954921a8 for height 54 +2025-11-14T18:25:05.469635Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 55 not found (last_processed=54, tip=54) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 54 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 54, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 54, is last block: false +2025-11-14T18:25:05.469688Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=54 +2025-11-14T18:25:05.469819Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 55 not found (last_processed=54, tip=54) +2025-11-14T18:25:05.520335Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:177: 139 Handling message Broadcast +2025-11-14T18:25:05.522914Z  INFO ThreadId(57) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 12) (epoch 1, view 12), parent height: 11 +2025-11-14T18:25:05.523514Z  INFO ThreadId(43) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 12) (epoch 1, view 12), parent height: 11 +2025-11-14T18:25:05.523525Z  INFO ThreadId(89) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 12) (epoch 1, view 12), parent height: 11 +2025-11-14T18:25:05.526578Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:149: 55 application: Handling message Propose for round Round(1, 13) (epoch 1, view 13), parent height: 12 +2025-11-14T18:25:05.527453Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 12) (last_processed_height=54, tip=54) +2025-11-14T18:25:05.527915Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 55 (previous tip: 54) +2025-11-14T18:25:05.527919Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 12) (last_processed_height=54, tip=54) +2025-11-14T18:25:05.527922Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 55 (last_processed_height: 54, tip: 55) +2025-11-14T18:25:05.527974Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 55)], last_processed_height: 54, tip: 55 +2025-11-14T18:25:05.527979Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:05.528343Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 55 (previous tip: 54) +2025-11-14T18:25:05.528348Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 55 (last_processed_height: 54, tip: 55) +2025-11-14T18:25:05.528362Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 12) (last_processed_height=54, tip=54) +2025-11-14T18:25:05.528373Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 55)], last_processed_height: 54, tip: 55 +2025-11-14T18:25:05.528377Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:05.528971Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 55 (previous tip: 54) +2025-11-14T18:25:05.528979Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 55 (last_processed_height: 54, tip: 55) +2025-11-14T18:25:05.529014Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 55)], last_processed_height: 54, tip: 55 +2025-11-14T18:25:05.529029Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:05.529145Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 12) (last_processed_height=54, tip=54) +2025-11-14T18:25:05.529357Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x66795f70d3a7d1d272d838e48f466d5706233b7d4cd2348fc76f66934cbd9bac for height 55 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 55 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 55, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 55, is last block: false +2025-11-14T18:25:05.529606Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=55 +2025-11-14T18:25:05.529613Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x66795f70d3a7d1d272d838e48f466d5706233b7d4cd2348fc76f66934cbd9bac for height 55 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 55 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 55, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 55, is last block: false +2025-11-14T18:25:05.529811Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=55 +2025-11-14T18:25:05.529816Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 56 not found (last_processed=55, tip=55) +2025-11-14T18:25:05.530004Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 56 not found (last_processed=55, tip=55) +2025-11-14T18:25:05.530085Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 55 (previous tip: 54) +2025-11-14T18:25:05.530110Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 55 (last_processed_height: 54, tip: 55) +2025-11-14T18:25:05.530167Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 55)], last_processed_height: 54, tip: 55 +2025-11-14T18:25:05.530170Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:05.530936Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x66795f70d3a7d1d272d838e48f466d5706233b7d4cd2348fc76f66934cbd9bac for height 55 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 55 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 55, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 55, is last block: false +2025-11-14T18:25:05.531111Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=55 +2025-11-14T18:25:05.531259Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x66795f70d3a7d1d272d838e48f466d5706233b7d4cd2348fc76f66934cbd9bac for height 55 +2025-11-14T18:25:05.531377Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 56 not found (last_processed=55, tip=55) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 55 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 55, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 55, is last block: false +2025-11-14T18:25:05.531392Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=55 +2025-11-14T18:25:05.531536Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 56 not found (last_processed=55, tip=55) +2025-11-14T18:25:05.582856Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:177: 55 Handling message Broadcast +2025-11-14T18:25:05.585819Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 13) (epoch 1, view 13), parent height: 12 +2025-11-14T18:25:05.586171Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 13) (epoch 1, view 13), parent height: 12 +2025-11-14T18:25:05.586176Z  INFO ThreadId(91) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 13) (epoch 1, view 13), parent height: 12 +2025-11-14T18:25:05.591211Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 13) (last_processed_height=55, tip=55) +2025-11-14T18:25:05.591224Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 13) (last_processed_height=55, tip=55) +2025-11-14T18:25:05.591303Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 13) (last_processed_height=55, tip=55) +2025-11-14T18:25:05.592093Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 13) (last_processed_height=55, tip=55) +2025-11-14T18:25:05.592397Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 56 (previous tip: 55) +2025-11-14T18:25:05.592404Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 56 (last_processed_height: 55, tip: 56) +2025-11-14T18:25:05.592417Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 56 (previous tip: 55) +2025-11-14T18:25:05.592419Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 56 (previous tip: 55) +2025-11-14T18:25:05.592423Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 56 (last_processed_height: 55, tip: 56) +2025-11-14T18:25:05.592424Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 56 (last_processed_height: 55, tip: 56) +2025-11-14T18:25:05.592436Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 56)], last_processed_height: 55, tip: 56 +2025-11-14T18:25:05.592439Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:05.592450Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 56)], last_processed_height: 55, tip: 56 +2025-11-14T18:25:05.592453Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:05.592459Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 56)], last_processed_height: 55, tip: 56 +2025-11-14T18:25:05.592462Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:05.592525Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 56 (previous tip: 55) +2025-11-14T18:25:05.592531Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 56 (last_processed_height: 55, tip: 56) +2025-11-14T18:25:05.592554Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 56)], last_processed_height: 55, tip: 56 +2025-11-14T18:25:05.592557Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:05.593562Z  INFO ThreadId(88) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xfec24919b4a2e7f405c0c13a937b3198886c6fea2af92798e4743f4bcff841ba for height 56 +2025-11-14T18:25:05.593566Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xfec24919b4a2e7f405c0c13a937b3198886c6fea2af92798e4743f4bcff841ba for height 56 +üüüüüüüüüüüüüüüüüüüüüüüüü +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 56 to reth +COMMITING BLOCK 56 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 56, is penultimate block: false +epoch_num_of_blocks: 50, new_height: 56, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 56, is last block: false +epoch_num_of_blocks: 50, new_height: 56, is last block: false +2025-11-14T18:25:05.593782Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=56 +2025-11-14T18:25:05.593782Z  INFO ThreadId(88) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=56 +2025-11-14T18:25:05.593793Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xfec24919b4a2e7f405c0c13a937b3198886c6fea2af92798e4743f4bcff841ba for height 56 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 56 to reth +2025-11-14T18:25:05.593948Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 57 not found (last_processed=56, tip=56) +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 56, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 56, is last block: false +2025-11-14T18:25:05.593956Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=56 +2025-11-14T18:25:05.593967Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 57 not found (last_processed=56, tip=56) +2025-11-14T18:25:05.593979Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xfec24919b4a2e7f405c0c13a937b3198886c6fea2af92798e4743f4bcff841ba for height 56 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 56 to reth +2025-11-14T18:25:05.594106Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 57 not found (last_processed=56, tip=56) +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 56, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 56, is last block: false +2025-11-14T18:25:05.594114Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=56 +2025-11-14T18:25:05.594261Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 57 not found (last_processed=56, tip=56) +2025-11-14T18:25:05.659657Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:05.911953Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:06.164884Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:06.416989Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:06.669857Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:06.922785Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +Node 1 at height 56 +Node 2 at height 56 +Node 3 at height 56 +Node 4 at height 56 +2025-11-14T18:25:07.174929Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:07.427304Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:07.592569Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:149: 15 application: Handling message Propose for round Round(1, 15) (epoch 1, view 15), parent height: 13 +2025-11-14T18:25:07.644335Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:177: 15 Handling message Broadcast +2025-11-14T18:25:07.646988Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 15) (epoch 1, view 15), parent height: 13 +2025-11-14T18:25:07.647041Z  INFO ThreadId(88) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 15) (epoch 1, view 15), parent height: 13 +2025-11-14T18:25:07.647489Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 15) (epoch 1, view 15), parent height: 13 +2025-11-14T18:25:07.650104Z  INFO ThreadId(88) summit_application::actor: application/src/actor.rs:149: 143 application: Handling message Propose for round Round(1, 16) (epoch 1, view 16), parent height: 15 +2025-11-14T18:25:07.650813Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 15) (last_processed_height=56, tip=56) +2025-11-14T18:25:07.650960Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 15) (last_processed_height=56, tip=56) +2025-11-14T18:25:07.651298Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 57 (previous tip: 56) +2025-11-14T18:25:07.651304Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 57 (last_processed_height: 56, tip: 57) +2025-11-14T18:25:07.651347Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 15) (last_processed_height=56, tip=56) +2025-11-14T18:25:07.651362Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 57)], last_processed_height: 56, tip: 57 +2025-11-14T18:25:07.651369Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:07.651424Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 57 (previous tip: 56) +2025-11-14T18:25:07.651430Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 57 (last_processed_height: 56, tip: 57) +2025-11-14T18:25:07.651458Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 57)], last_processed_height: 56, tip: 57 +2025-11-14T18:25:07.651461Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:07.651772Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 15) (last_processed_height=56, tip=56) +2025-11-14T18:25:07.652262Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 57 (previous tip: 56) +2025-11-14T18:25:07.652269Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 57 (last_processed_height: 56, tip: 57) +2025-11-14T18:25:07.652300Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 57)], last_processed_height: 56, tip: 57 +2025-11-14T18:25:07.652303Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:07.652488Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x60cb47e7b9bf725f1c4c4d4b6b6faf6122f6785ce48c530510aa9cd199774c98 for height 57 +2025-11-14T18:25:07.652541Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x60cb47e7b9bf725f1c4c4d4b6b6faf6122f6785ce48c530510aa9cd199774c98 for height 57 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 57 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 57, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 57, is last block: false +2025-11-14T18:25:07.652675Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=57 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 57 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 57, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 57, is last block: false +2025-11-14T18:25:07.652693Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=57 +2025-11-14T18:25:07.652779Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 57 (previous tip: 56) +2025-11-14T18:25:07.652787Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 57 (last_processed_height: 56, tip: 57) +2025-11-14T18:25:07.652825Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 58 not found (last_processed=57, tip=57) +2025-11-14T18:25:07.652869Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 58 not found (last_processed=57, tip=57) +2025-11-14T18:25:07.652944Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 57)], last_processed_height: 56, tip: 57 +2025-11-14T18:25:07.652948Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:07.653226Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x60cb47e7b9bf725f1c4c4d4b6b6faf6122f6785ce48c530510aa9cd199774c98 for height 57 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 57 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 57, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 57, is last block: false +2025-11-14T18:25:07.653394Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=57 +2025-11-14T18:25:07.653602Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 58 not found (last_processed=57, tip=57) +2025-11-14T18:25:07.653993Z  INFO ThreadId(89) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x60cb47e7b9bf725f1c4c4d4b6b6faf6122f6785ce48c530510aa9cd199774c98 for height 57 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 57 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 57, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 57, is last block: false +2025-11-14T18:25:07.654150Z  INFO ThreadId(88) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=57 +2025-11-14T18:25:07.654295Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 58 not found (last_processed=57, tip=57) +2025-11-14T18:25:07.679535Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:07.706030Z  INFO ThreadId(90) summit_application::actor: application/src/actor.rs:177: 143 Handling message Broadcast +2025-11-14T18:25:07.707905Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 16) (epoch 1, view 16), parent height: 15 +2025-11-14T18:25:07.708001Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 16) (epoch 1, view 16), parent height: 15 +2025-11-14T18:25:07.708535Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 16) (epoch 1, view 16), parent height: 15 +2025-11-14T18:25:07.710443Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:149: 139 application: Handling message Propose for round Round(1, 17) (epoch 1, view 17), parent height: 16 +2025-11-14T18:25:07.712313Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 16) (last_processed_height=57, tip=57) +2025-11-14T18:25:07.712940Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 16) (last_processed_height=57, tip=57) +2025-11-14T18:25:07.712951Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 16) (last_processed_height=57, tip=57) +2025-11-14T18:25:07.713410Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 16) (last_processed_height=57, tip=57) +2025-11-14T18:25:07.713584Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 58 (previous tip: 57) +2025-11-14T18:25:07.713595Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 58 (last_processed_height: 57, tip: 58) +2025-11-14T18:25:07.713652Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 58)], last_processed_height: 57, tip: 58 +2025-11-14T18:25:07.713659Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:07.714010Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 58 (previous tip: 57) +2025-11-14T18:25:07.714011Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 58 (previous tip: 57) +2025-11-14T18:25:07.714018Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 58 (last_processed_height: 57, tip: 58) +2025-11-14T18:25:07.714019Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 58 (last_processed_height: 57, tip: 58) +2025-11-14T18:25:07.714046Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 58)], last_processed_height: 57, tip: 58 +2025-11-14T18:25:07.714048Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:07.714050Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 58)], last_processed_height: 57, tip: 58 +2025-11-14T18:25:07.714053Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:07.714314Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 58 (previous tip: 57) +2025-11-14T18:25:07.714321Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 58 (last_processed_height: 57, tip: 58) +2025-11-14T18:25:07.714365Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 58)], last_processed_height: 57, tip: 58 +2025-11-14T18:25:07.714369Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:07.715580Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd38218bdd57a79c7585c0501f8db510bb328bd1aed0b0860dc0d8d7424ada135 for height 58 +2025-11-14T18:25:07.715661Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd38218bdd57a79c7585c0501f8db510bb328bd1aed0b0860dc0d8d7424ada135 for height 58 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 58 to reth +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 58 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 58, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 58, is last block: false +2025-11-14T18:25:07.715860Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=58 +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 58, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 58, is last block: false +2025-11-14T18:25:07.715879Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=58 +2025-11-14T18:25:07.715998Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd38218bdd57a79c7585c0501f8db510bb328bd1aed0b0860dc0d8d7424ada135 for height 58 +2025-11-14T18:25:07.716065Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 59 not found (last_processed=58, tip=58) +2025-11-14T18:25:07.716073Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 59 not found (last_processed=58, tip=58) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 58 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 58, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 58, is last block: false +2025-11-14T18:25:07.716186Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=58 +2025-11-14T18:25:07.716232Z  INFO ThreadId(88) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd38218bdd57a79c7585c0501f8db510bb328bd1aed0b0860dc0d8d7424ada135 for height 58 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 58 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 58, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 58, is last block: false +2025-11-14T18:25:07.716529Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 59 not found (last_processed=58, tip=58) +2025-11-14T18:25:07.716535Z  INFO ThreadId(90) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=58 +2025-11-14T18:25:07.716767Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 59 not found (last_processed=58, tip=58) +2025-11-14T18:25:07.767822Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:177: 139 Handling message Broadcast +2025-11-14T18:25:07.770971Z  INFO ThreadId(90) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 17) (epoch 1, view 17), parent height: 16 +2025-11-14T18:25:07.771046Z  INFO ThreadId(57) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 17) (epoch 1, view 17), parent height: 16 +2025-11-14T18:25:07.771158Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 17) (epoch 1, view 17), parent height: 16 +2025-11-14T18:25:07.773025Z  INFO ThreadId(57) summit_application::actor: application/src/actor.rs:149: 55 application: Handling message Propose for round Round(1, 18) (epoch 1, view 18), parent height: 17 +2025-11-14T18:25:07.775107Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 17) (last_processed_height=58, tip=58) +2025-11-14T18:25:07.775180Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 17) (last_processed_height=58, tip=58) +2025-11-14T18:25:07.775579Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 59 (previous tip: 58) +2025-11-14T18:25:07.775585Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 59 (last_processed_height: 58, tip: 59) +2025-11-14T18:25:07.775632Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 59)], last_processed_height: 58, tip: 59 +2025-11-14T18:25:07.775637Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:07.775642Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 17) (last_processed_height=58, tip=58) +2025-11-14T18:25:07.775710Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 59 (previous tip: 58) +2025-11-14T18:25:07.775715Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 59 (last_processed_height: 58, tip: 59) +2025-11-14T18:25:07.775737Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 59)], last_processed_height: 58, tip: 59 +2025-11-14T18:25:07.775740Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:07.776036Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 17) (last_processed_height=58, tip=58) +2025-11-14T18:25:07.776349Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 59 (previous tip: 58) +2025-11-14T18:25:07.776358Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 59 (last_processed_height: 58, tip: 59) +2025-11-14T18:25:07.776386Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 59)], last_processed_height: 58, tip: 59 +2025-11-14T18:25:07.776389Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:07.776716Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x733837a340a3928ed572c52d1556ebc77a9359ac694cc9549be29189c0e1a461 for height 59 +2025-11-14T18:25:07.776783Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 59 (previous tip: 58) +2025-11-14T18:25:07.776790Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 59 (last_processed_height: 58, tip: 59) +2025-11-14T18:25:07.776826Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 59)], last_processed_height: 58, tip: 59 +2025-11-14T18:25:07.776829Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +üüüüüüüüüüüüüüüüüüüüüüüüü +2025-11-14T18:25:07.776887Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x733837a340a3928ed572c52d1556ebc77a9359ac694cc9549be29189c0e1a461 for height 59 +COMMITING BLOCK 59 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 59, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 59, is last block: false +2025-11-14T18:25:07.776906Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=59 +2025-11-14T18:25:07.777149Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 60 not found (last_processed=59, tip=59) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 59 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 59, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 59, is last block: false +2025-11-14T18:25:07.777234Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=59 +2025-11-14T18:25:07.777435Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x733837a340a3928ed572c52d1556ebc77a9359ac694cc9549be29189c0e1a461 for height 59 +2025-11-14T18:25:07.777444Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 60 not found (last_processed=59, tip=59) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 59 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 59, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 59, is last block: false +2025-11-14T18:25:07.777594Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=59 +2025-11-14T18:25:07.777743Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 60 not found (last_processed=59, tip=59) +2025-11-14T18:25:07.778056Z  INFO ThreadId(90) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x733837a340a3928ed572c52d1556ebc77a9359ac694cc9549be29189c0e1a461 for height 59 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 59 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 59, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 59, is last block: false +2025-11-14T18:25:07.778208Z  INFO ThreadId(88) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=59 +2025-11-14T18:25:07.778370Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 60 not found (last_processed=59, tip=59) +2025-11-14T18:25:07.828786Z  INFO ThreadId(56) summit_application::actor: application/src/actor.rs:177: 55 Handling message Broadcast +2025-11-14T18:25:07.831241Z  INFO ThreadId(88) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 18) (epoch 1, view 18), parent height: 17 +2025-11-14T18:25:07.831279Z  INFO ThreadId(43) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 18) (epoch 1, view 18), parent height: 17 +2025-11-14T18:25:07.831299Z  INFO ThreadId(49) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 18) (epoch 1, view 18), parent height: 17 +2025-11-14T18:25:07.835630Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 18) (last_processed_height=59, tip=59) +2025-11-14T18:25:07.835635Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 18) (last_processed_height=59, tip=59) +2025-11-14T18:25:07.835647Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 18) (last_processed_height=59, tip=59) +2025-11-14T18:25:07.836136Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 60 (previous tip: 59) +2025-11-14T18:25:07.836142Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 60 (last_processed_height: 59, tip: 60) +2025-11-14T18:25:07.836178Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 60)], last_processed_height: 59, tip: 60 +2025-11-14T18:25:07.836181Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:07.836218Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 60 (previous tip: 59) +2025-11-14T18:25:07.836224Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 60 (last_processed_height: 59, tip: 60) +2025-11-14T18:25:07.836238Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 60 (previous tip: 59) +2025-11-14T18:25:07.836244Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 60 (last_processed_height: 59, tip: 60) +2025-11-14T18:25:07.836251Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 60)], last_processed_height: 59, tip: 60 +2025-11-14T18:25:07.836254Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:07.836275Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 60)], last_processed_height: 59, tip: 60 +2025-11-14T18:25:07.836278Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:07.836548Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 18) (last_processed_height=59, tip=59) +2025-11-14T18:25:07.837206Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 60 (previous tip: 59) +2025-11-14T18:25:07.837213Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 60 (last_processed_height: 59, tip: 60) +2025-11-14T18:25:07.837259Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 60)], last_processed_height: 59, tip: 60 +2025-11-14T18:25:07.837263Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:07.837299Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd9e97f0653003a51eb2f122f80f7eea87df8976d906fafeaba131a8ff9c8c6b3 for height 60 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 60 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 60, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 60, is last block: false +2025-11-14T18:25:07.837456Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=60 +2025-11-14T18:25:07.837477Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd9e97f0653003a51eb2f122f80f7eea87df8976d906fafeaba131a8ff9c8c6b3 for height 60 +2025-11-14T18:25:07.837648Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 61 not found (last_processed=60, tip=60) +2025-11-14T18:25:07.837655Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd9e97f0653003a51eb2f122f80f7eea87df8976d906fafeaba131a8ff9c8c6b3 for height 60 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 60 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 60, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 60, is last block: false +2025-11-14T18:25:07.837673Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=60 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 60 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 60, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 60, is last block: false +2025-11-14T18:25:07.837812Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=60 +2025-11-14T18:25:07.837974Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 61 not found (last_processed=60, tip=60) +2025-11-14T18:25:07.837976Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 61 not found (last_processed=60, tip=60) +2025-11-14T18:25:07.838191Z  INFO ThreadId(88) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd9e97f0653003a51eb2f122f80f7eea87df8976d906fafeaba131a8ff9c8c6b3 for height 60 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 60 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 60, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 60, is last block: false +2025-11-14T18:25:07.838323Z  INFO ThreadId(90) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=60 +2025-11-14T18:25:07.838511Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 61 not found (last_processed=60, tip=60) +2025-11-14T18:25:07.931255Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:08.183144Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:08.435595Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:08.688171Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:08.940758Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +Node 1 at height 60 +Node 2 at height 60 +Node 3 at height 60 +Node 4 at height 60 +2025-11-14T18:25:09.192946Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:09.445695Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:09.698283Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:09.837732Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:149: 15 application: Handling message Propose for round Round(1, 20) (epoch 1, view 20), parent height: 18 +2025-11-14T18:25:09.888731Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:177: 15 Handling message Broadcast +2025-11-14T18:25:09.891601Z  INFO ThreadId(57) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 20) (epoch 1, view 20), parent height: 18 +2025-11-14T18:25:09.892140Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 20) (epoch 1, view 20), parent height: 18 +2025-11-14T18:25:09.892438Z  INFO ThreadId(91) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 20) (epoch 1, view 20), parent height: 18 +2025-11-14T18:25:09.896236Z  INFO ThreadId(90) summit_application::actor: application/src/actor.rs:149: 143 application: Handling message Propose for round Round(1, 21) (epoch 1, view 21), parent height: 20 +2025-11-14T18:25:09.897005Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 20) (last_processed_height=60, tip=60) +2025-11-14T18:25:09.897464Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 61 (previous tip: 60) +2025-11-14T18:25:09.897468Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 61 (last_processed_height: 60, tip: 61) +2025-11-14T18:25:09.897504Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 61)], last_processed_height: 60, tip: 61 +2025-11-14T18:25:09.897507Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:09.897626Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 20) (last_processed_height=60, tip=60) +2025-11-14T18:25:09.897626Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 20) (last_processed_height=60, tip=60) +2025-11-14T18:25:09.897876Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 20) (last_processed_height=60, tip=60) +2025-11-14T18:25:09.898186Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 61 (previous tip: 60) +2025-11-14T18:25:09.898197Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 61 (last_processed_height: 60, tip: 61) +2025-11-14T18:25:09.898252Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 61)], last_processed_height: 60, tip: 61 +2025-11-14T18:25:09.898257Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:09.898390Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 61 (previous tip: 60) +2025-11-14T18:25:09.898397Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 61 (last_processed_height: 60, tip: 61) +2025-11-14T18:25:09.898429Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 61)], last_processed_height: 60, tip: 61 +2025-11-14T18:25:09.898432Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:09.898628Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 61 (previous tip: 60) +2025-11-14T18:25:09.898636Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 61 (last_processed_height: 60, tip: 61) +2025-11-14T18:25:09.898678Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 61)], last_processed_height: 60, tip: 61 +2025-11-14T18:25:09.898683Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:09.899063Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x8d119b91c96a88bf9c42d5c07de5db4e23bcae000577f83acadf722e113a313d for height 61 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 61 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 61, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 61, is last block: false +2025-11-14T18:25:09.899285Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=61 +2025-11-14T18:25:09.899497Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 62 not found (last_processed=61, tip=61) +2025-11-14T18:25:09.899765Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x8d119b91c96a88bf9c42d5c07de5db4e23bcae000577f83acadf722e113a313d for height 61 +2025-11-14T18:25:09.899921Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x8d119b91c96a88bf9c42d5c07de5db4e23bcae000577f83acadf722e113a313d for height 61 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 61 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 61, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 61, is last block: false +2025-11-14T18:25:09.899935Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=61 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 61 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 61, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 61, is last block: false +2025-11-14T18:25:09.900081Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=61 +2025-11-14T18:25:09.900116Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 62 not found (last_processed=61, tip=61) +2025-11-14T18:25:09.900273Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 62 not found (last_processed=61, tip=61) +2025-11-14T18:25:09.900465Z  INFO ThreadId(88) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x8d119b91c96a88bf9c42d5c07de5db4e23bcae000577f83acadf722e113a313d for height 61 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 61 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 61, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 61, is last block: false +2025-11-14T18:25:09.900597Z  INFO ThreadId(90) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=61 +2025-11-14T18:25:09.900773Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 62 not found (last_processed=61, tip=61) +2025-11-14T18:25:09.951180Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:09.952214Z  INFO ThreadId(90) summit_application::actor: application/src/actor.rs:177: 143 Handling message Broadcast +2025-11-14T18:25:09.954110Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 21) (epoch 1, view 21), parent height: 20 +2025-11-14T18:25:09.954129Z  INFO ThreadId(43) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 21) (epoch 1, view 21), parent height: 20 +2025-11-14T18:25:09.954182Z  INFO ThreadId(56) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 21) (epoch 1, view 21), parent height: 20 +2025-11-14T18:25:09.958110Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:149: 139 application: Handling message Propose for round Round(1, 22) (epoch 1, view 22), parent height: 21 +2025-11-14T18:25:09.958815Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 21) (last_processed_height=61, tip=61) +2025-11-14T18:25:09.958821Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 21) (last_processed_height=61, tip=61) +2025-11-14T18:25:09.958824Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 21) (last_processed_height=61, tip=61) +2025-11-14T18:25:09.959372Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 62 (previous tip: 61) +2025-11-14T18:25:09.959406Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 62 (last_processed_height: 61, tip: 62) +2025-11-14T18:25:09.959470Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 62)], last_processed_height: 61, tip: 62 +2025-11-14T18:25:09.959474Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:09.959532Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 62 (previous tip: 61) +2025-11-14T18:25:09.959537Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 62 (last_processed_height: 61, tip: 62) +2025-11-14T18:25:09.959572Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 62)], last_processed_height: 61, tip: 62 +2025-11-14T18:25:09.959577Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:09.959737Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 21) (last_processed_height=61, tip=61) +2025-11-14T18:25:09.959769Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 62 (previous tip: 61) +2025-11-14T18:25:09.959791Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 62 (last_processed_height: 61, tip: 62) +2025-11-14T18:25:09.959840Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 62)], last_processed_height: 61, tip: 62 +2025-11-14T18:25:09.959845Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:09.960729Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 62 (previous tip: 61) +2025-11-14T18:25:09.960738Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 62 (last_processed_height: 61, tip: 62) +2025-11-14T18:25:09.960794Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 62)], last_processed_height: 61, tip: 62 +2025-11-14T18:25:09.960799Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:09.960936Z  INFO ThreadId(88) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x841eb131db1e8e7489b8aa48fcd2e1fce40261bf0c0a94e9785fac348ec849ed for height 62 +2025-11-14T18:25:09.960936Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x841eb131db1e8e7489b8aa48fcd2e1fce40261bf0c0a94e9785fac348ec849ed for height 62 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 62 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 62, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 62, is last block: false +2025-11-14T18:25:09.961101Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=62 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 62 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 62, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 62, is last block: false +2025-11-14T18:25:09.961130Z  INFO ThreadId(88) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=62 +2025-11-14T18:25:09.961173Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x841eb131db1e8e7489b8aa48fcd2e1fce40261bf0c0a94e9785fac348ec849ed for height 62 +2025-11-14T18:25:09.961305Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 63 not found (last_processed=62, tip=62) +2025-11-14T18:25:09.961311Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 63 not found (last_processed=62, tip=62) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 62 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 62, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 62, is last block: false +2025-11-14T18:25:09.961331Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=62 +2025-11-14T18:25:09.961542Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 63 not found (last_processed=62, tip=62) +2025-11-14T18:25:09.961913Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x841eb131db1e8e7489b8aa48fcd2e1fce40261bf0c0a94e9785fac348ec849ed for height 62 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 62 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 62, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 62, is last block: false +2025-11-14T18:25:09.962047Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=62 +2025-11-14T18:25:09.962172Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 63 not found (last_processed=62, tip=62) +2025-11-14T18:25:10.013827Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:177: 139 Handling message Broadcast +2025-11-14T18:25:10.016506Z  INFO ThreadId(91) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 22) (epoch 1, view 22), parent height: 21 +2025-11-14T18:25:10.016514Z  INFO ThreadId(57) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 22) (epoch 1, view 22), parent height: 21 +2025-11-14T18:25:10.016574Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 22) (epoch 1, view 22), parent height: 21 +2025-11-14T18:25:10.018960Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:149: 55 application: Handling message Propose for round Round(1, 23) (epoch 1, view 23), parent height: 22 +2025-11-14T18:25:10.020776Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 22) (last_processed_height=62, tip=62) +2025-11-14T18:25:10.020782Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 22) (last_processed_height=62, tip=62) +2025-11-14T18:25:10.020777Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 22) (last_processed_height=62, tip=62) +2025-11-14T18:25:10.021247Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 63 (previous tip: 62) +2025-11-14T18:25:10.021252Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 63 (last_processed_height: 62, tip: 63) +2025-11-14T18:25:10.021282Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 63)], last_processed_height: 62, tip: 63 +2025-11-14T18:25:10.021286Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:10.021337Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 63 (previous tip: 62) +2025-11-14T18:25:10.021342Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 63 (last_processed_height: 62, tip: 63) +2025-11-14T18:25:10.021363Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 63 (previous tip: 62) +2025-11-14T18:25:10.021368Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 63)], last_processed_height: 62, tip: 63 +2025-11-14T18:25:10.021369Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 63 (last_processed_height: 62, tip: 63) +2025-11-14T18:25:10.021370Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:10.021405Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 63)], last_processed_height: 62, tip: 63 +2025-11-14T18:25:10.021408Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:10.021760Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 22) (last_processed_height=62, tip=62) +2025-11-14T18:25:10.022502Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xbe40902e0f6aa1e88ea1d7cefb1984cb2bc1428c2fe28e73b98148ecf4bccef5 for height 63 +2025-11-14T18:25:10.022547Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xbe40902e0f6aa1e88ea1d7cefb1984cb2bc1428c2fe28e73b98148ecf4bccef5 for height 63 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 63 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 63, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 63, is last block: false +2025-11-14T18:25:10.022706Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 63 (previous tip: 62) +2025-11-14T18:25:10.022710Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=63 +2025-11-14T18:25:10.022713Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 63 (last_processed_height: 62, tip: 63) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 63 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 63, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 63, is last block: false +2025-11-14T18:25:10.022740Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=63 +2025-11-14T18:25:10.022786Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 63)], last_processed_height: 62, tip: 63 +2025-11-14T18:25:10.022790Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:10.022892Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xbe40902e0f6aa1e88ea1d7cefb1984cb2bc1428c2fe28e73b98148ecf4bccef5 for height 63 +2025-11-14T18:25:10.022947Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 64 not found (last_processed=63, tip=63) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 63 to reth +2025-11-14T18:25:10.023017Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 64 not found (last_processed=63, tip=63) +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 63, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 63, is last block: false +2025-11-14T18:25:10.023026Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=63 +2025-11-14T18:25:10.023164Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 64 not found (last_processed=63, tip=63) +2025-11-14T18:25:10.023641Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xbe40902e0f6aa1e88ea1d7cefb1984cb2bc1428c2fe28e73b98148ecf4bccef5 for height 63 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 63 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 63, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 63, is last block: false +2025-11-14T18:25:10.023758Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=63 +2025-11-14T18:25:10.023861Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 64 not found (last_processed=63, tip=63) +2025-11-14T18:25:10.074659Z  INFO ThreadId(56) summit_application::actor: application/src/actor.rs:177: 55 Handling message Broadcast +2025-11-14T18:25:10.077522Z  INFO ThreadId(52) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 23) (epoch 1, view 23), parent height: 22 +2025-11-14T18:25:10.078276Z  INFO ThreadId(89) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 23) (epoch 1, view 23), parent height: 22 +2025-11-14T18:25:10.078292Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 23) (epoch 1, view 23), parent height: 22 +2025-11-14T18:25:10.081997Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 23) (last_processed_height=63, tip=63) +2025-11-14T18:25:10.082014Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 23) (last_processed_height=63, tip=63) +2025-11-14T18:25:10.082244Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 23) (last_processed_height=63, tip=63) +2025-11-14T18:25:10.082529Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 64 (previous tip: 63) +2025-11-14T18:25:10.082535Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 64 (last_processed_height: 63, tip: 64) +2025-11-14T18:25:10.082534Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 64 (previous tip: 63) +2025-11-14T18:25:10.082540Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 64 (last_processed_height: 63, tip: 64) +2025-11-14T18:25:10.082564Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 64)], last_processed_height: 63, tip: 64 +2025-11-14T18:25:10.082568Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:10.082580Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 64)], last_processed_height: 63, tip: 64 +2025-11-14T18:25:10.082584Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:10.082737Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 64 (previous tip: 63) +2025-11-14T18:25:10.082743Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 64 (last_processed_height: 63, tip: 64) +2025-11-14T18:25:10.082769Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 64)], last_processed_height: 63, tip: 64 +2025-11-14T18:25:10.082772Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:10.082969Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 23) (last_processed_height=63, tip=63) +2025-11-14T18:25:10.083751Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 64 (previous tip: 63) +2025-11-14T18:25:10.083761Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 64 (last_processed_height: 63, tip: 64) +2025-11-14T18:25:10.083793Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x4a27be30d28b7ce60bd9ceceb2eb15b34e5cde15caa429203552666fed730250 for height 64 +2025-11-14T18:25:10.083832Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 64)], last_processed_height: 63, tip: 64 +2025-11-14T18:25:10.083846Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:10.083833Z  INFO ThreadId(90) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x4a27be30d28b7ce60bd9ceceb2eb15b34e5cde15caa429203552666fed730250 for height 64 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 64 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 64, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 64, is last block: false +2025-11-14T18:25:10.083958Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=64 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 64 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 64, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 64, is last block: false +2025-11-14T18:25:10.084000Z  INFO ThreadId(89) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=64 +2025-11-14T18:25:10.084032Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x4a27be30d28b7ce60bd9ceceb2eb15b34e5cde15caa429203552666fed730250 for height 64 +2025-11-14T18:25:10.084115Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 65 not found (last_processed=64, tip=64) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 64 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 64, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 64, is last block: false +2025-11-14T18:25:10.084165Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=64 +2025-11-14T18:25:10.084172Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 65 not found (last_processed=64, tip=64) +2025-11-14T18:25:10.084320Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 65 not found (last_processed=64, tip=64) +2025-11-14T18:25:10.084724Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x4a27be30d28b7ce60bd9ceceb2eb15b34e5cde15caa429203552666fed730250 for height 64 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 64 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 64, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 64, is last block: false +2025-11-14T18:25:10.084828Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=64 +2025-11-14T18:25:10.084956Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 65 not found (last_processed=64, tip=64) +2025-11-14T18:25:10.203819Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:10.455977Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:10.709032Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:10.961979Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +Node 1 at height 64 +Node 2 at height 64 +Node 3 at height 64 +Node 4 at height 64 +2025-11-14T18:25:11.213013Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:11.465367Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:11.717123Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:11.969891Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:12.083870Z  INFO ThreadId(43) summit_application::actor: application/src/actor.rs:149: 15 application: Handling message Propose for round Round(1, 25) (epoch 1, view 25), parent height: 23 +2025-11-14T18:25:12.136044Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:177: 15 Handling message Broadcast +2025-11-14T18:25:12.138571Z  INFO ThreadId(88) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 25) (epoch 1, view 25), parent height: 23 +2025-11-14T18:25:12.138685Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 25) (epoch 1, view 25), parent height: 23 +2025-11-14T18:25:12.139072Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 25) (epoch 1, view 25), parent height: 23 +2025-11-14T18:25:12.142925Z  INFO ThreadId(90) summit_application::actor: application/src/actor.rs:149: 143 application: Handling message Propose for round Round(1, 26) (epoch 1, view 26), parent height: 25 +2025-11-14T18:25:12.144482Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 25) (last_processed_height=64, tip=64) +2025-11-14T18:25:12.144484Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 25) (last_processed_height=64, tip=64) +2025-11-14T18:25:12.144494Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 25) (last_processed_height=64, tip=64) +2025-11-14T18:25:12.145052Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 65 (previous tip: 64) +2025-11-14T18:25:12.145058Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 65 (last_processed_height: 64, tip: 65) +2025-11-14T18:25:12.145082Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 65 (previous tip: 64) +2025-11-14T18:25:12.145087Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 65 (last_processed_height: 64, tip: 65) +2025-11-14T18:25:12.145094Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 65)], last_processed_height: 64, tip: 65 +2025-11-14T18:25:12.145099Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:12.145103Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 65 (previous tip: 64) +2025-11-14T18:25:12.145109Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 65 (last_processed_height: 64, tip: 65) +2025-11-14T18:25:12.145115Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 65)], last_processed_height: 64, tip: 65 +2025-11-14T18:25:12.145118Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:12.145140Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 65)], last_processed_height: 64, tip: 65 +2025-11-14T18:25:12.145142Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:12.145438Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 25) (last_processed_height=64, tip=64) +2025-11-14T18:25:12.146002Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 65 (previous tip: 64) +2025-11-14T18:25:12.146010Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 65 (last_processed_height: 64, tip: 65) +2025-11-14T18:25:12.146037Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 65)], last_processed_height: 64, tip: 65 +2025-11-14T18:25:12.146041Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:12.146123Z  INFO ThreadId(88) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x9eebb46855cee62277a1ef48e508fb147824b471f3e6cba8d554ba22ccb83816 for height 65 +2025-11-14T18:25:12.146322Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x9eebb46855cee62277a1ef48e508fb147824b471f3e6cba8d554ba22ccb83816 for height 65 +2025-11-14T18:25:12.146365Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x9eebb46855cee62277a1ef48e508fb147824b471f3e6cba8d554ba22ccb83816 for height 65 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 65 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 65, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 65, is last block: false +2025-11-14T18:25:12.146411Z  INFO ThreadId(88) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=65 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 65 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 65, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 65, is last block: false +2025-11-14T18:25:12.146472Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=65 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 65 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 65, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 65, is last block: false +2025-11-14T18:25:12.146605Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=65 +2025-11-14T18:25:12.146650Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 66 not found (last_processed=65, tip=65) +2025-11-14T18:25:12.146704Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 66 not found (last_processed=65, tip=65) +2025-11-14T18:25:12.146828Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 66 not found (last_processed=65, tip=65) +2025-11-14T18:25:12.147075Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x9eebb46855cee62277a1ef48e508fb147824b471f3e6cba8d554ba22ccb83816 for height 65 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 65 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 65, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 65, is last block: false +2025-11-14T18:25:12.147203Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=65 +2025-11-14T18:25:12.147339Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 66 not found (last_processed=65, tip=65) +2025-11-14T18:25:12.197367Z  INFO ThreadId(89) summit_application::actor: application/src/actor.rs:177: 143 Handling message Broadcast +2025-11-14T18:25:12.200366Z  INFO ThreadId(56) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 26) (epoch 1, view 26), parent height: 25 +2025-11-14T18:25:12.200519Z  INFO ThreadId(43) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 26) (epoch 1, view 26), parent height: 25 +2025-11-14T18:25:12.201072Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 26) (epoch 1, view 26), parent height: 25 +2025-11-14T18:25:12.203302Z  INFO ThreadId(49) summit_application::actor: application/src/actor.rs:149: 139 application: Handling message Propose for round Round(1, 27) (epoch 1, view 27), parent height: 26 +2025-11-14T18:25:12.205514Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 26) (last_processed_height=65, tip=65) +2025-11-14T18:25:12.206143Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 26) (last_processed_height=65, tip=65) +2025-11-14T18:25:12.206230Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 26) (last_processed_height=65, tip=65) +2025-11-14T18:25:12.206383Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 26) (last_processed_height=65, tip=65) +2025-11-14T18:25:12.206493Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 66 (previous tip: 65) +2025-11-14T18:25:12.206500Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 66 (last_processed_height: 65, tip: 66) +2025-11-14T18:25:12.206542Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 66)], last_processed_height: 65, tip: 66 +2025-11-14T18:25:12.206547Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:12.206992Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 66 (previous tip: 65) +2025-11-14T18:25:12.207000Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 66 (last_processed_height: 65, tip: 66) +2025-11-14T18:25:12.207038Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 66)], last_processed_height: 65, tip: 66 +2025-11-14T18:25:12.207041Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:12.207088Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 66 (previous tip: 65) +2025-11-14T18:25:12.207102Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 66 (last_processed_height: 65, tip: 66) +2025-11-14T18:25:12.207297Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 66 (previous tip: 65) +2025-11-14T18:25:12.207309Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 66 (last_processed_height: 65, tip: 66) +2025-11-14T18:25:12.207309Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 66)], last_processed_height: 65, tip: 66 +2025-11-14T18:25:12.207315Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:12.207369Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 66)], last_processed_height: 65, tip: 66 +2025-11-14T18:25:12.207375Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:12.209580Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x58867259e688adcddd6fdf991c9f5d7d12edbf3754b9393f8b0acfe6bfe0f746 for height 66 +2025-11-14T18:25:12.209581Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x58867259e688adcddd6fdf991c9f5d7d12edbf3754b9393f8b0acfe6bfe0f746 for height 66 +2025-11-14T18:25:12.209729Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x58867259e688adcddd6fdf991c9f5d7d12edbf3754b9393f8b0acfe6bfe0f746 for height 66 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 66 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 66, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 66, is last block: false +2025-11-14T18:25:12.209996Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=66 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 66 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 66 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 66, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 66, is last block: false +epoch_num_of_blocks: 50, new_height: 66, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 66, is last block: false +2025-11-14T18:25:12.210140Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=66 +2025-11-14T18:25:12.210149Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=66 +2025-11-14T18:25:12.210157Z  INFO ThreadId(89) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x58867259e688adcddd6fdf991c9f5d7d12edbf3754b9393f8b0acfe6bfe0f746 for height 66 +2025-11-14T18:25:12.210484Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 67 not found (last_processed=66, tip=66) +2025-11-14T18:25:12.210484Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 67 not found (last_processed=66, tip=66) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 66 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 66, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 66, is last block: false +2025-11-14T18:25:12.210568Z  INFO ThreadId(89) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=66 +2025-11-14T18:25:12.210841Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 67 not found (last_processed=66, tip=66) +2025-11-14T18:25:12.210946Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 67 not found (last_processed=66, tip=66) +2025-11-14T18:25:12.222001Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:12.262057Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:177: 139 Handling message Broadcast +2025-11-14T18:25:12.264875Z  INFO ThreadId(56) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 27) (epoch 1, view 27), parent height: 26 +2025-11-14T18:25:12.265028Z  INFO ThreadId(88) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 27) (epoch 1, view 27), parent height: 26 +2025-11-14T18:25:12.265637Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 27) (epoch 1, view 27), parent height: 26 +2025-11-14T18:25:12.267374Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:149: 55 application: Handling message Propose for round Round(1, 28) (epoch 1, view 28), parent height: 27 +2025-11-14T18:25:12.269723Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 27) (last_processed_height=66, tip=66) +2025-11-14T18:25:12.269747Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 27) (last_processed_height=66, tip=66) +2025-11-14T18:25:12.269896Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 27) (last_processed_height=66, tip=66) +2025-11-14T18:25:12.270210Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 67 (previous tip: 66) +2025-11-14T18:25:12.270217Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 67 (last_processed_height: 66, tip: 67) +2025-11-14T18:25:12.270253Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 67 (previous tip: 66) +2025-11-14T18:25:12.270258Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 67 (last_processed_height: 66, tip: 67) +2025-11-14T18:25:12.270296Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 67)], last_processed_height: 66, tip: 67 +2025-11-14T18:25:12.270300Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:12.270301Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 67)], last_processed_height: 66, tip: 67 +2025-11-14T18:25:12.270309Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:12.270559Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 67 (previous tip: 66) +2025-11-14T18:25:12.270570Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 67 (last_processed_height: 66, tip: 67) +2025-11-14T18:25:12.270651Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 67)], last_processed_height: 66, tip: 67 +2025-11-14T18:25:12.270659Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:12.270817Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 27) (last_processed_height=66, tip=66) +2025-11-14T18:25:12.271431Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 67 (previous tip: 66) +2025-11-14T18:25:12.271440Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 67 (last_processed_height: 66, tip: 67) +2025-11-14T18:25:12.271498Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 67)], last_processed_height: 66, tip: 67 +2025-11-14T18:25:12.271502Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:12.271526Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x1e5fcd1b59c7532729e27fe1392c6395c624d82c64be3b172035fef10fc4a46b for height 67 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 67 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 67, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 67, is last block: false +2025-11-14T18:25:12.271715Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x1e5fcd1b59c7532729e27fe1392c6395c624d82c64be3b172035fef10fc4a46b for height 67 +2025-11-14T18:25:12.271717Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=67 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 67 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 67, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 67, is last block: false +2025-11-14T18:25:12.271863Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=67 +2025-11-14T18:25:12.271941Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 68 not found (last_processed=67, tip=67) +2025-11-14T18:25:12.272015Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 68 not found (last_processed=67, tip=67) +2025-11-14T18:25:12.272196Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x1e5fcd1b59c7532729e27fe1392c6395c624d82c64be3b172035fef10fc4a46b for height 67 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 67 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 67, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 67, is last block: false +2025-11-14T18:25:12.272372Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=67 +2025-11-14T18:25:12.272534Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 68 not found (last_processed=67, tip=67) +2025-11-14T18:25:12.272595Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x1e5fcd1b59c7532729e27fe1392c6395c624d82c64be3b172035fef10fc4a46b for height 67 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 67 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 67, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 67, is last block: false +2025-11-14T18:25:12.272706Z  INFO ThreadId(90) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=67 +2025-11-14T18:25:12.272847Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 68 not found (last_processed=67, tip=67) +2025-11-14T18:25:12.323341Z  INFO ThreadId(56) summit_application::actor: application/src/actor.rs:177: 55 Handling message Broadcast +2025-11-14T18:25:12.325776Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 28) (epoch 1, view 28), parent height: 27 +2025-11-14T18:25:12.325897Z  INFO ThreadId(91) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 28) (epoch 1, view 28), parent height: 27 +2025-11-14T18:25:12.326756Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 28) (epoch 1, view 28), parent height: 27 +2025-11-14T18:25:12.330254Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 28) (last_processed_height=67, tip=67) +2025-11-14T18:25:12.330268Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 28) (last_processed_height=67, tip=67) +2025-11-14T18:25:12.330284Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 28) (last_processed_height=67, tip=67) +2025-11-14T18:25:12.330839Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 68 (previous tip: 67) +2025-11-14T18:25:12.330850Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 68 (last_processed_height: 67, tip: 68) +2025-11-14T18:25:12.330853Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 68 (previous tip: 67) +2025-11-14T18:25:12.330858Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 68 (last_processed_height: 67, tip: 68) +2025-11-14T18:25:12.330891Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 68)], last_processed_height: 67, tip: 68 +2025-11-14T18:25:12.330894Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:12.330903Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 68)], last_processed_height: 67, tip: 68 +2025-11-14T18:25:12.330908Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:12.331185Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 68 (previous tip: 67) +2025-11-14T18:25:12.331197Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 68 (last_processed_height: 67, tip: 68) +2025-11-14T18:25:12.331256Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 68)], last_processed_height: 67, tip: 68 +2025-11-14T18:25:12.331264Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:12.331294Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 28) (last_processed_height=67, tip=67) +2025-11-14T18:25:12.332166Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 68 (previous tip: 67) +2025-11-14T18:25:12.332176Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 68 (last_processed_height: 67, tip: 68) +2025-11-14T18:25:12.332225Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 68)], last_processed_height: 67, tip: 68 +2025-11-14T18:25:12.332230Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:12.332349Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7a4011a5cc13fe2d807364c931f0736168b43eac1b0cf7ed87b2aa6e6ecee903 for height 68 +2025-11-14T18:25:12.332406Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7a4011a5cc13fe2d807364c931f0736168b43eac1b0cf7ed87b2aa6e6ecee903 for height 68 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 68 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 68, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 68, is last block: false +2025-11-14T18:25:12.332583Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=68 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 68 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 68, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 68, is last block: false +2025-11-14T18:25:12.332655Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=68 +2025-11-14T18:25:12.332780Z  INFO ThreadId(90) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7a4011a5cc13fe2d807364c931f0736168b43eac1b0cf7ed87b2aa6e6ecee903 for height 68 +2025-11-14T18:25:12.332809Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 69 not found (last_processed=68, tip=68) +2025-11-14T18:25:12.332815Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 69 not found (last_processed=68, tip=68) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 68 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 68, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 68, is last block: false +2025-11-14T18:25:12.332947Z  INFO ThreadId(90) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=68 +2025-11-14T18:25:12.333130Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 69 not found (last_processed=68, tip=68) +2025-11-14T18:25:12.333375Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7a4011a5cc13fe2d807364c931f0736168b43eac1b0cf7ed87b2aa6e6ecee903 for height 68 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 68 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 68, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 68, is last block: false +2025-11-14T18:25:12.333480Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=68 +2025-11-14T18:25:12.333599Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 69 not found (last_processed=68, tip=68) +2025-11-14T18:25:12.474283Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:12.726891Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:12.979692Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +Node 1 at height 68 +Node 2 at height 68 +Node 3 at height 68 +2025-11-14T18:25:13.231313Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +Node 4 at height 68 +2025-11-14T18:25:13.483302Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:13.734895Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:13.987832Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:14.240621Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:14.332824Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:149: 15 application: Handling message Propose for round Round(1, 30) (epoch 1, view 30), parent height: 28 +2025-11-14T18:25:14.383944Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:177: 15 Handling message Broadcast +2025-11-14T18:25:14.386616Z  INFO ThreadId(56) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 30) (epoch 1, view 30), parent height: 28 +2025-11-14T18:25:14.386648Z  INFO ThreadId(91) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 30) (epoch 1, view 30), parent height: 28 +2025-11-14T18:25:14.386850Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 30) (epoch 1, view 30), parent height: 28 +2025-11-14T18:25:14.390629Z  INFO ThreadId(90) summit_application::actor: application/src/actor.rs:149: 143 application: Handling message Propose for round Round(1, 31) (epoch 1, view 31), parent height: 30 +2025-11-14T18:25:14.392780Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 30) (last_processed_height=68, tip=68) +2025-11-14T18:25:14.392812Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 30) (last_processed_height=68, tip=68) +2025-11-14T18:25:14.392932Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 30) (last_processed_height=68, tip=68) +2025-11-14T18:25:14.393425Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 69 (previous tip: 68) +2025-11-14T18:25:14.393433Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 69 (last_processed_height: 68, tip: 69) +2025-11-14T18:25:14.393465Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 69)], last_processed_height: 68, tip: 69 +2025-11-14T18:25:14.393469Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:14.393545Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 69 (previous tip: 68) +2025-11-14T18:25:14.393551Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 69 (last_processed_height: 68, tip: 69) +2025-11-14T18:25:14.393578Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 69)], last_processed_height: 68, tip: 69 +2025-11-14T18:25:14.393580Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:14.393683Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 69 (previous tip: 68) +2025-11-14T18:25:14.393694Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 69 (last_processed_height: 68, tip: 69) +2025-11-14T18:25:14.393748Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 69)], last_processed_height: 68, tip: 69 +2025-11-14T18:25:14.393753Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:14.394597Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 30) (last_processed_height=68, tip=68) +2025-11-14T18:25:14.394756Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xc295910a7c84620a8477a71bace979b0b18de0c4592cd6a251535c2ea37cc9d6 for height 69 +2025-11-14T18:25:14.394893Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xc295910a7c84620a8477a71bace979b0b18de0c4592cd6a251535c2ea37cc9d6 for height 69 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 69 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 69, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 69, is last block: false +2025-11-14T18:25:14.394999Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=69 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 69 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 69, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 69, is last block: false +2025-11-14T18:25:14.395097Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=69 +2025-11-14T18:25:14.395138Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xc295910a7c84620a8477a71bace979b0b18de0c4592cd6a251535c2ea37cc9d6 for height 69 +2025-11-14T18:25:14.395249Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 70 not found (last_processed=69, tip=69) +üüüüüüüüüüüüüüüüüüüüüüüüü +2025-11-14T18:25:14.395259Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 70 not found (last_processed=69, tip=69) +COMMITING BLOCK 69 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 69, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 69, is last block: false +2025-11-14T18:25:14.395271Z  INFO ThreadId(89) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=69 +2025-11-14T18:25:14.395275Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 69 (previous tip: 68) +2025-11-14T18:25:14.395281Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 69 (last_processed_height: 68, tip: 69) +2025-11-14T18:25:14.395314Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 69)], last_processed_height: 68, tip: 69 +2025-11-14T18:25:14.395318Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:14.395430Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 70 not found (last_processed=69, tip=69) +2025-11-14T18:25:14.396238Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xc295910a7c84620a8477a71bace979b0b18de0c4592cd6a251535c2ea37cc9d6 for height 69 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 69 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 69, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 69, is last block: false +2025-11-14T18:25:14.396401Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=69 +2025-11-14T18:25:14.396533Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 70 not found (last_processed=69, tip=69) +2025-11-14T18:25:14.447153Z  INFO ThreadId(89) summit_application::actor: application/src/actor.rs:177: 143 Handling message Broadcast +2025-11-14T18:25:14.449373Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 31) (epoch 1, view 31), parent height: 30 +2025-11-14T18:25:14.449378Z  INFO ThreadId(43) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 31) (epoch 1, view 31), parent height: 30 +2025-11-14T18:25:14.449895Z  INFO ThreadId(57) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 31) (epoch 1, view 31), parent height: 30 +2025-11-14T18:25:14.452568Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:149: 139 application: Handling message Propose for round Round(1, 32) (epoch 1, view 32), parent height: 31 +2025-11-14T18:25:14.454100Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 31) (last_processed_height=69, tip=69) +2025-11-14T18:25:14.454714Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 70 (previous tip: 69) +2025-11-14T18:25:14.454719Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 70 (last_processed_height: 69, tip: 70) +2025-11-14T18:25:14.454753Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 31) (last_processed_height=69, tip=69) +2025-11-14T18:25:14.454757Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 70)], last_processed_height: 69, tip: 70 +2025-11-14T18:25:14.454761Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:14.454765Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 31) (last_processed_height=69, tip=69) +2025-11-14T18:25:14.455045Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 31) (last_processed_height=69, tip=69) +2025-11-14T18:25:14.455291Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 70 (previous tip: 69) +2025-11-14T18:25:14.455298Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 70 (last_processed_height: 69, tip: 70) +2025-11-14T18:25:14.455335Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 70)], last_processed_height: 69, tip: 70 +2025-11-14T18:25:14.455340Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:14.455590Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 70 (previous tip: 69) +2025-11-14T18:25:14.455596Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 70 (last_processed_height: 69, tip: 70) +2025-11-14T18:25:14.455638Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 70)], last_processed_height: 69, tip: 70 +2025-11-14T18:25:14.455642Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:14.455682Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 70 (previous tip: 69) +2025-11-14T18:25:14.455692Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 70 (last_processed_height: 69, tip: 70) +2025-11-14T18:25:14.455745Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 70)], last_processed_height: 69, tip: 70 +2025-11-14T18:25:14.455761Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:14.456052Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x253be61b773e79b7d4713a401864da779c87f22d9c6f884cf4b0527afbce33ca for height 70 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 70 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 70, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 70, is last block: false +2025-11-14T18:25:14.456357Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=70 +2025-11-14T18:25:14.456721Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 71 not found (last_processed=70, tip=70) +2025-11-14T18:25:14.457028Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x253be61b773e79b7d4713a401864da779c87f22d9c6f884cf4b0527afbce33ca for height 70 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 70 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 70, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 70, is last block: false +2025-11-14T18:25:14.457296Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=70 +2025-11-14T18:25:14.457385Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x253be61b773e79b7d4713a401864da779c87f22d9c6f884cf4b0527afbce33ca for height 70 +2025-11-14T18:25:14.457416Z  INFO ThreadId(90) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x253be61b773e79b7d4713a401864da779c87f22d9c6f884cf4b0527afbce33ca for height 70 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 70 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 70, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 70, is last block: false +2025-11-14T18:25:14.457570Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=70 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 70 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 70, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 70, is last block: false +2025-11-14T18:25:14.457580Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 71 not found (last_processed=70, tip=70) +2025-11-14T18:25:14.457581Z  INFO ThreadId(88) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=70 +2025-11-14T18:25:14.457709Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 71 not found (last_processed=70, tip=70) +2025-11-14T18:25:14.457717Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 71 not found (last_processed=70, tip=70) +2025-11-14T18:25:14.493272Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:14.507238Z  INFO ThreadId(52) summit_application::actor: application/src/actor.rs:177: 139 Handling message Broadcast +2025-11-14T18:25:14.510286Z  INFO ThreadId(43) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 32) (epoch 1, view 32), parent height: 31 +2025-11-14T18:25:14.510739Z  INFO ThreadId(57) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 32) (epoch 1, view 32), parent height: 31 +2025-11-14T18:25:14.510816Z  INFO ThreadId(90) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 32) (epoch 1, view 32), parent height: 31 +2025-11-14T18:25:14.513965Z  INFO ThreadId(56) summit_application::actor: application/src/actor.rs:149: 55 application: Handling message Propose for round Round(1, 33) (epoch 1, view 33), parent height: 32 +2025-11-14T18:25:14.515389Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 32) (last_processed_height=70, tip=70) +2025-11-14T18:25:14.515489Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 32) (last_processed_height=70, tip=70) +2025-11-14T18:25:14.515557Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 32) (last_processed_height=70, tip=70) +2025-11-14T18:25:14.515627Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 32) (last_processed_height=70, tip=70) +2025-11-14T18:25:14.516166Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 71 (previous tip: 70) +2025-11-14T18:25:14.516172Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 71 (last_processed_height: 70, tip: 71) +2025-11-14T18:25:14.516201Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 71 (previous tip: 70) +2025-11-14T18:25:14.516207Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 71 (last_processed_height: 70, tip: 71) +2025-11-14T18:25:14.516221Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 71)], last_processed_height: 70, tip: 71 +2025-11-14T18:25:14.516224Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:14.516240Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 71)], last_processed_height: 70, tip: 71 +2025-11-14T18:25:14.516243Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:14.516258Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 71 (previous tip: 70) +2025-11-14T18:25:14.516262Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 71 (last_processed_height: 70, tip: 71) +2025-11-14T18:25:14.516291Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 71)], last_processed_height: 70, tip: 71 +2025-11-14T18:25:14.516294Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:14.516309Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 71 (previous tip: 70) +2025-11-14T18:25:14.516317Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 71 (last_processed_height: 70, tip: 71) +2025-11-14T18:25:14.516347Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 71)], last_processed_height: 70, tip: 71 +2025-11-14T18:25:14.516350Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:14.517845Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xcd8e728da6351690461555db1d4414d702ac5f0d5761db673cdfb518b4ec9b92 for height 71 +2025-11-14T18:25:14.517845Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xcd8e728da6351690461555db1d4414d702ac5f0d5761db673cdfb518b4ec9b92 for height 71 +2025-11-14T18:25:14.518053Z  INFO ThreadId(90) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xcd8e728da6351690461555db1d4414d702ac5f0d5761db673cdfb518b4ec9b92 for height 71 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 71 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 71, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 71, is last block: false +2025-11-14T18:25:14.518100Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=71 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 71 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 71, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 71, is last block: false +2025-11-14T18:25:14.518114Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=71 +2025-11-14T18:25:14.518226Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xcd8e728da6351690461555db1d4414d702ac5f0d5761db673cdfb518b4ec9b92 for height 71 +2025-11-14T18:25:14.518290Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 72 not found (last_processed=71, tip=71) +2025-11-14T18:25:14.518325Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 72 not found (last_processed=71, tip=71) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 71 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 71, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 71, is last block: false +2025-11-14T18:25:14.518393Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=71 +2025-11-14T18:25:14.518507Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 72 not found (last_processed=71, tip=71) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 71 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 71, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 71, is last block: false +2025-11-14T18:25:14.518586Z  INFO ThreadId(90) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=71 +2025-11-14T18:25:14.518746Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 72 not found (last_processed=71, tip=71) +2025-11-14T18:25:14.569100Z  INFO ThreadId(57) summit_application::actor: application/src/actor.rs:177: 55 Handling message Broadcast +2025-11-14T18:25:14.571704Z  INFO ThreadId(89) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 33) (epoch 1, view 33), parent height: 32 +2025-11-14T18:25:14.571710Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 33) (epoch 1, view 33), parent height: 32 +2025-11-14T18:25:14.571733Z  INFO ThreadId(49) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 33) (epoch 1, view 33), parent height: 32 +2025-11-14T18:25:14.576632Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 33) (last_processed_height=71, tip=71) +2025-11-14T18:25:14.576653Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 33) (last_processed_height=71, tip=71) +2025-11-14T18:25:14.576656Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 33) (last_processed_height=71, tip=71) +2025-11-14T18:25:14.577308Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 72 (previous tip: 71) +2025-11-14T18:25:14.577325Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 72 (last_processed_height: 71, tip: 72) +2025-11-14T18:25:14.577368Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 72 (previous tip: 71) +2025-11-14T18:25:14.577396Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 72 (last_processed_height: 71, tip: 72) +2025-11-14T18:25:14.577454Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 72)], last_processed_height: 71, tip: 72 +2025-11-14T18:25:14.577467Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:14.577488Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 72)], last_processed_height: 71, tip: 72 +2025-11-14T18:25:14.577495Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:14.577653Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 72 (previous tip: 71) +2025-11-14T18:25:14.577672Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 72 (last_processed_height: 71, tip: 72) +2025-11-14T18:25:14.577747Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 72)], last_processed_height: 71, tip: 72 +2025-11-14T18:25:14.577758Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:14.578536Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 33) (last_processed_height=71, tip=71) +2025-11-14T18:25:14.580910Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 72 (previous tip: 71) +2025-11-14T18:25:14.580921Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 72 (last_processed_height: 71, tip: 72) +2025-11-14T18:25:14.580991Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 72)], last_processed_height: 71, tip: 72 +2025-11-14T18:25:14.581006Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:14.581180Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x90f4136cbc65111bb6be981690314883e22016a88ba63964b2e8b7efb9ed79f1 for height 72 +2025-11-14T18:25:14.581181Z  INFO ThreadId(89) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x90f4136cbc65111bb6be981690314883e22016a88ba63964b2e8b7efb9ed79f1 for height 72 +2025-11-14T18:25:14.581265Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x90f4136cbc65111bb6be981690314883e22016a88ba63964b2e8b7efb9ed79f1 for height 72 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 72 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 72, is penultimate block: false +üüüüüüüüüüüüüüüüüüüüüüüüü +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +COMMITING BLOCK 72 to reth +epoch_num_of_blocks: 50, new_height: 72, is last block: false +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 72, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 72, is last block: false +2025-11-14T18:25:14.581346Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=72 +2025-11-14T18:25:14.581349Z  INFO ThreadId(89) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=72 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 72 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 72, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 72, is last block: false +2025-11-14T18:25:14.581433Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=72 +2025-11-14T18:25:14.581521Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 73 not found (last_processed=72, tip=72) +2025-11-14T18:25:14.581522Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 73 not found (last_processed=72, tip=72) +2025-11-14T18:25:14.581664Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 73 not found (last_processed=72, tip=72) +2025-11-14T18:25:14.581917Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x90f4136cbc65111bb6be981690314883e22016a88ba63964b2e8b7efb9ed79f1 for height 72 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 72 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 72, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 72, is last block: false +2025-11-14T18:25:14.582050Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=72 +2025-11-14T18:25:14.582173Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 73 not found (last_processed=72, tip=72) +2025-11-14T18:25:14.745089Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:14.997846Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +Node 1 at height 72 +2025-11-14T18:25:15.250133Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +Node 2 at height 72 +Node 3 at height 72 +Node 4 at height 72 +2025-11-14T18:25:15.502215Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:15.754996Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:16.007603Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:16.260116Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:16.512952Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:16.578046Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:149: 15 application: Handling message Propose for round Round(1, 35) (epoch 1, view 35), parent height: 33 +2025-11-14T18:25:16.630620Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:177: 15 Handling message Broadcast +2025-11-14T18:25:16.632820Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 35) (epoch 1, view 35), parent height: 33 +2025-11-14T18:25:16.633128Z  INFO ThreadId(90) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 35) (epoch 1, view 35), parent height: 33 +2025-11-14T18:25:16.633193Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 35) (epoch 1, view 35), parent height: 33 +2025-11-14T18:25:16.637176Z  INFO ThreadId(91) summit_application::actor: application/src/actor.rs:149: 143 application: Handling message Propose for round Round(1, 36) (epoch 1, view 36), parent height: 35 +2025-11-14T18:25:16.638816Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 35) (last_processed_height=72, tip=72) +2025-11-14T18:25:16.638870Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 35) (last_processed_height=72, tip=72) +2025-11-14T18:25:16.639267Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 73 (previous tip: 72) +2025-11-14T18:25:16.639273Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 73 (last_processed_height: 72, tip: 73) +2025-11-14T18:25:16.639308Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 73)], last_processed_height: 72, tip: 73 +2025-11-14T18:25:16.639312Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:16.639689Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 73 (previous tip: 72) +2025-11-14T18:25:16.639695Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 73 (last_processed_height: 72, tip: 73) +2025-11-14T18:25:16.639729Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 73)], last_processed_height: 72, tip: 73 +2025-11-14T18:25:16.639732Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:16.640320Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 35) (last_processed_height=72, tip=72) +2025-11-14T18:25:16.640337Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 35) (last_processed_height=72, tip=72) +2025-11-14T18:25:16.640410Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xe5e320d7a65d498b9dc688e9e4de419f3e8334fcfceb6120905717c56fb083b3 for height 73 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 73 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 73, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 73, is last block: false +2025-11-14T18:25:16.640737Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=73 +2025-11-14T18:25:16.640939Z  INFO ThreadId(89) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xe5e320d7a65d498b9dc688e9e4de419f3e8334fcfceb6120905717c56fb083b3 for height 73 +2025-11-14T18:25:16.640945Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 74 not found (last_processed=73, tip=73) +2025-11-14T18:25:16.640964Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 73 (previous tip: 72) +2025-11-14T18:25:16.640971Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 73 (last_processed_height: 72, tip: 73) +2025-11-14T18:25:16.641058Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 73)], last_processed_height: 72, tip: 73 +2025-11-14T18:25:16.641063Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 73 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 73, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 73, is last block: false +2025-11-14T18:25:16.641078Z  INFO ThreadId(89) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=73 +2025-11-14T18:25:16.641187Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 73 (previous tip: 72) +2025-11-14T18:25:16.641193Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 73 (last_processed_height: 72, tip: 73) +2025-11-14T18:25:16.641220Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 73)], last_processed_height: 72, tip: 73 +2025-11-14T18:25:16.641224Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:16.641276Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 74 not found (last_processed=73, tip=73) +2025-11-14T18:25:16.642047Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xe5e320d7a65d498b9dc688e9e4de419f3e8334fcfceb6120905717c56fb083b3 for height 73 +2025-11-14T18:25:16.642057Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xe5e320d7a65d498b9dc688e9e4de419f3e8334fcfceb6120905717c56fb083b3 for height 73 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 73 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 73, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 73, is last block: false +2025-11-14T18:25:16.642179Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=73 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 73 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 73, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 73, is last block: false +2025-11-14T18:25:16.642191Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=73 +2025-11-14T18:25:16.642333Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 74 not found (last_processed=73, tip=73) +2025-11-14T18:25:16.642355Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 74 not found (last_processed=73, tip=73) +2025-11-14T18:25:16.692893Z  INFO ThreadId(89) summit_application::actor: application/src/actor.rs:177: 143 Handling message Broadcast +2025-11-14T18:25:16.695447Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 36) (epoch 1, view 36), parent height: 35 +2025-11-14T18:25:16.695525Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 36) (epoch 1, view 36), parent height: 35 +2025-11-14T18:25:16.696411Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 36) (epoch 1, view 36), parent height: 35 +2025-11-14T18:25:16.699681Z  INFO ThreadId(49) summit_application::actor: application/src/actor.rs:149: 139 application: Handling message Propose for round Round(1, 37) (epoch 1, view 37), parent height: 36 +2025-11-14T18:25:16.700335Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 36) (last_processed_height=73, tip=73) +2025-11-14T18:25:16.700423Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 36) (last_processed_height=73, tip=73) +2025-11-14T18:25:16.700790Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 74 (previous tip: 73) +2025-11-14T18:25:16.700795Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 74 (last_processed_height: 73, tip: 74) +2025-11-14T18:25:16.700825Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 74)], last_processed_height: 73, tip: 74 +2025-11-14T18:25:16.700828Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:16.700883Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 74 (previous tip: 73) +2025-11-14T18:25:16.700890Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 74 (last_processed_height: 73, tip: 74) +2025-11-14T18:25:16.700921Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 74)], last_processed_height: 73, tip: 74 +2025-11-14T18:25:16.700923Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:16.701052Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 36) (last_processed_height=73, tip=73) +2025-11-14T18:25:16.701086Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 36) (last_processed_height=73, tip=73) +2025-11-14T18:25:16.701662Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 74 (previous tip: 73) +2025-11-14T18:25:16.701671Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 74 (last_processed_height: 73, tip: 74) +2025-11-14T18:25:16.701698Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 74)], last_processed_height: 73, tip: 74 +2025-11-14T18:25:16.701700Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:16.701870Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x3705ae02353c42092576fa6a929b31be3ba88d576f92bd9e33fdb4f6cbcc1c07 for height 74 +2025-11-14T18:25:16.701870Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x3705ae02353c42092576fa6a929b31be3ba88d576f92bd9e33fdb4f6cbcc1c07 for height 74 +2025-11-14T18:25:16.701939Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 74 (previous tip: 73) +2025-11-14T18:25:16.701945Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 74 (last_processed_height: 73, tip: 74) +2025-11-14T18:25:16.701990Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 74)], last_processed_height: 73, tip: 74 +2025-11-14T18:25:16.701995Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +üüüüüüüüüüüüüüüüüüüüüüüüü +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 74 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +COMMITING BLOCK 74 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 74, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 74, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 74, is last block: false +epoch_num_of_blocks: 50, new_height: 74, is last block: false +2025-11-14T18:25:16.702031Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=74 +2025-11-14T18:25:16.702035Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=74 +2025-11-14T18:25:16.702159Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 75 not found (last_processed=74, tip=74) +2025-11-14T18:25:16.702209Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 75 not found (last_processed=74, tip=74) +2025-11-14T18:25:16.702889Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x3705ae02353c42092576fa6a929b31be3ba88d576f92bd9e33fdb4f6cbcc1c07 for height 74 +2025-11-14T18:25:16.702896Z  INFO ThreadId(88) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x3705ae02353c42092576fa6a929b31be3ba88d576f92bd9e33fdb4f6cbcc1c07 for height 74 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 74 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 74, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 74, is last block: false +2025-11-14T18:25:16.703009Z  INFO ThreadId(90) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=74 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 74 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 74, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 74, is last block: false +2025-11-14T18:25:16.703031Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=74 +2025-11-14T18:25:16.703133Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 75 not found (last_processed=74, tip=74) +2025-11-14T18:25:16.703145Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 75 not found (last_processed=74, tip=74) +2025-11-14T18:25:16.753981Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:177: 139 Handling message Broadcast +2025-11-14T18:25:16.756675Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 37) (epoch 1, view 37), parent height: 36 +2025-11-14T18:25:16.757142Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 37) (epoch 1, view 37), parent height: 36 +2025-11-14T18:25:16.757488Z  INFO ThreadId(88) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 37) (epoch 1, view 37), parent height: 36 +2025-11-14T18:25:16.761192Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:149: 55 application: Handling message Propose for round Round(1, 38) (epoch 1, view 38), parent height: 37 +2025-11-14T18:25:16.763135Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 37) (last_processed_height=74, tip=74) +2025-11-14T18:25:16.763253Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 37) (last_processed_height=74, tip=74) +2025-11-14T18:25:16.763282Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 37) (last_processed_height=74, tip=74) +2025-11-14T18:25:16.763313Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 37) (last_processed_height=74, tip=74) +2025-11-14T18:25:16.763762Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 75 (previous tip: 74) +2025-11-14T18:25:16.763768Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 75 (last_processed_height: 74, tip: 75) +2025-11-14T18:25:16.763805Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 75)], last_processed_height: 74, tip: 75 +2025-11-14T18:25:16.763809Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:16.763824Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 75 (previous tip: 74) +2025-11-14T18:25:16.763830Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 75 (last_processed_height: 74, tip: 75) +2025-11-14T18:25:16.763850Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 75 (previous tip: 74) +2025-11-14T18:25:16.763863Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 75 (last_processed_height: 74, tip: 75) +2025-11-14T18:25:16.763872Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 75)], last_processed_height: 74, tip: 75 +2025-11-14T18:25:16.763876Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:16.763884Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 75 (previous tip: 74) +2025-11-14T18:25:16.763890Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 75 (last_processed_height: 74, tip: 75) +2025-11-14T18:25:16.763905Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 75)], last_processed_height: 74, tip: 75 +2025-11-14T18:25:16.763912Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:16.763921Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 75)], last_processed_height: 74, tip: 75 +2025-11-14T18:25:16.763923Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:16.765224Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:16.765273Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xb141330021f84a7effa6714522614205496f4cf7970984fe14749df9157b39bd for height 75 +2025-11-14T18:25:16.765282Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xb141330021f84a7effa6714522614205496f4cf7970984fe14749df9157b39bd for height 75 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 75 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 75, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 75, is last block: false +2025-11-14T18:25:16.765562Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=75 +2025-11-14T18:25:16.765594Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xb141330021f84a7effa6714522614205496f4cf7970984fe14749df9157b39bd for height 75 +2025-11-14T18:25:16.765656Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xb141330021f84a7effa6714522614205496f4cf7970984fe14749df9157b39bd for height 75 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 75 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 75, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 75, is last block: false +2025-11-14T18:25:16.765669Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=75 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 75 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 75, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 75, is last block: false +2025-11-14T18:25:16.765769Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=75 +2025-11-14T18:25:16.765791Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 76 not found (last_processed=75, tip=75) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 75 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 75, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 75, is last block: false +2025-11-14T18:25:16.765841Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=75 +2025-11-14T18:25:16.765866Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 76 not found (last_processed=75, tip=75) +2025-11-14T18:25:16.765978Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 76 not found (last_processed=75, tip=75) +2025-11-14T18:25:16.766010Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 76 not found (last_processed=75, tip=75) +2025-11-14T18:25:16.817848Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:177: 55 Handling message Broadcast +2025-11-14T18:25:16.820106Z  INFO ThreadId(89) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 38) (epoch 1, view 38), parent height: 37 +2025-11-14T18:25:16.820367Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 38) (epoch 1, view 38), parent height: 37 +2025-11-14T18:25:16.820776Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 38) (epoch 1, view 38), parent height: 37 +2025-11-14T18:25:16.826044Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 38) (last_processed_height=75, tip=75) +2025-11-14T18:25:16.826245Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 38) (last_processed_height=75, tip=75) +2025-11-14T18:25:16.826616Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 76 (previous tip: 75) +2025-11-14T18:25:16.826626Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 76 (last_processed_height: 75, tip: 76) +2025-11-14T18:25:16.826656Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 76)], last_processed_height: 75, tip: 76 +2025-11-14T18:25:16.826659Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:16.826710Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 76 (previous tip: 75) +2025-11-14T18:25:16.826715Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 76 (last_processed_height: 75, tip: 76) +2025-11-14T18:25:16.826737Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 76)], last_processed_height: 75, tip: 76 +2025-11-14T18:25:16.826739Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:16.826965Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 38) (last_processed_height=75, tip=75) +2025-11-14T18:25:16.826979Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 38) (last_processed_height=75, tip=75) +2025-11-14T18:25:16.827521Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 76 (previous tip: 75) +2025-11-14T18:25:16.827527Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 76 (last_processed_height: 75, tip: 76) +2025-11-14T18:25:16.827563Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 76)], last_processed_height: 75, tip: 76 +2025-11-14T18:25:16.827569Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:16.827634Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 76 (previous tip: 75) +2025-11-14T18:25:16.827641Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 76 (last_processed_height: 75, tip: 76) +2025-11-14T18:25:16.827679Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 76)], last_processed_height: 75, tip: 76 +2025-11-14T18:25:16.827683Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:16.827806Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xe45ccbded28c5f66ca282a109c5ec3ad5da9a2060f05f0f1b885090c6ebb126e for height 76 +2025-11-14T18:25:16.827851Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xe45ccbded28c5f66ca282a109c5ec3ad5da9a2060f05f0f1b885090c6ebb126e for height 76 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 76 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 76, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 76, is last block: false +2025-11-14T18:25:16.827978Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=76 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 76 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 76, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 76, is last block: false +2025-11-14T18:25:16.827991Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=76 +2025-11-14T18:25:16.828139Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 77 not found (last_processed=76, tip=76) +2025-11-14T18:25:16.828147Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 77 not found (last_processed=76, tip=76) +2025-11-14T18:25:16.829379Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xe45ccbded28c5f66ca282a109c5ec3ad5da9a2060f05f0f1b885090c6ebb126e for height 76 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 76 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 76, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 76, is last block: false +2025-11-14T18:25:16.829543Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=76 +2025-11-14T18:25:16.829680Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:149: 15 application: Handling message Propose for round Round(1, 40) (epoch 1, view 40), parent height: 38 +2025-11-14T18:25:16.829682Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 77 not found (last_processed=76, tip=76) +2025-11-14T18:25:16.829727Z  INFO ThreadId(89) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xe45ccbded28c5f66ca282a109c5ec3ad5da9a2060f05f0f1b885090c6ebb126e for height 76 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 76 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 76, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 76, is last block: false +2025-11-14T18:25:16.829864Z  INFO ThreadId(88) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=76 +2025-11-14T18:25:16.830019Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 77 not found (last_processed=76, tip=76) +2025-11-14T18:25:16.881800Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:177: 15 Handling message Broadcast +2025-11-14T18:25:16.884333Z  INFO ThreadId(89) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 40) (epoch 1, view 40), parent height: 38 +2025-11-14T18:25:16.884394Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 40) (epoch 1, view 40), parent height: 38 +2025-11-14T18:25:16.884436Z  INFO ThreadId(57) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 40) (epoch 1, view 40), parent height: 38 +2025-11-14T18:25:16.886607Z  INFO ThreadId(90) summit_application::actor: application/src/actor.rs:149: 143 application: Handling message Propose for round Round(1, 41) (epoch 1, view 41), parent height: 40 +2025-11-14T18:25:16.953818Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 40) (last_processed_height=76, tip=76) +2025-11-14T18:25:16.955068Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 77 (previous tip: 76) +2025-11-14T18:25:16.955079Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 77 (last_processed_height: 76, tip: 77) +2025-11-14T18:25:16.955115Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 77)], last_processed_height: 76, tip: 77 +2025-11-14T18:25:16.955118Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:16.955473Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 40) (last_processed_height=76, tip=76) +2025-11-14T18:25:16.955708Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 40) (last_processed_height=76, tip=76) +2025-11-14T18:25:16.955794Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 40) (last_processed_height=76, tip=76) +2025-11-14T18:25:16.956049Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 77 (previous tip: 76) +2025-11-14T18:25:16.956057Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 77 (last_processed_height: 76, tip: 77) +2025-11-14T18:25:16.956090Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 77)], last_processed_height: 76, tip: 77 +2025-11-14T18:25:16.956093Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:16.956181Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x5dfa4fc970ae269583f5b0a29a35e507a482e437f3c26439103e71660272a129 for height 77 +2025-11-14T18:25:16.956320Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 77 (previous tip: 76) +2025-11-14T18:25:16.956325Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 77 (last_processed_height: 76, tip: 77) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 77 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 77, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 77, is last block: false +2025-11-14T18:25:16.956336Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=77 +2025-11-14T18:25:16.956366Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 77)], last_processed_height: 76, tip: 77 +2025-11-14T18:25:16.956370Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:16.956469Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 78 not found (last_processed=77, tip=77) +2025-11-14T18:25:16.956530Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 77 (previous tip: 76) +2025-11-14T18:25:16.956538Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 77 (last_processed_height: 76, tip: 77) +2025-11-14T18:25:16.956573Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 77)], last_processed_height: 76, tip: 77 +2025-11-14T18:25:16.956576Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:16.957323Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x5dfa4fc970ae269583f5b0a29a35e507a482e437f3c26439103e71660272a129 for height 77 +2025-11-14T18:25:16.957526Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x5dfa4fc970ae269583f5b0a29a35e507a482e437f3c26439103e71660272a129 for height 77 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 77 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 77, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +2025-11-14T18:25:16.957533Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x5dfa4fc970ae269583f5b0a29a35e507a482e437f3c26439103e71660272a129 for height 77 +epoch_num_of_blocks: 50, new_height: 77, is last block: false +2025-11-14T18:25:16.957542Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=77 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 77 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 77, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 77, is last block: false +2025-11-14T18:25:16.957653Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=77 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 77 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 77, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 77, is last block: false +2025-11-14T18:25:16.957709Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=77 +2025-11-14T18:25:16.957715Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 78 not found (last_processed=77, tip=77) +2025-11-14T18:25:16.957892Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 78 not found (last_processed=77, tip=77) +2025-11-14T18:25:16.958240Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 78 not found (last_processed=77, tip=77) +2025-11-14T18:25:17.009515Z  INFO ThreadId(88) summit_application::actor: application/src/actor.rs:177: 143 Handling message Broadcast +2025-11-14T18:25:17.012374Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 41) (epoch 1, view 41), parent height: 40 +2025-11-14T18:25:17.012559Z  INFO ThreadId(52) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 41) (epoch 1, view 41), parent height: 40 +2025-11-14T18:25:17.013044Z  INFO ThreadId(56) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 41) (epoch 1, view 41), parent height: 40 +2025-11-14T18:25:17.015355Z  INFO ThreadId(49) summit_application::actor: application/src/actor.rs:149: 139 application: Handling message Propose for round Round(1, 42) (epoch 1, view 42), parent height: 41 +2025-11-14T18:25:17.017093Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:17.080778Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 41) (last_processed_height=77, tip=77) +2025-11-14T18:25:17.081537Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 78 (previous tip: 77) +2025-11-14T18:25:17.081544Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 78 (last_processed_height: 77, tip: 78) +2025-11-14T18:25:17.081579Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 78)], last_processed_height: 77, tip: 78 +2025-11-14T18:25:17.081582Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:17.081807Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 41) (last_processed_height=77, tip=77) +2025-11-14T18:25:17.082090Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 41) (last_processed_height=77, tip=77) +2025-11-14T18:25:17.082547Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 78 (previous tip: 77) +2025-11-14T18:25:17.082549Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xbc305be9eaa0979f64cf44e0e41fcfb0654099fc64ce33ff81ad75a15db669f3 for height 78 +2025-11-14T18:25:17.082553Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 78 (last_processed_height: 77, tip: 78) +2025-11-14T18:25:17.082599Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 78)], last_processed_height: 77, tip: 78 +2025-11-14T18:25:17.082603Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:17.082667Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 41) (last_processed_height=77, tip=77) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 78 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 78, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +2025-11-14T18:25:17.082692Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 78 (previous tip: 77) +2025-11-14T18:25:17.082708Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 78 (last_processed_height: 77, tip: 78) +epoch_num_of_blocks: 50, new_height: 78, is last block: false +2025-11-14T18:25:17.082715Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=78 +2025-11-14T18:25:17.082763Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 78)], last_processed_height: 77, tip: 78 +2025-11-14T18:25:17.082768Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:17.082880Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 79 not found (last_processed=78, tip=78) +2025-11-14T18:25:17.083433Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 78 (previous tip: 77) +2025-11-14T18:25:17.083440Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 78 (last_processed_height: 77, tip: 78) +2025-11-14T18:25:17.083477Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xbc305be9eaa0979f64cf44e0e41fcfb0654099fc64ce33ff81ad75a15db669f3 for height 78 +2025-11-14T18:25:17.083492Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 78)], last_processed_height: 77, tip: 78 +2025-11-14T18:25:17.083495Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 78 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 78, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 78, is last block: false +2025-11-14T18:25:17.083694Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=78 +2025-11-14T18:25:17.083715Z  INFO ThreadId(90) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xbc305be9eaa0979f64cf44e0e41fcfb0654099fc64ce33ff81ad75a15db669f3 for height 78 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 78 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 78, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 78, is last block: false +2025-11-14T18:25:17.083834Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=78 +2025-11-14T18:25:17.083866Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 79 not found (last_processed=78, tip=78) +2025-11-14T18:25:17.084021Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 79 not found (last_processed=78, tip=78) +2025-11-14T18:25:17.084344Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xbc305be9eaa0979f64cf44e0e41fcfb0654099fc64ce33ff81ad75a15db669f3 for height 78 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 78 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 78, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 78, is last block: false +2025-11-14T18:25:17.084463Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=78 +2025-11-14T18:25:17.084599Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 79 not found (last_processed=78, tip=78) +2025-11-14T18:25:17.136165Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:177: 139 Handling message Broadcast +2025-11-14T18:25:17.204637Z  INFO ThreadId(90) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 42) (epoch 1, view 42), parent height: 41 +2025-11-14T18:25:17.205341Z  INFO ThreadId(43) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 42) (epoch 1, view 42), parent height: 41 +2025-11-14T18:25:17.205517Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 42) (epoch 1, view 42), parent height: 41 +2025-11-14T18:25:17.207319Z  INFO ThreadId(56) summit_application::actor: application/src/actor.rs:149: 55 application: Handling message Propose for round Round(1, 43) (epoch 1, view 43), parent height: 42 +2025-11-14T18:25:17.269734Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +Node 1 at height 78 +Node 2 at height 78 +Node 3 at height 78 +Node 4 at height 78 +2025-11-14T18:25:17.329177Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 42) (last_processed_height=78, tip=78) +2025-11-14T18:25:17.329741Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 42) (last_processed_height=78, tip=78) +2025-11-14T18:25:17.330163Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 42) (last_processed_height=78, tip=78) +2025-11-14T18:25:17.330323Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 79 (previous tip: 78) +2025-11-14T18:25:17.330335Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 79 (last_processed_height: 78, tip: 79) +2025-11-14T18:25:17.330392Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 79)], last_processed_height: 78, tip: 79 +2025-11-14T18:25:17.330399Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:17.330569Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 42) (last_processed_height=78, tip=78) +2025-11-14T18:25:17.330803Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 79 (previous tip: 78) +2025-11-14T18:25:17.330809Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 79 (last_processed_height: 78, tip: 79) +2025-11-14T18:25:17.330847Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 79)], last_processed_height: 78, tip: 79 +2025-11-14T18:25:17.330850Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:17.330873Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 79 (previous tip: 78) +2025-11-14T18:25:17.330879Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 79 (last_processed_height: 78, tip: 79) +2025-11-14T18:25:17.330909Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 79)], last_processed_height: 78, tip: 79 +2025-11-14T18:25:17.330912Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:17.331189Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 79 (previous tip: 78) +2025-11-14T18:25:17.331196Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 79 (last_processed_height: 78, tip: 79) +2025-11-14T18:25:17.331228Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 79)], last_processed_height: 78, tip: 79 +2025-11-14T18:25:17.331235Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:17.331657Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x71ba9f8324739cae75fe220a6b402384d7282125486e7b17d297eb824bacf7c7 for height 79 +2025-11-14T18:25:17.331819Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x71ba9f8324739cae75fe220a6b402384d7282125486e7b17d297eb824bacf7c7 for height 79 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 79 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 79, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 79, is last block: false +2025-11-14T18:25:17.331889Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=79 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 79 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 79, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 79, is last block: false +2025-11-14T18:25:17.331997Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=79 +2025-11-14T18:25:17.332072Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 80 not found (last_processed=79, tip=79) +2025-11-14T18:25:17.332080Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x71ba9f8324739cae75fe220a6b402384d7282125486e7b17d297eb824bacf7c7 for height 79 +2025-11-14T18:25:17.332203Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 80 not found (last_processed=79, tip=79) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 79 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 79, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 79, is last block: false +2025-11-14T18:25:17.332312Z  INFO ThreadId(89) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=79 +2025-11-14T18:25:17.332514Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 80 not found (last_processed=79, tip=79) +2025-11-14T18:25:17.332517Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x71ba9f8324739cae75fe220a6b402384d7282125486e7b17d297eb824bacf7c7 for height 79 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 79 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 79, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 79, is last block: false +2025-11-14T18:25:17.332669Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=79 +2025-11-14T18:25:17.332822Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 80 not found (last_processed=79, tip=79) +2025-11-14T18:25:17.382983Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:177: 55 Handling message Broadcast +2025-11-14T18:25:17.385730Z  INFO ThreadId(91) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 43) (epoch 1, view 43), parent height: 42 +2025-11-14T18:25:17.385768Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 43) (epoch 1, view 43), parent height: 42 +2025-11-14T18:25:17.386414Z  INFO ThreadId(52) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 43) (epoch 1, view 43), parent height: 42 +2025-11-14T18:25:17.456143Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 43) (last_processed_height=79, tip=79) +2025-11-14T18:25:17.456391Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 43) (last_processed_height=79, tip=79) +2025-11-14T18:25:17.456436Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 43) (last_processed_height=79, tip=79) +2025-11-14T18:25:17.456456Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 43) (last_processed_height=79, tip=79) +2025-11-14T18:25:17.456724Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 80 (previous tip: 79) +2025-11-14T18:25:17.456731Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 80 (last_processed_height: 79, tip: 80) +2025-11-14T18:25:17.456782Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 80)], last_processed_height: 79, tip: 80 +2025-11-14T18:25:17.456788Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:17.456881Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 80 (previous tip: 79) +2025-11-14T18:25:17.456886Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 80 (last_processed_height: 79, tip: 80) +2025-11-14T18:25:17.456926Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 80)], last_processed_height: 79, tip: 80 +2025-11-14T18:25:17.456928Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:17.456982Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 80 (previous tip: 79) +2025-11-14T18:25:17.456988Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 80 (last_processed_height: 79, tip: 80) +2025-11-14T18:25:17.457008Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 80 (previous tip: 79) +2025-11-14T18:25:17.457014Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 80 (last_processed_height: 79, tip: 80) +2025-11-14T18:25:17.457014Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 80)], last_processed_height: 79, tip: 80 +2025-11-14T18:25:17.457017Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:17.457046Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 80)], last_processed_height: 79, tip: 80 +2025-11-14T18:25:17.457050Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:17.458121Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x720f89d77604166a7df6ca2765a4f571212aad03f00ab40add742b9323389173 for height 80 +2025-11-14T18:25:17.458154Z  INFO ThreadId(90) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x720f89d77604166a7df6ca2765a4f571212aad03f00ab40add742b9323389173 for height 80 +2025-11-14T18:25:17.458246Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x720f89d77604166a7df6ca2765a4f571212aad03f00ab40add742b9323389173 for height 80 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 80 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 80, is penultimate block: false +2025-11-14T18:25:17.458351Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x720f89d77604166a7df6ca2765a4f571212aad03f00ab40add742b9323389173 for height 80 +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 80, is last block: false +2025-11-14T18:25:17.458360Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=80 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 80 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 80, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 80, is last block: false +2025-11-14T18:25:17.458391Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=80 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 80 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 80, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 80, is last block: false +2025-11-14T18:25:17.458416Z  INFO ThreadId(88) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=80 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 80 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 80, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 80, is last block: false +2025-11-14T18:25:17.458518Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=80 +2025-11-14T18:25:17.458559Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 81 not found (last_processed=80, tip=80) +2025-11-14T18:25:17.458562Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 81 not found (last_processed=80, tip=80) +2025-11-14T18:25:17.458579Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 81 not found (last_processed=80, tip=80) +2025-11-14T18:25:17.458652Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 81 not found (last_processed=80, tip=80) +2025-11-14T18:25:17.522325Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:17.579444Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:149: 15 application: Handling message Propose for round Round(1, 45) (epoch 1, view 45), parent height: 43 +2025-11-14T18:25:17.630919Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:177: 15 Handling message Broadcast +2025-11-14T18:25:17.633051Z  INFO ThreadId(88) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 45) (epoch 1, view 45), parent height: 43 +2025-11-14T18:25:17.633587Z  INFO ThreadId(56) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 45) (epoch 1, view 45), parent height: 43 +2025-11-14T18:25:17.633619Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 45) (epoch 1, view 45), parent height: 43 +2025-11-14T18:25:17.636934Z  INFO ThreadId(88) summit_application::actor: application/src/actor.rs:149: 143 application: Handling message Propose for round Round(1, 46) (epoch 1, view 46), parent height: 45 +2025-11-14T18:25:17.706099Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 45) (last_processed_height=80, tip=80) +2025-11-14T18:25:17.706114Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 45) (last_processed_height=80, tip=80) +2025-11-14T18:25:17.706644Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 81 (previous tip: 80) +2025-11-14T18:25:17.706659Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 81 (last_processed_height: 80, tip: 81) +2025-11-14T18:25:17.706660Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 81 (previous tip: 80) +2025-11-14T18:25:17.706666Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 81 (last_processed_height: 80, tip: 81) +2025-11-14T18:25:17.706707Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 81)], last_processed_height: 80, tip: 81 +2025-11-14T18:25:17.706710Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:17.706712Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 81)], last_processed_height: 80, tip: 81 +2025-11-14T18:25:17.706722Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:17.706997Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 45) (last_processed_height=80, tip=80) +2025-11-14T18:25:17.707583Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 81 (previous tip: 80) +2025-11-14T18:25:17.707593Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 81 (last_processed_height: 80, tip: 81) +2025-11-14T18:25:17.707642Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 81)], last_processed_height: 80, tip: 81 +2025-11-14T18:25:17.707646Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:17.707776Z  INFO ThreadId(90) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xfe8978ce99b49f6fdf951d01688270fbbd6dd8f33b59bab11c6fda7975c675d9 for height 81 +2025-11-14T18:25:17.707778Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xfe8978ce99b49f6fdf951d01688270fbbd6dd8f33b59bab11c6fda7975c675d9 for height 81 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 81 to reth +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 81 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 81, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 81, is last block: false +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 81, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 81, is last block: false +2025-11-14T18:25:17.707940Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=81 +2025-11-14T18:25:17.707947Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=81 +2025-11-14T18:25:17.708027Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 45) (last_processed_height=80, tip=80) +2025-11-14T18:25:17.708143Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 82 not found (last_processed=81, tip=81) +2025-11-14T18:25:17.708168Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 82 not found (last_processed=81, tip=81) +2025-11-14T18:25:17.708564Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xfe8978ce99b49f6fdf951d01688270fbbd6dd8f33b59bab11c6fda7975c675d9 for height 81 +2025-11-14T18:25:17.708640Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 81 (previous tip: 80) +2025-11-14T18:25:17.708645Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 81 (last_processed_height: 80, tip: 81) +2025-11-14T18:25:17.708670Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 81)], last_processed_height: 80, tip: 81 +2025-11-14T18:25:17.708674Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 81 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 81, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 81, is last block: false +2025-11-14T18:25:17.708713Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=81 +2025-11-14T18:25:17.708858Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 82 not found (last_processed=81, tip=81) +2025-11-14T18:25:17.709400Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xfe8978ce99b49f6fdf951d01688270fbbd6dd8f33b59bab11c6fda7975c675d9 for height 81 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 81 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 81, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 81, is last block: false +2025-11-14T18:25:17.709517Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=81 +2025-11-14T18:25:17.709698Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 82 not found (last_processed=81, tip=81) +2025-11-14T18:25:17.759725Z  INFO ThreadId(89) summit_application::actor: application/src/actor.rs:177: 143 Handling message Broadcast +2025-11-14T18:25:17.773589Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:17.828779Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 46) (epoch 1, view 46), parent height: 45 +2025-11-14T18:25:17.829480Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 46) (epoch 1, view 46), parent height: 45 +2025-11-14T18:25:17.829533Z  INFO ThreadId(56) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 46) (epoch 1, view 46), parent height: 45 +2025-11-14T18:25:17.831487Z  INFO ThreadId(52) summit_application::actor: application/src/actor.rs:149: 139 application: Handling message Propose for round Round(1, 47) (epoch 1, view 47), parent height: 46 +2025-11-14T18:25:17.954859Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 46) (last_processed_height=81, tip=81) +2025-11-14T18:25:17.954958Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 46) (last_processed_height=81, tip=81) +2025-11-14T18:25:17.955417Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 82 (previous tip: 81) +2025-11-14T18:25:17.955436Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 82 (last_processed_height: 81, tip: 82) +2025-11-14T18:25:17.955479Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 82)], last_processed_height: 81, tip: 82 +2025-11-14T18:25:17.955484Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:17.955929Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 82 (previous tip: 81) +2025-11-14T18:25:17.955934Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 82 (last_processed_height: 81, tip: 82) +2025-11-14T18:25:17.955964Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 82)], last_processed_height: 81, tip: 82 +2025-11-14T18:25:17.955967Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:17.956332Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 46) (last_processed_height=81, tip=81) +2025-11-14T18:25:17.956369Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 46) (last_processed_height=81, tip=81) +2025-11-14T18:25:17.956809Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x218ac88eec814852121a4d491b2ad33c2de0afe2a16375b2b542e76e854feb90 for height 82 +2025-11-14T18:25:17.956929Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 82 (previous tip: 81) +2025-11-14T18:25:17.956932Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x218ac88eec814852121a4d491b2ad33c2de0afe2a16375b2b542e76e854feb90 for height 82 +2025-11-14T18:25:17.956935Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 82 (last_processed_height: 81, tip: 82) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 82 to reth +2025-11-14T18:25:17.956974Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 82)], last_processed_height: 81, tip: 82 +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 82, is penultimate block: false +2025-11-14T18:25:17.956976Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 82, is last block: false +2025-11-14T18:25:17.956982Z  INFO ThreadId(89) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=82 +2025-11-14T18:25:17.957000Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 82 (previous tip: 81) +2025-11-14T18:25:17.957006Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 82 (last_processed_height: 81, tip: 82) +2025-11-14T18:25:17.957046Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 82)], last_processed_height: 81, tip: 82 +2025-11-14T18:25:17.957049Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 82 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 82, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 82, is last block: false +2025-11-14T18:25:17.957076Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=82 +2025-11-14T18:25:17.957155Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 83 not found (last_processed=82, tip=82) +2025-11-14T18:25:17.957221Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 83 not found (last_processed=82, tip=82) +2025-11-14T18:25:17.957914Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x218ac88eec814852121a4d491b2ad33c2de0afe2a16375b2b542e76e854feb90 for height 82 +2025-11-14T18:25:17.957963Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x218ac88eec814852121a4d491b2ad33c2de0afe2a16375b2b542e76e854feb90 for height 82 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 82 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 82, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 82, is last block: false +2025-11-14T18:25:17.958042Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=82 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 82 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 82, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 82, is last block: false +2025-11-14T18:25:17.958092Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=82 +2025-11-14T18:25:17.958198Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 83 not found (last_processed=82, tip=82) +2025-11-14T18:25:17.958219Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 83 not found (last_processed=82, tip=82) +2025-11-14T18:25:18.010012Z  INFO ThreadId(49) summit_application::actor: application/src/actor.rs:177: 139 Handling message Broadcast +2025-11-14T18:25:18.013280Z  INFO ThreadId(89) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 47) (epoch 1, view 47), parent height: 46 +2025-11-14T18:25:18.013301Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 47) (epoch 1, view 47), parent height: 46 +2025-11-14T18:25:18.013315Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 47) (epoch 1, view 47), parent height: 46 +2025-11-14T18:25:18.015702Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:149: 55 application: Handling message Propose for round Round(1, 48) (epoch 1, view 48), parent height: 47 +2025-11-14T18:25:18.024490Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:18.081568Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 47) (last_processed_height=82, tip=82) +2025-11-14T18:25:18.081575Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 47) (last_processed_height=82, tip=82) +2025-11-14T18:25:18.081594Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 47) (last_processed_height=82, tip=82) +2025-11-14T18:25:18.082093Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 83 (previous tip: 82) +2025-11-14T18:25:18.082106Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 83 (last_processed_height: 82, tip: 83) +2025-11-14T18:25:18.082174Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 83)], last_processed_height: 82, tip: 83 +2025-11-14T18:25:18.082181Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:18.082336Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 83 (previous tip: 82) +2025-11-14T18:25:18.082346Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 83 (last_processed_height: 82, tip: 83) +2025-11-14T18:25:18.082351Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 83 (previous tip: 82) +2025-11-14T18:25:18.082362Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 83 (last_processed_height: 82, tip: 83) +2025-11-14T18:25:18.082379Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 83)], last_processed_height: 82, tip: 83 +2025-11-14T18:25:18.082385Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:18.082438Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 83)], last_processed_height: 82, tip: 83 +2025-11-14T18:25:18.082444Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:18.083302Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 47) (last_processed_height=82, tip=82) +2025-11-14T18:25:18.083519Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xf87c1b48d36a96c535498b4b935a01be2c83a59841ad862f72d9c316d474e0eb for height 83 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 83 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 83, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 83, is last block: false +2025-11-14T18:25:18.083729Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=83 +2025-11-14T18:25:18.083747Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xf87c1b48d36a96c535498b4b935a01be2c83a59841ad862f72d9c316d474e0eb for height 83 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 83 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 83, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 83, is last block: false +2025-11-14T18:25:18.083889Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=83 +2025-11-14T18:25:18.083892Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 84 not found (last_processed=83, tip=83) +2025-11-14T18:25:18.084023Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 84 not found (last_processed=83, tip=83) +2025-11-14T18:25:18.084044Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 83 (previous tip: 82) +2025-11-14T18:25:18.084051Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 83 (last_processed_height: 82, tip: 83) +2025-11-14T18:25:18.084079Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 83)], last_processed_height: 82, tip: 83 +2025-11-14T18:25:18.084082Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:18.084205Z  INFO ThreadId(89) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xf87c1b48d36a96c535498b4b935a01be2c83a59841ad862f72d9c316d474e0eb for height 83 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 83 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 83, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 83, is last block: false +2025-11-14T18:25:18.084333Z  INFO ThreadId(89) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=83 +2025-11-14T18:25:18.084483Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 84 not found (last_processed=83, tip=83) +2025-11-14T18:25:18.084891Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xf87c1b48d36a96c535498b4b935a01be2c83a59841ad862f72d9c316d474e0eb for height 83 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 83 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 83, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 83, is last block: false +2025-11-14T18:25:18.085007Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=83 +2025-11-14T18:25:18.085121Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 84 not found (last_processed=83, tip=83) +2025-11-14T18:25:18.135959Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:177: 55 Handling message Broadcast +2025-11-14T18:25:18.205173Z  INFO ThreadId(90) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 48) (epoch 1, view 48), parent height: 47 +2025-11-14T18:25:18.205444Z  INFO ThreadId(43) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 48) (epoch 1, view 48), parent height: 47 +2025-11-14T18:25:18.205468Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 48) (epoch 1, view 48), parent height: 47 +2025-11-14T18:25:18.276232Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:18.330001Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 48) (last_processed_height=83, tip=83) +2025-11-14T18:25:18.330122Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 48) (last_processed_height=83, tip=83) +2025-11-14T18:25:18.330151Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:149: 15 application: Handling message Propose for round Round(1, 50) (epoch 1, view 50), parent height: 48 +2025-11-14T18:25:18.330616Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 48) (last_processed_height=83, tip=83) +2025-11-14T18:25:18.330845Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 84 (previous tip: 83) +2025-11-14T18:25:18.330859Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 84 (last_processed_height: 83, tip: 84) +2025-11-14T18:25:18.330922Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 84)], last_processed_height: 83, tip: 84 +2025-11-14T18:25:18.330929Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:18.331061Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 48) (last_processed_height=83, tip=83) +2025-11-14T18:25:18.331059Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 84 (previous tip: 83) +2025-11-14T18:25:18.331072Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 84 (last_processed_height: 83, tip: 84) +2025-11-14T18:25:18.331135Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 84)], last_processed_height: 83, tip: 84 +2025-11-14T18:25:18.331142Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:18.331185Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 84 (previous tip: 83) +2025-11-14T18:25:18.331197Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 84 (last_processed_height: 83, tip: 84) +2025-11-14T18:25:18.331268Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 84)], last_processed_height: 83, tip: 84 +2025-11-14T18:25:18.331273Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:18.331801Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 84 (previous tip: 83) +2025-11-14T18:25:18.331810Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 84 (last_processed_height: 83, tip: 84) +2025-11-14T18:25:18.331849Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 84)], last_processed_height: 83, tip: 84 +2025-11-14T18:25:18.331853Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:18.332289Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7b7c63a28bdc59b68aa682ff083ff4b7b3dce83cb25fbef651e17a784647c252 for height 84 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 84 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 84, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 84, is last block: false +2025-11-14T18:25:18.332500Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=84 +2025-11-14T18:25:18.332509Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7b7c63a28bdc59b68aa682ff083ff4b7b3dce83cb25fbef651e17a784647c252 for height 84 +2025-11-14T18:25:18.332512Z  INFO ThreadId(88) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7b7c63a28bdc59b68aa682ff083ff4b7b3dce83cb25fbef651e17a784647c252 for height 84 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 84 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 84, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 84, is last block: false +2025-11-14T18:25:18.332671Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=84 +2025-11-14T18:25:18.332899Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7b7c63a28bdc59b68aa682ff083ff4b7b3dce83cb25fbef651e17a784647c252 for height 84 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 84 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 84, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 84, is last block: false +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 84 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +2025-11-14T18:25:18.333040Z  INFO ThreadId(88) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=84 +epoch_num_of_blocks: 50, new_height: 84, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 84, is last block: false +2025-11-14T18:25:18.333049Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=84 +2025-11-14T18:25:18.333120Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 85 not found (last_processed=84, tip=84) +2025-11-14T18:25:18.333163Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 85 not found (last_processed=84, tip=84) +2025-11-14T18:25:18.333232Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 85 not found (last_processed=84, tip=84) +2025-11-14T18:25:18.333286Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 85 not found (last_processed=84, tip=84) +2025-11-14T18:25:18.384847Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:177: 15 Handling message Broadcast +2025-11-14T18:25:18.456219Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 50) (epoch 1, view 50), parent height: 48 +2025-11-14T18:25:18.457586Z  INFO ThreadId(89) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 50) (epoch 1, view 50), parent height: 48 +2025-11-14T18:25:18.457594Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 50) (epoch 1, view 50), parent height: 48 +2025-11-14T18:25:18.462421Z  INFO ThreadId(89) summit_application::actor: application/src/actor.rs:149: 143 application: Handling message Propose for round Round(1, 51) (epoch 1, view 51), parent height: 50 +2025-11-14T18:25:18.529055Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:18.578886Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 50) (last_processed_height=84, tip=84) +2025-11-14T18:25:18.578939Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 50) (last_processed_height=84, tip=84) +2025-11-14T18:25:18.579319Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 50) (last_processed_height=84, tip=84) +2025-11-14T18:25:18.579398Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 50) (last_processed_height=84, tip=84) +2025-11-14T18:25:18.579710Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 85 (previous tip: 84) +2025-11-14T18:25:18.579717Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 85 (last_processed_height: 84, tip: 85) +2025-11-14T18:25:18.579777Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 85)], last_processed_height: 84, tip: 85 +2025-11-14T18:25:18.579781Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:18.579993Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 85 (previous tip: 84) +2025-11-14T18:25:18.579998Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 85 (last_processed_height: 84, tip: 85) +2025-11-14T18:25:18.580027Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 85)], last_processed_height: 84, tip: 85 +2025-11-14T18:25:18.580029Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:18.580152Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 85 (previous tip: 84) +2025-11-14T18:25:18.580159Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 85 (last_processed_height: 84, tip: 85) +2025-11-14T18:25:18.580159Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 85 (previous tip: 84) +2025-11-14T18:25:18.580165Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 85 (last_processed_height: 84, tip: 85) +2025-11-14T18:25:18.580191Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 85)], last_processed_height: 84, tip: 85 +2025-11-14T18:25:18.580194Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:18.580196Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 85)], last_processed_height: 84, tip: 85 +2025-11-14T18:25:18.580199Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:18.581056Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x6b64c354de716c66ce7a5bed65efa7326b5b14ba3e5cb38d383cbe4ea3ca008c for height 85 +2025-11-14T18:25:18.581215Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x6b64c354de716c66ce7a5bed65efa7326b5b14ba3e5cb38d383cbe4ea3ca008c for height 85 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 85 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 85, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 85, is last block: false +2025-11-14T18:25:18.581275Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=85 +2025-11-14T18:25:18.581313Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x6b64c354de716c66ce7a5bed65efa7326b5b14ba3e5cb38d383cbe4ea3ca008c for height 85 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 85 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 85, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 85, is last block: false +2025-11-14T18:25:18.581380Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=85 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 85 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 85, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 85, is last block: false +2025-11-14T18:25:18.581468Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=85 +2025-11-14T18:25:18.581493Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 86 not found (last_processed=85, tip=85) +2025-11-14T18:25:18.581532Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 86 not found (last_processed=85, tip=85) +2025-11-14T18:25:18.581640Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 86 not found (last_processed=85, tip=85) +2025-11-14T18:25:18.581680Z  INFO ThreadId(90) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x6b64c354de716c66ce7a5bed65efa7326b5b14ba3e5cb38d383cbe4ea3ca008c for height 85 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 85 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 85, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 85, is last block: false +2025-11-14T18:25:18.581796Z  INFO ThreadId(90) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=85 +2025-11-14T18:25:18.581936Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 86 not found (last_processed=85, tip=85) +2025-11-14T18:25:18.633605Z  INFO ThreadId(89) summit_application::actor: application/src/actor.rs:177: 143 Handling message Broadcast +2025-11-14T18:25:18.635846Z  INFO ThreadId(43) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 51) (epoch 1, view 51), parent height: 50 +2025-11-14T18:25:18.635956Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 51) (epoch 1, view 51), parent height: 50 +2025-11-14T18:25:18.636017Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 51) (epoch 1, view 51), parent height: 50 +2025-11-14T18:25:18.637831Z  INFO ThreadId(49) summit_application::actor: application/src/actor.rs:149: 139 application: Handling message Propose for round Round(1, 52) (epoch 1, view 52), parent height: 51 +2025-11-14T18:25:18.705808Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 51) (last_processed_height=85, tip=85) +2025-11-14T18:25:18.705856Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 51) (last_processed_height=85, tip=85) +2025-11-14T18:25:18.705872Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 51) (last_processed_height=85, tip=85) +2025-11-14T18:25:18.706427Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 86 (previous tip: 85) +2025-11-14T18:25:18.706435Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 86 (last_processed_height: 85, tip: 86) +2025-11-14T18:25:18.706488Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 86 (previous tip: 85) +2025-11-14T18:25:18.706492Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 86 (last_processed_height: 85, tip: 86) +2025-11-14T18:25:18.706492Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 86)], last_processed_height: 85, tip: 86 +2025-11-14T18:25:18.706497Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:18.706528Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 86)], last_processed_height: 85, tip: 86 +2025-11-14T18:25:18.706532Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:18.706531Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 86 (previous tip: 85) +2025-11-14T18:25:18.706537Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 86 (last_processed_height: 85, tip: 86) +2025-11-14T18:25:18.706566Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 86)], last_processed_height: 85, tip: 86 +2025-11-14T18:25:18.706569Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:18.706809Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 51) (last_processed_height=85, tip=85) +2025-11-14T18:25:18.707366Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 86 (previous tip: 85) +2025-11-14T18:25:18.707373Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 86 (last_processed_height: 85, tip: 86) +2025-11-14T18:25:18.707403Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 86)], last_processed_height: 85, tip: 86 +2025-11-14T18:25:18.707408Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:18.707648Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd467133b0a7a7c78f00adf0a1da4aaeeadff7aaca358d63e045723e69efe721d for height 86 +2025-11-14T18:25:18.707648Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd467133b0a7a7c78f00adf0a1da4aaeeadff7aaca358d63e045723e69efe721d for height 86 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 86 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 86, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 86, is last block: false +2025-11-14T18:25:18.707833Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=86 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 86 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 86, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 86, is last block: false +2025-11-14T18:25:18.707854Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=86 +2025-11-14T18:25:18.707948Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd467133b0a7a7c78f00adf0a1da4aaeeadff7aaca358d63e045723e69efe721d for height 86 +2025-11-14T18:25:18.707990Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 87 not found (last_processed=86, tip=86) +2025-11-14T18:25:18.708045Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 87 not found (last_processed=86, tip=86) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 86 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 86, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 86, is last block: false +2025-11-14T18:25:18.708115Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=86 +2025-11-14T18:25:18.708299Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 87 not found (last_processed=86, tip=86) +2025-11-14T18:25:18.708465Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd467133b0a7a7c78f00adf0a1da4aaeeadff7aaca358d63e045723e69efe721d for height 86 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 86 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 86, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 86, is last block: false +2025-11-14T18:25:18.708588Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=86 +2025-11-14T18:25:18.708730Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 87 not found (last_processed=86, tip=86) +2025-11-14T18:25:18.759761Z  INFO ThreadId(49) summit_application::actor: application/src/actor.rs:177: 139 Handling message Broadcast +2025-11-14T18:25:18.781800Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:18.829260Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 52) (epoch 1, view 52), parent height: 51 +2025-11-14T18:25:18.829935Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 52) (epoch 1, view 52), parent height: 51 +2025-11-14T18:25:18.829994Z  INFO ThreadId(91) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 52) (epoch 1, view 52), parent height: 51 +2025-11-14T18:25:18.831902Z  INFO ThreadId(57) summit_application::actor: application/src/actor.rs:149: 55 application: Handling message Propose for round Round(1, 53) (epoch 1, view 53), parent height: 52 +2025-11-14T18:25:18.954275Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 52) (last_processed_height=86, tip=86) +2025-11-14T18:25:18.954436Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 52) (last_processed_height=86, tip=86) +2025-11-14T18:25:18.955217Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 52) (last_processed_height=86, tip=86) +2025-11-14T18:25:18.955352Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 87 (previous tip: 86) +2025-11-14T18:25:18.955364Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 87 (last_processed_height: 86, tip: 87) +2025-11-14T18:25:18.955434Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 87)], last_processed_height: 86, tip: 87 +2025-11-14T18:25:18.955440Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:18.955516Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 87 (previous tip: 86) +2025-11-14T18:25:18.955521Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 87 (last_processed_height: 86, tip: 87) +2025-11-14T18:25:18.955552Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 52) (last_processed_height=86, tip=86) +2025-11-14T18:25:18.955560Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 87)], last_processed_height: 86, tip: 87 +2025-11-14T18:25:18.955562Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:18.955692Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 87 (previous tip: 86) +2025-11-14T18:25:18.955697Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 87 (last_processed_height: 86, tip: 87) +2025-11-14T18:25:18.955743Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 87)], last_processed_height: 86, tip: 87 +2025-11-14T18:25:18.955746Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:18.956099Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 87 (previous tip: 86) +2025-11-14T18:25:18.956106Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 87 (last_processed_height: 86, tip: 87) +2025-11-14T18:25:18.956138Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 87)], last_processed_height: 86, tip: 87 +2025-11-14T18:25:18.956141Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:18.956679Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x116780593f190015fab3a4841b41c3d1f1147aad94b052629ed53fd9e64f8319 for height 87 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 87 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 87, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 87, is last block: false +2025-11-14T18:25:18.956856Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=87 +2025-11-14T18:25:18.956984Z  INFO ThreadId(90) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x116780593f190015fab3a4841b41c3d1f1147aad94b052629ed53fd9e64f8319 for height 87 +2025-11-14T18:25:18.957026Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 88 not found (last_processed=87, tip=87) +2025-11-14T18:25:18.957031Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x116780593f190015fab3a4841b41c3d1f1147aad94b052629ed53fd9e64f8319 for height 87 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 87 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 87, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 87, is last block: false +2025-11-14T18:25:18.957166Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=87 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 87 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 87, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 87, is last block: false +2025-11-14T18:25:18.957322Z  INFO ThreadId(90) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=87 +2025-11-14T18:25:18.957324Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 88 not found (last_processed=87, tip=87) +2025-11-14T18:25:18.957398Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x116780593f190015fab3a4841b41c3d1f1147aad94b052629ed53fd9e64f8319 for height 87 +2025-11-14T18:25:18.957482Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 88 not found (last_processed=87, tip=87) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 87 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 87, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 87, is last block: false +2025-11-14T18:25:18.957533Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=87 +2025-11-14T18:25:18.957691Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 88 not found (last_processed=87, tip=87) +2025-11-14T18:25:19.009465Z  INFO ThreadId(57) summit_application::actor: application/src/actor.rs:177: 55 Handling message Broadcast +2025-11-14T18:25:19.012618Z  INFO ThreadId(43) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 53) (epoch 1, view 53), parent height: 52 +2025-11-14T18:25:19.012637Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 53) (epoch 1, view 53), parent height: 52 +2025-11-14T18:25:19.012975Z  INFO ThreadId(90) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 53) (epoch 1, view 53), parent height: 52 +2025-11-14T18:25:19.034438Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:19.081272Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 53) (last_processed_height=87, tip=87) +2025-11-14T18:25:19.081323Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 53) (last_processed_height=87, tip=87) +2025-11-14T18:25:19.081518Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 53) (last_processed_height=87, tip=87) +2025-11-14T18:25:19.081780Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 88 (previous tip: 87) +2025-11-14T18:25:19.081786Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 88 (last_processed_height: 87, tip: 88) +2025-11-14T18:25:19.081823Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 88)], last_processed_height: 87, tip: 88 +2025-11-14T18:25:19.081827Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:19.081877Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 88 (previous tip: 87) +2025-11-14T18:25:19.081884Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 88 (last_processed_height: 87, tip: 88) +2025-11-14T18:25:19.081913Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 88)], last_processed_height: 87, tip: 88 +2025-11-14T18:25:19.081916Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:19.082013Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 88 (previous tip: 87) +2025-11-14T18:25:19.082019Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 88 (last_processed_height: 87, tip: 88) +2025-11-14T18:25:19.082039Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 53) (last_processed_height=87, tip=87) +2025-11-14T18:25:19.082047Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 88)], last_processed_height: 87, tip: 88 +2025-11-14T18:25:19.082049Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:19.082635Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 88 (previous tip: 87) +2025-11-14T18:25:19.082645Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 88 (last_processed_height: 87, tip: 88) +2025-11-14T18:25:19.082697Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 88)], last_processed_height: 87, tip: 88 +2025-11-14T18:25:19.082702Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:19.083041Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x4c5519124bd51287b3dfe7bd6a220601fb1d75a1b4cebabc7e334e2d587df539 for height 88 +2025-11-14T18:25:19.083093Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x4c5519124bd51287b3dfe7bd6a220601fb1d75a1b4cebabc7e334e2d587df539 for height 88 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 88 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 88, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 88, is last block: false +2025-11-14T18:25:19.083254Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x4c5519124bd51287b3dfe7bd6a220601fb1d75a1b4cebabc7e334e2d587df539 for height 88 +2025-11-14T18:25:19.083254Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=88 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 88 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 88, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 88, is last block: false +2025-11-14T18:25:19.083303Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=88 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 88 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 88, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 88, is last block: false +2025-11-14T18:25:19.083418Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=88 +2025-11-14T18:25:19.083441Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 89 not found (last_processed=88, tip=88) +2025-11-14T18:25:19.083516Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 89 not found (last_processed=88, tip=88) +2025-11-14T18:25:19.083618Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 89 not found (last_processed=88, tip=88) +2025-11-14T18:25:19.083676Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x4c5519124bd51287b3dfe7bd6a220601fb1d75a1b4cebabc7e334e2d587df539 for height 88 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 88 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 88, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 88, is last block: false +2025-11-14T18:25:19.083800Z  INFO ThreadId(88) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=88 +2025-11-14T18:25:19.083927Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 89 not found (last_processed=88, tip=88) +2025-11-14T18:25:19.204292Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:149: 15 application: Handling message Propose for round Round(1, 55) (epoch 1, view 55), parent height: 53 +2025-11-14T18:25:19.255817Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:177: 15 Handling message Broadcast +2025-11-14T18:25:19.258295Z  INFO ThreadId(88) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 55) (epoch 1, view 55), parent height: 53 +2025-11-14T18:25:19.258639Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 55) (epoch 1, view 55), parent height: 53 +2025-11-14T18:25:19.258722Z  INFO ThreadId(57) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 55) (epoch 1, view 55), parent height: 53 +2025-11-14T18:25:19.262253Z  INFO ThreadId(89) summit_application::actor: application/src/actor.rs:149: 143 application: Handling message Propose for round Round(1, 56) (epoch 1, view 56), parent height: 55 +2025-11-14T18:25:19.285794Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +Node 1 at height 88 +Node 2 at height 88 +Node 3 at height 88 +2025-11-14T18:25:19.330604Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 55) (last_processed_height=88, tip=88) +2025-11-14T18:25:19.330707Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 55) (last_processed_height=88, tip=88) +2025-11-14T18:25:19.331282Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 89 (previous tip: 88) +2025-11-14T18:25:19.331288Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 89 (last_processed_height: 88, tip: 89) +2025-11-14T18:25:19.331323Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 89)], last_processed_height: 88, tip: 89 +2025-11-14T18:25:19.331326Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:19.331439Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 89 (previous tip: 88) +2025-11-14T18:25:19.331445Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 89 (last_processed_height: 88, tip: 89) +2025-11-14T18:25:19.331474Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 89)], last_processed_height: 88, tip: 89 +2025-11-14T18:25:19.331478Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:19.331825Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 55) (last_processed_height=88, tip=88) +2025-11-14T18:25:19.331984Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 55) (last_processed_height=88, tip=88) +2025-11-14T18:25:19.332511Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 89 (previous tip: 88) +2025-11-14T18:25:19.332518Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 89 (last_processed_height: 88, tip: 89) +2025-11-14T18:25:19.332531Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x68a206954277c95c435cbb18a9e6b360ec0e05bed3f37213a7f3ffa8d2a9d2a5 for height 89 +2025-11-14T18:25:19.332552Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 89)], last_processed_height: 88, tip: 89 +2025-11-14T18:25:19.332555Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:19.332656Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x68a206954277c95c435cbb18a9e6b360ec0e05bed3f37213a7f3ffa8d2a9d2a5 for height 89 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 89 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +üüüüüüüüüüüüüüüüüüüüüüüüü +epoch_num_of_blocks: 50, new_height: 89, is penultimate block: false +COMMITING BLOCK 89 to reth +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 89, is last block: false +epoch_num_of_blocks: 50, new_height: 89, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 89, is last block: false +2025-11-14T18:25:19.332794Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=89 +2025-11-14T18:25:19.332796Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=89 +2025-11-14T18:25:19.332831Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 89 (previous tip: 88) +2025-11-14T18:25:19.332836Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 89 (last_processed_height: 88, tip: 89) +2025-11-14T18:25:19.332874Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 89)], last_processed_height: 88, tip: 89 +2025-11-14T18:25:19.332877Z  INFO ThreadId(50) summit_syncer::actor:[0m syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:19.332936Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 90 not found (last_processed=89, tip=89) +2025-11-14T18:25:19.332936Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 90 not found (last_processed=89, tip=89) +2025-11-14T18:25:19.333544Z  INFO ThreadId(88) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x68a206954277c95c435cbb18a9e6b360ec0e05bed3f37213a7f3ffa8d2a9d2a5 for height 89 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 89 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 89, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 89, is last block: false +2025-11-14T18:25:19.333724Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=89 +2025-11-14T18:25:19.333930Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x68a206954277c95c435cbb18a9e6b360ec0e05bed3f37213a7f3ffa8d2a9d2a5 for height 89 +2025-11-14T18:25:19.333948Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 90 not found (last_processed=89, tip=89) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 89 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 89, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 89, is last block: false +2025-11-14T18:25:19.334067Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=89 +2025-11-14T18:25:19.334200Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 90 not found (last_processed=89, tip=89) +Node 4 at height 89 +2025-11-14T18:25:19.386143Z  INFO ThreadId(88) summit_application::actor: application/src/actor.rs:177: 143 Handling message Broadcast +2025-11-14T18:25:19.454242Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 56) (epoch 1, view 56), parent height: 55 +2025-11-14T18:25:19.454331Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 56) (epoch 1, view 56), parent height: 55 +2025-11-14T18:25:19.454404Z  INFO ThreadId(56) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 56) (epoch 1, view 56), parent height: 55 +2025-11-14T18:25:19.460541Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:149: 139 application: Handling message Propose for round Round(1, 57) (epoch 1, view 57), parent height: 56 +2025-11-14T18:25:19.537916Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:19.579461Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 56) (last_processed_height=89, tip=89) +2025-11-14T18:25:19.580113Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 90 (previous tip: 89) +2025-11-14T18:25:19.580120Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 90 (last_processed_height: 89, tip: 90) +2025-11-14T18:25:19.580161Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 90)], last_processed_height: 89, tip: 90 +2025-11-14T18:25:19.580164Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:19.580807Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 56) (last_processed_height=89, tip=89) +2025-11-14T18:25:19.581149Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 56) (last_processed_height=89, tip=89) +2025-11-14T18:25:19.581230Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 56) (last_processed_height=89, tip=89) +2025-11-14T18:25:19.581358Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd23ab71e4d424197d49ea968a37286ef6ec213395b8f47cf3daec13e8169387e for height 90 +2025-11-14T18:25:19.581364Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 90 (previous tip: 89) +2025-11-14T18:25:19.581370Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 90 (last_processed_height: 89, tip: 90) +2025-11-14T18:25:19.581431Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 90)], last_processed_height: 89, tip: 90 +2025-11-14T18:25:19.581437Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 90 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 90, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 90, is last block: false +2025-11-14T18:25:19.581545Z  INFO ThreadId(88) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=90 +2025-11-14T18:25:19.581703Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 90 (previous tip: 89) +2025-11-14T18:25:19.581709Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 90 (last_processed_height: 89, tip: 90) +2025-11-14T18:25:19.581731Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 91 not found (last_processed=90, tip=90) +2025-11-14T18:25:19.581745Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 90)], last_processed_height: 89, tip: 90 +2025-11-14T18:25:19.581747Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:19.581835Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 90 (previous tip: 89) +2025-11-14T18:25:19.581841Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 90 (last_processed_height: 89, tip: 90) +2025-11-14T18:25:19.581876Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 90)], last_processed_height: 89, tip: 90 +2025-11-14T18:25:19.581881Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:19.582438Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd23ab71e4d424197d49ea968a37286ef6ec213395b8f47cf3daec13e8169387e for height 90 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 90 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 90, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 90, is last block: false +2025-11-14T18:25:19.582599Z  INFO ThreadId(52) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=90 +2025-11-14T18:25:19.582771Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 91 not found (last_processed=90, tip=90) +2025-11-14T18:25:19.582893Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd23ab71e4d424197d49ea968a37286ef6ec213395b8f47cf3daec13e8169387e for height 90 +2025-11-14T18:25:19.582896Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd23ab71e4d424197d49ea968a37286ef6ec213395b8f47cf3daec13e8169387e for height 90 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 90 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 90, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 90, is last block: false +2025-11-14T18:25:19.583032Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=90 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 90 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 90, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 90, is last block: false +2025-11-14T18:25:19.583047Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=90 +2025-11-14T18:25:19.583180Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 91 not found (last_processed=90, tip=90) +2025-11-14T18:25:19.583186Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 91 not found (last_processed=90, tip=90) +2025-11-14T18:25:19.634760Z  INFO ThreadId(52) summit_application::actor: application/src/actor.rs:177: 139 Handling message Broadcast +2025-11-14T18:25:19.636892Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 57) (epoch 1, view 57), parent height: 56 +2025-11-14T18:25:19.636893Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 57) (epoch 1, view 57), parent height: 56 +2025-11-14T18:25:19.636917Z  INFO ThreadId(91) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 57) (epoch 1, view 57), parent height: 56 +2025-11-14T18:25:19.640544Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:149: 55 application: Handling message Propose for round Round(1, 58) (epoch 1, view 58), parent height: 57 +2025-11-14T18:25:19.706408Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 57) (last_processed_height=90, tip=90) +2025-11-14T18:25:19.706418Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 57) (last_processed_height=90, tip=90) +2025-11-14T18:25:19.706419Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 57) (last_processed_height=90, tip=90) +2025-11-14T18:25:19.706433Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 57) (last_processed_height=90, tip=90) +2025-11-14T18:25:19.706992Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 91 (previous tip: 90) +2025-11-14T18:25:19.706994Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 91 (previous tip: 90) +2025-11-14T18:25:19.706998Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 91 (last_processed_height: 90, tip: 91) +2025-11-14T18:25:19.706999Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 91 (last_processed_height: 90, tip: 91) +2025-11-14T18:25:19.707037Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 91)], last_processed_height: 90, tip: 91 +2025-11-14T18:25:19.707037Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 91)], last_processed_height: 90, tip: 91 +2025-11-14T18:25:19.707040Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:19.707041Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:19.707077Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 91 (previous tip: 90) +2025-11-14T18:25:19.707081Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 91 (last_processed_height: 90, tip: 91) +2025-11-14T18:25:19.707103Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 91)], last_processed_height: 90, tip: 91 +2025-11-14T18:25:19.707105Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:19.707281Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 91 (previous tip: 90) +2025-11-14T18:25:19.707293Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 91 (last_processed_height: 90, tip: 91) +2025-11-14T18:25:19.707347Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 91)], last_processed_height: 90, tip: 91 +2025-11-14T18:25:19.707352Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:19.708227Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7bbde5df16887a62b0ae037a2117f2a3041ef146fcb935774a1c7b91a6a2f5c5 for height 91 +2025-11-14T18:25:19.708409Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7bbde5df16887a62b0ae037a2117f2a3041ef146fcb935774a1c7b91a6a2f5c5 for height 91 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 91 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 91, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 91, is last block: false +2025-11-14T18:25:19.708446Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=91 +2025-11-14T18:25:19.708527Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7bbde5df16887a62b0ae037a2117f2a3041ef146fcb935774a1c7b91a6a2f5c5 for height 91 +2025-11-14T18:25:19.708665Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 92 not found (last_processed=91, tip=91) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 91 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 91, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 91, is last block: false +2025-11-14T18:25:19.708680Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=91 +2025-11-14T18:25:19.708687Z  INFO ThreadId(88) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7bbde5df16887a62b0ae037a2117f2a3041ef146fcb935774a1c7b91a6a2f5c5 for height 91 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 91 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 91, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 91, is last block: false +2025-11-14T18:25:19.708772Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=91 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 91 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 91, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 91, is last block: false +2025-11-14T18:25:19.708862Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=91 +2025-11-14T18:25:19.708865Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 92 not found (last_processed=91, tip=91) +2025-11-14T18:25:19.708912Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 92 not found (last_processed=91, tip=91) +2025-11-14T18:25:19.709036Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 92 not found (last_processed=91, tip=91) +2025-11-14T18:25:19.760538Z  INFO ThreadId(57) summit_application::actor: application/src/actor.rs:177: 55 Handling message Broadcast +2025-11-14T18:25:19.790467Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:19.830243Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 58) (epoch 1, view 58), parent height: 57 +2025-11-14T18:25:19.830683Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 58) (epoch 1, view 58), parent height: 57 +2025-11-14T18:25:19.830943Z  INFO ThreadId(91) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 58) (epoch 1, view 58), parent height: 57 +2025-11-14T18:25:19.955238Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 58) (last_processed_height=91, tip=91) +2025-11-14T18:25:19.955296Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 58) (last_processed_height=91, tip=91) +2025-11-14T18:25:19.955465Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 58) (last_processed_height=91, tip=91) +2025-11-14T18:25:19.955487Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:149: 15 application: Handling message Propose for round Round(1, 60) (epoch 1, view 60), parent height: 58 +2025-11-14T18:25:19.956005Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 92 (previous tip: 91) +2025-11-14T18:25:19.956011Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 92 (last_processed_height: 91, tip: 92) +2025-11-14T18:25:19.956044Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 92)], last_processed_height: 91, tip: 92 +2025-11-14T18:25:19.956048Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:19.956259Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 92 (previous tip: 91) +2025-11-14T18:25:19.956273Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 92 (last_processed_height: 91, tip: 92) +2025-11-14T18:25:19.956280Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 92 (previous tip: 91) +2025-11-14T18:25:19.956285Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 92 (last_processed_height: 91, tip: 92) +2025-11-14T18:25:19.956292Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 58) (last_processed_height=91, tip=91) +2025-11-14T18:25:19.956309Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 92)], last_processed_height: 91, tip: 92 +2025-11-14T18:25:19.956311Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:19.956322Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 92)], last_processed_height: 91, tip: 92 +2025-11-14T18:25:19.956326Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:19.956927Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 92 (previous tip: 91) +2025-11-14T18:25:19.956937Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 92 (last_processed_height: 91, tip: 92) +2025-11-14T18:25:19.957008Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 92)], last_processed_height: 91, tip: 92 +2025-11-14T18:25:19.957033Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:19.957244Z  INFO ThreadId(90) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd41be32fab12a7df5017b23dccc7d630fead9cc0abae9ff477ac294caf7766a9 for height 92 +2025-11-14T18:25:19.957327Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd41be32fab12a7df5017b23dccc7d630fead9cc0abae9ff477ac294caf7766a9 for height 92 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 92 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 92, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 92, is last block: false +2025-11-14T18:25:19.957404Z  INFO ThreadId(89) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=92 +2025-11-14T18:25:19.957466Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd41be32fab12a7df5017b23dccc7d630fead9cc0abae9ff477ac294caf7766a9 for height 92 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 92 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 92, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 92, is last block: false +2025-11-14T18:25:19.957498Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=92 +2025-11-14T18:25:19.957574Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 93 not found (last_processed=92, tip=92) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 92 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 92, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 92, is last block: false +2025-11-14T18:25:19.957646Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=92 +2025-11-14T18:25:19.957717Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 93 not found (last_processed=92, tip=92) +2025-11-14T18:25:19.957813Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 93 not found (last_processed=92, tip=92) +2025-11-14T18:25:19.958067Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd41be32fab12a7df5017b23dccc7d630fead9cc0abae9ff477ac294caf7766a9 for height 92 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 92 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 92, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 92, is last block: false +2025-11-14T18:25:19.958193Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=92 +2025-11-14T18:25:19.958336Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 93 not found (last_processed=92, tip=92) +2025-11-14T18:25:20.009597Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:177: 15 Handling message Broadcast +2025-11-14T18:25:20.041776Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:20.081236Z  INFO ThreadId(90) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 60) (epoch 1, view 60), parent height: 58 +2025-11-14T18:25:20.081484Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 60) (epoch 1, view 60), parent height: 58 +2025-11-14T18:25:20.081697Z  INFO ThreadId(57) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 60) (epoch 1, view 60), parent height: 58 +2025-11-14T18:25:20.083466Z  INFO ThreadId(90) summit_application::actor: application/src/actor.rs:149: 143 application: Handling message Propose for round Round(1, 61) (epoch 1, view 61), parent height: 60 +2025-11-14T18:25:20.204187Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 60) (last_processed_height=92, tip=92) +2025-11-14T18:25:20.204296Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 60) (last_processed_height=92, tip=92) +2025-11-14T18:25:20.204475Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 60) (last_processed_height=92, tip=92) +2025-11-14T18:25:20.204655Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 60) (last_processed_height=92, tip=92) +2025-11-14T18:25:20.205217Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 93 (previous tip: 92) +2025-11-14T18:25:20.205228Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 93 (last_processed_height: 92, tip: 93) +2025-11-14T18:25:20.205332Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 93)], last_processed_height: 92, tip: 93 +2025-11-14T18:25:20.205340Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:20.205601Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 93 (previous tip: 92) +2025-11-14T18:25:20.205611Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 93 (last_processed_height: 92, tip: 93) +2025-11-14T18:25:20.205685Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 93)], last_processed_height: 92, tip: 93 +2025-11-14T18:25:20.205692Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:20.205712Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 93 (previous tip: 92) +2025-11-14T18:25:20.205718Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 93 (last_processed_height: 92, tip: 93) +2025-11-14T18:25:20.205764Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 93)], last_processed_height: 92, tip: 93 +2025-11-14T18:25:20.205769Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:20.206543Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 93 (previous tip: 92) +2025-11-14T18:25:20.206561Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 93 (last_processed_height: 92, tip: 93) +2025-11-14T18:25:20.206635Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 93)], last_processed_height: 92, tip: 93 +2025-11-14T18:25:20.206641Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:20.207394Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xcabdf78807b585634a9cc56b49de14643d6cda00491e1e9fddfbe1302cedbd1f for height 93 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 93 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 93, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 93, is last block: false +2025-11-14T18:25:20.207597Z  INFO ThreadId(56) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=93 +2025-11-14T18:25:20.207824Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 94 not found (last_processed=93, tip=93) +2025-11-14T18:25:20.207861Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xcabdf78807b585634a9cc56b49de14643d6cda00491e1e9fddfbe1302cedbd1f for height 93 +2025-11-14T18:25:20.207956Z  INFO ThreadId(89) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xcabdf78807b585634a9cc56b49de14643d6cda00491e1e9fddfbe1302cedbd1f for height 93 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 93 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 93, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 93, is last block: false +2025-11-14T18:25:20.208041Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=93 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 93 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 93, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 93, is last block: false +2025-11-14T18:25:20.208191Z  INFO ThreadId(89) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=93 +2025-11-14T18:25:20.208195Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xcabdf78807b585634a9cc56b49de14643d6cda00491e1e9fddfbe1302cedbd1f for height 93 +2025-11-14T18:25:20.208217Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 94 not found (last_processed=93, tip=93) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 93 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 93, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 93, is last block: false +2025-11-14T18:25:20.208329Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=93 +2025-11-14T18:25:20.208363Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 94 not found (last_processed=93, tip=93) +2025-11-14T18:25:20.208495Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 94 not found (last_processed=93, tip=93) +2025-11-14T18:25:20.259734Z  INFO ThreadId(89) summit_application::actor: application/src/actor.rs:177: 143 Handling message Broadcast +2025-11-14T18:25:20.262409Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 61) (epoch 1, view 61), parent height: 60 +2025-11-14T18:25:20.263309Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 61) (epoch 1, view 61), parent height: 60 +2025-11-14T18:25:20.263318Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 61) (epoch 1, view 61), parent height: 60 +2025-11-14T18:25:20.265230Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:149: 139 application: Handling message Propose for round Round(1, 62) (epoch 1, view 62), parent height: 61 +2025-11-14T18:25:20.294286Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:20.331212Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 61) (last_processed_height=93, tip=93) +2025-11-14T18:25:20.331744Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 94 (previous tip: 93) +2025-11-14T18:25:20.331749Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 94 (last_processed_height: 93, tip: 94) +2025-11-14T18:25:20.331788Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 94)], last_processed_height: 93, tip: 94 +2025-11-14T18:25:20.331792Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:20.332124Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 61) (last_processed_height=93, tip=93) +2025-11-14T18:25:20.332175Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 61) (last_processed_height=93, tip=93) +2025-11-14T18:25:20.332457Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 61) (last_processed_height=93, tip=93) +2025-11-14T18:25:20.333005Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x56a38773635a4147a64492a77d01020373ca80b359e7d3b28bed21623e1330ce for height 94 +2025-11-14T18:25:20.333066Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 94 (previous tip: 93) +2025-11-14T18:25:20.333072Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 94 (last_processed_height: 93, tip: 94) +2025-11-14T18:25:20.333119Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 94)], last_processed_height: 93, tip: 94 +2025-11-14T18:25:20.333123Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:20.333144Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 94 (previous tip: 93) +2025-11-14T18:25:20.333151Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 94 (last_processed_height: 93, tip: 94) +2025-11-14T18:25:20.333182Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 94)], last_processed_height: 93, tip: 94 +2025-11-14T18:25:20.333185Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 94 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 94, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 94, is last block: false +2025-11-14T18:25:20.333219Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=94 +2025-11-14T18:25:20.333201Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 94 (previous tip: 93) +2025-11-14T18:25:20.333234Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 94 (last_processed_height: 93, tip: 94) +2025-11-14T18:25:20.333266Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 94)], last_processed_height: 93, tip: 94 +2025-11-14T18:25:20.333270Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:20.333365Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 95 not found (last_processed=94, tip=94) +2025-11-14T18:25:20.334175Z  INFO ThreadId(89) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x56a38773635a4147a64492a77d01020373ca80b359e7d3b28bed21623e1330ce for height 94 +2025-11-14T18:25:20.334348Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x56a38773635a4147a64492a77d01020373ca80b359e7d3b28bed21623e1330ce for height 94 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 94 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 94, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 94, is last block: false +2025-11-14T18:25:20.334366Z  INFO ThreadId(90) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=94 +2025-11-14T18:25:20.334400Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x56a38773635a4147a64492a77d01020373ca80b359e7d3b28bed21623e1330ce for height 94 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 94 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 94, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 94, is last block: false +2025-11-14T18:25:20.334486Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=94 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 94 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 94, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 94, is last block: false +2025-11-14T18:25:20.334536Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=94 +2025-11-14T18:25:20.334541Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 95 not found (last_processed=94, tip=94) +2025-11-14T18:25:20.334608Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 95 not found (last_processed=94, tip=94) +2025-11-14T18:25:20.334683Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 95 not found (last_processed=94, tip=94) +2025-11-14T18:25:20.385140Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:177: 139 Handling message Broadcast +2025-11-14T18:25:20.454512Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 62) (epoch 1, view 62), parent height: 61 +2025-11-14T18:25:20.454732Z  INFO ThreadId(90) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 62) (epoch 1, view 62), parent height: 61 +2025-11-14T18:25:20.454943Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 62) (epoch 1, view 62), parent height: 61 +2025-11-14T18:25:20.456559Z  INFO ThreadId(56) summit_application::actor: application/src/actor.rs:149: 55 application: Handling message Propose for round Round(1, 63) (epoch 1, view 63), parent height: 62 +2025-11-14T18:25:20.547065Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:20.578961Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 62) (last_processed_height=94, tip=94) +2025-11-14T18:25:20.579245Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 62) (last_processed_height=94, tip=94) +2025-11-14T18:25:20.579823Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 95 (previous tip: 94) +2025-11-14T18:25:20.579830Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 95 (last_processed_height: 94, tip: 95) +2025-11-14T18:25:20.579866Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 95 (previous tip: 94) +2025-11-14T18:25:20.579871Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 95)], last_processed_height: 94, tip: 95 +2025-11-14T18:25:20.579877Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:20.579878Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 95 (last_processed_height: 94, tip: 95) +2025-11-14T18:25:20.579920Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 95)], last_processed_height: 94, tip: 95 +2025-11-14T18:25:20.579926Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:20.580026Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 62) (last_processed_height=94, tip=94) +2025-11-14T18:25:20.580537Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 95 (previous tip: 94) +2025-11-14T18:25:20.580545Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 95 (last_processed_height: 94, tip: 95) +2025-11-14T18:25:20.580585Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 95)], last_processed_height: 94, tip: 95 +2025-11-14T18:25:20.580589Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:20.580786Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 62) (last_processed_height=94, tip=94) +2025-11-14T18:25:20.581090Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xdb96b02f5cd7b632f67630fb362c6a2692661cad79e039516f0151bac8180c35 for height 95 +2025-11-14T18:25:20.581126Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xdb96b02f5cd7b632f67630fb362c6a2692661cad79e039516f0151bac8180c35 for height 95 +üüüüüüüüüüüüüüüüüüüüüüüüü +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 95 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 95, is penultimate block: false +COMMITING BLOCK 95 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 95, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 95, is last block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 95, is last block: false +2025-11-14T18:25:20.581300Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=95 +2025-11-14T18:25:20.581302Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=95 +2025-11-14T18:25:20.581508Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xdb96b02f5cd7b632f67630fb362c6a2692661cad79e039516f0151bac8180c35 for height 95 +2025-11-14T18:25:20.581511Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 96 not found (last_processed=95, tip=95) +2025-11-14T18:25:20.581588Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 95 (previous tip: 94) +2025-11-14T18:25:20.581594Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 95 (last_processed_height: 94, tip: 95) +2025-11-14T18:25:20.581634Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 95)], last_processed_height: 94, tip: 95 +2025-11-14T18:25:20.581637Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 95 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 95, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 95, is last block: false +2025-11-14T18:25:20.581665Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=95 +2025-11-14T18:25:20.581669Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 96 not found (last_processed=95, tip=95) +2025-11-14T18:25:20.581812Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 96 not found (last_processed=95, tip=95) +2025-11-14T18:25:20.582365Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xdb96b02f5cd7b632f67630fb362c6a2692661cad79e039516f0151bac8180c35 for height 95 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 95 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 95, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 95, is last block: false +2025-11-14T18:25:20.582476Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=95 +2025-11-14T18:25:20.582587Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 96 not found (last_processed=95, tip=95) +2025-11-14T18:25:20.633308Z  INFO ThreadId(57) summit_application::actor: application/src/actor.rs:177: 55 Handling message Broadcast +2025-11-14T18:25:20.636182Z  INFO ThreadId(89) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 63) (epoch 1, view 63), parent height: 62 +2025-11-14T18:25:20.636316Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 63) (epoch 1, view 63), parent height: 62 +2025-11-14T18:25:20.636708Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 63) (epoch 1, view 63), parent height: 62 +2025-11-14T18:25:20.706043Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 63) (last_processed_height=95, tip=95) +2025-11-14T18:25:20.706050Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 63) (last_processed_height=95, tip=95) +2025-11-14T18:25:20.706544Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 96 (previous tip: 95) +2025-11-14T18:25:20.706549Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 96 (last_processed_height: 95, tip: 96) +2025-11-14T18:25:20.706588Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 96)], last_processed_height: 95, tip: 96 +2025-11-14T18:25:20.706592Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:20.706636Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 96 (previous tip: 95) +2025-11-14T18:25:20.706642Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 96 (last_processed_height: 95, tip: 96) +2025-11-14T18:25:20.706670Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 96)], last_processed_height: 95, tip: 96 +2025-11-14T18:25:20.706673Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:20.706812Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 63) (last_processed_height=95, tip=95) +2025-11-14T18:25:20.706838Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 63) (last_processed_height=95, tip=95) +2025-11-14T18:25:20.707353Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 96 (previous tip: 95) +2025-11-14T18:25:20.707361Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 96 (last_processed_height: 95, tip: 96) +2025-11-14T18:25:20.707375Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 96 (previous tip: 95) +2025-11-14T18:25:20.707381Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 96 (last_processed_height: 95, tip: 96) +2025-11-14T18:25:20.707400Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 96)], last_processed_height: 95, tip: 96 +2025-11-14T18:25:20.707405Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:20.707459Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 96)], last_processed_height: 95, tip: 96 +2025-11-14T18:25:20.707467Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:20.707777Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7d8f249695cd354d0b3c5eee029e04f567329d1e7e5176bf459ef720cfbedf98 for height 96 +2025-11-14T18:25:20.707845Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7d8f249695cd354d0b3c5eee029e04f567329d1e7e5176bf459ef720cfbedf98 for height 96 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 96 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 96, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 96, is last block: false +2025-11-14T18:25:20.707956Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=96 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 96 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 96, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 96, is last block: false +2025-11-14T18:25:20.708031Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=96 +2025-11-14T18:25:20.708170Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 97 not found (last_processed=96, tip=96) +2025-11-14T18:25:20.708268Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 97 not found (last_processed=96, tip=96) +2025-11-14T18:25:20.708407Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7d8f249695cd354d0b3c5eee029e04f567329d1e7e5176bf459ef720cfbedf98 for height 96 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 96 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 96, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 96, is last block: false +2025-11-14T18:25:20.708553Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=96 +2025-11-14T18:25:20.708627Z  INFO ThreadId(88) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x7d8f249695cd354d0b3c5eee029e04f567329d1e7e5176bf459ef720cfbedf98 for height 96 +2025-11-14T18:25:20.708679Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 97 not found (last_processed=96, tip=96) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 96 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 96, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 96, is last block: false +2025-11-14T18:25:20.708750Z  INFO ThreadId(90) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=96 +2025-11-14T18:25:20.708860Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 97 not found (last_processed=96, tip=96) +2025-11-14T18:25:20.799517Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:20.828835Z  INFO ThreadId(46) summit_application::actor: application/src/actor.rs:149: 15 application: Handling message Propose for round Round(1, 65) (epoch 1, view 65), parent height: 63 +2025-11-14T18:25:20.880393Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:177: 15 Handling message Broadcast +2025-11-14T18:25:20.883174Z  INFO ThreadId(89) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 65) (epoch 1, view 65), parent height: 63 +2025-11-14T18:25:20.883643Z  INFO ThreadId(52) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 65) (epoch 1, view 65), parent height: 63 +2025-11-14T18:25:20.883646Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 65) (epoch 1, view 65), parent height: 63 +2025-11-14T18:25:20.887341Z  INFO ThreadId(89) summit_application::actor: application/src/actor.rs:149: 143 application: Handling message Propose for round Round(1, 66) (epoch 1, view 66), parent height: 65 +2025-11-14T18:25:20.955573Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 65) (last_processed_height=96, tip=96) +2025-11-14T18:25:20.956433Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 97 (previous tip: 96) +2025-11-14T18:25:20.956441Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 97 (last_processed_height: 96, tip: 97) +2025-11-14T18:25:20.956482Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 97)], last_processed_height: 96, tip: 97 +2025-11-14T18:25:20.956487Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:20.956574Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 65) (last_processed_height=96, tip=96) +2025-11-14T18:25:20.956810Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 65) (last_processed_height=96, tip=96) +2025-11-14T18:25:20.957112Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 97 (previous tip: 96) +2025-11-14T18:25:20.957119Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 97 (last_processed_height: 96, tip: 97) +2025-11-14T18:25:20.957157Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 97)], last_processed_height: 96, tip: 97 +2025-11-14T18:25:20.957161Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:20.957338Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 97 (previous tip: 96) +2025-11-14T18:25:20.957345Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 97 (last_processed_height: 96, tip: 97) +2025-11-14T18:25:20.957371Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 97)], last_processed_height: 96, tip: 97 +2025-11-14T18:25:20.957374Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:20.957501Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 65) (last_processed_height=96, tip=96) +2025-11-14T18:25:20.957552Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x52d8db316aef1c3111139c124aa9f450c359d26dcb616b74700c030d1d522d75 for height 97 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 97 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 97, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 97, is last block: false +2025-11-14T18:25:20.957808Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=97 +2025-11-14T18:25:20.957996Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 98 not found (last_processed=97, tip=97) +2025-11-14T18:25:20.958248Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 97 (previous tip: 96) +2025-11-14T18:25:20.958258Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 97 (last_processed_height: 96, tip: 97) +2025-11-14T18:25:20.958323Z  INFO ThreadId(90) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x52d8db316aef1c3111139c124aa9f450c359d26dcb616b74700c030d1d522d75 for height 97 +2025-11-14T18:25:20.958351Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 97)], last_processed_height: 96, tip: 97 +2025-11-14T18:25:20.958357Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:20.958425Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x52d8db316aef1c3111139c124aa9f450c359d26dcb616b74700c030d1d522d75 for height 97 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 97 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 97, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 97, is last block: false +2025-11-14T18:25:20.958472Z  INFO ThreadId(90) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=97 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 97 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 97, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 97, is last block: false +2025-11-14T18:25:20.958563Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=97 +2025-11-14T18:25:20.958654Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 98 not found (last_processed=97, tip=97) +2025-11-14T18:25:20.958709Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 98 not found (last_processed=97, tip=97) +2025-11-14T18:25:20.959133Z  INFO ThreadId(55) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x52d8db316aef1c3111139c124aa9f450c359d26dcb616b74700c030d1d522d75 for height 97 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 97 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 97, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 97, is last block: false +2025-11-14T18:25:20.959257Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=97 +2025-11-14T18:25:20.959377Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 98 not found (last_processed=97, tip=97) +2025-11-14T18:25:21.010377Z  INFO ThreadId(90) summit_application::actor: application/src/actor.rs:177: 143 Handling message Broadcast +2025-11-14T18:25:21.051029Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:21.079445Z  INFO ThreadId(57) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 66) (epoch 1, view 66), parent height: 65 +2025-11-14T18:25:21.079445Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(1, 66) (epoch 1, view 66), parent height: 65 +2025-11-14T18:25:21.079961Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 66) (epoch 1, view 66), parent height: 65 +2025-11-14T18:25:21.082486Z  INFO ThreadId(49) summit_application::actor: application/src/actor.rs:149: 139 application: Handling message Propose for round Round(1, 67) (epoch 1, view 67), parent height: 66 +2025-11-14T18:25:21.205064Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 66) (last_processed_height=97, tip=97) +2025-11-14T18:25:21.205132Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 66) (last_processed_height=97, tip=97) +2025-11-14T18:25:21.205156Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 66) (last_processed_height=97, tip=97) +2025-11-14T18:25:21.205695Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 98 (previous tip: 97) +2025-11-14T18:25:21.205702Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 98 (last_processed_height: 97, tip: 98) +2025-11-14T18:25:21.205739Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 98)], last_processed_height: 97, tip: 98 +2025-11-14T18:25:21.205743Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:21.205945Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 98 (previous tip: 97) +2025-11-14T18:25:21.205949Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 98 (last_processed_height: 97, tip: 98) +2025-11-14T18:25:21.205966Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 98)], last_processed_height: 97, tip: 98 +2025-11-14T18:25:21.205968Z  INFO ThreadId(43) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:21.206046Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 66) (last_processed_height=97, tip=97) +2025-11-14T18:25:21.206318Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 98 (previous tip: 97) +2025-11-14T18:25:21.206332Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 98 (last_processed_height: 97, tip: 98) +2025-11-14T18:25:21.206401Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 98)], last_processed_height: 97, tip: 98 +2025-11-14T18:25:21.206431Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:21.206893Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xa88d06acfc7bd83c015a639d4e711b9fccbddc208c46298dadb8c05fc3f57ea2 for height 98 +2025-11-14T18:25:21.206959Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xa88d06acfc7bd83c015a639d4e711b9fccbddc208c46298dadb8c05fc3f57ea2 for height 98 +2025-11-14T18:25:21.206971Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 98 (previous tip: 97) +2025-11-14T18:25:21.206977Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 98 (last_processed_height: 97, tip: 98) +2025-11-14T18:25:21.207047Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 98)], last_processed_height: 97, tip: 98 +2025-11-14T18:25:21.207052Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 98 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 98, is penultimate block: true +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 98, is last block: false +2025-11-14T18:25:21.207082Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=98 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 98 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 98, is penultimate block: true +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 98, is last block: false +2025-11-14T18:25:21.207139Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=98 +2025-11-14T18:25:21.207239Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 99 not found (last_processed=98, tip=98) +2025-11-14T18:25:21.207294Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 99 not found (last_processed=98, tip=98) +2025-11-14T18:25:21.207392Z  INFO ThreadId(51) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xa88d06acfc7bd83c015a639d4e711b9fccbddc208c46298dadb8c05fc3f57ea2 for height 98 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 98 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 98, is penultimate block: true +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 98, is last block: false +2025-11-14T18:25:21.207523Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=98 +2025-11-14T18:25:21.207693Z  INFO ThreadId(49) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 99 not found (last_processed=98, tip=98) +2025-11-14T18:25:21.207945Z  INFO ThreadId(90) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xa88d06acfc7bd83c015a639d4e711b9fccbddc208c46298dadb8c05fc3f57ea2 for height 98 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 98 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 98, is penultimate block: true +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 98, is last block: false +2025-11-14T18:25:21.208068Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=98 +2025-11-14T18:25:21.208199Z  INFO ThreadId(90) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 99 not found (last_processed=98, tip=98) +2025-11-14T18:25:21.259907Z  INFO ThreadId(51) summit_application::actor: application/src/actor.rs:177: 139 Handling message Broadcast +2025-11-14T18:25:21.263009Z  INFO ThreadId(43) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(1, 67) (epoch 1, view 67), parent height: 66 +2025-11-14T18:25:21.263291Z  INFO ThreadId(58) summit_application::actor: application/src/actor.rs:200: 55 application: Handling message Verify for round Round(1, 67) (epoch 1, view 67), parent height: 66 +2025-11-14T18:25:21.263536Z  INFO ThreadId(91) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(1, 67) (epoch 1, view 67), parent height: 66 +2025-11-14T18:25:21.267261Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:149: 55 application: Handling message Propose for round Round(1, 68) (epoch 1, view 68), parent height: 67 +2025-11-14T18:25:21.303621Z ERROR ThreadId(04) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:21.331290Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 67) (last_processed_height=98, tip=98) +2025-11-14T18:25:21.331303Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 67) (last_processed_height=98, tip=98) +2025-11-14T18:25:21.332204Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 67) (last_processed_height=98, tip=98) +2025-11-14T18:25:21.332206Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 99 (previous tip: 98) +2025-11-14T18:25:21.332217Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 99 (last_processed_height: 98, tip: 99) +2025-11-14T18:25:21.332214Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 99 (previous tip: 98) +2025-11-14T18:25:21.332227Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 99 (last_processed_height: 98, tip: 99) +2025-11-14T18:25:21.332339Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(1, 67) (last_processed_height=98, tip=98) +2025-11-14T18:25:21.332412Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 99)], last_processed_height: 98, tip: 99 +2025-11-14T18:25:21.332419Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:21.332496Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 99)], last_processed_height: 98, tip: 99 +2025-11-14T18:25:21.332502Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:21.332891Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 99 (previous tip: 98) +2025-11-14T18:25:21.332898Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 99 (last_processed_height: 98, tip: 99) +2025-11-14T18:25:21.333047Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 99)], last_processed_height: 98, tip: 99 +2025-11-14T18:25:21.333053Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:21.333135Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 99 (previous tip: 98) +2025-11-14T18:25:21.333141Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 99 (last_processed_height: 98, tip: 99) +2025-11-14T18:25:21.333309Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 99)], last_processed_height: 98, tip: 99 +2025-11-14T18:25:21.333316Z  INFO ThreadId(55) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:21.333542Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd6972d8d8068edce35b5516e4946a59e287a4a3aaafb21b119eead52c7c492ef for height 99 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 99 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 99, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 99, is last block: true +2025-11-14T18:25:21.333963Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd6972d8d8068edce35b5516e4946a59e287a4a3aaafb21b119eead52c7c492ef for height 99 +2025-11-14T18:25:21.334006Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:451: finalizer: epoch transition to epoch 2 with 5 validators at height 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++ +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 99 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 99, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 99, is last block: true +2025-11-14T18:25:21.334203Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd6972d8d8068edce35b5516e4946a59e287a4a3aaafb21b119eead52c7c492ef for height 99 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 99 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 99, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 99, is last block: true +Created checkpoint at epoch 1, height 98, view 66 +2025-11-14T18:25:21.334357Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0xd6972d8d8068edce35b5516e4946a59e287a4a3aaafb21b119eead52c7c492ef for height 99 +2025-11-14T18:25:21.334423Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:451: finalizer: epoch transition to epoch 2 with 5 validators at height 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++ +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 99 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 99, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 99, is last block: true +2025-11-14T18:25:21.334564Z  INFO ThreadId(43) summit_finalizer::actor: finalizer/src/actor.rs:451: finalizer: epoch transition to epoch 2 with 5 validators at height 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++ +Created checkpoint at epoch 1, height 98, view 66 +2025-11-14T18:25:21.334762Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:451: finalizer: epoch transition to epoch 2 with 5 validators at height 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++ +Created checkpoint at epoch 1, height 98, view 66 +Created checkpoint at epoch 1, height 98, view 66 +2025-11-14T18:25:21.335062Z  INFO ThreadId(49) summit_orchestrator::actor: orchestrator/src/actor.rs:307: orchestrator: received Enter message for epoch 2 with 5 validators +2025-11-14T18:25:21.335100Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=99 +2025-11-14T18:25:21.335271Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 100 not found (last_processed=99, tip=99) +2025-11-14T18:25:21.335396Z  INFO ThreadId(91) summit_orchestrator::actor: orchestrator/src/actor.rs:307: orchestrator: received Enter message for epoch 2 with 5 validators +2025-11-14T18:25:21.335411Z  INFO ThreadId(49) summit_orchestrator::actor: orchestrator/src/actor.rs:406: orchestrator: starting Simplex engine for epoch 2 +2025-11-14T18:25:21.335420Z  INFO ThreadId(49) summit_orchestrator::actor: orchestrator/src/actor.rs:335: entered epoch epoch=2 +2025-11-14T18:25:21.335427Z  INFO ThreadId(49) summit_orchestrator::actor: orchestrator/src/actor.rs:348: exited epoch epoch=1 +2025-11-14T18:25:21.335434Z  INFO ThreadId(90) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=99 +2025-11-14T18:25:21.335507Z  INFO ThreadId(50) commonware_consensus::simplex::actors::voter::actor: /home/matthias/.cargo/git/checkouts/monorepo-9732103c47eb4665/f395c9e/consensus/src/simplex/actors/voter/actor.rs:1688: consensus initialized current_view=1 elapsed=1.694µs +2025-11-14T18:25:21.335532Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:149: 139 application: Handling message Propose for round Round(2, 1) (epoch 2, view 1), parent height: 0 +2025-11-14T18:25:21.335553Z  INFO ThreadId(43) summit_orchestrator::actor: orchestrator/src/actor.rs:307: orchestrator: received Enter message for epoch 2 with 5 validators +2025-11-14T18:25:21.335585Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 100 not found (last_processed=99, tip=99) +2025-11-14T18:25:21.335590Z  INFO ThreadId(45) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=99 +2025-11-14T18:25:21.335721Z  INFO ThreadId(57) summit_orchestrator::actor: orchestrator/src/actor.rs:307: orchestrator: received Enter message for epoch 2 with 5 validators +2025-11-14T18:25:21.335728Z  INFO ThreadId(45) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 100 not found (last_processed=99, tip=99) +2025-11-14T18:25:21.335767Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=99 +2025-11-14T18:25:21.335777Z  INFO ThreadId(91) summit_orchestrator::actor: orchestrator/src/actor.rs:406: orchestrator: starting Simplex engine for epoch 2 +2025-11-14T18:25:21.335777Z  WARN ThreadId(58) summit_application::actor: application/src/actor.rs:167: Failed to create a block for round Round(1, 68): Aborting block proposal for epoch 2. Current epoch is 2 +2025-11-14T18:25:21.335786Z  INFO ThreadId(91) summit_orchestrator::actor: orchestrator/src/actor.rs:335: entered epoch epoch=2 +2025-11-14T18:25:21.335791Z  INFO ThreadId(91) summit_orchestrator::actor: orchestrator/src/actor.rs:348: exited epoch epoch=1 +2025-11-14T18:25:21.335862Z  INFO ThreadId(88) commonware_consensus::simplex::actors::voter::actor: /home/matthias/.cargo/git/checkouts/monorepo-9732103c47eb4665/f395c9e/consensus/src/simplex/actors/voter/actor.rs:1688: consensus initialized current_view=1 elapsed=431ns +2025-11-14T18:25:21.335942Z  INFO ThreadId(43) summit_orchestrator::actor: orchestrator/src/actor.rs:406: orchestrator: starting Simplex engine for epoch 2 +2025-11-14T18:25:21.335949Z  INFO ThreadId(43) summit_orchestrator::actor: orchestrator/src/actor.rs:335: entered epoch epoch=2 +2025-11-14T18:25:21.335954Z  INFO ThreadId(43) summit_orchestrator::actor: orchestrator/src/actor.rs:348: exited epoch epoch=1 +2025-11-14T18:25:21.335974Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 100 not found (last_processed=99, tip=99) +2025-11-14T18:25:21.336024Z  INFO ThreadId(45) commonware_consensus::simplex::actors::voter::actor: /home/matthias/.cargo/git/checkouts/monorepo-9732103c47eb4665/f395c9e/consensus/src/simplex/actors/voter/actor.rs:1688: consensus initialized current_view=1 elapsed=561ns +2025-11-14T18:25:21.336098Z  INFO ThreadId(57) summit_orchestrator::actor: orchestrator/src/actor.rs:406: orchestrator: starting Simplex engine for epoch 2 +2025-11-14T18:25:21.336106Z  INFO ThreadId(57) summit_orchestrator::actor: orchestrator/src/actor.rs:335: entered epoch epoch=2 +2025-11-14T18:25:21.336112Z  INFO ThreadId(57) summit_orchestrator::actor: orchestrator/src/actor.rs:348: exited epoch epoch=1 +2025-11-14T18:25:21.336201Z  INFO ThreadId(57) commonware_consensus::simplex::actors::voter::actor: /home/matthias/.cargo/git/checkouts/monorepo-9732103c47eb4665/f395c9e/consensus/src/simplex/actors/voter/actor.rs:1688: consensus initialized current_view=1 elapsed=601ns +Node 1 at height 99 +Node 2 at height 99 +Node 3 at height 99 +Node 4 at height 99 +2025-11-14T18:25:21.387590Z  WARN ThreadId(52) commonware_consensus::simplex::actors::voter::actor: /home/matthias/.cargo/git/checkouts/monorepo-9732103c47eb4665/f395c9e/consensus/src/simplex/actors/voter/actor.rs:1800: failed to record our container round=Round(2, 1) +2025-11-14T18:25:21.455712Z  INFO ThreadId(56) summit_application::actor: application/src/actor.rs:149: 55 application: Handling message Propose for round Round(2, 2) (epoch 2, view 2), parent height: 0 +2025-11-14T18:25:21.507736Z  INFO ThreadId(56) summit_application::actor: application/src/actor.rs:177: 55 Handling message Broadcast +2025-11-14T18:25:21.510611Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:200: 139 application: Handling message Verify for round Round(2, 2) (epoch 2, view 2), parent height: 0 +2025-11-14T18:25:21.510616Z  INFO ThreadId(91) summit_application::actor: application/src/actor.rs:200: 143 application: Handling message Verify for round Round(2, 2) (epoch 2, view 2), parent height: 0 +2025-11-14T18:25:21.510678Z  INFO ThreadId(44) summit_application::actor: application/src/actor.rs:200: 15 application: Handling message Verify for round Round(2, 2) (epoch 2, view 2), parent height: 0 +2025-11-14T18:25:21.510821Z  INFO ThreadId(52) summit_syncer::cache: syncer/src/cache.rs:227: restored verified archive elapsed=64.268µs +2025-11-14T18:25:21.510833Z  INFO ThreadId(88) summit_syncer::cache: syncer/src/cache.rs:227: restored verified archive elapsed=49.221µs +2025-11-14T18:25:21.510869Z  INFO ThreadId(52) summit_syncer::cache: syncer/src/cache.rs:227: restored notarized archive elapsed=35.796µs +2025-11-14T18:25:21.510869Z  INFO ThreadId(43) summit_syncer::cache: syncer/src/cache.rs:227: restored verified archive elapsed=74.808µs +2025-11-14T18:25:21.510893Z  INFO ThreadId(88) summit_syncer::cache: syncer/src/cache.rs:227: restored notarized archive elapsed=48.158µs +2025-11-14T18:25:21.510914Z  INFO ThreadId(43) summit_syncer::cache: syncer/src/cache.rs:227: restored notarized archive elapsed=34.924µs +2025-11-14T18:25:21.510930Z  INFO ThreadId(88) summit_syncer::cache: syncer/src/cache.rs:227: restored notarizations archive elapsed=31.218µs +2025-11-14T18:25:21.510932Z  INFO ThreadId(52) summit_syncer::cache: syncer/src/cache.rs:227: restored notarizations archive elapsed=55.963µs +2025-11-14T18:25:21.510972Z  INFO ThreadId(52) summit_syncer::cache: syncer/src/cache.rs:227: restored finalizations archive elapsed=31.438µs +2025-11-14T18:25:21.510971Z  INFO ThreadId(43) summit_syncer::cache: syncer/src/cache.rs:227: restored notarizations archive elapsed=49.782µs +2025-11-14T18:25:21.510992Z  INFO ThreadId(88) summit_syncer::cache: syncer/src/cache.rs:227: restored finalizations archive elapsed=54.43µs +2025-11-14T18:25:21.511028Z  INFO ThreadId(44) summit_syncer::cache: syncer/src/cache.rs:227: restored finalizations archive elapsed=42.197µs +2025-11-14T18:25:21.513213Z  INFO ThreadId(58) summit_syncer::cache: syncer/src/cache.rs:227: restored verified archive elapsed=29.535µs +2025-11-14T18:25:21.513244Z  INFO ThreadId(58) summit_syncer::cache: syncer/src/cache.rs:227: restored notarized archive elapsed=25.487µs +2025-11-14T18:25:21.513271Z  INFO ThreadId(58) summit_syncer::cache: syncer/src/cache.rs:227: restored notarizations archive elapsed=24.024µs +2025-11-14T18:25:21.513312Z  INFO ThreadId(57) summit_syncer::cache: syncer/src/cache.rs:227: restored finalizations archive elapsed=37.77µs +2025-11-14T18:25:21.555976Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:21.580764Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(2, 2) (last_processed_height=99, tip=99) +2025-11-14T18:25:21.581801Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 100 (previous tip: 99) +2025-11-14T18:25:21.581810Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 100 (last_processed_height: 99, tip: 100) +2025-11-14T18:25:21.581857Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(49, 100)], last_processed_height: 99, tip: 100 +2025-11-14T18:25:21.581862Z  INFO ThreadId(89) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:21.582023Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(2, 2) (last_processed_height=99, tip=99) +2025-11-14T18:25:21.582099Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(2, 2) (last_processed_height=99, tip=99) +2025-11-14T18:25:21.582612Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:510: syncer: received Message::Finalization for round Round(2, 2) (last_processed_height=99, tip=99) +2025-11-14T18:25:21.582912Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 100 (previous tip: 99) +2025-11-14T18:25:21.582921Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 100 (last_processed_height: 99, tip: 100) +2025-11-14T18:25:21.582955Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 100 (previous tip: 99) +2025-11-14T18:25:21.582964Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 100 (last_processed_height: 99, tip: 100) +2025-11-14T18:25:21.582976Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 100)], last_processed_height: 99, tip: 100 +2025-11-14T18:25:21.582982Z  INFO ThreadId(44) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:21.583005Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 100)], last_processed_height: 99, tip: 100 +2025-11-14T18:25:21.583010Z  INFO ThreadId(51) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:21.583378Z  INFO ThreadId(89) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x9caaddc3af361fdc9e925f950b633d382681c78d0ab6f190c48853402e3dab04 for height 100 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 100 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 100, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +2025-11-14T18:25:21.583573Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:988: syncer: new tip at height 100 (previous tip: 99) +epoch_num_of_blocks: 50, new_height: 100, is last block: false +2025-11-14T18:25:21.583581Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1000: syncer: stored finalization for height 100 (last_processed_height: 99, tip: 100) +2025-11-14T18:25:21.583584Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=100 +2025-11-14T18:25:21.583642Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1137: syncer: identify_gaps: archive ranges: [(1, 100)], last_processed_height: 99, tip: 100 +2025-11-14T18:25:21.583649Z  INFO ThreadId(57) summit_syncer::actor: syncer/src/actor.rs:1159: syncer: identify_gaps: found gaps: [] +2025-11-14T18:25:21.583899Z  INFO ThreadId(91) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 101 not found (last_processed=100, tip=100) +2025-11-14T18:25:21.584238Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x9caaddc3af361fdc9e925f950b633d382681c78d0ab6f190c48853402e3dab04 for height 100 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 100 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 100, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 100, is last block: false +2025-11-14T18:25:21.584461Z  INFO ThreadId(50) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=100 +2025-11-14T18:25:21.584570Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x9caaddc3af361fdc9e925f950b633d382681c78d0ab6f190c48853402e3dab04 for height 100 +2025-11-14T18:25:21.584652Z  INFO ThreadId(50) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 101 not found (last_processed=100, tip=100) +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 100 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 100, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 100, is last block: false +2025-11-14T18:25:21.584746Z  INFO ThreadId(46) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=100 +2025-11-14T18:25:21.584930Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 101 not found (last_processed=100, tip=100) +2025-11-14T18:25:21.585148Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:274: Commiting block 0x9caaddc3af361fdc9e925f950b633d382681c78d0ab6f190c48853402e3dab04 for height 100 +üüüüüüüüüüüüüüüüüüüüüüüüü +COMMITING BLOCK 100 to reth +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +epoch_num_of_blocks: 50, new_height: 100, is penultimate block: false +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +epoch_num_of_blocks: 50, new_height: 100, is last block: false +2025-11-14T18:25:21.585300Z  INFO ThreadId(58) summit_finalizer::actor: finalizer/src/actor.rs:516: finalized block new_height=100 +2025-11-14T18:25:21.585438Z  INFO ThreadId(58) summit_syncer::actor: syncer/src/actor.rs:821: syncer: try_dispatch_block: block 101 not found (last_processed=100, tip=100) +2025-11-14T18:25:21.808828Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:22.061370Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:22.312660Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:22.565173Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:22.817977Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:23.070799Z ERROR ThreadId(12) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +2025-11-14T18:25:23.323545Z ERROR ThreadId(10) alloy_rpc_client::poller: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-rpc-client-1.0.30/src/poller.rs:367: failed to poll err=error sending request for url (http://localhost:8545/) +All nodes have reached target height! +Test completed successfully! +Sending stop signals to all 4 nodes... +Sending stop signal to node index 0... +Sending stop signal to node index 1... +Sending stop signal to node index 2... +Sending stop signal to node index 3... +Waiting for all nodes to shut down... +Waiting for node index 0 to join... +Node 2 received stop signal, shutting down runtime... +Node 1 received stop signal, shutting down runtime... +Node 3 received stop signal, shutting down runtime... +Node 4 received stop signal, shutting down runtime... +2025-11-14T18:25:23.409837Z  INFO ThreadId(44) summit::prom::server: node/src/prom/server.rs:102: Metrics server shutting down: 0 +RPC server stopped: 0 +2025-11-14T18:25:23.409818Z  INFO ThreadId(50) summit::prom::server: node/src/prom/server.rs:102: Metrics server shutting down: 0 +RPC server stopped: 0 +2025-11-14T18:25:23.409870Z  INFO ThreadId(44) summit_finalizer::actor: finalizer/src/actor.rs:222: runtime terminated, shutting down finalizer: 0 +2025-11-14T18:25:23.409861Z  INFO ThreadId(49) summit_finalizer::actor: finalizer/src/actor.rs:222: runtime terminated, shutting down finalizer: 0 +2025-11-14T18:25:23.409878Z  INFO ThreadId(90) summit::prom::server: node/src/prom/server.rs:102: Metrics server shutting down: 0 +2025-11-14T18:25:23.409871Z  INFO ThreadId(58) summit::prom::server: node/src/prom/server.rs:102: Metrics server shutting down: 0 +2025-11-14T18:25:23.409914Z  WARN ThreadId(49) summit_orchestrator::actor: orchestrator/src/actor.rs:301: mailbox closed, shutting down orchestrator +2025-11-14T18:25:23.409924Z  INFO ThreadId(50) summit_application::actor: application/src/actor.rs:255: application received cancellation signal, exiting +2025-11-14T18:25:23.409922Z  INFO ThreadId(57) summit_finalizer::actor: finalizer/src/actor.rs:222: runtime terminated, shutting down finalizer: 0 +2025-11-14T18:25:23.409933Z  INFO ThreadId(49) summit::engine: node/src/engine.rs:380: cancellation triggered, waiting for actors to finish +2025-11-14T18:25:23.409938Z  INFO ThreadId(50) alloy_pubsub::service: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-pubsub-1.0.30/src/service.rs:256: Pubsub service request channel closed. Shutting down. +RPC server stopped: 0 +2025-11-14T18:25:23.409943Z  INFO ThreadId(56) summit_syncer::actor: syncer/src/actor.rs:611: handler closed, shutting down +2025-11-14T18:25:23.409950Z  INFO ThreadId(55) summit_application::actor: application/src/actor.rs:255: application received cancellation signal, exiting +2025-11-14T18:25:23.409952Z  INFO ThreadId(52) summit_syncer::actor: syncer/src/actor.rs:457: mailbox closed, shutting down +2025-11-14T18:25:23.409957Z  WARN ThreadId(57) summit_orchestrator::actor: orchestrator/src/actor.rs:301: mailbox closed, shutting down orchestrator +2025-11-14T18:25:23.409956Z  INFO ThreadId(91) summit_finalizer::actor: finalizer/src/actor.rs:222: runtime terminated, shutting down finalizer: 0 +2025-11-14T18:25:23.409967Z  INFO ThreadId(55) alloy_pubsub::service: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-pubsub-1.0.30/src/service.rs:256: Pubsub service request channel closed. Shutting down. +2025-11-14T18:25:23.409978Z  INFO ThreadId(57) summit::engine: node/src/engine.rs:380: cancellation triggered, waiting for actors to finish +2025-11-14T18:25:23.409976Z  INFO ThreadId(46) summit_syncer::actor: syncer/src/actor.rs:611: handler closed, shutting down +2025-11-14T18:25:23.409988Z  INFO ThreadId(89) summit_application::actor: application/src/actor.rs:255: application received cancellation signal, exiting +2025-11-14T18:25:23.410007Z  INFO ThreadId(88) summit_syncer::actor: syncer/src/actor.rs:611: handler closed, shutting down +2025-11-14T18:25:23.410098Z  WARN ThreadId(91) summit_orchestrator::actor: orchestrator/src/actor.rs:301: mailbox closed, shutting down orchestrator +2025-11-14T18:25:23.410102Z  INFO ThreadId(89) alloy_pubsub::service: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-pubsub-1.0.30/src/service.rs:256: Pubsub service request channel closed. Shutting down. +2025-11-14T18:25:23.410157Z  INFO ThreadId(45) summit_application::actor: application/src/actor.rs:255: application received cancellation signal, exiting +2025-11-14T18:25:23.410160Z  WARN ThreadId(44) summit_orchestrator::actor: orchestrator/src/actor.rs:301: mailbox closed, shutting down orchestrator +2025-11-14T18:25:23.410181Z  INFO ThreadId(45) alloy_pubsub::service: /home/matthias/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/alloy-pubsub-1.0.30/src/service.rs:256: Pubsub service request channel closed. Shutting down. +RPC server stopped: 0 +2025-11-14T18:25:23.410277Z  INFO ThreadId(90) summit::engine: node/src/engine.rs:380: cancellation triggered, waiting for actors to finish +2025-11-14T18:25:23.410385Z  INFO ThreadId(43) summit::engine: node/src/engine.rs:380: cancellation triggered, waiting for actors to finish +Node index 0 thread joined successfully +Waiting for node index 1 to join... +Node index 1 thread joined successfully +Waiting for node index 2 to join... +Node index 2 thread joined successfully +Waiting for node index 3 to join... +Node index 3 thread joined successfully +All nodes shut down cleanly diff --git a/syncer/src/actor.rs b/syncer/src/actor.rs index 55473521..598dad7b 100644 --- a/syncer/src/actor.rs +++ b/syncer/src/actor.rs @@ -53,8 +53,6 @@ use summit_types::scheme::SchemeProvider; const LATEST_KEY: U64 = U64::new(0xFF); /// The first block height that is present in the [immutable::Archive] of finalized blocks. -const FIRST_HEIGHT_IN_ARCHIVE: u64 = 1; - /// A pending acknowledgement from the application for processing a block at the contained height/commitment. #[pin_project] struct PendingAck { @@ -263,7 +261,8 @@ impl< ) .await .expect("failed to initialize application metadata"); - let last_processed_height = *application_metadata.get(&LATEST_KEY).unwrap_or(&0); + // The last processed height is passed in and comes from the finalizer + //let last_processed_height = *application_metadata.get(&LATEST_KEY).unwrap_or(&0); // Create metrics #[cfg(feature = "prom")] @@ -280,7 +279,6 @@ impl< "Processed height of application", processed_height.clone(), ); - let _ = processed_height.try_set(last_processed_height); // Initialize mailbox let (sender, mailbox) = mpsc::channel(config.mailbox_size); @@ -295,7 +293,7 @@ impl< max_repair: config.max_repair, block_codec_config: config.block_codec_config, last_processed_round: Round::new(0, 0), - last_processed_height, + last_processed_height: 0, pending_ack: None.into(), tip: 0, block_subscriptions: BTreeMap::new(), @@ -326,7 +324,7 @@ impl< max_repair: config.max_repair, block_codec_config: config.block_codec_config, last_processed_round: Round::new(0, 0), - last_processed_height, + last_processed_height: 0, pending_ack: None.into(), tip: 0, block_subscriptions: BTreeMap::new(), @@ -349,6 +347,8 @@ impl< buffer: buffered::Mailbox, resolver: (mpsc::Receiver>, R), sync_height: u64, + sync_epoch: u64, + sync_view: u64, ) -> Handle<()> where R: Resolver>, @@ -356,7 +356,15 @@ impl< { spawn_cell!( self.context, - self.run(application, buffer, resolver, sync_height).await + self.run( + application, + buffer, + resolver, + sync_height, + sync_epoch, + sync_view + ) + .await ) } @@ -367,10 +375,21 @@ impl< mut buffer: buffered::Mailbox, (mut resolver_rx, mut resolver): (mpsc::Receiver>, R), sync_height: u64, + sync_epoch: u64, + sync_view: u64, ) where R: Resolver>, K: PublicKey, { + self.last_processed_height = sync_height; + self.last_processed_round = Round::new(sync_epoch, sync_view); + self.tip = sync_height; + + #[cfg(feature = "prom")] + { + let _ = self.processed_height.try_set(self.last_processed_height); + } + // Create a local pool for waiter futures. let mut waiters = AbortablePool::<(B::Commitment, B)>::default(); @@ -687,7 +706,6 @@ impl< } // Valid finalization received - debug!(height, "received finalization"); let _ = response.send(true); self.finalize( height, @@ -1069,7 +1087,6 @@ impl< // shrink the size of the gap if finalizations for the requests heights // exist. If not, we rely on the recursive digest fetch above. let gap_end = std::cmp::max(cursor.height(), gap_start); - debug!(gap_start, gap_end, "requesting any finalized blocks"); for height in gap_start..gap_end { if self.waiting_finalized.insert(height) { resolver.fetch(Request::::Finalized { height }).await; @@ -1084,9 +1101,11 @@ impl< fn identify_gaps(&self) -> Vec<(u64, u64)> { let mut remaining = self.max_repair.get(); let mut gaps = Vec::new(); - let mut previous_end = FIRST_HEIGHT_IN_ARCHIVE.saturating_sub(1); + // Start from last_processed_height since blocks up to that height are already processed + let mut previous_end = self.last_processed_height; + let ranges: Vec<_> = self.finalized_blocks.ranges().collect(); - for (range_start, range_end) in self.finalized_blocks.ranges() { + for (range_start, range_end) in ranges { if remaining == 0 { break; } @@ -1102,7 +1121,6 @@ impl< previous_end = range_end; } - gaps } } From d23728f56f6d4f101d1ba0b297db8b2553463a3e Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Fri, 14 Nov 2025 21:20:11 -0500 Subject: [PATCH 76/81] chore: set blocks per epoch to 10000 --- node/src/engine.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/src/engine.rs b/node/src/engine.rs index aa92c60c..f71613d8 100644 --- a/node/src/engine.rs +++ b/node/src/engine.rs @@ -61,7 +61,7 @@ pub const BLOCKS_PER_EPOCH: u64 = 50; #[cfg(debug_assertions)] pub const BLOCKS_PER_EPOCH: u64 = 10; #[cfg(all(not(debug_assertions), not(feature = "e2e")))] -const BLOCKS_PER_EPOCH: u64 = 1000; +const BLOCKS_PER_EPOCH: u64 = 10000; const VALIDATOR_MAX_WITHDRAWALS_PER_BLOCK: usize = 16; // From db63f79281babc9739bab95fe90b296aa61d6b0a Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Tue, 18 Nov 2025 16:01:47 +0000 Subject: [PATCH 77/81] feat: initialize sync variables from consensus state returned by finalizer --- finalizer/src/actor.rs | 4 +++- node/src/engine.rs | 11 ++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/finalizer/src/actor.rs b/finalizer/src/actor.rs index 918fbc09..a8961489 100644 --- a/finalizer/src/actor.rs +++ b/finalizer/src/actor.rs @@ -83,6 +83,7 @@ impl< cfg: FinalizerConfig, ) -> ( Self, + ConsensusState, FinalizerMailbox, Block>, ) { let (tx, rx) = mpsc::channel(cfg.mailbox_size); // todo(dalton) pull mailbox size from config @@ -126,7 +127,7 @@ impl< pending_height_notifys: BTreeMap::new(), epoch_num_of_blocks: cfg.epoch_num_of_blocks, db, - state, + state: state.clone(), validator_max_withdrawals_per_block: cfg.validator_max_withdrawals_per_block, genesis_hash: cfg.genesis_hash, protocol_version_digest: Sha256::hash(&cfg.protocol_version.to_le_bytes()), @@ -139,6 +140,7 @@ impl< _signer_marker: PhantomData, _variant_marker: PhantomData, }, + state, FinalizerMailbox::new(tx), ) } diff --git a/node/src/engine.rs b/node/src/engine.rs index f71613d8..15f90394 100644 --- a/node/src/engine.rs +++ b/node/src/engine.rs @@ -114,10 +114,6 @@ where let scheme_provider: SummitSchemeProvider = SummitSchemeProvider::new(private_scalar); - let sync_height = cfg.initial_state.latest_height; - let sync_epoch = cfg.initial_state.epoch; - let sync_view = cfg.initial_state.view; - let cancellation_token = CancellationToken::new(); // create application @@ -196,7 +192,7 @@ where ); // create finalizer - let (finalizer, finalizer_mailbox) = Finalizer::new( + let (finalizer, initial_state, finalizer_mailbox) = Finalizer::new( context.with_label("finalizer"), FinalizerConfig { mailbox_size: cfg.mailbox_size, @@ -219,6 +215,11 @@ where }, ) .await; + // Initialize the sync variables from the consensus state returned by the finalizer. + // This covers the case where the finalizer reads the consensus state from disk. + let sync_height = initial_state.latest_height; + let sync_epoch = initial_state.epoch; + let sync_view = initial_state.view; Self { context, From e6cc571d68f0f28d774636bd1d41bbfd69675034 Mon Sep 17 00:00:00 2001 From: Matthias Wright Date: Tue, 18 Nov 2025 16:32:31 +0000 Subject: [PATCH 78/81] fix: increment epoch after writing to disk --- finalizer/src/actor.rs | 47 +++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/finalizer/src/actor.rs b/finalizer/src/actor.rs index a8961489..c39a0cdf 100644 --- a/finalizer/src/actor.rs +++ b/finalizer/src/actor.rs @@ -357,10 +357,6 @@ impl< let mut epoch_change = false; // Store finalizes checkpoint to database if is_last_block_of_epoch(self.epoch_num_of_blocks, new_height) { - // Increment epoch - self.state.epoch += 1; - // Set the epoch genesis hash for the next epoch - self.state.epoch_genesis_hash = block.digest().0; if let Some(finalization) = finalization { // The finalized signatures should always be included on the last block @@ -432,25 +428,6 @@ impl< } } - // Create the list of validators for the new epoch - let active_validators = self.state.get_active_validators(); - let network_keys = active_validators - .iter() - .map(|(node_key, _)| node_key.clone()) - .collect(); - self.oracle.register(self.state.epoch, network_keys).await; - - // Send the new validator list to the orchestrator amd start the Simplex engine - // for the new epoch - let active_validators = self.state.get_active_validators(); - self.orchestrator_mailbox - .report(Message::Enter(EpochTransition { - epoch: self.state.epoch, - validator_keys: active_validators, - })) - .await; - epoch_change = true; - #[cfg(feature = "prom")] let db_operations_start = Instant::now(); // This pending checkpoint should always exist, because it was created at the previous height. @@ -470,6 +447,30 @@ impl< histogram!("database_operations_duration_millis").record(db_operations_duration); } + // Increment epoch + self.state.epoch += 1; + // Set the epoch genesis hash for the next epoch + self.state.epoch_genesis_hash = block.digest().0; + + // Create the list of validators for the new epoch + let active_validators = self.state.get_active_validators(); + let network_keys = active_validators + .iter() + .map(|(node_key, _)| node_key.clone()) + .collect(); + self.oracle.register(self.state.epoch, network_keys).await; + + // Send the new validator list to the orchestrator amd start the Simplex engine + // for the new epoch + let active_validators = self.state.get_active_validators(); + self.orchestrator_mailbox + .report(Message::Enter(EpochTransition { + epoch: self.state.epoch, + validator_keys: active_validators, + })) + .await; + epoch_change = true; + // Only clear the added and removed validators after saving the state to disk if !self.state.added_validators.is_empty() { self.state.added_validators.clear(); From b4835df7bd524012b8a71c033214c9efe81735bc Mon Sep 17 00:00:00 2001 From: cdrappi Date: Tue, 18 Nov 2025 12:06:57 -0500 Subject: [PATCH 79/81] add comment --- node/src/bin/genesis.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/src/bin/genesis.rs b/node/src/bin/genesis.rs index 4f3b6301..933e44b5 100644 --- a/node/src/bin/genesis.rs +++ b/node/src/bin/genesis.rs @@ -56,7 +56,7 @@ struct Args { /// output for genesis file #[arg(short = 'o', long)] out_dir: String, - /// Filepath with IP addresses + /// Filepath with IP addresses/public keys #[arg(short = 'v', long)] validators_path: String, } From 6af5d6a4c6b78ff9f36a28d7f9b9c5c6b68062dd Mon Sep 17 00:00:00 2001 From: cdrappi Date: Tue, 18 Nov 2025 13:40:39 -0500 Subject: [PATCH 80/81] update genesis rpc --- example_genesis.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example_genesis.toml b/example_genesis.toml index aa244bc0..6c747043 100644 --- a/example_genesis.toml +++ b/example_genesis.toml @@ -1,4 +1,4 @@ -eth_genesis_hash = "0x655cc1ecc77fe1eab4b1e62a1f461b7fddc9b06109b5ab3e9dc68c144b30c773" +eth_genesis_hash = "0x93068b65464eeee04a47a3b16b3123d05a5d83882032525bdb5e297d654857f0" leader_timeout_ms = 2000 notarization_timeout_ms = 4000 nullify_timeout_ms = 4000 From fdcfa4a7ec540f12f64b5bc4d73306ee1f14d634 Mon Sep 17 00:00:00 2001 From: cdrappi Date: Tue, 18 Nov 2025 14:05:34 -0500 Subject: [PATCH 81/81] ok --- Cargo.lock | 1 + node/src/args.rs | 19 +++++++++++++----- rpc/Cargo.toml | 1 + rpc/src/lib.rs | 15 +++++++++----- rpc/src/routes.rs | 51 ++++++++++++++++++++++++++++++++++++++--------- 5 files changed, 68 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 61d8e913..c0864266 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5677,6 +5677,7 @@ dependencies = [ "ethereum_ssz", "futures", "serde", + "serde_json", "summit-finalizer", "summit-types", "tokio", diff --git a/node/src/args.rs b/node/src/args.rs index 9e6b60e5..b694c48d 100644 --- a/node/src/args.rs +++ b/node/src/args.rs @@ -192,15 +192,18 @@ impl Command { // use the context async move to spawn a new runtime let genesis_path = flags.genesis_path.clone(); - let key_path = flags.key_path.clone(); + let key_store_path = flags.key_store_path.clone(); let rpc_port = flags.rpc_port; let _rpc_handle = context .with_label("rpc_genesis") .spawn(move |_context| async move { let genesis_sender = Command::check_sender(genesis_path, genesis_tx); + let key_path = format!("{}/consensus_key.pem", key_store_path); + let share_path = format!("{}/share.pem", key_store_path); if let Err(e) = start_rpc_server_for_genesis( genesis_sender, key_path, + share_path, rpc_port, cloned_token, ) @@ -390,8 +393,10 @@ impl Command { let rpc_port = flags.rpc_port; let stop_signal = context.stopped(); let rpc_handle = context.with_label("rpc").spawn(move |_context| async move { + let key_path = format!("{}/consensus_key.pem", key_store_path); + let share_path = format!("{}/share.pem", key_store_path); if let Err(e) = - start_rpc_server(finalizer_mailbox, key_store_path, rpc_port, stop_signal).await + start_rpc_server(finalizer_mailbox, key_path, share_path, rpc_port, stop_signal).await { error!("RPC server failed: {}", e); } @@ -420,13 +425,15 @@ pub fn run_node_local( // use the context async move to spawn a new runtime let rpc_port = flags.rpc_port; let genesis_path = flags.genesis_path.clone(); - let key_path = flags.key_path.clone(); + let key_store_path = flags.key_store_path.clone(); let _rpc_handle = context .with_label("rpc_genesis") .spawn(move |_context| async move { let genesis_sender = Command::check_sender(genesis_path, genesis_tx); + let key_path = format!("{}/consensus_key.pem", key_store_path); + let share_path = format!("{}/share.pem", key_store_path); if let Err(e) = - start_rpc_server_for_genesis(genesis_sender, key_path, rpc_port, cloned_token) + start_rpc_server_for_genesis(genesis_sender, key_path, share_path, rpc_port, cloned_token) .await { error!("RPC server failed: {}", e); @@ -591,8 +598,10 @@ pub fn run_node_local( let rpc_port = flags.rpc_port; let stop_signal = context.stopped(); let rpc_handle = context.with_label("rpc").spawn(move |_context| async move { + let key_path = format!("{}/consensus_key.pem", key_store_path); + let share_path = format!("{}/share.pem", key_store_path); if let Err(e) = - start_rpc_server(finalizer_mailbox, key_store_path, rpc_port, stop_signal).await + start_rpc_server(finalizer_mailbox, key_path, share_path, rpc_port, stop_signal).await { error!("RPC server failed: {}", e); } diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index aa85758b..32b9d189 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -23,4 +23,5 @@ commonware-runtime = { workspace = true } ethereum_ssz.workspace = true dirs = "5.0.1" serde = { workspace = true } +serde_json = { workspace = true } tracing.workspace = true \ No newline at end of file diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 5f67e8aa..456d61d2 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -12,13 +12,15 @@ use tokio_util::sync::CancellationToken; pub struct RpcState { key_path: String, + share_path: String, finalizer_mailbox: FinalizerMailbox, } impl RpcState { - pub fn new(key_path: String, finalizer_mailbox: FinalizerMailbox) -> Self { + pub fn new(key_path: String, share_path: String, finalizer_mailbox: FinalizerMailbox) -> Self { Self { key_path, + share_path, finalizer_mailbox, } } @@ -27,10 +29,11 @@ impl RpcState { pub async fn start_rpc_server( finalizer_mailbox: FinalizerMailbox, key_path: String, + share_path: String, port: u16, stop_signal: Signal, ) -> anyhow::Result<()> { - let state = RpcState::new(key_path, finalizer_mailbox); + let state = RpcState::new(key_path, share_path, finalizer_mailbox); let server = RpcRoutes::mount(state); @@ -64,21 +67,23 @@ impl PathSender { pub struct GenesisRpcState { genesis: PathSender, key_path: String, + share_path: String, } impl GenesisRpcState { - pub fn new(genesis: PathSender, key_path: String) -> Self { - Self { genesis, key_path } + pub fn new(genesis: PathSender, key_path: String, share_path: String) -> Self { + Self { genesis, key_path, share_path } } } pub async fn start_rpc_server_for_genesis( genesis: PathSender, key_path: String, + share_path: String, port: u16, cancel_token: CancellationToken, ) -> anyhow::Result<()> { - let state = GenesisRpcState::new(genesis, key_path); + let state = GenesisRpcState::new(genesis, key_path, share_path); let server = RpcRoutes::mount_for_genesis(state); diff --git a/rpc/src/routes.rs b/rpc/src/routes.rs index 6a690ff1..96a8f515 100644 --- a/rpc/src/routes.rs +++ b/rpc/src/routes.rs @@ -9,13 +9,20 @@ use commonware_codec::DecodeExt as _; use commonware_consensus::Block as ConsensusBlock; use commonware_consensus::simplex::signing_scheme::Scheme; use commonware_cryptography::{Committable, Signer}; +use commonware_cryptography::bls12381::primitives::{group, variant::MinPk}; use commonware_utils::{from_hex_formatted, hex}; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; use ssz::Encode; use summit_types::{PrivateKey, PublicKey, utils::get_expanded_path}; use crate::{GenesisRpcState, PathSender, RpcState}; +#[derive(Serialize)] +struct PublicKeysResponse { + consensus: String, + share: String, +} + #[derive(Deserialize)] struct ValidatorBalanceQuery { public_key: String, @@ -32,7 +39,7 @@ impl RpcRoutes { Router::new() .route("/health", get(Self::handle_health_check)) - .route("/get_public_key", get(Self::handle_get_pub_key::)) + .route("/get_public_keys", get(Self::handle_get_pub_keys::)) .route("/get_checkpoint", get(Self::handle_get_checkpoint::)) .route( "/get_latest_height", @@ -51,7 +58,7 @@ impl RpcRoutes { Router::new() .route("/health", get(Self::handle_health_check)) - .route("/get_public_key", get(Self::handle_get_pub_key_genesis)) + .route("/get_public_keys", get(Self::handle_get_pub_keys_genesis)) .route("/send_genesis", post(Self::handle_send_genesis)) .with_state(state) } @@ -60,20 +67,32 @@ impl RpcRoutes { "Ok" } - async fn handle_get_pub_key( + async fn handle_get_pub_keys( State(state): State>>, ) -> Result { - let private_key = Self::read_ed_key_from_path(&state.key_path)?; + let consensus_key = Self::read_ed_key_from_path(&state.key_path)?; + let share_pubkey = Self::read_share_public_key_from_path(&state.share_path)?; - Ok(private_key.public_key().to_string()) + let response = PublicKeysResponse { + consensus: consensus_key.public_key().to_string(), + share: share_pubkey, + }; + + serde_json::to_string(&response).map_err(|e| format!("Failed to serialize response: {}", e)) } - async fn handle_get_pub_key_genesis( + async fn handle_get_pub_keys_genesis( State(state): State>, ) -> Result { - let private_key = Self::read_ed_key_from_path(&state.key_path)?; + let consensus_key = Self::read_ed_key_from_path(&state.key_path)?; + let share_pubkey = Self::read_share_public_key_from_path(&state.share_path)?; + + let response = PublicKeysResponse { + consensus: consensus_key.public_key().to_string(), + share: share_pubkey, + }; - Ok(private_key.public_key().to_string()) + serde_json::to_string(&response).map_err(|e| format!("Failed to serialize response: {}", e)) } fn read_ed_key_from_path(key_path: &str) -> Result { @@ -87,6 +106,20 @@ impl RpcRoutes { Ok(pk) } + fn read_share_public_key_from_path(share_path: &str) -> Result { + let path = get_expanded_path(share_path).map_err(|_| "unable to get share_path")?; + let encoded_share = + std::fs::read_to_string(path).map_err(|_| "Failed to read share file")?; + + let share_bytes = from_hex_formatted(&encoded_share).ok_or("Invalid hex format for share")?; + let share = group::Share::decode(&*share_bytes).map_err(|_| "unable to decode share")?; + + // Get the public key from the share and encode it as hex + let public_key: group::G1 = share.public::(); + use commonware_codec::Encode as _; + Ok(hex(&public_key.encode())) + } + async fn handle_get_checkpoint( State(state): State>>, ) -> Result {