diff --git a/binary/integer.go b/binary/integer.go index a00c07054502952f50408eba9a4bf8d000c654ba..cd57bf3a1b8ccf9536a31318b6c52d0f8a8cc624 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 aca675675cf1feffb53603685e804f2c1d7a712f..c0191bf6b861a8534a6da9697a9eb9af447f0d56 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 ffa5454c83bf4931eaa34095c6c16ebaef029730..b885d2664aad7e03f163cefaf9c008aade5b1346 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)