Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow migration of maxCodeSizeConfig to transitions.contractsizelimit #1623

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
83 changes: 43 additions & 40 deletions params/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,11 +258,11 @@ var (
AllCliqueProtocolChanges = &ChainConfig{big.NewInt(10), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}, nil, nil, nil, nil, false, 32, 32, big.NewInt(0), big.NewInt(0), nil, nil, false, nil, nil}

// Quorum chainID should 10
TestChainConfig = &ChainConfig{big.NewInt(10), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, new(EthashConfig), nil, nil, nil, nil, nil, false, 32, 32, big.NewInt(0), big.NewInt(0), nil, nil, false, nil, nil}
TestChainConfig = &ChainConfig{big.NewInt(10), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, new(EthashConfig), nil, nil, nil, nil, []Transition{{Block: big.NewInt(0), ContractSizeLimit: 32}}, false, 32, 0, big.NewInt(0), big.NewInt(0), nil, nil, false, nil, nil}
TestRules = TestChainConfig.Rules(new(big.Int))

QuorumTestChainConfig = &ChainConfig{big.NewInt(10), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, new(EthashConfig), nil, nil, nil, nil, nil, true, 64, 32, big.NewInt(0), big.NewInt(0), nil, big.NewInt(0), false, nil, nil}
QuorumMPSTestChainConfig = &ChainConfig{big.NewInt(10), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, new(EthashConfig), nil, nil, nil, nil, nil, true, 64, 32, big.NewInt(0), big.NewInt(0), nil, big.NewInt(0), true, nil, nil}
QuorumTestChainConfig = &ChainConfig{big.NewInt(10), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, new(EthashConfig), nil, nil, nil, nil, []Transition{{Block: big.NewInt(0), ContractSizeLimit: 32}}, true, 64, 0, big.NewInt(0), big.NewInt(0), nil, big.NewInt(0), false, nil, nil}
QuorumMPSTestChainConfig = &ChainConfig{big.NewInt(10), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, new(EthashConfig), nil, nil, nil, nil, []Transition{{Block: big.NewInt(0), ContractSizeLimit: 32}}, true, 64, 0, big.NewInt(0), big.NewInt(0), nil, big.NewInt(0), true, nil, nil}
)

// TrustedCheckpoint represents a set of post-processed trie roots (CHT and
Expand Down Expand Up @@ -484,7 +484,7 @@ func (c *ChainConfig) String() string {
default:
engine = "unknown"
}
return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v IsQuorum: %v Constantinople: %v TransactionSizeLimit: %v MaxCodeSize: %v Petersburg: %v Istanbul: %v, Muir Glacier: %v, Berlin: %v Catalyst: %v YOLO v3: %v PrivacyEnhancements: %v PrivacyPrecompile: %v EnableGasPriceBlock: %v Engine: %v}",
return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v IsQuorum: %v Constantinople: %v TransactionSizeLimit: %v MaxCodeSize: %v Petersburg: %v Istanbul: %v, Muir Glacier: %v, Berlin: %v Catalyst: %v YOLO v3: %v PrivacyEnhancements: %v PrivacyPrecompile: %v EnableGasPriceBlock: %v Engine: %v Transitions: %+v}",
c.ChainID,
c.HomesteadBlock,
c.DAOForkBlock,
Expand All @@ -507,6 +507,7 @@ func (c *ChainConfig) String() string {
c.PrivacyPrecompileBlock, //Quorum
c.EnableGasPriceBlock, //Quorum
engine,
c.Transitions,
)
}

Expand Down Expand Up @@ -609,22 +610,8 @@ func (c *ChainConfig) IsQIP714(num *big.Int) bool {
func (c *ChainConfig) GetMaxCodeSize(num *big.Int) int {
maxCodeSize := MaxCodeSize

if len(c.MaxCodeSizeConfig) > 0 {
log.Warn("WARNING: The attribute config.maxCodeSizeConfig is deprecated and will be removed in the future, please use config.transitions.contractsizelimit on genesis file")
for _, data := range c.MaxCodeSizeConfig {
if data.Block.Cmp(num) > 0 {
break
}
maxCodeSize = int(data.Size) * 1024
}
} else if c.MaxCodeSize > 0 {
if c.MaxCodeSizeChangeBlock != nil && c.MaxCodeSizeChangeBlock.Cmp(big.NewInt(0)) >= 0 {
if isForked(c.MaxCodeSizeChangeBlock, num) {
maxCodeSize = int(c.MaxCodeSize) * 1024
}
} else {
maxCodeSize = int(c.MaxCodeSize) * 1024
}
if len(c.MaxCodeSizeConfig) > 0 || (c.MaxCodeSizeChangeBlock != nil && c.MaxCodeSizeChangeBlock.Cmp(big.NewInt(0)) >= 0) {
log.Warn("WARNING: Support for attribute config.maxCodeSizeConfig has been removed, please use config.transitions.contractsizelimit on genesis file")
}

c.GetTransitionValue(num, func(transition Transition) {
Expand Down Expand Up @@ -717,23 +704,25 @@ func (c *ChainConfig) GetMinerMinGasLimit(num *big.Int, defaultValue uint64) uin
// validates the maxCodeSizeConfig data passed in config
func (c *ChainConfig) CheckMaxCodeConfigData() error {
if c.MaxCodeSize != 0 || (c.MaxCodeSizeChangeBlock != nil && c.MaxCodeSizeChangeBlock.Cmp(big.NewInt(0)) >= 0) {
return errors.New("maxCodeSize & maxCodeSizeChangeBlock deprecated. Consider using maxCodeSizeConfig")
return errors.New("maxCodeSize & maxCodeSizeChangeBlock unsupported. Use config.transitions.contractsizelimit")
}
// validate max code size data
// 1. Code size should not be less than 24 and greater than 128
// 2. block entries are in ascending order
prevBlock := big.NewInt(0)
for _, data := range c.MaxCodeSizeConfig {
if data.Size < 24 || data.Size > 128 {
return errors.New("Genesis max code size must be between 24 and 128")
}
if data.Block == nil {
return errors.New("Block number not given in maxCodeSizeConfig data")
}
if data.Block.Cmp(prevBlock) < 0 {
return errors.New("invalid maxCodeSize detail, block order has to be ascending")
for _, data := range c.Transitions {
if data.ContractSizeLimit != 0 {
if data.ContractSizeLimit < 24 || data.ContractSizeLimit > 128 {
return errors.New("Genesis contract size limit must be between 24 and 128")
}
if data.Block == nil {
return errors.New("Block number not given in transitions.contractsizelimit data")
}
if data.Block.Cmp(prevBlock) < 0 {
return errors.New("invalid transitions.contractsizelimit detail, block order has to be ascending")
}
prevBlock = data.Block
}
prevBlock = data.Block
}

return nil
Expand Down Expand Up @@ -787,6 +776,19 @@ func (c *ChainConfig) CheckTransitionsData() error {
return nil
}

// Quorum
//
// utility function to filter and return Transitions that specify contractsizelimit
func getContractSizeLimitTransitions(transitions []Transition) []Transition {
var contractSizeLimitTransitions []Transition
for _, t := range transitions {
if t.ContractSizeLimit != 0 {
contractSizeLimitTransitions = append(contractSizeLimitTransitions, Transition{Block: t.Block, ContractSizeLimit: t.ContractSizeLimit})
}
}
return contractSizeLimitTransitions
}

// Quorum
//
// checks if changes to maxCodeSizeConfig proposed are compatible
Expand All @@ -798,11 +800,12 @@ func isMaxCodeSizeConfigCompatible(c1, c2 *ChainConfig, head *big.Int) (error, *
}

// existing config had maxCodeSizeConfig and new one does not have the same return error
if len(c1.MaxCodeSizeConfig) > 0 && len(c2.MaxCodeSizeConfig) == 0 {
return fmt.Errorf("genesis file missing max code size information"), head, head
c2ContractSizeLimits := getContractSizeLimitTransitions(c2.Transitions)
if len(c1.MaxCodeSizeConfig) > 0 && len(c2ContractSizeLimits) == 0 {
return fmt.Errorf("genesis file missing contract size limit information in transitions"), head, head
}

if len(c2.MaxCodeSizeConfig) > 0 && len(c1.MaxCodeSizeConfig) == 0 {
if len(c2ContractSizeLimits) > 0 && len(c1.MaxCodeSizeConfig) == 0 {
return nil, big.NewInt(0), big.NewInt(0)
}

Expand All @@ -818,7 +821,7 @@ func isMaxCodeSizeConfigCompatible(c1, c2 *ChainConfig, head *big.Int) (error, *
}

c2RecsBelowHead := 0
for _, data := range c2.MaxCodeSizeConfig {
for _, data := range c2ContractSizeLimits {
if data.Block.Cmp(head) <= 0 {
c2RecsBelowHead++
} else {
Expand All @@ -828,14 +831,14 @@ func isMaxCodeSizeConfigCompatible(c1, c2 *ChainConfig, head *big.Int) (error, *

// if the count of past records is not matching return error
if c1RecsBelowHead != c2RecsBelowHead {
return errors.New("maxCodeSizeConfig data incompatible. updating maxCodeSize for past"), head, head
return errors.New("maxCodeSizeConfig data incompatible with transitions.contractsizelimit. attempting to update maxCodeSize for the past"), head, head
}

// validate that each past record is matching exactly. if not return error
for i := 0; i < c1RecsBelowHead; i++ {
if c1.MaxCodeSizeConfig[i].Block.Cmp(c2.MaxCodeSizeConfig[i].Block) != 0 ||
c1.MaxCodeSizeConfig[i].Size != c2.MaxCodeSizeConfig[i].Size {
return errors.New("maxCodeSizeConfig data incompatible. maxCodeSize historical data does not match"), head, head
if c1.MaxCodeSizeConfig[i].Block.Cmp(c2ContractSizeLimits[i].Block) != 0 ||
c1.MaxCodeSizeConfig[i].Size != c2ContractSizeLimits[i].ContractSizeLimit {
return errors.New("maxCodeSizeConfig data incompatible with transitions.contractsizelimit. maxCodeSize historical data does not match"), head, head
}
}

Expand Down Expand Up @@ -994,7 +997,7 @@ func (c *ChainConfig) CheckCompatible(newcfg *ChainConfig, height uint64, isQuor
// at multiple block heights and cannot be handled with in
// checkCompatible

// compare the maxCodeSize data between the old and new config
// compare the maxCodeSize data between the old and new config (config.transitions.contractsizelimit)
err, cBlock, newCfgBlock := isMaxCodeSizeConfigCompatible(c, newcfg, bhead)
if err != nil {
return newCompatError(err.Error(), cBlock, newCfgBlock)
Expand Down
87 changes: 38 additions & 49 deletions params/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,29 +94,35 @@ func TestCheckCompatible(t *testing.T) {
head uint64
wantErr *ConfigCompatError
}
var storedMaxCodeConfig0, storedMaxCodeConfig1, storedMaxCodeConfig2 []MaxCodeConfigStruct
var storedMaxCodeConfig0, storedMaxCodeConfig1 []MaxCodeConfigStruct
defaultRec := MaxCodeConfigStruct{big.NewInt(0), 24}
defaultTRec := Transition{Block: defaultRec.Block, ContractSizeLimit: defaultRec.Size}
rec1 := MaxCodeConfigStruct{big.NewInt(5), 32}
tRec1 := Transition{Block: rec1.Block, ContractSizeLimit: rec1.Size}
rec2 := MaxCodeConfigStruct{big.NewInt(10), 40}
tRec2 := Transition{Block: rec2.Block, ContractSizeLimit: rec2.Size}
rec3 := MaxCodeConfigStruct{big.NewInt(8), 40}
tRec3 := Transition{Block: rec3.Block, ContractSizeLimit: rec3.Size}

storedMaxCodeConfig0 = append(storedMaxCodeConfig0, defaultRec)

storedMaxCodeConfig1 = append(storedMaxCodeConfig1, defaultRec)
storedMaxCodeConfig1 = append(storedMaxCodeConfig1, rec1)
storedMaxCodeConfig1 = append(storedMaxCodeConfig1, rec2)

storedMaxCodeConfig2 = append(storedMaxCodeConfig2, rec1)
storedMaxCodeConfig2 = append(storedMaxCodeConfig2, rec2)
var storedMaxCodeConfig2 []Transition
storedMaxCodeConfig2 = append(storedMaxCodeConfig2, defaultTRec)
storedMaxCodeConfig2 = append(storedMaxCodeConfig2, tRec1)
storedMaxCodeConfig2 = append(storedMaxCodeConfig2, tRec2)

var passedValidMaxConfig0 []MaxCodeConfigStruct
passedValidMaxConfig0 = append(passedValidMaxConfig0, defaultRec)
passedValidMaxConfig0 = append(passedValidMaxConfig0, rec1)
var passedValidMaxConfig0 []Transition
passedValidMaxConfig0 = append(passedValidMaxConfig0, defaultTRec)
passedValidMaxConfig0 = append(passedValidMaxConfig0, tRec1)

var passedValidMaxConfig1 []MaxCodeConfigStruct
passedValidMaxConfig1 = append(passedValidMaxConfig1, defaultRec)
passedValidMaxConfig1 = append(passedValidMaxConfig1, rec1)
passedValidMaxConfig1 = append(passedValidMaxConfig1, rec3)
var passedValidMaxConfig1 []Transition
passedValidMaxConfig1 = append(passedValidMaxConfig1, defaultTRec)
passedValidMaxConfig1 = append(passedValidMaxConfig1, tRec1)
passedValidMaxConfig1 = append(passedValidMaxConfig1, tRec3)

tests := []test{
{stored: AllEthashProtocolChanges, new: AllEthashProtocolChanges, head: 0, wantErr: nil},
Expand Down Expand Up @@ -247,76 +253,59 @@ func TestCheckCompatible(t *testing.T) {
},
{
stored: &ChainConfig{MaxCodeSizeConfig: storedMaxCodeConfig0},
new: &ChainConfig{MaxCodeSizeConfig: nil},
new: &ChainConfig{MaxCodeSizeConfig: storedMaxCodeConfig0},
head: 4,
wantErr: &ConfigCompatError{
What: "genesis file missing max code size information",
What: "genesis file missing contract size limit information in transitions",
StoredConfig: big.NewInt(4),
NewConfig: big.NewInt(4),
RewindTo: 3,
},
},
{
stored: &ChainConfig{MaxCodeSizeConfig: storedMaxCodeConfig0},
new: &ChainConfig{MaxCodeSizeConfig: storedMaxCodeConfig0},
new: &ChainConfig{Transitions: storedMaxCodeConfig2},
head: 4,
wantErr: nil,
},
{
stored: &ChainConfig{MaxCodeSizeConfig: storedMaxCodeConfig0},
new: &ChainConfig{MaxCodeSizeConfig: passedValidMaxConfig0},
new: &ChainConfig{Transitions: passedValidMaxConfig0},
head: 10,
wantErr: &ConfigCompatError{
What: "maxCodeSizeConfig data incompatible. updating maxCodeSize for past",
What: "maxCodeSizeConfig data incompatible with transitions.contractsizelimit. attempting to update maxCodeSize for the past",
StoredConfig: big.NewInt(10),
NewConfig: big.NewInt(10),
RewindTo: 9,
},
},
{
stored: &ChainConfig{MaxCodeSizeConfig: storedMaxCodeConfig0},
new: &ChainConfig{MaxCodeSizeConfig: passedValidMaxConfig0},
new: &ChainConfig{Transitions: passedValidMaxConfig0},
head: 4,
wantErr: nil,
},
{
stored: &ChainConfig{MaxCodeSizeConfig: storedMaxCodeConfig1},
new: &ChainConfig{MaxCodeSizeConfig: storedMaxCodeConfig1},
new: &ChainConfig{Transitions: storedMaxCodeConfig2},
head: 12,
wantErr: nil,
},
{
stored: &ChainConfig{MaxCodeSizeConfig: storedMaxCodeConfig1},
new: &ChainConfig{MaxCodeSizeConfig: passedValidMaxConfig1},
new: &ChainConfig{Transitions: passedValidMaxConfig1},
head: 12,
wantErr: &ConfigCompatError{
What: "maxCodeSizeConfig data incompatible. maxCodeSize historical data does not match",
What: "maxCodeSizeConfig data incompatible with transitions.contractsizelimit. maxCodeSize historical data does not match",
StoredConfig: big.NewInt(12),
NewConfig: big.NewInt(12),
RewindTo: 11,
},
},
{
stored: &ChainConfig{MaxCodeSize: 32},
new: &ChainConfig{MaxCodeSizeConfig: storedMaxCodeConfig2},
head: 8,
wantErr: nil,
},
{
stored: &ChainConfig{MaxCodeSize: 32},
new: &ChainConfig{MaxCodeSizeConfig: storedMaxCodeConfig2},
head: 15,
wantErr: nil,
},
{
stored: &ChainConfig{MaxCodeSize: 32, MaxCodeSizeChangeBlock: big.NewInt(10)},
new: &ChainConfig{MaxCodeSizeConfig: storedMaxCodeConfig1},
head: 15,
wantErr: nil,
},
}

for _, test := range tests {
for i, test := range tests {
t.Logf("Test %d", i)
err := test.stored.CheckCompatible(test.new, test.head, false)
if !reflect.DeepEqual(err, test.wantErr) {
t.Errorf("error mismatch:\nstored: %v\nnew: %v\nhead: %v\nerr: %v\nwant: %v", test.stored, test.new, test.head, err, test.wantErr)
Expand Down Expand Up @@ -462,20 +451,20 @@ func TestGetMaxCodeSize(t *testing.T) {
{RinkebyChainConfig, 0, MaxCodeSize},
{GoerliChainConfig, 0, MaxCodeSize},
{YoloV3ChainConfig, 0, MaxCodeSize},
{AllEthashProtocolChanges, 0, 35 * 1024},
{AllCliqueProtocolChanges, 0, maxCodeDefault},
{AllEthashProtocolChanges, 0, MaxCodeSize},
{AllCliqueProtocolChanges, 0, MaxCodeSize},
{TestChainConfig, 0, maxCodeDefault},
{QuorumTestChainConfig, 0, maxCodeDefault},
{QuorumMPSTestChainConfig, 0, maxCodeDefault},
{&config1, 0, MaxCodeSize},
{&config1, 1, MaxCodeSize},
{&config1, 2, 28 * 1024},
{&config1, 3, 28 * 1024},
{&config1, 4, 32 * 1024},
{&config2, 0, MaxCodeSize},
{&config2, 1, MaxCodeSize},
{&config2, 2, 36 * 1024},
{&config2, 3, 36 * 1024},
{&config1, 0, maxCodeDefault},
{&config1, 1, maxCodeDefault},
{&config1, 2, maxCodeDefault},
{&config1, 3, maxCodeDefault},
{&config1, 4, maxCodeDefault},
{&config2, 0, maxCodeDefault},
{&config2, 1, maxCodeDefault},
{&config2, 2, maxCodeDefault},
{&config2, 3, maxCodeDefault},
{&config3, 0, MaxCodeSize},
{&config3, 1, MaxCodeSize},
{&config3, 2, 50 * 1024},
Expand Down
2 changes: 2 additions & 0 deletions permission/permission_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ func setup() {
Balance: big.NewInt(100000000000000),
},
}
conf := params.AllEthashProtocolChanges
conf.Transitions = []params.Transition{{Block: big.NewInt(0), ContractSizeLimit: 32 * 1024}}
ethConf := &eth.Config{
Genesis: &core.Genesis{Config: params.AllEthashProtocolChanges, GasLimit: 10000000000, Alloc: genesisAlloc},
Miner: miner.Config{Etherbase: guardianAddress},
Expand Down