Merge master 06eec5ad8 into ci-hashes-paths under the master-landing lock
This commit is contained in:
commit
34edde3cda
22 changed files with 1769 additions and 14 deletions
208
docs/plans/igneum-2.0-master/token-value/phase0/d02/README.md
Normal file
208
docs/plans/igneum-2.0-master/token-value/phase0/d02/README.md
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
# D02, the same-cap emission comparison (Token Value Phase 0)
|
||||
|
||||
Status: NOT RUN. A model, landed as a document and its tests; nothing activates. The founder's ratification of D02 (9 October 2026, 09:2x UK): "the same-cap emission comparison approved, the schedule pending evidence". This document is that evidence. It picks no schedule. Every figure below is printed by the generator; none is typed by hand. Generated file: edit `tools/token-value/d02/README.template.md` and rerun the generator, never this file.
|
||||
|
||||
## Sources
|
||||
|
||||
| source | identity |
|
||||
|---|---|
|
||||
| the volume, `docs/plans/igneum-2.0-master/token-value/igneum-2.0-token-value.pdf` (D02, p. 13 "Choose distribution deliberately", p. 73 the decision register) | sha256 `b79d295c99d9cf0a121b62efdc6743e7282a0d2de33a98f6811616afcbcaeaee` |
|
||||
| `docs/plans/igneum-2.0-master/token-value/rules-and-gates.json` (D02, TV-01, TV-03, TV-04) | sha256 `10ce307329e1663dcb6dce849317c9276c19252de5f483e9ee06015fc77cbe3d` |
|
||||
| the node fork igneum-node, `release-2.0.2-node` | commit `a284380bdd62d5d0d972cb38f2cbd1daeedda69d` |
|
||||
| `consensus/core/src/emission.rs` (EmissionSchedule, EmissionTable: the rule replayed here) | blob `3bb54489588836f58d91a166558f5a4af22205bb` |
|
||||
| `consensus/core/src/igneum.rs` (the cap, the year-one emission, the 20 percent proving share) | blob `ac914b7ef3dbeea6f861a8b82b16415bbe7f33c7` |
|
||||
| `consensus/core/src/config/params.rs` (MAINNET_PARAMS.emission = CURRENT rescaled to 18 decimals) | blob `d0ebf9bb3951ffafbdd9a3d9d0600537229ea710` |
|
||||
| `consensus/core/src/unit.rs` (8 and 18 decimals) | blob `6af7040f07b939e71f8930090f01d022c6136e87` |
|
||||
| `site/litepaper.html` on master at this landing | blob `ad11eaf29ca1f725a35dda3c7f4060dbf1fce509` |
|
||||
| TV-01's supply spec, `docs/plans/igneum-2.0-master/token-value/phase0/tv-01/supply-spec.json` | not landed at this version (BLOCKED row B1) |
|
||||
|
||||
## What D02 asks
|
||||
|
||||
The volume's decision register: compare the existing schedule with slower distribution before launch, and include delayed ordinary entrants and the dilution and security trade-offs. Its p. 13 names three model branches. This document models the first two. The third, a continuing subsidy, is a different supply proposition and is outside a same-cap comparison.
|
||||
|
||||
| branch (the volume, p. 13) | what it says to compare | modelled here as |
|
||||
|---|---|---|
|
||||
| Current proposed pacing | the exact compiled schedule, early concentration, first-year reward budget, later fee dependence | A, read from the node's code |
|
||||
| Longer distribution, same cap | reallocate timing without founder reserves; lower early subsidy and a longer participation opportunity | B, the literal instance (below), and C, this lane's alternative |
|
||||
|
||||
The volume names the shape of the longer branch and no number. B is its literal reading: the same curve, the same cap, the same ramp and terminal rule, with only the time axis stretched (x2). Nothing is reserved for anyone; every coin is still subsidy to miners and provers. C is this lane's own alternative, stated as such: the same cap reached by a smooth monthly glide with a 4-year half-life, so the subsidy never halves overnight. Both B and C are parameter sets of the node's existing `EmissionSchedule` (no new consensus code), valid under its `validate` rule.
|
||||
|
||||
## Method
|
||||
|
||||
- The generator replays `EmissionTable::build`, `scheduled_supply_at`, `rate_at`, `ramp` and `block_subsidy` from emission.rs line for line, in integer arithmetic, at mainnet's unit (18 decimals). The node's own Rust prints the same bytes for every schedule (the cross-check below).
|
||||
- A year is 31,557,600 DAA seconds (365.25 days, emission.rs `YEAR_SECONDS`). Year y is DAA seconds [(y - 1) x year, y x year). Emission is keyed to DAA time, so a calendar year equals a schedule year within the accuracy of the difficulty controller.
|
||||
- Every schedule carries the 30-day launch ramp from 10 percent and `Tail::Cap`: the curve runs to zero and its sum, less the ramp's withheld coins and the integer floors, is the scheduled total, never above the 4,000,000,000 IGN cap.
|
||||
- The split is the consensus split: 80 percent of each block's subsidy to the block's producer and 20 percent to the proving escrow (igneum.rs `PROVING_POOL_SHARE_PERCENT`). It is applied to each year's total; the per-block floor moves at most one base unit a block toward the producer, and the signing bonus moves part of a silent block's producer share to the pool without changing the total.
|
||||
- Per-block figures are at 1 block a second. Mainnet's params carry the inherited block-rate activation (`crescendo_activation`); a faster block rate divides every per-block figure by the same factor for every schedule, so the shares in the late-miner table do not move.
|
||||
- No price appears. Every amount is native IGN or base units.
|
||||
- Fee dependence uses a reference security budget of 1 percent of the cap a year (40M IGN), a stated yardstick and not a cost estimate, scaled by TV-04's revenue multiples (0.25x / 1x / 4x / 10x). "Fees needed" is the first year the subsidy alone falls under the budget; "fees exceed subsidy" is the first year the subsidy falls under half of it, after which fees must pay more than the subsidy for the budget to hold. Both read the subsidy's decline alone. The fee series is a parameter, never a forecast: `--fee-flat-ign N --fee-growth-bps G` prints the first year the subsidy plus that series falls under each budget. TV-04's own budget replaces the yardstick when it lands (BLOCKED row B2).
|
||||
- The volume defines no Gini-style cohort measure, so concentration is the share of the cap issued by each horizon and the share issued in years 1 to 2 against years 3 to 20.
|
||||
|
||||
## The schedules as code
|
||||
|
||||
The three parameter sets, as `consensus/core/src/emission.rs` `EmissionSchedule` literals at mainnet's unit (printed by the generator from its own schedule functions):
|
||||
|
||||
```rust
|
||||
// A: current pacing (release-2.0.2 mainnet)
|
||||
// EmissionSchedule::CURRENT.rescaled(8, 18): two-year halving cliffs, 30-day ramp from 10%, Tail::Cap
|
||||
EmissionSchedule {
|
||||
launch_rate: 31_688_087_810_000_000_000,
|
||||
ramp_seconds: 2_592_000,
|
||||
ramp_start_percent: 10,
|
||||
step_seconds: 63_115_200,
|
||||
step_decay_q32: 2_147_483_648,
|
||||
tail: Tail::Cap,
|
||||
}
|
||||
|
||||
// B: longer distribution, same cap (the volume; time axis x2)
|
||||
// the current curve on a time axis x2: launch rate / 2, halving every 4 years, same ramp, Tail::Cap
|
||||
EmissionSchedule {
|
||||
launch_rate: 15_844_043_900_000_000_000,
|
||||
ramp_seconds: 2_592_000,
|
||||
ramp_start_percent: 10,
|
||||
step_seconds: 126_230_400,
|
||||
step_decay_q32: 2_147_483_648,
|
||||
tail: Tail::Cap,
|
||||
}
|
||||
|
||||
// C: smooth glide, same cap (this lane's alternative)
|
||||
// monthly steps, multiplier 2^(-1/48) in Q32 (a 4-year half-life), launch rate set so the curve sums to the cap, same ramp, Tail::Cap
|
||||
EmissionSchedule {
|
||||
launch_rate: 21_806_679_390_000_000_000,
|
||||
ramp_seconds: 2_592_000,
|
||||
ramp_start_percent: 10,
|
||||
step_seconds: 2_629_800,
|
||||
step_decay_q32: 4_233_391_203,
|
||||
tail: Tail::Cap,
|
||||
}
|
||||
```
|
||||
|
||||
| key | schedule | launch rate (base units a DAA second) | launch rate a year (IGN) | step (DAA s) | step multiplier (Q32) | curve steps | subsidy zero from year | scheduled total (IGN) | cap minus total (IGN) |
|
||||
|---|---|---|---|---|---|---|---|---|---|
|
||||
| A | current pacing (release-2.0.2 mainnet) | 31,688,087,810,000,000,000 | 1,000.0M | 63,115,200 (2 years) | 2,147,483,648 | 66 | 131 | 3,963,039,000 | 36,961,000 |
|
||||
| B | longer distribution, same cap (the volume; time axis x2) | 15,844,043,900,000,000,000 | 500.0M | 126,230,400 (4 years) | 2,147,483,648 | 65 | 257 | 3,981,519,498 | 18,480,502 |
|
||||
| C | smooth glide, same cap (this lane's alternative) | 21,806,679,390,000,000,000 | 688.2M | 2,629,800 (1 month) | 4,233,391,203 | 2831 | 236 | 3,974,564,679 | 25,435,321 |
|
||||
|
||||
## 1. Issued supply and its share of the cap, at the end of each year
|
||||
|
||||
| schedule | year 1 | year 2 | year 5 | year 10 | year 20 |
|
||||
|---|---|---|---|---|---|
|
||||
| A | 963.0M (24.08%) | 1,963.0M (49.08%) | 3,213.0M (80.33%) | 3,838.0M (95.95%) | 3,959.1M (98.98%) |
|
||||
| B | 481.5M (12.04%) | 981.5M (24.54%) | 2,231.5M (55.79%) | 3,231.5M (80.79%) | 3,856.5M (96.41%) |
|
||||
| C | 611.0M (15.27%) | 1,146.1M (28.65%) | 2,292.8M (57.32%) | 3,267.5M (81.69%) | 3,849.6M (96.24%) |
|
||||
|
||||
Meaning: by the end of year 2 the current pacing has issued 49% of the cap against 25% under B and 29% under C, so a later arrival holds a smaller share of an early-issued supply under A. By year 20 the three stand at 99.0%, 96.4% and 96.2% of the cap.
|
||||
|
||||
## 2. Yearly issuance
|
||||
|
||||
| schedule | year 1 | year 2 | year 5 | year 10 | year 20 |
|
||||
|---|---|---|---|---|---|
|
||||
| A | 963.0M (24.08% of cap) | 1,000.0M (25.00% of cap) | 250.0M (6.25% of cap) | 62.5M (1.56% of cap) | 2.0M (0.05% of cap) |
|
||||
| B | 481.5M (12.04% of cap) | 500.0M (12.50% of cap) | 250.0M (6.25% of cap) | 125.0M (3.12% of cap) | 31.2M (0.78% of cap) |
|
||||
| C | 611.0M (15.27% of cap) | 535.2M (13.38% of cap) | 318.2M (7.96% of cap) | 133.8M (3.34% of cap) | 23.7M (0.59% of cap) |
|
||||
|
||||
Meaning: A's yearly issuance falls to 50% of the year before at each two-year boundary, while C's falls to 84.1% of the year before, every year, with no cliff.
|
||||
|
||||
## 3. Early security income (subsidy paid to miners and provers, IGN)
|
||||
|
||||
| schedule | year 1 subsidy (IGN) | to miners | to provers | of A's year 1 | years 1 to 5 (IGN) | to miners | to provers | of A's years 1 to 5 |
|
||||
|---|---|---|---|---|---|---|---|---|
|
||||
| A | 963.0M | 770.4M | 192.6M | 100.0% | 3,213.0M | 2,570.4M | 642.6M | 100.0% |
|
||||
| B | 481.5M | 385.2M | 96.3M | 50.0% | 2,231.5M | 1,785.2M | 446.3M | 69.5% |
|
||||
| C | 611.0M | 488.8M | 122.2M | 63.4% | 2,292.8M | 1,834.2M | 458.6M | 71.4% |
|
||||
|
||||
Meaning: in year 1, B pays 50% and C 63% of the subsidy A pays, so a longer schedule buys its later participation with a smaller first-year security budget in native units.
|
||||
|
||||
## 4. Concentration (the share issued early against the share issued later)
|
||||
|
||||
| schedule | years 1 to 2 (IGN) | of cap | years 3 to 20 (IGN) | of cap | years 1 to 2 of all issued by year 20 | ratio 1-2 : 3-20 | cap left after year 20 |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| A | 1,963.0M | 49.08% | 1,996.1M | 49.90% | 49.58% | 0.98 | 1.02% |
|
||||
| B | 981.5M | 24.54% | 2,875.0M | 71.87% | 25.45% | 0.34 | 3.59% |
|
||||
| C | 1,146.1M | 28.65% | 2,703.4M | 67.59% | 29.77% | 0.42 | 3.76% |
|
||||
|
||||
Meaning: the ratio column is how many coins years 1 to 2 issue for every coin years 3 to 20 issue; a lower ratio is a broader time distribution, not a broader holder distribution, which only a measured cohort can show (TV-03).
|
||||
|
||||
## 5. Late-miner participation (the subsidy a block pays a miner who joins later)
|
||||
|
||||
| schedule | year 1 full-rate subsidy a block (IGN, 1 block/s) | joining in year 5: a block (share of year 1) | joining in year 10: a block (share of year 1) | joining in year 20: a block (share of year 1) |
|
||||
|---|---|---|---|---|
|
||||
| A | 31.6881 | 7.9220 (25.00%) | 1.9805 (6.25%) | 0.0619 (0.20%) |
|
||||
| B | 15.8440 | 7.9220 (50.00%) | 3.9610 (25.00%) | 0.9903 (6.25%) |
|
||||
| C | 21.8067 | 10.9033 (50.00%) | 4.5843 (21.02%) | 0.8104 (3.72%) |
|
||||
|
||||
Meaning: a miner joining in year 10 sees 6.3% of the year-1 block subsidy under A, 25.0% under B and 21.0% under C; B pays that miner 2.0 times what A pays.
|
||||
|
||||
## 6. Fee dependence at TV-04's revenue multiples (the subsidy's decline alone)
|
||||
|
||||
| TV-04 multiple | reference budget a year (IGN) | A: year fees are needed / year fees exceed the subsidy | B: year fees are needed / year fees exceed the subsidy | C: year fees are needed / year fees exceed the subsidy |
|
||||
|---|---|---|---|---|
|
||||
| 0.25x | 10M | 15 / 17 | 25 / 29 | 25 / 29 |
|
||||
| 1x | 40M | 11 / 13 | 17 / 21 | 17 / 21 |
|
||||
| 4x | 160M | 7 / 9 | 9 / 13 | 9 / 13 |
|
||||
| 10x | 400M | 5 / 7 | 5 / 9 | 4 / 8 |
|
||||
|
||||
Meaning: at the 1x budget, fees must exceed the subsidy from year 13 under A, year 21 under B and year 21 under C, so a longer schedule moves fee dependence later at the cost of a smaller early subsidy. At the 10x budget the order can reverse: fees are first needed in year 5 under A, 5 under B and 4 under C, because a large budget is crossed early by any curve that starts lower.
|
||||
|
||||
## 7. The stretch factor (B on time axes x2, x3 and x4, beside A)
|
||||
|
||||
The volume gives no factor; this sweep shows how the trade moves with it.
|
||||
|
||||
| schedule | year 1 subsidy (IGN) | issued by year 2 | by year 5 | by year 10 | by year 20 | fees exceed subsidy at 1x (year) |
|
||||
|---|---|---|---|---|---|---|
|
||||
| A | 963.0M | 49.08% | 80.33% | 95.95% | 98.98% | 13 |
|
||||
| B | 481.5M | 24.54% | 55.79% | 80.79% | 96.41% | 21 |
|
||||
| B3 | 321.0M | 16.36% | 41.36% | 66.36% | 89.28% | 31 |
|
||||
| B4 | 240.8M | 12.27% | 31.02% | 56.02% | 81.02% | 33 |
|
||||
|
||||
## 8. The litepaper against the code
|
||||
|
||||
| litepaper sentence (site/litepaper.html) | the code, ramp included | the code's curve without the ramp |
|
||||
|---|---|---|
|
||||
| "Half of the 4 billion cap is mined in the first two years" | 49.08% | 50.00% |
|
||||
| "Nearly a quarter of all supply is mined in the first year" | 24.08% | 25.00% |
|
||||
| "3,938M IGN in the first 12 years of a 4,000M cap" | 3,900.5M | 3,937.5M |
|
||||
| "emission starts at 1 billion a year" | 963.0M in year 1 | 1,000.0M a year |
|
||||
|
||||
Meaning: the litepaper's sentences describe the curve without the 30-day ramp; the code, ramp included, issues slightly less in the first years. The words "approached and never reached" hold for every schedule here: each scheduled total is under the cap (table above, last column).
|
||||
|
||||
## Commands and checksums
|
||||
|
||||
Every run is on build-3 under the pid file `~/tv-d02/run.pid` (`tools/token-value/d02/run_on_box.sh`), never on the Mac.
|
||||
|
||||
| what | command | sha256 |
|
||||
|---|---|---|
|
||||
| the generator | `python3 tools/token-value/d02/d02_emission.py --out docs/plans/igneum-2.0-master/token-value/phase0/d02` | `0133addf96266a21a14d7dcff86139edca0c0a5f277d1488add85d09fe80f6ef` |
|
||||
| the README template | (read by the generator) | `92b14fee872fb1d78ff715a09dcda217fda905793aacde9e05c22f2fb7a3060d` |
|
||||
| the tests (known-failed first) | `python3 tools/token-value/d02/test_d02.py` | `cbe13d8becb72953bce3531065f27c51b957866a646eba96211feb93649178cc` |
|
||||
| the byte-identical check | `python3 tools/token-value/d02/d02_emission.py --check docs/plans/igneum-2.0-master/token-value/phase0/d02` | (exit 0 = byte-identical) |
|
||||
| `d02-schedules.csv` (parameters, curve steps, terminal values) | the generator | `1abd30eb7879607a43052c74bf2a6ee4fc27202754d6700cacbfb342ea20e3ae` |
|
||||
| `d02-years.csv` (years 1 to 40, every schedule) | the generator | `c03933af686c9c11454a0b1c188bf2dfa7903549dcc274fdbe43cd2c609723fd` |
|
||||
| `d02-horizons.csv` (years 1, 2, 5, 10, 20) | the generator | `4329ec9f51015577f297f56440b486543e4a40f1cb075270f7b17b02da5f542f` |
|
||||
| `d02-fee-dependence.csv` (every multiple, every schedule, fees required at each horizon) | the generator | `07375dc4cd075a720591326a792c238c54b28a0d8fa9decf38534bd2d738f854` |
|
||||
| `d02-manifest.sha256` (this README and every CSV) | the generator | (lists this file's sha) |
|
||||
|
||||
Searches for a crossing year run to year 1,000; an empty cell means the budget holds that long on the subsidy alone.
|
||||
|
||||
## Evidence
|
||||
|
||||
| file | what it shows |
|
||||
|---|---|
|
||||
| `evidence/known-failed-first.log` | the tests run on build-3 before the generator existed: they failed (no module) |
|
||||
| `evidence/box-generate.log` | the generator run on build-3 and the tests passing, with the output checksums |
|
||||
| `evidence/node-src.log` | every constant the generator uses, read back from the node's source at a284380b: agree |
|
||||
| `evidence/node-crosscheck.log` | the node's own `EmissionTable` (Rust, release-2.0.2-node) and the generator print byte-identical rows for every schedule, 8 and 18 decimals, years 1 to 40, plus the A schedule equal to `MAINNET_PARAMS.emission` |
|
||||
|
||||
## Open questions (BLOCKED rows)
|
||||
|
||||
| row | question | waits on | earliest clock (UK) |
|
||||
|---|---|---|---|
|
||||
| B0 | Which schedule launches: A, B (and at which factor), C, or another same-cap shape. This document does not pick it. | the founder ("pending evidence") after the independent panel reads this | the founder's word |
|
||||
| B1 | Reconcile against TV-01's supply spec (cap, unit, launch rate, ramp, step, terminal rule) | TV-01's `supply-spec.json` landing | 13:00 today, then this generator gains the read |
|
||||
| B2 | Replace the 1 percent yardstick with TV-04's role-by-role budget and its revenue multiples' base | TV-04's landing | TV-04's clock |
|
||||
| B3 | Arrival times and cohort shares under each schedule (delayed entrants as people, not blocks) | TV-03's simulation inputs and a cohort definition | TV-03's clock |
|
||||
| B4 | The litepaper's "after year 5" tail-vote sentence beside a capped schedule (D01 ratified capped issuance subject to TV-04) | D01's wording landing | the D01 lane's clock |
|
||||
|
||||
## Registry
|
||||
|
||||
The D02 evidence for the gates that cite it (TV-01 resolves D01 to D06; TV-03 asks for alternative emission schedules and delayed entrants; TV-04 asks for falling issuance at horizons 1, 5, 10 and 20) is the batch `registry-batch-tv-d02-20261009-01.json` in this folder: one cell, `model:tv-d02-emission`, every row NOT RUN with this README as its evidence, and the map cell it needs. It lands here, not under `tools/ci/batches/`, because the map has no TV cell yet and a batch under that path is replayed at every merge; the CI steward adds the cell and records it through `tools/ci/test-record.mjs`.
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
key,multiple,reference_budget_base_units_per_year,fees_needed_from_year,fees_exceed_subsidy_from_year,fees_required_y1_base_units,fees_required_y2_base_units,fees_required_y5_base_units,fees_required_y10_base_units,fees_required_y20_base_units
|
||||
A,0.25x,10000000000000000000000000,15,17,0,0,0,0,8046875000248328125000000
|
||||
A,1x,40000000000000000000000000,11,13,0,0,0,0,38046875000248328125000000
|
||||
A,4x,160000000000000000000000000,7,9,0,0,0,97500000007946500000000000,158046875000248328125000000
|
||||
A,10x,400000000000000000000000000,5,7,0,0,150000000031786000000000000,337500000007946500000000000,398046875000248328125000000
|
||||
B,0.25x,10000000000000000000000000,25,29,0,0,0,0,0
|
||||
B,1x,40000000000000000000000000,17,21,0,0,0,0,8750000013835000000000000
|
||||
B,4x,160000000000000000000000000,9,13,0,0,0,35000000055340000000000000,128750000013835000000000000
|
||||
B,10x,400000000000000000000000000,5,9,0,0,150000000110680000000000000,275000000055340000000000000,368750000013835000000000000
|
||||
C,0.25x,10000000000000000000000000,25,29,0,0,0,0,0
|
||||
C,1x,40000000000000000000000000,17,21,0,0,0,0,16349110655747632561636600
|
||||
C,4x,160000000000000000000000000,9,13,0,0,0,26210365993564584681976000,136349110655747632561636600
|
||||
C,10x,400000000000000000000000000,4,8,0,0,81792830514963727905583000,266210365993564584681976000,376349110655747632561636600
|
||||
B3,0.25x,10000000000000000000000000,37,43,0,0,0,0,0
|
||||
B3,1x,40000000000000000000000000,25,31,0,0,0,0,0
|
||||
B3,4x,160000000000000000000000000,13,19,0,0,0,0,118333333364929000000000000
|
||||
B3,10x,400000000000000000000000000,1,7,78987000205397168500000000,66666666919432000000000000,66666666919432000000000000,233333333459716000000000000,358333333364929000000000000
|
||||
B4,0.25x,10000000000000000000000000,41,49,0,0,0,0,0
|
||||
B4,1x,40000000000000000000000000,25,33,0,0,0,0,0
|
||||
B4,4x,160000000000000000000000000,9,17,0,0,0,35000000055340000000000000,97500000027670000000000000
|
||||
B4,10x,400000000000000000000000000,1,9,159240250078069877500000000,150000000110680000000000000,150000000110680000000000000,275000000055340000000000000,337500000027670000000000000
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
key,horizon_year,supply_end_base_units,supply_share_of_cap_pct,issuance_in_year_base_units,cumulative_miners_base_units,cumulative_provers_base_units
|
||||
A,1,963038999991632485500000000,24.075975,963038999991632485500000000,770431199993305988400000000,192607799998326497100000000
|
||||
A,2,1963038999864488485500000000,49.075975,999999999872856000000000000,1570431199891590788400000000,392607799972897697100000000
|
||||
A,5,3213038999705558485500000000,80.325975,249999999968214000000000000,2570431199764446788400000000,642607799941111697100000000
|
||||
A,10,3838038999626093485500000000,95.950975,62499999992053500000000000,3070431199700874788400000000,767607799925218697100000000
|
||||
A,20,3959132749610697141750000000,98.978319,1953124999751671875000000,3167306199688557713400000000,791826549922139428350000000
|
||||
B,1,481519499843860245000000000,12.037987,481519499843860245000000000,385215599875088196000000000,96303899968772049000000000
|
||||
B,2,981519499622500245000000000,24.537987,499999999778640000000000000,785215599698000196000000000,196303899924500049000000000
|
||||
B,5,2231519499069100245000000000,55.787987,249999999889320000000000000,1785215599255280196000000000,446303899813820049000000000
|
||||
B,10,3231519498626380245000000000,80.787987,124999999944660000000000000,2585215598901104196000000000,646303899725276049000000000
|
||||
B,20,3856519498349680245000000000,96.412987,31249999986165000000000000,3085215598679744196000000000,771303899669936049000000000
|
||||
C,1,610979018535627245578274400,15.274475,610979018535627245578274400,488783214828501796462619520,122195803707125449115654880
|
||||
C,2,1146137554929776436624538800,28.653439,535158536394149191046264400,916910043943821149299631040,229227510985955287324907760
|
||||
C,5,2292771849251398039205962200,57.319296,318207169485036272094417000,1834217479401118431364769760,458554369850279607841192440
|
||||
C,10,3267457898326278854141750400,81.686447,133789634006435415318024000,2613966318661023083313400320,653491579665255770828350080
|
||||
C,20,3849564679041320447617540800,96.239117,23650889344252367438363400,3079651743233056358094032640,769912935808264089523508160
|
||||
B3,1,321012999794602831500000000,8.025325,321012999794602831500000000,256810399835682265200000000,64202599958920566300000000
|
||||
B3,2,654346332875170831500000000,16.358658,333333333080568000000000000,523477066300136665200000000,130869266575034166300000000
|
||||
B3,5,1654346332116874831500000000,41.358658,333333333080568000000000000,1323477065693499865200000000,330869266423374966300000000
|
||||
B3,10,2654346331358578831500000000,66.358658,166666666540284000000000000,2123477065086863065200000000,530869266271715766300000000
|
||||
B3,20,3571012997330140831500000000,89.275325,41666666635071000000000000,2856810397864112665200000000,714202599466028166300000000
|
||||
B4,1,240759749921930122500000000,6.018994,240759749921930122500000000,192607799937544098000000000,48151949984386024500000000
|
||||
B4,2,490759749811250122500000000,12.268994,249999999889320000000000000,392607799849000098000000000,98151949962250024500000000
|
||||
B4,5,1240759749479210122500000000,31.018994,249999999889320000000000000,992607799583368098000000000,248151949895842024500000000
|
||||
B4,10,2240759749036490122500000000,56.018994,124999999944660000000000000,1792607799229192098000000000,448151949807298024500000000
|
||||
B4,20,3240759748593770122500000000,81.018994,62499999972330000000000000,2592607798875016098000000000,648151949718754024500000000
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
# input 0133addf96266a21a14d7dcff86139edca0c0a5f277d1488add85d09fe80f6ef tools/token-value/d02/d02_emission.py
|
||||
# input 92b14fee872fb1d78ff715a09dcda217fda905793aacde9e05c22f2fb7a3060d tools/token-value/d02/README.template.md
|
||||
1abd30eb7879607a43052c74bf2a6ee4fc27202754d6700cacbfb342ea20e3ae d02-schedules.csv
|
||||
c03933af686c9c11454a0b1c188bf2dfa7903549dcc274fdbe43cd2c609723fd d02-years.csv
|
||||
4329ec9f51015577f297f56440b486543e4a40f1cb075270f7b17b02da5f542f d02-horizons.csv
|
||||
07375dc4cd075a720591326a792c238c54b28a0d8fa9decf38534bd2d738f854 d02-fee-dependence.csv
|
||||
593b8c95381c0f3c4f83c0e0ca77273e81b946d43589a7af008a2507ad1ad3c6 README.md
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
key,decimals,launch_rate_base_units_per_second,ramp_seconds,ramp_start_percent,step_seconds,step_decay_q32,tail,curve_steps,zero_rate_from_second,zero_rate_from_year,scheduled_total_base_units,cap_minus_total_base_units,node_valid
|
||||
A,18,31688087810000000000,2592000,10,63115200,2147483648,cap,66,4102488000,131,3963038999610200483290968000,36961000389799516709032000,yes
|
||||
B,18,15844043900000000000,2592000,10,126230400,2147483648,cap,65,8078745600,257,3981519498294340241086857600,18480501705659758913142400,yes
|
||||
C,18,21806679390000000000,2592000,10,2629800,4233391203,cap,2831,7442334000,236,3974564678809408594431345000,25435321190591405568655000,yes
|
||||
B3,18,10562695930000000000,2592000,10,189345600,2147483648,cap,65,12118118400,385,3987679663680850826387668800,12320336319149173612331200,yes
|
||||
B4,18,7922021950000000000,2592000,10,252460800,2147483648,cap,64,15905030400,505,3990759748261730114673715200,9240251738269885326284800,yes
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
key,year,issuance_base_units,supply_end_base_units,supply_share_of_cap_pct,miners_base_units,provers_base_units,block_subsidy_year_start_1bps_base_units,block_subsidy_share_of_year1_full_pct
|
||||
A,1,963038999991632485500000000,963038999991632485500000000,24.075975,770431199993305988400000000,192607799998326497100000000,3168808781000000000,10.000000
|
||||
A,2,999999999872856000000000000,1963038999864488485500000000,49.075975,799999999898284800000000000,199999999974571200000000000,31688087810000000000,100.000000
|
||||
A,3,499999999936428000000000000,2463038999800916485500000000,61.575975,399999999949142400000000000,99999999987285600000000000,15844043905000000000,50.000000
|
||||
A,4,499999999936428000000000000,2963038999737344485500000000,74.075975,399999999949142400000000000,99999999987285600000000000,15844043905000000000,50.000000
|
||||
A,5,249999999968214000000000000,3213038999705558485500000000,80.325975,199999999974571200000000000,49999999993642800000000000,7922021952500000000,25.000000
|
||||
A,6,249999999968214000000000000,3463038999673772485500000000,86.575975,199999999974571200000000000,49999999993642800000000000,7922021952500000000,25.000000
|
||||
A,7,124999999984107000000000000,3588038999657879485500000000,89.700975,99999999987285600000000000,24999999996821400000000000,3961010976250000000,12.500000
|
||||
A,8,124999999984107000000000000,3713038999641986485500000000,92.825975,99999999987285600000000000,24999999996821400000000000,3961010976250000000,12.500000
|
||||
A,9,62499999992053500000000000,3775538999634039985500000000,94.388475,49999999993642800000000000,12499999998410700000000000,1980505488125000000,6.250000
|
||||
A,10,62499999992053500000000000,3838038999626093485500000000,95.950975,49999999993642800000000000,12499999998410700000000000,1980505488125000000,6.250000
|
||||
A,11,31249999996026750000000000,3869288999622120235500000000,96.732225,24999999996821400000000000,6249999999205350000000000,990252744062500000,3.125000
|
||||
A,12,31249999996026750000000000,3900538999618146985500000000,97.513475,24999999996821400000000000,6249999999205350000000000,990252744062500000,3.125000
|
||||
A,13,15624999998013375000000000,3916163999616160360500000000,97.904100,12499999998410700000000000,3124999999602675000000000,495126372031250000,1.562500
|
||||
A,14,15624999998013375000000000,3931788999614173735500000000,98.294725,12499999998410700000000000,3124999999602675000000000,495126372031250000,1.562500
|
||||
A,15,7812499999006687500000000,3939601499613180423000000000,98.490037,6249999999205350000000000,1562499999801337500000000,247563186015625000,0.781250
|
||||
A,16,7812499999006687500000000,3947413999612187110500000000,98.685350,6249999999205350000000000,1562499999801337500000000,247563186015625000,0.781250
|
||||
A,17,3906249999503343750000000,3951320249611690454250000000,98.783006,3124999999602675000000000,781249999900668750000000,123781593007812500,0.390625
|
||||
A,18,3906249999503343750000000,3955226499611193798000000000,98.880662,3124999999602675000000000,781249999900668750000000,123781593007812500,0.390625
|
||||
A,19,1953124999751671875000000,3957179624610945469875000000,98.929491,1562499999801337500000000,390624999950334375000000,61890796503906250,0.195313
|
||||
A,20,1953124999751671875000000,3959132749610697141750000000,98.978319,1562499999801337500000000,390624999950334375000000,61890796503906250,0.195313
|
||||
A,21,976562499875835937500000,3960109312110572977687500000,99.002733,781249999900668750000000,195312499975167187500000,30945398251953125,0.097656
|
||||
A,22,976562499875835937500000,3961085874610448813625000000,99.027147,781249999900668750000000,195312499975167187500000,30945398251953125,0.097656
|
||||
A,23,488281249937917952971200,3961574155860386731577971200,99.039354,390624999950334362376960,97656249987583590594240,15472699125976562,0.048828
|
||||
A,24,488281249937917952971200,3962062437110324649530942400,99.051561,390624999950334362376960,97656249987583590594240,15472699125976562,0.048828
|
||||
A,25,244140624968958976485600,3962306577735293608507428000,99.057664,195312499975167181188480,48828124993791795297120,7736349562988281,0.024414
|
||||
A,26,244140624968958976485600,3962550718360262567483913600,99.063768,195312499975167181188480,48828124993791795297120,7736349562988281,0.024414
|
||||
A,27,122070312484479472464000,3962672788672747046956377600,99.066820,97656249987583577971200,24414062496895894492800,3868174781494140,0.012207
|
||||
A,28,122070312484479472464000,3962794858985231526428841600,99.069871,97656249987583577971200,24414062496895894492800,3868174781494140,0.012207
|
||||
A,29,61035156242239736232000,3962855894141473766165073600,99.071397,48828124993791788985600,12207031248447947246400,1934087390747070,0.006104
|
||||
A,30,61035156242239736232000,3962916929297716005901305600,99.072923,48828124993791788985600,12207031248447947246400,1934087390747070,0.006104
|
||||
A,31,30517578121119868116000,3962947446875837125769421600,99.073686,24414062496895894492800,6103515624223973623200,967043695373535,0.003052
|
||||
A,32,30517578121119868116000,3962977964453958245637537600,99.074449,24414062496895894492800,6103515624223973623200,967043695373535,0.003052
|
||||
A,33,15258789060559918279200,3962993223243018805555816800,99.074831,12207031248447934623360,3051757812111983655840,483521847686767,0.001526
|
||||
A,34,15258789060559918279200,3963008482032079365474096000,99.075212,12207031248447934623360,3051757812111983655840,483521847686767,0.001526
|
||||
A,35,7629394530279943360800,3963016111426609645417456800,99.075403,6103515624223954688640,1525878906055988672160,241760923843383,0.000763
|
||||
A,36,7629394530279943360800,3963023740821139925360817600,99.075594,6103515624223954688640,1525878906055988672160,241760923843383,0.000763
|
||||
A,37,3814697265139955901600,3963027555518405065316719200,99.075689,3051757812111964721280,762939453027991180320,120880461921691,0.000381
|
||||
A,38,3814697265139955901600,3963031370215670205272620800,99.075784,3051757812111964721280,762939453027991180320,120880461921691,0.000381
|
||||
A,39,1907348632569962172000,3963033277564302775234792800,99.075832,1525878906055969737600,381469726513992434400,60440230960845,0.000191
|
||||
A,40,1907348632569962172000,3963035184912935345196964800,99.075880,1525878906055969737600,381469726513992434400,60440230960845,0.000191
|
||||
B,1,481519499843860245000000000,481519499843860245000000000,12.037987,385215599875088196000000000,96303899968772049000000000,1584404390000000000,10.000000
|
||||
B,2,499999999778640000000000000,981519499622500245000000000,24.537987,399999999822912000000000000,99999999955728000000000000,15844043900000000000,100.000000
|
||||
B,3,499999999778640000000000000,1481519499401140245000000000,37.037987,399999999822912000000000000,99999999955728000000000000,15844043900000000000,100.000000
|
||||
B,4,499999999778640000000000000,1981519499179780245000000000,49.537987,399999999822912000000000000,99999999955728000000000000,15844043900000000000,100.000000
|
||||
B,5,249999999889320000000000000,2231519499069100245000000000,55.787987,199999999911456000000000000,49999999977864000000000000,7922021950000000000,50.000000
|
||||
B,6,249999999889320000000000000,2481519498958420245000000000,62.037987,199999999911456000000000000,49999999977864000000000000,7922021950000000000,50.000000
|
||||
B,7,249999999889320000000000000,2731519498847740245000000000,68.287987,199999999911456000000000000,49999999977864000000000000,7922021950000000000,50.000000
|
||||
B,8,249999999889320000000000000,2981519498737060245000000000,74.537987,199999999911456000000000000,49999999977864000000000000,7922021950000000000,50.000000
|
||||
B,9,124999999944660000000000000,3106519498681720245000000000,77.662987,99999999955728000000000000,24999999988932000000000000,3961010975000000000,25.000000
|
||||
B,10,124999999944660000000000000,3231519498626380245000000000,80.787987,99999999955728000000000000,24999999988932000000000000,3961010975000000000,25.000000
|
||||
B,11,124999999944660000000000000,3356519498571040245000000000,83.912987,99999999955728000000000000,24999999988932000000000000,3961010975000000000,25.000000
|
||||
B,12,124999999944660000000000000,3481519498515700245000000000,87.037987,99999999955728000000000000,24999999988932000000000000,3961010975000000000,25.000000
|
||||
B,13,62499999972330000000000000,3544019498488030245000000000,88.600487,49999999977864000000000000,12499999994466000000000000,1980505487500000000,12.500000
|
||||
B,14,62499999972330000000000000,3606519498460360245000000000,90.162987,49999999977864000000000000,12499999994466000000000000,1980505487500000000,12.500000
|
||||
B,15,62499999972330000000000000,3669019498432690245000000000,91.725487,49999999977864000000000000,12499999994466000000000000,1980505487500000000,12.500000
|
||||
B,16,62499999972330000000000000,3731519498405020245000000000,93.287987,49999999977864000000000000,12499999994466000000000000,1980505487500000000,12.500000
|
||||
B,17,31249999986165000000000000,3762769498391185245000000000,94.069237,24999999988932000000000000,6249999997233000000000000,990252743750000000,6.250000
|
||||
B,18,31249999986165000000000000,3794019498377350245000000000,94.850487,24999999988932000000000000,6249999997233000000000000,990252743750000000,6.250000
|
||||
B,19,31249999986165000000000000,3825269498363515245000000000,95.631737,24999999988932000000000000,6249999997233000000000000,990252743750000000,6.250000
|
||||
B,20,31249999986165000000000000,3856519498349680245000000000,96.412987,24999999988932000000000000,6249999997233000000000000,990252743750000000,6.250000
|
||||
B,21,15624999993082500000000000,3872144498342762745000000000,96.803612,12499999994466000000000000,3124999998616500000000000,495126371875000000,3.125000
|
||||
B,22,15624999993082500000000000,3887769498335845245000000000,97.194237,12499999994466000000000000,3124999998616500000000000,495126371875000000,3.125000
|
||||
B,23,15624999993082500000000000,3903394498328927745000000000,97.584862,12499999994466000000000000,3124999998616500000000000,495126371875000000,3.125000
|
||||
B,24,15624999993082500000000000,3919019498322010245000000000,97.975487,12499999994466000000000000,3124999998616500000000000,495126371875000000,3.125000
|
||||
B,25,7812499996541250000000000,3926831998318551495000000000,98.170800,6249999997233000000000000,1562499999308250000000000,247563185937500000,1.562500
|
||||
B,26,7812499996541250000000000,3934644498315092745000000000,98.366112,6249999997233000000000000,1562499999308250000000000,247563185937500000,1.562500
|
||||
B,27,7812499996541250000000000,3942456998311633995000000000,98.561425,6249999997233000000000000,1562499999308250000000000,247563185937500000,1.562500
|
||||
B,28,7812499996541250000000000,3950269498308175245000000000,98.756737,6249999997233000000000000,1562499999308250000000000,247563185937500000,1.562500
|
||||
B,29,3906249998270625000000000,3954175748306445870000000000,98.854394,3124999998616500000000000,781249999654125000000000,123781592968750000,0.781250
|
||||
B,30,3906249998270625000000000,3958081998304716495000000000,98.952050,3124999998616500000000000,781249999654125000000000,123781592968750000,0.781250
|
||||
B,31,3906249998270625000000000,3961988248302987120000000000,99.049706,3124999998616500000000000,781249999654125000000000,123781592968750000,0.781250
|
||||
B,32,3906249998270625000000000,3965894498301257745000000000,99.147362,3124999998616500000000000,781249999654125000000000,123781592968750000,0.781250
|
||||
B,33,1953124999135312500000000,3967847623300393057500000000,99.196191,1562499999308250000000000,390624999827062500000000,61890796484375000,0.390625
|
||||
B,34,1953124999135312500000000,3969800748299528370000000000,99.245019,1562499999308250000000000,390624999827062500000000,61890796484375000,0.390625
|
||||
B,35,1953124999135312500000000,3971753873298663682500000000,99.293847,1562499999308250000000000,390624999827062500000000,61890796484375000,0.390625
|
||||
B,36,1953124999135312500000000,3973706998297798995000000000,99.342675,1562499999308250000000000,390624999827062500000000,61890796484375000,0.390625
|
||||
B,37,976562499567656250000000,3974683560797366651250000000,99.367089,781249999654125000000000,195312499913531250000000,30945398242187500,0.195313
|
||||
B,38,976562499567656250000000,3975660123296934307500000000,99.391503,781249999654125000000000,195312499913531250000000,30945398242187500,0.195313
|
||||
B,39,976562499567656250000000,3976636685796501963750000000,99.415917,781249999654125000000000,195312499913531250000000,30945398242187500,0.195313
|
||||
B,40,976562499567656250000000,3977613248296069620000000000,99.440331,781249999654125000000000,195312499913531250000000,30945398242187500,0.195313
|
||||
C,1,610979018535627245578274400,610979018535627245578274400,15.274475,488783214828501796462619520,122195803707125449115654880,2180667939000000000,10.000000
|
||||
C,2,535158536394149191046264400,1146137554929776436624538800,28.653439,428126829115319352837011520,107031707278829838209252880,18337158526060127248,84.089642
|
||||
C,3,450012894807540514003749000,1596150449737316950628287800,39.903761,360010315846032411202999200,90002578961508102800749800,15419650869176172099,70.710678
|
||||
C,4,378414230029044816483257400,1974564679766361767111545200,49.364117,302731384023235853186605920,75682846005808963296651480,12966329139238300872,59.460356
|
||||
C,5,318207169485036272094417000,2292771849251398039205962200,57.319296,254565735588029017675533600,63641433897007254418883400,10903339691247025739,50.000000
|
||||
C,6,267579268104972713401740600,2560351117356370752607702800,64.008778,214063414483978170721392480,53515853620994542680348120,9168579259874201020,42.044821
|
||||
C,7,225006447326322114423982800,2785357564682692867031685600,69.633939,180005157861057691539186240,45001289465264422884796560,7709825431934332497,35.355339
|
||||
C,8,189207114949396542714393600,2974564679632089409746079200,74.364117,151365691959517234171514880,37841422989879308542878720,6483164567387618584,29.730178
|
||||
C,9,159103584687754029077647200,3133668264319843438823726400,78.341707,127282867750203223262117760,31820716937550805815529440,5451669843747025733,25.000000
|
||||
C,10,133789634006435415318024000,3267457898326278854141750400,81.686447,107031707205148332254419200,26757926801287083063604800,4584289628359169198,21.022410
|
||||
C,11,112503223624436985594978000,3379961121950715839736728400,84.499028,90002578899549588475982400,22500644724887397118995600,3854912714640289461,17.677670
|
||||
C,12,94603557442135338211600800,3474564679392851177948329200,86.864117,75682845953708270569280640,18920711488427067642320160,3241582282578043355,14.865089
|
||||
C,13,79551792316494960731235000,3554116471709346138679564200,88.852912,63641433853195968584988000,15910358463298992146247000,2725834920935269287,12.500000
|
||||
C,14,66894816980192236709211000,3621011288689538375388775200,90.525282,53515853584153789367368800,13378963396038447341842200,2292144813390618934,10.511205
|
||||
C,15,56251611792856456695759600,3677262900482394832084534800,91.931573,45001289434285165356607680,11250322358571291339151920,1927456356656706329,8.838835
|
||||
C,16,47301778704786202296320400,3724564679187181034380855200,93.114117,37841422963828961837056320,9460355740957240459264080,1620791140731138700,7.432544
|
||||
C,17,39775896144556453193583600,3764340575331737487574438800,94.108514,31820716915645162554866880,7955179228911290638716720,1362917459998512845,6.250000
|
||||
C,18,33447408478583382590427000,3797787983810320870164865800,94.944700,26757926782866706072341600,6689481695716676518085400,1146072406300826627,5.255603
|
||||
C,19,28125805886747210014311600,3825913789697068080179177400,95.647845,22500644709397768011449280,5625161177349442002862320,963728177996633954,4.419417
|
||||
C,20,23650889344252367438363400,3849564679041320447617540800,96.239117,18920711475401893950690720,4730177868850473487672680,810395570086627852,3.716272
|
||||
C,21,19887948065432712762916200,3869452627106753160380457000,96.736316,15910358452346170210332960,3977589613086542552583240,681458729764695515,3.125000
|
||||
C,22,16723704233535323196823200,3886176331340288483577280200,97.154408,13378963386828258557458560,3344740846707064639364640,573036202953171886,2.627801
|
||||
C,23,14062902938533095636562200,3900239234278821579213842400,97.505981,11250322350826476509249760,2812580587706619127312440,481864088832457365,2.209709
|
||||
C,24,11825444668055816673622800,3912064678946877395887465200,97.801617,9460355734444653338898240,2365088933611163334724560,405197784903843171,1.858136
|
||||
C,25,9943974029293599184446600,3922008652976170995071911800,98.050216,7955179223434879347557280,1988794805858719836889320,340729364765067296,1.562500
|
||||
C,26,8361852113889477267170400,3930370505090060472339082200,98.259263,6689481691111581813736320,1672370422777895453434080,286518101377965219,1.313901
|
||||
C,27,7031451466846292850280800,3937401956556906765189363000,98.435049,5625161173477034280224640,1406290293369258570056160,240932044333298868,1.104854
|
||||
C,28,5912722331992724525411400,3943314678888899489714774400,98.582867,4730177865594179620329120,1182544466398544905082280,202598892382186199,0.929068
|
||||
C,29,4971987012935420712986400,3948286665901834910427760800,98.707167,3977589610348336570389120,994397402587084142597280,170364682323893408,0.781250
|
||||
C,30,4180926055505646194465400,3952467591957340556622226200,98.811690,3344740844404516955572320,836185211101129238893080,143259050639672239,0.656950
|
||||
C,31,3515725732213018648575000,3955983317689553575270801200,98.899583,2812580585770414918860000,703145146442603729715000,120466022125184518,0.552427
|
||||
C,32,2956361164978770037485000,3958939678854532345308286200,98.973492,2365088931983016029988000,591272232995754007497000,101299446156225396,0.464534
|
||||
C,33,2485993505612020662441600,3961425672360144365970727800,99.035642,1988794804489616529953280,497198701122404132488320,85182341132626576,0.390625
|
||||
C,34,2090463027033276593654400,3963516135387177642564382200,99.087903,1672370421626621274923520,418092605406655318730880,71629525295180926,0.328475
|
||||
C,35,1757862865501445130948000,3965273998252679087695330200,99.131850,1406290292401156104758400,351572573100289026189600,60233011041859791,0.276214
|
||||
C,36,1478180581980588649069200,3966752178834659676344399400,99.168804,1182544465584470919255360,295636116396117729813840,50649723060678838,0.232267
|
||||
C,37,1242996752378165184397800,3967995175587037841528797200,99.199879,994397401902532147518240,248599350475633036879560,42591170551653214,0.195312
|
||||
C,38,1045231513156864731434400,3969040407100194706260231600,99.226010,836185210525491785147520,209046302631372946286880,35814762635262857,0.164238
|
||||
C,39,878931432448190155200600,3969919338532642896415432200,99.247983,703145145958552124160480,175786286489638031040120,30116505510563651,0.138107
|
||||
C,40,739090290735895785332400,3970658428823378792200764600,99.266461,591272232588716628265920,147818058147179157066480,25324861521622479,0.116134
|
||||
B3,1,321012999794602831500000000,321012999794602831500000000,8.025325,256810399835682265200000000,64202599958920566300000000,1056269593000000000,10.000000
|
||||
B3,2,333333333080568000000000000,654346332875170831500000000,16.358658,266666666464454400000000000,66666666616113600000000000,10562695930000000000,100.000000
|
||||
B3,3,333333333080568000000000000,987679665955738831500000000,24.691992,266666666464454400000000000,66666666616113600000000000,10562695930000000000,100.000000
|
||||
B3,4,333333333080568000000000000,1321012999036306831500000000,33.025325,266666666464454400000000000,66666666616113600000000000,10562695930000000000,100.000000
|
||||
B3,5,333333333080568000000000000,1654346332116874831500000000,41.358658,266666666464454400000000000,66666666616113600000000000,10562695930000000000,100.000000
|
||||
B3,6,333333333080568000000000000,1987679665197442831500000000,49.691992,266666666464454400000000000,66666666616113600000000000,10562695930000000000,100.000000
|
||||
B3,7,166666666540284000000000000,2154346331737726831500000000,53.858658,133333333232227200000000000,33333333308056800000000000,5281347965000000000,50.000000
|
||||
B3,8,166666666540284000000000000,2321012998278010831500000000,58.025325,133333333232227200000000000,33333333308056800000000000,5281347965000000000,50.000000
|
||||
B3,9,166666666540284000000000000,2487679664818294831500000000,62.191992,133333333232227200000000000,33333333308056800000000000,5281347965000000000,50.000000
|
||||
B3,10,166666666540284000000000000,2654346331358578831500000000,66.358658,133333333232227200000000000,33333333308056800000000000,5281347965000000000,50.000000
|
||||
B3,11,166666666540284000000000000,2821012997898862831500000000,70.525325,133333333232227200000000000,33333333308056800000000000,5281347965000000000,50.000000
|
||||
B3,12,166666666540284000000000000,2987679664439146831500000000,74.691992,133333333232227200000000000,33333333308056800000000000,5281347965000000000,50.000000
|
||||
B3,13,83333333270142000000000000,3071012997709288831500000000,76.775325,66666666616113600000000000,16666666654028400000000000,2640673982500000000,25.000000
|
||||
B3,14,83333333270142000000000000,3154346330979430831500000000,78.858658,66666666616113600000000000,16666666654028400000000000,2640673982500000000,25.000000
|
||||
B3,15,83333333270142000000000000,3237679664249572831500000000,80.941992,66666666616113600000000000,16666666654028400000000000,2640673982500000000,25.000000
|
||||
B3,16,83333333270142000000000000,3321012997519714831500000000,83.025325,66666666616113600000000000,16666666654028400000000000,2640673982500000000,25.000000
|
||||
B3,17,83333333270142000000000000,3404346330789856831500000000,85.108658,66666666616113600000000000,16666666654028400000000000,2640673982500000000,25.000000
|
||||
B3,18,83333333270142000000000000,3487679664059998831500000000,87.191992,66666666616113600000000000,16666666654028400000000000,2640673982500000000,25.000000
|
||||
B3,19,41666666635071000000000000,3529346330695069831500000000,88.233658,33333333308056800000000000,8333333327014200000000000,1320336991250000000,12.500000
|
||||
B3,20,41666666635071000000000000,3571012997330140831500000000,89.275325,33333333308056800000000000,8333333327014200000000000,1320336991250000000,12.500000
|
||||
B3,21,41666666635071000000000000,3612679663965211831500000000,90.316992,33333333308056800000000000,8333333327014200000000000,1320336991250000000,12.500000
|
||||
B3,22,41666666635071000000000000,3654346330600282831500000000,91.358658,33333333308056800000000000,8333333327014200000000000,1320336991250000000,12.500000
|
||||
B3,23,41666666635071000000000000,3696012997235353831500000000,92.400325,33333333308056800000000000,8333333327014200000000000,1320336991250000000,12.500000
|
||||
B3,24,41666666635071000000000000,3737679663870424831500000000,93.441992,33333333308056800000000000,8333333327014200000000000,1320336991250000000,12.500000
|
||||
B3,25,20833333317535500000000000,3758512997187960331500000000,93.962825,16666666654028400000000000,4166666663507100000000000,660168495625000000,6.250000
|
||||
B3,26,20833333317535500000000000,3779346330505495831500000000,94.483658,16666666654028400000000000,4166666663507100000000000,660168495625000000,6.250000
|
||||
B3,27,20833333317535500000000000,3800179663823031331500000000,95.004492,16666666654028400000000000,4166666663507100000000000,660168495625000000,6.250000
|
||||
B3,28,20833333317535500000000000,3821012997140566831500000000,95.525325,16666666654028400000000000,4166666663507100000000000,660168495625000000,6.250000
|
||||
B3,29,20833333317535500000000000,3841846330458102331500000000,96.046158,16666666654028400000000000,4166666663507100000000000,660168495625000000,6.250000
|
||||
B3,30,20833333317535500000000000,3862679663775637831500000000,96.566992,16666666654028400000000000,4166666663507100000000000,660168495625000000,6.250000
|
||||
B3,31,10416666658767750000000000,3873096330434405581500000000,96.827408,8333333327014200000000000,2083333331753550000000000,330084247812500000,3.125000
|
||||
B3,32,10416666658767750000000000,3883512997093173331500000000,97.087825,8333333327014200000000000,2083333331753550000000000,330084247812500000,3.125000
|
||||
B3,33,10416666658767750000000000,3893929663751941081500000000,97.348242,8333333327014200000000000,2083333331753550000000000,330084247812500000,3.125000
|
||||
B3,34,10416666658767750000000000,3904346330410708831500000000,97.608658,8333333327014200000000000,2083333331753550000000000,330084247812500000,3.125000
|
||||
B3,35,10416666658767750000000000,3914762997069476581500000000,97.869075,8333333327014200000000000,2083333331753550000000000,330084247812500000,3.125000
|
||||
B3,36,10416666658767750000000000,3925179663728244331500000000,98.129492,8333333327014200000000000,2083333331753550000000000,330084247812500000,3.125000
|
||||
B3,37,5208333329383875000000000,3930387997057628206500000000,98.259700,4166666663507100000000000,1041666665876775000000000,165042123906250000,1.562500
|
||||
B3,38,5208333329383875000000000,3935596330387012081500000000,98.389908,4166666663507100000000000,1041666665876775000000000,165042123906250000,1.562500
|
||||
B3,39,5208333329383875000000000,3940804663716395956500000000,98.520117,4166666663507100000000000,1041666665876775000000000,165042123906250000,1.562500
|
||||
B3,40,5208333329383875000000000,3946012997045779831500000000,98.650325,4166666663507100000000000,1041666665876775000000000,165042123906250000,1.562500
|
||||
B4,1,240759749921930122500000000,240759749921930122500000000,6.018994,192607799937544098000000000,48151949984386024500000000,792202195000000000,10.000000
|
||||
B4,2,249999999889320000000000000,490759749811250122500000000,12.268994,199999999911456000000000000,49999999977864000000000000,7922021950000000000,100.000000
|
||||
B4,3,249999999889320000000000000,740759749700570122500000000,18.518994,199999999911456000000000000,49999999977864000000000000,7922021950000000000,100.000000
|
||||
B4,4,249999999889320000000000000,990759749589890122500000000,24.768994,199999999911456000000000000,49999999977864000000000000,7922021950000000000,100.000000
|
||||
B4,5,249999999889320000000000000,1240759749479210122500000000,31.018994,199999999911456000000000000,49999999977864000000000000,7922021950000000000,100.000000
|
||||
B4,6,249999999889320000000000000,1490759749368530122500000000,37.268994,199999999911456000000000000,49999999977864000000000000,7922021950000000000,100.000000
|
||||
B4,7,249999999889320000000000000,1740759749257850122500000000,43.518994,199999999911456000000000000,49999999977864000000000000,7922021950000000000,100.000000
|
||||
B4,8,249999999889320000000000000,1990759749147170122500000000,49.768994,199999999911456000000000000,49999999977864000000000000,7922021950000000000,100.000000
|
||||
B4,9,124999999944660000000000000,2115759749091830122500000000,52.893994,99999999955728000000000000,24999999988932000000000000,3961010975000000000,50.000000
|
||||
B4,10,124999999944660000000000000,2240759749036490122500000000,56.018994,99999999955728000000000000,24999999988932000000000000,3961010975000000000,50.000000
|
||||
B4,11,124999999944660000000000000,2365759748981150122500000000,59.143994,99999999955728000000000000,24999999988932000000000000,3961010975000000000,50.000000
|
||||
B4,12,124999999944660000000000000,2490759748925810122500000000,62.268994,99999999955728000000000000,24999999988932000000000000,3961010975000000000,50.000000
|
||||
B4,13,124999999944660000000000000,2615759748870470122500000000,65.393994,99999999955728000000000000,24999999988932000000000000,3961010975000000000,50.000000
|
||||
B4,14,124999999944660000000000000,2740759748815130122500000000,68.518994,99999999955728000000000000,24999999988932000000000000,3961010975000000000,50.000000
|
||||
B4,15,124999999944660000000000000,2865759748759790122500000000,71.643994,99999999955728000000000000,24999999988932000000000000,3961010975000000000,50.000000
|
||||
B4,16,124999999944660000000000000,2990759748704450122500000000,74.768994,99999999955728000000000000,24999999988932000000000000,3961010975000000000,50.000000
|
||||
B4,17,62499999972330000000000000,3053259748676780122500000000,76.331494,49999999977864000000000000,12499999994466000000000000,1980505487500000000,25.000000
|
||||
B4,18,62499999972330000000000000,3115759748649110122500000000,77.893994,49999999977864000000000000,12499999994466000000000000,1980505487500000000,25.000000
|
||||
B4,19,62499999972330000000000000,3178259748621440122500000000,79.456494,49999999977864000000000000,12499999994466000000000000,1980505487500000000,25.000000
|
||||
B4,20,62499999972330000000000000,3240759748593770122500000000,81.018994,49999999977864000000000000,12499999994466000000000000,1980505487500000000,25.000000
|
||||
B4,21,62499999972330000000000000,3303259748566100122500000000,82.581494,49999999977864000000000000,12499999994466000000000000,1980505487500000000,25.000000
|
||||
B4,22,62499999972330000000000000,3365759748538430122500000000,84.143994,49999999977864000000000000,12499999994466000000000000,1980505487500000000,25.000000
|
||||
B4,23,62499999972330000000000000,3428259748510760122500000000,85.706494,49999999977864000000000000,12499999994466000000000000,1980505487500000000,25.000000
|
||||
B4,24,62499999972330000000000000,3490759748483090122500000000,87.268994,49999999977864000000000000,12499999994466000000000000,1980505487500000000,25.000000
|
||||
B4,25,31249999986165000000000000,3522009748469255122500000000,88.050244,24999999988932000000000000,6249999997233000000000000,990252743750000000,12.500000
|
||||
B4,26,31249999986165000000000000,3553259748455420122500000000,88.831494,24999999988932000000000000,6249999997233000000000000,990252743750000000,12.500000
|
||||
B4,27,31249999986165000000000000,3584509748441585122500000000,89.612744,24999999988932000000000000,6249999997233000000000000,990252743750000000,12.500000
|
||||
B4,28,31249999986165000000000000,3615759748427750122500000000,90.393994,24999999988932000000000000,6249999997233000000000000,990252743750000000,12.500000
|
||||
B4,29,31249999986165000000000000,3647009748413915122500000000,91.175244,24999999988932000000000000,6249999997233000000000000,990252743750000000,12.500000
|
||||
B4,30,31249999986165000000000000,3678259748400080122500000000,91.956494,24999999988932000000000000,6249999997233000000000000,990252743750000000,12.500000
|
||||
B4,31,31249999986165000000000000,3709509748386245122500000000,92.737744,24999999988932000000000000,6249999997233000000000000,990252743750000000,12.500000
|
||||
B4,32,31249999986165000000000000,3740759748372410122500000000,93.518994,24999999988932000000000000,6249999997233000000000000,990252743750000000,12.500000
|
||||
B4,33,15624999993082500000000000,3756384748365492622500000000,93.909619,12499999994466000000000000,3124999998616500000000000,495126371875000000,6.250000
|
||||
B4,34,15624999993082500000000000,3772009748358575122500000000,94.300244,12499999994466000000000000,3124999998616500000000000,495126371875000000,6.250000
|
||||
B4,35,15624999993082500000000000,3787634748351657622500000000,94.690869,12499999994466000000000000,3124999998616500000000000,495126371875000000,6.250000
|
||||
B4,36,15624999993082500000000000,3803259748344740122500000000,95.081494,12499999994466000000000000,3124999998616500000000000,495126371875000000,6.250000
|
||||
B4,37,15624999993082500000000000,3818884748337822622500000000,95.472119,12499999994466000000000000,3124999998616500000000000,495126371875000000,6.250000
|
||||
B4,38,15624999993082500000000000,3834509748330905122500000000,95.862744,12499999994466000000000000,3124999998616500000000000,495126371875000000,6.250000
|
||||
B4,39,15624999993082500000000000,3850134748323987622500000000,96.253369,12499999994466000000000000,3124999998616500000000000,495126371875000000,6.250000
|
||||
B4,40,15624999993082500000000000,3865759748317070122500000000,96.643994,12499999994466000000000000,3124999998616500000000000,495126371875000000,6.250000
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
host igneum-build-3 python Python 3.12.3 commit 20872fa0c9e1668fa5e7aad3d5cbeaa671939d96 utc 2026-10-09T08:27:50Z pidfile /home/build/tv-d02/run.pid
|
||||
1abd30eb7879607a43052c74bf2a6ee4fc27202754d6700cacbfb342ea20e3ae d02-schedules.csv
|
||||
c03933af686c9c11454a0b1c188bf2dfa7903549dcc274fdbe43cd2c609723fd d02-years.csv
|
||||
4329ec9f51015577f297f56440b486543e4a40f1cb075270f7b17b02da5f542f d02-horizons.csv
|
||||
07375dc4cd075a720591326a792c238c54b28a0d8fa9decf38534bd2d738f854 d02-fee-dependence.csv
|
||||
593b8c95381c0f3c4f83c0e0ca77273e81b946d43589a7af008a2507ad1ad3c6 README.md
|
||||
b3278f06aaf0aca950dbba77c4bd67c670c3742049d3cb7367d0b0888daea407 d02-manifest.sha256
|
||||
test_a_one_byte_change_is_caught (__main__.ByteIdentical.test_a_one_byte_change_is_caught) ... ok
|
||||
test_outputs_regenerate_byte_identically (__main__.ByteIdentical.test_outputs_regenerate_byte_identically) ... ok
|
||||
test_current_at_8_decimals_is_the_33_step_table (__main__.NodeConstants.test_current_at_8_decimals_is_the_33_step_table) ... ok
|
||||
test_q32_root_reproduces_the_node_glide_constant (__main__.NodeConstants.test_q32_root_reproduces_the_node_glide_constant) ... ok
|
||||
test_ramp_and_block_subsidy_match_the_node_rules (__main__.NodeConstants.test_ramp_and_block_subsidy_match_the_node_rules) ... ok
|
||||
test_every_schedule_is_same_cap_and_node_valid (__main__.SameCap.test_every_schedule_is_same_cap_and_node_valid) ... ok
|
||||
test_the_longer_schedules_pay_less_in_year_one (__main__.SameCap.test_the_longer_schedules_pay_less_in_year_one) ... ok
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 7 tests in 0.008s
|
||||
|
||||
OK
|
||||
exit 0
|
||||
CHECK: byte-identical
|
||||
check exit 0
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
host igneum-build-3 python Python 3.12.3 commit 74b84406074fec8c92e369daa7e12b19374de24d utc 2026-10-09T08:15:57Z pidfile /home/build/tv-d02/run.pid
|
||||
Traceback (most recent call last):
|
||||
File "/home/build/tv-d02/igneum/tools/token-value/d02/test_d02.py", line 22, in <module>
|
||||
import d02_emission as g # noqa: E402 (the first run failed here: the generator did not exist yet)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
ModuleNotFoundError: No module named 'd02_emission'
|
||||
exit 1
|
||||
|
|
@ -0,0 +1,248 @@
|
|||
key,year,emission_base_units,supply_end_base_units,block_subsidy_year_start_1bps
|
||||
#A8,steps,33,final_supply,396303898888061649
|
||||
A8,1,96303899999163249,96303899999163249,316880878
|
||||
A8,2,99999999987285600,196303899986448849,3168808781
|
||||
A8,3,49999999977864000,246303899964312849,1584404390
|
||||
A8,4,49999999977864000,296303899942176849,1584404390
|
||||
A8,5,24999999988932000,321303899931108849,792202195
|
||||
A8,6,24999999988932000,346303899920040849,792202195
|
||||
A8,7,12499999978687200,358803899898728049,396101097
|
||||
A8,8,12499999978687200,371303899877415249,396101097
|
||||
A8,9,6249999973564800,377553899850980049,198050548
|
||||
A8,10,6249999973564800,383803899824544849,198050548
|
||||
A8,11,3124999986782400,386928899811327249,99025274
|
||||
A8,12,3124999986782400,390053899798109649,99025274
|
||||
A8,13,1562499993391200,391616399791500849,49512637
|
||||
A8,14,1562499993391200,393178899784892049,49512637
|
||||
A8,15,781249980916800,393960149765808849,24756318
|
||||
A8,16,781249980916800,394741399746725649,24756318
|
||||
A8,17,390624990458400,395132024737184049,12378159
|
||||
A8,18,390624990458400,395522649727642449,12378159
|
||||
A8,19,195312479450400,395717962207092849,6189079
|
||||
A8,20,195312479450400,395913274686543249,6189079
|
||||
A8,21,97656223946400,396010930910489649,3094539
|
||||
A8,22,97656223946400,396108587134436049,3094539
|
||||
A8,23,48828096194400,396157415230630449,1547269
|
||||
A8,24,48828096194400,396206243326824849,1547269
|
||||
A8,25,24414032318400,396230657359143249,773634
|
||||
A8,26,24414032318400,396255071391461649,773634
|
||||
A8,27,12207016159200,396267278407620849,386817
|
||||
A8,28,12207016159200,396279485423780049,386817
|
||||
A8,29,6103492300800,396285588916080849,193408
|
||||
A8,30,6103492300800,396291692408381649,193408
|
||||
A8,31,3051746150400,396294744154532049,96704
|
||||
A8,32,3051746150400,396297795900682449,96704
|
||||
A8,33,1525873075200,396299321773757649,48352
|
||||
A8,34,1525873075200,396300847646832849,48352
|
||||
A8,35,762936537600,396301610583370449,24176
|
||||
A8,36,762936537600,396302373519908049,24176
|
||||
A8,37,381468268800,396302754988176849,12088
|
||||
A8,38,381468268800,396303136456445649,12088
|
||||
A8,39,190734134400,396303327190580049,6044
|
||||
A8,40,190734134400,396303517924714449,6044
|
||||
#A18,is_mainnet_params_emission,true
|
||||
#A18,steps,66,final_supply,3963038999610200483290968000
|
||||
A18,1,963038999991632485500000000,963038999991632485500000000,3168808781000000000
|
||||
A18,2,999999999872856000000000000,1963038999864488485500000000,31688087810000000000
|
||||
A18,3,499999999936428000000000000,2463038999800916485500000000,15844043905000000000
|
||||
A18,4,499999999936428000000000000,2963038999737344485500000000,15844043905000000000
|
||||
A18,5,249999999968214000000000000,3213038999705558485500000000,7922021952500000000
|
||||
A18,6,249999999968214000000000000,3463038999673772485500000000,7922021952500000000
|
||||
A18,7,124999999984107000000000000,3588038999657879485500000000,3961010976250000000
|
||||
A18,8,124999999984107000000000000,3713038999641986485500000000,3961010976250000000
|
||||
A18,9,62499999992053500000000000,3775538999634039985500000000,1980505488125000000
|
||||
A18,10,62499999992053500000000000,3838038999626093485500000000,1980505488125000000
|
||||
A18,11,31249999996026750000000000,3869288999622120235500000000,990252744062500000
|
||||
A18,12,31249999996026750000000000,3900538999618146985500000000,990252744062500000
|
||||
A18,13,15624999998013375000000000,3916163999616160360500000000,495126372031250000
|
||||
A18,14,15624999998013375000000000,3931788999614173735500000000,495126372031250000
|
||||
A18,15,7812499999006687500000000,3939601499613180423000000000,247563186015625000
|
||||
A18,16,7812499999006687500000000,3947413999612187110500000000,247563186015625000
|
||||
A18,17,3906249999503343750000000,3951320249611690454250000000,123781593007812500
|
||||
A18,18,3906249999503343750000000,3955226499611193798000000000,123781593007812500
|
||||
A18,19,1953124999751671875000000,3957179624610945469875000000,61890796503906250
|
||||
A18,20,1953124999751671875000000,3959132749610697141750000000,61890796503906250
|
||||
A18,21,976562499875835937500000,3960109312110572977687500000,30945398251953125
|
||||
A18,22,976562499875835937500000,3961085874610448813625000000,30945398251953125
|
||||
A18,23,488281249937917952971200,3961574155860386731577971200,15472699125976562
|
||||
A18,24,488281249937917952971200,3962062437110324649530942400,15472699125976562
|
||||
A18,25,244140624968958976485600,3962306577735293608507428000,7736349562988281
|
||||
A18,26,244140624968958976485600,3962550718360262567483913600,7736349562988281
|
||||
A18,27,122070312484479472464000,3962672788672747046956377600,3868174781494140
|
||||
A18,28,122070312484479472464000,3962794858985231526428841600,3868174781494140
|
||||
A18,29,61035156242239736232000,3962855894141473766165073600,1934087390747070
|
||||
A18,30,61035156242239736232000,3962916929297716005901305600,1934087390747070
|
||||
A18,31,30517578121119868116000,3962947446875837125769421600,967043695373535
|
||||
A18,32,30517578121119868116000,3962977964453958245637537600,967043695373535
|
||||
A18,33,15258789060559918279200,3962993223243018805555816800,483521847686767
|
||||
A18,34,15258789060559918279200,3963008482032079365474096000,483521847686767
|
||||
A18,35,7629394530279943360800,3963016111426609645417456800,241760923843383
|
||||
A18,36,7629394530279943360800,3963023740821139925360817600,241760923843383
|
||||
A18,37,3814697265139955901600,3963027555518405065316719200,120880461921691
|
||||
A18,38,3814697265139955901600,3963031370215670205272620800,120880461921691
|
||||
A18,39,1907348632569962172000,3963033277564302775234792800,60440230960845
|
||||
A18,40,1907348632569962172000,3963035184912935345196964800,60440230960845
|
||||
#B18,steps,65,final_supply,3981519498294340241086857600
|
||||
B18,1,481519499843860245000000000,481519499843860245000000000,1584404390000000000
|
||||
B18,2,499999999778640000000000000,981519499622500245000000000,15844043900000000000
|
||||
B18,3,499999999778640000000000000,1481519499401140245000000000,15844043900000000000
|
||||
B18,4,499999999778640000000000000,1981519499179780245000000000,15844043900000000000
|
||||
B18,5,249999999889320000000000000,2231519499069100245000000000,7922021950000000000
|
||||
B18,6,249999999889320000000000000,2481519498958420245000000000,7922021950000000000
|
||||
B18,7,249999999889320000000000000,2731519498847740245000000000,7922021950000000000
|
||||
B18,8,249999999889320000000000000,2981519498737060245000000000,7922021950000000000
|
||||
B18,9,124999999944660000000000000,3106519498681720245000000000,3961010975000000000
|
||||
B18,10,124999999944660000000000000,3231519498626380245000000000,3961010975000000000
|
||||
B18,11,124999999944660000000000000,3356519498571040245000000000,3961010975000000000
|
||||
B18,12,124999999944660000000000000,3481519498515700245000000000,3961010975000000000
|
||||
B18,13,62499999972330000000000000,3544019498488030245000000000,1980505487500000000
|
||||
B18,14,62499999972330000000000000,3606519498460360245000000000,1980505487500000000
|
||||
B18,15,62499999972330000000000000,3669019498432690245000000000,1980505487500000000
|
||||
B18,16,62499999972330000000000000,3731519498405020245000000000,1980505487500000000
|
||||
B18,17,31249999986165000000000000,3762769498391185245000000000,990252743750000000
|
||||
B18,18,31249999986165000000000000,3794019498377350245000000000,990252743750000000
|
||||
B18,19,31249999986165000000000000,3825269498363515245000000000,990252743750000000
|
||||
B18,20,31249999986165000000000000,3856519498349680245000000000,990252743750000000
|
||||
B18,21,15624999993082500000000000,3872144498342762745000000000,495126371875000000
|
||||
B18,22,15624999993082500000000000,3887769498335845245000000000,495126371875000000
|
||||
B18,23,15624999993082500000000000,3903394498328927745000000000,495126371875000000
|
||||
B18,24,15624999993082500000000000,3919019498322010245000000000,495126371875000000
|
||||
B18,25,7812499996541250000000000,3926831998318551495000000000,247563185937500000
|
||||
B18,26,7812499996541250000000000,3934644498315092745000000000,247563185937500000
|
||||
B18,27,7812499996541250000000000,3942456998311633995000000000,247563185937500000
|
||||
B18,28,7812499996541250000000000,3950269498308175245000000000,247563185937500000
|
||||
B18,29,3906249998270625000000000,3954175748306445870000000000,123781592968750000
|
||||
B18,30,3906249998270625000000000,3958081998304716495000000000,123781592968750000
|
||||
B18,31,3906249998270625000000000,3961988248302987120000000000,123781592968750000
|
||||
B18,32,3906249998270625000000000,3965894498301257745000000000,123781592968750000
|
||||
B18,33,1953124999135312500000000,3967847623300393057500000000,61890796484375000
|
||||
B18,34,1953124999135312500000000,3969800748299528370000000000,61890796484375000
|
||||
B18,35,1953124999135312500000000,3971753873298663682500000000,61890796484375000
|
||||
B18,36,1953124999135312500000000,3973706998297798995000000000,61890796484375000
|
||||
B18,37,976562499567656250000000,3974683560797366651250000000,30945398242187500
|
||||
B18,38,976562499567656250000000,3975660123296934307500000000,30945398242187500
|
||||
B18,39,976562499567656250000000,3976636685796501963750000000,30945398242187500
|
||||
B18,40,976562499567656250000000,3977613248296069620000000000,30945398242187500
|
||||
#C18,steps,2831,final_supply,3974564678809408594431345000
|
||||
C18,1,610979018535627245578274400,610979018535627245578274400,2180667939000000000
|
||||
C18,2,535158536394149191046264400,1146137554929776436624538800,18337158526060127248
|
||||
C18,3,450012894807540514003749000,1596150449737316950628287800,15419650869176172099
|
||||
C18,4,378414230029044816483257400,1974564679766361767111545200,12966329139238300872
|
||||
C18,5,318207169485036272094417000,2292771849251398039205962200,10903339691247025739
|
||||
C18,6,267579268104972713401740600,2560351117356370752607702800,9168579259874201020
|
||||
C18,7,225006447326322114423982800,2785357564682692867031685600,7709825431934332497
|
||||
C18,8,189207114949396542714393600,2974564679632089409746079200,6483164567387618584
|
||||
C18,9,159103584687754029077647200,3133668264319843438823726400,5451669843747025733
|
||||
C18,10,133789634006435415318024000,3267457898326278854141750400,4584289628359169198
|
||||
C18,11,112503223624436985594978000,3379961121950715839736728400,3854912714640289461
|
||||
C18,12,94603557442135338211600800,3474564679392851177948329200,3241582282578043355
|
||||
C18,13,79551792316494960731235000,3554116471709346138679564200,2725834920935269287
|
||||
C18,14,66894816980192236709211000,3621011288689538375388775200,2292144813390618934
|
||||
C18,15,56251611792856456695759600,3677262900482394832084534800,1927456356656706329
|
||||
C18,16,47301778704786202296320400,3724564679187181034380855200,1620791140731138700
|
||||
C18,17,39775896144556453193583600,3764340575331737487574438800,1362917459998512845
|
||||
C18,18,33447408478583382590427000,3797787983810320870164865800,1146072406300826627
|
||||
C18,19,28125805886747210014311600,3825913789697068080179177400,963728177996633954
|
||||
C18,20,23650889344252367438363400,3849564679041320447617540800,810395570086627852
|
||||
C18,21,19887948065432712762916200,3869452627106753160380457000,681458729764695515
|
||||
C18,22,16723704233535323196823200,3886176331340288483577280200,573036202953171886
|
||||
C18,23,14062902938533095636562200,3900239234278821579213842400,481864088832457365
|
||||
C18,24,11825444668055816673622800,3912064678946877395887465200,405197784903843171
|
||||
C18,25,9943974029293599184446600,3922008652976170995071911800,340729364765067296
|
||||
C18,26,8361852113889477267170400,3930370505090060472339082200,286518101377965219
|
||||
C18,27,7031451466846292850280800,3937401956556906765189363000,240932044333298868
|
||||
C18,28,5912722331992724525411400,3943314678888899489714774400,202598892382186199
|
||||
C18,29,4971987012935420712986400,3948286665901834910427760800,170364682323893408
|
||||
C18,30,4180926055505646194465400,3952467591957340556622226200,143259050639672239
|
||||
C18,31,3515725732213018648575000,3955983317689553575270801200,120466022125184518
|
||||
C18,32,2956361164978770037485000,3958939678854532345308286200,101299446156225396
|
||||
C18,33,2485993505612020662441600,3961425672360144365970727800,85182341132626576
|
||||
C18,34,2090463027033276593654400,3963516135387177642564382200,71629525295180926
|
||||
C18,35,1757862865501445130948000,3965273998252679087695330200,60233011041859791
|
||||
C18,36,1478180581980588649069200,3966752178834659676344399400,50649723060678838
|
||||
C18,37,1242996752378165184397800,3967995175587037841528797200,42591170551653214
|
||||
C18,38,1045231513156864731434400,3969040407100194706260231600,35814762635262857
|
||||
C18,39,878931432448190155200600,3969919338532642896415432200,30116505510563651
|
||||
C18,40,739090290735895785332400,3970658428823378792200764600,25324861521622479
|
||||
#B318,steps,65,final_supply,3987679663680850826387668800
|
||||
B318,1,321012999794602831500000000,321012999794602831500000000,1056269593000000000
|
||||
B318,2,333333333080568000000000000,654346332875170831500000000,10562695930000000000
|
||||
B318,3,333333333080568000000000000,987679665955738831500000000,10562695930000000000
|
||||
B318,4,333333333080568000000000000,1321012999036306831500000000,10562695930000000000
|
||||
B318,5,333333333080568000000000000,1654346332116874831500000000,10562695930000000000
|
||||
B318,6,333333333080568000000000000,1987679665197442831500000000,10562695930000000000
|
||||
B318,7,166666666540284000000000000,2154346331737726831500000000,5281347965000000000
|
||||
B318,8,166666666540284000000000000,2321012998278010831500000000,5281347965000000000
|
||||
B318,9,166666666540284000000000000,2487679664818294831500000000,5281347965000000000
|
||||
B318,10,166666666540284000000000000,2654346331358578831500000000,5281347965000000000
|
||||
B318,11,166666666540284000000000000,2821012997898862831500000000,5281347965000000000
|
||||
B318,12,166666666540284000000000000,2987679664439146831500000000,5281347965000000000
|
||||
B318,13,83333333270142000000000000,3071012997709288831500000000,2640673982500000000
|
||||
B318,14,83333333270142000000000000,3154346330979430831500000000,2640673982500000000
|
||||
B318,15,83333333270142000000000000,3237679664249572831500000000,2640673982500000000
|
||||
B318,16,83333333270142000000000000,3321012997519714831500000000,2640673982500000000
|
||||
B318,17,83333333270142000000000000,3404346330789856831500000000,2640673982500000000
|
||||
B318,18,83333333270142000000000000,3487679664059998831500000000,2640673982500000000
|
||||
B318,19,41666666635071000000000000,3529346330695069831500000000,1320336991250000000
|
||||
B318,20,41666666635071000000000000,3571012997330140831500000000,1320336991250000000
|
||||
B318,21,41666666635071000000000000,3612679663965211831500000000,1320336991250000000
|
||||
B318,22,41666666635071000000000000,3654346330600282831500000000,1320336991250000000
|
||||
B318,23,41666666635071000000000000,3696012997235353831500000000,1320336991250000000
|
||||
B318,24,41666666635071000000000000,3737679663870424831500000000,1320336991250000000
|
||||
B318,25,20833333317535500000000000,3758512997187960331500000000,660168495625000000
|
||||
B318,26,20833333317535500000000000,3779346330505495831500000000,660168495625000000
|
||||
B318,27,20833333317535500000000000,3800179663823031331500000000,660168495625000000
|
||||
B318,28,20833333317535500000000000,3821012997140566831500000000,660168495625000000
|
||||
B318,29,20833333317535500000000000,3841846330458102331500000000,660168495625000000
|
||||
B318,30,20833333317535500000000000,3862679663775637831500000000,660168495625000000
|
||||
B318,31,10416666658767750000000000,3873096330434405581500000000,330084247812500000
|
||||
B318,32,10416666658767750000000000,3883512997093173331500000000,330084247812500000
|
||||
B318,33,10416666658767750000000000,3893929663751941081500000000,330084247812500000
|
||||
B318,34,10416666658767750000000000,3904346330410708831500000000,330084247812500000
|
||||
B318,35,10416666658767750000000000,3914762997069476581500000000,330084247812500000
|
||||
B318,36,10416666658767750000000000,3925179663728244331500000000,330084247812500000
|
||||
B318,37,5208333329383875000000000,3930387997057628206500000000,165042123906250000
|
||||
B318,38,5208333329383875000000000,3935596330387012081500000000,165042123906250000
|
||||
B318,39,5208333329383875000000000,3940804663716395956500000000,165042123906250000
|
||||
B318,40,5208333329383875000000000,3946012997045779831500000000,165042123906250000
|
||||
#B418,steps,64,final_supply,3990759748261730114673715200
|
||||
B418,1,240759749921930122500000000,240759749921930122500000000,792202195000000000
|
||||
B418,2,249999999889320000000000000,490759749811250122500000000,7922021950000000000
|
||||
B418,3,249999999889320000000000000,740759749700570122500000000,7922021950000000000
|
||||
B418,4,249999999889320000000000000,990759749589890122500000000,7922021950000000000
|
||||
B418,5,249999999889320000000000000,1240759749479210122500000000,7922021950000000000
|
||||
B418,6,249999999889320000000000000,1490759749368530122500000000,7922021950000000000
|
||||
B418,7,249999999889320000000000000,1740759749257850122500000000,7922021950000000000
|
||||
B418,8,249999999889320000000000000,1990759749147170122500000000,7922021950000000000
|
||||
B418,9,124999999944660000000000000,2115759749091830122500000000,3961010975000000000
|
||||
B418,10,124999999944660000000000000,2240759749036490122500000000,3961010975000000000
|
||||
B418,11,124999999944660000000000000,2365759748981150122500000000,3961010975000000000
|
||||
B418,12,124999999944660000000000000,2490759748925810122500000000,3961010975000000000
|
||||
B418,13,124999999944660000000000000,2615759748870470122500000000,3961010975000000000
|
||||
B418,14,124999999944660000000000000,2740759748815130122500000000,3961010975000000000
|
||||
B418,15,124999999944660000000000000,2865759748759790122500000000,3961010975000000000
|
||||
B418,16,124999999944660000000000000,2990759748704450122500000000,3961010975000000000
|
||||
B418,17,62499999972330000000000000,3053259748676780122500000000,1980505487500000000
|
||||
B418,18,62499999972330000000000000,3115759748649110122500000000,1980505487500000000
|
||||
B418,19,62499999972330000000000000,3178259748621440122500000000,1980505487500000000
|
||||
B418,20,62499999972330000000000000,3240759748593770122500000000,1980505487500000000
|
||||
B418,21,62499999972330000000000000,3303259748566100122500000000,1980505487500000000
|
||||
B418,22,62499999972330000000000000,3365759748538430122500000000,1980505487500000000
|
||||
B418,23,62499999972330000000000000,3428259748510760122500000000,1980505487500000000
|
||||
B418,24,62499999972330000000000000,3490759748483090122500000000,1980505487500000000
|
||||
B418,25,31249999986165000000000000,3522009748469255122500000000,990252743750000000
|
||||
B418,26,31249999986165000000000000,3553259748455420122500000000,990252743750000000
|
||||
B418,27,31249999986165000000000000,3584509748441585122500000000,990252743750000000
|
||||
B418,28,31249999986165000000000000,3615759748427750122500000000,990252743750000000
|
||||
B418,29,31249999986165000000000000,3647009748413915122500000000,990252743750000000
|
||||
B418,30,31249999986165000000000000,3678259748400080122500000000,990252743750000000
|
||||
B418,31,31249999986165000000000000,3709509748386245122500000000,990252743750000000
|
||||
B418,32,31249999986165000000000000,3740759748372410122500000000,990252743750000000
|
||||
B418,33,15624999993082500000000000,3756384748365492622500000000,495126371875000000
|
||||
B418,34,15624999993082500000000000,3772009748358575122500000000,495126371875000000
|
||||
B418,35,15624999993082500000000000,3787634748351657622500000000,495126371875000000
|
||||
B418,36,15624999993082500000000000,3803259748344740122500000000,495126371875000000
|
||||
B418,37,15624999993082500000000000,3818884748337822622500000000,495126371875000000
|
||||
B418,38,15624999993082500000000000,3834509748330905122500000000,495126371875000000
|
||||
B418,39,15624999993082500000000000,3850134748323987622500000000,495126371875000000
|
||||
B418,40,15624999993082500000000000,3865759748317070122500000000,495126371875000000
|
||||
|
Can't render this file because it has a wrong number of fields in line 43.
|
|
|
@ -0,0 +1,20 @@
|
|||
host igneum-build-3 python Python 3.12.3 commit 501a484db379265e3ca45616abae8db5796d9562 utc 2026-10-09T08:25:20Z pidfile /home/build/tv-d02/run.pid
|
||||
node a284380bdd62d5d0d972cb38f2cbd1daeedda69d emission.rs blob 3bb54489588836f58d91a166558f5a4af22205bb
|
||||
YEAR_SECONDS code 31557600 generator 31557600 agree
|
||||
MAX_CURVE_STEPS code 4096 generator 4096 agree
|
||||
CURRENT.launch_rate code 3168808781 generator 3168808781 agree
|
||||
CURRENT.ramp_seconds code 2592000 generator 2592000 agree
|
||||
CURRENT.ramp_start_percent code 10 generator 10 agree
|
||||
CURRENT.step_seconds code 2 * YEAR_SECONDS generator 2 * YEAR_SECONDS agree
|
||||
CURRENT.step_decay_q32 code 1 << 31 generator 1 << 31 agree
|
||||
CURRENT.tail code Tail::Cap generator Tail::Cap agree
|
||||
YEAR_ONE_EMISSION code 1000000000 generator 1000000000 agree
|
||||
SUPPLY_CAP code 4000000000 generator 4000000000 agree
|
||||
PROVING_POOL_SHARE_PERCENT code 20 generator 20 agree
|
||||
DEVNET_DECIMALS code 8 generator 8 agree
|
||||
EVM_DECIMALS code 18 generator 18 agree
|
||||
MAINNET emission code True generator True agree
|
||||
NODE-SRC: every constant agrees
|
||||
node rows 248 sha256 f6e3b6ee6ca5ebc476da7eacef04ee399bf207a48981e7888ca68d0103d48223
|
||||
python rows 248 sha256 f6e3b6ee6ca5ebc476da7eacef04ee399bf207a48981e7888ca68d0103d48223
|
||||
CROSSCHECK: byte-identical
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
host igneum-build-3 python Python 3.12.3 commit 501a484db379265e3ca45616abae8db5796d9562 utc 2026-10-09T08:25:20Z pidfile /home/build/tv-d02/run.pid
|
||||
node a284380bdd62d5d0d972cb38f2cbd1daeedda69d emission.rs blob 3bb54489588836f58d91a166558f5a4af22205bb
|
||||
YEAR_SECONDS code 31557600 generator 31557600 agree
|
||||
MAX_CURVE_STEPS code 4096 generator 4096 agree
|
||||
YEAR_ONE_EMISSION code 1000000000 generator 1000000000 agree
|
||||
SUPPLY_CAP code 4000000000 generator 4000000000 agree
|
||||
PROVING_POOL_SHARE_PERCENT code 20 generator 20 agree
|
||||
DEVNET_DECIMALS code 8 generator 8 agree
|
||||
EVM_DECIMALS code 18 generator 18 agree
|
||||
MAINNET emission code True generator True agree
|
||||
NODE-SRC: every constant agrees
|
||||
node rows 248 sha256 f6e3b6ee6ca5ebc476da7eacef04ee399bf207a48981e7888ca68d0103d48223
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"run_id": "tv-d02-20261009-01",
|
||||
"manifest_sha": "a284380b",
|
||||
"evidence_dir": "docs/plans/igneum-2.0-master/token-value/phase0/d02",
|
||||
"method": "model",
|
||||
"note": "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.",
|
||||
"cells": [
|
||||
{
|
||||
"cell": "model:tv-d02-emission",
|
||||
"cases": ["TV-01", "TV-03", "TV-04"],
|
||||
"status": "NOT RUN",
|
||||
"method": "model",
|
||||
"evidence": "docs/plans/igneum-2.0-master/token-value/phase0/d02/README.md",
|
||||
"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.",
|
||||
"claim_impact": "none: no public figure moves and no schedule is chosen; the README's table 8 records that the litepaper's emission sentences describe the curve without the 30-day ramp"
|
||||
}
|
||||
],
|
||||
"map_cell_requested": {
|
||||
"model:tv-d02-emission": {
|
||||
"command": "python3 tools/token-value/d02/test_d02.py && python3 tools/token-value/d02/d02_emission.py --check docs/plans/igneum-2.0-master/token-value/phase0/d02 (build-3, tools/token-value/d02/run_on_box.sh generate|crosscheck)",
|
||||
"box_class": "build box, CPU only (build-3)",
|
||||
"fixtures": ["F0"],
|
||||
"cases": ["TV-01", "TV-03", "TV-04"],
|
||||
"coverage": {
|
||||
"TV-01": "partial: the D02 evidence only; the other five decisions and the signed specification are other lanes'",
|
||||
"TV-03": "partial: issuance timing and per-block subsidy for delayed entrants under three same-cap schedules; no genesis audit, no outsider rehearsal, no cohort",
|
||||
"TV-04": "partial: the subsidy's decline and the fee-dependence year at the four multiples; no role costs, fee volatility or zero-external-job scenario"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -3,6 +3,7 @@
|
|||
// is never rendered here.
|
||||
// Runs on every deploy (Vercel build command) and locally with `node build.mjs`.
|
||||
import { readFileSync, writeFileSync, existsSync } from 'node:fs';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import { scrubBench } from './scrub.mjs';
|
||||
import { MARKS, VENDORS, tokensCss, markHtml } from './lib/marks.mjs';
|
||||
import { osHtml } from './lib/os-marks.mjs';
|
||||
|
|
@ -270,6 +271,15 @@ function stampProduct(html, file) {
|
|||
// Igneum 2.0 (8 October 2026): no testnet is served; any leftover paragraph marked data-testnet-notice is removed at build.
|
||||
const DL_HOST = 'https://dl.igneum.network';
|
||||
const DL_SNAPSHOT = join(here, 'downloads.json');
|
||||
const SERVED_GUARD = join(here, '..', 'tools', 'ci', 'served-identity-guard.sh');
|
||||
function guardServed(files) {
|
||||
const present = files.filter((f) => existsSync(f));
|
||||
if (!existsSync(SERVED_GUARD)) { console.log(`served-identity guard: tools/ci/served-identity-guard.sh is not in the tree yet; unguarded this build: ${present.map((f) => f.replace(here + '/', '')).join(', ')}`); return; }
|
||||
const r = spawnSync('bash', [SERVED_GUARD, ...present], { stdio: 'inherit' });
|
||||
if (r.status !== 0) throw new Error(`served-identity guard refused (exit ${r.status}: 1 = a hit, 2 = no private list) on ${present.map((f) => f.replace(here + '/', '')).join(', ')}; nothing is written`);
|
||||
console.log(`served-identity guard: clean on ${present.map((f) => f.replace(here + '/', '')).join(', ')}`);
|
||||
}
|
||||
|
||||
// The snapshot is a tracked file: the build rewrites it only on an explicit refresh (SITE_DOWNLOADS_REFRESH=1 or
|
||||
// --refresh-downloads, the ship pipeline's step, committed with the release), or in CI (a throwaway checkout). A plain
|
||||
// local build, and the pre-push hook, read live but never write: on 6 October 2026 the hook's build stamped 0.3.14's rows
|
||||
|
|
@ -311,6 +321,12 @@ function stampDownloads(html, file, dl) {
|
|||
return html;
|
||||
}
|
||||
const downloads = await loadDownloads();
|
||||
// the served-identity guard (the coordinator's 09:15 class, 9 October 2026: a served file generated from reports or merges
|
||||
// runs the identity grep at its publish step and refuses on a hit): the downloads snapshot and the release manifest (/release.json)
|
||||
// go through tools/ci/served-identity-guard.sh before the served tree is final; exit 1 is a hit, exit 2 no private list, both refuse.
|
||||
// Until the shared guard is in the tree the build says so and goes on, so a landing before it is not held by it.
|
||||
guardServed([DL_SNAPSHOT, join(here, 'release-manifest.json')]);
|
||||
|
||||
built.push(`downloads (${downloads.source}: ${Object.keys(downloads.files || {}).join(', ') || 'none'})`);
|
||||
|
||||
// the evidence page (/evidence): the claims table, the counts and the date are rendered from docs/evidence.md (6 October 2026);
|
||||
|
|
|
|||
|
|
@ -10,20 +10,20 @@
|
|||
# Patterns: the committed lists (tools/ci/forbidden-strings.txt, site/forbidden-strings.txt: machine model names, LAN addresses, home
|
||||
# paths, rig names, the zone word, the owner's name inside a host name) plus the PRIVATE list the export uses (the owner's names, machine
|
||||
# local names with his name, the home IP), read from IGNEUM_IDENTITY_LOCAL, else ~/.config/igneum/identity.local on the Mac, else the
|
||||
# public mirror's own list (~/Projects/igneum-public/tools/identity.local), else /srv/identity/identity.local on a box: one extended regular expression per line, comments with #. The private list never enters the
|
||||
# public mirror's own list (~/Projects/igneum-public/tools/identity.local), else /srv/builds/_identity/identity.local on a box: one extended regular expression per line, comments with #. The private list never enters the
|
||||
# repository. A publish host without the private list is refused (exit 2) unless IGNEUM_IDENTITY_LOCAL_OPTIONAL=1 names the run as a
|
||||
# tree check, never a publish. Refusals are appended to IGNEUM_IDENTITY_REFUSALS (default ~/.config/igneum/identity-refusals.log, or
|
||||
# /srv/identity/refusals.log on a box) as "<utc> <file> <pattern class> <line>" with the matched text replaced by <redacted>.
|
||||
# /srv/builds/_identity/refusals.log on a box) as "<utc> <file> <pattern class> <line>" with the matched text replaced by <redacted>.
|
||||
set -euo pipefail
|
||||
HERE="$(cd "$(dirname "$0")" && pwd -P)"; ME="$HERE/$(basename "$0")"; REPO="${IDENTITY_GUARD_REPO:-$(cd "$HERE/../.." && pwd -P)}"
|
||||
|
||||
# the BOX form (9 October 2026, 09:3x UK, the build-server lane's objection under the standing rule that a box holds no secret): on a box
|
||||
# the private list is a HASHED token list, /srv/identity/identity.hashes (one HMAC-SHA256 hex per literal token, under the 32-byte salt
|
||||
# at /srv/identity/salt; both mode 600), written on the Mac by tools/ci/served-identity-hashes.sh from the clear list and copied over,
|
||||
# the private list is a HASHED token list, /srv/builds/_identity/identity.hashes (one HMAC-SHA256 hex per literal token, under the 32-byte salt
|
||||
# at /srv/builds/_identity/salt; both mode 600), written on the Mac by tools/ci/served-identity-hashes.sh from the clear list and copied over,
|
||||
# never from the repository; the guard tokenizes the served file and matches digests, so the box carries no name and no address.
|
||||
# IGNEUM_IDENTITY_HASHES and IGNEUM_IDENTITY_SALT override the paths.
|
||||
hashed_hits() { # <file> -> prints "line" numbers whose tokens match a digest in the hashed list; empty when no hashed list
|
||||
local hf="${IGNEUM_IDENTITY_HASHES:-/srv/identity/identity.hashes}" sf="${IGNEUM_IDENTITY_SALT:-/srv/identity/salt}"
|
||||
local hf="${IGNEUM_IDENTITY_HASHES:-/srv/builds/_identity/identity.hashes}" sf="${IGNEUM_IDENTITY_SALT:-/srv/builds/_identity/salt}"
|
||||
[ -f "$hf" ] && [ -f "$sf" ] || return 0
|
||||
python3 - "$1" "$hf" "$sf" <<'PY2'
|
||||
import sys, hmac, hashlib, re
|
||||
|
|
@ -34,14 +34,19 @@ for n, line in enumerate(open(f, errors='replace'), 1):
|
|||
if t and hmac.new(salt, t.encode(), hashlib.sha256).hexdigest() in digests: print(n); break
|
||||
PY2
|
||||
}
|
||||
have_hashed() { [ -f "${IGNEUM_IDENTITY_HASHES:-/srv/identity/identity.hashes}" ] && [ -f "${IGNEUM_IDENTITY_SALT:-/srv/identity/salt}" ]; }
|
||||
have_hashed() { [ -f "${IGNEUM_IDENTITY_HASHES:-/srv/builds/_identity/identity.hashes}" ] && [ -f "${IGNEUM_IDENTITY_SALT:-/srv/builds/_identity/salt}" ]; }
|
||||
lists() { # prints every pattern, one per line: the committed lists, then the private one
|
||||
for f in "$REPO/tools/ci/forbidden-strings.txt" "$REPO/site/forbidden-strings.txt"; do [ -f "$f" ] && grep -vE '^\s*(#|$)' "$f" || true; done
|
||||
local got=0
|
||||
for f in "$REPO/tools/ci/forbidden-strings.txt" "$REPO/site/forbidden-strings.txt"; do [ -f "$f" ] && { grep -vE '^\s*(#|$)' "$f" || true; got=1; }; done
|
||||
if [ "$got" = 0 ]; then # a box: the shipped crate trees carry no lists; the bare mirror's master does (every box holds /srv/igneum.git)
|
||||
local mirror="${IGNEUM_IDENTITY_MIRROR:-/srv/igneum.git}"
|
||||
if [ -d "$mirror" ]; then for f in tools/ci/forbidden-strings.txt site/forbidden-strings.txt; do git -C "$mirror" show "master:$f" 2>/dev/null | grep -vE '^\s*(#|$)' || true; done; fi
|
||||
fi
|
||||
local priv="${IGNEUM_IDENTITY_LOCAL:-}"
|
||||
if [ -z "$priv" ]; then for c in "$HOME/.config/igneum/identity.local" "$HOME/Projects/igneum-public/tools/identity.local" /srv/identity/identity.local; do [ -f "$c" ] && { priv="$c"; break; }; done; fi # the public mirror's export list is the same private list on this Mac
|
||||
if [ -z "$priv" ]; then for c in "$HOME/.config/igneum/identity.local" "$HOME/Projects/igneum-public/tools/identity.local" /srv/builds/_identity/identity.local; do [ -f "$c" ] && { priv="$c"; break; }; done; fi # the public mirror's export list is the same private list on this Mac
|
||||
if [ -n "$priv" ] && [ -f "$priv" ]; then grep -vE '^\s*(#|$)' "$priv" || true; printf '%s\n' "__PRIVATE_LIST_PRESENT__"; fi
|
||||
}
|
||||
refusals_log() { if [ -n "${IGNEUM_IDENTITY_REFUSALS:-}" ]; then printf '%s' "$IGNEUM_IDENTITY_REFUSALS"; elif [ -d /srv/identity ]; then printf '%s' /srv/identity/refusals.log; else printf '%s' "$HOME/.config/igneum/identity-refusals.log"; fi; }
|
||||
refusals_log() { if [ -n "${IGNEUM_IDENTITY_REFUSALS:-}" ]; then printf '%s' "$IGNEUM_IDENTITY_REFUSALS"; elif [ -d /srv/builds/_identity ]; then printf '%s' /srv/builds/_identity/refusals.log; else printf '%s' "$HOME/.config/igneum/identity-refusals.log"; fi; }
|
||||
|
||||
guard() { # <file...> -> 0 clean, 1 hit, 2 no private list
|
||||
local all pats have_priv=0 f hits rc=0 log; all="$(lists)"
|
||||
|
|
@ -49,7 +54,7 @@ guard() { # <file...> -> 0 clean, 1 hit, 2 no private list
|
|||
pats="$(printf '%s\n' "$all" | grep -v '^__PRIVATE_LIST_PRESENT__$' || true)"
|
||||
if [ "$have_priv" = 0 ] && have_hashed; then have_priv=2; fi # the box form
|
||||
if [ "$have_priv" = 0 ] && [ "${IGNEUM_IDENTITY_LOCAL_OPTIONAL:-0}" != 1 ]; then
|
||||
echo "served-identity-guard: REFUSED: no private identity list on this host (the clear list on the Mac: IGNEUM_IDENTITY_LOCAL or ~/.config/igneum/identity.local; the hashed list on a box: /srv/identity/identity.hashes with its salt); a publish never runs without one" >&2; return 2
|
||||
echo "served-identity-guard: REFUSED: no private identity list on this host (the clear list on the Mac: IGNEUM_IDENTITY_LOCAL or ~/.config/igneum/identity.local; the hashed list on a box: /srv/builds/_identity/identity.hashes with its salt); a publish never runs without one" >&2; return 2
|
||||
fi
|
||||
[ -n "$pats" ] || { echo "served-identity-guard: no patterns at all; refusing" >&2; return 2; }
|
||||
log="$(refusals_log)"; mkdir -p "$(dirname "$log")" 2>/dev/null || true
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
# Writes the BOX form of the private identity list (9 October 2026): one HMAC-SHA256 hex digest per literal token in the clear list, under
|
||||
# a 32-byte salt, so a box carries no name and no address. Regex entries (metacharacters) are skipped and counted; literal names, local
|
||||
# machine names and addresses are tokenized the way the guard tokenizes a served file (lowercase, [A-Za-z0-9._-] runs). Run on the Mac;
|
||||
# copy the two files to the box by scp (never through the repository): /srv/identity/identity.hashes and /srv/identity/salt, mode 600.
|
||||
# copy the two files to the box by scp (never through the repository): /srv/builds/_identity/identity.hashes and /srv/builds/_identity/salt (build-owned; /srv itself is root's), mode 600.
|
||||
# tools/ci/served-identity-hashes.sh <identity.local> <salt file (created if absent, 32 random bytes)> > identity.hashes
|
||||
set -euo pipefail
|
||||
if [ "${1:-}" = --self-test ]; then
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ LINK="$HOME/Projects/igneum/site/.vercel/project.json"; [ -f "$LINK" ] || { echo
|
|||
# the Vercel project's Root Directory is "site": the deploy runs from the export's root with site/ inside it
|
||||
mkdir -p "$W/.vercel"; cp "$LINK" "$W/.vercel/project.json"
|
||||
echo "site export at $SHORT ($(git log -1 --format='%ci %s' "$SHA" | cut -c1-90)); no .git in $W"
|
||||
( cd "$W/site" && node build.mjs ) 2>&1 | tail -3
|
||||
( cd "$W/site" && node build.mjs ) 2>&1 | tail -3; [ "${PIPESTATUS[0]}" = 0 ] || { echo "the site build failed (the served-identity guard or the build itself); nothing deployed" >&2; exit 1; }
|
||||
echo "deploying $(TZ=UTC date +%H:%M:%SZ)"
|
||||
OUT=$( cd "$W" && npx --yes vercel@latest --global-config "$HOME/.config/igneum/vercel" --scope igneum deploy --prod --yes 2>&1 ) || { echo "$OUT" | tail -5 >&2; exit 1; }
|
||||
URL=$(echo "$OUT" | grep -oE 'https://[a-z0-9.-]*vercel\.app' | tail -1)
|
||||
|
|
|
|||
138
tools/token-value/d02/README.template.md
Normal file
138
tools/token-value/d02/README.template.md
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
# D02, the same-cap emission comparison (Token Value Phase 0)
|
||||
|
||||
Status: NOT RUN. A model, landed as a document and its tests; nothing activates. The founder's ratification of D02 (9 October 2026, 09:2x UK): "the same-cap emission comparison approved, the schedule pending evidence". This document is that evidence. It picks no schedule. Every figure below is printed by the generator; none is typed by hand. Generated file: edit `tools/token-value/d02/README.template.md` and rerun the generator, never this file.
|
||||
|
||||
## Sources
|
||||
|
||||
| source | identity |
|
||||
|---|---|
|
||||
| the volume, `docs/plans/igneum-2.0-master/token-value/igneum-2.0-token-value.pdf` (D02, p. 13 "Choose distribution deliberately", p. 73 the decision register) | sha256 `b79d295c99d9cf0a121b62efdc6743e7282a0d2de33a98f6811616afcbcaeaee` |
|
||||
| `docs/plans/igneum-2.0-master/token-value/rules-and-gates.json` (D02, TV-01, TV-03, TV-04) | sha256 `10ce307329e1663dcb6dce849317c9276c19252de5f483e9ee06015fc77cbe3d` |
|
||||
| the node fork igneum-node, `release-2.0.2-node` | commit `a284380bdd62d5d0d972cb38f2cbd1daeedda69d` |
|
||||
| `consensus/core/src/emission.rs` (EmissionSchedule, EmissionTable: the rule replayed here) | blob `3bb54489588836f58d91a166558f5a4af22205bb` |
|
||||
| `consensus/core/src/igneum.rs` (the cap, the year-one emission, the 20 percent proving share) | blob `ac914b7ef3dbeea6f861a8b82b16415bbe7f33c7` |
|
||||
| `consensus/core/src/config/params.rs` (MAINNET_PARAMS.emission = CURRENT rescaled to 18 decimals) | blob `d0ebf9bb3951ffafbdd9a3d9d0600537229ea710` |
|
||||
| `consensus/core/src/unit.rs` (8 and 18 decimals) | blob `6af7040f07b939e71f8930090f01d022c6136e87` |
|
||||
| `site/litepaper.html` on master at this landing | blob `ad11eaf29ca1f725a35dda3c7f4060dbf1fce509` |
|
||||
| TV-01's supply spec, `docs/plans/igneum-2.0-master/token-value/phase0/tv-01/supply-spec.json` | not landed at this version (BLOCKED row B1) |
|
||||
|
||||
## What D02 asks
|
||||
|
||||
The volume's decision register: compare the existing schedule with slower distribution before launch, and include delayed ordinary entrants and the dilution and security trade-offs. Its p. 13 names three model branches. This document models the first two. The third, a continuing subsidy, is a different supply proposition and is outside a same-cap comparison.
|
||||
|
||||
| branch (the volume, p. 13) | what it says to compare | modelled here as |
|
||||
|---|---|---|
|
||||
| Current proposed pacing | the exact compiled schedule, early concentration, first-year reward budget, later fee dependence | A, read from the node's code |
|
||||
| Longer distribution, same cap | reallocate timing without founder reserves; lower early subsidy and a longer participation opportunity | B, the literal instance (below), and C, this lane's alternative |
|
||||
|
||||
The volume names the shape of the longer branch and no number. B is its literal reading: the same curve, the same cap, the same ramp and terminal rule, with only the time axis stretched (x{{B_STRETCH}}). Nothing is reserved for anyone; every coin is still subsidy to miners and provers. C is this lane's own alternative, stated as such: the same cap reached by a smooth monthly glide with a {{C_HALF_LIFE_Y}}-year half-life, so the subsidy never halves overnight. Both B and C are parameter sets of the node's existing `EmissionSchedule` (no new consensus code), valid under its `validate` rule.
|
||||
|
||||
## Method
|
||||
|
||||
- The generator replays `EmissionTable::build`, `scheduled_supply_at`, `rate_at`, `ramp` and `block_subsidy` from emission.rs line for line, in integer arithmetic, at mainnet's unit (18 decimals). The node's own Rust prints the same bytes for every schedule (the cross-check below).
|
||||
- A year is {{YEAR_SECONDS}} DAA seconds (365.25 days, emission.rs `YEAR_SECONDS`). Year y is DAA seconds [(y - 1) x year, y x year). Emission is keyed to DAA time, so a calendar year equals a schedule year within the accuracy of the difficulty controller.
|
||||
- Every schedule carries the {{RAMP_DAYS}}-day launch ramp from {{RAMP_START}} percent and `Tail::Cap`: the curve runs to zero and its sum, less the ramp's withheld coins and the integer floors, is the scheduled total, never above the {{CAP_IGN}} IGN cap.
|
||||
- The split is the consensus split: {{MINER_PCT}} percent of each block's subsidy to the block's producer and {{PROVER_PCT}} percent to the proving escrow (igneum.rs `PROVING_POOL_SHARE_PERCENT`). It is applied to each year's total; the per-block floor moves at most one base unit a block toward the producer, and the signing bonus moves part of a silent block's producer share to the pool without changing the total.
|
||||
- Per-block figures are at 1 block a second. Mainnet's params carry the inherited block-rate activation (`crescendo_activation`); a faster block rate divides every per-block figure by the same factor for every schedule, so the shares in the late-miner table do not move.
|
||||
- No price appears. Every amount is native IGN or base units.
|
||||
- Fee dependence uses a reference security budget of {{REF_BUDGET_PCT}} percent of the cap a year ({{REF_BUDGET_IGN}} IGN), a stated yardstick and not a cost estimate, scaled by TV-04's revenue multiples ({{MULTIPLES}}). "Fees needed" is the first year the subsidy alone falls under the budget; "fees exceed subsidy" is the first year the subsidy falls under half of it, after which fees must pay more than the subsidy for the budget to hold. Both read the subsidy's decline alone. The fee series is a parameter, never a forecast: `--fee-flat-ign N --fee-growth-bps G` prints the first year the subsidy plus that series falls under each budget. TV-04's own budget replaces the yardstick when it lands (BLOCKED row B2).
|
||||
- The volume defines no Gini-style cohort measure, so concentration is the share of the cap issued by each horizon and the share issued in years 1 to 2 against years 3 to 20.
|
||||
|
||||
## The schedules as code
|
||||
|
||||
The three parameter sets, as `consensus/core/src/emission.rs` `EmissionSchedule` literals at mainnet's unit (printed by the generator from its own schedule functions):
|
||||
|
||||
```rust
|
||||
{{CODE_SCHEDULES}}
|
||||
```
|
||||
|
||||
{{T_SCHEDULES}}
|
||||
|
||||
## 1. Issued supply and its share of the cap, at the end of each year
|
||||
|
||||
{{T_SUPPLY}}
|
||||
|
||||
Meaning: by the end of year 2 the current pacing has issued {{M_Y2_A}} of the cap against {{M_Y2_B}} under B and {{M_Y2_C}} under C, so a later arrival holds a smaller share of an early-issued supply under A. By year 20 the three stand at {{M_Y20_A}}, {{M_Y20_B}} and {{M_Y20_C}} of the cap.
|
||||
|
||||
## 2. Yearly issuance
|
||||
|
||||
{{T_ISSUANCE}}
|
||||
|
||||
Meaning: A's yearly issuance falls to {{M_CLIFF_A}} of the year before at each two-year boundary, while C's falls to {{M_GLIDE_C}} of the year before, every year, with no cliff.
|
||||
|
||||
## 3. Early security income (subsidy paid to miners and provers, IGN)
|
||||
|
||||
{{T_SECURITY}}
|
||||
|
||||
Meaning: in year 1, B pays {{M_Y1_B}} and C {{M_Y1_C}} of the subsidy A pays, so a longer schedule buys its later participation with a smaller first-year security budget in native units.
|
||||
|
||||
## 4. Concentration (the share issued early against the share issued later)
|
||||
|
||||
{{T_CONC}}
|
||||
|
||||
Meaning: the ratio column is how many coins years 1 to 2 issue for every coin years 3 to 20 issue; a lower ratio is a broader time distribution, not a broader holder distribution, which only a measured cohort can show (TV-03).
|
||||
|
||||
## 5. Late-miner participation (the subsidy a block pays a miner who joins later)
|
||||
|
||||
{{T_LATE}}
|
||||
|
||||
Meaning: a miner joining in year 10 sees {{M_LATE10_A}} of the year-1 block subsidy under A, {{M_LATE10_B}} under B and {{M_LATE10_C}} under C; B pays that miner {{M_LATE10_BA}} times what A pays.
|
||||
|
||||
## 6. Fee dependence at TV-04's revenue multiples (the subsidy's decline alone)
|
||||
|
||||
{{T_FEES}}
|
||||
|
||||
Meaning: at the 1x budget, fees must exceed the subsidy from year {{M_EXC1_A}} under A, year {{M_EXC1_B}} under B and year {{M_EXC1_C}} under C, so a longer schedule moves fee dependence later at the cost of a smaller early subsidy. At the 10x budget the order can reverse: fees are first needed in year {{M_NEED10_A}} under A, {{M_NEED10_B}} under B and {{M_NEED10_C}} under C, because a large budget is crossed early by any curve that starts lower.
|
||||
|
||||
## 7. The stretch factor (B on time axes x2, x3 and x4, beside A)
|
||||
|
||||
The volume gives no factor; this sweep shows how the trade moves with it.
|
||||
|
||||
{{T_SWEEP}}
|
||||
|
||||
## 8. The litepaper against the code
|
||||
|
||||
{{T_LITEPAPER}}
|
||||
|
||||
Meaning: the litepaper's sentences describe the curve without the {{RAMP_DAYS}}-day ramp; the code, ramp included, issues slightly less in the first years. The words "approached and never reached" hold for every schedule here: each scheduled total is under the cap (table above, last column).
|
||||
|
||||
## Commands and checksums
|
||||
|
||||
Every run is on build-3 under the pid file `~/tv-d02/run.pid` (`tools/token-value/d02/run_on_box.sh`), never on the Mac.
|
||||
|
||||
| what | command | sha256 |
|
||||
|---|---|---|
|
||||
| the generator | `python3 tools/token-value/d02/d02_emission.py --out docs/plans/igneum-2.0-master/token-value/phase0/d02` | `{{SHA_GENERATOR}}` |
|
||||
| the README template | (read by the generator) | `{{SHA_TEMPLATE}}` |
|
||||
| the tests (known-failed first) | `python3 tools/token-value/d02/test_d02.py` | `{{SHA_TEST}}` |
|
||||
| the byte-identical check | `python3 tools/token-value/d02/d02_emission.py --check docs/plans/igneum-2.0-master/token-value/phase0/d02` | (exit 0 = byte-identical) |
|
||||
| `d02-schedules.csv` (parameters, curve steps, terminal values) | the generator | `{{SHA_SCHEDULES}}` |
|
||||
| `d02-years.csv` (years 1 to {{CSV_YEARS}}, every schedule) | the generator | `{{SHA_YEARS}}` |
|
||||
| `d02-horizons.csv` (years {{HORIZONS}}) | the generator | `{{SHA_HORIZONS}}` |
|
||||
| `d02-fee-dependence.csv` (every multiple, every schedule, fees required at each horizon) | the generator | `{{SHA_FEE_DEPENDENCE}}` |
|
||||
| `d02-manifest.sha256` (this README and every CSV) | the generator | (lists this file's sha) |
|
||||
|
||||
Searches for a crossing year run to year {{SEARCH_YEARS}}; an empty cell means the budget holds that long on the subsidy alone.
|
||||
|
||||
## Evidence
|
||||
|
||||
| file | what it shows |
|
||||
|---|---|
|
||||
| `evidence/known-failed-first.log` | the tests run on build-3 before the generator existed: they failed (no module) |
|
||||
| `evidence/box-generate.log` | the generator run on build-3 and the tests passing, with the output checksums |
|
||||
| `evidence/node-src.log` | every constant the generator uses, read back from the node's source at a284380b: agree |
|
||||
| `evidence/node-crosscheck.log` | the node's own `EmissionTable` (Rust, release-2.0.2-node) and the generator print byte-identical rows for every schedule, 8 and 18 decimals, years 1 to {{CSV_YEARS}}, plus the A schedule equal to `MAINNET_PARAMS.emission` |
|
||||
|
||||
## Open questions (BLOCKED rows)
|
||||
|
||||
| row | question | waits on | earliest clock (UK) |
|
||||
|---|---|---|---|
|
||||
| B0 | Which schedule launches: A, B (and at which factor), C, or another same-cap shape. This document does not pick it. | the founder ("pending evidence") after the independent panel reads this | the founder's word |
|
||||
| B1 | Reconcile against TV-01's supply spec (cap, unit, launch rate, ramp, step, terminal rule) | TV-01's `supply-spec.json` landing | 13:00 today, then this generator gains the read |
|
||||
| B2 | Replace the {{REF_BUDGET_PCT}} percent yardstick with TV-04's role-by-role budget and its revenue multiples' base | TV-04's landing | TV-04's clock |
|
||||
| B3 | Arrival times and cohort shares under each schedule (delayed entrants as people, not blocks) | TV-03's simulation inputs and a cohort definition | TV-03's clock |
|
||||
| B4 | The litepaper's "after year 5" tail-vote sentence beside a capped schedule (D01 ratified capped issuance subject to TV-04) | D01's wording landing | the D01 lane's clock |
|
||||
|
||||
## Registry
|
||||
|
||||
The D02 evidence for the gates that cite it (TV-01 resolves D01 to D06; TV-03 asks for alternative emission schedules and delayed entrants; TV-04 asks for falling issuance at horizons 1, 5, 10 and 20) is the batch `registry-batch-tv-d02-20261009-01.json` in this folder: one cell, `model:tv-d02-emission`, every row NOT RUN with this README as its evidence, and the map cell it needs. It lands here, not under `tools/ci/batches/`, because the map has no TV cell yet and a batch under that path is replayed at every merge; the CI steward adds the cell and records it through `tools/ci/test-record.mjs`.
|
||||
615
tools/token-value/d02/d02_emission.py
Normal file
615
tools/token-value/d02/d02_emission.py
Normal file
|
|
@ -0,0 +1,615 @@
|
|||
#!/usr/bin/env python3
|
||||
"""D02, the same-cap emission comparison (Token Value Phase 0, 9 October 2026).
|
||||
|
||||
Deterministic, standalone Python 3 (no third-party packages, integer arithmetic for every amount). It replays the node
|
||||
fork's own emission rule (igneum-node release-2.0.2-node a284380b, consensus/core/src/emission.rs: EmissionTable::build,
|
||||
scheduled_supply_at, rate_at, ramp, block_subsidy, ramp_withheld) for three schedules that share the 4,000,000,000 IGN
|
||||
cap, and writes the CSVs and the README of docs/plans/igneum-2.0-master/token-value/phase0/d02/.
|
||||
|
||||
python3 tools/token-value/d02/d02_emission.py --out docs/plans/igneum-2.0-master/token-value/phase0/d02
|
||||
python3 tools/token-value/d02/d02_emission.py --check docs/plans/igneum-2.0-master/token-value/phase0/d02
|
||||
python3 tools/token-value/d02/d02_emission.py --fee-flat-ign N [--fee-growth-bps G] the fee series parameter
|
||||
python3 tools/token-value/d02/d02_emission.py --node-src <igneum-node checkout> constants read from the code
|
||||
python3 tools/token-value/d02/d02_emission.py --params | --node-csv the Rust cross-check's input / twin
|
||||
|
||||
No price appears anywhere: every amount is native base units (18 decimals, mainnet's unit) or IGN.
|
||||
"""
|
||||
import argparse, hashlib, os, re, sys, tempfile, shutil
|
||||
|
||||
HERE = os.path.dirname(os.path.abspath(__file__))
|
||||
TEMPLATE = os.path.join(HERE, 'README.template.md')
|
||||
|
||||
# ---- the node's constants (release-2.0.2-node a284380b; --node-src re-reads each one from the source) -------------
|
||||
YEAR = 31_557_600 # emission.rs YEAR_SECONDS (365.25 days)
|
||||
MONTH = YEAR // 12 # emission.rs MONTH_SECONDS
|
||||
Q32 = 1 << 32 # emission.rs Q32_ONE
|
||||
MAX_CURVE_STEPS = 4_096 # emission.rs MAX_CURVE_STEPS
|
||||
YEAR_ONE_COINS = 1_000_000_000 # igneum.rs YEAR_ONE_EMISSION_SOMPI / SOMPI_PER_KASPA
|
||||
CAP_COINS = 4_000_000_000 # igneum.rs SUPPLY_CAP_SOMPI / SOMPI_PER_KASPA
|
||||
RAMP_SECONDS = 2_592_000 # emission.rs CURRENT.ramp_seconds (igneum.rs LAUNCH_RAMP_SECONDS)
|
||||
RAMP_START_PERCENT = 10 # emission.rs CURRENT.ramp_start_percent
|
||||
PROVER_PERCENT = 20 # igneum.rs PROVING_POOL_SHARE_PERCENT
|
||||
NODE_DECIMALS = 8 # unit.rs DEVNET_DECIMALS: the unit the schedules are written in
|
||||
MAIN_DECIMALS = 18 # unit.rs EVM_DECIMALS: mainnet's unit, params.rs MAINNET_PARAMS.emission
|
||||
NODE_COMMIT = 'a284380bdd62d5d0d972cb38f2cbd1daeedda69d'
|
||||
|
||||
# ---- the comparison's own choices (each stated in the README) -------------------------------------------------------
|
||||
HORIZONS = (1, 2, 5, 10, 20)
|
||||
JOIN_YEARS = (5, 10, 20)
|
||||
CSV_YEARS = 40
|
||||
B_STRETCH = 2 # the volume's shape, its literal instance: the same curve on a time axis x2
|
||||
SWEEP_STRETCH = (2, 3, 4)
|
||||
C_HALF_LIFE_MONTHS = 48 # this lane's alternative: a smooth monthly glide, four-year half-life
|
||||
TV04_MULTIPLES = ((1, 4), (1, 1), (4, 1), (10, 1)) # TV-04's .25x / 1x / 4x / 10x, as exact fractions
|
||||
REF_BUDGET_BPS_OF_CAP = 100 # the reference security budget: 1 percent of the cap a year (stated, not a cost)
|
||||
SEARCH_YEARS = 1_000
|
||||
|
||||
|
||||
# ---- integer helpers --------------------------------------------------------------------------------------------------
|
||||
def q32_pow2_neg_inv(n):
|
||||
"""floor(2^32 * 2^(-1/n)): the largest x with x^n <= 2^(32n - 1), by integer bisection (no floating point)."""
|
||||
lo, hi, lim = 0, Q32, 1 << (32 * n - 1)
|
||||
while lo < hi:
|
||||
mid = (lo + hi + 1) // 2
|
||||
if mid ** n <= lim:
|
||||
lo = mid
|
||||
else:
|
||||
hi = mid - 1
|
||||
return lo
|
||||
|
||||
|
||||
def rdiv(n, d):
|
||||
"""n / d rounded half up, non-negative integers."""
|
||||
return (2 * n + d) // (2 * d)
|
||||
|
||||
|
||||
def fixed(n, d, dp):
|
||||
"""n / d to dp decimals, rounded half up, as a string."""
|
||||
v = rdiv(n * 10 ** dp, d)
|
||||
s = str(v)
|
||||
if dp == 0:
|
||||
return s
|
||||
s = s.rjust(dp + 1, '0')
|
||||
return s[:-dp] + '.' + s[-dp:]
|
||||
|
||||
|
||||
def group(s):
|
||||
whole, _, frac = s.partition('.')
|
||||
out = ''
|
||||
while len(whole) > 3:
|
||||
out, whole = ',' + whole[-3:] + out, whole[:-3]
|
||||
return whole + out + ('.' + frac if frac else '')
|
||||
|
||||
|
||||
def pct(n, d, dp=2):
|
||||
return fixed(100 * n, d, dp) + '%'
|
||||
|
||||
|
||||
def mign(x, dec, dp=1):
|
||||
"""millions of IGN."""
|
||||
return group(fixed(x, 10 ** (dec + 6), dp)) + 'M'
|
||||
|
||||
|
||||
def ign(x, dec, dp=0):
|
||||
return group(fixed(x, 10 ** dec, dp))
|
||||
|
||||
|
||||
# ---- the schedules, as node EmissionSchedule parameter sets (written at 8 decimals, rescaled as mainnet does) --------
|
||||
def _sched(key, label, launch8, step, decay, decimals, note):
|
||||
k = 10 ** (decimals - NODE_DECIMALS)
|
||||
return dict(key=key, label=label, launch=launch8 * k, ramp=RAMP_SECONDS, ramp_start=RAMP_START_PERCENT,
|
||||
step=step, decay=decay, decimals=decimals, note=note)
|
||||
|
||||
|
||||
A_LAUNCH8 = YEAR_ONE_COINS * 10 ** NODE_DECIMALS // YEAR # igneum.rs BASE_SUBSIDY_PER_SECOND_SOMPI, floored
|
||||
|
||||
|
||||
def schedule_current(decimals=MAIN_DECIMALS):
|
||||
return _sched('A', 'current pacing (release-2.0.2 mainnet)', A_LAUNCH8, 2 * YEAR, 1 << 31, decimals,
|
||||
'EmissionSchedule::CURRENT.rescaled(8, 18): two-year halving cliffs, 30-day ramp from 10%, Tail::Cap')
|
||||
|
||||
|
||||
def schedule_stretch(s, decimals=MAIN_DECIMALS):
|
||||
key = 'B' if s == B_STRETCH else 'B%d' % s
|
||||
return _sched(key, 'longer distribution, same cap (the volume; time axis x%d)' % s, A_LAUNCH8 // s, s * 2 * YEAR,
|
||||
1 << 31, decimals, 'the current curve on a time axis x%d: launch rate / %d, halving every %d years, '
|
||||
'same ramp, Tail::Cap' % (s, s, 2 * s))
|
||||
|
||||
|
||||
def schedule_glide(decimals=MAIN_DECIMALS):
|
||||
q = q32_pow2_neg_inv(C_HALF_LIFE_MONTHS)
|
||||
launch8 = CAP_COINS * 10 ** NODE_DECIMALS * (Q32 - q) // (Q32 * MONTH)
|
||||
return _sched('C', 'smooth glide, same cap (this lane\'s alternative)', launch8, MONTH, q, decimals,
|
||||
'monthly steps, multiplier 2^(-1/%d) in Q32 (a %d-year half-life), launch rate set so the curve sums '
|
||||
'to the cap, same ramp, Tail::Cap' % (C_HALF_LIFE_MONTHS, C_HALF_LIFE_MONTHS // 12))
|
||||
|
||||
|
||||
def main_schedules():
|
||||
return [schedule_current(), schedule_stretch(B_STRETCH), schedule_glide()]
|
||||
|
||||
|
||||
def all_schedules():
|
||||
return main_schedules() + [schedule_stretch(s) for s in SWEEP_STRETCH if s != B_STRETCH]
|
||||
|
||||
|
||||
# ---- the node's rule, line for line (emission.rs at a284380b, Tail::Cap) ---------------------------------------------
|
||||
def ramp_withheld(rate, a, b, ramp_seconds, start_percent):
|
||||
if b <= a or ramp_seconds == 0:
|
||||
return 0
|
||||
n = b - a
|
||||
total = n * ramp_seconds - (a + b - 1) * n // 2
|
||||
return rate * (100 - start_percent) * total // (100 * ramp_seconds)
|
||||
|
||||
|
||||
class Table:
|
||||
def __init__(self, s):
|
||||
self.s = s
|
||||
self.rates, self.supplies = [], []
|
||||
rate, supply = s['launch'], 0
|
||||
for k in range(MAX_CURVE_STEPS):
|
||||
self.rates.append(rate)
|
||||
self.supplies.append(supply)
|
||||
if rate == 0:
|
||||
break
|
||||
a = k * s['step']
|
||||
b = a + s['step']
|
||||
withheld = ramp_withheld(rate, a, min(b, s['ramp']), s['ramp'], s['ramp_start']) if a < s['ramp'] else 0
|
||||
supply += rate * s['step'] - withheld
|
||||
rate = rate * s['decay'] >> 32
|
||||
if self.rates[-1] != 0:
|
||||
raise ValueError('%s: the curve does not reach zero within %d steps' % (s['key'], MAX_CURVE_STEPS))
|
||||
|
||||
def rate_at(self, sec):
|
||||
k = sec // self.s['step']
|
||||
return self.rates[k] if k < len(self.rates) else 0
|
||||
|
||||
def supply_at(self, sec):
|
||||
s = self.s
|
||||
k = sec // s['step']
|
||||
if k >= len(self.rates):
|
||||
return self.supplies[-1]
|
||||
base, rate = self.supplies[k], self.rates[k]
|
||||
a = k * s['step']
|
||||
withheld = ramp_withheld(rate, a, min(sec, s['ramp']), s['ramp'], s['ramp_start']) if a < s['ramp'] else 0
|
||||
return base + rate * (sec - a) - withheld
|
||||
|
||||
def ramp_of(self, full, sec):
|
||||
s = self.s
|
||||
if sec >= s['ramp']:
|
||||
return full
|
||||
num = s['ramp_start'] * s['ramp'] + (100 - s['ramp_start']) * sec
|
||||
return full * num // (100 * s['ramp'])
|
||||
|
||||
def block_subsidy(self, daa, bps):
|
||||
sec = daa // bps
|
||||
return self.ramp_of(self.rate_at(sec) // bps, sec)
|
||||
|
||||
# derived
|
||||
def year_issuance(self, y):
|
||||
return self.supply_at(y * YEAR) - self.supply_at((y - 1) * YEAR)
|
||||
|
||||
def total(self):
|
||||
return self.supplies[-1]
|
||||
|
||||
def zero_second(self):
|
||||
return (len(self.rates) - 1) * self.s['step']
|
||||
|
||||
|
||||
def cap_units(dec):
|
||||
return CAP_COINS * 10 ** dec
|
||||
|
||||
|
||||
def first_year(pred):
|
||||
for y in range(1, SEARCH_YEARS + 1):
|
||||
if pred(y):
|
||||
return y
|
||||
return None
|
||||
|
||||
|
||||
def ref_budget(dec, m):
|
||||
num, den = m
|
||||
return cap_units(dec) * REF_BUDGET_BPS_OF_CAP * num // (10_000 * den)
|
||||
|
||||
|
||||
def mult_label(m):
|
||||
num, den = m
|
||||
return ('%d' % num if den == 1 else '0.%s' % fixed(num, den, 2).split('.')[1]) + 'x'
|
||||
|
||||
|
||||
def split(x):
|
||||
p = x * PROVER_PERCENT // 100
|
||||
return x - p, p
|
||||
|
||||
|
||||
# ---- outputs ----------------------------------------------------------------------------------------------------------
|
||||
def csv_years(tables):
|
||||
rows = ['key,year,issuance_base_units,supply_end_base_units,supply_share_of_cap_pct,miners_base_units,'
|
||||
'provers_base_units,block_subsidy_year_start_1bps_base_units,block_subsidy_share_of_year1_full_pct']
|
||||
for t in tables:
|
||||
dec = t.s['decimals']
|
||||
full1 = t.block_subsidy(t.s['ramp'], 1)
|
||||
for y in range(1, CSV_YEARS + 1):
|
||||
e = t.year_issuance(y)
|
||||
mi, pr = split(e)
|
||||
bsub = t.block_subsidy((y - 1) * YEAR, 1)
|
||||
rows.append(','.join(str(v) for v in (t.s['key'], y, e, t.supply_at(y * YEAR),
|
||||
fixed(100 * t.supply_at(y * YEAR), cap_units(dec), 6), mi, pr, bsub,
|
||||
fixed(100 * bsub, full1, 6))))
|
||||
return '\n'.join(rows) + '\n'
|
||||
|
||||
|
||||
def csv_horizons(tables):
|
||||
rows = ['key,horizon_year,supply_end_base_units,supply_share_of_cap_pct,issuance_in_year_base_units,'
|
||||
'cumulative_miners_base_units,cumulative_provers_base_units']
|
||||
for t in tables:
|
||||
dec = t.s['decimals']
|
||||
for y in HORIZONS:
|
||||
sup = t.supply_at(y * YEAR)
|
||||
mi, pr = split(sup)
|
||||
rows.append(','.join(str(v) for v in (t.s['key'], y, sup, fixed(100 * sup, cap_units(dec), 6),
|
||||
t.year_issuance(y), mi, pr)))
|
||||
return '\n'.join(rows) + '\n'
|
||||
|
||||
|
||||
def csv_fees(tables):
|
||||
rows = ['key,multiple,reference_budget_base_units_per_year,fees_needed_from_year,fees_exceed_subsidy_from_year,'
|
||||
+ ','.join('fees_required_y%d_base_units' % y for y in HORIZONS)]
|
||||
for t in tables:
|
||||
dec = t.s['decimals']
|
||||
for m in TV04_MULTIPLES:
|
||||
r = ref_budget(dec, m)
|
||||
need = first_year(lambda y: t.year_issuance(y) < r)
|
||||
exceed = first_year(lambda y: 2 * t.year_issuance(y) < r)
|
||||
req = [max(0, r - t.year_issuance(y)) for y in HORIZONS]
|
||||
rows.append(','.join(str(v) for v in [t.s['key'], mult_label(m), r, need, exceed] + req))
|
||||
return '\n'.join(rows) + '\n'
|
||||
|
||||
|
||||
def csv_schedules(tables):
|
||||
rows = ['key,decimals,launch_rate_base_units_per_second,ramp_seconds,ramp_start_percent,step_seconds,'
|
||||
'step_decay_q32,tail,curve_steps,zero_rate_from_second,zero_rate_from_year,scheduled_total_base_units,'
|
||||
'cap_minus_total_base_units,node_valid']
|
||||
for t in tables:
|
||||
s = t.s
|
||||
rows.append(','.join(str(v) for v in (s['key'], s['decimals'], s['launch'], s['ramp'], s['ramp_start'],
|
||||
s['step'], s['decay'], 'cap', len(t.rates), t.zero_second(),
|
||||
t.zero_second() // YEAR + 1, t.total(),
|
||||
cap_units(s['decimals']) - t.total(), 'yes')))
|
||||
return '\n'.join(rows) + '\n'
|
||||
|
||||
|
||||
def md_table(head, rows):
|
||||
out = ['| ' + ' | '.join(head) + ' |', '|' + '|'.join('---' for _ in head) + '|']
|
||||
out += ['| ' + ' | '.join(str(c) for c in r) + ' |' for r in rows]
|
||||
return '\n'.join(out)
|
||||
|
||||
|
||||
def read_bytes(p):
|
||||
with open(p, 'rb') as f:
|
||||
return f.read()
|
||||
|
||||
|
||||
def sha256_file(p):
|
||||
return hashlib.sha256(read_bytes(p)).hexdigest()
|
||||
|
||||
|
||||
def values(tables, sweep):
|
||||
"""Every figure the README prints, keyed for the template."""
|
||||
v = {}
|
||||
A, B, C = tables
|
||||
dec = MAIN_DECIMALS
|
||||
capu = cap_units(dec)
|
||||
v['CAP_IGN'] = group(str(CAP_COINS))
|
||||
v['PROVER_PCT'] = str(PROVER_PERCENT)
|
||||
v['MINER_PCT'] = str(100 - PROVER_PERCENT)
|
||||
v['RAMP_DAYS'] = str(RAMP_SECONDS // 86_400)
|
||||
v['RAMP_START'] = str(RAMP_START_PERCENT)
|
||||
v['B_STRETCH'] = str(B_STRETCH)
|
||||
v['C_HALF_LIFE_Y'] = str(C_HALF_LIFE_MONTHS // 12)
|
||||
v['REF_BUDGET_PCT'] = fixed(REF_BUDGET_BPS_OF_CAP, 100, 0)
|
||||
v['REF_BUDGET_IGN'] = mign(ref_budget(dec, (1, 1)), dec, 0)
|
||||
v['CSV_YEARS'] = str(CSV_YEARS)
|
||||
v['SEARCH_YEARS'] = group(str(SEARCH_YEARS))
|
||||
v['HORIZONS'] = ', '.join(str(h) for h in HORIZONS)
|
||||
v['MULTIPLES'] = ' / '.join(mult_label(m) for m in TV04_MULTIPLES)
|
||||
v['YEAR_SECONDS'] = group(str(YEAR))
|
||||
v['MAX_STEPS'] = group(str(MAX_CURVE_STEPS))
|
||||
|
||||
# schedules as code
|
||||
rows = []
|
||||
for t in tables:
|
||||
s = t.s
|
||||
n = s['step'] // YEAR if s['step'] % YEAR == 0 else s['step'] // MONTH
|
||||
step = '%d %s%s' % (n, 'year' if s['step'] % YEAR == 0 else 'month', '' if n == 1 else 's')
|
||||
rows.append((s['key'], s['label'], group(str(s['launch'])), mign(s['launch'] * YEAR, dec),
|
||||
'%s (%s)' % (group(str(s['step'])), step), group(str(s['decay'])), len(t.rates),
|
||||
t.zero_second() // YEAR + 1, ign(t.total(), dec), ign(capu - t.total(), dec)))
|
||||
v['T_SCHEDULES'] = md_table(['key', 'schedule', 'launch rate (base units a DAA second)', 'launch rate a year (IGN)',
|
||||
'step (DAA s)', 'step multiplier (Q32)', 'curve steps', 'subsidy zero from year',
|
||||
'scheduled total (IGN)', 'cap minus total (IGN)'], rows)
|
||||
|
||||
def per_h(fn):
|
||||
return [[t.s['key']] + [fn(t, y) for y in HORIZONS] for t in tables]
|
||||
hh = ['schedule'] + ['year %d' % y for y in HORIZONS]
|
||||
v['T_SUPPLY'] = md_table(hh, per_h(lambda t, y: '%s (%s)' % (mign(t.supply_at(y * YEAR), dec),
|
||||
pct(t.supply_at(y * YEAR), capu))))
|
||||
v['T_ISSUANCE'] = md_table(hh, per_h(lambda t, y: '%s (%s of cap)' % (mign(t.year_issuance(y), dec),
|
||||
pct(t.year_issuance(y), capu))))
|
||||
# early security income
|
||||
rows = []
|
||||
for t in tables:
|
||||
y1 = t.supply_at(YEAR)
|
||||
y5 = t.supply_at(5 * YEAR)
|
||||
m1, p1 = split(y1)
|
||||
m5, p5 = split(y5)
|
||||
rows.append((t.s['key'], mign(y1, dec), mign(m1, dec), mign(p1, dec), pct(y1, A.supply_at(YEAR), 1),
|
||||
mign(y5, dec), mign(m5, dec), mign(p5, dec), pct(y5, A.supply_at(5 * YEAR), 1)))
|
||||
v['T_SECURITY'] = md_table(['schedule', 'year 1 subsidy (IGN)', 'to miners', 'to provers', 'of A\'s year 1',
|
||||
'years 1 to 5 (IGN)', 'to miners', 'to provers', 'of A\'s years 1 to 5'], rows)
|
||||
# concentration
|
||||
rows = []
|
||||
for t in tables:
|
||||
s2, s20 = t.supply_at(2 * YEAR), t.supply_at(20 * YEAR)
|
||||
rows.append((t.s['key'], mign(s2, dec), pct(s2, capu), mign(s20 - s2, dec), pct(s20 - s2, capu),
|
||||
pct(s2, s20), fixed(s2, s20 - s2, 2), pct(capu - s20, capu)))
|
||||
v['T_CONC'] = md_table(['schedule', 'years 1 to 2 (IGN)', 'of cap', 'years 3 to 20 (IGN)', 'of cap',
|
||||
'years 1 to 2 of all issued by year 20', 'ratio 1-2 : 3-20', 'cap left after year 20'],
|
||||
rows)
|
||||
# late miners
|
||||
rows = []
|
||||
for t in tables:
|
||||
full1 = t.block_subsidy(t.s['ramp'], 1)
|
||||
r = [t.s['key'], ign(full1, dec, 4)]
|
||||
for jy in JOIN_YEARS:
|
||||
b = t.block_subsidy((jy - 1) * YEAR, 1)
|
||||
r.append('%s (%s)' % (ign(b, dec, 4), pct(b, full1)))
|
||||
rows.append(r)
|
||||
v['T_LATE'] = md_table(['schedule', 'year 1 full-rate subsidy a block (IGN, 1 block/s)'] +
|
||||
['joining in year %d: a block (share of year 1)' % jy for jy in JOIN_YEARS], rows)
|
||||
# fee dependence
|
||||
rows = []
|
||||
for m in TV04_MULTIPLES:
|
||||
r = ref_budget(dec, m)
|
||||
row = [mult_label(m), mign(r, dec, 0)]
|
||||
for t in tables:
|
||||
need = first_year(lambda y: t.year_issuance(y) < r)
|
||||
exceed = first_year(lambda y: 2 * t.year_issuance(y) < r)
|
||||
row.append('%s / %s' % (need, exceed))
|
||||
rows.append(row)
|
||||
v['T_FEES'] = md_table(['TV-04 multiple', 'reference budget a year (IGN)'] +
|
||||
['%s: year fees are needed / year fees exceed the subsidy' % t.s['key'] for t in tables], rows)
|
||||
# stretch sweep
|
||||
rows = []
|
||||
for t in [A] + sweep:
|
||||
s = t.s
|
||||
r1 = ref_budget(dec, (1, 1))
|
||||
rows.append([s['key'], mign(t.year_issuance(1), dec)] +
|
||||
[pct(t.supply_at(y * YEAR), capu) for y in (2, 5, 10, 20)] +
|
||||
[first_year(lambda y: 2 * t.year_issuance(y) < r1)])
|
||||
v['T_SWEEP'] = md_table(['schedule', 'year 1 subsidy (IGN)', 'issued by year 2', 'by year 5', 'by year 10',
|
||||
'by year 20', 'fees exceed subsidy at 1x (year)'], rows)
|
||||
# litepaper reconciliation (the litepaper's sentences are quoted inputs; the right-hand columns are computed)
|
||||
curve12 = sum(A.rates[k] * A.s['step'] for k in range(6))
|
||||
v['T_LITEPAPER'] = md_table(
|
||||
['litepaper sentence (site/litepaper.html)', 'the code, ramp included', 'the code\'s curve without the ramp'],
|
||||
[('"Half of the 4 billion cap is mined in the first two years"', pct(A.supply_at(2 * YEAR), capu),
|
||||
pct(A.rates[0] * A.s['step'], capu)),
|
||||
('"Nearly a quarter of all supply is mined in the first year"', pct(A.supply_at(YEAR), capu),
|
||||
pct(A.rates[0] * YEAR, capu)),
|
||||
('"3,938M IGN in the first 12 years of a 4,000M cap"', mign(A.supply_at(12 * YEAR), dec),
|
||||
mign(curve12, dec)),
|
||||
('"emission starts at 1 billion a year"', mign(A.year_issuance(1), dec) + ' in year 1',
|
||||
mign(A.rates[0] * YEAR, dec) + ' a year')])
|
||||
# the schedules as node genesis parameters (consensus/core/src/emission.rs EmissionSchedule, at mainnet's unit)
|
||||
code = []
|
||||
for t in tables:
|
||||
s = t.s
|
||||
code.append('// %s: %s\n// %s\nEmissionSchedule {\n launch_rate: %s,\n ramp_seconds: %s,\n'
|
||||
' ramp_start_percent: %d,\n step_seconds: %s,\n step_decay_q32: %s,\n tail: Tail::Cap,\n}'
|
||||
% (s['key'], s['label'], s['note'], '{:_}'.format(s['launch']), '{:_}'.format(s['ramp']),
|
||||
s['ramp_start'], '{:_}'.format(s['step']), '{:_}'.format(s['decay'])))
|
||||
v['CODE_SCHEDULES'] = '\n\n'.join(code)
|
||||
# one-sentence meanings that carry figures
|
||||
v['M_Y1_B'] = pct(B.supply_at(YEAR), A.supply_at(YEAR), 0)
|
||||
v['M_Y1_C'] = pct(C.supply_at(YEAR), A.supply_at(YEAR), 0)
|
||||
v['M_Y2_A'] = pct(A.supply_at(2 * YEAR), capu, 0)
|
||||
v['M_Y2_B'] = pct(B.supply_at(2 * YEAR), capu, 0)
|
||||
v['M_Y2_C'] = pct(C.supply_at(2 * YEAR), capu, 0)
|
||||
v['M_Y20_A'] = pct(A.supply_at(20 * YEAR), capu, 1)
|
||||
v['M_Y20_B'] = pct(B.supply_at(20 * YEAR), capu, 1)
|
||||
v['M_Y20_C'] = pct(C.supply_at(20 * YEAR), capu, 1)
|
||||
full = {t.s['key']: t.block_subsidy(t.s['ramp'], 1) for t in tables}
|
||||
v['M_LATE10_A'] = pct(A.block_subsidy(9 * YEAR, 1), full['A'], 1)
|
||||
v['M_LATE10_B'] = pct(B.block_subsidy(9 * YEAR, 1), full['B'], 1)
|
||||
v['M_LATE10_C'] = pct(C.block_subsidy(9 * YEAR, 1), full['C'], 1)
|
||||
v['M_LATE10_BA'] = fixed(B.block_subsidy(9 * YEAR, 1), A.block_subsidy(9 * YEAR, 1), 1)
|
||||
r1 = ref_budget(dec, (1, 1))
|
||||
for t in tables:
|
||||
v['M_EXC1_' + t.s['key']] = str(first_year(lambda y: 2 * t.year_issuance(y) < r1))
|
||||
r10 = ref_budget(dec, (10, 1))
|
||||
for t in tables:
|
||||
v['M_NEED10_' + t.s['key']] = str(first_year(lambda y: t.year_issuance(y) < r10))
|
||||
v['M_CLIFF_A'] = pct(A.year_issuance(3), A.year_issuance(2), 0)
|
||||
v['M_GLIDE_C'] = pct(C.year_issuance(3), C.year_issuance(2), 1)
|
||||
return v
|
||||
|
||||
|
||||
def render(tables, sweep, out, shas):
|
||||
with open(TEMPLATE, encoding='utf-8') as f:
|
||||
text = f.read()
|
||||
v = values(tables, sweep)
|
||||
v.update(shas)
|
||||
def sub(m):
|
||||
k = m.group(1)
|
||||
if k not in v:
|
||||
raise KeyError('template placeholder {{%s}} has no value' % k)
|
||||
return v[k]
|
||||
text = re.sub(r'\{\{([A-Z0-9_]+)\}\}', sub, text)
|
||||
if '—' in text:
|
||||
raise ValueError('an em dash in the README')
|
||||
with open(os.path.join(out, 'README.md'), 'w', encoding='utf-8', newline='\n') as f:
|
||||
f.write(text)
|
||||
|
||||
|
||||
OUTPUT_CSVS = ('d02-schedules.csv', 'd02-years.csv', 'd02-horizons.csv', 'd02-fee-dependence.csv')
|
||||
MANIFEST = 'd02-manifest.sha256'
|
||||
|
||||
|
||||
def generate(out):
|
||||
os.makedirs(out, exist_ok=True)
|
||||
main = [Table(s) for s in main_schedules()]
|
||||
sweep = [Table(schedule_stretch(s)) for s in SWEEP_STRETCH]
|
||||
everything = main + [t for t in sweep if t.s['key'] != 'B']
|
||||
bodies = {'d02-schedules.csv': csv_schedules(everything), 'd02-years.csv': csv_years(everything),
|
||||
'd02-horizons.csv': csv_horizons(everything), 'd02-fee-dependence.csv': csv_fees(everything)}
|
||||
for n in OUTPUT_CSVS:
|
||||
with open(os.path.join(out, n), 'w', encoding='utf-8', newline='\n') as f:
|
||||
f.write(bodies[n])
|
||||
shas = {'SHA_GENERATOR': sha256_file(os.path.abspath(__file__)), 'SHA_TEMPLATE': sha256_file(TEMPLATE),
|
||||
'SHA_TEST': sha256_file(os.path.join(HERE, 'test_d02.py'))}
|
||||
for n in OUTPUT_CSVS:
|
||||
shas['SHA_' + n.replace('d02-', '').replace('.csv', '').replace('-', '_').upper()] = \
|
||||
sha256_file(os.path.join(out, n))
|
||||
render(main, sweep, out, shas)
|
||||
names = list(OUTPUT_CSVS) + ['README.md']
|
||||
lines = ['# input %s %s' % (shas['SHA_GENERATOR'], 'tools/token-value/d02/d02_emission.py'),
|
||||
'# input %s %s' % (shas['SHA_TEMPLATE'], 'tools/token-value/d02/README.template.md')]
|
||||
lines += ['%s %s' % (sha256_file(os.path.join(out, n)), n) for n in names]
|
||||
with open(os.path.join(out, MANIFEST), 'w', encoding='utf-8', newline='\n') as f:
|
||||
f.write('\n'.join(lines) + '\n')
|
||||
return names + [MANIFEST]
|
||||
|
||||
|
||||
def manifest_names(out):
|
||||
p = os.path.join(out, MANIFEST)
|
||||
if not os.path.exists(p):
|
||||
return []
|
||||
with open(p, encoding='utf-8') as f:
|
||||
names = [ln.split(' ', 1)[1].strip() for ln in f if ln.strip() and not ln.startswith('#')]
|
||||
return names + [MANIFEST]
|
||||
|
||||
|
||||
def compare(committed, fresh):
|
||||
"""Names that differ (or are missing) between a committed output folder and a fresh one."""
|
||||
bad = []
|
||||
for n in manifest_names(committed) or list(OUTPUT_CSVS) + ['README.md', MANIFEST]:
|
||||
a, b = os.path.join(committed, n), os.path.join(fresh, n)
|
||||
if not (os.path.exists(a) and os.path.exists(b)) or read_bytes(a) != read_bytes(b):
|
||||
bad.append(n)
|
||||
return bad
|
||||
|
||||
|
||||
# ---- the cross-checks against the node's source ---------------------------------------------------------------------
|
||||
def node_src_check(root):
|
||||
src = lambda rel: read_bytes(os.path.join(root, rel)).decode('utf-8')
|
||||
em = src('consensus/core/src/emission.rs')
|
||||
ig = src('consensus/core/src/igneum.rs')
|
||||
pa = src('consensus/core/src/config/params.rs')
|
||||
un = src('consensus/core/src/unit.rs')
|
||||
num = lambda s: int(s.replace('_', ''))
|
||||
cur = re.search(r'pub const CURRENT: EmissionSchedule = EmissionSchedule \{(.*?)\};', em, re.S).group(1)
|
||||
got = {
|
||||
'YEAR_SECONDS': num(re.search(r'pub const YEAR_SECONDS: u64 = ([\d_]+);', em).group(1)),
|
||||
'MAX_CURVE_STEPS': num(re.search(r'pub const MAX_CURVE_STEPS: usize = ([\d_]+);', em).group(1)),
|
||||
'CURRENT.launch_rate': num(re.search(r'launch_rate: ([\d_]+)', cur).group(1)),
|
||||
'CURRENT.ramp_seconds': num(re.search(r'ramp_seconds: ([\d_]+)', cur).group(1)),
|
||||
'CURRENT.ramp_start_percent': num(re.search(r'ramp_start_percent: ([\d_]+)', cur).group(1)),
|
||||
'CURRENT.step_seconds': re.search(r'step_seconds: ([^,]+),', cur).group(1).strip(),
|
||||
'CURRENT.step_decay_q32': re.search(r'step_decay_q32: ([^,]+),', cur).group(1).strip(),
|
||||
'CURRENT.tail': re.search(r'tail: ([^,]+),', cur).group(1).strip(),
|
||||
'YEAR_ONE_EMISSION': num(re.search(r'YEAR_ONE_EMISSION_SOMPI: u64 = ([\d_]+) \*', ig).group(1)),
|
||||
'SUPPLY_CAP': num(re.search(r'SUPPLY_CAP_SOMPI: u64 = ([\d_]+) \*', ig).group(1)),
|
||||
'PROVING_POOL_SHARE_PERCENT': num(re.search(r'PROVING_POOL_SHARE_PERCENT: u64 = ([\d_]+);', ig).group(1)),
|
||||
'DEVNET_DECIMALS': num(re.search(r'pub const DEVNET_DECIMALS: u8 = (\d+);', un).group(1)),
|
||||
'EVM_DECIMALS': num(re.search(r'pub const EVM_DECIMALS: u8 = (\d+);', un).group(1)),
|
||||
'MAINNET emission': 'EmissionSchedule::CURRENT.rescaled(crate::unit::DEVNET_DECIMALS, crate::unit::EVM_DECIMALS)'
|
||||
in pa.split('pub const MAINNET_PARAMS', 1)[1].split('pub const TESTNET_PARAMS', 1)[0],
|
||||
}
|
||||
want = {'YEAR_SECONDS': YEAR, 'MAX_CURVE_STEPS': MAX_CURVE_STEPS, 'CURRENT.launch_rate': A_LAUNCH8,
|
||||
'CURRENT.ramp_seconds': RAMP_SECONDS, 'CURRENT.ramp_start_percent': RAMP_START_PERCENT,
|
||||
'CURRENT.step_seconds': '2 * YEAR_SECONDS', 'CURRENT.step_decay_q32': '1 << 31',
|
||||
'CURRENT.tail': 'Tail::Cap', 'YEAR_ONE_EMISSION': YEAR_ONE_COINS, 'SUPPLY_CAP': CAP_COINS,
|
||||
'PROVING_POOL_SHARE_PERCENT': PROVER_PERCENT, 'DEVNET_DECIMALS': NODE_DECIMALS,
|
||||
'EVM_DECIMALS': MAIN_DECIMALS, 'MAINNET emission': True}
|
||||
bad = 0
|
||||
for k in want:
|
||||
ok = got[k] == want[k]
|
||||
bad += not ok
|
||||
print('%-28s code %-24s generator %-24s %s' % (k, got[k], want[k], 'agree' if ok else 'DIFFER'))
|
||||
print('NODE-SRC: %s' % ('every constant agrees' if not bad else '%d DIFFER' % bad))
|
||||
return bad
|
||||
|
||||
|
||||
def params_lines():
|
||||
out = []
|
||||
for s in [schedule_current(NODE_DECIMALS)] + all_schedules():
|
||||
out.append('%s %d %d %d %d %d %d' % (s['key'], s['decimals'], s['launch'], s['ramp'], s['ramp_start'],
|
||||
s['step'], s['decay']))
|
||||
return '\n'.join(out) + '\n'
|
||||
|
||||
|
||||
def node_csv():
|
||||
out = ['key,year,emission_base_units,supply_end_base_units,block_subsidy_year_start_1bps']
|
||||
for s in [schedule_current(NODE_DECIMALS)] + all_schedules():
|
||||
t = Table(s)
|
||||
if s['key'] == 'A' and s['decimals'] == MAIN_DECIMALS:
|
||||
out.append('#A18,is_mainnet_params_emission,true')
|
||||
tag = '%s%d' % (s['key'], s['decimals'])
|
||||
out.append('#%s,steps,%d,final_supply,%d' % (tag, len(t.rates), t.supplies[-1]))
|
||||
for y in range(1, CSV_YEARS + 1):
|
||||
out.append('%s,%d,%d,%d,%d' % (tag, y, t.year_issuance(y), t.supply_at(y * YEAR),
|
||||
t.block_subsidy((y - 1) * YEAR, 1)))
|
||||
return '\n'.join(out) + '\n'
|
||||
|
||||
|
||||
def fee_series(flat_ign, growth_bps):
|
||||
print('fee series (a parameter, not a forecast): %s IGN in year 1, growing %s bps a year' % (flat_ign, growth_bps))
|
||||
print('first year the subsidy plus this fee series falls under the reference budget (none = holds through year %d)'
|
||||
% SEARCH_YEARS)
|
||||
for s in main_schedules():
|
||||
t = Table(s)
|
||||
dec = s['decimals']
|
||||
f0 = flat_ign * 10 ** dec
|
||||
fee = lambda y: f0 * (10_000 + growth_bps) ** (y - 1) // 10_000 ** (y - 1)
|
||||
for m in TV04_MULTIPLES:
|
||||
r = ref_budget(dec, m)
|
||||
y = first_year(lambda y: t.year_issuance(y) + fee(y) < r)
|
||||
print('%s %s budget %s: %s' % (s['key'], mult_label(m), mign(r, dec, 0), y))
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||
ap.add_argument('--out')
|
||||
ap.add_argument('--check')
|
||||
ap.add_argument('--node-src')
|
||||
ap.add_argument('--params', action='store_true')
|
||||
ap.add_argument('--node-csv', action='store_true')
|
||||
ap.add_argument('--fee-flat-ign', type=int)
|
||||
ap.add_argument('--fee-growth-bps', type=int, default=0)
|
||||
a = ap.parse_args()
|
||||
if a.out:
|
||||
for n in generate(a.out):
|
||||
print('%s %s' % (sha256_file(os.path.join(a.out, n)), n))
|
||||
elif a.check:
|
||||
d = tempfile.mkdtemp(prefix='d02-check-')
|
||||
try:
|
||||
generate(d)
|
||||
bad = compare(a.check, d)
|
||||
finally:
|
||||
shutil.rmtree(d)
|
||||
print('CHECK: %s' % ('byte-identical' if not bad else 'DIFFER ' + ' '.join(bad)))
|
||||
sys.exit(1 if bad else 0)
|
||||
elif a.node_src:
|
||||
sys.exit(1 if node_src_check(a.node_src) else 0)
|
||||
elif a.params:
|
||||
sys.stdout.write(params_lines())
|
||||
elif a.node_csv:
|
||||
sys.stdout.write(node_csv())
|
||||
elif a.fee_flat_ign is not None:
|
||||
fee_series(a.fee_flat_ign, a.fee_growth_bps)
|
||||
else:
|
||||
ap.print_help()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
41
tools/token-value/d02/node_crosscheck/d02_emission_csv.rs
Normal file
41
tools/token-value/d02/node_crosscheck/d02_emission_csv.rs
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
//! D02 cross-check (Token Value Phase 0, 9 October 2026). Not part of any workspace in the igneum repo: run_on_box.sh
|
||||
//! copies it into a checkout of the node fork at release-2.0.2-node (a284380b) as
|
||||
//! consensus/core/examples/d02_emission_csv.rs, runs it, and removes it; the node's code is never changed.
|
||||
//!
|
||||
//! cargo run --release -p kaspa-consensus-core --example d02_emission_csv -- <params.txt>
|
||||
//!
|
||||
//! params.txt is the generator's `--params` output: one schedule a line, "key decimals launch_rate ramp_seconds
|
||||
//! ramp_start_percent step_seconds step_decay_q32". Every row printed is computed by the node's own EmissionTable
|
||||
//! (`kaspa_consensus_core::emission`), so the generator's `--node-csv` must print the same bytes.
|
||||
|
||||
use kaspa_consensus_core::config::params::MAINNET_PARAMS;
|
||||
use kaspa_consensus_core::emission::{EmissionSchedule, Tail, YEAR_SECONDS};
|
||||
|
||||
fn main() {
|
||||
let path = std::env::args().nth(1).expect("params file");
|
||||
let text = std::fs::read_to_string(&path).expect("read params");
|
||||
println!("key,year,emission_base_units,supply_end_base_units,block_subsidy_year_start_1bps");
|
||||
for line in text.lines().filter(|l| !l.trim().is_empty()) {
|
||||
let f: Vec<&str> = line.split_whitespace().collect();
|
||||
let n = |i: usize| -> u128 { f[i].parse().expect("number") };
|
||||
let s = EmissionSchedule {
|
||||
launch_rate: n(2),
|
||||
ramp_seconds: n(3) as u64,
|
||||
ramp_start_percent: n(4) as u64,
|
||||
step_seconds: n(5) as u64,
|
||||
step_decay_q32: n(6) as u64,
|
||||
tail: Tail::Cap,
|
||||
};
|
||||
s.validate().expect("valid schedule");
|
||||
if f[0] == "A" && f[1] == "18" {
|
||||
println!("#A18,is_mainnet_params_emission,{}", s == MAINNET_PARAMS.emission);
|
||||
}
|
||||
let t = s.table();
|
||||
println!("#{}{},steps,{},final_supply,{}", f[0], f[1], t.step_rate.len(), t.step_supply.last().unwrap());
|
||||
for y in 1..=40u64 {
|
||||
let a = (y - 1) * YEAR_SECONDS;
|
||||
let b = y * YEAR_SECONDS;
|
||||
println!("{}{},{},{},{},{}", f[0], f[1], y, t.scheduled_emission_between(a, b), t.scheduled_supply_at(b), t.block_subsidy(a, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
39
tools/token-value/d02/run_on_box.sh
Executable file
39
tools/token-value/d02/run_on_box.sh
Executable file
|
|
@ -0,0 +1,39 @@
|
|||
#!/usr/bin/env bash
|
||||
# D02 runner, build-3 only (founder's stop rule 2: no model runs on the Mac). Writes its pid file first:
|
||||
# ~/tv-d02/run.pid as "<pid> <start UTC> tv-d02 <mode>" and removes it on exit.
|
||||
# Usage, on build-3 from a checkout of this branch at ~/tv-d02/igneum:
|
||||
# tools/token-value/d02/run_on_box.sh test the tests (the first run is the known-failed one)
|
||||
# tools/token-value/d02/run_on_box.sh generate regenerate the outputs into the docs folder, then the tests
|
||||
# tools/token-value/d02/run_on_box.sh crosscheck the node's own Rust (release-2.0.2-node) against the generator
|
||||
set -euo pipefail
|
||||
export PATH="$HOME/.cargo/bin:$PATH"
|
||||
mode="${1:?test|generate|crosscheck}"
|
||||
base="$HOME/tv-d02"; mkdir -p "$base"
|
||||
pidf="$base/run.pid"
|
||||
echo "$$ $(date -u +%Y-%m-%dT%H:%M:%SZ) tv-d02 $mode" > "$pidf"
|
||||
trap 'rm -f "$pidf" "$base/igneum/vendor/rusty-kaspa/consensus/core/examples/d02_emission_csv.rs"' EXIT
|
||||
cd "$(git rev-parse --show-toplevel)"
|
||||
echo "host $(hostname) python $(python3 --version 2>&1) commit $(git rev-parse HEAD) utc $(date -u +%Y-%m-%dT%H:%M:%SZ) pidfile $pidf"
|
||||
case "$mode" in
|
||||
test) python3 tools/token-value/d02/test_d02.py ;;
|
||||
generate)
|
||||
python3 tools/token-value/d02/d02_emission.py --out docs/plans/igneum-2.0-master/token-value/phase0/d02
|
||||
python3 tools/token-value/d02/test_d02.py ;;
|
||||
crosscheck)
|
||||
node="$(pwd)/vendor/rusty-kaspa" # the layout the node expects: igneum-pow at ../../../../igneum-pow from consensus/pow
|
||||
# the checkout arrives from the Mac by rsync (build-3 reaches neither node mirror); re-stamped before cargo reads it
|
||||
test "$(git -C "$node" rev-parse HEAD)" = a284380bdd62d5d0d972cb38f2cbd1daeedda69d
|
||||
test -z "$(git -C "$node" status --porcelain)"
|
||||
find "$node" -path "$node/.git" -prune -o -type f -exec touch {} +
|
||||
echo "node $(git -C "$node" rev-parse HEAD) emission.rs blob $(git -C "$node" rev-parse HEAD:consensus/core/src/emission.rs)"
|
||||
python3 tools/token-value/d02/d02_emission.py --node-src "$node"
|
||||
cp tools/token-value/d02/node_crosscheck/d02_emission_csv.rs "$node/consensus/core/examples/d02_emission_csv.rs"
|
||||
python3 tools/token-value/d02/d02_emission.py --params > "$base/params.txt"
|
||||
( cd "$node" && CARGO_TARGET_DIR="$base/target" cargo run -q -j 8 --release -p kaspa-consensus-core --example d02_emission_csv -- "$base/params.txt" ) > "$base/node.csv"
|
||||
python3 tools/token-value/d02/d02_emission.py --node-csv > "$base/python.csv"
|
||||
rm -f "$node/consensus/core/examples/d02_emission_csv.rs"
|
||||
echo "node rows $(wc -l < "$base/node.csv") sha256 $(sha256sum "$base/node.csv" | cut -c1-64)"
|
||||
echo "python rows $(wc -l < "$base/python.csv") sha256 $(sha256sum "$base/python.csv" | cut -c1-64)"
|
||||
if cmp -s "$base/node.csv" "$base/python.csv"; then echo "CROSSCHECK: byte-identical"; else echo "CROSSCHECK: DIFFER"; diff "$base/node.csv" "$base/python.csv" | head -20; exit 1; fi ;;
|
||||
*) echo "unknown mode $mode"; exit 2 ;;
|
||||
esac
|
||||
92
tools/token-value/d02/test_d02.py
Executable file
92
tools/token-value/d02/test_d02.py
Executable file
|
|
@ -0,0 +1,92 @@
|
|||
#!/usr/bin/env python3
|
||||
"""D02 tests (Token Value Phase 0, 9 October 2026). Written before the generator; the first run failed on purpose
|
||||
(evidence/known-failed-first.log). Standalone Python 3, no third-party packages.
|
||||
|
||||
python3 tools/token-value/d02/test_d02.py from the repo root
|
||||
|
||||
What it holds:
|
||||
1. the generator reproduces the node's own constants (release-2.0.2-node a284380b): the 33-step table of the
|
||||
current schedule at 8 decimals, the ramp's withheld coins between 36 and 38 million, and the Q32 two-year
|
||||
glide multiplier 4,172,697,914 written in emission.rs;
|
||||
2. every schedule compared is same-cap (its scheduled total never exceeds the cap) and is a valid release-2.0.2
|
||||
EmissionSchedule (reaches zero inside MAX_CURVE_STEPS, Tail::Cap);
|
||||
3. the committed outputs regenerate byte-identically (every file the manifest names), and a one-byte change to a
|
||||
copy is caught (the check can fail).
|
||||
"""
|
||||
import os, sys, tempfile, shutil, unittest, hashlib
|
||||
|
||||
HERE = os.path.dirname(os.path.abspath(__file__))
|
||||
ROOT = os.path.abspath(os.path.join(HERE, '..', '..', '..'))
|
||||
OUT = os.path.join(ROOT, 'docs/plans/igneum-2.0-master/token-value/phase0/d02')
|
||||
sys.path.insert(0, HERE)
|
||||
import d02_emission as g # noqa: E402 (the first run failed here: the generator did not exist yet)
|
||||
|
||||
|
||||
class NodeConstants(unittest.TestCase):
|
||||
def test_current_at_8_decimals_is_the_33_step_table(self):
|
||||
t = g.Table(g.schedule_current(8))
|
||||
self.assertEqual(len(t.rates), 33)
|
||||
self.assertEqual(t.rates[0], 3_168_808_781)
|
||||
self.assertEqual(t.rates[-1], 0)
|
||||
withheld = g.CAP_COINS * 10 ** 8 - t.supply_at(2 ** 62)
|
||||
self.assertTrue(36_000_000 * 10 ** 8 < withheld < 38_000_000 * 10 ** 8, withheld)
|
||||
|
||||
def test_q32_root_reproduces_the_node_glide_constant(self):
|
||||
self.assertEqual(g.q32_pow2_neg_inv(24), 4_172_697_914)
|
||||
self.assertEqual(g.q32_pow2_neg_inv(1), 1 << 31)
|
||||
|
||||
def test_ramp_and_block_subsidy_match_the_node_rules(self):
|
||||
t = g.Table(g.schedule_current(8))
|
||||
self.assertEqual(t.block_subsidy(0, 1), 3_168_808_781 * 10 // 100)
|
||||
self.assertEqual(t.block_subsidy(2_592_000, 1), 3_168_808_781)
|
||||
self.assertEqual(t.block_subsidy(2 * g.YEAR, 1), 1_584_404_390)
|
||||
|
||||
|
||||
class SameCap(unittest.TestCase):
|
||||
def test_every_schedule_is_same_cap_and_node_valid(self):
|
||||
for s in g.all_schedules():
|
||||
t = g.Table(s)
|
||||
self.assertLessEqual(t.supply_at(2 ** 62), g.CAP_COINS * 10 ** s['decimals'], s['key'])
|
||||
self.assertEqual(t.rates[-1], 0, s['key'])
|
||||
self.assertLessEqual(len(t.rates), g.MAX_CURVE_STEPS, s['key'])
|
||||
# same cap within the ramp's withheld coins and the floors: at least 99 percent of the cap is scheduled
|
||||
self.assertGreaterEqual(100 * t.supply_at(2 ** 62), 99 * g.CAP_COINS * 10 ** s['decimals'], s['key'])
|
||||
|
||||
def test_the_longer_schedules_pay_less_in_year_one(self):
|
||||
a = g.Table(g.schedule_current(18)).supply_at(g.YEAR)
|
||||
for s in g.all_schedules():
|
||||
if s['key'] != 'A':
|
||||
self.assertLess(g.Table(s).supply_at(g.YEAR), a, s['key'])
|
||||
|
||||
|
||||
class ByteIdentical(unittest.TestCase):
|
||||
def test_outputs_regenerate_byte_identically(self):
|
||||
d = tempfile.mkdtemp(prefix='d02-')
|
||||
try:
|
||||
g.generate(d)
|
||||
names = g.manifest_names(OUT)
|
||||
self.assertTrue(names, 'the committed manifest is empty or missing')
|
||||
for n in names:
|
||||
with open(os.path.join(OUT, n), 'rb') as f1, open(os.path.join(d, n), 'rb') as f2:
|
||||
self.assertEqual(f1.read(), f2.read(), n)
|
||||
self.assertEqual(g.compare(OUT, d), [])
|
||||
finally:
|
||||
shutil.rmtree(d)
|
||||
|
||||
def test_a_one_byte_change_is_caught(self):
|
||||
d = tempfile.mkdtemp(prefix='d02-')
|
||||
try:
|
||||
g.generate(d)
|
||||
victim = os.path.join(d, 'd02-years.csv')
|
||||
with open(victim, 'rb') as f:
|
||||
b = bytearray(f.read())
|
||||
b[-2] = ord('9') if b[-2] != ord('9') else ord('8')
|
||||
with open(victim, 'wb') as f:
|
||||
f.write(bytes(b))
|
||||
self.assertIn('d02-years.csv', g.compare(OUT, d))
|
||||
finally:
|
||||
shutil.rmtree(d)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
||||
Loading…
Reference in a new issue