mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-11-21 23:29:38 +00:00
Merge pull request #3649 from nspcc-dev/vm-modpow
vm: fix MODPOW operation
This commit is contained in:
commit
a4633ce2c7
3 changed files with 12 additions and 4 deletions
|
@ -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),
|
||||
})
|
||||
})
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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))
|
||||
|
@ -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))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue