@@ -22,7 +22,7 @@ import (
2222 "reflect"
2323
2424 "github.com/ava-labs/libevm/libevm/pseudo"
25- "github.com/ava-labs/libevm/libevm/testonly "
25+ "github.com/ava-labs/libevm/libevm/register "
2626)
2727
2828// Extras are arbitrary payloads to be added as extra fields in [ChainConfig]
@@ -68,20 +68,17 @@ type Extras[C ChainConfigHooks, R RulesHooks] struct {
6868// alter Ethereum behaviour; if this isn't desired then they can embed
6969// [NOOPHooks] to satisfy either interface.
7070func RegisterExtras [C ChainConfigHooks , R RulesHooks ](e Extras [C , R ]) ExtraPayloads [C , R ] {
71- if registeredExtras != nil {
72- panic ("re-registration of Extras" )
73- }
7471 mustBeStructOrPointerToOne [C ]()
7572 mustBeStructOrPointerToOne [R ]()
7673
7774 payloads := e .payloads ()
78- registeredExtras = & extraConstructors {
75+ registeredExtras . MustRegister ( & extraConstructors {
7976 newChainConfig : pseudo .NewConstructor [C ]().Zero ,
8077 newRules : pseudo .NewConstructor [R ]().Zero ,
8178 reuseJSONRoot : e .ReuseJSONRoot ,
8279 newForRules : e .newForRules ,
8380 payloads : payloads ,
84- }
81+ })
8582 return payloads
8683}
8784
@@ -92,14 +89,12 @@ func RegisterExtras[C ChainConfigHooks, R RulesHooks](e Extras[C, R]) ExtraPaylo
9289// defer-called afterwards, either directly or via testing.TB.Cleanup(). This is
9390// a workaround for the single-call limitation on [RegisterExtras].
9491func TestOnlyClearRegisteredExtras () {
95- testonly .OrPanic (func () {
96- registeredExtras = nil
97- })
92+ registeredExtras .TestOnlyClear ()
9893}
9994
10095// registeredExtras holds non-generic constructors for the [Extras] types
10196// registered via [RegisterExtras].
102- var registeredExtras * extraConstructors
97+ var registeredExtras register. AtMostOnce [ * extraConstructors ]
10398
10499type extraConstructors struct {
105100 newChainConfig , newRules func () * pseudo.Type
@@ -115,7 +110,7 @@ type extraConstructors struct {
115110
116111func (e * Extras [C , R ]) newForRules (c * ChainConfig , r * Rules , blockNum * big.Int , isMerge bool , timestamp uint64 ) * pseudo.Type {
117112 if e .NewRules == nil {
118- return registeredExtras .newRules ()
113+ return registeredExtras .Get (). newRules ()
119114 }
120115 rExtra := e .NewRules (c , r , e .payloads ().FromChainConfig (c ), blockNum , isMerge , timestamp )
121116 return pseudo .From (rExtra ).Type
@@ -209,36 +204,36 @@ func (e ExtraPayloads[C, R]) hooksFromRules(r *Rules) RulesHooks {
209204// abstract the libevm-specific behaviour outside of original geth code.
210205func (c * ChainConfig ) addRulesExtra (r * Rules , blockNum * big.Int , isMerge bool , timestamp uint64 ) {
211206 r .extra = nil
212- if registeredExtras != nil {
213- r .extra = registeredExtras .newForRules (c , r , blockNum , isMerge , timestamp )
207+ if registeredExtras . Registered () {
208+ r .extra = registeredExtras .Get (). newForRules (c , r , blockNum , isMerge , timestamp )
214209 }
215210}
216211
217212// extraPayload returns the ChainConfig's extra payload iff [RegisterExtras] has
218213// already been called. If the payload hasn't been populated (typically via
219214// unmarshalling of JSON), a nil value is constructed and returned.
220215func (c * ChainConfig ) extraPayload () * pseudo.Type {
221- if registeredExtras == nil {
216+ if ! registeredExtras . Registered () {
222217 // This will only happen if someone constructs an [ExtraPayloads]
223218 // directly, without a call to [RegisterExtras].
224219 //
225220 // See https://google.github.io/styleguide/go/best-practices#when-to-panic
226221 panic (fmt .Sprintf ("%T.ExtraPayload() called before RegisterExtras()" , c ))
227222 }
228223 if c .extra == nil {
229- c .extra = registeredExtras .newChainConfig ()
224+ c .extra = registeredExtras .Get (). newChainConfig ()
230225 }
231226 return c .extra
232227}
233228
234229// extraPayload is equivalent to [ChainConfig.extraPayload].
235230func (r * Rules ) extraPayload () * pseudo.Type {
236- if registeredExtras == nil {
231+ if ! registeredExtras . Registered () {
237232 // See ChainConfig.extraPayload() equivalent.
238233 panic (fmt .Sprintf ("%T.ExtraPayload() called before RegisterExtras()" , r ))
239234 }
240235 if r .extra == nil {
241- r .extra = registeredExtras .newRules ()
236+ r .extra = registeredExtras .Get (). newRules ()
242237 }
243238 return r .extra
244239}
0 commit comments