You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

203 lines
5.2 KiB

10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
  1. package daemon
  2. import (
  3. "os"
  4. "os/signal"
  5. bc "github.com/tendermint/tendermint/blockchain"
  6. . "github.com/tendermint/tendermint/common"
  7. "github.com/tendermint/tendermint/config"
  8. "github.com/tendermint/tendermint/consensus"
  9. dbm "github.com/tendermint/tendermint/db"
  10. mempl "github.com/tendermint/tendermint/mempool"
  11. "github.com/tendermint/tendermint/p2p"
  12. "github.com/tendermint/tendermint/rpc"
  13. sm "github.com/tendermint/tendermint/state"
  14. )
  15. type Node struct {
  16. lz []p2p.Listener
  17. sw *p2p.Switch
  18. book *p2p.AddrBook
  19. blockStore *bc.BlockStore
  20. pexReactor *p2p.PEXReactor
  21. bcReactor *bc.BlockchainReactor
  22. mempoolReactor *mempl.MempoolReactor
  23. consensusState *consensus.ConsensusState
  24. consensusReactor *consensus.ConsensusReactor
  25. privValidator *sm.PrivValidator
  26. }
  27. func NewNode() *Node {
  28. // Get BlockStore
  29. blockStoreDB := dbm.GetDB("blockstore")
  30. blockStore := bc.NewBlockStore(blockStoreDB)
  31. // Get State
  32. stateDB := dbm.GetDB("state")
  33. state := sm.LoadState(stateDB)
  34. if state == nil {
  35. state = sm.MakeGenesisStateFromFile(stateDB, config.App().GetString("GenesisFile"))
  36. state.Save()
  37. }
  38. // Get PrivValidator
  39. var privValidator *sm.PrivValidator
  40. if _, err := os.Stat(config.App().GetString("PrivValidatorFile")); err == nil {
  41. privValidator = sm.LoadPrivValidator(config.App().GetString("PrivValidatorFile"))
  42. log.Info("Loaded PrivValidator", "file", config.App().GetString("PrivValidatorFile"), "privValidator", privValidator)
  43. } else {
  44. log.Info("No PrivValidator found", "file", config.App().GetString("PrivValidatorFile"))
  45. }
  46. // Get PEXReactor
  47. book := p2p.NewAddrBook(config.App().GetString("AddrBookFile"))
  48. pexReactor := p2p.NewPEXReactor(book)
  49. // Get BlockchainReactor
  50. bcReactor := bc.NewBlockchainReactor(state, blockStore, config.App().GetBool("FastSync"))
  51. // Get MempoolReactor
  52. mempool := mempl.NewMempool(state.Copy())
  53. mempoolReactor := mempl.NewMempoolReactor(mempool)
  54. // Get ConsensusReactor
  55. consensusState := consensus.NewConsensusState(state, blockStore, mempoolReactor)
  56. consensusReactor := consensus.NewConsensusReactor(consensusState, blockStore)
  57. if privValidator != nil {
  58. consensusReactor.SetPrivValidator(privValidator)
  59. }
  60. sw := p2p.NewSwitch()
  61. sw.SetNetwork(config.App().GetString("Network"))
  62. sw.AddReactor("PEX", pexReactor).Start(sw)
  63. sw.AddReactor("MEMPOOL", mempoolReactor).Start(sw)
  64. sw.AddReactor("BLOCKCHAIN", bcReactor).Start(sw)
  65. if !config.App().GetBool("FastSync") {
  66. sw.AddReactor("CONSENSUS", consensusReactor).Start(sw)
  67. } else {
  68. sw.AddReactor("CONSENSUS", consensusReactor)
  69. }
  70. return &Node{
  71. sw: sw,
  72. book: book,
  73. blockStore: blockStore,
  74. pexReactor: pexReactor,
  75. bcReactor: bcReactor,
  76. mempoolReactor: mempoolReactor,
  77. consensusState: consensusState,
  78. consensusReactor: consensusReactor,
  79. privValidator: privValidator,
  80. }
  81. }
  82. func (n *Node) Start() {
  83. log.Info("Starting Node")
  84. for _, l := range n.lz {
  85. go n.inboundConnectionRoutine(l)
  86. }
  87. n.book.Start()
  88. //n.sw.StartReactors()
  89. }
  90. func (n *Node) Stop() {
  91. log.Info("Stopping Node")
  92. // TODO: gracefully disconnect from peers.
  93. n.sw.Stop()
  94. n.book.Stop()
  95. }
  96. // Add a Listener to accept inbound peer connections.
  97. func (n *Node) AddListener(l p2p.Listener) {
  98. log.Info(Fmt("Added %v", l))
  99. n.lz = append(n.lz, l)
  100. n.book.AddOurAddress(l.ExternalAddress())
  101. }
  102. func (n *Node) inboundConnectionRoutine(l p2p.Listener) {
  103. for {
  104. inConn, ok := <-l.Connections()
  105. if !ok {
  106. break
  107. }
  108. // New inbound connection!
  109. peer, err := n.sw.AddPeerWithConnection(inConn, false)
  110. if err != nil {
  111. log.Info("Ignoring error from inbound connection: %v\n%v",
  112. peer, err)
  113. continue
  114. }
  115. // NOTE: We don't yet have the external address of the
  116. // remote (if they have a listener at all).
  117. // PEXReactor's pexRoutine will handle that.
  118. }
  119. // cleanup
  120. }
  121. func (n *Node) DialSeed() {
  122. addr := p2p.NewNetAddressString(config.App().GetString("SeedNode"))
  123. peer, err := n.sw.DialPeerWithAddress(addr)
  124. if err != nil {
  125. log.Error("Error dialing seed", "error", err)
  126. //n.book.MarkAttempt(addr)
  127. return
  128. } else {
  129. log.Info("Connected to seed", "peer", peer)
  130. n.book.AddAddress(addr, addr)
  131. }
  132. }
  133. func (n *Node) StartRpc() {
  134. rpc.SetRPCBlockStore(n.blockStore)
  135. rpc.SetRPCConsensusState(n.consensusState)
  136. rpc.SetRPCMempoolReactor(n.mempoolReactor)
  137. rpc.SetRPCSwitch(n.sw)
  138. rpc.StartHTTPServer()
  139. }
  140. func (n *Node) ConsensusState() *consensus.ConsensusState {
  141. return n.consensusState
  142. }
  143. func (n *Node) MempoolReactor() *mempl.MempoolReactor {
  144. return n.mempoolReactor
  145. }
  146. func Daemon() {
  147. // Create & start node
  148. n := NewNode()
  149. l := p2p.NewDefaultListener("tcp", config.App().GetString("ListenAddr"), false)
  150. n.AddListener(l)
  151. n.Start()
  152. // If seedNode is provided by config, dial out.
  153. if config.App().GetString("SeedNode") != "" {
  154. n.DialSeed()
  155. }
  156. // Run the RPC server.
  157. if config.App().GetString("RPC.HTTP.ListenAddr") != "" {
  158. n.StartRpc()
  159. }
  160. // Sleep forever and then...
  161. trapSignal(func() {
  162. n.Stop()
  163. })
  164. }
  165. func trapSignal(cb func()) {
  166. c := make(chan os.Signal, 1)
  167. signal.Notify(c, os.Interrupt)
  168. go func() {
  169. for sig := range c {
  170. log.Info(Fmt("captured %v, exiting..", sig))
  171. cb()
  172. os.Exit(1)
  173. }
  174. }()
  175. select {}
  176. }