From 4432869f2767536f33cd4d1af3b44e37650e9ace Mon Sep 17 00:00:00 2001 From: Yaroslav Savchuk Date: Fri, 10 Nov 2023 13:32:14 +0100 Subject: [PATCH] finalize --- x/deterministicgas/ante/ante.go | 25 ++++++++++++++++++++----- x/deterministicgas/spec/README.md | 21 +++++++++++++-------- x/deterministicgas/spec/README.tmpl.md | 21 +++++++++++++-------- x/deterministicgas/spec/generate.go | 7 +++++-- 4 files changed, 51 insertions(+), 23 deletions(-) diff --git a/x/deterministicgas/ante/ante.go b/x/deterministicgas/ante/ante.go index ccbd6be1c..eef32a302 100644 --- a/x/deterministicgas/ante/ante.go +++ b/x/deterministicgas/ante/ante.go @@ -1,12 +1,27 @@ package ante import ( + "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" authante "github.com/cosmos/cosmos-sdk/x/auth/ante" "github.com/CoreumFoundation/coreum/v3/x/deterministicgas" ) +type debugGasMeter struct { + sdk.GasMeter +} + +func newDBG(g sdk.GasMeter) debugGasMeter { + return debugGasMeter{g} +} + +func (dbg debugGasMeter) ConsumeGas(amount sdk.Gas, descriptor string) { + fmt.Printf("dbg gas: %v descriptor: %v\n", amount, descriptor) + dbg.GasMeter.ConsumeGas(amount, descriptor) +} + // SetInfiniteGasMeterDecorator sets the infinite gas limit for ante handler // CONTRACT: Must be the first decorator in the chain. // CONTRACT: Tx must implement GasTx interface. @@ -28,7 +43,7 @@ func (sigmd SetInfiniteGasMeterDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, ctx.GasMeter().ConsumeGas(sigmd.deterministicGasConfig.FixedGas, "Fixed") // Set infinite gas meter for ante handler - return next(ctx.WithGasMeter(sdk.NewInfiniteGasMeter()), tx, simulate) + return next(ctx.WithGasMeter(newDBG(sdk.NewInfiniteGasMeter())), tx, simulate) } // AddBaseGasDecorator adds free gas to gas meter. @@ -52,14 +67,14 @@ func (abgd AddBaseGasDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate if simulate || ctx.BlockHeight() == 0 { // During simulation and genesis initialization infinite gas meter is set inside context by `SetUpContextDecorator`. // Here, we reset it to initial state with 0 gas consumed. - gasMeter = sdk.NewInfiniteGasMeter() + gasMeter = newDBG(sdk.NewInfiniteGasMeter()) } else { params := abgd.ak.GetParams(ctx) // It is not needed to verify that tx really implements `GasTx` interface because it has been already done by // `SetUpContextDecorator` gasTx := tx.(authante.GasTx) - gasMeter = sdk.NewGasMeter(gasTx.GetGas() + abgd.deterministicGasConfig.TxBaseGas(params)) + gasMeter = newDBG(sdk.NewGasMeter(gasTx.GetGas() + abgd.deterministicGasConfig.TxBaseGas(params))) } return next(ctx.WithGasMeter(gasMeter), tx, simulate) } @@ -91,9 +106,9 @@ func (cfgd ChargeFixedGasDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simul if simulate || ctx.BlockHeight() == 0 { // During simulation and genesis initialization infinite gas meter is set inside context by `SetUpContextDecorator`. // We reset it to initial state with 0 gas consumed. - gasMeter = sdk.NewInfiniteGasMeter() + gasMeter = newDBG(sdk.NewInfiniteGasMeter()) } else { - gasMeter = sdk.NewGasMeter(gasTx.GetGas()) + gasMeter = newDBG(sdk.NewGasMeter(gasTx.GetGas())) } gasConsumed := ctx.GasMeter().GasConsumed() diff --git a/x/deterministicgas/spec/README.md b/x/deterministicgas/spec/README.md index 4d1823dc4..fc9a439db 100644 --- a/x/deterministicgas/spec/README.md +++ b/x/deterministicgas/spec/README.md @@ -16,31 +16,36 @@ complicated, nondeterministic execution path (e.g `/cosmwasm.wasm.v1.MsgExecuteC Here is formula for the transaction ` -Gas = FixedGas + Sum(Gas for each message) + GasForExtraBytes + GasForExtraSignatures +Gas = FixedGas + max((GasForBytes + GasForSignatures - TxBaseGas), 0) + Sum(Gas for each message) ` If message type is deterministic, then the value is looked up from the table, if it is non-deterministic, then the required gas is determined after the execution. ` -GasForExtraBytes = max(0, TxByteSize-FreeBytes) * TxSizeCostPerByte +GasForBytes = TxByteSize * TxSizeCostPerByte ` ` -GasForExtraSignatures = max(0, NumOfSigs-FreeSigs) * SigVerifyCost +GasForSignatures = NumOfSigs * SigVerifyCost ` Currently, we have values for the above variables as follows: - `FixedGas`: 65000 +- `TxBaseGas`: 21480 - `SigVerifyCost`: 1000 - `TxSizeCostPerByte`: 10 - `FreeSignatures`: 1 - `FreeBytes`: 2048 -As an example if the transaction has 1 signature on it and is below -2048 bytes, the user will not pay anything extra, and if one of those values exceed those limits, the user will pay for -the extra resources. + +To summarize user pays FixedGas as long as `GasForBytes + GasForSignatures <= TxBaseGas`. +If `GasForBytes + GasForSignatures > TxBaseGas` user will have to pay anything above `TxBaseGas` on top of `FixedGas`. + +As an example if the transaction has 1 signature on it and size is below +2048 bytes, the user will not pay anything extra. Or user can have multiple signatures but fewer bytes then nothing extra should be paid. + ### Full examples @@ -50,7 +55,7 @@ Let's say we have a transaction with 1 messages of type signatures and the tx size is 1000 bytes, total will be: ` -TotalGas = 65000 + 1 * 50000 + (1 - 1) * 1000 + max(0, 1000-2048) * 10 +TotalGas = 65000 + max(0, (21480 - 1 * 1000 + 1000 * 10)) + 1 * 50000 ` #### Example 2 @@ -59,7 +64,7 @@ Let's say we have a transaction with 2 messages of type signatures and the tx size is 2050 bytes, total will be: ` -TotalGas = 65000 + 2 * 70000 + (2 - 1) * 1000 + max(0, 2050-2048) * 10 +TotalGas = 65000 + max(0, (21480 - 2 * 1000 + 2050 * 10)) + 2 * 70000 ` ## Gas Tables diff --git a/x/deterministicgas/spec/README.tmpl.md b/x/deterministicgas/spec/README.tmpl.md index b91c67f76..ff6767282 100644 --- a/x/deterministicgas/spec/README.tmpl.md +++ b/x/deterministicgas/spec/README.tmpl.md @@ -15,31 +15,36 @@ complicated, nondeterministic execution path (e.g `/cosmwasm.wasm.v1.MsgExecuteC Here is formula for the transaction ` -Gas = FixedGas + Sum(Gas for each message) + GasForExtraBytes + GasForExtraSignatures +Gas = FixedGas + max((GasForBytes + GasForSignatures - TxBaseGas), 0) + Sum(Gas for each message) ` If message type is deterministic, then the value is looked up from the table, if it is non-deterministic, then the required gas is determined after the execution. ` -GasForExtraBytes = max(0, TxByteSize-FreeBytes) * TxSizeCostPerByte +GasForBytes = TxByteSize * TxSizeCostPerByte ` ` -GasForExtraSignatures = max(0, NumOfSigs-FreeSigs) * SigVerifyCost +GasForSignatures = NumOfSigs * SigVerifyCost ` Currently, we have values for the above variables as follows: - `FixedGas`: {{ .FixedGas }} +- `TxBaseGas`: {{ .TxBaseGas }} - `SigVerifyCost`: {{ .SigVerifyCost }} - `TxSizeCostPerByte`: {{ .TxSizeCostPerByte }} - `FreeSignatures`: {{ .FreeSignatures }} - `FreeBytes`: {{ .FreeBytes }} -As an example if the transaction has 1 signature on it and is below -2048 bytes, the user will not pay anything extra, and if one of those values exceed those limits, the user will pay for -the extra resources. + +To summarize user pays FixedGas as long as `GasForBytes + GasForSignatures <= TxBaseGas`. +If `GasForBytes + GasForSignatures > TxBaseGas` user will have to pay anything above `TxBaseGas` on top of `FixedGas`. + +As an example if the transaction has 1 signature on it and size is below +2048 bytes, the user will not pay anything extra. Or user can have multiple signatures but fewer bytes then nothing extra should be paid. + ### Full examples @@ -49,7 +54,7 @@ Let's say we have a transaction with 1 messages of type signatures and the tx size is 1000 bytes, total will be: ` -TotalGas = {{ .FixedGas }} + 1 * {{ .BankSendPerCoinGas }} + (1 - 1) * {{ .SigVerifyCost }} + max(0, 1000-{{ .FreeBytes }}) * {{ .TxSizeCostPerByte }} +TotalGas = {{ .FixedGas }} + max(0, ({{ .TxBaseGas }} - 1 * {{ .SigVerifyCost }} + 1000 * {{ .TxSizeCostPerByte }})) + 1 * {{ .BankSendPerCoinGas }} ` #### Example 2 @@ -58,7 +63,7 @@ Let's say we have a transaction with 2 messages of type signatures and the tx size is 2050 bytes, total will be: ` -TotalGas = {{ .FixedGas }} + 2 * {{ .MsgIssueGasPrice }} + (2 - 1) * {{ .SigVerifyCost }} + max(0, 2050-{{ .FreeBytes }}) * {{ .TxSizeCostPerByte }} +TotalGas = {{ .FixedGas }} + max(0, ({{ .TxBaseGas }} - 2 * {{ .SigVerifyCost }} + 2050 * {{ .TxSizeCostPerByte }})) + 2 * {{ .MsgIssueGasPrice }} ` ## Gas Tables diff --git a/x/deterministicgas/spec/generate.go b/x/deterministicgas/spec/generate.go index ac1257b81..c17e6462e 100644 --- a/x/deterministicgas/spec/generate.go +++ b/x/deterministicgas/spec/generate.go @@ -73,11 +73,13 @@ func main() { panic(err) } + authParams := auth.DefaultParams() err = template.Must(template.New("README.md").Parse(readmeTmpl)).Execute(file, struct { GeneratorComment string SigVerifyCost uint64 TxSizeCostPerByte uint64 FixedGas uint64 + TxBaseGas uint64 FreeBytes uint64 FreeSignatures uint64 @@ -95,8 +97,9 @@ func main() { }{ GeneratorComment: generatorComment, FixedGas: cfg.FixedGas, - SigVerifyCost: auth.DefaultSigVerifyCostSecp256k1, - TxSizeCostPerByte: auth.DefaultTxSizeCostPerByte, + TxBaseGas: cfg.TxBaseGas(authParams), + SigVerifyCost: authParams.SigVerifyCostSecp256k1, + TxSizeCostPerByte: authParams.TxSizeCostPerByte, FreeBytes: cfg.FreeBytes, FreeSignatures: cfg.FreeSignatures,