mod.rs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2026 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use std::sync::Arc;
  19. use darkfi::{
  20. net::Settings,
  21. rpc::settings::RpcSettings,
  22. util::logger::{setup_test_logger, Level},
  23. validator::{consensus::Fork, utils::best_fork_index, verification::verify_block},
  24. Result,
  25. };
  26. use darkfi_contract_test_harness::init_logger;
  27. use darkfi_sdk::{crypto::keypair::Network, num_traits::One};
  28. use num_bigint::BigUint;
  29. use smol::Executor;
  30. use tracing::warn;
  31. use url::Url;
  32. mod harness;
  33. use harness::{generate_node, Harness, HarnessConfig};
  34. mod forks;
  35. mod sync_forks;
  36. mod unproposed_txs;
  37. mod metering;
  38. async fn sync_blocks_real(ex: Arc<Executor<'static>>) -> Result<()> {
  39. init_logger();
  40. // Initialize harness in testing mode
  41. let pow_target = 120;
  42. let pow_fixed_difficulty = Some(BigUint::one());
  43. let config = HarnessConfig {
  44. pow_target,
  45. pow_fixed_difficulty: pow_fixed_difficulty.clone(),
  46. confirmation_threshold: 3,
  47. max_forks: 8,
  48. alice_url: "tcp+tls://127.0.0.1:18340".to_string(),
  49. bob_url: "tcp+tls://127.0.0.1:18341".to_string(),
  50. };
  51. let th = Harness::new(config, true, &ex).await?;
  52. // Generate a fork to create new blocks
  53. let mut fork = th.alice.validator.read().await.consensus.forks[0].full_clone()?;
  54. // Generate next blocks
  55. let block1 = th.generate_next_block(&mut fork).await?;
  56. let block2 = th.generate_next_block(&mut fork).await?;
  57. let block3 = th.generate_next_block(&mut fork).await?;
  58. let block4 = th.generate_next_block(&mut fork).await?;
  59. // Add them to nodes
  60. th.add_blocks(&[block1, block2.clone(), block3.clone(), block4]).await?;
  61. // Nodes must have one fork with 2 blocks
  62. th.validate_fork_chains(1, vec![2]).await;
  63. // Extend current fork sequence
  64. let block5 = th.generate_next_block(&mut fork).await?;
  65. // Create a new fork extending canonical
  66. let alice = th.alice.validator.read().await;
  67. fork = Fork::new(alice.consensus.blockchain.clone(), alice.consensus.module.clone()).await?;
  68. // Append block3 to fork and generate the next one
  69. verify_block(
  70. &fork.overlay,
  71. &fork.diffs,
  72. &mut fork.module,
  73. &block3,
  74. &block2,
  75. None,
  76. alice.verify_fees,
  77. )
  78. .await?;
  79. drop(alice);
  80. let block6 = th.generate_next_block(&mut fork).await?;
  81. // Add them to nodes
  82. th.add_blocks(&[block5, block6]).await?;
  83. // Grab current best fork index
  84. let alice = th.alice.validator.read().await;
  85. // If index corresponds to the small fork, confirmation
  86. // did not occur, as it's size is not over the threshold.
  87. let small_best = best_fork_index(&alice.consensus.forks)? == 1;
  88. drop(alice);
  89. if small_best {
  90. // Nodes must have one fork with 3 blocks and one with 2 blocks
  91. th.validate_fork_chains(2, vec![3, 2]).await;
  92. } else {
  93. // Nodes must have one fork with 2 blocks and one with 1 block
  94. th.validate_fork_chains(2, vec![2, 1]).await;
  95. }
  96. // We are going to create a third node and try to sync from Bob
  97. let mut settings = Settings {
  98. active_profiles: vec!["tcp+tls".to_string()],
  99. localnet: true,
  100. inbound_connections: 3,
  101. ..Default::default()
  102. };
  103. let charlie_url = Url::parse("tcp+tls://127.0.0.1:18342")?;
  104. settings.inbound_addrs = vec![charlie_url];
  105. let bob_url = th.bob.p2p_handler.p2p.settings().read().await.inbound_addrs[0].clone();
  106. settings.peers = vec![bob_url];
  107. let charlie = generate_node(
  108. &th.vks,
  109. &th.validator_config,
  110. &settings,
  111. &ex,
  112. false,
  113. Some((block2.header.height, block2.hash())),
  114. )
  115. .await?;
  116. // Verify node synced
  117. let alice = th.alice.validator.read().await;
  118. let charlie_validator = charlie.validator.read().await;
  119. assert_eq!(alice.blockchain.len(), charlie_validator.blockchain.len());
  120. assert!(charlie_validator.blockchain.headers.is_empty_sync());
  121. // Node must have just the best fork
  122. let index = best_fork_index(&alice.consensus.forks)?;
  123. let best_fork = &alice.consensus.forks[index];
  124. assert_eq!(charlie_validator.consensus.forks.len(), 1);
  125. assert_eq!(charlie_validator.consensus.forks[0].proposals.len(), best_fork.proposals.len());
  126. assert_eq!(charlie_validator.consensus.forks[0].diffs.len(), best_fork.diffs.len());
  127. drop(charlie_validator);
  128. drop(alice);
  129. // Extend the small fork sequence and add it to nodes
  130. th.add_blocks(&[th.generate_next_block(&mut fork).await?]).await?;
  131. // Nodes must have two forks with 2 blocks each
  132. th.validate_fork_chains(2, vec![2, 2]).await;
  133. // Check charlie has the correct forks
  134. let charlie_validator = charlie.validator.read().await;
  135. if small_best {
  136. // If Charlie already had the small fork as its best,
  137. // it will have a single fork with 3 blocks.
  138. assert_eq!(charlie_validator.consensus.forks.len(), 1);
  139. assert_eq!(charlie_validator.consensus.forks[0].proposals.len(), 3);
  140. assert_eq!(charlie_validator.consensus.forks[0].diffs.len(), 3);
  141. } else {
  142. // Charlie didn't originaly have the fork, but it
  143. // should be synced when its proposal was received
  144. assert_eq!(charlie_validator.consensus.forks.len(), 2);
  145. assert_eq!(charlie_validator.consensus.forks[0].proposals.len(), 2);
  146. assert_eq!(charlie_validator.consensus.forks[0].diffs.len(), 2);
  147. assert_eq!(charlie_validator.consensus.forks[1].proposals.len(), 2);
  148. assert_eq!(charlie_validator.consensus.forks[1].diffs.len(), 2);
  149. }
  150. drop(charlie_validator);
  151. // Since the don't know if the second fork was the best,
  152. // we extend it until it becomes best and a confirmation
  153. // occurred.
  154. loop {
  155. th.add_blocks(&[th.generate_next_block(&mut fork).await?]).await?;
  156. // Check if confirmation occured
  157. if th.alice.validator.read().await.blockchain.len() > 4 {
  158. break
  159. }
  160. }
  161. // Nodes must have executed confirmation, so we validate their chains
  162. th.validate_chains(4 + (fork.proposals.len() - 2)).await?;
  163. let last = th.alice.validator.read().await.blockchain.last()?.1;
  164. assert_eq!(last, fork.proposals[fork.proposals.len() - 3]);
  165. assert_eq!(last, th.bob.validator.read().await.blockchain.last()?.1);
  166. // Nodes must have one fork with 2 blocks
  167. th.validate_fork_chains(1, vec![2]).await;
  168. let alice = &th.alice.validator.read().await;
  169. let last_proposal = alice.consensus.forks[0].proposals[1];
  170. assert_eq!(last_proposal, *fork.proposals.last().unwrap());
  171. assert_eq!(last_proposal, th.bob.validator.read().await.consensus.forks[0].proposals[1]);
  172. // Same for Charlie
  173. let mut charlie = charlie.validator.write().await;
  174. charlie.confirmation().await?;
  175. charlie.validate_blockchain(pow_target, pow_fixed_difficulty).await?;
  176. assert_eq!(alice.blockchain.len(), charlie.blockchain.len());
  177. assert!(charlie.blockchain.headers.is_empty_sync());
  178. assert_eq!(last, charlie.blockchain.last()?.1);
  179. assert_eq!(charlie.consensus.forks.len(), 1);
  180. assert_eq!(charlie.consensus.forks[0].proposals.len(), 2);
  181. assert_eq!(charlie.consensus.forks[0].diffs.len(), 2);
  182. assert_eq!(last_proposal, charlie.consensus.forks[0].proposals[1]);
  183. // Thanks for reading
  184. Ok(())
  185. }
  186. #[test]
  187. fn sync_blocks() -> Result<()> {
  188. let ex = Arc::new(Executor::new());
  189. let (signal, shutdown) = smol::channel::unbounded::<()>();
  190. easy_parallel::Parallel::new().each(0..4, |_| smol::block_on(ex.run(shutdown.recv()))).finish(
  191. || {
  192. smol::block_on(async {
  193. sync_blocks_real(ex.clone()).await.unwrap();
  194. drop(signal);
  195. })
  196. },
  197. );
  198. Ok(())
  199. }
  200. #[test]
  201. /// Test the programmatic control of `Darkfid`.
  202. ///
  203. /// First we initialize a daemon, start it and then perform
  204. /// couple of restarts to verify everything works as expected.
  205. fn darkfid_programmatic_control() -> Result<()> {
  206. // We check this error so we can execute same file tests in parallel,
  207. // otherwise second one fails to init logger here.
  208. if setup_test_logger(
  209. &[],
  210. false,
  211. Level::Info,
  212. //Level::Verbose,
  213. //Level::Debug,
  214. //Level::Trace
  215. )
  216. .is_err()
  217. {
  218. warn!(target: "darkfid_programmatic_control", "Logger already initialized");
  219. }
  220. // Create an executor and communication signals
  221. let ex = Arc::new(smol::Executor::new());
  222. let (signal, shutdown) = smol::channel::unbounded::<()>();
  223. easy_parallel::Parallel::new().each(0..1, |_| smol::block_on(ex.run(shutdown.recv()))).finish(
  224. || {
  225. smol::block_on(async {
  226. // Daemon configuration
  227. let mut genesis_block = darkfi::blockchain::BlockInfo::default();
  228. let producer_tx = genesis_block.txs.pop().unwrap();
  229. genesis_block.append_txs(vec![producer_tx]);
  230. let sled_db = sled_overlay::sled::Config::new().temporary(true).open().unwrap();
  231. let overlay = darkfi::blockchain::BlockchainOverlay::new(
  232. &darkfi::blockchain::Blockchain::new(&sled_db).unwrap(),
  233. )
  234. .unwrap();
  235. let (_, vks) = darkfi_contract_test_harness::vks::get_cached_pks_and_vks().unwrap();
  236. darkfi_contract_test_harness::vks::inject(&overlay, &vks).unwrap();
  237. darkfi::validator::utils::deploy_native_contracts(&overlay, 20).await.unwrap();
  238. let diff = overlay.lock().unwrap().overlay.lock().unwrap().diff(&[]).unwrap();
  239. genesis_block.header.state_root =
  240. overlay.lock().unwrap().contracts.update_state_monotree(&diff).unwrap();
  241. let config = darkfi::validator::ValidatorConfig {
  242. confirmation_threshold: 1,
  243. max_forks: 8,
  244. pow_target: 20,
  245. pow_fixed_difficulty: Some(BigUint::one()),
  246. genesis_block,
  247. verify_fees: false,
  248. };
  249. let consensus_config = crate::ConsensusInitTaskConfig {
  250. skip_sync: true,
  251. checkpoint_height: None,
  252. checkpoint: None,
  253. };
  254. let rpc_settings = RpcSettings {
  255. listen: Url::parse("tcp://127.0.0.1:18245").unwrap(),
  256. ..RpcSettings::default()
  257. };
  258. let management_rpc_settings = RpcSettings {
  259. listen: Url::parse("tcp://127.0.0.1:18246").unwrap(),
  260. ..RpcSettings::default()
  261. };
  262. // Initialize a daemon
  263. let daemon = crate::Darkfid::init(
  264. Network::Mainnet,
  265. &sled_db,
  266. &config,
  267. &darkfi::net::Settings::default(),
  268. &ex,
  269. )
  270. .await
  271. .unwrap();
  272. // Start it
  273. daemon
  274. .start(
  275. &ex,
  276. &rpc_settings,
  277. &management_rpc_settings,
  278. &None,
  279. &None,
  280. &consensus_config,
  281. )
  282. .await
  283. .unwrap();
  284. // Stop it
  285. daemon.stop().await.unwrap();
  286. // Start it again
  287. daemon
  288. .start(
  289. &ex,
  290. &rpc_settings,
  291. &management_rpc_settings,
  292. &None,
  293. &None,
  294. &consensus_config,
  295. )
  296. .await
  297. .unwrap();
  298. // Stop it
  299. daemon.stop().await.unwrap();
  300. // Shutdown entirely
  301. drop(signal);
  302. })
  303. },
  304. );
  305. Ok(())
  306. }