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:
Aleksandr Bezobchuk
2023-05-24 16:09:19 +00:00
committed by GitHub
co-authored by marbar3778 cool-developer Aaron Craelius Matt Kocubinski Julien Robert
parent 166be3766b
commit 6cee22df52
148 changed files with 14747 additions and 15262 deletions
+1 -1
View File
@@ -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
+72
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
}
+37
View File
@@ -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
View File
@@ -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)