2018-06-20 17:35:30 -07:00
|
|
|
package node
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"net"
|
|
|
|
"net/http"
|
2018-09-21 17:50:06 -07:00
|
|
|
_ "net/http/pprof"
|
2018-12-22 05:58:27 +08:00
|
|
|
"os"
|
2018-09-21 17:50:06 -07:00
|
|
|
"strings"
|
2018-09-18 11:16:50 +02:00
|
|
|
"time"
|
2018-06-20 17:35:30 -07:00
|
|
|
|
2018-11-21 21:24:13 +04:00
|
|
|
"github.com/pkg/errors"
|
2018-07-10 15:49:48 +04:00
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
2018-06-20 17:35:30 -07:00
|
|
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
2018-11-14 15:47:41 +03:00
|
|
|
"github.com/rs/cors"
|
2018-06-20 17:35:30 -07:00
|
|
|
|
2018-11-21 21:24:13 +04:00
|
|
|
amino "github.com/tendermint/go-amino"
|
2018-09-21 17:50:06 -07:00
|
|
|
abci "github.com/tendermint/tendermint/abci/types"
|
blockchain: Reorg reactor (#3561)
* go routines in blockchain reactor
* Added reference to the go routine diagram
* Initial commit
* cleanup
* Undo testing_logger change, committed by mistake
* Fix the test loggers
* pulled some fsm code into pool.go
* added pool tests
* changes to the design
added block requests under peer
moved the request trigger in the reactor poolRoutine, triggered now by a ticker
in general moved everything required for making block requests smarter in the poolRoutine
added a simple map of heights to keep track of what will need to be requested next
added a few more tests
* send errors to FSM in a different channel than blocks
send errors (RemovePeer) from switch on a different channel than the
one receiving blocks
renamed channels
added more pool tests
* more pool tests
* lint errors
* more tests
* more tests
* switch fast sync to new implementation
* fixed data race in tests
* cleanup
* finished fsm tests
* address golangci comments :)
* address golangci comments :)
* Added timeout on next block needed to advance
* updating docs and cleanup
* fix issue in test from previous cleanup
* cleanup
* Added termination scenarios, tests and more cleanup
* small fixes to adr, comments and cleanup
* Fix bug in sendRequest()
If we tried to send a request to a peer not present in the switch, a
missing continue statement caused the request to be blackholed in a peer
that was removed and never retried.
While this bug was manifesting, the reactor kept asking for other
blocks that would be stored and never consumed. Added the number of
unconsumed blocks in the math for requesting blocks ahead of current
processing height so eventually there will be no more blocks requested
until the already received ones are consumed.
* remove bpPeer's didTimeout field
* Use distinct err codes for peer timeout and FSM timeouts
* Don't allow peers to update with lower height
* review comments from Ethan and Zarko
* some cleanup, renaming, comments
* Move block execution in separate goroutine
* Remove pool's numPending
* review comments
* fix lint, remove old blockchain reactor and duplicates in fsm tests
* small reorg around peer after review comments
* add the reactor spec
* verify block only once
* review comments
* change to int for max number of pending requests
* cleanup and godoc
* Add configuration flag fast sync version
* golangci fixes
* fix config template
* move both reactor versions under blockchain
* cleanup, golint, renaming stuff
* updated documentation, fixed more golint warnings
* integrate with behavior package
* sync with master
* gofmt
* add changelog_pending entry
* move to improvments
* suggestion to changelog entry
2019-07-23 10:58:52 +02:00
|
|
|
bcv0 "github.com/tendermint/tendermint/blockchain/v0"
|
|
|
|
bcv1 "github.com/tendermint/tendermint/blockchain/v1"
|
2018-06-20 17:35:30 -07:00
|
|
|
cfg "github.com/tendermint/tendermint/config"
|
2019-04-26 08:05:39 -04:00
|
|
|
"github.com/tendermint/tendermint/consensus"
|
2018-06-20 17:35:30 -07:00
|
|
|
cs "github.com/tendermint/tendermint/consensus"
|
2019-08-05 17:09:10 +02:00
|
|
|
"github.com/tendermint/tendermint/crypto"
|
2018-06-20 17:35:30 -07:00
|
|
|
"github.com/tendermint/tendermint/evidence"
|
2018-09-21 17:50:06 -07:00
|
|
|
cmn "github.com/tendermint/tendermint/libs/common"
|
|
|
|
"github.com/tendermint/tendermint/libs/log"
|
2019-03-11 22:45:58 +04:00
|
|
|
tmpubsub "github.com/tendermint/tendermint/libs/pubsub"
|
2018-06-20 17:35:30 -07:00
|
|
|
mempl "github.com/tendermint/tendermint/mempool"
|
|
|
|
"github.com/tendermint/tendermint/p2p"
|
|
|
|
"github.com/tendermint/tendermint/p2p/pex"
|
|
|
|
"github.com/tendermint/tendermint/privval"
|
|
|
|
"github.com/tendermint/tendermint/proxy"
|
|
|
|
rpccore "github.com/tendermint/tendermint/rpc/core"
|
|
|
|
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
|
|
|
grpccore "github.com/tendermint/tendermint/rpc/grpc"
|
2019-01-28 14:13:17 +02:00
|
|
|
rpcserver "github.com/tendermint/tendermint/rpc/lib/server"
|
2018-06-20 17:35:30 -07:00
|
|
|
sm "github.com/tendermint/tendermint/state"
|
|
|
|
"github.com/tendermint/tendermint/state/txindex"
|
|
|
|
"github.com/tendermint/tendermint/state/txindex/kv"
|
|
|
|
"github.com/tendermint/tendermint/state/txindex/null"
|
blockchain: Reorg reactor (#3561)
* go routines in blockchain reactor
* Added reference to the go routine diagram
* Initial commit
* cleanup
* Undo testing_logger change, committed by mistake
* Fix the test loggers
* pulled some fsm code into pool.go
* added pool tests
* changes to the design
added block requests under peer
moved the request trigger in the reactor poolRoutine, triggered now by a ticker
in general moved everything required for making block requests smarter in the poolRoutine
added a simple map of heights to keep track of what will need to be requested next
added a few more tests
* send errors to FSM in a different channel than blocks
send errors (RemovePeer) from switch on a different channel than the
one receiving blocks
renamed channels
added more pool tests
* more pool tests
* lint errors
* more tests
* more tests
* switch fast sync to new implementation
* fixed data race in tests
* cleanup
* finished fsm tests
* address golangci comments :)
* address golangci comments :)
* Added timeout on next block needed to advance
* updating docs and cleanup
* fix issue in test from previous cleanup
* cleanup
* Added termination scenarios, tests and more cleanup
* small fixes to adr, comments and cleanup
* Fix bug in sendRequest()
If we tried to send a request to a peer not present in the switch, a
missing continue statement caused the request to be blackholed in a peer
that was removed and never retried.
While this bug was manifesting, the reactor kept asking for other
blocks that would be stored and never consumed. Added the number of
unconsumed blocks in the math for requesting blocks ahead of current
processing height so eventually there will be no more blocks requested
until the already received ones are consumed.
* remove bpPeer's didTimeout field
* Use distinct err codes for peer timeout and FSM timeouts
* Don't allow peers to update with lower height
* review comments from Ethan and Zarko
* some cleanup, renaming, comments
* Move block execution in separate goroutine
* Remove pool's numPending
* review comments
* fix lint, remove old blockchain reactor and duplicates in fsm tests
* small reorg around peer after review comments
* add the reactor spec
* verify block only once
* review comments
* change to int for max number of pending requests
* cleanup and godoc
* Add configuration flag fast sync version
* golangci fixes
* fix config template
* move both reactor versions under blockchain
* cleanup, golint, renaming stuff
* updated documentation, fixed more golint warnings
* integrate with behavior package
* sync with master
* gofmt
* add changelog_pending entry
* move to improvments
* suggestion to changelog entry
2019-07-23 10:58:52 +02:00
|
|
|
"github.com/tendermint/tendermint/store"
|
2018-06-20 17:35:30 -07:00
|
|
|
"github.com/tendermint/tendermint/types"
|
2018-09-18 11:16:50 +02:00
|
|
|
tmtime "github.com/tendermint/tendermint/types/time"
|
2018-06-20 17:35:30 -07:00
|
|
|
"github.com/tendermint/tendermint/version"
|
2019-07-31 11:34:17 +02:00
|
|
|
dbm "github.com/tendermint/tm-db"
|
2018-06-20 17:35:30 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// DBContext specifies config information for loading a new DB.
|
|
|
|
type DBContext struct {
|
|
|
|
ID string
|
|
|
|
Config *cfg.Config
|
|
|
|
}
|
|
|
|
|
|
|
|
// DBProvider takes a DBContext and returns an instantiated DB.
|
|
|
|
type DBProvider func(*DBContext) (dbm.DB, error)
|
|
|
|
|
|
|
|
// DefaultDBProvider returns a database using the DBBackend and DBDir
|
|
|
|
// specified in the ctx.Config.
|
|
|
|
func DefaultDBProvider(ctx *DBContext) (dbm.DB, error) {
|
|
|
|
dbType := dbm.DBBackendType(ctx.Config.DBBackend)
|
|
|
|
return dbm.NewDB(ctx.ID, dbType, ctx.Config.DBDir()), nil
|
|
|
|
}
|
|
|
|
|
2019-05-30 18:40:17 -04:00
|
|
|
// GenesisDocProvider returns a GenesisDoc.
|
|
|
|
// It allows the GenesisDoc to be pulled from sources other than the
|
|
|
|
// filesystem, for instance from a distributed key-value store cluster.
|
|
|
|
type GenesisDocProvider func() (*types.GenesisDoc, error)
|
|
|
|
|
|
|
|
// DefaultGenesisDocProviderFunc returns a GenesisDocProvider that loads
|
|
|
|
// the GenesisDoc from the config.GenesisFile() on the filesystem.
|
|
|
|
func DefaultGenesisDocProviderFunc(config *cfg.Config) GenesisDocProvider {
|
|
|
|
return func() (*types.GenesisDoc, error) {
|
|
|
|
return types.GenesisDocFromFile(config.GenesisFile())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-20 17:35:30 -07:00
|
|
|
// NodeProvider takes a config and a logger and returns a ready to go Node.
|
|
|
|
type NodeProvider func(*cfg.Config, log.Logger) (*Node, error)
|
|
|
|
|
|
|
|
// DefaultNewNode returns a Tendermint node with default settings for the
|
|
|
|
// PrivValidator, ClientCreator, GenesisDoc, and DBProvider.
|
|
|
|
// It implements NodeProvider.
|
|
|
|
func DefaultNewNode(config *cfg.Config, logger log.Logger) (*Node, error) {
|
2018-08-15 16:29:45 +08:00
|
|
|
// Generate node PrivKey
|
|
|
|
nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile())
|
|
|
|
if err != nil {
|
2018-08-08 16:03:58 +04:00
|
|
|
return nil, err
|
2018-08-15 16:29:45 +08:00
|
|
|
}
|
2018-12-22 05:58:27 +08:00
|
|
|
|
|
|
|
// Convert old PrivValidator if it exists.
|
|
|
|
oldPrivVal := config.OldPrivValidatorFile()
|
|
|
|
newPrivValKey := config.PrivValidatorKeyFile()
|
|
|
|
newPrivValState := config.PrivValidatorStateFile()
|
|
|
|
if _, err := os.Stat(oldPrivVal); !os.IsNotExist(err) {
|
|
|
|
oldPV, err := privval.LoadOldFilePV(oldPrivVal)
|
|
|
|
if err != nil {
|
2019-04-26 08:05:39 -04:00
|
|
|
return nil, fmt.Errorf("error reading OldPrivValidator from %v: %v\n", oldPrivVal, err)
|
2018-12-22 05:58:27 +08:00
|
|
|
}
|
|
|
|
logger.Info("Upgrading PrivValidator file",
|
|
|
|
"old", oldPrivVal,
|
|
|
|
"newKey", newPrivValKey,
|
|
|
|
"newState", newPrivValState,
|
|
|
|
)
|
|
|
|
oldPV.Upgrade(newPrivValKey, newPrivValState)
|
|
|
|
}
|
|
|
|
|
2018-06-20 17:35:30 -07:00
|
|
|
return NewNode(config,
|
2018-12-22 05:58:27 +08:00
|
|
|
privval.LoadOrGenFilePV(newPrivValKey, newPrivValState),
|
2018-08-15 16:29:45 +08:00
|
|
|
nodeKey,
|
2018-06-20 17:35:30 -07:00
|
|
|
proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir()),
|
2019-05-30 18:40:17 -04:00
|
|
|
DefaultGenesisDocProviderFunc(config),
|
2018-06-20 17:35:30 -07:00
|
|
|
DefaultDBProvider,
|
2018-07-24 15:44:01 +04:00
|
|
|
DefaultMetricsProvider(config.Instrumentation),
|
2018-06-20 17:35:30 -07:00
|
|
|
logger,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
// MetricsProvider returns a consensus, p2p and mempool Metrics.
|
2019-01-15 21:16:33 +04:00
|
|
|
type MetricsProvider func(chainID string) (*cs.Metrics, *p2p.Metrics, *mempl.Metrics, *sm.Metrics)
|
2018-06-20 17:35:30 -07:00
|
|
|
|
2018-07-24 15:44:01 +04:00
|
|
|
// DefaultMetricsProvider returns Metrics build using Prometheus client library
|
|
|
|
// if Prometheus is enabled. Otherwise, it returns no-op Metrics.
|
|
|
|
func DefaultMetricsProvider(config *cfg.InstrumentationConfig) MetricsProvider {
|
2019-01-15 21:16:33 +04:00
|
|
|
return func(chainID string) (*cs.Metrics, *p2p.Metrics, *mempl.Metrics, *sm.Metrics) {
|
2018-07-24 15:44:01 +04:00
|
|
|
if config.Prometheus {
|
2019-01-15 21:16:33 +04:00
|
|
|
return cs.PrometheusMetrics(config.Namespace, "chain_id", chainID),
|
|
|
|
p2p.PrometheusMetrics(config.Namespace, "chain_id", chainID),
|
|
|
|
mempl.PrometheusMetrics(config.Namespace, "chain_id", chainID),
|
|
|
|
sm.PrometheusMetrics(config.Namespace, "chain_id", chainID)
|
2018-07-24 15:44:01 +04:00
|
|
|
}
|
2018-10-10 09:27:43 -07:00
|
|
|
return cs.NopMetrics(), p2p.NopMetrics(), mempl.NopMetrics(), sm.NopMetrics()
|
2018-07-24 15:44:01 +04:00
|
|
|
}
|
2018-06-20 17:35:30 -07:00
|
|
|
}
|
|
|
|
|
2019-07-03 17:17:59 +04:00
|
|
|
// Option sets a parameter for the node.
|
|
|
|
type Option func(*Node)
|
|
|
|
|
2019-07-30 17:08:11 +04:00
|
|
|
// CustomReactors allows you to add custom reactors (name -> p2p.Reactor) to
|
|
|
|
// the node's Switch.
|
|
|
|
//
|
|
|
|
// WARNING: using any name from the below list of the existing reactors will
|
|
|
|
// result in replacing it with the custom one.
|
|
|
|
//
|
|
|
|
// - MEMPOOL
|
|
|
|
// - BLOCKCHAIN
|
|
|
|
// - CONSENSUS
|
|
|
|
// - EVIDENCE
|
|
|
|
// - PEX
|
2019-07-03 17:17:59 +04:00
|
|
|
func CustomReactors(reactors map[string]p2p.Reactor) Option {
|
|
|
|
return func(n *Node) {
|
|
|
|
for name, reactor := range reactors {
|
2019-07-30 17:08:11 +04:00
|
|
|
if existingReactor := n.sw.Reactor(name); existingReactor != nil {
|
|
|
|
n.sw.Logger.Info("Replacing existing reactor with a custom one",
|
|
|
|
"name", name, "existing", existingReactor, "custom", reactor)
|
|
|
|
n.sw.RemoveReactor(name, existingReactor)
|
|
|
|
}
|
|
|
|
n.sw.AddReactor(name, reactor)
|
2019-07-03 17:17:59 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-20 17:35:30 -07:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// Node is the highest level interface to a full Tendermint node.
|
|
|
|
// It includes all configuration information and running services.
|
|
|
|
type Node struct {
|
|
|
|
cmn.BaseService
|
|
|
|
|
|
|
|
// config
|
|
|
|
config *cfg.Config
|
|
|
|
genesisDoc *types.GenesisDoc // initial validator set
|
|
|
|
privValidator types.PrivValidator // local node's validator key
|
|
|
|
|
|
|
|
// network
|
2018-09-18 22:14:40 +02:00
|
|
|
transport *p2p.MultiplexTransport
|
|
|
|
sw *p2p.Switch // p2p connections
|
|
|
|
addrBook pex.AddrBook // known peers
|
|
|
|
nodeInfo p2p.NodeInfo
|
|
|
|
nodeKey *p2p.NodeKey // our node privkey
|
|
|
|
isListening bool
|
2018-06-20 17:35:30 -07:00
|
|
|
|
|
|
|
// services
|
|
|
|
eventBus *types.EventBus // pub/sub for services
|
|
|
|
stateDB dbm.DB
|
blockchain: Reorg reactor (#3561)
* go routines in blockchain reactor
* Added reference to the go routine diagram
* Initial commit
* cleanup
* Undo testing_logger change, committed by mistake
* Fix the test loggers
* pulled some fsm code into pool.go
* added pool tests
* changes to the design
added block requests under peer
moved the request trigger in the reactor poolRoutine, triggered now by a ticker
in general moved everything required for making block requests smarter in the poolRoutine
added a simple map of heights to keep track of what will need to be requested next
added a few more tests
* send errors to FSM in a different channel than blocks
send errors (RemovePeer) from switch on a different channel than the
one receiving blocks
renamed channels
added more pool tests
* more pool tests
* lint errors
* more tests
* more tests
* switch fast sync to new implementation
* fixed data race in tests
* cleanup
* finished fsm tests
* address golangci comments :)
* address golangci comments :)
* Added timeout on next block needed to advance
* updating docs and cleanup
* fix issue in test from previous cleanup
* cleanup
* Added termination scenarios, tests and more cleanup
* small fixes to adr, comments and cleanup
* Fix bug in sendRequest()
If we tried to send a request to a peer not present in the switch, a
missing continue statement caused the request to be blackholed in a peer
that was removed and never retried.
While this bug was manifesting, the reactor kept asking for other
blocks that would be stored and never consumed. Added the number of
unconsumed blocks in the math for requesting blocks ahead of current
processing height so eventually there will be no more blocks requested
until the already received ones are consumed.
* remove bpPeer's didTimeout field
* Use distinct err codes for peer timeout and FSM timeouts
* Don't allow peers to update with lower height
* review comments from Ethan and Zarko
* some cleanup, renaming, comments
* Move block execution in separate goroutine
* Remove pool's numPending
* review comments
* fix lint, remove old blockchain reactor and duplicates in fsm tests
* small reorg around peer after review comments
* add the reactor spec
* verify block only once
* review comments
* change to int for max number of pending requests
* cleanup and godoc
* Add configuration flag fast sync version
* golangci fixes
* fix config template
* move both reactor versions under blockchain
* cleanup, golint, renaming stuff
* updated documentation, fixed more golint warnings
* integrate with behavior package
* sync with master
* gofmt
* add changelog_pending entry
* move to improvments
* suggestion to changelog entry
2019-07-23 10:58:52 +02:00
|
|
|
blockStore *store.BlockStore // store the blockchain to disk
|
|
|
|
bcReactor p2p.Reactor // for fast-syncing
|
|
|
|
mempoolReactor *mempl.Reactor // for gossipping transactions
|
2019-05-04 10:41:31 +04:00
|
|
|
mempool mempl.Mempool
|
2018-06-20 17:35:30 -07:00
|
|
|
consensusState *cs.ConsensusState // latest consensus state
|
|
|
|
consensusReactor *cs.ConsensusReactor // for participating in the consensus
|
2019-04-26 08:05:39 -04:00
|
|
|
pexReactor *pex.PEXReactor // for exchanging peer addresses
|
2018-06-20 17:35:30 -07:00
|
|
|
evidencePool *evidence.EvidencePool // tracking evidence
|
|
|
|
proxyApp proxy.AppConns // connection to the application
|
|
|
|
rpcListeners []net.Listener // rpc servers
|
|
|
|
txIndexer txindex.TxIndexer
|
|
|
|
indexerService *txindex.IndexerService
|
|
|
|
prometheusSrv *http.Server
|
|
|
|
}
|
|
|
|
|
blockchain: Reorg reactor (#3561)
* go routines in blockchain reactor
* Added reference to the go routine diagram
* Initial commit
* cleanup
* Undo testing_logger change, committed by mistake
* Fix the test loggers
* pulled some fsm code into pool.go
* added pool tests
* changes to the design
added block requests under peer
moved the request trigger in the reactor poolRoutine, triggered now by a ticker
in general moved everything required for making block requests smarter in the poolRoutine
added a simple map of heights to keep track of what will need to be requested next
added a few more tests
* send errors to FSM in a different channel than blocks
send errors (RemovePeer) from switch on a different channel than the
one receiving blocks
renamed channels
added more pool tests
* more pool tests
* lint errors
* more tests
* more tests
* switch fast sync to new implementation
* fixed data race in tests
* cleanup
* finished fsm tests
* address golangci comments :)
* address golangci comments :)
* Added timeout on next block needed to advance
* updating docs and cleanup
* fix issue in test from previous cleanup
* cleanup
* Added termination scenarios, tests and more cleanup
* small fixes to adr, comments and cleanup
* Fix bug in sendRequest()
If we tried to send a request to a peer not present in the switch, a
missing continue statement caused the request to be blackholed in a peer
that was removed and never retried.
While this bug was manifesting, the reactor kept asking for other
blocks that would be stored and never consumed. Added the number of
unconsumed blocks in the math for requesting blocks ahead of current
processing height so eventually there will be no more blocks requested
until the already received ones are consumed.
* remove bpPeer's didTimeout field
* Use distinct err codes for peer timeout and FSM timeouts
* Don't allow peers to update with lower height
* review comments from Ethan and Zarko
* some cleanup, renaming, comments
* Move block execution in separate goroutine
* Remove pool's numPending
* review comments
* fix lint, remove old blockchain reactor and duplicates in fsm tests
* small reorg around peer after review comments
* add the reactor spec
* verify block only once
* review comments
* change to int for max number of pending requests
* cleanup and godoc
* Add configuration flag fast sync version
* golangci fixes
* fix config template
* move both reactor versions under blockchain
* cleanup, golint, renaming stuff
* updated documentation, fixed more golint warnings
* integrate with behavior package
* sync with master
* gofmt
* add changelog_pending entry
* move to improvments
* suggestion to changelog entry
2019-07-23 10:58:52 +02:00
|
|
|
func initDBs(config *cfg.Config, dbProvider DBProvider) (blockStore *store.BlockStore, stateDB dbm.DB, err error) {
|
2019-04-26 08:05:39 -04:00
|
|
|
var blockStoreDB dbm.DB
|
|
|
|
blockStoreDB, err = dbProvider(&DBContext{"blockstore", config})
|
2018-06-20 17:35:30 -07:00
|
|
|
if err != nil {
|
2019-04-26 08:05:39 -04:00
|
|
|
return
|
2018-06-20 17:35:30 -07:00
|
|
|
}
|
blockchain: Reorg reactor (#3561)
* go routines in blockchain reactor
* Added reference to the go routine diagram
* Initial commit
* cleanup
* Undo testing_logger change, committed by mistake
* Fix the test loggers
* pulled some fsm code into pool.go
* added pool tests
* changes to the design
added block requests under peer
moved the request trigger in the reactor poolRoutine, triggered now by a ticker
in general moved everything required for making block requests smarter in the poolRoutine
added a simple map of heights to keep track of what will need to be requested next
added a few more tests
* send errors to FSM in a different channel than blocks
send errors (RemovePeer) from switch on a different channel than the
one receiving blocks
renamed channels
added more pool tests
* more pool tests
* lint errors
* more tests
* more tests
* switch fast sync to new implementation
* fixed data race in tests
* cleanup
* finished fsm tests
* address golangci comments :)
* address golangci comments :)
* Added timeout on next block needed to advance
* updating docs and cleanup
* fix issue in test from previous cleanup
* cleanup
* Added termination scenarios, tests and more cleanup
* small fixes to adr, comments and cleanup
* Fix bug in sendRequest()
If we tried to send a request to a peer not present in the switch, a
missing continue statement caused the request to be blackholed in a peer
that was removed and never retried.
While this bug was manifesting, the reactor kept asking for other
blocks that would be stored and never consumed. Added the number of
unconsumed blocks in the math for requesting blocks ahead of current
processing height so eventually there will be no more blocks requested
until the already received ones are consumed.
* remove bpPeer's didTimeout field
* Use distinct err codes for peer timeout and FSM timeouts
* Don't allow peers to update with lower height
* review comments from Ethan and Zarko
* some cleanup, renaming, comments
* Move block execution in separate goroutine
* Remove pool's numPending
* review comments
* fix lint, remove old blockchain reactor and duplicates in fsm tests
* small reorg around peer after review comments
* add the reactor spec
* verify block only once
* review comments
* change to int for max number of pending requests
* cleanup and godoc
* Add configuration flag fast sync version
* golangci fixes
* fix config template
* move both reactor versions under blockchain
* cleanup, golint, renaming stuff
* updated documentation, fixed more golint warnings
* integrate with behavior package
* sync with master
* gofmt
* add changelog_pending entry
* move to improvments
* suggestion to changelog entry
2019-07-23 10:58:52 +02:00
|
|
|
blockStore = store.NewBlockStore(blockStoreDB)
|
2018-06-20 17:35:30 -07:00
|
|
|
|
2019-04-26 08:05:39 -04:00
|
|
|
stateDB, err = dbProvider(&DBContext{"state", config})
|
2018-06-20 17:35:30 -07:00
|
|
|
if err != nil {
|
2019-04-26 08:05:39 -04:00
|
|
|
return
|
2018-06-20 17:35:30 -07:00
|
|
|
}
|
|
|
|
|
2019-04-26 08:05:39 -04:00
|
|
|
return
|
|
|
|
}
|
2018-06-20 17:35:30 -07:00
|
|
|
|
2019-04-26 08:05:39 -04:00
|
|
|
func createAndStartProxyAppConns(clientCreator proxy.ClientCreator, logger log.Logger) (proxy.AppConns, error) {
|
2018-09-19 09:35:09 -04:00
|
|
|
proxyApp := proxy.NewAppConns(clientCreator)
|
2018-06-20 17:35:30 -07:00
|
|
|
proxyApp.SetLogger(logger.With("module", "proxy"))
|
|
|
|
if err := proxyApp.Start(); err != nil {
|
2019-04-26 08:05:39 -04:00
|
|
|
return nil, fmt.Errorf("error starting proxy app connections: %v", err)
|
2018-06-20 17:35:30 -07:00
|
|
|
}
|
2019-04-26 08:05:39 -04:00
|
|
|
return proxyApp, nil
|
|
|
|
}
|
2018-06-20 17:35:30 -07:00
|
|
|
|
2019-04-26 08:05:39 -04:00
|
|
|
func createAndStartEventBus(logger log.Logger) (*types.EventBus, error) {
|
2019-01-28 15:36:35 +08:00
|
|
|
eventBus := types.NewEventBus()
|
|
|
|
eventBus.SetLogger(logger.With("module", "events"))
|
2019-04-26 08:05:39 -04:00
|
|
|
if err := eventBus.Start(); err != nil {
|
2019-01-28 15:36:35 +08:00
|
|
|
return nil, err
|
|
|
|
}
|
2019-04-26 08:05:39 -04:00
|
|
|
return eventBus, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func createAndStartIndexerService(config *cfg.Config, dbProvider DBProvider,
|
|
|
|
eventBus *types.EventBus, logger log.Logger) (*txindex.IndexerService, txindex.TxIndexer, error) {
|
2019-01-28 15:36:35 +08:00
|
|
|
|
|
|
|
var txIndexer txindex.TxIndexer
|
|
|
|
switch config.TxIndex.Indexer {
|
|
|
|
case "kv":
|
|
|
|
store, err := dbProvider(&DBContext{"tx_index", config})
|
|
|
|
if err != nil {
|
2019-04-26 08:05:39 -04:00
|
|
|
return nil, nil, err
|
2019-01-28 15:36:35 +08:00
|
|
|
}
|
2019-08-02 08:53:52 +02:00
|
|
|
switch {
|
|
|
|
case config.TxIndex.IndexTags != "":
|
2019-01-28 15:36:35 +08:00
|
|
|
txIndexer = kv.NewTxIndex(store, kv.IndexTags(splitAndTrimEmpty(config.TxIndex.IndexTags, ",", " ")))
|
2019-08-02 08:53:52 +02:00
|
|
|
case config.TxIndex.IndexAllTags:
|
2019-01-28 15:36:35 +08:00
|
|
|
txIndexer = kv.NewTxIndex(store, kv.IndexAllTags())
|
2019-08-02 08:53:52 +02:00
|
|
|
default:
|
2019-01-28 15:36:35 +08:00
|
|
|
txIndexer = kv.NewTxIndex(store)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
txIndexer = &null.TxIndex{}
|
|
|
|
}
|
|
|
|
|
|
|
|
indexerService := txindex.NewIndexerService(txIndexer, eventBus)
|
|
|
|
indexerService.SetLogger(logger.With("module", "txindex"))
|
2019-04-26 08:05:39 -04:00
|
|
|
if err := indexerService.Start(); err != nil {
|
|
|
|
return nil, nil, err
|
2019-01-28 15:36:35 +08:00
|
|
|
}
|
2019-04-26 08:05:39 -04:00
|
|
|
return indexerService, txIndexer, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func doHandshake(stateDB dbm.DB, state sm.State, blockStore sm.BlockStore,
|
2019-09-30 20:12:51 -04:00
|
|
|
genDoc *types.GenesisDoc, eventBus types.BlockEventPublisher, proxyApp proxy.AppConns, consensusLogger log.Logger) error {
|
2019-01-28 15:36:35 +08:00
|
|
|
|
2018-09-19 09:35:09 -04:00
|
|
|
handshaker := cs.NewHandshaker(stateDB, state, blockStore, genDoc)
|
|
|
|
handshaker.SetLogger(consensusLogger)
|
2019-01-28 15:36:35 +08:00
|
|
|
handshaker.SetEventBus(eventBus)
|
2018-09-19 09:35:09 -04:00
|
|
|
if err := handshaker.Handshake(proxyApp); err != nil {
|
2019-04-26 08:05:39 -04:00
|
|
|
return fmt.Errorf("error during handshake: %v", err)
|
2018-09-19 09:35:09 -04:00
|
|
|
}
|
2019-04-26 08:05:39 -04:00
|
|
|
return nil
|
|
|
|
}
|
2018-09-19 09:35:09 -04:00
|
|
|
|
2019-08-05 17:09:10 +02:00
|
|
|
func logNodeStartupInfo(state sm.State, pubKey crypto.PubKey, logger, consensusLogger log.Logger) {
|
2018-12-04 08:30:29 -05:00
|
|
|
// Log the version info.
|
|
|
|
logger.Info("Version info",
|
|
|
|
"software", version.TMCoreSemVer,
|
|
|
|
"block", version.BlockProtocol,
|
|
|
|
"p2p", version.P2PProtocol,
|
|
|
|
)
|
|
|
|
|
|
|
|
// If the state and software differ in block version, at least log it.
|
2018-10-17 15:30:53 -04:00
|
|
|
if state.Version.Consensus.Block != version.BlockProtocol {
|
2018-12-04 08:30:29 -05:00
|
|
|
logger.Info("Software and state have different block protocols",
|
|
|
|
"software", version.BlockProtocol,
|
|
|
|
"state", state.Version.Consensus.Block,
|
2018-10-17 15:30:53 -04:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2018-12-22 06:36:45 +01:00
|
|
|
addr := pubKey.Address()
|
2018-06-20 17:35:30 -07:00
|
|
|
// Log whether this node is a validator or an observer
|
2018-12-22 06:36:45 +01:00
|
|
|
if state.Validators.HasAddress(addr) {
|
|
|
|
consensusLogger.Info("This node is a validator", "addr", addr, "pubKey", pubKey)
|
2018-06-20 17:35:30 -07:00
|
|
|
} else {
|
2018-12-22 06:36:45 +01:00
|
|
|
consensusLogger.Info("This node is not a validator", "addr", addr, "pubKey", pubKey)
|
2018-06-20 17:35:30 -07:00
|
|
|
}
|
2019-04-26 08:05:39 -04:00
|
|
|
}
|
2018-06-20 17:35:30 -07:00
|
|
|
|
2019-04-26 08:05:39 -04:00
|
|
|
func onlyValidatorIsUs(state sm.State, privVal types.PrivValidator) bool {
|
|
|
|
if state.Validators.Size() > 1 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
addr, _ := state.Validators.GetByIndex(0)
|
|
|
|
return bytes.Equal(privVal.GetPubKey().Address(), addr)
|
|
|
|
}
|
|
|
|
|
|
|
|
func createMempoolAndMempoolReactor(config *cfg.Config, proxyApp proxy.AppConns,
|
2019-05-04 10:41:31 +04:00
|
|
|
state sm.State, memplMetrics *mempl.Metrics, logger log.Logger) (*mempl.Reactor, *mempl.CListMempool) {
|
2018-06-20 17:35:30 -07:00
|
|
|
|
2019-05-04 10:41:31 +04:00
|
|
|
mempool := mempl.NewCListMempool(
|
2018-06-20 17:35:30 -07:00
|
|
|
config.Mempool,
|
|
|
|
proxyApp.Mempool(),
|
|
|
|
state.LastBlockHeight,
|
|
|
|
mempl.WithMetrics(memplMetrics),
|
2018-11-11 16:09:33 +01:00
|
|
|
mempl.WithPreCheck(sm.TxPreCheck(state)),
|
|
|
|
mempl.WithPostCheck(sm.TxPostCheck(state)),
|
2018-06-20 17:35:30 -07:00
|
|
|
)
|
max-bytes PR follow-up (#2318)
* ReapMaxTxs: return all txs if max is negative
this mirrors ReapMaxBytes behavior
See https://github.com/tendermint/tendermint/pull/2184#discussion_r214439950
* increase MaxAminoOverheadForBlock
tested with:
```
func TestMaxAminoOverheadForBlock(t *testing.T) {
maxChainID := ""
for i := 0; i < MaxChainIDLen; i++ {
maxChainID += "𠜎"
}
h := Header{
ChainID: maxChainID,
Height: 10,
Time: time.Now().UTC(),
NumTxs: 100,
TotalTxs: 200,
LastBlockID: makeBlockID(make([]byte, 20), 300, make([]byte, 20)),
LastCommitHash: tmhash.Sum([]byte("last_commit_hash")),
DataHash: tmhash.Sum([]byte("data_hash")),
ValidatorsHash: tmhash.Sum([]byte("validators_hash")),
NextValidatorsHash: tmhash.Sum([]byte("next_validators_hash")),
ConsensusHash: tmhash.Sum([]byte("consensus_hash")),
AppHash: tmhash.Sum([]byte("app_hash")),
LastResultsHash: tmhash.Sum([]byte("last_results_hash")),
EvidenceHash: tmhash.Sum([]byte("evidence_hash")),
ProposerAddress: tmhash.Sum([]byte("proposer_address")),
}
b := Block{
Header: h,
Data: Data{Txs: makeTxs(10000, 100)},
Evidence: EvidenceData{},
LastCommit: &Commit{},
}
bz, err := cdc.MarshalBinary(b)
require.NoError(t, err)
assert.Equal(t, MaxHeaderBytes+MaxAminoOverheadForBlock-2, len(bz)-1000000-20000-1)
}
```
* fix MaxYYY constants calculation
by using math.MaxInt64
See https://github.com/tendermint/tendermint/pull/2184#discussion_r214444244
* pass mempool filter as an option
See https://github.com/tendermint/tendermint/pull/2184#discussion_r214445869
* fixes after Dev's comments
2018-09-04 11:46:34 +04:00
|
|
|
mempoolLogger := logger.With("module", "mempool")
|
2019-05-04 10:41:31 +04:00
|
|
|
mempoolReactor := mempl.NewReactor(config.Mempool, mempool)
|
2018-06-20 17:35:30 -07:00
|
|
|
mempoolReactor.SetLogger(mempoolLogger)
|
|
|
|
|
|
|
|
if config.Consensus.WaitForTxs() {
|
|
|
|
mempool.EnableTxsAvailable()
|
|
|
|
}
|
2019-04-26 08:05:39 -04:00
|
|
|
return mempoolReactor, mempool
|
|
|
|
}
|
|
|
|
|
|
|
|
func createEvidenceReactor(config *cfg.Config, dbProvider DBProvider,
|
|
|
|
stateDB dbm.DB, logger log.Logger) (*evidence.EvidenceReactor, *evidence.EvidencePool, error) {
|
2018-06-20 17:35:30 -07:00
|
|
|
|
|
|
|
evidenceDB, err := dbProvider(&DBContext{"evidence", config})
|
|
|
|
if err != nil {
|
2019-04-26 08:05:39 -04:00
|
|
|
return nil, nil, err
|
2018-06-20 17:35:30 -07:00
|
|
|
}
|
|
|
|
evidenceLogger := logger.With("module", "evidence")
|
2019-02-08 18:25:48 -05:00
|
|
|
evidencePool := evidence.NewEvidencePool(stateDB, evidenceDB)
|
2018-06-20 17:35:30 -07:00
|
|
|
evidencePool.SetLogger(evidenceLogger)
|
|
|
|
evidenceReactor := evidence.NewEvidenceReactor(evidencePool)
|
|
|
|
evidenceReactor.SetLogger(evidenceLogger)
|
2019-04-26 08:05:39 -04:00
|
|
|
return evidenceReactor, evidencePool, nil
|
|
|
|
}
|
2018-06-20 17:35:30 -07:00
|
|
|
|
blockchain: Reorg reactor (#3561)
* go routines in blockchain reactor
* Added reference to the go routine diagram
* Initial commit
* cleanup
* Undo testing_logger change, committed by mistake
* Fix the test loggers
* pulled some fsm code into pool.go
* added pool tests
* changes to the design
added block requests under peer
moved the request trigger in the reactor poolRoutine, triggered now by a ticker
in general moved everything required for making block requests smarter in the poolRoutine
added a simple map of heights to keep track of what will need to be requested next
added a few more tests
* send errors to FSM in a different channel than blocks
send errors (RemovePeer) from switch on a different channel than the
one receiving blocks
renamed channels
added more pool tests
* more pool tests
* lint errors
* more tests
* more tests
* switch fast sync to new implementation
* fixed data race in tests
* cleanup
* finished fsm tests
* address golangci comments :)
* address golangci comments :)
* Added timeout on next block needed to advance
* updating docs and cleanup
* fix issue in test from previous cleanup
* cleanup
* Added termination scenarios, tests and more cleanup
* small fixes to adr, comments and cleanup
* Fix bug in sendRequest()
If we tried to send a request to a peer not present in the switch, a
missing continue statement caused the request to be blackholed in a peer
that was removed and never retried.
While this bug was manifesting, the reactor kept asking for other
blocks that would be stored and never consumed. Added the number of
unconsumed blocks in the math for requesting blocks ahead of current
processing height so eventually there will be no more blocks requested
until the already received ones are consumed.
* remove bpPeer's didTimeout field
* Use distinct err codes for peer timeout and FSM timeouts
* Don't allow peers to update with lower height
* review comments from Ethan and Zarko
* some cleanup, renaming, comments
* Move block execution in separate goroutine
* Remove pool's numPending
* review comments
* fix lint, remove old blockchain reactor and duplicates in fsm tests
* small reorg around peer after review comments
* add the reactor spec
* verify block only once
* review comments
* change to int for max number of pending requests
* cleanup and godoc
* Add configuration flag fast sync version
* golangci fixes
* fix config template
* move both reactor versions under blockchain
* cleanup, golint, renaming stuff
* updated documentation, fixed more golint warnings
* integrate with behavior package
* sync with master
* gofmt
* add changelog_pending entry
* move to improvments
* suggestion to changelog entry
2019-07-23 10:58:52 +02:00
|
|
|
func createBlockchainReactor(config *cfg.Config,
|
|
|
|
state sm.State,
|
|
|
|
blockExec *sm.BlockExecutor,
|
|
|
|
blockStore *store.BlockStore,
|
|
|
|
fastSync bool,
|
|
|
|
logger log.Logger) (bcReactor p2p.Reactor, err error) {
|
|
|
|
|
|
|
|
switch config.FastSync.Version {
|
|
|
|
case "v0":
|
|
|
|
bcReactor = bcv0.NewBlockchainReactor(state.Copy(), blockExec, blockStore, fastSync)
|
|
|
|
case "v1":
|
|
|
|
bcReactor = bcv1.NewBlockchainReactor(state.Copy(), blockExec, blockStore, fastSync)
|
|
|
|
default:
|
|
|
|
return nil, fmt.Errorf("unknown fastsync version %s", config.FastSync.Version)
|
|
|
|
}
|
|
|
|
|
|
|
|
bcReactor.SetLogger(logger.With("module", "blockchain"))
|
|
|
|
return bcReactor, nil
|
|
|
|
}
|
|
|
|
|
2019-04-26 08:05:39 -04:00
|
|
|
func createConsensusReactor(config *cfg.Config,
|
|
|
|
state sm.State,
|
|
|
|
blockExec *sm.BlockExecutor,
|
|
|
|
blockStore sm.BlockStore,
|
2019-05-04 10:41:31 +04:00
|
|
|
mempool *mempl.CListMempool,
|
2019-04-26 08:05:39 -04:00
|
|
|
evidencePool *evidence.EvidencePool,
|
|
|
|
privValidator types.PrivValidator,
|
|
|
|
csMetrics *cs.Metrics,
|
|
|
|
fastSync bool,
|
|
|
|
eventBus *types.EventBus,
|
|
|
|
consensusLogger log.Logger) (*consensus.ConsensusReactor, *consensus.ConsensusState) {
|
2018-06-20 17:35:30 -07:00
|
|
|
|
|
|
|
consensusState := cs.NewConsensusState(
|
|
|
|
config.Consensus,
|
|
|
|
state.Copy(),
|
|
|
|
blockExec,
|
|
|
|
blockStore,
|
|
|
|
mempool,
|
|
|
|
evidencePool,
|
2018-09-25 04:14:38 -07:00
|
|
|
cs.StateMetrics(csMetrics),
|
2018-06-20 17:35:30 -07:00
|
|
|
)
|
|
|
|
consensusState.SetLogger(consensusLogger)
|
|
|
|
if privValidator != nil {
|
|
|
|
consensusState.SetPrivValidator(privValidator)
|
|
|
|
}
|
2018-09-25 04:14:38 -07:00
|
|
|
consensusReactor := cs.NewConsensusReactor(consensusState, fastSync, cs.ReactorMetrics(csMetrics))
|
2018-06-20 17:35:30 -07:00
|
|
|
consensusReactor.SetLogger(consensusLogger)
|
2018-09-18 22:14:40 +02:00
|
|
|
// services which will be publishing and/or subscribing for messages (events)
|
|
|
|
// consensusReactor will set it on consensusState and blockExecutor
|
|
|
|
consensusReactor.SetEventBus(eventBus)
|
2019-04-26 08:05:39 -04:00
|
|
|
return consensusReactor, consensusState
|
|
|
|
}
|
2018-06-20 17:35:30 -07:00
|
|
|
|
2019-04-26 08:05:39 -04:00
|
|
|
func createTransport(config *cfg.Config, nodeInfo p2p.NodeInfo, nodeKey *p2p.NodeKey, proxyApp proxy.AppConns) (*p2p.MultiplexTransport, []p2p.PeerFilterFunc) {
|
2018-09-18 22:14:40 +02:00
|
|
|
var (
|
2018-11-17 03:16:49 -05:00
|
|
|
mConnConfig = p2p.MConnConfig(config.P2P)
|
|
|
|
transport = p2p.NewMultiplexTransport(nodeInfo, *nodeKey, mConnConfig)
|
2018-09-18 22:14:40 +02:00
|
|
|
connFilters = []p2p.ConnFilterFunc{}
|
|
|
|
peerFilters = []p2p.PeerFilterFunc{}
|
|
|
|
)
|
|
|
|
|
|
|
|
if !config.P2P.AllowDuplicateIP {
|
|
|
|
connFilters = append(connFilters, p2p.ConnDuplicateIPFilter())
|
|
|
|
}
|
|
|
|
|
|
|
|
// Filter peers by addr or pubkey with an ABCI query.
|
|
|
|
// If the query return code is OK, add peer.
|
|
|
|
if config.FilterPeers {
|
|
|
|
connFilters = append(
|
|
|
|
connFilters,
|
|
|
|
// ABCI query for address filtering.
|
|
|
|
func(_ p2p.ConnSet, c net.Conn, _ []net.IP) error {
|
|
|
|
res, err := proxyApp.Query().QuerySync(abci.RequestQuery{
|
|
|
|
Path: fmt.Sprintf("/p2p/filter/addr/%s", c.RemoteAddr().String()),
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if res.IsErr() {
|
2019-04-26 08:05:39 -04:00
|
|
|
return fmt.Errorf("error querying abci app: %v", res)
|
2018-09-18 22:14:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
)
|
|
|
|
|
|
|
|
peerFilters = append(
|
|
|
|
peerFilters,
|
|
|
|
// ABCI query for ID filtering.
|
|
|
|
func(_ p2p.IPeerSet, p p2p.Peer) error {
|
|
|
|
res, err := proxyApp.Query().QuerySync(abci.RequestQuery{
|
|
|
|
Path: fmt.Sprintf("/p2p/filter/id/%s", p.ID()),
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if res.IsErr() {
|
2019-04-26 08:05:39 -04:00
|
|
|
return fmt.Errorf("error querying abci app: %v", res)
|
2018-09-18 22:14:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
p2p.MultiplexTransportConnFilters(connFilters...)(transport)
|
2019-04-26 08:05:39 -04:00
|
|
|
return transport, peerFilters
|
|
|
|
}
|
|
|
|
|
|
|
|
func createSwitch(config *cfg.Config,
|
2019-09-30 20:12:51 -04:00
|
|
|
transport p2p.Transport,
|
2019-04-26 08:05:39 -04:00
|
|
|
p2pMetrics *p2p.Metrics,
|
|
|
|
peerFilters []p2p.PeerFilterFunc,
|
2019-05-04 10:41:31 +04:00
|
|
|
mempoolReactor *mempl.Reactor,
|
blockchain: Reorg reactor (#3561)
* go routines in blockchain reactor
* Added reference to the go routine diagram
* Initial commit
* cleanup
* Undo testing_logger change, committed by mistake
* Fix the test loggers
* pulled some fsm code into pool.go
* added pool tests
* changes to the design
added block requests under peer
moved the request trigger in the reactor poolRoutine, triggered now by a ticker
in general moved everything required for making block requests smarter in the poolRoutine
added a simple map of heights to keep track of what will need to be requested next
added a few more tests
* send errors to FSM in a different channel than blocks
send errors (RemovePeer) from switch on a different channel than the
one receiving blocks
renamed channels
added more pool tests
* more pool tests
* lint errors
* more tests
* more tests
* switch fast sync to new implementation
* fixed data race in tests
* cleanup
* finished fsm tests
* address golangci comments :)
* address golangci comments :)
* Added timeout on next block needed to advance
* updating docs and cleanup
* fix issue in test from previous cleanup
* cleanup
* Added termination scenarios, tests and more cleanup
* small fixes to adr, comments and cleanup
* Fix bug in sendRequest()
If we tried to send a request to a peer not present in the switch, a
missing continue statement caused the request to be blackholed in a peer
that was removed and never retried.
While this bug was manifesting, the reactor kept asking for other
blocks that would be stored and never consumed. Added the number of
unconsumed blocks in the math for requesting blocks ahead of current
processing height so eventually there will be no more blocks requested
until the already received ones are consumed.
* remove bpPeer's didTimeout field
* Use distinct err codes for peer timeout and FSM timeouts
* Don't allow peers to update with lower height
* review comments from Ethan and Zarko
* some cleanup, renaming, comments
* Move block execution in separate goroutine
* Remove pool's numPending
* review comments
* fix lint, remove old blockchain reactor and duplicates in fsm tests
* small reorg around peer after review comments
* add the reactor spec
* verify block only once
* review comments
* change to int for max number of pending requests
* cleanup and godoc
* Add configuration flag fast sync version
* golangci fixes
* fix config template
* move both reactor versions under blockchain
* cleanup, golint, renaming stuff
* updated documentation, fixed more golint warnings
* integrate with behavior package
* sync with master
* gofmt
* add changelog_pending entry
* move to improvments
* suggestion to changelog entry
2019-07-23 10:58:52 +02:00
|
|
|
bcReactor p2p.Reactor,
|
2019-04-26 08:05:39 -04:00
|
|
|
consensusReactor *consensus.ConsensusReactor,
|
|
|
|
evidenceReactor *evidence.EvidenceReactor,
|
|
|
|
nodeInfo p2p.NodeInfo,
|
|
|
|
nodeKey *p2p.NodeKey,
|
|
|
|
p2pLogger log.Logger) *p2p.Switch {
|
2018-09-18 22:14:40 +02:00
|
|
|
|
|
|
|
sw := p2p.NewSwitch(
|
|
|
|
config.P2P,
|
|
|
|
transport,
|
|
|
|
p2p.WithMetrics(p2pMetrics),
|
|
|
|
p2p.SwitchPeerFilters(peerFilters...),
|
|
|
|
)
|
2018-06-20 17:35:30 -07:00
|
|
|
sw.SetLogger(p2pLogger)
|
|
|
|
sw.AddReactor("MEMPOOL", mempoolReactor)
|
|
|
|
sw.AddReactor("BLOCKCHAIN", bcReactor)
|
|
|
|
sw.AddReactor("CONSENSUS", consensusReactor)
|
|
|
|
sw.AddReactor("EVIDENCE", evidenceReactor)
|
2019-07-03 17:17:59 +04:00
|
|
|
|
2018-09-18 22:14:40 +02:00
|
|
|
sw.SetNodeInfo(nodeInfo)
|
|
|
|
sw.SetNodeKey(nodeKey)
|
|
|
|
|
2018-08-15 16:29:45 +08:00
|
|
|
p2pLogger.Info("P2P Node ID", "ID", nodeKey.ID(), "file", config.NodeKeyFile())
|
2019-04-26 08:05:39 -04:00
|
|
|
return sw
|
|
|
|
}
|
|
|
|
|
|
|
|
func createAddrBookAndSetOnSwitch(config *cfg.Config, sw *p2p.Switch,
|
2019-06-21 09:30:32 +04:00
|
|
|
p2pLogger log.Logger, nodeKey *p2p.NodeKey) (pex.AddrBook, error) {
|
2019-04-26 08:05:39 -04:00
|
|
|
|
|
|
|
addrBook := pex.NewAddrBook(config.P2P.AddrBookFile(), config.P2P.AddrBookStrict)
|
|
|
|
addrBook.SetLogger(p2pLogger.With("book", config.P2P.AddrBookFile()))
|
|
|
|
|
|
|
|
// Add ourselves to addrbook to prevent dialing ourselves
|
2019-06-21 09:30:32 +04:00
|
|
|
if config.P2P.ExternalAddress != "" {
|
|
|
|
addr, err := p2p.NewNetAddressString(p2p.IDAddressString(nodeKey.ID(), config.P2P.ExternalAddress))
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "p2p.external_address is incorrect")
|
|
|
|
}
|
|
|
|
addrBook.AddOurAddress(addr)
|
|
|
|
}
|
|
|
|
if config.P2P.ListenAddress != "" {
|
|
|
|
addr, err := p2p.NewNetAddressString(p2p.IDAddressString(nodeKey.ID(), config.P2P.ListenAddress))
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "p2p.laddr is incorrect")
|
|
|
|
}
|
|
|
|
addrBook.AddOurAddress(addr)
|
|
|
|
}
|
2019-04-26 08:05:39 -04:00
|
|
|
|
|
|
|
sw.SetAddrBook(addrBook)
|
|
|
|
|
2019-06-21 09:30:32 +04:00
|
|
|
return addrBook, nil
|
2019-04-26 08:05:39 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func createPEXReactorAndAddToSwitch(addrBook pex.AddrBook, config *cfg.Config,
|
|
|
|
sw *p2p.Switch, logger log.Logger) *pex.PEXReactor {
|
|
|
|
|
|
|
|
// TODO persistent peers ? so we can have their DNS addrs saved
|
|
|
|
pexReactor := pex.NewPEXReactor(addrBook,
|
|
|
|
&pex.PEXReactorConfig{
|
|
|
|
Seeds: splitAndTrimEmpty(config.P2P.Seeds, ",", " "),
|
|
|
|
SeedMode: config.P2P.SeedMode,
|
|
|
|
// See consensus/reactor.go: blocksToContributeToBecomeGoodPeer 10000
|
|
|
|
// blocks assuming 10s blocks ~ 28 hours.
|
|
|
|
// TODO (melekes): make it dynamic based on the actual block latencies
|
|
|
|
// from the live network.
|
|
|
|
// https://github.com/tendermint/tendermint/issues/3523
|
|
|
|
SeedDisconnectWaitPeriod: 28 * time.Hour,
|
|
|
|
})
|
|
|
|
pexReactor.SetLogger(logger.With("module", "pex"))
|
|
|
|
sw.AddReactor("PEX", pexReactor)
|
|
|
|
return pexReactor
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewNode returns a new, ready to go, Tendermint Node.
|
|
|
|
func NewNode(config *cfg.Config,
|
|
|
|
privValidator types.PrivValidator,
|
|
|
|
nodeKey *p2p.NodeKey,
|
|
|
|
clientCreator proxy.ClientCreator,
|
2019-05-30 18:40:17 -04:00
|
|
|
genesisDocProvider GenesisDocProvider,
|
2019-04-26 08:05:39 -04:00
|
|
|
dbProvider DBProvider,
|
|
|
|
metricsProvider MetricsProvider,
|
2019-07-03 17:17:59 +04:00
|
|
|
logger log.Logger,
|
|
|
|
options ...Option) (*Node, error) {
|
2019-04-26 08:05:39 -04:00
|
|
|
|
|
|
|
blockStore, stateDB, err := initDBs(config, dbProvider)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-05-30 18:40:17 -04:00
|
|
|
state, genDoc, err := LoadStateFromDBOrGenesisDocProvider(stateDB, genesisDocProvider)
|
2019-04-26 08:05:39 -04:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create the proxyApp and establish connections to the ABCI app (consensus, mempool, query).
|
|
|
|
proxyApp, err := createAndStartProxyAppConns(clientCreator, logger)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// EventBus and IndexerService must be started before the handshake because
|
|
|
|
// we might need to index the txs of the replayed block as this might not have happened
|
|
|
|
// when the node stopped last time (i.e. the node stopped after it saved the block
|
|
|
|
// but before it indexed the txs, or, endblocker panicked)
|
|
|
|
eventBus, err := createAndStartEventBus(logger)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Transaction indexing
|
|
|
|
indexerService, txIndexer, err := createAndStartIndexerService(config, dbProvider, eventBus, logger)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create the handshaker, which calls RequestInfo, sets the AppVersion on the state,
|
|
|
|
// and replays any blocks as necessary to sync tendermint with the app.
|
|
|
|
consensusLogger := logger.With("module", "consensus")
|
|
|
|
if err := doHandshake(stateDB, state, blockStore, genDoc, eventBus, proxyApp, consensusLogger); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reload the state. It will have the Version.Consensus.App set by the
|
|
|
|
// Handshake, and may have other modifications as well (ie. depending on
|
|
|
|
// what happened during block replay).
|
|
|
|
state = sm.LoadState(stateDB)
|
|
|
|
|
|
|
|
// If an address is provided, listen on the socket for a connection from an
|
|
|
|
// external signing process.
|
|
|
|
if config.PrivValidatorListenAddr != "" {
|
|
|
|
// FIXME: we should start services inside OnStart
|
|
|
|
privValidator, err = createAndStartPrivValidatorSocketClient(config.PrivValidatorListenAddr, logger)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "error with private validator socket client")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-05 17:09:10 +02:00
|
|
|
pubKey := privValidator.GetPubKey()
|
|
|
|
if pubKey == nil {
|
|
|
|
// TODO: GetPubKey should return errors - https://github.com/tendermint/tendermint/issues/3602
|
|
|
|
return nil, errors.New("could not retrieve public key from private validator")
|
|
|
|
}
|
|
|
|
|
|
|
|
logNodeStartupInfo(state, pubKey, logger, consensusLogger)
|
2019-04-26 08:05:39 -04:00
|
|
|
|
|
|
|
// Decide whether to fast-sync or not
|
|
|
|
// We don't fast-sync when the only validator is us.
|
blockchain: Reorg reactor (#3561)
* go routines in blockchain reactor
* Added reference to the go routine diagram
* Initial commit
* cleanup
* Undo testing_logger change, committed by mistake
* Fix the test loggers
* pulled some fsm code into pool.go
* added pool tests
* changes to the design
added block requests under peer
moved the request trigger in the reactor poolRoutine, triggered now by a ticker
in general moved everything required for making block requests smarter in the poolRoutine
added a simple map of heights to keep track of what will need to be requested next
added a few more tests
* send errors to FSM in a different channel than blocks
send errors (RemovePeer) from switch on a different channel than the
one receiving blocks
renamed channels
added more pool tests
* more pool tests
* lint errors
* more tests
* more tests
* switch fast sync to new implementation
* fixed data race in tests
* cleanup
* finished fsm tests
* address golangci comments :)
* address golangci comments :)
* Added timeout on next block needed to advance
* updating docs and cleanup
* fix issue in test from previous cleanup
* cleanup
* Added termination scenarios, tests and more cleanup
* small fixes to adr, comments and cleanup
* Fix bug in sendRequest()
If we tried to send a request to a peer not present in the switch, a
missing continue statement caused the request to be blackholed in a peer
that was removed and never retried.
While this bug was manifesting, the reactor kept asking for other
blocks that would be stored and never consumed. Added the number of
unconsumed blocks in the math for requesting blocks ahead of current
processing height so eventually there will be no more blocks requested
until the already received ones are consumed.
* remove bpPeer's didTimeout field
* Use distinct err codes for peer timeout and FSM timeouts
* Don't allow peers to update with lower height
* review comments from Ethan and Zarko
* some cleanup, renaming, comments
* Move block execution in separate goroutine
* Remove pool's numPending
* review comments
* fix lint, remove old blockchain reactor and duplicates in fsm tests
* small reorg around peer after review comments
* add the reactor spec
* verify block only once
* review comments
* change to int for max number of pending requests
* cleanup and godoc
* Add configuration flag fast sync version
* golangci fixes
* fix config template
* move both reactor versions under blockchain
* cleanup, golint, renaming stuff
* updated documentation, fixed more golint warnings
* integrate with behavior package
* sync with master
* gofmt
* add changelog_pending entry
* move to improvments
* suggestion to changelog entry
2019-07-23 10:58:52 +02:00
|
|
|
fastSync := config.FastSyncMode && !onlyValidatorIsUs(state, privValidator)
|
2019-04-26 08:05:39 -04:00
|
|
|
|
|
|
|
csMetrics, p2pMetrics, memplMetrics, smMetrics := metricsProvider(genDoc.ChainID)
|
|
|
|
|
|
|
|
// Make MempoolReactor
|
|
|
|
mempoolReactor, mempool := createMempoolAndMempoolReactor(config, proxyApp, state, memplMetrics, logger)
|
|
|
|
|
|
|
|
// Make Evidence Reactor
|
|
|
|
evidenceReactor, evidencePool, err := createEvidenceReactor(config, dbProvider, stateDB, logger)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// make block executor for consensus and blockchain reactors to execute blocks
|
|
|
|
blockExec := sm.NewBlockExecutor(
|
|
|
|
stateDB,
|
|
|
|
logger.With("module", "state"),
|
|
|
|
proxyApp.Consensus(),
|
|
|
|
mempool,
|
|
|
|
evidencePool,
|
|
|
|
sm.BlockExecutorWithMetrics(smMetrics),
|
|
|
|
)
|
|
|
|
|
|
|
|
// Make BlockchainReactor
|
blockchain: Reorg reactor (#3561)
* go routines in blockchain reactor
* Added reference to the go routine diagram
* Initial commit
* cleanup
* Undo testing_logger change, committed by mistake
* Fix the test loggers
* pulled some fsm code into pool.go
* added pool tests
* changes to the design
added block requests under peer
moved the request trigger in the reactor poolRoutine, triggered now by a ticker
in general moved everything required for making block requests smarter in the poolRoutine
added a simple map of heights to keep track of what will need to be requested next
added a few more tests
* send errors to FSM in a different channel than blocks
send errors (RemovePeer) from switch on a different channel than the
one receiving blocks
renamed channels
added more pool tests
* more pool tests
* lint errors
* more tests
* more tests
* switch fast sync to new implementation
* fixed data race in tests
* cleanup
* finished fsm tests
* address golangci comments :)
* address golangci comments :)
* Added timeout on next block needed to advance
* updating docs and cleanup
* fix issue in test from previous cleanup
* cleanup
* Added termination scenarios, tests and more cleanup
* small fixes to adr, comments and cleanup
* Fix bug in sendRequest()
If we tried to send a request to a peer not present in the switch, a
missing continue statement caused the request to be blackholed in a peer
that was removed and never retried.
While this bug was manifesting, the reactor kept asking for other
blocks that would be stored and never consumed. Added the number of
unconsumed blocks in the math for requesting blocks ahead of current
processing height so eventually there will be no more blocks requested
until the already received ones are consumed.
* remove bpPeer's didTimeout field
* Use distinct err codes for peer timeout and FSM timeouts
* Don't allow peers to update with lower height
* review comments from Ethan and Zarko
* some cleanup, renaming, comments
* Move block execution in separate goroutine
* Remove pool's numPending
* review comments
* fix lint, remove old blockchain reactor and duplicates in fsm tests
* small reorg around peer after review comments
* add the reactor spec
* verify block only once
* review comments
* change to int for max number of pending requests
* cleanup and godoc
* Add configuration flag fast sync version
* golangci fixes
* fix config template
* move both reactor versions under blockchain
* cleanup, golint, renaming stuff
* updated documentation, fixed more golint warnings
* integrate with behavior package
* sync with master
* gofmt
* add changelog_pending entry
* move to improvments
* suggestion to changelog entry
2019-07-23 10:58:52 +02:00
|
|
|
bcReactor, err := createBlockchainReactor(config, state, blockExec, blockStore, fastSync, logger)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "could not create blockchain reactor")
|
|
|
|
}
|
2019-04-26 08:05:39 -04:00
|
|
|
|
|
|
|
// Make ConsensusReactor
|
|
|
|
consensusReactor, consensusState := createConsensusReactor(
|
|
|
|
config, state, blockExec, blockStore, mempool, evidencePool,
|
|
|
|
privValidator, csMetrics, fastSync, eventBus, consensusLogger,
|
|
|
|
)
|
|
|
|
|
|
|
|
nodeInfo, err := makeNodeInfo(config, nodeKey, txIndexer, genDoc, state)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Setup Transport.
|
|
|
|
transport, peerFilters := createTransport(config, nodeInfo, nodeKey, proxyApp)
|
|
|
|
|
|
|
|
// Setup Switch.
|
|
|
|
p2pLogger := logger.With("module", "p2p")
|
|
|
|
sw := createSwitch(
|
|
|
|
config, transport, p2pMetrics, peerFilters, mempoolReactor, bcReactor,
|
|
|
|
consensusReactor, evidenceReactor, nodeInfo, nodeKey, p2pLogger,
|
|
|
|
)
|
|
|
|
|
p2p: make persistent prop independent of conn direction (#3593)
## Description
Previously only outbound peers can be persistent.
Now, even if the peer is inbound, if it's marked as persistent, when/if conn is lost,
Tendermint will try to reconnect. This part is actually optional and can be reverted.
Plus, seed won't disconnect from inbound peer if it's marked as
persistent. Fixes #3362
## Commits
* make persistent prop independent of conn direction
Previously only outbound peers can be persistent. Now, even if the peer
is inbound, if it's marked as persistent, when/if conn is lost,
Tendermint will try to reconnect.
Plus, seed won't disconnect from inbound peer if it's marked as
persistent. Fixes #3362
* fix TestPEXReactorDialPeer test
* add a changelog entry
* update changelog
* add two tests
* reformat code
* test UnsafeDialPeers and UnsafeDialSeeds
* add TestSwitchDialPeersAsync
* spec: update p2p/config spec
* fixes after Ismail's review
* Apply suggestions from code review
Co-Authored-By: melekes <anton.kalyaev@gmail.com>
* fix merge conflict
* remove sleep from TestPEXReactorDoesNotDisconnectFromPersistentPeerInSeedMode
We don't need it actually.
2019-05-03 17:21:56 +04:00
|
|
|
err = sw.AddPersistentPeers(splitAndTrimEmpty(config.P2P.PersistentPeers, ",", " "))
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "could not add peers from persistent_peers field")
|
|
|
|
}
|
|
|
|
|
2019-06-21 09:30:32 +04:00
|
|
|
addrBook, err := createAddrBookAndSetOnSwitch(config, sw, p2pLogger, nodeKey)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "could not create addrbook")
|
|
|
|
}
|
2018-06-20 17:35:30 -07:00
|
|
|
|
|
|
|
// Optionally, start the pex reactor
|
|
|
|
//
|
|
|
|
// TODO:
|
|
|
|
//
|
|
|
|
// We need to set Seeds and PersistentPeers on the switch,
|
|
|
|
// since it needs to be able to use these (and their DNS names)
|
|
|
|
// even if the PEX is off. We can include the DNS name in the NetAddress,
|
|
|
|
// but it would still be nice to have a clear list of the current "PersistentPeers"
|
|
|
|
// somewhere that we can return with net_info.
|
|
|
|
//
|
|
|
|
// If PEX is on, it should handle dialing the seeds. Otherwise the switch does it.
|
|
|
|
// Note we currently use the addrBook regardless at least for AddOurAddress
|
2019-04-26 08:05:39 -04:00
|
|
|
var pexReactor *pex.PEXReactor
|
2018-06-20 17:35:30 -07:00
|
|
|
if config.P2P.PexReactor {
|
2019-04-26 08:05:39 -04:00
|
|
|
pexReactor = createPEXReactorAndAddToSwitch(addrBook, config, sw, logger)
|
2018-06-20 17:35:30 -07:00
|
|
|
}
|
|
|
|
|
2019-04-26 08:05:39 -04:00
|
|
|
if config.ProfListenAddress != "" {
|
2019-06-22 10:30:23 +04:00
|
|
|
go func() {
|
|
|
|
logger.Error("Profile server", "err", http.ListenAndServe(config.ProfListenAddress, nil))
|
|
|
|
}()
|
2018-06-20 17:35:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
node := &Node{
|
|
|
|
config: config,
|
|
|
|
genesisDoc: genDoc,
|
|
|
|
privValidator: privValidator,
|
|
|
|
|
2018-09-18 22:14:40 +02:00
|
|
|
transport: transport,
|
|
|
|
sw: sw,
|
|
|
|
addrBook: addrBook,
|
|
|
|
nodeInfo: nodeInfo,
|
|
|
|
nodeKey: nodeKey,
|
2018-06-20 17:35:30 -07:00
|
|
|
|
|
|
|
stateDB: stateDB,
|
|
|
|
blockStore: blockStore,
|
|
|
|
bcReactor: bcReactor,
|
|
|
|
mempoolReactor: mempoolReactor,
|
2019-05-04 10:41:31 +04:00
|
|
|
mempool: mempool,
|
2018-06-20 17:35:30 -07:00
|
|
|
consensusState: consensusState,
|
|
|
|
consensusReactor: consensusReactor,
|
2019-04-26 08:05:39 -04:00
|
|
|
pexReactor: pexReactor,
|
2018-06-20 17:35:30 -07:00
|
|
|
evidencePool: evidencePool,
|
|
|
|
proxyApp: proxyApp,
|
|
|
|
txIndexer: txIndexer,
|
|
|
|
indexerService: indexerService,
|
|
|
|
eventBus: eventBus,
|
|
|
|
}
|
|
|
|
node.BaseService = *cmn.NewBaseService(logger, "Node", node)
|
2019-07-03 17:17:59 +04:00
|
|
|
|
|
|
|
for _, option := range options {
|
|
|
|
option(node)
|
|
|
|
}
|
|
|
|
|
2018-06-20 17:35:30 -07:00
|
|
|
return node, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// OnStart starts the Node. It implements cmn.Service.
|
|
|
|
func (n *Node) OnStart() error {
|
2018-09-18 11:16:50 +02:00
|
|
|
now := tmtime.Now()
|
|
|
|
genTime := n.genesisDoc.GenesisTime
|
|
|
|
if genTime.After(now) {
|
|
|
|
n.Logger.Info("Genesis time is in the future. Sleeping until then...", "genTime", genTime)
|
|
|
|
time.Sleep(genTime.Sub(now))
|
|
|
|
}
|
|
|
|
|
2018-07-18 02:22:09 -07:00
|
|
|
// Add private IDs to addrbook to block those peers being added
|
2018-09-05 14:13:25 +08:00
|
|
|
n.addrBook.AddPrivateIDs(splitAndTrimEmpty(n.config.P2P.PrivatePeerIDs, ",", " "))
|
2018-07-18 02:22:09 -07:00
|
|
|
|
2018-06-20 17:35:30 -07:00
|
|
|
// Start the RPC server before the P2P server
|
|
|
|
// so we can eg. receive txs for the first block
|
|
|
|
if n.config.RPC.ListenAddress != "" {
|
|
|
|
listeners, err := n.startRPC()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
n.rpcListeners = listeners
|
|
|
|
}
|
|
|
|
|
2018-07-24 15:44:01 +04:00
|
|
|
if n.config.Instrumentation.Prometheus &&
|
|
|
|
n.config.Instrumentation.PrometheusListenAddr != "" {
|
2018-06-20 17:35:30 -07:00
|
|
|
n.prometheusSrv = n.startPrometheusServer(n.config.Instrumentation.PrometheusListenAddr)
|
|
|
|
}
|
|
|
|
|
2018-09-18 22:14:40 +02:00
|
|
|
// Start the transport.
|
2019-06-06 00:39:28 +09:00
|
|
|
addr, err := p2p.NewNetAddressString(p2p.IDAddressString(n.nodeKey.ID(), n.config.P2P.ListenAddress))
|
2018-09-18 22:14:40 +02:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := n.transport.Listen(*addr); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
n.isListening = true
|
|
|
|
|
2019-05-04 10:41:31 +04:00
|
|
|
if n.config.Mempool.WalEnabled() {
|
|
|
|
n.mempool.InitWAL() // no need to have the mempool wal during tests
|
|
|
|
}
|
|
|
|
|
2018-06-20 17:35:30 -07:00
|
|
|
// Start the switch (the P2P server).
|
|
|
|
err = n.sw.Start()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Always connect to persistent peers
|
2019-05-07 11:09:06 +04:00
|
|
|
err = n.sw.DialPeersAsync(splitAndTrimEmpty(n.config.P2P.PersistentPeers, ",", " "))
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "could not dial peers from persistent_peers field")
|
|
|
|
}
|
2018-06-20 17:35:30 -07:00
|
|
|
|
2019-01-28 15:36:35 +08:00
|
|
|
return nil
|
2018-06-20 17:35:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// OnStop stops the Node. It implements cmn.Service.
|
|
|
|
func (n *Node) OnStop() {
|
|
|
|
n.BaseService.OnStop()
|
|
|
|
|
|
|
|
n.Logger.Info("Stopping Node")
|
2018-07-18 08:38:44 -07:00
|
|
|
|
|
|
|
// first stop the non-reactor services
|
|
|
|
n.eventBus.Stop()
|
|
|
|
n.indexerService.Stop()
|
|
|
|
|
|
|
|
// now stop the reactors
|
2018-06-20 17:35:30 -07:00
|
|
|
n.sw.Stop()
|
|
|
|
|
2018-11-06 07:39:05 +01:00
|
|
|
// stop mempool WAL
|
|
|
|
if n.config.Mempool.WalEnabled() {
|
2019-05-04 10:41:31 +04:00
|
|
|
n.mempool.CloseWAL()
|
2018-11-06 07:39:05 +01:00
|
|
|
}
|
|
|
|
|
2018-09-18 22:14:40 +02:00
|
|
|
if err := n.transport.Close(); err != nil {
|
|
|
|
n.Logger.Error("Error closing transport", "err", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
n.isListening = false
|
|
|
|
|
2018-07-18 08:38:44 -07:00
|
|
|
// finally stop the listeners / external services
|
2018-06-20 17:35:30 -07:00
|
|
|
for _, l := range n.rpcListeners {
|
|
|
|
n.Logger.Info("Closing rpc listener", "listener", l)
|
|
|
|
if err := l.Close(); err != nil {
|
|
|
|
n.Logger.Error("Error closing listener", "listener", l, "err", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-21 06:45:20 +00:00
|
|
|
if pvsc, ok := n.privValidator.(cmn.Service); ok {
|
2018-11-21 21:24:13 +04:00
|
|
|
pvsc.Stop()
|
2018-06-20 17:35:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if n.prometheusSrv != nil {
|
|
|
|
if err := n.prometheusSrv.Shutdown(context.Background()); err != nil {
|
|
|
|
// Error from closing listeners, or context timeout:
|
|
|
|
n.Logger.Error("Prometheus HTTP server Shutdown", "err", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ConfigureRPC sets all variables in rpccore so they will serve
|
|
|
|
// rpc calls from this node
|
|
|
|
func (n *Node) ConfigureRPC() {
|
|
|
|
rpccore.SetStateDB(n.stateDB)
|
|
|
|
rpccore.SetBlockStore(n.blockStore)
|
|
|
|
rpccore.SetConsensusState(n.consensusState)
|
2019-05-04 10:41:31 +04:00
|
|
|
rpccore.SetMempool(n.mempool)
|
2018-06-20 17:35:30 -07:00
|
|
|
rpccore.SetEvidencePool(n.evidencePool)
|
2018-09-18 22:14:40 +02:00
|
|
|
rpccore.SetP2PPeers(n.sw)
|
|
|
|
rpccore.SetP2PTransport(n)
|
2018-12-22 06:36:45 +01:00
|
|
|
pubKey := n.privValidator.GetPubKey()
|
|
|
|
rpccore.SetPubKey(pubKey)
|
2018-06-20 17:35:30 -07:00
|
|
|
rpccore.SetGenesisDoc(n.genesisDoc)
|
|
|
|
rpccore.SetAddrBook(n.addrBook)
|
|
|
|
rpccore.SetProxyAppQuery(n.proxyApp.Query())
|
|
|
|
rpccore.SetTxIndexer(n.txIndexer)
|
|
|
|
rpccore.SetConsensusReactor(n.consensusReactor)
|
|
|
|
rpccore.SetEventBus(n.eventBus)
|
|
|
|
rpccore.SetLogger(n.Logger.With("module", "rpc"))
|
2019-03-11 22:45:58 +04:00
|
|
|
rpccore.SetConfig(*n.config.RPC)
|
2018-06-20 17:35:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func (n *Node) startRPC() ([]net.Listener, error) {
|
|
|
|
n.ConfigureRPC()
|
2018-09-05 14:13:25 +08:00
|
|
|
listenAddrs := splitAndTrimEmpty(n.config.RPC.ListenAddress, ",", " ")
|
2018-06-20 17:35:30 -07:00
|
|
|
coreCodec := amino.NewCodec()
|
|
|
|
ctypes.RegisterAmino(coreCodec)
|
|
|
|
|
|
|
|
if n.config.RPC.Unsafe {
|
|
|
|
rpccore.AddUnsafeRoutes()
|
|
|
|
}
|
|
|
|
|
2019-07-20 16:44:42 +09:00
|
|
|
config := rpcserver.DefaultConfig()
|
|
|
|
config.MaxBodyBytes = n.config.RPC.MaxBodyBytes
|
|
|
|
config.MaxHeaderBytes = n.config.RPC.MaxHeaderBytes
|
|
|
|
config.MaxOpenConnections = n.config.RPC.MaxOpenConnections
|
|
|
|
// If necessary adjust global WriteTimeout to ensure it's greater than
|
|
|
|
// TimeoutBroadcastTxCommit.
|
|
|
|
// See https://github.com/tendermint/tendermint/issues/3435
|
|
|
|
if config.WriteTimeout <= n.config.RPC.TimeoutBroadcastTxCommit {
|
|
|
|
config.WriteTimeout = n.config.RPC.TimeoutBroadcastTxCommit + 1*time.Second
|
|
|
|
}
|
|
|
|
|
2018-06-20 17:35:30 -07:00
|
|
|
// we may expose the rpc over both a unix and tcp socket
|
|
|
|
listeners := make([]net.Listener, len(listenAddrs))
|
|
|
|
for i, listenAddr := range listenAddrs {
|
|
|
|
mux := http.NewServeMux()
|
|
|
|
rpcLogger := n.Logger.With("module", "rpc-server")
|
2019-03-11 22:45:58 +04:00
|
|
|
wmLogger := rpcLogger.With("protocol", "websocket")
|
|
|
|
wm := rpcserver.NewWebsocketManager(rpccore.Routes, coreCodec,
|
|
|
|
rpcserver.OnDisconnect(func(remoteAddr string) {
|
|
|
|
err := n.eventBus.UnsubscribeAll(context.Background(), remoteAddr)
|
|
|
|
if err != nil && err != tmpubsub.ErrSubscriptionNotFound {
|
|
|
|
wmLogger.Error("Failed to unsubscribe addr from events", "addr", remoteAddr, "err", err)
|
|
|
|
}
|
2019-07-20 16:44:42 +09:00
|
|
|
}),
|
|
|
|
rpcserver.ReadLimit(config.MaxBodyBytes),
|
|
|
|
)
|
2019-03-11 22:45:58 +04:00
|
|
|
wm.SetLogger(wmLogger)
|
2018-06-20 17:35:30 -07:00
|
|
|
mux.HandleFunc("/websocket", wm.WebsocketHandler)
|
|
|
|
rpcserver.RegisterRPCFuncs(mux, rpccore.Routes, coreCodec, rpcLogger)
|
2018-11-15 20:33:04 +00:00
|
|
|
listener, err := rpcserver.Listen(
|
|
|
|
listenAddr,
|
2019-03-20 00:45:51 +01:00
|
|
|
config,
|
2018-11-15 20:33:04 +00:00
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2018-11-14 15:47:41 +03:00
|
|
|
var rootHandler http.Handler = mux
|
|
|
|
if n.config.RPC.IsCorsEnabled() {
|
|
|
|
corsMiddleware := cors.New(cors.Options{
|
|
|
|
AllowedOrigins: n.config.RPC.CORSAllowedOrigins,
|
|
|
|
AllowedMethods: n.config.RPC.CORSAllowedMethods,
|
|
|
|
AllowedHeaders: n.config.RPC.CORSAllowedHeaders,
|
|
|
|
})
|
|
|
|
rootHandler = corsMiddleware.Handler(mux)
|
|
|
|
}
|
2019-03-24 01:08:15 +08:00
|
|
|
if n.config.RPC.IsTLSEnabled() {
|
|
|
|
go rpcserver.StartHTTPAndTLSServer(
|
|
|
|
listener,
|
|
|
|
rootHandler,
|
|
|
|
n.config.RPC.CertFile(),
|
|
|
|
n.config.RPC.KeyFile(),
|
|
|
|
rpcLogger,
|
|
|
|
config,
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
go rpcserver.StartHTTPServer(
|
|
|
|
listener,
|
|
|
|
rootHandler,
|
|
|
|
rpcLogger,
|
|
|
|
config,
|
|
|
|
)
|
|
|
|
}
|
2018-11-14 15:47:41 +03:00
|
|
|
|
2018-06-20 17:35:30 -07:00
|
|
|
listeners[i] = listener
|
|
|
|
}
|
|
|
|
|
|
|
|
// we expose a simplified api over grpc for convenience to app devs
|
|
|
|
grpcListenAddr := n.config.RPC.GRPCListenAddress
|
|
|
|
if grpcListenAddr != "" {
|
2019-03-20 00:45:51 +01:00
|
|
|
config := rpcserver.DefaultConfig()
|
|
|
|
config.MaxOpenConnections = n.config.RPC.MaxOpenConnections
|
|
|
|
listener, err := rpcserver.Listen(grpcListenAddr, config)
|
2018-06-20 17:35:30 -07:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2018-11-15 20:33:04 +00:00
|
|
|
go grpccore.StartGRPCServer(listener)
|
2018-06-20 17:35:30 -07:00
|
|
|
listeners = append(listeners, listener)
|
|
|
|
}
|
|
|
|
|
|
|
|
return listeners, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// startPrometheusServer starts a Prometheus HTTP server, listening for metrics
|
|
|
|
// collectors on addr.
|
|
|
|
func (n *Node) startPrometheusServer(addr string) *http.Server {
|
|
|
|
srv := &http.Server{
|
2018-07-10 15:49:48 +04:00
|
|
|
Addr: addr,
|
|
|
|
Handler: promhttp.InstrumentMetricHandler(
|
|
|
|
prometheus.DefaultRegisterer, promhttp.HandlerFor(
|
|
|
|
prometheus.DefaultGatherer,
|
|
|
|
promhttp.HandlerOpts{MaxRequestsInFlight: n.config.Instrumentation.MaxOpenConnections},
|
|
|
|
),
|
|
|
|
),
|
2018-06-20 17:35:30 -07:00
|
|
|
}
|
|
|
|
go func() {
|
|
|
|
if err := srv.ListenAndServe(); err != http.ErrServerClosed {
|
|
|
|
// Error starting or closing listener:
|
|
|
|
n.Logger.Error("Prometheus HTTP server ListenAndServe", "err", err)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
return srv
|
|
|
|
}
|
|
|
|
|
|
|
|
// Switch returns the Node's Switch.
|
|
|
|
func (n *Node) Switch() *p2p.Switch {
|
|
|
|
return n.sw
|
|
|
|
}
|
|
|
|
|
|
|
|
// BlockStore returns the Node's BlockStore.
|
blockchain: Reorg reactor (#3561)
* go routines in blockchain reactor
* Added reference to the go routine diagram
* Initial commit
* cleanup
* Undo testing_logger change, committed by mistake
* Fix the test loggers
* pulled some fsm code into pool.go
* added pool tests
* changes to the design
added block requests under peer
moved the request trigger in the reactor poolRoutine, triggered now by a ticker
in general moved everything required for making block requests smarter in the poolRoutine
added a simple map of heights to keep track of what will need to be requested next
added a few more tests
* send errors to FSM in a different channel than blocks
send errors (RemovePeer) from switch on a different channel than the
one receiving blocks
renamed channels
added more pool tests
* more pool tests
* lint errors
* more tests
* more tests
* switch fast sync to new implementation
* fixed data race in tests
* cleanup
* finished fsm tests
* address golangci comments :)
* address golangci comments :)
* Added timeout on next block needed to advance
* updating docs and cleanup
* fix issue in test from previous cleanup
* cleanup
* Added termination scenarios, tests and more cleanup
* small fixes to adr, comments and cleanup
* Fix bug in sendRequest()
If we tried to send a request to a peer not present in the switch, a
missing continue statement caused the request to be blackholed in a peer
that was removed and never retried.
While this bug was manifesting, the reactor kept asking for other
blocks that would be stored and never consumed. Added the number of
unconsumed blocks in the math for requesting blocks ahead of current
processing height so eventually there will be no more blocks requested
until the already received ones are consumed.
* remove bpPeer's didTimeout field
* Use distinct err codes for peer timeout and FSM timeouts
* Don't allow peers to update with lower height
* review comments from Ethan and Zarko
* some cleanup, renaming, comments
* Move block execution in separate goroutine
* Remove pool's numPending
* review comments
* fix lint, remove old blockchain reactor and duplicates in fsm tests
* small reorg around peer after review comments
* add the reactor spec
* verify block only once
* review comments
* change to int for max number of pending requests
* cleanup and godoc
* Add configuration flag fast sync version
* golangci fixes
* fix config template
* move both reactor versions under blockchain
* cleanup, golint, renaming stuff
* updated documentation, fixed more golint warnings
* integrate with behavior package
* sync with master
* gofmt
* add changelog_pending entry
* move to improvments
* suggestion to changelog entry
2019-07-23 10:58:52 +02:00
|
|
|
func (n *Node) BlockStore() *store.BlockStore {
|
2018-06-20 17:35:30 -07:00
|
|
|
return n.blockStore
|
|
|
|
}
|
|
|
|
|
|
|
|
// ConsensusState returns the Node's ConsensusState.
|
|
|
|
func (n *Node) ConsensusState() *cs.ConsensusState {
|
|
|
|
return n.consensusState
|
|
|
|
}
|
|
|
|
|
|
|
|
// ConsensusReactor returns the Node's ConsensusReactor.
|
|
|
|
func (n *Node) ConsensusReactor() *cs.ConsensusReactor {
|
|
|
|
return n.consensusReactor
|
|
|
|
}
|
|
|
|
|
2019-05-04 10:41:31 +04:00
|
|
|
// MempoolReactor returns the Node's mempool reactor.
|
|
|
|
func (n *Node) MempoolReactor() *mempl.Reactor {
|
2018-06-20 17:35:30 -07:00
|
|
|
return n.mempoolReactor
|
|
|
|
}
|
|
|
|
|
2019-05-04 10:41:31 +04:00
|
|
|
// Mempool returns the Node's mempool.
|
|
|
|
func (n *Node) Mempool() mempl.Mempool {
|
|
|
|
return n.mempool
|
|
|
|
}
|
|
|
|
|
2019-04-26 08:05:39 -04:00
|
|
|
// PEXReactor returns the Node's PEXReactor. It returns nil if PEX is disabled.
|
|
|
|
func (n *Node) PEXReactor() *pex.PEXReactor {
|
|
|
|
return n.pexReactor
|
|
|
|
}
|
|
|
|
|
2018-06-20 17:35:30 -07:00
|
|
|
// EvidencePool returns the Node's EvidencePool.
|
|
|
|
func (n *Node) EvidencePool() *evidence.EvidencePool {
|
|
|
|
return n.evidencePool
|
|
|
|
}
|
|
|
|
|
|
|
|
// EventBus returns the Node's EventBus.
|
|
|
|
func (n *Node) EventBus() *types.EventBus {
|
|
|
|
return n.eventBus
|
|
|
|
}
|
|
|
|
|
|
|
|
// PrivValidator returns the Node's PrivValidator.
|
|
|
|
// XXX: for convenience only!
|
|
|
|
func (n *Node) PrivValidator() types.PrivValidator {
|
|
|
|
return n.privValidator
|
|
|
|
}
|
|
|
|
|
|
|
|
// GenesisDoc returns the Node's GenesisDoc.
|
|
|
|
func (n *Node) GenesisDoc() *types.GenesisDoc {
|
|
|
|
return n.genesisDoc
|
|
|
|
}
|
|
|
|
|
|
|
|
// ProxyApp returns the Node's AppConns, representing its connections to the ABCI application.
|
|
|
|
func (n *Node) ProxyApp() proxy.AppConns {
|
|
|
|
return n.proxyApp
|
|
|
|
}
|
|
|
|
|
2019-02-18 13:23:40 +04:00
|
|
|
// Config returns the Node's config.
|
|
|
|
func (n *Node) Config() *cfg.Config {
|
|
|
|
return n.config
|
|
|
|
}
|
|
|
|
|
2018-09-18 22:14:40 +02:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
func (n *Node) Listeners() []string {
|
|
|
|
return []string{
|
|
|
|
fmt.Sprintf("Listener(@%v)", n.config.P2P.ExternalAddress),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *Node) IsListening() bool {
|
|
|
|
return n.isListening
|
|
|
|
}
|
|
|
|
|
|
|
|
// NodeInfo returns the Node's Info from the Switch.
|
|
|
|
func (n *Node) NodeInfo() p2p.NodeInfo {
|
|
|
|
return n.nodeInfo
|
|
|
|
}
|
|
|
|
|
|
|
|
func makeNodeInfo(
|
|
|
|
config *cfg.Config,
|
2019-04-26 08:05:39 -04:00
|
|
|
nodeKey *p2p.NodeKey,
|
2018-09-18 22:14:40 +02:00
|
|
|
txIndexer txindex.TxIndexer,
|
2019-04-26 08:05:39 -04:00
|
|
|
genDoc *types.GenesisDoc,
|
|
|
|
state sm.State,
|
2018-12-16 14:05:58 -05:00
|
|
|
) (p2p.NodeInfo, error) {
|
2018-06-20 17:35:30 -07:00
|
|
|
txIndexerStatus := "on"
|
2018-09-18 22:14:40 +02:00
|
|
|
if _, ok := txIndexer.(*null.TxIndex); ok {
|
2018-06-20 17:35:30 -07:00
|
|
|
txIndexerStatus = "off"
|
|
|
|
}
|
blockchain: Reorg reactor (#3561)
* go routines in blockchain reactor
* Added reference to the go routine diagram
* Initial commit
* cleanup
* Undo testing_logger change, committed by mistake
* Fix the test loggers
* pulled some fsm code into pool.go
* added pool tests
* changes to the design
added block requests under peer
moved the request trigger in the reactor poolRoutine, triggered now by a ticker
in general moved everything required for making block requests smarter in the poolRoutine
added a simple map of heights to keep track of what will need to be requested next
added a few more tests
* send errors to FSM in a different channel than blocks
send errors (RemovePeer) from switch on a different channel than the
one receiving blocks
renamed channels
added more pool tests
* more pool tests
* lint errors
* more tests
* more tests
* switch fast sync to new implementation
* fixed data race in tests
* cleanup
* finished fsm tests
* address golangci comments :)
* address golangci comments :)
* Added timeout on next block needed to advance
* updating docs and cleanup
* fix issue in test from previous cleanup
* cleanup
* Added termination scenarios, tests and more cleanup
* small fixes to adr, comments and cleanup
* Fix bug in sendRequest()
If we tried to send a request to a peer not present in the switch, a
missing continue statement caused the request to be blackholed in a peer
that was removed and never retried.
While this bug was manifesting, the reactor kept asking for other
blocks that would be stored and never consumed. Added the number of
unconsumed blocks in the math for requesting blocks ahead of current
processing height so eventually there will be no more blocks requested
until the already received ones are consumed.
* remove bpPeer's didTimeout field
* Use distinct err codes for peer timeout and FSM timeouts
* Don't allow peers to update with lower height
* review comments from Ethan and Zarko
* some cleanup, renaming, comments
* Move block execution in separate goroutine
* Remove pool's numPending
* review comments
* fix lint, remove old blockchain reactor and duplicates in fsm tests
* small reorg around peer after review comments
* add the reactor spec
* verify block only once
* review comments
* change to int for max number of pending requests
* cleanup and godoc
* Add configuration flag fast sync version
* golangci fixes
* fix config template
* move both reactor versions under blockchain
* cleanup, golint, renaming stuff
* updated documentation, fixed more golint warnings
* integrate with behavior package
* sync with master
* gofmt
* add changelog_pending entry
* move to improvments
* suggestion to changelog entry
2019-07-23 10:58:52 +02:00
|
|
|
|
|
|
|
var bcChannel byte
|
|
|
|
switch config.FastSync.Version {
|
|
|
|
case "v0":
|
|
|
|
bcChannel = bcv0.BlockchainChannel
|
|
|
|
case "v1":
|
|
|
|
bcChannel = bcv1.BlockchainChannel
|
|
|
|
default:
|
|
|
|
return nil, fmt.Errorf("unknown fastsync version %s", config.FastSync.Version)
|
|
|
|
}
|
|
|
|
|
2018-10-12 19:25:33 -04:00
|
|
|
nodeInfo := p2p.DefaultNodeInfo{
|
2019-04-26 08:05:39 -04:00
|
|
|
ProtocolVersion: p2p.NewProtocolVersion(
|
|
|
|
version.P2PProtocol, // global
|
|
|
|
state.Version.Consensus.Block,
|
|
|
|
state.Version.Consensus.App,
|
|
|
|
),
|
|
|
|
ID_: nodeKey.ID(),
|
|
|
|
Network: genDoc.ChainID,
|
|
|
|
Version: version.TMCoreSemVer,
|
2018-06-20 17:35:30 -07:00
|
|
|
Channels: []byte{
|
blockchain: Reorg reactor (#3561)
* go routines in blockchain reactor
* Added reference to the go routine diagram
* Initial commit
* cleanup
* Undo testing_logger change, committed by mistake
* Fix the test loggers
* pulled some fsm code into pool.go
* added pool tests
* changes to the design
added block requests under peer
moved the request trigger in the reactor poolRoutine, triggered now by a ticker
in general moved everything required for making block requests smarter in the poolRoutine
added a simple map of heights to keep track of what will need to be requested next
added a few more tests
* send errors to FSM in a different channel than blocks
send errors (RemovePeer) from switch on a different channel than the
one receiving blocks
renamed channels
added more pool tests
* more pool tests
* lint errors
* more tests
* more tests
* switch fast sync to new implementation
* fixed data race in tests
* cleanup
* finished fsm tests
* address golangci comments :)
* address golangci comments :)
* Added timeout on next block needed to advance
* updating docs and cleanup
* fix issue in test from previous cleanup
* cleanup
* Added termination scenarios, tests and more cleanup
* small fixes to adr, comments and cleanup
* Fix bug in sendRequest()
If we tried to send a request to a peer not present in the switch, a
missing continue statement caused the request to be blackholed in a peer
that was removed and never retried.
While this bug was manifesting, the reactor kept asking for other
blocks that would be stored and never consumed. Added the number of
unconsumed blocks in the math for requesting blocks ahead of current
processing height so eventually there will be no more blocks requested
until the already received ones are consumed.
* remove bpPeer's didTimeout field
* Use distinct err codes for peer timeout and FSM timeouts
* Don't allow peers to update with lower height
* review comments from Ethan and Zarko
* some cleanup, renaming, comments
* Move block execution in separate goroutine
* Remove pool's numPending
* review comments
* fix lint, remove old blockchain reactor and duplicates in fsm tests
* small reorg around peer after review comments
* add the reactor spec
* verify block only once
* review comments
* change to int for max number of pending requests
* cleanup and godoc
* Add configuration flag fast sync version
* golangci fixes
* fix config template
* move both reactor versions under blockchain
* cleanup, golint, renaming stuff
* updated documentation, fixed more golint warnings
* integrate with behavior package
* sync with master
* gofmt
* add changelog_pending entry
* move to improvments
* suggestion to changelog entry
2019-07-23 10:58:52 +02:00
|
|
|
bcChannel,
|
2018-06-20 17:35:30 -07:00
|
|
|
cs.StateChannel, cs.DataChannel, cs.VoteChannel, cs.VoteSetBitsChannel,
|
|
|
|
mempl.MempoolChannel,
|
|
|
|
evidence.EvidenceChannel,
|
|
|
|
},
|
2018-09-18 22:14:40 +02:00
|
|
|
Moniker: config.Moniker,
|
2018-10-12 19:25:33 -04:00
|
|
|
Other: p2p.DefaultNodeInfoOther{
|
2018-10-18 10:29:59 -04:00
|
|
|
TxIndex: txIndexerStatus,
|
|
|
|
RPCAddress: config.RPC.ListenAddress,
|
2018-06-20 17:35:30 -07:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2018-09-18 22:14:40 +02:00
|
|
|
if config.P2P.PexReactor {
|
2018-06-20 17:35:30 -07:00
|
|
|
nodeInfo.Channels = append(nodeInfo.Channels, pex.PexChannel)
|
|
|
|
}
|
|
|
|
|
2018-09-18 22:14:40 +02:00
|
|
|
lAddr := config.P2P.ExternalAddress
|
|
|
|
|
|
|
|
if lAddr == "" {
|
|
|
|
lAddr = config.P2P.ListenAddress
|
2018-06-20 17:35:30 -07:00
|
|
|
}
|
|
|
|
|
2018-09-18 22:14:40 +02:00
|
|
|
nodeInfo.ListenAddr = lAddr
|
2018-06-20 17:35:30 -07:00
|
|
|
|
2018-12-16 09:27:16 -08:00
|
|
|
err := nodeInfo.Validate()
|
2018-12-16 14:05:58 -05:00
|
|
|
return nodeInfo, err
|
2018-06-20 17:35:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
2019-05-30 18:40:17 -04:00
|
|
|
var (
|
|
|
|
genesisDocKey = []byte("genesisDoc")
|
|
|
|
)
|
|
|
|
|
|
|
|
// LoadStateFromDBOrGenesisDocProvider attempts to load the state from the
|
|
|
|
// database, or creates one using the given genesisDocProvider and persists the
|
|
|
|
// result to the database. On success this also returns the genesis doc loaded
|
|
|
|
// through the given provider.
|
|
|
|
func LoadStateFromDBOrGenesisDocProvider(stateDB dbm.DB, genesisDocProvider GenesisDocProvider) (sm.State, *types.GenesisDoc, error) {
|
|
|
|
// Get genesis doc
|
|
|
|
genDoc, err := loadGenesisDoc(stateDB)
|
|
|
|
if err != nil {
|
|
|
|
genDoc, err = genesisDocProvider()
|
|
|
|
if err != nil {
|
|
|
|
return sm.State{}, nil, err
|
|
|
|
}
|
|
|
|
// save genesis doc to prevent a certain class of user errors (e.g. when it
|
|
|
|
// was changed, accidentally or not). Also good for audit trail.
|
|
|
|
saveGenesisDoc(stateDB, genDoc)
|
|
|
|
}
|
|
|
|
state, err := sm.LoadStateFromDBOrGenesisDoc(stateDB, genDoc)
|
|
|
|
if err != nil {
|
|
|
|
return sm.State{}, nil, err
|
|
|
|
}
|
|
|
|
return state, genDoc, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// panics if failed to unmarshal bytes
|
|
|
|
func loadGenesisDoc(db dbm.DB) (*types.GenesisDoc, error) {
|
|
|
|
b := db.Get(genesisDocKey)
|
|
|
|
if len(b) == 0 {
|
|
|
|
return nil, errors.New("Genesis doc not found")
|
|
|
|
}
|
|
|
|
var genDoc *types.GenesisDoc
|
|
|
|
err := cdc.UnmarshalJSON(b, &genDoc)
|
|
|
|
if err != nil {
|
|
|
|
panic(fmt.Sprintf("Failed to load genesis doc due to unmarshaling error: %v (bytes: %X)", err, b))
|
|
|
|
}
|
|
|
|
return genDoc, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// panics if failed to marshal the given genesis document
|
|
|
|
func saveGenesisDoc(db dbm.DB, genDoc *types.GenesisDoc) {
|
|
|
|
b, err := cdc.MarshalJSON(genDoc)
|
|
|
|
if err != nil {
|
|
|
|
panic(fmt.Sprintf("Failed to save genesis doc due to marshaling error: %v", err))
|
|
|
|
}
|
|
|
|
db.SetSync(genesisDocKey, b)
|
|
|
|
}
|
|
|
|
|
2018-11-21 21:24:13 +04:00
|
|
|
func createAndStartPrivValidatorSocketClient(
|
|
|
|
listenAddr string,
|
|
|
|
logger log.Logger,
|
|
|
|
) (types.PrivValidator, error) {
|
2019-08-05 17:09:10 +02:00
|
|
|
pve, err := privval.NewSignerListener(listenAddr, logger)
|
2019-01-13 20:31:31 +01:00
|
|
|
if err != nil {
|
2019-08-05 17:09:10 +02:00
|
|
|
return nil, errors.Wrap(err, "failed to start private validator")
|
2018-11-21 21:24:13 +04:00
|
|
|
}
|
|
|
|
|
2019-08-05 17:09:10 +02:00
|
|
|
pvsc, err := privval.NewSignerClient(pve)
|
|
|
|
if err != nil {
|
2019-01-15 07:55:57 -05:00
|
|
|
return nil, errors.Wrap(err, "failed to start private validator")
|
2018-11-21 21:24:13 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return pvsc, nil
|
|
|
|
}
|
|
|
|
|
2018-09-05 14:13:25 +08:00
|
|
|
// splitAndTrimEmpty slices s into all subslices separated by sep and returns a
|
|
|
|
// slice of the string s with all leading and trailing Unicode code points
|
|
|
|
// contained in cutset removed. If sep is empty, SplitAndTrim splits after each
|
|
|
|
// UTF-8 sequence. First part is equivalent to strings.SplitN with a count of
|
|
|
|
// -1. also filter out empty strings, only return non-empty strings.
|
|
|
|
func splitAndTrimEmpty(s, sep, cutset string) []string {
|
|
|
|
if s == "" {
|
|
|
|
return []string{}
|
|
|
|
}
|
|
|
|
|
|
|
|
spl := strings.Split(s, sep)
|
|
|
|
nonEmptyStrings := make([]string, 0, len(spl))
|
|
|
|
for i := 0; i < len(spl); i++ {
|
|
|
|
element := strings.Trim(spl[i], cutset)
|
|
|
|
if element != "" {
|
|
|
|
nonEmptyStrings = append(nonEmptyStrings, element)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nonEmptyStrings
|
|
|
|
}
|