Skip to content
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
4 changes: 4 additions & 0 deletions crates/anvil/core/src/eth/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,10 @@ pub enum EthRequest {
#[serde(rename = "debug_getRawTransaction", with = "sequence")]
DebugGetRawTransaction(TxHash),

/// geth's `debug_getRawHeader` endpoint
#[serde(rename = "debug_getRawHeader", with = "sequence")]
DebugGetRawHeader(BlockId),

/// geth's `debug_traceTransaction` endpoint
#[serde(rename = "debug_traceTransaction")]
DebugTraceTransaction(B256, #[serde(default)] GethDebugTracingOptions),
Expand Down
7 changes: 7 additions & 0 deletions crates/anvil/src/eth/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ impl EthApi {
EthRequest::DebugGetRawTransaction(hash) => {
self.raw_transaction(hash).await.to_rpc_result()
}
EthRequest::DebugGetRawHeader(block) => self.raw_header(block).to_rpc_result(),
// non eth-standard rpc calls
EthRequest::DebugTraceTransaction(tx, opts) => {
self.debug_trace_transaction(tx, opts).await.to_rpc_result()
Expand Down Expand Up @@ -1578,6 +1579,12 @@ impl EthApi {
self.backend.block_receipts(number).await
}

/// Returns the canonical RLP encoding of a block header.
pub fn raw_header(&self, block: BlockId) -> Result<Option<Bytes>> {
node_info!("debug_getRawHeader");
Ok(self.backend.get_block(block).map(|block| alloy_rlp::encode(&block.header).into()))
}

/// Returns an uncles at given block and index.
///
/// Handler for ETH RPC call: `eth_getUncleByBlockHashAndIndex`
Expand Down
51 changes: 48 additions & 3 deletions crates/anvil/tests/it/beacon_api.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
use crate::utils::http_provider;
use alloy_consensus::{Blob, BlobTransactionSidecar, SidecarBuilder, SimpleCoder, Transaction};
use alloy_consensus::{
Blob, BlobTransactionSidecar, Header, SidecarBuilder, SimpleCoder, Transaction,
};
use alloy_network::{TransactionBuilder, TransactionBuilder4844};
use alloy_primitives::{B256, FixedBytes, U256, b256};
use alloy_primitives::{B256, Bytes, FixedBytes, U256, b256};
use alloy_provider::Provider;
use alloy_rpc_types::TransactionRequest;
use alloy_rlp::Decodable;
use alloy_rpc_types::{BlockNumberOrTag, TransactionRequest};
use alloy_rpc_types_beacon::{genesis::GenesisResponse, sidecar::GetBlobsResponse};
use alloy_serde::WithOtherFields;
use anvil::{NodeConfig, spawn};
use foundry_evm::hardfork::EthereumHardfork;
use serde_json::json;
use ssz::Decode;

#[tokio::test(flavor = "multi_thread")]
Expand Down Expand Up @@ -258,3 +262,44 @@ async fn test_beacon_api_get_genesis() {
FixedBytes::from([0x00, 0x00, 0x00, 0x00])
);
}

#[tokio::test(flavor = "multi_thread")]
async fn test_debug_get_raw_header() {
let (_api, handle) = spawn(NodeConfig::test()).await;
let provider = http_provider(&handle.http_endpoint());
let block = provider.get_block_by_number(BlockNumberOrTag::Latest).await.unwrap().unwrap();
let raw_header_response: serde_json::Value = reqwest::Client::new()
.post(handle.http_endpoint())
.json(&json!({
"jsonrpc": "2.0",
"id": 1,
"method": "debug_getRawHeader",
"params": ["latest"]
}))
.send()
.await
.unwrap()
.json()
.await
.unwrap();
let raw_header: Bytes = serde_json::from_value(raw_header_response["result"].clone()).unwrap();
let header = Header::decode(&mut raw_header.as_ref()).unwrap();

assert_eq!(header.hash_slow(), block.header.hash);

let unavailable_response: serde_json::Value = reqwest::Client::new()
.post(handle.http_endpoint())
.json(&json!({
"jsonrpc": "2.0",
"id": 1,
"method": "debug_getRawHeader",
"params": ["0xffffff"]
}))
.send()
.await
.unwrap()
.json()
.await
.unwrap();
assert!(unavailable_response["result"].is_null());
}
Loading