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