Review round 3: spec rules for F15, F17, F14, P11, E9, E10, G9; ledger and fixes rows
The four public sentences (F18, P13, E11, L7 in site/litepaper.html and site/index.html) were swept into the concurrent commit cd604db; this commit carries the rest. Spec 02: finality depth (43,200 DAA s, 12 h of median time) named as the reorg bound, merge depth as a merge limit only, simnet reorg test for gate 2; emission follows the code (365.25-day year, 63,115,200-s halving, 31.688 IGN per DAA second, reds inside the DAA window paid to the merger, E paid per block so coins are blocks times E). Spec 03: W2 and Q1 denominated in past-median time, weight as a share of each 60-s bucket; W6 keys are free, weight is the only Sybil-resistant quantity; 3.8 and 3.9 point exchanges at the finality depth. Spec 06: O-3.14, the finality simulation with the DAA in the loop under a pulsed rental (gate 3). Spec 07: shard sortition draws by weight (blue blocks drawn uniformly from the window); proof-record validity is relative to the carrying block's own selected-parent chain; 1-key-versus-1,000-keys test. Spec 08: release-key chain, rotation signed by the current key, revocation signed by the previous key, both published in a block; policy before the client ships. Ledger: status lines for F18, P13, E11, L7, P11, F17, F14, M14, F15, E9, E10, G9; P8 cross-reference. Fixes: section 2.2 rows 75 to 88, with M15, M20 and P12 marked code, owner consensus engineer. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
6a8acc24f5
commit
09900b9432
7 changed files with 71 additions and 41 deletions
|
|
@ -118,6 +118,29 @@ Who: the project lead (decision or account), Claude (text, spec, code, simulatio
|
|||
| C1, C12 | Item 68 | 33 |
|
||||
| L6 | Counsel before phase 4 | 59 |
|
||||
|
||||
### 2.2 Round 3 entries (3 October 2026, evening)
|
||||
|
||||
Added after `docs/review/round-3-2026-10-03.md`. Rows continue the numbering of section 2. "code, owner consensus engineer" marks a row that needs node code and is not Claude's text work; the ledger status for those stays as the review left it.
|
||||
|
||||
| # | Ledger | Issue | Fix | Who | When | EXPOSES |
|
||||
|---|---|---|---|---|---|---|
|
||||
| 75 | F18 | LP Finality: "a silent minority cannot freeze finality and a lock never waits for miners who have left" | Fixed 3 October 2026: the exchange engineer's replacement sentence in LP Finality; "Finality that never pauses" item added to "What Igneum does not claim" | Claude | done | no |
|
||||
| 76 | P13 | LP Proving: "Miners claim shards with a small bond" | Fixed 3 October 2026: "Shards are assigned by lot to eight provers for ten seconds, then open to anyone; there is no bond" | Claude | done | no |
|
||||
| 77 | E11 | HP tile "IGN burned from jobs, at launch"; the quoted paragraph had already left the trimmed page | Fixed 3 October 2026: tile reads "phase two"; caption adds "Jobs are paid on the customer's chain at launch; settlement in IGN with a 10% burn follows the proof bridge in phase two" | Claude | done | no |
|
||||
| 78 | L7 | LP Economics heading "Where the price comes from" and the burn-reduces-supply sentence | Fixed 3 October 2026: heading "Where fees go", sentence deleted. Counsel reads the section under row 46 | Claude; counsel | done; before public repo | no |
|
||||
| 79 | P11 | Native-execution veto written against the node's current selected chain | Spec 7.2 item 5 rewritten 3 October 2026, relative to the carrying block's own selected-parent chain. Left: `docs/design/execution-layer.md` 5.5 to match, and the two-node reorg test in its 8.5 | Claude | now | no |
|
||||
| 80 | F17, P8 | Shard sortition per key; keys are free; launcher mints 8 per card | Spec 7.2 step 2 draws by weight and spec 3.1 W6 states the principle, 3 October 2026. Left: client default of one vote key per operator (`MINERS` multiplies workers, not keys); S2 and the bitmap size (O-3.5, O-3.12) before the voter count can cross 8,192 | Claude (spec, done); miner client (default) | before testnet | no |
|
||||
| 81 | M14, F14 | Weight and presence windows in DAA seconds under a lagging retarget; no finality run with a DAA model | Spec 3.1 W2 and 3.3 Q1 in past-median time, weight per 60-s bucket, 3 October 2026 (simulated form kept beside it). O-3.14 added: `finality_v2.py` with the DAA in the loop, 50x pulsed renter, both W2 forms, logged in the bench-log. Controller choice is gate 2 (O-2.1) | Claude (spec, done); measurement (O-3.14) | before testnet | no |
|
||||
| 82 | F15 | Merge depth called the reorg bound; the code's bound is the finality depth, 43,200 DAA s | Spec 2.1, 3.8 and 3.9 name the finality depth, in median time (12 h), 3 October 2026; simnet reorg test (2, 6, 13 h forks) written into 2.1 for gate 2. Left: LP Finality "Kaspa's one-hour merge-depth bound limits any reorganisation" and "What Igneum does not claim" item 4 "bounded to one hour" | Claude (LP text); measurement (simnet) | now (LP); before testnet | no |
|
||||
| 83 | E9 | Spec year 365 days; code 365.25 (31,557,600 s, halving 63,115,200 s, 3,168,808,781 sompi/s) | Spec 2.5 follows the code, 3 October 2026. Divergence record for the code owner: the spec was changed, the code was not; add a test that reads the published numbers (year, halving interval, per-second rate, ramp) and asserts them against `consensus/core/src/igneum.rs`, and decide O-2.6 (8 decimals fits the u64 cap, 18 does not) before the first testnet genesis | code, owner consensus engineer | before testnet | no |
|
||||
| 84 | E10 | Spec said reds unpaid and "more blocks never means more coins"; code pays reds in the DAA window to the merger and mints per block | Spec 2.5 follows the code, 3 October 2026. Divergence record for the code owner: no code change; the litepaper Speed sentence "Emission is paid per unit of difficulty-adjusted work, never per block, so a faster chain never means more coins" is now wrong and must be rewritten (schedule in DAA seconds, paid per block, short-run rate set by the controller) | Claude (LP text) | now | no |
|
||||
| 85 | G9 | Release key: single steward, lost key unrevocable | Spec 8.2 items 2 and 5 rewritten 3 October 2026: key chain, rotation signed by the current key, revocation signed by the previous key (pre-signed certificate for K0), published in a block; policy before the client ships, with entity and jurisdiction. Left: the policy itself and the second holder (O-8.1, L1) | the project lead (custody), counsel | before testnet | EXPOSES: the policy names the entity, never a person's residence |
|
||||
| 86 | M15 | Pre-validation PoW cost: any past timestamp or claimed DAA score forces a 256 MiB cache fill before the checks that would reject the header | Run `check_difficulty_and_daa_score` and the past-median check before `check_pow_and_calc_block_level` in `validate_header`; derive the day from DAA score or the selected parent's window; `KEEP` 4; per-peer cap on cache builds. Review's first of five | code, owner consensus engineer | now | no |
|
||||
| 87 | M20 | Pruning proofs validated with the kHeavyHash stub: a fresh node cannot sync from a lottery-mined pruning point; a loosened check is forgeable with an existing ASIC | Thread the epoch and day seeds through `pruning_proof/validate.rs`, `apply.rs` and `mod.rs` (fork map a4, O-2.5); test by syncing a fresh node from the 30-hour devnet | code, owner consensus engineer | before testnet | no |
|
||||
| 88 | P12 | An aggregator rewrites `ProofRecord.provers` and takes the pool; shard proofs do not commit to the prover | Shard statement gains the prover's payout key as a public input, aggregation carries the keys as public outputs, a record whose list does not match is invalid; acceptance test A5 checks the match. Spec 7 and `docs/design/execution-layer.md` 5.1, 5.6 and 9.2 change with the code | code, owner consensus engineer (with execution engineer) | before testnet | no |
|
||||
|
||||
Not yet rowed from round 3: M16, M17, M18, M19, M21, F16, P14, P15, C13, L8, G10, X12. Their fixes are in the ledger entries.
|
||||
|
||||
## 3. Overclaims still in public text today
|
||||
|
||||
Checked against the files this evening. "present" means the quoted text is still live. "missing" means the item is an addition that has not been made. "fixed" means the replacement is in. Line numbers are from the stripped page text, not the HTML.
|
||||
|
|
|
|||
|
|
@ -338,7 +338,7 @@ Status: Closed by rule (3 October 2026). Spec section 7.2: sortition keyed to th
|
|||
|
||||
Answer: Fair, and the lottery/proving separation does not by itself fix it. If claims are first-come, latency wins. The candidate rule is sortition of shards: a VRF keyed to the block assigns each shard to a set of eligible provers, weighted by past proving or by a lottery, with fallback to open claiming after a timeout. This is a phase 1 specification item and a phase 4 devnet measurement. The 20% proving pool is paid per block as a fixed amount divided by consensus proving cost, so a prover's income is bounded by the shards it is assigned, not by how many it can grab.
|
||||
|
||||
Evidence: design doc "Proving speed on consumer GPUs" risk item and Finality v2 "Fees". Rule: not yet. Cross-reference (round 3, 3 October 2026): F17 reopens the per-key draw of spec 7.2, which a key-splitter sweeps by count.
|
||||
Evidence: design doc "Proving speed on consumer GPUs" risk item and Finality v2 "Fees". Rule: not yet. Cross-reference (round 3, 3 October 2026): F17 reopened the per-key draw of spec 7.2, which a key-splitter sweeps by count; spec 7.2 step 2 was rewritten the same evening to draw by weight (blue blocks drawn uniformly from the window), so this entry stays closed.
|
||||
|
||||
### P9. Shard griefing
|
||||
"Claim a shard with a small bond and never prove it. Repeat. Finality waits on you."
|
||||
|
|
@ -1042,7 +1042,7 @@ Added by `docs/review/round-3-2026-10-03.md`, which holds the full argument for
|
|||
### M14. A pulsed rental against the block-count DAA buys weight at a discount
|
||||
"Bring 50x the hashrate for two minutes once an hour. Kaspa's window keeps the 661 most recent samples, so you mine thousands of blocks at the old target before it moves, and when you leave the honest network crawls for hours at your difficulty. Weight is blocks over a window of blocks. You get a third of the window in a week for the price of a 1.6x average."
|
||||
|
||||
Status: Open, experiment scheduled.
|
||||
Status: Open, experiment scheduled as O-3.14 (3 October 2026). The weight half is written into the spec, see F14; the controller half is gate 2 (O-2.1).
|
||||
|
||||
Answer: Correct in mechanism and unmeasured in size. `sim/results_v2.md` runs every scenario with a perfect retarget (its assumption table) and no finality run has a DAA model (O-3.9). Tonight's honest step on the devnet showed the lag: 5.67 blocks a second in a two-minute bucket after the first retarget, 2,248 blocks in eight minutes against 480 expected, and 1.5 blocks a second an hour later (`docs/review/round-3-2026-10-03.md`, "Tonight's devnet"). The review's estimate is that a pulse buys under two windows of blocks (about 5,000) and the chain crawls after each, so the amplifier over the formula is about 2x at the cost of a visible attack; the estimate is not a simulation. The same lag is the farm operator's hop profit (`sim/difficulty/sim.py` profiles `hop3`, `hop10`, `polluted`), for which no result is in the bench-log. Fix in two parts: the controller (gate 2, O-2.1, with the simulation results logged) and the weight rule (F14).
|
||||
|
||||
|
|
@ -1114,7 +1114,7 @@ Evidence: spec 2.1; `docs/design/execution-layer.md` 5.4. Review id R3.4.
|
|||
### F14. Weight in blocks over a window in blocks under a lagging retarget
|
||||
"Your day counts assume the block supply is capped at one a second. It is not during a retarget lag, and weight is counted in blocks."
|
||||
|
||||
Status: Open, rule change proposed.
|
||||
Status: Rule written (3 October 2026): spec 3.1 W2 and 3.3 Q1 are denominated in past-median time, weight as a key's share of each 60-s bucket summed over 30 days; the simulated DAA-score form is kept beside it. O-3.14 (added the same evening) confirms or reverts it at gate 3. Was: Open, rule change proposed.
|
||||
|
||||
Answer: Correct; this is the finality half of M14. Spec W2 counts blue blocks over a window of 2,592,000 DAA seconds, and DAA seconds are blocks, so a burst both inflates a key's count and ages the window. Proposed change: denominate the vote window (W2) and the presence window (Q1) in past-median time, and define weight as a key's share of the blue blocks in each 60-second median-time bucket summed over the trailing 30 days, so 50x the blocks in one minute is one minute of weight. The simulation of M14 decides.
|
||||
|
||||
|
|
@ -1123,7 +1123,7 @@ Evidence: spec 3.1 W2, 3.3 Q1; `sim/results_v2.md` assumptions. Experiment: the
|
|||
### F15. Merge depth is not the reorg bound; the finality depth is
|
||||
"You tell exchanges that in month one the one-hour merge-depth bound limits a reorganisation. `check_bounded_merge_depth` only forbids merging an old red. The virtual switches to any heavier chain until the finality point, which you kept at 12 hours."
|
||||
|
||||
Status: Open, text and rule fix named.
|
||||
Status: Spec fixed (3 October 2026): spec 2.1 names the finality depth as the reorg bound and merge depth as a merge limit only, spec 3.8 and 3.9 tell exchanges to wait 12 hours of past-median time when `finality_active` is false, and the simnet reorg test is written into 2.1 for gate 2. Still to change: the litepaper Finality sentence ("one-hour merge-depth bound") and "What Igneum does not claim" item 4 ("bounded to one hour"). Was: Open, text and rule fix named.
|
||||
|
||||
Answer: Correct on reading the fork. `post_pow_validation.rs:79` bounds which reds a block may merge; the selected-chain switch is bounded by the finality point (`virtual_processor/processor.rs:1626`, `FINALITY_DURATION` 43,200 DAA seconds). So the month-one reorg bound is 12 hours of DAA time, not one hour, and spec 3.8, 3.9, litepaper "Finality" and "What Igneum does not claim" item 4 rest on the wrong constant. Fix: state the finality depth as the bound, in median time (M14 explains why not DAA time), or lower `FINALITY_DURATION` and accept Kaspa's finality-conflict handling at that depth; test with a heavier private chain forked 2, 6 and 13 hours back on simnet.
|
||||
|
||||
|
|
@ -1141,7 +1141,7 @@ Evidence: spec 3.5, 3.9. Review id R3.17.
|
|||
### F17. Keys are free and the official client mints eight per card
|
||||
"Your launcher runs 8 identities per vendor, each with its own vote key. For the vote that is harmless by design. For shard sortition, which ranks every eligible key and takes 8, it is the whole game: 1% of hashrate holds 259 keys above dust. And a few thousand PCs cross your 8,192-voter switch, whose construction is open."
|
||||
|
||||
Status: Open, rule change proposed. Reopens P8.
|
||||
Status: Rule fixed (3 October 2026): spec 7.2 step 2 draws the 8 assignees by weight (blue blocks drawn uniformly from the window, their keys assigned, with the 1-key-versus-1,000-keys test in O-5.1), and spec 3.1 W6 states that keys are free and weight is the only Sybil-resistant quantity. Still open: the client's one-key default, S2 (O-3.5) and the bitmap size (O-3.12). P8 stays closed. Was: Open, rule change proposed. Reopens P8.
|
||||
|
||||
Answer: Correct. Spec 7.2 step 2 ranks per key and eligibility is 100 blue blocks in 30 days (0.004% of hashrate at one block a second), so a miner with share s holds up to s x 2,592,000 / 100 keys and the draw of 8 is dominated by whoever splits most. `proto-cuda/windows-miner/start-mining.ps1` derives a key per identity (`MINERS` default 8). O-5.1's acceptance test (fastest prover under 25% of shards) does not catch a splitter, who wins by count. Fix: draw the 8 assignees by weight (8 blue blocks uniformly from the window, take their keys), so splitting changes nothing; the client defaults to one key per operator; specify S2 (O-3.5) and the bitmap size (O-3.12) before the count can cross 8,192.
|
||||
|
||||
|
|
@ -1150,7 +1150,7 @@ Evidence: spec 7.2, 3.4; the launcher. Cross-reference added to P8. Review id R3
|
|||
### F18. "A silent minority cannot freeze finality" is false under the floor
|
||||
"Your own simulation: 45% silent stalls finality for as long as they stay silent, 40% gives 138 stalls in three days, 50% churn stalls 4.1 days. The litepaper says a silent minority cannot freeze it and a lock never waits for miners who have left."
|
||||
|
||||
Status: Conceded, not yet stated; text fix named.
|
||||
Status: Fixed (3 October 2026). `site/litepaper.html` Finality carries the replacement sentence and "What Igneum does not claim" carries the pause item ("Finality that never pauses"). Was: Conceded, not yet stated; text fix named.
|
||||
|
||||
Answer: Correct. The sentence was true of the active-only rule and was not updated when the 56.7% floor was added (spec 3.3.1 states the liveness cost honestly: liveness ends between 40% and 45% silent). Fix: the replacement sentence in the review (exchange engineer, sentence), and a line in "What Igneum does not claim".
|
||||
|
||||
|
|
@ -1159,7 +1159,7 @@ Evidence: `sim/results_v2.md` C and D; spec 3.3.1; `site/litepaper.html` Finalit
|
|||
### P11. The native-execution veto makes block validity depend on the node's current selected chain
|
||||
"Section 5.5: a block is invalid if a proof record names a segment not on the node's selected chain, or disagrees with the node's own execution. Two honest nodes with different tips disagree on the same block. You removed the hidden-block penalty for this exact reason."
|
||||
|
||||
Status: Open, text fix named.
|
||||
Status: Fixed in the spec (3 October 2026): spec 7.2 item 5 is relative to the carrying block's own selected-parent chain and supersedes the design document's 5.5 wording. Still to follow: `docs/design/execution-layer.md` 5.5 itself and the two-node reorg test in its 8.5. Was: Open, text fix named.
|
||||
|
||||
Answer: Correct. `docs/design/execution-layer.md` 5.5 (D12) and spec 7.2 item 5 reference the node's selected chain, which is a property of its virtual, not of the block's past. Fix: a proof record is valid if the chain block it names is on the carrying block's own selected-parent chain and its `post_root` and receipts equal the execution of that segment along that chain, which every node computes from the block's past. Add a two-node reorg test to section 8.5.
|
||||
|
||||
|
|
@ -1177,7 +1177,7 @@ Evidence: `docs/design/execution-layer.md` 5.1, 5.4, 5.6, 9.2 A5. Review id R3.1
|
|||
### P13. The litepaper still claims shards with a bond
|
||||
"'Miners claim shards with a small bond.' Your spec 7.2 decided sortition with no bond the same day."
|
||||
|
||||
Status: Conceded, fix now.
|
||||
Status: Fixed (3 October 2026): `site/litepaper.html`, Proving, "How a block gets proven". Was: Conceded, fix now.
|
||||
|
||||
Answer: Correct. Fix: "Shards are assigned by lot to eight provers for ten seconds, then open to anyone; there is no bond." (`site/litepaper.html`, Proving, "How a block gets proven".)
|
||||
|
||||
|
|
@ -1204,7 +1204,7 @@ Evidence: spec 7.1; `docs/design/execution-layer.md` 8.2. Review id R3.12.
|
|||
### E9. The specification's year is 365 days; the code's is 365.25
|
||||
"Spec 2.5: 31,536,000 DAA seconds a year, halving every 63,072,000, about 31.7098 IGN a second. `igneum.rs`: 31,557,600, 63,115,200, 31.688 IGN. Which one is the money?"
|
||||
|
||||
Status: Open, decision now.
|
||||
Status: Fixed (3 October 2026): spec 2.5 follows the code (365.25-day year, 63,115,200-s halving, 31.688 IGN per DAA second, 8 decimals noted under O-2.6). The test that asserts the published numbers against `igneum.rs` is the code owner's row in `docs/fud-fixes.md`. Was: Open, decision now.
|
||||
|
||||
Answer: Correct. `consensus/core/src/igneum.rs` (`SECONDS_PER_YEAR = 31_557_600`, `HALVING_INTERVAL_SECONDS = 63_115_200`, `BASE_SUBSIDY_PER_SECOND_SOMPI = 3_168_808_781`) and spec 2.5 disagree; `docs/fork-divergence.md`'s per-second table follows the code. Fix: pick one (the code's values are tested and summed under the cap) and rewrite spec 2.5 and the litepaper's schedule to match, with a test that asserts the published numbers against the code.
|
||||
|
||||
|
|
@ -1213,7 +1213,7 @@ Evidence: the two files. Review id R3.19.
|
|||
### E10. Reds are paid in the code and "more blocks never means more coins" is false
|
||||
"Spec 2.5: red blocks are unpaid, emission is keyed to DAA score so more blocks never means more coins. `coinbase.rs` pays a red's 80% to the merging miner and its 20% to the pool, and every blue block in the DAA window mints `E(daa)`. Tonight your chain minted 4.7x the schedule for eight minutes."
|
||||
|
||||
Status: Conceded, text fix named.
|
||||
Status: Fixed (3 October 2026): spec 2.5 says reds inside the DAA window are paid to the merging miner (80%) and the pool (20%), that `E` is paid per block so coins are blocks times `E` under the controller's rate, and that the cap is unaffected; "more blocks never means more coins" is withdrawn. The litepaper Speed sentence "never per block, so a faster chain never means more coins" is a separate text fix, rowed in `docs/fud-fixes.md`. Was: Conceded, text fix named.
|
||||
|
||||
Answer: Correct. `consensus/src/processes/coinbase.rs:102` to `109` follows Kaspa's rule for reds; `block_subsidy` is paid per blue (and red) block in the DAA window, so coins are blocks times `E` and the controller's rate sets the short-run emission, as on every proof-of-work chain. Timestamps still cannot mint. Fix: spec 2.5 to say what the code does (reds paid to the merger, emission per block under the controller's rate, the cap unaffected), or the code to say what the spec does; the review recommends the code's rule.
|
||||
|
||||
|
|
@ -1222,7 +1222,7 @@ Evidence: the files; `docs/review/round-3-2026-10-03.md`, "Tonight's devnet". Re
|
|||
### E11. The homepage burns job fees at launch
|
||||
"'Jobs through Igneum's own market are paid in IGN and 10% of each fee is burned', with a tile 'IGN burned from jobs, at launch'. Your spec 5.4 settles launch jobs on the customer's chain with no burn. You fixed the litepaper (P10) and left the homepage."
|
||||
|
||||
Status: Conceded, fix now.
|
||||
Status: Fixed (3 October 2026): `site/index.html`, "Proofs sold to other chains" caption and the tile now read "phase two"; the quoted paragraph had already left the page when the homepage was trimmed (commit 047892e). Was: Conceded, fix now.
|
||||
|
||||
Answer: Correct. Fix: `site/index.html`, "Proofs sold to other chains": "Jobs are paid on the customer's chain at launch; settlement in IGN with a 10% burn follows the proof bridge in phase two", and the tile's label to "phase two". Extends P10 and overclaim 52.
|
||||
|
||||
|
|
@ -1240,7 +1240,7 @@ Evidence: none beyond M16. Review id R3.16.
|
|||
### L7. "Where the price comes from"
|
||||
"A heading in a document that says it is not an offer, followed by 'both reduce supply as they happen'. That is a value-accrual argument under a heading about price."
|
||||
|
||||
Status: Open, counsel; text fix now.
|
||||
Status: Fixed (3 October 2026): heading "Where fees go" and the sentence deleted, `site/litepaper.html` Economics. Counsel review of the section remains under L1 and L2. Was: Open, counsel; text fix now.
|
||||
|
||||
Answer: Correct as a reading. Fix: the heading becomes "Where fees go" and the sentence "Demand comes from use of the chain and from outsiders buying proofs, and both reduce supply as they happen" is deleted; counsel reviews the Economics section (L1, L2).
|
||||
|
||||
|
|
@ -1258,7 +1258,7 @@ Evidence: `site/litepaper.html`, Building, Questions builders ask. Review id R3.
|
|||
### G9. The release-key steward is one person, and a lost key cannot be revoked
|
||||
"Spec 8.2: the key that signs the software every miner runs is held by 'the steward named in the published key policy', policy deferred to testnet. And item 5 says a lost key is revoked by its own last signed release, which a lost key cannot sign."
|
||||
|
||||
Status: Open, policy and rule fix named; extends O-8.1.
|
||||
Status: Rule fixed (3 October 2026): spec 8.2 item 5, rotation signed by the current key and revocation signed by the previous key (a pre-signed certificate for K0), both published in a block; item 2 moves the policy to before the client ships and adds the entity and jurisdiction. Steward disclosure itself remains (O-8.1, L1). Was: Open, policy and rule fix named; extends O-8.1.
|
||||
|
||||
Answer: Correct on both. The steward is the control point a regulator writes down, and the revocation path as written freezes the update channel for ever on a lost key. Fix: a pre-signed revocation certificate held apart from the signing key, or a 2-of-3 key set with the policy published before the client ships rather than before testnet; and the entity and jurisdiction that employ the steward named with it (L1).
|
||||
|
||||
|
|
|
|||
|
|
@ -12,14 +12,16 @@ This section is written as a delta on rusty-kaspa. Everything not named here is
|
|||
| GHOSTDAG k | 18 | Kaspa's k table at 1 BPS (fork map f1) | Designed, taken from Kaspa's table (delta 0.01, network delay bound 5 s, `constants.rs:13 to 16`) |
|
||||
| Max parents | 10 | same | Designed |
|
||||
| Mergeset size limit | 180 | same | Designed |
|
||||
| Merge depth | 3,600 DAA s (3,600 blocks at 1 BPS) | `MERGE_DEPTH_DURATION` (fork map e1) | Designed, unchanged from Kaspa |
|
||||
| Finality depth (backstop only) | 43,200 DAA s | `FINALITY_DURATION` | Designed; live finality is section 3 |
|
||||
| Merge depth | 3,600 DAA s (3,600 blocks at 1 BPS) | `MERGE_DEPTH_DURATION` (fork map e1); `check_bounded_merge_depth`, `post_pow_validation.rs:79` | Designed, unchanged from Kaspa. Bounds which red blocks a block may merge; it is not a reorg bound (ledger F15, round 3) |
|
||||
| Finality depth | 43,200 DAA s (12 hours at 1 BPS) | `FINALITY_DURATION`; `virtual_processor/processor.rs:1626` | Designed. The reorg bound a user relies on whenever no certified checkpoint is newer: the virtual switches to any heavier selected chain forked above this depth (ledger F15). Live finality is section 3 |
|
||||
| Pruning depth | 108,000 DAA s | `PRUNING_DURATION` | Designed; MUST stay above the longest checkpoint gap and MUST NOT pass the latest certified checkpoint (section 3, F3) |
|
||||
| Coinbase maturity | 100 blocks | `bps.rs:119 to 121` | Designed |
|
||||
| Block-rate steps | 1, then 4, then 10 per second | design document, decisions table | Designed. Each step is a planned fork with its own test campaign (as Kaspa's Crescendo), taken only once proving lag holds under 60 s. Each step re-derives k, max parents and mergeset limit from Kaspa's table; the DAA-second schedules of sections 1, 3, 4 and 5 do not move |
|
||||
|
||||
Every Kaspa fork activation (`ForkActivation`) is `always()` on Igneum: there is no history to replay (fork map f2). Own genesis, network prefix, ports and seeders (`network.rs:42 to 60, 238 to 252`).
|
||||
|
||||
The reorg bound (ledger F15, round 3). Merge depth limits what an old block can merge; it does not stop the virtual switching to a heavier selected chain. The depth that stops a switch is the finality point, `FINALITY_DURATION`, 43,200 DAA s, and that is the bound users and exchanges rely on whenever no certified checkpoint is newer (section 3.9). It is stated to users in past-median time, 12 hours, because DAA seconds run fast under a retarget lag (ledger M14; `docs/review/round-3-2026-10-03.md`, "Tonight's devnet", where DAA time ran 2.9x the wall clock for 17 minutes). Whether to lower `FINALITY_DURATION` and accept Kaspa's finality-conflict handling at the lower depth is decided at gate 2 with a simnet test: a heavier private chain forked 2, 6 and 13 hours back is released and the node must refuse it at the depth this section names.
|
||||
|
||||
## 2.2 Proof of work (fork points a1 to a5)
|
||||
|
||||
| Fork point | Kaspa today | Igneum |
|
||||
|
|
@ -43,7 +45,7 @@ Kaspa's sampled DAA (KIP-4) is kept as the retarget: average target of a sampled
|
|||
|
||||
What fixes the window: the hash rate steps at every epoch because programs differ in cost (35 to 48 Mhash/s across seeds on the M5 Max, `docs/bench-log.md` first-run entry; 228 vs 185 Mhash/s for 104 vs 128 loads on the RTX 5090). With a 44-minute window a 30% step means roughly half an epoch at the wrong block rate (fork map c1). Two remedies, decided at gate 2 by a simpa run (fork map c2): shorten the window (candidate 1,800 s), or equalise cost per program through the exact-load-count rule of section 1.4.2, which this specification prefers because it removes the step rather than tracking it.
|
||||
|
||||
The 30-day vote-weight window of section 3 is a new reader of DAA scores, not a retarget change.
|
||||
The 30-day vote-weight window of section 3 is denominated in past-median time since 3 October 2026 (section 3.1 W2, ledger F14), so a retarget lag cannot age it; it is not a retarget change.
|
||||
|
||||
## 2.4 Header (fork point d)
|
||||
|
||||
|
|
@ -66,23 +68,23 @@ Designed (design document, "The token" and "Difficulty, block timing and proving
|
|||
| Parameter | Value | Label |
|
||||
|---|---|---|
|
||||
| Hard cap | 4,000,000,000 IGN, approached and never reached | Designed |
|
||||
| Year | 31,536,000 DAA s (365 days) | Designed, prototype value: the design document says "1 billion a year"; the day count is this specification's choice |
|
||||
| Year | 31,557,600 DAA s (365.25 days) | Decided 3 October 2026 (ledger E9, round 3): the specification follows the code, `consensus/core/src/igneum.rs` `SECONDS_PER_YEAR`; the earlier 365-day prototype value is withdrawn. The design document says "1 billion a year" |
|
||||
| Emission in the first two years | 1,000,000,000 IGN per year | Designed |
|
||||
| Halving interval | 63,072,000 DAA s (2 years), for ever | Designed |
|
||||
| Halving interval | 63,115,200 DAA s (2 years of 365.25 days), for ever | Decided (ledger E9), `HALVING_INTERVAL_SECONDS` |
|
||||
| Launch ramp | linear from 10% at genesis to 100% at DAA second 2,592,000 (30 days) | Designed |
|
||||
| Split | 80% block producer, 20% proving pool | Designed |
|
||||
| Base unit | Open (O-2.6): the EVM layer implies 10^18 per IGN; `docs/fork-map.md` b2 wrote `cap_sompi = 4e9 x 1e8`. One of the two is chosen before any coinbase code is written |
|
||||
| Split | 80% block producer, 20% proving pool. A red block inside the DAA window pays its 80% to the miner of the block that merges it and its 20% to the pool | Designed; the red rule Decided 3 October 2026 (ledger E10, round 3), `coinbase.rs:102 to 109` |
|
||||
| Base unit | Open (O-2.6): the code keeps Kaspa's 8 decimals (`SOMPI_PER_KASPA`, devnet v0), under which the cap is 4 x 10^17 units and fits a u64; 18 decimals (the EVM convention) puts the cap at 4 x 10^27 and needs a wider type. `docs/fork-map.md` b2 wrote `cap_sompi = 4e9 x 1e8`. Decided before the first testnet genesis |
|
||||
|
||||
Emission per DAA second at DAA score `t`:
|
||||
|
||||
```
|
||||
E(t) = ramp(t) * floor(10^9 * UNIT / 31,536,000) >> floor(t / 63,072,000)
|
||||
E(t) = ramp(t) * floor(10^9 * UNIT / 31,557,600) >> floor(t / 63,115,200)
|
||||
ramp(t) = min(1, 1/10 + 9/10 * t / 2,592,000) evaluated in integers as a rational with denominator 25,920,000
|
||||
```
|
||||
|
||||
With `UNIT = 10^18` the pre-ramp rate is about 31.7098 IGN per DAA second (Designed). The geometric series sums to 4 x 10^9 IGN; the ramp withholds 0.45 x 30/365 x 10^9 = about 37 million IGN that are never minted, and integer floors withhold a negligible further amount, so the cap is a strict bound.
|
||||
The pre-ramp rate is 31.68808781 IGN per DAA second at 8 decimals (`BASE_SUBSIDY_PER_SECOND_SOMPI` = 3,168,808,781, asserted by the code's own test) and about 31.688 IGN at any unit (Decided, ledger E9). The geometric series sums to 4 x 10^9 IGN; the ramp withholds 0.45 x 2,592,000 / 31,557,600 x 10^9 = about 37 million IGN that are never minted, and integer floors withhold a negligible further amount, so the cap is a strict bound.
|
||||
|
||||
Emission is keyed to DAA score, not to blocks or timestamps: more blocks never means more coins and miner-chosen timestamps cannot mint (hostile review table, "Emission per wall-clock second invites timestamp games"). Payment is to blue blocks only, through the merging block's coinbase as in Kaspa (`coinbase.rs:97 to 142`): the coinbase of block B pays, for each blue block M in B's mergeset, `E(daa_score(B))` split 80% to M's miner and 20% to the proving pool. Red blocks are unpaid. How the DAA-score increment is apportioned among the blues of one mergeset at higher block rates is Open (O-2.7); at 1 BPS the mergeset is usually one block.
|
||||
Emission is keyed to DAA score, not to timestamps: `E` is a function of DAA score and miner-chosen timestamps cannot mint (hostile review table, "Emission per wall-clock second invites timestamp games"). `E` is paid per block, so coins are blocks times `E`: when the controller lets the block rate run above target, short-run emission runs above schedule by the same factor, as on every proof-of-work chain, and the cap is unaffected because the halving schedule and the ramp are in DAA seconds (Decided 3 October 2026, ledger E10, round 3; the earlier sentence "more blocks never means more coins" is withdrawn, and the devnet of 3 October 2026 minted 4.7x the schedule for eight minutes during a retarget lag, `docs/review/round-3-2026-10-03.md`, "Tonight's devnet"). Payment is through the merging block's coinbase as in Kaspa (`coinbase.rs:97 to 142`): the coinbase of block B pays, for each blue block M in B's mergeset, `E(daa_score(B))` split 80% to M's miner and 20% to the proving pool; for each red block in B's mergeset that is inside the DAA window, the same `E` split 80% to B's own miner and 20% to the pool (`coinbase.rs:102 to 109`, Kaspa's rule, Decided, ledger E10); a red outside the DAA window earns only its coinbase-level fees, of which Igneum has none (fees are in section 5). How the DAA-score increment is apportioned among the blues of one mergeset at higher block rates is Open (O-2.7); at 1 BPS the mergeset is usually one block.
|
||||
|
||||
The 20% proving share is paid to the prover set recorded for the proven block, which is known 20 to 60 s after the block (design document, "Proving lag"). The coinbase payload format gains prover outputs (fork map b3, risk High). The rule that the pool is paid as a fixed amount per block divided among shards by consensus proving cost is in section 5.3.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,17 +2,18 @@
|
|||
|
||||
Spec version 0.1, 3 October 2026. Status of this section: Designed. Simulated at the checkpoint level with latency, partitions and eclipses but without a DAG (`sim/finality_v2.py`, `sim/results_v2.md`, `docs/bench-log.md` entry "sim/finality_v2.py"). Not implemented. Not externally reviewed. Gate 3 is the external review that tries to break it.
|
||||
|
||||
The rule is exactly the design document's "Finality rule, version 2, after the second hostile review" with the quorum floor added on 3 October 2026 after the second simulation. CLAUDE.md's FINALITY RULE V2 paragraph is the short form. Every quantity is in blue score or DAA seconds, never wall-clock (section 0.6).
|
||||
The rule is exactly the design document's "Finality rule, version 2, after the second hostile review" with the quorum floor added on 3 October 2026 after the second simulation. CLAUDE.md's FINALITY RULE V2 paragraph is the short form. Every quantity is in blue score, DAA seconds or past-median time, never wall-clock (section 0.6). Past-median time, `mt(B)`, is the median timestamp of a block's sampled past (Kaspa's `consensus/src/processes/past_median_time.rs`, `PAST_MEDIAN_TIME_SAMPLE_INTERVAL` 10, kept): consensus data computed from the block's past, which a burst of blocks cannot run fast the way it runs DAA score (ledger M14 and F14, round 3).
|
||||
|
||||
Two statements frame everything below. Finality is miner-only and self-contained: no stake, no bond, no other chain, no committee that is not the set of recent miners. Equivocation costs history, not coins, because there are no coins to slash.
|
||||
|
||||
## 3.1 Weight
|
||||
|
||||
- **W1.** Every block header names a vote key by `vote_key_hash` (section 2.4): the hash of a BLS12-381 G1 compressed public key. The first block that uses a key reveals the key in its coinbase payload. A header whose `vote_key_hash` has never been revealed is valid; the key simply cannot vote until it is revealed.
|
||||
- **W2.** The weight of key k at checkpoint block C is the number of blue blocks in C's past whose header names k and whose DAA score is in `(daa(C) - 2,592,000, daa(C)]` (the trailing 30 days). No damping, no cap, no floor. Blocks are the only thing in proof of work that cannot be forged, so weight is counted in blocks. The damped rule of version 1 was removed because its 2x cap was defeated by splitting into free keys (`sim/results.md` table C; `docs/bench-log.md` finality_sim entry).
|
||||
- **W3.** Dust: a key with fewer than 100 blocks in the window is not a voter and is in no denominator. Measured consequence (`sim/results_v2.md` A and G): every honest key in a 1,000-key Pareto network clears 100 blocks by day 20 from zero history and the smallest new keys need up to 25 days after a doubling; a 9x renter's victims lose about one point to dust (B).
|
||||
- **W2.** Weight is counted in blocks and denominated in past-median time (rule of 3 October 2026, ledger M14 and F14, round 3; the simulated form is kept below). Cut the trailing 30 days of past-median time before C, `(mt(C) - 2,592,000 s, mt(C)]`, into 43,200 buckets of 60 s; a blue block in C's past falls in the bucket that holds its own past-median time. The weight of key k at C is the sum over buckets of k's share of the blue blocks in that bucket (an empty bucket contributes 0 to everyone). A bucket is worth 1 whatever it holds, so 50x the blocks in one minute is one minute of weight, and a retarget lag can neither inflate a key's count nor age the window. No damping, no cap, no floor. Blocks are the only thing in proof of work that cannot be forged, so weight is counted in blocks; time is the denominator because blocks per unit of DAA time is exactly what a lagging controller lets a renter buy (section 2.3; `docs/review/round-3-2026-10-03.md`, "Tonight's devnet"). As simulated (`sim/results_v2.md`, every run): the number of blue blocks in C's past whose header names k and whose DAA score is in `(daa(C) - 2,592,000, daa(C)]`. The two forms agree whenever the controller holds the target; O-3.14 runs the simulation under both with the DAA in the loop and confirms or reverts this rule at gate 3. The damped rule of version 1 was removed because its 2x cap was defeated by splitting into free keys (`sim/results.md` table C; `docs/bench-log.md` finality_sim entry).
|
||||
- **W3.** Dust: a key with fewer than 100 blue blocks in the window (a block count, not bucket weight) is not a voter and is in no denominator. Measured consequence (`sim/results_v2.md` A and G): every honest key in a 1,000-key Pareto network clears 100 blocks by day 20 from zero history and the smallest new keys need up to 25 days after a doubling; a 9x renter's victims lose about one point to dust (B).
|
||||
- **W4.** Steady state: weight equals hashrate. Simulated correlation 1.00000 at day 60, Gini equal to three figures, weight-to-hash ratio within 0.82 to 1.12 for every key (`sim/results_v2.md` A).
|
||||
- **W5.** Key succession: a message signed by the old key naming a new key, included in any block, moves the old key's weight history to the new key once. The old key is dead thereafter: its later blocks earn nothing and its votes are invalid.
|
||||
- **W6.** Keys are free. Nothing in the protocol prices a vote key and the devnet launcher mints one per worker process (ledger F17, round 3). Weight is the only Sybil-resistant quantity in this specification, so every rule that draws from the voter population draws by weight and never per key: W2 (no damping, no per-key cap), the shard sortition of section 7.2 (drawn by weight since 3 October 2026) and the sub-user sortition of S2. A rule that counts keys is a rule a splitter wins.
|
||||
|
||||
The headline arithmetic (W2 with constant hashrate): an attacker with share a of hashrate for t days holds weight share `(t/30) x a/(1+a)`, verified by simulation to 0.04 points for a = 1 and 2 (`sim/results_v2.md` B).
|
||||
|
||||
|
|
@ -36,8 +37,8 @@ All in public, on the hashrate charts. 51% never reaches 2/3 while honest miners
|
|||
|
||||
## 3.3 Quorum
|
||||
|
||||
- **Q1.** Presence window P = 240 checkpoint indices (2 hours of blue score at 1 BPS).
|
||||
- **Q2.** Participation of key k at index i, "block reading" (rule of 3 October 2026, ledger F3): the number of indices j in `[i - 240, i - 1]` for which a valid vote by k at index j appears in the past of C_i, divided by 240, capped at 1. A vote "appears in the past of C_i" when it is carried, as a vote or inside a certificate, by any block in the past of C_i, blue or red. A key whose first block is fewer than 240 indices old counts 1. Votes are block payload: every block MUST carry every valid vote its producer has received for an index in `[i_b - 240, i_b]` (i_b the highest checkpoint index determined in the block's past) that is not already carried by a block in its past, up to the per-block vote bound of O-3.3; votes for one `(index, checkpoint hash)` pair MAY be aggregated inside the block into one BLS signature with a bitmap. A block that omits a vote it has received is not invalid (no node can prove what another received); the rule binds honest producers and the argument of 3.3.2 says why that is enough. This reading is objective, since every node computes it from the same past of C_i, and self-healing, since a missed index rolls out of the window after 240 indices. The "cert reading" of the simulation (only votes inside certificates count) is a subset of it and was the reading the simulation ran with; the node-local "seen" reading is rejected as not objective and the "frozen" reading as total with extra steps (`sim/results_v2.md`, "Recommended parameters").
|
||||
- **Q1.** Presence window P = 7,200 s of past-median time: index j is in the window of index i when `0 < mt(C_i) - mt(C_j) <= 7,200`. About 240 indices at the target rate. Denominated in median time, not indices or DAA seconds, so a burst of blocks cannot shrink the window to minutes (ledger M14 and F14, round 3; the simulation ran with a fixed 240 indices).
|
||||
- **Q2.** Participation of key k at index i, "block reading" (rule of 3 October 2026, ledger F3): the number of indices j in the presence window of i (Q1) for which a valid vote by k at index j appears in the past of C_i, divided by the number of indices in that window, capped at 1. A vote "appears in the past of C_i" when it is carried, as a vote or inside a certificate, by any block in the past of C_i, blue or red. A key whose first block is younger than the presence window counts 1. Votes are block payload: every block MUST carry every valid vote its producer has received for i_b or an index in its presence window (i_b the highest checkpoint index determined in the block's past) that is not already carried by a block in its past, up to the per-block vote bound of O-3.3; votes for one `(index, checkpoint hash)` pair MAY be aggregated inside the block into one BLS signature with a bitmap. A block that omits a vote it has received is not invalid (no node can prove what another received); the rule binds honest producers and the argument of 3.3.2 says why that is enough. This reading is objective, since every node computes it from the same past of C_i, and self-healing, since a missed index rolls out of the window after two hours of median time. The "cert reading" of the simulation (only votes inside certificates count) is a subset of it and was the reading the simulation ran with; the node-local "seen" reading is rejected as not objective and the "frozen" reading as total with extra steps (`sim/results_v2.md`, "Recommended parameters").
|
||||
- **Q3.** Active weight at i is the sum over voters of weight x participation. Total weight at i is the sum of weight over all keys above dust. A certificate for index i locks when the unscaled weight of its signers is at least **2/3 of active weight** AND at least **56.7% of total weight** (the floor 0.85 x 2/3 = 17/30). Both tests use weights and participation computed at C_i, so any node can verify a certificate from C_i's past.
|
||||
- **Q4.** Certificate grace: an aggregator closes a certificate at the later of quorum time and `t0 + grace`, where grace MUST be at least 3x the worst honest one-way network delay (15 s in the simulation at a 2-s delay; at a 5-s delay the slowest region already lost 1.7 points of participation to a 15-s grace, `sim/results_v2.md` A). The value is Open (O-3.4) and does not affect validity, only which votes a certificate carries.
|
||||
|
||||
|
|
@ -93,7 +94,7 @@ Decision of 3 October 2026. Under a cert-only reading, whoever aggregates and wh
|
|||
Why an aggregator or a block producer cannot push a key's participation below the honest level:
|
||||
|
||||
1. A vote is credited if it appears in any block in the past of C_i, blue or red, as a vote or inside a certificate. Certificates are one carrier among many, so the aggregator's bitmap selects nothing. An aggregator that drops a vote from its certificate changes which certificate locks (Q3 still has to be met by the votes it kept), not whether the vote counts for presence.
|
||||
2. A single block producer controls one block's payload. To keep k's vote for index j out of the past of C_i, every producer of every block that ends up in the past of C_i, over the up to 240 indices between j and i, has to omit it, and the rule of Q2 makes every honest producer carry it. Under GHOSTDAG the past of C_i includes red blocks and every block merged within the 3,600-s bound, so an honest block that carries the vote is in the past of C_i within an hour of being mined.
|
||||
2. A single block producer controls one block's payload. To keep k's vote for index j out of the past of C_i, every producer of every block that ends up in the past of C_i, over the about 240 indices between j and i, has to omit it, and the rule of Q2 makes every honest producer carry it. Under GHOSTDAG the past of C_i includes red blocks and every block merged within the 3,600-s bound, so an honest block that carries the vote is in the past of C_i within an hour of being mined.
|
||||
3. k is a voter only if it holds weight, which means it mined at least 100 blue blocks in the window. k carries its own votes in its own blocks, so suppressing k's participation means keeping k's own blocks out of the DAG for the whole presence window. That is excluding a miner from the chain for two hours, which is the eclipse of 3.3.2, where the floor already stops a lock, or a majority attack of 3.1, which the rule never claimed to survive.
|
||||
4. Nobody can raise participation falsely, because a vote is a BLS signature by k. Nobody can be made to vote twice at one index without producing equivocation evidence (3.6).
|
||||
|
||||
|
|
@ -133,7 +134,7 @@ Two rules are on the table:
|
|||
| Rule | Status |
|
||||
|---|---|
|
||||
| C5 as written: no certificate in the first 3,600 DAA s | Designed (design document) |
|
||||
| No certificate may form until the window holds 30 days of history: before DAA second 2,592,000 the chain runs plain GHOSTDAG under the merge-depth bound, exchanges are told so, and the node flag of 3.9 is false | Proposed (ledger F1), Open (O-3.1). This specification recommends it: the first month has no weight to defend with, so a lock in that month is a lock by whoever showed up, and the merge-depth bound already bounds a reorg to one hour |
|
||||
| No certificate may form until the window holds 30 days of history: before DAA second 2,592,000 the chain runs plain GHOSTDAG under the merge-depth and finality-depth bounds, exchanges are told so, and the node flag of 3.9 is false | Proposed (ledger F1), Open (O-3.1). This specification recommends it: the first month has no weight to defend with, so a lock in that month is a lock by whoever showed up, and the finality depth of section 2.1 already bounds a reorg to 12 hours (ledger F15: the merge-depth bound limits which old blocks can be merged, not which chain the node follows) |
|
||||
|
||||
Gate 3 decides, with the launch-month simulation that does not yet exist. Either way the litepaper states the rule.
|
||||
|
||||
|
|
@ -145,7 +146,7 @@ Designed. The node exposes `finality_active` (true when a certificate has formed
|
|||
|---|---|
|
||||
| `finality_active` and the deposit's block is in the past of `last_certified` | Credit. Expected wait about 90 to 120 s after inclusion |
|
||||
| `finality_active`, deposit not yet covered | Wait for the next certificate; do not count blocks |
|
||||
| `finality_active` false (first month, or a pause under 3.7 item 2) | Treat the chain as proof of work with a one-hour merge-depth bound. Credit nothing below 3,600 DAA s of depth, and for amounts that matter apply the operator's own hashrate judgement, as for any young proof-of-work chain. Listings are not sought before launch in any case (ledger X8) |
|
||||
| `finality_active` false (first month, or a pause under 3.7 item 2) | Treat the chain as proof of work. The reorg bound to rely on is the finality depth of section 2.1, 43,200 DAA s: the node follows any heavier selected chain forked above it (ledger F15, round 3). Merge depth, 3,600 DAA s, limits which old blocks can be merged and is not a reorg bound. Credit nothing until the deposit's block is at least 12 hours of past-median time below the selected tip; count median time, not DAA score, because DAA seconds run fast during a retarget lag (ledger M14). For amounts that matter apply the operator's own hashrate judgement, as for any young proof-of-work chain. Listings are not sought before launch in any case (ledger X8) |
|
||||
| Two certificates at one index observed (C4 evidence) | Suspend credits until the node's view resolves under 3.5 |
|
||||
|
||||
A certified checkpoint overrides the heaviest chain, so fresh hashrate cannot reorganise past `last_certified`; two thirds of 30-day weight can, and 3.1 says what that costs.
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ An item closes when its measurement is in `docs/bench-log.md` or its decision is
|
|||
| O-3.11 | Key succession (W5): replay protection and what happens if both keys mine after the message | Specify the message (old key, new key, DAA score, signature) and that blocks naming the old key after inclusion earn nothing | 3 |
|
||||
| O-3.12 | Vote message and certificate wire formats, aggregation rules, bitmap size at 10^4 keys | Specify with the P2P layer | 3 |
|
||||
| O-3.13 | `finality_active` flag semantics and exchange guidance (section 3.9) are Designed and untested | Devnet stall test; exchange guidance reviewed by an operator | 3, 4 |
|
||||
| O-3.14 | Finality simulation with the DAA in the loop under a pulsed rental (ledger M14 and F14, round 3): every run of `sim/results_v2.md` assumed a perfect retarget, and the devnet of 3 October 2026 showed DAA time running 2.9x the wall clock for 17 minutes after a hashrate step | `finality_v2.py` with Kaspa's sampled DAA and the controller chosen at gate 2 (section 2.3) in the loop, a 50x renter pulsing two minutes in every hour, under both forms of W2 and Q1 (DAA-score blocks as simulated; median-time buckets as specified in section 3.1 and 3.3), reporting the day the renter crosses a third and the chain's block rate meanwhile; logged in `docs/bench-log.md`; confirms or reverts the median-time form | 3 |
|
||||
|
||||
## 6.4 Section 4, seeds and the VDF
|
||||
|
||||
|
|
@ -104,11 +105,11 @@ Section 7 carries no open item of its own: its measurements are O-5.1 (shard sor
|
|||
|---|---|
|
||||
| 1 | 20 |
|
||||
| 2 | 9 (O-2.8 closed 3 October 2026 by section 7.1) |
|
||||
| 3 | 13 (O-3.3 and O-3.7 narrowed to parameters and confirmation on 3 October 2026) |
|
||||
| 3 | 14 (O-3.3 and O-3.7 narrowed to parameters and confirmation on 3 October 2026; O-3.14 added the same evening, round 3) |
|
||||
| 4 | 9 |
|
||||
| 5 | 8 (O-5.1, O-5.2 and O-5.6 narrowed on 3 October 2026) |
|
||||
| 7 | 0 |
|
||||
| 8 | 1 |
|
||||
| Total | 60 |
|
||||
| Total | 61 |
|
||||
|
||||
By gate (an item shared between two gates is counted at the earlier one): 16 belong to gate 1, 11 to gate 2, 21 to gate 3, 4 to gate 4, 3 to phase 2, 3 are decisions with a named owner outside a gate (O-5.2, O-5.8, O-8.1), 1 (O-2.10) waits on a later block-rate step, and 1 (O-1.20) is a note with no consensus consequence.
|
||||
By gate (an item shared between two gates is counted at the earlier one): 16 belong to gate 1, 11 to gate 2, 22 to gate 3, 4 to gate 4, 3 to phase 2, 3 are decisions with a named owner outside a gate (O-5.2, O-5.8, O-8.1), 1 (O-2.10) waits on a later block-rate step, and 1 (O-1.20) is a note with no consensus consequence.
|
||||
|
|
|
|||
|
|
@ -33,14 +33,14 @@ Rationale for every row, the precedents (Conflux eSpace, Kasplex, Igra) and the
|
|||
Decided 3 October 2026 (ledger P8 and C9, closed by this section). Every segment is cut into shards by proving gas at transaction boundaries, deterministically from the native trace, so every node computes the same shard list and the same shard ids `(segment hash, shard index)` (design document, section 5.1). Shards are not claimed first-come. They are assigned by sortition:
|
||||
|
||||
1. **Eligible provers.** The vote keys above dust under section 3 (at least 100 blue blocks in the trailing 30-day window at the chain block that heads the segment). The finality-rule population is the proving population; there is no separate registration.
|
||||
2. **Sortition.** For each shard, every eligible key k is ranked by `H("igneum-shard/" ‖ epoch_seed ‖ shard_id ‖ vote_key_hash(k))`, H the chain's hash of section 0.6, as an unsigned integer; the 8 lowest ranks are assigned to the shard. `epoch_seed` is the VDF output of section 4 for the epoch containing the chain block, so the producer cannot bias it, and `shard_id` commits to the segment, so the assignment is keyed to the block and known to every node the moment the segment is executed. The function is public and deterministic: it needs no private key and no proof of evaluation. Whether to replace the hash ranking with the private VRF of section 3.4 (so assignees are hidden until they prove) is settled together with O-3.5; nothing else in this section depends on the choice.
|
||||
2. **Sortition, by weight.** Rule of 3 October 2026 (ledger F17, round 3); the earlier per-key ranking is withdrawn because keys are free (section 3.1 W6) and a miner who split its blocks over many keys held most of the tickets. The window is the list of blue blocks in the chain block's past that W2 of section 3.1 counts at that chain block, in GHOSTDAG order, restricted to blocks whose key is eligible under step 1; N is its length. For draw n = 1, 2, ..., `r_n = H("igneum-shard/" ‖ epoch_seed ‖ shard_id ‖ n) mod N`, H the chain's hash of section 0.6 read as an unsigned integer, and the key named by block `r_n` of the window is an assignee. A key drawn again holds one slot and the draw continues; the draw stops at 8 distinct keys, or earlier when every eligible key holds a slot. A key is drawn in proportion to its blocks in the window, which is its weight up to the bucket normalisation of W2, so splitting one key into a thousand changes nothing, as it changes nothing for the vote. `epoch_seed` is the VDF output of section 4 for the epoch containing the chain block, so the producer cannot bias it, and `shard_id` commits to the segment, so the assignment is keyed to the block and known to every node the moment the segment is executed. The function is public and deterministic: it needs no private key and no proof of evaluation. Whether to replace the hash draw with the private VRF of section 3.4 (so assignees are hidden until they prove) is settled together with O-3.5; nothing else in this section depends on the choice.
|
||||
3. **Exclusive window.** From the moment the segment is executed, the 8 assignees hold the shard for 10 s of DAA time. A valid proof of the shard by any of the 8 that is included in a block during the window earns the shard's part of the proving pool (section 5.3); a proof by anyone else is valid but unpaid.
|
||||
4. **Open claiming.** After the window any prover MAY prove the shard, and the first valid proof included in a block earns the shard's part of the pool. There is no claim and no shard bond: nothing waits on an assigned prover, so there is nothing to bond against (ledger P9). The bond remains in the external job market, where a customer does wait (section 5.4).
|
||||
5. **Inclusion.** Shard proofs gossip like votes and any block producer MAY include them (design document, section 5.4). A block is invalid if a proof record it carries fails verification or names a state the node's own execution disagrees with (design document, section 5.5).
|
||||
5. **Inclusion.** Shard proofs gossip like votes and any block producer MAY include them (design document, section 5.4). A block is invalid if a proof record it carries fails verification, names a chain block that is not on the carrying block's own selected-parent chain, or carries a post-root or receipts that differ from the execution of that segment along that chain (rule of 3 October 2026, ledger P11, round 3). The test is relative to the carrying block's own chain, never to the validating node's current selected chain: that chain is a property of the node's virtual and differs between honest nodes every second on a DAG, so a rule written against it makes two honest nodes disagree on one block. Written this way, validity is a function of the block and its past and every node computes it identically, as for every other rule in the fork. The design document's section 5.5 wording ("the node's selected chain") is superseded by this item.
|
||||
|
||||
What the rule gives. A datacentre cannot sweep every shard by latency, because for 10 s only 8 drawn provers are paid, and the draw is proportional to the number of eligible keys a prover holds, which is bounded by its 30-day mining. Income from the pool is bounded by the shards a prover is assigned plus the shards nobody assigned proves in time, not by how many it can grab. A segment producer could grind transaction content to move the assignment; it gains only if it is also one of the many eligible provers, and the draw of 8 out of the whole population makes the gain small. Its size is part of the measurement below.
|
||||
What the rule gives. A datacentre cannot sweep every shard by latency, because for 10 s only 8 drawn provers are paid, and the draw is proportional to a prover's blocks in the window, which is its 30-day mining however many keys it spreads them over. Income from the pool is bounded by the shards a prover is assigned plus the shards nobody assigned proves in time, not by how many it can grab. A segment producer could grind transaction content to move the assignment; it gains only if it is also one of the many eligible provers, and the draw of 8 out of the whole population makes the gain small. Its size is part of the measurement below.
|
||||
|
||||
Parameters 8 and 10 s are Designed. They are set on the phase 4 devnet from the shard-time distribution across three prover speeds, with the acceptance test that the fastest prover wins under 25% of shards (design document, R7; O-5.1).
|
||||
Parameters 8 and 10 s are Designed. They are set on the phase 4 devnet from the shard-time distribution across three prover speeds, with the acceptance test that the fastest prover wins under 25% of shards (design document, R7; O-5.1), and the test that one key and 1,000 keys of equal weight win the same number of shards (ledger F17).
|
||||
|
||||
## 7.3 Bridges
|
||||
|
||||
|
|
@ -64,5 +64,7 @@ Nothing in consensus changes for any of this: the segment claim already commits
|
|||
| Provers assigned per shard | 8 | Designed, set at the phase 4 devnet (O-5.1) |
|
||||
| Exclusive proving window | 10 DAA s | Designed, set at the phase 4 devnet (O-5.1) |
|
||||
| Shard claim bond | none | Designed |
|
||||
| Sortition draw | by weight: blue blocks drawn uniformly from the window, their keys assigned | Decided 3 October 2026 (ledger F17) |
|
||||
| Proof-record validity | relative to the carrying block's own selected-parent chain | Decided 3 October 2026 (ledger P11) |
|
||||
| Bridged stablecoins at genesis | none | Decided (3 October 2026) |
|
||||
| Official bridge | none | Decided (3 October 2026) |
|
||||
|
|
|
|||
|
|
@ -13,10 +13,10 @@ The two findings it answers. An app that auto-updates on ten thousand machines i
|
|||
## 8.2 The release key
|
||||
|
||||
1. Every release MUST be signed by the release key. The release key's public half is published in the genesis block and is therefore in every node's copy of the chain; it is also in the repository and on the domain.
|
||||
2. The private half is held in hardware by the steward named in the published key policy. It never exists on a networked machine. The policy (who holds it, how a signature is produced, how the key is rotated or revoked) is published before the public testnet (O-8.1).
|
||||
2. The private half is held in hardware by the steward named in the published key policy. It never exists on a networked machine. The policy (who holds it, under which entity and in which jurisdiction, how a signature is produced, who holds the predecessor key of item 5) is published before the client ships to anyone outside the project, which is before the public testnet and not at it (O-8.1; ledger G9 and L1, round 3).
|
||||
3. The client MUST refuse any update whose signature does not verify under the release key. A refused update is reported to the user, with the hash it saw, and the running version continues.
|
||||
4. There are no silent updates. The client MAY check for a release and MUST show the version, its hash and the reproduction instructions; installation proceeds only when the user accepts it. The client never applies an update while mining without the user's acceptance for that version.
|
||||
5. Rotation of the release key is itself a signed release under the old key, published with a stated reason and a stated date, and is the only path to a new key. A key that is lost is a key that is revoked by its own last signed release, and the client then accepts no update at all until the user installs a new client by hand from the repository.
|
||||
5. Rotation and revocation (rule of 3 October 2026, ledger G9, round 3). Release keys form a chain K0, K1, K2 and so on, with K0 in genesis. Rotation: a message `(K_n, K_n+1, reason, date)` signed by K_n and published as a transaction in a block. From the first certified checkpoint whose past holds that block (before finality is active, from 43,200 DAA s of depth) the client accepts releases signed by K_n+1 and none signed by K_n. Rotation is the only path to a new key. Revocation: a message `(K_n, reason, date, successor or none)` signed by K_n-1, the previous key, published in a block the same way; it declares K_n lost or compromised. After a rotation the previous key is retired, not destroyed: it is kept in separate custody by a second holder named in the policy, and its only remaining power is to revoke its successor. K0 has no predecessor, so a revocation certificate for K0, signed by K0 at creation and naming a pre-generated K1, is held by the second holder apart from K0. From the block that carries a revocation onward the client MUST refuse every release signed by the revoked key and accepts releases under the named successor; if no successor is named, the client accepts no update at all until the user installs a new client by hand from the repository. A lost key is therefore revocable without its own signature, which the earlier rule (revocation "by its own last signed release") could not do.
|
||||
|
||||
## 8.3 The client cannot change consensus
|
||||
|
||||
|
|
@ -45,7 +45,8 @@ The two findings it answers. An app that auto-updates on ten thousand machines i
|
|||
| Parameter | Value | Label |
|
||||
|---|---|---|
|
||||
| Release key publication | genesis block, repository, domain | Decided |
|
||||
| Release key custody | hardware, held by the named steward, policy published before public testnet | Decided; policy Open (O-8.1) |
|
||||
| Release key custody | hardware, held by the named steward; the predecessor key with a second holder; policy published before the client ships | Decided; policy Open (O-8.1) |
|
||||
| Release key rotation and revocation | rotation signed by the current key, revocation signed by the previous key, both published in a block | Decided 3 October 2026 (ledger G9) |
|
||||
| Silent updates | none | Decided |
|
||||
| Consensus activation through the client | impossible; 90% of blue blocks signalling (section 5.7) | Decided |
|
||||
| Official download sources | the project's domain and the repository release page, hash shown beside the button | Decided |
|
||||
|
|
|
|||
Loading…
Reference in a new issue