1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
//! Bootstrap and continuously reshare threshold secrets.
//!
//! This module wires threshold-key management into consensus without owning the
//! application's state machine or private-key policy. It provides two public
//! entry points:
//!
//! - [`bootstrap`] runs a contained, one-shot DKG chain that trustlessly creates
//! an initial threshold secret.
//! - [`reshare`] runs alongside an application chain and continuously rotates
//! threshold shares across epochs.
//!
//! Both paths produce or consume [`types::EpochInfo`], the public artifact that
//! describes the threshold output for an epoch. The application stores that
//! artifact in its own blocks and installs epoch-scoped schemes through a
//! [`Registrar`].
//!
//! # Application Contract
//!
//! Application blocks implement [`ReshareBlock`] and carry at most one
//! [`types::Payload`]. Connect an application to the reshare mailbox by wrapping
//! it in [`reshare::Application`], which drives both sides of the contract:
//!
//! - For proposals, the wrapper selects and fetches the payload to include (a
//! dealer log from the midpoint onward, the epoch info on the final block) and
//! hands it to the application through [`reshare::Input`]. The
//! application takes it in its own `propose` and attaches it to the block it
//! builds, because only the application can build its block type. It does not
//! talk to the reshare mailbox or track epoch boundaries itself.
//! - For verification, the wrapper rejects a final block whose payload does not
//! match the independently constructed [`types::EpochInfo`], and rejects stray
//! payloads on early non-final blocks, so the application does not implement
//! these checks by hand.
//!
//! The protocol also requires the application to provide a [`SecretStore`].
//! Secret storage is intentionally user-owned: deployments differ on encryption,
//! access control, hardware isolation, backups, and pruning. Anything written to
//! this trait is private ceremony material and must be protected by the
//! application's security policy.
//!
//! # State Sync
//!
//! Reshare supports nodes that join through state sync. A node can participate in
//! the synced epoch's reshare ceremony when its certified floor is at or before
//! the epoch midpoint, because marshal replays the complete dealer-log inclusion
//! window. A later floor has skipped part of that public history, so the reshare
//! actor follows that ceremony for the rest of the epoch instead.
//!
//! Follower mode affects only resharing. State-sync startup first registers the
//! certified current-epoch consensus scheme, so a node with a recovered share can
//! still sign ordinary non-boundary blocks. It cannot locally derive the next
//! [`types::EpochInfo`] needed to propose or complete verification of the final
//! block, and resumes resharing after learning that block's externally finalized
//! outcome.
//!
//! A `player` that missed private dealings may need public reveals to recover its
//! share and must treat a revealed share as public. To preserve share privacy, a
//! future player should state sync while it is still a `next_player` and be online
//! before the early dealing window.
//!
//! This timing makes it safe for [`ParticipantsProvider`] to be backed by chain
//! state (e.g., a staking contract). The chain can announce future players first,
//! giving those nodes an epoch to state sync before their shares are needed.
//!
//! A node beginning state sync has no application state from which to resolve
//! participant reachability. Everything required to connect to the active
//! committee therefore rides in
//! [`types::EpochInfo`] itself: the key-only participant sets and the
//! transport [`network::Directory`] for those participants. The provider hooks
//! are consulted only while building or verifying an epoch's final block,
//! which only fully synced nodes do.
//!
//! Before starting either actor, initialize one [`state_sync::Plan`] under a
//! stable node-wide partition prefix and clone it into the orchestrator and
//! reshare configurations. The plan durably records fresh state-sync material
//! before the actors start, so a node can restart immediately after state sync
//! completes. Both actors share one recovery decision, and the plan removes
//! stale material once marshal's recovered epoch advances beyond the synced
//! epoch. This API is independent of the optional [`crate::stateful`] actor.
//!
//! [`probe`] fixes the state-sync floor and the epoch info atomically: the
//! floor is the highest finalization from an `f + 1` sample of the configured
//! bootstrap committee, and the epoch info is fetched for that floor's own
//! epoch. The actors therefore always start in the floor's epoch with its
//! public info in hand. If the network crosses an epoch boundary while
//! application state sync is still running, the node starts at the floor's
//! epoch and catches up through ordinary marshal delivery: backup vote or
//! certificate traffic from a future epoch hints marshal to fetch the missing
//! boundary finalization. See [`probe`] for the bootstrap trust model.
//!
//! # Peer Activation
//!
//! DKG peer identities remain key-only in ceremony artifacts and all wire
//! messages. Transport-specific reachability lives in the
//! [`network::Directory`] embedded in each [`types::EpochInfo`], so activation
//! through [`network::Manager`] consumes only in-band data:
//!
//! - One-shot bootstrap activates epoch zero from its configured directory
//! before registering its DKG channel.
//! - A fresh-node probe activates its configured bootstrap snapshot and
//! directory when the first subscriber appears, before requesting a latest
//! finalization.
//! - Continuous operation activates an epoch from the epoch's own
//! [`types::EpochInfo`] after its readiness gate opens and before Simplex or
//! its epoch channels start.
//!
//! Restart and state-sync entry activate the recovered epoch from the same
//! certificate-backed [`types::EpochInfo`] as uninterrupted operation, so no
//! out-of-band registry access is required during recovery.
//!
//! # Marshal Retention
//!
//! DKG startup relies on marshal's local finalized block archive unless the node
//! is entering through one-time state sync. On an ordinary restart, the active
//! epoch is derived from marshal's processed height, and the public
//! [`types::EpochInfo`] for that epoch is loaded from the finalized boundary
//! block that introduced it.
//!
//! For epoch zero, that boundary is height zero. For later epochs, the boundary
//! is the final block of the previous epoch:
//!
//! ```text
//! boundary(current_epoch) = last_block(current_epoch - 1)
//! ```
//!
//! An operator running stateful pruning MUST keep marshal's finalized block
//! retention window at least one full epoch wide, so the previous epoch's
//! boundary block survives until the current epoch finishes. Concretely, the
//! marshal retention floor configured through the stateful
//! [`PruneConfig`](crate::stateful::PruneConfig)
//! (`max_pending_acks + 1 + retained_marshal_blocks` finalized blocks) MUST be
//! greater than or equal to the DKG epoch length (`blocks_per_epoch`). DKG does
//! not need blocks before that previous boundary for ordinary restart, but it
//! does need the boundary block itself to recover the epoch's public threshold
//! output, participant set, and Simplex floor commitment.
//!
//! This coupling is the operator's responsibility. The two knobs are configured
//! independently: `blocks_per_epoch` is a DKG configuration, while the marshal
//! retention floor is set on the stateful
//! [`PruneConfig`](crate::stateful::PruneConfig). The library cannot enforce the
//! relationship, and no runtime check couples them
//! ([`PruneConfig::assert_valid`](crate::stateful::PruneConfig::assert_valid)
//! only compares marshal and QMDB retention). Pruning the boundary before the
//! current epoch finishes leaves a restarting validator without the local public
//! material required for normal recovery, and the orchestrator panics on startup
//! with a `missing finalized boundary block` error.
//!
//! Nodes that serve `dkg::probe` responses for other peers also need the
//! corresponding boundary finalization and boundary block for every epoch they
//! intend to serve.
//!
//! See [`probe`], [`fence`], [`orchestrator`], [`reshare`], [`state_sync`], and
//! [`types`] for the detailed actors, synchronization points, and wire artifacts.
use crate;
use ;
use ;
use Set;
use Future;
/// A [`Block`] that may carry a reshare [`Payload`](types::Payload).
/// A registrar of signing schemes that supplies a [`Provider`] an [`Epoch`]-scoped
/// [`ThresholdScheme`] in preparation for a transition to the given [`Epoch`].
///
/// [`Provider`]: commonware_cryptography::certificate::Provider
/// [`ThresholdScheme`]: commonware_consensus::simplex::scheme::bls12381_threshold
/// Interface for a secret store that persists and retrieves the private DKG/reshare
/// material for different [`Epoch`]s.
///
/// All material entrusted to this trait is secret and must be stored as such: it must
/// never be written to plaintext protocol storage, carried on-chain, or sent to peers.
/// This includes the dealer RNG seed, which seeds a dealer's sharing polynomial and so
/// reveals every share that dealer sends.
///
/// Writes must be durable before their returned future resolves. When
/// [`put_share`](Self::put_share), [`put_seed`](Self::put_seed), or
/// [`put_dealing`](Self::put_dealing) resolves, the stored material MUST survive a crash: the
/// reshare actor treats a resolved put as a durable commitment and does not re-derive the
/// material after a restart. A buffered store that resolves before the write is stable can let a
/// dealer reseed with fresh randomness and re-deal different shares for the same epoch
/// (equivocation), or lose a share it has already relied upon.
/// Participant policy provider.
///
/// This is the only application hook on canonical epoch structure: it supplies
/// the intended participant set and transport directory for a future `epoch`.
/// The actor derives dealers, current players, and ordinary epoch progression
/// from finalized public truth, and consults this only for the values of an
/// epoch it cannot yet read from a finalized boundary block.
///
/// Both hooks are consulted exclusively while building or verifying an epoch's
/// final block, so implementations may be backed by application state (e.g., a
/// staking or address-registry contract): a node performing those operations is
/// fully synced. Their results are embedded in the next
/// [`types::EpochInfo`], which is what recovering and state-syncing nodes use
/// instead of this provider.
///
/// [`participants`](Self::participants) and [`directory`](Self::directory)
/// must be deterministic for the same inputs across all honest nodes (see
/// their documentation for the exact contracts).