Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: multisig prepend existing signatures with given signature #1

Merged
merged 2 commits into from
Dec 12, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 96 additions & 1 deletion x/auth/client/cli/tx_multisign.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
"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"
Expand Down Expand Up @@ -120,6 +122,47 @@
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 {
if err := multisig.AddSignatureV2(multisigSig, sig, multisigPub.GetPubKeys()); err != nil {
return err
}
}

// read each signature and add it to the multisig if valid
for i := 2; i < len(args); i++ {
sigs, err := unmarshalSignatureJSON(clientCtx, args[i])
Expand All @@ -140,7 +183,7 @@
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)
Expand Down Expand Up @@ -418,3 +461,55 @@

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 {

Check failure on line 482 in x/auth/client/cli/tx_multisign.go

View workflow job for this annotation

GitHub Actions / golangci-lint

File is not `gofumpt`-ed (gofumpt)

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{

Check failure on line 502 in x/auth/client/cli/tx_multisign.go

View workflow job for this annotation

GitHub Actions / Analyze

SA1019: legacytx.StdSignature is deprecated: StdSignature represents a sig (staticcheck)

Check failure on line 502 in x/auth/client/cli/tx_multisign.go

View workflow job for this annotation

GitHub Actions / golangci-lint

SA1019: legacytx.StdSignature is deprecated: StdSignature represents a sig (staticcheck)
PubKey: pub,
Signature: singleSig.Signature,
}

sigV2, err := legacytx.StdSignatureToSignatureV2(cdc, stdSig)
if err == nil {
extractedSignatues = append(extractedSignatues, sigV2)
}
}
}
}
return extractedSignatues
}
Loading