core: implement Neo.Crypto.ECDsaVerify interop
This commit is contained in:
parent
1611ede58c
commit
5a30af2c75
3 changed files with 96 additions and 0 deletions
31
pkg/core/interop/crypto/ecdsa.go
Normal file
31
pkg/core/interop/crypto/ecdsa.go
Normal file
|
@ -0,0 +1,31 @@
|
|||
package crypto
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||
)
|
||||
|
||||
// ECDSAVerify checks ECDSA signature.
|
||||
func ECDSAVerify(ic *interop.Context, v *vm.VM) error {
|
||||
msg := getMessage(ic, v.Estack().Pop().Item())
|
||||
hashToCheck := hash.Sha256(msg).BytesBE()
|
||||
keyb := v.Estack().Pop().Bytes()
|
||||
signature := v.Estack().Pop().Bytes()
|
||||
pkey, err := keys.NewPublicKeyFromBytes(keyb)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
res := pkey.Verify(signature, hashToCheck)
|
||||
v.Estack().PushVal(res)
|
||||
return nil
|
||||
}
|
||||
|
||||
func getMessage(_ *interop.Context, item vm.StackItem) []byte {
|
||||
msg, err := item.TryBytes()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return msg
|
||||
}
|
|
@ -1,12 +1,14 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/dao"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/crypto"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/enumerator"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/iterator"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||
|
@ -231,6 +233,67 @@ func TestWitnessGetVerificationScript(t *testing.T) {
|
|||
require.Equal(t, witness.VerificationScript, value)
|
||||
}
|
||||
|
||||
func TestECDSAVerify(t *testing.T) {
|
||||
priv, err := keys.NewPrivateKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
chain := newTestChain(t)
|
||||
defer chain.Close()
|
||||
|
||||
ic := chain.newInteropContext(trigger.Application, dao.NewSimple(storage.NewMemoryStore()), nil, nil)
|
||||
runCase := func(t *testing.T, isErr bool, result interface{}, args ...interface{}) {
|
||||
v := vm.New()
|
||||
for i := range args {
|
||||
v.Estack().PushVal(args[i])
|
||||
}
|
||||
|
||||
var err error
|
||||
func() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err = fmt.Errorf("panic: %v", r)
|
||||
}
|
||||
}()
|
||||
err = crypto.ECDSAVerify(ic, v)
|
||||
}()
|
||||
|
||||
if isErr {
|
||||
require.Error(t, err)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, v.Estack().Len())
|
||||
require.Equal(t, result, v.Estack().Pop().Value().(bool))
|
||||
}
|
||||
|
||||
msg := []byte("test message")
|
||||
|
||||
t.Run("success", func(t *testing.T) {
|
||||
sign := priv.Sign(msg)
|
||||
runCase(t, false, true, sign, priv.PublicKey().Bytes(), msg)
|
||||
})
|
||||
|
||||
t.Run("missing arguments", func(t *testing.T) {
|
||||
runCase(t, true, false)
|
||||
sign := priv.Sign(msg)
|
||||
runCase(t, true, false, sign)
|
||||
runCase(t, true, false, sign, priv.PublicKey().Bytes())
|
||||
})
|
||||
|
||||
t.Run("invalid signature", func(t *testing.T) {
|
||||
sign := priv.Sign(msg)
|
||||
sign[0] ^= sign[0]
|
||||
runCase(t, false, false, sign, priv.PublicKey().Bytes(), msg)
|
||||
})
|
||||
|
||||
t.Run("invalid public key", func(t *testing.T) {
|
||||
sign := priv.Sign(msg)
|
||||
pub := priv.PublicKey().Bytes()
|
||||
pub = pub[10:]
|
||||
runCase(t, true, false, sign, pub, msg)
|
||||
})
|
||||
}
|
||||
|
||||
func TestPopInputFromVM(t *testing.T) {
|
||||
v, tx, _, chain := createVMAndTX(t)
|
||||
defer chain.Close()
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"sort"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/crypto"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/enumerator"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/iterator"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
|
@ -137,6 +138,7 @@ var neoInterops = []interop.Function{
|
|||
{Name: "Neo.Contract.GetStorageContext", Func: contractGetStorageContext, Price: 1},
|
||||
{Name: "Neo.Contract.IsPayable", Func: contractIsPayable, Price: 1},
|
||||
{Name: "Neo.Contract.Migrate", Func: contractMigrate, Price: 0},
|
||||
{Name: "Neo.Crypto.ECDsaVerify", Func: crypto.ECDSAVerify, Price: 1},
|
||||
{Name: "Neo.Enumerator.Concat", Func: enumerator.Concat, Price: 1},
|
||||
{Name: "Neo.Enumerator.Create", Func: enumerator.Create, Price: 1},
|
||||
{Name: "Neo.Enumerator.Next", Func: enumerator.Next, Price: 1},
|
||||
|
|
Loading…
Reference in a new issue