From 761cf507343844ca0de18c6c72cd00d7b6d7ccff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Keszey=20D=C3=A1niel?= Date: Mon, 26 Aug 2024 13:08:40 +0200 Subject: [PATCH 1/5] distinguish chains --- bin/reth/src/rpc.rs | 1 + crates/e2e-test-utils/src/node.rs | 1 + .../rpc-eth-api/src/helpers/transaction.rs | 43 +++++++++++- .../L2_txn_simulation/sendATxnToL2Rpc.py | 69 +++++++++++++++++++ 4 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 packages/protocol/scripts/L2_txn_simulation/sendATxnToL2Rpc.py diff --git a/bin/reth/src/rpc.rs b/bin/reth/src/rpc.rs index 21830492e182..5f3826336e3e 100644 --- a/bin/reth/src/rpc.rs +++ b/bin/reth/src/rpc.rs @@ -28,6 +28,7 @@ where /// Injects a raw transaction into the node tx pool via RPC server pub async fn inject_tx(&mut self, raw_tx: Bytes) -> EthResult { let eth_api = self.inner.eth_api(); + println!("Dani debug: Why not called? {:?}", raw_tx); // -> Not called most prob. because it is called during actual L2 execution. So the call to advance_block() in our main() will call it. eth_api.send_raw_transaction(raw_tx).await } diff --git a/crates/e2e-test-utils/src/node.rs b/crates/e2e-test-utils/src/node.rs index 3bd203277ac6..7d58d67adc3f 100644 --- a/crates/e2e-test-utils/src/node.rs +++ b/crates/e2e-test-utils/src/node.rs @@ -88,6 +88,7 @@ where let mut chain = Vec::with_capacity(length as usize); for i in 0..length { let raw_tx = tx_generator(i).await; + println!("Dani debug: advance()'s inject_tx"); let tx_hash = self.rpc.inject_tx(raw_tx).await?; let (payload, eth_attr) = self.advance_block(vec![], attributes_generator).await?; let block_hash = payload.block().hash(); diff --git a/crates/rpc/rpc-eth-api/src/helpers/transaction.rs b/crates/rpc/rpc-eth-api/src/helpers/transaction.rs index fa4c9be30787..11ada0d349ed 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/transaction.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/transaction.rs @@ -6,8 +6,8 @@ use std::{fmt, ops::Deref, sync::Arc}; use alloy_dyn_abi::TypedData; use futures::Future; use reth_primitives::{ - Address, BlockId, Bytes, FromRecoveredPooledTransaction, IntoRecoveredTransaction, Receipt, - SealedBlockWithSenders, TransactionMeta, TransactionSigned, TxHash, TxKind, B256, U256, + Address, BlockId, Bytes, FromRecoveredPooledTransaction, IntoRecoveredTransaction, Receipt,Signature, + SealedBlockWithSenders, TransactionMeta, TransactionSigned, TxHash, TxKind, B256, U256, PooledTransactionsElementEcRecovered, PooledTransactionsElement, transaction::extract_chain_id, }; use reth_provider::{BlockReaderIdExt, ReceiptProvider, TransactionsProvider}; use reth_rpc_eth_types::{ @@ -23,6 +23,7 @@ use reth_rpc_types::{ }; use reth_rpc_types_compat::transaction::from_recovered_with_block_context; use reth_transaction_pool::{TransactionOrigin, TransactionPool}; +use revm_primitives::{alloy_primitives::private::alloy_rlp::{self, Decodable}}; use super::EthSigner; @@ -231,11 +232,30 @@ pub trait EthTransactions: LoadTransaction { } } + fn get_chain_id(tx: &PooledTransactionsElementEcRecovered) -> alloy_rlp::Result> { + // Get the signature from the transaction + let signature = tx.signature(); + + // Get the v value from the signature + let v = signature.v(None); // We pass None as we don't know the chain_id yet + + // Use the public extract_chain_id function + let (_, chain_id) = extract_chain_id(v)?; + + Ok(chain_id) + } + /// Decodes and recovers the transaction and submits it to the pool. /// /// Returns the hash of the transaction. fn send_raw_transaction(&self, tx: Bytes) -> impl Future> + Send { async move { + + // It seems that both the 8545 RPC server (L1) and 10110 (L2 dedicated RPC) is routing into here BUT the send ether (sendATxnToL2Rpc.py) execution is happening on the correct chain. + // We (as builders) somehow gotta: + // 1. recognize the source (?) -> If L2 rpc/port then route towards the builder and not yet build L2 blocks + // 2. If block builder is full (or profitable, or some other sophisticated mechanism (?)) then flush towards TaikoL1 as calldata (or blob), then the 'BlockProposed' event is what will trigger the L2 execution. + println!("Dani debug: Raw txn bytes:{:?}", tx); // On optimism, transactions are forwarded directly to the sequencer to be included in // blocks that it builds. if let Some(client) = self.raw_tx_forwarder().as_ref() { @@ -244,6 +264,23 @@ pub trait EthTransactions: LoadTransaction { } let recovered = recover_raw_transaction(tx)?; + + match Self::get_chain_id(&recovered) { + Ok(maybe_chain_id) => { + if let Some(chain_id) = maybe_chain_id { + println!("Transaction is on network with chain ID: {}", chain_id); + // Perform your special logic here based on chain_id + } else { + println!("Transaction is pre-EIP-155 (no chain ID)"); + // Handle pre-EIP-155 transactions (no chain ID) + } + }, + Err(e) => { + eprintln!("Error decoding chain ID: {:?}", e); + // Handle RLP decoding error + } + } + let pool_transaction = ::Transaction::from_recovered_pooled_transaction( recovered, @@ -252,6 +289,8 @@ pub trait EthTransactions: LoadTransaction { // submit the transaction to the pool with a `Local` origin let hash = self.pool().add_transaction(TransactionOrigin::Local, pool_transaction).await?; + + println!("Dani debug: TXN hash:{:?}", hash); Ok(hash) } diff --git a/packages/protocol/scripts/L2_txn_simulation/sendATxnToL2Rpc.py b/packages/protocol/scripts/L2_txn_simulation/sendATxnToL2Rpc.py new file mode 100644 index 000000000000..4ba75d547cfb --- /dev/null +++ b/packages/protocol/scripts/L2_txn_simulation/sendATxnToL2Rpc.py @@ -0,0 +1,69 @@ +from web3 import Web3 +from eth_abi import encode +import argparse + +RPC_URL_L2 = 'http://127.0.0.1:' # Anything is fine for now as long as we dont have the L2 network, but if we have we can automate nonce and gas settings +w3_taiko_l2 = Web3(Web3.HTTPProvider(RPC_URL_L2)) + +# Some pre-loaded ETH addresses from Kurtosis private network (NO secret, no harm to use for private testnets!) +sender_addresses = ['0x8943545177806ED17B9F23F0a21ee5948eCaa776'] +sender_pks = ['bcdf20249abf0ed6d944c0288fad489e33f66b3960d9e6229c1cd214ed3bbe31'] + +receiver = '0xf93Ee4Cf8c6c40b329b0c0626F28333c132CF241' # This address also has pre-loaded ETH addresses + +parser = argparse.ArgumentParser() + +parser.add_argument("-p", "--port", help="port on localhost", + type=str, required=True) +# parser.add_argument("-c", "--chainid", help="l2 chainId", +# type=int, required=True) + +transaction_list = [] + +if __name__ == "__main__": + args = parser.parse_args() + port = args.port + w3_taiko_l2 = Web3(Web3.HTTPProvider(RPC_URL_L2+port)) + chainId = 167010 + + # Build the new tx list + idx = 0 + for sender in sender_addresses: + # Build the tx + transaction = { + 'chainId': chainId, + 'from': sender, + 'to': receiver, + 'value': w3_taiko_l2.to_wei('1', 'ether'), + 'nonce': w3_taiko_l2.eth.get_transaction_count(sender), + 'gas': 200000, + 'maxFeePerGas': 2000000000, # w3_taiko_l2.eth.gas_price or something + 'maxPriorityFeePerGas': 1000000000, + } + + # Debug prints of balance + # # Get the balance + # balance_wei = w3_taiko_l2.eth.get_balance(sender) + + # # Convert balance from Wei to Ether + # balance_eth = w3_taiko_l2.from_wei(balance_wei, 'ether') + # print("Balance before:", balance_eth) + + # 2. Sign tx with a private key + signed_txn = w3_taiko_l2.eth.account.sign_transaction(transaction, sender_pks[idx]) + + # print("RawTransaction:") + # print(signed_txn.rawTransaction) + print("RawTransaction.hex():") + print(signed_txn.rawTransaction.hex()) + + txn_hash = w3_taiko_l2.eth.send_raw_transaction(signed_txn.rawTransaction) + print("Txn hash:") + print(txn_hash.hex()) + + # # Get the balance + # balance_wei = w3_taiko_l2.eth.get_balance(sender) + + # # Convert balance from Wei to Ether + # balance_eth = w3_taiko_l2.from_wei(balance_wei, 'ether') + # print("Balance after:", balance_eth) \ No newline at end of file From 75924d79e20f5eaec1004c12c0ad74ed286ffbc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Keszey=20D=C3=A1niel?= Date: Mon, 26 Aug 2024 13:12:14 +0200 Subject: [PATCH 2/5] shorten debug log --- crates/rpc/rpc-eth-api/src/helpers/transaction.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/crates/rpc/rpc-eth-api/src/helpers/transaction.rs b/crates/rpc/rpc-eth-api/src/helpers/transaction.rs index 11ada0d349ed..9c8a34539f33 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/transaction.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/transaction.rs @@ -268,16 +268,13 @@ pub trait EthTransactions: LoadTransaction { match Self::get_chain_id(&recovered) { Ok(maybe_chain_id) => { if let Some(chain_id) = maybe_chain_id { - println!("Transaction is on network with chain ID: {}", chain_id); - // Perform your special logic here based on chain_id + println!("Dani debug: txn chain ID: {}", chain_id); } else { - println!("Transaction is pre-EIP-155 (no chain ID)"); - // Handle pre-EIP-155 transactions (no chain ID) + println!("Dani debug: pre-EIP-155 (no chain ID)"); } }, Err(e) => { eprintln!("Error decoding chain ID: {:?}", e); - // Handle RLP decoding error } } From d632c0d3029ce9854587714c2b5d1d40b5415bb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Keszey=20D=C3=A1niel?= Date: Tue, 27 Aug 2024 11:10:11 +0200 Subject: [PATCH 3/5] debugging --- bin/reth/src/payload.rs | 3 +++ crates/ethereum/evm/src/execute.rs | 2 ++ .../rpc-eth-api/src/helpers/transaction.rs | 26 ------------------- 3 files changed, 5 insertions(+), 26 deletions(-) diff --git a/bin/reth/src/payload.rs b/bin/reth/src/payload.rs index 24343843fa7d..029693e8b083 100644 --- a/bin/reth/src/payload.rs +++ b/bin/reth/src/payload.rs @@ -62,6 +62,9 @@ impl PayloadTestContext { pub async fn expect_built_payload(&mut self) -> eyre::Result { let second_event = self.payload_event_stream.next().await.unwrap()?; if let reth::payload::Events::BuiltPayload(payload) = second_event { + let payload_to_debug = payload.clone(); + println!("Dani debug expect_built_payload: when is it called: {:?}", payload_to_debug.block().number); + println!("Dani debug expect_built_payload: block's txns: {:?}", payload_to_debug.block().body); Ok(payload) } else { panic!("Expect a built payload event."); diff --git a/crates/ethereum/evm/src/execute.rs b/crates/ethereum/evm/src/execute.rs index fc077b86290e..930548d51553 100644 --- a/crates/ethereum/evm/src/execute.rs +++ b/crates/ethereum/evm/src/execute.rs @@ -314,6 +314,8 @@ where // 1. prepare state on new block self.on_new_block(&block.header); + println!("Dani debug: Execution happens on chainid: {:?}", self.chain_spec().chain()); + // 2. configure the evm and execute let env = self.evm_env_for_block(&block.header, total_difficulty); let output = { diff --git a/crates/rpc/rpc-eth-api/src/helpers/transaction.rs b/crates/rpc/rpc-eth-api/src/helpers/transaction.rs index 9c8a34539f33..2e8dedc5b3ce 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/transaction.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/transaction.rs @@ -232,19 +232,6 @@ pub trait EthTransactions: LoadTransaction { } } - fn get_chain_id(tx: &PooledTransactionsElementEcRecovered) -> alloy_rlp::Result> { - // Get the signature from the transaction - let signature = tx.signature(); - - // Get the v value from the signature - let v = signature.v(None); // We pass None as we don't know the chain_id yet - - // Use the public extract_chain_id function - let (_, chain_id) = extract_chain_id(v)?; - - Ok(chain_id) - } - /// Decodes and recovers the transaction and submits it to the pool. /// /// Returns the hash of the transaction. @@ -264,19 +251,6 @@ pub trait EthTransactions: LoadTransaction { } let recovered = recover_raw_transaction(tx)?; - - match Self::get_chain_id(&recovered) { - Ok(maybe_chain_id) => { - if let Some(chain_id) = maybe_chain_id { - println!("Dani debug: txn chain ID: {}", chain_id); - } else { - println!("Dani debug: pre-EIP-155 (no chain ID)"); - } - }, - Err(e) => { - eprintln!("Error decoding chain ID: {:?}", e); - } - } let pool_transaction = ::Transaction::from_recovered_pooled_transaction( From e703594620fb936f50a0da0ceaad7a9c9b8b6ad6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Keszey=20D=C3=A1niel?= Date: Wed, 28 Aug 2024 11:51:40 +0200 Subject: [PATCH 4/5] debug further --- bin/reth/src/rpc.rs | 1 - crates/blockchain-tree/src/blockchain_tree.rs | 1 + crates/ethereum/evm/src/execute.rs | 3 +-- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/bin/reth/src/rpc.rs b/bin/reth/src/rpc.rs index 5f3826336e3e..21830492e182 100644 --- a/bin/reth/src/rpc.rs +++ b/bin/reth/src/rpc.rs @@ -28,7 +28,6 @@ where /// Injects a raw transaction into the node tx pool via RPC server pub async fn inject_tx(&mut self, raw_tx: Bytes) -> EthResult { let eth_api = self.inner.eth_api(); - println!("Dani debug: Why not called? {:?}", raw_tx); // -> Not called most prob. because it is called during actual L2 execution. So the call to advance_block() in our main() will call it. eth_api.send_raw_transaction(raw_tx).await } diff --git a/crates/blockchain-tree/src/blockchain_tree.rs b/crates/blockchain-tree/src/blockchain_tree.rs index c07ae576c60b..570a73eb7fa6 100644 --- a/crates/blockchain-tree/src/blockchain_tree.rs +++ b/crates/blockchain-tree/src/blockchain_tree.rs @@ -393,6 +393,7 @@ where let provider = self.externals.provider_factory.provider()?; + println!("Dani debug: appears before validate_and_execute, if so, chain_id: {:?}", provider.chain_spec().chain().id()); // Validate that the block is post merge let parent_td = provider .header_td(&block.parent_hash)? diff --git a/crates/ethereum/evm/src/execute.rs b/crates/ethereum/evm/src/execute.rs index 930548d51553..b0a890455ea3 100644 --- a/crates/ethereum/evm/src/execute.rs +++ b/crates/ethereum/evm/src/execute.rs @@ -311,11 +311,10 @@ where ) -> Result { println!("execute_without_verification"); + // Original execution logic // 1. prepare state on new block self.on_new_block(&block.header); - println!("Dani debug: Execution happens on chainid: {:?}", self.chain_spec().chain()); - // 2. configure the evm and execute let env = self.evm_env_for_block(&block.header, total_difficulty); let output = { From 1133929476242467819339cc251ed0e81e867e1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Keszey=20D=C3=A1niel?= Date: Thu, 29 Aug 2024 12:17:35 +0200 Subject: [PATCH 5/5] more debug prints --- crates/blockchain-tree/src/chain.rs | 8 +++- crates/rpc/rpc-engine-api/src/engine_api.rs | 41 +++++++++++++++---- .../provider/src/providers/database/mod.rs | 5 +++ 3 files changed, 45 insertions(+), 9 deletions(-) diff --git a/crates/blockchain-tree/src/chain.rs b/crates/blockchain-tree/src/chain.rs index 5eca9c78933f..67ef9b293019 100644 --- a/crates/blockchain-tree/src/chain.rs +++ b/crates/blockchain-tree/src/chain.rs @@ -15,7 +15,7 @@ use reth_evm::execute::{BlockExecutionOutput, BlockExecutorProvider, Executor}; use reth_execution_errors::BlockExecutionError; use reth_execution_types::{Chain, ExecutionOutcome}; use reth_primitives::{ - BlockHash, BlockNumber, ForkBlock, GotExpected, SealedBlockWithSenders, SealedHeader, U256, + BlockHash, BlockNumber, ForkBlock, GotExpected, SealedBlockWithSenders, SealedHeader, U256, BufMut, }; use reth_provider::{ providers::{BundleStateProvider, ConsistentDbView}, @@ -293,6 +293,10 @@ impl AppendableChain { canonical_fork, }; + + println!("Dani debug before: validate_and_execute"); + println!("ID: {:?}", externals.provider_factory.chain_spec().chain().id()); + let (block_state, _) = Self::validate_and_execute( block.clone(), parent_block, @@ -304,6 +308,8 @@ impl AppendableChain { // extend the state. self.chain.append_block(block, block_state); + println!("Dani debug after text: validate_and_execute"); + Ok(()) } } diff --git a/crates/rpc/rpc-engine-api/src/engine_api.rs b/crates/rpc/rpc-engine-api/src/engine_api.rs index 862a8ca02c7f..892fbcbf11e6 100644 --- a/crates/rpc/rpc-engine-api/src/engine_api.rs +++ b/crates/rpc/rpc-engine-api/src/engine_api.rs @@ -5,7 +5,9 @@ use async_trait::async_trait; use jsonrpsee_core::RpcResult; use reth_beacon_consensus::BeaconConsensusEngineHandle; use reth_chainspec::ChainSpec; -use reth_engine_primitives::EngineTypes; +use reth_engine_primitives::{ + EngineTypes, BuiltPayload, +}; use reth_evm::provider::EvmEnvProvider; use reth_payload_builder::PayloadStore; use reth_payload_primitives::{ @@ -319,13 +321,36 @@ where )?; // Now resolve the payload - self.inner - .payload_store - .resolve(payload_id) - .await - .ok_or(EngineApiError::UnknownPayload)? - .map_err(|_| EngineApiError::UnknownPayload)? - .try_into() + let built_payload = self.inner + .payload_store + .resolve(payload_id) + .await + .ok_or(EngineApiError::UnknownPayload)? + .map_err(|_| EngineApiError::UnknownPayload)?; + + // Get the chain ID + let chain_id = self.inner.chain_spec.chain().id(); + + // Debug print only for a specific chain ID (e.g., 167010) + if chain_id == 167010 { + let block = built_payload.block(); + println!("Dani debug : BuiltPayload for chain_id {} and payload_id {:?}:", chain_id, payload_id); + println!(" Block Number: {:?}", block.number); + println!(" Block Hash: {:?}", block.hash()); + println!(" Parent Hash: {:?}", block.parent_hash); + println!(" State Root: {:?}", block.state_root); + println!(" Transactions Count: {}", block.body.len()); + println!(" Ommers Count: {}", block.ommers.len()); + println!(" Has Withdrawals: {}", block.withdrawals.is_some()); + println!(" Has Requests: {}", block.requests.is_some()); + println!(" Timestamp: {:?}", block.timestamp); + println!(" Gas Limit: {:?}", block.gas_limit); + println!(" Gas Used: {:?}", block.gas_used); + println!(" Base Fee Per Gas: {:?}", block.base_fee_per_gas); + println!(" Fees: {:?}", built_payload.fees()); + } + + built_payload.try_into() .map_err(|_| { warn!("could not transform built payload into ExecutionPayloadV3"); EngineApiError::UnknownPayload diff --git a/crates/storage/provider/src/providers/database/mod.rs b/crates/storage/provider/src/providers/database/mod.rs index a9df016a8add..df14b31a8700 100644 --- a/crates/storage/provider/src/providers/database/mod.rs +++ b/crates/storage/provider/src/providers/database/mod.rs @@ -77,6 +77,11 @@ impl ProviderFactory { &self.db } + /// Returns reference to the underlying chain_spec. + pub fn chain_spec(&self) -> Arc { + self.chain_spec.clone() + } + #[cfg(any(test, feature = "test-utils"))] /// Consumes Self and returns DB pub fn into_db(self) -> Arc {