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.

161 lines
3.9 KiB

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