Kaynağa Gözat

[WIP/crypsinous simulation] crypsinous simualtion still wip

mohab metwally 4 yıl önce
ebeveyn
işleme
7eee509922

+ 24 - 0
bin/crypsinous/src/main.rs

@@ -0,0 +1,24 @@
+use darkfi::{
+    stakeholder::Stakeholder,
+    blockchain::{EpochConsensus}
+};
+
+fn main()
+{
+    let slots=3;
+    let reward=22;
+    let epoch_consensus = EpochConsensus::new(slots, reward);
+    /// read n from the cmd
+    let n = 3;
+    /// initialize n stakeholders
+    let stakeholders = vec!(n);
+    for i in n {
+        let stakeholder = Stakeholder::new();
+        stakeholders.push(stakeholder);
+    }
+    /// when the clock signal a new slot.
+    /// check for leadership.
+    /// if lead publish construct block metadata.
+    /// push the new block before the end of the slot (clock should siganl the beging, and 1/k of the way to the end).
+    ///TODO stakeholder should signal new epoch, new slot in the background
+}

+ 2 - 2
example/lead.rs

@@ -62,6 +62,7 @@ fn main() {
 
     //TODO (fix) proof panics
     let lead_tx = TransactionLeadProof::new(lead_pk, coin.clone());
+    /*
     //lead_tx.verify(lead_vk, coin);
     let (st_id, st_hash)  = stakeholder.blockchain.last().unwrap();
     let empty_txs : Vec<Transaction> = vec!();
@@ -74,7 +75,6 @@ fn main() {
     // calculate public inputs
     let public_inputs = coin.public_inputs();
     let prover = MockProver::run(k, &contract, vec![public_inputs]).unwrap();
-    //
     assert_eq!(prover.verify(), Ok(()));
-    //
+    */
 }

+ 67 - 10
src/blockchain/epoch.rs

@@ -27,6 +27,30 @@ pub struct EpochItem {
     pub value: u64, // the stake value is static during the epoch.
 }
 
+/// epoch configuration
+/// this struct need be a singleton,
+/// should be populated from configuration file.
+#[derive(Copy,Debug,Default,Clone)]
+pub struct EpochConsensus {
+    pub len : u64, /// number of slots per epoch
+    pub reward: u64,
+}
+
+impl EpochConsensus{
+    fn new(len: u64, reward: u64) {
+        Self {len, reward}
+    }
+
+    /// TODO how is the reward derived?
+    fn get_reward(&self) {
+        self.reward
+    }
+
+    fn get_sl(&self) {
+        self.len
+    }
+}
+
 #[derive(Copy,Debug,Default,Clone)]
 pub struct Epoch {
     // TODO this need to emulate epoch
@@ -36,20 +60,18 @@ pub struct Epoch {
     //epoch item
     pub item: Option<EpochItem>,
     pub eta: pallas::Base, // CRS for the leader selection.
-
-}
-
-#[derive(Debug,Default,Clone)]
-pub struct LifeTime {
-    //lifetime metadata
-    //...
-    //lifetime epochs
-    pub epochs : Vec<Epoch>,
+    pub coins: Vec<LeadCoin>,
 }
 
-
 impl Epoch {
 
+    pub fn new(consensus: EpochConsensus, true_random:pallas::Base)
+    {
+        Self {len: consensus.len,
+              item: EpochItem {consensus.reward},
+              eta: true_random,
+        }
+    }
     fn create_coins_election_seeds(&self, sl: pallas::Base) -> (pallas::Base, pallas::Base) {
         let ELECTION_SEED_NONCE : pallas::Base = pallas::Base::from(3);
         let ELECTION_SEED_LEAD : pallas::Base = pallas::Base::from(22);
@@ -221,6 +243,41 @@ impl Epoch {
             };
             coins.push(coin);
         }
+        self.coins = coins;
         coins
     }
+
+    /// retrive leadership lottary coins of static stake,
+    /// retrived for for commitment in the genesis data
+    pub fn get_coins(&self) -> Vec<LeadCoin> {
+        return self.coins
+    }
+
+    /// see if the participant stakeholder of this epoch is
+    /// winning the lottery, in case of success return True
+    pub fn is_leader(&self, sl: u64) -> bool {
+        let coin = self.coins[i];
+        let y_exp = [
+            coin.root_sk,
+            coin.nonce,
+        ];
+        let y_exp_hash : pallas::Base = PoseidonHash::<_, _, poseidon::P128Pow5T3, poseidon::ContractLength<2>,3,2,>::init(y_exp);
+        let y = pedersen_commitment_scalar(coin.y_mu, y_exp_hash);
+        let ord = 1024; //TODO (res)
+        let target = ord*coin.value;
+        y < target
+    }
+
+    pub fn get_proof(&self, sl: u64) -> Proof {
+        let coin = self.coins[sl];
+        lead_proof::create_lead_proof(pk, coin)
+    }
+}
+
+#[derive(Debug,Default,Clone)]
+pub struct LifeTime {
+    //lifetime metadata
+    //...
+    //lifetime epochs
+    pub epochs : Vec<Epoch>,
 }

+ 2 - 0
src/blockchain/mod.rs

@@ -50,6 +50,8 @@ pub struct Blockchain {
 }
 
 impl Blockchain {
+    //FIXME why the blockchain taking genesis_data on the constructor as a hash?
+    //genesis data are supposed to be a a hash?
     /// Instantiate a new `Blockchain` with the given `sled` database.
     pub fn new(db: &sled::Db, genesis_ts: Timestamp, genesis_data: blake3::Hash) -> Result<Self> {
         let blocks = BlockStore::new(db, genesis_ts, genesis_data)?;

+ 8 - 25
src/crypto/lead_proof.rs

@@ -24,34 +24,17 @@ use rand::{thread_rng, Rng};
 #[allow(clippy::too_many_arguments)]
 pub fn create_lead_proof(pk: ProvingKey, coin: LeadCoin) -> Result<Proof> {
     //
-    let mut rng = thread_rng();
-    let yu64: u64 = rng.gen();
-    let rhou64: u64 = rng.gen();
-    let mau_y: pallas::Base = pallas::Base::from(yu64);
-    let mau_rho: pallas::Base = pallas::Base::from(rhou64);
-    let contract = LeadContract {
-        path: Value::known(coin.path.unwrap()),
-        coin_pk_x: Value::known(coin.pk_x.unwrap()),
-        coin_pk_y: Value::known(coin.pk_y.unwrap()),
-        root_sk: Value::known(coin.root_sk.unwrap()),
-        sf_root_sk: Value::known(mod_r_p(coin.root_sk.unwrap())),
-        path_sk: Value::known(coin.path_sk.unwrap()),
-        coin_timestamp: Value::known(coin.tau.unwrap()),
-        coin_nonce: Value::known(coin.nonce.unwrap()),
-        coin1_blind: Value::known(coin.c1_blind.unwrap()),
-        value: Value::known(coin.value.unwrap()),
-        coin2_blind: Value::known(coin.c2_blind.unwrap()),
-        cm_pos: Value::known(coin.idx),
-        //sn_c1: Value::known(coin.sn.unwrap()),
-        slot: Value::known(coin.sl.unwrap()),
-        mau_rho: Value::known(mod_r_p(mau_rho)),
-        mau_y: Value::known(mod_r_p(mau_y)),
-        root_cm: Value::known(coin.root_cm.unwrap()),
-    };
-
+    //let mut rng = thread_rng();
+    //let yu64: u64 = rng.gen();
+    //let rhou64: u64 = rng.gen();
+    //let mau_y: pallas::Base = pallas::Base::from(yu64);
+    //let mau_rho: pallas::Base = pallas::Base::from(rhou64);
+    let contract = coin.create_contract();
     //let start = Instant::now();
     let public_inputs = coin.public_inputs();
+    println!("creating proof");
     let proof = Proof::create(&pk, &[contract], &public_inputs, &mut OsRng)?;
+    println!("proof created");
     //debug!("Prove lead: [{:?}]", start.elapsed());
     Ok(proof)
 }

+ 2 - 1
src/crypto/proof.rs

@@ -61,7 +61,7 @@ impl Proof {
         mut rng: impl RngCore,
     ) -> std::result::Result<Self, plonk::Error> {
         let mut transcript = Blake2bWrite::<_, vesta::Affine, _>::init(vec![]);
-
+        println!("creating plonk proof");
         plonk::create_proof(
             &pk.params,
             &pk.pk,
@@ -70,6 +70,7 @@ impl Proof {
             &mut rng,
             &mut transcript,
         )?;
+        println!("created plonk proof");
 
         Ok(Proof(transcript.finalize()))
     }

+ 54 - 5
src/stakeholder/stakeholder.rs

@@ -1,10 +1,15 @@
 use crate::{
     consensus::{BlockInfo},
     util::time::Timestamp,
-    blockchain::{Blockchain},
+    blockchain::{Blockchain,Epoch},
     Result,
 };
 
+
+use darkfi::crypto::proof::VerifyingKey;
+use darkfi::crypto::proof::ProvingKey;
+
+
 use pasta_curves::{
     pallas,
 };
@@ -13,28 +18,44 @@ use group::ff::PrimeField;
 
 pub struct Stakeholder
 {
-    pub blockchain: Blockchain // stakeholder view of the blockchain
+    pub blockchain: Blockchain, // stakeholder view of the blockchain
+    pub clock : Clock,
+    pub coins : Vec<LeadCoin>, // owned stakes
+    pub epoch : &Epoch, // current epoch
+    pub epoch_consensus : EpochConsensus, // configuration for the epoch
+    pub pk : ProvingKey,
+    pub vk : VerifyingKey,
 }
 
 impl Stakeholder
 {
-    pub fn new() -> Result<Self>
+    /// initialize new stakeholder with sled in /tmp
+    pub fn new(consensus: EpochConsensus) -> Result<Self>
     {
         //TODO initialize the blockchain
         let path = "/tmp";
         let db = sled::open(path).unwrap();
         let ts = Timestamp::current_time();
-        let genesis_hash = blake3::hash(b"data");
+        let genesis_hash = blake3::hash(b"");
         let bc = Blockchain::new(&db, ts, genesis_hash).unwrap();
-        Ok(Self{blockchain: bc})
+        //TODO replace with const
+        let eta = pallas::base::one();
+        //let epoch = Epoch::new(consensus, eta);
+        let lead_pk = ProvingKey::build(k, &LeadContract::default());
+        let lead_vk = VerifyingKey::build(k, &LeadContract::default());
+        Ok(Self{blockchain: bc, epoch_consensus: consensus, pk:lead_pk, vk:lead_vk})
     }
 
+    /// add new blockinfo to the blockchain
     pub fn add_block(&self, block: BlockInfo)
     {
         let blocks = [block];
         self.blockchain.add(&blocks);
     }
 
+    /// extract leader selection lottery randomness \eta
+    /// it's the hash of the previous lead proof
+    /// converted to pallas base
     pub fn get_eta(&self) -> pallas::Base
     {
         let last_proof_slot : u64 = 0;
@@ -45,4 +66,32 @@ impl Stakeholder
         bytes[31] = 0;
         pallas::Base::from_repr(bytes).unwrap()
     }
+
+    /// on the onset of the epoch, layout the new the competing coins
+    /// assuming static stake during the epoch, enforced by the commitment to competing coins
+    /// in the epoch's gen2esis data.
+    pub fn new_epoch(&self)
+    {
+        let eta = self.get_eta();
+        let epoch = Epoch::new(self.consensus, self.get_eta());
+        let coins : Vec<LeadCoin> = epoch.create_coins();
+        self.epoch = epoch;
+        //TODO initialize blocks in the epoch, and add coin commitment in genesis
+    }
+
+    /// at the begining of the slot
+    /// stakeholder need to play the lottery for the slot.
+    /// FIXME if the stakeholder is not winning, staker can try different coins before,
+    /// commiting it's coins, to maximize success, thus,
+    /// the lottery proof need to be conditioned on the slot itself, and previous proof.
+    /// this will encourage each potential leader to play with honesty.
+    pub fn new_slot(&self) -> Result<bool, Proof>
+    {
+        let sl : u64 = self.clock.slot();
+        let is_leader : bool = self.epoch.is_leader(sl);
+        // if is leader create proof
+        let proof = self.epoch.get_proof(sl, self.pk);
+        //TODO initialize blocks in the epoch, and add proof
+        Ok(is_leader, proof)
+    }
 }

+ 2 - 2
src/zk/circuit/lead_contract.rs

@@ -651,9 +651,9 @@ impl Circuit<pallas::Base> for LeadContract {
 
         //TODO (research) this multiplication panics!
         let y_commit_exp = ar_chip.mul(
-            layouter.namespace(|| ""),
+        layouter.namespace(|| ""),
+        //root_sk.clone(), //(fix)
             &coin_nonce,
-            //root_sk.clone(), //(fix)
             &one,
         )?;