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

Feat: transition of contract size limit #1376

Merged
merged 10 commits into from
Apr 12, 2022
19 changes: 19 additions & 0 deletions params/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
)

// Genesis hashes to enforce below configs on.
Expand Down Expand Up @@ -430,6 +431,7 @@ type Transition struct {
EpochLength uint64 `json:"epochlength,omitempty"` // Number of blocks that should pass before pending validator votes are reset
BlockPeriodSeconds uint64 `json:"blockperiodseconds,omitempty"` // Minimum time between two consecutive IBFT or QBFT blocks’ timestamps in seconds
RequestTimeoutSeconds uint64 `json:"requesttimeoutseconds,omitempty"` // Minimum request timeout for each IBFT or QBFT round in milliseconds
ContractSizeLimit uint64 `json:"contractsizelimit,omitempty"` // Maximum smart contract code size
}

// String implements the fmt.Stringer interface.
Expand Down Expand Up @@ -565,6 +567,7 @@ 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
Expand All @@ -580,6 +583,13 @@ func (c *ChainConfig) GetMaxCodeSize(num *big.Int) int {
maxCodeSize = int(c.MaxCodeSize) * 1024
}
}
if len(c.Transitions) > 0 {
for i := 0; i < len(c.Transitions) && c.Transitions[i].Block.Cmp(num) <= 0; i++ {
if c.Transitions[i].ContractSizeLimit != 0 {
maxCodeSize = int(c.Transitions[i].ContractSizeLimit) * 1024
}
}
}
return maxCodeSize
}

Expand Down Expand Up @@ -623,6 +633,9 @@ func (c *ChainConfig) CheckTransitionsData() error {
if c.Istanbul != nil && c.Istanbul.TestQBFTBlock != nil && (transition.Algorithm == IBFT || transition.Algorithm == QBFT) {
return ErrTestQBFTBlockAndTransitions
}
if len(c.MaxCodeSizeConfig) > 0 && transition.ContractSizeLimit != 0 {
return ErrMaxCodeSizeConfigAndTransitions
}
if transition.Algorithm == QBFT {
isQBFT = true
}
Expand All @@ -635,6 +648,9 @@ func (c *ChainConfig) CheckTransitionsData() error {
if transition.Algorithm == IBFT && isQBFT {
return ErrTransition
}
if transition.ContractSizeLimit != 0 && (transition.ContractSizeLimit < 24 || transition.ContractSizeLimit > 128) {
return ErrContractSizeLimit
}
prevBlock = transition.Block
}
return nil
Expand Down Expand Up @@ -754,6 +770,9 @@ func isTransitionsConfigCompatible(c1, c2 *ChainConfig, head *big.Int) (error, *
if isSameBlock || c1.Transitions[i].EpochLength != c2.Transitions[i].EpochLength {
return ErrTransitionIncompatible("EpochLength"), head, head
}
if isSameBlock || c1.Transitions[i].ContractSizeLimit != c2.Transitions[i].ContractSizeLimit {
return ErrTransitionIncompatible("ContractSizeLimit"), head, head
}
}

return nil, big.NewInt(0), big.NewInt(0)
Expand Down
85 changes: 80 additions & 5 deletions params/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -328,10 +328,10 @@ func TestCheckTransitionsData(t *testing.T) {
wantErr error
}
var ibftTransitionsConfig, qbftTransitionsConfig, invalidTransition, invalidBlockOrder []Transition
tranI0 := Transition{big.NewInt(0), IBFT, 30000, 5, 10}
tranQ5 := Transition{big.NewInt(5), QBFT, 30000, 5, 10}
tranI10 := Transition{big.NewInt(10), IBFT, 30000, 5, 10}
tranQ8 := Transition{big.NewInt(8), QBFT, 30000, 5, 10}
tranI0 := Transition{big.NewInt(0), IBFT, 30000, 5, 10, 50}
tranQ5 := Transition{big.NewInt(5), QBFT, 30000, 5, 10, 50}
tranI10 := Transition{big.NewInt(10), IBFT, 30000, 5, 10, 50}
tranQ8 := Transition{big.NewInt(8), QBFT, 30000, 5, 10, 50}

ibftTransitionsConfig = append(ibftTransitionsConfig, tranI0, tranI10)
qbftTransitionsConfig = append(qbftTransitionsConfig, tranQ5, tranQ8)
Expand Down Expand Up @@ -391,7 +391,7 @@ func TestCheckTransitionsData(t *testing.T) {
wantErr: ErrBlockOrder,
},
{
stored: &ChainConfig{Transitions: []Transition{{nil, IBFT, 30000, 5, 10}}},
stored: &ChainConfig{Transitions: []Transition{{nil, IBFT, 30000, 5, 10, 50}}},
wantErr: ErrBlockNumberMissing,
},
{
Expand All @@ -402,6 +402,26 @@ func TestCheckTransitionsData(t *testing.T) {
stored: &ChainConfig{Transitions: []Transition{{Block: big.NewInt(0), Algorithm: ""}}},
wantErr: nil,
},
{
stored: &ChainConfig{MaxCodeSizeConfig: []MaxCodeConfigStruct{{big.NewInt(10), 24}}, Transitions: []Transition{{Block: big.NewInt(0), ContractSizeLimit: 50}}},
wantErr: ErrMaxCodeSizeConfigAndTransitions,
},
{
stored: &ChainConfig{Transitions: []Transition{{Block: big.NewInt(0), ContractSizeLimit: 23}}},
wantErr: ErrContractSizeLimit,
},
{
stored: &ChainConfig{Transitions: []Transition{{Block: big.NewInt(0), ContractSizeLimit: 129}}},
wantErr: ErrContractSizeLimit,
},
{
stored: &ChainConfig{Transitions: []Transition{{Block: big.NewInt(0), ContractSizeLimit: 50}}},
wantErr: nil,
},
{
stored: &ChainConfig{Transitions: []Transition{{Block: big.NewInt(0)}}},
wantErr: nil,
},
}

for _, test := range tests {
Expand All @@ -411,3 +431,58 @@ func TestCheckTransitionsData(t *testing.T) {
}
}
}

func TestGetMaxCodeSize(t *testing.T) {
type test struct {
config *ChainConfig
blockNumber int64
maxCode int
}
config1, config2, config3 := *TestChainConfig, *TestChainConfig, *TestChainConfig
config1.MaxCodeSizeConfig = []MaxCodeConfigStruct{
{big.NewInt(2), 28},
{big.NewInt(4), 32},
}
config1.MaxCodeSize = 34
config2.MaxCodeSize = 36
config2.MaxCodeSizeChangeBlock = big.NewInt(2)
config3.MaxCodeSize = 0
config3.Transitions = []Transition{
{Block: big.NewInt(2), ContractSizeLimit: 50},
{Block: big.NewInt(4), ContractSizeLimit: 54},
}
maxCodeDefault := 32 * 1024
tests := []test{
{MainnetChainConfig, 0, MaxCodeSize},
{RopstenChainConfig, 0, MaxCodeSize},
{RinkebyChainConfig, 0, MaxCodeSize},
{GoerliChainConfig, 0, MaxCodeSize},
{YoloV3ChainConfig, 0, MaxCodeSize},
{AllEthashProtocolChanges, 0, 35 * 1024},
{AllCliqueProtocolChanges, 0, maxCodeDefault},
{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},
{&config3, 0, MaxCodeSize},
{&config3, 1, MaxCodeSize},
{&config3, 2, 50 * 1024},
{&config3, 3, 50 * 1024},
{&config3, 4, 54 * 1024},
{&config3, 8, 54 * 1024},
}
for _, test := range tests {
maxCodeSize := test.config.GetMaxCodeSize(big.NewInt(test.blockNumber))
if !reflect.DeepEqual(maxCodeSize, test.maxCode) {
t.Errorf("error mismatch:\nexpected: %v\nreceived: %v\n", test.maxCode, maxCodeSize)
}
}
}
12 changes: 7 additions & 5 deletions params/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import (
)

var (
ErrTransitionAlgorithm = errors.New("transition algorithm is invalid, should be either `ibft` or `qbft`")
ErrBlockNumberMissing = errors.New("block number not given in transitions data")
ErrBlockOrder = errors.New("block order should be ascending")
ErrTransition = errors.New("can't transition from qbft to ibft")
ErrTestQBFTBlockAndTransitions = errors.New("can't use transition algorithm and testQBFTBlock at the same time")
ErrTransitionAlgorithm = errors.New("transition algorithm is invalid, should be either `ibft` or `qbft`")
ErrBlockNumberMissing = errors.New("block number not given in transitions data")
ErrBlockOrder = errors.New("block order should be ascending")
ErrTransition = errors.New("can't transition from qbft to ibft")
ErrTestQBFTBlockAndTransitions = errors.New("can't use transition algorithm and testQBFTBlock at the same time")
ErrMaxCodeSizeConfigAndTransitions = errors.New("can't use transition ContractSizeLimit and MaxCodeSizeConfig at the same time")
ErrContractSizeLimit = errors.New("transition contract code size must be between 24 and 128")
)

func ErrTransitionIncompatible(field string) error {
Expand Down