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

refactor(l2): handle not committed block #1192

Closed
wants to merge 17 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
13 changes: 9 additions & 4 deletions crates/l2/contracts/src/l1/OnChainProposer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -122,20 +122,25 @@ contract OnChainProposer is IOnChainProposer, ReentrancyGuard {
}

/// @inheritdoc IOnChainProposer
/// @notice The first `require` checks that the block number is the subsequent block.
/// @notice The second `require` checks if the block has been committed.
/// @notice The order of these `require` statements is important.
/// After the verification process, we delete the `blockCommitments` for `blockNumber - 1`. This means that when checking the block,
/// we might get an error indicating that the block hasn’t been committed, even though it was committed but deleted. Therefore, it has already been verified.
function verify(
uint256 blockNumber,
bytes calldata blockProof,
bytes32 imageId,
bytes32 journalDigest
) external override {
require(
blockCommitments[blockNumber].commitmentHash != bytes32(0),
"OnChainProposer: block not committed"
);
require(
blockNumber == lastVerifiedBlock + 1,
"OnChainProposer: block already verified"
);
require(
blockCommitments[blockNumber].commitmentHash != bytes32(0),
"OnChainProposer: block not committed"
);

if (R0VERIFIER != DEV_MODE) {
// If the verification fails, it will revert.
Expand Down
8 changes: 8 additions & 0 deletions crates/l2/proposer/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ pub enum ProverServerError {
EthClientError(#[from] EthClientError),
#[error("ProverServer failed to send transaction: {0}")]
FailedToVerifyProofOnChain(String),
#[error("ProverServer failed to write to TcpStream: {0}")]
WriteError(String),
#[error("ProverServer failed to access Store: {0}")]
FailedAccessingStore(#[from] StoreError),
#[error("ProverServer failed to get data from Store: {0}")]
ItemNotFoundInStore(String),
#[error("ProverServer failed to create inputs for the Prover: {0}")]
FailedToCreateProverInputs(#[from] EvmError),
}

#[derive(Debug, thiserror::Error)]
Expand Down
116 changes: 46 additions & 70 deletions crates/l2/proposer/l1_committer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,15 @@ use crate::{
},
utils::{
config::{committer::CommitterConfig, eth::EthConfig},
eth_client::{errors::EthClientError, eth_sender::Overrides, EthClient},
eth_client::{eth_sender::Overrides, EthClient},
merkle_tree::merkelize,
},
};
use bytes::Bytes;
use ethrex_blockchain::constants::TX_GAS_COST;
use ethrex_core::{
types::{
blobs_bundle, BlobsBundle, Block, EIP1559Transaction, GenericTransaction,
PrivilegedL2Transaction, PrivilegedTxType, Transaction, TxKind,
blobs_bundle, BlobsBundle, Block, PrivilegedL2Transaction, PrivilegedTxType, Transaction,
TxKind,
},
Address, H256, U256,
};
Expand All @@ -23,7 +22,6 @@ use ethrex_storage::Store;
use ethrex_vm::{evm_state, execute_block, get_state_transitions};
use keccak_hash::keccak;
use secp256k1::SecretKey;
use std::ops::Div;
use std::{collections::HashMap, time::Duration};
use tokio::time::sleep;
use tracing::{error, info, warn};
Expand Down Expand Up @@ -120,23 +118,41 @@ impl Committer {
let blobs_bundle = self.generate_blobs_bundle(state_diff.clone())?;

let head_block_hash = block_to_commit.hash();
match self
.send_commitment(

let mut wrapped_eip4844 = match self
.build_commitment_tx(
block_to_commit.header.number,
withdrawal_logs_merkle_root,
deposit_logs_hash,
blobs_bundle,
&blobs_bundle,
)
.await
{
Ok(commit_tx_hash) => {
info!(
"Sent commitment to block {head_block_hash:#x}, with transaction hash {commit_tx_hash:#x}"
);
}
Ok(tx) => tx,
Err(error) => {
error!("Failed to send commitment to block {head_block_hash:#x}. Manual intervention required: {error}");
panic!("Failed to send commitment to block {head_block_hash:#x}. Manual intervention required: {error}");
error!("Failed when constructing the commitment for block {head_block_hash:#x}. Manual intervention required: {error}");
// TODO: retry instead of throwing error.
// it may fail in the estimate_gas fn.
return Err(error);
}
};

let mut retries = 0;
let max_retries: u32 = 100;
while retries < max_retries {
match self.send_commitment(&wrapped_eip4844).await {
Ok(commit_tx_hash) => {
info!("Sent commitment for block {head_block_hash:#x}, with transaction hash {commit_tx_hash:#x}");
break;
}
Err(error) => {
error!("Failed to send commitment for block {head_block_hash:#x}, retrying. Manual intervention required: {error}");

self.eth_client.bump_eip4844(&mut wrapped_eip4844, 1.1);
retries += 1;
sleep(Duration::from_secs(2)).await;
continue;
}
}
}
}
Expand Down Expand Up @@ -285,13 +301,13 @@ impl Committer {
BlobsBundle::create_from_blobs(&vec![blob]).map_err(CommitterError::from)
}

pub async fn send_commitment(
pub async fn build_commitment_tx(
&self,
block_number: u64,
withdrawal_logs_merkle_root: H256,
deposit_logs_hash: H256,
blobs_bundle: BlobsBundle,
) -> Result<H256, CommitterError> {
blobs_bundle: &BlobsBundle,
) -> Result<WrappedEIP4844Transaction, CommitterError> {
info!("Sending commitment for block {block_number}");

let mut calldata = Vec::with_capacity(132);
Expand Down Expand Up @@ -320,64 +336,37 @@ impl Committer {
gas_price_per_blob: Some(U256::from_dec_str("100000000000").unwrap()),
..Default::default()
},
blobs_bundle,
blobs_bundle.clone(),
)
.await
.map_err(CommitterError::from)?;

Ok(wrapped_tx)
}

pub async fn send_commitment(
&self,
wrapped_eip4844: &WrappedEIP4844Transaction,
) -> Result<H256, CommitterError> {
let commit_tx_hash = self
.eth_client
.send_eip4844_transaction(wrapped_tx.clone(), &self.l1_private_key)
.send_eip4844_transaction(wrapped_eip4844.clone(), &self.l1_private_key)
.await
.map_err(CommitterError::from)?;

let commit_tx_hash = wrapped_eip4844_transaction_handler(
&self.eth_client,
&wrapped_tx,
wrapped_eip4844,
&self.l1_private_key,
commit_tx_hash,
10,
)
.await?;

info!("Commitment sent: {commit_tx_hash:#x}");

Ok(commit_tx_hash)
}
}

pub async fn send_transaction_with_calldata(
eth_client: &EthClient,
l1_address: Address,
l1_private_key: SecretKey,
to: Address,
nonce: Option<u64>,
calldata: Bytes,
) -> Result<H256, EthClientError> {
let mut tx = EIP1559Transaction {
to: TxKind::Call(to),
data: calldata,
max_fee_per_gas: eth_client.get_gas_price().await?.as_u64() * 2,
nonce: nonce.unwrap_or(eth_client.get_nonce(l1_address).await?),
chain_id: eth_client.get_chain_id().await?.as_u64(),
// Should the max_priority_fee_per_gas be dynamic?
max_priority_fee_per_gas: 10u64,
..Default::default()
};

let mut generic_tx = GenericTransaction::from(tx.clone());
generic_tx.from = l1_address;

tx.gas_limit = eth_client
.estimate_gas(generic_tx)
.await?
.saturating_add(TX_GAS_COST);

eth_client
.send_eip1559_transaction(tx, &l1_private_key)
.await
}

async fn wrapped_eip4844_transaction_handler(
eth_client: &EthClient,
wrapped_eip4844: &WrappedEIP4844Transaction,
Expand Down Expand Up @@ -409,24 +398,11 @@ async fn wrapped_eip4844_transaction_handler(
}
}

// If receipt was not found, send the same tx(same nonce) but with more gas.
// Sometimes the penalty is a 100%
warn!("Transaction not confirmed, resending with 110% more gas...");
// Increase max fee per gas by 110% (set it to 210% of the original)
wrapped_tx.tx.max_fee_per_gas =
(wrapped_tx.tx.max_fee_per_gas as f64 * 2.1).round() as u64;
wrapped_tx.tx.max_priority_fee_per_gas =
(wrapped_tx.tx.max_priority_fee_per_gas as f64 * 2.1).round() as u64;
wrapped_tx.tx.max_fee_per_blob_gas = wrapped_tx
.tx
.max_fee_per_blob_gas
.saturating_mul(U256::from(20))
.div(10);

commit_tx_hash = eth_client
.send_eip4844_transaction(wrapped_tx.clone(), l1_private_key)
.await
.map_err(CommitterError::from)?;
.bump_and_resend_eip4844(&mut wrapped_tx, l1_private_key)
.await?;

retries += 1;
}
Expand Down
Loading
Loading