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

consensus/metadata: added coin serial and new coin public inputs

aggstam 3 лет назад
Родитель
Сommit
8a60502a2f

+ 30 - 2
src/consensus/metadata.rs

@@ -43,8 +43,12 @@ pub struct Metadata {
     pub address: Address,
     /// Block owner slot competing coins public inputs
     pub public_inputs: Vec<pallas::Base>,
+    /// Block owner newlly minted coin public inputs
+    pub new_public_inputs: Vec<pallas::Base>,
     /// Block owner winning coin index
     pub winning_index: usize,
+    /// Block owner winning coin serial number
+    pub serial_number: pallas::Base,
     /// Response of global random oracle, or it's emulation.
     pub eta: [u8; 32],
     /// Leader NIZK proof
@@ -59,11 +63,23 @@ impl Default for Metadata {
         let address = Address::from(keypair.public);
         let signature = Signature::dummy();
         let public_inputs = vec![];
+        let new_public_inputs = vec![];
         let winning_index = 0;
+        let serial_number = pallas::Base::from(0);
         let eta: [u8; 32] = *blake3::hash(b"let there be dark!").as_bytes();
         let proof = LeadProof::default();
         let participants = vec![];
-        Self { signature, address, public_inputs, winning_index, eta, proof, participants }
+        Self {
+            signature,
+            address,
+            public_inputs,
+            new_public_inputs,
+            winning_index,
+            serial_number,
+            eta,
+            proof,
+            participants,
+        }
     }
 }
 
@@ -72,12 +88,24 @@ impl Metadata {
         signature: Signature,
         address: Address,
         public_inputs: Vec<pallas::Base>,
+        new_public_inputs: Vec<pallas::Base>,
         winning_index: usize,
+        serial_number: pallas::Base,
         eta: [u8; 32],
         proof: LeadProof,
         participants: Vec<Participant>,
     ) -> Self {
-        Self { signature, address, public_inputs, winning_index, eta, proof, participants }
+        Self {
+            signature,
+            address,
+            public_inputs,
+            new_public_inputs,
+            winning_index,
+            serial_number,
+            eta,
+            proof,
+            participants,
+        }
     }
 }
 

+ 4 - 0
src/consensus/ouroboros/stakeholder.rs

@@ -368,6 +368,8 @@ impl Stakeholder {
         info!("Winning coin index: {}", idx);
         // Generating leader proof
         let coin = self.epoch.get_coin(sl as usize, idx);
+        // TODO: Generate new LeadCoin from newlly minted coin, will reuse original coin for now
+        //let coin2 = something();
         let proof = self.epoch.get_proof(sl as usize, idx, &self.get_leadprovkingkey());
         //Verifying generated proof against winning coin public inputs
         info!("Leader proof generated successfully, veryfing...");
@@ -389,7 +391,9 @@ impl Stakeholder {
             sign,
             addr,
             coin.public_inputs(),
+            coin.public_inputs(),
             idx,
+            coin.sn.unwrap(),
             self.get_eta().to_repr(),
             LeadProof::from(proof),
             vec![],

+ 18 - 3
src/consensus/state.rs

@@ -356,7 +356,7 @@ impl ValidatorState {
     /// Generate a block proposal for the current slot, containing all
     /// unconfirmed transactions. Proposal extends the longest fork
     /// chain the node is holding.
-    pub fn propose(&self, idx: usize) -> Result<Option<BlockProposal>> {
+    pub fn propose(&mut self, idx: usize) -> Result<Option<BlockProposal>> {
         let slot = self.current_slot();
         let (prev_hash, index) = self.longest_chain_last_hash().unwrap();
         let unproposed_txs = self.unproposed_txs(index);
@@ -375,18 +375,25 @@ impl ValidatorState {
         let signed_proposal = self.secret.sign(&mut OsRng, &header.headerhash().as_bytes()[..]);
         let eta = self.get_eta().to_repr();
         // Generating leader proof
-        let coin = self.consensus.coins[self.relative_slot(slot) as usize][idx];
+        let relative_slot = self.relative_slot(slot) as usize;
+        let coin = self.consensus.coins[relative_slot][idx];
+        // TODO: Generate new LeadCoin from newlly minted coin, will reuse original coin for now
+        //let coin2 = something();
         let proof = lead_proof::create_lead_proof(&self.proving_key, coin)?;
         let participants = self.consensus.participants.values().cloned().collect();
         let metadata = Metadata::new(
             signed_proposal,
             self.address,
             coin.public_inputs(),
+            coin.public_inputs(),
             idx,
+            coin.sn.unwrap(),
             eta,
             LeadProof::from(proof),
             participants,
         );
+        // TODO: replace old coin with new coin
+        self.consensus.coins[relative_slot][idx] = coin;
 
         // TODO: [PLACEHOLDER] Add rewards calculation (proof?)
         // TODO: [PLACEHOLDER] Create and add rewards transaction
@@ -470,7 +477,7 @@ impl ValidatorState {
             );
             return Err(Error::UnknownNodeError)
         }
-        let leader = leader.unwrap();
+        let mut leader = leader.unwrap().clone();
 
         // Check if proposal header matches actual one
         let proposal_header = proposal.block.header.headerhash();
@@ -490,6 +497,8 @@ impl ValidatorState {
             return Err(Error::InvalidPublicInputsError)
         }
 
+        // TODO: Verify winning coin serial number
+
         // Verify proposal leader proof
         match proposal.block.metadata.proof.verify(&self.verifying_key, public_inputs) {
             Ok(_) => info!("receive_proposal(): Proof veryfied succsessfully!"),
@@ -532,6 +541,12 @@ impl ValidatorState {
         }
 
         // TODO: [PLACEHOLDER] Add rewards validation
+        // TODO: Append serial to merkle tree
+
+        // Replacing participants public inputs with the newlly minted ones
+        leader.coins[self.relative_slot(current) as usize][proposal.block.metadata.winning_index] =
+            proposal.block.metadata.new_public_inputs.clone();
+        self.append_participant(leader);
 
         // Check if proposal fork has can be finalized, to broadcast those blocks
         let mut to_broadcast = vec![];

+ 8 - 6
src/consensus/task/proposal.rs

@@ -108,7 +108,7 @@ pub async fn proposal_task(consensus_p2p: P2pPtr, sync_p2p: P2pPtr, state: Valid
         // Node checks if it's the slot leader to generate a new proposal
         // for that slot.
         let (won, idx) = state.read().await.is_slot_leader();
-        let result = if won { state.read().await.propose(idx) } else { Ok(None) };
+        let result = if won { state.write().await.propose(idx) } else { Ok(None) };
         let proposal = match result {
             Ok(prop) => {
                 if prop.is_none() {
@@ -135,11 +135,13 @@ pub async fn proposal_task(consensus_p2p: P2pPtr, sync_p2p: P2pPtr, state: Valid
                 }
                 // Broadcast finalized blocks info, if any:
                 if let Some(blocks) = to_broadcast {
-                    info!("consensus: Broadcasting finalized blocks");
-                    for info in blocks {
-                        match sync_p2p.broadcast(info).await {
-                            Ok(()) => info!("consensus: Broadcasted block"),
-                            Err(e) => error!("consensus: Failed broadcasting block: {}", e),
+                    if blocks.len() > 0 {
+                        info!("consensus: Broadcasting finalized blocks");
+                        for info in blocks {
+                            match sync_p2p.broadcast(info).await {
+                                Ok(()) => info!("consensus: Broadcasted block"),
+                                Err(e) => error!("consensus: Failed broadcasting block: {}", e),
+                            }
                         }
                     }
                 } else {