-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
Enable Fee Delegation #5768
Closed
Closed
Enable Fee Delegation #5768
Changes from all commits
Commits
Show all changes
85 commits
Select commit
Hold shift + click to select a range
abce938
Add docs
ethanfrey ea6fe7d
Add BasicFeeAllowance implementation
ethanfrey c46153c
Add expiration structs and complete basic fee
ethanfrey 42c17f5
Add delegation messages, add validation logic
ethanfrey 0c137cb
Add keeper and helper structs
ethanfrey 67cb830
Add alias and handler to top level
ethanfrey f6ba9bc
Add delegation module
ethanfrey a002366
Add basic querier
ethanfrey 15c6361
Add types tests
ethanfrey 410d1f1
Add types tests
ethanfrey f65db09
More internal test coverage
ethanfrey e0f6327
Solid internal test coverage
ethanfrey 93c9b7e
Expose Querier to top level module
ethanfrey 7968441
Add FeeAccount to auth/types, like StdTx, SignDoc
ethanfrey 7e82fb8
Fix all tests in x/auth
ethanfrey 64d5159
All tests pass
ethanfrey 8b2b64b
Appease the Golang Linter
ethanfrey 4e22edd
Merge remote-tracking branch 'origin/master' into cg-key-management/f…
ethanfrey be12b44
Add fee-account command line flag
ethanfrey c703e59
Start on DelegatedDeductFeeDecorator
ethanfrey 907776f
Cleanup the Decorator
ethanfrey 005afd9
Wire up delegation module in simapp
ethanfrey 45c64d2
add basic test for decorator (no delegation)
ethanfrey 87fd0ce
Table tests for deduct fees
ethanfrey d03c650
Table tests over all conditions of delegated fee decorator
ethanfrey e476c03
Build full ante handler stack and test it
ethanfrey 182eb34
Start genesis
ethanfrey 071e111
Implement Genesis
ethanfrey 0a362b8
Merge branch 'master' into cg-key-management/fee-delegation-new
alexanderbez 98b88a3
Rename package delegation to subkeys
ethanfrey 376e9cd
Clarify antes test cases, handle empty account w/o fees
ethanfrey 529764f
Allow paying delegated fees with no account
ethanfrey d293aae
Pull mempool into delegated ante, for control on StdFee
ethanfrey a8b3e31
Use custom DelegatedTx, DelegatedFee for subkeys
ethanfrey e939e98
Revert all changes to x/auth.StdTx
ethanfrey 6aef5c8
Appease scopelint
ethanfrey 1212772
Register DelegatedTx with codec
ethanfrey f688116
Merge branch 'master' into cg-key-management/fee-delegation-new
alexanderbez 61df0c6
Address PR comments
ethanfrey d684f92
Remove unnecessary DelegatedMempoolFeeDecorator
ethanfrey aacf6fb
Cleaned up errors in querier
ethanfrey 92f64cc
Clean up message sign bytes
ethanfrey 4daf4af
Minor PR comments
ethanfrey a497575
Replace GetAllFees... with Iterator variants
ethanfrey 73eab92
PrepareForExport adjusts grant expiration height
ethanfrey 546fa8f
Panic on de/serialization error in keeper
ethanfrey 5f9e391
Move custom ante handler chain to tests, update docs
ethanfrey c45dc71
More cleanup
ethanfrey 2be48ef
More doc cleanup
ethanfrey e8a624f
Renamed subkeys module to fee_grant
ethanfrey 6756099
Rename subkeys/delegation to fee grant in all strings
ethanfrey 320bad4
Modify Msg and Keeper methods to use Grant not Delegate
ethanfrey a625fd0
Merge remote-tracking branch 'origin/master' into cg-key-management/f…
ethanfrey 4b4391b
Add PeriodicFeeAllowance
ethanfrey 9ec284b
Update aliases
ethanfrey 4b34cf6
Cover all accept cases for PeriodicFeeAllowance
ethanfrey 78f1f7a
Et tu scopelint?
ethanfrey a1951b4
Update docs as requested
ethanfrey 17c39ca
Remove error return from GetFeeGrant
ethanfrey 9c399bb
Code cleanup as requested by PR
ethanfrey 6b9e06e
Merge remote-tracking branch 'origin/master' into cg-key-management/f…
ethanfrey 21b0ac5
Updated all errors to use new sdk/errors package
ethanfrey 2222d0e
Use test suite for keeper tests
ethanfrey eda42d4
Clean up alias.go file
ethanfrey a56b472
Define expected interfaces in exported, rather than importing from ac…
ethanfrey be29328
Remove dependency on auth/ante
ethanfrey 786bf01
Improve godoc, Logger
ethanfrey 5f2bcb5
Cleaned up ExpiresAt
ethanfrey 314b099
Improve error reporting with UseGrantedFee
ethanfrey 29958e0
Enforce period limit subset of basic limit
ethanfrey fb5b97a
Add events
ethanfrey eedb8d8
Rename fee_grant to feegrant
ethanfrey 88df255
Ensure KeeperTestSuite actually runs
ethanfrey dbf3578
Move types/tx to types
ethanfrey 375f114
Update alias file, include ante
ethanfrey 9af9f43
I do need nolint in alias.go
ethanfrey 3c390e5
Properly emit events in the handler. Use cosmos-sdk in amino types
ethanfrey de694c5
Merge branch 'master' into bez/enable-fee-auth
alexanderbez 720e9f4
Update godoc
alexanderbez eb46dd0
Linting...
alexanderbez 63cca04
Update errors
alexanderbez 8eddbb7
Update pkg doc and fix ante-handler order
alexanderbez f32db1d
Merge PR #5782: Migrate x/feegrant to proto
sahith-narahari 8dc477a
Merge branch 'master' of github.com:cosmos/cosmos-sdk into bez/enable…
sahith-narahari b8038ee
Merge branch 'master' of github.com:cosmos/cosmos-sdk into bez/enable…
sahith-narahari File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package simapp | ||
|
||
import ( | ||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
"github.com/cosmos/cosmos-sdk/x/auth" | ||
authante "github.com/cosmos/cosmos-sdk/x/auth/ante" | ||
"github.com/cosmos/cosmos-sdk/x/feegrant" | ||
feegrantante "github.com/cosmos/cosmos-sdk/x/feegrant/ante" | ||
) | ||
|
||
// NewAnteHandler returns an AnteHandler that checks and increments sequence | ||
// numbers, checks signatures & account numbers, and deducts fees from the first | ||
// signer. | ||
func NewAnteHandler( | ||
ak auth.AccountKeeper, supplyKeeper feegrant.SupplyKeeper, feeGrantKeeper feegrant.Keeper, | ||
sigGasConsumer auth.SignatureVerificationGasConsumer, | ||
) sdk.AnteHandler { | ||
|
||
return sdk.ChainAnteDecorators( | ||
authante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first | ||
authante.NewMempoolFeeDecorator(), | ||
authante.NewValidateBasicDecorator(), | ||
authante.NewValidateMemoDecorator(ak), | ||
authante.NewConsumeGasForTxSizeDecorator(ak), | ||
// DeductGrantedFeeDecorator will create an empty account if we sign with no | ||
// tokens but valid validation. This must be before SetPubKey, ValidateSigCount, | ||
// SigVerification, which error if account doesn't exist yet. | ||
feegrantante.NewDeductGrantedFeeDecorator(ak, supplyKeeper, feeGrantKeeper), | ||
authante.NewSetPubKeyDecorator(ak), // SetPubKeyDecorator must be called before all signature verification decorators | ||
authante.NewValidateSigCountDecorator(ak), | ||
authante.NewSigGasConsumeDecorator(ak, sigGasConsumer), | ||
authante.NewSigVerificationDecorator(ak), | ||
authante.NewIncrementSequenceDecorator(ak), // innermost AnteDecorator | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package feegrant | ||
|
||
import ( | ||
"github.com/cosmos/cosmos-sdk/x/feegrant/ante" | ||
"github.com/cosmos/cosmos-sdk/x/feegrant/keeper" | ||
"github.com/cosmos/cosmos-sdk/x/feegrant/types" | ||
) | ||
|
||
// nolint | ||
|
||
const ( | ||
DefaultCodespace = types.DefaultCodespace | ||
EventTypeUseFeeGrant = types.EventTypeUseFeeGrant | ||
EventTypeRevokeFeeGrant = types.EventTypeRevokeFeeGrant | ||
EventTypeSetFeeGrant = types.EventTypeSetFeeGrant | ||
AttributeKeyGranter = types.AttributeKeyGranter | ||
AttributeKeyGrantee = types.AttributeKeyGrantee | ||
ModuleName = types.ModuleName | ||
StoreKey = types.StoreKey | ||
RouterKey = types.RouterKey | ||
QuerierRoute = types.QuerierRoute | ||
QueryGetFeeAllowances = keeper.QueryGetFeeAllowances | ||
) | ||
|
||
var ( | ||
NewDeductGrantedFeeDecorator = ante.NewDeductGrantedFeeDecorator | ||
RegisterCodec = types.RegisterCodec | ||
ExpiresAtTime = types.ExpiresAtTime | ||
ExpiresAtHeight = types.ExpiresAtHeight | ||
ClockDuration = types.ClockDuration | ||
BlockDuration = types.BlockDuration | ||
FeeAllowanceKey = types.FeeAllowanceKey | ||
FeeAllowancePrefixByGrantee = types.FeeAllowancePrefixByGrantee | ||
NewMsgRevokeFeeAllowance = types.NewMsgRevokeFeeAllowance | ||
NewFeeGrantTx = types.NewFeeGrantTx | ||
CountSubKeys = types.CountSubKeys | ||
NewGrantedFee = types.NewGrantedFee | ||
StdSignBytes = types.StdSignBytes | ||
NewKeeper = keeper.NewKeeper | ||
NewQuerier = keeper.NewQuerier | ||
|
||
ModuleCdc = types.ModuleCdc | ||
ErrFeeLimitExceeded = types.ErrFeeLimitExceeded | ||
ErrFeeLimitExpired = types.ErrFeeLimitExpired | ||
ErrInvalidDuration = types.ErrInvalidDuration | ||
ErrNoAllowance = types.ErrNoAllowance | ||
FeeAllowanceKeyPrefix = types.FeeAllowanceKeyPrefix | ||
) | ||
|
||
type ( | ||
GrantedFeeTx = ante.GrantedFeeTx | ||
DeductGrantedFeeDecorator = ante.DeductGrantedFeeDecorator | ||
BasicFeeAllowance = types.BasicFeeAllowance | ||
ExpiresAt = types.ExpiresAt | ||
Duration = types.Duration | ||
FeeAllowance = types.FeeAllowance | ||
FeeAllowanceGrant = types.FeeAllowanceGrant | ||
MsgGrantFeeAllowance = types.MsgGrantFeeAllowance | ||
MsgRevokeFeeAllowance = types.MsgRevokeFeeAllowance | ||
PeriodicFeeAllowance = types.PeriodicFeeAllowance | ||
FeeGrantTx = types.FeeGrantTx | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. type name will be used as feegrant.FeeGrantTx by other packages, and that stutters; consider calling this Tx (from |
||
GrantedFee = types.GrantedFee | ||
DelegatedSignDoc = types.DelegatedSignDoc | ||
SupplyKeeper = types.SupplyKeeper | ||
Keeper = keeper.Keeper | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
package ante | ||
|
||
import ( | ||
"fmt" | ||
|
||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" | ||
"github.com/cosmos/cosmos-sdk/x/auth" | ||
"github.com/cosmos/cosmos-sdk/x/feegrant/keeper" | ||
"github.com/cosmos/cosmos-sdk/x/feegrant/types" | ||
) | ||
|
||
var ( | ||
_ GrantedFeeTx = (*types.FeeGrantTx)(nil) // assert FeeGrantTx implements GrantedFeeTx | ||
) | ||
|
||
// GrantedFeeTx defines the interface to be implemented by Tx to use the GrantedFeeDecorator | ||
type GrantedFeeTx interface { | ||
sdk.Tx | ||
|
||
GetGas() uint64 | ||
GetFee() sdk.Coins | ||
FeePayer() sdk.AccAddress | ||
MainSigner() sdk.AccAddress | ||
} | ||
|
||
// DeductGrantedFeeDecorator deducts fees from the first signer of the tx | ||
// If the first signer does not have the funds to pay for the fees, return with InsufficientFunds error | ||
// Call next AnteHandler if fees successfully deducted | ||
// CONTRACT: Tx must implement GrantedFeeTx interface to use DeductGrantedFeeDecorator | ||
type DeductGrantedFeeDecorator struct { | ||
ak types.AccountKeeper | ||
k keeper.Keeper | ||
sk types.SupplyKeeper | ||
} | ||
|
||
func NewDeductGrantedFeeDecorator(ak types.AccountKeeper, sk types.SupplyKeeper, k keeper.Keeper) DeductGrantedFeeDecorator { | ||
return DeductGrantedFeeDecorator{ | ||
ak: ak, | ||
k: k, | ||
sk: sk, | ||
} | ||
} | ||
|
||
// AnteHandle performs a decorated ante-handler responsible for deducting transaction | ||
// fees. Fees will be deducted from the account designated by the FeePayer on a | ||
// transaction by default. However, if the fee payer differs from the transaction | ||
// signer, the handler will check if a fee grant has been authorized. If the | ||
// transaction's signer does not exist, it will be created. | ||
func (d DeductGrantedFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { | ||
feeTx, ok := tx.(GrantedFeeTx) | ||
if !ok { | ||
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a GrantedFeeTx") | ||
} | ||
|
||
// sanity check from DeductFeeDecorator | ||
if addr := d.sk.GetModuleAddress(auth.FeeCollectorName); addr == nil { | ||
panic(fmt.Sprintf("%s module account has not been set", auth.FeeCollectorName)) | ||
} | ||
|
||
fee := feeTx.GetFee() | ||
feePayer := feeTx.FeePayer() | ||
txSigner := feeTx.MainSigner() | ||
|
||
// ensure the grant is allowed, if we request a different fee payer | ||
if !txSigner.Equals(feePayer) { | ||
err := d.k.UseGrantedFees(ctx, feePayer, txSigner, fee) | ||
if err != nil { | ||
return ctx, sdkerrors.Wrapf(err, "%s not allowed to pay fees from %s", txSigner, feePayer) | ||
} | ||
|
||
// if there was a valid grant, ensure that the txSigner account exists (we create it if needed) | ||
signerAcc := d.ak.GetAccount(ctx, txSigner) | ||
if signerAcc == nil { | ||
signerAcc = d.ak.NewAccountWithAddress(ctx, txSigner) | ||
d.ak.SetAccount(ctx, signerAcc) | ||
} | ||
} | ||
|
||
// now, either way, we know that we are authorized to deduct the fees from the feePayer account | ||
feePayerAcc := d.ak.GetAccount(ctx, feePayer) | ||
if feePayerAcc == nil { | ||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "fee payer address: %s does not exist", feePayer) | ||
} | ||
|
||
// move on if there is no fee to deduct | ||
if fee.IsZero() { | ||
return next(ctx, tx, simulate) | ||
} | ||
|
||
// deduct fee if non-zero | ||
err = auth.DeductFees(d.sk, ctx, feePayerAcc, fee) | ||
if err != nil { | ||
return ctx, err | ||
} | ||
|
||
return next(ctx, tx, simulate) | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aaronc @ethanfrey please verify the ante-handler and order here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It has been a while, but this looks good.
NewSetPubKeyDecorator
position is key, as otherwise an empty account could never use a grant until it had some tokens (which is not the behavior we wanted)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Starting to take a look at this work again as I'm trying to figure out how to deal with account numbers and sequences starting from 1 (which was a part of ADR 020).
So one thing that I'm aware of here is that if we create the account in the
DeduceGrantedFeeDecorator
that account number will differ from the one use for tx signing. So it seems like the correct approach to doing this is to allow accounts that don't yet exist in state to use some zero-value for account number to do signing. Since we want to avoid0
as a value for account number, it sounds like1
would become the zero value and2
would be the first number of any real account in state.What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another alternative is that accounts get created (if they don't exist) whenever fee grants are created. That might be a bit cleaner in some ways.
Although, conceptually the idea that there is some way for accounts that aren't in state to sign transactions sounds desirable to me.