Skip to content

Commit

Permalink
Merge pull request #3649 from nspcc-dev/vm-modpow
Browse files Browse the repository at this point in the history
vm: fix MODPOW operation
  • Loading branch information
AnnaShaleva authored Oct 31, 2024
2 parents e8b8c1a + cccbe84 commit a4633ce
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 4 deletions.
4 changes: 2 additions & 2 deletions pkg/compiler/syscall_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,9 +375,9 @@ func TestOpcode(t *testing.T) {
}`
eval(t, src, []stackitem.Item{
stackitem.Make(1),
stackitem.Make(2),
stackitem.Make(-3),
stackitem.Make(1),
stackitem.Make(2),
stackitem.Make(-3),
stackitem.Make(52),
})
})
Expand Down
6 changes: 6 additions & 0 deletions pkg/vm/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -1055,6 +1055,12 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
panic("zero modulus") // https://docs.microsoft.com/en-us/dotnet/api/system.numerics.biginteger.modpow?view=net-6.0#exceptions
}
res.Exp(base, exponent, modulus)

// https://github.com/nspcc-dev/neo-go/issues/3612
if base.Sign() < 0 && exponent.Bit(0) == 1 && res.Sign() != 0 {
absModulus := new(big.Int).Abs(modulus)
res.Sub(res, absModulus)
}
}

v.estack.PushItem(stackitem.NewBigInteger(res))
Expand Down
6 changes: 4 additions & 2 deletions pkg/vm/vm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -747,11 +747,12 @@ func TestMODMUL(t *testing.T) {
func TestMODPOW(t *testing.T) {
prog := makeProgram(opcode.MODPOW)
t.Run("good, positive base", getTestFuncForVM(prog, 1, 3, 4, 5))
t.Run("good, negative base", getTestFuncForVM(prog, 2, -3, 5, 5))
t.Run("good, negative base", getTestFuncForVM(prog, -3, -3, 5, 5))
t.Run("good, positive base, negative mod", getTestFuncForVM(prog, 1, 3, 4, -5))
t.Run("good, negative base, negative mod", getTestFuncForVM(prog, 2, -3, 5, -5))
t.Run("good, negative base, negative mod", getTestFuncForVM(prog, -3, -3, 5, -5))
t.Run("bad, big negative exponent", getTestFuncForVM(prog, nil, 3, -2, 5))
t.Run("bad, zero modulus", getTestFuncForVM(prog, nil, 3, 4, 0))
t.Run("zero result, negative base, even exponent", getTestFuncForVM(prog, 0, -2, 3, 8))

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

Expand Down

0 comments on commit a4633ce

Please sign in to comment.