Skip to content

Commit 3cf1438

Browse files
committed
feat: types.WithTempRegisteredExtras()
1 parent adfef8b commit 3cf1438

File tree

3 files changed

+116
-20
lines changed

3 files changed

+116
-20
lines changed

core/types/block.libevm.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ type BlockBodyHooks interface {
130130
// to no type having been registered.
131131
type NOOPBlockBodyHooks struct{}
132132

133-
var _ BlockBodyPayload[*NOOPBlockBodyHooks] = NOOPBlockBodyHooks{}
133+
var _ BlockBodyPayload[*NOOPBlockBodyHooks] = (*NOOPBlockBodyHooks)(nil)
134134

135135
func (NOOPBlockBodyHooks) Copy() *NOOPBlockBodyHooks { return &NOOPBlockBodyHooks{} }
136136

core/types/rlp_payload.libevm.go

Lines changed: 54 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,27 @@ import (
4444
// [Header] or [Block] / [Body] is a non-nil `HPtr` or `BPtr` respectively. The
4545
// latter guarantee ensures that hooks won't be called on nil-pointer receivers.
4646
func RegisterExtras[
47-
H any, HPtr interface {
48-
HeaderHooks
49-
*H
50-
},
51-
B any, BPtr interface {
52-
BlockBodyPayload[BPtr]
53-
*B
54-
},
47+
H any, HPtr HeaderHooksPointer[H],
48+
B any, BPtr BlockBodyHooksPointer[B, BPtr],
5549
SA any,
5650
]() ExtraPayloads[HPtr, BPtr, SA] {
57-
extra := ExtraPayloads[HPtr, BPtr, SA]{
51+
payloads, ctors := payloadsAndConstructors[H, HPtr, B, BPtr, SA]()
52+
registeredExtras.MustRegister(ctors)
53+
log.Info(
54+
"Registered core/types extras",
55+
"Header", log.TypeOf(pseudo.Zero[HPtr]().Value.Get()),
56+
"Block/Body", log.TypeOf(pseudo.Zero[BPtr]().Value.Get()),
57+
"StateAccount", log.TypeOf(pseudo.Zero[SA]().Value.Get()),
58+
)
59+
return payloads
60+
}
61+
62+
func payloadsAndConstructors[
63+
H any, HPtr HeaderHooksPointer[H],
64+
B any, BPtr BlockBodyHooksPointer[B, BPtr],
65+
SA any,
66+
]() (ExtraPayloads[HPtr, BPtr, SA], *extraConstructors) {
67+
payloads := ExtraPayloads[HPtr, BPtr, SA]{
5868
Header: pseudo.NewAccessor[*Header, HPtr](
5969
(*Header).extraPayload,
6070
func(h *Header, t *pseudo.Type) { h.extra = t },
@@ -72,7 +82,7 @@ func RegisterExtras[
7282
func(a StateOrSlimAccount, t *pseudo.Type) { a.extra().t = t },
7383
),
7484
}
75-
registeredExtras.MustRegister(&extraConstructors{
85+
ctors := &extraConstructors{
7686
stateAccountType: func() string {
7787
var x SA
7888
return fmt.Sprintf("%T", x)
@@ -84,15 +94,40 @@ func RegisterExtras[
8494
newHeader: pseudo.NewConstructor[H]().NewPointer, // i.e. non-nil HPtr
8595
newBlockOrBody: pseudo.NewConstructor[B]().NewPointer, // i.e. non-nil BPtr
8696
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
97+
hooks: payloads,
98+
}
99+
return payloads, ctors
100+
}
101+
102+
// WithTempRegisteredExtras temporarily registers `HPtr`, `BPtr`, and `SA` as if
103+
// calling [RegisterExtras] the same type parameters. The [ExtraPayloads] are
104+
// passed to `fn` instead of being returned. After `fn` returns, the
105+
// registration is returned to its former state, be that none or the types
106+
// originally passed to [RegisterExtras].
107+
//
108+
// This MUST NOT be used in a live chain. It is solely intended for off-chain
109+
// consumers that require access to extras.
110+
func WithTempRegisteredExtras[
111+
H any, B any, SA any,
112+
HPtr HeaderHooksPointer[H],
113+
BPtr BlockBodyHooksPointer[B, BPtr],
114+
](fn func(ExtraPayloads[HPtr, BPtr, SA])) {
115+
payloads, ctors := payloadsAndConstructors[H, HPtr, B, BPtr, SA]()
116+
registeredExtras.TempOverride(ctors, func() { fn(payloads) })
117+
}
118+
119+
// A HeaderHooksPointer is a type constraint for an implementation of
120+
// [HeaderHooks] with a pointer receiver.
121+
type HeaderHooksPointer[H any] interface {
122+
HeaderHooks
123+
*H
124+
}
125+
126+
// A BlockBodyHooksPointer is a type constraint for an implementation of
127+
// [BlockBodyPayload] with a pointer receiver.
128+
type BlockBodyHooksPointer[B any, Self any] interface {
129+
BlockBodyPayload[Self]
130+
*B
96131
}
97132

98133
// A BlockBodyPayload is an implementation of [BlockBodyHooks] that is also able
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright 2025 the libevm authors.
2+
//
3+
// The libevm additions to go-ethereum are free software: you can redistribute
4+
// them and/or modify them under the terms of the GNU Lesser General Public License
5+
// as published by the Free Software Foundation, either version 3 of the License,
6+
// or (at your option) any later version.
7+
//
8+
// The libevm additions are distributed in the hope that they will be useful,
9+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
11+
// General Public License for more details.
12+
//
13+
// You should have received a copy of the GNU Lesser General Public License
14+
// along with the go-ethereum library. If not, see
15+
// <http://www.gnu.org/licenses/>.
16+
17+
package types
18+
19+
import (
20+
"testing"
21+
)
22+
23+
func TestTempRegisteredExtras(t *testing.T) {
24+
TestOnlyClearRegisteredExtras()
25+
t.Cleanup(TestOnlyClearRegisteredExtras)
26+
27+
type (
28+
primary struct {
29+
NOOPHeaderHooks
30+
}
31+
override struct {
32+
NOOPHeaderHooks
33+
}
34+
)
35+
36+
RegisterExtras[primary, *primary, NOOPBlockBodyHooks, *NOOPBlockBodyHooks, bool]()
37+
testPrimaryExtras := func(t *testing.T) {
38+
t.Helper()
39+
assertHeaderHooksConcreteType[*primary](t)
40+
}
41+
42+
t.Run("before_temp", testPrimaryExtras)
43+
t.Run("WithTempRegisteredExtras", func(t *testing.T) {
44+
WithTempRegisteredExtras(func(ExtraPayloads[*override, *NOOPBlockBodyHooks, bool]) {
45+
assertHeaderHooksConcreteType[*override](t)
46+
})
47+
})
48+
t.Run("after_temp", testPrimaryExtras)
49+
}
50+
51+
func assertHeaderHooksConcreteType[WantT any](t *testing.T) {
52+
t.Helper()
53+
54+
hdr := new(Header)
55+
switch got := hdr.hooks().(type) {
56+
case WantT:
57+
default:
58+
var want WantT
59+
t.Errorf("%T.hooks() got concrete type %T; want %T", hdr, got, want)
60+
}
61+
}

0 commit comments

Comments
 (0)