diff options
author | Martin Holst Swende <martin@swende.se> | 2017-05-29 05:39:33 +0800 |
---|---|---|
committer | Martin Holst Swende <martin@swende.se> | 2017-06-05 14:44:11 +0800 |
commit | 3285a0fda37207ca1b79ac28e2c12c6f5efff89b (patch) | |
tree | f17d74593a9ed24dd99bf94a48d5ddeaff2e41c6 /core/vm | |
parent | 6171d01b1195abd7ac75044dcd507d4758d83cde (diff) | |
download | dexon-3285a0fda37207ca1b79ac28e2c12c6f5efff89b.tar.gz dexon-3285a0fda37207ca1b79ac28e2c12c6f5efff89b.tar.zst dexon-3285a0fda37207ca1b79ac28e2c12c6f5efff89b.zip |
core/vm, common/math: Add fast getByte for bigints, improve opByte
Diffstat (limited to 'core/vm')
-rw-r--r-- | core/vm/instructions.go | 13 | ||||
-rw-r--r-- | core/vm/instructions_test.go | 43 |
2 files changed, 49 insertions, 7 deletions
diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 42f1781d8..bcaf18e8a 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -256,15 +256,14 @@ func opXor(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stac } func opByte(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - th, val := stack.pop(), stack.pop() - if th.Cmp(big.NewInt(32)) < 0 { - byte := evm.interpreter.intPool.get().SetInt64(int64(math.PaddedBigBytes(val, 32)[th.Int64()])) - stack.push(byte) + th, val := stack.pop(), stack.peek() + if th.Cmp(common.Big32) < 0 { + b := math.BigEndian32ByteAt(val, int(th.Int64())) + val.SetInt64(int64(b)) } else { - stack.push(new(big.Int)) + val.SetUint64(0) } - - evm.interpreter.intPool.put(th, val) + evm.interpreter.intPool.put(th) return nil, nil } func opAddmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { diff --git a/core/vm/instructions_test.go b/core/vm/instructions_test.go new file mode 100644 index 000000000..50264bc3e --- /dev/null +++ b/core/vm/instructions_test.go @@ -0,0 +1,43 @@ +package vm + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/params" +) + +func TestByteOp(t *testing.T) { + + var ( + env = NewEVM(Context{}, nil, params.TestChainConfig, Config{EnableJit: false, ForceJit: false}) + stack = newstack() + ) + tests := []struct { + v string + th uint64 + expected *big.Int + }{ + {"ABCDEF0908070605040302010000000000000000000000000000000000000000", 0, big.NewInt(0xAB)}, + {"ABCDEF0908070605040302010000000000000000000000000000000000000000", 1, big.NewInt(0xCD)}, + {"00CDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff", 0, big.NewInt(0x00)}, + {"00CDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff", 1, big.NewInt(0xCD)}, + {"0000000000000000000000000000000000000000000000000000000000102030", 31, big.NewInt(0x30)}, + {"0000000000000000000000000000000000000000000000000000000000102030", 30, big.NewInt(0x20)}, + {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 32, big.NewInt(0x0)}, + {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 0xFFFFFFFFFFFFFFFF, big.NewInt(0x0)}, + } + pc := uint64(0) + for _, test := range tests { + val := new(big.Int).SetBytes(common.Hex2Bytes(test.v)) + th := new(big.Int).SetUint64(test.th) + stack.push(val) + stack.push(th) + opByte(&pc, env, nil, nil, stack) + actual := stack.pop() + if actual.Cmp(test.expected) != 0 { + t.Fatalf("Expected [%v] %v:th byte to be %v, was %v.", test.v, test.th, test.expected, actual) + } + } +} |