@@ -29,6 +29,7 @@ import (
2929 "github.com/ava-labs/libevm/core/types"
3030 "github.com/ava-labs/libevm/core/vm"
3131 "github.com/ava-labs/libevm/libevm"
32+ "github.com/ava-labs/libevm/libevm/stateconf"
3233 "github.com/ava-labs/libevm/params"
3334)
3435
@@ -43,10 +44,22 @@ import (
4344//
4445// Scenario (2) allows precompile access to be determined through inspection of
4546// the [types.Transaction] alone, without the need for execution.
47+ //
48+ // All [libevm.StateReader] instances are opened to the state at the beginning
49+ // of the block. The [StateDB] is the same one used to execute the block,
50+ // before being committed, and MAY be written to.
4651type Handler [Result any ] interface {
47- BeforeBlock (* types.Header )
52+ BeforeBlock (libevm. StateReader , * types.Block )
4853 Gas (* types.Transaction ) (gas uint64 , process bool )
4954 Process (sdb libevm.StateReader , index int , tx * types.Transaction ) Result
55+ AfterBlock (StateDB , * types.Block , types.Receipts )
56+ }
57+
58+ // StateDB is the subset of [state.StateDB] methods that MAY be called by
59+ // [Handler.AfterBlock].
60+ type StateDB interface {
61+ libevm.StateReader
62+ SetState (_ common.Address , key , val common.Hash , _ ... stateconf.StateDBStateOption )
5063}
5164
5265// A Processor orchestrates dispatch and collection of results from a [Handler].
@@ -162,9 +175,19 @@ func (p *Processor[R]) Close() {
162175// StartBlock dispatches transactions to the [Handler] and returns immediately.
163176// It MUST be paired with a call to [Processor.FinishBlock], without overlap of
164177// blocks.
165- func (p * Processor [R ]) StartBlock (b * types.Block , rules params.Rules , sdb * state.StateDB ) error {
178+ func (p * Processor [R ]) StartBlock (sdb * state.StateDB , rules params.Rules , b * types.Block ) error {
179+ // The distribution mechanism copies the StateDB so we don't need to do it
180+ // here, but the [Handler] is called directly so we do copy.
166181 p .stateShare .distribute (sdb )
167- p .handler .BeforeBlock (types .CopyHeader (b .Header ()))
182+ p .handler .BeforeBlock (
183+ sdb .Copy (),
184+ types .NewBlockWithHeader (
185+ b .Header (),
186+ ).WithBody (
187+ * b .Body (),
188+ ),
189+ )
190+
168191 txs := b .Transactions ()
169192 jobs := make ([]* job , 0 , len (txs ))
170193
@@ -206,14 +229,15 @@ func (p *Processor[R]) StartBlock(b *types.Block, rules params.Rules, sdb *state
206229// FinishBlock returns the [Processor] to a state ready for the next block. A
207230// return from FinishBlock guarantees that all dispatched work from the
208231// respective call to [Processor.StartBlock] has been completed.
209- func (p * Processor [R ]) FinishBlock (b * types.Block ) {
232+ func (p * Processor [R ]) FinishBlock (sdb vm. StateDB , b * types.Block , rs types. Receipts ) {
210233 for i := range len (b .Transactions ()) {
211234 // Every result channel is guaranteed to have some value in its buffer
212235 // because [Processor.BeforeBlock] either sends a nil *R or it
213236 // dispatches a job, which will send a non-nil *R.
214237 tx := (<- p .results [i ]).tx
215238 delete (p .txGas , tx )
216239 }
240+ p .handler .AfterBlock (sdb , b , rs )
217241}
218242
219243// Result blocks until the i'th transaction passed to [Processor.StartBlock] has
0 commit comments