forked from TrueCloudLab/neoneo-go
Merge pull request #354 from nspcc-dev/some-vm-opcodes-and-fixes
Implements NZ, PICK, TUCK, XDROP, INVERT. Fixes XTUCK.
This commit is contained in:
commit
c899ec3038
3 changed files with 313 additions and 30 deletions
|
@ -132,21 +132,15 @@ func (s *Stack) insert(e, at *Element) *Element {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
// InsertBefore will insert the element before the mark on the stack.
|
|
||||||
func (s *Stack) InsertBefore(e, mark *Element) *Element {
|
|
||||||
if mark == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return s.insert(e, mark.prev)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InsertAt will insert the given item (n) deep on the stack.
|
// InsertAt will insert the given item (n) deep on the stack.
|
||||||
|
// Be very careful using it and _always_ check both e and n before invocation
|
||||||
|
// as it will silently do wrong things otherwise.
|
||||||
func (s *Stack) InsertAt(e *Element, n int) *Element {
|
func (s *Stack) InsertAt(e *Element, n int) *Element {
|
||||||
before := s.Peek(n)
|
before := s.Peek(n - 1)
|
||||||
if before == nil {
|
if before == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return s.InsertBefore(e, before)
|
return s.insert(e, before)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push pushes the given element on the stack.
|
// Push pushes the given element on the stack.
|
||||||
|
|
79
pkg/vm/vm.go
79
pkg/vm/vm.go
|
@ -290,6 +290,26 @@ func (v *VM) execute(ctx *Context, op Instruction) {
|
||||||
v.estack.Push(a)
|
v.estack.Push(a)
|
||||||
v.estack.Push(b)
|
v.estack.Push(b)
|
||||||
|
|
||||||
|
case TUCK:
|
||||||
|
a := v.estack.Dup(0)
|
||||||
|
if a == nil {
|
||||||
|
panic("no top-level element found")
|
||||||
|
}
|
||||||
|
if v.estack.Len() < 2 {
|
||||||
|
panic("can't TUCK with a one-element stack")
|
||||||
|
}
|
||||||
|
v.estack.InsertAt(a, 2)
|
||||||
|
|
||||||
|
case XDROP:
|
||||||
|
n := int(v.estack.Pop().BigInt().Int64())
|
||||||
|
if n < 0 {
|
||||||
|
panic("invalid length")
|
||||||
|
}
|
||||||
|
e := v.estack.RemoveAt(n)
|
||||||
|
if e == nil {
|
||||||
|
panic("bad index")
|
||||||
|
}
|
||||||
|
|
||||||
case XSWAP:
|
case XSWAP:
|
||||||
n := int(v.estack.Pop().BigInt().Int64())
|
n := int(v.estack.Pop().BigInt().Int64())
|
||||||
if n < 0 {
|
if n < 0 {
|
||||||
|
@ -306,13 +326,19 @@ func (v *VM) execute(ctx *Context, op Instruction) {
|
||||||
b.value = aval
|
b.value = aval
|
||||||
}
|
}
|
||||||
|
|
||||||
case TUCK:
|
case XTUCK:
|
||||||
n := int(v.estack.Pop().BigInt().Int64())
|
n := int(v.estack.Pop().BigInt().Int64())
|
||||||
if n <= 0 {
|
if n < 0 {
|
||||||
panic("OTUCK: invalid length")
|
panic("XTUCK: invalid length")
|
||||||
}
|
}
|
||||||
|
a := v.estack.Dup(0)
|
||||||
v.estack.InsertAt(v.estack.Peek(0), n)
|
if a == nil {
|
||||||
|
panic("no top-level element found")
|
||||||
|
}
|
||||||
|
if n > v.estack.Len() {
|
||||||
|
panic("can't push to the position specified")
|
||||||
|
}
|
||||||
|
v.estack.InsertAt(a, n)
|
||||||
|
|
||||||
case ROT:
|
case ROT:
|
||||||
c := v.estack.Pop()
|
c := v.estack.Pop()
|
||||||
|
@ -333,10 +359,27 @@ func (v *VM) execute(ctx *Context, op Instruction) {
|
||||||
|
|
||||||
case OVER:
|
case OVER:
|
||||||
b := v.estack.Pop()
|
b := v.estack.Pop()
|
||||||
|
if b == nil {
|
||||||
|
panic("no top-level element found")
|
||||||
|
}
|
||||||
a := v.estack.Peek(0)
|
a := v.estack.Peek(0)
|
||||||
|
if a == nil {
|
||||||
|
panic("no second element found")
|
||||||
|
}
|
||||||
v.estack.Push(b)
|
v.estack.Push(b)
|
||||||
v.estack.Push(a)
|
v.estack.Push(a)
|
||||||
|
|
||||||
|
case PICK:
|
||||||
|
n := int(v.estack.Pop().BigInt().Int64())
|
||||||
|
if n < 0 {
|
||||||
|
panic("negative stack item returned")
|
||||||
|
}
|
||||||
|
a := v.estack.Peek(n)
|
||||||
|
if a == nil {
|
||||||
|
panic("no nth element found")
|
||||||
|
}
|
||||||
|
v.estack.Push(a)
|
||||||
|
|
||||||
case ROLL:
|
case ROLL:
|
||||||
n := int(v.estack.Pop().BigInt().Int64())
|
n := int(v.estack.Pop().BigInt().Int64())
|
||||||
if n < 0 {
|
if n < 0 {
|
||||||
|
@ -359,6 +402,11 @@ func (v *VM) execute(ctx *Context, op Instruction) {
|
||||||
v.estack.PushVal(reflect.DeepEqual(a,b))
|
v.estack.PushVal(reflect.DeepEqual(a,b))
|
||||||
|
|
||||||
// Bit operations.
|
// Bit operations.
|
||||||
|
case INVERT:
|
||||||
|
// inplace
|
||||||
|
a := v.estack.Peek(0).BigInt()
|
||||||
|
a.Not(a)
|
||||||
|
|
||||||
case AND:
|
case AND:
|
||||||
b := v.estack.Pop().BigInt()
|
b := v.estack.Pop().BigInt()
|
||||||
a := v.estack.Pop().BigInt()
|
a := v.estack.Pop().BigInt()
|
||||||
|
@ -499,8 +547,8 @@ func (v *VM) execute(ctx *Context, op Instruction) {
|
||||||
v.estack.PushVal(!x)
|
v.estack.PushVal(!x)
|
||||||
|
|
||||||
case NZ:
|
case NZ:
|
||||||
panic("todo NZ")
|
x := v.estack.Pop().BigInt()
|
||||||
// x := v.estack.Pop().BigInt()
|
v.estack.PushVal(x.Cmp(big.NewInt(0)) != 0)
|
||||||
|
|
||||||
// Object operations.
|
// Object operations.
|
||||||
case NEWARRAY:
|
case NEWARRAY:
|
||||||
|
@ -529,10 +577,6 @@ func (v *VM) execute(ctx *Context, op Instruction) {
|
||||||
panic("APPEND: not of underlying type Array")
|
panic("APPEND: not of underlying type Array")
|
||||||
}
|
}
|
||||||
|
|
||||||
case REVERSE:
|
|
||||||
|
|
||||||
case REMOVE:
|
|
||||||
|
|
||||||
case PACK:
|
case PACK:
|
||||||
n := int(v.estack.Pop().BigInt().Int64())
|
n := int(v.estack.Pop().BigInt().Int64())
|
||||||
if n < 0 || n > v.estack.Len() {
|
if n < 0 || n > v.estack.Len() {
|
||||||
|
@ -546,9 +590,6 @@ func (v *VM) execute(ctx *Context, op Instruction) {
|
||||||
|
|
||||||
v.estack.PushVal(items)
|
v.estack.PushVal(items)
|
||||||
|
|
||||||
case UNPACK:
|
|
||||||
panic("TODO")
|
|
||||||
|
|
||||||
case PICKITEM:
|
case PICKITEM:
|
||||||
var (
|
var (
|
||||||
key = v.estack.Pop()
|
key = v.estack.Pop()
|
||||||
|
@ -671,6 +712,10 @@ func (v *VM) execute(ctx *Context, op Instruction) {
|
||||||
v.state = haltState
|
v.state = haltState
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case CAT, SUBSTR, LEFT, RIGHT, CHECKSIG, CHECKMULTISIG,
|
||||||
|
UNPACK, REVERSE, REMOVE:
|
||||||
|
panic("unimplemented")
|
||||||
|
|
||||||
// Cryptographic operations.
|
// Cryptographic operations.
|
||||||
case SHA1:
|
case SHA1:
|
||||||
b := v.estack.Pop().Bytes()
|
b := v.estack.Pop().Bytes()
|
||||||
|
@ -690,12 +735,6 @@ func (v *VM) execute(ctx *Context, op Instruction) {
|
||||||
b := v.estack.Pop().Bytes()
|
b := v.estack.Pop().Bytes()
|
||||||
v.estack.PushVal(hash.DoubleSha256(b).Bytes())
|
v.estack.PushVal(hash.DoubleSha256(b).Bytes())
|
||||||
|
|
||||||
case CHECKSIG:
|
|
||||||
// pubkey := v.estack.Pop().Bytes()
|
|
||||||
// sig := v.estack.Pop().Bytes()
|
|
||||||
|
|
||||||
case CHECKMULTISIG:
|
|
||||||
|
|
||||||
case NOP:
|
case NOP:
|
||||||
// unlucky ^^
|
// unlucky ^^
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ func TestInteropHook(t *testing.T) {
|
||||||
EmitOpcode(buf, RET)
|
EmitOpcode(buf, RET)
|
||||||
v.Load(buf.Bytes())
|
v.Load(buf.Bytes())
|
||||||
v.Run()
|
v.Run()
|
||||||
|
assert.Equal(t, false, v.state.HasFlag(faultState))
|
||||||
assert.Equal(t, 1, v.estack.Len())
|
assert.Equal(t, 1, v.estack.Len())
|
||||||
assert.Equal(t, big.NewInt(1), v.estack.Pop().value.Value())
|
assert.Equal(t, big.NewInt(1), v.estack.Pop().value.Value())
|
||||||
}
|
}
|
||||||
|
@ -100,6 +101,7 @@ func TestAdd(t *testing.T) {
|
||||||
vm.estack.PushVal(4)
|
vm.estack.PushVal(4)
|
||||||
vm.estack.PushVal(2)
|
vm.estack.PushVal(2)
|
||||||
vm.Run()
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||||
assert.Equal(t, int64(6), vm.estack.Pop().BigInt().Int64())
|
assert.Equal(t, int64(6), vm.estack.Pop().BigInt().Int64())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,6 +111,7 @@ func TestMul(t *testing.T) {
|
||||||
vm.estack.PushVal(4)
|
vm.estack.PushVal(4)
|
||||||
vm.estack.PushVal(2)
|
vm.estack.PushVal(2)
|
||||||
vm.Run()
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||||
assert.Equal(t, int64(8), vm.estack.Pop().BigInt().Int64())
|
assert.Equal(t, int64(8), vm.estack.Pop().BigInt().Int64())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,6 +121,7 @@ func TestDiv(t *testing.T) {
|
||||||
vm.estack.PushVal(4)
|
vm.estack.PushVal(4)
|
||||||
vm.estack.PushVal(2)
|
vm.estack.PushVal(2)
|
||||||
vm.Run()
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||||
assert.Equal(t, int64(2), vm.estack.Pop().BigInt().Int64())
|
assert.Equal(t, int64(2), vm.estack.Pop().BigInt().Int64())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,6 +131,7 @@ func TestSub(t *testing.T) {
|
||||||
vm.estack.PushVal(4)
|
vm.estack.PushVal(4)
|
||||||
vm.estack.PushVal(2)
|
vm.estack.PushVal(2)
|
||||||
vm.Run()
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||||
assert.Equal(t, int64(2), vm.estack.Pop().BigInt().Int64())
|
assert.Equal(t, int64(2), vm.estack.Pop().BigInt().Int64())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,6 +141,7 @@ func TestLT(t *testing.T) {
|
||||||
vm.estack.PushVal(4)
|
vm.estack.PushVal(4)
|
||||||
vm.estack.PushVal(3)
|
vm.estack.PushVal(3)
|
||||||
vm.Run()
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||||
assert.Equal(t, false, vm.estack.Pop().Bool())
|
assert.Equal(t, false, vm.estack.Pop().Bool())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,6 +151,7 @@ func TestLTE(t *testing.T) {
|
||||||
vm.estack.PushVal(2)
|
vm.estack.PushVal(2)
|
||||||
vm.estack.PushVal(3)
|
vm.estack.PushVal(3)
|
||||||
vm.Run()
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||||
assert.Equal(t, true, vm.estack.Pop().Bool())
|
assert.Equal(t, true, vm.estack.Pop().Bool())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,6 +161,7 @@ func TestGT(t *testing.T) {
|
||||||
vm.estack.PushVal(9)
|
vm.estack.PushVal(9)
|
||||||
vm.estack.PushVal(3)
|
vm.estack.PushVal(3)
|
||||||
vm.Run()
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||||
assert.Equal(t, true, vm.estack.Pop().Bool())
|
assert.Equal(t, true, vm.estack.Pop().Bool())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -164,6 +172,7 @@ func TestGTE(t *testing.T) {
|
||||||
vm.estack.PushVal(3)
|
vm.estack.PushVal(3)
|
||||||
vm.estack.PushVal(3)
|
vm.estack.PushVal(3)
|
||||||
vm.Run()
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||||
assert.Equal(t, true, vm.estack.Pop().Bool())
|
assert.Equal(t, true, vm.estack.Pop().Bool())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,6 +183,7 @@ func TestDepth(t *testing.T) {
|
||||||
vm.estack.PushVal(2)
|
vm.estack.PushVal(2)
|
||||||
vm.estack.PushVal(3)
|
vm.estack.PushVal(3)
|
||||||
vm.Run()
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||||
assert.Equal(t, int64(3), vm.estack.Pop().BigInt().Int64())
|
assert.Equal(t, int64(3), vm.estack.Pop().BigInt().Int64())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,6 +193,7 @@ func TestNumEqual(t *testing.T) {
|
||||||
vm.estack.PushVal(1)
|
vm.estack.PushVal(1)
|
||||||
vm.estack.PushVal(2)
|
vm.estack.PushVal(2)
|
||||||
vm.Run()
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||||
assert.Equal(t, false, vm.estack.Pop().Bool())
|
assert.Equal(t, false, vm.estack.Pop().Bool())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,6 +203,7 @@ func TestNumNotEqual(t *testing.T) {
|
||||||
vm.estack.PushVal(2)
|
vm.estack.PushVal(2)
|
||||||
vm.estack.PushVal(2)
|
vm.estack.PushVal(2)
|
||||||
vm.Run()
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||||
assert.Equal(t, false, vm.estack.Pop().Bool())
|
assert.Equal(t, false, vm.estack.Pop().Bool())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,6 +212,7 @@ func TestINC(t *testing.T) {
|
||||||
vm := load(prog)
|
vm := load(prog)
|
||||||
vm.estack.PushVal(1)
|
vm.estack.PushVal(1)
|
||||||
vm.Run()
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||||
assert.Equal(t, big.NewInt(2), vm.estack.Pop().BigInt())
|
assert.Equal(t, big.NewInt(2), vm.estack.Pop().BigInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,6 +227,7 @@ func TestAppCall(t *testing.T) {
|
||||||
vm.estack.PushVal(2)
|
vm.estack.PushVal(2)
|
||||||
|
|
||||||
vm.Run()
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||||
elem := vm.estack.Pop() // depth should be 1
|
elem := vm.estack.Pop() // depth should be 1
|
||||||
assert.Equal(t, int64(1), elem.BigInt().Int64())
|
assert.Equal(t, int64(1), elem.BigInt().Int64())
|
||||||
}
|
}
|
||||||
|
@ -228,9 +242,245 @@ func TestSimpleCall(t *testing.T) {
|
||||||
}
|
}
|
||||||
vm := load(prog)
|
vm := load(prog)
|
||||||
vm.Run()
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||||
assert.Equal(t, result, int(vm.estack.Pop().BigInt().Int64()))
|
assert.Equal(t, result, int(vm.estack.Pop().BigInt().Int64()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNZtrue(t *testing.T) {
|
||||||
|
prog := makeProgram(NZ)
|
||||||
|
vm := load(prog)
|
||||||
|
vm.estack.PushVal(1)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||||
|
assert.Equal(t, true, vm.estack.Pop().Bool())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNZfalse(t *testing.T) {
|
||||||
|
prog := makeProgram(NZ)
|
||||||
|
vm := load(prog)
|
||||||
|
vm.estack.PushVal(0)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||||
|
assert.Equal(t, false, vm.estack.Pop().Bool())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPICKbadNoitem(t *testing.T) {
|
||||||
|
prog := makeProgram(PICK)
|
||||||
|
vm := load(prog)
|
||||||
|
vm.estack.PushVal(1)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, true, vm.state.HasFlag(faultState))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPICKbadNegative(t *testing.T) {
|
||||||
|
prog := makeProgram(PICK)
|
||||||
|
vm := load(prog)
|
||||||
|
vm.estack.PushVal(-1)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, true, vm.state.HasFlag(faultState))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPICKgood(t *testing.T) {
|
||||||
|
prog := makeProgram(PICK)
|
||||||
|
result := 2
|
||||||
|
vm := load(prog)
|
||||||
|
vm.estack.PushVal(0)
|
||||||
|
vm.estack.PushVal(1)
|
||||||
|
vm.estack.PushVal(result)
|
||||||
|
vm.estack.PushVal(3)
|
||||||
|
vm.estack.PushVal(4)
|
||||||
|
vm.estack.PushVal(5)
|
||||||
|
vm.estack.PushVal(3)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||||
|
assert.Equal(t, int64(result), vm.estack.Pop().BigInt().Int64())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestXTUCKbadNoitem(t *testing.T) {
|
||||||
|
prog := makeProgram(XTUCK)
|
||||||
|
vm := load(prog)
|
||||||
|
vm.estack.PushVal(1)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, true, vm.state.HasFlag(faultState))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestXTUCKbadNoN(t *testing.T) {
|
||||||
|
prog := makeProgram(XTUCK)
|
||||||
|
vm := load(prog)
|
||||||
|
vm.estack.PushVal(1)
|
||||||
|
vm.estack.PushVal(2)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, true, vm.state.HasFlag(faultState))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestXTUCKbadNegative(t *testing.T) {
|
||||||
|
prog := makeProgram(XTUCK)
|
||||||
|
vm := load(prog)
|
||||||
|
vm.estack.PushVal(-1)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, true, vm.state.HasFlag(faultState))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestXTUCKgood(t *testing.T) {
|
||||||
|
prog := makeProgram(XTUCK)
|
||||||
|
topelement := 5
|
||||||
|
xtuckdepth := 3
|
||||||
|
vm := load(prog)
|
||||||
|
vm.estack.PushVal(0)
|
||||||
|
vm.estack.PushVal(1)
|
||||||
|
vm.estack.PushVal(2)
|
||||||
|
vm.estack.PushVal(3)
|
||||||
|
vm.estack.PushVal(4)
|
||||||
|
vm.estack.PushVal(topelement)
|
||||||
|
vm.estack.PushVal(xtuckdepth)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||||
|
assert.Equal(t, int64(topelement), vm.estack.Peek(0).BigInt().Int64())
|
||||||
|
assert.Equal(t, int64(topelement), vm.estack.Peek(xtuckdepth).BigInt().Int64())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTUCKbadNoitems(t *testing.T) {
|
||||||
|
prog := makeProgram(TUCK)
|
||||||
|
vm := load(prog)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, true, vm.state.HasFlag(faultState))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTUCKbadNoitem(t *testing.T) {
|
||||||
|
prog := makeProgram(TUCK)
|
||||||
|
vm := load(prog)
|
||||||
|
vm.estack.PushVal(1)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, true, vm.state.HasFlag(faultState))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTUCKgood(t *testing.T) {
|
||||||
|
prog := makeProgram(TUCK)
|
||||||
|
vm := load(prog)
|
||||||
|
vm.estack.PushVal(42)
|
||||||
|
vm.estack.PushVal(34)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||||
|
assert.Equal(t, int64(34), vm.estack.Peek(0).BigInt().Int64())
|
||||||
|
assert.Equal(t, int64(42), vm.estack.Peek(1).BigInt().Int64())
|
||||||
|
assert.Equal(t, int64(34), vm.estack.Peek(2).BigInt().Int64())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTUCKgood2(t *testing.T) {
|
||||||
|
prog := makeProgram(TUCK)
|
||||||
|
vm := load(prog)
|
||||||
|
vm.estack.PushVal(11)
|
||||||
|
vm.estack.PushVal(42)
|
||||||
|
vm.estack.PushVal(34)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||||
|
assert.Equal(t, int64(34), vm.estack.Peek(0).BigInt().Int64())
|
||||||
|
assert.Equal(t, int64(42), vm.estack.Peek(1).BigInt().Int64())
|
||||||
|
assert.Equal(t, int64(34), vm.estack.Peek(2).BigInt().Int64())
|
||||||
|
assert.Equal(t, int64(11), vm.estack.Peek(3).BigInt().Int64())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOVERbadNoitem(t *testing.T) {
|
||||||
|
prog := makeProgram(OVER)
|
||||||
|
vm := load(prog)
|
||||||
|
vm.estack.PushVal(1)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, true, vm.state.HasFlag(faultState))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOVERbadNoitems(t *testing.T) {
|
||||||
|
prog := makeProgram(OVER)
|
||||||
|
vm := load(prog)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, true, vm.state.HasFlag(faultState))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOVERgood(t *testing.T) {
|
||||||
|
prog := makeProgram(OVER)
|
||||||
|
vm := load(prog)
|
||||||
|
vm.estack.PushVal(42)
|
||||||
|
vm.estack.PushVal(34)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||||
|
assert.Equal(t, int64(42), vm.estack.Peek(0).BigInt().Int64())
|
||||||
|
assert.Equal(t, int64(34), vm.estack.Peek(1).BigInt().Int64())
|
||||||
|
assert.Equal(t, int64(42), vm.estack.Peek(2).BigInt().Int64())
|
||||||
|
assert.Equal(t, 3, vm.estack.Len())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestXDROPbadNoitem(t *testing.T) {
|
||||||
|
prog := makeProgram(XDROP)
|
||||||
|
vm := load(prog)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, true, vm.state.HasFlag(faultState))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestXDROPbadNoN(t *testing.T) {
|
||||||
|
prog := makeProgram(XDROP)
|
||||||
|
vm := load(prog)
|
||||||
|
vm.estack.PushVal(1)
|
||||||
|
vm.estack.PushVal(2)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, true, vm.state.HasFlag(faultState))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestXDROPbadNegative(t *testing.T) {
|
||||||
|
prog := makeProgram(XDROP)
|
||||||
|
vm := load(prog)
|
||||||
|
vm.estack.PushVal(1)
|
||||||
|
vm.estack.PushVal(-1)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, true, vm.state.HasFlag(faultState))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestXDROPgood(t *testing.T) {
|
||||||
|
prog := makeProgram(XDROP)
|
||||||
|
vm := load(prog)
|
||||||
|
vm.estack.PushVal(0)
|
||||||
|
vm.estack.PushVal(1)
|
||||||
|
vm.estack.PushVal(2)
|
||||||
|
vm.estack.PushVal(2)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||||
|
assert.Equal(t, 2, vm.estack.Len())
|
||||||
|
assert.Equal(t, int64(2), vm.estack.Peek(0).BigInt().Int64())
|
||||||
|
assert.Equal(t, int64(1), vm.estack.Peek(1).BigInt().Int64())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestINVERTbadNoitem(t *testing.T) {
|
||||||
|
prog := makeProgram(INVERT)
|
||||||
|
vm := load(prog)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, true, vm.state.HasFlag(faultState))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestINVERTgood1(t *testing.T) {
|
||||||
|
prog := makeProgram(INVERT)
|
||||||
|
vm := load(prog)
|
||||||
|
vm.estack.PushVal(0)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||||
|
assert.Equal(t, int64(-1), vm.estack.Peek(0).BigInt().Int64())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestINVERTgood2(t *testing.T) {
|
||||||
|
prog := makeProgram(INVERT)
|
||||||
|
vm := load(prog)
|
||||||
|
vm.estack.PushVal(-1)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||||
|
assert.Equal(t, int64(0), vm.estack.Peek(0).BigInt().Int64())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestINVERTgood3(t *testing.T) {
|
||||||
|
prog := makeProgram(INVERT)
|
||||||
|
vm := load(prog)
|
||||||
|
vm.estack.PushVal(0x69)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||||
|
assert.Equal(t, int64(-0x6A), vm.estack.Peek(0).BigInt().Int64())
|
||||||
|
}
|
||||||
|
|
||||||
func makeProgram(opcodes ...Instruction) []byte {
|
func makeProgram(opcodes ...Instruction) []byte {
|
||||||
prog := make([]byte, len(opcodes)+1) // RET
|
prog := make([]byte, len(opcodes)+1) // RET
|
||||||
for i := 0; i < len(opcodes); i++ {
|
for i := 0; i < len(opcodes); i++ {
|
||||||
|
|
Loading…
Reference in a new issue