| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- pub mod structures;
- #[cfg(test)]
- mod tests {
- use std::{
- thread,
- time::{Duration, Instant},
- };
- use super::structures::{block::Block, node::Node};
- use darkfi::{crypto::token_id::generate_id2, util::NetworkName};
- #[test]
- fn protocol_execution() {
- // Genesis block is generated.
- let mut genesis_block = Block::new(
- String::from("⊥"),
- 0,
- vec![],
- String::from("proof"),
- String::from("r"),
- String::from("s"),
- );
- genesis_block.metadata.sm.notarized = true;
- genesis_block.metadata.sm.finalized = true;
- let genesis_time = Instant::now();
- // We create some nodes to participate in the Protocol.
- let mut node0 = Node::new(0, genesis_time, genesis_block.clone());
- let mut node1 = Node::new(1, genesis_time, genesis_block.clone());
- let mut node2 = Node::new(2, genesis_time, genesis_block.clone());
- // We store nodes public keys for voting.
- let node0_public_key = node0.public_key;
- let node1_public_key = node1.public_key;
- let node2_public_key = node2.public_key;
- // We simulate some epochs to test consistency.
- let token_id = generate_id2("STREAMLET", &NetworkName::Ethereum).unwrap();
- let tx = node0.generate_transaction(token_id, 100, &node1_public_key).unwrap();
- node0.receive_transaction(tx.clone());
- node0.broadcast_transaction(vec![&mut node1, &mut node2], tx);
- let tx = node1.generate_transaction(token_id, 200, &node2_public_key).unwrap();
- node1.receive_transaction(tx.clone());
- node1.broadcast_transaction(vec![&mut node0, &mut node2], tx);
- let tx = node2.generate_transaction(token_id, 300, &node1_public_key).unwrap();
- node2.receive_transaction(tx.clone());
- node2.broadcast_transaction(vec![&mut node0, &mut node1], tx);
- // Each node checks if they are the epoch leader. Leader will propose the block.
- let (leader_public_key, block_proposal) = if node0.check_if_epoch_leader(3) {
- node0.propose_block()
- } else if node1.check_if_epoch_leader(3) {
- node1.propose_block()
- } else {
- node2.propose_block()
- };
- // Leader broadcasts the proposed_block to rest nodes and they vote on it.
- let node0_vote =
- node0.receive_proposed_block(&leader_public_key, &block_proposal, 3).unwrap();
- let node1_vote =
- node1.receive_proposed_block(&leader_public_key, &block_proposal, 3).unwrap();
- let node2_vote =
- node2.receive_proposed_block(&leader_public_key, &block_proposal, 3).unwrap();
- // Each node broadcasts its vote to rest nodes.
- node0.receive_vote(&node0_public_key, &node0_vote, 3);
- node0.receive_vote(&node1_public_key, &node1_vote, 3);
- node0.receive_vote(&node2_public_key, &node2_vote, 3);
- node1.receive_vote(&node0_public_key, &node0_vote, 3);
- node1.receive_vote(&node1_public_key, &node1_vote, 3);
- node1.receive_vote(&node2_public_key, &node2_vote, 3);
- node2.receive_vote(&node0_public_key, &node0_vote, 3);
- node2.receive_vote(&node1_public_key, &node1_vote, 3);
- node2.receive_vote(&node2_public_key, &node2_vote, 3);
- // We verify that all nodes have the same blockchain on round end.
- verify_outputs(&node0, &node1, &node2);
- // We use thread sleep to simulate sinchronization period.
- thread::sleep(Duration::new(5, 0));
- // Next round.
- let tx = node0.generate_transaction(token_id, 400, &node1_public_key).unwrap();
- node0.receive_transaction(tx.clone());
- node0.broadcast_transaction(vec![&mut node1, &mut node2], tx);
- let tx = node1.generate_transaction(token_id, 500, &node2_public_key).unwrap();
- node1.receive_transaction(tx.clone());
- node1.broadcast_transaction(vec![&mut node0, &mut node2], tx);
- //let tx = node2.generate_transaction(token_id, 600, &node1_public_key).unwrap();
- //node2.receive_transaction(tx.clone());
- //node2.broadcast_transaction(vec![&mut node0, &mut node1], tx);
- // Each node checks if they are the epoch leader. Leader will propose the block.
- let (leader_public_key, block_proposal) = if node0.check_if_epoch_leader(3) {
- node0.propose_block()
- } else if node1.check_if_epoch_leader(3) {
- node1.propose_block()
- } else {
- node2.propose_block()
- };
- // Leader broadcasts the proposed_block to rest nodes and they vote on it.
- let node0_vote =
- node0.receive_proposed_block(&leader_public_key, &block_proposal, 3).unwrap();
- let node1_vote =
- node1.receive_proposed_block(&leader_public_key, &block_proposal, 3).unwrap();
- let node2_vote =
- node2.receive_proposed_block(&leader_public_key, &block_proposal, 3).unwrap();
- // Each node broadcasts its vote to rest nodes.
- node0.receive_vote(&node0_public_key, &node0_vote, 3);
- node0.receive_vote(&node1_public_key, &node1_vote, 3);
- node0.receive_vote(&node2_public_key, &node2_vote, 3);
- node1.receive_vote(&node0_public_key, &node0_vote, 3);
- node1.receive_vote(&node1_public_key, &node1_vote, 3);
- node1.receive_vote(&node2_public_key, &node2_vote, 3);
- node2.receive_vote(&node0_public_key, &node0_vote, 3);
- node2.receive_vote(&node1_public_key, &node1_vote, 3);
- node2.receive_vote(&node2_public_key, &node2_vote, 3);
- // We verify that all nodes have the same blockchain on round end.
- verify_outputs(&node0, &node1, &node2);
- // We use thread sleep to simulate sinchronization period.
- thread::sleep(Duration::new(5, 0));
- // Next round.
- let tx = node0.generate_transaction(token_id, 700, &node1_public_key).unwrap();
- node0.receive_transaction(tx.clone());
- node0.broadcast_transaction(vec![&mut node1, &mut node2], tx);
- //let tx = node1.generate_transaction(token_id, 800, &node2_public_key).unwrap();
- //node1.receive_transaction(tx.clone());
- //node1.broadcast_transaction(vec![&mut node0, &mut node2], tx);
- //let tx = node2.generate_transaction(token_id, 900, &node1_public_key).unwrap();
- //node2.receive_transaction(tx.clone());
- //node2.broadcast_transaction(vec![&mut node0, &mut node1], tx);
- // Each node checks if they are the epoch leader. Leader will propose the block.
- let (leader_public_key, block_proposal) = if node0.check_if_epoch_leader(3) {
- node0.propose_block()
- } else if node1.check_if_epoch_leader(3) {
- node1.propose_block()
- } else {
- node2.propose_block()
- };
- // Leader broadcasts the proposed_block to rest nodes and they vote on it.
- let node0_vote =
- node0.receive_proposed_block(&leader_public_key, &block_proposal, 3).unwrap();
- let node1_vote =
- node1.receive_proposed_block(&leader_public_key, &block_proposal, 3).unwrap();
- let node2_vote =
- node2.receive_proposed_block(&leader_public_key, &block_proposal, 3).unwrap();
- // Each node broadcasts its vote to rest nodes.
- node0.receive_vote(&node0_public_key, &node0_vote, 3);
- node0.receive_vote(&node1_public_key, &node1_vote, 3);
- node0.receive_vote(&node2_public_key, &node2_vote, 3);
- node1.receive_vote(&node0_public_key, &node0_vote, 3);
- node1.receive_vote(&node1_public_key, &node1_vote, 3);
- node1.receive_vote(&node2_public_key, &node2_vote, 3);
- node2.receive_vote(&node0_public_key, &node0_vote, 3);
- node2.receive_vote(&node1_public_key, &node1_vote, 3);
- node2.receive_vote(&node2_public_key, &node2_vote, 3);
- // We verify that all nodes have the same blockchain on round end.
- verify_outputs(&node0, &node1, &node2);
- }
- fn verify_outputs(node0: &Node, node1: &Node, node2: &Node) {
- assert!(node0.output() == node1.output());
- assert!(node1.output() == node2.output());
- }
- }
|