From febf163097c4cd489c13acf8fd98a9e79738153a Mon Sep 17 00:00:00 2001 From: smblucker <smblucker@outlook.com> Date: Mon, 14 May 2018 16:40:30 -0400 Subject: [PATCH] Implementing shl, shr, and sar opcodes Signed-off-by: smblucker <smblucker@outlook.com> --- binary/integer.go | 1 + execution/evm/vm.go | 44 +++- execution/evm/vm_test.go | 470 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 514 insertions(+), 1 deletion(-) diff --git a/binary/integer.go b/binary/integer.go index a00c0705..cd57bf3a 100644 --- a/binary/integer.go +++ b/binary/integer.go @@ -22,6 +22,7 @@ import ( ) var big1 = big.NewInt(1) +var Big256 = big.NewInt(256) 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) diff --git a/execution/evm/vm.go b/execution/evm/vm.go index aca67567..c0191bf6 100644 --- a/execution/evm/vm.go +++ b/execution/evm/vm.go @@ -496,6 +496,48 @@ func (vm *VM) call(caller acm.Account, callee acm.MutableAccount, code, input [] stack.Push64(int64(res)) vm.Debugf(" => 0x%X\n", res) + case SHL: //0x1B + shift, x := stack.PopBigInt(), stack.PopBigInt() + + if shift.Cmp(Big256) >= 0 { + reset := big.NewInt(0) + stack.PushBigInt(reset) + vm.Debugf(" %v << %v = %v\n", x, shift, reset) + } else { + shiftedValue := x.Lsh(x, uint(shift.Uint64())) + stack.PushBigInt(shiftedValue) + vm.Debugf(" %v << %v = %v\n", x, shift, shiftedValue) + } + + case SHR: //0x1C + shift, x := stack.PopBigInt(), stack.PopBigInt() + + if shift.Cmp(Big256) >= 0 { + reset := big.NewInt(0) + stack.PushBigInt(reset) + vm.Debugf(" %v << %v = %v\n", x, shift, reset) + } else { + shiftedValue := x.Rsh(x, uint(shift.Uint64())) + stack.PushBigInt(shiftedValue) + vm.Debugf(" %v << %v = %v\n", x, shift, shiftedValue) + } + + case SAR: //0x1D + shift, x := stack.PopBigInt(), stack.PopBigIntSigned() + + if shift.Cmp(Big256) >= 0 { + reset := big.NewInt(0) + if x.Sign() < 0 { + reset.SetInt64(-1) + } + stack.PushBigInt(reset) + vm.Debugf(" %v << %v = %v\n", x, shift, reset) + } else { + shiftedValue := x.Rsh(x, uint(shift.Uint64())) + stack.PushBigInt(shiftedValue) + vm.Debugf(" %v << %v = %v\n", x, shift, shiftedValue) + } + case SHA3: // 0x20 if useGasNegative(gas, GasSha3, &err) { return nil, err @@ -1111,7 +1153,7 @@ func (vm *VM) call(caller acm.Account, callee acm.MutableAccount, code, input [] case STOP: // 0x00 return nil, nil - case STATICCALL, SHL, SHR, SAR: + case STATICCALL: return nil, fmt.Errorf("%s not yet implemented", op.Name()) default: vm.Debugf("(pc) %-3v Unknown opcode %X\n", pc, op) diff --git a/execution/evm/vm_test.go b/execution/evm/vm_test.go index ffa5454c..b885d266 100644 --- a/execution/evm/vm_test.go +++ b/execution/evm/vm_test.go @@ -95,6 +95,476 @@ func TestVM(t *testing.T) { } } +func TestSHL(t *testing.T) { + ourVm := NewVM(newAppState(), newParams(), acm.ZeroAddress, nil, logger) + account1 := newAccount(1) + account2 := newAccount(1, 0, 1) + + var gas uint64 = 100000 + + //Shift left 0 + bytecode := MustSplice(PUSH1, 0x01, PUSH1, 0x00, SHL, return1()) + output, err := ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + value := []uint8([]byte{0x1}) + expected := LeftPadBytes(value, 32) + assert.Equal(t, expected, output) + + t.Logf("Result: %v == %v\n", output, expected) + + if err != nil { + t.Fatal(err) + } + + //Alternative shift left 0 + bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x00, SHL, return1()) + output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}) + + assert.Equal(t, expected, output) + + t.Logf("Result: %v == %v\n", output, expected) + + if err != nil { + t.Fatal(err) + } + + //Shift left 1 + bytecode = MustSplice(PUSH1, 0x01, PUSH1, 0x01, SHL, return1()) + output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + value = []uint8([]byte{0x2}) + expected = LeftPadBytes(value, 32) + assert.Equal(t, expected, output) + + t.Logf("Result: %v == %v\n", output, expected) + + if err != nil { + t.Fatal(err) + } + + //Alternative shift left 1 + bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x01, SHL, return1()) + output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE}) + + assert.Equal(t, expected, output) + + t.Logf("Result: %v == %v\n", output, expected) + + if err != nil { + t.Fatal(err) + } + + //Alternative shift left 1 + bytecode = MustSplice(PUSH32, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x01, SHL, return1()) + output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE}) + + assert.Equal(t, expected, output) + + t.Logf("Result: %v == %v\n", output, expected) + + if err != nil { + t.Fatal(err) + } + + //Shift left 255 + bytecode = MustSplice(PUSH1, 0x01, PUSH1, 0xFF, SHL, return1()) + output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + value = []uint8([]byte{0x80}) + expected = RightPadBytes(value, 32) + assert.Equal(t, expected, output) + + t.Logf("Result: %v == %v\n", output, expected) + + if err != nil { + t.Fatal(err) + } + + //Alternative shift left 255 + bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0xFF, SHL, return1()) + output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + value = []uint8([]byte{0x80}) + expected = RightPadBytes(value, 32) + assert.Equal(t, expected, output) + + t.Logf("Result: %v == %v\n", output, expected) + + if err != nil { + t.Fatal(err) + } + + //Shift left 256 (overflow) + bytecode = MustSplice(PUSH1, 0x01, PUSH2, 0x01, 0x00, SHL, return1()) + output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + value = []uint8([]byte{0x00}) + expected = LeftPadBytes(value, 32) + assert.Equal(t, expected, output) + + t.Logf("Result: %v == %v\n", output, expected) + + if err != nil { + t.Fatal(err) + } + + //Alternative shift left 256 (overflow) + bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH2, 0x01, 0x00, SHL, + return1()) + output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + value = []uint8([]byte{0x00}) + expected = LeftPadBytes(value, 32) + assert.Equal(t, expected, output) + + t.Logf("Result: %v == %v\n", output, expected) + + if err != nil { + t.Fatal(err) + } + + //Shift left 257 (overflow) + bytecode = MustSplice(PUSH1, 0x01, PUSH2, 0x01, 0x01, SHL, return1()) + output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + value = []uint8([]byte{0x00}) + expected = LeftPadBytes(value, 32) + assert.Equal(t, expected, output) + + t.Logf("Result: %v == %v\n", output, expected) + + if err != nil { + t.Fatal(err) + } + +} + +func TestSHR(t *testing.T) { + ourVm := NewVM(newAppState(), newParams(), acm.ZeroAddress, nil, logger) + account1 := newAccount(1) + account2 := newAccount(1, 0, 1) + + var gas uint64 = 100000 + + //Shift right 0 + bytecode := MustSplice(PUSH1, 0x01, PUSH1, 0x00, SHR, return1()) + output, err := ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + value := []uint8([]byte{0x1}) + expected := LeftPadBytes(value, 32) + assert.Equal(t, expected, output) + + t.Logf("Result: %v == %v\n", output, expected) + + if err != nil { + t.Fatal(err) + } + + //Alternative shift right 0 + bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x00, SHR, return1()) + output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}) + + assert.Equal(t, expected, output) + + t.Logf("Result: %v == %v\n", output, expected) + + if err != nil { + t.Fatal(err) + } + + //Shift right 1 + bytecode = MustSplice(PUSH1, 0x01, PUSH1, 0x01, SHR, return1()) + output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + value = []uint8([]byte{0x00}) + expected = LeftPadBytes(value, 32) + assert.Equal(t, expected, output) + + t.Logf("Result: %v == %v\n", output, expected) + + if err != nil { + t.Fatal(err) + } + + //Alternative shift right 1 + bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH1, 0x01, SHR, return1()) + output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + value = []uint8([]byte{0x40}) + expected = RightPadBytes(value, 32) + assert.Equal(t, expected, output) + + t.Logf("Result: %v == %v\n", output, expected) + + if err != nil { + t.Fatal(err) + } + + //Alternative shift right 1 + bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x01, SHR, return1()) + output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + expected = []uint8([]byte{0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}) + + assert.Equal(t, expected, output) + + t.Logf("Result: %v == %v\n", output, expected) + + if err != nil { + t.Fatal(err) + } + + //Shift right 255 + bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH1, 0xFF, SHR, return1()) + output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + value = []uint8([]byte{0x1}) + expected = LeftPadBytes(value, 32) + assert.Equal(t, expected, output) + + t.Logf("Result: %v == %v\n", output, expected) + + if err != nil { + t.Fatal(err) + } + + //Alternative shift right 255 + bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0xFF, SHR, return1()) + output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + value = []uint8([]byte{0x1}) + expected = LeftPadBytes(value, 32) + assert.Equal(t, expected, output) + + t.Logf("Result: %v == %v\n", output, expected) + + if err != nil { + t.Fatal(err) + } + + //Shift right 256 (underflow) + bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH2, 0x01, 0x00, SHR, + return1()) + output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + value = []uint8([]byte{0x00}) + expected = LeftPadBytes(value, 32) + assert.Equal(t, expected, output) + + t.Logf("Result: %v == %v\n", output, expected) + + if err != nil { + t.Fatal(err) + } + + //Alternative shift right 256 (underflow) + bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH2, 0x01, 0x00, SHR, + return1()) + output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + value = []uint8([]byte{0x00}) + expected = LeftPadBytes(value, 32) + assert.Equal(t, expected, output) + + t.Logf("Result: %v == %v\n", output, expected) + + if err != nil { + t.Fatal(err) + } + + //Shift right 257 (underflow) + bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH2, 0x01, 0x01, SHR, + return1()) + output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + value = []uint8([]byte{0x00}) + expected = LeftPadBytes(value, 32) + assert.Equal(t, expected, output) + + t.Logf("Result: %v == %v\n", output, expected) + + if err != nil { + t.Fatal(err) + } + +} + +func TestSAR(t *testing.T) { + ourVm := NewVM(newAppState(), newParams(), acm.ZeroAddress, nil, logger) + account1 := newAccount(1) + account2 := newAccount(1, 0, 1) + + var gas uint64 = 100000 + + //Shift arith right 0 + bytecode := MustSplice(PUSH1, 0x01, PUSH1, 0x00, SAR, return1()) + output, err := ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + value := []uint8([]byte{0x1}) + expected := LeftPadBytes(value, 32) + assert.Equal(t, expected, output) + + t.Logf("Result: %v == %v\n", output, expected) + + if err != nil { + t.Fatal(err) + } + + //Alternative arith shift right 0 + bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x00, SAR, return1()) + output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}) + + assert.Equal(t, expected, output) + + t.Logf("Result: %v == %v\n", output, expected) + + if err != nil { + t.Fatal(err) + } + + //Shift arith right 1 + bytecode = MustSplice(PUSH1, 0x01, PUSH1, 0x01, SAR, return1()) + output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + value = []uint8([]byte{0x00}) + expected = LeftPadBytes(value, 32) + assert.Equal(t, expected, output) + + t.Logf("Result: %v == %v\n", output, expected) + + if err != nil { + t.Fatal(err) + } + + //Alternative shift arith right 1 + bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH1, 0x01, SAR, return1()) + output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + value = []uint8([]byte{0xc0}) + expected = RightPadBytes(value, 32) + assert.Equal(t, expected, output) + + t.Logf("Result: %v == %v\n", output, expected) + + if err != nil { + t.Fatal(err) + } + + //Alternative shift arith right 1 + bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x01, SAR, return1()) + output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}) + + assert.Equal(t, expected, output) + + t.Logf("Result: %v == %v\n", output, expected) + + if err != nil { + t.Fatal(err) + } + + //Shift arith right 255 + bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH1, 0xFF, SAR, return1()) + output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}) + + assert.Equal(t, expected, output) + + t.Logf("Result: %v == %v\n", output, expected) + + if err != nil { + t.Fatal(err) + } + + //Alternative shift arith right 255 + bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0xFF, SAR, return1()) + output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}) + + assert.Equal(t, expected, output) + + t.Logf("Result: %v == %v\n", output, expected) + + if err != nil { + t.Fatal(err) + } + + //Alternative shift arith right 255 + bytecode = MustSplice(PUSH32, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0xFF, SAR, return1()) + output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + value = []uint8([]byte{0x00}) + expected = RightPadBytes(value, 32) + assert.Equal(t, expected, output) + + t.Logf("Result: %v == %v\n", output, expected) + + if err != nil { + t.Fatal(err) + } + + //Shift arith right 256 (reset) + bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH2, 0x01, 0x00, SAR, + return1()) + output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}) + + assert.Equal(t, expected, output) + + t.Logf("Result: %v == %v\n", output, expected) + + if err != nil { + t.Fatal(err) + } + + //Alternative shift arith right 256 (reset) + bytecode = MustSplice(PUSH32, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH2, 0x01, 0x00, SAR, + return1()) + output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + value = []uint8([]byte{0x00}) + expected = LeftPadBytes(value, 32) + assert.Equal(t, expected, output) + + t.Logf("Result: %v == %v\n", output, expected) + + if err != nil { + t.Fatal(err) + } + + //Shift arith right 257 (reset) + bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH2, 0x01, 0x01, SAR, + return1()) + output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas) + expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}) + + assert.Equal(t, expected, output) + + t.Logf("Result: %v == %v\n", output, expected) + + if err != nil { + t.Fatal(err) + } + +} + //Test attempt to jump to bad destination (position 16) func TestJumpErr(t *testing.T) { ourVm := NewVM(newAppState(), newParams(), acm.ZeroAddress, nil, logger) -- GitLab