1919package parallel
2020
2121import (
22+ "errors"
2223 "fmt"
2324 "sync"
2425
@@ -154,7 +155,8 @@ func (p *Processor[R]) FinishBlock(b *types.Block) {
154155 // Every result channel is guaranteed to have some value in its buffer
155156 // because [Processor.BeforeBlock] either sends a nil *R or it
156157 // dispatches a job that will send a non-nil *R.
157- delete (p .txGas , (<- p .results [i ]).tx )
158+ tx := (<- p .results [i ]).tx
159+ delete (p .txGas , tx )
158160 }
159161}
160162
@@ -171,7 +173,7 @@ func (p *Processor[R]) FinishBlock(b *types.Block) {
171173// that if R is a pointer then modifications will persist between calls.
172174func (p * Processor [R ]) Result (i int ) (R , bool ) {
173175 ch := p .results [i ]
174- r := ( <- ch )
176+ r := <- ch
175177 defer func () {
176178 ch <- r
177179 }()
@@ -185,13 +187,17 @@ func (p *Processor[R]) Result(i int) (R, bool) {
185187 return * r .val , true
186188}
187189
188- func (p * Processor [R ]) shouldProcess (tx * types.Transaction , rules params.Rules ) (ok bool , err error ) {
190+ func (p * Processor [R ]) shouldProcess (tx * types.Transaction , rules params.Rules ) (process bool , err error ) {
191+ // An explicit 0 is necessary to avoid [Processor.PreprocessingGasCharge]
192+ // returning [ErrTxUnknown].
193+ p .txGas [tx .Hash ()] = 0
194+
189195 cost , ok := p .handler .Gas (tx )
190196 if ! ok {
191197 return false , nil
192198 }
193199 defer func () {
194- if ok && err == nil {
200+ if process && err == nil {
195201 p .txGas [tx .Hash ()] = cost
196202 }
197203 }()
@@ -214,10 +220,19 @@ func (p *Processor[R]) shouldProcess(tx *types.Transaction, rules params.Rules)
214220 return left >= cost , nil
215221}
216222
217- var _ vm.Preprocessor = (* Processor [struct {}])(nil )
223+ // ErrTxUnknown is returned by [Processor.PreprocessingGasCharge] if it is
224+ // called with a transaction hash that wasn't in the last block passed to
225+ // [Processor.StartBlock].
226+ var ErrTxUnknown = errors .New ("transaction unknown by parallel preprocessor" )
218227
219228// PreprocessingGasCharge implements the [vm.Preprocessor] interface and MUST be
220229// registered via [vm.RegisterHooks] to ensure proper gas accounting.
221- func (p * Processor [R ]) PreprocessingGasCharge (tx common.Hash ) uint64 {
222- return p .txGas [tx ]
230+ func (p * Processor [R ]) PreprocessingGasCharge (tx common.Hash ) (uint64 , error ) {
231+ g , ok := p .txGas [tx ]
232+ if ! ok {
233+ return 0 , fmt .Errorf ("%w: %v" , ErrTxUnknown , tx )
234+ }
235+ return g , nil
223236}
237+
238+ var _ vm.Preprocessor = (* Processor [struct {}])(nil )
0 commit comments