mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-12-25 13:56:35 +00:00
6a4e312eac
We have additional logic for getting BaseExecFee policy value. This logic should be moved to interop context instead of being in Policer, because Policer is just an interface over Policy contract. After moving this logic to interop context, we need to use it to define BaseExecFee instead of (Policer).BaseExecFee. Thus, moving (*Blockchain).GetPrice to (*Context).GetPrice is necessary.
101 lines
3.1 KiB
Go
101 lines
3.1 KiB
Go
package crypto
|
|
|
|
import (
|
|
"crypto/elliptic"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/btcsuite/btcd/btcec"
|
|
"github.com/nspcc-dev/neo-go/pkg/core/fee"
|
|
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
|
"github.com/nspcc-dev/neo-go/pkg/crypto"
|
|
"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/util"
|
|
"github.com/nspcc-dev/neo-go/pkg/vm"
|
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
|
)
|
|
|
|
// ECDSASecp256r1Verify checks ECDSA signature using Secp256r1 elliptic curve.
|
|
func ECDSASecp256r1Verify(ic *interop.Context) error {
|
|
return ecdsaVerify(ic, elliptic.P256())
|
|
}
|
|
|
|
// ECDSASecp256k1Verify checks ECDSA signature using Secp256k1 elliptic curve
|
|
func ECDSASecp256k1Verify(ic *interop.Context) error {
|
|
return ecdsaVerify(ic, btcec.S256())
|
|
}
|
|
|
|
// ecdsaVerify is internal representation of ECDSASecp256k1Verify and
|
|
// ECDSASecp256r1Verify.
|
|
func ecdsaVerify(ic *interop.Context, curve elliptic.Curve) error {
|
|
hashToCheck, err := getMessageHash(ic, ic.VM.Estack().Pop().Item())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
keyb := ic.VM.Estack().Pop().Bytes()
|
|
signature := ic.VM.Estack().Pop().Bytes()
|
|
pkey, err := keys.NewPublicKeyFromBytes(keyb, curve)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
res := pkey.Verify(signature, hashToCheck.BytesBE())
|
|
ic.VM.Estack().PushVal(res)
|
|
return nil
|
|
}
|
|
|
|
// ECDSASecp256r1CheckMultisig checks multiple ECDSA signatures at once using
|
|
// Secp256r1 elliptic curve.
|
|
func ECDSASecp256r1CheckMultisig(ic *interop.Context) error {
|
|
return ecdsaCheckMultisig(ic, elliptic.P256())
|
|
}
|
|
|
|
// ECDSASecp256k1CheckMultisig checks multiple ECDSA signatures at once using
|
|
// Secp256k1 elliptic curve.
|
|
func ECDSASecp256k1CheckMultisig(ic *interop.Context) error {
|
|
return ecdsaCheckMultisig(ic, btcec.S256())
|
|
}
|
|
|
|
// ecdsaCheckMultisig is internal representation of ECDSASecp256r1CheckMultisig and
|
|
// ECDSASecp256k1CheckMultisig
|
|
func ecdsaCheckMultisig(ic *interop.Context, curve elliptic.Curve) error {
|
|
hashToCheck, err := getMessageHash(ic, ic.VM.Estack().Pop().Item())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
pkeys, err := ic.VM.Estack().PopSigElements()
|
|
if err != nil {
|
|
return fmt.Errorf("wrong parameters: %w", err)
|
|
}
|
|
if !ic.VM.AddGas(ic.BaseExecFee() * fee.ECDSAVerifyPrice * int64(len(pkeys))) {
|
|
return errors.New("gas limit exceeded")
|
|
}
|
|
sigs, err := ic.VM.Estack().PopSigElements()
|
|
if err != nil {
|
|
return fmt.Errorf("wrong parameters: %w", err)
|
|
}
|
|
// It's ok to have more keys than there are signatures (it would
|
|
// just mean that some keys didn't sign), but not the other way around.
|
|
if len(pkeys) < len(sigs) {
|
|
return errors.New("more signatures than there are keys")
|
|
}
|
|
sigok := vm.CheckMultisigPar(ic.VM, curve, hashToCheck.BytesBE(), pkeys, sigs)
|
|
ic.VM.Estack().PushVal(sigok)
|
|
return nil
|
|
}
|
|
|
|
func getMessageHash(ic *interop.Context, item stackitem.Item) (util.Uint256, error) {
|
|
var msg []byte
|
|
switch val := item.(type) {
|
|
case *stackitem.Interop:
|
|
return val.Value().(crypto.Verifiable).GetSignedHash(), nil
|
|
case stackitem.Null:
|
|
return ic.Container.GetSignedHash(), nil
|
|
default:
|
|
var err error
|
|
if msg, err = val.TryBytes(); err != nil {
|
|
return util.Uint256{}, err
|
|
}
|
|
}
|
|
return hash.Sha256(msg), nil
|
|
}
|