Skip to content

Commit

Permalink
Add PublicKeyCodec (#6372)
Browse files Browse the repository at this point in the history
* Add PublicKeyCodec

* Add tests

* Remove cache codec

* Remove cache codec

* Revert proto changes

* Revert proto changes

* refactor and move docs

* Lint

* Apply suggestions from code review

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>
  • Loading branch information
aaronc and fedekunze authored Jun 9, 2020
1 parent 08b7557 commit 6740d27
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 3 deletions.
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 decode PubKey of type %T. Use a custom PublicKeyCodec instead", key)
}
}

// 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. Use a custom PublicKeyCodec instead", key)
}
}
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)
}

0 comments on commit 6740d27

Please sign in to comment.