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.

190 lines
4.7 KiB

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