Procházet zdrojové kódy

[consensus] append TransactionLeadProof to ourboros metadata

mohab metwally před 4 roky
rodič
revize
3436f22696

+ 29 - 5
example/lead.rs

@@ -6,6 +6,10 @@ use pasta_curves::{
     pallas,
 };
 
+
+use darkfi::crypto::proof::VerifyingKey;
+use darkfi::crypto::proof::ProvingKey;
+
 use darkfi::{
     blockchain::{
         Blockchain,
@@ -16,17 +20,20 @@ use darkfi::{
     crypto::{
         constants::MERKLE_DEPTH_ORCHARD,
         leadcoin::LeadCoin,
+        lead_proof,
         merkle_node::MerkleNode,
         util::{mod_r_p, pedersen_commitment_scalar},
     },
+    tx::Transaction,
+    consensus::{TransactionLeadProof, Metadata, StreamletMetadata, BlockInfo},
     zk::circuit::lead_contract::LeadContract,
 };
 
 fn main() {
     let k: u32 = 13;
     //
-    //let lead_pk = ProvingKey::build(k, &LeadContract::default());
-    //let lead_vk = VerifyingKey::build(k, &LeadContract::default());
+    let lead_pk = ProvingKey::build(k, &LeadContract::default());
+    let lead_vk = VerifyingKey::build(k, &LeadContract::default());
     //
     const LEN: usize = 10;
     let epoch_item = EpochItem {
@@ -49,12 +56,29 @@ fn main() {
     let coin_idx = 0;
     let coin = coins[coin_idx];
     let contract = coin.create_contract();
-    //let proof = create_lead_proof(lead_pk.clone(), coin.clone()).unwrap();
-    //verify_lead_proof(&lead_vk, &proof, coin);
+
+    //
+    //let proof = lead_proof::create_lead_proof(lead_pk.clone(), coin.clone());
+    //lead_proof::verify_lead_proof(&lead_vk, &proof, coin);
+
+    let proof = lead_proof::create_lead_proof(lead_pk.clone(), coin.clone()).unwrap();
+    let lead_tx = TransactionLeadProof::new(lead_pk, coin.clone());
+    //TODO (fix)
+    //lead_tx.verify(lead_vk, coin);
+    //2 add proof transaction to the blockchain.
+    //2.1 first add the lead proof to the block metadata
+    //2.2 secondly read eta from the proof metadata
+    //3.3 (fix) blake3
+    let (st_id, st_hash)  = stakeholder.blockchain.last().unwrap();
+    let empty_txs : Vec<Transaction> = vec!();
+    let metadata = Metadata::new(Timestamp::current_time(), epoch.eta.to_repr(), lead_tx);
+    let sm = StreamletMetadata::new(vec!());
+    let bk_info = BlockInfo::new(st_hash, 1, 0, empty_txs, metadata, sm);
+    let blks = [bk_info];
+    stakeholder.blockchain.add(&blks);
 
     // calculate public inputs
     let public_inputs = coin.public_inputs();
-    //
     let prover = MockProver::run(k, &contract, vec![public_inputs]).unwrap();
     //
     assert_eq!(prover.verify(), Ok(()));

+ 1 - 10
src/blockchain/epoch.rs

@@ -86,24 +86,15 @@ impl Epoch {
             let sk_bytes = if _i ==0 {
                 let base = pedersen_commitment_scalar(pallas::Scalar::one(), pallas::Scalar::random(&mut rng));
                 let coord = base.to_affine().coordinates().unwrap();
-                //let sk_base =  coord.x() * coord.y();
-                let sk_base =  pallas::Base::one();
+                let sk_base =  coord.x() * coord.y();
                 prev_sk_base = sk_base;
                 sk_base.to_repr()
             } else {
-                /*
                 let base = pedersen_commitment_scalar(pallas::Scalar::one(), mod_r_p(prev_sk_base));
                 let coord = base.to_affine().coordinates().unwrap();
                 let sk_base =  coord.x() * coord.y();
                 prev_sk_base = sk_base;
                 sk_base.to_repr()
-                 */
-                let base = pedersen_commitment_scalar(pallas::Scalar::one(), pallas::Scalar::random(&mut rng));
-                let coord = base.to_affine().coordinates().unwrap();
-                //let sk_base =  coord.x() * coord.y();
-                let sk_base =  pallas::Base::one();
-                prev_sk_base = sk_base;
-                sk_base.to_repr()
             };
             let node = MerkleNode::from_bytes(&sk_bytes).unwrap();
             //let serialized = serde_json::to_string(&node).unwrap();

+ 6 - 3
src/blockchain/metadatastore.rs

@@ -1,5 +1,5 @@
 use crate::{
-    consensus::{Block, StreamletMetadata, OuroborosMetadata},
+    consensus::{Block, StreamletMetadata, OuroborosMetadata, TransactionLeadProof},
     util::{
         serial::{deserialize, serialize},
         time::Timestamp,
@@ -120,11 +120,14 @@ impl OuroborosMetadataStore {
             let genesis_block = Block::genesis_block(genesis_ts, genesis_data);
             let genesis_hash = blake3::hash(&serialize(&genesis_block));
 
+            let empty_lead_proof = TransactionLeadProof::default();
             let metadata = OuroborosMetadata {
-                eta,
+                eta: eta,
+                lead_proof: empty_lead_proof,
             };
 
-            store.insert(&[genesis_hash], &[metadata])?;
+            store.insert(&[genesis_hash],
+                         &[metadata])?;
         }
 
         Ok(store)

+ 4 - 2
src/consensus/block.rs

@@ -2,7 +2,7 @@ use std::io;
 
 use log::debug;
 
-use super::{Metadata, StreamletMetadata, OuroborosMetadata, BLOCK_VERSION};
+use super::{Metadata, StreamletMetadata, OuroborosMetadata, BLOCK_VERSION, TransactionLeadProof};
 use crate::{
     crypto::{address::Address, keypair::PublicKey, schnorr::Signature},
     impl_vec, net,
@@ -11,6 +11,7 @@ use crate::{
         serial::{serialize, Decodable, Encodable, SerialDecodable, SerialEncodable, VarInt},
         time::Timestamp,
     },
+
     Result,
 };
 
@@ -48,8 +49,9 @@ impl Block {
     /// Generate the genesis block.
     pub fn genesis_block(genesis_ts: Timestamp, genesis_data: blake3::Hash) -> Self {
         let eta : [u8; 32] = *blake3::hash(b"let there be dark!").as_bytes();
+        let empty_lead_proof = TransactionLeadProof::default();
         let metadata =
-            Metadata::new(genesis_ts, eta);
+            Metadata::new(genesis_ts, eta, empty_lead_proof);
 
         Self::new(genesis_data, 0, 0, vec![], metadata)
     }

+ 52 - 8
src/consensus/metadata.rs

@@ -1,9 +1,23 @@
 use super::{Participant, Vote};
-use crate::util::{
-    serial::{SerialDecodable, SerialEncodable},
-    time::Timestamp,
+use crate::{
+    util::{
+        serial::{SerialDecodable, SerialEncodable},
+        time::Timestamp,
+    },
+    crypto::{
+        proof::{
+            Proof,
+            ProvingKey,
+            VerifyingKey,
+        },
+        lead_proof,
+        leadcoin::LeadCoin,
+    },
+    Result, VerifyFailed, VerifyResult,
 };
 
+use log::error;
+
 /// This struct represents additional [`Block`](super::Block) information used by
 /// the consensus protocol
 #[derive(Debug, Clone, PartialEq, SerialEncodable, SerialDecodable)]
@@ -15,22 +29,52 @@ pub struct Metadata {
 }
 
 impl Metadata {
-    pub fn new(timestamp: Timestamp, eta: [u8;32]) -> Self {
-        Self { timestamp, om: OuroborosMetadata::new(eta) }
+    pub fn new(timestamp: Timestamp, eta: [u8;32], lead_proof: TransactionLeadProof) -> Self {
+        Self { timestamp, om: OuroborosMetadata::new(eta, lead_proof) }
     }
 }
 
+
+#[derive(Debug, Clone, PartialEq,  SerialEncodable, SerialDecodable)]
+pub struct TransactionLeadProof {
+    /// leadership proof
+    pub lead_proof: Proof,
+}
+
+impl TransactionLeadProof {
+    pub fn new(pk : ProvingKey, coin: LeadCoin) -> Self
+    {
+        let proof = lead_proof::create_lead_proof(pk.clone(), coin.clone()).unwrap();
+        Self { lead_proof: proof }
+    }
+
+    pub fn verify(&self, vk : VerifyingKey, coin: LeadCoin) -> VerifyResult<()>
+    {
+        lead_proof::verify_lead_proof(&vk, &self.lead_proof, coin)
+    }
+}
+
+impl Default for TransactionLeadProof {
+    fn default() -> Self
+    {
+        Self {lead_proof: Proof::new(vec!())}
+    }
+}
+
+
 /// This struct represents [`Block`](super::Block) information used by the Ouroboros
 /// Praos consensus protocol.
 #[derive(Debug, Clone, PartialEq, SerialEncodable, SerialDecodable)]
 pub struct OuroborosMetadata {
-    // response of global random oracle, or it's emulation.
+    /// response of global random oracle, or it's emulation.
     pub eta: [u8;32],
+    /// stakeholder lead NIZK lead proof
+    pub lead_proof : TransactionLeadProof,
 }
 
 impl OuroborosMetadata {
-    pub fn new(eta: [u8;32]) -> Self {
-        Self { eta }
+    pub fn new(eta: [u8;32], lead_proof: TransactionLeadProof) -> Self {
+        Self { eta, lead_proof }
     }
 }
 

+ 1 - 1
src/consensus/mod.rs

@@ -4,7 +4,7 @@ pub use block::{Block, BlockInfo, BlockProposal, ProposalChain};
 
 /// Consensus metadata
 pub mod metadata;
-pub use metadata::{Metadata, StreamletMetadata, OuroborosMetadata};
+pub use metadata::{Metadata, StreamletMetadata, OuroborosMetadata, TransactionLeadProof};
 
 /// Consensus participant
 pub mod participant;

+ 3 - 1
src/consensus/state.rs

@@ -12,7 +12,7 @@ use log::{debug, error, info, warn};
 use rand::rngs::OsRng;
 
 use super::{
-    Block, BlockInfo, BlockProposal, Metadata, Participant, ProposalChain, StreamletMetadata, Vote,
+    Block, BlockInfo, BlockProposal, Metadata, Participant, ProposalChain, StreamletMetadata, Vote, TransactionLeadProof,
 };
 use crate::{
     blockchain::Blockchain,
@@ -272,10 +272,12 @@ impl ValidatorState {
         let unproposed_txs = self.unproposed_txs(index);
 
         let eta : [u8;32] = *blake3::hash(b"let there be dark!").as_bytes();
+        let empty_lead_proof = TransactionLeadProof::default();
         let metadata = Metadata::new(
             Timestamp::current_time(),
             // empty seed
             eta,
+            empty_lead_proof,
         );
 
         let sm = StreamletMetadata::new(self.consensus.participants.values().cloned().collect());

+ 16 - 8
src/crypto/lead_proof.rs

@@ -1,7 +1,11 @@
 use std::time::Instant;
 
+
 use halo2_proofs::circuit::Value;
-use log::debug;
+use log::{
+    debug,
+    error
+};
 use pasta_curves::pallas;
 use rand::rngs::OsRng;
 
@@ -12,7 +16,7 @@ use crate::{
         util::mod_r_p,
     },
     zk::circuit::lead_contract::LeadContract,
-    Result,
+    Result, VerifyResult, VerifyFailed,
 };
 
 use rand::{thread_rng, Rng};
@@ -45,17 +49,21 @@ pub fn create_lead_proof(pk: ProvingKey, coin: LeadCoin) -> Result<Proof> {
         root_cm: Value::known(coin.root_cm.unwrap()),
     };
 
-    let start = Instant::now();
+    //let start = Instant::now();
     let public_inputs = coin.public_inputs();
     let proof = Proof::create(&pk, &[contract], &public_inputs, &mut OsRng)?;
-    debug!("Prove lead: [{:?}]", start.elapsed());
+    //debug!("Prove lead: [{:?}]", start.elapsed());
     Ok(proof)
 }
 
-pub fn verify_lead_proof(vk: &VerifyingKey, proof: &Proof, coin: LeadCoin) -> Result<()> {
+pub fn verify_lead_proof(vk: &VerifyingKey, proof: &Proof, coin: LeadCoin) -> VerifyResult<()> {
     let start = Instant::now();
     let public_inputs = coin.public_inputs();
-    proof.verify(vk, &public_inputs)?;
-    debug!("Verify lead: [{:?}]", start.elapsed());
-    Ok(())
+    match proof.verify(vk, &public_inputs) {
+        Ok(()) => {Ok(())},
+        Err(e) => {
+            error!("lead verification failed: {}", e);
+            Err(VerifyFailed::InternalError("lead verification failure".to_string()))
+        }
+    }
 }

+ 6 - 0
src/tx/mod.rs

@@ -1,10 +1,16 @@
 use std::io;
 
+use halo2_proofs::{
+    plonk
+};
+
 use log::error;
 use pasta_curves::group::Group;
 
 use crate::{
     crypto::{
+        leadcoin::LeadCoin,
+        lead_proof,
         burn_proof::verify_burn_proof,
         keypair::PublicKey,
         mint_proof::verify_mint_proof,