mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 02:49:55 +00:00
feat: Custom TransactionSigned
Like OpTransactionSigned, introduce a new tx type. Not a trivial change but might be beneficial for potential system tx changes e.g., in case it's separated into another tx type
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -8738,6 +8738,7 @@ dependencies = [
|
|||||||
"reth-cli",
|
"reth-cli",
|
||||||
"reth-cli-commands",
|
"reth-cli-commands",
|
||||||
"reth-cli-util",
|
"reth-cli-util",
|
||||||
|
"reth-codecs",
|
||||||
"reth-db",
|
"reth-db",
|
||||||
"reth-discv4",
|
"reth-discv4",
|
||||||
"reth-engine-primitives",
|
"reth-engine-primitives",
|
||||||
@ -8763,6 +8764,7 @@ dependencies = [
|
|||||||
"reth-rpc-engine-api",
|
"reth-rpc-engine-api",
|
||||||
"reth-rpc-eth-api",
|
"reth-rpc-eth-api",
|
||||||
"reth-tracing",
|
"reth-tracing",
|
||||||
|
"reth-transaction-pool",
|
||||||
"reth-trie-common",
|
"reth-trie-common",
|
||||||
"reth-trie-db",
|
"reth-trie-db",
|
||||||
"revm",
|
"revm",
|
||||||
|
|||||||
@ -45,6 +45,8 @@ reth-rpc-engine-api = { path = "../reth/crates/rpc/rpc-engine-api" }
|
|||||||
reth-tracing = { path = "../reth/crates/tracing" }
|
reth-tracing = { path = "../reth/crates/tracing" }
|
||||||
reth-trie-common = { path = "../reth/crates/trie/common", default-features = false }
|
reth-trie-common = { path = "../reth/crates/trie/common", default-features = false }
|
||||||
reth-trie-db = { path = "../reth/crates/trie/db" }
|
reth-trie-db = { path = "../reth/crates/trie/db" }
|
||||||
|
reth-codecs = { path = "../reth/crates/storage/codecs" }
|
||||||
|
reth-transaction-pool = { path = "../reth/crates/transaction-pool" }
|
||||||
revm = { version = "24.0.1" }
|
revm = { version = "24.0.1" }
|
||||||
|
|
||||||
# alloy dependencies
|
# alloy dependencies
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
use alloy_consensus::Transaction as AlloyTransaction;
|
use crate::node::primitives::TransactionSigned;
|
||||||
use alloy_primitives::address;
|
use alloy_consensus::Transaction as _;
|
||||||
use alloy_rpc_types::AccessList;
|
use alloy_rpc_types::AccessList;
|
||||||
use auto_impl::auto_impl;
|
use auto_impl::auto_impl;
|
||||||
use reth_evm::{FromRecoveredTx, FromTxWithEncoded, IntoTxEnv, TransactionEnv};
|
use reth_evm::{FromRecoveredTx, FromTxWithEncoded, IntoTxEnv, TransactionEnv};
|
||||||
use reth_primitives::TransactionSigned;
|
use reth_primitives_traits::SignerRecoverable;
|
||||||
use revm::{
|
use revm::{
|
||||||
context::TxEnv,
|
context::TxEnv,
|
||||||
context_interface::transaction::Transaction,
|
context_interface::transaction::Transaction,
|
||||||
@ -118,21 +118,10 @@ impl<T: revm::context::Transaction> IntoTxEnv<Self> for HlTxEnv<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn s_to_address(s: U256) -> Address {
|
|
||||||
if s == U256::ONE {
|
|
||||||
return address!("2222222222222222222222222222222222222222");
|
|
||||||
}
|
|
||||||
let mut buf = [0u8; 20];
|
|
||||||
buf.copy_from_slice(&s.to_be_bytes::<32>()[12..]);
|
|
||||||
Address::from_slice(&buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromRecoveredTx<TransactionSigned> for HlTxEnv<TxEnv> {
|
impl FromRecoveredTx<TransactionSigned> for HlTxEnv<TxEnv> {
|
||||||
fn from_recovered_tx(tx: &TransactionSigned, sender: Address) -> Self {
|
fn from_recovered_tx(tx: &TransactionSigned, sender: Address) -> Self {
|
||||||
if let Some(gas_price) = tx.gas_price() {
|
if tx.gas_price().is_some() && tx.gas_price().unwrap() == 0 {
|
||||||
if gas_price == 0 {
|
return Self::new(TxEnv::from_recovered_tx(tx, tx.recover_signer().unwrap()));
|
||||||
return Self::new(TxEnv::from_recovered_tx(tx, s_to_address(tx.signature().s())));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::new(TxEnv::from_recovered_tx(tx, sender))
|
Self::new(TxEnv::from_recovered_tx(tx, sender))
|
||||||
@ -141,7 +130,7 @@ impl FromRecoveredTx<TransactionSigned> for HlTxEnv<TxEnv> {
|
|||||||
|
|
||||||
impl FromTxWithEncoded<TransactionSigned> for HlTxEnv<TxEnv> {
|
impl FromTxWithEncoded<TransactionSigned> for HlTxEnv<TxEnv> {
|
||||||
fn from_encoded_tx(tx: &TransactionSigned, sender: Address, _encoded: Bytes) -> Self {
|
fn from_encoded_tx(tx: &TransactionSigned, sender: Address, _encoded: Bytes) -> Self {
|
||||||
let base = match tx.clone().into_typed_transaction() {
|
let base = match tx.clone().0.into_typed_transaction() {
|
||||||
reth_primitives::Transaction::Legacy(tx) => TxEnv::from_recovered_tx(&tx, sender),
|
reth_primitives::Transaction::Legacy(tx) => TxEnv::from_recovered_tx(&tx, sender),
|
||||||
reth_primitives::Transaction::Eip2930(tx) => TxEnv::from_recovered_tx(&tx, sender),
|
reth_primitives::Transaction::Eip2930(tx) => TxEnv::from_recovered_tx(&tx, sender),
|
||||||
reth_primitives::Transaction::Eip1559(tx) => TxEnv::from_recovered_tx(&tx, sender),
|
reth_primitives::Transaction::Eip1559(tx) => TxEnv::from_recovered_tx(&tx, sender),
|
||||||
|
|||||||
@ -1,6 +1,4 @@
|
|||||||
use crate::{hardforks::HlHardforks, node::HlNode, HlBlock, HlBlockBody, HlPrimitives};
|
use crate::{hardforks::HlHardforks, node::HlNode, HlBlock, HlBlockBody, HlPrimitives};
|
||||||
use alloy_consensus::BlockHeader as _;
|
|
||||||
use alloy_eips::eip7685::Requests;
|
|
||||||
use reth::{
|
use reth::{
|
||||||
api::FullNodeTypes,
|
api::FullNodeTypes,
|
||||||
beacon_consensus::EthBeaconConsensus,
|
beacon_consensus::EthBeaconConsensus,
|
||||||
@ -10,11 +8,9 @@ use reth::{
|
|||||||
validate_against_parent_4844, validate_against_parent_hash_number,
|
validate_against_parent_4844, validate_against_parent_hash_number,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use reth_chainspec::{EthChainSpec, EthereumHardforks};
|
use reth_chainspec::EthChainSpec;
|
||||||
use reth_primitives::{
|
use reth_primitives::{Receipt, RecoveredBlock, SealedBlock, SealedHeader};
|
||||||
gas_spent_by_transactions, GotExpected, Receipt, RecoveredBlock, SealedBlock, SealedHeader,
|
use reth_primitives_traits::BlockHeader;
|
||||||
};
|
|
||||||
use reth_primitives_traits::{Block, BlockHeader, Receipt as ReceiptTrait};
|
|
||||||
use reth_provider::BlockExecutionResult;
|
use reth_provider::BlockExecutionResult;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
@ -67,11 +63,8 @@ pub fn validate_against_parent_timestamp<H: BlockHeader>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<ChainSpec: EthChainSpec + HlHardforks> HeaderValidator for HlConsensus<ChainSpec> {
|
impl<ChainSpec: EthChainSpec + HlHardforks> HeaderValidator for HlConsensus<ChainSpec> {
|
||||||
fn validate_header(&self, _header: &SealedHeader) -> Result<(), ConsensusError> {
|
fn validate_header(&self, header: &SealedHeader) -> Result<(), ConsensusError> {
|
||||||
// TODO: doesn't work because of extradata check
|
self.inner.validate_header(header)
|
||||||
// self.inner.validate_header(header)
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_header_against_parent(
|
fn validate_header_against_parent(
|
||||||
@ -142,71 +135,17 @@ impl<ChainSpec: EthChainSpec + HlHardforks> Consensus<HlBlock> for HlConsensus<C
|
|||||||
|
|
||||||
mod reth_copy;
|
mod reth_copy;
|
||||||
|
|
||||||
pub fn validate_block_post_execution<B, R, ChainSpec>(
|
|
||||||
block: &RecoveredBlock<B>,
|
|
||||||
chain_spec: &ChainSpec,
|
|
||||||
receipts: &[R],
|
|
||||||
requests: &Requests,
|
|
||||||
) -> Result<(), ConsensusError>
|
|
||||||
where
|
|
||||||
B: Block,
|
|
||||||
R: ReceiptTrait,
|
|
||||||
ChainSpec: EthereumHardforks,
|
|
||||||
{
|
|
||||||
use reth_copy::verify_receipts;
|
|
||||||
// Copy of reth's validate_block_post_execution
|
|
||||||
// Differences:
|
|
||||||
// - Filter out system transactions for receipts check
|
|
||||||
|
|
||||||
// Check if gas used matches the value set in header.
|
|
||||||
let cumulative_gas_used =
|
|
||||||
receipts.last().map(|receipt| receipt.cumulative_gas_used()).unwrap_or(0);
|
|
||||||
if block.header().gas_used() != cumulative_gas_used {
|
|
||||||
return Err(ConsensusError::BlockGasUsed {
|
|
||||||
gas: GotExpected { got: cumulative_gas_used, expected: block.header().gas_used() },
|
|
||||||
gas_spent_by_tx: gas_spent_by_transactions(receipts),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Before Byzantium, receipts contained state root that would mean that expensive
|
|
||||||
// operation as hashing that is required for state root got calculated in every
|
|
||||||
// transaction This was replaced with is_success flag.
|
|
||||||
// See more about EIP here: https://eips.ethereum.org/EIPS/eip-658
|
|
||||||
if chain_spec.is_byzantium_active_at_block(block.header().number()) {
|
|
||||||
let receipts_for_root =
|
|
||||||
receipts.iter().filter(|&r| r.cumulative_gas_used() != 0).cloned().collect::<Vec<_>>();
|
|
||||||
if let Err(error) = verify_receipts(
|
|
||||||
block.header().receipts_root(),
|
|
||||||
block.header().logs_bloom(),
|
|
||||||
&receipts_for_root,
|
|
||||||
) {
|
|
||||||
tracing::debug!(%error, ?receipts, "receipts verification failed");
|
|
||||||
return Err(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate that the header requests hash matches the calculated requests hash
|
|
||||||
if chain_spec.is_prague_active_at_timestamp(block.header().timestamp()) {
|
|
||||||
let Some(header_requests_hash) = block.header().requests_hash() else {
|
|
||||||
return Err(ConsensusError::RequestsHashMissing);
|
|
||||||
};
|
|
||||||
let requests_hash = requests.requests_hash();
|
|
||||||
if requests_hash != header_requests_hash {
|
|
||||||
return Err(ConsensusError::BodyRequestsHashDiff(
|
|
||||||
GotExpected::new(requests_hash, header_requests_hash).into(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<ChainSpec: EthChainSpec + HlHardforks> FullConsensus<HlPrimitives> for HlConsensus<ChainSpec> {
|
impl<ChainSpec: EthChainSpec + HlHardforks> FullConsensus<HlPrimitives> for HlConsensus<ChainSpec> {
|
||||||
fn validate_block_post_execution(
|
fn validate_block_post_execution(
|
||||||
&self,
|
&self,
|
||||||
block: &RecoveredBlock<HlBlock>,
|
block: &RecoveredBlock<HlBlock>,
|
||||||
result: &BlockExecutionResult<Receipt>,
|
result: &BlockExecutionResult<Receipt>,
|
||||||
) -> Result<(), ConsensusError> {
|
) -> Result<(), ConsensusError> {
|
||||||
validate_block_post_execution(block, &self.chain_spec, &result.receipts, &result.requests)
|
reth_copy::validate_block_post_execution(
|
||||||
|
block,
|
||||||
|
&self.chain_spec,
|
||||||
|
&result.receipts,
|
||||||
|
&result.requests,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,14 +1,74 @@
|
|||||||
//! Copy of reth codebase.
|
//! Copy of reth codebase.
|
||||||
|
|
||||||
use alloy_consensus::{proofs::calculate_receipt_root, TxReceipt};
|
use alloy_consensus::{proofs::calculate_receipt_root, BlockHeader, TxReceipt};
|
||||||
|
use alloy_eips::eip7685::Requests;
|
||||||
use alloy_primitives::{Bloom, B256};
|
use alloy_primitives::{Bloom, B256};
|
||||||
use reth::consensus::ConsensusError;
|
use reth::consensus::ConsensusError;
|
||||||
use reth_primitives::GotExpected;
|
use reth_chainspec::EthereumHardforks;
|
||||||
use reth_primitives_traits::Receipt;
|
use reth_primitives::{gas_spent_by_transactions, GotExpected, RecoveredBlock};
|
||||||
|
use reth_primitives_traits::{Block, Receipt as ReceiptTrait};
|
||||||
|
|
||||||
|
pub fn validate_block_post_execution<B, R, ChainSpec>(
|
||||||
|
block: &RecoveredBlock<B>,
|
||||||
|
chain_spec: &ChainSpec,
|
||||||
|
receipts: &[R],
|
||||||
|
requests: &Requests,
|
||||||
|
) -> Result<(), ConsensusError>
|
||||||
|
where
|
||||||
|
B: Block,
|
||||||
|
R: ReceiptTrait,
|
||||||
|
ChainSpec: EthereumHardforks,
|
||||||
|
{
|
||||||
|
// Copy of reth's validate_block_post_execution
|
||||||
|
// Differences:
|
||||||
|
// - Filter out system transactions for receipts check
|
||||||
|
|
||||||
|
// Check if gas used matches the value set in header.
|
||||||
|
let cumulative_gas_used =
|
||||||
|
receipts.last().map(|receipt| receipt.cumulative_gas_used()).unwrap_or(0);
|
||||||
|
if block.header().gas_used() != cumulative_gas_used {
|
||||||
|
return Err(ConsensusError::BlockGasUsed {
|
||||||
|
gas: GotExpected { got: cumulative_gas_used, expected: block.header().gas_used() },
|
||||||
|
gas_spent_by_tx: gas_spent_by_transactions(receipts),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Before Byzantium, receipts contained state root that would mean that expensive
|
||||||
|
// operation as hashing that is required for state root got calculated in every
|
||||||
|
// transaction This was replaced with is_success flag.
|
||||||
|
// See more about EIP here: https://eips.ethereum.org/EIPS/eip-658
|
||||||
|
if chain_spec.is_byzantium_active_at_block(block.header().number()) {
|
||||||
|
let receipts_for_root =
|
||||||
|
receipts.iter().filter(|&r| r.cumulative_gas_used() != 0).cloned().collect::<Vec<_>>();
|
||||||
|
if let Err(error) = verify_receipts(
|
||||||
|
block.header().receipts_root(),
|
||||||
|
block.header().logs_bloom(),
|
||||||
|
&receipts_for_root,
|
||||||
|
) {
|
||||||
|
tracing::debug!(%error, ?receipts, "receipts verification failed");
|
||||||
|
return Err(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate that the header requests hash matches the calculated requests hash
|
||||||
|
if chain_spec.is_prague_active_at_timestamp(block.header().timestamp()) {
|
||||||
|
let Some(header_requests_hash) = block.header().requests_hash() else {
|
||||||
|
return Err(ConsensusError::RequestsHashMissing);
|
||||||
|
};
|
||||||
|
let requests_hash = requests.requests_hash();
|
||||||
|
if requests_hash != header_requests_hash {
|
||||||
|
return Err(ConsensusError::BodyRequestsHashDiff(
|
||||||
|
GotExpected::new(requests_hash, header_requests_hash).into(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Calculate the receipts root, and compare it against the expected receipts root and logs
|
/// Calculate the receipts root, and compare it against the expected receipts root and logs
|
||||||
/// bloom.
|
/// bloom.
|
||||||
pub(super) fn verify_receipts<R: Receipt>(
|
pub(super) fn verify_receipts<R: ReceiptTrait>(
|
||||||
expected_receipts_root: B256,
|
expected_receipts_root: B256,
|
||||||
expected_logs_bloom: Bloom,
|
expected_logs_bloom: Bloom,
|
||||||
receipts: &[R],
|
receipts: &[R],
|
||||||
|
|||||||
@ -3,7 +3,11 @@ use crate::{
|
|||||||
chainspec::HlChainSpec,
|
chainspec::HlChainSpec,
|
||||||
evm::{spec::HlSpecId, transaction::HlTxEnv},
|
evm::{spec::HlSpecId, transaction::HlTxEnv},
|
||||||
hardforks::HlHardforks,
|
hardforks::HlHardforks,
|
||||||
node::{evm::executor::is_system_transaction, types::ReadPrecompileMap},
|
node::{
|
||||||
|
evm::{executor::is_system_transaction, receipt_builder::RethReceiptBuilder},
|
||||||
|
primitives::{BlockBody, TransactionSigned},
|
||||||
|
types::ReadPrecompileMap,
|
||||||
|
},
|
||||||
HlBlock, HlBlockBody, HlPrimitives,
|
HlBlock, HlBlockBody, HlPrimitives,
|
||||||
};
|
};
|
||||||
use alloy_consensus::{BlockHeader, Header, Transaction as _, TxReceipt, EMPTY_OMMER_ROOT_HASH};
|
use alloy_consensus::{BlockHeader, Header, Transaction as _, TxReceipt, EMPTY_OMMER_ROOT_HASH};
|
||||||
@ -11,7 +15,6 @@ use alloy_eips::merge::BEACON_NONCE;
|
|||||||
use alloy_primitives::{Log, U256};
|
use alloy_primitives::{Log, U256};
|
||||||
use reth_chainspec::{EthChainSpec, EthereumHardforks, Hardforks};
|
use reth_chainspec::{EthChainSpec, EthereumHardforks, Hardforks};
|
||||||
use reth_ethereum_forks::EthereumHardfork;
|
use reth_ethereum_forks::EthereumHardfork;
|
||||||
use reth_ethereum_primitives::BlockBody;
|
|
||||||
use reth_evm::{
|
use reth_evm::{
|
||||||
block::{BlockExecutionError, BlockExecutorFactory, BlockExecutorFor},
|
block::{BlockExecutionError, BlockExecutorFactory, BlockExecutorFor},
|
||||||
eth::{receipt_builder::ReceiptBuilder, EthBlockExecutionCtx},
|
eth::{receipt_builder::ReceiptBuilder, EthBlockExecutionCtx},
|
||||||
@ -20,10 +23,8 @@ use reth_evm::{
|
|||||||
ConfigureEvm, EvmEnv, EvmFactory, ExecutionCtxFor, FromRecoveredTx, FromTxWithEncoded,
|
ConfigureEvm, EvmEnv, EvmFactory, ExecutionCtxFor, FromRecoveredTx, FromTxWithEncoded,
|
||||||
IntoTxEnv, NextBlockEnvAttributes,
|
IntoTxEnv, NextBlockEnvAttributes,
|
||||||
};
|
};
|
||||||
use reth_evm_ethereum::{EthBlockAssembler, RethReceiptBuilder};
|
use reth_evm_ethereum::EthBlockAssembler;
|
||||||
use reth_primitives::{
|
use reth_primitives::{logs_bloom, BlockTy, HeaderTy, Receipt, SealedBlock, SealedHeader};
|
||||||
logs_bloom, BlockTy, HeaderTy, Receipt, SealedBlock, SealedHeader, TransactionSigned,
|
|
||||||
};
|
|
||||||
use reth_primitives_traits::proofs;
|
use reth_primitives_traits::proofs;
|
||||||
use reth_provider::BlockExecutionResult;
|
use reth_provider::BlockExecutionResult;
|
||||||
use reth_revm::State;
|
use reth_revm::State;
|
||||||
|
|||||||
@ -2,7 +2,10 @@ use super::{config::HlBlockExecutionCtx, patch::patch_mainnet_after_tx};
|
|||||||
use crate::{
|
use crate::{
|
||||||
evm::transaction::HlTxEnv,
|
evm::transaction::HlTxEnv,
|
||||||
hardforks::HlHardforks,
|
hardforks::HlHardforks,
|
||||||
node::types::{ReadPrecompileInput, ReadPrecompileResult},
|
node::{
|
||||||
|
primitives::TransactionSigned,
|
||||||
|
types::{ReadPrecompileInput, ReadPrecompileResult},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use alloy_consensus::{Transaction, TxReceipt};
|
use alloy_consensus::{Transaction, TxReceipt};
|
||||||
use alloy_eips::{eip7685::Requests, Encodable2718};
|
use alloy_eips::{eip7685::Requests, Encodable2718};
|
||||||
@ -16,7 +19,6 @@ use reth_evm::{
|
|||||||
precompiles::{DynPrecompile, PrecompilesMap},
|
precompiles::{DynPrecompile, PrecompilesMap},
|
||||||
Database, Evm, FromRecoveredTx, FromTxWithEncoded, IntoTxEnv, OnStateHook, RecoveredTx,
|
Database, Evm, FromRecoveredTx, FromTxWithEncoded, IntoTxEnv, OnStateHook, RecoveredTx,
|
||||||
};
|
};
|
||||||
use reth_primitives::TransactionSigned;
|
|
||||||
use reth_provider::BlockExecutionResult;
|
use reth_provider::BlockExecutionResult;
|
||||||
use reth_revm::State;
|
use reth_revm::State;
|
||||||
use revm::{
|
use revm::{
|
||||||
@ -98,23 +100,7 @@ where
|
|||||||
{
|
{
|
||||||
/// Creates a new HlBlockExecutor.
|
/// Creates a new HlBlockExecutor.
|
||||||
pub fn new(mut evm: EVM, ctx: HlBlockExecutionCtx<'a>, spec: Spec, receipt_builder: R) -> Self {
|
pub fn new(mut evm: EVM, ctx: HlBlockExecutionCtx<'a>, spec: Spec, receipt_builder: R) -> Self {
|
||||||
let precompiles_mut = evm.precompiles_mut();
|
apply_precompiles(&mut evm, &ctx);
|
||||||
// For all precompile addresses just in case it's populated and not cleared
|
|
||||||
// Clear 0x00...08xx addresses
|
|
||||||
let addresses = precompiles_mut.addresses().cloned().collect::<Vec<_>>();
|
|
||||||
for address in addresses {
|
|
||||||
if address.starts_with(&[0u8; 18]) && address[19] == 8 {
|
|
||||||
precompiles_mut.apply_precompile(&address, |_| None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (address, precompile) in ctx.read_precompile_calls.iter() {
|
|
||||||
let precompile = precompile.clone();
|
|
||||||
precompiles_mut.apply_precompile(address, |_| {
|
|
||||||
Some(DynPrecompile::from(move |data: &[u8], gas: u64| {
|
|
||||||
run_precompile(&precompile, data, gas)
|
|
||||||
}))
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Self { spec, evm, gas_used: 0, receipts: vec![], receipt_builder, ctx }
|
Self { spec, evm, gas_used: 0, receipts: vec![], receipt_builder, ctx }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -127,6 +113,7 @@ where
|
|||||||
Tx: FromRecoveredTx<R::Transaction>
|
Tx: FromRecoveredTx<R::Transaction>
|
||||||
+ FromRecoveredTx<TransactionSigned>
|
+ FromRecoveredTx<TransactionSigned>
|
||||||
+ FromTxWithEncoded<TransactionSigned>,
|
+ FromTxWithEncoded<TransactionSigned>,
|
||||||
|
Precompiles = PrecompilesMap,
|
||||||
>,
|
>,
|
||||||
Spec: EthereumHardforks + HlHardforks + EthChainSpec + Hardforks,
|
Spec: EthereumHardforks + HlHardforks + EthChainSpec + Hardforks,
|
||||||
R: ReceiptBuilder<Transaction = TransactionSigned, Receipt: TxReceipt>,
|
R: ReceiptBuilder<Transaction = TransactionSigned, Receipt: TxReceipt>,
|
||||||
@ -140,6 +127,7 @@ where
|
|||||||
type Evm = E;
|
type Evm = E;
|
||||||
|
|
||||||
fn apply_pre_execution_changes(&mut self) -> Result<(), BlockExecutionError> {
|
fn apply_pre_execution_changes(&mut self) -> Result<(), BlockExecutionError> {
|
||||||
|
apply_precompiles(&mut self.evm, &self.ctx);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,3 +211,27 @@ where
|
|||||||
&self.evm
|
&self.evm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn apply_precompiles<'a, DB, EVM>(evm: &mut EVM, ctx: &HlBlockExecutionCtx<'a>)
|
||||||
|
where
|
||||||
|
EVM: Evm<DB = &'a mut State<DB>, Precompiles = PrecompilesMap>,
|
||||||
|
DB: Database + 'a,
|
||||||
|
{
|
||||||
|
let precompiles_mut = evm.precompiles_mut();
|
||||||
|
// For all precompile addresses just in case it's populated and not cleared
|
||||||
|
// Clear 0x00...08xx addresses
|
||||||
|
let addresses = precompiles_mut.addresses().cloned().collect::<Vec<_>>();
|
||||||
|
for address in addresses {
|
||||||
|
if address.starts_with(&[0u8; 18]) && address[19] == 8 {
|
||||||
|
precompiles_mut.apply_precompile(&address, |_| None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (address, precompile) in ctx.read_precompile_calls.iter() {
|
||||||
|
let precompile = precompile.clone();
|
||||||
|
precompiles_mut.apply_precompile(address, |_| {
|
||||||
|
Some(DynPrecompile::from(move |data: &[u8], gas: u64| {
|
||||||
|
run_precompile(&precompile, data, gas)
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -29,6 +29,7 @@ pub mod config;
|
|||||||
mod executor;
|
mod executor;
|
||||||
mod factory;
|
mod factory;
|
||||||
mod patch;
|
mod patch;
|
||||||
|
pub mod receipt_builder;
|
||||||
|
|
||||||
/// HL EVM implementation.
|
/// HL EVM implementation.
|
||||||
///
|
///
|
||||||
|
|||||||
30
src/node/evm/receipt_builder.rs
Normal file
30
src/node/evm/receipt_builder.rs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
use crate::node::primitives::TransactionSigned;
|
||||||
|
use alloy_evm::eth::receipt_builder::{ReceiptBuilder, ReceiptBuilderCtx};
|
||||||
|
use reth_evm::Evm;
|
||||||
|
use reth_primitives::Receipt;
|
||||||
|
|
||||||
|
/// A builder that operates on Reth primitive types, specifically [`TransactionSigned`] and
|
||||||
|
/// [`Receipt`].
|
||||||
|
#[derive(Debug, Clone, Copy, Default)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub struct RethReceiptBuilder;
|
||||||
|
|
||||||
|
impl ReceiptBuilder for RethReceiptBuilder {
|
||||||
|
type Transaction = TransactionSigned;
|
||||||
|
type Receipt = Receipt;
|
||||||
|
|
||||||
|
fn build_receipt<E: Evm>(
|
||||||
|
&self,
|
||||||
|
ctx: ReceiptBuilderCtx<'_, Self::Transaction, E>,
|
||||||
|
) -> Self::Receipt {
|
||||||
|
let ReceiptBuilderCtx { tx, result, cumulative_gas_used, .. } = ctx;
|
||||||
|
Receipt {
|
||||||
|
tx_type: tx.tx_type(),
|
||||||
|
// Success flag was added in `EIP-658: Embedding transaction status code in
|
||||||
|
// receipts`.
|
||||||
|
success: result.is_success(),
|
||||||
|
cumulative_gas_used,
|
||||||
|
logs: result.into_logs(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,7 +1,8 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
chainspec::HlChainSpec,
|
chainspec::HlChainSpec,
|
||||||
node::{
|
node::{
|
||||||
primitives::{HlBlock, HlBlockBody, HlPrimitives},
|
pool::HlPoolBuilder,
|
||||||
|
primitives::{BlockBody, HlBlock, HlBlockBody, HlPrimitives, TransactionSigned},
|
||||||
rpc::{
|
rpc::{
|
||||||
engine_api::{
|
engine_api::{
|
||||||
builder::HlEngineApiBuilder, payload::HlPayloadTypes,
|
builder::HlEngineApiBuilder, payload::HlPayloadTypes,
|
||||||
@ -24,8 +25,6 @@ use reth::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
use reth_engine_primitives::BeaconConsensusEngineHandle;
|
use reth_engine_primitives::BeaconConsensusEngineHandle;
|
||||||
use reth_node_ethereum::node::EthereumPoolBuilder;
|
|
||||||
use reth_primitives::BlockBody;
|
|
||||||
use reth_trie_db::MerklePatriciaTrie;
|
use reth_trie_db::MerklePatriciaTrie;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::sync::{oneshot, Mutex};
|
use tokio::sync::{oneshot, Mutex};
|
||||||
@ -59,12 +58,14 @@ impl HlNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod pool;
|
||||||
|
|
||||||
impl HlNode {
|
impl HlNode {
|
||||||
pub fn components<Node>(
|
pub fn components<Node>(
|
||||||
&self,
|
&self,
|
||||||
) -> ComponentsBuilder<
|
) -> ComponentsBuilder<
|
||||||
Node,
|
Node,
|
||||||
EthereumPoolBuilder,
|
HlPoolBuilder,
|
||||||
HlPayloadServiceBuilder,
|
HlPayloadServiceBuilder,
|
||||||
HlNetworkBuilder,
|
HlNetworkBuilder,
|
||||||
HlExecutorBuilder,
|
HlExecutorBuilder,
|
||||||
@ -75,7 +76,7 @@ impl HlNode {
|
|||||||
{
|
{
|
||||||
ComponentsBuilder::default()
|
ComponentsBuilder::default()
|
||||||
.node_types::<Node>()
|
.node_types::<Node>()
|
||||||
.pool(EthereumPoolBuilder::default())
|
.pool(HlPoolBuilder)
|
||||||
.executor(HlExecutorBuilder::default())
|
.executor(HlExecutorBuilder::default())
|
||||||
.payload(HlPayloadServiceBuilder::default())
|
.payload(HlPayloadServiceBuilder::default())
|
||||||
.network(HlNetworkBuilder { engine_handle_rx: self.engine_handle_rx.clone() })
|
.network(HlNetworkBuilder { engine_handle_rx: self.engine_handle_rx.clone() })
|
||||||
@ -97,7 +98,7 @@ where
|
|||||||
{
|
{
|
||||||
type ComponentsBuilder = ComponentsBuilder<
|
type ComponentsBuilder = ComponentsBuilder<
|
||||||
N,
|
N,
|
||||||
EthereumPoolBuilder,
|
HlPoolBuilder,
|
||||||
HlPayloadServiceBuilder,
|
HlPayloadServiceBuilder,
|
||||||
HlNetworkBuilder,
|
HlNetworkBuilder,
|
||||||
HlExecutorBuilder,
|
HlExecutorBuilder,
|
||||||
@ -131,7 +132,7 @@ where
|
|||||||
inner: BlockBody {
|
inner: BlockBody {
|
||||||
transactions: transactions
|
transactions: transactions
|
||||||
.into_transactions()
|
.into_transactions()
|
||||||
.map(|tx| tx.inner.into_inner().into())
|
.map(|tx| TransactionSigned(tx.inner.into_inner().into()))
|
||||||
.collect(),
|
.collect(),
|
||||||
ommers: Default::default(),
|
ommers: Default::default(),
|
||||||
withdrawals,
|
withdrawals,
|
||||||
|
|||||||
@ -64,7 +64,6 @@ where
|
|||||||
to_network: UnboundedSender<ImportEvent>,
|
to_network: UnboundedSender<ImportEvent>,
|
||||||
/// Pending block imports.
|
/// Pending block imports.
|
||||||
pending_imports: FuturesUnordered<ImportFut>,
|
pending_imports: FuturesUnordered<ImportFut>,
|
||||||
height: u64,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Provider> ImportService<Provider>
|
impl<Provider> ImportService<Provider>
|
||||||
@ -77,7 +76,6 @@ where
|
|||||||
engine: BeaconConsensusEngineHandle<HlPayloadTypes>,
|
engine: BeaconConsensusEngineHandle<HlPayloadTypes>,
|
||||||
from_network: UnboundedReceiver<IncomingBlock>,
|
from_network: UnboundedReceiver<IncomingBlock>,
|
||||||
to_network: UnboundedSender<ImportEvent>,
|
to_network: UnboundedSender<ImportEvent>,
|
||||||
height: u64,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
engine,
|
engine,
|
||||||
@ -85,7 +83,6 @@ where
|
|||||||
from_network,
|
from_network,
|
||||||
to_network,
|
to_network,
|
||||||
pending_imports: FuturesUnordered::new(),
|
pending_imports: FuturesUnordered::new(),
|
||||||
height,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,23 +169,10 @@ where
|
|||||||
|
|
||||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
let this = self.get_mut();
|
let this = self.get_mut();
|
||||||
let prev_height = this.height;
|
|
||||||
|
|
||||||
// Receive new blocks from network
|
// Receive new blocks from network
|
||||||
while let Some(block) = collect_block(this.height) {
|
while let Poll::Ready(Some((block, peer_id))) = this.from_network.poll_recv(cx) {
|
||||||
if this.height > prev_height + 1000 {
|
this.on_new_block(block, peer_id);
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
let peer_id = PeerId::random();
|
|
||||||
let reth_block = block.to_reth_block();
|
|
||||||
let td = U128::from(reth_block.header().difficulty());
|
|
||||||
let msg = NewBlockMessage {
|
|
||||||
hash: reth_block.header().hash_slow(),
|
|
||||||
block: Arc::new(HlNewBlock(NewBlock { block: reth_block, td })),
|
|
||||||
};
|
|
||||||
this.on_new_block(msg, peer_id);
|
|
||||||
this.height += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process completed imports and send events to network
|
// Process completed imports and send events to network
|
||||||
@ -366,7 +350,7 @@ mod tests {
|
|||||||
|
|
||||||
let handle = ImportHandle::new(to_import, import_outcome);
|
let handle = ImportHandle::new(to_import, import_outcome);
|
||||||
|
|
||||||
let service = ImportService::new(consensus, engine_handle, from_network, to_network, 1);
|
let service = ImportService::new(consensus, engine_handle, from_network, to_network);
|
||||||
tokio::spawn(Box::pin(async move {
|
tokio::spawn(Box::pin(async move {
|
||||||
service.await.unwrap();
|
service.await.unwrap();
|
||||||
}));
|
}));
|
||||||
|
|||||||
@ -11,7 +11,6 @@ use crate::{
|
|||||||
HlBlock,
|
HlBlock,
|
||||||
};
|
};
|
||||||
use alloy_rlp::{Decodable, Encodable};
|
use alloy_rlp::{Decodable, Encodable};
|
||||||
use reth_provider::BlockNumReader;
|
|
||||||
// use handshake::HlHandshake;
|
// use handshake::HlHandshake;
|
||||||
use reth::{
|
use reth::{
|
||||||
api::{FullNodeTypes, TxTy},
|
api::{FullNodeTypes, TxTy},
|
||||||
@ -37,12 +36,14 @@ pub struct HlNewBlock(pub NewBlock<HlBlock>);
|
|||||||
|
|
||||||
mod rlp {
|
mod rlp {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::HlBlockBody;
|
use crate::{
|
||||||
use alloy_consensus::{BlobTransactionSidecar, BlockBody, Header};
|
node::primitives::{BlockBody, TransactionSigned},
|
||||||
|
HlBlockBody,
|
||||||
|
};
|
||||||
|
use alloy_consensus::{BlobTransactionSidecar, Header};
|
||||||
use alloy_primitives::U128;
|
use alloy_primitives::U128;
|
||||||
use alloy_rlp::{RlpDecodable, RlpEncodable};
|
use alloy_rlp::{RlpDecodable, RlpEncodable};
|
||||||
use alloy_rpc_types::Withdrawals;
|
use alloy_rpc_types::Withdrawals;
|
||||||
use reth_primitives::TransactionSigned;
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
#[derive(RlpEncodable, RlpDecodable)]
|
#[derive(RlpEncodable, RlpDecodable)]
|
||||||
@ -170,8 +171,6 @@ impl HlNetworkBuilder {
|
|||||||
|
|
||||||
let handle = ImportHandle::new(to_import, import_outcome);
|
let handle = ImportHandle::new(to_import, import_outcome);
|
||||||
let consensus = Arc::new(HlConsensus { provider: ctx.provider().clone() });
|
let consensus = Arc::new(HlConsensus { provider: ctx.provider().clone() });
|
||||||
let number = ctx.provider().last_block_number().unwrap_or(1);
|
|
||||||
let number = std::cmp::max(number, 1);
|
|
||||||
|
|
||||||
ctx.task_executor().spawn_critical("block import", async move {
|
ctx.task_executor().spawn_critical("block import", async move {
|
||||||
let handle = engine_handle_rx
|
let handle = engine_handle_rx
|
||||||
@ -182,12 +181,13 @@ impl HlNetworkBuilder {
|
|||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
ImportService::new(consensus, handle, from_network, to_network, number).await.unwrap();
|
ImportService::new(consensus, handle, from_network, to_network).await.unwrap();
|
||||||
});
|
});
|
||||||
|
|
||||||
let network_builder = network_builder
|
let network_builder = network_builder
|
||||||
.boot_nodes(boot_nodes())
|
.boot_nodes(boot_nodes())
|
||||||
.set_head(ctx.head())
|
.set_head(ctx.head())
|
||||||
|
.with_pow()
|
||||||
.block_import(Box::new(HlBlockImport::new(handle)));
|
.block_import(Box::new(HlBlockImport::new(handle)));
|
||||||
// .discovery(discv4)
|
// .discovery(discv4)
|
||||||
// .eth_rlpx_handshake(Arc::new(HlHandshake::default()));
|
// .eth_rlpx_handshake(Arc::new(HlHandshake::default()));
|
||||||
|
|||||||
436
src/node/pool.rs
Normal file
436
src/node/pool.rs
Normal file
@ -0,0 +1,436 @@
|
|||||||
|
//! A placeholder for the transaction pool.
|
||||||
|
//!
|
||||||
|
//! We'll not use transaction pool in HL, since this node does not write to HL consensus;
|
||||||
|
//! just a minimum implementation to make the node compile would suffice.
|
||||||
|
//!
|
||||||
|
//! Ethereum transaction pool only supports TransactionSigned (EthereumTxEnvelope<TxEip4844>),
|
||||||
|
//! hence this placeholder for the transaction pool.
|
||||||
|
|
||||||
|
use crate::node::{primitives::TransactionSigned, HlNode};
|
||||||
|
use alloy_consensus::{
|
||||||
|
error::ValueError, EthereumTxEnvelope, Transaction as TransactionTrait, TxEip4844,
|
||||||
|
};
|
||||||
|
use alloy_eips::{
|
||||||
|
eip4844::BlobAndProofV2, eip7594::BlobTransactionSidecarVariant, eip7702::SignedAuthorization,
|
||||||
|
Typed2718,
|
||||||
|
};
|
||||||
|
use alloy_primitives::{Address, Bytes, ChainId, TxHash, TxKind, B256, U256};
|
||||||
|
use alloy_rpc_types::AccessList;
|
||||||
|
use alloy_rpc_types_engine::BlobAndProofV1;
|
||||||
|
use reth::{
|
||||||
|
api::FullNodeTypes,
|
||||||
|
builder::components::PoolBuilder,
|
||||||
|
transaction_pool::{PoolResult, PoolSize, PoolTransaction, TransactionOrigin, TransactionPool},
|
||||||
|
};
|
||||||
|
use reth_eth_wire::HandleMempoolData;
|
||||||
|
use reth_ethereum_primitives::PooledTransactionVariant;
|
||||||
|
use reth_primitives::Recovered;
|
||||||
|
use reth_primitives_traits::InMemorySize;
|
||||||
|
use reth_transaction_pool::{
|
||||||
|
error::InvalidPoolTransactionError, AllPoolTransactions, AllTransactionsEvents, BestTransactions, BestTransactionsAttributes, BlobStoreError, BlockInfo, EthPoolTransaction, GetPooledTransactionLimit, NewBlobSidecar, NewTransactionEvent, PropagatedTransactions, TransactionEvents, TransactionListenerKind, ValidPoolTransaction
|
||||||
|
};
|
||||||
|
use std::{collections::HashSet, sync::Arc};
|
||||||
|
use tokio::sync::mpsc::{self, Receiver};
|
||||||
|
|
||||||
|
pub struct HlPoolBuilder;
|
||||||
|
impl<Node> PoolBuilder<Node> for HlPoolBuilder
|
||||||
|
where
|
||||||
|
Node: FullNodeTypes<Types = HlNode>,
|
||||||
|
{
|
||||||
|
type Pool = HlTransactionPool;
|
||||||
|
|
||||||
|
async fn build_pool(
|
||||||
|
self,
|
||||||
|
_ctx: &reth::builder::BuilderContext<Node>,
|
||||||
|
) -> eyre::Result<Self::Pool> {
|
||||||
|
Ok(HlTransactionPool)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub struct HlPooledTransaction;
|
||||||
|
|
||||||
|
impl InMemorySize for HlPooledTransaction {
|
||||||
|
fn size(&self) -> usize {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TransactionTrait for HlPooledTransaction {
|
||||||
|
fn chain_id(&self) -> Option<ChainId> {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
fn nonce(&self) -> u64 {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
fn gas_limit(&self) -> u64 {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
fn gas_price(&self) -> Option<u128> {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
fn max_fee_per_gas(&self) -> u128 {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
fn max_priority_fee_per_gas(&self) -> Option<u128> {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
fn max_fee_per_blob_gas(&self) -> Option<u128> {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
fn priority_fee_or_price(&self) -> u128 {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
fn effective_gas_price(&self, _base_fee: Option<u64>) -> u128 {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
fn is_dynamic_fee(&self) -> bool {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
fn kind(&self) -> TxKind {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
fn is_create(&self) -> bool {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
fn value(&self) -> U256 {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
fn input(&self) -> &Bytes {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
fn access_list(&self) -> Option<&AccessList> {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
fn blob_versioned_hashes(&self) -> Option<&[B256]> {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
fn authorization_list(&self) -> Option<&[SignedAuthorization]> {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Typed2718 for HlPooledTransaction {
|
||||||
|
fn ty(&self) -> u8 {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PoolTransaction for HlPooledTransaction {
|
||||||
|
type TryFromConsensusError = ValueError<EthereumTxEnvelope<TxEip4844>>;
|
||||||
|
type Consensus = TransactionSigned;
|
||||||
|
type Pooled = PooledTransactionVariant;
|
||||||
|
|
||||||
|
fn try_from_consensus(
|
||||||
|
_tx: Recovered<Self::Consensus>,
|
||||||
|
) -> Result<Self, Self::TryFromConsensusError> {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clone_into_consensus(&self) -> Recovered<Self::Consensus> {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_consensus(self) -> Recovered<Self::Consensus> {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_pooled(_tx: Recovered<Self::Pooled>) -> Self {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hash(&self) -> &TxHash {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sender(&self) -> Address {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sender_ref(&self) -> &Address {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cost(&self) -> &U256 {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encoded_length(&self) -> usize {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ensure_max_init_code_size(
|
||||||
|
&self,
|
||||||
|
_max_init_code_size: usize,
|
||||||
|
) -> Result<(), InvalidPoolTransactionError> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EthPoolTransaction for HlPooledTransaction {
|
||||||
|
fn take_blob(&mut self) -> reth_transaction_pool::EthBlobTransactionSidecar {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_into_pooled_eip4844(
|
||||||
|
self,
|
||||||
|
_sidecar: Arc<alloy_eips::eip7594::BlobTransactionSidecarVariant>,
|
||||||
|
) -> Option<Recovered<Self::Pooled>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_from_eip4844(
|
||||||
|
_tx: Recovered<Self::Consensus>,
|
||||||
|
_sidecar: alloy_eips::eip7594::BlobTransactionSidecarVariant,
|
||||||
|
) -> Option<Self> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate_blob(
|
||||||
|
&self,
|
||||||
|
_blob: &alloy_eips::eip7594::BlobTransactionSidecarVariant,
|
||||||
|
_settings: &alloy_eips::eip4844::env_settings::KzgSettings,
|
||||||
|
) -> Result<(), alloy_consensus::BlobTransactionValidationError> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub struct HlTransactionPool;
|
||||||
|
impl TransactionPool for HlTransactionPool {
|
||||||
|
type Transaction = HlPooledTransaction;
|
||||||
|
|
||||||
|
fn pool_size(&self) -> PoolSize {
|
||||||
|
PoolSize::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn block_info(&self) -> BlockInfo {
|
||||||
|
BlockInfo::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn add_transaction_and_subscribe(
|
||||||
|
&self,
|
||||||
|
_origin: TransactionOrigin,
|
||||||
|
_transaction: Self::Transaction,
|
||||||
|
) -> PoolResult<TransactionEvents> {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn add_transaction(
|
||||||
|
&self,
|
||||||
|
_origin: TransactionOrigin,
|
||||||
|
_transaction: Self::Transaction,
|
||||||
|
) -> PoolResult<TxHash> {
|
||||||
|
Ok(TxHash::default())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn add_transactions(
|
||||||
|
&self,
|
||||||
|
_origin: TransactionOrigin,
|
||||||
|
_transactions: Vec<Self::Transaction>,
|
||||||
|
) -> Vec<PoolResult<TxHash>> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn transaction_event_listener(&self, _tx_hash: TxHash) -> Option<TransactionEvents> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn all_transactions_event_listener(&self) -> AllTransactionsEvents<Self::Transaction> {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pending_transactions_listener_for(
|
||||||
|
&self,
|
||||||
|
_kind: TransactionListenerKind,
|
||||||
|
) -> Receiver<TxHash> {
|
||||||
|
mpsc::channel(1).1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn blob_transaction_sidecars_listener(&self) -> Receiver<NewBlobSidecar> {
|
||||||
|
mpsc::channel(1).1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_transactions_listener_for(
|
||||||
|
&self,
|
||||||
|
_kind: TransactionListenerKind,
|
||||||
|
) -> Receiver<NewTransactionEvent<Self::Transaction>> {
|
||||||
|
mpsc::channel(1).1
|
||||||
|
}
|
||||||
|
fn pooled_transaction_hashes(&self) -> Vec<TxHash> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
fn pooled_transaction_hashes_max(&self, _max: usize) -> Vec<TxHash> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
fn pooled_transactions(&self) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
fn pooled_transactions_max(
|
||||||
|
&self,
|
||||||
|
_max: usize,
|
||||||
|
) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
fn get_pooled_transaction_elements(
|
||||||
|
&self,
|
||||||
|
_tx_hashes: Vec<TxHash>,
|
||||||
|
_limit: GetPooledTransactionLimit,
|
||||||
|
) -> Vec<<Self::Transaction as PoolTransaction>::Pooled> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
fn get_pooled_transaction_element(
|
||||||
|
&self,
|
||||||
|
_tx_hash: TxHash,
|
||||||
|
) -> Option<Recovered<<Self::Transaction as PoolTransaction>::Pooled>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
fn best_transactions(
|
||||||
|
&self,
|
||||||
|
) -> Box<dyn BestTransactions<Item = Arc<ValidPoolTransaction<Self::Transaction>>>> {
|
||||||
|
Box::new(std::iter::empty())
|
||||||
|
}
|
||||||
|
fn best_transactions_with_attributes(
|
||||||
|
&self,
|
||||||
|
_best_transactions_attributes: BestTransactionsAttributes,
|
||||||
|
) -> Box<dyn BestTransactions<Item = Arc<ValidPoolTransaction<Self::Transaction>>>> {
|
||||||
|
Box::new(std::iter::empty())
|
||||||
|
}
|
||||||
|
fn pending_transactions(&self) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
fn pending_transactions_max(
|
||||||
|
&self,
|
||||||
|
_max: usize,
|
||||||
|
) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
fn queued_transactions(&self) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
fn all_transactions(&self) -> AllPoolTransactions<Self::Transaction> {
|
||||||
|
AllPoolTransactions::default()
|
||||||
|
}
|
||||||
|
fn remove_transactions(
|
||||||
|
&self,
|
||||||
|
_hashes: Vec<TxHash>,
|
||||||
|
) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
fn remove_transactions_and_descendants(
|
||||||
|
&self,
|
||||||
|
_hashes: Vec<TxHash>,
|
||||||
|
) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
fn remove_transactions_by_sender(
|
||||||
|
&self,
|
||||||
|
_sender: Address,
|
||||||
|
) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
fn retain_unknown<A>(&self, _announcement: &mut A)
|
||||||
|
where
|
||||||
|
A: HandleMempoolData,
|
||||||
|
{
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
fn get(&self, _tx_hash: &TxHash) -> Option<Arc<ValidPoolTransaction<Self::Transaction>>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
fn get_all(&self, _txs: Vec<TxHash>) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
fn on_propagated(&self, _txs: PropagatedTransactions) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
fn get_transactions_by_sender(
|
||||||
|
&self,
|
||||||
|
_sender: Address,
|
||||||
|
) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
fn get_pending_transactions_with_predicate(
|
||||||
|
&self,
|
||||||
|
_predicate: impl FnMut(&ValidPoolTransaction<Self::Transaction>) -> bool,
|
||||||
|
) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
fn get_pending_transactions_by_sender(
|
||||||
|
&self,
|
||||||
|
_sender: Address,
|
||||||
|
) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
fn get_queued_transactions_by_sender(
|
||||||
|
&self,
|
||||||
|
_sender: Address,
|
||||||
|
) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
fn get_highest_transaction_by_sender(
|
||||||
|
&self,
|
||||||
|
_sender: Address,
|
||||||
|
) -> Option<Arc<ValidPoolTransaction<Self::Transaction>>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
fn get_highest_consecutive_transaction_by_sender(
|
||||||
|
&self,
|
||||||
|
_sender: Address,
|
||||||
|
_on_chain_nonce: u64,
|
||||||
|
) -> Option<Arc<ValidPoolTransaction<Self::Transaction>>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
fn get_transaction_by_sender_and_nonce(
|
||||||
|
&self,
|
||||||
|
_sender: Address,
|
||||||
|
_nonce: u64,
|
||||||
|
) -> Option<Arc<ValidPoolTransaction<Self::Transaction>>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
fn get_transactions_by_origin(
|
||||||
|
&self,
|
||||||
|
_origin: TransactionOrigin,
|
||||||
|
) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
fn get_pending_transactions_by_origin(
|
||||||
|
&self,
|
||||||
|
_origin: TransactionOrigin,
|
||||||
|
) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
fn unique_senders(&self) -> HashSet<Address> {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
fn get_blob(
|
||||||
|
&self,
|
||||||
|
_tx_hash: TxHash,
|
||||||
|
) -> Result<Option<Arc<BlobTransactionSidecarVariant>>, BlobStoreError> {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
fn get_all_blobs(
|
||||||
|
&self,
|
||||||
|
_tx_hashes: Vec<TxHash>,
|
||||||
|
) -> Result<Vec<(TxHash, Arc<BlobTransactionSidecarVariant>)>, BlobStoreError> {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
fn get_all_blobs_exact(
|
||||||
|
&self,
|
||||||
|
_tx_hashes: Vec<TxHash>,
|
||||||
|
) -> Result<Vec<Arc<BlobTransactionSidecarVariant>>, BlobStoreError> {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
fn get_blobs_for_versioned_hashes_v1(
|
||||||
|
&self,
|
||||||
|
_versioned_hashes: &[B256],
|
||||||
|
) -> Result<Vec<Option<BlobAndProofV1>>, BlobStoreError> {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
fn get_blobs_for_versioned_hashes_v2(
|
||||||
|
&self,
|
||||||
|
_versioned_hashes: &[B256],
|
||||||
|
) -> Result<Option<Vec<BlobAndProofV2>>, BlobStoreError> {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,14 +1,17 @@
|
|||||||
#![allow(clippy::owned_cow)]
|
#![allow(clippy::owned_cow)]
|
||||||
use alloy_consensus::{BlobTransactionSidecar, Header};
|
use alloy_consensus::{BlobTransactionSidecar, Header};
|
||||||
use alloy_rlp::{Encodable, RlpDecodable, RlpEncodable};
|
use alloy_rlp::{Encodable, RlpDecodable, RlpEncodable};
|
||||||
use reth_ethereum_primitives::{BlockBody, Receipt};
|
use reth_ethereum_primitives::Receipt;
|
||||||
use reth_primitives::{NodePrimitives, TransactionSigned};
|
use reth_primitives::NodePrimitives;
|
||||||
use reth_primitives_traits::{Block, BlockBody as BlockBodyTrait, InMemorySize};
|
use reth_primitives_traits::{Block, BlockBody as BlockBodyTrait, InMemorySize};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use crate::node::types::{ReadPrecompileCall, ReadPrecompileCalls};
|
use crate::node::types::{ReadPrecompileCall, ReadPrecompileCalls};
|
||||||
|
|
||||||
|
pub mod tx_wrapper;
|
||||||
|
pub use tx_wrapper::{BlockBody, TransactionSigned};
|
||||||
|
|
||||||
/// Primitive types for HyperEVM.
|
/// Primitive types for HyperEVM.
|
||||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
@ -46,11 +49,13 @@ pub struct HlBlockBody {
|
|||||||
|
|
||||||
impl InMemorySize for HlBlockBody {
|
impl InMemorySize for HlBlockBody {
|
||||||
fn size(&self) -> usize {
|
fn size(&self) -> usize {
|
||||||
self.inner.size() +
|
self.inner.size()
|
||||||
self.sidecars
|
+ self
|
||||||
|
.sidecars
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or(0, |s| s.capacity() * core::mem::size_of::<BlobTransactionSidecar>()) +
|
.map_or(0, |s| s.capacity() * core::mem::size_of::<BlobTransactionSidecar>())
|
||||||
self.read_precompile_calls
|
+ self
|
||||||
|
.read_precompile_calls
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or(0, |s| s.0.capacity() * core::mem::size_of::<ReadPrecompileCall>())
|
.map_or(0, |s| s.0.capacity() * core::mem::size_of::<ReadPrecompileCall>())
|
||||||
}
|
}
|
||||||
@ -79,6 +84,16 @@ impl BlockBodyTrait for HlBlockBody {
|
|||||||
fn ommers(&self) -> Option<&[Self::OmmerHeader]> {
|
fn ommers(&self) -> Option<&[Self::OmmerHeader]> {
|
||||||
self.inner.ommers()
|
self.inner.ommers()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn calculate_tx_root(&self) -> alloy_primitives::B256 {
|
||||||
|
alloy_consensus::proofs::calculate_transaction_root(
|
||||||
|
&self
|
||||||
|
.transactions()
|
||||||
|
.iter()
|
||||||
|
.filter(|tx| !tx.is_system_transaction())
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Block for HL
|
/// Block for HL
|
||||||
398
src/node/primitives/tx_wrapper.rs
Normal file
398
src/node/primitives/tx_wrapper.rs
Normal file
@ -0,0 +1,398 @@
|
|||||||
|
//! HlNodePrimitives::TransactionSigned; it's the same as ethereum transaction type,
|
||||||
|
//! except that it supports pseudo signer for system transactions.
|
||||||
|
use std::hash::Hasher;
|
||||||
|
|
||||||
|
use alloy_consensus::{
|
||||||
|
crypto::RecoveryError, EthereumTxEnvelope, Signed, Transaction as TransactionTrait, TxEip1559,
|
||||||
|
TxEip2930, TxEip4844, TxEip4844WithSidecar, TxEip7702, TxEnvelope, TxLegacy, TxType,
|
||||||
|
TypedTransaction,
|
||||||
|
};
|
||||||
|
use alloy_eips::{
|
||||||
|
eip2718::Eip2718Result, eip7594::BlobTransactionSidecarVariant, eip7702::SignedAuthorization,
|
||||||
|
Decodable2718, Encodable2718, Typed2718,
|
||||||
|
};
|
||||||
|
use alloy_primitives::{address, Address, Bytes, TxHash, TxKind, Uint, B256, U256};
|
||||||
|
use alloy_rpc_types::AccessList;
|
||||||
|
use alloy_signer::Signature;
|
||||||
|
use reth_codecs::alloy::transaction::FromTxCompact;
|
||||||
|
use reth_db::{
|
||||||
|
table::{Compress, Decompress},
|
||||||
|
DatabaseError,
|
||||||
|
};
|
||||||
|
use reth_evm::FromRecoveredTx;
|
||||||
|
use reth_primitives::Recovered;
|
||||||
|
use reth_primitives_traits::{
|
||||||
|
serde_bincode_compat::SerdeBincodeCompat, InMemorySize, SignedTransaction, SignerRecoverable,
|
||||||
|
};
|
||||||
|
use revm::context::TxEnv;
|
||||||
|
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
|
|
||||||
|
type InnerType = alloy_consensus::EthereumTxEnvelope<TxEip4844>;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Eq)]
|
||||||
|
pub struct TransactionSigned(pub InnerType);
|
||||||
|
|
||||||
|
fn s_to_address(s: U256) -> Address {
|
||||||
|
if s == U256::ONE {
|
||||||
|
return address!("2222222222222222222222222222222222222222");
|
||||||
|
}
|
||||||
|
let mut buf = [0u8; 20];
|
||||||
|
buf[0..20].copy_from_slice(&s.to_be_bytes::<32>()[12..32]);
|
||||||
|
Address::from_slice(&buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SignerRecoverable for TransactionSigned {
|
||||||
|
fn recover_signer(&self) -> Result<Address, RecoveryError> {
|
||||||
|
if self.is_system_transaction() {
|
||||||
|
return Ok(s_to_address(self.signature().s()));
|
||||||
|
}
|
||||||
|
self.0.recover_signer()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn recover_signer_unchecked(&self) -> Result<Address, RecoveryError> {
|
||||||
|
if self.is_system_transaction() {
|
||||||
|
return Ok(s_to_address(self.signature().s()));
|
||||||
|
}
|
||||||
|
self.0.recover_signer_unchecked()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SignedTransaction for TransactionSigned {
|
||||||
|
fn tx_hash(&self) -> &TxHash {
|
||||||
|
self.0.tx_hash()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn recover_signer_unchecked_with_buf(
|
||||||
|
&self,
|
||||||
|
buf: &mut Vec<u8>,
|
||||||
|
) -> Result<Address, RecoveryError> {
|
||||||
|
if self.is_system_transaction() {
|
||||||
|
return Ok(s_to_address(self.signature().s()));
|
||||||
|
}
|
||||||
|
|
||||||
|
self.0.recover_signer_unchecked_with_buf(buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
// NOTE: All lines below are just wrappers for the inner type.
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
|
||||||
|
impl Serialize for TransactionSigned {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
self.0.serialize(serializer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for TransactionSigned {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
Ok(Self(InnerType::deserialize(deserializer)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_from_signed {
|
||||||
|
($($tx:ident),*) => {
|
||||||
|
$(
|
||||||
|
impl From<Signed<$tx>> for TransactionSigned {
|
||||||
|
fn from(value: Signed<$tx>) -> Self {
|
||||||
|
Self(value.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_from_signed!(TxLegacy, TxEip2930, TxEip1559, TxEip7702, TypedTransaction);
|
||||||
|
|
||||||
|
impl InMemorySize for TransactionSigned {
|
||||||
|
#[inline]
|
||||||
|
fn size(&self) -> usize {
|
||||||
|
self.0.size()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl alloy_rlp::Encodable for TransactionSigned {
|
||||||
|
fn encode(&self, out: &mut dyn alloy_rlp::bytes::BufMut) {
|
||||||
|
self.0.encode(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn length(&self) -> usize {
|
||||||
|
self.0.length()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl alloy_rlp::Decodable for TransactionSigned {
|
||||||
|
fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
|
||||||
|
Ok(Self(TxEnvelope::decode(buf)?.into()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Encodable2718 for TransactionSigned {
|
||||||
|
fn type_flag(&self) -> Option<u8> {
|
||||||
|
self.0.type_flag()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode_2718_len(&self) -> usize {
|
||||||
|
self.0.encode_2718_len()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode_2718(&self, out: &mut dyn alloy_rlp::BufMut) {
|
||||||
|
self.0.encode_2718(out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Decodable2718 for TransactionSigned {
|
||||||
|
fn typed_decode(ty: u8, buf: &mut &[u8]) -> Eip2718Result<Self> {
|
||||||
|
Ok(Self(TxEnvelope::typed_decode(ty, buf)?.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fallback_decode(buf: &mut &[u8]) -> Eip2718Result<Self> {
|
||||||
|
Ok(Self(TxEnvelope::fallback_decode(buf)?.into()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Typed2718 for TransactionSigned {
|
||||||
|
fn ty(&self) -> u8 {
|
||||||
|
self.0.ty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for TransactionSigned {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.0 == other.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl core::hash::Hash for TransactionSigned {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
core::hash::Hash::hash(&self.0, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TransactionTrait for TransactionSigned {
|
||||||
|
fn chain_id(&self) -> Option<u64> {
|
||||||
|
self.0.chain_id()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn nonce(&self) -> u64 {
|
||||||
|
self.0.nonce()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gas_limit(&self) -> u64 {
|
||||||
|
self.0.gas_limit()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gas_price(&self) -> Option<u128> {
|
||||||
|
self.0.gas_price()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn max_fee_per_gas(&self) -> u128 {
|
||||||
|
self.0.max_fee_per_gas()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn max_priority_fee_per_gas(&self) -> Option<u128> {
|
||||||
|
self.0.max_priority_fee_per_gas()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn max_fee_per_blob_gas(&self) -> Option<u128> {
|
||||||
|
self.0.max_fee_per_blob_gas()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn priority_fee_or_price(&self) -> u128 {
|
||||||
|
self.0.priority_fee_or_price()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn effective_gas_price(&self, base_fee: Option<u64>) -> u128 {
|
||||||
|
self.0.effective_gas_price(base_fee)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn effective_tip_per_gas(&self, base_fee: u64) -> Option<u128> {
|
||||||
|
self.0.effective_tip_per_gas(base_fee)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_dynamic_fee(&self) -> bool {
|
||||||
|
self.0.is_dynamic_fee()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kind(&self) -> TxKind {
|
||||||
|
self.0.kind()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_create(&self) -> bool {
|
||||||
|
self.0.is_create()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn value(&self) -> Uint<256, 4> {
|
||||||
|
self.0.value()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn input(&self) -> &Bytes {
|
||||||
|
self.0.input()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn access_list(&self) -> Option<&AccessList> {
|
||||||
|
self.0.access_list()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn blob_versioned_hashes(&self) -> Option<&[B256]> {
|
||||||
|
self.0.blob_versioned_hashes()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn authorization_list(&self) -> Option<&[SignedAuthorization]> {
|
||||||
|
self.0.authorization_list()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl reth_codecs::Compact for TransactionSigned {
|
||||||
|
fn to_compact<B>(&self, buf: &mut B) -> usize
|
||||||
|
where
|
||||||
|
B: bytes::BufMut + AsMut<[u8]>,
|
||||||
|
{
|
||||||
|
self.0.to_compact(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_compact(buf: &[u8], _len: usize) -> (Self, &[u8]) {
|
||||||
|
let (tx, hash) = InnerType::from_compact(buf, _len);
|
||||||
|
(Self(tx), hash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn convert_recovered(value: Recovered<TransactionSigned>) -> Recovered<InnerType> {
|
||||||
|
let (tx, signer) = value.into_parts();
|
||||||
|
Recovered::new_unchecked(tx.0, signer)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromRecoveredTx<TransactionSigned> for TxEnv {
|
||||||
|
fn from_recovered_tx(tx: &TransactionSigned, sender: Address) -> Self {
|
||||||
|
TxEnv::from_recovered_tx(&tx.0, sender)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromTxCompact for TransactionSigned {
|
||||||
|
type TxType = TxType;
|
||||||
|
|
||||||
|
fn from_tx_compact(buf: &[u8], tx_type: Self::TxType, signature: Signature) -> (Self, &[u8])
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
let (tx, buf) = InnerType::from_tx_compact(buf, tx_type, signature);
|
||||||
|
(Self(tx), buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl reth_codecs::alloy::transaction::Envelope for TransactionSigned {
|
||||||
|
fn signature(&self) -> &Signature {
|
||||||
|
self.0.signature()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tx_type(&self) -> Self::TxType {
|
||||||
|
self.0.tx_type()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TransactionSigned {
|
||||||
|
pub const fn signature(&self) -> &Signature {
|
||||||
|
self.0.signature()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn tx_type(&self) -> TxType {
|
||||||
|
self.0.tx_type()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_system_transaction(&self) -> bool {
|
||||||
|
self.gas_price().is_some() && self.gas_price().unwrap() == 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct BincodeCompatTxCustom(pub TransactionSigned);
|
||||||
|
|
||||||
|
impl SerdeBincodeCompat for TransactionSigned {
|
||||||
|
type BincodeRepr<'a> = BincodeCompatTxCustom;
|
||||||
|
|
||||||
|
fn as_repr(&self) -> Self::BincodeRepr<'_> {
|
||||||
|
BincodeCompatTxCustom(self.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_repr(repr: Self::BincodeRepr<'_>) -> Self {
|
||||||
|
repr.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type BlockBody = alloy_consensus::BlockBody<TransactionSigned>;
|
||||||
|
|
||||||
|
impl From<TransactionSigned> for EthereumTxEnvelope<TxEip4844> {
|
||||||
|
fn from(value: TransactionSigned) -> Self {
|
||||||
|
value.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<TransactionSigned> for EthereumTxEnvelope<TxEip4844WithSidecar> {
|
||||||
|
type Error = <InnerType as TryInto<EthereumTxEnvelope<TxEip4844WithSidecar>>>::Error;
|
||||||
|
|
||||||
|
fn try_from(value: TransactionSigned) -> Result<Self, Self::Error> {
|
||||||
|
value.0.try_into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<TransactionSigned>
|
||||||
|
for EthereumTxEnvelope<TxEip4844WithSidecar<BlobTransactionSidecarVariant>>
|
||||||
|
{
|
||||||
|
type Error = <InnerType as TryInto<
|
||||||
|
EthereumTxEnvelope<TxEip4844WithSidecar<BlobTransactionSidecarVariant>>,
|
||||||
|
>>::Error;
|
||||||
|
|
||||||
|
fn try_from(value: TransactionSigned) -> Result<Self, Self::Error> {
|
||||||
|
value.0.try_into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<EthereumTxEnvelope<TxEip4844WithSidecar<BlobTransactionSidecarVariant>>>
|
||||||
|
for TransactionSigned
|
||||||
|
{
|
||||||
|
fn from(
|
||||||
|
value: EthereumTxEnvelope<TxEip4844WithSidecar<BlobTransactionSidecarVariant>>,
|
||||||
|
) -> Self {
|
||||||
|
Self(value.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Compress for TransactionSigned {
|
||||||
|
type Compressed = Vec<u8>;
|
||||||
|
|
||||||
|
fn compress(self) -> Self::Compressed {
|
||||||
|
self.0.compress()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compress_to_buf<B: bytes::BufMut + AsMut<[u8]>>(&self, buf: &mut B) {
|
||||||
|
self.0.compress_to_buf(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Decompress for TransactionSigned {
|
||||||
|
fn decompress(value: &[u8]) -> Result<Self, DatabaseError> {
|
||||||
|
Ok(Self(InnerType::decompress(value)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn convert_to_eth_block_body(value: BlockBody) -> alloy_consensus::BlockBody<InnerType> {
|
||||||
|
alloy_consensus::BlockBody {
|
||||||
|
transactions: value.transactions.into_iter().map(|tx| tx.0).collect(),
|
||||||
|
ommers: value.ommers,
|
||||||
|
withdrawals: value.withdrawals,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn convert_to_hl_block_body(value: alloy_consensus::BlockBody<InnerType>) -> BlockBody {
|
||||||
|
BlockBody {
|
||||||
|
transactions: value.transactions.into_iter().map(TransactionSigned).collect(),
|
||||||
|
ommers: value.ommers,
|
||||||
|
withdrawals: value.withdrawals,
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
chainspec::HlChainSpec,
|
chainspec::HlChainSpec,
|
||||||
node::{
|
node::{
|
||||||
|
primitives::TransactionSigned,
|
||||||
rpc::{HlEthApi, HlNodeCore},
|
rpc::{HlEthApi, HlNodeCore},
|
||||||
HlBlock, HlPrimitives,
|
HlBlock, HlPrimitives,
|
||||||
},
|
},
|
||||||
@ -10,7 +11,7 @@ use alloy_primitives::B256;
|
|||||||
use reth::{
|
use reth::{
|
||||||
api::NodeTypes,
|
api::NodeTypes,
|
||||||
builder::FullNodeComponents,
|
builder::FullNodeComponents,
|
||||||
primitives::{Receipt, SealedHeader, TransactionMeta, TransactionSigned},
|
primitives::{Receipt, SealedHeader, TransactionMeta},
|
||||||
providers::{BlockReaderIdExt, ProviderHeader, ReceiptProvider, TransactionsProvider},
|
providers::{BlockReaderIdExt, ProviderHeader, ReceiptProvider, TransactionsProvider},
|
||||||
rpc::{
|
rpc::{
|
||||||
eth::EthApiTypes,
|
eth::EthApiTypes,
|
||||||
@ -64,7 +65,7 @@ where
|
|||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(idx, (tx, receipt))| {
|
.map(|(idx, (tx, receipt))| {
|
||||||
let meta = TransactionMeta {
|
let meta = TransactionMeta {
|
||||||
tx_hash: *tx.tx_hash(),
|
tx_hash: *tx.0.tx_hash(),
|
||||||
index: idx as u64,
|
index: idx as u64,
|
||||||
block_hash,
|
block_hash,
|
||||||
block_number,
|
block_number,
|
||||||
@ -72,7 +73,7 @@ where
|
|||||||
excess_blob_gas,
|
excess_blob_gas,
|
||||||
timestamp,
|
timestamp,
|
||||||
};
|
};
|
||||||
EthReceiptBuilder::new(tx, meta, receipt, &receipts, blob_params)
|
EthReceiptBuilder::new(&tx.0, meta, receipt, &receipts, blob_params)
|
||||||
.map(|builder| builder.build())
|
.map(|builder| builder.build())
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, Self::Error>>()
|
.collect::<Result<Vec<_>, Self::Error>>()
|
||||||
@ -164,6 +165,6 @@ where
|
|||||||
.ok_or(EthApiError::HeaderNotFound(hash.into()))?;
|
.ok_or(EthApiError::HeaderNotFound(hash.into()))?;
|
||||||
let blob_params = self.provider().chain_spec().blob_params_at_timestamp(meta.timestamp);
|
let blob_params = self.provider().chain_spec().blob_params_at_timestamp(meta.timestamp);
|
||||||
|
|
||||||
Ok(EthReceiptBuilder::new(&tx, meta, &receipt, &all_receipts, blob_params)?.build())
|
Ok(EthReceiptBuilder::new(&tx.0, meta, &receipt, &all_receipts, blob_params)?.build())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,16 @@
|
|||||||
use super::HlNodeCore;
|
use super::HlNodeCore;
|
||||||
use crate::{node::rpc::HlEthApi, HlPrimitives};
|
use crate::{
|
||||||
|
node::{
|
||||||
|
primitives::{tx_wrapper::convert_recovered, TransactionSigned},
|
||||||
|
rpc::HlEthApi,
|
||||||
|
},
|
||||||
|
HlPrimitives,
|
||||||
|
};
|
||||||
use alloy_network::{Ethereum, Network};
|
use alloy_network::{Ethereum, Network};
|
||||||
use alloy_primitives::{Bytes, Signature, B256};
|
use alloy_primitives::{Bytes, Signature, B256};
|
||||||
use reth::{
|
use reth::{
|
||||||
builder::FullNodeComponents,
|
builder::FullNodeComponents,
|
||||||
primitives::{Receipt, Recovered, TransactionSigned},
|
primitives::{Receipt, Recovered},
|
||||||
providers::ReceiptProvider,
|
providers::ReceiptProvider,
|
||||||
rpc::{
|
rpc::{
|
||||||
eth::helpers::types::EthRpcConverter,
|
eth::helpers::types::EthRpcConverter,
|
||||||
@ -18,6 +24,7 @@ use reth_rpc_eth_api::{
|
|||||||
helpers::{EthSigner, EthTransactions, LoadTransaction, SpawnBlocking},
|
helpers::{EthSigner, EthTransactions, LoadTransaction, SpawnBlocking},
|
||||||
FromEthApiError, FullEthApiTypes, RpcNodeCore, RpcNodeCoreExt, TransactionCompat,
|
FromEthApiError, FullEthApiTypes, RpcNodeCore, RpcNodeCoreExt, TransactionCompat,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl<N> LoadTransaction for HlEthApi<N>
|
impl<N> LoadTransaction for HlEthApi<N>
|
||||||
where
|
where
|
||||||
Self: SpawnBlocking + FullEthApiTypes + RpcNodeCoreExt,
|
Self: SpawnBlocking + FullEthApiTypes + RpcNodeCoreExt,
|
||||||
@ -41,7 +48,7 @@ where
|
|||||||
tx_info: TransactionInfo,
|
tx_info: TransactionInfo,
|
||||||
) -> Result<Self::Transaction, Self::Error> {
|
) -> Result<Self::Transaction, Self::Error> {
|
||||||
let builder = EthRpcConverter::default();
|
let builder = EthRpcConverter::default();
|
||||||
builder.fill(tx, tx_info)
|
builder.fill(convert_recovered(tx), tx_info)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_simulate_v1_transaction(
|
fn build_simulate_v1_transaction(
|
||||||
@ -54,7 +61,10 @@ where
|
|||||||
|
|
||||||
// Create an empty signature for the transaction.
|
// Create an empty signature for the transaction.
|
||||||
let signature = Signature::new(Default::default(), Default::default(), false);
|
let signature = Signature::new(Default::default(), Default::default(), false);
|
||||||
Ok(TransactionSigned::new_unhashed(tx.into(), signature))
|
Ok(TransactionSigned(reth_primitives::TransactionSigned::new_unhashed(
|
||||||
|
tx.into(),
|
||||||
|
signature,
|
||||||
|
)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,10 @@
|
|||||||
use crate::{node::types::ReadPrecompileCalls, HlBlock, HlBlockBody, HlPrimitives};
|
use crate::{
|
||||||
|
node::{
|
||||||
|
primitives::tx_wrapper::{convert_to_eth_block_body, convert_to_hl_block_body},
|
||||||
|
types::ReadPrecompileCalls,
|
||||||
|
},
|
||||||
|
HlBlock, HlBlockBody, HlPrimitives,
|
||||||
|
};
|
||||||
use alloy_consensus::BlockHeader;
|
use alloy_consensus::BlockHeader;
|
||||||
use alloy_primitives::Bytes;
|
use alloy_primitives::Bytes;
|
||||||
use reth_chainspec::EthereumHardforks;
|
use reth_chainspec::EthereumHardforks;
|
||||||
@ -87,7 +93,7 @@ where
|
|||||||
for (block_number, body) in bodies {
|
for (block_number, body) in bodies {
|
||||||
match body {
|
match body {
|
||||||
Some(HlBlockBody { inner, sidecars: _, read_precompile_calls: rpc }) => {
|
Some(HlBlockBody { inner, sidecars: _, read_precompile_calls: rpc }) => {
|
||||||
eth_bodies.push((block_number, Some(inner)));
|
eth_bodies.push((block_number, Some(convert_to_eth_block_body(inner))));
|
||||||
read_precompile_calls.push((block_number, rpc));
|
read_precompile_calls.push((block_number, rpc));
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
@ -128,14 +134,22 @@ where
|
|||||||
inputs: Vec<ReadBodyInput<'_, Self::Block>>,
|
inputs: Vec<ReadBodyInput<'_, Self::Block>>,
|
||||||
) -> ProviderResult<Vec<HlBlockBody>> {
|
) -> ProviderResult<Vec<HlBlockBody>> {
|
||||||
let read_precompile_calls = self.read_precompile_calls(provider, &inputs)?;
|
let read_precompile_calls = self.read_precompile_calls(provider, &inputs)?;
|
||||||
let eth_bodies = self.0.read_block_bodies(provider, inputs)?;
|
let eth_bodies = self.0.read_block_bodies(
|
||||||
|
provider,
|
||||||
|
inputs
|
||||||
|
.into_iter()
|
||||||
|
.map(|(header, transactions)| {
|
||||||
|
(header, transactions.into_iter().map(|tx| tx.0).collect())
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
)?;
|
||||||
|
|
||||||
// NOTE: sidecars are not used in HyperEVM yet.
|
// NOTE: sidecars are not used in HyperEVM yet.
|
||||||
Ok(eth_bodies
|
Ok(eth_bodies
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.zip(read_precompile_calls)
|
.zip(read_precompile_calls)
|
||||||
.map(|(inner, read_precompile_calls)| HlBlockBody {
|
.map(|(inner, read_precompile_calls)| HlBlockBody {
|
||||||
inner,
|
inner: convert_to_hl_block_body(inner),
|
||||||
sidecars: None,
|
sidecars: None,
|
||||||
read_precompile_calls,
|
read_precompile_calls,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
//!
|
//!
|
||||||
//! Changes:
|
//! Changes:
|
||||||
//! - ReadPrecompileCalls supports RLP encoding / decoding
|
//! - ReadPrecompileCalls supports RLP encoding / decoding
|
||||||
use alloy_primitives::{Address, Bytes, Log};
|
use alloy_primitives::{Address, Bytes, Log, B256};
|
||||||
use alloy_rlp::{Decodable, Encodable, RlpDecodable, RlpEncodable};
|
use alloy_rlp::{Decodable, Encodable, RlpDecodable, RlpEncodable};
|
||||||
use bytes::BufMut;
|
use bytes::BufMut;
|
||||||
use revm::primitives::HashMap;
|
use revm::primitives::HashMap;
|
||||||
@ -69,6 +69,16 @@ impl BlockAndReceipts {
|
|||||||
MAINNET_CHAIN_ID,
|
MAINNET_CHAIN_ID,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn hash(&self) -> B256 {
|
||||||
|
let EvmBlock::Reth115(block) = &self.block;
|
||||||
|
block.header.hash
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn number(&self) -> u64 {
|
||||||
|
let EvmBlock::Reth115(block) = &self.block;
|
||||||
|
block.header.header.number
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
@ -1,15 +1,17 @@
|
|||||||
//! Copy of reth codebase to preserve serialization compatibility
|
//! Copy of reth codebase to preserve serialization compatibility
|
||||||
use alloy_consensus::{Header, Signed, TxEip1559, TxEip2930, TxEip4844, TxEip7702, TxLegacy};
|
use alloy_consensus::{Header, Signed, TxEip1559, TxEip2930, TxEip4844, TxEip7702, TxLegacy};
|
||||||
use alloy_primitives::{Address, BlockHash, Signature, TxKind, U256};
|
use alloy_primitives::{Address, BlockHash, Signature, TxKind, U256};
|
||||||
|
use reth_primitives::TransactionSigned as RethTxSigned;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
collections::BTreeMap,
|
collections::BTreeMap,
|
||||||
sync::{Arc, LazyLock, Mutex},
|
sync::{Arc, LazyLock, RwLock},
|
||||||
};
|
};
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
node::{
|
node::{
|
||||||
|
primitives::TransactionSigned as TxSigned,
|
||||||
spot_meta::{erc20_contract_to_spot_token, SpotId},
|
spot_meta::{erc20_contract_to_spot_token, SpotId},
|
||||||
types::{ReadPrecompileCalls, SystemTx},
|
types::{ReadPrecompileCalls, SystemTx},
|
||||||
},
|
},
|
||||||
@ -42,23 +44,23 @@ pub struct TransactionSigned {
|
|||||||
transaction: Transaction,
|
transaction: Transaction,
|
||||||
}
|
}
|
||||||
impl TransactionSigned {
|
impl TransactionSigned {
|
||||||
fn to_reth_transaction(&self) -> reth_primitives::TransactionSigned {
|
fn to_reth_transaction(&self) -> TxSigned {
|
||||||
match self.transaction.clone() {
|
match self.transaction.clone() {
|
||||||
Transaction::Legacy(tx) => {
|
Transaction::Legacy(tx) => {
|
||||||
reth_primitives::TransactionSigned::Legacy(Signed::new_unhashed(tx, self.signature))
|
TxSigned(RethTxSigned::Legacy(Signed::new_unhashed(tx, self.signature)))
|
||||||
|
}
|
||||||
|
Transaction::Eip2930(tx) => {
|
||||||
|
TxSigned(RethTxSigned::Eip2930(Signed::new_unhashed(tx, self.signature)))
|
||||||
|
}
|
||||||
|
Transaction::Eip1559(tx) => {
|
||||||
|
TxSigned(RethTxSigned::Eip1559(Signed::new_unhashed(tx, self.signature)))
|
||||||
|
}
|
||||||
|
Transaction::Eip4844(tx) => {
|
||||||
|
TxSigned(RethTxSigned::Eip4844(Signed::new_unhashed(tx, self.signature)))
|
||||||
|
}
|
||||||
|
Transaction::Eip7702(tx) => {
|
||||||
|
TxSigned(RethTxSigned::Eip7702(Signed::new_unhashed(tx, self.signature)))
|
||||||
}
|
}
|
||||||
Transaction::Eip2930(tx) => reth_primitives::TransactionSigned::Eip2930(
|
|
||||||
Signed::new_unhashed(tx, self.signature),
|
|
||||||
),
|
|
||||||
Transaction::Eip1559(tx) => reth_primitives::TransactionSigned::Eip1559(
|
|
||||||
Signed::new_unhashed(tx, self.signature),
|
|
||||||
),
|
|
||||||
Transaction::Eip4844(tx) => reth_primitives::TransactionSigned::Eip4844(
|
|
||||||
Signed::new_unhashed(tx, self.signature),
|
|
||||||
),
|
|
||||||
Transaction::Eip7702(tx) => reth_primitives::TransactionSigned::Eip7702(
|
|
||||||
Signed::new_unhashed(tx, self.signature),
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -67,24 +69,21 @@ type BlockBody = alloy_consensus::BlockBody<TransactionSigned, Header>;
|
|||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct SealedHeader {
|
pub struct SealedHeader {
|
||||||
hash: BlockHash,
|
pub hash: BlockHash,
|
||||||
header: Header,
|
pub header: Header,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct SealedBlock {
|
pub struct SealedBlock {
|
||||||
/// Sealed Header.
|
/// Sealed Header.
|
||||||
header: SealedHeader,
|
pub header: SealedHeader,
|
||||||
/// the block's body.
|
/// the block's body.
|
||||||
body: BlockBody,
|
pub body: BlockBody,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn system_tx_to_reth_transaction(
|
fn system_tx_to_reth_transaction(transaction: &SystemTx, chain_id: u64) -> TxSigned {
|
||||||
transaction: &SystemTx,
|
static EVM_MAP: LazyLock<Arc<RwLock<BTreeMap<Address, SpotId>>>> =
|
||||||
chain_id: u64,
|
LazyLock::new(|| Arc::new(RwLock::new(BTreeMap::new())));
|
||||||
) -> reth_primitives::TransactionSigned {
|
|
||||||
static EVM_MAP: LazyLock<Arc<Mutex<BTreeMap<Address, SpotId>>>> =
|
|
||||||
LazyLock::new(|| Arc::new(Mutex::new(BTreeMap::new())));
|
|
||||||
{
|
{
|
||||||
let Transaction::Legacy(tx) = &transaction.tx else {
|
let Transaction::Legacy(tx) = &transaction.tx else {
|
||||||
panic!("Unexpected transaction type");
|
panic!("Unexpected transaction type");
|
||||||
@ -96,16 +95,16 @@ fn system_tx_to_reth_transaction(
|
|||||||
U256::from(0x1)
|
U256::from(0x1)
|
||||||
} else {
|
} else {
|
||||||
loop {
|
loop {
|
||||||
if let Some(spot) = EVM_MAP.lock().unwrap().get(&to) {
|
if let Some(spot) = EVM_MAP.read().unwrap().get(&to) {
|
||||||
break spot.to_s();
|
break spot.to_s();
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("Contract not found: {:?} from spot mapping, fetching again...", to);
|
info!("Contract not found: {:?} from spot mapping, fetching again...", to);
|
||||||
*EVM_MAP.lock().unwrap() = erc20_contract_to_spot_token(chain_id).unwrap();
|
*EVM_MAP.write().unwrap() = erc20_contract_to_spot_token(chain_id).unwrap();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let signature = Signature::new(U256::from(0x1), s, true);
|
let signature = Signature::new(U256::from(0x1), s, true);
|
||||||
reth_primitives::TransactionSigned::Legacy(Signed::new_unhashed(tx.clone(), signature))
|
TxSigned(RethTxSigned::Legacy(Signed::new_unhashed(tx.clone(), signature)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user