Skip to content

Commit

Permalink
params: additional ChainConfig hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
darioush committed Sep 11, 2024
1 parent 5d99903 commit 88cb428
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 15 deletions.
2 changes: 2 additions & 0 deletions libevm/hookstest/stub.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ type Stub struct {
PrecompileOverrides map[common.Address]libevm.PrecompiledContract
CanExecuteTransactionFn func(common.Address, *common.Address, libevm.StateReader) error
CanCreateContractFn func(*libevm.AddressContext, libevm.StateReader) error

params.NOOPHooks
}

// Register is a convenience wrapper for registering s as both the
Expand Down
6 changes: 3 additions & 3 deletions params/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ func (c *ChainConfig) Description() string {
if c.VerkleTime != nil {
banner += fmt.Sprintf(" - Verkle: @%-10v\n", *c.VerkleTime)
}
return banner
return banner + c.Hooks().Description()
}

// IsHomestead returns whether num is either equal to the homestead block or greater.
Expand Down Expand Up @@ -671,7 +671,7 @@ func (c *ChainConfig) CheckConfigForkOrder() error {
lastFork = cur
}
}
return nil
return c.Hooks().CheckConfigForkOrder()
}

func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, headNumber *big.Int, headTimestamp uint64) *ConfigCompatError {
Expand Down Expand Up @@ -742,7 +742,7 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, headNumber *big.Int,
if isForkTimestampIncompatible(c.VerkleTime, newcfg.VerkleTime, headTimestamp) {
return newTimestampCompatError("Verkle fork timestamp", c.VerkleTime, newcfg.VerkleTime)
}
return nil
return c.Hooks().CheckCompatible(newcfg, headNumber, headTimestamp)
}

// BaseFeeChangeDenominator bounds the amount the base fee can change between blocks.
Expand Down
40 changes: 29 additions & 11 deletions params/config.libevm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func TestRegisterExtras(t *testing.T) {
}
}

func TestZeroExtrasAndPointers(t *testing.T) {
func TestModificationOfZeroExtras(t *testing.T) {
type (
ccExtra struct {
X int
Expand All @@ -137,39 +137,57 @@ func TestZeroExtrasAndPointers(t *testing.T) {
t.Cleanup(TestOnlyClearRegisteredExtras)
getter := RegisterExtras(Extras[ccExtra, rulesExtra]{})

var (
config ChainConfig
rules Rules
)
config := new(ChainConfig)
rules := new(Rules)
// These assertion helpers are defined before any modifications so that the
// closure is demonstrably over the original zero values.
assertChainConfigExtra := func(t *testing.T, want ccExtra, msg string) {
t.Helper()
assert.Equalf(t, want, getter.FromChainConfig(&config), "%T: "+msg, &config)
assert.Equalf(t, want, getter.FromChainConfig(config), "%T: "+msg, &config)
}
assertRulesExtra := func(t *testing.T, want rulesExtra, msg string) {
t.Helper()
assert.Equalf(t, want, getter.FromRules(&rules), "%T: "+msg, &rules)
assert.Equalf(t, want, getter.FromRules(rules), "%T: "+msg, &rules)
}

assertChainConfigExtra(t, ccExtra{}, "zero value")
assertRulesExtra(t, rulesExtra{}, "zero value")

const answer = 42
getter.PointerFromChainConfig(&config).X = answer
getter.PointerFromChainConfig(config).X = answer
assertChainConfigExtra(t, ccExtra{X: answer}, "after setting via pointer field")

const pi = 314159
getter.PointerFromRules(&rules).X = pi
getter.PointerFromRules(rules).X = pi
assertRulesExtra(t, rulesExtra{X: pi}, "after setting via pointer field")

ccReplace := ccExtra{X: 142857}
*getter.PointerFromChainConfig(&config) = ccReplace
*getter.PointerFromChainConfig(config) = ccReplace
assertChainConfigExtra(t, ccReplace, "after replacement of entire extra via `*pointer = x`")

rulesReplace := rulesExtra{X: 18101986}
*getter.PointerFromRules(&rules) = rulesReplace
*getter.PointerFromRules(rules) = rulesReplace
assertRulesExtra(t, rulesReplace, "after replacement of entire extra via `*pointer = x`")

if t.Failed() {
// The test of shallow copying is now guaranteed to fail.
return
}
t.Run("shallow copy", func(t *testing.T) {
ccCopy := *config
rCopy := *rules

assert.Equal(t, getter.FromChainConfig(&ccCopy), ccReplace, "ChainConfig extras copied")
assert.Equal(t, getter.FromRules(&rCopy), rulesReplace, "Rules extras copied")

const seqUp = 123456789
getter.PointerFromChainConfig(&ccCopy).X = seqUp
assertChainConfigExtra(t, ccExtra{X: seqUp}, "original changed because copy only shallow")

const seqDown = 987654321
getter.PointerFromRules(&rCopy).X = seqDown
assertRulesExtra(t, rulesExtra{X: seqDown}, "original changed because copy only shallow")
})
}

func TestExtrasPanic(t *testing.T) {
Expand Down
5 changes: 5 additions & 0 deletions params/example.libevm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ func constructRulesExtra(c *params.ChainConfig, r *params.Rules, cEx ChainConfig
// the standard [params.ChainConfig] struct.
type ChainConfigExtra struct {
MyForkTime *uint64 `json:"myForkTime"`

// (Optional) If not all hooks are desirable then embedding a [NOOPHooks]
// allows the type to satisfy the [ChainHooks] interface, resulting in
// default Ethereum behaviour.
params.NOOPHooks
}

// RulesExtra can be any struct. It too mirrors a common pattern in
Expand Down
20 changes: 19 additions & 1 deletion params/hooks.libevm.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
package params

import (
"math/big"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/libevm"
)

// ChainConfigHooks are required for all types registered as [Extras] for
// [ChainConfig] payloads.
type ChainConfigHooks interface{}
type ChainConfigHooks interface {
CheckCompatible(newcfg *ChainConfig, headNumber *big.Int, headTimestamp uint64) *ConfigCompatError
CheckConfigForkOrder() error
Description() string
}

// TODO(arr4n): given the choice of whether a hook should be defined on a
// ChainConfig or on the Rules, what are the guiding principles? A ChainConfig
Expand Down Expand Up @@ -66,6 +72,18 @@ var _ interface {
RulesHooks
} = NOOPHooks{}

func (NOOPHooks) CheckCompatible(_ *ChainConfig, _ *big.Int, _ uint64) *ConfigCompatError {
return nil
}

func (NOOPHooks) CheckConfigForkOrder() error {
return nil
}

func (NOOPHooks) Description() string {
return ""
}

// CanExecuteTransaction allows all (otherwise valid) transactions.
func (NOOPHooks) CanExecuteTransaction(_ common.Address, _ *common.Address, _ libevm.StateReader) error {
return nil
Expand Down

0 comments on commit 88cb428

Please sign in to comment.