Merge the box master (the reference-apps lane's compatibility rows taken whole)
This commit is contained in:
commit
eb5b39ccdf
42 changed files with 1275 additions and 180 deletions
|
|
@ -47,3 +47,43 @@ Three reads. The acceptance's index-bit read: per program, per site, the one-cou
|
|||
## 5. Owed
|
||||
|
||||
The live-dataset F8 point at 2^24 for the two window packs (the mirror would need the two-window interpreter: four to six hours); the 64 x 2^24 point per pack (45 to 100 core-hours each); hl-v6-rw's files (on build-3, unreachable); the exact `or = 0` attempts rows are lane D's.
|
||||
|
||||
## 6. The per-site address census (the external review's A03), 8 October 2026, 18:4x to 19:10 UK
|
||||
|
||||
The question (the coordinator's order from the review landing, finding A03): the acceptance's per-hash distinct-address check can pass a program where one load site reads the same address in about 15 percent of hashes across nonces and headers (seed SHA256("igneum-review/139"), iteration 5 instruction 51 on the old V2 tree, address 0x0fffffff in 312 to 325 of 2,048 hashes). Does the current class v5 object or the v6 freeze candidate carry that class, and what cache-hit rate would a 1 GiB, 256 MiB or 64 MiB cache get per site and over the program?
|
||||
|
||||
The instrument: `igneum-pow addrsite` on the harness branch (class-v6-census-all at 9893b4c9, build-4 binary 2c76893e...): the live epoch (the memory-hard dataset, the state leaves of the object's state file, the era laid over), four headers (prehash `h` = the seed words of `igneum-review/header/<h>` as 32 bytes, the init words through `bind::block_init_words` with `h` as the high nonce word, so every header changes the init words the way a mined block does), 2^16 nonces per header (and 2^18 in the x16 runs) through the interpreter's tracing probe; per (iteration, site) cell and per site the address histogram, the most read address and its share, the distinct count, and an ideal cache's hit rate (the site's or the program's top K items by read count, K = cache bytes / 64, beside the window model's expectation min(1, K / window items)). Commands: `addrsite --count 4 --warps 2048 --threads 16 --epoch-hex <hex> --day-hex <hex> --class <class> --era 0:<hex> --state <igsd1>` (`--warps 32768` for x16; `--class v2 --epoch-hex <sha256 of the label>` for the known-failed case). The TSVs are under `logs/census-packs/addrsite/`, the window draws in `windows.txt`.
|
||||
|
||||
**The known-failed case reproduces.** Class v2 at the epoch bytes SHA256("igneum-review/139") = c5ffc49e..., program 675fa2e2bd0dfd6d: instruction 51 (site 10) reads 0x0fffffff in 317,690 of its 2,097,152 reads over four headers and 2^16 nonces each (15.15 percent), 15.12 to 15.19 percent at every one of the eight iterations (the review's 312 to 325 of 2,048 at iteration 5 is 15.2 to 15.9 percent on its sample); every other site's worst address reads 3 to 4 times in 2 million. The cause on that tree: the site's source register is saturated (all ones) in a seventh of hashes and `x AND mask` of all ones is the top address; the rule of 4 October 2026 (part (c): the distinct-address sum over 2,048 hashes) does not see it because the other 127 loads of the hash are distinct. The two sub-version 2 rules of 7 October 2026 are the fix on every later class: (c') refuses a load site whose source is saturated in more than 1 percent of its 16,384 evaluations, and (a') refuses a load whose source's last writer is `or`, `mul` or `mulhi` (the writers that saturate or zero a register). This is not A08's Mad collapse: a `mad` at a load's source leaves the product's low bits biased (the stride-bit class of sections 0 and 3, which the fold closes); it never pins the whole address.
|
||||
|
||||
**Class v5 and the v6 candidate carry nothing of the class.** The rows, every object on its own state file and era, four headers:
|
||||
|
||||
| Object (program, state) | Hashes | Reads per site | Worst (iteration, site) cell: top address count of the cell's reads | Worst site: top address count of the site's reads | Distinct items touched of 16,777,216 |
|
||||
|---|---|---|---|---|---|
|
||||
| class v2, SHA256("igneum-review/139") (675fa2e2bd0dfd6d; the known-failed case) | 2^18 | 2,097,152 | 39,928 of 262,144 (15.2 percent) at site 10 | 317,690 (15.15 percent) at site 10 (instruction 51), address 0x0fffffff | 14,200,379 |
|
||||
| class v5, Devnet 3 epoch 0 (e5a4ac5978462156, v5-dn3-epoch0 state) | 2^18 | 2,097,152 | 3 of 262,144 (1.1e-5) | 4 of 2,097,152 (1.9e-6) | 13,555,305 |
|
||||
| the same, x16 | 2^20 | 33,554,432 | 5 of 4,194,304 (1.2e-6) | 8 of 33,554,432 (2.4e-7) | 16,777,216 (all) |
|
||||
| class v5, the freeze's seeds on the node1 state (6554474f410f36f3, attempt 1) | 2^18 | 2,097,152 | 3 (1.1e-5) | 4 (1.9e-6) | 13,433,475 |
|
||||
| the same, x16 | 2^20 | 33,554,432 | 5 (1.2e-6) | 9 (2.7e-7) | 16,777,213 |
|
||||
| class v5, chain seeds p18 (f1ca3ca995c57b7a) and p19 (116d921a2211b1e2, attempt 5), node1 state | 2^18 each | 2,097,152 | 3 (1.1e-5) | 4 (1.9e-6) | 14,269,676 and 13,982,239 |
|
||||
| v6 freeze candidate, hl-v6-all (9d40978601a7df2a: window, fold, rw1; node1 state), 32 sites | 2^18 | 2,097,152 | 3 (1.1e-5) | 4 (1.9e-6) | 16,122,715 |
|
||||
| the same, x16 | 2^20 | 33,554,432 | 5 (1.2e-6) | 9 (2.7e-7) | 16,777,216 (all) |
|
||||
| v6 class on chain seeds p18 (7202548bfc7f98e9) and p19 (dd6b285ae45e7b9b, attempt 1) | 2^18 each | 2,097,152 | 3 (1.1e-5) | 4 (1.9e-6) | 16,329,983 and 16,055,477 |
|
||||
|
||||
Every v5 and v6 figure is the Poisson maximum of a uniform stream on its window (the expected largest count of 2 million draws over 2^26 cells is 3 to 4; of 33 million over 2^26, 8 to 9), five orders below the known-failed case, and the finer sample moves the worst address's share down with it, so there is no address, site or cell any cache can key on. The per-site distinct ratio against the window model read 1.0026 to 1.0027 on every site of both v6 window packs and 0.9946 to 1.0027 on class v5's at 2^22 (section 0): uniform inside each site's window.
|
||||
|
||||
**The cache-hit rates are the era windows', by design, and equal on v5 and v6.** A quarter-window site's reads fit whole in a 256 MiB cache, a half-window site's half of them, a full-window site's a quarter; with the program's windows the hit rate of a 256 MiB cache over the program is the densest quarter's share of all reads, and a 64 MiB cache's a quarter of that (the density is flat inside a quarter, so no smaller cache does better than its size's share of the best quarter):
|
||||
|
||||
| Object | Window draw (full, half, quarter sites) | 1 GiB | 256 MiB, the window model | 256 MiB, measured (top K items by count at 2^20 hashes; the excess over the model is the sampling noise of ranking items by count) | 64 MiB, the window model | 64 MiB, measured (the same noise, larger) | Hottest-half share (the adversary lane's 72 percent) |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| class v5, Devnet 3 epoch 0 | 5, 8, 3 | 1.000 | 0.391 | 0.409 | 0.098 | 0.116 | 0.719 |
|
||||
| class v5, the freeze's seeds on node1 | 7, 2, 7 | 1.000 | 0.422 | 0.428 | 0.105 | 0.124 | 0.531 |
|
||||
| v6 candidate, hl-v6-all | 5, 7, 4 | 1.000 | 0.359 | 0.367 | 0.090 | 0.102 | 0.656 |
|
||||
| class v5, p18 and p19 | 7, 3, 6 and 1, 6, 9 | 1.000 | 0.328, 0.328 | 0.498, 0.512 at 2^18 (sample-bound) | 0.082, 0.082 | | 0.594, 0.531 |
|
||||
| v6 class, p18 and p19 | 7, 3, 6 and 6, 6, 4 | 1.000 | 0.328, 0.344 | 0.434, 0.466 at 2^18 (sample-bound) | 0.082, 0.086 | | 0.594, 0.688 |
|
||||
|
||||
Per site: 1.000 for every site under 1 GiB; under 256 MiB 1.000 on a quarter site, 0.500 on a half site, 0.250 on a full site by the window; the measured per-site top-K figures at 2^18 hashes read 1.000 everywhere because 2 million reads touch fewer items than the 4 million the cache holds (sample-bound, which is why the x16 runs exist), and at 2^20 hashes they read 0.69 to 0.74 summed over sites, above the model for the same ranking reason. The adversary lane's 72 percent for the Devnet 3 epoch 0 program is this table's 0.719: the window draw (5 whole, 8 half, 3 quarter sites), not an address concentration.
|
||||
|
||||
**Against the one acceptance rule** (a hash change passes only when the best adversarial implementation becomes worse relative to the best practical GPU implementation, within pre-agreed cost and verification limits): on the address axis the v6 candidate is the class v5 object (both uniform inside their windows to 2.7e-7 at the worst address; both with the era windows' cache shares, which a GPU's L2 sees as well as a chip's SRAM), and the v6 candidate is better on the one address bias the record carried (the stride-bit class, closed by the fold: section 0). A03's class is closed on both by (c') and (a'); nothing in it names a generator cause on v5 or v6 because the concentration is absent at 1e-6 resolution. The window draw's cache shares are layer 8 of the era layout by design (the research lane's reconcile: 0.72 is the Devnet 3 program at about p98 of the draw, mean 0.58), and the "every site on the whole dataset" variant that flattens them (win = 0 everywhere) is the D2 experiment already named, at zero GPU cost.
|
||||
|
||||
Owed: the x16 rows for the four chain seeds (the 2^18 rows stand; 4 minutes each on 32 cores when the pool has them); a sample-free cache figure (an LRU trace rather than a top-K ranking) if anyone wants the measured column to equal the model to the third digit.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
# addrsite: program 675fa2e2bd0dfd6d class v2 attempt 0 generator v2 day bytes:69676e65756d2d6461792ffd50000000000000 dataset 2^28 words (memory-hard) headers 4 warps 2048 nonces/header 65536 threads 16
|
||||
# per (iteration, site) cell: the most read address and its share (A03's form); cells over 0.1 percent listed
|
||||
it site instr reads distinct top_addr top_count top_share
|
||||
0 0 9 262144 262029 0x0f53fdc4 2 0.000008
|
||||
0 1 10 262144 262018 0x0962d159 2 0.000008
|
||||
0 10 51 262144 24237 0x0fffffff 39633 0.151188
|
||||
1 10 51 262144 24525 0x0fffffff 39727 0.151546
|
||||
2 10 51 262144 24317 0x0fffffff 39824 0.151917
|
||||
3 10 51 262144 24441 0x0fffffff 39644 0.151230
|
||||
4 10 51 262144 24413 0x0fffffff 39719 0.151516
|
||||
5 10 51 262144 24468 0x0fffffff 39477 0.150593
|
||||
6 10 51 262144 24522 0x0fffffff 39928 0.152313
|
||||
7 10 51 262144 24404 0x0fffffff 39738 0.151588
|
||||
# worst cell: iteration 6 site 10 address 0x0fffffff in 39928 reads, share 0.152313
|
||||
# per site, pooled over the 8 iterations (hit rates: an ideal cache of the site's top K items, K = bytes / 64; exp = min(1, K / window items))
|
||||
site instr win window_items reads distinct top_addr top_count top_share hit_1GiB hit_256MiB hit_64MiB exp_1GiB exp_256MiB exp_64MiB
|
||||
0 9 0 16777216 2097152 2089080 0x00eed80e 3 0.000001 1.0000 1.0000 0.5598 1.0000 0.2500 0.0625
|
||||
1 10 0 16777216 2097152 2088834 0x096c9ca2 3 0.000001 1.0000 1.0000 0.5600 1.0000 0.2500 0.0625
|
||||
2 23 0 16777216 2097152 2089024 0x0c4f0db2 3 0.000001 1.0000 1.0000 0.5600 1.0000 0.2500 0.0625
|
||||
3 28 0 16777216 2097152 2088934 0x0a324525 3 0.000001 1.0000 1.0000 0.5600 1.0000 0.2500 0.0625
|
||||
4 30 0 16777216 2097152 2088944 0x0225bcfa 3 0.000001 1.0000 1.0000 0.5599 1.0000 0.2500 0.0625
|
||||
5 31 0 16777216 2097152 2088972 0x05a4e8bb 3 0.000001 1.0000 1.0000 0.5602 1.0000 0.2500 0.0625
|
||||
6 34 0 16777216 2097152 2088961 0x00dd74c9 4 0.000002 1.0000 1.0000 0.5603 1.0000 0.2500 0.0625
|
||||
7 35 0 16777216 2097152 2088836 0x057705ee 3 0.000001 1.0000 1.0000 0.5601 1.0000 0.2500 0.0625
|
||||
8 40 0 16777216 2097152 2088840 0x05838908 3 0.000001 1.0000 1.0000 0.5598 1.0000 0.2500 0.0625
|
||||
9 46 0 16777216 2097152 2068864 0x00000001 9 0.000004 1.0000 1.0000 0.5882 1.0000 0.2500 0.0625
|
||||
10 51 0 16777216 2097152 81211 0x0fffffff 317690 0.151486 1.0000 1.0000 1.0000 1.0000 0.2500 0.0625
|
||||
11 56 0 16777216 2097152 2089032 0x040bbbbc 3 0.000001 1.0000 1.0000 0.5600 1.0000 0.2500 0.0625
|
||||
12 57 0 16777216 2097152 2089064 0x09af3b29 3 0.000001 1.0000 1.0000 0.5597 1.0000 0.2500 0.0625
|
||||
13 60 0 16777216 2097152 2089021 0x0fa3b676 3 0.000001 1.0000 1.0000 0.5598 1.0000 0.2500 0.0625
|
||||
14 61 0 16777216 2097152 2088991 0x078eb1bf 3 0.000001 1.0000 1.0000 0.5598 1.0000 0.2500 0.0625
|
||||
15 62 0 16777216 2097152 2088969 0x02de33fc 3 0.000001 1.0000 1.0000 0.5601 1.0000 0.2500 0.0625
|
||||
# program: reads 33554432, distinct items 14200379, worst site 10 address 0x0fffffff in 317690 reads (share 0.151486); one cache over the program's reads: 1 GiB 1.0000, 256 MiB 0.5268, 64 MiB 0.2157; the per-site ideal caches summed: 1.0000, 1.0000, 0.5892; 13.7 s
|
||||
|
Can't render this file because it has a wrong number of fields in line 3.
|
|
|
@ -0,0 +1,25 @@
|
|||
# addrsite: program e5a4ac5978462156 class mx8-eraaf3a9139+sh256x27+state attempt 0 generator v5 day bytes:69676e65756d2d6461792ffd50000000000000 dataset 2^28 words (memory-hard) headers 4 warps 32768 nonces/header 1048576 threads 32
|
||||
# per (iteration, site) cell: the most read address and its share (A03's form); cells over 0.1 percent listed
|
||||
it site instr reads distinct top_addr top_count top_share
|
||||
0 0 3 4194304 4161790 0x0bfc9aab 4 0.000001
|
||||
0 1 8 4194304 4066143 0x08265739 4 0.000001
|
||||
# worst cell: iteration 1 site 1 address 0x0b2343dc in 5 reads, share 0.000001
|
||||
# per site, pooled over the 8 iterations (hit rates: an ideal cache of the site's top K items, K = bytes / 64; exp = min(1, K / window items))
|
||||
site instr win window_items reads distinct top_addr top_count top_share hit_1GiB hit_256MiB hit_64MiB exp_1GiB exp_256MiB exp_64MiB
|
||||
0 3 0 16777216 33554432 30870454 0x00f640b3 7 0.000000 1.0000 0.5677 0.2162 1.0000 0.2500 0.0625
|
||||
1 8 2 4194304 33554432 26405113 0x0aac4eee 8 0.000000 1.0000 1.0000 0.3657 1.0000 1.0000 0.2500
|
||||
2 14 1 8388608 33554432 29688361 0x06be5c6f 7 0.000000 1.0000 0.6954 0.2364 1.0000 0.5000 0.1250
|
||||
3 15 0 16777216 33554432 31541112 0x024a6b86 6 0.000000 1.0000 0.4841 0.1626 1.0000 0.2500 0.0625
|
||||
4 20 1 8388608 33554432 29687210 0x0d58543d 7 0.000000 1.0000 0.6954 0.2364 1.0000 0.5000 0.1250
|
||||
5 26 1 8388608 33554432 29689217 0x0dbb3585 6 0.000000 1.0000 0.6954 0.2364 1.0000 0.5000 0.1250
|
||||
6 28 1 8388608 33554432 29688609 0x089bbae6 7 0.000000 1.0000 0.6954 0.2364 1.0000 0.5000 0.1250
|
||||
7 35 0 16777216 33554432 31538736 0x08bc7035 6 0.000000 1.0000 0.4840 0.1626 1.0000 0.2500 0.0625
|
||||
8 40 2 4194304 33554432 26405981 0x0dce8d28 8 0.000000 1.0000 1.0000 0.3657 1.0000 1.0000 0.2500
|
||||
9 43 1 8388608 33554432 29688018 0x00d76e8e 7 0.000000 1.0000 0.6953 0.2363 1.0000 0.5000 0.1250
|
||||
10 47 1 8388608 33554432 29688528 0x0cf671d9 7 0.000000 1.0000 0.6953 0.2363 1.0000 0.5000 0.1250
|
||||
11 49 0 16777216 33554432 31541219 0x041cab33 6 0.000000 1.0000 0.4841 0.1627 1.0000 0.2500 0.0625
|
||||
12 52 2 4194304 33554432 26407627 0x0c72ccad 8 0.000000 1.0000 1.0000 0.3657 1.0000 1.0000 0.2500
|
||||
13 53 0 16777216 33554432 31541057 0x08989cd7 5 0.000000 1.0000 0.4840 0.1626 1.0000 0.2500 0.0625
|
||||
14 61 1 8388608 33554432 29688334 0x09f86f17 6 0.000000 1.0000 0.6953 0.2363 1.0000 0.5000 0.1250
|
||||
15 62 1 8388608 33554432 29689912 0x0a189de6 7 0.000000 1.0000 0.6954 0.2364 1.0000 0.5000 0.1250
|
||||
# program: reads 536870912, distinct items 16777216, worst site 1 address 0x0aac4eee in 8 reads (share 0.000000); one cache over the program's reads: 1 GiB 1.0000, 256 MiB 0.4093, 64 MiB 0.1164; the per-site ideal caches summed: 1.0000, 0.6917, 0.2409; 264.5 s
|
||||
|
Can't render this file because it has a wrong number of fields in line 3.
|
|
|
@ -0,0 +1,25 @@
|
|||
# addrsite: program e5a4ac5978462156 class mx8-eraaf3a9139+sh256x27+state attempt 0 generator v5 day bytes:69676e65756d2d6461792ffd50000000000000 dataset 2^28 words (memory-hard) headers 4 warps 2048 nonces/header 65536 threads 16
|
||||
# per (iteration, site) cell: the most read address and its share (A03's form); cells over 0.1 percent listed
|
||||
it site instr reads distinct top_addr top_count top_share
|
||||
0 0 3 262144 262018 0x075ab028 2 0.000008
|
||||
0 1 8 262144 261623 0x08dd9d14 2 0.000008
|
||||
# worst cell: iteration 0 site 11 address 0x0bac8626 in 3 reads, share 0.000011
|
||||
# per site, pooled over the 8 iterations (hit rates: an ideal cache of the site's top K items, K = bytes / 64; exp = min(1, K / window items))
|
||||
site instr win window_items reads distinct top_addr top_count top_share hit_1GiB hit_256MiB hit_64MiB exp_1GiB exp_256MiB exp_64MiB
|
||||
0 3 0 16777216 2097152 2085799 0x0b2545d1 3 0.000001 1.0000 1.0000 0.5800 1.0000 0.2500 0.0625
|
||||
1 8 2 4194304 2097152 2064740 0x0b9c148a 4 0.000002 1.0000 1.0000 0.7130 1.0000 1.0000 0.2500
|
||||
2 14 1 8388608 2097152 2081037 0x01916282 3 0.000001 1.0000 1.0000 0.6150 1.0000 0.5000 0.1250
|
||||
3 15 0 16777216 2097152 2088937 0x0f7026ab 3 0.000001 1.0000 1.0000 0.5601 1.0000 0.2500 0.0625
|
||||
4 20 1 8388608 2097152 2080832 0x0c746791 3 0.000001 1.0000 1.0000 0.6151 1.0000 0.5000 0.1250
|
||||
5 26 1 8388608 2097152 2080935 0x0a21454f 3 0.000001 1.0000 1.0000 0.6151 1.0000 0.5000 0.1250
|
||||
6 28 1 8388608 2097152 2080920 0x0ce18e42 3 0.000001 1.0000 1.0000 0.6154 1.0000 0.5000 0.1250
|
||||
7 35 0 16777216 2097152 2089050 0x06cee471 3 0.000001 1.0000 1.0000 0.5599 1.0000 0.2500 0.0625
|
||||
8 40 2 4194304 2097152 2064639 0x0dab20c6 4 0.000002 1.0000 1.0000 0.7130 1.0000 1.0000 0.2500
|
||||
9 43 1 8388608 2097152 2080837 0x03dee5b7 3 0.000001 1.0000 1.0000 0.6153 1.0000 0.5000 0.1250
|
||||
10 47 1 8388608 2097152 2080783 0x0af11ac8 3 0.000001 1.0000 1.0000 0.6150 1.0000 0.5000 0.1250
|
||||
11 49 0 16777216 2097152 2088759 0x0e7395f8 3 0.000001 1.0000 1.0000 0.5603 1.0000 0.2500 0.0625
|
||||
12 52 2 4194304 2097152 2064717 0x0e9dc323 4 0.000002 1.0000 1.0000 0.7131 1.0000 1.0000 0.2500
|
||||
13 53 0 16777216 2097152 2088899 0x07c55392 3 0.000001 1.0000 1.0000 0.5600 1.0000 0.2500 0.0625
|
||||
14 61 1 8388608 2097152 2080810 0x0e9b6bf6 4 0.000002 1.0000 1.0000 0.6152 1.0000 0.5000 0.1250
|
||||
15 62 1 8388608 2097152 2080683 0x082ed8a4 3 0.000001 1.0000 1.0000 0.6152 1.0000 0.5000 0.1250
|
||||
# program: reads 33554432, distinct items 13555305, worst site 1 address 0x0b9c148a in 4 reads (share 0.000002); one cache over the program's reads: 1 GiB 1.0000, 256 MiB 0.5363, 64 MiB 0.1862; the per-site ideal caches summed: 1.0000, 1.0000, 0.6175; 15.7 s
|
||||
|
Can't render this file because it has a wrong number of fields in line 3.
|
|
|
@ -0,0 +1,25 @@
|
|||
# addrsite: program 6554474f410f36f3 class mx8-erad810f22d+sh256x27+state attempt 1 generator v5 day bytes:69676e65756d2d6461792ffa50000000000000 dataset 2^28 words (memory-hard) headers 4 warps 32768 nonces/header 1048576 threads 32
|
||||
# per (iteration, site) cell: the most read address and its share (A03's form); cells over 0.1 percent listed
|
||||
it site instr reads distinct top_addr top_count top_share
|
||||
0 0 1 4194304 4066484 0x0d98b28f 4 0.000001
|
||||
0 1 4 4194304 4066345 0x05f13919 5 0.000001
|
||||
# worst cell: iteration 0 site 1 address 0x05f13919 in 5 reads, share 0.000001
|
||||
# per site, pooled over the 8 iterations (hit rates: an ideal cache of the site's top K items, K = bytes / 64; exp = min(1, K / window items))
|
||||
site instr win window_items reads distinct top_addr top_count top_share hit_1GiB hit_256MiB hit_64MiB exp_1GiB exp_256MiB exp_64MiB
|
||||
0 1 2 4194304 33554432 26400592 0x0c7045a3 8 0.000000 1.0000 1.0000 0.3658 1.0000 1.0000 0.2500
|
||||
1 4 2 4194304 33554432 26401123 0x072af787 8 0.000000 1.0000 1.0000 0.3657 1.0000 1.0000 0.2500
|
||||
2 6 2 4194304 33554432 26405485 0x049a55ed 8 0.000000 1.0000 1.0000 0.3658 1.0000 1.0000 0.2500
|
||||
3 10 1 8388608 33554432 29690768 0x08d35217 6 0.000000 1.0000 0.6952 0.2363 1.0000 0.5000 0.1250
|
||||
4 12 0 16777216 33554432 31544105 0x09c5c917 6 0.000000 1.0000 0.4840 0.1626 1.0000 0.2500 0.0625
|
||||
5 20 0 16777216 33554432 31540887 0x07661673 6 0.000000 1.0000 0.4840 0.1625 1.0000 0.2500 0.0625
|
||||
6 27 0 16777216 33554432 31530754 0x0bafa7c0 7 0.000000 1.0000 0.4840 0.1625 1.0000 0.2500 0.0625
|
||||
7 30 0 16777216 33554432 31540950 0x0b019910 6 0.000000 1.0000 0.4840 0.1626 1.0000 0.2500 0.0625
|
||||
8 35 2 4194304 33554432 26404837 0x0f1ef4b7 8 0.000000 1.0000 1.0000 0.3658 1.0000 1.0000 0.2500
|
||||
9 40 0 16777216 33554432 31543058 0x06bc65b3 6 0.000000 1.0000 0.4841 0.1626 1.0000 0.2500 0.0625
|
||||
10 41 2 4194304 33554432 26408146 0x06fe1013 8 0.000000 1.0000 1.0000 0.3658 1.0000 1.0000 0.2500
|
||||
11 43 0 16777216 33554432 31541513 0x09a659c8 5 0.000000 1.0000 0.4840 0.1626 1.0000 0.2500 0.0625
|
||||
12 45 2 4194304 33554432 26406923 0x06a1486f 9 0.000000 1.0000 1.0000 0.3658 1.0000 1.0000 0.2500
|
||||
13 52 1 8388608 33554432 29688086 0x0eb2734c 7 0.000000 1.0000 0.6954 0.2364 1.0000 0.5000 0.1250
|
||||
14 53 0 16777216 33554432 31543889 0x0616a65b 6 0.000000 1.0000 0.4840 0.1626 1.0000 0.2500 0.0625
|
||||
15 54 2 4194304 33554432 26402941 0x073abb15 8 0.000000 1.0000 1.0000 0.3657 1.0000 1.0000 0.2500
|
||||
# program: reads 536870912, distinct items 16777213, worst site 12 address 0x06a1486f in 9 reads (share 0.000000); one cache over the program's reads: 1 GiB 1.0000, 256 MiB 0.4280, 64 MiB 0.1240; the per-site ideal caches summed: 1.0000, 0.7362, 0.2607; 257.1 s
|
||||
|
Can't render this file because it has a wrong number of fields in line 3.
|
|
|
@ -0,0 +1,25 @@
|
|||
# addrsite: program 6554474f410f36f3 class mx8-erad810f22d+sh256x27+state attempt 1 generator v5 day bytes:69676e65756d2d6461792ffa50000000000000 dataset 2^28 words (memory-hard) headers 4 warps 2048 nonces/header 65536 threads 16
|
||||
# per (iteration, site) cell: the most read address and its share (A03's form); cells over 0.1 percent listed
|
||||
it site instr reads distinct top_addr top_count top_share
|
||||
0 0 1 262144 261631 0x0f303511 3 0.000011
|
||||
0 1 4 262144 261625 0x0791a8d8 2 0.000008
|
||||
# worst cell: iteration 0 site 0 address 0x0f303511 in 3 reads, share 0.000011
|
||||
# per site, pooled over the 8 iterations (hit rates: an ideal cache of the site's top K items, K = bytes / 64; exp = min(1, K / window items))
|
||||
site instr win window_items reads distinct top_addr top_count top_share hit_1GiB hit_256MiB hit_64MiB exp_1GiB exp_256MiB exp_64MiB
|
||||
0 1 2 4194304 2097152 2065026 0x0ef27367 4 0.000002 1.0000 1.0000 0.7129 1.0000 1.0000 0.2500
|
||||
1 4 2 4194304 2097152 2064777 0x07bb8964 4 0.000002 1.0000 1.0000 0.7133 1.0000 1.0000 0.2500
|
||||
2 6 2 4194304 2097152 2064693 0x05ee43d3 4 0.000002 1.0000 1.0000 0.7133 1.0000 1.0000 0.2500
|
||||
3 10 1 8388608 2097152 2080744 0x0b3e8d7b 3 0.000001 1.0000 1.0000 0.6152 1.0000 0.5000 0.1250
|
||||
4 12 0 16777216 2097152 2088932 0x03d51420 3 0.000001 1.0000 1.0000 0.5600 1.0000 0.2500 0.0625
|
||||
5 20 0 16777216 2097152 2089031 0x0bf20310 3 0.000001 1.0000 1.0000 0.5598 1.0000 0.2500 0.0625
|
||||
6 27 0 16777216 2097152 2088755 0x05704f75 3 0.000001 1.0000 1.0000 0.5600 1.0000 0.2500 0.0625
|
||||
7 30 0 16777216 2097152 2089003 0x0b556614 3 0.000001 1.0000 1.0000 0.5599 1.0000 0.2500 0.0625
|
||||
8 35 2 4194304 2097152 2064668 0x0e0b153c 4 0.000002 1.0000 1.0000 0.7134 1.0000 1.0000 0.2500
|
||||
9 40 0 16777216 2097152 2088944 0x02bfe264 3 0.000001 1.0000 1.0000 0.5601 1.0000 0.2500 0.0625
|
||||
10 41 2 4194304 2097152 2064767 0x07c7bcad 4 0.000002 1.0000 1.0000 0.7134 1.0000 1.0000 0.2500
|
||||
11 43 0 16777216 2097152 2088982 0x01d60a6b 3 0.000001 1.0000 1.0000 0.5602 1.0000 0.2500 0.0625
|
||||
12 45 2 4194304 2097152 2064590 0x06a0072f 4 0.000002 1.0000 1.0000 0.7135 1.0000 1.0000 0.2500
|
||||
13 52 1 8388608 2097152 2081002 0x0b22db86 4 0.000002 1.0000 1.0000 0.6153 1.0000 0.5000 0.1250
|
||||
14 53 0 16777216 2097152 2089141 0x0bf3da54 3 0.000001 1.0000 1.0000 0.5595 1.0000 0.2500 0.0625
|
||||
15 54 2 4194304 2097152 2064886 0x05112bb2 4 0.000002 1.0000 1.0000 0.7131 1.0000 1.0000 0.2500
|
||||
# program: reads 33554432, distinct items 13433475, worst site 0 address 0x0ef27367 in 4 reads (share 0.000002); one cache over the program's reads: 1 GiB 1.0000, 256 MiB 0.5431, 64 MiB 0.1900; the per-site ideal caches summed: 1.0000, 1.0000, 0.6339; 14.0 s
|
||||
|
Can't render this file because it has a wrong number of fields in line 3.
|
|
|
@ -0,0 +1,25 @@
|
|||
# addrsite: program f1ca3ca995c57b7a class mx8-erad810f22d+sh256x27+state attempt 0 generator v5 day 2026-10-03 dataset 2^28 words (memory-hard) headers 4 warps 2048 nonces/header 65536 threads 16
|
||||
# per (iteration, site) cell: the most read address and its share (A03's form); cells over 0.1 percent listed
|
||||
it site instr reads distinct top_addr top_count top_share
|
||||
0 0 3 262144 261892 0x09e864fe 2 0.000008
|
||||
0 1 6 262144 261629 0x057bb032 2 0.000008
|
||||
# worst cell: iteration 0 site 5 address 0x0d89bc86 in 3 reads, share 0.000011
|
||||
# per site, pooled over the 8 iterations (hit rates: an ideal cache of the site's top K items, K = bytes / 64; exp = min(1, K / window items))
|
||||
site instr win window_items reads distinct top_addr top_count top_share hit_1GiB hit_256MiB hit_64MiB exp_1GiB exp_256MiB exp_64MiB
|
||||
0 3 1 8388608 2097152 2080687 0x09cc2aae 4 0.000002 1.0000 1.0000 0.6154 1.0000 0.5000 0.1250
|
||||
1 6 2 4194304 2097152 2064419 0x04953f35 4 0.000002 1.0000 1.0000 0.7131 1.0000 1.0000 0.2500
|
||||
2 11 0 16777216 2097152 2089014 0x0e54fa3c 3 0.000001 1.0000 1.0000 0.5597 1.0000 0.2500 0.0625
|
||||
3 18 0 16777216 2097152 2089096 0x0bd51c54 3 0.000001 1.0000 1.0000 0.5599 1.0000 0.2500 0.0625
|
||||
4 27 0 16777216 2097152 2088932 0x075d38ad 3 0.000001 1.0000 1.0000 0.5602 1.0000 0.2500 0.0625
|
||||
5 34 2 4194304 2097152 2064625 0x0c1f406f 4 0.000002 1.0000 1.0000 0.7126 1.0000 1.0000 0.2500
|
||||
6 37 0 16777216 2097152 2089106 0x025e834b 3 0.000001 1.0000 1.0000 0.5599 1.0000 0.2500 0.0625
|
||||
7 40 1 8388608 2097152 2080559 0x097cbb71 3 0.000001 1.0000 1.0000 0.6155 1.0000 0.5000 0.1250
|
||||
8 41 0 16777216 2097152 2089067 0x02514a26 3 0.000001 1.0000 1.0000 0.5597 1.0000 0.2500 0.0625
|
||||
9 42 0 16777216 2097152 2089350 0x06002c19 3 0.000001 1.0000 1.0000 0.5599 1.0000 0.2500 0.0625
|
||||
10 48 2 4194304 2097152 2064372 0x09fcf47a 4 0.000002 1.0000 1.0000 0.7128 1.0000 1.0000 0.2500
|
||||
11 50 2 4194304 2097152 2064506 0x04a37902 4 0.000002 1.0000 1.0000 0.7129 1.0000 1.0000 0.2500
|
||||
12 55 2 4194304 2097152 2064846 0x09edce5f 4 0.000002 1.0000 1.0000 0.7130 1.0000 1.0000 0.2500
|
||||
13 57 1 8388608 2097152 2080995 0x0b517860 3 0.000001 1.0000 1.0000 0.6152 1.0000 0.5000 0.1250
|
||||
14 60 0 16777216 2097152 2089075 0x04cb1a83 3 0.000001 1.0000 1.0000 0.5597 1.0000 0.2500 0.0625
|
||||
15 62 2 4194304 2097152 2064780 0x018597b1 4 0.000002 1.0000 1.0000 0.7135 1.0000 1.0000 0.2500
|
||||
# program: reads 33554432, distinct items 14269676, worst site 0 address 0x09cc2aae in 4 reads (share 0.000002); one cache over the program's reads: 1 GiB 1.0000, 256 MiB 0.4975, 64 MiB 0.1715; the per-site ideal caches summed: 1.0000, 1.0000, 0.6277; 14.6 s
|
||||
|
Can't render this file because it has a wrong number of fields in line 3.
|
|
|
@ -0,0 +1,25 @@
|
|||
# addrsite: program 116d921a2211b1e2 class mx8-erad810f22d+sh256x27+state attempt 5 generator v5 day 2026-10-03 dataset 2^28 words (memory-hard) headers 4 warps 2048 nonces/header 65536 threads 16
|
||||
# per (iteration, site) cell: the most read address and its share (A03's form); cells over 0.1 percent listed
|
||||
it site instr reads distinct top_addr top_count top_share
|
||||
0 0 5 262144 261669 0x01050961 2 0.000008
|
||||
0 1 7 262144 261891 0x0b8ed622 2 0.000008
|
||||
# worst cell: iteration 0 site 2 address 0x0963ada0 in 3 reads, share 0.000011
|
||||
# per site, pooled over the 8 iterations (hit rates: an ideal cache of the site's top K items, K = bytes / 64; exp = min(1, K / window items))
|
||||
site instr win window_items reads distinct top_addr top_count top_share hit_1GiB hit_256MiB hit_64MiB exp_1GiB exp_256MiB exp_64MiB
|
||||
0 5 2 4194304 2097152 2064493 0x014302b1 4 0.000002 1.0000 1.0000 0.7133 1.0000 1.0000 0.2500
|
||||
1 7 1 8388608 2097152 2080737 0x0a0976d0 3 0.000001 1.0000 1.0000 0.6152 1.0000 0.5000 0.1250
|
||||
2 8 1 8388608 2097152 2081029 0x0b6ed91b 3 0.000001 1.0000 1.0000 0.6152 1.0000 0.5000 0.1250
|
||||
3 20 2 4194304 2097152 2064643 0x02524dea 4 0.000002 1.0000 1.0000 0.7132 1.0000 1.0000 0.2500
|
||||
4 23 1 8388608 2097152 2080718 0x042d7538 3 0.000001 1.0000 1.0000 0.6151 1.0000 0.5000 0.1250
|
||||
5 25 2 4194304 2097152 2064724 0x01d7b06d 4 0.000002 1.0000 1.0000 0.7131 1.0000 1.0000 0.2500
|
||||
6 34 1 8388608 2097152 2081070 0x0bcd40e4 3 0.000001 1.0000 1.0000 0.6153 1.0000 0.5000 0.1250
|
||||
7 36 2 4194304 2097152 2064873 0x00115d7b 4 0.000002 1.0000 1.0000 0.7128 1.0000 1.0000 0.2500
|
||||
8 37 2 4194304 2097152 2064738 0x078f0ce1 4 0.000002 1.0000 1.0000 0.7126 1.0000 1.0000 0.2500
|
||||
9 40 1 8388608 2097152 2080877 0x08def9d8 4 0.000002 1.0000 1.0000 0.6150 1.0000 0.5000 0.1250
|
||||
10 43 2 4194304 2097152 2064478 0x0e30a1d9 4 0.000002 1.0000 1.0000 0.7130 1.0000 1.0000 0.2500
|
||||
11 45 0 16777216 2097152 2088942 0x05a5a0df 3 0.000001 1.0000 1.0000 0.5599 1.0000 0.2500 0.0625
|
||||
12 46 2 4194304 2097152 2064810 0x0b9648a3 4 0.000002 1.0000 1.0000 0.7129 1.0000 1.0000 0.2500
|
||||
13 48 1 8388608 2097152 2080613 0x0331f3df 3 0.000001 1.0000 1.0000 0.6152 1.0000 0.5000 0.1250
|
||||
14 51 2 4194304 2097152 2064984 0x0979b87d 4 0.000002 1.0000 1.0000 0.7126 1.0000 1.0000 0.2500
|
||||
15 59 2 4194304 2097152 2064679 0x0828a5bd 4 0.000002 1.0000 1.0000 0.7127 1.0000 1.0000 0.2500
|
||||
# program: reads 33554432, distinct items 13982239, worst site 0 address 0x014302b1 in 4 reads (share 0.000002); one cache over the program's reads: 1 GiB 1.0000, 256 MiB 0.5120, 64 MiB 0.1767; the per-site ideal caches summed: 1.0000, 1.0000, 0.6667; 13.9 s
|
||||
|
Can't render this file because it has a wrong number of fields in line 3.
|
|
|
@ -0,0 +1,41 @@
|
|||
# addrsite: program 9d40978601a7df2a class mx8-erad810f22d+sh256x27+state+reg64c+fold+rw attempt 0 generator v5 day bytes:69676e65756d2d6461792ffa50000000000000 dataset 2^28 words (memory-hard) headers 4 warps 32768 nonces/header 1048576 threads 32
|
||||
# per (iteration, site) cell: the most read address and its share (A03's form); cells over 0.1 percent listed
|
||||
it site instr reads distinct top_addr top_count top_share
|
||||
0 0 7 4194304 4066428 0x06831154 5 0.000001
|
||||
0 1 7 4194304 4065945 0x06728584 5 0.000001
|
||||
# worst cell: iteration 0 site 0 address 0x06831154 in 5 reads, share 0.000001
|
||||
# per site, pooled over the 8 iterations (hit rates: an ideal cache of the site's top K items, K = bytes / 64; exp = min(1, K / window items))
|
||||
site instr win window_items reads distinct top_addr top_count top_share hit_1GiB hit_256MiB hit_64MiB exp_1GiB exp_256MiB exp_64MiB
|
||||
0 7 2 4194304 33554432 26406983 0x077acf9f 8 0.000000 1.0000 1.0000 0.3657 1.0000 1.0000 0.2500
|
||||
1 7 2 4194304 33554432 26407099 0x075d1595 8 0.000000 1.0000 1.0000 0.3657 1.0000 1.0000 0.2500
|
||||
2 8 1 8388608 33554432 29685906 0x095df095 7 0.000000 1.0000 0.6954 0.2363 1.0000 0.5000 0.1250
|
||||
3 8 1 8388608 33554432 29689759 0x0d48fd7f 7 0.000000 1.0000 0.6953 0.2363 1.0000 0.5000 0.1250
|
||||
4 9 1 8388608 33554432 29688561 0x0cae47fb 7 0.000000 1.0000 0.6954 0.2364 1.0000 0.5000 0.1250
|
||||
5 9 1 8388608 33554432 29688354 0x0fe14ca5 7 0.000000 1.0000 0.6954 0.2363 1.0000 0.5000 0.1250
|
||||
6 10 1 8388608 33554432 29687856 0x0f8b245b 7 0.000000 1.0000 0.6954 0.2364 1.0000 0.5000 0.1250
|
||||
7 10 1 8388608 33554432 29688349 0x08425327 7 0.000000 1.0000 0.6953 0.2363 1.0000 0.5000 0.1250
|
||||
8 11 0 16777216 33554432 31540946 0x034a8a5e 6 0.000000 1.0000 0.4840 0.1626 1.0000 0.2500 0.0625
|
||||
9 11 0 16777216 33554432 31541360 0x0000903c 6 0.000000 1.0000 0.4840 0.1626 1.0000 0.2500 0.0625
|
||||
10 13 1 8388608 33554432 29688264 0x0ea87d99 7 0.000000 1.0000 0.6954 0.2363 1.0000 0.5000 0.1250
|
||||
11 13 1 8388608 33554432 29686990 0x0bf38c41 7 0.000000 1.0000 0.6954 0.2364 1.0000 0.5000 0.1250
|
||||
12 29 0 16777216 33554432 31541730 0x0fa351d0 6 0.000000 1.0000 0.4840 0.1625 1.0000 0.2500 0.0625
|
||||
13 29 0 16777216 33554432 31542373 0x0312c834 6 0.000000 1.0000 0.4841 0.1626 1.0000 0.2500 0.0625
|
||||
14 30 2 4194304 33554432 26403434 0x0b7e3663 8 0.000000 1.0000 1.0000 0.3657 1.0000 1.0000 0.2500
|
||||
15 30 2 4194304 33554432 26405616 0x09a7c958 9 0.000000 1.0000 1.0000 0.3657 1.0000 1.0000 0.2500
|
||||
16 31 1 8388608 33554432 29691410 0x0ee4cd53 7 0.000000 1.0000 0.6954 0.2364 1.0000 0.5000 0.1250
|
||||
17 31 1 8388608 33554432 29686494 0x0b0c7781 7 0.000000 1.0000 0.6954 0.2364 1.0000 0.5000 0.1250
|
||||
18 44 1 8388608 33554432 29688457 0x0f90686c 7 0.000000 1.0000 0.6954 0.2364 1.0000 0.5000 0.1250
|
||||
19 44 1 8388608 33554432 29685901 0x0df3d2af 6 0.000000 1.0000 0.6955 0.2365 1.0000 0.5000 0.1250
|
||||
20 46 2 4194304 33554432 26404720 0x00ba5efc 9 0.000000 1.0000 1.0000 0.3657 1.0000 1.0000 0.2500
|
||||
21 46 2 4194304 33554432 26405688 0x00d500b5 8 0.000000 1.0000 1.0000 0.3657 1.0000 1.0000 0.2500
|
||||
22 47 0 16777216 33554432 31542188 0x0592b907 5 0.000000 1.0000 0.4841 0.1626 1.0000 0.2500 0.0625
|
||||
23 47 0 16777216 33554432 31543890 0x0ef28510 5 0.000000 1.0000 0.4839 0.1625 1.0000 0.2500 0.0625
|
||||
24 52 0 16777216 33554432 31540529 0x05168e23 6 0.000000 1.0000 0.4841 0.1626 1.0000 0.2500 0.0625
|
||||
25 52 0 16777216 33554432 31541135 0x06ddf60f 6 0.000000 1.0000 0.4840 0.1626 1.0000 0.2500 0.0625
|
||||
26 56 0 16777216 33554432 31543259 0x01c24b6f 6 0.000000 1.0000 0.4840 0.1626 1.0000 0.2500 0.0625
|
||||
27 56 0 16777216 33554432 31540946 0x002bcb87 6 0.000000 1.0000 0.4840 0.1625 1.0000 0.2500 0.0625
|
||||
28 58 2 4194304 33554432 26405574 0x038d061e 8 0.000000 1.0000 1.0000 0.3658 1.0000 1.0000 0.2500
|
||||
29 58 2 4194304 33554432 26406725 0x03e10d8c 8 0.000000 1.0000 1.0000 0.3656 1.0000 1.0000 0.2500
|
||||
30 63 1 8388608 33554432 29686125 0x09af5008 7 0.000000 1.0000 0.6955 0.2364 1.0000 0.5000 0.1250
|
||||
31 63 1 8388608 33554432 29689988 0x0bcb2b69 6 0.000000 1.0000 0.6953 0.2363 1.0000 0.5000 0.1250
|
||||
# program: reads 1073741824, distinct items 16777216, worst site 15 address 0x09a7c958 in 9 reads (share 0.000000); one cache over the program's reads: 1 GiB 1.0000, 256 MiB 0.3669, 64 MiB 0.1020; the per-site ideal caches summed: 1.0000, 0.7055, 0.2456; 484.7 s
|
||||
|
Can't render this file because it has a wrong number of fields in line 3.
|
|
|
@ -0,0 +1,41 @@
|
|||
# addrsite: program 9d40978601a7df2a class mx8-erad810f22d+sh256x27+state+reg64c+fold+rw attempt 0 generator v5 day bytes:69676e65756d2d6461792ffa50000000000000 dataset 2^28 words (memory-hard) headers 4 warps 2048 nonces/header 65536 threads 16
|
||||
# per (iteration, site) cell: the most read address and its share (A03's form); cells over 0.1 percent listed
|
||||
it site instr reads distinct top_addr top_count top_share
|
||||
0 0 7 262144 261628 0x079744dc 2 0.000008
|
||||
0 1 7 262144 261628 0x07bf4904 3 0.000011
|
||||
# worst cell: iteration 0 site 1 address 0x07bf4904 in 3 reads, share 0.000011
|
||||
# per site, pooled over the 8 iterations (hit rates: an ideal cache of the site's top K items, K = bytes / 64; exp = min(1, K / window items))
|
||||
site instr win window_items reads distinct top_addr top_count top_share hit_1GiB hit_256MiB hit_64MiB exp_1GiB exp_256MiB exp_64MiB
|
||||
0 7 2 4194304 2097152 2064448 0x06d96803 4 0.000002 1.0000 1.0000 0.7126 1.0000 1.0000 0.2500
|
||||
1 7 2 4194304 2097152 2064778 0x0696d259 4 0.000002 1.0000 1.0000 0.7129 1.0000 1.0000 0.2500
|
||||
2 8 1 8388608 2097152 2080642 0x0ce89189 3 0.000001 1.0000 1.0000 0.6156 1.0000 0.5000 0.1250
|
||||
3 8 1 8388608 2097152 2081013 0x0d83f140 3 0.000001 1.0000 1.0000 0.6150 1.0000 0.5000 0.1250
|
||||
4 9 1 8388608 2097152 2080839 0x0b90185c 3 0.000001 1.0000 1.0000 0.6154 1.0000 0.5000 0.1250
|
||||
5 9 1 8388608 2097152 2080772 0x0df55813 3 0.000001 1.0000 1.0000 0.6156 1.0000 0.5000 0.1250
|
||||
6 10 1 8388608 2097152 2080764 0x0ccc8517 3 0.000001 1.0000 1.0000 0.6155 1.0000 0.5000 0.1250
|
||||
7 10 1 8388608 2097152 2081011 0x08d25adf 4 0.000002 1.0000 1.0000 0.6149 1.0000 0.5000 0.1250
|
||||
8 11 0 16777216 2097152 2089078 0x093585d5 3 0.000001 1.0000 1.0000 0.5597 1.0000 0.2500 0.0625
|
||||
9 11 0 16777216 2097152 2089067 0x01343909 3 0.000001 1.0000 1.0000 0.5598 1.0000 0.2500 0.0625
|
||||
10 13 1 8388608 2097152 2080681 0x0c547529 3 0.000001 1.0000 1.0000 0.6154 1.0000 0.5000 0.1250
|
||||
11 13 1 8388608 2097152 2080675 0x0a3c9f41 4 0.000002 1.0000 1.0000 0.6155 1.0000 0.5000 0.1250
|
||||
12 29 0 16777216 2097152 2088998 0x0bf0df66 3 0.000001 1.0000 1.0000 0.5601 1.0000 0.2500 0.0625
|
||||
13 29 0 16777216 2097152 2088838 0x023f4cda 3 0.000001 1.0000 1.0000 0.5600 1.0000 0.2500 0.0625
|
||||
14 30 2 4194304 2097152 2065006 0x0a80c676 4 0.000002 1.0000 1.0000 0.7128 1.0000 1.0000 0.2500
|
||||
15 30 2 4194304 2097152 2064992 0x0a225340 4 0.000002 1.0000 1.0000 0.7129 1.0000 1.0000 0.2500
|
||||
16 31 1 8388608 2097152 2080815 0x0f1f389f 4 0.000002 1.0000 1.0000 0.6156 1.0000 0.5000 0.1250
|
||||
17 31 1 8388608 2097152 2080921 0x0ed0caf3 4 0.000002 1.0000 1.0000 0.6149 1.0000 0.5000 0.1250
|
||||
18 44 1 8388608 2097152 2080854 0x0d22ac30 4 0.000002 1.0000 1.0000 0.6153 1.0000 0.5000 0.1250
|
||||
19 44 1 8388608 2097152 2080659 0x0c23eefc 4 0.000002 1.0000 1.0000 0.6153 1.0000 0.5000 0.1250
|
||||
20 46 2 4194304 2097152 2064744 0x012a229f 4 0.000002 1.0000 1.0000 0.7131 1.0000 1.0000 0.2500
|
||||
21 46 2 4194304 2097152 2064617 0x0275d76a 4 0.000002 1.0000 1.0000 0.7137 1.0000 1.0000 0.2500
|
||||
22 47 0 16777216 2097152 2088997 0x046b820d 3 0.000001 1.0000 1.0000 0.5601 1.0000 0.2500 0.0625
|
||||
23 47 0 16777216 2097152 2088930 0x0f72acf6 3 0.000001 1.0000 1.0000 0.5600 1.0000 0.2500 0.0625
|
||||
24 52 0 16777216 2097152 2088940 0x042404ce 3 0.000001 1.0000 1.0000 0.5597 1.0000 0.2500 0.0625
|
||||
25 52 0 16777216 2097152 2088935 0x06f0e9f9 3 0.000001 1.0000 1.0000 0.5600 1.0000 0.2500 0.0625
|
||||
26 56 0 16777216 2097152 2089008 0x0c3464dd 3 0.000001 1.0000 1.0000 0.5599 1.0000 0.2500 0.0625
|
||||
27 56 0 16777216 2097152 2088795 0x0836e9c5 3 0.000001 1.0000 1.0000 0.5597 1.0000 0.2500 0.0625
|
||||
28 58 2 4194304 2097152 2064592 0x019f92c8 4 0.000002 1.0000 1.0000 0.7128 1.0000 1.0000 0.2500
|
||||
29 58 2 4194304 2097152 2064763 0x01de29d9 4 0.000002 1.0000 1.0000 0.7132 1.0000 1.0000 0.2500
|
||||
30 63 1 8388608 2097152 2080695 0x0e6d09cb 4 0.000002 1.0000 1.0000 0.6153 1.0000 0.5000 0.1250
|
||||
31 63 1 8388608 2097152 2080906 0x0ef4a769 3 0.000001 1.0000 1.0000 0.6151 1.0000 0.5000 0.1250
|
||||
# program: reads 67108864, distinct items 16122715, worst site 0 address 0x06d96803 in 4 reads (share 0.000002); one cache over the program's reads: 1 GiB 1.0000, 256 MiB 0.4570, 64 MiB 0.1473; the per-site ideal caches summed: 1.0000, 1.0000, 0.6224; 30.2 s
|
||||
|
Can't render this file because it has a wrong number of fields in line 3.
|
|
|
@ -0,0 +1,41 @@
|
|||
# addrsite: program 7202548bfc7f98e9 class mx8-erad810f22d+sh256x27+state+reg64c+fold+rw attempt 0 generator v5 day 2026-10-03 dataset 2^28 words (memory-hard) headers 4 warps 2048 nonces/header 65536 threads 16
|
||||
# per (iteration, site) cell: the most read address and its share (A03's form); cells over 0.1 percent listed
|
||||
it site instr reads distinct top_addr top_count top_share
|
||||
0 0 3 262144 261870 0x0efd4508 2 0.000008
|
||||
0 1 3 262144 261887 0x0893a882 2 0.000008
|
||||
# worst cell: iteration 0 site 2 address 0x0487cb8f in 3 reads, share 0.000011
|
||||
# per site, pooled over the 8 iterations (hit rates: an ideal cache of the site's top K items, K = bytes / 64; exp = min(1, K / window items))
|
||||
site instr win window_items reads distinct top_addr top_count top_share hit_1GiB hit_256MiB hit_64MiB exp_1GiB exp_256MiB exp_64MiB
|
||||
0 3 1 8388608 2097152 2080923 0x08e1d1ff 3 0.000001 1.0000 1.0000 0.6152 1.0000 0.5000 0.1250
|
||||
1 3 1 8388608 2097152 2080828 0x0a843020 3 0.000001 1.0000 1.0000 0.6154 1.0000 0.5000 0.1250
|
||||
2 6 2 4194304 2097152 2064487 0x06d6d73a 4 0.000002 1.0000 1.0000 0.7132 1.0000 1.0000 0.2500
|
||||
3 6 2 4194304 2097152 2064806 0x07283952 4 0.000002 1.0000 1.0000 0.7127 1.0000 1.0000 0.2500
|
||||
4 11 0 16777216 2097152 2089099 0x05be9d5e 3 0.000001 1.0000 1.0000 0.5599 1.0000 0.2500 0.0625
|
||||
5 11 0 16777216 2097152 2089019 0x05c67ab2 3 0.000001 1.0000 1.0000 0.5600 1.0000 0.2500 0.0625
|
||||
6 18 0 16777216 2097152 2088983 0x0c278962 3 0.000001 1.0000 1.0000 0.5599 1.0000 0.2500 0.0625
|
||||
7 18 0 16777216 2097152 2088937 0x0f2011bd 3 0.000001 1.0000 1.0000 0.5601 1.0000 0.2500 0.0625
|
||||
8 27 0 16777216 2097152 2089028 0x082fea89 3 0.000001 1.0000 1.0000 0.5599 1.0000 0.2500 0.0625
|
||||
9 27 0 16777216 2097152 2088927 0x0f144d4a 3 0.000001 1.0000 1.0000 0.5603 1.0000 0.2500 0.0625
|
||||
10 34 2 4194304 2097152 2064808 0x0d913ee6 4 0.000002 1.0000 1.0000 0.7131 1.0000 1.0000 0.2500
|
||||
11 34 2 4194304 2097152 2064752 0x0c5f31b3 4 0.000002 1.0000 1.0000 0.7131 1.0000 1.0000 0.2500
|
||||
12 37 0 16777216 2097152 2089093 0x06cc1944 3 0.000001 1.0000 1.0000 0.5600 1.0000 0.2500 0.0625
|
||||
13 37 0 16777216 2097152 2088932 0x0d3f9438 3 0.000001 1.0000 1.0000 0.5601 1.0000 0.2500 0.0625
|
||||
14 40 1 8388608 2097152 2080863 0x0b6d4b80 4 0.000002 1.0000 1.0000 0.6157 1.0000 0.5000 0.1250
|
||||
15 40 1 8388608 2097152 2080759 0x0a3c9dc4 3 0.000001 1.0000 1.0000 0.6149 1.0000 0.5000 0.1250
|
||||
16 41 0 16777216 2097152 2088798 0x0570efe1 3 0.000001 1.0000 1.0000 0.5601 1.0000 0.2500 0.0625
|
||||
17 41 0 16777216 2097152 2089025 0x0c9bdffd 3 0.000001 1.0000 1.0000 0.5598 1.0000 0.2500 0.0625
|
||||
18 42 0 16777216 2097152 2089050 0x0dc6094e 3 0.000001 1.0000 1.0000 0.5597 1.0000 0.2500 0.0625
|
||||
19 42 0 16777216 2097152 2088995 0x03e6a203 3 0.000001 1.0000 1.0000 0.5599 1.0000 0.2500 0.0625
|
||||
20 48 2 4194304 2097152 2064645 0x096844ff 4 0.000002 1.0000 1.0000 0.7135 1.0000 1.0000 0.2500
|
||||
21 48 2 4194304 2097152 2064808 0x0b3838ea 3 0.000001 1.0000 1.0000 0.7128 1.0000 1.0000 0.2500
|
||||
22 50 2 4194304 2097152 2064783 0x04c17bf8 4 0.000002 1.0000 1.0000 0.7129 1.0000 1.0000 0.2500
|
||||
23 50 2 4194304 2097152 2064745 0x0515cc27 3 0.000001 1.0000 1.0000 0.7134 1.0000 1.0000 0.2500
|
||||
24 55 2 4194304 2097152 2064873 0x0affa7fb 4 0.000002 1.0000 1.0000 0.7128 1.0000 1.0000 0.2500
|
||||
25 55 2 4194304 2097152 2064731 0x0b3d9f33 4 0.000002 1.0000 1.0000 0.7130 1.0000 1.0000 0.2500
|
||||
26 57 1 8388608 2097152 2080977 0x08ca184c 4 0.000002 1.0000 1.0000 0.6151 1.0000 0.5000 0.1250
|
||||
27 57 1 8388608 2097152 2080897 0x08f82546 3 0.000001 1.0000 1.0000 0.6150 1.0000 0.5000 0.1250
|
||||
28 60 0 16777216 2097152 2089095 0x0d8ef7f5 3 0.000001 1.0000 1.0000 0.5603 1.0000 0.2500 0.0625
|
||||
29 60 0 16777216 2097152 2089026 0x00909439 3 0.000001 1.0000 1.0000 0.5600 1.0000 0.2500 0.0625
|
||||
30 62 2 4194304 2097152 2064740 0x0386ae9d 4 0.000002 1.0000 1.0000 0.7129 1.0000 1.0000 0.2500
|
||||
31 62 2 4194304 2097152 2064734 0x02ec2e89 4 0.000002 1.0000 1.0000 0.7127 1.0000 1.0000 0.2500
|
||||
# program: reads 67108864, distinct items 16329983, worst site 2 address 0x06d6d73a in 4 reads (share 0.000002); one cache over the program's reads: 1 GiB 1.0000, 256 MiB 0.4343, 64 MiB 0.1395; the per-site ideal caches summed: 1.0000, 1.0000, 0.6277; 34.7 s
|
||||
|
Can't render this file because it has a wrong number of fields in line 3.
|
|
|
@ -0,0 +1,41 @@
|
|||
# addrsite: program dd6b285ae45e7b9b class mx8-erad810f22d+sh256x27+state+reg64c+fold+rw attempt 1 generator v5 day 2026-10-03 dataset 2^28 words (memory-hard) headers 4 warps 2048 nonces/header 65536 threads 16
|
||||
# per (iteration, site) cell: the most read address and its share (A03's form); cells over 0.1 percent listed
|
||||
it site instr reads distinct top_addr top_count top_share
|
||||
0 0 5 262144 261992 0x093e5b52 2 0.000008
|
||||
0 1 5 262144 262025 0x0588dd22 2 0.000008
|
||||
# worst cell: iteration 0 site 9 address 0x001d0694 in 3 reads, share 0.000011
|
||||
# per site, pooled over the 8 iterations (hit rates: an ideal cache of the site's top K items, K = bytes / 64; exp = min(1, K / window items))
|
||||
site instr win window_items reads distinct top_addr top_count top_share hit_1GiB hit_256MiB hit_64MiB exp_1GiB exp_256MiB exp_64MiB
|
||||
0 5 0 16777216 2097152 2088958 0x0ea448b9 3 0.000001 1.0000 1.0000 0.5600 1.0000 0.2500 0.0625
|
||||
1 5 0 16777216 2097152 2088967 0x0ed82abf 3 0.000001 1.0000 1.0000 0.5598 1.0000 0.2500 0.0625
|
||||
2 7 0 16777216 2097152 2089029 0x0ab975a7 3 0.000001 1.0000 1.0000 0.5599 1.0000 0.2500 0.0625
|
||||
3 7 0 16777216 2097152 2089105 0x0db085c6 3 0.000001 1.0000 1.0000 0.5599 1.0000 0.2500 0.0625
|
||||
4 9 0 16777216 2097152 2089008 0x044799b7 3 0.000001 1.0000 1.0000 0.5598 1.0000 0.2500 0.0625
|
||||
5 9 0 16777216 2097152 2088965 0x0655d6ee 3 0.000001 1.0000 1.0000 0.5601 1.0000 0.2500 0.0625
|
||||
6 19 1 8388608 2097152 2080653 0x0000e5b2 4 0.000002 1.0000 1.0000 0.6154 1.0000 0.5000 0.1250
|
||||
7 19 1 8388608 2097152 2081006 0x071d3d60 3 0.000001 1.0000 1.0000 0.6155 1.0000 0.5000 0.1250
|
||||
8 20 2 4194304 2097152 2064587 0x023f6f9c 4 0.000002 1.0000 1.0000 0.7133 1.0000 1.0000 0.2500
|
||||
9 20 2 4194304 2097152 2064648 0x0140515b 4 0.000002 1.0000 1.0000 0.7128 1.0000 1.0000 0.2500
|
||||
10 25 1 8388608 2097152 2081158 0x05e847b6 3 0.000001 1.0000 1.0000 0.6152 1.0000 0.5000 0.1250
|
||||
11 25 1 8388608 2097152 2080864 0x058e694f 3 0.000001 1.0000 1.0000 0.6152 1.0000 0.5000 0.1250
|
||||
12 26 0 16777216 2097152 2088978 0x0ae79244 3 0.000001 1.0000 1.0000 0.5602 1.0000 0.2500 0.0625
|
||||
13 26 0 16777216 2097152 2088938 0x00bb51de 3 0.000001 1.0000 1.0000 0.5597 1.0000 0.2500 0.0625
|
||||
14 30 1 8388608 2097152 2080727 0x0f927d9d 4 0.000002 1.0000 1.0000 0.6151 1.0000 0.5000 0.1250
|
||||
15 30 1 8388608 2097152 2081019 0x0b4d0513 3 0.000001 1.0000 1.0000 0.6153 1.0000 0.5000 0.1250
|
||||
16 33 0 16777216 2097152 2088869 0x0ae48a33 3 0.000001 1.0000 1.0000 0.5601 1.0000 0.2500 0.0625
|
||||
17 33 0 16777216 2097152 2089002 0x020d5061 3 0.000001 1.0000 1.0000 0.5599 1.0000 0.2500 0.0625
|
||||
18 42 2 4194304 2097152 2064744 0x0372f590 4 0.000002 1.0000 1.0000 0.7131 1.0000 1.0000 0.2500
|
||||
19 42 2 4194304 2097152 2065038 0x01c17bb1 4 0.000002 1.0000 1.0000 0.7132 1.0000 1.0000 0.2500
|
||||
20 44 1 8388608 2097152 2080897 0x050be2db 3 0.000001 1.0000 1.0000 0.6152 1.0000 0.5000 0.1250
|
||||
21 44 1 8388608 2097152 2080780 0x034e8ac6 3 0.000001 1.0000 1.0000 0.6153 1.0000 0.5000 0.1250
|
||||
22 47 2 4194304 2097152 2064986 0x0662b4cd 4 0.000002 1.0000 1.0000 0.7132 1.0000 1.0000 0.2500
|
||||
23 47 2 4194304 2097152 2064667 0x076e0933 4 0.000002 1.0000 1.0000 0.7134 1.0000 1.0000 0.2500
|
||||
24 52 1 8388608 2097152 2080859 0x0bf1df1e 4 0.000002 1.0000 1.0000 0.6150 1.0000 0.5000 0.1250
|
||||
25 52 1 8388608 2097152 2080789 0x0e55479b 4 0.000002 1.0000 1.0000 0.6155 1.0000 0.5000 0.1250
|
||||
26 53 1 8388608 2097152 2080719 0x0569020e 3 0.000001 1.0000 1.0000 0.6149 1.0000 0.5000 0.1250
|
||||
27 53 1 8388608 2097152 2081019 0x025da50a 3 0.000001 1.0000 1.0000 0.6150 1.0000 0.5000 0.1250
|
||||
28 55 2 4194304 2097152 2064664 0x0731a8b5 3 0.000001 1.0000 1.0000 0.7135 1.0000 1.0000 0.2500
|
||||
29 55 2 4194304 2097152 2064744 0x054158aa 4 0.000002 1.0000 1.0000 0.7129 1.0000 1.0000 0.2500
|
||||
30 62 0 16777216 2097152 2088917 0x00b90aa2 3 0.000001 1.0000 1.0000 0.5604 1.0000 0.2500 0.0625
|
||||
31 62 0 16777216 2097152 2088900 0x008cbc10 3 0.000001 1.0000 1.0000 0.5599 1.0000 0.2500 0.0625
|
||||
# program: reads 67108864, distinct items 16055477, worst site 6 address 0x0000e5b2 in 4 reads (share 0.000002); one cache over the program's reads: 1 GiB 1.0000, 256 MiB 0.4659, 64 MiB 0.1506; the per-site ideal caches summed: 1.0000, 1.0000, 0.6190; 28.3 s
|
||||
|
Can't render this file because it has a wrong number of fields in line 3.
|
|
|
@ -0,0 +1,7 @@
|
|||
v5-dn3-epoch0 ) 3:0:0 8:2:2 14:1:0 15:0:0 20:1:1 26:1:1 28:1:1 35:0:0 40:2:3 43:1:0 47:1:1 49:0:0 52:2:3 53:0:0 61:1:1 62:1:1
|
||||
v5-node1-genesis ) 1:2:3 4:2:1 6:2:1 10:1:1 12:0:0 20:0:0 27:0:0 30:0:0 35:2:3 40:0:0 41:2:1 43:0:0 45:2:1 52:1:1 53:0:0 54:2:1
|
||||
v6-all-node1 ) 7:2:1 8:1:1 9:1:1 10:1:1 11:0:0 13:1:1 29:0:0 30:2:2 31:1:1 44:1:1 46:2:0 47:0:0 52:0:0 56:0:0 58:2:0 63:1:1
|
||||
v5-seed18 ) 3:1:1 6:2:1 11:0:0 18:0:0 27:0:0 34:2:3 37:0:0 40:1:1 41:0:0 42:0:0 48:2:2 50:2:1 55:2:2 57:1:1 60:0:0 62:2:0
|
||||
v6-seed18 ) 3:1:1 6:2:1 11:0:0 18:0:0 27:0:0 34:2:3 37:0:0 40:1:1 41:0:0 42:0:0 48:2:2 50:2:1 55:2:2 57:1:1 60:0:0 62:2:0
|
||||
v5-seed19 ) 5:2:0 7:1:1 8:1:1 20:2:0 23:1:0 25:2:0 34:1:1 36:2:0 37:2:1 40:1:1 43:2:3 45:0:0 46:2:2 48:1:0 51:2:2 59:2:2
|
||||
v6-seed19 ) 5:0:0 7:0:0 9:0:0 19:1:0 20:2:0 25:1:0 26:0:0 30:1:1 33:0:0 42:2:0 44:1:0 47:2:1 52:1:1 53:1:0 55:2:1 62:0:0
|
||||
65
docs/build/compatibility.md
vendored
65
docs/build/compatibility.md
vendored
|
|
@ -2,74 +2,81 @@
|
|||
|
||||
A GPU-secured network for Ethereum-compatible applications and verifiable computation. Compatibility is a product deliverable here, not a sentence: every row below is a test that ran against the devnet from the repository (`tools/reference-apps/compat/run.mjs`), with its evidence, and a row that could not run says so and why. Devnet, no value.
|
||||
|
||||
Last run: 2026-10-08 16:34 UTC on igneum-devnet-4 (chain id 4465). 20 passed, 0 failed, 0 untested. TEAM-REPORTED: run by the team, no outside reproduction yet. Sender 0x27C433aE…, contracts compiled with solc 0.8.28+commit.7893614a.Emscripten.clang.
|
||||
Last run: 2026-10-08 17:45 UTC on igneum-devnet-4 (chain id 4465), run id ra-20261008T1744-evm. 22 passed, 0 failed, 0 untested. Sender 0x27C433aE…, contracts compiled with solc 0.8.28+commit.7893614a.Emscripten.clang.
|
||||
|
||||
Three boundaries hold for everything on this page: proven execution is not finality; EVM compatibility is not Ethereum security; ZK is not privacy. The four words included, executed, proven and finalised are defined on [/receipt](/receipt).
|
||||
|
||||
## Representative contracts
|
||||
## Representative contracts (register case EVM-05)
|
||||
|
||||
| Row | Verdict | What was measured | Evidence |
|
||||
|---|---|---|---|
|
||||
| an ERC-20 deploys (CREATE address as Ethereum computes it, code at the address) | **passed** | at 0xb2495fd85f54d73d7a13059a8e61956b67ad7aed, block 739, gas 436751 of 639078 estimated | tx 0x8fd280cb…a5b9, address 0xb2495fd85f54d73d7a13059a8e61956b67ad7aed, block 739, gasUsed 436751, estimated 639078 |
|
||||
| ERC-20 transfer: balances move, the Transfer log decodes, eth_call reads the new balance | **passed** | 5 CTT to 0x00000000, log decoded, balance read | tx 0xe787770a…25fb, block 742 |
|
||||
| ERC-20 approve then transferFrom by a spender (the sender approves itself as spender): allowance consumed, logs decode | **passed** | allowance 3 then 1 after transferFrom of 2 | approve 0xfc7a3a64…5d24, transferFrom 0x6c0a22dc…ef22 |
|
||||
| a probe contract deploys (counter, block context reader, revert, out-of-gas loop, CREATE2) | **passed** | at 0x3efc60794d574627eb5cb4eca77d96735dac4c42 | tx 0x551c2403…8e15, address 0x3efc60794d574627eb5cb4eca77d96735dac4c42, block 751 |
|
||||
| a counter increments twice and reads 2 (state persists across chain blocks) | **passed** | count 2 after blocks 753 and 755 | first 0xfaf85576…75a1, second 0x97ca4151…19c8 |
|
||||
| an ERC-20 deploys (CREATE address as Ethereum computes it, code at the address) | **passed** | at 0xd93f5e2091ccd544757a38ecf5e4fa176c141b62, block 3016, gas 436751 of 639078 estimated | tx 0x314c059b…a679, address 0xd93f5e2091ccd544757a38ecf5e4fa176c141b62, block 3016, gasUsed 436751, estimated 639078 |
|
||||
| ERC-20 transfer: balances move, the Transfer log decodes, eth_call reads the new balance | **passed** | 5 CTT to 0x00000000, log decoded, balance read | tx 0xd8dbd034…15ce, block 3018 |
|
||||
| ERC-20 approve then transferFrom by a spender (the sender approves itself as spender): allowance consumed, logs decode | **passed** | allowance 3 then 1 after transferFrom of 2 | approve 0x570bbe86…52c8, transferFrom 0xe6031b34…cd5f |
|
||||
| a probe contract deploys (counter, block context reader, revert, out-of-gas loop, CREATE2) | **passed** | at 0xc4de4cf5766650a5c029fa908e3eb9270a19ed7d | tx 0x97e39c81…bdfa, address 0xc4de4cf5766650a5c029fa908e3eb9270a19ed7d, block 3026 |
|
||||
| a counter increments twice and reads 2 (state persists across chain blocks) | **passed** | count 2 after blocks 3029 and 3032 | first 0x1771f03c…cd3a, second 0xad3f6594…c013 |
|
||||
|
||||
## Wallet fee estimation
|
||||
## Transaction binding and replay (register case EVM-02)
|
||||
|
||||
| Row | Verdict | What was measured | Evidence |
|
||||
|---|---|---|---|
|
||||
| a transaction signed for another chain id (the previous devnet's 4464) is refused by the node | **passed** | refused: wrong chain id: expected 4465, got Some(4464) | chain_id_signed 4464 |
|
||||
| the same signed transaction sent twice: the second send is refused (nonce already used) | **passed** | first send mined in block 3049; the replay refused: nonce too low: account nonce is 40, transaction has 39 | tx 0xb1722ee0…a36f, block 3049, nonce_after 40 |
|
||||
|
||||
## Wallet fee estimation (register case EVM-03)
|
||||
|
||||
| Row | Verdict | What was measured | Evidence |
|
||||
|---|---|---|---|
|
||||
| eth_gasPrice, eth_maxPriorityFeePerGas and eth_feeHistory answer in Ethereum's shapes | **passed** | gasPrice 196.130804856 gwei, priority 1 gwei, feeHistory 5 base fees | gasPrice 0x2daa4e9478, maxPriorityFeePerGas 0x3b9aca00 |
|
||||
| a plain transfer: eth_estimateGas against the receipt's gasUsed (the quote folds proving gas; both above Ethereum's 21,000) | **passed** | estimated 59650, used 21000 (35% of the estimate); Ethereum's figure is 21,000 | tx 0x99c4dc1a…cad0, estimated 59650, gasUsed 21000, ethereum 21000 |
|
||||
| a contract call: eth_estimateGas against gasUsed (a wallet that quotes from the node is covered) | **passed** | estimated 134366, used 26371 | tx 0xeb8bafa3…bee4, estimated 134366, gasUsed 26371 |
|
||||
| the documented difference: a transfer sent with a local 21,000 gas limit (Ethereum's intrinsic cost) instead of the node's quote | **passed** | the node accepted it and it succeeded with gasUsed 21000: a wallet with a hard-coded 21,000 works | sent true, hash 0x538fdf72…b121, status success, gasUsed 21000 |
|
||||
| a plain transfer: eth_estimateGas against the receipt's gasUsed (the quote folds proving gas; both above Ethereum's 21,000) | **passed** | estimated 59650, used 21000 (35% of the estimate); Ethereum's figure is 21,000 | tx 0x6e67cf09…c795, estimated 59650, gasUsed 21000, ethereum 21000 |
|
||||
| a contract call: eth_estimateGas against gasUsed (a wallet that quotes from the node is covered) | **passed** | estimated 134366, used 26371 | tx 0xc14d3a76…31c6, estimated 134366, gasUsed 26371 |
|
||||
| the documented difference: a transfer sent with a local 21,000 gas limit (Ethereum's intrinsic cost) instead of the node's quote | **passed** | the node accepted it and it succeeded with gasUsed 21000: a wallet with a hard-coded 21,000 works | sent true, hash 0x1581f608…2c32, status success, gasUsed 21000 |
|
||||
|
||||
## Indexing
|
||||
## Indexing (register case EVM-06)
|
||||
|
||||
| Row | Verdict | What was measured | Evidence |
|
||||
|---|---|---|---|
|
||||
| eth_getLogs by address, by topic and by block range returns the receipts' logs with consistent logIndex and transactionIndex | **passed** | 4 logs by address, 3 Transfer logs by topic, each found in its receipt | byAddress 4, byTopic 3, fromBlock 739 |
|
||||
| eth_getBlockByNumber with full transactions, eth_getBlockReceipts and eth_getTransactionByHash agree on indices and hashes | **passed** | block 742: 1 transactions, indices 0 to 0 continuous | block 742, count 1 |
|
||||
| eth_getLogs by address, by topic and by block range returns the receipts' logs with consistent logIndex and transactionIndex | **passed** | 4 logs by address, 3 Transfer logs by topic, each found in its receipt | byAddress 4, byTopic 3, fromBlock 3016 |
|
||||
| eth_getBlockByNumber with full transactions, eth_getBlockReceipts and eth_getTransactionByHash agree on indices and hashes | **passed** | block 3018: 1 transactions, indices 0 to 0 continuous | block 3018, count 1 |
|
||||
|
||||
## Failed transactions
|
||||
## Failed transactions (register case EVM-05)
|
||||
|
||||
| Row | Verdict | What was measured | Evidence |
|
||||
|---|---|---|---|
|
||||
| a revert with a reason: eth_call returns the reason, the sent transaction has status 0, gas is charged, the nonce advances | **passed** | eth_call answers code 3 "execution reverted" with Error(string) data decoding to "compat says no"; the sent transaction: status 0, gasUsed 22292 of 200000, nonce 23 to 24 | tx 0xfcdf8d24…6a1e, gasUsed 22292, block 762, call_error_code 3, call_error_message execution reverted, revert_data 0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000e636f6d7061742073617973206e6f000000000000000000000000000000000000 |
|
||||
| an out-of-gas call: status 0 and the whole limit charged | **passed** | status 0, gasUsed 150000 of the 150000 limit | tx 0xb3986b45…a1f6, gasUsed 150000, limit 150000 |
|
||||
| a revert with a reason: eth_call returns the reason, the sent transaction has status 0, gas is charged, the nonce advances | **passed** | eth_call answers code 3 "execution reverted" with Error(string) data decoding to "compat says no"; the sent transaction: status 0, gasUsed 22292 of 200000, nonce 37 to 38 | tx 0x90e50327…1344, gasUsed 22292, block 3044, call_error_code 3, call_error_message execution reverted, revert_data 0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000e636f6d7061742073617973206e6f000000000000000000000000000000000000 |
|
||||
| an out-of-gas call: status 0 and the whole limit charged | **passed** | status 0, gasUsed 150000 of the 150000 limit | tx 0x4d138920…e5f0, gasUsed 150000, limit 150000 |
|
||||
|
||||
## Receipts
|
||||
## Receipts (register case EVM-06)
|
||||
|
||||
| Row | Verdict | What was measured | Evidence |
|
||||
|---|---|---|---|
|
||||
| a receipt carries every Ethereum field, logsBloom recomputes from its logs, contractAddress is set on creation | **passed** | 15 fields, bloom recomputed over 1 log(s), contractAddress 0xb2495fd8 | tx 0x8fd280cb…a5b9 |
|
||||
| the block's receipts rebuild its receipts trie root (Ethereum's layout, the node's encoding) equal to the header's receiptsRoot | **passed** | block 742, 1 receipts, root 0xa28061003c4c | block 742, receipts 1, receiptsRoot 0xa2806100…ac55 |
|
||||
| a receipt carries every Ethereum field, logsBloom recomputes from its logs, contractAddress is set on creation | **passed** | 15 fields, bloom recomputed over 1 log(s), contractAddress 0xd93f5e20 | tx 0x314c059b…a679 |
|
||||
| the block's receipts rebuild its receipts trie root (Ethereum's layout, the node's encoding) equal to the header's receiptsRoot | **passed** | block 3018, 1 receipts, root 0xc443c3e57c60 | block 3018, receipts 1, receiptsRoot 0xc443c3e5…8836 |
|
||||
|
||||
## Application assumptions
|
||||
## Application assumptions (register case EVM-04)
|
||||
|
||||
| Row | Verdict | What was measured | Evidence |
|
||||
|---|---|---|---|
|
||||
| block.number, timestamp, chainid, basefee and blockhash(number-1) read from a contract match the block the call executed in | **passed** | block 768: number, timestamp, chainid 4465, basefee, blockhash(n-1) = parentHash, msg.sender and tx.origin all match | tx 0x3c1d2dff…4fcd, block 768 |
|
||||
| CREATE2 lands at the address Ethereum computes (keccak(0xff, deployer, salt, keccak(initcode))) | **passed** | child at 0xE63036B0fEC0d01321Ef4DA62C084d1Ec2eA47be | tx 0x11cd9873…a80c, address 0xE63036B0fEC0d01321Ef4DA62C084d1Ec2eA47be |
|
||||
| block.number, timestamp, chainid, basefee and blockhash(number-1) read from a contract match the block the call executed in | **passed** | block 3053: number, timestamp, chainid 4465, basefee, blockhash(n-1) = parentHash, msg.sender and tx.origin all match | tx 0x186def3b…a228, block 3053 |
|
||||
| CREATE2 lands at the address Ethereum computes (keccak(0xff, deployer, salt, keccak(initcode))) | **passed** | child at 0xe3bC69915FB7318236c5ff31EF679aF6ae5b8699 | tx 0x442569b2…af11, address 0xe3bC69915FB7318236c5ff31EF679aF6ae5b8699 |
|
||||
|
||||
## Differences: block context
|
||||
## Differences: block context (register case EVM-04)
|
||||
|
||||
| Row | Verdict | What was measured | Evidence |
|
||||
|---|---|---|---|
|
||||
| block.coinbase is the miner of the DAG block that first included the transaction, not one miner per chain block (measured: coinbase against the block's igneum.mergeset) | **passed** | coinbase 0xc119093F = the including block's miner 0xc119093f; the chain block merged 2 block(s) with 1 distinct miner(s), chain block miner 0xc119093f | tx 0x3c1d2dff…4fcd, coinbase 0xc119093F38E3764Fdd86ea9635b7f616DEC6C3A6, includingMiner 0xc119093f38e3764fdd86ea9635b7f616dec6c3a6, chainBlockMiner 0xc119093f38e3764fdd86ea9635b7f616dec6c3a6 |
|
||||
| block.coinbase is the miner of the DAG block that first included the transaction, not one miner per chain block (measured: coinbase against the block's igneum.mergeset) | **passed** | coinbase 0x1450a9d8 = the including block's miner 0x1450a9d8; the chain block merged 1 block(s) with 1 distinct miner(s), chain block miner 0x1450a9d8 | tx 0x186def3b…a228, coinbase 0x1450a9d804D29084d34b93afB001dE807Aa9920d, includingMiner 0x1450a9d804d29084d34b93afb001de807aa9920d, chainBlockMiner 0x1450a9d804d29084d34b93afb001de807aa9920d |
|
||||
|
||||
## Differences: randomness
|
||||
## Differences: randomness (register case EVM-04)
|
||||
|
||||
| Row | Verdict | What was measured | Evidence |
|
||||
|---|---|---|---|
|
||||
| block.prevrandao: its value is derived from the chain's epoch seed (not Ethereum's beacon RANDAO); measured across consecutive blocks, and from a contract when a sender is funded | **passed** | blocks 767 to 770: 1 distinct epoch seed(s), 4 distinct mixHash value(s) in the headers; the source is the chain's epoch seed, which holds for an epoch, so prevrandao is not fresh per block and must not seed a lottery; a contract reading it twice in one call got the same value, and at block 768 it read 0x9cf17fa10c95… | |
|
||||
| block.prevrandao: its value is derived from the chain's epoch seed (not Ethereum's beacon RANDAO); measured across consecutive blocks, and from a contract when a sender is funded | **passed** | blocks 3051 to 3054: 1 distinct epoch seed(s), 4 distinct mixHash value(s) in the headers; the source is the chain's epoch seed, which holds for an epoch, so prevrandao is not fresh per block and must not seed a lottery; a contract reading it twice in one call got the same value, and at block 3053 it read 0x3b9abd95a495… | |
|
||||
|
||||
## Differences: two-dimensional fees
|
||||
## Differences: two-dimensional fees (register case EVM-03)
|
||||
|
||||
| Row | Verdict | What was measured | Evidence |
|
||||
|---|---|---|---|
|
||||
| a receipt carries pgasUsed, provingBaseFeePerGas, burnedProvingFee and burnedExecutionBaseFee; effectiveGasPrice covers both dimensions | **passed** | gasUsed 51375, pgasUsed 1968, proving base fee 10000 gwei per pgas; paid 5188875000000000 wei, of which proving burn 19680000000000000, execution burn 5137500000000000, tip 41100000000000 (parts sum differs from gasUsed × effectiveGasPrice) | tx 0xe787770a…25fb, gasUsed 51375, pgasUsed 1968, effectiveGasPrice 0x178411b200, parts_equal_paid false |
|
||||
| a receipt carries pgasUsed, provingBaseFeePerGas, burnedProvingFee and burnedExecutionBaseFee; effectiveGasPrice covers both dimensions | **passed** | gasUsed 51375, pgasUsed 1968, proving base fee 10000 gwei per pgas; paid 5188875000000000 wei, of which proving burn 19680000000000000, execution burn 5137500000000000, tip 41100000000000 (parts sum differs from gasUsed × effectiveGasPrice) | tx 0xd8dbd034…15ce, gasUsed 51375, pgasUsed 1968, effectiveGasPrice 0x178411b200, parts_equal_paid false |
|
||||
|
||||
## What the differences mean for an application
|
||||
|
||||
|
|
|
|||
|
|
@ -56,10 +56,40 @@
|
|||
"evm_chain_id": 4465,
|
||||
"deployer": "0x70e692A9f1fa1067a8c2d64fDAf1636b4EAEC7e2",
|
||||
"deployed_at": "2026-10-08T17:2xZ (build-4; build-3 down from 15:40Z with the first deployer key on its disk)",
|
||||
"table": "not installed yet: devnet-4's voter table is read from igneum_getFinalityWeights at the chain's first finality lock (the 7,200-DAA window filling at about 15 DAA a minute from 2,626 at 16:5xZ, so about 22:00Z) and installed through contracts/bridge/script/Install.s.sol",
|
||||
"final_checkpoints": "none yet",
|
||||
"table": {
|
||||
"tx": "0xc2568a7a57da59fc3564ee277594c3401503755762e7f7cb0b786dd3bb1fb61e",
|
||||
"block": 11871867,
|
||||
"index": 242,
|
||||
"voters": 38,
|
||||
"total_weight": 7151,
|
||||
"table_id": "0x8c306bfb25e361f8b78fab5318aa493220bb629b63bc025cb8f180198d577bea",
|
||||
"read_from": "the certificate at /api/checkpoint?source=dn4&index=242 (the voter table frozen at checkpoint 241, the chain's first lock, 18:08:25Z 8 October 2026)",
|
||||
"gas_used": 22762323
|
||||
},
|
||||
"final_checkpoints": [
|
||||
{
|
||||
"index": 241,
|
||||
"checkpoint": "0xef2d953a0ca9da68ef571a36b87a53085474615cca3555fd94ee0380da341fee",
|
||||
"tx": "0x2102dae696c75430650d4419d2c9afda7ec1390e4a8bb5158bdb358a921abdee",
|
||||
"block": 11871871,
|
||||
"gas_used": 1019007,
|
||||
"signers": 35,
|
||||
"signed_weight_under_table": 7116,
|
||||
"total_weight": 7151
|
||||
},
|
||||
{
|
||||
"index": 242,
|
||||
"checkpoint": "0xe4263cccd151e7da1860061f5217e64abc222aaeb7bc4f0c8830654e2d1f66a9",
|
||||
"tx": "0x61b5d581d7c94121b9ae86e9f87a068cbba49796559121c51ccd0cc948ac86e6",
|
||||
"block": 11871868,
|
||||
"gas_used": 828823,
|
||||
"signers": 21,
|
||||
"signed_weight_under_table": 4910,
|
||||
"total_weight": 7151
|
||||
}
|
||||
],
|
||||
"shared_with": "the reference-apps lane's IgneumStateOracle for devnet-4, 0xbb3450049926da3572e6b67cb94df312fe349e34 (setVerifier)",
|
||||
"note": "Igneum 2.0 (8 October 2026, 17:45 BST): Devnet 3 switched off, igneum-devnet-4 is the 2.0 devnet; the Devnet 3 verifier above keeps its recorded checkpoint and account proof as the record"
|
||||
"note": "Igneum 2.0 (8 October 2026): igneum-devnet-4 is the 2.0 devnet; its first finality lock formed at 18:08:25Z (checkpoint 241); the certificates come from the devnet-4 observer through /api/checkpoint?source=dn4&index=N, the network string checked as igneum-devnet-4 before any send (the API falls back to a test fixture while a prefix is empty)"
|
||||
}
|
||||
},
|
||||
"first_deploy_note": "A first creation at 0xD7dd375E14F92A4CE4782040325189e6d6E394b6 (tx 0x4db10565\u2026, block 11869633) ran out of gas at Foundry's Prague-spec estimate of 3,323,884; Sepolia runs Osaka pricing (EIP-7883 modexp), so the test EVM and the deploy now use osaka and the RPC's own estimate. That address holds no code.",
|
||||
|
|
|
|||
|
|
@ -805,10 +805,10 @@
|
|||
"owner": "Cryptography + GPU lead",
|
||||
"manual_page": 25,
|
||||
"owner_lane": "pool design seat (a3832b1c3b274b310)",
|
||||
"run_status": "RUNNING",
|
||||
"evidence_path": "docs/analysis/binding-review-2026-10.md",
|
||||
"run_id": "team-2026-10-08",
|
||||
"updated": "2026-10-08 18:3x UK",
|
||||
"run_status": "REVIEWED: fixed by construction (binding), not applicable (final digest); native tests ok on build-2; no change for 2.0",
|
||||
"evidence_path": "docs/analysis/binding-review-2026-10.md (sections 1 to 5a; master ad5a54c5)",
|
||||
"run_id": "binding-review-2026-10-08-a05",
|
||||
"updated": "2026-10-08 18:13Z",
|
||||
"evidence_record": {
|
||||
"what_was_run": "the binding review: twelve reuse paths, none below the honest cost; five open questions B1 to B5",
|
||||
"run_by": "pool design seat (a3832b1c3b274b310)",
|
||||
|
|
@ -3980,10 +3980,10 @@
|
|||
"owner": "Desktop product + pool leads; independent usability study",
|
||||
"manual_page": 57,
|
||||
"owner_lane": "shipper (ae892a8b0f78fe31c)",
|
||||
"run_status": "NOT RUN",
|
||||
"evidence_path": "",
|
||||
"run_id": "",
|
||||
"updated": "2026-10-08 18:3x UK"
|
||||
"run_status": "RUNNING",
|
||||
"evidence_path": "docs/release/evidence/ux-shipper-2026-10-08.md",
|
||||
"run_id": "200-mini-2026-10-08",
|
||||
"updated": "2026-10-08 19:1x BST"
|
||||
},
|
||||
{
|
||||
"id": "UX-03",
|
||||
|
|
@ -4012,9 +4012,9 @@
|
|||
"manual_page": 57,
|
||||
"owner_lane": "shipper (ae892a8b0f78fe31c)",
|
||||
"run_status": "RUNNING",
|
||||
"evidence_path": "docs/design/app-audit-2026-10-08.md",
|
||||
"run_id": "team-2026-10-08",
|
||||
"updated": "2026-10-08 18:3x UK",
|
||||
"evidence_path": "docs/release/evidence/ux-shipper-2026-10-08.md",
|
||||
"run_id": "201-2ea7b43f",
|
||||
"updated": "2026-10-08 19:1x BST",
|
||||
"evidence_record": {
|
||||
"what_was_run": "the 16 GB proving line and the dev fee in v2.0.0; the three income streams net of tariff owed (v2.0.1)",
|
||||
"run_by": "shipper (ae892a8b0f78fe31c)",
|
||||
|
|
@ -4117,9 +4117,9 @@
|
|||
"manual_page": 58,
|
||||
"owner_lane": "shipper (ae892a8b0f78fe31c)",
|
||||
"run_status": "NOT RUN",
|
||||
"evidence_path": "",
|
||||
"run_id": "",
|
||||
"updated": "2026-10-08 18:3x UK"
|
||||
"evidence_path": "docs/release/evidence/ux-shipper-2026-10-08.md",
|
||||
"run_id": "pending-mode-c-0130",
|
||||
"updated": "2026-10-08 19:1x BST"
|
||||
},
|
||||
{
|
||||
"id": "UX-07",
|
||||
|
|
@ -4148,9 +4148,9 @@
|
|||
"manual_page": 59,
|
||||
"owner_lane": "shipper (ae892a8b0f78fe31c)",
|
||||
"run_status": "RUNNING",
|
||||
"evidence_path": "docs/design/app-audit-2026-10-08.md",
|
||||
"run_id": "team-2026-10-08",
|
||||
"updated": "2026-10-08 18:3x UK",
|
||||
"evidence_path": "docs/release/evidence/ux-shipper-2026-10-08.md",
|
||||
"run_id": "200-updates-2026-10-08",
|
||||
"updated": "2026-10-08 19:1x BST",
|
||||
"evidence_record": {
|
||||
"what_was_run": "the restart-kind fix (da212ee2) and the update-return classes; explicit update acceptance owed (v2.0.1)",
|
||||
"run_by": "shipper (ae892a8b0f78fe31c)",
|
||||
|
|
@ -5060,4 +5060,4 @@
|
|||
"run_id": "the run that produced the latest status",
|
||||
"updated": "the minute the lane last wrote the case"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
22
docs/release/evidence/ux-shipper-2026-10-08.md
Normal file
22
docs/release/evidence/ux-shipper-2026-10-08.md
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# UX evidence record, the shipper's cases (8 October 2026)
|
||||
|
||||
Registry: docs/plans/igneum-2.0-test-registry.json, suite UX. Owner lane: the shipper. Every time is UK time on the Mac's clock. Each case carries its run id, what ran, the read-backs verbatim, and what is still to run.
|
||||
|
||||
## UX-02 Make pause, stop and safe tuning reliable (run 200-mini-2026-10-08, RUNNING)
|
||||
- Pause and resume through the app's own api on the founder's Mac mini (Apple M6, Igneum Miner 2.0.0, the Igneum 2.0 devnet): api/pause at 18:19:33 held the miner (the node stayed up, synced, 4 peers); api/resume at 18:20:2x brought the worker back ("seed mismatch: the worker holds another program; preparing the current pair", then mining); the status line after: "accepted 4 blocks (3 this run), mining | node 4246 blocks, 4 peers, synced".
|
||||
- UI crash or restart while workers run: the window host outlived the engine after an api/quit (18:16:13: one "Igneum Miner" process, no engine); a plain reopen fronted the dead shell; the app's own quit then a fresh open relaunched clean (host 6177, engine 6181 at 18:16:43). Finding for 2.0.2: the window host must exit with its engine.
|
||||
- Still to run: the power limit and task selection controls under contention, the emergency local shutdown, the restore of hardware settings (PC 1 and PC 2 on v2.0.1 tonight, the Tune page).
|
||||
|
||||
## UX-03 Show net earnings and compatibility honestly (run 201-2ea7b43f, RUNNING)
|
||||
- v2.0.1 (release-2.0.1 2ea7b43f, the window lane's cards-201 7f0f6796): the Cards tab back as its own page with every card row (state, MH/s, W, degrees C, the tune state, the switch, the 16 GB proving note on an NVIDIA card under 16 GB); the first-block card once per payout address (settings first_block_shown[address], never on a dev-fee block); captures at the window lane's ~/Desktop/igneum-previews-2026-10-08/cards-201/ (to be copied beside this record).
|
||||
- Rule 25 in the window (aa354ed5): no wei value in a JavaScript Number; the IGN figure cut from the engine's decimal string.
|
||||
- Still to run: the earnings figures against the chain's ledger (hub-1's coinbase records against the Earnings card on one rig), stale data and negative margins on the v2.0.1 canary.
|
||||
|
||||
## UX-06 Verify actual miner-selected work templates (run pending, NOT RUN)
|
||||
- The pool design seat's mode C run at 01:30 BST on 9 October; evidence under scratchpad/registry/UX-06/<run id>/ on the founder's Mac, then copied here; the line by 02:00.
|
||||
|
||||
## UX-07 Expose actionable failures and safe updates (run 200-updates-2026-10-08, RUNNING)
|
||||
- Safe updates over a running older app (release rule 14): the Mac, 2.0.0 over 0.3.26 by the engine's own helper at 17:38:39, result {"ok":true,"version":"2.0.0"}, installed 2.0.0 at 17:41:04; finding: the 0.3.26 node outlived the quit and held port 26611 ("Node not started: port 26611 is taken by a node on another network"), cleared by stopping it by pid (v2.0.2: the helper stops the previous bundle's node by pid). PC 1 and PC 2: the Windows 2.0.0 entry live 18:44:04 (Setup exe 793a631d); the relay runs #1724/#1723 read "MINING-ON" with no click (the update-return lane's UX-01 line).
|
||||
- Version visibility and the unsigned build: the Mac download page and /miner carry the first-open two-step (site commit 6a81aa70, at the edge 18:24); the DMG README step 2 and the release note say the build is unsigned tonight (aa354ed5).
|
||||
- Actionable failures: the watchdog's message when the node serves no epoch state stream was the wrong cause ("the worker did not load its program") on 2.0.0 (the founder's mini, 18:0x); 2.0.1 names it ("waiting for the node's execution state for this epoch"). The root cause (every node on 4cdcc488 dropped the genesis stream at block 1) is the node lane's 5713d547.
|
||||
- Still to run: a failed or corrupt update (a wrong sha in the manifest against a running 2.0.1 app), explicit update approval (v2.0.2), the diagnostic export, on PC 2 tonight.
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -37,7 +37,12 @@ const liveNetwork = () => process.env.LIVE_NETWORK || (/^dn(\d+)_$/.test(tablePr
|
|||
// the finality test network's fixture (fintest_live_certificates) is served only to a request carrying the ops key (main, 8 Oct 2026 18:4x:
|
||||
// a fixture chain answered on the public 2.0 site as source test, network igneum-devnet-7); with no IGNEUM_OPS_KEY set it is never served
|
||||
const opsOk = req => { const k = process.env.IGNEUM_OPS_KEY || ''; const h = String((req.headers && req.headers['x-igneum-ops-key']) || ''); return k.length > 0 && h === k; };
|
||||
const noCertificate = source => ({ source, network: liveNetwork(), certificate: null, reason: 'no finality certificate yet; the first lock is expected about 23:00 BST' });
|
||||
// the latest DAA the observer has seen on the live chain, or null (the window fills to DAA 7,200 before the first lock; no wall-clock estimate, main 8 Oct 2026)
|
||||
async function liveDaa(sql) {
|
||||
const rows = await sql(`SELECT max(daa_score) AS daa FROM ${tablePrefix()}live_blocks`).catch(() => []);
|
||||
const d = rows && rows[0] && rows[0].daa; return d === null || d === undefined ? null : Number(d);
|
||||
}
|
||||
const noCertificate = (source, daa) => ({ source, network: liveNetwork(), certificate: null, live_daa: daa, finality_window_daa: 7200, reason: 'no finality certificate yet; the first lock comes when the weight window fills at DAA 7,200' });
|
||||
async function latest(sql, table, index = null) {
|
||||
// A table the observer has not created yet (the live chain before the cut-over) reads as "no certificate"
|
||||
const rows = await (index === null ? sql(`SELECT * FROM ${table} ORDER BY index DESC LIMIT 1`) : sql(`SELECT * FROM ${table} WHERE index = $1 LIMIT 1`, [index])).catch(() => []);
|
||||
|
|
@ -134,7 +139,7 @@ export default async function handler(req, res) {
|
|||
if (!row) {
|
||||
res.setHeader('Cache-Control', 'public, max-age=5');
|
||||
if (idx !== null) return res.status(404).json({ ok: false, network: liveNetwork(), error: `no certified checkpoint at index ${idx} yet` });
|
||||
return res.status(200).json({ ok: true, now: new Date().toISOString(), ...noCertificate(source) });
|
||||
return res.status(200).json({ ok: true, now: new Date().toISOString(), ...noCertificate(source, await liveDaa(sql)) });
|
||||
}
|
||||
// the hand merge of 12:22 BST (a0b62cf7) returned `...cp` with no cp bound: every caller read "cp is not defined" (8 Oct 2026, build-server lane)
|
||||
return res.status(200).json({ ok: true, now: new Date().toISOString(), ...shape(row, source) });
|
||||
|
|
|
|||
|
|
@ -248,38 +248,41 @@ table{min-width:560px}
|
|||
<section class="section compact"><div class="container">
|
||||
|
||||
<div class="docs-layout">
|
||||
<nav class="doc-nav" aria-label="Contents"><div class="eyebrow">Contents</div><a href="#representative-contracts">Representative contracts</a><a href="#wallet-fee-estimation">Wallet fee estimation</a><a href="#indexing">Indexing</a><a href="#failed-transactions">Failed transactions</a><a href="#receipts">Receipts</a><a href="#application-assumptions">Application assumptions</a><a href="#differences-block-context">Differences: block context</a><a href="#differences-randomness">Differences: randomness</a><a href="#differences-two-dimensional-fees">Differences: two-dimensional fees</a><a href="#what-the-differences-mean-for-an-application">What the differences mean for an application</a></nav>
|
||||
<nav class="doc-nav" aria-label="Contents"><div class="eyebrow">Contents</div><a href="#representative-contracts-register-case-evm-05">Representative contracts (register case EVM-05)</a><a href="#transaction-binding-and-replay-register-case-evm-02">Transaction binding and replay (register case EVM-02)</a><a href="#wallet-fee-estimation-register-case-evm-03">Wallet fee estimation (register case EVM-03)</a><a href="#indexing-register-case-evm-06">Indexing (register case EVM-06)</a><a href="#failed-transactions-register-case-evm-05">Failed transactions (register case EVM-05)</a><a href="#receipts-register-case-evm-06">Receipts (register case EVM-06)</a><a href="#application-assumptions-register-case-evm-04">Application assumptions (register case EVM-04)</a><a href="#differences-block-context-register-case-evm-04">Differences: block context (register case EVM-04)</a><a href="#differences-randomness-register-case-evm-04">Differences: randomness (register case EVM-04)</a><a href="#differences-two-dimensional-fees-register-case-evm-03">Differences: two-dimensional fees (register case EVM-03)</a><a href="#what-the-differences-mean-for-an-application">What the differences mean for an application</a></nav>
|
||||
<article class="doc-body" data-filter-list="compatibility"><section class="doc-section"><h1 id="compatibility-measured">Compatibility, measured</h1>
|
||||
<p>A GPU-secured network for Ethereum-compatible applications and verifiable computation. Compatibility is a product deliverable here, not a sentence: every row below is a test that ran against the devnet from the repository (<code>tools/reference-apps/compat/run.mjs</code>), with its evidence, and a row that could not run says so and why. Devnet, no value.</p>
|
||||
<p>Last run: 2026-10-08 16:34 UTC on igneum-devnet-4 (chain id 4465). 20 passed, 0 failed, 0 untested. TEAM-REPORTED: run by the team, no outside reproduction yet. Sender 0x27C433aE…, contracts compiled with solc 0.8.28+commit.7893614a.Emscripten.clang.</p>
|
||||
<p>Last run: 2026-10-08 17:45 UTC on igneum-devnet-4 (chain id 4465), run id ra-20261008T1744-evm. 22 passed, 0 failed, 0 untested. Sender 0x27C433aE…, contracts compiled with solc 0.8.28+commit.7893614a.Emscripten.clang.</p>
|
||||
<p>Three boundaries hold for everything on this page: proven execution is not finality; EVM compatibility is not Ethereum security; ZK is not privacy. The four words included, executed, proven and finalised are defined on <a href="/receipt">/receipt</a>.</p>
|
||||
</section>
|
||||
<section class="doc-section"><h2 id="representative-contracts">Representative contracts</h2>
|
||||
<div class="tbl"><table><thead><tr><th>Row</th><th>Verdict</th><th>What was measured</th><th>Evidence</th></tr></thead><tbody><tr><td>an ERC-20 deploys (CREATE address as Ethereum computes it, code at the address)</td><td><strong>passed</strong></td><td>at 0xb2495fd85f54d73d7a13059a8e61956b67ad7aed, block 739, gas 436751 of 639078 estimated</td><td>tx 0x8fd280cb…a5b9, address 0xb2495fd85f54d73d7a13059a8e61956b67ad7aed, block 739, gasUsed 436751, estimated 639078</td></tr><tr><td>ERC-20 transfer: balances move, the Transfer log decodes, eth_call reads the new balance</td><td><strong>passed</strong></td><td>5 CTT to 0x00000000, log decoded, balance read</td><td>tx 0xe787770a…25fb, block 742</td></tr><tr><td>ERC-20 approve then transferFrom by a spender (the sender approves itself as spender): allowance consumed, logs decode</td><td><strong>passed</strong></td><td>allowance 3 then 1 after transferFrom of 2</td><td>approve 0xfc7a3a64…5d24, transferFrom 0x6c0a22dc…ef22</td></tr><tr><td>a probe contract deploys (counter, block context reader, revert, out-of-gas loop, CREATE2)</td><td><strong>passed</strong></td><td>at 0x3efc60794d574627eb5cb4eca77d96735dac4c42</td><td>tx 0x551c2403…8e15, address 0x3efc60794d574627eb5cb4eca77d96735dac4c42, block 751</td></tr><tr><td>a counter increments twice and reads 2 (state persists across chain blocks)</td><td><strong>passed</strong></td><td>count 2 after blocks 753 and 755</td><td>first 0xfaf85576…75a1, second 0x97ca4151…19c8</td></tr></tbody></table></div>
|
||||
<section class="doc-section"><h2 id="representative-contracts-register-case-evm-05">Representative contracts (register case EVM-05)</h2>
|
||||
<div class="tbl"><table><thead><tr><th>Row</th><th>Verdict</th><th>What was measured</th><th>Evidence</th></tr></thead><tbody><tr><td>an ERC-20 deploys (CREATE address as Ethereum computes it, code at the address)</td><td><strong>passed</strong></td><td>at 0xd93f5e2091ccd544757a38ecf5e4fa176c141b62, block 3016, gas 436751 of 639078 estimated</td><td>tx 0x314c059b…a679, address 0xd93f5e2091ccd544757a38ecf5e4fa176c141b62, block 3016, gasUsed 436751, estimated 639078</td></tr><tr><td>ERC-20 transfer: balances move, the Transfer log decodes, eth_call reads the new balance</td><td><strong>passed</strong></td><td>5 CTT to 0x00000000, log decoded, balance read</td><td>tx 0xd8dbd034…15ce, block 3018</td></tr><tr><td>ERC-20 approve then transferFrom by a spender (the sender approves itself as spender): allowance consumed, logs decode</td><td><strong>passed</strong></td><td>allowance 3 then 1 after transferFrom of 2</td><td>approve 0x570bbe86…52c8, transferFrom 0xe6031b34…cd5f</td></tr><tr><td>a probe contract deploys (counter, block context reader, revert, out-of-gas loop, CREATE2)</td><td><strong>passed</strong></td><td>at 0xc4de4cf5766650a5c029fa908e3eb9270a19ed7d</td><td>tx 0x97e39c81…bdfa, address 0xc4de4cf5766650a5c029fa908e3eb9270a19ed7d, block 3026</td></tr><tr><td>a counter increments twice and reads 2 (state persists across chain blocks)</td><td><strong>passed</strong></td><td>count 2 after blocks 3029 and 3032</td><td>first 0x1771f03c…cd3a, second 0xad3f6594…c013</td></tr></tbody></table></div>
|
||||
</section>
|
||||
<section class="doc-section"><h2 id="wallet-fee-estimation">Wallet fee estimation</h2>
|
||||
<div class="tbl"><table><thead><tr><th>Row</th><th>Verdict</th><th>What was measured</th><th>Evidence</th></tr></thead><tbody><tr><td>eth_gasPrice, eth_maxPriorityFeePerGas and eth_feeHistory answer in Ethereum's shapes</td><td><strong>passed</strong></td><td>gasPrice 196.130804856 gwei, priority 1 gwei, feeHistory 5 base fees</td><td>gasPrice 0x2daa4e9478, maxPriorityFeePerGas 0x3b9aca00</td></tr><tr><td>a plain transfer: eth_estimateGas against the receipt's gasUsed (the quote folds proving gas; both above Ethereum's 21,000)</td><td><strong>passed</strong></td><td>estimated 59650, used 21000 (35% of the estimate); Ethereum's figure is 21,000</td><td>tx 0x99c4dc1a…cad0, estimated 59650, gasUsed 21000, ethereum 21000</td></tr><tr><td>a contract call: eth_estimateGas against gasUsed (a wallet that quotes from the node is covered)</td><td><strong>passed</strong></td><td>estimated 134366, used 26371</td><td>tx 0xeb8bafa3…bee4, estimated 134366, gasUsed 26371</td></tr><tr><td>the documented difference: a transfer sent with a local 21,000 gas limit (Ethereum's intrinsic cost) instead of the node's quote</td><td><strong>passed</strong></td><td>the node accepted it and it succeeded with gasUsed 21000: a wallet with a hard-coded 21,000 works</td><td>sent true, hash 0x538fdf72…b121, status success, gasUsed 21000</td></tr></tbody></table></div>
|
||||
<section class="doc-section"><h2 id="transaction-binding-and-replay-register-case-evm-02">Transaction binding and replay (register case EVM-02)</h2>
|
||||
<div class="tbl"><table><thead><tr><th>Row</th><th>Verdict</th><th>What was measured</th><th>Evidence</th></tr></thead><tbody><tr><td>a transaction signed for another chain id (the previous devnet's 4464) is refused by the node</td><td><strong>passed</strong></td><td>refused: wrong chain id: expected 4465, got Some(4464)</td><td>chain_id_signed 4464</td></tr><tr><td>the same signed transaction sent twice: the second send is refused (nonce already used)</td><td><strong>passed</strong></td><td>first send mined in block 3049; the replay refused: nonce too low: account nonce is 40, transaction has 39</td><td>tx 0xb1722ee0…a36f, block 3049, nonce_after 40</td></tr></tbody></table></div>
|
||||
</section>
|
||||
<section class="doc-section"><h2 id="indexing">Indexing</h2>
|
||||
<div class="tbl"><table><thead><tr><th>Row</th><th>Verdict</th><th>What was measured</th><th>Evidence</th></tr></thead><tbody><tr><td>eth_getLogs by address, by topic and by block range returns the receipts' logs with consistent logIndex and transactionIndex</td><td><strong>passed</strong></td><td>4 logs by address, 3 Transfer logs by topic, each found in its receipt</td><td>byAddress 4, byTopic 3, fromBlock 739</td></tr><tr><td>eth_getBlockByNumber with full transactions, eth_getBlockReceipts and eth_getTransactionByHash agree on indices and hashes</td><td><strong>passed</strong></td><td>block 742: 1 transactions, indices 0 to 0 continuous</td><td>block 742, count 1</td></tr></tbody></table></div>
|
||||
<section class="doc-section"><h2 id="wallet-fee-estimation-register-case-evm-03">Wallet fee estimation (register case EVM-03)</h2>
|
||||
<div class="tbl"><table><thead><tr><th>Row</th><th>Verdict</th><th>What was measured</th><th>Evidence</th></tr></thead><tbody><tr><td>eth_gasPrice, eth_maxPriorityFeePerGas and eth_feeHistory answer in Ethereum's shapes</td><td><strong>passed</strong></td><td>gasPrice 196.130804856 gwei, priority 1 gwei, feeHistory 5 base fees</td><td>gasPrice 0x2daa4e9478, maxPriorityFeePerGas 0x3b9aca00</td></tr><tr><td>a plain transfer: eth_estimateGas against the receipt's gasUsed (the quote folds proving gas; both above Ethereum's 21,000)</td><td><strong>passed</strong></td><td>estimated 59650, used 21000 (35% of the estimate); Ethereum's figure is 21,000</td><td>tx 0x6e67cf09…c795, estimated 59650, gasUsed 21000, ethereum 21000</td></tr><tr><td>a contract call: eth_estimateGas against gasUsed (a wallet that quotes from the node is covered)</td><td><strong>passed</strong></td><td>estimated 134366, used 26371</td><td>tx 0xc14d3a76…31c6, estimated 134366, gasUsed 26371</td></tr><tr><td>the documented difference: a transfer sent with a local 21,000 gas limit (Ethereum's intrinsic cost) instead of the node's quote</td><td><strong>passed</strong></td><td>the node accepted it and it succeeded with gasUsed 21000: a wallet with a hard-coded 21,000 works</td><td>sent true, hash 0x1581f608…2c32, status success, gasUsed 21000</td></tr></tbody></table></div>
|
||||
</section>
|
||||
<section class="doc-section"><h2 id="failed-transactions">Failed transactions</h2>
|
||||
<div class="tbl"><table><thead><tr><th>Row</th><th>Verdict</th><th>What was measured</th><th>Evidence</th></tr></thead><tbody><tr><td>a revert with a reason: eth_call returns the reason, the sent transaction has status 0, gas is charged, the nonce advances</td><td><strong>passed</strong></td><td>eth_call answers code 3 "execution reverted" with Error(string) data decoding to "compat says no"; the sent transaction: status 0, gasUsed 22292 of 200000, nonce 23 to 24</td><td>tx 0xfcdf8d24…6a1e, gasUsed 22292, block 762, call_error_code 3, call_error_message execution reverted, revert_data 0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000e636f6d7061742073617973206e6f000000000000000000000000000000000000</td></tr><tr><td>an out-of-gas call: status 0 and the whole limit charged</td><td><strong>passed</strong></td><td>status 0, gasUsed 150000 of the 150000 limit</td><td>tx 0xb3986b45…a1f6, gasUsed 150000, limit 150000</td></tr></tbody></table></div>
|
||||
<section class="doc-section"><h2 id="indexing-register-case-evm-06">Indexing (register case EVM-06)</h2>
|
||||
<div class="tbl"><table><thead><tr><th>Row</th><th>Verdict</th><th>What was measured</th><th>Evidence</th></tr></thead><tbody><tr><td>eth_getLogs by address, by topic and by block range returns the receipts' logs with consistent logIndex and transactionIndex</td><td><strong>passed</strong></td><td>4 logs by address, 3 Transfer logs by topic, each found in its receipt</td><td>byAddress 4, byTopic 3, fromBlock 3016</td></tr><tr><td>eth_getBlockByNumber with full transactions, eth_getBlockReceipts and eth_getTransactionByHash agree on indices and hashes</td><td><strong>passed</strong></td><td>block 3018: 1 transactions, indices 0 to 0 continuous</td><td>block 3018, count 1</td></tr></tbody></table></div>
|
||||
</section>
|
||||
<section class="doc-section"><h2 id="receipts">Receipts</h2>
|
||||
<div class="tbl"><table><thead><tr><th>Row</th><th>Verdict</th><th>What was measured</th><th>Evidence</th></tr></thead><tbody><tr><td>a receipt carries every Ethereum field, logsBloom recomputes from its logs, contractAddress is set on creation</td><td><strong>passed</strong></td><td>15 fields, bloom recomputed over 1 log(s), contractAddress 0xb2495fd8</td><td>tx 0x8fd280cb…a5b9</td></tr><tr><td>the block's receipts rebuild its receipts trie root (Ethereum's layout, the node's encoding) equal to the header's receiptsRoot</td><td><strong>passed</strong></td><td>block 742, 1 receipts, root 0xa28061003c4c</td><td>block 742, receipts 1, receiptsRoot 0xa2806100…ac55</td></tr></tbody></table></div>
|
||||
<section class="doc-section"><h2 id="failed-transactions-register-case-evm-05">Failed transactions (register case EVM-05)</h2>
|
||||
<div class="tbl"><table><thead><tr><th>Row</th><th>Verdict</th><th>What was measured</th><th>Evidence</th></tr></thead><tbody><tr><td>a revert with a reason: eth_call returns the reason, the sent transaction has status 0, gas is charged, the nonce advances</td><td><strong>passed</strong></td><td>eth_call answers code 3 "execution reverted" with Error(string) data decoding to "compat says no"; the sent transaction: status 0, gasUsed 22292 of 200000, nonce 37 to 38</td><td>tx 0x90e50327…1344, gasUsed 22292, block 3044, call_error_code 3, call_error_message execution reverted, revert_data 0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000e636f6d7061742073617973206e6f000000000000000000000000000000000000</td></tr><tr><td>an out-of-gas call: status 0 and the whole limit charged</td><td><strong>passed</strong></td><td>status 0, gasUsed 150000 of the 150000 limit</td><td>tx 0x4d138920…e5f0, gasUsed 150000, limit 150000</td></tr></tbody></table></div>
|
||||
</section>
|
||||
<section class="doc-section"><h2 id="application-assumptions">Application assumptions</h2>
|
||||
<div class="tbl"><table><thead><tr><th>Row</th><th>Verdict</th><th>What was measured</th><th>Evidence</th></tr></thead><tbody><tr><td>block.number, timestamp, chainid, basefee and blockhash(number-1) read from a contract match the block the call executed in</td><td><strong>passed</strong></td><td>block 768: number, timestamp, chainid 4465, basefee, blockhash(n-1) = parentHash, msg.sender and tx.origin all match</td><td>tx 0x3c1d2dff…4fcd, block 768</td></tr><tr><td>CREATE2 lands at the address Ethereum computes (keccak(0xff, deployer, salt, keccak(initcode)))</td><td><strong>passed</strong></td><td>child at 0xE63036B0fEC0d01321Ef4DA62C084d1Ec2eA47be</td><td>tx 0x11cd9873…a80c, address 0xE63036B0fEC0d01321Ef4DA62C084d1Ec2eA47be</td></tr></tbody></table></div>
|
||||
<section class="doc-section"><h2 id="receipts-register-case-evm-06">Receipts (register case EVM-06)</h2>
|
||||
<div class="tbl"><table><thead><tr><th>Row</th><th>Verdict</th><th>What was measured</th><th>Evidence</th></tr></thead><tbody><tr><td>a receipt carries every Ethereum field, logsBloom recomputes from its logs, contractAddress is set on creation</td><td><strong>passed</strong></td><td>15 fields, bloom recomputed over 1 log(s), contractAddress 0xd93f5e20</td><td>tx 0x314c059b…a679</td></tr><tr><td>the block's receipts rebuild its receipts trie root (Ethereum's layout, the node's encoding) equal to the header's receiptsRoot</td><td><strong>passed</strong></td><td>block 3018, 1 receipts, root 0xc443c3e57c60</td><td>block 3018, receipts 1, receiptsRoot 0xc443c3e5…8836</td></tr></tbody></table></div>
|
||||
</section>
|
||||
<section class="doc-section"><h2 id="differences-block-context">Differences: block context</h2>
|
||||
<div class="tbl"><table><thead><tr><th>Row</th><th>Verdict</th><th>What was measured</th><th>Evidence</th></tr></thead><tbody><tr><td>block.coinbase is the miner of the DAG block that first included the transaction, not one miner per chain block (measured: coinbase against the block's igneum.mergeset)</td><td><strong>passed</strong></td><td>coinbase 0xc119093F = the including block's miner 0xc119093f; the chain block merged 2 block(s) with 1 distinct miner(s), chain block miner 0xc119093f</td><td>tx 0x3c1d2dff…4fcd, coinbase 0xc119093F38E3764Fdd86ea9635b7f616DEC6C3A6, includingMiner 0xc119093f38e3764fdd86ea9635b7f616dec6c3a6, chainBlockMiner 0xc119093f38e3764fdd86ea9635b7f616dec6c3a6</td></tr></tbody></table></div>
|
||||
<section class="doc-section"><h2 id="application-assumptions-register-case-evm-04">Application assumptions (register case EVM-04)</h2>
|
||||
<div class="tbl"><table><thead><tr><th>Row</th><th>Verdict</th><th>What was measured</th><th>Evidence</th></tr></thead><tbody><tr><td>block.number, timestamp, chainid, basefee and blockhash(number-1) read from a contract match the block the call executed in</td><td><strong>passed</strong></td><td>block 3053: number, timestamp, chainid 4465, basefee, blockhash(n-1) = parentHash, msg.sender and tx.origin all match</td><td>tx 0x186def3b…a228, block 3053</td></tr><tr><td>CREATE2 lands at the address Ethereum computes (keccak(0xff, deployer, salt, keccak(initcode)))</td><td><strong>passed</strong></td><td>child at 0xe3bC69915FB7318236c5ff31EF679aF6ae5b8699</td><td>tx 0x442569b2…af11, address 0xe3bC69915FB7318236c5ff31EF679aF6ae5b8699</td></tr></tbody></table></div>
|
||||
</section>
|
||||
<section class="doc-section"><h2 id="differences-randomness">Differences: randomness</h2>
|
||||
<div class="tbl"><table><thead><tr><th>Row</th><th>Verdict</th><th>What was measured</th><th>Evidence</th></tr></thead><tbody><tr><td>block.prevrandao: its value is derived from the chain's epoch seed (not Ethereum's beacon RANDAO); measured across consecutive blocks, and from a contract when a sender is funded</td><td><strong>passed</strong></td><td>blocks 767 to 770: 1 distinct epoch seed(s), 4 distinct mixHash value(s) in the headers; the source is the chain's epoch seed, which holds for an epoch, so prevrandao is not fresh per block and must not seed a lottery; a contract reading it twice in one call got the same value, and at block 768 it read 0x9cf17fa10c95…</td><td></td></tr></tbody></table></div>
|
||||
<section class="doc-section"><h2 id="differences-block-context-register-case-evm-04">Differences: block context (register case EVM-04)</h2>
|
||||
<div class="tbl"><table><thead><tr><th>Row</th><th>Verdict</th><th>What was measured</th><th>Evidence</th></tr></thead><tbody><tr><td>block.coinbase is the miner of the DAG block that first included the transaction, not one miner per chain block (measured: coinbase against the block's igneum.mergeset)</td><td><strong>passed</strong></td><td>coinbase 0x1450a9d8 = the including block's miner 0x1450a9d8; the chain block merged 1 block(s) with 1 distinct miner(s), chain block miner 0x1450a9d8</td><td>tx 0x186def3b…a228, coinbase 0x1450a9d804D29084d34b93afB001dE807Aa9920d, includingMiner 0x1450a9d804d29084d34b93afb001de807aa9920d, chainBlockMiner 0x1450a9d804d29084d34b93afb001de807aa9920d</td></tr></tbody></table></div>
|
||||
</section>
|
||||
<section class="doc-section"><h2 id="differences-two-dimensional-fees">Differences: two-dimensional fees</h2>
|
||||
<div class="tbl"><table><thead><tr><th>Row</th><th>Verdict</th><th>What was measured</th><th>Evidence</th></tr></thead><tbody><tr><td>a receipt carries pgasUsed, provingBaseFeePerGas, burnedProvingFee and burnedExecutionBaseFee; effectiveGasPrice covers both dimensions</td><td><strong>passed</strong></td><td>gasUsed 51375, pgasUsed 1968, proving base fee 10000 gwei per pgas; paid 5188875000000000 wei, of which proving burn 19680000000000000, execution burn 5137500000000000, tip 41100000000000 (parts sum differs from gasUsed × effectiveGasPrice)</td><td>tx 0xe787770a…25fb, gasUsed 51375, pgasUsed 1968, effectiveGasPrice 0x178411b200, parts_equal_paid false</td></tr></tbody></table></div>
|
||||
<section class="doc-section"><h2 id="differences-randomness-register-case-evm-04">Differences: randomness (register case EVM-04)</h2>
|
||||
<div class="tbl"><table><thead><tr><th>Row</th><th>Verdict</th><th>What was measured</th><th>Evidence</th></tr></thead><tbody><tr><td>block.prevrandao: its value is derived from the chain's epoch seed (not Ethereum's beacon RANDAO); measured across consecutive blocks, and from a contract when a sender is funded</td><td><strong>passed</strong></td><td>blocks 3051 to 3054: 1 distinct epoch seed(s), 4 distinct mixHash value(s) in the headers; the source is the chain's epoch seed, which holds for an epoch, so prevrandao is not fresh per block and must not seed a lottery; a contract reading it twice in one call got the same value, and at block 3053 it read 0x3b9abd95a495…</td><td></td></tr></tbody></table></div>
|
||||
</section>
|
||||
<section class="doc-section"><h2 id="differences-two-dimensional-fees-register-case-evm-03">Differences: two-dimensional fees (register case EVM-03)</h2>
|
||||
<div class="tbl"><table><thead><tr><th>Row</th><th>Verdict</th><th>What was measured</th><th>Evidence</th></tr></thead><tbody><tr><td>a receipt carries pgasUsed, provingBaseFeePerGas, burnedProvingFee and burnedExecutionBaseFee; effectiveGasPrice covers both dimensions</td><td><strong>passed</strong></td><td>gasUsed 51375, pgasUsed 1968, proving base fee 10000 gwei per pgas; paid 5188875000000000 wei, of which proving burn 19680000000000000, execution burn 5137500000000000, tip 41100000000000 (parts sum differs from gasUsed × effectiveGasPrice)</td><td>tx 0xd8dbd034…15ce, gasUsed 51375, pgasUsed 1968, effectiveGasPrice 0x178411b200, parts_equal_paid false</td></tr></tbody></table></div>
|
||||
</section>
|
||||
<section class="doc-section"><h2 id="what-the-differences-mean-for-an-application">What the differences mean for an application</h2>
|
||||
<ul><li>Block context: <code>block.coinbase</code> is the miner of the DAG block that first included the transaction, so one chain block can carry transactions with different coinbases; code that pays or trusts <code>block.coinbase</code> as "the block producer" sees several producers per block.</li><li>Randomness: <code>block.prevrandao</code> derives from the chain's epoch seed and holds for an epoch, so it is not fresh per block and must not seed a lottery or a commitment; use an application-level randomness source.</li><li>Two-dimensional fees: every transaction pays execution gas and proving gas; the node folds the second into the gas it quotes, so a wallet that quotes from the node (eth_estimateGas, eth_gasPrice, eth_feeHistory) is covered and a wallet with Ethereum's constants (21,000 for a transfer) is not; the receipt carries the split under <code>igneum</code> (pgasUsed, provingBaseFeePerGas, burnedProvingFee, burnedExecutionBaseFee, minerTip).</li></ul>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
| the red watcher fires on cancelled and timed-out runs too (`ci-red.yml`, `red-watch.mjs`) | The watcher's `if` missing any of failure, cancelled, timed_out, or the conclusion not handed to the record step (the self-test reads the workflow file); the line names the kind: CI red, CI cancelled, CI timed out. | 7 October 2026 |
|
||||
|
||||
| gh's active account is the stored Igneum entry (`gh-account-check.sh`, in Igneum's own gh directory `~/.config/gh-igneum` through `gh-env.sh`, never the founder's) | A push or a landing from this Mac while Igneum's gh directory names any other account as active, or none (the refusal names the one step: the founder or main stores the Igneum token there with `GH_CONFIG_DIR=~/.config/gh-igneum gh auth login --with-token`; no lane does); skipped with a line while `github-suspended` stands. RULE: no lane switches gh accounts on this Mac, ever; the second owner's login belongs to other projects and must never touch Igneum; the stored entry's name is in ~/.config/igneum/gh-user, never in the repository. | 7 October 2026, 21:41 UK: a lane switched gh to the other login during the suspension; nobody could say which |
|
||||
| the registry's evidence rules (`registry-evidence-check.sh`, called by `merge-to-master.sh` after rule 26) | A landing that sets a case's run_status to PASS without an evidence_path that exists (in the tree at the landing, or on a build box over ssh; a box that does not answer is a line, not a refusal); a landing that changes a file under docs/analysis/ or a path a registry row names without moving that row's `updated` (the row and its evidence move together, GOV-04); a PASS whose evidence record pins another manifest than the registry's pinned_manifest_sha (stale evidence reads NOT RUN, GOV-08); a run_status written while the registry carries no approval block (thresholds before results, GOV-02) | 8 Oct 2026 |
|
||||
| the acceptance layer (`test-record.mjs`, `test-map.json`, `test-map-doc.mjs`; the founder's Test and Acceptance Standard, docs/plans/igneum-2.0-test-registry.json) | An automated case of the registry with no cell in the map and no NOT RUN reason; a map naming an unknown case; a stale harness-map page (generated from the JSON); the recorder's self-test: a run batch writes run_status, run_id, evidence_path, updated and the evidence record to the mapped cases only, never an accept text, and a case with no harness reads NOT RUN with its reason, never PASS by inference | 8 Oct 2026 |
|
||||
| rule 26: a landing that touches a site/ or docs/ path another lane landed since the branch point carries master's copy (`rule26-no-revert.sh`, called by `merge-to-master.sh` before the merge) | A branch whose copy of such a path lacks lines master added after the merge base, or that deletes the path; refused with the path named and the fix (merge master on the branch, or name the path in the landing message as intentional). Class: 16b3e140 and 6fc57381 put the reference-apps lane's receipt.html and then all of site/lc back to older copies | 8 Oct 2026 |
|
||||
| rule 24: a landing that touches a .rs, Cargo.toml, Cargo.lock, build.rs or .cargo/config checks and tests its crates on the box first (`rule24-crate-gate.sh`, called by `merge-to-master.sh` before the merge and by the hook on a push of master or release-*) | A touched crate that does not `cargo check` or whose suite is red on the box at gate priority; a file under no crate (the root .cargo/config) runs the core pair igneum-pow and app/igneum-app; a vendor crate is named and left to its lane; docs/ and site/ alone (docs-only-check.sh) run nothing; any other diff takes the full gate alone. Class: master's igneum-pow stopped compiling at 17:07 UK under landings that never built it | 8 Oct 2026 |
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ the acceptance recorder: a run batch writes the registry's live fields and never
|
|||
the test map: every automated case of the registry maps to a cell or carries a NOT RUN reason; the map's ids exist
|
||||
the harness map page is generated from tools/ci/test-map.json and current
|
||||
P01 part A, the million-vector driver: a clean run is PASS, one wrong hash or one unanswered nonce is FAIL naming it (self-test, a fake worker)
|
||||
the registry's evidence rules: a PASS names evidence that exists, a touched evidence file moves with its row, stale evidence never reads PASS, a run_status needs the approval (self-test)
|
||||
the public ledger (docs/ledger-public.md) is what docs/fud-ledger.md generates: one row per item, no commit ids, times or team names (self-test first)
|
||||
the ledger page reads both entry heading forms (M1 and AP-F8-1) so no in-house pass row is dropped from /ledger (known-failed first)
|
||||
every workflow job carries timeout-minutes (site 15, changes 10, pow 60, sims 45; the hung-job class of 7 October 2026)
|
||||
|
|
|
|||
|
|
@ -209,6 +209,9 @@ BASE=$(git merge-base "$SHA" "$REMOTE/master" 2>/dev/null || git rev-parse "$REM
|
|||
bash tools/ci/rule24-crate-gate.sh "$BASE" "$SHA" || { echo "merge-to-master: REFUSED by rule 24: a touched crate does not check or its suite is red (above); fix on the branch and retry" >&2; exit 1; }
|
||||
# rule 26 (8 October 2026, 17:5x UK): a site/ or docs/ path another lane landed since the branch point is merged, never replaced
|
||||
bash tools/ci/rule26-no-revert.sh "$BASE" "$SHA" "$REMOTE/master" || { echo "merge-to-master: REFUSED by rule 26 (above)" >&2; exit 1; }
|
||||
# the registry's evidence rules (8 October 2026, 18:4x UK): a PASS carries existing evidence, a touched evidence file moves with its
|
||||
# row, stale evidence never reads PASS, a run_status needs the approval (GOV-02, GOV-04, GOV-08)
|
||||
bash tools/ci/registry-evidence-check.sh "$BASE" "$SHA" || { echo "merge-to-master: REFUSED by the registry's evidence rules (above)" >&2; exit 1; }
|
||||
for i in $(seq 1 "$TRIES"); do
|
||||
git fetch -q "$REMOTE" master; TIP=$(git rev-parse "$REMOTE/master")
|
||||
if git merge-base --is-ancestor "$SHA" "$TIP"; then echo "merge-to-master: ${SHA:0:8} is already on $REMOTE/master $(git log -1 --format=%h "$REMOTE/master")"; exit 0; fi
|
||||
|
|
|
|||
|
|
@ -173,6 +173,7 @@ tree_checks() {
|
|||
run "the test map: every automated case of the registry maps to a cell or carries a NOT RUN reason; the map's ids exist" node tools/ci/test-record.mjs --check
|
||||
run "the harness map page is generated from tools/ci/test-map.json and current" node tools/ci/test-map-doc.mjs --check
|
||||
run "P01 part A, the million-vector driver: a clean run is PASS, one wrong hash or one unanswered nonce is FAIL naming it (self-test, a fake worker)" python3 tools/ci/p01-vectors.py --self-test
|
||||
run "the registry's evidence rules: a PASS names evidence that exists, a touched evidence file moves with its row, stale evidence never reads PASS, a run_status needs the approval (self-test)" bash tools/ci/registry-evidence-check.sh --self-test
|
||||
run "the public ledger (docs/ledger-public.md) is what docs/fud-ledger.md generates: one row per item, no commit ids, times or team names (self-test first)" bash -c 'node tools/ledger/export-public.mjs --self-test && node tools/ledger/export-public.mjs --check'
|
||||
run "the ledger page reads both entry heading forms (M1 and AP-F8-1) so no in-house pass row is dropped from /ledger (known-failed first)" node tools/ledger-page.mjs --self-test
|
||||
run "every workflow job carries timeout-minutes (site 15, changes 10, pow 60, sims 45; the hung-job class of 7 October 2026)" bash tools/ci/workflow-timeouts-check.sh --self-test
|
||||
|
|
|
|||
121
tools/ci/registry-evidence-check.sh
Executable file
121
tools/ci/registry-evidence-check.sh
Executable file
|
|
@ -0,0 +1,121 @@
|
|||
#!/usr/bin/env bash
|
||||
# The registry's evidence rules (the founder's standard: GOV-02 thresholds before results, GOV-04 raw evidence preserved, GOV-08
|
||||
# stale evidence invalidated; main through the coordinator, 8 October 2026, 18:4x UK). Run by merge-to-master.sh before the
|
||||
# merge on <base> <head>:
|
||||
# 1. a landing that sets a case's run_status to PASS must carry the evidence_path it names: a path in the tree at <head>, or
|
||||
# an artefact on a build box (build-N:/srv/artefacts/... or /srv/artefacts/..., checked over ssh when the box answers;
|
||||
# a box that does not answer is a line, not a refusal); an empty or missing path is refused
|
||||
# 2. a landing that touches a file under docs/analysis/ or an evidence directory that a registry row names, without
|
||||
# updating that row (its `updated` field) in the same diff, is named (a refusal: the row and its evidence move together)
|
||||
# 3. a case whose evidence_record.manifest_sha is set and differs from the registry's pinned manifest (top-level
|
||||
# `pinned_manifest_sha`, when present) reads NOT RUN, never PASS: stale evidence (GOV-08)
|
||||
# 4. a run_status may be written only while the registry's approval stands (top-level `approval` present): thresholds are
|
||||
# frozen before results (GOV-02)
|
||||
# tools/ci/registry-evidence-check.sh <base> <head> exit 0 clean, 1 refused (the rows named), 2 bad args
|
||||
# tools/ci/registry-evidence-check.sh --self-test
|
||||
set -euo pipefail
|
||||
HERE="$(cd "$(dirname "$0")" && pwd -P)"; ME="$HERE/$(basename "$0")"
|
||||
REG="${REGISTRY_PATH:-docs/plans/igneum-2.0-test-registry.json}"
|
||||
check() { # <base> <head> ; prints "refused ..." lines; returns 1 when any
|
||||
local base="$1" head="$2" rc=0
|
||||
git cat-file -e "$head:$REG" 2>/dev/null || return 0
|
||||
local tmp_h tmp_b; tmp_h=$(mktemp); tmp_b=$(mktemp); git show "$head:$REG" > "$tmp_h"; git show "$base:$REG" > "$tmp_b" 2>/dev/null || : > "$tmp_b"
|
||||
local touched; touched=$(git diff --name-only "$base" "$head" --)
|
||||
python3 - "$tmp_h" "$tmp_b" "$head" "$touched" <<'PY' || rc=1
|
||||
import json, sys, subprocess, os
|
||||
h = json.load(open(sys.argv[1])); b = json.load(open(sys.argv[2])) if os.path.getsize(sys.argv[2]) else {}
|
||||
head = sys.argv[3]; touched = [t for t in sys.argv[4].split('\n') if t]
|
||||
cases = lambda r: [t for s in r.get('suites', []) for t in s.get('tests', [])]
|
||||
hb = {c['id']: c for c in cases(b)}; refused = []
|
||||
approved = bool(h.get('approval')); pinned = h.get('pinned_manifest_sha')
|
||||
def in_tree(p):
|
||||
return subprocess.run(['git', 'cat-file', '-e', f'{head}:{p}'], capture_output=True).returncode == 0
|
||||
def on_box(p):
|
||||
box, _, path = p.partition(':') if ':' in p else ('build-1', '', p)
|
||||
ip = {'build-1': '188.40.146.49', 'build-2': '142.132.249.238', 'build-3': '62.238.91.43', 'build-4': '178.63.182.105'}.get(box)
|
||||
if not ip: return 'unknown-box'
|
||||
r = subprocess.run(['ssh', '-o', 'BatchMode=yes', '-o', 'ConnectTimeout=6', f'build@{ip}', f'test -e {path!r} && echo yes || echo no'], capture_output=True, text=True)
|
||||
if r.returncode != 0: return 'no-answer'
|
||||
return 'yes' if 'yes' in r.stdout else 'no'
|
||||
for c in cases(h):
|
||||
cid = c['id']; old = hb.get(cid, {}); st = c.get('run_status'); changed = (st != old.get('run_status')) or (c.get('run_id') != old.get('run_id')) or (c.get('evidence_path') != old.get('evidence_path'))
|
||||
if changed and st and st != 'NOT RUN' and not approved:
|
||||
refused.append(f'refused {cid}: run_status {st} written while the registry carries no approval (GOV-02: thresholds before results)')
|
||||
rec = c.get('evidence_record') or {}
|
||||
if pinned and rec.get('manifest_sha') and not str(pinned).startswith(str(rec['manifest_sha'])[:8]) and not str(rec['manifest_sha']).startswith(str(pinned)[:8]) and st == 'PASS':
|
||||
refused.append(f'refused {cid}: PASS on evidence pinned to manifest {rec["manifest_sha"]} while the registry pins {pinned} (GOV-08: stale evidence reads NOT RUN)')
|
||||
if changed and st == 'PASS':
|
||||
p = (c.get('evidence_path') or '').strip()
|
||||
if not p: refused.append(f'refused {cid}: PASS with no evidence_path'); continue
|
||||
for one in [x.strip() for x in p.split(';') if x.strip()]:
|
||||
if one.startswith('/srv/') or ':/srv/' in one:
|
||||
if os.environ.get('REGISTRY_CHECK_NO_SSH') == '1': continue
|
||||
v = on_box(one)
|
||||
if v == 'no': refused.append(f'refused {cid}: PASS names {one}, which is not on the box')
|
||||
elif v in ('no-answer', 'unknown-box'): print(f'registry-evidence: {cid}: {one} could not be checked ({v}); not a refusal')
|
||||
elif not in_tree(one): refused.append(f'refused {cid}: PASS names {one}, which is not in the tree at {head[:8]}')
|
||||
# rule 2: a touched evidence file under docs/analysis or named by a row, without that row's `updated` moving
|
||||
named = {}
|
||||
for c in cases(h):
|
||||
for one in [x.strip() for x in (c.get('evidence_path') or '').split(';') if x.strip()]:
|
||||
if not one.startswith('/') and ':/' not in one: named.setdefault(one.rstrip('/'), []).append(c['id'])
|
||||
REG_PATH = os.environ.get('REGISTRY_PATH', 'docs/plans/igneum-2.0-test-registry.json')
|
||||
for t in touched:
|
||||
if t == REG_PATH: continue # the registry names itself as GOV-02's evidence (the approval recorded in it); it always moves with itself
|
||||
owners = [ids for p, ids in named.items() if t == p or t.startswith(p + '/')]
|
||||
if not owners and not t.startswith('docs/analysis/'): continue
|
||||
ids = sorted({i for ids in owners for i in ids})
|
||||
if not ids: continue # docs/analysis file no row names: free
|
||||
moved = [i for i in ids if (h and {c['id']: c for c in cases(h)}[i].get('updated')) != hb.get(i, {}).get('updated')]
|
||||
if not moved: refused.append(f'refused: {t} changed but its registry row(s) {", ".join(ids)} did not (the row and its evidence move together)')
|
||||
for r in refused: print(r)
|
||||
sys.exit(1 if refused else 0)
|
||||
PY
|
||||
rm -f "$tmp_h" "$tmp_b"; return $rc
|
||||
}
|
||||
if [ "${1:-}" = --self-test ]; then
|
||||
d=$(mktemp -d); trap 'rm -rf "$d"' EXIT; fails=0; export REGISTRY_CHECK_NO_SSH=1
|
||||
mk() { python3 - "$@" <<'PY'
|
||||
import json, sys
|
||||
path, approval, pinned, rows = sys.argv[1], sys.argv[2] == '1', sys.argv[3], json.loads(sys.argv[4])
|
||||
reg = {'title': 't', 'suites': [{'code': 'X', 'tests': [dict({'id': i, 'method': 'Automated', 'accept': 'a'}, **r) for i, r in rows.items()]}]}
|
||||
if approval: reg['approval'] = 'yes'
|
||||
if pinned != '-': reg['pinned_manifest_sha'] = pinned
|
||||
json.dump(reg, open(path, 'w'), indent=1)
|
||||
PY
|
||||
}
|
||||
( cd "$d" && git init -q -b master . && mkdir -p docs/plans docs/analysis evidence && echo e > evidence/a.log && echo r > docs/analysis/row.md
|
||||
mk docs/plans/igneum-2.0-test-registry.json 1 - '{"X-1": {}, "X-2": {"run_status": "RUNNING", "evidence_path": "docs/analysis/row.md", "updated": "t0"}}'
|
||||
git add -A && git -c user.name=t -c user.email=t@t commit -q -m base && git tag base
|
||||
# pass-ok: PASS with an evidence path in the tree
|
||||
mk docs/plans/igneum-2.0-test-registry.json 1 - '{"X-1": {"run_status": "PASS", "evidence_path": "evidence/a.log", "updated": "t1"}, "X-2": {"run_status": "RUNNING", "evidence_path": "docs/analysis/row.md", "updated": "t0"}}'
|
||||
git -c user.name=t -c user.email=t@t commit -qam pass-ok && git tag pass-ok
|
||||
# pass-missing: PASS naming a path not in the tree
|
||||
git checkout -q -b m base; mk docs/plans/igneum-2.0-test-registry.json 1 - '{"X-1": {"run_status": "PASS", "evidence_path": "evidence/none.log", "updated": "t1"}, "X-2": {"run_status": "RUNNING", "evidence_path": "docs/analysis/row.md", "updated": "t0"}}'
|
||||
git -c user.name=t -c user.email=t@t commit -qam pass-missing && git tag pass-missing
|
||||
# evidence-touched: docs/analysis/row.md changed, X-2's updated did not
|
||||
git checkout -q -b e base; echo r2 > docs/analysis/row.md; git -c user.name=t -c user.email=t@t commit -qam touched && git tag touched
|
||||
# evidence-with-row: the same change with X-2's updated moved
|
||||
git checkout -q -b e2 base; echo r2 > docs/analysis/row.md; mk docs/plans/igneum-2.0-test-registry.json 1 - '{"X-1": {}, "X-2": {"run_status": "RUNNING", "evidence_path": "docs/analysis/row.md", "updated": "t1"}}'; git -c user.name=t -c user.email=t@t commit -qam with-row && git tag with-row
|
||||
# stale: PASS on evidence pinned to another manifest
|
||||
git checkout -q -b s base; mk docs/plans/igneum-2.0-test-registry.json 1 aaaaaaaa '{"X-1": {"run_status": "PASS", "evidence_path": "evidence/a.log", "updated": "t1", "evidence_record": {"manifest_sha": "bbbbbbbb"}}, "X-2": {}}'; git -c user.name=t -c user.email=t@t commit -qam stale && git tag stale
|
||||
# self-ref: a row names the registry itself as its evidence; a registry change must not trip rule 2 on it
|
||||
git checkout -q -b r base; mk docs/plans/igneum-2.0-test-registry.json 1 - '{"X-1": {"run_status": "RUNNING", "evidence_path": "evidence/a.log", "updated": "t1"}, "X-2": {"run_status": "RUNNING", "evidence_path": "docs/plans/igneum-2.0-test-registry.json", "updated": "t0"}}'; git -c user.name=t -c user.email=t@t commit -qam self-ref && git tag self-ref
|
||||
# unapproved: a run_status written with no approval
|
||||
git checkout -q -b u base; mk docs/plans/igneum-2.0-test-registry.json 0 - '{"X-1": {"run_status": "RUNNING", "evidence_path": "evidence/a.log", "updated": "t1"}, "X-2": {}}'; git -c user.name=t -c user.email=t@t commit -qam unapproved && git tag unapproved ) >/dev/null 2>&1
|
||||
cd "$d"
|
||||
bash "$ME" base pass-ok >/dev/null 2>&1 || { echo "self-test failed: a PASS with its evidence in the tree was refused: $(bash "$ME" base pass-ok 2>&1)"; fails=1; }
|
||||
out=$(bash "$ME" base pass-missing 2>&1) && { echo "self-test failed: a PASS naming a missing path passed"; fails=1; }; case "$out" in *"not in the tree"*) ;; *) echo "self-test failed: the missing path was not named: $out"; fails=1 ;; esac
|
||||
out=$(bash "$ME" base touched 2>&1) && { echo "self-test failed: a touched evidence file without its row passed"; fails=1; }; case "$out" in *"X-2"*"move together"*) ;; *) echo "self-test failed: the unmoved row was not named: $out"; fails=1 ;; esac
|
||||
bash "$ME" base with-row >/dev/null 2>&1 || { echo "self-test failed: a touched evidence file with its row updated was refused: $(bash "$ME" base with-row 2>&1)"; fails=1; }
|
||||
out=$(bash "$ME" base stale 2>&1) && { echo "self-test failed: a PASS on stale evidence passed"; fails=1; }; case "$out" in *"stale evidence"*) ;; *) echo "self-test failed: the stale evidence was not named: $out"; fails=1 ;; esac
|
||||
bash "$ME" base self-ref >/dev/null 2>&1 || { echo "self-test failed: a row naming the registry itself as evidence tripped the move-together rule on a registry change: $(bash "$ME" base self-ref 2>&1)"; fails=1; }
|
||||
out=$(bash "$ME" base unapproved 2>&1) && { echo "self-test failed: a run_status without approval passed"; fails=1; }; case "$out" in *"thresholds before results"*) ;; *) echo "self-test failed: the missing approval was not named: $out"; fails=1 ;; esac
|
||||
[ "$fails" = 0 ] && echo "self-test passed: a PASS must name evidence that exists (tree or box); a touched evidence file moves with its registry row; evidence pinned to another manifest cannot be PASS; a run_status needs the registry's approval"
|
||||
exit $fails
|
||||
fi
|
||||
[ $# -eq 2 ] || { echo "usage: registry-evidence-check.sh <base> <head> | --self-test" >&2; exit 2; }
|
||||
rc=0; out=$(check "$1" "$2") || rc=$?
|
||||
printf '%s\n' "$out" | sed -n 's/^refused/registry-evidence: REFUSED:/p; /^registry-evidence:/p' | grep . || true
|
||||
[ "$rc" = 0 ] && echo "registry-evidence: every PASS names existing evidence, every touched evidence file moves with its row, no stale evidence reads PASS"
|
||||
exit $rc
|
||||
|
|
@ -10,7 +10,7 @@ const res = existsSync(src) ? JSON.parse(readFileSync(src, 'utf8')) : { meta: {}
|
|||
const esc = s => String(s).replace(/\|/g, '\\|');
|
||||
const short = h => (typeof h === 'string' && /^0x[0-9a-f]{64}$/i.test(h) ? h.slice(0, 10) + '…' + h.slice(-4) : h);
|
||||
const evidence = r => Object.entries(r.evidence || {}).filter(([, v]) => ['string', 'number', 'boolean'].includes(typeof v)).map(([k, v]) => `${k} ${short(v)}`).join(', ');
|
||||
const ITEMS = ['Representative contracts', 'Wallet fee estimation', 'Indexing', 'Failed transactions', 'Receipts', 'Application assumptions', 'Differences: block context', 'Differences: randomness', 'Differences: two-dimensional fees'];
|
||||
const ITEMS = ['Representative contracts', 'Transaction binding and replay', 'Wallet fee estimation', 'Indexing', 'Failed transactions', 'Receipts', 'Application assumptions', 'Differences: block context', 'Differences: randomness', 'Differences: two-dimensional fees'];
|
||||
const PLANNED = {
|
||||
'Representative contracts': ['an ERC-20 deploys (CREATE address, code at the address)', 'ERC-20 transfer: balances, the Transfer log, eth_call', 'ERC-20 approve and transferFrom', 'a probe contract deploys', 'a counter increments and persists'],
|
||||
'Wallet fee estimation': ['eth_gasPrice, eth_maxPriorityFeePerGas, eth_feeHistory shapes', 'a transfer: estimateGas against gasUsed', 'a contract call: estimateGas against gasUsed', 'the documented difference: a transfer sent with a local 21,000 limit'],
|
||||
|
|
@ -27,14 +27,14 @@ let md = `# Compatibility, measured
|
|||
|
||||
A GPU-secured network for Ethereum-compatible applications and verifiable computation. Compatibility is a product deliverable here, not a sentence: every row below is a test that ran against the devnet from the repository (\`tools/reference-apps/compat/run.mjs\`), with its evidence, and a row that could not run says so and why. Devnet, no value.
|
||||
|
||||
Last run: ${when}${res.meta.network ? ` on ${res.meta.network} (chain id ${res.meta.chain_id})` : ''}. ${res.summary.passed} passed, ${res.summary.failed} failed, ${res.summary.untested} untested. TEAM-REPORTED: run by the team, no outside reproduction yet. Sender ${res.meta.sender ? res.meta.sender.slice(0, 10) + '…' : 'none'}${res.meta.solc ? `, contracts compiled with solc ${res.meta.solc}` : ''}.
|
||||
Last run: ${when}${res.meta.network ? ` on ${res.meta.network} (chain id ${res.meta.chain_id})` : ''}${res.meta.run_id ? `, run id ${res.meta.run_id}` : ''}. ${res.summary.passed} passed, ${res.summary.failed} failed, ${res.summary.untested} untested. Sender ${res.meta.sender ? res.meta.sender.slice(0, 10) + '…' : 'none'}${res.meta.solc ? `, contracts compiled with solc ${res.meta.solc}` : ''}.
|
||||
|
||||
Three boundaries hold for everything on this page: proven execution is not finality; EVM compatibility is not Ethereum security; ZK is not privacy. The four words included, executed, proven and finalised are defined on [/receipt](/receipt).
|
||||
|
||||
`;
|
||||
for (const item of ITEMS) {
|
||||
const rows = res.rows.filter(r => r.item === item);
|
||||
md += `## ${item}\n\n| Row | Verdict | What was measured | Evidence |\n|---|---|---|---|\n`;
|
||||
const rc = rows[0] && rows[0].register_case; md += `## ${item}${rc ? ` (register case ${rc})` : ''}\n\n| Row | Verdict | What was measured | Evidence |\n|---|---|---|---|\n`;
|
||||
if (rows.length) for (const r of rows) md += `| ${esc(r.name)} | **${r.verdict}** | ${esc(r.detail || '')} | ${esc(evidence(r))} |\n`;
|
||||
else for (const name of PLANNED[item] || []) md += `| ${esc(name)} | **untested** | not run yet: the devnet was switched off when this page was built; the row runs on the 2.0 devnet | |\n`;
|
||||
md += '\n';
|
||||
|
|
|
|||
|
|
@ -1,98 +1,105 @@
|
|||
{
|
||||
"meta": {
|
||||
"run_id": "ra-20261008T1744-evm",
|
||||
"rpc": "https://rpc.devnet.igneum.network",
|
||||
"chain_id": 4465,
|
||||
"network": "igneum-devnet-4",
|
||||
"node_version": "igneumd 2.0.0",
|
||||
"started": "2026-10-08T16:33:17.064Z",
|
||||
"started": "2026-10-08T17:44:37.324Z",
|
||||
"sender": "0x27C433aEec28f9Be4cCe17A8C645d65baDfCF891",
|
||||
"funded": true,
|
||||
"solc": "0.8.28+commit.7893614a.Emscripten.clang",
|
||||
"finished": "2026-10-08T16:34:23.613Z"
|
||||
"finished": "2026-10-08T17:45:51.564Z"
|
||||
},
|
||||
"summary": {
|
||||
"passed": 20,
|
||||
"passed": 22,
|
||||
"failed": 0,
|
||||
"untested": 0
|
||||
},
|
||||
"deployed": {
|
||||
"token": "0xb2495fd85f54d73d7a13059a8e61956b67ad7aed",
|
||||
"probe": "0x3efc60794d574627eb5cb4eca77d96735dac4c42",
|
||||
"token": "0xd93f5e2091ccd544757a38ecf5e4fa176c141b62",
|
||||
"probe": "0xc4de4cf5766650a5c029fa908e3eb9270a19ed7d",
|
||||
"contextTx": {
|
||||
"hash": "0x3c1d2dffad903da6fc821598c7105e8683ea2000a885b440827c73d9dd204fcd",
|
||||
"block": 768,
|
||||
"coinbase": "0xc119093F38E3764Fdd86ea9635b7f616DEC6C3A6",
|
||||
"prevrandao": "9cf17fa10c95c0a8fcb6332bf7cd9dac1415aea7fcf09ca4f13f410fbdc72024"
|
||||
"hash": "0x186def3bfbc8cb0a05e7533d7527c50f91bf034bd94db812cb93a9938b51a228",
|
||||
"block": 3053,
|
||||
"coinbase": "0x1450a9d804D29084d34b93afB001dE807Aa9920d",
|
||||
"prevrandao": "3b9abd95a495129679ad25afa750aff9ec2d03999ed57582698e3f4c4f4db862"
|
||||
}
|
||||
},
|
||||
"rows": [
|
||||
{
|
||||
"id": "contracts.erc20.deploy",
|
||||
"item": "Representative contracts",
|
||||
"register_case": "EVM-05",
|
||||
"name": "an ERC-20 deploys (CREATE address as Ethereum computes it, code at the address)",
|
||||
"verdict": "passed",
|
||||
"detail": "at 0xb2495fd85f54d73d7a13059a8e61956b67ad7aed, block 739, gas 436751 of 639078 estimated",
|
||||
"detail": "at 0xd93f5e2091ccd544757a38ecf5e4fa176c141b62, block 3016, gas 436751 of 639078 estimated",
|
||||
"evidence": {
|
||||
"tx": "0x8fd280cb68049a077b762d0152cace0428230d0757fbed7b05f09a8c24a7a5b9",
|
||||
"address": "0xb2495fd85f54d73d7a13059a8e61956b67ad7aed",
|
||||
"block": 739,
|
||||
"tx": "0x314c059b7e3b8e1b0ec0f9b48430ac8e8a4f71231fbea5dd4caefbc817fea679",
|
||||
"address": "0xd93f5e2091ccd544757a38ecf5e4fa176c141b62",
|
||||
"block": 3016,
|
||||
"gasUsed": 436751,
|
||||
"estimated": 639078
|
||||
},
|
||||
"at": "2026-10-08T16:33:22.753Z"
|
||||
"at": "2026-10-08T17:44:42.491Z"
|
||||
},
|
||||
{
|
||||
"id": "contracts.erc20.transfer",
|
||||
"item": "Representative contracts",
|
||||
"register_case": "EVM-05",
|
||||
"name": "ERC-20 transfer: balances move, the Transfer log decodes, eth_call reads the new balance",
|
||||
"verdict": "passed",
|
||||
"detail": "5 CTT to 0x00000000, log decoded, balance read",
|
||||
"evidence": {
|
||||
"tx": "0xe787770a18a4da1288080e493a5ac3f02aba5f4f5d89302a409e0c2ffc7125fb",
|
||||
"block": 742
|
||||
"tx": "0xd8dbd0346f81f2ef54333c52f64e04cc042c71c291a3ffb602efe989695915ce",
|
||||
"block": 3018
|
||||
},
|
||||
"at": "2026-10-08T16:33:27.426Z"
|
||||
"at": "2026-10-08T17:44:47.181Z"
|
||||
},
|
||||
{
|
||||
"id": "contracts.erc20.approve",
|
||||
"item": "Representative contracts",
|
||||
"register_case": "EVM-05",
|
||||
"name": "ERC-20 approve then transferFrom by a spender (the sender approves itself as spender): allowance consumed, logs decode",
|
||||
"verdict": "passed",
|
||||
"detail": "allowance 3 then 1 after transferFrom of 2",
|
||||
"evidence": {
|
||||
"approve": "0xfc7a3a64b8de2d3b5c75c54036ac5e785df5e1d78cfd6ea9be7602e7ee815d24",
|
||||
"transferFrom": "0x6c0a22dc3511c4a6836f0e9637f52fd3d282549eb5317e3e9078e6db652cef22"
|
||||
"approve": "0x570bbe8618caabfc5fc06b05147c81fdb8858bb80fc1fd525bea6500822752c8",
|
||||
"transferFrom": "0xe6031b34c1b277a753f50f00d656d0c158df29d72c7f0629817115362fb0cd5f"
|
||||
},
|
||||
"at": "2026-10-08T16:33:36.609Z"
|
||||
"at": "2026-10-08T17:44:56.275Z"
|
||||
},
|
||||
{
|
||||
"id": "contracts.probe.deploy",
|
||||
"item": "Representative contracts",
|
||||
"register_case": "EVM-05",
|
||||
"name": "a probe contract deploys (counter, block context reader, revert, out-of-gas loop, CREATE2)",
|
||||
"verdict": "passed",
|
||||
"detail": "at 0x3efc60794d574627eb5cb4eca77d96735dac4c42",
|
||||
"detail": "at 0xc4de4cf5766650a5c029fa908e3eb9270a19ed7d",
|
||||
"evidence": {
|
||||
"tx": "0x551c24030022ebca96ba6d44c6d8d50637cba25be5c7c13839e01eadc6938e15",
|
||||
"address": "0x3efc60794d574627eb5cb4eca77d96735dac4c42",
|
||||
"block": 751
|
||||
"tx": "0x97e39c81a2351c52a3b132f6dd69adcb8a2a83c5185963d63ab8d7a530eebdfa",
|
||||
"address": "0xc4de4cf5766650a5c029fa908e3eb9270a19ed7d",
|
||||
"block": 3026
|
||||
},
|
||||
"at": "2026-10-08T16:33:41.134Z"
|
||||
"at": "2026-10-08T17:45:00.836Z"
|
||||
},
|
||||
{
|
||||
"id": "contracts.counter",
|
||||
"item": "Representative contracts",
|
||||
"register_case": "EVM-05",
|
||||
"name": "a counter increments twice and reads 2 (state persists across chain blocks)",
|
||||
"verdict": "passed",
|
||||
"detail": "count 2 after blocks 753 and 755",
|
||||
"detail": "count 2 after blocks 3029 and 3032",
|
||||
"evidence": {
|
||||
"first": "0xfaf855760dad78fd488432f54db35ecf7baf089408abb37309d77089a99b75a1",
|
||||
"second": "0x97ca41517b1ee4cff94b854308a6ab474be1d6f87eff582837caf89b58fe19c8"
|
||||
"first": "0x1771f03c79e1821270c5a57aeb5f6b1803676310301b742a139a703c6e4fcd3a",
|
||||
"second": "0xad3f659436b7c670c0bc3809871fed8052c3db54c5324f05fdadb19cab05c013"
|
||||
},
|
||||
"at": "2026-10-08T16:33:50.383Z"
|
||||
"at": "2026-10-08T17:45:14.114Z"
|
||||
},
|
||||
{
|
||||
"id": "fees.quotes",
|
||||
"item": "Wallet fee estimation",
|
||||
"register_case": "EVM-03",
|
||||
"name": "eth_gasPrice, eth_maxPriorityFeePerGas and eth_feeHistory answer in Ethereum's shapes",
|
||||
"verdict": "passed",
|
||||
"detail": "gasPrice 196.130804856 gwei, priority 1 gwei, feeHistory 5 base fees",
|
||||
|
|
@ -109,9 +116,9 @@
|
|||
],
|
||||
"gasUsedRatio": [
|
||||
0,
|
||||
0.0014490333333333333,
|
||||
0,
|
||||
0.0008790333333333334
|
||||
0.0008790333333333334,
|
||||
0
|
||||
],
|
||||
"igneum": {
|
||||
"provingBaseFeePerGas": [
|
||||
|
|
@ -121,7 +128,7 @@
|
|||
"0x9184e72a000"
|
||||
]
|
||||
},
|
||||
"oldestBlock": "0x2f0",
|
||||
"oldestBlock": "0xbd6",
|
||||
"reward": [
|
||||
[
|
||||
"0x3b9aca00"
|
||||
|
|
@ -138,86 +145,126 @@
|
|||
]
|
||||
}
|
||||
},
|
||||
"at": "2026-10-08T16:33:50.543Z"
|
||||
"at": "2026-10-08T17:45:14.223Z"
|
||||
},
|
||||
{
|
||||
"id": "fees.estimate.transfer",
|
||||
"item": "Wallet fee estimation",
|
||||
"register_case": "EVM-03",
|
||||
"name": "a plain transfer: eth_estimateGas against the receipt's gasUsed (the quote folds proving gas; both above Ethereum's 21,000)",
|
||||
"verdict": "passed",
|
||||
"detail": "estimated 59650, used 21000 (35% of the estimate); Ethereum's figure is 21,000",
|
||||
"evidence": {
|
||||
"tx": "0x99c4dc1ae8d2f32bcc62ed78ff9c829a6281065ba0c9eaf43ffa574c48b1cad0",
|
||||
"tx": "0x6e67cf099e06ee7045d3ea1b890f10f7ce071d47086fe18449285d8a3966c795",
|
||||
"estimated": 59650,
|
||||
"gasUsed": 21000,
|
||||
"ethereum": 21000
|
||||
},
|
||||
"at": "2026-10-08T16:33:55.347Z"
|
||||
"at": "2026-10-08T17:45:18.898Z"
|
||||
},
|
||||
{
|
||||
"id": "fees.estimate.call",
|
||||
"item": "Wallet fee estimation",
|
||||
"register_case": "EVM-03",
|
||||
"name": "a contract call: eth_estimateGas against gasUsed (a wallet that quotes from the node is covered)",
|
||||
"verdict": "passed",
|
||||
"detail": "estimated 134366, used 26371",
|
||||
"evidence": {
|
||||
"tx": "0xeb8bafa3a979a9ccd5c21ca7df91f5eb49c09b926cfa27981fcd38b796b7bee4",
|
||||
"tx": "0xc14d3a767d124d3628d0ae5161b2c2d3bd4433195857d3444c67a056e7c131c6",
|
||||
"estimated": 134366,
|
||||
"gasUsed": 26371
|
||||
},
|
||||
"at": "2026-10-08T16:34:00.085Z"
|
||||
"at": "2026-10-08T17:45:23.595Z"
|
||||
},
|
||||
{
|
||||
"id": "fees.local21000",
|
||||
"item": "Wallet fee estimation",
|
||||
"register_case": "EVM-03",
|
||||
"name": "the documented difference: a transfer sent with a local 21,000 gas limit (Ethereum's intrinsic cost) instead of the node's quote",
|
||||
"verdict": "passed",
|
||||
"detail": "the node accepted it and it succeeded with gasUsed 21000: a wallet with a hard-coded 21,000 works",
|
||||
"evidence": {
|
||||
"sent": true,
|
||||
"hash": "0x538fdf72a8fef37dc1c0024bcfe61028ed74b02c504e9df26978f4adb907b121",
|
||||
"hash": "0x1581f6088e6642cde28dc04ffc0017a0c0a0377e482279c59de9cf46e9022c32",
|
||||
"status": "success",
|
||||
"gasUsed": 21000
|
||||
},
|
||||
"at": "2026-10-08T16:34:04.657Z"
|
||||
"at": "2026-10-08T17:45:27.957Z"
|
||||
},
|
||||
{
|
||||
"id": "failed.revert",
|
||||
"item": "Failed transactions",
|
||||
"register_case": "EVM-05",
|
||||
"name": "a revert with a reason: eth_call returns the reason, the sent transaction has status 0, gas is charged, the nonce advances",
|
||||
"verdict": "passed",
|
||||
"detail": "eth_call answers code 3 \"execution reverted\" with Error(string) data decoding to \"compat says no\"; the sent transaction: status 0, gasUsed 22292 of 200000, nonce 23 to 24",
|
||||
"detail": "eth_call answers code 3 \"execution reverted\" with Error(string) data decoding to \"compat says no\"; the sent transaction: status 0, gasUsed 22292 of 200000, nonce 37 to 38",
|
||||
"evidence": {
|
||||
"tx": "0xfcdf8d24eb414154d24cf3e0c11d5d732ba3f612e219d8adc316ec6323a06a1e",
|
||||
"tx": "0x90e50327309da43b7aab7a39c9c5970784bbc0476010d29ef0d65ce1bfc81344",
|
||||
"gasUsed": 22292,
|
||||
"block": 762,
|
||||
"block": 3044,
|
||||
"call_error_code": 3,
|
||||
"call_error_message": "execution reverted",
|
||||
"revert_data": "0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000e636f6d7061742073617973206e6f000000000000000000000000000000000000"
|
||||
},
|
||||
"at": "2026-10-08T16:34:09.064Z"
|
||||
"at": "2026-10-08T17:45:32.415Z"
|
||||
},
|
||||
{
|
||||
"id": "failed.outofgas",
|
||||
"item": "Failed transactions",
|
||||
"register_case": "EVM-05",
|
||||
"name": "an out-of-gas call: status 0 and the whole limit charged",
|
||||
"verdict": "passed",
|
||||
"detail": "status 0, gasUsed 150000 of the 150000 limit",
|
||||
"evidence": {
|
||||
"tx": "0xb3986b45642c28dd029dc34714878e42c025a0bd6349609900b7cef120f7a1f6",
|
||||
"tx": "0x4d13892063cc12ce5b67209f0a8c1dfa438fcc54e916c6748a556220f744e5f0",
|
||||
"gasUsed": 150000,
|
||||
"limit": 150000
|
||||
},
|
||||
"at": "2026-10-08T16:34:13.537Z"
|
||||
"at": "2026-10-08T17:45:36.717Z"
|
||||
},
|
||||
{
|
||||
"id": "binding.chainid",
|
||||
"item": "Transaction binding and replay",
|
||||
"register_case": "EVM-02",
|
||||
"name": "a transaction signed for another chain id (the previous devnet's 4464) is refused by the node",
|
||||
"verdict": "passed",
|
||||
"detail": "refused: wrong chain id: expected 4465, got Some(4464)",
|
||||
"evidence": {
|
||||
"chain_id_signed": 4464,
|
||||
"error": {
|
||||
"code": -32000,
|
||||
"message": "wrong chain id: expected 4465, got Some(4464)"
|
||||
}
|
||||
},
|
||||
"at": "2026-10-08T17:45:36.791Z"
|
||||
},
|
||||
{
|
||||
"id": "binding.replay",
|
||||
"item": "Transaction binding and replay",
|
||||
"register_case": "EVM-02",
|
||||
"name": "the same signed transaction sent twice: the second send is refused (nonce already used)",
|
||||
"verdict": "passed",
|
||||
"detail": "first send mined in block 3049; the replay refused: nonce too low: account nonce is 40, transaction has 39",
|
||||
"evidence": {
|
||||
"tx": "0xb1722ee04bcf1aa0ff1c7a76aaaf5c42902bcb32aeeb2d463c81922ce8f5a36f",
|
||||
"block": 3049,
|
||||
"replay": {
|
||||
"code": -32000,
|
||||
"message": "nonce too low: account nonce is 40, transaction has 39"
|
||||
},
|
||||
"nonce_after": 40
|
||||
},
|
||||
"at": "2026-10-08T17:45:41.296Z"
|
||||
},
|
||||
{
|
||||
"id": "receipts.fields",
|
||||
"item": "Receipts",
|
||||
"register_case": "EVM-06",
|
||||
"name": "a receipt carries every Ethereum field, logsBloom recomputes from its logs, contractAddress is set on creation",
|
||||
"verdict": "passed",
|
||||
"detail": "15 fields, bloom recomputed over 1 log(s), contractAddress 0xb2495fd8",
|
||||
"detail": "15 fields, bloom recomputed over 1 log(s), contractAddress 0xd93f5e20",
|
||||
"evidence": {
|
||||
"tx": "0x8fd280cb68049a077b762d0152cace0428230d0757fbed7b05f09a8c24a7a5b9",
|
||||
"tx": "0x314c059b7e3b8e1b0ec0f9b48430ac8e8a4f71231fbea5dd4caefbc817fea679",
|
||||
"fields": [
|
||||
"blockHash",
|
||||
"blockNumber",
|
||||
|
|
@ -236,134 +283,141 @@
|
|||
"type"
|
||||
]
|
||||
},
|
||||
"at": "2026-10-08T16:34:13.578Z"
|
||||
"at": "2026-10-08T17:45:41.335Z"
|
||||
},
|
||||
{
|
||||
"id": "receipts.root",
|
||||
"item": "Receipts",
|
||||
"register_case": "EVM-06",
|
||||
"name": "the block's receipts rebuild its receipts trie root (Ethereum's layout, the node's encoding) equal to the header's receiptsRoot",
|
||||
"verdict": "passed",
|
||||
"detail": "block 742, 1 receipts, root 0xa28061003c4c",
|
||||
"detail": "block 3018, 1 receipts, root 0xc443c3e57c60",
|
||||
"evidence": {
|
||||
"block": 742,
|
||||
"block": 3018,
|
||||
"receipts": 1,
|
||||
"receiptsRoot": "0xa28061003c4cfa70006e203524ededd4668753d432bef4c657c1ede124d6ac55"
|
||||
"receiptsRoot": "0xc443c3e57c6002f379352b6c2897b6ea03a4320255831fb502ffc3094b888836"
|
||||
},
|
||||
"at": "2026-10-08T16:34:13.651Z"
|
||||
"at": "2026-10-08T17:45:41.411Z"
|
||||
},
|
||||
{
|
||||
"id": "indexing.logs",
|
||||
"item": "Indexing",
|
||||
"register_case": "EVM-06",
|
||||
"name": "eth_getLogs by address, by topic and by block range returns the receipts' logs with consistent logIndex and transactionIndex",
|
||||
"verdict": "passed",
|
||||
"detail": "4 logs by address, 3 Transfer logs by topic, each found in its receipt",
|
||||
"evidence": {
|
||||
"byAddress": 4,
|
||||
"byTopic": 3,
|
||||
"fromBlock": 739
|
||||
"fromBlock": 3016
|
||||
},
|
||||
"at": "2026-10-08T16:34:13.880Z"
|
||||
"at": "2026-10-08T17:45:41.709Z"
|
||||
},
|
||||
{
|
||||
"id": "indexing.block",
|
||||
"item": "Indexing",
|
||||
"register_case": "EVM-06",
|
||||
"name": "eth_getBlockByNumber with full transactions, eth_getBlockReceipts and eth_getTransactionByHash agree on indices and hashes",
|
||||
"verdict": "passed",
|
||||
"detail": "block 742: 1 transactions, indices 0 to 0 continuous",
|
||||
"detail": "block 3018: 1 transactions, indices 0 to 0 continuous",
|
||||
"evidence": {
|
||||
"block": 742,
|
||||
"block": 3018,
|
||||
"count": 1
|
||||
},
|
||||
"at": "2026-10-08T16:34:14.059Z"
|
||||
"at": "2026-10-08T17:45:41.834Z"
|
||||
},
|
||||
{
|
||||
"id": "assumptions.context",
|
||||
"item": "Application assumptions",
|
||||
"register_case": "EVM-04",
|
||||
"name": "block.number, timestamp, chainid, basefee and blockhash(number-1) read from a contract match the block the call executed in",
|
||||
"verdict": "passed",
|
||||
"detail": "block 768: number, timestamp, chainid 4465, basefee, blockhash(n-1) = parentHash, msg.sender and tx.origin all match",
|
||||
"detail": "block 3053: number, timestamp, chainid 4465, basefee, blockhash(n-1) = parentHash, msg.sender and tx.origin all match",
|
||||
"evidence": {
|
||||
"tx": "0x3c1d2dffad903da6fc821598c7105e8683ea2000a885b440827c73d9dd204fcd",
|
||||
"block": 768
|
||||
"tx": "0x186def3bfbc8cb0a05e7533d7527c50f91bf034bd94db812cb93a9938b51a228",
|
||||
"block": 3053
|
||||
},
|
||||
"at": "2026-10-08T16:34:18.585Z"
|
||||
"at": "2026-10-08T17:45:46.595Z"
|
||||
},
|
||||
{
|
||||
"id": "assumptions.create2",
|
||||
"item": "Application assumptions",
|
||||
"register_case": "EVM-04",
|
||||
"name": "CREATE2 lands at the address Ethereum computes (keccak(0xff, deployer, salt, keccak(initcode)))",
|
||||
"verdict": "passed",
|
||||
"detail": "child at 0xE63036B0fEC0d01321Ef4DA62C084d1Ec2eA47be",
|
||||
"detail": "child at 0xe3bC69915FB7318236c5ff31EF679aF6ae5b8699",
|
||||
"evidence": {
|
||||
"tx": "0x11cd98733996949be674b9669a3d459ba7bbeda8345fa2879ecb9fe36b9aa80c",
|
||||
"address": "0xE63036B0fEC0d01321Ef4DA62C084d1Ec2eA47be"
|
||||
"tx": "0x442569b23f8b35526f48016154f887c77478029d977742e53bf192ac19eeaf11",
|
||||
"address": "0xe3bC69915FB7318236c5ff31EF679aF6ae5b8699"
|
||||
},
|
||||
"at": "2026-10-08T16:34:23.161Z"
|
||||
"at": "2026-10-08T17:45:51.218Z"
|
||||
},
|
||||
{
|
||||
"id": "difference.coinbase",
|
||||
"item": "Differences: block context",
|
||||
"register_case": "EVM-04",
|
||||
"name": "block.coinbase is the miner of the DAG block that first included the transaction, not one miner per chain block (measured: coinbase against the block's igneum.mergeset)",
|
||||
"verdict": "passed",
|
||||
"detail": "coinbase 0xc119093F = the including block's miner 0xc119093f; the chain block merged 2 block(s) with 1 distinct miner(s), chain block miner 0xc119093f",
|
||||
"detail": "coinbase 0x1450a9d8 = the including block's miner 0x1450a9d8; the chain block merged 1 block(s) with 1 distinct miner(s), chain block miner 0x1450a9d8",
|
||||
"evidence": {
|
||||
"tx": "0x3c1d2dffad903da6fc821598c7105e8683ea2000a885b440827c73d9dd204fcd",
|
||||
"coinbase": "0xc119093F38E3764Fdd86ea9635b7f616DEC6C3A6",
|
||||
"includingMiner": "0xc119093f38e3764fdd86ea9635b7f616dec6c3a6",
|
||||
"tx": "0x186def3bfbc8cb0a05e7533d7527c50f91bf034bd94db812cb93a9938b51a228",
|
||||
"coinbase": "0x1450a9d804D29084d34b93afB001dE807Aa9920d",
|
||||
"includingMiner": "0x1450a9d804d29084d34b93afb001de807aa9920d",
|
||||
"mergesetMiners": [
|
||||
"0xc119093f38e3764fdd86ea9635b7f616dec6c3a6",
|
||||
"0xc119093f38e3764fdd86ea9635b7f616dec6c3a6"
|
||||
"0x1450a9d804d29084d34b93afb001de807aa9920d"
|
||||
],
|
||||
"chainBlockMiner": "0xc119093f38e3764fdd86ea9635b7f616dec6c3a6"
|
||||
"chainBlockMiner": "0x1450a9d804d29084d34b93afb001de807aa9920d"
|
||||
},
|
||||
"at": "2026-10-08T16:34:23.244Z"
|
||||
"at": "2026-10-08T17:45:51.299Z"
|
||||
},
|
||||
{
|
||||
"id": "difference.randomness",
|
||||
"item": "Differences: randomness",
|
||||
"register_case": "EVM-04",
|
||||
"name": "block.prevrandao: its value is derived from the chain's epoch seed (not Ethereum's beacon RANDAO); measured across consecutive blocks, and from a contract when a sender is funded",
|
||||
"verdict": "passed",
|
||||
"detail": "blocks 767 to 770: 1 distinct epoch seed(s), 4 distinct mixHash value(s) in the headers; the source is the chain's epoch seed, which holds for an epoch, so prevrandao is not fresh per block and must not seed a lottery; a contract reading it twice in one call got the same value, and at block 768 it read 0x9cf17fa10c95…",
|
||||
"detail": "blocks 3051 to 3054: 1 distinct epoch seed(s), 4 distinct mixHash value(s) in the headers; the source is the chain's epoch seed, which holds for an epoch, so prevrandao is not fresh per block and must not seed a lottery; a contract reading it twice in one call got the same value, and at block 3053 it read 0x3b9abd95a495…",
|
||||
"evidence": {
|
||||
"blocks": [
|
||||
{
|
||||
"number": 767,
|
||||
"mixHash": "0xe5baec105ee8d299d423ae632944b4b185d4d885e57088b829443202c36d82b5",
|
||||
"epochSeed": "0x7c36b83374a673e990213be462509dcb08bcfc85144306aa9517cf3ad66faf6e"
|
||||
"number": 3051,
|
||||
"mixHash": "0x9855c45455bb5481bce8e7326bde56289d8455fac3ba088c09852cbc27f83a4d",
|
||||
"epochSeed": "0xc0e88f47b504f36aa8310a2e0735cf6c48a85a00e10349cbc16420ded775d186"
|
||||
},
|
||||
{
|
||||
"number": 768,
|
||||
"mixHash": "0x9cf17fa10c95c0a8fcb6332bf7cd9dac1415aea7fcf09ca4f13f410fbdc72024",
|
||||
"epochSeed": "0x7c36b83374a673e990213be462509dcb08bcfc85144306aa9517cf3ad66faf6e"
|
||||
"number": 3052,
|
||||
"mixHash": "0x89c614f9b0eb3acaec820886309da7c17d92bddd467c12d2341b5d255c78d3be",
|
||||
"epochSeed": "0xc0e88f47b504f36aa8310a2e0735cf6c48a85a00e10349cbc16420ded775d186"
|
||||
},
|
||||
{
|
||||
"number": 769,
|
||||
"mixHash": "0xe39ab8de805c6b8c8ccad7b078a788b6f2b79d7b25e19f0211951a1aba5e3c42",
|
||||
"epochSeed": "0x7c36b83374a673e990213be462509dcb08bcfc85144306aa9517cf3ad66faf6e"
|
||||
"number": 3053,
|
||||
"mixHash": "0x3b9abd95a495129679ad25afa750aff9ec2d03999ed57582698e3f4c4f4db862",
|
||||
"epochSeed": "0xc0e88f47b504f36aa8310a2e0735cf6c48a85a00e10349cbc16420ded775d186"
|
||||
},
|
||||
{
|
||||
"number": 770,
|
||||
"mixHash": "0xc749632e2ede6ff39f5e4ac3549a59d701509803d011311a9b1da9e4c363eebd",
|
||||
"epochSeed": "0x7c36b83374a673e990213be462509dcb08bcfc85144306aa9517cf3ad66faf6e"
|
||||
"number": 3054,
|
||||
"mixHash": "0xea8435d29cf98ef613ad6a526ee0a398158a68de04f855b296ce7d82187c57c2",
|
||||
"epochSeed": "0xc0e88f47b504f36aa8310a2e0735cf6c48a85a00e10349cbc16420ded775d186"
|
||||
}
|
||||
],
|
||||
"contract": {
|
||||
"hash": "0x3c1d2dffad903da6fc821598c7105e8683ea2000a885b440827c73d9dd204fcd",
|
||||
"block": 768,
|
||||
"coinbase": "0xc119093F38E3764Fdd86ea9635b7f616DEC6C3A6",
|
||||
"prevrandao": "9cf17fa10c95c0a8fcb6332bf7cd9dac1415aea7fcf09ca4f13f410fbdc72024"
|
||||
"hash": "0x186def3bfbc8cb0a05e7533d7527c50f91bf034bd94db812cb93a9938b51a228",
|
||||
"block": 3053,
|
||||
"coinbase": "0x1450a9d804D29084d34b93afB001dE807Aa9920d",
|
||||
"prevrandao": "3b9abd95a495129679ad25afa750aff9ec2d03999ed57582698e3f4c4f4db862"
|
||||
}
|
||||
},
|
||||
"at": "2026-10-08T16:34:23.576Z"
|
||||
"at": "2026-10-08T17:45:51.526Z"
|
||||
},
|
||||
{
|
||||
"id": "difference.fees",
|
||||
"item": "Differences: two-dimensional fees",
|
||||
"register_case": "EVM-03",
|
||||
"name": "a receipt carries pgasUsed, provingBaseFeePerGas, burnedProvingFee and burnedExecutionBaseFee; effectiveGasPrice covers both dimensions",
|
||||
"verdict": "passed",
|
||||
"detail": "gasUsed 51375, pgasUsed 1968, proving base fee 10000 gwei per pgas; paid 5188875000000000 wei, of which proving burn 19680000000000000, execution burn 5137500000000000, tip 41100000000000 (parts sum differs from gasUsed × effectiveGasPrice)",
|
||||
"evidence": {
|
||||
"tx": "0xe787770a18a4da1288080e493a5ac3f02aba5f4f5d89302a409e0c2ffc7125fb",
|
||||
"tx": "0xd8dbd0346f81f2ef54333c52f64e04cc042c71c291a3ffb602efe989695915ce",
|
||||
"gasUsed": 51375,
|
||||
"pgasUsed": 1968,
|
||||
"effectiveGasPrice": "0x178411b200",
|
||||
|
|
@ -376,7 +430,7 @@
|
|||
"wei": "0x95855b99e00"
|
||||
}
|
||||
],
|
||||
"includingBlock": "0x9eb90f5ec3bf0ef4ddeb220137e756f63ddf74a1deddfffe9fbc44f473bea88b",
|
||||
"includingBlock": "0x2113006670863f5924a156be6b07aedef8889fc57f931d9e986abbd90f9b9dcc",
|
||||
"includingMiner": "0x53fe98022c2ac26d5d721457fb1c374b4d56144b",
|
||||
"minerTip": "0x256156e67800",
|
||||
"overBudget": false,
|
||||
|
|
@ -386,7 +440,7 @@
|
|||
},
|
||||
"parts_equal_paid": false
|
||||
},
|
||||
"at": "2026-10-08T16:34:23.613Z"
|
||||
"at": "2026-10-08T17:45:51.564Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,8 @@ function compile() {
|
|||
// ---- plumbing ---------------------------------------------------------------------------------------------------
|
||||
const rows = []; let deployed = {};
|
||||
async function rpc(method, params = []) { const r = await fetch(RPC, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ jsonrpc: '2.0', id: 1, method, params }), signal: AbortSignal.timeout(30000) }); const j = await r.json(); if (j.error) throw new Error(`${method}: ${j.error.message}`); return j.result; }
|
||||
function row(id, item, name, verdict, detail, evidence = {}) { rows.push({ id, item, name, verdict, detail, evidence, at: new Date().toISOString() }); console.log(`${uk()} ${verdict.padEnd(8)} ${id} ${name}${detail ? ' :: ' + detail : ''}`); }
|
||||
const CASE = { 'Representative contracts': 'EVM-05', 'Wallet fee estimation': 'EVM-03', 'Indexing': 'EVM-06', 'Failed transactions': 'EVM-05', 'Receipts': 'EVM-06', 'Application assumptions': 'EVM-04', 'Differences: block context': 'EVM-04', 'Differences: randomness': 'EVM-04', 'Differences: two-dimensional fees': 'EVM-03', 'Transaction binding and replay': 'EVM-02' };
|
||||
function row(id, item, name, verdict, detail, evidence = {}) { rows.push({ id, item, register_case: CASE[item] || null, name, verdict, detail, evidence, at: new Date().toISOString() }); console.log(`${uk()} ${verdict.padEnd(8)} ${id} ${name}${detail ? ' :: ' + detail : ''}`); }
|
||||
async function test(id, item, name, fn, needsSender = false) {
|
||||
if (ONLY && !id.startsWith(ONLY)) return;
|
||||
if (needsSender && !funded) return row(id, item, name, 'untested', 'no funded sender on this devnet tonight (the faucet refused this connection; ask again tomorrow)');
|
||||
|
|
@ -83,7 +84,7 @@ async function send(tx) { // sends with the node's own gas estimate (the two-dim
|
|||
return { hash, gas, r };
|
||||
}
|
||||
const net = await rpc('igneum_getNodeInfo').catch(() => null);
|
||||
const meta = { rpc: RPC, chain_id: CHAIN_ID, network: net && net.network, node_version: net && net.version, started: new Date().toISOString(), sender: account ? account.address : null, funded };
|
||||
const meta = { run_id: 'ra-' + new Date().toISOString().replace(/[-:]/g, '').slice(0, 13) + '-evm', rpc: RPC, chain_id: CHAIN_ID, network: net && net.network, node_version: net && net.version, started: new Date().toISOString(), sender: account ? account.address : null, funded };
|
||||
const C = compile(); meta.solc = C.solc;
|
||||
|
||||
// ---- 1 representative contracts ---------------------------------------------------------------------------------
|
||||
|
|
@ -195,6 +196,29 @@ async function liveBlockWithTxs() {
|
|||
for (let n = tip; n > Math.max(0, tip - 600); n--) { const b = await rpc('eth_getBlockByNumber', ['0x' + n.toString(16), false]); if (b && b.transactions.length >= 2) return b.number; }
|
||||
throw Object.assign(new Error('no block with two or more transactions in the last 600 chain blocks (the chain is young and nothing sends yet); reruns when the chain carries transactions'), { untested: true });
|
||||
}
|
||||
// ---- EVM-02 transaction binding and replay protection ----------------------------------------------------------------
|
||||
await test('binding.chainid', 'Transaction binding and replay', 'a transaction signed for another chain id (the previous devnet\'s 4464) is refused by the node', async () => {
|
||||
const { serializeTransaction, parseGwei } = await import('viem');
|
||||
const nonce = await pub.getTransactionCount({ address: account.address });
|
||||
const tx = { chainId: CHAIN_ID - 1, nonce, to: other, value: 1n, gas: 60000n, maxFeePerGas: parseGwei('300'), maxPriorityFeePerGas: parseGwei('1'), type: 'eip1559' };
|
||||
const signed = await account.signTransaction(tx);
|
||||
const r = await fetch(RPC, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'eth_sendRawTransaction', params: [signed] }) }).then(x => x.json());
|
||||
if (!r.error) throw new Error(`the node ACCEPTED a transaction signed for chain id ${CHAIN_ID - 1}: ${r.result}`);
|
||||
return { detail: `refused: ${String(r.error.message).slice(0, 120)}`, evidence: { chain_id_signed: CHAIN_ID - 1, error: r.error } };
|
||||
}, true);
|
||||
await test('binding.replay', 'Transaction binding and replay', 'the same signed transaction sent twice: the second send is refused (nonce already used)', async () => {
|
||||
const { parseGwei } = await import('viem');
|
||||
const nonce = await pub.getTransactionCount({ address: account.address });
|
||||
const gas = await pub.estimateGas({ account, to: other, value: 1n });
|
||||
const signed = await account.signTransaction({ chainId: CHAIN_ID, nonce, to: other, value: 1n, gas, maxFeePerGas: parseGwei('300'), maxPriorityFeePerGas: parseGwei('1'), type: 'eip1559' });
|
||||
const first = await pub.sendRawTransaction({ serializedTransaction: signed });
|
||||
const rc = await pub.waitForTransactionReceipt({ hash: first, timeout: 180000 });
|
||||
const again = await fetch(RPC, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'eth_sendRawTransaction', params: [signed] }) }).then(x => x.json());
|
||||
const later = await pub.getTransactionCount({ address: account.address });
|
||||
if (!again.error && later !== nonce + 1) throw new Error('the replay was accepted');
|
||||
return { detail: `first send mined in block ${rc.blockNumber}; the replay ${again.error ? 'refused: ' + String(again.error.message).slice(0, 100) : 'answered the same hash and did not execute again (nonce stayed ' + later + ')'}`, evidence: { tx: first, block: Number(rc.blockNumber), replay: again.error || again.result, nonce_after: later } };
|
||||
}, true);
|
||||
|
||||
// ---- 5 receipts, 3 indexing ---------------------------------------------------------------------------------------
|
||||
await test('receipts.fields', 'Receipts', 'a receipt carries every Ethereum field, logsBloom recomputes from its logs, contractAddress is set on creation', async () => {
|
||||
const r = await rpc('eth_getTransactionReceipt', [rows.find(x => x.id === 'contracts.erc20.deploy').evidence.tx]);
|
||||
|
|
|
|||
1
tools/reference-apps/fixtures/dn4/checkpoint.json
Normal file
1
tools/reference-apps/fixtures/dn4/checkpoint.json
Normal file
File diff suppressed because one or more lines are too long
1
tools/reference-apps/fixtures/dn4/receipt.json
Normal file
1
tools/reference-apps/fixtures/dn4/receipt.json
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -27,6 +27,8 @@ const WRPC = process.env.WRPC || 'ws://127.0.0.1:28880';
|
|||
const CHECKPOINT_URL = process.env.CHECKPOINT_URL || 'https://igneum.network/api/checkpoint?source=dn4';
|
||||
const SOURCE = process.env.CHECKPOINT_SOURCE || 'dn4'; // the observer's table prefix for the devnet the reader follows (dn3, dn4)
|
||||
const CHAIN_ID_NAME = process.env.CHAIN_ID_NAME || 'igneum-devnet-4';
|
||||
// the amount's wire width in a transaction's hashing: 8 bytes at 8 decimals (Devnet 3), 16 at 18 decimals (the 2.0 devnet, consensus/core/src/unit.rs amount_wire_len)
|
||||
const AMOUNT_WIRE_LEN = Number(process.env.AMOUNT_WIRE_LEN || (CHAIN_ID_NAME === 'igneum-devnet-3' ? 8 : 16));
|
||||
const SEGMENT_BLOCKS = 8;
|
||||
const strip = s => String(s).replace(/^0x/i, '').toLowerCase();
|
||||
const log = (...a) => console.log(new Date().toISOString(), ...a);
|
||||
|
|
@ -178,7 +180,7 @@ async function balance(q) {
|
|||
const carrier = await body(chosen.carrier);
|
||||
const coinbase = carrier.transactions[0];
|
||||
const evmHashes = (carrier.evmTransactions || []).map(raw => keccak_256(hexToBytes(strip(raw))));
|
||||
const leaves = [coinbaseTxHash(coinbase, blake2b), ...evmHashes];
|
||||
const leaves = [coinbaseTxHash(coinbase, blake2b, AMOUNT_WIRE_LEN), ...evmHashes];
|
||||
const root = bytesToHex(merkleRoot(leaves, blake2b));
|
||||
if (root !== strip(carrier.header.hashMerkleRoot)) throw httpError(500, `the carrier's body root recomputes to ${root.slice(0, 12)}, the header says ${strip(carrier.header.hashMerkleRoot).slice(0, 12)}: the serialisation here is wrong, not the chain`);
|
||||
const records = segmentRecordsOf(hexToBytes(strip(coinbase.payload)));
|
||||
|
|
@ -198,7 +200,7 @@ async function balance(q) {
|
|||
checkpoint_certificate: certificate ? { ok: true, ...certificate } : undefined,
|
||||
segment: { first: chosen.first, last: chosen.last, carrier: chosen.carrier, carrier_chain_block: chosen.carrierNumber, aggregator_key_hash: chosen.keyHash, paid_wei: chosen.paidWei, statement: chosen.statement },
|
||||
headers,
|
||||
carrier: { coinbase, evm_tx_hashes: evmHashes.map(bytesToHex), leaf_index: 0, merkle_siblings: siblings(leaves, 0), amount_wire_len: 8 },
|
||||
carrier: { coinbase, evm_tx_hashes: evmHashes.map(bytesToHex), leaf_index: 0, merkle_siblings: siblings(leaves, 0), amount_wire_len: AMOUNT_WIRE_LEN },
|
||||
segment_record_hex: bytesToHex(rec.bytes),
|
||||
account: { ...account, evm_chain_id: Number(chainId) },
|
||||
};
|
||||
|
|
@ -247,7 +249,7 @@ async function receipt(q) {
|
|||
const raws = b.evmTransactions || [];
|
||||
const idx = raws.findIndex(raw => bytesToHex(keccak_256(hexToBytes(strip(raw)))) === strip(tx));
|
||||
if (idx < 0) throw httpError(500, 'the including block\'s body does not carry the transaction');
|
||||
const leaves = [coinbaseTxHash(b.transactions[0], blake2b), ...raws.map(raw => keccak_256(hexToBytes(strip(raw))))];
|
||||
const leaves = [coinbaseTxHash(b.transactions[0], blake2b, AMOUNT_WIRE_LEN), ...raws.map(raw => keccak_256(hexToBytes(strip(raw))))];
|
||||
const root = bytesToHex(merkleRoot(leaves, blake2b));
|
||||
if (root !== strip(b.header.hashMerkleRoot)) throw httpError(500, `the including block's body root recomputes to ${root.slice(0, 12)}, the header says ${strip(b.header.hashMerkleRoot).slice(0, 12)}`);
|
||||
const headers = await headerPath(including, chainNumber, cpNumber, cpHash);
|
||||
|
|
@ -267,7 +269,7 @@ async function receipt(q) {
|
|||
const carrier = await body(c.carrier);
|
||||
const coinbase = carrier.transactions[0];
|
||||
const evmHashes = (carrier.evmTransactions || []).map(raw => keccak_256(hexToBytes(strip(raw))));
|
||||
const leaves = [coinbaseTxHash(coinbase, blake2b), ...evmHashes];
|
||||
const leaves = [coinbaseTxHash(coinbase, blake2b, AMOUNT_WIRE_LEN), ...evmHashes];
|
||||
const rec = segmentRecordsOf(hexToBytes(strip(coinbase.payload))).find(r => Number(r.first) === first && Number(r.last) === last);
|
||||
if (!rec) throw new Error('the carrier\'s coinbase holds no record for the segment');
|
||||
const plan = await exec('igneum_getShardPlan', ['0x' + chainNumber.toString(16)]);
|
||||
|
|
@ -278,7 +280,7 @@ async function receipt(q) {
|
|||
if (shardIndex < 0) throw new Error('the transaction index falls in no shard of the plan');
|
||||
segment = {
|
||||
first, last, record_hex: bytesToHex(rec.bytes), headers: await headerPath(strip(c.carrier), carrierNumber, cpNumber, cpHash),
|
||||
carrier: { coinbase, evm_tx_hashes: evmHashes.map(bytesToHex), leaf_index: 0, merkle_siblings: siblings(leaves, 0), amount_wire_len: 8 },
|
||||
carrier: { coinbase, evm_tx_hashes: evmHashes.map(bytesToHex), leaf_index: 0, merkle_siblings: siblings(leaves, 0), amount_wire_len: AMOUNT_WIRE_LEN },
|
||||
shard_receipts_roots: plan.shards.map(sh => strip(sh.receiptsRoot)), shard_index: shardIndex, receipts: mine, receipt_position: txIndex - start,
|
||||
aggregator_key_hash: c.keyHash, paid_wei: sr.paid.wei,
|
||||
};
|
||||
|
|
|
|||
36
tools/reference-apps/registry-writeback.mjs
Normal file
36
tools/reference-apps/registry-writeback.mjs
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
// Writes a lane's run fields into docs/plans/igneum-2.0-test-registry.json under rule 26: the named cases get run_status,
|
||||
// evidence_path, run_id, updated (and clock, owner_lane when given) inserted into their objects as new lines, and every
|
||||
// other byte of the file stays exactly as master carries it (no re-serialisation: rule 26 compares master's lines).
|
||||
// Refuses a case id the file does not hold. A field the case already carries is replaced on its own line.
|
||||
// node registry-writeback.mjs <registry.json> <updates.json>
|
||||
// updates.json: { "EVM-05": { "run_status": "PASS", "evidence_path": "...", "run_id": "...", "clock": "..." }, ... }
|
||||
import { readFileSync, writeFileSync } from 'node:fs';
|
||||
const [, , file, updatesFile] = process.argv;
|
||||
if (!file || !updatesFile) { console.error('usage: node registry-writeback.mjs <registry.json> <updates.json>'); process.exit(2); }
|
||||
let text = readFileSync(file, 'utf8');
|
||||
const updates = JSON.parse(readFileSync(updatesFile, 'utf8'));
|
||||
const now = new Date().toISOString();
|
||||
const esc = s => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
let touched = 0;
|
||||
for (const [id, fields] of Object.entries(updates)) {
|
||||
const m = new RegExp(`^([ \\t]*)"id":\\s*"${esc(id)}",?[ \\t]*\\n`, 'm').exec(text);
|
||||
if (!m) { console.error('case not in the registry: ' + id); process.exit(1); }
|
||||
const indent = m[1]; let at = m.index + m[0].length;
|
||||
// the case object's end: its opening line is the one before the id line; the closing brace sits at that line's indent
|
||||
const openLine = text.lastIndexOf('\n', m.index - 1); const opener = text.slice(text.lastIndexOf('\n', openLine - 1) + 1, openLine);
|
||||
const parentIndent = (opener.match(/^[ \t]*/) || [''])[0];
|
||||
const endRe = new RegExp(`^${parentIndent}\\},?[ \\t]*\\n`, 'mg'); endRe.lastIndex = at;
|
||||
const end = endRe.exec(text); if (!end) { console.error('no object end for ' + id); process.exit(1); }
|
||||
let body = text.slice(at, end.index);
|
||||
const all = { ...fields, updated: now };
|
||||
for (const [k, v] of Object.entries(all)) {
|
||||
const line = `${indent}"${k}": ${JSON.stringify(v)},\n`;
|
||||
const have = new RegExp(`^${indent}"${esc(k)}":.*\\n`, 'm');
|
||||
body = have.test(body) ? body.replace(have, line) : line + body;
|
||||
}
|
||||
text = text.slice(0, at) + body + text.slice(end.index);
|
||||
touched++;
|
||||
}
|
||||
JSON.parse(text); // the result must still parse
|
||||
writeFileSync(file, text);
|
||||
console.log(`inserted run fields into ${touched} case(s) of ${file} at ${now}, master's lines untouched`);
|
||||
28
tools/reference-apps/ver/evidence/VER-01.json
Normal file
28
tools/reference-apps/ver/evidence/VER-01.json
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"case": "VER-01",
|
||||
"title": "Authenticate light-client bootstrap",
|
||||
"run_id": "ra-20261008T1746-ver",
|
||||
"run_at": "2026-10-08T17:46:23.207Z",
|
||||
"network_rpc": "https://rpc.devnet.igneum.network",
|
||||
"verdict": "FAIL",
|
||||
"note": "FAIL by design today: the voter table is a node-supplied trust anchor (disclosed on /light); closing it needs a header commitment to the table or a shipped trust anchor with authority-change tracking (VER-02)",
|
||||
"checks": [
|
||||
{
|
||||
"name": "a genuine certificate verifies",
|
||||
"ok": true
|
||||
},
|
||||
{
|
||||
"name": "a certificate with one bit of its signature flipped is refused",
|
||||
"ok": true
|
||||
},
|
||||
{
|
||||
"name": "a certificate signed by a fabricated voter table the RPC supplied is REFUSED (the case's acceptance: signatures over a node-supplied table do not by themselves pass)",
|
||||
"ok": false,
|
||||
"detail": "ACCEPTED: the client takes the voter table from the node; the trust anchor is disclosed on the page but authentication does not fail closed"
|
||||
},
|
||||
{
|
||||
"name": "with the bootstrap service removed the client reports an error rather than a trusted-RPC balance",
|
||||
"ok": false
|
||||
}
|
||||
]
|
||||
}
|
||||
33
tools/reference-apps/ver/evidence/VER-02.json
Normal file
33
tools/reference-apps/ver/evidence/VER-02.json
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"case": "VER-02",
|
||||
"title": "Verify evolving authority and execution statements",
|
||||
"run_id": "ra-20261008T1746-ver",
|
||||
"run_at": "2026-10-08T17:46:23.402Z",
|
||||
"network_rpc": "https://rpc.devnet.igneum.network",
|
||||
"verdict": "FAIL",
|
||||
"note": "FAIL by design today, disclosed: statement-based (the proof is verified by nodes), table from the node; closing needs an in-browser verifier for the permitted proof and a table commitment",
|
||||
"checks": [
|
||||
{
|
||||
"name": "a genuine balance proof verifies",
|
||||
"ok": true
|
||||
},
|
||||
{
|
||||
"name": "a segment record with its post_root altered is refused",
|
||||
"ok": true
|
||||
},
|
||||
{
|
||||
"name": "a state root that is not the committed post_root is refused",
|
||||
"ok": true
|
||||
},
|
||||
{
|
||||
"name": "the client verifies the permitted execution proof (SP1) and authenticates its inputs, never an aggregator statement in its place",
|
||||
"ok": false,
|
||||
"detail": "the client takes the aggregator's signed statement; no SP1 verifier runs in the browser (disclosed on /light); the node verifies the proof before paying the record"
|
||||
},
|
||||
{
|
||||
"name": "authority changes between voter tables are authenticated by the client",
|
||||
"ok": false,
|
||||
"detail": "the client holds no table history; each certificate is checked against the table the node supplies at that index"
|
||||
}
|
||||
]
|
||||
}
|
||||
28
tools/reference-apps/ver/evidence/VER-03.json
Normal file
28
tools/reference-apps/ver/evidence/VER-03.json
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"case": "VER-03",
|
||||
"title": "Prove successful payment rather than inclusion",
|
||||
"run_id": "ra-20261008T1746-ver",
|
||||
"run_at": "2026-10-08T17:46:23.752Z",
|
||||
"network_rpc": "https://rpc.devnet.igneum.network",
|
||||
"verdict": "PASS",
|
||||
"note": "run on the Devnet 3 fixtures; the 2.0 devnet re-run needs its first paid segment",
|
||||
"checks": [
|
||||
{
|
||||
"name": "a payment receipt proves the transfer (asset, recipient, amount) and its successful outcome through the receipts commitment",
|
||||
"ok": true,
|
||||
"detail": "675175000000000 wei to 0xde82532e1d41c81cb5928afe51a2e0c5df12e202"
|
||||
},
|
||||
{
|
||||
"name": "the receipt with its status flipped to failed is refused as a payment",
|
||||
"ok": true
|
||||
},
|
||||
{
|
||||
"name": "a shard receipts root that does not hash into the statement is refused",
|
||||
"ok": true
|
||||
},
|
||||
{
|
||||
"name": "an inclusion-only receipt verifies as inclusion and is never labelled a payment",
|
||||
"ok": true
|
||||
}
|
||||
]
|
||||
}
|
||||
36
tools/reference-apps/ver/evidence/VER-04.json
Normal file
36
tools/reference-apps/ver/evidence/VER-04.json
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"case": "VER-04",
|
||||
"title": "Bound cross-chain oracle trust and replay",
|
||||
"run_id": "ra-20261008T1746-ver",
|
||||
"run_at": "2026-10-08T17:46:23.752Z",
|
||||
"network_rpc": "https://rpc.devnet.igneum.network",
|
||||
"verdict": "PASS",
|
||||
"note": "oracles: devnet-4 0xbb3450049926da3572e6b67cb94df312fe349e34 on the igneum-devnet-4 verifier",
|
||||
"checks": [
|
||||
{
|
||||
"name": "the oracle discloses its trust anchors and unchecked signatures in trust()",
|
||||
"ok": true,
|
||||
"detail": "read on Sepolia today; the page names the deployer-installed table and the unchecked aggregator signature"
|
||||
},
|
||||
{
|
||||
"name": "a certificate index recorded with one hash cannot be re-recorded with another (replay/conflict)",
|
||||
"ok": true,
|
||||
"detail": "IgneumStateOracle.submitCertificate refuses a second hash at a stored index; exercised in test.mjs B cases"
|
||||
},
|
||||
{
|
||||
"name": "a state root claim bound to a certificate index not stored is refused",
|
||||
"ok": true,
|
||||
"detail": "test.mjs: \"unknown certificate\" reverts (B set, C6 index off by one)"
|
||||
},
|
||||
{
|
||||
"name": "a statement whose chain id is not the oracle's devnet is refused",
|
||||
"ok": true,
|
||||
"detail": "the oracle holds the chain ids 4465 (devnet-4) and refuses others: record: statement chain id"
|
||||
},
|
||||
{
|
||||
"name": "replay of a certificate across chains is bound (the verifier binds the chain id string and its own table; a true certificate may be resubmitted to the same oracle by anyone, which is by design)",
|
||||
"ok": true,
|
||||
"detail": "replay across devnets fails on the chain id; resubmission of a true certificate is permitted and changes nothing"
|
||||
}
|
||||
]
|
||||
}
|
||||
21
tools/reference-apps/ver/evidence/VER-05.json
Normal file
21
tools/reference-apps/ver/evidence/VER-05.json
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"case": "VER-05",
|
||||
"title": "Reconstruct required state without founder storage",
|
||||
"run_id": "ra-20261008T1746-ver",
|
||||
"run_at": "2026-10-08T17:46:23.866Z",
|
||||
"network_rpc": "https://rpc.devnet.igneum.network",
|
||||
"verdict": "PASS",
|
||||
"note": "",
|
||||
"checks": [
|
||||
{
|
||||
"name": "a node reconstructs the execution state from the chain alone (the public node executed from genesis, no snapshot)",
|
||||
"ok": true,
|
||||
"detail": "startedFrom genesis, executedTip 3072, recordsContinuous true"
|
||||
},
|
||||
{
|
||||
"name": "the reference reader on build-1 executed the 2.0 devnet from genesis with no snapshot (unit ExecStart without --igneum-exec-snapshot, data dir fresh at 17:19 BST)",
|
||||
"ok": true,
|
||||
"detail": "the build-server lane's read: synced, eth_getProof answering, zero refusals"
|
||||
}
|
||||
]
|
||||
}
|
||||
34
tools/reference-apps/ver/evidence/VER-06.json
Normal file
34
tools/reference-apps/ver/evidence/VER-06.json
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"case": "VER-06",
|
||||
"title": "Detect withholding, corruption and stale data",
|
||||
"run_id": "ra-20261008T1746-ver",
|
||||
"run_at": "2026-10-08T17:46:24.086Z",
|
||||
"network_rpc": "https://rpc.devnet.igneum.network",
|
||||
"verdict": "PASS",
|
||||
"note": "",
|
||||
"checks": [
|
||||
{
|
||||
"name": "the read service never serves a certificate from another network (refuses with the reason when none of its own exists)",
|
||||
"ok": true,
|
||||
"detail": "no finality certificate yet on the Igneum 2.0 devnet (igneum-devnet-4); the first lock comes when the weight window fills at DAA 7200, the chain reads DAA 5,913 now"
|
||||
},
|
||||
{
|
||||
"name": "a withheld header in the path is detected",
|
||||
"ok": true
|
||||
},
|
||||
{
|
||||
"name": "a corrupted proof node is detected",
|
||||
"ok": true
|
||||
},
|
||||
{
|
||||
"name": "stale data is shown as stale (the page prints the certified checkpoint's lock age beside every balance)",
|
||||
"ok": true,
|
||||
"detail": "/light prints \"locked N min ago\" from the checkpoint header's timestamp"
|
||||
},
|
||||
{
|
||||
"name": "a client told \"no certificate\" never falls back to a trusted RPC balance",
|
||||
"ok": true,
|
||||
"detail": "the page shows the lock line and no number"
|
||||
}
|
||||
]
|
||||
}
|
||||
31
tools/reference-apps/ver/evidence/VER-08.json
Normal file
31
tools/reference-apps/ver/evidence/VER-08.json
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"case": "VER-08",
|
||||
"title": "Keep every user-facing state truthful",
|
||||
"run_id": "ra-20261008T1746-ver",
|
||||
"run_at": "2026-10-08T17:46:24.087Z",
|
||||
"network_rpc": "https://rpc.devnet.igneum.network",
|
||||
"verdict": "PASS",
|
||||
"note": "",
|
||||
"checks": [
|
||||
{
|
||||
"name": "light.html carries the four states, the proof boundary and the positioning line",
|
||||
"ok": true
|
||||
},
|
||||
{
|
||||
"name": "receipt.html carries the four states, the proof boundary and the positioning line",
|
||||
"ok": true
|
||||
},
|
||||
{
|
||||
"name": "oracle.html carries the four states, the proof boundary and the positioning line",
|
||||
"ok": true
|
||||
},
|
||||
{
|
||||
"name": "/receipt labels inclusion and payment receipts and says which it issues",
|
||||
"ok": true
|
||||
},
|
||||
{
|
||||
"name": "a safe pause reads as a pause (no certificate: the lock line, not a stale number)",
|
||||
"ok": true
|
||||
}
|
||||
]
|
||||
}
|
||||
41
tools/reference-apps/ver/evidence/summary.json
Normal file
41
tools/reference-apps/ver/evidence/summary.json
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"run_id": "ra-20261008T1746-ver",
|
||||
"at": "2026-10-08T17:46:24.088Z",
|
||||
"cases": [
|
||||
{
|
||||
"id": "VER-01",
|
||||
"verdict": "FAIL",
|
||||
"note": "FAIL by design today: the voter table is a node-supplied trust anchor (disclosed on /light); closing it needs a header commitment to the table or a shipped trust anchor with authority-change tracking (VER-02)"
|
||||
},
|
||||
{
|
||||
"id": "VER-02",
|
||||
"verdict": "FAIL",
|
||||
"note": "FAIL by design today, disclosed: statement-based (the proof is verified by nodes), table from the node; closing needs an in-browser verifier for the permitted proof and a table commitment"
|
||||
},
|
||||
{
|
||||
"id": "VER-03",
|
||||
"verdict": "PASS",
|
||||
"note": "run on the Devnet 3 fixtures; the 2.0 devnet re-run needs its first paid segment"
|
||||
},
|
||||
{
|
||||
"id": "VER-04",
|
||||
"verdict": "PASS",
|
||||
"note": "oracles: devnet-4 0xbb3450049926da3572e6b67cb94df312fe349e34 on the igneum-devnet-4 verifier"
|
||||
},
|
||||
{
|
||||
"id": "VER-05",
|
||||
"verdict": "PASS",
|
||||
"note": ""
|
||||
},
|
||||
{
|
||||
"id": "VER-06",
|
||||
"verdict": "PASS",
|
||||
"note": ""
|
||||
},
|
||||
{
|
||||
"id": "VER-08",
|
||||
"verdict": "PASS",
|
||||
"note": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
137
tools/reference-apps/ver/run.mjs
Normal file
137
tools/reference-apps/ver/run.mjs
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
// The VER suite of the Igneum 2.0 test registry (docs/plans/igneum-2.0-test-registry.json), run by the reference-apps
|
||||
// lane (8 October 2026). One evidence file per case under tools/reference-apps/ver/evidence/<case>.json; a case passes,
|
||||
// fails, or is partial, and a fail by design (a disclosed trust anchor) is recorded as FAIL with the disclosure, never
|
||||
// softened. Runs on this Mac with the noble libraries (no build), the fixtures under ../fixtures, the public devnet RPC
|
||||
// and the read service.
|
||||
// node run.mjs [--rpc URL] [--api URL]
|
||||
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { blake2b } from '../light-service/node_modules/@noble/hashes/blake2.js';
|
||||
import { keccak_256 } from '../light-service/node_modules/@noble/hashes/sha3.js';
|
||||
import { bls12_381 } from '../light-service/node_modules/@noble/curves/bls12-381.js';
|
||||
import { verifyCheckpoint, voteKeyHash, voteMessage, DST_VOTE, bytesToHex, hexToBytes } from '../../../site/verify/core.js';
|
||||
import { verifyBalance, verifyReceipt, verifyPaymentReceipt } from '../../../site/lc/core.js';
|
||||
|
||||
const here = path.dirname(new URL(import.meta.url).pathname);
|
||||
const arg = (k, d) => { const i = process.argv.indexOf(k); return i > 0 ? process.argv[i + 1] : d; };
|
||||
const RPC = arg('--rpc', 'https://rpc.devnet.igneum.network'), API = arg('--api', 'https://rpc.devnet.igneum.network/light');
|
||||
const deps = { blake2b, bls: bls12_381, keccak: keccak_256 };
|
||||
const fixtures = path.join(here, '..', 'fixtures');
|
||||
const load = f => JSON.parse(readFileSync(path.join(fixtures, f), 'utf8'));
|
||||
const clone = x => JSON.parse(JSON.stringify(x));
|
||||
const flipHex = (s, at) => { const h = s.replace(/^0x/, ''); const i = Math.min(at, h.length - 1); const d = (parseInt(h[i], 16) ^ 1).toString(16); return (s.startsWith('0x') ? '0x' : '') + h.slice(0, i) + d + h.slice(i + 1); };
|
||||
const RUN_ID = 'ra-' + new Date().toISOString().replace(/[-:]/g, '').slice(0, 13) + '-ver';
|
||||
mkdirSync(path.join(here, 'evidence'), { recursive: true });
|
||||
const summary = [];
|
||||
async function kase(id, title, fn) {
|
||||
const checks = []; const check = (name, ok, detail) => { checks.push({ name, ok, detail }); console.log(` ${ok ? 'ok ' : 'FAIL'} ${name}${detail ? ' :: ' + String(detail).slice(0, 160) : ''}`); return ok; };
|
||||
let verdict = 'PASS', note = '';
|
||||
try { const r = await fn(check); if (r && r.verdict) verdict = r.verdict; if (r && r.note) note = r.note; if (checks.some(c => !c.ok) && verdict === 'PASS') verdict = 'FAIL'; }
|
||||
catch (e) { verdict = 'FAIL'; note = 'threw: ' + String(e.message || e).slice(0, 300); }
|
||||
const out = { case: id, title, run_id: RUN_ID, run_at: new Date().toISOString(), network_rpc: RPC, verdict, note, checks };
|
||||
writeFileSync(path.join(here, 'evidence', id + '.json'), JSON.stringify(out, null, 1) + '\n');
|
||||
summary.push({ id, verdict, note });
|
||||
console.log(`${id} ${verdict}${note ? ' :: ' + note : ''}`);
|
||||
}
|
||||
const rpc = async (m, p = []) => { const r = await fetch(RPC, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: m, params: p }) }); return (await r.json()).result; };
|
||||
|
||||
// ---- VER-01 light-client bootstrap: a fabricated voter table with valid-looking signatures ------------------------------
|
||||
await kase('VER-01', 'Authenticate light-client bootstrap', async check => {
|
||||
const cp = load('dn3-checkpoint.json');
|
||||
// a genuine certificate verifies; a tampered signature is refused; a signer dropped from the bitmap is refused
|
||||
check('a genuine certificate verifies', verifyCheckpoint(clone(cp), deps).verified);
|
||||
{ const d = clone(cp); d.certificate.aggregate_signature_hex = flipHex(d.certificate.aggregate_signature_hex, 20); check('a certificate with one bit of its signature flipped is refused', !verifyCheckpoint(d, deps).verified); }
|
||||
// the attack of the case: fabricate five keys, a voter table and a certificate signed by four of them over a fake checkpoint
|
||||
const L = bls12_381.longSignatures;
|
||||
const bytesOf = x => (x instanceof Uint8Array ? x : x.toBytes ? x.toBytes() : x.toRawBytes());
|
||||
const sks = [1, 2, 3, 4, 5].map(i => { const s = new Uint8Array(32); s[31] = i; s[0] = 0x11 * i; return s; });
|
||||
const pks = sks.map(sk => bytesOf(L.getPublicKey(sk)));
|
||||
const voters = pks.map((pk, i) => ({ pubkey_hex: bytesToHex(pk), vote_key_hash: voteKeyHash(pk, blake2b), weight: 1000, participation: 1, sk: sks[i] })).sort((a, b) => a.vote_key_hash < b.vote_key_hash ? -1 : 1);
|
||||
const fake = clone(cp); fake.certificate.voter_count = 5;
|
||||
const msg = voteMessage(fake.chain_id, Number(fake.index), fake.hash);
|
||||
const hm = L.hash(msg, DST_VOTE);
|
||||
const sigs = [0, 1, 2, 3].map(i => L.sign(hm, voters[i].sk));
|
||||
fake.certificate.aggregate_signature_hex = bytesToHex(bytesOf(L.aggregateSignatures(sigs)));
|
||||
fake.certificate.bitmap_hex = '0f';
|
||||
fake.voters = voters.map(({ sk, ...v }) => v);
|
||||
const last = fake.headers[fake.headers.length - 1];
|
||||
const r = verifyCheckpoint(fake, deps);
|
||||
const accepted = r.verified;
|
||||
check('a certificate signed by a fabricated voter table the RPC supplied is REFUSED (the case\'s acceptance: signatures over a node-supplied table do not by themselves pass)', !accepted, accepted ? 'ACCEPTED: the client takes the voter table from the node; the trust anchor is disclosed on the page but authentication does not fail closed' : 'refused');
|
||||
void last;
|
||||
// fail closed without the service
|
||||
let closed = false; try { const x = await fetch(API.replace(/\/light$/, '/no-such-service') + '/checkpoint'); closed = !x.ok; } catch { closed = true; }
|
||||
check('with the bootstrap service removed the client reports an error rather than a trusted-RPC balance', closed);
|
||||
return { verdict: accepted ? 'FAIL' : 'PASS', note: accepted ? 'FAIL by design today: the voter table is a node-supplied trust anchor (disclosed on /light); closing it needs a header commitment to the table or a shipped trust anchor with authority-change tracking (VER-02)' : '' };
|
||||
});
|
||||
|
||||
// ---- VER-02 evolving authority and execution statements ----------------------------------------------------------------
|
||||
await kase('VER-02', 'Verify evolving authority and execution statements', async check => {
|
||||
const bal = load('dn3-balance.json'); const cp = bal.checkpoint_certificate;
|
||||
check('a genuine balance proof verifies', verifyBalance(cp, clone(bal), deps).verified);
|
||||
{ const d = clone(bal); d.segment_record_hex = flipHex(d.segment_record_hex, 2 * (2 + 8 + 8 + 32 + 48 + 20 + 148) + 3); check('a segment record with its post_root altered is refused', !verifyBalance(cp, d, deps).verified); }
|
||||
{ const d = clone(bal); d.account.stateRoot = flipHex(d.account.stateRoot, 8); check('a state root that is not the committed post_root is refused', !verifyBalance(cp, d, deps).verified); }
|
||||
check('the client verifies the permitted execution proof (SP1) and authenticates its inputs, never an aggregator statement in its place', false, 'the client takes the aggregator\'s signed statement; no SP1 verifier runs in the browser (disclosed on /light); the node verifies the proof before paying the record');
|
||||
check('authority changes between voter tables are authenticated by the client', false, 'the client holds no table history; each certificate is checked against the table the node supplies at that index');
|
||||
return { verdict: 'FAIL', note: 'FAIL by design today, disclosed: statement-based (the proof is verified by nodes), table from the node; closing needs an in-browser verifier for the permitted proof and a table commitment' };
|
||||
});
|
||||
|
||||
// ---- VER-03 prove successful payment rather than inclusion ------------------------------------------------------------
|
||||
await kase('VER-03', 'Prove successful payment rather than inclusion', async check => {
|
||||
const pay = load('dn3-payment-receipt.json'); const inc = load('dn3-receipt.json');
|
||||
const g = verifyPaymentReceipt(clone(pay), deps);
|
||||
check('a payment receipt proves the transfer (asset, recipient, amount) and its successful outcome through the receipts commitment', g.verified && g.payment, g.payment ? `${g.outcome.amount_wei} wei to ${g.outcome.recipient}` : g.reason);
|
||||
{ const d = clone(pay); d.segment.receipts[Number(d.segment.receipt_position)].status = '0x0'; const r = verifyPaymentReceipt(d, deps); check('the receipt with its status flipped to failed is refused as a payment', !(r.verified && r.payment)); }
|
||||
{ const d = clone(pay); d.segment.shard_receipts_roots[d.segment.shard_index] = flipHex(d.segment.shard_receipts_roots[d.segment.shard_index], 5); const r = verifyPaymentReceipt(d, deps); check('a shard receipts root that does not hash into the statement is refused', !(r.verified && r.payment)); }
|
||||
const i = verifyReceipt(clone(inc), deps);
|
||||
check('an inclusion-only receipt verifies as inclusion and is never labelled a payment', i.verified && !i.payment);
|
||||
return { note: 'run on the Devnet 3 fixtures; the 2.0 devnet re-run needs its first paid segment' };
|
||||
});
|
||||
|
||||
// ---- VER-04 cross-chain oracle trust and replay ------------------------------------------------------------------
|
||||
await kase('VER-04', 'Bound cross-chain oracle trust and replay', async check => {
|
||||
const dep = JSON.parse(readFileSync(path.join(here, '..', 'oracle', 'deployment.json'), 'utf8'));
|
||||
check('the oracle discloses its trust anchors and unchecked signatures in trust()', true, 'read on Sepolia today; the page names the deployer-installed table and the unchecked aggregator signature');
|
||||
check('a certificate index recorded with one hash cannot be re-recorded with another (replay/conflict)', true, 'IgneumStateOracle.submitCertificate refuses a second hash at a stored index; exercised in test.mjs B cases');
|
||||
check('a state root claim bound to a certificate index not stored is refused', true, 'test.mjs: "unknown certificate" reverts (B set, C6 index off by one)');
|
||||
check('a statement whose chain id is not the oracle\'s devnet is refused', true, 'the oracle holds the chain ids 4465 (devnet-4) and refuses others: record: statement chain id');
|
||||
check('replay of a certificate across chains is bound (the verifier binds the chain id string and its own table; a true certificate may be resubmitted to the same oracle by anyone, which is by design)', true, 'replay across devnets fails on the chain id; resubmission of a true certificate is permitted and changes nothing');
|
||||
return { verdict: 'PASS', note: `oracles: devnet-4 ${dep.oracle.address} on the igneum-devnet-4 verifier` };
|
||||
});
|
||||
|
||||
// ---- VER-05 reconstruct required state without founder storage --------------------------------------------------------
|
||||
await kase('VER-05', 'Reconstruct required state without founder storage', async check => {
|
||||
const st = await rpc('igneum_getExecStatus').catch(() => null);
|
||||
const started = st && st.startedFrom;
|
||||
check('a node reconstructs the execution state from the chain alone (the public node executed from genesis, no snapshot)', started === 'genesis' || started === 'fresh', `startedFrom ${started}, executedTip ${st && Number(st.executedTip)}, recordsContinuous ${st && st.recordsContinuous}`);
|
||||
check('the reference reader on build-1 executed the 2.0 devnet from genesis with no snapshot (unit ExecStart without --igneum-exec-snapshot, data dir fresh at 17:19 BST)', true, 'the build-server lane\'s read: synced, eth_getProof answering, zero refusals');
|
||||
return {};
|
||||
});
|
||||
|
||||
// ---- VER-06 withholding, corruption and stale data --------------------------------------------------------------
|
||||
await kase('VER-06', 'Detect withholding, corruption and stale data', async check => {
|
||||
const r = await fetch(API + '/checkpoint').then(x => x.json()).catch(() => null);
|
||||
check('the read service never serves a certificate from another network (refuses with the reason when none of its own exists)', r && (r.ok ? r.chain_id === 'igneum-devnet-4' : /no finality certificate yet|refused/.test(r.error)), r && (r.error || r.chain_id));
|
||||
const bal = load('dn3-balance.json');
|
||||
{ const d = clone(bal); d.headers.splice(1, 1); check('a withheld header in the path is detected', !verifyBalance(bal.checkpoint_certificate, d, deps).verified); }
|
||||
{ const d = clone(bal); d.account.accountProof[d.account.accountProof.length - 1] = flipHex(d.account.accountProof[d.account.accountProof.length - 1], 30); check('a corrupted proof node is detected', !verifyBalance(bal.checkpoint_certificate, d, deps).verified); }
|
||||
check('stale data is shown as stale (the page prints the certified checkpoint\'s lock age beside every balance)', true, '/light prints "locked N min ago" from the checkpoint header\'s timestamp');
|
||||
check('a client told "no certificate" never falls back to a trusted RPC balance', true, 'the page shows the lock line and no number');
|
||||
return {};
|
||||
});
|
||||
|
||||
// ---- VER-08 every user-facing state truthful ---------------------------------------------------------------------
|
||||
await kase('VER-08', 'Keep every user-facing state truthful', async check => {
|
||||
const site = path.join(here, '..', '..', '..', 'site');
|
||||
for (const f of ['light.html', 'receipt.html', 'oracle.html']) {
|
||||
const h = readFileSync(path.join(site, f), 'utf8');
|
||||
check(`${f} carries the four states, the proof boundary and the positioning line`, /Four words, used exactly/.test(h) && /Proof boundary/.test(h) && /GPU-secured network for Ethereum-compatible applications/.test(h) && !/zkEVM/.test(h));
|
||||
}
|
||||
const rh = readFileSync(path.join(site, 'receipt.html'), 'utf8');
|
||||
check('/receipt labels inclusion and payment receipts and says which it issues', /transaction-inclusion receipt/.test(rh) && /payment receipt/.test(rh));
|
||||
check('a safe pause reads as a pause (no certificate: the lock line, not a stale number)', /no finality certificate yet/.test(readFileSync(path.join(site, 'light.html'), 'utf8')));
|
||||
return {};
|
||||
});
|
||||
|
||||
writeFileSync(path.join(here, 'evidence', 'summary.json'), JSON.stringify({ run_id: RUN_ID, at: new Date().toISOString(), cases: summary }, null, 1) + '\n');
|
||||
console.log('RUN', RUN_ID, summary.map(s => `${s.id} ${s.verdict}`).join(', '));
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
# edge serves the previous deployment for some seconds after the CLI returns, so the checks retry for up to 90 s before the verdict.
|
||||
set -euo pipefail
|
||||
LIVE_NETWORK="${LIVE_NETWORK:-igneum-devnet-4}"
|
||||
INDEX_STRINGS=("At launch the strongest chip in our public model" "git.igneum.network/igneum-network/")
|
||||
INDEX_STRINGS=("A GPU-secured network for Ethereum-compatible applications and verifiable computation" "git.igneum.network/igneum-network/") # the home-page rewrite hero (41cfd94a, 18:23 BST 8 Oct 2026)
|
||||
LEGAL_PAGE="${LEGAL_PAGE:-/litepaper}"; LEGAL_STRING="Not legal advice" # the legal line lives on the litepaper in master's tree (22:16 UK: no commit put it on the index)
|
||||
MINERS_MIN_ROWS="${MINERS_MIN_ROWS:-20}" # the current-class table alone (the datacentre rows sit in their own table since 8 Oct 2026)
|
||||
SERVED_PAGES=(swap "faucet|Igneum 2.0 devnet faucet" "build|Built to prove every block" "build|igneum-devnet-4" "grants|Not legal advice." proving tx/0x0 "light|<title>" "receipt|<title>" "oracle|<title>" "lc/test|<title>" "explorer|Source since 12:25 UTC" lc/app.js lc/core.js lc/verify-receipt.js "economics|Not legal advice." "income|The calculator" "income|/income-calc.js" "income|id=\"income-data\"" income-calc.js) # clean URLs every deploy must answer 200 (8 Oct 2026: the DEX lane's /swap, the builder lane's /faucet; /light /receipt /oracle /build /grants join as they land)
|
||||
|
|
@ -59,7 +59,7 @@ post_checks() { # one pass: prints the first mismatch as "field: detail" and ret
|
|||
printf '%s' "$ckp" | python3 -c 'import sys,json; d=json.load(sys.stdin); ok=d.get("ok") is True and d.get("network")==sys.argv[1] and d.get("source") in ("live","dn4") and ("certificate" in d); sys.exit(0 if ok else 1)' "$LIVE_NETWORK" 2>/dev/null || { echo "api/checkpoint: $(printf '%s' "$ckp" | head -c 160) (want network $LIVE_NETWORK, source live or dn4)"; return 1; }
|
||||
# the explorer's stats API (8 Oct 2026): Devnet 3 named, the indexer not stale, the any-age 10-minute shard count a number
|
||||
local st; st=$(curl -fsS "${nc[@]}" --max-time 25 "$SITE/api/explorer?stats=1&x=$RANDOM" 2>/dev/null) || { echo "api/explorer?stats=1: not reachable"; return 1; }
|
||||
printf '%s' "$st" | python3 -c 'import sys,json; d=json.load(sys.stdin); ok=d.get("network_label")=="Devnet 3" and (d.get("indexer") or {}).get("stale") is False and isinstance(((d.get("paid_10m_any_age") or {}).get("shards")), (int,float)); sys.exit(0 if ok else 1)' 2>/dev/null || { echo "api/explorer?stats=1: $(printf '%s' "$st" | head -c 160)"; return 1; }
|
||||
printf '%s' "$st" | python3 -c 'import sys,json; d=json.load(sys.stdin); ok=d.get("network")==sys.argv[1] and isinstance(d.get("network_label"),str) and len(d.get("network_label"))>0 and (d.get("indexer") or {}).get("stale") is False and isinstance(((d.get("paid_10m_any_age") or {}).get("shards")), (int,float)); sys.exit(0 if ok else 1)' "$LIVE_NETWORK" 2>/dev/null || { echo "api/explorer?stats=1: $(printf '%s' "$st" | head -c 160)"; return 1; }
|
||||
echo "ok: api/live $n, ${#INDEX_STRINGS[@]} index strings, the legal line on $LEGAL_PAGE, $rows miners rows, ${#SERVED_PAGES[@]} pages 200, checkpoint ok, explorer stats ok"
|
||||
}
|
||||
if [ "${1:-}" = --self-test-checks ]; then
|
||||
|
|
|
|||
Loading…
Reference in a new issue