@@ -21,6 +21,7 @@ import (
2121 "io"
2222
2323 "github.com/ava-labs/libevm/common"
24+ "github.com/ava-labs/libevm/libevm"
2425 "github.com/ava-labs/libevm/libevm/pseudo"
2526 "github.com/ava-labs/libevm/libevm/register"
2627 "github.com/ava-labs/libevm/libevm/testonly"
@@ -44,17 +45,27 @@ import (
4445// [Header] or [Block] / [Body] is a non-nil `HPtr` or `BPtr` respectively. The
4546// latter guarantee ensures that hooks won't be called on nil-pointer receivers.
4647func RegisterExtras [
47- H any , HPtr interface {
48- HeaderHooks
49- * H
50- },
51- B any , BPtr interface {
52- BlockBodyPayload [BPtr ]
53- * B
54- },
48+ H any , HPtr HeaderHooksPointer [H ],
49+ B any , BPtr BlockBodyHooksPointer [B , BPtr ],
5550 SA any ,
5651]() ExtraPayloads [HPtr , BPtr , SA ] {
57- extra := ExtraPayloads [HPtr , BPtr , SA ]{
52+ payloads , ctors := payloadsAndConstructors [H , HPtr , B , BPtr , SA ]()
53+ registeredExtras .MustRegister (ctors )
54+ log .Info (
55+ "Registered core/types extras" ,
56+ "Header" , log .TypeOf (pseudo .Zero [HPtr ]().Value .Get ()),
57+ "Block/Body" , log .TypeOf (pseudo .Zero [BPtr ]().Value .Get ()),
58+ "StateAccount" , log .TypeOf (pseudo .Zero [SA ]().Value .Get ()),
59+ )
60+ return payloads
61+ }
62+
63+ func payloadsAndConstructors [
64+ H any , HPtr HeaderHooksPointer [H ],
65+ B any , BPtr BlockBodyHooksPointer [B , BPtr ],
66+ SA any ,
67+ ]() (ExtraPayloads [HPtr , BPtr , SA ], * extraConstructors ) {
68+ payloads := ExtraPayloads [HPtr , BPtr , SA ]{
5869 Header : pseudo .NewAccessor [* Header , HPtr ](
5970 (* Header ).extraPayload ,
6071 func (h * Header , t * pseudo.Type ) { h .extra = t },
@@ -72,7 +83,7 @@ func RegisterExtras[
7283 func (a StateOrSlimAccount , t * pseudo.Type ) { a .extra ().t = t },
7384 ),
7485 }
75- registeredExtras . MustRegister ( & extraConstructors {
86+ ctors := & extraConstructors {
7687 stateAccountType : func () string {
7788 var x SA
7889 return fmt .Sprintf ("%T" , x )
@@ -84,23 +95,54 @@ func RegisterExtras[
8495 newHeader : pseudo .NewConstructor [H ]().NewPointer , // i.e. non-nil HPtr
8596 newBlockOrBody : pseudo .NewConstructor [B ]().NewPointer , // i.e. non-nil BPtr
8697 newStateAccount : pseudo .NewConstructor [SA ]().Zero ,
87- hooks : extra ,
88- })
89- log .Info (
90- "Registered core/types extras" ,
91- "Header" , log .TypeOf (pseudo .Zero [HPtr ]().Value .Get ()),
92- "Block/Body" , log .TypeOf (pseudo .Zero [BPtr ]().Value .Get ()),
93- "StateAccount" , log .TypeOf (pseudo .Zero [SA ]().Value .Get ()),
94- )
95- return extra
98+ hooks : payloads ,
99+ }
100+ return payloads , ctors
101+ }
102+
103+ // WithTempRegisteredExtras temporarily registers `HPtr`, `BPtr`, and `SA` as if
104+ // calling [RegisterExtras] the same type parameters. The [ExtraPayloads] are
105+ // passed to `fn` instead of being returned; the argument MUST NOT be persisted
106+ // beyond the life of `fn`. After `fn` returns, the registration is returned to
107+ // its former state, be that none or the types originally passed to
108+ // [RegisterExtras].
109+ //
110+ // This MUST NOT be used on a live chain. It is solely intended for off-chain
111+ // consumers that require access to extras. Said consumers SHOULD NOT, however
112+ // call this function directly. Use the libevm/temporary.WithRegisteredExtras()
113+ // function instead as it atomically overrides all possible packages.
114+ func WithTempRegisteredExtras [
115+ H , B , SA any ,
116+ HPtr HeaderHooksPointer [H ],
117+ BPtr BlockBodyHooksPointer [B , BPtr ],
118+ ](lock libevm.ExtrasLock , fn func (ExtraPayloads [HPtr , BPtr , SA ]) error ) error {
119+ if err := lock .Verify (); err != nil {
120+ return err
121+ }
122+ payloads , ctors := payloadsAndConstructors [H , HPtr , B , BPtr , SA ]()
123+ return registeredExtras .TempOverride (ctors , func () error { return fn (payloads ) })
124+ }
125+
126+ // A HeaderHooksPointer is a type constraint for an implementation of
127+ // [HeaderHooks] with a pointer receiver.
128+ type HeaderHooksPointer [H any ] interface {
129+ HeaderHooks
130+ * H
131+ }
132+
133+ // A BlockBodyHooksPointer is a type constraint for an implementation of
134+ // [BlockBodyPayload] with a pointer receiver.
135+ type BlockBodyHooksPointer [B any , Self any ] interface {
136+ BlockBodyPayload [Self ]
137+ * B
96138}
97139
98140// A BlockBodyPayload is an implementation of [BlockBodyHooks] that is also able
99141// to clone itself. Both [Block.Body] and [Block.WithBody] require this
100142// functionality to copy the payload between the types.
101- type BlockBodyPayload [BPtr any ] interface {
143+ type BlockBodyPayload [Self any ] interface {
102144 BlockBodyHooks
103- Copy () BPtr
145+ Copy () Self
104146}
105147
106148// TestOnlyClearRegisteredExtras clears the [Extras] previously passed to
0 commit comments