mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat: CanonStateNotification for commit and reorg (#2156)
This commit is contained in:
@ -20,6 +20,7 @@ use reth_primitives::{
|
||||
BlockBody, BlockHash, BlockHashOrNumber, BlockNumber, ChainSpec, Header, SealedBlock,
|
||||
SealedHeader, H256, U256,
|
||||
};
|
||||
use reth_provider::CanonStateNotificationSender;
|
||||
use reth_transaction_pool::TransactionPool;
|
||||
use std::{collections::HashMap, sync::Arc};
|
||||
use tokio::sync::{mpsc::UnboundedSender, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
@ -31,7 +32,6 @@ mod task;
|
||||
|
||||
pub use crate::client::AutoSealClient;
|
||||
pub use mode::{FixedBlockTimeMiner, MiningMode, ReadyTransactionMiner};
|
||||
use reth_interfaces::events::NewBlockNotificationSink;
|
||||
pub use task::MiningTask;
|
||||
|
||||
/// A consensus implementation intended for local development and testing purposes.
|
||||
@ -83,7 +83,7 @@ pub struct AutoSealBuilder<Client, Pool> {
|
||||
mode: MiningMode,
|
||||
storage: Storage,
|
||||
to_engine: UnboundedSender<BeaconEngineMessage>,
|
||||
new_block_notification_sender: NewBlockNotificationSink,
|
||||
canon_state_notification: CanonStateNotificationSender,
|
||||
}
|
||||
|
||||
// === impl AutoSealBuilder ===
|
||||
@ -95,7 +95,7 @@ impl<Client, Pool: TransactionPool> AutoSealBuilder<Client, Pool> {
|
||||
client: Client,
|
||||
pool: Pool,
|
||||
to_engine: UnboundedSender<BeaconEngineMessage>,
|
||||
new_block_notification_sender: NewBlockNotificationSink,
|
||||
canon_state_notification: CanonStateNotificationSender,
|
||||
) -> Self {
|
||||
let mode = MiningMode::interval(std::time::Duration::from_secs(1));
|
||||
Self {
|
||||
@ -105,7 +105,7 @@ impl<Client, Pool: TransactionPool> AutoSealBuilder<Client, Pool> {
|
||||
pool,
|
||||
mode,
|
||||
to_engine,
|
||||
new_block_notification_sender,
|
||||
canon_state_notification,
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,21 +117,14 @@ impl<Client, Pool: TransactionPool> AutoSealBuilder<Client, Pool> {
|
||||
|
||||
/// Consumes the type and returns all components
|
||||
pub fn build(self) -> (AutoSealConsensus, AutoSealClient, MiningTask<Client, Pool>) {
|
||||
let Self {
|
||||
client,
|
||||
consensus,
|
||||
pool,
|
||||
mode,
|
||||
storage,
|
||||
to_engine,
|
||||
new_block_notification_sender,
|
||||
} = self;
|
||||
let Self { client, consensus, pool, mode, storage, to_engine, canon_state_notification } =
|
||||
self;
|
||||
let auto_client = AutoSealClient::new(storage.clone());
|
||||
let task = MiningTask::new(
|
||||
Arc::clone(&consensus.chain_spec),
|
||||
mode,
|
||||
to_engine,
|
||||
new_block_notification_sender,
|
||||
canon_state_notification,
|
||||
storage,
|
||||
client,
|
||||
pool,
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
use crate::{mode::MiningMode, Storage};
|
||||
use futures_util::{future::BoxFuture, FutureExt, StreamExt};
|
||||
use reth_beacon_consensus::BeaconEngineMessage;
|
||||
use reth_interfaces::{consensus::ForkchoiceState, events::NewBlockNotificationSink};
|
||||
use reth_interfaces::consensus::ForkchoiceState;
|
||||
use reth_primitives::{
|
||||
constants::{EMPTY_RECEIPTS, EMPTY_TRANSACTIONS},
|
||||
proofs, Block, BlockBody, ChainSpec, Header, IntoRecoveredTransaction, ReceiptWithBloom,
|
||||
EMPTY_OMMER_ROOT, U256,
|
||||
SealedBlockWithSenders, EMPTY_OMMER_ROOT, U256,
|
||||
};
|
||||
use reth_provider::StateProviderFactory;
|
||||
use reth_provider::{CanonStateNotificationSender, Chain, StateProviderFactory};
|
||||
use reth_revm::{
|
||||
database::{State, SubState},
|
||||
executor::Executor,
|
||||
@ -45,7 +45,7 @@ pub struct MiningTask<Client, Pool: TransactionPool> {
|
||||
/// TODO: ideally this would just be a sender of hashes
|
||||
to_engine: UnboundedSender<BeaconEngineMessage>,
|
||||
/// Used to notify consumers of new blocks
|
||||
new_block_notification_sender: NewBlockNotificationSink,
|
||||
canon_state_notification: CanonStateNotificationSender,
|
||||
/// The pipeline events to listen on
|
||||
pipe_line_events: Option<UnboundedReceiverStream<PipelineEvent>>,
|
||||
}
|
||||
@ -58,7 +58,7 @@ impl<Client, Pool: TransactionPool> MiningTask<Client, Pool> {
|
||||
chain_spec: Arc<ChainSpec>,
|
||||
miner: MiningMode,
|
||||
to_engine: UnboundedSender<BeaconEngineMessage>,
|
||||
new_block_notification_sender: NewBlockNotificationSink,
|
||||
canon_state_notification: CanonStateNotificationSender,
|
||||
storage: Storage,
|
||||
client: Client,
|
||||
pool: Pool,
|
||||
@ -71,7 +71,7 @@ impl<Client, Pool: TransactionPool> MiningTask<Client, Pool> {
|
||||
storage,
|
||||
pool,
|
||||
to_engine,
|
||||
new_block_notification_sender,
|
||||
canon_state_notification,
|
||||
queued: Default::default(),
|
||||
pipe_line_events: None,
|
||||
}
|
||||
@ -116,7 +116,7 @@ where
|
||||
let chain_spec = Arc::clone(&this.chain_spec);
|
||||
let pool = this.pool.clone();
|
||||
let mut events = this.pipe_line_events.take();
|
||||
let new_block_notification_sender = this.new_block_notification_sender.clone();
|
||||
let canon_state_notification = this.canon_state_notification.clone();
|
||||
|
||||
// Create the mining future that creates a block, notifies the engine that drives
|
||||
// the pipeline
|
||||
@ -165,24 +165,30 @@ where
|
||||
|
||||
trace!(target: "consensus::auto", transactions=?&block.body, "executing transactions");
|
||||
|
||||
match executor.execute_transactions(&block, U256::ZERO, None) {
|
||||
Ok((res, gas_used)) => {
|
||||
let senders = block
|
||||
.body
|
||||
.iter()
|
||||
.map(|tx| tx.recover_signer())
|
||||
.collect::<Option<Vec<_>>>()?;
|
||||
|
||||
match executor.execute_transactions(&block, U256::ZERO, Some(senders.clone())) {
|
||||
Ok((post_state, gas_used)) => {
|
||||
let Block { mut header, body, .. } = block;
|
||||
|
||||
// clear all transactions from pool
|
||||
pool.remove_transactions(body.iter().map(|tx| tx.hash));
|
||||
|
||||
header.receipts_root = if res.receipts().is_empty() {
|
||||
header.receipts_root = if post_state.receipts().is_empty() {
|
||||
EMPTY_RECEIPTS
|
||||
} else {
|
||||
let receipts_with_bloom = res
|
||||
let receipts_with_bloom = post_state
|
||||
.receipts()
|
||||
.iter()
|
||||
.map(|r| r.clone().into())
|
||||
.collect::<Vec<ReceiptWithBloom>>();
|
||||
proofs::calculate_receipt_root(receipts_with_bloom.iter())
|
||||
};
|
||||
|
||||
let transactions = body.clone();
|
||||
let body =
|
||||
BlockBody { transactions: body, ommers: vec![], withdrawals: None };
|
||||
header.gas_used = gas_used;
|
||||
@ -223,11 +229,25 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
let header = header.seal_slow();
|
||||
debug!(target: "consensus::auto", header=?header.hash(), "sending block notification");
|
||||
// seal the block
|
||||
let block = Block {
|
||||
header,
|
||||
body: transactions,
|
||||
ommers: vec![],
|
||||
withdrawals: None,
|
||||
};
|
||||
let sealed_block = block.seal_slow();
|
||||
let sealed_block_with_senders =
|
||||
SealedBlockWithSenders::new(sealed_block, senders)
|
||||
.expect("senders are valid");
|
||||
debug!(target: "consensus::auto", header=?sealed_block_with_senders.hash(), "sending block notification");
|
||||
|
||||
let chain =
|
||||
Arc::new(Chain::new(vec![(sealed_block_with_senders, post_state)]));
|
||||
|
||||
// send block notification
|
||||
let _ = new_block_notification_sender.send(Arc::new(header));
|
||||
let _ = canon_state_notification
|
||||
.send(reth_provider::CanonStateNotification::Commit { new: chain });
|
||||
}
|
||||
Err(err) => {
|
||||
warn!(target: "consensus::auto", ?err, "failed to execute block")
|
||||
|
||||
Reference in New Issue
Block a user