@@ -43,10 +43,15 @@ import (
4343//
4444// Scenario (2) allows precompile access to be determined through inspection of
4545// the [types.Transaction] alone, without the need for execution.
46+ //
47+ // All [libevm.StateReader] instances are opened to the state at the beginning
48+ // of the block. The [vm.StateDB] is the same one used to execute the block,
49+ // before being committed.
4650type Handler [Result any ] interface {
47- BeforeBlock (* types.Header )
51+ BeforeBlock (libevm. StateReader , * types.Block )
4852 Gas (* types.Transaction ) (gas uint64 , process bool )
4953 Process (sdb libevm.StateReader , index int , tx * types.Transaction ) Result
54+ AfterBlock (vm.StateDB , * types.Block , types.Receipts )
5055}
5156
5257// A Processor orchestrates dispatch and collection of results from a [Handler].
@@ -162,9 +167,19 @@ func (p *Processor[R]) Close() {
162167// StartBlock dispatches transactions to the [Handler] and returns immediately.
163168// It MUST be paired with a call to [Processor.FinishBlock], without overlap of
164169// blocks.
165- func (p * Processor [R ]) StartBlock (b * types.Block , rules params.Rules , sdb * state.StateDB ) error {
170+ func (p * Processor [R ]) StartBlock (sdb * state.StateDB , rules params.Rules , b * types.Block ) error {
171+ // The distribution mechanism copies the StateDB so we don't need to do it
172+ // here, but the [Handler] is called directly so we do copy.
166173 p .stateShare .distribute (sdb )
167- p .handler .BeforeBlock (types .CopyHeader (b .Header ()))
174+ p .handler .BeforeBlock (
175+ sdb .Copy (),
176+ types .NewBlockWithHeader (
177+ b .Header (),
178+ ).WithBody (
179+ * b .Body (),
180+ ),
181+ )
182+
168183 txs := b .Transactions ()
169184 jobs := make ([]* job , 0 , len (txs ))
170185
@@ -206,14 +221,15 @@ func (p *Processor[R]) StartBlock(b *types.Block, rules params.Rules, sdb *state
206221// FinishBlock returns the [Processor] to a state ready for the next block. A
207222// return from FinishBlock guarantees that all dispatched work from the
208223// respective call to [Processor.StartBlock] has been completed.
209- func (p * Processor [R ]) FinishBlock (b * types.Block ) {
224+ func (p * Processor [R ]) FinishBlock (sdb vm. StateDB , b * types.Block , rs types. Receipts ) {
210225 for i := range len (b .Transactions ()) {
211226 // Every result channel is guaranteed to have some value in its buffer
212227 // because [Processor.BeforeBlock] either sends a nil *R or it
213228 // dispatches a job, which will send a non-nil *R.
214229 tx := (<- p .results [i ]).tx
215230 delete (p .txGas , tx )
216231 }
232+ p .handler .AfterBlock (sdb , b , rs )
217233}
218234
219235// Result blocks until the i'th transaction passed to [Processor.StartBlock] has
0 commit comments