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: support extension options for build tx (backport: #15992) #16317

Merged
merged 2 commits into from
May 28, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

* (baseapp) [#16290](https://github.com/cosmos/cosmos-sdk/pull/16290) Add circuit breaker setter in baseapp.
* (x/group) [#16191](https://github.com/cosmos/cosmos-sdk/pull/16191) Add EventProposalPruned event to group module whenever a proposal is pruned.
* (tx) [#15992](https://github.com/cosmos/cosmos-sdk/pull/15992) Add `WithExtensionOptions` in tx Factory to allow
julienrbrt marked this conversation as resolved.
Show resolved Hide resolved

### Improvements

Expand Down
28 changes: 28 additions & 0 deletions client/tx/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
Expand Down Expand Up @@ -41,6 +42,7 @@ type Factory struct {
feeGranter sdk.AccAddress
feePayer sdk.AccAddress
gasPrices sdk.DecCoins
extOptions []*codectypes.Any
signMode signing.SignMode
simulateAndExecute bool
preprocessTxHook client.PreprocessTxFn
Expand Down Expand Up @@ -279,6 +281,28 @@ func (f Factory) PreprocessTx(keyname string, builder client.TxBuilder) error {
return f.preprocessTxHook(f.chainID, key.GetType(), builder)
}

// WithExtensionOptions returns a Factory with given extension options added to the existing options,
// Example to add dynamic fee extension options:
//
// extOpt := ethermint.ExtensionOptionDynamicFeeTx{
// MaxPriorityPrice: sdk.NewInt(1000000),
// }
//
// extBytes, _ := extOpt.Marshal()
//
// extOpts := []*types.Any{
// {
// TypeUrl: "/ethermint.types.v1.ExtensionOptionDynamicFeeTx",
// Value: extBytes,
// },
// }
//
// txf.WithExtensionOptions(extOpts...)
func (f Factory) WithExtensionOptions(extOpts ...*codectypes.Any) Factory {
f.extOptions = extOpts
return f
}

// BuildUnsignedTx builds a transaction to be signed given a set of messages.
// Once created, the fee, memo, and messages are set.
func (f Factory) BuildUnsignedTx(msgs ...sdk.Msg) (client.TxBuilder, error) {
Expand Down Expand Up @@ -327,6 +351,10 @@ func (f Factory) BuildUnsignedTx(msgs ...sdk.Msg) (client.TxBuilder, error) {
tx.SetFeePayer(f.feePayer)
tx.SetTimeoutHeight(f.TimeoutHeight())

if etx, ok := tx.(client.ExtendedTxBuilder); ok {
etx.SetExtensionOptions(f.extOptions...)
}

return tx, nil
}

Expand Down
67 changes: 32 additions & 35 deletions client/tx/tx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing"
ante "github.com/cosmos/cosmos-sdk/x/auth/ante"
Expand Down Expand Up @@ -108,6 +109,16 @@ func TestCalculateGas(t *testing.T) {
}
}

func mockTxFactory(txCfg client.TxConfig) tx.Factory {
return tx.Factory{}.
WithTxConfig(txCfg).
WithAccountNumber(50).
WithSequence(23).
WithFees("50stake").
WithMemo("memo").
WithChainID("test-chain")
}

func TestBuildSimTx(t *testing.T) {
txCfg, cdc := newTestTxConfig(t)

Expand All @@ -117,17 +128,7 @@ func TestBuildSimTx(t *testing.T) {
path := hd.CreateHDPath(118, 0, 0).String()
_, _, err = kb.NewMnemonic("test_key1", keyring.English, path, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
require.NoError(t, err)

txf := tx.Factory{}.
WithTxConfig(txCfg).
WithAccountNumber(50).
WithSequence(23).
WithFees("50stake").
WithMemo("memo").
WithChainID("test-chain").
WithSignMode(txCfg.SignModeHandler().DefaultMode()).
WithKeybase(kb)

txf := mockTxFactory(txCfg).WithSignMode(txCfg.SignModeHandler().DefaultMode()).WithKeybase(kb)
msg := banktypes.NewMsgSend(sdk.AccAddress("from"), sdk.AccAddress("to"), nil)
bz, err := txf.BuildSimTx(msg)
require.NoError(t, err)
Expand All @@ -143,16 +144,7 @@ func TestBuildUnsignedTx(t *testing.T) {

_, _, err = kb.NewMnemonic("test_key1", keyring.English, path, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
require.NoError(t, err)

txf := tx.Factory{}.
WithTxConfig(txConfig).
WithAccountNumber(50).
WithSequence(23).
WithFees("50stake").
WithMemo("memo").
WithChainID("test-chain").
WithKeybase(kb)

txf := mockTxFactory(txConfig).WithKeybase(kb)
msg := banktypes.NewMsgSend(sdk.AccAddress("from"), sdk.AccAddress("to"), nil)
tx, err := txf.BuildUnsignedTx(msg)
require.NoError(t, err)
Expand All @@ -163,6 +155,23 @@ func TestBuildUnsignedTx(t *testing.T) {
require.Empty(t, sigs)
}

func TestBuildUnsignedTxWithWithExtensionOptions(t *testing.T) {
txCfg := moduletestutil.MakeBuilderTestTxConfig()
extOpts := []*codectypes.Any{
{
TypeUrl: "/test",
Value: []byte("test"),
},
}
txf := mockTxFactory(txCfg).WithExtensionOptions(extOpts...)
msg := banktypes.NewMsgSend(sdk.AccAddress("from"), sdk.AccAddress("to"), nil)
tx, err := txf.BuildUnsignedTx(msg)
require.NoError(t, err)
require.NotNil(t, tx)
txb := tx.(*moduletestutil.TestTxBuilder)
require.Equal(t, extOpts, txb.ExtOptions)
}

func TestMnemonicInMemo(t *testing.T) {
txConfig, cdc := newTestTxConfig(t)
kb, err := keyring.New(t.Name(), "test", t.TempDir(), nil, cdc)
Expand Down Expand Up @@ -239,13 +248,7 @@ func TestSign(t *testing.T) {
requireT.NotEqual(pubKey1.Bytes(), pubKey2.Bytes())
t.Log("Pub keys:", pubKey1, pubKey2)

txfNoKeybase := tx.Factory{}.
WithTxConfig(txConfig).
WithAccountNumber(50).
WithSequence(23).
WithFees("50stake").
WithMemo("memo").
WithChainID("test-chain")
txfNoKeybase := mockTxFactory(txConfig)
txfDirect := txfNoKeybase.
WithKeybase(kb).
WithSignMode(signingtypes.SignMode_SIGN_MODE_DIRECT)
Expand Down Expand Up @@ -406,13 +409,7 @@ func TestPreprocessHook(t *testing.T) {
return nil
})

txfDirect := tx.Factory{}.
WithTxConfig(txConfig).
WithAccountNumber(50).
WithSequence(23).
WithFees("50stake").
WithMemo("memo").
WithChainID("test-chain").
txfDirect := mockTxFactory(txConfig).
WithKeybase(kb).
WithSignMode(signingtypes.SignMode_SIGN_MODE_DIRECT).
WithPreprocessTxHook(preprocessHook)
Expand Down
7 changes: 7 additions & 0 deletions client/tx_config.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package client

import (
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/tx"
signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing"
Expand Down Expand Up @@ -48,4 +49,10 @@ type (
SetFeeGranter(feeGranter sdk.AccAddress)
AddAuxSignerData(tx.AuxSignerData) error
}

// ExtendedTxBuilder extends the TxBuilder interface,
// which is used to set extension options to be included in a transaction.
ExtendedTxBuilder interface {
SetExtensionOptions(extOpts ...*codectypes.Any)
}
)
35 changes: 35 additions & 0 deletions types/module/testutil/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,38 @@ func MakeTestEncodingConfig(modules ...module.AppModuleBasic) TestEncodingConfig

return encCfg
}

func MakeTestTxConfig() client.TxConfig {
interfaceRegistry := types.NewInterfaceRegistry()
cdc := codec.NewProtoCodec(interfaceRegistry)
return tx.NewTxConfig(cdc, tx.DefaultSignModes)
}

type TestBuilderTxConfig struct {
client.TxConfig
TxBuilder *TestTxBuilder
}

func MakeBuilderTestTxConfig() TestBuilderTxConfig {
return TestBuilderTxConfig{
TxConfig: MakeTestTxConfig(),
}
}

func (cfg TestBuilderTxConfig) NewTxBuilder() client.TxBuilder {
if cfg.TxBuilder == nil {
cfg.TxBuilder = &TestTxBuilder{
TxBuilder: cfg.TxConfig.NewTxBuilder(),
}
}
return cfg.TxBuilder
}

type TestTxBuilder struct {
client.TxBuilder
ExtOptions []*types.Any
}

func (b *TestTxBuilder) SetExtensionOptions(extOpts ...*types.Any) {
b.ExtOptions = extOpts
}