Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit 2e2b6fd

Browse files
authored
frame/authority-discovery: Have authorities() return both current and next (#6788)
* frame/authority-discovery: Have authorities() return both current and next Authority address lookups on the DHT happen periodically (every 10 mintues) and are rather slow (~10 seconds). In order to smooth the transition period between two sessions, have the runtime module return both the current as well as the next authority set. Thereby the client authority module will: 1. Publish its addresses one session in advance. 2. Prefetch the addresses of authorities of the next session in advance. * frame/authority-discovery: Deduplicate authority ids * frame/authority-discovery: Don't dedup on_genesis authorities * frame/authority-discovery: Remove mut and sort on comparison in tests * frame/authority-discovery: Use BTreeSet for deduplication
1 parent f0c6a84 commit 2e2b6fd

File tree

3 files changed

+71
-29
lines changed
  • client/authority-discovery/src
  • frame/authority-discovery/src
  • primitives/authority-discovery/src

3 files changed

+71
-29
lines changed

client/authority-discovery/src/worker.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ pub enum Role {
9999
///
100100
/// 2. **Discovers other authorities**
101101
///
102-
/// 1. Retrieves the current set of authorities.
102+
/// 1. Retrieves the current and next set of authorities.
103103
///
104104
/// 2. Starts DHT queries for the ids of the authorities.
105105
///
@@ -447,7 +447,7 @@ where
447447
.collect::<HashMap<_, _>>()
448448
};
449449

450-
// Check if the event origins from an authority in the current authority set.
450+
// Check if the event origins from an authority in the current or next authority set.
451451
let authority_id: &AuthorityId = authorities
452452
.get(&remote_key)
453453
.ok_or(Error::MatchingHashedAuthorityIdWithAuthorityId)?;
@@ -514,12 +514,12 @@ where
514514
Ok(())
515515
}
516516

517-
/// Retrieve our public keys within the current authority set.
517+
/// Retrieve our public keys within the current and next authority set.
518518
//
519519
// A node might have multiple authority discovery keys within its keystore, e.g. an old one and
520-
// one for the upcoming session. In addition it could be participating in the current authority
521-
// set with two keys. The function does not return all of the local authority discovery public
522-
// keys, but only the ones intersecting with the current authority set.
520+
// one for the upcoming session. In addition it could be participating in the current and (/ or)
521+
// next authority set with two keys. The function does not return all of the local authority
522+
// discovery public keys, but only the ones intersecting with the current or next authority set.
523523
fn get_own_public_keys_within_authority_set(
524524
key_store: &BareCryptoStorePtr,
525525
client: &Client,
@@ -530,14 +530,14 @@ where
530530
.collect::<HashSet<_>>();
531531

532532
let id = BlockId::hash(client.info().best_hash);
533-
let current_authorities = client.runtime_api()
533+
let authorities = client.runtime_api()
534534
.authorities(&id)
535535
.map_err(Error::CallingRuntime)?
536536
.into_iter()
537537
.map(std::convert::Into::into)
538538
.collect::<HashSet<_>>();
539539

540-
let intersection = local_pub_keys.intersection(&current_authorities)
540+
let intersection = local_pub_keys.intersection(&authorities)
541541
.cloned()
542542
.map(std::convert::Into::into)
543543
.collect();

frame/authority-discovery/src/lib.rs

Lines changed: 61 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
// Ensure we're `no_std` when compiling for Wasm.
2424
#![cfg_attr(not(feature = "std"), no_std)]
2525

26-
use sp_std::prelude::*;
26+
use sp_std::{collections::btree_set::BTreeSet, prelude::*};
2727
use frame_support::{decl_module, decl_storage};
2828
use sp_authority_discovery::AuthorityId;
2929

@@ -32,7 +32,7 @@ pub trait Trait: frame_system::Trait + pallet_session::Trait {}
3232

3333
decl_storage! {
3434
trait Store for Module<T: Trait> as AuthorityDiscovery {
35-
/// Keys of the current authority set.
35+
/// Keys of the current and next authority set.
3636
Keys get(fn keys): Vec<AuthorityId>;
3737
}
3838
add_extra_genesis {
@@ -47,7 +47,7 @@ decl_module! {
4747
}
4848

4949
impl<T: Trait> Module<T> {
50-
/// Retrieve authority identifiers of the current authority set.
50+
/// Retrieve authority identifiers of the current and next authority set.
5151
pub fn authorities() -> Vec<AuthorityId> {
5252
Keys::get()
5353
}
@@ -71,17 +71,17 @@ impl<T: Trait> pallet_session::OneSessionHandler<T::AccountId> for Module<T> {
7171
where
7272
I: Iterator<Item = (&'a T::AccountId, Self::Key)>,
7373
{
74-
let keys = authorities.map(|x| x.1).collect::<Vec<_>>();
75-
Self::initialize_keys(&keys);
74+
Self::initialize_keys(&authorities.map(|x| x.1).collect::<Vec<_>>());
7675
}
7776

78-
fn on_new_session<'a, I: 'a>(changed: bool, validators: I, _queued_validators: I)
77+
fn on_new_session<'a, I: 'a>(changed: bool, validators: I, queued_validators: I)
7978
where
8079
I: Iterator<Item = (&'a T::AccountId, Self::Key)>,
8180
{
82-
// Remember who the authorities are for the new session.
81+
// Remember who the authorities are for the new and next session.
8382
if changed {
84-
Keys::put(validators.map(|x| x.1).collect::<Vec<_>>());
83+
let keys = validators.chain(queued_validators).map(|x| x.1).collect::<BTreeSet<_>>();
84+
Keys::put(keys.into_iter().collect::<Vec<_>>());
8585
}
8686
}
8787

@@ -192,12 +192,13 @@ mod tests {
192192
}
193193

194194
#[test]
195-
fn authorities_returns_current_authority_set() {
196-
// The whole authority discovery module ignores account ids, but we still need it for
197-
// `pallet_session::OneSessionHandler::on_new_session`, thus its safe to use the same value everywhere.
195+
fn authorities_returns_current_and_next_authority_set() {
196+
// The whole authority discovery module ignores account ids, but we still need them for
197+
// `pallet_session::OneSessionHandler::on_new_session`, thus its safe to use the same value
198+
// everywhere.
198199
let account_id = AuthorityPair::from_seed_slice(vec![10; 32].as_ref()).unwrap().public();
199200

200-
let first_authorities: Vec<AuthorityId> = vec![0, 1].into_iter()
201+
let mut first_authorities: Vec<AuthorityId> = vec![0, 1].into_iter()
201202
.map(|i| AuthorityPair::from_seed_slice(vec![i; 32].as_ref()).unwrap().public())
202203
.map(AuthorityId::from)
203204
.collect();
@@ -206,12 +207,21 @@ mod tests {
206207
.map(|i| AuthorityPair::from_seed_slice(vec![i; 32].as_ref()).unwrap().public())
207208
.map(AuthorityId::from)
208209
.collect();
209-
210210
// Needed for `pallet_session::OneSessionHandler::on_new_session`.
211-
let second_authorities_and_account_ids: Vec<(&AuthorityId, AuthorityId)> = second_authorities.clone()
211+
let second_authorities_and_account_ids = second_authorities.clone()
212212
.into_iter()
213213
.map(|id| (&account_id, id))
214+
.collect::<Vec<(&AuthorityId, AuthorityId)> >();
215+
216+
let mut third_authorities: Vec<AuthorityId> = vec![4, 5].into_iter()
217+
.map(|i| AuthorityPair::from_seed_slice(vec![i; 32].as_ref()).unwrap().public())
218+
.map(AuthorityId::from)
214219
.collect();
220+
// Needed for `pallet_session::OneSessionHandler::on_new_session`.
221+
let third_authorities_and_account_ids = third_authorities.clone()
222+
.into_iter()
223+
.map(|id| (&account_id, id))
224+
.collect::<Vec<(&AuthorityId, AuthorityId)> >();
215225

216226
// Build genesis.
217227
let mut t = frame_system::GenesisConfig::default()
@@ -233,23 +243,55 @@ mod tests {
233243
AuthorityDiscovery::on_genesis_session(
234244
first_authorities.iter().map(|id| (id, id.clone()))
235245
);
236-
assert_eq!(first_authorities, AuthorityDiscovery::authorities());
246+
first_authorities.sort();
247+
let mut authorities_returned = AuthorityDiscovery::authorities();
248+
authorities_returned.sort();
249+
assert_eq!(first_authorities, authorities_returned);
237250

238251
// When `changed` set to false, the authority set should not be updated.
239252
AuthorityDiscovery::on_new_session(
240253
false,
241254
second_authorities_and_account_ids.clone().into_iter(),
242-
vec![].into_iter(),
255+
third_authorities_and_account_ids.clone().into_iter(),
256+
);
257+
let mut authorities_returned = AuthorityDiscovery::authorities();
258+
authorities_returned.sort();
259+
assert_eq!(
260+
first_authorities,
261+
authorities_returned,
262+
"Expected authority set not to change as `changed` was set to false.",
243263
);
244-
assert_eq!(first_authorities, AuthorityDiscovery::authorities());
245264

246265
// When `changed` set to true, the authority set should be updated.
247266
AuthorityDiscovery::on_new_session(
248267
true,
249268
second_authorities_and_account_ids.into_iter(),
250-
vec![].into_iter(),
269+
third_authorities_and_account_ids.clone().into_iter(),
270+
);
271+
let mut second_and_third_authorities = second_authorities.iter()
272+
.chain(third_authorities.iter())
273+
.cloned()
274+
.collect::<Vec<AuthorityId>>();
275+
second_and_third_authorities.sort();
276+
assert_eq!(
277+
second_and_third_authorities,
278+
AuthorityDiscovery::authorities(),
279+
"Expected authority set to contain both the authorities of the new as well as the \
280+
next session."
281+
);
282+
283+
// With overlapping authority sets, `authorities()` should return a deduplicated set.
284+
AuthorityDiscovery::on_new_session(
285+
true,
286+
third_authorities_and_account_ids.clone().into_iter(),
287+
third_authorities_and_account_ids.clone().into_iter(),
288+
);
289+
third_authorities.sort();
290+
assert_eq!(
291+
third_authorities,
292+
AuthorityDiscovery::authorities(),
293+
"Expected authority set to be deduplicated."
251294
);
252-
assert_eq!(second_authorities, AuthorityDiscovery::authorities());
253295
});
254296
}
255297
}

primitives/authority-discovery/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ sp_api::decl_runtime_apis! {
4545
/// The authority discovery api.
4646
///
4747
/// This api is used by the `client/authority-discovery` module to retrieve identifiers
48-
/// of the current authority set.
48+
/// of the current and next authority set.
4949
pub trait AuthorityDiscoveryApi {
50-
/// Retrieve authority identifiers of the current authority set.
50+
/// Retrieve authority identifiers of the current and next authority set.
5151
fn authorities() -> Vec<AuthorityId>;
5252
}
5353
}

0 commit comments

Comments
 (0)