feat: let sign-batch read multiple files (#13454)
* feat: let `sign-batch` read multiple files * add changelog * fix gosec issue * simplify
This commit is contained in:
parent
2151427b5e
commit
6efbedb1c7
@ -52,6 +52,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
* (x/auth) [#13210](https://github.com/cosmos/cosmos-sdk/pull/13210) Add `Query/AccountInfo` endpoint for simplified access to basic account info.
|
||||
* (cli) [#13147](https://github.com/cosmos/cosmos-sdk/pull/13147) Add the `--append` flag to the `sign-batch` CLI cmd to combine the messages and sign those txs which are created with `--generate-only`.
|
||||
* (x/consensus) [#12905](https://github.com/cosmos/cosmos-sdk/pull/12905) Create a new `x/consensus` module that is now responsible for maintaining Tendermint consensus parameters instead of `x/param`. Legacy types remain in order to facilitate parameter migration from the deprecated `x/params`. App developers should ensure that they execute `baseapp.MigrateParams` during their chain upgrade. These legacy types will be removed in a future release.
|
||||
* (cli) [#13454](https://github.com/cosmos/cosmos-sdk/pull/13454) `sign-batch` CLI can now read multiple transaction files.
|
||||
|
||||
### Improvements
|
||||
|
||||
|
||||
@ -29,7 +29,7 @@ type BroadcastReq struct {
|
||||
Mode string `json:"mode" yaml:"mode"`
|
||||
}
|
||||
|
||||
// GetSignCommand returns the sign command
|
||||
// GetMultiSignCommand returns the multi-sign command
|
||||
func GetMultiSignCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "multi-sign [file] [name] [[signature]...]",
|
||||
@ -258,21 +258,11 @@ func makeBatchMultisignCmd() func(cmd *cobra.Command, args []string) error {
|
||||
txFactory = txFactory.WithSignMode(signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON)
|
||||
}
|
||||
|
||||
infile := os.Stdin
|
||||
if args[0] != "-" {
|
||||
infile, err = os.Open(args[0])
|
||||
defer func() {
|
||||
err2 := infile.Close()
|
||||
if err == nil {
|
||||
err = err2
|
||||
}
|
||||
}()
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("couldn't open %s: %w", args[0], err)
|
||||
}
|
||||
// reads tx from args[0]
|
||||
scanner, err := authclient.ReadTxsFromInput(txCfg, args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
scanner := authclient.NewBatchScanner(txCfg, infile)
|
||||
|
||||
k, err := getMultisigRecord(clientCtx, args[1])
|
||||
if err != nil {
|
||||
|
||||
@ -27,11 +27,11 @@ const (
|
||||
// GetSignBatchCommand returns the transaction sign-batch command.
|
||||
func GetSignBatchCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "sign-batch [file]",
|
||||
Use: "sign-batch [file] ([file2]...)",
|
||||
Short: "Sign transaction batch files",
|
||||
Long: `Sign batch files of transactions generated with --generate-only.
|
||||
The command processes list of transactions from file (one StdTx each line), generate
|
||||
signed transactions or signatures and print their JSON encoding, delimited by '\n'.
|
||||
The command processes list of transactions from a file (one StdTx each line), or multiple files.
|
||||
Then generates signed transactions or signatures and print their JSON encoding, delimited by '\n'.
|
||||
As the signatures are generated, the command updates the account and sequence number accordingly.
|
||||
|
||||
If the --signature-only flag is set, it will output the signature parts only.
|
||||
@ -50,7 +50,7 @@ account key. It implies --signature-only.
|
||||
`,
|
||||
PreRun: preSignCmd,
|
||||
RunE: makeSignBatchCmd(),
|
||||
Args: cobra.ExactArgs(1),
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
}
|
||||
|
||||
cmd.Flags().String(flagMultisig, "", "Address or key name of the multisig account on behalf of which the transaction shall be signed")
|
||||
@ -74,7 +74,6 @@ func makeSignBatchCmd() func(cmd *cobra.Command, args []string) error {
|
||||
txFactory := tx.NewFactoryCLI(clientCtx, cmd.Flags())
|
||||
txCfg := clientCtx.TxConfig
|
||||
printSignatureOnly, _ := cmd.Flags().GetBool(flagSigOnly)
|
||||
infile := os.Stdin
|
||||
|
||||
ms, err := cmd.Flags().GetString(flagMultisig)
|
||||
if err != nil {
|
||||
@ -86,17 +85,14 @@ func makeSignBatchCmd() func(cmd *cobra.Command, args []string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer closeFunc()
|
||||
clientCtx.WithOutput(cmd.OutOrStdout())
|
||||
|
||||
if args[0] != "-" {
|
||||
infile, err = os.Open(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// reads tx from args
|
||||
scanner, err := authclient.ReadTxsFromInput(txCfg, args...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
scanner := authclient.NewBatchScanner(txCfg, infile)
|
||||
|
||||
if !clientCtx.Offline {
|
||||
if ms == "" {
|
||||
@ -121,9 +117,9 @@ func makeSignBatchCmd() func(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
}
|
||||
|
||||
appendMessagesToSingleMsg, _ := cmd.Flags().GetBool(flagAppend)
|
||||
if appendMessagesToSingleMsg {
|
||||
// It will combine all tx msgs and create single signed transaction
|
||||
appendMessagesToSingleTx, _ := cmd.Flags().GetBool(flagAppend)
|
||||
// Combines all tx msgs and create single signed transaction
|
||||
if appendMessagesToSingleTx {
|
||||
txBuilder := clientCtx.TxConfig.NewTxBuilder()
|
||||
msgs := make([]sdk.Msg, 0)
|
||||
newGasLimit := uint64(0)
|
||||
@ -151,39 +147,24 @@ func makeSignBatchCmd() func(cmd *cobra.Command, args []string) error {
|
||||
// set the gasLimit
|
||||
txBuilder.SetGasLimit(newGasLimit)
|
||||
|
||||
// sign the txs
|
||||
if ms == "" {
|
||||
from, _ := cmd.Flags().GetString(flags.FlagFrom)
|
||||
_, fromName, _, err := client.GetFromFields(clientCtx, txFactory.Keybase(), from)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting account from keybase: %w", err)
|
||||
}
|
||||
err = authclient.SignTx(txFactory, clientCtx, fromName, txBuilder, true, true)
|
||||
if err != nil {
|
||||
if err := sign(clientCtx, txBuilder, txFactory, from); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
multisigAddr, _, _, err := client.GetFromFields(clientCtx, txFactory.Keybase(), ms)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting account from keybase: %w", err)
|
||||
}
|
||||
err = authclient.SignTxWithSignerAddress(
|
||||
txFactory, clientCtx, multisigAddr, clientCtx.GetFromName(), txBuilder, clientCtx.Offline, true)
|
||||
if err != nil {
|
||||
if err := multisigSign(clientCtx, txBuilder, txFactory, ms); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
json, err := marshalSignatureJSON(txCfg, txBuilder, printSignatureOnly)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd.Printf("%s\n", json)
|
||||
|
||||
} else {
|
||||
// It will generate signed tx for each tx
|
||||
for sequence := txFactory.Sequence(); scanner.Scan(); sequence++ {
|
||||
@ -193,37 +174,23 @@ func makeSignBatchCmd() func(cmd *cobra.Command, args []string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// sign the txs
|
||||
if ms == "" {
|
||||
from, _ := cmd.Flags().GetString(flags.FlagFrom)
|
||||
_, fromName, _, err := client.GetFromFields(clientCtx, txFactory.Keybase(), from)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting account from keybase: %w", err)
|
||||
}
|
||||
err = authclient.SignTx(txFactory, clientCtx, fromName, txBuilder, true, true)
|
||||
if err != nil {
|
||||
if err := sign(clientCtx, txBuilder, txFactory, from); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
multisigAddr, _, _, err := client.GetFromFields(clientCtx, txFactory.Keybase(), ms)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting account from keybase: %w", err)
|
||||
}
|
||||
err = authclient.SignTxWithSignerAddress(
|
||||
txFactory, clientCtx, multisigAddr, clientCtx.GetFromName(), txBuilder, clientCtx.Offline, true)
|
||||
if err != nil {
|
||||
if err := multisigSign(clientCtx, txBuilder, txFactory, ms); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
json, err := marshalSignatureJSON(txCfg, txBuilder, printSignatureOnly)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd.Printf("%s\n", json)
|
||||
}
|
||||
}
|
||||
@ -236,6 +203,40 @@ func makeSignBatchCmd() func(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
}
|
||||
|
||||
func sign(clientCtx client.Context, txBuilder client.TxBuilder, txFactory tx.Factory, from string) error {
|
||||
_, fromName, _, err := client.GetFromFields(clientCtx, txFactory.Keybase(), from)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting account from keybase: %w", err)
|
||||
}
|
||||
|
||||
if err = authclient.SignTx(txFactory, clientCtx, fromName, txBuilder, true, true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func multisigSign(clientCtx client.Context, txBuilder client.TxBuilder, txFactory tx.Factory, multisig string) error {
|
||||
multisigAddr, _, _, err := client.GetFromFields(clientCtx, txFactory.Keybase(), multisig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting account from keybase: %w", err)
|
||||
}
|
||||
|
||||
if err = authclient.SignTxWithSignerAddress(
|
||||
txFactory,
|
||||
clientCtx,
|
||||
multisigAddr,
|
||||
clientCtx.GetFromName(),
|
||||
txBuilder,
|
||||
clientCtx.Offline,
|
||||
true,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func setOutputFile(cmd *cobra.Command) (func(), error) {
|
||||
outputDoc, _ := cmd.Flags().GetString(flags.FlagOutputDocument)
|
||||
if outputDoc == "" {
|
||||
|
||||
@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/cosmos/gogoproto/jsonpb"
|
||||
@ -90,7 +91,7 @@ func SignTxWithSignerAddress(txFactory tx.Factory, clientCtx client.Context, add
|
||||
return tx.Sign(txFactory, name, txBuilder, overwrite)
|
||||
}
|
||||
|
||||
// Read and decode a StdTx from the given filename. Can pass "-" to read from stdin.
|
||||
// Read and decode a StdTx from the given filename. Can pass "-" to read from stdin.
|
||||
func ReadTxFromFile(ctx client.Context, filename string) (tx sdk.Tx, err error) {
|
||||
var bytes []byte
|
||||
|
||||
@ -107,6 +108,33 @@ func ReadTxFromFile(ctx client.Context, filename string) (tx sdk.Tx, err error)
|
||||
return ctx.TxConfig.TxJSONDecoder()(bytes)
|
||||
}
|
||||
|
||||
// ReadTxsFromInput reads multiples txs from the given filename(s). Can pass "-" to read from stdin.
|
||||
// Unlike ReadTxFromFile, this function does not decode the txs.
|
||||
func ReadTxsFromInput(txCfg client.TxConfig, filenames ...string) (scanner *BatchScanner, err error) {
|
||||
if len(filenames) == 0 {
|
||||
return nil, fmt.Errorf("no file name provided")
|
||||
}
|
||||
|
||||
var infile io.Reader = os.Stdin
|
||||
if filenames[0] != "-" {
|
||||
buf := new(bytes.Buffer)
|
||||
for _, f := range filenames {
|
||||
bytes, err := os.ReadFile(filepath.Clean(f))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't read %s: %w", f, err)
|
||||
}
|
||||
|
||||
if _, err := buf.WriteString(string(bytes)); err != nil {
|
||||
return nil, fmt.Errorf("couldn't write to merged file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
infile = buf
|
||||
}
|
||||
|
||||
return NewBatchScanner(txCfg, infile), nil
|
||||
}
|
||||
|
||||
// NewBatchScanner returns a new BatchScanner to read newline-delimited StdTx transactions from r.
|
||||
func NewBatchScanner(cfg client.TxConfig, r io.Reader) *BatchScanner {
|
||||
return &BatchScanner{Scanner: bufio.NewScanner(r), cfg: cfg}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user