Skip to content

Commit 7622e27

Browse files
committed
Merge tag 'v0.47.5' of https://github.com/cosmos/cosmos-sdk into upgrade/v0.47.x
Release v0.47.5
2 parents 609dc56 + 2e9e5d6 commit 7622e27

File tree

32 files changed

+392
-68
lines changed

32 files changed

+392
-68
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,24 @@ Ref: https://keepachangelog.com/en/1.0.0/
3737

3838
## [Unreleased]
3939

40+
## [v0.47.5](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.47.5) - 2023-09-01
41+
42+
### Features
43+
44+
* (client/rpc) [#17274](https://github.com/cosmos/cosmos-sdk/pull/17274) Add `QueryEventForTxCmd` cmd to subscribe and wait event for transaction by hash.
45+
* (keyring) [#17424](https://github.com/cosmos/cosmos-sdk/pull/17424) Allows to import private keys encoded in hex.
46+
4047
### Improvements
4148

49+
* (x/gov) [#17387](https://github.com/cosmos/cosmos-sdk/pull/17387) Add `MsgSubmitProposal` `SetMsgs` method.
4250
* (x/gov) [#17354](https://github.com/cosmos/cosmos-sdk/issues/17354) Emit `VoterAddr` in `proposal_vote` event.
4351
* (x/group, x/gov) [#17220](https://github.com/cosmos/cosmos-sdk/pull/17220) Add `--skip-metadata` flag in `draft-proposal` to skip metadata prompt.
4452
* (x/genutil) [#17296](https://github.com/cosmos/cosmos-sdk/pull/17296) Add `MigrateHandler` to allow reuse migrate genesis related function.
4553
* In v0.46, v0.47 this function is additive to the `genesis migrate` command. However in v0.50+, adding custom migrations to the `genesis migrate` command is directly possible.
4654

4755
### Bug Fixes
4856

57+
* (server) [#17181](https://github.com/cosmos/cosmos-sdk/pull/17181) Fix `db_backend` lookup fallback from `config.toml`.
4958
* (runtime) [#17284](https://github.com/cosmos/cosmos-sdk/pull/17284) Properly allow to combine depinject-enabled modules and non-depinject-enabled modules in app v2.
5059
* (baseapp) [#17159](https://github.com/cosmos/cosmos-sdk/pull/17159) Validators can propose blocks that exceed the gas limit.
5160
* (baseapp) [#16547](https://github.com/cosmos/cosmos-sdk/pull/16547) Ensure a transaction's gas limit cannot exceed the block gas limit.

RELEASE_NOTES.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
1-
# Cosmos SDK v0.47.4 Release Notes
1+
# Cosmos SDK v0.47.5 Release Notes
22

33
💬 [**Release Discussion**](https://github.com/orgs/cosmos/discussions/categories/announcements)
44

55
## 🚀 Highlights
66

7-
Missed the v0.47.0 announcement? Read it [here](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.47.0).
8-
For this fourth patch release of the `v0.47.x` line, some of the notable changes include:
7+
Get ready for v0.50.0 and start integrating with the next [Cosmos SDK](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.50.0-rc.0) release.
98

10-
* An improvement in `<appd> prune` UX.
11-
* Improving the error handling when there is a snapshot creation failure.
9+
For this 5th patch release of the `v0.47.x` line, some of the notable changes include:
1210

13-
Check out the [changelog](https://github.com/cosmos/cosmos-sdk/blob/v0.47.4/CHANGELOG.md) for an exhaustive list of changes or [compare changes](https://github.com/cosmos/cosmos-sdk/compare/release/v0.47.3...v0.47.4) from last release.
11+
* A new command for importing private keys encoded in hex. This complements the existing `import` command that supports mnemonic and key files.
12+
Use `<appd> keys import <name> <hex>` to import a private key encoded in hex.
13+
* A new command, `rpc.QueryEventForTxCmd` for querying a transaction by its hash and blocking until the transaction is included in a block. It is useful as an alternative to the legacy `--sync block`.
14+
15+
Check out the [changelog](https://github.com/cosmos/cosmos-sdk/blob/v0.47.5/CHANGELOG.md) for an exhaustive list of changes or [compare changes](https://github.com/cosmos/cosmos-sdk/compare/release/v0.47.4...v0.47.5) from last release.
1416

1517
Refer to the [upgrading guide](https://github.com/cosmos/cosmos-sdk/blob/release/v0.47.x/UPGRADING.md) when migrating from `v0.46.x` to `v0.47.0`.

client/keys/import.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,16 @@ package keys
22

33
import (
44
"bufio"
5+
"fmt"
56
"os"
67

78
"github.com/spf13/cobra"
89

910
"github.com/cosmos/cosmos-sdk/client"
11+
"github.com/cosmos/cosmos-sdk/client/flags"
1012
"github.com/cosmos/cosmos-sdk/client/input"
13+
"github.com/cosmos/cosmos-sdk/crypto/hd"
14+
"github.com/cosmos/cosmos-sdk/version"
1115
)
1216

1317
// ImportKeyCommand imports private keys from a keyfile.
@@ -38,3 +42,22 @@ func ImportKeyCommand() *cobra.Command {
3842
},
3943
}
4044
}
45+
46+
func ImportKeyHexCommand() *cobra.Command {
47+
cmd := &cobra.Command{
48+
Use: "import-hex <name> <hex>",
49+
Short: "Import private keys into the local keybase",
50+
Long: fmt.Sprintf("Import hex encoded private key into the local keybase.\nSupported key-types can be obtained with:\n%s list-key-types", version.AppName),
51+
Args: cobra.ExactArgs(2),
52+
RunE: func(cmd *cobra.Command, args []string) error {
53+
clientCtx, err := client.GetClientQueryContext(cmd)
54+
if err != nil {
55+
return err
56+
}
57+
keyType, _ := cmd.Flags().GetString(flags.FlagKeyType)
58+
return clientCtx.Keyring.ImportPrivKeyHex(args[0], args[1], keyType)
59+
},
60+
}
61+
cmd.Flags().String(flags.FlagKeyType, string(hd.Secp256k1Type), "private key signing algorithm kind")
62+
return cmd
63+
}

client/keys/import_test.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,60 @@ HbP+c6JmeJy9JXe2rbbF1QtCX1gLqGcDQPBXiCtFvP7/8wTZtVOPj8vREzhZ9ElO
115115
})
116116
}
117117
}
118+
119+
func Test_runImportHexCmd(t *testing.T) {
120+
cdc := clienttestutil.MakeTestCodec(t)
121+
testCases := []struct {
122+
name string
123+
keyringBackend string
124+
hexKey string
125+
keyType string
126+
expectError bool
127+
}{
128+
{
129+
name: "test backend success",
130+
keyringBackend: keyring.BackendTest,
131+
hexKey: "0xa3e57952e835ed30eea86a2993ac2a61c03e74f2085b3635bd94aa4d7ae0cfdf",
132+
keyType: "secp256k1",
133+
},
134+
}
135+
136+
for _, tc := range testCases {
137+
t.Run(tc.name, func(t *testing.T) {
138+
cmd := ImportKeyHexCommand()
139+
cmd.Flags().AddFlagSet(Commands("home").PersistentFlags())
140+
mockIn := testutil.ApplyMockIODiscardOutErr(cmd)
141+
142+
// Now add a temporary keybase
143+
kbHome := t.TempDir()
144+
kb, err := keyring.New(sdk.KeyringServiceName(), tc.keyringBackend, kbHome, nil, cdc)
145+
require.NoError(t, err)
146+
147+
clientCtx := client.Context{}.
148+
WithKeyringDir(kbHome).
149+
WithKeyring(kb).
150+
WithInput(mockIn).
151+
WithCodec(cdc)
152+
ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)
153+
154+
t.Cleanup(cleanupKeys(t, kb, "keyname1"))
155+
156+
defer func() {
157+
_ = os.RemoveAll(kbHome)
158+
}()
159+
160+
cmd.SetArgs([]string{
161+
"keyname1", tc.hexKey,
162+
fmt.Sprintf("--%s=%s", flags.FlagKeyType, tc.keyType),
163+
fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, tc.keyringBackend),
164+
})
165+
166+
err = cmd.ExecuteContext(ctx)
167+
if tc.expectError {
168+
require.Error(t, err)
169+
} else {
170+
require.NoError(t, err)
171+
}
172+
})
173+
}
174+
}

client/keys/root.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ The pass backend requires GnuPG: https://gnupg.org/
4242
AddKeyCommand(),
4343
ExportKeyCommand(),
4444
ImportKeyCommand(),
45+
ImportKeyHexCommand(),
4546
ListKeysCmd(),
4647
ListKeyTypesCmd(),
4748
ShowKeysCmd(),

client/keys/root_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@ func TestCommands(t *testing.T) {
1111
assert.Assert(t, rootCommands != nil)
1212

1313
// Commands are registered
14-
assert.Equal(t, 11, len(rootCommands.Commands()))
14+
assert.Equal(t, 12, len(rootCommands.Commands()))
1515
}

client/rpc/tx.go

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
package rpc
2+
3+
import (
4+
"context"
5+
"encoding/hex"
6+
"fmt"
7+
"strings"
8+
"time"
9+
10+
rpchttp "github.com/cometbft/cometbft/rpc/client/http"
11+
coretypes "github.com/cometbft/cometbft/rpc/core/types"
12+
tmtypes "github.com/cometbft/cometbft/types"
13+
"github.com/spf13/cobra"
14+
15+
"github.com/cosmos/cosmos-sdk/client"
16+
"github.com/cosmos/cosmos-sdk/client/flags"
17+
sdk "github.com/cosmos/cosmos-sdk/types"
18+
"github.com/cosmos/cosmos-sdk/types/errors"
19+
)
20+
21+
func newTxResponseCheckTx(res *coretypes.ResultBroadcastTxCommit) *sdk.TxResponse {
22+
if res == nil {
23+
return nil
24+
}
25+
26+
var txHash string
27+
if res.Hash != nil {
28+
txHash = res.Hash.String()
29+
}
30+
31+
parsedLogs, _ := sdk.ParseABCILogs(res.CheckTx.Log)
32+
33+
return &sdk.TxResponse{
34+
Height: res.Height,
35+
TxHash: txHash,
36+
Codespace: res.CheckTx.Codespace,
37+
Code: res.CheckTx.Code,
38+
Data: strings.ToUpper(hex.EncodeToString(res.CheckTx.Data)),
39+
RawLog: res.CheckTx.Log,
40+
Logs: parsedLogs,
41+
Info: res.CheckTx.Info,
42+
GasWanted: res.CheckTx.GasWanted,
43+
GasUsed: res.CheckTx.GasUsed,
44+
Events: res.CheckTx.Events,
45+
}
46+
}
47+
48+
func newTxResponseDeliverTx(res *coretypes.ResultBroadcastTxCommit) *sdk.TxResponse {
49+
if res == nil {
50+
return nil
51+
}
52+
53+
var txHash string
54+
if res.Hash != nil {
55+
txHash = res.Hash.String()
56+
}
57+
58+
parsedLogs, _ := sdk.ParseABCILogs(res.DeliverTx.Log)
59+
60+
return &sdk.TxResponse{
61+
Height: res.Height,
62+
TxHash: txHash,
63+
Codespace: res.DeliverTx.Codespace,
64+
Code: res.DeliverTx.Code,
65+
Data: strings.ToUpper(hex.EncodeToString(res.DeliverTx.Data)),
66+
RawLog: res.DeliverTx.Log,
67+
Logs: parsedLogs,
68+
Info: res.DeliverTx.Info,
69+
GasWanted: res.DeliverTx.GasWanted,
70+
GasUsed: res.DeliverTx.GasUsed,
71+
Events: res.DeliverTx.Events,
72+
}
73+
}
74+
75+
func newResponseFormatBroadcastTxCommit(res *coretypes.ResultBroadcastTxCommit) *sdk.TxResponse {
76+
if res == nil {
77+
return nil
78+
}
79+
80+
if !res.CheckTx.IsOK() {
81+
return newTxResponseCheckTx(res)
82+
}
83+
84+
return newTxResponseDeliverTx(res)
85+
}
86+
87+
// QueryEventForTxCmd returns a CLI command that subscribes to a WebSocket connection and waits for a transaction event with the given hash.
88+
func QueryEventForTxCmd() *cobra.Command {
89+
cmd := &cobra.Command{
90+
Use: "event-query-tx-for [hash]",
91+
Short: "Query for a transaction by hash",
92+
Long: `Subscribes to a CometBFT WebSocket connection and waits for a transaction event with the given hash.`,
93+
Args: cobra.ExactArgs(1),
94+
RunE: func(cmd *cobra.Command, args []string) error {
95+
clientCtx, err := client.GetClientTxContext(cmd)
96+
if err != nil {
97+
return err
98+
}
99+
c, err := rpchttp.New(clientCtx.NodeURI, "/websocket")
100+
if err != nil {
101+
return err
102+
}
103+
if err := c.Start(); err != nil {
104+
return err
105+
}
106+
defer c.Stop() //nolint:errcheck // ignore stop error
107+
108+
ctx, cancel := context.WithTimeout(context.Background(), time.Second*15)
109+
defer cancel()
110+
111+
hash := args[0]
112+
query := fmt.Sprintf("%s='%s' AND %s='%s'", tmtypes.EventTypeKey, tmtypes.EventTx, tmtypes.TxHashKey, hash)
113+
const subscriber = "subscriber"
114+
eventCh, err := c.Subscribe(ctx, subscriber, query)
115+
if err != nil {
116+
return fmt.Errorf("failed to subscribe to tx: %w", err)
117+
}
118+
defer c.UnsubscribeAll(context.Background(), subscriber) //nolint:errcheck // ignore unsubscribe error
119+
120+
select {
121+
case evt := <-eventCh:
122+
if txe, ok := evt.Data.(tmtypes.EventDataTx); ok {
123+
res := &coretypes.ResultBroadcastTxCommit{
124+
DeliverTx: txe.Result,
125+
Hash: tmtypes.Tx(txe.Tx).Hash(),
126+
Height: txe.Height,
127+
}
128+
return clientCtx.PrintProto(newResponseFormatBroadcastTxCommit(res))
129+
}
130+
case <-ctx.Done():
131+
return errors.ErrLogic.Wrapf("timed out waiting for event, the transaction could have already been included or wasn't yet included")
132+
}
133+
return nil
134+
},
135+
}
136+
137+
flags.AddTxFlagsToCmd(cmd)
138+
139+
return cmd
140+
}

core/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ go 1.19
55
require (
66
cosmossdk.io/api v0.3.1
77
cosmossdk.io/depinject v1.0.0-alpha.4
8-
cosmossdk.io/math v1.0.1
8+
cosmossdk.io/math v1.1.2
99
github.com/cosmos/cosmos-proto v1.0.0-beta.2
1010
github.com/stretchr/testify v1.8.4
1111
google.golang.org/grpc v1.55.0

crypto/keyring/keyring.go

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ const (
4343

4444
// temporary pass phrase for exporting a key during a key rename
4545
passPhrase = "temp"
46+
// prefix for exported hex private keys
47+
hexPrefix = "0x"
4648
)
4749

4850
var (
@@ -113,7 +115,8 @@ type Signer interface {
113115
type Importer interface {
114116
// ImportPrivKey imports ASCII armored passphrase-encrypted private keys.
115117
ImportPrivKey(uid, armor, passphrase string) error
116-
118+
// ImportPrivKeyHex imports hex encoded keys.
119+
ImportPrivKeyHex(uid, privKey, algoStr string) error
117120
// ImportPubKey imports ASCII armored public keys.
118121
ImportPubKey(uid string, armor string) error
119122
}
@@ -333,7 +336,30 @@ func (ks keystore) ImportPrivKey(uid, armor, passphrase string) error {
333336
return nil
334337
}
335338

336-
func (ks keystore) ImportPubKey(uid string, armor string) error {
339+
func (ks keystore) ImportPrivKeyHex(uid, privKey, algoStr string) error {
340+
if _, err := ks.Key(uid); err == nil {
341+
return fmt.Errorf("cannot overwrite key: %s", uid)
342+
}
343+
if privKey[:2] == hexPrefix {
344+
privKey = privKey[2:]
345+
}
346+
decodedPriv, err := hex.DecodeString(privKey)
347+
if err != nil {
348+
return err
349+
}
350+
algo, err := NewSigningAlgoFromString(algoStr, ks.options.SupportedAlgos)
351+
if err != nil {
352+
return err
353+
}
354+
priv := algo.Generate()(decodedPriv)
355+
_, err = ks.writeLocalKey(uid, priv)
356+
if err != nil {
357+
return err
358+
}
359+
return nil
360+
}
361+
362+
func (ks keystore) ImportPubKey(uid, armor string) error {
337363
if _, err := ks.Key(uid); err == nil {
338364
return fmt.Errorf("cannot overwrite key: %s", uid)
339365
}

0 commit comments

Comments
 (0)