diff --git a/CHANGELOG.md b/CHANGELOG.md index bf3c871b02fa..c7b9f696a343 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements +* (client) [#16075](https://github.com/cosmos/cosmos-sdk/pull/16075) Partly revert [#15953](https://github.com/cosmos/cosmos-sdk/issues/15953) and `factory.Prepare` now does nothing in offline mode. * (server) [#15984](https://github.com/cosmos/cosmos-sdk/pull/15984) Use `cosmossdk.io/log` package for logging instead of CometBFT logger. NOTE: v0.45 and v0.46 were not using CometBFT logger either. This keeps the same underlying logger (zerolog) as in v0.45.x+ and v0.46.x+ but now properly supporting filtered logging. * (gov) [#15979](https://github.com/cosmos/cosmos-sdk/pull/15979) Improve gov error message when failing to convert v1 proposal to v1beta1. diff --git a/client/account_retriever.go b/client/account_retriever.go index 24de5423e2ea..ff5be9bc8589 100644 --- a/client/account_retriever.go +++ b/client/account_retriever.go @@ -28,7 +28,9 @@ var _ AccountRetriever = (*MockAccountRetriever)(nil) // MockAccountRetriever defines a no-op basic AccountRetriever that can be used // in mocked contexts. Tests or context that need more sophisticated testing // state should implement their own mock AccountRetriever. -type MockAccountRetriever struct{} +type MockAccountRetriever struct { + ReturnAccNum, ReturnAccSeq uint64 +} func (mar MockAccountRetriever) GetAccount(_ Context, _ sdk.AccAddress) (Account, error) { return nil, nil @@ -43,5 +45,5 @@ func (mar MockAccountRetriever) EnsureExists(_ Context, _ sdk.AccAddress) error } func (mar MockAccountRetriever) GetAccountNumberSequence(_ Context, _ sdk.AccAddress) (uint64, uint64, error) { - return 0, 0, nil + return mar.ReturnAccNum, mar.ReturnAccSeq, nil } diff --git a/client/tx/factory.go b/client/tx/factory.go index e9482bc854ad..99195f2c2170 100644 --- a/client/tx/factory.go +++ b/client/tx/factory.go @@ -430,9 +430,14 @@ func (f Factory) getSimPK() (cryptotypes.PubKey, error) { // Prepare ensures the account defined by ctx.GetFromAddress() exists and // if the account number and/or the account sequence number are zero (not set), -// they will be queried for and set on the provided Factory. A new Factory with -// the updated fields will be returned. +// they will be queried for and set on the provided Factory. +// A new Factory with the updated fields will be returned. +// Note: When in offline mode, the Prepare does nothing and returns the original factory. func (f Factory) Prepare(clientCtx client.Context) (Factory, error) { + if clientCtx.Offline { + return f, nil + } + fc := f from := clientCtx.GetFromAddress() @@ -441,14 +446,19 @@ func (f Factory) Prepare(clientCtx client.Context) (Factory, error) { } initNum, initSeq := fc.accountNumber, fc.sequence - if initNum == 0 && initSeq == 0 { + if initNum == 0 || initSeq == 0 { num, seq, err := fc.accountRetriever.GetAccountNumberSequence(clientCtx, from) if err != nil { return fc, err } - fc = fc.WithAccountNumber(num) - fc = fc.WithSequence(seq) + if initNum == 0 { + fc = fc.WithAccountNumber(num) + } + + if initSeq == 0 { + fc = fc.WithSequence(seq) + } } return fc, nil diff --git a/client/tx/factory_test.go b/client/tx/factory_test.go new file mode 100644 index 000000000000..7a8c4cc2dd46 --- /dev/null +++ b/client/tx/factory_test.go @@ -0,0 +1,34 @@ +package tx_test + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/stretchr/testify/require" +) + +func TestFactoryPrepate(t *testing.T) { + t.Parallel() + + factory := tx.Factory{} + clientCtx := client.Context{} + + output, err := factory.Prepare(clientCtx.WithOffline(true)) + require.NoError(t, err) + require.Equal(t, output, factory) + + factory = tx.Factory{}.WithAccountRetriever(client.MockAccountRetriever{ReturnAccNum: 10, ReturnAccSeq: 1}).WithAccountNumber(5) + output, err = factory.Prepare(clientCtx.WithFrom("foo")) + require.NoError(t, err) + require.NotEqual(t, output, factory) + require.Equal(t, output.AccountNumber(), uint64(5)) + require.Equal(t, output.Sequence(), uint64(1)) + + factory = tx.Factory{}.WithAccountRetriever(client.MockAccountRetriever{ReturnAccNum: 10, ReturnAccSeq: 1}) + output, err = factory.Prepare(clientCtx.WithFrom("foo")) + require.NoError(t, err) + require.NotEqual(t, output, factory) + require.Equal(t, output.AccountNumber(), uint64(10)) + require.Equal(t, output.Sequence(), uint64(1)) +}