Просмотр исходного кода

consensus: participants logic updated, proposal proof validation added, fmt

aggstam 3 лет назад
Родитель
Сommit
4ba31723c1

+ 2 - 12
bin/darkfid/src/main.rs

@@ -10,8 +10,7 @@ use darkfi::{
     async_daemonize, cli_desc,
     async_daemonize, cli_desc,
     consensus::{
     consensus::{
         proto::{
         proto::{
-            ProtocolKeepAlive, ProtocolParticipant, ProtocolProposal, ProtocolSync,
-            ProtocolSyncConsensus, ProtocolTx,
+            ProtocolParticipant, ProtocolProposal, ProtocolSync, ProtocolSyncConsensus, ProtocolTx,
         },
         },
         state::ValidatorStatePtr,
         state::ValidatorStatePtr,
         task::{block_sync_task, proposal_task},
         task::{block_sync_task, proposal_task},
@@ -402,14 +401,6 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'_>>) -> Result<()> {
                 })
                 })
                 .await;
                 .await;
 
 
-            let _state = state.clone();
-            registry
-                .register(net::SESSION_ALL, move |channel, p2p| {
-                    let state = _state.clone();
-                    async move { ProtocolKeepAlive::init(channel, state, p2p).await.unwrap() }
-                })
-                .await;
-
             let _state = state.clone();
             let _state = state.clone();
             registry
             registry
                 .register(net::SESSION_ALL, move |channel, p2p| {
                 .register(net::SESSION_ALL, move |channel, p2p| {
@@ -474,8 +465,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'_>>) -> Result<()> {
         consensus_p2p.clone().unwrap().wait_for_outbound(ex.clone()).await?;
         consensus_p2p.clone().unwrap().wait_for_outbound(ex.clone()).await?;
 
 
         info!("Starting consensus protocol task");
         info!("Starting consensus protocol task");
-        let _ex = ex.clone();
-        ex.spawn(proposal_task(consensus_p2p.unwrap(), sync_p2p.unwrap(), state, _ex)).detach();
+        ex.spawn(proposal_task(consensus_p2p.unwrap(), sync_p2p.unwrap(), state)).detach();
     } else {
     } else {
         info!("Not starting consensus P2P network");
         info!("Not starting consensus P2P network");
     }
     }

+ 1 - 1
script/research/crypsinous_playground/src/main.rs

@@ -111,7 +111,7 @@ async fn realmain(args: Args, _ex: Arc<smol::Executor<'_>>) -> Result<()>  {
             match lead_proof::verify_lead_proof(&verifying_key, &proof.unwrap(), &coin.public_inputs()) {
             match lead_proof::verify_lead_proof(&verifying_key, &proof.unwrap(), &coin.public_inputs()) {
                 Ok(_) => info!("Proof veryfied succsessfully!"),
                 Ok(_) => info!("Proof veryfied succsessfully!"),
                 Err(e) => error!("Error during leader proof verification: {}", e),
                 Err(e) => error!("Error during leader proof verification: {}", e),
-            }            
+            }
         }
         }
     }
     }
     
     

+ 13 - 4
src/consensus/metadata.rs

@@ -1,4 +1,5 @@
 use darkfi_serial::{SerialDecodable, SerialEncodable};
 use darkfi_serial::{SerialDecodable, SerialEncodable};
+use pasta_curves::pallas;
 use rand::rngs::OsRng;
 use rand::rngs::OsRng;
 
 
 use super::Participant;
 use super::Participant;
@@ -22,6 +23,10 @@ pub struct Metadata {
     pub signature: Signature,
     pub signature: Signature,
     /// Block owner address
     /// Block owner address
     pub address: Address,
     pub address: Address,
+    /// Block owner slot competing coins public inputs
+    pub public_inputs: Vec<pallas::Base>,
+    /// Block owner winning coin index
+    pub winning_index: usize,
     /// Response of global random oracle, or it's emulation.
     /// Response of global random oracle, or it's emulation.
     pub eta: [u8; 32],
     pub eta: [u8; 32],
     /// Leader NIZK proof
     /// Leader NIZK proof
@@ -35,10 +40,12 @@ impl Default for Metadata {
         let keypair = Keypair::random(&mut OsRng);
         let keypair = Keypair::random(&mut OsRng);
         let address = Address::from(keypair.public);
         let address = Address::from(keypair.public);
         let signature = Signature::dummy();
         let signature = Signature::dummy();
+        let public_inputs = vec![];
+        let winning_index = 0;
         let eta: [u8; 32] = *blake3::hash(b"let there be dark!").as_bytes();
         let eta: [u8; 32] = *blake3::hash(b"let there be dark!").as_bytes();
         let proof = LeadProof::default();
         let proof = LeadProof::default();
         let participants = vec![];
         let participants = vec![];
-        Self { signature, address, eta, proof, participants }
+        Self { signature, address, public_inputs, winning_index, eta, proof, participants }
     }
     }
 }
 }
 
 
@@ -46,11 +53,13 @@ impl Metadata {
     pub fn new(
     pub fn new(
         signature: Signature,
         signature: Signature,
         address: Address,
         address: Address,
+        public_inputs: Vec<pallas::Base>,
+        winning_index: usize,
         eta: [u8; 32],
         eta: [u8; 32],
         proof: LeadProof,
         proof: LeadProof,
         participants: Vec<Participant>,
         participants: Vec<Participant>,
     ) -> Self {
     ) -> Self {
-        Self { signature, address, eta, proof, participants }
+        Self { signature, address, public_inputs, winning_index, eta, proof, participants }
     }
     }
 }
 }
 
 
@@ -67,8 +76,8 @@ impl LeadProof {
         Self { proof }
         Self { proof }
     }
     }
 
 
-    pub fn verify(&self, vk: VerifyingKey, public_inputs: &[DrkCircuitField]) -> VerifyResult<()> {
-        lead_proof::verify_lead_proof(&vk, &self.proof, public_inputs)
+    pub fn verify(&self, vk: &VerifyingKey, public_inputs: &[DrkCircuitField]) -> VerifyResult<()> {
+        lead_proof::verify_lead_proof(vk, &self.proof, public_inputs)
     }
     }
 }
 }
 
 

+ 3 - 4
src/consensus/mod.rs

@@ -8,7 +8,7 @@ pub use metadata::{LeadProof, Metadata};
 
 
 /// Consensus participant
 /// Consensus participant
 pub mod participant;
 pub mod participant;
-pub use participant::{KeepAlive, Participant};
+pub use participant::Participant;
 
 
 /// Consensus state
 /// Consensus state
 pub mod state;
 pub mod state;
@@ -66,14 +66,13 @@ lazy_static! {
     // Epoch configuration
     // Epoch configuration
     /// Slots in an epoch
     /// Slots in an epoch
     pub static ref EPOCH_LENGTH: u64 = 10;
     pub static ref EPOCH_LENGTH: u64 = 10;
+
     /// Block leader reward
     /// Block leader reward
     pub static ref REWARD: u64 = 420;
     pub static ref REWARD: u64 = 420;
+
     /// `2 * DELTA` represents slot time
     /// `2 * DELTA` represents slot time
     pub static ref DELTA: u64 = 20;
     pub static ref DELTA: u64 = 20;
 
 
-    /// Quarantine duration, in slots
-    pub static ref QUARANTINE_DURATION: u64 = 5;
-    
     /// Leader proof rows number
     /// Leader proof rows number
     pub static ref LEADER_PROOF_K: u32 = 13;
     pub static ref LEADER_PROOF_K: u32 = 13;
 
 

+ 9 - 2
src/consensus/ouroboros/stakeholder.rs

@@ -364,8 +364,15 @@ impl Stakeholder {
         let keypair = coin.keypair.unwrap();
         let keypair = coin.keypair.unwrap();
         let addr = Address::from(keypair.public);
         let addr = Address::from(keypair.public);
         let sign = keypair.secret.sign(proof.as_ref());
         let sign = keypair.secret.sign(proof.as_ref());
-        let meta =
-            Metadata::new(sign, addr, self.get_eta().to_repr(), LeadProof::from(proof), vec![]);
+        let meta = Metadata::new(
+            sign,
+            addr,
+            coin.public_inputs(),
+            idx,
+            self.get_eta().to_repr(),
+            LeadProof::from(proof),
+            vec![],
+        );
         self.workspace.add_metadata(meta);
         self.workspace.add_metadata(meta);
         let owned_coin = self.finalize_coin(&self.epoch.get_coin(sl as usize, idx as usize));
         let owned_coin = self.finalize_coin(&self.epoch.get_coin(sl as usize, idx as usize));
         self.ownedcoins.push(owned_coin);
         self.ownedcoins.push(owned_coin);

+ 10 - 24
src/consensus/participant.rs

@@ -1,7 +1,8 @@
 use darkfi_serial::{SerialDecodable, SerialEncodable};
 use darkfi_serial::{SerialDecodable, SerialEncodable};
+use pasta_curves::pallas;
 
 
 use crate::{
 use crate::{
-    crypto::{address::Address, keypair::PublicKey, schnorr::Signature},
+    crypto::{address::Address, keypair::PublicKey},
     net,
     net,
 };
 };
 
 
@@ -13,15 +14,17 @@ pub struct Participant {
     pub public_key: PublicKey,
     pub public_key: PublicKey,
     /// Node wallet address
     /// Node wallet address
     pub address: Address,
     pub address: Address,
-    /// Last slot node send a keep alive message
-    pub seen: u64,
-    /// Slot participant was quarantined by the node
-    pub quarantined: Option<u64>,
+    /// Node current epoch competing coins public inputs
+    pub coins: Vec<Vec<Vec<pallas::Base>>>,
 }
 }
 
 
 impl Participant {
 impl Participant {
-    pub fn new(public_key: PublicKey, address: Address, joined: u64) -> Self {
-        Self { public_key, address, seen: joined, quarantined: None }
+    pub fn new(
+        public_key: PublicKey,
+        address: Address,
+        coins: Vec<Vec<Vec<pallas::Base>>>,
+    ) -> Self {
+        Self { public_key, address, coins }
     }
     }
 }
 }
 
 
@@ -30,20 +33,3 @@ impl net::Message for Participant {
         "participant"
         "participant"
     }
     }
 }
 }
-
-/// Struct represending a keep alive message, containing signed slot for validation
-#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
-pub struct KeepAlive {
-    /// Node address
-    pub address: Address,
-    /// Slot message was send
-    pub slot: u64,
-    /// Slot signature
-    pub signature: Signature,
-}
-
-impl net::Message for KeepAlive {
-    fn name() -> &'static str {
-        "keepalive"
-    }
-}

+ 0 - 4
src/consensus/proto/mod.rs

@@ -2,10 +2,6 @@
 mod protocol_participant;
 mod protocol_participant;
 pub use protocol_participant::ProtocolParticipant;
 pub use protocol_participant::ProtocolParticipant;
 
 
-/// Participant keep alive protocol
-mod protocol_keep_alive;
-pub use protocol_keep_alive::ProtocolKeepAlive;
-
 /// Block proposal protocol
 /// Block proposal protocol
 mod protocol_proposal;
 mod protocol_proposal;
 pub use protocol_proposal::ProtocolProposal;
 pub use protocol_proposal::ProtocolProposal;

+ 0 - 92
src/consensus/proto/protocol_keep_alive.rs

@@ -1,92 +0,0 @@
-use async_std::sync::Arc;
-use async_trait::async_trait;
-use log::{debug, error};
-use smol::Executor;
-use url::Url;
-
-use crate::{
-    consensus::{KeepAlive, ValidatorStatePtr},
-    net::{
-        ChannelPtr, MessageSubscription, P2pPtr, ProtocolBase, ProtocolBasePtr,
-        ProtocolJobsManager, ProtocolJobsManagerPtr,
-    },
-    Result,
-};
-
-pub struct ProtocolKeepAlive {
-    keep_alive_sub: MessageSubscription<KeepAlive>,
-    jobsman: ProtocolJobsManagerPtr,
-    state: ValidatorStatePtr,
-    p2p: P2pPtr,
-    channel_address: Url,
-}
-
-impl ProtocolKeepAlive {
-    pub async fn init(
-        channel: ChannelPtr,
-        state: ValidatorStatePtr,
-        p2p: P2pPtr,
-    ) -> Result<ProtocolBasePtr> {
-        debug!("Adding ProtocolKeepAlive to the protocol registry");
-        let msg_subsystem = channel.get_message_subsystem();
-        msg_subsystem.add_dispatch::<KeepAlive>().await;
-
-        let keep_alive_sub = channel.subscribe_msg::<KeepAlive>().await?;
-        let channel_address = channel.address();
-
-        Ok(Arc::new(Self {
-            keep_alive_sub,
-            jobsman: ProtocolJobsManager::new("ProtocolKeepAlive", channel),
-            state,
-            p2p,
-            channel_address,
-        }))
-    }
-
-    async fn handle_receive_keep_alive(self: Arc<Self>) -> Result<()> {
-        debug!("ProtocolKeepAlive::handle_receive_keep_alive() [START]");
-        let exclude_list = vec![self.channel_address.clone()];
-        loop {
-            let keep_alive = match self.keep_alive_sub.receive().await {
-                Ok(v) => v,
-                Err(e) => {
-                    error!("ProtocolKeepAlive::handle_receive_keep_alive(): recv error: {}", e);
-                    continue
-                }
-            };
-
-            debug!("ProtocolKeepAlive::handle_receive_keep_alive() recv: {:?}", keep_alive);
-
-            let keep_alive_copy = (*keep_alive).clone();
-
-            if self.state.write().await.participant_keep_alive(keep_alive_copy.clone()) {
-                if let Err(e) =
-                    self.p2p.broadcast_with_exclude(keep_alive_copy, &exclude_list).await
-                {
-                    error!(
-                        "ProtocolKeepAlive::handle_receive_keep_alive(): p2p broadcast failed: {}",
-                        e
-                    );
-                };
-            }
-        }
-    }
-}
-
-#[async_trait]
-impl ProtocolBase for ProtocolKeepAlive {
-    async fn start(self: Arc<Self>, executor: Arc<Executor<'_>>) -> Result<()> {
-        debug!("ProtocolKeepAlive::start() [START]");
-        self.jobsman.clone().start(executor.clone());
-        self.jobsman
-            .clone()
-            .spawn(self.clone().handle_receive_keep_alive(), executor.clone())
-            .await;
-        debug!("ProtocolKeepAlive::start() [END]");
-        Ok(())
-    }
-
-    fn name(&self) -> &'static str {
-        "ProtocolKeepAlive"
-    }
-}

+ 60 - 170
src/consensus/state.rs

@@ -16,8 +16,8 @@ use pasta_curves::pallas;
 use rand::rngs::OsRng;
 use rand::rngs::OsRng;
 
 
 use super::{
 use super::{
-    Block, BlockInfo, BlockProposal, coins, Header, KeepAlive, LeadProof, Metadata, Participant,
-    ProposalChain, DELTA, EPOCH_LENGTH, QUARANTINE_DURATION, LEADER_PROOF_K,
+    coins, Block, BlockInfo, BlockProposal, Header, LeadProof, Metadata, Participant,
+    ProposalChain, DELTA, EPOCH_LENGTH, LEADER_PROOF_K,
 };
 };
 
 
 use crate::{
 use crate::{
@@ -25,8 +25,8 @@ use crate::{
     crypto::{
     crypto::{
         address::Address,
         address::Address,
         keypair::{PublicKey, SecretKey},
         keypair::{PublicKey, SecretKey},
-        leadcoin::LeadCoin,
         lead_proof,
         lead_proof,
+        leadcoin::LeadCoin,
         proof::{ProvingKey, VerifyingKey},
         proof::{ProvingKey, VerifyingKey},
         schnorr::{SchnorrPublic, SchnorrSecret},
         schnorr::{SchnorrPublic, SchnorrSecret},
     },
     },
@@ -220,6 +220,11 @@ impl ValidatorState {
         true
         true
     }
     }
 
 
+    /// Calculates current epoch.
+    pub fn current_epoch(&self) -> u64 {
+        self.slot_epoch(self.current_slot())
+    }
+
     /// Calculates the epoch of the provided slot.
     /// Calculates the epoch of the provided slot.
     /// Epoch duration is configured using the `EPOCH_LENGTH` value.
     /// Epoch duration is configured using the `EPOCH_LENGTH` value.
     pub fn slot_epoch(&self, slot: u64) -> u64 {
     pub fn slot_epoch(&self, slot: u64) -> u64 {
@@ -232,6 +237,11 @@ impl ValidatorState {
         self.consensus.genesis_ts.elapsed() / (2 * *DELTA)
         self.consensus.genesis_ts.elapsed() / (2 * *DELTA)
     }
     }
 
 
+    /// Calculates the relative number of the provided slot.
+    pub fn relative_slot(&self, slot: u64) -> u64 {
+        slot % *EPOCH_LENGTH
+    }
+
     /// Finds the last slot a proposal or block was generated.
     /// Finds the last slot a proposal or block was generated.
     pub fn last_slot(&self) -> Result<u64> {
     pub fn last_slot(&self) -> Result<u64> {
         let mut slot = 0;
         let mut slot = 0;
@@ -266,17 +276,15 @@ impl ValidatorState {
 
 
         Duration::new(diff.num_seconds().try_into().unwrap(), 0)
         Duration::new(diff.num_seconds().try_into().unwrap(), 0)
     }
     }
-    
+
     /// Calculate slots until next Nth epoch.
     /// Calculate slots until next Nth epoch.
     /// Epoch duration is configured using the EPOCH_LENGTH value.
     /// Epoch duration is configured using the EPOCH_LENGTH value.
     pub fn slots_to_next_n_epoch(&self, n: u64) -> u64 {
     pub fn slots_to_next_n_epoch(&self, n: u64) -> u64 {
         assert!(n > 0);
         assert!(n > 0);
-        let epoch_length = *EPOCH_LENGTH;
-        let relavite_slot = self.current_slot() % epoch_length;
-        let slots_till_next_epoch = epoch_length - relavite_slot;
-        ((n - 1) * epoch_length) + slots_till_next_epoch
+        let slots_till_next_epoch = *EPOCH_LENGTH - self.relative_slot(self.current_slot());
+        ((n - 1) * *EPOCH_LENGTH) + slots_till_next_epoch
     }
     }
-    
+
     /// Calculates seconds until next Nth epoch starting time.
     /// Calculates seconds until next Nth epoch starting time.
     pub fn next_n_epoch_start(&self, n: u64) -> Duration {
     pub fn next_n_epoch_start(&self, n: u64) -> Duration {
         self.next_n_slot_start(self.slots_to_next_n_epoch(n))
         self.next_n_slot_start(self.slots_to_next_n_epoch(n))
@@ -291,6 +299,8 @@ impl ValidatorState {
     /// Find slot leader, using a simple hash method.
     /// Find slot leader, using a simple hash method.
     /// Leader calculation is based on how many nodes are participating
     /// Leader calculation is based on how many nodes are participating
     /// in the network.
     /// in the network.
+    /// Note: leaving this for future usage
+    /// TODO: if not used, participants BTreeMap can become a HashSet
     pub fn slot_leader(&mut self) -> Participant {
     pub fn slot_leader(&mut self) -> Participant {
         let slot = self.current_slot();
         let slot = self.current_slot();
         // DefaultHasher is used to hash the slot number
         // DefaultHasher is used to hash the slot number
@@ -303,16 +313,14 @@ impl ValidatorState {
         // the same key in calculated position.
         // the same key in calculated position.
         self.consensus.participants.iter().nth(pos as usize).unwrap().1.clone()
         self.consensus.participants.iter().nth(pos as usize).unwrap().1.clone()
     }
     }
-    
+
     /// Check if new epoch has started, to create new epoch coins.
     /// Check if new epoch has started, to create new epoch coins.
     /// Returns flag to signify if epoch has changed and vector of
     /// Returns flag to signify if epoch has changed and vector of
     /// new epoch competing coins.
     /// new epoch competing coins.
-    pub async fn epoch_changed(&mut self) -> Result<(bool, Vec<Vec<LeadCoin>>)> {
-        let slot = self.current_slot();
-        let epoch = self.slot_epoch(slot);
-        let check = epoch > self.consensus.epoch;
+    pub async fn epoch_changed(&mut self) -> Result<bool> {
+        let epoch = self.current_epoch();
         if epoch <= self.consensus.epoch {
         if epoch <= self.consensus.epoch {
-            return Ok((false, vec![]))
+            return Ok(false)
         }
         }
         // TODO: Retrieve previous lead proof
         // TODO: Retrieve previous lead proof
         let eta = pallas::Base::one();
         let eta = pallas::Base::one();
@@ -321,11 +329,11 @@ impl ValidatorState {
         // TODO: slot parameter should be absolute slot, not relative.
         // TODO: slot parameter should be absolute slot, not relative.
         // At start of epoch, relative slot is 0.
         // At start of epoch, relative slot is 0.
         self.consensus.coins = coins::create_epoch_coins(eta, &owned, epoch, 0);
         self.consensus.coins = coins::create_epoch_coins(eta, &owned, epoch, 0);
-        Ok((true, self.consensus.coins.clone()))      
+        Ok(true)
     }
     }
 
 
     /// Wrapper for coins::is_leader
     /// Wrapper for coins::is_leader
-    pub fn is_slot_leader(&self) -> (bool, usize) { 
+    pub fn is_slot_leader(&self) -> (bool, usize) {
         coins::is_leader(self.current_slot(), &self.consensus.coins)
         coins::is_leader(self.current_slot(), &self.consensus.coins)
     }
     }
 
 
@@ -355,8 +363,16 @@ impl ValidatorState {
         let coin = self.consensus.coins[slot as usize][idx];
         let coin = self.consensus.coins[slot as usize][idx];
         let proof = lead_proof::create_lead_proof(&self.proving_key, coin)?;
         let proof = lead_proof::create_lead_proof(&self.proving_key, coin)?;
         let participants = self.consensus.participants.values().cloned().collect();
         let participants = self.consensus.participants.values().cloned().collect();
-        let metadata = Metadata::new(signed_proposal, self.address, eta, LeadProof::from(proof), participants);
-        
+        let metadata = Metadata::new(
+            signed_proposal,
+            self.address,
+            coin.public_inputs(),
+            idx,
+            eta,
+            LeadProof::from(proof),
+            participants,
+        );
+
         // TODO: [PLACEHOLDER] Add rewards calculation (proof?)
         // TODO: [PLACEHOLDER] Add rewards calculation (proof?)
         // TODO: [PLACEHOLDER] Create and add rewards transaction
         // TODO: [PLACEHOLDER] Create and add rewards transaction
         Ok(Some(BlockProposal::new(header, unproposed_txs, metadata)))
         Ok(Some(BlockProposal::new(header, unproposed_txs, metadata)))
@@ -430,25 +446,38 @@ impl ValidatorState {
             None => return Ok(None),
             None => return Ok(None),
         }
         }
 
 
-        // Node refreshes participants records
-        self.refresh_participants()?;
-        
-        // TODO: retrieve leader from participants list
-        // TODO: validate provided proof using known coins
-        let mut leader = self.slot_leader();
-        if leader.address != proposal.block.metadata.address {
+        let leader = self.consensus.participants.get(&proposal.block.metadata.address);
+        if leader.is_none() {
             warn!(
             warn!(
-                "Received proposal not from slot leader ({}), but from ({})",
-                leader.address, proposal.block.metadata.address
+                "receive_proposal(): Received proposal from unknown node: ({})",
+                proposal.block.metadata.address
             );
             );
             return Ok(None)
             return Ok(None)
         }
         }
+        let leader = leader.unwrap();
+
+        let public_inputs = &leader.coins[current as usize][proposal.block.metadata.winning_index];
+        if public_inputs != &proposal.block.metadata.public_inputs {
+            warn!("receive_proposal(): Received proposal public inputs are invalid.");
+            return Ok(None)
+        }
+
+        match proposal.block.metadata.proof.verify(&self.verifying_key, &public_inputs) {
+            Ok(_) => info!("receive_proposal(): Proof veryfied succsessfully!"),
+            Err(e) => {
+                error!("receive_proposal(): Error during leader proof verification: {}", e);
+                return Ok(None)
+            }
+        }
 
 
         if !leader.public_key.verify(
         if !leader.public_key.verify(
             proposal.block.header.headerhash().as_bytes(),
             proposal.block.header.headerhash().as_bytes(),
             &proposal.block.metadata.signature,
             &proposal.block.metadata.signature,
         ) {
         ) {
-            warn!("Proposer ({}) signature could not be verified", proposal.block.metadata.address);
+            warn!(
+                "receive_proposal(): Proposer ({}) signature could not be verified",
+                proposal.block.metadata.address
+            );
             return Ok(None)
             return Ok(None)
         }
         }
 
 
@@ -466,21 +495,9 @@ impl ValidatorState {
             }
             }
         }
         }
 
 
-        // TODO: [PLACEHOLDER] Add balance proof validation
-        // TODO: [PLACEHOLDER] Add crypsinous proof validation (to replace balance proof)
         // TODO: [PLACEHOLDER] Add rewards validation
         // TODO: [PLACEHOLDER] Add rewards validation
 
 
-        if current > leader.seen {
-            leader.seen = current;
-        }
-
-        // Invalidating quarantine
-        leader.quarantined = None;
-
-        self.consensus.participants.insert(leader.address, leader);
-
         let index = self.find_extended_chain_index(&proposal)?;
         let index = self.find_extended_chain_index(&proposal)?;
-
         if index == -2 {
         if index == -2 {
             return Ok(None)
             return Ok(None)
         }
         }
@@ -498,7 +515,7 @@ impl ValidatorState {
                         to_broadcast = v;
                         to_broadcast = v;
                     }
                     }
                     Err(e) => {
                     Err(e) => {
-                        error!("consensus: Block finalization failed: {}", e);
+                        error!("receive_proposal(): Block finalization failed: {}", e);
                         return Err(e)
                         return Err(e)
                     }
                     }
                 }
                 }
@@ -650,139 +667,12 @@ impl ValidatorState {
             return false
             return false
         }
         }
 
 
-        // TODO: [PLACEHOLDER] Add balance proof validation
+        // TODO: [PLACEHOLDER] don't blintly trust the public inputs/validate them
 
 
         self.consensus.pending_participants.push(participant);
         self.consensus.pending_participants.push(participant);
         true
         true
     }
     }
 
 
-    /// Update participant seen.
-    pub fn participant_keep_alive(&mut self, keep_alive: KeepAlive) -> bool {
-        match self.consensus.participants.get(&keep_alive.address) {
-            None => {
-                warn!(
-                    "Keep alive message from unknown participant: {}",
-                    keep_alive.address.to_string()
-                );
-                false
-            }
-            Some(participant) => {
-                let current = self.current_slot();
-                if current != keep_alive.slot {
-                    warn!("keep alive message slot is not current one for: {}", keep_alive.address);
-                    return false
-                }
-
-                let serialized = serialize(&current);
-                if !participant.public_key.verify(&serialized, &keep_alive.signature) {
-                    warn!(
-                        "Keep alive message signature could not be verified for: {}",
-                        keep_alive.address
-                    );
-                    return false
-                }
-
-                // TODO: [PLACEHOLDER] Add balance proof validation
-
-                // Updating participant last seen slot
-                let mut participant = participant.clone();
-                participant.seen = current;
-
-                // Invalidating quarantine
-                participant.quarantined = None;
-
-                self.consensus.participants.insert(participant.address, participant);
-
-                true
-            }
-        }
-    }
-
-    /// Refresh the participants map, to retain only the active ones.
-    /// Active nodes are considered those that their last seen slot is
-    /// in range: [current_slot - QUARANTINE_DURATION, current_slot]
-    /// Inactive nodes are marked as quarantined, so they can be removed if
-    /// they are in quarantine more than the predifined quarantine period.
-    pub fn refresh_participants(&mut self) -> Result<()> {
-        // Node checks if it should refresh its participants list
-        let current = self.current_slot();
-        if current <= self.consensus.refreshed {
-            debug!("refresh_participants(): Participants have been refreshed this slot.");
-            return Ok(())
-        }
-
-        debug!("refresh_participants(): Adding pending participants");
-        for participant in &self.consensus.pending_participants {
-            self.consensus.participants.insert(participant.address, participant.clone());
-        }
-
-        if self.consensus.pending_participants.is_empty() {
-            debug!(
-                "refresh_participants(): Didn't manage to add any participant, pending were empty."
-            );
-        }
-
-        self.consensus.pending_participants = vec![];
-
-        let mut inactive = Vec::new();
-        let low_bound = current - *QUARANTINE_DURATION;
-
-        debug!(
-            "refresh_participants(): Node {} checking slots range: {} -> {}",
-            self.address, low_bound, current
-        );
-
-        let leader = self.slot_leader();
-        for (index, participant) in self.consensus.participants.iter_mut() {
-            match participant.quarantined {
-                Some(slot) => {
-                    if slot < low_bound {
-                        warn!(
-                            "refresh_participants(): Removing participant: {} (seen {}, quarantined {})",
-                            participant.address,
-                            participant.seen,
-                            slot
-                        );
-                        inactive.push(*index);
-                    }
-                }
-                None => {
-                    // Slot leader is always quarantined, to cover the case they become inactive the slot before
-                    // becoming the leader. This can be used for slashing in the future.
-                    if participant.address == leader.address {
-                        debug!(
-                            "refresh_participants(): Quaranteening leader: {} (seen {})",
-                            participant.address, participant.seen
-                        );
-                        participant.quarantined = Some(current);
-                        continue
-                    }
-                    if participant.seen < low_bound {
-                        warn!(
-                            "refresh_participants(): Quaranteening participant: {} (seen {})",
-                            participant.address, participant.seen
-                        );
-                        participant.quarantined = Some(current);
-                    }
-                }
-            }
-        }
-
-        for index in inactive {
-            self.consensus.participants.remove(&index);
-        }
-
-        if self.consensus.participants.is_empty() {
-            // If no nodes are active, node becomes a single node network.
-            let participant = Participant::new(self.public, self.address, self.current_slot());
-            self.consensus.participants.insert(participant.address, participant);
-        }
-
-        self.consensus.refreshed = current;
-
-        Ok(())
-    }
-
     /// Utility function to reset the current consensus state.
     /// Utility function to reset the current consensus state.
     pub fn reset_consensus_state(&mut self) -> Result<()> {
     pub fn reset_consensus_state(&mut self) -> Result<()> {
         let genesis_ts = self.consensus.genesis_ts;
         let genesis_ts = self.consensus.genesis_ts;

+ 1 - 1
src/consensus/task/block_sync.rs

@@ -45,7 +45,7 @@ pub async fn block_sync_task(p2p: net::P2pPtr, state: ValidatorStatePtr) -> Resu
 
 
                 last = last_received;
                 last = last_received;
             }
             }
-        },
+        }
         None => warn!("Node is not connected to other nodes"),
         None => warn!("Node is not connected to other nodes"),
     };
     };
 
 

+ 0 - 51
src/consensus/task/keep_alive.rs

@@ -1,51 +0,0 @@
-use async_std::sync::Arc;
-use darkfi_serial::serialize;
-use log::{debug, error};
-use rand::Rng;
-use smol::Executor;
-
-use crate::{
-    consensus::{KeepAlive, ValidatorStatePtr, QUARANTINE_DURATION},
-    crypto::schnorr::SchnorrSecret,
-    net::P2pPtr,
-    util::async_util::sleep,
-    Result,
-};
-
-/// async task used for sending keep alive messages in background.
-pub async fn keep_alive_task(
-    p2p: P2pPtr,
-    state: ValidatorStatePtr,
-    ex: Arc<Executor<'_>>,
-) -> Result<()> {
-    ex.spawn(async move {
-        loop {
-            // Pick a random slot in range: next slot + QUARANTINE_DURATION, exluding first and last
-            let slot = rand::thread_rng().gen_range(2..*QUARANTINE_DURATION);
-            let seconds = state.read().await.next_n_slot_start(slot).as_secs();
-            debug!("keep_alive_task: Waiting for next {} slots ({} sec)", slot, seconds);
-
-            // Sleep until that slot
-            sleep(seconds).await;
-
-            // TODO: [PLACEHOLDER] Add balance proof creation
-
-            // Create keep alive message
-            let secret = state.read().await.secret;
-            let address = state.read().await.address;
-            let slot = state.read().await.current_slot();
-            let serialized = serialize(&slot);
-            let signature = secret.sign(&serialized);
-            let keep_alive = KeepAlive { address, slot, signature };
-
-            // Broadcast keep alive message
-            match p2p.broadcast(keep_alive).await {
-                Ok(()) => debug!("keep_alive_task: Keep alive message broadcasted successfully."),
-                Err(e) => error!("keep_alive_task: Failed broadcasting keep alive message: {}", e),
-            }
-        }
-    })
-    .detach();
-
-    Ok(())
-}

+ 0 - 3
src/consensus/task/mod.rs

@@ -8,6 +8,3 @@ pub use consensus_sync::consensus_sync_task;
 
 
 mod proposal;
 mod proposal;
 pub use proposal::proposal_task;
 pub use proposal::proposal_task;
-
-mod keep_alive;
-pub use keep_alive::keep_alive_task;

+ 34 - 51
src/consensus/task/proposal.rs

@@ -1,10 +1,8 @@
 use std::time::Duration;
 use std::time::Duration;
 
 
-use async_std::sync::Arc;
 use log::{debug, error, info};
 use log::{debug, error, info};
-use smol::Executor;
 
 
-use super::{consensus_sync_task, keep_alive_task};
+use super::consensus_sync_task;
 use crate::{
 use crate::{
     consensus::{Participant, ValidatorStatePtr},
     consensus::{Participant, ValidatorStatePtr},
     net::P2pPtr,
     net::P2pPtr,
@@ -12,14 +10,7 @@ use crate::{
 };
 };
 
 
 /// async task used for participating in the consensus protocol
 /// async task used for participating in the consensus protocol
-pub async fn proposal_task(
-    consensus_p2p: P2pPtr,
-    sync_p2p: P2pPtr,
-    state: ValidatorStatePtr,
-    ex: Arc<Executor<'_>>,
-) {
-    // TODO: [PLACEHOLDER] Add balance proof creation
-
+pub async fn proposal_task(consensus_p2p: P2pPtr, sync_p2p: P2pPtr, state: ValidatorStatePtr) {
     // Node waits just before the current or next epoch end, so it can
     // Node waits just before the current or next epoch end, so it can
     // start syncing latest state.
     // start syncing latest state.
     let mut seconds_until_next_epoch = state.read().await.next_n_epoch_start(1);
     let mut seconds_until_next_epoch = state.read().await.next_n_epoch_start(1);
@@ -41,38 +32,16 @@ pub async fn proposal_task(
 
 
     // Node syncs its consensus state
     // Node syncs its consensus state
     if let Err(e) = consensus_sync_task(consensus_p2p.clone(), state.clone()).await {
     if let Err(e) = consensus_sync_task(consensus_p2p.clone(), state.clone()).await {
-        error!("Failed syncing consensus state: {}. Quitting consensus.", e);
+        error!("consensus: Failed syncing consensus state: {}. Quitting consensus.", e);
         // TODO: Perhaps notify over a channel in order to
         // TODO: Perhaps notify over a channel in order to
         // stop consensus p2p protocols.
         // stop consensus p2p protocols.
         return
         return
     };
     };
-    
-    // TODO: change participation logic
-    // nodes will broadcast a Participants message on the start or end
-    // of each epoch, containing their coins public inputs.
-    // Only these nodes will be considered valid.
-    // Node signals the network that it will start participating
-    let public = state.read().await.public;
-    let address = state.read().await.address;
-    let cur_slot = state.read().await.current_slot();
-    let participant = Participant::new(public, address, cur_slot);
-    state.write().await.append_participant(participant.clone());
-
-    match consensus_p2p.broadcast(participant).await {
-        Ok(()) => info!("consensus: Participation message broadcasted successfully."),
-        Err(e) => error!("Failed broadcasting consensus participation: {}", e),
-    }
-
-    // Node initiates the background task to send keep alive messages
-    match keep_alive_task(consensus_p2p.clone(), state.clone(), ex).await {
-        Ok(()) => info!("consensus: Keep alive background task initiated successfully."),
-        Err(e) => error!("Failed to initiate keep alive background task: {}", e),
-    }
 
 
     // Node modifies its participating slot to next.
     // Node modifies its participating slot to next.
     match state.write().await.set_participating() {
     match state.write().await.set_participating() {
         Ok(()) => info!("consensus: Node will start participating in the next slot"),
         Ok(()) => info!("consensus: Node will start participating in the next slot"),
-        Err(e) => error!("Failed to set participation slot: {}", e),
+        Err(e) => error!("consensus: Failed to set participation slot: {}", e),
     }
     }
 
 
     loop {
     loop {
@@ -80,18 +49,36 @@ pub async fn proposal_task(
         info!("consensus: Waiting for next slot ({} sec)", seconds_next_slot);
         info!("consensus: Waiting for next slot ({} sec)", seconds_next_slot);
         sleep(seconds_next_slot).await;
         sleep(seconds_next_slot).await;
 
 
-        // Node refreshes participants records
-        match state.write().await.refresh_participants() {
-            Ok(()) => debug!("Participants refreshed successfully."),
-            Err(e) => error!("Failed refreshing consensus participants: {}", e),
-        }
-        
         // Node checks if epoch has changed, to broadcast a new participation message
         // Node checks if epoch has changed, to broadcast a new participation message
         match state.write().await.epoch_changed().await {
         match state.write().await.epoch_changed().await {
-            Ok((broadcast, coins)) => {
-                if broadcast {
-                    //TODO: broadcast new participation message
-                    //TODO: sleep 2 seconds so all nodes can have the new epoch participants
+            Ok(changed) => {
+                if changed {
+                    let lock = state.read().await;
+                    info!("consensus: New epoch started: {}", lock.current_epoch());
+                    let public = lock.public;
+                    let address = lock.address;
+                    let mut coins = vec![];
+                    for slot_coins in &lock.consensus.coins {
+                        let mut slot_coins_inputs = vec![];
+                        for slot_coin in slot_coins {
+                            slot_coins_inputs.push(slot_coin.public_inputs());
+                        }
+                        coins.push(slot_coins_inputs);
+                    }
+                    let participant = Participant::new(public, address, coins);
+                    state.write().await.append_participant(participant.clone());
+
+                    match consensus_p2p.broadcast(participant).await {
+                        Ok(()) => {
+                            info!("consensus: Participation message broadcasted successfully.")
+                        }
+                        Err(e) => {
+                            error!("consensus: Failed broadcasting consensus participation: {}", e)
+                        }
+                    }
+                    // Node sleeps 2 seconds so all nodes can have the new epoch participants
+                    //TODO: optimize this
+                    sleep(2).await;
                 }
                 }
             }
             }
             Err(e) => {
             Err(e) => {
@@ -99,16 +86,12 @@ pub async fn proposal_task(
                 continue
                 continue
             }
             }
         };
         };
-        
+
         // Node checks if it's the slot leader to generate a new proposal
         // Node checks if it's the slot leader to generate a new proposal
         // for that slot.
         // for that slot.
         let lock = state.read().await;
         let lock = state.read().await;
         let (won, idx) = lock.is_slot_leader();
         let (won, idx) = lock.is_slot_leader();
-        let result = if won {
-            lock.propose(idx)
-        } else {
-            Ok(None)
-        };
+        let result = if won { lock.propose(idx) } else { Ok(None) };
 
 
         let proposal = match result {
         let proposal = match result {
             Ok(prop) => {
             Ok(prop) => {

+ 1 - 1
src/crypto/leadcoin.rs

@@ -59,7 +59,7 @@ impl LeadCoin {
                 .hash(y_coord_arr);
                 .hash(y_coord_arr);
         let cm_pos = self.idx;
         let cm_pos = self.idx;
         let public_inputs: [pallas::Base; LEAD_PUBLIC_INPUT_LEN] =
         let public_inputs: [pallas::Base; LEAD_PUBLIC_INPUT_LEN] =
-             [po_nonce, *po_pk.x(), *po_pk.y(), po_y];
+            [po_nonce, *po_pk.x(), *po_pk.y(), po_y];
         public_inputs
         public_inputs
     }
     }
 
 

+ 77 - 121
src/zk/circuit/tx_contract.rs

@@ -9,7 +9,7 @@ use darkfi_sdk::crypto::{
 use halo2_gadgets::{
 use halo2_gadgets::{
     ecc::{
     ecc::{
         chip::{EccChip, EccConfig},
         chip::{EccChip, EccConfig},
-        FixedPoint, FixedPointBaseField, ScalarFixed, NonIdentityPoint,
+        FixedPoint, FixedPointBaseField, NonIdentityPoint, ScalarFixed,
     },
     },
     poseidon::{
     poseidon::{
         primitives as poseidon, Hash as PoseidonHash, Pow5Chip as PoseidonChip,
         primitives as poseidon, Hash as PoseidonHash, Pow5Chip as PoseidonChip,
@@ -269,13 +269,11 @@ impl Circuit<pallas::Base> for TxContract {
         config: Self::Config,
         config: Self::Config,
         mut layouter: impl Layouter<pallas::Base>,
         mut layouter: impl Layouter<pallas::Base>,
     ) -> Result<(), Error> {
     ) -> Result<(), Error> {
-
         let less_than_chip = config.lessthan_chip();
         let less_than_chip = config.lessthan_chip();
-        NativeRangeCheckChip::<WINDOW_SIZE, NUM_OF_BITS, NUM_OF_WINDOWS>
-            ::load_k_table(
-                &mut layouter,
-                config.lessthan_config.k_values_table,
-            )?;
+        NativeRangeCheckChip::<WINDOW_SIZE, NUM_OF_BITS, NUM_OF_WINDOWS>::load_k_table(
+            &mut layouter,
+            config.lessthan_config.k_values_table,
+        )?;
         SinsemillaChip::load(config.sinsemilla_config_1.clone(), &mut layouter)?;
         SinsemillaChip::load(config.sinsemilla_config_1.clone(), &mut layouter)?;
         let ecc_chip = config.ecc_chip();
         let ecc_chip = config.ecc_chip();
         let ar_chip = config.arith_chip();
         let ar_chip = config.arith_chip();
@@ -293,75 +291,53 @@ impl Circuit<pallas::Base> for TxContract {
             config.advices[0],
             config.advices[0],
             Value::known(-pallas::Base::one()),
             Value::known(-pallas::Base::one()),
         )?;
         )?;
-        let root_cm = self.load_private(layouter.namespace(|| ""),
-                                        config.advices[0],
-                                        self.root_cm
-        )?;
+        let root_cm =
+            self.load_private(layouter.namespace(|| ""), config.advices[0], self.root_cm)?;
 
 
-        let coin1_sk = self.load_private(layouter.namespace(|| "root sk"),
-                                              config.advices[0],
-                                              self.coin1_sk
-        )?;
+        let coin1_sk =
+            self.load_private(layouter.namespace(|| "root sk"), config.advices[0], self.coin1_sk)?;
 
 
-        let coin1_root_sk = self.load_private(layouter.namespace(|| "root root sk"),
-                                              config.advices[0],
-                                              self.coin1_root_sk
+        let coin1_root_sk = self.load_private(
+            layouter.namespace(|| "root root sk"),
+            config.advices[0],
+            self.coin1_root_sk,
         )?;
         )?;
 
 
-        let coin1_value = self.load_private(layouter.namespace(|| ""),
-                                            config.advices[0],
-                                            self.coin1_value
-        )?;
+        let coin1_value =
+            self.load_private(layouter.namespace(|| ""), config.advices[0], self.coin1_value)?;
 
 
-        let coin1_nonce = self.load_private(layouter.namespace(|| ""),
-                                            config.advices[0],
-                                            self.coin1_nonce
-        )?;
+        let coin1_nonce =
+            self.load_private(layouter.namespace(|| ""), config.advices[0], self.coin1_nonce)?;
 
 
-        let coin1_sn = self.load_private(layouter.namespace(|| ""),
-                                            config.advices[0],
-                                            self.coin1_sn
-        )?;
+        let coin1_sn =
+            self.load_private(layouter.namespace(|| ""), config.advices[0], self.coin1_sn)?;
 
 
-        let coin2_sk = self.load_private(layouter.namespace(|| "root sk"),
-                                         config.advices[0],
-                                         self.coin2_sk
-        )?;
+        let coin2_sk =
+            self.load_private(layouter.namespace(|| "root sk"), config.advices[0], self.coin2_sk)?;
 
 
-        let coin2_root_sk = self.load_private(layouter.namespace(|| "root sk"),
-                                              config.advices[0],
-                                              self.coin2_root_sk
+        let coin2_root_sk = self.load_private(
+            layouter.namespace(|| "root sk"),
+            config.advices[0],
+            self.coin2_root_sk,
         )?;
         )?;
 
 
-        let coin2_value = self.load_private(layouter.namespace(|| ""),
-                                              config.advices[0],
-                                              self.coin2_value
-        )?;
+        let coin2_value =
+            self.load_private(layouter.namespace(|| ""), config.advices[0], self.coin2_value)?;
 
 
-        let coin2_nonce = self.load_private(layouter.namespace(|| ""),
-                                            config.advices[0],
-                                            self.coin2_nonce
-        )?;
+        let coin2_nonce =
+            self.load_private(layouter.namespace(|| ""), config.advices[0], self.coin2_nonce)?;
 
 
-        let coin2_sn = self.load_private(layouter.namespace(|| ""),
-                                         config.advices[0],
-                                         self.coin2_sn
-        )?;
+        let coin2_sn =
+            self.load_private(layouter.namespace(|| ""), config.advices[0], self.coin2_sn)?;
 
 
-        let coin3_value = self.load_private(layouter.namespace(|| ""),
-                                            config.advices[0],
-                                            self.coin3_value
-        )?;
+        let coin3_value =
+            self.load_private(layouter.namespace(|| ""), config.advices[0], self.coin3_value)?;
 
 
-        let coin3_pk = self.load_private(layouter.namespace(|| ""),
-                                            config.advices[0],
-                                            self.coin3_pk
-        )?;
+        let coin3_pk =
+            self.load_private(layouter.namespace(|| ""), config.advices[0], self.coin3_pk)?;
 
 
-        let coin3_nonce = self.load_private(layouter.namespace(|| ""),
-                                            config.advices[0],
-                                            self.coin3_nonce
-        )?;
+        let coin3_nonce =
+            self.load_private(layouter.namespace(|| ""), config.advices[0], self.coin3_nonce)?;
 
 
         let ref_coin3_cm = NonIdentityPoint::new(
         let ref_coin3_cm = NonIdentityPoint::new(
             ecc_chip.clone(),
             ecc_chip.clone(),
@@ -369,20 +345,14 @@ impl Circuit<pallas::Base> for TxContract {
             self.coin3_cm.map(|x| x.to_affine()),
             self.coin3_cm.map(|x| x.to_affine()),
         )?;
         )?;
 
 
-        let coin4_value = self.load_private(layouter.namespace(|| ""),
-                                            config.advices[0],
-                                            self.coin4_value
-        )?;
+        let coin4_value =
+            self.load_private(layouter.namespace(|| ""), config.advices[0], self.coin4_value)?;
 
 
-        let coin4_pk = self.load_private(layouter.namespace(|| ""),
-                                         config.advices[0],
-                                         self.coin4_pk
-        )?;
+        let coin4_pk =
+            self.load_private(layouter.namespace(|| ""), config.advices[0], self.coin4_pk)?;
 
 
-        let coin4_nonce = self.load_private(layouter.namespace(|| ""),
-                                            config.advices[0],
-                                            self.coin4_nonce
-        )?;
+        let coin4_nonce =
+            self.load_private(layouter.namespace(|| ""), config.advices[0], self.coin4_nonce)?;
 
 
         let ref_coin4_cm = NonIdentityPoint::new(
         let ref_coin4_cm = NonIdentityPoint::new(
             ecc_chip.clone(),
             ecc_chip.clone(),
@@ -399,13 +369,13 @@ impl Circuit<pallas::Base> for TxContract {
         let coin1_pk: AssignedCell<Fp, Fp> = {
         let coin1_pk: AssignedCell<Fp, Fp> = {
             let poseidon_message = [one.clone(), coin1_root_sk.clone()];
             let poseidon_message = [one.clone(), coin1_root_sk.clone()];
             let poseidon_hasher = PoseidonHash::<
             let poseidon_hasher = PoseidonHash::<
-                    _,
+                _,
                 _,
                 _,
                 poseidon::P128Pow5T3,
                 poseidon::P128Pow5T3,
                 poseidon::ConstantLength<2>,
                 poseidon::ConstantLength<2>,
                 3,
                 3,
                 2,
                 2,
-                >::init(
+            >::init(
                 config.poseidon_chip(), layouter.namespace(|| "Poseidon init")
                 config.poseidon_chip(), layouter.namespace(|| "Poseidon init")
             )?;
             )?;
             let poseidon_output =
             let poseidon_output =
@@ -427,13 +397,13 @@ impl Circuit<pallas::Base> for TxContract {
         let coin2_pk: AssignedCell<Fp, Fp> = {
         let coin2_pk: AssignedCell<Fp, Fp> = {
             let poseidon_message = [one.clone(), coin2_root_sk.clone()];
             let poseidon_message = [one.clone(), coin2_root_sk.clone()];
             let poseidon_hasher = PoseidonHash::<
             let poseidon_hasher = PoseidonHash::<
-                    _,
+                _,
                 _,
                 _,
                 poseidon::P128Pow5T3,
                 poseidon::P128Pow5T3,
                 poseidon::ConstantLength<2>,
                 poseidon::ConstantLength<2>,
                 3,
                 3,
                 2,
                 2,
-                >::init(
+            >::init(
                 config.poseidon_chip(), layouter.namespace(|| "Poseidon init")
                 config.poseidon_chip(), layouter.namespace(|| "Poseidon init")
             )?;
             )?;
             let poseidon_output =
             let poseidon_output =
@@ -454,12 +424,8 @@ impl Circuit<pallas::Base> for TxContract {
         // ========
         // ========
         let com1 = {
         let com1 = {
             let nullifier2_msg: AssignedCell<Fp, Fp> = {
             let nullifier2_msg: AssignedCell<Fp, Fp> = {
-                let poseidon_message = [
-                    coin1_pk.clone(),
-                    coin1_value.clone(),
-                    coin1_nonce.clone(),
-                    one.clone()
-                ];
+                let poseidon_message =
+                    [coin1_pk.clone(), coin1_value.clone(), coin1_nonce.clone(), one.clone()];
                 let poseidon_hasher = PoseidonHash::<
                 let poseidon_hasher = PoseidonHash::<
                     _,
                     _,
                     _,
                     _,
@@ -511,12 +477,8 @@ impl Circuit<pallas::Base> for TxContract {
         // ========
         // ========
         let com2 = {
         let com2 = {
             let nullifier2_msg: AssignedCell<Fp, Fp> = {
             let nullifier2_msg: AssignedCell<Fp, Fp> = {
-                let poseidon_message = [
-                    coin2_pk.clone(),
-                    coin2_value.clone(),
-                    coin2_nonce.clone(),
-                    one.clone()
-                ];
+                let poseidon_message =
+                    [coin2_pk.clone(), coin2_value.clone(), coin2_nonce.clone(), one.clone()];
                 let poseidon_hasher = PoseidonHash::<
                 let poseidon_hasher = PoseidonHash::<
                     _,
                     _,
                     _,
                     _,
@@ -568,12 +530,8 @@ impl Circuit<pallas::Base> for TxContract {
         // ========
         // ========
         let com3 = {
         let com3 = {
             let nullifier2_msg: AssignedCell<Fp, Fp> = {
             let nullifier2_msg: AssignedCell<Fp, Fp> = {
-                let poseidon_message = [
-                    coin3_pk.clone(),
-                    coin3_value.clone(),
-                    coin3_nonce.clone(),
-                    one.clone()
-                ];
+                let poseidon_message =
+                    [coin3_pk.clone(), coin3_value.clone(), coin3_nonce.clone(), one.clone()];
                 let poseidon_hasher = PoseidonHash::<
                 let poseidon_hasher = PoseidonHash::<
                     _,
                     _,
                     _,
                     _,
@@ -606,19 +564,15 @@ impl Circuit<pallas::Base> for TxContract {
             coin_commit_r.mul(layouter.namespace(|| "coin serial number commit R"), coin3_blind)?
             coin_commit_r.mul(layouter.namespace(|| "coin serial number commit R"), coin3_blind)?
         };
         };
         let coin3_commit = com2.add(layouter.namespace(|| "nonce commit"), &blind)?;
         let coin3_commit = com2.add(layouter.namespace(|| "nonce commit"), &blind)?;
-        coin3_commit.constrain_equal(layouter.namespace(||""), &ref_coin3_cm);
+        coin3_commit.constrain_equal(layouter.namespace(|| ""), &ref_coin3_cm);
 
 
         // ========
         // ========
         // coin4 cm
         // coin4 cm
         // ========
         // ========
         let com4 = {
         let com4 = {
             let nullifier2_msg: AssignedCell<Fp, Fp> = {
             let nullifier2_msg: AssignedCell<Fp, Fp> = {
-                let poseidon_message = [
-                    coin4_pk.clone(),
-                    coin4_value.clone(),
-                    coin4_nonce.clone(),
-                    one.clone()
-                ];
+                let poseidon_message =
+                    [coin4_pk.clone(), coin4_value.clone(), coin4_nonce.clone(), one.clone()];
                 let poseidon_hasher = PoseidonHash::<
                 let poseidon_hasher = PoseidonHash::<
                     _,
                     _,
                     _,
                     _,
@@ -651,10 +605,12 @@ impl Circuit<pallas::Base> for TxContract {
             coin_commit_r.mul(layouter.namespace(|| "coin serial number commit R"), coin4_blind)?
             coin_commit_r.mul(layouter.namespace(|| "coin serial number commit R"), coin4_blind)?
         };
         };
         let coin4_commit = com2.add(layouter.namespace(|| " commit"), &blind)?;
         let coin4_commit = com2.add(layouter.namespace(|| " commit"), &blind)?;
-        coin4_commit.constrain_equal(layouter.namespace(||""), &ref_coin4_cm);
+        coin4_commit.constrain_equal(layouter.namespace(|| ""), &ref_coin4_cm);
 
 
-        let v1pv2: AssignedCell<Fp, Fp> = ar_chip.add(layouter.namespace(||""), &coin1_value, &coin2_value)?;
-        let v3pv4: AssignedCell<Fp, Fp> = ar_chip.add(layouter.namespace(||""), &coin3_value, &coin4_value)?;
+        let v1pv2: AssignedCell<Fp, Fp> =
+            ar_chip.add(layouter.namespace(|| ""), &coin1_value, &coin2_value)?;
+        let v3pv4: AssignedCell<Fp, Fp> =
+            ar_chip.add(layouter.namespace(|| ""), &coin3_value, &coin4_value)?;
 
 
         // ==========
         // ==========
         // COIN1 PATH
         // COIN1 PATH
@@ -672,13 +628,13 @@ impl Circuit<pallas::Base> for TxContract {
         let coin1_cm_hash: AssignedCell<Fp, Fp> = {
         let coin1_cm_hash: AssignedCell<Fp, Fp> = {
             let poseidon_message = [coin1_commit_x.clone(), coin1_commit_y.clone()];
             let poseidon_message = [coin1_commit_x.clone(), coin1_commit_y.clone()];
             let poseidon_hasher = PoseidonHash::<
             let poseidon_hasher = PoseidonHash::<
-                    _,
+                _,
                 _,
                 _,
                 poseidon::P128Pow5T3,
                 poseidon::P128Pow5T3,
                 poseidon::ConstantLength<2>,
                 poseidon::ConstantLength<2>,
                 3,
                 3,
                 2,
                 2,
-                >::init(
+            >::init(
                 config.poseidon_chip(), layouter.namespace(|| "Poseidon init")
                 config.poseidon_chip(), layouter.namespace(|| "Poseidon init")
             )?;
             )?;
 
 
@@ -687,8 +643,8 @@ impl Circuit<pallas::Base> for TxContract {
             let poseidon_output: AssignedCell<Fp, Fp> = poseidon_output;
             let poseidon_output: AssignedCell<Fp, Fp> = poseidon_output;
             poseidon_output
             poseidon_output
         };
         };
-        let coin1_cm_root = merkle_inputs
-            .calculate_root(layouter.namespace(|| "calculate root"), coin1_cm_hash)?;
+        let coin1_cm_root =
+            merkle_inputs.calculate_root(layouter.namespace(|| "calculate root"), coin1_cm_hash)?;
 
 
         // ==========
         // ==========
         // COIN2 PATH
         // COIN2 PATH
@@ -706,13 +662,13 @@ impl Circuit<pallas::Base> for TxContract {
         let coin2_cm_hash: AssignedCell<Fp, Fp> = {
         let coin2_cm_hash: AssignedCell<Fp, Fp> = {
             let poseidon_message = [coin2_commit_x.clone(), coin2_commit_y.clone()];
             let poseidon_message = [coin2_commit_x.clone(), coin2_commit_y.clone()];
             let poseidon_hasher = PoseidonHash::<
             let poseidon_hasher = PoseidonHash::<
-                    _,
+                _,
                 _,
                 _,
                 poseidon::P128Pow5T3,
                 poseidon::P128Pow5T3,
                 poseidon::ConstantLength<2>,
                 poseidon::ConstantLength<2>,
                 3,
                 3,
                 2,
                 2,
-                >::init(
+            >::init(
                 config.poseidon_chip(), layouter.namespace(|| "Poseidon init")
                 config.poseidon_chip(), layouter.namespace(|| "Poseidon init")
             )?;
             )?;
 
 
@@ -721,8 +677,8 @@ impl Circuit<pallas::Base> for TxContract {
             let poseidon_output: AssignedCell<Fp, Fp> = poseidon_output;
             let poseidon_output: AssignedCell<Fp, Fp> = poseidon_output;
             poseidon_output
             poseidon_output
         };
         };
-        let coin2_cm_root = merkle_inputs
-            .calculate_root(layouter.namespace(|| "calculate root"), coin2_cm_hash)?;
+        let coin2_cm_root =
+            merkle_inputs.calculate_root(layouter.namespace(|| "calculate root"), coin2_cm_hash)?;
 
 
         // =============
         // =============
         // COIN1 sk root
         // COIN1 sk root
@@ -735,8 +691,8 @@ impl Circuit<pallas::Base> for TxContract {
             self.coin1_sk_pos,
             self.coin1_sk_pos,
             path,
             path,
         );
         );
-        let coin1_sk_root = merkle_inputs
-            .calculate_root(layouter.namespace(|| "calculate root"), coin1_sk)?;
+        let coin1_sk_root =
+            merkle_inputs.calculate_root(layouter.namespace(|| "calculate root"), coin1_sk)?;
 
 
         // =============
         // =============
         // COIN2 sk root
         // COIN2 sk root
@@ -749,8 +705,8 @@ impl Circuit<pallas::Base> for TxContract {
             self.coin2_sk_pos,
             self.coin2_sk_pos,
             path,
             path,
         );
         );
-        let coin2_sk_root = merkle_inputs
-            .calculate_root(layouter.namespace(|| "calculate root"), coin2_sk)?;
+        let coin2_sk_root =
+            merkle_inputs.calculate_root(layouter.namespace(|| "calculate root"), coin2_sk)?;
 
 
         // ========
         // ========
         // coin1 sn
         // coin1 sn
@@ -758,13 +714,13 @@ impl Circuit<pallas::Base> for TxContract {
         let coin1_sn_commit: AssignedCell<Fp, Fp> = {
         let coin1_sn_commit: AssignedCell<Fp, Fp> = {
             let poseidon_message = [coin1_nonce.clone(), coin1_root_sk.clone()];
             let poseidon_message = [coin1_nonce.clone(), coin1_root_sk.clone()];
             let poseidon_hasher = PoseidonHash::<
             let poseidon_hasher = PoseidonHash::<
-                    _,
+                _,
                 _,
                 _,
                 poseidon::P128Pow5T3,
                 poseidon::P128Pow5T3,
                 poseidon::ConstantLength<2>,
                 poseidon::ConstantLength<2>,
                 3,
                 3,
                 2,
                 2,
-                >::init(
+            >::init(
                 config.poseidon_chip(), layouter.namespace(|| "Poseidon init")
                 config.poseidon_chip(), layouter.namespace(|| "Poseidon init")
             )?;
             )?;
 
 
@@ -780,13 +736,13 @@ impl Circuit<pallas::Base> for TxContract {
         let coin2_sn_commit: AssignedCell<Fp, Fp> = {
         let coin2_sn_commit: AssignedCell<Fp, Fp> = {
             let poseidon_message = [coin2_nonce.clone(), coin2_root_sk.clone()];
             let poseidon_message = [coin2_nonce.clone(), coin2_root_sk.clone()];
             let poseidon_hasher = PoseidonHash::<
             let poseidon_hasher = PoseidonHash::<
-                    _,
+                _,
                 _,
                 _,
                 poseidon::P128Pow5T3,
                 poseidon::P128Pow5T3,
                 poseidon::ConstantLength<2>,
                 poseidon::ConstantLength<2>,
                 3,
                 3,
                 2,
                 2,
-                >::init(
+            >::init(
                 config.poseidon_chip(), layouter.namespace(|| "Poseidon init")
                 config.poseidon_chip(), layouter.namespace(|| "Poseidon init")
             )?;
             )?;