🔄 Auto-sync: from Discussion #1748 every hour.
Dynamic devshard: per-escrow BLS DKG (NIZK dealings, on-chain T0)
Автор: @akup · Категория: Protocol Improvements · Создано: 2026-09-10 13:56 UTC · Обновлено: 2026-09-11 04:38 UTC
📝 Описание
Dynamic devshard: per-escrow BLS DKG (NIZK dealings, on-chain T0)
Status: draft — design only; not implemented.
Related: host-initiated close in finalization.
This document specifies a per-escrow BLS12-381 distributed key generation (DKG) so a devshard has a stable root public key PK that a third party can check was generated by the hosts who actually dealt for that escrow. Dealings are publicly verifiable (NIZK). There is no complaint / dispute phase.
Dealings are p2p off-chain. The chain sees only the final artifact T0 (signed dealings + PK). It re-verifies that artifact (hosts are not trusted). A deadline unions every valid signed dealing anyone submitted, so one assembler cannot drop a host. Then PK = ∏ A_i over that union.
Resharing (keep PK after a membership tx) is a follow-on. Genesis uniqueness does not depend on it.
1. Summary
Today MsgCreateDevshardEscrow locks funds and samples slots (typically 16 participant addresses). Settlement still uses per-slot signatures. There is no per-escrow BLS key, and the existing x/bls DKG is epoch-wide, interactive, and rebuilt every epoch.
This proposal makes escrow creation heavier:
- Chain creates the escrow and lists eligible participants (
slots) — already true. The creator does not pick the host set. - Listed hosts run the DKG p2p (NIZK dealings, §5). They do not put each dealing on-chain.
- Any listed host submits
MsgSubmitDevshardT0with the artifact (signed dealings + claimedPK). Gas-free if the signer is a listed slot (§6.5). The chain re-verifies every dealing; “we already checked p2p” is not trusted. - The chain does not lock
PKon the first tx. Untildkg_deadlineit unions every valid signed dealing from every submit (happy path = one fullT0; an omitted host adds only their dealing). At the deadline, if|D| ≥ t, it storesT0andPK = ∏ A_i. Otherwise DKG fails. - The escrow is not execution-ready until DKG completes. After that,
PKis a compact quorum verifier key (telemetry, and optionally a settle encoding). It is not what makes host-initiated close or roster changes possible — see What this buys.
PK alone is a group element and proves nothing about origin. T0 is the proof. Hosts assemble it off-chain; the chain re-verifies and unions fragments so the submitter does not choose the dealer subset.
Heavier create is the cost. The win is a chain-stored PK that third parties can check without trusting the creator or fetching n slot signatures — see What this buys.
What this buys
The chain-stored PK is a compact quorum verifier that a third party can check without trusting the escrow creator. That is the product. Self-settle and dynamic membership are not.
Not a win: self-settle
Today MsgSettleDevshardEscrow requires settler == escrow.Creator (VerifyDevshardSettlement) and 2n/3+1 per-slot secp signatures. Host-initiated close needs the first check dropped. The second check is already committee authorization.
finalization.md is the close protocol: off-chain vote/commit, then one FinalizeSubmit carrying VoteQC / CommitQC (or today’s slot signatures). The Cosmos signer can be any host or relayer. BLS is not required.
A threshold signature Verify(PK, settlement_digest, σ) can shrink that tx. Compactness is not a new capability and is not a reason to run this DKG. Per-slot signatures stay a valid settle encoding.
Not a win: dynamic membership
Today slots are frozen at MsgCreateDevshardEscrow. Changing the roster without a new escrow is a membership tx (add host / remove host): update slots, version the roster for nonce routing and quorum. That tx is required whether or not a BLS key exists — it is how every host and the chain learn who is in and when the set changed.
Resharing (§11) does not replace that tx. It is extra work after the membership tx, only if a PK already exists and third parties should keep verifying the same key. BLS does not make the shard dynamic; the membership tx does. A new DKG on each add would only matter if you had chosen PK as a cached identity (telemetry below).
Cross-devshard verifiable telemetry
Each host sits in many devshards. Inflight work (“how much is this host processing right now”) is local to a shard unless it is published. Self-signed load is cheap to lie about. A threshold BLS signature under that shard’s PK is a quorum statement:
telemetry = {
escrow_id,
height, // or height-sync aligned height
loads: [ (slot_or_host, inflight_work), ... ]
}
σ = ThresholdBLS(sk, domain || telemetry)
Gossip telemetry ‖ σ among chain participants (hosts / controllers), not as per-inference on-chain txs. Any other devshard:
- Reads
PKforescrow_idfrom chain (the DKG output). - Checks
Verify(PK, telemetry, σ). - Treats the loads as quorum-attested by that shard.
No need to be in the escrow, no need for T0 at verify time, no trust in the gossip relay. The chain-stored PK is the verifier key. (n slot signatures would also work if the verifier fetches the current slots; PK is the compact form.)
Uses: avoid sending more work to a host already hot in other shards; validation / admission / routing with a shared view of in-process load.
Constraints (so this stays telemetry, not a second consensus):
- Periodic, height-bound, compact (counts / tokens in flight — not prompts).
- Replay: bind
escrow_id+ height (and maybe a monotonic telemetry nonce); ignore stale heights. - Not per-inference gossip. Same bias as cPoC / finalization: flood only attestations, not every request.
- Wire, cadence, and aggregation across many escrows are a follow-on spec; this DKG supplies the compact
PKthose attestations verify against.
2. Goals
- Joint generation — no listed host (and no outsider) knows
skunless they corrupt more than the signing threshold. - Binding —
PKis uniquely determined by this escrow’s ceremony id and the union of valid signed dealings at the deadline. A censored subset packed by oneT0sender cannot be the final product. - Public verifiability — a third party (and the chain) verifies
T0without private shares and without a dispute round. - No DKG disputes — invalid dealings are dropped; they are not argued on-chain.
- Stable root key (optional follow-on) — if third parties cache
PK, a membership tx may be followed by resharing soPKdoes not rotate. Resharing is not what changes the roster. - Reuse identities — dealers are the escrow
slots; encryption and dealing signatures use each participant’s already-registered secp256k1 account key. - Gas-free T0 submit —
MsgSubmitDevshardT0from a listed slot charges no fee. Cost is prepaid byCreateDevshardFee. - Off-shard verify — any chain participant can check a shard BLS signature (telemetry) against on-chain
PK. Compact BLS settle is an optional encoding, not a close-authority change.
3. Non-goals (this document)
- Replacing the epoch
x/blsDKG used for network-wide PoC signatures. - Host-initiated close — drop
settler == Creatorand verify host quorum (CommitQCor slot signatures).finalization.mdowns that. BLS settle is optional compactness. - Membership txs (
add host/remove host) — required to changeslotswhether or not this DKG exists. This doc does not specify who may add or hownew_slotsis chosen. - Exact protobuf for an optional BLS settle field vs today’s
repeated DevshardSlotSignature. - Full telemetry gossip protocol (cadence, transport, cross-escrow merge). This doc only states that threshold-signed load is the payload those protocols verify.
- P2p wire for dealing gossip (any all-to-all among
slotsis enough; NIZKs do not need extra rounds). This doc only requires: each dealing is signed, and the chain sees a union of those signed blobs by the deadline. - SNARK compression of
T0(only if on-chain verify gas becomes a problem).
4. Glossary
| Term | Meaning |
|---|---|
n |
Number of listed hosts. Today n = len(slots) = GroupSize (16). |
t |
Signing threshold. Align with settlement quorum: t = DevshardQuorumSlots (2n/3 + 1 = 11). t shares reconstruct sk / a signature. |
| Dealer / player | In genesis, the same set: every listed slot deals and receives a share. |
A_i |
Dealer i’s public contribution g^{a_{i,0}} (G2, BLS12-381). |
PK |
Root group public key ∏ A_i over accepted dealers (all valid dealings at the deadline). |
PK_i |
Public share of participant i, used later for share verification and resharing. |
| NIZK dealing | One message: verification vector, encrypted shares, proofs, identity signature. Anyone can check it. |
T0 |
Frozen genesis artifact: union of valid signed dealings at the deadline, plus derived PK. Built p2p; chain re-verifies and unions fragments. |
T_k |
Reshare transcript for round k≥1: old public shares, new committee, accepted reshare dealings, same PK. |
| Ceremony id | Domain separator tying dealings to this escrow on this chain (and, for reshare, round k + new slot list). |
5. Why NIZK (and what it is not)
A signature on A_i only proves identity i published a group element. It does not prove:
iknowsa_iwithA_i = g^{a_i}(rogue-key / contribution cancellation: last dealer setsA_n = PK* · (∏_{j<n} A_j)^{-1}and knowssk*);- ciphertexts are Shamir evaluations of the committed polynomial (classical Feldman needs a complaint round).
Two NIZKs per dealing close that:
- PoK of discrete log of
A_i(Schnorr / Fiat–Shamir), bound to the ceremony id — blocks cancellation. - Share correctness — ciphertexts match the Feldman vector (
C_i[0] = A_i). Specified in §5.2 as DLEQ/PVSS, not Groth 2021.
NIZKs do not by themselves name the dealers. Long-term signatures on the dealing do. NIZKs do not survive as a proof if the chain only stores PK and throws T0 away.
Protocol effect: dealing is one shot; aggregation is “keep valid dealings.” No VERIFYING phase, no MsgSubmitVerificationVector, no dispute txs.
That path is specified at the message layer (§6.3–§6.4): the keeper re-verifies every dealing inside the submitted artifact; a bad dealing is dropped from the union (or fails that tx), not a complaint. Hosts already verified p2p; the chain does it again so a lying T0 cannot pass. What §5.1 specifies is which checks run.
5.1 What the chain verifies (no DKG disputes)
On each dealing inside MsgSubmitDevshardT0 (and on any fragment merged before the deadline) the keeper MUST check, in order:
- Eligibility — dealing signer ∈
slots, at most one dealing per slot in the union, window open. Not a NIZK. - Schnorr PoK of
A_i = C_i[0]— Fiat–Shamir, bound toceremony_id. Anti-cancellation. Required. Foundational Schnorr/Fiat–Shamir patents have expired; this is the same class as RFC 8235. - Share correctness (PVSS) — for every recipient slot
j, the ciphertext encryptsf_i(j)consistent with the Feldman vectorC_i. Anyone can check; recipients do not complain. Required for “no disputes.” Must not depend on Groth 2021 (§5.2). - Subgroup / degree —
C_ihastcoefficients in the BLS12-381 subgroup used forPK.
If any check fails, that dealing is not admitted to the union. There is no complaint phase.
Schnorr without (3) would still need Feldman decrypt-and-complain (today’s epoch x/bls). That contradicts this section. Groth 2021 is one implementation of (3); it is not the spec.
5.2 Share correctness without Groth 2021 (patent-avoidance)
Normative v1: Feldman vector + hashed-ElGamal in the same group as g + Chaum–Pedersen DLEQ, Fiat–Shamir (Schoenmakers-style PVSS, 1990s). No pairing product argument, no Groth NI-DKG.
Each participant has an encryption key pk_j = g^{x_j} in the same group as the Feldman generator (G2, matching PK). Not secp256k1 ECIES: proving ECIES plaintext in a cheap NIZK is why people reach for SNARKs or Groth’s pairing encryption.
For each recipient j, dealer i with share s = f_i(j):
Y_j = ∏_k C_i[k]^{j^k} // Feldman, Y_j = g^s
r ← random
R = g^r
U = pk_j^r
ct = s + H(ceremony_id ‖ i ‖ j ‖ U) // field add (scalar)
π_j = DLEQ(g, R, pk_j, U) // Chaum–Pedersen: same r
Fiat–Shamir for π_j binds ceremony_id, i, j, C_i, R, U, ct.
Chain (n = 16):
Y_jequals Feldman(C_i,j)π_jverifiesY_j ≟ g^{ct - H(ceremony_id ‖ i ‖ j ‖ U)}
(this binds the plaintext toY_j; without it, hashed-ElGamal would need a recipient complaint)
The chain never decrypts.
Recipient j: s = ct - H(ceremony_id ‖ i ‖ j ‖ R^{x_j}). If the three checks passed, g^s = Y_j already.
Do not use for v1: Groth 2021 NI-DKG, Groth16, or a vendor SNARK/STARK stack. Those can carry implementation patents. Schnorr + DLEQ are 1980s/1990s sigma protocols whose foundational patents have expired. This is not a legal opinion; it is the construction this spec requires so we are not tied to Groth 2021.
Optional later: swap Groth-style multi-receiver pairing encryption behind the same verify(dealing) → bool interface (compression only). For n = 16 that is not expected to win on-chain verify cost — see §5.3.
5.3 Comparison with Groth NI-DKG (2021)
Reference: Jens Groth, Non-interactive distributed key generation and key resharing, ePrint 2021/339. Not Groth16 (2016). (If “Groth 2011” is used loosely, it is the same pairing-NIZK family; the DKG paper is 2021.)
Same protocol. P2p one dealing per dealer, one T0 on chain, same deadline union, same Lagrange reshare (§11). Groth does not cut interactions or rounds.
Different payload. DLEQ: Feldman vector + n hashed-ElGamals + n Chaum–Pedersen proofs. Groth: packed pairing CCA ciphertext + one pairing NIZK for the whole dealing.
| DLEQ (this spec, v1) | Groth 2021 | |
|---|---|---|
| Interactions | 1 dealing / dealer; 1 artifact tx | same |
| Dealing size | O(t + n) |
smaller (multi-receiver pack) |
| On-chain verify | n cheap G2 DLEQs + 1 Schnorr per dealing |
1 pairing-product NIZK per dealing |
Full T0 (n dealers) |
n² DLEQs (16² = 256 at GroupSize) |
n pairing verifies |
| Patents / v1 | Schnorr + DLEQ only | do not require |
n = 16: DLEQ is expected as fast or faster on-chain. Each DLEQ is a few G2 multi-exps (same class as existing BLS ops). Groth verify is pairings, which cost much more per op. Groth reduces count of proofs, not protocol work; at 16 slots that count is small, so pairings do not pay off. Groth’s win is large n (Internet Computer scale), where n² DLEQs and n ElGamals dominate size and time.
v1 stays DLEQ. Revisit Groth only if a profiled MsgSubmitDevshardT0 verify is too slow and counsel accepts that implementation.
6. On-chain create → DKG → store PK
6.1 Escrow create (existing, extended)
MsgCreateDevshardEscrow stays the listing step:
- Sample
slotsfrom the model epoch group (currentGetSlotsFromSorted/app_hash/escrow_id/model_id). - Lock funds, persist escrow.
CreateDevshardFee(already charged at create) pre-pays on-chain artifact verify (MsgSubmitDevshardT0), not n dealing txs.
New escrow fields (conceptual):
| Field | After create | After successful DKG |
|---|---|---|
slots |
listed participants | unchanged |
dkg_status |
PENDING |
COMPLETED or FAILED |
dkg_deadline |
create height + dkg_timeout_blocks |
— |
bls_pk |
empty | PK |
t0_hash |
empty | H(T0) |
t0 |
empty | full transcript (or blob + hash; see §8) |
The escrow is not ready for inference while dkg_status != COMPLETED. Hosts that would otherwise attach on create wait for PK.
dkg_timeout_blocks is a new param: the dealing window. At that height the EndBlocker either finalizes PK or marks FAILED (refund / refusal, same spirit as refusal_timeout).
6.2 P2P dealings, on-chain artifact only
Dealings are not chain txs. Listed hosts gossip signed NIZK dealings among slots (transport out of scope). Each host verifies Schnorr + DLEQ locally, decrypts its ciphertexts, and holds a candidate set D.
What goes on-chain is the artifact: the set of signed dealings plus a claimed PK. The chain re-verifies (same checks as hosts). “Already verified off-chain” is not an input.
Waiting for a deadline and accepting a quorum is still required (offline hosts should not fail create). A single assembled T0 would otherwise allow:
Did the submitter drop some hosts’ dealings?
That is subset censorship, not a NIZK failure. Close it without putting n dealings on-chain in the happy path:
- Each dealing is signed by its slot (already true). Anyone who has a signed dealing can include it in a
MsgSubmitDevshardT0. - Do not finalize on the first tx. Until
dkg_deadline, the keeper unions valid dealings by slot id from every submit (fullT0or a one-dealing fragment).PKis the product over that union at the deadline, not over a preferred blob. - Happy path: one listed host submits one complete
T0(all p2p dealings). Omitted host: one small extra submit of their signed dealing; it merges.
A listed host who never dealt p2p and never submitted a fragment is absent, not censored.
6.3 Off-chain dealing window
Listed hosts watch devshard_escrow_created. Each host i ∈ slots that participates:
- Builds ceremony id (§7).
- Samples polynomial
f_iof degreet-1. - P2p-broadcasts one signed dealing (Feldman
C_i, per-recipient ElGamal + DLEQ, Schnorr onA_i, identity signature). Ciphertexts cover the fullslotslist. - Collects peers’ dealings, verifies §5.1, decrypts own shares. Does not freeze
sk_iuntil the chain deadline (the accepted set may still grow).
Any listed host may then submit:
MsgSubmitDevshardT0 {
creator // must be ∈ slots
escrow_id
dealings // 1..n signed dealings (full T0 or a fragment)
pk // claimed product; must match recompute over
// (existing union ∪ these dealings) at finalize
}
Keeper, per dealing in the message:
- Escrow exists, not settled,
dkg_status == PENDING, height< dkg_deadline. - Dealer ∈
slots; if that slot already has a dealing in the union, the new one must be byte-identical (else reject that dealing). ceremony_idmatches §7.- Identity signature is that slot’s account key.
- Schnorr + all DLEQs (§5.1–§5.2).
- Ciphertexts addressed to the full
slotslist.
Admit each valid dealing into the escrow’s union. Invalid dealings are skipped; they are not disputes. Claimed pk is not stored until the deadline (recomputed from the union).
Fee is 0 when the Cosmos signer is a listed slot (§6.5).
6.4 Deadline aggregation (chain freezes T0)
At dkg_deadline, let D be the union of admitted dealings, ordered by slot index.
- If
|D| < t(ormin_dealers):dkg_status = FAILED. NoPK. - Else:
PK = ∏_{i ∈ D} A_i(ignore the claimedpkexcept as a sanity check: mismatch → still use the recomputed product, or fail the artifact if a submit insisted on a wrongpk— normative: always recompute)- Derive
PK_i - Persist
T0 = (ceremony_id, slots, D, PK, …),t0_hash,dkg_status = COMPLETED - Emit
devshard_dkg_completed
The submitter never chooses the product. They only relay signed dealings the chain re-checks.
Accepted dealers set sk_i = ∑_{j ∈ D} f_j(i) from ciphertexts in the frozen T0 (same bytes they already had p2p if the union matches).
MsgCreateDevshardEscrow
│
▼
slots listed, dkg_status=PENDING, deadline set
│
▼
p2p NIZK dealings among slots
│
▼
MsgSubmitDevshardT0 (artifact or fragment, gas-free, window open)
│ union more T0/fragments until deadline
▼
dkg_deadline EndBlocker
│
├── |D| < t → FAILED
└── |D| ≥ t → T0 := union D, PK := ∏ A_i, COMPLETED
6.5 MsgSubmitDevshardT0 is gas-free
Plan: listed hosts post the artifact (or a missing-dealing fragment) with zero gas fee. Create already paid; the signer must be ∈ slots. That is spam protection — at most a handful of T0 txs per escrow, not an open faucet.
Ante (cheap, before DLEQ verify): 0 fee only if:
- msg type is
MsgSubmitDevshardT0; - escrow
PENDING, height< dkg_deadline; - signer ∈
slots.
Anyone else pays the normal min fee.
Still meter gas. Cap dealings per tx and bytes. Prepaid verify budget (from CreateDevshardFee) decrements on each dealing verified (success or fail) so a listed host cannot loop junk proofs for free forever.
7. Ceremony id
Computed by hosts and by the keeper. Suggested preimage (canonical protobuf / byte encoding TBD):
ceremony_id = H(
"gonka/devshard/dkg/v1" ||
chain_id ||
escrow_id ||
epoch_index ||
model_id ||
app_hash || // create-time, already on escrow
encode(slots) || // ordered addresses as stored
n || t
)
Every NIZK challenge and every dealing signature MUST include ceremony_id. That is what stops:
- replaying another escrow’s
T0; - mixing dealers from a different slot list;
- using a
PKgenerated offline, or from a subset packed by one submitter.
Reshare rounds use a different domain (dkg/v1 vs reshare/v1) and bind round k plus the new slot list (§11). Genesis dealings cannot be replayed as reshares.
8. T0 artifact
T0 is public. It MUST NOT contain secret polynomials or decrypted sk_i.
Minimum contents:
- version,
ceremony_id,n,t - full eligible
slots(create-time list) - accepted dealer set
D ⊆ slots(those with a valid dealing by the deadline) - per dealer in
D: the dealing already verified at submit time - derived
PKandPK_i(recomputable)
T0 is the concatenation of keeper-accepted dealings plus the EndBlocker product. It is not a message someone uploads.
Storage:
- Dealings live in submitted
T0/ fragments until the deadline; then the escrow points at the frozen union (t0_hashover canonical encoding). - Must persist
PKandH(T0). Full dealings stay on-chain (n = 16). Do not skip NIZK verify at submit and keep only a laterPK.
Hosts keep sk_i in local sealed storage (same class of problem as escrow-keys-at-rest.md, but for BLS shares).
9. Cryptographic profile (v1)
| Item | Choice |
|---|---|
| Curve | BLS12-381, PK and commitments in G2 (same convention as current x/bls) |
| Signatures later | threshold BLS, signatures in G1, hash-to-G1 |
| Sharing | Shamir, degree t-1 |
| Encryption | Same-group hashed-ElGamal: pk_j = g^{x_j} in G2 (§5.2). Not secp256k1 ECIES. |
| PoK | Schnorr NIZK on A_i, Fiat–Shamir with ceremony_id |
| Share NIZK | Chaum–Pedersen DLEQ per recipient (§5.2). Groth 2021 is not v1. |
| Identity sig | secp256k1 over the dealing body |
Do not use interactive Feldman + verification-vector acks for this ceremony.
10. Using PK after COMPLETED
- Clients / other shards learn
PKfrom escrow query. They verify BLS signatures againstPK. They do not needT0unless they audit origin. - Telemetry (the consumer this DKG is for). Gossip
Verify(PK, load_attestation, σ)across chain participants (What this buys). - Settlement (optional encoding). The keeper may accept
Verify(PK, settlement_digest, σ)as a compact stand-in for slot signatures /CommitQC. That does not replace droppingsettler == Creatoror the finalization commit procedure. Per-slot signatures remain sufficient. - Partial signatures during the session still use
sk_i/PK_iamong hosts; aggregation is off-chain.
Until COMPLETED, gateways must not treat the escrow as live.
11. Resharing ceremony (math)
Join/leave is a membership tx on mainnet (add host / remove host). That tx is what changes slots. Recreating the escrow is unnecessary even with secp-only settlement.
This section is only for keeping an already issued PK after that tx. A new DKG would sample a new sk and a new PK, breaking telemetry verifiers that cached the old key. Resharing produces a fresh Shamir sharing of the same sk for a new player set (n', t'). Who may add or remove, and how new_slots is chosen, belong on the membership tx — not here.
11.1 What is already known
After genesis (or after T_{k-1}), there is a unique polynomial F of degree < t with F(0) = sk and PK = g^{sk}.
Old player i holds sk_i = F(i). Everyone can compute the public share
from the previous verification vector (evaluate commitments at i). The chain stores PK and the PK_i for the current committee.
Write λ_{i,Q}(0) for the Lagrange coefficient of old id i in a set Q of size t, interpolating at 0:
Any honest t-set Q of old shares satisfies ∑_{i ∈ Q} λ_{i,Q}(0) · sk_i = sk, hence
That identity is what a reshare must preserve. It is not the genesis rule PK = ∏ A_i (sum of fresh secrets). Mixing the two aggregations would yield the wrong key.
11.2 Each old holder re-shares sk_i
Old dealer i does not sample a new a_{i,0}. They sample a polynomial g_i of degree < t' with constant term equal to their existing share:
Verification vector C'_i = (g^{g_i(0)}, g^{g_i,1}, …, g^{g_i,t'-1}). Encrypted values g_i(j) for every new player id j in the new slot list (size n'). Same NIZK dealing shape as genesis: PoK of dlog of C'_i[0], share-correctness of the ciphertexts.
The binding that this is a reshare of the shard key, not a new DKG:
If that fails, the dealing is invalid. A dealer cannot re-share an arbitrary scalar and still pass.
Ceremony id for round k (hosts and keeper):
reshare_id = H(
"gonka/devshard/reshare/v1" ||
chain_id || escrow_id || k ||
encode(old_slots) || encode(new_slots) ||
t || t' || PK
)
NIZKs and dealing signatures bind reshare_id. Ciphertexts are addressed to new_slots, not to the old list.
11.3 Deadline set and canonical interpolating set
Each old slot that still holds sk_i p2p-broadcasts one reshare dealing. Same inclusion as genesis: signed dealings, MsgSubmitDevshardTk (or reuse T0 msg shape) relays the artifact; union until reshare_deadline; take every valid dealing D.
If |D| < t, the round fails. PK unchanged; old shares still work. No T_k.
If |D| ≥ t, let Q be the canonical t-subset of D (lowest old slot indices in D). New shares and the new verification vector are interpolated from Q only. Extra valid dealings (D \ Q) are stored and checked (C'_i[0] = PK_i) but do not enter Lagrange — using |Q| ≠ t in the sum below would be the wrong degree.
This is the dual of genesis “product of all A_i”: here the secret is already fixed, so the combinator is Lagrange on a t-set, not a product over everyone who showed up.
11.4 New shares
New player j decrypts g_i(j) for each i ∈ Q and sets
Then sk'_j = F'(j) for a unique F' of degree < t' with F'(0) = sk. In general sk'_j ≠ sk_j even if j was already in the old committee.
Public new verification vector (homomorphic, chain-computable):
Constant term:
That is the keeper check that the reshare did not change the root key. New public shares PK'_j = C'(j) (evaluate C' at new ids). Old sk_i for members who left are useless for F'; they cannot sign under the new sharing.
Add is the same formulas with n' > n (new ids appear in the ciphertext list). Remove is n' < n (left ids get no new share). t' may equal t.
11.5 T_k
Chain-built, like T0:
reshare_id, old slots, new slots,t,t',Q,D- each accepted reshare dealing
- stored
PK(must equalC'[0]) - new
PK'_j
Third parties: origin is still T0; current custody is T_k. Signature verify uses PK only.
Who may open a reshare round is the membership tx (or a follow-on after it). Fee exemption for reshare txs is not specified here. The math does not depend on them.
12. Open questions
- Minimum
|D|. Defaultt(11 of 16) matches signing quorum. A highermin_dealers(e.g.n-f) makes post-DKG liveness safer if more hosts drop. Not a trust issue if §6.2–§6.4 hold. - Warm vs cold key. Dealings must be signed by the same key the chain uses to identify
slots[j](cold / account). Warm keys stay for session traffic, not for DKG identity. - Library / encodings. Freeze Schnorr + DLEQ encodings (§5.2) before proto freeze. Groth 2021 is not required.
- Failed DKG refunds — exact reuse of
refusal_timeoutvs a dedicated DKG fail handler.
13. Contrast with current x/bls epoch DKG
Epoch x/bls today |
This proposal | |
|---|---|---|
| Scope | whole epoch validator set | one escrow’s slots |
| Lifetime | new key every epoch | PK stable for the escrow |
| Dealings | Feldman + private share check | p2p Feldman + Schnorr + DLEQ; chain re-verifies T0 (§5–§6) |
| Phases | DEALING → VERIFYING → COMPLETED | p2p deal → submit artifact → deadline freeze T0 |
| Disputes | verification vectors / implicit complaints | none (bad dealing omitted from union) |
| Proof of origin | not aimed at third parties per escrow | frozen T0 on the escrow |
| Chain role | collect parts, then aggregate C_k0 |
re-verify artifact, union fragments, PK = ∏ A_i |
Do not overload InitiateKeyGenerationForEpoch for devshards.
14. Implementation sketch (when scheduled)
- Params:
dkg_timeout_blocks, optionalmin_dealers; proto fields onDevshardEscrow;MsgSubmitDevshardT0. - Ante:
MsgSubmitDevshardT0is gas-free when signer ∈slots(§6.5), plus prepaid verify budget. - Host: p2p NIZK deal, submit artifact with 0 fee, at deadline persist
sk_ifrom frozenT0. - Keeper: §6.3 per-dealing checks on the artifact; union fragments; EndBlocker §6.4.
- Tests: cancellation fails verify; wrong
escrow_idrejected; omitted dealing still counts if submitted as a fragment; finalize only at deadline;PK = ∏ A_iover union; unlisted signer not fee-exempt. - Later: telemetry gossip; optional compact BLS settle encoding; reshare p2p +
T_kafter a membership tx ifPKmust stay stable (§11).
💬 Комментарии (2)
Комментарий 1 — @vitaly-andr
2026-09-10 14:31 UTC
One thing worth knowing before you settle the "failed DKG refunds" question, since it touches the mechanism you would most likely reuse: the existing refund-on-failure path is currently not wired up.
InvokeSetBlsHooks (x/bls/module/module.go:243) asks depinject for *keeper.Keeper, while
ModuleOutputs provides the keeper by value (module.go:214-218). Nothing provides the pointer,
invoker dependencies are optional, so the parameter arrives nil and the guard at the top returns
without calling SetHooks. Hooks() then keeps returning the empty implementation, and both
AfterThresholdSigningFailed and AfterThresholdSigningCompleted are no-ops in any app built this
way. I confirmed it in a simulation run where a bridge mint's signature expired after the usual three
attempts and the inference-side failure hook never fired.
Filed with the details in #1749. Raising it here because a per-escrow DKG that leans on the same
hook surface for its own failure handling would inherit the same silence, and because the choice
between "reuse refusal_timeout" and "a dedicated DKG fail handler" reads differently once you know
the current handler is not reached at all.
↳ Ответ от @aikuznetsov · 2026-09-10 15:34 UTC
Thanks for catching this — the concern looks valid.
We should fix the existing BLS hook wiring as part of this work, or preferably as a prerequisite, since it already affects the current threshold-signing failure and completion paths independently of the proposed per-escrow DKG.
For the DKG implementation, we should also add an integration test that exercises the complete failure path through the actual app wiring and verifies that: - the escrow transitions to
DKG_FAILED; - the expected refund is executed; - the registered failure handler is actually invoked.
↳ Ответ от @akup · 2026-09-10 17:09 UTC
I think that it is possible that
x/bls/module/module.gowill not be used as it is.Most important thing here we need to use NIZK for share dealing, that is currently not used. It eliminates disputes and also helps to publish verifiable artifact to prove public key that we generate with DKG belongs to the devshard. Also it is absolutely another module and it is not intersecting with current bridge BLS
Also current proposal is currently draft and far away from implementation, it is to discuss the idea and concept
Комментарий 2 — @aikuznetsov
2026-09-10 15:27 UTC
I like the original idea, especially removing the sequencer as the single authority capable of closing an escrow. A chain-verifiable committee authorization mechanism would make devshards substantially more resilient to a cheating or unavailable sequencer.
My main concern is the increase in devshard startup time.
Today, escrow creation requires one transaction and the shard can start almost immediately. With the proposed DKG, the escrow remains PENDING until dkg_deadline, even if enough—or all—dealings arrive earlier. Depending on dkg_timeout_blocks, this could increase startup time from roughly one block to tens of seconds or more.
Have we considered alternative approaches or a phased implementation?
| Option | Expected startup | Advantages | Disadvantages |
|---|---|---|---|
| 1. Keep the existing 11-of-16 secp256k1 slot signatures and remove the creator-only restriction | ~1 block | Smallest protocol change; immediately solves the main self-close problem; any relayer can submit a settlement authorized by the existing quorum | Larger settlement proof; no stable per-devshard public key; committee changes require updating the authorization set |
| 2. Pre-register an individual BLS key with proof-of-possession for every host, then use an aggregate signature plus a signer bitmap | ~1 block | Constant-size aggregate signature; no per-escrow DKG; efficient quorum verification; suitable for settlement and signed telemetry | The effective verification key depends on the signer bitmap and committee version; no single stable PK across membership changes |
| 3. Keep the proposed threshold DKG, but add an optimistic 16-of-16 fast path | ~2–3 blocks in the healthy case; full deadline otherwise | Preserves the stable root PK, resharing, and the complete security model of the proposal; if every listed slot submits, nobody can have been omitted |
Still requires complex NI-DKG/PVSS implementation; an offline host disables the fast path and startup falls back to the full deadline |
For option 3, the rule could be:
```text all 16 valid dealings received → finalize immediately 11–15 valid dealings received → wait until dkg_deadline and include all received dealings fewer than 11 at deadline → DKG_FAILED
↳ Ответ от @akup · 2026-09-10 17:04 UTC
Actually, I think we can already start to use devshardEscrow immediately without waiting for DKG. As it's finalization is for settlement and load share. It seams to be ok to wait 10-20 seconds before we can start settle and share load.
Also I think it's not so bad to wait even 20 seconds before we start. In case of gateway it has multiple devshards and can wait for new ones to start without downtime visible for enduser. In case when user creates devshard wscrow on his own, it also seams to be ok to wait 20 seconds, and then use it during one epoch (around 24 hours)