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 _;
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        + 'static,
35{
36    PayloadBuilderService::new(Default::default(), futures_util::stream::empty())
37}
38
39/// Creates a new [`PayloadBuilderService`] for testing purposes and spawns it in the background.
40pub fn spawn_test_payload_service<T>() -> PayloadBuilderHandle<T>
41where
42    T: PayloadTypes<PayloadAttributes = EthPayloadAttributes, BuiltPayload = EthBuiltPayload>
43        + 'static,
44{
45    let (service, handle) = test_payload_service();
46    tokio::spawn(service);
47    handle
48}
49
50/// A [`PayloadJobGenerator`] for testing purposes
51#[derive(Debug, Default)]
52#[non_exhaustive]
53pub struct TestPayloadJobGenerator;
54
55impl PayloadJobGenerator for TestPayloadJobGenerator {
56    type Job = TestPayloadJob;
57
58    fn new_payload_job(
59        &self,
60        input: BuildNewPayload<EthPayloadAttributes>,
61        _id: PayloadId,
62    ) -> Result<Self::Job, PayloadBuilderError> {
63        Ok(TestPayloadJob { attr: input.attributes })
64    }
65}
66
67/// A [`PayloadJob`] for testing purposes
68#[derive(Debug)]
69pub struct TestPayloadJob {
70    attr: EthPayloadAttributes,
71}
72
73impl Future for TestPayloadJob {
74    type Output = Result<(), PayloadBuilderError>;
75
76    fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
77        Poll::Pending
78    }
79}
80
81impl PayloadJob for TestPayloadJob {
82    type PayloadAttributes = EthPayloadAttributes;
83    type ResolvePayloadFuture =
84        futures_util::future::Ready<Result<EthBuiltPayload, PayloadBuilderError>>;
85    type BuiltPayload = EthBuiltPayload;
86
87    fn best_payload(&self) -> Result<EthBuiltPayload, PayloadBuilderError> {
88        Ok(EthBuiltPayload::new(
89            Arc::new(Block::<_>::default().seal_slow()),
90            U256::ZERO,
91            Some(Default::default()),
92            None,
93        ))
94    }
95
96    fn payload_attributes(&self) -> Result<EthPayloadAttributes, PayloadBuilderError> {
97        Ok(self.attr.clone())
98    }
99
100    fn payload_timestamp(&self) -> Result<u64, PayloadBuilderError> {
101        Ok(self.attr.timestamp)
102    }
103
104    fn resolve_kind(
105        &mut self,
106        _kind: PayloadKind,
107    ) -> (Self::ResolvePayloadFuture, KeepPayloadJobAlive) {
108        let fut = futures_util::future::ready(self.best_payload());
109        (fut, KeepPayloadJobAlive::No)
110    }
111}