mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-01-10 07:08:05 -05:00
[WIP/crypsinous simulation] crypsinous simualtion still wip
This commit is contained in:
24
bin/crypsinous/src/main.rs
Normal file
24
bin/crypsinous/src/main.rs
Normal file
@@ -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
|
||||
}
|
||||
@@ -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(()));
|
||||
//
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
pub coins: Vec<LeadCoin>,
|
||||
}
|
||||
|
||||
#[derive(Debug,Default,Clone)]
|
||||
pub struct LifeTime {
|
||||
//lifetime metadata
|
||||
//...
|
||||
//lifetime epochs
|
||||
pub epochs : Vec<Epoch>,
|
||||
}
|
||||
|
||||
|
||||
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>,
|
||||
}
|
||||
|
||||
@@ -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)?;
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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()))
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
)?;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user