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.

268 lines
7.0 KiB

9 years ago
9 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
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. package node
  2. import (
  3. "fmt"
  4. "math/rand"
  5. "net"
  6. "net/http"
  7. "os"
  8. "strconv"
  9. "strings"
  10. "time"
  11. bc "github.com/tendermint/tendermint/blockchain"
  12. . "github.com/tendermint/tendermint/common"
  13. "github.com/tendermint/tendermint/consensus"
  14. dbm "github.com/tendermint/tendermint/db"
  15. "github.com/tendermint/tendermint/events"
  16. mempl "github.com/tendermint/tendermint/mempool"
  17. "github.com/tendermint/tendermint/p2p"
  18. "github.com/tendermint/tendermint/rpc/core"
  19. "github.com/tendermint/tendermint/rpc/server"
  20. sm "github.com/tendermint/tendermint/state"
  21. "github.com/tendermint/tendermint/types"
  22. )
  23. import _ "net/http/pprof"
  24. func init() {
  25. go func() {
  26. fmt.Println(http.ListenAndServe("0.0.0.0:6060", nil))
  27. }()
  28. }
  29. type Node struct {
  30. sw *p2p.Switch
  31. evsw *events.EventSwitch
  32. book *p2p.AddrBook
  33. blockStore *bc.BlockStore
  34. pexReactor *p2p.PEXReactor
  35. bcReactor *bc.BlockchainReactor
  36. mempoolReactor *mempl.MempoolReactor
  37. consensusState *consensus.ConsensusState
  38. consensusReactor *consensus.ConsensusReactor
  39. privValidator *sm.PrivValidator
  40. }
  41. func NewNode() *Node {
  42. // Get BlockStore
  43. blockStoreDB := dbm.GetDB("blockstore")
  44. blockStore := bc.NewBlockStore(blockStoreDB)
  45. // Get State
  46. stateDB := dbm.GetDB("state")
  47. state := sm.LoadState(stateDB)
  48. if state == nil {
  49. state = sm.MakeGenesisStateFromFile(stateDB, config.GetString("genesis_file"))
  50. state.Save()
  51. }
  52. // Get PrivValidator
  53. var privValidator *sm.PrivValidator
  54. privValidatorFile := config.GetString("priv_validator_file")
  55. if _, err := os.Stat(privValidatorFile); err == nil {
  56. privValidator = sm.LoadPrivValidator(privValidatorFile)
  57. log.Info("Loaded PrivValidator",
  58. "file", privValidatorFile, "privValidator", privValidator)
  59. } else {
  60. privValidator = sm.GenPrivValidator()
  61. privValidator.SetFile(privValidatorFile)
  62. privValidator.Save()
  63. log.Info("Generated PrivValidator", "file", privValidatorFile)
  64. }
  65. eventSwitch := new(events.EventSwitch)
  66. eventSwitch.Start()
  67. // Get PEXReactor
  68. book := p2p.NewAddrBook(config.GetString("addrbook_file"))
  69. pexReactor := p2p.NewPEXReactor(book)
  70. // Get BlockchainReactor
  71. bcReactor := bc.NewBlockchainReactor(state, blockStore, config.GetBool("fast_sync"))
  72. // Get MempoolReactor
  73. mempool := mempl.NewMempool(state.Copy())
  74. mempoolReactor := mempl.NewMempoolReactor(mempool)
  75. // Get ConsensusReactor
  76. consensusState := consensus.NewConsensusState(state, blockStore, mempoolReactor)
  77. consensusReactor := consensus.NewConsensusReactor(consensusState, blockStore)
  78. if privValidator != nil {
  79. consensusReactor.SetPrivValidator(privValidator)
  80. }
  81. // so the consensus reactor won't do anything until we're synced
  82. if config.GetBool("fast_sync") {
  83. consensusReactor.SetSyncing(true)
  84. }
  85. sw := p2p.NewSwitch()
  86. sw.AddReactor("PEX", pexReactor)
  87. sw.AddReactor("MEMPOOL", mempoolReactor)
  88. sw.AddReactor("BLOCKCHAIN", bcReactor)
  89. sw.AddReactor("CONSENSUS", consensusReactor)
  90. // add the event switch to all services
  91. // they should all satisfy events.Eventable
  92. SetFireable(eventSwitch, pexReactor, bcReactor, mempoolReactor, consensusReactor)
  93. return &Node{
  94. sw: sw,
  95. evsw: eventSwitch,
  96. book: book,
  97. blockStore: blockStore,
  98. pexReactor: pexReactor,
  99. bcReactor: bcReactor,
  100. mempoolReactor: mempoolReactor,
  101. consensusState: consensusState,
  102. consensusReactor: consensusReactor,
  103. privValidator: privValidator,
  104. }
  105. }
  106. // Call Start() after adding the listeners.
  107. func (n *Node) Start() {
  108. log.Info("Starting Node")
  109. n.book.Start()
  110. nodeInfo := makeNodeInfo(n.sw)
  111. n.sw.SetNodeInfo(nodeInfo)
  112. n.sw.Start()
  113. }
  114. func (n *Node) Stop() {
  115. log.Info("Stopping Node")
  116. // TODO: gracefully disconnect from peers.
  117. n.sw.Stop()
  118. n.book.Stop()
  119. }
  120. // Add the event switch to reactors, mempool, etc.
  121. func SetFireable(evsw *events.EventSwitch, eventables ...events.Eventable) {
  122. for _, e := range eventables {
  123. e.SetFireable(evsw)
  124. }
  125. }
  126. // Add a Listener to accept inbound peer connections.
  127. // Add listeners before starting the Node.
  128. // The first listener is the primary listener (in NodeInfo)
  129. func (n *Node) AddListener(l p2p.Listener) {
  130. log.Info(Fmt("Added %v", l))
  131. n.sw.AddListener(l)
  132. n.book.AddOurAddress(l.ExternalAddress())
  133. }
  134. // NOTE: Blocking
  135. func (n *Node) DialSeed() {
  136. // permute the list, dial them in random order.
  137. seeds := strings.Split(config.GetString("seeds"), ",")
  138. perm := rand.Perm(len(seeds))
  139. for i := 0; i < len(perm); i++ {
  140. go func(i int) {
  141. time.Sleep(time.Duration(rand.Int63n(3000)) * time.Millisecond)
  142. j := perm[i]
  143. addr := p2p.NewNetAddressString(seeds[j])
  144. n.dialSeed(addr)
  145. }(i)
  146. }
  147. }
  148. func (n *Node) dialSeed(addr *p2p.NetAddress) {
  149. peer, err := n.sw.DialPeerWithAddress(addr)
  150. if err != nil {
  151. log.Error("Error dialing seed", "error", err)
  152. //n.book.MarkAttempt(addr)
  153. return
  154. } else {
  155. log.Info("Connected to seed", "peer", peer)
  156. n.book.AddAddress(addr, addr)
  157. }
  158. }
  159. func (n *Node) StartRPC() {
  160. core.SetBlockStore(n.blockStore)
  161. core.SetConsensusState(n.consensusState)
  162. core.SetConsensusReactor(n.consensusReactor)
  163. core.SetMempoolReactor(n.mempoolReactor)
  164. core.SetSwitch(n.sw)
  165. core.SetPrivValidator(n.privValidator)
  166. listenAddr := config.GetString("rpc_laddr")
  167. mux := http.NewServeMux()
  168. rpcserver.RegisterEventsHandler(mux, n.evsw)
  169. rpcserver.RegisterRPCFuncs(mux, core.Routes)
  170. rpcserver.StartHTTPServer(listenAddr, mux)
  171. }
  172. func (n *Node) Switch() *p2p.Switch {
  173. return n.sw
  174. }
  175. func (n *Node) BlockStore() *bc.BlockStore {
  176. return n.blockStore
  177. }
  178. func (n *Node) ConsensusState() *consensus.ConsensusState {
  179. return n.consensusState
  180. }
  181. func (n *Node) MempoolReactor() *mempl.MempoolReactor {
  182. return n.mempoolReactor
  183. }
  184. func (n *Node) EventSwitch() *events.EventSwitch {
  185. return n.evsw
  186. }
  187. func makeNodeInfo(sw *p2p.Switch) *types.NodeInfo {
  188. nodeInfo := &types.NodeInfo{
  189. Network: config.GetString("network"),
  190. Moniker: config.GetString("moniker"),
  191. Version: config.GetString("version"),
  192. }
  193. if !sw.IsListening() {
  194. return nodeInfo
  195. }
  196. p2pListener := sw.Listeners()[0]
  197. p2pHost := p2pListener.ExternalAddress().IP.String()
  198. p2pPort := p2pListener.ExternalAddress().Port
  199. rpcListenAddr := config.GetString("rpc_laddr")
  200. _, rpcPortStr, _ := net.SplitHostPort(rpcListenAddr)
  201. rpcPort, err := strconv.Atoi(rpcPortStr)
  202. if err != nil {
  203. panic(Fmt("Expected numeric RPC.ListenAddr port but got %v", rpcPortStr))
  204. }
  205. // We assume that the rpcListener has the same ExternalAddress.
  206. // This is probably true because both P2P and RPC listeners use UPnP.
  207. nodeInfo.Host = p2pHost
  208. nodeInfo.P2PPort = p2pPort
  209. nodeInfo.RPCPort = uint16(rpcPort)
  210. return nodeInfo
  211. }
  212. //------------------------------------------------------------------------------
  213. func RunNode() {
  214. // Create & start node
  215. n := NewNode()
  216. l := p2p.NewDefaultListener("tcp", config.GetString("node_laddr"), false)
  217. n.AddListener(l)
  218. n.Start()
  219. // If seedNode is provided by config, dial out.
  220. if len(config.GetString("seeds")) > 0 {
  221. n.DialSeed()
  222. }
  223. // Run the RPC server.
  224. if config.GetString("rpc_laddr") != "" {
  225. n.StartRPC()
  226. }
  227. // Sleep forever and then...
  228. TrapSignal(func() {
  229. n.Stop()
  230. })
  231. }