Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .github/workflows/pr_perf_blocks_exec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ jobs:
BINS="base,head"
hyperfine --setup "./bin/ethrex-base removedb" -w 5 -N -r 10 --show-output --export-markdown "bench_pr_comparison.md" \
-L bin "$BINS" -n "{bin}" \
"./bin/ethrex-{bin} --network test_data/genesis-l2-ci.json import ./test_data/l2-1k-erc20.rlp --removedb --force"
"./bin/ethrex-{bin} --network test_data/genesis-l2-ci.json --force import ./test_data/l2-1k-erc20.rlp --removedb"
echo -e "## Benchmark Block Execution Results Comparison Against Main\n\n$(cat bench_pr_comparison.md)" > bench_pr_comparison.md
- name: Upload PR results
uses: actions/upload-artifact@v4
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Perf

### 2025-04-11

- Asyncify some DB read APIs, as well as its users [#2430](https://github.com/lambdaclass/ethrex/pull/2430)

### 2025-04-09

- Fix an issue where the table was locked for up to 20 sec when performing a ping: [2368](https://github.com/lambdaclass/ethrex/pull/2368)
Expand Down
10 changes: 6 additions & 4 deletions cmd/ef_tests/blockchain/test_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ pub async fn run_ef_test(test_key: &str, test: &TestUnit) {
}
}
}
check_poststate_against_db(test_key, test, &store)
check_poststate_against_db(test_key, test, &store).await
}

/// Tests the rlp decoding of a block
Expand Down Expand Up @@ -136,13 +136,14 @@ fn check_prestate_against_db(test_key: &str, test: &TestUnit, db: &Store) {
/// Checks that all accounts in the post-state are present and have the correct values in the DB
/// Panics if any comparison fails
/// Tests that previously failed the validation stage shouldn't be executed with this function.
fn check_poststate_against_db(test_key: &str, test: &TestUnit, db: &Store) {
let latest_block_number = db.get_latest_block_number().unwrap();
async fn check_poststate_against_db(test_key: &str, test: &TestUnit, db: &Store) {
let latest_block_number = db.get_latest_block_number().await.unwrap();
for (addr, account) in &test.post_state {
let expected_account: CoreAccount = account.clone().into();
// Check info
let db_account_info = db
.get_account_info(latest_block_number, *addr)
.await
.expect("Failed to read from DB")
.unwrap_or_else(|| {
panic!("Account info for address {addr} not found in DB, test:{test_key}")
Expand All @@ -167,6 +168,7 @@ fn check_poststate_against_db(test_key: &str, test: &TestUnit, db: &Store) {
for (key, value) in expected_account.storage {
let db_storage_value = db
.get_storage_at(latest_block_number, *addr, key)
.await
.expect("Failed to read from DB")
.unwrap_or_else(|| {
panic!("Storage missing for address {addr} key {key} in DB test:{test_key}")
Expand All @@ -178,7 +180,7 @@ fn check_poststate_against_db(test_key: &str, test: &TestUnit, db: &Store) {
}
}
// Check lastblockhash is in store
let last_block_number = db.get_latest_block_number().unwrap();
let last_block_number = db.get_latest_block_number().await.unwrap();
let last_block_hash = db
.get_block_header(last_block_number)
.unwrap()
Expand Down
5 changes: 3 additions & 2 deletions cmd/ethrex/ethrex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,16 @@ async fn main() -> eyre::Result<()> {
blockchain.clone(),
cancel_token.clone(),
tracker.clone(),
);
)
.await;

init_metrics(&opts, tracker.clone());

cfg_if::cfg_if! {
if #[cfg(feature = "dev")] {
use ethrex::initializers::init_dev_network;

init_dev_network(&opts, &store, tracker.clone());
init_dev_network(&opts, &store, tracker.clone()).await;
} else {
use ethrex::initializers::init_network;

Expand Down
10 changes: 6 additions & 4 deletions cmd/ethrex/initializers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ pub fn init_blockchain(evm_engine: EvmEngine, store: Store) -> Arc<Blockchain> {
}

#[allow(clippy::too_many_arguments)]
pub fn init_rpc_api(
pub async fn init_rpc_api(
opts: &Options,
#[cfg(feature = "l2")] l2_opts: &L2Options,
signer: &SigningKey,
Expand All @@ -119,7 +119,8 @@ pub fn init_rpc_api(
cancel_token,
blockchain.clone(),
store.clone(),
);
)
.await;

let rpc_api = ethrex_rpc::start_api(
get_http_socket_addr(opts),
Expand Down Expand Up @@ -208,14 +209,15 @@ pub async fn init_network(
}

#[cfg(feature = "dev")]
pub fn init_dev_network(opts: &Options, store: &Store, tracker: TaskTracker) {
pub async fn init_dev_network(opts: &Options, store: &Store, tracker: TaskTracker) {
if opts.dev {
info!("Running in DEV_MODE");

let head_block_hash = {
let current_block_number = store.get_latest_block_number().unwrap();
let current_block_number = store.get_latest_block_number().await.unwrap();
store
.get_canonical_block_hash(current_block_number)
.await
.unwrap()
.unwrap()
};
Expand Down
3 changes: 2 additions & 1 deletion cmd/ethrex/l2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,8 @@ impl Command {
blockchain.clone(),
cancel_token.clone(),
tracker.clone(),
);
)
.await;

// TODO: Add a --metrics flag to enable metrics.
init_metrics(&opts.node_opts, tracker.clone());
Expand Down
25 changes: 14 additions & 11 deletions crates/blockchain/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ impl Blockchain {

/// Add a blob transaction and its blobs bundle to the mempool checking that the transaction is valid
#[cfg(feature = "c-kzg")]
pub fn add_blob_transaction_to_pool(
pub async fn add_blob_transaction_to_pool(
&self,
transaction: EIP4844Transaction,
blobs_bundle: BlobsBundle,
Expand All @@ -364,7 +364,7 @@ impl Blockchain {
let sender = transaction.sender();

// Validate transaction
self.validate_transaction(&transaction, sender)?;
self.validate_transaction(&transaction, sender).await?;

// Add transaction and blobs bundle to storage
let hash = transaction.compute_hash();
Expand All @@ -375,14 +375,17 @@ impl Blockchain {
}

/// Add a transaction to the mempool checking that the transaction is valid
pub fn add_transaction_to_pool(&self, transaction: Transaction) -> Result<H256, MempoolError> {
pub async fn add_transaction_to_pool(
&self,
transaction: Transaction,
) -> Result<H256, MempoolError> {
// Blob transactions should be submitted via add_blob_transaction along with the corresponding blobs bundle
if matches!(transaction, Transaction::EIP4844Transaction(_)) {
return Err(MempoolError::BlobTxNoBlobsBundle);
}
let sender = transaction.sender();
// Validate transaction
self.validate_transaction(&transaction, sender)?;
self.validate_transaction(&transaction, sender).await?;

let hash = transaction.compute_hash();

Expand Down Expand Up @@ -430,14 +433,14 @@ impl Blockchain {

*/

pub fn validate_transaction(
pub async fn validate_transaction(
&self,
tx: &Transaction,
sender: Address,
) -> Result<(), MempoolError> {
// TODO: Add validations here

let header_no = self.storage.get_latest_block_number()?;
let header_no = self.storage.get_latest_block_number().await?;
let header = self
.storage
.get_block_header(header_no)?
Expand Down Expand Up @@ -477,7 +480,7 @@ impl Blockchain {
}
};

let maybe_sender_acc_info = self.storage.get_account_info(header_no, sender)?;
let maybe_sender_acc_info = self.storage.get_account_info(header_no, sender).await?;

if let Some(sender_acc_info) = maybe_sender_acc_info {
if tx.nonce() < sender_acc_info.nonce {
Expand Down Expand Up @@ -562,8 +565,8 @@ pub fn validate_receipts_root(
}

// Returns the hash of the head of the canonical chain (the latest valid hash).
pub fn latest_canonical_block_hash(storage: &Store) -> Result<H256, ChainError> {
let latest_block_number = storage.get_latest_block_number()?;
pub async fn latest_canonical_block_hash(storage: &Store) -> Result<H256, ChainError> {
let latest_block_number = storage.get_latest_block_number().await?;
if let Some(latest_valid_header) = storage.get_block_header(latest_block_number)? {
let latest_valid_hash = latest_valid_header.compute_block_hash();
return Ok(latest_valid_hash);
Expand Down Expand Up @@ -611,12 +614,12 @@ pub fn validate_block(
Ok(())
}

pub fn is_canonical(
pub async fn is_canonical(
store: &Store,
block_number: BlockNumber,
block_hash: BlockHash,
) -> Result<bool, StoreError> {
match store.get_canonical_block_hash(block_number)? {
match store.get_canonical_block_hash(block_number).await? {
Some(hash) if hash == block_hash => Ok(true),
_ => Ok(false),
}
Expand Down
19 changes: 10 additions & 9 deletions crates/blockchain/fork_choice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,15 @@ pub async fn apply_fork_choice(
return Err(InvalidForkChoice::Syncing);
};

let latest = store.get_latest_block_number()?;
let latest = store.get_latest_block_number().await?;

// If the head block is an already present head ancestor, skip the update.
if is_canonical(store, head.number, head_hash)? && head.number < latest {
if is_canonical(store, head.number, head_hash).await? && head.number < latest {
return Err(InvalidForkChoice::NewHeadAlreadyCanonical);
}

// Find blocks that will be part of the new canonical chain.
let Some(new_canonical_blocks) = find_link_with_canonical_chain(store, &head)? else {
let Some(new_canonical_blocks) = find_link_with_canonical_chain(store, &head).await? else {
return Err(InvalidForkChoice::Disconnected(
error::ForkChoiceElement::Head,
error::ForkChoiceElement::Safe,
Expand All @@ -76,7 +76,7 @@ pub async fn apply_fork_choice(

// Check that finalized and safe blocks are part of the new canonical chain.
if let Some(ref finalized) = finalized_res {
if !((is_canonical(store, finalized.number, finalized_hash)?
if !((is_canonical(store, finalized.number, finalized_hash).await?
&& finalized.number <= link_block_number)
|| (finalized.number == head.number && finalized_hash == head_hash)
|| new_canonical_blocks.contains(&(finalized.number, finalized_hash)))
Expand All @@ -89,7 +89,8 @@ pub async fn apply_fork_choice(
}

if let Some(ref safe) = safe_res {
if !((is_canonical(store, safe.number, safe_hash)? && safe.number <= link_block_number)
if !((is_canonical(store, safe.number, safe_hash).await?
&& safe.number <= link_block_number)
|| (safe.number == head.number && safe_hash == head_hash)
|| new_canonical_blocks.contains(&(safe.number, safe_hash)))
{
Expand Down Expand Up @@ -159,7 +160,7 @@ fn check_order(
// - Ok(Some([])): the block is already canonical.
// - Ok(Some(branch)): the "branch" is a sequence of blocks that connects the ancestor and the
// descendant.
fn find_link_with_canonical_chain(
async fn find_link_with_canonical_chain(
store: &Store,
block: &BlockHeader,
) -> Result<Option<Vec<(BlockNumber, BlockHash)>>, StoreError> {
Expand All @@ -168,11 +169,11 @@ fn find_link_with_canonical_chain(
let mut header = block.clone();
let mut branch = Vec::new();

if is_canonical(store, block_number, block_hash)? {
if is_canonical(store, block_number, block_hash).await? {
return Ok(Some(branch));
}

let genesis_number = store.get_earliest_block_number()?;
let genesis_number = store.get_earliest_block_number().await?;

while block_number > genesis_number {
block_number -= 1;
Expand All @@ -185,7 +186,7 @@ fn find_link_with_canonical_chain(
Err(error) => return Err(error),
};

if is_canonical(store, block_number, parent_hash)? {
if is_canonical(store, block_number, parent_hash).await? {
return Ok(Some(branch));
} else {
branch.push((block_number, parent_hash));
Expand Down
Loading