Skip to content

Commit 74ed069

Browse files
committed
feat: before- and after-block hooks with additional arguments
1 parent 866bb86 commit 74ed069

File tree

2 files changed

+28
-10
lines changed

2 files changed

+28
-10
lines changed

libevm/precompiles/parallel/parallel.go

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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.
4650
type 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

libevm/precompiles/parallel/parallel_test.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ type concat struct {
5454
gas uint64
5555
}
5656

57-
func (c *concat) BeforeBlock(h *types.Header) {
58-
c.headerExtra = slices.Clone(h.Extra)
57+
func (c *concat) BeforeBlock(_ libevm.StateReader, b *types.Block) {
58+
c.headerExtra = slices.Clone(b.Header().Extra)
5959
}
6060

6161
func (c *concat) Gas(tx *types.Transaction) (uint64, bool) {
@@ -77,6 +77,8 @@ func (c *concat) Process(sdb libevm.StateReader, i int, tx *types.Transaction) [
7777
)
7878
}
7979

80+
func (*concat) AfterBlock(vm.StateDB, *types.Block, types.Receipts) {}
81+
8082
func TestProcessor(t *testing.T) {
8183
handler := &concat{
8284
addr: common.Address{'c', 'o', 'n', 'c', 'a', 't'},
@@ -173,8 +175,8 @@ func TestProcessor(t *testing.T) {
173175

174176
extra := []byte("extra")
175177
block := types.NewBlock(&types.Header{Extra: extra}, txs, nil, nil, trie.NewStackTrie(nil))
176-
require.NoError(t, p.StartBlock(block, rules, sdb), "StartBlock()")
177-
defer p.FinishBlock(block)
178+
require.NoError(t, p.StartBlock(sdb, rules, block), "StartBlock()")
179+
defer p.FinishBlock(sdb, block, nil)
178180

179181
for i, tx := range txs {
180182
wantOK := wantProcessed[i]
@@ -305,8 +307,7 @@ func TestIntegration(t *testing.T) {
305307
}
306308

307309
block := types.NewBlock(header, txs, nil, nil, trie.NewStackTrie(nil))
308-
require.NoError(t, sut.StartBlock(block, rules, state), "StartBlock()")
309-
defer sut.FinishBlock(block)
310+
require.NoError(t, sut.StartBlock(state, rules, block), "StartBlock()")
310311

311312
pool := core.GasPool(math.MaxUint64)
312313
var got []*types.Receipt
@@ -332,4 +333,5 @@ func TestIntegration(t *testing.T) {
332333
if diff := cmp.Diff(want, got, ignore); diff != "" {
333334
t.Errorf("%T diff (-want +got):\n%s", got, diff)
334335
}
336+
sut.FinishBlock(state, block, got)
335337
}

0 commit comments

Comments
 (0)