diff --git a/core/vm/common.go b/core/vm/common.go
index fbc8866f5..8a9678293 100644
--- a/core/vm/common.go
+++ b/core/vm/common.go
@@ -17,7 +17,7 @@
package vm
import (
- "math/big"
+ "github.com/core-coin/uint256"
"github.com/core-coin/go-core/common"
"github.com/core-coin/go-core/common/math"
@@ -25,7 +25,7 @@ import (
// calcMemSize64 calculates the required memory size, and returns
// the size and whether the result overflowed uint64
-func calcMemSize64(off, l *big.Int) (uint64, bool) {
+func calcMemSize64(off, l *uint256.Int) (uint64, bool) {
if !l.IsUint64() {
return 0, true
}
@@ -35,16 +35,16 @@ func calcMemSize64(off, l *big.Int) (uint64, bool) {
// calcMemSize64WithUint calculates the required memory size, and returns
// the size and whether the result overflowed uint64
// Identical to calcMemSize64, but length is a uint64
-func calcMemSize64WithUint(off *big.Int, length64 uint64) (uint64, bool) {
+func calcMemSize64WithUint(off *uint256.Int, length64 uint64) (uint64, bool) {
// if length is zero, memsize is always zero, regardless of offset
if length64 == 0 {
return 0, false
}
// Check that offset doesn't overflow
- if !off.IsUint64() {
+ offset64, overflow := off.Uint64WithOverflow()
+ if overflow {
return 0, true
}
- offset64 := off.Uint64()
val := offset64 + length64
// if value < either of it's parts, then it overflowed
return val, val < offset64
@@ -64,22 +64,6 @@ func getData(data []byte, start uint64, size uint64) []byte {
return common.RightPadBytes(data[start:end], int(size))
}
-// getDataBig returns a slice from the data based on the start and size and pads
-// up to size with zero's. This function is overflow safe.
-func getDataBig(data []byte, start *big.Int, size *big.Int) []byte {
- dlen := big.NewInt(int64(len(data)))
-
- s := math.BigMin(start, dlen)
- e := math.BigMin(new(big.Int).Add(s, size), dlen)
- return common.RightPadBytes(data[s.Uint64():e.Uint64()], int(size.Uint64()))
-}
-
-// bigUint64 returns the integer casted to a uint64 and returns whether it
-// overflowed in the process.
-func bigUint64(v *big.Int) (uint64, bool) {
- return v.Uint64(), !v.IsUint64()
-}
-
// toWordSize returns the ceiled word size required for memory expansion.
func toWordSize(size uint64) uint64 {
if size > math.MaxUint64-31 {
@@ -88,12 +72,3 @@ func toWordSize(size uint64) uint64 {
return (size + 31) / 32
}
-
-func allZero(b []byte) bool {
- for _, byte := range b {
- if byte != 0 {
- return false
- }
- }
- return true
-}
diff --git a/core/vm/contract.go b/core/vm/contract.go
index f18f77567..f799bba0c 100644
--- a/core/vm/contract.go
+++ b/core/vm/contract.go
@@ -17,6 +17,7 @@
package vm
import (
+ "github.com/core-coin/uint256"
"math/big"
"github.com/core-coin/go-core/common"
@@ -57,8 +58,8 @@ type Contract struct {
CodeAddr *common.Address
Input []byte
- Energy uint64
- value *big.Int
+ Energy uint64
+ value *big.Int
}
// NewContract returns a new contract environment for the execution of CVM.
@@ -81,11 +82,11 @@ func NewContract(caller ContractRef, object ContractRef, value *big.Int, energy
return c
}
-func (c *Contract) validJumpdest(dest *big.Int) bool {
- udest := dest.Uint64()
+func (c *Contract) validJumpdest(dest *uint256.Int) bool {
+ udest, overflow := dest.Uint64WithOverflow()
// PC cannot go beyond len(code) and certainly can't be bigger than 63bits.
// Don't bother checking for JUMPDEST in that case.
- if dest.BitLen() >= 63 || udest >= uint64(len(c.Code)) {
+ if overflow || udest >= uint64(len(c.Code)) {
return false
}
// Only JUMPDESTs allowed for destinations
diff --git a/core/vm/cvm.go b/core/vm/cvm.go
index 765facda4..0040d766b 100644
--- a/core/vm/cvm.go
+++ b/core/vm/cvm.go
@@ -76,12 +76,12 @@ type Context struct {
GetHash GetHashFunc
// Message information
- Origin common.Address // Provides information for ORIGIN
+ Origin common.Address // Provides information for ORIGIN
EnergyPrice *big.Int // Provides information for ENERGYPRICE
// Block information
Coinbase common.Address // Provides information for COINBASE
- EnergyLimit uint64 // Provides information for ENERGYLIMIT
+ EnergyLimit uint64 // Provides information for ENERGYLIMIT
BlockNumber *big.Int // Provides information for NUMBER
Time *big.Int // Provides information for TIME
Difficulty *big.Int // Provides information for DIFFICULTY
@@ -338,7 +338,7 @@ func (cvm *CVM) StaticCall(caller ContractRef, addr common.Address, input []byte
// We do an AddBalance of zero here, just in order to trigger a touch.
// but is the correct thing to do and matters on other networks, in tests, and potential
// future scenarios
- cvm.StateDB.AddBalance(addr, bigZero)
+ cvm.StateDB.AddBalance(addr, big.NewInt(0))
// When an error was returned by the CVM or when setting the creation code
// above we revert to the snapshot and consume any energy remaining.
diff --git a/core/vm/eips.go b/core/vm/eips.go
index b24d10377..bc52da4f8 100644
--- a/core/vm/eips.go
+++ b/core/vm/eips.go
@@ -16,15 +16,17 @@
package vm
+import "github.com/core-coin/uint256"
+
func opSelfBalance(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- balance := interpreter.intPool.get().Set(interpreter.cvm.StateDB.GetBalance(contract.Address()))
+ balance, _ := uint256.FromBig(interpreter.cvm.StateDB.GetBalance(contract.Address()))
stack.push(balance)
return nil, nil
}
// opNetworkID implements NETWORKID opcode
func opNetworkID(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- networkId := interpreter.intPool.get().Set(interpreter.cvm.chainConfig.NetworkID)
+ networkId, _ := uint256.FromBig(interpreter.cvm.chainConfig.NetworkID)
stack.push(networkId)
return nil, nil
}
diff --git a/core/vm/energy.go b/core/vm/energy.go
index 798e5b7a5..7a709d810 100644
--- a/core/vm/energy.go
+++ b/core/vm/energy.go
@@ -17,7 +17,7 @@
package vm
import (
- "math/big"
+ "github.com/core-coin/uint256"
)
// Energy costs
@@ -33,7 +33,7 @@ const (
// callEnergy returns the actual energy cost of the call.
//
// The returned energy is energy - base * 63 / 64.
-func callEnergy(availableEnergy, base uint64, callCost *big.Int) (uint64, error) {
+func callEnergy(availableEnergy, base uint64, callCost *uint256.Int) (uint64, error) {
availableEnergy = availableEnergy - base
energy := availableEnergy - availableEnergy/64
// If the bit length exceeds 64 bit we know that the newly calculated "energy" for CIP150
diff --git a/core/vm/energy_table.go b/core/vm/energy_table.go
index 04909ab06..7e33d90c1 100644
--- a/core/vm/energy_table.go
+++ b/core/vm/energy_table.go
@@ -70,7 +70,7 @@ func memoryCopierEnergy(stackpos int) energyFunc {
return 0, err
}
// And energy for copying data, charged per word at param.CopyEnergy
- words, overflow := bigUint64(stack.Back(stackpos))
+ words, overflow := stack.Back(stackpos).Uint64WithOverflow()
if overflow {
return 0, errEnergyUintOverflow
}
@@ -114,14 +114,14 @@ func energySStore(cvm *CVM, contract *Contract, stack *Stack, mem *Memory, memor
// Energy sentry honoured, do the actual energy calculation based on the stored value
var (
y, x = stack.Back(1), stack.Back(0)
- current = cvm.StateDB.GetState(contract.Address(), common.BigToHash(x))
+ current = cvm.StateDB.GetState(contract.Address(), common.Hash(x.Bytes32()))
)
- value := common.BigToHash(y)
+ value := common.Hash(y.Bytes32())
if current == value { // noop (1)
return params.SstoreNoopEnergy, nil
}
- original := cvm.StateDB.GetCommittedState(contract.Address(), common.BigToHash(x))
+ original := cvm.StateDB.GetCommittedState(contract.Address(), common.Hash(x.Bytes32()))
if original == current {
if original == (common.Hash{}) { // create slot (2.1.1)
return params.SstoreInitEnergy, nil
@@ -150,7 +150,7 @@ func energySStore(cvm *CVM, contract *Contract, stack *Stack, mem *Memory, memor
func makeEnergyLog(n uint64) energyFunc {
return func(cvm *CVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
- requestedSize, overflow := bigUint64(stack.Back(1))
+ requestedSize, overflow := stack.Back(1).Uint64WithOverflow()
if overflow {
return 0, errEnergyUintOverflow
}
@@ -183,7 +183,7 @@ func energySha3(cvm *CVM, contract *Contract, stack *Stack, mem *Memory, memoryS
if err != nil {
return 0, err
}
- wordEnergy, overflow := bigUint64(stack.Back(1))
+ wordEnergy, overflow := stack.Back(1).Uint64WithOverflow()
if overflow {
return 0, errEnergyUintOverflow
}
@@ -217,7 +217,7 @@ func energyCreate2(cvm *CVM, contract *Contract, stack *Stack, mem *Memory, memo
if err != nil {
return 0, err
}
- wordEnergy, overflow := bigUint64(stack.Back(2))
+ wordEnergy, overflow := stack.Back(2).Uint64WithOverflow()
if overflow {
return 0, errEnergyUintOverflow
}
@@ -234,7 +234,7 @@ func energyExp(cvm *CVM, contract *Contract, stack *Stack, mem *Memory, memorySi
expByteLen := uint64((stack.data[stack.len()-2].BitLen() + 7) / 8)
var (
- energy = expByteLen * params.ExpByte // no overflow check required. Max is 256 * ExpByte energy
+ energy = expByteLen * params.ExpByte // no overflow check required. Max is 256 * ExpByte energy
overflow bool
)
if energy, overflow = math.SafeAdd(energy, params.ExpEnergy); overflow {
@@ -245,9 +245,9 @@ func energyExp(cvm *CVM, contract *Contract, stack *Stack, mem *Memory, memorySi
func energyCall(cvm *CVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
var (
- energy uint64
- transfersValue = stack.Back(2).Sign() != 0
- address = common.BigToAddress(stack.Back(1))
+ energy uint64
+ transfersValue = !stack.Back(2).IsZero()
+ address = common.Address(stack.Back(1).Bytes22())
)
if transfersValue && cvm.StateDB.Empty(address) {
energy += params.CallNewAccountEnergy
@@ -264,7 +264,7 @@ func energyCall(cvm *CVM, contract *Contract, stack *Stack, mem *Memory, memoryS
return 0, errEnergyUintOverflow
}
- cvm.callEnergyTemp, err = callEnergy( contract.Energy, energy, stack.Back(0))
+ cvm.callEnergyTemp, err = callEnergy(contract.Energy, energy, stack.Back(0))
if err != nil {
return 0, err
}
@@ -280,7 +280,7 @@ func energyCallCode(cvm *CVM, contract *Contract, stack *Stack, mem *Memory, mem
return 0, err
}
var (
- energy uint64
+ energy uint64
overflow bool
)
if stack.Back(2).Sign() != 0 {
@@ -335,7 +335,7 @@ func energySelfdestruct(cvm *CVM, contract *Contract, stack *Stack, mem *Memory,
var energy uint64
energy = params.SelfdestructEnergy
- var address = common.BigToAddress(stack.Back(0))
+ var address = common.Address(stack.Back(0).Bytes22())
if cvm.StateDB.Empty(address) && cvm.StateDB.GetBalance(contract.Address()).Sign() != 0 {
energy += params.CreateBySelfdestructEnergy
diff --git a/core/vm/instructions.go b/core/vm/instructions.go
index 164f8fe7f..9dce1deee 100644
--- a/core/vm/instructions.go
+++ b/core/vm/instructions.go
@@ -18,18 +18,14 @@ package vm
import (
"errors"
- "math/big"
-
"github.com/core-coin/go-core/common"
- "github.com/core-coin/go-core/common/math"
"github.com/core-coin/go-core/core/types"
"github.com/core-coin/go-core/params"
+ "github.com/core-coin/uint256"
"golang.org/x/crypto/sha3"
)
var (
- bigZero = new(big.Int)
- tt255 = math.BigPow(2, 255)
errWriteProtection = errors.New("cvm: write protection")
errReturnDataOutOfBounds = errors.New("cvm: return data out of bounds")
errExecutionReverted = errors.New("cvm: execution reverted")
@@ -39,286 +35,162 @@ var (
func opAdd(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
x, y := stack.pop(), stack.peek()
- math.U256(y.Add(x, y))
-
- interpreter.intPool.put(x)
+ y.Add(&x, y)
return nil, nil
}
func opSub(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
x, y := stack.pop(), stack.peek()
- math.U256(y.Sub(x, y))
-
- interpreter.intPool.put(x)
+ y.Sub(&x, y)
return nil, nil
}
func opMul(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.pop()
- stack.push(math.U256(x.Mul(x, y)))
-
- interpreter.intPool.put(y)
+ x, y := stack.pop(), stack.peek()
+ y.Mul(&x, y)
return nil, nil
}
func opDiv(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
x, y := stack.pop(), stack.peek()
- if y.Sign() != 0 {
- math.U256(y.Div(x, y))
- } else {
- y.SetUint64(0)
- }
- interpreter.intPool.put(x)
+ y.Div(&x, y)
return nil, nil
}
func opSdiv(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := math.S256(stack.pop()), math.S256(stack.pop())
- res := interpreter.intPool.getZero()
-
- if y.Sign() == 0 || x.Sign() == 0 {
- stack.push(res)
- } else {
- if x.Sign() != y.Sign() {
- res.Div(x.Abs(x), y.Abs(y))
- res.Neg(res)
- } else {
- res.Div(x.Abs(x), y.Abs(y))
- }
- stack.push(math.U256(res))
- }
- interpreter.intPool.put(x, y)
+ x, y := stack.pop(), stack.peek()
+ y.SDiv(&x, y)
return nil, nil
}
func opMod(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.pop()
- if y.Sign() == 0 {
- stack.push(x.SetUint64(0))
- } else {
- stack.push(math.U256(x.Mod(x, y)))
- }
- interpreter.intPool.put(y)
+ x, y := stack.pop(), stack.peek()
+ y.Mod(&x, y)
return nil, nil
}
func opSmod(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := math.S256(stack.pop()), math.S256(stack.pop())
- res := interpreter.intPool.getZero()
-
- if y.Sign() == 0 {
- stack.push(res)
- } else {
- if x.Sign() < 0 {
- res.Mod(x.Abs(x), y.Abs(y))
- res.Neg(res)
- } else {
- res.Mod(x.Abs(x), y.Abs(y))
- }
- stack.push(math.U256(res))
- }
- interpreter.intPool.put(x, y)
+ x, y := stack.pop(), stack.peek()
+ y.SMod(&x, y)
return nil, nil
}
func opExp(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- base, exponent := stack.pop(), stack.pop()
- // some shortcuts
- cmpToOne := exponent.Cmp(big1)
- if cmpToOne < 0 { // Exponent is zero
- // x ^ 0 == 1
- stack.push(base.SetUint64(1))
- } else if base.Sign() == 0 {
- // 0 ^ y, if y != 0, == 0
- stack.push(base.SetUint64(0))
- } else if cmpToOne == 0 { // Exponent is one
- // x ^ 1 == x
- stack.push(base)
- } else {
- stack.push(math.Exp(base, exponent))
- interpreter.intPool.put(base)
- }
- interpreter.intPool.put(exponent)
+ base, exponent := stack.pop(), stack.peek()
+ exponent.Exp(&base, exponent)
return nil, nil
}
func opSignExtend(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- back := stack.pop()
- if back.Cmp(big.NewInt(31)) < 0 {
- bit := uint(back.Uint64()*8 + 7)
- num := stack.pop()
- mask := back.Lsh(common.Big1, bit)
- mask.Sub(mask, common.Big1)
- if num.Bit(int(bit)) > 0 {
- num.Or(num, mask.Not(mask))
- } else {
- num.And(num, mask)
- }
-
- stack.push(math.U256(num))
- }
-
- interpreter.intPool.put(back)
+ back, num := stack.pop(), stack.peek()
+ num.ExtendSign(num, &back)
return nil, nil
}
func opNot(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
x := stack.peek()
- math.U256(x.Not(x))
+ x.Not(x)
return nil, nil
}
func opLt(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
x, y := stack.pop(), stack.peek()
- if x.Cmp(y) < 0 {
- y.SetUint64(1)
+ if x.Lt(y) {
+ y.SetOne()
} else {
- y.SetUint64(0)
+ y.Clear()
}
- interpreter.intPool.put(x)
return nil, nil
}
func opGt(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
x, y := stack.pop(), stack.peek()
- if x.Cmp(y) > 0 {
- y.SetUint64(1)
+ if x.Gt(y) {
+ y.SetOne()
} else {
- y.SetUint64(0)
+ y.Clear()
}
- interpreter.intPool.put(x)
return nil, nil
}
func opSlt(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
x, y := stack.pop(), stack.peek()
-
- xSign := x.Cmp(tt255)
- ySign := y.Cmp(tt255)
-
- switch {
- case xSign >= 0 && ySign < 0:
- y.SetUint64(1)
-
- case xSign < 0 && ySign >= 0:
- y.SetUint64(0)
-
- default:
- if x.Cmp(y) < 0 {
- y.SetUint64(1)
- } else {
- y.SetUint64(0)
- }
+ if x.Slt(y) {
+ y.SetOne()
+ } else {
+ y.Clear()
}
- interpreter.intPool.put(x)
return nil, nil
}
func opSgt(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
x, y := stack.pop(), stack.peek()
-
- xSign := x.Cmp(tt255)
- ySign := y.Cmp(tt255)
-
- switch {
- case xSign >= 0 && ySign < 0:
- y.SetUint64(0)
-
- case xSign < 0 && ySign >= 0:
- y.SetUint64(1)
-
- default:
- if x.Cmp(y) > 0 {
- y.SetUint64(1)
- } else {
- y.SetUint64(0)
- }
+ if x.Sgt(y) {
+ y.SetOne()
+ } else {
+ y.Clear()
}
- interpreter.intPool.put(x)
return nil, nil
}
func opEq(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
x, y := stack.pop(), stack.peek()
- if x.Cmp(y) == 0 {
- y.SetUint64(1)
+ if x.Eq(y) {
+ y.SetOne()
} else {
- y.SetUint64(0)
+ y.Clear()
}
- interpreter.intPool.put(x)
return nil, nil
}
func opIszero(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
x := stack.peek()
- if x.Sign() > 0 {
- x.SetUint64(0)
+ if x.IsZero() {
+ x.SetOne()
} else {
- x.SetUint64(1)
+ x.Clear()
}
return nil, nil
}
func opAnd(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.pop()
- stack.push(x.And(x, y))
-
- interpreter.intPool.put(y)
+ x, y := stack.pop(), stack.peek()
+ y.And(&x, y)
return nil, nil
}
func opOr(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
x, y := stack.pop(), stack.peek()
- y.Or(x, y)
-
- interpreter.intPool.put(x)
+ y.Or(&x, y)
return nil, nil
}
func opXor(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
x, y := stack.pop(), stack.peek()
- y.Xor(x, y)
-
- interpreter.intPool.put(x)
+ y.Xor(&x, y)
return nil, nil
}
func opByte(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
th, val := stack.pop(), stack.peek()
- if th.Cmp(common.Big32) < 0 {
- b := math.Byte(val, 32, int(th.Int64()))
- val.SetUint64(uint64(b))
- } else {
- val.SetUint64(0)
- }
- interpreter.intPool.put(th)
+ val.Byte(&th)
return nil, nil
}
func opAddmod(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y, z := stack.pop(), stack.pop(), stack.pop()
- if z.Cmp(bigZero) > 0 {
- x.Add(x, y)
- x.Mod(x, z)
- stack.push(math.U256(x))
+ x, y, z := stack.pop(), stack.pop(), stack.peek()
+ if z.IsZero() {
+ z.Clear()
} else {
- stack.push(x.SetUint64(0))
+ z.AddMod(&x, &y, z)
}
- interpreter.intPool.put(y, z)
return nil, nil
}
func opMulmod(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y, z := stack.pop(), stack.pop(), stack.pop()
- if z.Cmp(bigZero) > 0 {
- x.Mul(x, y)
- x.Mod(x, z)
- stack.push(math.U256(x))
- } else {
- stack.push(x.SetUint64(0))
- }
- interpreter.intPool.put(y, z)
+ x, y, z := stack.pop(), stack.pop(), stack.peek()
+ z.MulMod(&x, &y, z)
return nil, nil
}
@@ -327,15 +199,12 @@ func opMulmod(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memor
// and pushes on the stack arg2 shifted to the left by arg1 number of bits.
func opSHL(pc *uint64, interpreter *CVMInterpreter, 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 interpreter.intPool.put(shift) // First operand back into the pool
-
- if shift.Cmp(common.Big256) >= 0 {
- value.SetUint64(0)
- return nil, nil
+ shift, value := stack.pop(), stack.peek()
+ if shift.LtUint64(256) {
+ value.Lsh(value, uint(shift.Uint64()))
+ } else {
+ value.Clear()
}
- n := uint(shift.Uint64())
- math.U256(value.Lsh(value, n))
return nil, nil
}
@@ -345,15 +214,12 @@ func opSHL(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *
// and pushes on the stack arg2 shifted to the right by arg1 number of bits with zero fill.
func opSHR(pc *uint64, interpreter *CVMInterpreter, 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 interpreter.intPool.put(shift) // First operand back into the pool
-
- if shift.Cmp(common.Big256) >= 0 {
- value.SetUint64(0)
- return nil, nil
+ shift, value := stack.pop(), stack.peek()
+ if shift.LtUint64(256) {
+ value.Rsh(value, uint(shift.Uint64()))
+ } else {
+ value.Clear()
}
- n := uint(shift.Uint64())
- math.U256(value.Rsh(value, n))
return nil, nil
}
@@ -363,28 +229,25 @@ func opSHR(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *
// and pushes on the stack arg2 shifted to the right by arg1 number of bits with sign extension.
func opSAR(pc *uint64, interpreter *CVMInterpreter, 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 interpreter.intPool.put(shift) // First operand back into the pool
-
- if shift.Cmp(common.Big256) >= 0 {
+ shift, value := stack.pop(), stack.peek()
+ if shift.GtUint64(256) {
if value.Sign() >= 0 {
- value.SetUint64(0)
+ value.Clear()
} else {
- value.SetInt64(-1)
+ // Max negative shift: all bits set
+ value.SetAllOne()
}
- stack.push(math.U256(value))
return nil, nil
}
n := uint(shift.Uint64())
- value.Rsh(value, n)
- stack.push(math.U256(value))
+ value.SRsh(value, n)
return nil, nil
}
func opSha3(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- offset, size := stack.pop(), stack.pop()
- data := memory.GetPtr(offset.Int64(), size.Int64())
+ offset, size := stack.pop(), stack.peek()
+ data := memory.GetPtr(int64(offset.Uint64()), int64(size.Uint64()))
if interpreter.hasher == nil {
interpreter.hasher = sha3.New256().(keccakState)
@@ -398,45 +261,51 @@ func opSha3(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory
if cvm.vmConfig.EnablePreimageRecording {
cvm.StateDB.AddPreimage(interpreter.hasherBuf, data)
}
- stack.push(interpreter.intPool.get().SetBytes(interpreter.hasherBuf[:]))
-
- interpreter.intPool.put(offset, size)
+ size.SetBytes(interpreter.hasherBuf[:])
return nil, nil
}
func opAddress(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(interpreter.intPool.get().SetBytes(contract.Address().Bytes()))
+ stack.push(new(uint256.Int).SetBytes(contract.Address().Bytes()))
return nil, nil
}
func opBalance(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
slot := stack.peek()
- slot.Set(interpreter.cvm.StateDB.GetBalance(common.BigToAddress(slot)))
+ address := common.Address(slot.Bytes22())
+ slot.SetFromBig(interpreter.cvm.StateDB.GetBalance(address))
return nil, nil
}
func opOrigin(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(interpreter.intPool.get().SetBytes(interpreter.cvm.Origin.Bytes()))
+ stack.push(new(uint256.Int).SetBytes(interpreter.cvm.Origin.Bytes()))
return nil, nil
}
func opCaller(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(interpreter.intPool.get().SetBytes(contract.Caller().Bytes()))
+ stack.push(new(uint256.Int).SetBytes(contract.Caller().Bytes()))
return nil, nil
}
func opCallValue(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(interpreter.intPool.get().Set(contract.value))
+ v, _ := uint256.FromBig(contract.value)
+ stack.push(v)
return nil, nil
}
func opCallDataLoad(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(interpreter.intPool.get().SetBytes(getDataBig(contract.Input, stack.pop(), big32)))
+ x := stack.peek()
+ if offset, overflow := x.Uint64WithOverflow(); !overflow {
+ data := getData(contract.Input, offset, 32)
+ x.SetBytes(data)
+ } else {
+ x.Clear()
+ }
return nil, nil
}
func opCallDataSize(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(interpreter.intPool.get().SetInt64(int64(len(contract.Input))))
+ stack.push(new(uint256.Int).SetUint64(uint64(len(contract.Input))))
return nil, nil
}
@@ -446,14 +315,19 @@ func opCallDataCopy(pc *uint64, interpreter *CVMInterpreter, contract *Contract,
dataOffset = stack.pop()
length = stack.pop()
)
- memory.Set(memOffset.Uint64(), length.Uint64(), getDataBig(contract.Input, dataOffset, length))
-
- interpreter.intPool.put(memOffset, dataOffset, length)
+ dataOffset64, overflow := dataOffset.Uint64WithOverflow()
+ if overflow {
+ dataOffset64 = 0xffffffffffffffff
+ }
+ // These values are checked for overflow during energy cost calculation
+ memOffset64 := memOffset.Uint64()
+ length64 := length.Uint64()
+ memory.Set(memOffset64, length64, getData(contract.Input, dataOffset64, length64))
return nil, nil
}
func opReturnDataSize(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(interpreter.intPool.get().SetUint64(uint64(len(interpreter.returnData))))
+ stack.push(new(uint256.Int).SetUint64(uint64(len(interpreter.returnData))))
return nil, nil
}
@@ -462,28 +336,33 @@ func opReturnDataCopy(pc *uint64, interpreter *CVMInterpreter, contract *Contrac
memOffset = stack.pop()
dataOffset = stack.pop()
length = stack.pop()
-
- end = interpreter.intPool.get().Add(dataOffset, length)
)
- defer interpreter.intPool.put(memOffset, dataOffset, length, end)
- if !end.IsUint64() || uint64(len(interpreter.returnData)) < end.Uint64() {
+ offset64, overflow := dataOffset.Uint64WithOverflow()
+ if overflow {
return nil, errReturnDataOutOfBounds
}
- memory.Set(memOffset.Uint64(), length.Uint64(), interpreter.returnData[dataOffset.Uint64():end.Uint64()])
-
+ // we can reuse dataOffset now (aliasing it for clarity)
+ var end = dataOffset
+ end.Add(&dataOffset, &length)
+ end64, overflow := end.Uint64WithOverflow()
+ if overflow || uint64(len(interpreter.returnData)) < end64 {
+ return nil, errReturnDataOutOfBounds
+ }
+ memory.Set(memOffset.Uint64(), length.Uint64(), interpreter.returnData[offset64:end64])
return nil, nil
}
func opExtCodeSize(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
slot := stack.peek()
- slot.SetUint64(uint64(interpreter.cvm.StateDB.GetCodeSize(common.BigToAddress(slot))))
+ slot.SetUint64(uint64(interpreter.cvm.StateDB.GetCodeSize(common.Address(slot.Bytes22()))))
return nil, nil
}
func opCodeSize(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- l := interpreter.intPool.get().SetInt64(int64(len(contract.Code)))
+ l := new(uint256.Int)
+ l.SetUint64(uint64(len(contract.Code)))
stack.push(l)
return nil, nil
@@ -495,24 +374,31 @@ func opCodeCopy(pc *uint64, interpreter *CVMInterpreter, contract *Contract, mem
codeOffset = stack.pop()
length = stack.pop()
)
- codeCopy := getDataBig(contract.Code, codeOffset, length)
+ uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow()
+ if overflow {
+ uint64CodeOffset = 0xffffffffffffffff
+ }
+ codeCopy := getData(contract.Code, uint64CodeOffset, length.Uint64())
memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy)
- interpreter.intPool.put(memOffset, codeOffset, length)
return nil, nil
}
func opExtCodeCopy(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
var (
- addr = common.BigToAddress(stack.pop())
+ a = stack.pop()
memOffset = stack.pop()
codeOffset = stack.pop()
length = stack.pop()
)
- codeCopy := getDataBig(interpreter.cvm.StateDB.GetCode(addr), codeOffset, length)
+ uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow()
+ if overflow {
+ uint64CodeOffset = 0xffffffffffffffff
+ }
+ addr := common.Address(a.Bytes22())
+ codeCopy := getData(interpreter.cvm.StateDB.GetCode(addr), uint64CodeOffset, length.Uint64())
memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy)
- interpreter.intPool.put(memOffset, codeOffset, length)
return nil, nil
}
@@ -544,9 +430,9 @@ func opExtCodeCopy(pc *uint64, interpreter *CVMInterpreter, contract *Contract,
// this account should be regarded as a non-existent account and zero should be returned.
func opExtCodeHash(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
slot := stack.peek()
- address := common.BigToAddress(slot)
+ address := common.Address(slot.Bytes22())
if interpreter.cvm.StateDB.Empty(address) {
- slot.SetUint64(0)
+ slot.Clear()
} else {
slot.SetBytes(interpreter.cvm.StateDB.GetCodeHash(address).Bytes())
}
@@ -554,56 +440,69 @@ func opExtCodeHash(pc *uint64, interpreter *CVMInterpreter, contract *Contract,
}
func opEnergyprice(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(interpreter.intPool.get().Set(interpreter.cvm.EnergyPrice))
+ v, _ := uint256.FromBig(interpreter.cvm.EnergyPrice)
+ stack.push(v)
return nil, nil
}
func opBlockhash(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- num := stack.pop()
-
- n := interpreter.intPool.get().Sub(interpreter.cvm.BlockNumber, common.Big257)
- if num.Cmp(n) > 0 && num.Cmp(interpreter.cvm.BlockNumber) < 0 {
- stack.push(interpreter.cvm.GetHash(num.Uint64()).Big())
+ num := stack.peek()
+ num64, overflow := num.Uint64WithOverflow()
+ if overflow {
+ num.Clear()
+ return nil, nil
+ }
+ var upper, lower uint64
+ upper = interpreter.cvm.BlockNumber.Uint64()
+ if upper < 257 {
+ lower = 0
} else {
- stack.push(interpreter.intPool.getZero())
+ lower = upper - 256
+ }
+ if num64 >= lower && num64 < upper {
+ num.SetBytes(interpreter.cvm.GetHash(num64).Bytes())
+ } else {
+ num.Clear()
}
- interpreter.intPool.put(num, n)
return nil, nil
}
func opCoinbase(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(interpreter.intPool.get().SetBytes(interpreter.cvm.Coinbase.Bytes()))
+ stack.push(new(uint256.Int).SetBytes(interpreter.cvm.Coinbase.Bytes()))
return nil, nil
}
func opTimestamp(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(math.U256(interpreter.intPool.get().Set(interpreter.cvm.Time)))
+ v, _ := uint256.FromBig(interpreter.cvm.Time)
+ stack.push(v)
return nil, nil
}
func opNumber(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(math.U256(interpreter.intPool.get().Set(interpreter.cvm.BlockNumber)))
+ v, _ := uint256.FromBig(interpreter.cvm.BlockNumber)
+ stack.push(v)
return nil, nil
}
func opDifficulty(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(math.U256(interpreter.intPool.get().Set(interpreter.cvm.Difficulty)))
+ v, _ := uint256.FromBig(interpreter.cvm.Difficulty)
+ stack.push(v)
return nil, nil
}
func opEnergyLimit(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(math.U256(interpreter.intPool.get().SetUint64(interpreter.cvm.EnergyLimit)))
+ stack.push(new(uint256.Int).SetUint64(interpreter.cvm.EnergyLimit))
return nil, nil
}
func opPop(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- interpreter.intPool.put(stack.pop())
+ stack.pop()
return nil, nil
}
func opMload(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
v := stack.peek()
- offset := v.Int64()
+ offset := int64(v.Uint64())
v.SetBytes(memory.GetPtr(offset, 32))
return nil, nil
}
@@ -611,50 +510,46 @@ func opMload(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory
func opMstore(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
// pop value of the stack
mStart, val := stack.pop(), stack.pop()
- memory.Set32(mStart.Uint64(), val)
-
- interpreter.intPool.put(mStart, val)
+ memory.Set32(mStart.Uint64(), &val)
return nil, nil
}
func opMstore8(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- off, val := stack.pop().Int64(), stack.pop().Int64()
- memory.store[off] = byte(val & 0xff)
-
+ off, val := stack.pop(), stack.pop()
+ memory.store[off.Uint64()] = byte(val.Uint64())
return nil, nil
}
func opSload(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
loc := stack.peek()
- val := interpreter.cvm.StateDB.GetState(contract.Address(), common.BigToHash(loc))
+ hash := common.Hash(loc.Bytes32())
+ val := interpreter.cvm.StateDB.GetState(contract.Address(), hash)
loc.SetBytes(val.Bytes())
return nil, nil
}
func opSstore(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- loc := common.BigToHash(stack.pop())
+ loc := stack.pop()
val := stack.pop()
- interpreter.cvm.StateDB.SetState(contract.Address(), loc, common.BigToHash(val))
-
- interpreter.intPool.put(val)
+ interpreter.cvm.StateDB.SetState(contract.Address(),
+ common.Hash(loc.Bytes32()), common.Hash(val.Bytes32()))
return nil, nil
}
func opJump(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
pos := stack.pop()
- if !contract.validJumpdest(pos) {
+ if !contract.validJumpdest(&pos) {
return nil, errInvalidJump
}
*pc = pos.Uint64()
- interpreter.intPool.put(pos)
return nil, nil
}
func opJumpi(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
pos, cond := stack.pop(), stack.pop()
- if cond.Sign() != 0 {
- if !contract.validJumpdest(pos) {
+ if !cond.IsZero() {
+ if !contract.validJumpdest(&pos) {
return nil, errInvalidJump
}
*pc = pos.Uint64()
@@ -662,7 +557,6 @@ func opJumpi(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory
*pc++
}
- interpreter.intPool.put(pos, cond)
return nil, nil
}
@@ -671,17 +565,17 @@ func opJumpdest(pc *uint64, interpreter *CVMInterpreter, contract *Contract, mem
}
func opPc(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(interpreter.intPool.get().SetUint64(*pc))
+ stack.push(new(uint256.Int).SetUint64(*pc))
return nil, nil
}
func opMsize(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(interpreter.intPool.get().SetInt64(int64(memory.Len())))
+ stack.push(new(uint256.Int).SetUint64(uint64(memory.Len())))
return nil, nil
}
func opEnergy(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(interpreter.intPool.get().SetUint64(contract.Energy))
+ stack.push(new(uint256.Int).SetUint64(contract.Energy))
return nil, nil
}
@@ -689,25 +583,27 @@ func opCreate(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memor
var (
value = stack.pop()
offset, size = stack.pop(), stack.pop()
- input = memory.GetCopy(offset.Int64(), size.Int64())
- energy = contract.Energy
+ input = memory.GetCopy(int64(offset.Uint64()), int64(size.Uint64()))
+ energy = contract.Energy
)
energy -= energy / 64
+ // reuse size int for stackvalue
+ stackvalue := size
contract.UseEnergy(energy)
- res, addr, returnEnergy, suberr := interpreter.cvm.Create(contract, input, energy, value)
+ res, addr, returnEnergy, suberr := interpreter.cvm.Create(contract, input, energy, value.ToBig())
// Push item on the stack based on the returned error. We must
// ignore this error and pretend the operation was successful.
if suberr == ErrCodeStoreOutOfEnergy {
- stack.push(interpreter.intPool.getZero())
+ stackvalue.Clear()
} else if suberr != nil && suberr != ErrCodeStoreOutOfEnergy {
- stack.push(interpreter.intPool.getZero())
+ stackvalue.Clear()
} else {
- stack.push(interpreter.intPool.get().SetBytes(addr.Bytes()))
+ stackvalue.SetBytes(addr.Bytes())
}
+ stack.push(&stackvalue)
contract.Energy += returnEnergy
- interpreter.intPool.put(value, offset, size)
if suberr == errExecutionReverted {
return res, nil
@@ -720,22 +616,25 @@ func opCreate2(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memo
endowment = stack.pop()
offset, size = stack.pop(), stack.pop()
salt = stack.pop()
- input = memory.GetCopy(offset.Int64(), size.Int64())
- energy = contract.Energy
+ input = memory.GetCopy(int64(offset.Uint64()), int64(size.Uint64()))
+ energy = contract.Energy
)
// Apply CIP150
energy -= energy / 64
contract.UseEnergy(energy)
- res, addr, returnEnergy, suberr := interpreter.cvm.Create2(contract, input, energy, endowment, salt)
+ // reuse size int for stackvalue
+ stackvalue := size
+ res, addr, returnEnergy, suberr := interpreter.cvm.Create2(contract, input, energy,
+ endowment.ToBig(), salt.ToBig())
// Push item on the stack based on the returned error.
if suberr != nil {
- stack.push(interpreter.intPool.getZero())
+ stackvalue.Clear()
} else {
- stack.push(interpreter.intPool.get().SetBytes(addr.Bytes()))
+ stackvalue.SetBytes(addr.Bytes())
}
+ stack.push(&stackvalue)
contract.Energy += returnEnergy
- interpreter.intPool.put(endowment, offset, size, salt)
if suberr == errExecutionReverted {
return res, nil
@@ -745,125 +644,119 @@ func opCreate2(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memo
func opCall(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
// Pop energy. The actual energy in interpreter.cvm.callEnergyTemp.
- interpreter.intPool.put(stack.pop())
+ // We can use this as a temporary value
+ temp := stack.pop()
energy := interpreter.cvm.callEnergyTemp
// Pop other call parameters.
addr, value, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop()
- toAddr := common.BigToAddress(addr)
- value = math.U256(value)
+ toAddr := common.Address(addr.Bytes22())
// Get the arguments from the memory.
- args := memory.GetPtr(inOffset.Int64(), inSize.Int64())
+ args := memory.GetPtr(int64(inOffset.Uint64()), int64(inSize.Uint64()))
- if value.Sign() != 0 {
+ if !value.IsZero() {
energy += params.CallStipend
}
- ret, returnEnergy, err := interpreter.cvm.Call(contract, toAddr, args, energy, value)
+ ret, returnEnergy, err := interpreter.cvm.Call(contract, toAddr, args, energy, value.ToBig())
if err != nil {
- stack.push(interpreter.intPool.getZero())
+ temp.Clear()
} else {
- stack.push(interpreter.intPool.get().SetUint64(1))
+ temp.SetOne()
}
+ stack.push(&temp)
if err == nil || err == errExecutionReverted {
memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
}
contract.Energy += returnEnergy
-
- interpreter.intPool.put(addr, value, inOffset, inSize, retOffset, retSize)
return ret, nil
}
func opCallCode(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
// Pop energy. The actual energy is in interpreter.cvm.callEnergyTemp.
- interpreter.intPool.put(stack.pop())
+ // We use it as a temporary value
+ temp := stack.pop()
energy := interpreter.cvm.callEnergyTemp
// Pop other call parameters.
addr, value, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop()
- toAddr := common.BigToAddress(addr)
- value = math.U256(value)
+ toAddr := common.Address(addr.Bytes22())
// Get arguments from the memory.
- args := memory.GetPtr(inOffset.Int64(), inSize.Int64())
+ args := memory.GetPtr(int64(inOffset.Uint64()), int64(inSize.Uint64()))
- if value.Sign() != 0 {
+ if !value.IsZero() {
energy += params.CallStipend
}
- ret, returnEnergy, err := interpreter.cvm.CallCode(contract, toAddr, args, energy, value)
+ ret, returnEnergy, err := interpreter.cvm.CallCode(contract, toAddr, args, energy, value.ToBig())
if err != nil {
- stack.push(interpreter.intPool.getZero())
+ temp.Clear()
} else {
- stack.push(interpreter.intPool.get().SetUint64(1))
+ temp.SetOne()
}
+ stack.push(&temp)
if err == nil || err == errExecutionReverted {
memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
}
contract.Energy += returnEnergy
-
- interpreter.intPool.put(addr, value, inOffset, inSize, retOffset, retSize)
return ret, nil
}
func opDelegateCall(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
// Pop energy. The actual energy is in interpreter.cvm.callEnergyTemp.
- interpreter.intPool.put(stack.pop())
+ // We use it as a temporary value
+ temp := stack.pop()
energy := interpreter.cvm.callEnergyTemp
// Pop other call parameters.
addr, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop()
- toAddr := common.BigToAddress(addr)
+ toAddr := common.Address(addr.Bytes22())
// Get arguments from the memory.
- args := memory.GetPtr(inOffset.Int64(), inSize.Int64())
+ args := memory.GetPtr(int64(inOffset.Uint64()), int64(inSize.Uint64()))
ret, returnEnergy, err := interpreter.cvm.DelegateCall(contract, toAddr, args, energy)
if err != nil {
- stack.push(interpreter.intPool.getZero())
+ temp.Clear()
} else {
- stack.push(interpreter.intPool.get().SetUint64(1))
+ temp.SetOne()
}
+ stack.push(&temp)
if err == nil || err == errExecutionReverted {
memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
}
contract.Energy += returnEnergy
-
- interpreter.intPool.put(addr, inOffset, inSize, retOffset, retSize)
return ret, nil
}
func opStaticCall(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
// Pop energy. The actual energy is in interpreter.cvm.callEnergyTemp.
- interpreter.intPool.put(stack.pop())
+ // We use it as a temporary value
+ temp := stack.pop()
energy := interpreter.cvm.callEnergyTemp
// Pop other call parameters.
addr, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop()
- toAddr := common.BigToAddress(addr)
+ toAddr := common.Address(addr.Bytes22())
// Get arguments from the memory.
- args := memory.GetPtr(inOffset.Int64(), inSize.Int64())
+ args := memory.GetPtr(int64(inOffset.Uint64()), int64(inSize.Uint64()))
ret, returnEnergy, err := interpreter.cvm.StaticCall(contract, toAddr, args, energy)
if err != nil {
- stack.push(interpreter.intPool.getZero())
+ temp.Clear()
} else {
- stack.push(interpreter.intPool.get().SetUint64(1))
+ temp.SetOne()
}
+ stack.push(&temp)
if err == nil || err == errExecutionReverted {
memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
}
contract.Energy += returnEnergy
-
- interpreter.intPool.put(addr, inOffset, inSize, retOffset, retSize)
return ret, nil
}
func opReturn(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
offset, size := stack.pop(), stack.pop()
- ret := memory.GetPtr(offset.Int64(), size.Int64())
-
- interpreter.intPool.put(offset, size)
+ ret := memory.GetPtr(int64(offset.Uint64()), int64(size.Uint64()))
return ret, nil
}
func opRevert(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
offset, size := stack.pop(), stack.pop()
- ret := memory.GetPtr(offset.Int64(), size.Int64())
-
- interpreter.intPool.put(offset, size)
+ ret := memory.GetPtr(int64(offset.Uint64()), int64(size.Uint64()))
return ret, nil
}
@@ -872,8 +765,9 @@ func opStop(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory
}
func opSuicide(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
+ beneficiary := stack.pop()
balance := interpreter.cvm.StateDB.GetBalance(contract.Address())
- interpreter.cvm.StateDB.AddBalance(common.BigToAddress(stack.pop()), balance)
+ interpreter.cvm.StateDB.AddBalance(common.Address(beneficiary.Bytes22()), balance)
interpreter.cvm.StateDB.Suicide(contract.Address())
return nil, nil
@@ -887,10 +781,11 @@ func makeLog(size int) executionFunc {
topics := make([]common.Hash, size)
mStart, mSize := stack.pop(), stack.pop()
for i := 0; i < size; i++ {
- topics[i] = common.BigToHash(stack.pop())
+ addr := stack.pop()
+ topics[i] = common.Hash(addr.Bytes32())
}
- d := memory.GetCopy(mStart.Int64(), mSize.Int64())
+ d := memory.GetCopy(int64(mStart.Uint64()), int64(mSize.Uint64()))
interpreter.cvm.StateDB.AddLog(&types.Log{
Address: contract.Address(),
Topics: topics,
@@ -900,7 +795,6 @@ func makeLog(size int) executionFunc {
BlockNumber: interpreter.cvm.BlockNumber.Uint64(),
})
- interpreter.intPool.put(mStart, mSize)
return nil, nil
}
}
@@ -909,13 +803,13 @@ func makeLog(size int) executionFunc {
func opPush1(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
var (
codeLen = uint64(len(contract.Code))
- integer = interpreter.intPool.get()
+ integer = new(uint256.Int)
)
*pc += 1
if *pc < codeLen {
stack.push(integer.SetUint64(uint64(contract.Code[*pc])))
} else {
- stack.push(integer.SetUint64(0))
+ stack.push(integer.Clear())
}
return nil, nil
}
@@ -935,8 +829,9 @@ func makePush(size uint64, pushByteSize int) executionFunc {
endMin = startMin + pushByteSize
}
- integer := interpreter.intPool.get()
- stack.push(integer.SetBytes(common.RightPadBytes(contract.Code[startMin:endMin], pushByteSize)))
+ integer := new(uint256.Int)
+ stack.push(integer.SetBytes(common.RightPadBytes(
+ contract.Code[startMin:endMin], pushByteSize)))
*pc += size
return nil, nil
@@ -946,7 +841,7 @@ func makePush(size uint64, pushByteSize int) executionFunc {
// make dup instruction function
func makeDup(size int64) executionFunc {
return func(pc *uint64, interpreter *CVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.dup(interpreter.intPool, int(size))
+ stack.dup(int(size))
return nil, nil
}
}
diff --git a/core/vm/instructions_test.go b/core/vm/instructions_test.go
index 14301c537..70f220c62 100644
--- a/core/vm/instructions_test.go
+++ b/core/vm/instructions_test.go
@@ -20,8 +20,8 @@ import (
"bytes"
"encoding/json"
"fmt"
+ "github.com/core-coin/uint256"
"io/ioutil"
- "math/big"
"testing"
"github.com/core-coin/go-core/common"
@@ -97,42 +97,22 @@ func testTwoOperandOp(t *testing.T, tests []TwoOperandTestcase, opFn executionFu
pc = uint64(0)
cvmInterpreter = env.interpreter.(*CVMInterpreter)
)
- // Stuff a couple of nonzero bigints into pool, to ensure that ops do not rely on pooled integers to be zero
- cvmInterpreter.intPool = poolOfIntPools.get()
- cvmInterpreter.intPool.put(big.NewInt(-1337))
- cvmInterpreter.intPool.put(big.NewInt(-1337))
- cvmInterpreter.intPool.put(big.NewInt(-1337))
-
for i, test := range tests {
- x := new(big.Int).SetBytes(common.Hex2Bytes(test.X))
- y := new(big.Int).SetBytes(common.Hex2Bytes(test.Y))
- expected := new(big.Int).SetBytes(common.Hex2Bytes(test.Expected))
+ x := new(uint256.Int).SetBytes(common.Hex2Bytes(test.X))
+ y := new(uint256.Int).SetBytes(common.Hex2Bytes(test.Y))
+ expected := new(uint256.Int).SetBytes(common.Hex2Bytes(test.Expected))
stack.push(x)
stack.push(y)
opFn(&pc, cvmInterpreter, nil, nil, stack)
+ if len(stack.data) != 1 {
+ t.Errorf("Expected one item on stack after %v, got %d: ", name, len(stack.data))
+ }
actual := stack.pop()
if actual.Cmp(expected) != 0 {
t.Errorf("Testcase %v %d, %v(%x, %x): expected %x, got %x", name, i, name, x, y, 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 cvmInterpreter.intPool.pool.len() > 0 {
-
- poolvals := make(map[*big.Int]struct{})
- poolvals[actual] = struct{}{}
-
- for cvmInterpreter.intPool.pool.len() > 0 {
- key := cvmInterpreter.intPool.get()
- if _, exist := poolvals[key]; exist {
- t.Errorf("Testcase %v %d, pool contains double-entry", name, i)
- }
- poolvals[key] = struct{}{}
- }
- }
}
- poolOfIntPools.put(cvmInterpreter.intPool)
}
func TestByteOp(t *testing.T) {
@@ -166,6 +146,44 @@ func TestSHL(t *testing.T) {
testTwoOperandOp(t, tests, opSHL, "shl")
}
+func TestAddMod(t *testing.T) {
+ var (
+ env = NewCVM(Context{}, nil, params.TestChainConfig, Config{})
+ stack = newstack()
+ evmInterpreter = NewCVMInterpreter(env, env.vmConfig)
+ pc = uint64(0)
+ )
+ tests := []struct {
+ x string
+ y string
+ z string
+ expected string
+ }{
+ {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe",
+ "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe",
+ },
+ }
+ // x + y = 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd
+ // in 256 bit repr, fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd
+
+ for i, test := range tests {
+ x := new(uint256.Int).SetBytes(common.Hex2Bytes(test.x))
+ y := new(uint256.Int).SetBytes(common.Hex2Bytes(test.y))
+ z := new(uint256.Int).SetBytes(common.Hex2Bytes(test.z))
+ expected := new(uint256.Int).SetBytes(common.Hex2Bytes(test.expected))
+ stack.push(z)
+ stack.push(y)
+ stack.push(x)
+ opAddmod(&pc, evmInterpreter, nil, nil, stack)
+ actual := stack.pop()
+ if actual.Cmp(expected) != 0 {
+ t.Errorf("Testcase %d, expected %x, got %x", i, expected, actual)
+ }
+ }
+}
+
func TestSHR(t *testing.T) {
// Testcases from https://github.com/core-coin/CIPs/blob/master/CIPS/cip-145.md#shr-logical-shift-right
tests := []TwoOperandTestcase{
@@ -216,11 +234,10 @@ func getResult(args []*twoOperandParams, opFn executionFunc) []TwoOperandTestcas
pc = uint64(0)
interpreter = env.interpreter.(*CVMInterpreter)
)
- interpreter.intPool = poolOfIntPools.get()
result := make([]TwoOperandTestcase, len(args))
for i, param := range args {
- x := new(big.Int).SetBytes(common.Hex2Bytes(param.x))
- y := new(big.Int).SetBytes(common.Hex2Bytes(param.y))
+ x := new(uint256.Int).SetBytes(common.Hex2Bytes(param.x))
+ y := new(uint256.Int).SetBytes(common.Hex2Bytes(param.y))
stack.push(x)
stack.push(y)
opFn(&pc, interpreter, nil, nil, stack)
@@ -268,7 +285,6 @@ func opBenchmark(bench *testing.B, op func(pc *uint64, interpreter *CVMInterpret
)
env.interpreter = cvmInterpreter
- cvmInterpreter.intPool = poolOfIntPools.get()
// convert args
byteArgs := make([][]byte, len(args))
for i, arg := range args {
@@ -278,13 +294,12 @@ func opBenchmark(bench *testing.B, op func(pc *uint64, interpreter *CVMInterpret
bench.ResetTimer()
for i := 0; i < bench.N; i++ {
for _, arg := range byteArgs {
- a := new(big.Int).SetBytes(arg)
- stack.push(a)
+ a := new(uint256.Int)
+ a.SetBytes(arg)
}
op(&pc, cvmInterpreter, nil, nil, stack)
stack.pop()
}
- poolOfIntPools.put(cvmInterpreter.intPool)
}
func BenchmarkOpAdd64(b *testing.B) {
@@ -504,21 +519,19 @@ func TestOpMstore(t *testing.T) {
)
env.interpreter = cvmInterpreter
- cvmInterpreter.intPool = poolOfIntPools.get()
mem.Resize(64)
pc := uint64(0)
v := "abcdef00000000000000abba000000000deaf000000c0de00100000000133700"
- stack.pushN(new(big.Int).SetBytes(common.Hex2Bytes(v)), big.NewInt(0))
+ stack.pushN(*new(uint256.Int).SetBytes(common.Hex2Bytes(v)), *new(uint256.Int))
opMstore(&pc, cvmInterpreter, nil, mem, stack)
if got := common.Bytes2Hex(mem.GetCopy(0, 32)); got != v {
t.Fatalf("Mstore fail, got %v, expected %v", got, v)
}
- stack.pushN(big.NewInt(0x1), big.NewInt(0))
+ stack.pushN(*new(uint256.Int).SetUint64(0x1), *new(uint256.Int))
opMstore(&pc, cvmInterpreter, nil, mem, stack)
if common.Bytes2Hex(mem.GetCopy(0, 32)) != "0000000000000000000000000000000000000000000000000000000000000001" {
t.Fatalf("Mstore failed to overwrite previous value")
}
- poolOfIntPools.put(cvmInterpreter.intPool)
}
func BenchmarkOpMstore(bench *testing.B) {
@@ -530,18 +543,16 @@ func BenchmarkOpMstore(bench *testing.B) {
)
env.interpreter = cvmInterpreter
- cvmInterpreter.intPool = poolOfIntPools.get()
mem.Resize(64)
pc := uint64(0)
- memStart := big.NewInt(0)
- value := big.NewInt(0x1337)
+ memStart := new(uint256.Int)
+ value := new(uint256.Int).SetUint64(0x1337)
bench.ResetTimer()
for i := 0; i < bench.N; i++ {
- stack.pushN(value, memStart)
+ stack.pushN(*value, *memStart)
opMstore(&pc, cvmInterpreter, nil, mem, stack)
}
- poolOfIntPools.put(cvmInterpreter.intPool)
}
func BenchmarkOpSHA3(bench *testing.B) {
@@ -552,17 +563,15 @@ func BenchmarkOpSHA3(bench *testing.B) {
cvmInterpreter = NewCVMInterpreter(env, env.vmConfig)
)
env.interpreter = cvmInterpreter
- cvmInterpreter.intPool = poolOfIntPools.get()
mem.Resize(32)
pc := uint64(0)
- start := big.NewInt(0)
+ start := uint256.NewInt(0)
bench.ResetTimer()
for i := 0; i < bench.N; i++ {
- stack.pushN(big.NewInt(32), start)
+ stack.pushN(*uint256.NewInt(32), *start)
opSha3(&pc, cvmInterpreter, nil, mem, stack)
}
- poolOfIntPools.put(cvmInterpreter.intPool)
}
func TestCreate2Addreses(t *testing.T) { //TODO: TEST
diff --git a/core/vm/int_pool_verifier.go b/core/vm/int_pool_verifier.go
deleted file mode 100644
index 58b1256c6..000000000
--- a/core/vm/int_pool_verifier.go
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2017 by the Authors
-// This file is part of the go-core library.
-//
-// The go-core library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-core library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-core library. If not, see .
-
-// +build VERIFY_CVM_INTEGER_POOL
-
-package vm
-
-import "fmt"
-
-const verifyPool = true
-
-func verifyIntegerPool(ip *intPool) {
- for i, item := range ip.pool.data {
- if item.Cmp(checkVal) != 0 {
- panic(fmt.Sprintf("%d'th item failed aggressive pool check. Value was modified", i))
- }
- }
-}
diff --git a/core/vm/int_pool_verifier_empty.go b/core/vm/int_pool_verifier_empty.go
deleted file mode 100644
index f20ea3294..000000000
--- a/core/vm/int_pool_verifier_empty.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2017 by the Authors
-// This file is part of the go-core library.
-//
-// The go-core library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-core library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-core library. If not, see .
-
-// +build !VERIFY_CVM_INTEGER_POOL
-
-package vm
-
-const verifyPool = false
-
-func verifyIntegerPool(ip *intPool) {}
diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go
index 646fdeab2..8c779bf74 100644
--- a/core/vm/interpreter.go
+++ b/core/vm/interpreter.go
@@ -75,8 +75,6 @@ type CVMInterpreter struct {
cvm *CVM
cfg Config
- intPool *intPool
-
hasher keccakState // SHA3 hasher instance shared across opcodes
hasherBuf common.Hash // SHA3 hasher result array shared aross opcodes
@@ -111,14 +109,6 @@ func NewCVMInterpreter(cvm *CVM, cfg Config) *CVMInterpreter {
// considered a revert-and-consume-all-energy operation except for
// errExecutionReverted which means revert-and-keep-energy-left.
func (in *CVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (ret []byte, err error) {
- if in.intPool == nil {
- in.intPool = poolOfIntPools.get()
- defer func() {
- poolOfIntPools.put(in.intPool)
- in.intPool = nil
- }()
- }
-
// Increment the call depth which is restricted to 1024
in.cvm.depth++
defer func() { in.cvm.depth-- }()
@@ -156,9 +146,6 @@ func (in *CVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
)
contract.Input = input
- // Reclaim the stack as an int pool when the execution stops
- defer func() { in.intPool.put(stack.data...) }()
-
if in.cfg.Debug {
defer func() {
if err != nil {
@@ -248,11 +235,6 @@ func (in *CVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
// execute the operation
res, err = operation.execute(&pc, in, contract, mem, stack)
- // verifyPool is a build flag. Pool verification makes sure the integrity
- // of the integer pool by comparing values to a default value.
- if verifyPool {
- verifyIntegerPool(in.intPool)
- }
// if the operation clears the return data (e.g. it has returning data)
// set the last return to the result of the operation.
if operation.returns {
diff --git a/core/vm/intpool.go b/core/vm/intpool.go
deleted file mode 100644
index e6f5ccc5e..000000000
--- a/core/vm/intpool.go
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright 2017 by the Authors
-// This file is part of the go-core library.
-//
-// The go-core library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-core library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-core library. If not, see .
-
-package vm
-
-import (
- "math/big"
- "sync"
-)
-
-var checkVal = big.NewInt(-42)
-
-const poolLimit = 256
-
-// intPool is a pool of big integers that
-// can be reused for all big.Int operations.
-type intPool struct {
- pool *Stack
-}
-
-func newIntPool() *intPool {
- return &intPool{pool: newstack()}
-}
-
-// get retrieves a big int from the pool, allocating one if the pool is empty.
-// Note, the returned int's value is arbitrary and will not be zeroed!
-func (p *intPool) get() *big.Int {
- if p.pool.len() > 0 {
- return p.pool.pop()
- }
- return new(big.Int)
-}
-
-// getZero retrieves a big int from the pool, setting it to zero or allocating
-// a new one if the pool is empty.
-func (p *intPool) getZero() *big.Int {
- if p.pool.len() > 0 {
- return p.pool.pop().SetUint64(0)
- }
- return new(big.Int)
-}
-
-// put returns an allocated big int to the pool to be later reused by get calls.
-// Note, the values as saved as is; neither put nor get zeroes the ints out!
-func (p *intPool) put(is ...*big.Int) {
- if len(p.pool.data) > poolLimit {
- return
- }
- for _, i := range is {
- // verifyPool is a build flag. Pool verification makes sure the integrity
- // of the integer pool by comparing values to a default value.
- if verifyPool {
- i.Set(checkVal)
- }
- p.pool.push(i)
- }
-}
-
-// The intPool pool's default capacity
-const poolDefaultCap = 25
-
-// intPoolPool manages a pool of intPools.
-type intPoolPool struct {
- pools []*intPool
- lock sync.Mutex
-}
-
-var poolOfIntPools = &intPoolPool{
- pools: make([]*intPool, 0, poolDefaultCap),
-}
-
-// get is looking for an available pool to return.
-func (ipp *intPoolPool) get() *intPool {
- ipp.lock.Lock()
- defer ipp.lock.Unlock()
-
- if len(poolOfIntPools.pools) > 0 {
- ip := ipp.pools[len(ipp.pools)-1]
- ipp.pools = ipp.pools[:len(ipp.pools)-1]
- return ip
- }
- return newIntPool()
-}
-
-// put a pool that has been allocated with get.
-func (ipp *intPoolPool) put(ip *intPool) {
- ipp.lock.Lock()
- defer ipp.lock.Unlock()
-
- if len(ipp.pools) < cap(ipp.pools) {
- ipp.pools = append(ipp.pools, ip)
- }
-}
diff --git a/core/vm/intpool_test.go b/core/vm/intpool_test.go
deleted file mode 100644
index 31b85eebd..000000000
--- a/core/vm/intpool_test.go
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2018 by the Authors
-// This file is part of the go-core library.
-//
-// The go-core library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-core library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-core library. If not, see .
-
-package vm
-
-import (
- "testing"
-)
-
-func TestIntPoolPoolGet(t *testing.T) {
- poolOfIntPools.pools = make([]*intPool, 0, poolDefaultCap)
-
- nip := poolOfIntPools.get()
- if nip == nil {
- t.Fatalf("Invalid pool allocation")
- }
-}
-
-func TestIntPoolPoolPut(t *testing.T) {
- poolOfIntPools.pools = make([]*intPool, 0, poolDefaultCap)
-
- nip := poolOfIntPools.get()
- if len(poolOfIntPools.pools) != 0 {
- t.Fatalf("Pool got added to list when none should have been")
- }
-
- poolOfIntPools.put(nip)
- if len(poolOfIntPools.pools) == 0 {
- t.Fatalf("Pool did not get added to list when one should have been")
- }
-}
-
-func TestIntPoolPoolReUse(t *testing.T) {
- poolOfIntPools.pools = make([]*intPool, 0, poolDefaultCap)
- nip := poolOfIntPools.get()
- poolOfIntPools.put(nip)
- poolOfIntPools.get()
-
- if len(poolOfIntPools.pools) != 0 {
- t.Fatalf("Invalid number of pools. Got %d, expected %d", len(poolOfIntPools.pools), 0)
- }
-}
diff --git a/core/vm/logger.go b/core/vm/logger.go
index 7e6790717..c5bb829eb 100644
--- a/core/vm/logger.go
+++ b/core/vm/logger.go
@@ -58,8 +58,8 @@ type LogConfig struct {
type StructLog struct {
Pc uint64 `json:"pc"`
Op OpCode `json:"op"`
- Energy uint64 `json:"energy"`
- EnergyCost uint64 `json:"energyCost"`
+ Energy uint64 `json:"energy"`
+ EnergyCost uint64 `json:"energyCost"`
Memory []byte `json:"memory"`
MemorySize int `json:"memSize"`
Stack []*big.Int `json:"stack"`
@@ -72,8 +72,8 @@ type StructLog struct {
// overrides for gencodec
type structLogMarshaling struct {
Stack []*math.HexOrDecimal256
- Energy math.HexOrDecimal64
- EnergyCost math.HexOrDecimal64
+ Energy math.HexOrDecimal64
+ EnergyCost math.HexOrDecimal64
Memory hexutil.Bytes
OpName string `json:"opName"` // adds call to OpName() in MarshalJSON
ErrorString string `json:"error"` // adds call to ErrorString() in MarshalJSON
@@ -153,8 +153,8 @@ func (l *StructLogger) CaptureState(env *CVM, pc uint64, op OpCode, energy, cost
// it in the local storage container.
if op == SSTORE && stack.len() >= 2 {
var (
- value = common.BigToHash(stack.data[stack.len()-2])
- address = common.BigToHash(stack.data[stack.len()-1])
+ value = common.Hash(stack.data[stack.len()-2].Bytes32())
+ address = common.Hash(stack.data[stack.len()-1].Bytes32())
)
l.changedValues[contract.Address()][address] = value
}
@@ -169,7 +169,7 @@ func (l *StructLogger) CaptureState(env *CVM, pc uint64, op OpCode, energy, cost
if !l.cfg.DisableStack {
stck = make([]*big.Int, len(stack.Data()))
for i, item := range stack.Data() {
- stck[i] = new(big.Int).Set(item)
+ stck[i] = new(big.Int).Set(item.ToBig())
}
}
// Copy a snapshot of the current storage to a new container
diff --git a/core/vm/logger_json.go b/core/vm/logger_json.go
index 0c9ad474a..ec7f71ec6 100644
--- a/core/vm/logger_json.go
+++ b/core/vm/logger_json.go
@@ -50,8 +50,8 @@ func (l *JSONLogger) CaptureState(env *CVM, pc uint64, op OpCode, energy, cost u
log := StructLog{
Pc: pc,
Op: op,
- Energy: energy,
- EnergyCost: cost,
+ Energy: energy,
+ EnergyCost: cost,
MemorySize: memory.Len(),
Storage: nil,
Depth: depth,
@@ -62,7 +62,12 @@ func (l *JSONLogger) CaptureState(env *CVM, pc uint64, op OpCode, energy, cost u
log.Memory = memory.Data()
}
if !l.cfg.DisableStack {
- log.Stack = stack.Data()
+ //TODO(@holiman) improve this
+ logstack := make([]*big.Int, len(stack.Data()))
+ for i, item := range stack.Data() {
+ logstack[i] = item.ToBig()
+ }
+ log.Stack = logstack
}
return l.encoder.Encode(log)
}
@@ -75,10 +80,10 @@ func (l *JSONLogger) CaptureFault(env *CVM, pc uint64, op OpCode, energy, cost u
// CaptureEnd is triggered at end of execution.
func (l *JSONLogger) CaptureEnd(output []byte, energyUsed uint64, t time.Duration, err error) error {
type endLog struct {
- Output string `json:"output"`
+ Output string `json:"output"`
EnergyUsed math.HexOrDecimal64 `json:"energyUsed"`
- Time time.Duration `json:"time"`
- Err string `json:"error,omitempty"`
+ Time time.Duration `json:"time"`
+ Err string `json:"error,omitempty"`
}
if err != nil {
return l.encoder.Encode(endLog{common.Bytes2Hex(output), math.HexOrDecimal64(energyUsed), t, err.Error()})
diff --git a/core/vm/logger_test.go b/core/vm/logger_test.go
index 9eb698364..c1a131468 100644
--- a/core/vm/logger_test.go
+++ b/core/vm/logger_test.go
@@ -17,6 +17,7 @@
package vm
import (
+ "github.com/core-coin/uint256"
"math/big"
"testing"
@@ -29,7 +30,7 @@ type dummyContractRef struct {
calledForEach bool
}
-func (dummyContractRef) ReturnEnergy(*big.Int) {}
+func (dummyContractRef) ReturnEnergy(*big.Int) {}
func (dummyContractRef) Address() common.Address { return common.Address{} }
func (dummyContractRef) Value() *big.Int { return new(big.Int) }
func (dummyContractRef) SetCode(common.Hash, []byte) {}
@@ -56,8 +57,8 @@ func TestStoreCapture(t *testing.T) {
stack = newstack()
contract = NewContract(&dummyContractRef{}, &dummyContractRef{}, new(big.Int), 0)
)
- stack.push(big.NewInt(1))
- stack.push(big.NewInt(0))
+ stack.push(uint256.NewInt(1))
+ stack.push(new(uint256.Int))
var index common.Hash
logger.CaptureState(env, 0, SSTORE, 0, 0, mem, stack, contract, 0, nil)
if len(logger.changedValues[contract.Address()]) == 0 {
diff --git a/core/vm/memory.go b/core/vm/memory.go
index 144b3481c..5f223bcbd 100644
--- a/core/vm/memory.go
+++ b/core/vm/memory.go
@@ -18,14 +18,12 @@ package vm
import (
"fmt"
- "math/big"
-
- "github.com/core-coin/go-core/common/math"
+ "github.com/core-coin/uint256"
)
// Memory implements a simple memory model for the Core Virtual Machine.
type Memory struct {
- store []byte
+ store []byte
lastEnergyCost uint64
}
@@ -50,7 +48,7 @@ func (m *Memory) Set(offset, size uint64, value []byte) {
// Set32 sets the 32 bytes starting at offset to the value of val, left-padded with zeroes to
// 32 bytes.
-func (m *Memory) Set32(offset uint64, val *big.Int) {
+func (m *Memory) Set32(offset uint64, val *uint256.Int) {
// length of store may never be less than offset + size.
// The store should be resized PRIOR to setting the memory
if offset+32 > uint64(len(m.store)) {
@@ -59,7 +57,7 @@ func (m *Memory) Set32(offset uint64, val *big.Int) {
// Zero the memory area
copy(m.store[offset:offset+32], []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})
// Fill in relevant bits
- math.ReadBits(val, m.store[offset:offset+32])
+ val.WriteToSlice(m.store[offset:])
}
// Resize resizes the memory to size
diff --git a/core/vm/stack.go b/core/vm/stack.go
index 90ac3ca5a..6bc2c4c81 100644
--- a/core/vm/stack.go
+++ b/core/vm/stack.go
@@ -18,36 +18,35 @@ package vm
import (
"fmt"
- "math/big"
+ "github.com/core-coin/uint256"
)
// Stack is an object for basic stack operations. Items popped to the stack are
// expected to be changed and modified. stack does not take care of adding newly
// initialised objects.
type Stack struct {
- data []*big.Int
+ data []uint256.Int
}
func newstack() *Stack {
- return &Stack{data: make([]*big.Int, 0, 1024)}
+ return &Stack{data: make([]uint256.Int, 0, 16)}
}
-// Data returns the underlying big.Int array.
-func (st *Stack) Data() []*big.Int {
+// Data returns the underlying uint256 array.
+func (st *Stack) Data() []uint256.Int {
return st.data
}
-func (st *Stack) push(d *big.Int) {
+func (st *Stack) push(d *uint256.Int) {
// NOTE push limit (1024) is checked in baseCheck
- //stackItem := new(big.Int).Set(d)
- //st.data = append(st.data, stackItem)
- st.data = append(st.data, d)
+ st.data = append(st.data, *d)
}
-func (st *Stack) pushN(ds ...*big.Int) {
+func (st *Stack) pushN(ds ...uint256.Int) {
+ // FIXME: Is there a way to pass args by pointers.
st.data = append(st.data, ds...)
}
-func (st *Stack) pop() (ret *big.Int) {
+func (st *Stack) pop() (ret uint256.Int) {
ret = st.data[len(st.data)-1]
st.data = st.data[:len(st.data)-1]
return
@@ -61,17 +60,17 @@ func (st *Stack) swap(n int) {
st.data[st.len()-n], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-n]
}
-func (st *Stack) dup(pool *intPool, n int) {
- st.push(pool.get().Set(st.data[st.len()-n]))
+func (st *Stack) dup(n int) {
+ st.push(&st.data[st.len()-n])
}
-func (st *Stack) peek() *big.Int {
- return st.data[st.len()-1]
+func (st *Stack) peek() *uint256.Int {
+ return &st.data[st.len()-1]
}
// Back returns the n'th item in stack
-func (st *Stack) Back(n int) *big.Int {
- return st.data[st.len()-n-1]
+func (st *Stack) Back(n int) *uint256.Int {
+ return &st.data[st.len()-n-1]
}
// Print dumps the content of the stack
diff --git a/go.sum b/go.sum
index 63337cd78..4abb6f08f 100644
--- a/go.sum
+++ b/go.sum
@@ -75,6 +75,8 @@ github.com/core-coin/go-goldilocks v1.0.9 h1:NEX5+LXeLpj3yJPKQgEffj2ly33rOvANsWD
github.com/core-coin/go-goldilocks v1.0.9/go.mod h1:r6mSidt/OMBXorR8jBJYJttsver3m2EBAcSuf+m2Js0=
github.com/core-coin/go-randomy v0.0.14 h1:MIzErlW7djO5IcoMAPNYLOC4YZV47TPmofusu01TGZY=
github.com/core-coin/go-randomy v0.0.14/go.mod h1:7YzU3Hrss60CzXlzziTZNAQUN6u+eLAHH1cL1JRGLBE=
+github.com/core-coin/uint256 v1.0.0 h1:AzgINl9YCnYDRJBlqFlWsVb4sr814LcvPAvkPyVBFVo=
+github.com/core-coin/uint256 v1.0.0/go.mod h1:rrinB/+X6+31MswTK2xwoFGi8i75SH1ILSsRSoOFa1I=
github.com/core-coin/go-randomy v0.0.18 h1:m0IW81uirjpT0fCAnS+5PxPrbI+s/zviFK8hfQbhRcs=
github.com/core-coin/go-randomy v0.0.18/go.mod h1:7YzU3Hrss60CzXlzziTZNAQUN6u+eLAHH1cL1JRGLBE=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
diff --git a/xcb/tracers/tracer.go b/xcb/tracers/tracer.go
index 669fa1b53..beb93eb28 100644
--- a/xcb/tracers/tracer.go
+++ b/xcb/tracers/tracer.go
@@ -163,7 +163,7 @@ func (sw *stackWrapper) peek(idx int) *big.Int {
log.Warn("Tracer accessed out of bound stack", "size", len(sw.stack.Data()), "index", idx)
return new(big.Int)
}
- return sw.stack.Data()[len(sw.stack.Data())-idx-1]
+ return sw.stack.Back(idx).ToBig()
}
// pushObject assembles a JSVM object wrapping a swappable stack and pushes it