main.rs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  1. use std::{net::SocketAddr, path::PathBuf, sync::Arc, thread, time::Duration};
  2. use async_executor::Executor;
  3. use async_trait::async_trait;
  4. use easy_parallel::Parallel;
  5. use log::{debug, error, info};
  6. use serde::{Deserialize, Serialize};
  7. use serde_json::{json, Value};
  8. use simplelog::{ColorChoice, TermLogger, TerminalMode};
  9. use structopt::StructOpt;
  10. use structopt_toml::StructOptToml;
  11. use darkfi::{
  12. consensus2::{
  13. block::{BlockOrder, BlockResponse},
  14. participant::Participant,
  15. state::{ConsensusRequest, ConsensusResponse, ValidatorState, ValidatorStatePtr},
  16. tx::Tx,
  17. proto::{ProtocolSync, ProtocolTx, ProtocolVote, ProtocolProposal, ProtocolParticipant, ProtocolSyncConsensus}
  18. },
  19. net,
  20. rpc::{
  21. jsonrpc,
  22. jsonrpc::{
  23. from_result,
  24. ErrorCode::{InternalError, InvalidParams, InvalidRequest, MethodNotFound},
  25. JsonRequest, JsonResult, ValueResult,
  26. },
  27. rpcserver::{listen_and_serve, RequestHandler, RpcServerConfig},
  28. },
  29. util::{
  30. cli::{log_config, spawn_config},
  31. expand_path,
  32. path::get_config_path,
  33. },
  34. Result,
  35. };
  36. const CONFIG_FILE: &str = r"validatord_config.toml";
  37. const CONFIG_FILE_CONTENTS: &[u8] = include_bytes!("../validatord_config.toml");
  38. #[derive(Debug, Deserialize, Serialize, StructOpt, StructOptToml)]
  39. #[serde(default)]
  40. struct Opt {
  41. #[structopt(short, long, default_value = CONFIG_FILE)]
  42. /// Configuration file to use
  43. config: String,
  44. #[structopt(long, default_value = "0.0.0.0:11000")]
  45. /// Accept address
  46. accept: SocketAddr,
  47. #[structopt(long, default_value = "0.0.0.0:12000")]
  48. /// Consensus accept address
  49. caccept: SocketAddr,
  50. #[structopt(long)]
  51. /// Seed nodes
  52. seeds: Vec<SocketAddr>,
  53. #[structopt(long)]
  54. /// Consensus seed nodes
  55. cseeds: Vec<SocketAddr>,
  56. #[structopt(long)]
  57. /// Manual connections
  58. connect: Vec<SocketAddr>,
  59. #[structopt(long, default_value = "5")]
  60. /// Connection slots
  61. slots: u32,
  62. #[structopt(long, default_value = "127.0.0.1:11000")]
  63. /// External address
  64. external: SocketAddr,
  65. #[structopt(long, default_value = "127.0.0.1:12000")]
  66. /// Consensus accept address
  67. cexternal: SocketAddr,
  68. #[structopt(long, default_value = "/tmp/darkfid.log")]
  69. /// Logfile path
  70. log: String,
  71. #[structopt(long, default_value = "127.0.0.1:6660")]
  72. /// The endpoint where validatord will bind its RPC socket
  73. rpc: SocketAddr,
  74. #[structopt(long)]
  75. /// Whether to listen with TLS or plain TCP
  76. tls: bool,
  77. #[structopt(long, default_value = "~/.config/darkfi/validatord_identity.pfx")]
  78. /// TLS certificate to use
  79. identity: PathBuf,
  80. #[structopt(long, default_value = "FOOBAR")]
  81. /// Password for the created TLS identity
  82. password: String,
  83. #[structopt(long, default_value = "1648383795")]
  84. /// Timestamp of the genesis block creation
  85. genesis: i64,
  86. #[structopt(long, default_value = "~/.config/darkfi/validatord_db_0")]
  87. /// Path to the sled database folder
  88. database: String,
  89. #[structopt(long, default_value = "0")]
  90. /// Node ID, used only for testing
  91. id: u64,
  92. #[structopt(short, long, default_value = "0")]
  93. /// How many threads to utilize
  94. threads: usize,
  95. #[structopt(short, long, parse(from_occurrences))]
  96. /// Multiple levels can be used (-vv)
  97. verbose: u8,
  98. }
  99. async fn syncing_task(p2p: net::P2pPtr, state: ValidatorStatePtr) -> Result<()> {
  100. info!("Node starts syncing blockchain...");
  101. // We retrieve p2p network connected channels, so we can use it to parallelize downloads
  102. // Using len here because is_empty() uses unstable library feature 'exact_size_is_empty'
  103. if p2p.channels().lock().await.values().len() != 0 {
  104. // Currently we will use just the last channel
  105. let channel = p2p.channels().lock().await.values().last().unwrap().clone();
  106. // Communication setup
  107. let message_subsytem = channel.get_message_subsystem();
  108. message_subsytem.add_dispatch::<BlockResponse>().await;
  109. let response_sub = channel
  110. .subscribe_msg::<BlockResponse>()
  111. .await
  112. .expect("Missing BlockResponse dispatcher!");
  113. // Nodes sends the last known block hash of the canonical blockchain
  114. // and loops until the respond is the same block (used to utilize batch requests)
  115. let mut last = state.read().await.blockchain.last()?.unwrap();
  116. info!("Last known block: {:?} - {:?}", last.0, last.1);
  117. loop {
  118. // Node creates a BlockOrder and sends it
  119. let order = BlockOrder { sl: last.0, block: last.1 };
  120. channel.send(order).await?;
  121. // Node stores responce data. Extra validations can be added here.
  122. let response = response_sub.receive().await?;
  123. for info in &response.blocks {
  124. state.write().await.blockchain.add_by_info(info.clone())?;
  125. }
  126. let last_received = state.read().await.blockchain.last()?.unwrap();
  127. info!("Last received block: {:?} - {:?}", last_received.0, last_received.1);
  128. if last == last_received {
  129. break
  130. }
  131. last = last_received;
  132. }
  133. } else {
  134. info!("Node is not connected to other nodes.");
  135. }
  136. info!("Node synced!");
  137. Ok(())
  138. }
  139. async fn syncing_consensus_task(p2p: net::P2pPtr, state: ValidatorStatePtr) -> Result<()> {
  140. info!("Node starts syncing consensus state...");
  141. // Using len here because is_empty() uses unstable library feature 'exact_size_is_empty'
  142. if p2p.channels().lock().await.values().len() != 0 {
  143. // Nodes ask for the consensus state of the last channel peer
  144. let channel = p2p.channels().lock().await.values().last().unwrap().clone();
  145. // Communication setup
  146. let message_subsytem = channel.get_message_subsystem();
  147. message_subsytem.add_dispatch::<ConsensusResponse>().await;
  148. let response_sub = channel
  149. .subscribe_msg::<ConsensusResponse>()
  150. .await
  151. .expect("Missing ConsensusResponse dispatcher!");
  152. // Node creates a ConsensusRequest and sends it
  153. let request = ConsensusRequest { id: state.read().await.id };
  154. channel.send(request).await?;
  155. // Node stores responce data. Extra validations can be added here.
  156. let response = response_sub.receive().await?;
  157. state.write().await.consensus = response.consensus.clone();
  158. } else {
  159. info!("Node is not connected to other nodes, resetting consensus state.");
  160. state.write().await.reset_consensus_state()?;
  161. }
  162. info!("Node synced!");
  163. Ok(())
  164. }
  165. async fn proposal_task(p2p: net::P2pPtr, state: ValidatorStatePtr) {
  166. // Node waits just before the current or next epoch end,
  167. // so it can start syncing latest state.
  168. let mut seconds_until_next_epoch = state.read().await.next_epoch_start();
  169. let one_sec = Duration::new(1, 0);
  170. loop {
  171. if seconds_until_next_epoch > one_sec {
  172. seconds_until_next_epoch = seconds_until_next_epoch - one_sec;
  173. break
  174. }
  175. info!("Waiting for next epoch({:?} sec)...", seconds_until_next_epoch);
  176. thread::sleep(seconds_until_next_epoch);
  177. seconds_until_next_epoch = state.read().await.next_epoch_start();
  178. }
  179. info!("Waiting for next epoch({:?} sec)...", seconds_until_next_epoch);
  180. thread::sleep(seconds_until_next_epoch);
  181. // Node syncs its consensus state
  182. let result = syncing_consensus_task(p2p.clone(), state.clone()).await;
  183. match result {
  184. Ok(()) => (),
  185. Err(e) => error!("Sync consensus state failed. Error: {:?}", e),
  186. }
  187. // Node signals the network that it will start participating
  188. let participant =
  189. Participant::new(state.read().await.id, state.read().await.current_epoch());
  190. state.write().await.append_self_participant(participant.clone());
  191. let result = p2p.broadcast(participant.clone()).await;
  192. match result {
  193. Ok(()) => info!("Participation message broadcasted successfuly."),
  194. Err(e) => error!("Broadcast failed. Error: {:?}", e),
  195. }
  196. // After initialization node waits for next epoch to start participating
  197. let seconds_until_next_epoch = state.read().await.next_epoch_start();
  198. info!("Waiting for next epoch({:?} sec)...", seconds_until_next_epoch);
  199. thread::sleep(seconds_until_next_epoch);
  200. // Node modifies its participating flag to true
  201. state.write().await.participating = true;
  202. loop {
  203. // Node refreshes participants records
  204. state.write().await.refresh_participants();
  205. // Node checks if its the epoch leader to generate a new proposal for that epoch
  206. let result = if state.write().await.is_epoch_leader() {
  207. state.read().await.propose()
  208. } else {
  209. Ok(None)
  210. };
  211. match result {
  212. Ok(proposal) => {
  213. if proposal.is_none() {
  214. info!("Node is not the epoch leader. Sleeping till next epoch...");
  215. } else {
  216. // Leader creates a vote for the proposal and broadcasts them both
  217. let unwrapped = proposal.unwrap();
  218. info!("Node is the epoch leader. Proposed block: {:?}", unwrapped);
  219. let vote = state.write().await.receive_proposal(&unwrapped);
  220. match vote {
  221. Ok(x) => {
  222. if x.is_none() {
  223. error!("Node did not vote for the proposed block.");
  224. } else {
  225. let vote = x.unwrap();
  226. let result = state.write().await.receive_vote(&vote);
  227. match result {
  228. Ok(_) => info!("Vote saved successfuly."),
  229. Err(e) => error!("Vote save failed. Error: {:?}", e),
  230. }
  231. // Broadcasting block
  232. let result = p2p.broadcast(unwrapped).await;
  233. match result {
  234. Ok(()) => info!("Proposal broadcasted successfuly."),
  235. Err(e) => error!("Broadcast failed. Error: {:?}", e),
  236. }
  237. // Broadcasting leader vote
  238. let result = p2p.broadcast(vote).await;
  239. match result {
  240. Ok(()) => info!("Leader vote broadcasted successfuly."),
  241. Err(e) => error!("Broadcast failed. Error: {:?}", e),
  242. }
  243. }
  244. }
  245. Err(e) => {
  246. error!("Error prosessing proposal: {:?}", e)
  247. }
  248. }
  249. }
  250. }
  251. Err(e) => error!("Block proposal failed. Error: {:?}", e),
  252. }
  253. // Current node state is flushed to sled database
  254. let result = state.read().await.save_consensus_state();
  255. match result {
  256. Ok(()) => (),
  257. Err(e) => {
  258. error!("State could not be flushed: {:?}", e)
  259. }
  260. };
  261. // Node waits until next epoch
  262. let seconds_until_next_epoch = state.read().await.next_epoch_start();
  263. info!("Waiting for next epoch({:?} sec)...", seconds_until_next_epoch);
  264. thread::sleep(seconds_until_next_epoch);
  265. }
  266. }
  267. async fn start(executor: Arc<Executor<'_>>, opts: &Opt) -> Result<()> {
  268. let rpc_server_config = RpcServerConfig {
  269. socket_addr: opts.rpc,
  270. use_tls: opts.tls,
  271. identity_path: opts.identity.clone(),
  272. identity_pass: opts.password.clone(),
  273. };
  274. // Main subnet settings
  275. let subnet_settings = net::Settings {
  276. inbound: Some(opts.accept),
  277. outbound_connections: opts.slots,
  278. external_addr: Some(opts.external),
  279. peers: opts.connect.clone(),
  280. seeds: opts.seeds.clone(),
  281. ..Default::default()
  282. };
  283. // Consensus subnet settings
  284. let consensus_subnet_settings = net::Settings {
  285. inbound: Some(opts.caccept),
  286. outbound_connections: opts.slots,
  287. external_addr: Some(opts.cexternal),
  288. peers: opts.connect.clone(),
  289. seeds: opts.cseeds.clone(),
  290. ..Default::default()
  291. };
  292. // State setup
  293. let genesis = opts.genesis;
  294. let database_path = expand_path(&opts.database).unwrap();
  295. let id = opts.id.clone();
  296. let state = ValidatorState::new(database_path, id, genesis).unwrap();
  297. // Main P2P registry setup
  298. let main_p2p = net::P2p::new(subnet_settings).await;
  299. let registry = main_p2p.protocol_registry();
  300. // Adding ProtocolSync to the registry
  301. let state2 = state.clone();
  302. let consensus_mode = true; // This flag should be based on staking
  303. registry
  304. .register(net::SESSION_ALL, move |channel, main_p2p| {
  305. let state = state2.clone();
  306. async move { ProtocolSync::init(channel, state, main_p2p, consensus_mode).await }
  307. })
  308. .await;
  309. // Adding ProtocolTx to the registry
  310. let state2 = state.clone();
  311. registry
  312. .register(net::SESSION_ALL, move |channel, main_p2p| {
  313. let state = state2.clone();
  314. async move { ProtocolTx::init(channel, state, main_p2p).await }
  315. })
  316. .await;
  317. // Performs seed session
  318. main_p2p.clone().start(executor.clone()).await?;
  319. // Actual main p2p session
  320. let ex2 = executor.clone();
  321. let p2p = main_p2p.clone();
  322. executor
  323. .spawn(async move {
  324. if let Err(err) = p2p.run(ex2).await {
  325. error!("Error: p2p run failed {}", err);
  326. }
  327. })
  328. .detach();
  329. // RPC interface
  330. let ex2 = executor.clone();
  331. let ex3 = ex2.clone();
  332. let rpc_interface = Arc::new(JsonRpcInterface {
  333. state: state.clone(),
  334. p2p: main_p2p.clone(),
  335. _rpc_listen_addr: opts.rpc,
  336. });
  337. executor
  338. .spawn(async move { listen_and_serve(rpc_server_config, rpc_interface, ex3).await })
  339. .detach();
  340. // Node starts syncing
  341. let state2 = state.clone();
  342. syncing_task(main_p2p.clone(), state2).await?;
  343. // Consensus P2P registry setup
  344. let consensus_p2p = net::P2p::new(consensus_subnet_settings).await;
  345. let registry = consensus_p2p.protocol_registry();
  346. // Adding PropotolVote to the registry
  347. let p2p = main_p2p.clone();
  348. let state2 = state.clone();
  349. registry
  350. .register(net::SESSION_ALL, move |channel, consensus_p2p| {
  351. let state = state2.clone();
  352. let main_p2p = p2p.clone();
  353. async move { ProtocolVote::init(channel, state, main_p2p, consensus_p2p).await }
  354. })
  355. .await;
  356. // Adding ProtocolProposal to the registry
  357. let state2 = state.clone();
  358. registry
  359. .register(net::SESSION_ALL, move |channel, consensus_p2p| {
  360. let state = state2.clone();
  361. async move { ProtocolProposal::init(channel, state, consensus_p2p).await }
  362. })
  363. .await;
  364. // Adding ProtocolParticipant to the registry
  365. let state2 = state.clone();
  366. registry
  367. .register(net::SESSION_ALL, move |channel, consensus_p2p| {
  368. let state = state2.clone();
  369. async move { ProtocolParticipant::init(channel, state, consensus_p2p).await }
  370. })
  371. .await;
  372. // Adding ProtocolSyncForks to the registry
  373. let state2 = state.clone();
  374. registry
  375. .register(net::SESSION_ALL, move |channel, _consensus_p2p| {
  376. let state = state2.clone();
  377. async move { ProtocolSyncConsensus::init(channel, state).await }
  378. })
  379. .await;
  380. // Performs seed session
  381. consensus_p2p.clone().start(executor.clone()).await?;
  382. // Actual consensus p2p session
  383. let ex2 = executor.clone();
  384. let p2p = consensus_p2p.clone();
  385. executor
  386. .spawn(async move {
  387. if let Err(err) = p2p.run(ex2).await {
  388. error!("Error: p2p run failed {}", err);
  389. }
  390. })
  391. .detach();
  392. proposal_task(consensus_p2p, state).await;
  393. Ok(())
  394. }
  395. struct JsonRpcInterface {
  396. state: ValidatorStatePtr,
  397. p2p: net::P2pPtr,
  398. _rpc_listen_addr: SocketAddr,
  399. }
  400. #[async_trait]
  401. impl RequestHandler for JsonRpcInterface {
  402. async fn handle_request(&self, req: JsonRequest, _executor: Arc<Executor<'_>>) -> JsonResult {
  403. if req.params.as_array().is_none() {
  404. return jsonrpc::error(InvalidRequest, None, req.id).into()
  405. }
  406. debug!(target: "RPC", "--> {}", serde_json::to_string(&req).unwrap());
  407. from_result(
  408. match req.method.as_str() {
  409. Some("ping") => self.pong().await,
  410. Some("get_info") => self.get_info().await,
  411. Some("receive_tx") => self.receive_tx(req.params).await,
  412. Some(_) | None => Err(MethodNotFound),
  413. },
  414. req.id,
  415. )
  416. }
  417. }
  418. impl JsonRpcInterface {
  419. // --> {"jsonrpc": "2.0", "method": "ping", "params": [], "id": 42}
  420. // <-- {"jsonrpc": "2.0", "result": "pong", "id": 42}
  421. async fn pong(&self) -> ValueResult<Value> {
  422. Ok(json!("pong"))
  423. }
  424. // --> {"jsonrpc": "2.0", "method": "get_info", "params": [], "id": 42}
  425. // <-- {"jsonrpc": "2.0", "result": {"nodeID": [], "nodeinfo" [], "id": 42}
  426. async fn get_info(&self) -> ValueResult<Value> {
  427. Ok(self.p2p.get_info().await)
  428. }
  429. // --> {"jsonrpc": "2.0", "method": "receive_tx", "params": ["tx"], "id": 42}
  430. // <-- {"jsonrpc": "2.0", "result": true, "id": 0}
  431. async fn receive_tx(&self, params: Value) -> ValueResult<Value> {
  432. let args = params.as_array().unwrap();
  433. if args.len() != 1 {
  434. return Err(InvalidParams)
  435. }
  436. let payload = String::from(args[0].as_str().unwrap());
  437. let tx = Tx { payload };
  438. self.state.write().await.append_tx(tx.clone());
  439. let result = self.p2p.broadcast(tx).await;
  440. match result {
  441. Ok(()) => Ok(json!(true)),
  442. Err(_) => Err(InternalError),
  443. }
  444. }
  445. }
  446. #[async_std::main]
  447. async fn main() -> Result<()> {
  448. let opts = Opt::from_args_with_toml(&String::from_utf8(CONFIG_FILE_CONTENTS.to_vec()).unwrap())
  449. .unwrap();
  450. let config_path = get_config_path(Some(opts.config.clone()), CONFIG_FILE)?;
  451. spawn_config(&config_path, CONFIG_FILE_CONTENTS)?;
  452. let opts = Opt::from_args_with_toml(&String::from_utf8(CONFIG_FILE_CONTENTS.to_vec()).unwrap())
  453. .unwrap();
  454. let (lvl, conf) = log_config(opts.verbose.into())?;
  455. TermLogger::init(lvl, conf, TerminalMode::Mixed, ColorChoice::Auto)?;
  456. let ex = Arc::new(Executor::new());
  457. let (signal, shutdown) = async_channel::unbounded::<()>();
  458. let ex2 = ex.clone();
  459. let nthreads = if opts.threads == 0 { num_cpus::get() } else { opts.threads };
  460. debug!(target: "VALIDATOR DAEMON", "Executing with opts: {:?}", opts);
  461. debug!(target: "VALIDATOR DAEMON", "Run {} executor threads", nthreads);
  462. let (_, result) = Parallel::new()
  463. .each(0..nthreads, |_| smol::future::block_on(ex.run(shutdown.recv())))
  464. // Run the main future on the current thread.
  465. .finish(|| {
  466. smol::future::block_on(async move {
  467. start(ex2.clone(), &opts).await?;
  468. drop(signal);
  469. Ok::<(), darkfi::Error>(())
  470. })
  471. });
  472. result
  473. }