forked from cerc-io/plugeth
core, vm, common: define constantinople fork + shift (#16045)
* core, vm, common: define constantinople fork, start implementation of shift instructions * vm: more testcases * vm: add tests for intpool erroneous intpool handling * core, vm, common: fix constantinople review concerns * vm: add string<->op definitions for new opcodes
This commit is contained in:
parent
ae9f97221a
commit
44d40ffce1
@ -631,6 +631,7 @@ func deployDashboard(client *sshClient, network string, conf *config, config *da
|
|||||||
"Tangerine": conf.Genesis.Config.EIP150Block,
|
"Tangerine": conf.Genesis.Config.EIP150Block,
|
||||||
"Spurious": conf.Genesis.Config.EIP155Block,
|
"Spurious": conf.Genesis.Config.EIP155Block,
|
||||||
"Byzantium": conf.Genesis.Config.ByzantiumBlock,
|
"Byzantium": conf.Genesis.Config.ByzantiumBlock,
|
||||||
|
"Constantinople": conf.Genesis.Config.ConstantinopleBlock,
|
||||||
})
|
})
|
||||||
files[filepath.Join(workdir, "index.html")] = indexfile.Bytes()
|
files[filepath.Join(workdir, "index.html")] = indexfile.Bytes()
|
||||||
|
|
||||||
|
@ -25,6 +25,6 @@ var (
|
|||||||
Big3 = big.NewInt(3)
|
Big3 = big.NewInt(3)
|
||||||
Big0 = big.NewInt(0)
|
Big0 = big.NewInt(0)
|
||||||
Big32 = big.NewInt(32)
|
Big32 = big.NewInt(32)
|
||||||
Big256 = big.NewInt(0xff)
|
Big256 = big.NewInt(256)
|
||||||
Big257 = big.NewInt(257)
|
Big257 = big.NewInt(257)
|
||||||
)
|
)
|
||||||
|
@ -302,6 +302,66 @@ func opMulmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *S
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// opSHL implements Shift Left
|
||||||
|
// The SHL instruction (shift left) pops 2 values from the stack, first arg1 and then arg2,
|
||||||
|
// and pushes on the stack arg2 shifted to the left by arg1 number of bits.
|
||||||
|
func opSHL(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||||
|
// Note, second operand is left in the stack; accumulate result into it, and no need to push it afterwards
|
||||||
|
shift, value := math.U256(stack.pop()), math.U256(stack.peek())
|
||||||
|
defer evm.interpreter.intPool.put(shift) // First operand back into the pool
|
||||||
|
|
||||||
|
if shift.Cmp(common.Big256) >= 0 {
|
||||||
|
value.SetUint64(0)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
n := uint(shift.Uint64())
|
||||||
|
math.U256(value.Lsh(value, n))
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// opSHR implements Logical Shift Right
|
||||||
|
// The SHR instruction (logical shift right) pops 2 values from the stack, first arg1 and then arg2,
|
||||||
|
// and pushes on the stack arg2 shifted to the right by arg1 number of bits with zero fill.
|
||||||
|
func opSHR(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||||
|
// Note, second operand is left in the stack; accumulate result into it, and no need to push it afterwards
|
||||||
|
shift, value := math.U256(stack.pop()), math.U256(stack.peek())
|
||||||
|
defer evm.interpreter.intPool.put(shift) // First operand back into the pool
|
||||||
|
|
||||||
|
if shift.Cmp(common.Big256) >= 0 {
|
||||||
|
value.SetUint64(0)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
n := uint(shift.Uint64())
|
||||||
|
math.U256(value.Rsh(value, n))
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// opSAR implements Arithmetic Shift Right
|
||||||
|
// The SAR instruction (arithmetic shift right) pops 2 values from the stack, first arg1 and then arg2,
|
||||||
|
// and pushes on the stack arg2 shifted to the right by arg1 number of bits with sign extension.
|
||||||
|
func opSAR(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||||
|
// Note, S256 returns (potentially) a new bigint, so we're popping, not peeking this one
|
||||||
|
shift, value := math.U256(stack.pop()), math.S256(stack.pop())
|
||||||
|
defer evm.interpreter.intPool.put(shift) // First operand back into the pool
|
||||||
|
|
||||||
|
if shift.Cmp(common.Big256) >= 0 {
|
||||||
|
if value.Sign() > 0 {
|
||||||
|
value.SetUint64(0)
|
||||||
|
} else {
|
||||||
|
value.SetInt64(-1)
|
||||||
|
}
|
||||||
|
stack.push(math.U256(value))
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
n := uint(shift.Uint64())
|
||||||
|
value.Rsh(value, n)
|
||||||
|
stack.push(math.U256(value))
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
func opSha3(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
func opSha3(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||||
offset, size := stack.pop(), stack.pop()
|
offset, size := stack.pop(), stack.pop()
|
||||||
data := memory.Get(offset.Int64(), size.Int64())
|
data := memory.Get(offset.Int64(), size.Int64())
|
||||||
|
@ -24,6 +24,48 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type twoOperandTest struct {
|
||||||
|
x string
|
||||||
|
y string
|
||||||
|
expected string
|
||||||
|
}
|
||||||
|
|
||||||
|
func testTwoOperandOp(t *testing.T, tests []twoOperandTest, opFn func(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error)) {
|
||||||
|
var (
|
||||||
|
env = NewEVM(Context{}, nil, params.TestChainConfig, Config{EnableJit: false, ForceJit: false})
|
||||||
|
stack = newstack()
|
||||||
|
pc = uint64(0)
|
||||||
|
)
|
||||||
|
for i, test := range tests {
|
||||||
|
x := new(big.Int).SetBytes(common.Hex2Bytes(test.x))
|
||||||
|
shift := new(big.Int).SetBytes(common.Hex2Bytes(test.y))
|
||||||
|
expected := new(big.Int).SetBytes(common.Hex2Bytes(test.expected))
|
||||||
|
stack.push(x)
|
||||||
|
stack.push(shift)
|
||||||
|
opFn(&pc, env, nil, nil, stack)
|
||||||
|
actual := stack.pop()
|
||||||
|
if actual.Cmp(expected) != 0 {
|
||||||
|
t.Errorf("Testcase %d, expected %v, got %v", i, expected, actual)
|
||||||
|
}
|
||||||
|
// Check pool usage
|
||||||
|
// 1.pool is not allowed to contain anything on the stack
|
||||||
|
// 2.pool is not allowed to contain the same pointers twice
|
||||||
|
if env.interpreter.intPool.pool.len() > 0 {
|
||||||
|
|
||||||
|
poolvals := make(map[*big.Int]struct{})
|
||||||
|
poolvals[actual] = struct{}{}
|
||||||
|
|
||||||
|
for env.interpreter.intPool.pool.len() > 0 {
|
||||||
|
key := env.interpreter.intPool.get()
|
||||||
|
if _, exist := poolvals[key]; exist {
|
||||||
|
t.Errorf("Testcase %d, pool contains double-entry", i)
|
||||||
|
}
|
||||||
|
poolvals[key] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestByteOp(t *testing.T) {
|
func TestByteOp(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
env = NewEVM(Context{}, nil, params.TestChainConfig, Config{EnableJit: false, ForceJit: false})
|
env = NewEVM(Context{}, nil, params.TestChainConfig, Config{EnableJit: false, ForceJit: false})
|
||||||
@ -57,6 +99,98 @@ func TestByteOp(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSHL(t *testing.T) {
|
||||||
|
// Testcases from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-145.md#shl-shift-left
|
||||||
|
tests := []twoOperandTest{
|
||||||
|
{"0000000000000000000000000000000000000000000000000000000000000001", "00", "0000000000000000000000000000000000000000000000000000000000000001"},
|
||||||
|
{"0000000000000000000000000000000000000000000000000000000000000001", "01", "0000000000000000000000000000000000000000000000000000000000000002"},
|
||||||
|
{"0000000000000000000000000000000000000000000000000000000000000001", "ff", "8000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
{"0000000000000000000000000000000000000000000000000000000000000001", "0100", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
{"0000000000000000000000000000000000000000000000000000000000000001", "0101", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "00", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
|
||||||
|
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "01", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},
|
||||||
|
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ff", "8000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0100", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
{"0000000000000000000000000000000000000000000000000000000000000000", "01", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "01", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},
|
||||||
|
}
|
||||||
|
testTwoOperandOp(t, tests, opSHL)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSHR(t *testing.T) {
|
||||||
|
// Testcases from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-145.md#shr-logical-shift-right
|
||||||
|
tests := []twoOperandTest{
|
||||||
|
{"0000000000000000000000000000000000000000000000000000000000000001", "00", "0000000000000000000000000000000000000000000000000000000000000001"},
|
||||||
|
{"0000000000000000000000000000000000000000000000000000000000000001", "01", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
{"8000000000000000000000000000000000000000000000000000000000000000", "01", "4000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
{"8000000000000000000000000000000000000000000000000000000000000000", "ff", "0000000000000000000000000000000000000000000000000000000000000001"},
|
||||||
|
{"8000000000000000000000000000000000000000000000000000000000000000", "0100", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
{"8000000000000000000000000000000000000000000000000000000000000000", "0101", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "00", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
|
||||||
|
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "01", "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
|
||||||
|
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ff", "0000000000000000000000000000000000000000000000000000000000000001"},
|
||||||
|
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0100", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
{"0000000000000000000000000000000000000000000000000000000000000000", "01", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
}
|
||||||
|
testTwoOperandOp(t, tests, opSHR)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSAR(t *testing.T) {
|
||||||
|
// Testcases from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-145.md#sar-arithmetic-shift-right
|
||||||
|
tests := []twoOperandTest{
|
||||||
|
{"0000000000000000000000000000000000000000000000000000000000000001", "00", "0000000000000000000000000000000000000000000000000000000000000001"},
|
||||||
|
{"0000000000000000000000000000000000000000000000000000000000000001", "01", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
{"8000000000000000000000000000000000000000000000000000000000000000", "01", "c000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
{"8000000000000000000000000000000000000000000000000000000000000000", "ff", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
|
||||||
|
{"8000000000000000000000000000000000000000000000000000000000000000", "0100", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
|
||||||
|
{"8000000000000000000000000000000000000000000000000000000000000000", "0101", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
|
||||||
|
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "00", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
|
||||||
|
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "01", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
|
||||||
|
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ff", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
|
||||||
|
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0100", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
|
||||||
|
{"0000000000000000000000000000000000000000000000000000000000000000", "01", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
{"4000000000000000000000000000000000000000000000000000000000000000", "fe", "0000000000000000000000000000000000000000000000000000000000000001"},
|
||||||
|
{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "f8", "000000000000000000000000000000000000000000000000000000000000007f"},
|
||||||
|
{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "fe", "0000000000000000000000000000000000000000000000000000000000000001"},
|
||||||
|
{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ff", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0100", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
}
|
||||||
|
|
||||||
|
testTwoOperandOp(t, tests, opSAR)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSGT(t *testing.T) {
|
||||||
|
tests := []twoOperandTest{
|
||||||
|
{"0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
{"0000000000000000000000000000000000000000000000000000000000000001", "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0000000000000000000000000000000000000000000000000000000000000001"},
|
||||||
|
{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000001"},
|
||||||
|
{"0000000000000000000000000000000000000000000000000000000000000001", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
{"8000000000000000000000000000000000000000000000000000000000000001", "8000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
{"8000000000000000000000000000000000000000000000000000000000000001", "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0000000000000000000000000000000000000000000000000000000000000001"},
|
||||||
|
{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "8000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
}
|
||||||
|
testTwoOperandOp(t, tests, opSgt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSLT(t *testing.T) {
|
||||||
|
tests := []twoOperandTest{
|
||||||
|
{"0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
{"0000000000000000000000000000000000000000000000000000000000000001", "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000001"},
|
||||||
|
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
{"0000000000000000000000000000000000000000000000000000000000000001", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0000000000000000000000000000000000000000000000000000000000000001"},
|
||||||
|
{"8000000000000000000000000000000000000000000000000000000000000001", "8000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
{"8000000000000000000000000000000000000000000000000000000000000001", "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "8000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000001"},
|
||||||
|
}
|
||||||
|
testTwoOperandOp(t, tests, opSlt)
|
||||||
|
}
|
||||||
|
|
||||||
func opBenchmark(bench *testing.B, op func(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error), args ...string) {
|
func opBenchmark(bench *testing.B, op func(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error), args ...string) {
|
||||||
var (
|
var (
|
||||||
env = NewEVM(Context{}, nil, params.TestChainConfig, Config{EnableJit: false, ForceJit: false})
|
env = NewEVM(Context{}, nil, params.TestChainConfig, Config{EnableJit: false, ForceJit: false})
|
||||||
@ -259,3 +393,22 @@ func BenchmarkOpMulmod(b *testing.B) {
|
|||||||
|
|
||||||
opBenchmark(b, opMulmod, x, y, z)
|
opBenchmark(b, opMulmod, x, y, z)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkOpSHL(b *testing.B) {
|
||||||
|
x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
|
||||||
|
y := "ff"
|
||||||
|
|
||||||
|
opBenchmark(b, opSHL, x, y)
|
||||||
|
}
|
||||||
|
func BenchmarkOpSHR(b *testing.B) {
|
||||||
|
x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
|
||||||
|
y := "ff"
|
||||||
|
|
||||||
|
opBenchmark(b, opSHR, x, y)
|
||||||
|
}
|
||||||
|
func BenchmarkOpSAR(b *testing.B) {
|
||||||
|
x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
|
||||||
|
y := "ff"
|
||||||
|
|
||||||
|
opBenchmark(b, opSAR, x, y)
|
||||||
|
}
|
||||||
|
@ -68,6 +68,8 @@ func NewInterpreter(evm *EVM, cfg Config) *Interpreter {
|
|||||||
// we'll set the default jump table.
|
// we'll set the default jump table.
|
||||||
if !cfg.JumpTable[STOP].valid {
|
if !cfg.JumpTable[STOP].valid {
|
||||||
switch {
|
switch {
|
||||||
|
case evm.ChainConfig().IsConstantinople(evm.BlockNumber):
|
||||||
|
cfg.JumpTable = constantinopleInstructionSet
|
||||||
case evm.ChainConfig().IsByzantium(evm.BlockNumber):
|
case evm.ChainConfig().IsByzantium(evm.BlockNumber):
|
||||||
cfg.JumpTable = byzantiumInstructionSet
|
cfg.JumpTable = byzantiumInstructionSet
|
||||||
case evm.ChainConfig().IsHomestead(evm.BlockNumber):
|
case evm.ChainConfig().IsHomestead(evm.BlockNumber):
|
||||||
|
@ -54,8 +54,35 @@ var (
|
|||||||
frontierInstructionSet = NewFrontierInstructionSet()
|
frontierInstructionSet = NewFrontierInstructionSet()
|
||||||
homesteadInstructionSet = NewHomesteadInstructionSet()
|
homesteadInstructionSet = NewHomesteadInstructionSet()
|
||||||
byzantiumInstructionSet = NewByzantiumInstructionSet()
|
byzantiumInstructionSet = NewByzantiumInstructionSet()
|
||||||
|
constantinopleInstructionSet = NewConstantinopleInstructionSet()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// NewConstantinopleInstructionSet returns the frontier, homestead
|
||||||
|
// byzantium and contantinople instructions.
|
||||||
|
func NewConstantinopleInstructionSet() [256]operation {
|
||||||
|
// instructions that can be executed during the byzantium phase.
|
||||||
|
instructionSet := NewByzantiumInstructionSet()
|
||||||
|
instructionSet[SHL] = operation{
|
||||||
|
execute: opSHL,
|
||||||
|
gasCost: constGasFunc(GasFastestStep),
|
||||||
|
validateStack: makeStackFunc(2, 1),
|
||||||
|
valid: true,
|
||||||
|
}
|
||||||
|
instructionSet[SHR] = operation{
|
||||||
|
execute: opSHR,
|
||||||
|
gasCost: constGasFunc(GasFastestStep),
|
||||||
|
validateStack: makeStackFunc(2, 1),
|
||||||
|
valid: true,
|
||||||
|
}
|
||||||
|
instructionSet[SAR] = operation{
|
||||||
|
execute: opSAR,
|
||||||
|
gasCost: constGasFunc(GasFastestStep),
|
||||||
|
validateStack: makeStackFunc(2, 1),
|
||||||
|
valid: true,
|
||||||
|
}
|
||||||
|
return instructionSet
|
||||||
|
}
|
||||||
|
|
||||||
// NewByzantiumInstructionSet returns the frontier, homestead and
|
// NewByzantiumInstructionSet returns the frontier, homestead and
|
||||||
// byzantium instructions.
|
// byzantium instructions.
|
||||||
func NewByzantiumInstructionSet() [256]operation {
|
func NewByzantiumInstructionSet() [256]operation {
|
||||||
|
@ -63,6 +63,9 @@ const (
|
|||||||
XOR
|
XOR
|
||||||
NOT
|
NOT
|
||||||
BYTE
|
BYTE
|
||||||
|
SHL
|
||||||
|
SHR
|
||||||
|
SAR
|
||||||
|
|
||||||
SHA3 = 0x20
|
SHA3 = 0x20
|
||||||
)
|
)
|
||||||
@ -234,6 +237,9 @@ var opCodeToString = map[OpCode]string{
|
|||||||
OR: "OR",
|
OR: "OR",
|
||||||
XOR: "XOR",
|
XOR: "XOR",
|
||||||
BYTE: "BYTE",
|
BYTE: "BYTE",
|
||||||
|
SHL: "SHL",
|
||||||
|
SHR: "SHR",
|
||||||
|
SAR: "SAR",
|
||||||
ADDMOD: "ADDMOD",
|
ADDMOD: "ADDMOD",
|
||||||
MULMOD: "MULMOD",
|
MULMOD: "MULMOD",
|
||||||
|
|
||||||
@ -400,6 +406,9 @@ var stringToOp = map[string]OpCode{
|
|||||||
"OR": OR,
|
"OR": OR,
|
||||||
"XOR": XOR,
|
"XOR": XOR,
|
||||||
"BYTE": BYTE,
|
"BYTE": BYTE,
|
||||||
|
"SHL": SHL,
|
||||||
|
"SHR": SHR,
|
||||||
|
"SAR": SAR,
|
||||||
"ADDMOD": ADDMOD,
|
"ADDMOD": ADDMOD,
|
||||||
"MULMOD": MULMOD,
|
"MULMOD": MULMOD,
|
||||||
"SHA3": SHA3,
|
"SHA3": SHA3,
|
||||||
|
@ -40,7 +40,7 @@ var (
|
|||||||
EIP155Block: big.NewInt(2675000),
|
EIP155Block: big.NewInt(2675000),
|
||||||
EIP158Block: big.NewInt(2675000),
|
EIP158Block: big.NewInt(2675000),
|
||||||
ByzantiumBlock: big.NewInt(4370000),
|
ByzantiumBlock: big.NewInt(4370000),
|
||||||
|
ConstantinopleBlock: nil,
|
||||||
Ethash: new(EthashConfig),
|
Ethash: new(EthashConfig),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ var (
|
|||||||
EIP155Block: big.NewInt(10),
|
EIP155Block: big.NewInt(10),
|
||||||
EIP158Block: big.NewInt(10),
|
EIP158Block: big.NewInt(10),
|
||||||
ByzantiumBlock: big.NewInt(1700000),
|
ByzantiumBlock: big.NewInt(1700000),
|
||||||
|
ConstantinopleBlock: nil,
|
||||||
Ethash: new(EthashConfig),
|
Ethash: new(EthashConfig),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +70,7 @@ var (
|
|||||||
EIP155Block: big.NewInt(3),
|
EIP155Block: big.NewInt(3),
|
||||||
EIP158Block: big.NewInt(3),
|
EIP158Block: big.NewInt(3),
|
||||||
ByzantiumBlock: big.NewInt(1035301),
|
ByzantiumBlock: big.NewInt(1035301),
|
||||||
|
ConstantinopleBlock: nil,
|
||||||
Clique: &CliqueConfig{
|
Clique: &CliqueConfig{
|
||||||
Period: 15,
|
Period: 15,
|
||||||
Epoch: 30000,
|
Epoch: 30000,
|
||||||
@ -82,16 +82,16 @@ var (
|
|||||||
//
|
//
|
||||||
// This configuration is intentionally not using keyed fields to force anyone
|
// This configuration is intentionally not using keyed fields to force anyone
|
||||||
// adding flags to the config to also have to set these fields.
|
// 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), new(EthashConfig), 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), nil, new(EthashConfig), nil}
|
||||||
|
|
||||||
// AllCliqueProtocolChanges contains every protocol change (EIPs) introduced
|
// AllCliqueProtocolChanges contains every protocol change (EIPs) introduced
|
||||||
// and accepted by the Ethereum core developers into the Clique consensus.
|
// and accepted by the Ethereum core developers into the Clique consensus.
|
||||||
//
|
//
|
||||||
// This configuration is intentionally not using keyed fields to force anyone
|
// This configuration is intentionally not using keyed fields to force anyone
|
||||||
// adding flags to the config to also have to set these fields.
|
// adding flags to the config to also have to set these fields.
|
||||||
AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, &CliqueConfig{Period: 0, Epoch: 30000}}
|
AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}}
|
||||||
|
|
||||||
TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), new(EthashConfig), nil}
|
TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil}
|
||||||
TestRules = TestChainConfig.Rules(new(big.Int))
|
TestRules = TestChainConfig.Rules(new(big.Int))
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -116,6 +116,7 @@ type ChainConfig struct {
|
|||||||
EIP158Block *big.Int `json:"eip158Block,omitempty"` // EIP158 HF block
|
EIP158Block *big.Int `json:"eip158Block,omitempty"` // EIP158 HF block
|
||||||
|
|
||||||
ByzantiumBlock *big.Int `json:"byzantiumBlock,omitempty"` // Byzantium switch block (nil = no fork, 0 = already on byzantium)
|
ByzantiumBlock *big.Int `json:"byzantiumBlock,omitempty"` // Byzantium switch block (nil = no fork, 0 = already on byzantium)
|
||||||
|
ConstantinopleBlock *big.Int `json:"constantinopleBlock,omitempty"` // Constantinople switch block (nil = no fork, 0 = already activated)
|
||||||
|
|
||||||
// Various consensus engines
|
// Various consensus engines
|
||||||
Ethash *EthashConfig `json:"ethash,omitempty"`
|
Ethash *EthashConfig `json:"ethash,omitempty"`
|
||||||
@ -152,7 +153,7 @@ func (c *ChainConfig) String() string {
|
|||||||
default:
|
default:
|
||||||
engine = "unknown"
|
engine = "unknown"
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Engine: %v}",
|
return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Engine: %v}",
|
||||||
c.ChainId,
|
c.ChainId,
|
||||||
c.HomesteadBlock,
|
c.HomesteadBlock,
|
||||||
c.DAOForkBlock,
|
c.DAOForkBlock,
|
||||||
@ -161,6 +162,7 @@ func (c *ChainConfig) String() string {
|
|||||||
c.EIP155Block,
|
c.EIP155Block,
|
||||||
c.EIP158Block,
|
c.EIP158Block,
|
||||||
c.ByzantiumBlock,
|
c.ByzantiumBlock,
|
||||||
|
c.ConstantinopleBlock,
|
||||||
engine,
|
engine,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -191,6 +193,10 @@ func (c *ChainConfig) IsByzantium(num *big.Int) bool {
|
|||||||
return isForked(c.ByzantiumBlock, num)
|
return isForked(c.ByzantiumBlock, num)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ChainConfig) IsConstantinople(num *big.Int) bool {
|
||||||
|
return isForked(c.ConstantinopleBlock, num)
|
||||||
|
}
|
||||||
|
|
||||||
// GasTable returns the gas table corresponding to the current phase (homestead or homestead reprice).
|
// GasTable returns the gas table corresponding to the current phase (homestead or homestead reprice).
|
||||||
//
|
//
|
||||||
// The returned GasTable's fields shouldn't, under any circumstances, be changed.
|
// The returned GasTable's fields shouldn't, under any circumstances, be changed.
|
||||||
@ -251,6 +257,9 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, head *big.Int) *Confi
|
|||||||
if isForkIncompatible(c.ByzantiumBlock, newcfg.ByzantiumBlock, head) {
|
if isForkIncompatible(c.ByzantiumBlock, newcfg.ByzantiumBlock, head) {
|
||||||
return newCompatError("Byzantium fork block", c.ByzantiumBlock, newcfg.ByzantiumBlock)
|
return newCompatError("Byzantium fork block", c.ByzantiumBlock, newcfg.ByzantiumBlock)
|
||||||
}
|
}
|
||||||
|
if isForkIncompatible(c.ConstantinopleBlock, newcfg.ConstantinopleBlock, head) {
|
||||||
|
return newCompatError("Constantinople fork block", c.ConstantinopleBlock, newcfg.ConstantinopleBlock)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user