mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2025-01-10 15:54:05 +00:00
vm: fix MODPOW operation
Close #3612 Signed-off-by: Ekaterina Pavlova <ekt@morphbits.io>
This commit is contained in:
parent
b8a65d3c37
commit
cccbe843be
3 changed files with 12 additions and 4 deletions
|
@ -375,9 +375,9 @@ func TestOpcode(t *testing.T) {
|
||||||
}`
|
}`
|
||||||
eval(t, src, []stackitem.Item{
|
eval(t, src, []stackitem.Item{
|
||||||
stackitem.Make(1),
|
stackitem.Make(1),
|
||||||
stackitem.Make(2),
|
stackitem.Make(-3),
|
||||||
stackitem.Make(1),
|
stackitem.Make(1),
|
||||||
stackitem.Make(2),
|
stackitem.Make(-3),
|
||||||
stackitem.Make(52),
|
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
|
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)
|
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))
|
v.estack.PushItem(stackitem.NewBigInteger(res))
|
||||||
|
|
|
@ -747,11 +747,12 @@ func TestMODMUL(t *testing.T) {
|
||||||
func TestMODPOW(t *testing.T) {
|
func TestMODPOW(t *testing.T) {
|
||||||
prog := makeProgram(opcode.MODPOW)
|
prog := makeProgram(opcode.MODPOW)
|
||||||
t.Run("good, positive base", getTestFuncForVM(prog, 1, 3, 4, 5))
|
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, 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, big negative exponent", getTestFuncForVM(prog, nil, 3, -2, 5))
|
||||||
t.Run("bad, zero modulus", getTestFuncForVM(prog, nil, 3, 4, 0))
|
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("inverse compatibility", func(t *testing.T) { // Tests are taken from C# node.
|
||||||
t.Run("bad mod", getTestFuncForVM(prog, nil, 1, -1, 0))
|
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("bad base", getTestFuncForVM(prog, nil, 0, -1, 1))
|
||||||
t.Run("no inverse exists", getTestFuncForVM(prog, nil, math.MaxUint16, -1, math.MaxUint8))
|
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, 52, 19, -1, 141))
|
||||||
|
t.Run("good", getTestFuncForVM(prog, 1, 5, -1, 4))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue