diff --git a/example/lead.rs b/example/lead.rs index 92a64defd..7268d89b0 100644 --- a/example/lead.rs +++ b/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 = 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(())); diff --git a/src/blockchain/epoch.rs b/src/blockchain/epoch.rs index e6eae4550..388cd290e 100644 --- a/src/blockchain/epoch.rs +++ b/src/blockchain/epoch.rs @@ -86,22 +86,13 @@ 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(); - 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)); + } 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(); - let sk_base = pallas::Base::one(); + let sk_base = coord.x() * coord.y(); prev_sk_base = sk_base; sk_base.to_repr() }; diff --git a/src/blockchain/metadatastore.rs b/src/blockchain/metadatastore.rs index 7b7b72e6d..b8230ad8e 100644 --- a/src/blockchain/metadatastore.rs +++ b/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) diff --git a/src/consensus/block.rs b/src/consensus/block.rs index 427ebdd19..763ff4877 100644 --- a/src/consensus/block.rs +++ b/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) } diff --git a/src/consensus/metadata.rs b/src/consensus/metadata.rs index 8a9e96e63..ad735d3b4 100644 --- a/src/consensus/metadata.rs +++ b/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 } } } diff --git a/src/consensus/mod.rs b/src/consensus/mod.rs index 927ad3a10..aa5c370b0 100644 --- a/src/consensus/mod.rs +++ b/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; diff --git a/src/consensus/state.rs b/src/consensus/state.rs index 5f70873c2..3fa076400 100644 --- a/src/consensus/state.rs +++ b/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()); diff --git a/src/crypto/lead_proof.rs b/src/crypto/lead_proof.rs index 99ebab715..ca64e2dff 100644 --- a/src/crypto/lead_proof.rs +++ b/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 { 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())) + } + } } diff --git a/src/tx/mod.rs b/src/tx/mod.rs index 477920c41..a18b2610f 100644 --- a/src/tx/mod.rs +++ b/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,