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.

245 lines
6.7 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
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. "github.com/ebuchman/debora"
  6. bc "github.com/tendermint/tendermint2/blockchain"
  7. . "github.com/tendermint/tendermint2/common"
  8. "github.com/tendermint/tendermint2/config"
  9. "github.com/tendermint/tendermint2/consensus"
  10. dbm "github.com/tendermint/tendermint2/db"
  11. mempl "github.com/tendermint/tendermint2/mempool"
  12. "github.com/tendermint/tendermint2/p2p"
  13. "github.com/tendermint/tendermint2/rpc"
  14. "github.com/tendermint/tendermint2/rpc/core"
  15. sm "github.com/tendermint/tendermint2/state"
  16. )
  17. type Node struct {
  18. lz []p2p.Listener
  19. sw *p2p.Switch
  20. book *p2p.AddrBook
  21. blockStore *bc.BlockStore
  22. pexReactor *p2p.PEXReactor
  23. bcReactor *bc.BlockchainReactor
  24. mempoolReactor *mempl.MempoolReactor
  25. consensusState *consensus.ConsensusState
  26. consensusReactor *consensus.ConsensusReactor
  27. privValidator *sm.PrivValidator
  28. }
  29. func NewNode() *Node {
  30. // Get BlockStore
  31. blockStoreDB := dbm.GetDB("blockstore")
  32. blockStore := bc.NewBlockStore(blockStoreDB)
  33. // Get State
  34. stateDB := dbm.GetDB("state")
  35. state := sm.LoadState(stateDB)
  36. if state == nil {
  37. state = sm.MakeGenesisStateFromFile(stateDB, config.App().GetString("GenesisFile"))
  38. state.Save()
  39. }
  40. // Get PrivValidator
  41. var privValidator *sm.PrivValidator
  42. if _, err := os.Stat(config.App().GetString("PrivValidatorFile")); err == nil {
  43. privValidator = sm.LoadPrivValidator(config.App().GetString("PrivValidatorFile"))
  44. log.Info("Loaded PrivValidator", "file", config.App().GetString("PrivValidatorFile"), "privValidator", privValidator)
  45. } else {
  46. log.Info("No PrivValidator found", "file", config.App().GetString("PrivValidatorFile"))
  47. }
  48. // Get PEXReactor
  49. book := p2p.NewAddrBook(config.App().GetString("AddrBookFile"))
  50. pexReactor := p2p.NewPEXReactor(book)
  51. // Get BlockchainReactor
  52. bcReactor := bc.NewBlockchainReactor(state, blockStore, config.App().GetBool("FastSync"))
  53. // Get MempoolReactor
  54. mempool := mempl.NewMempool(state.Copy())
  55. mempoolReactor := mempl.NewMempoolReactor(mempool)
  56. // Get ConsensusReactor
  57. consensusState := consensus.NewConsensusState(state, blockStore, mempoolReactor)
  58. consensusReactor := consensus.NewConsensusReactor(consensusState, blockStore)
  59. if privValidator != nil {
  60. consensusReactor.SetPrivValidator(privValidator)
  61. }
  62. sw := p2p.NewSwitch()
  63. sw.SetNetwork(config.App().GetString("Network"))
  64. sw.AddReactor("PEX", pexReactor)
  65. sw.AddReactor("MEMPOOL", mempoolReactor)
  66. sw.AddReactor("BLOCKCHAIN", bcReactor)
  67. sw.AddReactor("CONSENSUS", consensusReactor)
  68. return &Node{
  69. sw: sw,
  70. book: book,
  71. blockStore: blockStore,
  72. pexReactor: pexReactor,
  73. bcReactor: bcReactor,
  74. mempoolReactor: mempoolReactor,
  75. consensusState: consensusState,
  76. consensusReactor: consensusReactor,
  77. privValidator: privValidator,
  78. }
  79. }
  80. func (n *Node) Start() {
  81. log.Info("Starting Node")
  82. for _, l := range n.lz {
  83. go n.inboundConnectionRoutine(l)
  84. }
  85. n.book.Start()
  86. //n.sw.StartReactors()...
  87. n.sw.Reactor("PEX").Start(n.sw)
  88. n.sw.Reactor("MEMPOOL").Start(n.sw)
  89. n.sw.Reactor("BLOCKCHAIN").Start(n.sw)
  90. if !config.App().GetBool("FastSync") {
  91. n.sw.Reactor("CONSENSUS").Start(n.sw)
  92. }
  93. }
  94. func (n *Node) Stop() {
  95. log.Info("Stopping Node")
  96. // TODO: gracefully disconnect from peers.
  97. n.sw.Stop()
  98. n.book.Stop()
  99. }
  100. // Add a Listener to accept inbound peer connections.
  101. func (n *Node) AddListener(l p2p.Listener) {
  102. log.Info(Fmt("Added %v", l))
  103. n.lz = append(n.lz, l)
  104. n.book.AddOurAddress(l.ExternalAddress())
  105. }
  106. func (n *Node) inboundConnectionRoutine(l p2p.Listener) {
  107. for {
  108. inConn, ok := <-l.Connections()
  109. if !ok {
  110. break
  111. }
  112. // New inbound connection!
  113. peer, err := n.sw.AddPeerWithConnection(inConn, false)
  114. if err != nil {
  115. log.Info("Ignoring error from inbound connection: %v\n%v",
  116. peer, err)
  117. continue
  118. }
  119. // NOTE: We don't yet have the external address of the
  120. // remote (if they have a listener at all).
  121. // PEXReactor's pexRoutine will handle that.
  122. }
  123. // cleanup
  124. }
  125. func (n *Node) DialSeed() {
  126. addr := p2p.NewNetAddressString(config.App().GetString("SeedNode"))
  127. peer, err := n.sw.DialPeerWithAddress(addr)
  128. if err != nil {
  129. log.Error("Error dialing seed", "error", err)
  130. //n.book.MarkAttempt(addr)
  131. return
  132. } else {
  133. log.Info("Connected to seed", "peer", peer)
  134. n.book.AddAddress(addr, addr)
  135. }
  136. }
  137. func (n *Node) StartRPC() {
  138. core.SetBlockStore(n.blockStore)
  139. core.SetConsensusState(n.consensusState)
  140. core.SetMempoolReactor(n.mempoolReactor)
  141. core.SetSwitch(n.sw)
  142. rpc.StartHTTPServer()
  143. }
  144. func (n *Node) Switch() *p2p.Switch {
  145. return n.sw
  146. }
  147. func (n *Node) ConsensusState() *consensus.ConsensusState {
  148. return n.consensusState
  149. }
  150. func (n *Node) MempoolReactor() *mempl.MempoolReactor {
  151. return n.mempoolReactor
  152. }
  153. // debora variables
  154. var (
  155. AppName = "tendermint"
  156. SrcPath = "github.com/tendermint/tendermint2/cmd"
  157. PublicKey = "30820122300d06092a864886f70d01010105000382010f003082010a0282010100dd861e9cd5a3f3fc27d46531aa9d87f5b63f6358fa00397482c4ab93abf4ab2e3ed75380fc714d52b5e80afc184f21d5732f2d6dacc23f0e802e585ee005347c2af0ad992ee5c11b2a96f72bcae78bef314ba4448b33c3a1df7a4d6e6a808d21dfeb67ef974c0357ba54649dbcd92ec2a8d3a510da747e70cb859a7f9b15a6eceb2179c225afd3f8fb15be38988f9b82622d855f343af5830ca30a5beff3905b618f6cc39142a60ff5840595265a1f7b9fbd504760667a1b2508097c1831fd13f54c794a08468d65db9e27aff0a889665ebd7de4a6e9a6c09b3811b6cda623be48e1214ba0f9b378441e2a02b3891bc8ec1ae7081988e15c2f53fa6512784b390203010001"
  158. DeboraCallPort = 56565
  159. )
  160. type DeboraMode int
  161. const (
  162. DeboraPeerMode DeboraMode = iota
  163. DeboraDevMode
  164. )
  165. func deboraBroadcast(n *Node) func([]byte) {
  166. return func(payload []byte) {
  167. msg := &p2p.PexDeboraMessage{Payload: payload}
  168. n.sw.Broadcast(p2p.PexChannel, msg)
  169. }
  170. }
  171. func Daemon(deborable DeboraMode) {
  172. // Add to debora
  173. if deborable == DeboraPeerMode {
  174. if err := debora.Add(PublicKey, SrcPath, AppName, config.App().GetString("Debora.LogFile")); err != nil {
  175. log.Info("Failed to add program to debora", "error", err)
  176. }
  177. }
  178. // Create & start node
  179. n := NewNode()
  180. l := p2p.NewDefaultListener("tcp", config.App().GetString("ListenAddr"), false)
  181. n.AddListener(l)
  182. n.Start()
  183. if deborable == DeboraDevMode {
  184. log.Info("Running debora-dev server (listen to call)")
  185. debora.DebListenAndServe("tendermint", DeboraCallPort, deboraBroadcast(n))
  186. }
  187. // If seedNode is provided by config, dial out.
  188. if config.App().GetString("SeedNode") != "" {
  189. n.DialSeed()
  190. }
  191. // Run the RPC server.
  192. if config.App().GetString("RPC.HTTP.ListenAddr") != "" {
  193. n.StartRPC()
  194. }
  195. // Sleep forever and then...
  196. trapSignal(func() {
  197. n.Stop()
  198. })
  199. }
  200. func trapSignal(cb func()) {
  201. c := make(chan os.Signal, 1)
  202. signal.Notify(c, os.Interrupt)
  203. go func() {
  204. for sig := range c {
  205. log.Info(Fmt("captured %v, exiting..", sig))
  206. cb()
  207. os.Exit(1)
  208. }
  209. }()
  210. select {}
  211. }