diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d23427aa35..34db9f4a9f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -138,6 +138,7 @@ be used to retrieve the actual proposal `Content`. Also the `NewMsgSubmitProposa * (types) [\#6327](https://github.com/cosmos/cosmos-sdk/pull/6327) `sdk.Msg` now inherits `proto.Message`, as a result all `sdk.Msg` types now use pointer semantics. * (codec) [\#6330](https://github.com/cosmos/cosmos-sdk/pull/6330) `codec.RegisterCrypto` has been moved to the `crypto/codec` package and the global `codec.Cdc` Amino instance has been deprecated and moved to the `codec/legacy_global` package. * (x/ibc) [\#6374](https://github.com/cosmos/cosmos-sdk/pull/6374) `VerifyMembership` and `VerifyNonMembership` now take a `specs []string` argument to specify the proof format used for verification. Most SDK chains can simply use `commitmenttypes.GetSDKSpecs()` for this argument. +* (crypto/types/multisig) [\#6373](https://github.com/cosmos/cosmos-sdk/pull/6373) `multisig.Multisignature` has been renamed to `AminoMultisignature` ### Features diff --git a/crypto/types/multisig/codec.go b/crypto/types/multisig/codec.go index 9fedd111b1c..052b4f85566 100644 --- a/crypto/types/multisig/codec.go +++ b/crypto/types/multisig/codec.go @@ -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) } diff --git a/crypto/types/multisig/multisignature.go b/crypto/types/multisig/multisignature.go index 2e21935f26a..b13072e2804 100644 --- a/crypto/types/multisig/multisignature.go +++ b/crypto/types/multisig/multisignature.go @@ -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) } diff --git a/crypto/types/multisig/pubkey.go b/crypto/types/multisig/pubkey.go new file mode 100644 index 00000000000..a3935a4bb4d --- /dev/null +++ b/crypto/types/multisig/pubkey.go @@ -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) diff --git a/crypto/types/multisig/threshold_pubkey.go b/crypto/types/multisig/threshold_pubkey.go index 13fa11638cc..f27f2001cc9 100644 --- a/crypto/types/multisig/threshold_pubkey.go +++ b/crypto/types/multisig/threshold_pubkey.go @@ -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 } +// 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 +} + +// 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) + return Cdc.MustMarshalBinaryBare(pk) } -// Address returns tmhash(PubKey.Bytes()) +// Address returns tmhash(PubKeyMultisigThreshold.Bytes()) func (pk PubKeyMultisigThreshold) Address() crypto.Address { return crypto.AddressHash(pk.Bytes()) } diff --git a/crypto/types/multisig/threshold_pubkey_test.go b/crypto/types/multisig/threshold_pubkey_test.go index cc4aa780b27..4eaf52ffa11 100644 --- a/crypto/types/multisig/threshold_pubkey_test.go +++ b/crypto/types/multisig/threshold_pubkey_test.go @@ -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, + } +} diff --git a/crypto/types/types.pb.go b/crypto/types/types.pb.go index 6887feafd90..a1f1b83dbf5 100644 --- a/crypto/types/types.pb.go +++ b/crypto/types/types.pb.go @@ -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 } } diff --git a/crypto/types/types.proto b/crypto/types/types.proto index 2496ad8e30d..97a2c67859b 100644 --- a/crypto/types/types.proto +++ b/crypto/types/types.proto @@ -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. diff --git a/types/tx/signing/signature.go b/types/tx/signing/signature.go new file mode 100644 index 00000000000..47744de2843 --- /dev/null +++ b/types/tx/signing/signature.go @@ -0,0 +1,17 @@ +package signing + +import "github.com/tendermint/tendermint/crypto" + +// SignatureV2 is a convenience type that is easier to use in application logic +// than the protobuf SignerInfo's and raw signature bytes. It goes beyond the +// first sdk.Signature types by supporting sign modes and explicitly nested +// multi-signatures. It is intended to be used for both building and verifying +// signatures. +type SignatureV2 struct { + // PubKey is the public key to use for verifying the signature + PubKey crypto.PubKey + + // Data is the actual data of the signature which includes SignMode's and + // the signatures themselves for either single or multi-signatures. + Data SignatureData +} diff --git a/types/tx/signing/signature_data.go b/types/tx/signing/signature_data.go new file mode 100644 index 00000000000..174902ac106 --- /dev/null +++ b/types/tx/signing/signature_data.go @@ -0,0 +1,36 @@ +package signing + +import ( + "github.com/cosmos/cosmos-sdk/crypto/types" +) + +// SignatureData represents either a *SingleSignatureData or *MultiSignatureData. +// It is a convenience type that is easier to use in buiness logic than the encoded +// protobuf ModeInfo's and raw signatures. +type SignatureData interface { + isSignatureData() +} + +// SingleSignatureData represents the signature and SignMode of a single (non-multisig) signer +type SingleSignatureData struct { + // SignMode represents the SignMode of the signature + SignMode SignMode + + // SignMode represents the SignMode of the signature + Signature []byte +} + +// MultiSignatureData represents the nested SignatureData of a multisig signature +type MultiSignatureData struct { + // BitArray is a compact way of indicating which signers from the multisig key + // have signed + BitArray *types.CompactBitArray + + // Signatures is the nested SignatureData's for each signer + Signatures []SignatureData +} + +var _, _ SignatureData = &SingleSignatureData{}, &MultiSignatureData{} + +func (m *SingleSignatureData) isSignatureData() {} +func (m *MultiSignatureData) isSignatureData() {} diff --git a/types/tx/signing/types.pb.go b/types/tx/signing/types.pb.go new file mode 100644 index 00000000000..4207f12ad27 --- /dev/null +++ b/types/tx/signing/types.pb.go @@ -0,0 +1,84 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: types/tx/signing/types.proto + +package signing + +import ( + fmt "fmt" + proto "github.com/gogo/protobuf/proto" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// SignMode represents a signing mode with its own security guarantees +type SignMode int32 + +const ( + // SIGN_MODE_UNSPECIFIED specifies an unknown signing mode and will be rejected + SignMode_SIGN_MODE_UNSPECIFIED SignMode = 0 + // SIGN_MODE_DIRECT specifies a signing mode which uses SignDoc and is verified + // with raw bytes from Tx + SignMode_SIGN_MODE_DIRECT SignMode = 1 + // SIGN_MODE_TEXTUAL is a future signing mode that will verify some human-readable + // textual representation on top of the binary representation from SIGN_MODE_DIRECT + SignMode_SIGN_MODE_TEXTUAL SignMode = 2 + // SIGN_MODE_LEGACY_AMINO_JSON is a backwards compatibility mode which uses + // Amino JSON and will be removed in the future + SignMode_SIGN_MODE_LEGACY_AMINO_JSON SignMode = 127 +) + +var SignMode_name = map[int32]string{ + 0: "SIGN_MODE_UNSPECIFIED", + 1: "SIGN_MODE_DIRECT", + 2: "SIGN_MODE_TEXTUAL", + 127: "SIGN_MODE_LEGACY_AMINO_JSON", +} + +var SignMode_value = map[string]int32{ + "SIGN_MODE_UNSPECIFIED": 0, + "SIGN_MODE_DIRECT": 1, + "SIGN_MODE_TEXTUAL": 2, + "SIGN_MODE_LEGACY_AMINO_JSON": 127, +} + +func (x SignMode) String() string { + return proto.EnumName(SignMode_name, int32(x)) +} + +func (SignMode) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_52d5d5e2efced9ba, []int{0} +} + +func init() { + proto.RegisterEnum("cosmos_sdk.tx.signing.v1.SignMode", SignMode_name, SignMode_value) +} + +func init() { proto.RegisterFile("types/tx/signing/types.proto", fileDescriptor_52d5d5e2efced9ba) } + +var fileDescriptor_52d5d5e2efced9ba = []byte{ + // 222 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x29, 0xa9, 0x2c, 0x48, + 0x2d, 0xd6, 0x2f, 0xa9, 0xd0, 0x2f, 0xce, 0x4c, 0xcf, 0xcb, 0xcc, 0x4b, 0xd7, 0x07, 0x0b, 0xe8, + 0x15, 0x14, 0xe5, 0x97, 0xe4, 0x0b, 0x49, 0x24, 0xe7, 0x17, 0xe7, 0xe6, 0x17, 0xc7, 0x17, 0xa7, + 0x64, 0xeb, 0x95, 0x54, 0xe8, 0x41, 0x95, 0xe8, 0x95, 0x19, 0x6a, 0x15, 0x73, 0x71, 0x04, 0x67, + 0xa6, 0xe7, 0xf9, 0xe6, 0xa7, 0xa4, 0x0a, 0x49, 0x72, 0x89, 0x06, 0x7b, 0xba, 0xfb, 0xc5, 0xfb, + 0xfa, 0xbb, 0xb8, 0xc6, 0x87, 0xfa, 0x05, 0x07, 0xb8, 0x3a, 0x7b, 0xba, 0x79, 0xba, 0xba, 0x08, + 0x30, 0x08, 0x89, 0x70, 0x09, 0x20, 0xa4, 0x5c, 0x3c, 0x83, 0x5c, 0x9d, 0x43, 0x04, 0x18, 0x85, + 0x44, 0xb9, 0x04, 0x11, 0xa2, 0x21, 0xae, 0x11, 0x21, 0xa1, 0x8e, 0x3e, 0x02, 0x4c, 0x42, 0xf2, + 0x5c, 0xd2, 0x08, 0x61, 0x1f, 0x57, 0x77, 0x47, 0xe7, 0xc8, 0x78, 0x47, 0x5f, 0x4f, 0x3f, 0xff, + 0x78, 0xaf, 0x60, 0x7f, 0x3f, 0x81, 0x7a, 0x27, 0xf7, 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, 0xd2, 0x4d, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x87, + 0xb8, 0x19, 0x4a, 0xe9, 0x16, 0xa7, 0x64, 0xeb, 0xa3, 0xfb, 0x31, 0x89, 0x0d, 0xec, 0x3d, 0x63, + 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa0, 0x11, 0xdd, 0x92, 0xfe, 0x00, 0x00, 0x00, +} diff --git a/types/tx/signing/types.proto b/types/tx/signing/types.proto new file mode 100644 index 00000000000..d015f8cc1ef --- /dev/null +++ b/types/tx/signing/types.proto @@ -0,0 +1,22 @@ +syntax = "proto3"; +package cosmos_sdk.tx.signing.v1; + +option go_package = "github.com/cosmos/cosmos-sdk/types/tx/signing"; + +// SignMode represents a signing mode with its own security guarantees +enum SignMode { + // SIGN_MODE_UNSPECIFIED specifies an unknown signing mode and will be rejected + SIGN_MODE_UNSPECIFIED = 0; + + // SIGN_MODE_DIRECT specifies a signing mode which uses SignDoc and is verified + // with raw bytes from Tx + SIGN_MODE_DIRECT = 1; + + // SIGN_MODE_TEXTUAL is a future signing mode that will verify some human-readable + // textual representation on top of the binary representation from SIGN_MODE_DIRECT + SIGN_MODE_TEXTUAL = 2; + + // SIGN_MODE_LEGACY_AMINO_JSON is a backwards compatibility mode which uses + // Amino JSON and will be removed in the future + SIGN_MODE_LEGACY_AMINO_JSON = 127; +} diff --git a/types/tx/types.pb.go b/types/tx/types.pb.go index 16e2ac453b5..770cc361077 100644 --- a/types/tx/types.pb.go +++ b/types/tx/types.pb.go @@ -9,6 +9,7 @@ import ( types1 "github.com/cosmos/cosmos-sdk/crypto/types" github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" types2 "github.com/cosmos/cosmos-sdk/types" + signing "github.com/cosmos/cosmos-sdk/types/tx/signing" _ "github.com/gogo/protobuf/gogoproto" proto "github.com/gogo/protobuf/proto" io "io" @@ -27,45 +28,6 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package -// SignMode represents a signing mode with its own security guarantees -type SignMode int32 - -const ( - // SIGN_MODE_UNSPECIFIED specifies an unknown signing mode and will be rejected - SignMode_SIGN_MODE_UNSPECIFIED SignMode = 0 - // SIGN_MODE_DIRECT specifies a signing mode which uses SignDoc and is verified - // with raw bytes from Tx - SignMode_SIGN_MODE_DIRECT SignMode = 1 - // SIGN_MODE_TEXTUAL is a future signing mode that will verify some human-readable - // textual representation on top of the binary representation from SIGN_MODE_DIRECT - SignMode_SIGN_MODE_TEXTUAL SignMode = 2 - // SIGN_MODE_LEGACY_AMINO_JSON is a backwards compatibility mode which uses - // Amino JSON and will be removed in the future - SignMode_SIGN_MODE_LEGACY_AMINO_JSON SignMode = 127 -) - -var SignMode_name = map[int32]string{ - 0: "SIGN_MODE_UNSPECIFIED", - 1: "SIGN_MODE_DIRECT", - 2: "SIGN_MODE_TEXTUAL", - 127: "SIGN_MODE_LEGACY_AMINO_JSON", -} - -var SignMode_value = map[string]int32{ - "SIGN_MODE_UNSPECIFIED": 0, - "SIGN_MODE_DIRECT": 1, - "SIGN_MODE_TEXTUAL": 2, - "SIGN_MODE_LEGACY_AMINO_JSON": 127, -} - -func (x SignMode) String() string { - return proto.EnumName(SignMode_name, int32(x)) -} - -func (SignMode) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_1c6ac8fa65877134, []int{0} -} - // Tx is the standard type used for broadcasting transactions type Tx struct { // body is the processable content of the transaction @@ -511,7 +473,7 @@ func (*ModeInfo) XXX_OneofWrappers() []interface{} { // to allow for additional fields such as locale for SIGN_MODE_TEXTUAL in the future type ModeInfo_Single struct { // mode is the signing mode of the single signer - Mode SignMode `protobuf:"varint,1,opt,name=mode,proto3,enum=cosmos_sdk.tx.v1.SignMode" json:"mode,omitempty"` + Mode signing.SignMode `protobuf:"varint,1,opt,name=mode,proto3,enum=cosmos_sdk.tx.signing.v1.SignMode" json:"mode,omitempty"` } func (m *ModeInfo_Single) Reset() { *m = ModeInfo_Single{} } @@ -547,11 +509,11 @@ func (m *ModeInfo_Single) XXX_DiscardUnknown() { var xxx_messageInfo_ModeInfo_Single proto.InternalMessageInfo -func (m *ModeInfo_Single) GetMode() SignMode { +func (m *ModeInfo_Single) GetMode() signing.SignMode { if m != nil { return m.Mode } - return SignMode_SIGN_MODE_UNSPECIFIED + return signing.SignMode_SIGN_MODE_UNSPECIFIED } // Multi is the mode info for a multisig public key @@ -669,7 +631,6 @@ func (m *Fee) GetGasLimit() uint64 { } func init() { - proto.RegisterEnum("cosmos_sdk.tx.v1.SignMode", SignMode_name, SignMode_value) proto.RegisterType((*Tx)(nil), "cosmos_sdk.tx.v1.Tx") proto.RegisterType((*SignDoc)(nil), "cosmos_sdk.tx.v1.SignDoc") proto.RegisterType((*TxBody)(nil), "cosmos_sdk.tx.v1.TxBody") @@ -684,60 +645,56 @@ func init() { func init() { proto.RegisterFile("types/tx/types.proto", fileDescriptor_1c6ac8fa65877134) } var fileDescriptor_1c6ac8fa65877134 = []byte{ - // 842 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x55, 0x4d, 0x6f, 0xe3, 0x44, - 0x18, 0x8e, 0x93, 0x34, 0x4d, 0xde, 0xee, 0x47, 0x3a, 0xb4, 0x92, 0x9b, 0xa2, 0x34, 0x44, 0x2a, - 0x04, 0x04, 0xce, 0xb2, 0x7b, 0x60, 0x11, 0x87, 0x55, 0x92, 0xa6, 0xdb, 0x40, 0x9b, 0xa2, 0x49, - 0x56, 0x82, 0x95, 0x90, 0xe5, 0xd8, 0x53, 0x67, 0xd4, 0x78, 0x26, 0x78, 0xc6, 0x28, 0xe1, 0x82, - 0x38, 0x70, 0xe2, 0xc2, 0x85, 0x3f, 0xc1, 0x2f, 0x59, 0x71, 0xda, 0x23, 0x17, 0x3e, 0xd4, 0xfe, - 0x10, 0x90, 0xc7, 0xe3, 0xa4, 0x6a, 0x4a, 0xb8, 0x71, 0xca, 0xeb, 0xc7, 0xcf, 0xf3, 0xcc, 0xfb, - 0x95, 0x31, 0xec, 0xc8, 0xf9, 0x94, 0x88, 0xa6, 0x9c, 0x35, 0x55, 0x60, 0x4d, 0x43, 0x2e, 0x39, - 0x2a, 0xbb, 0x5c, 0x04, 0x5c, 0xd8, 0xc2, 0xbb, 0xb4, 0xe4, 0xcc, 0xfa, 0xe6, 0xc3, 0xca, 0xdb, - 0x72, 0x4c, 0x43, 0xcf, 0x9e, 0x3a, 0xa1, 0x9c, 0x37, 0x15, 0xa9, 0xe9, 0x73, 0x9f, 0x2f, 0xa3, - 0x44, 0x59, 0x31, 0xdd, 0x70, 0x3e, 0x95, 0xbc, 0xa9, 0x6d, 0x97, 0x9e, 0x95, 0xed, 0x55, 0x68, - 0xcf, 0xe7, 0xdc, 0x9f, 0x90, 0xc4, 0x6f, 0x14, 0x5d, 0x34, 0x1d, 0x36, 0x4f, 0x5e, 0xd5, 0x7f, - 0x34, 0x20, 0x3b, 0x9c, 0xa1, 0xf7, 0x21, 0x3f, 0xe2, 0xde, 0xdc, 0x34, 0x6a, 0x46, 0x63, 0xeb, - 0xb1, 0x69, 0xdd, 0xce, 0xcb, 0x1a, 0xce, 0xda, 0xdc, 0x9b, 0x63, 0xc5, 0x42, 0x1f, 0x41, 0xc9, - 0x89, 0xe4, 0xd8, 0xa6, 0xec, 0x82, 0x9b, 0x59, 0x25, 0xa9, 0xac, 0x4a, 0x5a, 0x91, 0x1c, 0xf7, - 0xd8, 0x05, 0xc7, 0x45, 0x47, 0x47, 0xa8, 0x0a, 0x20, 0xa8, 0xcf, 0x1c, 0x19, 0x85, 0x44, 0x98, - 0xb9, 0x5a, 0xae, 0x71, 0x0f, 0xdf, 0x40, 0xea, 0xbf, 0x1b, 0xb0, 0x39, 0xa0, 0x3e, 0x3b, 0xe2, - 0xee, 0xff, 0x95, 0xd2, 0x1e, 0x14, 0xdd, 0xb1, 0x43, 0x99, 0x4d, 0x3d, 0x33, 0x57, 0x33, 0x1a, - 0x25, 0xbc, 0xa9, 0x9e, 0x7b, 0x1e, 0x3a, 0x84, 0x07, 0x8e, 0xeb, 0xf2, 0x88, 0x49, 0x9b, 0x45, - 0xc1, 0x88, 0x84, 0x66, 0xbe, 0x66, 0x34, 0xf2, 0xf8, 0xbe, 0x46, 0xfb, 0x0a, 0x44, 0xef, 0x42, - 0x39, 0xa5, 0x09, 0xf2, 0x75, 0x44, 0x98, 0x4b, 0xcc, 0x0d, 0x45, 0x7c, 0xa8, 0xf1, 0x81, 0x86, - 0xeb, 0x3f, 0x67, 0xa1, 0x90, 0xa4, 0x8d, 0x1e, 0x41, 0x31, 0x20, 0x42, 0x38, 0x3e, 0x11, 0xa6, - 0x51, 0xcb, 0x35, 0xb6, 0x1e, 0xef, 0x58, 0xc9, 0x98, 0xac, 0x74, 0x4c, 0x56, 0x8b, 0xcd, 0xf1, - 0x82, 0x85, 0x10, 0xe4, 0x03, 0x12, 0x24, 0xd5, 0x95, 0xb0, 0x8a, 0xe3, 0x14, 0x25, 0x0d, 0x08, - 0x8f, 0xa4, 0x3d, 0x26, 0xd4, 0x1f, 0x4b, 0x55, 0x43, 0x0e, 0xdf, 0xd7, 0xe8, 0x89, 0x02, 0x51, - 0x1b, 0xb6, 0xc9, 0x4c, 0x12, 0x26, 0x28, 0x67, 0x36, 0x9f, 0x4a, 0xca, 0x99, 0x30, 0xff, 0xde, - 0x5c, 0x73, 0x6c, 0x79, 0xc1, 0x3f, 0x4f, 0xe8, 0xe8, 0x25, 0x54, 0x19, 0x67, 0xb6, 0x1b, 0x52, - 0x49, 0x5d, 0x67, 0x62, 0xdf, 0x61, 0xf8, 0x70, 0x8d, 0xe1, 0x3e, 0xe3, 0xac, 0xa3, 0xb5, 0xdd, - 0x5b, 0xde, 0x75, 0x09, 0xc5, 0x74, 0x34, 0xe8, 0x19, 0xdc, 0x8b, 0x37, 0x82, 0x84, 0x6a, 0x96, - 0x69, 0x73, 0xde, 0x5c, 0x1d, 0xe6, 0x40, 0xb1, 0xd4, 0x38, 0xb7, 0xc4, 0x22, 0x16, 0xe8, 0x1d, - 0xc8, 0x5d, 0x10, 0xa2, 0x97, 0x60, 0x77, 0x55, 0x77, 0x4c, 0x08, 0x8e, 0x19, 0xf5, 0x6f, 0x01, - 0x96, 0x1e, 0xe8, 0x09, 0xc0, 0x34, 0x1a, 0x4d, 0xa8, 0x6b, 0x5f, 0x92, 0x74, 0xeb, 0xee, 0x2e, - 0xa5, 0x94, 0xf0, 0x3e, 0x23, 0x6a, 0xed, 0x02, 0xee, 0x91, 0xff, 0x58, 0xbb, 0x33, 0xee, 0x91, - 0x64, 0xed, 0x02, 0x1d, 0xd5, 0x7f, 0xcd, 0x42, 0x31, 0x85, 0xd1, 0x27, 0x50, 0x10, 0x94, 0xf9, - 0x13, 0xa2, 0x8f, 0x7d, 0xeb, 0xdf, 0x2d, 0xac, 0x81, 0x22, 0x9e, 0x64, 0xb0, 0x96, 0xa0, 0xa7, - 0xb0, 0x11, 0x44, 0x13, 0x49, 0xf5, 0xf1, 0xb5, 0x35, 0xda, 0xb3, 0x98, 0x77, 0x92, 0xc1, 0x89, - 0xa0, 0xf2, 0x14, 0x0a, 0x89, 0x1b, 0xb2, 0x20, 0x1f, 0x67, 0xa6, 0x8e, 0x7f, 0x70, 0x57, 0x05, - 0x71, 0x9f, 0x62, 0x1b, 0xac, 0x78, 0x95, 0x1f, 0x0c, 0xd8, 0x50, 0x66, 0xa8, 0x05, 0xc5, 0x11, - 0x95, 0x4e, 0x18, 0x3a, 0x69, 0xcf, 0x0e, 0x6f, 0xaa, 0x93, 0x5b, 0x2a, 0x76, 0xe8, 0xf0, 0x60, - 0xea, 0xb8, 0xb2, 0x4d, 0x65, 0x2b, 0x26, 0xe3, 0x85, 0x0c, 0x7d, 0x0c, 0xb0, 0xe8, 0xa1, 0x30, - 0xb3, 0x6a, 0xdc, 0xeb, 0x9a, 0x58, 0x4a, 0x9b, 0x28, 0xda, 0x1b, 0x90, 0x13, 0x51, 0x50, 0xff, - 0xde, 0x80, 0xdc, 0x31, 0x21, 0xe8, 0x2b, 0x28, 0x38, 0x41, 0xfc, 0x87, 0xd3, 0x4b, 0xf3, 0xc6, - 0x4d, 0x17, 0x95, 0x03, 0x65, 0xed, 0x47, 0xaf, 0xfe, 0x38, 0xc8, 0xfc, 0xf2, 0xe7, 0x41, 0xc3, - 0xa7, 0x72, 0x1c, 0x8d, 0x2c, 0x97, 0x07, 0xcd, 0x84, 0xa6, 0x7f, 0x3e, 0x10, 0xde, 0xa5, 0xbe, - 0x3e, 0x63, 0x81, 0xc0, 0xda, 0x14, 0xed, 0x43, 0xc9, 0x77, 0x84, 0x3d, 0xa1, 0x01, 0x95, 0xaa, - 0xdb, 0x79, 0x5c, 0xf4, 0x1d, 0x71, 0x1a, 0x3f, 0xbf, 0x27, 0xa0, 0x98, 0x36, 0x09, 0xed, 0xc1, - 0xee, 0xa0, 0xf7, 0xbc, 0x6f, 0x9f, 0x9d, 0x1f, 0x75, 0xed, 0x17, 0xfd, 0xc1, 0xe7, 0xdd, 0x4e, - 0xef, 0xb8, 0xd7, 0x3d, 0x2a, 0x67, 0xd0, 0x0e, 0x94, 0x97, 0xaf, 0x8e, 0x7a, 0xb8, 0xdb, 0x19, - 0x96, 0x0d, 0xb4, 0x0b, 0xdb, 0x4b, 0x74, 0xd8, 0xfd, 0x62, 0xf8, 0xa2, 0x75, 0x5a, 0xce, 0xa2, - 0x03, 0xd8, 0x5f, 0xc2, 0xa7, 0xdd, 0xe7, 0xad, 0xce, 0x97, 0x76, 0xeb, 0xac, 0xd7, 0x3f, 0xb7, - 0x3f, 0x1d, 0x9c, 0xf7, 0xcb, 0xdf, 0xb5, 0x9f, 0xbd, 0xba, 0xaa, 0x1a, 0xaf, 0xaf, 0xaa, 0xc6, - 0x5f, 0x57, 0x55, 0xe3, 0xa7, 0xeb, 0x6a, 0xe6, 0xf5, 0x75, 0x35, 0xf3, 0xdb, 0x75, 0x35, 0xf3, - 0xf2, 0x70, 0x7d, 0x75, 0xfa, 0x33, 0x34, 0x2a, 0xa8, 0xc5, 0x7e, 0xf2, 0x4f, 0x00, 0x00, 0x00, - 0xff, 0xff, 0x28, 0x03, 0x76, 0x89, 0x9f, 0x06, 0x00, 0x00, + // 774 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x55, 0x3d, 0x6f, 0xe3, 0x46, + 0x10, 0x15, 0x45, 0x49, 0x96, 0xc6, 0xdf, 0x1b, 0x07, 0xa0, 0x65, 0x83, 0x56, 0x08, 0x38, 0x51, + 0x80, 0x84, 0x72, 0x6c, 0x20, 0x1f, 0x48, 0xe1, 0x48, 0x4e, 0x0c, 0x1b, 0x89, 0x13, 0x80, 0x72, + 0x65, 0x20, 0x20, 0x28, 0x72, 0x45, 0x2d, 0x2c, 0xee, 0x2a, 0xdc, 0x65, 0x20, 0xa5, 0x4b, 0x91, + 0x2a, 0x4d, 0x9a, 0xfc, 0x89, 0xfb, 0x25, 0x2e, 0x8d, 0xab, 0xae, 0xb9, 0x0f, 0xd8, 0x3f, 0xe4, + 0x0e, 0x5c, 0x2e, 0x65, 0x9f, 0xe5, 0xd3, 0x75, 0x57, 0x69, 0xf8, 0xf8, 0xde, 0x9b, 0xd9, 0x99, + 0xd1, 0x12, 0x36, 0xc4, 0x64, 0x84, 0x79, 0x4b, 0x8c, 0x5b, 0x32, 0xb0, 0x47, 0x31, 0x13, 0x0c, + 0xad, 0xf9, 0x8c, 0x47, 0x8c, 0xbb, 0x3c, 0xb8, 0xb4, 0xc5, 0xd8, 0xfe, 0xf3, 0xab, 0xfa, 0xa7, + 0x62, 0x40, 0xe2, 0xc0, 0x1d, 0x79, 0xb1, 0x98, 0xb4, 0x24, 0xa9, 0x15, 0xb2, 0x90, 0xdd, 0x45, + 0x99, 0xb2, 0x6e, 0xf8, 0xf1, 0x64, 0x24, 0x58, 0x4b, 0xd9, 0xde, 0x79, 0xd6, 0xd7, 0x67, 0xa1, + 0xed, 0x69, 0x72, 0x4e, 0x42, 0x4a, 0x68, 0xf8, 0xd6, 0xdb, 0xcd, 0x90, 0xb1, 0x70, 0x88, 0xb3, + 0x6c, 0xbd, 0xa4, 0xdf, 0xf2, 0xe8, 0x24, 0x7b, 0x65, 0xfd, 0xab, 0x41, 0xf1, 0x7c, 0x8c, 0xbe, + 0x80, 0x52, 0x8f, 0x05, 0x13, 0x43, 0x6b, 0x68, 0xcd, 0xc5, 0x7d, 0xc3, 0x7e, 0x58, 0xb5, 0x7d, + 0x3e, 0xee, 0xb0, 0x60, 0xe2, 0x48, 0x16, 0xfa, 0x06, 0x6a, 0x5e, 0x22, 0x06, 0x2e, 0xa1, 0x7d, + 0x66, 0x14, 0xa5, 0xa4, 0x3e, 0x2b, 0x69, 0x27, 0x62, 0x70, 0x4a, 0xfb, 0xcc, 0xa9, 0x7a, 0x2a, + 0x42, 0x26, 0x40, 0x5a, 0x9f, 0x27, 0x92, 0x18, 0x73, 0x43, 0x6f, 0xe8, 0xcd, 0x25, 0xe7, 0x1e, + 0x62, 0x3d, 0xd7, 0x60, 0xa1, 0x4b, 0x42, 0xfa, 0x23, 0xf3, 0x3f, 0x54, 0x49, 0x9b, 0x50, 0xf5, + 0x07, 0x1e, 0xa1, 0x2e, 0x09, 0x0c, 0xbd, 0xa1, 0x35, 0x6b, 0xce, 0x82, 0x7c, 0x3e, 0x0d, 0xd0, + 0x2e, 0xac, 0x78, 0xbe, 0xcf, 0x12, 0x2a, 0x5c, 0x9a, 0x44, 0x3d, 0x1c, 0x1b, 0xa5, 0x86, 0xd6, + 0x2c, 0x39, 0xcb, 0x0a, 0xfd, 0x55, 0x82, 0xe8, 0x73, 0x58, 0xcb, 0x69, 0x1c, 0xff, 0x91, 0x60, + 0xea, 0x63, 0xa3, 0x2c, 0x89, 0xab, 0x0a, 0xef, 0x2a, 0xd8, 0xfa, 0xbf, 0x08, 0x95, 0xac, 0x6c, + 0xb4, 0x07, 0xd5, 0x08, 0x73, 0xee, 0x85, 0x98, 0x1b, 0x5a, 0x43, 0x6f, 0x2e, 0xee, 0x6f, 0xd8, + 0xd9, 0x98, 0xec, 0x7c, 0x4c, 0x76, 0x9b, 0x4e, 0x9c, 0x29, 0x0b, 0x21, 0x28, 0x45, 0x38, 0xca, + 0x4e, 0x57, 0x73, 0x64, 0x9c, 0x96, 0x28, 0x48, 0x84, 0x59, 0x22, 0xdc, 0x01, 0x26, 0xe1, 0x40, + 0xc8, 0x33, 0xe8, 0xce, 0xb2, 0x42, 0x4f, 0x24, 0x88, 0x3a, 0xb0, 0x8e, 0xc7, 0x02, 0x53, 0x4e, + 0x18, 0x75, 0xd9, 0x48, 0x10, 0x46, 0xb9, 0xf1, 0x7a, 0x61, 0x4e, 0xda, 0xb5, 0x29, 0xff, 0xb7, + 0x8c, 0x8e, 0x2e, 0xc0, 0xa4, 0x8c, 0xba, 0x7e, 0x4c, 0x04, 0xf1, 0xbd, 0xa1, 0xfb, 0x88, 0xe1, + 0xea, 0x1c, 0xc3, 0x2d, 0xca, 0xe8, 0x91, 0xd2, 0xfe, 0xf4, 0xc0, 0xdb, 0x12, 0x50, 0xcd, 0x47, + 0x83, 0x0e, 0x61, 0x29, 0xdd, 0x08, 0x1c, 0xcb, 0x59, 0xe6, 0xcd, 0xd9, 0x9e, 0x1d, 0x66, 0x57, + 0xb2, 0xe4, 0x38, 0x17, 0xf9, 0x34, 0xe6, 0xe8, 0x33, 0xd0, 0xfb, 0x18, 0xab, 0x25, 0xf8, 0x78, + 0x56, 0x77, 0x8c, 0xb1, 0x93, 0x32, 0xac, 0xbf, 0x00, 0xee, 0x3c, 0xd0, 0x01, 0xc0, 0x28, 0xe9, + 0x0d, 0x89, 0xef, 0x5e, 0xe2, 0x7c, 0xeb, 0x1e, 0x3f, 0x4a, 0x2d, 0xe3, 0xfd, 0x8c, 0xe5, 0xda, + 0x45, 0x2c, 0xc0, 0xef, 0x59, 0xbb, 0x33, 0x16, 0xe0, 0x6c, 0xed, 0x22, 0x15, 0x59, 0x4f, 0x8b, + 0x50, 0xcd, 0x61, 0xf4, 0x3d, 0x54, 0x38, 0xa1, 0xe1, 0x10, 0xab, 0xb4, 0x9f, 0xbc, 0xdb, 0xc2, + 0xee, 0x4a, 0xe2, 0x49, 0xc1, 0x51, 0x12, 0xf4, 0x2d, 0x94, 0xa3, 0x64, 0x28, 0x88, 0x4a, 0xdf, + 0x98, 0xa3, 0x3d, 0x4b, 0x79, 0x27, 0x05, 0x27, 0x13, 0xd4, 0x7f, 0x80, 0x4a, 0xe6, 0x86, 0xbe, + 0x86, 0x52, 0x5a, 0x99, 0x4c, 0xbf, 0xb2, 0x6f, 0x3d, 0xb0, 0x50, 0x57, 0x4a, 0xde, 0xf3, 0xd4, + 0xce, 0x91, 0xfc, 0xfa, 0x3f, 0x1a, 0x94, 0xa5, 0x29, 0x6a, 0x43, 0xb5, 0x47, 0x84, 0x17, 0xc7, + 0x5e, 0xde, 0xbb, 0xdd, 0xfb, 0x2e, 0xd9, 0x5d, 0x96, 0x3a, 0x1c, 0xb1, 0x68, 0xe4, 0xf9, 0xa2, + 0x43, 0x44, 0x3b, 0x25, 0x3b, 0x53, 0x19, 0xfa, 0x0e, 0x60, 0xda, 0x4b, 0x6e, 0x14, 0xe5, 0xd8, + 0xe7, 0x35, 0xb3, 0x96, 0x37, 0x93, 0x77, 0xca, 0xa0, 0xf3, 0x24, 0xb2, 0xfe, 0xd6, 0x40, 0x3f, + 0xc6, 0x18, 0xfd, 0x0e, 0x15, 0x2f, 0x4a, 0xff, 0x78, 0x6a, 0x79, 0x3e, 0xba, 0xef, 0x22, 0x6b, + 0x20, 0xb4, 0xb3, 0x77, 0xf5, 0x62, 0xa7, 0xf0, 0xe4, 0xe5, 0x4e, 0x33, 0x24, 0x62, 0x90, 0xf4, + 0x6c, 0x9f, 0x45, 0xad, 0x8c, 0xa6, 0x7e, 0xbe, 0xe4, 0xc1, 0xa5, 0xba, 0x46, 0x53, 0x01, 0x77, + 0x94, 0x29, 0xda, 0x82, 0x5a, 0xe8, 0x71, 0x77, 0x48, 0x22, 0x22, 0x64, 0xd7, 0x4b, 0x4e, 0x35, + 0xf4, 0xf8, 0x2f, 0xe9, 0x73, 0xe7, 0xf0, 0xea, 0xc6, 0xd4, 0xae, 0x6f, 0x4c, 0xed, 0xd5, 0x8d, + 0xa9, 0xfd, 0x77, 0x6b, 0x16, 0xae, 0x6f, 0xcd, 0xc2, 0xb3, 0x5b, 0xb3, 0x70, 0xb1, 0x3b, 0x3f, + 0x91, 0xfa, 0x6e, 0xf4, 0x2a, 0x72, 0xd7, 0x0e, 0xde, 0x04, 0x00, 0x00, 0xff, 0xff, 0x03, 0x5c, + 0xe0, 0x71, 0x50, 0x06, 0x00, 0x00, } func (m *Tx) Marshal() (dAtA []byte, err error) { @@ -2424,7 +2381,7 @@ func (m *ModeInfo_Single) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.Mode |= SignMode(b&0x7F) << shift + m.Mode |= signing.SignMode(b&0x7F) << shift if b < 0x80 { break } diff --git a/types/tx/types.proto b/types/tx/types.proto index 51ec4da8439..9aa2f64a8a1 100644 --- a/types/tx/types.proto +++ b/types/tx/types.proto @@ -4,6 +4,7 @@ package cosmos_sdk.tx.v1; import "third_party/proto/gogoproto/gogo.proto"; import "crypto/types/types.proto"; import "types/types.proto"; +import "types/tx/signing/types.proto"; import "google/protobuf/any.proto"; option go_package = "github.com/cosmos/cosmos-sdk/tx/types"; @@ -104,7 +105,7 @@ message ModeInfo { // to allow for additional fields such as locale for SIGN_MODE_TEXTUAL in the future message Single { // mode is the signing mode of the single signer - SignMode mode = 1; + cosmos_sdk.tx.signing.v1.SignMode mode = 1; } // Multi is the mode info for a multisig public key @@ -118,24 +119,6 @@ message ModeInfo { } } -// SignMode represents a signing mode with its own security guarantees -enum SignMode { - // SIGN_MODE_UNSPECIFIED specifies an unknown signing mode and will be rejected - SIGN_MODE_UNSPECIFIED = 0; - - // SIGN_MODE_DIRECT specifies a signing mode which uses SignDoc and is verified - // with raw bytes from Tx - SIGN_MODE_DIRECT = 1; - - // SIGN_MODE_TEXTUAL is a future signing mode that will verify some human-readable - // textual representation on top of the binary representation from SIGN_MODE_DIRECT - SIGN_MODE_TEXTUAL = 2; - - // SIGN_MODE_LEGACY_AMINO_JSON is a backwards compatibility mode which uses - // Amino JSON and will be removed in the future - SIGN_MODE_LEGACY_AMINO_JSON = 127; -} - // Fee includes the amount of coins paid in fees and the maximum // gas to be used by the transaction. The ratio yields an effective "gasprice", // which must be above some miminum to be accepted into the mempool. diff --git a/x/auth/ante/sigverify.go b/x/auth/ante/sigverify.go index 762d53f8c7c..29a561479fe 100644 --- a/x/auth/ante/sigverify.go +++ b/x/auth/ante/sigverify.go @@ -306,7 +306,7 @@ func DefaultSigVerificationGasConsumer( return nil case multisig.PubKeyMultisigThreshold: - var multisignature multisig.Multisignature + var multisignature multisig.AminoMultisignature legacy.Cdc.MustUnmarshalBinaryBare(sig, &multisignature) ConsumeMultisignatureVerificationGas(meter, multisignature, pubkey, params) @@ -319,7 +319,7 @@ func DefaultSigVerificationGasConsumer( // ConsumeMultisignatureVerificationGas consumes gas from a GasMeter for verifying a multisig pubkey signature func ConsumeMultisignatureVerificationGas( - meter sdk.GasMeter, sig multisig.Multisignature, pubkey multisig.PubKeyMultisigThreshold, params types.Params, + meter sdk.GasMeter, sig multisig.AminoMultisignature, pubkey multisig.PubKeyMultisigThreshold, params types.Params, ) { size := sig.BitArray.Size() diff --git a/x/auth/ante/sigverify_test.go b/x/auth/ante/sigverify_test.go index 0c69dba9d3d..33781020af0 100644 --- a/x/auth/ante/sigverify_test.go +++ b/x/auth/ante/sigverify_test.go @@ -4,6 +4,8 @@ import ( "fmt" "testing" + "github.com/cosmos/cosmos-sdk/simapp" + "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" @@ -58,15 +60,21 @@ func TestSetPubKey(t *testing.T) { func TestConsumeSignatureVerificationGas(t *testing.T) { params := types.DefaultParams() msg := []byte{1, 2, 3, 4} + _, cdc := simapp.MakeCodecs() pkSet1, sigSet1 := generatePubKeysAndSignatures(5, msg, false) multisigKey1 := multisig.NewPubKeyMultisigThreshold(2, pkSet1) multisignature1 := multisig.NewMultisig(len(pkSet1)) expectedCost1 := expectedGasCostByKeys(pkSet1) for i := 0; i < len(pkSet1); i++ { - err := multisignature1.AddSignatureFromPubKey(sigSet1[i], pkSet1[i], pkSet1) + stdSig := types.StdSignature{PubKey: pkSet1[i].Bytes(), Signature: sigSet1[i]} + sigV2, err := types.StdSignatureToSignatureV2(cdc, stdSig) + require.NoError(t, err) + err = multisig.AddSignatureV2(multisignature1, sigV2, pkSet1) require.NoError(t, err) } + aminoMultisignature1, err := types.SignatureDataToAminoSignature(cdc, multisignature1) + require.NoError(t, err) type args struct { meter sdk.GasMeter @@ -82,7 +90,7 @@ func TestConsumeSignatureVerificationGas(t *testing.T) { }{ {"PubKeyEd25519", args{sdk.NewInfiniteGasMeter(), nil, ed25519.GenPrivKey().PubKey(), params}, types.DefaultSigVerifyCostED25519, true}, {"PubKeySecp256k1", args{sdk.NewInfiniteGasMeter(), nil, secp256k1.GenPrivKey().PubKey(), params}, types.DefaultSigVerifyCostSecp256k1, false}, - {"Multisig", args{sdk.NewInfiniteGasMeter(), multisignature1.Marshal(), multisigKey1, params}, expectedCost1, false}, + {"Multisig", args{sdk.NewInfiniteGasMeter(), aminoMultisignature1, multisigKey1, params}, expectedCost1, false}, {"unknown key", args{sdk.NewInfiniteGasMeter(), nil, nil, params}, 0, true}, } for _, tt := range tests { diff --git a/x/auth/client/cli/tx_multisign.go b/x/auth/client/cli/tx_multisign.go index 58002e4a124..c0af04548fb 100644 --- a/x/auth/client/cli/tx_multisign.go +++ b/x/auth/client/cli/tx_multisign.go @@ -107,13 +107,24 @@ func makeMultiSignCmd(cdc *codec.Codec) func(cmd *cobra.Command, args []string) if ok := stdSig.GetPubKey().VerifyBytes(sigBytes, stdSig.Signature); !ok { return fmt.Errorf("couldn't verify signature") } - if err := multisigSig.AddSignatureFromPubKey(stdSig.Signature, stdSig.GetPubKey(), multisigPub.PubKeys); err != nil { + + sigV2, err := types.StdSignatureToSignatureV2(cdc, stdSig) + if err != nil { + return nil + } + + if err := multisig.AddSignatureV2(multisigSig, sigV2, multisigPub.PubKeys); err != nil { return err } } - newStdSig := types.StdSignature{Signature: cdc.MustMarshalBinaryBare(multisigSig), PubKey: multisigPub.Bytes()} //nolint:staticcheck - newTx := types.NewStdTx(stdTx.GetMsgs(), stdTx.Fee, []types.StdSignature{newStdSig}, stdTx.GetMemo()) //nolint:staticcheck + sigBz, err := types.SignatureDataToAminoSignature(cdc, multisigSig) + if err != nil { + return err + } + + newStdSig := types.StdSignature{Signature: sigBz, PubKey: multisigPub.Bytes()} //nolint:staticcheck + newTx := types.NewStdTx(stdTx.GetMsgs(), stdTx.Fee, []types.StdSignature{newStdSig}, stdTx.GetMemo()) //nolint:staticcheck sigOnly := viper.GetBool(flagSigOnly) var json []byte diff --git a/x/auth/client/cli/validate_sigs.go b/x/auth/client/cli/validate_sigs.go index 7782021a78b..630085da129 100644 --- a/x/auth/client/cli/validate_sigs.go +++ b/x/auth/client/cli/validate_sigs.go @@ -108,7 +108,7 @@ func printAndValidateSigs( multiPK, ok := sig.GetPubKey().(multisig.PubKeyMultisigThreshold) if ok { - var multiSig multisig.Multisignature + var multiSig multisig.AminoMultisignature clientCtx.Codec.MustUnmarshalBinaryBare(sig.Signature, &multiSig) var b strings.Builder diff --git a/x/auth/signing/amino/amino.go b/x/auth/signing/amino/amino.go index 5788fca7549..f9efc3d91ae 100644 --- a/x/auth/signing/amino/amino.go +++ b/x/auth/signing/amino/amino.go @@ -4,7 +4,7 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" - types "github.com/cosmos/cosmos-sdk/types/tx" + signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" "github.com/cosmos/cosmos-sdk/x/auth/ante" "github.com/cosmos/cosmos-sdk/x/auth/signing" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -16,19 +16,19 @@ type LegacyAminoJSONHandler struct{} var _ signing.SignModeHandler = LegacyAminoJSONHandler{} // DefaultMode implements SignModeHandler.DefaultMode -func (h LegacyAminoJSONHandler) DefaultMode() types.SignMode { - return types.SignMode_SIGN_MODE_LEGACY_AMINO_JSON +func (h LegacyAminoJSONHandler) DefaultMode() signingtypes.SignMode { + return signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON } // Modes implements SignModeHandler.Modes -func (LegacyAminoJSONHandler) Modes() []types.SignMode { - return []types.SignMode{types.SignMode_SIGN_MODE_LEGACY_AMINO_JSON} +func (LegacyAminoJSONHandler) Modes() []signingtypes.SignMode { + return []signingtypes.SignMode{signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON} } // DefaultMode implements SignModeHandler.GetSignBytes -func (LegacyAminoJSONHandler) GetSignBytes(mode types.SignMode, data signing.SignerData, tx sdk.Tx) ([]byte, error) { - if mode != types.SignMode_SIGN_MODE_LEGACY_AMINO_JSON { - return nil, fmt.Errorf("expected %s, got %s", types.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, mode) +func (LegacyAminoJSONHandler) GetSignBytes(mode signingtypes.SignMode, data signing.SignerData, tx sdk.Tx) ([]byte, error) { + if mode != signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON { + return nil, fmt.Errorf("expected %s, got %s", signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, mode) } feeTx, ok := tx.(ante.FeeTx) diff --git a/x/auth/signing/amino/amino_test.go b/x/auth/signing/amino/amino_test.go index b72eaaffb57..3e073ae881a 100644 --- a/x/auth/signing/amino/amino_test.go +++ b/x/auth/signing/amino/amino_test.go @@ -8,7 +8,7 @@ import ( "github.com/tendermint/tendermint/crypto/secp256k1" sdk "github.com/cosmos/cosmos-sdk/types" - txtypes "github.com/cosmos/cosmos-sdk/types/tx" + signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/auth/signing" "github.com/cosmos/cosmos-sdk/x/auth/signing/amino" @@ -55,7 +55,7 @@ func TestLegacyAminoJSONHandler_GetSignBytes(t *testing.T) { AccountNumber: accNum, AccountSequence: seqNum, } - signBz, err := handler.GetSignBytes(txtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, signingData, tx) + signBz, err := handler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, signingData, tx) require.NoError(t, err) expectedSignBz := auth.StdSignBytes(chainId, accNum, seqNum, fee, msgs, memo) @@ -63,16 +63,16 @@ func TestLegacyAminoJSONHandler_GetSignBytes(t *testing.T) { require.Equal(t, expectedSignBz, signBz) // expect error with wrong sign mode - _, err = handler.GetSignBytes(txtypes.SignMode_SIGN_MODE_DIRECT, signingData, tx) + _, err = handler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_DIRECT, signingData, tx) require.Error(t, err) } func TestLegacyAminoJSONHandler_DefaultMode(t *testing.T) { handler := amino.LegacyAminoJSONHandler{} - require.Equal(t, txtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, handler.DefaultMode()) + require.Equal(t, signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, handler.DefaultMode()) } func TestLegacyAminoJSONHandler_Modes(t *testing.T) { handler := amino.LegacyAminoJSONHandler{} - require.Equal(t, []txtypes.SignMode{txtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON}, handler.Modes()) + require.Equal(t, []signingtypes.SignMode{signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON}, handler.Modes()) } diff --git a/x/auth/signing/handler_map.go b/x/auth/signing/handler_map.go index 90421db9430..936de47da5d 100644 --- a/x/auth/signing/handler_map.go +++ b/x/auth/signing/handler_map.go @@ -3,24 +3,25 @@ package signing import ( "fmt" + "github.com/cosmos/cosmos-sdk/types/tx/signing" + sdk "github.com/cosmos/cosmos-sdk/types" - types "github.com/cosmos/cosmos-sdk/types/tx" ) // SignModeHandlerMap is SignModeHandler that aggregates multiple SignModeHandler's into // a single handler type SignModeHandlerMap struct { - defaultMode types.SignMode - modes []types.SignMode - signModeHandlers map[types.SignMode]SignModeHandler + defaultMode signing.SignMode + modes []signing.SignMode + signModeHandlers map[signing.SignMode]SignModeHandler } var _ SignModeHandler = SignModeHandlerMap{} // NewSignModeHandlerMap returns a new SignModeHandlerMap with the provided defaultMode and handlers -func NewSignModeHandlerMap(defaultMode types.SignMode, handlers []SignModeHandler) SignModeHandlerMap { - handlerMap := make(map[types.SignMode]SignModeHandler) - var modes []types.SignMode +func NewSignModeHandlerMap(defaultMode signing.SignMode, handlers []SignModeHandler) SignModeHandlerMap { + handlerMap := make(map[signing.SignMode]SignModeHandler) + var modes []signing.SignMode for _, h := range handlers { for _, m := range h.Modes() { @@ -40,17 +41,17 @@ func NewSignModeHandlerMap(defaultMode types.SignMode, handlers []SignModeHandle } // DefaultMode implements SignModeHandler.DefaultMode -func (h SignModeHandlerMap) DefaultMode() types.SignMode { +func (h SignModeHandlerMap) DefaultMode() signing.SignMode { return h.defaultMode } // Modes implements SignModeHandler.Modes -func (h SignModeHandlerMap) Modes() []types.SignMode { +func (h SignModeHandlerMap) Modes() []signing.SignMode { return h.modes } // DefaultMode implements SignModeHandler.GetSignBytes -func (h SignModeHandlerMap) GetSignBytes(mode types.SignMode, data SignerData, tx sdk.Tx) ([]byte, error) { +func (h SignModeHandlerMap) GetSignBytes(mode signing.SignMode, data SignerData, tx sdk.Tx) ([]byte, error) { handler, found := h.signModeHandlers[mode] if !found { return nil, fmt.Errorf("can't verify sign mode %s", mode.String()) diff --git a/x/auth/signing/handler_map_test.go b/x/auth/signing/handler_map_test.go index 0133c38a1df..9c8d516eebe 100644 --- a/x/auth/signing/handler_map_test.go +++ b/x/auth/signing/handler_map_test.go @@ -8,7 +8,7 @@ import ( "github.com/tendermint/tendermint/crypto/secp256k1" sdk "github.com/cosmos/cosmos-sdk/types" - txtypes "github.com/cosmos/cosmos-sdk/types/tx" + signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" "github.com/cosmos/cosmos-sdk/x/auth/signing" "github.com/cosmos/cosmos-sdk/x/auth/signing/amino" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -17,7 +17,7 @@ import ( func MakeTestHandlerMap() signing.SignModeHandler { return signing.NewSignModeHandlerMap( - txtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, + signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, []signing.SignModeHandler{ amino.LegacyAminoJSONHandler{}, }, @@ -66,27 +66,27 @@ func TestHandlerMap_GetSignBytes(t *testing.T) { AccountNumber: accNum, AccountSequence: seqNum, } - signBz, err := handler.GetSignBytes(txtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, signingData, tx) + signBz, err := handler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, signingData, tx) require.NoError(t, err) - expectedSignBz, err := aminoJSONHandler.GetSignBytes(txtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, signingData, tx) + expectedSignBz, err := aminoJSONHandler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, signingData, tx) require.NoError(t, err) require.Equal(t, expectedSignBz, signBz) // expect error with wrong sign mode - _, err = aminoJSONHandler.GetSignBytes(txtypes.SignMode_SIGN_MODE_DIRECT, signingData, tx) + _, err = aminoJSONHandler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_DIRECT, signingData, tx) require.Error(t, err) } func TestHandlerMap_DefaultMode(t *testing.T) { handler := MakeTestHandlerMap() - require.Equal(t, txtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, handler.DefaultMode()) + require.Equal(t, signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, handler.DefaultMode()) } func TestHandlerMap_Modes(t *testing.T) { handler := MakeTestHandlerMap() modes := handler.Modes() - require.Contains(t, modes, txtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON) + require.Contains(t, modes, signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON) require.Len(t, modes, 1) } diff --git a/x/auth/signing/sign_mode_handler.go b/x/auth/signing/sign_mode_handler.go index 2ad40e31a2e..31ddcdd5185 100644 --- a/x/auth/signing/sign_mode_handler.go +++ b/x/auth/signing/sign_mode_handler.go @@ -2,7 +2,7 @@ package signing import ( sdk "github.com/cosmos/cosmos-sdk/types" - txtypes "github.com/cosmos/cosmos-sdk/types/tx" + "github.com/cosmos/cosmos-sdk/types/tx/signing" ) // SignModeHandler defines a interface to be implemented by types which will handle @@ -10,14 +10,14 @@ import ( type SignModeHandler interface { // DefaultMode is the default mode that is to be used with this handler if no // other mode is specified. This can be useful for testing and CLI usage - DefaultMode() txtypes.SignMode + DefaultMode() signing.SignMode // Modes is the list of modes supporting by this handler - Modes() []txtypes.SignMode + Modes() []signing.SignMode // GetSignBytes returns the sign bytes for the provided SignMode, SignerData and Tx, // or an error - GetSignBytes(mode txtypes.SignMode, data SignerData, tx sdk.Tx) ([]byte, error) + GetSignBytes(mode signing.SignMode, data SignerData, tx sdk.Tx) ([]byte, error) } // SignerData is the specific information needed to sign a transaction that generally diff --git a/x/auth/types/stdtx.go b/x/auth/types/stdtx.go index 6b6f8ac5103..c81c3cd91cb 100644 --- a/x/auth/types/stdtx.go +++ b/x/auth/types/stdtx.go @@ -4,6 +4,8 @@ import ( "encoding/json" "fmt" + "github.com/cosmos/cosmos-sdk/types/tx/signing" + "github.com/tendermint/tendermint/crypto" yaml "gopkg.in/yaml.v2" @@ -356,3 +358,96 @@ func (tx StdTx) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { } return nil } + +// StdSignatureToSignatureV2 converts a StdSignature to a SignatureV2 +func StdSignatureToSignatureV2(cdc *codec.Codec, sig StdSignature) (signing.SignatureV2, error) { + pk := sig.GetPubKey() + data, err := pubKeySigToSigData(cdc, pk, sig.Signature) + if err != nil { + return signing.SignatureV2{}, err + } + + return signing.SignatureV2{ + PubKey: pk, + Data: data, + }, nil +} + +func pubKeySigToSigData(cdc *codec.Codec, key crypto.PubKey, sig []byte) (signing.SignatureData, error) { + multiPK, ok := key.(multisig.PubKey) + if !ok { + return &signing.SingleSignatureData{ + SignMode: signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, + Signature: sig, + }, nil + } + var multiSig multisig.AminoMultisignature + err := cdc.UnmarshalBinaryBare(sig, &multiSig) + if err != nil { + return nil, err + } + + sigs := multiSig.Sigs + sigDatas := make([]signing.SignatureData, len(sigs)) + pubKeys := multiPK.GetPubKeys() + bitArray := multiSig.BitArray + n := multiSig.BitArray.Size() + signatures := multisig.NewMultisig(n) + sigIdx := 0 + for i := 0; i < n; i++ { + if bitArray.GetIndex(i) { + data, err := pubKeySigToSigData(cdc, pubKeys[i], multiSig.Sigs[sigIdx]) + if err != nil { + return nil, sdkerrors.Wrapf(err, "Unable to convert Signature to SigData %d", sigIdx) + } + + sigDatas[sigIdx] = data + multisig.AddSignature(signatures, data, sigIdx) + sigIdx++ + } + } + + return signatures, nil +} + +// MultiSignatureDataToAminoMultisignature converts a MultiSignatureData to an AminoMultisignature. +// Only SIGN_MODE_LEGACY_AMINO_JSON is supported. +func MultiSignatureDataToAminoMultisignature(cdc *codec.Codec, mSig *signing.MultiSignatureData) (multisig.AminoMultisignature, error) { + n := len(mSig.Signatures) + sigs := make([][]byte, n) + + for i := 0; i < n; i++ { + var err error + sigs[i], err = SignatureDataToAminoSignature(cdc, mSig.Signatures[i]) + if err != nil { + return multisig.AminoMultisignature{}, sdkerrors.Wrapf(err, "Unable to convert Signature Data to signature %d", i) + } + } + + return multisig.AminoMultisignature{ + BitArray: mSig.BitArray, + Sigs: sigs, + }, nil +} + +// SignatureDataToAminoSignature converts a SignatureData to amino-encoded signature bytes. +// Only SIGN_MODE_LEGACY_AMINO_JSON is supported. +func SignatureDataToAminoSignature(cdc *codec.Codec, data signing.SignatureData) ([]byte, error) { + switch data := data.(type) { + case *signing.SingleSignatureData: + if data.SignMode != signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON { + return nil, fmt.Errorf("expected %s, got %s", signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, data.SignMode) + } + + return data.Signature, nil + case *signing.MultiSignatureData: + aminoMSig, err := MultiSignatureDataToAminoMultisignature(cdc, data) + if err != nil { + return nil, err + } + + return cdc.MarshalBinaryBare(aminoMSig) + default: + return nil, fmt.Errorf("unexpected signature data %T", data) + } +} diff --git a/x/auth/types/stdtx_test.go b/x/auth/types/stdtx_test.go index 09230d03eec..df43ccda926 100644 --- a/x/auth/types/stdtx_test.go +++ b/x/auth/types/stdtx_test.go @@ -4,6 +4,11 @@ import ( "fmt" "testing" + "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/crypto/types/multisig" + + "github.com/cosmos/cosmos-sdk/types/tx/signing" + "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto" @@ -167,3 +172,58 @@ func TestStdSignatureMarshalYAML(t *testing.T) { require.Equal(t, tc.output, string(bz), "test case #%d", i) } } + +func TestSignatureV2Conversions(t *testing.T) { + _, pubKey, _ := KeyTestPubAddr() + cdc := codec.New() + sdk.RegisterCodec(cdc) + RegisterCodec(cdc) + dummy := []byte("dummySig") + sig := StdSignature{PubKey: pubKey.Bytes(), Signature: dummy} + + sigV2, err := StdSignatureToSignatureV2(cdc, sig) + require.NoError(t, err) + require.Equal(t, pubKey, sigV2.PubKey) + require.Equal(t, &signing.SingleSignatureData{ + SignMode: signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, + Signature: dummy, + }, sigV2.Data) + + sigBz, err := SignatureDataToAminoSignature(cdc, sigV2.Data) + require.NoError(t, err) + require.Equal(t, dummy, sigBz) + + // multisigs + _, pubKey2, _ := KeyTestPubAddr() + multiPK := multisig.NewPubKeyMultisigThreshold(1, []crypto.PubKey{ + pubKey, pubKey2, + }) + dummy2 := []byte("dummySig2") + bitArray := types.NewCompactBitArray(2) + bitArray.SetIndex(0, true) + bitArray.SetIndex(1, true) + msigData := &signing.MultiSignatureData{ + BitArray: bitArray, + Signatures: []signing.SignatureData{ + &signing.SingleSignatureData{ + SignMode: signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, + Signature: dummy, + }, + &signing.SingleSignatureData{ + SignMode: signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, + Signature: dummy2, + }, + }, + } + + msig, err := SignatureDataToAminoSignature(cdc, msigData) + require.NoError(t, err) + + sigV2, err = StdSignatureToSignatureV2(cdc, StdSignature{ + PubKey: multiPK.Bytes(), + Signature: msig, + }) + require.NoError(t, err) + require.Equal(t, multiPK, sigV2.PubKey) + require.Equal(t, msigData, sigV2.Data) +}