diff --git a/data_structures/src/chain/mod.rs b/data_structures/src/chain/mod.rs index ea6d43792..95c75c811 100644 --- a/data_structures/src/chain/mod.rs +++ b/data_structures/src/chain/mod.rs @@ -4592,7 +4592,7 @@ mod tests { use crate::{ proto::versioning::{ProtocolVersion, VersionedHashable}, - superblock::{mining_build_superblock, ARSIdentities}, + superblock::{mining_build_superblock, ValidatorIdentities}, transaction::{CommitTransactionBody, RevealTransactionBody, VTTransactionBody}, }; @@ -6473,11 +6473,11 @@ mod tests { let expected_order = vec![p1_bls, p2_bls, p3_bls]; let ordered_identities = rep_engine.get_rep_ordered_ars_list(); - let ars_identities = ARSIdentities::new(ordered_identities); + let validator_identities = ValidatorIdentities::new(ordered_identities); assert_eq!( expected_order, - ars_identities.get_rep_ordered_bn256_list(&alt_keys) + validator_identities.get_ordered_bn256_list(&alt_keys) ); } @@ -6515,11 +6515,11 @@ mod tests { let expected_order = vec![p1_bls, p2_bls, p3_bls]; let ordered_identities = rep_engine.get_rep_ordered_ars_list(); - let ars_identities = ARSIdentities::new(ordered_identities); + let validator_identities = ValidatorIdentities::new(ordered_identities); assert_eq!( expected_order, - ars_identities.get_rep_ordered_bn256_list(&alt_keys) + validator_identities.get_ordered_bn256_list(&alt_keys) ); } @@ -6573,11 +6573,11 @@ mod tests { let expected_order = vec![p1_bls, p2_bls, p4_bls, p5_bls, p3_bls]; let ordered_identities = rep_engine.get_rep_ordered_ars_list(); - let ars_identities = ARSIdentities::new(ordered_identities); + let validator_identities = ValidatorIdentities::new(ordered_identities); assert_eq!( expected_order, - ars_identities.get_rep_ordered_bn256_list(&alt_keys) + validator_identities.get_ordered_bn256_list(&alt_keys) ); } diff --git a/data_structures/src/staking/stakes.rs b/data_structures/src/staking/stakes.rs index a5e22a6f8..8d10c27ab 100644 --- a/data_structures/src/staking/stakes.rs +++ b/data_structures/src/staking/stakes.rs @@ -1,5 +1,6 @@ use std::{ - collections::{btree_map::Entry, BTreeMap}, + cmp::PartialOrd, + collections::{btree_map::Entry, BTreeMap, HashSet}, fmt::{Debug, Display}, ops::{Add, Div, Mul, Sub}, }; @@ -80,6 +81,9 @@ where /// it never gets persisted and rather always read from constants, or hide the field and the related method /// behind a #[test] thing. minimum_stakeable: Option, + /// A listing of all active validators (mined a block or solved a data request) indexed by the validator address + /// and the epoch of when it was active as value + by_active: BTreeMap, } impl Stakes @@ -108,7 +112,8 @@ where + Debug + Display + Send - + Sync, + + Sync + + PartialOrd, Power: Copy + Default + Ord + Add + Div, u64: From + From, { @@ -251,6 +256,7 @@ where // No need to keep the entry if the stake has gone to zero if final_coins.is_zero() { by_address_entry.remove(); + self.by_active.remove(&key.validator); self.by_coins.remove(&CoinsAndAddresses { coins: initial_coins, addresses: key, @@ -311,6 +317,41 @@ where } } + /// Return the total number of validators. + pub fn validator_count(&self, active_since: Option) -> usize { + match active_since { + None => self.by_active.len(), + Some(epoch) => { + let mut count = 0; + for (_, active) in self.by_active.iter() { + if *active >= epoch { + count += 1; + } + } + count + } + } + } + + /// Get a vector of all validator that were active since a given epoch + pub fn get_active_validators(&self, active_since: Epoch) -> Vec
{ + self.by_active + .iter() + .filter(|(_, epoch)| **epoch >= active_since) + .map(|(address, _)| address.clone()) + .collect() + } + + /// Update the active epoch of the validators passed as an argument + pub fn update_active_epoch(&mut self, validators: HashSet
, active: Epoch) { + for validator in validators { + self.by_active + .entry(validator) + .and_modify(|validator| *validator = active) + .or_insert(active); + } + } + /// Query stakes by stake key. #[inline(always)] fn query_by_key(&self, key: StakeKey
) -> StakingResult { @@ -372,7 +413,8 @@ where + Debug + Display + Send - + Sync, + + Sync + + PartialOrd, Power: Add + Copy + Default + Div + Ord + Debug, Wit: Mul, u64: From + From, @@ -419,7 +461,8 @@ where + Debug + Send + Sync - + Display, + + Display + + PartialOrd, Power: Add + Copy + Default + Div + Ord + Debug, Wit: Mul, u64: From + From, diff --git a/data_structures/src/superblock.rs b/data_structures/src/superblock.rs index 8557596ed..94e22a3f2 100644 --- a/data_structures/src/superblock.rs +++ b/data_structures/src/superblock.rs @@ -52,16 +52,16 @@ pub enum SuperBlockConsensus { Unknown, } -/// ARS identities +/// Validator identities #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -pub struct ARSIdentities { - // HashSet of the identities in a specific ARS +pub struct ValidatorIdentities { + // HashSet of the validator identities at a specific block height identities: HashSet, - // Ordered vector of the identities in a specific ARS + // Ordered vector of the most recently active validator identities at a specific block height ordered_identities: Vec, } -impl ARSIdentities { +impl ValidatorIdentities { pub fn len(&self) -> usize { self.identities.len() } @@ -71,13 +71,13 @@ impl ARSIdentities { } pub fn new(ordered_identities: Vec) -> Self { - ARSIdentities { + ValidatorIdentities { identities: ordered_identities.iter().cloned().collect(), ordered_identities, } } - pub fn get_rep_ordered_bn256_list(&self, alt_keys: &AltKeys) -> Vec { + pub fn get_ordered_bn256_list(&self, alt_keys: &AltKeys) -> Vec { self.ordered_identities .iter() .filter_map(|pkh| alt_keys.get_bn256(pkh).cloned()) @@ -225,10 +225,10 @@ impl SuperBlockVotesMempool { /// State related to superblocks #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] pub struct SuperBlockState { - // Structure of the current Active Reputation Set identities - ars_current_identities: ARSIdentities, - // Structure of the previous Active Reputation Set identities - ars_previous_identities: ARSIdentities, + // Structure of the current set of validator identities + validator_current_identities: ValidatorIdentities, + // Structure of the previous set of validator identities + validator_previous_identities: ValidatorIdentities, /// The most recently created superblock. This one is yet to be voted and decided upon. current_superblock: Option, // Current superblock beacon including the superblock hash created by this node @@ -246,8 +246,8 @@ impl SuperBlockState { pub fn new(superblock_genesis_hash: Hash, bootstrap_committee: Vec) -> Self { Self { signing_committee: bootstrap_committee.clone().into_iter().collect(), - ars_previous_identities: ARSIdentities::new(bootstrap_committee.clone()), - ars_current_identities: ARSIdentities::new(bootstrap_committee), + validator_previous_identities: ValidatorIdentities::new(bootstrap_committee.clone()), + validator_current_identities: ValidatorIdentities::new(bootstrap_committee), current_superblock_beacon: CheckpointBeacon { checkpoint: 0, hash_prev_block: superblock_genesis_hash, @@ -306,7 +306,7 @@ impl SuperBlockState { Some(true) => self.insert_vote(sbv.clone()), Some(false) => { if sbv.superblock_index == current_superblock_index - || self.ars_previous_identities.is_empty() + || self.validator_previous_identities.is_empty() { AddSuperBlockVote::NotInSigningCommittee } else { @@ -402,13 +402,13 @@ impl SuperBlockState { } } - fn update_ars_identities(&mut self, new_identities: ARSIdentities) { - self.ars_previous_identities = std::mem::take(&mut self.ars_current_identities); - self.ars_current_identities = new_identities; + fn update_validator_identities(&mut self, new_identities: ValidatorIdentities) { + self.validator_previous_identities = std::mem::take(&mut self.validator_current_identities); + self.validator_current_identities = new_identities; } /// Produces a `SuperBlock` that includes the blocks in `block_headers` if there is at least one of them. - /// `ars_identities` will be used to validate all the superblock votes received for the + /// `validator_identities` will be used to validate all the superblock votes received for the /// next superblock. The votes for the current superblock must be validated using them /// to calculate the superblock_signing_committee. /// The ordered bn256 keys will be merkelized and appended to the superblock @@ -416,7 +416,7 @@ impl SuperBlockState { pub fn build_superblock( &mut self, block_headers: &[BlockHeader], - ars_identities: ARSIdentities, + validator_identities: ValidatorIdentities, signing_committee_size: u32, superblock_index: u32, last_block_in_previous_superblock: Hash, @@ -424,9 +424,9 @@ impl SuperBlockState { sync_superblock: Option, block_epoch: Epoch, ) -> SuperBlock { - let key_leaves = hash_key_leaves(&ars_identities.get_rep_ordered_bn256_list(alt_keys)); + let key_leaves = hash_key_leaves(&validator_identities.get_ordered_bn256_list(alt_keys)); - self.update_ars_identities(ars_identities); + self.update_validator_identities(validator_identities); // During synchronization we use the superblock received as consensus by our outbounds // to have the right value of the signing committee size. From now on, we have all the values @@ -434,7 +434,7 @@ impl SuperBlockState { let superblock = if let Some(sb) = sync_superblock { // Before updating the superblock_beacon, calculate the signing committee let signing_committee = calculate_superblock_signing_committee( - self.ars_previous_identities.clone(), + self.validator_previous_identities.clone(), sb.signing_committee_length, superblock_index, self.current_superblock_beacon.hash_prev_block, @@ -453,7 +453,7 @@ impl SuperBlockState { } else { // Before updating the superblock_beacon, calculate the signing committee let signing_committee = calculate_superblock_signing_committee( - self.ars_previous_identities.clone(), + self.validator_previous_identities.clone(), signing_committee_size, superblock_index, self.current_superblock_beacon.hash_prev_block, @@ -562,18 +562,18 @@ impl SuperBlockState { /// Calculates the superblock signing committee for a given superblock hash and ars #[allow(clippy::cast_possible_truncation)] pub fn calculate_superblock_signing_committee( - ars_identities: ARSIdentities, + validator_identities: ValidatorIdentities, signing_committee_size: u32, current_superblock_index: u32, superblock_hash: Hash, block_epoch: Epoch, ) -> HashSet { // If the number of identities is lower than committee_size all the members of the ARS sign the superblock - if ars_identities.len() < usize::try_from(signing_committee_size).unwrap() { - ars_identities.identities + if validator_identities.len() < usize::try_from(signing_committee_size).unwrap() { + validator_identities.identities } else if after_second_hard_fork(block_epoch, get_environment()) { // Start counting the members of the subset from: - // sha256(superblock_hash || superblock_index) % ars_identities.len() + // sha256(superblock_hash || superblock_index) % validator_identities.len() let superblock_hash_and_index_bytes = [ superblock_hash.as_ref(), current_superblock_index.to_be_bytes().as_ref(), @@ -582,12 +582,12 @@ pub fn calculate_superblock_signing_committee( let superblock_hash_and_index_bytes_hashed = Hash::from(calculate_sha256(&superblock_hash_and_index_bytes)); let first = superblock_hash_and_index_bytes_hashed - .div_mod(ars_identities.len() as u64) + .div_mod(validator_identities.len() as u64) .1 as usize; // Get the subset let subset = magic_partition_2( - &ars_identities.ordered_identities, + &validator_identities.ordered_identities, first, signing_committee_size.try_into().unwrap(), superblock_hash_and_index_bytes_hashed.as_ref(), @@ -603,11 +603,11 @@ pub fn calculate_superblock_signing_committee( // Start counting the members of the subset from the superblock_hash plus superblock index hash let mut first = u32::from(first_byte_sb_hash) + u32::from(first_byte_index_hash); // We need to choose a first member from all the potential ARS members - first %= ars_identities.len() as u32; + first %= validator_identities.len() as u32; // Get the subset let subset = magic_partition( - &ars_identities.ordered_identities.to_vec(), + &validator_identities.ordered_identities.to_vec(), first.try_into().unwrap(), signing_committee_size.try_into().unwrap(), ); @@ -956,7 +956,7 @@ mod tests { let sb1 = sbs.build_superblock( &block_headers, - ARSIdentities::new(ars2), + ValidatorIdentities::new(ars2), 100, 0, Hash::default(), @@ -1005,12 +1005,12 @@ mod tests { let block_headers = vec![BlockHeader::default()]; let pkhs = vec![create_pkh(1)]; let keys = vec![create_bn256(1)]; - let ars_identities = ARSIdentities::new(pkhs.clone()); + let validator_identities = ValidatorIdentities::new(pkhs.clone()); let alt_keys = create_alt_keys(pkhs, keys); let genesis_hash = Hash::default(); let sb1 = sbs.build_superblock( &block_headers, - ars_identities, + validator_identities, 100, 0, genesis_hash, @@ -1035,12 +1035,12 @@ mod tests { let genesis_hash = Hash::default(); let pkhs = vec![create_pkh(1)]; let keys = vec![create_bn256(1)]; - let ars_identities = ARSIdentities::new(pkhs.clone()); + let validator_identities = ValidatorIdentities::new(pkhs.clone()); let alt_keys = create_alt_keys(pkhs, keys); let first_superblock = sbs.build_superblock( &block_headers, - ars_identities.clone(), + validator_identities.clone(), 100, 0, genesis_hash, @@ -1052,7 +1052,7 @@ mod tests { let expected_superblock = SuperBlock::new( 0, hash_merkle_tree_root(&hash_key_leaves( - &ars_identities.get_rep_ordered_bn256_list(&alt_keys), + &validator_identities.get_ordered_bn256_list(&alt_keys), )), Hash::default(), 0, @@ -1068,13 +1068,13 @@ mod tests { .unwrap(); let expected_sbs = SuperBlockState { - ars_current_identities: ars_identities, + ars_current_identities: validator_identities, signing_committee: HashSet::new(), current_superblock_beacon: CheckpointBeacon { checkpoint: 0, hash_prev_block: expected_superblock_hash, }, - ars_previous_identities: ARSIdentities::default(), + ars_previous_identities: ValidatorIdentities::default(), ..Default::default() }; assert_eq!(sbs, expected_sbs); @@ -1087,14 +1087,14 @@ mod tests { let block_headers = vec![BlockHeader::default()]; let pkhs = vec![create_pkh(1)]; let keys = vec![create_bn256(1)]; - let ars_identities = ARSIdentities::new(pkhs.clone()); + let validator_identities = ValidatorIdentities::new(pkhs.clone()); let alt_keys = create_alt_keys(pkhs, keys); let genesis_hash = Hash::default(); sbs.build_superblock( &block_headers, - ars_identities.clone(), + validator_identities.clone(), 100, 0, genesis_hash, @@ -1106,7 +1106,7 @@ mod tests { let expected_second_superblock = SuperBlock::new( 1, hash_merkle_tree_root(&hash_key_leaves( - &ars_identities.get_rep_ordered_bn256_list(&alt_keys), + &validator_identities.get_ordered_bn256_list(&alt_keys), )), Hash::default(), 1, @@ -1118,7 +1118,7 @@ mod tests { assert_eq!( sbs.build_superblock( &[], - ars_identities.clone(), + validator_identities.clone(), 100, 1, genesis_hash, @@ -1135,8 +1135,8 @@ mod tests { checkpoint: 1, hash_prev_block: expected_second_superblock.hash(), }; - expected_sbs.signing_committee = ars_identities.identities.iter().cloned().collect(); - expected_sbs.ars_previous_identities = ars_identities; + expected_sbs.signing_committee = validator_identities.identities.iter().cloned().collect(); + expected_sbs.ars_previous_identities = validator_identities; assert_eq!(sbs, expected_sbs); } @@ -1156,13 +1156,13 @@ mod tests { let block_headers = vec![BlockHeader::default()]; let pkhs = vec![create_pkh(1)]; let keys = vec![create_bn256(1)]; - let ars_identities = ARSIdentities::new(pkhs.clone()); + let validator_identities = ValidatorIdentities::new(pkhs.clone()); let alt_keys = create_alt_keys(pkhs, keys); let genesis_hash = Hash::default(); let _sb1 = sbs.build_superblock( &block_headers, - ars_identities.clone(), + validator_identities.clone(), 100, 0, genesis_hash, @@ -1179,7 +1179,7 @@ mod tests { let _sb2 = sbs.build_superblock( &block_headers, - ars_identities, + validator_identities, 100, 1, genesis_hash, @@ -1213,9 +1213,9 @@ mod tests { let p1 = PublicKey::from_bytes([1; 33]); let pkhs = vec![p1.pkh()]; let keys = vec![create_bn256(1)]; - let ars0 = ARSIdentities::new(vec![]); - let ars1 = ARSIdentities::new(pkhs.clone()); - let ars2 = ARSIdentities::new(pkhs.clone()); + let ars0 = ValidatorIdentities::new(vec![]); + let ars1 = ValidatorIdentities::new(pkhs.clone()); + let ars2 = ValidatorIdentities::new(pkhs.clone()); let alt_keys = create_alt_keys(pkhs, keys); @@ -1276,9 +1276,9 @@ mod tests { let p1 = PublicKey::from_bytes([1; 33]); let pkhs = vec![p1.pkh()]; let keys = vec![create_bn256(1)]; - let ars0 = ARSIdentities::new(vec![]); - let ars1 = ARSIdentities::new(pkhs.clone()); - let ars2 = ARSIdentities::new(pkhs.clone()); + let ars0 = ValidatorIdentities::new(vec![]); + let ars1 = ValidatorIdentities::new(pkhs.clone()); + let ars2 = ValidatorIdentities::new(pkhs.clone()); let alt_keys = create_alt_keys(pkhs, keys); // Superblock votes for index 0 cannot be validated because we do not know the ARS for index -1 @@ -1339,9 +1339,9 @@ mod tests { let p1 = PublicKey::from_bytes([1; 33]); let pkhs = vec![p1.pkh()]; let keys = vec![create_bn256(1)]; - let ars0 = ARSIdentities::new(vec![]); - let ars1 = ARSIdentities::new(pkhs.clone()); - let ars2 = ARSIdentities::new(pkhs.clone()); + let ars0 = ValidatorIdentities::new(vec![]); + let ars1 = ValidatorIdentities::new(pkhs.clone()); + let ars2 = ValidatorIdentities::new(pkhs.clone()); let alt_keys = create_alt_keys(pkhs, keys); // Superblock votes for index 0 cannot be validated because we do not know the ARS for index -1 @@ -1402,9 +1402,9 @@ mod tests { let p1 = PublicKey::from_bytes([1; 33]); let pkhs = vec![p1.pkh()]; let keys = vec![create_bn256(1)]; - let ars0 = ARSIdentities::new(vec![]); - let ars1 = ARSIdentities::new(pkhs.clone()); - let ars2 = ARSIdentities::new(pkhs.clone()); + let ars0 = ValidatorIdentities::new(vec![]); + let ars1 = ValidatorIdentities::new(pkhs.clone()); + let ars2 = ValidatorIdentities::new(pkhs.clone()); let alt_keys = create_alt_keys(pkhs, keys); // Superblock votes for index 0 cannot be validated because we do not know the ARS for index -1 @@ -1479,11 +1479,11 @@ mod tests { let p2 = PublicKey::from_bytes([2; 33]); let p3 = PublicKey::from_bytes([3; 33]); - let ars0 = ARSIdentities::new(vec![]); - let ars1 = ARSIdentities::new(vec![p1.pkh()]); - let ars2 = ARSIdentities::new(vec![p2.pkh()]); - let ars3 = ARSIdentities::new(vec![p3.pkh()]); - let ars4 = ARSIdentities::new(vec![]); + let ars0 = ValidatorIdentities::new(vec![]); + let ars1 = ValidatorIdentities::new(vec![p1.pkh()]); + let ars2 = ValidatorIdentities::new(vec![p2.pkh()]); + let ars3 = ValidatorIdentities::new(vec![p3.pkh()]); + let ars4 = ValidatorIdentities::new(vec![]); let pkhs = vec![p1.pkh(), p2.pkh(), p3.pkh()]; let keys = vec![create_bn256(1), create_bn256(2), create_bn256(3)]; let alt_keys = create_alt_keys(pkhs, keys); @@ -1634,7 +1634,7 @@ mod tests { let pkhs = vec![p1.pkh(), p2.pkh(), p3.pkh()]; let keys = vec![create_bn256(1), create_bn256(2), create_bn256(3)]; - let ars_identities = ARSIdentities::new(pkhs.clone()); + let validator_identities = ValidatorIdentities::new(pkhs.clone()); let alt_keys = create_alt_keys(pkhs, keys); let create_votes = |superblock_hash, superblock_index| { @@ -1659,7 +1659,7 @@ mod tests { // (because it does not exist). When adding a vote it will return NotInSigningCommittee let sb0 = sbs.build_superblock( &block_headers, - ars_identities.clone(), + validator_identities.clone(), 100, 0, genesis_hash, @@ -1687,10 +1687,10 @@ mod tests { AddSuperBlockVote::NotInSigningCommittee ); - // Create a superblock with the ars_identities + // Create a superblock with the validator_identities let sb1 = sbs.build_superblock( &block_headers, - ars_identities.clone(), + validator_identities.clone(), 100, 1, genesis_hash, @@ -1719,7 +1719,7 @@ mod tests { let sb2 = sbs.build_superblock( &block_headers, - ars_identities, + validator_identities, 100, 2, genesis_hash, @@ -1765,9 +1765,9 @@ mod tests { ]; let alt_keys = create_alt_keys(pkhs1.clone(), keys); - let ars0 = ARSIdentities::new(pkhs0); - let ars1 = ARSIdentities::new(pkhs1); - let ars2 = ARSIdentities::new(pkhs2); + let ars0 = ValidatorIdentities::new(pkhs0); + let ars1 = ValidatorIdentities::new(pkhs1); + let ars2 = ValidatorIdentities::new(pkhs2); let create_votes = |superblock_hash, superblock_index| { let mut v1 = SuperBlockVote::new_unsigned(superblock_hash, superblock_index); @@ -1894,14 +1894,14 @@ mod tests { let pkhs = vec![p1.pkh(), p2.pkh(), p3.pkh()]; let keys = vec![create_bn256(1), create_bn256(2), create_bn256(3)]; - let ars_identities = ARSIdentities::new(pkhs.clone()); + let validator_identities = ValidatorIdentities::new(pkhs.clone()); let alt_keys = create_alt_keys(pkhs, keys); let block_headers = vec![BlockHeader::default()]; let genesis_hash = Hash::default(); let _sb1 = sbs.build_superblock( &block_headers, - ars_identities.clone(), + validator_identities.clone(), 100, 0, genesis_hash, @@ -1912,7 +1912,7 @@ mod tests { let expected_sb2 = mining_build_superblock( &block_headers, - &hash_key_leaves(&ars_identities.get_rep_ordered_bn256_list(&alt_keys)), + &hash_key_leaves(&validator_identities.get_ordered_bn256_list(&alt_keys)), 1, genesis_hash, 3, @@ -1929,7 +1929,7 @@ mod tests { // Create the second superblock afterwards let sb2 = sbs.build_superblock( &block_headers, - ars_identities.clone(), + validator_identities.clone(), 100, 1, genesis_hash, @@ -1954,7 +1954,7 @@ mod tests { // set as "InvalidIndex" let _sb3 = sbs.build_superblock( &block_headers, - ars_identities, + validator_identities, 100, 2, genesis_hash, @@ -1982,7 +1982,7 @@ mod tests { let pkhs = vec![p1.pkh(), p2.pkh(), p3.pkh()]; let keys = vec![create_bn256(1), create_bn256(2), create_bn256(3)]; - let ars_identities = ARSIdentities::new(pkhs.clone()); + let validator_identities = ValidatorIdentities::new(pkhs.clone()); let alt_keys = create_alt_keys(pkhs, keys); let block_headers = vec![BlockHeader::default()]; @@ -1990,7 +1990,7 @@ mod tests { // superblock with index 0. let _sb1 = sbs.build_superblock( &block_headers, - ars_identities.clone(), + validator_identities.clone(), 2, 0, genesis_hash, @@ -2001,7 +2001,7 @@ mod tests { // superblock with index 1 let sb2 = sbs.build_superblock( &block_headers, - ars_identities.clone(), + validator_identities.clone(), 2, 1, genesis_hash, @@ -2012,7 +2012,7 @@ mod tests { let expected_sb2 = mining_build_superblock( &block_headers, - &hash_key_leaves(&ars_identities.get_rep_ordered_bn256_list(&alt_keys)), + &hash_key_leaves(&validator_identities.get_ordered_bn256_list(&alt_keys)), 1, genesis_hash, 2, @@ -2060,13 +2060,13 @@ mod tests { let block_headers = vec![BlockHeader::default()]; let pkhs = vec![create_pkh(1)]; let keys = vec![create_bn256(1)]; - let ars_identities = ARSIdentities::new(pkhs.clone()); + let validator_identities = ValidatorIdentities::new(pkhs.clone()); let alt_keys = create_alt_keys(pkhs, keys); let genesis_hash = Hash::default(); let _sb1 = sbs.build_superblock( &block_headers, - ars_identities, + validator_identities, 100, 2, genesis_hash, @@ -2089,13 +2089,13 @@ mod tests { let block_headers = vec![BlockHeader::default()]; let pkhs = vec![create_pkh(1)]; let keys = vec![create_bn256(1)]; - let ars_identities = ARSIdentities::new(pkhs.clone()); + let validator_identities = ValidatorIdentities::new(pkhs.clone()); let alt_keys = create_alt_keys(pkhs, keys); let genesis_hash = Hash::default(); let _sb1 = sbs.build_superblock( &block_headers, - ars_identities.clone(), + validator_identities.clone(), 100, 2, genesis_hash, @@ -2106,7 +2106,7 @@ mod tests { let _sb2 = sbs.build_superblock( &block_headers, - ars_identities, + validator_identities, 2, 5, genesis_hash, @@ -2142,7 +2142,7 @@ mod tests { create_bn256(3), create_bn256(4), ]; - let ars_identities = ARSIdentities::new(pkhs.clone()); + let validator_identities = ValidatorIdentities::new(pkhs.clone()); let alt_keys = create_alt_keys(pkhs, keys); let block_headers = vec![BlockHeader::default()]; @@ -2150,7 +2150,7 @@ mod tests { // superblock with index 0. let _sb1 = sbs.build_superblock( &block_headers, - ars_identities.clone(), + validator_identities.clone(), 2, 0, genesis_hash, @@ -2161,7 +2161,7 @@ mod tests { // superblock with index 1 let sb2 = sbs.build_superblock( &block_headers, - ars_identities.clone(), + validator_identities.clone(), 2, 1, genesis_hash, @@ -2172,7 +2172,7 @@ mod tests { let expected_sb2 = mining_build_superblock( &block_headers, - &hash_key_leaves(&ars_identities.get_rep_ordered_bn256_list(&alt_keys)), + &hash_key_leaves(&validator_identities.get_ordered_bn256_list(&alt_keys)), 1, genesis_hash, 2, @@ -2223,14 +2223,14 @@ mod tests { let pkhs = vec![p1.pkh(), p2.pkh(), p3.pkh()]; let keys = vec![create_bn256(1), create_bn256(2), create_bn256(3)]; - let ars_identities = ARSIdentities::new(pkhs.clone()); + let validator_identities = ValidatorIdentities::new(pkhs.clone()); let alt_keys = create_alt_keys(pkhs, keys); let block_headers = vec![BlockHeader::default()]; let genesis_hash = Hash::default(); let _sb1 = sbs.build_superblock( &block_headers, - ars_identities.clone(), + validator_identities.clone(), 100, 0, genesis_hash, @@ -2238,7 +2238,7 @@ mod tests { None, 1, ); - sbs.ars_previous_identities = ars_identities.clone(); + sbs.ars_previous_identities = validator_identities.clone(); let committee_size = 4; let subset = calculate_superblock_signing_committee( sbs.ars_previous_identities, @@ -2247,7 +2247,7 @@ mod tests { sbs.current_superblock_beacon.hash_prev_block, 1, ); - assert_eq!(ars_identities.len(), subset.len()); + assert_eq!(validator_identities.len(), subset.len()); } #[test] fn test_build_superblock_with_optional_superblock() { @@ -2268,7 +2268,7 @@ mod tests { create_bn256(4), create_bn256(5), ]; - let ars = ARSIdentities::new(pkhs.clone()); + let ars = ValidatorIdentities::new(pkhs.clone()); let alt_keys = create_alt_keys(pkhs, keys); sbs.ars_current_identities = ars.clone(); @@ -2342,14 +2342,14 @@ mod tests { p7.pkh(), p8.pkh(), ]; - let ars_identities = ARSIdentities::new(pkhs.clone()); + let validator_identities = ValidatorIdentities::new(pkhs.clone()); let alt_keys = create_alt_keys(pkhs, vec![]); let block_headers = vec![BlockHeader::default()]; let genesis_hash = Hash::default(); let _sb1 = sbs.build_superblock( &block_headers, - ars_identities.clone(), + validator_identities.clone(), 4, 0, genesis_hash, @@ -2357,7 +2357,7 @@ mod tests { None, 1, ); - sbs.ars_previous_identities = ars_identities; + sbs.ars_previous_identities = validator_identities; let committee_size = 4; let subset = calculate_superblock_signing_committee( sbs.ars_previous_identities, @@ -2387,14 +2387,14 @@ mod tests { let p3 = PublicKey::from_bytes([3; 33]); let pkhs = vec![p1.pkh(), p2.pkh(), p3.pkh()]; - let ars_identities = ARSIdentities::new(pkhs.clone()); + let validator_identities = ValidatorIdentities::new(pkhs.clone()); let alt_keys = create_alt_keys(pkhs, vec![]); let block_headers = vec![BlockHeader::default()]; let genesis_hash = Hash::default(); let _sb1 = sbs.build_superblock( &block_headers, - ars_identities.clone(), + validator_identities.clone(), 2, 0, genesis_hash, @@ -2402,7 +2402,7 @@ mod tests { None, 1, ); - sbs.ars_previous_identities = ars_identities.clone(); + sbs.ars_previous_identities = validator_identities.clone(); let committee_size = 2; let subset = calculate_superblock_signing_committee( sbs.ars_previous_identities, @@ -2416,7 +2416,7 @@ mod tests { assert_eq!(subset, vec![p1.pkh(), p3.pkh()].into_iter().collect()); assert_eq!(usize::try_from(committee_size).unwrap(), subset.len()); - sbs.ars_previous_identities = ars_identities; + sbs.ars_previous_identities = validator_identities; let committee_size = 2; let subset_2 = calculate_superblock_signing_committee( sbs.ars_previous_identities.clone(), @@ -2568,12 +2568,12 @@ mod tests { #[test] fn test_get_beacon_2() { let superblock_state = SuperBlockState { - ars_current_identities: ARSIdentities::default(), + ars_current_identities: ValidatorIdentities::default(), current_superblock_beacon: CheckpointBeacon { checkpoint: 0, hash_prev_block: Hash::SHA256([1; 32]), }, - ars_previous_identities: ARSIdentities::default(), + ars_previous_identities: ValidatorIdentities::default(), ..Default::default() }; let beacon = superblock_state.get_beacon(); @@ -2590,12 +2590,12 @@ mod tests { #[test] fn test_get_beacon_3() { let superblock_state = SuperBlockState { - ars_current_identities: ARSIdentities::default(), + ars_current_identities: ValidatorIdentities::default(), current_superblock_beacon: CheckpointBeacon { checkpoint: 1, hash_prev_block: Hash::default(), }, - ars_previous_identities: ARSIdentities::default(), + ars_previous_identities: ValidatorIdentities::default(), ..Default::default() }; let beacon = superblock_state.get_beacon(); @@ -2645,9 +2645,9 @@ mod tests { create_bn256(4), create_bn256(5), ]; - let ars0 = ARSIdentities::new(vec![]); - let ars1 = ARSIdentities::new(pkhs.clone()); - let ars2 = ARSIdentities::new(pkhs.clone()); + let ars0 = ValidatorIdentities::new(vec![]); + let ars1 = ValidatorIdentities::new(pkhs.clone()); + let ars2 = ValidatorIdentities::new(pkhs.clone()); let alt_keys = create_alt_keys(pkhs, keys); diff --git a/node/src/actors/chain_manager/mod.rs b/node/src/actors/chain_manager/mod.rs index 02d822f55..99d17efbd 100644 --- a/node/src/actors/chain_manager/mod.rs +++ b/node/src/actors/chain_manager/mod.rs @@ -61,7 +61,7 @@ use witnet_data_structures::{ penalize_factor, priority::{Priorities, PriorityEngine, PriorityVisitor}, reputation_issuance, - tapi::{after_second_hard_fork, current_active_wips, in_emergency_period, ActiveWips}, + tapi::{after_second_hard_fork, current_active_wips, ActiveWips}, Alpha, AltKeys, Block, BlockHeader, Bn256PublicKey, ChainImport, ChainInfo, ChainState, CheckpointBeacon, CheckpointVRF, ConsensusConstants, DataRequestInfo, DataRequestOutput, DataRequestStage, Epoch, EpochConstants, Hash, Hashable, InventoryEntry, InventoryItem, @@ -72,7 +72,7 @@ use witnet_data_structures::{ get_environment, radon_report::{RadonReport, ReportContext}, staking::prelude::*, - superblock::{ARSIdentities, AddSuperBlockVote, SuperBlockConsensus}, + superblock::{AddSuperBlockVote, SuperBlockConsensus, ValidatorIdentities}, transaction::{RevealTransaction, TallyTransaction, Transaction}, types::{ visitor::{StatefulVisitor, Visitor}, @@ -972,6 +972,25 @@ impl ChainManager { let miner_pkh = block.block_header.proof.proof.pkh(); + // Track all active addresses to update the active epoch of all validators + let mut active_addresses: HashSet = HashSet::new(); + active_addresses.insert(miner_pkh); + + for ta_tx in &block.txns.tally_txns { + // Only update active epoch of honest validators + // If there was a liar or error committer, the last output is the creator of the data request + // This is not guaranteed to be a validator, so do not update its active epoch + let data_requester_output = + ta_tx.out_of_consensus.len() + ta_tx.error_committers.len() > 0; + for (i, output) in ta_tx.outputs.iter().enumerate() { + if data_requester_output && i == ta_tx.outputs.len() - 1 { + break; + } + active_addresses.insert(output.pkh); + } + } + stakes.update_active_epoch(active_addresses, block_epoch); + // Do not update reputation or stakes when consolidating genesis block if block_hash != chain_info.consensus_constants.genesis_hash { update_reputation( @@ -1876,30 +1895,11 @@ impl ChainManager { } let chain_info = act.chain_state.chain_info.as_ref().unwrap(); - let reputation_engine = act.chain_state.reputation_engine.as_ref().unwrap(); let last_superblock_signed_by_bootstrap = last_superblock_signed_by_bootstrap(&chain_info.consensus_constants); - let ars_members = - // Before reaching the epoch activity_period + collateral_age the bootstrap committee signs the superblock - // collateral_age is measured in blocks instead of epochs, but this only means that the period in which - // the bootstrap committee signs is at least epoch activity_period + collateral_age - if let Some(ars_members) = in_emergency_period(superblock_index, get_environment()) { - // Bootstrap committee - ars_members - } else if superblock_index >= last_superblock_signed_by_bootstrap { - reputation_engine.get_rep_ordered_ars_list() - } else { - chain_info - .consensus_constants - .bootstrapping_committee - .iter() - .map(|add| add.parse().expect("Malformed bootstrapping committee")) - .collect() - }; - - // Get the list of members of the ARS with reputation greater than 0 - // the list itself is ordered by decreasing reputation - let ars_identities = ARSIdentities::new(ars_members); + // Get the list of validators sorted by most recently active + let validators = act.chain_state.stakes.get_active_validators(block_epoch - 2000); + let ars_identities = ValidatorIdentities::new(validators); // After the second hard fork, the superblock committee size must be at least 50 let min_committee_size = if after_second_hard_fork(block_epoch, get_environment()) {