Merge tv-02-supply-replay 2fd7d3d3 into master (gate: green on 22a4f326, recorded by tools/ci/pre-push.sh; landed on the build mirror)
This commit is contained in:
commit
d7a1bcb24c
6 changed files with 166 additions and 22 deletions
|
|
@ -13,7 +13,10 @@ end and every halving step until the subsidy is 0), the terminal block and one f
|
|||
byte-identical. Both reorg fixtures agree with each other and with integers written by hand before either replay ran,
|
||||
and the known-failed no-undo ledger is refused. Implementation B written from the published words alone (rule set
|
||||
v0) diverges at the first row, genesis. The cause is one rule the words never state: genesis issues nothing, so the
|
||||
block at height h carries DAA score h - 1. The total at the terminal is unchanged by it. No cap breach, no issuance
|
||||
block at height h carries DAA score h - 1. The total at the terminal is unchanged by it. On the TV-01 lane's supply spec (supply-spec.json at
|
||||
tv-01-supply-spec 9cd09130, which states that rule) B agrees with A to the integer on both profiles the spec carries,
|
||||
devnet-4 and mainnet, and on both reorg fixtures, and A's terminal rows equal the terminal supplies the spec itself
|
||||
states. No cap breach, no issuance
|
||||
after the terminal block, and the node's two issuance code paths agree on all 46,010,980,803 blocks replayed.
|
||||
|
||||
| network object | blocks a second | decimals | terminal block (last with a subsidy) | issued supply at the terminal, base units | IGN | under the 4,000,000,000 cap by |
|
||||
|
|
@ -39,7 +42,8 @@ subsidy of the table below; a pool sees the same numbers per block found. Neithe
|
|||
| the node's issuance code | igneum-node bf60948a (release-2.0.3-node-k6); the six files that decide issuance are byte-identical in release-2.0.2-node a284380b: consensus/core/src/emission.rs, consensus/core/src/igneum.rs, consensus/src/processes/coinbase.rs, consensus/core/src/config/params.rs, consensus/src/processes/window.rs, consensus/src/processes/difficulty.rs |
|
||||
| the volume's rules | docs/plans/igneum-2.0-master/token-value/rules-and-gates.json, sha256 10ce307329e1663d... (TV-02, VR-02, D01) |
|
||||
| the published words | site/litepaper.html (sha256 35ac65e151339089..., blob db1b8bf7b1d2) and site/economics.html (sha256 449c20b85cc4eede..., blob b15926199f06), both at master 6824d49cc32d |
|
||||
| the TV-01 supply spec | not landed at the time of this run (docs/plans/igneum-2.0-master/token-value/phase0/tv-01/supply-spec.json, a first version due 13:00 UK). B ran on the two interim rule sets below; the re-run on the spec is the open row R1 |
|
||||
| the TV-01 supply spec | docs/plans/igneum-2.0-master/token-value/phase0/tv-01/supply-spec.json (schema 1.0.0) at the TV-01 lane's branch tip tv-01-supply-spec 9cd091303 ("TV-01 complete"), blob bdddb09df2cd, sha256 3ffdd3084aff06d963df6c326cda88719d576f07d9cbfb56079de1a8b40c4403; not yet on master when B ran on it (09:0x UTC). Mapped to B's rules by tools/token-value/tv-02/replay-spec/tv01_adapter.py (rules-tv01-spec.json, sha256 061fa669be287b73...), which refuses any rule it cannot map |
|
||||
| B's interim rule sets, before the spec | the two below, run first (08:22 UTC) |
|
||||
| B's rules v0 (words only) | tools/token-value/tv-02/replay-spec/rules-v0-litepaper.json, sha256 67707b095584d8bb8bc99e799875b8d167512085385ea6883bc12575d98fbb33 |
|
||||
| B's rules v0.1 (v0 plus the genesis rule) | tools/token-value/tv-02/replay-spec/rules-v0.1-genesis-rule.json, sha256 d72d5578dfe4e0c860b45fdb37a749dd7f1b0365175a38349dd413b1e93eb0b9; the genesis rule from the node lane's written answer (9 October 2026, 09:25 UK), cited by file and line |
|
||||
|
||||
|
|
@ -94,7 +98,7 @@ no-undo ledger are each reported; equal inputs read EQUAL).
|
|||
|
||||
## Results
|
||||
|
||||
Run 9 October 2026, 08:22 to 08:35 UTC. A on build-5, B on build-6, the comparison on build-5 over B's outputs
|
||||
Run 9 October 2026, 08:22 to 08:35 UTC (rule sets v0 and v0.1) and 09:03 to 09:07 UTC (the TV-01 spec). A on build-5, B on build-6, the comparison on build-5 over B's outputs
|
||||
copied from build-6. A rebuilt from this landing's source re-ran byte-identical (the second run under rerun-final/).
|
||||
|
||||
| comparison | rules (B) | result | first difference |
|
||||
|
|
@ -106,6 +110,12 @@ copied from build-6. A rebuilt from this landing's source re-ran byte-identical
|
|||
| reorg-first-step-k2 | v0.1 | EQUAL, every row, and both equal the hand-written integers; no-undo refused | none |
|
||||
| straight, all three objects | v0 (words only) | DIFFER | row 1, genesis: A (0, 0, subsidy 0, cumulative 0), B (0, 0, 3168808781000000000, 3168808781000000000) on devnet-4; 316880878100000000 on mainnet; 316880878 on devnet. Every later row is one block apart in height; the terminal total is identical |
|
||||
| both reorg fixtures | v0 (words only) | DIFFER from A and from the fixture, by the same one-block shift | row 1, the ancestor: A DAA 2,591,999, cumulative 45174523722296485498848000; B DAA 2,592,000, cumulative 45174555410384295498848000 |
|
||||
| straight, devnet-4, 232 rows | the TV-01 spec | EQUAL, byte-identical (sha256 6ede4f4a2fe3c551...) | none, the ramp's end and steps 1 to 65 (the spec's 66 transitions), the terminal and one step past |
|
||||
| straight, mainnet, 226 rows | the TV-01 spec | EQUAL, byte-identical (sha256 3cf7f426d062722d...) | none, the ramp's end and steps 1 to 62 (the spec's 63 transitions) |
|
||||
| reorg-ramp-end-k1 and reorg-first-step-k2 | the TV-01 spec | EQUAL, every row, both equal the hand-written integers; no-undo refused | none |
|
||||
| A's terminal rows against the spec's own numbers | the TV-01 spec | EQUAL: mainnet 3963038999610200467816224000 at height 39,131,424,000; devnet-4 3963038999610200483289816000 at height 4,102,488,000 | none |
|
||||
|
||||
The spec carries the devnet-4 and mainnet profiles only; the 8-decimal devnet stands on rule set v0.1.
|
||||
|
||||
The rule that explains the v0 divergence: the published words (litepaper, economics page) never say what genesis
|
||||
issues or which DAA score block h carries. The node's rule is that genesis never enters the DAA window
|
||||
|
|
@ -141,14 +151,15 @@ read back over the EVM RPC on 8 October 2026); this replay did not read the chai
|
|||
|
||||
| id | row | state | waits on, earliest clock |
|
||||
|---|---|---|---|
|
||||
| R1 | Re-run B on the TV-01 supply spec and record its sha here | BLOCKED | the spec's first version, due 13:00 UK today; the re-run takes under a minute on build-6 |
|
||||
| R2 | The published words (and the TV-01 spec) must state the genesis rule: genesis issues nothing, block h carries DAA score h - 1. Without it a reader reproduces the supply one block early (the v0 divergence above) | BLOCKED | TV-01's spec text |
|
||||
| R3 | The words must state the per-block order at more than one block a second: the per-second rate divided by the blocks a second and floored, then the ramp (B assumed it; it matches the node). The other order changes the mainnet ramp's sum | BLOCKED | TV-01's spec text |
|
||||
| R4 | The mainnet object's 10 blocks a second against the litepaper's "1 / s blocks, rising to 10 (designed)": the supply at 10 differs from 1 by 15,473,592,000 base units (0.000000015 IGN) and ends six years earlier (year 124, not 130); which rate mainnet launches at is a spec question | BLOCKED | TV-01, D01 |
|
||||
| R1 | B re-ran on the TV-01 spec at 9cd09130 (EQUAL above). If the spec changes before or when it lands on master, B re-runs on the landed sha (under a minute on build-6; the adapter refuses an unmapped rule) | NOT RUN | the spec's landing on master |
|
||||
| R2 | The genesis rule (genesis issues nothing, block h carries DAA score h - 1) is now stated in the TV-01 spec (rules.genesis_rule, "genesis-unrewarded"); the litepaper and economics page still do not state it, and a reader of the words alone reproduces the supply one block early (the v0 divergence above) | NOT RUN | the site lane, if the served words take it |
|
||||
| R3 | The per-block order at more than one block a second (the per-second rate divided by the blocks a second and floored, then the ramp) is stated in the TV-01 spec (rules.per_block); B had assumed it from the words and it matches the node | NOT RUN | none |
|
||||
| R4 | The TV-01 spec names the mainnet profile (MAINNET_PARAMS, 10 blocks a second) as the monetary contract; the litepaper says "1 / s blocks, rising to 10 (designed)". At 10 the supply differs from 1 by 15,473,592,000 base units (0.000000015 IGN) and ends six years earlier (year 124, not 130) | NOT RUN | none for TV-02 |
|
||||
| R5 | The 8-decimal and 18-decimal schedules are not the same coin amounts after the first halving (3,168,808,781 is odd, so the 8-decimal halving floors and the 18-decimal one does not): the 18-decimal supply is 10.74 IGN larger. igneum.rs's comment that the 18-decimal numbers are "the 8-decimal ones times 10^10" holds for the launch rate only. Informational; no network mixes the two | NOT RUN | none |
|
||||
| R6 | The testnet-1 object carries a percent tail (`EmissionSchedule::TESTNET_1`, no cap). D01 ratified capped issuance; that object is outside it and was not replayed | BLOCKED | TV-01, D01 |
|
||||
| R7 | DEVNET4_GENESIS carries the 8-byte subsidy layout on an 18-decimal network: read at 16 bytes its subsidy field is 134825277635862783248051596202800963840 base units (A's genesis-payload output). The window rule keeps it from ever being paid (the node lane, 09:25 UK); any other reader of that field (an explorer, an executor path) must apply the same rule. The node lane takes the B10 test case for devnet-3 and devnet-4 as a 2.0.3 test item | NOT RUN | the node lane's 2.0.3 test |
|
||||
| R8 | The rest of the gate's procedure: paid (the 80/20 split is by subtraction, so producer plus pool equals the subsidy per block by construction), burned (the pool's OP_RETURN script on devnet v0), locked, outstanding, red and non-DAA blocks in a DAG, the execution layer's ledger, duplicate records, wrappers. This replay covers issued supply on a straight chain and its reorg only | NOT RUN | a later TV-02 item |
|
||||
| R10 | The compiled mainnet genesis still carries Kaspa's DAA score 1,312,860 (the TV-01 spec's C09, BLOCKED there). Both replays and the spec's profile take genesis at DAA 0; a mainnet genesis at 1,312,860 would start the schedule 131,286 seconds into the ramp | BLOCKED | TV-01's C09, the node lane |
|
||||
| R9 | Independence: A and B share no code, language or method, but one lane wrote both and B's rules were written after reading the node; the panel should weigh that | NOT RUN | the independent panel |
|
||||
|
||||
## Run commands
|
||||
|
|
@ -169,12 +180,14 @@ On build-6 (B), from tools/token-value/tv-02 alone (no node code on the box):
|
|||
./run-b.sh <tv-02 dir> /srv/artefacts/token-value/tv-02 replay-spec/rules-v0.1-genesis-rule.json selftest
|
||||
./run-b.sh <tv-02 dir> /srv/artefacts/token-value/tv-02 replay-spec/rules-v0.1-genesis-rule.json straight devnet4
|
||||
./run-b.sh <tv-02 dir> /srv/artefacts/token-value/tv-02 replay-spec/rules-v0.1-genesis-rule.json reorg fixtures/reorg-ramp-end-k1.json
|
||||
python3 replay-spec/tv01_adapter.py <supply-spec.json> replay-spec/rules-tv01-spec.json # then the same three commands on it
|
||||
```
|
||||
|
||||
The comparison, on build-5 with B's outputs copied to <out>/from-build-6:
|
||||
|
||||
```
|
||||
tools/token-value/tv-02/compare-all.sh <tv-02 dir> /srv/artefacts/token-value/tv-02 rules-v0.1-genesis-rule
|
||||
NETS="devnet4 mainnet" SPEC_RULES=<out>/from-build-6/rules-tv01-spec.json tools/token-value/tv-02/compare-all.sh <tv-02 dir> /srv/artefacts/token-value/tv-02 rules-tv01-spec
|
||||
python3 tools/token-value/tv-02/table.py a-devnet4.csv a-devnet4-labels.csv 18
|
||||
```
|
||||
|
||||
|
|
@ -189,5 +202,6 @@ Each run writes its pid file first (run-a.pid, run-b.pid, compare.pid in the out
|
|||
| the comparison logs and tables | build-5:/srv/artefacts/token-value/tv-02/compare-rules-v0.1-genesis-rule.log (sha256 81545cc811ff208b...), compare-rules-v0-litepaper.log (sha256 f743ecf3a323afba...), table-*.md |
|
||||
| all of the above, copied | build-1:/srv/artefacts/token-value/tv-02/build-5/ and build-1:/srv/artefacts/token-value/tv-02/build-6/ |
|
||||
| the binary that ran | tv02-replay-node sha256 ef3af79157947584... (source at 4e206eaf8); rebuilt from this landing 25ff78695bd9d972..., outputs byte-identical |
|
||||
| B's code that ran | replay_spec.py sha256 acd68e1b8f9f4d1a591791caa408ba539680125db1af763fe0a7fb7e1e25eaf4 (this landing's file) |
|
||||
| B's code that ran | replay_spec.py sha256 acd68e1b8f9f4d1a... on rule sets v0 and v0.1; c07aba106afbd8e4299e1c177719399265c388fe5b2af1922cd66dd72aac6d77 (this landing's file: the spec's integer launch rate and Q32 step multiplier read when stated, nothing else changed) on the TV-01 spec |
|
||||
| the spec run | build-6:/srv/artefacts/token-value/tv-02/b-rules-tv01-spec-*; build-5:/srv/artefacts/token-value/tv-02/compare-rules-tv01-spec.log (sha256 7d18441d0e6825ba...); both copied to build-1 (build-5/ and build-6/) |
|
||||
| the registry batch | docs/plans/igneum-2.0-master/token-value/phase0/tv-02/registry-batch-tv-02.json (TV-02 NOT RUN, the proposed cell native:tv-02; the CI steward records it and names the cell on the map) |
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"run_id": "tv-02-20261009-01",
|
||||
"manifest_sha": "af2c23bc",
|
||||
"manifest_sha": "426c7c85",
|
||||
"method": "native",
|
||||
"evidence_dir": "build-1:/srv/artefacts/token-value/tv-02",
|
||||
"release_identity": {
|
||||
"commit": "af2c23bc (branch tv-02-supply-replay: the two implementations, the fixtures from 4e206eaf8, the compare harness)",
|
||||
"commit": "426c7c85 (master, the first TV-02 landing) and the spec-run landing after it (branch tv-02-supply-replay)",
|
||||
"lockfile": "tools/token-value/tv-02/replay-node/Cargo.lock",
|
||||
"binary": "tv02-replay-node sha256 ef3af79157947584... (the run), 25ff78695bd9d972... (rebuilt from af2c23bc, outputs byte-identical)",
|
||||
"network_object": "the compiled objects of igneum-node bf60948a read by A (devnet4_params, MAINNET_PARAMS, DEVNET_PARAMS); no chain state read or written",
|
||||
"activation": "none (Phase 0 lands documents and tests only)",
|
||||
"profile_hashes": "igneum-node bf60948a (emission.rs, igneum.rs, coinbase.rs, params.rs, window.rs, difficulty.rs byte-identical in release-2.0.2-node a284380b); rules-and-gates.json 10ce3073...; B rules v0 67707b09..., v0.1 d72d5578...; replay_spec.py acd68e1b..."
|
||||
"profile_hashes": "igneum-node bf60948a (emission.rs, igneum.rs, coinbase.rs, params.rs, window.rs, difficulty.rs byte-identical in release-2.0.2-node a284380b); rules-and-gates.json 10ce3073...; B rules v0 67707b09..., v0.1 d72d5578...; replay_spec.py acd68e1b...; the TV-01 supply-spec.json at 9cd09130 sha256 3ffdd308...; replay_spec.py on the spec c07aba10..."
|
||||
},
|
||||
"claim_impact": "none: no served figure moves; the supply ever issued on the 2.0 objects is 3,963,038,999.61 IGN under the 4,000,000,000 cap, with nothing after the terminal block",
|
||||
"reviewer": "",
|
||||
|
|
@ -23,8 +23,8 @@
|
|||
"status": "NOT RUN",
|
||||
"in_progress": true,
|
||||
"method": "native",
|
||||
"evidence": "docs/plans/igneum-2.0-master/token-value/phase0/tv-02/README.md; build-1:/srv/artefacts/token-value/tv-02/build-5/compare-rules-v0.1-genesis-rule.log; build-1:/srv/artefacts/token-value/tv-02/build-5/compare-rules-v0-litepaper.log; build-1:/srv/artefacts/token-value/tv-02/build-5/a-*.csv; build-1:/srv/artefacts/token-value/tv-02/build-6/b-*.csv",
|
||||
"note": "two supply replays, A (Rust on the node's issuance code at bf60948a, build-5) and B (Python from the rules in words, build-6), no shared code: with rule set v0.1 (the words plus the genesis rule, window.rs 176-179) EQUAL to the integer, byte-identical CSVs, at every transition's before/at/after, the terminal and one step past, on the devnet-4 (1 bps, 18 decimals), mainnet (10 bps, 18) and devnet (8) objects, and on two hand-written reorg fixtures with the no-undo ledger refused; with the words alone (v0) DIFFER at genesis (A 0, B 3168808781000000000 on devnet-4), a one-block shift with the terminal total unchanged (3963038999610200483289816000 base units on devnet-4); the TV-01 spec re-run, paid/burned/locked accounting, DAG reds and independent signoff are open rows; NOT RUN until the independent panel reads it"
|
||||
"evidence": "docs/plans/igneum-2.0-master/token-value/phase0/tv-02/README.md; build-1:/srv/artefacts/token-value/tv-02/build-5/compare-rules-v0.1-genesis-rule.log; build-1:/srv/artefacts/token-value/tv-02/build-5/compare-rules-v0-litepaper.log; build-1:/srv/artefacts/token-value/tv-02/build-5/a-*.csv; build-1:/srv/artefacts/token-value/tv-02/build-6/b-*.csv; build-1:/srv/artefacts/token-value/tv-02/build-5/compare-rules-tv01-spec.log; build-1:/srv/artefacts/token-value/tv-02/build-6/b-rules-tv01-spec-*.csv",
|
||||
"note": "two supply replays, A (Rust on the node's issuance code at bf60948a, build-5) and B (Python from the rules in words, build-6), no shared code: with rule set v0.1 (the words plus the genesis rule, window.rs 176-179) EQUAL to the integer, byte-identical CSVs, at every transition's before/at/after, the terminal and one step past, on the devnet-4 (1 bps, 18 decimals), mainnet (10 bps, 18) and devnet (8) objects, and on two hand-written reorg fixtures with the no-undo ledger refused; with the words alone (v0) DIFFER at genesis (A 0, B 3168808781000000000 on devnet-4), a one-block shift with the terminal total unchanged (3963038999610200483289816000 base units on devnet-4); on the TV-01 supply spec (9cd09130) EQUAL on devnet-4 and mainnet and both fixtures, A's terminal rows equal to the spec's stated terminal supplies; paid/burned/locked accounting, the mainnet genesis DAA score (C09), DAG reds and independent signoff are open rows; NOT RUN until the independent panel reads it"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
#!/usr/bin/env bash
|
||||
# TV-02: every comparison of A's outputs with B's, on A's box (build-5) with B's outputs copied from build-6 into
|
||||
# <out>/from-build-6. Usage: compare-all.sh <tv-02 dir> <out dir> <B rules tag> ; writes <out>/compare-<tag>.log
|
||||
# <out>/from-build-6. Usage: [NETS="devnet4 mainnet"] [SPEC_RULES=<B rules mapped from the TV-01 spec>] compare-all.sh
|
||||
# <tv-02 dir> <out dir> <B rules tag> ; writes <out>/compare-<tag>.log. With SPEC_RULES, A's terminal row is also checked
|
||||
# against the terminal supply and height the spec itself states.
|
||||
set -u
|
||||
D="$1"; O="$2"; TAG="$3"
|
||||
PID="$O/compare.pid"; echo "$$ $(date -u +%FT%TZ) tv02-compare $TAG" > "$PID"; trap 'rm -f "$PID"' EXIT
|
||||
B="$O/from-build-6"; LOG="$O/compare-$TAG.log"; : > "$LOG"
|
||||
python3 "$D/compare.py" selftest >> "$LOG" 2>&1
|
||||
for N in devnet4 mainnet devnet; do
|
||||
for N in ${NETS:-devnet4 mainnet devnet}; do
|
||||
echo "== straight $N" >> "$LOG"
|
||||
python3 "$D/compare.py" straight "$O/a-$N.csv" "$B/b-$TAG-$N.csv" >> "$LOG" 2>&1; echo "exit $?" >> "$LOG"
|
||||
done
|
||||
|
|
@ -14,4 +16,21 @@ for F in reorg-ramp-end-k1 reorg-first-step-k2; do
|
|||
echo "== reorg $F" >> "$LOG"
|
||||
python3 "$D/compare.py" reorg "$O/a-reorg-$F.csv" "$B/b-$TAG-reorg-$F.csv" "$D/fixtures/$F.json" "$O/a-devnet4.csv" >> "$LOG" 2>&1; echo "exit $?" >> "$LOG"
|
||||
done
|
||||
if [ -n "${SPEC_RULES:-}" ]; then
|
||||
echo "== the spec's own terminal supply against A's terminal row" >> "$LOG"
|
||||
python3 - "$SPEC_RULES" "$O" >> "$LOG" 2>&1 <<'PY'
|
||||
import csv, json, sys
|
||||
spec = json.load(open(sys.argv[1]))
|
||||
ok = True
|
||||
for net, t in spec["spec_terminal_supply"].items():
|
||||
rows = {int(r["height"]): r for r in csv.DictReader(open("%s/a-%s.csv" % (sys.argv[2], net)))}
|
||||
h = int(t["last_paying_block_height"])
|
||||
got = rows[h]["cumulative"] if h in rows else None
|
||||
same = got == str(t["terminal_supply"]) and rows[h + 1]["subsidy"] == "0"
|
||||
ok = ok and same
|
||||
print("%s %s: spec terminal %s at height %d, A %s" % ("EQUAL" if same else "DIFFER", net, t["terminal_supply"], h, got))
|
||||
sys.exit(0 if ok else 1)
|
||||
PY
|
||||
echo "exit $?" >> "$LOG"
|
||||
fi
|
||||
cat "$LOG"
|
||||
|
|
|
|||
|
|
@ -33,12 +33,18 @@ class Schedule:
|
|||
self.bps = int(n["bps"])
|
||||
self.decimals = int(n["decimals"])
|
||||
self.year = int(r["year_seconds"])
|
||||
fd = int(r["launch_rate_floor_decimals"])
|
||||
floor_rate = int(r["year_one_emission_ign"]) * 10 ** fd // self.year
|
||||
if self.decimals >= fd:
|
||||
self.rate0 = floor_rate * 10 ** (self.decimals - fd)
|
||||
if "launch_rate_per_second" in r:
|
||||
# a spec that states the launch rate as an integer at the network's unit (the TV-01 spec)
|
||||
self.rate0 = int(r["launch_rate_per_second"])
|
||||
else:
|
||||
self.rate0 = int(r["year_one_emission_ign"]) * 10 ** self.decimals // self.year
|
||||
fd = int(r["launch_rate_floor_decimals"])
|
||||
floor_rate = int(r["year_one_emission_ign"]) * 10 ** fd // self.year
|
||||
if self.decimals >= fd:
|
||||
self.rate0 = floor_rate * 10 ** (self.decimals - fd)
|
||||
else:
|
||||
self.rate0 = int(r["year_one_emission_ign"]) * 10 ** self.decimals // self.year
|
||||
# the step multiplier in Q32 when the rules state one (2^31 is a halving); absent, a halving
|
||||
self.decay_q32 = int(r.get("step_decay_q32", 2 ** 31))
|
||||
self.step = int(r["step_seconds"])
|
||||
self.ramp_s = int(r["ramp_seconds"])
|
||||
self.ramp_start = int(r["ramp_start_percent"])
|
||||
|
|
@ -55,10 +61,10 @@ class Schedule:
|
|||
|
||||
# --- the per-block rule, from the words ---
|
||||
def rate(self, k):
|
||||
"""Per-second rate in step k: the launch rate halved k times, floored each time (equal to rate0 // 2**k)."""
|
||||
"""Per-second rate in step k: the launch rate times the step multiplier k times, floored each time (a halving: rate0 // 2**k)."""
|
||||
x = self.rate0
|
||||
for _ in range(k):
|
||||
x //= 2
|
||||
x = x * self.decay_q32 // 2 ** 32
|
||||
if x == 0:
|
||||
break
|
||||
return x
|
||||
|
|
|
|||
42
tools/token-value/tv-02/replay-spec/rules-tv01-spec.json
Normal file
42
tools/token-value/tv-02/replay-spec/rules-tv01-spec.json
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"id": "tv02-rules-from-tv01-spec",
|
||||
"status": "B's rules mapped from the TV-01 supply spec by tv01_adapter.py",
|
||||
"spec_path": "replay-spec/supply-spec-9cd09130.json",
|
||||
"spec_sha256": "3ffdd3084aff06d963df6c326cda88719d576f07d9cbfb56079de1a8b40c4403",
|
||||
"spec_version": "1.0.0",
|
||||
"rules": {
|
||||
"year_seconds": 31557600,
|
||||
"launch_rate_per_second": "31688087810000000000",
|
||||
"step_seconds": 63115200,
|
||||
"step_decay_q32": 2147483648,
|
||||
"ramp_seconds": 2592000,
|
||||
"ramp_start_percent": 10,
|
||||
"per_block_order": "divide_then_ramp",
|
||||
"tail": "cap",
|
||||
"supply_cap_ign": 4000000000,
|
||||
"genesis_issues": "nothing",
|
||||
"daa_of_height": "height_minus_one"
|
||||
},
|
||||
"networks": {
|
||||
"mainnet": {
|
||||
"bps": 10,
|
||||
"decimals": 18,
|
||||
"source": "supply-spec.json schedules[mainnet]"
|
||||
},
|
||||
"devnet4": {
|
||||
"bps": 1,
|
||||
"decimals": 18,
|
||||
"source": "supply-spec.json schedules[devnet-4]"
|
||||
}
|
||||
},
|
||||
"spec_terminal_supply": {
|
||||
"mainnet": {
|
||||
"terminal_supply": "3963038999610200467816224000",
|
||||
"last_paying_block_height": 39131424000
|
||||
},
|
||||
"devnet4": {
|
||||
"terminal_supply": "3963038999610200483289816000",
|
||||
"last_paying_block_height": 4102488000
|
||||
}
|
||||
}
|
||||
}
|
||||
63
tools/token-value/tv-02/replay-spec/tv01_adapter.py
Normal file
63
tools/token-value/tv-02/replay-spec/tv01_adapter.py
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
#!/usr/bin/env python3
|
||||
"""TV-02: maps the TV-01 lane's supply spec (supply-spec.json) to B's rules file, field by field, refusing any rule it
|
||||
cannot map. B then replays from the spec's own numbers. Standalone Python 3; no code from A or from the spec's generator.
|
||||
|
||||
tv01_adapter.py <supply-spec.json> <out rules.json>
|
||||
"""
|
||||
import hashlib
|
||||
import json
|
||||
import sys
|
||||
|
||||
|
||||
def main(spec_path, out_path):
|
||||
raw = open(spec_path, "rb").read()
|
||||
spec = json.loads(raw)
|
||||
r = spec["rules"]
|
||||
if r.get("tail") != "cap":
|
||||
raise SystemExit("the spec's tail is %r; B replays a capped schedule only" % r.get("tail"))
|
||||
per_block = r["per_block"].replace(" ", "")
|
||||
if "ramp(floor(rate[" not in per_block or "/bps),s)" not in per_block:
|
||||
raise SystemExit("the spec's per-block rule is not divide-then-ramp: %r" % r["per_block"])
|
||||
g = r["genesis_rule"]
|
||||
if g.get("rule") != "genesis-unrewarded" or "DAA score + 1" not in g.get("height_of_daa_score", ""):
|
||||
raise SystemExit("unmapped genesis rule %r" % g)
|
||||
out = {
|
||||
"id": "tv02-rules-from-tv01-spec",
|
||||
"status": "B's rules mapped from the TV-01 supply spec by tv01_adapter.py",
|
||||
"spec_path": spec_path,
|
||||
"spec_sha256": hashlib.sha256(raw).hexdigest(),
|
||||
"spec_version": spec.get("schema", {}).get("version"),
|
||||
"rules": {
|
||||
"year_seconds": int(r["year_seconds"]),
|
||||
"launch_rate_per_second": str(r["launch_rate_per_second"]),
|
||||
"step_seconds": int(r["step_seconds"]),
|
||||
"step_decay_q32": int(r["step_decay_q32"]),
|
||||
"ramp_seconds": int(r["ramp_seconds"]),
|
||||
"ramp_start_percent": int(r["ramp_start_percent"]),
|
||||
"per_block_order": "divide_then_ramp",
|
||||
"tail": "cap",
|
||||
"supply_cap_ign": int(spec["cap"]["coins"]),
|
||||
"genesis_issues": "nothing",
|
||||
"daa_of_height": "height_minus_one",
|
||||
},
|
||||
"networks": {},
|
||||
"spec_terminal_supply": {},
|
||||
}
|
||||
if int(spec["units"]["decimals"]) != 18:
|
||||
raise SystemExit("unexpected decimals %r" % spec["units"]["decimals"])
|
||||
for sch in spec["schedules"]:
|
||||
name = {"devnet-4": "devnet4", "mainnet": "mainnet"}.get(sch["profile"], sch["profile"])
|
||||
if int(sch.get("genesis_daa_score", 0)) != 0:
|
||||
raise SystemExit("profile %s: genesis DAA score %r is not 0" % (name, sch["genesis_daa_score"]))
|
||||
out["networks"][name] = {"bps": int(sch["bps"]), "decimals": int(sch["decimals"]), "source": "supply-spec.json schedules[%s]" % sch["profile"]}
|
||||
out["spec_terminal_supply"][name] = {"terminal_supply": sch["terminal_supply"], "last_paying_block_height": sch["last_paying_block_height"]}
|
||||
json.dump(out, open(out_path, "w"), indent=2)
|
||||
open(out_path, "a").write("\n")
|
||||
print("mapped %s (sha256 %s) to %s: networks %s" % (spec_path, out["spec_sha256"], out_path, sorted(out["networks"])))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) != 3:
|
||||
print(__doc__, file=sys.stderr)
|
||||
sys.exit(2)
|
||||
main(sys.argv[1], sys.argv[2])
|
||||
Loading…
Reference in a new issue