diff --git a/chain/chain/src/approval_verification.rs b/chain/chain/src/approval_verification.rs index 5a1b3c8561c..1df76fd05a2 100644 --- a/chain/chain/src/approval_verification.rs +++ b/chain/chain/src/approval_verification.rs @@ -14,7 +14,7 @@ pub fn verify_approval_with_approvers_info( prev_block_height: BlockHeight, block_height: BlockHeight, approvals: &[Option>], - info: Vec<(ApprovalStake, bool)>, + info: Vec, ) -> Result { if approvals.len() > info.len() { return Ok(false); @@ -29,9 +29,9 @@ pub fn verify_approval_with_approvers_info( block_height, ); - for ((validator, is_slashed), may_be_signature) in info.into_iter().zip(approvals.iter()) { + for (validator, may_be_signature) in info.into_iter().zip(approvals.iter()) { if let Some(signature) = may_be_signature { - if is_slashed || !signature.verify(message_to_sign.as_ref(), &validator.public_key) { + if !signature.verify(message_to_sign.as_ref(), &validator.public_key) { return Ok(false); } } @@ -43,7 +43,7 @@ pub fn verify_approval_with_approvers_info( pub fn verify_approvals_and_threshold_orphan( can_approved_block_be_produced: &dyn Fn( &[Option>], - &[(Balance, Balance, bool)], + &[(Balance, Balance)], ) -> bool, prev_block_hash: &CryptoHash, prev_block_height: BlockHeight, @@ -70,7 +70,7 @@ pub fn verify_approvals_and_threshold_orphan( } let stakes = block_approvers .iter() - .map(|stake| (stake.stake_this_epoch, stake.stake_next_epoch, false)) + .map(|stake| (stake.stake_this_epoch, stake.stake_next_epoch)) .collect::>(); if !can_approved_block_be_produced(approvals, &stakes) { Err(Error::NotEnoughApprovals) diff --git a/chain/chain/src/chain.rs b/chain/chain/src/chain.rs index def1fe1f4a3..87d5bc3d3f4 100644 --- a/chain/chain/src/chain.rs +++ b/chain/chain/src/chain.rs @@ -340,12 +340,7 @@ impl Chain { chain_genesis.height, chain_genesis.min_gas_price, chain_genesis.total_supply, - Chain::compute_bp_hash( - epoch_manager, - EpochId::default(), - EpochId::default(), - &CryptoHash::default(), - )?, + Chain::compute_bp_hash(epoch_manager, EpochId::default(), EpochId::default())?, ); Ok((genesis_block, genesis_chunks)) } @@ -613,10 +608,8 @@ impl Chain { epoch_manager: &dyn EpochManagerAdapter, epoch_id: EpochId, prev_epoch_id: EpochId, - last_known_hash: &CryptoHash, ) -> Result { - let bps = epoch_manager.get_epoch_block_producers_ordered(&epoch_id, last_known_hash)?; - let validator_stakes = bps.into_iter().map(|(bp, _)| bp).collect_vec(); + let validator_stakes = epoch_manager.get_epoch_block_producers_ordered(&epoch_id)?; let protocol_version = epoch_manager.get_epoch_protocol_version(&prev_epoch_id)?; Self::compute_bp_hash_from_validator_stakes( &validator_stakes, @@ -752,11 +745,8 @@ impl Chain { } }; - let next_block_producers = get_epoch_block_producers_view( - final_block_header.next_epoch_id(), - header.prev_hash(), - epoch_manager, - )?; + let next_block_producers = + get_epoch_block_producers_view(final_block_header.next_epoch_id(), epoch_manager)?; create_light_client_block_view(&final_block_header, chain_store, Some(next_block_producers)) } @@ -997,7 +987,6 @@ impl Chain { self.epoch_manager.as_ref(), *header.next_epoch_id(), *header.epoch_id(), - header.prev_hash(), )? { return Err(Error::InvalidNextBPHash); @@ -1042,7 +1031,7 @@ impl Chain { .epoch_manager .get_epoch_block_approvers_ordered(header.prev_hash())? .iter() - .map(|(x, is_slashed)| (x.stake_this_epoch, x.stake_next_epoch, *is_slashed)) + .map(|x| (x.stake_this_epoch, x.stake_next_epoch)) .collect::>(); if !Doomslug::can_approved_block_be_produced( self.doomslug_threshold_mode, diff --git a/chain/chain/src/doomslug.rs b/chain/chain/src/doomslug.rs index ea280de6334..13ec4c9f966 100644 --- a/chain/chain/src/doomslug.rs +++ b/chain/chain/src/doomslug.rs @@ -280,7 +280,7 @@ impl DoomslugApprovalsTrackersAtHeight { fn process_approval( &mut self, approval: &Approval, - stakes: &[(ApprovalStake, bool)], + stakes: &[ApprovalStake], threshold_mode: DoomslugThresholdMode, ) -> DoomslugBlockProductionReadiness { if let Some(last_parent) = self.last_approval_per_account.get(&approval.account_id) { @@ -300,13 +300,7 @@ impl DoomslugApprovalsTrackersAtHeight { let account_id_to_stakes = stakes .iter() - .filter_map(|(x, is_slashed)| { - if *is_slashed { - None - } else { - Some((x.account_id.clone(), (x.stake_this_epoch, x.stake_next_epoch))) - } - }) + .map(|x| (x.account_id.clone(), (x.stake_this_epoch, x.stake_next_epoch))) .collect::>(); assert_eq!(account_id_to_stakes.len(), stakes.len()); @@ -559,27 +553,25 @@ impl Doomslug { pub fn can_approved_block_be_produced( mode: DoomslugThresholdMode, approvals: &[Option>], - stakes: &[(Balance, Balance, bool)], + stakes: &[(Balance, Balance)], ) -> bool { if mode == DoomslugThresholdMode::NoApprovals { return true; } - let threshold1 = stakes.iter().map(|(x, _, _)| x).sum::() * 2 / 3; - let threshold2 = stakes.iter().map(|(_, x, _)| x).sum::() * 2 / 3; + let threshold1 = stakes.iter().map(|(x, _)| x).sum::() * 2 / 3; + let threshold2 = stakes.iter().map(|(_, x)| x).sum::() * 2 / 3; let approved_stake1 = approvals .iter() .zip(stakes.iter()) - .filter(|(_, (_, _, is_slashed))| !*is_slashed) - .map(|(approval, (stake, _, _))| if approval.is_some() { *stake } else { 0 }) + .map(|(approval, (stake, _))| if approval.is_some() { *stake } else { 0 }) .sum::(); let approved_stake2 = approvals .iter() .zip(stakes.iter()) - .filter(|(_, (_, _, is_slashed))| !*is_slashed) - .map(|(approval, (_, stake, _))| if approval.is_some() { *stake } else { 0 }) + .map(|(approval, (_, stake))| if approval.is_some() { *stake } else { 0 }) .sum::(); (approved_stake1 > threshold1 || threshold1 == 0) @@ -639,7 +631,7 @@ impl Doomslug { fn on_approval_message_internal( &mut self, approval: &Approval, - stakes: &[(ApprovalStake, bool)], + stakes: &[ApprovalStake], ) -> DoomslugBlockProductionReadiness { let threshold_mode = self.threshold_mode; let ret = self @@ -662,7 +654,7 @@ impl Doomslug { } /// Processes single approval - pub fn on_approval_message(&mut self, approval: &Approval, stakes: &[(ApprovalStake, bool)]) { + pub fn on_approval_message(&mut self, approval: &Approval, stakes: &[ApprovalStake]) { if approval.target_height < self.tip.height || approval.target_height > self.tip.height + MAX_HEIGHTS_AHEAD_TO_STORE_APPROVALS { @@ -935,7 +927,6 @@ mod tests { stake_next_epoch: *stake_next_epoch, public_key: SecretKey::from_seed(KeyType::ED25519, account_id).public_key(), }) - .map(|stake| (stake, false)) .collect::>(); let signers = accounts .iter() @@ -1058,7 +1049,6 @@ mod tests { stake_next_epoch, public_key: SecretKey::from_seed(KeyType::ED25519, account_id).public_key(), }) - .map(|stake| (stake, false)) .collect::>(); let clock = FakeClock::new(Utc::UNIX_EPOCH); let mut tracker = DoomslugApprovalsTrackersAtHeight::new(clock.clock()); diff --git a/chain/chain/src/lightclient.rs b/chain/chain/src/lightclient.rs index bb629412089..8f053a4be4c 100644 --- a/chain/chain/src/lightclient.rs +++ b/chain/chain/src/lightclient.rs @@ -1,7 +1,7 @@ use near_chain_primitives::Error; use near_epoch_manager::EpochManagerAdapter; use near_primitives::block::BlockHeader; -use near_primitives::hash::{hash, CryptoHash}; +use near_primitives::hash::hash; use near_primitives::types::EpochId; use near_primitives::views::validator_stake_view::ValidatorStakeView; use near_primitives::views::{BlockHeaderInnerLiteView, LightClientBlockView}; @@ -10,13 +10,12 @@ use crate::ChainStoreAccess; pub fn get_epoch_block_producers_view( epoch_id: &EpochId, - prev_hash: &CryptoHash, epoch_manager: &dyn EpochManagerAdapter, ) -> Result, Error> { Ok(epoch_manager - .get_epoch_block_producers_ordered(epoch_id, prev_hash)? + .get_epoch_block_producers_ordered(epoch_id)? .iter() - .map(|x| x.0.clone().into()) + .map(|x| x.clone().into()) .collect::>()) } diff --git a/chain/chain/src/runtime/tests.rs b/chain/chain/src/runtime/tests.rs index 76fc95d9950..43334b2284f 100644 --- a/chain/chain/src/runtime/tests.rs +++ b/chain/chain/src/runtime/tests.rs @@ -1,4 +1,4 @@ -use std::collections::BTreeSet; +use std::collections::{BTreeSet, HashSet}; use std::path::PathBuf; use crate::types::{ChainConfig, RuntimeStorageConfig}; @@ -506,14 +506,14 @@ fn test_validator_rotation() { env.epoch_manager.get_epoch_id_from_prev_block(&env.head.last_block_hash).unwrap(); assert_eq!( env.epoch_manager - .get_epoch_block_producers_ordered(&epoch_id, &env.head.last_block_hash) + .get_epoch_block_producers_ordered(&epoch_id) .unwrap() .iter() - .map(|x| (x.0.account_id().clone(), x.1)) - .collect::>(), - vec![("test3".parse().unwrap(), false), ("test1".parse().unwrap(), false)] + .map(|x| x.account_id().clone()) + .collect::>(), + vec!["test3".parse().unwrap(), "test1".parse().unwrap()] .into_iter() - .collect::>() + .collect::>() ); let test1_acc = env.view_account(&"test1".parse().unwrap()); @@ -831,7 +831,7 @@ fn test_get_validator_info() { let shard_layout = env.epoch_manager.get_shard_layout(&epoch_id).unwrap(); let shard_id = shard_layout.shard_ids().next().unwrap(); - let em = env.runtime.epoch_manager.read(); + let em = env.runtime.epoch_manager.clone(); let bp = em.get_block_producer_info(&epoch_id, height).unwrap(); let cp_key = ChunkProductionKey { epoch_id, height_created: height, shard_id }; let cp = em.get_chunk_producer_info(&cp_key).unwrap(); @@ -1029,13 +1029,14 @@ fn test_challenges() { assert_eq!(env.view_account(&"test2".parse().unwrap()).locked, 0); let mut bps = env .epoch_manager - .get_epoch_block_producers_ordered(&env.head.epoch_id, &env.head.last_block_hash) + .get_epoch_block_producers_ordered(&env.head.epoch_id) .unwrap() .iter() - .map(|x| (x.0.account_id().clone(), x.1)) + .map(|x| x.account_id().clone()) .collect::>(); bps.sort_unstable(); - assert_eq!(bps, vec![("test1".parse().unwrap(), false), ("test2".parse().unwrap(), true)]); + let expected_bps: Vec = vec!["test1".parse().unwrap(), "test2".parse().unwrap()]; + assert_eq!(bps, expected_bps); let msg = vec![0, 1, 2]; let signer = InMemorySigner::test_signer(&"test2".parse().unwrap()); let signature = signer.sign(&msg); @@ -1079,20 +1080,15 @@ fn test_double_sign_challenge_not_all_slashed() { assert_eq!(env.view_account(&"test2".parse().unwrap()).locked, TESTING_INIT_STAKE); let mut bps = env .epoch_manager - .get_epoch_block_producers_ordered(&env.head.epoch_id, &env.head.last_block_hash) + .get_epoch_block_producers_ordered(&env.head.epoch_id) .unwrap() .iter() - .map(|x| (x.0.account_id().clone(), x.1)) + .map(|x| x.account_id().clone()) .collect::>(); bps.sort_unstable(); - assert_eq!( - bps, - vec![ - ("test1".parse().unwrap(), false), - ("test2".parse().unwrap(), true), - ("test3".parse().unwrap(), false) - ] - ); + let expected_bps: Vec = + vec!["test1".parse().unwrap(), "test2".parse().unwrap(), "test3".parse().unwrap()]; + assert_eq!(bps, expected_bps); let msg = vec![0, 1, 2]; let signer = InMemorySigner::test_signer(&"test2".parse().unwrap()); let signature = signer.sign(&msg); diff --git a/chain/chain/src/test_utils/kv_runtime.rs b/chain/chain/src/test_utils/kv_runtime.rs index 9065e9f8a7f..3ebed7e7a8b 100644 --- a/chain/chain/src/test_utils/kv_runtime.rs +++ b/chain/chain/src/test_utils/kv_runtime.rs @@ -443,12 +443,11 @@ impl EpochManagerAdapter for MockEpochManager { } fn get_part_owner(&self, epoch_id: &EpochId, part_id: u64) -> Result { - let validators = - &self.get_epoch_block_producers_ordered(epoch_id, &CryptoHash::default())?; + let validators = &self.get_epoch_block_producers_ordered(epoch_id)?; // if we don't use data_parts and total_parts as part of the formula here, the part owner // would not depend on height, and tests wouldn't catch passing wrong height here let idx = part_id as usize + self.num_data_parts() + self.num_total_parts(); - Ok(validators[idx as usize % validators.len()].0.account_id().clone()) + Ok(validators[idx as usize % validators.len()].account_id().clone()) } fn get_block_info(&self, _hash: &CryptoHash) -> Result, EpochError> { @@ -659,16 +658,15 @@ impl EpochManagerAdapter for MockEpochManager { fn get_epoch_block_producers_ordered( &self, epoch_id: &EpochId, - _last_known_block_hash: &CryptoHash, - ) -> Result, EpochError> { + ) -> Result, EpochError> { let validators = self.get_block_producers(self.get_valset_for_epoch(epoch_id)?); - Ok(validators.iter().map(|x| (x.clone(), false)).collect()) + Ok(validators.iter().map(|x| x.clone()).collect()) } fn get_epoch_block_approvers_ordered( &self, parent_hash: &CryptoHash, - ) -> Result, EpochError> { + ) -> Result, EpochError> { let (_cur_epoch, cur_valset, next_epoch) = self.get_epoch_and_valset(*parent_hash)?; let mut validators = self .get_block_producers(cur_valset) @@ -686,7 +684,7 @@ impl EpochManagerAdapter for MockEpochManager { .map(|x| x.get_approval_stake(true)), ); } - let validators = validators.into_iter().map(|stake| (stake, false)).collect::>(); + let validators = validators.into_iter().map(|stake| stake).collect::>(); Ok(validators) } diff --git a/chain/chain/src/tests/doomslug.rs b/chain/chain/src/tests/doomslug.rs index 62ce0cc1bb0..acee6129f0e 100644 --- a/chain/chain/src/tests/doomslug.rs +++ b/chain/chain/src/tests/doomslug.rs @@ -43,7 +43,6 @@ fn one_iter( stake_next_epoch: 1, public_key: SecretKey::from_seed(KeyType::ED25519, account_id).public_key(), }) - .map(|stake| (stake, false)) .collect::>(); let signers = account_ids .iter() diff --git a/chain/chain/src/tests/garbage_collection.rs b/chain/chain/src/tests/garbage_collection.rs index 2b8a8160cc3..2da84c321ca 100644 --- a/chain/chain/src/tests/garbage_collection.rs +++ b/chain/chain/src/tests/garbage_collection.rs @@ -55,7 +55,6 @@ fn do_fork( let block = if next_epoch_id == *prev_block.header().next_epoch_id() { TestBlockBuilder::new(Clock::real(), &prev_block, signer.clone()).build() } else { - let prev_hash = prev_block.hash(); let epoch_id = *prev_block.header().next_epoch_id(); if verbose { println!( @@ -64,13 +63,9 @@ fn do_fork( prev_block.header().height() + 1 ); } - let next_bp_hash = Chain::compute_bp_hash( - chain.epoch_manager.as_ref(), - next_epoch_id, - epoch_id, - &prev_hash, - ) - .unwrap(); + let next_bp_hash = + Chain::compute_bp_hash(chain.epoch_manager.as_ref(), next_epoch_id, epoch_id) + .unwrap(); TestBlockBuilder::new(Clock::real(), &prev_block, signer.clone()) .epoch_id(epoch_id) .next_epoch_id(next_epoch_id) @@ -740,10 +735,8 @@ fn add_block( let block = if next_epoch_id == *prev_block.header().next_epoch_id() { TestBlockBuilder::new(Clock::real(), &prev_block, signer).height(height).build() } else { - let prev_hash = prev_block.hash(); let epoch_id = *prev_block.header().next_epoch_id(); - let next_bp_hash = - Chain::compute_bp_hash(epoch_manager, next_epoch_id, epoch_id, &prev_hash).unwrap(); + let next_bp_hash = Chain::compute_bp_hash(epoch_manager, next_epoch_id, epoch_id).unwrap(); TestBlockBuilder::new(Clock::real(), &prev_block, signer) .height(height) .epoch_id(epoch_id) diff --git a/chain/chunks/src/shards_manager_actor.rs b/chain/chunks/src/shards_manager_actor.rs index 8356f8a83d1..95def14da2e 100644 --- a/chain/chunks/src/shards_manager_actor.rs +++ b/chain/chunks/src/shards_manager_actor.rs @@ -581,18 +581,16 @@ impl ShardsManagerActor { let epoch_id = self.epoch_manager.get_epoch_id_from_prev_block(parent_hash).unwrap(); let block_producers = self .epoch_manager - .get_epoch_block_producers_ordered(&epoch_id, parent_hash)? + .get_epoch_block_producers_ordered(&epoch_id)? .into_iter() - .filter_map(|(validator_stake, is_slashed)| { + .filter_map(|validator_stake| { let account_id = validator_stake.take_account_id(); - if !is_slashed - && self.shard_tracker.cares_about_shard_this_or_next_epoch( - Some(&account_id), - parent_hash, - shard_id, - false, - ) - && me != Some(&account_id) + if self.shard_tracker.cares_about_shard_this_or_next_epoch( + Some(&account_id), + parent_hash, + shard_id, + false, + ) && me != Some(&account_id) { Some(account_id) } else { @@ -642,9 +640,8 @@ impl ShardsManagerActor { Some(it) => it, }; let epoch_id = self.epoch_manager.get_epoch_id_from_prev_block(prev_hash)?; - let block_producers = - self.epoch_manager.get_epoch_block_producers_ordered(&epoch_id, prev_hash)?; - for (bp, _) in block_producers { + let block_producers = self.epoch_manager.get_epoch_block_producers_ordered(&epoch_id)?; + for bp in block_producers { if bp.account_id() == me { return Ok(true); } @@ -1872,8 +1869,7 @@ impl ShardsManagerActor { ); let protocol_version = self.epoch_manager.get_epoch_protocol_version(epoch_id)?; - let block_producers = - self.epoch_manager.get_epoch_block_producers_ordered(&epoch_id, latest_block_hash)?; + let block_producers = self.epoch_manager.get_epoch_block_producers_ordered(&epoch_id)?; let current_chunk_height = partial_encoded_chunk.header.height_created(); // SingleShardTracking: If enabled, we only forward the parts to the block producers @@ -1889,7 +1885,7 @@ impl ShardsManagerActor { shard_id, })? .take_account_id(); - for (bp, _) in block_producers { + for bp in block_producers { let bp_account_id = bp.take_account_id(); if self.shard_tracker.cares_about_shard_this_or_next_epoch( @@ -1937,7 +1933,7 @@ impl ShardsManagerActor { }) .collect::, _>>()?; next_chunk_producers.remove(me); - for (bp, _) in block_producers { + for bp in block_producers { let bp_account_id = bp.take_account_id(); // no need to send anything to myself if me == &bp_account_id { diff --git a/chain/chunks/src/test_utils.rs b/chain/chunks/src/test_utils.rs index 3d56e2cd1ea..3ae13b30057 100644 --- a/chain/chunks/src/test_utils.rs +++ b/chain/chunks/src/test_utils.rs @@ -113,10 +113,10 @@ impl ChunkTestFixture { .take_account_id(); let signer = create_test_signer(mock_chunk_producer.as_str()); let validators: Vec<_> = epoch_manager - .get_epoch_block_producers_ordered(&EpochId::default(), &CryptoHash::default()) + .get_epoch_block_producers_ordered(&EpochId::default()) .unwrap() .into_iter() - .map(|v| v.0.account_id().clone()) + .map(|v| v.account_id().clone()) .collect(); let mock_shard_tracker = validators .iter() diff --git a/chain/client/src/client.rs b/chain/client/src/client.rs index aacf7e48a25..2986019f7ce 100644 --- a/chain/client/src/client.rs +++ b/chain/client/src/client.rs @@ -781,12 +781,8 @@ impl Client { .epoch_manager .get_epoch_block_approvers_ordered(&prev_hash)? .into_iter() - .map(|(ApprovalStake { account_id, .. }, is_slashed)| { - if is_slashed { - None - } else { - approvals_map.remove(&account_id).map(|x| x.0.signature.into()) - } + .map(|ApprovalStake { account_id, .. }| { + approvals_map.remove(&account_id).map(|x| x.0.signature.into()) }) .collect(); @@ -804,12 +800,7 @@ impl Client { let max_gas_price = self.chain.block_economics_config.max_gas_price(protocol_version); let next_bp_hash = if prev_epoch_id != epoch_id { - Chain::compute_bp_hash( - self.epoch_manager.as_ref(), - next_epoch_id, - epoch_id, - &prev_hash, - )? + Chain::compute_bp_hash(self.epoch_manager.as_ref(), next_epoch_id, epoch_id)? } else { prev_next_bp_hash }; @@ -2835,10 +2826,7 @@ impl Client { .or_default() .insert(cp.public_key().clone()); } - for (bp, _) in self - .epoch_manager - .get_epoch_block_producers_ordered(epoch_id, &tip.last_block_hash)? - { + for bp in self.epoch_manager.get_epoch_block_producers_ordered(epoch_id)? { account_keys .entry(bp.account_id().clone()) .or_default() diff --git a/chain/client/src/client_actor.rs b/chain/client/src/client_actor.rs index 419b83e77be..7d31d4e35a8 100644 --- a/chain/client/src/client_actor.rs +++ b/chain/client/src/client_actor.rs @@ -703,12 +703,12 @@ impl Handler for ClientActorInner { let validators: Vec = self .client .epoch_manager - .get_epoch_block_producers_ordered(&head.epoch_id, &head.last_block_hash) + .get_epoch_block_producers_ordered(&head.epoch_id) .into_chain_error()? .into_iter() - .map(|(validator_stake, is_slashed)| ValidatorInfo { + .map(|validator_stake| ValidatorInfo { account_id: validator_stake.take_account_id(), - is_slashed, + is_slashed: false, }) .collect(); diff --git a/chain/client/src/debug.rs b/chain/client/src/debug.rs index 32208467549..7d149898198 100644 --- a/chain/client/src/debug.rs +++ b/chain/client/src/debug.rs @@ -200,17 +200,16 @@ impl ClientActorInner { fn get_producers_for_epoch( &self, epoch_id: &EpochId, - last_known_block_hash: &CryptoHash, ) -> Result<(Vec, Vec), Error> { let mut block_producers_set = HashSet::new(); let block_producers: Vec = self .client .epoch_manager - .get_epoch_block_producers_ordered(epoch_id, last_known_block_hash)? + .get_epoch_block_producers_ordered(epoch_id)? .into_iter() - .map(|(validator_stake, is_slashed)| { + .map(|validator_stake| { block_producers_set.insert(validator_stake.account_id().as_str().to_owned()); - ValidatorInfo { account_id: validator_stake.take_account_id(), is_slashed } + ValidatorInfo { account_id: validator_stake.take_account_id(), is_slashed: false } }) .collect(); let chunk_only_producers = self @@ -243,8 +242,7 @@ impl ClientActorInner { let epoch_id = block.header().epoch_id(); let shard_layout = self.client.epoch_manager.get_shard_layout(&epoch_id)?; - let (validators, chunk_only_producers) = - self.get_producers_for_epoch(&epoch_id, ¤t_block)?; + let (validators, chunk_only_producers) = self.get_producers_for_epoch(&epoch_id)?; let shards_size_and_parts: Vec<(u64, u64)> = block .chunks() @@ -338,7 +336,7 @@ impl ClientActorInner { let epoch_start_height = self.client.epoch_manager.get_epoch_start_height(&head.last_block_hash)?; let (validators, chunk_only_producers) = - self.get_producers_for_epoch(&head.next_epoch_id, &head.last_block_hash)?; + self.get_producers_for_epoch(&head.next_epoch_id)?; Ok(EpochInfoView { epoch_height: self @@ -680,8 +678,8 @@ impl ClientActorInner { .iter() .map(|validator| { ( - validator.0.account_id.clone(), - (validator.0.stake_this_epoch / 10u128.pow(24)) as u64, + validator.account_id.clone(), + (validator.stake_this_epoch / 10u128.pow(24)) as u64, ) }) .collect::>() diff --git a/chain/client/src/info.rs b/chain/client/src/info.rs index be83e62940e..baa6a2c5dcb 100644 --- a/chain/client/src/info.rs +++ b/chain/client/src/info.rs @@ -168,8 +168,8 @@ impl InfoHelper { // Don't set the metric in this case. client .epoch_manager - .get_epoch_block_producers_ordered(&head.epoch_id, &head.last_block_hash) - .map_or(None, |bp| Some(bp.iter().any(|bp| bp.0.account_id() == &account_id))) + .get_epoch_block_producers_ordered(&head.epoch_id) + .map_or(None, |bp| Some(bp.iter().any(|bp| bp.account_id() == &account_id))) }) { metrics::IS_BLOCK_PRODUCER.set(if is_bp { 1 } else { 0 }); } @@ -979,7 +979,6 @@ mod tests { use near_epoch_manager::test_utils::*; use near_epoch_manager::EpochManager; use near_network::test_utils::peer_id_from_seed; - use near_primitives::hash::CryptoHash; use near_store::genesis::initialize_genesis_state; #[test] @@ -1081,7 +1080,6 @@ mod tests { "for this test, make sure number of validators are more than block producer seats" ); - let last_block_hash = CryptoHash::default(); let epoch_id = EpochId::default(); let epoch_length = 2; let num_shards = 2; @@ -1101,10 +1099,7 @@ mod tests { // First check that we have different number of block and chunk producers. assert_eq!( num_block_producer_seats, - epoch_manager_adapter - .get_epoch_block_producers_ordered(&epoch_id, &last_block_hash) - .unwrap() - .len() + epoch_manager_adapter.get_epoch_block_producers_ordered(&epoch_id).unwrap().len() ); assert_eq!( num_validators, diff --git a/chain/client/src/view_client_actor.rs b/chain/client/src/view_client_actor.rs index 04eaabc7377..c89f7805b11 100644 --- a/chain/client/src/view_client_actor.rs +++ b/chain/client/src/view_client_actor.rs @@ -908,11 +908,7 @@ impl Handler for ViewClientActorInner { .with_label_values(&["GetValidatorOrdered"]) .start_timer(); Ok(self.maybe_block_id_to_block_header(msg.block_id).and_then(|header| { - get_epoch_block_producers_view( - header.epoch_id(), - header.prev_hash(), - self.epoch_manager.as_ref(), - ) + get_epoch_block_producers_view(header.epoch_id(), self.epoch_manager.as_ref()) })?) } } diff --git a/chain/epoch-manager/src/adapter.rs b/chain/epoch-manager/src/adapter.rs index 5cc37519665..12d721b2e71 100644 --- a/chain/epoch-manager/src/adapter.rs +++ b/chain/epoch-manager/src/adapter.rs @@ -189,31 +189,55 @@ pub trait EpochManagerAdapter: Send + Sync { fn get_epoch_block_producers_ordered( &self, epoch_id: &EpochId, - last_known_block_hash: &CryptoHash, - ) -> Result, EpochError>; + ) -> Result, EpochError>; fn get_epoch_block_approvers_ordered( &self, parent_hash: &CryptoHash, - ) -> Result, EpochError>; + ) -> Result, EpochError>; /// Returns all the chunk producers for a given epoch. + /// Note: overwritten in EpochManagerHandler to apply caching fn get_epoch_chunk_producers( &self, epoch_id: &EpochId, - ) -> Result, EpochError>; + ) -> Result, EpochError> { + let mut producers: HashSet = HashSet::default(); + // Collect unique chunk producers. + let epoch_info = self.get_epoch_info(epoch_id)?; + for chunk_producers in epoch_info.chunk_producers_settlement() { + producers.extend(chunk_producers); + } + Ok(producers.iter().map(|producer_id| epoch_info.get_validator(*producer_id)).collect()) + } + /// Returns AccountIds of chunk producers that are assigned to a given shard-id in a given epoch. fn get_epoch_chunk_producers_for_shard( &self, epoch_id: &EpochId, shard_id: ShardId, - ) -> Result, EpochError>; + ) -> Result, EpochError> { + let epoch_info = self.get_epoch_info(&epoch_id)?; + let shard_layout = self.get_shard_layout(&epoch_id)?; + let shard_index = shard_layout.get_shard_index(shard_id)?; + + let chunk_producers_settlement = epoch_info.chunk_producers_settlement(); + let chunk_producers = chunk_producers_settlement + .get(shard_index) + .ok_or_else(|| EpochError::ShardingError(format!("invalid shard id {shard_id}")))?; + Ok(chunk_producers + .iter() + .map(|index| epoch_info.validator_account_id(*index).clone()) + .collect()) + } /// Returns all validators for a given epoch. fn get_epoch_all_validators( &self, epoch_id: &EpochId, - ) -> Result, EpochError>; + ) -> Result, EpochError> { + Ok(self.get_epoch_info(epoch_id)?.validators_iter().collect::>()) + } /// Block producers for given height for the main block. Return EpochError if outside of known boundaries. /// TODO: Deprecate in favour of get_block_producer_info @@ -221,28 +245,67 @@ pub trait EpochManagerAdapter: Send + Sync { &self, epoch_id: &EpochId, height: BlockHeight, - ) -> Result; + ) -> Result { + self.get_block_producer_info(epoch_id, height).map(|validator| validator.take_account_id()) + } /// Block producers and stake for given height for the main block. Return EpochError if outside of known boundaries. fn get_block_producer_info( &self, epoch_id: &EpochId, height: BlockHeight, - ) -> Result; + ) -> Result { + let epoch_info = self.get_epoch_info(epoch_id)?; + let validator_id = epoch_info.sample_block_producer(height); + Ok(epoch_info.get_validator(validator_id)) + } /// Chunk producer info for given height for given shard. Return EpochError if outside of known boundaries. fn get_chunk_producer_info( &self, key: &ChunkProductionKey, - ) -> Result; + ) -> Result { + let epoch_info = self.get_epoch_info(&key.epoch_id)?; + let shard_layout = self.get_shard_layout(&key.epoch_id)?; + let Some(validator_id) = + epoch_info.sample_chunk_producer(&shard_layout, key.shard_id, key.height_created) + else { + return Err(EpochError::ChunkProducerSelectionError(format!( + "Invalid shard {} for height {}", + key.shard_id, key.height_created, + ))); + }; + Ok(epoch_info.get_validator(validator_id)) + } /// Gets the chunk validators for a given height and shard. + /// Note: overwritten in EpochManagerHandler to apply caching fn get_chunk_validator_assignments( &self, epoch_id: &EpochId, shard_id: ShardId, height: BlockHeight, - ) -> Result, EpochError>; + ) -> Result, EpochError> { + let epoch_info = self.get_epoch_info(epoch_id)?; + let shard_layout = self.get_shard_layout(epoch_id)?; + let chunk_validators_per_shard = epoch_info.sample_chunk_validators(height); + for (shard_index, chunk_validators) in chunk_validators_per_shard.into_iter().enumerate() { + let cur_shard_id = shard_layout.get_shard_id(shard_index)?; + if cur_shard_id != shard_id { + continue; + } + let chunk_validators = chunk_validators + .into_iter() + .map(|(validator_id, assignment_weight)| { + (epoch_info.get_validator(validator_id).take_account_id(), assignment_weight) + }) + .collect(); + return Ok(Arc::new(ChunkValidatorAssignments::new(chunk_validators))); + } + Err(EpochError::ChunkValidatorSelectionError(format!( + "Invalid shard ID {shard_id} for height {height}, epoch {epoch_id:?} for chunk validation", + ))) + } fn get_validator_by_account_id( &self, @@ -261,7 +324,7 @@ pub trait EpochManagerAdapter: Send + Sync { /// it for "production" code. fn get_validator_info( &self, - epoch_id: ValidatorInfoIdentifier, + epoch_identifier: ValidatorInfoIdentifier, ) -> Result; fn add_validator_proposals( @@ -271,8 +334,12 @@ pub trait EpochManagerAdapter: Send + Sync { ) -> Result; /// Epoch active protocol version. - fn get_epoch_protocol_version(&self, epoch_id: &EpochId) - -> Result; + fn get_epoch_protocol_version( + &self, + epoch_id: &EpochId, + ) -> Result { + self.get_epoch_info(epoch_id).map(|info| info.protocol_version()) + } /// Get protocol version of next epoch. fn get_next_epoch_protocol_version( @@ -291,7 +358,6 @@ pub trait EpochManagerAdapter: Send + Sync { } // TODO #3488 this likely to be updated - fn is_chunk_producer_for_epoch( &self, epoch_id: &EpochId, @@ -436,7 +502,76 @@ pub trait EpochManagerAdapter: Send + Sync { &self, tip: &Tip, height: BlockHeight, - ) -> Result, EpochError>; + ) -> Result, EpochError> { + // If the tip is at the genesis block, it has to be handled in a special way. + // For genesis block, epoch_first_block() is the dummy block (11111...) + // with height 0, which could cause issues with estimating the epoch end + // if the genesis height is nonzero. It's easier to handle it manually. + if tip.prev_block_hash == CryptoHash::default() { + if tip.height == height { + return Ok(vec![tip.epoch_id]); + } + + if height > tip.height { + return Ok(vec![tip.next_epoch_id]); + } + + return Ok(vec![]); + } + + // See if the height is in the current epoch + let current_epoch_first_block_hash = + *self.get_block_info(&tip.last_block_hash)?.epoch_first_block(); + let current_epoch_first_block_info = + self.get_block_info(¤t_epoch_first_block_hash)?; + + let current_epoch_start = current_epoch_first_block_info.height(); + let current_epoch_length = self.get_epoch_config(&tip.epoch_id)?.epoch_length; + let current_epoch_estimated_end = current_epoch_start.saturating_add(current_epoch_length); + + // All blocks with height lower than the estimated end are guaranteed to reside in the current epoch. + // The situation is clear here. + if (current_epoch_start..current_epoch_estimated_end).contains(&height) { + return Ok(vec![tip.epoch_id]); + } + + // If the height is higher than the current epoch's estimated end, then it's + // not clear in which epoch it'll be. Under normal circumstances it would be + // in the next epoch, but with missing blocks the current epoch could stretch out + // past its estimated end, so the height might end up being in the current epoch, + // even though its height is higher than the estimated end. + if height >= current_epoch_estimated_end { + return Ok(vec![tip.epoch_id, tip.next_epoch_id]); + } + + // Finally try the previous epoch. + // First and last blocks of the previous epoch are already known, so the situation is clear. + let prev_epoch_last_block_hash = current_epoch_first_block_info.prev_hash(); + let prev_epoch_last_block_info = self.get_block_info(prev_epoch_last_block_hash)?; + let prev_epoch_first_block_info = + self.get_block_info(prev_epoch_last_block_info.epoch_first_block())?; + + // If the current epoch is the epoch after genesis, then the previous + // epoch contains only the genesis block. This case has to be handled separately + // because epoch_first_block() points to the dummy block (1111..), which has height 0. + if tip.epoch_id == EpochId(CryptoHash::default()) { + let genesis_block_info = prev_epoch_last_block_info; + if height == genesis_block_info.height() { + return Ok(vec![*genesis_block_info.epoch_id()]); + } else { + return Ok(vec![]); + } + } + + if (prev_epoch_first_block_info.height()..=prev_epoch_last_block_info.height()) + .contains(&height) + { + return Ok(vec![*prev_epoch_last_block_info.epoch_id()]); + } + + // The height doesn't belong to any of the epochs around the tip, return an empty Vec. + Ok(vec![]) + } /// Returns the list of ShardUIds in the current shard layout that will be /// resharded in the future within this client. Those shards should be @@ -696,16 +831,15 @@ impl EpochManagerAdapter for EpochManagerHandle { fn get_epoch_block_producers_ordered( &self, epoch_id: &EpochId, - last_known_block_hash: &CryptoHash, - ) -> Result, EpochError> { + ) -> Result, EpochError> { let epoch_manager = self.read(); - Ok(epoch_manager.get_all_block_producers_ordered(epoch_id, last_known_block_hash)?.to_vec()) + Ok(epoch_manager.get_all_block_producers_ordered(epoch_id)?.to_vec()) } fn get_epoch_block_approvers_ordered( &self, parent_hash: &CryptoHash, - ) -> Result, EpochError> { + ) -> Result, EpochError> { let current_epoch_id = self.get_epoch_id_from_prev_block(parent_hash)?; let next_epoch_id = self.get_next_epoch_id_from_prev_block(parent_hash)?; let epoch_manager = self.read(); @@ -720,39 +854,6 @@ impl EpochManagerAdapter for EpochManagerHandle { Ok(epoch_manager.get_all_chunk_producers(epoch_id)?.to_vec()) } - fn get_epoch_chunk_producers_for_shard( - &self, - epoch_id: &EpochId, - shard_id: ShardId, - ) -> Result, EpochError> { - let epoch_manager = self.read(); - epoch_manager.get_epoch_chunk_producers_for_shard(epoch_id, shard_id) - } - - fn get_block_producer( - &self, - epoch_id: &EpochId, - height: BlockHeight, - ) -> Result { - self.get_block_producer_info(epoch_id, height).map(|validator| validator.take_account_id()) - } - - fn get_block_producer_info( - &self, - epoch_id: &EpochId, - height: BlockHeight, - ) -> Result { - let epoch_manager = self.read(); - Ok(epoch_manager.get_block_producer_info(epoch_id, height)?) - } - - fn get_chunk_producer_info( - &self, - key: &ChunkProductionKey, - ) -> Result { - self.read().get_chunk_producer_info(key) - } - fn get_chunk_validator_assignments( &self, epoch_id: &EpochId, @@ -782,14 +883,6 @@ impl EpochManagerAdapter for EpochManagerHandle { epoch_manager.add_validator_proposals(block_info, random_value) } - fn get_epoch_protocol_version( - &self, - epoch_id: &EpochId, - ) -> Result { - let epoch_manager = self.read(); - Ok(epoch_manager.get_epoch_info(epoch_id)?.protocol_version()) - } - fn init_after_epoch_sync( &self, store_update: &mut StoreUpdate, @@ -817,22 +910,4 @@ impl EpochManagerAdapter for EpochManagerHandle { next_epoch_info, ) } - - fn possible_epochs_of_height_around_tip( - &self, - tip: &Tip, - height: BlockHeight, - ) -> Result, EpochError> { - let epoch_manager = self.read(); - epoch_manager.possible_epochs_of_height_around_tip(tip, height) - } - - /// Returns the set of chunk validators for a given epoch - fn get_epoch_all_validators( - &self, - epoch_id: &EpochId, - ) -> Result, EpochError> { - let epoch_manager = self.read(); - Ok(epoch_manager.get_epoch_info(epoch_id)?.validators_iter().collect::>()) - } } diff --git a/chain/epoch-manager/src/lib.rs b/chain/epoch-manager/src/lib.rs index 16b1f855d6d..422d7e7cd89 100644 --- a/chain/epoch-manager/src/lib.rs +++ b/chain/epoch-manager/src/lib.rs @@ -14,7 +14,6 @@ use near_primitives::errors::EpochError; use near_primitives::hash::CryptoHash; use near_primitives::shard_layout::ShardLayout; use near_primitives::stateless_validation::validator_assignment::ChunkValidatorAssignments; -use near_primitives::stateless_validation::ChunkProductionKey; use near_primitives::types::validator_stake::ValidatorStake; use near_primitives::types::{ AccountId, ApprovalStake, Balance, BlockChunkValidatorStats, BlockHeight, ChunkStats, EpochId, @@ -150,9 +149,9 @@ pub struct EpochManager { /// Cache of epoch id to epoch start height epoch_id_to_start: SyncLruCache, /// Epoch validators ordered by `block_producer_settlement`. - epoch_validators_ordered: SyncLruCache>, + epoch_validators_ordered: SyncLruCache>, /// Unique validators ordered by `block_producer_settlement`. - epoch_validators_ordered_unique: SyncLruCache>, + epoch_validators_ordered_unique: SyncLruCache>, /// Unique chunk producers. epoch_chunk_producers_unique: SyncLruCache>, @@ -949,55 +948,33 @@ impl EpochManager { Ok(store_update) } - /// Given epoch id and height, returns validator information that suppose to produce - /// the block at that height. We don't require caller to know about EpochIds. - pub fn get_block_producer_info( - &self, - epoch_id: &EpochId, - height: BlockHeight, - ) -> Result { - let epoch_info = self.get_epoch_info(epoch_id)?; - let validator_id = epoch_info.sample_block_producer(height); - Ok(epoch_info.get_validator(validator_id)) - } - - /// Returns settlement of all block producers in current epoch, with indicator on whether they are slashed or not. + /// Returns settlement of all block producers in current epoch pub fn get_all_block_producers_settlement( &self, epoch_id: &EpochId, - last_known_block_hash: &CryptoHash, - ) -> Result, EpochError> { - // TODO(3674): Revisit this when we enable slashing + ) -> Result, EpochError> { self.epoch_validators_ordered.get_or_try_put(*epoch_id, |epoch_id| { - let block_info = self.get_block_info(last_known_block_hash)?; let epoch_info = self.get_epoch_info(epoch_id)?; let result = epoch_info .block_producers_settlement() .iter() - .map(|&validator_id| { - let validator_stake = epoch_info.get_validator(validator_id); - let is_slashed = - block_info.slashed().contains_key(validator_stake.account_id()); - (validator_stake, is_slashed) - }) + .map(|&validator_id| epoch_info.get_validator(validator_id)) .collect(); Ok(result) }) } - /// Returns all unique block producers in current epoch sorted by account_id, with indicator on whether they are slashed or not. + /// Returns all unique block producers in current epoch sorted by account_id. pub fn get_all_block_producers_ordered( &self, epoch_id: &EpochId, - last_known_block_hash: &CryptoHash, - ) -> Result, EpochError> { + ) -> Result, EpochError> { self.epoch_validators_ordered_unique.get_or_try_put(*epoch_id, |epoch_id| { - let settlement = - self.get_all_block_producers_settlement(epoch_id, last_known_block_hash)?; + let settlement = self.get_all_block_producers_settlement(epoch_id)?; let mut validators: HashSet = HashSet::default(); let result = settlement .iter() - .filter(|(validator_stake, _is_slashed)| { + .filter(|validator_stake| { let account_id = validator_stake.account_id(); validators.insert(account_id.clone()) }) @@ -1025,27 +1002,6 @@ impl EpochManager { }) } - /// Returns AccountIds of chunk producers that are assigned to a given shard-id in a given epoch. - pub fn get_epoch_chunk_producers_for_shard( - &self, - epoch_id: &EpochId, - shard_id: ShardId, - ) -> Result, EpochError> { - let epoch_info = self.get_epoch_info(&epoch_id)?; - - let shard_layout = self.get_shard_layout(&epoch_id)?; - let shard_index = shard_layout.get_shard_index(shard_id)?; - - let chunk_producers_settlement = epoch_info.chunk_producers_settlement(); - let chunk_producers = chunk_producers_settlement - .get(shard_index) - .ok_or_else(|| EpochError::ShardingError(format!("invalid shard id {shard_id}")))?; - Ok(chunk_producers - .iter() - .map(|index| epoch_info.validator_account_id(*index).clone()) - .collect()) - } - /// Returns the list of chunk_validators for the given shard_id and height and set of account ids. /// Generation of chunk_validators and their order is deterministic for given shard_id and height. /// We cache the generated chunk_validators. @@ -1089,36 +1045,30 @@ impl EpochManager { parent_hash: &CryptoHash, current_epoch_id: EpochId, next_epoch_id: EpochId, - ) -> Result, EpochError> { - let mut settlement = - self.get_all_block_producers_settlement(¤t_epoch_id, parent_hash)?.to_vec(); + ) -> Result, EpochError> { + let mut settlement = self.get_all_block_producers_settlement(¤t_epoch_id)?.to_vec(); let settlement_epoch_boundary = settlement.len(); let block_info = self.get_block_info(parent_hash)?; if self.next_block_need_approvals_from_next_epoch(&block_info)? { - settlement.extend( - self.get_all_block_producers_settlement(&next_epoch_id, parent_hash)? - .iter() - .cloned(), - ); + settlement + .extend(self.get_all_block_producers_settlement(&next_epoch_id)?.iter().cloned()); } let mut result = vec![]; let mut validators: HashMap = HashMap::default(); - for (ord, (validator_stake, is_slashed)) in settlement.into_iter().enumerate() { + for (ord, validator_stake) in settlement.into_iter().enumerate() { let account_id = validator_stake.account_id(); match validators.get(account_id) { None => { validators.insert(account_id.clone(), result.len()); - result.push(( - validator_stake.get_approval_stake(ord >= settlement_epoch_boundary), - is_slashed, - )); + result + .push(validator_stake.get_approval_stake(ord >= settlement_epoch_boundary)); } Some(old_ord) => { if ord >= settlement_epoch_boundary { - result[*old_ord].0.stake_next_epoch = validator_stake.stake(); + result[*old_ord].stake_next_epoch = validator_stake.stake(); }; } }; @@ -1126,24 +1076,6 @@ impl EpochManager { Ok(result) } - /// For given epoch_id, height and shard_id returns validator that is chunk producer. - pub fn get_chunk_producer_info( - &self, - key: &ChunkProductionKey, - ) -> Result { - let ChunkProductionKey { epoch_id, shard_id, height_created } = key; - let epoch_info = self.get_epoch_info(epoch_id)?; - let shard_layout = self.get_shard_layout(epoch_id)?; - let validator_id = epoch_info - .sample_chunk_producer(&shard_layout, *shard_id, *height_created) - .ok_or_else(|| { - EpochError::ChunkProducerSelectionError(format!( - "Invalid shard {shard_id} for height {height_created}" - )) - })?; - Ok(epoch_info.get_validator(validator_id)) - } - /// Returns validator for given account id for given epoch. /// We don't require caller to know about EpochIds. Doesn't account for slashing. pub fn get_validator_by_account_id( @@ -1946,81 +1878,4 @@ impl EpochManager { Ok(None) } } - - pub fn possible_epochs_of_height_around_tip( - &self, - tip: &Tip, - height: BlockHeight, - ) -> Result, EpochError> { - // If the tip is at the genesis block, it has to be handled in a special way. - // For genesis block, epoch_first_block() is the dummy block (11111...) - // with height 0, which could cause issues with estimating the epoch end - // if the genesis height is nonzero. It's easier to handle it manually. - if tip.prev_block_hash == CryptoHash::default() { - if tip.height == height { - return Ok(vec![tip.epoch_id]); - } - - if height > tip.height { - return Ok(vec![tip.next_epoch_id]); - } - - return Ok(vec![]); - } - - // See if the height is in the current epoch - let current_epoch_first_block_hash = - *self.get_block_info(&tip.last_block_hash)?.epoch_first_block(); - let current_epoch_first_block_info = - self.get_block_info(¤t_epoch_first_block_hash)?; - - let current_epoch_start = current_epoch_first_block_info.height(); - let current_epoch_length = self - .get_epoch_config(self.get_epoch_info(&tip.epoch_id)?.protocol_version()) - .epoch_length; - let current_epoch_estimated_end = current_epoch_start.saturating_add(current_epoch_length); - - // All blocks with height lower than the estimated end are guaranteed to reside in the current epoch. - // The situation is clear here. - if (current_epoch_start..current_epoch_estimated_end).contains(&height) { - return Ok(vec![tip.epoch_id]); - } - - // If the height is higher than the current epoch's estimated end, then it's - // not clear in which epoch it'll be. Under normal circumstances it would be - // in the next epoch, but with missing blocks the current epoch could stretch out - // past its estimated end, so the height might end up being in the current epoch, - // even though its height is higher than the estimated end. - if height >= current_epoch_estimated_end { - return Ok(vec![tip.epoch_id, tip.next_epoch_id]); - } - - // Finally try the previous epoch. - // First and last blocks of the previous epoch are already known, so the situation is clear. - let prev_epoch_last_block_hash = current_epoch_first_block_info.prev_hash(); - let prev_epoch_last_block_info = self.get_block_info(prev_epoch_last_block_hash)?; - let prev_epoch_first_block_info = - self.get_block_info(prev_epoch_last_block_info.epoch_first_block())?; - - // If the current epoch is the epoch after genesis, then the previous - // epoch contains only the genesis block. This case has to be handled separately - // because epoch_first_block() points to the dummy block (1111..), which has height 0. - if tip.epoch_id == EpochId(CryptoHash::default()) { - let genesis_block_info = prev_epoch_last_block_info; - if height == genesis_block_info.height() { - return Ok(vec![*genesis_block_info.epoch_id()]); - } else { - return Ok(vec![]); - } - } - - if (prev_epoch_first_block_info.height()..=prev_epoch_last_block_info.height()) - .contains(&height) - { - return Ok(vec![*prev_epoch_last_block_info.epoch_id()]); - } - - // The height doesn't belong to any of the epochs around the tip, return an empty Vec. - Ok(vec![]) - } } diff --git a/chain/epoch-manager/src/test_utils.rs b/chain/epoch-manager/src/test_utils.rs index 002a666beb6..6415180ac17 100644 --- a/chain/epoch-manager/src/test_utils.rs +++ b/chain/epoch-manager/src/test_utils.rs @@ -299,9 +299,8 @@ pub fn setup_epoch_manager_with_block_and_chunk_producers( ) .unwrap(); // Sanity check that the election results are indeed as expected. - let actual_block_producers = epoch_manager - .get_all_block_producers_ordered(&EpochId::default(), &CryptoHash::default()) - .unwrap(); + let actual_block_producers = + epoch_manager.get_all_block_producers_ordered(&EpochId::default()).unwrap(); assert_eq!(actual_block_producers.len(), block_producers.len()); let actual_chunk_producers = epoch_manager.get_all_chunk_producers(&EpochId::default()).unwrap(); diff --git a/chain/epoch-manager/src/tests/mod.rs b/chain/epoch-manager/src/tests/mod.rs index b2f34532d2b..377ef465f30 100644 --- a/chain/epoch-manager/src/tests/mod.rs +++ b/chain/epoch-manager/src/tests/mod.rs @@ -24,6 +24,7 @@ use near_primitives::shard_layout::ShardLayout; use near_primitives::sharding::{ShardChunkHeader, ShardChunkHeaderV3}; use near_primitives::stateless_validation::chunk_endorsements_bitmap::ChunkEndorsementsBitmap; use near_primitives::stateless_validation::partial_witness::PartialEncodedStateWitness; +use near_primitives::stateless_validation::ChunkProductionKey; use near_primitives::types::AccountInfo; use near_primitives::types::ValidatorKickoutReason::{ NotEnoughBlocks, NotEnoughChunkEndorsements, NotEnoughChunks, @@ -35,27 +36,6 @@ use near_store::test_utils::create_test_store; use near_store::ShardUId; use num_rational::Ratio; -impl EpochManager { - /// Returns number of produced and expected blocks by given validator. - fn get_num_validator_blocks( - &mut self, - epoch_id: &EpochId, - last_known_block_hash: &CryptoHash, - account_id: &AccountId, - ) -> Result { - let epoch_info = self.get_epoch_info(epoch_id)?; - let validator_id = *epoch_info - .get_validator_id(account_id) - .ok_or_else(|| EpochError::NotAValidator(account_id.clone(), *epoch_id))?; - let aggregator = self.get_epoch_info_aggregator_upto_last(last_known_block_hash)?; - Ok(aggregator - .block_tracker - .get(&validator_id) - .unwrap_or(&ValidatorStats { produced: 0, expected: 0 }) - .clone()) - } -} - #[test] fn test_stake_validator() { let amount_staked = 1_000_000; @@ -240,32 +220,26 @@ fn test_fork_finalization() { let epoch1 = epoch_manager.get_epoch_id(&h[1]).unwrap(); let mut bps = epoch_manager .read() - .get_all_block_producers_ordered(&epoch1, &h[1]) + .get_all_block_producers_ordered(&epoch1) .unwrap() .iter() - .map(|x| (x.0.account_id().clone(), x.1)) + .map(|x| x.account_id().clone()) .collect::>(); bps.sort_unstable(); - assert_eq!( - bps, - vec![ - ("test1".parse().unwrap(), false), - ("test2".parse().unwrap(), false), - ("test3".parse().unwrap(), false) - ] - ); - + let expected_bps: Vec = + vec!["test1".parse().unwrap(), "test2".parse().unwrap(), "test3".parse().unwrap()]; + assert_eq!(bps, expected_bps); let last_block = blocks_test2.last().unwrap(); let epoch2_1 = epoch_manager.get_epoch_id(last_block).unwrap(); assert_eq!( epoch_manager .read() - .get_all_block_producers_ordered(&epoch2_1, &h[1]) + .get_all_block_producers_ordered(&epoch2_1) .unwrap() .iter() - .map(|x| (x.0.account_id().clone(), x.1)) + .map(|x| x.account_id().clone()) .collect::>(), - vec![("test2".parse().unwrap(), false), ("test4".parse().unwrap(), false)] + vec!["test2".parse::().unwrap(), "test4".parse().unwrap()] ); let last_block = blocks_test1.last().unwrap(); @@ -273,12 +247,12 @@ fn test_fork_finalization() { assert_eq!( epoch_manager .read() - .get_all_block_producers_ordered(&epoch2_2, &h[1]) + .get_all_block_producers_ordered(&epoch2_2) .unwrap() .iter() - .map(|x| (x.0.account_id().clone(), x.1)) + .map(|x| x.account_id().clone()) .collect::>(), - vec![("test1".parse().unwrap(), false), ("test3".parse().unwrap(), false),] + vec!["test1".parse::().unwrap(), "test3".parse().unwrap(),] ); // Check that if we have a different epoch manager and apply only second branch we get the same results. @@ -467,13 +441,13 @@ fn test_slashing() { let epoch_id = epoch_manager.get_epoch_id(&h[1]).unwrap(); let mut bps = epoch_manager - .get_all_block_producers_ordered(&epoch_id, &h[1]) + .get_all_block_producers_ordered(&epoch_id) .unwrap() .iter() - .map(|x| (x.0.account_id().clone(), x.1)) + .map(|x| x.account_id().clone()) .collect::>(); bps.sort_unstable(); - assert_eq!(bps, vec![("test1".parse().unwrap(), true), ("test2".parse().unwrap(), false)]); + assert_eq!(bps, vec!["test1".parse::().unwrap(), "test2".parse().unwrap()]); record_block(&mut epoch_manager, h[1], h[2], 2, vec![]); record_block(&mut epoch_manager, h[2], h[3], 3, vec![]); @@ -1428,7 +1402,7 @@ fn test_epoch_info_aggregator_reorg_beginning_of_epoch() { } fn count_missing_blocks( - epoch_manager: &EpochManager, + epoch_manager: &dyn EpochManagerAdapter, epoch_id: &EpochId, height_range: std::ops::Range, produced_heights: &[u64], @@ -1447,47 +1421,66 @@ fn count_missing_blocks( result } +fn get_num_validator_blocks( + em_handle: &EpochManagerHandle, + epoch_id: &EpochId, + last_known_block_hash: &CryptoHash, + account_id: &AccountId, +) -> Result { + let epoch_info = em_handle.get_epoch_info(epoch_id)?; + let validator_id = *epoch_info + .get_validator_id(account_id) + .ok_or_else(|| EpochError::NotAValidator(account_id.clone(), *epoch_id))?; + let aggregator = em_handle.read().get_epoch_info_aggregator_upto_last(last_known_block_hash)?; + Ok(aggregator + .block_tracker + .get(&validator_id) + .unwrap_or(&ValidatorStats { produced: 0, expected: 0 }) + .clone()) +} + #[test] fn test_num_missing_blocks() { let stake_amount = 1_000_000; let validators = vec![("test1".parse().unwrap(), stake_amount), ("test2".parse().unwrap(), stake_amount)]; let epoch_length = 2; - let mut em = - setup_epoch_manager(validators, epoch_length, 1, 2, 10, 10, 0, default_reward_calculator()); + let em = + setup_epoch_manager(validators, epoch_length, 1, 2, 10, 10, 0, default_reward_calculator()) + .into_handle(); let h = hash_range(8); - record_block(&mut em, Default::default(), h[0], 0, vec![]); - record_block(&mut em, h[0], h[1], 1, vec![]); - record_block(&mut em, h[1], h[3], 3, vec![]); + record_block(&mut em.write(), Default::default(), h[0], 0, vec![]); + record_block(&mut em.write(), h[0], h[1], 1, vec![]); + record_block(&mut em.write(), h[1], h[3], 3, vec![]); let epoch_id = em.get_epoch_id(&h[1]).unwrap(); assert_eq!( - em.get_num_validator_blocks(&epoch_id, &h[3], &"test1".parse().unwrap()).unwrap(), - count_missing_blocks(&mut em, &epoch_id, 1..4, &[1, 3], "test1"), + get_num_validator_blocks(&em, &epoch_id, &h[3], &"test1".parse().unwrap()).unwrap(), + count_missing_blocks(&em, &epoch_id, 1..4, &[1, 3], "test1"), ); assert_eq!( - em.get_num_validator_blocks(&epoch_id, &h[3], &"test2".parse().unwrap()).unwrap(), - count_missing_blocks(&mut em, &epoch_id, 1..4, &[1, 3], "test2"), + get_num_validator_blocks(&em, &epoch_id, &h[3], &"test2".parse().unwrap()).unwrap(), + count_missing_blocks(&em, &epoch_id, 1..4, &[1, 3], "test2"), ); // Build chain 0 <- x <- x <- x <- ( 4 <- 5 ) <- x <- 7 - record_block(&mut em, h[0], h[4], 4, vec![]); + record_block(&mut em.write(), h[0], h[4], 4, vec![]); let epoch_id = em.get_epoch_id(&h[4]).unwrap(); // Block 4 is first block after genesis and starts new epoch, but we actually count how many missed blocks have happened since block 0. assert_eq!( - em.get_num_validator_blocks(&epoch_id, &h[4], &"test1".parse().unwrap()).unwrap(), - count_missing_blocks(&mut em, &epoch_id, 1..5, &[4], "test1"), + get_num_validator_blocks(&em, &epoch_id, &h[4], &"test1".parse().unwrap()).unwrap(), + count_missing_blocks(&em, &epoch_id, 1..5, &[4], "test1"), ); assert_eq!( - em.get_num_validator_blocks(&epoch_id, &h[4], &"test2".parse().unwrap()).unwrap(), - count_missing_blocks(&mut em, &epoch_id, 1..5, &[4], "test2"), + get_num_validator_blocks(&em, &epoch_id, &h[4], &"test2".parse().unwrap()).unwrap(), + count_missing_blocks(&em, &epoch_id, 1..5, &[4], "test2"), ); - record_block(&mut em, h[4], h[5], 5, vec![]); - record_block(&mut em, h[5], h[7], 7, vec![]); + record_block(&mut em.write(), h[4], h[5], 5, vec![]); + record_block(&mut em.write(), h[5], h[7], 7, vec![]); let epoch_id = em.get_epoch_id(&h[7]).unwrap(); // The next epoch started after 5 with 6, and test2 missed their slot from perspective of block 7. assert_eq!( - em.get_num_validator_blocks(&epoch_id, &h[7], &"test2".parse().unwrap()).unwrap(), - count_missing_blocks(&mut em, &epoch_id, 6..8, &[7], "test2"), + get_num_validator_blocks(&em, &epoch_id, &h[7], &"test2".parse().unwrap()).unwrap(), + count_missing_blocks(&em, &epoch_id, 6..8, &[7], "test2"), ); } @@ -2520,14 +2513,14 @@ fn test_epoch_validators_cache() { let epoch_id = EpochId(h[2]); let epoch_validators = - epoch_manager.get_all_block_producers_settlement(&epoch_id, &h[3]).unwrap().to_vec(); + epoch_manager.get_all_block_producers_settlement(&epoch_id).unwrap().to_vec(); assert_eq!(epoch_manager.epoch_validators_ordered.len(), 1); let epoch_validators_in_cache = epoch_manager.epoch_validators_ordered.get(&epoch_id).unwrap(); assert_eq!(*epoch_validators, *epoch_validators_in_cache); assert_eq!(epoch_manager.epoch_validators_ordered_unique.len(), 0); let epoch_validators_unique = - epoch_manager.get_all_block_producers_ordered(&epoch_id, &h[3]).unwrap().to_vec(); + epoch_manager.get_all_block_producers_ordered(&epoch_id).unwrap().to_vec(); let epoch_validators_unique_in_cache = epoch_manager.epoch_validators_ordered_unique.get(&epoch_id).unwrap(); assert_eq!(*epoch_validators_unique, *epoch_validators_unique_in_cache); @@ -2557,10 +2550,10 @@ fn test_chunk_producers() { let epoch_id = EpochId(h[2]); let block_producers = epoch_manager - .get_all_block_producers_settlement(&epoch_id, &h[4]) + .get_all_block_producers_settlement(&epoch_id) .unwrap() .iter() - .map(|(stake, _)| stake.account_id().to_string()) + .map(|stake| stake.account_id().to_string()) .collect::>(); assert_eq!(vec!(String::from("test1"), String::from("test2")), block_producers); @@ -3436,11 +3429,12 @@ fn test_possible_epochs_of_height_around_tip() { let genesis_epoch = EpochId(CryptoHash::default()); let epoch_length = 5; - let mut epoch_manager = setup_default_epoch_manager(validators, epoch_length, 1, 2, 90, 60); + let epoch_manager = + setup_default_epoch_manager(validators, epoch_length, 1, 2, 90, 60).into_handle(); // Add the genesis block with height 1000 let genesis_height = 1000; - record_block(&mut epoch_manager, CryptoHash::default(), h[0], genesis_height, vec![]); + record_block(&mut epoch_manager.write(), CryptoHash::default(), h[0], genesis_height, vec![]); let genesis_tip = Tip { height: genesis_height, @@ -3482,7 +3476,7 @@ fn test_possible_epochs_of_height_around_tip() { for i in 1..=5 { let height = genesis_height + i as BlockHeight; tracing::info!(target: "test", height); - record_block(&mut epoch_manager, h[i - 1], h[i], height, vec![]); + record_block(&mut epoch_manager.write(), h[i - 1], h[i], height, vec![]); let tip = Tip { height, last_block_hash: h[i], @@ -3524,7 +3518,7 @@ fn test_possible_epochs_of_height_around_tip() { for i in 6..=10 { let height = genesis_height + i as BlockHeight; tracing::info!(target: "test", height); - record_block(&mut epoch_manager, h[i - 1], h[i], height, vec![]); + record_block(&mut epoch_manager.write(), h[i - 1], h[i], height, vec![]); let tip = Tip { height, last_block_hash: h[i], @@ -3584,7 +3578,7 @@ fn test_possible_epochs_of_height_around_tip() { vec![], DEFAULT_TOTAL_SUPPLY, ); - epoch_manager.record_block_info(block_info, [0; 32]).unwrap().commit().unwrap(); + epoch_manager.write().record_block_info(block_info, [0; 32]).unwrap().commit().unwrap(); let tip = Tip { height, last_block_hash: h[i], @@ -3647,7 +3641,7 @@ fn test_possible_epochs_of_height_around_tip() { vec![], DEFAULT_TOTAL_SUPPLY, ); - epoch_manager.record_block_info(block_info, [0; 32]).unwrap().commit().unwrap(); + epoch_manager.write().record_block_info(block_info, [0; 32]).unwrap().commit().unwrap(); let tip = Tip { height, last_block_hash: h[i], @@ -3700,7 +3694,7 @@ fn test_possible_epochs_of_height_around_tip() { for i in 27..=31 { let height = genesis_height + i as BlockHeight; tracing::info!(target: "test", height); - record_block(&mut epoch_manager, h[i - 1], h[i], height, vec![]); + record_block(&mut epoch_manager.write(), h[i - 1], h[i], height, vec![]); let tip = Tip { height, last_block_hash: h[i], diff --git a/genesis-tools/genesis-populate/src/lib.rs b/genesis-tools/genesis-populate/src/lib.rs index adb3da3b228..2605ad49a80 100644 --- a/genesis-tools/genesis-populate/src/lib.rs +++ b/genesis-tools/genesis-populate/src/lib.rs @@ -250,7 +250,6 @@ impl GenesisBuilder { self.epoch_manager.as_ref(), EpochId::default(), EpochId::default(), - &CryptoHash::default(), )?, ); diff --git a/integration-tests/src/tests/client/features/adversarial_behaviors.rs b/integration-tests/src/tests/client/features/adversarial_behaviors.rs index 03381e25ab7..5eb5dc46a76 100644 --- a/integration-tests/src/tests/client/features/adversarial_behaviors.rs +++ b/integration-tests/src/tests/client/features/adversarial_behaviors.rs @@ -199,9 +199,8 @@ fn slow_test_non_adversarial_case() { let final_prev_block_hash = test.env.clients[0].chain.head().unwrap().prev_block_hash; let final_epoch_id = epoch_manager.get_epoch_id_from_prev_block(&final_prev_block_hash).unwrap(); - let final_block_producers = epoch_manager - .get_epoch_block_producers_ordered(&final_epoch_id, &final_prev_block_hash) - .unwrap(); + let final_block_producers = + epoch_manager.get_epoch_block_producers_ordered(&final_epoch_id).unwrap(); // No producers should be kicked out. assert_eq!(final_block_producers.len(), 4); let final_chunk_producers = epoch_manager.get_epoch_chunk_producers(&final_epoch_id).unwrap(); @@ -355,9 +354,8 @@ fn test_banning_chunk_producer_when_seeing_invalid_chunk_base( let final_prev_block_hash = test.env.clients[0].chain.head().unwrap().prev_block_hash; let final_epoch_id = epoch_manager.get_epoch_id_from_prev_block(&final_prev_block_hash).unwrap(); - let final_block_producers = epoch_manager - .get_epoch_block_producers_ordered(&final_epoch_id, &final_prev_block_hash) - .unwrap(); + let final_block_producers = + epoch_manager.get_epoch_block_producers_ordered(&final_epoch_id).unwrap(); assert!(final_block_producers.len() >= 3); // 3 validators if the bad validator was a block producer let final_chunk_producers = epoch_manager.get_epoch_chunk_producers(&final_epoch_id).unwrap(); assert_eq!(final_chunk_producers.len(), 7); diff --git a/integration-tests/src/tests/client/features/in_memory_tries.rs b/integration-tests/src/tests/client/features/in_memory_tries.rs index 11ee41fa4b3..3a5e9345650 100644 --- a/integration-tests/src/tests/client/features/in_memory_tries.rs +++ b/integration-tests/src/tests/client/features/in_memory_tries.rs @@ -82,10 +82,7 @@ fn slow_test_in_memory_trie_node_consistency() { assert_eq!( env.clients[0] .epoch_manager - .get_epoch_block_producers_ordered( - &EpochId::default(), - &env.clients[0].chain.head().unwrap().last_block_hash - ) + .get_epoch_block_producers_ordered(&EpochId::default()) .unwrap() .len(), 2 @@ -469,10 +466,7 @@ fn test_in_memory_trie_consistency_with_state_sync_base_case(track_all_shards: b assert_eq!( env.clients[0] .epoch_manager - .get_epoch_block_producers_ordered( - &EpochId::default(), - &env.clients[0].chain.head().unwrap().last_block_hash - ) + .get_epoch_block_producers_ordered(&EpochId::default()) .unwrap() .len(), NUM_VALIDATORS diff --git a/tools/state-viewer/src/commands.rs b/tools/state-viewer/src/commands.rs index 7d0350960b6..06dcc1da538 100644 --- a/tools/state-viewer/src/commands.rs +++ b/tools/state-viewer/src/commands.rs @@ -615,8 +615,7 @@ pub(crate) fn print_chain( println!( "Epoch {} Validators {:?}", format_hash(epoch_id.0, show_full_hashes), - epoch_manager - .get_epoch_block_producers_ordered(&epoch_id, header.hash()) + epoch_manager.get_epoch_block_producers_ordered(&epoch_id) ); } Err(err) => { diff --git a/tools/state-viewer/src/state_dump.rs b/tools/state-viewer/src/state_dump.rs index 7521e2fb91b..ae8e2bfe939 100644 --- a/tools/state-viewer/src/state_dump.rs +++ b/tools/state-viewer/src/state_dump.rs @@ -41,18 +41,13 @@ pub fn state_dump( last_block_header.hash() ); let genesis_height = last_block_header.height() + 1; - let block_producers = epoch_manager - .get_epoch_block_producers_ordered(last_block_header.epoch_id(), last_block_header.hash()) - .unwrap(); + let block_producers = + epoch_manager.get_epoch_block_producers_ordered(last_block_header.epoch_id()).unwrap(); let validators = block_producers .into_iter() - .filter_map(|(info, is_slashed)| { - if !is_slashed { - let (account_id, public_key, stake) = info.destructure(); - Some((account_id, (public_key, stake))) - } else { - None - } + .map(|info| { + let (account_id, public_key, stake) = info.destructure(); + (account_id, (public_key, stake)) }) .collect::>(); @@ -479,14 +474,11 @@ mod test { safe_produce_blocks(&mut env, 1, epoch_length * 2 + 1); let head = env.clients[0].chain.head().unwrap(); - let last_block_hash = head.last_block_hash; let cur_epoch_id = head.epoch_id; - let block_producers = env.clients[0] - .epoch_manager - .get_epoch_block_producers_ordered(&cur_epoch_id, &last_block_hash) - .unwrap(); + let block_producers = + env.clients[0].epoch_manager.get_epoch_block_producers_ordered(&cur_epoch_id).unwrap(); assert_eq!( - block_producers.into_iter().map(|(r, _)| r.take_account_id()).collect::>(), + block_producers.into_iter().map(|r| r.take_account_id()).collect::>(), HashSet::from_iter(vec!["test0".parse().unwrap(), "test1".parse().unwrap()]) ); let last_block = env.clients[0].chain.get_block(&head.last_block_hash).unwrap(); @@ -555,14 +547,11 @@ mod test { safe_produce_blocks(&mut env, 1, epoch_length * 2 + 1); let head = env.clients[0].chain.head().unwrap(); - let last_block_hash = head.last_block_hash; let cur_epoch_id = head.epoch_id; - let block_producers = env.clients[0] - .epoch_manager - .get_epoch_block_producers_ordered(&cur_epoch_id, &last_block_hash) - .unwrap(); + let block_producers = + env.clients[0].epoch_manager.get_epoch_block_producers_ordered(&cur_epoch_id).unwrap(); assert_eq!( - block_producers.into_iter().map(|(r, _)| r.take_account_id()).collect::>(), + block_producers.into_iter().map(|r| r.take_account_id()).collect::>(), HashSet::from_iter(vec!["test0".parse().unwrap(), "test1".parse().unwrap()]), ); let last_block = env.clients[0].chain.get_block(&head.last_block_hash).unwrap(); @@ -618,14 +607,11 @@ mod test { safe_produce_blocks(&mut env, 1, epoch_length * 2 + 1); let head = env.clients[0].chain.head().unwrap(); - let last_block_hash = head.last_block_hash; let cur_epoch_id = head.epoch_id; - let block_producers = env.clients[0] - .epoch_manager - .get_epoch_block_producers_ordered(&cur_epoch_id, &last_block_hash) - .unwrap(); + let block_producers = + env.clients[0].epoch_manager.get_epoch_block_producers_ordered(&cur_epoch_id).unwrap(); assert_eq!( - block_producers.into_iter().map(|(r, _)| r.take_account_id()).collect::>(), + block_producers.into_iter().map(|r| r.take_account_id()).collect::>(), HashSet::from_iter(vec!["test0".parse().unwrap(), "test1".parse().unwrap()]) ); let last_block = env.clients[0].chain.get_block(&head.last_block_hash).unwrap(); @@ -899,14 +885,11 @@ mod test { ) .unwrap(); let head = env.clients[0].chain.head().unwrap(); - let last_block_hash = head.last_block_hash; let cur_epoch_id = head.epoch_id; - let block_producers = env.clients[0] - .epoch_manager - .get_epoch_block_producers_ordered(&cur_epoch_id, &last_block_hash) - .unwrap(); + let block_producers = + env.clients[0].epoch_manager.get_epoch_block_producers_ordered(&cur_epoch_id).unwrap(); assert_eq!( - block_producers.into_iter().map(|(r, _)| r.take_account_id()).collect::>(), + block_producers.into_iter().map(|r| r.take_account_id()).collect::>(), HashSet::from_iter(vec!["test0".parse().unwrap(), "test1".parse().unwrap()]) ); let last_block = env.clients[0].chain.get_block(&head.last_block_hash).unwrap(); @@ -952,14 +935,11 @@ mod test { safe_produce_blocks(&mut env, 1, epoch_length * 2 + 1); let head = env.clients[0].chain.head().unwrap(); - let last_block_hash = head.last_block_hash; let cur_epoch_id = head.epoch_id; - let block_producers = env.clients[0] - .epoch_manager - .get_epoch_block_producers_ordered(&cur_epoch_id, &last_block_hash) - .unwrap(); + let block_producers = + env.clients[0].epoch_manager.get_epoch_block_producers_ordered(&cur_epoch_id).unwrap(); assert_eq!( - block_producers.into_iter().map(|(r, _)| r.take_account_id()).collect::>(), + block_producers.into_iter().map(|r| r.take_account_id()).collect::>(), HashSet::from_iter(vec!["test0".parse().unwrap(), "test1".parse().unwrap()]), );