mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat: flashbots_validateBuilderSubmissionV4 (#12243)
This commit is contained in:
@ -2,12 +2,15 @@ use crate::utils::eth_payload_attributes;
|
||||
use alloy_eips::{calc_next_block_base_fee, eip2718::Encodable2718};
|
||||
use alloy_primitives::{Address, B256, U256};
|
||||
use alloy_provider::{network::EthereumWallet, Provider, ProviderBuilder, SendableTx};
|
||||
use alloy_rpc_types_beacon::relay::{BidTrace, SignedBidSubmissionV3};
|
||||
use alloy_rpc_types_beacon::relay::{BidTrace, SignedBidSubmissionV3, SignedBidSubmissionV4};
|
||||
use rand::{rngs::StdRng, Rng, SeedableRng};
|
||||
use reth::rpc::{
|
||||
api::BuilderBlockValidationRequestV3,
|
||||
compat::engine::payload::block_to_payload_v3,
|
||||
types::{engine::BlobsBundleV1, TransactionRequest},
|
||||
use reth::{
|
||||
payload::BuiltPayload,
|
||||
rpc::{
|
||||
api::{BuilderBlockValidationRequestV3, BuilderBlockValidationRequestV4},
|
||||
compat::engine::payload::block_to_payload_v3,
|
||||
types::{engine::BlobsBundleV1, TransactionRequest},
|
||||
},
|
||||
};
|
||||
use reth_chainspec::{ChainSpecBuilder, MAINNET};
|
||||
use reth_e2e_test_utils::setup_engine;
|
||||
@ -115,7 +118,7 @@ async fn test_fee_history() -> eyre::Result<()> {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_flashbots_validate() -> eyre::Result<()> {
|
||||
async fn test_flashbots_validate_v3() -> eyre::Result<()> {
|
||||
reth_tracing::init_test_tracing();
|
||||
|
||||
let chain_spec = Arc::new(
|
||||
@ -187,3 +190,78 @@ async fn test_flashbots_validate() -> eyre::Result<()> {
|
||||
.is_err());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_flashbots_validate_v4() -> eyre::Result<()> {
|
||||
reth_tracing::init_test_tracing();
|
||||
|
||||
let chain_spec = Arc::new(
|
||||
ChainSpecBuilder::default()
|
||||
.chain(MAINNET.chain)
|
||||
.genesis(serde_json::from_str(include_str!("../assets/genesis.json")).unwrap())
|
||||
.prague_activated()
|
||||
.build(),
|
||||
);
|
||||
|
||||
let (mut nodes, _tasks, wallet) =
|
||||
setup_engine::<EthereumNode>(1, chain_spec.clone(), false, eth_payload_attributes).await?;
|
||||
let mut node = nodes.pop().unwrap();
|
||||
let provider = ProviderBuilder::new()
|
||||
.with_recommended_fillers()
|
||||
.wallet(EthereumWallet::new(wallet.gen().swap_remove(0)))
|
||||
.on_http(node.rpc_url());
|
||||
|
||||
node.advance(100, |_| {
|
||||
let provider = provider.clone();
|
||||
Box::pin(async move {
|
||||
let SendableTx::Envelope(tx) =
|
||||
provider.fill(TransactionRequest::default().to(Address::ZERO)).await.unwrap()
|
||||
else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
tx.encoded_2718().into()
|
||||
})
|
||||
})
|
||||
.await?;
|
||||
|
||||
let _ = provider.send_transaction(TransactionRequest::default().to(Address::ZERO)).await?;
|
||||
let (payload, attrs) = node.new_payload().await?;
|
||||
|
||||
let mut request = BuilderBlockValidationRequestV4 {
|
||||
request: SignedBidSubmissionV4 {
|
||||
message: BidTrace {
|
||||
parent_hash: payload.block().parent_hash,
|
||||
block_hash: payload.block().hash(),
|
||||
gas_used: payload.block().gas_used,
|
||||
gas_limit: payload.block().gas_limit,
|
||||
..Default::default()
|
||||
},
|
||||
execution_payload: block_to_payload_v3(payload.block().clone()),
|
||||
blobs_bundle: BlobsBundleV1::new([]),
|
||||
execution_requests: payload.requests().unwrap_or_default().to_vec(),
|
||||
signature: Default::default(),
|
||||
},
|
||||
parent_beacon_block_root: attrs.parent_beacon_block_root.unwrap(),
|
||||
registered_gas_limit: payload.block().gas_limit,
|
||||
};
|
||||
|
||||
provider
|
||||
.raw_request::<_, ()>("flashbots_validateBuilderSubmissionV4".into(), (&request,))
|
||||
.await
|
||||
.expect("request should validate");
|
||||
|
||||
request.registered_gas_limit -= 1;
|
||||
assert!(provider
|
||||
.raw_request::<_, ()>("flashbots_validateBuilderSubmissionV4".into(), (&request,))
|
||||
.await
|
||||
.is_err());
|
||||
request.registered_gas_limit += 1;
|
||||
|
||||
request.request.execution_payload.payload_inner.payload_inner.state_root = B256::ZERO;
|
||||
assert!(provider
|
||||
.raw_request::<_, ()>("flashbots_validateBuilderSubmissionV4".into(), (&request,))
|
||||
.await
|
||||
.is_err());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -46,7 +46,10 @@ pub mod servers {
|
||||
rpc::RpcApiServer,
|
||||
trace::TraceApiServer,
|
||||
txpool::TxPoolApiServer,
|
||||
validation::{BlockSubmissionValidationApiServer, BuilderBlockValidationRequestV3},
|
||||
validation::{
|
||||
BlockSubmissionValidationApiServer, BuilderBlockValidationRequestV3,
|
||||
BuilderBlockValidationRequestV4,
|
||||
},
|
||||
web3::Web3ApiServer,
|
||||
};
|
||||
pub use reth_rpc_eth_api::{
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
use alloy_primitives::B256;
|
||||
use alloy_rpc_types_beacon::relay::{
|
||||
BuilderBlockValidationRequest, BuilderBlockValidationRequestV2, SignedBidSubmissionV3,
|
||||
SignedBidSubmissionV4,
|
||||
};
|
||||
use jsonrpsee::proc_macros::rpc;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -24,6 +25,22 @@ pub struct BuilderBlockValidationRequestV3 {
|
||||
pub parent_beacon_block_root: B256,
|
||||
}
|
||||
|
||||
/// A Request to validate a [`SignedBidSubmissionV4`]
|
||||
///
|
||||
/// <https://github.com/flashbots/builder/blob/7577ac81da21e760ec6693637ce2a81fe58ac9f8/eth/block-validation/api.go#L198-L202>
|
||||
#[serde_as]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct BuilderBlockValidationRequestV4 {
|
||||
/// The request to be validated.
|
||||
#[serde(flatten)]
|
||||
pub request: SignedBidSubmissionV4,
|
||||
/// The registered gas limit for the validation request.
|
||||
#[serde_as(as = "DisplayFromStr")]
|
||||
pub registered_gas_limit: u64,
|
||||
/// The parent beacon block root for the validation request.
|
||||
pub parent_beacon_block_root: B256,
|
||||
}
|
||||
|
||||
/// Block validation rpc interface.
|
||||
#[cfg_attr(not(feature = "client"), rpc(server, namespace = "flashbots"))]
|
||||
#[cfg_attr(feature = "client", rpc(server, client, namespace = "flashbots"))]
|
||||
@ -48,4 +65,11 @@ pub trait BlockSubmissionValidationApi {
|
||||
&self,
|
||||
request: BuilderBlockValidationRequestV3,
|
||||
) -> jsonrpsee::core::RpcResult<()>;
|
||||
|
||||
/// A Request to validate a block submission.
|
||||
#[method(name = "validateBuilderSubmissionV4")]
|
||||
async fn validate_builder_submission_v4(
|
||||
&self,
|
||||
request: BuilderBlockValidationRequestV4,
|
||||
) -> jsonrpsee::core::RpcResult<()>;
|
||||
}
|
||||
|
||||
@ -20,7 +20,10 @@ use reth_provider::{
|
||||
StateProviderFactory, WithdrawalsProvider,
|
||||
};
|
||||
use reth_revm::database::StateProviderDatabase;
|
||||
use reth_rpc_api::{BlockSubmissionValidationApiServer, BuilderBlockValidationRequestV3};
|
||||
use reth_rpc_api::{
|
||||
BlockSubmissionValidationApiServer, BuilderBlockValidationRequestV3,
|
||||
BuilderBlockValidationRequestV4,
|
||||
};
|
||||
use reth_rpc_eth_types::EthApiError;
|
||||
use reth_rpc_server_types::{result::internal_rpc_err, ToRpcResult};
|
||||
use reth_trie::HashedPostState;
|
||||
@ -415,4 +418,37 @@ where
|
||||
.map_err(|e| RethError::Other(e.into()))
|
||||
.to_rpc_result()
|
||||
}
|
||||
|
||||
/// Validates a block submitted to the relay
|
||||
async fn validate_builder_submission_v4(
|
||||
&self,
|
||||
request: BuilderBlockValidationRequestV4,
|
||||
) -> RpcResult<()> {
|
||||
let block = self
|
||||
.payload_validator
|
||||
.ensure_well_formed_payload(
|
||||
ExecutionPayload::V3(request.request.execution_payload),
|
||||
ExecutionPayloadSidecar::v4(
|
||||
CancunPayloadFields {
|
||||
parent_beacon_block_root: request.parent_beacon_block_root,
|
||||
versioned_hashes: self
|
||||
.validate_blobs_bundle(request.request.blobs_bundle)
|
||||
.map_err(|e| RethError::Other(e.into()))
|
||||
.to_rpc_result()?,
|
||||
},
|
||||
request.request.execution_requests.into(),
|
||||
),
|
||||
)
|
||||
.to_rpc_result()?
|
||||
.try_seal_with_senders()
|
||||
.map_err(|_| EthApiError::InvalidTransactionSignature)?;
|
||||
|
||||
self.validate_message_against_block(
|
||||
block,
|
||||
request.request.message,
|
||||
request.registered_gas_limit,
|
||||
)
|
||||
.map_err(|e| RethError::Other(e.into()))
|
||||
.to_rpc_result()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user