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.

160 lines
3.9 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
  1. // +build tendermintd
  2. package main
  3. import (
  4. "os"
  5. "os/signal"
  6. "github.com/tendermint/tendermint/blocks"
  7. "github.com/tendermint/tendermint/config"
  8. "github.com/tendermint/tendermint/consensus"
  9. db_ "github.com/tendermint/tendermint/db"
  10. mempool_ "github.com/tendermint/tendermint/mempool"
  11. "github.com/tendermint/tendermint/p2p"
  12. state_ "github.com/tendermint/tendermint/state"
  13. )
  14. type Node struct {
  15. lz []p2p.Listener
  16. sw *p2p.Switch
  17. book *p2p.AddrBook
  18. pexReactor *p2p.PEXReactor
  19. mempoolReactor *mempool_.MempoolReactor
  20. consensusReactor *consensus.ConsensusReactor
  21. privValidator *consensus.PrivValidator
  22. }
  23. func NewNode() *Node {
  24. // Get BlockStore
  25. blockStoreDB := db_.NewMemDB() // TODO configurable db.
  26. blockStore := blocks.NewBlockStore(blockStoreDB)
  27. // Get State
  28. stateDB := db_.NewMemDB() // TODO configurable db.
  29. state := state_.LoadState(stateDB)
  30. if state == nil {
  31. state = state_.GenesisStateFromFile(stateDB, config.RootDir+"/genesis.json")
  32. }
  33. // Get PrivAccount
  34. var privValidator *consensus.PrivValidator
  35. if _, err := os.Stat(config.RootDir + "/private.json"); os.IsExist(err) {
  36. privAccount := state_.PrivAccountFromFile(config.RootDir + "/private.json")
  37. privValidatorDB := db_.NewMemDB() // TODO configurable db.
  38. privValidator = consensus.NewPrivValidator(privValidatorDB, privAccount)
  39. }
  40. // Get PEXReactor
  41. book := p2p.NewAddrBook(config.RootDir + "/addrbook.json")
  42. pexReactor := p2p.NewPEXReactor(book)
  43. // Get MempoolReactor
  44. mempool := mempool_.NewMempool(state)
  45. mempoolReactor := mempool_.NewMempoolReactor(mempool)
  46. // Get ConsensusReactor
  47. consensusReactor := consensus.NewConsensusReactor(blockStore, mempool, state)
  48. if privValidator != nil {
  49. consensusReactor.SetPrivValidator(privValidator)
  50. }
  51. sw := p2p.NewSwitch([]p2p.Reactor{pexReactor, mempoolReactor, consensusReactor})
  52. return &Node{
  53. sw: sw,
  54. book: book,
  55. pexReactor: pexReactor,
  56. mempoolReactor: mempoolReactor,
  57. consensusReactor: consensusReactor,
  58. privValidator: privValidator,
  59. }
  60. }
  61. func (n *Node) Start() {
  62. log.Info("Starting node")
  63. for _, l := range n.lz {
  64. go n.inboundConnectionRoutine(l)
  65. }
  66. n.book.Start()
  67. n.sw.Start()
  68. }
  69. func (n *Node) Stop() {
  70. log.Info("Stopping node")
  71. // TODO: gracefully disconnect from peers.
  72. n.sw.Stop()
  73. n.book.Stop()
  74. }
  75. // Add a Listener to accept inbound peer connections.
  76. func (n *Node) AddListener(l p2p.Listener) {
  77. log.Info("Added %v", l)
  78. n.lz = append(n.lz, l)
  79. n.book.AddOurAddress(l.ExternalAddress())
  80. }
  81. func (n *Node) inboundConnectionRoutine(l p2p.Listener) {
  82. for {
  83. inConn, ok := <-l.Connections()
  84. if !ok {
  85. break
  86. }
  87. // New inbound connection!
  88. peer, err := n.sw.AddPeerWithConnection(inConn, false)
  89. if err != nil {
  90. log.Info("Ignoring error from inbound connection: %v\n%v",
  91. peer, err)
  92. continue
  93. }
  94. // NOTE: We don't yet have the external address of the
  95. // remote (if they have a listener at all).
  96. // PEXReactor's pexRoutine will handle that.
  97. }
  98. // cleanup
  99. }
  100. //-----------------------------------------------------------------------------
  101. func main() {
  102. // Parse config flags
  103. config.ParseFlags()
  104. // Create & start node
  105. n := NewNode()
  106. l := p2p.NewDefaultListener("tcp", config.Config.LAddr)
  107. n.AddListener(l)
  108. n.Start()
  109. // If seedNode is provided by config, dial out.
  110. if config.Config.SeedNode != "" {
  111. peer, err := n.sw.DialPeerWithAddress(p2p.NewNetAddressString(config.Config.SeedNode))
  112. if err != nil {
  113. log.Error("Error dialing seed: %v", err)
  114. //n.book.MarkAttempt(addr)
  115. return
  116. } else {
  117. log.Info("Connected to seed: %v", peer)
  118. }
  119. }
  120. // Sleep forever and then...
  121. trapSignal(func() {
  122. n.Stop()
  123. })
  124. }
  125. func trapSignal(cb func()) {
  126. c := make(chan os.Signal, 1)
  127. signal.Notify(c, os.Interrupt)
  128. go func() {
  129. for sig := range c {
  130. log.Info("captured %v, exiting..", sig)
  131. cb()
  132. os.Exit(1)
  133. }
  134. }()
  135. select {}
  136. }