2020-07-06 10:03:45 -07:00
package tx
import (
2020-07-25 01:10:04 -07:00
"github.com/gogo/protobuf/proto"
2020-07-06 10:03:45 -07:00
"github.com/cosmos/cosmos-sdk/client"
feat: Add AuxTxBuilder (#10455)
<!--
The default pull request template is for types feat, fix, or refactor.
For other templates, add one of the following parameters to the url:
- template=docs.md
- template=other.md
-->
## Description
Closes: #10443
For creating an intermediary/auxiliary tx (e.g. by the tipper in tipped transactions), using the existing `client.TxBuilder` is awkward. We propose a new client-side builder for this purpose.
API Usage (e.g. how the tipper would programmtically use this):
```go
// Note: there's no need to use clientCtx.TxConfig anymore!
bldr := clienttx.NewAuxTxBuilder()
err := bldr.SetMsgs(msgs...)
bldr.SetAddress("cosmos1...")
bldr.SetMemo(...)
bldr.SetTip(...)
bldr.SetPubKey(...)
err := bldr.SetSignMode(...) // DIRECT_AUX or AMINO, or else error
// ... other setters are available
// Get the bytes to sign.
signBz, err := bldr.GetSignBytes()
// Sign the bz using your favorite method.
sig, err := privKey.sign(signBz)
// Set the signature
bldr.SetSig(sig)
// Get the final auxSignerData to be sent to the fee payer
auxSignerData, err:= bldr.GetAuxSignerData()
```
auxSignerData is a protobuf message, whose JSON reprensentation looks like:
```json
{
"address": "cosmos1...",
"mode": "SIGN_MODE_{DIRECT_AUX,LEGACY_AMINO_JSON}",
"sign_doc": {
"body_bytes": "{base64 bytes}",
"public_key": {
"@type": "cosmos.sepc256k1.PubKey",
"key": "{base64 bytes}"
},
"chain_id": "...",
"account_number": 24,
"sequence": 42,
"tip": {
"amount": [{ "denom": "uregen", "amount": 1000 }],
"tipper": "cosmos1..."
}
},
"sig": "{base64 bytes}"
}
```
Then the fee payer would use the TxBuilder to construct the final TX, with a new helper method: `AddAuxSignerData`:
```go
// get auxSignerData from AuxTxBuilder
auxSignerData := ...
txBuilder := txConfig.NewTxBuilder()
err := txBuilder.AddAuxSignerData(auxSignerData)
// Set fee payer data
txBuilder.SetFee()
txBuilder.SetGasLimit()
txBuilder.SetFeePayer()
sigs, err := txBuilder.GetSignaturesV2()
auxSig := sigs[0] // the aux signer's signature
// Set all signer infos (1st round of calling SetSignatures)
txBuilder.SetSignatures(
auxSig, // The aux SignatureV2
signing.SignatureV2{...}, // The feePayer's SignatureV2
)
// Sign
signBz, err = encCfg.TxConfig.SignModeHandler().GetSignBytes(...)
feepayerSig, err := feepayerPriv.Sign(signBz)
// Set all signatures (2nd round of calling SetSignatures)
txBuilder.SetSignatures(
auxSig, // The aux SignatureV2
signing.SignatureV2{feepayerSig, ...}, // The feePayer's SignatureV2
)
```
---
### Author Checklist
*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*
I have...
- [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] added `!` to the type prefix if API or client breaking change
- [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting))
- [ ] provided a link to the relevant issue or specification
- [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules)
- [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing)
- [ ] added a changelog entry to `CHANGELOG.md`
- [ ] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [ ] updated the relevant documentation or specification
- [ ] reviewed "Files changed" and left comments if necessary
- [ ] confirmed all CI checks have passed
### Reviewers Checklist
*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*
I have...
- [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [ ] manually tested (if applicable)
2021-11-11 03:25:13 -08:00
"github.com/cosmos/cosmos-sdk/codec"
2020-07-06 10:03:45 -07:00
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
2020-11-09 08:01:43 -08:00
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
2020-07-06 10:03:45 -07:00
sdk "github.com/cosmos/cosmos-sdk/types"
2021-03-09 23:16:04 -08:00
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
2020-07-29 08:52:22 -07:00
"github.com/cosmos/cosmos-sdk/types/tx"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
2021-10-01 07:30:22 -07:00
"github.com/cosmos/cosmos-sdk/x/auth/middleware"
2020-07-29 08:52:22 -07:00
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
2020-07-06 10:03:45 -07:00
)
2020-08-24 07:41:08 -07:00
// wrapper is a wrapper around the tx.Tx proto.Message which retain the raw
// body and auth_info bytes.
type wrapper struct {
feat: Add AuxTxBuilder (#10455)
<!--
The default pull request template is for types feat, fix, or refactor.
For other templates, add one of the following parameters to the url:
- template=docs.md
- template=other.md
-->
## Description
Closes: #10443
For creating an intermediary/auxiliary tx (e.g. by the tipper in tipped transactions), using the existing `client.TxBuilder` is awkward. We propose a new client-side builder for this purpose.
API Usage (e.g. how the tipper would programmtically use this):
```go
// Note: there's no need to use clientCtx.TxConfig anymore!
bldr := clienttx.NewAuxTxBuilder()
err := bldr.SetMsgs(msgs...)
bldr.SetAddress("cosmos1...")
bldr.SetMemo(...)
bldr.SetTip(...)
bldr.SetPubKey(...)
err := bldr.SetSignMode(...) // DIRECT_AUX or AMINO, or else error
// ... other setters are available
// Get the bytes to sign.
signBz, err := bldr.GetSignBytes()
// Sign the bz using your favorite method.
sig, err := privKey.sign(signBz)
// Set the signature
bldr.SetSig(sig)
// Get the final auxSignerData to be sent to the fee payer
auxSignerData, err:= bldr.GetAuxSignerData()
```
auxSignerData is a protobuf message, whose JSON reprensentation looks like:
```json
{
"address": "cosmos1...",
"mode": "SIGN_MODE_{DIRECT_AUX,LEGACY_AMINO_JSON}",
"sign_doc": {
"body_bytes": "{base64 bytes}",
"public_key": {
"@type": "cosmos.sepc256k1.PubKey",
"key": "{base64 bytes}"
},
"chain_id": "...",
"account_number": 24,
"sequence": 42,
"tip": {
"amount": [{ "denom": "uregen", "amount": 1000 }],
"tipper": "cosmos1..."
}
},
"sig": "{base64 bytes}"
}
```
Then the fee payer would use the TxBuilder to construct the final TX, with a new helper method: `AddAuxSignerData`:
```go
// get auxSignerData from AuxTxBuilder
auxSignerData := ...
txBuilder := txConfig.NewTxBuilder()
err := txBuilder.AddAuxSignerData(auxSignerData)
// Set fee payer data
txBuilder.SetFee()
txBuilder.SetGasLimit()
txBuilder.SetFeePayer()
sigs, err := txBuilder.GetSignaturesV2()
auxSig := sigs[0] // the aux signer's signature
// Set all signer infos (1st round of calling SetSignatures)
txBuilder.SetSignatures(
auxSig, // The aux SignatureV2
signing.SignatureV2{...}, // The feePayer's SignatureV2
)
// Sign
signBz, err = encCfg.TxConfig.SignModeHandler().GetSignBytes(...)
feepayerSig, err := feepayerPriv.Sign(signBz)
// Set all signatures (2nd round of calling SetSignatures)
txBuilder.SetSignatures(
auxSig, // The aux SignatureV2
signing.SignatureV2{feepayerSig, ...}, // The feePayer's SignatureV2
)
```
---
### Author Checklist
*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*
I have...
- [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] added `!` to the type prefix if API or client breaking change
- [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting))
- [ ] provided a link to the relevant issue or specification
- [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules)
- [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing)
- [ ] added a changelog entry to `CHANGELOG.md`
- [ ] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [ ] updated the relevant documentation or specification
- [ ] reviewed "Files changed" and left comments if necessary
- [ ] confirmed all CI checks have passed
### Reviewers Checklist
*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*
I have...
- [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [ ] manually tested (if applicable)
2021-11-11 03:25:13 -08:00
cdc codec . Codec
2020-07-06 10:03:45 -07:00
tx * tx . Tx
// bodyBz represents the protobuf encoding of TxBody. This should be encoding
// from the client using TxRaw if the tx was decoded from the wire
bodyBz [ ] byte
// authInfoBz represents the protobuf encoding of TxBody. This should be encoding
// from the client using TxRaw if the tx was decoded from the wire
authInfoBz [ ] byte
2020-08-03 12:47:25 -07:00
txBodyHasUnknownNonCriticals bool
2020-07-06 10:03:45 -07:00
}
var (
2021-10-01 07:30:22 -07:00
_ authsigning . Tx = & wrapper { }
_ client . TxBuilder = & wrapper { }
2021-12-07 10:02:21 -08:00
_ tx . TipTx = & wrapper { }
2021-10-01 07:30:22 -07:00
_ middleware . HasExtensionOptionsTx = & wrapper { }
_ ExtensionOptionsTxBuilder = & wrapper { }
2021-10-22 06:13:37 -07:00
_ tx . TipTx = & wrapper { }
2020-07-06 10:03:45 -07:00
)
2020-08-24 07:41:08 -07:00
// ExtensionOptionsTxBuilder defines a TxBuilder that can also set extensions.
2020-08-18 06:44:56 -07:00
type ExtensionOptionsTxBuilder interface {
client . TxBuilder
SetExtensionOptions ( ... * codectypes . Any )
SetNonCriticalExtensionOptions ( ... * codectypes . Any )
}
feat: Add AuxTxBuilder (#10455)
<!--
The default pull request template is for types feat, fix, or refactor.
For other templates, add one of the following parameters to the url:
- template=docs.md
- template=other.md
-->
## Description
Closes: #10443
For creating an intermediary/auxiliary tx (e.g. by the tipper in tipped transactions), using the existing `client.TxBuilder` is awkward. We propose a new client-side builder for this purpose.
API Usage (e.g. how the tipper would programmtically use this):
```go
// Note: there's no need to use clientCtx.TxConfig anymore!
bldr := clienttx.NewAuxTxBuilder()
err := bldr.SetMsgs(msgs...)
bldr.SetAddress("cosmos1...")
bldr.SetMemo(...)
bldr.SetTip(...)
bldr.SetPubKey(...)
err := bldr.SetSignMode(...) // DIRECT_AUX or AMINO, or else error
// ... other setters are available
// Get the bytes to sign.
signBz, err := bldr.GetSignBytes()
// Sign the bz using your favorite method.
sig, err := privKey.sign(signBz)
// Set the signature
bldr.SetSig(sig)
// Get the final auxSignerData to be sent to the fee payer
auxSignerData, err:= bldr.GetAuxSignerData()
```
auxSignerData is a protobuf message, whose JSON reprensentation looks like:
```json
{
"address": "cosmos1...",
"mode": "SIGN_MODE_{DIRECT_AUX,LEGACY_AMINO_JSON}",
"sign_doc": {
"body_bytes": "{base64 bytes}",
"public_key": {
"@type": "cosmos.sepc256k1.PubKey",
"key": "{base64 bytes}"
},
"chain_id": "...",
"account_number": 24,
"sequence": 42,
"tip": {
"amount": [{ "denom": "uregen", "amount": 1000 }],
"tipper": "cosmos1..."
}
},
"sig": "{base64 bytes}"
}
```
Then the fee payer would use the TxBuilder to construct the final TX, with a new helper method: `AddAuxSignerData`:
```go
// get auxSignerData from AuxTxBuilder
auxSignerData := ...
txBuilder := txConfig.NewTxBuilder()
err := txBuilder.AddAuxSignerData(auxSignerData)
// Set fee payer data
txBuilder.SetFee()
txBuilder.SetGasLimit()
txBuilder.SetFeePayer()
sigs, err := txBuilder.GetSignaturesV2()
auxSig := sigs[0] // the aux signer's signature
// Set all signer infos (1st round of calling SetSignatures)
txBuilder.SetSignatures(
auxSig, // The aux SignatureV2
signing.SignatureV2{...}, // The feePayer's SignatureV2
)
// Sign
signBz, err = encCfg.TxConfig.SignModeHandler().GetSignBytes(...)
feepayerSig, err := feepayerPriv.Sign(signBz)
// Set all signatures (2nd round of calling SetSignatures)
txBuilder.SetSignatures(
auxSig, // The aux SignatureV2
signing.SignatureV2{feepayerSig, ...}, // The feePayer's SignatureV2
)
```
---
### Author Checklist
*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*
I have...
- [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] added `!` to the type prefix if API or client breaking change
- [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting))
- [ ] provided a link to the relevant issue or specification
- [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules)
- [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing)
- [ ] added a changelog entry to `CHANGELOG.md`
- [ ] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [ ] updated the relevant documentation or specification
- [ ] reviewed "Files changed" and left comments if necessary
- [ ] confirmed all CI checks have passed
### Reviewers Checklist
*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*
I have...
- [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [ ] manually tested (if applicable)
2021-11-11 03:25:13 -08:00
func newBuilder ( cdc codec . Codec ) * wrapper {
2020-08-24 07:41:08 -07:00
return & wrapper {
feat: Add AuxTxBuilder (#10455)
<!--
The default pull request template is for types feat, fix, or refactor.
For other templates, add one of the following parameters to the url:
- template=docs.md
- template=other.md
-->
## Description
Closes: #10443
For creating an intermediary/auxiliary tx (e.g. by the tipper in tipped transactions), using the existing `client.TxBuilder` is awkward. We propose a new client-side builder for this purpose.
API Usage (e.g. how the tipper would programmtically use this):
```go
// Note: there's no need to use clientCtx.TxConfig anymore!
bldr := clienttx.NewAuxTxBuilder()
err := bldr.SetMsgs(msgs...)
bldr.SetAddress("cosmos1...")
bldr.SetMemo(...)
bldr.SetTip(...)
bldr.SetPubKey(...)
err := bldr.SetSignMode(...) // DIRECT_AUX or AMINO, or else error
// ... other setters are available
// Get the bytes to sign.
signBz, err := bldr.GetSignBytes()
// Sign the bz using your favorite method.
sig, err := privKey.sign(signBz)
// Set the signature
bldr.SetSig(sig)
// Get the final auxSignerData to be sent to the fee payer
auxSignerData, err:= bldr.GetAuxSignerData()
```
auxSignerData is a protobuf message, whose JSON reprensentation looks like:
```json
{
"address": "cosmos1...",
"mode": "SIGN_MODE_{DIRECT_AUX,LEGACY_AMINO_JSON}",
"sign_doc": {
"body_bytes": "{base64 bytes}",
"public_key": {
"@type": "cosmos.sepc256k1.PubKey",
"key": "{base64 bytes}"
},
"chain_id": "...",
"account_number": 24,
"sequence": 42,
"tip": {
"amount": [{ "denom": "uregen", "amount": 1000 }],
"tipper": "cosmos1..."
}
},
"sig": "{base64 bytes}"
}
```
Then the fee payer would use the TxBuilder to construct the final TX, with a new helper method: `AddAuxSignerData`:
```go
// get auxSignerData from AuxTxBuilder
auxSignerData := ...
txBuilder := txConfig.NewTxBuilder()
err := txBuilder.AddAuxSignerData(auxSignerData)
// Set fee payer data
txBuilder.SetFee()
txBuilder.SetGasLimit()
txBuilder.SetFeePayer()
sigs, err := txBuilder.GetSignaturesV2()
auxSig := sigs[0] // the aux signer's signature
// Set all signer infos (1st round of calling SetSignatures)
txBuilder.SetSignatures(
auxSig, // The aux SignatureV2
signing.SignatureV2{...}, // The feePayer's SignatureV2
)
// Sign
signBz, err = encCfg.TxConfig.SignModeHandler().GetSignBytes(...)
feepayerSig, err := feepayerPriv.Sign(signBz)
// Set all signatures (2nd round of calling SetSignatures)
txBuilder.SetSignatures(
auxSig, // The aux SignatureV2
signing.SignatureV2{feepayerSig, ...}, // The feePayer's SignatureV2
)
```
---
### Author Checklist
*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*
I have...
- [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] added `!` to the type prefix if API or client breaking change
- [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting))
- [ ] provided a link to the relevant issue or specification
- [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules)
- [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing)
- [ ] added a changelog entry to `CHANGELOG.md`
- [ ] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [ ] updated the relevant documentation or specification
- [ ] reviewed "Files changed" and left comments if necessary
- [ ] confirmed all CI checks have passed
### Reviewers Checklist
*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*
I have...
- [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [ ] manually tested (if applicable)
2021-11-11 03:25:13 -08:00
cdc : cdc ,
2020-07-06 10:03:45 -07:00
tx : & tx . Tx {
Body : & tx . TxBody { } ,
AuthInfo : & tx . AuthInfo {
Fee : & tx . Fee { } ,
} ,
} ,
}
}
2020-08-24 07:41:08 -07:00
func ( w * wrapper ) GetMsgs ( ) [ ] sdk . Msg {
2020-09-10 11:26:47 -07:00
return w . tx . GetMsgs ( )
2020-07-06 10:03:45 -07:00
}
2020-08-24 07:41:08 -07:00
func ( w * wrapper ) ValidateBasic ( ) error {
2020-09-10 11:26:47 -07:00
return w . tx . ValidateBasic ( )
2020-07-06 10:03:45 -07:00
}
2020-08-24 07:41:08 -07:00
func ( w * wrapper ) getBodyBytes ( ) [ ] byte {
if len ( w . bodyBz ) == 0 {
2020-07-06 10:03:45 -07:00
// if bodyBz is empty, then marshal the body. bodyBz will generally
// be set to nil whenever SetBody is called so the result of calling
// this method should always return the correct bytes. Note that after
// decoding bodyBz is derived from TxRaw so that it matches what was
// transmitted over the wire
2020-07-25 01:10:04 -07:00
var err error
2020-08-24 07:41:08 -07:00
w . bodyBz , err = proto . Marshal ( w . tx . Body )
2020-07-25 01:10:04 -07:00
if err != nil {
panic ( err )
}
2020-07-06 10:03:45 -07:00
}
2020-08-24 07:41:08 -07:00
return w . bodyBz
2020-07-06 10:03:45 -07:00
}
2020-08-24 07:41:08 -07:00
func ( w * wrapper ) getAuthInfoBytes ( ) [ ] byte {
if len ( w . authInfoBz ) == 0 {
2020-07-06 10:03:45 -07:00
// if authInfoBz is empty, then marshal the body. authInfoBz will generally
// be set to nil whenever SetAuthInfo is called so the result of calling
// this method should always return the correct bytes. Note that after
// decoding authInfoBz is derived from TxRaw so that it matches what was
// transmitted over the wire
2020-07-25 01:10:04 -07:00
var err error
2020-08-24 07:41:08 -07:00
w . authInfoBz , err = proto . Marshal ( w . tx . AuthInfo )
2020-07-25 01:10:04 -07:00
if err != nil {
panic ( err )
}
2020-07-06 10:03:45 -07:00
}
2020-08-24 07:41:08 -07:00
return w . authInfoBz
2020-07-06 10:03:45 -07:00
}
2020-08-24 07:41:08 -07:00
func ( w * wrapper ) GetSigners ( ) [ ] sdk . AccAddress {
2020-09-10 11:26:47 -07:00
return w . tx . GetSigners ( )
2020-07-06 10:03:45 -07:00
}
2021-03-09 23:16:04 -08:00
func ( w * wrapper ) GetPubKeys ( ) ( [ ] cryptotypes . PubKey , error ) {
2020-09-21 09:48:28 -07:00
signerInfos := w . tx . AuthInfo . SignerInfos
2020-11-09 08:01:43 -08:00
pks := make ( [ ] cryptotypes . PubKey , len ( signerInfos ) )
2020-07-06 10:03:45 -07:00
2020-09-21 09:48:28 -07:00
for i , si := range signerInfos {
// NOTE: it is okay to leave this nil if there is no PubKey in the SignerInfo.
// PubKey's can be left unset in SignerInfo.
if si . PublicKey == nil {
continue
2020-07-06 10:03:45 -07:00
}
2021-03-09 23:16:04 -08:00
pkAny := si . PublicKey . GetCachedValue ( )
pk , ok := pkAny . ( cryptotypes . PubKey )
2020-09-21 09:48:28 -07:00
if ok {
pks [ i ] = pk
2021-03-09 23:16:04 -08:00
} else {
return nil , sdkerrors . Wrapf ( sdkerrors . ErrLogic , "Expecting PubKey, got: %T" , pkAny )
2020-09-21 09:48:28 -07:00
}
2020-07-06 10:03:45 -07:00
}
2021-03-09 23:16:04 -08:00
return pks , nil
2020-07-06 10:03:45 -07:00
}
2020-08-24 07:41:08 -07:00
func ( w * wrapper ) GetGas ( ) uint64 {
return w . tx . AuthInfo . Fee . GasLimit
2020-07-06 10:03:45 -07:00
}
2020-08-24 07:41:08 -07:00
func ( w * wrapper ) GetFee ( ) sdk . Coins {
return w . tx . AuthInfo . Fee . Amount
2020-07-06 10:03:45 -07:00
}
2020-08-24 07:41:08 -07:00
func ( w * wrapper ) FeePayer ( ) sdk . AccAddress {
2020-09-30 02:03:44 -07:00
feePayer := w . tx . AuthInfo . Fee . Payer
if feePayer != "" {
payerAddr , err := sdk . AccAddressFromBech32 ( feePayer )
if err != nil {
panic ( err )
}
return payerAddr
}
// use first signer as default if no payer specified
2020-08-24 07:41:08 -07:00
return w . GetSigners ( ) [ 0 ]
2020-07-06 10:03:45 -07:00
}
2020-10-05 14:56:09 -07:00
func ( w * wrapper ) FeeGranter ( ) sdk . AccAddress {
feePayer := w . tx . AuthInfo . Fee . Granter
if feePayer != "" {
granterAddr , err := sdk . AccAddressFromBech32 ( feePayer )
if err != nil {
panic ( err )
}
return granterAddr
}
return nil
}
2021-10-22 06:13:37 -07:00
func ( w * wrapper ) GetTip ( ) * tx . Tip {
return w . tx . AuthInfo . Tip
}
2020-08-24 07:41:08 -07:00
func ( w * wrapper ) GetMemo ( ) string {
return w . tx . Body . Memo
2020-07-06 10:03:45 -07:00
}
2020-08-07 16:32:22 -07:00
// GetTimeoutHeight returns the transaction's timeout height (if set).
2020-08-24 07:41:08 -07:00
func ( w * wrapper ) GetTimeoutHeight ( ) uint64 {
return w . tx . Body . TimeoutHeight
2020-08-07 16:32:22 -07:00
}
2020-08-24 07:41:08 -07:00
func ( w * wrapper ) GetSignaturesV2 ( ) ( [ ] signing . SignatureV2 , error ) {
signerInfos := w . tx . AuthInfo . SignerInfos
sigs := w . tx . Signatures
2021-03-09 23:16:04 -08:00
pubKeys , err := w . GetPubKeys ( )
if err != nil {
return nil , err
}
2020-07-06 10:03:45 -07:00
n := len ( signerInfos )
res := make ( [ ] signing . SignatureV2 , n )
for i , si := range signerInfos {
2020-09-02 13:41:13 -07:00
// handle nil signatures (in case of simulation)
if si . ModeInfo == nil {
res [ i ] = signing . SignatureV2 {
PubKey : pubKeys [ i ] ,
}
} else {
var err error
sigData , err := ModeInfoAndSigToSignatureData ( si . ModeInfo , sigs [ i ] )
if err != nil {
return nil , err
}
res [ i ] = signing . SignatureV2 {
PubKey : pubKeys [ i ] ,
Data : sigData ,
Sequence : si . GetSequence ( ) ,
}
2020-07-06 10:03:45 -07:00
}
}
return res , nil
}
2020-08-24 07:41:08 -07:00
func ( w * wrapper ) SetMsgs ( msgs ... sdk . Msg ) error {
feat: Add group module proto definitions and basic types (#9631)
<!--
The default pull request template is for types feat, fix, or refactor.
For other templates, add one of the following parameters to the url:
- template=docs.md
- template=other.md
-->
## Description
ref: https://github.com/cosmos/cosmos-sdk/issues/7633
<!-- Add a description of the changes that this PR introduces and the files that
are the most critical to review. -->
Following up on https://github.com/cosmos/cosmos-sdk/pull/9089, this PR is the first step towards the migration of [x/group](https://github.com/regen-network/regen-ledger/tree/master/x/group) into the SDK. It introduces the group module proto definitions (types, tx, query) and other types.
The rest of the code (module, server, client, genesis...) is dependent on various other discussions (https://github.com/cosmos/cosmos-sdk/issues/9238, https://github.com/cosmos/cosmos-sdk/discussions/9182, https://github.com/cosmos/cosmos-sdk/issues/9237, https://github.com/cosmos/cosmos-sdk/issues/7773) and will be added in follow-up PRs incrementally.
---
### Author Checklist
*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*
I have...
- [x] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [x] added `!` to the type prefix if API or client breaking change
- [x] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting))
- [x] provided a link to the relevant issue or specification
- [x] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules)
- [x] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing)
- [ ] added a changelog entry to `CHANGELOG.md`
- [x] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [x] updated the relevant documentation or specification
- [x] reviewed "Files changed" and left comments if necessary
- [x] confirmed all CI checks have passed
### Reviewers Checklist
*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*
I have...
- [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [ ] manually tested (if applicable)
2021-07-09 00:36:16 -07:00
anys , err := tx . SetMsgs ( msgs )
if err != nil {
return err
2020-07-06 10:03:45 -07:00
}
2020-08-24 07:41:08 -07:00
w . tx . Body . Messages = anys
2020-07-06 10:03:45 -07:00
// set bodyBz to nil because the cached bodyBz no longer matches tx.Body
2020-08-24 07:41:08 -07:00
w . bodyBz = nil
2020-07-06 10:03:45 -07:00
return nil
}
2020-08-07 16:32:22 -07:00
// SetTimeoutHeight sets the transaction's height timeout.
2020-08-24 07:41:08 -07:00
func ( w * wrapper ) SetTimeoutHeight ( height uint64 ) {
w . tx . Body . TimeoutHeight = height
2020-08-07 16:32:22 -07:00
// set bodyBz to nil because the cached bodyBz no longer matches tx.Body
2020-08-24 07:41:08 -07:00
w . bodyBz = nil
2020-08-07 16:32:22 -07:00
}
2020-08-24 07:41:08 -07:00
func ( w * wrapper ) SetMemo ( memo string ) {
w . tx . Body . Memo = memo
2020-07-06 10:03:45 -07:00
// set bodyBz to nil because the cached bodyBz no longer matches tx.Body
2020-08-24 07:41:08 -07:00
w . bodyBz = nil
2020-07-06 10:03:45 -07:00
}
2020-08-24 07:41:08 -07:00
func ( w * wrapper ) SetGasLimit ( limit uint64 ) {
if w . tx . AuthInfo . Fee == nil {
w . tx . AuthInfo . Fee = & tx . Fee { }
2020-07-06 10:03:45 -07:00
}
2020-08-24 07:41:08 -07:00
w . tx . AuthInfo . Fee . GasLimit = limit
2020-07-06 10:03:45 -07:00
// set authInfoBz to nil because the cached authInfoBz no longer matches tx.AuthInfo
2020-08-24 07:41:08 -07:00
w . authInfoBz = nil
2020-07-06 10:03:45 -07:00
}
2020-08-24 07:41:08 -07:00
func ( w * wrapper ) SetFeeAmount ( coins sdk . Coins ) {
if w . tx . AuthInfo . Fee == nil {
w . tx . AuthInfo . Fee = & tx . Fee { }
2020-07-06 10:03:45 -07:00
}
2020-08-24 07:41:08 -07:00
w . tx . AuthInfo . Fee . Amount = coins
2020-07-06 10:03:45 -07:00
// set authInfoBz to nil because the cached authInfoBz no longer matches tx.AuthInfo
2020-08-24 07:41:08 -07:00
w . authInfoBz = nil
2020-07-06 10:03:45 -07:00
}
2021-10-04 03:57:08 -07:00
func ( w * wrapper ) SetTip ( tip * tx . Tip ) {
w . tx . AuthInfo . Tip = tip
// set authInfoBz to nil because the cached authInfoBz no longer matches tx.AuthInfo
w . authInfoBz = nil
}
2020-09-30 02:03:44 -07:00
func ( w * wrapper ) SetFeePayer ( feePayer sdk . AccAddress ) {
if w . tx . AuthInfo . Fee == nil {
w . tx . AuthInfo . Fee = & tx . Fee { }
}
w . tx . AuthInfo . Fee . Payer = feePayer . String ( )
// set authInfoBz to nil because the cached authInfoBz no longer matches tx.AuthInfo
w . authInfoBz = nil
}
2020-10-05 14:56:09 -07:00
func ( w * wrapper ) SetFeeGranter ( feeGranter sdk . AccAddress ) {
if w . tx . AuthInfo . Fee == nil {
w . tx . AuthInfo . Fee = & tx . Fee { }
}
w . tx . AuthInfo . Fee . Granter = feeGranter . String ( )
// set authInfoBz to nil because the cached authInfoBz no longer matches tx.AuthInfo
w . authInfoBz = nil
}
2020-08-24 07:41:08 -07:00
func ( w * wrapper ) SetSignatures ( signatures ... signing . SignatureV2 ) error {
2020-07-06 10:03:45 -07:00
n := len ( signatures )
signerInfos := make ( [ ] * tx . SignerInfo , n )
rawSigs := make ( [ ] [ ] byte , n )
for i , sig := range signatures {
var modeInfo * tx . ModeInfo
modeInfo , rawSigs [ i ] = SignatureDataToModeInfoAndSig ( sig . Data )
2020-12-18 06:55:25 -08:00
any , err := codectypes . NewAnyWithValue ( sig . PubKey )
2020-07-06 10:03:45 -07:00
if err != nil {
return err
}
signerInfos [ i ] = & tx . SignerInfo {
2020-09-21 09:48:28 -07:00
PublicKey : any ,
2020-07-06 10:03:45 -07:00
ModeInfo : modeInfo ,
2020-08-21 07:20:47 -07:00
Sequence : sig . Sequence ,
2020-07-06 10:03:45 -07:00
}
}
2020-08-24 07:41:08 -07:00
w . setSignerInfos ( signerInfos )
w . setSignatures ( rawSigs )
2020-07-06 10:03:45 -07:00
return nil
}
2020-08-24 07:41:08 -07:00
func ( w * wrapper ) setSignerInfos ( infos [ ] * tx . SignerInfo ) {
w . tx . AuthInfo . SignerInfos = infos
2020-07-06 10:03:45 -07:00
// set authInfoBz to nil because the cached authInfoBz no longer matches tx.AuthInfo
2020-08-24 07:41:08 -07:00
w . authInfoBz = nil
}
feat: Add AuxTxBuilder (#10455)
<!--
The default pull request template is for types feat, fix, or refactor.
For other templates, add one of the following parameters to the url:
- template=docs.md
- template=other.md
-->
## Description
Closes: #10443
For creating an intermediary/auxiliary tx (e.g. by the tipper in tipped transactions), using the existing `client.TxBuilder` is awkward. We propose a new client-side builder for this purpose.
API Usage (e.g. how the tipper would programmtically use this):
```go
// Note: there's no need to use clientCtx.TxConfig anymore!
bldr := clienttx.NewAuxTxBuilder()
err := bldr.SetMsgs(msgs...)
bldr.SetAddress("cosmos1...")
bldr.SetMemo(...)
bldr.SetTip(...)
bldr.SetPubKey(...)
err := bldr.SetSignMode(...) // DIRECT_AUX or AMINO, or else error
// ... other setters are available
// Get the bytes to sign.
signBz, err := bldr.GetSignBytes()
// Sign the bz using your favorite method.
sig, err := privKey.sign(signBz)
// Set the signature
bldr.SetSig(sig)
// Get the final auxSignerData to be sent to the fee payer
auxSignerData, err:= bldr.GetAuxSignerData()
```
auxSignerData is a protobuf message, whose JSON reprensentation looks like:
```json
{
"address": "cosmos1...",
"mode": "SIGN_MODE_{DIRECT_AUX,LEGACY_AMINO_JSON}",
"sign_doc": {
"body_bytes": "{base64 bytes}",
"public_key": {
"@type": "cosmos.sepc256k1.PubKey",
"key": "{base64 bytes}"
},
"chain_id": "...",
"account_number": 24,
"sequence": 42,
"tip": {
"amount": [{ "denom": "uregen", "amount": 1000 }],
"tipper": "cosmos1..."
}
},
"sig": "{base64 bytes}"
}
```
Then the fee payer would use the TxBuilder to construct the final TX, with a new helper method: `AddAuxSignerData`:
```go
// get auxSignerData from AuxTxBuilder
auxSignerData := ...
txBuilder := txConfig.NewTxBuilder()
err := txBuilder.AddAuxSignerData(auxSignerData)
// Set fee payer data
txBuilder.SetFee()
txBuilder.SetGasLimit()
txBuilder.SetFeePayer()
sigs, err := txBuilder.GetSignaturesV2()
auxSig := sigs[0] // the aux signer's signature
// Set all signer infos (1st round of calling SetSignatures)
txBuilder.SetSignatures(
auxSig, // The aux SignatureV2
signing.SignatureV2{...}, // The feePayer's SignatureV2
)
// Sign
signBz, err = encCfg.TxConfig.SignModeHandler().GetSignBytes(...)
feepayerSig, err := feepayerPriv.Sign(signBz)
// Set all signatures (2nd round of calling SetSignatures)
txBuilder.SetSignatures(
auxSig, // The aux SignatureV2
signing.SignatureV2{feepayerSig, ...}, // The feePayer's SignatureV2
)
```
---
### Author Checklist
*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*
I have...
- [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] added `!` to the type prefix if API or client breaking change
- [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting))
- [ ] provided a link to the relevant issue or specification
- [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules)
- [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing)
- [ ] added a changelog entry to `CHANGELOG.md`
- [ ] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [ ] updated the relevant documentation or specification
- [ ] reviewed "Files changed" and left comments if necessary
- [ ] confirmed all CI checks have passed
### Reviewers Checklist
*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*
I have...
- [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [ ] manually tested (if applicable)
2021-11-11 03:25:13 -08:00
func ( w * wrapper ) setSignerInfoAtIndex ( index int , info * tx . SignerInfo ) {
if w . tx . AuthInfo . SignerInfos == nil {
w . tx . AuthInfo . SignerInfos = make ( [ ] * tx . SignerInfo , len ( w . GetSigners ( ) ) )
}
w . tx . AuthInfo . SignerInfos [ index ] = info
// set authInfoBz to nil because the cached authInfoBz no longer matches tx.AuthInfo
w . authInfoBz = nil
}
2020-08-24 07:41:08 -07:00
func ( w * wrapper ) setSignatures ( sigs [ ] [ ] byte ) {
w . tx . Signatures = sigs
}
2020-07-29 08:52:22 -07:00
feat: Add AuxTxBuilder (#10455)
<!--
The default pull request template is for types feat, fix, or refactor.
For other templates, add one of the following parameters to the url:
- template=docs.md
- template=other.md
-->
## Description
Closes: #10443
For creating an intermediary/auxiliary tx (e.g. by the tipper in tipped transactions), using the existing `client.TxBuilder` is awkward. We propose a new client-side builder for this purpose.
API Usage (e.g. how the tipper would programmtically use this):
```go
// Note: there's no need to use clientCtx.TxConfig anymore!
bldr := clienttx.NewAuxTxBuilder()
err := bldr.SetMsgs(msgs...)
bldr.SetAddress("cosmos1...")
bldr.SetMemo(...)
bldr.SetTip(...)
bldr.SetPubKey(...)
err := bldr.SetSignMode(...) // DIRECT_AUX or AMINO, or else error
// ... other setters are available
// Get the bytes to sign.
signBz, err := bldr.GetSignBytes()
// Sign the bz using your favorite method.
sig, err := privKey.sign(signBz)
// Set the signature
bldr.SetSig(sig)
// Get the final auxSignerData to be sent to the fee payer
auxSignerData, err:= bldr.GetAuxSignerData()
```
auxSignerData is a protobuf message, whose JSON reprensentation looks like:
```json
{
"address": "cosmos1...",
"mode": "SIGN_MODE_{DIRECT_AUX,LEGACY_AMINO_JSON}",
"sign_doc": {
"body_bytes": "{base64 bytes}",
"public_key": {
"@type": "cosmos.sepc256k1.PubKey",
"key": "{base64 bytes}"
},
"chain_id": "...",
"account_number": 24,
"sequence": 42,
"tip": {
"amount": [{ "denom": "uregen", "amount": 1000 }],
"tipper": "cosmos1..."
}
},
"sig": "{base64 bytes}"
}
```
Then the fee payer would use the TxBuilder to construct the final TX, with a new helper method: `AddAuxSignerData`:
```go
// get auxSignerData from AuxTxBuilder
auxSignerData := ...
txBuilder := txConfig.NewTxBuilder()
err := txBuilder.AddAuxSignerData(auxSignerData)
// Set fee payer data
txBuilder.SetFee()
txBuilder.SetGasLimit()
txBuilder.SetFeePayer()
sigs, err := txBuilder.GetSignaturesV2()
auxSig := sigs[0] // the aux signer's signature
// Set all signer infos (1st round of calling SetSignatures)
txBuilder.SetSignatures(
auxSig, // The aux SignatureV2
signing.SignatureV2{...}, // The feePayer's SignatureV2
)
// Sign
signBz, err = encCfg.TxConfig.SignModeHandler().GetSignBytes(...)
feepayerSig, err := feepayerPriv.Sign(signBz)
// Set all signatures (2nd round of calling SetSignatures)
txBuilder.SetSignatures(
auxSig, // The aux SignatureV2
signing.SignatureV2{feepayerSig, ...}, // The feePayer's SignatureV2
)
```
---
### Author Checklist
*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*
I have...
- [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] added `!` to the type prefix if API or client breaking change
- [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting))
- [ ] provided a link to the relevant issue or specification
- [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules)
- [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing)
- [ ] added a changelog entry to `CHANGELOG.md`
- [ ] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [ ] updated the relevant documentation or specification
- [ ] reviewed "Files changed" and left comments if necessary
- [ ] confirmed all CI checks have passed
### Reviewers Checklist
*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*
I have...
- [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [ ] manually tested (if applicable)
2021-11-11 03:25:13 -08:00
func ( w * wrapper ) setSignatureAtIndex ( index int , sig [ ] byte ) {
if w . tx . Signatures == nil {
w . tx . Signatures = make ( [ ] [ ] byte , len ( w . GetSigners ( ) ) )
}
w . tx . Signatures [ index ] = sig
}
2020-08-24 07:41:08 -07:00
func ( w * wrapper ) GetTx ( ) authsigning . Tx {
return w
2020-07-29 08:52:22 -07:00
}
2020-12-18 06:55:25 -08:00
func ( w * wrapper ) GetProtoTx ( ) * tx . Tx {
return w . tx
}
// Deprecated: AsAny extracts proto Tx and wraps it into Any.
// NOTE: You should probably use `GetProtoTx` if you want to serialize the transaction.
2020-09-10 11:26:47 -07:00
func ( w * wrapper ) AsAny ( ) * codectypes . Any {
return codectypes . UnsafePackAny ( w . tx )
2020-07-06 10:03:45 -07:00
}
2020-08-24 07:41:08 -07:00
// WrapTx creates a TxBuilder wrapper around a tx.Tx proto message.
2020-09-21 09:48:28 -07:00
func WrapTx ( protoTx * tx . Tx ) client . TxBuilder {
2020-08-24 07:41:08 -07:00
return & wrapper {
2020-09-21 09:48:28 -07:00
tx : protoTx ,
2020-08-24 07:41:08 -07:00
}
2020-07-06 10:03:45 -07:00
}
2020-08-18 06:44:56 -07:00
2020-08-24 07:41:08 -07:00
func ( w * wrapper ) GetExtensionOptions ( ) [ ] * codectypes . Any {
return w . tx . Body . ExtensionOptions
2020-08-18 06:44:56 -07:00
}
2020-08-24 07:41:08 -07:00
func ( w * wrapper ) GetNonCriticalExtensionOptions ( ) [ ] * codectypes . Any {
return w . tx . Body . NonCriticalExtensionOptions
2020-08-18 06:44:56 -07:00
}
2020-08-24 07:41:08 -07:00
func ( w * wrapper ) SetExtensionOptions ( extOpts ... * codectypes . Any ) {
w . tx . Body . ExtensionOptions = extOpts
w . bodyBz = nil
2020-08-18 06:44:56 -07:00
}
2020-08-24 07:41:08 -07:00
func ( w * wrapper ) SetNonCriticalExtensionOptions ( extOpts ... * codectypes . Any ) {
w . tx . Body . NonCriticalExtensionOptions = extOpts
w . bodyBz = nil
2020-08-18 06:44:56 -07:00
}
feat: Add AuxTxBuilder (#10455)
<!--
The default pull request template is for types feat, fix, or refactor.
For other templates, add one of the following parameters to the url:
- template=docs.md
- template=other.md
-->
## Description
Closes: #10443
For creating an intermediary/auxiliary tx (e.g. by the tipper in tipped transactions), using the existing `client.TxBuilder` is awkward. We propose a new client-side builder for this purpose.
API Usage (e.g. how the tipper would programmtically use this):
```go
// Note: there's no need to use clientCtx.TxConfig anymore!
bldr := clienttx.NewAuxTxBuilder()
err := bldr.SetMsgs(msgs...)
bldr.SetAddress("cosmos1...")
bldr.SetMemo(...)
bldr.SetTip(...)
bldr.SetPubKey(...)
err := bldr.SetSignMode(...) // DIRECT_AUX or AMINO, or else error
// ... other setters are available
// Get the bytes to sign.
signBz, err := bldr.GetSignBytes()
// Sign the bz using your favorite method.
sig, err := privKey.sign(signBz)
// Set the signature
bldr.SetSig(sig)
// Get the final auxSignerData to be sent to the fee payer
auxSignerData, err:= bldr.GetAuxSignerData()
```
auxSignerData is a protobuf message, whose JSON reprensentation looks like:
```json
{
"address": "cosmos1...",
"mode": "SIGN_MODE_{DIRECT_AUX,LEGACY_AMINO_JSON}",
"sign_doc": {
"body_bytes": "{base64 bytes}",
"public_key": {
"@type": "cosmos.sepc256k1.PubKey",
"key": "{base64 bytes}"
},
"chain_id": "...",
"account_number": 24,
"sequence": 42,
"tip": {
"amount": [{ "denom": "uregen", "amount": 1000 }],
"tipper": "cosmos1..."
}
},
"sig": "{base64 bytes}"
}
```
Then the fee payer would use the TxBuilder to construct the final TX, with a new helper method: `AddAuxSignerData`:
```go
// get auxSignerData from AuxTxBuilder
auxSignerData := ...
txBuilder := txConfig.NewTxBuilder()
err := txBuilder.AddAuxSignerData(auxSignerData)
// Set fee payer data
txBuilder.SetFee()
txBuilder.SetGasLimit()
txBuilder.SetFeePayer()
sigs, err := txBuilder.GetSignaturesV2()
auxSig := sigs[0] // the aux signer's signature
// Set all signer infos (1st round of calling SetSignatures)
txBuilder.SetSignatures(
auxSig, // The aux SignatureV2
signing.SignatureV2{...}, // The feePayer's SignatureV2
)
// Sign
signBz, err = encCfg.TxConfig.SignModeHandler().GetSignBytes(...)
feepayerSig, err := feepayerPriv.Sign(signBz)
// Set all signatures (2nd round of calling SetSignatures)
txBuilder.SetSignatures(
auxSig, // The aux SignatureV2
signing.SignatureV2{feepayerSig, ...}, // The feePayer's SignatureV2
)
```
---
### Author Checklist
*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*
I have...
- [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] added `!` to the type prefix if API or client breaking change
- [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting))
- [ ] provided a link to the relevant issue or specification
- [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules)
- [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing)
- [ ] added a changelog entry to `CHANGELOG.md`
- [ ] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [ ] updated the relevant documentation or specification
- [ ] reviewed "Files changed" and left comments if necessary
- [ ] confirmed all CI checks have passed
### Reviewers Checklist
*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*
I have...
- [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [ ] manually tested (if applicable)
2021-11-11 03:25:13 -08:00
func ( w * wrapper ) AddAuxSignerData ( data tx . AuxSignerData ) error {
err := data . ValidateBasic ( )
if err != nil {
return err
}
w . bodyBz = data . SignDoc . BodyBytes
var body tx . TxBody
err = w . cdc . Unmarshal ( w . bodyBz , & body )
if err != nil {
return err
}
2021-11-16 12:48:52 -08:00
if w . tx . Body . Memo != "" && w . tx . Body . Memo != body . Memo {
return sdkerrors . ErrInvalidRequest . Wrapf ( "TxBuilder has memo %s, got %s in AuxSignerData" , w . tx . Body . Memo , body . Memo )
}
if w . tx . Body . TimeoutHeight != 0 && w . tx . Body . TimeoutHeight != body . TimeoutHeight {
return sdkerrors . ErrInvalidRequest . Wrapf ( "TxBuilder has timeout height %d, got %d in AuxSignerData" , w . tx . Body . TimeoutHeight , body . TimeoutHeight )
}
if len ( w . tx . Body . ExtensionOptions ) != 0 {
if len ( w . tx . Body . ExtensionOptions ) != len ( body . ExtensionOptions ) {
return sdkerrors . ErrInvalidRequest . Wrapf ( "TxBuilder has %d extension options, got %d in AuxSignerData" , len ( w . tx . Body . ExtensionOptions ) , len ( body . ExtensionOptions ) )
}
for i , o := range w . tx . Body . ExtensionOptions {
if ! o . Equal ( body . ExtensionOptions [ i ] ) {
return sdkerrors . ErrInvalidRequest . Wrapf ( "TxBuilder has extension option %+v at index %d, got %+v in AuxSignerData" , o , i , body . ExtensionOptions [ i ] )
}
}
}
if len ( w . tx . Body . NonCriticalExtensionOptions ) != 0 {
if len ( w . tx . Body . NonCriticalExtensionOptions ) != len ( body . NonCriticalExtensionOptions ) {
return sdkerrors . ErrInvalidRequest . Wrapf ( "TxBuilder has %d non-critical extension options, got %d in AuxSignerData" , len ( w . tx . Body . NonCriticalExtensionOptions ) , len ( body . NonCriticalExtensionOptions ) )
}
for i , o := range w . tx . Body . NonCriticalExtensionOptions {
if ! o . Equal ( body . NonCriticalExtensionOptions [ i ] ) {
return sdkerrors . ErrInvalidRequest . Wrapf ( "TxBuilder has non-critical extension option %+v at index %d, got %+v in AuxSignerData" , o , i , body . NonCriticalExtensionOptions [ i ] )
}
}
}
if len ( w . tx . Body . Messages ) != 0 {
if len ( w . tx . Body . Messages ) != len ( body . Messages ) {
return sdkerrors . ErrInvalidRequest . Wrapf ( "TxBuilder has %d Msgs, got %d in AuxSignerData" , len ( w . tx . Body . Messages ) , len ( body . Messages ) )
}
for i , o := range w . tx . Body . Messages {
if ! o . Equal ( body . Messages [ i ] ) {
return sdkerrors . ErrInvalidRequest . Wrapf ( "TxBuilder has Msg %+v at index %d, got %+v in AuxSignerData" , o , i , body . Messages [ i ] )
}
}
}
if w . tx . AuthInfo . Tip != nil && data . SignDoc . Tip != nil {
if ! w . tx . AuthInfo . Tip . Amount . IsEqual ( data . SignDoc . Tip . Amount ) {
return sdkerrors . ErrInvalidRequest . Wrapf ( "TxBuilder has tip %+v, got %+v in AuxSignerData" , w . tx . AuthInfo . Tip . Amount , data . SignDoc . Tip . Amount )
}
if w . tx . AuthInfo . Tip . Tipper != data . SignDoc . Tip . Tipper {
return sdkerrors . ErrInvalidRequest . Wrapf ( "TxBuilder has tipper %s, got %s in AuxSignerData" , w . tx . AuthInfo . Tip . Tipper , data . SignDoc . Tip . Tipper )
}
}
feat: Add AuxTxBuilder (#10455)
<!--
The default pull request template is for types feat, fix, or refactor.
For other templates, add one of the following parameters to the url:
- template=docs.md
- template=other.md
-->
## Description
Closes: #10443
For creating an intermediary/auxiliary tx (e.g. by the tipper in tipped transactions), using the existing `client.TxBuilder` is awkward. We propose a new client-side builder for this purpose.
API Usage (e.g. how the tipper would programmtically use this):
```go
// Note: there's no need to use clientCtx.TxConfig anymore!
bldr := clienttx.NewAuxTxBuilder()
err := bldr.SetMsgs(msgs...)
bldr.SetAddress("cosmos1...")
bldr.SetMemo(...)
bldr.SetTip(...)
bldr.SetPubKey(...)
err := bldr.SetSignMode(...) // DIRECT_AUX or AMINO, or else error
// ... other setters are available
// Get the bytes to sign.
signBz, err := bldr.GetSignBytes()
// Sign the bz using your favorite method.
sig, err := privKey.sign(signBz)
// Set the signature
bldr.SetSig(sig)
// Get the final auxSignerData to be sent to the fee payer
auxSignerData, err:= bldr.GetAuxSignerData()
```
auxSignerData is a protobuf message, whose JSON reprensentation looks like:
```json
{
"address": "cosmos1...",
"mode": "SIGN_MODE_{DIRECT_AUX,LEGACY_AMINO_JSON}",
"sign_doc": {
"body_bytes": "{base64 bytes}",
"public_key": {
"@type": "cosmos.sepc256k1.PubKey",
"key": "{base64 bytes}"
},
"chain_id": "...",
"account_number": 24,
"sequence": 42,
"tip": {
"amount": [{ "denom": "uregen", "amount": 1000 }],
"tipper": "cosmos1..."
}
},
"sig": "{base64 bytes}"
}
```
Then the fee payer would use the TxBuilder to construct the final TX, with a new helper method: `AddAuxSignerData`:
```go
// get auxSignerData from AuxTxBuilder
auxSignerData := ...
txBuilder := txConfig.NewTxBuilder()
err := txBuilder.AddAuxSignerData(auxSignerData)
// Set fee payer data
txBuilder.SetFee()
txBuilder.SetGasLimit()
txBuilder.SetFeePayer()
sigs, err := txBuilder.GetSignaturesV2()
auxSig := sigs[0] // the aux signer's signature
// Set all signer infos (1st round of calling SetSignatures)
txBuilder.SetSignatures(
auxSig, // The aux SignatureV2
signing.SignatureV2{...}, // The feePayer's SignatureV2
)
// Sign
signBz, err = encCfg.TxConfig.SignModeHandler().GetSignBytes(...)
feepayerSig, err := feepayerPriv.Sign(signBz)
// Set all signatures (2nd round of calling SetSignatures)
txBuilder.SetSignatures(
auxSig, // The aux SignatureV2
signing.SignatureV2{feepayerSig, ...}, // The feePayer's SignatureV2
)
```
---
### Author Checklist
*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*
I have...
- [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] added `!` to the type prefix if API or client breaking change
- [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting))
- [ ] provided a link to the relevant issue or specification
- [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules)
- [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing)
- [ ] added a changelog entry to `CHANGELOG.md`
- [ ] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [ ] updated the relevant documentation or specification
- [ ] reviewed "Files changed" and left comments if necessary
- [ ] confirmed all CI checks have passed
### Reviewers Checklist
*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*
I have...
- [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [ ] manually tested (if applicable)
2021-11-11 03:25:13 -08:00
w . SetMemo ( body . Memo )
w . SetTimeoutHeight ( body . TimeoutHeight )
w . SetExtensionOptions ( body . ExtensionOptions ... )
w . SetNonCriticalExtensionOptions ( body . NonCriticalExtensionOptions ... )
msgs := make ( [ ] sdk . Msg , len ( body . Messages ) )
for i , msgAny := range body . Messages {
msgs [ i ] = msgAny . GetCachedValue ( ) . ( sdk . Msg )
}
w . SetMsgs ( msgs ... )
w . SetTip ( data . GetSignDoc ( ) . GetTip ( ) )
// Get the aux signer's index in GetSigners.
signerIndex := - 1
for i , signer := range w . GetSigners ( ) {
if signer . String ( ) == data . Address {
signerIndex = i
}
}
if signerIndex < 0 {
return sdkerrors . ErrLogic . Wrapf ( "address %s is not a signer" , data . Address )
}
w . setSignerInfoAtIndex ( signerIndex , & tx . SignerInfo {
PublicKey : data . SignDoc . PublicKey ,
ModeInfo : & tx . ModeInfo { Sum : & tx . ModeInfo_Single_ { Single : & tx . ModeInfo_Single { Mode : data . Mode } } } ,
Sequence : data . SignDoc . Sequence ,
} )
w . setSignatureAtIndex ( signerIndex , data . Sig )
return nil
}