From 3285a0fda37207ca1b79ac28e2c12c6f5efff89b Mon Sep 17 00:00:00 2001
From: Martin Holst Swende <martin@swende.se>
Date: Sun, 28 May 2017 23:39:33 +0200
Subject: core/vm, common/math: Add fast getByte for bigints, improve opByte

---
 core/vm/instructions.go      | 13 ++++++-------
 core/vm/instructions_test.go | 43 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 49 insertions(+), 7 deletions(-)
 create mode 100644 core/vm/instructions_test.go

(limited to 'core/vm')

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)
+		}
+	}
+}
-- 
cgit v1.2.3