From 52b0d661e065e52380c797ebef9fc9e1da1ae11e Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 10 Sep 2019 14:19:36 +0300 Subject: [PATCH 1/6] vm: implement BigInt -> Boolean conversion --- pkg/vm/stack.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkg/vm/stack.go b/pkg/vm/stack.go index 17c6e8143..234d27dc0 100644 --- a/pkg/vm/stack.go +++ b/pkg/vm/stack.go @@ -63,6 +63,11 @@ func (e *Element) BigInt() *big.Int { switch t := e.value.(type) { case *BigIntegerItem: return t.value + case *BoolItem: + if t.value { + return big.NewInt(1) + } + return big.NewInt(0) default: b := t.Value().([]uint8) return new(big.Int).SetBytes(util.ArrayReverse(b)) From 9b10b4c4d8b931bdeeae0ef7963646a18cd9c04c Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 10 Sep 2019 14:19:52 +0300 Subject: [PATCH 2/6] vm: add tests for SIGN --- pkg/vm/vm_test.go | 65 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/pkg/vm/vm_test.go b/pkg/vm/vm_test.go index 9eb26e22b..a379c71c1 100644 --- a/pkg/vm/vm_test.go +++ b/pkg/vm/vm_test.go @@ -312,6 +312,71 @@ func TestNEWSTRUCTWrongType(t *testing.T) { assert.Equal(t, true, vm.state.HasFlag(faultState)) } +func TestSIGNNoArgument(t *testing.T) { + prog := makeProgram(SIGN) + vm := load(prog) + vm.Run() + assert.Equal(t, true, vm.state.HasFlag(faultState)) +} + +func TestSIGNWrongType(t *testing.T) { + prog := makeProgram(SIGN) + vm := load(prog) + vm.estack.PushVal([]StackItem{}) + vm.Run() + assert.Equal(t, true, vm.state.HasFlag(faultState)) +} + +func TestSIGNBool(t *testing.T) { + prog := makeProgram(SIGN) + vm := load(prog) + vm.estack.PushVal(false) + vm.Run() + assert.Equal(t, false, vm.state.HasFlag(faultState)) + assert.Equal(t, 1, vm.estack.Len()) + assert.Equal(t, &BigIntegerItem{big.NewInt(0)}, vm.estack.Pop().value) +} + +func TestSIGNPositiveInt(t *testing.T) { + prog := makeProgram(SIGN) + vm := load(prog) + vm.estack.PushVal(1) + vm.Run() + assert.Equal(t, false, vm.state.HasFlag(faultState)) + assert.Equal(t, 1, vm.estack.Len()) + assert.Equal(t, &BigIntegerItem{big.NewInt(1)}, vm.estack.Pop().value) +} + +func TestSIGNNegativeInt(t *testing.T) { + prog := makeProgram(SIGN) + vm := load(prog) + vm.estack.PushVal(-1) + vm.Run() + assert.Equal(t, false, vm.state.HasFlag(faultState)) + assert.Equal(t, 1, vm.estack.Len()) + assert.Equal(t, &BigIntegerItem{big.NewInt(-1)}, vm.estack.Pop().value) +} + +func TestSIGNZero(t *testing.T) { + prog := makeProgram(SIGN) + vm := load(prog) + vm.estack.PushVal(0) + vm.Run() + assert.Equal(t, false, vm.state.HasFlag(faultState)) + assert.Equal(t, 1, vm.estack.Len()) + assert.Equal(t, &BigIntegerItem{big.NewInt(0)}, vm.estack.Pop().value) +} + +func TestSIGNByteArray(t *testing.T) { + prog := makeProgram(SIGN) + vm := load(prog) + vm.estack.PushVal([]byte{0, 1}) + vm.Run() + assert.Equal(t, false, vm.state.HasFlag(faultState)) + assert.Equal(t, 1, vm.estack.Len()) + assert.Equal(t, &BigIntegerItem{big.NewInt(1)}, vm.estack.Pop().value) +} + func TestAppCall(t *testing.T) { prog := []byte{byte(APPCALL)} hash := util.Uint160{} From 7e14c5a274a851e1d3d76468a7f10e5b72917438 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 10 Sep 2019 14:38:25 +0300 Subject: [PATCH 3/6] vm: implement * -> ByteArray conversion --- pkg/vm/stack.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/pkg/vm/stack.go b/pkg/vm/stack.go index 234d27dc0..09aecf22d 100644 --- a/pkg/vm/stack.go +++ b/pkg/vm/stack.go @@ -86,7 +86,19 @@ func (e *Element) Bool() bool { // Bytes attempts to get the underlying value of the element as a byte array. // Will panic if the assertion failed which will be caught by the VM. func (e *Element) Bytes() []byte { - return e.value.Value().([]byte) + switch t := e.value.(type) { + case *ByteArrayItem: + return t.value + case *BigIntegerItem: + return util.ArrayReverse(t.value.Bytes()) // neoVM returns in LE + case *BoolItem: + if t.value { + return []byte{1} + } + return []byte{0} + default: + panic("can't convert to []byte: " + t.String()) + } } // Array attempts to get the underlying value of the element as an array of From f2393e5efc924213e6dedc388caa0c21a01eb8dc Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 10 Sep 2019 14:43:40 +0300 Subject: [PATCH 4/6] vm: implement * -> Boolean conversion --- pkg/vm/stack.go | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/pkg/vm/stack.go b/pkg/vm/stack.go index 09aecf22d..740aa835e 100644 --- a/pkg/vm/stack.go +++ b/pkg/vm/stack.go @@ -77,10 +77,23 @@ func (e *Element) BigInt() *big.Int { // Bool attempts to get the underlying value of the element as a boolean. // Will panic if the assertion failed which will be caught by the VM. func (e *Element) Bool() bool { - if v, ok := e.value.Value().(*big.Int); ok { - return v.Int64() == 1 + switch t := e.value.(type) { + case *BigIntegerItem: + return t.value.Int64() != 0 + case *BoolItem: + return t.value + case *ArrayItem, *StructItem: + return true + case *ByteArrayItem: + for _, b := range t.value { + if b != 0 { + return true + } + } + return false + default: + panic("can't convert to bool: " + t.String()) } - return e.value.Value().(bool) } // Bytes attempts to get the underlying value of the element as a byte array. From 1289d0f7e9e190cce6a525bd995e63471179678a Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 10 Sep 2019 14:57:39 +0300 Subject: [PATCH 5/6] vm: add tests for NOT --- pkg/vm/vm_test.go | 61 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/pkg/vm/vm_test.go b/pkg/vm/vm_test.go index a379c71c1..18c6f0316 100644 --- a/pkg/vm/vm_test.go +++ b/pkg/vm/vm_test.go @@ -111,6 +111,67 @@ func TestPushData4(t *testing.T) { } +func TestNOTNoArgument(t *testing.T) { + prog := makeProgram(NOT) + vm := load(prog) + vm.Run() + assert.Equal(t, true, vm.state.HasFlag(faultState)) +} + +func TestNOTBool(t *testing.T) { + prog := makeProgram(NOT) + vm := load(prog) + vm.estack.PushVal(false) + vm.Run() + assert.Equal(t, false, vm.state.HasFlag(faultState)) + assert.Equal(t, &BoolItem{true}, vm.estack.Pop().value) +} + +func TestNOTNonZeroInt(t *testing.T) { + prog := makeProgram(NOT) + vm := load(prog) + vm.estack.PushVal(3) + vm.Run() + assert.Equal(t, false, vm.state.HasFlag(faultState)) + assert.Equal(t, &BoolItem{false}, vm.estack.Pop().value) +} + +func TestNOTArray(t *testing.T) { + prog := makeProgram(NOT) + vm := load(prog) + vm.estack.PushVal([]StackItem{}) + vm.Run() + assert.Equal(t, false, vm.state.HasFlag(faultState)) + assert.Equal(t, &BoolItem{false}, vm.estack.Pop().value) +} + +func TestNOTStruct(t *testing.T) { + prog := makeProgram(NOT) + vm := load(prog) + vm.estack.Push(NewElement(&StructItem{[]StackItem{}})) + vm.Run() + assert.Equal(t, false, vm.state.HasFlag(faultState)) + assert.Equal(t, &BoolItem{false}, vm.estack.Pop().value) +} + +func TestNOTByteArray0(t *testing.T) { + prog := makeProgram(NOT) + vm := load(prog) + vm.estack.PushVal([]byte{0, 0}) + vm.Run() + assert.Equal(t, false, vm.state.HasFlag(faultState)) + assert.Equal(t, &BoolItem{true}, vm.estack.Pop().value) +} + +func TestNOTByteArray1(t *testing.T) { + prog := makeProgram(NOT) + vm := load(prog) + vm.estack.PushVal([]byte{0, 1}) + vm.Run() + assert.Equal(t, false, vm.state.HasFlag(faultState)) + assert.Equal(t, &BoolItem{false}, vm.estack.Pop().value) +} + func TestAdd(t *testing.T) { prog := makeProgram(ADD) vm := load(prog) From 31f4c7486bedd009c1fb7b39afd6a9d36ba7d1c3 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 10 Sep 2019 17:28:53 +0300 Subject: [PATCH 6/6] vm: add tests for CAT --- pkg/vm/vm_test.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/pkg/vm/vm_test.go b/pkg/vm/vm_test.go index 18c6f0316..9506c7404 100644 --- a/pkg/vm/vm_test.go +++ b/pkg/vm/vm_test.go @@ -729,6 +729,28 @@ func TestCATGood(t *testing.T) { assert.Equal(t, []byte("abcdef"), vm.estack.Peek(0).Bytes()) } +func TestCATInt0ByteArray(t *testing.T) { + prog := makeProgram(CAT) + vm := load(prog) + vm.estack.PushVal(0) + vm.estack.PushVal([]byte{}) + vm.Run() + assert.Equal(t, false, vm.state.HasFlag(faultState)) + assert.Equal(t, 1, vm.estack.Len()) + assert.Equal(t, &ByteArrayItem{[]byte{}}, vm.estack.Pop().value) +} + +func TestCATByteArrayInt1(t *testing.T) { + prog := makeProgram(CAT) + vm := load(prog) + vm.estack.PushVal([]byte{}) + vm.estack.PushVal(1) + vm.Run() + assert.Equal(t, false, vm.state.HasFlag(faultState)) + assert.Equal(t, 1, vm.estack.Len()) + assert.Equal(t, &ByteArrayItem{[]byte{1}}, vm.estack.Pop().value) +} + func TestSUBSTRBadNoArgs(t *testing.T) { prog := makeProgram(SUBSTR) vm := load(prog)