Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ffe9084566 |
Generated
+932
-757
File diff suppressed because it is too large
Load Diff
@@ -14,7 +14,6 @@ use cosmwasm_std::Decimal;
|
|||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use cosmwasm_std::Addr;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
|
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
@@ -511,5 +510,4 @@ pub enum QueryMsg {
|
|||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub struct MigrateMsg {
|
pub struct MigrateMsg {
|
||||||
pub vesting_contract_address: Option<String>,
|
pub vesting_contract_address: Option<String>,
|
||||||
pub gateway_address: Addr,
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,17 +7,18 @@ use std::borrow::Borrow;
|
|||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
|
||||||
use bls12_381::{G1Projective, G2Projective, Scalar};
|
use bls12_381::{G1Projective, G2Projective, Scalar};
|
||||||
use digest::generic_array::typenum::Unsigned;
|
|
||||||
use digest::Digest;
|
use digest::Digest;
|
||||||
|
use digest::generic_array::typenum::Unsigned;
|
||||||
use group::GroupEncoding;
|
use group::GroupEncoding;
|
||||||
use itertools::izip;
|
use itertools::izip;
|
||||||
use sha2::Sha256;
|
use sha2::Sha256;
|
||||||
|
|
||||||
|
use crate::Attribute;
|
||||||
use crate::error::{CoconutError, Result};
|
use crate::error::{CoconutError, Result};
|
||||||
|
use crate::scheme::issuance::compute_commitment_hash;
|
||||||
use crate::scheme::setup::Parameters;
|
use crate::scheme::setup::Parameters;
|
||||||
use crate::scheme::VerificationKey;
|
use crate::scheme::VerificationKey;
|
||||||
use crate::utils::{hash_g1, try_deserialize_scalar, try_deserialize_scalar_vec};
|
use crate::utils::{hash_g1, try_deserialize_scalar, try_deserialize_scalar_vec};
|
||||||
use crate::Attribute;
|
|
||||||
|
|
||||||
// as per the reference python implementation
|
// as per the reference python implementation
|
||||||
type ChallengeDigest = Sha256;
|
type ChallengeDigest = Sha256;
|
||||||
@@ -38,10 +39,10 @@ pub struct ProofCmCs {
|
|||||||
// and as per the bls12-381 library all elements are using big-endian form
|
// and as per the bls12-381 library all elements are using big-endian form
|
||||||
/// Generates a Scalar [or Fp] challenge by hashing a number of elliptic curve points.
|
/// Generates a Scalar [or Fp] challenge by hashing a number of elliptic curve points.
|
||||||
fn compute_challenge<D, I, B>(iter: I) -> Scalar
|
fn compute_challenge<D, I, B>(iter: I) -> Scalar
|
||||||
where
|
where
|
||||||
D: Digest,
|
D: Digest,
|
||||||
I: Iterator<Item = B>,
|
I: Iterator<Item=B>,
|
||||||
B: AsRef<[u8]>,
|
B: AsRef<[u8]>,
|
||||||
{
|
{
|
||||||
let mut h = D::new();
|
let mut h = D::new();
|
||||||
for point_representation in iter {
|
for point_representation in iter {
|
||||||
@@ -69,8 +70,8 @@ fn produce_response(witness: &Scalar, challenge: &Scalar, secret: &Scalar) -> Sc
|
|||||||
|
|
||||||
// note: it's caller's responsibility to ensure witnesses.len() = secrets.len()
|
// note: it's caller's responsibility to ensure witnesses.len() = secrets.len()
|
||||||
fn produce_responses<S>(witnesses: &[Scalar], challenge: &Scalar, secrets: &[S]) -> Vec<Scalar>
|
fn produce_responses<S>(witnesses: &[Scalar], challenge: &Scalar, secrets: &[S]) -> Vec<Scalar>
|
||||||
where
|
where
|
||||||
S: Borrow<Scalar>,
|
S: Borrow<Scalar>,
|
||||||
{
|
{
|
||||||
debug_assert_eq!(witnesses.len(), secrets.len());
|
debug_assert_eq!(witnesses.len(), secrets.len());
|
||||||
|
|
||||||
@@ -91,6 +92,7 @@ impl ProofCmCs {
|
|||||||
commitments: &[G1Projective],
|
commitments: &[G1Projective],
|
||||||
pedersen_commitments_openings: &[Scalar],
|
pedersen_commitments_openings: &[Scalar],
|
||||||
private_attributes: &[Attribute],
|
private_attributes: &[Attribute],
|
||||||
|
public_attributes: &[Attribute],
|
||||||
) -> Self {
|
) -> Self {
|
||||||
// note: this is only called from `prepare_blind_sign` that already checks
|
// note: this is only called from `prepare_blind_sign` that already checks
|
||||||
// whether private attributes are non-empty and whether we don't have too many
|
// whether private attributes are non-empty and whether we don't have too many
|
||||||
@@ -104,7 +106,7 @@ impl ProofCmCs {
|
|||||||
let witness_attributes = params.n_random_scalars(private_attributes.len());
|
let witness_attributes = params.n_random_scalars(private_attributes.len());
|
||||||
|
|
||||||
// recompute h
|
// recompute h
|
||||||
let h = hash_g1(commitment.to_bytes());
|
let h = compute_commitment_hash(*commitment, public_attributes);
|
||||||
let hs_bytes = params
|
let hs_bytes = params
|
||||||
.gen_hs()
|
.gen_hs()
|
||||||
.iter()
|
.iter()
|
||||||
@@ -119,10 +121,10 @@ impl ProofCmCs {
|
|||||||
// Ccm = (wr * g1) + (wm[0] * hs[0]) + ... + (wm[i] * hs[i])
|
// Ccm = (wr * g1) + (wm[0] * hs[0]) + ... + (wm[i] * hs[i])
|
||||||
let commitment_attributes = g1 * witness_commitment_opening
|
let commitment_attributes = g1 * witness_commitment_opening
|
||||||
+ witness_attributes
|
+ witness_attributes
|
||||||
.iter()
|
.iter()
|
||||||
.zip(params.gen_hs().iter())
|
.zip(params.gen_hs().iter())
|
||||||
.map(|(wm_i, hs_i)| hs_i * wm_i)
|
.map(|(wm_i, hs_i)| hs_i * wm_i)
|
||||||
.sum::<G1Projective>();
|
.sum::<G1Projective>();
|
||||||
|
|
||||||
// zkp commitments for the individual attributes
|
// zkp commitments for the individual attributes
|
||||||
let commitments_attributes = witness_pedersen_commitments_openings
|
let commitments_attributes = witness_pedersen_commitments_openings
|
||||||
@@ -186,7 +188,7 @@ impl ProofCmCs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// recompute h
|
// recompute h
|
||||||
let h = hash_g1(commitment.to_bytes());
|
let h = compute_commitment_hash(*commitment, public_attributes);
|
||||||
let g1 = params.gen1();
|
let g1 = params.gen1();
|
||||||
|
|
||||||
let hs_bytes = params
|
let hs_bytes = params
|
||||||
@@ -199,26 +201,26 @@ impl ProofCmCs {
|
|||||||
// Cw = (cm * c) + (rr * g1) + (rm[0] * hs[0]) + ... + (rm[n] * hs[n])
|
// Cw = (cm * c) + (rr * g1) + (rm[0] * hs[0]) + ... + (rm[n] * hs[n])
|
||||||
let commitment_attributes = (commitment
|
let commitment_attributes = (commitment
|
||||||
- public_attributes
|
- public_attributes
|
||||||
.iter()
|
.iter()
|
||||||
.zip(params.gen_hs().iter().skip(self.response_attributes.len()))
|
.zip(params.gen_hs().iter().skip(self.response_attributes.len()))
|
||||||
.map(|(pub_attr, hs)| hs * pub_attr)
|
.map(|(pub_attr, hs)| hs * pub_attr)
|
||||||
.sum::<G1Projective>())
|
.sum::<G1Projective>())
|
||||||
* self.challenge
|
* self.challenge
|
||||||
+ g1 * self.response_opening
|
+ g1 * self.response_opening
|
||||||
+ self
|
+ self
|
||||||
.response_attributes
|
.response_attributes
|
||||||
.iter()
|
.iter()
|
||||||
.zip(params.gen_hs().iter())
|
.zip(params.gen_hs().iter())
|
||||||
.map(|(res_attr, hs)| hs * res_attr)
|
.map(|(res_attr, hs)| hs * res_attr)
|
||||||
.sum::<G1Projective>();
|
.sum::<G1Projective>();
|
||||||
|
|
||||||
let commitments_attributes = izip!(
|
let commitments_attributes = izip!(
|
||||||
commitments.iter(),
|
commitments.iter(),
|
||||||
self.response_openings.iter(),
|
self.response_openings.iter(),
|
||||||
self.response_attributes.iter()
|
self.response_attributes.iter()
|
||||||
)
|
)
|
||||||
.map(|(cm_j, r_o_j, r_m_j)| cm_j * self.challenge + g1 * r_o_j + h * r_m_j)
|
.map(|(cm_j, r_o_j, r_m_j)| cm_j * self.challenge + g1 * r_o_j + h * r_m_j)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let commitments_bytes = commitments
|
let commitments_bytes = commitments
|
||||||
.iter()
|
.iter()
|
||||||
@@ -365,10 +367,10 @@ impl ProofKappaZeta {
|
|||||||
let commitment_kappa = params.gen2() * witness_blinder
|
let commitment_kappa = params.gen2() * witness_blinder
|
||||||
+ verification_key.alpha
|
+ verification_key.alpha
|
||||||
+ witness_attributes
|
+ witness_attributes
|
||||||
.iter()
|
.iter()
|
||||||
.zip(verification_key.beta_g2.iter())
|
.zip(verification_key.beta_g2.iter())
|
||||||
.map(|(wm_i, beta_i)| beta_i * wm_i)
|
.map(|(wm_i, beta_i)| beta_i * wm_i)
|
||||||
.sum::<G2Projective>();
|
.sum::<G2Projective>();
|
||||||
|
|
||||||
// zeta is the public value associated with the serial number
|
// zeta is the public value associated with the serial number
|
||||||
let commitment_zeta = params.gen2() * witness_serial_number;
|
let commitment_zeta = params.gen2() * witness_serial_number;
|
||||||
@@ -422,10 +424,10 @@ impl ProofKappaZeta {
|
|||||||
+ params.gen2() * self.response_blinder
|
+ params.gen2() * self.response_blinder
|
||||||
+ verification_key.alpha * (Scalar::one() - self.challenge)
|
+ verification_key.alpha * (Scalar::one() - self.challenge)
|
||||||
+ response_attributes
|
+ response_attributes
|
||||||
.iter()
|
.iter()
|
||||||
.zip(verification_key.beta_g2.iter())
|
.zip(verification_key.beta_g2.iter())
|
||||||
.map(|(priv_attr, beta_i)| beta_i * priv_attr)
|
.map(|(priv_attr, beta_i)| beta_i * priv_attr)
|
||||||
.sum::<G2Projective>();
|
.sum::<G2Projective>();
|
||||||
|
|
||||||
// zeta is the public value associated with the serial number
|
// zeta is the public value associated with the serial number
|
||||||
let commitment_zeta = zeta * self.challenge + params.gen2() * self.response_serial_number;
|
let commitment_zeta = zeta * self.challenge + params.gen2() * self.response_serial_number;
|
||||||
@@ -529,9 +531,18 @@ mod tests {
|
|||||||
let cms: [G1Projective; 1] = [G1Projective::random(&mut rng)];
|
let cms: [G1Projective; 1] = [G1Projective::random(&mut rng)];
|
||||||
let rs = params.n_random_scalars(1);
|
let rs = params.n_random_scalars(1);
|
||||||
let private_attributes = params.n_random_scalars(1);
|
let private_attributes = params.n_random_scalars(1);
|
||||||
|
let public_attributes = params.n_random_scalars(1);
|
||||||
|
|
||||||
// 0 public 1 private
|
// 0 public 1 private
|
||||||
let pi_s = ProofCmCs::construct(¶ms, &cm, &r, &cms, &rs, &private_attributes);
|
let pi_s = ProofCmCs::construct(
|
||||||
|
¶ms,
|
||||||
|
&cm,
|
||||||
|
&r,
|
||||||
|
&cms,
|
||||||
|
&rs,
|
||||||
|
&private_attributes,
|
||||||
|
&public_attributes,
|
||||||
|
);
|
||||||
|
|
||||||
let bytes = pi_s.to_bytes();
|
let bytes = pi_s.to_bytes();
|
||||||
assert_eq!(ProofCmCs::from_bytes(&bytes).unwrap(), pi_s);
|
assert_eq!(ProofCmCs::from_bytes(&bytes).unwrap(), pi_s);
|
||||||
@@ -547,7 +558,15 @@ mod tests {
|
|||||||
let private_attributes = params.n_random_scalars(2);
|
let private_attributes = params.n_random_scalars(2);
|
||||||
|
|
||||||
// 0 public 2 privates
|
// 0 public 2 privates
|
||||||
let pi_s = ProofCmCs::construct(¶ms, &cm, &r, &cms, &rs, &private_attributes);
|
let pi_s = ProofCmCs::construct(
|
||||||
|
¶ms,
|
||||||
|
&cm,
|
||||||
|
&r,
|
||||||
|
&cms,
|
||||||
|
&rs,
|
||||||
|
&private_attributes,
|
||||||
|
&public_attributes,
|
||||||
|
);
|
||||||
|
|
||||||
let bytes = pi_s.to_bytes();
|
let bytes = pi_s.to_bytes();
|
||||||
assert_eq!(ProofCmCs::from_bytes(&bytes).unwrap(), pi_s);
|
assert_eq!(ProofCmCs::from_bytes(&bytes).unwrap(), pi_s);
|
||||||
|
|||||||
@@ -201,8 +201,16 @@ pub fn compute_pedersen_commitments_for_private_attributes(
|
|||||||
(commitments_openings, pedersen_commitments)
|
(commitments_openings, pedersen_commitments)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compute_commitment_hash(commitment: G1Projective) -> G1Projective {
|
pub fn compute_commitment_hash(
|
||||||
hash_g1(commitment.to_bytes())
|
commitment: G1Projective,
|
||||||
|
public_attributes: &[Attribute],
|
||||||
|
) -> G1Projective {
|
||||||
|
let mut msg_bytes = Vec::with_capacity(public_attributes.len() * 32);
|
||||||
|
msg_bytes.extend_from_slice(&commitment.to_affine().to_compressed());
|
||||||
|
for attr in public_attributes {
|
||||||
|
msg_bytes.extend_from_slice(&attr.to_bytes());
|
||||||
|
}
|
||||||
|
hash_g1(msg_bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds cryptographic material required for blind sign.
|
/// Builds cryptographic material required for blind sign.
|
||||||
@@ -230,7 +238,7 @@ pub fn prepare_blind_sign(
|
|||||||
compute_attributes_commitment(params, private_attributes, public_attributes, hs);
|
compute_attributes_commitment(params, private_attributes, public_attributes, hs);
|
||||||
|
|
||||||
// Compute the challenge as the commitment hash
|
// Compute the challenge as the commitment hash
|
||||||
let commitment_hash = compute_commitment_hash(commitment);
|
let commitment_hash = compute_commitment_hash(commitment, public_attributes);
|
||||||
|
|
||||||
let (pedersen_commitments_openings, pedersen_commitments) =
|
let (pedersen_commitments_openings, pedersen_commitments) =
|
||||||
compute_pedersen_commitments_for_private_attributes(
|
compute_pedersen_commitments_for_private_attributes(
|
||||||
@@ -246,6 +254,7 @@ pub fn prepare_blind_sign(
|
|||||||
&pedersen_commitments,
|
&pedersen_commitments,
|
||||||
&pedersen_commitments_openings,
|
&pedersen_commitments_openings,
|
||||||
private_attributes,
|
private_attributes,
|
||||||
|
public_attributes,
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
@@ -276,7 +285,7 @@ pub fn blind_sign(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Verify the commitment hash
|
// Verify the commitment hash
|
||||||
let h = hash_g1(blind_sign_request.commitment.to_bytes());
|
let h = compute_commitment_hash(blind_sign_request.commitment, public_attributes);
|
||||||
if !(h == blind_sign_request.commitment_hash) {
|
if !(h == blind_sign_request.commitment_hash) {
|
||||||
return Err(CoconutError::Issuance(
|
return Err(CoconutError::Issuance(
|
||||||
"Failed to verify the commitment hash".to_string(),
|
"Failed to verify the commitment hash".to_string(),
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ use mixnet_contract_common::error::MixnetContractError;
|
|||||||
use mixnet_contract_common::{
|
use mixnet_contract_common::{
|
||||||
ContractState, ContractStateParams, ExecuteMsg, InstantiateMsg, Interval, MigrateMsg, QueryMsg,
|
ContractState, ContractStateParams, ExecuteMsg, InstantiateMsg, Interval, MigrateMsg, QueryMsg,
|
||||||
};
|
};
|
||||||
use crate::gateways::storage;
|
|
||||||
|
|
||||||
fn default_initial_state(
|
fn default_initial_state(
|
||||||
owner: Addr,
|
owner: Addr,
|
||||||
@@ -569,17 +568,6 @@ pub fn migrate(
|
|||||||
mixnet_params_storage::CONTRACT_STATE.save(deps.storage, ¤t_state)?;
|
mixnet_params_storage::CONTRACT_STATE.save(deps.storage, ¤t_state)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let gateway_bond = match storage::gateways()
|
|
||||||
.idx
|
|
||||||
.owner
|
|
||||||
.item(deps.storage, msg.gateway_address.clone())?
|
|
||||||
{
|
|
||||||
Some(record) => record.1,
|
|
||||||
None => return Err(MixnetContractError::NoAssociatedGatewayBond { owner: msg.gateway_address.clone() }),
|
|
||||||
};
|
|
||||||
|
|
||||||
storage::gateways().remove(deps.storage, gateway_bond.identity())?;
|
|
||||||
|
|
||||||
Ok(Default::default())
|
Ok(Default::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,16 @@ pub struct RewardedSetUpdater {
|
|||||||
storage: NymApiStorage,
|
storage: NymApiStorage,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Weight of a layer being chose is reciprocal to current count in layer
|
||||||
|
fn layer_weight(l: &Layer, layer_assignments: &HashMap<Layer, f32>) -> f32 {
|
||||||
|
let total = layer_assignments.values().fold(0., |acc, i| acc + i);
|
||||||
|
if total == 0. {
|
||||||
|
1.
|
||||||
|
} else {
|
||||||
|
1. - (layer_assignments.get(l).unwrap_or(&0.) / total)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl RewardedSetUpdater {
|
impl RewardedSetUpdater {
|
||||||
pub(crate) async fn current_interval_details(
|
pub(crate) async fn current_interval_details(
|
||||||
&self,
|
&self,
|
||||||
@@ -78,13 +88,15 @@ impl RewardedSetUpdater {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Needs to run for active and reserve sets separatley, as it does not preserve order
|
|
||||||
async fn determine_layers(
|
async fn determine_layers(
|
||||||
&self,
|
&self,
|
||||||
set: &[MixNodeDetails],
|
rewarded_set: &[MixNodeDetails],
|
||||||
) -> Result<Vec<LayerAssignment>, RewardingError> {
|
) -> Result<(Vec<LayerAssignment>, HashMap<String, Layer>), RewardingError> {
|
||||||
let mut assignments = Vec::with_capacity(set.len());
|
let mut families_in_layer: HashMap<String, Layer> = HashMap::new();
|
||||||
let target_layer_count = set.len() / 3;
|
let mut assignments = vec![];
|
||||||
|
let mut layer_assignments: HashMap<Layer, f32> = HashMap::new();
|
||||||
|
let mut rng = OsRng;
|
||||||
|
let layers = vec![Layer::One, Layer::Two, Layer::Three];
|
||||||
|
|
||||||
let mix_to_family = self.validator_cache.mix_to_family().await.to_vec();
|
let mix_to_family = self.validator_cache.mix_to_family().await.to_vec();
|
||||||
|
|
||||||
@@ -92,60 +104,31 @@ impl RewardedSetUpdater {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.collect::<HashMap<IdentityKey, FamilyHead>>();
|
.collect::<HashMap<IdentityKey, FamilyHead>>();
|
||||||
|
|
||||||
let mut regular_nodes = Vec::with_capacity(set.len());
|
for mix in rewarded_set {
|
||||||
|
let family = mix_to_family.get(&mix.bond_information.identity().to_owned());
|
||||||
|
// Get layer already assigned to nodes family, if any
|
||||||
|
let family_layer = family.and_then(|h| families_in_layer.get(h.identity()));
|
||||||
|
|
||||||
let mut families = HashMap::new();
|
// Same node families are always assigned to the same layer, otherwise layer selected by a random weighted choice
|
||||||
|
let layer = if let Some(layer) = family_layer {
|
||||||
for node in set.iter() {
|
layer.to_owned()
|
||||||
if let Some(fh) = mix_to_family.get(node.bond_information.identity()) {
|
|
||||||
let family: &mut Vec<u32> = families.entry(fh.identity()).or_default();
|
|
||||||
family.push(node.mix_id())
|
|
||||||
} else {
|
} else {
|
||||||
regular_nodes.push(node.mix_id())
|
layers
|
||||||
|
.choose_weighted(&mut rng, |l| layer_weight(l, &layer_assignments))?
|
||||||
|
.to_owned()
|
||||||
|
};
|
||||||
|
|
||||||
|
assignments.push(LayerAssignment::new(mix.mix_id(), layer));
|
||||||
|
|
||||||
|
// layer accounting
|
||||||
|
let layer_entry = layer_assignments.entry(layer).or_insert(0.);
|
||||||
|
*layer_entry += 1.;
|
||||||
|
if let Some(family) = family {
|
||||||
|
families_in_layer.insert(family.identity().to_string(), layer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut layers = HashMap::new();
|
Ok((assignments, families_in_layer))
|
||||||
layers.insert(Layer::One, Vec::with_capacity(target_layer_count));
|
|
||||||
layers.insert(Layer::Two, Vec::with_capacity(target_layer_count));
|
|
||||||
layers.insert(Layer::Three, Vec::with_capacity(target_layer_count));
|
|
||||||
|
|
||||||
// Assign all members of a family to same layer
|
|
||||||
for (_head, members) in families.iter_mut() {
|
|
||||||
let smallest_layer = layers
|
|
||||||
.iter()
|
|
||||||
.min_by_key(|(_layer, members)| members.len())
|
|
||||||
.map(|(layer, _members)| *layer)
|
|
||||||
.unwrap_or(Layer::One);
|
|
||||||
|
|
||||||
let entry = layers.entry(smallest_layer).or_default();
|
|
||||||
if entry.len() + members.len() <= target_layer_count {
|
|
||||||
entry.extend_from_slice(members)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assign nodes with no families into layers
|
|
||||||
for mix_id in regular_nodes.drain(..) {
|
|
||||||
let smallest_layer = layers
|
|
||||||
.iter()
|
|
||||||
.min_by_key(|(_layer, members)| members.len())
|
|
||||||
.map(|(layer, _members)| *layer)
|
|
||||||
.unwrap_or(Layer::One);
|
|
||||||
|
|
||||||
let entry = layers.entry(smallest_layer).or_default();
|
|
||||||
if entry.len() < target_layer_count {
|
|
||||||
entry.push(mix_id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (layer, members) in layers {
|
|
||||||
let layer_assignments = members
|
|
||||||
.into_iter()
|
|
||||||
.map(|mix_id| LayerAssignment::new(mix_id, layer));
|
|
||||||
assignments.extend(layer_assignments);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(assignments)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn determine_rewarded_set(
|
fn determine_rewarded_set(
|
||||||
@@ -265,19 +248,11 @@ impl RewardedSetUpdater {
|
|||||||
let new_rewarded_set =
|
let new_rewarded_set =
|
||||||
self.determine_rewarded_set(all_mixnodes, rewarding_parameters.rewarded_set_size)?;
|
self.determine_rewarded_set(all_mixnodes, rewarding_parameters.rewarded_set_size)?;
|
||||||
|
|
||||||
let (active_set, reserve_set) =
|
let (layer_assignments, _families_in_layer) =
|
||||||
new_rewarded_set.split_at(rewarding_parameters.active_set_size as usize);
|
self.determine_layers(&new_rewarded_set).await?;
|
||||||
|
|
||||||
let mut active_set_layer_assignments = self.determine_layers(active_set).await?;
|
|
||||||
let reserve_set_layer_assignments = self.determine_layers(reserve_set).await?;
|
|
||||||
|
|
||||||
active_set_layer_assignments.extend(reserve_set_layer_assignments);
|
|
||||||
|
|
||||||
self.nyxd_client
|
self.nyxd_client
|
||||||
.advance_current_epoch(
|
.advance_current_epoch(layer_assignments, rewarding_parameters.active_set_size)
|
||||||
active_set_layer_assignments,
|
|
||||||
rewarding_parameters.active_set_size,
|
|
||||||
)
|
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
Reference in New Issue
Block a user