mod.rs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2024 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::{net::Settings, validator::utils::best_fork_index, Result};
  20. use darkfi_contract_test_harness::init_logger;
  21. use darkfi_sdk::num_traits::One;
  22. use num_bigint::BigUint;
  23. use smol::Executor;
  24. use url::Url;
  25. mod harness;
  26. use harness::{generate_node, Harness, HarnessConfig};
  27. mod forks;
  28. async fn sync_blocks_real(ex: Arc<Executor<'static>>) -> Result<()> {
  29. init_logger();
  30. // Initialize harness in testing mode
  31. let pow_target = 90;
  32. let pow_fixed_difficulty = Some(BigUint::one());
  33. let config = HarnessConfig {
  34. pow_target,
  35. pow_fixed_difficulty: pow_fixed_difficulty.clone(),
  36. alice_initial: 1000,
  37. bob_initial: 500,
  38. };
  39. let th = Harness::new(config, true, &ex).await?;
  40. // Retrieve genesis block
  41. let previous = th.alice.validator.blockchain.last_block()?;
  42. // Generate next blocks
  43. let block1 = th.generate_next_block(&previous).await?;
  44. let block2 = th.generate_next_block(&block1).await?;
  45. let block3 = th.generate_next_block(&block2).await?;
  46. let block4 = th.generate_next_block(&block3).await?;
  47. // Add them to nodes
  48. th.add_blocks(&vec![block1, block2, block3.clone(), block4.clone()]).await?;
  49. // Extend current fork sequence
  50. let block5 = th.generate_next_block(&block4).await?;
  51. // Create a new fork extending canonical
  52. let block6 = th.generate_next_block(&block3).await?;
  53. // Add them to nodes
  54. th.add_blocks(&vec![block5, block6.clone()]).await?;
  55. // Validate chains
  56. // Last blocks are not finalized yet
  57. th.validate_chains(4).await?;
  58. // Nodes must have one fork with 2 blocks and one with 1 block
  59. th.validate_fork_chains(2, vec![2, 1]).await;
  60. // We are going to create a third node and try to sync from Bob
  61. let mut sync_settings =
  62. Settings { localnet: true, inbound_connections: 3, ..Default::default() };
  63. let charlie_url = Url::parse("tcp+tls://127.0.0.1:18342")?;
  64. sync_settings.inbound_addrs = vec![charlie_url];
  65. let bob_url = th.bob.sync_p2p.settings().inbound_addrs[0].clone();
  66. sync_settings.peers = vec![bob_url];
  67. let charlie =
  68. generate_node(&th.vks, &th.validator_config, &sync_settings, None, &ex, false).await?;
  69. // Verify node synced
  70. let alice = &th.alice.validator;
  71. let charlie = &charlie.validator;
  72. charlie.validate_blockchain(pow_target, pow_fixed_difficulty.clone()).await?;
  73. assert_eq!(alice.blockchain.len(), charlie.blockchain.len());
  74. // Node must have just the best fork
  75. let forks = alice.consensus.forks.read().await;
  76. let best_fork = &forks[best_fork_index(&forks)?];
  77. let charlie_forks = charlie.consensus.forks.read().await;
  78. assert_eq!(charlie_forks.len(), 1);
  79. assert_eq!(charlie_forks[0].proposals.len(), best_fork.proposals.len());
  80. let small_best = best_fork.proposals.len() == 1;
  81. drop(forks);
  82. drop(charlie_forks);
  83. // Extend the small fork sequence and add it to nodes
  84. let block7 = th.generate_next_block(&block6).await?;
  85. th.add_blocks(&vec![block7.clone()]).await?;
  86. // Nodes must have two forks with 2 blocks each
  87. th.validate_fork_chains(2, vec![2, 2]).await;
  88. // If Charlie already had the small fork as its best,
  89. // it will have a single fork with 2 blocks.
  90. let charlie_forks = charlie.consensus.forks.read().await;
  91. if small_best {
  92. assert_eq!(charlie_forks.len(), 1);
  93. assert_eq!(charlie_forks[0].proposals.len(), 2);
  94. } else {
  95. // Charlie didn't originaly have the fork, but it
  96. // should be synced when its proposal was received
  97. assert_eq!(charlie_forks.len(), 2);
  98. assert_eq!(charlie_forks[0].proposals.len(), 2);
  99. assert_eq!(charlie_forks[1].proposals.len(), 2);
  100. }
  101. drop(charlie_forks);
  102. // Extend the second fork and add it to nodes
  103. let block8 = th.generate_next_block(&block7).await?;
  104. th.add_blocks(&vec![block8.clone()]).await?;
  105. // Nodes must have executed finalization, so we validate their chains
  106. th.validate_chains(6).await?;
  107. let bob = &th.bob.validator;
  108. let last = alice.blockchain.last()?.1;
  109. assert_eq!(last, block7.hash()?);
  110. assert_eq!(last, bob.blockchain.last()?.1);
  111. // Nodes must have one fork with 1 block
  112. th.validate_fork_chains(1, vec![1]).await;
  113. let last_proposal = *alice.consensus.forks.read().await[0].proposals.last().unwrap();
  114. assert_eq!(last_proposal, block8.hash()?);
  115. assert_eq!(&last_proposal, bob.consensus.forks.read().await[0].proposals.last().unwrap());
  116. // Same for Charlie
  117. charlie.finalization().await?;
  118. charlie.validate_blockchain(pow_target, pow_fixed_difficulty).await?;
  119. assert_eq!(alice.blockchain.len(), charlie.blockchain.len());
  120. assert_eq!(last, charlie.blockchain.last()?.1);
  121. let charlie_forks = charlie.consensus.forks.read().await;
  122. assert_eq!(charlie_forks.len(), 1);
  123. assert_eq!(charlie_forks[0].proposals.len(), 1);
  124. assert_eq!(last_proposal, charlie_forks[0].proposals[0]);
  125. // Thanks for reading
  126. Ok(())
  127. }
  128. #[test]
  129. fn sync_blocks() -> Result<()> {
  130. let ex = Arc::new(Executor::new());
  131. let (signal, shutdown) = smol::channel::unbounded::<()>();
  132. easy_parallel::Parallel::new().each(0..4, |_| smol::block_on(ex.run(shutdown.recv()))).finish(
  133. || {
  134. smol::block_on(async {
  135. sync_blocks_real(ex.clone()).await.unwrap();
  136. drop(signal);
  137. })
  138. },
  139. );
  140. Ok(())
  141. }