Kaynağa Gözat

make fix and cargo fmt.

Luther Blissett 3 yıl önce
ebeveyn
işleme
88abda32ce
43 değiştirilmiş dosya ile 1156 ekleme ve 1163 silme
  1. 2 0
      bin/dao-cli/src/main.rs
  2. 1 1
      bin/daod/src/dao_contract/exec/validate.rs
  3. 1 1
      bin/daod/src/dao_contract/mint/validate.rs
  4. 2 2
      bin/daod/src/dao_contract/propose/validate.rs
  5. 2 2
      bin/daod/src/dao_contract/vote/validate.rs
  6. 34 34
      bin/daod/src/demo.rs
  7. 1 1
      bin/daod/src/example_contract/foo/validate.rs
  8. 1 1
      bin/daod/src/money_contract/state.rs
  9. 2 2
      bin/daod/src/money_contract/transfer/validate.rs
  10. 1 1
      bin/daod/src/money_contract/transfer/wallet.rs
  11. 5 5
      bin/darkwiki/darkwikid/src/main.rs
  12. 3 3
      bin/darkwiki/darkwikid/src/patch.rs
  13. 2 3
      bin/dnetview/src/main.rs
  14. 7 12
      bin/dnetview/src/view.rs
  15. 8 8
      bin/fud/fud/src/main.rs
  16. 2 1
      bin/ircd/src/buffers.rs
  17. 37 30
      bin/ircd/src/model.rs
  18. 5 3
      bin/ircd/src/protocol_privmsg2.rs
  19. 1 1
      bin/ircd/src/view.rs
  20. 6 6
      bin/ircd2/src/crypto.rs
  21. 6 10
      bin/ircd2/src/irc/client.rs
  22. 1 1
      bin/ircd2/src/main.rs
  23. 36 30
      bin/ircd2/src/model.rs
  24. 2 2
      bin/ircd2/src/protocol_event.rs
  25. 3 3
      bin/ircd2/src/settings.rs
  26. 4 3
      bin/lilith/src/main.rs
  27. 1 3
      bin/tau/taud/src/error.rs
  28. 7 8
      bin/tau/taud/src/jsonrpc.rs
  29. 3 3
      bin/tau/taud/src/main.rs
  30. 3 3
      bin/tau/taud/src/task_info.rs
  31. 3 5
      example/crypsinous.rs
  32. 3 4
      example/lead.rs
  33. 11 7
      src/blockchain/epoch.rs
  34. 7 10
      src/consensus/state.rs
  35. 0 319
      src/dht/dht.rs
  36. 316 3
      src/dht/mod.rs
  37. 1 1
      src/dht/protocol.rs
  38. 1 1
      src/net/hosts.rs
  39. 1 1
      src/net/session/outbound_session.rs
  40. 1 0
      src/rpc/websockets.rs
  41. 621 2
      src/stakeholder/mod.rs
  42. 0 622
      src/stakeholder/stakeholder.rs
  43. 2 5
      src/util/clock.rs

+ 2 - 0
bin/dao-cli/src/main.rs

@@ -40,6 +40,8 @@ impl Rpc {
 async fn start(options: CliDao) -> Result<()> {
     let rpc_addr = "tcp://127.0.0.1:7777";
     let client = Rpc { client: RpcClient::new(Url::parse(rpc_addr)?).await? };
+
+    #[allow(clippy::single_match)]
     match options.command {
         Some(CliDaoSubCommands::Hello {}) => {
             let reply = client.say_hello().await?;

+ 1 - 1
bin/daod/src/dao_contract/exec/validate.rs

@@ -115,7 +115,7 @@ pub fn state_transition(
     let func_call = &parent_tx.func_calls[func_call_index];
     let call_data = func_call.call_data.as_any();
 
-    assert_eq!((&*call_data).type_id(), TypeId::of::<CallData>());
+    assert_eq!((*call_data).type_id(), TypeId::of::<CallData>());
     let call_data = call_data.downcast_ref::<CallData>();
 
     // This will be inside wasm so unwrap is fine.

+ 1 - 1
bin/daod/src/dao_contract/mint/validate.rs

@@ -18,7 +18,7 @@ pub fn state_transition(
     let func_call = &parent_tx.func_calls[func_call_index];
     let call_data = func_call.call_data.as_any();
 
-    assert_eq!((&*call_data).type_id(), TypeId::of::<CallData>());
+    assert_eq!((*call_data).type_id(), TypeId::of::<CallData>());
     let call_data = call_data.downcast_ref::<CallData>();
 
     // This will be inside wasm so unwrap is fine.

+ 2 - 2
bin/daod/src/dao_contract/propose/validate.rs

@@ -53,7 +53,7 @@ impl CallDataBase for CallData {
         let mut zk_publics = Vec::new();
         let mut total_funds_commit = pallas::Point::identity();
 
-        assert!(self.inputs.len() > 0, "inputs length cannot be zero");
+        assert!(!self.inputs.is_empty(), "inputs length cannot be zero");
         for input in &self.inputs {
             total_funds_commit += input.value_commit;
             let value_coords = input.value_commit.to_affine().coordinates().unwrap();
@@ -131,7 +131,7 @@ pub fn state_transition(
     let func_call = &parent_tx.func_calls[func_call_index];
     let call_data = func_call.call_data.as_any();
 
-    assert_eq!((&*call_data).type_id(), TypeId::of::<CallData>());
+    assert_eq!((*call_data).type_id(), TypeId::of::<CallData>());
     let call_data = call_data.downcast_ref::<CallData>();
 
     // This will be inside wasm so unwrap is fine.

+ 2 - 2
bin/daod/src/dao_contract/vote/validate.rs

@@ -58,7 +58,7 @@ impl CallDataBase for CallData {
         let mut zk_publics = Vec::new();
         let mut all_votes_commit = pallas::Point::identity();
 
-        assert!(self.inputs.len() > 0, "inputs length cannot be zero");
+        assert!(!self.inputs.is_empty(), "inputs length cannot be zero");
         for input in &self.inputs {
             all_votes_commit += input.vote_commit;
             let value_coords = input.vote_commit.to_affine().coordinates().unwrap();
@@ -142,7 +142,7 @@ pub fn state_transition(
     let func_call = &parent_tx.func_calls[func_call_index];
     let call_data = func_call.call_data.as_any();
 
-    assert_eq!((&*call_data).type_id(), TypeId::of::<CallData>());
+    assert_eq!((*call_data).type_id(), TypeId::of::<CallData>());
     let call_data = call_data.downcast_ref::<CallData>();
 
     // This will be inside wasm so unwrap is fine.

+ 34 - 34
bin/daod/src/demo.rs

@@ -51,6 +51,7 @@ type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
 #[derive(Eq, PartialEq)]
 pub struct HashableBase(pub pallas::Base);
 
+// FIXME: TODO: This should need Hash, use something else like a b58 string.
 impl std::hash::Hash for HashableBase {
     fn hash<H: Hasher>(&self, state: &mut H) {
         let bytes = self.0.to_repr();
@@ -136,12 +137,12 @@ impl Transaction {
                 match zk_bins.lookup(key).unwrap() {
                     ZkContractInfo::Binary(info) => {
                         let verifying_key = &info.verifying_key;
-                        let verify_result = proof.verify(&verifying_key, public_vals);
+                        let verify_result = proof.verify(verifying_key, public_vals);
                         assert!(verify_result.is_ok(), "verify proof[{}]='{}' failed", i, key);
                     }
                     ZkContractInfo::Native(info) => {
                         let verifying_key = &info.verifying_key;
-                        let verify_result = proof.verify(&verifying_key, public_vals);
+                        let verify_result = proof.verify(verifying_key, public_vals);
                         assert!(verify_result.is_ok(), "verify proof[{}]='{}' failed", i, key);
                     }
                 };
@@ -166,7 +167,7 @@ impl Transaction {
     }
 }
 
-fn sign(signature_secrets: Vec<SecretKey>, func_calls: &Vec<FuncCall>) -> Vec<Signature> {
+fn sign(signature_secrets: &[SecretKey], func_calls: &[FuncCall]) -> Vec<Signature> {
     let mut signatures = vec![];
     let mut unsigned_tx_data = vec![];
     for (_i, (signature_secret, func_call)) in
@@ -233,11 +234,13 @@ impl StateRegistry {
         self.states.insert(HashableBase(contract_id), state);
     }
 
-    pub fn lookup_mut<'a, S: 'static>(&'a mut self, contract_id: ContractId) -> Option<&'a mut S> {
+    //pub fn lookup_mut<'a, S: 'static>(&'a mut self, contract_id: ContractId) -> Option<&'a mut S> {
+    pub fn lookup_mut<S: 'static>(&mut self, contract_id: ContractId) -> Option<&mut S> {
         self.states.get_mut(&HashableBase(contract_id)).and_then(|state| state.downcast_mut())
     }
 
-    pub fn lookup<'a, S: 'static>(&'a self, contract_id: ContractId) -> Option<&'a S> {
+    //pub fn lookup<'a, S: 'static>(&'a self, contract_id: ContractId) -> Option<&'a S> {
+    pub fn lookup<S: 'static>(&self, contract_id: ContractId) -> Option<&S> {
         self.states.get(&HashableBase(contract_id)).and_then(|state| state.downcast_ref())
     }
 }
@@ -266,14 +269,14 @@ pub async fn example() -> Result<()> {
 
     //// Wallet
 
-    let foo = example_contract::foo::wallet::Foo { a: 5, b: 10 };
+    let foo_w = example_contract::foo::wallet::Foo { a: 5, b: 10 };
     let signature_secret = SecretKey::random(&mut OsRng);
 
-    let builder = example_contract::foo::wallet::Builder { foo, signature_secret };
+    let builder = example_contract::foo::wallet::Builder { foo: foo_w, signature_secret };
     let func_call = builder.build(&zk_bins);
     let func_calls = vec![func_call];
 
-    let signatures = sign(vec![signature_secret], &func_calls);
+    let signatures = sign(&[signature_secret], &func_calls);
     let tx = Transaction { func_calls, signatures };
 
     //// Validator
@@ -412,7 +415,7 @@ pub async fn demo() -> Result<()> {
     let func_call = builder.build(&zk_bins);
     let func_calls = vec![func_call];
 
-    let signatures = sign(vec![signature_secret], &func_calls);
+    let signatures = sign(&[signature_secret], &func_calls);
     let tx = Transaction { func_calls, signatures };
 
     //// Validator
@@ -457,7 +460,7 @@ pub async fn demo() -> Result<()> {
         assert_eq!(tx.func_calls.len(), 1);
         let func_call = &tx.func_calls[0];
         let call_data = func_call.call_data.as_any();
-        assert_eq!((&*call_data).type_id(), TypeId::of::<dao_contract::mint::validate::CallData>());
+        assert_eq!((*call_data).type_id(), TypeId::of::<dao_contract::mint::validate::CallData>());
         let call_data = call_data.downcast_ref::<dao_contract::mint::validate::CallData>().unwrap();
         call_data.dao_bulla.clone()
     };
@@ -509,7 +512,7 @@ pub async fn demo() -> Result<()> {
     let func_call = builder.build(&zk_bins)?;
     let func_calls = vec![func_call];
 
-    let signatures = sign(vec![cashier_signature_secret], &func_calls);
+    let signatures = sign(&[cashier_signature_secret], &func_calls);
     let tx = Transaction { func_calls, signatures };
 
     //// Validator
@@ -636,7 +639,7 @@ pub async fn demo() -> Result<()> {
     let func_call = builder.build(&zk_bins)?;
     let func_calls = vec![func_call];
 
-    let signatures = sign(vec![cashier_signature_secret], &func_calls);
+    let signatures = sign(&[cashier_signature_secret], &func_calls);
     let tx = Transaction { func_calls, signatures };
 
     //// Validator
@@ -730,7 +733,7 @@ pub async fn demo() -> Result<()> {
     let (money_leaf_position, money_merkle_path) = {
         let state = states.lookup::<money_contract::State>(*money_contract::CONTRACT_ID).unwrap();
         let tree = &state.tree;
-        let leaf_position = gov_recv[0].leaf_position.clone();
+        let leaf_position = gov_recv[0].leaf_position;
         let root = tree.root(0).unwrap();
         let merkle_path = tree.authentication_path(leaf_position, &root).unwrap();
         (leaf_position, merkle_path)
@@ -775,7 +778,7 @@ pub async fn demo() -> Result<()> {
 
     let builder = dao_contract::propose::wallet::Builder {
         inputs: vec![input],
-        proposal: proposal.clone(),
+        proposal,
         dao: dao_params.clone(),
         dao_leaf_position,
         dao_merkle_path,
@@ -785,7 +788,7 @@ pub async fn demo() -> Result<()> {
     let func_call = builder.build(&zk_bins);
     let func_calls = vec![func_call];
 
-    let signatures = sign(vec![signature_secret], &func_calls);
+    let signatures = sign(&[signature_secret], &func_calls);
     let tx = Transaction { func_calls, signatures };
 
     //// Validator
@@ -818,7 +821,7 @@ pub async fn demo() -> Result<()> {
         let func_call = &tx.func_calls[0];
         let call_data = func_call.call_data.as_any();
         assert_eq!(
-            (&*call_data).type_id(),
+            (*call_data).type_id(),
             TypeId::of::<dao_contract::propose::validate::CallData>()
         );
         let call_data =
@@ -874,7 +877,7 @@ pub async fn demo() -> Result<()> {
     let (money_leaf_position, money_merkle_path) = {
         let state = states.lookup::<money_contract::State>(*money_contract::CONTRACT_ID).unwrap();
         let tree = &state.tree;
-        let leaf_position = gov_recv[0].leaf_position.clone();
+        let leaf_position = gov_recv[0].leaf_position;
         let root = tree.root(0).unwrap();
         let merkle_path = tree.authentication_path(leaf_position, &root).unwrap();
         (leaf_position, merkle_path)
@@ -890,8 +893,7 @@ pub async fn demo() -> Result<()> {
     };
 
     let vote_option: bool = true;
-
-    assert!(vote_option == true || vote_option == false);
+    // assert!(vote_option || !vote_option); // wtf
 
     // We create a new keypair to encrypt the vote.
     // For the demo MVP, you can just use the dao_keypair secret
@@ -911,7 +913,7 @@ pub async fn demo() -> Result<()> {
     let func_call = builder.build(&zk_bins);
     let func_calls = vec![func_call];
 
-    let signatures = sign(vec![signature_secret], &func_calls);
+    let signatures = sign(&[signature_secret], &func_calls);
     let tx = Transaction { func_calls, signatures };
 
     //// Validator
@@ -945,7 +947,7 @@ pub async fn demo() -> Result<()> {
         assert_eq!(tx.func_calls.len(), 1);
         let func_call = &tx.func_calls[0];
         let call_data = func_call.call_data.as_any();
-        assert_eq!((&*call_data).type_id(), TypeId::of::<dao_contract::vote::validate::CallData>());
+        assert_eq!((*call_data).type_id(), TypeId::of::<dao_contract::vote::validate::CallData>());
         let call_data = call_data.downcast_ref::<dao_contract::vote::validate::CallData>().unwrap();
 
         let header = &call_data.header;
@@ -962,7 +964,7 @@ pub async fn demo() -> Result<()> {
     let (money_leaf_position, money_merkle_path) = {
         let state = states.lookup::<money_contract::State>(*money_contract::CONTRACT_ID).unwrap();
         let tree = &state.tree;
-        let leaf_position = gov_recv[1].leaf_position.clone();
+        let leaf_position = gov_recv[1].leaf_position;
         let root = tree.root(0).unwrap();
         let merkle_path = tree.authentication_path(leaf_position, &root).unwrap();
         (leaf_position, merkle_path)
@@ -978,8 +980,7 @@ pub async fn demo() -> Result<()> {
     };
 
     let vote_option: bool = false;
-
-    assert!(vote_option == true || vote_option == false);
+    // assert!(vote_option || !vote_option); // wtf
 
     // We create a new keypair to encrypt the vote.
     let vote_keypair_2 = Keypair::random(&mut OsRng);
@@ -998,7 +999,7 @@ pub async fn demo() -> Result<()> {
     let func_call = builder.build(&zk_bins);
     let func_calls = vec![func_call];
 
-    let signatures = sign(vec![signature_secret], &func_calls);
+    let signatures = sign(&[signature_secret], &func_calls);
     let tx = Transaction { func_calls, signatures };
 
     //// Validator
@@ -1032,7 +1033,7 @@ pub async fn demo() -> Result<()> {
         assert_eq!(tx.func_calls.len(), 1);
         let func_call = &tx.func_calls[0];
         let call_data = func_call.call_data.as_any();
-        assert_eq!((&*call_data).type_id(), TypeId::of::<dao_contract::vote::validate::CallData>());
+        assert_eq!((*call_data).type_id(), TypeId::of::<dao_contract::vote::validate::CallData>());
         let call_data = call_data.downcast_ref::<dao_contract::vote::validate::CallData>().unwrap();
 
         let header = &call_data.header;
@@ -1049,7 +1050,7 @@ pub async fn demo() -> Result<()> {
     let (money_leaf_position, money_merkle_path) = {
         let state = states.lookup::<money_contract::State>(*money_contract::CONTRACT_ID).unwrap();
         let tree = &state.tree;
-        let leaf_position = gov_recv[2].leaf_position.clone();
+        let leaf_position = gov_recv[2].leaf_position;
         let root = tree.root(0).unwrap();
         let merkle_path = tree.authentication_path(leaf_position, &root).unwrap();
         (leaf_position, merkle_path)
@@ -1065,8 +1066,7 @@ pub async fn demo() -> Result<()> {
     };
 
     let vote_option: bool = true;
-
-    assert!(vote_option == true || vote_option == false);
+    // assert!(vote_option || !vote_option); // wtf
 
     // We create a new keypair to encrypt the vote.
     let vote_keypair_3 = Keypair::random(&mut OsRng);
@@ -1085,7 +1085,7 @@ pub async fn demo() -> Result<()> {
     let func_call = builder.build(&zk_bins);
     let func_calls = vec![func_call];
 
-    let signatures = sign(vec![signature_secret], &func_calls);
+    let signatures = sign(&[signature_secret], &func_calls);
     let tx = Transaction { func_calls, signatures };
 
     //// Validator
@@ -1119,7 +1119,7 @@ pub async fn demo() -> Result<()> {
         assert_eq!(tx.func_calls.len(), 1);
         let func_call = &tx.func_calls[0];
         let call_data = func_call.call_data.as_any();
-        assert_eq!((&*call_data).type_id(), TypeId::of::<dao_contract::vote::validate::CallData>());
+        assert_eq!((*call_data).type_id(), TypeId::of::<dao_contract::vote::validate::CallData>());
         let call_data = call_data.downcast_ref::<dao_contract::vote::validate::CallData>().unwrap();
 
         let header = &call_data.header;
@@ -1208,7 +1208,7 @@ pub async fn demo() -> Result<()> {
     let (treasury_leaf_position, treasury_merkle_path) = {
         let state = states.lookup::<money_contract::State>(*money_contract::CONTRACT_ID).unwrap();
         let tree = &state.tree;
-        let leaf_position = dao_recv_coin.leaf_position.clone();
+        let leaf_position = dao_recv_coin.leaf_position;
         let root = tree.root(0).unwrap();
         let merkle_path = tree.authentication_path(leaf_position, &root).unwrap();
         (leaf_position, merkle_path)
@@ -1272,7 +1272,7 @@ pub async fn demo() -> Result<()> {
     let exec_func_call = builder.build(&zk_bins);
     let func_calls = vec![transfer_func_call, exec_func_call];
 
-    let signatures = sign(vec![tx_signature_secret, exec_signature_secret], &func_calls);
+    let signatures = sign(&[tx_signature_secret, exec_signature_secret], &func_calls);
     let tx = Transaction { func_calls, signatures };
 
     {
@@ -1284,7 +1284,7 @@ pub async fn demo() -> Result<()> {
         let transfer_call_data = transfer_func_call.call_data.as_any();
 
         assert_eq!(
-            (&*transfer_call_data).type_id(),
+            (*transfer_call_data).type_id(),
             TypeId::of::<money_contract::transfer::validate::CallData>()
         );
         let transfer_call_data =

+ 1 - 1
bin/daod/src/example_contract/foo/validate.rs

@@ -65,7 +65,7 @@ pub fn state_transition(
     let func_call = &parent_tx.func_calls[func_call_index];
     let call_data = func_call.call_data.as_any();
 
-    assert_eq!((&*call_data).type_id(), TypeId::of::<CallData>());
+    assert_eq!((*call_data).type_id(), TypeId::of::<CallData>());
     let call_data = call_data.downcast_ref::<CallData>();
 
     // This will be inside wasm so unwrap is fine.

+ 1 - 1
bin/daod/src/money_contract/state.rs

@@ -41,7 +41,7 @@ impl WalletCache {
         for (other_secret, own_coins) in self.cache.iter_mut() {
             if *secret == *other_secret {
                 // clear own_coins vec, and return current contents
-                return std::mem::replace(own_coins, Vec::new())
+                return std::mem::take(own_coins)
             }
         }
         panic!("you forget to track() this secret!");

+ 2 - 2
bin/daod/src/money_contract/transfer/validate.rs

@@ -72,7 +72,7 @@ pub fn state_transition(
     let func_call = &parent_tx.func_calls[func_call_index];
     let call_data = func_call.call_data.as_any();
 
-    assert_eq!((&*call_data).type_id(), TypeId::of::<CallData>());
+    assert_eq!((*call_data).type_id(), TypeId::of::<CallData>());
     let call_data = call_data.downcast_ref::<CallData>();
 
     // This will be inside wasm so unwrap is fine.
@@ -219,7 +219,7 @@ impl CallData {
             error!("tx::verify(): Missing inputs");
             return Err(VerifyFailed::LackingInputs)
         }
-        if self.outputs.len() == 0 {
+        if self.outputs.is_empty() {
             error!("tx::verify(): Missing outputs");
             return Err(VerifyFailed::LackingOutputs)
         }

+ 1 - 1
bin/daod/src/money_contract/transfer/wallet.rs

@@ -155,7 +155,7 @@ impl Builder {
         let mut outputs = vec![];
         let mut output_blinds = vec![];
         // This value_blind calc assumes there will always be at least a single output
-        assert!(self.outputs.len() > 0);
+        assert!(!self.outputs.is_empty());
 
         for (i, output) in self.outputs.iter().enumerate() {
             let value_blind = if i == self.outputs.len() - 1 {

+ 5 - 5
bin/darkwiki/darkwikid/src/main.rs

@@ -224,7 +224,7 @@ impl Darkwiki {
                 }
                 patch = self.raft.1.recv().fuse() => {
                     for (workspace, salsa_box) in self.workspaces.iter() {
-                        if let Ok(mut patch) = decrypt_patch(&patch.clone()?, &salsa_box) {
+                        if let Ok(mut patch) = decrypt_patch(&patch.clone()?, salsa_box) {
                             info!("[{}] Receive a {:?}", workspace, patch);
                             patch.workspace = workspace.clone();
                             self.on_receive_patch(&patch)?;
@@ -260,7 +260,7 @@ impl Darkwiki {
             sync_patch.author = received_patch.author.clone();
             save_json_file::<Patch>(&sync_id_path, &sync_patch)?;
         } else if !received_patch.base.is_empty() {
-            save_json_file::<Patch>(&sync_id_path, &received_patch)?;
+            save_json_file::<Patch>(&sync_id_path, received_patch)?;
         }
 
         Ok(())
@@ -291,7 +291,7 @@ impl Darkwiki {
             if !dry {
                 for patch in patches {
                     info!("Send a {:?}", patch);
-                    let encrypt_patch = encrypt_patch(&patch, &salsa_box, rng)?;
+                    let encrypt_patch = encrypt_patch(&patch, salsa_box, rng)?;
                     self.raft.0.send(encrypt_patch).await?;
                 }
             }
@@ -379,7 +379,7 @@ impl Darkwiki {
         // save and compare docs in darkwiki and local dirs
         // then merged with sync patches if any received
         let mut docs = vec![];
-        get_docs_paths(&mut docs, &docs_path, None)?;
+        get_docs_paths(&mut docs, docs_path, None)?;
         for doc in docs {
             let doc_path = doc.to_str().unwrap();
 
@@ -582,7 +582,7 @@ async fn realmain(settings: Args, executor: Arc<Executor<'_>>) -> Result<()> {
         loop {
             println!("Name for the new workspace: ");
             let mut workspace = String::new();
-            stdin().read_line(&mut workspace).ok().expect("Failed to read line");
+            stdin().read_line(&mut workspace).expect("Failed to read line");
             let workspace = workspace.to_lowercase();
             let workspace = workspace.trim();
             if workspace.is_empty() && workspace.len() < 3 {

+ 3 - 3
bin/darkwiki/darkwikid/src/patch.rs

@@ -507,7 +507,7 @@ mod tests {
         patch1.insert("ex");
         patch1.retain(7);
 
-        let mut patch2 = patch_init.clone();
+        let mut patch2 = patch_init;
         patch2.delete(4);
         patch2.insert("new");
         patch2.retain(13);
@@ -544,7 +544,7 @@ mod tests {
         patch1.insert("ex");
         patch1.retain(7);
 
-        let mut patch2 = patch_init.clone();
+        let mut patch2 = patch_init;
         patch2.delete(4);
         patch2.insert("new");
         patch2.retain(13);
@@ -565,7 +565,7 @@ mod tests {
         patch1.retain(13);
         patch1.insert(" world");
 
-        let mut patch2 = patch_init.clone();
+        let mut patch2 = patch_init;
         patch2.retain(1);
         patch2.delete(5);
         patch2.insert("this is the title");

+ 2 - 3
bin/dnetview/src/main.rs

@@ -73,9 +73,8 @@ impl DnetView {
                 }
             })?;
 
-            match err {
-                Some(e) => return Err(e),
-                None => {}
+            if let Some(e) = err {
+                return Err(e)
             }
 
             self.view.msg_list.scroll()?;

+ 7 - 12
bin/dnetview/src/view.rs

@@ -109,17 +109,12 @@ impl<'a> View {
     // according to what set of msgs is selected.
     // it's ugly. would prefer something more simple
     fn update_msg_index(&mut self) {
-        match self.id_menu.state.selected() {
-            Some(i) => match self.ordered_list.get(i) {
-                Some(i) => match self.msg_list.msg_map.get(i) {
-                    Some(i) => {
-                        self.msg_list.index = i.len();
-                    }
-                    None => {}
-                },
-                None => {}
-            },
-            None => {}
+        if let Some(sel) = self.id_menu.state.selected() {
+            if let Some(ord) = self.ordered_list.get(sel) {
+                if let Some(i) = self.msg_list.msg_map.get(ord) {
+                    self.msg_list.index = i.len();
+                }
+            }
         }
     }
 
@@ -328,7 +323,7 @@ impl<'a> View {
                         lines.push(Spans::from(accept_addr));
                     }
                     if session.hosts.is_some() {
-                        let hosts = Span::styled(format!("Hosts:"), style);
+                        let hosts = Span::styled("Hosts:".to_string(), style);
                         lines.push(Spans::from(hosts));
                         for host in session.hosts.as_ref().unwrap() {
                             let host = Span::styled(format!("      {}", host), style);

+ 8 - 8
bin/fud/fud/src/main.rs

@@ -275,21 +275,21 @@ impl Fud {
 
         // We execute this sequence to prevent lock races between threads
         // Verify key exists
-        let exists = self.dht.read().await.contains_key(key_hash.clone());
-        if let None = exists {
+        let exists = self.dht.read().await.contains_key(key_hash);
+        if exists.is_none() {
             info!("Did not find key: {}", key);
-            return server_error(RpcError::UnknownKey, id).into()
+            return server_error(RpcError::UnknownKey, id)
         }
 
         // Check if key is local or should query network
         let path = self.folder.join(key.clone());
         let local = exists.unwrap();
         if local {
-            match self.dht.read().await.get(key_hash.clone()) {
+            match self.dht.read().await.get(key_hash) {
                 Some(_) => return JsonResponse::new(json!(path), id).into(),
                 None => {
                     info!("Did not find key: {}", key);
-                    return server_error(RpcError::UnknownKey, id).into()
+                    return server_error(RpcError::UnknownKey, id)
                 }
             }
         }
@@ -297,7 +297,7 @@ impl Fud {
         info!("Key doesn't exist locally, querring network...");
         if let Err(e) = self.dht.read().await.request_key(key_hash).await {
             error!("Failed to query key: {}", e);
-            return server_error(RpcError::QueryFailed, id).into()
+            return server_error(RpcError::QueryFailed, id)
         }
 
         info!("Waiting response...");
@@ -322,13 +322,13 @@ impl Fud {
                     }
                     None => {
                         info!("Did not find key: {}", key);
-                        server_error(RpcError::UnknownKey, id).into()
+                        server_error(RpcError::UnknownKey, id)
                     }
                 }
             }
             Err(e) => {
                 error!("Error while waiting network response: {}", e);
-                server_error(RpcError::WaitingNetworkError, id).into()
+                server_error(RpcError::WaitingNetworkError, id)
             }
         }
     }

+ 2 - 1
bin/ircd/src/buffers.rs

@@ -24,7 +24,7 @@ pub fn create_buffers() -> Buffers {
     Arc::new(Msgs { privmsgs, unread_msgs, seen_ids })
 }
 
-#[derive(Clone)]
+#[derive(Default, Clone)]
 pub struct RingBuffer<T> {
     pub items: VecDeque<T>,
 }
@@ -71,6 +71,7 @@ impl<T: Eq + PartialEq + Clone> RingBuffer<T> {
     }
 }
 
+#[derive(Default)]
 pub struct PrivmsgsBuffer {
     msgs: Mutex<OrderingAlgo>,
 }

+ 37 - 30
bin/ircd/src/model.rs

@@ -1,6 +1,6 @@
-use async_std::sync::Arc;
-use std::{fmt, io};
+use std::{cmp::Ordering, fmt, io};
 
+use async_std::sync::Arc;
 use fxhash::FxHashMap;
 use ripemd::{Digest, Ripemd256};
 
@@ -138,7 +138,7 @@ impl Model {
         let root_node_id = root_node.event.hash();
 
         let mut event_map = FxHashMap::default();
-        event_map.insert(root_node_id.clone(), root_node);
+        event_map.insert(root_node_id, root_node);
 
         Self { current_root: root_node_id, orphans: FxHashMap::default(), event_map, events_queue }
     }
@@ -159,7 +159,7 @@ impl Model {
         for (event_hash, node) in self.event_map.iter() {
             // check if the node is a leaf
             if node.children.is_empty() {
-                leaves.push(event_hash.clone());
+                leaves.push(*event_hash);
             }
         }
 
@@ -188,7 +188,7 @@ impl Model {
                 continue
             }
 
-            let prev_event = orphan.previous_event_hash.clone();
+            let prev_event = orphan.previous_event_hash;
 
             let node =
                 EventNode { parent: Some(prev_event), event: orphan.clone(), children: Vec::new() };
@@ -217,7 +217,7 @@ impl Model {
                 continue
             }
 
-            let depth = self.diff_depth(leaf.clone(), head);
+            let depth = self.diff_depth(leaf, head);
             if depth > MAX_DEPTH {
                 self.remove_node(leaf);
             }
@@ -235,14 +235,14 @@ impl Model {
                 continue
             }
 
-            let ancestor = self.find_ancestor(leaf.clone(), head);
+            let ancestor = self.find_ancestor(leaf, head);
             ancestors.push(ancestor);
         }
 
         // find the highest ancestor
-        let highest_ancestor = ancestors.iter().max_by(|&a, &b| {
-            self.find_depth(a.clone(), &head).cmp(&self.find_depth(b.clone(), &head))
-        });
+        let highest_ancestor = ancestors
+            .iter()
+            .max_by(|&a, &b| self.find_depth(*a, &head).cmp(&self.find_depth(*b, &head)));
 
         // set the new root
         if let Some(ancestor) = highest_ancestor {
@@ -263,13 +263,13 @@ impl Model {
 
                 let root_childs = &root.children;
                 assert_eq!(root_childs.len(), 1);
-                let child = root_childs.get(0).unwrap().clone();
+                let child = *root_childs.first().unwrap();
 
                 self.event_map.remove(&root_hash);
                 root = self.event_map.get(&child).unwrap();
             }
 
-            self.current_root = ancestor.clone();
+            self.current_root = *ancestor;
         }
     }
 
@@ -305,7 +305,7 @@ impl Model {
     fn find_longest_chain(&self, parent_node: &EventId, i: u32) -> (EventId, u32) {
         let children = &self.event_map.get(parent_node).unwrap().children;
         if children.is_empty() {
-            return (parent_node.clone(), i)
+            return (*parent_node, i)
         }
 
         let mut current_max = 0;
@@ -313,21 +313,28 @@ impl Model {
         for node in children.iter() {
             let (grandchild_node, grandchild_i) = self.find_longest_chain(node, i + 1);
 
-            if grandchild_i > current_max {
-                current_max = grandchild_i;
-                current_node = Some(grandchild_node);
-            } else if grandchild_i == current_max {
-                // Break ties using the timestamp
-
-                let grandchild_node_timestamp =
-                    self.event_map.get(&grandchild_node).unwrap().event.timestamp;
-                let current_node_timestamp =
-                    self.event_map.get(&current_node.unwrap()).unwrap().event.timestamp;
-
-                if grandchild_node_timestamp > current_node_timestamp {
+            match &grandchild_i.cmp(&current_max) {
+                Ordering::Greater => {
                     current_max = grandchild_i;
                     current_node = Some(grandchild_node);
                 }
+                Ordering::Equal => {
+                    // Break ties using the timestamp
+
+                    let grandchild_node_timestamp =
+                        self.event_map.get(&grandchild_node).unwrap().event.timestamp;
+                    let current_node_timestamp =
+                        self.event_map.get(&current_node.unwrap()).unwrap().event.timestamp;
+
+                    if grandchild_node_timestamp > current_node_timestamp {
+                        current_max = grandchild_i;
+                        current_node = Some(grandchild_node);
+                    }
+                }
+                Ordering::Less => {
+                    // Left a todo here because not sure if it should be handled.
+                    todo!();
+                }
             }
         }
         assert_ne!(current_max, 0);
@@ -338,7 +345,7 @@ impl Model {
         let mut depth = 0;
         while &node != ancestor_id {
             depth += 1;
-            if let Some(parent) = self.event_map.get(&node).unwrap().parent.clone() {
+            if let Some(parent) = self.event_map.get(&node).unwrap().parent {
                 node = parent
             } else {
                 break
@@ -372,7 +379,7 @@ impl Model {
         let is_child = node_b == self.event_map.get(&node_a).unwrap().parent.unwrap();
 
         if is_child {
-            return node_b.clone()
+            return node_b
         }
 
         while node_a != node_b {
@@ -387,7 +394,7 @@ impl Model {
             node_b = node_b_parent;
         }
 
-        node_a.clone()
+        node_a
     }
 
     fn diff_depth(&self, node_a: EventId, node_b: EventId) -> u32 {
@@ -400,7 +407,7 @@ impl Model {
 
     fn _debug(&self) {
         for (event_id, event_node) in &self.event_map {
-            let depth = self.find_depth(event_id.clone(), &self.current_root);
+            let depth = self.find_depth(*event_id, &self.current_root);
             println!("{}: {:?} [depth={}]", hex::encode(&event_id), event_node.event, depth);
         }
 
@@ -612,7 +619,7 @@ mod tests {
     #[test]
     fn test_event_hash() {
         let events_queue = EventsQueue::new();
-        let mut model = Model::new(events_queue);
+        let model = Model::new(events_queue);
         let root_id = model.current_root;
 
         let timestamp = get_current_time() + 1;

+ 5 - 3
bin/ircd/src/protocol_privmsg2.rs

@@ -23,7 +23,7 @@ const UNREAD_EVENT_EXPIRE_TIME: u64 = 3600; // in seconds
 const SIZE_OF_SEEN_BUFFER: usize = 65536;
 const MAX_CONFIRM: u8 = 4;
 
-#[derive(Clone)]
+#[derive(Default, Clone)]
 struct RingBuffer<T> {
     pub items: VecDeque<T>,
 }
@@ -69,6 +69,7 @@ struct GetData {
     events: Vec<EventId>,
 }
 
+#[derive(Default)]
 pub struct Seen<T> {
     seen: Mutex<RingBuffer<T>>,
 }
@@ -88,6 +89,7 @@ impl<T: Eq + PartialEq + Clone> Seen<T> {
     }
 }
 
+#[derive(Default)]
 pub struct UnreadEvents {
     events: FxHashMap<EventId, Event>,
 }
@@ -129,14 +131,14 @@ impl UnreadEvents {
         let mut prune_ids = vec![];
         for (id, e) in self.events.iter() {
             if e.timestamp + (UNREAD_EVENT_EXPIRE_TIME * 1000) < get_current_time() {
-                prune_ids.push(id.clone());
+                prune_ids.push(*id);
             }
         }
         for id in prune_ids {
             self.events.remove(&id);
         }
 
-        self.events.insert(event.hash().clone(), event.clone());
+        self.events.insert(event.hash(), event.clone());
     }
 }
 

+ 1 - 1
bin/ircd/src/view.rs

@@ -2,7 +2,7 @@ use fxhash::FxHashMap;
 
 use darkfi::Result;
 
-use crate::model::{Event, EventId, EventsQueueArc, Model};
+use crate::model::{Event, EventId, EventsQueueArc};
 
 struct View {
     seen: FxHashMap<EventId, Event>,

+ 6 - 6
bin/ircd2/src/crypto.rs

@@ -74,10 +74,10 @@ pub fn decrypt_target(
             continue
         }
 
-        let salt_box = chan_info.salt_box(&name).clone();
+        let salt_box = chan_info.salt_box(name).clone();
 
         if let Some(salt_box) = salt_box {
-            if let Some(_) = try_decrypt(&salt_box, &privmsg.target) {
+            if try_decrypt(&salt_box, &privmsg.target).is_some() {
                 privmsg.target = name.clone();
                 return
             }
@@ -89,10 +89,10 @@ pub fn decrypt_target(
     }
 
     for (name, contact_info) in configured_contacts {
-        let salt_box = contact_info.salt_box(&private_key.as_ref().unwrap(), &name).clone();
+        let salt_box = contact_info.salt_box(private_key.as_ref().unwrap(), name).clone();
 
         if let Some(salt_box) = salt_box {
-            if let Some(_) = try_decrypt(&salt_box, &privmsg.target) {
+            if try_decrypt(&salt_box, &privmsg.target).is_some() {
                 privmsg.target = name.clone();
                 return
             }
@@ -102,8 +102,8 @@ pub fn decrypt_target(
 
 /// Decrypt PrivMsg nickname and message
 pub fn decrypt_privmsg(salt_box: &SalsaBox, privmsg: &mut PrivMsgEvent) {
-    let decrypted_nick = try_decrypt(&salt_box, &privmsg.nick);
-    let decrypted_msg = try_decrypt(&salt_box, &privmsg.msg);
+    let decrypted_nick = try_decrypt(salt_box, &privmsg.nick);
+    let decrypted_msg = try_decrypt(salt_box, &privmsg.msg);
 
     if decrypted_nick.is_none() && decrypted_msg.is_none() {
         return

+ 6 - 10
bin/ircd2/src/irc/client.rs

@@ -88,9 +88,7 @@ impl<C: AsyncRead + AsyncWrite + Send + Unpin + 'static> IrcClient<C> {
         self.irc_config.private_key = new_config.private_key;
         self.irc_config.password = new_config.password;
 
-        if let Err(_) =
-            self.on_receive_join(self.irc_config.channels.keys().cloned().collect()).await
-        {
+        if self.on_receive_join(self.irc_config.channels.keys().cloned().collect()).await.is_err() {
             warn!("Error to join updated channels");
         }
     }
@@ -134,7 +132,7 @@ impl<C: AsyncRead + AsyncWrite + Send + Unpin + 'static> IrcClient<C> {
         } else if self.irc_config.private_key.is_some() {
             if let Some(contact_info) = self.irc_config.contacts.get(&msg.target) {
                 let salt_box = &contact_info
-                    .salt_box(&self.irc_config.private_key.as_ref().unwrap(), &msg.target);
+                    .salt_box(self.irc_config.private_key.as_ref().unwrap(), &msg.target);
 
                 if salt_box.is_none() {
                     return Ok(())
@@ -201,10 +199,8 @@ impl<C: AsyncRead + AsyncWrite + Send + Unpin + 'static> IrcClient<C> {
     }
 
     async fn registre(&mut self) -> Result<()> {
-        if !self.irc_config.is_pass_init {
-            if self.irc_config.password.is_empty() {
-                self.irc_config.is_pass_init = true
-            }
+        if !self.irc_config.is_pass_init && self.irc_config.password.is_empty() {
+            self.irc_config.is_pass_init = true
         }
 
         if !self.irc_config.is_registered &&
@@ -477,14 +473,14 @@ impl<C: AsyncRead + AsyncWrite + Send + Unpin + 'static> IrcClient<C> {
                 return Ok(())
             }
 
-            if let Some(salt_box) = &channel_info.salt_box(&target) {
+            if let Some(salt_box) = &channel_info.salt_box(target) {
                 encrypt_privmsg(salt_box, &mut privmsg);
                 info!("[CLIENT {}] (Encrypted) PRIVMSG: {:?}", self.address, privmsg.to_string());
             }
         } else if self.irc_config.private_key.is_some() {
             if let Some(contact_info) = self.irc_config.contacts.get(target) {
                 if let Some(salt_box) =
-                    &contact_info.salt_box(&self.irc_config.private_key.as_ref().unwrap(), target)
+                    &contact_info.salt_box(self.irc_config.private_key.as_ref().unwrap(), target)
                 {
                     encrypt_privmsg(salt_box, &mut privmsg);
                     info!(

+ 1 - 1
bin/ircd2/src/main.rs

@@ -67,7 +67,7 @@ async fn realmain(settings: Args, executor: Arc<Executor<'_>>) -> Result<()> {
     ////////////////////
     let events_queue = EventsQueue::new();
     let model = Arc::new(Mutex::new(Model::new(events_queue.clone())));
-    let view = Arc::new(Mutex::new(View::new(events_queue)));
+    let _view = Arc::new(Mutex::new(View::new(events_queue)));
 
     ////////////////////
     // P2p setup

+ 36 - 30
bin/ircd2/src/model.rs

@@ -1,6 +1,6 @@
-use async_std::sync::{Arc, Mutex};
-use std::fmt;
+use std::{cmp::Ordering, fmt};
 
+use async_std::sync::{Arc, Mutex};
 use fxhash::FxHashMap;
 use ripemd::{Digest, Ripemd256};
 
@@ -88,7 +88,7 @@ impl Model {
         let root_node_id = root_node.event.hash();
 
         let mut event_map = FxHashMap::default();
-        event_map.insert(root_node_id.clone(), root_node);
+        event_map.insert(root_node_id, root_node);
 
         Self { current_root: root_node_id, orphans: FxHashMap::default(), event_map, events_queue }
     }
@@ -109,7 +109,7 @@ impl Model {
         for (event_hash, node) in self.event_map.iter() {
             // check if the node is a leaf
             if node.children.is_empty() {
-                leaves.push(event_hash.clone());
+                leaves.push(*event_hash);
             }
         }
 
@@ -138,7 +138,7 @@ impl Model {
                 continue
             }
 
-            let prev_event = orphan.previous_event_hash.clone();
+            let prev_event = orphan.previous_event_hash;
 
             let node =
                 EventNode { parent: Some(prev_event), event: orphan.clone(), children: Vec::new() };
@@ -170,7 +170,7 @@ impl Model {
                 continue
             }
 
-            let depth = self.diff_depth(leaf.clone(), head);
+            let depth = self.diff_depth(leaf, head);
             if depth > MAX_DEPTH {
                 self.remove_node(leaf);
             }
@@ -188,14 +188,14 @@ impl Model {
                 continue
             }
 
-            let ancestor = self.find_ancestor(leaf.clone(), head);
+            let ancestor = self.find_ancestor(leaf, head);
             ancestors.push(ancestor);
         }
 
         // find the highest ancestor
-        let highest_ancestor = ancestors.iter().max_by(|&a, &b| {
-            self.find_depth(a.clone(), &head).cmp(&self.find_depth(b.clone(), &head))
-        });
+        let highest_ancestor = ancestors
+            .iter()
+            .max_by(|&a, &b| self.find_depth(*a, &head).cmp(&self.find_depth(*b, &head)));
 
         // set the new root
         if let Some(ancestor) = highest_ancestor {
@@ -216,13 +216,13 @@ impl Model {
 
                 let root_childs = &root.children;
                 assert_eq!(root_childs.len(), 1);
-                let child = root_childs.get(0).unwrap().clone();
+                let child = *root_childs.first().unwrap();
 
                 self.event_map.remove(&root_hash);
                 root = self.event_map.get(&child).unwrap();
             }
 
-            self.current_root = ancestor.clone();
+            self.current_root = *ancestor;
         }
     }
 
@@ -258,7 +258,7 @@ impl Model {
     fn find_longest_chain(&self, parent_node: &EventId, i: u32) -> (EventId, u32) {
         let children = &self.event_map.get(parent_node).unwrap().children;
         if children.is_empty() {
-            return (parent_node.clone(), i)
+            return (*parent_node, i)
         }
 
         let mut current_max = 0;
@@ -266,21 +266,27 @@ impl Model {
         for node in children.iter() {
             let (grandchild_node, grandchild_i) = self.find_longest_chain(node, i + 1);
 
-            if grandchild_i > current_max {
-                current_max = grandchild_i;
-                current_node = Some(grandchild_node);
-            } else if grandchild_i == current_max {
-                // Break ties using the timestamp
-
-                let grandchild_node_timestamp =
-                    self.event_map.get(&grandchild_node).unwrap().event.timestamp;
-                let current_node_timestamp =
-                    self.event_map.get(&current_node.unwrap()).unwrap().event.timestamp;
-
-                if grandchild_node_timestamp > current_node_timestamp {
+            match &grandchild_i.cmp(&current_max) {
+                Ordering::Greater => {
                     current_max = grandchild_i;
                     current_node = Some(grandchild_node);
                 }
+                Ordering::Equal => {
+                    // Break ties using the timestamp
+                    let grandchild_node_timestamp =
+                        self.event_map.get(&grandchild_node).unwrap().event.timestamp;
+                    let current_node_timestamp =
+                        self.event_map.get(&current_node.unwrap()).unwrap().event.timestamp;
+
+                    if grandchild_node_timestamp > current_node_timestamp {
+                        current_max = grandchild_i;
+                        current_node = Some(grandchild_node);
+                    }
+                }
+                Ordering::Less => {
+                    // Left a todo here, not sure if it should be handled
+                    todo!();
+                }
             }
         }
         assert_ne!(current_max, 0);
@@ -291,7 +297,7 @@ impl Model {
         let mut depth = 0;
         while &node != ancestor_id {
             depth += 1;
-            if let Some(parent) = self.event_map.get(&node).unwrap().parent.clone() {
+            if let Some(parent) = self.event_map.get(&node).unwrap().parent {
                 node = parent
             } else {
                 break
@@ -325,7 +331,7 @@ impl Model {
         let is_child = node_b == self.event_map.get(&node_a).unwrap().parent.unwrap();
 
         if is_child {
-            return node_b.clone()
+            return node_b
         }
 
         while node_a != node_b {
@@ -340,7 +346,7 @@ impl Model {
             node_b = node_b_parent;
         }
 
-        node_a.clone()
+        node_a
     }
 
     fn diff_depth(&self, node_a: EventId, node_b: EventId) -> u32 {
@@ -353,7 +359,7 @@ impl Model {
 
     fn _debug(&self) {
         for (event_id, event_node) in &self.event_map {
-            let depth = self.find_depth(event_id.clone(), &self.current_root);
+            let depth = self.find_depth(*event_id, &self.current_root);
             println!("{}: {:?} [depth={}]", hex::encode(&event_id), event_node.event, depth);
         }
 
@@ -566,7 +572,7 @@ mod tests {
     #[test]
     fn test_event_hash() {
         let events_queue = EventsQueue::new();
-        let mut model = Model::new(events_queue);
+        let model = Model::new(events_queue);
         let root_id = model.current_root;
 
         let timestamp = get_current_time() + 1;

+ 2 - 2
bin/ircd2/src/protocol_event.rs

@@ -133,14 +133,14 @@ impl UnreadEvents {
         let mut prune_ids = vec![];
         for (id, e) in self.events.iter() {
             if e.timestamp + (UNREAD_EVENT_EXPIRE_TIME * 1000) < get_current_time() {
-                prune_ids.push(id.clone());
+                prune_ids.push(*id);
             }
         }
         for id in prune_ids {
             self.events.remove(&id);
         }
 
-        self.events.insert(event.hash().clone(), event.clone());
+        self.events.insert(event.hash(), event.clone());
     }
 }
 

+ 3 - 3
bin/ircd2/src/settings.rs

@@ -90,7 +90,7 @@ pub struct Args {
 /// [contact."nick"]
 /// pubkey = "7CkVuFgwTUpJn5Sv67Q3fyEDpa28yrSeL5Hg2GqQ4jfM"
 /// ```
-#[derive(Clone, Debug, Deserialize, Serialize)]
+#[derive(Default, Clone, Debug, Deserialize, Serialize)]
 pub struct ContactInfo {
     pub pubkey: Option<String>,
 }
@@ -103,7 +103,7 @@ impl ContactInfo {
     pub fn salt_box(&self, private_key: &str, contact_name: &str) -> Option<SalsaBox> {
         if let Ok(private) = parse_priv(private_key) {
             if let Some(p) = &self.pubkey {
-                if let Ok(public) = parse_pub(&p) {
+                if let Ok(public) = parse_pub(p) {
                     return Some(SalsaBox::new(&public, &private))
                 } else {
                     error!("Uncorrect public key in for contact {}", contact_name);
@@ -130,7 +130,7 @@ impl ContactInfo {
 /// Having a topic set is useful if one wants to have a topic in the
 /// configured channel. It is not shared with others, but it is useful
 /// for personal reference.
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Default, Clone, Debug, Serialize, Deserialize)]
 pub struct ChannelInfo {
     /// Optional topic for the channel
     pub topic: Option<String>,

+ 4 - 3
bin/lilith/src/main.rs

@@ -191,7 +191,7 @@ async fn spawn_network(
 }
 
 /// Retrieve saved hosts for provided networks
-fn load_hosts(path: &Path, networks: &Vec<String>) -> FxHashMap<String, FxHashSet<Url>> {
+fn load_hosts(path: &Path, networks: &[&str]) -> FxHashMap<String, FxHashSet<Url>> {
     let mut saved_hosts = FxHashMap::default();
     info!("Retrieving saved hosts from: {:?}", path);
     let contents = load_file(path);
@@ -202,7 +202,7 @@ fn load_hosts(path: &Path, networks: &Vec<String>) -> FxHashMap<String, FxHashSe
 
     for line in contents.unwrap().lines() {
         let data: Vec<&str> = line.split('\t').collect();
-        if networks.contains(&data[0].to_string()) {
+        if networks.contains(&data[0]) {
             let mut hosts = match saved_hosts.get(data[0]) {
                 Some(hosts) => hosts.clone(),
                 None => FxHashSet::default(),
@@ -274,7 +274,8 @@ async fn realmain(args: Args, ex: Arc<Executor<'_>>) -> Result<()> {
 
     // Retrieve saved hosts for configured networks
     let full_path = expand_path(&args.hosts_file)?;
-    let saved_hosts = load_hosts(&full_path, &configured_nets.keys().cloned().collect());
+    let nets: Vec<&str> = configured_nets.keys().map(|x| x.as_str()).collect();
+    let saved_hosts = load_hosts(&full_path, &nets);
 
     // Spawn configured networks
     let mut spawns = vec![];

+ 1 - 3
bin/tau/taud/src/error.rs

@@ -59,9 +59,7 @@ pub fn to_json_result(res: TaudResult<Value>, id: Value) -> JsonResult {
             TaudError::Darkfi(e) => {
                 JsonError::new(ErrorCode::InternalError, Some(e.to_string()), id).into()
             }
-            TaudError::IoError(e) => {
-                JsonError::new(ErrorCode::InternalError, Some(e.to_string()), id).into()
-            }
+            TaudError::IoError(e) => JsonError::new(ErrorCode::InternalError, Some(e), id).into(),
         },
     }
 }

+ 7 - 8
bin/tau/taud/src/jsonrpc.rs

@@ -351,18 +351,17 @@ impl JsonRpcInterface {
                 .map(|t| t.id)
                 .collect();
 
-        let task_ref_ids: Vec<String> =
-            MonthTasks::load_current_tasks(&self.dataset_path, ws.clone(), false)?
-                .into_iter()
-                .map(|t| t.ref_id)
-                .collect();
-
-        let imported_tasks = MonthTasks::load_current_tasks(&path, ws, true)?;
+        let imported_tasks = MonthTasks::load_current_tasks(&path, ws.clone(), true)?;
 
         for mut task in imported_tasks {
-            if task_ref_ids.contains(&task.ref_id) {
+            if MonthTasks::load_current_tasks(&self.dataset_path, ws.clone(), false)?
+                .into_iter()
+                .map(|t| t.ref_id)
+                .any(|x| x == task.ref_id)
+            {
                 continue
             }
+
             task.id = find_free_id(&task_ids);
             task_ids.push(task.id);
             self.notify_queue_sender.send(task).await.map_err(Error::from)?;

+ 3 - 3
bin/tau/taud/src/main.rs

@@ -130,7 +130,7 @@ async fn on_receive_task(
     workspaces: &FxHashMap<String, SalsaBox>,
 ) -> TaudResult<()> {
     for (workspace, salsa_box) in workspaces.iter() {
-        let task = decrypt_task(&task, &salsa_box);
+        let task = decrypt_task(task, salsa_box);
         if let Err(e) = task {
             info!("unable to decrypt the task: {}", e);
             continue
@@ -139,7 +139,7 @@ async fn on_receive_task(
         let mut task = task.unwrap();
         info!(target: "tau", "Save the task: ref: {}", task.ref_id);
         task.workspace = workspace.clone();
-        task.save(&datastore_path)?;
+        task.save(datastore_path)?;
     }
     Ok(())
 }
@@ -187,7 +187,7 @@ async fn realmain(settings: Args, executor: Arc<Executor<'_>>) -> Result<()> {
         loop {
             println!("Name for the new workspace: ");
             let mut workspace = String::new();
-            stdin().read_line(&mut workspace).ok().expect("Failed to read line");
+            stdin().read_line(&mut workspace).expect("Failed to read line");
             let workspace = workspace.to_lowercase();
             let workspace = workspace.trim();
             if workspace.is_empty() && workspace.len() < 3 {

+ 3 - 3
bin/tau/taud/src/task_info.rs

@@ -179,13 +179,13 @@ impl TaskInfo {
     pub fn set_title(&mut self, title: &str) {
         debug!(target: "tau", "TaskInfo::set_title()");
         self.title = title.into();
-        self.set_event("title", &title);
+        self.set_event("title", title);
     }
 
     pub fn set_desc(&mut self, desc: &str) {
         debug!(target: "tau", "TaskInfo::set_desc()");
         self.desc = desc.into();
-        self.set_event("desc", &desc);
+        self.set_event("desc", desc);
     }
 
     pub fn set_tags(&mut self, tags: &[String]) {
@@ -259,6 +259,6 @@ impl TaskInfo {
             return
         }
         self.state = state.to_string();
-        self.set_event("state", &state);
+        self.set_event("state", state);
     }
 }

+ 3 - 5
example/crypsinous.rs

@@ -6,7 +6,6 @@ use clap::Parser;
 use futures::executor::block_on;
 use std::thread;
 use url::Url;
-use vec;
 
 #[derive(Parser)]
 struct NetCli {
@@ -22,7 +21,7 @@ struct NetCli {
 
 #[async_std::main]
 async fn main() {
-    let _ = env_logger::init();
+    env_logger::init();
     let args = NetCli::parse();
     let addr = vec![Url::parse(args.addr.as_str()).unwrap()];
     let mut peers = vec![];
@@ -47,7 +46,7 @@ async fn main() {
         connect_timeout_seconds: 10,
         channel_handshake_seconds: 4,
         channel_heartbeat_seconds: 10,
-        external_addr: addr.clone(),
+        external_addr: addr,
         peers,
         seeds,
         ..Default::default()
@@ -58,8 +57,7 @@ async fn main() {
     let id = Timestamp::current_time().0;
 
     let mut stakeholder =
-        block_on(Stakeholder::new(epoch_consensus.clone(), settings.clone(), &path, id, Some(k)))
-            .unwrap();
+        block_on(Stakeholder::new(epoch_consensus, settings, &path, id, Some(k))).unwrap();
 
     let handle = thread::spawn(move || {
         block_on(stakeholder.background(Some(9)));

+ 3 - 4
example/lead.rs

@@ -1,7 +1,6 @@
-use env_logger;
 use futures::executor::block_on;
 use halo2_proofs::dev::MockProver;
-use log::{debug, error, info, log_enabled, Level};
+use log::debug;
 use pasta_curves::pallas;
 use url::Url;
 
@@ -14,13 +13,13 @@ use darkfi::{
 
 fn main() {
     debug!("..");
-    let _ = env_logger::init();
+    env_logger::init();
     let k: u32 = 13;
     //
 
     //
     const LEN: usize = 10;
-    let value = 33223; //static stake value
+    let _value = 33223; //static stake value
 
     //
     let settings = Settings {

+ 11 - 7
src/blockchain/epoch.rs

@@ -102,8 +102,12 @@ impl Epoch {
         self.consensus.get_epoch_len() as usize
     }
 
+    pub fn is_empty(&self) -> bool {
+        self.len() == 0
+    }
+
     pub fn col(&self) -> usize {
-        if self.coins.len() == 0 {
+        if self.coins.is_empty() {
             0
         } else {
             self.coins[0].len()
@@ -180,21 +184,21 @@ impl Epoch {
         let (root_sks, path_sks) = self.create_coins_sks();
 
         // matrix of leadcoins, each row has competing coins per slot.
-        let mut coins: Vec<Vec<LeadCoin>> = vec![];
+        let _coins: Vec<Vec<LeadCoin>> = vec![];
         for i in 0..self.len() {
             // if you have any stake used is for competition
-            if owned.len() > 0 {
+            if !owned.is_empty() {
                 let mut slot_coins = vec![];
-                for j in 0..owned.len() {
+                for elem in &owned {
                     let coin = self.create_leadcoin(
                         sigma,
-                        owned[j].note.value,
+                        elem.note.value,
                         i,
                         root_sks[i],
                         path_sks[i],
                         seeds[i],
                     );
-                    slot_coins.push(coin.clone());
+                    slot_coins.push(coin);
                 }
                 self.coins.push(slot_coins);
             }
@@ -330,7 +334,7 @@ impl Epoch {
             am_leader.push(iam_leader);
         }
         *idx = highest_stake_idx;
-        am_leader.len() > 0
+        !am_leader.is_empty()
     }
 
     /// * `sl` - relative slot index (zero based)

+ 7 - 10
src/consensus/state.rs

@@ -499,17 +499,14 @@ impl ValidatorState {
             }
         }
 
-        match fork {
-            Some(mut chain) => {
-                debug!("Proposal to fork a forkchain was received.");
-                chain.proposals.pop(); // removing last block to create the fork
-                if !chain.proposals.is_empty() {
-                    // if len is 0 we will verify against blockchain last block
-                    self.consensus.proposals.push(chain);
-                    return Ok(self.consensus.proposals.len() as i64 - 1)
-                }
+        if let Some(mut chain) = fork {
+            debug!("Proposal to fork a forkchain was received.");
+            chain.proposals.pop(); // removing last block to create the fork
+            if !chain.proposals.is_empty() {
+                // if len is 0 we will verify against blockchain last block
+                self.consensus.proposals.push(chain);
+                return Ok(self.consensus.proposals.len() as i64 - 1)
             }
-            None => (),
         }
 
         let (last_slot, last_block) = self.blockchain.last()?;

+ 0 - 319
src/dht/dht.rs

@@ -1,319 +0,0 @@
-use async_executor::Executor;
-use async_std::sync::{Arc, RwLock};
-use chrono::Utc;
-use futures::{select, FutureExt};
-use fxhash::FxHashMap;
-use log::{debug, error, warn};
-use rand::Rng;
-use std::collections::HashSet;
-
-use crate::{
-    net,
-    net::P2pPtr,
-    serial::serialize,
-    util::async_util::sleep,
-    Error::{NetworkNotConnected, UnknownKey},
-    Result,
-};
-
-use super::{
-    messages::{KeyRequest, KeyResponse, LookupMapRequest, LookupMapResponse, LookupRequest},
-    protocol::Protocol,
-};
-
-// Constants configuration
-const SEEN_DURATION: i64 = 120;
-
-/// Atomic pointer to DHT state
-pub type DhtPtr = Arc<RwLock<Dht>>;
-
-// TODO: proper errors
-// TODO: lookup table to be based on directly connected peers, not broadcast based
-// Using string in structures because we are at an external crate
-// and cant use blake3 serialization. To be replaced once merged with core src.
-
-/// Struct representing DHT state.
-pub struct Dht {
-    /// Daemon id
-    pub id: blake3::Hash,
-    /// Daemon hasmap
-    pub map: FxHashMap<blake3::Hash, Vec<u8>>,
-    /// Network lookup map, containing nodes that holds each key
-    pub lookup: FxHashMap<blake3::Hash, HashSet<blake3::Hash>>,
-    /// P2P network pointer
-    pub p2p: P2pPtr,
-    /// Channel to receive responses from P2P
-    p2p_recv_channel: async_channel::Receiver<KeyResponse>,
-    /// Stop signal channel to terminate background processes
-    stop_signal: async_channel::Receiver<()>,
-    /// Daemon seen requests/responses ids and timestamp,
-    /// to prevent rebroadcasting and loops
-    pub seen: FxHashMap<blake3::Hash, i64>,
-}
-
-impl Dht {
-    pub async fn new(
-        initial: Option<FxHashMap<blake3::Hash, HashSet<blake3::Hash>>>,
-        p2p_ptr: P2pPtr,
-        stop_signal: async_channel::Receiver<()>,
-        ex: Arc<Executor<'_>>,
-    ) -> Result<DhtPtr> {
-        // Generate a random id
-        let mut rng = rand::thread_rng();
-        let n: u16 = rng.gen();
-        let id = blake3::hash(&serialize(&n));
-        let map = FxHashMap::default();
-        let lookup = match initial {
-            Some(l) => l,
-            None => FxHashMap::default(),
-        };
-        let p2p = p2p_ptr.clone();
-        let (p2p_send_channel, p2p_recv_channel) = async_channel::unbounded::<KeyResponse>();
-        let seen = FxHashMap::default();
-
-        let dht = Arc::new(RwLock::new(Dht {
-            id,
-            map,
-            lookup,
-            p2p,
-            p2p_recv_channel,
-            stop_signal,
-            seen,
-        }));
-
-        // Registering P2P protocols
-        let registry = p2p_ptr.protocol_registry();
-        let _dht = dht.clone();
-        registry
-            .register(net::SESSION_ALL, move |channel, p2p_ptr| {
-                let sender = p2p_send_channel.clone();
-                let dht = _dht.clone();
-                async move { Protocol::init(channel, sender, dht, p2p_ptr).await.unwrap() }
-            })
-            .await;
-
-        // Task to periodically clean up daemon seen messages
-        ex.spawn(prune_seen_messages(dht.clone())).detach();
-
-        Ok(dht)
-    }
-
-    /// Store provided key value pair, update lookup map and broadcast new insert to network
-    pub async fn insert(
-        &mut self,
-        key: blake3::Hash,
-        value: Vec<u8>,
-    ) -> Result<Option<blake3::Hash>> {
-        self.map.insert(key, value);
-
-        if let Err(e) = self.lookup_insert(key, self.id) {
-            error!("Failed to insert record to lookup map: {}", e);
-            return Err(e)
-        };
-
-        let request = LookupRequest::new(self.id, key, 0);
-        if let Err(e) = self.p2p.broadcast(request).await {
-            error!("Failed broadcasting request: {}", e);
-            return Err(e)
-        }
-
-        Ok(Some(key))
-    }
-
-    /// Remove provided key value pair and update lookup map
-    pub async fn remove(&mut self, key: blake3::Hash) -> Result<Option<blake3::Hash>> {
-        // Check if key value pair existed and act accordingly
-        match self.map.remove(&key) {
-            Some(_) => {
-                debug!("Key removed: {}", key);
-                let request = LookupRequest::new(self.id, key, 1);
-                if let Err(e) = self.p2p.broadcast(request).await {
-                    error!("Failed broadcasting request: {}", e);
-                    return Err(e)
-                }
-
-                self.lookup_remove(key, self.id)
-            }
-            None => Ok(None),
-        }
-    }
-
-    /// Store provided key node pair in lookup map and update network
-    pub fn lookup_insert(
-        &mut self,
-        key: blake3::Hash,
-        node_id: blake3::Hash,
-    ) -> Result<Option<blake3::Hash>> {
-        let mut lookup_set = match self.lookup.get(&key) {
-            Some(s) => s.clone(),
-            None => HashSet::new(),
-        };
-
-        lookup_set.insert(node_id);
-        self.lookup.insert(key, lookup_set);
-
-        Ok(Some(key))
-    }
-
-    /// Remove provided node id from keys set in local lookup map
-    pub fn lookup_remove(
-        &mut self,
-        key: blake3::Hash,
-        node_id: blake3::Hash,
-    ) -> Result<Option<blake3::Hash>> {
-        if let Some(s) = self.lookup.get(&key) {
-            let mut lookup_set = s.clone();
-            lookup_set.remove(&node_id);
-            if lookup_set.is_empty() {
-                self.lookup.remove(&key);
-            } else {
-                self.lookup.insert(key, lookup_set);
-            }
-        }
-
-        Ok(Some(key))
-    }
-
-    /// Verify if provided key exists and return flag if local or in network
-    pub fn contains_key(&self, key: blake3::Hash) -> Option<bool> {
-        match self.lookup.contains_key(&key) {
-            true => Some(self.map.contains_key(&key)),
-            false => None,
-        }
-    }
-
-    /// Get key from local map, acting as daemon cache
-    pub fn get(&self, key: blake3::Hash) -> Option<&Vec<u8>> {
-        self.map.get(&key)
-    }
-
-    /// Generate key request and broadcast it to the network
-    pub async fn request_key(&self, key: blake3::Hash) -> Result<()> {
-        // Verify the key exist in the lookup map.
-        let peers = match self.lookup.get(&key) {
-            Some(v) => v.clone(),
-            None => return Err(UnknownKey),
-        };
-
-        debug!("Key is in peers: {:?}", peers);
-
-        // We retrieve p2p network connected channels, to verify if we
-        // are connected to a network.
-        // Using len here because is_empty() uses unstable library feature
-        // called 'exact_size_is_empty'.
-        if self.p2p.channels().lock().await.values().len() == 0 {
-            return Err(NetworkNotConnected)
-        }
-
-        // We create a key request, and broadcast it to the network
-        // We choose last known peer as request recipient
-        let peer = *peers.iter().last().unwrap();
-        let request = KeyRequest::new(self.id, peer, key);
-        // TODO: ask connected peers directly, not broadcast
-        if let Err(e) = self.p2p.broadcast(request).await {
-            error!("Failed broadcasting request: {}", e);
-            return Err(e)
-        }
-
-        Ok(())
-    }
-
-    /// Auxilary function to sync lookup map with network
-    pub async fn sync_lookup_map(&mut self) -> Result<()> {
-        debug!("Starting lookup map sync...");
-        let channels_map = self.p2p.channels().lock().await.clone();
-        let values = channels_map.values();
-        // Using len here because is_empty() uses unstable library feature
-        // called 'exact_size_is_empty'.
-        if values.len() != 0 {
-            // Node iterates the channel peers to ask for their lookup map
-            for channel in values {
-                // Communication setup
-                let msg_subsystem = channel.get_message_subsystem();
-                msg_subsystem.add_dispatch::<LookupMapResponse>().await;
-                let response_sub = channel.subscribe_msg::<LookupMapResponse>().await?;
-
-                // Node creates a `LookupMapRequest` and sends it
-                let order = LookupMapRequest::new(self.id);
-                channel.send(order).await?;
-
-                // Node stores response data.
-                let resp = response_sub.receive().await?;
-                if resp.lookup.is_empty() {
-                    warn!("Retrieved empty lookup map from an unsynced node, retrying...");
-                    continue
-                }
-
-                // Store retrieved records
-                debug!("Processing received records");
-                for (k, v) in &resp.lookup {
-                    for node in v {
-                        self.lookup_insert(*k, *node)?;
-                    }
-                }
-
-                break
-            }
-        } else {
-            warn!("Node is not connected to other nodes");
-        }
-
-        debug!("Lookup map synced!");
-        Ok(())
-    }
-}
-
-// Auxilary function to wait for a key response from the P2P network.
-pub async fn waiting_for_response(dht: DhtPtr) -> Result<Option<KeyResponse>> {
-    let (p2p_recv_channel, stop_signal, timeout) = {
-        let _dht = dht.read().await;
-        (
-            _dht.p2p_recv_channel.clone(),
-            _dht.stop_signal.clone(),
-            _dht.p2p.settings().connect_timeout_seconds as u64,
-        )
-    };
-    let ex = Arc::new(async_executor::Executor::new());
-    let (timeout_s, timeout_r) = async_channel::unbounded::<()>();
-    ex.spawn(async move {
-        sleep(timeout).await;
-        timeout_s.send(()).await.unwrap_or(());
-    })
-    .detach();
-
-    select! {
-        msg = p2p_recv_channel.recv().fuse() => {
-                let response = msg?;
-                return Ok(Some(response))
-        },
-        _ = stop_signal.recv().fuse() => {},
-        _ = timeout_r.recv().fuse() => {},
-    }
-    Ok(None)
-}
-
-// Auxilary function to periodically prun seen messages, based on when they were received.
-// This helps us to prevent broadcasting loops.
-async fn prune_seen_messages(dht: DhtPtr) {
-    loop {
-        sleep(SEEN_DURATION as u64).await;
-        debug!("Pruning seen messages");
-
-        let now = Utc::now().timestamp();
-
-        let mut prune = vec![];
-        let map = dht.read().await.seen.clone();
-        for (k, v) in map.iter() {
-            if now - v > SEEN_DURATION {
-                prune.push(k);
-            }
-        }
-
-        let mut map = map.clone();
-        for i in prune {
-            map.remove(i);
-        }
-
-        dht.write().await.seen = map;
-    }
-}

+ 316 - 3
src/dht/mod.rs

@@ -1,6 +1,319 @@
-pub mod dht;
-pub use dht::{waiting_for_response, Dht, DhtPtr};
+use async_executor::Executor;
+use async_std::sync::{Arc, RwLock};
+use chrono::Utc;
+use futures::{select, FutureExt};
+use fxhash::FxHashMap;
+use log::{debug, error, warn};
+use rand::Rng;
+use std::collections::HashSet;
 
-mod messages;
+use crate::{
+    net,
+    net::P2pPtr,
+    serial::serialize,
+    util::async_util::sleep,
+    Error::{NetworkNotConnected, UnknownKey},
+    Result,
+};
 
+mod messages;
+use messages::{KeyRequest, KeyResponse, LookupMapRequest, LookupMapResponse, LookupRequest};
 mod protocol;
+use protocol::Protocol;
+
+// Constants configuration
+const SEEN_DURATION: i64 = 120;
+
+/// Atomic pointer to DHT state
+pub type DhtPtr = Arc<RwLock<Dht>>;
+
+// TODO: proper errors
+// TODO: lookup table to be based on directly connected peers, not broadcast based
+// Using string in structures because we are at an external crate
+// and cant use blake3 serialization. To be replaced once merged with core src.
+
+/// Struct representing DHT state.
+pub struct Dht {
+    /// Daemon id
+    pub id: blake3::Hash,
+    /// Daemon hasmap
+    pub map: FxHashMap<blake3::Hash, Vec<u8>>,
+    /// Network lookup map, containing nodes that holds each key
+    pub lookup: FxHashMap<blake3::Hash, HashSet<blake3::Hash>>,
+    /// P2P network pointer
+    pub p2p: P2pPtr,
+    /// Channel to receive responses from P2P
+    p2p_recv_channel: async_channel::Receiver<KeyResponse>,
+    /// Stop signal channel to terminate background processes
+    stop_signal: async_channel::Receiver<()>,
+    /// Daemon seen requests/responses ids and timestamp,
+    /// to prevent rebroadcasting and loops
+    pub seen: FxHashMap<blake3::Hash, i64>,
+}
+
+impl Dht {
+    pub async fn new(
+        initial: Option<FxHashMap<blake3::Hash, HashSet<blake3::Hash>>>,
+        p2p_ptr: P2pPtr,
+        stop_signal: async_channel::Receiver<()>,
+        ex: Arc<Executor<'_>>,
+    ) -> Result<DhtPtr> {
+        // Generate a random id
+        let mut rng = rand::thread_rng();
+        let n: u16 = rng.gen();
+        let id = blake3::hash(&serialize(&n));
+        let map = FxHashMap::default();
+        let lookup = match initial {
+            Some(l) => l,
+            None => FxHashMap::default(),
+        };
+        let p2p = p2p_ptr.clone();
+        let (p2p_send_channel, p2p_recv_channel) = async_channel::unbounded::<KeyResponse>();
+        let seen = FxHashMap::default();
+
+        let dht = Arc::new(RwLock::new(Dht {
+            id,
+            map,
+            lookup,
+            p2p,
+            p2p_recv_channel,
+            stop_signal,
+            seen,
+        }));
+
+        // Registering P2P protocols
+        let registry = p2p_ptr.protocol_registry();
+        let _dht = dht.clone();
+        registry
+            .register(net::SESSION_ALL, move |channel, p2p_ptr| {
+                let sender = p2p_send_channel.clone();
+                let dht = _dht.clone();
+                async move { Protocol::init(channel, sender, dht, p2p_ptr).await.unwrap() }
+            })
+            .await;
+
+        // Task to periodically clean up daemon seen messages
+        ex.spawn(prune_seen_messages(dht.clone())).detach();
+
+        Ok(dht)
+    }
+
+    /// Store provided key value pair, update lookup map and broadcast new insert to network
+    pub async fn insert(
+        &mut self,
+        key: blake3::Hash,
+        value: Vec<u8>,
+    ) -> Result<Option<blake3::Hash>> {
+        self.map.insert(key, value);
+
+        if let Err(e) = self.lookup_insert(key, self.id) {
+            error!("Failed to insert record to lookup map: {}", e);
+            return Err(e)
+        };
+
+        let request = LookupRequest::new(self.id, key, 0);
+        if let Err(e) = self.p2p.broadcast(request).await {
+            error!("Failed broadcasting request: {}", e);
+            return Err(e)
+        }
+
+        Ok(Some(key))
+    }
+
+    /// Remove provided key value pair and update lookup map
+    pub async fn remove(&mut self, key: blake3::Hash) -> Result<Option<blake3::Hash>> {
+        // Check if key value pair existed and act accordingly
+        match self.map.remove(&key) {
+            Some(_) => {
+                debug!("Key removed: {}", key);
+                let request = LookupRequest::new(self.id, key, 1);
+                if let Err(e) = self.p2p.broadcast(request).await {
+                    error!("Failed broadcasting request: {}", e);
+                    return Err(e)
+                }
+
+                self.lookup_remove(key, self.id)
+            }
+            None => Ok(None),
+        }
+    }
+
+    /// Store provided key node pair in lookup map and update network
+    pub fn lookup_insert(
+        &mut self,
+        key: blake3::Hash,
+        node_id: blake3::Hash,
+    ) -> Result<Option<blake3::Hash>> {
+        let mut lookup_set = match self.lookup.get(&key) {
+            Some(s) => s.clone(),
+            None => HashSet::new(),
+        };
+
+        lookup_set.insert(node_id);
+        self.lookup.insert(key, lookup_set);
+
+        Ok(Some(key))
+    }
+
+    /// Remove provided node id from keys set in local lookup map
+    pub fn lookup_remove(
+        &mut self,
+        key: blake3::Hash,
+        node_id: blake3::Hash,
+    ) -> Result<Option<blake3::Hash>> {
+        if let Some(s) = self.lookup.get(&key) {
+            let mut lookup_set = s.clone();
+            lookup_set.remove(&node_id);
+            if lookup_set.is_empty() {
+                self.lookup.remove(&key);
+            } else {
+                self.lookup.insert(key, lookup_set);
+            }
+        }
+
+        Ok(Some(key))
+    }
+
+    /// Verify if provided key exists and return flag if local or in network
+    pub fn contains_key(&self, key: blake3::Hash) -> Option<bool> {
+        match self.lookup.contains_key(&key) {
+            true => Some(self.map.contains_key(&key)),
+            false => None,
+        }
+    }
+
+    /// Get key from local map, acting as daemon cache
+    pub fn get(&self, key: blake3::Hash) -> Option<&Vec<u8>> {
+        self.map.get(&key)
+    }
+
+    /// Generate key request and broadcast it to the network
+    pub async fn request_key(&self, key: blake3::Hash) -> Result<()> {
+        // Verify the key exist in the lookup map.
+        let peers = match self.lookup.get(&key) {
+            Some(v) => v.clone(),
+            None => return Err(UnknownKey),
+        };
+
+        debug!("Key is in peers: {:?}", peers);
+
+        // We retrieve p2p network connected channels, to verify if we
+        // are connected to a network.
+        // Using len here because is_empty() uses unstable library feature
+        // called 'exact_size_is_empty'.
+        if self.p2p.channels().lock().await.values().len() == 0 {
+            return Err(NetworkNotConnected)
+        }
+
+        // We create a key request, and broadcast it to the network
+        // We choose last known peer as request recipient
+        let peer = *peers.iter().last().unwrap();
+        let request = KeyRequest::new(self.id, peer, key);
+        // TODO: ask connected peers directly, not broadcast
+        if let Err(e) = self.p2p.broadcast(request).await {
+            error!("Failed broadcasting request: {}", e);
+            return Err(e)
+        }
+
+        Ok(())
+    }
+
+    /// Auxilary function to sync lookup map with network
+    pub async fn sync_lookup_map(&mut self) -> Result<()> {
+        debug!("Starting lookup map sync...");
+        let channels_map = self.p2p.channels().lock().await.clone();
+        let values = channels_map.values();
+        // Using len here because is_empty() uses unstable library feature
+        // called 'exact_size_is_empty'.
+        if values.len() != 0 {
+            // Node iterates the channel peers to ask for their lookup map
+            for channel in values {
+                // Communication setup
+                let msg_subsystem = channel.get_message_subsystem();
+                msg_subsystem.add_dispatch::<LookupMapResponse>().await;
+                let response_sub = channel.subscribe_msg::<LookupMapResponse>().await?;
+
+                // Node creates a `LookupMapRequest` and sends it
+                let order = LookupMapRequest::new(self.id);
+                channel.send(order).await?;
+
+                // Node stores response data.
+                let resp = response_sub.receive().await?;
+                if resp.lookup.is_empty() {
+                    warn!("Retrieved empty lookup map from an unsynced node, retrying...");
+                    continue
+                }
+
+                // Store retrieved records
+                debug!("Processing received records");
+                for (k, v) in &resp.lookup {
+                    for node in v {
+                        self.lookup_insert(*k, *node)?;
+                    }
+                }
+
+                break
+            }
+        } else {
+            warn!("Node is not connected to other nodes");
+        }
+
+        debug!("Lookup map synced!");
+        Ok(())
+    }
+}
+
+// Auxilary function to wait for a key response from the P2P network.
+pub async fn waiting_for_response(dht: DhtPtr) -> Result<Option<KeyResponse>> {
+    let (p2p_recv_channel, stop_signal, timeout) = {
+        let _dht = dht.read().await;
+        (
+            _dht.p2p_recv_channel.clone(),
+            _dht.stop_signal.clone(),
+            _dht.p2p.settings().connect_timeout_seconds as u64,
+        )
+    };
+    let ex = Arc::new(async_executor::Executor::new());
+    let (timeout_s, timeout_r) = async_channel::unbounded::<()>();
+    ex.spawn(async move {
+        sleep(timeout).await;
+        timeout_s.send(()).await.unwrap_or(());
+    })
+    .detach();
+
+    select! {
+        msg = p2p_recv_channel.recv().fuse() => {
+                let response = msg?;
+                return Ok(Some(response))
+        },
+        _ = stop_signal.recv().fuse() => {},
+        _ = timeout_r.recv().fuse() => {},
+    }
+    Ok(None)
+}
+
+// Auxilary function to periodically prun seen messages, based on when they were received.
+// This helps us to prevent broadcasting loops.
+async fn prune_seen_messages(dht: DhtPtr) {
+    loop {
+        sleep(SEEN_DURATION as u64).await;
+        debug!("Pruning seen messages");
+
+        let now = Utc::now().timestamp();
+
+        let mut prune = vec![];
+        let map = dht.read().await.seen.clone();
+        for (k, v) in map.iter() {
+            if now - v > SEEN_DURATION {
+                prune.push(k);
+            }
+        }
+
+        let mut map = map.clone();
+        for i in prune {
+            map.remove(i);
+        }
+
+        dht.write().await.seen = map;
+    }
+}

+ 1 - 1
src/dht/protocol.rs

@@ -13,8 +13,8 @@ use crate::{
 };
 
 use super::{
-    dht::DhtPtr,
     messages::{KeyRequest, KeyResponse, LookupMapRequest, LookupMapResponse, LookupRequest},
+    DhtPtr,
 };
 
 pub struct Protocol {

+ 1 - 1
src/net/hosts.rs

@@ -148,5 +148,5 @@ fn is_valid_onion(onion: &str) -> bool {
 
     let alphabet = base32::Alphabet::RFC4648 { padding: false };
 
-    !base32::decode(alphabet, onion).is_none()
+    base32::decode(alphabet, onion).is_some()
 }

+ 1 - 1
src/net/session/outbound_session.rs

@@ -203,7 +203,7 @@ impl OutboundSession {
                         continue
                     }
 
-                    self.clone().register_channel(channel.clone(), executor.clone()).await?;
+                    self.register_channel(channel.clone(), executor.clone()).await?;
 
                     // Channel is now connected but not yet setup
 

+ 1 - 0
src/rpc/websockets.rs

@@ -13,6 +13,7 @@ use url::Url;
 
 use crate::{Error, Result as DrkResult};
 
+#[allow(clippy::large_enum_variant)]
 pub enum WsStream {
     Tcp(WebSocketStream<Async<TcpStream>>),
     Tls(WebSocketStream<TlsStream<Async<TcpStream>>>),

+ 621 - 2
src/stakeholder/mod.rs

@@ -1,2 +1,621 @@
-pub mod stakeholder;
-pub use stakeholder::Stakeholder;
+use async_executor::Executor;
+use async_std::sync::Arc;
+use halo2_proofs::arithmetic::Field;
+use log::{debug, error, info};
+use std::fmt;
+
+use rand::rngs::OsRng;
+use std::{thread, time::Duration};
+
+use crate::zk::circuit::{BurnContract, LeadContract, MintContract};
+use incrementalmerkletree::{bridgetree::BridgeTree, Tree};
+
+use crate::{
+    blockchain::{Blockchain, Epoch, EpochConsensus},
+    consensus::{
+        Block, BlockInfo, Header, OuroborosMetadata, StakeholderMetadata, StreamletMetadata,
+        TransactionLeadProof,
+    },
+    crypto::{
+        address::Address,
+        coin::OwnCoin,
+        constants::MERKLE_DEPTH,
+        keypair::{Keypair, PublicKey, SecretKey},
+        leadcoin::LeadCoin,
+        merkle_node::MerkleNode,
+        note::{EncryptedNote, Note},
+        nullifier::Nullifier,
+        proof::{Proof, ProvingKey, VerifyingKey},
+        schnorr::{SchnorrPublic, SchnorrSecret, Signature},
+    },
+    net::{MessageSubscription, P2p, Settings, SettingsPtr},
+    node::state::{state_transition, ProgramState, StateUpdate},
+    tx::{
+        builder::{
+            TransactionBuilder, TransactionBuilderClearInputInfo, TransactionBuilderOutputInfo,
+        },
+        Transaction,
+    },
+    util::{
+        clock::{Clock, Ticks},
+        path::expand_path,
+        time::Timestamp,
+    },
+    Result,
+};
+
+use url::Url;
+
+use pasta_curves::pallas;
+
+use group::ff::PrimeField;
+
+const LOG_T: &str = "stakeholder";
+const TREE_LEN: usize = 100;
+
+#[derive(Debug)]
+pub struct SlotWorkspace {
+    pub st: blake3::Hash,      // hash of the previous block
+    pub e: u64,                // epoch index
+    pub sl: u64,               // relative slot index
+    pub txs: Vec<Transaction>, // unpublished block transactions
+    pub root: MerkleNode,
+    /// merkle root of txs
+    pub m: StakeholderMetadata,
+    pub om: OuroborosMetadata,
+    pub is_leader: bool,
+    pub proof: Proof,
+    pub block: BlockInfo,
+}
+
+impl Default for SlotWorkspace {
+    fn default() -> Self {
+        Self {
+            st: blake3::hash(b""),
+            e: 0,
+            sl: 0,
+            txs: vec![],
+            root: MerkleNode(pallas::Base::zero()),
+            is_leader: false,
+            m: StakeholderMetadata::default(),
+            om: OuroborosMetadata::default(),
+            proof: Proof::default(),
+            block: BlockInfo::default(),
+        }
+    }
+}
+
+impl SlotWorkspace {
+    pub fn new_block(&self) -> (BlockInfo, blake3::Hash) {
+        let sm = StreamletMetadata::new(vec![]);
+        let header = Header::new(self.st, self.e, self.sl, Timestamp::current_time(), self.root);
+        let block = BlockInfo::new(header, self.txs.clone(), self.m.clone(), self.om.clone(), sm);
+        let hash = block.blockhash();
+        (block, hash)
+    }
+
+    pub fn add_tx(&mut self, tx: Transaction) {
+        self.txs.push(tx);
+    }
+
+    pub fn set_root(&mut self, root: MerkleNode) {
+        self.root = root;
+    }
+
+    pub fn set_stakeholdermetadata(&mut self, meta: StakeholderMetadata) {
+        self.m = meta;
+    }
+
+    pub fn set_ouroborosmetadata(&mut self, meta: OuroborosMetadata) {
+        self.om = meta;
+    }
+
+    pub fn set_sl(&mut self, sl: u64) {
+        self.sl = sl;
+    }
+
+    pub fn set_st(&mut self, st: blake3::Hash) {
+        self.st = st;
+    }
+
+    pub fn set_e(&mut self, e: u64) {
+        self.e = e;
+    }
+
+    pub fn set_proof(&mut self, proof: Proof) {
+        self.proof = proof;
+    }
+
+    pub fn set_leader(&mut self, alead: bool) {
+        self.is_leader = alead;
+    }
+}
+
+struct StakeholderState {
+    /// The entire Merkle tree state
+    tree: BridgeTree<MerkleNode, MERKLE_DEPTH>,
+    /// List of all previous and the current Merkle roots.
+    /// This is the hashed value of all the children.
+    merkle_roots: Vec<MerkleNode>,
+    /// Nullifiers prevent double spending
+    nullifiers: Vec<Nullifier>,
+    /// All received coins
+    // NOTE: We need maybe a flag to keep track of which ones are
+    // spent. Maybe the spend field links to a tx hash:input index.
+    // We should also keep track of the tx hash:output index where
+    // this coin was received.
+    own_coins: Vec<OwnCoin>,
+    /// Verifying key for the mint zk circuit.
+    mint_vk: VerifyingKey,
+    /// Verifying key for the burn zk circuit.
+    burn_vk: VerifyingKey,
+
+    /// Public key of the cashier
+    cashier_signature_public: PublicKey,
+
+    /// Public key of the faucet
+    faucet_signature_public: PublicKey,
+
+    /// List of all our secret keys
+    secrets: Vec<SecretKey>,
+}
+
+impl ProgramState for StakeholderState {
+    fn is_valid_cashier_public_key(&self, public: &PublicKey) -> bool {
+        public == &self.cashier_signature_public
+    }
+
+    fn is_valid_faucet_public_key(&self, public: &PublicKey) -> bool {
+        public == &self.faucet_signature_public
+    }
+
+    fn is_valid_merkle(&self, merkle_root: &MerkleNode) -> bool {
+        self.merkle_roots.iter().any(|m| m == merkle_root)
+    }
+
+    fn nullifier_exists(&self, nullifier: &Nullifier) -> bool {
+        self.nullifiers.iter().any(|n| n == nullifier)
+    }
+
+    fn mint_vk(&self) -> &VerifyingKey {
+        &self.mint_vk
+    }
+
+    fn burn_vk(&self) -> &VerifyingKey {
+        &self.burn_vk
+    }
+}
+
+impl StakeholderState {
+    fn apply(&mut self, mut update: StateUpdate) {
+        // Extend our list of nullifiers with the ones from the update
+        self.nullifiers.append(&mut update.nullifiers);
+
+        // Update merkle tree and witnesses
+        for (coin, enc_note) in update.coins.into_iter().zip(update.enc_notes.into_iter()) {
+            // Add the new coins to the Merkle tree
+            let node = MerkleNode(coin.0);
+            self.tree.append(&node);
+
+            // Keep track of all Merkle roots that have existed
+            self.merkle_roots.push(self.tree.root(0).unwrap());
+
+            // If it's our own coin, witness it and append to the vector.
+            if let Some((note, secret)) = self.try_decrypt_note(enc_note) {
+                let leaf_position = self.tree.witness().unwrap();
+                let nullifier = Nullifier::new(secret, note.serial);
+                let own_coin = OwnCoin { coin, note, secret, nullifier, leaf_position };
+                self.own_coins.push(own_coin);
+            }
+        }
+    }
+
+    fn try_decrypt_note(&self, ciphertext: EncryptedNote) -> Option<(Note, SecretKey)> {
+        // Loop through all our secret keys...
+        for secret in &self.secrets {
+            // .. attempt to decrypt the note ...
+            if let Ok(note) = ciphertext.decrypt(secret) {
+                // ... and return the decrypted note for this coin.
+                return Some((note, *secret))
+            }
+        }
+
+        // We weren't able to decrypt the note with any of our keys.
+        None
+    }
+}
+
+pub struct Stakeholder {
+    pub blockchain: Blockchain, // stakeholder view of the blockchain
+    pub net: Arc<P2p>,
+    pub clock: Clock,
+    pub ownedcoins: Vec<OwnCoin>,        // owned stakes
+    pub epoch: Epoch,                    // current epoch
+    pub epoch_consensus: EpochConsensus, // configuration for the epoch
+    pub lead_pk: ProvingKey,
+    pub mint_pk: ProvingKey,
+    pub burn_pk: ProvingKey,
+    pub lead_vk: VerifyingKey,
+    pub mint_vk: VerifyingKey,
+    pub burn_vk: VerifyingKey,
+    pub playing: bool,
+    pub workspace: SlotWorkspace,
+    pub id: i64,
+    pub keypair: Keypair,
+    pub cashier_signature_public: PublicKey,
+    pub faucet_signature_public: PublicKey,
+    pub cashier_signature_secret: SecretKey,
+    pub faucet_signature_secret: SecretKey,
+    //pub subscription: Subscription<Result<ChannelPtr>>,
+    //pub chanptr : ChannelPtr,
+    //pub msgsub : MessageSubscription::<BlockInfo>,
+}
+
+impl Stakeholder {
+    pub async fn new(
+        consensus: EpochConsensus,
+        settings: Settings,
+        rel_path: &str,
+        id: i64,
+        k: Option<u32>,
+    ) -> Result<Self> {
+        let path = expand_path(rel_path).unwrap();
+        let db = sled::open(&path)?;
+        let ts = Timestamp::current_time();
+        let genesis_hash = blake3::hash(b"");
+        let bc = Blockchain::new(&db, ts, genesis_hash).unwrap();
+        let eta = pallas::Base::one();
+        let epoch = Epoch::new(consensus, eta);
+
+        let lead_pk = ProvingKey::build(k.unwrap(), &LeadContract::default());
+        let mint_pk = ProvingKey::build(k.unwrap(), &MintContract::default());
+        let burn_pk = ProvingKey::build(k.unwrap(), &BurnContract::default());
+        let lead_vk = VerifyingKey::build(k.unwrap(), &LeadContract::default());
+        let mint_vk = VerifyingKey::build(k.unwrap(), &MintContract::default());
+        let burn_vk = VerifyingKey::build(k.unwrap(), &BurnContract::default());
+        let p2p = P2p::new(settings.clone()).await;
+        let workspace = SlotWorkspace::default();
+        let clock = Clock::new(
+            Some(consensus.get_epoch_len()),
+            Some(consensus.get_slot_len()),
+            Some(consensus.get_tick_len()),
+            settings.peers,
+        );
+        let cashier_signature_secret = SecretKey::random(&mut OsRng);
+        let cashier_signature_public = PublicKey::from_secret(cashier_signature_secret);
+
+        let faucet_signature_secret = SecretKey::random(&mut OsRng);
+        let faucet_signature_public = PublicKey::from_secret(faucet_signature_secret);
+
+        let keypair = Keypair::random(&mut OsRng);
+        debug!(target: LOG_T, "stakeholder constructed");
+        Ok(Self {
+            blockchain: bc,
+            net: p2p,
+            clock,
+            ownedcoins: vec![], //TODO should be read from wallet db.
+            epoch,
+            epoch_consensus: consensus,
+            lead_pk,
+            mint_pk,
+            burn_pk,
+            lead_vk,
+            mint_vk,
+            burn_vk,
+            playing: true,
+            workspace,
+            id,
+            keypair,
+            cashier_signature_public,
+            faucet_signature_public,
+            cashier_signature_secret,
+            faucet_signature_secret,
+        })
+    }
+
+    /// wrapper on Schnorr signature
+    pub fn sign(&self, message: &[u8]) -> Signature {
+        info!(target: LOG_T, "sign()");
+        self.keypair.secret.sign(message)
+    }
+
+    /// wrapper on schnorr public verify
+    pub fn verify(&self, message: &[u8], signature: &Signature) -> bool {
+        info!(target: LOG_T, "verify()");
+        self.keypair.public.verify(message, signature)
+    }
+
+    pub fn get_leadprovkingkey(&self) -> ProvingKey {
+        info!(target: LOG_T, "get_leadprovkingkey()");
+        self.lead_pk.clone()
+    }
+
+    pub fn get_mintprovkingkey(&self) -> ProvingKey {
+        info!(target: LOG_T, "get_mintprovkingkey()");
+        self.mint_pk.clone()
+    }
+
+    pub fn get_burnprovkingkey(&self) -> ProvingKey {
+        info!(target: LOG_T, "get_burnprovkingkey()");
+        self.burn_pk.clone()
+    }
+
+    pub fn get_leadverifyingkey(&self) -> VerifyingKey {
+        info!(target: LOG_T, "get_leadverifyingkey()");
+        self.lead_vk.clone()
+    }
+
+    pub fn get_mintverifyingkey(&self) -> VerifyingKey {
+        info!(target: LOG_T, "get_mintverifyingkey()");
+        self.mint_vk.clone()
+    }
+
+    pub fn get_burnverifyingkey(&self) -> VerifyingKey {
+        info!(target: LOG_T, "get_burnverifyingkey()");
+        self.burn_vk.clone()
+    }
+
+    /// get list stakeholder peers on the p2p network for synchronization
+    pub fn get_peers(&self) -> Vec<Url> {
+        info!(target: LOG_T, "get_peers()");
+        let settings: SettingsPtr = self.net.settings();
+        settings.peers.clone()
+    }
+
+    /*
+    fn  new_block(&self) {
+        //TODO initialize blocks in the epoch, and add coin commitment in genesis
+        let block_info = BlockInfo::new(st, e, sl, txs, metadata, sm);
+        self.block = block_info;
+    }
+    */
+
+    async fn init_network(&self) -> Result<()> {
+        info!(target: LOG_T, "init_network()");
+        let exec = Arc::new(Executor::new());
+        self.net.clone().start(exec.clone()).await?;
+        exec.spawn(self.net.clone().run(exec.clone())).detach();
+        info!(target: LOG_T, "net initialized");
+        Ok(())
+    }
+
+    pub fn get_net(&self) -> Arc<P2p> {
+        info!(target: LOG_T, "get_net()");
+        //TODO use P2p ptr not to overwrite wrappers
+        self.net.clone()
+    }
+
+    /// add new blockinfo to the blockchain
+    pub fn add_block(&self, block: BlockInfo) {
+        info!(target: LOG_T, "add_block()");
+        let blocks = [block];
+        let _len = self.blockchain.add(&blocks);
+    }
+
+    pub fn add_tx(&mut self, tx: Transaction) {
+        info!(target: LOG_T, "add_tx()");
+        self.workspace.add_tx(tx);
+    }
+
+    /// extract leader selection lottery randomness \eta
+    /// it's the hash of the previous lead proof
+    /// converted to pallas base
+    pub fn get_eta(&self) -> pallas::Base {
+        info!(target: LOG_T, "get_eta()");
+
+        let proof_tx_hash = self.blockchain.get_last_proof_hash().unwrap();
+        let mut bytes: [u8; 32] = *proof_tx_hash.as_bytes();
+        // read first 254 bits
+        bytes[30] = 0;
+        bytes[31] = 0;
+        pallas::Base::from_repr(bytes).unwrap()
+    }
+
+    pub fn valid_block(&self, _blk: BlockInfo) -> bool {
+        info!(target: LOG_T, "valid_block()");
+
+        //TODO implement
+        true
+    }
+
+    /// listen to the network,
+    /// for new transactions.
+    pub fn sync_tx(&self) {
+        //TODO
+    }
+
+    /// listen to the network channels,
+    /// receive new messages, or blocks,
+    /// validate the block proof, and the transactions,
+    /// if so add the proof to metadata if stakeholder isn't the lead.
+    pub async fn sync_block(&self) {
+        info!(target: LOG_T, "syncing blocks");
+        for chanptr in self.net.channels().lock().await.values() {
+            let message_subsytem = chanptr.get_message_subsystem();
+            message_subsytem.add_dispatch::<BlockInfo>().await;
+            //TODO start channel if isn't started yet
+            //let info = chanptr.get_info();
+            let msg_sub: MessageSubscription<BlockInfo> =
+                chanptr.subscribe_msg::<BlockInfo>().await.expect("missing blockinfo");
+
+            let res = msg_sub.receive().await.unwrap();
+            let blk: BlockInfo = (*res).to_owned();
+            //TODO validate the block proof, and transactions.
+            if self.valid_block(blk.clone()) {
+                //TODO if valid only.
+                let _len = self.blockchain.add(&[blk]);
+            } else {
+                error!(target: LOG_T, "received block is invalid!");
+            }
+        }
+    }
+
+    pub async fn background(&mut self, hardlimit: Option<u8>) {
+        info!(target: LOG_T, "background");
+        let _ = self.init_network().await;
+        let _ = self.clock.sync().await;
+        let mut c: u8 = 0;
+        let lim: u8 = hardlimit.unwrap_or(0);
+        while self.playing {
+            if c > lim && lim > 0 {
+                break
+            }
+            // clock ticks slot begins
+            // initialize the epoch if it's the time
+            // check for leadership
+            match self.clock.ticks().await {
+                Ticks::GENESIS { e, sl } => {
+                    //TODO (res) any initialization happening here?
+                    self.new_epoch();
+                    self.new_slot(e, sl);
+                }
+                Ticks::NEWEPOCH { e, sl } => {
+                    self.new_epoch();
+                    self.new_slot(e, sl);
+                }
+                Ticks::NEWSLOT { e, sl } => self.new_slot(e, sl),
+                Ticks::TOCKS => {
+                    info!(target: LOG_T, "tocks");
+                    // slot is about to end.
+                    // sync, and validate.
+                    // no more transactions to be received/send to the end of slot.
+                    if self.workspace.is_leader {
+                        info!(target: LOG_T, "[leadership won]");
+                        //craete block
+                        let (block_info, _block_hash) = self.workspace.new_block();
+                        //add the block to the blockchain
+                        self.add_block(block_info.clone());
+                        let block: Block = Block::from(block_info.clone());
+                        // publish the block
+                        //TODO (fix) before publishing the workspace tx root need to be set.
+                        let _ret = self.net.broadcast(block).await;
+                    } else {
+                        //
+                        self.sync_block().await;
+                    }
+                }
+                Ticks::IDLE => continue,
+                Ticks::OUTOFSYNC => {
+                    error!(target: LOG_T, "clock/blockchain are out of sync");
+                    // clock, and blockchain are out of sync
+                    let _ = self.clock.sync().await;
+                    self.sync_block().await;
+                }
+            }
+            thread::sleep(Duration::from_millis(1000));
+            c += 1;
+        }
+    }
+
+    /// on the onset of the epoch, layout the new the competing coins
+    /// assuming static stake during the epoch, enforced by the commitment to competing coins
+    /// in the epoch's gen2esis data.
+    fn new_epoch(&mut self) {
+        info!(target: LOG_T, "[new epoch] {}", self);
+        let eta = self.get_eta();
+        let mut epoch = Epoch::new(self.epoch_consensus, eta);
+        // total stake
+        let num_slots = self.workspace.sl;
+        let epochs = self.workspace.e;
+        let epoch_len = self.epoch_consensus.get_epoch_len();
+        // TODO sigma scalar for tunning target function
+        // it's value is dependent on the tekonomics,
+        // set to one untill then.
+        let reward = pallas::Base::one();
+        let num_slots = num_slots + epochs * epoch_len;
+        let sigma: pallas::Base = pallas::Base::from(num_slots) * reward;
+        epoch.create_coins(sigma, self.ownedcoins.clone()); // set epoch interal fields working space with competing coins
+        self.epoch = epoch.clone();
+    }
+
+    /// at the begining of the slot
+    /// stakeholder need to play the lottery for the slot.
+    /// FIXME if the stakeholder is not winning, staker can try different coins before,
+    /// commiting it's coins, to maximize success, thus,
+    /// the lottery proof need to be conditioned on the slot itself, and previous proof.
+    /// this will encourage each potential leader to play with honesty.
+    /// TODO this is fixed by commiting to the stakers at epoch genesis slot
+    /// * `e` - epoch index
+    /// * `sl` - slot relative index
+    fn new_slot(&mut self, e: u64, sl: u64) {
+        info!(target: LOG_T, "[new slot] {}, e:{}, rel sl:{}", self, e, sl);
+        let st: blake3::Hash = if e > 0 || (e == 0 && sl > 0) {
+            self.workspace.block.blockhash()
+        } else {
+            blake3::hash(b"")
+        };
+        // set workspace
+        self.workspace.set_sl(sl);
+        self.workspace.set_e(e);
+        self.workspace.set_st(st);
+        let mut winning_coin_idx: usize = 0;
+        let won = self.epoch.is_leader(sl, &mut winning_coin_idx);
+        let proof = if won {
+            self.epoch.get_proof(sl, winning_coin_idx, &self.get_leadprovkingkey())
+        } else {
+            Proof::new(vec![])
+        };
+        self.workspace.set_leader(won);
+        self.workspace.set_proof(proof.clone());
+
+        let addr = Address::from(self.keypair.public);
+        let sign = self.sign(proof.as_ref());
+        let stakeholder_meta = StakeholderMetadata::new(sign, addr);
+        let ouroboros_meta =
+            OuroborosMetadata::new(self.get_eta().to_repr(), TransactionLeadProof::from(proof));
+        self.workspace.set_stakeholdermetadata(stakeholder_meta);
+        self.workspace.set_ouroborosmetadata(ouroboros_meta);
+        //
+        if won {
+            //TODO (res) verify the coin is finalized
+            // could be finalized in later slot accord to the finalization policy that is WIP.
+            let owned_coin =
+                self.finalize_coin(&self.epoch.get_coin(sl as usize, winning_coin_idx as usize));
+            self.ownedcoins.push(owned_coin);
+        }
+    }
+
+    //TODO (res) validate the owncoin is the same winning leadcoin
+    pub fn finalize_coin(&self, coin: &LeadCoin) -> OwnCoin {
+        info!(target: LOG_T, "finalize coin");
+        let mut state = StakeholderState {
+            tree: BridgeTree::<MerkleNode, MERKLE_DEPTH>::new(TREE_LEN),
+            merkle_roots: vec![],
+            nullifiers: vec![],
+            own_coins: vec![],
+            mint_vk: self.mint_vk.clone(),
+            burn_vk: self.burn_vk.clone(),
+            cashier_signature_public: self.cashier_signature_public,
+            faucet_signature_public: self.faucet_signature_public,
+            secrets: vec![self.keypair.secret],
+        };
+
+        let token_id = pallas::Base::random(&mut OsRng);
+        let builder = TransactionBuilder {
+            clear_inputs: vec![TransactionBuilderClearInputInfo {
+                value: coin.value.unwrap(),
+                token_id,
+                signature_secret: self.cashier_signature_secret,
+            }],
+            inputs: vec![],
+            outputs: vec![TransactionBuilderOutputInfo {
+                value: coin.value.unwrap(),
+                token_id,
+                public: self.keypair.public,
+            }],
+        };
+        let tx = builder.build(&self.mint_pk, &self.burn_pk).unwrap();
+
+        tx.verify(&state.mint_vk, &state.burn_vk).unwrap();
+        let _note = tx.outputs[0].enc_note.decrypt(&self.keypair.secret).unwrap();
+        let update = state_transition(&state, tx).unwrap();
+        state.apply(update);
+        state.own_coins[0].clone()
+    }
+}
+
+impl fmt::Display for Stakeholder {
+    fn fmt(&self, formater: &mut fmt::Formatter) -> fmt::Result {
+        formater.write_fmt(format_args!("stakeholder with id: {}", self.id))
+    }
+}

+ 0 - 622
src/stakeholder/stakeholder.rs

@@ -1,622 +0,0 @@
-use async_executor::Executor;
-use async_std::sync::Arc;
-use halo2_proofs::arithmetic::Field;
-use log::{debug, error, info};
-use std::fmt;
-
-use rand::rngs::OsRng;
-use std::{thread, time::Duration};
-
-use crate::zk::circuit::{BurnContract, LeadContract, MintContract};
-use incrementalmerkletree::{bridgetree::BridgeTree, Tree};
-
-use crate::{
-    blockchain::{Blockchain, Epoch, EpochConsensus},
-    consensus::{
-        Block, BlockInfo, Header, OuroborosMetadata, StakeholderMetadata, StreamletMetadata,
-        TransactionLeadProof,
-    },
-    crypto::{
-        address::Address,
-        coin::OwnCoin,
-        constants::MERKLE_DEPTH,
-        keypair::{Keypair, PublicKey, SecretKey},
-        leadcoin::LeadCoin,
-        merkle_node::MerkleNode,
-        note::{EncryptedNote, Note},
-        nullifier::Nullifier,
-        proof::{Proof, ProvingKey, VerifyingKey},
-        schnorr::{SchnorrPublic, SchnorrSecret, Signature},
-    },
-    net::{MessageSubscription, P2p, Settings, SettingsPtr},
-    node::state::{state_transition, ProgramState, StateUpdate},
-    tx::{
-        builder::{
-            TransactionBuilder, TransactionBuilderClearInputInfo, TransactionBuilderInputInfo,
-            TransactionBuilderOutputInfo,
-        },
-        Transaction,
-    },
-    util::{
-        clock::{Clock, Ticks},
-        path::expand_path,
-        time::Timestamp,
-    },
-    Result,
-};
-
-use url::Url;
-
-use pasta_curves::pallas;
-
-use group::ff::PrimeField;
-
-const LOG_T: &str = "stakeholder";
-const TREE_LEN: usize = 100;
-
-#[derive(Debug)]
-pub struct SlotWorkspace {
-    pub st: blake3::Hash,      // hash of the previous block
-    pub e: u64,                // epoch index
-    pub sl: u64,               // relative slot index
-    pub txs: Vec<Transaction>, // unpublished block transactions
-    pub root: MerkleNode,
-    /// merkle root of txs
-    pub m: StakeholderMetadata,
-    pub om: OuroborosMetadata,
-    pub is_leader: bool,
-    pub proof: Proof,
-    pub block: BlockInfo,
-}
-
-impl Default for SlotWorkspace {
-    fn default() -> Self {
-        Self {
-            st: blake3::hash(b""),
-            e: 0,
-            sl: 0,
-            txs: vec![],
-            root: MerkleNode(pallas::Base::zero()),
-            is_leader: false,
-            m: StakeholderMetadata::default(),
-            om: OuroborosMetadata::default(),
-            proof: Proof::default(),
-            block: BlockInfo::default(),
-        }
-    }
-}
-
-impl SlotWorkspace {
-    pub fn new_block(&self) -> (BlockInfo, blake3::Hash) {
-        let sm = StreamletMetadata::new(vec![]);
-        let header = Header::new(self.st, self.e, self.sl, Timestamp::current_time(), self.root);
-        let block = BlockInfo::new(header, self.txs.clone(), self.m.clone(), self.om.clone(), sm);
-        let hash = block.blockhash();
-        (block, hash)
-    }
-
-    pub fn add_tx(&mut self, tx: Transaction) {
-        self.txs.push(tx);
-    }
-
-    pub fn set_root(&mut self, root: MerkleNode) {
-        self.root = root;
-    }
-
-    pub fn set_stakeholdermetadata(&mut self, meta: StakeholderMetadata) {
-        self.m = meta;
-    }
-
-    pub fn set_ouroborosmetadata(&mut self, meta: OuroborosMetadata) {
-        self.om = meta;
-    }
-
-    pub fn set_sl(&mut self, sl: u64) {
-        self.sl = sl;
-    }
-
-    pub fn set_st(&mut self, st: blake3::Hash) {
-        self.st = st;
-    }
-
-    pub fn set_e(&mut self, e: u64) {
-        self.e = e;
-    }
-
-    pub fn set_proof(&mut self, proof: Proof) {
-        self.proof = proof;
-    }
-
-    pub fn set_leader(&mut self, alead: bool) {
-        self.is_leader = alead;
-    }
-}
-
-struct StakeholderState {
-    /// The entire Merkle tree state
-    tree: BridgeTree<MerkleNode, MERKLE_DEPTH>,
-    /// List of all previous and the current Merkle roots.
-    /// This is the hashed value of all the children.
-    merkle_roots: Vec<MerkleNode>,
-    /// Nullifiers prevent double spending
-    nullifiers: Vec<Nullifier>,
-    /// All received coins
-    // NOTE: We need maybe a flag to keep track of which ones are
-    // spent. Maybe the spend field links to a tx hash:input index.
-    // We should also keep track of the tx hash:output index where
-    // this coin was received.
-    own_coins: Vec<OwnCoin>,
-    /// Verifying key for the mint zk circuit.
-    mint_vk: VerifyingKey,
-    /// Verifying key for the burn zk circuit.
-    burn_vk: VerifyingKey,
-
-    /// Public key of the cashier
-    cashier_signature_public: PublicKey,
-
-    /// Public key of the faucet
-    faucet_signature_public: PublicKey,
-
-    /// List of all our secret keys
-    secrets: Vec<SecretKey>,
-}
-
-impl ProgramState for StakeholderState {
-    fn is_valid_cashier_public_key(&self, public: &PublicKey) -> bool {
-        public == &self.cashier_signature_public
-    }
-
-    fn is_valid_faucet_public_key(&self, public: &PublicKey) -> bool {
-        public == &self.faucet_signature_public
-    }
-
-    fn is_valid_merkle(&self, merkle_root: &MerkleNode) -> bool {
-        self.merkle_roots.iter().any(|m| m == merkle_root)
-    }
-
-    fn nullifier_exists(&self, nullifier: &Nullifier) -> bool {
-        self.nullifiers.iter().any(|n| n == nullifier)
-    }
-
-    fn mint_vk(&self) -> &VerifyingKey {
-        &self.mint_vk
-    }
-
-    fn burn_vk(&self) -> &VerifyingKey {
-        &self.burn_vk
-    }
-}
-
-impl StakeholderState {
-    fn apply(&mut self, mut update: StateUpdate) {
-        // Extend our list of nullifiers with the ones from the update
-        self.nullifiers.append(&mut update.nullifiers);
-
-        // Update merkle tree and witnesses
-        for (coin, enc_note) in update.coins.into_iter().zip(update.enc_notes.into_iter()) {
-            // Add the new coins to the Merkle tree
-            let node = MerkleNode(coin.0);
-            self.tree.append(&node);
-
-            // Keep track of all Merkle roots that have existed
-            self.merkle_roots.push(self.tree.root(0).unwrap());
-
-            // If it's our own coin, witness it and append to the vector.
-            if let Some((note, secret)) = self.try_decrypt_note(enc_note) {
-                let leaf_position = self.tree.witness().unwrap();
-                let nullifier = Nullifier::new(secret, note.serial);
-                let own_coin = OwnCoin { coin, note, secret, nullifier, leaf_position };
-                self.own_coins.push(own_coin);
-            }
-        }
-    }
-
-    fn try_decrypt_note(&self, ciphertext: EncryptedNote) -> Option<(Note, SecretKey)> {
-        // Loop through all our secret keys...
-        for secret in &self.secrets {
-            // .. attempt to decrypt the note ...
-            if let Ok(note) = ciphertext.decrypt(secret) {
-                // ... and return the decrypted note for this coin.
-                return Some((note, *secret))
-            }
-        }
-
-        // We weren't able to decrypt the note with any of our keys.
-        None
-    }
-}
-
-pub struct Stakeholder {
-    pub blockchain: Blockchain, // stakeholder view of the blockchain
-    pub net: Arc<P2p>,
-    pub clock: Clock,
-    pub ownedcoins: Vec<OwnCoin>,        // owned stakes
-    pub epoch: Epoch,                    // current epoch
-    pub epoch_consensus: EpochConsensus, // configuration for the epoch
-    pub lead_pk: ProvingKey,
-    pub mint_pk: ProvingKey,
-    pub burn_pk: ProvingKey,
-    pub lead_vk: VerifyingKey,
-    pub mint_vk: VerifyingKey,
-    pub burn_vk: VerifyingKey,
-    pub playing: bool,
-    pub workspace: SlotWorkspace,
-    pub id: i64,
-    pub keypair: Keypair,
-    pub cashier_signature_public: PublicKey,
-    pub faucet_signature_public: PublicKey,
-    pub cashier_signature_secret: SecretKey,
-    pub faucet_signature_secret: SecretKey,
-    //pub subscription: Subscription<Result<ChannelPtr>>,
-    //pub chanptr : ChannelPtr,
-    //pub msgsub : MessageSubscription::<BlockInfo>,
-}
-
-impl Stakeholder {
-    pub async fn new(
-        consensus: EpochConsensus,
-        settings: Settings,
-        rel_path: &str,
-        id: i64,
-        k: Option<u32>,
-    ) -> Result<Self> {
-        let path = expand_path(rel_path).unwrap();
-        let db = sled::open(&path)?;
-        let ts = Timestamp::current_time();
-        let genesis_hash = blake3::hash(b"");
-        let bc = Blockchain::new(&db, ts, genesis_hash).unwrap();
-        let eta = pallas::Base::one();
-        let epoch = Epoch::new(consensus, eta);
-
-        let lead_pk = ProvingKey::build(k.unwrap(), &LeadContract::default());
-        let mint_pk = ProvingKey::build(k.unwrap(), &MintContract::default());
-        let burn_pk = ProvingKey::build(k.unwrap(), &BurnContract::default());
-        let lead_vk = VerifyingKey::build(k.unwrap(), &LeadContract::default());
-        let mint_vk = VerifyingKey::build(k.unwrap(), &MintContract::default());
-        let burn_vk = VerifyingKey::build(k.unwrap(), &BurnContract::default());
-        let p2p = P2p::new(settings.clone()).await;
-        let workspace = SlotWorkspace::default();
-        let clock = Clock::new(
-            Some(consensus.get_epoch_len()),
-            Some(consensus.get_slot_len()),
-            Some(consensus.get_tick_len()),
-            settings.peers,
-        );
-        let cashier_signature_secret = SecretKey::random(&mut OsRng);
-        let cashier_signature_public = PublicKey::from_secret(cashier_signature_secret);
-
-        let faucet_signature_secret = SecretKey::random(&mut OsRng);
-        let faucet_signature_public = PublicKey::from_secret(faucet_signature_secret);
-
-        let keypair = Keypair::random(&mut OsRng);
-        debug!(target: LOG_T, "stakeholder constructed");
-        Ok(Self {
-            blockchain: bc,
-            net: p2p,
-            clock,
-            ownedcoins: vec![], //TODO should be read from wallet db.
-            epoch,
-            epoch_consensus: consensus,
-            lead_pk,
-            mint_pk,
-            burn_pk,
-            lead_vk,
-            mint_vk,
-            burn_vk,
-            playing: true,
-            workspace,
-            id,
-            keypair,
-            cashier_signature_public,
-            faucet_signature_public,
-            cashier_signature_secret,
-            faucet_signature_secret,
-        })
-    }
-
-    /// wrapper on Schnorr signature
-    pub fn sign(&self, message: &[u8]) -> Signature {
-        info!(target: LOG_T, "sign()");
-        self.keypair.secret.sign(message)
-    }
-
-    /// wrapper on schnorr public verify
-    pub fn verify(&self, message: &[u8], signature: &Signature) -> bool {
-        info!(target: LOG_T, "verify()");
-        self.keypair.public.verify(message, signature)
-    }
-
-    pub fn get_leadprovkingkey(&self) -> ProvingKey {
-        info!(target: LOG_T, "get_leadprovkingkey()");
-        self.lead_pk.clone()
-    }
-
-    pub fn get_mintprovkingkey(&self) -> ProvingKey {
-        info!(target: LOG_T, "get_mintprovkingkey()");
-        self.mint_pk.clone()
-    }
-
-    pub fn get_burnprovkingkey(&self) -> ProvingKey {
-        info!(target: LOG_T, "get_burnprovkingkey()");
-        self.burn_pk.clone()
-    }
-
-    pub fn get_leadverifyingkey(&self) -> VerifyingKey {
-        info!(target: LOG_T, "get_leadverifyingkey()");
-        self.lead_vk.clone()
-    }
-
-    pub fn get_mintverifyingkey(&self) -> VerifyingKey {
-        info!(target: LOG_T, "get_mintverifyingkey()");
-        self.mint_vk.clone()
-    }
-
-    pub fn get_burnverifyingkey(&self) -> VerifyingKey {
-        info!(target: LOG_T, "get_burnverifyingkey()");
-        self.burn_vk.clone()
-    }
-
-    /// get list stakeholder peers on the p2p network for synchronization
-    pub fn get_peers(&self) -> Vec<Url> {
-        info!(target: LOG_T, "get_peers()");
-        let settings: SettingsPtr = self.net.settings();
-        settings.peers.clone()
-    }
-
-    /*
-    fn  new_block(&self) {
-        //TODO initialize blocks in the epoch, and add coin commitment in genesis
-        let block_info = BlockInfo::new(st, e, sl, txs, metadata, sm);
-        self.block = block_info;
-    }
-    */
-
-    async fn init_network(&self) -> Result<()> {
-        info!(target: LOG_T, "init_network()");
-        let exec = Arc::new(Executor::new());
-        self.net.clone().start(exec.clone()).await?;
-        exec.spawn(self.net.clone().run(exec.clone())).detach();
-        info!(target: LOG_T, "net initialized");
-        Ok(())
-    }
-
-    pub fn get_net(&self) -> Arc<P2p> {
-        info!(target: LOG_T, "get_net()");
-        //TODO use P2p ptr not to overwrite wrappers
-        self.net.clone()
-    }
-
-    /// add new blockinfo to the blockchain
-    pub fn add_block(&self, block: BlockInfo) {
-        info!(target: LOG_T, "add_block()");
-        let blocks = [block];
-        let _len = self.blockchain.add(&blocks);
-    }
-
-    pub fn add_tx(&mut self, tx: Transaction) {
-        info!(target: LOG_T, "add_tx()");
-        self.workspace.add_tx(tx);
-    }
-
-    /// extract leader selection lottery randomness \eta
-    /// it's the hash of the previous lead proof
-    /// converted to pallas base
-    pub fn get_eta(&self) -> pallas::Base {
-        info!(target: LOG_T, "get_eta()");
-
-        let proof_tx_hash = self.blockchain.get_last_proof_hash().unwrap();
-        let mut bytes: [u8; 32] = *proof_tx_hash.as_bytes();
-        // read first 254 bits
-        bytes[30] = 0;
-        bytes[31] = 0;
-        pallas::Base::from_repr(bytes).unwrap()
-    }
-
-    pub fn valid_block(&self, _blk: BlockInfo) -> bool {
-        info!(target: LOG_T, "valid_block()");
-
-        //TODO implement
-        true
-    }
-
-    /// listen to the network,
-    /// for new transactions.
-    pub fn sync_tx(&self) {
-        //TODO
-    }
-
-    /// listen to the network channels,
-    /// receive new messages, or blocks,
-    /// validate the block proof, and the transactions,
-    /// if so add the proof to metadata if stakeholder isn't the lead.
-    pub async fn sync_block(&self) {
-        info!(target: LOG_T, "syncing blocks");
-        for chanptr in self.net.channels().lock().await.values() {
-            let message_subsytem = chanptr.get_message_subsystem();
-            message_subsytem.add_dispatch::<BlockInfo>().await;
-            //TODO start channel if isn't started yet
-            //let info = chanptr.get_info();
-            let msg_sub: MessageSubscription<BlockInfo> =
-                chanptr.subscribe_msg::<BlockInfo>().await.expect("missing blockinfo");
-
-            let res = msg_sub.receive().await.unwrap();
-            let blk: BlockInfo = (*res).to_owned();
-            //TODO validate the block proof, and transactions.
-            if self.valid_block(blk.clone()) {
-                //TODO if valid only.
-                let _len = self.blockchain.add(&[blk]);
-            } else {
-                error!(target: LOG_T, "received block is invalid!");
-            }
-        }
-    }
-
-    pub async fn background(&mut self, hardlimit: Option<u8>) {
-        info!(target: LOG_T, "background");
-        let _ = self.init_network().await;
-        let _ = self.clock.sync().await;
-        let mut c: u8 = 0;
-        let lim: u8 = hardlimit.unwrap_or(0);
-        while self.playing {
-            if c > lim && lim > 0 {
-                break
-            }
-            // clock ticks slot begins
-            // initialize the epoch if it's the time
-            // check for leadership
-            match self.clock.ticks().await {
-                Ticks::GENESIS { e, sl } => {
-                    //TODO (res) any initialization happening here?
-                    self.new_epoch();
-                    self.new_slot(e, sl);
-                }
-                Ticks::NEWEPOCH { e, sl } => {
-                    self.new_epoch();
-                    self.new_slot(e, sl);
-                }
-                Ticks::NEWSLOT { e, sl } => self.new_slot(e, sl),
-                Ticks::TOCKS => {
-                    info!(target: LOG_T, "tocks");
-                    // slot is about to end.
-                    // sync, and validate.
-                    // no more transactions to be received/send to the end of slot.
-                    if self.workspace.is_leader {
-                        info!(target: LOG_T, "[leadership won]");
-                        //craete block
-                        let (block_info, _block_hash) = self.workspace.new_block();
-                        //add the block to the blockchain
-                        self.add_block(block_info.clone());
-                        let block: Block = Block::from(block_info.clone());
-                        // publish the block
-                        //TODO (fix) before publishing the workspace tx root need to be set.
-                        let _ret = self.net.broadcast(block).await;
-                    } else {
-                        //
-                        self.sync_block().await;
-                    }
-                }
-                Ticks::IDLE => continue,
-                Ticks::OUTOFSYNC => {
-                    error!(target: LOG_T, "clock/blockchain are out of sync");
-                    // clock, and blockchain are out of sync
-                    let _ = self.clock.sync().await;
-                    self.sync_block().await;
-                }
-            }
-            thread::sleep(Duration::from_millis(1000));
-            c += 1;
-        }
-    }
-
-    /// on the onset of the epoch, layout the new the competing coins
-    /// assuming static stake during the epoch, enforced by the commitment to competing coins
-    /// in the epoch's gen2esis data.
-    fn new_epoch(&mut self) {
-        info!(target: LOG_T, "[new epoch] {}", self);
-        let eta = self.get_eta();
-        let mut epoch = Epoch::new(self.epoch_consensus, eta);
-        // total stake
-        let num_slots = self.workspace.sl;
-        let epochs = self.workspace.e;
-        let epoch_len = self.epoch_consensus.get_epoch_len();
-        // TODO sigma scalar for tunning target function
-        // it's value is dependent on the tekonomics,
-        // set to one untill then.
-        let reward = pallas::Base::one();
-        let num_slots = num_slots + epochs * epoch_len;
-        let sigma: pallas::Base = pallas::Base::from(num_slots) * reward;
-        epoch.create_coins(sigma, self.ownedcoins.clone()); // set epoch interal fields working space with competing coins
-        self.epoch = epoch.clone();
-    }
-
-    /// at the begining of the slot
-    /// stakeholder need to play the lottery for the slot.
-    /// FIXME if the stakeholder is not winning, staker can try different coins before,
-    /// commiting it's coins, to maximize success, thus,
-    /// the lottery proof need to be conditioned on the slot itself, and previous proof.
-    /// this will encourage each potential leader to play with honesty.
-    /// TODO this is fixed by commiting to the stakers at epoch genesis slot
-    /// * `e` - epoch index
-    /// * `sl` - slot relative index
-    fn new_slot(&mut self, e: u64, sl: u64) {
-        info!(target: LOG_T, "[new slot] {}, e:{}, rel sl:{}", self, e, sl);
-        let st: blake3::Hash = if e > 0 || (e == 0 && sl > 0) {
-            self.workspace.block.blockhash()
-        } else {
-            blake3::hash(b"")
-        };
-        // set workspace
-        self.workspace.set_sl(sl);
-        self.workspace.set_e(e);
-        self.workspace.set_st(st);
-        let mut winning_coin_idx: usize = 0;
-        let won = self.epoch.is_leader(sl, &mut winning_coin_idx);
-        let proof = if won {
-            self.epoch.get_proof(sl, winning_coin_idx, &self.get_leadprovkingkey())
-        } else {
-            Proof::new(vec![])
-        };
-        self.workspace.set_leader(won);
-        self.workspace.set_proof(proof.clone());
-
-        let addr = Address::from(self.keypair.public);
-        let sign = self.sign(proof.as_ref());
-        let stakeholder_meta = StakeholderMetadata::new(sign, addr);
-        let ouroboros_meta =
-            OuroborosMetadata::new(self.get_eta().to_repr(), TransactionLeadProof::from(proof));
-        self.workspace.set_stakeholdermetadata(stakeholder_meta);
-        self.workspace.set_ouroborosmetadata(ouroboros_meta);
-        //
-        if won {
-            //TODO (res) verify the coin is finalized
-            // could be finalized in later slot accord to the finalization policy that is WIP.
-            let owned_coin =
-                self.finalize_coin(&self.epoch.get_coin(sl as usize, winning_coin_idx as usize));
-            self.ownedcoins.push(owned_coin);
-        }
-    }
-
-    //TODO (res) validate the owncoin is the same winning leadcoin
-    pub fn finalize_coin(&self, coin: &LeadCoin) -> OwnCoin {
-        info!(target: LOG_T, "finalize coin");
-        let mut state = StakeholderState {
-            tree: BridgeTree::<MerkleNode, MERKLE_DEPTH>::new(TREE_LEN),
-            merkle_roots: vec![],
-            nullifiers: vec![],
-            own_coins: vec![],
-            mint_vk: self.mint_vk.clone(),
-            burn_vk: self.burn_vk.clone(),
-            cashier_signature_public: self.cashier_signature_public.clone(),
-            faucet_signature_public: self.faucet_signature_public.clone(),
-            secrets: vec![self.keypair.secret],
-        };
-
-        let token_id = pallas::Base::random(&mut OsRng);
-        let builder = TransactionBuilder {
-            clear_inputs: vec![TransactionBuilderClearInputInfo {
-                value: coin.value.unwrap(),
-                token_id,
-                signature_secret: self.cashier_signature_secret,
-            }],
-            inputs: vec![],
-            outputs: vec![TransactionBuilderOutputInfo {
-                value: coin.value.unwrap(),
-                token_id,
-                public: self.keypair.public,
-            }],
-        };
-        let tx = builder.build(&self.mint_pk, &self.burn_pk).unwrap();
-
-        tx.verify(&state.mint_vk, &state.burn_vk).unwrap();
-        let _note = tx.outputs[0].enc_note.decrypt(&self.keypair.secret).unwrap();
-        let update = state_transition(&state, tx).unwrap();
-        state.apply(update);
-        state.own_coins[0].clone()
-    }
-}
-
-impl fmt::Display for Stakeholder {
-    fn fmt(&self, formater: &mut fmt::Formatter) -> fmt::Result {
-        formater.write_fmt(format_args!("stakeholder with id: {}", self.id))
-    }
-}

+ 2 - 5
src/util/clock.rs

@@ -154,10 +154,7 @@ impl Clock {
 
 #[cfg(test)]
 mod tests {
-    use crate::util::{
-        clock::{Clock, Ticks},
-        time,
-    };
+    use crate::util::clock::{Clock, Ticks};
     use futures::executor::block_on;
     use std::{thread, time::Duration};
     #[test]
@@ -166,7 +163,7 @@ mod tests {
         //block th for 3 secs
         thread::sleep(Duration::from_millis(1000));
         let ttg = block_on(clock.time_to_genesis()).0;
-        assert!(ttg >= 1 && ttg < 2);
+        assert!((1..2).contains(&ttg));
     }
 
     fn clock_ticking() {