From 34371774fe3d6e6e55f43792b76fccaeda16b457 Mon Sep 17 00:00:00 2001 From: oxichigo <142579496+OxIchigo@users.noreply.github.com> Date: Thu, 30 Nov 2023 05:51:03 +0000 Subject: [PATCH 1/2] feat: multisig prepend existing signatures with given signature --- x/auth/client/cli/tx_multisign.go | 95 ++++++++++++++++++++++++++++++- 1 file changed, 94 insertions(+), 1 deletion(-) diff --git a/x/auth/client/cli/tx_multisign.go b/x/auth/client/cli/tx_multisign.go index 049a36f211c3..5b9523c18688 100644 --- a/x/auth/client/cli/tx_multisign.go +++ b/x/auth/client/cli/tx_multisign.go @@ -11,8 +11,10 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/crypto/keyring" kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" "github.com/cosmos/cosmos-sdk/crypto/types/multisig" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/errors" @@ -120,6 +122,45 @@ func makeMultiSignCmd() func(cmd *cobra.Command, args []string) (err error) { txFactory = txFactory.WithAccountNumber(accnum).WithSequence(seq) } + sigVerifiableTx := parsedTx.(signing.SigVerifiableTx) + oldSigs, _ := sigVerifiableTx.GetSignaturesV2() + txPubKeys, _ := sigVerifiableTx.GetPubKeys() + signModeHandler := txCfg.SignModeHandler() + + extractedSignatues := make([]signingtypes.SignatureV2, 0) + + for _, sig := range oldSigs { + extractedSigs := extractSignatues(sig, txPubKeys, clientCtx.LegacyAmino, func(pk cryptotypes.PubKey, signatureData signingtypes.SignatureData) error { + signingData := signing.SignerData{ + Address: sdk.AccAddress(pk.Address()).String(), + ChainID: txFactory.ChainID(), + AccountNumber: txFactory.AccountNumber(), + Sequence: txFactory.Sequence(), + PubKey: pk, + } + + singleSignatureData, ok := signatureData.(*signingtypes.SingleSignatureData) + // TODO - Implemenation required for multisignatureData case + if !ok { + return fmt.Errorf("nested multisignature is not supported yet") + } + msg, _ := signModeHandler.GetSignBytes(singleSignatureData.SignMode, signingData, txBuilder.GetTx()) + + valid := pk.VerifySignature(msg, singleSignatureData.Signature) + if !valid { + return fmt.Errorf("signature doesn't match with the given public key") + } + return nil + }) + + // Add All extracted signatures into signature slice + extractedSignatues = append(extractedSignatues, extractedSigs...) + } + + for _, sig := range extractedSignatues { + multisig.AddSignatureV2(multisigSig, sig, multisigPub.GetPubKeys()) + } + // read each signature and add it to the multisig if valid for i := 2; i < len(args); i++ { sigs, err := unmarshalSignatureJSON(clientCtx, args[i]) @@ -140,7 +181,7 @@ func makeMultiSignCmd() func(cmd *cobra.Command, args []string) (err error) { PubKey: sig.PubKey, } - err = signing.VerifySignature(sig.PubKey, signingData, sig.Data, txCfg.SignModeHandler(), txBuilder.GetTx()) + err = signing.VerifySignature(sig.PubKey, signingData, sig.Data, signModeHandler, txBuilder.GetTx()) if err != nil { addr, _ := sdk.AccAddressFromHexUnsafe(sig.PubKey.Address().String()) return fmt.Errorf("couldn't verify signature for address %s", addr) @@ -418,3 +459,55 @@ func getMultisigRecord(clientCtx client.Context, name string) (*keyring.Record, return multisigRecord, nil } + +type SignatureVerifier func(cryptotypes.PubKey, signingtypes.SignatureData) error + +func matchPubKeyAndSignature(signatureData signingtypes.SignatureData, keys []cryptotypes.PubKey, verificationHandler SignatureVerifier) cryptotypes.PubKey { + for _, key := range keys { + multiPubkey, ok := key.(*kmultisig.LegacyAminoPubKey) + if ok { + return matchPubKeyAndSignature(signatureData, multiPubkey.GetPubKeys(), verificationHandler) + } + err := verificationHandler(key, signatureData) + if err == nil { + return key + } + } + return nil +} + +func extractSignatues(oldSig signingtypes.SignatureV2, pubKeys []cryptotypes.PubKey, cdc *codec.LegacyAmino, + verificationHandler SignatureVerifier) []signingtypes.SignatureV2 { + + extractedSignatues := make([]signingtypes.SignatureV2, 0) + + switch data := oldSig.Data.(type) { + + case *signingtypes.SingleSignatureData: + return append(extractedSignatues, oldSig) + + case *signingtypes.MultiSignatureData: + for _, sig := range data.Signatures { + // TODO - convert this into switch case to handle nested multisig + singleSig, ok := sig.(*signingtypes.SingleSignatureData) + if !ok { + continue + } + + pub := matchPubKeyAndSignature(singleSig, pubKeys, verificationHandler) + if pub != nil { + // TODO - find replacement for this deprecated method + stdSig := legacytx.StdSignature{ + PubKey: pub, + Signature: singleSig.Signature, + } + + sigV2, err := legacytx.StdSignatureToSignatureV2(cdc, stdSig) + if err == nil { + extractedSignatues = append(extractedSignatues, sigV2) + } + } + } + } + return extractedSignatues +} From 2fa6a01b98888d87046a2cc74929f51d5fb584d5 Mon Sep 17 00:00:00 2001 From: 0xCrypto-Bear Date: Tue, 12 Dec 2023 12:29:25 +0530 Subject: [PATCH 2/2] fix: lint fixes --- x/auth/client/cli/tx_multisign.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/x/auth/client/cli/tx_multisign.go b/x/auth/client/cli/tx_multisign.go index 5b9523c18688..a8e7bf4407be 100644 --- a/x/auth/client/cli/tx_multisign.go +++ b/x/auth/client/cli/tx_multisign.go @@ -158,7 +158,9 @@ func makeMultiSignCmd() func(cmd *cobra.Command, args []string) (err error) { } for _, sig := range extractedSignatues { - multisig.AddSignatureV2(multisigSig, sig, multisigPub.GetPubKeys()) + if err := multisig.AddSignatureV2(multisigSig, sig, multisigPub.GetPubKeys()); err != nil { + return err + } } // read each signature and add it to the multisig if valid