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.

263 lines
6.9 KiB

10 years ago
10 years ago
10 years ago
10 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
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
  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, config.GetBool("fast_sync"))
  78. if privValidator != nil {
  79. consensusReactor.SetPrivValidator(privValidator)
  80. }
  81. sw := p2p.NewSwitch()
  82. sw.AddReactor("PEX", pexReactor)
  83. sw.AddReactor("MEMPOOL", mempoolReactor)
  84. sw.AddReactor("BLOCKCHAIN", bcReactor)
  85. sw.AddReactor("CONSENSUS", consensusReactor)
  86. // add the event switch to all services
  87. // they should all satisfy events.Eventable
  88. SetFireable(eventSwitch, pexReactor, bcReactor, mempoolReactor, consensusReactor)
  89. return &Node{
  90. sw: sw,
  91. evsw: eventSwitch,
  92. book: book,
  93. blockStore: blockStore,
  94. pexReactor: pexReactor,
  95. bcReactor: bcReactor,
  96. mempoolReactor: mempoolReactor,
  97. consensusState: consensusState,
  98. consensusReactor: consensusReactor,
  99. privValidator: privValidator,
  100. }
  101. }
  102. // Call Start() after adding the listeners.
  103. func (n *Node) Start() {
  104. log.Info("Starting Node")
  105. n.book.Start()
  106. nodeInfo := makeNodeInfo(n.sw)
  107. n.sw.SetNodeInfo(nodeInfo)
  108. n.sw.Start()
  109. }
  110. func (n *Node) Stop() {
  111. log.Info("Stopping Node")
  112. // TODO: gracefully disconnect from peers.
  113. n.sw.Stop()
  114. n.book.Stop()
  115. }
  116. // Add the event switch to reactors, mempool, etc.
  117. func SetFireable(evsw *events.EventSwitch, eventables ...events.Eventable) {
  118. for _, e := range eventables {
  119. e.SetFireable(evsw)
  120. }
  121. }
  122. // Add a Listener to accept inbound peer connections.
  123. // Add listeners before starting the Node.
  124. // The first listener is the primary listener (in NodeInfo)
  125. func (n *Node) AddListener(l p2p.Listener) {
  126. log.Info(Fmt("Added %v", l))
  127. n.sw.AddListener(l)
  128. n.book.AddOurAddress(l.ExternalAddress())
  129. }
  130. // NOTE: Blocking
  131. func (n *Node) DialSeed() {
  132. // permute the list, dial them in random order.
  133. seeds := strings.Split(config.GetString("seeds"), ",")
  134. perm := rand.Perm(len(seeds))
  135. for i := 0; i < len(perm); i++ {
  136. go func(i int) {
  137. time.Sleep(time.Duration(rand.Int63n(3000)) * time.Millisecond)
  138. j := perm[i]
  139. addr := p2p.NewNetAddressString(seeds[j])
  140. n.dialSeed(addr)
  141. }(i)
  142. }
  143. }
  144. func (n *Node) dialSeed(addr *p2p.NetAddress) {
  145. peer, err := n.sw.DialPeerWithAddress(addr)
  146. if err != nil {
  147. log.Error("Error dialing seed", "error", err)
  148. //n.book.MarkAttempt(addr)
  149. return
  150. } else {
  151. log.Info("Connected to seed", "peer", peer)
  152. n.book.AddAddress(addr, addr)
  153. }
  154. }
  155. func (n *Node) StartRPC() {
  156. core.SetBlockStore(n.blockStore)
  157. core.SetConsensusState(n.consensusState)
  158. core.SetConsensusReactor(n.consensusReactor)
  159. core.SetMempoolReactor(n.mempoolReactor)
  160. core.SetSwitch(n.sw)
  161. core.SetPrivValidator(n.privValidator)
  162. listenAddr := config.GetString("rpc_laddr")
  163. mux := http.NewServeMux()
  164. rpcserver.RegisterEventsHandler(mux, n.evsw)
  165. rpcserver.RegisterRPCFuncs(mux, core.Routes)
  166. rpcserver.StartHTTPServer(listenAddr, mux)
  167. }
  168. func (n *Node) Switch() *p2p.Switch {
  169. return n.sw
  170. }
  171. func (n *Node) BlockStore() *bc.BlockStore {
  172. return n.blockStore
  173. }
  174. func (n *Node) ConsensusState() *consensus.ConsensusState {
  175. return n.consensusState
  176. }
  177. func (n *Node) MempoolReactor() *mempl.MempoolReactor {
  178. return n.mempoolReactor
  179. }
  180. func (n *Node) EventSwitch() *events.EventSwitch {
  181. return n.evsw
  182. }
  183. func makeNodeInfo(sw *p2p.Switch) *types.NodeInfo {
  184. nodeInfo := &types.NodeInfo{
  185. Network: config.GetString("network"),
  186. Moniker: config.GetString("moniker"),
  187. Version: config.GetString("version"),
  188. }
  189. if !sw.IsListening() {
  190. return nodeInfo
  191. }
  192. p2pListener := sw.Listeners()[0]
  193. p2pHost := p2pListener.ExternalAddress().IP.String()
  194. p2pPort := p2pListener.ExternalAddress().Port
  195. rpcListenAddr := config.GetString("rpc_laddr")
  196. _, rpcPortStr, _ := net.SplitHostPort(rpcListenAddr)
  197. rpcPort, err := strconv.Atoi(rpcPortStr)
  198. if err != nil {
  199. panic(Fmt("Expected numeric RPC.ListenAddr port but got %v", rpcPortStr))
  200. }
  201. // We assume that the rpcListener has the same ExternalAddress.
  202. // This is probably true because both P2P and RPC listeners use UPnP.
  203. nodeInfo.Host = p2pHost
  204. nodeInfo.P2PPort = p2pPort
  205. nodeInfo.RPCPort = uint16(rpcPort)
  206. return nodeInfo
  207. }
  208. //------------------------------------------------------------------------------
  209. func RunNode() {
  210. // Create & start node
  211. n := NewNode()
  212. l := p2p.NewDefaultListener("tcp", config.GetString("node_laddr"), false)
  213. n.AddListener(l)
  214. n.Start()
  215. // If seedNode is provided by config, dial out.
  216. if len(config.GetString("seeds")) > 0 {
  217. n.DialSeed()
  218. }
  219. // Run the RPC server.
  220. if config.GetString("rpc_laddr") != "" {
  221. n.StartRPC()
  222. }
  223. // Sleep forever and then...
  224. TrapSignal(func() {
  225. n.Stop()
  226. })
  227. }