native: extend CryptoLib's verifyWithECDsa with hasher parameter
Replace native CryptoLib's verifyWithECDsa `curve` parameter by `curveHash` parameter which is a enum over supported pairs of named curves and hash functions. Even though this change is a compatible extension of the protocol, it changes the genesis state due to parameter renaming. But we're going to resync chain in 3.7 release anyway, so it's not a big deal. Also, we need to check mainnet and testnet compatibility in case if anyone has ever called verifyWithECDsa with 24 or 25 `curve` value. Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
This commit is contained in:
parent
2617e3b4f9
commit
9ef71b9226
6 changed files with 117 additions and 73 deletions
|
@ -74,8 +74,10 @@ func TestRoleManagementRole(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCryptoLibNamedCurve(t *testing.T) {
|
func TestCryptoLibNamedCurve(t *testing.T) {
|
||||||
require.EqualValues(t, native.Secp256k1, crypto.Secp256k1)
|
require.EqualValues(t, native.Secp256k1Sha256, crypto.Secp256k1Sha256)
|
||||||
require.EqualValues(t, native.Secp256r1, crypto.Secp256r1)
|
require.EqualValues(t, native.Secp256r1Sha256, crypto.Secp256r1Sha256)
|
||||||
|
require.EqualValues(t, native.Secp256k1Keccak256, crypto.Secp256k1Keccak256)
|
||||||
|
require.EqualValues(t, native.Secp256r1Keccak256, crypto.Secp256r1Keccak256)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOracleContractValues(t *testing.T) {
|
func TestOracleContractValues(t *testing.T) {
|
||||||
|
@ -233,7 +235,7 @@ func TestNativeHelpersCompile(t *testing.T) {
|
||||||
{"sha256", []string{"[]byte{1, 2, 3}"}},
|
{"sha256", []string{"[]byte{1, 2, 3}"}},
|
||||||
{"ripemd160", []string{"[]byte{1, 2, 3}"}},
|
{"ripemd160", []string{"[]byte{1, 2, 3}"}},
|
||||||
{"murmur32", []string{"[]byte{1, 2, 3}", "123"}},
|
{"murmur32", []string{"[]byte{1, 2, 3}", "123"}},
|
||||||
{"verifyWithECDsa", []string{"[]byte{1, 2, 3}", pub, sig, "crypto.Secp256k1"}},
|
{"verifyWithECDsa", []string{"[]byte{1, 2, 3}", pub, sig, "crypto.Secp256k1Sha256"}},
|
||||||
{"bls12381Serialize", []string{"crypto.Bls12381Point{}"}},
|
{"bls12381Serialize", []string{"crypto.Bls12381Point{}"}},
|
||||||
{"bls12381Deserialize", []string{"[]byte{1, 2, 3}"}},
|
{"bls12381Deserialize", []string{"[]byte{1, 2, 3}"}},
|
||||||
{"bls12381Equal", []string{"crypto.Bls12381Point{}", "crypto.Bls12381Point{}"}},
|
{"bls12381Equal", []string{"crypto.Bls12381Point{}", "crypto.Bls12381Point{}"}},
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
"github.com/twmb/murmur3"
|
"github.com/twmb/murmur3"
|
||||||
"golang.org/x/crypto/sha3"
|
"golang.org/x/crypto/sha3"
|
||||||
|
@ -28,13 +29,18 @@ type Crypto struct {
|
||||||
interop.ContractMD
|
interop.ContractMD
|
||||||
}
|
}
|
||||||
|
|
||||||
// NamedCurve identifies named elliptic curves.
|
// HashFunc is a delegate representing a hasher function with 256 bytes output length.
|
||||||
type NamedCurve byte
|
type HashFunc func([]byte) util.Uint256
|
||||||
|
|
||||||
// Various named elliptic curves.
|
// NamedCurveHash identifies a pair of named elliptic curve and hash function.
|
||||||
|
type NamedCurveHash byte
|
||||||
|
|
||||||
|
// Various pairs of named elliptic curves and hash functions.
|
||||||
const (
|
const (
|
||||||
Secp256k1 NamedCurve = 22
|
Secp256k1Sha256 NamedCurveHash = 22
|
||||||
Secp256r1 NamedCurve = 23
|
Secp256r1Sha256 NamedCurveHash = 23
|
||||||
|
Secp256k1Keccak256 NamedCurveHash = 24
|
||||||
|
Secp256r1Keccak256 NamedCurveHash = 25
|
||||||
)
|
)
|
||||||
|
|
||||||
const cryptoContractID = -3
|
const cryptoContractID = -3
|
||||||
|
@ -63,7 +69,7 @@ func newCrypto() *Crypto {
|
||||||
manifest.NewParameter("message", smartcontract.ByteArrayType),
|
manifest.NewParameter("message", smartcontract.ByteArrayType),
|
||||||
manifest.NewParameter("pubkey", smartcontract.ByteArrayType),
|
manifest.NewParameter("pubkey", smartcontract.ByteArrayType),
|
||||||
manifest.NewParameter("signature", smartcontract.ByteArrayType),
|
manifest.NewParameter("signature", smartcontract.ByteArrayType),
|
||||||
manifest.NewParameter("curve", smartcontract.IntegerType))
|
manifest.NewParameter("curveHash", smartcontract.IntegerType))
|
||||||
md = newMethodAndPrice(c.verifyWithECDsa, 1<<15, callflag.NoneFlag)
|
md = newMethodAndPrice(c.verifyWithECDsa, 1<<15, callflag.NoneFlag)
|
||||||
c.AddMethod(md, desc)
|
c.AddMethod(md, desc)
|
||||||
|
|
||||||
|
@ -142,7 +148,6 @@ func (c *Crypto) verifyWithECDsa(_ *interop.Context, args []stackitem.Item) stac
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Errorf("invalid message stackitem: %w", err))
|
panic(fmt.Errorf("invalid message stackitem: %w", err))
|
||||||
}
|
}
|
||||||
hashToCheck := hash.Sha256(msg)
|
|
||||||
pubkey, err := args[1].TryBytes()
|
pubkey, err := args[1].TryBytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Errorf("invalid pubkey stackitem: %w", err))
|
panic(fmt.Errorf("invalid pubkey stackitem: %w", err))
|
||||||
|
@ -151,10 +156,11 @@ func (c *Crypto) verifyWithECDsa(_ *interop.Context, args []stackitem.Item) stac
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Errorf("invalid signature stackitem: %w", err))
|
panic(fmt.Errorf("invalid signature stackitem: %w", err))
|
||||||
}
|
}
|
||||||
curve, err := curveFromStackitem(args[3])
|
curve, hasher, err := curveHasherFromStackitem(args[3])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Errorf("invalid curve stackitem: %w", err))
|
panic(fmt.Errorf("invalid curveHash stackitem: %w", err))
|
||||||
}
|
}
|
||||||
|
hashToCheck := hasher(msg)
|
||||||
pkey, err := keys.NewPublicKeyFromBytes(pubkey, curve)
|
pkey, err := keys.NewPublicKeyFromBytes(pubkey, curve)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Errorf("failed to decode pubkey: %w", err))
|
panic(fmt.Errorf("failed to decode pubkey: %w", err))
|
||||||
|
@ -163,22 +169,26 @@ func (c *Crypto) verifyWithECDsa(_ *interop.Context, args []stackitem.Item) stac
|
||||||
return stackitem.NewBool(res)
|
return stackitem.NewBool(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
func curveFromStackitem(si stackitem.Item) (elliptic.Curve, error) {
|
func curveHasherFromStackitem(si stackitem.Item) (elliptic.Curve, HashFunc, error) {
|
||||||
curve, err := si.TryInteger()
|
curve, err := si.TryInteger()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
if !curve.IsInt64() {
|
if !curve.IsInt64() {
|
||||||
return nil, errors.New("not an int64")
|
return nil, nil, errors.New("not an int64")
|
||||||
}
|
}
|
||||||
c := curve.Int64()
|
c := curve.Int64()
|
||||||
switch c {
|
switch c {
|
||||||
case int64(Secp256k1):
|
case int64(Secp256k1Sha256):
|
||||||
return secp256k1.S256(), nil
|
return secp256k1.S256(), hash.Sha256, nil
|
||||||
case int64(Secp256r1):
|
case int64(Secp256r1Sha256):
|
||||||
return elliptic.P256(), nil
|
return elliptic.P256(), hash.Sha256, nil
|
||||||
|
case int64(Secp256k1Keccak256):
|
||||||
|
return secp256k1.S256(), Keccak256, nil
|
||||||
|
case int64(Secp256r1Keccak256):
|
||||||
|
return elliptic.P256(), Keccak256, nil
|
||||||
default:
|
default:
|
||||||
return nil, errors.New("unsupported curve type")
|
return nil, nil, errors.New("unsupported curve/hash type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,13 +305,7 @@ func (c *Crypto) keccak256(_ *interop.Context, args []stackitem.Item) stackitem.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
return stackitem.NewByteArray(Keccak256(bs).BytesBE())
|
||||||
digest := sha3.NewLegacyKeccak256()
|
|
||||||
_, err = digest.Write(bs)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return stackitem.NewByteArray(digest.Sum(nil))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Metadata implements the Contract interface.
|
// Metadata implements the Contract interface.
|
||||||
|
@ -333,3 +337,14 @@ func (c *Crypto) PostPersist(ic *interop.Context) error {
|
||||||
func (c *Crypto) ActiveIn() *config.Hardfork {
|
func (c *Crypto) ActiveIn() *config.Hardfork {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Keccak256 hashes the incoming byte slice using the
|
||||||
|
// keccak256 algorithm.
|
||||||
|
func Keccak256(data []byte) util.Uint256 {
|
||||||
|
var hash util.Uint256
|
||||||
|
hasher := sha3.NewLegacyKeccak256()
|
||||||
|
_, _ = hasher.Write(data)
|
||||||
|
|
||||||
|
hasher.Sum(hash[:0])
|
||||||
|
return hash
|
||||||
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
|
|
||||||
"github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
|
"github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
"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/crypto/keys"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
|
@ -118,29 +119,44 @@ func TestMurmur32(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCryptoLibVerifyWithECDsa(t *testing.T) {
|
func TestCryptoLibVerifyWithECDsa(t *testing.T) {
|
||||||
t.Run("R1", func(t *testing.T) {
|
t.Run("R1 sha256", func(t *testing.T) {
|
||||||
testECDSAVerify(t, Secp256r1)
|
testECDSAVerify(t, Secp256r1Sha256)
|
||||||
})
|
})
|
||||||
t.Run("K1", func(t *testing.T) {
|
t.Run("K1 sha256", func(t *testing.T) {
|
||||||
testECDSAVerify(t, Secp256k1)
|
testECDSAVerify(t, Secp256k1Sha256)
|
||||||
|
})
|
||||||
|
t.Run("R1 keccak256", func(t *testing.T) {
|
||||||
|
testECDSAVerify(t, Secp256r1Keccak256)
|
||||||
|
})
|
||||||
|
t.Run("K1 keccak256", func(t *testing.T) {
|
||||||
|
testECDSAVerify(t, Secp256k1Keccak256)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func testECDSAVerify(t *testing.T, curve NamedCurve) {
|
func testECDSAVerify(t *testing.T, curve NamedCurveHash) {
|
||||||
var (
|
var (
|
||||||
priv *keys.PrivateKey
|
priv *keys.PrivateKey
|
||||||
err error
|
err error
|
||||||
c = newCrypto()
|
c = newCrypto()
|
||||||
ic = &interop.Context{VM: vm.New()}
|
ic = &interop.Context{VM: vm.New()}
|
||||||
actual stackitem.Item
|
actual stackitem.Item
|
||||||
|
hasher HashFunc
|
||||||
)
|
)
|
||||||
switch curve {
|
switch curve {
|
||||||
case Secp256k1:
|
case Secp256k1Sha256:
|
||||||
priv, err = keys.NewSecp256k1PrivateKey()
|
priv, err = keys.NewSecp256k1PrivateKey()
|
||||||
case Secp256r1:
|
hasher = hash.Sha256
|
||||||
|
case Secp256r1Sha256:
|
||||||
priv, err = keys.NewPrivateKey()
|
priv, err = keys.NewPrivateKey()
|
||||||
|
hasher = hash.Sha256
|
||||||
|
case Secp256k1Keccak256:
|
||||||
|
priv, err = keys.NewSecp256k1PrivateKey()
|
||||||
|
hasher = Keccak256
|
||||||
|
case Secp256r1Keccak256:
|
||||||
|
priv, err = keys.NewPrivateKey()
|
||||||
|
hasher = Keccak256
|
||||||
default:
|
default:
|
||||||
t.Fatal("unknown curve")
|
t.Fatal("unknown curve/hash")
|
||||||
}
|
}
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
@ -162,7 +178,7 @@ func testECDSAVerify(t *testing.T, curve NamedCurve) {
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := []byte("test message")
|
msg := []byte("test message")
|
||||||
sign := priv.Sign(msg)
|
sign := priv.SignHash(hasher(msg))
|
||||||
|
|
||||||
t.Run("bad message item", func(t *testing.T) {
|
t.Run("bad message item", func(t *testing.T) {
|
||||||
runCase(t, true, false, stackitem.NewInterop("cheburek"), priv.PublicKey().Bytes(), sign, int64(curve))
|
runCase(t, true, false, stackitem.NewInterop("cheburek"), priv.PublicKey().Bytes(), sign, int64(curve))
|
||||||
|
@ -254,3 +270,13 @@ func TestCryptolib_ScalarFromBytes_Compat(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestKeccak256(t *testing.T) {
|
||||||
|
input := []byte("hello")
|
||||||
|
data := Keccak256(input)
|
||||||
|
|
||||||
|
expected := "1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8"
|
||||||
|
actual := hex.EncodeToString(data.BytesBE())
|
||||||
|
|
||||||
|
require.Equal(t, expected, actual)
|
||||||
|
}
|
||||||
|
|
|
@ -75,14 +75,13 @@ func TestCryptoLib_KoblitzVerificationScript(t *testing.T) {
|
||||||
// This transaction (along with the network magic) should be signed by the user's Koblitz private key.
|
// This transaction (along with the network magic) should be signed by the user's Koblitz private key.
|
||||||
msg := constructMsg(t, uint32(e.Chain.GetConfig().Magic), tx)
|
msg := constructMsg(t, uint32(e.Chain.GetConfig().Magic), tx)
|
||||||
|
|
||||||
// The user has to sign the Sha256 hash of the message by his Koblitz key.
|
// The user has to sign the hash of the message by his Koblitz key.
|
||||||
// Please, note that this Sha256 hash may easily be replaced by Keccaak hash via minor adjustment of
|
// Please, note that this Keccak256 hash may easily be replaced by sha256 hash if needed.
|
||||||
// CryptoLib's `verifyWithECDsa` behaviour (if needed).
|
signature := pk.SignHash(native.Keccak256(msg))
|
||||||
signature := pk.SignHash(hash.Sha256(msg))
|
|
||||||
|
|
||||||
// Ensure that signature verification passes. This line here is just for testing purposes,
|
// Ensure that signature verification passes. This line here is just for testing purposes,
|
||||||
// it won't be present in the real code.
|
// it won't be present in the real code.
|
||||||
require.True(t, pk.PublicKey().Verify(signature, hash.Sha256(msg).BytesBE()))
|
require.True(t, pk.PublicKey().Verify(signature, native.Keccak256(msg).BytesBE()))
|
||||||
|
|
||||||
// Build invocation witness script for the user's account.
|
// Build invocation witness script for the user's account.
|
||||||
invBytes := buildKoblitzInvocationScript(t, signature)
|
invBytes := buildKoblitzInvocationScript(t, signature)
|
||||||
|
@ -105,32 +104,32 @@ func TestCryptoLib_KoblitzVerificationScript(t *testing.T) {
|
||||||
|
|
||||||
// The simplest witness verification script with low length and low execution cost
|
// The simplest witness verification script with low length and low execution cost
|
||||||
// (98 bytes, 2092530 GAS including Invocation script execution).
|
// (98 bytes, 2092530 GAS including Invocation script execution).
|
||||||
// The user has to sign the sha256([var-bytes-network-magic, txHash-bytes-BE]).
|
// The user has to sign the keccak256([var-bytes-network-magic, txHash-bytes-BE]).
|
||||||
check(t, buildKoblitzVerificationScriptSimpleSingleHash, constructMessageNoHash)
|
check(t, buildKoblitzVerificationScriptSimpleSingleHash, constructMessageNoHash)
|
||||||
|
|
||||||
// Even more simple witness verification script with low length and low execution cost
|
// Even more simple witness verification script with low length and low execution cost
|
||||||
// (95 bytes, 2092320 GAS including Invocation script execution).
|
// (95 bytes, 2092320 GAS including Invocation script execution).
|
||||||
// The user has to sign the sha256([var-bytes-network-magic, txHash-bytes-BE]).
|
// The user has to sign the keccak256([var-bytes-network-magic, txHash-bytes-BE]).
|
||||||
// The difference is that network magic is a static value, thus, both verification script and
|
// The difference is that network magic is a static value, thus, both verification script and
|
||||||
// user address are network-specific.
|
// user address are network-specific.
|
||||||
check(t, buildKoblitzVerificationScriptSimpleSingleHashStaticMagic, constructMessageNoHash)
|
check(t, buildKoblitzVerificationScriptSimpleSingleHashStaticMagic, constructMessageNoHash)
|
||||||
|
|
||||||
// More complicated verification script with higher length and higher execution cost
|
// More complicated verification script with higher length and higher execution cost
|
||||||
// (136 bytes, 4120620 GAS including Invocation script execution).
|
// (136 bytes, 4120620 GAS including Invocation script execution).
|
||||||
// The user has to sign the sha256(sha256([var-bytes-network-magic, txHash-bytes-BE])).
|
// The user has to sign the keccak256(sha256([var-bytes-network-magic, txHash-bytes-BE])).
|
||||||
check(t, buildKoblitzVerificationScriptSimple, constructMessageSimple)
|
check(t, buildKoblitzVerificationScriptSimple, constructMessageSimple)
|
||||||
|
|
||||||
// Witness verification script that follows the existing standard CheckSig account generation rules
|
// Witness verification script that follows the existing standard CheckSig account generation rules
|
||||||
// and has larger length and higher execution cost.
|
// and has larger length and higher execution cost.
|
||||||
// (186 bytes, 5116020 GAS including Invocation script execution).
|
// (186 bytes, 5116020 GAS including Invocation script execution).
|
||||||
// The user has to sign the sha256(sha256([4-bytes-network-magic-LE, txHash-bytes-BE]))
|
// The user has to sign the keccak256(sha256([4-bytes-network-magic-LE, txHash-bytes-BE]))
|
||||||
check(t, buildKoblitzVerificationScriptCompat, constructMessageCompat)
|
check(t, buildKoblitzVerificationScriptCompat, constructMessageCompat)
|
||||||
}
|
}
|
||||||
|
|
||||||
// buildKoblitzVerificationScriptSimpleSingleHash builds witness verification script for Koblitz public key.
|
// buildKoblitzVerificationScriptSimpleSingleHash builds witness verification script for Koblitz public key.
|
||||||
// This method differs from buildKoblitzVerificationScriptCompat in that it checks
|
// This method differs from buildKoblitzVerificationScriptCompat in that it checks
|
||||||
//
|
//
|
||||||
// sha256([var-bytes-network-magic, txHash-bytes-BE])
|
// keccak256([var-bytes-network-magic, txHash-bytes-BE])
|
||||||
//
|
//
|
||||||
// instead of (comparing with N3)
|
// instead of (comparing with N3)
|
||||||
//
|
//
|
||||||
|
@ -141,9 +140,9 @@ func buildKoblitzVerificationScriptSimpleSingleHash(t *testing.T, pub *keys.Publ
|
||||||
// vrf is witness verification script corresponding to the pub.
|
// vrf is witness verification script corresponding to the pub.
|
||||||
// vrf is witness verification script corresponding to the pk.
|
// vrf is witness verification script corresponding to the pk.
|
||||||
vrf := io.NewBufBinWriter()
|
vrf := io.NewBufBinWriter()
|
||||||
emit.Int(vrf.BinWriter, int64(native.Secp256k1)) // push Koblitz curve identifier.
|
emit.Int(vrf.BinWriter, int64(native.Secp256k1Keccak256)) // push Koblitz curve identifier.
|
||||||
emit.Opcodes(vrf.BinWriter, opcode.SWAP) // swap curve identifier with the signature.
|
emit.Opcodes(vrf.BinWriter, opcode.SWAP) // swap curve identifier with the signature.
|
||||||
emit.Bytes(vrf.BinWriter, pub.Bytes()) // emit the caller's public key.
|
emit.Bytes(vrf.BinWriter, pub.Bytes()) // emit the caller's public key.
|
||||||
// Construct and push the signed message. The signed message is effectively the network-dependent transaction hash,
|
// Construct and push the signed message. The signed message is effectively the network-dependent transaction hash,
|
||||||
// i.e. msg = [network-magic-bytes, tx.Hash()]
|
// i.e. msg = [network-magic-bytes, tx.Hash()]
|
||||||
// Firstly, retrieve network magic (it's uint32 wrapped into BigInteger and represented as Integer stackitem on stack).
|
// Firstly, retrieve network magic (it's uint32 wrapped into BigInteger and represented as Integer stackitem on stack).
|
||||||
|
@ -164,7 +163,7 @@ func buildKoblitzVerificationScriptSimpleSingleHash(t *testing.T, pub *keys.Publ
|
||||||
// READY: loaded 98 instructions
|
// READY: loaded 98 instructions
|
||||||
// NEO-GO-VM 0 > ops
|
// NEO-GO-VM 0 > ops
|
||||||
// INDEX OPCODE PARAMETER
|
// INDEX OPCODE PARAMETER
|
||||||
// 0 PUSHINT8 22 (16) <<
|
// 0 PUSHINT8 24 (18) <<
|
||||||
// 2 SWAP
|
// 2 SWAP
|
||||||
// 3 PUSHDATA1 0363d7a48125a76cdea6e098c9f128e82920ed428e5fb4caf1d7f81c16cad0c205
|
// 3 PUSHDATA1 0363d7a48125a76cdea6e098c9f128e82920ed428e5fb4caf1d7f81c16cad0c205
|
||||||
// 38 SYSCALL System.Runtime.GetNetwork (c5fba0e0)
|
// 38 SYSCALL System.Runtime.GetNetwork (c5fba0e0)
|
||||||
|
@ -183,7 +182,7 @@ func buildKoblitzVerificationScriptSimpleSingleHash(t *testing.T, pub *keys.Publ
|
||||||
// buildKoblitzVerificationScriptSimpleSingleHashStaticMagic builds witness verification script for Koblitz public key.
|
// buildKoblitzVerificationScriptSimpleSingleHashStaticMagic builds witness verification script for Koblitz public key.
|
||||||
// This method differs from buildKoblitzVerificationScriptCompat in that it checks
|
// This method differs from buildKoblitzVerificationScriptCompat in that it checks
|
||||||
//
|
//
|
||||||
// sha256([var-bytes-network-magic, txHash-bytes-BE])
|
// keccak256([var-bytes-network-magic, txHash-bytes-BE])
|
||||||
//
|
//
|
||||||
// instead of (comparing with N3)
|
// instead of (comparing with N3)
|
||||||
//
|
//
|
||||||
|
@ -197,9 +196,9 @@ func buildKoblitzVerificationScriptSimpleSingleHashStaticMagic(t *testing.T, pub
|
||||||
// vrf is witness verification script corresponding to the pub.
|
// vrf is witness verification script corresponding to the pub.
|
||||||
// vrf is witness verification script corresponding to the pk.
|
// vrf is witness verification script corresponding to the pk.
|
||||||
vrf := io.NewBufBinWriter()
|
vrf := io.NewBufBinWriter()
|
||||||
emit.Int(vrf.BinWriter, int64(native.Secp256k1)) // push Koblitz curve identifier.
|
emit.Int(vrf.BinWriter, int64(native.Secp256k1Keccak256)) // push Koblitz curve identifier.
|
||||||
emit.Opcodes(vrf.BinWriter, opcode.SWAP) // swap curve identifier with the signature.
|
emit.Opcodes(vrf.BinWriter, opcode.SWAP) // swap curve identifier with the signature.
|
||||||
emit.Bytes(vrf.BinWriter, pub.Bytes()) // emit the caller's public key.
|
emit.Bytes(vrf.BinWriter, pub.Bytes()) // emit the caller's public key.
|
||||||
// Construct and push the signed message. The signed message is effectively the network-dependent transaction hash,
|
// Construct and push the signed message. The signed message is effectively the network-dependent transaction hash,
|
||||||
// i.e. msg = [network-magic-bytes, tx.Hash()]
|
// i.e. msg = [network-magic-bytes, tx.Hash()]
|
||||||
// Firstly, push static network magic (it's 42 for unit test chain).
|
// Firstly, push static network magic (it's 42 for unit test chain).
|
||||||
|
@ -220,7 +219,7 @@ func buildKoblitzVerificationScriptSimpleSingleHashStaticMagic(t *testing.T, pub
|
||||||
// READY: loaded 95 instructions
|
// READY: loaded 95 instructions
|
||||||
// NEO-GO-VM 0 > ops
|
// NEO-GO-VM 0 > ops
|
||||||
// INDEX OPCODE PARAMETER
|
// INDEX OPCODE PARAMETER
|
||||||
// 0 PUSHINT8 22 (16) <<
|
// 0 PUSHINT8 24 (18) <<
|
||||||
// 2 SWAP
|
// 2 SWAP
|
||||||
// 3 PUSHDATA1 0296e13080ade92a2ab722338c2a249ee8d83a14f649c68321664165f06bd110bd
|
// 3 PUSHDATA1 0296e13080ade92a2ab722338c2a249ee8d83a14f649c68321664165f06bd110bd
|
||||||
// 38 PUSHINT8 42 (2a)
|
// 38 PUSHINT8 42 (2a)
|
||||||
|
@ -239,7 +238,7 @@ func buildKoblitzVerificationScriptSimpleSingleHashStaticMagic(t *testing.T, pub
|
||||||
// buildKoblitzVerificationScriptSimple builds witness verification script for Koblitz public key.
|
// buildKoblitzVerificationScriptSimple builds witness verification script for Koblitz public key.
|
||||||
// This method differs from buildKoblitzVerificationScriptCompat in that it checks
|
// This method differs from buildKoblitzVerificationScriptCompat in that it checks
|
||||||
//
|
//
|
||||||
// sha256(sha256([var-bytes-network-magic, txHash-bytes-BE]))
|
// keccak256(sha256([var-bytes-network-magic, txHash-bytes-BE]))
|
||||||
//
|
//
|
||||||
// instead of (comparing with N3)
|
// instead of (comparing with N3)
|
||||||
//
|
//
|
||||||
|
@ -255,9 +254,9 @@ func buildKoblitzVerificationScriptSimple(t *testing.T, pub *keys.PublicKey) []b
|
||||||
// vrf is witness verification script corresponding to the pub.
|
// vrf is witness verification script corresponding to the pub.
|
||||||
// vrf is witness verification script corresponding to the pk.
|
// vrf is witness verification script corresponding to the pk.
|
||||||
vrf := io.NewBufBinWriter()
|
vrf := io.NewBufBinWriter()
|
||||||
emit.Int(vrf.BinWriter, int64(native.Secp256k1)) // push Koblitz curve identifier.
|
emit.Int(vrf.BinWriter, int64(native.Secp256k1Keccak256)) // push Koblitz curve identifier.
|
||||||
emit.Opcodes(vrf.BinWriter, opcode.SWAP) // swap curve identifier with the signature.
|
emit.Opcodes(vrf.BinWriter, opcode.SWAP) // swap curve identifier with the signature.
|
||||||
emit.Bytes(vrf.BinWriter, pub.Bytes()) // emit the caller's public key.
|
emit.Bytes(vrf.BinWriter, pub.Bytes()) // emit the caller's public key.
|
||||||
// Construct and push the signed message. The signed message is effectively the network-dependent transaction hash,
|
// Construct and push the signed message. The signed message is effectively the network-dependent transaction hash,
|
||||||
// i.e. msg = Sha256([network-magic-bytes, tx.Hash()])
|
// i.e. msg = Sha256([network-magic-bytes, tx.Hash()])
|
||||||
// Firstly, retrieve network magic (it's uint32 wrapped into BigInteger and represented as Integer stackitem on stack).
|
// Firstly, retrieve network magic (it's uint32 wrapped into BigInteger and represented as Integer stackitem on stack).
|
||||||
|
@ -280,7 +279,7 @@ func buildKoblitzVerificationScriptSimple(t *testing.T, pub *keys.PublicKey) []b
|
||||||
// READY: loaded 136 instructions
|
// READY: loaded 136 instructions
|
||||||
// NEO-GO-VM 0 > ops
|
// NEO-GO-VM 0 > ops
|
||||||
// INDEX OPCODE PARAMETER
|
// INDEX OPCODE PARAMETER
|
||||||
// 0 PUSHINT8 22 (16) <<
|
// 0 PUSHINT8 24 (18) <<
|
||||||
// 2 SWAP
|
// 2 SWAP
|
||||||
// 3 PUSHDATA1 03a77f137afbb4b68d7a450aa5a28fe335f804c589a808494b4b626eb98707f37d
|
// 3 PUSHDATA1 03a77f137afbb4b68d7a450aa5a28fe335f804c589a808494b4b626eb98707f37d
|
||||||
// 38 SYSCALL System.Runtime.GetNetwork (c5fba0e0)
|
// 38 SYSCALL System.Runtime.GetNetwork (c5fba0e0)
|
||||||
|
@ -305,7 +304,7 @@ func buildKoblitzVerificationScriptSimple(t *testing.T, pub *keys.PublicKey) []b
|
||||||
// buildKoblitzVerificationScript builds custom verification script for the provided Koblitz public key.
|
// buildKoblitzVerificationScript builds custom verification script for the provided Koblitz public key.
|
||||||
// It checks that the following message is signed by the provided public key:
|
// It checks that the following message is signed by the provided public key:
|
||||||
//
|
//
|
||||||
// sha256(sha256([4-bytes-network-magic-LE, txHash-bytes-BE]))
|
// keccak256(sha256([4-bytes-network-magic-LE, txHash-bytes-BE]))
|
||||||
//
|
//
|
||||||
// It produces constant-length verification script (186 bytes) independently of the network parameters.
|
// It produces constant-length verification script (186 bytes) independently of the network parameters.
|
||||||
func buildKoblitzVerificationScriptCompat(t *testing.T, pub *keys.PublicKey) []byte {
|
func buildKoblitzVerificationScriptCompat(t *testing.T, pub *keys.PublicKey) []byte {
|
||||||
|
@ -313,9 +312,9 @@ func buildKoblitzVerificationScriptCompat(t *testing.T, pub *keys.PublicKey) []b
|
||||||
|
|
||||||
// vrf is witness verification script corresponding to the pub.
|
// vrf is witness verification script corresponding to the pub.
|
||||||
vrf := io.NewBufBinWriter()
|
vrf := io.NewBufBinWriter()
|
||||||
emit.Int(vrf.BinWriter, int64(native.Secp256k1)) // push Koblitz curve identifier.
|
emit.Int(vrf.BinWriter, int64(native.Secp256k1Keccak256)) // push Koblitz curve identifier.
|
||||||
emit.Opcodes(vrf.BinWriter, opcode.SWAP) // swap curve identifier with the signature.
|
emit.Opcodes(vrf.BinWriter, opcode.SWAP) // swap curve identifier with the signature.
|
||||||
emit.Bytes(vrf.BinWriter, pub.Bytes()) // emit the caller's public key.
|
emit.Bytes(vrf.BinWriter, pub.Bytes()) // emit the caller's public key.
|
||||||
// Construct and push the signed message. The signed message is effectively the network-dependent transaction hash,
|
// Construct and push the signed message. The signed message is effectively the network-dependent transaction hash,
|
||||||
// i.e. msg = Sha256([4-bytes-network-magic-LE, tx.Hash()])
|
// i.e. msg = Sha256([4-bytes-network-magic-LE, tx.Hash()])
|
||||||
// Firstly, convert network magic (uint32) to LE buffer.
|
// Firstly, convert network magic (uint32) to LE buffer.
|
||||||
|
@ -381,7 +380,7 @@ func buildKoblitzVerificationScriptCompat(t *testing.T, pub *keys.PublicKey) []b
|
||||||
// READY: loaded 186 instructions
|
// READY: loaded 186 instructions
|
||||||
// NEO-GO-VM 0 > ops
|
// NEO-GO-VM 0 > ops
|
||||||
// INDEX OPCODE PARAMETER
|
// INDEX OPCODE PARAMETER
|
||||||
// 0 PUSHINT8 22 (16) <<
|
// 0 PUSHINT8 24 (18) <<
|
||||||
// 2 SWAP
|
// 2 SWAP
|
||||||
// 3 PUSHDATA1 02627ef9c3631e3ccb8fbc4c5b6c49e38ccede5a79afb1e1b0708fbb958a7802d7
|
// 3 PUSHDATA1 02627ef9c3631e3ccb8fbc4c5b6c49e38ccede5a79afb1e1b0708fbb958a7802d7
|
||||||
// 38 SYSCALL System.Runtime.GetNetwork (c5fba0e0)
|
// 38 SYSCALL System.Runtime.GetNetwork (c5fba0e0)
|
||||||
|
|
|
@ -13,13 +13,15 @@ import (
|
||||||
// Hash represents CryptoLib contract hash.
|
// Hash represents CryptoLib contract hash.
|
||||||
const Hash = "\x1b\xf5\x75\xab\x11\x89\x68\x84\x13\x61\x0a\x35\xa1\x28\x86\xcd\xe0\xb6\x6c\x72"
|
const Hash = "\x1b\xf5\x75\xab\x11\x89\x68\x84\x13\x61\x0a\x35\xa1\x28\x86\xcd\xe0\xb6\x6c\x72"
|
||||||
|
|
||||||
// NamedCurve represents a named elliptic curve.
|
// NamedCurveHash represents a pair of named elliptic curve and hash function.
|
||||||
type NamedCurve byte
|
type NamedCurveHash byte
|
||||||
|
|
||||||
// Various named elliptic curves.
|
// Various pairs of named elliptic curves and hash functions.
|
||||||
const (
|
const (
|
||||||
Secp256k1 NamedCurve = 22
|
Secp256k1Sha256 NamedCurveHash = 22
|
||||||
Secp256r1 NamedCurve = 23
|
Secp256r1Sha256 NamedCurveHash = 23
|
||||||
|
Secp256k1Keccak256 NamedCurveHash = 24
|
||||||
|
Secp256r1Keccak256 NamedCurveHash = 25
|
||||||
)
|
)
|
||||||
|
|
||||||
// Sha256 calls `sha256` method of native CryptoLib contract and computes SHA256 hash of b.
|
// Sha256 calls `sha256` method of native CryptoLib contract and computes SHA256 hash of b.
|
||||||
|
@ -40,8 +42,8 @@ func Murmur32(b []byte, seed int) []byte {
|
||||||
|
|
||||||
// VerifyWithECDsa calls `verifyWithECDsa` method of native CryptoLib contract and checks that sig is
|
// VerifyWithECDsa calls `verifyWithECDsa` method of native CryptoLib contract and checks that sig is
|
||||||
// a correct msg's signature for the given pub (serialized public key on the given curve).
|
// a correct msg's signature for the given pub (serialized public key on the given curve).
|
||||||
func VerifyWithECDsa(msg []byte, pub interop.PublicKey, sig interop.Signature, curve NamedCurve) bool {
|
func VerifyWithECDsa(msg []byte, pub interop.PublicKey, sig interop.Signature, curveHash NamedCurveHash) bool {
|
||||||
return neogointernal.CallWithToken(Hash, "verifyWithECDsa", int(contract.NoneFlag), msg, pub, sig, curve).(bool)
|
return neogointernal.CallWithToken(Hash, "verifyWithECDsa", int(contract.NoneFlag), msg, pub, sig, curveHash).(bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bls12381Point represents BLS12-381 curve point (G1 or G2 in the Affine or
|
// Bls12381Point represents BLS12-381 curve point (G1 or G2 in the Affine or
|
||||||
|
|
|
@ -89,7 +89,7 @@ const (
|
||||||
faultedTxHashLE = "82279bfe9bada282ca0f8cb8e0bb124b921af36f00c69a518320322c6f4fef60"
|
faultedTxHashLE = "82279bfe9bada282ca0f8cb8e0bb124b921af36f00c69a518320322c6f4fef60"
|
||||||
faultedTxBlock uint32 = 23
|
faultedTxBlock uint32 = 23
|
||||||
invokescriptContractAVM = "VwIADBQBDAMOBQYMDQIODw0DDgcJAAAAAErZMCQE2zBwaEH4J+yMqiYEEUAMFA0PAwIJAAIBAwcDBAUCAQAOBgwJStkwJATbMHFpQfgn7IyqJgQSQBNA"
|
invokescriptContractAVM = "VwIADBQBDAMOBQYMDQIODw0DDgcJAAAAAErZMCQE2zBwaEH4J+yMqiYEEUAMFA0PAwIJAAIBAwcDBAUCAQAOBgwJStkwJATbMHFpQfgn7IyqJgQSQBNA"
|
||||||
block20StateRootLE = "637aac452ef781dee7ac5e898a1edf4d3c5b6420288ea5232dad620f39d2152a"
|
block20StateRootLE = "c187c5a3272054dadbf8a1c896435462bb8c79c8a09595d5ebd96dbc7fd7129d"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
Loading…
Reference in a new issue