-
Notifications
You must be signed in to change notification settings - Fork 3.8k
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
Add FeeAccount to StdTx and add fee-delegation module #4616
Changes from 6 commits
1470b7f
efb559f
3a5598b
7b42a27
af9743a
8d6ef9b
980d713
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -32,10 +32,16 @@ func init() { | |||||
// and also to accept or reject different types of PubKey's. This is where apps can define their own PubKey | ||||||
type SignatureVerificationGasConsumer = func(meter sdk.GasMeter, sig []byte, pubkey crypto.PubKey, params Params) sdk.Result | ||||||
|
||||||
type FeeDelegationHandler interface { | ||||||
// AllowDelegatedFees checks if the grantee can use the granter's account to spend the specified fees, updating | ||||||
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. Can we wrap the comments at 80 chars (if not already)? |
||||||
// any fee allowance in accordance with the provided fees | ||||||
AllowDelegatedFees(ctx sdk.Context, grantee sdk.AccAddress, granter sdk.AccAddress, fee sdk.Coins) bool | ||||||
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.
Suggested change
|
||||||
} | ||||||
|
||||||
// NewAnteHandler returns an AnteHandler that checks and increments sequence | ||||||
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. Lets update the godoc to now mention the use of the new fee delegation logic. |
||||||
// numbers, checks signatures & account numbers, and deducts fees from the first | ||||||
// signer. | ||||||
func NewAnteHandler(ak AccountKeeper, supplyKeeper types.SupplyKeeper, sigGasConsumer SignatureVerificationGasConsumer) sdk.AnteHandler { | ||||||
func NewAnteHandler(ak AccountKeeper, supplyKeeper types.SupplyKeeper, feeDelegationHandler FeeDelegationHandler, sigGasConsumer SignatureVerificationGasConsumer) sdk.AnteHandler { | ||||||
return func( | ||||||
ctx sdk.Context, tx sdk.Tx, simulate bool, | ||||||
) (newCtx sdk.Context, res sdk.Result, abort bool) { | ||||||
|
@@ -110,34 +116,42 @@ func NewAnteHandler(ak AccountKeeper, supplyKeeper types.SupplyKeeper, sigGasCon | |||||
signerAccs := make([]Account, len(signerAddrs)) | ||||||
isGenesis := ctx.BlockHeight() == 0 | ||||||
|
||||||
// fetch first signer, who's going to pay the fees | ||||||
signerAccs[0], res = GetSignerAcc(newCtx, ak, signerAddrs[0]) | ||||||
feeAddr := stdTx.FeeAccount | ||||||
if len(feeAddr) != 0 { | ||||||
// check if fees can be delegated | ||||||
if feeDelegationHandler == nil { | ||||||
return newCtx, sdk.ErrUnknownRequest("delegated fees aren't supported").Result(), true | ||||||
} | ||||||
if !feeDelegationHandler.AllowDelegatedFees(ctx, signerAddrs[0], feeAddr, stdTx.Fee.Amount) { | ||||||
return newCtx, res, true | ||||||
} | ||||||
} else { | ||||||
// use first signer, who's going to pay the fees | ||||||
feeAddr = signerAddrs[0] | ||||||
} | ||||||
|
||||||
// pay fees with the fee account | ||||||
feeAccount, res := GetSignerAcc(newCtx, ak, feeAddr) | ||||||
if !res.IsOK() { | ||||||
return newCtx, res, true | ||||||
} | ||||||
|
||||||
// deduct the fees | ||||||
if !stdTx.Fee.Amount.IsZero() { | ||||||
res = DeductFees(supplyKeeper, newCtx, signerAccs[0], stdTx.Fee.Amount) | ||||||
res = DeductFees(supplyKeeper, newCtx, feeAccount, stdTx.Fee.Amount) | ||||||
if !res.IsOK() { | ||||||
return newCtx, res, true | ||||||
} | ||||||
|
||||||
// reload the account as fees have been deducted | ||||||
signerAccs[0] = ak.GetAccount(newCtx, signerAccs[0].GetAddress()) | ||||||
} | ||||||
|
||||||
// stdSigs contains the sequence number, account number, and signatures. | ||||||
// When simulating, this would just be a 0-length slice. | ||||||
stdSigs := stdTx.GetSignatures() | ||||||
|
||||||
for i := 0; i < len(stdSigs); i++ { | ||||||
// skip the fee payer, account is cached and fees were deducted already | ||||||
if i != 0 { | ||||||
signerAccs[i], res = GetSignerAcc(newCtx, ak, signerAddrs[i]) | ||||||
if !res.IsOK() { | ||||||
return newCtx, res, true | ||||||
} | ||||||
signerAccs[i], res = GetSignerAcc(newCtx, ak, signerAddrs[i]) | ||||||
if !res.IsOK() { | ||||||
return newCtx, res, true | ||||||
} | ||||||
|
||||||
// check signature, return account with incremented nonce | ||||||
|
@@ -417,6 +431,6 @@ func GetSignBytes(chainID string, stdTx StdTx, acc Account, genesis bool) []byte | |||||
} | ||||||
|
||||||
return StdSignBytes( | ||||||
chainID, accNum, acc.GetSequence(), stdTx.Fee, stdTx.Msgs, stdTx.Memo, | ||||||
chainID, accNum, acc.GetSequence(), stdTx.Fee, stdTx.Msgs, stdTx.Memo, stdTx.FeeAccount, | ||||||
) | ||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -67,6 +67,17 @@ func CompleteAndBroadcastTxCLI(txBldr authtypes.TxBuilder, cliCtx context.CLICon | |
return nil | ||
} | ||
|
||
// support delegated fee payments | ||
feeAccount := viper.GetString(flags.FlagFeeAccount) | ||
if len(feeAccount) != 0 { | ||
feeAcccountAddr, err := sdk.AccAddressFromBech32(feeAccount) | ||
if err != nil { | ||
return err | ||
} | ||
txBldr.WithFeeAccount(feeAcccountAddr) | ||
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.
|
||
} | ||
|
||
|
||
if !cliCtx.SkipConfirm { | ||
stdSignMsg, err := txBldr.BuildSignMsg(msgs) | ||
if err != nil { | ||
|
@@ -344,7 +355,7 @@ func buildUnsignedStdTxOffline(txBldr authtypes.TxBuilder, cliCtx context.CLICon | |
return stdTx, nil | ||
} | ||
|
||
return authtypes.NewStdTx(stdSignMsg.Msgs, stdSignMsg.Fee, nil, stdSignMsg.Memo), nil | ||
return authtypes.NewStdTx(stdSignMsg.Msgs, stdSignMsg.Fee, nil, stdSignMsg.Memo, stdSignMsg.FeeAccount), nil | ||
} | ||
|
||
func isTxSigner(user sdk.AccAddress, signers []sdk.AccAddress) bool { | ||
|
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.
Can we add a godoc to
FeeDelegationHandler
?