Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 48 additions & 12 deletions core/vm/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,41 @@ var PrecompiledContractsIstanbul = map[common.Address]PrecompiledContract{
// PrecompiledContractsBerlin contains the default set of pre-compiled Ethereum
// contracts used in the Berlin release.
var PrecompiledContractsBerlin = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{0x01}): &ecrecover{},
common.BytesToAddress([]byte{0x02}): &sha256hash{},
common.BytesToAddress([]byte{0x03}): &ripemd160hash{},
common.BytesToAddress([]byte{0x04}): &dataCopy{},
common.BytesToAddress([]byte{0x05}): &bigModExp{eip2565: true},
common.BytesToAddress([]byte{0x06}): &bn256AddIstanbul{},
common.BytesToAddress([]byte{0x07}): &bn256ScalarMulIstanbul{},
common.BytesToAddress([]byte{0x08}): &bn256PairingIstanbul{},
common.BytesToAddress([]byte{0x09}): &blake2F{},
}

// PrecompiledContractsPrague contains the set of pre-compiled Ethereum
// contracts activated in the Prague fork. These are exported for testing purposes.
var PrecompiledContractsPrague = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{0x01}): &ecrecover{},
common.BytesToAddress([]byte{0x02}): &sha256hash{},
common.BytesToAddress([]byte{0x03}): &ripemd160hash{},
common.BytesToAddress([]byte{0x04}): &dataCopy{},
common.BytesToAddress([]byte{0x05}): &bigModExp{eip2565: true},
common.BytesToAddress([]byte{0x06}): &bn256AddIstanbul{},
common.BytesToAddress([]byte{0x07}): &bn256ScalarMulIstanbul{},
common.BytesToAddress([]byte{0x08}): &bn256PairingIstanbul{},
common.BytesToAddress([]byte{0x09}): &blake2F{},
common.BytesToAddress([]byte{0x0b}): &bls12381G1Add{},
common.BytesToAddress([]byte{0x0c}): &bls12381G1MultiExp{},
common.BytesToAddress([]byte{0x0d}): &bls12381G2Add{},
common.BytesToAddress([]byte{0x0e}): &bls12381G2MultiExp{},
common.BytesToAddress([]byte{0x0f}): &bls12381Pairing{},
common.BytesToAddress([]byte{0x10}): &bls12381MapG1{},
common.BytesToAddress([]byte{0x11}): &bls12381MapG2{},
}

// PrecompiledContractsOsaka contains the set of pre-compiled Ethereum
// contracts activated in the Osaka fork.
var PrecompiledContractsOsaka = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{0x01}): &ecrecover{},
common.BytesToAddress([]byte{0x02}): &sha256hash{},
common.BytesToAddress([]byte{0x03}): &ripemd160hash{},
Expand All @@ -101,20 +136,10 @@ var PrecompiledContractsBerlin = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{0x01, 0x00}): &p256Verify{},
}

Comment on lines 96 to +138

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[imo]
It would be better to include all active PrecompiledContracts from 0x01 for this hardfork, if the name is based on the hardfork.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit dc380bd.

// PrecompiledContractsBLS contains the set of pre-compiled Ethereum
// contracts specified in EIP-2537. These are exported for testing purposes.
var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{0x0b}): &bls12381G1Add{},
common.BytesToAddress([]byte{0x0c}): &bls12381G1MultiExp{},
common.BytesToAddress([]byte{0x0d}): &bls12381G2Add{},
common.BytesToAddress([]byte{0x0e}): &bls12381G2MultiExp{},
common.BytesToAddress([]byte{0x0f}): &bls12381Pairing{},
common.BytesToAddress([]byte{0x10}): &bls12381MapG1{},
common.BytesToAddress([]byte{0x11}): &bls12381MapG2{},
}

var (
PrecompiledAddressesBerlin []common.Address
PrecompiledAddressesPrague []common.Address
PrecompiledAddressesOsaka []common.Address
PrecompiledAddressesIstanbul []common.Address
PrecompiledAddressesByzantium []common.Address
PrecompiledAddressesHomestead []common.Address
Expand All @@ -133,12 +158,22 @@ func init() {
for k := range PrecompiledContractsBerlin {
PrecompiledAddressesBerlin = append(PrecompiledAddressesBerlin, k)
}
for k := range PrecompiledContractsPrague {
PrecompiledAddressesPrague = append(PrecompiledAddressesPrague, k)
}
for k := range PrecompiledContractsOsaka {
PrecompiledAddressesOsaka = append(PrecompiledAddressesOsaka, k)
}
}

// ActivePrecompiles returns the precompiles enabled with the current configuration.
func ActivePrecompiles(rules params.Rules) []common.Address {
var result []common.Address
switch {
case rules.IsOsaka:
result = PrecompiledAddressesOsaka
case rules.IsPrague:
result = PrecompiledAddressesPrague
case rules.IsBerlin:
result = PrecompiledAddressesBerlin
case rules.IsIstanbul:
Expand All @@ -148,6 +183,7 @@ func ActivePrecompiles(rules params.Rules) []common.Address {
default:
result = PrecompiledAddressesHomestead
}
result = append([]common.Address{}, result...)
if rules.IsPrivacyPrecompile {
result = append(result, common.QuorumPrivacyPrecompileContractAddress())
}
Expand Down
4 changes: 4 additions & 0 deletions core/vm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ type (
func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) {
var precompiles map[common.Address]PrecompiledContract
switch {
case evm.chainRules.IsOsaka:
precompiles = PrecompiledContractsOsaka
case evm.chainRules.IsPrague:
precompiles = PrecompiledContractsPrague
case evm.chainRules.IsBerlin:
precompiles = PrecompiledContractsBerlin
case evm.chainRules.IsIstanbul:
Expand Down
79 changes: 79 additions & 0 deletions core/vm/evm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,85 @@ func TestActivePrecompiles(t *testing.T) {
IsPrivacyPrecompile: false,
},
},
want: []common.Address{
common.BytesToAddress([]byte{0x01}),
common.BytesToAddress([]byte{0x02}),
common.BytesToAddress([]byte{0x03}),
common.BytesToAddress([]byte{0x04}),
common.BytesToAddress([]byte{0x05}),
common.BytesToAddress([]byte{0x06}),
common.BytesToAddress([]byte{0x07}),
common.BytesToAddress([]byte{0x08}),
common.BytesToAddress([]byte{0x09}),
},
},
{
name: "berlin-plus-prague",
evm: &EVM{
chainRules: params.Rules{
IsBerlin: true,
IsPrague: true,
IsPrivacyPrecompile: false,
},
},
want: []common.Address{
common.BytesToAddress([]byte{0x01}),
common.BytesToAddress([]byte{0x02}),
common.BytesToAddress([]byte{0x03}),
common.BytesToAddress([]byte{0x04}),
common.BytesToAddress([]byte{0x05}),
common.BytesToAddress([]byte{0x06}),
common.BytesToAddress([]byte{0x07}),
common.BytesToAddress([]byte{0x08}),
common.BytesToAddress([]byte{0x09}),
common.BytesToAddress([]byte{0x0b}),
common.BytesToAddress([]byte{0x0c}),
common.BytesToAddress([]byte{0x0d}),
common.BytesToAddress([]byte{0x0e}),
common.BytesToAddress([]byte{0x0f}),
common.BytesToAddress([]byte{0x10}),
common.BytesToAddress([]byte{0x11}),
},
},
{
name: "berlin-plus-osaka",
evm: &EVM{
chainRules: params.Rules{
IsBerlin: true,
IsOsaka: true,
IsPrivacyPrecompile: false,
},
},
want: []common.Address{
common.BytesToAddress([]byte{0x01}),
common.BytesToAddress([]byte{0x02}),
common.BytesToAddress([]byte{0x03}),
common.BytesToAddress([]byte{0x04}),
common.BytesToAddress([]byte{0x05}),
common.BytesToAddress([]byte{0x06}),
common.BytesToAddress([]byte{0x07}),
common.BytesToAddress([]byte{0x08}),
common.BytesToAddress([]byte{0x09}),
common.BytesToAddress([]byte{0x0b}),
common.BytesToAddress([]byte{0x0c}),
common.BytesToAddress([]byte{0x0d}),
common.BytesToAddress([]byte{0x0e}),
common.BytesToAddress([]byte{0x0f}),
common.BytesToAddress([]byte{0x10}),
common.BytesToAddress([]byte{0x11}),
common.BytesToAddress([]byte{0x01, 0x00}),
},
},
{
name: "berlin-plus-prague-and-osaka",
evm: &EVM{
chainRules: params.Rules{
IsBerlin: true,
IsPrague: true,
IsOsaka: true,
IsPrivacyPrecompile: false,
},
},
want: []common.Address{
common.BytesToAddress([]byte{0x01}),
common.BytesToAddress([]byte{0x02}),
Expand Down
56 changes: 49 additions & 7 deletions params/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,21 +248,21 @@ var (
//
// This configuration is intentionally not using keyed fields to force anyone
// adding flags to the config to also have to set these fields.
AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), 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, 35, big.NewInt(0), big.NewInt(0), nil, nil, false, nil, nil}
AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), 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), big.NewInt(0), big.NewInt(0), nil, nil, nil, new(EthashConfig), nil, nil, nil, nil, nil, false, 32, 35, big.NewInt(0), big.NewInt(0), nil, nil, false, nil, nil}

// AllCliqueProtocolChanges contains every protocol change (EIPs) introduced
// and accepted by the Ethereum core developers into the Clique consensus.
//
// This configuration is intentionally not using keyed fields to force anyone
// adding flags to the config to also have to set these fields.
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}
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), 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), 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}
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, 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, 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}
)

// TrustedCheckpoint represents a set of post-processed trie roots (CHT and
Expand Down Expand Up @@ -344,6 +344,8 @@ type ChainConfig struct {
IstanbulBlock *big.Int `json:"istanbulBlock,omitempty"` // Istanbul switch block (nil = no fork, 0 = already on istanbul)
MuirGlacierBlock *big.Int `json:"muirGlacierBlock,omitempty"` // Eip-2384 (bomb delay) switch block (nil = no fork, 0 = already activated)
BerlinBlock *big.Int `json:"berlinBlock,omitempty"` // Berlin switch block (nil = no fork, 0 = already on berlin)
PragueBlock *big.Int `json:"pragueBlock,omitempty"` // Prague switch block (nil = no fork, 0 = already on prague)
OsakaBlock *big.Int `json:"osakaBlock,omitempty"` // Osaka switch block (nil = no fork, 0 = already on osaka)

YoloV3Block *big.Int `json:"yoloV3Block,omitempty"` // YOLO v3: Gas repricings TODO @holiman add EIP references
EWASMBlock *big.Int `json:"ewasmBlock,omitempty"` // EWASM switch block (nil = no fork, 0 = already activated)
Expand Down Expand Up @@ -486,7 +488,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, Prague: %v, Osaka: %v Catalyst: %v YOLO v3: %v PrivacyEnhancements: %v PrivacyPrecompile: %v EnableGasPriceBlock: %v Engine: %v}",
c.ChainID,
c.HomesteadBlock,
c.DAOForkBlock,
Expand All @@ -503,6 +505,8 @@ func (c *ChainConfig) String() string {
c.IstanbulBlock,
c.MuirGlacierBlock,
c.BerlinBlock,
c.PragueBlock,
c.OsakaBlock,
c.CatalystBlock,
c.YoloV3Block,
c.PrivacyEnhancementsBlock, //Quorum
Expand Down Expand Up @@ -582,6 +586,16 @@ func (c *ChainConfig) IsBerlin(num *big.Int) bool {
return isForked(c.BerlinBlock, num) || isForked(c.YoloV3Block, num)
}

// IsPrague returns whether num is either equal to the Prague fork block or greater.
func (c *ChainConfig) IsPrague(num *big.Int) bool {
return c.IsBerlin(num) && isForked(c.PragueBlock, num)
}

// IsOsaka returns whether num is either equal to the Osaka fork block or greater.
func (c *ChainConfig) IsOsaka(num *big.Int) bool {
return c.IsPrague(num) && isForked(c.OsakaBlock, num)
}

// IsCatalyst returns whether num is either equal to the Merge fork block or greater.
func (c *ChainConfig) IsCatalyst(num *big.Int) bool {
return isForked(c.CatalystBlock, num)
Expand Down Expand Up @@ -1060,6 +1074,26 @@ func (c *ChainConfig) CheckConfigForkOrder() error {
lastFork = cur
}
}
if c.PragueBlock != nil {
if c.BerlinBlock == nil {
return fmt.Errorf("unsupported fork ordering: berlinBlock not enabled, but pragueBlock enabled at %v",
c.PragueBlock)
}
if c.BerlinBlock.Cmp(c.PragueBlock) > 0 {
return fmt.Errorf("unsupported fork ordering: berlinBlock enabled at %v, but pragueBlock enabled at %v",
c.BerlinBlock, c.PragueBlock)
}
}
if c.OsakaBlock != nil {
if c.PragueBlock == nil {
return fmt.Errorf("unsupported fork ordering: pragueBlock not enabled, but osakaBlock enabled at %v",
c.OsakaBlock)
}
if c.PragueBlock.Cmp(c.OsakaBlock) > 0 {
return fmt.Errorf("unsupported fork ordering: pragueBlock enabled at %v, but osakaBlock enabled at %v",
c.PragueBlock, c.OsakaBlock)
}
}
return nil
}

Expand Down Expand Up @@ -1110,6 +1144,12 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, head *big.Int, isQuor
if isForkIncompatible(c.BerlinBlock, newcfg.BerlinBlock, head) {
return newCompatError("Berlin fork block", c.BerlinBlock, newcfg.BerlinBlock)
}
if isForkIncompatible(c.PragueBlock, newcfg.PragueBlock, head) {
return newCompatError("Prague fork block", c.PragueBlock, newcfg.PragueBlock)
}
if isForkIncompatible(c.OsakaBlock, newcfg.OsakaBlock, head) {
return newCompatError("Osaka fork block", c.OsakaBlock, newcfg.OsakaBlock)
}
if isForkIncompatible(c.YoloV3Block, newcfg.YoloV3Block, head) {
return newCompatError("YOLOv3 fork block", c.YoloV3Block, newcfg.YoloV3Block)
}
Expand Down Expand Up @@ -1201,7 +1241,7 @@ type Rules struct {
ChainID *big.Int
IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool
IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool
IsBerlin, IsCatalyst bool
IsBerlin, IsPrague, IsOsaka, IsCatalyst bool
// Quorum
IsPrivacyEnhancementsEnabled bool
IsPrivacyPrecompile bool
Expand All @@ -1225,6 +1265,8 @@ func (c *ChainConfig) Rules(num *big.Int) Rules {
IsPetersburg: c.IsPetersburg(num),
IsIstanbul: c.IsIstanbul(num),
IsBerlin: c.IsBerlin(num),
IsPrague: c.IsPrague(num),
IsOsaka: c.IsOsaka(num),
IsCatalyst: c.IsCatalyst(num),
// Quorum
IsPrivacyEnhancementsEnabled: c.IsPrivacyEnhancementsEnabled(num),
Expand Down
Loading
Loading