mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-04-28 03:00:18 -04:00
180 lines
8.1 KiB
Rust
180 lines
8.1 KiB
Rust
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());
|
|
}
|
|
}
|