Skip to content

Commit

Permalink
Merge branch 'dev' into 543-extra-apis
Browse files Browse the repository at this point in the history
  • Loading branch information
cyborgshead committed Nov 15, 2020
2 parents 90aabf4 + c90dbb1 commit 207afc4
Show file tree
Hide file tree
Showing 140 changed files with 2,726 additions and 6,680 deletions.
106 changes: 56 additions & 50 deletions app/ante.go
Original file line number Diff line number Diff line change
@@ -1,84 +1,90 @@
package app

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/auth/ante"
"github.com/cosmos/cosmos-sdk/x/auth/keeper"
"github.com/cosmos/cosmos-sdk/x/auth/types"

"github.com/cybercongress/go-cyber/x/bandwidth"
)

// NewAnteHandler returns an AnteHandler that checks and increments sequence
// numbers, checks signatures & account numbers, and deducts fees from the first
// signer.
func NewAnteHandler(ak keeper.AccountKeeper, supplyKeeper types.SupplyKeeper, sigGasConsumer ante.SignatureVerificationGasConsumer) sdk.AnteHandler {
func NewAnteHandler(
ak keeper.AccountKeeper,
abk *bandwidth.BandwidthMeter,
supplyKeeper types.SupplyKeeper,
sigGasConsumer ante.SignatureVerificationGasConsumer,
) sdk.AnteHandler {
return sdk.ChainAnteDecorators(
NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first
ante.NewSetUpContextDecorator(),
ante.NewMempoolFeeDecorator(),
ante.NewValidateBasicDecorator(),
ante.NewValidateMemoDecorator(ak),
ante.NewConsumeGasForTxSizeDecorator(ak),
ante.NewSetPubKeyDecorator(ak), // SetPubKeyDecorator must be called before all signature verification decorators
ante.NewSetPubKeyDecorator(ak),
ante.NewValidateSigCountDecorator(ak),
//ante.NewDeductFeeDecorator(ak, supplyKeeper),
ante.NewDeductFeeDecorator(ak, supplyKeeper),
NewDeductBandwidthDecorator(ak, abk),
ante.NewSigGasConsumeDecorator(ak, sigGasConsumer),
ante.NewSigVerificationDecorator(ak),
ante.NewIncrementSequenceDecorator(ak), // innermost AnteDecorator
ante.NewIncrementSequenceDecorator(ak),
)
}

var (
_ GasTx = (*types.StdTx)(nil) // assert StdTx implements GasTx
_ FeeTx = (*types.StdTx)(nil)
)

// GasTx defines a Tx with a GetGas() method which is needed to use SetUpContextDecorator
type GasTx interface {
type FeeTx interface {
sdk.Tx
GetGas() uint64
GetFee() sdk.Coins
FeePayer() sdk.AccAddress
}

// SetUpContextDecorator sets the GasMeter in the Context and wraps the next AnteHandler with a defer clause
// to recover from any downstream OutOfGas panics in the AnteHandler chain to return an error with information
// on gas provided and gas used.
// CONTRACT: Must be first decorator in the chain
// CONTRACT: Tx must implement GasTx interface
type SetUpContextDecorator struct{}

func NewSetUpContextDecorator() SetUpContextDecorator {
return SetUpContextDecorator{}
type DeductBandwidthDecorator struct {
ak auth.AccountKeeper
bm *bandwidth.BandwidthMeter
}

func (sud SetUpContextDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
// all transactions must implement GasTx
gasTx, ok := tx.(GasTx)
func NewDeductBandwidthDecorator(ak auth.AccountKeeper, bm *bandwidth.BandwidthMeter) DeductBandwidthDecorator {
return DeductBandwidthDecorator{
ak: ak,
bm: bm,
}
}

func (dbd DeductBandwidthDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
feeTx, ok := tx.(FeeTx)
if !ok {
newCtx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
return newCtx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be GasTx")
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx")
}

feePayer := feeTx.FeePayer()
feePayerAcc := dbd.ak.GetAccount(ctx, feePayer)

if feePayerAcc == nil {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "fee payer address: %s does not exist", feePayer)
}

newCtx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter())

// Decorator will catch an OutOfGasPanic caused in the next antehandler
// AnteHandlers must have their own defer/recover in order for the BaseApp
// to know how much gas was used! This is because the GasMeter is created in
// the AnteHandler, but if it panics the context won't be set properly in
// runTx's recover call.
defer func() {
if r := recover(); r != nil {
switch rType := r.(type) {
case sdk.ErrorOutOfGas:
log := fmt.Sprintf(
"out of gas in location: %v; gasWanted: %d, gasUsed: %d",
rType.Descriptor, gasTx.GetGas(), newCtx.GasMeter().GasConsumed())

err = sdkerrors.Wrap(sdkerrors.ErrOutOfGas, log)
default:
panic(r)
}
}
}()

return next(newCtx, tx, simulate)
}
txCost := dbd.bm.GetPricedTxCost(ctx, tx)
accountBandwidth := dbd.bm.GetCurrentAccountBandwidth(ctx, feePayerAcc.GetAddress())

currentBlockSpentBandwidth := dbd.bm.GetCurrentBlockSpentBandwidth(ctx)
maxBlockBandwidth := dbd.bm.GetMaxBlockBandwidth(ctx)

if !accountBandwidth.HasEnoughRemained(txCost) {
return ctx, bandwidth.ErrNotEnoughBandwidth
} else if (uint64(txCost) + currentBlockSpentBandwidth) > maxBlockBandwidth {
return ctx, bandwidth.ErrExceededMaxBlockBandwidth
} else {
dbd.bm.ConsumeAccountBandwidth(ctx, accountBandwidth, txCost)
dbd.bm.AddToBlockBandwidth(txCost)
}

return next(ctx, tx, simulate)
}

Loading

0 comments on commit 207afc4

Please sign in to comment.