feat: Add `fee.{payer,granter}` and `tip` fields to StdSignDoc (#10348)
* Add IsTipper * Use addr in signer data * Always populate addr in signer data * fi error messages * make proto gen * fix build * Add fields to sign docs and sign mode handler * Remove getSequence * Update x/auth/migrations/legacytx/stdtx.go Co-authored-by: Simon Warta <2603011+webmaster128@users.noreply.github.com> * Update x/auth/migrations/legacytx/stdsign.go Co-authored-by: Simon Warta <2603011+webmaster128@users.noreply.github.com> * Use addressCodec * NewTxConfig with addrCdc * REmove simapp.NewBech32 * Move bech32 stuff to x/auth/address * Add changelog * Move address.Codec to x/auth * Fix test * Add tests for tipper and feepayer * Rename tests * Add more tests * Empty tip test * Revert unwanted files * Less line diff * fix test * fix another test * Fix test * Update x/auth/migrations/legacytx/stdtx_test.go Co-authored-by: atheeshp <59333759+atheeshp@users.noreply.github.com> * Address reviews Co-authored-by: Simon Warta <2603011+webmaster128@users.noreply.github.com> Co-authored-by: atheeshp <59333759+atheeshp@users.noreply.github.com>
This commit is contained in:
parent
994219a4d2
commit
956d8b4915
|
@ -50,6 +50,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||||
* [\#10045](https://github.com/cosmos/cosmos-sdk/pull/10045) Revert [#8549](https://github.com/cosmos/cosmos-sdk/pull/8549). Do not route grpc queries through Tendermint.
|
* [\#10045](https://github.com/cosmos/cosmos-sdk/pull/10045) Revert [#8549](https://github.com/cosmos/cosmos-sdk/pull/8549). Do not route grpc queries through Tendermint.
|
||||||
* [\#10326](https://github.com/cosmos/cosmos-sdk/pull/10326) `x/authz` add query all grants by granter query.
|
* [\#10326](https://github.com/cosmos/cosmos-sdk/pull/10326) `x/authz` add query all grants by granter query.
|
||||||
* [\#10024](https://github.com/cosmos/cosmos-sdk/pull/10024) `store/cachekv` performance improvement by reduced growth factor for iterator ranging by using binary searches to find dirty items when unsorted key count >= 1024
|
* [\#10024](https://github.com/cosmos/cosmos-sdk/pull/10024) `store/cachekv` performance improvement by reduced growth factor for iterator ranging by using binary searches to find dirty items when unsorted key count >= 1024
|
||||||
|
* [\#10348](https://github.com/cosmos/cosmos-sdk/pull/10348) Add `fee.{payer,granter}` and `tip` fields to StdSignDoc for signing tipped transactions.
|
||||||
|
|
||||||
### API Breaking Changes
|
### API Breaking Changes
|
||||||
|
|
||||||
|
@ -98,8 +99,9 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||||
* Replace `baseapp.SetAnteHandler` with `baseapp.SetTxHandler`.
|
* Replace `baseapp.SetAnteHandler` with `baseapp.SetTxHandler`.
|
||||||
* Move Msg routers from BaseApp to middlewares.
|
* Move Msg routers from BaseApp to middlewares.
|
||||||
* Move Baseapp panic recovery into a middleware.
|
* Move Baseapp panic recovery into a middleware.
|
||||||
* Rename simulation helper methods `baseapp.{Check,Deliver}` to `baseapp.Sim{Check,Deliver}**.
|
* Rename simulation helper methods `baseapp.{Check,Deliver}` to `baseapp.Sim{Check,Deliver}**`.
|
||||||
* (x/gov) [\#10373](https://github.com/cosmos/cosmos-sdk/pull/10373) Removed gov `keeper.{MustMarshal, MustUnmarshal}`.
|
* (x/gov) [\#10373](https://github.com/cosmos/cosmos-sdk/pull/10373) Removed gov `keeper.{MustMarshal, MustUnmarshal}`.
|
||||||
|
* [\#10348](https://github.com/cosmos/cosmos-sdk/pull/10348) StdSignBytes takes a new argument of type `*tx.Tip` for signing over tips using LEGACY_AMINO_JSON.
|
||||||
|
|
||||||
|
|
||||||
### Client Breaking Changes
|
### Client Breaking Changes
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
package tx
|
||||||
|
|
||||||
|
import (
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TipTx defines the interface to be implemented by Txs that handle Tips.
|
||||||
|
type TipTx interface {
|
||||||
|
sdk.FeeTx
|
||||||
|
GetTip() *Tip
|
||||||
|
}
|
|
@ -43,7 +43,7 @@ func (stdTxSignModeHandler) GetSignBytes(mode signingtypes.SignMode, data signin
|
||||||
}
|
}
|
||||||
|
|
||||||
return StdSignBytes(
|
return StdSignBytes(
|
||||||
data.ChainID, data.AccountNumber, data.Sequence, stdTx.GetTimeoutHeight(), StdFee{Amount: stdTx.GetFee(), Gas: stdTx.GetGas()}, tx.GetMsgs(), stdTx.GetMemo(),
|
data.ChainID, data.AccountNumber, data.Sequence, stdTx.GetTimeoutHeight(), StdFee{Amount: stdTx.GetFee(), Gas: stdTx.GetGas()}, tx.GetMsgs(), stdTx.GetMemo(), nil,
|
||||||
), nil
|
), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ func TestLegacyAminoJSONHandler_GetSignBytes(t *testing.T) {
|
||||||
signBz, err := handler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, signingData, tx)
|
signBz, err := handler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, signingData, tx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
expectedSignBz := StdSignBytes(chainId, accNum, seqNum, timeoutHeight, fee, msgs, memo)
|
expectedSignBz := StdSignBytes(chainId, accNum, seqNum, timeoutHeight, fee, msgs, memo, nil)
|
||||||
|
|
||||||
require.Equal(t, expectedSignBz, signBz)
|
require.Equal(t, expectedSignBz, signBz)
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
|
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
|
"github.com/cosmos/cosmos-sdk/types/tx"
|
||||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -47,10 +48,11 @@ type StdSignDoc struct {
|
||||||
Memo string `json:"memo" yaml:"memo"`
|
Memo string `json:"memo" yaml:"memo"`
|
||||||
Fee json.RawMessage `json:"fee" yaml:"fee"`
|
Fee json.RawMessage `json:"fee" yaml:"fee"`
|
||||||
Msgs []json.RawMessage `json:"msgs" yaml:"msgs"`
|
Msgs []json.RawMessage `json:"msgs" yaml:"msgs"`
|
||||||
|
Tip *StdTip `json:"tip,omitempty" yaml:"tip"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// StdSignBytes returns the bytes to sign for a transaction.
|
// StdSignBytes returns the bytes to sign for a transaction.
|
||||||
func StdSignBytes(chainID string, accnum, sequence, timeout uint64, fee StdFee, msgs []sdk.Msg, memo string) []byte {
|
func StdSignBytes(chainID string, accnum, sequence, timeout uint64, fee StdFee, msgs []sdk.Msg, memo string, tip *tx.Tip) []byte {
|
||||||
msgsBytes := make([]json.RawMessage, 0, len(msgs))
|
msgsBytes := make([]json.RawMessage, 0, len(msgs))
|
||||||
for _, msg := range msgs {
|
for _, msg := range msgs {
|
||||||
legacyMsg, ok := msg.(LegacyMsg)
|
legacyMsg, ok := msg.(LegacyMsg)
|
||||||
|
@ -61,6 +63,15 @@ func StdSignBytes(chainID string, accnum, sequence, timeout uint64, fee StdFee,
|
||||||
msgsBytes = append(msgsBytes, json.RawMessage(legacyMsg.GetSignBytes()))
|
msgsBytes = append(msgsBytes, json.RawMessage(legacyMsg.GetSignBytes()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var stdTip *StdTip
|
||||||
|
if tip != nil {
|
||||||
|
if tip.Tipper == "" {
|
||||||
|
panic(fmt.Errorf("tipper cannot be empty"))
|
||||||
|
}
|
||||||
|
|
||||||
|
stdTip = &StdTip{Amount: tip.Amount, Tipper: tip.Tipper}
|
||||||
|
}
|
||||||
|
|
||||||
bz, err := legacy.Cdc.MarshalJSON(StdSignDoc{
|
bz, err := legacy.Cdc.MarshalJSON(StdSignDoc{
|
||||||
AccountNumber: accnum,
|
AccountNumber: accnum,
|
||||||
ChainID: chainID,
|
ChainID: chainID,
|
||||||
|
@ -69,6 +80,7 @@ func StdSignBytes(chainID string, accnum, sequence, timeout uint64, fee StdFee,
|
||||||
Msgs: msgsBytes,
|
Msgs: msgsBytes,
|
||||||
Sequence: sequence,
|
Sequence: sequence,
|
||||||
TimeoutHeight: timeout,
|
TimeoutHeight: timeout,
|
||||||
|
Tip: stdTip,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -106,7 +118,6 @@ func (ss StdSignature) MarshalYAML() (interface{}, error) {
|
||||||
pk = ss.PubKey.String()
|
pk = ss.PubKey.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bz, err := yaml.Marshal(struct {
|
bz, err := yaml.Marshal(struct {
|
||||||
PubKey string `json:"pub_key"`
|
PubKey string `json:"pub_key"`
|
||||||
Signature string `json:"signature"`
|
Signature string `json:"signature"`
|
||||||
|
|
|
@ -21,7 +21,7 @@ type StdSignMsg struct {
|
||||||
|
|
||||||
// get message bytes
|
// get message bytes
|
||||||
func (msg StdSignMsg) Bytes() []byte {
|
func (msg StdSignMsg) Bytes() []byte {
|
||||||
return StdSignBytes(msg.ChainID, msg.AccountNumber, msg.Sequence, msg.TimeoutHeight, msg.Fee, msg.Msgs, msg.Memo)
|
return StdSignBytes(msg.ChainID, msg.AccountNumber, msg.Sequence, msg.TimeoutHeight, msg.Fee, msg.Msgs, msg.Memo, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg StdSignMsg) UnpackInterfaces(unpacker types.AnyUnpacker) error {
|
func (msg StdSignMsg) UnpackInterfaces(unpacker types.AnyUnpacker) error {
|
||||||
|
|
|
@ -25,8 +25,10 @@ var (
|
||||||
// which must be above some miminum to be accepted into the mempool.
|
// which must be above some miminum to be accepted into the mempool.
|
||||||
// [Deprecated]
|
// [Deprecated]
|
||||||
type StdFee struct {
|
type StdFee struct {
|
||||||
Amount sdk.Coins `json:"amount" yaml:"amount"`
|
Amount sdk.Coins `json:"amount" yaml:"amount"`
|
||||||
Gas uint64 `json:"gas" yaml:"gas"`
|
Gas uint64 `json:"gas" yaml:"gas"`
|
||||||
|
Payer string `json:"payer,omitempty" yaml:"payer"`
|
||||||
|
Granter string `json:"granter,omitempty" yaml:"granter"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: NewStdFee returns a new instance of StdFee
|
// Deprecated: NewStdFee returns a new instance of StdFee
|
||||||
|
@ -70,6 +72,12 @@ func (fee StdFee) GasPrices() sdk.DecCoins {
|
||||||
return sdk.NewDecCoinsFromCoins(fee.Amount...).QuoDec(sdk.NewDec(int64(fee.Gas)))
|
return sdk.NewDecCoinsFromCoins(fee.Amount...).QuoDec(sdk.NewDec(int64(fee.Gas)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StdTip is the tips used in a tipped transaction.
|
||||||
|
type StdTip struct {
|
||||||
|
Amount sdk.Coins `json:"amount" yaml:"amount"`
|
||||||
|
Tipper string `json:"tipper" yaml:"tipper"`
|
||||||
|
}
|
||||||
|
|
||||||
// StdTx is the legacy transaction format for wrapping a Msg with Fee and Signatures.
|
// StdTx is the legacy transaction format for wrapping a Msg with Fee and Signatures.
|
||||||
// It only works with Amino, please prefer the new protobuf Tx in types/tx.
|
// It only works with Amino, please prefer the new protobuf Tx in types/tx.
|
||||||
// NOTE: the first signature is the fee payer (Signatures must not be nil).
|
// NOTE: the first signature is the fee payer (Signatures must not be nil).
|
||||||
|
|
|
@ -17,6 +17,7 @@ import (
|
||||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
|
"github.com/cosmos/cosmos-sdk/types/tx"
|
||||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -41,7 +42,7 @@ func NewTestStdFee() StdFee {
|
||||||
func NewTestTx(ctx sdk.Context, msgs []sdk.Msg, privs []cryptotypes.PrivKey, accNums []uint64, seqs []uint64, timeout uint64, fee StdFee) sdk.Tx {
|
func NewTestTx(ctx sdk.Context, msgs []sdk.Msg, privs []cryptotypes.PrivKey, accNums []uint64, seqs []uint64, timeout uint64, fee StdFee) sdk.Tx {
|
||||||
sigs := make([]StdSignature, len(privs))
|
sigs := make([]StdSignature, len(privs))
|
||||||
for i, priv := range privs {
|
for i, priv := range privs {
|
||||||
signBytes := StdSignBytes(ctx.ChainID(), accNums[i], seqs[i], timeout, fee, msgs, "")
|
signBytes := StdSignBytes(ctx.ChainID(), accNums[i], seqs[i], timeout, fee, msgs, "", nil)
|
||||||
|
|
||||||
sig, err := priv.Sign(signBytes)
|
sig, err := priv.Sign(signBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -80,24 +81,72 @@ func TestStdSignBytes(t *testing.T) {
|
||||||
fee StdFee
|
fee StdFee
|
||||||
msgs []sdk.Msg
|
msgs []sdk.Msg
|
||||||
memo string
|
memo string
|
||||||
|
tip *tx.Tip
|
||||||
}
|
}
|
||||||
defaultFee := NewTestStdFee()
|
defaultFee := NewTestStdFee()
|
||||||
|
defaultTip := &tx.Tip{Tipper: addr.String(), Amount: sdk.NewCoins(sdk.NewInt64Coin("tiptoken", 150))}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
|
name string
|
||||||
args args
|
args args
|
||||||
want string
|
want string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
args{"1234", 3, 6, 10, defaultFee, []sdk.Msg{testdata.NewTestMsg(addr)}, "memo"},
|
"with timeout height",
|
||||||
fmt.Sprintf("{\"account_number\":\"3\",\"chain_id\":\"1234\",\"fee\":{\"amount\":[{\"amount\":\"150\",\"denom\":\"atom\"}],\"gas\":\"100000\"},\"memo\":\"memo\",\"msgs\":[[\"%s\"]],\"sequence\":\"6\",\"timeout_height\":\"10\"}", addr),
|
args{"1234", 3, 6, 10, defaultFee, []sdk.Msg{testdata.NewTestMsg(addr)}, "memo", nil},
|
||||||
|
fmt.Sprintf(`{"account_number":"3","chain_id":"1234","fee":{"amount":[{"amount":"150","denom":"atom"}],"gas":"100000"},"memo":"memo","msgs":[["%s"]],"sequence":"6","timeout_height":"10"}`, addr),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
args{"1234", 3, 6, 0, defaultFee, []sdk.Msg{testdata.NewTestMsg(addr)}, "memo"},
|
"no timeout height (omitempty)",
|
||||||
fmt.Sprintf("{\"account_number\":\"3\",\"chain_id\":\"1234\",\"fee\":{\"amount\":[{\"amount\":\"150\",\"denom\":\"atom\"}],\"gas\":\"100000\"},\"memo\":\"memo\",\"msgs\":[[\"%s\"]],\"sequence\":\"6\"}", addr),
|
args{"1234", 3, 6, 0, defaultFee, []sdk.Msg{testdata.NewTestMsg(addr)}, "memo", nil},
|
||||||
|
fmt.Sprintf(`{"account_number":"3","chain_id":"1234","fee":{"amount":[{"amount":"150","denom":"atom"}],"gas":"100000"},"memo":"memo","msgs":[["%s"]],"sequence":"6"}`, addr),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"empty fee",
|
||||||
|
args{"1234", 3, 6, 0, StdFee{}, []sdk.Msg{testdata.NewTestMsg(addr)}, "memo", nil},
|
||||||
|
fmt.Sprintf(`{"account_number":"3","chain_id":"1234","fee":{"amount":[],"gas":"0"},"memo":"memo","msgs":[["%s"]],"sequence":"6"}`, addr),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"no fee payer and fee granter (both omitempty)",
|
||||||
|
args{"1234", 3, 6, 0, StdFee{Amount: defaultFee.Amount, Gas: defaultFee.Gas}, []sdk.Msg{testdata.NewTestMsg(addr)}, "memo", nil},
|
||||||
|
fmt.Sprintf(`{"account_number":"3","chain_id":"1234","fee":{"amount":[{"amount":"150","denom":"atom"}],"gas":"100000"},"memo":"memo","msgs":[["%s"]],"sequence":"6"}`, addr),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"with fee granter, no fee payer (omitempty)",
|
||||||
|
args{"1234", 3, 6, 0, StdFee{Amount: defaultFee.Amount, Gas: defaultFee.Gas, Granter: addr.String()}, []sdk.Msg{testdata.NewTestMsg(addr)}, "memo", nil},
|
||||||
|
fmt.Sprintf(`{"account_number":"3","chain_id":"1234","fee":{"amount":[{"amount":"150","denom":"atom"}],"gas":"100000","granter":"%s"},"memo":"memo","msgs":[["%s"]],"sequence":"6"}`, addr, addr),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"with fee payer, no fee granter (omitempty)",
|
||||||
|
args{"1234", 3, 6, 0, StdFee{Amount: defaultFee.Amount, Gas: defaultFee.Gas, Payer: addr.String()}, []sdk.Msg{testdata.NewTestMsg(addr)}, "memo", nil},
|
||||||
|
fmt.Sprintf(`{"account_number":"3","chain_id":"1234","fee":{"amount":[{"amount":"150","denom":"atom"}],"gas":"100000","payer":"%s"},"memo":"memo","msgs":[["%s"]],"sequence":"6"}`, addr, addr),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"with fee payer and fee granter",
|
||||||
|
args{"1234", 3, 6, 0, StdFee{Amount: defaultFee.Amount, Gas: defaultFee.Gas, Payer: addr.String(), Granter: addr.String()}, []sdk.Msg{testdata.NewTestMsg(addr)}, "memo", nil},
|
||||||
|
fmt.Sprintf(`{"account_number":"3","chain_id":"1234","fee":{"amount":[{"amount":"150","denom":"atom"}],"gas":"100000","granter":"%s","payer":"%s"},"memo":"memo","msgs":[["%s"]],"sequence":"6"}`, addr, addr, addr),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"no fee, with tip",
|
||||||
|
args{"1234", 3, 6, 0, StdFee{}, []sdk.Msg{testdata.NewTestMsg(addr)}, "memo", defaultTip},
|
||||||
|
fmt.Sprintf(`{"account_number":"3","chain_id":"1234","fee":{"amount":[],"gas":"0"},"memo":"memo","msgs":[["%s"]],"sequence":"6","tip":{"amount":[{"amount":"150","denom":"tiptoken"}],"tipper":"%s"}}`, addr, addr),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"with fee and with tip",
|
||||||
|
args{"1234", 3, 6, 0, StdFee{Amount: defaultFee.Amount, Gas: defaultFee.Gas, Payer: addr.String()}, []sdk.Msg{testdata.NewTestMsg(addr)}, "memo", defaultTip},
|
||||||
|
fmt.Sprintf(`{"account_number":"3","chain_id":"1234","fee":{"amount":[{"amount":"150","denom":"atom"}],"gas":"100000","payer":"%s"},"memo":"memo","msgs":[["%s"]],"sequence":"6","tip":{"amount":[{"amount":"150","denom":"tiptoken"}],"tipper":"%s"}}`, addr, addr, addr),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"with empty tip (but not nil), tipper cannot be empty",
|
||||||
|
args{"1234", 3, 6, 0, defaultFee, []sdk.Msg{testdata.NewTestMsg(addr)}, "memo", &tx.Tip{Tipper: addr.String()}},
|
||||||
|
fmt.Sprintf(`{"account_number":"3","chain_id":"1234","fee":{"amount":[{"amount":"150","denom":"atom"}],"gas":"100000"},"memo":"memo","msgs":[["%s"]],"sequence":"6","tip":{"amount":[],"tipper":"%s"}}`, addr, addr),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for i, tc := range tests {
|
for i, tc := range tests {
|
||||||
got := string(StdSignBytes(tc.args.chainID, tc.args.accnum, tc.args.sequence, tc.args.timeoutHeight, tc.args.fee, tc.args.msgs, tc.args.memo))
|
tc := tc
|
||||||
require.Equal(t, tc.want, got, "Got unexpected result on test case i: %d", i)
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
got := string(StdSignBytes(tc.args.chainID, tc.args.accnum, tc.args.sequence, tc.args.timeoutHeight, tc.args.fee, tc.args.msgs, tc.args.memo, tc.args.tip))
|
||||||
|
require.Equal(t, tc.want, got, "Got unexpected result on test case i: %d", i)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ func TestVerifySignature(t *testing.T) {
|
||||||
Sequence: acc.GetSequence(),
|
Sequence: acc.GetSequence(),
|
||||||
SignerIndex: 0,
|
SignerIndex: 0,
|
||||||
}
|
}
|
||||||
signBytes := legacytx.StdSignBytes(signerData.ChainID, signerData.AccountNumber, signerData.Sequence, 10, fee, msgs, memo)
|
signBytes := legacytx.StdSignBytes(signerData.ChainID, signerData.AccountNumber, signerData.Sequence, 10, fee, msgs, memo, nil)
|
||||||
signature, err := priv.Sign(signBytes)
|
signature, err := priv.Sign(signBytes)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ func TestVerifySignature(t *testing.T) {
|
||||||
multisigKey := kmultisig.NewLegacyAminoPubKey(2, pkSet)
|
multisigKey := kmultisig.NewLegacyAminoPubKey(2, pkSet)
|
||||||
multisignature := multisig.NewMultisig(2)
|
multisignature := multisig.NewMultisig(2)
|
||||||
msgs = []sdk.Msg{testdata.NewTestMsg(addr, addr1)}
|
msgs = []sdk.Msg{testdata.NewTestMsg(addr, addr1)}
|
||||||
multiSignBytes := legacytx.StdSignBytes(signerData.ChainID, signerData.AccountNumber, signerData.Sequence, 10, fee, msgs, memo)
|
multiSignBytes := legacytx.StdSignBytes(signerData.ChainID, signerData.AccountNumber, signerData.Sequence, 10, fee, msgs, memo, nil)
|
||||||
|
|
||||||
sig1, err := priv.Sign(multiSignBytes)
|
sig1, err := priv.Sign(multiSignBytes)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
|
@ -35,6 +35,7 @@ var (
|
||||||
_ client.TxBuilder = &wrapper{}
|
_ client.TxBuilder = &wrapper{}
|
||||||
_ middleware.HasExtensionOptionsTx = &wrapper{}
|
_ middleware.HasExtensionOptionsTx = &wrapper{}
|
||||||
_ ExtensionOptionsTxBuilder = &wrapper{}
|
_ ExtensionOptionsTxBuilder = &wrapper{}
|
||||||
|
_ tx.TipTx = &wrapper{}
|
||||||
)
|
)
|
||||||
|
|
||||||
// ExtensionOptionsTxBuilder defines a TxBuilder that can also set extensions.
|
// ExtensionOptionsTxBuilder defines a TxBuilder that can also set extensions.
|
||||||
|
@ -156,6 +157,10 @@ func (w *wrapper) FeeGranter() sdk.AccAddress {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *wrapper) GetTip() *tx.Tip {
|
||||||
|
return w.tx.AuthInfo.Tip
|
||||||
|
}
|
||||||
|
|
||||||
func (w *wrapper) GetMemo() string {
|
func (w *wrapper) GetMemo() string {
|
||||||
return w.tx.Body.Memo
|
return w.tx.Body.Memo
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ func (signModeDirectAuxHandler) GetSignBytes(
|
||||||
AccountNumber: data.AccountNumber,
|
AccountNumber: data.AccountNumber,
|
||||||
Sequence: data.Sequence,
|
Sequence: data.Sequence,
|
||||||
Tip: protoTx.tx.AuthInfo.Tip,
|
Tip: protoTx.tx.AuthInfo.Tip,
|
||||||
PublicKey: protoTx.tx.AuthInfo.SignerInfos[data.SignerIndex].PublicKey,
|
PublicKey: signerInfo.PublicKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
return signDocDirectAux.Marshal()
|
return signDocDirectAux.Marshal()
|
||||||
|
|
|
@ -46,9 +46,33 @@ func (s signModeLegacyAminoJSONHandler) GetSignBytes(mode signingtypes.SignMode,
|
||||||
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "%s does not support protobuf extension options", signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON)
|
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "%s does not support protobuf extension options", signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addr := data.Address
|
||||||
|
if addr == "" {
|
||||||
|
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "got empty address in %s handler", signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON)
|
||||||
|
}
|
||||||
|
|
||||||
|
tip := protoTx.GetTip()
|
||||||
|
isTipper := tip != nil && tip.Tipper == addr
|
||||||
|
|
||||||
|
// We set a convention that if the tipper signs with LEGACY_AMINO_JSON, then
|
||||||
|
// they sign over empty fees and 0 gas.
|
||||||
|
if isTipper {
|
||||||
|
return legacytx.StdSignBytes(
|
||||||
|
data.ChainID, data.AccountNumber, data.Sequence, protoTx.GetTimeoutHeight(),
|
||||||
|
// The tipper signs over 0 fee and 0 gas, no feepayer, no feegranter by convention.
|
||||||
|
legacytx.StdFee{},
|
||||||
|
tx.GetMsgs(), protoTx.GetMemo(), tip,
|
||||||
|
), nil
|
||||||
|
}
|
||||||
|
|
||||||
return legacytx.StdSignBytes(
|
return legacytx.StdSignBytes(
|
||||||
data.ChainID, data.AccountNumber, data.Sequence, protoTx.GetTimeoutHeight(),
|
data.ChainID, data.AccountNumber, data.Sequence, protoTx.GetTimeoutHeight(),
|
||||||
legacytx.StdFee{Amount: protoTx.GetFee(), Gas: protoTx.GetGas()},
|
legacytx.StdFee{
|
||||||
tx.GetMsgs(), protoTx.GetMemo(),
|
Amount: protoTx.GetFee(),
|
||||||
|
Gas: protoTx.GetGas(),
|
||||||
|
Payer: protoTx.tx.AuthInfo.Fee.Payer,
|
||||||
|
Granter: protoTx.tx.AuthInfo.Fee.Granter,
|
||||||
|
},
|
||||||
|
tx.GetMsgs(), protoTx.GetMemo(), tip,
|
||||||
), nil
|
), nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
cdctypes "github.com/cosmos/cosmos-sdk/codec/types"
|
cdctypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/types/tx"
|
||||||
signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing"
|
signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||||
"github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx"
|
"github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx"
|
||||||
"github.com/cosmos/cosmos-sdk/x/auth/signing"
|
"github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||||
|
@ -33,17 +34,79 @@ func buildTx(t *testing.T, bldr *wrapper) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLegacyAminoJSONHandler_GetSignBytes(t *testing.T) {
|
func TestLegacyAminoJSONHandler_GetSignBytes(t *testing.T) {
|
||||||
|
var (
|
||||||
|
chainId = "test-chain"
|
||||||
|
accNum uint64 = 7
|
||||||
|
seqNum uint64 = 7
|
||||||
|
tip *tx.Tip = &tx.Tip{Tipper: addr1.String(), Amount: coins}
|
||||||
|
)
|
||||||
|
|
||||||
|
testcases := []struct {
|
||||||
|
name string
|
||||||
|
signer string
|
||||||
|
malleate func(*wrapper)
|
||||||
|
expectedSignBz []byte
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"signer which is also fee payer (no tips)", addr1.String(),
|
||||||
|
func(w *wrapper) {},
|
||||||
|
legacytx.StdSignBytes(chainId, accNum, seqNum, timeout, legacytx.StdFee{Amount: coins, Gas: gas}, []sdk.Msg{msg}, memo, nil),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"signer which is also fee payer (with tips)", addr2.String(),
|
||||||
|
func(w *wrapper) { w.SetTip(tip) },
|
||||||
|
legacytx.StdSignBytes(chainId, accNum, seqNum, timeout, legacytx.StdFee{Amount: coins, Gas: gas}, []sdk.Msg{msg}, memo, tip),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"explicit fee payer", addr1.String(),
|
||||||
|
func(w *wrapper) { w.SetFeePayer(addr2) },
|
||||||
|
legacytx.StdSignBytes(chainId, accNum, seqNum, timeout, legacytx.StdFee{Amount: coins, Gas: gas, Payer: addr2.String()}, []sdk.Msg{msg}, memo, nil),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"explicit fee granter", addr1.String(),
|
||||||
|
func(w *wrapper) { w.SetFeeGranter(addr2) },
|
||||||
|
legacytx.StdSignBytes(chainId, accNum, seqNum, timeout, legacytx.StdFee{Amount: coins, Gas: gas, Granter: addr2.String()}, []sdk.Msg{msg}, memo, nil),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"explicit fee payer and fee granter", addr1.String(),
|
||||||
|
func(w *wrapper) {
|
||||||
|
w.SetFeePayer(addr2)
|
||||||
|
w.SetFeeGranter(addr2)
|
||||||
|
},
|
||||||
|
legacytx.StdSignBytes(chainId, accNum, seqNum, timeout, legacytx.StdFee{Amount: coins, Gas: gas, Payer: addr2.String(), Granter: addr2.String()}, []sdk.Msg{msg}, memo, nil),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"signer which is also tipper", addr1.String(),
|
||||||
|
func(w *wrapper) { w.SetTip(tip) },
|
||||||
|
legacytx.StdSignBytes(chainId, accNum, seqNum, timeout, legacytx.StdFee{}, []sdk.Msg{msg}, memo, tip),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
handler := signModeLegacyAminoJSONHandler{}
|
||||||
|
for _, tc := range testcases {
|
||||||
|
tc := tc
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
bldr := newBuilder()
|
||||||
|
buildTx(t, bldr)
|
||||||
|
tx := bldr.GetTx()
|
||||||
|
tc.malleate(bldr)
|
||||||
|
|
||||||
|
signingData := signing.SignerData{
|
||||||
|
Address: tc.signer,
|
||||||
|
ChainID: chainId,
|
||||||
|
AccountNumber: accNum,
|
||||||
|
Sequence: seqNum,
|
||||||
|
}
|
||||||
|
signBz, err := handler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, signingData, tx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Equal(t, tc.expectedSignBz, signBz)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
bldr := newBuilder()
|
bldr := newBuilder()
|
||||||
buildTx(t, bldr)
|
buildTx(t, bldr)
|
||||||
tx := bldr.GetTx()
|
tx := bldr.GetTx()
|
||||||
|
|
||||||
var (
|
|
||||||
chainId = "test-chain"
|
|
||||||
accNum uint64 = 7
|
|
||||||
seqNum uint64 = 7
|
|
||||||
)
|
|
||||||
|
|
||||||
handler := signModeLegacyAminoJSONHandler{}
|
|
||||||
signingData := signing.SignerData{
|
signingData := signing.SignerData{
|
||||||
Address: addr1.String(),
|
Address: addr1.String(),
|
||||||
ChainID: chainId,
|
ChainID: chainId,
|
||||||
|
@ -51,18 +114,9 @@ func TestLegacyAminoJSONHandler_GetSignBytes(t *testing.T) {
|
||||||
Sequence: seqNum,
|
Sequence: seqNum,
|
||||||
SignerIndex: 0,
|
SignerIndex: 0,
|
||||||
}
|
}
|
||||||
signBz, err := handler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, signingData, tx)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
expectedSignBz := legacytx.StdSignBytes(chainId, accNum, seqNum, timeout, legacytx.StdFee{
|
|
||||||
Amount: coins,
|
|
||||||
Gas: gas,
|
|
||||||
}, []sdk.Msg{msg}, memo)
|
|
||||||
|
|
||||||
require.Equal(t, expectedSignBz, signBz)
|
|
||||||
|
|
||||||
// expect error with wrong sign mode
|
// expect error with wrong sign mode
|
||||||
_, err = handler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_DIRECT, signingData, tx)
|
_, err := handler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_DIRECT, signingData, tx)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
|
|
||||||
// expect error with extension options
|
// expect error with extension options
|
||||||
|
@ -72,7 +126,7 @@ func TestLegacyAminoJSONHandler_GetSignBytes(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
bldr.tx.Body.ExtensionOptions = []*cdctypes.Any{any}
|
bldr.tx.Body.ExtensionOptions = []*cdctypes.Any{any}
|
||||||
tx = bldr.GetTx()
|
tx = bldr.GetTx()
|
||||||
signBz, err = handler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, signingData, tx)
|
_, err = handler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, signingData, tx)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
|
|
||||||
// expect error with non-critical extension options
|
// expect error with non-critical extension options
|
||||||
|
@ -80,7 +134,7 @@ func TestLegacyAminoJSONHandler_GetSignBytes(t *testing.T) {
|
||||||
buildTx(t, bldr)
|
buildTx(t, bldr)
|
||||||
bldr.tx.Body.NonCriticalExtensionOptions = []*cdctypes.Any{any}
|
bldr.tx.Body.NonCriticalExtensionOptions = []*cdctypes.Any{any}
|
||||||
tx = bldr.GetTx()
|
tx = bldr.GetTx()
|
||||||
signBz, err = handler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, signingData, tx)
|
_, err = handler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, signingData, tx)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue