Skip to content
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

refactor(x/auth): Decouple store from auth module #21405

Closed
wants to merge 14 commits into from
6 changes: 6 additions & 0 deletions runtime/gas.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ type SDKGasMeter struct {
gm gas.Meter
}

func NewSDKGasMeter(gm gas.Meter) SDKGasMeter {
return SDKGasMeter{
gm: gm,
}
}

func (gm SDKGasMeter) GasConsumed() storetypes.Gas {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tac0turtle this is where i think we need a consumed API

return gm.gm.Consumed()
}
Expand Down
12 changes: 12 additions & 0 deletions types/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,18 @@ func (c Context) WithGasMeter(meter storetypes.GasMeter) Context {
return c
}

// WithNewGasMeter returns a Context with a newly created transaction GasMeter.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imho we shouldn't add anything to sdk.Context. We want to move away from it.

func (c Context) WithNewGasMeter(gaslimit storetypes.Gas) Context {
c.gasMeter = storetypes.NewGasMeter(gaslimit)
return c
Comment on lines 220 to +226
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change potentially affects state.

Call sequence:

(github.com/cosmos/cosmos-sdk/types.Context).WithBlockGasMeter (types/context.go:224)
(*github.com/cosmos/cosmos-sdk/baseapp.BaseApp).PrepareProposal (types/context.go:393)

}

// WithNewGasMeter returns a Context with a newly created transaction InfiniteGasMeter.
func (c Context) WithNewInfiniteGasMeter() Context {
c.gasMeter = storetypes.NewInfiniteGasMeter()
return c
}

// WithBlockGasMeter returns a Context with an updated block GasMeter
func (c Context) WithBlockGasMeter(meter storetypes.GasMeter) Context {
c.blockGasMeter = meter
Expand Down
19 changes: 19 additions & 0 deletions types/gas.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package types

import (
storetypes "cosmossdk.io/store/types"
)

// Wrapper errors for store/v1 ErrorOutOfGas, ErrorNegativeGasConsumed and ErrorGasOverflow so that
// modules don't have to import storev1 directly.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather have module import store tan the SDK tbh (my t.wo cents)
Can we avoid adding stuff in the SDK?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmmmm if we use stf gas implementation then we can avoid import storetypes ErrorOutOfGas all together (so i dont have to wrapped it here). But then we need to add a wrapper for the legacy sdkCtx gas meter, the problem is that the wrapper is in runtime


// ErrorNegativeGasConsumed defines an error thrown when the amount of gas refunded results in a
// negative gas consumed amount.
type ErrorNegativeGasConsumed = storetypes.ErrorNegativeGasConsumed

// ErrorOutOfGas defines an error thrown when an action results in out of gas.
type ErrorOutOfGas = storetypes.ErrorOutOfGas

// ErrorGasOverflow defines an error thrown when an action results gas consumption
// unsigned integer overflow.
type ErrorGasOverflow = storetypes.ErrorGasOverflow
6 changes: 3 additions & 3 deletions x/auth/ante/basic.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import (
"time"

appmodulev2 "cosmossdk.io/core/appmodule/v2"
"cosmossdk.io/core/gas"
"cosmossdk.io/core/transaction"
errorsmod "cosmossdk.io/errors"
storetypes "cosmossdk.io/store/types"

"github.com/cosmos/cosmos-sdk/codec/legacy"
"github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
Expand Down Expand Up @@ -139,7 +139,7 @@ func (cgts ConsumeTxSizeGasDecorator) ValidateTx(ctx context.Context, tx sdk.Tx)
params := cgts.ak.GetParams(ctx)

gasService := cgts.ak.GetEnvironment().GasService
if err := gasService.GasMeter(ctx).Consume(params.TxSizeCostPerByte*storetypes.Gas(len(tx.Bytes())), "txSize"); err != nil {
if err := gasService.GasMeter(ctx).Consume(params.TxSizeCostPerByte*gas.Gas(len(tx.Bytes())), "txSize"); err != nil {
return err
}

Expand Down Expand Up @@ -175,7 +175,7 @@ func (cgts ConsumeTxSizeGasDecorator) ValidateTx(ctx context.Context, tx sdk.Tx)
}

sigBz := legacy.Cdc.MustMarshal(simSig)
cost := storetypes.Gas(len(sigBz) + 6)
cost := gas.Gas(len(sigBz) + 6)

// If the pubkey is a multi-signature pubkey, then we estimate for the maximum
// number of signers.
Expand Down
4 changes: 2 additions & 2 deletions x/auth/ante/basic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import (
"github.com/stretchr/testify/require"

appmodulev2 "cosmossdk.io/core/appmodule/v2"
"cosmossdk.io/core/gas"
"cosmossdk.io/core/header"
storetypes "cosmossdk.io/store/types"

cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
Expand Down Expand Up @@ -138,7 +138,7 @@ func TestConsumeGasForTxSize(t *testing.T) {
require.Nil(t, err, "Cannot marshal tx: %v", err)

params := suite.accountKeeper.GetParams(suite.ctx)
expectedGas := storetypes.Gas(len(txBytes)) * params.TxSizeCostPerByte
expectedGas := gas.Gas(len(txBytes)) * params.TxSizeCostPerByte

// Set suite.ctx with TxBytes manually
suite.ctx = suite.ctx.WithTxBytes(txBytes)
Expand Down
7 changes: 3 additions & 4 deletions x/auth/ante/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (

"cosmossdk.io/core/appmodule"
errorsmod "cosmossdk.io/errors"
storetypes "cosmossdk.io/store/types"
consensusv1 "cosmossdk.io/x/consensus/types"

sdk "github.com/cosmos/cosmos-sdk/types"
Expand Down Expand Up @@ -72,7 +71,7 @@ func (sud SetUpContextDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, _ bool,
defer func() {
if r := recover(); r != nil {
switch rType := r.(type) {
case storetypes.ErrorOutOfGas:
case sdk.ErrorOutOfGas:
log := fmt.Sprintf(
"out of gas in location: %v; gasWanted: %d, gasUsed: %d",
rType.Descriptor, gasTx.GetGas(), newCtx.GasMeter().GasConsumed())
Expand All @@ -92,8 +91,8 @@ func SetGasMeter(ctx sdk.Context, gasLimit uint64) sdk.Context {
// In various cases such as simulation and during the genesis block, we do not
// meter any gas utilization.
if ctx.ExecMode() == sdk.ExecModeSimulate || ctx.BlockHeight() == 0 { // NOTE: using environment here breaks the API of SetGasMeter, an alternative must be found for server/v2. ref: https://github.com/cosmos/cosmos-sdk/issues/19640
return ctx.WithGasMeter(storetypes.NewInfiniteGasMeter())
return ctx.WithNewInfiniteGasMeter()
}

return ctx.WithGasMeter(storetypes.NewGasMeter(gasLimit))
return ctx.WithNewGasMeter(gasLimit)
}
20 changes: 17 additions & 3 deletions x/auth/ante/setup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ package ante_test
import (
"testing"

"github.com/golang/mock/gomock"
"github.com/stretchr/testify/require"

storetypes "cosmossdk.io/store/types"
"cosmossdk.io/core/gas"
gastestutil "cosmossdk.io/core/testing/gas"

cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/runtime"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
Expand Down Expand Up @@ -36,9 +39,14 @@ func TestSetupDecorator_BlockMaxGas(t *testing.T) {
sud := ante.NewSetUpContextDecorator(suite.env)
antehandler := sdk.ChainAnteDecorators(sud)

ctrl := gomock.NewController(t)
mockMeter := gastestutil.NewMockMeter(ctrl)

suite.ctx = suite.ctx.
WithBlockHeight(1).
WithGasMeter(storetypes.NewGasMeter(0))
WithGasMeter(runtime.NewSDKGasMeter(
mockMeter,
))

_, err = antehandler(suite.ctx, tx, false)
require.Error(t, err)
Expand Down Expand Up @@ -66,8 +74,14 @@ func TestSetup(t *testing.T) {
sud := ante.NewSetUpContextDecorator(suite.env)
antehandler := sdk.ChainAnteDecorators(sud)

ctrl := gomock.NewController(t)
mockMeter := gastestutil.NewMockMeter(ctrl)
mockMeter.EXPECT().Limit().Return(gas.Gas(0)).Times(1)

// Set height to non-zero value for GasMeter to be set
suite.ctx = suite.ctx.WithBlockHeight(1).WithGasMeter(storetypes.NewGasMeter(0))
suite.ctx = suite.ctx.WithBlockHeight(1).WithGasMeter(runtime.NewSDKGasMeter(
mockMeter,
))

// Context GasMeter Limit not set
require.Equal(t, uint64(0), suite.ctx.GasMeter().Limit(), "GasMeter set with limit before setup")
Expand Down
3 changes: 1 addition & 2 deletions x/auth/ante/sigverify_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"cosmossdk.io/core/gas"
"cosmossdk.io/core/header"
gastestutil "cosmossdk.io/core/testing/gas"
storetypes "cosmossdk.io/store/types"
txsigning "cosmossdk.io/x/tx/signing"

"github.com/cosmos/cosmos-sdk/codec"
Expand Down Expand Up @@ -302,7 +301,7 @@ func TestSigIntegration(t *testing.T) {
require.Equal(t, initialSigCost*uint64(len(privs)), doubleCost-initialCost)
}

func runSigDecorators(t *testing.T, params types.Params, privs ...cryptotypes.PrivKey) (storetypes.Gas, error) {
func runSigDecorators(t *testing.T, params types.Params, privs ...cryptotypes.PrivKey) (gas.Gas, error) {
t.Helper()
suite := SetupTestSuite(t, true)
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
Expand Down
5 changes: 2 additions & 3 deletions x/auth/ante/testutil_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
"cosmossdk.io/core/appmodule"
"cosmossdk.io/core/header"
coretesting "cosmossdk.io/core/testing"
storetypes "cosmossdk.io/store/types"
consensustypes "cosmossdk.io/x/consensus/types"

"github.com/cosmos/cosmos-sdk/baseapp"
Expand Down Expand Up @@ -76,8 +75,8 @@
suite.feeGrantKeeper = antetestutil.NewMockFeegrantKeeper(ctrl)
suite.acctsModKeeper = authtestutil.NewMockAccountsModKeeper(ctrl)

key := storetypes.NewKVStoreKey(types.StoreKey)
testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test"))
key := runtime.NewKVStoreKey(types.StoreKey)

Check failure on line 78 in x/auth/ante/testutil_test.go

View workflow job for this annotation

GitHub Actions / golangci-lint

undefined: runtime.NewKVStoreKey

Check failure on line 78 in x/auth/ante/testutil_test.go

View workflow job for this annotation

GitHub Actions / tests (02)

undefined: runtime.NewKVStoreKey
testCtx := testutil.DefaultContextWithDB(t, key, runtime.NewTransientStoreKey("transient_test"))

Check failure on line 79 in x/auth/ante/testutil_test.go

View workflow job for this annotation

GitHub Actions / golangci-lint

undefined: runtime.NewTransientStoreKey (typecheck)

Check failure on line 79 in x/auth/ante/testutil_test.go

View workflow job for this annotation

GitHub Actions / tests (02)

undefined: runtime.NewTransientStoreKey
suite.ctx = testCtx.Ctx.WithIsCheckTx(isCheckTx).WithBlockHeight(1).WithHeaderInfo(header.Info{Height: 1, ChainID: testCtx.Ctx.ChainID()})
suite.encCfg = moduletestutil.MakeTestEncodingConfig(codectestutil.CodecOptions{}, auth.AppModule{})

Expand Down
31 changes: 27 additions & 4 deletions x/auth/ante/unordered_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import (
"testing"
"time"

"github.com/golang/mock/gomock"
"github.com/stretchr/testify/require"

"cosmossdk.io/core/header"
storetypes "cosmossdk.io/store/types"
gastestutil "cosmossdk.io/core/testing/gas"

cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/runtime"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
Expand Down Expand Up @@ -88,7 +90,14 @@ func TestUnorderedTxDecorator_UnorderedTx_AlreadyExists(t *testing.T) {
chain := sdk.ChainAnteDecorators(ante.NewUnorderedTxDecorator(unorderedtx.DefaultMaxTimeoutDuration, txm, suite.accountKeeper.GetEnvironment(), ante.DefaultSha256Cost))

tx, txBz := genUnorderedTx(t, true, time.Now().Add(time.Minute))
ctx := sdk.Context{}.WithTxBytes(txBz).WithHeaderInfo(header.Info{Time: time.Now()}).WithGasMeter(storetypes.NewGasMeter(gasConsumed))

ctrl := gomock.NewController(t)
mockMeter := gastestutil.NewMockMeter(ctrl)
mockMeter.EXPECT().Consume(gasConsumed, "consume gas for calculating tx hash").Times(1)

ctx := sdk.Context{}.WithTxBytes(txBz).WithHeaderInfo(header.Info{Time: time.Now()}).WithGasMeter(runtime.NewSDKGasMeter(
mockMeter,
))

bz := [32]byte{}
copy(bz[:], txBz[:32])
Expand All @@ -111,7 +120,14 @@ func TestUnorderedTxDecorator_UnorderedTx_ValidCheckTx(t *testing.T) {
chain := sdk.ChainAnteDecorators(ante.NewUnorderedTxDecorator(unorderedtx.DefaultMaxTimeoutDuration, txm, suite.accountKeeper.GetEnvironment(), ante.DefaultSha256Cost))

tx, txBz := genUnorderedTx(t, true, time.Now().Add(time.Minute))
ctx := sdk.Context{}.WithTxBytes(txBz).WithHeaderInfo(header.Info{Time: time.Now()}).WithExecMode(sdk.ExecModeCheck).WithGasMeter(storetypes.NewGasMeter(gasConsumed))

ctrl := gomock.NewController(t)
mockMeter := gastestutil.NewMockMeter(ctrl)
mockMeter.EXPECT().Consume(gasConsumed, "consume gas for calculating tx hash").Times(1)

ctx := sdk.Context{}.WithTxBytes(txBz).WithHeaderInfo(header.Info{Time: time.Now()}).WithExecMode(sdk.ExecModeCheck).WithGasMeter(runtime.NewSDKGasMeter(
mockMeter,
))

_, err := chain(ctx, tx, false)
require.NoError(t, err)
Expand All @@ -130,7 +146,14 @@ func TestUnorderedTxDecorator_UnorderedTx_ValidDeliverTx(t *testing.T) {
chain := sdk.ChainAnteDecorators(ante.NewUnorderedTxDecorator(unorderedtx.DefaultMaxTimeoutDuration, txm, suite.accountKeeper.GetEnvironment(), ante.DefaultSha256Cost))

tx, txBz := genUnorderedTx(t, true, time.Now().Add(time.Minute))
ctx := sdk.Context{}.WithTxBytes(txBz).WithHeaderInfo(header.Info{Time: time.Now()}).WithExecMode(sdk.ExecModeFinalize).WithGasMeter(storetypes.NewGasMeter(gasConsumed))

ctrl := gomock.NewController(t)
mockMeter := gastestutil.NewMockMeter(ctrl)
mockMeter.EXPECT().Consume(gasConsumed, "consume gas for calculating tx hash").Times(1)

ctx := sdk.Context{}.WithTxBytes(txBz).WithHeaderInfo(header.Info{Time: time.Now()}).WithExecMode(sdk.ExecModeFinalize).WithGasMeter(runtime.NewSDKGasMeter(
mockMeter,
))

_, err := chain(ctx, tx, false)
require.NoError(t, err)
Expand Down
44 changes: 37 additions & 7 deletions x/auth/ante/unorderedtx/snapshotter.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import (
"errors"
"io"
"time"

snapshot "cosmossdk.io/store/snapshots/types"
)

const (
Expand All @@ -15,7 +13,39 @@ const (
chunkSize = txHashSize + timeoutSize
)

var _ snapshot.ExtensionSnapshotter = &Snapshotter{}
// ErrUnknownFormat is returned when an unknown format is used.
var ErrUnknownFormat = errors.New("unknown snapshot format")

// ExtensionPayloadReader read extension payloads,
// it returns io.EOF when reached either end of stream or the extension boundaries.
type ExtensionPayloadReader = func() ([]byte, error)

// ExtensionPayloadWriter is a helper to write extension payloads to underlying stream.
type ExtensionPayloadWriter = func([]byte) error

// ExtensionSnapshotter is an extension Snapshotter that is appended to the snapshot stream.
// ExtensionSnapshotter has an unique name and manages it's own internal formats.
type ExtensionSnapshotter interface {
// SnapshotName returns the name of snapshotter, it should be unique in the manager.
SnapshotName() string

// SnapshotFormat returns the default format the extension snapshotter use to encode the
// payloads when taking a snapshot.
// It's defined within the extension, different from the global format for the whole state-sync snapshot.
SnapshotFormat() uint32

// SupportedFormats returns a list of formats it can restore from.
SupportedFormats() []uint32

// SnapshotExtension writes extension payloads into the underlying protobuf stream.
SnapshotExtension(height uint64, payloadWriter ExtensionPayloadWriter) error

// RestoreExtension restores an extension state snapshot,
// the payload reader returns `io.EOF` when reached the extension boundaries.
RestoreExtension(height uint64, format uint32, payloadReader ExtensionPayloadReader) error
}

var _ ExtensionSnapshotter = &Snapshotter{}

const (
// SnapshotFormat defines the snapshot format of exported unordered transactions.
Expand Down Expand Up @@ -46,20 +76,20 @@ func (s *Snapshotter) SupportedFormats() []uint32 {
return []uint32{SnapshotFormat}
}

func (s *Snapshotter) SnapshotExtension(height uint64, payloadWriter snapshot.ExtensionPayloadWriter) error {
func (s *Snapshotter) SnapshotExtension(height uint64, payloadWriter ExtensionPayloadWriter) error {
// export all unordered transactions as a single blob
return s.m.exportSnapshot(height, payloadWriter)
}

func (s *Snapshotter) RestoreExtension(height uint64, format uint32, payloadReader snapshot.ExtensionPayloadReader) error {
func (s *Snapshotter) RestoreExtension(height uint64, format uint32, payloadReader ExtensionPayloadReader) error {
if format == SnapshotFormat {
return s.restore(height, payloadReader)
}

return snapshot.ErrUnknownFormat
return ErrUnknownFormat
}

func (s *Snapshotter) restore(height uint64, payloadReader snapshot.ExtensionPayloadReader) error {
func (s *Snapshotter) restore(height uint64, payloadReader ExtensionPayloadReader) error {
// the payload should be the entire set of unordered transactions
payload, err := payloadReader()
if err != nil {
Expand Down
7 changes: 2 additions & 5 deletions x/auth/keeper/deterministic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
"cosmossdk.io/core/appmodule"
"cosmossdk.io/core/header"
coretesting "cosmossdk.io/core/testing"
storetypes "cosmossdk.io/store/types"

"github.com/cosmos/cosmos-sdk/baseapp"
codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil"
Expand All @@ -36,7 +35,6 @@

accountNumberLanes uint64

key *storetypes.KVStoreKey
environment appmodule.Environment
ctx sdk.Context
queryClient types.QueryClient
Expand All @@ -60,10 +58,10 @@
suite.encCfg = moduletestutil.MakeTestEncodingConfig(codectestutil.CodecOptions{}, auth.AppModule{})

suite.Require()
key := storetypes.NewKVStoreKey(types.StoreKey)
key := runtime.NewKVStoreKey(types.StoreKey)

Check failure on line 61 in x/auth/keeper/deterministic_test.go

View workflow job for this annotation

GitHub Actions / golangci-lint

undefined: runtime.NewKVStoreKey

Check failure on line 61 in x/auth/keeper/deterministic_test.go

View workflow job for this annotation

GitHub Actions / tests (03)

undefined: runtime.NewKVStoreKey
storeService := runtime.NewKVStoreService(key)
env := runtime.NewEnvironment(storeService, coretesting.NewNopLogger())
testCtx := testutil.DefaultContextWithDB(suite.T(), key, storetypes.NewTransientStoreKey("transient_test"))
testCtx := testutil.DefaultContextWithDB(suite.T(), key, runtime.NewTransientStoreKey("transient_test"))

Check failure on line 64 in x/auth/keeper/deterministic_test.go

View workflow job for this annotation

GitHub Actions / golangci-lint

undefined: runtime.NewTransientStoreKey

Check failure on line 64 in x/auth/keeper/deterministic_test.go

View workflow job for this annotation

GitHub Actions / tests (03)

undefined: runtime.NewTransientStoreKey
suite.ctx = testCtx.Ctx.WithHeaderInfo(header.Info{})

// gomock initializations
Expand Down Expand Up @@ -101,7 +99,6 @@
types.RegisterQueryServer(queryHelper, keeper.NewQueryServer(suite.accountKeeper))
suite.queryClient = types.NewQueryClient(queryHelper)

suite.key = key
suite.environment = env
suite.maccPerms = maccPerms
suite.accountNumberLanes = 1
Expand Down
Loading
Loading