From 8a334b1ab65b102e9d417135e57235adbada29db Mon Sep 17 00:00:00 2001 From: xuexiansong Date: Thu, 8 Apr 2021 15:02:06 +0800 Subject: [PATCH] Feat(BVM): change op mod (#1872) --- protocol/vm/numeric.go | 22 +++------ protocol/vm/numeric_test.go | 115 +++++++++++++++++++++++++++++++++++++++----- protocol/vm/vm_test.go | 10 ---- 3 files changed, 111 insertions(+), 36 deletions(-) diff --git a/protocol/vm/numeric.go b/protocol/vm/numeric.go index 122b53f4..d2218627 100644 --- a/protocol/vm/numeric.go +++ b/protocol/vm/numeric.go @@ -250,30 +250,22 @@ func opMod(vm *virtualMachine) error { if err != nil { return err } - y, err := vm.popInt64(true) + + y, err := vm.popBigInt(true) if err != nil { return err } - x, err := vm.popInt64(true) + + x, err := vm.popBigInt(true) if err != nil { return err } - if y == 0 { - return ErrDivZero - } - res, ok := checked.ModInt64(x, y) - if !ok { - return ErrRange - } - - // Go's modulus operator produces the wrong result for mixed-sign - // operands - if res != 0 && (x >= 0) != (y >= 0) { - res += y + if y.IsZero() { + return ErrDivZero } - return vm.pushInt64(res, true) + return vm.pushBigInt(x.Mod(x, y), true) } func opLshift(vm *virtualMachine) error { diff --git a/protocol/vm/numeric_test.go b/protocol/vm/numeric_test.go index b059f5e8..0a723e6e 100644 --- a/protocol/vm/numeric_test.go +++ b/protocol/vm/numeric_test.go @@ -209,17 +209,6 @@ func TestNumericOps(t *testing.T) { op: OP_MOD, startVM: &virtualMachine{ runLimit: 50000, - dataStack: [][]byte{Int64Bytes(-12), {10}}, - }, - wantVM: &virtualMachine{ - runLimit: 49992, - deferredCost: -16, - dataStack: [][]byte{{8}}, - }, - }, { - op: OP_MOD, - startVM: &virtualMachine{ - runLimit: 50000, dataStack: [][]byte{{2}, {0}}, }, wantErr: ErrDivZero, @@ -1257,3 +1246,107 @@ func Test_opAdd(t *testing.T) { }) } } + +func Test_opMod(t *testing.T) { + type args struct { + vm *virtualMachine + } + tests := []struct { + name string + args args + want [][]byte + wantErr bool + }{ + { + name: "Test 2 mod 2 = 0", + args: args{ + vm: &virtualMachine{ + runLimit: 50000, + dataStack: [][]byte{{0x02},{0x02}}, + }, + }, + want: [][]byte{{}}, + wantErr: false, + }, + { + name: "Test 2 mod 1 = 0", + args: args{ + vm: &virtualMachine{ + runLimit: 50000, + dataStack: [][]byte{{0x02},{0x01}}, + }, + }, + want: [][]byte{{}}, + wantErr: false, + }, + { + name: "Test 255 mod 4 = 3", + args: args{ + vm: &virtualMachine{ + runLimit: 50000, + dataStack: [][]byte{{0xff},{0x04}}, + }, + }, + want: [][]byte{{0x03}}, + wantErr: false, + }, + { + name: "Test that two bytes number become one byte number", + args: args{ + vm: &virtualMachine{ + runLimit: 50000, + dataStack: [][]byte{{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},{0x03}}, + }, + }, + want: [][]byte{{0x01}}, + wantErr: false, + }, + { + name: "Test for 0 mod 2 got 0", + args: args{ + vm: &virtualMachine{ + runLimit: 50000, + dataStack: [][]byte{{},{0x02}}, + }, + }, + want: [][]byte{{}}, + wantErr: false, + }, + { + name: "Test for -1 div 2 got error", + args: args{ + vm: &virtualMachine{ + runLimit: 50000, + dataStack: [][]byte{mocks.U256NumNegative1,{0x02}}, + }, + }, + want: nil, + wantErr: true, + }, + { + name: "Test for 1 div 0 got error", + args: args{ + vm: &virtualMachine{ + runLimit: 50000, + dataStack: [][]byte{{0x01},{}}, + }, + }, + want: nil, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := opMod(tt.args.vm); err != nil { + if !tt.wantErr { + t.Errorf("opMod() error = %v, wantErr %v", err, tt.wantErr) + } else { + return + } + } + if !testutil.DeepEqual(tt.args.vm.dataStack, tt.want) { + t.Errorf("opMod() error, got %v and wantErr %v", tt.args.vm.dataStack, tt.want) + } + }) + } +} diff --git a/protocol/vm/vm_test.go b/protocol/vm/vm_test.go index 8fab176c..34ffffca 100644 --- a/protocol/vm/vm_test.go +++ b/protocol/vm/vm_test.go @@ -67,10 +67,6 @@ func doOKNotOK(t *testing.T, expectOK bool) { {"2DIV -1 NUMEQUAL", [][]byte{Int64Bytes(-1)}, true}, {"2DIV -1 NUMEQUAL", [][]byte{Int64Bytes(-2)}, true}, - {"NEGATE -1 NUMEQUAL", [][]byte{Int64Bytes(1)}, false}, - {"NEGATE 1 NUMEQUAL", [][]byte{Int64Bytes(-1)}, false}, - {"NEGATE 0 NUMEQUAL", [][]byte{Int64Bytes(0)}, false}, - {"ABS 1 NUMEQUAL", [][]byte{Int64Bytes(1)}, false}, {"ABS 1 NUMEQUAL", [][]byte{Int64Bytes(-1)}, false}, {"ABS 0 NUMEQUAL", [][]byte{Int64Bytes(0)}, false}, @@ -87,13 +83,7 @@ func doOKNotOK(t *testing.T, expectOK bool) { {"DIV 2 NUMEQUAL", [][]byte{Int64Bytes(6), Int64Bytes(3)}, false}, {"MOD 0 NUMEQUAL", [][]byte{Int64Bytes(6), Int64Bytes(2)}, false}, - {"MOD 0 NUMEQUAL", [][]byte{Int64Bytes(-6), Int64Bytes(2)}, false}, - {"MOD 0 NUMEQUAL", [][]byte{Int64Bytes(6), Int64Bytes(-2)}, false}, - {"MOD 0 NUMEQUAL", [][]byte{Int64Bytes(-6), Int64Bytes(-2)}, false}, {"MOD 2 NUMEQUAL", [][]byte{Int64Bytes(12), Int64Bytes(10)}, false}, - {"MOD 8 NUMEQUAL", [][]byte{Int64Bytes(-12), Int64Bytes(10)}, false}, - {"MOD -8 NUMEQUAL", [][]byte{Int64Bytes(12), Int64Bytes(-10)}, false}, - {"MOD -2 NUMEQUAL", [][]byte{Int64Bytes(-12), Int64Bytes(-10)}, false}, {"LSHIFT 2 NUMEQUAL", [][]byte{Int64Bytes(1), Int64Bytes(1)}, false}, {"LSHIFT 4 NUMEQUAL", [][]byte{Int64Bytes(1), Int64Bytes(2)}, false}, -- 2.11.0