From 1af7abd6be3fcb7afbe429063b032dc20ab15c12 Mon Sep 17 00:00:00 2001 From: Silas Davis <silas@monax.io> Date: Fri, 2 Mar 2018 17:23:45 +0000 Subject: [PATCH] Fix issue with SIGNEXTEND and refactor arithmetic Our SIGNEXTEND was broken on positive numbers because for these numbers it `Add`ed the sign extension mask rather than `And`ing it. I took the opportunity to tidy up the arithmetical opcodes and add some test. Signed-off-by: Silas Davis <silas@monax.io> --- binary/integer.go | 45 +++++++- binary/integer_test.go | 158 ++++++++++++++++++++++++++ binary/word256.go | 5 +- binary/word256_test.go | 4 + execution/evm/common.go | 40 ------- execution/evm/stack.go | 20 ++++ execution/evm/vm.go | 202 ++++++++++++--------------------- execution/execution.go | 18 +-- logging/config/filter_test.go | 16 +++ logging/lifecycle/lifecycle.go | 4 +- 10 files changed, 329 insertions(+), 183 deletions(-) delete mode 100644 execution/evm/common.go diff --git a/binary/integer.go b/binary/integer.go index f8651484..a00c0705 100644 --- a/binary/integer.go +++ b/binary/integer.go @@ -17,10 +17,14 @@ package binary import ( "encoding/binary" "math" + "math/big" "sort" ) -const Uint64TopBitMask = 1 << 63 +var big1 = big.NewInt(1) +var tt256 = new(big.Int).Lsh(big1, 256) +var tt256m1 = new(big.Int).Sub(new(big.Int).Lsh(big1, 256), big1) +var tt255 = new(big.Int).Lsh(big1, 255) // Sort for []uint64 @@ -75,3 +79,42 @@ func GetInt64BE(src []byte) int64 { func IsUint64SumOverflow(a, b uint64) bool { return math.MaxUint64-a < b } + +// + +// Converts a possibly negative big int x into a positive big int encoding a twos complement representation of x +// truncated to 32 bytes +func U256(x *big.Int) *big.Int { + // Note that the And operation induces big.Int to hold a positive representation of a negative number + return new(big.Int).And(x, tt256m1) +} + +// Interprets a positive big.Int as a 256-bit two's complement signed integer +func S256(x *big.Int) *big.Int { + // Sign bit not set, value is its positive self + if x.Cmp(tt255) < 0 { + return x + } else { + // negative value is represented + return new(big.Int).Sub(x, tt256) + } +} + +// Treats the positive big int x as if it contains an embedded a back + 1 byte signed integer in its least significant +// bits and extends that sign +func SignExtend(back uint64, x *big.Int) *big.Int { + // we assume x contains a signed integer of back + 1 bytes width + // most significant bit of the back'th byte, + signBit := back*8 + 7 + // single bit set at sign bit position + mask := new(big.Int).Lsh(big1, uint(signBit)) + // all bits below sign bit set to 1 all above (including sign bit) set to 0 + mask.Sub(mask, big1) + if x.Bit(int(signBit)) == 1 { + // Number represented is negative - set all bits above sign bit (including sign bit) + return x.Or(x, mask.Not(mask)) + } else { + // Number represented is positive - clear all bits above sign bit (including sign bit) + return x.And(x, mask) + } +} diff --git a/binary/integer_test.go b/binary/integer_test.go index e530c5a7..c0c1533f 100644 --- a/binary/integer_test.go +++ b/binary/integer_test.go @@ -2,9 +2,16 @@ package binary import ( "math" + "math/big" "testing" + "strconv" + "strings" + + "fmt" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestIsUint64SumOverflow(t *testing.T) { @@ -17,3 +24,154 @@ func TestIsUint64SumOverflow(t *testing.T) { assert.True(t, IsUint64SumOverflow(a+b, 1)) assert.True(t, IsUint64SumOverflow(a+1, b+1)) } + +func zero() *big.Int { + return new(big.Int) +} + +var big2E255 = zero().Lsh(big1, 255) +var big2E256 = zero().Lsh(big1, 256) +var big2E257 = zero().Lsh(big1, 257) + +func TestU256(t *testing.T) { + expected := big2E255 + encoded := U256(expected) + assertBigIntEqual(t, expected, encoded, "Top bit set big int is fixed point") + + expected = zero() + encoded = U256(big2E256) + assertBigIntEqual(t, expected, encoded, "Ceiling bit is exact overflow") + + expected = zero().Sub(big2E256, big1) + encoded = U256(expected) + assertBigIntEqual(t, expected, encoded, "Max unsigned big int is fixed point") + + expected = big1 + encoded = U256(zero().Add(big2E256, big1)) + assertBigIntEqual(t, expected, encoded, "Overflow by one") + + expected = big2E255 + encoded = U256(zero().Add(big2E256, big2E255)) + assertBigIntEqual(t, expected, encoded, "Overflow by doubling") + + negative := big.NewInt(-234) + assert.Equal(t, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16", + fmt.Sprintf("%X", U256(negative).Bytes()), "byte representation is twos complement") + + expected, ok := zero().SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16", 16) + require.True(t, ok) + assertBigIntEqual(t, expected, U256(negative), "Bytes representation should be twos complement") + + expected = zero() + encoded = U256(zero().Neg(big2E256)) + assertBigIntEqual(t, expected, encoded, "Floor bit is overflow") + + expected = big2E255 + encoded = zero().Neg(big2E255) + encoded = U256(encoded) + assertBigIntEqual(t, expected, encoded, "2**255 is Self complement") + + expected = zero().Add(big2E255, big1) + encoded = zero().Neg(big2E255) + encoded = encoded.Add(encoded, big1) + encoded = U256(encoded) + assertBigIntEqual(t, expected, encoded, "") +} + +func TestS256(t *testing.T) { + expected := zero().Neg(big2E255) + signed := S256(big2E255) + assertBigIntEqual(t, expected, signed, "Should be negative") + + expected = zero().Sub(big2E255, big1) + signed = S256(expected) + assertBigIntEqual(t, expected, signed, "Maximum twos complement positive is fixed point") + + expected = zero() + signed = S256(expected) + assertBigIntEqual(t, expected, signed, "Twos complement of zero is fixed poount") + + // Technically undefined but let's not let that stop us + expected = zero().Sub(big2E257, big2E256) + signed = S256(big2E257) + assertBigIntEqual(t, expected, signed, "Out of twos complement bounds") +} + +func TestSignExtend(t *testing.T) { + assertSignExtend(t, 16, 0, + "0000 0000 1001 0000", + "1111 1111 1001 0000") + + assertSignExtend(t, 16, 1, + "1001 0000", + "1001 0000") + + assertSignExtend(t, 32, 2, + "0000 0000 1000 0000 1101 0011 1001 0000", + "1111 1111 1000 0000 1101 0011 1001 0000") + + assertSignExtend(t, 32, 2, + "0000 0000 0000 0000 1101 0011 1001 0000", + "0000 0000 0000 0000 1101 0011 1001 0000") + + // Here we have a stray bit set in the 4th most significant byte that gets wiped out + assertSignExtend(t, 32, 2, + "0001 0000 0000 0000 1101 0011 1001 0000", + "0000 0000 0000 0000 1101 0011 1001 0000") + assertSignExtend(t, 32, 2, + "0001 0000 1000 0000 1101 0011 1001 0000", + "1111 1111 1000 0000 1101 0011 1001 0000") + + assertSignExtend(t, 32, 3, + "0001 0000 1000 0000 1101 0011 1001 0000", + "0001 0000 1000 0000 1101 0011 1001 0000") + + assertSignExtend(t, 32, 3, + "1001 0000 1000 0000 1101 0011 1001 0000", + "1001 0000 1000 0000 1101 0011 1001 0000") + + assertSignExtend(t, 64, 3, + "0000 0000 0000 0000 0000 0000 0000 0000 1001 0000 1000 0000 1101 0011 1001 0000", + "1111 1111 1111 1111 1111 1111 1111 1111 1001 0000 1000 0000 1101 0011 1001 0000") + + assertSignExtend(t, 64, 3, + "0000 0000 0000 0000 0000 0000 0000 0000 0001 0000 1000 0000 1101 0011 1001 0000", + "0000 0000 0000 0000 0000 0000 0000 0000 0001 0000 1000 0000 1101 0011 1001 0000") +} + +func assertSignExtend(t *testing.T, bitSize int, bytesBack uint64, inputString, expectedString string) bool { + input := intFromString(t, bitSize, inputString) + expected := intFromString(t, bitSize, expectedString) + //actual := SignExtend(big.NewInt(bytesBack), big.NewInt(int64(input))) + actual := SignExtend(bytesBack, big.NewInt(int64(input))) + var ret bool + switch bitSize { + case 8: + ret = assert.Equal(t, uint8(expected), uint8(actual.Int64())) + case 16: + ret = assert.Equal(t, uint16(expected), uint16(actual.Int64())) + case 32: + ret = assert.Equal(t, uint32(expected), uint32(actual.Int64())) + case 64: + ret = assert.Equal(t, uint64(expected), uint64(actual.Int64())) + default: + t.Fatalf("Cannot test SignExtend for non-Go-native bit size %v", bitSize) + return false + } + if !ret { + + } + return ret +} + +func assertBigIntEqual(t *testing.T, expected, actual *big.Int, messages ...string) bool { + return assert.True(t, expected.Cmp(actual) == 0, fmt.Sprintf("%s - not equal:\n%v (expected)\n%v (actual)", + strings.Join(messages, " "), expected, actual)) +} + +func intFromString(t *testing.T, bitSize int, binStrings ...string) uint64 { + binaryString := strings.Replace(strings.Join(binStrings, ""), " ", "", -1) + i, err := strconv.ParseUint(binaryString, 2, bitSize) + require.NoError(t, err) + return i +} diff --git a/binary/word256.go b/binary/word256.go index 6d11fe9a..02a90581 100644 --- a/binary/word256.go +++ b/binary/word256.go @@ -16,16 +16,19 @@ package binary import ( "bytes" + "math/big" "sort" ) var ( Zero256 = Word256{} - One256 = Word256{1} + One256 = LeftPadWord256([]byte{1}) ) const Word256Length = 32 +var BigWord256Length = big.NewInt(Word256Length) + var trimCutSet = string([]byte{0}) type Word256 [Word256Length]byte diff --git a/binary/word256_test.go b/binary/word256_test.go index 055d3910..78aaeb59 100644 --- a/binary/word256_test.go +++ b/binary/word256_test.go @@ -37,3 +37,7 @@ func TestLeftPadWord256(t *testing.T) { }, LeftPadWord256([]byte{1, 2, 3})) } + +func TestOne256(t *testing.T) { + assert.Equal(t, Int64ToWord256(1), One256) +} diff --git a/execution/evm/common.go b/execution/evm/common.go deleted file mode 100644 index e8fb7444..00000000 --- a/execution/evm/common.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2017 Monax Industries Limited -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package evm - -import ( - "math/big" -) - -// To256 -// -// "cast" the big int to a 256 big int (i.e., limit to) -var tt256 = new(big.Int).Lsh(big.NewInt(1), 256) -var tt256m1 = new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(1)) -var tt255 = new(big.Int).Lsh(big.NewInt(1), 255) - -func U256(x *big.Int) *big.Int { - x.And(x, tt256m1) - return x -} - -func S256(x *big.Int) *big.Int { - if x.Cmp(tt255) < 0 { - return x - } else { - // We don't want to modify x, ever - return new(big.Int).Sub(x, tt256) - } -} diff --git a/execution/evm/stack.go b/execution/evm/stack.go index 0d8a8f3f..2db80183 100644 --- a/execution/evm/stack.go +++ b/execution/evm/stack.go @@ -17,6 +17,8 @@ package evm import ( "fmt" + "math/big" + . "github.com/hyperledger/burrow/binary" ) @@ -78,6 +80,15 @@ func (st *Stack) PushU64(i uint64) { st.Push(Uint64ToWord256(i)) } +// Pushes the bigInt as a Word256 encoding negative values in 32-byte twos complement and returns the encoded result +func (st *Stack) PushBigInt(bigInt *big.Int) Word256 { + word := LeftPadWord256(U256(bigInt).Bytes()) + st.Push(word) + return word +} + +// Pops + func (st *Stack) Pop() Word256 { st.useGas(GasStackOp) if st.ptr == 0 { @@ -102,6 +113,15 @@ func (st *Stack) PopU64() uint64 { return Uint64FromWord256(d) } +func (st *Stack) PopBigIntSigned() *big.Int { + return S256(st.PopBigInt()) +} + +func (st *Stack) PopBigInt() *big.Int { + d := st.Pop() + return new(big.Int).SetBytes(d[:]) +} + func (st *Stack) Len() int { return st.ptr } diff --git a/execution/evm/vm.go b/execution/evm/vm.go index f20efce7..3513e5ac 100644 --- a/execution/evm/vm.go +++ b/execution/evm/vm.go @@ -18,7 +18,6 @@ import ( "bytes" "errors" "fmt" - "math/big" acm "github.com/hyperledger/burrow/account" . "github.com/hyperledger/burrow/binary" @@ -220,202 +219,147 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value switch op { case ADD: // 0x01 - x, y := stack.Pop(), stack.Pop() - xb := new(big.Int).SetBytes(x[:]) - yb := new(big.Int).SetBytes(y[:]) - sum := new(big.Int).Add(xb, yb) - res := LeftPadWord256(U256(sum).Bytes()) - stack.Push(res) - vm.Debugf(" %v + %v = %v (%X)\n", xb, yb, sum, res) + x, y := stack.PopBigInt(), stack.PopBigInt() + sum := x.Add(x, y) + res := stack.PushBigInt(sum) + vm.Debugf(" %v + %v = %v (%X)\n", x, y, sum, res) case MUL: // 0x02 - x, y := stack.Pop(), stack.Pop() - xb := new(big.Int).SetBytes(x[:]) - yb := new(big.Int).SetBytes(y[:]) - prod := new(big.Int).Mul(xb, yb) - res := LeftPadWord256(U256(prod).Bytes()) - stack.Push(res) - vm.Debugf(" %v * %v = %v (%X)\n", xb, yb, prod, res) + x, y := stack.PopBigInt(), stack.PopBigInt() + prod := x.Mul(x, y) + res := stack.PushBigInt(prod) + vm.Debugf(" %v * %v = %v (%X)\n", x, y, prod, res) case SUB: // 0x03 - x, y := stack.Pop(), stack.Pop() - xb := new(big.Int).SetBytes(x[:]) - yb := new(big.Int).SetBytes(y[:]) - diff := new(big.Int).Sub(xb, yb) - res := LeftPadWord256(U256(diff).Bytes()) - stack.Push(res) - vm.Debugf(" %v - %v = %v (%X)\n", xb, yb, diff, res) + x, y := stack.PopBigInt(), stack.PopBigInt() + diff := x.Sub(x, y) + res := stack.PushBigInt(diff) + vm.Debugf(" %v - %v = %v (%X)\n", x, y, diff, res) case DIV: // 0x04 - x, y := stack.Pop(), stack.Pop() - if y.IsZero() { + x, y := stack.PopBigInt(), stack.PopBigInt() + if y.Sign() == 0 { stack.Push(Zero256) vm.Debugf(" %x / %x = %v\n", x, y, 0) } else { - xb := new(big.Int).SetBytes(x[:]) - yb := new(big.Int).SetBytes(y[:]) - div := new(big.Int).Div(xb, yb) - res := LeftPadWord256(U256(div).Bytes()) - stack.Push(res) - vm.Debugf(" %v / %v = %v (%X)\n", xb, yb, div, res) + div := x.Div(x, y) + res := stack.PushBigInt(div) + vm.Debugf(" %v / %v = %v (%X)\n", x, y, div, res) } case SDIV: // 0x05 - x, y := stack.Pop(), stack.Pop() - if y.IsZero() { + x, y := stack.PopBigIntSigned(), stack.PopBigIntSigned() + if y.Sign() == 0 { stack.Push(Zero256) vm.Debugf(" %x / %x = %v\n", x, y, 0) } else { - xb := S256(new(big.Int).SetBytes(x[:])) - yb := S256(new(big.Int).SetBytes(y[:])) - div := new(big.Int).Div(xb, yb) - res := LeftPadWord256(U256(div).Bytes()) - stack.Push(res) - vm.Debugf(" %v / %v = %v (%X)\n", xb, yb, div, res) + div := x.Div(x, y) + res := stack.PushBigInt(div) + vm.Debugf(" %v / %v = %v (%X)\n", x, y, div, res) } case MOD: // 0x06 - x, y := stack.Pop(), stack.Pop() - if y.IsZero() { + x, y := stack.PopBigInt(), stack.PopBigInt() + if y.Sign() == 0 { stack.Push(Zero256) vm.Debugf(" %v %% %v = %v\n", x, y, 0) } else { - xb := new(big.Int).SetBytes(x[:]) - yb := new(big.Int).SetBytes(y[:]) - mod := new(big.Int).Mod(xb, yb) - res := LeftPadWord256(U256(mod).Bytes()) - stack.Push(res) - vm.Debugf(" %v %% %v = %v (%X)\n", xb, yb, mod, res) + mod := x.Mod(x, y) + res := stack.PushBigInt(mod) + vm.Debugf(" %v %% %v = %v (%X)\n", x, y, mod, res) } case SMOD: // 0x07 - x, y := stack.Pop(), stack.Pop() - if y.IsZero() { + x, y := stack.PopBigIntSigned(), stack.PopBigIntSigned() + if y.Sign() == 0 { stack.Push(Zero256) vm.Debugf(" %v %% %v = %v\n", x, y, 0) } else { - xb := S256(new(big.Int).SetBytes(x[:])) - yb := S256(new(big.Int).SetBytes(y[:])) - mod := new(big.Int).Mod(xb, yb) - res := LeftPadWord256(U256(mod).Bytes()) - stack.Push(res) - vm.Debugf(" %v %% %v = %v (%X)\n", xb, yb, mod, res) + mod := x.Mod(x, y) + res := stack.PushBigInt(mod) + vm.Debugf(" %v %% %v = %v (%X)\n", x, y, mod, res) } case ADDMOD: // 0x08 - x, y, z := stack.Pop(), stack.Pop(), stack.Pop() - if z.IsZero() { + x, y, z := stack.PopBigInt(), stack.PopBigInt(), stack.PopBigInt() + if z.Sign() == 0 { stack.Push(Zero256) vm.Debugf(" %v %% %v = %v\n", x, y, 0) } else { - xb := new(big.Int).SetBytes(x[:]) - yb := new(big.Int).SetBytes(y[:]) - zb := new(big.Int).SetBytes(z[:]) - add := new(big.Int).Add(xb, yb) - mod := new(big.Int).Mod(add, zb) - res := LeftPadWord256(U256(mod).Bytes()) - stack.Push(res) - vm.Debugf(" %v + %v %% %v = %v (%X)\n", - xb, yb, zb, mod, res) + add := x.Add(x, y) + mod := add.Mod(add, z) + res := stack.PushBigInt(mod) + vm.Debugf(" %v + %v %% %v = %v (%X)\n", x, y, z, mod, res) } case MULMOD: // 0x09 - x, y, z := stack.Pop(), stack.Pop(), stack.Pop() - if z.IsZero() { + x, y, z := stack.PopBigInt(), stack.PopBigInt(), stack.PopBigInt() + if z.Sign() == 0 { stack.Push(Zero256) vm.Debugf(" %v %% %v = %v\n", x, y, 0) } else { - xb := new(big.Int).SetBytes(x[:]) - yb := new(big.Int).SetBytes(y[:]) - zb := new(big.Int).SetBytes(z[:]) - mul := new(big.Int).Mul(xb, yb) - mod := new(big.Int).Mod(mul, zb) - res := LeftPadWord256(U256(mod).Bytes()) - stack.Push(res) - vm.Debugf(" %v * %v %% %v = %v (%X)\n", - xb, yb, zb, mod, res) + mul := x.Mul(x, y) + mod := mul.Mod(mul, z) + res := stack.PushBigInt(mod) + vm.Debugf(" %v * %v %% %v = %v (%X)\n", x, y, z, mod, res) } case EXP: // 0x0A - x, y := stack.Pop(), stack.Pop() - xb := new(big.Int).SetBytes(x[:]) - yb := new(big.Int).SetBytes(y[:]) - pow := new(big.Int).Exp(xb, yb, big.NewInt(0)) - res := LeftPadWord256(U256(pow).Bytes()) - stack.Push(res) - vm.Debugf(" %v ** %v = %v (%X)\n", xb, yb, pow, res) + x, y := stack.PopBigInt(), stack.PopBigInt() + pow := x.Exp(x, y, nil) + res := stack.PushBigInt(pow) + vm.Debugf(" %v ** %v = %v (%X)\n", x, y, pow, res) case SIGNEXTEND: // 0x0B - back := stack.Pop() - backb := new(big.Int).SetBytes(back[:]) - if backb.Cmp(big.NewInt(31)) < 0 { - bit := uint(backb.Uint64()*8 + 7) - num := stack.Pop() - numb := new(big.Int).SetBytes(num[:]) - mask := new(big.Int).Lsh(big.NewInt(1), bit) - mask.Sub(mask, big.NewInt(1)) - if numb.Bit(int(bit)) == 1 { - numb.Or(numb, mask.Not(mask)) - } else { - numb.Add(numb, mask) - } - res := LeftPadWord256(U256(numb).Bytes()) - vm.Debugf(" = %v (%X)", numb, res) - stack.Push(res) + back := stack.PopU64() + if back < Word256Length-1 { + stack.PushBigInt(SignExtend(back, stack.PopBigInt())) } case LT: // 0x10 - x, y := stack.Pop(), stack.Pop() - xb := new(big.Int).SetBytes(x[:]) - yb := new(big.Int).SetBytes(y[:]) - if xb.Cmp(yb) < 0 { - stack.Push64(1) - vm.Debugf(" %v < %v = %v\n", xb, yb, 1) + x, y := stack.PopBigInt(), stack.PopBigInt() + if x.Cmp(y) < 0 { + stack.Push(One256) + vm.Debugf(" %v < %v = %v\n", x, y, 1) } else { stack.Push(Zero256) - vm.Debugf(" %v < %v = %v\n", xb, yb, 0) + vm.Debugf(" %v < %v = %v\n", x, y, 0) } case GT: // 0x11 - x, y := stack.Pop(), stack.Pop() - xb := new(big.Int).SetBytes(x[:]) - yb := new(big.Int).SetBytes(y[:]) - if xb.Cmp(yb) > 0 { - stack.Push64(1) - vm.Debugf(" %v > %v = %v\n", xb, yb, 1) + x, y := stack.PopBigInt(), stack.PopBigInt() + if x.Cmp(y) > 0 { + stack.Push(One256) + vm.Debugf(" %v > %v = %v\n", x, y, 1) } else { stack.Push(Zero256) - vm.Debugf(" %v > %v = %v\n", xb, yb, 0) + vm.Debugf(" %v > %v = %v\n", x, y, 0) } case SLT: // 0x12 - x, y := stack.Pop(), stack.Pop() - xb := S256(new(big.Int).SetBytes(x[:])) - yb := S256(new(big.Int).SetBytes(y[:])) - if xb.Cmp(yb) < 0 { - stack.Push64(1) - vm.Debugf(" %v < %v = %v\n", xb, yb, 1) + x, y := stack.PopBigIntSigned(), stack.PopBigIntSigned() + if x.Cmp(y) < 0 { + stack.Push(One256) + vm.Debugf(" %v < %v = %v\n", x, y, 1) } else { stack.Push(Zero256) - vm.Debugf(" %v < %v = %v\n", xb, yb, 0) + vm.Debugf(" %v < %v = %v\n", x, y, 0) } case SGT: // 0x13 - x, y := stack.Pop(), stack.Pop() - xb := S256(new(big.Int).SetBytes(x[:])) - yb := S256(new(big.Int).SetBytes(y[:])) - if xb.Cmp(yb) > 0 { - stack.Push64(1) - vm.Debugf(" %v > %v = %v\n", xb, yb, 1) + x, y := stack.PopBigIntSigned(), stack.PopBigIntSigned() + if x.Cmp(y) > 0 { + stack.Push(One256) + vm.Debugf(" %v > %v = %v\n", x, y, 1) } else { stack.Push(Zero256) - vm.Debugf(" %v > %v = %v\n", xb, yb, 0) + vm.Debugf(" %v > %v = %v\n", x, y, 0) } case EQ: // 0x14 x, y := stack.Pop(), stack.Pop() if bytes.Equal(x[:], y[:]) { - stack.Push64(1) + stack.Push(One256) vm.Debugf(" %X == %X = %v\n", x, y, 1) } else { stack.Push(Zero256) @@ -425,7 +369,7 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value case ISZERO: // 0x15 x := stack.Pop() if x.IsZero() { - stack.Push64(1) + stack.Push(One256) vm.Debugf(" %X == 0 = %v\n", x, 1) } else { stack.Push(Zero256) diff --git a/execution/execution.go b/execution/execution.go index 09fd8c9f..ed822a71 100644 --- a/execution/execution.go +++ b/execution/execution.go @@ -301,7 +301,6 @@ func (exe *executor) Execute(tx txs.Tx) error { // The logic in runCall MUST NOT return. if exe.runCall { - // VM call variables var ( gas uint64 = tx.GasLimit @@ -329,11 +328,11 @@ func (exe *executor) Execute(tx txs.Tx) error { // that will take your fees if outAcc == nil { logging.InfoMsg(logger, "Call to address that does not exist", - "caller_address", inAcc.Address, + "caller_address", inAcc.Address(), "callee_address", tx.Address) } else { logging.InfoMsg(logger, "Call to address that holds no code", - "caller_address", inAcc.Address, + "caller_address", inAcc.Address(), "callee_address", tx.Address) } err = txs.ErrTxInvalidAddress @@ -344,16 +343,17 @@ func (exe *executor) Execute(tx txs.Tx) error { if createContract { // We already checked for permission callee = evm.DeriveNewAccount(caller, permission.GlobalAccountPermissions(exe.state)) - logging.TraceMsg(logger, "Created new contract", - "contract_address", callee.Address, - "contract_code", callee.Code) code = tx.Data + logging.TraceMsg(logger, "Creating new contract", + "contract_address", callee.Address(), + "init_code", code) } else { callee = acm.AsMutableAccount(outAcc) - logging.TraceMsg(logger, "Calling existing contract", - "contract_address", callee.Address, - "contract_code", callee.Code) code = callee.Code() + logging.TraceMsg(logger, "Calling existing contract", + "contract_address", callee.Address(), + "input", tx.Data, + "contract_code", code) } logger.Trace("callee", callee.Address().String()) diff --git a/logging/config/filter_test.go b/logging/config/filter_test.go index 5e847acb..9602fa71 100644 --- a/logging/config/filter_test.go +++ b/logging/config/filter_test.go @@ -115,5 +115,21 @@ func TestIncludeAnyFilterPredicate(t *testing.T) { assert.False(t, fp([]interface{}{"Foo", "bar", "Shoes", 3427})) assert.False(t, fp([]interface{}{"Foo", "bar", "Shoes", 42, "Bosh", "Bish"})) assert.False(t, fp([]interface{}{"Food", 0.2, "Shoes", 42})) +} + +func TestKeyOnlyPredicate(t *testing.T) { + fc := &FilterConfig{ + FilterMode: IncludeWhenAnyMatches, + Predicates: []*KeyValuePredicateConfig{ + { + KeyRegex: "Bosh", + }, + }, + } + fp, err := BuildFilterPredicate(fc) + assert.NoError(t, err) + assert.True(t, fp([]interface{}{"Foo", "bar", "Shoes", 3427})) + assert.False(t, fp([]interface{}{"Foo", "bar", "Shoes", 42, "Bosh", "Bish"})) + assert.True(t, fp([]interface{}{"Food", 0.2, "Shoes", 42})) } diff --git a/logging/lifecycle/lifecycle.go b/logging/lifecycle/lifecycle.go index 8d9428fd..e68a2602 100644 --- a/logging/lifecycle/lifecycle.go +++ b/logging/lifecycle/lifecycle.go @@ -57,9 +57,7 @@ func NewLoggerFromLoggingConfig(loggingConfig *config.LoggingConfig) (types.Info go func() { err := <-errCh.Out() if err != nil { - logger.Info("logging_error", err, - "logging_config", loggingConfig.RootTOMLString(), - "logger", fmt.Sprintf("%#v", logger)) + fmt.Printf("Logging error: %v", err) } }() -- GitLab