feat!: Comet v0.38 Integration (#15519)
Co-authored-by: marbar3778 <marbar3778@yahoo.com> Co-authored-by: cool-developer <51834436+cool-develope@users.noreply.github.com> Co-authored-by: Aaron Craelius <aaron@regen.network> Co-authored-by: Matt Kocubinski <mkocubinski@gmail.com> Co-authored-by: Julien Robert <julien@rbrt.fr>
This commit is contained in:
co-authored by
marbar3778
cool-developer
Aaron Craelius
Matt Kocubinski
Julien Robert
parent
166be3766b
commit
6cee22df52
@@ -104,7 +104,7 @@ func (s *Server) Start(ctx context.Context, cfg config.Config) error {
|
||||
cmtCfg.WriteTimeout = time.Duration(cfg.API.RPCWriteTimeout) * time.Second
|
||||
cmtCfg.MaxBodyBytes = int64(cfg.API.RPCMaxBodyBytes)
|
||||
|
||||
listener, err := tmrpcserver.Listen(cfg.API.Address, cmtCfg)
|
||||
listener, err := tmrpcserver.Listen(cfg.API.Address, cmtCfg.MaxOpenConnections)
|
||||
if err != nil {
|
||||
s.mtx.Unlock()
|
||||
return err
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
abci "github.com/cometbft/cometbft/abci/types"
|
||||
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
||||
)
|
||||
|
||||
type cometABCIWrapper struct {
|
||||
app servertypes.ABCI
|
||||
}
|
||||
|
||||
func NewCometABCIWrapper(app servertypes.ABCI) abci.Application {
|
||||
return cometABCIWrapper{app: app}
|
||||
}
|
||||
|
||||
func (w cometABCIWrapper) Info(_ context.Context, req *abci.RequestInfo) (*abci.ResponseInfo, error) {
|
||||
return w.app.Info(req)
|
||||
}
|
||||
|
||||
func (w cometABCIWrapper) Query(ctx context.Context, req *abci.RequestQuery) (*abci.ResponseQuery, error) {
|
||||
return w.app.Query(ctx, req)
|
||||
}
|
||||
|
||||
func (w cometABCIWrapper) CheckTx(_ context.Context, req *abci.RequestCheckTx) (*abci.ResponseCheckTx, error) {
|
||||
return w.app.CheckTx(req)
|
||||
}
|
||||
|
||||
func (w cometABCIWrapper) InitChain(_ context.Context, req *abci.RequestInitChain) (*abci.ResponseInitChain, error) {
|
||||
return w.app.InitChain(req)
|
||||
}
|
||||
|
||||
func (w cometABCIWrapper) PrepareProposal(_ context.Context, req *abci.RequestPrepareProposal) (*abci.ResponsePrepareProposal, error) {
|
||||
return w.app.PrepareProposal(req)
|
||||
}
|
||||
|
||||
func (w cometABCIWrapper) ProcessProposal(_ context.Context, req *abci.RequestProcessProposal) (*abci.ResponseProcessProposal, error) {
|
||||
return w.app.ProcessProposal(req)
|
||||
}
|
||||
|
||||
func (w cometABCIWrapper) FinalizeBlock(_ context.Context, req *abci.RequestFinalizeBlock) (*abci.ResponseFinalizeBlock, error) {
|
||||
return w.app.FinalizeBlock(req)
|
||||
}
|
||||
|
||||
func (w cometABCIWrapper) ExtendVote(ctx context.Context, req *abci.RequestExtendVote) (*abci.ResponseExtendVote, error) {
|
||||
return w.app.ExtendVote(ctx, req)
|
||||
}
|
||||
|
||||
func (w cometABCIWrapper) VerifyVoteExtension(_ context.Context, req *abci.RequestVerifyVoteExtension) (*abci.ResponseVerifyVoteExtension, error) {
|
||||
return w.app.VerifyVoteExtension(req)
|
||||
}
|
||||
|
||||
func (w cometABCIWrapper) Commit(_ context.Context, _ *abci.RequestCommit) (*abci.ResponseCommit, error) {
|
||||
return w.app.Commit()
|
||||
}
|
||||
|
||||
func (w cometABCIWrapper) ListSnapshots(_ context.Context, req *abci.RequestListSnapshots) (*abci.ResponseListSnapshots, error) {
|
||||
return w.app.ListSnapshots(req)
|
||||
}
|
||||
|
||||
func (w cometABCIWrapper) OfferSnapshot(_ context.Context, req *abci.RequestOfferSnapshot) (*abci.ResponseOfferSnapshot, error) {
|
||||
return w.app.OfferSnapshot(req)
|
||||
}
|
||||
|
||||
func (w cometABCIWrapper) LoadSnapshotChunk(_ context.Context, req *abci.RequestLoadSnapshotChunk) (*abci.ResponseLoadSnapshotChunk, error) {
|
||||
return w.app.LoadSnapshotChunk(req)
|
||||
}
|
||||
|
||||
func (w cometABCIWrapper) ApplySnapshotChunk(_ context.Context, req *abci.RequestApplySnapshotChunk) (*abci.ResponseApplySnapshotChunk, error) {
|
||||
return w.app.ApplySnapshotChunk(req)
|
||||
}
|
||||
+3
-2
@@ -6,6 +6,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"cosmossdk.io/log"
|
||||
cmtcfg "github.com/cometbft/cometbft/config"
|
||||
"github.com/cometbft/cometbft/light"
|
||||
"github.com/cometbft/cometbft/node"
|
||||
"github.com/cometbft/cometbft/p2p"
|
||||
@@ -284,13 +285,13 @@ func BootstrapStateCmd(appCreator types.AppCreator) *cobra.Command {
|
||||
height = app.CommitMultiStore().LastCommitID().Version
|
||||
}
|
||||
|
||||
blockStoreDB, err := node.DefaultDBProvider(&node.DBContext{ID: "blockstore", Config: cfg})
|
||||
blockStoreDB, err := cmtcfg.DefaultDBProvider(&cmtcfg.DBContext{ID: "blockstore", Config: cfg})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
blockStore := store.NewBlockStore(blockStoreDB)
|
||||
|
||||
stateDB, err := node.DefaultDBProvider(&node.DBContext{ID: "state", Config: cfg})
|
||||
stateDB, err := cmtcfg.DefaultDBProvider(&cmtcfg.DBContext{ID: "state", Config: cfg})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+6
-5
@@ -17,6 +17,7 @@ import (
|
||||
bam "github.com/cosmos/cosmos-sdk/baseapp"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
|
||||
)
|
||||
@@ -24,7 +25,7 @@ import (
|
||||
// NewApp creates a simple mock kvstore app for testing. It should work
|
||||
// similar to a real app. Make sure rootDir is empty before running the test,
|
||||
// in order to guarantee consistent results.
|
||||
func NewApp(rootDir string, logger log.Logger) (abci.Application, error) {
|
||||
func NewApp(rootDir string, logger log.Logger) (servertypes.ABCI, error) {
|
||||
db, err := db.NewGoLevelDB("mock", filepath.Join(rootDir, "data"), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -96,21 +97,21 @@ type GenesisJSON struct {
|
||||
|
||||
// InitChainer returns a function that can initialize the chain
|
||||
// with key/value pairs
|
||||
func InitChainer(key storetypes.StoreKey) func(sdk.Context, abci.RequestInitChain) (abci.ResponseInitChain, error) {
|
||||
return func(ctx sdk.Context, req abci.RequestInitChain) (abci.ResponseInitChain, error) {
|
||||
func InitChainer(key storetypes.StoreKey) func(sdk.Context, *abci.RequestInitChain) (*abci.ResponseInitChain, error) {
|
||||
return func(ctx sdk.Context, req *abci.RequestInitChain) (*abci.ResponseInitChain, error) {
|
||||
stateJSON := req.AppStateBytes
|
||||
|
||||
genesisState := new(GenesisJSON)
|
||||
err := json.Unmarshal(stateJSON, genesisState)
|
||||
if err != nil {
|
||||
return abci.ResponseInitChain{}, err
|
||||
return &abci.ResponseInitChain{}, err
|
||||
}
|
||||
|
||||
for _, val := range genesisState.Values {
|
||||
store := ctx.KVStore(key)
|
||||
store.Set([]byte(val.Key), []byte(val.Value))
|
||||
}
|
||||
return abci.ResponseInitChain{}, nil
|
||||
return &abci.ResponseInitChain{}, nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+22
-16
@@ -1,22 +1,23 @@
|
||||
package mock
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/rand"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"cosmossdk.io/log"
|
||||
abci "github.com/cometbft/cometbft/abci/types"
|
||||
cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
||||
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
|
||||
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
|
||||
)
|
||||
|
||||
// SetupApp initializes a new application,
|
||||
// failing t if initialization fails.
|
||||
func SetupApp(t *testing.T) abci.Application {
|
||||
func SetupApp(t *testing.T) servertypes.ABCI {
|
||||
t.Helper()
|
||||
|
||||
logger := log.NewTestLogger(t)
|
||||
@@ -38,7 +39,12 @@ func TestInitApp(t *testing.T) {
|
||||
req := abci.RequestInitChain{
|
||||
AppStateBytes: appState,
|
||||
}
|
||||
app.InitChain(req)
|
||||
res, err := app.InitChain(&req)
|
||||
require.NoError(t, err)
|
||||
app.FinalizeBlock(&abci.RequestFinalizeBlock{
|
||||
Hash: res.AppHash,
|
||||
Height: 1,
|
||||
})
|
||||
app.Commit()
|
||||
|
||||
// make sure we can query these values
|
||||
@@ -47,7 +53,8 @@ func TestInitApp(t *testing.T) {
|
||||
Data: []byte("foo"),
|
||||
}
|
||||
|
||||
qres := app.Query(query)
|
||||
qres, err := app.Query(context.Background(), &query)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint32(0), qres.Code, qres.Log)
|
||||
require.Equal(t, []byte("bar"), qres.Value)
|
||||
}
|
||||
@@ -64,18 +71,16 @@ func TestDeliverTx(t *testing.T) {
|
||||
tx := NewTx(key, value, randomAccounts[0].Address)
|
||||
txBytes := tx.GetSignBytes()
|
||||
|
||||
app.BeginBlock(abci.RequestBeginBlock{Header: cmtproto.Header{
|
||||
AppHash: []byte("apphash"),
|
||||
Height: 1,
|
||||
}})
|
||||
res, err := app.FinalizeBlock(&abci.RequestFinalizeBlock{
|
||||
Hash: []byte("apphash"),
|
||||
Height: 1,
|
||||
Txs: [][]byte{txBytes},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, res.AppHash)
|
||||
|
||||
dres := app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes})
|
||||
require.Equal(t, uint32(0), dres.Code, dres.Log)
|
||||
|
||||
app.EndBlock(abci.RequestEndBlock{})
|
||||
|
||||
cres := app.Commit()
|
||||
require.NotEmpty(t, cres.Data)
|
||||
_, err = app.Commit()
|
||||
require.NoError(t, err)
|
||||
|
||||
// make sure we can query these values
|
||||
query := abci.RequestQuery{
|
||||
@@ -83,7 +88,8 @@ func TestDeliverTx(t *testing.T) {
|
||||
Data: []byte(key),
|
||||
}
|
||||
|
||||
qres := app.Query(query)
|
||||
qres, err := app.Query(context.Background(), &query)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint32(0), qres.Code, qres.Log)
|
||||
require.Equal(t, []byte(value), qres.Value)
|
||||
}
|
||||
|
||||
+61
-49
@@ -255,7 +255,8 @@ func startStandAlone(svrCtx *Context, app types.Application, opts StartCmdOption
|
||||
addr := svrCtx.Viper.GetString(flagAddress)
|
||||
transport := svrCtx.Viper.GetString(flagTransport)
|
||||
|
||||
svr, err := server.NewServer(addr, transport, app)
|
||||
cmtApp := NewCometABCIWrapper(app)
|
||||
svr, err := server.NewServer(addr, transport, cmtApp)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating listener: %v", err)
|
||||
}
|
||||
@@ -337,50 +338,25 @@ func startInProcess(svrCtx *Context, svrCfg serverconfig.Config, clientCtx clien
|
||||
return g.Wait()
|
||||
}
|
||||
|
||||
func startApp(svrCtx *Context, appCreator types.AppCreator, opts StartCmdOptions) (app types.Application, cleanupFn func(), err error) {
|
||||
traceWriter, traceCleanupFn, err := setupTraceWriter(svrCtx)
|
||||
if err != nil {
|
||||
return app, traceCleanupFn, err
|
||||
}
|
||||
|
||||
home := svrCtx.Config.RootDir
|
||||
db, err := opts.DBOpener(home, GetAppDBBackend(svrCtx.Viper))
|
||||
if err != nil {
|
||||
return app, traceCleanupFn, err
|
||||
}
|
||||
|
||||
app = appCreator(svrCtx.Logger, db, traceWriter, svrCtx.Viper)
|
||||
cleanupFn = func() {
|
||||
traceCleanupFn()
|
||||
if localErr := app.Close(); localErr != nil {
|
||||
svrCtx.Logger.Error(localErr.Error())
|
||||
}
|
||||
}
|
||||
return app, cleanupFn, nil
|
||||
}
|
||||
|
||||
func getCtx(svrCtx *Context, block bool) (*errgroup.Group, context.Context) {
|
||||
ctx, cancelFn := context.WithCancel(context.Background())
|
||||
g, ctx := errgroup.WithContext(ctx)
|
||||
// listen for quit signals so the calling parent process can gracefully exit
|
||||
ListenForQuitSignals(g, block, cancelFn, svrCtx.Logger)
|
||||
return g, ctx
|
||||
}
|
||||
|
||||
func startCmtNode(cfg *cmtcfg.Config, app types.Application, svrCtx *Context) (tmNode *node.Node, cleanupFn func(), err error) {
|
||||
cleanupFn = func() {}
|
||||
// TODO: Move nodeKey into being created within the function.
|
||||
func startCmtNode(
|
||||
cfg *cmtcfg.Config,
|
||||
app types.Application,
|
||||
svrCtx *Context,
|
||||
) (tmNode *node.Node, cleanupFn func(), err error) {
|
||||
nodeKey, err := p2p.LoadOrGenNodeKey(cfg.NodeKeyFile())
|
||||
if err != nil {
|
||||
return nil, cleanupFn, err
|
||||
}
|
||||
|
||||
cmtApp := NewCometABCIWrapper(app)
|
||||
tmNode, err = node.NewNode(
|
||||
cfg,
|
||||
pvm.LoadOrGenFilePV(cfg.PrivValidatorKeyFile(), cfg.PrivValidatorStateFile()),
|
||||
nodeKey,
|
||||
proxy.NewLocalClientCreator(app),
|
||||
proxy.NewLocalClientCreator(cmtApp),
|
||||
getGenDocProvider(cfg),
|
||||
node.DefaultDBProvider,
|
||||
cmtcfg.DefaultDBProvider,
|
||||
node.DefaultMetricsProvider(cfg.Instrumentation),
|
||||
servercmtlog.CometLoggerWrapper{Logger: svrCtx.Logger},
|
||||
)
|
||||
@@ -448,9 +424,14 @@ func setupTraceWriter(svrCtx *Context) (traceWriter io.WriteCloser, cleanup func
|
||||
return traceWriter, cleanup, nil
|
||||
}
|
||||
|
||||
func startGrpcServer(ctx context.Context, g *errgroup.Group, config serverconfig.GRPCConfig, clientCtx client.Context, svrCtx *Context, app types.Application) (
|
||||
*grpc.Server, client.Context, error,
|
||||
) {
|
||||
func startGrpcServer(
|
||||
ctx context.Context,
|
||||
g *errgroup.Group,
|
||||
config serverconfig.GRPCConfig,
|
||||
clientCtx client.Context,
|
||||
svrCtx *Context,
|
||||
app types.Application,
|
||||
) (*grpc.Server, client.Context, error) {
|
||||
if !config.Enable {
|
||||
// return grpcServer as nil if gRPC is disabled
|
||||
return nil, clientCtx, nil
|
||||
@@ -502,22 +483,23 @@ func startGrpcServer(ctx context.Context, g *errgroup.Group, config serverconfig
|
||||
return grpcSrv, clientCtx, nil
|
||||
}
|
||||
|
||||
func startAPIServer(ctx context.Context, g *errgroup.Group, cmtCfg *cmtcfg.Config, svrCfg serverconfig.Config,
|
||||
clientCtx client.Context, svrCtx *Context, app types.Application, home string, grpcSrv *grpc.Server, metrics *telemetry.Metrics,
|
||||
func startAPIServer(
|
||||
ctx context.Context,
|
||||
g *errgroup.Group,
|
||||
cmtCfg *cmtcfg.Config,
|
||||
svrCfg serverconfig.Config,
|
||||
clientCtx client.Context,
|
||||
svrCtx *Context,
|
||||
app types.Application,
|
||||
home string,
|
||||
grpcSrv *grpc.Server,
|
||||
metrics *telemetry.Metrics,
|
||||
) error {
|
||||
if !svrCfg.API.Enable {
|
||||
return nil
|
||||
}
|
||||
// TODO: Why do we reload and unmarshal the entire genesis doc in order to get the chain ID.
|
||||
// surely theres a better way. This is likely a serious node start time overhead.
|
||||
// Shouldn't it be in cmtCfg.ChainID() ?
|
||||
genDocProvider := getGenDocProvider(cmtCfg)
|
||||
genDoc, err := genDocProvider()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
clientCtx = clientCtx.WithHomeDir(home).WithChainID(genDoc.ChainID)
|
||||
clientCtx = clientCtx.WithHomeDir(home)
|
||||
|
||||
apiSrv := api.New(clientCtx, svrCtx.Logger.With("module", "api-server"), grpcSrv)
|
||||
app.RegisterAPIRoutes(apiSrv, svrCfg.API)
|
||||
@@ -594,3 +576,33 @@ func emitServerInfoMetrics() {
|
||||
|
||||
telemetry.SetGaugeWithLabels([]string{"server", "info"}, 1, ls)
|
||||
}
|
||||
|
||||
func getCtx(svrCtx *Context, block bool) (*errgroup.Group, context.Context) {
|
||||
ctx, cancelFn := context.WithCancel(context.Background())
|
||||
g, ctx := errgroup.WithContext(ctx)
|
||||
// listen for quit signals so the calling parent process can gracefully exit
|
||||
ListenForQuitSignals(g, block, cancelFn, svrCtx.Logger)
|
||||
return g, ctx
|
||||
}
|
||||
|
||||
func startApp(svrCtx *Context, appCreator types.AppCreator, opts StartCmdOptions) (app types.Application, cleanupFn func(), err error) {
|
||||
traceWriter, traceCleanupFn, err := setupTraceWriter(svrCtx)
|
||||
if err != nil {
|
||||
return app, traceCleanupFn, err
|
||||
}
|
||||
|
||||
home := svrCtx.Config.RootDir
|
||||
db, err := opts.DBOpener(home, GetAppDBBackend(svrCtx.Viper))
|
||||
if err != nil {
|
||||
return app, traceCleanupFn, err
|
||||
}
|
||||
|
||||
app = appCreator(svrCtx.Logger, db, traceWriter, svrCtx.Viper)
|
||||
cleanupFn = func() {
|
||||
traceCleanupFn()
|
||||
if localErr := app.Close(); localErr != nil {
|
||||
svrCtx.Logger.Error(localErr.Error())
|
||||
}
|
||||
}
|
||||
return app, cleanupFn, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
abci "github.com/cometbft/cometbft/abci/types"
|
||||
)
|
||||
|
||||
// ABCI is an interface that enables any finite, deterministic state machine
|
||||
// to be driven by a blockchain-based replication engine via the ABCI.
|
||||
type ABCI interface {
|
||||
// Info/Query Connection
|
||||
Info(*abci.RequestInfo) (*abci.ResponseInfo, error) // Return application info
|
||||
Query(context.Context, *abci.RequestQuery) (*abci.ResponseQuery, error) // Query for state
|
||||
|
||||
// Mempool Connection
|
||||
CheckTx(*abci.RequestCheckTx) (*abci.ResponseCheckTx, error) // Validate a tx for the mempool
|
||||
|
||||
// Consensus Connection
|
||||
InitChain(*abci.RequestInitChain) (*abci.ResponseInitChain, error) // Initialize blockchain w validators/other info from CometBFT
|
||||
PrepareProposal(*abci.RequestPrepareProposal) (*abci.ResponsePrepareProposal, error)
|
||||
ProcessProposal(*abci.RequestProcessProposal) (*abci.ResponseProcessProposal, error)
|
||||
// Deliver the decided block with its txs to the Application
|
||||
FinalizeBlock(*abci.RequestFinalizeBlock) (*abci.ResponseFinalizeBlock, error)
|
||||
// Create application specific vote extension
|
||||
ExtendVote(context.Context, *abci.RequestExtendVote) (*abci.ResponseExtendVote, error)
|
||||
// Verify application's vote extension data
|
||||
VerifyVoteExtension(*abci.RequestVerifyVoteExtension) (*abci.ResponseVerifyVoteExtension, error)
|
||||
// Commit the state and return the application Merkle root hash
|
||||
Commit() (*abci.ResponseCommit, error)
|
||||
|
||||
// State Sync Connection
|
||||
ListSnapshots(*abci.RequestListSnapshots) (*abci.ResponseListSnapshots, error) // List available snapshots
|
||||
OfferSnapshot(*abci.RequestOfferSnapshot) (*abci.ResponseOfferSnapshot, error) // Offer a snapshot to the application
|
||||
LoadSnapshotChunk(*abci.RequestLoadSnapshotChunk) (*abci.ResponseLoadSnapshotChunk, error) // Load a snapshot chunk
|
||||
ApplySnapshotChunk(*abci.RequestApplySnapshotChunk) (*abci.ResponseApplySnapshotChunk, error) // Apply a shapshot chunk
|
||||
}
|
||||
+1
-2
@@ -7,7 +7,6 @@ import (
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/store/snapshots"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
abci "github.com/cometbft/cometbft/abci/types"
|
||||
cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
|
||||
cmttypes "github.com/cometbft/cometbft/types"
|
||||
dbm "github.com/cosmos/cosmos-db"
|
||||
@@ -35,7 +34,7 @@ type (
|
||||
// The interface defines the necessary contracts to be implemented in order
|
||||
// to fully bootstrap and start an application.
|
||||
Application interface {
|
||||
abci.Application
|
||||
ABCI
|
||||
|
||||
RegisterAPIRoutes(*api.Server, config.APIConfig)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user