Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

L2 builder preparation #34

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions bin/reth/src/payload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ impl<E: EngineTypes> PayloadTestContext<E> {
pub async fn expect_built_payload(&mut self) -> eyre::Result<E::BuiltPayload> {
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.");
Expand Down
1 change: 1 addition & 0 deletions crates/blockchain-tree/src/blockchain_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?
Expand Down
8 changes: 7 additions & 1 deletion crates/blockchain-tree/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -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,
Expand All @@ -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(())
}
}
1 change: 1 addition & 0 deletions crates/e2e-test-utils/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
1 change: 1 addition & 0 deletions crates/ethereum/evm/src/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ where
) -> Result<EthExecuteOutput, BlockExecutionError> {
println!("execute_without_verification");

// Original execution logic
// 1. prepare state on new block
self.on_new_block(&block.header);

Expand Down
41 changes: 33 additions & 8 deletions crates/rpc/rpc-engine-api/src/engine_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -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
Expand Down
14 changes: 12 additions & 2 deletions crates/rpc/rpc-eth-api/src/helpers/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand All @@ -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;

Expand Down Expand Up @@ -236,6 +237,12 @@ pub trait EthTransactions: LoadTransaction {
/// Returns the hash of the transaction.
fn send_raw_transaction(&self, tx: Bytes) -> impl Future<Output = EthResult<B256>> + 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);
Comment on lines +240 to +245
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Brechtpd Could you please have a look on the above comments:

  1. Is it the correct understanding ? Is the comment valid ?
  2. Currently i'm trying to distinguish based on chain_id, tho i could not find a way to extract it from Signature Maybe it is not even the best approach to distinguish tho seems obvious ?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would guess ideally the node is configured differently in some way between L1 and L2. With L2 having a somewhat custom payload builder likely, and then instead of propegating the block through the network like done on L1, it would instead propose the block to the gwyneth smart contract (probably something related to the engine api, but haven't looked up the normal flow for this).

On the other hand, we can also just make it easy for now and just collect the tx here and propose the block to the smart contract when it's configured as an L2 node and then we can see later. Normally, the block building wil be done through something like rbuilder, so reth itself only really needs to be able to sync with a given tx list (and the internal payload builder would only be a fallback path).

// 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() {
Expand All @@ -244,6 +251,7 @@ pub trait EthTransactions: LoadTransaction {
}

let recovered = recover_raw_transaction(tx)?;

let pool_transaction =
<Self::Pool as TransactionPool>::Transaction::from_recovered_pooled_transaction(
recovered,
Expand All @@ -252,6 +260,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)
}
Expand Down
5 changes: 5 additions & 0 deletions crates/storage/provider/src/providers/database/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ impl<DB> ProviderFactory<DB> {
&self.db
}

/// Returns reference to the underlying chain_spec.
pub fn chain_spec(&self) -> Arc<ChainSpec> {
self.chain_spec.clone()
}

#[cfg(any(test, feature = "test-utils"))]
/// Consumes Self and returns DB
pub fn into_db(self) -> Arc<DB> {
Expand Down
69 changes: 69 additions & 0 deletions packages/protocol/scripts/L2_txn_simulation/sendATxnToL2Rpc.py
Original file line number Diff line number Diff line change
@@ -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)
Loading