lib.rs 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. pub mod structures;
  2. #[cfg(test)]
  3. mod tests {
  4. use std::{
  5. thread,
  6. time::{Duration, Instant},
  7. };
  8. use super::structures::{block::Block, node::Node};
  9. use darkfi::{crypto::token_id::generate_id2, util::NetworkName};
  10. #[test]
  11. fn protocol_execution() {
  12. // Genesis block is generated.
  13. let mut genesis_block = Block::new(String::from("⊥"), 0, vec![]);
  14. genesis_block.notarized = true;
  15. genesis_block.finalized = true;
  16. let genesis_time = Instant::now();
  17. // We create some nodes to participate in the Protocol.
  18. let mut node0 = Node::new(0, genesis_time, genesis_block.clone());
  19. let mut node1 = Node::new(1, genesis_time, genesis_block.clone());
  20. let mut node2 = Node::new(2, genesis_time, genesis_block.clone());
  21. // We store nodes public keys for voting.
  22. let node0_public_key = node0.public_key;
  23. let node1_public_key = node1.public_key;
  24. let node2_public_key = node2.public_key;
  25. // We simulate some epochs to test consistency.
  26. let token_id = generate_id2("STREAMLET", &NetworkName::Ethereum).unwrap();
  27. let tx = node0.generate_transaction(token_id, 100, &node1_public_key).unwrap();
  28. node0.receive_transaction(tx.clone());
  29. node0.broadcast_transaction(vec![&mut node1, &mut node2], tx);
  30. let tx = node1.generate_transaction(token_id, 200, &node2_public_key).unwrap();
  31. node1.receive_transaction(tx.clone());
  32. node1.broadcast_transaction(vec![&mut node0, &mut node2], tx);
  33. let tx = node2.generate_transaction(token_id, 300, &node1_public_key).unwrap();
  34. node2.receive_transaction(tx.clone());
  35. node2.broadcast_transaction(vec![&mut node0, &mut node1], tx);
  36. // Each node checks if they are the epoch leader. Leader will propose the block.
  37. let (leader_public_key, block_proposal) = if node0.check_if_epoch_leader(3) {
  38. node0.propose_block()
  39. } else if node1.check_if_epoch_leader(3) {
  40. node1.propose_block()
  41. } else {
  42. node2.propose_block()
  43. };
  44. // Leader broadcasts the proposed_block to rest nodes and they vote on it.
  45. let node0_vote =
  46. node0.receive_proposed_block(&leader_public_key, &block_proposal, 3).unwrap();
  47. let node1_vote =
  48. node1.receive_proposed_block(&leader_public_key, &block_proposal, 3).unwrap();
  49. let node2_vote =
  50. node2.receive_proposed_block(&leader_public_key, &block_proposal, 3).unwrap();
  51. // Each node broadcasts its vote to rest nodes.
  52. node0.receive_vote(&node0_public_key, &node0_vote, 3);
  53. node0.receive_vote(&node1_public_key, &node1_vote, 3);
  54. node0.receive_vote(&node2_public_key, &node2_vote, 3);
  55. node1.receive_vote(&node0_public_key, &node0_vote, 3);
  56. node1.receive_vote(&node1_public_key, &node1_vote, 3);
  57. node1.receive_vote(&node2_public_key, &node2_vote, 3);
  58. node2.receive_vote(&node0_public_key, &node0_vote, 3);
  59. node2.receive_vote(&node1_public_key, &node1_vote, 3);
  60. node2.receive_vote(&node2_public_key, &node2_vote, 3);
  61. // We verify that all nodes have the same blockchain on round end.
  62. verify_outputs(&node0, &node1, &node2);
  63. // We use thread sleep to simulate sinchronization period.
  64. thread::sleep(Duration::new(5, 0));
  65. // Next round.
  66. let tx = node0.generate_transaction(token_id, 400, &node1_public_key).unwrap();
  67. node0.receive_transaction(tx.clone());
  68. node0.broadcast_transaction(vec![&mut node1, &mut node2], tx);
  69. let tx = node1.generate_transaction(token_id, 500, &node2_public_key).unwrap();
  70. node1.receive_transaction(tx.clone());
  71. node1.broadcast_transaction(vec![&mut node0, &mut node2], tx);
  72. //let tx = node2.generate_transaction(token_id, 600, &node1_public_key).unwrap();
  73. //node2.receive_transaction(tx.clone());
  74. //node2.broadcast_transaction(vec![&mut node0, &mut node1], tx);
  75. // Each node checks if they are the epoch leader. Leader will propose the block.
  76. let (leader_public_key, block_proposal) = if node0.check_if_epoch_leader(3) {
  77. node0.propose_block()
  78. } else if node1.check_if_epoch_leader(3) {
  79. node1.propose_block()
  80. } else {
  81. node2.propose_block()
  82. };
  83. // Leader broadcasts the proposed_block to rest nodes and they vote on it.
  84. let node0_vote =
  85. node0.receive_proposed_block(&leader_public_key, &block_proposal, 3).unwrap();
  86. let node1_vote =
  87. node1.receive_proposed_block(&leader_public_key, &block_proposal, 3).unwrap();
  88. let node2_vote =
  89. node2.receive_proposed_block(&leader_public_key, &block_proposal, 3).unwrap();
  90. // Each node broadcasts its vote to rest nodes.
  91. node0.receive_vote(&node0_public_key, &node0_vote, 3);
  92. node0.receive_vote(&node1_public_key, &node1_vote, 3);
  93. node0.receive_vote(&node2_public_key, &node2_vote, 3);
  94. node1.receive_vote(&node0_public_key, &node0_vote, 3);
  95. node1.receive_vote(&node1_public_key, &node1_vote, 3);
  96. node1.receive_vote(&node2_public_key, &node2_vote, 3);
  97. node2.receive_vote(&node0_public_key, &node0_vote, 3);
  98. node2.receive_vote(&node1_public_key, &node1_vote, 3);
  99. node2.receive_vote(&node2_public_key, &node2_vote, 3);
  100. // We verify that all nodes have the same blockchain on round end.
  101. verify_outputs(&node0, &node1, &node2);
  102. // We use thread sleep to simulate sinchronization period.
  103. thread::sleep(Duration::new(5, 0));
  104. // Next round.
  105. let tx = node0.generate_transaction(token_id, 700, &node1_public_key).unwrap();
  106. node0.receive_transaction(tx.clone());
  107. node0.broadcast_transaction(vec![&mut node1, &mut node2], tx);
  108. //let tx = node1.generate_transaction(token_id, 800, &node2_public_key).unwrap();
  109. //node1.receive_transaction(tx.clone());
  110. //node1.broadcast_transaction(vec![&mut node0, &mut node2], tx);
  111. //let tx = node2.generate_transaction(token_id, 900, &node1_public_key).unwrap();
  112. //node2.receive_transaction(tx.clone());
  113. //node2.broadcast_transaction(vec![&mut node0, &mut node1], tx);
  114. // Each node checks if they are the epoch leader. Leader will propose the block.
  115. let (leader_public_key, block_proposal) = if node0.check_if_epoch_leader(3) {
  116. node0.propose_block()
  117. } else if node1.check_if_epoch_leader(3) {
  118. node1.propose_block()
  119. } else {
  120. node2.propose_block()
  121. };
  122. // Leader broadcasts the proposed_block to rest nodes and they vote on it.
  123. let node0_vote =
  124. node0.receive_proposed_block(&leader_public_key, &block_proposal, 3).unwrap();
  125. let node1_vote =
  126. node1.receive_proposed_block(&leader_public_key, &block_proposal, 3).unwrap();
  127. let node2_vote =
  128. node2.receive_proposed_block(&leader_public_key, &block_proposal, 3).unwrap();
  129. // Each node broadcasts its vote to rest nodes.
  130. node0.receive_vote(&node0_public_key, &node0_vote, 3);
  131. node0.receive_vote(&node1_public_key, &node1_vote, 3);
  132. node0.receive_vote(&node2_public_key, &node2_vote, 3);
  133. node1.receive_vote(&node0_public_key, &node0_vote, 3);
  134. node1.receive_vote(&node1_public_key, &node1_vote, 3);
  135. node1.receive_vote(&node2_public_key, &node2_vote, 3);
  136. node2.receive_vote(&node0_public_key, &node0_vote, 3);
  137. node2.receive_vote(&node1_public_key, &node1_vote, 3);
  138. node2.receive_vote(&node2_public_key, &node2_vote, 3);
  139. // We verify that all nodes have the same blockchain on round end.
  140. verify_outputs(&node0, &node1, &node2);
  141. }
  142. fn verify_outputs(node0: &Node, node1: &Node, node2: &Node) {
  143. assert!(node0.output() == node1.output());
  144. assert!(node1.output() == node2.output());
  145. }
  146. }