main.rs 20 KB

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