|
@@ -13,6 +13,7 @@ use pasta_curves::{
|
|
|
use rand::{thread_rng, Rng};
|
|
use rand::{thread_rng, Rng};
|
|
|
|
|
|
|
|
use crate::crypto::{
|
|
use crate::crypto::{
|
|
|
|
|
+ coin::OwnCoin,
|
|
|
constants::MERKLE_DEPTH_ORCHARD,
|
|
constants::MERKLE_DEPTH_ORCHARD,
|
|
|
lead_proof,
|
|
lead_proof,
|
|
|
leadcoin::LeadCoin,
|
|
leadcoin::LeadCoin,
|
|
@@ -20,7 +21,6 @@ use crate::crypto::{
|
|
|
proof::{Proof, ProvingKey},
|
|
proof::{Proof, ProvingKey},
|
|
|
types::DrkValueBlind,
|
|
types::DrkValueBlind,
|
|
|
util::{mod_r_p, pedersen_commitment_base, pedersen_commitment_u64},
|
|
util::{mod_r_p, pedersen_commitment_base, pedersen_commitment_u64},
|
|
|
- coin::OwnCoin,
|
|
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
const PRF_NULLIFIER_PREFIX: u64 = 0;
|
|
const PRF_NULLIFIER_PREFIX: u64 = 0;
|
|
@@ -79,20 +79,15 @@ impl EpochConsensus {
|
|
|
pub struct Epoch {
|
|
pub struct Epoch {
|
|
|
pub consensus: EpochConsensus,
|
|
pub consensus: EpochConsensus,
|
|
|
// should have ep, slot, current block, etc.
|
|
// should have ep, slot, current block, etc.
|
|
|
- pub eta: pallas::Base, // CRS for the leader selection.
|
|
|
|
|
|
|
+ pub eta: pallas::Base, // CRS for the leader selection.
|
|
|
coins: Vec<Vec<LeadCoin>>, // competing coins
|
|
coins: Vec<Vec<LeadCoin>>, // competing coins
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
impl Epoch {
|
|
impl Epoch {
|
|
|
pub fn new(consensus: EpochConsensus, true_random: pallas::Base) -> Self {
|
|
pub fn new(consensus: EpochConsensus, true_random: pallas::Base) -> Self {
|
|
|
- Self {
|
|
|
|
|
- consensus: consensus,
|
|
|
|
|
- eta: true_random,
|
|
|
|
|
- coins: vec![],
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ Self { consensus, eta: true_random, coins: vec![] }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-
|
|
|
|
|
/// retrive leadership lottary coins of static stake,
|
|
/// retrive leadership lottary coins of static stake,
|
|
|
/// retrived for for commitment in the genesis data
|
|
/// retrived for for commitment in the genesis data
|
|
|
pub fn get_coins(&self) -> Vec<Vec<LeadCoin>> {
|
|
pub fn get_coins(&self) -> Vec<Vec<LeadCoin>> {
|
|
@@ -103,12 +98,12 @@ impl Epoch {
|
|
|
self.coins[sl][idx]
|
|
self.coins[sl][idx]
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- pub fn len(&self) -> usize {
|
|
|
|
|
|
|
+ pub fn len(&self) -> usize {
|
|
|
self.consensus.get_epoch_len() as usize
|
|
self.consensus.get_epoch_len() as usize
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
pub fn col(&self) -> usize {
|
|
pub fn col(&self) -> usize {
|
|
|
- if self.coins.len()==0 {
|
|
|
|
|
|
|
+ if self.coins.len() == 0 {
|
|
|
0
|
|
0
|
|
|
} else {
|
|
} else {
|
|
|
self.coins[0].len()
|
|
self.coins[0].len()
|
|
@@ -116,7 +111,7 @@ impl Epoch {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//
|
|
//
|
|
|
- fn create_coins_election_seeds(&self, sl: pallas::Base) -> (pallas::Base, pallas::Base) {
|
|
|
|
|
|
|
+ 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_nonce: pallas::Base = pallas::Base::from(3);
|
|
|
let election_seed_lead: pallas::Base = pallas::Base::from(22);
|
|
let election_seed_lead: pallas::Base = pallas::Base::from(22);
|
|
|
|
|
|
|
@@ -144,7 +139,7 @@ impl Epoch {
|
|
|
let mut root_sks: Vec<MerkleNode> = vec![];
|
|
let mut root_sks: Vec<MerkleNode> = vec![];
|
|
|
let mut path_sks: Vec<[MerkleNode; MERKLE_DEPTH_ORCHARD]> = vec![];
|
|
let mut path_sks: Vec<[MerkleNode; MERKLE_DEPTH_ORCHARD]> = vec![];
|
|
|
let mut prev_sk_base: pallas::Base = pallas::Base::one();
|
|
let mut prev_sk_base: pallas::Base = pallas::Base::one();
|
|
|
- for _i in 0..self.len(){
|
|
|
|
|
|
|
+ for _i in 0..self.len() {
|
|
|
//TODO (fix) add sk for the coin struct to be used in txs decryption of tx notes.
|
|
//TODO (fix) add sk for the coin struct to be used in txs decryption of tx notes.
|
|
|
let sk_bytes = if _i == 0 {
|
|
let sk_bytes = if _i == 0 {
|
|
|
let base = pedersen_commitment_u64(1, pallas::Scalar::random(&mut rng));
|
|
let base = pedersen_commitment_u64(1, pallas::Scalar::random(&mut rng));
|
|
@@ -175,7 +170,7 @@ impl Epoch {
|
|
|
(root_sks, path_sks)
|
|
(root_sks, path_sks)
|
|
|
}
|
|
}
|
|
|
//note! the strategy here is single competing coin per slot.
|
|
//note! the strategy here is single competing coin per slot.
|
|
|
- pub fn create_coins (&mut self, sigma: pallas::Base, owned : Vec<OwnCoin>) -> Vec<Vec<LeadCoin>> {
|
|
|
|
|
|
|
+ pub fn create_coins(&mut self, sigma: pallas::Base, owned: Vec<OwnCoin>) -> Vec<Vec<LeadCoin>> {
|
|
|
let mut rng = thread_rng();
|
|
let mut rng = thread_rng();
|
|
|
let mut seeds: Vec<u64> = vec![];
|
|
let mut seeds: Vec<u64> = vec![];
|
|
|
for _i in 0..self.len() {
|
|
for _i in 0..self.len() {
|
|
@@ -188,10 +183,17 @@ impl Epoch {
|
|
|
let mut coins: Vec<Vec<LeadCoin>> = vec![];
|
|
let mut coins: Vec<Vec<LeadCoin>> = vec![];
|
|
|
for i in 0..self.len() {
|
|
for i in 0..self.len() {
|
|
|
// if you have any stake used is for competition
|
|
// if you have any stake used is for competition
|
|
|
- if owned.len()>0 {
|
|
|
|
|
|
|
+ if owned.len() > 0 {
|
|
|
let mut slot_coins = vec![];
|
|
let mut slot_coins = vec![];
|
|
|
- for j in 0..owned.len() {
|
|
|
|
|
- let coin = self.create_leadcoin(sigma, owned[j].note.value, i, root_sks[i], path_sks[i], seeds[i]);
|
|
|
|
|
|
|
+ for j in 0..owned.len() {
|
|
|
|
|
+ let coin = self.create_leadcoin(
|
|
|
|
|
+ sigma,
|
|
|
|
|
+ owned[j].note.value,
|
|
|
|
|
+ i,
|
|
|
|
|
+ root_sks[i],
|
|
|
|
|
+ path_sks[i],
|
|
|
|
|
+ seeds[i],
|
|
|
|
|
+ );
|
|
|
slot_coins.push(coin.clone());
|
|
slot_coins.push(coin.clone());
|
|
|
}
|
|
}
|
|
|
self.coins.push(slot_coins);
|
|
self.coins.push(slot_coins);
|
|
@@ -199,18 +201,21 @@ impl Epoch {
|
|
|
// otherwise compete with zero stake
|
|
// otherwise compete with zero stake
|
|
|
else {
|
|
else {
|
|
|
let coin = self.create_leadcoin(sigma, 0, i, root_sks[i], path_sks[i], seeds[i]);
|
|
let coin = self.create_leadcoin(sigma, 0, i, root_sks[i], path_sks[i], seeds[i]);
|
|
|
- self.coins.push(vec!(coin));
|
|
|
|
|
|
|
+ self.coins.push(vec![coin]);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
self.coins.clone()
|
|
self.coins.clone()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- pub fn create_leadcoin(&self, sigma: pallas::Base,
|
|
|
|
|
- value : u64,
|
|
|
|
|
- i: usize,
|
|
|
|
|
- c_root_sk: MerkleNode,
|
|
|
|
|
- c_path_sk: [MerkleNode; MERKLE_DEPTH_ORCHARD],
|
|
|
|
|
- seed: u64) -> LeadCoin {
|
|
|
|
|
|
|
+ pub fn create_leadcoin(
|
|
|
|
|
+ &self,
|
|
|
|
|
+ sigma: pallas::Base,
|
|
|
|
|
+ value: u64,
|
|
|
|
|
+ i: usize,
|
|
|
|
|
+ c_root_sk: MerkleNode,
|
|
|
|
|
+ c_path_sk: [MerkleNode; MERKLE_DEPTH_ORCHARD],
|
|
|
|
|
+ seed: u64,
|
|
|
|
|
+ ) -> LeadCoin {
|
|
|
//random commitment blinding values
|
|
//random commitment blinding values
|
|
|
let mut rng = thread_rng();
|
|
let mut rng = thread_rng();
|
|
|
let c_cm1_blind: DrkValueBlind = pallas::Scalar::random(&mut rng);
|
|
let c_cm1_blind: DrkValueBlind = pallas::Scalar::random(&mut rng);
|
|
@@ -227,19 +232,18 @@ impl Epoch {
|
|
|
let coin_pk_msg = [c_tau, c_root_sk.inner()];
|
|
let coin_pk_msg = [c_tau, c_root_sk.inner()];
|
|
|
let c_pk: pallas::Base =
|
|
let c_pk: pallas::Base =
|
|
|
poseidon::Hash::<_, poseidon::P128Pow5T3, poseidon::ConstantLength<2>, 3, 2>::init()
|
|
poseidon::Hash::<_, poseidon::P128Pow5T3, poseidon::ConstantLength<2>, 3, 2>::init()
|
|
|
- .hash(coin_pk_msg);
|
|
|
|
|
|
|
+ .hash(coin_pk_msg);
|
|
|
|
|
|
|
|
let c_seed = pallas::Base::from(seed);
|
|
let c_seed = pallas::Base::from(seed);
|
|
|
let sn_msg = [c_seed, c_root_sk.inner()];
|
|
let sn_msg = [c_seed, c_root_sk.inner()];
|
|
|
let c_sn: pallas::Base =
|
|
let c_sn: pallas::Base =
|
|
|
poseidon::Hash::<_, poseidon::P128Pow5T3, poseidon::ConstantLength<2>, 3, 2>::init()
|
|
poseidon::Hash::<_, poseidon::P128Pow5T3, poseidon::ConstantLength<2>, 3, 2>::init()
|
|
|
- .hash(sn_msg);
|
|
|
|
|
|
|
+ .hash(sn_msg);
|
|
|
|
|
|
|
|
- let coin_commit_msg_input =
|
|
|
|
|
- [pallas::Base::from(PRF_NULLIFIER_PREFIX), c_pk, c_v, c_seed];
|
|
|
|
|
|
|
+ let coin_commit_msg_input = [pallas::Base::from(PRF_NULLIFIER_PREFIX), c_pk, c_v, c_seed];
|
|
|
let coin_commit_msg: pallas::Base =
|
|
let coin_commit_msg: pallas::Base =
|
|
|
poseidon::Hash::<_, poseidon::P128Pow5T3, poseidon::ConstantLength<4>, 3, 2>::init()
|
|
poseidon::Hash::<_, poseidon::P128Pow5T3, poseidon::ConstantLength<4>, 3, 2>::init()
|
|
|
- .hash(coin_commit_msg_input);
|
|
|
|
|
|
|
+ .hash(coin_commit_msg_input);
|
|
|
let c_cm: pallas::Point = pedersen_commitment_base(coin_commit_msg, c_cm1_blind);
|
|
let c_cm: pallas::Point = pedersen_commitment_base(coin_commit_msg, c_cm1_blind);
|
|
|
let c_cm_coordinates = c_cm.to_affine().coordinates().unwrap();
|
|
let c_cm_coordinates = c_cm.to_affine().coordinates().unwrap();
|
|
|
let c_cm_base: pallas::Base = c_cm_coordinates.x() * c_cm_coordinates.y();
|
|
let c_cm_base: pallas::Base = c_cm_coordinates.x() * c_cm_coordinates.y();
|
|
@@ -247,21 +251,17 @@ impl Epoch {
|
|
|
tree_cm.append(&c_cm_node.clone());
|
|
tree_cm.append(&c_cm_node.clone());
|
|
|
let leaf_position = tree_cm.witness();
|
|
let leaf_position = tree_cm.witness();
|
|
|
let c_root_cm = tree_cm.root(0).unwrap();
|
|
let c_root_cm = tree_cm.root(0).unwrap();
|
|
|
- let c_cm_path =
|
|
|
|
|
- tree_cm.authentication_path(leaf_position.unwrap(), &c_root_cm).unwrap();
|
|
|
|
|
|
|
+ let c_cm_path = tree_cm.authentication_path(leaf_position.unwrap(), &c_root_cm).unwrap();
|
|
|
|
|
|
|
|
let coin_nonce2_msg = [c_seed, c_root_sk.inner()];
|
|
let coin_nonce2_msg = [c_seed, c_root_sk.inner()];
|
|
|
let c_seed2: pallas::Base =
|
|
let c_seed2: pallas::Base =
|
|
|
- poseidon::Hash::<_, poseidon::P128Pow5T3, poseidon::ConstantLength<2>, 3, 2>::init(
|
|
|
|
|
- )
|
|
|
|
|
- .hash(coin_nonce2_msg);
|
|
|
|
|
|
|
+ poseidon::Hash::<_, poseidon::P128Pow5T3, poseidon::ConstantLength<2>, 3, 2>::init()
|
|
|
|
|
+ .hash(coin_nonce2_msg);
|
|
|
|
|
|
|
|
- let coin2_commit_msg_input =
|
|
|
|
|
- [pallas::Base::from(PRF_NULLIFIER_PREFIX), c_pk, c_v, c_seed2];
|
|
|
|
|
|
|
+ let coin2_commit_msg_input = [pallas::Base::from(PRF_NULLIFIER_PREFIX), c_pk, c_v, c_seed2];
|
|
|
let coin2_commit_msg: pallas::Base =
|
|
let coin2_commit_msg: pallas::Base =
|
|
|
- poseidon::Hash::<_, poseidon::P128Pow5T3, poseidon::ConstantLength<4>, 3, 2>::init(
|
|
|
|
|
- )
|
|
|
|
|
- .hash(coin2_commit_msg_input);
|
|
|
|
|
|
|
+ poseidon::Hash::<_, poseidon::P128Pow5T3, poseidon::ConstantLength<4>, 3, 2>::init()
|
|
|
|
|
+ .hash(coin2_commit_msg_input);
|
|
|
let c_cm2 = pedersen_commitment_base(coin2_commit_msg, c_cm2_blind);
|
|
let c_cm2 = pedersen_commitment_base(coin2_commit_msg, c_cm2_blind);
|
|
|
|
|
|
|
|
// election seeds
|
|
// election seeds
|
|
@@ -297,30 +297,32 @@ impl Epoch {
|
|
|
/// * `sl` - slot relative index
|
|
/// * `sl` - slot relative index
|
|
|
/// * `idx` - index of the winning coin
|
|
/// * `idx` - index of the winning coin
|
|
|
/// returns true if the stakeholder is a leader for the current slot, else otherwise
|
|
/// returns true if the stakeholder is a leader for the current slot, else otherwise
|
|
|
- pub fn is_leader(&self, sl: u64, idx: &mut usize) -> bool {
|
|
|
|
|
|
|
+ pub fn is_leader(&self, sl: u64, idx: &mut usize) -> bool {
|
|
|
let slusize = sl as usize;
|
|
let slusize = sl as usize;
|
|
|
debug!("slot: {}, coin len: {}", sl, self.coins.len());
|
|
debug!("slot: {}, coin len: {}", sl, self.coins.len());
|
|
|
assert!(slusize < self.coins.len());
|
|
assert!(slusize < self.coins.len());
|
|
|
- let competing_coins : &Vec<LeadCoin>= &self.coins.clone()[sl as usize];
|
|
|
|
|
|
|
+ let competing_coins: &Vec<LeadCoin> = &self.coins.clone()[sl as usize];
|
|
|
let mut am_leader = vec![];
|
|
let mut am_leader = vec![];
|
|
|
let mut highest_stake = 0;
|
|
let mut highest_stake = 0;
|
|
|
- let mut highest_stake_idx : usize= 0;
|
|
|
|
|
|
|
+ let mut highest_stake_idx: usize = 0;
|
|
|
for (winning_idx, coin) in competing_coins.iter().enumerate() {
|
|
for (winning_idx, coin) in competing_coins.iter().enumerate() {
|
|
|
let y_exp = [coin.root_sk.unwrap(), coin.nonce.unwrap()];
|
|
let y_exp = [coin.root_sk.unwrap(), coin.nonce.unwrap()];
|
|
|
let y_exp_hash: pallas::Base =
|
|
let y_exp_hash: pallas::Base =
|
|
|
- poseidon::Hash::<_, poseidon::P128Pow5T3, poseidon::ConstantLength<2>, 3, 2>::init()
|
|
|
|
|
|
|
+ poseidon::Hash::<_, poseidon::P128Pow5T3, poseidon::ConstantLength<2>, 3, 2>::init(
|
|
|
|
|
+ )
|
|
|
.hash(y_exp);
|
|
.hash(y_exp);
|
|
|
// pick x coordinate of y for comparison
|
|
// pick x coordinate of y for comparison
|
|
|
- let y_x: pallas::Base = *pedersen_commitment_base(coin.y_mu.unwrap(), mod_r_p(y_exp_hash))
|
|
|
|
|
- .to_affine()
|
|
|
|
|
- .coordinates()
|
|
|
|
|
- .unwrap()
|
|
|
|
|
- .x();
|
|
|
|
|
|
|
+ let y_x: pallas::Base =
|
|
|
|
|
+ *pedersen_commitment_base(coin.y_mu.unwrap(), mod_r_p(y_exp_hash))
|
|
|
|
|
+ .to_affine()
|
|
|
|
|
+ .coordinates()
|
|
|
|
|
+ .unwrap()
|
|
|
|
|
+ .x();
|
|
|
let ord = pallas::Base::from(10241024); //TODO fine tune this scalar.
|
|
let ord = pallas::Base::from(10241024); //TODO fine tune this scalar.
|
|
|
let target = ord * pallas::Base::from(coin.value.unwrap());
|
|
let target = ord * pallas::Base::from(coin.value.unwrap());
|
|
|
debug!("y_x: {:?}, target: {:?}", y_x, target);
|
|
debug!("y_x: {:?}, target: {:?}", y_x, target);
|
|
|
//TODO (FIX) reversed for testin
|
|
//TODO (FIX) reversed for testin
|
|
|
- let iam_leader = target < y_x;
|
|
|
|
|
|
|
+ let iam_leader = target < y_x;
|
|
|
if iam_leader && coin.value.unwrap() > highest_stake {
|
|
if iam_leader && coin.value.unwrap() > highest_stake {
|
|
|
highest_stake = coin.value.unwrap();
|
|
highest_stake = coin.value.unwrap();
|
|
|
highest_stake_idx = winning_idx;
|
|
highest_stake_idx = winning_idx;
|
|
@@ -336,8 +338,8 @@ impl Epoch {
|
|
|
/// * `pk` - proving key
|
|
/// * `pk` - proving key
|
|
|
/// returns the of proof of the winning coin of slot `sl` at index `idx` with
|
|
/// returns the of proof of the winning coin of slot `sl` at index `idx` with
|
|
|
/// proving key `pk`
|
|
/// proving key `pk`
|
|
|
- pub fn get_proof(&self, sl: u64, idx : usize, pk: &ProvingKey) -> Proof {
|
|
|
|
|
- let competing_coins : &Vec<LeadCoin> = &self.coins.clone()[sl as usize];
|
|
|
|
|
|
|
+ pub fn get_proof(&self, sl: u64, idx: usize, pk: &ProvingKey) -> Proof {
|
|
|
|
|
+ let competing_coins: &Vec<LeadCoin> = &self.coins.clone()[sl as usize];
|
|
|
let coin = competing_coins[idx];
|
|
let coin = competing_coins[idx];
|
|
|
lead_proof::create_lead_proof(pk, coin).unwrap()
|
|
lead_proof::create_lead_proof(pk, coin).unwrap()
|
|
|
}
|
|
}
|