iuna

iuna

iuna - experimental mainnet-candidate protocol
git clone https://getiuna.org/git/iuna.git
Log | Files | Refs | README | LICENSE

README.md (8048B)


      1 # Docker Compose end-to-end tests
      2 
      3 This harness runs the six-node network with a deliberately isolated consensus
      4 profile, iuna-local-e2e-5s-v1. Its target block time is 5 seconds, its Docker
      5 subnet is 172.29.0.0/24, and its management ports are 28661 through 28666.
      6 The optional sync-test node uses 28667. The regular local testnet keeps its
      7 10-minute target and can run alongside it.
      8 
      9 The e2e binary refuses to start unless IUNA_LOCAL_TESTNET=true. Its profile ID
     10 is part of the launch-profile hash, so a 5-second checkpoint cannot be loaded by
     11 the regular local-testnet build.
     12 
     13 ## Everyday workflow
     14 
     15 Start a fresh network:
     16 
     17 ```sh
     18 ./e2e/iuna_e2e.py reset
     19 ./e2e/iuna_e2e.py up --build
     20 ./e2e/iuna_e2e.py status
     21 ```
     22 
     23 Start from a committed checkpoint and wait for all nodes to converge:
     24 
     25 ```sh
     26 ./e2e/iuna_e2e.py up --snapshot pre-objective-finality
     27 ./e2e/iuna_e2e.py wait 1001 --converge
     28 ```
     29 
     30 Run the same flow as one test, including log collection on failure and teardown:
     31 
     32 ```sh
     33 ./e2e/iuna_e2e.py smoke \
     34   --from pre-objective-finality \
     35   --through 1001
     36 ```
     37 
     38 Run the complete assertion suite (build the image on the first scenario):
     39 
     40 ```sh
     41 ./e2e/iuna_e2e.py test --build
     42 ```
     43 
     44 Run the standard post-activation gate used by deployment:
     45 
     46 ```sh
     47 ./e2e/iuna_e2e.py test post-activation --build
     48 ```
     49 
     50 This verifies the committed checkpoints, crosses 999 through 1001, then restores
     51 the first objective checkpoint, advances the restarted network through 1007,
     52 interrupts both an empty-node bootstrap and stale range sync, and runs a physical
     53 3-3 P2P partition/recovery scenario.
     54 
     55 Tests can also be selected individually:
     56 
     57 ```sh
     58 ./e2e/iuna_e2e.py test snapshots
     59 ./e2e/iuna_e2e.py test fallback-activation
     60 ./e2e/iuna_e2e.py test objective-finality
     61 ./e2e/iuna_e2e.py test checkpoint-restart
     62 ./e2e/iuna_e2e.py test sync-resilience
     63 ./e2e/iuna_e2e.py test partition-recovery
     64 ```
     65 
     66 Preserve a machine-readable phase report and complete container logs:
     67 
     68 ```sh
     69 ./e2e/iuna_e2e.py test sync-resilience \
     70   --evidence-dir release-evidence
     71 ```
     72 
     73 snapshots is fast and does not need Docker. It verifies checksums, manifest
     74 metadata, the six stored chain databases, canonical heights and tips, and the
     75 profile of every committed checkpoint. The network scenarios restore the
     76 checkpoint before a protocol boundary and assert six-node convergence, the
     77 isolated e2e profile, finality state, canonical block identity, and the read-only
     78 blocks, network-health, peers, mempool, and wallet APIs on every node.
     79 
     80 fallback-activation crosses height 300 and checks that objective finality has
     81 not activated early. objective-finality crosses heights 1000 and 1001 and
     82 requires a certified checkpoint. checkpoint-restart proves that the certified
     83 checkpoint survives a full six-node restart, advances through height 1007, and
     84 that block 1007 is finalized by a ticket derived from a burn included at height
     85 1002 or later. At that height, the ticket maturity and expiry windows exclude
     86 every pre-pipeline burn, so this covers a complete post-activation burn-to-block
     87 lifecycle.
     88 
     89 partition-recovery gives the e2e containers network-administration capability
     90 and installs temporary firewall rules that split the six real node processes
     91 into two connected groups of three. It requires both islands to converge
     92 internally on different tips containing new recovery blocks, removes the rules,
     93 requires six-node convergence, restarts node6 with its existing data, and waits
     94 for a new rank-0 ticket block that finalizes at or beyond the canonical recovery
     95 height. The disposable scenario deterministically leaves one automatic finalizer
     96 active per island; disabling the other members cancels their in-flight VDFs
     97 before partitioning. Before healing it also stops one island's worker so a single
     98 canonical branch can overtake the other. It restores every node's original
     99 finalization settings after convergence, avoiding both a recovery-less small
    100 island and competing recovery branches.
    101 
    102 sync-resilience restores the mature six-node checkpoint and adds a seventh,
    103 non-finalizing syncnode with a fresh data directory. It interrupts that node
    104 before its fetched chain is persisted, then requires a successful restart and
    105 seven-node convergence. Next it gives the same node the height-299 chain/UI
    106 fixture, waits until the management API reports active incremental range
    107 validation, interrupts it again, and requires the persisted stale node to
    108 resume and converge. The six reference nodes start with finalization paused so
    109 the sync target stays fixed and fork races are not conflated with the sync
    110 failure being tested.
    111 
    112 Each evidence run is stored in a timestamped directory with report.json and
    113 nodes.log. The report records the base Git revision, dirty-worktree flag, an
    114 exact SHA-256 fingerprint of all tracked working-tree contents, and per-phase
    115 node tips and checkpoints. Scenario-specific phases add the sync start,
    116 validated and target heights or both partition recovery heights, the canonical
    117 recovery block, the restarted service, and the resumed rank-0 ticket. The tree
    118 fingerprint also identifies the tested state while deployment has staged
    119 version changes that are committed and tagged only after all gates pass.
    120 It is updated after every completed phase so a failed run remains useful. Raw
    121 node logs contain public node/wallet addresses but no configuration files,
    122 passwords, wallet ciphertext, or recovery phrases. deployment.sh enables this
    123 automatically under release-evidence/; set IUNA_RELEASE_EVIDENCE_DIR to copy
    124 release evidence to another retained location.
    125 
    126 Use --keep on smoke to leave a failed or successful network running. Stop a
    127 network without deleting its mutable data with:
    128 
    129 ```sh
    130 ./e2e/iuna_e2e.py down
    131 ```
    132 
    133 Runtime data lives in e2e/.runtime and is ignored by Git. Set
    134 IUNA_E2E_RUNTIME_DIR, IUNA_E2E_SNAPSHOTS_DIR, IUNA_E2E_PROJECT, or the
    135 IUNA_E2E_*_PORT variables when a test needs independent paths or ports.
    136 reset only removes the six service directories beneath that configured runtime
    137 directory plus the disposable sync-node directory; committed checkpoints are
    138 never touched.
    139 
    140 ## Building mature checkpoints
    141 
    142 checkpoints.json records the protocol boundaries worth preserving:
    143 
    144 - 299 and 300: fallback-ticket invalidation;
    145 - 999 and 1000: signing v1, replay protection, grinding resistance, and
    146   objective-finality activation;
    147 - 1001: the first block that can certify checkpoint 1000.
    148 
    149 Generate all missing checkpoints during one continuous run:
    150 
    151 ```sh
    152 ./e2e/iuna_e2e.py reset
    153 ./e2e/iuna_e2e.py up --build
    154 ./e2e/iuna_e2e.py capture-plan
    155 ```
    156 
    157 At five seconds per block, reaching height 1001 takes roughly 84 minutes plus
    158 startup and synchronization overhead. This is a one-time fixture-building job;
    159 normal tests restore the resulting checkpoints in seconds. Capture one custom
    160 boundary with:
    161 
    162 ```sh
    163 ./e2e/iuna_e2e.py capture pre-objective-finality --height 999
    164 ```
    165 
    166 Capture waits until the bootstrap SQLite checkpoint reaches the requested
    167 height, then pauses all containers before copying anything. An e2e-only helper
    168 materializes the canonical compact chain at the exact requested height, even if
    169 the live chain advanced across that height between polls. That canonical chain
    170 database and its prebuilt UI projection are paired with every node's encrypted
    171 test wallet and configuration.
    172 Keeping all six identities matters because their mature tickets and committee
    173 lineage must remain usable after restore. Persisting the derived UI database
    174 keeps mature-checkpoint startup fast. SQLite's backup API removes WAL dependence,
    175 a manifest records the live source height plus every exact node height and tip,
    176 and SHA-256 checksums are verified before restore.
    177 
    178 Snapshots use the intentionally public Compose password testtesttest unless
    179 IUNA_TESTNET_PASSWORD was set while they were generated. They are disposable
    180 test credentials only. Use the same password when restoring a snapshot.
    181 
    182 Commit reviewed snapshot directories under e2e/snapshots/. Do not commit the
    183 mutable e2e/.runtime directory.