github.com/Gessiux/neatchain@v1.3.1/chain/consensus/neatcon/node.go (about) 1 package neatcon 2 3 import ( 4 "io/ioutil" 5 "os" 6 "strings" 7 8 cmn "github.com/Gessiux/go-common" 9 cfg "github.com/Gessiux/go-config" 10 dbm "github.com/Gessiux/go-db" 11 "github.com/Gessiux/neatchain/chain/consensus/neatcon/consensus" 12 "github.com/Gessiux/neatchain/chain/consensus/neatcon/epoch" 13 "github.com/Gessiux/neatchain/chain/consensus/neatcon/types" 14 "github.com/Gessiux/neatchain/chain/core" 15 "github.com/Gessiux/neatchain/chain/log" 16 "github.com/Gessiux/neatchain/params" 17 ) 18 19 type Node struct { 20 cmn.BaseService 21 22 //genesisDoc *types.GenesisDoc // initial validator set 23 privValidator *types.PrivValidator // local node's validator key 24 25 epochDB dbm.DB 26 27 // services 28 evsw types.EventSwitch // pub/sub for services 29 //blockStore *bc.BlockStore // store the blockchain to disk 30 consensusState *consensus.ConsensusState // latest consensus state 31 consensusReactor *consensus.ConsensusReactor // for participating in the consensus 32 33 cch core.CrossChainHelper 34 logger log.Logger 35 } 36 37 func NewNodeNotStart(backend *backend, config cfg.Config, chainConfig *params.ChainConfig, cch core.CrossChainHelper, genDoc *types.GenesisDoc) *Node { 38 // Get PrivValidator 39 var privValidator *types.PrivValidator 40 privValidatorFile := config.GetString("priv_validator_file") 41 if _, err := os.Stat(privValidatorFile); err == nil { 42 privValidator = types.LoadPrivValidator(privValidatorFile) 43 } 44 45 // Initial Epoch 46 epochDB := dbm.NewDB("epoch", config.GetString("db_backend"), config.GetString("db_dir")) 47 ep := epoch.InitEpoch(epochDB, genDoc, backend.logger) 48 49 // We should start mine if we are in the ValidatorSet 50 if privValidator != nil && ep.Validators.HasAddress(privValidator.Address[:]) { 51 backend.shouldStart = true 52 } else { 53 backend.shouldStart = false 54 } 55 56 // Make ConsensusReactor 57 consensusState := consensus.NewConsensusState(backend, config, chainConfig, cch, ep) 58 if privValidator != nil { 59 consensusState.SetPrivValidator(privValidator) 60 } 61 consensusReactor := consensus.NewConsensusReactor(consensusState /*, fastSync*/) 62 63 // Add Reactor to P2P Switch 64 //sw.AddReactor(config.GetString("chain_id"), "CONSENSUS", consensusReactor) 65 66 // Make event switch 67 eventSwitch := types.NewEventSwitch() 68 // add the event switch to all services 69 // they should all satisfy events.Eventable 70 SetEventSwitch(eventSwitch, consensusReactor) 71 72 node := &Node{ 73 privValidator: privValidator, 74 75 epochDB: epochDB, 76 77 evsw: eventSwitch, 78 79 cch: cch, 80 81 consensusState: consensusState, 82 consensusReactor: consensusReactor, 83 84 logger: backend.logger, 85 } 86 node.BaseService = *cmn.NewBaseService(backend.logger, "Node", node) 87 88 return node 89 } 90 91 func (n *Node) OnStart() error { 92 93 n.logger.Info("(n *Node) OnStart()") 94 95 // Check Private Validator has been set 96 if n.privValidator == nil { 97 return ErrNoPrivValidator 98 } 99 100 /* 101 state, epoch := n.consensusState.InitStateAndEpoch() 102 n.consensusState.Initialize() 103 n.consensusState.UpdateToStateAndEpoch(state, epoch) 104 */ 105 _, err := n.evsw.Start() 106 if err != nil { 107 n.logger.Errorf("Failed to start switch: %v", err) 108 return err 109 } 110 111 // Start the Consensus Reactor for this Chain 112 _, err = n.consensusReactor.Start() 113 if err != nil { 114 n.logger.Errorf("Failed to start Consensus Reactor. Error: %v", err) 115 return err 116 } 117 118 n.consensusReactor.AfterStart() 119 120 return nil 121 } 122 123 func (n *Node) OnStop() { 124 n.logger.Info("(n *Node) OnStop() called") 125 n.BaseService.OnStop() 126 127 //n.sw.StopChainReactor(n.consensusState.GetState().NTCExtra.ChainID) 128 n.evsw.Stop() 129 n.consensusReactor.Stop() 130 } 131 132 //update the state with new insert block information 133 //func (n *Node) SaveState(block *neatTypes.Block) { 134 // 135 // epoch := n.consensusState.Epoch 136 // state := n.consensusState.GetState() 137 // 138 // fmt.Printf("(n *Node) SaveState(block *neatTypes.Block) with state.height = %v, block.height = %v\n", 139 // uint64(state.NTCExtra.Height), block.NumberU64()) 140 // 141 // if uint64(state.NTCExtra.Height) != block.NumberU64() { 142 // fmt.Printf("(n *Node) SaveState(block *neatTypes.Block), block height not equal\n") 143 // } 144 // 145 // epoch.Save() 146 // //state.Save() 147 // 148 // n.consensusState.StartNewHeight() 149 //} 150 151 func (n *Node) RunForever() { 152 // Sleep forever and then... 153 cmn.TrapSignal(func() { 154 n.Stop() 155 }) 156 } 157 158 // Add the event switch to reactors, mempool, etc. 159 func SetEventSwitch(evsw types.EventSwitch, eventables ...types.Eventable) { 160 for _, e := range eventables { 161 e.SetEventSwitch(evsw) 162 } 163 } 164 165 func (n *Node) ConsensusState() *consensus.ConsensusState { 166 return n.consensusState 167 } 168 169 func (n *Node) ConsensusReactor() *consensus.ConsensusReactor { 170 return n.consensusReactor 171 } 172 173 func (n *Node) EventSwitch() types.EventSwitch { 174 return n.evsw 175 } 176 177 // XXX: for convenience 178 func (n *Node) PrivValidator() *types.PrivValidator { 179 return n.privValidator 180 } 181 182 /* 183 func (n *Node) GenesisDoc() *types.GenesisDoc { 184 return n.genesisDoc 185 } 186 */ 187 188 //------------------------------------------------------------------------------ 189 // Users wishing to: 190 // * use an external signer for their validators 191 // * supply an in-proc abci app 192 // should fork neatcon/neatcon and implement RunNode to 193 // call NewNode with their custom priv validator and/or custom 194 // proxy.ClientCreator interface 195 /* 196 func RunNode(config cfg.Config, app *app.EthermintApplication) { 197 // Wait until the genesis doc becomes available 198 genDocFile := config.GetString("genesis_file") 199 if !cmn.FileExists(genDocFile) { 200 log.Notice(cmn.Fmt("Waiting for genesis file %v...", genDocFile)) 201 for { 202 time.Sleep(time.Second) 203 if !cmn.FileExists(genDocFile) { 204 continue 205 } 206 jsonBlob, err := ioutil.ReadFile(genDocFile) 207 if err != nil { 208 cmn.Exit(cmn.Fmt("Couldn't read GenesisDoc file: %v", err)) 209 } 210 genDoc, err := types.GenesisDocFromJSON(jsonBlob) 211 if err != nil { 212 cmn.PanicSanity(cmn.Fmt("Genesis doc parse json error: %v", err)) 213 } 214 if genDoc.ChainID == "" { 215 cmn.PanicSanity(cmn.Fmt("Genesis doc %v must include non-empty chain_id", genDocFile)) 216 } 217 config.Set("chain_id", genDoc.ChainID) 218 } 219 } 220 221 // Create & start node 222 n := NewNodeDefault(config, nil) 223 224 //protocol, address := ProtocolAndAddress(config.GetString("node_laddr")) 225 //l := p2p.NewDefaultListener(protocol, address, config.GetBool("skip_upnp")) 226 //n.AddListener(l) 227 err := n.OnStart() 228 if err != nil { 229 cmn.Exit(cmn.Fmt("Failed to start node: %v", err)) 230 } 231 232 //log.Notice("Started node", "nodeInfo", n.sw.NodeInfo()) 233 // If seedNode is provided by config, dial out. 234 if config.GetString("seeds") != "" { 235 seeds := strings.Split(config.GetString("seeds"), ",") 236 n.DialSeeds(seeds) 237 } 238 239 // Run the RPC server. 240 if config.GetString("rpc_laddr") != "" { 241 _, err := n.StartRPC() 242 if err != nil { 243 cmn.PanicCrisis(err) 244 } 245 } 246 // Sleep forever and then... 247 cmn.TrapSignal(func() { 248 n.Stop() 249 }) 250 } 251 */ 252 253 //func (n *Node) NodeInfo() *p2p.NodeInfo { 254 // return n.sw.NodeInfo() 255 //} 256 // 257 //func (n *Node) DialSeeds(seeds []string) error { 258 // return n.sw.DialSeeds(n.addrBook, seeds) 259 //} 260 261 // Defaults to tcp 262 func ProtocolAndAddress(listenAddr string) (string, string) { 263 protocol, address := "tcp", listenAddr 264 parts := strings.SplitN(address, "://", 2) 265 if len(parts) == 2 { 266 protocol, address = parts[0], parts[1] 267 } 268 return protocol, address 269 } 270 271 func MakeNeatConNode(backend *backend, config cfg.Config, chainConfig *params.ChainConfig, cch core.CrossChainHelper) *Node { 272 273 var genDoc *types.GenesisDoc 274 genDocFile := config.GetString("genesis_file") 275 276 if !cmn.FileExists(genDocFile) { 277 if chainConfig.NeatChainId == params.MainnetChainConfig.NeatChainId { 278 genDoc, _ = types.GenesisDocFromJSON([]byte(types.MainnetGenesisJSON)) 279 } else if chainConfig.NeatChainId == params.TestnetChainConfig.NeatChainId { 280 genDoc, _ = types.GenesisDocFromJSON([]byte(types.TestnetGenesisJSON)) 281 } else { 282 return nil 283 } 284 } else { 285 genDoc = readGenesisFromFile(genDocFile) 286 } 287 config.Set("chain_id", genDoc.ChainID) 288 289 return NewNodeNotStart(backend, config, chainConfig, cch, genDoc) 290 } 291 292 func readGenesisFromFile(genDocFile string) *types.GenesisDoc { 293 jsonBlob, err := ioutil.ReadFile(genDocFile) 294 if err != nil { 295 cmn.Exit(cmn.Fmt("Couldn't read GenesisDoc file: %v", err)) 296 } 297 genDoc, err := types.GenesisDocFromJSON(jsonBlob) 298 if err != nil { 299 cmn.PanicSanity(cmn.Fmt("Genesis doc parse json error: %v", err)) 300 } 301 if genDoc.ChainID == "" { 302 cmn.PanicSanity(cmn.Fmt("Genesis doc %v must include non-empty chain_id", genDocFile)) 303 } 304 return genDoc 305 }