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

Replace RollingSessionWindow in approval-voting with RuntimeInfo #7123

Merged
merged 26 commits into from
May 12, 2023
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
5eb24c6
Replace `RollingSessionWindow` with `RuntimeInfo` - initial commit
tdimitrov Apr 13, 2023
b0da049
Fix tests in import
tdimitrov Apr 20, 2023
93e6863
Fix the rest of the tests
tdimitrov Apr 20, 2023
a7b74cc
Remove dead code
tdimitrov Apr 20, 2023
0f84b42
Fix todos
tdimitrov Apr 21, 2023
0e486d4
Simplify session caching
tdimitrov Apr 21, 2023
f6a9d98
Comments for `SessionInfoProvider`
tdimitrov Apr 21, 2023
2918b42
Separate `SessionInfoProvider` from `State`
tdimitrov Apr 21, 2023
837f952
`cache_session_info_for_head` becomes freestanding function
tdimitrov Apr 21, 2023
6f609f3
Remove unneeded `mut` usage
tdimitrov Apr 21, 2023
82a0ebc
fn session_info -> fn get_session_info() to avoid name clashes. The f…
tdimitrov Apr 24, 2023
dca7287
Fix SessionInfo retrieval
tdimitrov Apr 24, 2023
360b96d
Code cleanup
tdimitrov Apr 24, 2023
caa2529
Don't wrap `SessionInfoProvider` in an `Option`
tdimitrov Apr 25, 2023
7665ecd
Remove `earliest_session()`
tdimitrov Apr 27, 2023
3f2b85c
Remove pre-caching -> wip
tdimitrov Apr 28, 2023
19e9588
Fix some tests and code cleanup
tdimitrov May 2, 2023
70d136f
Fix all tests
tdimitrov May 2, 2023
6e348c9
Fixes in tests
tdimitrov May 2, 2023
4fa4403
Fix comments, variable names and small style changes
tdimitrov May 2, 2023
dc0542a
Fix a warning
tdimitrov May 2, 2023
233478e
impl From<SessionWindowSize> for NonZeroUsize
tdimitrov May 5, 2023
d27220a
Fix logging for `get_session_info` - remove redundant logs and decrea…
tdimitrov May 6, 2023
407eb27
Merge branch 'master' into tsv-rolling-session-approval-voting
tdimitrov May 6, 2023
2ed7dfd
Code review feedback
tdimitrov May 9, 2023
dcac680
Merge branch 'master' into tsv-rolling-session-approval-voting
tdimitrov May 10, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
228 changes: 153 additions & 75 deletions node/core/approval-voting/src/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,7 @@ use polkadot_node_subsystem::{
},
overseer, RuntimeApiError, SubsystemError, SubsystemResult,
};
use polkadot_node_subsystem_util::{
determine_new_blocks,
rolling_session_window::{RollingSessionWindow, SessionWindowUpdate},
};
use polkadot_node_subsystem_util::determine_new_blocks;
use polkadot_primitives::{
BlockNumber, CandidateEvent, CandidateHash, CandidateReceipt, ConsensusLog, CoreIndex,
GroupIndex, Hash, Header, SessionIndex,
Expand All @@ -59,9 +56,12 @@ use std::collections::HashMap;
use super::approval_db::v1;
use crate::{
backend::{Backend, OverlayedBackend},
cache_session_info_for_head,
criteria::{AssignmentCriteria, OurAssignment},
get_session_info,
persisted_entries::CandidateEntry,
time::{slot_number_to_tick, Tick},
SessionInfoProvider,
};

use super::{State, LOG_TARGET};
Expand All @@ -78,7 +78,7 @@ struct ImportedBlockInfo {
}

struct ImportedBlockInfoEnv<'a> {
session_window: &'a Option<RollingSessionWindow>,
runtime_info: &'a mut Option<SessionInfoProvider>, // this is required just for the `earliest_session()`
tdimitrov marked this conversation as resolved.
Show resolved Hide resolved
assignment_criteria: &'a (dyn AssignmentCriteria + Send + Sync),
keystore: &'a LocalKeystore,
}
Expand Down Expand Up @@ -160,11 +160,7 @@ async fn imported_block_info<Context>(
return Err(ImportedBlockInfoError::FutureCancelled("SessionIndexForChild", error)),
};

if env
.session_window
.as_ref()
.map_or(true, |s| session_index < s.earliest_session())
{
if env.runtime_info.as_ref().map_or(true, |s| session_index < s.earliest_session()) {
gum::debug!(
target: LOG_TARGET,
"Block {} is from ancient session {}. Skipping",
Expand Down Expand Up @@ -212,15 +208,19 @@ async fn imported_block_info<Context>(
}
};

let session_info = match env.session_window.as_ref().and_then(|s| s.session_info(session_index))
{
Some(s) => s,
None => {
gum::debug!(target: LOG_TARGET, "Session info unavailable for block {}", block_hash,);

return Err(ImportedBlockInfoError::SessionInfoUnavailable)
},
};
let session_info =
match get_session_info(env.runtime_info, ctx.sender(), block_hash, session_index).await {
Some(session_info) => session_info,
None => {
gum::error!(
tdimitrov marked this conversation as resolved.
Show resolved Hide resolved
target: LOG_TARGET,
relay_parent = ?block_hash,
session = session_index,
"Session info unavailable"
);
return Err(ImportedBlockInfoError::SessionInfoUnavailable)
},
};

let (assignments, slot, relay_vrf_story) = {
let unsafe_vrf = approval_types::babe_unsafe_vrf_info(&block_header);
Expand Down Expand Up @@ -323,8 +323,9 @@ pub struct BlockImportedCandidates {
#[overseer::contextbounds(ApprovalVoting, prefix = self::overseer)]
pub(crate) async fn handle_new_head<Context, B: Backend>(
ctx: &mut Context,
state: &mut State,
state: &State,
db: &mut OverlayedBackend<'_, B>,
session_info_provider: &mut Option<SessionInfoProvider>,
head: Hash,
finalized_number: &Option<BlockNumber>,
) -> SubsystemResult<Vec<BlockImportedCandidates>> {
Expand Down Expand Up @@ -360,25 +361,7 @@ pub(crate) async fn handle_new_head<Context, B: Backend>(
};

// Update session info based on most recent head.
match state.cache_session_info_for_head(ctx, head).await {
Err(e) => {
gum::debug!(
target: LOG_TARGET,
?head,
?e,
"Could not cache session info when processing head.",
);
return Ok(Vec::new())
},
Ok(Some(a @ SessionWindowUpdate::Advanced { .. })) => {
gum::info!(
target: LOG_TARGET,
update = ?a,
"Advanced session window for approvals",
);
},
Ok(_) => {},
}
cache_session_info_for_head(ctx.sender(), head, session_info_provider).await;
tdimitrov marked this conversation as resolved.
Show resolved Hide resolved

// If we've just started the node and are far behind,
// import at most `MAX_HEADS_LOOK_BACK` blocks.
Expand Down Expand Up @@ -407,7 +390,7 @@ pub(crate) async fn handle_new_head<Context, B: Backend>(
let mut imported_blocks_and_info = Vec::with_capacity(new_blocks.len());
for (block_hash, block_header) in new_blocks.into_iter().rev() {
let env = ImportedBlockInfoEnv {
session_window: &state.session_window,
runtime_info: session_info_provider,
assignment_criteria: &*state.assignment_criteria,
keystore: &state.keystore,
};
Expand Down Expand Up @@ -461,11 +444,25 @@ pub(crate) async fn handle_new_head<Context, B: Backend>(
force_approve,
} = imported_block_info;

let session_info = state
.session_window
.as_ref()
.and_then(|s| s.session_info(session_index))
.expect("imported_block_info requires session info to be available; qed");
let session_info = match get_session_info(
session_info_provider,
ctx.sender(),
head,
session_index,
)
.await
{
Some(session_info) => session_info,
None => {
gum::error!(
tdimitrov marked this conversation as resolved.
Show resolved Hide resolved
target: LOG_TARGET,
session = session_index,
?head,
"Can't get session info for the new head"
);
return Ok(Vec::new())
},
};

let (block_tick, no_show_duration) = {
let block_tick = slot_number_to_tick(state.slot_duration_millis, slot);
Expand Down Expand Up @@ -609,13 +606,19 @@ pub(crate) async fn handle_new_head<Context, B: Backend>(
#[cfg(test)]
pub(crate) mod tests {
use super::*;
use crate::approval_db::v1::DbBackend;
use crate::{approval_db::v1::DbBackend, RuntimeInfo, RuntimeInfoConfig};
use ::test_helpers::{dummy_candidate_receipt, dummy_hash};
use assert_matches::assert_matches;
use polkadot_node_primitives::approval::{VrfSignature, VrfTranscript};
use polkadot_node_primitives::{
approval::{VrfSignature, VrfTranscript},
DISPUTE_WINDOW,
};
use polkadot_node_subsystem::messages::{AllMessages, ApprovalVotingMessage};
use polkadot_node_subsystem_test_helpers::make_subsystem_context;
use polkadot_node_subsystem_util::database::Database;
use polkadot_node_subsystem_util::{
database::Database,
runtime::{ExtendedSessionInfo, ValidatorInfo},
};
use polkadot_primitives::{Id as ParaId, IndexedVec, SessionInfo, ValidatorId, ValidatorIndex};
pub(crate) use sp_consensus_babe::{
digests::{CompatibleDigestItem, PreDigest, SecondaryVRFPreDigest},
Expand All @@ -624,7 +627,7 @@ pub(crate) mod tests {
use sp_core::{crypto::VrfSigner, testing::TaskExecutor};
use sp_keyring::sr25519::Keyring as Sr25519Keyring;
pub(crate) use sp_runtime::{Digest, DigestItem};
use std::{pin::Pin, sync::Arc};
use std::{num::NonZeroUsize, pin::Pin, sync::Arc};

use crate::{approval_db::v1::Config as DatabaseConfig, criteria, BlockEntry};

Expand All @@ -649,26 +652,42 @@ pub(crate) mod tests {
}

fn blank_state() -> State {
let db = kvdb_memorydb::create(NUM_COLUMNS);
let db = polkadot_node_subsystem_util::database::kvdb_impl::DbAdapter::new(db, &[]);
let db: Arc<dyn Database> = Arc::new(db);
State {
session_window: None,
keystore: Arc::new(LocalKeystore::in_memory()),
slot_duration_millis: 6_000,
clock: Box::new(MockClock::default()),
assignment_criteria: Box::new(MockAssignmentCriteria),
db,
db_config: TEST_CONFIG,
spans: HashMap::new(),
}
}

fn single_session_state(index: SessionIndex, info: SessionInfo) -> State {
State {
session_window: Some(RollingSessionWindow::with_session_info(index, vec![info])),
..blank_state()
}
fn single_session_state(
index: SessionIndex,
info: SessionInfo,
relay_parent: Hash,
) -> (State, SessionInfoProvider) {
let runtime_info = RuntimeInfo::new_with_cache(
RuntimeInfoConfig {
keystore: None,
session_cache_lru_size: NonZeroUsize::new(DISPUTE_WINDOW.get() as usize)
.expect("DISPUTE_WINDOW can't be 0; qed."),
},
vec![(
index,
relay_parent,
ExtendedSessionInfo {
session_info: info,
validator_info: ValidatorInfo { our_group: None, our_index: None },
},
)],
);

let state = blank_state();

let session_info_provider =
SessionInfoProvider { runtime_info, gaps_in_cache: false, highest_session_seen: index };

(state, session_info_provider)
}

struct MockAssignmentCriteria;
Expand Down Expand Up @@ -776,13 +795,30 @@ pub(crate) mod tests {
.map(|(r, c, g)| (r.hash(), r.clone(), *c, *g))
.collect::<Vec<_>>();

let session_window =
RollingSessionWindow::with_session_info(session, vec![session_info]);
let session_info_provider = SessionInfoProvider {
runtime_info: RuntimeInfo::new_with_cache(
RuntimeInfoConfig {
keystore: None,
session_cache_lru_size: NonZeroUsize::new(DISPUTE_WINDOW.get() as usize)
.expect("DISPUTE_WINDOW can't be 0; qed."),
},
vec![(
session,
hash,
ExtendedSessionInfo {
session_info,
validator_info: ValidatorInfo { our_index: None, our_group: None },
},
)],
),
gaps_in_cache: false,
highest_session_seen: session,
};

let header = header.clone();
Box::pin(async move {
let env = ImportedBlockInfoEnv {
session_window: &Some(session_window),
runtime_info: &mut Some(session_info_provider),
assignment_criteria: &MockAssignmentCriteria,
keystore: &LocalKeystore::in_memory(),
};
Expand Down Expand Up @@ -882,13 +918,30 @@ pub(crate) mod tests {
.collect::<Vec<_>>();

let test_fut = {
let session_window =
RollingSessionWindow::with_session_info(session, vec![session_info]);
let session_info_provider = SessionInfoProvider {
runtime_info: RuntimeInfo::new_with_cache(
RuntimeInfoConfig {
keystore: None,
session_cache_lru_size: NonZeroUsize::new(DISPUTE_WINDOW.get() as usize)
eskimor marked this conversation as resolved.
Show resolved Hide resolved
.expect("DISPUTE_WINDOW can't be 0; qed."),
},
vec![(
session,
hash,
ExtendedSessionInfo {
session_info,
validator_info: ValidatorInfo { our_index: None, our_group: None },
},
)],
),
gaps_in_cache: false,
highest_session_seen: session,
};

let header = header.clone();
Box::pin(async move {
let env = ImportedBlockInfoEnv {
session_window: &Some(session_window),
runtime_info: &mut Some(session_info_provider),
assignment_criteria: &MockAssignmentCriteria,
keystore: &LocalKeystore::in_memory(),
};
Expand Down Expand Up @@ -982,12 +1035,12 @@ pub(crate) mod tests {
.collect::<Vec<_>>();

let test_fut = {
let session_window = None;
let mut runtime_info = None;

let header = header.clone();
Box::pin(async move {
let env = ImportedBlockInfoEnv {
session_window: &session_window,
runtime_info: &mut runtime_info,
assignment_criteria: &MockAssignmentCriteria,
keystore: &LocalKeystore::in_memory(),
};
Expand Down Expand Up @@ -1077,13 +1130,30 @@ pub(crate) mod tests {
.map(|(r, c, g)| (r.hash(), r.clone(), *c, *g))
.collect::<Vec<_>>();

let session_window =
Some(RollingSessionWindow::with_session_info(session, vec![session_info]));
let session_info_provider = SessionInfoProvider {
runtime_info: RuntimeInfo::new_with_cache(
RuntimeInfoConfig {
keystore: None,
session_cache_lru_size: NonZeroUsize::new(DISPUTE_WINDOW.get() as usize)
.expect("DISPUTE_WINDOW can't be 0; qed."),
},
vec![(
session,
hash,
ExtendedSessionInfo {
session_info,
validator_info: ValidatorInfo { our_index: None, our_group: None },
},
)],
),
gaps_in_cache: false,
highest_session_seen: session,
};

let header = header.clone();
Box::pin(async move {
let env = ImportedBlockInfoEnv {
session_window: &session_window,
runtime_info: &mut Some(session_info_provider),
assignment_criteria: &MockAssignmentCriteria,
keystore: &LocalKeystore::in_memory(),
};
Expand Down Expand Up @@ -1220,7 +1290,8 @@ pub(crate) mod tests {
.map(|(r, c, g)| CandidateEvent::CandidateIncluded(r, Vec::new().into(), c, g))
.collect::<Vec<_>>();

let mut state = single_session_state(session, session_info);
let (state, session_info_provider) =
single_session_state(session, session_info, parent_hash);
overlay_db.write_block_entry(
v1::BlockEntry {
block_hash: parent_hash,
Expand All @@ -1242,9 +1313,16 @@ pub(crate) mod tests {
let test_fut = {
Box::pin(async move {
let mut overlay_db = OverlayedBackend::new(&db);
let result = handle_new_head(&mut ctx, &mut state, &mut overlay_db, hash, &Some(1))
.await
.unwrap();
let result = handle_new_head(
&mut ctx,
&state,
&mut overlay_db,
&mut Some(session_info_provider),
hash,
&Some(1),
)
.await
.unwrap();

let write_ops = overlay_db.into_write_ops();
db.write(write_ops).unwrap();
Expand Down
Loading