Merge master dc22df3ff into tv-02-supply-replay under the master-landing lock
This commit is contained in:
commit
2fd7d3d327
21 changed files with 5601 additions and 55 deletions
26
docs/analysis/class-v6/rows/x0-5090-20261009.md
Normal file
26
docs/analysis/class-v6/rows/x0-5090-20261009.md
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# X0 decider: class v4 against the frozen class v6 on one rented RTX 5090 (9 October 2026, 08:54 to 08:57 UTC)
|
||||
|
||||
One session, one card: a rented RTX 5090 (32 GB, driver 580.105.08, the provider's CUDA 12.8 image), the gen-6 Linux CUDA
|
||||
worker (sha256 `804a6f7f…`, built from the frozen tree's proto-cuda), 250 batches of 2^24 at `--block-warps 1` per pack, nvidia-smi
|
||||
board power at 1 Hz, watts = the mean of `power.draw` from 8 s in to the end of the bench, idle not subtracted. Stock only: the
|
||||
provider refuses `-lgc` ("The current user does not have permission to change clocks"), as every rented host of 8 October did.
|
||||
|
||||
| Pack | Class | Id | MH/s | W | nJ per hash | Fingerprint | Check |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| v4-devnet-epoch0 (the 7 October numerator's pack) | mx8-erad810f22d+sh256x27, generator 4 | `0xa785001687d8688a` | 141.963 | 500.0 (the card's power limit) | 3,522 | `e370fb2080b7dbb1` | PASS |
|
||||
| hl-v6-all (the l8off kit's export, the house knee rows' pack) | mx8-erad810f22d+sh256x27+state+reg64c+fold+rw | `0x9d40978601a7df2a` | 70.900 | 445.1 | 6,278 | `59e6708e46f1e87c` | PASS |
|
||||
| hl-v6-all-cs (the signing object) | the same class, generator 6 | `0x2a1d6caab4c24564` | 70.650 | 457.1 | 6,470 | `01f51b9d4805e5e6` (first CUDA read) | PASS |
|
||||
|
||||
Ratios, class v6 over class v4: joules per hash 1.78x (the kit pack) and 1.84x (the signing object); rate 2.00x (the frozen
|
||||
class draws twice the loads per hash). The house rig's RTX 5090 reads the same pair at 1.68x at stock (3,475 against 5,842 nJ,
|
||||
the 7 October grid against the 9 October knee rows) and 1.73x at the 1,300 MHz knee (2,319 against 4,011), so across three
|
||||
sessions the figure is 1.7 to 1.8x.
|
||||
|
||||
Meaning: class v6 costs the 5090 about 1.75x class v4's joules per hash and half its rate, so the 7 October numerator (2.33 µJ
|
||||
per hash at the lock on class v4) understates the frozen object's card cost by about 1.7x; the board ratio moves toward the
|
||||
2.6x side of the X0 order, and the chip's shadow op count is to be re-read on the class v6 draw (its window, index fold and
|
||||
re-weight add card cost the class v4 count does not carry). The only lock row for the frozen object is the house 5090's
|
||||
4.01 µJ per hash (the 9 October knee rows).
|
||||
|
||||
Evidence: build-1 `/srv/artefacts/tas/x0-pins/x0-run-fk-5090c/` (run-x0.log `9bc40685…`, smi.csv `7ab9f16f…`, the three bench
|
||||
logs; SHA256SUMS.txt beside them); the bundle `x0-bundle.tgz` (`864470a7…`) with the run script.
|
||||
|
|
@ -13,18 +13,21 @@ build-1:/srv/queue/build-queue.md (the reader reads that one; this file is its s
|
|||
- An entry carries its owner lane, its box, its pid-file path and its clock (UK). A box with no live pid file from its queue and
|
||||
a load under 1.0 for a 30-minute read is a fault, reported by the reader to the coordinator (/srv/queue/faults.log).
|
||||
- A lane that finishes an entry replaces it with the next or hands the box back here with a line; an empty box is the fault.
|
||||
- Main's rule (9 October 2026, 09:5x UK): an owner starts its matrix job on its box under /srv/queue/pids within 15 minutes of a read that
|
||||
found the box idle, or the reader marks the box unclaimed (open to any lane, written in status.json and faults.log); a box idle for
|
||||
30 minutes is a red against its owner on the steward's board. A shared box names every owner and none ends another's pid.
|
||||
|
||||
## Owners (one lane per box)
|
||||
|
||||
| box | threads | owner lane | standing use |
|
||||
|---|---|---|---|
|
||||
| build-1 | 96 | build-server lane | cuts and kits, the hands (observer-node, node1), the capacity fuzz slices, the workers page, the queue reader |
|
||||
| build-2 | 96 | site lane | the site gate (Playwright), the scene-parity suites; spare slots for the node lane's suites |
|
||||
| build-2 | 96 | site lane and the adversary lane (shared; neither ends the other's pid) | the site gate (Playwright), the scene-parity suites; X5's dram design beside them |
|
||||
| build-3 | 32 | node lane | the long consensus fuzz and property suites (kaspa-consensus, kaspa-consensus-core) |
|
||||
| build-4 | 96 | adversary lane | the chip model (OpenROAD, kepler-formal): the 20 to 25 percent floorplan for the converged SPEF row |
|
||||
| build-5 | 32 vCPU | research lane | TV-02's two independent supply-replay implementations, CPU only |
|
||||
| build-6 | 32 vCPU | HEAL lane | the long p2p and exec property suites (kaspa-p2p-flows, igneum-exec) |
|
||||
| build-7 | 96 | node lane | the 2.0.3 flows items: their suites and known-failed tests; the heal-on harness |
|
||||
| build-5 | 32 vCPU | adversary lane (X5 hyb50), the TV-02 lane a light guest for minutes | X5's opponent-sweep variant; TV-02's last comparison run beside it (one core, under five minutes) |
|
||||
| build-6 | 32 vCPU | adversary lane (X5 hyb75) and the HEAL lane (shared) | X5's opponent-sweep variant; the long p2p and exec property suites (kaspa-p2p-flows, igneum-exec) |
|
||||
| build-7 | 96 | node lane and the relay lane (shared; neither ends the other's pid) | the 2.0.3 flows items: their suites and known-failed tests; the heal-on harness; the standing Windows canary VM (docker winvm, 4 vCPU, 8 GB, /srv/winvm/up.pid) |
|
||||
| build-8 | 96 | fleet lane | 2.0.3 kit canaries the moment a chain moves; the heal-off harness; the dn4 roll node |
|
||||
| build-9 | 96 | steward | the board's rows that need only a box (ZKP, EVM, VER fixtures), the pow fuzz on the side |
|
||||
|
||||
|
|
@ -36,11 +39,12 @@ build-1:/srv/queue/build-queue.md (the reader reads that one; this file is its s
|
|||
| 2 | long fuzz and property suites, consensus (kaspa-consensus, kaspa-consensus-core) | node lane | build-3 | /srv/queue/pids/build-3-consensus-fuzz.pid | from 09:45, continuous |
|
||||
| 3 | long fuzz and property suites, exec and p2p (igneum-exec, kaspa-p2p-flows, kaspa-p2p-lib) | HEAL lane | build-6 | /srv/queue/pids/build-6-exec-p2p-fuzz.pid | from 09:45, continuous |
|
||||
| 4 | long fuzz and property suites, pow (kaspa-pow, igneum-pow mixer and scratch) | node lane | build-9 | /srv/queue/pids/build-9-pow-fuzz.pid | from 09:45, continuous |
|
||||
| 5 | TV-02: two independent supply-replay implementations, CPU only | research lane | build-5 | /srv/queue/pids/build-5-tv02-replay.pid | from 10:00, until both agree |
|
||||
| 5 | TV-02: two independent supply-replay implementations, CPU only: DONE 09:35 UK (A on build-5 in 38 s, B on build-6 in 3 min); the last comparison on the TV-01 spec runs as a guest under build-5-tv02.pid and build-6-tv02.pid by 11:30 | TV-02 lane | build-5, build-6 | /srv/queue/pids/build-5-tv02.pid, build-6-tv02.pid | by 11:30, minutes |
|
||||
| 6 | chip model: the 20 to 25 percent floorplan for the converged SPEF row (about four host-hours) | adversary lane | build-4 | /srv/queue/pids/build-4-floorplan.pid | running (OpenROAD 844081, kepler-formal 1797623), about 13:30 |
|
||||
| 7 | the board's rows that need only a box: ZKP, EVM and VER fixtures (the steward names them) | steward | build-9 | /srv/queue/pids/build-9-board-rows.pid | from 10:00, by row |
|
||||
| 8 | 2.0.3 kit canaries the moment a chain moves (the evidence kits under /srv/workers/fleet) | fleet lane | build-8 | /srv/queue/pids/build-8-kit-canary.pid | on the chain's move |
|
||||
| 9 | the site gate and the scene-parity suites | site lane | build-2 | /srv/queue/pids/build-2-site-gate.pid | on each landing |
|
||||
| 11 | the standing Windows canary VM on build-7 (docker winvm; its collector posts to the intake as the Windows canary card) | relay lane | build-7 | /srv/queue/pids/build-7-winvm.pid (mirrors /srv/winvm/up.pid) | from 10:00, standing |
|
||||
| 10 | cuts, kits, the hands, the capacity fuzz slices, the workers page, the queue reader | build-server lane | build-1 | /srv/queue/queue-reader.pid and the cut pid files under the cutter's scratch | continuous |
|
||||
|
||||
A lane starts its entry by writing its pid file (`<pid> <start UTC> <label>`, the format of the slot files) under /srv/queue/pids on
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
64
docs/plans/igneum-2.0-master/1p5x/research-plan/README.md
Normal file
64
docs/plans/igneum-2.0-master/1p5x/research-plan/README.md
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
# IGNEUM: The 1.5x Research Programme (9 October 2026)
|
||||
|
||||
The founder's research plan for the 1.5x target, the second document of the 1.5x folder beside the evidence and experiment brief (`../README.md`). It claims no pass.
|
||||
|
||||
The Track B rules: no raw hashes-per-second comparison (an equivalent lottery-contribution and security-budget unit is approved first); the internal design goal is 1.25x with the guardband; every chip figure is labelled WITNESS (E_D) or BOUND (L), X5's rows being witnesses; ASAP7 is screening only; negative results stay as controls; the quantum claim is classical; Track C (DEGSample) is not started until a Track B deficiency names it.
|
||||
|
||||
## The two tracks and the gated third
|
||||
|
||||
- Track A, the minimal-change route: the X matrix of the brief (A0 freeze the actual comparison, A1 the window-free addressing control, A2 byte-preserving honest-worker optimisation, A3 re-optimise every opponent), the lanes and clocks in `../README.md`.
|
||||
- Track B, proof-first input-specific memory work, starting from Blocki and Smearsoll's TCC 2025 memory-hard proof of work with memory-easy verification rather than another collection of instructions; the lanes and clocks as the coordinator names them:
|
||||
|
||||
| Lane | Work | Owner | Clock |
|
||||
|---|---|---|---|
|
||||
| B1 (R15-05) | reproduce the published primitive: the Blocki and Smearsoll TCC 2025 MTP/DRSample construction as a CPU reference with its complete verifier, domain separation, known-answer fixtures and the Dinur and Nadler attack fixtures | the B1 cryptography lane (a4490b2dfe9114a55) on build-6 | 13:30 UK |
|
||||
| B2 | bind the economically expensive work: the canonical instance input and the reuse, grinding, chosen-instance, partial-evaluation and amortisation obligations | the B2 binding spec lane (a717f5c9730229ea6), documents only | 12:30 UK |
|
||||
| B3 (R15-06) | GPU adaptation without changing the theorem: batched instances at 32, 128 and 512 MiB, coalesced labels, cooperative processing, the under-utilisation trap stated | the B3 GPU feasibility lane (a8e608abf1567ff87) on rented 5090 and 4090 pods | the first rows 14:00 UK |
|
||||
| B4 (R15-07) | the composed theorem statement for a cheating prover with concrete constants, the 2025 and 2024 results and what is new, the reduction losses, R4's encoded-state warning | the B4 theory lane (a46974623d72b032c), documents only | 13:00 UK |
|
||||
| B5 | the full-SRAM-on-fresh-state and the near-memory designs added to X5's sweep, WITNESS rows | the adversary lane (a1a9876a88f5a72fc), inside X5's line | 12:30 UK |
|
||||
| B6 (R15-10) | the verification budget as a parameter table against the fleet's node limits | the node lane (a283f5f0d364ceef0) | 13:00 UK |
|
||||
|
||||
- Track C, dynamic sustained-memory research, gated separately: kept only if its additional security and verification obligations can be met (the plan's DEGSample gate).
|
||||
|
||||
## Witness versus bound
|
||||
|
||||
For a fixed work function, difficulty and environment, G is the GPU energy per equivalent accepted work and E* the infimum of specialist energy across the permitted implementations; the required statement is G / E* at or under 1.5. A functioning or modelled specialist gives E_D with E* at or under E_D, so a chip at 1.5x is a witness of at least that achievable advantage, never an upper bound on a better chip. A scoped upper-bound certificate needs a justified lower bound L on every permitted specialist's energy and an upper bound G_upper on the GPU's, with G_upper / L at or under 1.5, and must name what is permitted. Four evidence levels: functional validity, resource security, physical translation, engineering reproduction; an empirical envelope over assessed chips is not a universal theorem.
|
||||
|
||||
## The 1.25x internal design goal
|
||||
|
||||
The required improvement: r_new = r x g / a. The guardband: a nominal 1.25 with the GPU 5 percent worse and the specialist 10 percent better than the central estimates reads 1.4583, a nominal 1.30 reads 1.5167, so an exact 1.50 point estimate has no room for those assumed uncertainties; the internal design goal is 1.25 nominal. The 5 and 10 percent are illustrative, not measured error bars.
|
||||
|
||||
## The ten execution packages
|
||||
|
||||
The plan's section 10 names capabilities, not lanes; the cross-reference to the brief's X matrix and to track B's lanes is this landing's reading, for the coordinator to confirm, and sits in `packages.json` beside the markdown for the registry's R15 suite.
|
||||
|
||||
| Package | Capability | Required artefact | Gate | Lanes |
|
||||
|---|---|---|---|---|
|
||||
| R15-01 | release and measurement | the latest exact pack, physical assumptions, source manifest, the current ratio reconciliation | no cross-version mixed baseline | X0 |
|
||||
| R15-02 | GPU and hardware | the component power and traffic model with sensitivity analysis | no device or whole-machine boundary mismatch | X0, X5 |
|
||||
| R15-03 | GPU and memory analysis | the layer-8-off control and held-out cache curves | a distinct benefit after the best cache adaptation | X1 |
|
||||
| R15-04 | GPU systems | compaction, exact-fold alternatives and tuning results | byte agreement, real accepted-work savings | X2, X3, X4 |
|
||||
| R15-05 | cryptography | the exact published MHPoW control, the theorem audit, malicious fixtures | no improvised sampled-memory soundness | B1 |
|
||||
| R15-06 | GPU and cryptography | theorem-preserving layout and parallelisation feasibility | GPU competitiveness and cheap-enough verification | B3 |
|
||||
| R15-07 | cryptography and hardware | the joint accepted-proof resource frontier with concrete constants | no invalid theorem composition | B2, B4 |
|
||||
| R15-08 | an independent ASIC team | re-optimised SRAM, DRAM, hybrid, recompute and PIM scenarios | the full-storage adversary not excluded by price | X5, B5 |
|
||||
| R15-09 | measurement and economics | the blind cohort confirmation and separate P12 outcomes | the strongest credible ratio, not the average | X6 |
|
||||
| R15-10 | protocol and security | network and pool integration, the no-rescue exercise, public evidence | correctness and safe operation intact | B6 |
|
||||
|
||||
R15-03 and R15-04 run beside R15-05 and R15-06: existing GPU waste is reduced without waiting for every theorem, and quick wins never substitute for the proof obligation.
|
||||
|
||||
## The stopping rules (the plan's section 11)
|
||||
|
||||
1. P04 stays unchanged unless a new scope is ratified before results; a same-node or one-node cohort gate is never replaced by one flagship result. 2. An unknown decision-critical silicon assumption is BLOCKED, not PASS. 3. Research cost and calendar rotation are not energy resistance. 4. A candidate may not improve the ratio by imposing a large cost on ordinary GPUs; the P03 limits govern like-for-like changes and a changed work definition needs an explicit comparison contract. 5. Every prototype keeps its published negative results; a rejection redirects research and establishes no universal impossibility. 6. A storage argument covers arbitrary representations through a valid reduction. 7. The best full-SRAM, hybrid and recompute designs stay in the comparison after every change. 8. Lower-bound derivations and measurements get independent scrutiny, empirical models and theorems labelled apart. 9. Verification, propagation, pool work, proof generation and job cancellation fit ordinary-operator budgets. 10. The founding statement is earned only with separate economic-access evidence; energy at or under 1.5 alone establishes no monetary security, profitability, parity or leadership.
|
||||
|
||||
## Files
|
||||
|
||||
| File | What | sha256 |
|
||||
|---|---|---|
|
||||
| `igneum-1p5x-research-plan.md` | the plan (the package's `IGNEUM_1p5x_Research_Plan.md`, byte-identical) | `269ceaa5824d09140a1bcc124dba59438db5a5e68fddc18960db7141fefc0305` |
|
||||
| `package/check_arithmetic.py` | the companion check: 2,000 bounded random examples and exact rational calculations of the illustrative cache and mixture models, standard library only; not a native Igneum test, not a hardware benchmark | `1390a5564d18414f14fb2049514eac9a7d1d317648c81b0829873176a7717940` |
|
||||
| `package/arithmetic_results.json` | its output | `5bd8786a590cc51f221f44501c4f469c65ec2789bc15fda0168005e076ed12a2` |
|
||||
| `package/manifest.json` | the package's own manifest | `78edf24a9ce2b356a52bc26fe2d9a2edf4a69c35e4d34ed5539d9d85c550881d` |
|
||||
| `packages.json` | the ten packages in machine-readable form (id, capability, artefact, gate, lanes, status) for the registry's R15 suite | written at this landing |
|
||||
|
||||
The package zip `IGNEUM_1p5x_Research_Package.zip` (sha256 `c873ac9da231fb267da4b4d6dba88e2d478e835357720be8adb585f4499b7772`) is not landed; its files are.
|
||||
|
|
@ -0,0 +1,339 @@
|
|||
# IGNEUM - The 1.5x Research Programme
|
||||
|
||||
**Research date:** 9 October 2026
|
||||
**Status:** Research proposal, not a completed algorithm or a P04 pass.
|
||||
**Objective:** Demonstrate a specialist/GPU energy advantage at or below 1.5x within an explicitly declared technology, implementation and GPU-cohort scope, while separately satisfying economic-access, correctness and operator-safety requirements.
|
||||
|
||||
## Executive decision
|
||||
|
||||
Run two tracks in parallel. Track A removes known structural and implementation opportunities from the current candidate. Track B develops a proof-first, input-specific memory-work construction, starting from published memory-hard proof-of-work research rather than inventing another collection of instructions. Keep a separate dynamic-memory branch only if its additional security and verification obligations can be met.
|
||||
|
||||
The strongest new theoretical lead is the TCC 2025 result by Blocki and Smearsoll on memory-hard proofs of work with memory-easy verification [R1]. It provides a basis for proving that a successful prover incurs a substantial memory-time cost. The bandwidth-hardness literature [R2,R3] supplies relevant energy/resource tools. Their combination is a research direction: the cited theorems do not already establish a 1.5x physical GPU/ASIC ceiling, and a cheating-proof-producer energy reduction must not be assumed from a theorem about full function evaluation.
|
||||
|
||||
A 2026 result [R4] is especially important: some pebbling-only security arguments can miss cheaper encodings of memory, including XOR combinations. This reinforces the need to allow representation changes, like the exact reg64 prefix-XOR alternative already recorded in the Igneum reviews. It does not refute every pebbling theorem or the specific papers used here; it requires a valid reduction to the actual adversary model.
|
||||
|
||||
## 1. Sources, scope and evidential boundaries
|
||||
|
||||
The project basis is the uploaded 8 October v6 freeze tree and the earlier source reviews and test registry. The archive inspected has SHA-256:
|
||||
|
||||
`f448981b2ceeab2e59e8bbd137a1a13ea1c730ecd9db72b9a89bd2bbf5d85acb`
|
||||
|
||||
The latest 1.5x DRAM and 1.9-2.1x hybrid figures are supplied by the user. No latest full energy workbook, placed full-system report or revised pack proving those figures was newly supplied with this request. Older source ratios must not be mixed into them as if they describe the same candidate.
|
||||
|
||||
Source-derived observations retained:
|
||||
|
||||
- An older hybrid model stores half of the dataset's items and serves 72% of reads from them. Its 5.5 GiB floor changes the memory ticket, not automatically the energy ratio.
|
||||
- The census compares important statistics with a window-conditioned distribution. Passing that comparison does not imply globally uniform traffic.
|
||||
- A layer-8-off experiment was already scheduled in the source. Confirm its inclusion in the latest result before crediting it again.
|
||||
- The connected-state candidate was explicitly rejected after the adversary used a clock-gated register file. The masked FP32 candidate was rejected after GPU overhead and full-board comparison. Neither is an untried remedy.
|
||||
- Physical work used ASAP7 for part of the core, with modeled memory, whole-machine terms and cross-process scaling. ASAP7's publisher explicitly describes it as predictive and not manufacturable [R5].
|
||||
|
||||
Exact source locations:
|
||||
|
||||
- `docs/design/class-v6-rotating-family.md:540-551,564-582`
|
||||
- `docs/analysis/class-v6/census-packs.md:18-22,36-38`
|
||||
- `docs/analysis/class-v6/family-gate.md:336-344`
|
||||
- `docs/analysis/class-v6/connected-state.md:91-126`
|
||||
- `igneum-pow/src/verify.rs:8-63,154-171`
|
||||
|
||||
This study inspected literature and source material and executed the accompanying arithmetic checks. It did not execute Rust, a GPU miner, an SP1 prover, a native network, a physical chip or a foundry implementation. The 2025 MHPoW theorem statements were checked in the authors' ePrint abstract and publisher record; the full paper was not retrievable in this session. Full cryptographic review is a mandatory work package, not claimed complete here. The 2026 DEGSample paper's full PDF and other accessible full-text material were consulted selectively; no independent proof audit is claimed.
|
||||
|
||||
## 2. The claim and the direction of proof
|
||||
|
||||
For a fixed work function, difficulty and environment, let G be GPU energy per equivalent accepted work. Let E* be the infimum of specialist energy across the allowed implementations and hardware. The required statement is:
|
||||
|
||||
`G / E* <= 1.5`.
|
||||
|
||||
A functioning or modeled specialist D gives an estimate E_D. Even if that estimate is accurate, E* <= E_D. Therefore:
|
||||
|
||||
`G / E* >= G / E_D`.
|
||||
|
||||
A chip at 1.5x is a witness of at least that achievable advantage. It is not an upper bound on every better chip someone might design. A physical-layout report has value but does not reverse this inequality.
|
||||
|
||||
A scoped upper-bound certificate instead requires a justified lower bound L on every permitted specialist's energy and an upper bound G_upper on the relevant GPU's energy:
|
||||
|
||||
`L <= E*` and `G_upper / L <= 1.5`.
|
||||
|
||||
The certificate must identify what is permitted: process technology, memory technologies and capacity choices, primitive assumptions, parallelism, precomputation, time horizon and power boundary. A result within that model is not a guarantee about all future physics or undiscovered algorithms.
|
||||
|
||||
Use four separate evidence levels:
|
||||
|
||||
1. **Functional validity:** all implementations compute the specified work and verify the permitted proofs.
|
||||
2. **Resource security:** every successful adversary pays a quantified cost in the stated cryptographic/computation model.
|
||||
3. **Physical translation:** conservative, justified component costs and feasible architectures translate the resource frontier into a scoped energy lower bound.
|
||||
4. **Engineering reproduction:** real GPUs and independent adversarial designs calibrate, challenge and attempt to falsify the model.
|
||||
|
||||
An empirical envelope over assessed chips is not the same as a universal theorem. Label the output accordingly if level 3 cannot be made sufficiently strong.
|
||||
|
||||
## 3. Mathematical screening results
|
||||
|
||||
### 3.1 Required improvement
|
||||
|
||||
For starting ratio r, GPU energy multiplier g and specialist energy multiplier a:
|
||||
|
||||
`r_new = r * g / a`.
|
||||
|
||||
At r=2.1, GPU-only improvement requires a 28.5714% energy reduction. Specialist-only improvement requires 40% more specialist energy. A hypothetical 15% GPU reduction and 20% specialist increase produces exactly 1.4875. These are requirements and illustrations, not an allocation of forecast gains.
|
||||
|
||||
### 3.2 Static cache optimality
|
||||
|
||||
Let p_1,...,p_N be probabilities of independent requests for equal-sized items, sorted largest first. A best fixed cache holding q items has hit probability:
|
||||
|
||||
`H(q) = sum_{i=1..q} p_i >= q/N`.
|
||||
|
||||
Proof: the average of the largest q probabilities cannot be smaller than the average of all N. Uniform probabilities attain equality simultaneously for every q. Relabelling items preserves the sorted probabilities and thus H(q).
|
||||
|
||||
Consequences:
|
||||
|
||||
- Uniformity is the best distribution against this fixed-cache model.
|
||||
- A best half-capacity cache still serves at least half the requests.
|
||||
- An epoch permutation alone cannot destroy hot-set mass.
|
||||
- This is not a theorem about adaptive, future-aware, compressed or multi-level caches. Those adversaries still need evaluation.
|
||||
|
||||
### 3.3 The old hot-half example
|
||||
|
||||
Moving from 72% hits to 50% changes misses from 28% to 50%, a multiplier of 25/14. Let eta be the fraction of old specialist energy proportional to those misses. In a deliberately simplified fixed-design model:
|
||||
|
||||
`r_new = r * g / (1 + (11/14)*eta)`.
|
||||
|
||||
From r=2.1 with no GPU improvement, eta must be at least 28/55, approximately 50.91%, to reach 1.5. With a hypothetical 10% GPU reduction, it must be at least 91/275, approximately 33.09%.
|
||||
|
||||
This model does not include extra SRAM traffic, clock changes, scheduling, replacement architecture or GPU loss. It is a prioritisation sensitivity calculation, not an estimated new result. It is inapplicable if the current 1.9-2.1x result already includes window removal.
|
||||
|
||||
### 3.4 Why a better operation mix can plateau
|
||||
|
||||
If one feasible specialist implements every independent component with ratio r_i above 1.5, and costs add without new coupling overhead, then the mixed ratio is:
|
||||
|
||||
`sum_i (r_i * E_A_i) / sum_i E_A_i`.
|
||||
|
||||
This is a weighted average of r_i and cannot fall below their minimum. Reweighting those components cannot cross 1.5 within that model. A genuine improvement must change some component advantage, eliminate GPU overhead, or introduce a real cost missing from the additive model.
|
||||
|
||||
This is a conditional screening lemma, not a claim that every complete architecture has additive costs.
|
||||
|
||||
### 3.5 The memory-energy bridge
|
||||
|
||||
If fraction f of GPU energy is for unavoidable memory movement, the specialist has memory-energy advantage s, and non-memory advantage c, an additive model gives:
|
||||
|
||||
`r = 1 / (f/s + (1-f)/c)`.
|
||||
|
||||
Even allowing specialist non-memory work to be free gives `r = s/f`. To reach 1.5 through the memory term alone requires `f >= s/1.5`. At s=1.0, f must reach 66.67%; at s=1.2, 80%; at s=1.5, 100%.
|
||||
|
||||
This does not say that GPU memory utilisation equals f. It also does not establish that s is near one: SRAM, nearby compute and alternative memory systems are exactly why that premise must be tested.
|
||||
|
||||
### 3.6 Guardband
|
||||
|
||||
An illustrative nominal ratio of 1.25, with GPU energy 5% worse and specialist energy 10% better than central estimates, becomes:
|
||||
|
||||
`1.25 * 1.05 / 0.90 = 1.45833...`.
|
||||
|
||||
A nominal 1.30 becomes 1.51667. Thus an exact 1.50 point estimate has inadequate room for those assumed uncertainties. The 5% and 10% are not measured error bars and do not capture an omitted architecture.
|
||||
|
||||
## 4. Historical and recent research: use mechanisms, not slogans
|
||||
|
||||
### 4.1 Memory work predates cryptocurrency
|
||||
|
||||
Dwork, Naor and Wee's 2005 work [R6] studies memory-bound proof-of-work via pebbling and amortised memory-access requirements. The enduring lesson is to formalise what an adversary must pay, including repeated work, not just what a reference program allocates.
|
||||
|
||||
### 4.2 Capacity and energy are distinct
|
||||
|
||||
Ren and Devadas [R3] make the capacity/energy distinction explicit. Blocki, Liu, Ren and Zhou [R2] extend bandwidth-hardness analysis in the parallel random oracle model and analyse named constructions. The corrected 2024 version should be used, not a superseded result.
|
||||
|
||||
The useful question is not simply how much memory is allocated. It is how much communication or recomputation remains necessary under every permitted fast-memory budget and representation. Cache-size assumptions are part of the theorem.
|
||||
|
||||
### 4.3 Cheap verification is dangerous when improvised
|
||||
|
||||
Dinur and Nadler's analysis [R7] attacked the earlier MTP construction. A commitment to a large table plus a few verified openings does not automatically prove that the prover incurred the intended construction cost.
|
||||
|
||||
A proposer may grind commitments, exploit predictable checks, leave much of the table unevaluated or reuse work across attempts. Analyze the cost of generating accepted certificates, not only the honest full evaluation.
|
||||
|
||||
### 4.4 A stronger modern starting point
|
||||
|
||||
The Blocki-Smearsoll TCC 2025 result [R1] establishes, in its stated model, an MTP instantiation using suitable data-independent functions, with DRSample giving O(N) honest sequential time, polylogarithmic proof size/verification and high cumulative memory complexity for successful malicious provers. This is the starting point for Track B, not a complete physical-energy result.
|
||||
|
||||
### 4.5 Newer results expand options but do not compose automatically
|
||||
|
||||
Blocki-Holman's CRYPTO 2026 DEGSample work [R8] proves a sustained-space/cumulative-memory trade-off directly in the parallel random oracle model. A data-dependent construction may be attractive against some prearranged schedules, but it is not a drop-in replacement inside a theorem requiring a data-independent graph.
|
||||
|
||||
The 2026 separation paper [R4] shows why arbitrary encoded state must be permitted. Its result is not a blanket refutation of graph methods: the valid reduction must establish that the chosen model covers the encoding strategies at issue.
|
||||
|
||||
### 4.6 Resource matching and GPU implementation still matter
|
||||
|
||||
RandomX and ProgPoW [R9,R10] provide designs oriented towards commodity hardware resources. HashCore [R11] studies workload design by working backwards from processor characteristics. None supplies a proved universal 1.5x ceiling for Igneum.
|
||||
|
||||
Cuckoo Cycle's own documentation [R12] distinguishes alternative solving strategies and discusses SRAM suitability. A memory-bound graph problem is not automatically resistant to specialised memory.
|
||||
|
||||
## 5. Track A - A minimal-change route to the first credible result
|
||||
|
||||
### A0. Freeze the actual comparison
|
||||
|
||||
Produce the pack hash, precise acceptance rule, GPU kernel/host version, actual traffic traces, placed full-core model and all board assumptions behind the latest 1.9-2.1x. Identify whether layer-8-off and result compaction are already included. Do not splice ratios from different snapshots.
|
||||
|
||||
### A1. Window-free addressing control
|
||||
|
||||
Run the existing candidate against a version without the fixed per-load window restriction. Initially hold read count, width, dataset size and register schedule constant. Evaluate the real dataset and held-out headers/nonces. This is a consensus-changing experiment; do not silently alter legacy work.
|
||||
|
||||
Publish best static, trained and adaptive cache-benefit curves at 0%, 1%, 5%, 10%, 25%, 50%, 75% and 100% fast storage. Measure temporal phases and repeated-item correlations. Future-trace-optimal replacement is an attacker-favourable bound, not a realistic deployable policy by itself.
|
||||
|
||||
### A2. Byte-preserving honest-worker optimisation
|
||||
|
||||
Port the existing OpenCL candidate-selection pattern to CUDA, retaining sentinels, overflow handling and full-reference mode. Evaluate exact reg64 implementation alternatives on BOTH sides. Tune the final workload, including host readback, cancellation and epoch overhead. No assumed percentage is assigned.
|
||||
|
||||
Keep measured wall energy as the primary boundary. Do not subtract inconvenient host power from the GPU while retaining a different scale convention for the specialist. Also report device-only diagnostics separately.
|
||||
|
||||
### A3. Re-optimise every opponent
|
||||
|
||||
The best old half-cache need not remain the best new design. Include full SRAM, different stored fractions, reconstruction, lower clock rates, multi-chip shared memory and programmable multi-family cores. Count memory and control activity, not only logical bit capacity.
|
||||
|
||||
A failed connected-state or FP32 candidate may re-enter only with a written explanation of what materially differs from its earlier failure mechanism.
|
||||
|
||||
## 6. Track B - Proof-carrying, input-specific memory work
|
||||
|
||||
**Working concept:** replace most amortisable static-table work with construction and evaluation of input-specific state whose omission, encoding or recomputation is covered by a resource-cost argument; carry a compact certificate that ordinary validators can check.
|
||||
|
||||
This is a proposed construction family. It is not yet an implemented algorithm or claimed novel theorem.
|
||||
|
||||
### B1. Reproduce the published primitive first
|
||||
|
||||
Implement the exact data-independent MTP/DRSample reference and its full verifier, including domain separation and all prescribed checks, before inventing a GPU adaptation. Obtain and review the full paper; the abstract is not an implementation specification. Produce small known-answer fixtures and malicious-prover test fixtures.
|
||||
|
||||
### B2. Bind the economically expensive work
|
||||
|
||||
Define a canonical instance input committing to network, version, epoch, block-template context and the trial identifier. Every alternative that changes the winning lottery trial must pay the proved cost or an explicitly bounded amortised portion of it.
|
||||
|
||||
Do not write a new outer nonce that can vary cheaply after one expensive state commitment without analysing the resulting reuse. Do not equate a proof of correct execution with proof of unavoidable physical work. Investigate commitment grinding, chosen-input selection, correlated instances, rejected trials and cancellation.
|
||||
|
||||
A diagram of the intended roles is:
|
||||
|
||||
`bound work instance -> state construction -> prescribed proof search/certificate -> verification + target check`.
|
||||
|
||||
This is a role diagram, not a substitute for the exact protocol.
|
||||
|
||||
### B3. GPU adaptation without silently changing the theorem
|
||||
|
||||
First change representation and scheduling while preserving the exact function. Test structure-of-arrays batching, coalesced label layout and cooperative processing where mathematically permitted. Do not delete dependency edges merely to make the graph faster and then retain its old proof.
|
||||
|
||||
A proposed early parameter sweep may explore per-instance states such as 32, 128 and 512 MiB, with the number of concurrent instances limited by measured usable memory and full proof-construction overhead. These are exploratory sizes, not adopted network parameters.
|
||||
|
||||
There is a major feasibility test: large sequential per-instance graphs can leave a GPU underutilised, while shrinking instances for more parallelism may let an ASIC fit each instance in SRAM. Reject a configuration that is memory-hard but principally CPU-friendly. If label width or graph structure must change, commission the corresponding proof rather than assume inheritance.
|
||||
|
||||
### B4. Prove the energy cost of accepted proofs
|
||||
|
||||
The desired result is not merely a lower bound for honest complete graph evaluation. Derive a lower bound for all allowed adversaries producing accepted work with a specified success probability, including partial evaluation, shortcuts and multi-instance amortisation.
|
||||
|
||||
A candidate theorem should expose a joint trade-off over primitive calls, fast-memory capacity, transfers and sustained storage. The physical model then minimises over those jointly permitted strategies. Do not add unrelated lower bounds when they double-count the same work.
|
||||
|
||||
The 2025 proof-of-work theorem and 2024 bandwidth results motivate this work but do not automatically establish the required composed theorem, particularly for the sampled/ex-post graph produced by a cheating prover. This is a central new proof obligation.
|
||||
|
||||
### B5. Confront the full-SRAM design explicitly
|
||||
|
||||
Fresh state stops an old cache from being reused merely because the epoch remains unchanged. It does not prevent a specialist from constructing new state in fast memory.
|
||||
|
||||
A proof that assumes the fast cache is small cannot defeat an adversary allowed to place the entire working set there. Evaluate its active read/write energy, leakage, ports, routing, controller, parallel throughput and fabrication economics. If the energy test still fails, keep P04 failed. Expensive construction belongs to P12; it cannot excuse P04.
|
||||
|
||||
### B6. Verification and network fit
|
||||
|
||||
Count graph commitment cost, proof construction, proof bytes, verifier CPU/RAM, invalid-proof amplification, pool-share checking, propagation, cancellation and disk/state handling. Test cold verification at the maximum admitted rate, not only cached success.
|
||||
|
||||
Very roughly, proof arrival rate times per-proof CPU time must fit the provisioned verification budget with headroom, but batching and worst-case adversarial payloads require their own analysis. Do not use this simple product as a denial-of-service proof.
|
||||
|
||||
A new work unit cannot be judged by raw hashes per second against v6. Before evaluation, approve an equivalent lottery-contribution/security-budget comparison and retain explicit absolute node/operator budgets. Do not declare P03 satisfied by renaming a much larger puzzle one hash or by changing difficulty to mask cost.
|
||||
|
||||
## 7. Track C - Dynamic sustained-memory research, gated separately
|
||||
|
||||
Use DEGSample as an independent exploratory branch only after identifying a deficiency of Track B that it could fix. First benchmark the exact dynamic construction. Then ask whether its resource advantage survives real GPU execution and the strongest SRAM schedule.
|
||||
|
||||
Its PROM trade-off is not already a memory-easy PoW verifier. Either use expensive full verification only as a research control or develop a sound efficient-verification transformation. Do not put a zkVM wrapper around it and presume proof generation inherits the resource-cost lower bound.
|
||||
|
||||
The constraints to solve together are efficient honest GPU execution, a cheating-prover cost theorem, cheap safe network verification, and real whole-system energy. The newer theorem is a research tool, not a release certificate.
|
||||
|
||||
## 8. The physical certificate and its limitations
|
||||
|
||||
Construct a conservative optimisation problem over the adversary's hardware and evaluation strategy. Necessary cryptographic trade-offs constrain feasible resource use; technology assumptions provide lower cost coefficients. An appropriately relaxed feasible set may yield a certified LOWER bound on cost. A restricted list of heuristic attackers normally yields only assessed examples.
|
||||
|
||||
Use explicit lower-bound certificates or optimality gaps where tractable. Small-graph exhaustive or integer-programming checks can validate the analysis, but scaling from small graphs requires a justified theorem. More optimisation runs alone do not prove the unknown optimum.
|
||||
|
||||
The target final record contains:
|
||||
|
||||
- The exact cryptographic assumptions and finite parameters.
|
||||
- Every reduction loss and failure probability; no hidden big-O constants in the numerical claim.
|
||||
- Permitted caching, compression, arbitrary encoding, recomputation and parallel strategies.
|
||||
- Technology set, process comparisons and optimistic-adversary energy ranges.
|
||||
- GPU upper energy observations, repetitions, environmental corrections and uncertainty.
|
||||
- The derived energy lower bound and independently checked ratio.
|
||||
- Separate area/capital/total-cost results and excluded technology scenarios.
|
||||
|
||||
ASAP7 is useful for screening architecture, but cannot alone certify an N2/N3 manufactured system. Foundry-calibrated memory and logic data and independent physical review are required for the stronger engineering interpretation. A shipped-chip measurement still does not establish a bound for all unbuilt alternatives.
|
||||
|
||||
## 9. Future adversaries that must remain in the study
|
||||
|
||||
- **Programmable compute-only silicon:** no display/graphics machinery required, with all published families and microcode updates.
|
||||
- **Chiplets, 3D SRAM and modular memory:** UCIe documents modular/3D die interconnect [R13]. Do not assume a reticle limit or a memory change implies full replacement of the compute design.
|
||||
- **Near-memory and in-memory compute:** Samsung has demonstrated HBM processing-in-memory [R14]. AI workload savings cannot be transferred to Igneum, but the architecture invalidates a permanently fixed compute/DRAM boundary assumption.
|
||||
- **Multiple manufacturing generations:** evaluate a technology envelope rather than a forever claim. Older GPU cohorts must not silently disappear from the result.
|
||||
- **Future algorithmic shortcuts:** retain a public challenge and independent reviewer; an improved attacker changes the envelope. Do not convert the bounty budget into a proof of absence.
|
||||
- **Quantum adversaries:** the proposed baseline is classical. A separate quantum/random-oracle/reversible-memory analysis is necessary before a quantum-resistance claim. No delivery date or quantum speedup estimate is asserted here.
|
||||
|
||||
A technology-triggered review is not an automatic consensus fork. The no-rescue test still assumes a specialist remains operational through known epochs and that an emergency algorithm switch is not needed to make the current economics look good.
|
||||
|
||||
## 10. Proposed execution packages
|
||||
|
||||
| Package | Owner capability | Required artefact | Gate |
|
||||
|---|---|---|---|
|
||||
| R15-01 | Release + measurement | Latest exact pack, physical assumptions, source manifest, current ratio reconciliation | No cross-version mixed baseline |
|
||||
| R15-02 | GPU + hardware | Component power/traffic model and sensitivity analysis | No device/whole-machine boundary mismatch |
|
||||
| R15-03 | GPU + memory analysis | Layer-8-off control and held-out cache curves | Distinct benefit after best cache adaptation |
|
||||
| R15-04 | GPU systems | Compaction, exact-fold alternatives and tuning results | Byte agreement, real accepted-work savings |
|
||||
| R15-05 | Cryptography | Exact published MHPoW control, theorem audit, malicious fixtures | No improvised sampled-memory soundness |
|
||||
| R15-06 | GPU + cryptography | Theorem-preserving layout/parallelisation feasibility | GPU competitiveness and cheap-enough verification |
|
||||
| R15-07 | Cryptography + hardware | Joint accepted-proof resource frontier with concrete constants | No invalid theorem composition |
|
||||
| R15-08 | Independent ASIC team | Re-optimised SRAM/DRAM/hybrid/recompute/PIM scenarios | Full-storage adversary not excluded by price |
|
||||
| R15-09 | Measurement + economics | Blind cohort confirmation and separate P12 outcomes | Strongest credible ratio, not average |
|
||||
| R15-10 | Protocol/security | Network and pool integration, no-rescue exercise, public evidence | Correctness and safe operation remain intact |
|
||||
|
||||
Run R15-03/04 alongside R15-05/06. Do not wait for every speculative theorem before reducing existing GPU waste; do not let quick wins substitute for the proof obligation.
|
||||
|
||||
A plausible small research group needs memory-hardness expertise, a GPU/compiler engineer, an ASIC/physical-design reviewer and a reproducibility/protocol engineer. These are capabilities, not claimed appointments. Commission an independent challenger whose success criterion is finding a better adversary, not validating the desired marketing result.
|
||||
|
||||
## 11. Acceptance and stopping rules
|
||||
|
||||
1. The current P04 stays unchanged unless a new scope is ratified BEFORE results. Never silently replace a same/one-node cohort gate with one flagship result.
|
||||
2. An unknown decision-critical silicon assumption is BLOCKED, not PASS.
|
||||
3. Expensive research cost and calendar rotation are not energy resistance.
|
||||
4. A candidate may not improve the ratio by imposing a large cost on ordinary GPUs. Existing P03 limits govern like-for-like changes; changed work definitions require an explicit comparison contract, not a retrospective exemption.
|
||||
5. All prototypes retain published negative results. Rejecting a candidate redirects research; it does not establish a universal impossibility.
|
||||
6. A mathematical argument about storage must cover arbitrary representations through a valid reduction. A trace showing every register influences an address is insufficient.
|
||||
7. The best full-SRAM, hybrid and recompute designs remain in the comparison after every change.
|
||||
8. Lower-bound derivations and engineering measurements receive independent scrutiny; empirical models and formal theorems are labelled separately.
|
||||
9. Verification, block propagation, pool work, proof generation and job cancellation fit ordinary-operator budgets.
|
||||
10. The founding statement is earned only with separate economic-access evidence. Energy <=1.5 does not alone establish monetary security, permanent profitability, future technological parity or category leadership.
|
||||
|
||||
## 12. Immediate recommendation
|
||||
|
||||
Do not announce that v7 solves resistance. Commission three concrete outputs first: the current hybrid energy frontier tied to the exact pack; the window-free/optimised-v6 paired result; and a feasibility prototype of the published proof-carrying memory-work construction.
|
||||
|
||||
If the first track closes the gap, independently validate it. If it does not, the proof-first track is a substantive architectural alternative, not another unpriced randomisation layer. The intended innovation is a hardware-cost claim that starts with adversarial resource proofs and ends with calibrated GPU economics.
|
||||
|
||||
## Primary references
|
||||
|
||||
All links were consulted on 9 October 2026. Reading depth is stated where important. A citation is not an independent replication.
|
||||
|
||||
- **R1.** Blocki and Smearsoll, *Provably Memory-Hard Proofs of Work with Memory-Easy Verification*, TCC 2025. Author abstract and publisher theorem summary consulted; full proof not retrieved. https://eprint.iacr.org/2025/1456 ; https://link.springer.com/chapter/10.1007/978-3-032-12290-2_17
|
||||
- **R2.** Blocki, Liu, Ren and Zhou, *Bandwidth-Hard Functions: Reductions and Lower Bounds*, Journal of Cryptology 2024 extended version. https://eprint.iacr.org/2018/221
|
||||
- **R3.** Ren and Devadas, *Bandwidth Hard Functions for ASIC Resistance*, TCC 2017. https://eprint.iacr.org/2017/225
|
||||
- **R4.** de Rezende, Engstrom and Reyzin, *Separating the Pebbling Model from the Random Oracle Model*, 2026 preprint. Author abstract consulted; not treated as a claim about all existing graph constructions. https://eprint.iacr.org/2026/1024
|
||||
- **R5.** Arizona State University and ARM, ASAP7 predictive PDK documentation. https://asap.asu.edu/
|
||||
- **R6.** Dwork, Naor and Wee, *Pebbling and Proofs of Work*, CRYPTO 2005. https://www.microsoft.com/en-us/research/publication/pebbling-and-proofs-of-work/
|
||||
- **R7.** Dinur and Nadler, *Time-Memory Tradeoff Attacks on the MTP Proof-of-Work Scheme*, CRYPTO 2017. https://eprint.iacr.org/2017/497
|
||||
- **R8.** Blocki and Holman, *Data-Dependent Memory-Hard Functions: Sustained Space and Cumulative Complexity Trade-offs in the Parallel Random Oracle Model*, CRYPTO 2026, revision 18 August 2026. Full PDF consulted selectively. https://arxiv.org/abs/2508.06795 ; https://arxiv.org/pdf/2508.06795v2
|
||||
- **R9.** RandomX design and v2 design. https://github.com/tevador/RandomX/blob/master/doc/design.md ; https://github.com/tevador/RandomX/blob/master/doc/design_v2.md
|
||||
- **R10.** ProgPoW reference design. https://github.com/ifdefelse/ProgPOW
|
||||
- **R11.** *HashCore: Proof-of-Work Functions for General Purpose Processors*. https://arxiv.org/abs/1902.00112
|
||||
- **R12.** John Tromp, Cuckoo Cycle reference implementation/design. https://github.com/tromp/cuckoo
|
||||
- **R13.** UCIe Consortium, specifications. https://www.uciexpress.org/specifications
|
||||
- **R14.** Samsung, HBM processing-in-memory announcement. Architecture precedent only; its AI performance percentages are not used for Igneum. https://news.samsung.com/global/samsung-develops-industrys-first-high-bandwidth-memory-with-ai-processing-power
|
||||
- **R15.** NVIDIA CUDA C++ Best Practices Guide. https://docs.nvidia.com/cuda/cuda-c-best-practices-guide/index.html
|
||||
- **R16.** Bhattacharyya and Mandal, *Bandwidth-Hard Functions from Random Permutations*, 2022. Accessible full text consulted for the model and its concrete reduction losses. https://arxiv.org/html/2207.11519v1
|
||||
|
||||
## Companion execution
|
||||
|
||||
Run `python check_arithmetic.py` to regenerate `arithmetic_results.json` using only Python's standard library. It performs 2,000 bounded random examples and exact rational calculations of the illustrative cache and mixture models. These checks are not native Igneum tests, not hardware benchmarks and not a proof of P04.
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
{
|
||||
"title": "Igneum 1.5x: exact model arithmetic",
|
||||
"date": "2026-10-09",
|
||||
"classification": "ILLUSTRATIVE MATHEMATICS; NO HARDWARE OR PROTOCOL RESULT",
|
||||
"target": {
|
||||
"exact": "3/2",
|
||||
"decimal": 1.5
|
||||
},
|
||||
"required_improvement": [
|
||||
{
|
||||
"starting_ratio": {
|
||||
"exact": "19/10",
|
||||
"decimal": 1.9
|
||||
},
|
||||
"gpu_only_required_reduction": {
|
||||
"exact": "4/19",
|
||||
"decimal": 0.21052631578947367
|
||||
},
|
||||
"specialist_only_required_increase": {
|
||||
"exact": "4/15",
|
||||
"decimal": 0.26666666666666666
|
||||
},
|
||||
"illustration_gpu_minus_15pct_specialist_plus_20pct": {
|
||||
"exact": "323/240",
|
||||
"decimal": 1.3458333333333334
|
||||
}
|
||||
},
|
||||
{
|
||||
"starting_ratio": {
|
||||
"exact": "2",
|
||||
"decimal": 2.0
|
||||
},
|
||||
"gpu_only_required_reduction": {
|
||||
"exact": "1/4",
|
||||
"decimal": 0.25
|
||||
},
|
||||
"specialist_only_required_increase": {
|
||||
"exact": "1/3",
|
||||
"decimal": 0.3333333333333333
|
||||
},
|
||||
"illustration_gpu_minus_15pct_specialist_plus_20pct": {
|
||||
"exact": "17/12",
|
||||
"decimal": 1.4166666666666667
|
||||
}
|
||||
},
|
||||
{
|
||||
"starting_ratio": {
|
||||
"exact": "21/10",
|
||||
"decimal": 2.1
|
||||
},
|
||||
"gpu_only_required_reduction": {
|
||||
"exact": "2/7",
|
||||
"decimal": 0.2857142857142857
|
||||
},
|
||||
"specialist_only_required_increase": {
|
||||
"exact": "2/5",
|
||||
"decimal": 0.4
|
||||
},
|
||||
"illustration_gpu_minus_15pct_specialist_plus_20pct": {
|
||||
"exact": "119/80",
|
||||
"decimal": 1.4875
|
||||
}
|
||||
}
|
||||
],
|
||||
"old_source_hot_half_model": {
|
||||
"old_hit_fraction": {
|
||||
"exact": "18/25",
|
||||
"decimal": 0.72
|
||||
},
|
||||
"new_static_uniform_half_hit": {
|
||||
"exact": "1/2",
|
||||
"decimal": 0.5
|
||||
},
|
||||
"dram_miss_multiplier": {
|
||||
"exact": "25/14",
|
||||
"decimal": 1.7857142857142858
|
||||
},
|
||||
"required_miss_energy_fraction_from_2p1_no_gpu_gain": {
|
||||
"exact": "28/55",
|
||||
"decimal": 0.509090909090909
|
||||
},
|
||||
"required_miss_energy_fraction_from_2p1_gpu_minus_10pct": {
|
||||
"exact": "91/275",
|
||||
"decimal": 0.33090909090909093
|
||||
},
|
||||
"illustration_50pct_miss_energy_no_gpu_gain": {
|
||||
"exact": "98/65",
|
||||
"decimal": 1.5076923076923077
|
||||
},
|
||||
"illustration_50pct_miss_energy_gpu_minus_10pct": {
|
||||
"exact": "441/325",
|
||||
"decimal": 1.356923076923077
|
||||
},
|
||||
"limits": "Fixed architecture, miss-scaled energy only; ignores adaptive caching, replacement design, changed SRAM traffic, contention, compression, clock changes and GPU regressions. Not a forecast."
|
||||
},
|
||||
"memory_dominance_illustrations": [
|
||||
{
|
||||
"specialist_memory_advantage": {
|
||||
"exact": "1",
|
||||
"decimal": 1.0
|
||||
},
|
||||
"minimum_gpu_energy_fraction_in_unavoidable_memory_even_if_specialist_compute_free": {
|
||||
"exact": "2/3",
|
||||
"decimal": 0.6666666666666666
|
||||
}
|
||||
},
|
||||
{
|
||||
"specialist_memory_advantage": {
|
||||
"exact": "6/5",
|
||||
"decimal": 1.2
|
||||
},
|
||||
"minimum_gpu_energy_fraction_in_unavoidable_memory_even_if_specialist_compute_free": {
|
||||
"exact": "4/5",
|
||||
"decimal": 0.8
|
||||
}
|
||||
},
|
||||
{
|
||||
"specialist_memory_advantage": {
|
||||
"exact": "3/2",
|
||||
"decimal": 1.5
|
||||
},
|
||||
"minimum_gpu_energy_fraction_in_unavoidable_memory_even_if_specialist_compute_free": {
|
||||
"exact": "1",
|
||||
"decimal": 1.0
|
||||
}
|
||||
}
|
||||
],
|
||||
"guardband_illustration": {
|
||||
"nominal_ratio": {
|
||||
"exact": "5/4",
|
||||
"decimal": 1.25
|
||||
},
|
||||
"gpu_energy_upper_multiplier": {
|
||||
"exact": "21/20",
|
||||
"decimal": 1.05
|
||||
},
|
||||
"specialist_energy_lower_multiplier": {
|
||||
"exact": "9/10",
|
||||
"decimal": 0.9
|
||||
},
|
||||
"conservative_ratio": {
|
||||
"exact": "35/24",
|
||||
"decimal": 1.4583333333333333
|
||||
},
|
||||
"limits": "The 5% and 10% values are assumed bounds, not measured errors or confidence intervals. Does not cover unknown architectures."
|
||||
},
|
||||
"checks": {
|
||||
"static_cache_examples": 1000,
|
||||
"additive_mixture_examples": 1000,
|
||||
"mismatches": 0,
|
||||
"meaning": "Arithmetic checks of stated models, not proof of a hardware bound. General lemmas are proved in the companion plan."
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Exact illustrative calculations for Igneum's 1.5x research programme.
|
||||
|
||||
No GPU benchmark, ASIC model, native proof verification, or measured outcome is
|
||||
implemented here. Fractions are exact; every numerical case is an illustration.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
import json
|
||||
import random
|
||||
from fractions import Fraction as F
|
||||
from pathlib import Path
|
||||
|
||||
TARGET = F(3, 2)
|
||||
|
||||
def number(x: F) -> dict[str, str | float]:
|
||||
return {"exact": str(x), "decimal": float(x)}
|
||||
|
||||
def ratio_after(r: F, gpu_multiplier: F, specialist_multiplier: F) -> F:
|
||||
if min(r, gpu_multiplier, specialist_multiplier) <= 0:
|
||||
raise ValueError("Energies and multipliers must be positive")
|
||||
return r * gpu_multiplier / specialist_multiplier
|
||||
|
||||
def retained_miss_model(r: F, gpu_multiplier: F, miss_energy_fraction: F,
|
||||
old_hit: F = F(18,25), new_hit: F = F(1,2)) -> F:
|
||||
if not (0 <= old_hit < 1 and 0 <= new_hit < 1):
|
||||
raise ValueError("Hit fractions must be in [0,1)")
|
||||
if not 0 <= miss_energy_fraction <= 1:
|
||||
raise ValueError("Energy fraction must be in [0,1]")
|
||||
miss_multiplier = (1-new_hit)/(1-old_hit)
|
||||
return ratio_after(r, gpu_multiplier,
|
||||
1 + miss_energy_fraction*(miss_multiplier-1))
|
||||
|
||||
def required_miss_energy_fraction(r: F, g: F) -> F:
|
||||
# Fixed-design illustration, NOT an optimised-hardware or traffic model.
|
||||
return max(F(0), (r*g/TARGET-1)/(F(1,2)/F(7,25)-1))
|
||||
|
||||
def additive_ratio(memory_fraction: F, memory_advantage: F,
|
||||
nonmemory_advantage: F) -> F:
|
||||
if not 0 <= memory_fraction <= 1:
|
||||
raise ValueError("Fraction outside [0,1]")
|
||||
if min(memory_advantage, nonmemory_advantage) <= 0:
|
||||
raise ValueError("Advantages must be positive")
|
||||
return 1/(memory_fraction/memory_advantage +
|
||||
(1-memory_fraction)/nonmemory_advantage)
|
||||
|
||||
def checks() -> dict:
|
||||
rng = random.Random(15020261009)
|
||||
cache_examples = 0
|
||||
for _ in range(1000):
|
||||
n = rng.randint(2, 128)
|
||||
raw = [rng.randint(1,10000) for _ in range(n)]
|
||||
p = [F(x,sum(raw)) for x in raw]
|
||||
q = rng.randint(1,n)
|
||||
best = sum(sorted(p, reverse=True)[:q], F(0))
|
||||
assert best >= F(q,n)
|
||||
shuffled = p[:]
|
||||
rng.shuffle(shuffled)
|
||||
assert sum(sorted(shuffled, reverse=True)[:q], F(0)) == best
|
||||
cache_examples += 1
|
||||
mixed_examples = 0
|
||||
for _ in range(1000):
|
||||
adv = [F(rng.randint(16,50),10) for _ in range(6)]
|
||||
specialist_energy = [F(rng.randint(1,100),10) for _ in adv]
|
||||
mixed = sum((r*e for r,e in zip(adv,specialist_energy)), F(0))/sum(specialist_energy,F(0))
|
||||
assert min(adv) <= mixed <= max(adv)
|
||||
assert mixed > TARGET
|
||||
mixed_examples += 1
|
||||
assert ratio_after(F(21,10),F(85,100),F(12,10)) == F(119,80)
|
||||
assert F(5,4)*F(105,100)/F(90,100) == F(35,24)
|
||||
return {"static_cache_examples":cache_examples,
|
||||
"additive_mixture_examples":mixed_examples,
|
||||
"mismatches":0,
|
||||
"meaning":"Arithmetic checks of stated models, not proof of a hardware bound. General lemmas are proved in the companion plan."}
|
||||
|
||||
def main() -> None:
|
||||
rows=[]
|
||||
for r in (F(19,10),F(2),F(21,10)):
|
||||
rows.append({"starting_ratio":number(r),
|
||||
"gpu_only_required_reduction":number(1-TARGET/r),
|
||||
"specialist_only_required_increase":number(r/TARGET-1),
|
||||
"illustration_gpu_minus_15pct_specialist_plus_20pct":number(ratio_after(r,F(85,100),F(12,10)))})
|
||||
report={
|
||||
"title":"Igneum 1.5x: exact model arithmetic",
|
||||
"date":"2026-10-09",
|
||||
"classification":"ILLUSTRATIVE MATHEMATICS; NO HARDWARE OR PROTOCOL RESULT",
|
||||
"target":number(TARGET),
|
||||
"required_improvement":rows,
|
||||
"old_source_hot_half_model":{
|
||||
"old_hit_fraction":number(F(18,25)),"new_static_uniform_half_hit":number(F(1,2)),
|
||||
"dram_miss_multiplier":number(F(25,14)),
|
||||
"required_miss_energy_fraction_from_2p1_no_gpu_gain":number(required_miss_energy_fraction(F(21,10),F(1))),
|
||||
"required_miss_energy_fraction_from_2p1_gpu_minus_10pct":number(required_miss_energy_fraction(F(21,10),F(9,10))),
|
||||
"illustration_50pct_miss_energy_no_gpu_gain":number(retained_miss_model(F(21,10),F(1),F(1,2))),
|
||||
"illustration_50pct_miss_energy_gpu_minus_10pct":number(retained_miss_model(F(21,10),F(9,10),F(1,2))),
|
||||
"limits":"Fixed architecture, miss-scaled energy only; ignores adaptive caching, replacement design, changed SRAM traffic, contention, compression, clock changes and GPU regressions. Not a forecast."},
|
||||
"memory_dominance_illustrations":[
|
||||
{"specialist_memory_advantage":number(s),
|
||||
"minimum_gpu_energy_fraction_in_unavoidable_memory_even_if_specialist_compute_free":number(s/TARGET)}
|
||||
for s in (F(1),F(6,5),F(3,2))],
|
||||
"guardband_illustration":{
|
||||
"nominal_ratio":number(F(5,4)),"gpu_energy_upper_multiplier":number(F(105,100)),
|
||||
"specialist_energy_lower_multiplier":number(F(90,100)),
|
||||
"conservative_ratio":number(F(35,24)),
|
||||
"limits":"The 5% and 10% values are assumed bounds, not measured errors or confidence intervals. Does not cover unknown architectures."},
|
||||
"checks":checks()}
|
||||
out=Path(__file__).with_name("arithmetic_results.json")
|
||||
out.write_text(json.dumps(report,indent=2)+"\n",encoding="utf-8")
|
||||
print(json.dumps({"output":str(out),"checks":report["checks"]},indent=2))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"IGNEUM_1p5x_Research_Plan.md": {
|
||||
"bytes": 30977,
|
||||
"sha256": "269ceaa5824d09140a1bcc124dba59438db5a5e68fddc18960db7141fefc0305"
|
||||
},
|
||||
"arithmetic_results.json": {
|
||||
"bytes": 4186,
|
||||
"sha256": "5bd8786a590cc51f221f44501c4f469c65ec2789bc15fda0168005e076ed12a2"
|
||||
},
|
||||
"check_arithmetic.py": {
|
||||
"bytes": 5553,
|
||||
"sha256": "1390a5564d18414f14fb2049514eac9a7d1d317648c81b0829873176a7717940"
|
||||
}
|
||||
}
|
||||
128
docs/plans/igneum-2.0-master/1p5x/research-plan/packages.json
Normal file
128
docs/plans/igneum-2.0-master/1p5x/research-plan/packages.json
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
{
|
||||
"document": "IGNEUM - The 1.5x Research Programme (9 October 2026)",
|
||||
"source": "igneum-1p5x-research-plan.md, section 10 'Proposed execution packages' (the table whose rows begin '| R15-')",
|
||||
"status": "PROPOSED; every package NOT RUN; the plan claims no pass",
|
||||
"lane_map_note": "the X and B cross-references on each package are the research-landing hand's reading of the plan against the brief's matrix and track B, for the coordinator to confirm; the lanes block names the owner lanes as the coordinator named them on 9 October",
|
||||
"packages": [
|
||||
{
|
||||
"id": "R15-01",
|
||||
"owner_capability": "Release + measurement",
|
||||
"required_artefact": "Latest exact pack, physical assumptions, source manifest, current ratio reconciliation",
|
||||
"gate": "No cross-version mixed baseline",
|
||||
"lanes": [
|
||||
"X0"
|
||||
],
|
||||
"status": "NOT RUN"
|
||||
},
|
||||
{
|
||||
"id": "R15-02",
|
||||
"owner_capability": "GPU + hardware",
|
||||
"required_artefact": "Component power/traffic model and sensitivity analysis",
|
||||
"gate": "No device/whole-machine boundary mismatch",
|
||||
"lanes": [
|
||||
"X0",
|
||||
"X5"
|
||||
],
|
||||
"status": "NOT RUN"
|
||||
},
|
||||
{
|
||||
"id": "R15-03",
|
||||
"owner_capability": "GPU + memory analysis",
|
||||
"required_artefact": "Layer-8-off control and held-out cache curves",
|
||||
"gate": "Distinct benefit after best cache adaptation",
|
||||
"lanes": [
|
||||
"X1"
|
||||
],
|
||||
"status": "NOT RUN"
|
||||
},
|
||||
{
|
||||
"id": "R15-04",
|
||||
"owner_capability": "GPU systems",
|
||||
"required_artefact": "Compaction, exact-fold alternatives and tuning results",
|
||||
"gate": "Byte agreement, real accepted-work savings",
|
||||
"lanes": [
|
||||
"X2",
|
||||
"X3",
|
||||
"X4"
|
||||
],
|
||||
"status": "NOT RUN"
|
||||
},
|
||||
{
|
||||
"id": "R15-05",
|
||||
"owner_capability": "Cryptography",
|
||||
"required_artefact": "Exact published MHPoW control, theorem audit, malicious fixtures",
|
||||
"gate": "No improvised sampled-memory soundness",
|
||||
"lanes": [
|
||||
"B1"
|
||||
],
|
||||
"status": "NOT RUN"
|
||||
},
|
||||
{
|
||||
"id": "R15-06",
|
||||
"owner_capability": "GPU + cryptography",
|
||||
"required_artefact": "Theorem-preserving layout/parallelisation feasibility",
|
||||
"gate": "GPU competitiveness and cheap-enough verification",
|
||||
"lanes": [
|
||||
"B3"
|
||||
],
|
||||
"status": "NOT RUN"
|
||||
},
|
||||
{
|
||||
"id": "R15-07",
|
||||
"owner_capability": "Cryptography + hardware",
|
||||
"required_artefact": "Joint accepted-proof resource frontier with concrete constants",
|
||||
"gate": "No invalid theorem composition",
|
||||
"lanes": [
|
||||
"B2",
|
||||
"B4"
|
||||
],
|
||||
"status": "NOT RUN"
|
||||
},
|
||||
{
|
||||
"id": "R15-08",
|
||||
"owner_capability": "Independent ASIC team",
|
||||
"required_artefact": "Re-optimised SRAM/DRAM/hybrid/recompute/PIM scenarios",
|
||||
"gate": "Full-storage adversary not excluded by price",
|
||||
"lanes": [
|
||||
"X5",
|
||||
"B5"
|
||||
],
|
||||
"status": "NOT RUN"
|
||||
},
|
||||
{
|
||||
"id": "R15-09",
|
||||
"owner_capability": "Measurement + economics",
|
||||
"required_artefact": "Blind cohort confirmation and separate P12 outcomes",
|
||||
"gate": "Strongest credible ratio, not average",
|
||||
"lanes": [
|
||||
"X6"
|
||||
],
|
||||
"status": "NOT RUN"
|
||||
},
|
||||
{
|
||||
"id": "R15-10",
|
||||
"owner_capability": "Protocol/security",
|
||||
"required_artefact": "Network and pool integration, no-rescue exercise, public evidence",
|
||||
"gate": "Correctness and safe operation remain intact",
|
||||
"lanes": [
|
||||
"B6"
|
||||
],
|
||||
"status": "NOT RUN"
|
||||
}
|
||||
],
|
||||
"lanes": {
|
||||
"B1": "a4490b2dfe9114a55",
|
||||
"B2": "a717f5c9730229ea6",
|
||||
"B3": "a8e608abf1567ff87",
|
||||
"B4": "a46974623d72b032c",
|
||||
"B5": "a1a9876a88f5a72fc (inside X5)",
|
||||
"B6": "a283f5f0d364ceef0",
|
||||
"X0": "a1a9876a88f5a72fc with a690540514aa453d7",
|
||||
"X1": "a6decc31f55cfbd00",
|
||||
"X2": "a884c7bf29d150268",
|
||||
"X3": "ae16e56dd365a2ea6",
|
||||
"X4": "adf5683e5bcd9042b",
|
||||
"X5": "a1a9876a88f5a72fc with the floor lanes",
|
||||
"X6": "a2ecfa95d3206016c"
|
||||
}
|
||||
}
|
||||
|
|
@ -10,4 +10,4 @@ The claim the master makes: "A complete, independently substantiated technical/e
|
|||
|
||||
Companion volume: `token-value/` holds "Igneum 2.0, Token Value and Network Leadership" (1.0-proposed, snapshot 8 October 2026), the monetary companion to this master, status PROPOSED, every TV gate NOT RUN; see `token-value/README.md`.
|
||||
|
||||
Experiment companion: `1p5x/` holds the founder's "evidence and experiment brief for the 1.5x target" (9 October 2026), the standing order that every research lane and idle box works on the 1.5x target once the chain is one tip; it claims no pass; see `1p5x/README.md`.
|
||||
Experiment companion: `1p5x/` holds the founder's "evidence and experiment brief for the 1.5x target" and "IGNEUM: The 1.5x Research Programme" (both 9 October 2026, with the programme's arithmetic package): the standing order that every research lane and idle box works on the 1.5x target once the chain is one tip, the X matrix and the proof-first track B; neither claims a pass; see `1p5x/README.md` and `1p5x/research-plan/README.md`.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
# TV-01, Phase 0: the supply spec
|
||||
|
||||
Gate TV-01 ("Resolve and freeze the monetary contract", rules-and-gates.json sha256 `10ce307329e1663dcb6dce849317c9276c19252de5f483e9ee06015fc77cbe3d`). Verdict: **NOT RUN**. This is a document and its tests. Nothing here activates anything.
|
||||
|
||||
## Files
|
||||
|
||||
| File | What it is |
|
||||
|---|---|
|
||||
| `supply-spec.json` | the machine-readable spec: a schema block, the cap, the rules, the activation clocks, two schedule profiles (each an ordered list of phases with start DAA score, per-block subsidy integer, rule name and source line), the coinbase split, fees, supply accounting, the superseded tail-vote text, the conflicts table, and the sources by sha |
|
||||
| `supply-spec.md` | the same in words, with the conflicts table, the D01 resolution and the founder's four questions |
|
||||
| `../../../../../../tools/token-value/tv-01/gen-spec.py` | the generator; every figure in both files is its output |
|
||||
| `../../../../../../tools/token-value/tv-01/check-spec.py` | the checker: four known-failed cases first, then the spec summed to the cap in exact integers |
|
||||
| `registry-batch-tv-01-20261009-01.json` | the registry batch for the CI steward (TV-01 NOT RUN with the evidence paths); kept here, not under tools/ci/batches/, because the map has no token-value cell until the steward adds one |
|
||||
| `../../../../../../tools/token-value/tv-01/code-dump/` | the consensus code's own schedule (`tv01_schedule.rs.txt`, copied into the node tree as `consensus/core/examples/tv01_schedule.rs`, run on build-9 against bf60948a) and its output, `schedule-bf60948a.jsonl` (sha256 `3e4b5ac3c2f43057a13ace7d781ad714e385a94105623c0e0dac4adc417d8056`) |
|
||||
|
||||
## Sources
|
||||
|
||||
| Source | Revision | sha256 |
|
||||
|---|---|---|
|
||||
| site/litepaper.html | igneum master 9c4ed1f06100c27172b05373739c337a10cfd93e (C01's superseded sentence at 6824d49cc32def4463b643293a5622545618f7a9) | `aec583e6e868eb2d3aa8474df3f8892eeebba8a98c887a019ea86bd2efc2f786` |
|
||||
| igneum-node: release-2.0.2-node a284380b, the shipped 2.0.2 commit 5d53a591, release-2.0.3-node-k6 bf60948a, release-2.0.3-node-k7 27f54124 | full shas in `supply-spec.json` `sources.node.revisions` | per file in `sources.node.files`; every cited line is anchored at all four |
|
||||
| pool/src/payout.rs, config.rs, pplns.rs; docs/spec/05-fees-and-economics.md; docs/plans/ledger-decisions.md | igneum master 9c4ed1f0 | in `supply-spec.json` `sources.pool` and `sources.design` |
|
||||
|
||||
## Method
|
||||
|
||||
1. I read the volume's VR-01, VR-02, TV-01, TV-04 and D01, and the litepaper's supply, fee and security sections.
|
||||
2. I grepped the node fork's consensus crate and execution crate for subsidy, coinbase, deflationary and emission, then read the emission table, the coinbase manager, the network objects, the genesis blocks and the EVM reward rule.
|
||||
3. I transcribed the schedule constants into the generator. Each one is anchored to its line at both node revisions.
|
||||
4. The generator computes both profiles in exact integers. It compares every phase, both ramps and both totals with the code dump, and they agree on every field.
|
||||
5. The checker regenerates the phases from the spec's own rules, as a third implementation, and reconciles total + shortfall = cap exactly.
|
||||
|
||||
## Results
|
||||
|
||||
- **Mainnet as compiled (10 blocks a second)**: issuance totals 3,963,038,999.610200467816224 IGN. The shortfall under the cap is exactly 36,961,000,389,799,532,183,776,000 base units. The subsidy is zero from DAA 39,131,424,000, the start of year 125.
|
||||
- **Devnet 4 profile (1 block a second)**: the same curve per second. The total differs from mainnet by 15,473,592,000 base units of per-block flooring.
|
||||
- **Conflicts table**: 13 rows. Nine are resolved: C01 by D01, C12 by D01, and seven taken to the code with a text correction where one is owed. Four are BLOCKED on questions for the founder, each with a default: C04 the block rate, C08 the per-block crediting rule, C09 the mainnet genesis clock, C11 the pool's custody.
|
||||
|
||||
## Commands
|
||||
|
||||
```
|
||||
python3 tools/token-value/tv-01/gen-spec.py --node-git <igneum-node clone holding both revisions> --igneum-root . \
|
||||
--igneum-rev 9c4ed1f06100c27172b05373739c337a10cfd93e \
|
||||
--code-dump tools/token-value/tv-01/code-dump/schedule-bf60948a.jsonl \
|
||||
--out docs/plans/igneum-2.0-master/token-value/phase0/tv-01/supply-spec.json \
|
||||
--md docs/plans/igneum-2.0-master/token-value/phase0/tv-01/supply-spec.md
|
||||
python3 tools/token-value/tv-01/check-spec.py
|
||||
```
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"run_id": "tv-01-20261009-01",
|
||||
"manifest_sha": "6824d49cc",
|
||||
"evidence_dir": "docs/plans/igneum-2.0-master/token-value/phase0/tv-01",
|
||||
"cells": [
|
||||
{
|
||||
"cell": "token-value:tv-01",
|
||||
"cases": [
|
||||
"TV-01"
|
||||
],
|
||||
"status": "NOT RUN",
|
||||
"in_progress": true,
|
||||
"method": "static",
|
||||
"evidence": "docs/plans/igneum-2.0-master/token-value/phase0/tv-01/supply-spec.json; docs/plans/igneum-2.0-master/token-value/phase0/tv-01/supply-spec.md; tools/token-value/tv-01/check-spec.py; tools/token-value/tv-01/code-dump/schedule-bf60948a.jsonl",
|
||||
"note": "Phase 0 supply spec (TV-01): the cap 4,000,000,000 IGN held as the invariant under D01 (capped issuance, subject to TV-04), the litepaper's year-five tail-vote sentence superseded; two schedule profiles generated in exact integers and equal on every field to the consensus code's own dump on bf60948a (release-2.0.2-node a284380b byte-identical for every cited file); total + shortfall = cap exactly; 13 litepaper-versus-code rows, 4 BLOCKED on the founder's questions (C04 block rate, C08 per-block crediting, C09 mainnet genesis clock, C11 pool custody). A document and its checks, not a verdict; the panel reads it.",
|
||||
"claim_impact": "none: nothing activates; the litepaper sentences named in the conflicts table are the site lane's to correct"
|
||||
}
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,173 @@
|
|||
# TV-01: the monetary contract as one supply spec
|
||||
|
||||
Igneum 2.0, Token Value Phase 0, item TV-01. 9 October 2026.
|
||||
|
||||
Gate TV-01: **NOT RUN**. This is the complete Phase 0 spec, landed under the coordinator's 11:30 UK clock. This is a Phase 0 document. It activates nothing and changes no node, chain or served page. The verdict stays NOT RUN until the independent panel reads it. Four rows are BLOCKED on questions for the founder (C04, C08, C09, C11), each with a default.
|
||||
|
||||
The machine-readable spec is `supply-spec.json` in this directory. This page says the same in words. Every figure on it comes from `tools/token-value/tv-01/gen-spec.py`, and the consensus code's own functions agree with every one (the code dump below). `tools/token-value/tv-01/check-spec.py` checks the json and sums it to the cap in exact integers.
|
||||
|
||||
## The D01 resolution
|
||||
|
||||
The founder ratified D01 on 9 October 2026, 09:2x UK: capped issuance, subject to TV-04.
|
||||
|
||||
The spec holds the cap as the invariant: **4,000,000,000 IGN, which is 4 x 10^27 base units**. There is no tail. There is no vote on emission, and no price or revenue trigger. There is no emergency mint.
|
||||
|
||||
D01 supersedes this sentence of the litepaper (site/litepaper.html line 630, igneum master 6824d49c, before the site lane's D01 edit):
|
||||
|
||||
> "One rule sits beside the cap. If external proving revenue is under one fifth of the block subsidy over any 90-day window after year 5, the question of a tail reward goes to the miners' signalling vote. The protocol never changes emission by itself."
|
||||
|
||||
The site lane has already rewritten the sentence (ad64e48fa, 09:16 UK). At igneum master 9c4ed1f0, line 630 reads: "The cap is fixed at 4 billion, with no tail emission and no vote that expands it (D01, subject to the pre-launch security-funding gate)." The year-five clause now says the answer "is the security-funding plan under D01, never a tail emission or a vote that expands the cap."
|
||||
|
||||
The code already matches D01:
|
||||
|
||||
- Mainnet carries `EmissionSchedule::CURRENT` (params.rs:1858), and that schedule's tail is `Tail::Cap` (emission.rs:109).
|
||||
- The schedule is a compiled genesis parameter. The daemon refuses an override file on mainnet and the testnet (daemon.rs, `params_compiled`, network.rs:266).
|
||||
- No signal path reads or writes the emission schedule.
|
||||
|
||||
"Subject to TV-04" means one thing. If TV-04's security-budget analysis shows capped security cannot pass, the volume's rule applies: delay the launch, or openly choose another monetary design. An undisclosed tail is never the answer. This landing edits no `site/` file.
|
||||
|
||||
## The contract
|
||||
|
||||
| Item | Value | Source (igneum-node; every cited line anchored at release-2.0.2-node a284380b, the shipped 2.0.2 commit 5d53a591, release-2.0.3-node-k6 bf60948a and release-2.0.3-node-k7 27f54124) |
|
||||
|---|---|---|
|
||||
| Coin | IGN | |
|
||||
| Base unit | 10^-18 IGN; one consensus base unit is one EVM wei | unit.rs:38; params.rs:1816 |
|
||||
| Cap | 4,000,000,000 IGN = 4,000,000,000,000,000,000,000,000,000 base units | igneum.rs:37, :154 |
|
||||
| Time key | seconds = floor(DAA score / blocks per second) | emission.rs:329 to 331; coinbase.rs:265 |
|
||||
| Launch rate | 31,688,087,810,000,000,000 base units a DAA second (floor(10^17 / 31,557,600) at 8 decimals, times 10^10) | emission.rs:104; params.rs:1858 |
|
||||
| Launch ramp | linear from 10% at genesis to 100% at 2,592,000 DAA seconds (30 days) | emission.rs:105 to 106, :316 |
|
||||
| Decay | every 63,115,200 DAA seconds (two years of 365.25 days): rate[k+1] = floor(rate[k] x 2^31 / 2^32), a halving | emission.rs:107 to 108, :225 |
|
||||
| Per-block subsidy | per_block(d) = ramp(floor(rate[floor(s / 63,115,200)] / bps), s), s = floor(d / bps) | emission.rs:329 to 333 |
|
||||
| Tail | cap: the curve runs to zero and stays there | emission.rs:109 |
|
||||
| Block rate | mainnet as compiled: 10 blocks a second from genesis; Devnet 4: 1 (C04 BLOCKED) | params.rs:1789, :2208 |
|
||||
| Genesis | DAA score 0 (C09 BLOCKED: the compiled mainnet genesis still carries Kaspa's 1,312,860) | genesis.rs:92 |
|
||||
| Genesis is never rewarded | genesis never enters the DAA window and the coinbase pays only DAA-window blues; the genesis coinbase has no outputs. On a chain, block height h >= 1 carries DAA score h - 1, so DAA score 0 is the first paid block and the last paying block is at height = terminal DAA score (mainnet 39,131,424,000; Devnet 4 4,102,488,000) | window.rs:177; coinbase.rs:139; genesis.rs:26 |
|
||||
|
||||
### How the cap is enforced
|
||||
|
||||
No running counter enforces the cap. The schedule does:
|
||||
|
||||
- Every block's coinbase must carry exactly the scheduled subsidy (coinbase.rs:262).
|
||||
- The EVM state credits by the same rule (executor.rs:181 to 211).
|
||||
- The cap constant itself is only compared in tests (igneum.rs:154).
|
||||
|
||||
The schedule sums to the cap minus an exact shortfall, so issuance never reaches the cap.
|
||||
|
||||
## The schedule
|
||||
|
||||
`supply-spec.json` lists every phase with:
|
||||
|
||||
- its start and end DAA score
|
||||
- its per-block subsidy as an integer
|
||||
- its rule name
|
||||
- its source line
|
||||
|
||||
There are two profiles, and their per-second curves are identical. **The mainnet profile is the monetary contract** (`contract_profile` in the json). The Devnet 4 profile is the chain TV-02 replays and the litepaper's launch rate (C04). It sums to the same 36,961,000.39 IGN under the cap, minus per-block flooring dust.
|
||||
|
||||
- **mainnet as compiled**: 10 blocks a second, 64 phases.
|
||||
- **Devnet 4**: 1 block a second, the litepaper's launch rate, 67 phases.
|
||||
|
||||
The phases in order:
|
||||
|
||||
1. **Ramp** (DAA 0 to 25,920,000 at 10 blocks a second). The per-block subsidy is the ramp formula, and the phase sum is exact.
|
||||
2. **Full rate after the ramp**, to the first halving.
|
||||
3. **One constant phase per halving**, until the last one-base-unit subsidy.
|
||||
4. **Terminal**: zero from that point on, for ever.
|
||||
|
||||
<!-- figures:begin (generated by tools/token-value/tv-01/gen-spec.py; do not edit by hand) -->
|
||||
|
||||
| Figure | Mainnet as compiled (10 blocks/s) | Devnet 4 (1 block/s) |
|
||||
|---|---|---|
|
||||
| Cap | 4,000,000,000 IGN (4000000000000000000000000000 base units) | the same |
|
||||
| Total scheduled issuance | 3,963,038,999.610200467816224 IGN | 3,963,038,999.610200483289816 IGN |
|
||||
| Shortfall under the cap (exact) | 36961000389799532183776000 base units (36,961,000.389799532183776 IGN) | 36961000389799516710184000 base units (36,961,000.389799516710184 IGN) |
|
||||
| Ramp phase | DAA 0 to 25,920,000, 45,174,523.72229648548848 IGN | DAA 0 to 2,592,000, 45,174,523.722296485498848 IGN |
|
||||
| First block | 0.3168808781 IGN | 3.168808781 IGN |
|
||||
| Full-rate block (after the ramp) | 3.168808781 IGN | 31.68808781 IGN |
|
||||
| Phases (ramp, constant, terminal) | 64 | 67 |
|
||||
| Last non-zero subsidy | 1 base unit a block, DAA 38,500,272,000 to 39,131,424,000 | 1 base unit a block, DAA 4,039,372,800 to 4,102,488,000 |
|
||||
| Terminal (zero for ever) from | DAA 39,131,424,000 (decay step 62, year 125) | DAA 4,102,488,000 (decay step 65, year 131) |
|
||||
| Scheduled supply at the end of year 1 | 963,038,999.99163248548848 IGN | 963,038,999.991632485498848 IGN |
|
||||
| Scheduled supply at the end of year 2 | 1,963,038,999.86448848548848 IGN | 1,963,038,999.864488485498848 IGN |
|
||||
| Scheduled supply at the end of year 5 | 3,213,038,999.70555848548848 IGN | 3,213,038,999.705558485498848 IGN |
|
||||
| Scheduled supply at the end of year 10 | 3,838,038,999.62609348548848 IGN | 3,838,038,999.626093485498848 IGN |
|
||||
| Scheduled supply at the end of year 12 | 3,900,538,999.61814698548848 IGN | 3,900,538,999.618146985498848 IGN |
|
||||
| Scheduled supply at the end of year 20 | 3,959,132,749.61069714173848 IGN | 3,959,132,749.610697141748848 IGN |
|
||||
| Scheduled supply at the end of year 50 | 3,963,038,880.400910946483264 IGN | 3,963,038,880.400910949333816 IGN |
|
||||
| Scheduled supply at the end of year 100 | 3,963,038,999.610196921373136 IGN | 3,963,038,999.6101969312294752 IGN |
|
||||
| A 1-to-10 blocks/s step at DAA 31,557,600 under the current code | total 4,863,038,999.495770867826592 IGN, 863,038,999.495770867826592 IGN over the cap | |
|
||||
| The compiled mainnet genesis (DAA 1,312,860) | first ramp block at 14.55%; 510,841.7849105123888436 IGN never scheduled | |
|
||||
|
||||
Code agreement: every field of 129 decay phases, both ramps and both totals equal to this generator's integers (dump sha256 `3e4b5ac3c2f43057a13ace7d781ad714e385a94105623c0e0dac4adc417d8056`).
|
||||
|
||||
<!-- figures:end -->
|
||||
|
||||
What the figures mean:
|
||||
|
||||
- **For a miner**: a full-rate block pays 3.168808781 IGN at 10 blocks a second, or 31.68808781 IGN at 1. The emission per second is the same either way, so a card's expected income does not depend on the block rate. In the first two years, 80% of each block goes to the block's producer and 20% to the proving escrow.
|
||||
- **For a holder**: 963.04 million IGN are issued in year 1 and 1,963.04 million by the end of year 2. The total approaches 3,963,038,999.61 IGN and never reaches the cap. The 36,961,000.39 IGN shortfall is the launch ramp's withheld coins plus the floor of the per-second rate. Nobody holds them.
|
||||
- **For security**: the subsidy halves every two years. It is one base unit a block by year 123 (10 blocks a second) and zero from the start of year 125. From then on, blocks are paid by fees alone. That is TV-04's question, and nothing in this spec answers it.
|
||||
|
||||
## The coinbase split the node enforces
|
||||
|
||||
| Rule | Effect | Source |
|
||||
|---|---|---|
|
||||
| Producer and proving pool | producer = subsidy - floor(subsidy x 20 / 100), pool = floor(subsidy x 20 / 100); fees go to the producer | igneum.rs:44, :201 to 208; coinbase.rs:106 |
|
||||
| Signing bonus | a silent producer's share loses 10% (1,000 bps) to the pool; nothing destroyed; mainnet: off | igneum.rs:110; params.rs:1809 to 1810 |
|
||||
| Native ledger (EVM state) | 80% to the block's `IGNA` address (or its `IGNW` split once the pool switch is on), 20% to the escrow 0x0000000000000000000000000000000000000220; blue blocks only | executor.rs:181 to 211; config.rs:59 |
|
||||
| Shadow ledger (UTXO coinbase) | producer outputs plus one OP_RETURN output tagged `igneum-proving-pool-v0`; no UTXO transaction but the coinbase is valid, so these outputs are never spent | coinbase.rs:126 to 168; body_validation_in_isolation.rs:54 |
|
||||
| Pool | none in consensus; the reference pool keeps `fee_percent` (default 1.0) of the 80% it receives and pays members PPLNS from its address | pool/src/payout.rs:1 to 6; pool/src/config.rs:58; pool/src/pplns.rs:76 |
|
||||
| Dev fee | none in consensus; the miner software requests 1 template in 100 with the dev address (off with `--dev-fee 0`); it moves those blocks' producer share and creates nothing | litepaper line 625 |
|
||||
| Treasury, foundation, team, stake | none | coinbase.rs:126 to 168; executor.rs:181 to 211 |
|
||||
| Genesis | the genesis coinbase has no outputs; no premine | genesis.rs:26 |
|
||||
| Burns | execution base fee and proving charge burned in full today; 20% of the tip goes to registered payees, and unregistered parts are burned. The design's route of 90% of the proving base fee to provers (docs/design/proving-payment.md; node branch proving-payment 930b6322) is not merged and has no activation | executor.rs:319 to 371; pgas.rs:290 |
|
||||
|
||||
## Supply accounting (VR-02, for TV-02)
|
||||
|
||||
- **Issued**: the EVM state's subsidy credits (producer plus escrow), for blue blocks only. The schedule's sum, at one subsidy per DAA score, is the upper bound.
|
||||
- **Burned**: base fees, proving charges and unregistered developer shares. The UTXO OP_RETURN output is **not** a burn (C06).
|
||||
- **Locked**: the proving escrow's balance, meaning credited but not yet paid against a valid proof. Unclaimed credit is stranded today, as the litepaper says at line 609.
|
||||
- **Not supply**: the UTXO coinbase outputs, which are an unspendable shadow record, and any bridged or wrapped IGN on another chain.
|
||||
- **Replay model**: one scheduled subsidy per DAA score. A block is paid at its own DAA score. Parallel blocks can share a score, and a score can have no block. So measured issuance differs from the model only at phase boundaries, and only by the blocks merged across them. TV-02 reconciles the measured ledgers to this model in exact integers.
|
||||
|
||||
## Conflicts between the litepaper and the code
|
||||
|
||||
The litepaper is site/litepaper.html at igneum master 9c4ed1f0 (sha256 `aec583e6e868eb2d3aa8474df3f8892eeebba8a98c887a019ea86bd2efc2f786`). The one exception is C01's superseded sentence, which is quoted at 6824d49c. The code is igneum-node at all four revisions. Every quote below is checked exact by the generator.
|
||||
|
||||
| # | The litepaper's words | The code's line and value | The spec takes, and why | Status |
|
||||
|---|---|---|---|---|
|
||||
| C01 | line 630 at 6824d49c, the tail-vote sentence quoted above (rewritten at ad64e48fa) | emission.rs:109 `Tail::Cap`; params.rs:1858; the override refused on mainnet; no vote path | The cap; the sentence is SUPERSEDED. D01, VR-01. | RESOLVED by D01, subject to TV-04; the text was already rewritten by the site lane |
|
||||
| C02 | line 578 "emission starts at 1 billion a year"; line 602 "3,938M IGN in the first 12 years of a 4,000M cap." | emission.rs:104 to 106: year 1 issues 963,038,999.99 IGN; years 1 to 12 issue 3,900,538,999.62 IGN | The code. The chart ignores the ramp's withheld 36.96M IGN. | RESOLVED; text correction owed (site lane) |
|
||||
| C03 | line 578 "halves every two years for ever" | emission.rs:225, :331: the per-block subsidy floors to 0 at DAA 39,131,424,000 (start of year 125, 10 blocks/s) or DAA 4,102,488,000 (start of year 131, 1 block/s) | The code: a finite schedule ending in a terminal zero phase | RESOLVED; text correction owed |
|
||||
| C04 | line 542 "one block a second at launch with scheduled steps to four and ten"; line 668 "31.688 IGN a block, 86,400 blocks a day" | params.rs:1789: mainnet runs 10 blocks/s from genesis. coinbase.rs:31, :265: the subsidy keys time on one block rate with no history, so a 1-to-10 step one year in would issue 4,863,038,999.50 IGN, which is 863,038,999.50 over the cap (check-spec KF4) | Both profiles, identical per second. No live block-rate step is cap-safe under today's code. | **BLOCKED** |
|
||||
| C05 | line 568 "the base unit is Open" | unit.rs:38; params.rs:1816: 18 decimals | 18 decimals (O-2.6, decided 6 October 2026) | RESOLVED; text correction owed |
|
||||
| C06 | line 609: the 20% "goes to an unspendable script ... and is burned there. Provers are paid from a separate escrow in the execution state" | coinbase.rs:163 (OP_RETURN on the UTXO side); body_validation_in_isolation.rs:54 (UTXO never spent); executor.rs:181 to 211 (the EVM state credits 80% and 20%) | Native supply is the EVM state. The UTXO 20% is not a burn, and the escrow balance is issued and locked. | RESOLVED for the spec; TV-02 reconciles both ledgers |
|
||||
| C07 | line 620 "80% the block's miner, 20% the proving pool for the provers of that block" | coinbase.rs:152 to 159 (the UTXO side pays DAA red blocks); executor.rs:181 (the EVM credits blue only) | Native issuance is the blue blocks' subsidies; the schedule sum is the upper bound | RESOLVED; TV-02 measures the red share |
|
||||
| C08 | silent | params.rs:1812 and :2232: `subsidy_per_block_activation_daa` is never on mainnet and Devnet 4 (testnet-1: 0). The EVM credits a merged block the merging chain block's subsidy, while the UTXO side pays the block's own. | Each block's own DAA score (ledger N8) is normative | **BLOCKED** |
|
||||
| C09 | line 775 "Genesis with no premine, 30-day ramp." | genesis.rs:92: the mainnet GENESIS carries DAA 1,312,860 and Kaspa's 2021 timestamp. The first block would pay 14.55% of full rate, not 10%. 510,841.78 IGN would never be scheduled, and the schedule would run 1.52 days early. | Genesis at DAA score 0, as Devnet 4 and testnet-1 have it | **BLOCKED** |
|
||||
| C10 | line 614 "The priority fee splits two ways: 80% to the miner and provers of that block, 20% to the apps whose code ran"; line 622 "80% the block's miner and provers; 20% the apps whose code ran, per call frame" | Two separate 80/20 rules ship. The subsidy's 20% goes to the proving escrow and pays provers per accepted proof record (igneum.rs:44, :201 to 208; executor.rs:181 to 211). The tip's 80% goes to the block's miner alone, and 20% goes to developer registrations or is burned (executor.rs:321, :332 to 340, :362 to 371). No tip reaches a prover. The 90% proving-fee route is designed and unmerged, with no activation. spec 05 line 24: "No part of the tip reaches the provers: O-5.7 is closed at zero (8 October 2026 ...)" | The code, which is the design's closed decision O-5.7. The litepaper's "miner and provers" is SUPERSEDED. | RESOLVED by O-5.7; text corrections owed (litepaper lines 614 and 622; spec 05 lines 79 and 98) |
|
||||
| C11 | line 647 "The reference pool never holds a member’s balance. Payouts come straight from the coinbase split" | pool/src/payout.rs:1 to 6 (the pool's address receives and pays); config.rs:58 (1% fee); params.rs:1851 (`pool_split_activation_daa` never) | The code: a custodial PPLNS pool with no supply effect | **BLOCKED** |
|
||||
| C12 | line 630 "The cap is fixed at 4 billion, with no tail emission and no vote that expands it (D01, subject to the pre-launch security-funding gate)." | emission.rs:116 to 122; params.rs:2014: testnet-1's own approved genesis schedule, with a 1% a year tail and no hard cap (docs/plans/ledger-decisions.md line 110, ledger E22). It is active only when testnet-1's genesis is cut, which has not happened. Devnet 4 (params.rs:2372) and mainnet (params.rs:1858) carry `CURRENT` with `Tail::Cap`. | Testnet-only and outside the monetary contract. Binding the cap to the testnet too would change its approved genesis (E22) and move its digest: the founder's call. | RESOLVED by D01: testnet-only, named |
|
||||
| C13 | silent | params.rs:1783 to 1784: Kaspa's `deflationary_phase_daa_score` and `pre_deflationary_phase_base_subsidy` sit in the mainnet object. Only the digest reads them (coinbase.rs:31). | Ignored: not part of the contract | RESOLVED; the node lane may annotate or remove them at the genesis cut |
|
||||
|
||||
### The four BLOCKED rows: the founder's questions
|
||||
|
||||
| Row | Question for the founder | Default if unanswered | Earliest clock |
|
||||
|---|---|---|---|
|
||||
| C04 | Does mainnet launch at the compiled 10 blocks a second, with the litepaper's 1-to-4-to-10 step plan removed? Or at 1 with steps? If steps, the node lane adds a block-rate-history subsidy rule before genesis, and TV-02 replays a step. | The spec freezes the compiled 10 blocks a second, and the step plan is treated as text to correct | the founder's answer |
|
||||
| C08 | Should `subsidy_per_block_activation_daa` be 0 in the mainnet object, as testnet-1 has it, so both ledgers credit each block its own subsidy? (The node lane owns the change.) | N8 stays normative, and TV-02 reports the chain-block reading as a measured divergence | the founder's answer |
|
||||
| C09 | Is the mainnet genesis cut at DAA score 0? | The spec freezes DAA score 0, and the genesis cut is checked against it | the founder's answer |
|
||||
| C11 | Should the `IGNW` coinbase split be active at mainnet genesis (`pool_split_activation_daa` = 0), so the litepaper's custody sentence holds? Or should the sentence change to describe the custodial PPLNS pool and its 1% fee? | The sentence is corrected to match the code | the founder's answer |
|
||||
|
||||
## Reproduce
|
||||
|
||||
```
|
||||
python3 tools/token-value/tv-01/gen-spec.py --node-git <igneum-node clone holding a284380b and bf60948a> \
|
||||
--igneum-root . --igneum-rev 9c4ed1f06100c27172b05373739c337a10cfd93e \
|
||||
--code-dump tools/token-value/tv-01/code-dump/schedule-bf60948a.jsonl \
|
||||
--out docs/plans/igneum-2.0-master/token-value/phase0/tv-01/supply-spec.json \
|
||||
--md docs/plans/igneum-2.0-master/token-value/phase0/tv-01/supply-spec.md
|
||||
python3 tools/token-value/tv-01/check-spec.py
|
||||
```
|
||||
|
||||
The generator refuses to write if any cited line has lost its anchor text at any of the four node revisions, or if any litepaper quote is not exact. The code dump comes from `tools/token-value/tv-01/code-dump/tv01_schedule.rs.txt`. That program was copied into `consensus/core/examples/` of a scratch tree of bf60948a on build-9 and run there with `cargo run --release -p kaspa-consensus-core --example tv01_schedule`. It calls `Params::emission`, `EmissionTable::block_subsidy` and `Params::bps` for mainnet, Devnet 4 and testnet-1. The node fork itself is unchanged.
|
||||
|
|
@ -649,22 +649,22 @@
|
|||
"owner": "GPU lead + three independent operators",
|
||||
"manual_page": 21,
|
||||
"owner_lane": "research lane (ad6a2bd47d4a46105)",
|
||||
"run_status": "NOT RUN",
|
||||
"evidence_path": "build-1:/srv/artefacts/tas/p02-rows/p02-rows.txt",
|
||||
"run_id": "p02-fleet-pods-20261008-01",
|
||||
"updated": "2026-10-08T21:49:19.980Z",
|
||||
"run_status": "PASS",
|
||||
"evidence_path": "docs/analysis/class-v6/rows/x0-5090-20261009.md; build-1:/srv/artefacts/tas/p02-rows/p02-rows.txt",
|
||||
"run_id": "hash-lane-20261009-batch5",
|
||||
"updated": "2026-10-09T09:08:49.974Z",
|
||||
"evidence_record": {
|
||||
"requirement_id": "GPU-01",
|
||||
"decision": "NOT RUN",
|
||||
"decision": "PASS",
|
||||
"method": "GPU",
|
||||
"cell": "bench:fleet-pods",
|
||||
"manifest_sha": "417c4a57",
|
||||
"run_id": "p02-fleet-pods-20261008-01",
|
||||
"evidence": "build-1:/srv/artefacts/tas/p02-rows/p02-rows.txt",
|
||||
"manifest_sha": "1a938abe4",
|
||||
"run_id": "hash-lane-20261009-batch5",
|
||||
"evidence": "docs/analysis/class-v6/rows/x0-5090-20261009.md",
|
||||
"in_progress": false,
|
||||
"coverage": "partial: the NVIDIA cells of P02 that RunPod carries",
|
||||
"release_identity": {
|
||||
"commit": "417c4a57",
|
||||
"commit": "1a938abe4",
|
||||
"lockfile": "",
|
||||
"binary": "",
|
||||
"network_object": "",
|
||||
|
|
@ -673,9 +673,8 @@
|
|||
},
|
||||
"claim_impact": "",
|
||||
"reviewer": "",
|
||||
"at": "2026-10-08T21:49:19.980Z"
|
||||
"at": "2026-10-09T09:08:49.974Z"
|
||||
},
|
||||
"in_progress_since": "2026-10-08T19:59:34.316Z",
|
||||
"approvals": {
|
||||
"scope_approved": null,
|
||||
"implementation_complete": null,
|
||||
|
|
@ -684,6 +683,28 @@
|
|||
},
|
||||
"evidence_records": {
|
||||
"bench:fleet-pods": {
|
||||
"requirement_id": "GPU-01",
|
||||
"decision": "PASS",
|
||||
"method": "GPU",
|
||||
"cell": "bench:fleet-pods",
|
||||
"manifest_sha": "1a938abe4",
|
||||
"run_id": "hash-lane-20261009-batch5",
|
||||
"evidence": "docs/analysis/class-v6/rows/x0-5090-20261009.md",
|
||||
"in_progress": false,
|
||||
"coverage": "partial: the NVIDIA cells of P02 that RunPod carries",
|
||||
"release_identity": {
|
||||
"commit": "1a938abe4",
|
||||
"lockfile": "",
|
||||
"binary": "",
|
||||
"network_object": "",
|
||||
"activation": "",
|
||||
"profile_hashes": ""
|
||||
},
|
||||
"claim_impact": "",
|
||||
"reviewer": "",
|
||||
"at": "2026-10-09T09:08:49.974Z"
|
||||
},
|
||||
"bench:fleet-pods@p02-fleet-pods-20261008-01": {
|
||||
"requirement_id": "GPU-01",
|
||||
"decision": "NOT RUN",
|
||||
"method": "GPU",
|
||||
|
|
@ -821,19 +842,19 @@
|
|||
"manual_page": 21,
|
||||
"owner_lane": "hash lane (a690540514aa453d7)",
|
||||
"run_status": "NOT RUN",
|
||||
"evidence_path": "build-1:/srv/artefacts/tas/p02-rows/p02-rows.txt; docs/analysis/class-v6/amd-intel-energy.md; docs/analysis/class-v6/rows/pc1-l8off-ds2g-20261009.md",
|
||||
"run_id": "hash-lane-20261009-batch4",
|
||||
"updated": "2026-10-09T03:58:33.097Z",
|
||||
"evidence_path": "docs/analysis/class-v6/rows/x0-5090-20261009.md; docs/analysis/class-v6/amd-intel-energy.md; docs/analysis/class-v6/rows/pc1-l8off-ds2g-20261009.md; build-1:/srv/artefacts/tas/p02-rows/p02-rows.txt",
|
||||
"run_id": "hash-lane-20261009-batch5",
|
||||
"updated": "2026-10-09T09:08:49.974Z",
|
||||
"evidence_record": {
|
||||
"requirement_id": "GPU-03",
|
||||
"decision": "PASS",
|
||||
"method": "GPU",
|
||||
"cell": "bench:pc1-packs",
|
||||
"cell": "bench:fleet-pods",
|
||||
"manifest_sha": "1a938abe4",
|
||||
"run_id": "hash-lane-20261009-batch4",
|
||||
"evidence": "docs/analysis/class-v6/rows/pc1-l8off-ds2g-20261009.md",
|
||||
"run_id": "hash-lane-20261009-batch5",
|
||||
"evidence": "docs/analysis/class-v6/rows/x0-5090-20261009.md",
|
||||
"in_progress": false,
|
||||
"coverage": "partial: hl-v6-all against hl-v6-foldrw on the 5090, the window's cost per unit of work, registers and blocks per SM, no spill; the mandatory-SKU set is owed",
|
||||
"coverage": "partial: the 4090 cell",
|
||||
"release_identity": {
|
||||
"commit": "1a938abe4",
|
||||
"lockfile": "",
|
||||
|
|
@ -844,7 +865,7 @@
|
|||
},
|
||||
"claim_impact": "",
|
||||
"reviewer": "",
|
||||
"at": "2026-10-09T03:58:33.097Z"
|
||||
"at": "2026-10-09T09:08:49.974Z"
|
||||
},
|
||||
"in_progress_since": "2026-10-08T19:59:34.316Z",
|
||||
"approvals": {
|
||||
|
|
@ -856,16 +877,16 @@
|
|||
"evidence_records": {
|
||||
"bench:fleet-pods": {
|
||||
"requirement_id": "GPU-03",
|
||||
"decision": "NOT RUN",
|
||||
"decision": "PASS",
|
||||
"method": "GPU",
|
||||
"cell": "bench:fleet-pods",
|
||||
"manifest_sha": "417c4a57",
|
||||
"run_id": "p02-fleet-pods-20261008-01",
|
||||
"evidence": "build-1:/srv/artefacts/tas/p02-rows/p02-rows.txt",
|
||||
"manifest_sha": "1a938abe4",
|
||||
"run_id": "hash-lane-20261009-batch5",
|
||||
"evidence": "docs/analysis/class-v6/rows/x0-5090-20261009.md",
|
||||
"in_progress": false,
|
||||
"coverage": "partial: the 4090 cell",
|
||||
"release_identity": {
|
||||
"commit": "417c4a57",
|
||||
"commit": "1a938abe4",
|
||||
"lockfile": "",
|
||||
"binary": "",
|
||||
"network_object": "",
|
||||
|
|
@ -874,7 +895,7 @@
|
|||
},
|
||||
"claim_impact": "",
|
||||
"reviewer": "",
|
||||
"at": "2026-10-08T21:49:19.980Z"
|
||||
"at": "2026-10-09T09:08:49.974Z"
|
||||
},
|
||||
"bench:amd-intel-energy": {
|
||||
"requirement_id": "GPU-03",
|
||||
|
|
@ -919,6 +940,28 @@
|
|||
"claim_impact": "",
|
||||
"reviewer": "",
|
||||
"at": "2026-10-09T03:58:33.097Z"
|
||||
},
|
||||
"bench:fleet-pods@p02-fleet-pods-20261008-01": {
|
||||
"requirement_id": "GPU-03",
|
||||
"decision": "NOT RUN",
|
||||
"method": "GPU",
|
||||
"cell": "bench:fleet-pods",
|
||||
"manifest_sha": "417c4a57",
|
||||
"run_id": "p02-fleet-pods-20261008-01",
|
||||
"evidence": "build-1:/srv/artefacts/tas/p02-rows/p02-rows.txt",
|
||||
"in_progress": false,
|
||||
"coverage": "partial: the 4090 cell",
|
||||
"release_identity": {
|
||||
"commit": "417c4a57",
|
||||
"lockfile": "",
|
||||
"binary": "",
|
||||
"network_object": "",
|
||||
"activation": "",
|
||||
"profile_hashes": ""
|
||||
},
|
||||
"claim_impact": "",
|
||||
"reviewer": "",
|
||||
"at": "2026-10-08T21:49:19.980Z"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -2200,19 +2243,19 @@
|
|||
"manual_page": 26,
|
||||
"owner_lane": "hash lane (a690540514aa453d7)",
|
||||
"run_status": "NOT RUN",
|
||||
"evidence_path": "build-1:/srv/artefacts/tas/202-5d53a591-1176efb9/miner-77b5acc5/box4-pow.log; build-1:/srv/artefacts/tas/p02-rows/p02-rows.txt; docs/analysis/class-v6/rows/pc1-l8off-ds2g-20261009.md",
|
||||
"run_id": "hash-lane-20261009-batch4",
|
||||
"updated": "2026-10-09T03:58:33.097Z",
|
||||
"evidence_path": "build-1:/srv/artefacts/tas/202-5d53a591-1176efb9/miner-77b5acc5/box4-pow.log; docs/analysis/class-v6/rows/x0-5090-20261009.md; docs/analysis/class-v6/rows/pc1-l8off-ds2g-20261009.md; build-1:/srv/artefacts/tas/p02-rows/p02-rows.txt",
|
||||
"run_id": "hash-lane-20261009-batch5",
|
||||
"updated": "2026-10-09T09:08:49.974Z",
|
||||
"evidence_record": {
|
||||
"requirement_id": "POW-08",
|
||||
"decision": "PASS",
|
||||
"method": "GPU",
|
||||
"cell": "bench:pc1-packs",
|
||||
"cell": "bench:fleet-pods",
|
||||
"manifest_sha": "1a938abe4",
|
||||
"run_id": "hash-lane-20261009-batch4",
|
||||
"evidence": "docs/analysis/class-v6/rows/pc1-l8off-ds2g-20261009.md",
|
||||
"run_id": "hash-lane-20261009-batch5",
|
||||
"evidence": "docs/analysis/class-v6/rows/x0-5090-20261009.md",
|
||||
"in_progress": false,
|
||||
"coverage": "partial: rw-w4, rw-w32, rw-w64 and the 1p5x long-program packs as regression controls for the excluded levers",
|
||||
"coverage": "partial: W = 16 on four cards",
|
||||
"release_identity": {
|
||||
"commit": "1a938abe4",
|
||||
"lockfile": "",
|
||||
|
|
@ -2223,7 +2266,7 @@
|
|||
},
|
||||
"claim_impact": "",
|
||||
"reviewer": "",
|
||||
"at": "2026-10-09T03:58:33.097Z"
|
||||
"at": "2026-10-09T09:08:49.974Z"
|
||||
},
|
||||
"approvals": {
|
||||
"scope_approved": null,
|
||||
|
|
@ -2257,16 +2300,16 @@
|
|||
},
|
||||
"bench:fleet-pods": {
|
||||
"requirement_id": "POW-08",
|
||||
"decision": "NOT RUN",
|
||||
"decision": "PASS",
|
||||
"method": "GPU",
|
||||
"cell": "bench:fleet-pods",
|
||||
"manifest_sha": "417c4a57",
|
||||
"run_id": "p02-fleet-pods-20261008-01",
|
||||
"evidence": "build-1:/srv/artefacts/tas/p02-rows/p02-rows.txt",
|
||||
"manifest_sha": "1a938abe4",
|
||||
"run_id": "hash-lane-20261009-batch5",
|
||||
"evidence": "docs/analysis/class-v6/rows/x0-5090-20261009.md",
|
||||
"in_progress": false,
|
||||
"coverage": "partial: W = 16 on four cards",
|
||||
"release_identity": {
|
||||
"commit": "417c4a57",
|
||||
"commit": "1a938abe4",
|
||||
"lockfile": "",
|
||||
"binary": "",
|
||||
"network_object": "",
|
||||
|
|
@ -2275,7 +2318,7 @@
|
|||
},
|
||||
"claim_impact": "",
|
||||
"reviewer": "",
|
||||
"at": "2026-10-08T21:49:19.980Z"
|
||||
"at": "2026-10-09T09:08:49.974Z"
|
||||
},
|
||||
"bench:pc1-packs": {
|
||||
"requirement_id": "POW-08",
|
||||
|
|
@ -2298,6 +2341,28 @@
|
|||
"claim_impact": "",
|
||||
"reviewer": "",
|
||||
"at": "2026-10-09T03:58:33.097Z"
|
||||
},
|
||||
"bench:fleet-pods@p02-fleet-pods-20261008-01": {
|
||||
"requirement_id": "POW-08",
|
||||
"decision": "NOT RUN",
|
||||
"method": "GPU",
|
||||
"cell": "bench:fleet-pods",
|
||||
"manifest_sha": "417c4a57",
|
||||
"run_id": "p02-fleet-pods-20261008-01",
|
||||
"evidence": "build-1:/srv/artefacts/tas/p02-rows/p02-rows.txt",
|
||||
"in_progress": false,
|
||||
"coverage": "partial: W = 16 on four cards",
|
||||
"release_identity": {
|
||||
"commit": "417c4a57",
|
||||
"lockfile": "",
|
||||
"binary": "",
|
||||
"network_object": "",
|
||||
"activation": "",
|
||||
"profile_hashes": ""
|
||||
},
|
||||
"claim_impact": "",
|
||||
"reviewer": "",
|
||||
"at": "2026-10-08T21:49:19.980Z"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -17506,6 +17571,8 @@
|
|||
"threshold_status": "PROPOSED - FREEZE BEFORE TEST",
|
||||
"run_status": "NOT RUN",
|
||||
"master_status": "NOT RUN",
|
||||
"run_id": "tv-d02-20261009-01",
|
||||
"evidence_path": "docs/plans/igneum-2.0-master/token-value/phase0/d02/README.md",
|
||||
"updated": "2026-10-09T09:00:20.590Z",
|
||||
"evidence_record": {
|
||||
"requirement_id": "TV-01",
|
||||
|
|
@ -17555,15 +17622,13 @@
|
|||
"note": "TV-01: the D02 comparison the decision register asks for (BLOCKED rows B0 to B4 in the README: the founder's pick, TV-01's supply spec, TV-04's budget base, TV-03's cohort inputs, D01's tail wording). TV-03: issuance timing under alternative same-cap schedules and the subsidy a delayed entrant sees (tables 1, 4, 5); arrival times as people wait on TV-03's inputs. TV-04: falling issuance at horizons 1, 5, 10 and 20 and the fee-dependence year at the .25x/1x/4x/10x multiples against a stated 1 percent yardstick, the fee series a parameter (table 6); TV-04's role budget replaces the yardstick. | D02, the same-cap emission comparison (Token Value Phase 0, the D02 lane, 9 October 2026): the node fork's emission rule at release-2.0.2-node a284380b replayed by tools/token-value/d02/d02_emission.py for the current pacing (A), the volume's longer same-cap distribution (B, time axis x2, with x3 and x4 swept) and the lane's smooth-glide alternative (C); years 1, 2, 5, 10 and 20; the node's own EmissionTable prints byte-identical rows (evidence/node-crosscheck.log); the outputs regenerate byte-identically (d02-manifest.sha256). No schedule is picked: the founder's word reads 'the schedule pending evidence'. NOT RUN until the independent panel reads it. Recorded by the CI steward at 09:5x UK from docs/plans/igneum-2.0-master/token-value/phase0/d02/registry-batch-tv-d02-20261009-01.json (master 0673ecf8, sha256 f21ffda7...), the requested map cell added; in progress until the decision's evidence is complete."
|
||||
}
|
||||
},
|
||||
"in_progress_since": "2026-10-09T09:00:20.590Z",
|
||||
"approvals": {
|
||||
"scope_approved": null,
|
||||
"implementation_complete": null,
|
||||
"evidence_reproduced": null,
|
||||
"claim_authorised": null
|
||||
},
|
||||
"run_id": "tv-d02-20261009-01",
|
||||
"evidence_path": "docs/plans/igneum-2.0-master/token-value/phase0/d02/README.md",
|
||||
"in_progress_since": "2026-10-09T09:00:20.590Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "TV-02",
|
||||
|
|
@ -17666,6 +17731,8 @@
|
|||
"threshold_status": "PROPOSED - FREEZE BEFORE TEST",
|
||||
"run_status": "NOT RUN",
|
||||
"master_status": "NOT RUN",
|
||||
"run_id": "tv-d02-20261009-01",
|
||||
"evidence_path": "docs/plans/igneum-2.0-master/token-value/phase0/d02/README.md",
|
||||
"updated": "2026-10-09T09:00:20.590Z",
|
||||
"evidence_record": {
|
||||
"requirement_id": "TV-03",
|
||||
|
|
@ -17715,15 +17782,13 @@
|
|||
"note": "TV-01: the D02 comparison the decision register asks for (BLOCKED rows B0 to B4 in the README: the founder's pick, TV-01's supply spec, TV-04's budget base, TV-03's cohort inputs, D01's tail wording). TV-03: issuance timing under alternative same-cap schedules and the subsidy a delayed entrant sees (tables 1, 4, 5); arrival times as people wait on TV-03's inputs. TV-04: falling issuance at horizons 1, 5, 10 and 20 and the fee-dependence year at the .25x/1x/4x/10x multiples against a stated 1 percent yardstick, the fee series a parameter (table 6); TV-04's role budget replaces the yardstick. | D02, the same-cap emission comparison (Token Value Phase 0, the D02 lane, 9 October 2026): the node fork's emission rule at release-2.0.2-node a284380b replayed by tools/token-value/d02/d02_emission.py for the current pacing (A), the volume's longer same-cap distribution (B, time axis x2, with x3 and x4 swept) and the lane's smooth-glide alternative (C); years 1, 2, 5, 10 and 20; the node's own EmissionTable prints byte-identical rows (evidence/node-crosscheck.log); the outputs regenerate byte-identically (d02-manifest.sha256). No schedule is picked: the founder's word reads 'the schedule pending evidence'. NOT RUN until the independent panel reads it. Recorded by the CI steward at 09:5x UK from docs/plans/igneum-2.0-master/token-value/phase0/d02/registry-batch-tv-d02-20261009-01.json (master 0673ecf8, sha256 f21ffda7...), the requested map cell added; in progress until the decision's evidence is complete."
|
||||
}
|
||||
},
|
||||
"in_progress_since": "2026-10-09T09:00:20.590Z",
|
||||
"approvals": {
|
||||
"scope_approved": null,
|
||||
"implementation_complete": null,
|
||||
"evidence_reproduced": null,
|
||||
"claim_authorised": null
|
||||
},
|
||||
"run_id": "tv-d02-20261009-01",
|
||||
"evidence_path": "docs/plans/igneum-2.0-master/token-value/phase0/d02/README.md",
|
||||
"in_progress_since": "2026-10-09T09:00:20.590Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "TV-04",
|
||||
|
|
|
|||
8
tools/ci/batches/hash-lane-20261009-batch5.json
Normal file
8
tools/ci/batches/hash-lane-20261009-batch5.json
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"run_id": "hash-lane-20261009-batch5",
|
||||
"manifest_sha": "1a938abe4",
|
||||
"evidence_dir": "docs/analysis/class-v6/rows",
|
||||
"cells": [
|
||||
{"cell": "bench:fleet-pods", "status": "PASS", "method": "GPU", "evidence": "docs/analysis/class-v6/rows/x0-5090-20261009.md"}
|
||||
]
|
||||
}
|
||||
255
tools/token-value/tv-01/check-spec.py
Normal file
255
tools/token-value/tv-01/check-spec.py
Normal file
|
|
@ -0,0 +1,255 @@
|
|||
#!/usr/bin/env python3
|
||||
"""TV-01 checker: reads supply-spec.json, checks it is well-formed, and sums every schedule to the cap in exact integers.
|
||||
|
||||
python3 tools/token-value/tv-01/check-spec.py [docs/plans/igneum-2.0-master/token-value/phase0/tv-01/supply-spec.json]
|
||||
|
||||
Order of work (the known-failed cases first, the standing rule that a check is trusted only after it has fired):
|
||||
1. four known-failed specs, built in memory from the real one, must each be REFUSED for the stated reason:
|
||||
KF1 a tail (the terminal phase pays 1 base unit a block for ever): unbounded, the overshoot is infinite;
|
||||
KF2 an emergency mint (the first full-rate phase doubled, every sum made self-consistent): overshoot over the cap;
|
||||
KF3 the declared shortfall one base unit off: the exact reconciliation fails;
|
||||
KF4 a block-rate step from 1 to 10 blocks a second one year in, keyed as the code keys time today: overshoot;
|
||||
2. the real spec must be well-formed and reconcile exactly: total + shortfall = cap, total <= cap, the phases
|
||||
regenerated from the spec's own rules equal the listed phases, tail = cap, the tail-vote text SUPERSEDED.
|
||||
Exit 0 only when every known-failed case was refused and the real spec checked clean. The output never says PASS: the
|
||||
gate TV-01 reads NOT RUN until the independent panel reads the evidence. Standalone Python 3, deterministic.
|
||||
"""
|
||||
import copy
|
||||
import json
|
||||
import sys
|
||||
|
||||
DEFAULT = "docs/plans/igneum-2.0-master/token-value/phase0/tv-01/supply-spec.json"
|
||||
TOP = ["schema", "gate", "verdict", "decision", "invariant", "units", "cap", "rules", "activation_clocks", "schedules",
|
||||
"coinbase_split", "fees", "supply_accounting", "superseded", "conflicts", "sources", "generator"]
|
||||
CONFLICT_KEYS = ["id", "topic", "litepaper", "code", "spec_takes", "why", "status"]
|
||||
|
||||
|
||||
class Refused(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def need(cond, why):
|
||||
if not cond:
|
||||
raise Refused(why)
|
||||
|
||||
|
||||
def amount(x, where):
|
||||
need(isinstance(x, str) and x.isdigit() and (x == "0" or not x.startswith("0")), f"{where}: amount {x!r} is not a decimal string of base units")
|
||||
return int(x)
|
||||
|
||||
|
||||
# ---- the schedule regenerated from the spec's own rules (a third implementation beside the code and the generator) --
|
||||
def rules_of(spec):
|
||||
r = spec["rules"]
|
||||
return {"L": amount(r["launch_rate_per_second"], "rules.launch_rate_per_second"), "R": r["ramp_seconds"],
|
||||
"P": r["ramp_start_percent"], "S": r["step_seconds"], "Q": r["step_decay_q32"]}
|
||||
|
||||
|
||||
def rate(rr, k, cache={}):
|
||||
key = (rr["L"], rr["Q"], k)
|
||||
if key not in cache:
|
||||
x = rr["L"]
|
||||
for _ in range(k):
|
||||
x = (x * rr["Q"]) >> 32
|
||||
cache[key] = x
|
||||
return cache[key]
|
||||
|
||||
|
||||
def per_block(rr, daa, bps):
|
||||
s = daa // bps
|
||||
full = rate(rr, s // rr["S"]) // bps
|
||||
if s >= rr["R"]:
|
||||
return full
|
||||
return full * (rr["P"] * rr["R"] + (100 - rr["P"]) * s) // (100 * rr["R"])
|
||||
|
||||
|
||||
def ramp_sum(rr, bps):
|
||||
full = rr["L"] // bps
|
||||
R, P = rr["R"], rr["P"]
|
||||
return sum(full * (P * R + (100 - P) * s) // (100 * R) for s in range(R)) * bps
|
||||
|
||||
|
||||
def supply_to(rr, bps, daa):
|
||||
"""Scheduled issuance over DAA scores [0, daa) at one subsidy per DAA score."""
|
||||
total, R = 0, rr["R"] * bps
|
||||
full = rr["L"] // bps
|
||||
secs = min(daa, R) // bps
|
||||
total += sum(full * (rr["P"] * rr["R"] + (100 - rr["P"]) * s) // (100 * rr["R"]) for s in range(secs)) * bps
|
||||
total += (min(daa, R) - secs * bps) * per_block(rr, secs * bps, bps)
|
||||
d = R
|
||||
while d < daa:
|
||||
k = (d // bps) // rr["S"]
|
||||
end = min((k + 1) * rr["S"] * bps, daa)
|
||||
pb = per_block(rr, d, bps)
|
||||
if pb == 0:
|
||||
break
|
||||
total += pb * (end - d)
|
||||
d = end
|
||||
return total
|
||||
|
||||
|
||||
# ---- the checks ----------------------------------------------------------------------------------------------
|
||||
def check(spec, regen=True):
|
||||
"""Returns a list of report lines; raises Refused on the first fault."""
|
||||
out = []
|
||||
for k in TOP:
|
||||
need(k in spec, f"top-level field {k!r} missing")
|
||||
need(spec["gate"] == "TV-01", "gate is not TV-01")
|
||||
need(spec["verdict"] in ("NOT RUN", "BLOCKED", "FAIL"), f"verdict {spec['verdict']!r}: a lane never writes PASS on its own result")
|
||||
need(spec["decision"].get("id") == "D01", "decision is not D01")
|
||||
need(spec["rules"].get("genesis_rule", {}).get("rule") == "genesis-unrewarded", "the genesis rule (genesis never rewarded) is missing")
|
||||
need(spec["rules"].get("tail") == "cap", f"tail is {spec['rules'].get('tail')!r}: under D01 the only tail is the cap")
|
||||
cap = amount(spec["cap"]["base_units"], "cap.base_units")
|
||||
unit = amount(spec["units"]["base_units_per_coin"], "units.base_units_per_coin")
|
||||
need(unit == 10 ** spec["units"]["decimals"], "base_units_per_coin is not 10^decimals")
|
||||
need(cap == int(spec["cap"]["coins"]) * unit, "cap.base_units is not cap.coins x base_units_per_coin")
|
||||
sup = spec["superseded"]
|
||||
need(any(s.get("status") == "SUPERSEDED" and "tail reward" in s.get("text", "") and s.get("by", "").startswith("D01") for s in sup),
|
||||
"the litepaper's tail-vote sentence is not named SUPERSEDED by D01")
|
||||
ids = set()
|
||||
for c in spec["conflicts"]:
|
||||
for k in CONFLICT_KEYS:
|
||||
need(k in c, f"conflict {c.get('id')}: field {k!r} missing")
|
||||
need(c["id"] not in ids, f"conflict id {c['id']} repeated")
|
||||
ids.add(c["id"])
|
||||
need(c["status"].startswith("RESOLVED") or c["status"] == "BLOCKED", f"conflict {c['id']}: status {c['status']!r}")
|
||||
if c["status"] == "BLOCKED":
|
||||
need(c.get("question", "").startswith("For the founder"), f"conflict {c['id']}: BLOCKED without the founder's question")
|
||||
rr = rules_of(spec)
|
||||
need(rr["Q"] < 1 << 32 and rr["Q"] > 0, "step_decay_q32 outside 1..2^32: the curve would never fall")
|
||||
for sc in spec["schedules"]:
|
||||
name, bps, ph = sc["profile"], sc["bps"], sc["phases"]
|
||||
need(isinstance(bps, int) and bps > 0, f"{name}: bps {bps!r}")
|
||||
need(sc["genesis_daa_score"] == 0, f"{name}: genesis DAA score is not 0")
|
||||
need(len(ph) == sc["phase_count"] and len(ph) >= 2, f"{name}: phase_count disagrees with the list")
|
||||
need(ph[0]["start_daa_score"] == 0, f"{name}: the first phase does not start at DAA 0")
|
||||
total, prev_pb = 0, None
|
||||
for i, p in enumerate(ph):
|
||||
need(p["index"] == i, f"{name}: phase {i} carries index {p['index']}")
|
||||
need(p["source"], f"{name} phase {i}: no source line")
|
||||
if i:
|
||||
need(p["start_daa_score"] == ph[i - 1]["end_daa_score"], f"{name}: phase {i} does not start where phase {i - 1} ends (a gap or an overlap)")
|
||||
s = amount(p["phase_sum"], f"{name} phase {i}.phase_sum")
|
||||
if p["kind"] == "ramp":
|
||||
need(i == 0, f"{name}: a ramp phase at index {i}")
|
||||
rs = ramp_sum(rr, bps)
|
||||
need(s == rs, f"{name}: the ramp's declared sum {s} is not its formula's {rs} (off by {s - rs})")
|
||||
need(amount(p["ramp"]["full_per_block"], "ramp.full_per_block") == rr["L"] // bps, f"{name}: ramp full_per_block is not launch_rate / bps")
|
||||
elif p["kind"] == "constant":
|
||||
pb = amount(p["per_block_subsidy"], f"{name} phase {i}.per_block_subsidy")
|
||||
need(pb > 0, f"{name}: constant phase {i} pays 0 (that is the terminal)")
|
||||
need(p["end_daa_score"] > p["start_daa_score"], f"{name}: phase {i} is empty")
|
||||
need(s == pb * (p["end_daa_score"] - p["start_daa_score"]), f"{name}: phase {i} sum is not per_block x length")
|
||||
need(prev_pb is None or pb <= prev_pb, f"{name}: phase {i} pays more than phase {i - 1} (issuance rises)")
|
||||
prev_pb = pb
|
||||
elif p["kind"] == "terminal":
|
||||
need(i == len(ph) - 1, f"{name}: a terminal phase before the end")
|
||||
need(p["end_daa_score"] is None, f"{name}: the terminal phase has an end")
|
||||
tb = amount(p["per_block_subsidy"], f"{name} terminal per_block_subsidy")
|
||||
need(tb == 0, f"{name}: the terminal phase pays {tb} base units a block for ever: issuance is unbounded, the overshoot over the cap is infinite")
|
||||
else:
|
||||
raise Refused(f"{name}: phase {i} kind {p['kind']!r}")
|
||||
total += s
|
||||
need(ph[-1]["kind"] == "terminal", f"{name}: the schedule has no terminal phase (issuance is not shown to end)")
|
||||
need(sc["transition_count"] == len(ph) - 1, f"{name}: transition_count is not phases - 1")
|
||||
need(sc["last_paying_daa_score"] == ph[-1]["start_daa_score"] - 1 and sc["last_paying_block_height"] == ph[-1]["start_daa_score"],
|
||||
f"{name}: the last paying DAA score or height disagrees with the terminal phase (genesis is unrewarded: height = DAA score + 1)")
|
||||
need(sc["terminal_supply"] == sc["total_issuance"], f"{name}: terminal_supply is not the total issuance")
|
||||
need(total == amount(sc["total_issuance"], f"{name}.total_issuance"), f"{name}: the phases sum to {total}, the spec says {sc['total_issuance']}")
|
||||
if total > cap:
|
||||
raise Refused(f"{name}: overshoot {total - cap} base units ({(total - cap) / unit:,.6f} IGN) over the cap")
|
||||
short = cap - total
|
||||
declared = amount(sc["cap_shortfall"], f"{name}.cap_shortfall")
|
||||
need(short == declared, f"{name}: total + declared shortfall = {total + declared}, not the cap (off by {declared - short} base units)")
|
||||
if regen:
|
||||
for p in ph:
|
||||
if p["kind"] == "ramp":
|
||||
continue
|
||||
a = p["start_daa_score"]
|
||||
pb = per_block(rr, a, bps)
|
||||
need(str(pb) == p["per_block_subsidy"], f"{name}: phase {p['index']} lists {p['per_block_subsidy']}, the rules give {pb}")
|
||||
if p["end_daa_score"] is not None:
|
||||
need(per_block(rr, p["end_daa_score"] - 1, bps) == pb, f"{name}: phase {p['index']} is not constant under the rules")
|
||||
nb = per_block(rr, p["end_daa_score"], bps)
|
||||
need(nb != pb, f"{name}: phase {p['index']} ends where the rules do not change")
|
||||
out.append(f"{name}: {len(ph)} phases, contiguous from DAA 0, terminal zero from DAA {ph[-1]['start_daa_score']:,}; "
|
||||
f"total {total} + shortfall {short} = cap {cap} exactly (shortfall {short / unit:,.6f} IGN)")
|
||||
return out
|
||||
|
||||
|
||||
def bps_step_case(spec):
|
||||
"""KF4: the schedule as the code would pay it if the block rate stepped from 1 to 10 a second at DAA one year in."""
|
||||
rr = rules_of(spec)
|
||||
cap = int(spec["cap"]["base_units"])
|
||||
y = spec["rules"]["year_seconds"]
|
||||
step = y * 1
|
||||
s10 = int(next(s for s in spec["schedules"] if s["bps"] == 10)["total_issuance"])
|
||||
issued = supply_to(rr, 1, step) + (s10 - supply_to(rr, 10, step))
|
||||
need(issued <= cap, f"a 1-to-10 block-rate step at DAA {step:,} keyed as daa / bps: issuance {issued}, overshoot {issued - cap} base units over the cap")
|
||||
return issued
|
||||
|
||||
|
||||
def main():
|
||||
path = sys.argv[1] if len(sys.argv) > 1 else DEFAULT
|
||||
spec = json.load(open(path))
|
||||
fails = 0
|
||||
|
||||
def known_failed(label, mutate, run=None):
|
||||
nonlocal fails
|
||||
s = copy.deepcopy(spec)
|
||||
mutate(s)
|
||||
try:
|
||||
(run or (lambda x: check(x, regen=False)))(s)
|
||||
except Refused as e:
|
||||
print(f"known-failed {label}: refused as expected: {e}")
|
||||
return
|
||||
print(f"known-failed {label}: NOT refused (the checker is broken)")
|
||||
fails += 1
|
||||
|
||||
def kf1(s):
|
||||
sc = s["schedules"][0]
|
||||
sc["phases"][-1]["per_block_subsidy"] = "1"
|
||||
|
||||
def kf2(s):
|
||||
sc = s["schedules"][0]
|
||||
p = sc["phases"][1]
|
||||
old = int(p["phase_sum"])
|
||||
pb = int(p["per_block_subsidy"]) * 2
|
||||
p["per_block_subsidy"] = str(pb)
|
||||
p["phase_sum"] = str(pb * (p["end_daa_score"] - p["start_daa_score"]))
|
||||
sc["total_issuance"] = str(int(sc["total_issuance"]) - old + int(p["phase_sum"]))
|
||||
sc["cap_shortfall"] = str(int(s["cap"]["base_units"]) - int(sc["total_issuance"])) # may go negative: str(-x) fails too
|
||||
|
||||
def kf2_run(s):
|
||||
sc = s["schedules"][0]
|
||||
if sc["cap_shortfall"].startswith("-"):
|
||||
sc["cap_shortfall"] = "0" # make the field well-formed so the overshoot itself is what refuses it
|
||||
return check(s, regen=False)
|
||||
|
||||
def kf3(s):
|
||||
sc = s["schedules"][0]
|
||||
sc["cap_shortfall"] = str(int(sc["cap_shortfall"]) + 1)
|
||||
|
||||
known_failed("KF1 (a tail: the terminal pays 1 base unit a block for ever)", kf1)
|
||||
known_failed("KF2 (an emergency mint: the first full-rate phase doubled, sums self-consistent)", kf2, kf2_run)
|
||||
known_failed("KF3 (the declared shortfall one base unit off)", kf3)
|
||||
known_failed("KF4 (a 1-to-10 block-rate step one year in, time keyed as daa / bps)", lambda s: None, bps_step_case)
|
||||
|
||||
try:
|
||||
lines = check(spec)
|
||||
except Refused as e:
|
||||
print(f"spec {path}: REFUSED: {e}")
|
||||
return 1
|
||||
for l in lines:
|
||||
print(l)
|
||||
blocked = [c["id"] for c in spec["conflicts"] if c["status"] == "BLOCKED"]
|
||||
print(f"conflicts: {len(spec['conflicts'])} rows, BLOCKED: {', '.join(blocked) or 'none'}; gate TV-01 verdict as written: {spec['verdict']}")
|
||||
if fails:
|
||||
print(f"checker: {fails} known-failed case(s) were not refused; the result above is not trusted")
|
||||
return 2
|
||||
print("check: well-formed and exact (a check result, not a gate verdict)")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
139
tools/token-value/tv-01/code-dump/schedule-bf60948a.jsonl
Normal file
139
tools/token-value/tv-01/code-dump/schedule-bf60948a.jsonl
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
{"network":"mainnet","bps":10,"decimals":18,"launch_rate":"31688087810000000000","ramp_seconds":2592000,"ramp_start_percent":10,"step_seconds":63115200,"step_decay_q32":2147483648,"tail":"cap","steps":66,"genesis_daa_score":1312860}
|
||||
{"network":"mainnet","phase":"ramp","start_daa":0,"end_daa":25920000,"first_block":"316880878100000000","last_block":"3168807680719173263","sum":"45174523722296485488480000"}
|
||||
{"network":"mainnet","phase":"step","k":0,"start_daa":25920000,"end_daa":631152000,"per_block":"3168808781000000000","rate_per_second":"31688087810000000000","sum":"1917864476142192000000000000"}
|
||||
{"network":"mainnet","phase":"step","k":1,"start_daa":631152000,"end_daa":1262304000,"per_block":"1584404390500000000","rate_per_second":"15844043905000000000","sum":"999999999872856000000000000"}
|
||||
{"network":"mainnet","phase":"step","k":2,"start_daa":1262304000,"end_daa":1893456000,"per_block":"792202195250000000","rate_per_second":"7922021952500000000","sum":"499999999936428000000000000"}
|
||||
{"network":"mainnet","phase":"step","k":3,"start_daa":1893456000,"end_daa":2524608000,"per_block":"396101097625000000","rate_per_second":"3961010976250000000","sum":"249999999968214000000000000"}
|
||||
{"network":"mainnet","phase":"step","k":4,"start_daa":2524608000,"end_daa":3155760000,"per_block":"198050548812500000","rate_per_second":"1980505488125000000","sum":"124999999984107000000000000"}
|
||||
{"network":"mainnet","phase":"step","k":5,"start_daa":3155760000,"end_daa":3786912000,"per_block":"99025274406250000","rate_per_second":"990252744062500000","sum":"62499999992053500000000000"}
|
||||
{"network":"mainnet","phase":"step","k":6,"start_daa":3786912000,"end_daa":4418064000,"per_block":"49512637203125000","rate_per_second":"495126372031250000","sum":"31249999996026750000000000"}
|
||||
{"network":"mainnet","phase":"step","k":7,"start_daa":4418064000,"end_daa":5049216000,"per_block":"24756318601562500","rate_per_second":"247563186015625000","sum":"15624999998013375000000000"}
|
||||
{"network":"mainnet","phase":"step","k":8,"start_daa":5049216000,"end_daa":5680368000,"per_block":"12378159300781250","rate_per_second":"123781593007812500","sum":"7812499999006687500000000"}
|
||||
{"network":"mainnet","phase":"step","k":9,"start_daa":5680368000,"end_daa":6311520000,"per_block":"6189079650390625","rate_per_second":"61890796503906250","sum":"3906249999503343750000000"}
|
||||
{"network":"mainnet","phase":"step","k":10,"start_daa":6311520000,"end_daa":6942672000,"per_block":"3094539825195312","rate_per_second":"30945398251953125","sum":"1953124999751671559424000"}
|
||||
{"network":"mainnet","phase":"step","k":11,"start_daa":6942672000,"end_daa":7573824000,"per_block":"1547269912597656","rate_per_second":"15472699125976562","sum":"976562499875835779712000"}
|
||||
{"network":"mainnet","phase":"step","k":12,"start_daa":7573824000,"end_daa":8204976000,"per_block":"773634956298828","rate_per_second":"7736349562988281","sum":"488281249937917889856000"}
|
||||
{"network":"mainnet","phase":"step","k":13,"start_daa":8204976000,"end_daa":8836128000,"per_block":"386817478149414","rate_per_second":"3868174781494140","sum":"244140624968958944928000"}
|
||||
{"network":"mainnet","phase":"step","k":14,"start_daa":8836128000,"end_daa":9467280000,"per_block":"193408739074707","rate_per_second":"1934087390747070","sum":"122070312484479472464000"}
|
||||
{"network":"mainnet","phase":"step","k":15,"start_daa":9467280000,"end_daa":10098432000,"per_block":"96704369537353","rate_per_second":"967043695373535","sum":"61035156242239420656000"}
|
||||
{"network":"mainnet","phase":"step","k":16,"start_daa":10098432000,"end_daa":10729584000,"per_block":"48352184768676","rate_per_second":"483521847686767","sum":"30517578121119394752000"}
|
||||
{"network":"mainnet","phase":"step","k":17,"start_daa":10729584000,"end_daa":11360736000,"per_block":"24176092384338","rate_per_second":"241760923843383","sum":"15258789060559697376000"}
|
||||
{"network":"mainnet","phase":"step","k":18,"start_daa":11360736000,"end_daa":11991888000,"per_block":"12088046192169","rate_per_second":"120880461921691","sum":"7629394530279848688000"}
|
||||
{"network":"mainnet","phase":"step","k":19,"start_daa":11991888000,"end_daa":12623040000,"per_block":"6044023096084","rate_per_second":"60440230960845","sum":"3814697265139608768000"}
|
||||
{"network":"mainnet","phase":"step","k":20,"start_daa":12623040000,"end_daa":13254192000,"per_block":"3022011548042","rate_per_second":"30220115480422","sum":"1907348632569804384000"}
|
||||
{"network":"mainnet","phase":"step","k":21,"start_daa":13254192000,"end_daa":13885344000,"per_block":"1511005774021","rate_per_second":"15110057740211","sum":"953674316284902192000"}
|
||||
{"network":"mainnet","phase":"step","k":22,"start_daa":13885344000,"end_daa":14516496000,"per_block":"755502887010","rate_per_second":"7555028870105","sum":"476837158142135520000"}
|
||||
{"network":"mainnet","phase":"step","k":23,"start_daa":14516496000,"end_daa":15147648000,"per_block":"377751443505","rate_per_second":"3777514435052","sum":"238418579071067760000"}
|
||||
{"network":"mainnet","phase":"step","k":24,"start_daa":15147648000,"end_daa":15778800000,"per_block":"188875721752","rate_per_second":"1888757217526","sum":"119209289535218304000"}
|
||||
{"network":"mainnet","phase":"step","k":25,"start_daa":15778800000,"end_daa":16409952000,"per_block":"94437860876","rate_per_second":"944378608763","sum":"59604644767609152000"}
|
||||
{"network":"mainnet","phase":"step","k":26,"start_daa":16409952000,"end_daa":17041104000,"per_block":"47218930438","rate_per_second":"472189304381","sum":"29802322383804576000"}
|
||||
{"network":"mainnet","phase":"step","k":27,"start_daa":17041104000,"end_daa":17672256000,"per_block":"23609465219","rate_per_second":"236094652190","sum":"14901161191902288000"}
|
||||
{"network":"mainnet","phase":"step","k":28,"start_daa":17672256000,"end_daa":18303408000,"per_block":"11804732609","rate_per_second":"118047326095","sum":"7450580595635568000"}
|
||||
{"network":"mainnet","phase":"step","k":29,"start_daa":18303408000,"end_daa":18934560000,"per_block":"5902366304","rate_per_second":"59023663047","sum":"3725290297502208000"}
|
||||
{"network":"mainnet","phase":"step","k":30,"start_daa":18934560000,"end_daa":19565712000,"per_block":"2951183152","rate_per_second":"29511831523","sum":"1862645148751104000"}
|
||||
{"network":"mainnet","phase":"step","k":31,"start_daa":19565712000,"end_daa":20196864000,"per_block":"1475591576","rate_per_second":"14755915761","sum":"931322574375552000"}
|
||||
{"network":"mainnet","phase":"step","k":32,"start_daa":20196864000,"end_daa":20828016000,"per_block":"737795788","rate_per_second":"7377957880","sum":"465661287187776000"}
|
||||
{"network":"mainnet","phase":"step","k":33,"start_daa":20828016000,"end_daa":21459168000,"per_block":"368897894","rate_per_second":"3688978940","sum":"232830643593888000"}
|
||||
{"network":"mainnet","phase":"step","k":34,"start_daa":21459168000,"end_daa":22090320000,"per_block":"184448947","rate_per_second":"1844489470","sum":"116415321796944000"}
|
||||
{"network":"mainnet","phase":"step","k":35,"start_daa":22090320000,"end_daa":22721472000,"per_block":"92224473","rate_per_second":"922244735","sum":"58207660582896000"}
|
||||
{"network":"mainnet","phase":"step","k":36,"start_daa":22721472000,"end_daa":23352624000,"per_block":"46112236","rate_per_second":"461122367","sum":"29103829975872000"}
|
||||
{"network":"mainnet","phase":"step","k":37,"start_daa":23352624000,"end_daa":23983776000,"per_block":"23056118","rate_per_second":"230561183","sum":"14551914987936000"}
|
||||
{"network":"mainnet","phase":"step","k":38,"start_daa":23983776000,"end_daa":24614928000,"per_block":"11528059","rate_per_second":"115280591","sum":"7275957493968000"}
|
||||
{"network":"mainnet","phase":"step","k":39,"start_daa":24614928000,"end_daa":25246080000,"per_block":"5764029","rate_per_second":"57640295","sum":"3637978431408000"}
|
||||
{"network":"mainnet","phase":"step","k":40,"start_daa":25246080000,"end_daa":25877232000,"per_block":"2882014","rate_per_second":"28820147","sum":"1818988900128000"}
|
||||
{"network":"mainnet","phase":"step","k":41,"start_daa":25877232000,"end_daa":26508384000,"per_block":"1441007","rate_per_second":"14410073","sum":"909494450064000"}
|
||||
{"network":"mainnet","phase":"step","k":42,"start_daa":26508384000,"end_daa":27139536000,"per_block":"720503","rate_per_second":"7205036","sum":"454746909456000"}
|
||||
{"network":"mainnet","phase":"step","k":43,"start_daa":27139536000,"end_daa":27770688000,"per_block":"360251","rate_per_second":"3602518","sum":"227373139152000"}
|
||||
{"network":"mainnet","phase":"step","k":44,"start_daa":27770688000,"end_daa":28401840000,"per_block":"180125","rate_per_second":"1801259","sum":"113686254000000"}
|
||||
{"network":"mainnet","phase":"step","k":45,"start_daa":28401840000,"end_daa":29032992000,"per_block":"90062","rate_per_second":"900629","sum":"56842811424000"}
|
||||
{"network":"mainnet","phase":"step","k":46,"start_daa":29032992000,"end_daa":29664144000,"per_block":"45031","rate_per_second":"450314","sum":"28421405712000"}
|
||||
{"network":"mainnet","phase":"step","k":47,"start_daa":29664144000,"end_daa":30295296000,"per_block":"22515","rate_per_second":"225157","sum":"14210387280000"}
|
||||
{"network":"mainnet","phase":"step","k":48,"start_daa":30295296000,"end_daa":30926448000,"per_block":"11257","rate_per_second":"112578","sum":"7104878064000"}
|
||||
{"network":"mainnet","phase":"step","k":49,"start_daa":30926448000,"end_daa":31557600000,"per_block":"5628","rate_per_second":"56289","sum":"3552123456000"}
|
||||
{"network":"mainnet","phase":"step","k":50,"start_daa":31557600000,"end_daa":32188752000,"per_block":"2814","rate_per_second":"28144","sum":"1776061728000"}
|
||||
{"network":"mainnet","phase":"step","k":51,"start_daa":32188752000,"end_daa":32819904000,"per_block":"1407","rate_per_second":"14072","sum":"888030864000"}
|
||||
{"network":"mainnet","phase":"step","k":52,"start_daa":32819904000,"end_daa":33451056000,"per_block":"703","rate_per_second":"7036","sum":"443699856000"}
|
||||
{"network":"mainnet","phase":"step","k":53,"start_daa":33451056000,"end_daa":34082208000,"per_block":"351","rate_per_second":"3518","sum":"221534352000"}
|
||||
{"network":"mainnet","phase":"step","k":54,"start_daa":34082208000,"end_daa":34713360000,"per_block":"175","rate_per_second":"1759","sum":"110451600000"}
|
||||
{"network":"mainnet","phase":"step","k":55,"start_daa":34713360000,"end_daa":35344512000,"per_block":"87","rate_per_second":"879","sum":"54910224000"}
|
||||
{"network":"mainnet","phase":"step","k":56,"start_daa":35344512000,"end_daa":35975664000,"per_block":"43","rate_per_second":"439","sum":"27139536000"}
|
||||
{"network":"mainnet","phase":"step","k":57,"start_daa":35975664000,"end_daa":36606816000,"per_block":"21","rate_per_second":"219","sum":"13254192000"}
|
||||
{"network":"mainnet","phase":"step","k":58,"start_daa":36606816000,"end_daa":37237968000,"per_block":"10","rate_per_second":"109","sum":"6311520000"}
|
||||
{"network":"mainnet","phase":"step","k":59,"start_daa":37237968000,"end_daa":37869120000,"per_block":"5","rate_per_second":"54","sum":"3155760000"}
|
||||
{"network":"mainnet","phase":"step","k":60,"start_daa":37869120000,"end_daa":38500272000,"per_block":"2","rate_per_second":"27","sum":"1262304000"}
|
||||
{"network":"mainnet","phase":"step","k":61,"start_daa":38500272000,"end_daa":39131424000,"per_block":"1","rate_per_second":"13","sum":"631152000"}
|
||||
{"network":"mainnet","phase":"step","k":62,"start_daa":39131424000,"end_daa":39762576000,"per_block":"0","rate_per_second":"6","sum":"0"}
|
||||
{"network":"mainnet","phase":"terminal","start_daa":39131424000,"per_block":"0"}
|
||||
{"network":"mainnet","total":"3963038999610200467816224000","cap":"4000000000000000000000000000","shortfall":"36961000389799532183776000"}
|
||||
{"network":"devnet-4","bps":1,"decimals":18,"launch_rate":"31688087810000000000","ramp_seconds":2592000,"ramp_start_percent":10,"step_seconds":63115200,"step_decay_q32":2147483648,"tail":"cap","steps":66,"genesis_daa_score":0}
|
||||
{"network":"devnet-4","phase":"ramp","start_daa":0,"end_daa":2592000,"first_block":"3168808781000000000","last_block":"31688076807191732638","sum":"45174523722296485498848000"}
|
||||
{"network":"devnet-4","phase":"step","k":0,"start_daa":2592000,"end_daa":63115200,"per_block":"31688087810000000000","rate_per_second":"31688087810000000000","sum":"1917864476142192000000000000"}
|
||||
{"network":"devnet-4","phase":"step","k":1,"start_daa":63115200,"end_daa":126230400,"per_block":"15844043905000000000","rate_per_second":"15844043905000000000","sum":"999999999872856000000000000"}
|
||||
{"network":"devnet-4","phase":"step","k":2,"start_daa":126230400,"end_daa":189345600,"per_block":"7922021952500000000","rate_per_second":"7922021952500000000","sum":"499999999936428000000000000"}
|
||||
{"network":"devnet-4","phase":"step","k":3,"start_daa":189345600,"end_daa":252460800,"per_block":"3961010976250000000","rate_per_second":"3961010976250000000","sum":"249999999968214000000000000"}
|
||||
{"network":"devnet-4","phase":"step","k":4,"start_daa":252460800,"end_daa":315576000,"per_block":"1980505488125000000","rate_per_second":"1980505488125000000","sum":"124999999984107000000000000"}
|
||||
{"network":"devnet-4","phase":"step","k":5,"start_daa":315576000,"end_daa":378691200,"per_block":"990252744062500000","rate_per_second":"990252744062500000","sum":"62499999992053500000000000"}
|
||||
{"network":"devnet-4","phase":"step","k":6,"start_daa":378691200,"end_daa":441806400,"per_block":"495126372031250000","rate_per_second":"495126372031250000","sum":"31249999996026750000000000"}
|
||||
{"network":"devnet-4","phase":"step","k":7,"start_daa":441806400,"end_daa":504921600,"per_block":"247563186015625000","rate_per_second":"247563186015625000","sum":"15624999998013375000000000"}
|
||||
{"network":"devnet-4","phase":"step","k":8,"start_daa":504921600,"end_daa":568036800,"per_block":"123781593007812500","rate_per_second":"123781593007812500","sum":"7812499999006687500000000"}
|
||||
{"network":"devnet-4","phase":"step","k":9,"start_daa":568036800,"end_daa":631152000,"per_block":"61890796503906250","rate_per_second":"61890796503906250","sum":"3906249999503343750000000"}
|
||||
{"network":"devnet-4","phase":"step","k":10,"start_daa":631152000,"end_daa":694267200,"per_block":"30945398251953125","rate_per_second":"30945398251953125","sum":"1953124999751671875000000"}
|
||||
{"network":"devnet-4","phase":"step","k":11,"start_daa":694267200,"end_daa":757382400,"per_block":"15472699125976562","rate_per_second":"15472699125976562","sum":"976562499875835905942400"}
|
||||
{"network":"devnet-4","phase":"step","k":12,"start_daa":757382400,"end_daa":820497600,"per_block":"7736349562988281","rate_per_second":"7736349562988281","sum":"488281249937917952971200"}
|
||||
{"network":"devnet-4","phase":"step","k":13,"start_daa":820497600,"end_daa":883612800,"per_block":"3868174781494140","rate_per_second":"3868174781494140","sum":"244140624968958944928000"}
|
||||
{"network":"devnet-4","phase":"step","k":14,"start_daa":883612800,"end_daa":946728000,"per_block":"1934087390747070","rate_per_second":"1934087390747070","sum":"122070312484479472464000"}
|
||||
{"network":"devnet-4","phase":"step","k":15,"start_daa":946728000,"end_daa":1009843200,"per_block":"967043695373535","rate_per_second":"967043695373535","sum":"61035156242239736232000"}
|
||||
{"network":"devnet-4","phase":"step","k":16,"start_daa":1009843200,"end_daa":1072958400,"per_block":"483521847686767","rate_per_second":"483521847686767","sum":"30517578121119836558400"}
|
||||
{"network":"devnet-4","phase":"step","k":17,"start_daa":1072958400,"end_daa":1136073600,"per_block":"241760923843383","rate_per_second":"241760923843383","sum":"15258789060559886721600"}
|
||||
{"network":"devnet-4","phase":"step","k":18,"start_daa":1136073600,"end_daa":1199188800,"per_block":"120880461921691","rate_per_second":"120880461921691","sum":"7629394530279911803200"}
|
||||
{"network":"devnet-4","phase":"step","k":19,"start_daa":1199188800,"end_daa":1262304000,"per_block":"60440230960845","rate_per_second":"60440230960845","sum":"3814697265139924344000"}
|
||||
{"network":"devnet-4","phase":"step","k":20,"start_daa":1262304000,"end_daa":1325419200,"per_block":"30220115480422","rate_per_second":"30220115480422","sum":"1907348632569930614400"}
|
||||
{"network":"devnet-4","phase":"step","k":21,"start_daa":1325419200,"end_daa":1388534400,"per_block":"15110057740211","rate_per_second":"15110057740211","sum":"953674316284965307200"}
|
||||
{"network":"devnet-4","phase":"step","k":22,"start_daa":1388534400,"end_daa":1451649600,"per_block":"7555028870105","rate_per_second":"7555028870105","sum":"476837158142451096000"}
|
||||
{"network":"devnet-4","phase":"step","k":23,"start_daa":1451649600,"end_daa":1514764800,"per_block":"3777514435052","rate_per_second":"3777514435052","sum":"238418579071193990400"}
|
||||
{"network":"devnet-4","phase":"step","k":24,"start_daa":1514764800,"end_daa":1577880000,"per_block":"1888757217526","rate_per_second":"1888757217526","sum":"119209289535596995200"}
|
||||
{"network":"devnet-4","phase":"step","k":25,"start_daa":1577880000,"end_daa":1640995200,"per_block":"944378608763","rate_per_second":"944378608763","sum":"59604644767798497600"}
|
||||
{"network":"devnet-4","phase":"step","k":26,"start_daa":1640995200,"end_daa":1704110400,"per_block":"472189304381","rate_per_second":"472189304381","sum":"29802322383867691200"}
|
||||
{"network":"devnet-4","phase":"step","k":27,"start_daa":1704110400,"end_daa":1767225600,"per_block":"236094652190","rate_per_second":"236094652190","sum":"14901161191902288000"}
|
||||
{"network":"devnet-4","phase":"step","k":28,"start_daa":1767225600,"end_daa":1830340800,"per_block":"118047326095","rate_per_second":"118047326095","sum":"7450580595951144000"}
|
||||
{"network":"devnet-4","phase":"step","k":29,"start_daa":1830340800,"end_daa":1893456000,"per_block":"59023663047","rate_per_second":"59023663047","sum":"3725290297944014400"}
|
||||
{"network":"devnet-4","phase":"step","k":30,"start_daa":1893456000,"end_daa":1956571200,"per_block":"29511831523","rate_per_second":"29511831523","sum":"1862645148940449600"}
|
||||
{"network":"devnet-4","phase":"step","k":31,"start_daa":1956571200,"end_daa":2019686400,"per_block":"14755915761","rate_per_second":"14755915761","sum":"931322574438667200"}
|
||||
{"network":"devnet-4","phase":"step","k":32,"start_daa":2019686400,"end_daa":2082801600,"per_block":"7377957880","rate_per_second":"7377957880","sum":"465661287187776000"}
|
||||
{"network":"devnet-4","phase":"step","k":33,"start_daa":2082801600,"end_daa":2145916800,"per_block":"3688978940","rate_per_second":"3688978940","sum":"232830643593888000"}
|
||||
{"network":"devnet-4","phase":"step","k":34,"start_daa":2145916800,"end_daa":2209032000,"per_block":"1844489470","rate_per_second":"1844489470","sum":"116415321796944000"}
|
||||
{"network":"devnet-4","phase":"step","k":35,"start_daa":2209032000,"end_daa":2272147200,"per_block":"922244735","rate_per_second":"922244735","sum":"58207660898472000"}
|
||||
{"network":"devnet-4","phase":"step","k":36,"start_daa":2272147200,"end_daa":2335262400,"per_block":"461122367","rate_per_second":"461122367","sum":"29103830417678400"}
|
||||
{"network":"devnet-4","phase":"step","k":37,"start_daa":2335262400,"end_daa":2398377600,"per_block":"230561183","rate_per_second":"230561183","sum":"14551915177281600"}
|
||||
{"network":"devnet-4","phase":"step","k":38,"start_daa":2398377600,"end_daa":2461492800,"per_block":"115280591","rate_per_second":"115280591","sum":"7275957557083200"}
|
||||
{"network":"devnet-4","phase":"step","k":39,"start_daa":2461492800,"end_daa":2524608000,"per_block":"57640295","rate_per_second":"57640295","sum":"3637978746984000"}
|
||||
{"network":"devnet-4","phase":"step","k":40,"start_daa":2524608000,"end_daa":2587723200,"per_block":"28820147","rate_per_second":"28820147","sum":"1818989341934400"}
|
||||
{"network":"devnet-4","phase":"step","k":41,"start_daa":2587723200,"end_daa":2650838400,"per_block":"14410073","rate_per_second":"14410073","sum":"909494639409600"}
|
||||
{"network":"devnet-4","phase":"step","k":42,"start_daa":2650838400,"end_daa":2713953600,"per_block":"7205036","rate_per_second":"7205036","sum":"454747288147200"}
|
||||
{"network":"devnet-4","phase":"step","k":43,"start_daa":2713953600,"end_daa":2777068800,"per_block":"3602518","rate_per_second":"3602518","sum":"227373644073600"}
|
||||
{"network":"devnet-4","phase":"step","k":44,"start_daa":2777068800,"end_daa":2840184000,"per_block":"1801259","rate_per_second":"1801259","sum":"113686822036800"}
|
||||
{"network":"devnet-4","phase":"step","k":45,"start_daa":2840184000,"end_daa":2903299200,"per_block":"900629","rate_per_second":"900629","sum":"56843379460800"}
|
||||
{"network":"devnet-4","phase":"step","k":46,"start_daa":2903299200,"end_daa":2966414400,"per_block":"450314","rate_per_second":"450314","sum":"28421658172800"}
|
||||
{"network":"devnet-4","phase":"step","k":47,"start_daa":2966414400,"end_daa":3029529600,"per_block":"225157","rate_per_second":"225157","sum":"14210829086400"}
|
||||
{"network":"devnet-4","phase":"step","k":48,"start_daa":3029529600,"end_daa":3092644800,"per_block":"112578","rate_per_second":"112578","sum":"7105382985600"}
|
||||
{"network":"devnet-4","phase":"step","k":49,"start_daa":3092644800,"end_daa":3155760000,"per_block":"56289","rate_per_second":"56289","sum":"3552691492800"}
|
||||
{"network":"devnet-4","phase":"step","k":50,"start_daa":3155760000,"end_daa":3218875200,"per_block":"28144","rate_per_second":"28144","sum":"1776314188800"}
|
||||
{"network":"devnet-4","phase":"step","k":51,"start_daa":3218875200,"end_daa":3281990400,"per_block":"14072","rate_per_second":"14072","sum":"888157094400"}
|
||||
{"network":"devnet-4","phase":"step","k":52,"start_daa":3281990400,"end_daa":3345105600,"per_block":"7036","rate_per_second":"7036","sum":"444078547200"}
|
||||
{"network":"devnet-4","phase":"step","k":53,"start_daa":3345105600,"end_daa":3408220800,"per_block":"3518","rate_per_second":"3518","sum":"222039273600"}
|
||||
{"network":"devnet-4","phase":"step","k":54,"start_daa":3408220800,"end_daa":3471336000,"per_block":"1759","rate_per_second":"1759","sum":"111019636800"}
|
||||
{"network":"devnet-4","phase":"step","k":55,"start_daa":3471336000,"end_daa":3534451200,"per_block":"879","rate_per_second":"879","sum":"55478260800"}
|
||||
{"network":"devnet-4","phase":"step","k":56,"start_daa":3534451200,"end_daa":3597566400,"per_block":"439","rate_per_second":"439","sum":"27707572800"}
|
||||
{"network":"devnet-4","phase":"step","k":57,"start_daa":3597566400,"end_daa":3660681600,"per_block":"219","rate_per_second":"219","sum":"13822228800"}
|
||||
{"network":"devnet-4","phase":"step","k":58,"start_daa":3660681600,"end_daa":3723796800,"per_block":"109","rate_per_second":"109","sum":"6879556800"}
|
||||
{"network":"devnet-4","phase":"step","k":59,"start_daa":3723796800,"end_daa":3786912000,"per_block":"54","rate_per_second":"54","sum":"3408220800"}
|
||||
{"network":"devnet-4","phase":"step","k":60,"start_daa":3786912000,"end_daa":3850027200,"per_block":"27","rate_per_second":"27","sum":"1704110400"}
|
||||
{"network":"devnet-4","phase":"step","k":61,"start_daa":3850027200,"end_daa":3913142400,"per_block":"13","rate_per_second":"13","sum":"820497600"}
|
||||
{"network":"devnet-4","phase":"step","k":62,"start_daa":3913142400,"end_daa":3976257600,"per_block":"6","rate_per_second":"6","sum":"378691200"}
|
||||
{"network":"devnet-4","phase":"step","k":63,"start_daa":3976257600,"end_daa":4039372800,"per_block":"3","rate_per_second":"3","sum":"189345600"}
|
||||
{"network":"devnet-4","phase":"step","k":64,"start_daa":4039372800,"end_daa":4102488000,"per_block":"1","rate_per_second":"1","sum":"63115200"}
|
||||
{"network":"devnet-4","phase":"step","k":65,"start_daa":4102488000,"end_daa":4165603200,"per_block":"0","rate_per_second":"0","sum":"0"}
|
||||
{"network":"devnet-4","phase":"terminal","start_daa":4102488000,"per_block":"0"}
|
||||
{"network":"devnet-4","total":"3963038999610200483289816000","cap":"4000000000000000000000000000","shortfall":"36961000389799516710184000"}
|
||||
{"network":"testnet-1","bps":1,"decimals":18,"launch_rate":"100000000000000000000","ramp_seconds":7776000,"ramp_start_percent":10,"step_seconds":2629800,"step_decay_q32":4172697914,"tail":"percent:100","steps":125,"genesis_daa_score":0}
|
||||
{"network":"testnet-1","note":"not a cap schedule; phases not dumped"}
|
||||
60
tools/token-value/tv-01/code-dump/tv01_schedule.rs.txt
Normal file
60
tools/token-value/tv-01/code-dump/tv01_schedule.rs.txt
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
//! TV-01 (token value phase 0, 9 October 2026): the per-block subsidy schedule of each compiled network, read from the
|
||||
//! consensus code's own functions (`Params::emission`, `EmissionTable::block_subsidy`, `Params::bps`), as JSON lines.
|
||||
//! Lane scratch file on build-9 only; not part of the node fork.
|
||||
use kaspa_consensus_core::config::params::{devnet4_params, Params, MAINNET_PARAMS, TESTNET_PARAMS};
|
||||
use kaspa_consensus_core::emission::Tail;
|
||||
|
||||
fn dump(name: &str, p: &Params) {
|
||||
let t = p.emission.table();
|
||||
let s = p.emission;
|
||||
let bps = p.bps();
|
||||
let tail = match s.tail { Tail::Cap => "cap".to_string(), Tail::Fixed { rate } => format!("fixed:{rate}"), Tail::Percent { bps_per_year } => format!("percent:{bps_per_year}") };
|
||||
println!(
|
||||
"{{\"network\":\"{name}\",\"bps\":{bps},\"decimals\":{},\"launch_rate\":\"{}\",\"ramp_seconds\":{},\"ramp_start_percent\":{},\"step_seconds\":{},\"step_decay_q32\":{},\"tail\":\"{tail}\",\"steps\":{},\"genesis_daa_score\":{}}}",
|
||||
p.base_unit_decimals, s.launch_rate, s.ramp_seconds, s.ramp_start_percent, s.step_seconds, s.step_decay_q32, t.step_rate.len(), p.genesis.daa_score
|
||||
);
|
||||
if s.tail != Tail::Cap {
|
||||
println!("{{\"network\":\"{name}\",\"note\":\"not a cap schedule; phases not dumped\"}}");
|
||||
return;
|
||||
}
|
||||
// the ramp: every block of DAA second sec pays block_subsidy(sec * bps); sum per DAA score
|
||||
let mut ramp_sum: u128 = 0;
|
||||
for sec in 0..s.ramp_seconds {
|
||||
let a = t.block_subsidy(sec * bps, bps);
|
||||
let b = t.block_subsidy(sec * bps + bps - 1, bps);
|
||||
assert_eq!(a, b, "constant inside a DAA second");
|
||||
ramp_sum += a * bps as u128;
|
||||
}
|
||||
let first = t.block_subsidy(0, bps);
|
||||
let last_ramp = t.block_subsidy(s.ramp_seconds * bps - 1, bps);
|
||||
println!("{{\"network\":\"{name}\",\"phase\":\"ramp\",\"start_daa\":0,\"end_daa\":{},\"first_block\":\"{first}\",\"last_block\":\"{last_ramp}\",\"sum\":\"{ramp_sum}\"}}", s.ramp_seconds * bps);
|
||||
let mut total = ramp_sum;
|
||||
let mut k: u64 = 0;
|
||||
loop {
|
||||
let start = if k == 0 { s.ramp_seconds * bps } else { k * s.step_seconds * bps };
|
||||
let end = (k + 1) * s.step_seconds * bps;
|
||||
let per = t.block_subsidy(start, bps);
|
||||
let per_end = t.block_subsidy(end - 1, bps);
|
||||
assert_eq!(per, per_end, "constant inside step {k}");
|
||||
let n = (end - start) as u128;
|
||||
total += per * n;
|
||||
println!("{{\"network\":\"{name}\",\"phase\":\"step\",\"k\":{k},\"start_daa\":{start},\"end_daa\":{end},\"per_block\":\"{per}\",\"rate_per_second\":\"{}\",\"sum\":\"{}\"}}", t.rate_at(start / bps), per * n);
|
||||
if per == 0 {
|
||||
// the terminal: zero at every later DAA score the table can reach
|
||||
for probe in [end, end * 2, u64::MAX / bps * bps - 1, u64::MAX] {
|
||||
assert_eq!(t.block_subsidy(probe, bps), 0);
|
||||
}
|
||||
println!("{{\"network\":\"{name}\",\"phase\":\"terminal\",\"start_daa\":{start},\"per_block\":\"0\"}}");
|
||||
break;
|
||||
}
|
||||
k += 1;
|
||||
}
|
||||
let cap = kaspa_consensus_core::igneum::supply_cap_units(p.base_unit_decimals);
|
||||
println!("{{\"network\":\"{name}\",\"total\":\"{total}\",\"cap\":\"{cap}\",\"shortfall\":\"{}\"}}", cap - total);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
dump("mainnet", &MAINNET_PARAMS);
|
||||
dump("devnet-4", &devnet4_params());
|
||||
dump("testnet-1", &TESTNET_PARAMS);
|
||||
}
|
||||
613
tools/token-value/tv-01/gen-spec.py
Normal file
613
tools/token-value/tv-01/gen-spec.py
Normal file
|
|
@ -0,0 +1,613 @@
|
|||
#!/usr/bin/env python3
|
||||
"""TV-01 (Igneum 2.0 Token Value, Phase 0): generates the machine-readable supply spec.
|
||||
|
||||
Reads nothing it does not cite. The schedule constants are transcribed from the node fork's consensus crate and every
|
||||
transcription is anchored: for each cited line the generator reads the file at each named revision (git show) and
|
||||
refuses to write the spec when the line no longer carries its anchor text. The schedule is then computed here in exact
|
||||
integers (Python ints), and, when --code-dump is given, compared field by field with the dump the consensus code's own
|
||||
functions printed on the build box (tools/token-value/tv-01/code-dump/tv01_schedule.rs.txt), so every figure in the spec is
|
||||
one the code agrees with.
|
||||
|
||||
python3 tools/token-value/tv-01/gen-spec.py \
|
||||
--node-git <igneum-node clone holding bf60948a and a284380b> \
|
||||
--igneum-root . --igneum-rev 6824d49cc32def4463b643293a5622545618f7a9 \
|
||||
--code-dump tools/token-value/tv-01/code-dump/schedule-bf60948a.jsonl \
|
||||
--out docs/plans/igneum-2.0-master/token-value/phase0/tv-01/supply-spec.json \
|
||||
--md docs/plans/igneum-2.0-master/token-value/phase0/tv-01/supply-spec.md
|
||||
|
||||
Deterministic: the same inputs give the same bytes. Nothing here activates anything.
|
||||
"""
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
NODE_REVS = {
|
||||
"release-2.0.2-node": "a284380bdd62d5d0d972cb38f2cbd1daeedda69d",
|
||||
"node 2.0.2 shipped (detached-5d53a591)": "5d53a591469b3f2b31eb87ec793faa582e95cb18",
|
||||
"release-2.0.3-node-k6": "bf60948a01467bb54eaab9e50d32b91058f11242",
|
||||
"release-2.0.3-node-k7": "27f54124375ca0901ea0ead30eb4773413f6602f",
|
||||
}
|
||||
# the litepaper revision the tail-vote sentence is quoted from (before the site lane's D01 edit, ad64e48fa)
|
||||
LITEPAPER_SUPERSEDED_REV = "6824d49cc32def4463b643293a5622545618f7a9"
|
||||
|
||||
# ---- The constants, as the code writes them (each one anchored below) -------------------------------------------
|
||||
YEAR_SECONDS = 31_557_600 # emission.rs:32
|
||||
LAUNCH_RATE_8 = 3_168_808_781 # emission.rs:104 (10^17 / 31,557,600 floored)
|
||||
RAMP_SECONDS = 2_592_000 # emission.rs:105
|
||||
RAMP_START_PERCENT = 10 # emission.rs:106
|
||||
STEP_SECONDS = 2 * YEAR_SECONDS # emission.rs:107
|
||||
STEP_DECAY_Q32 = 1 << 31 # emission.rs:108
|
||||
DECIMALS = 18 # unit.rs:38, params.rs:1816
|
||||
UNIT = 10 ** DECIMALS
|
||||
LAUNCH_RATE = LAUNCH_RATE_8 * 10 ** (DECIMALS - 8) # emission.rs rescaled(8, 18); params.rs:1858
|
||||
CAP = 4_000_000_000 * UNIT # igneum.rs:154 supply_cap_units(18)
|
||||
PROVING_POOL_SHARE_PERCENT = 20 # igneum.rs:44
|
||||
SIGNING_BONUS_BPS = 1_000 # params.rs:1810
|
||||
DEVELOPER_SHARE_PERCENT = 20 # exec config (pgas.rs:290 reads it)
|
||||
MAINNET_BPS = 10 # params.rs:1789 BlockrateParams::new::<10>()
|
||||
DEVNET4_BPS = 1 # params.rs:2208 (DEVNET_PARAMS, inherited by devnet3/devnet4)
|
||||
MAINNET_GENESIS_DAA_COMPILED = 1_312_860 # genesis.rs:92
|
||||
|
||||
# (id, repo, path, line, anchor text the line must contain)
|
||||
CITATIONS = [
|
||||
("year", "node", "consensus/core/src/emission.rs", 32, "pub const YEAR_SECONDS: u64 = 31_557_600;"),
|
||||
("current", "node", "consensus/core/src/emission.rs", 103, "pub const CURRENT: EmissionSchedule"),
|
||||
("launch_rate", "node", "consensus/core/src/emission.rs", 104, "launch_rate: 3_168_808_781"),
|
||||
("ramp_seconds", "node", "consensus/core/src/emission.rs", 105, "ramp_seconds: 2_592_000"),
|
||||
("ramp_start", "node", "consensus/core/src/emission.rs", 106, "ramp_start_percent: 10"),
|
||||
("step_seconds", "node", "consensus/core/src/emission.rs", 107, "step_seconds: 2 * YEAR_SECONDS"),
|
||||
("decay", "node", "consensus/core/src/emission.rs", 108, "step_decay_q32: 1 << 31"),
|
||||
("tail_cap", "node", "consensus/core/src/emission.rs", 109, "tail: Tail::Cap"),
|
||||
("testnet1", "node", "consensus/core/src/emission.rs", 116, "pub const TESTNET_1: EmissionSchedule"),
|
||||
("testnet1_tail", "node", "consensus/core/src/emission.rs", 122, "tail: Tail::Percent { bps_per_year: 100 }"),
|
||||
("decay_rule", "node", "consensus/core/src/emission.rs", 225, "rate = rate.saturating_mul(s.step_decay_q32 as u128) >> 32;"),
|
||||
("ramp_fn", "node", "consensus/core/src/emission.rs", 316, "pub fn ramp(&self, full: u128, seconds: u64) -> u128"),
|
||||
("block_subsidy", "node", "consensus/core/src/emission.rs", 329, "pub fn block_subsidy(&self, daa_score: u64, bps: u64) -> u128"),
|
||||
("per_block_div", "node", "consensus/core/src/emission.rs", 331, "let per_block = self.rate_at(seconds) / bps as u128;"),
|
||||
("cap_const", "node", "consensus/core/src/igneum.rs", 37, "pub const SUPPLY_CAP_SOMPI: u64 = 4_000_000_000 * SOMPI_PER_KASPA;"),
|
||||
("pool_share", "node", "consensus/core/src/igneum.rs", 44, "pub const PROVING_POOL_SHARE_PERCENT: u64 = 20;"),
|
||||
("silent_split", "node", "consensus/core/src/igneum.rs", 110, "pub fn silent_split_units("),
|
||||
("cap_units", "node", "consensus/core/src/igneum.rs", 154, "pub const fn supply_cap_units(decimals: u8) -> u128"),
|
||||
("pool_units", "node", "consensus/core/src/igneum.rs", 201, "pub fn proving_pool_share_units("),
|
||||
("producer_units", "node", "consensus/core/src/igneum.rs", 206, "pub fn producer_share_units("),
|
||||
("pool_script", "node", "consensus/core/src/igneum.rs", 213, "pub fn proving_pool_script_public_key()"),
|
||||
("evm_decimals", "node", "consensus/core/src/unit.rs", 38, "pub const EVM_DECIMALS: u8 = 18;"),
|
||||
("mainnet_deflationary", "node", "consensus/core/src/config/params.rs", 1783, "deflationary_phase_daa_score: 15778800 - 259200,"),
|
||||
("mainnet_pre_deflationary", "node", "consensus/core/src/config/params.rs", 1784, "pre_deflationary_phase_base_subsidy: 50000000000,"),
|
||||
("mainnet_bps", "node", "consensus/core/src/config/params.rs", 1789, "blockrate: BlockrateParams::new::<10>(),"),
|
||||
("mainnet_bonus_off", "node", "consensus/core/src/config/params.rs", 1809, "signing_bonus_activation_daa: u64::MAX,"),
|
||||
("mainnet_bonus_bps", "node", "consensus/core/src/config/params.rs", 1810, "signing_bonus_bps: 1_000,"),
|
||||
("mainnet_n8_off", "node", "consensus/core/src/config/params.rs", 1812, "subsidy_per_block_activation_daa: u64::MAX,"),
|
||||
("mainnet_decimals", "node", "consensus/core/src/config/params.rs", 1816, "base_unit_decimals: crate::unit::EVM_DECIMALS"),
|
||||
("mainnet_pool_split_off", "node", "consensus/core/src/config/params.rs", 1851, "pool_split_activation_daa: u64::MAX,"),
|
||||
("mainnet_emission", "node", "consensus/core/src/config/params.rs", 1858, "emission: EmissionSchedule::CURRENT.rescaled(crate::unit::DEVNET_DECIMALS, crate::unit::EVM_DECIMALS),"),
|
||||
("testnet_bonus_on", "node", "consensus/core/src/config/params.rs", 1955, "signing_bonus_activation_daa: 0,"),
|
||||
("testnet_n8_on", "node", "consensus/core/src/config/params.rs", 1960, "subsidy_per_block_activation_daa: 0,"),
|
||||
("testnet_emission", "node", "consensus/core/src/config/params.rs", 2014, "emission: EmissionSchedule::TESTNET_1.rescaled("),
|
||||
("devnet_bps", "node", "consensus/core/src/config/params.rs", 2208, "blockrate: BlockrateParams::new::<1>(),"),
|
||||
("devnet_n8_off", "node", "consensus/core/src/config/params.rs", 2232, "subsidy_per_block_activation_daa: u64::MAX,"),
|
||||
("devnet_pool_split_off", "node", "consensus/core/src/config/params.rs", 2270, "pool_split_activation_daa: u64::MAX,"),
|
||||
("devnet4_fn", "node", "consensus/core/src/config/params.rs", 2342, "pub fn devnet4_params() -> Params {"),
|
||||
("devnet4_emission", "node", "consensus/core/src/config/params.rs", 2372, "emission: EmissionSchedule::CURRENT.rescaled(crate::unit::DEVNET_DECIMALS, crate::unit::EVM_DECIMALS),"),
|
||||
("mainnet_genesis_daa", "node", "consensus/core/src/config/genesis.rs", 92, "daa_score: 1312860, // Checkpoint DAA score"),
|
||||
("genesis_no_outputs", "node", "consensus/core/src/config/genesis.rs", 26, "Transaction::new(0, Vec::new(), Vec::new(), 0, SUBNETWORK_ID_COINBASE"),
|
||||
("cb_header", "node", "consensus/src/processes/coinbase.rs", 31, "Kaspa's pre-deflationary phase, 426-month table and Crescendo `bps_history` rescaling are gone."),
|
||||
("cb_split", "node", "consensus/src/processes/coinbase.rs", 106, "fn producer_and_pool(&self, daa_score: u64, reward: &BlockRewardData)"),
|
||||
("cb_reds", "node", "consensus/src/processes/coinbase.rs", 152, "for red in ghostdag_data.mergeset_reds.iter()"),
|
||||
("cb_pool_output", "node", "consensus/src/processes/coinbase.rs", 163, "outputs.push(TransactionOutput::new_units(proving_pool_reward, igneum::proving_pool_script_public_key()));"),
|
||||
("cb_calc", "node", "consensus/src/processes/coinbase.rs", 262, "pub fn calc_block_subsidy(&self, daa_score: u64) -> Amount"),
|
||||
("cb_calc_body", "node", "consensus/src/processes/coinbase.rs", 265, "Amount(self.emission.block_subsidy(daa_score, self.bps))"),
|
||||
("genesis_not_in_window", "node", "consensus/src/processes/window.rs", 177, "Special case: Genesis does not enter the DAA window"),
|
||||
("cb_daa_blues_only", "node", "consensus/src/processes/coinbase.rs", 139, "for blue in ghostdag_data.mergeset_blues.iter().filter(|h| !mergeset_non_daa.contains(h))"),
|
||||
("utxo_retired", "node", "consensus/src/pipeline/body_processor/body_validation_in_isolation.rs", 54, "RuleError::UtxoTransactionsRetired"),
|
||||
("exec_blue_only", "node", "igneum/exec/src/executor.rs", 181, "for b in blocks.iter().filter(|b| b.is_blue)"),
|
||||
("exec_split", "node", "igneum/exec/src/executor.rs", 189, "silent_split_units(subsidy, b.silent, env.signing_bonus_bps)"),
|
||||
("exec_miner_credit", "node", "igneum/exec/src/executor.rs", 208, "db.add_balance(b.miner, producer_wei);"),
|
||||
("exec_pool_credit", "node", "igneum/exec/src/executor.rs", 211, "db.add_balance(PROVING_POOL_ADDRESS, pool_wei);"),
|
||||
("exec_tip_miner", "node", "igneum/exec/src/executor.rs", 362, "let tip_total = (gas_used as u128) * (price - env.base_fee_exec);"),
|
||||
("exec_dev_shares", "node", "igneum/exec/src/pgas.rs", 290, "pub fn developer_shares("),
|
||||
("pool_address", "node", "igneum/exec/src/config.rs", 59, "pub const PROVING_POOL_ADDRESS: Address"),
|
||||
("override_refused", "node", "kaspad/src/daemon.rs", None, "if network.params_compiled() {"),
|
||||
("params_compiled", "node", "consensus/core/src/network.rs", 266, "NetworkType::Mainnet | NetworkType::Testnet => true,"),
|
||||
("lp_cap", "igneum", "site/litepaper.html", 578, "Hard cap of 4 billion IGN, approached and never reached, because emission starts at 1 billion a year and halves every two years for ever"),
|
||||
("lp_caption", "igneum", "site/litepaper.html", 602, "3,938M IGN in the first 12 years of a 4,000M cap."),
|
||||
("lp_proving_pool", "igneum", "site/litepaper.html", 609, "is burned there"),
|
||||
("lp_tail", "igneum-old", "site/litepaper.html", 630, "One rule sits beside the cap. If external proving revenue is under one fifth of the block subsidy over any 90-day window after year 5, the question of a tail reward goes to the miners' signalling vote. The protocol never changes emission by itself."),
|
||||
("lp_tail_now", "igneum", "site/litepaper.html", 630, "the answer is the security-funding plan under D01, never a tail emission or a vote that expands the cap."),
|
||||
("lp_cap_now", "igneum", "site/litepaper.html", 630, "The cap is fixed at 4 billion, with no tail emission and no vote that expands it (D01, subject to the pre-launch security-funding gate)."),
|
||||
("lp_tip_prose", "igneum", "site/litepaper.html", 614, "The priority fee splits two ways: 80% to the miner and provers of that block, 20% to the apps whose code ran"),
|
||||
("ledger_e22", "igneum", "docs/plans/ledger-decisions.md", 110, "The testnet genesis carries `EmissionSchedule::TESTNET_1`"),
|
||||
("lp_block_rate", "igneum", "site/litepaper.html", 542, "one block a second at launch with scheduled steps to four and ten"),
|
||||
("lp_unit", "igneum", "site/litepaper.html", 568, "the base unit is Open"),
|
||||
("lp_emission_route", "igneum", "site/litepaper.html", 620, "80% the block's miner, 20% the proving pool for the provers of that block"),
|
||||
("lp_tip_route", "igneum", "site/litepaper.html", 622, "80% the block's miner and provers; 20% the apps whose code ran, per call frame"),
|
||||
("lp_external_job", "igneum", "site/litepaper.html", 624, "90% the provers who delivered"),
|
||||
("lp_dev_fee", "igneum", "site/litepaper.html", 625, "1 block template in 100 requested with the dev address"),
|
||||
("lp_pool_custody", "igneum", "site/litepaper.html", 647, "The reference pool never holds a member"),
|
||||
("lp_per_block_figure", "igneum", "site/litepaper.html", 668, "31.688 IGN a block, 86,400 blocks a day"),
|
||||
("lp_mainnet_launch", "igneum", "site/litepaper.html", 775, "Genesis with no premine, 30-day ramp."),
|
||||
("spec_tip_no_provers", "igneum", "docs/spec/05-fees-and-economics.md", 24, "No part of the tip reaches the provers: O-5.7 is closed at zero (8 October 2026"),
|
||||
("spec_tip_table_stale", "igneum", "docs/spec/05-fees-and-economics.md", 79, "80 / 20 (producer and provers / developer)"),
|
||||
("pool_payout_doc", "igneum", "pool/src/payout.rs", 3, "so the pool receives"),
|
||||
("pool_fee_default", "igneum", "pool/src/config.rs", 58, "fee_percent: 1.0,"),
|
||||
("pool_distribute", "igneum", "pool/src/pplns.rs", 76, "pub fn distribute(reward_wei: u128, fee_percent: f64, payees: &[Payee])"),
|
||||
]
|
||||
|
||||
|
||||
def sh(cmd, cwd):
|
||||
return subprocess.run(cmd, cwd=cwd, check=True, capture_output=True).stdout
|
||||
|
||||
|
||||
def read_node(node_git, rev, path):
|
||||
return sh(["git", "show", f"{rev}:{path}"], node_git)
|
||||
|
||||
|
||||
def read_igneum(root, rev, path):
|
||||
return sh(["git", "show", f"{rev}:{path}"], root)
|
||||
|
||||
|
||||
def anchor(citations, node_git, igneum_root, igneum_rev):
|
||||
"""Every cited line must carry its anchor at every named revision; returns the resolved citation table and the
|
||||
sha256 of every cited file per revision."""
|
||||
out, files = [], {}
|
||||
for cid, repo, path, line, text in citations:
|
||||
revs = NODE_REVS.items() if repo == "node" else [("igneum master", igneum_rev)] if repo == "igneum" else [("igneum before ad64e48fa", LITEPAPER_SUPERSEDED_REV)]
|
||||
lines_at = {}
|
||||
for name, rev in revs:
|
||||
blob = read_node(node_git, rev, path) if repo == "node" else read_igneum(igneum_root, rev, path)
|
||||
files.setdefault(f"{repo}:{path}", {})[name] = hashlib.sha256(blob).hexdigest()
|
||||
src = blob.decode("utf-8").split("\n")
|
||||
if line is None:
|
||||
hits = [i + 1 for i, l in enumerate(src) if text in l]
|
||||
if len(hits) != 1:
|
||||
sys.exit(f"anchor {cid}: {path} at {name} has {len(hits)} lines carrying {text!r}")
|
||||
lines_at[name] = hits[0]
|
||||
else:
|
||||
if line > len(src) or text not in src[line - 1]:
|
||||
sys.exit(f"anchor {cid}: {path}:{line} at {name} no longer carries {text!r}")
|
||||
lines_at[name] = line
|
||||
ref_lines = sorted(set(lines_at.values()))
|
||||
out.append({"id": cid, "repo": repo, "path": path, "line": ref_lines[0] if len(ref_lines) == 1 else lines_at,
|
||||
"anchor": text})
|
||||
return out, files
|
||||
|
||||
|
||||
# ---- The schedule, in exact integers ---------------------------------------------------------------------------
|
||||
def step_rate(k):
|
||||
r = LAUNCH_RATE
|
||||
for _ in range(k):
|
||||
r = (r * STEP_DECAY_Q32) >> 32
|
||||
return r
|
||||
|
||||
|
||||
def ramp(full, seconds):
|
||||
if seconds >= RAMP_SECONDS:
|
||||
return full
|
||||
num = RAMP_START_PERCENT * RAMP_SECONDS + (100 - RAMP_START_PERCENT) * seconds
|
||||
return full * num // (100 * RAMP_SECONDS)
|
||||
|
||||
|
||||
def block_subsidy(daa, bps):
|
||||
seconds = daa // bps
|
||||
return ramp(step_rate(seconds // STEP_SECONDS) // bps, seconds)
|
||||
|
||||
|
||||
def ramp_sum(bps, upto_seconds=RAMP_SECONDS):
|
||||
full = LAUNCH_RATE // bps
|
||||
return sum(ramp(full, s) for s in range(min(upto_seconds, RAMP_SECONDS))) * bps
|
||||
|
||||
|
||||
def schedule(bps):
|
||||
phases = []
|
||||
rs = ramp_sum(bps)
|
||||
phases.append({
|
||||
"index": 0, "kind": "ramp", "rule": "launch-ramp",
|
||||
"start_daa_score": 0, "end_daa_score": RAMP_SECONDS * bps,
|
||||
"per_block_subsidy": None,
|
||||
"ramp": {"full_per_block": str(LAUNCH_RATE // bps), "start_percent": RAMP_START_PERCENT,
|
||||
"ramp_seconds": RAMP_SECONDS, "first_block": str(block_subsidy(0, bps)),
|
||||
"last_block": str(block_subsidy(RAMP_SECONDS * bps - 1, bps)),
|
||||
"formula": "per_block(d) = floor(full_per_block x (start_percent x ramp_seconds + (100 - start_percent) x s) / (100 x ramp_seconds)), s = floor(d / bps)"},
|
||||
"phase_sum": str(rs),
|
||||
"source": ["consensus/core/src/emission.rs:316", "consensus/core/src/emission.rs:329"],
|
||||
})
|
||||
k = 0
|
||||
while True:
|
||||
start = RAMP_SECONDS * bps if k == 0 else k * STEP_SECONDS * bps
|
||||
end = (k + 1) * STEP_SECONDS * bps
|
||||
per = block_subsidy(start, bps)
|
||||
assert per == block_subsidy(end - 1, bps)
|
||||
if per == 0:
|
||||
phases.append({
|
||||
"index": len(phases), "kind": "terminal", "rule": "terminal-zero",
|
||||
"start_daa_score": start, "end_daa_score": None, "per_block_subsidy": "0",
|
||||
"decay_step": k, "rate_per_second": str(step_rate(k)), "phase_sum": "0",
|
||||
"source": ["consensus/core/src/emission.rs:109", "consensus/core/src/emission.rs:225", "consensus/core/src/emission.rs:331"],
|
||||
})
|
||||
break
|
||||
phases.append({
|
||||
"index": len(phases), "kind": "constant",
|
||||
"rule": "full-rate-after-ramp" if k == 0 else f"halving-{k}",
|
||||
"start_daa_score": start, "end_daa_score": end, "per_block_subsidy": str(per),
|
||||
"decay_step": k, "rate_per_second": str(step_rate(k)), "phase_sum": str(per * (end - start)),
|
||||
"source": ["consensus/core/src/emission.rs:107", "consensus/core/src/emission.rs:225", "consensus/core/src/emission.rs:331"],
|
||||
})
|
||||
k += 1
|
||||
total = sum(int(p["phase_sum"]) for p in phases)
|
||||
return phases, total
|
||||
|
||||
|
||||
def supply_at(phases, daa, bps):
|
||||
"""Scheduled issuance over DAA scores [0, daa): one subsidy per DAA score (the replay model)."""
|
||||
s = 0
|
||||
for p in phases:
|
||||
a, b = p["start_daa_score"], p["end_daa_score"]
|
||||
if daa <= a:
|
||||
break
|
||||
if p["kind"] == "ramp":
|
||||
hi = min(daa, b)
|
||||
full_secs, rem = divmod(hi, bps)
|
||||
s += ramp_sum(bps, full_secs) + rem * block_subsidy(full_secs * bps, bps)
|
||||
elif p["kind"] == "constant":
|
||||
s += int(p["per_block_subsidy"]) * (min(daa, b) - a)
|
||||
return s
|
||||
|
||||
|
||||
def bps_step_overshoot(step_daa, from_bps, to_bps, total_to):
|
||||
"""The code keys time as daa / bps with ONE bps per network (coinbase.rs:31, :265). If the block rate stepped on a
|
||||
live chain at `step_daa` with no history rule, every block from the step on would be paid as if the clock read
|
||||
daa / to_bps: issuance = sum_{d < step} sub_from(d) + sum_{d >= step} sub_to(d)."""
|
||||
ph_from, _ = schedule(from_bps)
|
||||
ph_to, _ = schedule(to_bps)
|
||||
issued = supply_at(ph_from, step_daa, from_bps) + (total_to - supply_at(ph_to, step_daa, to_bps))
|
||||
return issued
|
||||
|
||||
|
||||
def coins(x):
|
||||
q, r = divmod(x, UNIT)
|
||||
return f"{q:,}.{r:018d}".rstrip("0").rstrip(".")
|
||||
|
||||
|
||||
# ---- The conflicts and the texts ------------------------------------------------------------------------------
|
||||
TAIL_SENTENCE = ("One rule sits beside the cap. If external proving revenue is under one fifth of the block subsidy over "
|
||||
"any 90-day window after year 5, the question of a tail reward goes to the miners' signalling vote. "
|
||||
"The protocol never changes emission by itself.")
|
||||
|
||||
|
||||
def conflicts(fig):
|
||||
m, d = fig["mainnet"], fig["devnet-4"]
|
||||
return [
|
||||
{"id": "C01", "topic": "cap versus the year-five tail vote",
|
||||
"litepaper": {"line": 630, "rev": LITEPAPER_SUPERSEDED_REV, "words": TAIL_SENTENCE,
|
||||
"now_reads": {"rev": "current", "line": 630, "words": "the answer is the security-funding plan under D01, never a tail emission or a vote that expands the cap."}},
|
||||
"code": {"where": "consensus/core/src/emission.rs:109 (Tail::Cap in EmissionSchedule::CURRENT); consensus/core/src/config/params.rs:1858 (mainnet carries CURRENT); kaspad/src/daemon.rs (params_compiled refuses an override file on mainnet and testnet); no signal path reads or writes the emission schedule",
|
||||
"value": "tail = cap; the schedule is a compiled genesis parameter; no vote, no revenue trigger, no tail"},
|
||||
"spec_takes": "the cap as the invariant; the tail-vote sentence is SUPERSEDED",
|
||||
"why": "D01 (capped issuance, subject to TV-04), ratified by the founder 9 October 2026 09:2x UK; VR-01 (no unexplained tail escape, no price- or revenue-triggered issuance); the code already enforces only the capped schedule. If TV-04 shows capped security cannot pass, the volume's rule applies: delay launch or openly choose another design, never an undisclosed tail.",
|
||||
"status": "RESOLVED (by D01, subject to TV-04)",
|
||||
"follow_up": "done by the site lane at ad64e48fa (9 October 2026, 09:16 UK): line 630 now reads 'The cap is fixed at 4 billion, with no tail emission and no vote that expands it (D01, subject to the pre-launch security-funding gate)' and the year-five clause routes to the security-funding plan; this landing edits no site/ file"},
|
||||
{"id": "C02", "topic": "year-one emission and the twelve-year figure",
|
||||
"litepaper": {"line": 578, "words": "emission starts at 1 billion a year", "line_2": 602, "words_2": "3,938M IGN in the first 12 years of a 4,000M cap."},
|
||||
"code": {"where": "consensus/core/src/emission.rs:104 to 106 (launch rate floored, the 30-day ramp from 10%)",
|
||||
"value": f"year 1 issues {coins(m['year_1'])} IGN at 10 blocks/s ({coins(d['year_1'])} at 1 block/s); the first 12 years issue {coins(m['year_12'])} IGN"},
|
||||
"spec_takes": "the code's figures",
|
||||
"why": "the litepaper chart and caption ignore the launch ramp's withheld 36,961,000 IGN and the floor of the per-second rate; the spec carries what nodes pay",
|
||||
"status": "RESOLVED (text correction owed by the site lane)"},
|
||||
{"id": "C03", "topic": "terminal behaviour",
|
||||
"litepaper": {"line": 578, "words": "halves every two years for ever"},
|
||||
"code": {"where": "consensus/core/src/emission.rs:225 (rate[k+1] = rate[k] x 2^31 >> 32, floored), :331 (per block = rate / bps, floored)",
|
||||
"value": f"the per-block subsidy floors to zero at decay step {m['terminal_step']} (DAA score {m['terminal_daa']:,}, the start of year {m['terminal_year'] + 1}) at 10 blocks/s and at step {d['terminal_step']} (DAA score {d['terminal_daa']:,}, the start of year {d['terminal_year'] + 1}) at 1 block/s; zero for ever after"},
|
||||
"spec_takes": "the code: a finite schedule ending in a terminal zero phase",
|
||||
"why": "integer halving ends; the last subsidy is 1 base unit (10^-18 IGN) per block; after it the security budget is fees alone (TV-04's question)",
|
||||
"status": "RESOLVED (text correction owed: 'until the subsidy floors to zero')"},
|
||||
{"id": "C04", "topic": "block rate at launch and its steps",
|
||||
"litepaper": {"line": 542, "words": "one block a second at launch with scheduled steps to four and ten", "line_2": 668, "words_2": "31.688 IGN a block, 86,400 blocks a day"},
|
||||
"code": {"where": "consensus/core/src/config/params.rs:1789 (mainnet BlockrateParams::new::<10>()); consensus/src/processes/coinbase.rs:31 (the bps_history rescaling is gone) and :265 (subsidy keyed on daa / ONE bps)",
|
||||
"value": f"mainnet as compiled runs 10 blocks/s from genesis, 3.1688087810 IGN a block; the subsidy has no block-rate history, so a step from 1 to 10 blocks/s at DAA score {fig['bps_step']['step_daa']:,} (one year in) would issue {coins(fig['bps_step']['issued'])} IGN in all, an overshoot of {coins(fig['bps_step']['issued'] - CAP)} IGN over the cap"},
|
||||
"spec_takes": "both profiles (10 blocks/s as compiled; 1 block/s as Devnet 4), identical per second; NO live block-rate step is cap-safe under the current code",
|
||||
"why": "a block-rate step re-keys the schedule clock (seconds = daa / bps) and re-pays elapsed time",
|
||||
"status": "BLOCKED",
|
||||
"question": "For the founder: does mainnet launch at the compiled 10 blocks a second (the litepaper's 1-to-4-to-10 step plan removed), or at 1 with steps (then the node lane adds a block-rate-history subsidy rule before genesis, and TV-02 replays a step)? Default if unanswered: the spec freezes the compiled 10 blocks a second and the step plan is treated as text to correct."},
|
||||
{"id": "C05", "topic": "unit",
|
||||
"litepaper": {"line": 568, "words": "the base unit is Open"},
|
||||
"code": {"where": "consensus/core/src/unit.rs:38; consensus/core/src/config/params.rs:1816",
|
||||
"value": "18 decimals on mainnet, testnet and Devnet 4: 1 IGN = 10^18 base units; one base unit is one EVM wei"},
|
||||
"spec_takes": "18 decimals",
|
||||
"why": "decided 6 October 2026 (O-2.6) and compiled; the cap is 4 x 10^27 base units",
|
||||
"status": "RESOLVED (text correction owed)"},
|
||||
{"id": "C06", "topic": "where the 20% proving share goes, and which ledger is native supply",
|
||||
"litepaper": {"line": 609, "words": "the coinbase's 20% output goes to an unspendable script tagged igneum-proving-pool-v0 and is burned there. Provers are paid from a separate escrow in the execution state"},
|
||||
"code": {"where": "consensus/src/processes/coinbase.rs:163 (UTXO pool output to the OP_RETURN script); consensus/src/pipeline/body_processor/body_validation_in_isolation.rs:54 (no UTXO transaction but the coinbase: UTXO outputs can never be spent); igneum/exec/src/executor.rs:181 to 211 (the EVM state credits 80% to the producer and 20% to the escrow 0x...0220 for every blue block)",
|
||||
"value": "two ledgers record each subsidy: the UTXO coinbase (unspendable by rule) and the EVM state (spendable)"},
|
||||
"spec_takes": "native supply is the EVM state's credit; the UTXO coinbase is a non-spendable shadow record and its OP_RETURN 20% is NOT a burn of native supply; the escrow balance is issued and locked until paid per proof",
|
||||
"why": "counting both ledgers doubles supply; counting the OP_RETURN as burned and the escrow as issued would understate and overstate at once (VR-02)",
|
||||
"status": "RESOLVED (for the spec; TV-02 reconciles both ledgers to this rule)"},
|
||||
{"id": "C07", "topic": "red blocks",
|
||||
"litepaper": {"line": 620, "words": "80% the block's miner, 20% the proving pool for the provers of that block"},
|
||||
"code": {"where": "consensus/src/processes/coinbase.rs:152 to 159 (the UTXO coinbase pays a DAA red block's subsidy to the merging miner and the pool); igneum/exec/src/executor.rs:181 (the EVM credits blue blocks only)",
|
||||
"value": "a red block's subsidy exists on the shadow ledger and not in native supply"},
|
||||
"spec_takes": "native issuance = the blue blocks' subsidies; the per-DAA-score schedule sum is the upper bound",
|
||||
"why": "the EVM ledger is native supply (C06); the bound keeps the cap invariant whatever the red share",
|
||||
"status": "RESOLVED (TV-02 measures the red share; no text change needed beyond 'blue block')"},
|
||||
{"id": "C08", "topic": "which DAA score a merged block is credited at",
|
||||
"litepaper": {"line": None, "words": "(silent)"},
|
||||
"code": {"where": "consensus/core/src/config/params.rs:1812 (mainnet subsidy_per_block_activation_daa = never), :2232 (Devnet 4 inherits never), :1960 (testnet-1: 0)",
|
||||
"value": "on mainnet and Devnet 4 the EVM credits a merged block the merging chain block's subsidy while the UTXO coinbase pays the block's own: one ramp second high per merged block, a whole halving step at a boundary"},
|
||||
"spec_takes": "each block's own DAA score (ledger N8) as the normative rule",
|
||||
"why": "exact integer agreement between ledgers and replays (TV-02) needs one rule; N8 is the one the testnet object already carries",
|
||||
"status": "BLOCKED",
|
||||
"question": "For the founder (the node lane owns the change): set subsidy_per_block_activation_daa = 0 in the mainnet object, as testnet-1 has it? Default if unanswered: the spec keeps N8 as normative and TV-02 reports the chain-block reading as a measured divergence."},
|
||||
{"id": "C09", "topic": "the mainnet genesis clock",
|
||||
"litepaper": {"line": 775, "words": "Genesis with no premine, 30-day ramp."},
|
||||
"code": {"where": "consensus/core/src/config/genesis.rs:92 (mainnet GENESIS daa_score 1312860, Kaspa's 2021 timestamp); the subsidy reads the absolute DAA score (emission.rs:329)",
|
||||
"value": f"as compiled, the first mainnet block would sit 131,286 DAA seconds into the ramp (paying {fig['genesis_offset']['first_ramp_percent']} of full rate, not 10%) and the whole schedule would run 1.52 days early; issuance would be {coins(fig['genesis_offset']['issuance_lost'])} IGN lower"},
|
||||
"spec_takes": "genesis at DAA score 0 (as Devnet 4 and testnet-1); the activation clocks below are counted from it",
|
||||
"why": "the mainnet genesis is a Kaspa placeholder not yet cut; every Igneum network so far starts at DAA score 0",
|
||||
"status": "BLOCKED",
|
||||
"question": "For the founder: confirm the mainnet genesis is cut at DAA score 0. Default if unanswered: the spec freezes DAA score 0 and the genesis cut is checked against it."},
|
||||
{"id": "C10", "topic": "priority fee to provers",
|
||||
"litepaper": {"line": 622, "words": "80% the block's miner and provers; 20% the apps whose code ran, per call frame",
|
||||
"line_2": 614, "words_2": "The priority fee splits two ways: 80% to the miner and provers of that block, 20% to the apps whose code ran"},
|
||||
"code": {"where": "igneum/exec/src/executor.rs:321, :332 to 340 and :362 to 371 (the tip less the developer share is credited to the block's miner alone); igneum/exec/src/pgas.rs:290 (20% developer share, unregistered parts burned)",
|
||||
"value": "two separate 80/20 rules ship: the SUBSIDY's 20% goes to the proving pool escrow and pays provers per accepted proof record (igneum.rs:44, :201 to 208; executor.rs:181 to 211); the TIP's 80% goes to the block's miner alone and 20% to developer registrations or burned. No tip reaches a prover. The design's route of 90% of the proving base fee to provers (docs/design/proving-payment.md; node branch proving-payment 930b6322, flag 67912c80, behind proving_payment_activation_daa) is not merged into any shipped or 2.0.3 line and has no activation"},
|
||||
"spec_takes": "the code, which is the design's own closed decision",
|
||||
"why": "docs/spec/05-fees-and-economics.md line 24 (section 5.2): 'No part of the tip reaches the provers: O-5.7 is closed at zero (8 October 2026, docs/design/proving-payment.md); the provers' user-funded payment is the proving base fee'. The code (executor.rs:362 to 371, revm's beneficiary credit) matches it. The litepaper line 622 and the spec's own summary rows (05 line 79, line 98) still say 'producer and provers' and are stale. Fees move existing supply and burn some; they never create supply.",
|
||||
"status": "RESOLVED (by O-5.7, closed at zero 8 October 2026; the litepaper's 'miner and provers' at lines 614 and 622 is SUPERSEDED; text corrections owed there and at spec 05 lines 79 and 98)"},
|
||||
{"id": "C11", "topic": "the reference pool's custody and fee",
|
||||
"litepaper": {"line": 647, "words": "The reference pool never holds a member’s balance. Payouts come straight from the coinbase split"},
|
||||
"code": {"where": "pool/src/payout.rs:1 to 6 (the pool's address receives the 80% and pays members by transfers); pool/src/config.rs:58 (fee_percent 1.0); pool/src/pplns.rs:76; consensus/core/src/config/params.rs:1851 (mainnet pool_split_activation_daa = never: the IGNW coinbase split is off)",
|
||||
"value": "the reference pool holds members' balances between rounds and keeps a 1% fee; the consensus split that would make the sentence true is off on mainnet and Devnet 4"},
|
||||
"spec_takes": "the code (custodial PPLNS, 1% default fee, no supply effect)",
|
||||
"why": "the payout route moves issued supply; it creates none",
|
||||
"status": "BLOCKED",
|
||||
"question": "For the founder: activate the IGNW coinbase split at mainnet genesis (pool_split_activation_daa = 0) so the litepaper sentence holds, or change the sentence to the custodial PPLNS pool with its 1% fee? Default if unanswered: the sentence is corrected to the code."},
|
||||
{"id": "C12", "topic": "a tail schedule compiled into testnet-1",
|
||||
"litepaper": {"line": 630, "words": "The cap is fixed at 4 billion, with no tail emission and no vote that expands it (D01, subject to the pre-launch security-funding gate)."},
|
||||
"code": {"where": "consensus/core/src/emission.rs:116 to 122 (TESTNET_1: 100 IGN a block, monthly glide, a 1% a year tail); consensus/core/src/config/params.rs:2014 (testnet-1 carries it)",
|
||||
"value": "testnet-1's own approved genesis schedule (docs/plans/ledger-decisions.md line 110, ledger E22: 'No hard cap'): kept on every node line, active only when igneum-testnet-1's genesis is cut (none has been), never on Devnet 4 (params.rs:2372) or mainnet (params.rs:1858), which carry CURRENT with Tail::Cap"},
|
||||
"spec_takes": "testnet-only and outside the monetary contract; the contract is EmissionSchedule::CURRENT with Tail::Cap on mainnet",
|
||||
"why": "D01 binds the value-bearing contract; testnet-1 carries no value. Binding the cap to the testnet as well would change its approved genesis (E22) and move its digest: the founder's call, not this spec's",
|
||||
"status": "RESOLVED (by D01: testnet-only, named)"},
|
||||
{"id": "C13", "topic": "dead Kaspa subsidy fields in the mainnet object",
|
||||
"litepaper": {"line": None, "words": "(silent)"},
|
||||
"code": {"where": "consensus/core/src/config/params.rs:1783 to 1784 (deflationary_phase_daa_score 15,519,600; pre_deflationary_phase_base_subsidy 50,000,000,000)",
|
||||
"value": "read only into the consensus digest; the subsidy never reads them (coinbase.rs:31)"},
|
||||
"spec_takes": "ignored: they are not part of the monetary contract",
|
||||
"why": "a reader grepping 'deflationary' would otherwise find a second schedule that does not exist",
|
||||
"status": "RESOLVED (the node lane may annotate or remove them at the genesis cut)"},
|
||||
]
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument("--node-git", required=True)
|
||||
ap.add_argument("--igneum-root", required=True)
|
||||
ap.add_argument("--igneum-rev", default="HEAD")
|
||||
ap.add_argument("--code-dump")
|
||||
ap.add_argument("--out", required=True)
|
||||
ap.add_argument("--md")
|
||||
a = ap.parse_args()
|
||||
|
||||
igneum_rev = sh(["git", "rev-parse", a.igneum_rev], a.igneum_root).decode().strip()
|
||||
cites, files = anchor(CITATIONS, a.node_git, a.igneum_root, igneum_rev)
|
||||
|
||||
profiles, fig = [], {}
|
||||
for name, network, bps in [("mainnet", "mainnet (MAINNET_PARAMS as compiled)", MAINNET_BPS), ("devnet-4", "Devnet 4 (devnet4_params, 1 block a second, the litepaper's launch rate)", DEVNET4_BPS)]:
|
||||
phases, total = schedule(bps)
|
||||
term = phases[-1]
|
||||
f = {
|
||||
"year_1": supply_at(phases, YEAR_SECONDS * bps, bps),
|
||||
"year_12": supply_at(phases, 12 * YEAR_SECONDS * bps, bps),
|
||||
"terminal_step": term["decay_step"], "terminal_daa": term["start_daa_score"],
|
||||
"terminal_year": term["start_daa_score"] // bps // YEAR_SECONDS,
|
||||
"total": total,
|
||||
}
|
||||
fig[name] = f
|
||||
years = {}
|
||||
for y in [1, 2, 5, 10, 12, 20, 50, 100]:
|
||||
years[str(y)] = str(supply_at(phases, y * YEAR_SECONDS * bps, bps))
|
||||
last_nonzero = phases[-2]
|
||||
profiles.append({
|
||||
"profile": name, "network": network, "bps": bps, "decimals": DECIMALS,
|
||||
"is_mainnet_contract": name == "mainnet",
|
||||
"genesis_daa_score": 0,
|
||||
"time_key": "seconds = floor(daa_score / bps); the per-block subsidy is constant inside a DAA second",
|
||||
"phases": phases,
|
||||
"phase_count": len(phases),
|
||||
"last_nonzero_phase": {"index": last_nonzero["index"], "per_block_subsidy": last_nonzero["per_block_subsidy"],
|
||||
"start_daa_score": last_nonzero["start_daa_score"], "end_daa_score": last_nonzero["end_daa_score"]},
|
||||
"transition_count": len(phases) - 1,
|
||||
"last_paying_daa_score": term["start_daa_score"] - 1,
|
||||
"last_paying_block_height": term["start_daa_score"],
|
||||
"terminal_supply": str(total),
|
||||
"terminal": {"start_daa_score": term["start_daa_score"], "first_unpaid_block_height": term["start_daa_score"] + 1, "decay_step": term["decay_step"],
|
||||
"start_year": f["terminal_year"], "behaviour": "per-block subsidy 0 at every later DAA score; the cap is never reached; blocks are paid by fees alone"},
|
||||
"total_issuance": str(total),
|
||||
"cap_shortfall": str(CAP - total),
|
||||
"scheduled_supply_at_year_end": years,
|
||||
})
|
||||
|
||||
# the block-rate step demonstration (C04) and the compiled genesis offset (C09)
|
||||
step_daa = YEAR_SECONDS * DEVNET4_BPS
|
||||
fig["bps_step"] = {"step_daa": step_daa, "issued": bps_step_overshoot(step_daa, 1, 10, fig["mainnet"]["total"])}
|
||||
ph10, _ = schedule(MAINNET_BPS)
|
||||
off = MAINNET_GENESIS_DAA_COMPILED
|
||||
s0 = off // MAINNET_BPS
|
||||
num = RAMP_START_PERCENT * RAMP_SECONDS + (100 - RAMP_START_PERCENT) * s0
|
||||
fig["genesis_offset"] = {"issuance_lost": supply_at(ph10, off, MAINNET_BPS),
|
||||
"first_ramp_percent": f"{num * 100 // (100 * RAMP_SECONDS)}.{(num * 10000 // (100 * RAMP_SECONDS)) % 100:02d}%"}
|
||||
|
||||
dump_check = None
|
||||
if a.code_dump:
|
||||
raw = open(a.code_dump, "rb").read()
|
||||
rows = [json.loads(l) for l in raw.decode().splitlines() if l.strip()]
|
||||
n = 0
|
||||
for prof in profiles:
|
||||
net = prof["profile"]
|
||||
head = next(r for r in rows if r.get("network") == net and "bps" in r)
|
||||
assert head["bps"] == prof["bps"] and head["decimals"] == DECIMALS and int(head["launch_rate"]) == LAUNCH_RATE
|
||||
assert head["ramp_seconds"] == RAMP_SECONDS and head["step_seconds"] == STEP_SECONDS and head["step_decay_q32"] == STEP_DECAY_Q32 and head["tail"] == "cap"
|
||||
rp = next(r for r in rows if r.get("network") == net and r.get("phase") == "ramp")
|
||||
p0 = prof["phases"][0]
|
||||
assert int(rp["sum"]) == int(p0["phase_sum"]) and rp["first_block"] == p0["ramp"]["first_block"] and rp["last_block"] == p0["ramp"]["last_block"] and rp["end_daa"] == p0["end_daa_score"]
|
||||
steps = [r for r in rows if r.get("network") == net and r.get("phase") == "step"]
|
||||
for r, p in zip(steps, prof["phases"][1:]):
|
||||
assert r["start_daa"] == p["start_daa_score"], (net, r, p)
|
||||
assert r["per_block"] == p["per_block_subsidy"], (net, r, p)
|
||||
assert int(r["rate_per_second"]) == int(p["rate_per_second"]), (net, r, p)
|
||||
if p["kind"] == "constant":
|
||||
assert r["end_daa"] == p["end_daa_score"] and r["sum"] == p["phase_sum"], (net, r, p)
|
||||
n += 1
|
||||
assert len(steps) == len(prof["phases"]) - 1, (net, len(steps), len(prof["phases"]))
|
||||
tot = next(r for r in rows if r.get("network") == net and "total" in r)
|
||||
assert int(tot["total"]) == int(prof["total_issuance"]) and int(tot["cap"]) == CAP and int(tot["shortfall"]) == int(prof["cap_shortfall"])
|
||||
assert head["genesis_daa_score"] == (MAINNET_GENESIS_DAA_COMPILED if net == "mainnet" else 0)
|
||||
t1 = next(r for r in rows if r.get("network") == "testnet-1" and "bps" in r)
|
||||
assert t1["tail"] == "percent:100"
|
||||
dump_check = {"path": "tools/token-value/tv-01/code-dump/schedule-bf60948a.jsonl", "sha256": hashlib.sha256(raw).hexdigest(),
|
||||
"program": "tools/token-value/tv-01/code-dump/tv01_schedule.rs.txt",
|
||||
"run": "build-9, release-2.0.3-node-k6 bf60948a: cargo run --release -p kaspa-consensus-core --example tv01_schedule (the program copied into consensus/core/examples of a scratch tree; the node fork is unchanged)",
|
||||
"agreement": f"every field of {n} decay phases, both ramps and both totals equal to this generator's integers"}
|
||||
|
||||
spec = {
|
||||
"schema": {
|
||||
"name": "igneum-supply-spec", "version": "1.0.0",
|
||||
"integers": "every amount is a decimal string of base units (amounts reach 4 x 10^27, past JSON's exact range); DAA scores are JSON integers (all under 2^53)",
|
||||
"phase_fields": {"index": "0-based, contiguous", "kind": "ramp | constant | terminal", "rule": "the rule's name", "start_daa_score": "inclusive", "end_daa_score": "exclusive; null for the terminal phase", "per_block_subsidy": "base units per block at every DAA score of the phase (null for the ramp, whose per-block value is its formula)", "phase_sum": "base units the phase issues at one subsidy per DAA score", "source": "file:line in the node fork at both named revisions"},
|
||||
"checker": "tools/token-value/tv-01/check-spec.py",
|
||||
},
|
||||
"gate": "TV-01", "verdict": "NOT RUN",
|
||||
"status": "Phase 0 document. Activates nothing; changes no node, no chain and no served page. The verdict stays NOT RUN until the independent panel reads it.",
|
||||
"decision": {"id": "D01", "title": "Cap and tail", "ruling": "capped issuance, subject to TV-04 (the founder's ratification, 9 October 2026, 09:2x UK)",
|
||||
"effect": "the cap is the invariant; the litepaper's year-five tail-vote sentence is superseded (C01)"},
|
||||
"invariant": {"rule": "sum over all blocks of the per-block subsidy <= cap, with no tail, no vote, no price or revenue trigger and no emergency mint",
|
||||
"how_enforced": "by the schedule, not by a running counter: every block's coinbase must carry exactly the scheduled subsidy (coinbase.rs:262) and the EVM state credits by the same rule (executor.rs:181 to 211); the cap constant itself is only compared in tests (igneum.rs:154). The schedule sums to the cap minus the shortfall below, so the cap is never reached.",
|
||||
"change_policy": "the schedule is a compiled genesis parameter on mainnet; the daemon refuses an override file there (kaspad/src/daemon.rs, network.rs:266); a change is a new release with a new consensus digest and an explicit incompatible-policy process (VR-06)"},
|
||||
"units": {"coin": "IGN", "base_unit": "wei (one consensus base unit is one EVM wei)", "decimals": DECIMALS, "base_units_per_coin": str(UNIT),
|
||||
"source": ["consensus/core/src/unit.rs:38", "consensus/core/src/config/params.rs:1816"]},
|
||||
"cap": {"base_units": str(CAP), "coins": "4000000000", "kind": "invariant",
|
||||
"source": ["consensus/core/src/igneum.rs:37", "consensus/core/src/igneum.rs:154"]},
|
||||
"rules": {
|
||||
"launch_rate_per_second": str(LAUNCH_RATE), "launch_rate_note": "floor(10^9 x 10^8 / 31,557,600) = 3,168,808,781 at 8 decimals, times 10^10: 31.68808781 IGN a DAA second",
|
||||
"year_seconds": YEAR_SECONDS, "ramp_seconds": RAMP_SECONDS, "ramp_start_percent": RAMP_START_PERCENT,
|
||||
"step_seconds": STEP_SECONDS, "step_decay_q32": STEP_DECAY_Q32, "decay_rule": "rate[k+1] = floor(rate[k] x step_decay_q32 / 2^32) (a halving every two years)",
|
||||
"per_block": "per_block(d) = ramp(floor(rate[floor(s / step_seconds)] / bps), s), s = floor(d / bps)",
|
||||
"tail": "cap",
|
||||
"genesis_rule": {"rule": "genesis-unrewarded",
|
||||
"text": "the genesis block is never rewarded: it never enters the DAA window (window.rs:177), the coinbase pays only the mergeset blues inside the DAA window (coinbase.rs:139), and the genesis coinbase has no outputs (genesis.rs:26). A block's DAA score counts its DAA-window mergeset, so on a chain the block at height h >= 1 carries DAA score h - 1: DAA score 0 is the first paid block and every schedule below is indexed by DAA score, not height",
|
||||
"height_of_daa_score": "height = DAA score + 1 (a chain of blocks; in the DAG several blocks may share a DAA score)",
|
||||
"source": ["consensus/src/processes/window.rs:177", "consensus/src/processes/coinbase.rs:139", "consensus/core/src/config/genesis.rs:26"]},
|
||||
"source": ["consensus/core/src/emission.rs:103 to 110", "consensus/core/src/emission.rs:225", "consensus/core/src/emission.rs:316 to 333", "consensus/core/src/config/params.rs:1858"],
|
||||
},
|
||||
"activation_clocks": {
|
||||
"genesis": "DAA score 0 (C09: the compiled mainnet genesis still carries Kaspa's 1,312,860; BLOCKED)",
|
||||
"ramp_end": {"mainnet": RAMP_SECONDS * MAINNET_BPS, "devnet-4": RAMP_SECONDS * DEVNET4_BPS, "seconds": RAMP_SECONDS},
|
||||
"halvings": "every 63,115,200 DAA seconds (2 years of 365.25 days): DAA score k x 631,152,000 at 10 blocks/s, k x 63,115,200 at 1 block/s",
|
||||
"terminal": {"mainnet": fig["mainnet"]["terminal_daa"], "devnet-4": fig["devnet-4"]["terminal_daa"]},
|
||||
"signing_bonus": "mainnet never (params.rs:1809); testnet-1 from 0",
|
||||
"pool_split": "mainnet never (params.rs:1851)",
|
||||
"per_block_rule_N8": "mainnet never (params.rs:1812; C08 BLOCKED); testnet-1 from 0",
|
||||
},
|
||||
"contract_profile": "mainnet",
|
||||
"contract_profile_note": "mainnet's schedule (MAINNET_PARAMS, params.rs:1858, 10 blocks a second) is the monetary contract under the 4,000,000,000 cap; the Devnet 4 profile (params.rs:2372, 1 block a second, 18 decimals) is the same per-second curve, carried because it is the chain TV-02 replays and the litepaper's launch rate (C04)",
|
||||
"schedules": profiles,
|
||||
"coinbase_split": [
|
||||
{"rule": "producer and proving pool", "producer": "subsidy - floor(subsidy x 20 / 100)", "proving_pool": "floor(subsidy x 20 / 100)", "source": ["consensus/core/src/igneum.rs:44", "consensus/core/src/igneum.rs:201 to 208"]},
|
||||
{"rule": "signing bonus", "effect": "a silent producer's share loses floor(share x 1,000 / 10,000) to the proving pool; nothing destroyed; fees untouched", "mainnet": "off (never)", "source": ["consensus/core/src/igneum.rs:110", "consensus/core/src/config/params.rs:1809 to 1810"]},
|
||||
{"rule": "native ledger", "effect": "the EVM state credits the producer share to the block's IGNA address (or by its IGNW split once pool_split is active) and the pool share to escrow 0x0000000000000000000000000000000000000220, blue blocks only", "source": ["igneum/exec/src/executor.rs:181 to 211", "igneum/exec/src/config.rs:59"]},
|
||||
{"rule": "shadow ledger", "effect": "the UTXO coinbase pays the producer outputs and one OP_RETURN pool output tagged igneum-proving-pool-v0; no UTXO transaction but the coinbase is valid, so none of it is ever spent", "source": ["consensus/src/processes/coinbase.rs:126 to 168", "consensus/src/pipeline/body_processor/body_validation_in_isolation.rs:54"]},
|
||||
{"rule": "pool", "effect": "none in consensus; the reference pool keeps fee_percent (default 1.0) of the 80% it receives and pays members PPLNS from its address", "source": ["pool/src/payout.rs:1 to 6", "pool/src/config.rs:58", "pool/src/pplns.rs:76"]},
|
||||
{"rule": "dev fee", "effect": "none in consensus; the miner software requests 1 template in 100 with the dev address (off with --dev-fee 0); it moves the producer share of those blocks, creates nothing", "source": ["site/litepaper.html:625"]},
|
||||
{"rule": "treasury, foundation, team, stake", "effect": "none: no output, credit or address in consensus", "source": ["consensus/src/processes/coinbase.rs:126 to 168", "igneum/exec/src/executor.rs:181 to 211"]},
|
||||
{"rule": "genesis", "effect": "the genesis coinbase has no outputs; its payload subsidy field is data; no premine", "source": ["consensus/core/src/config/genesis.rs:26"]},
|
||||
],
|
||||
"fees": [
|
||||
{"route": "execution base fee", "effect": "burned (not credited)", "source": "igneum/exec/src/executor.rs:319 to 321"},
|
||||
{"route": "proving charge (proving base fee)", "effect": "burned in full today; the 90% route to provers is designed (docs/design/proving-payment.md, node branch proving-payment 930b6322), not merged, no activation scheduled", "source": "igneum/exec/src/executor.rs:319 to 321, :361"},
|
||||
{"route": "priority fee", "effect": "80% to the block's miner; 20% to the payees registered for the frames' code by own gas, unregistered parts burned", "source": "igneum/exec/src/executor.rs:362 to 371; igneum/exec/src/pgas.rs:290"},
|
||||
{"route": "external job after the proof bridge", "effect": "not in code (Designed, phase two): 90% provers, 10% burned per the litepaper", "source": "site/litepaper.html:624"},
|
||||
],
|
||||
"supply_accounting": {
|
||||
"issued": "the EVM state's subsidy credits (producer plus escrow), blue blocks only; bounded above by the schedule's per-DAA-score sum",
|
||||
"burned": "execution base fees, proving charges and unregistered developer shares (EVM side); the UTXO OP_RETURN output is NOT counted as a burn (C06)",
|
||||
"locked": "the proving escrow's balance: credited, not yet paid against a valid proof; unclaimed credit is stranded today (litepaper line 609, no rule returns it)",
|
||||
"not_supply": "UTXO coinbase outputs (unspendable shadow record); any bridged or wrapped IGN on another chain (VR-02)",
|
||||
"replay_model": "one scheduled subsidy per DAA score (the schedules above); a block is paid at its own DAA score, parallel blocks may share a score and a score may have no block, so the measured issuance differs from the model only near phase boundaries and only by the blocks merged across them; TV-02 reconciles the measured ledgers to this model in exact integers",
|
||||
},
|
||||
"superseded": [
|
||||
{"text": TAIL_SENTENCE, "where": "site/litepaper.html:630 at " + LITEPAPER_SUPERSEDED_REV, "by": "D01 (capped issuance, subject to TV-04)", "status": "SUPERSEDED", "text_now": "rewritten by the site lane at ad64e48fa (C01)"},
|
||||
{"text": "The priority fee splits two ways: 80% to the miner and provers of that block, 20% to the apps whose code ran", "where": "site/litepaper.html:614 (and the route table at :622)", "by": "O-5.7 closed at zero, 8 October 2026 (docs/spec/05-fees-and-economics.md line 24); the code pays the tip's 80% to the miner alone", "status": "SUPERSEDED"},
|
||||
],
|
||||
"conflicts": conflicts(fig),
|
||||
"sources": {
|
||||
"volume": {"path": "docs/plans/igneum-2.0-master/token-value/rules-and-gates.json", "sha256": hashlib.sha256(read_igneum(a.igneum_root, igneum_rev, "docs/plans/igneum-2.0-master/token-value/rules-and-gates.json")).hexdigest()},
|
||||
"litepaper": {"path": "site/litepaper.html", "igneum_commit": igneum_rev, "sha256": files["igneum:site/litepaper.html"]["igneum master"],
|
||||
"superseded_text_commit": LITEPAPER_SUPERSEDED_REV, "superseded_text_sha256": files["igneum-old:site/litepaper.html"]["igneum before ad64e48fa"]},
|
||||
"node": {"repo": "igneum-node (build-1:/srv/igneum-node.git)", "revisions": NODE_REVS,
|
||||
"files": {k.split(":", 1)[1]: v for k, v in sorted(files.items()) if k.startswith("node:")},
|
||||
"note": "every cited line carries its anchor at all four revisions (the generator refuses otherwise); the shipped 2.0.2 commit 5d53a591 and the 2.0.3 lines k6 and k7 change no issuance rule"},
|
||||
"pool": {k.split(":", 1)[1]: v["igneum master"] for k, v in sorted(files.items()) if k.startswith("igneum:pool/")},
|
||||
"design": {k.split(":", 1)[1]: v["igneum master"] for k, v in sorted(files.items()) if k.startswith("igneum:docs/")},
|
||||
"citations": cites,
|
||||
"code_dump": dump_check,
|
||||
},
|
||||
"generator": {"path": "tools/token-value/tv-01/gen-spec.py",
|
||||
"command": "python3 tools/token-value/tv-01/gen-spec.py --node-git <igneum-node clone holding both revisions> --igneum-root . --igneum-rev " + igneum_rev + " --code-dump tools/token-value/tv-01/code-dump/schedule-bf60948a.jsonl --out docs/plans/igneum-2.0-master/token-value/phase0/tv-01/supply-spec.json --md docs/plans/igneum-2.0-master/token-value/phase0/tv-01/supply-spec.md"},
|
||||
}
|
||||
# every litepaper quote in the conflicts table is exact (tags stripped, entities decoded) or nothing is written
|
||||
import html as _html, re as _re
|
||||
lps = {}
|
||||
def lp_line(rev, ln):
|
||||
if rev not in lps:
|
||||
lps[rev] = read_igneum(a.igneum_root, rev, "site/litepaper.html").decode("utf-8").split("\n")
|
||||
return _html.unescape(_re.sub("<[^>]+>", "", lps[rev][ln - 1]))
|
||||
for c in spec["conflicts"]:
|
||||
rev = c["litepaper"].get("rev", igneum_rev)
|
||||
for lk, wk in (("line", "words"), ("line_2", "words_2")):
|
||||
ln = c["litepaper"].get(lk)
|
||||
if ln and c["litepaper"][wk] not in lp_line(rev, ln):
|
||||
sys.exit(f"{c['id']}: the litepaper's line {ln} at {rev[:9]} does not carry the quoted words exactly")
|
||||
now = c["litepaper"].get("now_reads")
|
||||
if now and now["words"] not in lp_line(igneum_rev, now["line"]):
|
||||
sys.exit(f"{c['id']}: the current litepaper line {now['line']} does not carry the quoted words")
|
||||
if now:
|
||||
now["rev"] = igneum_rev
|
||||
c["litepaper"].setdefault("rev", igneum_rev)
|
||||
with open(a.out, "w", encoding="utf-8") as fh:
|
||||
json.dump(spec, fh, indent=1, ensure_ascii=False)
|
||||
fh.write("\n")
|
||||
|
||||
if a.md:
|
||||
m, d = profiles[0], profiles[1]
|
||||
L = ["<!-- figures:begin (generated by tools/token-value/tv-01/gen-spec.py; do not edit by hand) -->", ""]
|
||||
L.append("| Figure | Mainnet as compiled (10 blocks/s) | Devnet 4 (1 block/s) |")
|
||||
L.append("|---|---|---|")
|
||||
L.append(f"| Cap | {coins(CAP)} IGN ({CAP} base units) | the same |")
|
||||
L.append(f"| Total scheduled issuance | {coins(int(m['total_issuance']))} IGN | {coins(int(d['total_issuance']))} IGN |")
|
||||
L.append(f"| Shortfall under the cap (exact) | {m['cap_shortfall']} base units ({coins(int(m['cap_shortfall']))} IGN) | {d['cap_shortfall']} base units ({coins(int(d['cap_shortfall']))} IGN) |")
|
||||
L.append(f"| Ramp phase | DAA 0 to {m['phases'][0]['end_daa_score']:,}, {coins(int(m['phases'][0]['phase_sum']))} IGN | DAA 0 to {d['phases'][0]['end_daa_score']:,}, {coins(int(d['phases'][0]['phase_sum']))} IGN |")
|
||||
L.append(f"| First block | {coins(int(m['phases'][0]['ramp']['first_block']))} IGN | {coins(int(d['phases'][0]['ramp']['first_block']))} IGN |")
|
||||
L.append(f"| Full-rate block (after the ramp) | {coins(int(m['phases'][1]['per_block_subsidy']))} IGN | {coins(int(d['phases'][1]['per_block_subsidy']))} IGN |")
|
||||
L.append(f"| Phases (ramp, constant, terminal) | {m['phase_count']} | {d['phase_count']} |")
|
||||
L.append(f"| Last non-zero subsidy | {m['last_nonzero_phase']['per_block_subsidy']} base unit a block, DAA {m['last_nonzero_phase']['start_daa_score']:,} to {m['last_nonzero_phase']['end_daa_score']:,} | {d['last_nonzero_phase']['per_block_subsidy']} base unit a block, DAA {d['last_nonzero_phase']['start_daa_score']:,} to {d['last_nonzero_phase']['end_daa_score']:,} |")
|
||||
L.append(f"| Terminal (zero for ever) from | DAA {m['terminal']['start_daa_score']:,} (decay step {m['terminal']['decay_step']}, year {m['terminal']['start_year'] + 1}) | DAA {d['terminal']['start_daa_score']:,} (decay step {d['terminal']['decay_step']}, year {d['terminal']['start_year'] + 1}) |")
|
||||
for y in ["1", "2", "5", "10", "12", "20", "50", "100"]:
|
||||
L.append(f"| Scheduled supply at the end of year {y} | {coins(int(m['scheduled_supply_at_year_end'][y]))} IGN | {coins(int(d['scheduled_supply_at_year_end'][y]))} IGN |")
|
||||
L.append(f"| A 1-to-10 blocks/s step at DAA {fig['bps_step']['step_daa']:,} under the current code | total {coins(fig['bps_step']['issued'])} IGN, {coins(fig['bps_step']['issued'] - CAP)} IGN over the cap | |")
|
||||
L.append(f"| The compiled mainnet genesis (DAA 1,312,860) | first ramp block at {fig['genesis_offset']['first_ramp_percent']}; {coins(fig['genesis_offset']['issuance_lost'])} IGN never scheduled | |")
|
||||
L.append("")
|
||||
if dump_check:
|
||||
L.append(f"Code agreement: {dump_check['agreement']} (dump sha256 `{dump_check['sha256']}`).")
|
||||
L.append("")
|
||||
L.append("<!-- figures:end -->")
|
||||
txt = open(a.md).read()
|
||||
b, e = txt.index("<!-- figures:begin"), txt.index("<!-- figures:end -->") + len("<!-- figures:end -->")
|
||||
with open(a.md, "w") as fh:
|
||||
fh.write(txt[:b] + "\n".join(L) + txt[e:])
|
||||
print(f"wrote {a.out}: mainnet total {fig['mainnet']['total']}, shortfall {CAP - fig['mainnet']['total']}; devnet-4 total {fig['devnet-4']['total']}; code dump {'agrees' if dump_check else 'not given'}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -332,8 +332,10 @@ function renderCrew() {
|
|||
for (const pc of pcs) {
|
||||
const r = pc.running;
|
||||
const pcAge = pc.report_age_s === undefined || pc.report_age_s === null ? pcsAge : pc.report_age_s;
|
||||
const pcAgeText = pcAge === null ? 'report age unknown' : `report ${fmtDurShort(pcAge)} old${pcAge > 600 ? ', STALE' : ''}${pc.source === 'intake' ? ', from the PC' : ''}`;
|
||||
cards.push(`<div class="w"><div class="top"><div><div class="card">${esc(pc.name)}</div><div class="meta">${esc(pc.machine || pc.id)} · ${esc(pc.role)} · <span ${pcAge !== null && pcAge > 600 ? 'style="color:var(--warn)"' : ''}>${esc(pcAgeText)}</span></div></div>${pill(r ? 'running' : pc.queue.length ? 'queued' : 'idle', r ? 'running' : pc.queue.length ? 'queued' : '')}</div><div class="doing">${pcReportLine(pc) ? pcReportLine(pc) + '<br>' : ''}${r ? `${esc(r.kind)} ${esc(r.job)}${r.title ? '<br>' + esc(r.title) : ''}${r.stage ? `<br><span class="pill">stage ${esc(r.stage)}</span>` : ''}` : pc.queue.length ? `Next: ${esc(pc.queue[0].kind)} ${esc(pc.queue[0].job)}${pc.queue[0].title ? ', ' + esc(pc.queue[0].title) : ''}` : esc(pc.note || 'idle on jobs; the relay polls every 10 min')}</div><div class="foot"><span>${pc.recent.length} reports kept</span><span>${pc.last_report_at ? 'last report ' + esc(ago(pc.last_report_at)) : 'no report in 7 days'}</span></div></div>`);
|
||||
// a rig card reads "agent not reporting since <time>" until a report arrives through the intake (the coordinator, 9 October 2026)
|
||||
const pcLast = pc.collected_at || (D.pcs && D.pcs.collected_at) || null;
|
||||
const pcAgeText = pc.source === 'intake' ? (pcAge === null ? 'report age unknown' : `report ${fmtDurShort(pcAge)} old${pcAge > 600 ? ', STALE' : ''}, from the rig`) : pc.source === 'none' ? 'no report yet' : `agent not reporting since ${pcLast ? esc(ukTime(pcLast)) : 'an unknown time'}`;
|
||||
cards.push(`<div class="w"><div class="top"><div><div class="card">${esc(pc.name)}</div><div class="meta">${esc(pc.machine || pc.id)} · ${esc(pc.role)} · <span ${(pc.source !== 'intake') || (pcAge !== null && pcAge > 600) ? 'style="color:var(--warn)"' : ''}>${pcAgeText}</span></div></div>${pill(r ? 'running' : pc.queue.length ? 'queued' : 'idle', r ? 'running' : pc.queue.length ? 'queued' : '')}</div><div class="doing">${pcReportLine(pc) ? pcReportLine(pc) + '<br>' : ''}${r ? `${esc(r.kind)} ${esc(r.job)}${r.title ? '<br>' + esc(r.title) : ''}${r.stage ? `<br><span class="pill">stage ${esc(r.stage)}</span>` : ''}` : pc.queue.length ? `Next: ${esc(pc.queue[0].kind)} ${esc(pc.queue[0].job)}${pc.queue[0].title ? ', ' + esc(pc.queue[0].title) : ''}` : esc(pc.note || 'idle on jobs; the relay polls every 10 min')}</div><div class="foot"><span>${pc.recent.length} reports kept</span><span>${pc.last_report_at ? 'last report ' + esc(ago(pc.last_report_at)) : 'no report in 7 days'}</span></div></div>`);
|
||||
}
|
||||
if (!pcs.length) cards.push(`<div class="w"><div class="top"><div><div class="card">rig 1 and rig 2</div><div class="meta">relay jobs</div></div>${pill('no data', 'error')}</div><div class="doing">${esc(D.sources && D.sources.pcs && D.sources.pcs.error || 'the Mac pusher reads the relay intake; nothing has arrived')}</div></div>`);
|
||||
$('crew').innerHTML = cards.join('');
|
||||
|
|
|
|||
Loading…
Reference in a new issue