diff --git a/contribs/gnodev/pkg/dev/node.go b/contribs/gnodev/pkg/dev/node.go index d70cf0f1c85..4decc806638 100644 --- a/contribs/gnodev/pkg/dev/node.go +++ b/contribs/gnodev/pkg/dev/node.go @@ -70,13 +70,12 @@ func NewDevNode(ctx context.Context, logger *slog.Logger, emitter emitter.Emitte if err != nil { return nil, fmt.Errorf("unable to initialize the node: %w", err) } - client := client.NewLocal(node) return &Node{ Node: node, emitter: emitter, - client: client, + client: client.NewLocal(), pkgs: mpkgs, logger: logger, loadedPackages: len(pkgsTxs), diff --git a/contribs/gnokeykc/go.mod b/contribs/gnokeykc/go.mod index 5bfce2a4ddd..dc4267fa914 100644 --- a/contribs/gnokeykc/go.mod +++ b/contribs/gnokeykc/go.mod @@ -10,7 +10,6 @@ require ( ) require ( - dario.cat/mergo v1.0.0 // indirect github.com/alessio/shellescape v1.4.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/btcsuite/btcd/btcutil v1.1.3 // indirect @@ -31,7 +30,6 @@ require ( github.com/peterbourgon/ff/v3 v3.4.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rs/cors v1.10.1 // indirect github.com/stretchr/testify v1.8.4 // indirect github.com/zondax/hid v0.9.2 // indirect github.com/zondax/ledger-go v0.14.3 // indirect diff --git a/tm2/pkg/bft/proxy/app_conn.go b/tm2/pkg/bft/appconn/app_conn.go similarity index 52% rename from tm2/pkg/bft/proxy/app_conn.go rename to tm2/pkg/bft/appconn/app_conn.go index 0bb3c76f331..078a7ba1180 100644 --- a/tm2/pkg/bft/proxy/app_conn.go +++ b/tm2/pkg/bft/appconn/app_conn.go @@ -1,4 +1,5 @@ -package proxy +// Package appconn manages the connection of Tendermint to the application layer. +package appconn import ( abcicli "github.com/gnolang/gno/tm2/pkg/bft/abci/client" @@ -8,7 +9,7 @@ import ( //---------------------------------------------------------------------------------------- // Enforce which abci msgs can be sent on a connection at the type level -type AppConnConsensus interface { +type Consensus interface { SetResponseCallback(abcicli.Callback) Error() error @@ -20,7 +21,7 @@ type AppConnConsensus interface { CommitSync() (abci.ResponseCommit, error) } -type AppConnMempool interface { +type Mempool interface { SetResponseCallback(abcicli.Callback) Error() error @@ -30,7 +31,7 @@ type AppConnMempool interface { FlushSync() error } -type AppConnQuery interface { +type Query interface { Error() error EchoSync(string) (abci.ResponseEcho, error) @@ -41,104 +42,104 @@ type AppConnQuery interface { } //----------------------------------------------------------------------------------------- -// Implements AppConnConsensus (subset of abcicli.Client) +// Implements Consensus (subset of abcicli.Client) -type appConnConsensus struct { +type consensus struct { appConn abcicli.Client } -func NewAppConnConsensus(appConn abcicli.Client) *appConnConsensus { - return &appConnConsensus{ +func NewConsensus(appConn abcicli.Client) *consensus { + return &consensus{ appConn: appConn, } } -func (app *appConnConsensus) SetResponseCallback(cb abcicli.Callback) { +func (app *consensus) SetResponseCallback(cb abcicli.Callback) { app.appConn.SetResponseCallback(cb) } -func (app *appConnConsensus) Error() error { +func (app *consensus) Error() error { return app.appConn.Error() } -func (app *appConnConsensus) InitChainSync(req abci.RequestInitChain) (abci.ResponseInitChain, error) { +func (app *consensus) InitChainSync(req abci.RequestInitChain) (abci.ResponseInitChain, error) { return app.appConn.InitChainSync(req) } -func (app *appConnConsensus) BeginBlockSync(req abci.RequestBeginBlock) (abci.ResponseBeginBlock, error) { +func (app *consensus) BeginBlockSync(req abci.RequestBeginBlock) (abci.ResponseBeginBlock, error) { return app.appConn.BeginBlockSync(req) } -func (app *appConnConsensus) DeliverTxAsync(req abci.RequestDeliverTx) *abcicli.ReqRes { +func (app *consensus) DeliverTxAsync(req abci.RequestDeliverTx) *abcicli.ReqRes { return app.appConn.DeliverTxAsync(req) } -func (app *appConnConsensus) EndBlockSync(req abci.RequestEndBlock) (abci.ResponseEndBlock, error) { +func (app *consensus) EndBlockSync(req abci.RequestEndBlock) (abci.ResponseEndBlock, error) { return app.appConn.EndBlockSync(req) } -func (app *appConnConsensus) CommitSync() (abci.ResponseCommit, error) { +func (app *consensus) CommitSync() (abci.ResponseCommit, error) { return app.appConn.CommitSync() } //------------------------------------------------ -// Implements AppConnMempool (subset of abcicli.Client) +// Implements Mempool (subset of abcicli.Client) -type appConnMempool struct { +type mempool struct { appConn abcicli.Client } -func NewAppConnMempool(appConn abcicli.Client) *appConnMempool { - return &appConnMempool{ +func NewMempool(appConn abcicli.Client) *mempool { + return &mempool{ appConn: appConn, } } -func (app *appConnMempool) SetResponseCallback(cb abcicli.Callback) { +func (app *mempool) SetResponseCallback(cb abcicli.Callback) { app.appConn.SetResponseCallback(cb) } -func (app *appConnMempool) Error() error { +func (app *mempool) Error() error { return app.appConn.Error() } -func (app *appConnMempool) FlushAsync() *abcicli.ReqRes { +func (app *mempool) FlushAsync() *abcicli.ReqRes { return app.appConn.FlushAsync() } -func (app *appConnMempool) FlushSync() error { +func (app *mempool) FlushSync() error { return app.appConn.FlushSync() } -func (app *appConnMempool) CheckTxAsync(req abci.RequestCheckTx) *abcicli.ReqRes { +func (app *mempool) CheckTxAsync(req abci.RequestCheckTx) *abcicli.ReqRes { return app.appConn.CheckTxAsync(req) } //------------------------------------------------ -// Implements AppConnQuery (subset of abcicli.Client) +// Implements Query (subset of abcicli.Client) -type appConnQuery struct { +type query struct { appConn abcicli.Client } -func NewAppConnQuery(appConn abcicli.Client) *appConnQuery { - return &appConnQuery{ +func NewQuery(appConn abcicli.Client) *query { + return &query{ appConn: appConn, } } -func (app *appConnQuery) Error() error { +func (app *query) Error() error { return app.appConn.Error() } -func (app *appConnQuery) EchoSync(msg string) (abci.ResponseEcho, error) { +func (app *query) EchoSync(msg string) (abci.ResponseEcho, error) { return app.appConn.EchoSync(msg) } -func (app *appConnQuery) InfoSync(req abci.RequestInfo) (abci.ResponseInfo, error) { +func (app *query) InfoSync(req abci.RequestInfo) (abci.ResponseInfo, error) { return app.appConn.InfoSync(req) } -func (app *appConnQuery) QuerySync(reqQuery abci.RequestQuery) (abci.ResponseQuery, error) { +func (app *query) QuerySync(reqQuery abci.RequestQuery) (abci.ResponseQuery, error) { return app.appConn.QuerySync(reqQuery) } diff --git a/tm2/pkg/bft/proxy/multi_app_conn.go b/tm2/pkg/bft/appconn/multi_app_conn.go similarity index 68% rename from tm2/pkg/bft/proxy/multi_app_conn.go rename to tm2/pkg/bft/appconn/multi_app_conn.go index b820dbcb286..ba241d262a7 100644 --- a/tm2/pkg/bft/proxy/multi_app_conn.go +++ b/tm2/pkg/bft/appconn/multi_app_conn.go @@ -1,6 +1,7 @@ -package proxy +package appconn import ( + abcicli "github.com/gnolang/gno/tm2/pkg/bft/abci/client" "github.com/gnolang/gno/tm2/pkg/errors" "github.com/gnolang/gno/tm2/pkg/service" ) @@ -11,56 +12,61 @@ import ( type AppConns interface { service.Service - Mempool() AppConnMempool - Consensus() AppConnConsensus - Query() AppConnQuery + Mempool() Mempool + Consensus() Consensus + Query() Query +} + +// NewABCIClient returns newly connected client +type ClientCreator interface { + NewABCIClient() (abcicli.Client, error) } func NewAppConns(clientCreator ClientCreator) AppConns { - return NewMultiAppConn(clientCreator) + return NewMulti(clientCreator) } //----------------------------- -// multiAppConn implements AppConns +// multi implements AppConns -// a multiAppConn is made of a few appConns (mempool, consensus, query) +// a multi is made of a few appConns (mempool, consensus, query) // and manages their underlying abci clients // TODO: on app restart, clients must reboot together -type multiAppConn struct { +type multi struct { service.BaseService - mempoolConn *appConnMempool - consensusConn *appConnConsensus - queryConn *appConnQuery + mempoolConn *mempool + consensusConn *consensus + queryConn *query clientCreator ClientCreator } // Make all necessary abci connections to the application -func NewMultiAppConn(clientCreator ClientCreator) *multiAppConn { - multiAppConn := &multiAppConn{ +func NewMulti(clientCreator ClientCreator) *multi { + multi := &multi{ clientCreator: clientCreator, } - multiAppConn.BaseService = *service.NewBaseService(nil, "multiAppConn", multiAppConn) - return multiAppConn + multi.BaseService = *service.NewBaseService(nil, "multi", multi) + return multi } // Returns the mempool connection -func (app *multiAppConn) Mempool() AppConnMempool { +func (app *multi) Mempool() Mempool { return app.mempoolConn } // Returns the consensus Connection -func (app *multiAppConn) Consensus() AppConnConsensus { +func (app *multi) Consensus() Consensus { return app.consensusConn } // Returns the query Connection -func (app *multiAppConn) Query() AppConnQuery { +func (app *multi) Query() Query { return app.queryConn } -func (app *multiAppConn) OnStart() error { +func (app *multi) OnStart() error { // query connection querycli, err := app.clientCreator.NewABCIClient() if err != nil { @@ -70,7 +76,7 @@ func (app *multiAppConn) OnStart() error { if err := querycli.Start(); err != nil { return errors.Wrap(err, "Error starting ABCI client (query connection)") } - app.queryConn = NewAppConnQuery(querycli) + app.queryConn = NewQuery(querycli) // mempool connection memcli, err := app.clientCreator.NewABCIClient() @@ -81,7 +87,7 @@ func (app *multiAppConn) OnStart() error { if err := memcli.Start(); err != nil { return errors.Wrap(err, "Error starting ABCI client (mempool connection)") } - app.mempoolConn = NewAppConnMempool(memcli) + app.mempoolConn = NewMempool(memcli) // consensus connection concli, err := app.clientCreator.NewABCIClient() @@ -92,7 +98,7 @@ func (app *multiAppConn) OnStart() error { if err := concli.Start(); err != nil { return errors.Wrap(err, "Error starting ABCI client (consensus connection)") } - app.consensusConn = NewAppConnConsensus(concli) + app.consensusConn = NewConsensus(concli) return nil } diff --git a/tm2/pkg/bft/blockchain/reactor_test.go b/tm2/pkg/bft/blockchain/reactor_test.go index 935c56f0b52..7f96cdefc97 100644 --- a/tm2/pkg/bft/blockchain/reactor_test.go +++ b/tm2/pkg/bft/blockchain/reactor_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" + "github.com/gnolang/gno/tm2/pkg/bft/appconn" cfg "github.com/gnolang/gno/tm2/pkg/bft/config" "github.com/gnolang/gno/tm2/pkg/bft/mempool/mock" "github.com/gnolang/gno/tm2/pkg/bft/proxy" @@ -48,7 +49,7 @@ func randGenesisDoc(numValidators int, randPower bool, minPower int64) (*types.G type BlockchainReactorPair struct { reactor *BlockchainReactor - app proxy.AppConns + app appconn.AppConns } func newBlockchainReactor(logger *slog.Logger, genDoc *types.GenesisDoc, privVals []types.PrivValidator, maxBlockHeight int64) BlockchainReactorPair { @@ -58,7 +59,7 @@ func newBlockchainReactor(logger *slog.Logger, genDoc *types.GenesisDoc, privVal app := &testApp{} cc := proxy.NewLocalClientCreator(app) - proxyApp := proxy.NewAppConns(cc) + proxyApp := appconn.NewAppConns(cc) err := proxyApp.Start() if err != nil { panic(errors.Wrap(err, "error start app")) diff --git a/tm2/pkg/bft/consensus/reactor.go b/tm2/pkg/bft/consensus/reactor.go index ed7a6ae6547..aee695114f8 100644 --- a/tm2/pkg/bft/consensus/reactor.go +++ b/tm2/pkg/bft/consensus/reactor.go @@ -875,26 +875,14 @@ var ( // PeerState contains the known state of a peer, including its connection and // threadsafe access to its PeerRoundState. -// NOTE: THIS GETS DUMPED WITH rpc/core/consensus.go. +// NOTE: PeerStateExposed gets dumped with rpc/core/consensus.go. // Be mindful of what you Expose. type PeerState struct { peer p2p.Peer logger *slog.Logger - mtx sync.Mutex // NOTE: Modify below using setters, never directly. - PRS cstypes.PeerRoundState `json:"round_state"` // Exposed. - Stats *peerStateStats `json:"stats"` // Exposed. -} - -// peerStateStats holds internal statistics for a peer. -type peerStateStats struct { - Votes int `json:"votes"` - BlockParts int `json:"block_parts"` -} - -func (pss peerStateStats) String() string { - return fmt.Sprintf("peerStateStats{votes: %d, blockParts: %d}", - pss.Votes, pss.BlockParts) + mtx sync.Mutex // NOTE: Modify below using setters, never directly. + cstypes.PeerStateExposed } // NewPeerState returns a new PeerState for the given Peer @@ -902,13 +890,15 @@ func NewPeerState(peer p2p.Peer) *PeerState { return &PeerState{ peer: peer, logger: log.NewNoopLogger(), - PRS: cstypes.PeerRoundState{ - Round: -1, - ProposalPOLRound: -1, - LastCommitRound: -1, - CatchupCommitRound: -1, + PeerStateExposed: cstypes.PeerStateExposed{ + PRS: cstypes.PeerRoundState{ + Round: -1, + ProposalPOLRound: -1, + LastCommitRound: -1, + CatchupCommitRound: -1, + }, + Stats: &cstypes.PeerStateStats{}, }, - Stats: &peerStateStats{}, } } @@ -929,12 +919,14 @@ func (ps *PeerState) GetRoundState() *cstypes.PeerRoundState { return &prs } -// ToJSON returns a json of PeerState, marshalled using go-amino. -func (ps *PeerState) ToJSON() ([]byte, error) { +// GetExposed returns the PeerStateExposed. This method is type-asserted for +// working with rpc/core.go without an import. +// The returned value is read-only. +func (ps *PeerState) GetExposed() cstypes.PeerStateExposed { ps.mtx.Lock() defer ps.mtx.Unlock() - return amino.MarshalJSON(ps) + return ps.PeerStateExposed } // GetHeight returns an atomic snapshot of the PeerRoundState's height diff --git a/tm2/pkg/bft/consensus/replay.go b/tm2/pkg/bft/consensus/replay.go index 5fe24229007..a423d634c2f 100644 --- a/tm2/pkg/bft/consensus/replay.go +++ b/tm2/pkg/bft/consensus/replay.go @@ -10,6 +10,7 @@ import ( "time" abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" + "github.com/gnolang/gno/tm2/pkg/bft/appconn" cstypes "github.com/gnolang/gno/tm2/pkg/bft/consensus/types" "github.com/gnolang/gno/tm2/pkg/bft/mempool/mock" "github.com/gnolang/gno/tm2/pkg/bft/proxy" @@ -232,7 +233,7 @@ func (h *Handshaker) NBlocks() int { } // TODO: retry the handshake/replay if it fails ? -func (h *Handshaker) Handshake(proxyApp proxy.AppConns) error { +func (h *Handshaker) Handshake(proxyApp appconn.AppConns) error { // Handshake is done via ABCI Info on the query conn. res, err := proxyApp.Query().InfoSync(abci.RequestInfo{}) if err != nil { @@ -279,7 +280,7 @@ func (h *Handshaker) ReplayBlocks( state sm.State, appHash []byte, appBlockHeight int64, - proxyApp proxy.AppConns, + proxyApp appconn.AppConns, ) ([]byte, error) { storeBlockHeight := h.store.Height() stateBlockHeight := state.LastBlockHeight @@ -392,7 +393,7 @@ func (h *Handshaker) ReplayBlocks( appBlockHeight, storeBlockHeight, stateBlockHeight)) } -func (h *Handshaker) replayBlocks(state sm.State, proxyApp proxy.AppConns, appBlockHeight, storeBlockHeight int64, mutateState bool) ([]byte, error) { +func (h *Handshaker) replayBlocks(state sm.State, proxyApp appconn.AppConns, appBlockHeight, storeBlockHeight int64, mutateState bool) ([]byte, error) { // App is further behind than it should be, so we need to replay blocks. // We replay all blocks from appBlockHeight+1. // @@ -439,7 +440,7 @@ func (h *Handshaker) replayBlocks(state sm.State, proxyApp proxy.AppConns, appBl } // ApplyBlock on the proxyApp with the last block. -func (h *Handshaker) replayBlock(state sm.State, height int64, proxyApp proxy.AppConnConsensus) (sm.State, error) { +func (h *Handshaker) replayBlock(state sm.State, height int64, proxyApp appconn.Consensus) (sm.State, error) { block := h.store.LoadBlock(height) meta := h.store.LoadBlockMeta(height) @@ -483,7 +484,7 @@ Did you reset Tendermint without resetting your application's data?`, // mockProxyApp uses ABCIResponses to give the right results // Useful because we don't want to call Commit() twice for the same block on the real app. -func newMockProxyApp(appHash []byte, abciResponses *sm.ABCIResponses) proxy.AppConnConsensus { +func newMockProxyApp(appHash []byte, abciResponses *sm.ABCIResponses) appconn.Consensus { clientCreator := proxy.NewLocalClientCreator(&mockProxyApp{ appHash: appHash, abciResponses: abciResponses, @@ -493,7 +494,7 @@ func newMockProxyApp(appHash []byte, abciResponses *sm.ABCIResponses) proxy.AppC if err != nil { panic(err) } - return proxy.NewAppConnConsensus(cli) + return appconn.Consensus(cli) } type mockProxyApp struct { diff --git a/tm2/pkg/bft/consensus/replay_file.go b/tm2/pkg/bft/consensus/replay_file.go index 7bfa3de9231..bddc6b429be 100644 --- a/tm2/pkg/bft/consensus/replay_file.go +++ b/tm2/pkg/bft/consensus/replay_file.go @@ -9,6 +9,7 @@ import ( "strconv" "strings" + "github.com/gnolang/gno/tm2/pkg/bft/appconn" cfg "github.com/gnolang/gno/tm2/pkg/bft/config" cnscfg "github.com/gnolang/gno/tm2/pkg/bft/consensus/config" cstypes "github.com/gnolang/gno/tm2/pkg/bft/consensus/types" @@ -301,7 +302,7 @@ func newConsensusStateForReplay(config cfg.BaseConfig, csConfig *cnscfg.Consensu config.ABCI, config.DBDir(), ) - proxyApp := proxy.NewAppConns(clientCreator) + proxyApp := appconn.NewAppConns(clientCreator) err = proxyApp.Start() if err != nil { osm.Exit(fmt.Sprintf("Error starting proxy app conns: %v", err)) diff --git a/tm2/pkg/bft/consensus/replay_test.go b/tm2/pkg/bft/consensus/replay_test.go index fd586a1ec4f..6f138cd03e1 100644 --- a/tm2/pkg/bft/consensus/replay_test.go +++ b/tm2/pkg/bft/consensus/replay_test.go @@ -20,6 +20,7 @@ import ( "github.com/gnolang/gno/tm2/pkg/amino" "github.com/gnolang/gno/tm2/pkg/bft/abci/example/kvstore" abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" + "github.com/gnolang/gno/tm2/pkg/bft/appconn" cfg "github.com/gnolang/gno/tm2/pkg/bft/config" cstypes "github.com/gnolang/gno/tm2/pkg/bft/consensus/types" "github.com/gnolang/gno/tm2/pkg/bft/mempool/mock" @@ -690,7 +691,7 @@ func testHandshakeReplay(t *testing.T, config *cfg.Config, nBlocks int, mode uin if nBlocks > 0 { // run nBlocks against a new client to build up the app state. // use a throwaway tendermint state - proxyApp := proxy.NewAppConns(clientCreator2) + proxyApp := appconn.NewAppConns(clientCreator2) stateDB1 := memdb.NewMemDB() sm.SaveState(stateDB1, genesisState) buildAppStateFromChain(proxyApp, stateDB1, genesisState, chain, nBlocks, mode) @@ -701,7 +702,7 @@ func testHandshakeReplay(t *testing.T, config *cfg.Config, nBlocks int, mode uin genDoc, _ := sm.MakeGenesisDocFromFile(config.GenesisFile()) handshaker := NewHandshaker(stateDB, state, store, genDoc) handshaker.SetEventSwitch(evsw) - proxyApp := proxy.NewAppConns(clientCreator2) + proxyApp := appconn.NewAppConns(clientCreator2) if err := proxyApp.Start(); err != nil { t.Fatalf("Error starting proxy app connections: %v", err) } @@ -733,7 +734,7 @@ func testHandshakeReplay(t *testing.T, config *cfg.Config, nBlocks int, mode uin } } -func applyBlock(stateDB dbm.DB, st sm.State, blk *types.Block, proxyApp proxy.AppConns) sm.State { +func applyBlock(stateDB dbm.DB, st sm.State, blk *types.Block, proxyApp appconn.AppConns) sm.State { testPartSize := types.BlockPartSizeBytes blockExec := sm.NewBlockExecutor(stateDB, log.NewNoopLogger(), proxyApp.Consensus(), mempool) @@ -745,7 +746,7 @@ func applyBlock(stateDB dbm.DB, st sm.State, blk *types.Block, proxyApp proxy.Ap return newState } -func buildAppStateFromChain(proxyApp proxy.AppConns, stateDB dbm.DB, +func buildAppStateFromChain(proxyApp appconn.AppConns, stateDB dbm.DB, state sm.State, chain []*types.Block, nBlocks int, mode uint, ) { // start a new app without handshake, play nBlocks blocks @@ -788,7 +789,7 @@ func buildTMStateFromChain(config *cfg.Config, stateDB dbm.DB, state sm.State, c app := kvstore.NewPersistentKVStoreApplication(filepath.Join(config.DBDir(), fmt.Sprintf("replay_test_%d_%d_t", nBlocks, mode))) defer app.Close() clientCreator := proxy.NewLocalClientCreator(app) - proxyApp := proxy.NewAppConns(clientCreator) + proxyApp := appconn.NewAppConns(clientCreator) if err := proxyApp.Start(); err != nil { panic(err) } @@ -850,7 +851,7 @@ func TestHandshakePanicsIfAppReturnsWrongAppHash(t *testing.T) { { app := &badApp{numBlocks: 3, allHashesAreWrong: true} clientCreator := proxy.NewLocalClientCreator(app) - proxyApp := proxy.NewAppConns(clientCreator) + proxyApp := appconn.NewAppConns(clientCreator) err := proxyApp.Start() require.NoError(t, err) defer proxyApp.Stop() @@ -868,7 +869,7 @@ func TestHandshakePanicsIfAppReturnsWrongAppHash(t *testing.T) { { app := &badApp{numBlocks: 3, onlyLastHashIsWrong: true} clientCreator := proxy.NewLocalClientCreator(app) - proxyApp := proxy.NewAppConns(clientCreator) + proxyApp := appconn.NewAppConns(clientCreator) err := proxyApp.Start() require.NoError(t, err) defer proxyApp.Stop() @@ -1124,7 +1125,7 @@ func TestHandshakeUpdatesValidators(t *testing.T) { // now start the app using the handshake - it should sync genDoc, _ := sm.MakeGenesisDocFromFile(config.GenesisFile()) handshaker := NewHandshaker(stateDB, state, store, genDoc) - proxyApp := proxy.NewAppConns(clientCreator) + proxyApp := appconn.NewAppConns(clientCreator) if err := proxyApp.Start(); err != nil { t.Fatalf("Error starting proxy app connections: %v", err) } diff --git a/tm2/pkg/bft/consensus/types/peer_round_state.go b/tm2/pkg/bft/consensus/types/peer_round_state.go index f92528657ba..3a569c43d7e 100644 --- a/tm2/pkg/bft/consensus/types/peer_round_state.go +++ b/tm2/pkg/bft/consensus/types/peer_round_state.go @@ -4,6 +4,7 @@ import ( "fmt" "time" + "github.com/gnolang/gno/tm2/pkg/amino" "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/bitarray" ) @@ -55,3 +56,28 @@ func (prs PeerRoundState) StringIndented(indent string) string { indent, prs.CatchupCommit, prs.CatchupCommitRound, indent) } + +//----------------------------------------------------------------------------- + +// PeerStateExposed represents the exposed information about a peer. +// NOTE: This gets dumped with rpc/core/consensus.go. Be mindful of what you expose. +type PeerStateExposed struct { + PRS PeerRoundState `json:"round_state"` // Exposed. + Stats *PeerStateStats `json:"stats"` // Exposed. +} + +// ToJSON returns a json of PeerState, marshalled using go-amino. +func (ps PeerStateExposed) ToJSON() ([]byte, error) { + return amino.MarshalJSON(ps) +} + +// PeerStateStats holds internal statistics for a peer. +type PeerStateStats struct { + Votes int `json:"votes"` + BlockParts int `json:"block_parts"` +} + +func (pss PeerStateStats) String() string { + return fmt.Sprintf("PeerStateStats{votes: %d, blockParts: %d}", + pss.Votes, pss.BlockParts) +} diff --git a/tm2/pkg/bft/consensus/wal_generator.go b/tm2/pkg/bft/consensus/wal_generator.go index 0e51249f685..175771f50ed 100644 --- a/tm2/pkg/bft/consensus/wal_generator.go +++ b/tm2/pkg/bft/consensus/wal_generator.go @@ -1,129 +1,17 @@ package consensus import ( - "bufio" - "bytes" "fmt" "io" "log/slog" - "path/filepath" "testing" "time" - "github.com/gnolang/gno/tm2/pkg/bft/abci/example/kvstore" cfg "github.com/gnolang/gno/tm2/pkg/bft/config" - "github.com/gnolang/gno/tm2/pkg/bft/mempool/mock" - "github.com/gnolang/gno/tm2/pkg/bft/privval" - "github.com/gnolang/gno/tm2/pkg/bft/proxy" - sm "github.com/gnolang/gno/tm2/pkg/bft/state" - "github.com/gnolang/gno/tm2/pkg/bft/store" - "github.com/gnolang/gno/tm2/pkg/bft/types" walm "github.com/gnolang/gno/tm2/pkg/bft/wal" - "github.com/gnolang/gno/tm2/pkg/db/memdb" - "github.com/gnolang/gno/tm2/pkg/errors" - "github.com/gnolang/gno/tm2/pkg/events" - "github.com/gnolang/gno/tm2/pkg/log" "github.com/gnolang/gno/tm2/pkg/random" ) -// WALGenerateNBlocks generates a consensus WAL. It does this by spinning up a -// stripped down version of node (proxy app, event bus, consensus state) with a -// persistent kvstore application and special consensus wal instance -// (heightStopWAL) and waits until numBlocks are created. If the node fails to produce given numBlocks, it returns an error. -func WALGenerateNBlocks(t *testing.T, wr io.Writer, numBlocks int) (err error) { - t.Helper() - - config := getConfig(t) - - app := kvstore.NewPersistentKVStoreApplication(filepath.Join(config.DBDir(), "wal_generator")) - defer app.Close() - - logger := log.NewNoopLogger().With("wal_generator", "wal_generator") - logger.Info("generating WAL (last height msg excluded)", "numBlocks", numBlocks) - - // ----------- - // COPY PASTE FROM node.go WITH A FEW MODIFICATIONS - // NOTE: we can't import node package because of circular dependency. - // NOTE: we don't do handshake so need to set state.Version.Consensus.App directly. - privValidatorKeyFile := config.PrivValidatorKeyFile() - privValidatorStateFile := config.PrivValidatorStateFile() - privValidator := privval.LoadOrGenFilePV(privValidatorKeyFile, privValidatorStateFile) - genDoc, err := types.GenesisDocFromFile(config.GenesisFile()) - if err != nil { - return errors.Wrap(err, "failed to read genesis file") - } - blockStoreDB := memdb.NewMemDB() - stateDB := blockStoreDB - state, err := sm.MakeGenesisState(genDoc) - if err != nil { - return errors.Wrap(err, "failed to make genesis state") - } - state.AppVersion = kvstore.AppVersion - sm.SaveState(stateDB, state) - blockStore := store.NewBlockStore(blockStoreDB) - - proxyApp := proxy.NewAppConns(proxy.NewLocalClientCreator(app)) - proxyApp.SetLogger(logger.With("module", "proxy")) - if err := proxyApp.Start(); err != nil { - return errors.Wrap(err, "failed to start proxy app connections") - } - defer proxyApp.Stop() - - evsw := events.NewEventSwitch() - evsw.SetLogger(logger.With("module", "events")) - if err := evsw.Start(); err != nil { - return errors.Wrap(err, "failed to start event bus") - } - defer evsw.Stop() - mempool := mock.Mempool{} - blockExec := sm.NewBlockExecutor(stateDB, log.NewNoopLogger(), proxyApp.Consensus(), mempool) - consensusState := NewConsensusState(config.Consensus, state.Copy(), blockExec, blockStore, mempool) - consensusState.SetLogger(logger) - consensusState.SetEventSwitch(evsw) - if privValidator != nil { - consensusState.SetPrivValidator(privValidator) - } - // END OF COPY PASTE - // ----------- - - // set consensus wal to buffered WAL, which will write all incoming msgs to buffer - numBlocksWritten := make(chan struct{}) - wal := newHeightStopWAL(logger, walm.NewWALWriter(wr, maxMsgSize), int64(numBlocks)+1, numBlocksWritten) - // See wal.go OnStart(). - // Since we separate the WALWriter from the WAL, we need to - // initialize ourself. - wal.WriteMetaSync(walm.MetaMessage{Height: 1}) - consensusState.wal = wal - - if err := consensusState.Start(); err != nil { - return errors.Wrap(err, "failed to start consensus state") - } - - select { - case <-numBlocksWritten: - consensusState.Stop() - return nil - case <-time.After(2 * time.Minute): - consensusState.Stop() - return fmt.Errorf("waited too long for tendermint to produce %d blocks (grep logs for `wal_generator`)", numBlocks) - } -} - -// WALWithNBlocks returns a WAL content with numBlocks. -func WALWithNBlocks(t *testing.T, numBlocks int) (data []byte, err error) { - t.Helper() - - var b bytes.Buffer - wr := bufio.NewWriter(&b) - - if err := WALGenerateNBlocks(t, wr, numBlocks); err != nil { - return []byte{}, err - } - - wr.Flush() - return b.Bytes(), nil -} - func randPort() int { // returns between base and base + spread base, spread := 20000, 20000 diff --git a/tm2/pkg/bft/consensus/wal_test.go b/tm2/pkg/bft/consensus/wal_test.go index b5d49dd6354..42651c0727d 100644 --- a/tm2/pkg/bft/consensus/wal_test.go +++ b/tm2/pkg/bft/consensus/wal_test.go @@ -1,6 +1,10 @@ package consensus import ( + "bufio" + "bytes" + "fmt" + "io" "path/filepath" "testing" "time" @@ -9,7 +13,18 @@ import ( "github.com/stretchr/testify/require" auto "github.com/gnolang/gno/tm2/pkg/autofile" + "github.com/gnolang/gno/tm2/pkg/bft/abci/example/kvstore" + "github.com/gnolang/gno/tm2/pkg/bft/appconn" + "github.com/gnolang/gno/tm2/pkg/bft/mempool/mock" + "github.com/gnolang/gno/tm2/pkg/bft/privval" + "github.com/gnolang/gno/tm2/pkg/bft/proxy" + sm "github.com/gnolang/gno/tm2/pkg/bft/state" + "github.com/gnolang/gno/tm2/pkg/bft/store" + "github.com/gnolang/gno/tm2/pkg/bft/types" walm "github.com/gnolang/gno/tm2/pkg/bft/wal" + "github.com/gnolang/gno/tm2/pkg/db/memdb" + "github.com/gnolang/gno/tm2/pkg/errors" + "github.com/gnolang/gno/tm2/pkg/events" "github.com/gnolang/gno/tm2/pkg/log" ) @@ -84,3 +99,105 @@ func TestWALTruncate(t *testing.T) { assert.True(t, ok, "expected message of type EventRoundState") assert.Equal(t, rs.Height, h+1, "wrong height") } + +// XXX: WALGenerateNBlocks and WALWithNBlocks were removed from wal_generator.go +// as they are unused. +// If you intend to use them, please move them to a separate package. + +// WALGenerateNBlocks generates a consensus WAL. It does this by spinning up a +// stripped down version of node (proxy app, event bus, consensus state) with a +// persistent kvstore application and special consensus wal instance +// (heightStopWAL) and waits until numBlocks are created. If the node fails to produce given numBlocks, it returns an error. +func WALGenerateNBlocks(t *testing.T, wr io.Writer, numBlocks int) (err error) { + t.Helper() + + config := getConfig(t) + + app := kvstore.NewPersistentKVStoreApplication(filepath.Join(config.DBDir(), "wal_generator")) + defer app.Close() + + logger := log.NewNoopLogger().With("wal_generator", "wal_generator") + logger.Info("generating WAL (last height msg excluded)", "numBlocks", numBlocks) + + // ----------- + // COPY PASTE FROM node.go WITH A FEW MODIFICATIONS + // NOTE: we can't import node package because of circular dependency. + // NOTE: we don't do handshake so need to set state.Version.Consensus.App directly. + privValidatorKeyFile := config.PrivValidatorKeyFile() + privValidatorStateFile := config.PrivValidatorStateFile() + privValidator := privval.LoadOrGenFilePV(privValidatorKeyFile, privValidatorStateFile) + genDoc, err := types.GenesisDocFromFile(config.GenesisFile()) + if err != nil { + return errors.Wrap(err, "failed to read genesis file") + } + blockStoreDB := memdb.NewMemDB() + stateDB := blockStoreDB + state, err := sm.MakeGenesisState(genDoc) + if err != nil { + return errors.Wrap(err, "failed to make genesis state") + } + state.AppVersion = kvstore.AppVersion + sm.SaveState(stateDB, state) + blockStore := store.NewBlockStore(blockStoreDB) + + proxyApp := appconn.NewAppConns(proxy.NewLocalClientCreator(app)) + proxyApp.SetLogger(logger.With("module", "proxy")) + if err := proxyApp.Start(); err != nil { + return errors.Wrap(err, "failed to start proxy app connections") + } + defer proxyApp.Stop() + + evsw := events.NewEventSwitch() + evsw.SetLogger(logger.With("module", "events")) + if err := evsw.Start(); err != nil { + return errors.Wrap(err, "failed to start event bus") + } + defer evsw.Stop() + mempool := mock.Mempool{} + blockExec := sm.NewBlockExecutor(stateDB, log.NewNoopLogger(), proxyApp.Consensus(), mempool) + consensusState := NewConsensusState(config.Consensus, state.Copy(), blockExec, blockStore, mempool) + consensusState.SetLogger(logger) + consensusState.SetEventSwitch(evsw) + if privValidator != nil { + consensusState.SetPrivValidator(privValidator) + } + // END OF COPY PASTE + // ----------- + + // set consensus wal to buffered WAL, which will write all incoming msgs to buffer + numBlocksWritten := make(chan struct{}) + wal := newHeightStopWAL(logger, walm.NewWALWriter(wr, maxMsgSize), int64(numBlocks)+1, numBlocksWritten) + // See wal.go OnStart(). + // Since we separate the WALWriter from the WAL, we need to + // initialize ourself. + wal.WriteMetaSync(walm.MetaMessage{Height: 1}) + consensusState.wal = wal + + if err := consensusState.Start(); err != nil { + return errors.Wrap(err, "failed to start consensus state") + } + + select { + case <-numBlocksWritten: + consensusState.Stop() + return nil + case <-time.After(2 * time.Minute): + consensusState.Stop() + return fmt.Errorf("waited too long for tendermint to produce %d blocks (grep logs for `wal_generator`)", numBlocks) + } +} + +// WALWithNBlocks returns a WAL content with numBlocks. +func WALWithNBlocks(t *testing.T, numBlocks int) (data []byte, err error) { + t.Helper() + + var b bytes.Buffer + wr := bufio.NewWriter(&b) + + if err := WALGenerateNBlocks(t, wr, numBlocks); err != nil { + return []byte{}, err + } + + wr.Flush() + return b.Bytes(), nil +} diff --git a/tm2/pkg/bft/mempool/clist_mempool.go b/tm2/pkg/bft/mempool/clist_mempool.go index e7a356d1ad3..47f3419222b 100644 --- a/tm2/pkg/bft/mempool/clist_mempool.go +++ b/tm2/pkg/bft/mempool/clist_mempool.go @@ -12,8 +12,8 @@ import ( auto "github.com/gnolang/gno/tm2/pkg/autofile" abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" + "github.com/gnolang/gno/tm2/pkg/bft/appconn" cfg "github.com/gnolang/gno/tm2/pkg/bft/mempool/config" - "github.com/gnolang/gno/tm2/pkg/bft/proxy" "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/clist" "github.com/gnolang/gno/tm2/pkg/errors" @@ -33,7 +33,7 @@ type CListMempool struct { config *cfg.MempoolConfig mtx sync.Mutex - proxyAppConn proxy.AppConnMempool + proxyAppConn appconn.Mempool txs *clist.CList // concurrent linked-list of good txs preCheck PreCheckFunc height int64 // the last block Update()'d to @@ -75,7 +75,7 @@ type CListMempoolOption func(*CListMempool) // NewCListMempool returns a new mempool with the given configuration and connection to an application. func NewCListMempool( config *cfg.MempoolConfig, - proxyAppConn proxy.AppConnMempool, + proxyAppConn appconn.Mempool, height int64, maxTxBytes int64, options ...CListMempoolOption, diff --git a/tm2/pkg/bft/node/node.go b/tm2/pkg/bft/node/node.go index a588f860f63..5fe47bb8893 100644 --- a/tm2/pkg/bft/node/node.go +++ b/tm2/pkg/bft/node/node.go @@ -12,6 +12,7 @@ import ( "sync" "time" + "github.com/gnolang/gno/tm2/pkg/bft/appconn" "github.com/gnolang/gno/tm2/pkg/bft/state/eventstore/file" "github.com/rs/cors" @@ -163,7 +164,7 @@ type Node struct { mempool mempl.Mempool consensusState *cs.ConsensusState // latest consensus state consensusReactor *cs.ConsensusReactor // for participating in the consensus - proxyApp proxy.AppConns // connection to the application + proxyApp appconn.AppConns // connection to the application rpcListeners []net.Listener // rpc servers txEventStore eventstore.TxEventStore eventStoreService *eventstore.Service @@ -186,8 +187,8 @@ func initDBs(config *cfg.Config, dbProvider DBProvider) (blockStore *store.Block return } -func createAndStartProxyAppConns(clientCreator proxy.ClientCreator, logger *slog.Logger) (proxy.AppConns, error) { - proxyApp := proxy.NewAppConns(clientCreator) +func createAndStartProxyAppConns(clientCreator proxy.ClientCreator, logger *slog.Logger) (appconn.AppConns, error) { + proxyApp := appconn.NewAppConns(clientCreator) proxyApp.SetLogger(logger.With("module", "proxy")) if err := proxyApp.Start(); err != nil { return nil, fmt.Errorf("error starting proxy app connections: %w", err) @@ -228,7 +229,7 @@ func createAndStartEventStoreService( } func doHandshake(stateDB dbm.DB, state sm.State, blockStore sm.BlockStore, - genDoc *types.GenesisDoc, evsw events.EventSwitch, proxyApp proxy.AppConns, consensusLogger *slog.Logger, + genDoc *types.GenesisDoc, evsw events.EventSwitch, proxyApp appconn.AppConns, consensusLogger *slog.Logger, ) error { handshaker := cs.NewHandshaker(stateDB, state, blockStore, genDoc) handshaker.SetLogger(consensusLogger) @@ -262,7 +263,7 @@ func onlyValidatorIsUs(state sm.State, privVal types.PrivValidator) bool { return privVal.GetPubKey().Address() == addr } -func createMempoolAndMempoolReactor(config *cfg.Config, proxyApp proxy.AppConns, +func createMempoolAndMempoolReactor(config *cfg.Config, proxyApp appconn.AppConns, state sm.State, logger *slog.Logger, ) (*mempl.Reactor, *mempl.CListMempool) { mempool := mempl.NewCListMempool( @@ -324,7 +325,7 @@ func createConsensusReactor(config *cfg.Config, return consensusReactor, consensusState } -func createTransport(config *cfg.Config, nodeInfo p2p.NodeInfo, nodeKey *p2p.NodeKey, proxyApp proxy.AppConns) (*p2p.MultiplexTransport, []p2p.PeerFilterFunc) { +func createTransport(config *cfg.Config, nodeInfo p2p.NodeInfo, nodeKey *p2p.NodeKey, proxyApp appconn.AppConns) (*p2p.MultiplexTransport, []p2p.PeerFilterFunc) { var ( mConnConfig = p2p.MConnConfig(config.P2P) transport = p2p.NewMultiplexTransport(nodeInfo, *nodeKey, mConnConfig) @@ -411,7 +412,7 @@ func createSwitch(config *cfg.Config, func NewNode(config *cfg.Config, privValidator types.PrivValidator, nodeKey *p2p.NodeKey, - clientCreator proxy.ClientCreator, + clientCreator appconn.ClientCreator, genesisDocProvider GenesisDocProvider, dbProvider DBProvider, logger *slog.Logger, @@ -588,6 +589,16 @@ func (n *Node) OnStart() error { time.Sleep(genTime.Sub(now)) } + // Set up the GLOBAL variables in rpc/core which refer to this node. + // This is done separately from startRPC(), as the values in rpc/core are used, + // for instance, to set up Local clients (rpc/client) which work without + // a network connection. + n.configureRPC() + if n.config.RPC.Unsafe { + rpccore.AddUnsafeRoutes() + } + rpccore.Start() + // Start the RPC server before the P2P server // so we can eg. receive txs for the first block if n.config.RPC.ListenAddress != "" { @@ -673,9 +684,9 @@ func (n *Node) Ready() <-chan struct{} { return n.firstBlockSignal } -// ConfigureRPC sets all variables in rpccore so they will serve +// configureRPC sets all variables in rpccore so they will serve // rpc calls from this node -func (n *Node) ConfigureRPC() { +func (n *Node) configureRPC() { rpccore.SetStateDB(n.stateDB) rpccore.SetBlockStore(n.blockStore) rpccore.SetConsensusState(n.consensusState) @@ -686,19 +697,13 @@ func (n *Node) ConfigureRPC() { rpccore.SetPubKey(pubKey) rpccore.SetGenesisDoc(n.genesisDoc) rpccore.SetProxyAppQuery(n.proxyApp.Query()) - rpccore.SetConsensusReactor(n.consensusReactor) + rpccore.SetGetFastSync(n.consensusReactor.FastSync) rpccore.SetLogger(n.Logger.With("module", "rpc")) rpccore.SetEventSwitch(n.evsw) rpccore.SetConfig(*n.config.RPC) } func (n *Node) startRPC() ([]net.Listener, error) { - n.ConfigureRPC() - if n.config.RPC.Unsafe { - rpccore.AddUnsafeRoutes() - } - rpccore.Start() - listenAddrs := splitAndTrimEmpty(n.config.RPC.ListenAddress, ",", " ") config := rpcserver.DefaultConfig() @@ -831,7 +836,7 @@ func (n *Node) GenesisDoc() *types.GenesisDoc { } // ProxyApp returns the Node's AppConns, representing its connections to the ABCI application. -func (n *Node) ProxyApp() proxy.AppConns { +func (n *Node) ProxyApp() appconn.AppConns { return n.proxyApp } diff --git a/tm2/pkg/bft/node/node_test.go b/tm2/pkg/bft/node/node_test.go index 1f410591510..c8e83b4963a 100644 --- a/tm2/pkg/bft/node/node_test.go +++ b/tm2/pkg/bft/node/node_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/gnolang/gno/tm2/pkg/bft/abci/example/kvstore" + "github.com/gnolang/gno/tm2/pkg/bft/appconn" cfg "github.com/gnolang/gno/tm2/pkg/bft/config" mempl "github.com/gnolang/gno/tm2/pkg/bft/mempool" "github.com/gnolang/gno/tm2/pkg/bft/privval" @@ -257,7 +258,7 @@ func TestCreateProposalBlock(t *testing.T) { config := cfg.ResetTestRoot("node_create_proposal") defer os.RemoveAll(config.RootDir) cc := proxy.NewLocalClientCreator(kvstore.NewKVStoreApplication()) - proxyApp := proxy.NewAppConns(cc) + proxyApp := appconn.NewAppConns(cc) err := proxyApp.Start() require.Nil(t, err) defer proxyApp.Stop() diff --git a/tm2/pkg/bft/rpc/client/localclient.go b/tm2/pkg/bft/rpc/client/localclient.go index cdd2cd31bb1..cbfaccb35b2 100644 --- a/tm2/pkg/bft/rpc/client/localclient.go +++ b/tm2/pkg/bft/rpc/client/localclient.go @@ -3,7 +3,6 @@ package client import ( "log/slog" - nm "github.com/gnolang/gno/tm2/pkg/bft/node" "github.com/gnolang/gno/tm2/pkg/bft/rpc/core" ctypes "github.com/gnolang/gno/tm2/pkg/bft/rpc/core/types" rpctypes "github.com/gnolang/gno/tm2/pkg/bft/rpc/lib/types" @@ -11,33 +10,33 @@ import ( "github.com/gnolang/gno/tm2/pkg/log" ) -/* -Local is a Client implementation that directly executes the rpc -functions on a given node, without going through HTTP or GRPC. - -This implementation is useful for: - -* Running tests against a node in-process without the overhead -of going through an http server -* Communication between an ABCI app and Tendermint core when they -are compiled in process. - -For real clients, you probably want to use client.HTTP. For more -powerful control during testing, you probably want the "client/mock" package. -*/ +// Local is a Client implementation that directly executes the rpc +// functions on a given node, without going through any network connection. +// +// As this connects directly to a Node instance, a Local client only works +// after the Node has been started. Note that the way this works is (alas) +// through the use of singletons in rpc/core. As a consequence, you may only +// have one active node at a time, and Local can only connect to that specific +// node. Keep this in mind for parallel tests, or attempting to simulate a +// network. +// +// This implementation is useful for: +// +// - Running tests against a node in-process without the overhead +// of going through an http server +// - Communication between an ABCI app and Tendermint core when they +// are compiled in process. +// +// For real clients, you probably want to use the [HTTP] client. For more +// powerful control during testing, you probably want the "client/mock" package. type Local struct { Logger *slog.Logger ctx *rpctypes.Context } -// NewLocal configures a client that calls the Node directly. -// -// Note that given how rpc/core works with package singletons, that -// you can only have one node per process. So make sure test cases -// don't run in parallel, or try to simulate an entire network in -// one process... -func NewLocal(node *nm.Node) *Local { - node.ConfigureRPC() +// NewLocal configures a client that calls the Node directly through rpc/core, +// without requiring a network connection. See [Local]. +func NewLocal() *Local { return &Local{ Logger: log.NewNoopLogger(), ctx: &rpctypes.Context{}, diff --git a/tm2/pkg/bft/rpc/client/rpc_test.go b/tm2/pkg/bft/rpc/client/rpc_test.go index e09ae8d4466..78cfdc7e4ee 100644 --- a/tm2/pkg/bft/rpc/client/rpc_test.go +++ b/tm2/pkg/bft/rpc/client/rpc_test.go @@ -23,7 +23,7 @@ func getHTTPClient() *client.HTTP { } func getLocalClient() *client.Local { - return client.NewLocal(node) + return client.NewLocal() } // GetClients returns a slice of clients for table-driven tests diff --git a/tm2/pkg/bft/rpc/core/consensus.go b/tm2/pkg/bft/rpc/core/consensus.go index a552252f8c0..e87e6b526d3 100644 --- a/tm2/pkg/bft/rpc/core/consensus.go +++ b/tm2/pkg/bft/rpc/core/consensus.go @@ -1,7 +1,7 @@ package core import ( - cm "github.com/gnolang/gno/tm2/pkg/bft/consensus" + cstypes "github.com/gnolang/gno/tm2/pkg/bft/consensus/types" ctypes "github.com/gnolang/gno/tm2/pkg/bft/rpc/core/types" rpctypes "github.com/gnolang/gno/tm2/pkg/bft/rpc/lib/types" sm "github.com/gnolang/gno/tm2/pkg/bft/state" @@ -217,11 +217,13 @@ func DumpConsensusState(ctx *rpctypes.Context) (*ctypes.ResultDumpConsensusState peers := p2pPeers.Peers().List() peerStates := make([]ctypes.PeerStateInfo, len(peers)) for i, peer := range peers { - peerState, ok := peer.Get(types.PeerStateKey).(*cm.PeerState) + peerState, ok := peer.Get(types.PeerStateKey).(interface { + GetExposed() cstypes.PeerStateExposed + }) if !ok { // peer does not have a state yet continue } - peerStateJSON, err := peerState.ToJSON() + peerStateJSON, err := peerState.GetExposed().ToJSON() if err != nil { return nil, err } diff --git a/tm2/pkg/bft/rpc/core/pipe.go b/tm2/pkg/bft/rpc/core/pipe.go index 01d558f0b2b..9493e7c5873 100644 --- a/tm2/pkg/bft/rpc/core/pipe.go +++ b/tm2/pkg/bft/rpc/core/pipe.go @@ -4,11 +4,10 @@ import ( "fmt" "log/slog" - "github.com/gnolang/gno/tm2/pkg/bft/consensus" + "github.com/gnolang/gno/tm2/pkg/bft/appconn" cnscfg "github.com/gnolang/gno/tm2/pkg/bft/consensus/config" cstypes "github.com/gnolang/gno/tm2/pkg/bft/consensus/types" mempl "github.com/gnolang/gno/tm2/pkg/bft/mempool" - "github.com/gnolang/gno/tm2/pkg/bft/proxy" cfg "github.com/gnolang/gno/tm2/pkg/bft/rpc/config" sm "github.com/gnolang/gno/tm2/pkg/bft/state" "github.com/gnolang/gno/tm2/pkg/bft/types" @@ -55,7 +54,7 @@ type peers interface { var ( // external, thread safe interfaces - proxyAppQuery proxy.AppConnQuery + proxyAppQuery appconn.Query // interfaces defined in types and above stateDB dbm.DB @@ -65,12 +64,12 @@ var ( p2pTransport transport // objects - pubKey crypto.PubKey - genDoc *types.GenesisDoc // cache the genesis structure - consensusReactor *consensus.ConsensusReactor - evsw events.EventSwitch - gTxDispatcher *txDispatcher - mempool mempl.Mempool + pubKey crypto.PubKey + genDoc *types.GenesisDoc // cache the genesis structure + evsw events.EventSwitch + gTxDispatcher *txDispatcher + mempool mempl.Mempool + getFastSync func() bool // avoids dependency on consensus pkg logger *slog.Logger @@ -109,12 +108,12 @@ func SetGenesisDoc(doc *types.GenesisDoc) { genDoc = doc } -func SetProxyAppQuery(appConn proxy.AppConnQuery) { +func SetProxyAppQuery(appConn appconn.Query) { proxyAppQuery = appConn } -func SetConsensusReactor(conR *consensus.ConsensusReactor) { - consensusReactor = conR +func SetGetFastSync(v func() bool) { + getFastSync = v } func SetLogger(l *slog.Logger) { diff --git a/tm2/pkg/bft/rpc/core/status.go b/tm2/pkg/bft/rpc/core/status.go index 5aaf0761ea1..9bc5f3ea6fc 100644 --- a/tm2/pkg/bft/rpc/core/status.go +++ b/tm2/pkg/bft/rpc/core/status.go @@ -74,7 +74,7 @@ import ( // ``` func Status(ctx *rpctypes.Context) (*ctypes.ResultStatus, error) { var latestHeight int64 - if consensusReactor.FastSync() { + if getFastSync() { latestHeight = blockStore.Height() } else { latestHeight = consensusState.GetLastHeight() @@ -106,7 +106,7 @@ func Status(ctx *rpctypes.Context) (*ctypes.ResultStatus, error) { LatestAppHash: latestAppHash, LatestBlockHeight: latestHeight, LatestBlockTime: latestBlockTime, - CatchingUp: consensusReactor.FastSync(), + CatchingUp: getFastSync(), }, ValidatorInfo: ctypes.ValidatorInfo{ Address: pubKey.Address(), diff --git a/tm2/pkg/bft/state/execution.go b/tm2/pkg/bft/state/execution.go index 00660646b6e..1f3e4c90333 100644 --- a/tm2/pkg/bft/state/execution.go +++ b/tm2/pkg/bft/state/execution.go @@ -6,9 +6,9 @@ import ( "github.com/gnolang/gno/tm2/pkg/amino" abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" + "github.com/gnolang/gno/tm2/pkg/bft/appconn" "github.com/gnolang/gno/tm2/pkg/bft/fail" mempl "github.com/gnolang/gno/tm2/pkg/bft/mempool" - "github.com/gnolang/gno/tm2/pkg/bft/proxy" "github.com/gnolang/gno/tm2/pkg/bft/types" typesver "github.com/gnolang/gno/tm2/pkg/bft/types/version" tmver "github.com/gnolang/gno/tm2/pkg/bft/version" @@ -28,7 +28,7 @@ type BlockExecutor struct { db dbm.DB // execute the app against this - proxyApp proxy.AppConnConsensus + proxyApp appconn.Consensus // events evsw events.EventSwitch @@ -44,7 +44,7 @@ type BlockExecutorOption func(executor *BlockExecutor) // NewBlockExecutor returns a new BlockExecutor with a NopEventBus. // Call SetEventBus to provide one. -func NewBlockExecutor(db dbm.DB, logger *slog.Logger, proxyApp proxy.AppConnConsensus, mempool mempl.Mempool, options ...BlockExecutorOption) *BlockExecutor { +func NewBlockExecutor(db dbm.DB, logger *slog.Logger, proxyApp appconn.Consensus, mempool mempl.Mempool, options ...BlockExecutorOption) *BlockExecutor { res := &BlockExecutor{ db: db, proxyApp: proxyApp, @@ -207,7 +207,7 @@ func (blockExec *BlockExecutor) Commit( // Returns a list of transaction results and updates to the validator set func execBlockOnProxyApp( logger *slog.Logger, - proxyAppConn proxy.AppConnConsensus, + proxyAppConn appconn.Consensus, block *types.Block, stateDB dbm.DB, ) (*ABCIResponses, error) { @@ -431,7 +431,7 @@ func fireEvents(evsw events.EventSwitch, block *types.Block, abciResponses *ABCI // ExecCommitBlock executes and commits a block on the proxyApp without validating or mutating the state. // It returns the application root hash (result of abci.Commit). func ExecCommitBlock( - appConnConsensus proxy.AppConnConsensus, + appConnConsensus appconn.Consensus, block *types.Block, logger *slog.Logger, stateDB dbm.DB, diff --git a/tm2/pkg/bft/state/execution_test.go b/tm2/pkg/bft/state/execution_test.go index 18dd8746840..008ec19be03 100644 --- a/tm2/pkg/bft/state/execution_test.go +++ b/tm2/pkg/bft/state/execution_test.go @@ -11,6 +11,7 @@ import ( "github.com/gnolang/gno/tm2/pkg/async" "github.com/gnolang/gno/tm2/pkg/bft/abci/example/kvstore" abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" + "github.com/gnolang/gno/tm2/pkg/bft/appconn" "github.com/gnolang/gno/tm2/pkg/bft/mempool/mock" "github.com/gnolang/gno/tm2/pkg/bft/proxy" sm "github.com/gnolang/gno/tm2/pkg/bft/state" @@ -32,7 +33,7 @@ func TestApplyBlock(t *testing.T) { t.Parallel() cc := proxy.NewLocalClientCreator(kvstore.NewKVStoreApplication()) - proxyApp := proxy.NewAppConns(cc) + proxyApp := appconn.NewAppConns(cc) err := proxyApp.Start() require.Nil(t, err) defer proxyApp.Stop() @@ -59,7 +60,7 @@ func TestBeginBlockValidators(t *testing.T) { app := &testApp{} cc := proxy.NewLocalClientCreator(app) - proxyApp := proxy.NewAppConns(cc) + proxyApp := appconn.NewAppConns(cc) err := proxyApp.Start() require.Nil(t, err) defer proxyApp.Stop() @@ -266,7 +267,7 @@ func TestEndBlockValidatorUpdates(t *testing.T) { app := &testApp{} cc := proxy.NewLocalClientCreator(app) - proxyApp := proxy.NewAppConns(cc) + proxyApp := appconn.NewAppConns(cc) err := proxyApp.Start() require.Nil(t, err) defer proxyApp.Stop() @@ -334,7 +335,7 @@ func TestEndBlockValidatorUpdatesResultingInEmptySet(t *testing.T) { app := &testApp{} cc := proxy.NewLocalClientCreator(app) - proxyApp := proxy.NewAppConns(cc) + proxyApp := appconn.NewAppConns(cc) err := proxyApp.Start() require.Nil(t, err) defer proxyApp.Stop() diff --git a/tm2/pkg/bft/state/helpers_test.go b/tm2/pkg/bft/state/helpers_test.go index b8b041635c6..0b8dba98221 100644 --- a/tm2/pkg/bft/state/helpers_test.go +++ b/tm2/pkg/bft/state/helpers_test.go @@ -5,6 +5,7 @@ import ( "fmt" abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" + "github.com/gnolang/gno/tm2/pkg/bft/appconn" "github.com/gnolang/gno/tm2/pkg/bft/proxy" sm "github.com/gnolang/gno/tm2/pkg/bft/state" "github.com/gnolang/gno/tm2/pkg/bft/types" @@ -19,10 +20,10 @@ type paramsChangeTestCase struct { params abci.ConsensusParams } -func newTestApp() proxy.AppConns { +func newTestApp() appconn.AppConns { app := &testApp{} cc := proxy.NewLocalClientCreator(app) - return proxy.NewAppConns(cc) + return appconn.NewAppConns(cc) } func makeAndCommitGoodBlock( diff --git a/tm2/pkg/bft/types/keys.go b/tm2/pkg/bft/types/keys.go index 941e82b65b0..dfd49ef9b42 100644 --- a/tm2/pkg/bft/types/keys.go +++ b/tm2/pkg/bft/types/keys.go @@ -1,6 +1,5 @@ package types // UNSTABLE -var ( - PeerStateKey = "ConsensusReactor.peerState" -) +// PeerStateKey allows to get the *consensus.PeerState from a [github.com/gnolang/gno/tm2/pkg/p2p.Peer]. +const PeerStateKey = "ConsensusReactor.peerState"