Merge remote-tracking branch 'origin/master' into peer-directory
# Conflicts: # infra/fast-time/fork-gate.mjs # infra/fast-time/override-60x.json
29
docs/design/genesis-forward-harness/digest-base-dc141409.log
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
Latency ladder inactive (no activation in the override file): every class v4 program at rung 0, 27 shadow passes; no ladder bits in the header
|
||||
Program class signal inactive (the window or the floor is absent from the override file): headers carry block version 2 exactly
|
||||
Fees on igneum-devnet-973: pgas table v0, B_p 30000000 pgas, S_p 7500000 pgas, floors 1000000000 wei per gas and 1000000000 wei per pgas; calibrated v1 from DAA score never
|
||||
Consensus params digest: 079d8a7e736abbd4b135eb1d652466ca7906ea1b200e22eac97f795e626356e7 (exchanged in the p2p handshake; a peer with another digest is refused)
|
||||
2026-10-07 15:14:29.331+02:00 [INFO ] igneumd/2.1.0-dc141409
|
||||
2026-10-07 15:14:29.331+02:00 [INFO ] Application directory: gf-digest/d-base
|
||||
2026-10-07 15:14:29.331+02:00 [INFO ] Data directory: gf-digest/d-base/igneum-devnet-973/datadir
|
||||
2026-10-07 15:14:29.331+02:00 [INFO ] Logs to console only
|
||||
2026-10-07 15:14:29.350+02:00 [INFO ] Finality v2 (igneum-devnet-973): interval 30 depth 20 window 7200 DAA dust 5 presence 20 aggregators 8 ban 7200 fold 3; rule v3 (frozen table, certificate fold) from checkpoint DAA never; 0 checkpoints known, next index 1, 0 locks, 0 keys; C1 in DAA seconds from DAA never; weight-gated deep fork choice from DAA never; leave rule (W7, delay 3600 DAA) from checkpoint DAA never, 0 leaves
|
||||
2026-10-07 15:14:29.363+02:00 [INFO ] [igneum-exec] proving v0: payouts from DAA score never, window 7200 DAA, dust 5, verifier Off
|
||||
2026-10-07 15:14:29.363+02:00 [INFO ] [igneum-exec] proving v1: segment records from DAA score never, 8 blocks a segment, unproven after 600 DAA, aggregator share 1000 bps, shard program id unknown, aggregator id unknown
|
||||
2026-10-07 15:14:29.364+02:00 [INFO ] [igneum-exec] verifying keys embedded: shard program id 0x2b1a81cb413236cf063077b46ed3111628f6c41036bcf6e23ee4cbbf5679ef7a aggregator id 0x474678f35f7545db28055d5e5bbc308231d84a5a072202087a2a8d5b09123896
|
||||
2026-10-07 15:14:29.370+02:00 [INFO ] template prewarm: on (the cached block template is rebuilt on every virtual change; IGNEUM_TEMPLATE_PREWARM=0 turns it off)
|
||||
2026-10-07 15:14:29.371+02:00 [INFO ] GRPC Server starting on: 127.0.0.1:29770
|
||||
2026-10-07 15:14:29.372+02:00 [INFO ] P2P Server starting on: 127.0.0.1:29771
|
||||
2026-10-07 15:14:29.373+02:00 [INFO ] [igneum-exec] chain follower started
|
||||
2026-10-07 15:14:29.373+02:00 [INFO ] [igneum-exec] proof verifier: Off (no SP1 verification on this node)
|
||||
2026-10-07 15:14:29.373+02:00 [INFO ] [igneum-exec] exec sync: sink edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07 is chain block 0; pruning point edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07 is chain block Some(0) (DAA 0); retention root edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07 is chain block Some(0) (DAA 0), its body held
|
||||
2026-10-07 15:14:29.373+02:00 [INFO ] [igneum-exec] eth_ JSON-RPC listening on 127.0.0.1:26790
|
||||
2026-10-07 15:14:29.373+02:00 [INFO ] [igneum-exec] exec sync: no snapshot to resume from (no snapshot file); the follower starts at genesis
|
||||
2026-10-07 15:14:29.373+02:00 [INFO ] [igneum-exec] exec sync: waiting for consensus to sync before the executor starts (the sink is 393269 s old)
|
||||
2026-10-07 15:14:29.373+02:00 [WARN ] [igneum-exec] cannot bind the eth_ JSON-RPC server on 127.0.0.1:26790: Address already in use (os error 98)
|
||||
2026-10-07 15:14:29.374+02:00 [INFO ] WRPC Server starting on: 127.0.0.1:29772
|
||||
2026-10-07 15:14:29.474+02:00 [INFO ] [igneum-exec] chain follower stopped
|
||||
^SIGTERM - shutting down...
|
||||
2026-10-07 15:14:54.316+02:00 [INFO ] P2P Server stopped: 127.0.0.1:29771
|
||||
2026-10-07 15:14:54.316+02:00 [INFO ] WRPC Server stopped on: 127.0.0.1:29772
|
||||
2026-10-07 15:14:54.317+02:00 [INFO ] GRPC Server stopped on: 127.0.0.1:29770
|
||||
2026-10-07 15:14:54.824+02:00 [INFO ] igneumd has stopped...
|
||||
29
docs/design/genesis-forward-harness/digest-no-file.log
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
Latency ladder inactive (no activation in the override file): every class v4 program at rung 0, 27 shadow passes; no ladder bits in the header
|
||||
Program class signal inactive (the window or the floor is absent from the override file): headers carry block version 2 exactly
|
||||
Fees on igneum-devnet-973: pgas table v0, B_p 30000000 pgas, S_p 7500000 pgas, floors 1000000000 wei per gas and 1000000000 wei per pgas; calibrated v1 from DAA score never
|
||||
Consensus params digest: 079d8a7e736abbd4b135eb1d652466ca7906ea1b200e22eac97f795e626356e7 (exchanged in the p2p handshake; a peer with another digest is refused)
|
||||
2026-10-07 15:12:35.092+02:00 [INFO ] igneumd/2.1.0-75810130
|
||||
2026-10-07 15:12:35.093+02:00 [INFO ] Application directory: gf-digest/d-none
|
||||
2026-10-07 15:12:35.093+02:00 [INFO ] Data directory: gf-digest/d-none/igneum-devnet-973/datadir
|
||||
2026-10-07 15:12:35.093+02:00 [INFO ] Logs to console only
|
||||
2026-10-07 15:12:35.128+02:00 [INFO ] Finality v2 (igneum-devnet-973): interval 30 depth 20 window 7200 DAA dust 5 presence 20 aggregators 8 ban 7200 fold 3; rule v3 (frozen table, certificate fold) from checkpoint DAA never; 0 checkpoints known, next index 1, 0 locks, 0 keys; C1 in DAA seconds from DAA never; weight-gated deep fork choice from DAA never; leave rule (W7, delay 3600 DAA) from checkpoint DAA never, 0 leaves; key succession (W5) from checkpoint DAA never, 0 successions; signature scheme 0 (0 = BLS12-381), any other refused until a class names it
|
||||
2026-10-07 15:12:35.136+02:00 [INFO ] [igneum-exec] proving v0: payouts from DAA score never, window 7200 DAA, dust 5, verifier Off
|
||||
2026-10-07 15:12:35.136+02:00 [INFO ] [igneum-exec] proving v1: segment records from DAA score never, 8 blocks a segment, unproven after 600 DAA, aggregator share 1000 bps, shard program id unknown, aggregator id unknown
|
||||
2026-10-07 15:12:35.136+02:00 [INFO ] [igneum-exec] proof archive at gf-digest/d-none/igneum-devnet-973/datadir/evm/proofs: 0 proofs
|
||||
2026-10-07 15:12:35.136+02:00 [INFO ] [igneum-exec] verifying keys embedded: shard program id 0x2b1a81cb413236cf063077b46ed3111628f6c41036bcf6e23ee4cbbf5679ef7a aggregator id 0x474678f35f7545db28055d5e5bbc308231d84a5a072202087a2a8d5b09123896
|
||||
2026-10-07 15:12:35.141+02:00 [INFO ] template prewarm: on (the cached block template is rebuilt on every virtual change; IGNEUM_TEMPLATE_PREWARM=0 turns it off)
|
||||
2026-10-07 15:12:35.141+02:00 [INFO ] GRPC Server starting on: 127.0.0.1:29760
|
||||
2026-10-07 15:12:35.141+02:00 [INFO ] P2P Server starting on: 127.0.0.1:29761
|
||||
2026-10-07 15:12:35.141+02:00 [INFO ] [igneum-exec] eth_ JSON-RPC listening on 127.0.0.1:26790
|
||||
2026-10-07 15:12:35.141+02:00 [INFO ] [igneum-exec] proof verifier: Off (no SP1 verification on this node)
|
||||
2026-10-07 15:12:35.142+02:00 [INFO ] [igneum-exec] chain follower started
|
||||
2026-10-07 15:12:35.142+02:00 [INFO ] WRPC Server starting on: 127.0.0.1:29762
|
||||
2026-10-07 15:12:35.142+02:00 [WARN ] [igneum-exec] cannot bind the eth_ JSON-RPC server on 127.0.0.1:26790: Address already in use (os error 98)
|
||||
2026-10-07 15:12:35.142+02:00 [INFO ] [igneum-exec] exec sync: sink edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07 is chain block 0; pruning point edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07 is chain block Some(0) (DAA 0); retention root edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07 is chain block Some(0) (DAA 0), its body held
|
||||
2026-10-07 15:12:35.142+02:00 [INFO ] [igneum-exec] exec sync: no snapshot to resume from (no snapshot file); the follower starts at genesis
|
||||
2026-10-07 15:12:35.142+02:00 [INFO ] [igneum-exec] chain follower stopped
|
||||
^SIGTERM - shutting down...
|
||||
2026-10-07 15:13:00.089+02:00 [INFO ] P2P Server stopped: 127.0.0.1:29761
|
||||
2026-10-07 15:13:00.089+02:00 [INFO ] GRPC Server stopped on: 127.0.0.1:29760
|
||||
2026-10-07 15:13:00.089+02:00 [INFO ] WRPC Server stopped on: 127.0.0.1:29762
|
||||
2026-10-07 15:13:00.597+02:00 [INFO ] igneumd has stopped...
|
||||
32
docs/design/genesis-forward-harness/digest-testnet-shape.log
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
Signature scheme byte from the override file: genesis scheme 0 (0 = BLS12-381); every vote item and key reveal carries its scheme byte on the wire from DAA score 0; any other scheme refused until a class the 95 percent signal moves to names it
|
||||
Key succession (W5) from the override file: a vote key hands its window weight and its forfeit term to a successor key once, from checkpoint DAA score 0; the successor inherits the window
|
||||
Latency ladder from the override file: rungs 27, 35, 53, [88], [173], [267] shadow passes, cache [512 MiB] beside them (brackets: inadmissible, never entered), active from epoch 0 (DAA score 0 rounded up to the epoch boundary at 0), one rung per decision at 90 percent of blue blocks in each of 7 consecutive windows of 86400 DAA ending at an epoch's seed block
|
||||
Latency ladder active: rungs 27, 35, 53, [88], [173], [267] shadow passes, cache [512 MiB] beside them, this node signals none (header version bits 15 and 14; both set asks for the cache rung)
|
||||
Program class signal inactive (the window or the floor is absent from the override file): headers carry block version 2 exactly
|
||||
Fees on igneum-devnet-973: pgas table v0, B_p 30000000 pgas, S_p 7500000 pgas, floors 1000000000 wei per gas and 1000000000 wei per pgas; calibrated v1 from DAA score never
|
||||
Consensus params digest: 60e842a738c7dea04543af93e990fb962618ace0b76b38013a63cb29dd45644a (exchanged in the p2p handshake; a peer with another digest is refused)
|
||||
2026-10-07 15:13:26.156+02:00 [INFO ] igneumd/2.1.0-75810130
|
||||
2026-10-07 15:13:26.156+02:00 [INFO ] Application directory: gf-digest/d-testnet-shape
|
||||
2026-10-07 15:13:26.156+02:00 [INFO ] Data directory: gf-digest/d-testnet-shape/igneum-devnet-973/datadir
|
||||
2026-10-07 15:13:26.156+02:00 [INFO ] Logs to console only
|
||||
2026-10-07 15:13:26.172+02:00 [INFO ] Finality v2 (igneum-devnet-973): interval 30 depth 20 window 7200 DAA dust 5 presence 20 aggregators 8 ban 7200 fold 3; rule v3 (frozen table, certificate fold) from checkpoint DAA never; 0 checkpoints known, next index 1, 0 locks, 0 keys; C1 in DAA seconds from DAA never; weight-gated deep fork choice from DAA never; leave rule (W7, delay 3600 DAA) from checkpoint DAA never, 0 leaves; key succession (W5) from checkpoint DAA 0, 0 successions; signature scheme 0 (0 = BLS12-381), any other refused until a class names it
|
||||
2026-10-07 15:13:26.180+02:00 [INFO ] [igneum-exec] proving v0: payouts from DAA score never, window 7200 DAA, dust 5, verifier Off
|
||||
2026-10-07 15:13:26.180+02:00 [INFO ] [igneum-exec] proving v1: segment records from DAA score never, 8 blocks a segment, unproven after 600 DAA, aggregator share 1000 bps, shard program id unknown, aggregator id unknown
|
||||
2026-10-07 15:13:26.180+02:00 [INFO ] [igneum-exec] proof archive at gf-digest/d-testnet-shape/igneum-devnet-973/datadir/evm/proofs: 0 proofs
|
||||
2026-10-07 15:13:26.181+02:00 [INFO ] [igneum-exec] verifying keys embedded: shard program id 0x2b1a81cb413236cf063077b46ed3111628f6c41036bcf6e23ee4cbbf5679ef7a aggregator id 0x474678f35f7545db28055d5e5bbc308231d84a5a072202087a2a8d5b09123896
|
||||
2026-10-07 15:13:26.185+02:00 [INFO ] template prewarm: on (the cached block template is rebuilt on every virtual change; IGNEUM_TEMPLATE_PREWARM=0 turns it off)
|
||||
2026-10-07 15:13:26.186+02:00 [INFO ] GRPC Server starting on: 127.0.0.1:29760
|
||||
2026-10-07 15:13:26.186+02:00 [INFO ] P2P Server starting on: 127.0.0.1:29761
|
||||
2026-10-07 15:13:26.186+02:00 [INFO ] [igneum-exec] eth_ JSON-RPC listening on 127.0.0.1:26790
|
||||
2026-10-07 15:13:26.186+02:00 [INFO ] WRPC Server starting on: 127.0.0.1:29762
|
||||
2026-10-07 15:13:26.186+02:00 [INFO ] [igneum-exec] chain follower started
|
||||
2026-10-07 15:13:26.186+02:00 [INFO ] [igneum-exec] proof verifier: Off (no SP1 verification on this node)
|
||||
2026-10-07 15:13:26.186+02:00 [WARN ] [igneum-exec] cannot bind the eth_ JSON-RPC server on 127.0.0.1:26790: Address already in use (os error 98)
|
||||
2026-10-07 15:13:26.186+02:00 [INFO ] [igneum-exec] exec sync: sink edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07 is chain block 0; pruning point edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07 is chain block Some(0) (DAA 0); retention root edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07 is chain block Some(0) (DAA 0), its body held
|
||||
2026-10-07 15:13:26.186+02:00 [INFO ] [igneum-exec] exec sync: no snapshot to resume from (no snapshot file); the follower starts at genesis
|
||||
2026-10-07 15:13:26.186+02:00 [INFO ] [igneum-exec] chain follower stopped
|
||||
^SIGTERM - shutting down...
|
||||
2026-10-07 15:13:51.152+02:00 [INFO ] P2P Server stopped: 127.0.0.1:29761
|
||||
2026-10-07 15:13:51.152+02:00 [INFO ] WRPC Server stopped on: 127.0.0.1:29762
|
||||
2026-10-07 15:13:51.152+02:00 [INFO ] GRPC Server stopped on: 127.0.0.1:29760
|
||||
2026-10-07 15:13:51.660+02:00 [INFO ] igneumd has stopped...
|
||||
|
|
@ -0,0 +1,695 @@
|
|||
{
|
||||
"expect": "no-succession",
|
||||
"pass": false,
|
||||
"checks": {
|
||||
"window_filled_before_the_succession": true,
|
||||
"succession_accepted_on_submit": true,
|
||||
"carried_once_on_every_node": false,
|
||||
"successor_inherits_on_every_node": false,
|
||||
"old_key_handed_over_on_every_node": false,
|
||||
"nodes_agree_on_the_successor_weight": false,
|
||||
"refused_old_again_on_n2": false,
|
||||
"refused_old_again_on_n0": false,
|
||||
"refused_successor_that_handed_over": false,
|
||||
"scheme_1_refused_by_every_node": true,
|
||||
"locks_continue_after_the_fold": true,
|
||||
"zero_rejected_by_nodes": true,
|
||||
"sinks_agree": true
|
||||
},
|
||||
"old_key": "e4036b1e79c817f2",
|
||||
"new_key": "2f031ed35a29ced8",
|
||||
"old_blocks_before": 41,
|
||||
"succeeded_at_daa": 261,
|
||||
"carried_seen_at_daa": null,
|
||||
"new_mined_alone": 112,
|
||||
"rows": [
|
||||
{
|
||||
"new": {
|
||||
"blocks": 37,
|
||||
"keyHash": "2f031ed35a29ced8",
|
||||
"participation": 1,
|
||||
"pubkey": "80ab38c523736ad8944c7d3375e7563ba3b0d5a3ab149bec568cf207edcc9e1ab1ee2566e06ff422a5ec4c85a4049976",
|
||||
"strippedUntilDaa": 0,
|
||||
"succeededFrom": "",
|
||||
"succeededTo": "",
|
||||
"voter": true
|
||||
},
|
||||
"old": {
|
||||
"blocks": 0,
|
||||
"keyHash": "e4036b1e79c817f2",
|
||||
"participation": 0,
|
||||
"pubkey": "b0fd8eebbbaad96268e5f7b8a86090ca0c723954a0a5cb81c92b633094c1742b2505c4f7cea646c5c96bb52e57400067",
|
||||
"strippedUntilDaa": 0,
|
||||
"succeededFrom": "",
|
||||
"succeededTo": "6543d321fd61aedb",
|
||||
"voter": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"new": {
|
||||
"blocks": 0,
|
||||
"keyHash": "2f031ed35a29ced8",
|
||||
"participation": 0,
|
||||
"pubkey": "80ab38c523736ad8944c7d3375e7563ba3b0d5a3ab149bec568cf207edcc9e1ab1ee2566e06ff422a5ec4c85a4049976",
|
||||
"strippedUntilDaa": 0,
|
||||
"succeededFrom": "",
|
||||
"succeededTo": "e4036b1e79c817f2",
|
||||
"voter": false
|
||||
},
|
||||
"old": {
|
||||
"blocks": 0,
|
||||
"keyHash": "e4036b1e79c817f2",
|
||||
"participation": 0,
|
||||
"pubkey": "b0fd8eebbbaad96268e5f7b8a86090ca0c723954a0a5cb81c92b633094c1742b2505c4f7cea646c5c96bb52e57400067",
|
||||
"strippedUntilDaa": 0,
|
||||
"succeededFrom": "",
|
||||
"succeededTo": "6543d321fd61aedb",
|
||||
"voter": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"new": {
|
||||
"blocks": 37,
|
||||
"keyHash": "2f031ed35a29ced8",
|
||||
"participation": 1,
|
||||
"pubkey": "80ab38c523736ad8944c7d3375e7563ba3b0d5a3ab149bec568cf207edcc9e1ab1ee2566e06ff422a5ec4c85a4049976",
|
||||
"strippedUntilDaa": 0,
|
||||
"succeededFrom": "",
|
||||
"succeededTo": "",
|
||||
"voter": true
|
||||
},
|
||||
"old": {
|
||||
"blocks": 0,
|
||||
"keyHash": "e4036b1e79c817f2",
|
||||
"participation": 0,
|
||||
"pubkey": "b0fd8eebbbaad96268e5f7b8a86090ca0c723954a0a5cb81c92b633094c1742b2505c4f7cea646c5c96bb52e57400067",
|
||||
"strippedUntilDaa": 0,
|
||||
"succeededFrom": "",
|
||||
"succeededTo": "6543d321fd61aedb",
|
||||
"voter": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"locks": [
|
||||
12,
|
||||
12,
|
||||
12
|
||||
],
|
||||
"locks_at_fold": 9,
|
||||
"refusals": [
|
||||
{
|
||||
"what": "w5-old -> w5-third on n2",
|
||||
"code": 0,
|
||||
"line": "1791378723.612 SUCCEED old=e4036b1e79c817f2 new=6543d321fd61aedb daa=502 (accepted: carried in this node's next block)"
|
||||
},
|
||||
{
|
||||
"what": "w5-old -> w5-third on n0",
|
||||
"code": 0,
|
||||
"line": "1791378723.629 SUCCEED old=e4036b1e79c817f2 new=6543d321fd61aedb daa=502 (accepted: carried in this node's next block)"
|
||||
},
|
||||
{
|
||||
"what": "w5-new -> w5-old on n1",
|
||||
"code": 0,
|
||||
"line": "1791378723.645 SUCCEED old=2f031ed35a29ced8 new=e4036b1e79c817f2 daa=502 (accepted: carried in this node's next block)"
|
||||
}
|
||||
],
|
||||
"probes": [
|
||||
{
|
||||
"node": 0,
|
||||
"code": 0,
|
||||
"line": "1791378723.659 SCHEME 1 REFUSED key=b875b095c1b5d559 index=16 (refused: vote carries signature scheme 1; the active scheme is 0 (BLS12-381); another scheme is named only by a program class the 95 percent signal moves to, and none names one)"
|
||||
},
|
||||
{
|
||||
"node": 1,
|
||||
"code": 0,
|
||||
"line": "1791378723.672 SCHEME 1 REFUSED key=b875b095c1b5d559 index=16 (refused: vote carries signature scheme 1; the active scheme is 0 (BLS12-381); another scheme is named only by a program class the 95 percent signal moves to, and none names one)"
|
||||
},
|
||||
{
|
||||
"node": 2,
|
||||
"code": 0,
|
||||
"line": "1791378723.687 SCHEME 1 REFUSED key=b875b095c1b5d559 index=16 (refused: vote carries signature scheme 1; the active scheme is 0 (BLS12-381); another scheme is named only by a program class the 95 percent signal moves to, and none names one)"
|
||||
}
|
||||
],
|
||||
"samples": [
|
||||
{
|
||||
"t": 5.7,
|
||||
"daa": 0,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"?",
|
||||
"?",
|
||||
"?"
|
||||
],
|
||||
"locks": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 20.7,
|
||||
"daa": 7,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"?",
|
||||
"?",
|
||||
"?"
|
||||
],
|
||||
"locks": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 35.7,
|
||||
"daa": 17,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"?",
|
||||
"?",
|
||||
"?"
|
||||
],
|
||||
"locks": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 50.7,
|
||||
"daa": 36,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"?",
|
||||
"?",
|
||||
"?"
|
||||
],
|
||||
"locks": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 65.7,
|
||||
"daa": 57,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"29/3",
|
||||
"29/3",
|
||||
"29/3"
|
||||
],
|
||||
"locks": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 80.8,
|
||||
"daa": 79,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"29/3",
|
||||
"29/3",
|
||||
"29/3"
|
||||
],
|
||||
"locks": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 95.8,
|
||||
"daa": 92,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"59/3",
|
||||
"59/3",
|
||||
"59/3"
|
||||
],
|
||||
"locks": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 110.8,
|
||||
"daa": 104,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"59/3",
|
||||
"59/3",
|
||||
"59/3"
|
||||
],
|
||||
"locks": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 125.8,
|
||||
"daa": 114,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"89/3",
|
||||
"89/3",
|
||||
"89/3"
|
||||
],
|
||||
"locks": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 140.8,
|
||||
"daa": 123,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"89/3",
|
||||
"89/3",
|
||||
"89/3"
|
||||
],
|
||||
"locks": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 155.8,
|
||||
"daa": 135,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"89/3",
|
||||
"89/3",
|
||||
"89/3"
|
||||
],
|
||||
"locks": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 170.9,
|
||||
"daa": 152,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"119/3",
|
||||
"119/3",
|
||||
"119/3"
|
||||
],
|
||||
"locks": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 185.9,
|
||||
"daa": 173,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"120/3",
|
||||
"120/3",
|
||||
"120/3"
|
||||
],
|
||||
"locks": [
|
||||
1,
|
||||
1,
|
||||
1
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 200.9,
|
||||
"daa": 187,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"120/3",
|
||||
"120/3",
|
||||
"120/3"
|
||||
],
|
||||
"locks": [
|
||||
1,
|
||||
1,
|
||||
1
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 215.9,
|
||||
"daa": 203,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"120/3",
|
||||
"120/3",
|
||||
"120/3"
|
||||
],
|
||||
"locks": [
|
||||
2,
|
||||
2,
|
||||
2
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 230.9,
|
||||
"daa": 224,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"120/3",
|
||||
"120/3",
|
||||
"120/3"
|
||||
],
|
||||
"locks": [
|
||||
2,
|
||||
2,
|
||||
2
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 246,
|
||||
"daa": 242,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"120/3",
|
||||
"120/3",
|
||||
"120/3"
|
||||
],
|
||||
"locks": [
|
||||
3,
|
||||
3,
|
||||
3
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 261,
|
||||
"daa": 258,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"120/3",
|
||||
"120/3",
|
||||
"120/3"
|
||||
],
|
||||
"locks": [
|
||||
3,
|
||||
3,
|
||||
3
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 276.5,
|
||||
"daa": 270,
|
||||
"phase": "carry",
|
||||
"weights": [
|
||||
"120/3",
|
||||
"120/3",
|
||||
"120/3"
|
||||
],
|
||||
"locks": [
|
||||
4,
|
||||
4,
|
||||
4
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 291.6,
|
||||
"daa": 285,
|
||||
"phase": "carry",
|
||||
"weights": [
|
||||
"120/3",
|
||||
"120/3",
|
||||
"120/3"
|
||||
],
|
||||
"locks": [
|
||||
4,
|
||||
4,
|
||||
4
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 306.6,
|
||||
"daa": 308,
|
||||
"phase": "carry",
|
||||
"weights": [
|
||||
"118/3",
|
||||
"118/3",
|
||||
"118/3"
|
||||
],
|
||||
"locks": [
|
||||
4,
|
||||
4,
|
||||
4
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 321.7,
|
||||
"daa": 338,
|
||||
"phase": "carry",
|
||||
"weights": [
|
||||
"120/4",
|
||||
"120/4",
|
||||
"120/4"
|
||||
],
|
||||
"locks": [
|
||||
4,
|
||||
4,
|
||||
4
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 336.7,
|
||||
"daa": 357,
|
||||
"phase": "carry",
|
||||
"weights": [
|
||||
"120/4",
|
||||
"120/4",
|
||||
"120/4"
|
||||
],
|
||||
"locks": [
|
||||
4,
|
||||
4,
|
||||
4
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 351.8,
|
||||
"daa": 368,
|
||||
"phase": "carry",
|
||||
"weights": [
|
||||
"120/4",
|
||||
"120/4",
|
||||
"120/4"
|
||||
],
|
||||
"locks": [
|
||||
4,
|
||||
4,
|
||||
4
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 366.9,
|
||||
"daa": 385,
|
||||
"phase": "carry",
|
||||
"weights": [
|
||||
"120/4",
|
||||
"120/4",
|
||||
"120/4"
|
||||
],
|
||||
"locks": [
|
||||
5,
|
||||
5,
|
||||
5
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 382,
|
||||
"daa": 406,
|
||||
"phase": "carry",
|
||||
"weights": [
|
||||
"120/4",
|
||||
"120/4",
|
||||
"120/4"
|
||||
],
|
||||
"locks": [
|
||||
5,
|
||||
5,
|
||||
5
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 397,
|
||||
"daa": 424,
|
||||
"phase": "carry",
|
||||
"weights": [
|
||||
"120/3",
|
||||
"120/3",
|
||||
"120/3"
|
||||
],
|
||||
"locks": [
|
||||
6,
|
||||
6,
|
||||
6
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 412.1,
|
||||
"daa": 441,
|
||||
"phase": "carry",
|
||||
"weights": [
|
||||
"120/3",
|
||||
"120/3",
|
||||
"120/3"
|
||||
],
|
||||
"locks": [
|
||||
7,
|
||||
7,
|
||||
7
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 427.2,
|
||||
"daa": 454,
|
||||
"phase": "carry",
|
||||
"weights": [
|
||||
"120/3",
|
||||
"120/3",
|
||||
"120/3"
|
||||
],
|
||||
"locks": [
|
||||
7,
|
||||
7,
|
||||
7
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 442.3,
|
||||
"daa": 469,
|
||||
"phase": "carry",
|
||||
"weights": [
|
||||
"120/3",
|
||||
"120/3",
|
||||
"120/3"
|
||||
],
|
||||
"locks": [
|
||||
7,
|
||||
7,
|
||||
7
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 457.3,
|
||||
"daa": 485,
|
||||
"phase": "carry",
|
||||
"weights": [
|
||||
"120/3",
|
||||
"120/3",
|
||||
"120/3"
|
||||
],
|
||||
"locks": [
|
||||
8,
|
||||
8,
|
||||
8
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 472.4,
|
||||
"daa": 494,
|
||||
"phase": "carry",
|
||||
"weights": [
|
||||
"120/3",
|
||||
"120/3",
|
||||
"120/3"
|
||||
],
|
||||
"locks": [
|
||||
8,
|
||||
8,
|
||||
8
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 487.6,
|
||||
"daa": 509,
|
||||
"phase": "after",
|
||||
"weights": [
|
||||
"120/3",
|
||||
"120/3",
|
||||
"120/3"
|
||||
],
|
||||
"locks": [
|
||||
9,
|
||||
9,
|
||||
9
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 502.6,
|
||||
"daa": 526,
|
||||
"phase": "after",
|
||||
"weights": [
|
||||
"120/3",
|
||||
"120/3",
|
||||
"120/3"
|
||||
],
|
||||
"locks": [
|
||||
9,
|
||||
9,
|
||||
9
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 517.6,
|
||||
"daa": 545,
|
||||
"phase": "after",
|
||||
"weights": [
|
||||
"120/3",
|
||||
"120/3",
|
||||
"120/3"
|
||||
],
|
||||
"locks": [
|
||||
10,
|
||||
10,
|
||||
10
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 532.7,
|
||||
"daa": 561,
|
||||
"phase": "after",
|
||||
"weights": [
|
||||
"120/3",
|
||||
"120/3",
|
||||
"120/3"
|
||||
],
|
||||
"locks": [
|
||||
11,
|
||||
11,
|
||||
11
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 547.7,
|
||||
"daa": 578,
|
||||
"phase": "after",
|
||||
"weights": [
|
||||
"120/3",
|
||||
"120/3",
|
||||
"120/3"
|
||||
],
|
||||
"locks": [
|
||||
11,
|
||||
11,
|
||||
11
|
||||
]
|
||||
}
|
||||
],
|
||||
"wall_s": 560.2,
|
||||
"binaries": {
|
||||
"igneumd": "/srv/builds/igneum-wt-genesis-forward/vendor/igneum-node-gf/target/release/igneumd",
|
||||
"miner": "/srv/builds/igneum-wt-genesis-forward/vendor/igneum-node-gf/target/release/igneum-miner"
|
||||
}
|
||||
}
|
||||
455
docs/design/genesis-forward-harness/pass-succession.json
Normal file
|
|
@ -0,0 +1,455 @@
|
|||
{
|
||||
"expect": "succession",
|
||||
"pass": true,
|
||||
"checks": {
|
||||
"window_filled_before_the_succession": true,
|
||||
"succession_accepted_on_submit": true,
|
||||
"carried_once_on_every_node": true,
|
||||
"successor_inherits_on_every_node": true,
|
||||
"old_key_handed_over_on_every_node": true,
|
||||
"nodes_agree_on_the_successor_weight": true,
|
||||
"refused_old_again_on_n2": true,
|
||||
"refused_old_again_on_n0": true,
|
||||
"refused_successor_that_handed_over": true,
|
||||
"scheme_1_refused_by_every_node": true,
|
||||
"locks_continue_after_the_fold": true,
|
||||
"zero_rejected_by_nodes": true,
|
||||
"sinks_agree": true
|
||||
},
|
||||
"old_key": "e4036b1e79c817f2",
|
||||
"new_key": "2f031ed35a29ced8",
|
||||
"old_blocks_before": 42,
|
||||
"succeeded_at_daa": 260,
|
||||
"carried_seen_at_daa": 266,
|
||||
"new_mined_alone": 29,
|
||||
"rows": [
|
||||
{
|
||||
"new": {
|
||||
"blocks": 37,
|
||||
"keyHash": "2f031ed35a29ced8",
|
||||
"participation": 1,
|
||||
"pubkey": "80ab38c523736ad8944c7d3375e7563ba3b0d5a3ab149bec568cf207edcc9e1ab1ee2566e06ff422a5ec4c85a4049976",
|
||||
"strippedUntilDaa": 0,
|
||||
"succeededFrom": "e4036b1e79c817f2",
|
||||
"succeededTo": "",
|
||||
"voter": true
|
||||
},
|
||||
"old": {
|
||||
"blocks": 0,
|
||||
"keyHash": "e4036b1e79c817f2",
|
||||
"participation": 0,
|
||||
"pubkey": "b0fd8eebbbaad96268e5f7b8a86090ca0c723954a0a5cb81c92b633094c1742b2505c4f7cea646c5c96bb52e57400067",
|
||||
"strippedUntilDaa": 0,
|
||||
"succeededFrom": "",
|
||||
"succeededTo": "2f031ed35a29ced8",
|
||||
"voter": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"new": {
|
||||
"blocks": 37,
|
||||
"keyHash": "2f031ed35a29ced8",
|
||||
"participation": 1,
|
||||
"pubkey": "80ab38c523736ad8944c7d3375e7563ba3b0d5a3ab149bec568cf207edcc9e1ab1ee2566e06ff422a5ec4c85a4049976",
|
||||
"strippedUntilDaa": 0,
|
||||
"succeededFrom": "e4036b1e79c817f2",
|
||||
"succeededTo": "",
|
||||
"voter": true
|
||||
},
|
||||
"old": {
|
||||
"blocks": 0,
|
||||
"keyHash": "e4036b1e79c817f2",
|
||||
"participation": 0,
|
||||
"pubkey": "b0fd8eebbbaad96268e5f7b8a86090ca0c723954a0a5cb81c92b633094c1742b2505c4f7cea646c5c96bb52e57400067",
|
||||
"strippedUntilDaa": 0,
|
||||
"succeededFrom": "",
|
||||
"succeededTo": "2f031ed35a29ced8",
|
||||
"voter": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"new": {
|
||||
"blocks": 37,
|
||||
"keyHash": "2f031ed35a29ced8",
|
||||
"participation": 1,
|
||||
"pubkey": "80ab38c523736ad8944c7d3375e7563ba3b0d5a3ab149bec568cf207edcc9e1ab1ee2566e06ff422a5ec4c85a4049976",
|
||||
"strippedUntilDaa": 0,
|
||||
"succeededFrom": "e4036b1e79c817f2",
|
||||
"succeededTo": "",
|
||||
"voter": true
|
||||
},
|
||||
"old": {
|
||||
"blocks": 0,
|
||||
"keyHash": "e4036b1e79c817f2",
|
||||
"participation": 0,
|
||||
"pubkey": "b0fd8eebbbaad96268e5f7b8a86090ca0c723954a0a5cb81c92b633094c1742b2505c4f7cea646c5c96bb52e57400067",
|
||||
"strippedUntilDaa": 0,
|
||||
"succeededFrom": "",
|
||||
"succeededTo": "2f031ed35a29ced8",
|
||||
"voter": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"locks": [
|
||||
7,
|
||||
7,
|
||||
7
|
||||
],
|
||||
"locks_at_fold": 4,
|
||||
"refusals": [
|
||||
{
|
||||
"what": "w5-old -> w5-third on n2",
|
||||
"code": 3,
|
||||
"line": "1791379651.057 SUCCEED REFUSED old=e4036b1e79c817f2 new=6543d321fd61aedb daa=290 (refused: key e4036b1e79c817f2 has already handed its weight to 2f031ed35a29ced8; a key hands over once)"
|
||||
},
|
||||
{
|
||||
"what": "w5-old -> w5-third on n0",
|
||||
"code": 3,
|
||||
"line": "1791379651.072 SUCCEED REFUSED old=e4036b1e79c817f2 new=6543d321fd61aedb daa=290 (refused: key e4036b1e79c817f2 has already handed its weight to 2f031ed35a29ced8; a key hands over once)"
|
||||
},
|
||||
{
|
||||
"what": "w5-new -> w5-old on n1",
|
||||
"code": 3,
|
||||
"line": "1791379651.085 SUCCEED REFUSED old=2f031ed35a29ced8 new=e4036b1e79c817f2 daa=290 (refused: successor e4036b1e79c817f2 has itself handed its weight to 2f031ed35a29ced8; it signs nothing and can inherit nothing)"
|
||||
}
|
||||
],
|
||||
"probes": [
|
||||
{
|
||||
"node": 0,
|
||||
"code": 0,
|
||||
"line": "1791379651.097 SCHEME 1 REFUSED key=b875b095c1b5d559 index=9 (refused: vote carries signature scheme 1; the active scheme is 0 (BLS12-381); another scheme is named only by a program class the 95 percent signal moves to, and none names one)"
|
||||
},
|
||||
{
|
||||
"node": 1,
|
||||
"code": 0,
|
||||
"line": "1791379651.110 SCHEME 1 REFUSED key=b875b095c1b5d559 index=9 (refused: vote carries signature scheme 1; the active scheme is 0 (BLS12-381); another scheme is named only by a program class the 95 percent signal moves to, and none names one)"
|
||||
},
|
||||
{
|
||||
"node": 2,
|
||||
"code": 0,
|
||||
"line": "1791379651.123 SCHEME 1 REFUSED key=b875b095c1b5d559 index=9 (refused: vote carries signature scheme 1; the active scheme is 0 (BLS12-381); another scheme is named only by a program class the 95 percent signal moves to, and none names one)"
|
||||
}
|
||||
],
|
||||
"samples": [
|
||||
{
|
||||
"t": 5.6,
|
||||
"daa": 0,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"?",
|
||||
"?",
|
||||
"?"
|
||||
],
|
||||
"locks": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 20.6,
|
||||
"daa": 37,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"?",
|
||||
"?",
|
||||
"?"
|
||||
],
|
||||
"locks": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 35.6,
|
||||
"daa": 56,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"28/3",
|
||||
"28/3",
|
||||
"28/3"
|
||||
],
|
||||
"locks": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 50.6,
|
||||
"daa": 71,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"28/3",
|
||||
"28/3",
|
||||
"28/3"
|
||||
],
|
||||
"locks": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 65.6,
|
||||
"daa": 85,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"58/3",
|
||||
"58/3",
|
||||
"58/3"
|
||||
],
|
||||
"locks": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 80.6,
|
||||
"daa": 106,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"58/3",
|
||||
"58/3",
|
||||
"58/3"
|
||||
],
|
||||
"locks": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 95.6,
|
||||
"daa": 126,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"88/3",
|
||||
"88/3",
|
||||
"88/3"
|
||||
],
|
||||
"locks": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 110.6,
|
||||
"daa": 141,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"118/3",
|
||||
"118/3",
|
||||
"118/3"
|
||||
],
|
||||
"locks": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 125.6,
|
||||
"daa": 155,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"118/3",
|
||||
"118/3",
|
||||
"118/3"
|
||||
],
|
||||
"locks": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 140.6,
|
||||
"daa": 166,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"118/3",
|
||||
"118/3",
|
||||
"118/3"
|
||||
],
|
||||
"locks": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 155.7,
|
||||
"daa": 185,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"120/3",
|
||||
"120/3",
|
||||
"120/3"
|
||||
],
|
||||
"locks": [
|
||||
1,
|
||||
1,
|
||||
1
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 170.7,
|
||||
"daa": 202,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"120/3",
|
||||
"120/3",
|
||||
"120/3"
|
||||
],
|
||||
"locks": [
|
||||
2,
|
||||
2,
|
||||
2
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 185.7,
|
||||
"daa": 213,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"120/3",
|
||||
"120/3",
|
||||
"120/3"
|
||||
],
|
||||
"locks": [
|
||||
2,
|
||||
2,
|
||||
2
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 200.7,
|
||||
"daa": 229,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"120/3",
|
||||
"120/3",
|
||||
"120/3"
|
||||
],
|
||||
"locks": [
|
||||
2,
|
||||
2,
|
||||
2
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 215.7,
|
||||
"daa": 244,
|
||||
"phase": "fill",
|
||||
"weights": [
|
||||
"120/3",
|
||||
"120/3",
|
||||
"120/3"
|
||||
],
|
||||
"locks": [
|
||||
3,
|
||||
3,
|
||||
3
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 233.2,
|
||||
"daa": 261,
|
||||
"phase": "carry",
|
||||
"weights": [
|
||||
"120/3",
|
||||
"120/3",
|
||||
"120/3"
|
||||
],
|
||||
"locks": [
|
||||
4,
|
||||
4,
|
||||
4
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 248.3,
|
||||
"daa": 280,
|
||||
"phase": "carry",
|
||||
"weights": [
|
||||
"120/3",
|
||||
"120/3",
|
||||
"120/3"
|
||||
],
|
||||
"locks": [
|
||||
4,
|
||||
4,
|
||||
4
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 263.4,
|
||||
"daa": 300,
|
||||
"phase": "after",
|
||||
"weights": [
|
||||
"120/3",
|
||||
"120/3",
|
||||
"120/3"
|
||||
],
|
||||
"locks": [
|
||||
5,
|
||||
5,
|
||||
5
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 278.4,
|
||||
"daa": 316,
|
||||
"phase": "after",
|
||||
"weights": [
|
||||
"120/3",
|
||||
"120/3",
|
||||
"120/3"
|
||||
],
|
||||
"locks": [
|
||||
5,
|
||||
5,
|
||||
5
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 293.4,
|
||||
"daa": 328,
|
||||
"phase": "after",
|
||||
"weights": [
|
||||
"120/3",
|
||||
"120/3",
|
||||
"120/3"
|
||||
],
|
||||
"locks": [
|
||||
6,
|
||||
6,
|
||||
6
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 308.4,
|
||||
"daa": 343,
|
||||
"phase": "after",
|
||||
"weights": [
|
||||
"120/3",
|
||||
"120/3",
|
||||
"120/3"
|
||||
],
|
||||
"locks": [
|
||||
6,
|
||||
6,
|
||||
6
|
||||
]
|
||||
}
|
||||
],
|
||||
"wall_s": 317,
|
||||
"binaries": {
|
||||
"igneumd": "/srv/builds/igneum-wt-genesis-forward/vendor/igneum-node-gf/target/release/igneumd",
|
||||
"miner": "/srv/builds/igneum-wt-genesis-forward/vendor/igneum-node-gf/target/release/igneum-miner"
|
||||
}
|
||||
}
|
||||
85
docs/design/genesis-forward.md
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
# Genesis forward-compatibility: the scheme byte, key succession, the cache rung
|
||||
|
||||
7 October 2026, 10:1x UK, the project lead's order to build mission item 8 now (`docs/analysis/mission/mission.md` section 2.8; the research in `docs/analysis/mission/future.md` sections 1.3, 7 and 10 and `docs/design/finality-in-proof.md` section 7). Branch `genesis-forward` on the node fork (from release-0.3.19-node dc141409, the merged line that carries the ladder and the W7 leave item, which ca3-v4-0318 alone does not) and `genesis-forward` on the repo. Three genesis fields, every switch never on the devnet (its digest does not move), all three set at the testnet genesis by the testnet lane, which holds the cut and re-pins. The class-group VDF's quantum fallback is flagged in spec 04 section 4.8, not built.
|
||||
|
||||
## 1. The scheme byte
|
||||
|
||||
| Item | Place | Value |
|
||||
|---|---|---|
|
||||
| The byte | `finality::Vote::sig_scheme`, `finality::KeyReveal::sig_scheme`, `finality::Succession::successor_scheme` | `SIG_SCHEME_BLS12_381` = 0 everywhere today |
|
||||
| The genesis value | `Params::sig_scheme` (override key `sig_scheme`) | 0 on every network |
|
||||
| The switch | `Params::sig_scheme_activation_daa` (override key `sig_scheme_activation_daa`; `u64::MAX` = never) | never on devnet, simnet, mainnet; 0 at the testnet genesis |
|
||||
| The digest | both fields enter once the switch is set (the 0.3.15 rule) | the devnet's digest unchanged; the testnet's moves at the cut |
|
||||
| The wire, plain | vote item tag 1 (`Vote::LEN` = 280 bytes), evidence tag 3, reveal `IGNK` + 288 hex: scheme 0 implied | byte for byte what every live network carries |
|
||||
| The wire, explicit | vote item tag 5 = `scheme \|\| vote`, evidence tag 6 = `scheme \|\| first \|\| second`, reveal `IGNS` + 2 hex of the scheme + 288 hex | written by every template once the switch is active (`encode_section_explicit_within`); a vote of any other scheme is always explicit, so a scheme the node does not run is never mistaken for one it does |
|
||||
| The active scheme | `igneum::active_sig_scheme(genesis, class)` = the scheme the program class at the sink names (`SIG_SCHEME_OF_CLASS`, a genesis table with no row today), else the genesis byte; the finality manager re-reads it at every virtual change | 0 |
|
||||
| The refusal | `FinalityManager::scheme_refusal`: a reveal is not registered, a vote is not recorded, carried or gossiped, a successor is refused; the RPC answers `refused: vote carries signature scheme 1; the active scheme is 0 (BLS12-381); another scheme is named only by a program class the 95 percent signal moves to, and none names one` | every node, whatever its switch |
|
||||
|
||||
Why a class change names the scheme: the flip is the P2 mechanism (95 percent of mining weight over a window with a floor height, the one path a consensus change takes on this chain), and the aggregated-vote format must ship first (naive ML-DSA-44 votes at 8,192 voters cost 19.4 MB a checkpoint and 57 GB a day, `future.md` 7.3; with 250x SNARK aggregation about 223 MB a day). Adding a row to the table is a code change under the class path; the byte is in every item from genesis so the row costs no fork.
|
||||
|
||||
## 2. Key succession, W5
|
||||
|
||||
| Item | Place | Value |
|
||||
|---|---|---|
|
||||
| The item | `finality::Succession` (tag 7, 297 bytes): `daa`, old key, successor key, successor scheme, the old key's signature, the successor's signature, both over `"igneum-succeed-v1/" \|\| chain_id \|\| 0 \|\| daa \|\| old \|\| new \|\| scheme` under `IGNEUM_SUCCEED_V1_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_` | the successor's signature is its consent and its proof of possession in one |
|
||||
| The switch | `Params::finality_succession_activation_daa` (override key of the same name) | never everywhere; 0 at the testnet genesis; in the digest once set |
|
||||
| Submission | `submitFinalitySuccession` (RPC op 158, gRPC 1131/1132, wRPC, `igneum-miner succeed <grpc url> <old label> <new label>`) | carried after the leaves in the templates of the node that holds it; no p2p gossip kind (the successor's own node mines it) |
|
||||
| The fold | `successions_at` (deterministic like `leaves_at`: the lowest-DAA carrier in C's past dates it) and `fold_successions` inside `voters_at`: the old key's window blocks are credited to the successor as they stand (count and oldest block), the old key leaves the table, a ban or a leave on the old key lands on the successor; the successor's presence counts the old key's carried votes | from the first checkpoint whose past holds the carrier; the window inherited, not a fresh one |
|
||||
| Once | one record per old key: a second succession from a key that handed over is refused (`already handed its weight to`), a successor that has itself handed over is refused (`has itself handed`), which also refuses every cycle; a chain old to new to newer is legal | a record outlives the weight it moved by one window, then is trimmed |
|
||||
| After | the old key's votes are refused (`handed its weight to`), never counted, never carried | the old key is dead |
|
||||
| The report | `getFinalityWeights`: `succeededFrom` on the successor's row, a weightless row for the old key with `succeededTo` | both nodes of the unit test agree on every voter list |
|
||||
|
||||
Not in this round: a p2p gossip kind for successions (the leave's shape, protocol version bump); the app's "rotate key" button, which signs the item from the old key's label and restarts the miner under the new label (the `succeed` subcommand is the primitive); the aggregated-vote format.
|
||||
|
||||
## 3. The cache rung beside N
|
||||
|
||||
| Item | Place | Value |
|
||||
|---|---|---|
|
||||
| The rung | `igneum::CacheRung { mib, admissible }` as `LatencyLadder::cache_rung` (override key `latency_ladder_cache_rung`) | `{512, false}` at genesis; a power of two above the 256 MiB genesis cache |
|
||||
| The signal | `LadderSignal::Cache` = both ladder bits set (header version 0xc000; until today both set was "no signal" and no node ever stamped it, so no block written so far changes meaning); `IGNEUM_LADDER_SIGNAL=cache` | code 3 in `PowEpochInfo::latency_ladder_signal` |
|
||||
| The rule | `latency_ladder_step_signalled_with_cache`: the cache step moves 0 to 1 when every one of the newest seven windows reaches 90 percent for the cache rung, the rung is admissible and the cool-down holds (the oldest window begins after the last decision, shared with N); never back; never in the same decision as N (one signal per block, exclusive shares) | `LadderState::cache_step` |
|
||||
| The digest | the rung's size and flag enter with the ladder, once `latency_ladder_activation_daa` is set | the testnet's digest moves at the cut |
|
||||
| The RPC | `powEpoch.latencyLadderCacheStep`, `nextLatencyLadderCacheStep`, `latencyLadderCacheMib`, `nextLatencyLadderCacheMib`, `latencyLadderCacheBps`, `latencyLadderCacheWeakestBps`, `latencyLadderCacheAdmissible` (proto fields 37 to 43); the daemon's ladder line (`cache [512 MiB]`) | the rung visible on every node |
|
||||
| The gate | `admissible` in the genesis list, false until measured: the cold verify of one warp with the 512 MiB cache on the reference core with its SMT sibling loaded under 10 ms (the verifier reads the cache, so this is the bound), the day-cache build on a 2019-class core under twice today's, and the 8 GB tier still holding dataset, cache and the prover footprint | the rule never enters an inadmissible rung (tested) |
|
||||
|
||||
Why beside N and not a seventh N rung: the six approved rungs and their indices stand (the project lead, 7 October 2026, 09:3x UK); a rung inserted in the list would either sit behind the three inadmissible rungs (unreachable) or shift the approved indices. A second lever on the same signal carrier keeps the list as approved and the cool-down shared.
|
||||
|
||||
Owed with the measurement: the engine's consumption of `cache_mib` (`EpochSeeds` carries `shadow_reps` today and no cache size; the pack and the three hosts build a 256 MiB cache), so the flag stays false until the path exists and is measured. Per tier what the rung means: every tier from 8 GB holds a 512 MiB cache; the day-cache build doubles (about 0.7 s on the reference core today, approximate, from the class v4 fill line); the Apple tier's unified memory holds it; a pool user does nothing.
|
||||
|
||||
## 4. The class-group VDF under a quantum computer
|
||||
|
||||
Flagged in spec 04 section 4.8, not sized: Shor computes the class-group order, which removes the sequentiality assumption of the Wesolowski VDF, so an attacker with a cryptographically relevant quantum computer grinds the hourly seed (a liveness nuisance against the lottery, not a safety break; finality rests on the vote keys of section 1). The fallback is a hash-chain delay behind the same version byte, designed when the scheme flip is scheduled.
|
||||
|
||||
## 5. Gates
|
||||
|
||||
| Gate | Where | Result |
|
||||
|---|---|---|
|
||||
| The digest test | `consensus_digest_covers_every_consensus_field_and_nothing_else` (30 edits; the scheme byte and the cache rung alone move nothing), `override_params_carry_the_genesis_forward_fields_and_the_digest_moves_only_when_set` | section 6 |
|
||||
| Scheme 1 refused by every node until the signal | unit: `a_vote_reveal_or_successor_of_another_signature_scheme_is_refused_until_a_class_names_it` (RPC, in a block, a reveal, a successor; the explicit template form); fast-time: `probe-scheme` on three nodes | section 6 |
|
||||
| A succession carried once and refused twice | unit: `a_key_hands_its_window_to_a_successor_once_and_a_second_succession_is_refused` (two nodes); fast-time: `infra/fast-time/key-succession.mjs` (the known-failed case `--expect no-succession` first) | section 6 |
|
||||
| The ladder rung visible in the RPC | `powEpoch.latencyLadderCache*` on `getBlockTemplate`, the daemon line; unit: `latency_ladder_rule` (an inadmissible cache rung never entered; with the flag, 90 percent in seven windows enters it, N still steps after it, one rung, never back) | section 6 |
|
||||
| The codec | `scheme_byte_and_succession_items_round_trip_and_an_older_decoder_stops_at_them` | section 6 |
|
||||
|
||||
## 6. Results (7 October 2026, 12:5x to 14:3x UK; igneum-build-1 for the gate build, the harness and the digests, igneum-build-2 for the suites)
|
||||
|
||||
| Gate | Run | Result |
|
||||
|---|---|---|
|
||||
| The digest test | `cargo test --release -p kaspa-consensus-core --lib` on build-2 at 75810130 | 124 passed, 0 failed, 2 ignored (`consensus_digest_covers_every_consensus_field_and_nothing_else` with 30 edits, `override_params_carry_the_genesis_forward_fields_and_the_digest_moves_only_when_set`, `latency_ladder_rule` with the cache rung) |
|
||||
| The 60x keeper test | `fast_time_60x_file_is_the_devnet_at_60x` on build-2 against the completed file (repo 9c9a1f52) | 1 passed (the file had lacked 17 fields on master, `emission` and `proving_consensus_verify_daa` among them; the box mirrors carry no `infra/`, so the test skips there unless the file is shipped) |
|
||||
| Scheme 1 refused by every node | unit `a_vote_reveal_or_successor_of_another_signature_scheme_is_refused_until_a_class_names_it`; fast-time `probe-scheme` on three nodes, both harness cases | green in the suite runs; every node: `SCHEME 1 REFUSED ... (refused: vote carries signature scheme 1; the active scheme is 0 (BLS12-381); another scheme is named only by a program class the 95 percent signal moves to, and none names one)` |
|
||||
| A succession carried once and refused twice | unit `a_key_hands_its_window_to_a_successor_once_and_a_second_succession_is_refused` (two nodes); fast-time `infra/fast-time/key-succession.mjs` on build-1 (3 nodes, one CPU miner each, override-60x with the three switches at 0) | known-failed case first (`--expect no-succession`, 13:04 to 13:13 UK, `genesis-forward-harness/known-failed-no-succession.json`): FAIL as it must on every carried-once check with the probe, the locks and the sinks holding. Pass case (`--expect succession`, node bdb34f62, 13:23 to 13:28 UK, `pass-succession.json`): PASS, every check holds: w5-old held 42 blocks at DAA 260; the succession accepted on n2 at DAA 261 and carried by a block at DAA 266 on every node; at the fold (DAA 290) every node reads w5-new 37 blocks (7 mined alone) and w5-old 0 with `succeededTo`; w5-old to w5-third refused on n2 and n0 (`already handed`), w5-new to w5-old refused on n1 (`has itself handed`); locks 4 to 7 on every node after the fold; 0 rejected blocks, sinks agree; 317 s wall |
|
||||
| The cache rung visible in the RPC | `powEpoch.latencyLadderCache*` (proto fields 37 to 43); the daemon's ladder line | the testnet-shaped file prints `rungs 27, 35, 53, [88], [173], [267] shadow passes, cache [512 MiB] beside them` (`digest-testnet-shape.log`) |
|
||||
| The codec | `scheme_byte_and_succession_items_round_trip_and_an_older_decoder_stops_at_them` | green in the suite runs |
|
||||
| The digest, cross-binary | igneumd 75810130 against the 0.3.20 base dc141409 (bs0319's build), both with no file, devnet suffix 973 | both `079d8a7e736abbd4` (`digest-no-file.log`, `digest-base-dc141409.log`): the three fields at never move nothing; the ladder alone at 0 reads `772f9f8e3ef59ca1`, the testnet-shaped file (ladder at 0, scheme switch at 0, succession at 0, the cache rung) `60e842a738c7dea0`, on devnet params; the testnet lane's own number comes from `TESTNET_PARAMS` at its cut. The 0.3.18 line's `c562d70e` is behind the decimals, tail-emission and subsidy fields of the 0.3.19 and 0.3.20 lines, not behind these |
|
||||
| The gate build | `tools/build-remote.sh --priority gate` on build-1 at bdb34f62 | igneumd 57,554,336 B sha256 6d0aa37b..., igneum-miner 10,240,768 B sha256 69fc3c63... (commit string carried) |
|
||||
| The consensus suite | `cargo test --release -p kaspa-consensus` (all targets) on build-2 at f95178a1, twice | 114 passed, 0 failed, 3 ignored in the lib binary both times, the two moved targets 1 each; `cargo check -p kaspad` clean. Before the fix below the lib binary failed 1 of 114 on one of the two-node tests in three of four runs (the succession test once, the pre-existing F23 test twice), node 1 refusing block 61 at DAA 60 with `UnexpectedDifficulty`, the two nodes' bits about 17,000 apart in the mantissa |
|
||||
|
||||
Faults found on the way, both mine: (1) rule v3's frozen table stood at the lock before the carrier, where the old key still weighed and signed nothing, so nothing locked after the fold (fixed in `frozen_table`, 9322cc1d); (2) the template read the explicit-form switch from the process-wide static that only the daemon installs, so `TestConsensus` wrote the plain form (the manager holds the activation now, daa61847).
|
||||
|
||||
### 6a. The two-node refusal: found and fixed (f95178a1)
|
||||
|
||||
The probe on build-2: F23 alone three times, green each time; the three two-node tests together three times, green each time; so the refusal needed the rest of the lib binary. The cause: `consensus/src/consensus/services.rs` built the difficulty manager with `igneum::pow_epoch_blocks()`, the process-wide static, where every other argument of that constructor comes from `params`; two pruning-proof tests in the same binary (`igneum_m20_tests.rs:27`, `igneum_pow.rs:346`) install a 60-block schedule process-wide, so a `TestConsensus` built inside that window read a 60-block epoch into its difficulty manager while its partner read 3,600, the two disagreed on `reference_window` from DAA 60, and the second node refused block 61, the exact block of every refusal. The fix is the manager's own field, `params.pow_epoch_blocks`. The node's behaviour is unchanged (the daemon installs the static from the same params before building the consensus); the class is the static-at-construction read, the sibling of the signal-table race the node lane moved two installing tests for on 7 October 2026. The test helper now names the node and the block it refuses, which is what found it.
|
||||
|
||||
## 7. For the testnet lane
|
||||
|
||||
Override keys and testnet values: `sig_scheme: 0`, `sig_scheme_activation_daa: 0`, `finality_succession_activation_daa: 0`, `latency_ladder_cache_rung: {"mib": 512, "admissible": false}` (the six N rungs unchanged). Digest: with the ladder already active from genesis the cache rung's two fields enter after the six rungs' fields; the scheme switch adds two fields, the succession switch one. `print_testnet_object` prints the four keys.
|
||||
|
|
@ -2434,3 +2434,35 @@ Same rule as the counts above. 167 entries.
|
|||
|
||||
The bucket "Decided or closed by rule" counts each entry once: M8, M11 and P16 move there from Answered, so Answered is 28 less those three plus M16 and E17, as the table states; the sum of the rows is 167 with M8, M11, P16 and F3, F17 counted in Decided only.
|
||||
|
||||
|
||||
## Genesis forward-compatibility entries (7 October 2026, mission item 8, branch `genesis-forward`)
|
||||
|
||||
The three genesis fields of `docs/analysis/mission/mission.md` section 2.8, built on the node fork branch `genesis-forward` (from release-0.3.19-node dc141409) and the repo branch `genesis-forward`; the design and the gates in `docs/design/genesis-forward.md`. Every switch is never on the devnet (its digest c562d70e... does not move); the testnet genesis sets all three (the testnet lane re-pins and re-digests).
|
||||
|
||||
### GF1. A post-quantum signature scheme would need a hard fork, and every vote key is a public BLS12-381 point
|
||||
"When a quantum computer comes, every BLS vote key is forged and the chain has no way to change the scheme without a fork of the kind you say you never need."
|
||||
|
||||
Status: Fixed (7 October 2026). `sig_scheme` byte in every vote item and key reveal (`finality::SIG_SCHEME_BLS12_381` = 0), `Params::sig_scheme` and `Params::sig_scheme_activation_daa` in the digest once set; any other byte refused by every node (`scheme_refusal`) until a program class the 95 percent signal moves to names it (`igneum::sig_scheme_of_class`, empty today). Gate: the digest test `override_params_carry_the_genesis_forward_fields_and_the_digest_moves_only_when_set` and `consensus_digest_covers_every_consensus_field_and_nothing_else` (30 edits); a scheme-1 vote refused over RPC, in a block, and as a successor's scheme (`a_vote_reveal_or_successor_of_another_signature_scheme_is_refused_until_a_class_names_it`); the fast-time probe on three nodes (`infra/fast-time/key-succession.mjs`, `probe-scheme`).
|
||||
|
||||
Answer: The byte costs nothing now and a fork later. The flip is a class change (spec 03 W1 as amended): the aggregated-vote format ships first (naive ML-DSA-44 votes at 8,192 voters cost 57 GB a day, `future.md` 7.3), the scheme second, both by the 95 percent signal with a floor height. Per tier at migration: a home miner on any card runs the updater and signs one succession item (GF2); nothing hardware-specific, the signature runs on the CPU.
|
||||
|
||||
### GF2. A vote key cannot move: a miner who changes keys re-earns 30 days of weight, and so does the post-quantum migration
|
||||
"Your weight is bound to a key. Rotate it, lose a month. So nobody rotates, and the one day everyone must rotate, finality pauses for a month."
|
||||
|
||||
Status: Fixed (7 October 2026). W5 key succession implemented (spec 03 W5 as amended): a succession item signed by both keys, carried in blocks after the leaves, folds the old key's window blocks and forfeit term into the successor from the first checkpoint whose past holds the carrier (`successions_at`, `fold_successions`); once per key, a second succession refused, a successor that has itself handed over refused. Behind `finality_succession_activation_daa`. Gate: carried once and refused twice in the unit test on two nodes and in the fast-time harness.
|
||||
|
||||
Answer: The successor inherits the window, not a fresh one, so a key rotation costs no weight and the migration of GF1 is one item per key. The old key signs nothing after; a buyer of a key gets the clean transfer (spec 3.11.5) and the seller's copy is worthless.
|
||||
|
||||
### GF3. A 256 MB on-chip cache makes the lottery hash 2 to 3x cheaper for the card that has it, and the cache size is a constant
|
||||
"The dataset is built from a 256 MiB cache. A datacentre part with a 256 MB last-level cache keeps the whole cache on die and skips the memory. Consumer cards cannot."
|
||||
|
||||
Status: Fixed as a genesis lever, measurement owed (7 October 2026). The latency ladder carries one cache rung beside N (`LatencyLadder::cache_rung`, 512 MiB, `LadderSignal::Cache` = both ladder bits, the same 90 percent in seven windows, one rung, never back, in the digest with the ladder); inadmissible at genesis until the verifier bound and the 8 GB tier are measured (design doc section 3); visible in `getBlockTemplate`'s `powEpoch` (`latencyLadderCacheStep`, `latencyLadderCacheMib`, `latencyLadderCacheBps`, `latencyLadderCacheAdmissible`) and in the daemon's ladder line.
|
||||
|
||||
Answer: Consumer LLC is 96 to 128 MB today and datacentre 256 MB (`chip-model-v3`, approximate), so the shortcut is a datacentre card's today and a consumer card's in a generation or two. The rung lets the miners double the cache by signal the day the shortcut shows on the hash-rate charts, without a fork; the measurement that admits it is the same verifier bound as every N rung. Per tier: a 512 MiB cache is held by every tier from 8 GB up; the day-cache build doubles (about 0.7 s on the reference core today, approximate); the verifier reads the cache, not the dataset, so the 10 ms bound decides.
|
||||
|
||||
### GF4. The class-group VDF falls to the same quantum computer
|
||||
"Shor computes the class-group order; your epoch seed is then grindable."
|
||||
|
||||
Status: Conceded, flagged in spec 04 section 4.8 (7 October 2026); not sized. The fallback is a hash-chain delay behind the same version byte that moves the signature scheme; designed when the scheme flip is scheduled.
|
||||
|
||||
Answer: A grindable hourly seed is a liveness nuisance against the lottery, not a safety break: finality rests on the vote keys (GF1), the seed on the VDF. The two flip together by one class change.
|
||||
|
|
|
|||
112
docs/plans/mission-item-12-peer-directory.md
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
# Mission item 12: the weight-backed peer directory, prototype (status log)
|
||||
|
||||
Lane: horizon (mission items 4 and 12), 7 October 2026, after item 4's gate line. Branches: `peer-directory` (this repo, on
|
||||
master) and `peer-directory-node` (the fork, on release-0.3.20-node dc141409; targets 0.3.21). Times UK (BST) unless marked Z.
|
||||
|
||||
The item (mission.md 2.12, invent.md 7.1): a coinbase section where a key above dust may publish its node's address; a fresh
|
||||
node dials from that list weighted by 30-day weight, beside the DNS seeds. Gate: a fresh node with genesis peers only reaches 8
|
||||
outbound from the directory; a 34 percent attacker eclipses under 0.1 percent of 1,000 fresh starts (simulation is fine); the NAT
|
||||
fraction measured on the fleet (owed to the fleet lane, asked 7 October 13:0x UK; nothing rented). Dropped if the NAT fraction
|
||||
makes the list useless: this lane reports, it does not decide.
|
||||
|
||||
## 1. What exists to build on (read before writing)
|
||||
|
||||
| Where | What | Used how |
|
||||
|---|---|---|
|
||||
| fork `consensus/core/src/finality.rs` `FinalityItem` (tags 1 vote, 2 certificate, 3 evidence, 4 leave), `encode_section` / `decode_section` (`items || len || "IGNF"` at the end of the coinbase payload), `Leave` (W7: `daa || pubkey || signature`, signed by the vote key, carried LAST so a decoder from before its tag stops at it) | the section codec and the item shape to copy | the address item is tag 5 with the same carriage rule: last, after leaves, and only once its switch is on |
|
||||
| fork `consensus/src/processes/finality.rs` `ingest_leave` (block-carried, dated by the lowest carrier), `template_candidates` / `section_from` (what a template carries), `leave_active` (switch by DAA), `FinalityState.leaves` (persisted) | the ingest, the carriage and the switch pattern | the directory is a map key hash to (address, carrier DAA), persisted in the state the same way |
|
||||
| fork `components/connectionmanager/src/lib.rs` `handle_outbound_connections` | dials from the address manager's prioritised random iterator, then the DNS seeders when connections are still missing | the directory draw goes between the two: addresses drawn by weight from the directory are fed to the address manager and dialled before the seeders are asked |
|
||||
| fork `components/addressmanager/src/lib.rs` `add_address`, `iterate_prioritized_random_addresses` (weighted by failure count and prefix bucket) | the store a dialled address lives in | directory addresses enter it like seeder answers; the weight decides which enter, the store's own rule decides the order |
|
||||
| fork `consensus/core/src/config/params.rs` `consensus_digest` (a switch at never is outside the digest; set, it is in) | the activation pattern every 0.3.16 switch follows | `peer_directory_activation_daa`, never on every network |
|
||||
|
||||
## 2. Design, as built (prototype; fork branch peer-directory-node on release-0.3.20-node dc141409, commits 0cad5106 and db28d331 (tests); repo branch peer-directory on master 819d536b, commits 9a64d18c and 3e0dfa17 (gate), pushed to origin)
|
||||
|
||||
| Item | Rule |
|
||||
|---|---|
|
||||
| Wire | `AddressAnnounce { daa, ip: [u8; 16], port, pubkey, signature }` (core `finality.rs`), 171 B, signed by the vote key the header names under `IGNEUM_ADDR_V1` over `"igneum-addr-v1/" || chain_id || 0 || daa || ip || port` |
|
||||
| Carriage | in the MINER's extra data as `IGNP || hex(body)`, the key reveal's form (`IGNA` is already the EVM payout tag), never in the finality section: no switch for carriage, a node without the tag never meets it; `igneum-miner mine --announce <ip:port>` puts one in every template of every identity (`announced`, dated at the sink's DAA score when the run began) |
|
||||
| Reading | `FinalityManager::on_block_body` at or above `peer_directory_activation_daa`: the announcement must be by the block's own key, verify, and name a routable-in-form address; one node-local entry per key, the newest carrier wins (not persisted: a restarted node refills it from the blocks it sees; a prototype's gap) |
|
||||
| Report | `ConsensusApi::peer_directory()` rows with each key's weight at the latest determined checkpoint (0 under dust); entries older than a weight window dropped on the way |
|
||||
| Draw | `ConsensusApi::peer_directory_draw(n, exclude)`: without replacement, proportional to weight, keys under dust never drawn |
|
||||
| Dialling | `ConnectionManager::handle_outbound_connections`: after the address store's own iterator and before the DNS seeders, when connections are still missing, 2 x missing addresses from the draw enter the address store and are dialled at once (`DirectoryDraw` closure wired in `protocol/flows/src/service.rs` through the consensus's blocking session) |
|
||||
| Switch | `peer_directory_activation_daa`, never on every network (the four network constants), in the digest once set, in `OverrideParams` and the 60x file |
|
||||
| Not done | the RPC that lists the directory (the harness reads `getConnectedPeerInfo` and the node log instead); persistence across restarts; Ember and the phone's use of the list (invent.md 7.1's third hour) |
|
||||
|
||||
## 3. Gate plan
|
||||
|
||||
| Gate | How |
|
||||
|---|---|
|
||||
| a fresh node with genesis peers only reaches 8 outbound from the directory | fast-time network of 10 listing nodes (each announcing its loopback address) plus one fresh node started with `--outpeers=8`, `--nodnsseed` and one `--addpeer` to a genesis peer that serves blocks only; the fresh node's `getConnectedPeerInfo` shows 8 outbound within 5 min, all from the directory |
|
||||
| a 34 percent attacker eclipses under 0.1 percent of 1,000 fresh starts | `sim/peer-directory/eclipse.py`: the draw as implemented (weighted, without replacement, 8 peers) over a table where the attacker's keys hold 34 percent of the weight and list 34 percent of the addresses; 1,000 starts; expected 1.8e-4 at 8 peers (invent.md model E); also 16 peers and the honest-majority-of-peers reading |
|
||||
| the NAT fraction | RECEIVED from the fleet lane (ac055d60427caab99) at 13:1x UK, read at 12:06Z from each standing live-devnet node's own log, nothing rented: reachable from outside 2 of 14 (hub-1, RunPod, 26611 mapped: 2,844 inbound peer connections against 86 outbound; pool-1, RunPod, mapped 4463: 1,692 against 99); not reachable 12 of 14 (every Vast box: 0 inbound peer connections each, 96 to 542 outbound, no `--externalip`, no mapped port). So 86 percent of the fleet's nodes sit behind NAT and hold their 4 to 5 peers by dialling out; the two reachable nodes carry every inbound connection. Caveat (theirs): a rented fleet overstates the NAT share for datacentre operators and understates it for home miners; a fair read for "a node started with the defaults". Left out: the four Devnet 2 pods and the Hetzner seed. The marker was "Connected to incoming peer" against "Connected to outgoing peer" (the RPC server's local accepts are not peers). |
|
||||
|
||||
## 4. Runs
|
||||
|
||||
### The eclipse simulation (`sim/peer-directory/eclipse.py`, box 2, nice 10, 13:5x to 14:0x UK)
|
||||
|
||||
The draw as implemented (without replacement, proportional to weight at the latest checkpoint), 200 honest keys with Zipf
|
||||
weights, the attacker at 34 percent of the weight split over `m` keys of equal weight, seed 7.
|
||||
|
||||
| starts | peers | attacker keys | eclipsed | rate | model E a^n | attacker majority of the peers |
|
||||
|---|---|---|---|---|---|---|
|
||||
| 1,000 | 8 | 8 | 0 | 0 | 1.79e-4 | 4.0 percent |
|
||||
| 1,000 | 8 | 64 | 1 | 1.0e-3 | 1.79e-4 | 9.8 percent |
|
||||
| 1,000 | 8 | 1,000 | 0 | 0 | 1.79e-4 | 10.7 percent |
|
||||
| 1,000 | 16 | 8, 64, 1,000 | 0, 0, 0 | 0 | 3.19e-8 | 0, 9.2, 9.2 percent |
|
||||
| 100,000 | 8 | 8 | 0 | 0 | 1.79e-4 | 4.8 percent |
|
||||
| 100,000 | 8 | 64 | 14 | 1.4e-4 | 1.79e-4 | 10.7 percent |
|
||||
| 100,000 | 8 | 1,000 | 22 | 2.2e-4 | 1.79e-4 | 11.6 percent |
|
||||
|
||||
The gate's line (under 0.1 percent of 1,000 fresh starts) is met at 100,000 starts: 1.4e-4 and 2.2e-4, where 1,000 starts
|
||||
cannot resolve it (1 in 1,000 is exactly the line). Two readings beyond model E: with fewer attacker keys than peers an eclipse
|
||||
is impossible under the draw without replacement (the dust threshold, 100 blocks a window on mainnet, prices each attacker
|
||||
key at 100 blocks), and the attacker holds a MAJORITY of a fresh node's peers in about 11 percent of starts at 8 peers, which
|
||||
is the number that matters for a relay-level attack rather than a full eclipse; 16 peers takes that to 9 percent and the
|
||||
eclipse to zero in 1,000.
|
||||
|
||||
### Unit tests (box 2)
|
||||
|
||||
| Test | Result |
|
||||
|---|---|
|
||||
| core `address_announce_round_trips_and_verifies_under_its_key_only` | 1 of 1 |
|
||||
| node `the_peer_directory_lists_a_blocks_own_key_at_its_newest_address_only_when_switched_on` (known-failed first: the switch at never lists nothing) | 1 of 1 |
|
||||
| `cargo check -p kaspad -p igneum-miner --features kaspad/igneum-pow` on the branch | ok |
|
||||
|
||||
### The fast-time gate (box 2, `tools/fast-time-remote.sh --box 2`, binary of peer-directory-node 0cad5106, 13:27 to 13:34 UK)
|
||||
|
||||
`infra/fast-time/peer-directory.mjs`: ten listing nodes at one CPU thread each, every miner announcing its node's loopback
|
||||
p2p address, every node advertising an unroutable external ip (10.255.0.0/16) so ordinary address gossip hands a fresh node
|
||||
dead addresses only; after 200 s a fresh node starts with `--outpeers=8` and one `--addpeer` to node 0 and is watched 180 s.
|
||||
|
||||
| Case | Must | Got | Numbers |
|
||||
|---|---|---|---|
|
||||
| switch off, expect one (the known-failed case) | PASS | PASS | node 0 logged 0 listings; the fresh node held 1 outbound (node 0) for the whole watch, 0 draw lines, synced 448 blocks |
|
||||
| switch off, expect eight (the harness's own failed shape) | FAIL | FAIL | 1 outbound, 0 from the directory |
|
||||
| switch on, expect eight (THE GATE LINE) | PASS | PASS | node 0 logged 10 listings; the fresh node reached 8 outbound at 231.7 s (about 30 s after it started), 9 connections from the directory in one draw, synced 414 blocks |
|
||||
|
||||
Three harness faults on the way, each fixed: the log directory missing on the box (every case died at the redirect); the
|
||||
peer count read `isOutbound` where the fork's `RpcPeerInfo` is `is_outbound`; and the wrapper's first run checking the
|
||||
worktree root out on the box (fixed on horizon, 10140f9f, carried here).
|
||||
|
||||
## 5. Verdict line for main
|
||||
|
||||
The prototype does what invent.md 7.1 asked, on the numbers: a fresh node with one genesis peer and dead gossip reached 8
|
||||
outbound from the directory in about 30 s; the eclipse by a 34 percent attacker is 1.4e-4 to 2.2e-4 at 8 peers over 100,000
|
||||
starts (under the 0.1 percent line; 0 with 8 or fewer attacker keys, since the draw is without replacement), and the attacker
|
||||
holds a majority of a fresh node's peers in about 11 percent of starts, which is the number to watch. The NAT reading (2 of 14
|
||||
standing nodes reachable, 86 percent behind NAT with no inbound path) makes the list a SEED SUPPLEMENT, not a replacement:
|
||||
today it would list the two reachable fleet nodes beside the seeds, and a home miner's node (the 12-of-14 class unless the app
|
||||
maps a port) is a reader of the list, never a listing. Per tier: a home miner's node gains weight-backed peers beside the seeds
|
||||
at no cost and lists nothing by default; a rig or a pool node with a mapped port opts in with `--announce` and 171 bytes a block;
|
||||
the phone and Ember verify mode are not wired (not done). Listed as useful or dropped is main's and the project lead's call; this lane's
|
||||
reading is "keep as a seed supplement behind its switch", which costs 1.7 MB a day per node at 10,000 listing keys (approximate,
|
||||
from the item size) and nothing while the switch is never.
|
||||
|
||||
Open: an RPC that lists the directory; persistence across restarts; Ember and the phone; the testnet object and every network
|
||||
file carry no `peer_directory` field (the switch stays never until a cut sets it).
|
||||
|
||||
## 6. Rebase for 0.3.21 (14:0x UK, the shipper's order)
|
||||
|
||||
peer-directory-node rebased onto release-0.3.20-node c4459193 in one round, no conflict: tip 2e32d5f6, on both box mirrors under its name. Suite on build-2 at 2e32d5f6: igneum-miner 19 of 19, connectionmanager 0 tests, consensus lib 116 of 117 (the ban flake only; cargo stopped before consensus-core's target). Digest on tools/fleet/override.json: 7bd98cc4..., the same as the pin's binary. Handed to the node lane a283f5f0d364ceef0.
|
||||
|
||||
Digest on the file hub-1 runs (/root/fleet/override.json, sixteen fields, the copy at /tmp/igneum-devnet/override-v3-live.json on build-1): eada4bda8aa8368c2b2c3d17744bc7a70a0ff0e996dad681884d3ac5de1207eb, the shipper's string, read 14:1x UK from the branch binary on build-2; 7bd98cc4 was master's tools/fleet/override.json, another file. The live digest is unchanged by this branch.
|
||||
142
docs/plans/mission-item-4-fork-gate.md
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
# Mission item 4: weight-gated deep fork choice, the gate (status log)
|
||||
|
||||
Lane: horizon (mission items 4 and 12), started 7 October 2026, 12:41 UK, on main's brief. Branches: `horizon` (this repo, on master
|
||||
d1285cef) and `horizon-node` (the fork, on release-0.3.20-node dc141409, the 0.3.20 line; this work targets 0.3.21). Worktrees
|
||||
`igneum-wt-horizon` and `igneum-wt-horizon/vendor/igneum-node-horizon`. Times are UK (BST) unless marked Z.
|
||||
|
||||
The item (mission.md 2.4): a tip whose fork point is older than D (10 min of past-median time) is a fork-choice candidate only
|
||||
if the keys that built it hold at least a third of the weight table at the fork point. Gate, fast time: a 51 percent fresh-key
|
||||
fork from 15 min back is refused by every honest node; a one-third-weight fork is accepted; partition heal unchanged. Known-failed
|
||||
cases first.
|
||||
|
||||
## 1. What already existed (read before writing anything)
|
||||
|
||||
| Where | What | State |
|
||||
|---|---|---|
|
||||
| fork `consensus/src/processes/finality.rs` `deep_fork_refusal`, asked by `sink_search_algorithm` for every popped candidate | the rule, behind `fork_gate_activation_daa` (never on every network; in the digest once set) with `fork_gate_window_daa` 600 s; the fork point is the highest chain ancestor of the candidate on the sink's chain; depth = the larger of sink minus fork and candidate minus fork; builders = the vote keys of every block of the candidate's chain since the fork (chain blocks and mergesets); the table = `voters_at(fork)`; refused under `3 x weight < total`; node-local memo per refused block | on the 0.3.20 line since 61b22057 (6 October), fixes 3301cf32 (depth along both chains) and aa0182aa (no extension shortcut) |
|
||||
| fork unit tests | `without_the_fork_gate_a_minor_keys_deep_fork_wins` (known-failed), `the_fork_gate_refuses_a_deep_fork_under_a_third_and_passes_the_rest` (25 percent refused, 75 percent passes, inside the window passes) | green on that line |
|
||||
| `infra/fast-time/fork-gate.mjs` on branch ca3-v4-node (never on master) | a TWO-node harness: A at 75 percent, B at 25 percent, A IDLE through the split; cases gate-on hold (PASS 23:45Z 6 Oct), gate-off reorg (PASS), gate-off hold (FAIL as it must); run on the Mac; a `pkill -f` on the devnet suffix | the record in `docs/plans/counter-asic-3-node.md` 7.5 |
|
||||
| the live devnet and Devnet 2 override files, the testnet object | no `fork_gate` field anywhere: the switch is never on every network | unchanged by this lane |
|
||||
|
||||
What the mission gate asks beyond that record: a FRESH key (0 of the table, not 25 percent), the honest side MINING through the
|
||||
split (the record idled it), EVERY honest node (two, not one), the one-third case accepted, and the partition heal shown unchanged
|
||||
with the gate on and off. Nothing in the rule needed to change for any of these; this lane adds the proof.
|
||||
|
||||
## 2. What this lane added
|
||||
|
||||
| Piece | Where | What |
|
||||
|---|---|---|
|
||||
| Fresh-key unit test | fork `a_fresh_keys_deep_fork_wins_only_with_the_gate_off` | known-failed first: at never a key with no block in the table wins by blue work; at 0 it is refused with weight 0 of the table |
|
||||
| One-third line unit test | fork `the_gate_passes_at_one_third_of_the_table_and_refuses_under_it` | eight (honest mix, fork height) pairs; each outcome equals `3 x weight >= total` read from the table the gate reads; both sides seen |
|
||||
| Three-node harness | `infra/fast-time/fork-gate.mjs` (new on master's line) | H1 and H2 honest and mining through every phase, B the third node; modes attack (B fresh, 3 of 5 threads), third (B at about half of the table), partition (H1 against H2); a reorg is read from the chain (`getVirtualChainFromBlock` of the pre-cut tip lists removed blocks), never from a key; blue work compared as BigInt; leftovers stopped by pid file |
|
||||
| The six-case runner | `infra/fast-time/fork-gate-gate.mjs` | known-failed cases first, then the gate line, the one-third case, the two partition heals; GREEN only when every case gives the verdict it must and the two heals agree |
|
||||
| Box wrapper | `tools/fast-time-remote.sh` (whole-body block; listed in `tools/ci/whole-body-check.sh`) | runs a harness on a box under a slot with a holder line and a JSONL row, the node binaries from a fork worktree's target on the box, results fetched back |
|
||||
|
||||
## 2a. The hole the known-failed cases found (13:1x to 13:3x UK)
|
||||
|
||||
The one-third unit test failed on box 2 at its second pair: B on every fourth block, fork at height 50, B holding 12 of 49 at
|
||||
the fork, and the private tip WON. A probe test (temporary, since removed) read the gate's own answer at fork heights 40, 45,
|
||||
48, 50, 55, 60 and 65: refused at 40, 48 and 60; let through at 45, 50 and 55 (65 is inside the window, a legitimate pass).
|
||||
The let-through rows read "keys 2, signed 44 of 44": the honest key A was in the attacker's builders. The pattern is the fork
|
||||
block's own key: heights that are multiples of 4 sit on B's blocks and were refused; the others sit on A's blocks and passed.
|
||||
|
||||
Cause: `collect_builders` took each chain block's mergeset (blues and reds) and GHOSTDAG's `mergeset_blues[0]` is the block's
|
||||
selected parent, so the first private block above the fork carried the FORK block into the builders, and the fork block was
|
||||
A's. A 25 percent key forking right after a 75 percent key's block walked through the gate with A's weight on its side. The
|
||||
same reading let a private chain that merges honest blocks as side parents inherit every merged key. The 6 October harness
|
||||
PASS (23:45Z) was luck: its pre-cut sink was B-built, so the leaked key was B's own.
|
||||
|
||||
Fix (fork, `collect_builders(block, sink, keys)`): a builder is the key of a block the sink does NOT have (not a DAG ancestor
|
||||
of the sink, the sink itself included). The fork block is the sink's; honest blocks the attacker merged are the sink's; a
|
||||
partition side's own blocks are not, so a heal is unchanged. New unit test, known-failed shape first:
|
||||
`a_deep_fork_counts_only_the_blocks_the_sink_lacks_as_builders` (B from A's block at 45 refused; a private chain merging
|
||||
honest blocks 46 to 80 wins at never and is refused at 0).
|
||||
|
||||
Also seen: `ban_is_decided_by_the_carrying_block_so_nodes_agree_on_every_voter_list` died with `UnexpectedDifficulty` in the
|
||||
full crate run (box 2 under load 65) and passed alone (1 of 1, 13:1x UK); not this lane's change, noted for the suite count.
|
||||
|
||||
## 3. Runs
|
||||
|
||||
### Commits
|
||||
|
||||
| Repo | Branch | Commit | What |
|
||||
|---|---|---|---|
|
||||
| fork | horizon-node (on release-0.3.20-node dc141409) | eb32d2e0 | the builders fix (`collect_builders` skips every block the sink has) and the fork-gate tests on the two-instance lab |
|
||||
| fork | horizon-node | a6a71ac2 | the lab inserts into the judge first and rebuilds a block refused on `UnexpectedDifficulty` (the suite's flake class) |
|
||||
| repo | horizon (on master d1285cef) | 0dc2adff | the three-node harness, the six-case runner, the box wrapper, the whole-body check row |
|
||||
|
||||
### Suites (box 2, igneum-build-2, nice 10 on 32 cores)
|
||||
|
||||
| Run (UK) | Command | Result |
|
||||
|---|---|---|
|
||||
| 12:5x | `-- test --release -p kaspa-consensus` (the first test version, no fix) | 111 of 113: my one-third test FAIL (the hole), `ban_is_decided_by_the_carrying_block...` FAIL on `UnexpectedDifficulty` (load 65; passes alone 13:1x, 1 of 1) |
|
||||
| 13:2x | `-- test --release -p kaspa-consensus --lib processes::finality::tests` (the fix, the lab) | 24 of 24 |
|
||||
| 13:3x | `-- test --release -p kaspa-consensus` (eb32d2e0 content) | 112 of 114: two lab tests FAIL on `UnexpectedDifficulty` (the same flake class, now reachable by the lab's second instance) |
|
||||
| 13:3x | `-- test --release -p kaspa-consensus` at a6a71ac2, 0dcaf4c5, ca7acb99 (the lab's rebuild, a pause between rebuilds, salted hashes) | 111 or 112 of 114 each: the two labs whose instances share one config still FAIL at block 61 under load; the probes showed `UnexpectedDifficulty` thirty times over 7.5 s, so neither clock nor hash memo |
|
||||
| 13:38 | `-- test --release -p kaspa-consensus` at 6eb21fc9 (the lab on `DifficultyRule::KaspaSampled`, DAG-only bits) | 113 of 114 in the lib target, 3 ignored; the one FAIL is the pre-existing `ban_is_decided_by_the_carrying_block_so_nodes_agree_on_every_voter_list` (the same class: the dual rule's template bits and header stamp disagree at block 61, the first retarget, under load; passes alone). The lib target failing stops cargo before the integration targets. |
|
||||
|
||||
Fork commits after eb32d2e0, test-only: a6a71ac2, 0dcaf4c5, ca7acb99, f225ed9f, 6eb21fc9 (the lab inserts into the judge first and rebuilds on the flake; a pause between rebuilds; every lab its own hash words; the DAG-only difficulty rule; the import). The binary content of kaspad and igneum-miner is the same from eb32d2e0 on; the gate binary carries 6eb21fc9.
|
||||
|
||||
### Build (box 1, igneum-build-1)
|
||||
|
||||
| Run (UK) | Command | Result |
|
||||
|---|---|---|
|
||||
| (pending) | `tools/build-remote.sh --no-fetch -- build --release -p kaspad -p igneum-miner --features kaspad/igneum-pow` from the fork worktree at a6a71ac2 (igneum-pow at 8c728ca3 through an untracked paths override to `igneum-pow-amend`, the 0.3.20 pairing); two earlier submissions of the uncommitted tree were stopped by pid so the gate binary carries the commit | |
|
||||
|
||||
### Tree checks (the Mac, checks only)
|
||||
|
||||
`tools/ci/pre-push.sh --ci` on horizon 0dc2adff: GREEN, 43 checks in 31 s (13:3x UK).
|
||||
|
||||
### The gate (box 2, igneum-build-2, by main's word at 13:4x UK: box 1's slots stay with the 0.3.20 pin)
|
||||
|
||||
Binary: `igneumd` and `igneum-miner` of horizon-node 6eb21fc9 (igneum-pow 8c728ca3), built on box 2 at 13:5x UK
|
||||
(`tools/build-remote.sh --box 2`, 113 s); run through `tools/fast-time-remote.sh --box 2` (one slot, the bounded class, 583 s
|
||||
for the six cases side by side), case summaries and logs in `docs/plans/mission-item-4-gate/`. Window 60 DAA, joint 240 s,
|
||||
split 180 s, watch 150 s; honest nodes H1 and H2 at one CPU thread each through every phase; the attacker at 3 threads in
|
||||
the split (60 percent of the CPU hash: the refusal reads weight, not how much heavier the chain is).
|
||||
|
||||
| Case | Must | Got | Side 2 at the fork | Fork depth (DAA) | Blue work at the heal, side 2 against H1 | Honest nodes after the heal |
|
||||
|---|---|---|---|---|---|---|
|
||||
| attack, gate off, expect reorg (the rule's known-failed case) | PASS | PASS | 0 bps (fresh key) | 191 | 17,470,131 against 14,893,198 | H1 and H2 reorged at 510 s, 0 refusal lines |
|
||||
| attack, gate off, expect hold (the harness's own failed shape) | FAIL | FAIL | 0 bps | 179 | 19,683,187 against 17,459,678 | H1 and H2 reorged at 480 s, 0 refusal lines |
|
||||
| attack, gate on, expect hold (THE GATE LINE) | PASS | PASS | 0 bps | 197 | 20,297,242 against 14,807,915 | H1 and H2 HELD for the whole watch, 177 refusal lines each, both know side 2's tip; side 2 kept its chain |
|
||||
| third, gate on, expect reorg (a one-third-weight fork accepted) | PASS | PASS | 6,000 bps | 166 | 28,969,222 against 24,628,833 | H1 and H2 reorged at 477 s, 0 refusal lines |
|
||||
| partition, gate on, expect reorg | PASS | PASS | 3,719 bps | 194 | 18,089,683 against 11,490,863 | H1 reorged at 507 s, 0 refusal lines; H2 kept its chain |
|
||||
| partition, gate off, expect reorg (the same outcome) | PASS | PASS | 5,583 bps | 191 | 19,576,159 against 12,270,631 | H1 reorged at 507 s, 0 refusal lines; H2 kept its chain |
|
||||
|
||||
GATE GREEN, 13:58 UK: 6 of 6 cases gave the verdict they must; the partition heal is the same with the gate on and off
|
||||
(both reorg H1 onto the heavier side, 0 refusals). Reading "15 min back" at fast time: the devnet window is 600 s and the
|
||||
mission's 15 min is one and a half windows; the harness keeps the window at 60 DAA and the split at 180 s, three windows
|
||||
deep, so the refusal was asked from 61 s of the split on and held for its whole second half.
|
||||
|
||||
## 4. Consequences per tier
|
||||
|
||||
One sentence: with the fix, a renter's or a chain-splitter's deep reorg is bounded by weight for every tier alike, and an
|
||||
honest key's own blocks are never refused.
|
||||
|
||||
| Tier | What the number means |
|
||||
|---|---|
|
||||
| Home miner (one card, any size, Windows, Linux or macOS, any vendor) | its node refuses the same tips a rig's or a pool's node refuses; a fresh-key chain from more than ten minutes back never becomes its sink while the key that built it holds under a third of the window; nothing to configure, nothing to pay; the memo costs one mergeset per refused block |
|
||||
| Rig | the same; a rig's own blocks after a connectivity gap are built by its own keys and pass on share |
|
||||
| Pool user | the pool's node holds the chain the pool mined; a renter cannot reorganise the pool's payouts past ten minutes without a third of the weight |
|
||||
| Exchange and holder | a 12-hour double spend during a pause or in the first month (51-percent.md section 5 rank 2, USD 146 at 1 GH/s) is gone: the deep fork is refused at every honest node, lock or no lock |
|
||||
| The rule's cost | none for certificates; a partition side under a third cannot reorg the other past the window (the intended outcome, unchanged by the fix) |
|
||||
|
||||
Before the fix the bound held only when the fork sat on a block of a small key; a renter forking right after a large
|
||||
miner's block, or merging honest blocks into its chain, walked through on every tier.
|
||||
|
||||
## 5. Open
|
||||
|
||||
| Item | Owner |
|
||||
|---|---|
|
||||
| Merge: horizon-node is on release-0.3.20-node dc141409; main's word is to rebase onto the 0.3.20 pin once named (c4459193 the candidate) for 0.3.21; never a push to a release branch | this lane, when main names the pin |
|
||||
| The difficulty red: `ban_is_decided_by_the_carrying_block...` and, before the lab moved to the DAG-only rule, two lab tests, on `UnexpectedDifficulty` at block 61 (the first retarget) under the full suite's load; the dual rule's template bits come from a virtual resolved at one instant and the header is stamped at a later one | the node lane for 0.3.21 (main's word: logged, not fixed here) |
|
||||
| The fork's test block builder asks the gate (it runs the sink search from the parents it is given): any future test that builds a private chain on a gated instance builds it on the fork block instead; the lab's two-instance shape is the pattern | the node lane; a note in `consensus/src/consensus/test_consensus.rs` is owed |
|
||||
| `tools/box` named in the brief does not exist; the box tooling is `tools/build-remote.sh` on `infra/build-server/lib.sh`, which `tools/fast-time-remote.sh` uses; the wrapper's first run checked the worktree root out on box 2 and took the fork sources with it (fixed the same hour: overlay only, 10140f9f) | main's reading |
|
||||
| The devnet, Devnet 2 and the testnet object carry no `fork_gate` field: the switch stays never everywhere until a cut sets it (in the digest once set) | the shipper and the project lead |
|
||||
|
||||
## 6. Rebase for 0.3.21 (14:0x UK, the shipper's order)
|
||||
|
||||
horizon-node rebased onto release-0.3.20-node c4459193 (the 0.3.20 pin) in one round, no conflict: tip 437f0438, on both box mirrors under its name. Suite on build-2 at 437f0438: `-p kaspa-consensus` lib 117 of 119, 3 ignored (the ban difficulty flake and `a_chain_that_misses_an_adopted_lock_never_locks_here`, which passes alone 1 of 1 and passed in every earlier full run; load 113). Digest on tools/fleet/override.json (origin/master): 7bd98cc4..., the same as the pin's own binary on that file. Handed to the node lane a283f5f0d364ceef0 for the 0.3.21 merge after 55768f88, miner-reliability-20 and pool-finish-node.
|
||||
|
||||
Digest on the file hub-1 runs (/root/fleet/override.json, sixteen fields, the copy at /tmp/igneum-devnet/override-v3-live.json on build-1): eada4bda8aa8368c2b2c3d17744bc7a70a0ff0e996dad681884d3ac5de1207eb, the shipper's string, read 14:1x UK from the branch binary on build-2; 7bd98cc4 was master's tools/fleet/override.json, another file. The live digest is unchanged by this branch.
|
||||
|
|
@ -0,0 +1,933 @@
|
|||
{
|
||||
"pass": false,
|
||||
"expect": "hold",
|
||||
"case": "attack-gate-off-expect-hold",
|
||||
"mode": "attack",
|
||||
"gate": "off",
|
||||
"window": 60,
|
||||
"joint": 240,
|
||||
"split": 180,
|
||||
"watch": 150,
|
||||
"threads": {
|
||||
"honest_each": 1,
|
||||
"attacker_split": 3,
|
||||
"attacker_joint": 0
|
||||
},
|
||||
"keys": {
|
||||
"h1": "8da9ddee…",
|
||||
"h2": "eda9cde4…",
|
||||
"side2": "0e2c6fe2…"
|
||||
},
|
||||
"share_at_fork": {
|
||||
"side2": 0,
|
||||
"others": 120,
|
||||
"side2_bps": 0
|
||||
},
|
||||
"fork_daa": 247,
|
||||
"fork_depth_daa_at_heal": 179,
|
||||
"sinks": {
|
||||
"joint": {
|
||||
"h1": {
|
||||
"hash": "0535d8ae67287238ee528bae5ab1f366273bd1c65c6a94342ec3879a40b81c88",
|
||||
"blocks": 248,
|
||||
"daa": 247,
|
||||
"blue": 248,
|
||||
"blueWork": "11209205",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"h2": {
|
||||
"hash": "0535d8ae67287238ee528bae5ab1f366273bd1c65c6a94342ec3879a40b81c88",
|
||||
"blocks": 248,
|
||||
"daa": 247,
|
||||
"blue": 248,
|
||||
"blueWork": "11209205",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"side2": {
|
||||
"hash": "0535d8ae67287238ee528bae5ab1f366273bd1c65c6a94342ec3879a40b81c88",
|
||||
"blocks": 248,
|
||||
"daa": 247,
|
||||
"blue": 248,
|
||||
"blueWork": "11209205",
|
||||
"key": "8da9ddee…"
|
||||
}
|
||||
},
|
||||
"split": {
|
||||
"h1": {
|
||||
"hash": "d5347d2cd3468901fda8e5a1caffe0be55d45eb12739577fadb0141d2291c2ba",
|
||||
"blocks": 412,
|
||||
"daa": 411,
|
||||
"blue": 412,
|
||||
"blueWork": "17459678",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"h2": {
|
||||
"hash": "d5347d2cd3468901fda8e5a1caffe0be55d45eb12739577fadb0141d2291c2ba",
|
||||
"blocks": 412,
|
||||
"daa": 411,
|
||||
"blue": 412,
|
||||
"blueWork": "17459678",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"side2": {
|
||||
"hash": "bfdb75e384417228a85f4098f8f2bb65d40c271ce674bea2d1cc8a3c6c335f53",
|
||||
"blocks": 427,
|
||||
"daa": 426,
|
||||
"blue": 427,
|
||||
"blueWork": "19683187",
|
||||
"key": "0e2c6fe2…"
|
||||
}
|
||||
}
|
||||
},
|
||||
"per_node": {
|
||||
"h1": {
|
||||
"held": false,
|
||||
"reorged": true,
|
||||
"reorg_at_s": 480.3,
|
||||
"knows_side2_tip": true,
|
||||
"refusal_lines": 0
|
||||
},
|
||||
"h2": {
|
||||
"held": false,
|
||||
"reorged": true,
|
||||
"reorg_at_s": 480.3,
|
||||
"knows_side2_tip": true,
|
||||
"refusal_lines": 0
|
||||
}
|
||||
},
|
||||
"checks": {
|
||||
"side2_under_a_third_at_fork": true,
|
||||
"fork_deeper_than_window": true,
|
||||
"side2_heavier_at_heal": true,
|
||||
"every_honest_node_learned_side2_chain": true,
|
||||
"every_honest_node_held": false,
|
||||
"every_honest_node_reorged": true,
|
||||
"every_honest_node_logged_a_refusal": false,
|
||||
"no_honest_node_logged_a_refusal": true,
|
||||
"side2_kept_its_chain": true
|
||||
},
|
||||
"failed_checks": [
|
||||
"every_honest_node_held",
|
||||
"every_honest_node_logged_a_refusal"
|
||||
],
|
||||
"refusal_example": null,
|
||||
"samples": [
|
||||
{
|
||||
"t": 425.2,
|
||||
"h1": {
|
||||
"blocks": 416,
|
||||
"sink": "7b85c0879ec1a3f0",
|
||||
"daa": 414,
|
||||
"blue": 415,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 416,
|
||||
"sink": "7b85c0879ec1a3f0",
|
||||
"daa": 414,
|
||||
"blue": 415,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 435,
|
||||
"sink": "8bb7e69cea95ecaa",
|
||||
"blue": 435,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 430.2,
|
||||
"h1": {
|
||||
"blocks": 423,
|
||||
"sink": "44ee221996bf6519",
|
||||
"daa": 422,
|
||||
"blue": 423,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 423,
|
||||
"sink": "44ee221996bf6519",
|
||||
"daa": 422,
|
||||
"blue": 423,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 441,
|
||||
"sink": "46ee56ca78abcfa4",
|
||||
"blue": 441,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 435.2,
|
||||
"h1": {
|
||||
"blocks": 430,
|
||||
"sink": "fe81d0b598b34760",
|
||||
"daa": 429,
|
||||
"blue": 430,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 430,
|
||||
"sink": "fe81d0b598b34760",
|
||||
"daa": 429,
|
||||
"blue": 430,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 445,
|
||||
"sink": "bf71c714df908384",
|
||||
"blue": 445,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 440.2,
|
||||
"h1": {
|
||||
"blocks": 440,
|
||||
"sink": "acab21ca95900afc",
|
||||
"daa": 439,
|
||||
"blue": 440,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 440,
|
||||
"sink": "acab21ca95900afc",
|
||||
"daa": 439,
|
||||
"blue": 440,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 448,
|
||||
"sink": "b8fccb90e479e8a5",
|
||||
"blue": 448,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 445.3,
|
||||
"h1": {
|
||||
"blocks": 443,
|
||||
"sink": "d9051d6139ae8afa",
|
||||
"daa": 442,
|
||||
"blue": 443,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 443,
|
||||
"sink": "d9051d6139ae8afa",
|
||||
"daa": 442,
|
||||
"blue": 443,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 456,
|
||||
"sink": "2cc48c7a2084d5e4",
|
||||
"blue": 456,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 450.3,
|
||||
"h1": {
|
||||
"blocks": 450,
|
||||
"sink": "cea4dc9c673bd13a",
|
||||
"daa": 449,
|
||||
"blue": 450,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 450,
|
||||
"sink": "cea4dc9c673bd13a",
|
||||
"daa": 449,
|
||||
"blue": 450,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 466,
|
||||
"sink": "4f46263c45d1d32a",
|
||||
"blue": 466,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 455.3,
|
||||
"h1": {
|
||||
"blocks": 452,
|
||||
"sink": "1a8679962a368c21",
|
||||
"daa": 451,
|
||||
"blue": 452,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 452,
|
||||
"sink": "1a8679962a368c21",
|
||||
"daa": 451,
|
||||
"blue": 452,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 472,
|
||||
"sink": "12dcc825edc2fa17",
|
||||
"blue": 472,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 460.3,
|
||||
"h1": {
|
||||
"blocks": 454,
|
||||
"sink": "2a7c0240cfe56042",
|
||||
"daa": 453,
|
||||
"blue": 454,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 454,
|
||||
"sink": "2a7c0240cfe56042",
|
||||
"daa": 453,
|
||||
"blue": 454,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 480,
|
||||
"sink": "bbb6cf12cfd7419f",
|
||||
"blue": 480,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 465.3,
|
||||
"h1": {
|
||||
"blocks": 454,
|
||||
"sink": "2a7c0240cfe56042",
|
||||
"daa": 453,
|
||||
"blue": 454,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 454,
|
||||
"sink": "2a7c0240cfe56042",
|
||||
"daa": 453,
|
||||
"blue": 454,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 488,
|
||||
"sink": "f443140c40db1ff4",
|
||||
"blue": 488,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 470.3,
|
||||
"h1": {
|
||||
"blocks": 456,
|
||||
"sink": "2c2bf05b3992cb6b",
|
||||
"daa": 455,
|
||||
"blue": 456,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 456,
|
||||
"sink": "2c2bf05b3992cb6b",
|
||||
"daa": 455,
|
||||
"blue": 456,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 493,
|
||||
"sink": "0dd0e90fa5bb4330",
|
||||
"blue": 493,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 475.3,
|
||||
"h1": {
|
||||
"blocks": 458,
|
||||
"sink": "cde3915508aeb008",
|
||||
"daa": 457,
|
||||
"blue": 458,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 458,
|
||||
"sink": "cde3915508aeb008",
|
||||
"daa": 457,
|
||||
"blue": 458,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 496,
|
||||
"sink": "7adc2714fa7a10c9",
|
||||
"blue": 496,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 480.3,
|
||||
"h1": {
|
||||
"blocks": 505,
|
||||
"sink": "f08f99c6711510d7",
|
||||
"daa": 504,
|
||||
"blue": 505,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 505,
|
||||
"sink": "f08f99c6711510d7",
|
||||
"daa": 504,
|
||||
"blue": 505,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 505,
|
||||
"sink": "f08f99c6711510d7",
|
||||
"blue": 505,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 485.3,
|
||||
"h1": {
|
||||
"blocks": 509,
|
||||
"sink": "9dfb826d38e1f6a4",
|
||||
"daa": 508,
|
||||
"blue": 509,
|
||||
"key": "8da9ddee",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 509,
|
||||
"sink": "9dfb826d38e1f6a4",
|
||||
"daa": 508,
|
||||
"blue": 509,
|
||||
"key": "8da9ddee",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 509,
|
||||
"sink": "9dfb826d38e1f6a4",
|
||||
"blue": 509,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 490.4,
|
||||
"h1": {
|
||||
"blocks": 511,
|
||||
"sink": "a9bdeeb2148190f1",
|
||||
"daa": 510,
|
||||
"blue": 511,
|
||||
"key": "8da9ddee",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 511,
|
||||
"sink": "a9bdeeb2148190f1",
|
||||
"daa": 510,
|
||||
"blue": 511,
|
||||
"key": "8da9ddee",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 511,
|
||||
"sink": "a9bdeeb2148190f1",
|
||||
"blue": 511,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 495.4,
|
||||
"h1": {
|
||||
"blocks": 522,
|
||||
"sink": "fa5aefefc31e1c4c",
|
||||
"daa": 521,
|
||||
"blue": 522,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 522,
|
||||
"sink": "fa5aefefc31e1c4c",
|
||||
"daa": 521,
|
||||
"blue": 522,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 522,
|
||||
"sink": "fa5aefefc31e1c4c",
|
||||
"blue": 522,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 500.4,
|
||||
"h1": {
|
||||
"blocks": 525,
|
||||
"sink": "3f659b8355cf6fb8",
|
||||
"daa": 524,
|
||||
"blue": 525,
|
||||
"key": "8da9ddee",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 525,
|
||||
"sink": "3f659b8355cf6fb8",
|
||||
"daa": 524,
|
||||
"blue": 525,
|
||||
"key": "8da9ddee",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 525,
|
||||
"sink": "3f659b8355cf6fb8",
|
||||
"blue": 525,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 505.4,
|
||||
"h1": {
|
||||
"blocks": 528,
|
||||
"sink": "2b00a2431aecf64d",
|
||||
"daa": 527,
|
||||
"blue": 528,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 528,
|
||||
"sink": "2b00a2431aecf64d",
|
||||
"daa": 527,
|
||||
"blue": 528,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 528,
|
||||
"sink": "2b00a2431aecf64d",
|
||||
"blue": 528,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 510.4,
|
||||
"h1": {
|
||||
"blocks": 534,
|
||||
"sink": "f10f202f1b8adf79",
|
||||
"daa": 533,
|
||||
"blue": 534,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 534,
|
||||
"sink": "f10f202f1b8adf79",
|
||||
"daa": 533,
|
||||
"blue": 534,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 534,
|
||||
"sink": "f10f202f1b8adf79",
|
||||
"blue": 534,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 515.4,
|
||||
"h1": {
|
||||
"blocks": 541,
|
||||
"sink": "d70cd34944d6d565",
|
||||
"daa": 540,
|
||||
"blue": 541,
|
||||
"key": "8da9ddee",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 541,
|
||||
"sink": "d70cd34944d6d565",
|
||||
"daa": 540,
|
||||
"blue": 541,
|
||||
"key": "8da9ddee",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 541,
|
||||
"sink": "d70cd34944d6d565",
|
||||
"blue": 541,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 520.4,
|
||||
"h1": {
|
||||
"blocks": 546,
|
||||
"sink": "35d62b928d603bac",
|
||||
"daa": 545,
|
||||
"blue": 546,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 546,
|
||||
"sink": "35d62b928d603bac",
|
||||
"daa": 545,
|
||||
"blue": 546,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 546,
|
||||
"sink": "35d62b928d603bac",
|
||||
"blue": 546,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 525.4,
|
||||
"h1": {
|
||||
"blocks": 552,
|
||||
"sink": "11ee723145434436",
|
||||
"daa": 551,
|
||||
"blue": 552,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 552,
|
||||
"sink": "11ee723145434436",
|
||||
"daa": 551,
|
||||
"blue": 552,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 552,
|
||||
"sink": "11ee723145434436",
|
||||
"blue": 552,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 530.4,
|
||||
"h1": {
|
||||
"blocks": 561,
|
||||
"sink": "096fe4e02ba023a4",
|
||||
"daa": 560,
|
||||
"blue": 561,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 561,
|
||||
"sink": "096fe4e02ba023a4",
|
||||
"daa": 560,
|
||||
"blue": 561,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 561,
|
||||
"sink": "096fe4e02ba023a4",
|
||||
"blue": 561,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 535.4,
|
||||
"h1": {
|
||||
"blocks": 566,
|
||||
"sink": "58b6d24c4920da55",
|
||||
"daa": 565,
|
||||
"blue": 566,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 566,
|
||||
"sink": "58b6d24c4920da55",
|
||||
"daa": 565,
|
||||
"blue": 566,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 566,
|
||||
"sink": "58b6d24c4920da55",
|
||||
"blue": 566,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 540.4,
|
||||
"h1": {
|
||||
"blocks": 567,
|
||||
"sink": "3a757d2721963b97",
|
||||
"daa": 566,
|
||||
"blue": 567,
|
||||
"key": "8da9ddee",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 567,
|
||||
"sink": "3a757d2721963b97",
|
||||
"daa": 566,
|
||||
"blue": 567,
|
||||
"key": "8da9ddee",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 567,
|
||||
"sink": "3a757d2721963b97",
|
||||
"blue": 567,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 545.4,
|
||||
"h1": {
|
||||
"blocks": 572,
|
||||
"sink": "40cb1b5ff6ffa6e2",
|
||||
"daa": 571,
|
||||
"blue": 572,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 572,
|
||||
"sink": "40cb1b5ff6ffa6e2",
|
||||
"daa": 571,
|
||||
"blue": 572,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 572,
|
||||
"sink": "40cb1b5ff6ffa6e2",
|
||||
"blue": 572,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 550.4,
|
||||
"h1": {
|
||||
"blocks": 577,
|
||||
"sink": "e3f1416a5521d05a",
|
||||
"daa": 576,
|
||||
"blue": 577,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 577,
|
||||
"sink": "e3f1416a5521d05a",
|
||||
"daa": 576,
|
||||
"blue": 577,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 577,
|
||||
"sink": "e3f1416a5521d05a",
|
||||
"blue": 577,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 555.5,
|
||||
"h1": {
|
||||
"blocks": 584,
|
||||
"sink": "38b6a8056ad74b9d",
|
||||
"daa": 583,
|
||||
"blue": 584,
|
||||
"key": "8da9ddee",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 584,
|
||||
"sink": "38b6a8056ad74b9d",
|
||||
"daa": 583,
|
||||
"blue": 584,
|
||||
"key": "8da9ddee",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 584,
|
||||
"sink": "38b6a8056ad74b9d",
|
||||
"blue": 584,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 560.5,
|
||||
"h1": {
|
||||
"blocks": 589,
|
||||
"sink": "69c3e39a47332124",
|
||||
"daa": 588,
|
||||
"blue": 589,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 589,
|
||||
"sink": "69c3e39a47332124",
|
||||
"daa": 588,
|
||||
"blue": 589,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 589,
|
||||
"sink": "69c3e39a47332124",
|
||||
"blue": 589,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 565.5,
|
||||
"h1": {
|
||||
"blocks": 592,
|
||||
"sink": "6fe943b09aa71ffa",
|
||||
"daa": 591,
|
||||
"blue": 592,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 592,
|
||||
"sink": "6fe943b09aa71ffa",
|
||||
"daa": 591,
|
||||
"blue": 592,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 592,
|
||||
"sink": "6fe943b09aa71ffa",
|
||||
"blue": 592,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 570.5,
|
||||
"h1": {
|
||||
"blocks": 595,
|
||||
"sink": "b5217027de64f1a2",
|
||||
"daa": 594,
|
||||
"blue": 595,
|
||||
"key": "8da9ddee",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 595,
|
||||
"sink": "b5217027de64f1a2",
|
||||
"daa": 594,
|
||||
"blue": 595,
|
||||
"key": "8da9ddee",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 595,
|
||||
"sink": "b5217027de64f1a2",
|
||||
"blue": 595,
|
||||
"reorged": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"node": "/srv/builds/igneum-wt-horizon/vendor/igneum-node-horizon/target/release/igneumd",
|
||||
"miner": "/srv/builds/igneum-wt-horizon/vendor/igneum-node-horizon/target/release/igneum-miner",
|
||||
"slot": 1,
|
||||
"ports": {
|
||||
"base": 30730,
|
||||
"suffix": 981
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
12:48:26.701 fg1 case attack-gate-off-expect-hold: mode attack, gate off (window 60 DAA), joint 240 s, split 180 s, watch 150 s, honest 1 thread(s) each, attacker 3 (joint 0), expect hold
|
||||
12:48:28.281 fg1 h1 up pid 480222 json 30732 p2p 30731
|
||||
12:48:29.791 fg1 h2 up pid 481550 json 30742 p2p 30741 addpeer 30731
|
||||
12:48:31.307 fg1 b up pid 482808 json 30752 p2p 30751 addpeer 30761,30762
|
||||
12:52:34.325 fg1 phase 1 done at 240.0 s: H1 248 blocks sink 0535d8ae daa 247; H2 248 sink 0535d8ae; side 2 (b) 248 sink 0535d8ae; keys H1 8da9ddee H2 eda9cde4 side2 fresh (none yet)
|
||||
12:52:34.384 fg1 weight at the fork (last 120 blue blocks of H1's chain): side 2 0, others 120, side 2 0 bps
|
||||
12:52:34.387 fg1 links cut at 240.1 s; side 2 (b) now mines with 3 thread(s), the honest side with 1 each
|
||||
12:55:34.491 fg1 phase 2 done at 420.2 s: H1 412 blocks sink d5347d2c daa 411 blue 412 work 17459678; side 2 427 sink bfdb75e3 daa 426 blue 427 work 19683187 (side 2 heavier: true); fork depth 179 DAA against window 60
|
||||
12:55:34.491 fg1 links restored at 420.2 s; watching H1 and H2 for 150 s
|
||||
12:56:04.581 fg1 t=450.3 s H1 450 blocks sink cea4dc9c held; H2 450 blocks sink cea4dc9c held; side 2 466 blocks sink 4f46263c
|
||||
12:56:34.656 fg1 H1 left its pre-cut chain at 480.3 s: sink f08f99c6711510d7 by 0e2c6fe2
|
||||
12:56:34.659 fg1 H2 left its pre-cut chain at 480.3 s: sink f08f99c6711510d7 by 0e2c6fe2
|
||||
12:56:34.661 fg1 t=480.3 s H1 505 blocks sink f08f99c6 REORGED; H2 505 blocks sink f08f99c6 REORGED; side 2 505 blocks sink f08f99c6
|
||||
12:57:04.702 fg1 t=510.4 s H1 534 blocks sink f10f202f REORGED; H2 534 blocks sink f10f202f REORGED; side 2 534 blocks sink f10f202f
|
||||
12:57:34.751 fg1 t=540.4 s H1 567 blocks sink 3a757d27 REORGED; H2 567 blocks sink 3a757d27 REORGED; side 2 567 blocks sink 3a757d27
|
||||
12:58:04.813 fg1 t=570.5 s H1 595 blocks sink b5217027 REORGED; H2 595 blocks sink b5217027 REORGED; side 2 595 blocks sink b5217027
|
||||
12:58:04.825 fg1 SUMMARY FAIL (attack-gate-off-expect-hold): side 2 held 0 bps of the blue blocks at the fork; fork depth 179 DAA against window 60; side 2 blue work 19683187 against H1 17459678 at the heal; H1 reorged at 480.3 s (0 refusal lines, knows side 2's tip: true); H2 reorged at 480.3 s (0 refusal lines, knows side 2's tip: true); side 2 kept its chain: true; FAILED CHECK every_honest_node_held, every_honest_node_logged_a_refusal
|
||||
12:58:04.825 fg1 summary: /srv/builds/igneum-wt-horizon/docs/plans/mission-item-4-gate/fork-gate-attack-gate-off-expect-hold.json
|
||||
|
|
@ -0,0 +1,930 @@
|
|||
{
|
||||
"pass": true,
|
||||
"expect": "reorg",
|
||||
"case": "attack-gate-off-expect-reorg",
|
||||
"mode": "attack",
|
||||
"gate": "off",
|
||||
"window": 60,
|
||||
"joint": 240,
|
||||
"split": 180,
|
||||
"watch": 150,
|
||||
"threads": {
|
||||
"honest_each": 1,
|
||||
"attacker_split": 3,
|
||||
"attacker_joint": 0
|
||||
},
|
||||
"keys": {
|
||||
"h1": "8da9ddee…",
|
||||
"h2": "eda9cde4…",
|
||||
"side2": "0e2c6fe2…"
|
||||
},
|
||||
"share_at_fork": {
|
||||
"side2": 0,
|
||||
"others": 120,
|
||||
"side2_bps": 0
|
||||
},
|
||||
"fork_daa": 240,
|
||||
"fork_depth_daa_at_heal": 191,
|
||||
"sinks": {
|
||||
"joint": {
|
||||
"h1": {
|
||||
"hash": "e66998c63f8f5d2f3f9108a5c61730f3d5ee06a0553f47e3bce314a0e4d7228e",
|
||||
"blocks": 242,
|
||||
"daa": 240,
|
||||
"blue": 241,
|
||||
"blueWork": "8689541",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"h2": {
|
||||
"hash": "e66998c63f8f5d2f3f9108a5c61730f3d5ee06a0553f47e3bce314a0e4d7228e",
|
||||
"blocks": 242,
|
||||
"daa": 240,
|
||||
"blue": 241,
|
||||
"blueWork": "8689541",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"side2": {
|
||||
"hash": "e66998c63f8f5d2f3f9108a5c61730f3d5ee06a0553f47e3bce314a0e4d7228e",
|
||||
"blocks": 242,
|
||||
"daa": 240,
|
||||
"blue": 241,
|
||||
"blueWork": "8689541",
|
||||
"key": "8da9ddee…"
|
||||
}
|
||||
},
|
||||
"split": {
|
||||
"h1": {
|
||||
"hash": "6e932c389f2ad01a39873317f9549f0a336e66a7c840669dd5bcb44a979a19ad",
|
||||
"blocks": 421,
|
||||
"daa": 420,
|
||||
"blue": 421,
|
||||
"blueWork": "14893198",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"h2": {
|
||||
"hash": "6e932c389f2ad01a39873317f9549f0a336e66a7c840669dd5bcb44a979a19ad",
|
||||
"blocks": 421,
|
||||
"daa": 420,
|
||||
"blue": 421,
|
||||
"blueWork": "14893198",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"side2": {
|
||||
"hash": "d93a1238a397f68337f4bc28d6197a61a32fbca176f3e7f4248b6b330e239cc8",
|
||||
"blocks": 432,
|
||||
"daa": 431,
|
||||
"blue": 432,
|
||||
"blueWork": "17470131",
|
||||
"key": "0e2c6fe2…"
|
||||
}
|
||||
}
|
||||
},
|
||||
"per_node": {
|
||||
"h1": {
|
||||
"held": false,
|
||||
"reorged": true,
|
||||
"reorg_at_s": 510.4,
|
||||
"knows_side2_tip": true,
|
||||
"refusal_lines": 0
|
||||
},
|
||||
"h2": {
|
||||
"held": false,
|
||||
"reorged": true,
|
||||
"reorg_at_s": 510.4,
|
||||
"knows_side2_tip": true,
|
||||
"refusal_lines": 0
|
||||
}
|
||||
},
|
||||
"checks": {
|
||||
"side2_under_a_third_at_fork": true,
|
||||
"fork_deeper_than_window": true,
|
||||
"side2_heavier_at_heal": true,
|
||||
"every_honest_node_learned_side2_chain": true,
|
||||
"every_honest_node_held": false,
|
||||
"every_honest_node_reorged": true,
|
||||
"every_honest_node_logged_a_refusal": false,
|
||||
"no_honest_node_logged_a_refusal": true,
|
||||
"side2_kept_its_chain": true
|
||||
},
|
||||
"failed_checks": [],
|
||||
"refusal_example": null,
|
||||
"samples": [
|
||||
{
|
||||
"t": 425.2,
|
||||
"h1": {
|
||||
"blocks": 426,
|
||||
"sink": "719c3c11c14e54ed",
|
||||
"daa": 425,
|
||||
"blue": 426,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 426,
|
||||
"sink": "719c3c11c14e54ed",
|
||||
"daa": 425,
|
||||
"blue": 426,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 438,
|
||||
"sink": "c704e731f479e045",
|
||||
"blue": 438,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 430.2,
|
||||
"h1": {
|
||||
"blocks": 432,
|
||||
"sink": "fe308e06a3529e00",
|
||||
"daa": 431,
|
||||
"blue": 432,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 432,
|
||||
"sink": "fe308e06a3529e00",
|
||||
"daa": 431,
|
||||
"blue": 432,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 442,
|
||||
"sink": "7ca72d6ee8a28b46",
|
||||
"blue": 442,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 435.2,
|
||||
"h1": {
|
||||
"blocks": 436,
|
||||
"sink": "ba7e8b5f41caf493",
|
||||
"daa": 435,
|
||||
"blue": 436,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 436,
|
||||
"sink": "ba7e8b5f41caf493",
|
||||
"daa": 435,
|
||||
"blue": 436,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 446,
|
||||
"sink": "5459e40a1e9137e0",
|
||||
"blue": 446,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 440.2,
|
||||
"h1": {
|
||||
"blocks": 438,
|
||||
"sink": "19432a8a37b593ad",
|
||||
"daa": 437,
|
||||
"blue": 438,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 438,
|
||||
"sink": "19432a8a37b593ad",
|
||||
"daa": 437,
|
||||
"blue": 438,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 455,
|
||||
"sink": "5fdf67fc248f6500",
|
||||
"blue": 455,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 445.3,
|
||||
"h1": {
|
||||
"blocks": 446,
|
||||
"sink": "aada7bf1e3d16b25",
|
||||
"daa": 445,
|
||||
"blue": 446,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 446,
|
||||
"sink": "aada7bf1e3d16b25",
|
||||
"daa": 445,
|
||||
"blue": 446,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 466,
|
||||
"sink": "85ccafa8a9d39de0",
|
||||
"blue": 466,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 450.3,
|
||||
"h1": {
|
||||
"blocks": 447,
|
||||
"sink": "1761d6112c00d161",
|
||||
"daa": 446,
|
||||
"blue": 447,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 447,
|
||||
"sink": "1761d6112c00d161",
|
||||
"daa": 446,
|
||||
"blue": 447,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 475,
|
||||
"sink": "594fe7ff929c559f",
|
||||
"blue": 475,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 455.3,
|
||||
"h1": {
|
||||
"blocks": 455,
|
||||
"sink": "3d694806975e096e",
|
||||
"daa": 454,
|
||||
"blue": 455,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 455,
|
||||
"sink": "3d694806975e096e",
|
||||
"daa": 454,
|
||||
"blue": 455,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 480,
|
||||
"sink": "bf92fbb2a472d205",
|
||||
"blue": 480,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 460.3,
|
||||
"h1": {
|
||||
"blocks": 461,
|
||||
"sink": "4c2da8fcb362f14d",
|
||||
"daa": 460,
|
||||
"blue": 461,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 461,
|
||||
"sink": "4c2da8fcb362f14d",
|
||||
"daa": 460,
|
||||
"blue": 461,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 482,
|
||||
"sink": "90cc4fd0fac9bef2",
|
||||
"blue": 482,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 465.3,
|
||||
"h1": {
|
||||
"blocks": 467,
|
||||
"sink": "4cd5d4fda0703837",
|
||||
"daa": 466,
|
||||
"blue": 467,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 467,
|
||||
"sink": "4cd5d4fda0703837",
|
||||
"daa": 466,
|
||||
"blue": 467,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 484,
|
||||
"sink": "8d822c253a2939d6",
|
||||
"blue": 484,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 470.3,
|
||||
"h1": {
|
||||
"blocks": 473,
|
||||
"sink": "beeb70fa234a9a4b",
|
||||
"daa": 472,
|
||||
"blue": 473,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 473,
|
||||
"sink": "beeb70fa234a9a4b",
|
||||
"daa": 472,
|
||||
"blue": 473,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 487,
|
||||
"sink": "ed057653dec1d416",
|
||||
"blue": 487,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 475.3,
|
||||
"h1": {
|
||||
"blocks": 480,
|
||||
"sink": "47c9ab35c01f2f7d",
|
||||
"daa": 479,
|
||||
"blue": 480,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 480,
|
||||
"sink": "47c9ab35c01f2f7d",
|
||||
"daa": 479,
|
||||
"blue": 480,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 495,
|
||||
"sink": "072c31cf3c13877b",
|
||||
"blue": 495,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 480.3,
|
||||
"h1": {
|
||||
"blocks": 486,
|
||||
"sink": "918c05c7a79ce8ed",
|
||||
"daa": 485,
|
||||
"blue": 486,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 486,
|
||||
"sink": "918c05c7a79ce8ed",
|
||||
"daa": 485,
|
||||
"blue": 486,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 504,
|
||||
"sink": "6ab8526912a92786",
|
||||
"blue": 504,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 485.4,
|
||||
"h1": {
|
||||
"blocks": 491,
|
||||
"sink": "5b94825a96af8031",
|
||||
"daa": 490,
|
||||
"blue": 491,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 491,
|
||||
"sink": "5b94825a96af8031",
|
||||
"daa": 490,
|
||||
"blue": 491,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 511,
|
||||
"sink": "e5d2d2cf5ca14138",
|
||||
"blue": 511,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 490.4,
|
||||
"h1": {
|
||||
"blocks": 494,
|
||||
"sink": "7d0fd0b857ad553d",
|
||||
"daa": 493,
|
||||
"blue": 494,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 494,
|
||||
"sink": "7d0fd0b857ad553d",
|
||||
"daa": 493,
|
||||
"blue": 494,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 518,
|
||||
"sink": "6acadef70d9d2b7e",
|
||||
"blue": 518,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 495.4,
|
||||
"h1": {
|
||||
"blocks": 500,
|
||||
"sink": "4e35f238846e9802",
|
||||
"daa": 499,
|
||||
"blue": 500,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 500,
|
||||
"sink": "4e35f238846e9802",
|
||||
"daa": 499,
|
||||
"blue": 500,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 524,
|
||||
"sink": "a0e5e0544388677b",
|
||||
"blue": 524,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 500.4,
|
||||
"h1": {
|
||||
"blocks": 502,
|
||||
"sink": "1f3cf87f97e6661c",
|
||||
"daa": 501,
|
||||
"blue": 502,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 502,
|
||||
"sink": "1f3cf87f97e6661c",
|
||||
"daa": 501,
|
||||
"blue": 502,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 530,
|
||||
"sink": "f0ba9826edcf48e7",
|
||||
"blue": 530,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 505.4,
|
||||
"h1": {
|
||||
"blocks": 509,
|
||||
"sink": "532a873c7ad783c5",
|
||||
"daa": 508,
|
||||
"blue": 509,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 509,
|
||||
"sink": "532a873c7ad783c5",
|
||||
"daa": 508,
|
||||
"blue": 509,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 537,
|
||||
"sink": "b138a9d8ba0b3454",
|
||||
"blue": 537,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 510.4,
|
||||
"h1": {
|
||||
"blocks": 545,
|
||||
"sink": "b878077d471c2a73",
|
||||
"daa": 544,
|
||||
"blue": 545,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 545,
|
||||
"sink": "b878077d471c2a73",
|
||||
"daa": 544,
|
||||
"blue": 545,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 545,
|
||||
"sink": "b878077d471c2a73",
|
||||
"blue": 545,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 515.4,
|
||||
"h1": {
|
||||
"blocks": 556,
|
||||
"sink": "95bd60b5bf755ef1",
|
||||
"daa": 555,
|
||||
"blue": 556,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 556,
|
||||
"sink": "95bd60b5bf755ef1",
|
||||
"daa": 555,
|
||||
"blue": 556,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 556,
|
||||
"sink": "95bd60b5bf755ef1",
|
||||
"blue": 556,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 520.4,
|
||||
"h1": {
|
||||
"blocks": 569,
|
||||
"sink": "258f2c477b49756d",
|
||||
"daa": 568,
|
||||
"blue": 569,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 569,
|
||||
"sink": "258f2c477b49756d",
|
||||
"daa": 568,
|
||||
"blue": 569,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 569,
|
||||
"sink": "258f2c477b49756d",
|
||||
"blue": 569,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 525.4,
|
||||
"h1": {
|
||||
"blocks": 571,
|
||||
"sink": "e8cc9969d5d1dc10",
|
||||
"daa": 570,
|
||||
"blue": 571,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 571,
|
||||
"sink": "e8cc9969d5d1dc10",
|
||||
"daa": 570,
|
||||
"blue": 571,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 571,
|
||||
"sink": "e8cc9969d5d1dc10",
|
||||
"blue": 571,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 530.5,
|
||||
"h1": {
|
||||
"blocks": 573,
|
||||
"sink": "da3da53755578a2d",
|
||||
"daa": 572,
|
||||
"blue": 573,
|
||||
"key": "8da9ddee",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 573,
|
||||
"sink": "da3da53755578a2d",
|
||||
"daa": 572,
|
||||
"blue": 573,
|
||||
"key": "8da9ddee",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 573,
|
||||
"sink": "da3da53755578a2d",
|
||||
"blue": 573,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 535.5,
|
||||
"h1": {
|
||||
"blocks": 576,
|
||||
"sink": "65ba87e325c66754",
|
||||
"daa": 575,
|
||||
"blue": 576,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 576,
|
||||
"sink": "65ba87e325c66754",
|
||||
"daa": 575,
|
||||
"blue": 576,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 576,
|
||||
"sink": "65ba87e325c66754",
|
||||
"blue": 576,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 540.5,
|
||||
"h1": {
|
||||
"blocks": 580,
|
||||
"sink": "11e564345e74f2cb",
|
||||
"daa": 579,
|
||||
"blue": 580,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 580,
|
||||
"sink": "11e564345e74f2cb",
|
||||
"daa": 579,
|
||||
"blue": 580,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 580,
|
||||
"sink": "11e564345e74f2cb",
|
||||
"blue": 580,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 545.5,
|
||||
"h1": {
|
||||
"blocks": 585,
|
||||
"sink": "b1d2689648b6d765",
|
||||
"daa": 584,
|
||||
"blue": 585,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 585,
|
||||
"sink": "b1d2689648b6d765",
|
||||
"daa": 584,
|
||||
"blue": 585,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 585,
|
||||
"sink": "b1d2689648b6d765",
|
||||
"blue": 585,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 550.5,
|
||||
"h1": {
|
||||
"blocks": 594,
|
||||
"sink": "0856bc8c348725e9",
|
||||
"daa": 593,
|
||||
"blue": 594,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 594,
|
||||
"sink": "0856bc8c348725e9",
|
||||
"daa": 593,
|
||||
"blue": 594,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 594,
|
||||
"sink": "0856bc8c348725e9",
|
||||
"blue": 594,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 555.5,
|
||||
"h1": {
|
||||
"blocks": 597,
|
||||
"sink": "b0b25422dae4fab7",
|
||||
"daa": 596,
|
||||
"blue": 597,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 597,
|
||||
"sink": "b0b25422dae4fab7",
|
||||
"daa": 596,
|
||||
"blue": 597,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 597,
|
||||
"sink": "b0b25422dae4fab7",
|
||||
"blue": 597,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 560.5,
|
||||
"h1": {
|
||||
"blocks": 606,
|
||||
"sink": "733de568ec588157",
|
||||
"daa": 605,
|
||||
"blue": 606,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 606,
|
||||
"sink": "733de568ec588157",
|
||||
"daa": 605,
|
||||
"blue": 606,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 606,
|
||||
"sink": "733de568ec588157",
|
||||
"blue": 606,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 565.5,
|
||||
"h1": {
|
||||
"blocks": 608,
|
||||
"sink": "ad3c86d071a93e75",
|
||||
"daa": 607,
|
||||
"blue": 608,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 608,
|
||||
"sink": "ad3c86d071a93e75",
|
||||
"daa": 607,
|
||||
"blue": 608,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 608,
|
||||
"sink": "ad3c86d071a93e75",
|
||||
"blue": 608,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 570.5,
|
||||
"h1": {
|
||||
"blocks": 613,
|
||||
"sink": "a38c3c8af9f6290d",
|
||||
"daa": 612,
|
||||
"blue": 613,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 613,
|
||||
"sink": "a38c3c8af9f6290d",
|
||||
"daa": 612,
|
||||
"blue": 613,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 613,
|
||||
"sink": "a38c3c8af9f6290d",
|
||||
"blue": 613,
|
||||
"reorged": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"node": "/srv/builds/igneum-wt-horizon/vendor/igneum-node-horizon/target/release/igneumd",
|
||||
"miner": "/srv/builds/igneum-wt-horizon/vendor/igneum-node-horizon/target/release/igneum-miner",
|
||||
"slot": 0,
|
||||
"ports": {
|
||||
"base": 30690,
|
||||
"suffix": 980
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
12:48:26.701 fg0 case attack-gate-off-expect-reorg: mode attack, gate off (window 60 DAA), joint 240 s, split 180 s, watch 150 s, honest 1 thread(s) each, attacker 3 (joint 0), expect reorg
|
||||
12:48:28.258 fg0 h1 up pid 480223 json 30692 p2p 30691
|
||||
12:48:29.769 fg0 h2 up pid 481517 json 30702 p2p 30701 addpeer 30691
|
||||
12:48:31.285 fg0 b up pid 482726 json 30712 p2p 30711 addpeer 30721,30722
|
||||
12:52:34.300 fg0 phase 1 done at 240.0 s: H1 242 blocks sink e66998c6 daa 240; H2 242 sink e66998c6; side 2 (b) 242 sink e66998c6; keys H1 8da9ddee H2 eda9cde4 side2 fresh (none yet)
|
||||
12:52:34.368 fg0 weight at the fork (last 120 blue blocks of H1's chain): side 2 0, others 120, side 2 0 bps
|
||||
12:52:34.370 fg0 links cut at 240.1 s; side 2 (b) now mines with 3 thread(s), the honest side with 1 each
|
||||
12:55:34.480 fg0 phase 2 done at 420.2 s: H1 421 blocks sink 6e932c38 daa 420 blue 421 work 14893198; side 2 432 sink d93a1238 daa 431 blue 432 work 17470131 (side 2 heavier: true); fork depth 191 DAA against window 60
|
||||
12:55:34.481 fg0 links restored at 420.2 s; watching H1 and H2 for 150 s
|
||||
12:56:04.569 fg0 t=450.3 s H1 447 blocks sink 1761d611 held; H2 447 blocks sink 1761d611 held; side 2 475 blocks sink 594fe7ff
|
||||
12:56:34.644 fg0 t=480.4 s H1 486 blocks sink 918c05c7 held; H2 486 blocks sink 918c05c7 held; side 2 504 blocks sink 6ab85269
|
||||
12:57:04.714 fg0 H1 left its pre-cut chain at 510.4 s: sink b878077d471c2a73 by eda9cde4
|
||||
12:57:04.717 fg0 H2 left its pre-cut chain at 510.4 s: sink b878077d471c2a73 by eda9cde4
|
||||
12:57:04.719 fg0 t=510.4 s H1 545 blocks sink b878077d REORGED; H2 545 blocks sink b878077d REORGED; side 2 545 blocks sink b878077d
|
||||
12:57:34.769 fg0 t=540.5 s H1 580 blocks sink 11e56434 REORGED; H2 580 blocks sink 11e56434 REORGED; side 2 580 blocks sink 11e56434
|
||||
12:58:04.814 fg0 t=570.5 s H1 613 blocks sink a38c3c8a REORGED; H2 613 blocks sink a38c3c8a REORGED; side 2 613 blocks sink a38c3c8a
|
||||
12:58:04.822 fg0 SUMMARY PASS (attack-gate-off-expect-reorg): side 2 held 0 bps of the blue blocks at the fork; fork depth 191 DAA against window 60; side 2 blue work 17470131 against H1 14893198 at the heal; H1 reorged at 510.4 s (0 refusal lines, knows side 2's tip: true); H2 reorged at 510.4 s (0 refusal lines, knows side 2's tip: true); side 2 kept its chain: true
|
||||
12:58:04.822 fg0 summary: /srv/builds/igneum-wt-horizon/docs/plans/mission-item-4-gate/fork-gate-attack-gate-off-expect-reorg.json
|
||||
|
|
@ -0,0 +1,930 @@
|
|||
{
|
||||
"pass": true,
|
||||
"expect": "hold",
|
||||
"case": "attack-gate-on-expect-hold",
|
||||
"mode": "attack",
|
||||
"gate": "on",
|
||||
"window": 60,
|
||||
"joint": 240,
|
||||
"split": 180,
|
||||
"watch": 150,
|
||||
"threads": {
|
||||
"honest_each": 1,
|
||||
"attacker_split": 3,
|
||||
"attacker_joint": 0
|
||||
},
|
||||
"keys": {
|
||||
"h1": "8da9ddee…",
|
||||
"h2": "eda9cde4…",
|
||||
"side2": "0e2c6fe2…"
|
||||
},
|
||||
"share_at_fork": {
|
||||
"side2": 0,
|
||||
"others": 121,
|
||||
"side2_bps": 0
|
||||
},
|
||||
"fork_daa": 233,
|
||||
"fork_depth_daa_at_heal": 197,
|
||||
"sinks": {
|
||||
"joint": {
|
||||
"h1": {
|
||||
"hash": "7ed68743f22e711490406bd380cf66fff94579fcc981344c317a46c18cbc61bb",
|
||||
"blocks": 234,
|
||||
"daa": 233,
|
||||
"blue": 234,
|
||||
"blueWork": "8862250",
|
||||
"key": "eda9cde4…"
|
||||
},
|
||||
"h2": {
|
||||
"hash": "7ed68743f22e711490406bd380cf66fff94579fcc981344c317a46c18cbc61bb",
|
||||
"blocks": 234,
|
||||
"daa": 233,
|
||||
"blue": 234,
|
||||
"blueWork": "8862250",
|
||||
"key": "eda9cde4…"
|
||||
},
|
||||
"side2": {
|
||||
"hash": "7ed68743f22e711490406bd380cf66fff94579fcc981344c317a46c18cbc61bb",
|
||||
"blocks": 234,
|
||||
"daa": 233,
|
||||
"blue": 234,
|
||||
"blueWork": "8862250",
|
||||
"key": "eda9cde4…"
|
||||
}
|
||||
},
|
||||
"split": {
|
||||
"h1": {
|
||||
"hash": "036cfe568f3d403351b338ea41b7069ad4eae0ce95308436a25b6c7aa4c1372a",
|
||||
"blocks": 396,
|
||||
"daa": 395,
|
||||
"blue": 396,
|
||||
"blueWork": "14807915",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"h2": {
|
||||
"hash": "036cfe568f3d403351b338ea41b7069ad4eae0ce95308436a25b6c7aa4c1372a",
|
||||
"blocks": 396,
|
||||
"daa": 395,
|
||||
"blue": 396,
|
||||
"blueWork": "14807915",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"side2": {
|
||||
"hash": "abb93c2318f6c2ebdbd4e14a50b3d73ba7f483b8b06b18666e1015d038d4011a",
|
||||
"blocks": 431,
|
||||
"daa": 430,
|
||||
"blue": 431,
|
||||
"blueWork": "20297242",
|
||||
"key": "0e2c6fe2…"
|
||||
}
|
||||
}
|
||||
},
|
||||
"per_node": {
|
||||
"h1": {
|
||||
"held": true,
|
||||
"reorged": false,
|
||||
"reorg_at_s": null,
|
||||
"knows_side2_tip": true,
|
||||
"refusal_lines": 177
|
||||
},
|
||||
"h2": {
|
||||
"held": true,
|
||||
"reorged": false,
|
||||
"reorg_at_s": null,
|
||||
"knows_side2_tip": true,
|
||||
"refusal_lines": 177
|
||||
}
|
||||
},
|
||||
"checks": {
|
||||
"side2_under_a_third_at_fork": true,
|
||||
"fork_deeper_than_window": true,
|
||||
"side2_heavier_at_heal": true,
|
||||
"every_honest_node_learned_side2_chain": true,
|
||||
"every_honest_node_held": true,
|
||||
"every_honest_node_reorged": false,
|
||||
"every_honest_node_logged_a_refusal": true,
|
||||
"no_honest_node_logged_a_refusal": false,
|
||||
"side2_kept_its_chain": true
|
||||
},
|
||||
"failed_checks": [],
|
||||
"refusal_example": "Fork choice: block 41225a00fb38b6394540a5707443bd70e678484cbd20aa3fa8e807bb24df8d4a forks 252 DAA back from the sink's chain and its builders hold 0.00% of the weight table at the fork (under one third); not a sink candidate (ledger 51-percent rank 2)",
|
||||
"samples": [
|
||||
{
|
||||
"t": 425.2,
|
||||
"h1": {
|
||||
"blocks": 407,
|
||||
"sink": "b9b5fef0daea5b74",
|
||||
"daa": 406,
|
||||
"blue": 407,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 407,
|
||||
"sink": "b9b5fef0daea5b74",
|
||||
"daa": 406,
|
||||
"blue": 407,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 436,
|
||||
"sink": "b87c6327c3fc8298",
|
||||
"blue": 436,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 430.2,
|
||||
"h1": {
|
||||
"blocks": 412,
|
||||
"sink": "cd9991f248c9bf46",
|
||||
"daa": 411,
|
||||
"blue": 412,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 412,
|
||||
"sink": "cd9991f248c9bf46",
|
||||
"daa": 411,
|
||||
"blue": 412,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 439,
|
||||
"sink": "4c1b609fad53a391",
|
||||
"blue": 439,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 435.2,
|
||||
"h1": {
|
||||
"blocks": 417,
|
||||
"sink": "b2bb0dc00c197917",
|
||||
"daa": 416,
|
||||
"blue": 417,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 417,
|
||||
"sink": "b2bb0dc00c197917",
|
||||
"daa": 416,
|
||||
"blue": 417,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 444,
|
||||
"sink": "e382cbd3ac4dcf26",
|
||||
"blue": 444,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 440.2,
|
||||
"h1": {
|
||||
"blocks": 422,
|
||||
"sink": "b711c4c23605870d",
|
||||
"daa": 421,
|
||||
"blue": 422,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 422,
|
||||
"sink": "b711c4c23605870d",
|
||||
"daa": 421,
|
||||
"blue": 422,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 446,
|
||||
"sink": "c35dab954cd4acf4",
|
||||
"blue": 446,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 445.2,
|
||||
"h1": {
|
||||
"blocks": 428,
|
||||
"sink": "f99b9d3dbc93d6c8",
|
||||
"daa": 427,
|
||||
"blue": 428,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 428,
|
||||
"sink": "f99b9d3dbc93d6c8",
|
||||
"daa": 427,
|
||||
"blue": 428,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 449,
|
||||
"sink": "d92f53e2d140db35",
|
||||
"blue": 449,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 450.3,
|
||||
"h1": {
|
||||
"blocks": 431,
|
||||
"sink": "1e9a17dfc27a2670",
|
||||
"daa": 430,
|
||||
"blue": 431,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 431,
|
||||
"sink": "1e9a17dfc27a2670",
|
||||
"daa": 430,
|
||||
"blue": 431,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 456,
|
||||
"sink": "162c5de6d4f74ea9",
|
||||
"blue": 456,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 455.3,
|
||||
"h1": {
|
||||
"blocks": 438,
|
||||
"sink": "65be332f457b64e0",
|
||||
"daa": 437,
|
||||
"blue": 438,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 438,
|
||||
"sink": "65be332f457b64e0",
|
||||
"daa": 437,
|
||||
"blue": 438,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 461,
|
||||
"sink": "6b7998086b33a85d",
|
||||
"blue": 461,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 460.3,
|
||||
"h1": {
|
||||
"blocks": 446,
|
||||
"sink": "5ee05b91ff342422",
|
||||
"daa": 445,
|
||||
"blue": 446,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 446,
|
||||
"sink": "5ee05b91ff342422",
|
||||
"daa": 445,
|
||||
"blue": 446,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 468,
|
||||
"sink": "2ef3594b2514a766",
|
||||
"blue": 468,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 465.3,
|
||||
"h1": {
|
||||
"blocks": 451,
|
||||
"sink": "faad0b35cf941017",
|
||||
"daa": 450,
|
||||
"blue": 451,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 451,
|
||||
"sink": "faad0b35cf941017",
|
||||
"daa": 450,
|
||||
"blue": 451,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 471,
|
||||
"sink": "e57eb146c13fa041",
|
||||
"blue": 471,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 470.3,
|
||||
"h1": {
|
||||
"blocks": 454,
|
||||
"sink": "b5f88fdf5097139b",
|
||||
"daa": 453,
|
||||
"blue": 454,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 454,
|
||||
"sink": "b5f88fdf5097139b",
|
||||
"daa": 453,
|
||||
"blue": 454,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 479,
|
||||
"sink": "bac0a7b389fb2418",
|
||||
"blue": 479,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 475.3,
|
||||
"h1": {
|
||||
"blocks": 463,
|
||||
"sink": "e93acb17237cc9b3",
|
||||
"daa": 462,
|
||||
"blue": 463,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 463,
|
||||
"sink": "e93acb17237cc9b3",
|
||||
"daa": 462,
|
||||
"blue": 463,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 481,
|
||||
"sink": "7a533b847de36a0c",
|
||||
"blue": 481,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 480.3,
|
||||
"h1": {
|
||||
"blocks": 467,
|
||||
"sink": "ea2b7270dba4deba",
|
||||
"daa": 466,
|
||||
"blue": 467,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 467,
|
||||
"sink": "ea2b7270dba4deba",
|
||||
"daa": 466,
|
||||
"blue": 467,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 485,
|
||||
"sink": "5f36be5a27dc4f1f",
|
||||
"blue": 485,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 485.3,
|
||||
"h1": {
|
||||
"blocks": 470,
|
||||
"sink": "caab7c55e1185c44",
|
||||
"daa": 469,
|
||||
"blue": 470,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 470,
|
||||
"sink": "caab7c55e1185c44",
|
||||
"daa": 469,
|
||||
"blue": 470,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 490,
|
||||
"sink": "9b058d11e4a8a864",
|
||||
"blue": 490,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 490.4,
|
||||
"h1": {
|
||||
"blocks": 472,
|
||||
"sink": "19057874449c22ea",
|
||||
"daa": 471,
|
||||
"blue": 472,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 472,
|
||||
"sink": "19057874449c22ea",
|
||||
"daa": 471,
|
||||
"blue": 472,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 493,
|
||||
"sink": "422c79a9ec4780dd",
|
||||
"blue": 493,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 495.4,
|
||||
"h1": {
|
||||
"blocks": 475,
|
||||
"sink": "b6f0161d81faa3e9",
|
||||
"daa": 474,
|
||||
"blue": 475,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 475,
|
||||
"sink": "b6f0161d81faa3e9",
|
||||
"daa": 474,
|
||||
"blue": 475,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 497,
|
||||
"sink": "33c53267da1c7bd5",
|
||||
"blue": 497,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 500.4,
|
||||
"h1": {
|
||||
"blocks": 482,
|
||||
"sink": "6e821ff35e24b700",
|
||||
"daa": 481,
|
||||
"blue": 482,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 482,
|
||||
"sink": "6e821ff35e24b700",
|
||||
"daa": 481,
|
||||
"blue": 482,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 501,
|
||||
"sink": "6536fa666794da92",
|
||||
"blue": 501,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 505.4,
|
||||
"h1": {
|
||||
"blocks": 486,
|
||||
"sink": "bee5af11ed677228",
|
||||
"daa": 485,
|
||||
"blue": 486,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 486,
|
||||
"sink": "bee5af11ed677228",
|
||||
"daa": 485,
|
||||
"blue": 486,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 510,
|
||||
"sink": "be1419603638e1fb",
|
||||
"blue": 510,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 510.4,
|
||||
"h1": {
|
||||
"blocks": 491,
|
||||
"sink": "ed71ec00678a9e10",
|
||||
"daa": 490,
|
||||
"blue": 491,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 491,
|
||||
"sink": "ed71ec00678a9e10",
|
||||
"daa": 490,
|
||||
"blue": 491,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 515,
|
||||
"sink": "7b32f850c803ef02",
|
||||
"blue": 515,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 515.4,
|
||||
"h1": {
|
||||
"blocks": 499,
|
||||
"sink": "ed904ccbc28c9980",
|
||||
"daa": 498,
|
||||
"blue": 499,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 499,
|
||||
"sink": "ed904ccbc28c9980",
|
||||
"daa": 498,
|
||||
"blue": 499,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 519,
|
||||
"sink": "a26ebf100dcba0c2",
|
||||
"blue": 519,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 520.4,
|
||||
"h1": {
|
||||
"blocks": 503,
|
||||
"sink": "462b0c2c35c67c54",
|
||||
"daa": 502,
|
||||
"blue": 503,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 503,
|
||||
"sink": "462b0c2c35c67c54",
|
||||
"daa": 502,
|
||||
"blue": 503,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 526,
|
||||
"sink": "aaaebc1389fe11fd",
|
||||
"blue": 526,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 525.4,
|
||||
"h1": {
|
||||
"blocks": 504,
|
||||
"sink": "87f25e6a386a8165",
|
||||
"daa": 503,
|
||||
"blue": 504,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 504,
|
||||
"sink": "87f25e6a386a8165",
|
||||
"daa": 503,
|
||||
"blue": 504,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 529,
|
||||
"sink": "c096bda65c99e6f8",
|
||||
"blue": 529,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 530.4,
|
||||
"h1": {
|
||||
"blocks": 510,
|
||||
"sink": "6c5d1398a7445010",
|
||||
"daa": 509,
|
||||
"blue": 510,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 510,
|
||||
"sink": "6c5d1398a7445010",
|
||||
"daa": 509,
|
||||
"blue": 510,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 533,
|
||||
"sink": "3341a65b2b284f17",
|
||||
"blue": 533,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 535.4,
|
||||
"h1": {
|
||||
"blocks": 514,
|
||||
"sink": "0d661c0b8cc34ab8",
|
||||
"daa": 513,
|
||||
"blue": 514,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 514,
|
||||
"sink": "0d661c0b8cc34ab8",
|
||||
"daa": 513,
|
||||
"blue": 514,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 542,
|
||||
"sink": "7c3a8038df112ee7",
|
||||
"blue": 542,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 540.4,
|
||||
"h1": {
|
||||
"blocks": 525,
|
||||
"sink": "f2b83fc149654b8d",
|
||||
"daa": 524,
|
||||
"blue": 525,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 525,
|
||||
"sink": "f2b83fc149654b8d",
|
||||
"daa": 524,
|
||||
"blue": 525,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 545,
|
||||
"sink": "36e6ba6e49e7c6f2",
|
||||
"blue": 545,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 545.5,
|
||||
"h1": {
|
||||
"blocks": 533,
|
||||
"sink": "8f1d9ad77edf47d0",
|
||||
"daa": 532,
|
||||
"blue": 533,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 533,
|
||||
"sink": "8f1d9ad77edf47d0",
|
||||
"daa": 532,
|
||||
"blue": 533,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 554,
|
||||
"sink": "857f2b7d99ddcba6",
|
||||
"blue": 554,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 550.5,
|
||||
"h1": {
|
||||
"blocks": 537,
|
||||
"sink": "4cd35471c65af8ff",
|
||||
"daa": 536,
|
||||
"blue": 537,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 537,
|
||||
"sink": "4cd35471c65af8ff",
|
||||
"daa": 536,
|
||||
"blue": 537,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 560,
|
||||
"sink": "5ed4bc501713930a",
|
||||
"blue": 560,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 555.5,
|
||||
"h1": {
|
||||
"blocks": 544,
|
||||
"sink": "1174f796fda59e3e",
|
||||
"daa": 543,
|
||||
"blue": 544,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 544,
|
||||
"sink": "1174f796fda59e3e",
|
||||
"daa": 543,
|
||||
"blue": 544,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 565,
|
||||
"sink": "f7d136350536fa6b",
|
||||
"blue": 565,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 560.5,
|
||||
"h1": {
|
||||
"blocks": 548,
|
||||
"sink": "f6ed678d1b0a96f8",
|
||||
"daa": 547,
|
||||
"blue": 548,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 548,
|
||||
"sink": "f6ed678d1b0a96f8",
|
||||
"daa": 547,
|
||||
"blue": 548,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 568,
|
||||
"sink": "37ac0328bf8f53e4",
|
||||
"blue": 568,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 565.5,
|
||||
"h1": {
|
||||
"blocks": 556,
|
||||
"sink": "86f4c28c6ba82275",
|
||||
"daa": 555,
|
||||
"blue": 556,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 556,
|
||||
"sink": "86f4c28c6ba82275",
|
||||
"daa": 555,
|
||||
"blue": 556,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 572,
|
||||
"sink": "9d9ec576b2742464",
|
||||
"blue": 572,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 570.5,
|
||||
"h1": {
|
||||
"blocks": 560,
|
||||
"sink": "3210de1f85cbfc76",
|
||||
"daa": 559,
|
||||
"blue": 560,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 560,
|
||||
"sink": "3210de1f85cbfc76",
|
||||
"daa": 559,
|
||||
"blue": 560,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 574,
|
||||
"sink": "3496b576346db4bb",
|
||||
"blue": 574,
|
||||
"reorged": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"node": "/srv/builds/igneum-wt-horizon/vendor/igneum-node-horizon/target/release/igneumd",
|
||||
"miner": "/srv/builds/igneum-wt-horizon/vendor/igneum-node-horizon/target/release/igneum-miner",
|
||||
"slot": 2,
|
||||
"ports": {
|
||||
"base": 30770,
|
||||
"suffix": 982
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
12:48:26.709 fg2 case attack-gate-on-expect-hold: mode attack, gate on (window 60 DAA), joint 240 s, split 180 s, watch 150 s, honest 1 thread(s) each, attacker 3 (joint 0), expect hold
|
||||
12:48:28.273 fg2 h1 up pid 480230 json 30772 p2p 30771
|
||||
12:48:29.784 fg2 h2 up pid 481529 json 30782 p2p 30781 addpeer 30771
|
||||
12:48:31.299 fg2 b up pid 482751 json 30792 p2p 30791 addpeer 30801,30802
|
||||
12:52:34.314 fg2 phase 1 done at 240.0 s: H1 234 blocks sink 7ed68743 daa 233; H2 234 sink 7ed68743; side 2 (b) 234 sink 7ed68743; keys H1 8da9ddee H2 eda9cde4 side2 fresh (none yet)
|
||||
12:52:34.371 fg2 weight at the fork (last 121 blue blocks of H1's chain): side 2 0, others 121, side 2 0 bps
|
||||
12:52:34.375 fg2 links cut at 240.1 s; side 2 (b) now mines with 3 thread(s), the honest side with 1 each
|
||||
12:55:34.483 fg2 phase 2 done at 420.2 s: H1 396 blocks sink 036cfe56 daa 395 blue 396 work 14807915; side 2 431 sink abb93c23 daa 430 blue 431 work 20297242 (side 2 heavier: true); fork depth 197 DAA against window 60
|
||||
12:55:34.484 fg2 links restored at 420.2 s; watching H1 and H2 for 150 s
|
||||
12:56:04.568 fg2 t=450.3 s H1 431 blocks sink 1e9a17df held; H2 431 blocks sink 1e9a17df held; side 2 456 blocks sink 162c5de6
|
||||
12:56:34.640 fg2 t=480.3 s H1 467 blocks sink ea2b7270 held; H2 467 blocks sink ea2b7270 held; side 2 485 blocks sink 5f36be5a
|
||||
12:57:04.717 fg2 t=510.4 s H1 491 blocks sink ed71ec00 held; H2 491 blocks sink ed71ec00 held; side 2 515 blocks sink 7b32f850
|
||||
12:57:34.757 fg2 t=540.5 s H1 525 blocks sink f2b83fc1 held; H2 525 blocks sink f2b83fc1 held; side 2 545 blocks sink 36e6ba6e
|
||||
12:58:04.809 fg2 t=570.5 s H1 560 blocks sink 3210de1f held; H2 560 blocks sink 3210de1f held; side 2 574 blocks sink 3496b576
|
||||
12:58:04.822 fg2 SUMMARY PASS (attack-gate-on-expect-hold): side 2 held 0 bps of the blue blocks at the fork; fork depth 197 DAA against window 60; side 2 blue work 20297242 against H1 14807915 at the heal; H1 held (177 refusal lines, knows side 2's tip: true); H2 held (177 refusal lines, knows side 2's tip: true); side 2 kept its chain: true
|
||||
12:58:04.822 fg2 summary: /srv/builds/igneum-wt-horizon/docs/plans/mission-item-4-gate/fork-gate-attack-gate-on-expect-hold.json
|
||||
|
|
@ -0,0 +1,653 @@
|
|||
{
|
||||
"pass": true,
|
||||
"expect": "reorg",
|
||||
"case": "partition-gate-off-expect-reorg",
|
||||
"mode": "partition",
|
||||
"gate": "off",
|
||||
"window": 60,
|
||||
"joint": 240,
|
||||
"split": 180,
|
||||
"watch": 150,
|
||||
"threads": {
|
||||
"honest_each": 1,
|
||||
"attacker_split": 3,
|
||||
"attacker_joint": 1
|
||||
},
|
||||
"keys": {
|
||||
"h1": "8da9ddee…",
|
||||
"h2": null,
|
||||
"side2": "eda9cde4…"
|
||||
},
|
||||
"share_at_fork": {
|
||||
"side2": 67,
|
||||
"others": 53,
|
||||
"side2_bps": 5583
|
||||
},
|
||||
"fork_daa": 244,
|
||||
"fork_depth_daa_at_heal": 191,
|
||||
"sinks": {
|
||||
"joint": {
|
||||
"h1": {
|
||||
"hash": "58126c351aa6324a992a47fa66cca22369450c9835d312772c87d3e1aeb409a0",
|
||||
"blocks": 245,
|
||||
"daa": 244,
|
||||
"blue": 245,
|
||||
"blueWork": "9558440",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"h2": {
|
||||
"hash": "58126c351aa6324a992a47fa66cca22369450c9835d312772c87d3e1aeb409a0",
|
||||
"blocks": 245,
|
||||
"daa": 244,
|
||||
"blue": 245,
|
||||
"blueWork": "9558440",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"side2": {
|
||||
"hash": "58126c351aa6324a992a47fa66cca22369450c9835d312772c87d3e1aeb409a0",
|
||||
"blocks": 245,
|
||||
"daa": 244,
|
||||
"blue": 245,
|
||||
"blueWork": "9558440",
|
||||
"key": "8da9ddee…"
|
||||
}
|
||||
},
|
||||
"split": {
|
||||
"h1": {
|
||||
"hash": "a27a341c694aacf22b1a78f44d433e4104f58b23533afb73b7ee6fb9aa37afe4",
|
||||
"blocks": 405,
|
||||
"daa": 404,
|
||||
"blue": 405,
|
||||
"blueWork": "12270631",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"h2": {
|
||||
"hash": "f9181a06c0db716fe4ed200f6f0046c9cb8fae2eb57dd7da4697a268c434a232",
|
||||
"blocks": 436,
|
||||
"daa": 435,
|
||||
"blue": 436,
|
||||
"blueWork": "19576159",
|
||||
"key": "eda9cde4…"
|
||||
},
|
||||
"side2": {
|
||||
"hash": "f9181a06c0db716fe4ed200f6f0046c9cb8fae2eb57dd7da4697a268c434a232",
|
||||
"blocks": 436,
|
||||
"daa": 435,
|
||||
"blue": 436,
|
||||
"blueWork": "19576159",
|
||||
"key": "eda9cde4…"
|
||||
}
|
||||
}
|
||||
},
|
||||
"per_node": {
|
||||
"h1": {
|
||||
"held": false,
|
||||
"reorged": true,
|
||||
"reorg_at_s": 507.4,
|
||||
"knows_side2_tip": true,
|
||||
"refusal_lines": 0
|
||||
}
|
||||
},
|
||||
"checks": {
|
||||
"side2_under_a_third_at_fork": false,
|
||||
"fork_deeper_than_window": true,
|
||||
"side2_heavier_at_heal": true,
|
||||
"every_honest_node_learned_side2_chain": true,
|
||||
"every_honest_node_held": false,
|
||||
"every_honest_node_reorged": true,
|
||||
"every_honest_node_logged_a_refusal": false,
|
||||
"no_honest_node_logged_a_refusal": true,
|
||||
"side2_kept_its_chain": true
|
||||
},
|
||||
"failed_checks": [],
|
||||
"refusal_example": null,
|
||||
"samples": [
|
||||
{
|
||||
"t": 427.2,
|
||||
"h1": {
|
||||
"blocks": 411,
|
||||
"sink": "d783538ac11687a9",
|
||||
"daa": 410,
|
||||
"blue": 411,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 439,
|
||||
"sink": "aa3da0091db61498",
|
||||
"blue": 439,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 432.2,
|
||||
"h1": {
|
||||
"blocks": 416,
|
||||
"sink": "5084ccaac5b21e34",
|
||||
"daa": 415,
|
||||
"blue": 416,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 448,
|
||||
"sink": "c98585f0a1f24913",
|
||||
"blue": 448,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 437.2,
|
||||
"h1": {
|
||||
"blocks": 421,
|
||||
"sink": "950f8b1c7d4cac21",
|
||||
"daa": 420,
|
||||
"blue": 421,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 452,
|
||||
"sink": "c4ad3925b38e9285",
|
||||
"blue": 452,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 442.2,
|
||||
"h1": {
|
||||
"blocks": 424,
|
||||
"sink": "767cbc91083a48b0",
|
||||
"daa": 423,
|
||||
"blue": 424,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 455,
|
||||
"sink": "c91b500a6d256eb3",
|
||||
"blue": 455,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 447.3,
|
||||
"h1": {
|
||||
"blocks": 429,
|
||||
"sink": "d36268f977a04b6a",
|
||||
"daa": 428,
|
||||
"blue": 429,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 465,
|
||||
"sink": "c5a91c0c5352b0d6",
|
||||
"blue": 465,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 452.3,
|
||||
"h1": {
|
||||
"blocks": 438,
|
||||
"sink": "a7ecf244074b481d",
|
||||
"daa": 437,
|
||||
"blue": 438,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 468,
|
||||
"sink": "cd8cfb427f0c78e4",
|
||||
"blue": 468,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 457.3,
|
||||
"h1": {
|
||||
"blocks": 441,
|
||||
"sink": "29f8733c4ec6fa4b",
|
||||
"daa": 440,
|
||||
"blue": 441,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 473,
|
||||
"sink": "277bfdb7682804f9",
|
||||
"blue": 473,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 462.3,
|
||||
"h1": {
|
||||
"blocks": 451,
|
||||
"sink": "ae072b1106d34635",
|
||||
"daa": 450,
|
||||
"blue": 451,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 476,
|
||||
"sink": "d0f88a7c220ff170",
|
||||
"blue": 476,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 467.3,
|
||||
"h1": {
|
||||
"blocks": 458,
|
||||
"sink": "9fcfa1edabf60dd7",
|
||||
"daa": 457,
|
||||
"blue": 458,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 486,
|
||||
"sink": "9f66b943e3b972b7",
|
||||
"blue": 486,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 472.3,
|
||||
"h1": {
|
||||
"blocks": 462,
|
||||
"sink": "8dcef0d603690a6e",
|
||||
"daa": 461,
|
||||
"blue": 462,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 493,
|
||||
"sink": "a70a07e96280ab1e",
|
||||
"blue": 493,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 477.3,
|
||||
"h1": {
|
||||
"blocks": 464,
|
||||
"sink": "c6dceb1dfe662639",
|
||||
"daa": 463,
|
||||
"blue": 464,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 495,
|
||||
"sink": "1b6074e848285a01",
|
||||
"blue": 495,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 482.4,
|
||||
"h1": {
|
||||
"blocks": 468,
|
||||
"sink": "97b7a7a0a8248207",
|
||||
"daa": 467,
|
||||
"blue": 468,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 500,
|
||||
"sink": "a4045188d0e6fb97",
|
||||
"blue": 500,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 487.4,
|
||||
"h1": {
|
||||
"blocks": 472,
|
||||
"sink": "2326f1a0ffea21d8",
|
||||
"daa": 471,
|
||||
"blue": 472,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 504,
|
||||
"sink": "813c0c0f3fe0d62b",
|
||||
"blue": 504,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 492.4,
|
||||
"h1": {
|
||||
"blocks": 476,
|
||||
"sink": "2e8644b1907a9120",
|
||||
"daa": 475,
|
||||
"blue": 476,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 508,
|
||||
"sink": "9345acb132973ee6",
|
||||
"blue": 508,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 497.4,
|
||||
"h1": {
|
||||
"blocks": 481,
|
||||
"sink": "04a443536671ab8f",
|
||||
"daa": 480,
|
||||
"blue": 481,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 512,
|
||||
"sink": "0db73c40f531667d",
|
||||
"blue": 512,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 502.4,
|
||||
"h1": {
|
||||
"blocks": 487,
|
||||
"sink": "9afd673d306dc43c",
|
||||
"daa": 486,
|
||||
"blue": 487,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 519,
|
||||
"sink": "e749191f14932323",
|
||||
"blue": 519,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 507.4,
|
||||
"h1": {
|
||||
"blocks": 527,
|
||||
"sink": "afed1d222ea7304d",
|
||||
"daa": 526,
|
||||
"blue": 527,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 527,
|
||||
"sink": "afed1d222ea7304d",
|
||||
"blue": 527,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 512.4,
|
||||
"h1": {
|
||||
"blocks": 538,
|
||||
"sink": "54deb8450401f863",
|
||||
"daa": 537,
|
||||
"blue": 538,
|
||||
"key": "8da9ddee",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 538,
|
||||
"sink": "54deb8450401f863",
|
||||
"blue": 538,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 517.4,
|
||||
"h1": {
|
||||
"blocks": 543,
|
||||
"sink": "089737446a988ecf",
|
||||
"daa": 542,
|
||||
"blue": 543,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 543,
|
||||
"sink": "089737446a988ecf",
|
||||
"blue": 543,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 522.4,
|
||||
"h1": {
|
||||
"blocks": 547,
|
||||
"sink": "fddba72379711067",
|
||||
"daa": 546,
|
||||
"blue": 547,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 547,
|
||||
"sink": "fddba72379711067",
|
||||
"blue": 547,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 527.4,
|
||||
"h1": {
|
||||
"blocks": 553,
|
||||
"sink": "d090e72490be6b7a",
|
||||
"daa": 552,
|
||||
"blue": 553,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 553,
|
||||
"sink": "d090e72490be6b7a",
|
||||
"blue": 553,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 532.4,
|
||||
"h1": {
|
||||
"blocks": 561,
|
||||
"sink": "1caf40533f6a2857",
|
||||
"daa": 560,
|
||||
"blue": 561,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 561,
|
||||
"sink": "1caf40533f6a2857",
|
||||
"blue": 561,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 537.4,
|
||||
"h1": {
|
||||
"blocks": 573,
|
||||
"sink": "e5b85c33b2b6aa09",
|
||||
"daa": 572,
|
||||
"blue": 573,
|
||||
"key": "8da9ddee",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 573,
|
||||
"sink": "e5b85c33b2b6aa09",
|
||||
"blue": 573,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 542.4,
|
||||
"h1": {
|
||||
"blocks": 578,
|
||||
"sink": "317e329b8505cf1e",
|
||||
"daa": 577,
|
||||
"blue": 578,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 578,
|
||||
"sink": "317e329b8505cf1e",
|
||||
"blue": 578,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 547.5,
|
||||
"h1": {
|
||||
"blocks": 581,
|
||||
"sink": "e19cd0330c3cdf25",
|
||||
"daa": 580,
|
||||
"blue": 581,
|
||||
"key": "8da9ddee",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 581,
|
||||
"sink": "e19cd0330c3cdf25",
|
||||
"blue": 581,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 552.5,
|
||||
"h1": {
|
||||
"blocks": 586,
|
||||
"sink": "38f228d7ffc3d0c1",
|
||||
"daa": 585,
|
||||
"blue": 586,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 586,
|
||||
"sink": "38f228d7ffc3d0c1",
|
||||
"blue": 586,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 557.5,
|
||||
"h1": {
|
||||
"blocks": 592,
|
||||
"sink": "ae515bf3d13e4865",
|
||||
"daa": 591,
|
||||
"blue": 592,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 592,
|
||||
"sink": "ae515bf3d13e4865",
|
||||
"blue": 592,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 562.5,
|
||||
"h1": {
|
||||
"blocks": 595,
|
||||
"sink": "eeade53e9149c05a",
|
||||
"daa": 594,
|
||||
"blue": 595,
|
||||
"key": "8da9ddee",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 595,
|
||||
"sink": "eeade53e9149c05a",
|
||||
"blue": 595,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 567.5,
|
||||
"h1": {
|
||||
"blocks": 597,
|
||||
"sink": "a939e8caebf875d6",
|
||||
"daa": 596,
|
||||
"blue": 597,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 597,
|
||||
"sink": "a939e8caebf875d6",
|
||||
"blue": 597,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 572.5,
|
||||
"h1": {
|
||||
"blocks": 605,
|
||||
"sink": "1e585f80dc1050fa",
|
||||
"daa": 604,
|
||||
"blue": 605,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 605,
|
||||
"sink": "1e585f80dc1050fa",
|
||||
"blue": 605,
|
||||
"reorged": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"node": "/srv/builds/igneum-wt-horizon/vendor/igneum-node-horizon/target/release/igneumd",
|
||||
"miner": "/srv/builds/igneum-wt-horizon/vendor/igneum-node-horizon/target/release/igneum-miner",
|
||||
"slot": 5,
|
||||
"ports": {
|
||||
"base": 30890,
|
||||
"suffix": 985
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
12:48:26.732 fg5 case partition-gate-off-expect-reorg: mode partition, gate off (window 60 DAA), joint 240 s, split 180 s, watch 150 s, honest 1 thread(s) each, attacker 3 (joint 1), expect reorg
|
||||
12:48:28.310 fg5 h1 up pid 480280 json 30892 p2p 30891
|
||||
12:48:29.828 fg5 h2 up pid 481840 json 30902 p2p 30901 addpeer 30921
|
||||
12:52:32.849 fg5 phase 1 done at 240.0 s: H1 245 blocks sink 58126c35 daa 244; H2 245 sink 58126c35; side 2 (h2) 245 sink 58126c35; keys H1 8da9ddee H2 undefined side2 eda9cde4
|
||||
12:52:32.909 fg5 weight at the fork (last 120 blue blocks of H1's chain): side 2 67, others 53, side 2 5583 bps
|
||||
12:52:34.922 fg5 links cut at 242.1 s; side 2 (h2) now mines with 3 thread(s), the honest side with 1 each
|
||||
12:55:35.025 fg5 phase 2 done at 422.2 s: H1 405 blocks sink a27a341c daa 404 blue 405 work 12270631; side 2 436 sink f9181a06 daa 435 blue 436 work 19576159 (side 2 heavier: true); fork depth 191 DAA against window 60
|
||||
12:55:35.026 fg5 links restored at 422.2 s; watching H1 for 150 s
|
||||
12:56:05.117 fg5 t=452.3 s H1 438 blocks sink a7ecf244 held; side 2 468 blocks sink cd8cfb42
|
||||
12:56:35.193 fg5 t=482.4 s H1 468 blocks sink 97b7a7a0 held; side 2 500 blocks sink a4045188
|
||||
12:57:00.247 fg5 H1 left its pre-cut chain at 507.4 s: sink afed1d222ea7304d by eda9cde4
|
||||
12:57:05.255 fg5 t=512.4 s H1 538 blocks sink 54deb845 REORGED; side 2 538 blocks sink 54deb845
|
||||
12:57:35.285 fg5 t=542.5 s H1 578 blocks sink 317e329b REORGED; side 2 578 blocks sink 317e329b
|
||||
12:58:05.313 fg5 t=572.5 s H1 605 blocks sink 1e585f80 REORGED; side 2 605 blocks sink 1e585f80
|
||||
12:58:05.317 fg5 SUMMARY PASS (partition-gate-off-expect-reorg): side 2 held 5583 bps of the blue blocks at the fork; fork depth 191 DAA against window 60; side 2 blue work 19576159 against H1 12270631 at the heal; H1 reorged at 507.4 s (0 refusal lines, knows side 2's tip: true); side 2 kept its chain: true
|
||||
12:58:05.318 fg5 summary: /srv/builds/igneum-wt-horizon/docs/plans/mission-item-4-gate/fork-gate-partition-gate-off-expect-reorg.json
|
||||
|
|
@ -0,0 +1,653 @@
|
|||
{
|
||||
"pass": true,
|
||||
"expect": "reorg",
|
||||
"case": "partition-gate-on-expect-reorg",
|
||||
"mode": "partition",
|
||||
"gate": "on",
|
||||
"window": 60,
|
||||
"joint": 240,
|
||||
"split": 180,
|
||||
"watch": 150,
|
||||
"threads": {
|
||||
"honest_each": 1,
|
||||
"attacker_split": 3,
|
||||
"attacker_joint": 1
|
||||
},
|
||||
"keys": {
|
||||
"h1": "8da9ddee…",
|
||||
"h2": null,
|
||||
"side2": "eda9cde4…"
|
||||
},
|
||||
"share_at_fork": {
|
||||
"side2": 45,
|
||||
"others": 76,
|
||||
"side2_bps": 3719
|
||||
},
|
||||
"fork_daa": 245,
|
||||
"fork_depth_daa_at_heal": 194,
|
||||
"sinks": {
|
||||
"joint": {
|
||||
"h1": {
|
||||
"hash": "5c4cb584dc015892ddff89337412ed0883d9f97b4e791e7af2f7f64764f4f1e8",
|
||||
"blocks": 246,
|
||||
"daa": 245,
|
||||
"blue": 246,
|
||||
"blueWork": "8723556",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"h2": {
|
||||
"hash": "5c4cb584dc015892ddff89337412ed0883d9f97b4e791e7af2f7f64764f4f1e8",
|
||||
"blocks": 246,
|
||||
"daa": 245,
|
||||
"blue": 246,
|
||||
"blueWork": "8723556",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"side2": {
|
||||
"hash": "5c4cb584dc015892ddff89337412ed0883d9f97b4e791e7af2f7f64764f4f1e8",
|
||||
"blocks": 246,
|
||||
"daa": 245,
|
||||
"blue": 246,
|
||||
"blueWork": "8723556",
|
||||
"key": "8da9ddee…"
|
||||
}
|
||||
},
|
||||
"split": {
|
||||
"h1": {
|
||||
"hash": "753507c15705f4ea8ed19bc2697a11c489a052a45f28c64f9ac3d8400fa66647",
|
||||
"blocks": 412,
|
||||
"daa": 411,
|
||||
"blue": 412,
|
||||
"blueWork": "11490863",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"h2": {
|
||||
"hash": "32b7c1757fa288eed0a8ab709e49fd86f72be531db19c58e63d0aeca7a34c4f6",
|
||||
"blocks": 440,
|
||||
"daa": 439,
|
||||
"blue": 440,
|
||||
"blueWork": "18089683",
|
||||
"key": "eda9cde4…"
|
||||
},
|
||||
"side2": {
|
||||
"hash": "32b7c1757fa288eed0a8ab709e49fd86f72be531db19c58e63d0aeca7a34c4f6",
|
||||
"blocks": 440,
|
||||
"daa": 439,
|
||||
"blue": 440,
|
||||
"blueWork": "18089683",
|
||||
"key": "eda9cde4…"
|
||||
}
|
||||
}
|
||||
},
|
||||
"per_node": {
|
||||
"h1": {
|
||||
"held": false,
|
||||
"reorged": true,
|
||||
"reorg_at_s": 507.4,
|
||||
"knows_side2_tip": true,
|
||||
"refusal_lines": 0
|
||||
}
|
||||
},
|
||||
"checks": {
|
||||
"side2_under_a_third_at_fork": false,
|
||||
"fork_deeper_than_window": true,
|
||||
"side2_heavier_at_heal": true,
|
||||
"every_honest_node_learned_side2_chain": true,
|
||||
"every_honest_node_held": false,
|
||||
"every_honest_node_reorged": true,
|
||||
"every_honest_node_logged_a_refusal": false,
|
||||
"no_honest_node_logged_a_refusal": true,
|
||||
"side2_kept_its_chain": true
|
||||
},
|
||||
"failed_checks": [],
|
||||
"refusal_example": null,
|
||||
"samples": [
|
||||
{
|
||||
"t": 427.2,
|
||||
"h1": {
|
||||
"blocks": 420,
|
||||
"sink": "3c08068c8a93e490",
|
||||
"daa": 419,
|
||||
"blue": 420,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 443,
|
||||
"sink": "5058df4580954747",
|
||||
"blue": 443,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 432.2,
|
||||
"h1": {
|
||||
"blocks": 424,
|
||||
"sink": "de896377901e94a8",
|
||||
"daa": 423,
|
||||
"blue": 424,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 455,
|
||||
"sink": "a07d00aee9d3376d",
|
||||
"blue": 455,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 437.2,
|
||||
"h1": {
|
||||
"blocks": 435,
|
||||
"sink": "eaff2cb616a46c0e",
|
||||
"daa": 434,
|
||||
"blue": 435,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 461,
|
||||
"sink": "4783198d038613db",
|
||||
"blue": 461,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 442.2,
|
||||
"h1": {
|
||||
"blocks": 439,
|
||||
"sink": "103fa3b3ea629ad7",
|
||||
"daa": 438,
|
||||
"blue": 439,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 465,
|
||||
"sink": "91ba868ec4f84eef",
|
||||
"blue": 465,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 447.3,
|
||||
"h1": {
|
||||
"blocks": 448,
|
||||
"sink": "8437327aa78561ba",
|
||||
"daa": 447,
|
||||
"blue": 448,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 474,
|
||||
"sink": "bb9ac90349a213e3",
|
||||
"blue": 474,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 452.3,
|
||||
"h1": {
|
||||
"blocks": 450,
|
||||
"sink": "03bd0f5a924e03ee",
|
||||
"daa": 449,
|
||||
"blue": 450,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 478,
|
||||
"sink": "eca80f2c1a2106d5",
|
||||
"blue": 478,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 457.3,
|
||||
"h1": {
|
||||
"blocks": 461,
|
||||
"sink": "3fc505f8af71ea5f",
|
||||
"daa": 460,
|
||||
"blue": 461,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 481,
|
||||
"sink": "017216a3976533dd",
|
||||
"blue": 481,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 462.3,
|
||||
"h1": {
|
||||
"blocks": 463,
|
||||
"sink": "a1b1d645d944446d",
|
||||
"daa": 462,
|
||||
"blue": 463,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 488,
|
||||
"sink": "3ade2bb97b8e7548",
|
||||
"blue": 488,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 467.3,
|
||||
"h1": {
|
||||
"blocks": 466,
|
||||
"sink": "5b046e8c04baa74e",
|
||||
"daa": 465,
|
||||
"blue": 466,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 494,
|
||||
"sink": "179ad98b8bcc4ea5",
|
||||
"blue": 494,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 472.3,
|
||||
"h1": {
|
||||
"blocks": 470,
|
||||
"sink": "aaf64f90ccac9c8a",
|
||||
"daa": 469,
|
||||
"blue": 470,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 498,
|
||||
"sink": "1970740c1d9b0f6c",
|
||||
"blue": 498,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 477.3,
|
||||
"h1": {
|
||||
"blocks": 473,
|
||||
"sink": "b557fc4c16174c35",
|
||||
"daa": 472,
|
||||
"blue": 473,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 506,
|
||||
"sink": "078df046b3a9953f",
|
||||
"blue": 506,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 482.3,
|
||||
"h1": {
|
||||
"blocks": 480,
|
||||
"sink": "7d7d5f6734e2c727",
|
||||
"daa": 479,
|
||||
"blue": 480,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 510,
|
||||
"sink": "9e0f40b6766308e8",
|
||||
"blue": 510,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 487.4,
|
||||
"h1": {
|
||||
"blocks": 485,
|
||||
"sink": "6d3ff10f4556a1ca",
|
||||
"daa": 484,
|
||||
"blue": 485,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 512,
|
||||
"sink": "aecf9f8ea6485764",
|
||||
"blue": 512,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 492.4,
|
||||
"h1": {
|
||||
"blocks": 489,
|
||||
"sink": "1196cd92a2989963",
|
||||
"daa": 488,
|
||||
"blue": 489,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 518,
|
||||
"sink": "0a3a90068c2d74c0",
|
||||
"blue": 518,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 497.4,
|
||||
"h1": {
|
||||
"blocks": 494,
|
||||
"sink": "27ca83564fbe47ce",
|
||||
"daa": 493,
|
||||
"blue": 494,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 524,
|
||||
"sink": "42b2b2dc9f1e4be2",
|
||||
"blue": 524,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 502.4,
|
||||
"h1": {
|
||||
"blocks": 498,
|
||||
"sink": "3f2c6e34b36b890e",
|
||||
"daa": 497,
|
||||
"blue": 498,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 531,
|
||||
"sink": "d19320eebc86c66d",
|
||||
"blue": 531,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 507.4,
|
||||
"h1": {
|
||||
"blocks": 535,
|
||||
"sink": "126029df2f9caa4a",
|
||||
"daa": 534,
|
||||
"blue": 535,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 535,
|
||||
"sink": "126029df2f9caa4a",
|
||||
"blue": 535,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 512.4,
|
||||
"h1": {
|
||||
"blocks": 543,
|
||||
"sink": "533898421902f564",
|
||||
"daa": 542,
|
||||
"blue": 543,
|
||||
"key": "8da9ddee",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 543,
|
||||
"sink": "533898421902f564",
|
||||
"blue": 543,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 517.4,
|
||||
"h1": {
|
||||
"blocks": 546,
|
||||
"sink": "85a43553233cf34b",
|
||||
"daa": 545,
|
||||
"blue": 546,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 546,
|
||||
"sink": "85a43553233cf34b",
|
||||
"blue": 546,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 522.4,
|
||||
"h1": {
|
||||
"blocks": 554,
|
||||
"sink": "bed61271f9a8252d",
|
||||
"daa": 553,
|
||||
"blue": 554,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 554,
|
||||
"sink": "bed61271f9a8252d",
|
||||
"blue": 554,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 527.4,
|
||||
"h1": {
|
||||
"blocks": 560,
|
||||
"sink": "9e91960a30057229",
|
||||
"daa": 559,
|
||||
"blue": 560,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 560,
|
||||
"sink": "9e91960a30057229",
|
||||
"blue": 560,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 532.4,
|
||||
"h1": {
|
||||
"blocks": 564,
|
||||
"sink": "cd6d1240dc30d2e4",
|
||||
"daa": 563,
|
||||
"blue": 564,
|
||||
"key": "8da9ddee",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 564,
|
||||
"sink": "cd6d1240dc30d2e4",
|
||||
"blue": 564,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 537.4,
|
||||
"h1": {
|
||||
"blocks": 570,
|
||||
"sink": "0208b9cbd8adfa78",
|
||||
"daa": 569,
|
||||
"blue": 570,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 570,
|
||||
"sink": "0208b9cbd8adfa78",
|
||||
"blue": 570,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 542.4,
|
||||
"h1": {
|
||||
"blocks": 573,
|
||||
"sink": "627692d65f09e879",
|
||||
"daa": 572,
|
||||
"blue": 573,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 573,
|
||||
"sink": "627692d65f09e879",
|
||||
"blue": 573,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 547.5,
|
||||
"h1": {
|
||||
"blocks": 576,
|
||||
"sink": "84b34763f034804b",
|
||||
"daa": 575,
|
||||
"blue": 576,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 576,
|
||||
"sink": "84b34763f034804b",
|
||||
"blue": 576,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 552.5,
|
||||
"h1": {
|
||||
"blocks": 580,
|
||||
"sink": "4ce7dce8da22296a",
|
||||
"daa": 579,
|
||||
"blue": 580,
|
||||
"key": "8da9ddee",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 580,
|
||||
"sink": "4ce7dce8da22296a",
|
||||
"blue": 580,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 557.5,
|
||||
"h1": {
|
||||
"blocks": 585,
|
||||
"sink": "f8c7fb1089532dde",
|
||||
"daa": 584,
|
||||
"blue": 585,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 585,
|
||||
"sink": "f8c7fb1089532dde",
|
||||
"blue": 585,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 562.5,
|
||||
"h1": {
|
||||
"blocks": 590,
|
||||
"sink": "07d408946584e422",
|
||||
"daa": 589,
|
||||
"blue": 590,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 590,
|
||||
"sink": "07d408946584e422",
|
||||
"blue": 590,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 567.5,
|
||||
"h1": {
|
||||
"blocks": 598,
|
||||
"sink": "3ffc006b66a221b9",
|
||||
"daa": 597,
|
||||
"blue": 598,
|
||||
"key": "8da9ddee",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 598,
|
||||
"sink": "3ffc006b66a221b9",
|
||||
"blue": 598,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 572.5,
|
||||
"h1": {
|
||||
"blocks": 602,
|
||||
"sink": "b3827232c44b06d2",
|
||||
"daa": 601,
|
||||
"blue": 602,
|
||||
"key": "8da9ddee",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 602,
|
||||
"sink": "b3827232c44b06d2",
|
||||
"blue": 602,
|
||||
"reorged": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"node": "/srv/builds/igneum-wt-horizon/vendor/igneum-node-horizon/target/release/igneumd",
|
||||
"miner": "/srv/builds/igneum-wt-horizon/vendor/igneum-node-horizon/target/release/igneum-miner",
|
||||
"slot": 4,
|
||||
"ports": {
|
||||
"base": 30850,
|
||||
"suffix": 984
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
12:48:26.723 fg4 case partition-gate-on-expect-reorg: mode partition, gate on (window 60 DAA), joint 240 s, split 180 s, watch 150 s, honest 1 thread(s) each, attacker 3 (joint 1), expect reorg
|
||||
12:48:28.322 fg4 h1 up pid 480248 json 30852 p2p 30851
|
||||
12:48:29.844 fg4 h2 up pid 481994 json 30862 p2p 30861 addpeer 30881
|
||||
12:52:32.858 fg4 phase 1 done at 240.0 s: H1 246 blocks sink 5c4cb584 daa 245; H2 246 sink 5c4cb584; side 2 (h2) 246 sink 5c4cb584; keys H1 8da9ddee H2 undefined side2 eda9cde4
|
||||
12:52:32.918 fg4 weight at the fork (last 121 blue blocks of H1's chain): side 2 45, others 76, side 2 3719 bps
|
||||
12:52:34.929 fg4 links cut at 242.1 s; side 2 (h2) now mines with 3 thread(s), the honest side with 1 each
|
||||
12:55:35.033 fg4 phase 2 done at 422.2 s: H1 412 blocks sink 753507c1 daa 411 blue 412 work 11490863; side 2 440 sink 32b7c175 daa 439 blue 440 work 18089683 (side 2 heavier: true); fork depth 194 DAA against window 60
|
||||
12:55:35.035 fg4 links restored at 422.2 s; watching H1 for 150 s
|
||||
12:56:05.124 fg4 t=452.3 s H1 450 blocks sink 03bd0f5a held; side 2 478 blocks sink eca80f2c
|
||||
12:56:35.198 fg4 t=482.4 s H1 480 blocks sink 7d7d5f67 held; side 2 510 blocks sink 9e0f40b6
|
||||
12:57:00.246 fg4 H1 left its pre-cut chain at 507.4 s: sink 126029df2f9caa4a by eda9cde4
|
||||
12:57:05.255 fg4 t=512.4 s H1 543 blocks sink 53389842 REORGED; side 2 543 blocks sink 53389842
|
||||
12:57:35.298 fg4 t=542.5 s H1 573 blocks sink 627692d6 REORGED; side 2 573 blocks sink 627692d6
|
||||
12:58:05.330 fg4 t=572.5 s H1 602 blocks sink b3827232 REORGED; side 2 602 blocks sink b3827232
|
||||
12:58:05.334 fg4 SUMMARY PASS (partition-gate-on-expect-reorg): side 2 held 3719 bps of the blue blocks at the fork; fork depth 194 DAA against window 60; side 2 blue work 18089683 against H1 11490863 at the heal; H1 reorged at 507.4 s (0 refusal lines, knows side 2's tip: true); side 2 kept its chain: true
|
||||
12:58:05.334 fg4 summary: /srv/builds/igneum-wt-horizon/docs/plans/mission-item-4-gate/fork-gate-partition-gate-on-expect-reorg.json
|
||||
|
|
@ -0,0 +1,930 @@
|
|||
{
|
||||
"pass": true,
|
||||
"expect": "reorg",
|
||||
"case": "third-gate-on-expect-reorg",
|
||||
"mode": "third",
|
||||
"gate": "on",
|
||||
"window": 60,
|
||||
"joint": 240,
|
||||
"split": 180,
|
||||
"watch": 150,
|
||||
"threads": {
|
||||
"honest_each": 1,
|
||||
"attacker_split": 3,
|
||||
"attacker_joint": 2
|
||||
},
|
||||
"keys": {
|
||||
"h1": "8da9ddee…",
|
||||
"h2": "eda9cde4…",
|
||||
"side2": "0e2c6fe2…"
|
||||
},
|
||||
"share_at_fork": {
|
||||
"side2": 72,
|
||||
"others": 48,
|
||||
"side2_bps": 6000
|
||||
},
|
||||
"fork_daa": 268,
|
||||
"fork_depth_daa_at_heal": 166,
|
||||
"sinks": {
|
||||
"joint": {
|
||||
"h1": {
|
||||
"hash": "037edd2a2976af7aec3f6b00d0532706f2c4bc48a2ace2d4e92f027492aa42af",
|
||||
"blocks": 269,
|
||||
"daa": 268,
|
||||
"blue": 269,
|
||||
"blueWork": "17483286",
|
||||
"key": "0e2c6fe2…"
|
||||
},
|
||||
"h2": {
|
||||
"hash": "037edd2a2976af7aec3f6b00d0532706f2c4bc48a2ace2d4e92f027492aa42af",
|
||||
"blocks": 269,
|
||||
"daa": 268,
|
||||
"blue": 269,
|
||||
"blueWork": "17483286",
|
||||
"key": "0e2c6fe2…"
|
||||
},
|
||||
"side2": {
|
||||
"hash": "037edd2a2976af7aec3f6b00d0532706f2c4bc48a2ace2d4e92f027492aa42af",
|
||||
"blocks": 269,
|
||||
"daa": 268,
|
||||
"blue": 269,
|
||||
"blueWork": "17483286",
|
||||
"key": "0e2c6fe2…"
|
||||
}
|
||||
},
|
||||
"split": {
|
||||
"h1": {
|
||||
"hash": "06f666ba3c449f2fab804e75612a00c748a8d56568806c30a7006aae175bb27d",
|
||||
"blocks": 426,
|
||||
"daa": 425,
|
||||
"blue": 426,
|
||||
"blueWork": "24628833",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"h2": {
|
||||
"hash": "06f666ba3c449f2fab804e75612a00c748a8d56568806c30a7006aae175bb27d",
|
||||
"blocks": 426,
|
||||
"daa": 425,
|
||||
"blue": 426,
|
||||
"blueWork": "24628833",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"side2": {
|
||||
"hash": "71396cf73521295ad0fbeb320de980989ea0788dbc859129d8972a9e091e0a3c",
|
||||
"blocks": 435,
|
||||
"daa": 434,
|
||||
"blue": 435,
|
||||
"blueWork": "28969222",
|
||||
"key": "0e2c6fe2…"
|
||||
}
|
||||
}
|
||||
},
|
||||
"per_node": {
|
||||
"h1": {
|
||||
"held": false,
|
||||
"reorged": true,
|
||||
"reorg_at_s": 477.3,
|
||||
"knows_side2_tip": true,
|
||||
"refusal_lines": 0
|
||||
},
|
||||
"h2": {
|
||||
"held": false,
|
||||
"reorged": true,
|
||||
"reorg_at_s": 477.3,
|
||||
"knows_side2_tip": true,
|
||||
"refusal_lines": 0
|
||||
}
|
||||
},
|
||||
"checks": {
|
||||
"side2_under_a_third_at_fork": false,
|
||||
"fork_deeper_than_window": true,
|
||||
"side2_heavier_at_heal": true,
|
||||
"every_honest_node_learned_side2_chain": true,
|
||||
"every_honest_node_held": false,
|
||||
"every_honest_node_reorged": true,
|
||||
"every_honest_node_logged_a_refusal": false,
|
||||
"no_honest_node_logged_a_refusal": true,
|
||||
"side2_kept_its_chain": true
|
||||
},
|
||||
"failed_checks": [],
|
||||
"refusal_example": null,
|
||||
"samples": [
|
||||
{
|
||||
"t": 427.2,
|
||||
"h1": {
|
||||
"blocks": 431,
|
||||
"sink": "9a61020b8d49143a",
|
||||
"daa": 430,
|
||||
"blue": 431,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 431,
|
||||
"sink": "9a61020b8d49143a",
|
||||
"daa": 430,
|
||||
"blue": 431,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 441,
|
||||
"sink": "05e6f9d4ef677d31",
|
||||
"blue": 441,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 432.2,
|
||||
"h1": {
|
||||
"blocks": 439,
|
||||
"sink": "a4130e66a3d4a3df",
|
||||
"daa": 438,
|
||||
"blue": 439,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 439,
|
||||
"sink": "a4130e66a3d4a3df",
|
||||
"daa": 438,
|
||||
"blue": 439,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 449,
|
||||
"sink": "f7d08aee6cf90b41",
|
||||
"blue": 449,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 437.2,
|
||||
"h1": {
|
||||
"blocks": 442,
|
||||
"sink": "e1cc039c584559d7",
|
||||
"daa": 441,
|
||||
"blue": 442,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 442,
|
||||
"sink": "e1cc039c584559d7",
|
||||
"daa": 441,
|
||||
"blue": 442,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 455,
|
||||
"sink": "fa56a0ac4e5fb99c",
|
||||
"blue": 455,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 442.2,
|
||||
"h1": {
|
||||
"blocks": 444,
|
||||
"sink": "6904c2a75c7344fe",
|
||||
"daa": 443,
|
||||
"blue": 444,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 444,
|
||||
"sink": "6904c2a75c7344fe",
|
||||
"daa": 443,
|
||||
"blue": 444,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 459,
|
||||
"sink": "04b09f8a190c4051",
|
||||
"blue": 459,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 447.2,
|
||||
"h1": {
|
||||
"blocks": 449,
|
||||
"sink": "d55f8f3f03247788",
|
||||
"daa": 448,
|
||||
"blue": 449,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 449,
|
||||
"sink": "d55f8f3f03247788",
|
||||
"daa": 448,
|
||||
"blue": 449,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 462,
|
||||
"sink": "a6fa74e0833a3e0c",
|
||||
"blue": 462,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 452.2,
|
||||
"h1": {
|
||||
"blocks": 454,
|
||||
"sink": "feb2905b292ab9c7",
|
||||
"daa": 453,
|
||||
"blue": 454,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 454,
|
||||
"sink": "feb2905b292ab9c7",
|
||||
"daa": 453,
|
||||
"blue": 454,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 464,
|
||||
"sink": "093014496d558f65",
|
||||
"blue": 464,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 457.3,
|
||||
"h1": {
|
||||
"blocks": 462,
|
||||
"sink": "b10ed98591f50ec6",
|
||||
"daa": 461,
|
||||
"blue": 462,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 462,
|
||||
"sink": "b10ed98591f50ec6",
|
||||
"daa": 461,
|
||||
"blue": 462,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 469,
|
||||
"sink": "7a00df10d8b78e18",
|
||||
"blue": 469,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 462.3,
|
||||
"h1": {
|
||||
"blocks": 467,
|
||||
"sink": "ebf8c4bd560f2ccf",
|
||||
"daa": 466,
|
||||
"blue": 467,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 467,
|
||||
"sink": "ebf8c4bd560f2ccf",
|
||||
"daa": 466,
|
||||
"blue": 467,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 474,
|
||||
"sink": "ade976380c06a8d8",
|
||||
"blue": 474,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 467.3,
|
||||
"h1": {
|
||||
"blocks": 471,
|
||||
"sink": "311bf74ecfb1cb33",
|
||||
"daa": 470,
|
||||
"blue": 471,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 471,
|
||||
"sink": "311bf74ecfb1cb33",
|
||||
"daa": 470,
|
||||
"blue": 471,
|
||||
"key": "8da9ddee",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 482,
|
||||
"sink": "a1dc4abe41431122",
|
||||
"blue": 482,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 472.3,
|
||||
"h1": {
|
||||
"blocks": 476,
|
||||
"sink": "0fc8726976801d2b",
|
||||
"daa": 475,
|
||||
"blue": 476,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 476,
|
||||
"sink": "0fc8726976801d2b",
|
||||
"daa": 475,
|
||||
"blue": 476,
|
||||
"key": "eda9cde4",
|
||||
"reorged": false,
|
||||
"knows_side2_tip": false
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 487,
|
||||
"sink": "c2c737c0d473f009",
|
||||
"blue": 487,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 477.3,
|
||||
"h1": {
|
||||
"blocks": 492,
|
||||
"sink": "df2ecca49796b69c",
|
||||
"daa": 491,
|
||||
"blue": 492,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 492,
|
||||
"sink": "df2ecca49796b69c",
|
||||
"daa": 491,
|
||||
"blue": 492,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 492,
|
||||
"sink": "df2ecca49796b69c",
|
||||
"blue": 492,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 482.3,
|
||||
"h1": {
|
||||
"blocks": 498,
|
||||
"sink": "33ab64dbbd41433e",
|
||||
"daa": 497,
|
||||
"blue": 498,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 498,
|
||||
"sink": "33ab64dbbd41433e",
|
||||
"daa": 497,
|
||||
"blue": 498,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 498,
|
||||
"sink": "33ab64dbbd41433e",
|
||||
"blue": 498,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 487.3,
|
||||
"h1": {
|
||||
"blocks": 506,
|
||||
"sink": "4fa4f31a124990c1",
|
||||
"daa": 505,
|
||||
"blue": 506,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 506,
|
||||
"sink": "4fa4f31a124990c1",
|
||||
"daa": 505,
|
||||
"blue": 506,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 506,
|
||||
"sink": "4fa4f31a124990c1",
|
||||
"blue": 506,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 492.3,
|
||||
"h1": {
|
||||
"blocks": 510,
|
||||
"sink": "4121ec5f7e04b3a2",
|
||||
"daa": 509,
|
||||
"blue": 510,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 510,
|
||||
"sink": "4121ec5f7e04b3a2",
|
||||
"daa": 509,
|
||||
"blue": 510,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 510,
|
||||
"sink": "4121ec5f7e04b3a2",
|
||||
"blue": 510,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 497.3,
|
||||
"h1": {
|
||||
"blocks": 518,
|
||||
"sink": "217d584ac3d48f32",
|
||||
"daa": 517,
|
||||
"blue": 518,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 518,
|
||||
"sink": "217d584ac3d48f32",
|
||||
"daa": 517,
|
||||
"blue": 518,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 518,
|
||||
"sink": "217d584ac3d48f32",
|
||||
"blue": 518,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 502.3,
|
||||
"h1": {
|
||||
"blocks": 527,
|
||||
"sink": "d14ed2e5f11c7df7",
|
||||
"daa": 526,
|
||||
"blue": 527,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 527,
|
||||
"sink": "d14ed2e5f11c7df7",
|
||||
"daa": 526,
|
||||
"blue": 527,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 527,
|
||||
"sink": "d14ed2e5f11c7df7",
|
||||
"blue": 527,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 507.3,
|
||||
"h1": {
|
||||
"blocks": 533,
|
||||
"sink": "23cf4405d058110e",
|
||||
"daa": 532,
|
||||
"blue": 533,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 533,
|
||||
"sink": "23cf4405d058110e",
|
||||
"daa": 532,
|
||||
"blue": 533,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 533,
|
||||
"sink": "23cf4405d058110e",
|
||||
"blue": 533,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 512.4,
|
||||
"h1": {
|
||||
"blocks": 537,
|
||||
"sink": "ec6ff75c8617a6c0",
|
||||
"daa": 535,
|
||||
"blue": 536,
|
||||
"key": "8da9ddee",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 537,
|
||||
"sink": "ec6ff75c8617a6c0",
|
||||
"daa": 535,
|
||||
"blue": 536,
|
||||
"key": "8da9ddee",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 537,
|
||||
"sink": "ec6ff75c8617a6c0",
|
||||
"blue": 536,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 517.4,
|
||||
"h1": {
|
||||
"blocks": 542,
|
||||
"sink": "53152f1d8342a7ba",
|
||||
"daa": 541,
|
||||
"blue": 542,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 542,
|
||||
"sink": "53152f1d8342a7ba",
|
||||
"daa": 541,
|
||||
"blue": 542,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 542,
|
||||
"sink": "53152f1d8342a7ba",
|
||||
"blue": 542,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 522.4,
|
||||
"h1": {
|
||||
"blocks": 548,
|
||||
"sink": "1425827f8f967320",
|
||||
"daa": 547,
|
||||
"blue": 548,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 548,
|
||||
"sink": "1425827f8f967320",
|
||||
"daa": 547,
|
||||
"blue": 548,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 548,
|
||||
"sink": "1425827f8f967320",
|
||||
"blue": 548,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 527.4,
|
||||
"h1": {
|
||||
"blocks": 554,
|
||||
"sink": "12bc21c9e6549a42",
|
||||
"daa": 553,
|
||||
"blue": 554,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 554,
|
||||
"sink": "12bc21c9e6549a42",
|
||||
"daa": 553,
|
||||
"blue": 554,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 554,
|
||||
"sink": "12bc21c9e6549a42",
|
||||
"blue": 554,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 532.4,
|
||||
"h1": {
|
||||
"blocks": 559,
|
||||
"sink": "b17be188847a071b",
|
||||
"daa": 558,
|
||||
"blue": 559,
|
||||
"key": "8da9ddee",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 559,
|
||||
"sink": "b17be188847a071b",
|
||||
"daa": 558,
|
||||
"blue": 559,
|
||||
"key": "8da9ddee",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 559,
|
||||
"sink": "b17be188847a071b",
|
||||
"blue": 559,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 537.4,
|
||||
"h1": {
|
||||
"blocks": 564,
|
||||
"sink": "bcf3066ae7329fb1",
|
||||
"daa": 563,
|
||||
"blue": 564,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 564,
|
||||
"sink": "bcf3066ae7329fb1",
|
||||
"daa": 563,
|
||||
"blue": 564,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 564,
|
||||
"sink": "bcf3066ae7329fb1",
|
||||
"blue": 564,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 542.4,
|
||||
"h1": {
|
||||
"blocks": 571,
|
||||
"sink": "3c8486f382c004a4",
|
||||
"daa": 570,
|
||||
"blue": 571,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 571,
|
||||
"sink": "3c8486f382c004a4",
|
||||
"daa": 570,
|
||||
"blue": 571,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 571,
|
||||
"sink": "3c8486f382c004a4",
|
||||
"blue": 571,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 547.4,
|
||||
"h1": {
|
||||
"blocks": 573,
|
||||
"sink": "55eb5bc461792e81",
|
||||
"daa": 572,
|
||||
"blue": 573,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 573,
|
||||
"sink": "55eb5bc461792e81",
|
||||
"daa": 572,
|
||||
"blue": 573,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 573,
|
||||
"sink": "55eb5bc461792e81",
|
||||
"blue": 573,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 552.4,
|
||||
"h1": {
|
||||
"blocks": 577,
|
||||
"sink": "c5812db6a85bdadb",
|
||||
"daa": 576,
|
||||
"blue": 577,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 577,
|
||||
"sink": "c5812db6a85bdadb",
|
||||
"daa": 576,
|
||||
"blue": 577,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 577,
|
||||
"sink": "c5812db6a85bdadb",
|
||||
"blue": 577,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 557.4,
|
||||
"h1": {
|
||||
"blocks": 579,
|
||||
"sink": "a43cb662dec21b79",
|
||||
"daa": 578,
|
||||
"blue": 579,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 579,
|
||||
"sink": "a43cb662dec21b79",
|
||||
"daa": 578,
|
||||
"blue": 579,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 579,
|
||||
"sink": "a43cb662dec21b79",
|
||||
"blue": 579,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 562.4,
|
||||
"h1": {
|
||||
"blocks": 586,
|
||||
"sink": "a5490f8482cfcac1",
|
||||
"daa": 585,
|
||||
"blue": 586,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 586,
|
||||
"sink": "a5490f8482cfcac1",
|
||||
"daa": 585,
|
||||
"blue": 586,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 586,
|
||||
"sink": "a5490f8482cfcac1",
|
||||
"blue": 586,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 567.5,
|
||||
"h1": {
|
||||
"blocks": 590,
|
||||
"sink": "85ff280e3c193276",
|
||||
"daa": 589,
|
||||
"blue": 590,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 590,
|
||||
"sink": "85ff280e3c193276",
|
||||
"daa": 589,
|
||||
"blue": 590,
|
||||
"key": "eda9cde4",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 590,
|
||||
"sink": "85ff280e3c193276",
|
||||
"blue": 590,
|
||||
"reorged": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 572.5,
|
||||
"h1": {
|
||||
"blocks": 591,
|
||||
"sink": "eb3dbbc60e30ebba",
|
||||
"daa": 590,
|
||||
"blue": 591,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"h2": {
|
||||
"blocks": 591,
|
||||
"sink": "eb3dbbc60e30ebba",
|
||||
"daa": 590,
|
||||
"blue": 591,
|
||||
"key": "0e2c6fe2",
|
||||
"reorged": true,
|
||||
"knows_side2_tip": true
|
||||
},
|
||||
"side2": {
|
||||
"blocks": 591,
|
||||
"sink": "eb3dbbc60e30ebba",
|
||||
"blue": 591,
|
||||
"reorged": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"node": "/srv/builds/igneum-wt-horizon/vendor/igneum-node-horizon/target/release/igneumd",
|
||||
"miner": "/srv/builds/igneum-wt-horizon/vendor/igneum-node-horizon/target/release/igneum-miner",
|
||||
"slot": 3,
|
||||
"ports": {
|
||||
"base": 30810,
|
||||
"suffix": 983
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
12:48:26.802 fg3 case third-gate-on-expect-reorg: mode third, gate on (window 60 DAA), joint 240 s, split 180 s, watch 150 s, honest 1 thread(s) each, attacker 3 (joint 2), expect reorg
|
||||
12:48:28.386 fg3 h1 up pid 480989 json 30812 p2p 30811
|
||||
12:48:29.896 fg3 h2 up pid 482351 json 30822 p2p 30821 addpeer 30811
|
||||
12:48:31.410 fg3 b up pid 483327 json 30832 p2p 30831 addpeer 30841,30842
|
||||
12:52:34.426 fg3 phase 1 done at 240.0 s: H1 269 blocks sink 037edd2a daa 268; H2 269 sink 037edd2a; side 2 (b) 269 sink 037edd2a; keys H1 8da9ddee H2 eda9cde4 side2 0e2c6fe2
|
||||
12:52:34.451 fg3 weight at the fork (last 120 blue blocks of H1's chain): side 2 72, others 48, side 2 6000 bps
|
||||
12:52:36.465 fg3 links cut at 242.1 s; side 2 (b) now mines with 3 thread(s), the honest side with 1 each
|
||||
12:55:36.572 fg3 phase 2 done at 422.2 s: H1 426 blocks sink 06f666ba daa 425 blue 426 work 24628833; side 2 435 sink 71396cf7 daa 434 blue 435 work 28969222 (side 2 heavier: true); fork depth 166 DAA against window 60
|
||||
12:55:36.573 fg3 links restored at 422.2 s; watching H1 and H2 for 150 s
|
||||
12:56:06.662 fg3 t=452.2 s H1 454 blocks sink feb2905b held; H2 454 blocks sink feb2905b held; side 2 464 blocks sink 09301449
|
||||
12:56:31.716 fg3 H1 left its pre-cut chain at 477.3 s: sink df2ecca49796b69c by 0e2c6fe2
|
||||
12:56:31.720 fg3 H2 left its pre-cut chain at 477.3 s: sink df2ecca49796b69c by 0e2c6fe2
|
||||
12:56:36.729 fg3 t=482.3 s H1 498 blocks sink 33ab64db REORGED; H2 498 blocks sink 33ab64db REORGED; side 2 498 blocks sink 33ab64db
|
||||
12:57:06.776 fg3 t=512.4 s H1 537 blocks sink ec6ff75c REORGED; H2 537 blocks sink ec6ff75c REORGED; side 2 537 blocks sink ec6ff75c
|
||||
12:57:36.826 fg3 t=542.4 s H1 571 blocks sink 3c8486f3 REORGED; H2 571 blocks sink 3c8486f3 REORGED; side 2 571 blocks sink 3c8486f3
|
||||
12:58:06.880 fg3 t=572.5 s H1 591 blocks sink eb3dbbc6 REORGED; H2 591 blocks sink eb3dbbc6 REORGED; side 2 591 blocks sink eb3dbbc6
|
||||
12:58:06.890 fg3 SUMMARY PASS (third-gate-on-expect-reorg): side 2 held 6000 bps of the blue blocks at the fork; fork depth 166 DAA against window 60; side 2 blue work 28969222 against H1 24628833 at the heal; H1 reorged at 477.3 s (0 refusal lines, knows side 2's tip: true); H2 reorged at 477.3 s (0 refusal lines, knows side 2's tip: true); side 2 kept its chain: true
|
||||
12:58:06.890 fg3 summary: /srv/builds/igneum-wt-horizon/docs/plans/mission-item-4-gate/fork-gate-third-gate-on-expect-reorg.json
|
||||
796
docs/plans/mission-item-4-gate/summary.json
Normal file
|
|
@ -0,0 +1,796 @@
|
|||
{
|
||||
"green": true,
|
||||
"at": "2026-10-07T12:58:08.407Z",
|
||||
"heal_unchanged": true,
|
||||
"node": "/srv/builds/igneum-wt-horizon/vendor/igneum-node-horizon/target/release/igneumd",
|
||||
"miner": "/srv/builds/igneum-wt-horizon/vendor/igneum-node-horizon/target/release/igneum-miner",
|
||||
"cases": [
|
||||
{
|
||||
"mode": "attack",
|
||||
"gate": "off",
|
||||
"expect": "reorg",
|
||||
"must": "PASS",
|
||||
"line": "the rule's known-failed case: without the gate a fresh key's heavier deep fork wins on every honest node",
|
||||
"slot": 0,
|
||||
"name": "attack-gate-off-expect-reorg",
|
||||
"verdict": "PASS",
|
||||
"as_it_must": true,
|
||||
"secs": 581,
|
||||
"exit": 0,
|
||||
"summary_line": "SUMMARY PASS (attack-gate-off-expect-reorg): side 2 held 0 bps of the blue blocks at the fork; fork depth 191 DAA against window 60; side 2 blue work 17470131 against H1 14893198 at the heal; H1 reorged at 510.4 s (0 refusal lines, knows side 2's tip: true); H2 reorged at 510.4 s (0 refusal lines, knows side 2's tip: true); side 2 kept its chain: true",
|
||||
"summary": {
|
||||
"pass": true,
|
||||
"expect": "reorg",
|
||||
"case": "attack-gate-off-expect-reorg",
|
||||
"mode": "attack",
|
||||
"gate": "off",
|
||||
"window": 60,
|
||||
"joint": 240,
|
||||
"split": 180,
|
||||
"watch": 150,
|
||||
"threads": {
|
||||
"honest_each": 1,
|
||||
"attacker_split": 3,
|
||||
"attacker_joint": 0
|
||||
},
|
||||
"keys": {
|
||||
"h1": "8da9ddee…",
|
||||
"h2": "eda9cde4…",
|
||||
"side2": "0e2c6fe2…"
|
||||
},
|
||||
"share_at_fork": {
|
||||
"side2": 0,
|
||||
"others": 120,
|
||||
"side2_bps": 0
|
||||
},
|
||||
"fork_daa": 240,
|
||||
"fork_depth_daa_at_heal": 191,
|
||||
"sinks": {
|
||||
"joint": {
|
||||
"h1": {
|
||||
"hash": "e66998c63f8f5d2f3f9108a5c61730f3d5ee06a0553f47e3bce314a0e4d7228e",
|
||||
"blocks": 242,
|
||||
"daa": 240,
|
||||
"blue": 241,
|
||||
"blueWork": "8689541",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"h2": {
|
||||
"hash": "e66998c63f8f5d2f3f9108a5c61730f3d5ee06a0553f47e3bce314a0e4d7228e",
|
||||
"blocks": 242,
|
||||
"daa": 240,
|
||||
"blue": 241,
|
||||
"blueWork": "8689541",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"side2": {
|
||||
"hash": "e66998c63f8f5d2f3f9108a5c61730f3d5ee06a0553f47e3bce314a0e4d7228e",
|
||||
"blocks": 242,
|
||||
"daa": 240,
|
||||
"blue": 241,
|
||||
"blueWork": "8689541",
|
||||
"key": "8da9ddee…"
|
||||
}
|
||||
},
|
||||
"split": {
|
||||
"h1": {
|
||||
"hash": "6e932c389f2ad01a39873317f9549f0a336e66a7c840669dd5bcb44a979a19ad",
|
||||
"blocks": 421,
|
||||
"daa": 420,
|
||||
"blue": 421,
|
||||
"blueWork": "14893198",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"h2": {
|
||||
"hash": "6e932c389f2ad01a39873317f9549f0a336e66a7c840669dd5bcb44a979a19ad",
|
||||
"blocks": 421,
|
||||
"daa": 420,
|
||||
"blue": 421,
|
||||
"blueWork": "14893198",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"side2": {
|
||||
"hash": "d93a1238a397f68337f4bc28d6197a61a32fbca176f3e7f4248b6b330e239cc8",
|
||||
"blocks": 432,
|
||||
"daa": 431,
|
||||
"blue": 432,
|
||||
"blueWork": "17470131",
|
||||
"key": "0e2c6fe2…"
|
||||
}
|
||||
}
|
||||
},
|
||||
"per_node": {
|
||||
"h1": {
|
||||
"held": false,
|
||||
"reorged": true,
|
||||
"reorg_at_s": 510.4,
|
||||
"knows_side2_tip": true,
|
||||
"refusal_lines": 0
|
||||
},
|
||||
"h2": {
|
||||
"held": false,
|
||||
"reorged": true,
|
||||
"reorg_at_s": 510.4,
|
||||
"knows_side2_tip": true,
|
||||
"refusal_lines": 0
|
||||
}
|
||||
},
|
||||
"checks": {
|
||||
"side2_under_a_third_at_fork": true,
|
||||
"fork_deeper_than_window": true,
|
||||
"side2_heavier_at_heal": true,
|
||||
"every_honest_node_learned_side2_chain": true,
|
||||
"every_honest_node_held": false,
|
||||
"every_honest_node_reorged": true,
|
||||
"every_honest_node_logged_a_refusal": false,
|
||||
"no_honest_node_logged_a_refusal": true,
|
||||
"side2_kept_its_chain": true
|
||||
},
|
||||
"failed_checks": [],
|
||||
"refusal_example": null,
|
||||
"node": "/srv/builds/igneum-wt-horizon/vendor/igneum-node-horizon/target/release/igneumd",
|
||||
"miner": "/srv/builds/igneum-wt-horizon/vendor/igneum-node-horizon/target/release/igneum-miner",
|
||||
"slot": 0,
|
||||
"ports": {
|
||||
"base": 30690,
|
||||
"suffix": 980
|
||||
}
|
||||
},
|
||||
"log": "/srv/builds/igneum-wt-horizon/docs/plans/mission-item-4-gate/fork-gate-attack-gate-off-expect-reorg.log"
|
||||
},
|
||||
{
|
||||
"mode": "attack",
|
||||
"gate": "off",
|
||||
"expect": "hold",
|
||||
"must": "FAIL",
|
||||
"line": "the harness's own failed shape: with the gate off it must not report a hold",
|
||||
"slot": 1,
|
||||
"name": "attack-gate-off-expect-hold",
|
||||
"verdict": "FAIL",
|
||||
"as_it_must": true,
|
||||
"secs": 581,
|
||||
"exit": 1,
|
||||
"summary_line": "SUMMARY FAIL (attack-gate-off-expect-hold): side 2 held 0 bps of the blue blocks at the fork; fork depth 179 DAA against window 60; side 2 blue work 19683187 against H1 17459678 at the heal; H1 reorged at 480.3 s (0 refusal lines, knows side 2's tip: true); H2 reorged at 480.3 s (0 refusal lines, knows side 2's tip: true); side 2 kept its chain: true; FAILED CHECK every_honest_node_held, every_honest_node_logged_a_refusal",
|
||||
"summary": {
|
||||
"pass": false,
|
||||
"expect": "hold",
|
||||
"case": "attack-gate-off-expect-hold",
|
||||
"mode": "attack",
|
||||
"gate": "off",
|
||||
"window": 60,
|
||||
"joint": 240,
|
||||
"split": 180,
|
||||
"watch": 150,
|
||||
"threads": {
|
||||
"honest_each": 1,
|
||||
"attacker_split": 3,
|
||||
"attacker_joint": 0
|
||||
},
|
||||
"keys": {
|
||||
"h1": "8da9ddee…",
|
||||
"h2": "eda9cde4…",
|
||||
"side2": "0e2c6fe2…"
|
||||
},
|
||||
"share_at_fork": {
|
||||
"side2": 0,
|
||||
"others": 120,
|
||||
"side2_bps": 0
|
||||
},
|
||||
"fork_daa": 247,
|
||||
"fork_depth_daa_at_heal": 179,
|
||||
"sinks": {
|
||||
"joint": {
|
||||
"h1": {
|
||||
"hash": "0535d8ae67287238ee528bae5ab1f366273bd1c65c6a94342ec3879a40b81c88",
|
||||
"blocks": 248,
|
||||
"daa": 247,
|
||||
"blue": 248,
|
||||
"blueWork": "11209205",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"h2": {
|
||||
"hash": "0535d8ae67287238ee528bae5ab1f366273bd1c65c6a94342ec3879a40b81c88",
|
||||
"blocks": 248,
|
||||
"daa": 247,
|
||||
"blue": 248,
|
||||
"blueWork": "11209205",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"side2": {
|
||||
"hash": "0535d8ae67287238ee528bae5ab1f366273bd1c65c6a94342ec3879a40b81c88",
|
||||
"blocks": 248,
|
||||
"daa": 247,
|
||||
"blue": 248,
|
||||
"blueWork": "11209205",
|
||||
"key": "8da9ddee…"
|
||||
}
|
||||
},
|
||||
"split": {
|
||||
"h1": {
|
||||
"hash": "d5347d2cd3468901fda8e5a1caffe0be55d45eb12739577fadb0141d2291c2ba",
|
||||
"blocks": 412,
|
||||
"daa": 411,
|
||||
"blue": 412,
|
||||
"blueWork": "17459678",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"h2": {
|
||||
"hash": "d5347d2cd3468901fda8e5a1caffe0be55d45eb12739577fadb0141d2291c2ba",
|
||||
"blocks": 412,
|
||||
"daa": 411,
|
||||
"blue": 412,
|
||||
"blueWork": "17459678",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"side2": {
|
||||
"hash": "bfdb75e384417228a85f4098f8f2bb65d40c271ce674bea2d1cc8a3c6c335f53",
|
||||
"blocks": 427,
|
||||
"daa": 426,
|
||||
"blue": 427,
|
||||
"blueWork": "19683187",
|
||||
"key": "0e2c6fe2…"
|
||||
}
|
||||
}
|
||||
},
|
||||
"per_node": {
|
||||
"h1": {
|
||||
"held": false,
|
||||
"reorged": true,
|
||||
"reorg_at_s": 480.3,
|
||||
"knows_side2_tip": true,
|
||||
"refusal_lines": 0
|
||||
},
|
||||
"h2": {
|
||||
"held": false,
|
||||
"reorged": true,
|
||||
"reorg_at_s": 480.3,
|
||||
"knows_side2_tip": true,
|
||||
"refusal_lines": 0
|
||||
}
|
||||
},
|
||||
"checks": {
|
||||
"side2_under_a_third_at_fork": true,
|
||||
"fork_deeper_than_window": true,
|
||||
"side2_heavier_at_heal": true,
|
||||
"every_honest_node_learned_side2_chain": true,
|
||||
"every_honest_node_held": false,
|
||||
"every_honest_node_reorged": true,
|
||||
"every_honest_node_logged_a_refusal": false,
|
||||
"no_honest_node_logged_a_refusal": true,
|
||||
"side2_kept_its_chain": true
|
||||
},
|
||||
"failed_checks": [
|
||||
"every_honest_node_held",
|
||||
"every_honest_node_logged_a_refusal"
|
||||
],
|
||||
"refusal_example": null,
|
||||
"node": "/srv/builds/igneum-wt-horizon/vendor/igneum-node-horizon/target/release/igneumd",
|
||||
"miner": "/srv/builds/igneum-wt-horizon/vendor/igneum-node-horizon/target/release/igneum-miner",
|
||||
"slot": 1,
|
||||
"ports": {
|
||||
"base": 30730,
|
||||
"suffix": 981
|
||||
}
|
||||
},
|
||||
"log": "/srv/builds/igneum-wt-horizon/docs/plans/mission-item-4-gate/fork-gate-attack-gate-off-expect-hold.log"
|
||||
},
|
||||
{
|
||||
"mode": "attack",
|
||||
"gate": "on",
|
||||
"expect": "hold",
|
||||
"must": "PASS",
|
||||
"line": "the gate line: a fresh-key fork from three windows back, heavier by blue work, refused by every honest node",
|
||||
"slot": 2,
|
||||
"name": "attack-gate-on-expect-hold",
|
||||
"verdict": "PASS",
|
||||
"as_it_must": true,
|
||||
"secs": 581,
|
||||
"exit": 0,
|
||||
"summary_line": "SUMMARY PASS (attack-gate-on-expect-hold): side 2 held 0 bps of the blue blocks at the fork; fork depth 197 DAA against window 60; side 2 blue work 20297242 against H1 14807915 at the heal; H1 held (177 refusal lines, knows side 2's tip: true); H2 held (177 refusal lines, knows side 2's tip: true); side 2 kept its chain: true",
|
||||
"summary": {
|
||||
"pass": true,
|
||||
"expect": "hold",
|
||||
"case": "attack-gate-on-expect-hold",
|
||||
"mode": "attack",
|
||||
"gate": "on",
|
||||
"window": 60,
|
||||
"joint": 240,
|
||||
"split": 180,
|
||||
"watch": 150,
|
||||
"threads": {
|
||||
"honest_each": 1,
|
||||
"attacker_split": 3,
|
||||
"attacker_joint": 0
|
||||
},
|
||||
"keys": {
|
||||
"h1": "8da9ddee…",
|
||||
"h2": "eda9cde4…",
|
||||
"side2": "0e2c6fe2…"
|
||||
},
|
||||
"share_at_fork": {
|
||||
"side2": 0,
|
||||
"others": 121,
|
||||
"side2_bps": 0
|
||||
},
|
||||
"fork_daa": 233,
|
||||
"fork_depth_daa_at_heal": 197,
|
||||
"sinks": {
|
||||
"joint": {
|
||||
"h1": {
|
||||
"hash": "7ed68743f22e711490406bd380cf66fff94579fcc981344c317a46c18cbc61bb",
|
||||
"blocks": 234,
|
||||
"daa": 233,
|
||||
"blue": 234,
|
||||
"blueWork": "8862250",
|
||||
"key": "eda9cde4…"
|
||||
},
|
||||
"h2": {
|
||||
"hash": "7ed68743f22e711490406bd380cf66fff94579fcc981344c317a46c18cbc61bb",
|
||||
"blocks": 234,
|
||||
"daa": 233,
|
||||
"blue": 234,
|
||||
"blueWork": "8862250",
|
||||
"key": "eda9cde4…"
|
||||
},
|
||||
"side2": {
|
||||
"hash": "7ed68743f22e711490406bd380cf66fff94579fcc981344c317a46c18cbc61bb",
|
||||
"blocks": 234,
|
||||
"daa": 233,
|
||||
"blue": 234,
|
||||
"blueWork": "8862250",
|
||||
"key": "eda9cde4…"
|
||||
}
|
||||
},
|
||||
"split": {
|
||||
"h1": {
|
||||
"hash": "036cfe568f3d403351b338ea41b7069ad4eae0ce95308436a25b6c7aa4c1372a",
|
||||
"blocks": 396,
|
||||
"daa": 395,
|
||||
"blue": 396,
|
||||
"blueWork": "14807915",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"h2": {
|
||||
"hash": "036cfe568f3d403351b338ea41b7069ad4eae0ce95308436a25b6c7aa4c1372a",
|
||||
"blocks": 396,
|
||||
"daa": 395,
|
||||
"blue": 396,
|
||||
"blueWork": "14807915",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"side2": {
|
||||
"hash": "abb93c2318f6c2ebdbd4e14a50b3d73ba7f483b8b06b18666e1015d038d4011a",
|
||||
"blocks": 431,
|
||||
"daa": 430,
|
||||
"blue": 431,
|
||||
"blueWork": "20297242",
|
||||
"key": "0e2c6fe2…"
|
||||
}
|
||||
}
|
||||
},
|
||||
"per_node": {
|
||||
"h1": {
|
||||
"held": true,
|
||||
"reorged": false,
|
||||
"reorg_at_s": null,
|
||||
"knows_side2_tip": true,
|
||||
"refusal_lines": 177
|
||||
},
|
||||
"h2": {
|
||||
"held": true,
|
||||
"reorged": false,
|
||||
"reorg_at_s": null,
|
||||
"knows_side2_tip": true,
|
||||
"refusal_lines": 177
|
||||
}
|
||||
},
|
||||
"checks": {
|
||||
"side2_under_a_third_at_fork": true,
|
||||
"fork_deeper_than_window": true,
|
||||
"side2_heavier_at_heal": true,
|
||||
"every_honest_node_learned_side2_chain": true,
|
||||
"every_honest_node_held": true,
|
||||
"every_honest_node_reorged": false,
|
||||
"every_honest_node_logged_a_refusal": true,
|
||||
"no_honest_node_logged_a_refusal": false,
|
||||
"side2_kept_its_chain": true
|
||||
},
|
||||
"failed_checks": [],
|
||||
"refusal_example": "Fork choice: block 41225a00fb38b6394540a5707443bd70e678484cbd20aa3fa8e807bb24df8d4a forks 252 DAA back from the sink's chain and its builders hold 0.00% of the weight table at the fork (under one third); not a sink candidate (ledger 51-percent rank 2)",
|
||||
"node": "/srv/builds/igneum-wt-horizon/vendor/igneum-node-horizon/target/release/igneumd",
|
||||
"miner": "/srv/builds/igneum-wt-horizon/vendor/igneum-node-horizon/target/release/igneum-miner",
|
||||
"slot": 2,
|
||||
"ports": {
|
||||
"base": 30770,
|
||||
"suffix": 982
|
||||
}
|
||||
},
|
||||
"log": "/srv/builds/igneum-wt-horizon/docs/plans/mission-item-4-gate/fork-gate-attack-gate-on-expect-hold.log"
|
||||
},
|
||||
{
|
||||
"mode": "third",
|
||||
"gate": "on",
|
||||
"expect": "reorg",
|
||||
"must": "PASS",
|
||||
"line": "a fork whose builder holds at least a third of the table at the fork is accepted",
|
||||
"slot": 3,
|
||||
"name": "third-gate-on-expect-reorg",
|
||||
"verdict": "PASS",
|
||||
"as_it_must": true,
|
||||
"secs": 583,
|
||||
"exit": 0,
|
||||
"summary_line": "SUMMARY PASS (third-gate-on-expect-reorg): side 2 held 6000 bps of the blue blocks at the fork; fork depth 166 DAA against window 60; side 2 blue work 28969222 against H1 24628833 at the heal; H1 reorged at 477.3 s (0 refusal lines, knows side 2's tip: true); H2 reorged at 477.3 s (0 refusal lines, knows side 2's tip: true); side 2 kept its chain: true",
|
||||
"summary": {
|
||||
"pass": true,
|
||||
"expect": "reorg",
|
||||
"case": "third-gate-on-expect-reorg",
|
||||
"mode": "third",
|
||||
"gate": "on",
|
||||
"window": 60,
|
||||
"joint": 240,
|
||||
"split": 180,
|
||||
"watch": 150,
|
||||
"threads": {
|
||||
"honest_each": 1,
|
||||
"attacker_split": 3,
|
||||
"attacker_joint": 2
|
||||
},
|
||||
"keys": {
|
||||
"h1": "8da9ddee…",
|
||||
"h2": "eda9cde4…",
|
||||
"side2": "0e2c6fe2…"
|
||||
},
|
||||
"share_at_fork": {
|
||||
"side2": 72,
|
||||
"others": 48,
|
||||
"side2_bps": 6000
|
||||
},
|
||||
"fork_daa": 268,
|
||||
"fork_depth_daa_at_heal": 166,
|
||||
"sinks": {
|
||||
"joint": {
|
||||
"h1": {
|
||||
"hash": "037edd2a2976af7aec3f6b00d0532706f2c4bc48a2ace2d4e92f027492aa42af",
|
||||
"blocks": 269,
|
||||
"daa": 268,
|
||||
"blue": 269,
|
||||
"blueWork": "17483286",
|
||||
"key": "0e2c6fe2…"
|
||||
},
|
||||
"h2": {
|
||||
"hash": "037edd2a2976af7aec3f6b00d0532706f2c4bc48a2ace2d4e92f027492aa42af",
|
||||
"blocks": 269,
|
||||
"daa": 268,
|
||||
"blue": 269,
|
||||
"blueWork": "17483286",
|
||||
"key": "0e2c6fe2…"
|
||||
},
|
||||
"side2": {
|
||||
"hash": "037edd2a2976af7aec3f6b00d0532706f2c4bc48a2ace2d4e92f027492aa42af",
|
||||
"blocks": 269,
|
||||
"daa": 268,
|
||||
"blue": 269,
|
||||
"blueWork": "17483286",
|
||||
"key": "0e2c6fe2…"
|
||||
}
|
||||
},
|
||||
"split": {
|
||||
"h1": {
|
||||
"hash": "06f666ba3c449f2fab804e75612a00c748a8d56568806c30a7006aae175bb27d",
|
||||
"blocks": 426,
|
||||
"daa": 425,
|
||||
"blue": 426,
|
||||
"blueWork": "24628833",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"h2": {
|
||||
"hash": "06f666ba3c449f2fab804e75612a00c748a8d56568806c30a7006aae175bb27d",
|
||||
"blocks": 426,
|
||||
"daa": 425,
|
||||
"blue": 426,
|
||||
"blueWork": "24628833",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"side2": {
|
||||
"hash": "71396cf73521295ad0fbeb320de980989ea0788dbc859129d8972a9e091e0a3c",
|
||||
"blocks": 435,
|
||||
"daa": 434,
|
||||
"blue": 435,
|
||||
"blueWork": "28969222",
|
||||
"key": "0e2c6fe2…"
|
||||
}
|
||||
}
|
||||
},
|
||||
"per_node": {
|
||||
"h1": {
|
||||
"held": false,
|
||||
"reorged": true,
|
||||
"reorg_at_s": 477.3,
|
||||
"knows_side2_tip": true,
|
||||
"refusal_lines": 0
|
||||
},
|
||||
"h2": {
|
||||
"held": false,
|
||||
"reorged": true,
|
||||
"reorg_at_s": 477.3,
|
||||
"knows_side2_tip": true,
|
||||
"refusal_lines": 0
|
||||
}
|
||||
},
|
||||
"checks": {
|
||||
"side2_under_a_third_at_fork": false,
|
||||
"fork_deeper_than_window": true,
|
||||
"side2_heavier_at_heal": true,
|
||||
"every_honest_node_learned_side2_chain": true,
|
||||
"every_honest_node_held": false,
|
||||
"every_honest_node_reorged": true,
|
||||
"every_honest_node_logged_a_refusal": false,
|
||||
"no_honest_node_logged_a_refusal": true,
|
||||
"side2_kept_its_chain": true
|
||||
},
|
||||
"failed_checks": [],
|
||||
"refusal_example": null,
|
||||
"node": "/srv/builds/igneum-wt-horizon/vendor/igneum-node-horizon/target/release/igneumd",
|
||||
"miner": "/srv/builds/igneum-wt-horizon/vendor/igneum-node-horizon/target/release/igneum-miner",
|
||||
"slot": 3,
|
||||
"ports": {
|
||||
"base": 30810,
|
||||
"suffix": 983
|
||||
}
|
||||
},
|
||||
"log": "/srv/builds/igneum-wt-horizon/docs/plans/mission-item-4-gate/fork-gate-third-gate-on-expect-reorg.log"
|
||||
},
|
||||
{
|
||||
"mode": "partition",
|
||||
"gate": "on",
|
||||
"expect": "reorg",
|
||||
"must": "PASS",
|
||||
"line": "partition heal with the gate on: the heavier side wins",
|
||||
"slot": 4,
|
||||
"name": "partition-gate-on-expect-reorg",
|
||||
"verdict": "PASS",
|
||||
"as_it_must": true,
|
||||
"secs": 581,
|
||||
"exit": 0,
|
||||
"summary_line": "SUMMARY PASS (partition-gate-on-expect-reorg): side 2 held 3719 bps of the blue blocks at the fork; fork depth 194 DAA against window 60; side 2 blue work 18089683 against H1 11490863 at the heal; H1 reorged at 507.4 s (0 refusal lines, knows side 2's tip: true); side 2 kept its chain: true",
|
||||
"summary": {
|
||||
"pass": true,
|
||||
"expect": "reorg",
|
||||
"case": "partition-gate-on-expect-reorg",
|
||||
"mode": "partition",
|
||||
"gate": "on",
|
||||
"window": 60,
|
||||
"joint": 240,
|
||||
"split": 180,
|
||||
"watch": 150,
|
||||
"threads": {
|
||||
"honest_each": 1,
|
||||
"attacker_split": 3,
|
||||
"attacker_joint": 1
|
||||
},
|
||||
"keys": {
|
||||
"h1": "8da9ddee…",
|
||||
"h2": null,
|
||||
"side2": "eda9cde4…"
|
||||
},
|
||||
"share_at_fork": {
|
||||
"side2": 45,
|
||||
"others": 76,
|
||||
"side2_bps": 3719
|
||||
},
|
||||
"fork_daa": 245,
|
||||
"fork_depth_daa_at_heal": 194,
|
||||
"sinks": {
|
||||
"joint": {
|
||||
"h1": {
|
||||
"hash": "5c4cb584dc015892ddff89337412ed0883d9f97b4e791e7af2f7f64764f4f1e8",
|
||||
"blocks": 246,
|
||||
"daa": 245,
|
||||
"blue": 246,
|
||||
"blueWork": "8723556",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"h2": {
|
||||
"hash": "5c4cb584dc015892ddff89337412ed0883d9f97b4e791e7af2f7f64764f4f1e8",
|
||||
"blocks": 246,
|
||||
"daa": 245,
|
||||
"blue": 246,
|
||||
"blueWork": "8723556",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"side2": {
|
||||
"hash": "5c4cb584dc015892ddff89337412ed0883d9f97b4e791e7af2f7f64764f4f1e8",
|
||||
"blocks": 246,
|
||||
"daa": 245,
|
||||
"blue": 246,
|
||||
"blueWork": "8723556",
|
||||
"key": "8da9ddee…"
|
||||
}
|
||||
},
|
||||
"split": {
|
||||
"h1": {
|
||||
"hash": "753507c15705f4ea8ed19bc2697a11c489a052a45f28c64f9ac3d8400fa66647",
|
||||
"blocks": 412,
|
||||
"daa": 411,
|
||||
"blue": 412,
|
||||
"blueWork": "11490863",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"h2": {
|
||||
"hash": "32b7c1757fa288eed0a8ab709e49fd86f72be531db19c58e63d0aeca7a34c4f6",
|
||||
"blocks": 440,
|
||||
"daa": 439,
|
||||
"blue": 440,
|
||||
"blueWork": "18089683",
|
||||
"key": "eda9cde4…"
|
||||
},
|
||||
"side2": {
|
||||
"hash": "32b7c1757fa288eed0a8ab709e49fd86f72be531db19c58e63d0aeca7a34c4f6",
|
||||
"blocks": 440,
|
||||
"daa": 439,
|
||||
"blue": 440,
|
||||
"blueWork": "18089683",
|
||||
"key": "eda9cde4…"
|
||||
}
|
||||
}
|
||||
},
|
||||
"per_node": {
|
||||
"h1": {
|
||||
"held": false,
|
||||
"reorged": true,
|
||||
"reorg_at_s": 507.4,
|
||||
"knows_side2_tip": true,
|
||||
"refusal_lines": 0
|
||||
}
|
||||
},
|
||||
"checks": {
|
||||
"side2_under_a_third_at_fork": false,
|
||||
"fork_deeper_than_window": true,
|
||||
"side2_heavier_at_heal": true,
|
||||
"every_honest_node_learned_side2_chain": true,
|
||||
"every_honest_node_held": false,
|
||||
"every_honest_node_reorged": true,
|
||||
"every_honest_node_logged_a_refusal": false,
|
||||
"no_honest_node_logged_a_refusal": true,
|
||||
"side2_kept_its_chain": true
|
||||
},
|
||||
"failed_checks": [],
|
||||
"refusal_example": null,
|
||||
"node": "/srv/builds/igneum-wt-horizon/vendor/igneum-node-horizon/target/release/igneumd",
|
||||
"miner": "/srv/builds/igneum-wt-horizon/vendor/igneum-node-horizon/target/release/igneum-miner",
|
||||
"slot": 4,
|
||||
"ports": {
|
||||
"base": 30850,
|
||||
"suffix": 984
|
||||
}
|
||||
},
|
||||
"log": "/srv/builds/igneum-wt-horizon/docs/plans/mission-item-4-gate/fork-gate-partition-gate-on-expect-reorg.log"
|
||||
},
|
||||
{
|
||||
"mode": "partition",
|
||||
"gate": "off",
|
||||
"expect": "reorg",
|
||||
"must": "PASS",
|
||||
"line": "partition heal with the gate off: the same outcome, so the heal is unchanged",
|
||||
"slot": 5,
|
||||
"name": "partition-gate-off-expect-reorg",
|
||||
"verdict": "PASS",
|
||||
"as_it_must": true,
|
||||
"secs": 581,
|
||||
"exit": 0,
|
||||
"summary_line": "SUMMARY PASS (partition-gate-off-expect-reorg): side 2 held 5583 bps of the blue blocks at the fork; fork depth 191 DAA against window 60; side 2 blue work 19576159 against H1 12270631 at the heal; H1 reorged at 507.4 s (0 refusal lines, knows side 2's tip: true); side 2 kept its chain: true",
|
||||
"summary": {
|
||||
"pass": true,
|
||||
"expect": "reorg",
|
||||
"case": "partition-gate-off-expect-reorg",
|
||||
"mode": "partition",
|
||||
"gate": "off",
|
||||
"window": 60,
|
||||
"joint": 240,
|
||||
"split": 180,
|
||||
"watch": 150,
|
||||
"threads": {
|
||||
"honest_each": 1,
|
||||
"attacker_split": 3,
|
||||
"attacker_joint": 1
|
||||
},
|
||||
"keys": {
|
||||
"h1": "8da9ddee…",
|
||||
"h2": null,
|
||||
"side2": "eda9cde4…"
|
||||
},
|
||||
"share_at_fork": {
|
||||
"side2": 67,
|
||||
"others": 53,
|
||||
"side2_bps": 5583
|
||||
},
|
||||
"fork_daa": 244,
|
||||
"fork_depth_daa_at_heal": 191,
|
||||
"sinks": {
|
||||
"joint": {
|
||||
"h1": {
|
||||
"hash": "58126c351aa6324a992a47fa66cca22369450c9835d312772c87d3e1aeb409a0",
|
||||
"blocks": 245,
|
||||
"daa": 244,
|
||||
"blue": 245,
|
||||
"blueWork": "9558440",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"h2": {
|
||||
"hash": "58126c351aa6324a992a47fa66cca22369450c9835d312772c87d3e1aeb409a0",
|
||||
"blocks": 245,
|
||||
"daa": 244,
|
||||
"blue": 245,
|
||||
"blueWork": "9558440",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"side2": {
|
||||
"hash": "58126c351aa6324a992a47fa66cca22369450c9835d312772c87d3e1aeb409a0",
|
||||
"blocks": 245,
|
||||
"daa": 244,
|
||||
"blue": 245,
|
||||
"blueWork": "9558440",
|
||||
"key": "8da9ddee…"
|
||||
}
|
||||
},
|
||||
"split": {
|
||||
"h1": {
|
||||
"hash": "a27a341c694aacf22b1a78f44d433e4104f58b23533afb73b7ee6fb9aa37afe4",
|
||||
"blocks": 405,
|
||||
"daa": 404,
|
||||
"blue": 405,
|
||||
"blueWork": "12270631",
|
||||
"key": "8da9ddee…"
|
||||
},
|
||||
"h2": {
|
||||
"hash": "f9181a06c0db716fe4ed200f6f0046c9cb8fae2eb57dd7da4697a268c434a232",
|
||||
"blocks": 436,
|
||||
"daa": 435,
|
||||
"blue": 436,
|
||||
"blueWork": "19576159",
|
||||
"key": "eda9cde4…"
|
||||
},
|
||||
"side2": {
|
||||
"hash": "f9181a06c0db716fe4ed200f6f0046c9cb8fae2eb57dd7da4697a268c434a232",
|
||||
"blocks": 436,
|
||||
"daa": 435,
|
||||
"blue": 436,
|
||||
"blueWork": "19576159",
|
||||
"key": "eda9cde4…"
|
||||
}
|
||||
}
|
||||
},
|
||||
"per_node": {
|
||||
"h1": {
|
||||
"held": false,
|
||||
"reorged": true,
|
||||
"reorg_at_s": 507.4,
|
||||
"knows_side2_tip": true,
|
||||
"refusal_lines": 0
|
||||
}
|
||||
},
|
||||
"checks": {
|
||||
"side2_under_a_third_at_fork": false,
|
||||
"fork_deeper_than_window": true,
|
||||
"side2_heavier_at_heal": true,
|
||||
"every_honest_node_learned_side2_chain": true,
|
||||
"every_honest_node_held": false,
|
||||
"every_honest_node_reorged": true,
|
||||
"every_honest_node_logged_a_refusal": false,
|
||||
"no_honest_node_logged_a_refusal": true,
|
||||
"side2_kept_its_chain": true
|
||||
},
|
||||
"failed_checks": [],
|
||||
"refusal_example": null,
|
||||
"node": "/srv/builds/igneum-wt-horizon/vendor/igneum-node-horizon/target/release/igneumd",
|
||||
"miner": "/srv/builds/igneum-wt-horizon/vendor/igneum-node-horizon/target/release/igneum-miner",
|
||||
"slot": 5,
|
||||
"ports": {
|
||||
"base": 30890,
|
||||
"suffix": 985
|
||||
}
|
||||
},
|
||||
"log": "/srv/builds/igneum-wt-horizon/docs/plans/mission-item-4-gate/fork-gate-partition-gate-off-expect-reorg.log"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
Before Width: | Height: | Size: 613 KiB After Width: | Height: | Size: 676 KiB |
|
Before Width: | Height: | Size: 634 KiB After Width: | Height: | Size: 611 KiB |
|
Before Width: | Height: | Size: 393 KiB After Width: | Height: | Size: 377 KiB |
|
Before Width: | Height: | Size: 416 KiB After Width: | Height: | Size: 386 KiB |
|
|
@ -207,7 +207,7 @@ Implemented for the prototype size; Designed for genesis.
|
|||
|
||||
A load reads one 4-byte word at `src AND MASK`. Every load in every emitted kernel has exactly this form; the static check in `TESTS.md` section 5 is part of conformance (section 1.15). Because item values do not depend on the dataset size (section 1.8.5), the 1 GiB vectors remain valid for words below 2^28 at any larger size.
|
||||
|
||||
Growth beyond genesis is in section 1.13; under program class v3 the cache follows the dataset's doublings (1.13.3) and the verifier holds 256 MiB, then 512 MiB from year 4 and 1 GiB from year 12.
|
||||
Growth beyond genesis is in section 1.13; under program class v3 the cache follows the dataset's doublings (1.13.3) and the verifier holds 256 MiB, then 512 MiB from year 4 and 1 GiB from year 12. Beside the schedule the latency ladder (`docs/design/latency-ladder.md`) carries one cache rung (genesis forward-compatibility, 7 October 2026, `docs/design/genesis-forward.md` section 3): `LatencyLadder::cache_rung`, 512 MiB, entered by the same rule as a shadow rung (90 percent of blue blocks with both ladder bits set in each of seven consecutive windows, one decision per seven windows, one rung, never back), because a consumer last-level cache at the cache size gives that card's owners a 2 to 3x shortcut (`chip-model-v3`; consumer LLC 96 to 128 MB today, datacentre 256 MB). Its gate is the rung's `admissible` flag in the genesis list, false until the cold verify with the larger cache on the reference core with its sibling loaded is measured under 10 ms, the day-cache build on a 2019-class core under twice today's, and the 8 GB tier still holds dataset, cache and the prover footprint; the engine's consumption of the larger cache is owed with that measurement, and the rule never enters the rung before the flag is set.
|
||||
|
||||
## 1.6 Register initialisation
|
||||
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ Two statements frame everything below. Finality is miner-only and self-contained
|
|||
|
||||
## 3.1 Weight
|
||||
|
||||
- **W1.** Every block header names a vote key by `vote_key_hash` (section 2.4): the hash of a BLS12-381 G1 compressed public key. The first block that uses a key reveals the key in its coinbase payload. A header whose `vote_key_hash` has never been revealed is valid; the key simply cannot vote until it is revealed.
|
||||
- **W1.** Every block header names a vote key by `vote_key_hash` (section 2.4): the hash of a BLS12-381 G1 compressed public key. The first block that uses a key reveals the key in its coinbase payload. A header whose `vote_key_hash` has never been revealed is valid; the key simply cannot vote until it is revealed. Every key reveal and every vote item carries a signature scheme byte, `sig_scheme` (genesis forward-compatibility, 7 October 2026, `docs/design/genesis-forward.md`): the genesis value is 0, BLS12-381 in the minimal-public-key setting, and a node refuses any reveal, vote or successor whose byte is not the active scheme. The active scheme is the genesis byte until a program class that the 95 percent class signal moves to names another (`igneum::sig_scheme_of_class`, a genesis table with no row today), so a post-quantum scheme arrives by signal, never by a fork; the aggregated-vote format (`docs/analysis/mission/future.md` 7.3) ships before the flip.
|
||||
- **W2.** Weight is counted in blocks and denominated in past-median time (rule of 3 October 2026, ledger M14 and F14, round 3; the simulated form is kept below). Cut the trailing 30 days of past-median time before C, `(mt(C) - 2,592,000 s, mt(C)]`, into 43,200 buckets of 60 s; a blue block in C's past falls in the bucket that holds its own past-median time. The weight of key k at C is the sum over buckets of k's share of the blue blocks in that bucket (an empty bucket contributes 0 to everyone). A bucket is worth 1 whatever it holds, so 50x the blocks in one minute is one minute of weight, and a retarget lag can neither inflate a key's count nor age the window. No damping, no cap, no floor. Blocks are the only thing in proof of work that cannot be forged, so weight is counted in blocks; time is the denominator because blocks per unit of DAA time is exactly what a lagging controller lets a renter buy (section 2.3; `docs/review/round-3-2026-10-03.md`, "Tonight's devnet"). As simulated (`sim/results_v2.md`, every run): the number of blue blocks in C's past whose header names k and whose DAA score is in `(daa(C) - 2,592,000, daa(C)]`. The two forms agree whenever the controller holds the target; O-3.14 runs the simulation under both with the DAA in the loop and confirms or reverts this rule at gate 3. The damped rule of version 1 was removed because its 2x cap was defeated by splitting into free keys (`sim/results.md` table C; `docs/bench-log.md` finality_sim entry).
|
||||
- **W3.** Dust: a key with fewer than 100 blue blocks in the window (a block count, not bucket weight) is not a voter and is in no denominator. Measured consequence (`sim/results_v2.md` A and G): every honest key in a 1,000-key Pareto network clears 100 blocks by day 20 from zero history and the smallest new keys need up to 25 days after a doubling; a 9x renter's victims lose about one point to dust (B).
|
||||
- **W4.** Steady state: weight equals hashrate. Simulated correlation 1.00000 at day 60, Gini equal to three figures, weight-to-hash ratio within 0.82 to 1.12 for every key (`sim/results_v2.md` A).
|
||||
- **W5.** Key succession: a message signed by the old key naming a new key, included in any block, moves the old key's weight history to the new key once. The old key is dead thereafter: its later blocks earn nothing and its votes are invalid.
|
||||
- **W5.** Key succession: a succession item signed by both keys (the old key hands over, the successor consents and proves possession in one signature) over `(chain_id, daa, old key, successor key, successor scheme)`, carried in any block, moves the old key's weight to the successor once. The fold is a function of the chain, as the equivocation ban (3.6) and the leave (W7) are: at checkpoint C the old key's blue blocks in the window are credited to the successor exactly when some block in C's past carries the succession and the rule is active at C, the successor inherits the window as it stands (the count and its oldest block, never a fresh window), and a ban or a leave on the old key lands on the successor (the forfeit term inherited). The old key is dead thereafter: its votes are refused and never carried, and no node records a second succession from it, nor one naming as successor a key that has itself handed over (which also refuses every cycle). A chain old to new to newer is legal, each key handing over once. Implemented 7 October 2026 (`docs/design/genesis-forward.md` section 2; behind `finality_succession_activation_daa`, 0 on the testnet).
|
||||
- **W6.** Keys are free. Nothing in the protocol prices a vote key and the devnet launcher mints one per worker process (ledger F17, round 3). Weight is the only Sybil-resistant quantity in this specification, so every rule that draws from the voter population draws by weight and never per key: W2 (no damping, no per-key cap), the shard sortition of section 7.2 (drawn by weight since 3 October 2026) and the sub-user sortition of S2. A rule that counts keys is a rule a splitter wins.
|
||||
|
||||
The headline arithmetic (W2 with constant hashrate): an attacker with share a of hashrate for t days holds weight share `(t/30) x a/(1+a)`, verified by simulation to 0.04 points for a = 1 and 2 (`sim/results_v2.md` B).
|
||||
|
|
@ -166,9 +166,10 @@ Status of this section: Implemented in `vendor/igneum-node` (reading guide in `d
|
|||
|
||||
| Clause | Implementation | Departure or gap |
|
||||
|---|---|---|
|
||||
| W1 | `vote_key_hash` = BLAKE2b (domain `IgneumVoteKeyHash`) of the 48-byte compressed G1 key. The key is revealed with a proof of possession in the miner's coinbase extra data (`IGNK` plus 288 hex characters) and a node registers it only when the hash matches the header. A vote carries the public key too, so a key that votes is revealed by its vote | The reveal is hex, not binary, because the template RPC carries extra data as a UTF-8 string. Mainnet should carry the reveal in a dedicated field or transaction |
|
||||
| W1 | `vote_key_hash` = BLAKE2b (domain `IgneumVoteKeyHash`) of the 48-byte compressed G1 key. The key is revealed with a proof of possession in the miner's coinbase extra data (`IGNK` plus 288 hex characters, scheme 0 implied; or `IGNS` plus two hex characters of the scheme byte plus the 288, the explicit form) and a node registers it only when the hash matches the header and the scheme byte is the active one. A vote carries the public key too, so a key that votes is revealed by its vote. The vote item carries its scheme byte as item tag 5 (`scheme \|\| vote`; tag 1 is the plain scheme-0 form every live network carries), evidence as tag 6; under `sig_scheme_activation_daa` every template writes the explicit forms (7 October 2026) | The reveal is hex, not binary, because the template RPC carries extra data as a UTF-8 string. Mainnet should carry the reveal in a dedicated field or transaction |
|
||||
| W2 | Blue blocks per key in `(daa(C) - window, daa(C)]`, counted along C's selected chain through every chain block's mergeset blues, C included | O(window) per checkpoint: fine at the devnet window of 7,200 DAA seconds, not at 2,592,000. Mainnet needs an incremental window kept per chain block |
|
||||
| W3, W5 | Dust excludes a key from the voter list and from both denominators | Key succession (W5) is not implemented |
|
||||
| W3 | Dust excludes a key from the voter list and from both denominators | |
|
||||
| W5 | `Succession` item (tag 7, 297 bytes: daa, old key, successor key, successor scheme byte, both signatures under `IGNEUM_SUCCEED_V1_...`), submitted over `submitFinalitySuccession` by the successor's miner, carried after the leaves in the templates of every node that holds it, one record per old key; `successions_at` dates it from the lowest-DAA carrier in C's past and `voters_at` folds the old key into the successor (`fold_successions`), bans and leaves with it; the successor's presence counts the old key's carried votes; `getFinalityWeights` shows `succeededFrom` on the successor and a weightless `succeededTo` row for the old key. Behind `finality_succession_activation_daa` (never on the devnet, 0 on the testnet). Tests: the unit test `a_key_hands_its_window_to_a_successor_once_and_a_second_succession_is_refused` (two nodes agree on every voter list, the successor locks on the inherited weight, A to D and C to A refused) and the fast-time harness `infra/fast-time/key-succession.mjs` | Successions travel in blocks only (no p2p gossip kind; the successor's own node carries it); a record outlives the weight it moved by one window and is then trimmed, so a key that handed over could hand over again two windows later with nothing left to hand |
|
||||
| C1 | Checkpoint i is the lowest selected-chain block with blue score at least 30 i (blue scores along the chain can skip values), determined when the sink's blue score reaches 30 i + d, d = 20 on devnet. Re-determination (branch `fud-consensus`, 4 October 2026 night, ledger F24): after every virtual change, every unlocked record whose block is no longer a chain ancestor of the sink is determined again on the new chain (`on_virtual_changed`, "re-determined" log line); the certificate held over the old block is dropped, the fold clock restarts, and the certificates kept pending over the new block (`pending_certificates`, at most 4 per index, indices up to 64 ahead of the next determination) are verified. A locked record is never revisited. Unit test `reorg_past_an_unlocked_checkpoint_re_determines_it_and_verifies_the_pending_certificate` (a 6-block side chain's certificate is pending with no conflict, the 15-block side chain overtakes, index 13 is re-determined and locks from it; a block with the wrong blue score is refused) and `a_locked_checkpoint_pins_the_chain_and_a_certificate_against_it_conflicts` (a side chain twice as long does not become the sink past a lock, the certificate against the lock is the one conflict) | d = 20 is below the placeholder 60; the devnet reorg-depth distribution that sets d has not been recorded. Measured in `docs/bench-log.md`, "round-4 consensus items" (reorg run) |
|
||||
| C2 | BLS signature over `"igneum-vote-v1/" \|\| chain_id \|\| 0 \|\| index \|\| hash(C_i)` under `IGNEUM_VOTE_V1_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_`; the chain id is the prefixed network name (`igneum-devnet`, `igneum-devnet-7`); votes are p2p message 70 and ride in the coinbase extra data of every block | |
|
||||
| C3 | Certificate = index, checkpoint, voter count, signer bitmap over the canonical voter list (keys above dust and not stripped, sorted by key hash), aggregate signature, aggregator key hash and sortition proof. Every template carries the certificates not yet in its past | The validity rule (a block whose selected chain misses a certified checkpoint is invalid) is NOT enforced; only fork choice (F1, F2) is |
|
||||
|
|
|
|||
|
|
@ -103,4 +103,6 @@ Decision at gate 3 with the devnet, where the time to first block after an epoch
|
|||
|
||||
## 4.8 Open items from the prototype
|
||||
|
||||
Flagged, not sized (genesis forward-compatibility, 7 October 2026, `docs/analysis/mission/future.md` 7.2 and `docs/design/genesis-forward.md` section 4): a cryptographically relevant quantum computer computes the class-group order by Shor, which removes the sequentiality assumption of the Wesolowski VDF, so an attacker with one grinds the hourly program seed; the fallback is a hash-chain delay behind the same version byte that moves the signature scheme (a class change by the 95 percent signal), designed and sized when the scheme flip is scheduled, not before. Nothing in the pipeline of 4.3 and 4.4 changes today.
|
||||
|
||||
Carried into section 6: external review of `classgroup.rs` against chiavdf (O-4.1); reference core choice (O-4.2); whether `C(e)` must be certified and the header field (O-4.3); the fallback (O-4.4); HashPrime layout, carrying D in the proof, compact form encoding (O-4.5); reduction only when `a` exceeds 8 limbs as chiavdf does, a further speedup to port (O-4.6); no fuzzing of `deserialize` on hostile bytes beyond validity checks, no measurement on NVIDIA or AMD hosts' CPUs (O-4.7).
|
||||
|
|
|
|||
|
|
@ -326,6 +326,11 @@ pub fn era_draw(era_bytes: &[u8], allowed: &[u8]) -> EraParams {
|
|||
let j = i + (r[i] % n as u64) as usize;
|
||||
c.swap(i, j);
|
||||
}
|
||||
// Draws 8 and 9, consumed and not used (spec 01 section 1.13.1 for `epoch_len`; `docs/design/latency-ladder.md`
|
||||
// section 2 for the latency ladder): both parameters are set by miner signal, and consuming their slots here means a
|
||||
// later use of either changes no other draw. Nothing below reads them, so every value drawn above is what it was.
|
||||
let _epoch_len_draw = s.next();
|
||||
let _latency_ladder_draw = s.next();
|
||||
let mut chosen: Vec<u8> = c[..free].to_vec();
|
||||
chosen.sort_unstable();
|
||||
let mut pos = [0u8; 4];
|
||||
|
|
@ -804,7 +809,43 @@ pub const V3_CLASS: LoadClass = LoadClass { era: None, hot: None, ..LoadClass::M
|
|||
/// of 256 ALU instructions run 27 times per iteration ("mx8+sh256x27", 55,296 shadow instructions per hash). The
|
||||
/// base program, the 16 loads, the item construction, the cache growth rule and the era draw are class v3's, draw
|
||||
/// for draw, so a v4 epoch's day cache and dataset are the v3 day's. Composed with the era exactly as V3 is.
|
||||
pub const V4_CLASS: LoadClass = LoadClass { shadow: Some(ShadowClass { instrs: 256, reps: 27 }), ..V3_CLASS };
|
||||
pub const V4_CLASS: LoadClass = LoadClass { shadow: Some(ShadowClass { instrs: V4_SHADOW_INSTRS, reps: V4_SHADOW_REPS }), ..V3_CLASS };
|
||||
|
||||
/// The shadow block size of class v4 at every rung of the latency ladder (`docs/design/latency-ladder.md`): 256
|
||||
/// instructions. The ladder moves the pass count alone.
|
||||
pub const V4_SHADOW_INSTRS: u16 = 256;
|
||||
|
||||
/// The shadow passes of class v4 at rung 0 of the latency ladder: 27 (`mx8+sh256x27`, about 102,100 counted ops).
|
||||
pub const V4_SHADOW_REPS: u16 = 27;
|
||||
|
||||
/// Class v4 at a rung of the latency ladder (`docs/design/latency-ladder.md` section 2): [`V4_CLASS`] with the
|
||||
/// 256-instruction shadow block run `reps` times per iteration. `reps` 0 means the class's own count, so
|
||||
/// `v4_class_at(0) == v4_class_at(27) == V4_CLASS` and a caller that knows no rung changes nothing.
|
||||
pub fn v4_class_at(reps: u16) -> LoadClass {
|
||||
if reps == 0 {
|
||||
V4_CLASS
|
||||
} else {
|
||||
LoadClass { shadow: Some(ShadowClass { instrs: V4_SHADOW_INSTRS, reps }), ..V3_CLASS }
|
||||
}
|
||||
}
|
||||
|
||||
/// The shadow passes of a class v4 load class at any rung of the ladder, the era draw set aside (`Some(27)` for
|
||||
/// [`V4_CLASS`] itself); `None` for every other class, a measurement class with another block size included.
|
||||
pub fn v4_rung_reps(class: &LoadClass) -> Option<u16> {
|
||||
let base = LoadClass { era: None, ..*class };
|
||||
match base.shadow {
|
||||
Some(ShadowClass { instrs: V4_SHADOW_INSTRS, reps }) if LoadClass { shadow: None, ..base } == V3_CLASS => Some(reps),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Counted integer ops per hash of class v4 at `reps` shadow passes, the convention of
|
||||
/// `docs/analysis/latency-shadow-2026-10-06.md` section 1: 930 for the base program and its loads, 1.83 ops per
|
||||
/// shadow instruction (137 / 75 over the non-load weights), 8 iterations x 256 instructions x `reps` shadow
|
||||
/// instructions. Approximate by construction; the label of a rung, never a consensus value.
|
||||
pub fn v4_counted_ops(reps: u16) -> u64 {
|
||||
930 + (ITERATIONS as u64 * V4_SHADOW_INSTRS as u64 * reps as u64 * 183).div_ceil(100)
|
||||
}
|
||||
|
||||
/// The width set class v3's era draw chooses from: 4 bytes only (the read-width decision of 5 October 2026; the
|
||||
/// draw is consumed, so widening the set at genesis keeps the derivation).
|
||||
|
|
@ -1009,7 +1050,12 @@ impl Program {
|
|||
/// || attempt_le32`. Written into every pack so a version 1 program, or another attempt of the same seed,
|
||||
/// can never be mistaken for this one.
|
||||
pub fn program_id(&self) -> u64 {
|
||||
if self.class.is_v2() || self.generator == GENERATOR_VERSION_V3 || self.generator == GENERATOR_VERSION_V4 {
|
||||
// Latency ladder (docs/design/latency-ladder.md section 7): a class v4 program above rung 0 carries its shadow
|
||||
// size in the id (`program_id_class`, the "shadow/" bytes), so two rungs of one seed never share an id and a
|
||||
// pack of another rung is refused as a pack of another class is. Rung 0 keeps `program_id(4, seed, attempt)`
|
||||
// byte for byte, so every v4 id written before the ladder stands.
|
||||
let v4_rung_0 = self.generator == GENERATOR_VERSION_V4 && LoadClass { era: None, ..self.class } == V4_CLASS;
|
||||
if self.class.is_v2() || self.generator == GENERATOR_VERSION_V3 || v4_rung_0 {
|
||||
// Spec 01 section 1.4.6: a class v3 program's id is `program_id(3, seed, attempt)`, a class v4 program's
|
||||
// `program_id(4, seed, attempt)` (Counter ASIC 3.0); the generator version in the preimage separates
|
||||
// them from every version 2 program of the same seed
|
||||
|
|
@ -1378,6 +1424,27 @@ pub fn generate_from_seed_bytes_program_class(seed_string: &str, seed_bytes: &[u
|
|||
p
|
||||
}
|
||||
|
||||
/// [`generate_from_seed_bytes_program_class`] at a rung of the latency ladder (`docs/design/latency-ladder.md`
|
||||
/// section 2): `shadow_reps` is the shadow pass count the chain's step gives the epoch, 0 for the class's own. Class
|
||||
/// v4 at a rung above 0 draws from [`v4_class_at`] with the era inside and generator 4 stamped; every other class,
|
||||
/// and class v4 at rung 0, is [`generate_from_seed_bytes_program_class`] byte for byte. The base program, the 16 loads
|
||||
/// and the era draw do not move with the rung: only the pass count of the shadow block does.
|
||||
pub fn generate_from_seed_bytes_program_class_shadow(seed_string: &str, seed_bytes: &[u8], class: ProgramClass, era_bytes: Option<&[u8]>, shadow_reps: u16) -> Program {
|
||||
if class != ProgramClass::V4 || shadow_reps == 0 || shadow_reps == V4_SHADOW_REPS {
|
||||
return generate_from_seed_bytes_program_class(seed_string, seed_bytes, class, era_bytes);
|
||||
}
|
||||
let base = v4_class_at(shadow_reps);
|
||||
match era_bytes {
|
||||
Some(era) => generate_era_generator(seed_string, seed_bytes, base, era, &V3_ALLOWED, GENERATOR_VERSION_V4),
|
||||
None => {
|
||||
let mut p = generate_from_seed_bytes_class(seed_string, seed_bytes, base);
|
||||
p.generator = GENERATOR_VERSION_V4;
|
||||
p.era_bytes = None;
|
||||
p
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The program of a seed string (its UTF-8 bytes are the program seed).
|
||||
pub fn generate(seed_string: &str) -> Program {
|
||||
generate_from_seed_bytes(seed_string, seed_string.as_bytes())
|
||||
|
|
@ -2027,4 +2094,72 @@ mod tests {
|
|||
assert_eq!(again.shadow, sh.shadow);
|
||||
assert_eq!(crate::verify::hash_warp(&again, 0, &ds), h1);
|
||||
}
|
||||
|
||||
/// Latency ladder (`docs/design/latency-ladder.md`), the known-failed case first: before the ladder a changed N
|
||||
/// was a hard fork. Two nodes drawing class v4 at 27 and at 35 passes from the same seeds build the same base
|
||||
/// program and the same shadow block, carry generator 4 on both and, under the id rule as it stood, the SAME id
|
||||
/// (`program_id(4, seed, attempt)` reads no shadow size), yet their warps hash differently: every block of one is
|
||||
/// invalid to the other and no pack line told them apart. After: the rung is a parameter of the chain's step,
|
||||
/// rung 0 is `V4_CLASS` byte for byte, and a rung above carries its pass count in the id.
|
||||
#[test]
|
||||
fn latency_ladder_known_failed_a_changed_n_was_a_hard_fork_and_rungs_are_class_v4() {
|
||||
let era = [7u8; 32];
|
||||
let today = generate_from_seed_bytes_program_class("igneum-genesis", b"igneum-genesis", ProgramClass::V4, Some(&era));
|
||||
let r0 = generate_from_seed_bytes_program_class_shadow("igneum-genesis", b"igneum-genesis", ProgramClass::V4, Some(&era), 0);
|
||||
let r27 = generate_from_seed_bytes_program_class_shadow("igneum-genesis", b"igneum-genesis", ProgramClass::V4, Some(&era), V4_SHADOW_REPS);
|
||||
assert_eq!(r0, today, "rung 0 is class v4 byte for byte");
|
||||
assert_eq!(r27, today, "27 passes is rung 0");
|
||||
let r1 = generate_from_seed_bytes_program_class_shadow("igneum-genesis", b"igneum-genesis", ProgramClass::V4, Some(&era), 35);
|
||||
// the failed case, as it stood: the same base, the same block, the same seed words, generator 4 on both, one id
|
||||
assert_eq!(r1.instrs, today.instrs, "the base program is the class's, draw for draw");
|
||||
assert_eq!(r1.shadow, today.shadow, "the block is the same draw; only the pass count moves");
|
||||
assert_eq!((r1.seed, r1.attempt, r1.generator, r1.era_bytes.clone()), (today.seed, today.attempt, today.generator, today.era_bytes.clone()));
|
||||
assert_eq!(program_id(GENERATOR_VERSION_V4, &r1.seed, r1.attempt), program_id(GENERATOR_VERSION_V4, &today.seed, today.attempt), "the old rule gave both nodes one id");
|
||||
assert_eq!(r1.shadow_reps(), 35);
|
||||
assert_eq!(r1.shadow_instrs_per_hash(), ITERATIONS * 256 * 35);
|
||||
let ds = crate::verify::DatasetSource::new("2026-10-06", crate::verify::DatasetMode::ClosedForm, 20);
|
||||
let h0 = crate::verify::hash_warp(&today, 0, &ds);
|
||||
let h1 = crate::verify::hash_warp(&r1, 0, &ds);
|
||||
assert_ne!(h0, h1, "a changed N is another hash: before the ladder, a hard fork");
|
||||
// after: the rung is in the id above rung 0; rung 0 keeps the id written before the ladder
|
||||
assert_ne!(r1.program_id(), today.program_id(), "the rung is in the id");
|
||||
assert_eq!(r1.program_id(), program_id_class(GENERATOR_VERSION_V4, &r1.seed, r1.attempt, &r1.class));
|
||||
assert_eq!(today.program_id(), program_id(GENERATOR_VERSION_V4, &today.seed, today.attempt), "rung 0 keeps the v4 id");
|
||||
assert_eq!(r1.program_class(), ProgramClass::V4, "a rung is class v4");
|
||||
assert_eq!(v4_rung_reps(&r1.class), Some(35));
|
||||
assert_eq!(v4_rung_reps(&today.class), Some(27));
|
||||
assert_eq!(v4_rung_reps(&V4_CLASS), Some(27));
|
||||
assert_eq!(v4_rung_reps(&V3_CLASS), None);
|
||||
assert_eq!(v4_rung_reps(&LoadClass::V2), None);
|
||||
assert_eq!(v4_rung_reps(&LoadClass::MX8.with_shadow(64, 52)), None, "another block size is a measurement class, not a rung");
|
||||
assert_eq!(v4_class_at(0), V4_CLASS);
|
||||
assert_eq!(v4_class_at(27), V4_CLASS);
|
||||
assert_eq!(v4_class_at(35), LoadClass::parse("mx8+sh256x35").unwrap());
|
||||
assert_eq!(LoadClass { era: None, ..r1.class }, v4_class_at(35), "the era rides inside the rung's class");
|
||||
assert_eq!(r1.class.era, today.class.era, "the same era draw at every rung");
|
||||
assert!(check(&r1).is_ok(), "the acceptance rule reads the base program, which did not move");
|
||||
// every rung of the designed ladder is another program with its own id
|
||||
let rungs = [27u16, 35, 53, 88, 173, 267];
|
||||
let ids: Vec<u64> = rungs.iter().map(|&r| generate_from_seed_bytes_program_class_shadow("igneum-genesis", b"igneum-genesis", ProgramClass::V4, Some(&era), r).program_id()).collect();
|
||||
for i in 0..ids.len() {
|
||||
for j in 0..i {
|
||||
assert_ne!(ids[i], ids[j], "rungs {} and {} share an id", rungs[i], rungs[j]);
|
||||
}
|
||||
}
|
||||
// the ops labels of the rungs, within 1 percent of the measured rungs of algorithm.md 5.3a
|
||||
for (r, ops) in [(27u16, 102_100u64), (35, 132_100), (53, 199_600), (88, 330_700), (173, 649_400), (267, 1_001_600)] {
|
||||
let got = v4_counted_ops(r);
|
||||
assert!(got.abs_diff(ops) * 100 < ops, "reps {r}: {got} counted ops against the label {ops}");
|
||||
}
|
||||
// other classes ignore the rung; class v4 without an era takes it
|
||||
assert_eq!(generate_from_seed_bytes_program_class_shadow("igneum-genesis", b"igneum-genesis", ProgramClass::V3, Some(&era), 35), generate_from_seed_bytes_program_class("igneum-genesis", b"igneum-genesis", ProgramClass::V3, Some(&era)));
|
||||
assert_eq!(generate_from_seed_bytes_program_class_shadow("igneum-genesis", b"igneum-genesis", ProgramClass::V2, None, 35), generate_from_seed_bytes_program_class("igneum-genesis", b"igneum-genesis", ProgramClass::V2, None));
|
||||
let bare = generate_from_seed_bytes_program_class_shadow("igneum-genesis", b"igneum-genesis", ProgramClass::V4, None, 35);
|
||||
assert_eq!((bare.generator, bare.shadow_reps(), bare.era_bytes.is_none()), (GENERATOR_VERSION_V4, 35, true));
|
||||
// the era stream consumes draws 8 and 9 after the seven it uses, so the seven are what they were: the pinned era
|
||||
// packs of tests/packs.rs hold the values; here, the draw is a function of the bytes and the set alone
|
||||
let e = era_draw(&era, &V3_ALLOWED);
|
||||
assert_eq!(e, era_draw(&era, &V3_ALLOWED));
|
||||
assert_eq!(e.width_words, 1);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ pub mod verify;
|
|||
|
||||
pub use bind::{block_init_words, day_bytes, pow256_from_lane, target64_from_le256};
|
||||
pub use accept::{check as accept_program, AcceptReport, Reject};
|
||||
pub use generator::{generate, generate_from_seed_bytes, generate_from_seed_bytes_program_class, Instr, LoadClass, Op, Program, ProgramClass, GENERATOR_VERSION, GENERATOR_VERSION_V3, GENERATOR_VERSION_V4, V3_CLASS, V4_CLASS};
|
||||
pub use generator::{generate, generate_from_seed_bytes, generate_from_seed_bytes_program_class, generate_from_seed_bytes_program_class_shadow, v4_class_at, v4_counted_ops, v4_rung_reps, Instr, LoadClass, Op, Program, ProgramClass, GENERATOR_VERSION, GENERATOR_VERSION_V3, GENERATOR_VERSION_V4, V3_CLASS, V4_CLASS, V4_SHADOW_INSTRS, V4_SHADOW_REPS};
|
||||
pub use memhard::{cache_log2_words, dataset_log2_words, days_since_genesis, growth_doublings, Cache, MemhardCpu, MixParams, Shape};
|
||||
pub use seed::{fnv1a64, seed_words, SplitMix64};
|
||||
pub use verify::{hash_warp, interpret_warp_init, verify_block, DatasetMode, DatasetSource, Epoch};
|
||||
|
|
|
|||
|
|
@ -44,6 +44,9 @@ struct Args {
|
|||
days: u64,
|
||||
/// The program class (Counter ASIC 2.0 seam): v2 (default), v3 (V3_CLASS, generator 3) or v4 (V4_CLASS, generator 4).
|
||||
program_class: Option<ProgramClass>,
|
||||
/// The shadow pass count of a class v4 program at a rung of the latency ladder (`--shadow-reps`, 0 = the class's
|
||||
/// own 27; `docs/design/latency-ladder.md`); read under `--program-class v4` only.
|
||||
shadow_reps: u16,
|
||||
/// The era seed bytes a class v3 chain program records (`--era-hex`).
|
||||
era_hex: Option<String>,
|
||||
/// Era layout: `--era igneum-era-test/<n>` or `--era <n>:<64 hex>` composes the era class over `--class` with
|
||||
|
|
@ -99,6 +102,7 @@ fn usage() -> ! {
|
|||
\x20 also: w4, w16, w64, w64x4, p4,p16,p64[xN], <class>m<mult>[g], <class>+sh<S>x<R> (latency-shadow block of S ALU instructions x R passes per iteration, Counter ASIC 3.0 item 8)\n\
|
||||
\x20 --days N days since genesis for the cache growth rule of a class with it (default 0: the 2^26-word cache)\n\
|
||||
\x20 --program-class v2|v3|v4 the program class of the seam (v3 = generator 3 on V3_CLASS, v4 = generator 4 on V4_CLASS = mx8+sh256x27, the chain's own derivation; --era-hex records the era seed)\n\
|
||||
\x20 --shadow-reps N class v4 at a rung of the latency ladder: the shadow block's pass count (0 = the class's own 27; docs/design/latency-ladder.md), with --program-class v4\n\
|
||||
\x20 --era E era layout over --class: igneum-era-test/<n> or <n>:<64 hex> (the 32-byte era seed E_n)\n\
|
||||
\x20 --era-widths 4[,16,64] the width set the era draws from, in bytes (default 4: pinned; more lets the era draw it)"
|
||||
);
|
||||
|
|
@ -123,6 +127,7 @@ fn parse() -> Args {
|
|||
days: 0,
|
||||
program_class: None,
|
||||
era_hex: None,
|
||||
shadow_reps: 0,
|
||||
era: None,
|
||||
era_widths: vec![1],
|
||||
};
|
||||
|
|
@ -146,6 +151,7 @@ fn parse() -> Args {
|
|||
"--days" => a.days = val().parse().unwrap_or_else(|_| usage()),
|
||||
"--program-class" => a.program_class = Some(ProgramClass::parse(&val()).unwrap_or_else(|| usage())),
|
||||
"--era-hex" => a.era_hex = Some(val()),
|
||||
"--shadow-reps" => a.shadow_reps = val().parse().unwrap_or_else(|_| usage()),
|
||||
"--era" => a.era = Some(parse_era(&val()).unwrap_or_else(|| usage())),
|
||||
"--era-widths" => a.era_widths = parse_widths(&val()).unwrap_or_else(|| usage()),
|
||||
_ => usage(),
|
||||
|
|
@ -222,7 +228,7 @@ fn epoch_of_class(a: &Args, mode: DatasetMode) -> (Epoch, String) {
|
|||
let label = format!("igneum-epoch/{eh}/day/{dh}");
|
||||
let e = match a.program_class {
|
||||
Some(pc) => Epoch {
|
||||
program: Epoch::chain_program(&eb, era.as_deref(), pc, &label),
|
||||
program: Epoch::chain_program_shadow(&eb, era.as_deref(), pc, a.shadow_reps, &label),
|
||||
dataset: Epoch::chain_dataset_day(&db, pc, a.days, a.dataset_log2),
|
||||
},
|
||||
None => Epoch::from_seed_bytes_day(&eb, &db, &label, a.class, a.days, a.dataset_log2),
|
||||
|
|
@ -232,7 +238,7 @@ fn epoch_of_class(a: &Args, mode: DatasetMode) -> (Epoch, String) {
|
|||
_ => {
|
||||
let e = match a.program_class {
|
||||
Some(pc) => {
|
||||
let program = igneum_pow::generator::generate_from_seed_bytes_program_class(&a.seed, a.seed.as_bytes(), pc, era.as_deref());
|
||||
let program = igneum_pow::generator::generate_from_seed_bytes_program_class_shadow(&a.seed, a.seed.as_bytes(), pc, era.as_deref(), a.shadow_reps);
|
||||
let lc = pc.load_class();
|
||||
let shape = Shape::for_class_day(&lc, a.days);
|
||||
let log2 = if lc.growth { igneum_pow::memhard::dataset_log2_words(a.dataset_log2, a.days) } else { a.dataset_log2 };
|
||||
|
|
@ -410,7 +416,7 @@ fn show(a: &Args) {
|
|||
// the load class of --class, the era of --era composed over it
|
||||
let era_hex_bytes = a.era_hex.as_deref().map(|h| igneum_pow::bind::unhex(h).unwrap_or_else(|| usage()));
|
||||
let mut p = match a.program_class {
|
||||
Some(pc) => igneum_pow::generator::generate_from_seed_bytes_program_class(&label, &bytes, pc, era_hex_bytes.as_deref()),
|
||||
Some(pc) => igneum_pow::generator::generate_from_seed_bytes_program_class_shadow(&label, &bytes, pc, era_hex_bytes.as_deref(), a.shadow_reps),
|
||||
None => igneum_pow::generator::generate_from_seed_bytes_class(&label, &bytes, a.class),
|
||||
};
|
||||
if let (None, Some((_, eb, _))) = (a.program_class, &a.era) {
|
||||
|
|
|
|||
|
|
@ -626,6 +626,13 @@ impl Epoch {
|
|||
crate::generator::generate_from_seed_bytes_program_class(label, epoch_seed, class, era_bytes)
|
||||
}
|
||||
|
||||
/// [`Epoch::chain_program`] at a rung of the latency ladder (`docs/design/latency-ladder.md`): `shadow_reps` is
|
||||
/// the shadow pass count the chain's step gives the epoch (0 = the class's own, which is [`Epoch::chain_program`]
|
||||
/// byte for byte). The node's engine and the miner's pack export call this with the step the template names.
|
||||
pub fn chain_program_shadow(epoch_seed: &[u8], era_bytes: Option<&[u8]>, class: ProgramClass, shadow_reps: u16, label: &str) -> Program {
|
||||
crate::generator::generate_from_seed_bytes_program_class_shadow(label, epoch_seed, class, era_bytes, shadow_reps)
|
||||
}
|
||||
|
||||
/// The day's cache and dataset of [`Epoch::from_chain_seeds`], the one entry the node's engine builds a day
|
||||
/// cache through. The class is an argument because the Counter ASIC 2.0 integration gives class v3 its own item
|
||||
/// construction (the mixer multiplier) and cache size schedule (ca2-mixer); today both classes build the day of
|
||||
|
|
|
|||
|
|
@ -309,11 +309,14 @@ const refusalExample = honest.map(n => n.grepLog(/Fork choice: block .* not a si
|
|||
const summary = {
|
||||
pass: good, expect: EXPECT, case: CASE, mode: MODE, gate: GATE, window: WINDOW, joint: JOINT, split: SPLIT, watch: WATCH,
|
||||
threads: { honest_each: HT, attacker_split: AT, attacker_joint: MODE === 'third' ? AJT : MODE === 'partition' ? HT : 0 },
|
||||
keys, share_at_fork: share, fork_daa: forkDaa, fork_depth_daa_at_heal: forkDepthAtHeal,
|
||||
keys: Object.fromEntries(Object.entries(keys).map(([k, v]) => [k, short(v)])), share_at_fork: share, fork_daa: forkDaa, fork_depth_daa_at_heal: forkDepthAtHeal,
|
||||
sinks: { joint: strip(joint), split: strip(split) }, per_node: perNode, checks, failed_checks: fails, refusal_example: refusalExample,
|
||||
samples, node: IGNEUMD, miner: CPU_MINER, slot: SLOT, ports: { base: BASE, suffix: SUFFIX },
|
||||
};
|
||||
function strip(o) { const r = {}; for (const [k, v] of Object.entries(o)) r[k] = { ...v, blueWork: v.blueWork.toString() }; return r; }
|
||||
// a key in a summary is its first 8 hex and an ellipsis, never the 64 (7 October 2026: the 6 October summaries' raw keys
|
||||
// turned the no-secrets check red on every CI run of their branch; a 64-hex value next to the word key is a secret shape)
|
||||
const short = (k) => (typeof k === 'string' && k.length === 64 ? `${k.slice(0, 8)}…` : k);
|
||||
function strip(o) { const r = {}; for (const [k, v] of Object.entries(o)) r[k] = { ...v, blueWork: v.blueWork.toString(), key: short(v.key) }; return r; }
|
||||
mkdirSync(OUT.replace(/\/[^/]+$/, ''), { recursive: true });
|
||||
writeFileSync(OUT, JSON.stringify(summary, null, 2));
|
||||
log(`SUMMARY ${good ? 'PASS' : 'FAIL'} (${CASE}): side 2 held ${share.side2_bps ?? 0} bps of the blue blocks at the fork; fork depth ${forkDepthAtHeal} DAA against window ${WINDOW}; side 2 blue work ${split.side2.blueWork} against H1 ${split.h1.blueWork} at the heal; ${honest.map(n => `${n.name.toUpperCase()} ${perNode[n.name].reorged ? `reorged at ${perNode[n.name].reorg_at_s} s` : 'held'} (${perNode[n.name].refusal_lines} refusal lines, knows side 2's tip: ${perNode[n.name].knows_side2_tip})`).join('; ')}; side 2 kept its chain: ${checks.side2_kept_its_chain}${fails.length ? `; FAILED CHECK ${fails.join(', ')}` : ''}`);
|
||||
|
|
|
|||
229
infra/fast-time/key-succession.mjs
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
#!/usr/bin/env node
|
||||
// Genesis forward-compatibility (mission item 8, docs/analysis/mission/mission.md 2.8; docs/design/genesis-forward.md):
|
||||
// the fast-time gate for the W5 key succession and the sig_scheme byte, on a 3-node network with one real CPU miner
|
||||
// per node, the class-v4-signal.mjs shape. Ports 29720 and up, network igneum-devnet-972, data /tmp/igneum-fast-time-w5;
|
||||
// override-60x.json with CPU genesis bits, finality v3, the leave item, the key succession and the explicit scheme
|
||||
// forms all active from DAA 0.
|
||||
//
|
||||
// The gate, in order (every check is a chain-side fact read from the nodes, never a rate or a process name):
|
||||
// 1. the window fills: the old key (node 2's miner, label w5-old) holds blocks on every node's weight table;
|
||||
// 2. carried once: node 2's miner stops (no leave), `igneum-miner succeed` hands w5-old to w5-new, a miner starts
|
||||
// under w5-new; every node logs the succession carried by a block, every node's getFinalityWeights shows w5-new
|
||||
// inheriting (succeededFrom = the old key's hash, blocks above what w5-new mined alone) and w5-old with no weight
|
||||
// (succeededTo = the new key's hash); finality keeps locking with the new key signing;
|
||||
// 3. refused twice: w5-old to w5-third is refused on node 2 AND on node 0 (A has handed over); w5-new to w5-old is
|
||||
// refused (the successor named has handed over);
|
||||
// 4. the scheme byte: a vote stamped with scheme 1 is refused by every node with the reason (probe-scheme).
|
||||
// The known-failed case is run first: `--expect no-succession` with the succession never submitted must report FAIL
|
||||
// on the carried-once checks (the harness is trusted only after it fires on a failure).
|
||||
//
|
||||
// node infra/fast-time/key-succession.mjs [--expect succession|no-succession] [--secs 720] [--succeed-at-daa 260]
|
||||
// IGNEUMD, IGNEUM_MINER name the binaries (defaults: the genesis-forward fork worktree's target-remote/release on the
|
||||
// box, target/release on the Mac).
|
||||
|
||||
import { spawn, spawnSync } from 'node:child_process';
|
||||
import { mkdirSync, rmSync, writeFileSync, readFileSync, openSync, existsSync } from 'node:fs';
|
||||
import { Rpc } from '../../tools/finality-attacks/lib/rpc.mjs';
|
||||
|
||||
const ROOT = new URL('../../', import.meta.url).pathname;
|
||||
const FILE = `${ROOT}infra/fast-time/override-60x.json`;
|
||||
const BIN = process.env.IGNEUM_GF_BIN || (existsSync(`${ROOT}vendor/igneum-node-gf/target/release/igneumd`) ? `${ROOT}vendor/igneum-node-gf/target/release` : `${ROOT}vendor/igneum-node-gf/target-remote/release`);
|
||||
const IGNEUMD = process.env.IGNEUMD || `${BIN}/igneumd`;
|
||||
const CPU_MINER = process.env.IGNEUM_MINER || `${BIN}/igneum-miner`;
|
||||
const TMP = process.env.IGNEUM_FAST_TIME_DIR || '/tmp/igneum-fast-time-w5';
|
||||
const BASE = 29720, SUFFIX = 972;
|
||||
const NEVER = '18446744073709551615';
|
||||
const args = process.argv.slice(2);
|
||||
const flag = (name, dflt) => { const i = args.indexOf(`--${name}`); return i >= 0 ? +args[i + 1] : dflt; };
|
||||
const sflag = (name) => { const i = args.indexOf(`--${name}`); return i >= 0 ? args[i + 1] : null; };
|
||||
const GENESIS_BITS = flag('genesis-bits', 0x1f010000);
|
||||
const SECS = flag('secs', 720);
|
||||
const SUCCEED_AT = flag('succeed-at-daa', 260);
|
||||
const EXPECT = sflag('expect') || 'succession';
|
||||
if (!['succession', 'no-succession'].includes(EXPECT)) { console.error('usage: --expect succession|no-succession'); process.exit(2); }
|
||||
const started = [];
|
||||
const log = (...a) => console.log(new Date().toISOString().slice(11, 23), ...a);
|
||||
const sleep = (ms) => new Promise(r => setTimeout(r, ms));
|
||||
for (const b of [IGNEUMD, CPU_MINER]) if (!existsSync(b)) { console.error(`missing ${b}`); process.exit(2); }
|
||||
|
||||
rmSync(TMP, { recursive: true, force: true }); mkdirSync(TMP, { recursive: true });
|
||||
const baseText = readFileSync(FILE, 'utf8');
|
||||
const field = (name) => { const m = new RegExp(`"${name}":\\s*([0-9]+)`).exec(baseText); return m ? +m[1] : undefined; };
|
||||
const DAY_MS = field('pow_day_ms');
|
||||
const WINDOW = (() => { const m = /"weight_window":\s*([0-9]+)/.exec(baseText); return m ? +m[1] : 120; })();
|
||||
export function mergeOverrideText(text, fields) {
|
||||
let out = text;
|
||||
for (const k of Object.keys(fields)) out = out.replace(new RegExp(`\\s*"${k}":\\s*[^,}\\n]+,?`), '');
|
||||
const extra = Object.entries(fields).map(([k, v]) => `"${k}": ${typeof v === 'string' && !/^\d+$/.test(v) ? JSON.stringify(v) : v}`).join(', ');
|
||||
return out.replace(/,?\s*}\s*$/, `,\n ${extra}\n}\n`);
|
||||
}
|
||||
const override = `${TMP}/override.json`;
|
||||
writeFileSync(override, mergeOverrideText(baseText, {
|
||||
genesis_bits: GENESIS_BITS, skip_proof_of_work: false, finality_v3_activation_daa: '0', finality_leave_activation_daa: '0',
|
||||
finality_succession_activation_daa: '0', sig_scheme_activation_daa: '0', sig_scheme: '0', latency_ladder_activation_daa: NEVER,
|
||||
}));
|
||||
log(`expect ${EXPECT}; weight window ${WINDOW} DAA; the succession at DAA ${SUCCEED_AT}; run ${SECS} s`);
|
||||
|
||||
class Node {
|
||||
constructor(i, connect = []) {
|
||||
this.i = i; this.grpcPort = BASE + i * 10; this.p2pPort = BASE + i * 10 + 1; this.jsonPort = BASE + i * 10 + 2;
|
||||
this.connect = connect; this.dir = `${TMP}/n${i}`; this.logFile = `${this.dir}/node.log`;
|
||||
}
|
||||
get grpc() { return `grpc://127.0.0.1:${this.grpcPort}`; }
|
||||
async start() {
|
||||
mkdirSync(this.dir, { recursive: true });
|
||||
const a = ['--devnet', `--devnet-suffix=${SUFFIX}`, '--nodnsseed', '--disable-upnp', '--nologfiles', '--enable-unsynced-mining', '--utxoindex',
|
||||
`--appdir=${this.dir}`, `--rpclisten=127.0.0.1:${this.grpcPort}`, `--rpclisten-json=127.0.0.1:${this.jsonPort}`,
|
||||
`--listen=127.0.0.1:${this.p2pPort}`, `--override-params-file=${override}`, '--loglevel=info', '--yes'];
|
||||
if (this.connect.length) a.push(`--connect=${this.connect.join(',')}`); else a.push('--outpeers=0');
|
||||
const out = openSync(this.logFile, 'a');
|
||||
this.proc = spawn(IGNEUMD, a, { stdio: ['ignore', out, out] });
|
||||
started.push(this.proc);
|
||||
await sleep(1500);
|
||||
this.rpc = new Rpc(`ws://127.0.0.1:${this.jsonPort}`);
|
||||
if (!(await this.rpc.connect())) throw new Error(`n${this.i}: rpc did not open`);
|
||||
log(`n${this.i} up pid ${this.proc.pid} json ${this.jsonPort} p2p ${this.p2pPort}`);
|
||||
return this;
|
||||
}
|
||||
grepLog(re) { try { return readFileSync(this.logFile, 'utf8').split('\n').filter(l => re.test(l)); } catch { return []; } }
|
||||
async weights() { try { return await this.rpc.call('getFinalityWeights'); } catch (e) { return null; } }
|
||||
async daa() { try { return +(await this.rpc.call('getBlockDagInfo')).virtualDaaScore; } catch { return null; } }
|
||||
}
|
||||
function miner(argv, name, env = {}) {
|
||||
const out = openSync(`${TMP}/${name}.log`, 'a');
|
||||
const p = spawn(CPU_MINER, argv, { stdio: ['ignore', out, out], env: { ...process.env, IGNEUM_POW_DAY_MS: String(DAY_MS), ...env } });
|
||||
started.push(p);
|
||||
return p;
|
||||
}
|
||||
function minerArgs(node, label, noLeave) {
|
||||
const a = ['mine', node.grpc, '1', String(SECS), label, '--engine', 'igneum-pow', '--payout-label', label, '--status-secs', '30'];
|
||||
if (noLeave) a.push('--no-leave');
|
||||
return a;
|
||||
}
|
||||
async function stopAll() {
|
||||
for (const p of started.reverse()) { try { p.kill('SIGINT'); } catch { } }
|
||||
await sleep(1500);
|
||||
for (const p of started) { try { p.kill('SIGKILL'); } catch { } }
|
||||
}
|
||||
process.on('SIGINT', async () => { await stopAll(); process.exit(130); });
|
||||
process.on('unhandledRejection', async (e) => { log(`FAILED: ${e?.stack || e}`); await stopAll(); process.exit(3); });
|
||||
const minerLog = (name) => { try { return readFileSync(`${TMP}/${name}.log`, 'utf8').split('\n'); } catch { return []; } };
|
||||
const keyHash = (label) => (spawnSync(CPU_MINER, ['key-hash', label], { encoding: 'utf8' }).stdout || '').trim();
|
||||
const CARRIED_LINE = /hands its weight and its forfeit term to .*(carried by|now carried by)/;
|
||||
const LOCK_LINE = /Finality: checkpoint (\d+) LOCKED/;
|
||||
|
||||
const t0 = Date.now();
|
||||
const since = () => ((Date.now() - t0) / 1000).toFixed(1);
|
||||
const n0 = await new Node(0).start();
|
||||
const n1 = await new Node(1, [`127.0.0.1:${n0.p2pPort}`]).start();
|
||||
const n2 = await new Node(2, [`127.0.0.1:${n0.p2pPort}`]).start();
|
||||
const nodes = [n0, n1, n2];
|
||||
for (const n of nodes) log(`n${n.i}: ${n.grepLog(/Key succession \(W5\) from the override file/).map(l => l.replace(/^.*?(Key succession)/, '$1'))[0] || '(no W5 line)'} | ${n.grepLog(/Signature scheme byte from the override file/).map(l => l.replace(/^.*?(Signature scheme)/, '$1'))[0] || '(no scheme line)'}`);
|
||||
log(`n0 digest: ${n0.grepLog(/Consensus params digest/).map(l => l.replace(/^.*?digest: /, '').slice(0, 16)).join(' ')}`);
|
||||
const OLD = 'w5-old', NEW = 'w5-new', THIRD = 'w5-third', PROBE = 'w5-probe';
|
||||
const oldHash = keyHash(OLD), newHash = keyHash(NEW);
|
||||
log(`old key ${oldHash.slice(0, 16)} (${OLD}), successor ${newHash.slice(0, 16)} (${NEW})`);
|
||||
miner(minerArgs(n0, 'w5-a0', false), 'cpu0');
|
||||
miner(minerArgs(n1, 'w5-b1', false), 'cpu1');
|
||||
let cpu2 = miner(minerArgs(n2, OLD, true), 'cpu2');
|
||||
|
||||
const samples = [];
|
||||
let phase = 'fill', oldBlocksBefore = null, succeedOutcome = null, succeededAtDaa = null, newStartedAt = null, carriedSeenAt = null;
|
||||
let refusals = [], probes = [], locksBefore = null, locksAfter = null, lastReport = 0;
|
||||
const run = (argv) => { const r = spawnSync(CPU_MINER, argv, { encoding: 'utf8' }); return { code: r.status, out: (r.stdout || '') + (r.stderr || '') }; };
|
||||
while (Date.now() - t0 < SECS * 1000) {
|
||||
await sleep(1000);
|
||||
const daa = await n0.daa();
|
||||
if (daa == null) continue;
|
||||
if (Date.now() - lastReport > 15000) {
|
||||
lastReport = Date.now();
|
||||
const w = await Promise.all(nodes.map(n => n.weights()));
|
||||
const rows = w.map(r => r ? `${r.totalWeight}/${r.voters}` : '?');
|
||||
const locks = nodes.map(n => n.grepLog(LOCK_LINE).length);
|
||||
log(`t=${since()} s daa ${daa} phase ${phase} total/voters per node ${rows.join(' ')} locks ${locks.join(' ')}`);
|
||||
samples.push({ t: +since(), daa, phase, weights: rows, locks });
|
||||
}
|
||||
if (phase === 'fill' && daa >= SUCCEED_AT) {
|
||||
const w = await n0.weights();
|
||||
const row = w?.keys?.find(k => k.keyHash === oldHash);
|
||||
oldBlocksBefore = row ? +row.blocks : 0;
|
||||
locksBefore = n0.grepLog(LOCK_LINE).length;
|
||||
log(`window filled: ${OLD} holds ${oldBlocksBefore} blocks on n0 at daa ${daa}; ${locksBefore} locks on n0`);
|
||||
try { cpu2.kill('SIGINT'); } catch { }
|
||||
await sleep(2500);
|
||||
if (EXPECT === 'succession') {
|
||||
succeedOutcome = run(['succeed', n2.grpc, OLD, NEW]);
|
||||
log(`succeed ${OLD} -> ${NEW} on n2: exit ${succeedOutcome.code}: ${succeedOutcome.out.trim().split('\n').pop()}`);
|
||||
} else {
|
||||
log(`known-failed case: no succession submitted`);
|
||||
}
|
||||
succeededAtDaa = daa;
|
||||
newStartedAt = daa;
|
||||
cpu2 = miner(minerArgs(n2, NEW, false), 'cpu2b');
|
||||
phase = 'carry';
|
||||
continue;
|
||||
}
|
||||
if (phase === 'carry') {
|
||||
const carried = nodes.map(n => n.grepLog(CARRIED_LINE).length > 0);
|
||||
if (carried.every(Boolean) && carriedSeenAt == null) { carriedSeenAt = daa; log(`carried: every node logs the succession carried by a block at daa ${daa}`); }
|
||||
// the fold: every node's report shows the successor inheriting and the old key handed over
|
||||
const w = await Promise.all(nodes.map(n => n.weights()));
|
||||
const folded = w.every(r => r && r.keys.some(k => k.keyHash === newHash && k.succeededFrom === oldHash) && r.keys.some(k => k.keyHash === oldHash && k.succeededTo === newHash));
|
||||
if (folded || (EXPECT === 'no-succession' && daa >= succeededAtDaa + 2 * WINDOW)) {
|
||||
const minedAlone = minerLog('cpu2b').filter(l => /ACCEPTED block/.test(l)).length;
|
||||
const rows = w.map(r => ({ new: r?.keys?.find(k => k.keyHash === newHash) || null, old: r?.keys?.find(k => k.keyHash === oldHash) || null }));
|
||||
log(`fold at daa ${daa}: ${NEW} mined ${minedAlone} blocks alone; per node new/old blocks ${rows.map(r => `${r.new?.blocks ?? '-'}/${r.old?.blocks ?? '-'}`).join(' ')}`);
|
||||
// refused twice, on n2 and on n0 (every node); and the successor named has handed over
|
||||
refusals = [
|
||||
{ what: `${OLD} -> ${THIRD} on n2`, ...run(['succeed', n2.grpc, OLD, THIRD]) },
|
||||
{ what: `${OLD} -> ${THIRD} on n0`, ...run(['succeed', n0.grpc, OLD, THIRD]) },
|
||||
{ what: `${NEW} -> ${OLD} on n1`, ...run(['succeed', n1.grpc, NEW, OLD]) },
|
||||
];
|
||||
for (const r of refusals) log(`${r.what}: exit ${r.code}: ${r.out.trim().split('\n').pop()}`);
|
||||
probes = nodes.map(n => ({ node: n.i, ...run(['probe-scheme', n.grpc, PROBE, '1']) }));
|
||||
for (const p of probes) log(`probe scheme 1 on n${p.node}: exit ${p.code}: ${p.out.trim().split('\n').pop()}`);
|
||||
phase = 'after';
|
||||
locksAfter = n0.grepLog(LOCK_LINE).length;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (phase === 'after') {
|
||||
// locks keep coming with the new key signing: two windows after the fold is enough to see it
|
||||
const locksNow = n0.grepLog(LOCK_LINE).length;
|
||||
if (locksNow > locksAfter + 2) { log(`locks after the fold: ${locksNow} on n0 (${locksAfter} at the fold)`); break; }
|
||||
}
|
||||
}
|
||||
await sleep(1500);
|
||||
const w = await Promise.all(nodes.map(n => n.weights()));
|
||||
const dag = await Promise.all(nodes.map(async n => { try { return await n.rpc.call('getBlockDagInfo'); } catch (e) { return { error: e.message }; } }));
|
||||
const minedAlone = minerLog('cpu2b').filter(l => /ACCEPTED block/.test(l)).length;
|
||||
const rows = w.map(r => ({ new: r?.keys?.find(k => k.keyHash === newHash) || null, old: r?.keys?.find(k => k.keyHash === oldHash) || null }));
|
||||
const locks = nodes.map(n => n.grepLog(LOCK_LINE).length);
|
||||
const rejectedNode = nodes.map(n => n.grepLog(/PoW rejected|Rejected block|rejected block/i).length);
|
||||
const checks = {
|
||||
window_filled_before_the_succession: oldBlocksBefore != null && oldBlocksBefore >= 5,
|
||||
succession_accepted_on_submit: EXPECT === 'succession' ? succeedOutcome?.code === 0 && /SUCCEED old=/.test(succeedOutcome.out) : succeedOutcome == null,
|
||||
carried_once_on_every_node: nodes.every(n => n.grepLog(CARRIED_LINE).length >= 1),
|
||||
successor_inherits_on_every_node: rows.every(r => r.new && r.new.succeededFrom === oldHash && +r.new.blocks > minedAlone),
|
||||
old_key_handed_over_on_every_node: rows.every(r => r.old && r.old.succeededTo === newHash && +r.old.blocks === 0 && r.old.voter === false),
|
||||
nodes_agree_on_the_successor_weight: new Set(rows.map(r => String(r.new?.blocks))).size === 1,
|
||||
refused_old_again_on_n2: refusals[0]?.code === 3 && /already handed/.test(refusals[0].out),
|
||||
refused_old_again_on_n0: refusals[1]?.code === 3 && /already handed/.test(refusals[1].out),
|
||||
refused_successor_that_handed_over: refusals[2]?.code === 3 && /has itself handed/.test(refusals[2].out),
|
||||
scheme_1_refused_by_every_node: probes.length === 3 && probes.every(p => p.code === 0 && /SCHEME 1 REFUSED/.test(p.out) && /active scheme is 0/.test(p.out)),
|
||||
locks_continue_after_the_fold: locksAfter != null && locks[0] > locksAfter + 2,
|
||||
zero_rejected_by_nodes: rejectedNode.every(c => c === 0),
|
||||
sinks_agree: new Set(dag.map(d => String(d.sink))).size === 1,
|
||||
};
|
||||
const pass = Object.values(checks).every(Boolean);
|
||||
const summary = {
|
||||
expect: EXPECT, pass, checks, old_key: oldHash, new_key: newHash, old_blocks_before: oldBlocksBefore, succeeded_at_daa: succeededAtDaa,
|
||||
carried_seen_at_daa: carriedSeenAt, new_mined_alone: minedAlone, rows, locks, locks_at_fold: locksAfter, refusals: refusals.map(r => ({ what: r.what, code: r.code, line: r.out.trim().split('\n').pop() })),
|
||||
probes: probes.map(p => ({ node: p.node, code: p.code, line: p.out.trim().split('\n').pop() })), samples, wall_s: +since(),
|
||||
binaries: { igneumd: IGNEUMD, miner: CPU_MINER },
|
||||
};
|
||||
// the summary carries key hashes as their first 16 hex characters (tools/ci/no-secrets-check.sh reads committed summaries)
|
||||
writeFileSync(`${TMP}/summary.json`, JSON.stringify(summary, null, 2).replace(/\b([0-9a-f]{16})[0-9a-f]{48}\b/g, '$1'));
|
||||
log(`SUMMARY ${pass ? 'PASS' : 'FAIL'} (${EXPECT}): ${Object.entries(checks).filter(([, v]) => !v).map(([k]) => `FAILED CHECK ${k}`).join('; ') || 'every check holds'}; ${TMP}/summary.json`);
|
||||
await stopAll();
|
||||
process.exit(pass ? 0 : 1);
|
||||
|
|
@ -67,6 +67,27 @@
|
|||
"proving_v1_unproven_daa": 10,
|
||||
"proving_v1_aggregator_share_bps": 1000,
|
||||
"fees_v1_activation_daa": 0,
|
||||
"difficulty_v3_activation_daa": 18446744073709551615,
|
||||
"finality_daa_rule_activation_daa": 18446744073709551615,
|
||||
"fork_gate_activation_daa": 18446744073709551615,
|
||||
"fork_gate_window_daa": 600,
|
||||
"vote_or_burn_activation_daa": 18446744073709551615,
|
||||
"vote_burn_bps": 2000,
|
||||
"signing_bonus_activation_daa": 18446744073709551615,
|
||||
"signing_bonus_bps": 1000,
|
||||
"finality_leave_activation_daa": 18446744073709551615,
|
||||
"latency_ladder": [{"reps": 27, "admissible": true}, {"reps": 35, "admissible": true}, {"reps": 53, "admissible": true}, {"reps": 88, "admissible": false}, {"reps": 173, "admissible": false}, {"reps": 267, "admissible": false}],
|
||||
"latency_ladder_activation_daa": 18446744073709551615,
|
||||
"latency_ladder_window_daa": 120,
|
||||
"exec_restart_state_root": "",
|
||||
"emission": {"launch_rate": "3168808781", "ramp_seconds": 2592000, "ramp_start_percent": 10, "step_seconds": 63115200, "step_decay_q32": 2147483648, "tail": {"kind": "cap"}},
|
||||
"proving_consensus_verify_daa": 18446744073709551615,
|
||||
"proving_shard_program_id": "",
|
||||
"proving_aggregator_id": "",
|
||||
"sig_scheme": 0,
|
||||
"sig_scheme_activation_daa": 18446744073709551615,
|
||||
"finality_succession_activation_daa": 18446744073709551615,
|
||||
"latency_ladder_cache_rung": {"mib": 512, "admissible": false},
|
||||
"fees": {"pgas": {"version": 1, "cycles_per_pgas": 1000, "intrinsic_pgas_per_tx": 300, "modexp_base": 10, "modexp_per_byte_numer": 1, "modexp_per_byte_denom": 10}, "block_proving_gas_limit": 120000, "shard_proving_gas_budget": 30000, "min_execution_base_fee_wei": 100000000000, "min_proving_base_fee_wei": 10000000000000, "initial_execution_base_fee_wei": 100000000000, "initial_proving_base_fee_wei": 10000000000000, "base_fee_change_denominator": 8},
|
||||
"peer_directory_activation_daa": null
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,6 +65,10 @@ Wake (`api/wake.mjs`, 0.3.6, 5 October 2026): `GET /wake?since=<stamp>` is publi
|
|||
|
||||
An unknown hostname that registers appears in the feed with a "name this machine" box, or `node tools/relay.mjs name <hostname> PC2`. PC1 is DESKTOP-KMCV30N.
|
||||
|
||||
## The job-channel ping (MF-11, 7 October 2026)
|
||||
|
||||
PC 2 lost power at 10:46Z on 7 October 2026 and nothing said so until a person read the intake. From 0.3.21 every app wake request carries `machine=<id8>&v=<version>&job=<last job id>`; `/wake` records one row per machine in `relay_wake_seen` before it holds (`relay/lib/wake.mjs`: `recordSeen`, `seenList`, `pingState`, `PING_SILENT_S` = 900 s); the console's Machines tab reads it as "job channel polled N ago, last job X" and, after 15 minutes without a poll, "job channel silent since <time>, last job X" in red, whatever the uploads say (`api/console.mjs` `poll`, `ui.html`). No secret travels: id8 is what the console already shows. Test: `node --test relay/test/wake.test.mjs`.
|
||||
|
||||
## Deploy
|
||||
|
||||
```
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
// POST sync {items:[...]} bulk upsert by key
|
||||
import { neon, authed, readJson, str, iso } from '../lib/relay.mjs';
|
||||
import { kv, kvNum, lastMatch, FAULT, parseLabel, parseMinerTail, parseHeader, parseAppTail, STALE_S, markStale } from '../lib/parse.mjs';
|
||||
import { seenList, pingState, PING_SILENT_S } from '../lib/wake.mjs';
|
||||
import { parseRecords, aggregate } from '../lib/ember.mjs';
|
||||
|
||||
const json = (res, status, obj) => { res.status(status).setHeader('Content-Type', 'application/json; charset=utf-8'); res.end(JSON.stringify(obj)); };
|
||||
|
|
@ -117,6 +118,10 @@ async function machines(sql) {
|
|||
}
|
||||
}
|
||||
await otaMemo(sql, groups);
|
||||
// the job channel's ping (MF-11, 7 October 2026): every 0.3.21 app names itself on its wake long-poll; a machine whose
|
||||
// last poll is over PING_SILENT_S old reads "job channel silent since <time>, last job <name>" on its card
|
||||
let pings = new Map();
|
||||
try { pings = new Map((await seenList(sql)).map(p => [p.machine, p])); } catch (e) { /* the cards render without it */ }
|
||||
const now = Date.now();
|
||||
const out = [...groups.values()].map(g => {
|
||||
const id8 = g.id.startsWith('legacy:') ? null : g.id;
|
||||
|
|
@ -127,6 +132,7 @@ async function machines(sql) {
|
|||
name: id8 ? (NAMES[id8] || (g.platform === 'mac' ? 'Mac' : 'PC ' + id8)) : g.id.slice(7),
|
||||
host: [...g.hosts][0] || null, legacy: !id8,
|
||||
last_seen: g.last_seen, silent_s, silent: silent_s === null || silent_s > SILENT_S,
|
||||
poll: id8 ? pingState(pings.get(id8), now) : null,
|
||||
stopped: (silent_s === null || silent_s > SILENT_S) && g.app && g.app.stopped ? g.app.stopped : null,
|
||||
app_version: (g.app && g.app.version) || (g.header && g.header.version) || null,
|
||||
app: g.app ? { at: g.app.at, status: g.app.status || null, ota: g.app.ota || null, power_cap: g.app.power_cap || null, jobs_file: g.app.jobs_file || null, jobs: g.app.jobs || [] } : null,
|
||||
|
|
@ -149,9 +155,9 @@ async function machines(sql) {
|
|||
// several Mac installs (test runs): the newest is "Mac", the others keep their id
|
||||
let macSeen = false;
|
||||
for (const m of out) if (m.platform === 'mac' && m.name === 'Mac') { if (macSeen) m.name = `Mac ${m.id8}`; macSeen = true; }
|
||||
for (const n of ['Mac', 'PC 1', 'PC 2', "Sam's Mac"]) if (!out.some(m => m.name === n)) out.push({ id: n, id8: Object.keys(NAMES).find(k => NAMES[k] === n) || null, platform: n.endsWith('Mac') ? 'mac' : 'win', name: n, host: null, legacy: false, last_seen: null, silent_s: null, silent: true, app_version: null, app: null, node: {}, cards: [], hash_total: 0, accepted_total: 0, faults: 0, telemetry: [], events: [], gpus: [], gpus_at: null, hotplug: [], labels: [], runs: [], never: true });
|
||||
for (const n of ['Mac', 'PC 1', 'PC 2', "Sam's Mac"]) if (!out.some(m => m.name === n)) { const id8 = Object.keys(NAMES).find(k => NAMES[k] === n) || null; out.push({ id: n, id8, platform: n.endsWith('Mac') ? 'mac' : 'win', name: n, host: null, legacy: false, last_seen: null, silent_s: null, silent: true, poll: id8 ? pingState(pings.get(id8), now) : null, app_version: null, app: null, node: {}, cards: [], hash_total: 0, accepted_total: 0, faults: 0, telemetry: [], events: [], gpus: [], gpus_at: null, hotplug: [], labels: [], runs: [], never: true }); }
|
||||
out.sort((a, b) => order(a) - order(b) || (b.last_seen || '').localeCompare(a.last_seen || ''));
|
||||
return { machines: out.filter(m => NAMED.has(m.name) || (m.silent_s !== null && m.silent_s < HIDE_AFTER_S)), silent_after_s: SILENT_S, hide_after_s: HIDE_AFTER_S };
|
||||
return { machines: out.filter(m => NAMED.has(m.name) || (m.silent_s !== null && m.silent_s < HIDE_AFTER_S)), silent_after_s: SILENT_S, hide_after_s: HIDE_AFTER_S, poll_silent_after_s: PING_SILENT_S };
|
||||
}
|
||||
|
||||
// ---- jobs ---------------------------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -5,6 +5,10 @@
|
|||
// GET wake?since=<stamp>[&hold=45] holds up to 45 s; answers as soon as the stored stamp differs from `since`,
|
||||
// else the unchanged stamp at the deadline; without `since` the current stamp
|
||||
// at once. Reply: {ok, stamp, at, added, changed, held_ms}.
|
||||
// [&machine=<id8>&v=<version>&job=<id>] the ping (MF-11, 0.3.21): the app names itself on every request and the
|
||||
// relay keeps one row per machine (relay_wake_seen: last poll, version, last job);
|
||||
// the console shows "silent since <time>, last job <name>" after PING_SILENT_S
|
||||
// without a poll. No secret: id8 is what the console already shows.
|
||||
// POST wake {stamp, added?} records the stamp (publish-jobs.sh, after a verified deploy). Reply:
|
||||
// {ok, stamp, at, added}.
|
||||
// Storage: table relay_wake, one row per stamp, the newest row is the stamp; the first POST creates the table.
|
||||
|
|
@ -18,6 +22,8 @@ export const HOLDS_MAX = 64; // held requests per instance; above it
|
|||
const EMPTY = { stamp: '', at: null, added: [] };
|
||||
|
||||
export const validStamp = s => typeof s === 'string' && s.length > 0 && s.length <= STAMP_MAX && /^[\w.:-]+$/.test(s);
|
||||
export const validMachine = s => typeof s === 'string' && /^[0-9a-f]{8}$/.test(s);
|
||||
export const PING_SILENT_S = 900; // 15 minutes without a poll from a machine: its job channel is dead
|
||||
|
||||
const isoOf = v => { if (!v) return null; const d = new Date(String(v).replace(' ', 'T').replace(/([+-]\d\d)$/, '$1:00')); return isNaN(d) ? String(v) : d.toISOString(); };
|
||||
const clip = (v, max) => (v === undefined || v === null ? '' : String(v)).slice(0, max);
|
||||
|
|
@ -70,13 +76,53 @@ export async function latest(sql) {
|
|||
}
|
||||
}
|
||||
|
||||
/** The ping table: one row per machine, the last poll, the app version and the last job it named. */
|
||||
export async function ensureSeenTable(sql, state = {}) {
|
||||
if (state.seenTable) return;
|
||||
await sql(`CREATE TABLE IF NOT EXISTS relay_wake_seen (machine text PRIMARY KEY, last_seen timestamptz NOT NULL DEFAULT now(), version text NOT NULL DEFAULT '', last_job text NOT NULL DEFAULT '')`);
|
||||
state.seenTable = true;
|
||||
}
|
||||
|
||||
/** Records one poll from a machine (the GET's machine, v and job); invalid or absent ids record nothing. */
|
||||
export async function recordSeen(sql, { machine, version, job }, state = {}) {
|
||||
if (!validMachine(machine)) return false;
|
||||
await ensureSeenTable(sql, state);
|
||||
await sql(`INSERT INTO relay_wake_seen (machine, last_seen, version, last_job) VALUES ($1, now(), $2, $3)
|
||||
ON CONFLICT (machine) DO UPDATE SET last_seen = now(), version = EXCLUDED.version, last_job = CASE WHEN EXCLUDED.last_job = '' THEN relay_wake_seen.last_job ELSE EXCLUDED.last_job END`,
|
||||
[machine, clip(version, 32), clip(job, 80)]);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Every machine's last poll: [{machine, last_seen, version, last_job}]; [] before the first ping. */
|
||||
export async function seenList(sql) {
|
||||
try {
|
||||
const rows = await sql(`SELECT machine, last_seen, version, last_job FROM relay_wake_seen ORDER BY machine`);
|
||||
return rows.map(r => ({ machine: String(r.machine), last_seen: isoOf(r.last_seen), version: String(r.version || ''), last_job: String(r.last_job || '') }));
|
||||
} catch (e) {
|
||||
if (/relay_wake_seen/.test(String(e.message)) && /does not exist/.test(String(e.message))) return [];
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* What the console says about a machine's job channel from its last ping: {silent, silent_s, since, last_job, version,
|
||||
* never}. Silent after PING_SILENT_S without a poll; `since` is the last poll's time (what the card prints after
|
||||
* "silent since"); never = no ping on record.
|
||||
*/
|
||||
export function pingState(seen, now = Date.now(), silentAfterS = PING_SILENT_S) {
|
||||
if (!seen || !seen.last_seen) return { silent: true, never: true, silent_s: null, since: null, last_job: '', version: '' };
|
||||
const t = Date.parse(seen.last_seen);
|
||||
const silent_s = isNaN(t) ? null : Math.max(0, Math.round((now - t) / 1000));
|
||||
return { silent: silent_s === null || silent_s > silentAfterS, never: false, silent_s, since: isNaN(t) ? seen.last_seen : new Date(t).toISOString(), last_job: seen.last_job || '', version: seen.version || '' };
|
||||
}
|
||||
|
||||
export const ipOf = req => String(req.headers['x-forwarded-for'] || (req.socket && req.socket.remoteAddress) || '').split(',')[0].trim();
|
||||
|
||||
/**
|
||||
* The handler with its dependencies injected: sql (Neon), authed (the relay's check), readJson, json (the reply
|
||||
* writer), limiter, holds (a counter shared by the instance), now and sleep (the test's fake clock).
|
||||
*/
|
||||
export function makeHandler({ sql, authed, readJson, json, limiter = new RateLimit(), holds = { n: 0 }, now = Date.now, sleep }) {
|
||||
export function makeHandler({ sql, authed, readJson, json, limiter = new RateLimit(), holds = { n: 0 }, now = Date.now, sleep, state = {} }) {
|
||||
return async function handler(req, res) {
|
||||
res.setHeader('Cache-Control', 'no-store');
|
||||
const q = req.query || {};
|
||||
|
|
@ -84,6 +130,8 @@ export function makeHandler({ sql, authed, readJson, json, limiter = new RateLim
|
|||
if (req.method === 'GET') {
|
||||
const wait = limiter.take(ipOf(req));
|
||||
if (wait !== null) { res.setHeader('Retry-After', String(wait)); return json(res, 429, { ok: false, error: 'rate limited', retry_after: wait }); }
|
||||
// the ping lands before the hold, so a machine is "seen" the moment it asks, not 45 s later
|
||||
if (q.machine !== undefined) { try { await recordSeen(sql, { machine: clip(q.machine, 16), version: q.v, job: q.job }, state); } catch (e) { /* the wake still answers */ } }
|
||||
const since = clip(q.since, STAMP_MAX * 2);
|
||||
const asked = q.hold === undefined ? HOLD_MS_MAX : (Number(q.hold) || 0) * 1000;
|
||||
const holdMs = holds.n >= HOLDS_MAX ? 0 : Math.min(HOLD_MS_MAX, asked);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// node --test relay/test/wake.test.mjs (no dependencies, no database: a fake sql, a fake clock, a fake sleep)
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { waitForChange, RateLimit, validStamp, makeHandler, HOLD_MS_MAX, HOLDS_MAX } from '../lib/wake.mjs';
|
||||
import { waitForChange, RateLimit, validStamp, makeHandler, HOLD_MS_MAX, HOLDS_MAX, recordSeen, seenList, pingState, PING_SILENT_S, validMachine } from '../lib/wake.mjs';
|
||||
|
||||
// a clock that only moves when something sleeps on it
|
||||
function clock(start = 1_000_000) {
|
||||
|
|
@ -12,10 +12,21 @@ function clock(start = 1_000_000) {
|
|||
// the smallest Neon stand-in: one table relay_wake, newest row first, no table until the first CREATE
|
||||
function fakeDb() {
|
||||
const rows = [];
|
||||
const seen = [];
|
||||
let created = false;
|
||||
let seenCreated = false;
|
||||
let seq = 0;
|
||||
const nowIso = () => '2026-10-07T13:00:00.000Z';
|
||||
const sql = async (query, params = []) => {
|
||||
if (/CREATE TABLE/.test(query)) { created = true; return []; }
|
||||
if (/CREATE TABLE IF NOT EXISTS relay_wake /.test(query)) { created = true; return []; }
|
||||
if (/CREATE TABLE IF NOT EXISTS relay_wake_seen/.test(query)) { seenCreated = true; return []; }
|
||||
if (/INSERT INTO relay_wake_seen/.test(query)) {
|
||||
const [machine, version, last_job] = params;
|
||||
const hit = seen.find(r => r.machine === machine);
|
||||
if (hit) { hit.last_seen = nowIso(); hit.version = version; if (last_job) hit.last_job = last_job; } else seen.push({ machine, last_seen: nowIso(), version, last_job });
|
||||
return [];
|
||||
}
|
||||
if (/SELECT machine, last_seen, version, last_job FROM relay_wake_seen/.test(query)) { if (!seenCreated) throw new Error('relation "relay_wake_seen" does not exist'); return seen.map(r => ({ ...r })); }
|
||||
if (!created) throw new Error('relation "relay_wake" does not exist');
|
||||
if (/INSERT INTO relay_wake/.test(query)) {
|
||||
const [stamp, meta] = params;
|
||||
|
|
@ -28,7 +39,7 @@ function fakeDb() {
|
|||
if (/SELECT stamp, at, meta FROM relay_wake/.test(query)) { const r = rows[rows.length - 1]; return r ? [r] : []; }
|
||||
throw new Error('unexpected query ' + query);
|
||||
};
|
||||
return { sql, rows, set: (stamp, added = []) => { rows.push({ id: ++seq, stamp, at: '2026-10-05 12:00:00+00', meta: { added } }); created = true; } };
|
||||
return { sql, rows, seen, set: (stamp, added = []) => { rows.push({ id: ++seq, stamp, at: '2026-10-05 12:00:00+00', meta: { added } }); created = true; } };
|
||||
}
|
||||
|
||||
function res() {
|
||||
|
|
@ -150,3 +161,40 @@ test('handler: a database error is a 500 with its message, not a hang', async ()
|
|||
const r = res(); await h(req('GET', { since: 'S1' }), r);
|
||||
assert.deepEqual([reply(r).code, reply(r).error], [500, 'connection refused']);
|
||||
});
|
||||
|
||||
test('MF-11: a wake request that names its machine is recorded as a ping with the version and the last job; a bad id records nothing', async () => {
|
||||
const db = fakeDb(); const c = clock();
|
||||
db.set('2026-10-07T13:00:00Z.aaaa');
|
||||
const h = makeHandler({ sql: db.sql, authed: () => 'token', readJson: async () => ({}), json, limiter: new RateLimit({ now: c.now }), now: c.now, sleep: c.sleep });
|
||||
let r = res();
|
||||
await h(req('GET', { since: '2026-10-07T13:00:00Z.aaaa', hold: '0', machine: '1ccfe586', v: '0.3.21', job: 'update-now-0319-1ccfe586' }), r);
|
||||
assert.equal(reply(r).code, 200);
|
||||
assert.deepEqual(db.seen, [{ machine: '1ccfe586', last_seen: '2026-10-07T13:00:00.000Z', version: '0.3.21', last_job: 'update-now-0319-1ccfe586' }]);
|
||||
// a later poll without a job keeps the last job; a bad machine id is ignored
|
||||
r = res(); await h(req('GET', { hold: '0', machine: '1ccfe586', v: '0.3.21' }), r);
|
||||
assert.equal(db.seen[0].last_job, 'update-now-0319-1ccfe586');
|
||||
r = res(); await h(req('GET', { hold: '0', machine: 'DROP TABLE', v: 'x' }), r);
|
||||
assert.equal(reply(r).code, 200);
|
||||
assert.equal(db.seen.length, 1);
|
||||
assert.equal(await recordSeen(db.sql, { machine: 'zz', version: '', job: '' }), false);
|
||||
assert.equal(validMachine('1ccfe586'), true);
|
||||
assert.equal(validMachine('1CCFE586'), false);
|
||||
const list = await seenList(db.sql);
|
||||
assert.equal(list[0].machine, '1ccfe586');
|
||||
assert.equal(list[0].last_seen, '2026-10-07T13:00:00.000Z');
|
||||
// before the first ping the list is empty rather than an error
|
||||
assert.deepEqual(await seenList(fakeDb().sql), []);
|
||||
});
|
||||
|
||||
test('MF-11: the console reads a machine as silent after 15 minutes without a poll, with the time of the last one and the last job', () => {
|
||||
const seen = { machine: '1ccfe586', last_seen: '2026-10-07T10:46:00.000Z', version: '0.3.19', last_job: 'update-now-0319-1ccfe586' };
|
||||
const at = t => Date.parse(t);
|
||||
assert.equal(PING_SILENT_S, 900);
|
||||
const fresh = pingState(seen, at('2026-10-07T10:50:00Z'));
|
||||
assert.equal(fresh.silent, false);
|
||||
assert.equal(fresh.silent_s, 240);
|
||||
const quiet = pingState(seen, at('2026-10-07T11:01:01Z'));
|
||||
assert.deepEqual(quiet, { silent: true, never: false, silent_s: 901, since: '2026-10-07T10:46:00.000Z', last_job: 'update-now-0319-1ccfe586', version: '0.3.19' });
|
||||
assert.equal(pingState(seen, at('2026-10-07T11:00:59Z')).silent, false, 'exactly inside the window');
|
||||
assert.deepEqual(pingState(null, at('2026-10-07T11:00:00Z')), { silent: true, never: true, silent_s: null, since: null, last_job: '', version: '' });
|
||||
});
|
||||
|
|
|
|||
|
|
@ -268,11 +268,16 @@ input[type=text]{width:100%}
|
|||
function machineCard(mc) {
|
||||
const n = mc.node || {};
|
||||
const silentTxt = mc.never ? 'never seen' : mc.stopped ? `stopped (${esc(mc.stopped.reason)}) ${ago(mc.stopped.at)} ago` : (mc.silent ? `silent ${ago(mc.last_seen)}` : `seen ${ago(mc.last_seen)} ago`);
|
||||
// the job channel's ping (MF-11): a dead app polls nothing, and this line says so after 15 minutes, with the last job it ran
|
||||
const p = mc.poll;
|
||||
const pollTxt = !p ? '' : p.never ? `<div class="note" style="margin-top:8px;color:var(--ash)">job channel: no poll on record (an app before 0.3.21, or never started)</div>`
|
||||
: p.silent ? `<div class="note" style="margin-top:8px;color:var(--red)">job channel silent since ${when(p.since)} (${ago(p.since)} ago)${p.last_job ? `, last job ${esc(p.last_job)}` : ', no job on record'}${p.version ? ` <small>(app ${esc(p.version)})</small>` : ''}: nothing reaches this machine until the app runs again</div>`
|
||||
: `<div class="note" style="margin-top:8px">job channel polled ${ago(p.since)} ago${p.last_job ? `, last job ${esc(p.last_job)}` : ''}</div>`;
|
||||
const tele = mc.telemetry && mc.telemetry.length ? `<div class="tw"><table class="t"><thead><tr><th>telemetry</th><th class="num">p95</th><th class="num">max</th><th class="num">cap</th><th class="num">GPU</th><th class="num">mem</th></tr></thead><tbody>${mc.telemetry.map(t => `<tr><td>${esc(t.name)}</td><td class="num">${t.p95_w} W</td><td class="num">${t.max_w} W</td><td class="num">${t.cap_w} W</td><td class="num ${t.max_gpu_c >= 85 ? 'bad' : ''}">${t.max_gpu_c} C</td><td class="num ${t.max_mem_c >= 95 ? 'bad' : ''}">${t.max_mem_c} C</td></tr>`).join('')}</tbody></table></div>` : (mc.cards.length ? `<div class="note" style="margin-top:8px">${mc.app ? 'no stability lines yet (power and temperatures come from nvidia-smi every 5 min; none on a Mac)' : 'the app log is not in the intake (an app before 0.3.3)'}</div>` : '');
|
||||
const events = mc.events && mc.events.length ? `<div style="margin-top:8px">${mc.events.map(e => `<div class="ev"><span class="t">${when(e.at)}</span><span class="k ${e.kind}">${e.kind}</span><span>${esc(e.text)}</span></div>`).join('')}</div>` : '';
|
||||
return `<article class="card ${mc.stopped ? 'stopped' : mc.silent ? 'red' : 'live'}">
|
||||
<h3>${esc(mc.name)}<span class="id">${esc(mc.id8 || '')}${mc.host ? ' ' + esc(mc.host) : ''}${mc.legacy ? ' (old launcher)' : ''}</span><span class="seen ${mc.silent ? 'bad' : ''}">${silentTxt}</span></h3>
|
||||
${mc.never ? '<div class="note" style="margin-top:8px">nothing from this machine in the log intake in the last 48 h</div>' : kvs([
|
||||
${pollTxt}${mc.never ? '<div class="note" style="margin-top:8px">nothing from this machine in the log intake in the last 48 h</div>' : kvs([
|
||||
['app', mc.app_version ? esc(mc.app_version) : '<small>not in the intake</small>'],
|
||||
['ota', mc.app && mc.app.ota ? esc(mc.app.ota.state) : (mc.app_version ? 'no update pending' : '?'), mc.app && mc.app.ota ? ((mc.app.ota.state === 'updated' || mc.app.ota.state === 'current') ? 'good' : 'warm') : ''],
|
||||
['node', n.version ? esc(n.version) : '?'],
|
||||
|
|
@ -302,7 +307,7 @@ input[type=text]{width:100%}
|
|||
const live = j.machines.filter(mc => !mc.silent).length;
|
||||
$('#n-machines').textContent = `${live}/${j.machines.length}`;
|
||||
$('#n-machines').className = 'n' + (j.machines.some(mc => mc.silent && !mc.never && mc.name !== 'Mac') ? ' hot' : '');
|
||||
$('#p-machines').innerHTML = `<div class="note">red after ${j.silent_after_s / 60} min without an upload; unnamed ids drop off after ${j.hide_after_s / 60} min. Hash rate and accepted blocks come from the newest STATUS line per card, height and peers from the node log, power and temperatures from the app's stability lines. Refreshed ${when(j.now)}.</div><div class="grid">${j.machines.map(machineCard).join('')}</div>`;
|
||||
$('#p-machines').innerHTML = `<div class="note">red after ${j.silent_after_s / 60} min without an upload; the job channel reads silent after ${(j.poll_silent_after_s || 900) / 60} min without a poll; unnamed ids drop off after ${j.hide_after_s / 60} min. Hash rate and accepted blocks come from the newest STATUS line per card, height and peers from the node log, power and temperatures from the app's stability lines. Refreshed ${when(j.now)}.</div><div class="grid">${j.machines.map(machineCard).join('')}</div>`;
|
||||
}
|
||||
|
||||
// ---- jobs ----
|
||||
|
|
|
|||
|
|
@ -254,14 +254,14 @@
|
|||
<article class="record"><div class="record-top"><time datetime="2026-10-05">5 Oct 2026</time><span class="badge">log</span></div><h3>Live devnet: real transactions, the first non-empty shard proven and…</h3><p>Live devnet: real transactions, the first non-empty shard proven and paid, and the exporter's block structure fixed</p></article>
|
||||
<article class="record"><div class="record-top"><time datetime="2026-10-05">5 Oct 2026</time><span class="badge">log</span></div><h3>The program id split</h3><p>The program id split: why the Apple M5 Max rejected the RTX 5090 Windows rig's proofs, and the verifier at 114 s</p></article>
|
||||
<article class="record"><div class="record-top"><time datetime="2026-10-05">5 Oct 2026</time><span class="badge">log</span></div><h3>Live devnet: the first shards proven, verified and paid</h3></article>
|
||||
<article class="record"><div class="record-top"><time datetime="2026-10-04">4 Oct 2026</time><span class="badge">log</span></div><h3>Economy simulation: mining versus proving under stress</h3><p>Sim/economy: mining versus proving under stress, agent-based</p></article>
|
||||
<article class="record"><div class="record-top"><time datetime="2026-10-04">4 Oct 2026</time><span class="badge">log</span></div><h3>Difficulty rule attacked seven ways</h3><p>Difficulty rule under attack: pool hopping, pulsed rental, timestamp stretching, short-lane oscillation, epoch games, polluted window, block flood</p></article>
|
||||
<article class="record"><div class="record-top"><time datetime="2026-10-04">4 Oct 2026</time><span class="badge">log</span></div><h3>Timestamp attack on the difficulty rule fixed</h3><p>Difficulty rule: timestamp attack fixed , simulator regression, 3-node forger test</p></article>
|
||||
<article class="record"><div class="record-top"><time datetime="2026-10-04">4 Oct 2026</time><span class="badge">log</span></div><h3>Devnet v4: nine branches merged into one node</h3><p>Devnet-v4 integration: nine branches merged, 3-node test network on the merged node, Windows cross-build</p></article>
|
||||
<article class="record"><div class="record-top"><time datetime="2026-10-04">4 Oct 2026</time><span class="badge">log</span></div><h3>Generator v2 adopted: every hash does 128 distinct reads</h3><p>Generator version 2 adopted: exact load count, fresh-source loads, program acceptance; every vector re-cut, three workers re-checked, 20,000-program census, devnet-v4 binaries rebuilt</p></article>
|
||||
<article class="record"><div class="record-top"><time datetime="2026-10-04">4 Oct 2026</time><span class="badge">log</span></div><h3>First GPU proof of an Igneum block: 1.4 s on an RTX 5090</h3><p>Proving v0 on the RTX 5090: first GPU proof of an Igneum block</p></article>
|
||||
<article class="record"><div class="record-top"><time datetime="2026-10-04">4 Oct 2026</time><span class="badge">log</span></div><h3>Devnet v4 live: generator v2, two-thirds floor, fresh chain</h3><p>Devnet v4 cut-over: generator v2, 2/3 floor, three nodes and a seed on a fresh chain</p></article>
|
||||
<article class="record"><div class="record-top"><time datetime="2026-10-04">4 Oct 2026</time><span class="badge">log</span></div><h3>First live hourly swap: no pause on Mac, NVIDIA or AMD</h3><p>First hourly program swap on the live devnet: compile-ahead, no pause, two cards</p></article></div>
|
||||
<article class="record"><div class="record-top"><time datetime="2026-10-04">4 Oct 2026</time><span class="badge">log</span></div><h3>One-click Windows workers</h3><p>One-click Windows workers: what the Apple M5 Max could measure</p></article>
|
||||
<article class="record"><div class="record-top"><time datetime="2026-10-04">4 Oct 2026</time><span class="badge">log</span></div><h3>Proving: devnet v4 shards on the Apple M5 Max CPU, loaded machine</h3></article>
|
||||
<article class="record"><div class="record-top"><time datetime="2026-10-04">4 Oct 2026</time><span class="badge">log</span></div><h3>First live finality lock: 77.4% of weight, 17 voters</h3><p>First finality lock on the live devnet: checkpoint 242 at 77.4% of all weight, two hours after genesis</p></article>
|
||||
<article class="record"><div class="record-top"><time datetime="2026-10-04">4 Oct 2026</time><span class="badge">log</span></div><h3>The gfx1036 worker fault and what the Apple M5 Max could and could…</h3><p>The gfx1036 worker fault and what the Apple M5 Max could and could not reproduce</p></article>
|
||||
<article class="record"><div class="record-top"><time datetime="2026-10-04">4 Oct 2026</time><span class="badge">log</span></div><h3>A node 60 s behind the clock is silently dead</h3></article>
|
||||
<article class="record"><div class="record-top"><time datetime="2026-10-04">4 Oct 2026</time><span class="badge">log</span></div><h3>First machine on the one-click app: a 5090 at 118 MH/s</h3><p>First machine on the Igneum Miner app: the RTX 5090 Windows rig's RTX 5090 at 118 MH/s, via Setup.exe</p></article>
|
||||
<article class="record"><div class="record-top"><time datetime="2026-10-04">4 Oct 2026</time><span class="badge">log</span></div><h3>Difficulty rule v2</h3><p>Difficulty rule v2: the live oscillation, its cause, the DAG replay, the fix behind a height switch</p></article>
|
||||
<article class="record"><div class="record-top"><time datetime="2026-10-04">4 Oct 2026</time><span class="badge">log</span></div><h3>The observer stored nothing for 78 minutes, then 7,022 blocks in two…</h3><p>The observer stored nothing for 78 minutes, then 7,022 blocks in two minutes</p></article></div>
|
||||
<p class="empty-state" data-filter-empty="log" hidden>Nothing in the log matches that.</p>
|
||||
<p class="note">Every entry is a dated heading of <a href="/bench">the engineering log</a>, where the commands and the hardware are. The phases and their gates are the litepaper’s <a href="/litepaper#roadmap">roadmap</a>.</p>
|
||||
<div class="onward"><a href="/bench" class="btn">The engineering log</a><a href="/evidence" class="btn">Every claim and its status</a><a href="/live" class="btn">The live devnet</a></div>
|
||||
|
|
|
|||
|
|
@ -212,43 +212,43 @@
|
|||
},
|
||||
{
|
||||
"date": "2026-10-04",
|
||||
"text": "Sim/economy: mining versus proving under stress, agent-based",
|
||||
"short": "Economy simulation: mining versus proving under stress"
|
||||
"text": "One-click Windows workers: what the Apple M5 Max could measure",
|
||||
"short": "One-click Windows workers"
|
||||
},
|
||||
{
|
||||
"date": "2026-10-04",
|
||||
"text": "Difficulty rule under attack: pool hopping, pulsed rental, timestamp stretching, short-lane oscillation, epoch games, polluted window, block flood",
|
||||
"short": "Difficulty rule attacked seven ways"
|
||||
"text": "Proving: devnet v4 shards on the Apple M5 Max CPU, loaded machine",
|
||||
"short": "Proving: devnet v4 shards on the Apple M5 Max CPU, loaded machine"
|
||||
},
|
||||
{
|
||||
"date": "2026-10-04",
|
||||
"text": "Difficulty rule: timestamp attack fixed , simulator regression, 3-node forger test",
|
||||
"short": "Timestamp attack on the difficulty rule fixed"
|
||||
"text": "First finality lock on the live devnet: checkpoint 242 at 77.4% of all weight, two hours after genesis",
|
||||
"short": "First live finality lock: 77.4% of weight, 17 voters"
|
||||
},
|
||||
{
|
||||
"date": "2026-10-04",
|
||||
"text": "Devnet-v4 integration: nine branches merged, 3-node test network on the merged node, Windows cross-build",
|
||||
"short": "Devnet v4: nine branches merged into one node"
|
||||
"text": "The gfx1036 worker fault and what the Apple M5 Max could and could not reproduce",
|
||||
"short": "The gfx1036 worker fault and what the Apple M5 Max could and could…"
|
||||
},
|
||||
{
|
||||
"date": "2026-10-04",
|
||||
"text": "Generator version 2 adopted: exact load count, fresh-source loads, program acceptance; every vector re-cut, three workers re-checked, 20,000-program census, devnet-v4 binaries rebuilt",
|
||||
"short": "Generator v2 adopted: every hash does 128 distinct reads"
|
||||
"text": "A node 60 s behind the clock is silently dead",
|
||||
"short": "A node 60 s behind the clock is silently dead"
|
||||
},
|
||||
{
|
||||
"date": "2026-10-04",
|
||||
"text": "Proving v0 on the RTX 5090: first GPU proof of an Igneum block",
|
||||
"short": "First GPU proof of an Igneum block: 1.4 s on an RTX 5090"
|
||||
"text": "First machine on the Igneum Miner app: the RTX 5090 Windows rig's RTX 5090 at 118 MH/s, via Setup.exe",
|
||||
"short": "First machine on the one-click app: a 5090 at 118 MH/s"
|
||||
},
|
||||
{
|
||||
"date": "2026-10-04",
|
||||
"text": "Devnet v4 cut-over: generator v2, 2/3 floor, three nodes and a seed on a fresh chain",
|
||||
"short": "Devnet v4 live: generator v2, two-thirds floor, fresh chain"
|
||||
"text": "Difficulty rule v2: the live oscillation, its cause, the DAG replay, the fix behind a height switch",
|
||||
"short": "Difficulty rule v2"
|
||||
},
|
||||
{
|
||||
"date": "2026-10-04",
|
||||
"text": "First hourly program swap on the live devnet: compile-ahead, no pause, two cards",
|
||||
"short": "First live hourly swap: no pause on Mac, NVIDIA or AMD"
|
||||
"text": "The observer stored nothing for 78 minutes, then 7,022 blocks in two minutes",
|
||||
"short": "The observer stored nothing for 78 minutes, then 7,022 blocks in two…"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@
|
|||
@media (max-width:1000px){.gcol{border-right:0;border-bottom:var(--hair)}}
|
||||
.gcol .state{position:absolute;left:25px;top:14px;z-index:3;font-size:10px}
|
||||
.scene{position:relative}
|
||||
#dag{display:block;width:100%;height:418px;background:var(--row);touch-action:pan-y}
|
||||
#dag{display:block;width:100%;background:var(--row);touch-action:pan-y}
|
||||
.gtop{display:flex;flex-wrap:wrap;align-items:center;gap:8px 14px;padding:10px 25px;border-bottom:var(--hair);font:10px/1.7 var(--mono);color:var(--ash)}
|
||||
.gtop .hint{white-space:nowrap}
|
||||
.gtop .lg{display:flex;flex-wrap:wrap;gap:6px 10px;flex:1 1 auto;justify-content:center}
|
||||
|
|
@ -626,10 +626,6 @@ details.tablebar summary{display:flex;align-items:center}
|
|||
function uninspect(){sel=null;$('insp-close').hidden=true;$('i-kind').textContent='select a block';$('i-title').textContent='Select a block';$('i-hash').textContent='Click the graph, or a row of the table below.';$('i-shard-count').textContent='not set';$('i-track').innerHTML='';$('i-shards').innerHTML='<li class="muted">No block selected.</li>';['i-incl','i-miner','i-blue','i-daa','i-parents','i-time','i-cp','i-lock'].forEach(function(id){$(id).textContent='not set';});if(proof)proof.setBlock(null);}
|
||||
$('insp-close').addEventListener('click',function(){if(dag)dag.select(null,'clear');uninspect();});
|
||||
// the four stats above the graph, from the module's own window
|
||||
// the scene box fits its lanes: the renderer places lanes at 46 px (40 on phones) under a 58 px top band and over a 38 px axis
|
||||
// (scene/live-dag.js 2.0.3 layout()); one lane per key in view plus the others lane, capped at the renderer's 7 (4 on phones)
|
||||
var fitH=0;
|
||||
function fit(st){var c=$('dag');if(!c||!st)return;var cap=st.narrow?4:7,laneH=st.narrow?40:46,keys=Math.max(2,st.minerKeys||0),lanes=Math.min(cap,keys>cap?cap:keys+(keys>cap?1:0));var h=58+lanes*laneH+38;if(h!==fitH){fitH=h;c.style.height=h+'px';}}
|
||||
function miner(st){if(!dag)return;var cps=dag.getCheckpoints(),cp=cps.length?cps[cps.length-1]:null;
|
||||
$('m-blocks').textContent=fmtN(st.blocks);$('m-win').textContent='last '+st.window+' s';$('m-keys').textContent=st.minerKeys+' miner keys · not a card count';$('lane-caption').textContent=st.minerKeys+' keys';
|
||||
$('m-mine').textContent=mine?fmtN(st.own):'0';$('m-mine').classList.toggle('dim',!mine);$('m-key').textContent=mine||'not set';
|
||||
|
|
@ -642,7 +638,7 @@ details.tablebar summary{display:flex;align-items:center}
|
|||
onState:function(st,reason){var el=$('dag-state');el.className='state '+(st==='live'?'live':st==='failed'?'bad':'');el.innerHTML='<span class="dot '+(st==='live'?'live':st==='failed'?'bad':'off')+'"></span>'+(st==='live'?'live devnet':esc(reason||st));if(proof)proof.setPaused(st!=='live'||dag.getStats().paused);},
|
||||
onPause:function(p){$('dag-follow').classList.toggle('on',!p);if(proof)proof.setPaused(p||dag.getState().state!=='live');},
|
||||
onFollow:function(f){$('dag-follow').classList.toggle('on',f);},
|
||||
onStats:function(st){miner(st);fit(st);},
|
||||
onStats:miner,autoHeight:true,
|
||||
onSelect:function(b,why){if(b){var full=lastD&&(lastD.blocks||[]).filter(function(x){return x.hash===b.hash;})[0];inspect(Object.assign({},b,full?{number:full.number}:{}));}else uninspect();}});
|
||||
if(window.IgneumProof&&!proof)proof=IgneumProof.mount($('proof'));
|
||||
if(lastD)feed(lastD);}
|
||||
|
|
|
|||
|
|
@ -6,9 +6,14 @@
|
|||
# infra/build-server/remote-run.sh --self-test-slots (slots, jobs, quiet beside builds and suites, leased cores excluded).
|
||||
#
|
||||
# tools/ci/box-locks-check.sh # exit 1 when either self-test fails or the box cannot be reached
|
||||
# tools/ci/box-locks-check.sh --ci # the same, but a runner with no box (no BUILD_HOST, no ~/.config/igneum/build-server) prints
|
||||
# # "ok (no box from this runner)" and exits 0: GitHub's hosted runner cannot reach the box
|
||||
# # (master went red on 7 Oct 2026 the moment this check landed); the Mac hook and the
|
||||
# # self-hosted runners that carry the box file run it live
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/../.."
|
||||
. infra/build-server/lib.sh
|
||||
if [ "${1:-}" = --ci ] && [ -z "${BUILD_HOST:-}" ] && [ ! -s "$BS_HOST_FILE" ]; then echo "box-locks: ok (no box from this runner: no BUILD_HOST and no $BS_HOST_FILE; the Mac hook and the box runners run the lock self-tests)"; exit 0; fi
|
||||
bs_host 1
|
||||
stamp="ci-$$-$(date +%s)"
|
||||
scp -q "${BS_SSH_OPTS[@]}" infra/build-server/lease.sh "$BS_HOST:/tmp/lease-$stamp.sh"
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ tree_checks() {
|
|||
run "long-running tools keep their body in one parsed block (the edited-while-running class)" bash -c 'bash tools/ci/whole-body-check.sh --self-test && bash tools/ci/whole-body-check.sh'
|
||||
run "build-remote without a priority flag bounds suites and benches (nice 10, 32 cores); a gate runs unbounded" bash tools/ci/build-kind-default-check.sh
|
||||
run "the class router is a preference with spill-over (a held or overloaded box hands the job to the other one)" bash tools/ci/route-spill-check.sh
|
||||
run "per-core leases, the quiet class and the reaper pass on the box (lease.sh and remote-run.sh self-tests over ssh)" bash tools/ci/box-locks-check.sh
|
||||
run "per-core leases, the quiet class and the reaper pass on the box (lease.sh and remote-run.sh self-tests over ssh)" bash tools/ci/box-locks-check.sh $( [ "$MODE" = ci ] && echo --ci )
|
||||
run "the simulators job runs on master and release-* pushes and pull requests into them only" bash tools/ci/sims-branch-check.sh
|
||||
run "no shell assignment hides behind a trailing comment (the swallowed-defaults class)" bash -c 'bash tools/ci/defaults-line-check.sh --self-test && bash tools/ci/defaults-line-check.sh'
|
||||
run "no script kills or finds a process by a plain name or a file name (pgrep/pkill -f literals, ps | grep)" bash -c 'bash tools/ci/kill-by-name-check.sh --self-test && bash tools/ci/kill-by-name-check.sh'
|
||||
|
|
|
|||