Skip to content

Commit a4633ce

Browse files
authored
Merge pull request #3649 from nspcc-dev/vm-modpow
vm: fix MODPOW operation
2 parents e8b8c1a + cccbe84 commit a4633ce

File tree

3 files changed

+12
-4
lines changed

3 files changed

+12
-4
lines changed

pkg/compiler/syscall_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -375,9 +375,9 @@ func TestOpcode(t *testing.T) {
375375
}`
376376
eval(t, src, []stackitem.Item{
377377
stackitem.Make(1),
378-
stackitem.Make(2),
378+
stackitem.Make(-3),
379379
stackitem.Make(1),
380-
stackitem.Make(2),
380+
stackitem.Make(-3),
381381
stackitem.Make(52),
382382
})
383383
})

pkg/vm/vm.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1055,6 +1055,12 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
10551055
panic("zero modulus") // https://docs.microsoft.com/en-us/dotnet/api/system.numerics.biginteger.modpow?view=net-6.0#exceptions
10561056
}
10571057
res.Exp(base, exponent, modulus)
1058+
1059+
// https://github.com/nspcc-dev/neo-go/issues/3612
1060+
if base.Sign() < 0 && exponent.Bit(0) == 1 && res.Sign() != 0 {
1061+
absModulus := new(big.Int).Abs(modulus)
1062+
res.Sub(res, absModulus)
1063+
}
10581064
}
10591065

10601066
v.estack.PushItem(stackitem.NewBigInteger(res))

pkg/vm/vm_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -747,11 +747,12 @@ func TestMODMUL(t *testing.T) {
747747
func TestMODPOW(t *testing.T) {
748748
prog := makeProgram(opcode.MODPOW)
749749
t.Run("good, positive base", getTestFuncForVM(prog, 1, 3, 4, 5))
750-
t.Run("good, negative base", getTestFuncForVM(prog, 2, -3, 5, 5))
750+
t.Run("good, negative base", getTestFuncForVM(prog, -3, -3, 5, 5))
751751
t.Run("good, positive base, negative mod", getTestFuncForVM(prog, 1, 3, 4, -5))
752-
t.Run("good, negative base, negative mod", getTestFuncForVM(prog, 2, -3, 5, -5))
752+
t.Run("good, negative base, negative mod", getTestFuncForVM(prog, -3, -3, 5, -5))
753753
t.Run("bad, big negative exponent", getTestFuncForVM(prog, nil, 3, -2, 5))
754754
t.Run("bad, zero modulus", getTestFuncForVM(prog, nil, 3, 4, 0))
755+
t.Run("zero result, negative base, even exponent", getTestFuncForVM(prog, 0, -2, 3, 8))
755756

756757
t.Run("inverse compatibility", func(t *testing.T) { // Tests are taken from C# node.
757758
t.Run("bad mod", getTestFuncForVM(prog, nil, 1, -1, 0))
@@ -760,6 +761,7 @@ func TestMODPOW(t *testing.T) {
760761
t.Run("bad base", getTestFuncForVM(prog, nil, 0, -1, 1))
761762
t.Run("no inverse exists", getTestFuncForVM(prog, nil, math.MaxUint16, -1, math.MaxUint8))
762763
t.Run("good", getTestFuncForVM(prog, 52, 19, -1, 141))
764+
t.Run("good", getTestFuncForVM(prog, 1, 5, -1, 4))
763765
})
764766
}
765767

0 commit comments

Comments
 (0)