Add SignatureV2 infrastructure (#6373)

* Updte tx generator

* Add sigv2, PublicKeyCodec

* revert changes

* revert changes

* updates

* Updates

* Integrate multisig support

* Undo move

* remove func

* undo

* godocs

* godocs, cleanup

* Cleanup

* godocs, tests

* lint

* Re-enable VerifyBytes

* Address comments

* Fix imports

* Update crypto/types/multisig/multisignature.go

* Add test for MultiSignatureData

* Add nested multisig case

* Add test for AddSignatureV2

* Add changelog

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>
Co-authored-by: sahith-narahari <sahithnarahari@gmail.com>
This commit is contained in:
Aaron Craelius
2020-06-12 18:13:20 +00:00
committed by GitHub
co-authored by Federico Kunze sahith-narahari
parent 7871910359
commit 60f7edfe3d
25 changed files with 752 additions and 286 deletions
+8 -8
View File
@@ -1,7 +1,7 @@
package multisig
import (
amino "github.com/tendermint/go-amino"
"github.com/tendermint/go-amino"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/ed25519"
@@ -10,21 +10,21 @@ import (
)
// 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 (
PubKeyAminoRoute = "tendermint/PubKeyMultisigThreshold"
)
var cdc = amino.NewCodec()
var Cdc = amino.NewCodec()
func init() {
cdc.RegisterInterface((*crypto.PubKey)(nil), nil)
cdc.RegisterConcrete(PubKeyMultisigThreshold{},
Cdc.RegisterInterface((*crypto.PubKey)(nil), nil)
Cdc.RegisterConcrete(PubKeyMultisigThreshold{},
PubKeyAminoRoute, nil)
cdc.RegisterConcrete(ed25519.PubKeyEd25519{},
Cdc.RegisterConcrete(ed25519.PubKeyEd25519{},
ed25519.PubKeyAminoName, nil)
cdc.RegisterConcrete(sr25519.PubKeySr25519{},
Cdc.RegisterConcrete(sr25519.PubKeySr25519{},
sr25519.PubKeyAminoName, nil)
cdc.RegisterConcrete(secp256k1.PubKeySecp256k1{},
Cdc.RegisterConcrete(secp256k1.PubKeySecp256k1{},
secp256k1.PubKeyAminoName, nil)
}
+31 -19
View File
@@ -7,20 +7,23 @@ import (
"github.com/tendermint/tendermint/crypto"
"github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
)
// Multisignature is used to represent the signature object used in the multisigs.
// AminoMultisignature is used to represent amino multi-signatures for StdTx's.
// It is assumed that all signatures were made with SIGN_MODE_LEGACY_AMINO_JSON.
// Sigs is a list of signatures, sorted by corresponding index.
type Multisignature struct {
type AminoMultisignature struct {
BitArray *types.CompactBitArray
Sigs [][]byte
}
// NewMultisig returns a new Multisignature of size n.
func NewMultisig(n int) *Multisignature {
// Default the signature list to have a capacity of two, since we can
// expect that most multisigs will require multiple signers.
return &Multisignature{types.NewCompactBitArray(n), make([][]byte, 0, 2)}
// NewMultisig returns a new MultiSignatureData
func NewMultisig(n int) *signing.MultiSignatureData {
return &signing.MultiSignatureData{
BitArray: types.NewCompactBitArray(n),
Signatures: make([]signing.SignatureData, 0, n),
}
}
// GetIndex returns the index of pk in keys. Returns -1 if not found
@@ -35,29 +38,39 @@ func getIndex(pk crypto.PubKey, keys []crypto.PubKey) int {
// AddSignature adds a signature to the multisig, at the corresponding index.
// If the signature already exists, replace it.
func (mSig *Multisignature) AddSignature(sig []byte, index int) {
func AddSignature(mSig *signing.MultiSignatureData, sig signing.SignatureData, index int) {
newSigIndex := mSig.BitArray.NumTrueBitsBefore(index)
// Signature already exists, just replace the value there
if mSig.BitArray.GetIndex(index) {
mSig.Sigs[newSigIndex] = sig
mSig.Signatures[newSigIndex] = sig
return
}
mSig.BitArray.SetIndex(index, true)
// Optimization if the index is the greatest index
if newSigIndex == len(mSig.Sigs) {
mSig.Sigs = append(mSig.Sigs, sig)
if newSigIndex == len(mSig.Signatures) {
mSig.Signatures = append(mSig.Signatures, sig)
return
}
// Expand slice by one with a dummy element, move all elements after i
// over by one, then place the new signature in that gap.
mSig.Sigs = append(mSig.Sigs, make([]byte, 0))
copy(mSig.Sigs[newSigIndex+1:], mSig.Sigs[newSigIndex:])
mSig.Sigs[newSigIndex] = sig
mSig.Signatures = append(mSig.Signatures, &signing.SingleSignatureData{})
copy(mSig.Signatures[newSigIndex+1:], mSig.Signatures[newSigIndex:])
mSig.Signatures[newSigIndex] = sig
}
// AddSignatureFromPubKey adds a signature to the multisig, at the index in
// keys corresponding to the provided pubkey.
func (mSig *Multisignature) AddSignatureFromPubKey(sig []byte, pubkey crypto.PubKey, keys []crypto.PubKey) error {
func AddSignatureFromPubKey(mSig *signing.MultiSignatureData, sig signing.SignatureData, pubkey crypto.PubKey, keys []crypto.PubKey) error {
if mSig == nil {
return fmt.Errorf("value of mSig is nil %v", mSig)
}
if sig == nil {
return fmt.Errorf("value of sig is nil %v", sig)
}
if pubkey == nil || keys == nil {
return fmt.Errorf("pubkey or keys can't be nil %v %v", pubkey, keys)
}
index := getIndex(pubkey, keys)
if index == -1 {
keysStr := make([]string, len(keys))
@@ -68,11 +81,10 @@ func (mSig *Multisignature) AddSignatureFromPubKey(sig []byte, pubkey crypto.Pub
return fmt.Errorf("provided key %X doesn't exist in pubkeys: \n%s", pubkey.Bytes(), strings.Join(keysStr, "\n"))
}
mSig.AddSignature(sig, index)
AddSignature(mSig, sig, index)
return nil
}
// Marshal the multisignature with amino
func (mSig *Multisignature) Marshal() []byte {
return cdc.MustMarshalBinaryBare(mSig)
func AddSignatureV2(mSig *signing.MultiSignatureData, sig signing.SignatureV2, keys []crypto.PubKey) error {
return AddSignatureFromPubKey(mSig, sig.Data, sig.PubKey, keys)
}
+25
View File
@@ -0,0 +1,25 @@
package multisig
import (
"github.com/tendermint/tendermint/crypto"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
)
// PubKey defines a type which supports multi-signature verification via MultiSignatureData
// which supports multiple SignMode's.
type PubKey interface {
crypto.PubKey
// VerifyMultisignature verifies the provide multi-signature represented by MultiSignatureData
// using getSignBytes to retrieve the sign bytes to verify against for the provided mode.
VerifyMultisignature(getSignBytes GetSignBytesFunc, sig *signing.MultiSignatureData) error
// GetPubKeys returns the crypto.PubKey's nested within the multi-sig PubKey
GetPubKeys() []crypto.PubKey
}
// GetSignBytesFunc defines a function type which returns sign bytes for a given SignMode or an error.
// It will generally be implemented as a closure which wraps whatever signable object signatures are
// being verified against.
type GetSignBytesFunc func(mode signing.SignMode) ([]byte, error)
+68 -8
View File
@@ -1,7 +1,11 @@
package multisig
import (
"fmt"
"github.com/tendermint/tendermint/crypto"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
)
// PubKeyMultisigThreshold implements a K of N threshold multisig.
@@ -10,11 +14,11 @@ type PubKeyMultisigThreshold struct {
PubKeys []crypto.PubKey `json:"pubkeys"`
}
var _ crypto.PubKey = PubKeyMultisigThreshold{}
var _ PubKey = PubKeyMultisigThreshold{}
// NewPubKeyMultisigThreshold returns a new PubKeyMultisigThreshold.
// Panics if len(pubkeys) < k or 0 >= k.
func NewPubKeyMultisigThreshold(k int, pubkeys []crypto.PubKey) crypto.PubKey {
func NewPubKeyMultisigThreshold(k int, pubkeys []crypto.PubKey) PubKey {
if k <= 0 {
panic("threshold k of n multisignature: k <= 0")
}
@@ -35,9 +39,12 @@ func NewPubKeyMultisigThreshold(k int, pubkeys []crypto.PubKey) crypto.PubKey {
// 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
// a concern.
//
// NOTE: VerifyMultisignature should preferred to VerifyBytes which only works
// with amino multisignatures.
func (pk PubKeyMultisigThreshold) VerifyBytes(msg []byte, marshalledSig []byte) bool {
var sig Multisignature
err := cdc.UnmarshalBinaryBare(marshalledSig, &sig)
var sig AminoMultisignature
err := Cdc.UnmarshalBinaryBare(marshalledSig, &sig)
if err != nil {
return false
}
@@ -67,12 +74,65 @@ func (pk PubKeyMultisigThreshold) VerifyBytes(msg []byte, marshalledSig []byte)
return true
}
// Bytes returns the amino encoded version of the PubKeyMultisigThreshold
func (pk PubKeyMultisigThreshold) Bytes() []byte {
return cdc.MustMarshalBinaryBare(pk)
// VerifyMultisignature implements the PubKey.VerifyMultisignature method
func (pk PubKeyMultisigThreshold) VerifyMultisignature(getSignBytes GetSignBytesFunc, sig *signing.MultiSignatureData) error {
bitarray := sig.BitArray
sigs := sig.Signatures
size := bitarray.Size()
// ensure bit array is the correct size
if len(pk.PubKeys) != size {
return fmt.Errorf("bit array size is incorrect %d", len(pk.PubKeys))
}
// ensure size of signature list
if len(sigs) < int(pk.K) || len(sigs) > size {
return fmt.Errorf("signature size is incorrect %d", len(sigs))
}
// ensure at least k signatures are set
if bitarray.NumTrueBitsBefore(size) < int(pk.K) {
return fmt.Errorf("minimum number of signatures not set, have %d, expected %d", bitarray.NumTrueBitsBefore(size), int(pk.K))
}
// index in the list of signatures which we are concerned with.
sigIndex := 0
for i := 0; i < size; i++ {
if bitarray.GetIndex(i) {
si := sig.Signatures[sigIndex]
switch si := si.(type) {
case *signing.SingleSignatureData:
msg, err := getSignBytes(si.SignMode)
if err != nil {
return err
}
if !pk.PubKeys[i].VerifyBytes(msg, si.Signature) {
return err
}
case *signing.MultiSignatureData:
nestedMultisigPk, ok := pk.PubKeys[i].(PubKey)
if !ok {
return fmt.Errorf("unable to parse pubkey of index %d", i)
}
if err := nestedMultisigPk.VerifyMultisignature(getSignBytes, si); err != nil {
return err
}
default:
return fmt.Errorf("improper signature data type for index %d", sigIndex)
}
sigIndex++
}
}
return nil
}
// Address returns tmhash(PubKey.Bytes())
// GetPubKeys implements the PubKey.GetPubKeys method
func (pk PubKeyMultisigThreshold) GetPubKeys() []crypto.PubKey {
return pk.PubKeys
}
// Bytes returns the amino encoded version of the PubKeyMultisigThreshold
func (pk PubKeyMultisigThreshold) Bytes() []byte {
return Cdc.MustMarshalBinaryBare(pk)
}
// Address returns tmhash(PubKeyMultisigThreshold.Bytes())
func (pk PubKeyMultisigThreshold) Address() crypto.Address {
return crypto.AddressHash(pk.Bytes())
}
+126 -43
View File
@@ -1,4 +1,4 @@
package multisig
package multisig_test
import (
"math/rand"
@@ -6,6 +6,12 @@ import (
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/crypto/secp256k1"
@@ -22,7 +28,7 @@ func TestThresholdMultisigValidCases(t *testing.T) {
pubkeys []crypto.PubKey
signingIndices []int
// signatures should be the same size as signingIndices.
signatures [][]byte
signatures []signing.SignatureData
passAfterKSignatures []bool
}{
{
@@ -35,50 +41,49 @@ func TestThresholdMultisigValidCases(t *testing.T) {
},
}
for tcIndex, tc := range cases {
multisigKey := NewPubKeyMultisigThreshold(tc.k, tc.pubkeys)
multisignature := NewMultisig(len(tc.pubkeys))
multisigKey := multisig.NewPubKeyMultisigThreshold(tc.k, tc.pubkeys)
multisignature := multisig.NewMultisig(len(tc.pubkeys))
signBytesFn := func(mode signing.SignMode) ([]byte, error) { return tc.msg, nil }
for i := 0; i < tc.k-1; i++ {
signingIndex := tc.signingIndices[i]
require.NoError(
t,
multisignature.AddSignatureFromPubKey(tc.signatures[signingIndex], tc.pubkeys[signingIndex], tc.pubkeys),
multisig.AddSignatureFromPubKey(multisignature, tc.signatures[signingIndex], tc.pubkeys[signingIndex], tc.pubkeys),
)
bz := multisignature.Marshal()
require.False(
require.Error(
t,
multisigKey.VerifyBytes(tc.msg, bz),
multisigKey.VerifyMultisignature(signBytesFn, multisignature),
"multisig passed when i < k, tc %d, i %d", tcIndex, i,
)
require.NoError(
t,
multisignature.AddSignatureFromPubKey(tc.signatures[signingIndex], tc.pubkeys[signingIndex], tc.pubkeys),
multisig.AddSignatureFromPubKey(multisignature, tc.signatures[signingIndex], tc.pubkeys[signingIndex], tc.pubkeys),
)
require.Equal(
t,
i+1,
len(multisignature.Sigs),
len(multisignature.Signatures),
"adding a signature for the same pubkey twice increased signature count by 2, tc %d", tcIndex,
)
}
bz := multisignature.Marshal()
require.False(
require.Error(
t,
multisigKey.VerifyBytes(tc.msg, bz),
multisigKey.VerifyMultisignature(signBytesFn, multisignature),
"multisig passed with k - 1 sigs, tc %d", tcIndex,
)
require.NoError(
t,
multisignature.AddSignatureFromPubKey(
multisig.AddSignatureFromPubKey(
multisignature,
tc.signatures[tc.signingIndices[tc.k]],
tc.pubkeys[tc.signingIndices[tc.k]],
tc.pubkeys,
),
)
bz = multisignature.Marshal()
require.True(
require.NoError(
t,
multisigKey.VerifyBytes(tc.msg, bz),
multisigKey.VerifyMultisignature(signBytesFn, multisignature),
"multisig failed after k good signatures, tc %d", tcIndex,
)
@@ -87,23 +92,24 @@ func TestThresholdMultisigValidCases(t *testing.T) {
require.NoError(
t,
multisignature.AddSignatureFromPubKey(tc.signatures[signingIndex], tc.pubkeys[signingIndex], tc.pubkeys),
multisig.AddSignatureFromPubKey(multisignature, tc.signatures[signingIndex], tc.pubkeys[signingIndex], tc.pubkeys),
)
bz := multisignature.Marshal()
require.Equal(
t,
tc.passAfterKSignatures[i-tc.k-1],
multisigKey.VerifyBytes(tc.msg, bz),
tc.passAfterKSignatures[i-(tc.k)-1],
multisigKey.VerifyMultisignature(func(mode signing.SignMode) ([]byte, error) {
return tc.msg, nil
}, multisignature),
"multisig didn't verify as expected after k sigs, tc %d, i %d", tcIndex, i,
)
require.NoError(
t,
multisignature.AddSignatureFromPubKey(tc.signatures[signingIndex], tc.pubkeys[signingIndex], tc.pubkeys),
multisig.AddSignatureFromPubKey(multisignature, tc.signatures[signingIndex], tc.pubkeys[signingIndex], tc.pubkeys),
)
require.Equal(
t,
i+1,
len(multisignature.Sigs),
len(multisignature.Signatures),
"adding a signature for the same pubkey twice increased signature count by 2, tc %d", tcIndex,
)
}
@@ -114,24 +120,24 @@ func TestThresholdMultisigValidCases(t *testing.T) {
func TestThresholdMultisigDuplicateSignatures(t *testing.T) {
msg := []byte{1, 2, 3, 4, 5}
pubkeys, sigs := generatePubKeysAndSignatures(5, msg)
multisigKey := NewPubKeyMultisigThreshold(2, pubkeys)
multisignature := NewMultisig(5)
bz := multisignature.Marshal()
multisigKey := multisig.NewPubKeyMultisigThreshold(2, pubkeys)
multisignature := multisig.NewMultisig(5)
signBytesFn := func(mode signing.SignMode) ([]byte, error) { return msg, nil }
require.False(t, multisigKey.VerifyBytes(msg, bz))
multisignature.AddSignatureFromPubKey(sigs[0], pubkeys[0], pubkeys)
require.Error(t, multisigKey.VerifyMultisignature(signBytesFn, multisignature))
multisig.AddSignatureFromPubKey(multisignature, sigs[0], pubkeys[0], pubkeys)
// Add second signature manually
multisignature.Sigs = append(multisignature.Sigs, sigs[0])
require.False(t, multisigKey.VerifyBytes(msg, bz))
multisignature.Signatures = append(multisignature.Signatures, sigs[0])
require.Error(t, multisigKey.VerifyMultisignature(signBytesFn, multisignature))
}
// TODO: Fully replace this test with table driven tests
func TestMultiSigPubKeyEquality(t *testing.T) {
msg := []byte{1, 2, 3, 4}
pubkeys, _ := generatePubKeysAndSignatures(5, msg)
multisigKey := NewPubKeyMultisigThreshold(2, pubkeys)
var unmarshalledMultisig PubKeyMultisigThreshold
cdc.MustUnmarshalBinaryBare(multisigKey.Bytes(), &unmarshalledMultisig)
multisigKey := multisig.NewPubKeyMultisigThreshold(2, pubkeys)
var unmarshalledMultisig multisig.PubKeyMultisigThreshold
multisig.Cdc.MustUnmarshalBinaryBare(multisigKey.Bytes(), &unmarshalledMultisig)
require.True(t, multisigKey.Equals(unmarshalledMultisig))
// Ensure that reordering pubkeys is treated as a different pubkey
@@ -139,36 +145,88 @@ func TestMultiSigPubKeyEquality(t *testing.T) {
copy(pubkeysCpy, pubkeys)
pubkeysCpy[4] = pubkeys[3]
pubkeysCpy[3] = pubkeys[4]
multisigKey2 := NewPubKeyMultisigThreshold(2, pubkeysCpy)
multisigKey2 := multisig.NewPubKeyMultisigThreshold(2, pubkeysCpy)
require.False(t, multisigKey.Equals(multisigKey2))
}
func TestAddress(t *testing.T) {
msg := []byte{1, 2, 3, 4}
pubkeys, _ := generatePubKeysAndSignatures(5, msg)
multisigKey := NewPubKeyMultisigThreshold(2, pubkeys)
multisigKey := multisig.NewPubKeyMultisigThreshold(2, pubkeys)
require.Len(t, multisigKey.Address().Bytes(), 20)
}
func TestPubKeyMultisigThresholdAminoToIface(t *testing.T) {
msg := []byte{1, 2, 3, 4}
pubkeys, _ := generatePubKeysAndSignatures(5, msg)
multisigKey := NewPubKeyMultisigThreshold(2, pubkeys)
multisigKey := multisig.NewPubKeyMultisigThreshold(2, pubkeys)
ab, err := cdc.MarshalBinaryLengthPrefixed(multisigKey)
ab, err := multisig.Cdc.MarshalBinaryLengthPrefixed(multisigKey)
require.NoError(t, err)
// like other crypto.Pubkey implementations (e.g. ed25519.PubKey),
// PubKey should be deserializable into a crypto.PubKey:
// like other crypto.Pubkey implementations (e.g. ed25519.PubKeyMultisigThreshold),
// PubKeyMultisigThreshold should be deserializable into a crypto.PubKeyMultisigThreshold:
var pubKey crypto.PubKey
err = cdc.UnmarshalBinaryLengthPrefixed(ab, &pubKey)
err = multisig.Cdc.UnmarshalBinaryLengthPrefixed(ab, &pubKey)
require.NoError(t, err)
require.Equal(t, multisigKey, pubKey)
}
func generatePubKeysAndSignatures(n int, msg []byte) (pubkeys []crypto.PubKey, signatures [][]byte) {
func TestMultiSignature(t *testing.T) {
msg := []byte{1, 2, 3, 4}
pk, sig := generateNestedMultiSignature(3, msg)
signBytesFn := func(mode signing.SignMode) ([]byte, error) { return msg, nil }
err := pk.VerifyMultisignature(signBytesFn, sig)
require.NoError(t, err)
}
func TestMultiSigMigration(t *testing.T) {
msg := []byte{1, 2, 3, 4}
pkSet, sigs := generatePubKeysAndSignatures(2, msg)
multisignature := multisig.NewMultisig(2)
multisigKey := multisig.NewPubKeyMultisigThreshold(2, pkSet)
signBytesFn := func(mode signing.SignMode) ([]byte, error) { return msg, nil }
cdc := codec.New()
err := multisig.AddSignatureFromPubKey(multisignature, sigs[0], pkSet[0], pkSet)
// create a StdSignature for msg, and convert it to sigV2
sig := authtypes.StdSignature{PubKey: pkSet[1].Bytes(), Signature: msg}
sigV2, err := authtypes.StdSignatureToSignatureV2(cdc, sig)
require.NoError(t, multisig.AddSignatureV2(multisignature, sigV2, pkSet))
require.NoError(t, err)
require.NotNil(t, sigV2)
require.NoError(t, multisigKey.VerifyMultisignature(signBytesFn, multisignature))
}
func TestAddSignatureFromPubKeyNilCheck(t *testing.T) {
pkSet, sigs := generatePubKeysAndSignatures(5, []byte{1, 2, 3, 4})
multisignature := multisig.NewMultisig(5)
//verify no error is returned with all non-nil values
err := multisig.AddSignatureFromPubKey(multisignature, sigs[0], pkSet[0], pkSet)
require.NoError(t, err)
//verify error is returned when key value is nil
err = multisig.AddSignatureFromPubKey(multisignature, sigs[0], pkSet[0], nil)
require.Error(t, err)
//verify error is returned when pubkey value is nil
err = multisig.AddSignatureFromPubKey(multisignature, sigs[0], nil, pkSet)
require.Error(t, err)
//verify error is returned when signature value is nil
err = multisig.AddSignatureFromPubKey(multisignature, nil, pkSet[0], pkSet)
require.Error(t, err)
//verify error is returned when multisignature value is nil
err = multisig.AddSignatureFromPubKey(nil, sigs[0], pkSet[0], pkSet)
require.Error(t, err)
}
func generatePubKeysAndSignatures(n int, msg []byte) (pubkeys []crypto.PubKey, signatures []signing.SignatureData) {
pubkeys = make([]crypto.PubKey, n)
signatures = make([][]byte, n)
signatures = make([]signing.SignatureData, n)
for i := 0; i < n; i++ {
var privkey crypto.PrivKey
switch rand.Int63() % 3 {
@@ -180,7 +238,32 @@ func generatePubKeysAndSignatures(n int, msg []byte) (pubkeys []crypto.PubKey, s
privkey = sr25519.GenPrivKey()
}
pubkeys[i] = privkey.PubKey()
signatures[i], _ = privkey.Sign(msg)
sig, _ := privkey.Sign(msg)
signatures[i] = &signing.SingleSignatureData{Signature: sig}
}
return
}
func generateNestedMultiSignature(n int, msg []byte) (multisig.PubKey, *signing.MultiSignatureData) {
pubkeys := make([]crypto.PubKey, n)
signatures := make([]signing.SignatureData, n)
bitArray := types.NewCompactBitArray(n)
for i := 0; i < n; i++ {
nestedPks, nestedSigs := generatePubKeysAndSignatures(5, msg)
nestedBitArray := types.NewCompactBitArray(5)
for j := 0; j < 5; j++ {
nestedBitArray.SetIndex(j, true)
}
nestedSig := &signing.MultiSignatureData{
BitArray: nestedBitArray,
Signatures: nestedSigs,
}
signatures[i] = nestedSig
pubkeys[i] = multisig.NewPubKeyMultisigThreshold(5, nestedPks)
bitArray.SetIndex(i, true)
}
return multisig.NewPubKeyMultisigThreshold(n, pubkeys), &signing.MultiSignatureData{
BitArray: bitArray,
Signatures: signatures,
}
}
+57 -47
View File
@@ -168,7 +168,7 @@ func (*PublicKey) XXX_OneofWrappers() []interface{} {
// keys and a threshold
type PubKeyMultisigThreshold struct {
K uint32 `protobuf:"varint,1,opt,name=threshold,proto3" json:"threshold,omitempty" yaml:"threshold"`
PubKeys []*PublicKey `protobuf:"bytes,2,rep,name=pubkeys,proto3" json:"pubkeys,omitempty" yaml:"pubkeys"`
PubKeys []*PublicKey `protobuf:"bytes,2,rep,name=public_keys,json=publicKeys,proto3" json:"public_keys,omitempty" yaml:"pubkeys"`
}
func (m *PubKeyMultisigThreshold) Reset() { *m = PubKeyMultisigThreshold{} }
@@ -222,7 +222,8 @@ func (m *PubKeyMultisigThreshold) GetPubKeys() []*PublicKey {
// See cosmos_sdk.tx.v1.ModeInfo.Multi for how to specify which signers signed
// and with which modes
type MultiSignature struct {
Sigs [][]byte `protobuf:"bytes,1,rep,name=sigs,proto3" json:"sigs,omitempty"`
Signatures [][]byte `protobuf:"bytes,1,rep,name=signatures,proto3" json:"signatures,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *MultiSignature) Reset() { *m = MultiSignature{} }
@@ -258,9 +259,9 @@ func (m *MultiSignature) XXX_DiscardUnknown() {
var xxx_messageInfo_MultiSignature proto.InternalMessageInfo
func (m *MultiSignature) GetSigs() [][]byte {
func (m *MultiSignature) GetSignatures() [][]byte {
if m != nil {
return m.Sigs
return m.Signatures
}
return nil
}
@@ -330,39 +331,40 @@ func init() {
func init() { proto.RegisterFile("crypto/types/types.proto", fileDescriptor_2165b2a1badb1b0c) }
var fileDescriptor_2165b2a1badb1b0c = []byte{
// 501 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x52, 0xcd, 0x6a, 0xdb, 0x40,
0x18, 0x94, 0xec, 0xb8, 0x8e, 0x37, 0x69, 0xdc, 0x2e, 0x86, 0x2a, 0x86, 0x4a, 0x46, 0x94, 0xe2,
0x16, 0x22, 0x61, 0x17, 0xb7, 0x34, 0xb7, 0x28, 0x97, 0x80, 0x29, 0x18, 0xa5, 0x87, 0x52, 0x28,
0x42, 0x3f, 0x5b, 0x79, 0xb1, 0xa4, 0x15, 0xbb, 0xab, 0xd2, 0x7d, 0x89, 0xd2, 0x63, 0x8f, 0xe9,
0xbd, 0x0f, 0xd2, 0x63, 0x8e, 0x3d, 0x99, 0x22, 0xbf, 0x41, 0x9e, 0xa0, 0x44, 0x2b, 0xc5, 0xa1,
0x24, 0x17, 0x69, 0xf7, 0x9b, 0xf9, 0x46, 0x33, 0xdf, 0x27, 0xa0, 0x85, 0x54, 0xe4, 0x9c, 0xd8,
0x5c, 0xe4, 0x88, 0xc9, 0xa7, 0x95, 0x53, 0xc2, 0x09, 0x1c, 0x84, 0x84, 0xa5, 0x84, 0x79, 0x2c,
0x5a, 0x59, 0x92, 0x64, 0x7d, 0x99, 0x0c, 0x9f, 0xf3, 0x25, 0xa6, 0x91, 0x97, 0xfb, 0x94, 0x0b,
0xbb, 0x22, 0xda, 0x31, 0x89, 0xc9, 0xf6, 0x24, 0xbb, 0x87, 0x87, 0x31, 0x21, 0x71, 0x82, 0x24,
0x25, 0x28, 0x3e, 0xdb, 0x7e, 0x26, 0x24, 0x64, 0x7e, 0x6b, 0x81, 0xde, 0xa2, 0x08, 0x12, 0x1c,
0xce, 0x91, 0x80, 0x3a, 0xe8, 0x31, 0x14, 0xe6, 0xd3, 0xd9, 0xeb, 0xd5, 0x44, 0x53, 0x47, 0xea,
0x78, 0xff, 0x4c, 0x71, 0xb7, 0x25, 0x38, 0x04, 0x5d, 0x14, 0x4d, 0x67, 0xb3, 0xc9, 0x5b, 0xad,
0x55, 0xa3, 0x4d, 0xe1, 0x1a, 0x63, 0x54, 0x62, 0xed, 0x06, 0xab, 0x0b, 0x70, 0x0e, 0x76, 0xd3,
0x22, 0xe1, 0x98, 0xe1, 0x58, 0xdb, 0x19, 0xa9, 0xe3, 0xbd, 0xe9, 0x91, 0x75, 0x57, 0x22, 0x6b,
0x51, 0x04, 0x73, 0x24, 0xde, 0xd5, 0xdc, 0xf7, 0x4b, 0x8a, 0xd8, 0x92, 0x24, 0xd1, 0x99, 0xe2,
0xde, 0x08, 0xdc, 0x32, 0x49, 0x27, 0x5a, 0xe7, 0x3f, 0x93, 0x74, 0x02, 0x67, 0x00, 0xf8, 0x99,
0xf0, 0xf2, 0x22, 0x58, 0x21, 0xa1, 0xf5, 0xab, 0xcf, 0x0d, 0x2c, 0x39, 0x02, 0xab, 0x19, 0x81,
0x75, 0x92, 0x89, 0xeb, 0x36, 0x3f, 0x13, 0x8b, 0x8a, 0xe8, 0x74, 0x40, 0x9b, 0x15, 0xa9, 0xf9,
0x4b, 0x05, 0x4f, 0xee, 0x71, 0x01, 0xdf, 0x80, 0x1e, 0x6f, 0x2e, 0xd5, 0x78, 0x1e, 0x3a, 0x87,
0xe5, 0xda, 0x50, 0xe7, 0x57, 0x6b, 0xe3, 0x91, 0xf0, 0xd3, 0xe4, 0xd8, 0xbc, 0xc1, 0x4d, 0x77,
0xcb, 0x85, 0x1f, 0x40, 0x57, 0xda, 0x61, 0x5a, 0x6b, 0xd4, 0x1e, 0xef, 0x4d, 0x8d, 0x7b, 0xe3,
0xcb, 0x4d, 0x38, 0x4f, 0xcb, 0xb5, 0xd1, 0x95, 0x3e, 0xd8, 0xd5, 0xda, 0x38, 0x90, 0xea, 0xb5,
0x88, 0xe9, 0x36, 0x72, 0xe6, 0x33, 0x70, 0x50, 0xf9, 0x3c, 0xc7, 0x71, 0xe6, 0xf3, 0x82, 0x22,
0x08, 0xc1, 0x0e, 0xc3, 0x31, 0xd3, 0xd4, 0x51, 0x7b, 0xbc, 0xef, 0x56, 0x67, 0xf3, 0x13, 0xe8,
0x9f, 0x92, 0x34, 0xf7, 0x43, 0xee, 0x60, 0x7e, 0x42, 0xa9, 0x2f, 0xe0, 0x4b, 0xf0, 0x18, 0x7d,
0xe5, 0xd4, 0xf7, 0x02, 0xcc, 0x99, 0xc7, 0x38, 0xa1, 0xa8, 0xce, 0xe4, 0xf6, 0x2b, 0xc0, 0xc1,
0x9c, 0x9d, 0x57, 0x65, 0x38, 0x00, 0x1d, 0x94, 0xa0, 0x94, 0xc9, 0xa5, 0xbb, 0xf2, 0x72, 0xbc,
0xfb, 0xe3, 0xc2, 0x50, 0x2e, 0x7e, 0x1a, 0x8a, 0x73, 0xfa, 0xbb, 0xd4, 0xd5, 0xcb, 0x52, 0x57,
0xff, 0x96, 0xba, 0xfa, 0x7d, 0xa3, 0x2b, 0x97, 0x1b, 0x5d, 0xf9, 0xb3, 0xd1, 0x95, 0x8f, 0x2f,
0x62, 0xcc, 0x97, 0x45, 0x60, 0x85, 0x24, 0xb5, 0x65, 0xe2, 0xfa, 0x75, 0xc4, 0xa2, 0x95, 0x7d,
0xfb, 0x77, 0x0f, 0x1e, 0x54, 0xab, 0x79, 0xf5, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x1e, 0xd7, 0x43,
0xb2, 0x05, 0x03, 0x00, 0x00,
// 514 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x53, 0xc1, 0x6a, 0xdb, 0x4a,
0x14, 0x95, 0xec, 0xf8, 0x25, 0x1e, 0xe7, 0xc5, 0xed, 0x60, 0xa8, 0x62, 0xa8, 0x64, 0xb4, 0x28,
0x6e, 0x21, 0x12, 0x76, 0x71, 0x4a, 0xbd, 0x8b, 0xb2, 0x09, 0x98, 0x82, 0x51, 0xba, 0x2a, 0x14,
0x21, 0xc9, 0x53, 0x59, 0x58, 0xf2, 0x88, 0xb9, 0xa3, 0xd2, 0xf9, 0x89, 0xd2, 0x65, 0x97, 0xc9,
0x37, 0xf4, 0x27, 0xba, 0xf4, 0xb2, 0x2b, 0x53, 0xec, 0x3f, 0xc8, 0x17, 0x94, 0x68, 0xa4, 0xd8,
0x94, 0x66, 0x23, 0xe9, 0x9e, 0x73, 0x46, 0xf7, 0xdc, 0x73, 0x25, 0xa4, 0x85, 0x4c, 0x64, 0x9c,
0xda, 0x5c, 0x64, 0x04, 0xe4, 0xd5, 0xca, 0x18, 0xe5, 0x14, 0x77, 0x42, 0x0a, 0x29, 0x05, 0x0f,
0x66, 0x0b, 0x4b, 0x8a, 0xac, 0xcf, 0x83, 0xee, 0x0b, 0x3e, 0x8f, 0xd9, 0xcc, 0xcb, 0x7c, 0xc6,
0x85, 0x5d, 0x08, 0xed, 0x88, 0x46, 0x74, 0xf7, 0x24, 0x4f, 0x77, 0x4f, 0x23, 0x4a, 0xa3, 0x84,
0x48, 0x49, 0x90, 0x7f, 0xb2, 0xfd, 0xa5, 0x90, 0x94, 0xf9, 0xb5, 0x86, 0x9a, 0xd3, 0x3c, 0x48,
0xe2, 0x70, 0x42, 0x04, 0xd6, 0x51, 0x13, 0x48, 0x98, 0x0d, 0x47, 0xe7, 0x8b, 0x81, 0xa6, 0xf6,
0xd4, 0xfe, 0xf1, 0x95, 0xe2, 0xee, 0x20, 0xdc, 0x45, 0x87, 0x64, 0x36, 0x1c, 0x8d, 0x06, 0x6f,
0xb5, 0x5a, 0xc9, 0x56, 0xc0, 0x3d, 0x07, 0x4c, 0x72, 0xf5, 0x8a, 0x2b, 0x01, 0x3c, 0x41, 0x47,
0x69, 0x9e, 0xf0, 0x18, 0xe2, 0x48, 0x3b, 0xe8, 0xa9, 0xfd, 0xd6, 0xf0, 0xcc, 0xfa, 0xd7, 0x44,
0xd6, 0x34, 0x0f, 0x26, 0x44, 0xbc, 0x2b, 0xb5, 0xef, 0xe7, 0x8c, 0xc0, 0x9c, 0x26, 0xb3, 0x2b,
0xc5, 0x7d, 0x78, 0xc1, 0x9e, 0x49, 0x36, 0xd0, 0x1a, 0x7f, 0x99, 0x64, 0x03, 0x3c, 0x42, 0xc8,
0x5f, 0x0a, 0x2f, 0xcb, 0x83, 0x05, 0x11, 0x5a, 0xbb, 0x68, 0xd7, 0xb1, 0x64, 0x04, 0x56, 0x15,
0x81, 0x75, 0xb1, 0x14, 0xf7, 0xc7, 0xfc, 0xa5, 0x98, 0x16, 0x42, 0xa7, 0x81, 0xea, 0x90, 0xa7,
0xe6, 0x0f, 0x15, 0x3d, 0x7b, 0xc4, 0x05, 0x7e, 0x83, 0x9a, 0xbc, 0x2a, 0x8a, 0x78, 0xfe, 0x77,
0x4e, 0x37, 0x6b, 0x43, 0x9d, 0xdc, 0xad, 0x8d, 0x27, 0xc2, 0x4f, 0x93, 0xb1, 0xf9, 0xc0, 0x9b,
0xee, 0x4e, 0x8b, 0x3d, 0xd4, 0xca, 0x8a, 0x90, 0xbd, 0x05, 0x11, 0xa0, 0xd5, 0x7a, 0xf5, 0x7e,
0x6b, 0x68, 0x3c, 0x1a, 0x81, 0xdc, 0x86, 0xf3, 0x7c, 0xb3, 0x36, 0x0e, 0xa5, 0x17, 0xb8, 0x5b,
0x1b, 0x27, 0xb2, 0x83, 0x9c, 0x0b, 0x4c, 0x17, 0x65, 0x95, 0x12, 0xcc, 0x73, 0x74, 0x52, 0xd8,
0xbd, 0x8e, 0xa3, 0xa5, 0xcf, 0x73, 0x46, 0xb0, 0x8e, 0x10, 0x54, 0x05, 0x68, 0x6a, 0xaf, 0xde,
0x3f, 0x76, 0xf7, 0x90, 0xf1, 0xc1, 0xea, 0xd6, 0x50, 0xcd, 0x8f, 0xa8, 0x7d, 0x49, 0xd3, 0xcc,
0x0f, 0xb9, 0x13, 0xf3, 0x0b, 0xc6, 0x7c, 0x81, 0x5f, 0xa1, 0xa7, 0xe4, 0x0b, 0x67, 0xbe, 0x17,
0xc4, 0x1c, 0x3c, 0xe0, 0x94, 0x91, 0x72, 0x58, 0xb7, 0x5d, 0x10, 0x4e, 0xcc, 0xe1, 0xba, 0x80,
0x71, 0x07, 0x35, 0x48, 0x42, 0x52, 0x90, 0x5f, 0x83, 0x2b, 0x8b, 0xf1, 0xd1, 0xf7, 0x1b, 0x43,
0xb9, 0xb9, 0x35, 0x14, 0xe7, 0xf2, 0xe7, 0x46, 0x57, 0x57, 0x1b, 0x5d, 0xfd, 0xbd, 0xd1, 0xd5,
0x6f, 0x5b, 0x5d, 0x59, 0x6d, 0x75, 0xe5, 0xd7, 0x56, 0x57, 0x3e, 0xbc, 0x8c, 0x62, 0x3e, 0xcf,
0x03, 0x2b, 0xa4, 0xa9, 0x2d, 0x63, 0x28, 0x6f, 0x67, 0x30, 0x5b, 0xd8, 0xfb, 0xff, 0x41, 0xf0,
0x5f, 0xb1, 0xb3, 0xd7, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0xb8, 0x46, 0x56, 0x25, 0x1e, 0x03,
0x00, 0x00,
}
func (m *PublicKey) Marshal() (dAtA []byte, err error) {
@@ -565,11 +567,15 @@ func (m *MultiSignature) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i
var l int
_ = l
if len(m.Sigs) > 0 {
for iNdEx := len(m.Sigs) - 1; iNdEx >= 0; iNdEx-- {
i -= len(m.Sigs[iNdEx])
copy(dAtA[i:], m.Sigs[iNdEx])
i = encodeVarintTypes(dAtA, i, uint64(len(m.Sigs[iNdEx])))
if m.XXX_unrecognized != nil {
i -= len(m.XXX_unrecognized)
copy(dAtA[i:], m.XXX_unrecognized)
}
if len(m.Signatures) > 0 {
for iNdEx := len(m.Signatures) - 1; iNdEx >= 0; iNdEx-- {
i -= len(m.Signatures[iNdEx])
copy(dAtA[i:], m.Signatures[iNdEx])
i = encodeVarintTypes(dAtA, i, uint64(len(m.Signatures[iNdEx])))
i--
dAtA[i] = 0xa
}
@@ -731,12 +737,15 @@ func (m *MultiSignature) Size() (n int) {
}
var l int
_ = l
if len(m.Sigs) > 0 {
for _, b := range m.Sigs {
if len(m.Signatures) > 0 {
for _, b := range m.Signatures {
l = len(b)
n += 1 + l + sovTypes(uint64(l))
}
}
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
return n
}
@@ -1138,7 +1147,7 @@ func (m *MultiSignature) Unmarshal(dAtA []byte) error {
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Sigs", wireType)
return fmt.Errorf("proto: wrong wireType = %d for field Signatures", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
@@ -1165,8 +1174,8 @@ func (m *MultiSignature) Unmarshal(dAtA []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Sigs = append(m.Sigs, make([]byte, postIndex-iNdEx))
copy(m.Sigs[len(m.Sigs)-1], dAtA[iNdEx:postIndex])
m.Signatures = append(m.Signatures, make([]byte, postIndex-iNdEx))
copy(m.Signatures[len(m.Signatures)-1], dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
@@ -1183,6 +1192,7 @@ func (m *MultiSignature) Unmarshal(dAtA []byte) error {
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
iNdEx += skippy
}
}
+3 -2
View File
@@ -26,14 +26,15 @@ message PublicKey {
// keys and a threshold
message PubKeyMultisigThreshold {
uint32 threshold = 1 [(gogoproto.customname) = "K", (gogoproto.moretags) = "yaml:\"threshold\""];
repeated PublicKey pubkeys = 2 [(gogoproto.customname) = "PubKeys", (gogoproto.moretags) = "yaml:\"pubkeys\""];
repeated PublicKey public_keys = 2 [(gogoproto.customname) = "PubKeys", (gogoproto.moretags) = "yaml:\"pubkeys\""];
}
// MultiSignature wraps the signatures from a PubKeyMultisigThreshold.
// See cosmos_sdk.tx.v1.ModeInfo.Multi for how to specify which signers signed
// and with which modes
message MultiSignature {
repeated bytes sigs = 1;
option (gogoproto.goproto_unrecognized) = true;
repeated bytes signatures = 1;
}
// CompactBitArray is an implementation of a space efficient bit array.