Cleanup up Multisig naming (#2255)

* crypto/multisig: Pubkey -> PubKey

* crypto/encoding/amino: use pkg vars for routes

* crypto/multisig/bitarray

* crypto/multisig: ThresholdMultiSignaturePubKey -> PubKeyMultisigThreshold

* crypto/encoding/amino: add PubKeyMultisig to table

* remove bA import alias

https://github.com/tendermint/tendermint/pull/2255#discussion_r211900709
This commit is contained in:
Ethan Buchman
2018-08-28 00:41:40 -04:00
committed by Anton Kaliaev
parent 8972b6e293
commit 38b401657e
8 changed files with 50 additions and 44 deletions

View File

@ -2,8 +2,10 @@ package cryptoAmino
import ( import (
amino "github.com/tendermint/go-amino" amino "github.com/tendermint/go-amino"
"github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/crypto/multisig"
"github.com/tendermint/tendermint/crypto/secp256k1" "github.com/tendermint/tendermint/crypto/secp256k1"
) )
@ -24,15 +26,17 @@ func RegisterAmino(cdc *amino.Codec) {
// These are all written here instead of // These are all written here instead of
cdc.RegisterInterface((*crypto.PubKey)(nil), nil) cdc.RegisterInterface((*crypto.PubKey)(nil), nil)
cdc.RegisterConcrete(ed25519.PubKeyEd25519{}, cdc.RegisterConcrete(ed25519.PubKeyEd25519{},
"tendermint/PubKeyEd25519", nil) ed25519.PubKeyAminoRoute, nil)
cdc.RegisterConcrete(secp256k1.PubKeySecp256k1{}, cdc.RegisterConcrete(secp256k1.PubKeySecp256k1{},
"tendermint/PubKeySecp256k1", nil) secp256k1.PubKeyAminoRoute, nil)
cdc.RegisterConcrete(multisig.PubKeyMultisigThreshold{},
multisig.PubKeyMultisigThresholdAminoRoute, nil)
cdc.RegisterInterface((*crypto.PrivKey)(nil), nil) cdc.RegisterInterface((*crypto.PrivKey)(nil), nil)
cdc.RegisterConcrete(ed25519.PrivKeyEd25519{}, cdc.RegisterConcrete(ed25519.PrivKeyEd25519{},
"tendermint/PrivKeyEd25519", nil) ed25519.PrivKeyAminoRoute, nil)
cdc.RegisterConcrete(secp256k1.PrivKeySecp256k1{}, cdc.RegisterConcrete(secp256k1.PrivKeySecp256k1{},
"tendermint/PrivKeySecp256k1", nil) secp256k1.PrivKeyAminoRoute, nil)
} }
func PrivKeyFromBytes(privKeyBytes []byte) (privKey crypto.PrivKey, err error) { func PrivKeyFromBytes(privKeyBytes []byte) (privKey crypto.PrivKey, err error) {

View File

@ -53,6 +53,7 @@ func ExamplePrintRegisteredTypes() {
//| ---- | ---- | ------ | ----- | ------ | //| ---- | ---- | ------ | ----- | ------ |
//| PubKeyEd25519 | tendermint/PubKeyEd25519 | 0x1624DE64 | 0x20 | | //| PubKeyEd25519 | tendermint/PubKeyEd25519 | 0x1624DE64 | 0x20 | |
//| PubKeySecp256k1 | tendermint/PubKeySecp256k1 | 0xEB5AE987 | 0x21 | | //| PubKeySecp256k1 | tendermint/PubKeySecp256k1 | 0xEB5AE987 | 0x21 | |
//| PubKeyMultisigThreshold | tendermint/PubKeyMultisigThreshold | 0x22C1F7E2 | variable | |
//| PrivKeyEd25519 | tendermint/PrivKeyEd25519 | 0xA3288910 | 0x40 | | //| PrivKeyEd25519 | tendermint/PrivKeyEd25519 | 0xA3288910 | 0x40 | |
//| PrivKeySecp256k1 | tendermint/PrivKeySecp256k1 | 0xE1B0F79B | 0x20 | | //| PrivKeySecp256k1 | tendermint/PrivKeySecp256k1 | 0xE1B0F79B | 0x20 | |
} }

View File

@ -1,4 +1,4 @@
package multisig package bitarray
import ( import (
"bytes" "bytes"

View File

@ -1,4 +1,4 @@
package multisig package bitarray
import ( import (
"encoding/json" "encoding/json"

View File

@ -4,12 +4,13 @@ import (
"errors" "errors"
"github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/multisig/bitarray"
) )
// Multisignature is used to represent the signature object used in the multisigs. // Multisignature is used to represent the signature object used in the multisigs.
// Sigs is a list of signatures, sorted by corresponding index. // Sigs is a list of signatures, sorted by corresponding index.
type Multisignature struct { type Multisignature struct {
BitArray *CompactBitArray BitArray *bitarray.CompactBitArray
Sigs [][]byte Sigs [][]byte
} }
@ -17,7 +18,7 @@ type Multisignature struct {
func NewMultisig(n int) *Multisignature { func NewMultisig(n int) *Multisignature {
// Default the signature list to have a capacity of two, since we can // Default the signature list to have a capacity of two, since we can
// expect that most multisigs will require multiple signers. // expect that most multisigs will require multiple signers.
return &Multisignature{NewCompactBitArray(n), make([][]byte, 0, 2)} return &Multisignature{bitarray.NewCompactBitArray(n), make([][]byte, 0, 2)}
} }
// GetIndex returns the index of pk in keys. Returns -1 if not found // GetIndex returns the index of pk in keys. Returns -1 if not found
@ -52,9 +53,9 @@ func (mSig *Multisignature) AddSignature(sig []byte, index int) {
mSig.Sigs[newSigIndex] = sig mSig.Sigs[newSigIndex] = sig
} }
// AddSignatureFromPubkey adds a signature to the multisig, // AddSignatureFromPubKey adds a signature to the multisig,
// at the index in keys corresponding to the provided pubkey. // at the index in keys corresponding to the provided pubkey.
func (mSig *Multisignature) AddSignatureFromPubkey(sig []byte, pubkey crypto.PubKey, keys []crypto.PubKey) error { func (mSig *Multisignature) AddSignatureFromPubKey(sig []byte, pubkey crypto.PubKey, keys []crypto.PubKey) error {
index := getIndex(pubkey, keys) index := getIndex(pubkey, keys)
if index == -1 { if index == -1 {
return errors.New("provided key didn't exist in pubkeys") return errors.New("provided key didn't exist in pubkeys")

View File

@ -5,24 +5,24 @@ import (
"github.com/tendermint/tendermint/crypto/tmhash" "github.com/tendermint/tendermint/crypto/tmhash"
) )
// ThresholdMultiSignaturePubKey implements a K of N threshold multisig. // PubKeyMultisigThreshold implements a K of N threshold multisig.
type ThresholdMultiSignaturePubKey struct { type PubKeyMultisigThreshold struct {
K uint `json:"threshold"` K uint `json:"threshold"`
Pubkeys []crypto.PubKey `json:"pubkeys"` PubKeys []crypto.PubKey `json:"pubkeys"`
} }
var _ crypto.PubKey = &ThresholdMultiSignaturePubKey{} var _ crypto.PubKey = &PubKeyMultisigThreshold{}
// NewThresholdMultiSignaturePubKey returns a new ThresholdMultiSignaturePubKey. // NewPubKeyMultisigThreshold returns a new PubKeyMultisigThreshold.
// Panics if len(pubkeys) < k or 0 >= k. // Panics if len(pubkeys) < k or 0 >= k.
func NewThresholdMultiSignaturePubKey(k int, pubkeys []crypto.PubKey) crypto.PubKey { func NewPubKeyMultisigThreshold(k int, pubkeys []crypto.PubKey) crypto.PubKey {
if k <= 0 { if k <= 0 {
panic("threshold k of n multisignature: k <= 0") panic("threshold k of n multisignature: k <= 0")
} }
if len(pubkeys) < k { if len(pubkeys) < k {
panic("threshold k of n multisignature: len(pubkeys) < k") panic("threshold k of n multisignature: len(pubkeys) < k")
} }
return &ThresholdMultiSignaturePubKey{uint(k), pubkeys} return &PubKeyMultisigThreshold{uint(k), pubkeys}
} }
// VerifyBytes expects sig to be an amino encoded version of a MultiSignature. // VerifyBytes expects sig to be an amino encoded version of a MultiSignature.
@ -31,7 +31,7 @@ func NewThresholdMultiSignaturePubKey(k int, pubkeys []crypto.PubKey) crypto.Pub
// and all signatures are valid. (Not just k of the signatures) // and all signatures are valid. (Not just k of the signatures)
// The multisig uses a bitarray, so multiple signatures for the same key is not // The multisig uses a bitarray, so multiple signatures for the same key is not
// a concern. // a concern.
func (pk *ThresholdMultiSignaturePubKey) VerifyBytes(msg []byte, marshalledSig []byte) bool { func (pk *PubKeyMultisigThreshold) VerifyBytes(msg []byte, marshalledSig []byte) bool {
var sig *Multisignature var sig *Multisignature
err := cdc.UnmarshalBinaryBare(marshalledSig, &sig) err := cdc.UnmarshalBinaryBare(marshalledSig, &sig)
if err != nil { if err != nil {
@ -39,7 +39,7 @@ func (pk *ThresholdMultiSignaturePubKey) VerifyBytes(msg []byte, marshalledSig [
} }
size := sig.BitArray.Size() size := sig.BitArray.Size()
// ensure bit array is the correct size // ensure bit array is the correct size
if len(pk.Pubkeys) != size { if len(pk.PubKeys) != size {
return false return false
} }
// ensure size of signature list // ensure size of signature list
@ -54,7 +54,7 @@ func (pk *ThresholdMultiSignaturePubKey) VerifyBytes(msg []byte, marshalledSig [
sigIndex := 0 sigIndex := 0
for i := 0; i < size; i++ { for i := 0; i < size; i++ {
if sig.BitArray.GetIndex(i) { if sig.BitArray.GetIndex(i) {
if !pk.Pubkeys[i].VerifyBytes(msg, sig.Sigs[sigIndex]) { if !pk.PubKeys[i].VerifyBytes(msg, sig.Sigs[sigIndex]) {
return false return false
} }
sigIndex++ sigIndex++
@ -63,28 +63,28 @@ func (pk *ThresholdMultiSignaturePubKey) VerifyBytes(msg []byte, marshalledSig [
return true return true
} }
// Bytes returns the amino encoded version of the ThresholdMultiSignaturePubKey // Bytes returns the amino encoded version of the PubKeyMultisigThreshold
func (pk *ThresholdMultiSignaturePubKey) Bytes() []byte { func (pk *PubKeyMultisigThreshold) Bytes() []byte {
return cdc.MustMarshalBinaryBare(pk) return cdc.MustMarshalBinaryBare(pk)
} }
// Address returns tmhash(ThresholdMultiSignaturePubKey.Bytes()) // Address returns tmhash(PubKeyMultisigThreshold.Bytes())
func (pk *ThresholdMultiSignaturePubKey) Address() crypto.Address { func (pk *PubKeyMultisigThreshold) Address() crypto.Address {
return crypto.Address(tmhash.Sum(pk.Bytes())) return crypto.Address(tmhash.Sum(pk.Bytes()))
} }
// Equals returns true iff pk and other both have the same number of keys, and // Equals returns true iff pk and other both have the same number of keys, and
// all constituent keys are the same, and in the same order. // all constituent keys are the same, and in the same order.
func (pk *ThresholdMultiSignaturePubKey) Equals(other crypto.PubKey) bool { func (pk *PubKeyMultisigThreshold) Equals(other crypto.PubKey) bool {
otherKey, sameType := other.(*ThresholdMultiSignaturePubKey) otherKey, sameType := other.(*PubKeyMultisigThreshold)
if !sameType { if !sameType {
return false return false
} }
if pk.K != otherKey.K || len(pk.Pubkeys) != len(otherKey.Pubkeys) { if pk.K != otherKey.K || len(pk.PubKeys) != len(otherKey.PubKeys) {
return false return false
} }
for i := 0; i < len(pk.Pubkeys); i++ { for i := 0; i < len(pk.PubKeys); i++ {
if !pk.Pubkeys[i].Equals(otherKey.Pubkeys[i]) { if !pk.PubKeys[i].Equals(otherKey.PubKeys[i]) {
return false return false
} }
} }

View File

@ -34,30 +34,30 @@ func TestThresholdMultisigValidCases(t *testing.T) {
}, },
} }
for tcIndex, tc := range cases { for tcIndex, tc := range cases {
multisigKey := NewThresholdMultiSignaturePubKey(tc.k, tc.pubkeys) multisigKey := NewPubKeyMultisigThreshold(tc.k, tc.pubkeys)
multisignature := NewMultisig(len(tc.pubkeys)) multisignature := NewMultisig(len(tc.pubkeys))
for i := 0; i < tc.k-1; i++ { for i := 0; i < tc.k-1; i++ {
signingIndex := tc.signingIndices[i] signingIndex := tc.signingIndices[i]
multisignature.AddSignatureFromPubkey(tc.signatures[signingIndex], tc.pubkeys[signingIndex], tc.pubkeys) multisignature.AddSignatureFromPubKey(tc.signatures[signingIndex], tc.pubkeys[signingIndex], tc.pubkeys)
require.False(t, multisigKey.VerifyBytes(tc.msg, multisignature.Marshal()), require.False(t, multisigKey.VerifyBytes(tc.msg, multisignature.Marshal()),
"multisig passed when i < k, tc %d, i %d", tcIndex, i) "multisig passed when i < k, tc %d, i %d", tcIndex, i)
multisignature.AddSignatureFromPubkey(tc.signatures[signingIndex], tc.pubkeys[signingIndex], tc.pubkeys) multisignature.AddSignatureFromPubKey(tc.signatures[signingIndex], tc.pubkeys[signingIndex], tc.pubkeys)
require.Equal(t, i+1, len(multisignature.Sigs), require.Equal(t, i+1, len(multisignature.Sigs),
"adding a signature for the same pubkey twice increased signature count by 2, tc %d", tcIndex) "adding a signature for the same pubkey twice increased signature count by 2, tc %d", tcIndex)
} }
require.False(t, multisigKey.VerifyBytes(tc.msg, multisignature.Marshal()), require.False(t, multisigKey.VerifyBytes(tc.msg, multisignature.Marshal()),
"multisig passed with k - 1 sigs, tc %d", tcIndex) "multisig passed with k - 1 sigs, tc %d", tcIndex)
multisignature.AddSignatureFromPubkey(tc.signatures[tc.signingIndices[tc.k]], tc.pubkeys[tc.signingIndices[tc.k]], tc.pubkeys) multisignature.AddSignatureFromPubKey(tc.signatures[tc.signingIndices[tc.k]], tc.pubkeys[tc.signingIndices[tc.k]], tc.pubkeys)
require.True(t, multisigKey.VerifyBytes(tc.msg, multisignature.Marshal()), require.True(t, multisigKey.VerifyBytes(tc.msg, multisignature.Marshal()),
"multisig failed after k good signatures, tc %d", tcIndex) "multisig failed after k good signatures, tc %d", tcIndex)
for i := tc.k + 1; i < len(tc.signingIndices); i++ { for i := tc.k + 1; i < len(tc.signingIndices); i++ {
signingIndex := tc.signingIndices[i] signingIndex := tc.signingIndices[i]
multisignature.AddSignatureFromPubkey(tc.signatures[signingIndex], tc.pubkeys[signingIndex], tc.pubkeys) multisignature.AddSignatureFromPubKey(tc.signatures[signingIndex], tc.pubkeys[signingIndex], tc.pubkeys)
require.Equal(t, tc.passAfterKSignatures[i-tc.k-1], require.Equal(t, tc.passAfterKSignatures[i-tc.k-1],
multisigKey.VerifyBytes(tc.msg, multisignature.Marshal()), multisigKey.VerifyBytes(tc.msg, multisignature.Marshal()),
"multisig didn't verify as expected after k sigs, tc %d, i %d", tcIndex, i) "multisig didn't verify as expected after k sigs, tc %d, i %d", tcIndex, i)
multisignature.AddSignatureFromPubkey(tc.signatures[signingIndex], tc.pubkeys[signingIndex], tc.pubkeys) multisignature.AddSignatureFromPubKey(tc.signatures[signingIndex], tc.pubkeys[signingIndex], tc.pubkeys)
require.Equal(t, i+1, len(multisignature.Sigs), require.Equal(t, i+1, len(multisignature.Sigs),
"adding a signature for the same pubkey twice increased signature count by 2, tc %d", tcIndex) "adding a signature for the same pubkey twice increased signature count by 2, tc %d", tcIndex)
} }
@ -68,21 +68,21 @@ func TestThresholdMultisigValidCases(t *testing.T) {
func TestThresholdMultisigDuplicateSignatures(t *testing.T) { func TestThresholdMultisigDuplicateSignatures(t *testing.T) {
msg := []byte{1, 2, 3, 4, 5} msg := []byte{1, 2, 3, 4, 5}
pubkeys, sigs := generatePubKeysAndSignatures(5, msg) pubkeys, sigs := generatePubKeysAndSignatures(5, msg)
multisigKey := NewThresholdMultiSignaturePubKey(2, pubkeys) multisigKey := NewPubKeyMultisigThreshold(2, pubkeys)
multisignature := NewMultisig(5) multisignature := NewMultisig(5)
require.False(t, multisigKey.VerifyBytes(msg, multisignature.Marshal())) require.False(t, multisigKey.VerifyBytes(msg, multisignature.Marshal()))
multisignature.AddSignatureFromPubkey(sigs[0], pubkeys[0], pubkeys) multisignature.AddSignatureFromPubKey(sigs[0], pubkeys[0], pubkeys)
// Add second signature manually // Add second signature manually
multisignature.Sigs = append(multisignature.Sigs, sigs[0]) multisignature.Sigs = append(multisignature.Sigs, sigs[0])
require.False(t, multisigKey.VerifyBytes(msg, multisignature.Marshal())) require.False(t, multisigKey.VerifyBytes(msg, multisignature.Marshal()))
} }
// TODO: Fully replace this test with table driven tests // TODO: Fully replace this test with table driven tests
func TestMultiSigPubkeyEquality(t *testing.T) { func TestMultiSigPubKeyEquality(t *testing.T) {
msg := []byte{1, 2, 3, 4} msg := []byte{1, 2, 3, 4}
pubkeys, _ := generatePubKeysAndSignatures(5, msg) pubkeys, _ := generatePubKeysAndSignatures(5, msg)
multisigKey := NewThresholdMultiSignaturePubKey(2, pubkeys) multisigKey := NewPubKeyMultisigThreshold(2, pubkeys)
var unmarshalledMultisig *ThresholdMultiSignaturePubKey var unmarshalledMultisig *PubKeyMultisigThreshold
cdc.MustUnmarshalBinaryBare(multisigKey.Bytes(), &unmarshalledMultisig) cdc.MustUnmarshalBinaryBare(multisigKey.Bytes(), &unmarshalledMultisig)
require.True(t, multisigKey.Equals(unmarshalledMultisig)) require.True(t, multisigKey.Equals(unmarshalledMultisig))
@ -91,7 +91,7 @@ func TestMultiSigPubkeyEquality(t *testing.T) {
copy(pubkeysCpy, pubkeys) copy(pubkeysCpy, pubkeys)
pubkeysCpy[4] = pubkeys[3] pubkeysCpy[4] = pubkeys[3]
pubkeysCpy[3] = pubkeys[4] pubkeysCpy[3] = pubkeys[4]
multisigKey2 := NewThresholdMultiSignaturePubKey(2, pubkeysCpy) multisigKey2 := NewPubKeyMultisigThreshold(2, pubkeysCpy)
require.False(t, multisigKey.Equals(multisigKey2)) require.False(t, multisigKey.Equals(multisigKey2))
} }

View File

@ -10,15 +10,15 @@ import (
// TODO: Figure out API for others to either add their own pubkey types, or // TODO: Figure out API for others to either add their own pubkey types, or
// to make verify / marshal accept a cdc. // to make verify / marshal accept a cdc.
const ( const (
ThresholdPubkeyAminoRoute = "tendermint/PubkeyMultisigThreshold" PubKeyMultisigThresholdAminoRoute = "tendermint/PubKeyMultisigThreshold"
) )
var cdc = amino.NewCodec() var cdc = amino.NewCodec()
func init() { func init() {
cdc.RegisterInterface((*crypto.PubKey)(nil), nil) cdc.RegisterInterface((*crypto.PubKey)(nil), nil)
cdc.RegisterConcrete(ThresholdMultiSignaturePubKey{}, cdc.RegisterConcrete(PubKeyMultisigThreshold{},
ThresholdPubkeyAminoRoute, nil) PubKeyMultisigThresholdAminoRoute, nil)
cdc.RegisterConcrete(ed25519.PubKeyEd25519{}, cdc.RegisterConcrete(ed25519.PubKeyEd25519{},
ed25519.PubKeyAminoRoute, nil) ed25519.PubKeyAminoRoute, nil)
cdc.RegisterConcrete(secp256k1.PubKeySecp256k1{}, cdc.RegisterConcrete(secp256k1.PubKeySecp256k1{},