Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PublicKeyCodec #6372

Merged
merged 12 commits into from
Jun 9, 2020
15 changes: 15 additions & 0 deletions crypto/types/codec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package types

import (
"github.com/tendermint/tendermint/crypto"
)

// PublicKeyCodec defines a type which can encode and decode crypto.PubKey's
// to and from protobuf PublicKey's
type PublicKeyCodec interface {
// Encode encodes the crypto.PubKey as a protobuf PublicKey or returns an error
Encode(key crypto.PubKey) (*PublicKey, error)

// Decode decodes a crypto.PubKey from a protobuf PublicKey or returns an error
Decode(key *PublicKey) (crypto.PubKey, error)
}
3 changes: 0 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
github.com/confio/ics23 v0.6.0 h1:bQsi55t2+xjW6EWDl83IBF1VWurplbUu+OT6pukeiEo=
github.com/confio/ics23-iavl v0.6.0 h1:vVRCuVaP38FCw1kTeEdFuGuiY+2vAGTBQoH7Zxkq/ws=
github.com/confio/ics23-iavl v0.6.0/go.mod h1:mmXAxD1vWoO0VP8YHu6mM1QHGv71NQqa1iSVm4HeKcY=
github.com/confio/ics23/go v0.0.0-20200323120010-7d9a00f0a2fa/go.mod h1:W1I3XC8d9N8OTu/ct5VJ84ylcOunZwMXsWkd27nvVts=
Expand Down Expand Up @@ -467,8 +466,6 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.0 h1:jlIyCplCJFULU/01vCkhKuTyc3OorI3bJFuw6obfgho=
github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
Expand Down
90 changes: 90 additions & 0 deletions std/pubkey.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package std

import (
"fmt"

"github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"

"github.com/tendermint/tendermint/crypto"
ed255192 "github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/crypto/secp256k1"
"github.com/tendermint/tendermint/crypto/sr25519"
)

// DefaultPublicKeyCodec implements the standard PublicKeyCodec for the SDK which
// supports a standard set of public key types
type DefaultPublicKeyCodec struct{}

var _ types.PublicKeyCodec = DefaultPublicKeyCodec{}

// Decode implements the PublicKeyCodec.Decode method
func (cdc DefaultPublicKeyCodec) Decode(key *types.PublicKey) (crypto.PubKey, error) {
switch key := key.Sum.(type) {
case *types.PublicKey_Secp256K1:
n := len(key.Secp256K1)
if n != secp256k1.PubKeySecp256k1Size {
return nil, fmt.Errorf("wrong length %d for secp256k1 public key", n)
}
var res secp256k1.PubKeySecp256k1
copy(res[:], key.Secp256K1)
return res, nil
case *types.PublicKey_Ed25519:
n := len(key.Ed25519)
if n != ed255192.PubKeyEd25519Size {
return nil, fmt.Errorf("wrong length %d for ed25519 public key", n)
}
var res ed255192.PubKeyEd25519
copy(res[:], key.Ed25519)
return res, nil
case *types.PublicKey_Sr25519:
n := len(key.Sr25519)
if n != sr25519.PubKeySr25519Size {
return nil, fmt.Errorf("wrong length %d for sr25519 public key", n)
}
var res sr25519.PubKeySr25519
copy(res[:], key.Sr25519)
return res, nil
case *types.PublicKey_Multisig:
pubKeys := key.Multisig.PubKeys
resKeys := make([]crypto.PubKey, len(pubKeys))
for i, k := range pubKeys {
dk, err := cdc.Decode(k)
if err != nil {
return nil, err
}
resKeys[i] = dk
}
return multisig.NewPubKeyMultisigThreshold(int(key.Multisig.K), resKeys), nil
default:
return nil, fmt.Errorf("can't encode PubKey of type %T", key)
aaronc marked this conversation as resolved.
Show resolved Hide resolved
}
}

// Encode implements the PublicKeyCodec.Encode method
func (cdc DefaultPublicKeyCodec) Encode(key crypto.PubKey) (*types.PublicKey, error) {
switch key := key.(type) {
case secp256k1.PubKeySecp256k1:
return &types.PublicKey{Sum: &types.PublicKey_Secp256K1{Secp256K1: key[:]}}, nil
case ed255192.PubKeyEd25519:
return &types.PublicKey{Sum: &types.PublicKey_Ed25519{Ed25519: key[:]}}, nil
case sr25519.PubKeySr25519:
return &types.PublicKey{Sum: &types.PublicKey_Sr25519{Sr25519: key[:]}}, nil
case multisig.PubKeyMultisigThreshold:
pubKeys := key.PubKeys
resKeys := make([]*types.PublicKey, len(pubKeys))
for i, k := range pubKeys {
dk, err := cdc.Encode(k)
if err != nil {
return nil, err
}
resKeys[i] = dk
}
return &types.PublicKey{Sum: &types.PublicKey_Multisig{Multisig: &types.PubKeyMultisigThreshold{
K: uint32(key.K),
PubKeys: resKeys,
}}}, nil
default:
return nil, fmt.Errorf("can't encode PubKey of type %T", key)
aaronc marked this conversation as resolved.
Show resolved Hide resolved
}
}
41 changes: 41 additions & 0 deletions std/pubkey_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package std_test

import (
"testing"

"github.com/cosmos/cosmos-sdk/std"

"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/crypto/secp256k1"
"github.com/tendermint/tendermint/crypto/sr25519"

"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
)

func roundTripTest(t *testing.T, pubKey crypto.PubKey) {
cdc := std.DefaultPublicKeyCodec{}

pubKeyEnc, err := cdc.Encode(pubKey)
require.NoError(t, err)
pubKeyDec, err := cdc.Decode(pubKeyEnc)
require.NoError(t, err)
require.Equal(t, pubKey, pubKeyDec)
}

func TestDefaultPublicKeyCodec(t *testing.T) {
pubKeySecp256k1 := secp256k1.GenPrivKey().PubKey()
roundTripTest(t, pubKeySecp256k1)

pubKeyEd25519 := ed25519.GenPrivKey().PubKey()
roundTripTest(t, pubKeyEd25519)

pubKeySr25519 := sr25519.GenPrivKey().PubKey()
roundTripTest(t, pubKeySr25519)

pubKeyMultisig := multisig.NewPubKeyMultisigThreshold(2, []crypto.PubKey{
pubKeySecp256k1, pubKeyEd25519, pubKeySr25519,
})
roundTripTest(t, pubKeyMultisig)
}