Skip to main content

reth_payload_builder/
test_utils.rs

1//! Utils for testing purposes.
2
3use crate::{
4    service::BuildNewPayload, traits::KeepPayloadJobAlive, EthBuiltPayload, PayloadBuilderHandle,
5    PayloadBuilderService, PayloadJob, PayloadJobGenerator,
6};
7
8use alloy_consensus::Block;
9use alloy_primitives::U256;
10use alloy_rpc_types::engine::PayloadId;
11use reth_chain_state::CanonStateNotification;
12use reth_ethereum_engine_primitives::EthPayloadAttributes;
13use reth_payload_builder_primitives::PayloadBuilderError;
14use reth_payload_primitives::{PayloadKind, PayloadTypes};
15use reth_primitives_traits::{Block as _, RecoveredBlock};
16use std::{
17    future::Future,
18    pin::Pin,
19    sync::Arc,
20    task::{Context, Poll},
21};
22
23/// Creates a new [`PayloadBuilderService`] for testing purposes.
24pub fn test_payload_service<T>() -> (
25    PayloadBuilderService<
26        TestPayloadJobGenerator,
27        futures_util::stream::Empty<CanonStateNotification>,
28        T,
29    >,
30    PayloadBuilderHandle<T>,
31)
32where
33    T: PayloadTypes<PayloadAttributes = EthPayloadAttributes, BuiltPayload = EthBuiltPayload>,
34{
35    PayloadBuilderService::new(Default::default(), futures_util::stream::empty())
36}
37
38/// Creates a new [`PayloadBuilderService`] for testing purposes and spawns it in the background.
39pub fn spawn_test_payload_service<T>() -> PayloadBuilderHandle<T>
40where
41    T: PayloadTypes<PayloadAttributes = EthPayloadAttributes, BuiltPayload = EthBuiltPayload>,
42{
43    let (service, handle) = test_payload_service();
44    tokio::spawn(service);
45    handle
46}
47
48/// A [`PayloadJobGenerator`] for testing purposes
49#[derive(Debug, Default)]
50#[non_exhaustive]
51pub struct TestPayloadJobGenerator;
52
53impl PayloadJobGenerator for TestPayloadJobGenerator {
54    type Job = TestPayloadJob;
55
56    fn new_payload_job(
57        &self,
58        input: BuildNewPayload<EthPayloadAttributes>,
59        _id: PayloadId,
60    ) -> Result<Self::Job, PayloadBuilderError> {
61        Ok(TestPayloadJob { attr: input.attributes })
62    }
63}
64
65/// A [`PayloadJob`] for testing purposes
66#[derive(Debug)]
67pub struct TestPayloadJob {
68    attr: EthPayloadAttributes,
69}
70
71impl Future for TestPayloadJob {
72    type Output = Result<(), PayloadBuilderError>;
73
74    fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
75        Poll::Pending
76    }
77}
78
79impl PayloadJob for TestPayloadJob {
80    type PayloadAttributes = EthPayloadAttributes;
81    type ResolvePayloadFuture =
82        futures_util::future::Ready<Result<EthBuiltPayload, PayloadBuilderError>>;
83    type BuiltPayload = EthBuiltPayload;
84
85    fn best_payload(&self) -> Result<EthBuiltPayload, PayloadBuilderError> {
86        Ok(EthBuiltPayload::new(
87            Arc::new(RecoveredBlock::new_sealed(Block::<_>::default().seal_slow(), vec![])),
88            U256::ZERO,
89            Some(Default::default()),
90            None,
91        ))
92    }
93
94    fn payload_attributes(&self) -> Result<EthPayloadAttributes, PayloadBuilderError> {
95        Ok(self.attr.clone())
96    }
97
98    fn payload_timestamp(&self) -> Result<u64, PayloadBuilderError> {
99        Ok(self.attr.timestamp)
100    }
101
102    fn resolve_kind(
103        &mut self,
104        _kind: PayloadKind,
105    ) -> (Self::ResolvePayloadFuture, KeepPayloadJobAlive) {
106        let fut = futures_util::future::ready(self.best_payload());
107        (fut, KeepPayloadJobAlive::No)
108    }
109}