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

Cleanup Istanbul #856

Merged
merged 2 commits into from May 5, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion consensus/misc/eip1559_test.go
Expand Up @@ -30,7 +30,6 @@ import (
func copyConfig(original *params.ChainConfig) *params.ChainConfig {
return &params.ChainConfig{
ChainID: original.ChainID,
IstanbulBlock: original.IstanbulBlock,
MuirGlacierBlock: original.MuirGlacierBlock,
BerlinBlock: original.BerlinBlock,
LondonBlock: original.LondonBlock,
Expand Down
1 change: 0 additions & 1 deletion core/state_processor_test.go
Expand Up @@ -566,7 +566,6 @@ func TestStateProcessorErrors(t *testing.T) {
var (
config = &params.ChainConfig{
ChainID: big.NewInt(1),
IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0),
Expand Down
8 changes: 2 additions & 6 deletions core/state_transition.go
Expand Up @@ -126,7 +126,7 @@ func (result *ExecutionResult) Revert() []byte {
}

// IntrinsicGas computes the 'intrinsic gas' for a message with the given data.
func IntrinsicGas(data []byte, accessList types.AccessList, isContractCreation bool, isEIP2028 bool) (uint64, error) {
func IntrinsicGas(data []byte, accessList types.AccessList, isContractCreation bool) (uint64, error) {
// Set the starting gas for the raw transaction
var gas uint64
if isContractCreation {
Expand All @@ -145,9 +145,6 @@ func IntrinsicGas(data []byte, accessList types.AccessList, isContractCreation b
}
// Make sure we don't exceed uint64 for all data combinations
nonZeroGas := params.TxDataNonZeroGas
if isEIP2028 {
nonZeroGas = params.TxDataNonZeroGasEIP2028
}
if (math.MaxUint64-gas)/nonZeroGas < nz {
return 0, ErrGasUintOverflow
}
Expand Down Expand Up @@ -304,12 +301,11 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
}
msg := st.msg
sender := vm.AccountRef(msg.From())
istanbul := st.evm.ChainConfig().IsIstanbul(st.evm.Context.BlockNumber)
london := st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber)
contractCreation := msg.To() == nil

// Check clauses 4-5, subtract intrinsic gas if everything is correct
gas, err := IntrinsicGas(st.data, st.msg.AccessList(), contractCreation, istanbul)
gas, err := IntrinsicGas(st.data, st.msg.AccessList(), contractCreation)
if err != nil {
return nil, err
}
Expand Down
8 changes: 3 additions & 5 deletions core/tx_pool.go
Expand Up @@ -233,9 +233,8 @@ type TxPool struct {
signer types.Signer
mu sync.RWMutex

istanbul bool // Fork indicator whether we are in the istanbul stage.
eip2718 bool // Fork indicator whether we are using EIP-2718 type transactions.
eip1559 bool // Fork indicator whether we are using EIP-1559 type transactions.
eip2718 bool // Fork indicator whether we are using EIP-2718 type transactions.
eip1559 bool // Fork indicator whether we are using EIP-1559 type transactions.

currentState *state.StateDB // Current state in the blockchain head
pendingNonces *txNoncer // Pending state tracking virtual nonces
Expand Down Expand Up @@ -633,7 +632,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
return ErrInsufficientFunds
}
// Ensure the transaction has more gas than the basic tx fee.
intrGas, err := IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil, pool.istanbul)
intrGas, err := IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil)
if err != nil {
return err
}
Expand Down Expand Up @@ -1309,7 +1308,6 @@ func (pool *TxPool) reset(oldHead, newHead *types.Header) {

// Update all fork indicator by next pending block number.
next := new(big.Int).Add(newHead.Number(), big.NewInt(1))
pool.istanbul = pool.chainconfig.IsIstanbul(next)
pool.eip2718 = pool.chainconfig.IsBerlin(next)
pool.eip1559 = pool.chainconfig.IsLondon(next)
}
Expand Down
41 changes: 20 additions & 21 deletions core/vm/contracts.go
Expand Up @@ -64,9 +64,9 @@ func InitializePrecompiles() {
PrecompiledContracts[PrecompiledAddresses[common.NodeLocation.Name()][2]] = &ripemd160hash{}
PrecompiledContracts[PrecompiledAddresses[common.NodeLocation.Name()][3]] = &dataCopy{}
PrecompiledContracts[PrecompiledAddresses[common.NodeLocation.Name()][4]] = &bigModExp{eip2565: true}
PrecompiledContracts[PrecompiledAddresses[common.NodeLocation.Name()][5]] = &bn256AddIstanbul{}
PrecompiledContracts[PrecompiledAddresses[common.NodeLocation.Name()][6]] = &bn256ScalarMulIstanbul{}
PrecompiledContracts[PrecompiledAddresses[common.NodeLocation.Name()][7]] = &bn256PairingIstanbul{}
PrecompiledContracts[PrecompiledAddresses[common.NodeLocation.Name()][5]] = &bn256Add{}
PrecompiledContracts[PrecompiledAddresses[common.NodeLocation.Name()][6]] = &bn256ScalarMul{}
PrecompiledContracts[PrecompiledAddresses[common.NodeLocation.Name()][7]] = &bn256Pairing{}
PrecompiledContracts[PrecompiledAddresses[common.NodeLocation.Name()][8]] = &blake2F{}
}

Expand Down Expand Up @@ -462,16 +462,15 @@ func runBn256Add(input []byte) ([]byte, error) {
return res.Marshal(), nil
}

// bn256Add implements a native elliptic curve point addition conforming to
// Istanbul consensus rules.
type bn256AddIstanbul struct{}
// bn256Add implements a native elliptic curve point addition conforming to consensus rules.
type bn256Add struct{}

// RequiredGas returns the gas required to execute the pre-compiled contract.
func (c *bn256AddIstanbul) RequiredGas(input []byte) uint64 {
return params.Bn256AddGasIstanbul
func (c *bn256Add) RequiredGas(input []byte) uint64 {
return params.Bn256AddGas
}

func (c *bn256AddIstanbul) Run(input []byte) ([]byte, error) {
func (c *bn256Add) Run(input []byte) ([]byte, error) {
return runBn256Add(input)
}

Expand All @@ -486,16 +485,16 @@ func runBn256ScalarMul(input []byte) ([]byte, error) {
return res.Marshal(), nil
}

// bn256ScalarMulIstanbul implements a native elliptic curve scalar
// multiplication conforming to Istanbul consensus rules.
type bn256ScalarMulIstanbul struct{}
// bn256ScalarMul implements a native elliptic curve scalar
// multiplication conforming to consensus rules.
type bn256ScalarMul struct{}

// RequiredGas returns the gas required to execute the pre-compiled contract.
func (c *bn256ScalarMulIstanbul) RequiredGas(input []byte) uint64 {
return params.Bn256ScalarMulGasIstanbul
func (c *bn256ScalarMul) RequiredGas(input []byte) uint64 {
return params.Bn256ScalarMulGas
}

func (c *bn256ScalarMulIstanbul) Run(input []byte) ([]byte, error) {
func (c *bn256ScalarMul) Run(input []byte) ([]byte, error) {
return runBn256ScalarMul(input)
}

Expand Down Expand Up @@ -540,16 +539,16 @@ func runBn256Pairing(input []byte) ([]byte, error) {
return false32Byte, nil
}

// bn256PairingIstanbul implements a pairing pre-compile for the bn256 curve
// conforming to Istanbul consensus rules.
type bn256PairingIstanbul struct{}
// bn256Pairing implements a pairing pre-compile for the bn256 curve
// conforming to consensus rules.
type bn256Pairing struct{}

// RequiredGas returns the gas required to execute the pre-compiled contract.
func (c *bn256PairingIstanbul) RequiredGas(input []byte) uint64 {
return params.Bn256PairingBaseGasIstanbul + uint64(len(input)/192)*params.Bn256PairingPerPointGasIstanbul
func (c *bn256Pairing) RequiredGas(input []byte) uint64 {
return params.Bn256PairingBaseGas + uint64(len(input)/192)*params.Bn256PairingPerPointGas
}

func (c *bn256PairingIstanbul) Run(input []byte) ([]byte, error) {
func (c *bn256Pairing) Run(input []byte) ([]byte, error) {
return runBn256Pairing(input)
}

Expand Down
7 changes: 3 additions & 4 deletions core/vm/contracts_test.go
Expand Up @@ -52,13 +52,12 @@ var allPrecompiles = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{4}): &dataCopy{},
common.BytesToAddress([]byte{5}): &bigModExp{eip2565: false},
common.BytesToAddress([]byte{0xf5}): &bigModExp{eip2565: true},
common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
common.BytesToAddress([]byte{6}): &bn256Add{},
common.BytesToAddress([]byte{7}): &bn256ScalarMul{},
common.BytesToAddress([]byte{8}): &bn256Pairing{},
common.BytesToAddress([]byte{9}): &blake2F{},
}

// EIP-152 test vectors
var blake2FMalformedInputTests = []precompiledFailureTest{
{
Input: "",
Expand Down
41 changes: 0 additions & 41 deletions core/vm/eips.go
Expand Up @@ -28,9 +28,6 @@ var activators = map[int]func(*JumpTable){
3529: enable3529,
3198: enable3198,
2929: enable2929,
2200: enable2200,
1884: enable1884,
1344: enable1344,
}

// EnableEIP enables the given EIP on the config.
Expand Down Expand Up @@ -58,26 +55,6 @@ func ActivateableEips() []string {
return nums
}

// enable1884 applies EIP-1884 to the given jump table:
// - Increase cost of BALANCE to 700
// - Increase cost of EXTCODEHASH to 700
// - Increase cost of SLOAD to 800
// - Define SELFBALANCE, with cost GasFastStep (5)
func enable1884(jt *JumpTable) {
// Gas cost changes
jt[SLOAD].constantGas = params.SloadGasEIP1884
jt[BALANCE].constantGas = params.BalanceGasEIP1884
jt[EXTCODEHASH].constantGas = params.ExtcodeHashGasEIP1884

// New opcode
jt[SELFBALANCE] = &operation{
execute: opSelfBalance,
constantGas: GasFastStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
}
}

func opSelfBalance(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
internalAddr, err := scope.Contract.Address().InternalAddress()
if err != nil {
Expand All @@ -88,31 +65,13 @@ func opSelfBalance(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
return nil, nil
}

// enable1344 applies EIP-1344 (ChainID Opcode)
// - Adds an opcode that returns the current chain’s unique identifier
func enable1344(jt *JumpTable) {
// New opcode
jt[CHAINID] = &operation{
execute: opChainID,
constantGas: GasQuickStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
}
}

// opChainID implements CHAINID opcode
func opChainID(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
chainId, _ := uint256.FromBig(interpreter.evm.chainConfig.ChainID)
scope.Stack.push(chainId)
return nil, nil
}

// enable2200 applies EIP-2200 (Rebalance net-metered SSTORE)
func enable2200(jt *JumpTable) {
jt[SLOAD].constantGas = params.SloadGasEIP2200
jt[SSTORE].dynamicGas = gasSStoreEIP2200
}

// enable2929 enables "EIP-2929: Gas cost increases for state access opcodes"
// https://eips.ethereum.org/EIPS/eip-2929
func enable2929(jt *JumpTable) {
Expand Down
48 changes: 11 additions & 37 deletions core/vm/gas_table.go
Expand Up @@ -93,32 +93,6 @@ var (
gasReturnDataCopy = memoryCopierGas(2)
)

func gasSStore(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
var (
y, x = stack.Back(1), stack.Back(0)
internalContractAddr, err = contract.Address().InternalAddress()
)
if err != nil {
return 0, err
}
current := evm.StateDB.GetState(internalContractAddr, x.Bytes32())

// This checks for 3 scenario's and calculates gas accordingly:
//
// 1. From a zero-value address to a non-zero value (NEW VALUE)
// 2. From a non-zero value address to a zero-value address (DELETE)
// 3. From a non-zero to a non-zero (CHANGE)
switch {
case current == (common.Hash{}) && y.Sign() != 0: // 0 => non 0
return params.SstoreSetGas, nil
case current != (common.Hash{}) && y.Sign() == 0: // non 0 => 0
evm.StateDB.AddRefund(params.SstoreRefundGas)
return params.SstoreClearGas, nil
default: // non 0 => non 0 (or 0 => 0)
return params.SstoreResetGas, nil
}
}

// 0. If *gasleft* is less than or equal to 2300, fail the current call.
// 1. If current value equals new value (this is a no-op), SLOAD_GAS is deducted.
// 2. If current value does not equal new value:
Expand All @@ -132,9 +106,9 @@ func gasSStore(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySi
// 2.2.2. If original value equals new value (this storage slot is reset):
// 2.2.2.1. If original value is 0, add SSTORE_SET_GAS - SLOAD_GAS to refund counter.
// 2.2.2.2. Otherwise, add SSTORE_RESET_GAS - SLOAD_GAS gas to refund counter.
func gasSStoreEIP2200(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
func gasSStore(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
// If we fail the minimum gas availability invariant, fail (0)
if contract.Gas <= params.SstoreSentryGasEIP2200 {
if contract.Gas <= params.SstoreSentryGas {
return 0, errors.New("not enough gas for reentrancy sentry")
}
// Gas sentry honoured, do the actual gas calculation based on the stored value
Expand All @@ -149,33 +123,33 @@ func gasSStoreEIP2200(evm *EVM, contract *Contract, stack *Stack, mem *Memory, m
value := common.Hash(y.Bytes32())

if current == value { // noop (1)
return params.SloadGasEIP2200, nil
return params.SloadGas, nil
}
original := evm.StateDB.GetCommittedState(internalContractAddr, x.Bytes32())
if original == current {
if original == (common.Hash{}) { // create slot (2.1.1)
return params.SstoreSetGasEIP2200, nil
return params.SstoreSetGas, nil
}
if value == (common.Hash{}) { // delete slot (2.1.2b)
evm.StateDB.AddRefund(params.SstoreClearsScheduleRefundEIP2200)
evm.StateDB.AddRefund(params.SstoreClearsScheduleRefund)
}
return params.SstoreResetGasEIP2200, nil // write existing slot (2.1.2)
return params.SstoreResetGas, nil // write existing slot (2.1.2)
}
if original != (common.Hash{}) {
if current == (common.Hash{}) { // recreate slot (2.2.1.1)
evm.StateDB.SubRefund(params.SstoreClearsScheduleRefundEIP2200)
evm.StateDB.SubRefund(params.SstoreClearsScheduleRefund)
} else if value == (common.Hash{}) { // delete slot (2.2.1.2)
evm.StateDB.AddRefund(params.SstoreClearsScheduleRefundEIP2200)
evm.StateDB.AddRefund(params.SstoreClearsScheduleRefund)
}
}
if original == value {
if original == (common.Hash{}) { // reset to original inexistent slot (2.2.2.1)
evm.StateDB.AddRefund(params.SstoreSetGasEIP2200 - params.SloadGasEIP2200)
evm.StateDB.AddRefund(params.SstoreSetGas - params.SloadGas)
} else { // reset to original existing slot (2.2.2.2)
evm.StateDB.AddRefund(params.SstoreResetGasEIP2200 - params.SloadGasEIP2200)
evm.StateDB.AddRefund(params.SstoreResetGas - params.SloadGas)
}
}
return params.SloadGasEIP2200, nil // dirty update (2.2)
return params.SloadGas, nil // dirty update (2.2)
}

func makeGasLog(n uint64) gasFunc {
Expand Down
8 changes: 4 additions & 4 deletions core/vm/gas_table_test.go
Expand Up @@ -48,7 +48,7 @@ func TestMemoryGasCost(t *testing.T) {
}
}

var eip2200Tests = []struct {
var gasSStoreTests = []struct {
original byte
gaspool uint64
input string
Expand Down Expand Up @@ -77,8 +77,8 @@ var eip2200Tests = []struct {
{1, 2307, "0x6001600055", 806, 0, nil}, // 1 -> 1 (2301 sentry + 2xPUSH)
}

func TestEIP2200(t *testing.T) {
for i, tt := range eip2200Tests {
func TestgasSStore(t *testing.T) {
for i, tt := range gasSStoreTests {
address := common.BytesToAddress([]byte("contract"))

statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
Expand All @@ -91,7 +91,7 @@ func TestEIP2200(t *testing.T) {
CanTransfer: func(StateDB, common.Address, *big.Int) bool { return true },
Transfer: func(StateDB, common.Address, common.Address, *big.Int) {},
}
vmenv := NewEVM(vmctx, TxContext{}, statedb, params.AllBlake3powProtocolChanges, Config{ExtraEips: []int{2200}})
vmenv := NewEVM(vmctx, TxContext{}, statedb, params.AllBlake3powProtocolChanges, Config{})

_, gas, err := vmenv.Call(AccountRef(common.Address{}), address, nil, tt.gaspool, new(big.Int))
if err != tt.failure {
Expand Down
15 changes: 12 additions & 3 deletions core/vm/jump_table.go
Expand Up @@ -141,9 +141,18 @@ func NewInstructionSet() JumpTable {
writes: true,
returns: true,
}
enable1344(&instructionSet) // ChainID opcode - https://eips.ethereum.org/EIPS/eip-1344
enable1884(&instructionSet) // Reprice reader opcodes - https://eips.ethereum.org/EIPS/eip-1884
enable2200(&instructionSet) // Net metered SSTORE - https://eips.ethereum.org/EIPS/eip-2200
instructionSet[CHAINID] = &operation{
execute: opChainID,
constantGas: GasQuickStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
}
instructionSet[SELFBALANCE] = &operation{
execute: opSelfBalance,
constantGas: GasFastStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
}
enable2929(&instructionSet) // Access lists for trie accesses https://eips.ethereum.org/EIPS/eip-2929
enable3529(&instructionSet) // EIP-3529: Reduction in refunds https://eips.ethereum.org/EIPS/eip-3529
enable3198(&instructionSet) // Base fee opcode https://eips.ethereum.org/EIPS/eip-3198
Expand Down