Skip to content

Commit c54d88d

Browse files
committed
feat: params.WithTempRegisteredExtras()
1 parent 7841149 commit c54d88d

File tree

2 files changed

+114
-8
lines changed

2 files changed

+114
-8
lines changed

params/config.libevm.go

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,8 @@ func RegisterExtras[C ChainConfigHooks, R RulesHooks](e Extras[C, R]) ExtraPaylo
7272
mustBeStructOrPointerToOne[C]()
7373
mustBeStructOrPointerToOne[R]()
7474

75-
payloads := e.payloads()
76-
registeredExtras.MustRegister(&extraConstructors{
77-
newChainConfig: pseudo.NewConstructor[C]().Zero,
78-
newRules: pseudo.NewConstructor[R]().Zero,
79-
reuseJSONRoot: e.ReuseJSONRoot,
80-
newForRules: e.newForRules,
81-
payloads: payloads,
82-
})
75+
payloads, ctors := payloadsAndConstructors(e)
76+
registeredExtras.MustRegister(ctors)
8377
log.Info(
8478
"Registered params extras",
8579
"ChainConfig", log.TypeOf(pseudo.Zero[C]().Value.Get()),
@@ -89,6 +83,33 @@ func RegisterExtras[C ChainConfigHooks, R RulesHooks](e Extras[C, R]) ExtraPaylo
8983
return payloads
9084
}
9185

86+
func payloadsAndConstructors[C ChainConfigHooks, R RulesHooks](e Extras[C, R]) (ExtraPayloads[C, R], *extraConstructors) {
87+
payloads := e.payloads()
88+
return payloads, &extraConstructors{
89+
newChainConfig: pseudo.NewConstructor[C]().Zero,
90+
newRules: pseudo.NewConstructor[R]().Zero,
91+
reuseJSONRoot: e.ReuseJSONRoot,
92+
newForRules: e.newForRules,
93+
payloads: payloads,
94+
}
95+
}
96+
97+
// WithTempRegisteredExtras temporarily registers `C` and `R` as if calling
98+
// [RegisterExtras] with `e`. The [ExtraPayloads] are passed to `fn` instead of
99+
// being returned. After `fn` returns, the registration is returned to its
100+
// former state, be that none or the types originally passed to
101+
// [RegisterExtras].
102+
//
103+
// This MUST NOT be used in a live chain. It is solely intended for off-chain
104+
// consumers that require access to extras.
105+
func WithTempRegisteredExtras[C ChainConfigHooks, R RulesHooks](
106+
e Extras[C, R],
107+
fn func(ExtraPayloads[C, R]),
108+
) {
109+
payloads, ctors := payloadsAndConstructors(e)
110+
registeredExtras.TempOverride(ctors, func() { fn(payloads) })
111+
}
112+
92113
// TestOnlyClearRegisteredExtras clears the [Extras] previously passed to
93114
// [RegisterExtras]. It panics if called from a non-testing call stack.
94115
//

params/config.libevm_test.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,3 +277,88 @@ func assertPanics(t *testing.T, fn func(), wantContains string) {
277277
}()
278278
fn()
279279
}
280+
281+
func TestTempRegisteredExtras(t *testing.T) {
282+
TestOnlyClearRegisteredExtras()
283+
t.Cleanup(TestOnlyClearRegisteredExtras)
284+
285+
type (
286+
primaryCC struct {
287+
X int
288+
NOOPHooks
289+
}
290+
primaryRules struct {
291+
X int
292+
NOOPHooks
293+
}
294+
295+
overrideCC struct {
296+
X string
297+
NOOPHooks
298+
}
299+
overrideRules struct {
300+
X string
301+
NOOPHooks
302+
}
303+
)
304+
305+
primary := Extras[primaryCC, primaryRules]{
306+
NewRules: func(_ *ChainConfig, _ *Rules, cc primaryCC, _ *big.Int, _ bool, _ uint64) primaryRules {
307+
return primaryRules{
308+
X: cc.X,
309+
}
310+
},
311+
}
312+
override := Extras[overrideCC, overrideRules]{
313+
NewRules: func(_ *ChainConfig, _ *Rules, cc overrideCC, _ *big.Int, _ bool, _ uint64) overrideRules {
314+
return overrideRules{
315+
X: cc.X,
316+
}
317+
},
318+
}
319+
320+
extras := RegisterExtras(primary)
321+
testPrimaryExtras := func(t *testing.T) {
322+
t.Helper()
323+
assertRulesCopiedFromChainConfig(
324+
t, extras, 42,
325+
func(cc *primaryCC, x int) { cc.X = x },
326+
func(r *primaryRules) int { return r.X },
327+
)
328+
}
329+
330+
t.Run("before_temp", testPrimaryExtras)
331+
t.Run("WithTempRegisteredExtras", func(t *testing.T) {
332+
WithTempRegisteredExtras(
333+
override,
334+
func(extras ExtraPayloads[overrideCC, overrideRules]) { // deliberately shadow `extras`
335+
assertRulesCopiedFromChainConfig(
336+
t, extras, "hello, world",
337+
func(cc *overrideCC, x string) { cc.X = x },
338+
func(r *overrideRules) string { return r.X },
339+
)
340+
},
341+
)
342+
})
343+
t.Run("after_temp", testPrimaryExtras)
344+
}
345+
346+
func assertRulesCopiedFromChainConfig[C ChainConfigHooks, R RulesHooks, Payload any](
347+
t *testing.T,
348+
extras ExtraPayloads[C, R],
349+
val Payload,
350+
setX func(*C, Payload),
351+
getX func(*R) Payload,
352+
) {
353+
t.Helper()
354+
355+
cc := new(ChainConfig)
356+
var ccExtra C
357+
setX(&ccExtra, val)
358+
359+
extras.ChainConfig.Set(cc, ccExtra)
360+
rules := cc.Rules(nil, false, 0)
361+
rulesExtra := extras.Rules.Get(&rules)
362+
363+
assert.Equalf(t, val, getX(&rulesExtra), "%T.X copied from %T.X", rulesExtra, ccExtra)
364+
}

0 commit comments

Comments
 (0)