chore: cleanup core/app (#21368)
This commit is contained in:
parent
58af7ee027
commit
355f748add
@ -1,24 +0,0 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"cosmossdk.io/core/transaction"
|
||||
)
|
||||
|
||||
// MsgInterfaceProtoName defines the protobuf name of the cosmos Msg interface
|
||||
const MsgInterfaceProtoName = "cosmos.base.v1beta1.Msg"
|
||||
|
||||
type ProtoCodec interface {
|
||||
Marshal(v transaction.Msg) ([]byte, error)
|
||||
Unmarshal(data []byte, v transaction.Msg) error
|
||||
Name() string
|
||||
}
|
||||
|
||||
type InterfaceRegistry interface {
|
||||
AnyResolver
|
||||
ListImplementations(ifaceTypeURL string) []string
|
||||
ListAllInterfaces() []string
|
||||
}
|
||||
|
||||
type AnyResolver = interface {
|
||||
Resolve(typeUrl string) (transaction.Msg, error)
|
||||
}
|
||||
@ -1,6 +0,0 @@
|
||||
package app
|
||||
|
||||
var (
|
||||
RuntimeIdentity = []byte("runtime")
|
||||
ConsensusIdentity = []byte("consensus")
|
||||
)
|
||||
@ -1,4 +1,4 @@
|
||||
package app
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -9,17 +9,7 @@ import (
|
||||
"cosmossdk.io/core/transaction"
|
||||
)
|
||||
|
||||
type QueryRequest struct {
|
||||
Height int64
|
||||
Path string
|
||||
Data []byte
|
||||
}
|
||||
|
||||
type QueryResponse struct {
|
||||
Height int64
|
||||
Value []byte
|
||||
}
|
||||
|
||||
// BlockRequest defines the request structure for a block coming from consensus server to the state transition function.
|
||||
type BlockRequest[T transaction.Tx] struct {
|
||||
Height uint64
|
||||
Time time.Time
|
||||
@ -32,8 +22,8 @@ type BlockRequest[T transaction.Tx] struct {
|
||||
IsGenesis bool
|
||||
}
|
||||
|
||||
// BlockResponse defines the response structure for a block coming from the state transition function to consensus server.
|
||||
type BlockResponse struct {
|
||||
Apphash []byte
|
||||
ValidatorUpdates []appmodulev2.ValidatorUpdate
|
||||
PreBlockEvents []event.Event
|
||||
BeginBlockEvents []event.Event
|
||||
@ -41,30 +31,22 @@ type BlockResponse struct {
|
||||
EndBlockEvents []event.Event
|
||||
}
|
||||
|
||||
type RequestInitChain struct {
|
||||
Time time.Time
|
||||
ChainId string
|
||||
Validators []appmodulev2.ValidatorUpdate
|
||||
AppStateBytes []byte
|
||||
InitialHeight int64
|
||||
}
|
||||
|
||||
type ResponseInitChain struct {
|
||||
Validators []appmodulev2.ValidatorUpdate
|
||||
AppHash []byte
|
||||
}
|
||||
|
||||
// TxResult defines the result of a transaction execution.
|
||||
type TxResult struct {
|
||||
Events []event.Event
|
||||
Resp []transaction.Msg
|
||||
Error error
|
||||
Code uint32
|
||||
Data []byte
|
||||
Log string
|
||||
Info string
|
||||
// Events produced by the transaction.
|
||||
Events []event.Event
|
||||
// Response messages produced by the transaction.
|
||||
Resp []transaction.Msg
|
||||
// Error produced by the transaction.
|
||||
Error error
|
||||
// Code produced by the transaction.
|
||||
// A non-zero code is an error that is either define by the module via the cosmossdk.io/errors/v2 package
|
||||
// or injected through the antehandler along the execution of the transaction.
|
||||
Code uint32
|
||||
// GasWanted is the maximum units of work we allow this tx to perform.
|
||||
GasWanted uint64
|
||||
GasUsed uint64
|
||||
Codespace string
|
||||
// GasUsed is the amount of gas actually consumed.
|
||||
GasUsed uint64
|
||||
}
|
||||
|
||||
// VersionModifier defines the interface fulfilled by BaseApp
|
||||
20
core/server/codec.go
Normal file
20
core/server/codec.go
Normal file
@ -0,0 +1,20 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"cosmossdk.io/core/transaction"
|
||||
)
|
||||
|
||||
// InterfaceRegistry defines the interface for resolving interfaces
|
||||
// The interface registry is used to resolve interfaces from type URLs,
|
||||
// this is only used for the server and not for modules
|
||||
type InterfaceRegistry interface {
|
||||
AnyResolver
|
||||
ListImplementations(ifaceTypeURL string) []string
|
||||
ListAllInterfaces() []string
|
||||
}
|
||||
|
||||
// AnyResolver defines the interface for resolving interfaces
|
||||
// This is used to avoid the gogoproto import in core
|
||||
type AnyResolver = interface {
|
||||
Resolve(typeUrl string) (transaction.Msg, error)
|
||||
}
|
||||
4
core/server/doc.go
Normal file
4
core/server/doc.go
Normal file
@ -0,0 +1,4 @@
|
||||
// Server Defines types and interfaces which are shared between Consensus, Appmanager and Stf
|
||||
// This package is not meant to be used directly by modules instead if an advanced user would like
|
||||
// to create a custom server or replace a component in the server they will need to use the app package.
|
||||
package server
|
||||
@ -12,10 +12,10 @@ import (
|
||||
runtimev1alpha1 "cosmossdk.io/api/cosmos/app/runtime/v1alpha1"
|
||||
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
|
||||
reflectionv1 "cosmossdk.io/api/cosmos/reflection/v1"
|
||||
"cosmossdk.io/core/app"
|
||||
"cosmossdk.io/core/appmodule"
|
||||
"cosmossdk.io/core/comet"
|
||||
"cosmossdk.io/core/legacy"
|
||||
"cosmossdk.io/core/server"
|
||||
"cosmossdk.io/core/store"
|
||||
"cosmossdk.io/depinject"
|
||||
"cosmossdk.io/depinject/appconfig"
|
||||
@ -288,7 +288,7 @@ func ProvideTransientStoreService(
|
||||
return transientStoreService{key: storeKey}
|
||||
}
|
||||
|
||||
func ProvideAppVersionModifier(app *AppBuilder) app.VersionModifier {
|
||||
func ProvideAppVersionModifier(app *AppBuilder) server.VersionModifier {
|
||||
return app.app
|
||||
}
|
||||
|
||||
|
||||
@ -15,11 +15,11 @@ import (
|
||||
appv1alpha1 "cosmossdk.io/api/cosmos/app/v1alpha1"
|
||||
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
|
||||
reflectionv1 "cosmossdk.io/api/cosmos/reflection/v1"
|
||||
"cosmossdk.io/core/app"
|
||||
appmodulev2 "cosmossdk.io/core/appmodule/v2"
|
||||
"cosmossdk.io/core/comet"
|
||||
"cosmossdk.io/core/legacy"
|
||||
"cosmossdk.io/core/registry"
|
||||
"cosmossdk.io/core/server"
|
||||
"cosmossdk.io/core/store"
|
||||
"cosmossdk.io/core/transaction"
|
||||
"cosmossdk.io/depinject"
|
||||
@ -240,8 +240,8 @@ func ProvideCometService() comet.Service {
|
||||
return &services.ContextAwareCometInfoService{}
|
||||
}
|
||||
|
||||
// ProvideAppVersionModifier returns nil, `app.VersionModifier` is a feature of BaseApp and neither used nor required for runtim/v2.
|
||||
// ProvideAppVersionModifier returns nil, `app.VersionModifier` is a feature of BaseApp and neither used nor required for runtime/v2.
|
||||
// nil is acceptable, see: https://github.com/cosmos/cosmos-sdk/blob/0a6ee406a02477ae8ccbfcbe1b51fc3930087f4c/x/upgrade/keeper/keeper.go#L438
|
||||
func ProvideAppVersionModifier[T transaction.Tx](app *AppBuilder[T]) app.VersionModifier {
|
||||
func ProvideAppVersionModifier[T transaction.Tx](app *AppBuilder[T]) server.VersionModifier {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -9,15 +9,23 @@ import (
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
_ "cosmossdk.io/api/amino" // Import amino.proto file for reflection
|
||||
appmanager "cosmossdk.io/core/app"
|
||||
"cosmossdk.io/core/server"
|
||||
"cosmossdk.io/core/transaction"
|
||||
)
|
||||
|
||||
// protocdc defines the interface for marshaling and unmarshaling messages in server/v2
|
||||
type protocdc interface {
|
||||
Marshal(v transaction.Msg) ([]byte, error)
|
||||
Unmarshal(data []byte, v transaction.Msg) error
|
||||
Name() string
|
||||
}
|
||||
|
||||
type protoCodec struct {
|
||||
interfaceRegistry appmanager.InterfaceRegistry
|
||||
interfaceRegistry server.InterfaceRegistry
|
||||
}
|
||||
|
||||
// newProtoCodec returns a reference to a new ProtoCodec
|
||||
func newProtoCodec(interfaceRegistry appmanager.InterfaceRegistry) *protoCodec {
|
||||
func newProtoCodec(interfaceRegistry server.InterfaceRegistry) *protoCodec {
|
||||
return &protoCodec{
|
||||
interfaceRegistry: interfaceRegistry,
|
||||
}
|
||||
@ -62,7 +70,7 @@ func (pc *protoCodec) GRPCCodec() encoding.Codec {
|
||||
|
||||
// grpcProtoCodec is the implementation of the gRPC proto codec.
|
||||
type grpcProtoCodec struct {
|
||||
cdc appmanager.ProtoCodec
|
||||
cdc protocdc
|
||||
}
|
||||
|
||||
var errUnknownProtoType = errors.New("codec: unknown proto type") // sentinel error
|
||||
|
||||
@ -7,7 +7,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
appmanager "cosmossdk.io/core/app"
|
||||
"cosmossdk.io/core/server"
|
||||
corestore "cosmossdk.io/core/store"
|
||||
"cosmossdk.io/core/transaction"
|
||||
)
|
||||
@ -39,10 +39,10 @@ type AppManager[T transaction.Tx] struct {
|
||||
// InitGenesis initializes the genesis state of the application.
|
||||
func (a AppManager[T]) InitGenesis(
|
||||
ctx context.Context,
|
||||
blockRequest *appmanager.BlockRequest[T],
|
||||
blockRequest *server.BlockRequest[T],
|
||||
initGenesisJSON []byte,
|
||||
txDecoder transaction.Codec[T],
|
||||
) (*appmanager.BlockResponse, corestore.WriterMap, error) {
|
||||
) (*server.BlockResponse, corestore.WriterMap, error) {
|
||||
v, zeroState, err := a.db.StateLatest()
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to get latest state: %w", err)
|
||||
@ -116,8 +116,8 @@ func (a AppManager[T]) ExportGenesis(ctx context.Context, version uint64) ([]byt
|
||||
|
||||
func (a AppManager[T]) DeliverBlock(
|
||||
ctx context.Context,
|
||||
block *appmanager.BlockRequest[T],
|
||||
) (*appmanager.BlockResponse, corestore.WriterMap, error) {
|
||||
block *server.BlockRequest[T],
|
||||
) (*server.BlockResponse, corestore.WriterMap, error) {
|
||||
latestVersion, currentState, err := a.db.StateLatest()
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to create new state for height %d: %w", block.Height, err)
|
||||
@ -138,19 +138,19 @@ func (a AppManager[T]) DeliverBlock(
|
||||
// ValidateTx will validate the tx against the latest storage state. This means that
|
||||
// only the stateful validation will be run, not the execution portion of the tx.
|
||||
// If full execution is needed, Simulate must be used.
|
||||
func (a AppManager[T]) ValidateTx(ctx context.Context, tx T) (appmanager.TxResult, error) {
|
||||
func (a AppManager[T]) ValidateTx(ctx context.Context, tx T) (server.TxResult, error) {
|
||||
_, latestState, err := a.db.StateLatest()
|
||||
if err != nil {
|
||||
return appmanager.TxResult{}, err
|
||||
return server.TxResult{}, err
|
||||
}
|
||||
return a.stf.ValidateTx(ctx, latestState, a.config.ValidateTxGasLimit, tx), nil
|
||||
}
|
||||
|
||||
// Simulate runs validation and execution flow of a Tx.
|
||||
func (a AppManager[T]) Simulate(ctx context.Context, tx T) (appmanager.TxResult, corestore.WriterMap, error) {
|
||||
func (a AppManager[T]) Simulate(ctx context.Context, tx T) (server.TxResult, corestore.WriterMap, error) {
|
||||
_, state, err := a.db.StateLatest()
|
||||
if err != nil {
|
||||
return appmanager.TxResult{}, nil, err
|
||||
return server.TxResult{}, nil, err
|
||||
}
|
||||
result, cs := a.stf.Simulate(ctx, state, a.config.SimulationGasLimit, tx) // TODO: check if this is done in the antehandler
|
||||
return result, cs, nil
|
||||
|
||||
@ -3,7 +3,7 @@ package appmanager
|
||||
import (
|
||||
"context"
|
||||
|
||||
appmanager "cosmossdk.io/core/app"
|
||||
"cosmossdk.io/core/server"
|
||||
"cosmossdk.io/core/store"
|
||||
"cosmossdk.io/core/transaction"
|
||||
)
|
||||
@ -13,9 +13,9 @@ type StateTransitionFunction[T transaction.Tx] interface {
|
||||
// DeliverBlock executes a block of transactions.
|
||||
DeliverBlock(
|
||||
ctx context.Context,
|
||||
block *appmanager.BlockRequest[T],
|
||||
block *server.BlockRequest[T],
|
||||
state store.ReaderMap,
|
||||
) (blockResult *appmanager.BlockResponse, newState store.WriterMap, err error)
|
||||
) (blockResult *server.BlockResponse, newState store.WriterMap, err error)
|
||||
|
||||
// ValidateTx validates a transaction.
|
||||
ValidateTx(
|
||||
@ -23,7 +23,7 @@ type StateTransitionFunction[T transaction.Tx] interface {
|
||||
state store.ReaderMap,
|
||||
gasLimit uint64,
|
||||
tx T,
|
||||
) appmanager.TxResult
|
||||
) server.TxResult
|
||||
|
||||
// Simulate executes a transaction in simulation mode.
|
||||
Simulate(
|
||||
@ -31,7 +31,7 @@ type StateTransitionFunction[T transaction.Tx] interface {
|
||||
state store.ReaderMap,
|
||||
gasLimit uint64,
|
||||
tx T,
|
||||
) (appmanager.TxResult, store.WriterMap)
|
||||
) (server.TxResult, store.WriterMap)
|
||||
|
||||
// Query executes a query on the application.
|
||||
Query(
|
||||
|
||||
@ -11,10 +11,10 @@ import (
|
||||
abciproto "github.com/cometbft/cometbft/api/cometbft/abci/v1"
|
||||
gogoproto "github.com/cosmos/gogoproto/proto"
|
||||
|
||||
coreappmgr "cosmossdk.io/core/app"
|
||||
"cosmossdk.io/core/comet"
|
||||
corecontext "cosmossdk.io/core/context"
|
||||
"cosmossdk.io/core/event"
|
||||
"cosmossdk.io/core/server"
|
||||
"cosmossdk.io/core/store"
|
||||
"cosmossdk.io/core/transaction"
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
@ -134,10 +134,6 @@ func (c *Consensus[T]) CheckTx(ctx context.Context, req *abciproto.CheckTxReques
|
||||
GasWanted: uint64ToInt64(resp.GasWanted),
|
||||
GasUsed: uint64ToInt64(resp.GasUsed),
|
||||
Events: intoABCIEvents(resp.Events, c.indexedEvents),
|
||||
Info: resp.Info,
|
||||
Data: resp.Data,
|
||||
Log: resp.Log,
|
||||
Codespace: resp.Codespace,
|
||||
}
|
||||
if resp.Error != nil {
|
||||
cometResp.Code = 1
|
||||
@ -268,7 +264,7 @@ func (c *Consensus[T]) InitChain(ctx context.Context, req *abciproto.InitChainRe
|
||||
// populate hash with empty byte slice instead of nil
|
||||
bz := sha256.Sum256([]byte{})
|
||||
|
||||
br := &coreappmgr.BlockRequest[T]{
|
||||
br := &server.BlockRequest[T]{
|
||||
Height: uint64(req.InitialHeight - 1),
|
||||
Time: req.Time,
|
||||
Hash: bz[:],
|
||||
@ -289,7 +285,7 @@ func (c *Consensus[T]) InitChain(ctx context.Context, req *abciproto.InitChainRe
|
||||
// TODO necessary? where should this WARN live if it all. helpful for testing
|
||||
for _, txRes := range blockresponse.TxResults {
|
||||
if txRes.Error != nil {
|
||||
c.logger.Warn("genesis tx failed", "code", txRes.Code, "log", txRes.Log, "error", txRes.Error)
|
||||
c.logger.Warn("genesis tx failed", "code", txRes.Code, "error", txRes.Error)
|
||||
}
|
||||
}
|
||||
|
||||
@ -441,7 +437,7 @@ func (c *Consensus[T]) FinalizeBlock(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
blockReq := &coreappmgr.BlockRequest[T]{
|
||||
blockReq := &server.BlockRequest[T]{
|
||||
Height: uint64(req.Height),
|
||||
Time: req.Time,
|
||||
Hash: req.Hash,
|
||||
|
||||
@ -9,14 +9,14 @@ import (
|
||||
"github.com/cosmos/gogoproto/proto"
|
||||
|
||||
consensusv1 "cosmossdk.io/api/cosmos/consensus/v1"
|
||||
appmanager "cosmossdk.io/core/app"
|
||||
"cosmossdk.io/core/server"
|
||||
"cosmossdk.io/core/store"
|
||||
"cosmossdk.io/core/transaction"
|
||||
"cosmossdk.io/server/v2/cometbft/mempool"
|
||||
)
|
||||
|
||||
type AppManager[T transaction.Tx] interface {
|
||||
ValidateTx(ctx context.Context, tx T) (appmanager.TxResult, error)
|
||||
ValidateTx(ctx context.Context, tx T) (server.TxResult, error)
|
||||
Query(ctx context.Context, version uint64, request transaction.Msg) (response transaction.Msg, err error)
|
||||
}
|
||||
|
||||
|
||||
@ -3,8 +3,8 @@ package cometbft
|
||||
import (
|
||||
"context"
|
||||
|
||||
coreappmgr "cosmossdk.io/core/app"
|
||||
"cosmossdk.io/core/event"
|
||||
"cosmossdk.io/core/server"
|
||||
"cosmossdk.io/core/store"
|
||||
"cosmossdk.io/server/v2/streaming"
|
||||
)
|
||||
@ -14,7 +14,7 @@ func (c *Consensus[T]) streamDeliverBlockChanges(
|
||||
ctx context.Context,
|
||||
height int64,
|
||||
txs [][]byte,
|
||||
txResults []coreappmgr.TxResult,
|
||||
txResults []server.TxResult,
|
||||
events []event.Event,
|
||||
stateChanges []store.StateChanges,
|
||||
) error {
|
||||
@ -23,13 +23,9 @@ func (c *Consensus[T]) streamDeliverBlockChanges(
|
||||
for i, txResult := range txResults {
|
||||
streamingTxResults[i] = &streaming.ExecTxResult{
|
||||
Code: txResult.Code,
|
||||
Data: txResult.Data,
|
||||
Log: txResult.Log,
|
||||
Info: txResult.Info,
|
||||
GasWanted: uint64ToInt64(txResult.GasWanted),
|
||||
GasUsed: uint64ToInt64(txResult.GasUsed),
|
||||
Events: streaming.IntoStreamingEvents(txResult.Events),
|
||||
Codespace: txResult.Codespace,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -17,10 +17,10 @@ import (
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
|
||||
v1beta1 "cosmossdk.io/api/cosmos/base/abci/v1beta1"
|
||||
appmanager "cosmossdk.io/core/app"
|
||||
appmodulev2 "cosmossdk.io/core/appmodule/v2"
|
||||
"cosmossdk.io/core/comet"
|
||||
"cosmossdk.io/core/event"
|
||||
"cosmossdk.io/core/server"
|
||||
"cosmossdk.io/core/transaction"
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
consensus "cosmossdk.io/x/consensus/types"
|
||||
@ -68,7 +68,7 @@ func splitABCIQueryPath(requestPath string) (path []string) {
|
||||
}
|
||||
|
||||
func finalizeBlockResponse(
|
||||
in *appmanager.BlockResponse,
|
||||
in *server.BlockResponse,
|
||||
cp *cmtproto.ConsensusParams,
|
||||
appHash []byte,
|
||||
indexSet map[string]struct{},
|
||||
@ -99,7 +99,7 @@ func intoABCIValidatorUpdates(updates []appmodulev2.ValidatorUpdate) []abci.Vali
|
||||
return valsetUpdates
|
||||
}
|
||||
|
||||
func intoABCITxResults(results []appmanager.TxResult, indexSet map[string]struct{}) []*abci.ExecTxResult {
|
||||
func intoABCITxResults(results []server.TxResult, indexSet map[string]struct{}) []*abci.ExecTxResult {
|
||||
res := make([]*abci.ExecTxResult, len(results))
|
||||
for i := range results {
|
||||
if results[i].Error != nil {
|
||||
@ -146,7 +146,7 @@ func intoABCIEvents(events []event.Event, indexSet map[string]struct{}) []abci.E
|
||||
return abciEvents
|
||||
}
|
||||
|
||||
func intoABCISimulationResponse(txRes appmanager.TxResult, indexSet map[string]struct{}) ([]byte, error) {
|
||||
func intoABCISimulationResponse(txRes server.TxResult, indexSet map[string]struct{}) ([]byte, error) {
|
||||
indexAll := len(indexSet) == 0
|
||||
abciEvents := make([]*abciv1.Event, len(txRes.Events))
|
||||
for i, e := range txRes.Events {
|
||||
|
||||
@ -11,7 +11,7 @@ import (
|
||||
"github.com/spf13/viper"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
coreapp "cosmossdk.io/core/app"
|
||||
coreserver "cosmossdk.io/core/server"
|
||||
"cosmossdk.io/core/transaction"
|
||||
"cosmossdk.io/log"
|
||||
serverv2 "cosmossdk.io/server/v2"
|
||||
@ -42,7 +42,7 @@ func (*mockApp[T]) GetAppManager() *appmanager.AppManager[T] {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*mockApp[T]) InterfaceRegistry() coreapp.InterfaceRegistry {
|
||||
func (*mockApp[T]) InterfaceRegistry() coreserver.InterfaceRegistry {
|
||||
return &mockInterfaceRegistry{}
|
||||
}
|
||||
|
||||
|
||||
@ -3,7 +3,6 @@ package branch
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/tidwall/btree"
|
||||
|
||||
"cosmossdk.io/core/store"
|
||||
@ -11,21 +10,32 @@ import (
|
||||
|
||||
func TestBranch(t *testing.T) {
|
||||
set := func(s interface{ Set([]byte, []byte) error }, key, value string) {
|
||||
require.NoError(t, s.Set([]byte(key), []byte(value)))
|
||||
err := s.Set([]byte(key), []byte(value))
|
||||
if err != nil {
|
||||
t.Errorf("Error setting value: %v", err)
|
||||
}
|
||||
}
|
||||
get := func(s interface{ Get([]byte) ([]byte, error) }, key, wantValue string) {
|
||||
value, err := s.Get([]byte(key))
|
||||
require.NoError(t, err)
|
||||
if err != nil {
|
||||
t.Errorf("Error getting value: %v", err)
|
||||
}
|
||||
if wantValue == "" {
|
||||
require.Nil(t, value)
|
||||
if value != nil {
|
||||
t.Errorf("Expected nil value, got: %v", value)
|
||||
}
|
||||
} else {
|
||||
require.Equal(t, wantValue, string(value))
|
||||
if string(value) != wantValue {
|
||||
t.Errorf("Expected value: %s, got: %s", wantValue, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
remove := func(s interface{ Delete([]byte) error }, key string) {
|
||||
err := s.Delete([]byte(key))
|
||||
require.NoError(t, err)
|
||||
if err != nil {
|
||||
t.Errorf("Error deleting value: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
iter := func(s interface {
|
||||
@ -41,15 +51,23 @@ func TestBranch(t *testing.T) {
|
||||
endKey = nil
|
||||
}
|
||||
iter, err := s.Iterator(startKey, endKey)
|
||||
require.NoError(t, err)
|
||||
if err != nil {
|
||||
t.Errorf("Error creating iterator: %v", err)
|
||||
}
|
||||
defer iter.Close()
|
||||
numPairs := len(wantPairs)
|
||||
for i := 0; i < numPairs; i++ {
|
||||
require.True(t, iter.Valid(), "expected iterator to be valid")
|
||||
if !iter.Valid() {
|
||||
t.Errorf("Expected iterator to be valid")
|
||||
}
|
||||
gotKey, gotValue := string(iter.Key()), string(iter.Value())
|
||||
wantKey, wantValue := wantPairs[i][0], wantPairs[i][1]
|
||||
require.Equal(t, wantKey, gotKey)
|
||||
require.Equal(t, wantValue, gotValue)
|
||||
if wantKey != gotKey {
|
||||
t.Errorf("Expected key: %s, got: %s", wantKey, gotKey)
|
||||
}
|
||||
if wantValue != gotValue {
|
||||
t.Errorf("Expected value: %s, got: %s", wantValue, gotValue)
|
||||
}
|
||||
iter.Next()
|
||||
}
|
||||
}
|
||||
@ -107,8 +125,6 @@ func newMemState() memStore {
|
||||
return memStore{btree.NewBTreeGOptions(byKeys, btree.Options{Degree: bTreeDegree, NoLocks: true})}
|
||||
}
|
||||
|
||||
var _ store.Writer = memStore{}
|
||||
|
||||
type memStore struct {
|
||||
t *btree.BTreeG[item]
|
||||
}
|
||||
|
||||
@ -6,7 +6,6 @@ import (
|
||||
"testing"
|
||||
|
||||
gogotypes "github.com/cosmos/gogoproto/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
appmodulev2 "cosmossdk.io/core/appmodule/v2"
|
||||
"cosmossdk.io/server/v2/stf/branch"
|
||||
@ -61,8 +60,12 @@ func TestBranchService(t *testing.T) {
|
||||
kvSet(t, ctx, "cookies")
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotZero(t, gasUsed)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
if gasUsed == 0 {
|
||||
t.Error("expected non-zero gasUsed")
|
||||
}
|
||||
stateHas(t, stfCtx.state, "cookies")
|
||||
})
|
||||
|
||||
@ -72,8 +75,12 @@ func TestBranchService(t *testing.T) {
|
||||
kvSet(t, ctx, "cookies")
|
||||
return errors.New("fail")
|
||||
})
|
||||
require.Error(t, err)
|
||||
require.NotZero(t, gasUsed)
|
||||
if err == nil {
|
||||
t.Error("expected error")
|
||||
}
|
||||
if gasUsed == 0 {
|
||||
t.Error("expected non-zero gasUsed")
|
||||
}
|
||||
stateNotHas(t, stfCtx.state, "cookies")
|
||||
})
|
||||
|
||||
@ -85,9 +92,15 @@ func TestBranchService(t *testing.T) {
|
||||
_ = state.Set([]byte("not out of gas"), []byte{})
|
||||
return state.Set([]byte("out of gas"), []byte{})
|
||||
})
|
||||
require.Error(t, err)
|
||||
require.NotZero(t, gasUsed)
|
||||
if err == nil {
|
||||
t.Error("expected error")
|
||||
}
|
||||
if gasUsed == 0 {
|
||||
t.Error("expected non-zero gasUsed")
|
||||
}
|
||||
stateNotHas(t, stfCtx.state, "cookies")
|
||||
require.Equal(t, uint64(1000), stfCtx.meter.Limit()-stfCtx.meter.Remaining())
|
||||
if stfCtx.meter.Limit()-stfCtx.meter.Remaining() != 1000 {
|
||||
t.Error("expected gas limit precision to be 1000")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -7,17 +7,10 @@ replace cosmossdk.io/core => ../../../core
|
||||
require (
|
||||
cosmossdk.io/core v0.11.0
|
||||
github.com/cosmos/gogoproto v1.7.0
|
||||
github.com/stretchr/testify v1.9.0
|
||||
github.com/tidwall/btree v1.7.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
|
||||
google.golang.org/protobuf v1.34.2 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
replace github.com/cosmos/gogoproto => github.com/cosmos/gogoproto v1.6.1-0.20240809124342-d6a57064ada0
|
||||
|
||||
@ -1,22 +1,10 @@
|
||||
github.com/cosmos/gogoproto v1.6.1-0.20240809124342-d6a57064ada0 h1:qZdcY4sKyAnaUwFRtSKkk9YdeMuQixWxLagI/8jhJo4=
|
||||
github.com/cosmos/gogoproto v1.6.1-0.20240809124342-d6a57064ada0/go.mod h1:Y+g956rcUf2vr4uwtCcK/1Xx9BWVluCtcI9vsh0GHmk=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/cosmos/gogoproto v1.7.0 h1:79USr0oyXAbxg3rspGh/m4SWNyoz/GLaAh0QlCe2fro=
|
||||
github.com/cosmos/gogoproto v1.7.0/go.mod h1:yWChEv5IUEYURQasfyBW5ffkMHR/90hiHgbNgrtp4j0=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI=
|
||||
github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY=
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
10
server/v2/stf/identity.go
Normal file
10
server/v2/stf/identity.go
Normal file
@ -0,0 +1,10 @@
|
||||
package stf
|
||||
|
||||
var (
|
||||
// Identity defines STF's bytes identity and it's used by STF to store things in its own state.
|
||||
Identity = []byte("stf")
|
||||
// RuntimeIdentity defines the bytes identity of the runtime.
|
||||
RuntimeIdentity = []byte("runtime")
|
||||
// ConsensusIdentity defines the bytes identity of the consensus.
|
||||
ConsensusIdentity = []byte("consensus")
|
||||
)
|
||||
@ -5,7 +5,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
appmanager "cosmossdk.io/core/app"
|
||||
appmodulev2 "cosmossdk.io/core/appmodule/v2"
|
||||
corecontext "cosmossdk.io/core/context"
|
||||
"cosmossdk.io/core/event"
|
||||
@ -13,15 +12,13 @@ import (
|
||||
"cosmossdk.io/core/header"
|
||||
"cosmossdk.io/core/log"
|
||||
"cosmossdk.io/core/router"
|
||||
"cosmossdk.io/core/server"
|
||||
"cosmossdk.io/core/store"
|
||||
"cosmossdk.io/core/transaction"
|
||||
stfgas "cosmossdk.io/server/v2/stf/gas"
|
||||
"cosmossdk.io/server/v2/stf/internal"
|
||||
)
|
||||
|
||||
// Identity defines STF's bytes identity and it's used by STF to store things in its own state.
|
||||
var Identity = []byte("stf")
|
||||
|
||||
type eContextKey struct{}
|
||||
|
||||
var executionContextKey = eContextKey{}
|
||||
@ -89,9 +86,9 @@ func NewSTF[T transaction.Tx](
|
||||
// executes the block and returns the block results and the new state.
|
||||
func (s STF[T]) DeliverBlock(
|
||||
ctx context.Context,
|
||||
block *appmanager.BlockRequest[T],
|
||||
block *server.BlockRequest[T],
|
||||
state store.ReaderMap,
|
||||
) (blockResult *appmanager.BlockResponse, newState store.WriterMap, err error) {
|
||||
) (blockResult *server.BlockResponse, newState store.WriterMap, err error) {
|
||||
// creates a new branchFn state, from the readonly view of the state
|
||||
// that can be written to.
|
||||
newState = s.branchFn(state)
|
||||
@ -108,7 +105,7 @@ func (s STF[T]) DeliverBlock(
|
||||
return nil, nil, fmt.Errorf("unable to set initial header info, %w", err)
|
||||
}
|
||||
|
||||
exCtx := s.makeContext(ctx, appmanager.ConsensusIdentity, newState, internal.ExecModeFinalize)
|
||||
exCtx := s.makeContext(ctx, ConsensusIdentity, newState, internal.ExecModeFinalize)
|
||||
exCtx.setHeaderInfo(hi)
|
||||
|
||||
// reset events
|
||||
@ -142,7 +139,7 @@ func (s STF[T]) DeliverBlock(
|
||||
}
|
||||
|
||||
// execute txs
|
||||
txResults := make([]appmanager.TxResult, len(block.Txs))
|
||||
txResults := make([]server.TxResult, len(block.Txs))
|
||||
// TODO: skip first tx if vote extensions are enabled (marko)
|
||||
for i, txBytes := range block.Txs {
|
||||
// check if we need to return early or continue delivering txs
|
||||
@ -159,8 +156,7 @@ func (s STF[T]) DeliverBlock(
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return &appmanager.BlockResponse{
|
||||
Apphash: nil,
|
||||
return &server.BlockResponse{
|
||||
ValidatorUpdates: valset,
|
||||
PreBlockEvents: preBlockEvents,
|
||||
BeginBlockEvents: beginBlockEvents,
|
||||
@ -176,7 +172,7 @@ func (s STF[T]) deliverTx(
|
||||
tx T,
|
||||
execMode transaction.ExecMode,
|
||||
hi header.Info,
|
||||
) appmanager.TxResult {
|
||||
) server.TxResult {
|
||||
// recover in the case of a panic
|
||||
var recoveryError error
|
||||
defer func() {
|
||||
@ -188,26 +184,26 @@ func (s STF[T]) deliverTx(
|
||||
// handle error from GetGasLimit
|
||||
gasLimit, gasLimitErr := tx.GetGasLimit()
|
||||
if gasLimitErr != nil {
|
||||
return appmanager.TxResult{
|
||||
return server.TxResult{
|
||||
Error: gasLimitErr,
|
||||
}
|
||||
}
|
||||
|
||||
if recoveryError != nil {
|
||||
return appmanager.TxResult{
|
||||
return server.TxResult{
|
||||
Error: recoveryError,
|
||||
}
|
||||
}
|
||||
|
||||
validateGas, validationEvents, err := s.validateTx(ctx, state, gasLimit, tx, execMode)
|
||||
if err != nil {
|
||||
return appmanager.TxResult{
|
||||
return server.TxResult{
|
||||
Error: err,
|
||||
}
|
||||
}
|
||||
|
||||
execResp, execGas, execEvents, err := s.execTx(ctx, state, gasLimit-validateGas, tx, execMode, hi)
|
||||
return appmanager.TxResult{
|
||||
return server.TxResult{
|
||||
Events: append(validationEvents, execEvents...),
|
||||
GasUsed: execGas + validateGas,
|
||||
GasWanted: gasLimit,
|
||||
@ -230,7 +226,7 @@ func (s STF[T]) validateTx(
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
validateCtx := s.makeContext(ctx, appmanager.RuntimeIdentity, validateState, execMode)
|
||||
validateCtx := s.makeContext(ctx, RuntimeIdentity, validateState, execMode)
|
||||
validateCtx.setHeaderInfo(hi)
|
||||
validateCtx.setGasLimit(gasLimit)
|
||||
err = s.doTxValidation(validateCtx, tx)
|
||||
@ -259,7 +255,7 @@ func (s STF[T]) execTx(
|
||||
// in case of error during message execution, we do not apply the exec state.
|
||||
// instead we run the post exec handler in a new branchFn from the initial state.
|
||||
postTxState := s.branchFn(state)
|
||||
postTxCtx := s.makeContext(ctx, appmanager.RuntimeIdentity, postTxState, execMode)
|
||||
postTxCtx := s.makeContext(ctx, RuntimeIdentity, postTxState, execMode)
|
||||
postTxCtx.setHeaderInfo(hi)
|
||||
|
||||
postTxErr := s.postTxExec(postTxCtx, tx, false)
|
||||
@ -279,7 +275,7 @@ func (s STF[T]) execTx(
|
||||
// tx execution went fine, now we use the same state to run the post tx exec handler,
|
||||
// in case the execution of the post tx fails, then no state change is applied and the
|
||||
// whole execution step is rolled back.
|
||||
postTxCtx := s.makeContext(ctx, appmanager.RuntimeIdentity, execState, execMode) // NO gas limit.
|
||||
postTxCtx := s.makeContext(ctx, RuntimeIdentity, execState, execMode) // NO gas limit.
|
||||
postTxCtx.setHeaderInfo(hi)
|
||||
postTxErr := s.postTxExec(postTxCtx, tx, true)
|
||||
if postTxErr != nil {
|
||||
@ -316,7 +312,7 @@ func (s STF[T]) runTxMsgs(
|
||||
}
|
||||
msgResps := make([]transaction.Msg, len(msgs))
|
||||
|
||||
execCtx := s.makeContext(ctx, nil, state, execMode)
|
||||
execCtx := s.makeContext(ctx, RuntimeIdentity, state, execMode)
|
||||
execCtx.setHeaderInfo(hi)
|
||||
execCtx.setGasLimit(gasLimit)
|
||||
for i, msg := range msgs {
|
||||
@ -414,11 +410,11 @@ func (s STF[T]) Simulate(
|
||||
state store.ReaderMap,
|
||||
gasLimit uint64,
|
||||
tx T,
|
||||
) (appmanager.TxResult, store.WriterMap) {
|
||||
) (server.TxResult, store.WriterMap) {
|
||||
simulationState := s.branchFn(state)
|
||||
hi, err := s.getHeaderInfo(simulationState)
|
||||
if err != nil {
|
||||
return appmanager.TxResult{}, nil
|
||||
return server.TxResult{}, nil
|
||||
}
|
||||
txr := s.deliverTx(ctx, simulationState, tx, internal.ExecModeSimulate, hi)
|
||||
|
||||
@ -432,10 +428,10 @@ func (s STF[T]) ValidateTx(
|
||||
state store.ReaderMap,
|
||||
gasLimit uint64,
|
||||
tx T,
|
||||
) appmanager.TxResult {
|
||||
) server.TxResult {
|
||||
validationState := s.branchFn(state)
|
||||
gasUsed, events, err := s.validateTx(ctx, validationState, gasLimit, tx, transaction.ExecModeCheck)
|
||||
return appmanager.TxResult{
|
||||
return server.TxResult{
|
||||
Events: events,
|
||||
GasUsed: gasUsed,
|
||||
Error: err,
|
||||
@ -591,9 +587,9 @@ func newExecutionContext(
|
||||
state: meteredState,
|
||||
meter: meter,
|
||||
events: make([]event.Event, 0),
|
||||
sender: sender,
|
||||
headerInfo: header.Info{},
|
||||
execMode: execMode,
|
||||
sender: sender,
|
||||
branchFn: branchFn,
|
||||
makeGasMeter: makeGasMeterFn,
|
||||
makeGasMeteredStore: makeGasMeteredStoreFn,
|
||||
|
||||
@ -2,11 +2,11 @@ package stf
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
gogoproto "github.com/cosmos/gogoproto/proto"
|
||||
gogotypes "github.com/cosmos/gogoproto/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"cosmossdk.io/core/appmodule/v2"
|
||||
"cosmossdk.io/core/transaction"
|
||||
@ -20,29 +20,41 @@ func TestRouter(t *testing.T) {
|
||||
|
||||
router := coreRouterImpl{handlers: map[string]appmodule.Handler{
|
||||
gogoproto.MessageName(expectedMsg): func(ctx context.Context, gotMsg transaction.Msg) (msgResp transaction.Msg, err error) {
|
||||
require.Equal(t, expectedMsg, gotMsg)
|
||||
if !reflect.DeepEqual(expectedMsg, gotMsg) {
|
||||
t.Errorf("expected message: %v, got: %v", expectedMsg, gotMsg)
|
||||
}
|
||||
return expectedResp, nil
|
||||
},
|
||||
}}
|
||||
|
||||
t.Run("can invoke message by name", func(t *testing.T) {
|
||||
err := router.CanInvoke(context.Background(), expectedMsgName)
|
||||
require.NoError(t, err, "must be invocable")
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("can invoke message by type URL", func(t *testing.T) {
|
||||
err := router.CanInvoke(context.Background(), "/"+expectedMsgName)
|
||||
require.NoError(t, err)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("cannot invoke unknown message", func(t *testing.T) {
|
||||
err := router.CanInvoke(context.Background(), "not exist")
|
||||
require.Error(t, err)
|
||||
if err == nil {
|
||||
t.Error("expected error, got nil")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("invoke", func(t *testing.T) {
|
||||
gotResp, err := router.Invoke(context.Background(), expectedMsg)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedResp, gotResp)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(expectedResp, gotResp) {
|
||||
t.Errorf("expected response: %v, got: %v", expectedResp, gotResp)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -4,15 +4,15 @@ import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"errors"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
gogotypes "github.com/cosmos/gogoproto/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
appmanager "cosmossdk.io/core/app"
|
||||
appmodulev2 "cosmossdk.io/core/appmodule/v2"
|
||||
coregas "cosmossdk.io/core/gas"
|
||||
"cosmossdk.io/core/server"
|
||||
"cosmossdk.io/core/store"
|
||||
"cosmossdk.io/core/transaction"
|
||||
"cosmossdk.io/server/v2/stf/branch"
|
||||
@ -46,10 +46,14 @@ func addMsgHandlerToSTF[T any, PT interface {
|
||||
return typedResp, nil
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to register handler: %v", err)
|
||||
}
|
||||
|
||||
msgRouter, err := msgRouterBuilder.Build()
|
||||
require.NoError(t, err)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to build message router: %v", err)
|
||||
}
|
||||
stf.msgRouter = msgRouter
|
||||
}
|
||||
|
||||
@ -93,34 +97,44 @@ func TestSTF(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("begin and end block", func(t *testing.T) {
|
||||
_, newState, err := s.DeliverBlock(context.Background(), &appmanager.BlockRequest[mock.Tx]{
|
||||
_, newState, err := s.DeliverBlock(context.Background(), &server.BlockRequest[mock.Tx]{
|
||||
Height: uint64(1),
|
||||
Time: time.Date(2024, 2, 3, 18, 23, 0, 0, time.UTC),
|
||||
AppHash: sum[:],
|
||||
Hash: sum[:],
|
||||
}, state)
|
||||
require.NoError(t, err)
|
||||
if err != nil {
|
||||
t.Errorf("DeliverBlock error: %v", err)
|
||||
}
|
||||
stateHas(t, newState, "begin-block")
|
||||
stateHas(t, newState, "end-block")
|
||||
})
|
||||
|
||||
t.Run("basic tx", func(t *testing.T) {
|
||||
result, newState, err := s.DeliverBlock(context.Background(), &appmanager.BlockRequest[mock.Tx]{
|
||||
result, newState, err := s.DeliverBlock(context.Background(), &server.BlockRequest[mock.Tx]{
|
||||
Height: uint64(1),
|
||||
Time: time.Date(2024, 2, 3, 18, 23, 0, 0, time.UTC),
|
||||
AppHash: sum[:],
|
||||
Hash: sum[:],
|
||||
Txs: []mock.Tx{mockTx},
|
||||
}, state)
|
||||
require.NoError(t, err)
|
||||
if err != nil {
|
||||
t.Errorf("DeliverBlock error: %v", err)
|
||||
}
|
||||
stateHas(t, newState, "validate")
|
||||
stateHas(t, newState, "exec")
|
||||
stateHas(t, newState, "post-tx-exec")
|
||||
|
||||
require.Len(t, result.TxResults, 1)
|
||||
if len(result.TxResults) != 1 {
|
||||
t.Errorf("Expected 1 TxResult, got %d", len(result.TxResults))
|
||||
}
|
||||
txResult := result.TxResults[0]
|
||||
require.NotZero(t, txResult.GasUsed)
|
||||
require.Equal(t, mockTx.GasLimit, txResult.GasWanted)
|
||||
if txResult.GasUsed == 0 {
|
||||
t.Errorf("GasUsed should not be zero")
|
||||
}
|
||||
if txResult.GasWanted != mockTx.GasLimit {
|
||||
t.Errorf("Expected GasWanted to be %d, got %d", mockTx.GasLimit, txResult.GasWanted)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("exec tx out of gas", func(t *testing.T) {
|
||||
@ -136,22 +150,30 @@ func TestSTF(t *testing.T) {
|
||||
// out of gas immediately at tx validation level.
|
||||
s.doTxValidation = func(ctx context.Context, tx mock.Tx) error {
|
||||
w, err := ctx.(*executionContext).state.GetWriter(actorName)
|
||||
require.NoError(t, err)
|
||||
if err != nil {
|
||||
t.Errorf("GetWriter error: %v", err)
|
||||
}
|
||||
err = w.Set([]byte("gas_failure"), []byte{})
|
||||
require.Error(t, err)
|
||||
if err == nil {
|
||||
t.Error("Expected error, got nil")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
result, newState, err := s.DeliverBlock(context.Background(), &appmanager.BlockRequest[mock.Tx]{
|
||||
result, newState, err := s.DeliverBlock(context.Background(), &server.BlockRequest[mock.Tx]{
|
||||
Height: uint64(1),
|
||||
Time: time.Date(2024, 2, 3, 18, 23, 0, 0, time.UTC),
|
||||
AppHash: sum[:],
|
||||
Hash: sum[:],
|
||||
Txs: []mock.Tx{mockTx},
|
||||
}, state)
|
||||
require.NoError(t, err)
|
||||
if err != nil {
|
||||
t.Errorf("DeliverBlock error: %v", err)
|
||||
}
|
||||
stateNotHas(t, newState, "gas_failure") // assert during out of gas no state changes leaked.
|
||||
require.ErrorIs(t, result.TxResults[0].Error, coregas.ErrOutOfGas, result.TxResults[0].Error)
|
||||
if !errors.Is(result.TxResults[0].Error, coregas.ErrOutOfGas) {
|
||||
t.Errorf("Expected ErrOutOfGas, got %v", result.TxResults[0].Error)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("fail exec tx", func(t *testing.T) {
|
||||
@ -161,15 +183,19 @@ func TestSTF(t *testing.T) {
|
||||
return nil, errors.New("failure")
|
||||
})
|
||||
|
||||
blockResult, newState, err := s.DeliverBlock(context.Background(), &appmanager.BlockRequest[mock.Tx]{
|
||||
blockResult, newState, err := s.DeliverBlock(context.Background(), &server.BlockRequest[mock.Tx]{
|
||||
Height: uint64(1),
|
||||
Time: time.Date(2024, 2, 3, 18, 23, 0, 0, time.UTC),
|
||||
AppHash: sum[:],
|
||||
Hash: sum[:],
|
||||
Txs: []mock.Tx{mockTx},
|
||||
}, state)
|
||||
require.NoError(t, err)
|
||||
require.ErrorContains(t, blockResult.TxResults[0].Error, "failure")
|
||||
if err != nil {
|
||||
t.Errorf("DeliverBlock error: %v", err)
|
||||
}
|
||||
if !strings.Contains(blockResult.TxResults[0].Error.Error(), "failure") {
|
||||
t.Errorf("Expected error to contain 'failure', got %v", blockResult.TxResults[0].Error)
|
||||
}
|
||||
stateHas(t, newState, "begin-block")
|
||||
stateHas(t, newState, "end-block")
|
||||
stateHas(t, newState, "validate")
|
||||
@ -182,15 +208,19 @@ func TestSTF(t *testing.T) {
|
||||
s.postTxExec = func(ctx context.Context, tx mock.Tx, success bool) error {
|
||||
return errors.New("post tx failure")
|
||||
}
|
||||
blockResult, newState, err := s.DeliverBlock(context.Background(), &appmanager.BlockRequest[mock.Tx]{
|
||||
blockResult, newState, err := s.DeliverBlock(context.Background(), &server.BlockRequest[mock.Tx]{
|
||||
Height: uint64(1),
|
||||
Time: time.Date(2024, 2, 3, 18, 23, 0, 0, time.UTC),
|
||||
AppHash: sum[:],
|
||||
Hash: sum[:],
|
||||
Txs: []mock.Tx{mockTx},
|
||||
}, state)
|
||||
require.NoError(t, err)
|
||||
require.ErrorContains(t, blockResult.TxResults[0].Error, "post tx failure")
|
||||
if err != nil {
|
||||
t.Errorf("DeliverBlock error: %v", err)
|
||||
}
|
||||
if !strings.Contains(blockResult.TxResults[0].Error.Error(), "post tx failure") {
|
||||
t.Errorf("Expected error to contain 'post tx failure', got %v", blockResult.TxResults[0].Error)
|
||||
}
|
||||
stateHas(t, newState, "begin-block")
|
||||
stateHas(t, newState, "end-block")
|
||||
stateHas(t, newState, "validate")
|
||||
@ -204,15 +234,19 @@ func TestSTF(t *testing.T) {
|
||||
return nil, errors.New("exec failure")
|
||||
})
|
||||
s.postTxExec = func(ctx context.Context, tx mock.Tx, success bool) error { return errors.New("post tx failure") }
|
||||
blockResult, newState, err := s.DeliverBlock(context.Background(), &appmanager.BlockRequest[mock.Tx]{
|
||||
blockResult, newState, err := s.DeliverBlock(context.Background(), &server.BlockRequest[mock.Tx]{
|
||||
Height: uint64(1),
|
||||
Time: time.Date(2024, 2, 3, 18, 23, 0, 0, time.UTC),
|
||||
AppHash: sum[:],
|
||||
Hash: sum[:],
|
||||
Txs: []mock.Tx{mockTx},
|
||||
}, state)
|
||||
require.NoError(t, err)
|
||||
require.ErrorContains(t, blockResult.TxResults[0].Error, "exec failure\npost tx failure")
|
||||
if err != nil {
|
||||
t.Errorf("DeliverBlock error: %v", err)
|
||||
}
|
||||
if !strings.Contains(blockResult.TxResults[0].Error.Error(), "exec failure\npost tx failure") {
|
||||
t.Errorf("Expected error to contain 'exec failure\npost tx failure', got %v", blockResult.TxResults[0].Error)
|
||||
}
|
||||
stateHas(t, newState, "begin-block")
|
||||
stateHas(t, newState, "end-block")
|
||||
stateHas(t, newState, "validate")
|
||||
@ -224,15 +258,19 @@ func TestSTF(t *testing.T) {
|
||||
// update stf to fail on the validation step
|
||||
s := s.clone()
|
||||
s.doTxValidation = func(ctx context.Context, tx mock.Tx) error { return errors.New("failure") }
|
||||
blockResult, newState, err := s.DeliverBlock(context.Background(), &appmanager.BlockRequest[mock.Tx]{
|
||||
blockResult, newState, err := s.DeliverBlock(context.Background(), &server.BlockRequest[mock.Tx]{
|
||||
Height: uint64(1),
|
||||
Time: time.Date(2024, 2, 3, 18, 23, 0, 0, time.UTC),
|
||||
AppHash: sum[:],
|
||||
Hash: sum[:],
|
||||
Txs: []mock.Tx{mockTx},
|
||||
}, state)
|
||||
require.NoError(t, err)
|
||||
require.ErrorContains(t, blockResult.TxResults[0].Error, "failure")
|
||||
if err != nil {
|
||||
t.Errorf("DeliverBlock error: %v", err)
|
||||
}
|
||||
if !strings.Contains(blockResult.TxResults[0].Error.Error(), "failure") {
|
||||
t.Errorf("Expected error to contain 'failure', got %v", blockResult.TxResults[0].Error)
|
||||
}
|
||||
stateHas(t, newState, "begin-block")
|
||||
stateHas(t, newState, "end-block")
|
||||
stateNotHas(t, newState, "validate")
|
||||
@ -250,12 +288,16 @@ func TestSTF(t *testing.T) {
|
||||
}
|
||||
// test ValidateTx as it validates with check execMode
|
||||
res := s.ValidateTx(context.Background(), state, mockTx.GasLimit, mockTx)
|
||||
require.Error(t, res.Error)
|
||||
if res.Error == nil {
|
||||
t.Error("Expected error, got nil")
|
||||
}
|
||||
|
||||
// test validate tx with exec mode as finalize
|
||||
_, _, err := s.validateTx(context.Background(), s.branchFn(state), mockTx.GasLimit,
|
||||
mockTx, transaction.ExecModeFinalize)
|
||||
require.NoError(t, err)
|
||||
if err != nil {
|
||||
t.Errorf("validateTx error: %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -264,24 +306,42 @@ var actorName = []byte("cookies")
|
||||
func kvSet(t *testing.T, ctx context.Context, v string) {
|
||||
t.Helper()
|
||||
state, err := ctx.(*executionContext).state.GetWriter(actorName)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, state.Set([]byte(v), []byte(v)))
|
||||
if err != nil {
|
||||
t.Errorf("Set error: %v", err)
|
||||
} else {
|
||||
err = state.Set([]byte(v), []byte(v))
|
||||
if err != nil {
|
||||
t.Errorf("Set error: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func stateHas(t *testing.T, accountState store.ReaderMap, key string) {
|
||||
t.Helper()
|
||||
state, err := accountState.GetReader(actorName)
|
||||
require.NoError(t, err)
|
||||
if err != nil {
|
||||
t.Errorf("GetReader error: %v", err)
|
||||
}
|
||||
has, err := state.Has([]byte(key))
|
||||
require.NoError(t, err)
|
||||
require.Truef(t, has, "state did not have key: %s", key)
|
||||
if err != nil {
|
||||
t.Errorf("Has error: %v", err)
|
||||
}
|
||||
if !has {
|
||||
t.Errorf("State did not have key: %s", key)
|
||||
}
|
||||
}
|
||||
|
||||
func stateNotHas(t *testing.T, accountState store.ReaderMap, key string) {
|
||||
t.Helper()
|
||||
state, err := accountState.GetReader(actorName)
|
||||
require.NoError(t, err)
|
||||
if err != nil {
|
||||
t.Errorf("GetReader error: %v", err)
|
||||
}
|
||||
has, err := state.Has([]byte(key))
|
||||
require.NoError(t, err)
|
||||
require.Falsef(t, has, "state was not supposed to have key: %s", key)
|
||||
if err != nil {
|
||||
t.Errorf("Has error: %v", err)
|
||||
}
|
||||
if has {
|
||||
t.Errorf("State was not supposed to have key: %s", key)
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ import (
|
||||
gogoproto "github.com/cosmos/gogoproto/proto"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
coreapp "cosmossdk.io/core/app"
|
||||
"cosmossdk.io/core/server"
|
||||
"cosmossdk.io/core/transaction"
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/server/v2/appmanager"
|
||||
@ -14,7 +14,7 @@ type AppCreator[T transaction.Tx] func(log.Logger, *viper.Viper) AppI[T]
|
||||
|
||||
type AppI[T transaction.Tx] interface {
|
||||
Name() string
|
||||
InterfaceRegistry() coreapp.InterfaceRegistry
|
||||
InterfaceRegistry() server.InterfaceRegistry
|
||||
GetAppManager() *appmanager.AppManager[T]
|
||||
GetConsensusAuthority() string
|
||||
GetGPRCMethodsToMessageMap() map[string]func() gogoproto.Message
|
||||
|
||||
@ -6,8 +6,8 @@ import (
|
||||
"github.com/spf13/viper"
|
||||
|
||||
clienthelpers "cosmossdk.io/client/v2/helpers"
|
||||
coreapp "cosmossdk.io/core/app"
|
||||
"cosmossdk.io/core/legacy"
|
||||
"cosmossdk.io/core/server"
|
||||
"cosmossdk.io/core/transaction"
|
||||
"cosmossdk.io/depinject"
|
||||
"cosmossdk.io/log"
|
||||
@ -212,7 +212,7 @@ func (app *SimApp[T]) AppCodec() codec.Codec {
|
||||
}
|
||||
|
||||
// InterfaceRegistry returns SimApp's InterfaceRegistry.
|
||||
func (app *SimApp[T]) InterfaceRegistry() coreapp.InterfaceRegistry {
|
||||
func (app *SimApp[T]) InterfaceRegistry() server.InterfaceRegistry {
|
||||
return app.interfaceRegistry
|
||||
}
|
||||
|
||||
|
||||
@ -11,9 +11,9 @@ import (
|
||||
"github.com/spf13/viper"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
app2 "cosmossdk.io/core/app"
|
||||
"cosmossdk.io/core/comet"
|
||||
context2 "cosmossdk.io/core/context"
|
||||
"cosmossdk.io/core/server"
|
||||
"cosmossdk.io/core/store"
|
||||
"cosmossdk.io/core/transaction"
|
||||
"cosmossdk.io/log"
|
||||
@ -80,7 +80,7 @@ func NewTestApp(t *testing.T) (*SimApp[transaction.Tx], context.Context) {
|
||||
|
||||
_, newState, err := app.InitGenesis(
|
||||
ctx,
|
||||
&app2.BlockRequest[transaction.Tx]{
|
||||
&server.BlockRequest[transaction.Tx]{
|
||||
Time: time.Now(),
|
||||
Hash: bz[:],
|
||||
ChainId: "theChain",
|
||||
@ -123,7 +123,7 @@ func MoveNextBlock(t *testing.T, app *SimApp[transaction.Tx], ctx context.Contex
|
||||
|
||||
_, newState, err := app.DeliverBlock(
|
||||
ctx,
|
||||
&app2.BlockRequest[transaction.Tx]{
|
||||
&server.BlockRequest[transaction.Tx]{
|
||||
Height: height + 1,
|
||||
Time: time.Now(),
|
||||
Hash: bz[:],
|
||||
|
||||
@ -6,8 +6,8 @@ import (
|
||||
|
||||
modulev1 "cosmossdk.io/api/cosmos/upgrade/module/v1"
|
||||
"cosmossdk.io/core/address"
|
||||
"cosmossdk.io/core/app"
|
||||
"cosmossdk.io/core/appmodule"
|
||||
coreserver "cosmossdk.io/core/server"
|
||||
"cosmossdk.io/depinject"
|
||||
"cosmossdk.io/depinject/appconfig"
|
||||
authtypes "cosmossdk.io/x/auth/types"
|
||||
@ -40,7 +40,7 @@ type ModuleInputs struct {
|
||||
Environment appmodule.Environment
|
||||
Cdc codec.Codec
|
||||
AddressCodec address.Codec
|
||||
AppVersionModifier app.VersionModifier
|
||||
AppVersionModifier coreserver.VersionModifier
|
||||
|
||||
AppOpts servertypes.AppOptions `optional:"true"` // server v0
|
||||
Viper *viper.Viper `optional:"true"` // server v2
|
||||
|
||||
@ -13,8 +13,8 @@ import (
|
||||
|
||||
"github.com/hashicorp/go-metrics"
|
||||
|
||||
"cosmossdk.io/core/app"
|
||||
"cosmossdk.io/core/appmodule"
|
||||
"cosmossdk.io/core/server"
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
"cosmossdk.io/store/prefix"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
@ -34,7 +34,7 @@ type Keeper struct {
|
||||
skipUpgradeHeights map[int64]bool // map of heights to skip for an upgrade
|
||||
cdc codec.BinaryCodec // App-wide binary codec
|
||||
upgradeHandlers map[string]types.UpgradeHandler // map of plan name to upgrade handler
|
||||
versionModifier app.VersionModifier // implements setting the protocol version field on BaseApp
|
||||
versionModifier server.VersionModifier // implements setting the protocol version field on BaseApp
|
||||
downgradeVerified bool // tells if we've already sanity checked that this binary version isn't being used against an old state.
|
||||
authority string // the address capable of executing and canceling an upgrade. Usually the gov module account
|
||||
initVersionMap appmodule.VersionMap // the module version map at init genesis
|
||||
@ -51,7 +51,7 @@ func NewKeeper(
|
||||
skipUpgradeHeights map[int64]bool,
|
||||
cdc codec.BinaryCodec,
|
||||
homePath string,
|
||||
vs app.VersionModifier,
|
||||
vs server.VersionModifier,
|
||||
authority string,
|
||||
) *Keeper {
|
||||
k := &Keeper{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user