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.

172 lines
4.4 KiB

10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 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
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
11 years ago
  1. package main
  2. import (
  3. "os"
  4. "os/signal"
  5. "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 *block.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 := block.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. return &Node{
  59. sw: sw,
  60. book: book,
  61. pexReactor: pexReactor,
  62. blockStore: blockStore,
  63. mempoolReactor: mempoolReactor,
  64. consensusState: consensusState,
  65. consensusReactor: consensusReactor,
  66. privValidator: privValidator,
  67. }
  68. }
  69. func (n *Node) Start() {
  70. log.Info("Starting Node")
  71. for _, l := range n.lz {
  72. go n.inboundConnectionRoutine(l)
  73. }
  74. n.book.Start()
  75. n.sw.Start()
  76. }
  77. func (n *Node) Stop() {
  78. log.Info("Stopping Node")
  79. // TODO: gracefully disconnect from peers.
  80. n.sw.Stop()
  81. n.book.Stop()
  82. }
  83. // Add a Listener to accept inbound peer connections.
  84. func (n *Node) AddListener(l p2p.Listener) {
  85. log.Info(Fmt("Added %v", l))
  86. n.lz = append(n.lz, l)
  87. n.book.AddOurAddress(l.ExternalAddress())
  88. }
  89. func (n *Node) inboundConnectionRoutine(l p2p.Listener) {
  90. for {
  91. inConn, ok := <-l.Connections()
  92. if !ok {
  93. break
  94. }
  95. // New inbound connection!
  96. peer, err := n.sw.AddPeerWithConnection(inConn, false)
  97. if err != nil {
  98. log.Info("Ignoring error from inbound connection: %v\n%v",
  99. peer, err)
  100. continue
  101. }
  102. // NOTE: We don't yet have the external address of the
  103. // remote (if they have a listener at all).
  104. // PEXReactor's pexRoutine will handle that.
  105. }
  106. // cleanup
  107. }
  108. func daemon() {
  109. // Create & start node
  110. n := NewNode()
  111. l := p2p.NewDefaultListener("tcp", config.App.GetString("ListenAddr"), false)
  112. n.AddListener(l)
  113. n.Start()
  114. // If seedNode is provided by config, dial out.
  115. if config.App.GetString("SeedNode") != "" {
  116. addr := p2p.NewNetAddressString(config.App.GetString("SeedNode"))
  117. peer, err := n.sw.DialPeerWithAddress(addr)
  118. if err != nil {
  119. log.Error("Error dialing seed", "error", err)
  120. //n.book.MarkAttempt(addr)
  121. return
  122. } else {
  123. log.Info("Connected to seed", "peer", peer)
  124. n.book.AddAddress(addr, addr)
  125. }
  126. }
  127. // Run the RPC server.
  128. if config.App.GetString("RPC.HTTP.ListenAddr") != "" {
  129. rpc.SetRPCBlockStore(n.blockStore)
  130. rpc.SetRPCConsensusState(n.consensusState)
  131. rpc.SetRPCMempoolReactor(n.mempoolReactor)
  132. rpc.StartHTTPServer()
  133. }
  134. // Sleep forever and then...
  135. trapSignal(func() {
  136. n.Stop()
  137. })
  138. }
  139. func trapSignal(cb func()) {
  140. c := make(chan os.Signal, 1)
  141. signal.Notify(c, os.Interrupt)
  142. go func() {
  143. for sig := range c {
  144. log.Info(Fmt("captured %v, exiting..", sig))
  145. cb()
  146. os.Exit(1)
  147. }
  148. }()
  149. select {}
  150. }