You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs(openspec): register ic-nns-delegation-reader crates after manager/reader split
Upstream PR #10699 split NNSDelegationReader/Builder and the certificate
validation logic out of ic-nns-delegation-manager into a new
ic-nns-delegation-reader crate (plus its ic-nns-delegation-reader-test-utils
helper crate), and added proactive/reactive delegation fetching driven by
consistency checks against the latest certified state.
The NNS Delegation Manager is responsible for periodically fetching NNS delegation certificates from the NNS subnet and making them available to non-NNS subnets. These delegations allow non-NNS subnets to issue certified responses on behalf of the NNS. The module provides:
8
+
Delegation fetching and delegation reading/building live in two separate crates:
9
9
10
-
1.**NNSDelegationManager** -- A background task that periodically fetches delegations from the NNS subnet over TLS-secured HTTP connections.
11
-
2.**NNSDelegationReader** -- A reader (backed by a `tokio::sync::watch`channel) that provides the latest delegationto callers with configurable canister range filtering.
12
-
3.**NNSDelegationBuilder** -- A builder that parses raw NNS certificates, precomputes filtered variants, and constructs `CertificateDelegation` values on demand.
13
-
4.**CanisterRangesFilter** -- An enum controlling which canister range data is included in the returned delegation.
-**`ic-nns-delegation-manager`**(`nns_delegation_manager.rs`) -- A background task that fetches delegations from the NNS subnet over TLS-secured HTTP connections, both proactively (on a fixed interval) and reactively (whenever the currently held delegation no longer matches the replica's latest certified state), and publishes them via a `tokio::sync::watch` channel.
11
+
-**`ic-nns-delegation-reader`**(`reader.rs`, `validation.rs`) -- Provides `NNSDelegationReader` (a reader wrapping the `watch::Receiver` side of the channel), `NNSDelegationBuilder` (parses raw NNS certificates, precomputes filtered variants, and constructs `CertificateDelegation` values on demand), `CanisterRangesFilter` (controls which canister range data is included in a *returned*delegation), and the certificate-tree validation/consistency-checking logic (`CanisterRangesCheck`, `is_tree_consistent_with`, `DelegationValidationError`, `DelegationVerificationError`) used to decide whether a held delegation is still consistent with the current certified state.
12
+
-**`ic-nns-delegation-reader-test-utils`** -- Shared test helpers for constructing `NNSDelegationReader`/`NNSDelegationBuilder` instances in tests of downstream crates.
13
+
14
+
`DelegationManagerMetrics` (in the manager crate) tracks update counts, fetch durations, delegation sizes, fetch errors, state-comparison errors, held-back delegations, and reactive fetches.
15
15
16
16
## Requirements
17
17
@@ -31,17 +31,53 @@ The delegation manager spawns a background task that periodically fetches the NN
-**AND** the reader is still marked as initialized (notifying waiters)
33
33
34
-
#### Scenario: Periodic refresh after interval
34
+
#### Scenario: Proactive refresh after interval
35
35
-**WHEN** the delegation manager has fetched an initial delegation
36
-
-**THEN** it waits for `DELEGATION_UPDATE_INTERVAL` (5 minutes in production, 5 seconds in tests) before fetching a new delegation
37
-
-**AND** a new fetch is not triggered before that interval elapses
38
-
-**AND** after the interval, a fresh delegation replaces the previous one if different
36
+
-**THEN** it waits for `DELEGATION_PROACTIVE_UPDATE_INTERVAL` (5 minutes in production, 5 seconds in tests) before proactively fetching a new delegation
37
+
-**AND** a new proactive fetch is not triggered before that interval elapses
38
+
-**AND** after the interval, a fresh delegation replaces the previous one if different, unless it is held back (see Reactive Fetching)
39
39
40
40
#### Scenario: Delegation is unchanged
41
41
-**WHEN** the delegation manager fetches a new delegation identical to the current one
42
42
-**THEN** the `watch::Sender` does not notify receivers of a change
43
43
-**AND** the existing delegation remains available
44
44
45
+
### Requirement: Reactive Fetching on State Mismatch
46
+
47
+
In addition to the proactive interval, the manager reactively fetches a new delegation whenever the currently held delegation is no longer consistent with the replica's latest certified state (e.g. the state's routing table or subnet public keys have advanced past what the delegation reflects).
48
+
49
+
#### Scenario: Proactively fetched delegation held back
50
+
-**WHEN** a proactively fetched delegation is checked against the latest certified state via `is_delegation_valid_with_respect_to_state`
51
+
-**AND** the check returns `false` (the delegation is inconsistent with the state)
52
+
-**THEN** the new delegation is held back (not published)
53
+
-**AND** the `nns_delegation_manager_held_back_delegations_total` counter is incremented
54
+
-**AND** the previously published delegation (if any) remains available to readers
55
+
56
+
#### Scenario: Reactive fetch triggered by stale delegation
57
+
-**WHEN** the reactive interval (`DELEGATION_REACTIVE_UPDATE_INTERVAL`: 10 seconds in production, 1 second in tests) elapses
58
+
-**AND** the currently held delegation is inconsistent with the latest certified state
59
+
-**THEN** the manager fetches a new delegation immediately
60
+
-**AND** the `nns_delegation_manager_reactive_fetches_total` counter is incremented
61
+
62
+
#### Scenario: Reactive fetch skipped when delegation still valid
63
+
-**WHEN** the reactive interval elapses
64
+
-**AND** the currently held delegation is still consistent with the latest certified state
65
+
-**THEN** no fetch is performed on that tick
66
+
67
+
#### Scenario: No delegation yet, or on the NNS subnet
68
+
-**WHEN** there is no currently held delegation (startup, or the replica is on the NNS subnet where delegations are always `None`)
69
+
-**THEN**`is_delegation_valid_with_respect_to_state` returns `Some(true)`, so a proactive fetch is never held back in this case
70
+
71
+
#### Scenario: Certified state unavailable
72
+
-**WHEN** the latest certified state cannot be obtained
-**AND** the caller (`proactive_fetch`/`reactive_fetch`) treats this as "not provably invalid", so proactive fetches are accepted and reactive fetches are skipped
75
+
76
+
#### Scenario: State comparison error
77
+
-**WHEN** comparing the held delegation's certificate tree against the certified state's routing table and subnet public keys fails
78
+
-**THEN** a warning is logged
79
+
-**AND** the `nns_delegation_manager_state_comparison_errors_total` counter is incremented
80
+
45
81
### Requirement: Delegation Validation
46
82
47
83
Fetched delegations are validated against the registry and the NNS root public key before being accepted.
@@ -199,6 +235,10 @@ The delegation manager exposes Prometheus metrics for observability.
#### Scenario: Reactive-fetch and held-back-delegation metrics
239
+
-**WHEN** the manager performs a reactive fetch or holds back a proactively fetched delegation
240
+
-**THEN**`nns_delegation_manager_reactive_fetches_total` or `nns_delegation_manager_held_back_delegations_total` is incremented respectively, as described under Reactive Fetching on State Mismatch
241
+
202
242
### Requirement: Initialization Awaiting
203
243
204
244
The `NNSDelegationReader` supports waiting until the first delegation fetch completes.
0 commit comments