From ddd775d703ff1b327a95cc6e988d9ad44a4de2f5 Mon Sep 17 00:00:00 2001 From: Omar Abdulla Date: Mon, 14 Jul 2025 22:53:40 +0300 Subject: [PATCH] Add a way to get the block difficulty from the node --- crates/node-interaction/src/lib.rs | 9 ++++--- crates/node/src/geth.rs | 38 +++++++++++++++++++++++++----- crates/node/src/kitchensink.rs | 36 ++++++++++++++++++++++++---- 3 files changed, 69 insertions(+), 14 deletions(-) diff --git a/crates/node-interaction/src/lib.rs b/crates/node-interaction/src/lib.rs index f054842..fdb21d8 100644 --- a/crates/node-interaction/src/lib.rs +++ b/crates/node-interaction/src/lib.rs @@ -1,6 +1,6 @@ //! This crate implements all node interactions. -use alloy::primitives::{Address, ChainId}; +use alloy::primitives::{Address, ChainId, U256}; use alloy::rpc::types::trace::geth::{DiffMode, GethTrace}; use alloy::rpc::types::{TransactionReceipt, TransactionRequest}; use anyhow::Result; @@ -28,8 +28,11 @@ pub trait EthereumNode { // TODO: This is currently a u128 due to Kitchensink needing more than 64 bits for its gas limit // when we implement the changes to the gas we need to adjust this to be a u64. /// Returns the gas limit of the last block. - fn gas_limit(&self) -> Result; + fn block_gas_limit(&self) -> Result; /// Returns the coinbase of the last block. - fn coinbase(&self) -> Result
; + fn block_coinbase(&self) -> Result
; + + /// Returns the difficulty of the last block. + fn block_difficulty(&self) -> Result; } diff --git a/crates/node/src/geth.rs b/crates/node/src/geth.rs index 0a18e6f..3c4a54d 100644 --- a/crates/node/src/geth.rs +++ b/crates/node/src/geth.rs @@ -16,7 +16,7 @@ use std::{ use alloy::{ eips::BlockNumberOrTag, network::{Ethereum, EthereumWallet}, - primitives::Address, + primitives::{Address, U256}, providers::{ Provider, ProviderBuilder, ext::DebugApi, @@ -363,7 +363,7 @@ impl EthereumNode for Instance { } #[tracing::instrument(skip_all, fields(geth_node_id = self.id))] - fn gas_limit(&self) -> anyhow::Result { + fn block_gas_limit(&self) -> anyhow::Result { let provider = self.provider(); BlockingExecutor::execute(async move { provider @@ -376,7 +376,7 @@ impl EthereumNode for Instance { } #[tracing::instrument(skip_all, fields(geth_node_id = self.id))] - fn coinbase(&self) -> anyhow::Result
{ + fn block_coinbase(&self) -> anyhow::Result
{ let provider = self.provider(); BlockingExecutor::execute(async move { provider @@ -387,6 +387,19 @@ impl EthereumNode for Instance { .map(|block| block.header.beneficiary) })? } + + #[tracing::instrument(skip_all, fields(geth_node_id = self.id))] + fn block_difficulty(&self) -> anyhow::Result { + let provider = self.provider(); + BlockingExecutor::execute(async move { + provider + .await? + .get_block_by_number(BlockNumberOrTag::Latest) + .await? + .ok_or(anyhow::Error::msg("Blockchain has no blocks")) + .map(|block| block.header.difficulty) + })? + } } impl Node for Instance { @@ -536,7 +549,7 @@ mod tests { let (node, _temp_dir) = new_node(); // Act - let gas_limit = node.gas_limit(); + let gas_limit = node.block_gas_limit(); // Assert let gas_limit = gas_limit.expect("Failed to get the gas limit"); @@ -549,10 +562,23 @@ mod tests { let (node, _temp_dir) = new_node(); // Act - let coinbase = node.coinbase(); + let coinbase = node.block_coinbase(); // Assert - let coinbase = coinbase.expect("Failed to get the gas limit"); + let coinbase = coinbase.expect("Failed to get the coinbase"); assert_eq!(coinbase, Address::new([0xFF; 20])) } + + #[test] + fn can_get_block_difficulty_from_node() { + // Arrange + let (node, _temp_dir) = new_node(); + + // Act + let block_difficulty = node.block_difficulty(); + + // Assert + let block_difficulty = block_difficulty.expect("Failed to get the block difficulty"); + assert_eq!(block_difficulty, U256::ZERO) + } } diff --git a/crates/node/src/kitchensink.rs b/crates/node/src/kitchensink.rs index f055ae1..957eec8 100644 --- a/crates/node/src/kitchensink.rs +++ b/crates/node/src/kitchensink.rs @@ -439,7 +439,7 @@ impl EthereumNode for KitchensinkNode { } #[tracing::instrument(skip_all, fields(geth_node_id = self.id))] - fn gas_limit(&self) -> anyhow::Result { + fn block_gas_limit(&self) -> anyhow::Result { let provider = self.provider(); BlockingExecutor::execute(async move { provider @@ -452,7 +452,7 @@ impl EthereumNode for KitchensinkNode { } #[tracing::instrument(skip_all, fields(geth_node_id = self.id))] - fn coinbase(&self) -> anyhow::Result
{ + fn block_coinbase(&self) -> anyhow::Result
{ let provider = self.provider(); BlockingExecutor::execute(async move { provider @@ -463,6 +463,19 @@ impl EthereumNode for KitchensinkNode { .map(|block| block.header.beneficiary) })? } + + #[tracing::instrument(skip_all, fields(geth_node_id = self.id))] + fn block_difficulty(&self) -> anyhow::Result { + let provider = self.provider(); + BlockingExecutor::execute(async move { + provider + .await? + .get_block_by_number(BlockNumberOrTag::Latest) + .await? + .ok_or(anyhow::Error::msg("Blockchain has no blocks")) + .map(|block| block.header.difficulty) + })? + } } impl Node for KitchensinkNode { @@ -1209,7 +1222,7 @@ mod tests { let (node, _temp_dir) = new_node(); // Act - let gas_limit = node.gas_limit(); + let gas_limit = node.block_gas_limit(); // Assert let gas_limit = gas_limit.expect("Failed to get the gas limit"); @@ -1222,10 +1235,23 @@ mod tests { let (node, _temp_dir) = new_node(); // Act - let coinbase = node.coinbase(); + let coinbase = node.block_coinbase(); // Assert - let coinbase = coinbase.expect("Failed to get the gas limit"); + let coinbase = coinbase.expect("Failed to get the coinbase"); assert_eq!(coinbase, Address::ZERO) } + + #[test] + fn can_get_block_difficulty_from_node() { + // Arrange + let (node, _temp_dir) = new_node(); + + // Act + let block_difficulty = node.block_difficulty(); + + // Assert + let block_difficulty = block_difficulty.expect("Failed to get the block difficulty"); + assert_eq!(block_difficulty, U256::ZERO) + } }