mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-17 18:30:45 +00:00
fix: ExtraPayloads.SetOn{ChainConfig,Rules}() overrides shallow copy (#42)
This commit is contained in:
parent
210f8ab8e1
commit
1478c18b9a
2 changed files with 41 additions and 16 deletions
|
|
@ -169,14 +169,18 @@ func (ExtraPayloads[C, R]) FromChainConfig(c *ChainConfig) C {
|
||||||
|
|
||||||
// PointerFromChainConfig returns a pointer to the ChainConfig's extra payload.
|
// PointerFromChainConfig returns a pointer to the ChainConfig's extra payload.
|
||||||
// This is guaranteed to be non-nil.
|
// This is guaranteed to be non-nil.
|
||||||
|
//
|
||||||
|
// Note that copying a ChainConfig by dereferencing a pointer will result in a
|
||||||
|
// shallow copy and that the *C returned here will therefore be shared by all
|
||||||
|
// copies. If this is not the desired behaviour, use
|
||||||
|
// [ExtraPayloads.SetOnChainConfig].
|
||||||
func (ExtraPayloads[C, R]) PointerFromChainConfig(c *ChainConfig) *C {
|
func (ExtraPayloads[C, R]) PointerFromChainConfig(c *ChainConfig) *C {
|
||||||
return pseudo.MustPointerTo[C](c.extraPayload()).Value.Get()
|
return pseudo.MustPointerTo[C](c.extraPayload()).Value.Get()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetOnChainConfig sets the ChainConfig's extra payload. It is equivalent to
|
// SetOnChainConfig sets the ChainConfig's extra payload.
|
||||||
// `*e.PointerFromChainConfig(cc) = val`.
|
|
||||||
func (e ExtraPayloads[C, R]) SetOnChainConfig(cc *ChainConfig, val C) {
|
func (e ExtraPayloads[C, R]) SetOnChainConfig(cc *ChainConfig, val C) {
|
||||||
*e.PointerFromChainConfig(cc) = val
|
cc.extra = pseudo.From(val).Type
|
||||||
}
|
}
|
||||||
|
|
||||||
// hooksFromChainConfig is equivalent to FromChainConfig(), but returns an
|
// hooksFromChainConfig is equivalent to FromChainConfig(), but returns an
|
||||||
|
|
@ -193,14 +197,17 @@ func (ExtraPayloads[C, R]) FromRules(r *Rules) R {
|
||||||
|
|
||||||
// PointerFromRules returns a pointer to the Rules's extra payload. This is
|
// PointerFromRules returns a pointer to the Rules's extra payload. This is
|
||||||
// guaranteed to be non-nil.
|
// guaranteed to be non-nil.
|
||||||
|
//
|
||||||
|
// Note that copying a Rules by dereferencing a pointer will result in a shallow
|
||||||
|
// copy and that the *R returned here will therefore be shared by all copies. If
|
||||||
|
// this is not the desired behaviour, use [ExtraPayloads.SetOnRules].
|
||||||
func (ExtraPayloads[C, R]) PointerFromRules(r *Rules) *R {
|
func (ExtraPayloads[C, R]) PointerFromRules(r *Rules) *R {
|
||||||
return pseudo.MustPointerTo[R](r.extraPayload()).Value.Get()
|
return pseudo.MustPointerTo[R](r.extraPayload()).Value.Get()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetOnRules sets the Rules' extra payload. It is equivalent to
|
// SetOnRules sets the Rules' extra payload.
|
||||||
// `*e.PointerFromRules(r) = val`.
|
|
||||||
func (e ExtraPayloads[C, R]) SetOnRules(r *Rules, val R) {
|
func (e ExtraPayloads[C, R]) SetOnRules(r *Rules, val R) {
|
||||||
*e.PointerFromRules(r) = val
|
r.extra = pseudo.From(val).Type
|
||||||
}
|
}
|
||||||
|
|
||||||
// hooksFromRules is the [RulesHooks] equivalent of hooksFromChainConfig().
|
// hooksFromRules is the [RulesHooks] equivalent of hooksFromChainConfig().
|
||||||
|
|
|
||||||
|
|
@ -189,20 +189,38 @@ func TestModificationOfZeroExtras(t *testing.T) {
|
||||||
// The test of shallow copying is now guaranteed to fail.
|
// The test of shallow copying is now guaranteed to fail.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t.Run("shallow copy", func(t *testing.T) {
|
t.Run("copy", func(t *testing.T) {
|
||||||
|
const (
|
||||||
|
// Arbitrary test values.
|
||||||
|
seqUp = 123456789
|
||||||
|
seqDown = 987654321
|
||||||
|
)
|
||||||
|
|
||||||
ccCopy := *config
|
ccCopy := *config
|
||||||
|
t.Run("ChainConfig", func(t *testing.T) {
|
||||||
|
assert.Equal(t, extras.FromChainConfig(&ccCopy), ccReplace, "extras copied")
|
||||||
|
|
||||||
|
extras.PointerFromChainConfig(&ccCopy).X = seqUp
|
||||||
|
assertChainConfigExtra(t, ccExtra{X: seqUp}, "original changed via copied.PointerFromChainConfig because copy only shallow")
|
||||||
|
|
||||||
|
ccReplace = ccExtra{X: seqDown}
|
||||||
|
extras.SetOnChainConfig(&ccCopy, ccReplace)
|
||||||
|
assert.Equal(t, extras.FromChainConfig(&ccCopy), ccReplace, "SetOnChainConfig effect")
|
||||||
|
assertChainConfigExtra(t, ccExtra{X: seqUp}, "original unchanged after copied.SetOnChainConfig")
|
||||||
|
})
|
||||||
|
|
||||||
rCopy := *rules
|
rCopy := *rules
|
||||||
|
t.Run("Rules", func(t *testing.T) {
|
||||||
|
assert.Equal(t, extras.FromRules(&rCopy), rulesReplace, "extras copied")
|
||||||
|
|
||||||
assert.Equal(t, extras.FromChainConfig(&ccCopy), ccReplace, "ChainConfig extras copied")
|
extras.PointerFromRules(&rCopy).X = seqUp
|
||||||
assert.Equal(t, extras.FromRules(&rCopy), rulesReplace, "Rules extras copied")
|
assertRulesExtra(t, rulesExtra{X: seqUp}, "original changed via copied.PointerFromRuels because copy only shallow")
|
||||||
|
|
||||||
const seqUp = 123456789
|
rulesReplace = rulesExtra{X: seqDown}
|
||||||
extras.PointerFromChainConfig(&ccCopy).X = seqUp
|
extras.SetOnRules(&rCopy, rulesReplace)
|
||||||
assertChainConfigExtra(t, ccExtra{X: seqUp}, "original changed because copy only shallow")
|
assert.Equal(t, extras.FromRules(&rCopy), rulesReplace, "SetOnRules effect")
|
||||||
|
assertRulesExtra(t, rulesExtra{X: seqUp}, "original unchanged after copied.SetOnRules")
|
||||||
const seqDown = 987654321
|
})
|
||||||
extras.PointerFromRules(&rCopy).X = seqDown
|
|
||||||
assertRulesExtra(t, rulesExtra{X: seqDown}, "original changed because copy only shallow")
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue