feat: build_payload based on block context StateProvider #42
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Currently
build_payload
is defined per platform by taking the payload (as a checkpoint from payload API) and a provider to get access to state:rblib/src/platform/mod.rs
Lines 104 to 114 in 624ead4
The provider is bounded with
ProviderBounds
, which isStateProviderFactory + ChainSpecProvider + HeaderProvider
. SoProviderBounds
is stronger than just aStateProvider
bound as the state factory should be able to create state provider for different blocks etc; it's basically a provider to the full node state.rblib/src/pipelines/mod.rs
Lines 346 to 353 in 624ead4
In reth codebase the
Client
trait is a similar bound. Its used indefault_ethereum_payload
(used in the implementation of build_payload for Ethereum platform):https://github.com/paradigmxyz/reth/blob/ab2b11f40eed3623219c49022061a11a0b5e2c0c/crates/ethereum/payload/src/lib.rs#L132-L150
Inside the implementation, client is used to get the latest StateProvider
client.state_by_block_hash(parent_header.hash())
and to get chain specclient.chain_spec()
:https://github.com/paradigmxyz/reth/blob/ab2b11f40eed3623219c49022061a11a0b5e2c0c/crates/ethereum/payload/src/lib.rs#L155
https://github.com/paradigmxyz/reth/blob/ab2b11f40eed3623219c49022061a11a0b5e2c0c/crates/ethereum/payload/src/lib.rs#L175
Similarly, in our own implementation of build_payload for the Optimism platform we use the provider to get latest state
provider.state_by_block_hash(payload.block().parent().hash())
. The chainspec is accessible with the block context withpayload.block().chainspec()
.rblib/src/platform/optimism/mod.rs
Lines 115 to 117 in 624ead4
rblib/src/platform/optimism/mod.rs
Line 106 in 624ead4
So for build_payload, we don’t really need
StateProviderFactory + ChainSpecProvider
as we already have access to latestStateProvider
and chainspec in block context.Regarding
HeaderProvider
, it seems to be used only within pipeline API’s PayloadJobGenerator in new_payload_job to request the parent block header to initialize block context.rblib/src/pipelines/service.rs
Lines 174 to 200 in 624ead4
ProviderBounds
is defined as part of the pipeline API and used mostly within the pipeline service to request for node states. I consider pipeline API to be built “on top” of payload/platform API, as a way to abstract building workflows on top of the node. That's why it's hard to get access to it within pipeline/steps, as you’re not supposed to directly read state from the node but instead use checkpoint abstraction.With this in mind I suggest trying to change build_payload to not take “node provider” but only “latest block state provider”. This would also allows to build payload directly from a checkpoint/from the block context, so within a step
payload.build_payload()
orctx.block().build_payload(payload)
.This PR shows an example of how it could look like.
Issue: to be able to fully use
default_ethereum_payload
there's a need for some shims with the latestStateProvider
as it expects aStateProviderFactory + ChainSpecProvider
. I forked it to change the behavior. We would want to implement a different payload building process anyway (checkpoint aware)TLDR; lets completely abstract node state from payload/platform and make build_payload takes only StateProvider from BlockContext::base_state