From c0e7a02ce49d16ddc1779fa1e78260697f99277a Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Wed, 18 Nov 2020 17:51:06 -0500 Subject: [PATCH 1/4] elaborate on runtime API --- .../src/node/approval/approval-voting.md | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/roadmap/implementers-guide/src/node/approval/approval-voting.md b/roadmap/implementers-guide/src/node/approval/approval-voting.md index 72bb9d075c0b..30dc40ec55c5 100644 --- a/roadmap/implementers-guide/src/node/approval/approval-voting.md +++ b/roadmap/implementers-guide/src/node/approval/approval-voting.md @@ -91,9 +91,7 @@ struct BlockEntry { // unix epoch. type Tick = u64; -struct TrackerEntry - -struct StoredBlockRange(BlockNumber, BlockNumber) +struct StoredBlockRange(BlockNumber, BlockNumber); ``` In the schema, we map @@ -107,6 +105,10 @@ CandidateHash => CandidateEntry ## Logic +```rust +const APPROVAL_SESSIONS: SessionIndex = 6; +``` + In-memory state: ```rust @@ -149,7 +151,13 @@ On receiving an `OverseerSignal::BlockFinalized(h)`, we fetch the block number ` On receiving an `OverseerSignal::ActiveLeavesUpdate(update)`: * We determine the set of new blocks that were not in our previous view. This is done by querying the ancestry of all new items in the view and contrasting against the stored `BlockNumber`s. Typically, there will be only one new block. We fetch the headers and information on these blocks from the ChainApi subsystem. - * We update the `StoredBlockRange` and the `BlockNumber` maps. We use the RuntimeApiSubsystem to determine the set of candidates included in these blocks and use BABE logic to determine the slot number and VRF of the blocks. + * We update the `StoredBlockRange` and the `BlockNumber` maps. + * We use the RuntiemApiSubsystem to determine information about these blocks. It is generally safe to assume that runtime state is available for recent, unfinalized blocks. In the case that it isn't, it means that we are catching up to the head of the chain and needn't worry about assignments to those blocks anyway, as the security assumption of the protocol tolerates nodes being temporarily offline or out-of-date. + * We fetch the set of candidates included by each block by dispatching a `RuntimeApiRequest::CandidateEvents` and checking the `CandidateIncluded` events. + * We fetch the session of the block by dispatching a `session_index_for_child` request with the parent-hash of the block. + * If the session index - `APPROVAL_SESSIONS` > `state.earliest_session`, then bump `state.earliest_sessions` to that amount and prune earlier sessions. + * If the session isn't in our `state.session_info`, load the session info for it and for all sessions since the earliest-session, including the earliest-session, if that is missing. And it can be, just after pruning, if we've done a big jump forward, as is the case when we've just finished chain synchronization. + * We use the RuntimeApiSubsystem to determine the set of candidates included in these blocks and use BABE logic to determine the slot number and VRF of the blocks. * We also note how late we appear to have received the block. We create a `BlockEntry` for each block and a `CandidateEntry` for each candidate obtained from `CandidateIncluded` events after making a `RuntimeApiRequest::CandidateEvents` request. * Ensure that the `CandidateEntry` contains a `block_assignments` entry for the block, with the correct backing group set. * If a validator in this session, compute and assign `our_assignment` for the `block_assignments` From 7270b80f9b1a5780f2c72c268381e2ffffc19b0d Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Wed, 18 Nov 2020 17:53:30 -0500 Subject: [PATCH 2/4] clarify what to do if the runtime API calls fail --- roadmap/implementers-guide/src/node/approval/approval-voting.md | 1 + 1 file changed, 1 insertion(+) diff --git a/roadmap/implementers-guide/src/node/approval/approval-voting.md b/roadmap/implementers-guide/src/node/approval/approval-voting.md index 30dc40ec55c5..dbb16037e269 100644 --- a/roadmap/implementers-guide/src/node/approval/approval-voting.md +++ b/roadmap/implementers-guide/src/node/approval/approval-voting.md @@ -157,6 +157,7 @@ On receiving an `OverseerSignal::ActiveLeavesUpdate(update)`: * We fetch the session of the block by dispatching a `session_index_for_child` request with the parent-hash of the block. * If the session index - `APPROVAL_SESSIONS` > `state.earliest_session`, then bump `state.earliest_sessions` to that amount and prune earlier sessions. * If the session isn't in our `state.session_info`, load the session info for it and for all sessions since the earliest-session, including the earliest-session, if that is missing. And it can be, just after pruning, if we've done a big jump forward, as is the case when we've just finished chain synchronization. + * If any of the runtime API calls fail, we just warn and skip the block. * We use the RuntimeApiSubsystem to determine the set of candidates included in these blocks and use BABE logic to determine the slot number and VRF of the blocks. * We also note how late we appear to have received the block. We create a `BlockEntry` for each block and a `CandidateEntry` for each candidate obtained from `CandidateIncluded` events after making a `RuntimeApiRequest::CandidateEvents` request. * Ensure that the `CandidateEntry` contains a `block_assignments` entry for the block, with the correct backing group set. From d81daf185c9be89d7cd9e0230c8a651537e8d1a1 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Thu, 19 Nov 2020 11:55:38 -0500 Subject: [PATCH 3/4] Update roadmap/implementers-guide/src/node/approval/approval-voting.md Co-authored-by: Peter Goodspeed-Niklaus --- roadmap/implementers-guide/src/node/approval/approval-voting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roadmap/implementers-guide/src/node/approval/approval-voting.md b/roadmap/implementers-guide/src/node/approval/approval-voting.md index dbb16037e269..f47c79de1e94 100644 --- a/roadmap/implementers-guide/src/node/approval/approval-voting.md +++ b/roadmap/implementers-guide/src/node/approval/approval-voting.md @@ -155,7 +155,7 @@ On receiving an `OverseerSignal::ActiveLeavesUpdate(update)`: * We use the RuntiemApiSubsystem to determine information about these blocks. It is generally safe to assume that runtime state is available for recent, unfinalized blocks. In the case that it isn't, it means that we are catching up to the head of the chain and needn't worry about assignments to those blocks anyway, as the security assumption of the protocol tolerates nodes being temporarily offline or out-of-date. * We fetch the set of candidates included by each block by dispatching a `RuntimeApiRequest::CandidateEvents` and checking the `CandidateIncluded` events. * We fetch the session of the block by dispatching a `session_index_for_child` request with the parent-hash of the block. - * If the session index - `APPROVAL_SESSIONS` > `state.earliest_session`, then bump `state.earliest_sessions` to that amount and prune earlier sessions. + * If the `session index - APPROVAL_SESSIONS > state.earliest_session`, then bump `state.earliest_sessions` to that amount and prune earlier sessions. * If the session isn't in our `state.session_info`, load the session info for it and for all sessions since the earliest-session, including the earliest-session, if that is missing. And it can be, just after pruning, if we've done a big jump forward, as is the case when we've just finished chain synchronization. * If any of the runtime API calls fail, we just warn and skip the block. * We use the RuntimeApiSubsystem to determine the set of candidates included in these blocks and use BABE logic to determine the slot number and VRF of the blocks. From b25b9a4749bba1e5e7a82218036ba33c019f3edd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 24 Nov 2020 14:14:23 +0100 Subject: [PATCH 4/4] Update roadmap/implementers-guide/src/node/approval/approval-voting.md --- roadmap/implementers-guide/src/node/approval/approval-voting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roadmap/implementers-guide/src/node/approval/approval-voting.md b/roadmap/implementers-guide/src/node/approval/approval-voting.md index f47c79de1e94..5e9f1e360ce6 100644 --- a/roadmap/implementers-guide/src/node/approval/approval-voting.md +++ b/roadmap/implementers-guide/src/node/approval/approval-voting.md @@ -152,7 +152,7 @@ On receiving an `OverseerSignal::BlockFinalized(h)`, we fetch the block number ` On receiving an `OverseerSignal::ActiveLeavesUpdate(update)`: * We determine the set of new blocks that were not in our previous view. This is done by querying the ancestry of all new items in the view and contrasting against the stored `BlockNumber`s. Typically, there will be only one new block. We fetch the headers and information on these blocks from the ChainApi subsystem. * We update the `StoredBlockRange` and the `BlockNumber` maps. - * We use the RuntiemApiSubsystem to determine information about these blocks. It is generally safe to assume that runtime state is available for recent, unfinalized blocks. In the case that it isn't, it means that we are catching up to the head of the chain and needn't worry about assignments to those blocks anyway, as the security assumption of the protocol tolerates nodes being temporarily offline or out-of-date. + * We use the RuntimeApiSubsystem to determine information about these blocks. It is generally safe to assume that runtime state is available for recent, unfinalized blocks. In the case that it isn't, it means that we are catching up to the head of the chain and needn't worry about assignments to those blocks anyway, as the security assumption of the protocol tolerates nodes being temporarily offline or out-of-date. * We fetch the set of candidates included by each block by dispatching a `RuntimeApiRequest::CandidateEvents` and checking the `CandidateIncluded` events. * We fetch the session of the block by dispatching a `session_index_for_child` request with the parent-hash of the block. * If the `session index - APPROVAL_SESSIONS > state.earliest_session`, then bump `state.earliest_sessions` to that amount and prune earlier sessions.