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(cli): add --append flag to sign-batch cli cmd #13147

Merged
merged 33 commits into from
Sep 26, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
14afa31
feat(cli): add `multi-msg-sign`
gsk967 Sep 4, 2022
419b65d
chore: update the changelog
gsk967 Sep 4, 2022
8c87572
chore: fix the lint issue
gsk967 Sep 4, 2022
fe690ca
chore: address the pr comments
gsk967 Sep 5, 2022
f5e4c65
Merge branch 'main' into sai/multi_msg_sign_13066
gsk967 Sep 5, 2022
1774549
Merge branch 'main' into sai/multi_msg_sign_13066
gsk967 Sep 5, 2022
f932afa
Merge branch 'main' into sai/multi_msg_sign_13066
gsk967 Sep 5, 2022
7e8f9f0
Merge branch 'main' into sai/multi_msg_sign_13066
gsk967 Sep 6, 2022
9956878
Merge branch 'main' into sai/multi_msg_sign_13066
anilcse Sep 6, 2022
abb13b5
Merge branch 'main' into sai/multi_msg_sign_13066
gsk967 Sep 7, 2022
606758b
Merge branch 'sai/multi_msg_sign_13066' of github.com:gsk967/cosmos-s…
gsk967 Sep 7, 2022
07b4a71
Merge branch 'main' into sai/multi_msg_sign_13066
gsk967 Sep 7, 2022
ea907b1
Merge branch 'main' into sai/multi_msg_sign_13066
gsk967 Sep 8, 2022
a2c1d44
Merge branch 'main' into sai/multi_msg_sign_13066
gsk967 Sep 8, 2022
d90d78a
Merge branch 'main' into sai/multi_msg_sign_13066
gsk967 Sep 8, 2022
a7b7234
chore: address the pr comments
gsk967 Sep 8, 2022
fa44e9c
Merge remote-tracking branch 'mine/sai/multi_msg_sign_13066' into sai…
gsk967 Sep 8, 2022
ff3ee19
Merge branch 'main' into sai/multi_msg_sign_13066
gsk967 Sep 12, 2022
947d528
Merge branch 'main' into sai/multi_msg_sign_13066
gsk967 Sep 12, 2022
0c20e5a
Merge branch 'main' into sai/multi_msg_sign_13066
gsk967 Sep 22, 2022
565ed1a
refactor: refactored `sign-batch` to generate single signed tx
gsk967 Sep 22, 2022
6fb556e
chore: updated the changelog
gsk967 Sep 22, 2022
861e5c5
fix: fix the lint
gsk967 Sep 22, 2022
a5c6e15
test: fix the tests on auth
gsk967 Sep 22, 2022
6fc9145
Merge branch 'main' into sai/multi_msg_sign_13066
gsk967 Sep 23, 2022
382d63a
Merge branch 'main' into sai/multi_msg_sign_13066
julienrbrt Sep 23, 2022
9fd6081
Merge branch 'main' into sai/multi_msg_sign_13066
gsk967 Sep 24, 2022
4206be9
Merge branch 'main' into sai/multi_msg_sign_13066
gsk967 Sep 24, 2022
42a0d2f
Merge branch 'main' into sai/multi_msg_sign_13066
julienrbrt Sep 24, 2022
7ff9c11
Merge branch 'main' into sai/multi_msg_sign_13066
julienrbrt Sep 25, 2022
162e22e
Merge branch 'main' into sai/multi_msg_sign_13066
gsk967 Sep 26, 2022
d0780aa
Merge branch 'main' into sai/multi_msg_sign_13066
gsk967 Sep 26, 2022
ea5d655
Merge branch 'main' into sai/multi_msg_sign_13066
alexanderbez Sep 26, 2022
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
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (client) [#12936](https://github.com/cosmos/cosmos-sdk/pull/12936) Add capability to preprocess transactions before broadcasting from a higher level chain.
* (x/authz) [#13047](https://github.com/cosmos/cosmos-sdk/pull/13047) Add a GetAuthorization function to the keeper.
* (cli) [#12742](https://github.com/cosmos/cosmos-sdk/pull/12742) Add the `prune` CLI cmd to manually prune app store history versions based on the pruning options.

* (cli) [#13147](https://github.com/cosmos/cosmos-sdk/pull/13147) Add the `multi-msg-sign` CLI cmd to combine the messages and sign those txs which are created with `--generate-only`.
### Improvements
gsk967 marked this conversation as resolved.
Show resolved Hide resolved

* [#12981](https://github.com/cosmos/cosmos-sdk/pull/12981) Return proper error when parsing telemetry configuration.
Expand Down
1 change: 1 addition & 0 deletions simapp/simd/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ func txCommand() *cobra.Command {
cmd.AddCommand(
authcmd.GetSignCommand(),
authcmd.GetSignBatchCommand(),
authcmd.GetMultiMsgSignCommand(),
authcmd.GetMultiSignCommand(),
authcmd.GetMultiSignBatchCmd(),
authcmd.GetValidateSignaturesCommand(),
Expand Down
73 changes: 73 additions & 0 deletions x/auth/client/cli/tx_multisign.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,79 @@ type BroadcastReq struct {
Mode string `json:"mode" yaml:"mode"`
}

// GetMultiMsgSignCommand returns the multi-msg-sign cmd
func GetMultiMsgSignCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "multi-msg-sign [file] [file]...",
Short: "Combine messages from transactions which are generated offline.",
PreRun: preSignCmd,
Example: fmt.Sprintf("%s tx multi-msg-sign tx1.json tx2.json tx3.json ", version.AppName),
Long: strings.TrimSpace(
fmt.Sprintf(
`Combine the transactions created with the --generate-only flag and Sign those transactions.
gsk967 marked this conversation as resolved.
Show resolved Hide resolved

Example:
$ %s tx multi-msg-sign tx1.json tx2.json tx3.json

It will read a transactions from [files], sign it, and print its JSON encoding.
gsk967 marked this conversation as resolved.
Show resolved Hide resolved

The --offline flag makes sure that the client will not reach out to full node.
As a result, the account and sequence number queries will not be performed and
it is required to set such parameters manually. Note, invalid values will cause
the transaction to fail.

The --multisig=<multisig_key> flag generates a signature on behalf of a multisig account
key. It implies --signature-only. Full multisig signed transactions may eventually
be generated via the 'multisign' command.
`, version.AppName,
)),

RunE: makeMultiMsgSignCmd(),
gsk967 marked this conversation as resolved.
Show resolved Hide resolved
}

cmd.Flags().String(flagMultisig, "", "Address or key name of the multisig account on behalf of which the transaction shall be signed")
cmd.Flags().Bool(flagOverwrite, false, "Overwrite existing signatures with a new one. If disabled, new signature will be appended")
gsk967 marked this conversation as resolved.
Show resolved Hide resolved
cmd.Flags().Bool(flagSigOnly, false, "Print only the signatures")
cmd.Flags().String(flags.FlagOutputDocument, "", "The document will be written to the given file instead of STDOUT")
cmd.Flags().Bool(flagAmino, false, "Generate Amino encoded JSON suitable for submiting to the txs REST endpoint")
flags.AddTxFlagsToCmd(cmd)

cmd.MarkFlagRequired(flags.FlagFrom)

return cmd
}

func makeMultiMsgSignCmd() func(cmd *cobra.Command, args []string) error {
return func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

txBuilder := clientCtx.TxConfig.NewTxBuilder()
msgs := make([]sdk.Msg, 0)
for i := 0; i < len(args); i++ {
parsedTx, err := authclient.ReadTxFromFile(clientCtx, args[i])
if err != nil {
return err
}
fe, err := clientCtx.TxConfig.WrapTxBuilder(parsedTx)
gsk967 marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return err
}
msgs = append(msgs, parsedTx.GetMsgs()...)
gsk967 marked this conversation as resolved.
Show resolved Hide resolved
txBuilder.SetMemo(fe.GetTx().GetMemo())
txBuilder.SetTip(fe.GetTx().GetTip())
txBuilder.SetGasLimit(fe.GetTx().GetGas())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're doing this in a loop, so aren't we overriding these fields, for each tx?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now I am adding memo, remaining fields to tx from cmd.Flags

}

txBuilder.SetMsgs(msgs...)
txBuilder.SetGasLimit(txBuilder.GetTx().GetGas() * uint64(len(msgs)))

return signTx(cmd, clientCtx, tx.NewFactoryCLI(clientCtx, cmd.Flags()), txBuilder.GetTx())
}
}

// GetSignCommand returns the sign command
func GetMultiSignCommand() *cobra.Command {
cmd := &cobra.Command{
Expand Down
193 changes: 102 additions & 91 deletions x/auth/client/cli/tx_sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/tx"
kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
"github.com/cosmos/cosmos-sdk/types"

authclient "github.com/cosmos/cosmos-sdk/x/auth/client"
)
Expand Down Expand Up @@ -216,129 +217,139 @@ func makeSignCmd() func(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
f := cmd.Flags()

clientCtx, txF, newTx, err := readTxAndInitContexts(clientCtx, cmd, args[0])
if err != nil {
return err
}

txCfg := clientCtx.TxConfig
txBuilder, err := txCfg.WrapTxBuilder(newTx)
return signTx(cmd, clientCtx, txF, newTx)
}
}

func signTx(cmd *cobra.Command, clientCtx client.Context, txF tx.Factory, newTx types.Tx) error {
f := cmd.Flags()
txCfg := clientCtx.TxConfig
txBuilder, err := txCfg.WrapTxBuilder(newTx)
if err != nil {
return err
}

printSignatureOnly, err := cmd.Flags().GetBool(flagSigOnly)
if err != nil {
gsk967 marked this conversation as resolved.
Show resolved Hide resolved
return err
}

multisig, err := cmd.Flags().GetString(flagMultisig)
if err != nil {
return err
}

from, err := cmd.Flags().GetString(flags.FlagFrom)
if err != nil {
return err
}

_, fromName, _, err := client.GetFromFields(clientCtx, txF.Keybase(), from)
if err != nil {
return fmt.Errorf("error getting account from keybase: %w", err)
}

overwrite, err := f.GetBool(flagOverwrite)
if err != nil {
return err
}

if multisig != "" {
// Bech32 decode error, maybe it's a name, we try to fetch from keyring
multisigAddr, multisigName, _, err := client.GetFromFields(clientCtx, txF.Keybase(), multisig)
if err != nil {
return err
return fmt.Errorf("error getting account from keybase: %w", err)
}

printSignatureOnly, _ := cmd.Flags().GetBool(flagSigOnly)
multisig, _ := cmd.Flags().GetString(flagMultisig)
multisigkey, err := getMultisigRecord(clientCtx, multisigName)
if err != nil {
return err
}
from, _ := cmd.Flags().GetString(flags.FlagFrom)
_, fromName, _, err := client.GetFromFields(clientCtx, txF.Keybase(), from)
multisigPubKey, err := multisigkey.GetPubKey()
if err != nil {
return fmt.Errorf("error getting account from keybase: %w", err)
return err
}
multisigLegacyPub := multisigPubKey.(*kmultisig.LegacyAminoPubKey)

overwrite, _ := f.GetBool(flagOverwrite)
if multisig != "" {
// Bech32 decode error, maybe it's a name, we try to fetch from keyring
multisigAddr, multisigName, _, err := client.GetFromFields(clientCtx, txF.Keybase(), multisig)
if err != nil {
return fmt.Errorf("error getting account from keybase: %w", err)
}
multisigkey, err := getMultisigRecord(clientCtx, multisigName)
if err != nil {
return err
}
multisigPubKey, err := multisigkey.GetPubKey()
if err != nil {
return err
}
multisigLegacyPub := multisigPubKey.(*kmultisig.LegacyAminoPubKey)

fromRecord, err := clientCtx.Keyring.Key(fromName)
if err != nil {
return fmt.Errorf("error getting account from keybase: %w", err)
}
fromPubKey, err := fromRecord.GetPubKey()
if err != nil {
return err
}

var found bool
for _, pubkey := range multisigLegacyPub.GetPubKeys() {
if pubkey.Equals(fromPubKey) {
found = true
}
}
if !found {
return fmt.Errorf("signing key is not a part of multisig key")
}
err = authclient.SignTxWithSignerAddress(
txF, clientCtx, multisigAddr, fromName, txBuilder, clientCtx.Offline, overwrite)
if err != nil {
return err
}
printSignatureOnly = true
} else {
err = authclient.SignTx(txF, clientCtx, clientCtx.GetFromName(), txBuilder, clientCtx.Offline, overwrite)
fromRecord, err := clientCtx.Keyring.Key(fromName)
if err != nil {
return fmt.Errorf("error getting account from keybase: %w", err)
}
fromPubKey, err := fromRecord.GetPubKey()
if err != nil {
return err
}

aminoJSON, err := f.GetBool(flagAmino)
var found bool
for _, pubkey := range multisigLegacyPub.GetPubKeys() {
if pubkey.Equals(fromPubKey) {
found = true
}
}
if !found {
return fmt.Errorf("signing key is not a part of multisig key")
}
err = authclient.SignTxWithSignerAddress(
txF, clientCtx, multisigAddr, fromName, txBuilder, clientCtx.Offline, overwrite)
if err != nil {
return err
}
printSignatureOnly = true
} else {
err = authclient.SignTx(txF, clientCtx, clientCtx.GetFromName(), txBuilder, clientCtx.Offline, overwrite)
}
if err != nil {
return err
}

aminoJSON, err := f.GetBool(flagAmino)
if err != nil {
return err
}

bMode, err := f.GetString(flags.FlagBroadcastMode)
if err != nil {
return err
}

// set output
closeFunc, err := setOutputFile(cmd)
if err != nil {
return err
}

defer closeFunc()
clientCtx.WithOutput(cmd.OutOrStdout())

bMode, err := f.GetString(flags.FlagBroadcastMode)
var json []byte
if aminoJSON {
stdTx, err := tx.ConvertTxToStdTx(clientCtx.LegacyAmino, txBuilder.GetTx())
if err != nil {
return err
}

var json []byte
if aminoJSON {
stdTx, err := tx.ConvertTxToStdTx(clientCtx.LegacyAmino, txBuilder.GetTx())
if err != nil {
return err
}
req := BroadcastReq{
Tx: stdTx,
Mode: bMode,
}
json, err = clientCtx.LegacyAmino.MarshalJSON(req)
if err != nil {
return err
}
} else {
json, err = marshalSignatureJSON(txCfg, txBuilder, printSignatureOnly)
if err != nil {
return err
}
req := BroadcastReq{
Tx: stdTx,
Mode: bMode,
}

outputDoc, _ := cmd.Flags().GetString(flags.FlagOutputDocument)
if outputDoc == "" {
cmd.Printf("%s\n", json)
return nil
json, err = clientCtx.LegacyAmino.MarshalJSON(req)
if err != nil {
return err
}

fp, err := os.OpenFile(outputDoc, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o644)
} else {
json, err = marshalSignatureJSON(txCfg, txBuilder, printSignatureOnly)
if err != nil {
return err
}
defer func() {
err2 := fp.Close()
if err == nil {
err = err2
}
}()

_, err = fp.Write(append(json, '\n'))
return err
}

cmd.Printf("%s\n", json)

return err
}

func marshalSignatureJSON(txConfig client.TxConfig, txBldr client.TxBuilder, signatureOnly bool) ([]byte, error) {
Expand Down