mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2025-01-10 15:54:05 +00:00
core: add Neo.Crypto.CheckSig interop
This commit is contained in:
parent
14ade42101
commit
4e6c1092b8
7 changed files with 87 additions and 0 deletions
|
@ -93,6 +93,7 @@ func TestSyscallExecution(t *testing.T) {
|
||||||
"crypto.ECDsaSecp256k1Verify": {interopnames.NeoCryptoVerifyWithECDsaSecp256k1, []string{b, pub, sig}, false},
|
"crypto.ECDsaSecp256k1Verify": {interopnames.NeoCryptoVerifyWithECDsaSecp256k1, []string{b, pub, sig}, false},
|
||||||
"crypto.ECDSASecp256r1CheckMultisig": {interopnames.NeoCryptoCheckMultisigWithECDsaSecp256r1, []string{b, pubs, sigs}, false},
|
"crypto.ECDSASecp256r1CheckMultisig": {interopnames.NeoCryptoCheckMultisigWithECDsaSecp256r1, []string{b, pubs, sigs}, false},
|
||||||
"crypto.ECDSASecp256k1CheckMultisig": {interopnames.NeoCryptoCheckMultisigWithECDsaSecp256k1, []string{b, pubs, sigs}, false},
|
"crypto.ECDSASecp256k1CheckMultisig": {interopnames.NeoCryptoCheckMultisigWithECDsaSecp256k1, []string{b, pubs, sigs}, false},
|
||||||
|
"crypto.CheckSig": {interopnames.NeoCryptoCheckSig, []string{pub, sig}, false},
|
||||||
}
|
}
|
||||||
ic := &interop.Context{}
|
ic := &interop.Context{}
|
||||||
core.SpawnVM(ic) // set Functions field
|
core.SpawnVM(ic) // set Functions field
|
||||||
|
|
|
@ -99,3 +99,17 @@ func getMessageHash(ic *interop.Context, item stackitem.Item) (util.Uint256, err
|
||||||
}
|
}
|
||||||
return hash.Sha256(msg), nil
|
return hash.Sha256(msg), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ECDSASecp256r1CheckSig checks ECDSA signature using Secp256r1 elliptic curve.
|
||||||
|
func ECDSASecp256r1CheckSig(ic *interop.Context) error {
|
||||||
|
hashToCheck := ic.Container.GetSignedHash()
|
||||||
|
keyb := ic.VM.Estack().Pop().Bytes()
|
||||||
|
signature := ic.VM.Estack().Pop().Bytes()
|
||||||
|
pkey, err := keys.NewPublicKeyFromBytes(keyb, elliptic.P256())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
res := pkey.Verify(signature, hashToCheck.BytesBE())
|
||||||
|
ic.VM.Estack().PushVal(res)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -279,3 +279,64 @@ func testCurveCHECKMULTISIGBad(t *testing.T, isR1 bool) {
|
||||||
require.Error(t, v.Run())
|
require.Error(t, v.Run())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCheckSig(t *testing.T) {
|
||||||
|
priv, err := keys.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
verifyFunc := ECDSASecp256r1CheckSig
|
||||||
|
d := dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false)
|
||||||
|
ic := &interop.Context{DAO: dao.NewCached(d)}
|
||||||
|
runCase := func(t *testing.T, isErr bool, result interface{}, args ...interface{}) {
|
||||||
|
ic.SpawnVM()
|
||||||
|
for i := range args {
|
||||||
|
ic.VM.Estack().PushVal(args[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
func() {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
err = fmt.Errorf("panic: %v", r)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
err = verifyFunc(ic)
|
||||||
|
}()
|
||||||
|
|
||||||
|
if isErr {
|
||||||
|
require.Error(t, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 1, ic.VM.Estack().Len())
|
||||||
|
require.Equal(t, result, ic.VM.Estack().Pop().Value().(bool))
|
||||||
|
}
|
||||||
|
|
||||||
|
tx := transaction.New(netmode.UnitTestNet, []byte{0, 1, 2}, 1)
|
||||||
|
msg := tx.GetSignedPart()
|
||||||
|
ic.Container = tx
|
||||||
|
|
||||||
|
t.Run("success", func(t *testing.T) {
|
||||||
|
sign := priv.Sign(msg)
|
||||||
|
runCase(t, false, true, sign, priv.PublicKey().Bytes())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("missing argument", func(t *testing.T) {
|
||||||
|
runCase(t, true, false)
|
||||||
|
sign := priv.Sign(msg)
|
||||||
|
runCase(t, true, false, sign)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("invalid signature", func(t *testing.T) {
|
||||||
|
sign := priv.Sign(msg)
|
||||||
|
sign[0] = ^sign[0]
|
||||||
|
runCase(t, false, false, sign, priv.PublicKey().Bytes())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("invalid public key", func(t *testing.T) {
|
||||||
|
sign := priv.Sign(msg)
|
||||||
|
pub := priv.PublicKey().Bytes()
|
||||||
|
pub[0] = 0xFF // invalid prefix
|
||||||
|
runCase(t, true, false, sign, pub)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ var (
|
||||||
ecdsaSecp256k1VerifyID = interopnames.ToID([]byte(interopnames.NeoCryptoVerifyWithECDsaSecp256k1))
|
ecdsaSecp256k1VerifyID = interopnames.ToID([]byte(interopnames.NeoCryptoVerifyWithECDsaSecp256k1))
|
||||||
ecdsaSecp256r1CheckMultisigID = interopnames.ToID([]byte(interopnames.NeoCryptoCheckMultisigWithECDsaSecp256r1))
|
ecdsaSecp256r1CheckMultisigID = interopnames.ToID([]byte(interopnames.NeoCryptoCheckMultisigWithECDsaSecp256r1))
|
||||||
ecdsaSecp256k1CheckMultisigID = interopnames.ToID([]byte(interopnames.NeoCryptoCheckMultisigWithECDsaSecp256k1))
|
ecdsaSecp256k1CheckMultisigID = interopnames.ToID([]byte(interopnames.NeoCryptoCheckMultisigWithECDsaSecp256k1))
|
||||||
|
neoCryptoCheckSigID = interopnames.ToID([]byte(interopnames.NeoCryptoCheckSig))
|
||||||
)
|
)
|
||||||
|
|
||||||
var cryptoInterops = []interop.Function{
|
var cryptoInterops = []interop.Function{
|
||||||
|
@ -17,6 +18,7 @@ var cryptoInterops = []interop.Function{
|
||||||
{ID: ecdsaSecp256k1VerifyID, Func: ECDSASecp256k1Verify},
|
{ID: ecdsaSecp256k1VerifyID, Func: ECDSASecp256k1Verify},
|
||||||
{ID: ecdsaSecp256r1CheckMultisigID, Func: ECDSASecp256r1CheckMultisig},
|
{ID: ecdsaSecp256r1CheckMultisigID, Func: ECDSASecp256r1CheckMultisig},
|
||||||
{ID: ecdsaSecp256k1CheckMultisigID, Func: ECDSASecp256k1CheckMultisig},
|
{ID: ecdsaSecp256k1CheckMultisigID, Func: ECDSASecp256k1CheckMultisig},
|
||||||
|
{ID: neoCryptoCheckSigID, Func: ECDSASecp256r1CheckSig},
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
|
@ -41,6 +41,7 @@ const (
|
||||||
NeoCryptoVerifyWithECDsaSecp256k1 = "Neo.Crypto.VerifyWithECDsaSecp256k1"
|
NeoCryptoVerifyWithECDsaSecp256k1 = "Neo.Crypto.VerifyWithECDsaSecp256k1"
|
||||||
NeoCryptoCheckMultisigWithECDsaSecp256r1 = "Neo.Crypto.CheckMultisigWithECDsaSecp256r1"
|
NeoCryptoCheckMultisigWithECDsaSecp256r1 = "Neo.Crypto.CheckMultisigWithECDsaSecp256r1"
|
||||||
NeoCryptoCheckMultisigWithECDsaSecp256k1 = "Neo.Crypto.CheckMultisigWithECDsaSecp256k1"
|
NeoCryptoCheckMultisigWithECDsaSecp256k1 = "Neo.Crypto.CheckMultisigWithECDsaSecp256k1"
|
||||||
|
NeoCryptoCheckSig = "Neo.Crypto.CheckSig"
|
||||||
)
|
)
|
||||||
|
|
||||||
var names = []string{
|
var names = []string{
|
||||||
|
@ -83,4 +84,5 @@ var names = []string{
|
||||||
NeoCryptoVerifyWithECDsaSecp256k1,
|
NeoCryptoVerifyWithECDsaSecp256k1,
|
||||||
NeoCryptoCheckMultisigWithECDsaSecp256r1,
|
NeoCryptoCheckMultisigWithECDsaSecp256r1,
|
||||||
NeoCryptoCheckMultisigWithECDsaSecp256k1,
|
NeoCryptoCheckMultisigWithECDsaSecp256k1,
|
||||||
|
NeoCryptoCheckSig,
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,6 +81,7 @@ var neoInterops = []interop.Function{
|
||||||
Price: fee.ECDSAVerifyPrice, ParamCount: 3},
|
Price: fee.ECDSAVerifyPrice, ParamCount: 3},
|
||||||
{Name: interopnames.NeoCryptoCheckMultisigWithECDsaSecp256r1, Func: crypto.ECDSASecp256r1CheckMultisig, Price: 0, ParamCount: 3},
|
{Name: interopnames.NeoCryptoCheckMultisigWithECDsaSecp256r1, Func: crypto.ECDSASecp256r1CheckMultisig, Price: 0, ParamCount: 3},
|
||||||
{Name: interopnames.NeoCryptoCheckMultisigWithECDsaSecp256k1, Func: crypto.ECDSASecp256k1CheckMultisig, Price: 0, ParamCount: 3},
|
{Name: interopnames.NeoCryptoCheckMultisigWithECDsaSecp256k1, Func: crypto.ECDSASecp256k1CheckMultisig, Price: 0, ParamCount: 3},
|
||||||
|
{Name: interopnames.NeoCryptoCheckSig, Func: crypto.ECDSASecp256r1CheckSig, Price: fee.ECDSAVerifyPrice, ParamCount: 2},
|
||||||
}
|
}
|
||||||
|
|
||||||
// initIDinInteropsSlice initializes IDs from names in one given
|
// initIDinInteropsSlice initializes IDs from names in one given
|
||||||
|
|
|
@ -31,3 +31,9 @@ func ECDSASecp256r1CheckMultisig(msg []byte, pubs []interop.PublicKey, sigs []in
|
||||||
func ECDSASecp256k1CheckMultisig(msg []byte, pubs []interop.PublicKey, sigs []interop.Signature) bool {
|
func ECDSASecp256k1CheckMultisig(msg []byte, pubs []interop.PublicKey, sigs []interop.Signature) bool {
|
||||||
return neogointernal.Syscall3("Neo.Crypto.CheckMultisigWithECDsaSecp256k1", msg, pubs, sigs).(bool)
|
return neogointernal.Syscall3("Neo.Crypto.CheckMultisigWithECDsaSecp256k1", msg, pubs, sigs).(bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CheckSig checks that sig is correct script-container's signature for a given pub
|
||||||
|
// (serialized public key). It uses `Neo.Crypto.CheckSig` syscall.
|
||||||
|
func CheckSig(pub interop.PublicKey, sig interop.Signature) bool {
|
||||||
|
return neogointernal.Syscall2("Neo.Crypto.CheckSig", pub, sig).(bool)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue