From c6f8f0aefc110c10f2fcee12a7687c69a03b662e Mon Sep 17 00:00:00 2001 From: Marko Date: Thu, 15 Oct 2020 10:10:06 +0200 Subject: [PATCH] crypto: add in secp256k1 support (#5500) Secp256k1 was removed in the protobuf migration, this pr adds it back in order to provide this functionality for users (band) Closes: #5495 --- .markdownlintignore | 1 + CHANGELOG.md | 1 - UPGRADING.md | 5 +- abci/example/kvstore/persistent_kvstore.go | 2 +- crypto/ed25519/ed25519.go | 6 +- crypto/encoding/codec.go | 16 ++ crypto/secp256k1/secp256k1.go | 173 ++++++++++++++++++++ crypto/secp256k1/secp256k1_internal_test.go | 74 +++++++++ crypto/secp256k1/secp256k1_nocgo.go | 75 +++++++++ crypto/secp256k1/secp256k1_test.go | 116 +++++++++++++ go.mod | 3 + go.sum | 26 +++ proto/tendermint/crypto/keys.pb.go | 153 +++++++++++++++-- proto/tendermint/crypto/keys.proto | 3 +- types/params_test.go | 7 +- types/protobuf.go | 7 +- 16 files changed, 643 insertions(+), 25 deletions(-) create mode 100644 crypto/secp256k1/secp256k1.go create mode 100644 crypto/secp256k1/secp256k1_internal_test.go create mode 100644 crypto/secp256k1/secp256k1_nocgo.go create mode 100644 crypto/secp256k1/secp256k1_test.go diff --git a/.markdownlintignore b/.markdownlintignore index c4f0964fc..12b20d6bb 100644 --- a/.markdownlintignore +++ b/.markdownlintignore @@ -1,5 +1,6 @@ docs/node_modules CHANGELOG.md docs/architecture/* +crypto/secp256k1/** scripts/* .github diff --git a/CHANGELOG.md b/CHANGELOG.md index f8ab6a841..5dffcffba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,7 +58,6 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi - [evidence] [\#5319](https://github.com/tendermint/tendermint/issues/5319) Remove Amnesia & potentialAmnesia evidence types and removed POLC. (@marbar3778) - [evidence] [\#5361](https://github.com/tendermint/tendermint/pull/5361) Add LightClientAttackEvidence and change evidence interface (@cmwaters) - [params] [\#5319](https://github.com/tendermint/tendermint/issues/5319) Remove `ProofofTrialPeriod` from evidence params (@marbar3778) - - [crypto/secp256k1] [\#5280](https://github.com/tendermint/tendermint/issues/5280) `secp256k1` has been removed from the Tendermint repo. (@marbar3778) - [light] [\#5347](https://github.com/tendermint/tendermint/issues/5347) `NewClient`, `NewHTTPClient`, `VerifyHeader` and `VerifyLightBlockAtHeight` now accept `context.Context` as 1st param (@melekes) - [state] [\#5348](https://github.com/tendermint/tendermint/issues/5348) Define an Interface for the state store. (@marbar3778) diff --git a/UPGRADING.md b/UPGRADING.md index 79b0e00b7..7152a9400 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -38,7 +38,7 @@ the encoding format (see "Protocol Buffers," below) and the block header (see "B * The field `Proof`, on the ABCI type `ResponseQuery`, is now named `ProofOps`. For more, see "Crypto," below. -* The method `SetOption` has been removed from the ABCI.Client interface. This feature was used in the early ABCI implementation's. +* The method `SetOption` has been removed from the ABCI.Client interface. This feature was used in the early ABCI implementation's. ### P2P Protocol @@ -119,9 +119,6 @@ Tendermint 0.34 includes new and updated consensus parameters. * The multisig functionality that was previously in Tendermint now has a new home within the Cosmos SDK: [`cosmos/cosmos-sdk/types/multisig`](https://github.com/cosmos/cosmos-sdk/blob/master/crypto/types/multisig/multisignature.go). -* Similarly, secp256k1 has been removed from the Tendermint repo. - There is still [a secp256k1 implementation in the Cosmos SDK](https://github.com/cosmos/cosmos-sdk/tree/443e0c1f89bd3730a731aea30453bd732f7efa35/crypto/keys/secp256k1), - and we recommend you use that package for all your secp256k1 needs. #### `merkle` Package diff --git a/abci/example/kvstore/persistent_kvstore.go b/abci/example/kvstore/persistent_kvstore.go index 188fe43bb..b584f497d 100644 --- a/abci/example/kvstore/persistent_kvstore.go +++ b/abci/example/kvstore/persistent_kvstore.go @@ -239,11 +239,11 @@ func (app *PersistentKVStoreApplication) execValidatorTx(tx []byte) types.Respon // add, update, or remove a validator func (app *PersistentKVStoreApplication) updateValidator(v types.ValidatorUpdate) types.ResponseDeliverTx { - key := []byte("val:" + string(v.PubKey.GetEd25519())) pubkey, err := cryptoenc.PubKeyFromProto(v.PubKey) if err != nil { panic(fmt.Errorf("can't decode public key: %w", err)) } + key := []byte("val:" + string(pubkey.Bytes())) if v.Power == 0 { // remove validator diff --git a/crypto/ed25519/ed25519.go b/crypto/ed25519/ed25519.go index b7318043a..36095eece 100644 --- a/crypto/ed25519/ed25519.go +++ b/crypto/ed25519/ed25519.go @@ -31,7 +31,7 @@ const ( // private key representations used by RFC 8032. SeedSize = 32 - keyType = "ed25519" + KeyType = "ed25519" ) func init() { @@ -93,7 +93,7 @@ func (privKey PrivKey) Equals(other crypto.PrivKey) bool { } func (privKey PrivKey) Type() string { - return keyType + return KeyType } // GenPrivKey generates a new ed25519 private key. @@ -159,7 +159,7 @@ func (pubKey PubKey) String() string { } func (pubKey PubKey) Type() string { - return keyType + return KeyType } func (pubKey PubKey) Equals(other crypto.PubKey) bool { diff --git a/crypto/encoding/codec.go b/crypto/encoding/codec.go index 7438cb5fb..f9c721131 100644 --- a/crypto/encoding/codec.go +++ b/crypto/encoding/codec.go @@ -5,6 +5,7 @@ import ( "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" + "github.com/tendermint/tendermint/crypto/secp256k1" "github.com/tendermint/tendermint/libs/json" pc "github.com/tendermint/tendermint/proto/tendermint/crypto" ) @@ -12,6 +13,7 @@ import ( func init() { json.RegisterType((*pc.PublicKey)(nil), "tendermint.crypto.PublicKey") json.RegisterType((*pc.PublicKey_Ed25519)(nil), "tendermint.crypto.PublicKey_Ed25519") + json.RegisterType((*pc.PublicKey_Secp256K1)(nil), "tendermint.crypto.PublicKey_Secp256K1") } // PubKeyToProto takes crypto.PubKey and transforms it to a protobuf Pubkey @@ -24,6 +26,12 @@ func PubKeyToProto(k crypto.PubKey) (pc.PublicKey, error) { Ed25519: k, }, } + case secp256k1.PubKey: + kp = pc.PublicKey{ + Sum: &pc.PublicKey_Secp256K1{ + Secp256K1: k, + }, + } default: return kp, fmt.Errorf("toproto: key type %v is not supported", k) } @@ -41,6 +49,14 @@ func PubKeyFromProto(k pc.PublicKey) (crypto.PubKey, error) { pk := make(ed25519.PubKey, ed25519.PubKeySize) copy(pk, k.Ed25519) return pk, nil + case *pc.PublicKey_Secp256K1: + if len(k.Secp256K1) != secp256k1.PubKeySize { + return nil, fmt.Errorf("invalid size for PubKeyEd25519. Got %d, expected %d", + len(k.Secp256K1), secp256k1.PubKeySize) + } + pk := make(secp256k1.PubKey, secp256k1.PubKeySize) + copy(pk, k.Secp256K1) + return pk, nil default: return nil, fmt.Errorf("fromproto: key type %v is not supported", k) } diff --git a/crypto/secp256k1/secp256k1.go b/crypto/secp256k1/secp256k1.go new file mode 100644 index 000000000..fe5296900 --- /dev/null +++ b/crypto/secp256k1/secp256k1.go @@ -0,0 +1,173 @@ +package secp256k1 + +import ( + "bytes" + "crypto/sha256" + "crypto/subtle" + "fmt" + "io" + "math/big" + + secp256k1 "github.com/btcsuite/btcd/btcec" + "golang.org/x/crypto/ripemd160" // nolint: staticcheck // necessary for Bitcoin address format + + "github.com/tendermint/tendermint/crypto" + tmjson "github.com/tendermint/tendermint/libs/json" +) + +//------------------------------------- +const ( + PrivKeyName = "tendermint/PrivKeySecp256k1" + PubKeyName = "tendermint/PubKeySecp256k1" + + KeyType = "secp256k1" + PrivKeySize = 32 +) + +func init() { + tmjson.RegisterType(PubKey{}, PubKeyName) + tmjson.RegisterType(PrivKey{}, PrivKeyName) +} + +var _ crypto.PrivKey = PrivKey{} + +// PrivKey implements PrivKey. +type PrivKey []byte + +// Bytes marshalls the private key using amino encoding. +func (privKey PrivKey) Bytes() []byte { + return []byte(privKey) +} + +// PubKey performs the point-scalar multiplication from the privKey on the +// generator point to get the pubkey. +func (privKey PrivKey) PubKey() crypto.PubKey { + _, pubkeyObject := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey) + + pk := pubkeyObject.SerializeCompressed() + + return PubKey(pk) +} + +// Equals - you probably don't need to use this. +// Runs in constant time based on length of the keys. +func (privKey PrivKey) Equals(other crypto.PrivKey) bool { + if otherSecp, ok := other.(PrivKey); ok { + return subtle.ConstantTimeCompare(privKey[:], otherSecp[:]) == 1 + } + return false +} + +func (privKey PrivKey) Type() string { + return KeyType +} + +// GenPrivKey generates a new ECDSA private key on curve secp256k1 private key. +// It uses OS randomness to generate the private key. +func GenPrivKey() PrivKey { + return genPrivKey(crypto.CReader()) +} + +// genPrivKey generates a new secp256k1 private key using the provided reader. +func genPrivKey(rand io.Reader) PrivKey { + var privKeyBytes [PrivKeySize]byte + d := new(big.Int) + + for { + privKeyBytes = [PrivKeySize]byte{} + _, err := io.ReadFull(rand, privKeyBytes[:]) + if err != nil { + panic(err) + } + + d.SetBytes(privKeyBytes[:]) + // break if we found a valid point (i.e. > 0 and < N == curverOrder) + isValidFieldElement := 0 < d.Sign() && d.Cmp(secp256k1.S256().N) < 0 + if isValidFieldElement { + break + } + } + + return PrivKey(privKeyBytes[:]) +} + +var one = new(big.Int).SetInt64(1) + +// GenPrivKeySecp256k1 hashes the secret with SHA2, and uses +// that 32 byte output to create the private key. +// +// It makes sure the private key is a valid field element by setting: +// +// c = sha256(secret) +// k = (c mod (n − 1)) + 1, where n = curve order. +// +// NOTE: secret should be the output of a KDF like bcrypt, +// if it's derived from user input. +func GenPrivKeySecp256k1(secret []byte) PrivKey { + secHash := sha256.Sum256(secret) + // to guarantee that we have a valid field element, we use the approach of: + // "Suite B Implementer’s Guide to FIPS 186-3", A.2.1 + // https://apps.nsa.gov/iaarchive/library/ia-guidance/ia-solutions-for-classified/algorithm-guidance/suite-b-implementers-guide-to-fips-186-3-ecdsa.cfm + // see also https://github.com/golang/go/blob/0380c9ad38843d523d9c9804fe300cb7edd7cd3c/src/crypto/ecdsa/ecdsa.go#L89-L101 + fe := new(big.Int).SetBytes(secHash[:]) + n := new(big.Int).Sub(secp256k1.S256().N, one) + fe.Mod(fe, n) + fe.Add(fe, one) + + feB := fe.Bytes() + privKey32 := make([]byte, PrivKeySize) + // copy feB over to fixed 32 byte privKey32 and pad (if necessary) + copy(privKey32[32-len(feB):32], feB) + + return PrivKey(privKey32) +} + +//------------------------------------- + +var _ crypto.PubKey = PubKey{} + +// PubKeySize is comprised of 32 bytes for one field element +// (the x-coordinate), plus one byte for the parity of the y-coordinate. +const PubKeySize = 33 + +// PubKey implements crypto.PubKey. +// It is the compressed form of the pubkey. The first byte depends is a 0x02 byte +// if the y-coordinate is the lexicographically largest of the two associated with +// the x-coordinate. Otherwise the first byte is a 0x03. +// This prefix is followed with the x-coordinate. +type PubKey []byte + +// Address returns a Bitcoin style addresses: RIPEMD160(SHA256(pubkey)) +func (pubKey PubKey) Address() crypto.Address { + if len(pubKey) != PubKeySize { + panic("length of pubkey is incorrect") + } + hasherSHA256 := sha256.New() + _, _ = hasherSHA256.Write(pubKey) // does not error + sha := hasherSHA256.Sum(nil) + + hasherRIPEMD160 := ripemd160.New() + _, _ = hasherRIPEMD160.Write(sha) // does not error + + return crypto.Address(hasherRIPEMD160.Sum(nil)) +} + +// Bytes returns the pubkey marshalled with amino encoding. +func (pubKey PubKey) Bytes() []byte { + return []byte(pubKey) +} + +func (pubKey PubKey) String() string { + return fmt.Sprintf("PubKeySecp256k1{%X}", pubKey[:]) +} + +func (pubKey PubKey) Equals(other crypto.PubKey) bool { + if otherSecp, ok := other.(PubKey); ok { + return bytes.Equal(pubKey[:], otherSecp[:]) + } + return false +} + +func (pubKey PubKey) Type() string { + return KeyType +} diff --git a/crypto/secp256k1/secp256k1_internal_test.go b/crypto/secp256k1/secp256k1_internal_test.go new file mode 100644 index 000000000..bceddc24f --- /dev/null +++ b/crypto/secp256k1/secp256k1_internal_test.go @@ -0,0 +1,74 @@ +package secp256k1 + +import ( + "bytes" + "math/big" + "testing" + + "github.com/stretchr/testify/require" + + secp256k1 "github.com/btcsuite/btcd/btcec" +) + +func Test_genPrivKey(t *testing.T) { + + empty := make([]byte, 32) + oneB := big.NewInt(1).Bytes() + onePadded := make([]byte, 32) + copy(onePadded[32-len(oneB):32], oneB) + t.Logf("one padded: %v, len=%v", onePadded, len(onePadded)) + + validOne := append(empty, onePadded...) + tests := []struct { + name string + notSoRand []byte + shouldPanic bool + }{ + {"empty bytes (panics because 1st 32 bytes are zero and 0 is not a valid field element)", empty, true}, + {"curve order: N", secp256k1.S256().N.Bytes(), true}, + {"valid because 0 < 1 < N", validOne, false}, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + if tt.shouldPanic { + require.Panics(t, func() { + genPrivKey(bytes.NewReader(tt.notSoRand)) + }) + return + } + got := genPrivKey(bytes.NewReader(tt.notSoRand)) + fe := new(big.Int).SetBytes(got[:]) + require.True(t, fe.Cmp(secp256k1.S256().N) < 0) + require.True(t, fe.Sign() > 0) + }) + } +} + +// Ensure that signature verification works, and that +// non-canonical signatures fail. +// Note: run with CGO_ENABLED=0 or go test -tags !cgo. +func TestSignatureVerificationAndRejectUpperS(t *testing.T) { + msg := []byte("We have lingered long enough on the shores of the cosmic ocean.") + for i := 0; i < 500; i++ { + priv := GenPrivKey() + sigStr, err := priv.Sign(msg) + require.NoError(t, err) + sig := signatureFromBytes(sigStr) + require.False(t, sig.S.Cmp(secp256k1halfN) > 0) + + pub := priv.PubKey() + require.True(t, pub.VerifySignature(msg, sigStr)) + + // malleate: + sig.S.Sub(secp256k1.S256().CurveParams.N, sig.S) + require.True(t, sig.S.Cmp(secp256k1halfN) > 0) + malSigStr := serializeSig(sig) + + require.False(t, pub.VerifySignature(msg, malSigStr), + "VerifyBytes incorrect with malleated & invalid S. sig=%v, key=%v", + sig, + priv, + ) + } +} diff --git a/crypto/secp256k1/secp256k1_nocgo.go b/crypto/secp256k1/secp256k1_nocgo.go new file mode 100644 index 000000000..cba9bbe4c --- /dev/null +++ b/crypto/secp256k1/secp256k1_nocgo.go @@ -0,0 +1,75 @@ +// +build !libsecp256k1 + +package secp256k1 + +import ( + "math/big" + + secp256k1 "github.com/btcsuite/btcd/btcec" + + "github.com/tendermint/tendermint/crypto" +) + +// used to reject malleable signatures +// see: +// - https://github.com/ethereum/go-ethereum/blob/f9401ae011ddf7f8d2d95020b7446c17f8d98dc1/crypto/signature_nocgo.go#L90-L93 +// - https://github.com/ethereum/go-ethereum/blob/f9401ae011ddf7f8d2d95020b7446c17f8d98dc1/crypto/crypto.go#L39 +var secp256k1halfN = new(big.Int).Rsh(secp256k1.S256().N, 1) + +// Sign creates an ECDSA signature on curve Secp256k1, using SHA256 on the msg. +// The returned signature will be of the form R || S (in lower-S form). +func (privKey PrivKey) Sign(msg []byte) ([]byte, error) { + priv, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey) + + sig, err := priv.Sign(crypto.Sha256(msg)) + if err != nil { + return nil, err + } + + sigBytes := serializeSig(sig) + return sigBytes, nil +} + +// VerifySignature verifies a signature of the form R || S. +// It rejects signatures which are not in lower-S form. +func (pubKey PubKey) VerifySignature(msg []byte, sigStr []byte) bool { + if len(sigStr) != 64 { + return false + } + + pub, err := secp256k1.ParsePubKey(pubKey, secp256k1.S256()) + if err != nil { + return false + } + + // parse the signature: + signature := signatureFromBytes(sigStr) + // Reject malleable signatures. libsecp256k1 does this check but btcec doesn't. + // see: https://github.com/ethereum/go-ethereum/blob/f9401ae011ddf7f8d2d95020b7446c17f8d98dc1/crypto/signature_nocgo.go#L90-L93 + if signature.S.Cmp(secp256k1halfN) > 0 { + return false + } + + return signature.Verify(crypto.Sha256(msg), pub) +} + +// Read Signature struct from R || S. Caller needs to ensure +// that len(sigStr) == 64. +func signatureFromBytes(sigStr []byte) *secp256k1.Signature { + return &secp256k1.Signature{ + R: new(big.Int).SetBytes(sigStr[:32]), + S: new(big.Int).SetBytes(sigStr[32:64]), + } +} + +// Serialize signature to R || S. +// R, S are padded to 32 bytes respectively. +func serializeSig(sig *secp256k1.Signature) []byte { + rBytes := sig.R.Bytes() + sBytes := sig.S.Bytes() + sigBytes := make([]byte, 64) + // 0 pad the byte arrays from the left if they aren't big enough. + copy(sigBytes[32-len(rBytes):32], rBytes) + copy(sigBytes[64-len(sBytes):64], sBytes) + return sigBytes +} diff --git a/crypto/secp256k1/secp256k1_test.go b/crypto/secp256k1/secp256k1_test.go new file mode 100644 index 000000000..83249ef6a --- /dev/null +++ b/crypto/secp256k1/secp256k1_test.go @@ -0,0 +1,116 @@ +package secp256k1_test + +import ( + "encoding/hex" + "math/big" + "testing" + + "github.com/btcsuite/btcutil/base58" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/secp256k1" + + underlyingSecp256k1 "github.com/btcsuite/btcd/btcec" +) + +type keyData struct { + priv string + pub string + addr string +} + +var secpDataTable = []keyData{ + { + priv: "a96e62ed3955e65be32703f12d87b6b5cf26039ecfa948dc5107a495418e5330", + pub: "02950e1cdfcb133d6024109fd489f734eeb4502418e538c28481f22bce276f248c", + addr: "1CKZ9Nx4zgds8tU7nJHotKSDr4a9bYJCa3", + }, +} + +func TestPubKeySecp256k1Address(t *testing.T) { + for _, d := range secpDataTable { + privB, _ := hex.DecodeString(d.priv) + pubB, _ := hex.DecodeString(d.pub) + addrBbz, _, _ := base58.CheckDecode(d.addr) + addrB := crypto.Address(addrBbz) + + var priv secp256k1.PrivKey = secp256k1.PrivKey(privB) + + pubKey := priv.PubKey() + pubT, _ := pubKey.(secp256k1.PubKey) + pub := pubT + addr := pubKey.Address() + + assert.Equal(t, pub, secp256k1.PubKey(pubB), "Expected pub keys to match") + assert.Equal(t, addr, addrB, "Expected addresses to match") + } +} + +func TestSignAndValidateSecp256k1(t *testing.T) { + privKey := secp256k1.GenPrivKey() + pubKey := privKey.PubKey() + + msg := crypto.CRandBytes(128) + sig, err := privKey.Sign(msg) + require.Nil(t, err) + + assert.True(t, pubKey.VerifySignature(msg, sig)) + + // Mutate the signature, just one bit. + sig[3] ^= byte(0x01) + + assert.False(t, pubKey.VerifySignature(msg, sig)) +} + +// This test is intended to justify the removal of calls to the underlying library +// in creating the privkey. +func TestSecp256k1LoadPrivkeyAndSerializeIsIdentity(t *testing.T) { + numberOfTests := 256 + for i := 0; i < numberOfTests; i++ { + // Seed the test case with some random bytes + privKeyBytes := [32]byte{} + copy(privKeyBytes[:], crypto.CRandBytes(32)) + + // This function creates a private and public key in the underlying libraries format. + // The private key is basically calling new(big.Int).SetBytes(pk), which removes leading zero bytes + priv, _ := underlyingSecp256k1.PrivKeyFromBytes(underlyingSecp256k1.S256(), privKeyBytes[:]) + // this takes the bytes returned by `(big int).Bytes()`, and if the length is less than 32 bytes, + // pads the bytes from the left with zero bytes. Therefore these two functions composed + // result in the identity function on privKeyBytes, hence the following equality check + // always returning true. + serializedBytes := priv.Serialize() + require.Equal(t, privKeyBytes[:], serializedBytes) + } +} + +func TestGenPrivKeySecp256k1(t *testing.T) { + // curve oder N + N := underlyingSecp256k1.S256().N + tests := []struct { + name string + secret []byte + }{ + {"empty secret", []byte{}}, + { + "some long secret", + []byte("We live in a society exquisitely dependent on science and technology, " + + "in which hardly anyone knows anything about science and technology."), + }, + {"another seed used in cosmos tests #1", []byte{0}}, + {"another seed used in cosmos tests #2", []byte("mySecret")}, + {"another seed used in cosmos tests #3", []byte("")}, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + gotPrivKey := secp256k1.GenPrivKeySecp256k1(tt.secret) + require.NotNil(t, gotPrivKey) + // interpret as a big.Int and make sure it is a valid field element: + fe := new(big.Int).SetBytes(gotPrivKey[:]) + require.True(t, fe.Cmp(N) < 0) + require.True(t, fe.Sign() > 0) + }) + } +} diff --git a/go.mod b/go.mod index ef7b2bb27..6dffe4b16 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,8 @@ require ( github.com/BurntSushi/toml v0.3.1 github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d github.com/Workiva/go-datastructures v1.0.52 + github.com/btcsuite/btcd v0.21.0-beta + github.com/btcsuite/btcutil v1.0.2 github.com/confio/ics23/go v0.0.0-20200817220745-f173e6211efb github.com/cosmos/iavl v0.15.0-rc3.0.20201009144442-230e9bdf52cd github.com/fortytw2/leaktest v1.3.0 @@ -16,6 +18,7 @@ require ( github.com/gorilla/websocket v1.4.2 github.com/gtank/merlin v0.1.1 github.com/libp2p/go-buffer-pool v0.0.2 + github.com/magiconair/properties v1.8.1 github.com/minio/highwayhash v1.0.1 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.7.1 diff --git a/go.sum b/go.sum index fadf9a45f..b4ee70be9 100644 --- a/go.sum +++ b/go.sum @@ -27,6 +27,7 @@ github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrd github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/Workiva/go-datastructures v1.0.52 h1:PLSK6pwn8mYdaoaCZEMsXBpBotr4HHn9abU0yMQt0NI= github.com/Workiva/go-datastructures v1.0.52/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -52,6 +53,20 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.21.0-beta h1:At9hIZdJW0s9E/fAz28nrz6AmcNlSVucCH796ZteX1M= +github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v1.0.2 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2uts= +github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -85,9 +100,11 @@ github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwc github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/dgraph-io/badger/v2 v2.2007.1 h1:t36VcBCpo4SsmAD5M8wVv1ieVzcALyGfaJ92z4ccULM= github.com/dgraph-io/badger/v2 v2.2007.1/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE= github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de h1:t0UHb5vdojIDUqktM6+xJAfScFBsVpXZmqC9dsgJmeA= @@ -248,11 +265,14 @@ github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmK github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -264,6 +284,7 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -327,6 +348,7 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= @@ -499,6 +521,7 @@ go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+ go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -510,6 +533,8 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413 h1:ULYEB3JvPRE/IfO+9uO7vKV/xzVTO7XPAwm8xbf4w2g= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM= @@ -535,6 +560,7 @@ golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKG golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA= diff --git a/proto/tendermint/crypto/keys.pb.go b/proto/tendermint/crypto/keys.pb.go index cb54ce0f1..2e7282b0a 100644 --- a/proto/tendermint/crypto/keys.pb.go +++ b/proto/tendermint/crypto/keys.pb.go @@ -28,6 +28,7 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type PublicKey struct { // Types that are valid to be assigned to Sum: // *PublicKey_Ed25519 + // *PublicKey_Secp256K1 Sum isPublicKey_Sum `protobuf_oneof:"sum"` } @@ -75,8 +76,12 @@ type isPublicKey_Sum interface { type PublicKey_Ed25519 struct { Ed25519 []byte `protobuf:"bytes,1,opt,name=ed25519,proto3,oneof" json:"ed25519,omitempty"` } +type PublicKey_Secp256K1 struct { + Secp256K1 []byte `protobuf:"bytes,2,opt,name=secp256k1,proto3,oneof" json:"secp256k1,omitempty"` +} -func (*PublicKey_Ed25519) isPublicKey_Sum() {} +func (*PublicKey_Ed25519) isPublicKey_Sum() {} +func (*PublicKey_Secp256K1) isPublicKey_Sum() {} func (m *PublicKey) GetSum() isPublicKey_Sum { if m != nil { @@ -92,10 +97,18 @@ func (m *PublicKey) GetEd25519() []byte { return nil } +func (m *PublicKey) GetSecp256K1() []byte { + if x, ok := m.GetSum().(*PublicKey_Secp256K1); ok { + return x.Secp256K1 + } + return nil +} + // XXX_OneofWrappers is for the internal use of the proto package. func (*PublicKey) XXX_OneofWrappers() []interface{} { return []interface{}{ (*PublicKey_Ed25519)(nil), + (*PublicKey_Secp256K1)(nil), } } @@ -106,19 +119,20 @@ func init() { func init() { proto.RegisterFile("tendermint/crypto/keys.proto", fileDescriptor_cb048658b234868c) } var fileDescriptor_cb048658b234868c = []byte{ - // 180 bytes of a gzipped FileDescriptorProto + // 199 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x29, 0x49, 0xcd, 0x4b, 0x49, 0x2d, 0xca, 0xcd, 0xcc, 0x2b, 0xd1, 0x4f, 0x2e, 0xaa, 0x2c, 0x28, 0xc9, 0xd7, 0xcf, 0x4e, 0xad, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x44, 0xc8, 0xea, 0x41, 0x64, 0xa5, - 0x44, 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0xb2, 0xfa, 0x20, 0x16, 0x44, 0xa1, 0x92, 0x05, 0x17, 0x67, + 0x44, 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0xb2, 0xfa, 0x20, 0x16, 0x44, 0xa1, 0x52, 0x04, 0x17, 0x67, 0x40, 0x69, 0x52, 0x4e, 0x66, 0xb2, 0x77, 0x6a, 0xa5, 0x90, 0x14, 0x17, 0x7b, 0x6a, 0x8a, 0x91, - 0xa9, 0xa9, 0xa1, 0xa5, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x8f, 0x07, 0x43, 0x10, 0x4c, 0xc0, 0x8a, - 0xe3, 0xc5, 0x02, 0x79, 0xc6, 0x17, 0x0b, 0xe5, 0x19, 0x9d, 0x58, 0xb9, 0x98, 0x8b, 0x4b, 0x73, - 0x9d, 0x82, 0x4e, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x09, - 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, 0xf1, 0x58, 0x8e, 0x21, 0xca, 0x22, 0x3d, 0xb3, - 0x24, 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f, 0x57, 0x1f, 0xc9, 0x95, 0x48, 0x4c, 0x88, 0x33, 0x30, - 0x7c, 0x90, 0xc4, 0x06, 0x96, 0x30, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x51, 0x7d, 0xc1, 0x7b, - 0xdd, 0x00, 0x00, 0x00, + 0xa9, 0xa9, 0xa1, 0xa5, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x8f, 0x07, 0x43, 0x10, 0x4c, 0x40, 0x48, + 0x8e, 0x8b, 0xb3, 0x38, 0x35, 0xb9, 0xc0, 0xc8, 0xd4, 0x2c, 0xdb, 0x50, 0x82, 0x09, 0x2a, 0x8b, + 0x10, 0xb2, 0xe2, 0x78, 0xb1, 0x40, 0x9e, 0xf1, 0xc5, 0x42, 0x79, 0x46, 0x27, 0x56, 0x2e, 0xe6, + 0xe2, 0xd2, 0x5c, 0xa7, 0xa0, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, + 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x0b, 0x8f, 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, 0xb2, + 0x48, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x47, 0xf2, 0x05, 0x12, 0x13, + 0xe2, 0x4c, 0x0c, 0x1f, 0x26, 0xb1, 0x81, 0x25, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xe8, + 0x1d, 0x1e, 0xe2, 0xfd, 0x00, 0x00, 0x00, } func (this *PublicKey) Compare(that interface{}) int { @@ -157,6 +171,8 @@ func (this *PublicKey) Compare(that interface{}) int { switch this.Sum.(type) { case *PublicKey_Ed25519: thisType = 0 + case *PublicKey_Secp256K1: + thisType = 1 default: panic(fmt.Sprintf("compare: unexpected type %T in oneof", this.Sum)) } @@ -164,6 +180,8 @@ func (this *PublicKey) Compare(that interface{}) int { switch that1.Sum.(type) { case *PublicKey_Ed25519: that1Type = 0 + case *PublicKey_Secp256K1: + that1Type = 1 default: panic(fmt.Sprintf("compare: unexpected type %T in oneof", that1.Sum)) } @@ -209,6 +227,36 @@ func (this *PublicKey_Ed25519) Compare(that interface{}) int { } return 0 } +func (this *PublicKey_Secp256K1) Compare(that interface{}) int { + if that == nil { + if this == nil { + return 0 + } + return 1 + } + + that1, ok := that.(*PublicKey_Secp256K1) + if !ok { + that2, ok := that.(PublicKey_Secp256K1) + if ok { + that1 = &that2 + } else { + return 1 + } + } + if that1 == nil { + if this == nil { + return 0 + } + return 1 + } else if this == nil { + return -1 + } + if c := bytes.Compare(this.Secp256K1, that1.Secp256K1); c != 0 { + return c + } + return 0 +} func (this *PublicKey) Equal(that interface{}) bool { if that == nil { return this == nil @@ -263,6 +311,30 @@ func (this *PublicKey_Ed25519) Equal(that interface{}) bool { } return true } +func (this *PublicKey_Secp256K1) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PublicKey_Secp256K1) + if !ok { + that2, ok := that.(PublicKey_Secp256K1) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !bytes.Equal(this.Secp256K1, that1.Secp256K1) { + return false + } + return true +} func (m *PublicKey) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -311,6 +383,22 @@ func (m *PublicKey_Ed25519) MarshalToSizedBuffer(dAtA []byte) (int, error) { } return len(dAtA) - i, nil } +func (m *PublicKey_Secp256K1) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PublicKey_Secp256K1) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Secp256K1 != nil { + i -= len(m.Secp256K1) + copy(dAtA[i:], m.Secp256K1) + i = encodeVarintKeys(dAtA, i, uint64(len(m.Secp256K1))) + i-- + dAtA[i] = 0x12 + } + return len(dAtA) - i, nil +} func encodeVarintKeys(dAtA []byte, offset int, v uint64) int { offset -= sovKeys(v) base := offset @@ -346,6 +434,18 @@ func (m *PublicKey_Ed25519) Size() (n int) { } return n } +func (m *PublicKey_Secp256K1) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Secp256K1 != nil { + l = len(m.Secp256K1) + n += 1 + l + sovKeys(uint64(l)) + } + return n +} func sovKeys(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 @@ -415,6 +515,39 @@ func (m *PublicKey) Unmarshal(dAtA []byte) error { copy(v, dAtA[iNdEx:postIndex]) m.Sum = &PublicKey_Ed25519{v} iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Secp256K1", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowKeys + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthKeys + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthKeys + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := make([]byte, postIndex-iNdEx) + copy(v, dAtA[iNdEx:postIndex]) + m.Sum = &PublicKey_Secp256K1{v} + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipKeys(dAtA[iNdEx:]) diff --git a/proto/tendermint/crypto/keys.proto b/proto/tendermint/crypto/keys.proto index af9db49fc..16fd7adf3 100644 --- a/proto/tendermint/crypto/keys.proto +++ b/proto/tendermint/crypto/keys.proto @@ -11,6 +11,7 @@ message PublicKey { option (gogoproto.equal) = true; oneof sum { - bytes ed25519 = 1; + bytes ed25519 = 1; + bytes secp256k1 = 2; } } diff --git a/types/params_test.go b/types/params_test.go index e6fbc4cad..f3a71ca50 100644 --- a/types/params_test.go +++ b/types/params_test.go @@ -13,7 +13,8 @@ import ( ) var ( - valEd25519 = []string{ABCIPubKeyTypeEd25519} + valEd25519 = []string{ABCIPubKeyTypeEd25519} + valSecp256k1 = []string{ABCIPubKeyTypeSecp256k1} ) func TestConsensusParamsValidation(t *testing.T) { @@ -127,10 +128,10 @@ func TestConsensusParamsUpdate(t *testing.T) { MaxBytes: 50, }, Validator: &tmproto.ValidatorParams{ - PubKeyTypes: valEd25519, + PubKeyTypes: valSecp256k1, }, }, - makeParams(100, 200, 10, 300, 50, valEd25519), + makeParams(100, 200, 10, 300, 50, valSecp256k1), }, } for _, tc := range testCases { diff --git a/types/protobuf.go b/types/protobuf.go index 75d7b1ceb..1e633338b 100644 --- a/types/protobuf.go +++ b/types/protobuf.go @@ -8,6 +8,7 @@ import ( "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" cryptoenc "github.com/tendermint/tendermint/crypto/encoding" + "github.com/tendermint/tendermint/crypto/secp256k1" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" ) @@ -15,13 +16,15 @@ import ( // Use strings to distinguish types in ABCI messages const ( - ABCIPubKeyTypeEd25519 = "ed25519" + ABCIPubKeyTypeEd25519 = ed25519.KeyType + ABCIPubKeyTypeSecp256k1 = secp256k1.KeyType ) // TODO: Make non-global by allowing for registration of more pubkey types var ABCIPubKeyTypesToNames = map[string]string{ - ABCIPubKeyTypeEd25519: ed25519.PubKeyName, + ABCIPubKeyTypeEd25519: ed25519.PubKeyName, + ABCIPubKeyTypeSecp256k1: secp256k1.PubKeyName, } //-------------------------------------------------------