From 630eea1e791996c6282d2298543595fce4351990 Mon Sep 17 00:00:00 2001 From: Dendi Suhubdy <4477337+dendisuhubdy@users.noreply.github.com> Date: Thu, 29 Oct 2026 08:03:07 +0800 Subject: [PATCH] =?UTF-8?q?deploy:=20cut-chain22-genesis.sh=20=E2=80=94=20?= =?UTF-8?q?chain=2021's=20shape=20with=20v0.8.2's=20genesis-gated=20rules?= =?UTF-8?q?=20on=20(PST-1,=20PERP-6,=20PERP-101,=20CON-60,=20MSA-4,=20TOK-?= =?UTF-8?q?1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Derived from cut-chain21-genesis.sh with chain 21 as the source. Writes and asserts program_state.refuse_panics true (monorepo#15), perps.bound_payouts true (#13), perps.sparse_windows true + max_window_heights (#12), perps.engine_program_log_height 14 (derived from `rand perp image-hc`), multisig.max_accounts, and tokens.incremental_root true (docs/deploy.md's recommendation); field-probes each into the genesis hash (7 variants) and reads each back in check-limits (refuse_panics through the hash: no RPC serves it). max_window_heights, max_accounts and the treasury balance are the owner's: the real cut takes no default, DRY_RUN puts in loud placeholders. Chain 21's treasury vault, perps exchange and program vaults have no documented carry rule: the cut refuses while any holds value unless dropped knowingly (MULTISIG_NOT_CARRIED_OK, PERPS_STATE_NOT_CARRIED_OK, PROGRAM_VAULTS_DROPPED_OK) and named on the record's drops: line. docs/deploy.md gains "The next cut: chain 22 (audit v11 gated fields)"; CHANGELOG Unreleased notes the tooling. No cut was made. SELFTEST=1: 277 passed, 0 failed. shellcheck clean. DRY_RUN passed end to end with the v0.8.2 release binaries and with debug binaries built at 97bcf4b1 (perp-prover from durian.market): the perps genesis root re-derives as chain 21's da0e3a53…, the 7-variant field probe passes, and the loopback node serves chain 22 as cut. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 12 + deploy/cut-chain22-genesis.sh | 2835 +++++++++++++++++++++++++++++++++ docs/deploy.md | 79 + 3 files changed, 2926 insertions(+) create mode 100755 deploy/cut-chain22-genesis.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index 9aefa278..be87228e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,18 @@ Node: `rand_getEmission.faucet` are `true` only on a validator whose key is a faucet minter, and `rand_mint` on any other validator refuses up front, naming the minters. +Deploy tooling (no node or chain change): + +- **`deploy/cut-chain22-genesis.sh`**: the chain-22 cut, derived from chain 21's script with chain + 21 as the source, switching on v0.8.2's genesis-gated rules — `program_state.refuse_panics` + (PST-1, monorepo#15), `perps.bound_payouts` (PERP-6, #13), `perps.sparse_windows` with + `perps.max_window_heights` (PERP-101, #12), `perps.engine_program_log_height` 14 (CON-60), + `multisig.max_accounts` (MSA-4) and `tokens.incremental_root` — each asserted on the finished + file, field-probed into the genesis hash and read back by `check-limits`. `max_window_heights`, + `max_accounts` and the treasury's balance are the owner's (no default); chain 21's treasury + vault, perps exchange and program vaults are refused unless dropped knowingly and named on the + record. Not run: no cut was made (`docs/deploy.md`, "The next cut: chain 22"). + Wallet (`rand`; client-only, no node or chain change): - **`rand` no longer exits 1 after a successful submit** (#141): `submitted ` is diff --git a/deploy/cut-chain22-genesis.sh b/deploy/cut-chain22-genesis.sh new file mode 100755 index 00000000..3a79e19e --- /dev/null +++ b/deploy/cut-chain22-genesis.sh @@ -0,0 +1,2835 @@ +#!/usr/bin/env bash +# Cut the chain-22 genesis: chain 21's shape and value, cut from a snapshot of chain 21, on a build +# that knows audit v10/v11's genesis-gated rules (v0.8.2, 299378d0, or later: the audit/v10-node +# and audit/v10-perps merges d7358e90 / 81b9a2c0), with those rules switched on — the fields that +# close randprotocol/monorepo#12 (PERP-101), #13 (PERP-6) and #15 (PST-1) at the cut +# (CHANGELOG.md v0.8.2; docs/deploy.md, "The next cut: chain 22 (audit v11 gated fields)"): +# - `program_state.refuse_panics: true` (PST-1, docs/program-state.md:136): an Invoke whose call +# proof publishes guest-sdk's panic sentinel (0xdeadbeef in output 7) is invalid; +# - `perps.bound_payouts: true` (PERP-6, docs/perps.md:62): a state proof may not pay out more +# collateral than `initial_collateral + collateral_in − collateral_out`; `initial_collateral` +# ABSENT (0, docs/perps.md:63) — the engine starts from `perp-prover genesis-state`, a fresh +# state holding nothing (see OPEN 4: chain 21's exchange is NOT carried); +# - `perps.sparse_windows: true` + `perps.max_window_heights` (PERP-101, docs/perps.md:64,66): +# input-less blocks record no digest, a window spans at most max_window_heights heights — +# max_window_heights is an OPERATOR INPUT (OPEN 1); +# - `perps.engine_program_log_height` (CON-60, docs/perps.md:65): the pinned engine's program +# height, DERIVED like engine_hc (`rand perp image-hc` prints it on stderr) and pinned here as +# EXPECT_ENGINE_PROGRAM_LOG_HEIGHT 14 (the pinned image f286a611…, read 2026-10-29 with v0.8.2); +# - `multisig.max_accounts` (MSA-4, docs/multisig.md:60) — an OPERATOR INPUT (OPEN 2); +# - `tokens.incremental_root: true` (audit v6 TOK-1, docs/deploy.md "The next cut: +# `tokens.incremental_root`": "Recommended: on, for the next cut"; chain 21 did not carry it and +# no record says why — the user's standing rule takes the recommended value; striking it is one +# constant, TOKENS_INCREMENTAL_ROOT, here and in docs/deploy.md together). +# +# deploy/cut-chain22-genesis.sh snapshot # chain 21 still up, bridge daemons stopped +# WALLET= deploy/cut-chain22-genesis.sh balances +# # read-only toward the chain: the RAND carry list +# CUT_RECORD= CHAIN21_SNAPSHOT= NODE= WALLET= \ +# EXPECT_NODE_VERSION= PERP_PROVER= \ +# PERPS_MAX_WINDOW_HEIGHTS=<64..4096> MULTISIG_MAX_ACCOUNTS= \ +# [PERP_IMAGE=] [TREASURY=] \ +# [MULTISIG_NOT_CARRIED_OK=1] [PERPS_STATE_NOT_CARRIED_OK=1] [PROGRAM_VAULTS_DROPPED_OK=1] \ +# deploy/cut-chain22-genesis.sh # the cut +# NODE= deploy/cut-chain22-genesis.sh check-limits +# # after launch: what the first node serves +# # (base_fees_burned "0" — BASE_FEES_BURNED_ANY=1 +# # after the first bundle — and perps proved_height +# # 0, no accounts, collateral counters "0": run it +# # before the first deposit and state proof) +# SELFTEST=1 deploy/cut-chain22-genesis.sh # no network, no binaries: the assembly on fixtures +# DRY_RUN=1 NODE=… WALLET=… PERP_PROVER=… RAND_MSAUTH_VK= \ +# MULTISIG_NOT_CARRIED_OK=1 deploy/cut-chain22-genesis.sh +# # no network: the REAL cut path (rand-node genesis, +# # alloc-note, perp-prover genesis-state, init, a +# # loopback probe node) on inputs synthesised from +# # the committed chain-21 genesis — its treasury +# # holding its genesis balance, so the dry run, like +# # the cut, refuses without MULTISIG_NOT_CARRIED_OK=1; +# # without a TREASURY file it uses chain 21's genesis +# # signers (public keys) at chain 21's 100 000 RAND; +# # without PERPS_MAX_WINDOW_HEIGHTS / +# # MULTISIG_MAX_ACCOUNTS it uses each field's lower +# # bound (64; 1), LOUDLY, as PLACEHOLDERS +# +# OPEN — owner decision before the cut (the real cut refuses until each is given; nothing below is +# a recommendation — the docs give none): +# 1. perps.max_window_heights (PERP-101). No documented value. The range is max_window_blocks +# (64) ..= MAX_WINDOW_HEIGHTS (4096) (docs/perps.md:66, PerpsConfig::check); the documented +# default, 0, is refused beside sparse_windows. It is the most heights one state proof spans +# AND the heartbeat interval (an input-less close is recorded every max_window_heights +# heights, so funding, marks and liquidations run at least that often), and back-pressure +# holds new orders at 4 × it past the proved height (docs/perps.md "Sparse windows"). The +# v11 perps report leaves it to the owner ("choose max_window_heights for chain 22"). +# Input: PERPS_MAX_WINDOW_HEIGHTS, no default. +# 2. multisig.max_accounts (MSA-4). No documented value; the documented default is ABSENT +# (unbounded — chain 21's rule, which would not close MSA-4). It counts the seeded treasury, +# so it is ≥ 1; `CreateMultisig` past it is refused for good (docs/multisig.md:60). +# Input: MULTISIG_MAX_ACCOUNTS, no default. +# 3. The treasury (chain 21's 2-of-3 multisig account d5fd1883…1958, seeded with 100 000 RAND +# NEW ISSUANCE at chain 21's cut). No document says how a multisig account crosses a cut: the +# register is genesis state, the treasury's vault is not a note, so `balances` never sees it +# and nothing re-creates it. This script does what chain 21's did — seeds ONE treasury from +# TREASURY (default ~/.rand-chain22/treasury.txt) as NEW ISSUANCE, signers asserted equal to +# chain 21's (in order; TREASURY_ROTATED=1 carries a live rotation, TREASURY_SIGNERS_CHANGED=1 +# knowingly other keys), threshold 2, a fresh salt (so a new id) — and REFUSES while chain 21's +# register holds any RAND (rand_getSupply.multisig_rand_held > 0: the treasury's vault, and +# any account created on chain 21) unless MULTISIG_NOT_CARRIED_OK=1, which drops it (the cut +# record's `drops:` must then name the treasury/multisig). The chain-22 BALANCE (re-issue +# chain 21's 100 000, the vault's live balance, or another amount) is the owner's: TREASURY's +# `balance` line, printed beside chain 21's issued and live figures. +# 4. Chain 21's perps exchange (accounts, positions, collateral, pending withdrawals). No carry +# rule exists: the engine state is proved off chain and chain 22's engine starts from +# `perp-prover genesis-state` over the market list (the same root as chain 21's genesis, +# da0e3a53…). The cut REFUSES while chain 21's exchange is not empty (rand_getPerps.accounts, +# pending_withdrawals, or the collateral counters — which count only since each node's +# v0.8.2 roll, so `accounts` is the reliable one) unless PERPS_STATE_NOT_CARRIED_OK=1 (the +# cut record's `drops:` must then name perps). `initial_collateral` stays absent (0): it is +# only for a seeded engine, and no seeding is designed. +# 5. zUSD inside the exchange (and in any multisig vault). A token's total supply does not move +# on a perp deposit (docs/perps.md "The supply audit"), so chain 21's zUSD supply still equals +# Σ locked, and the carry rule still demands Σ ZUSD_CARRY == Σ locked == custody: zUSD held by +# the exchange is in no wallet, and the operator must say, line by line in ZUSD_CARRY, whose +# note re-issues it (the depositors at their engine balances, or another holder). `balances` +# prints the operator wallets' zUSD beside Σ ZUSD_CARRY; the cut refuses any other total. +# 6. NOT carried, documented default off, no recommendation: `incremental_nullifier_root` (the +# hot path's nullifier MMR; docs/compute-optimization.md §3.1 says such changes "ride the next +# genesis-gated cut" but no page recommends it for one), `staking.slashing` (recommended only +# once stake is held by more than one operator, docs/deploy.md D8 — still one), and the +# aggregation-only fields (`aggregation`, `fees.subsidy_net_of_fees`, `proposer_share_bps`, +# `prove_base`, `usd_subsidy`: deferred until aggregation is admitted). Each is refused here as +# chain 21 refused it. +# 7. EXPECT_NODE_VERSION has no default: v0.8.2 is the first release with every field above; +# v0.8.3 (rc1 9443de63, main 97bcf4b1) is untagged. Set it to the release the cut runs. +# +# Known gap (not a decision): no RPC serves `program_state.refuse_panics` (rand_getLimits' +# program_state object is cell_fee/max_reads/max_writes/max_payouts). `check-limits` therefore +# reads it back through the genesis hash alone — the node must serve the hash `init` derives from +# the file, and the field probe proved that hash moves without the field. Serving it is a node +# follow-up. +# +# DERIVED from deploy/cut-chain21-genesis.sh (chain 21 — v0.8.0, live since 2026-10-12 10:31 UTC, +# genesis ca76c276…ca9a, running v0.8.2 since 2026-10-28): the same snapshot / balances / carry-over +# rule / splice, with chain 21 as the source. Read it first. What this script does that chain 21's +# did not: +# +# * THE NEW FIELDS above, each written by the build (a flag) or the cut (a section file), +# asserted on the finished file, proved part of the genesis hash by this rand-node (the cut +# re-derives the hash without each and refuses if it does not move: 7 variants — +# program_state.refuse_panics, perps.bound_payouts, perps.sparse_windows (with +# max_window_heights, which is refused alone), perps.max_window_heights at another value, +# perps.engine_program_log_height, multisig.max_accounts, tokens.incremental_root), and read +# back from the first node after launch (`check-limits`: rand_getPerps' bound_payouts, +# initial_collateral, sparse_windows, max_window_heights, engine_program_log_height and the +# collateral counters; rand_getLimits.multisig.max_accounts; rand_getTokens.incremental_root; +# refuse_panics through the hash, above). +# - refuse_panics: `rand-node genesis --program-state-refuse-panics` (v0.8.2, d3a1eb46). +# - max_accounts: a field of the `--multisig` file this script writes. +# - the perps fields: in the perps section file this script splices (as chain 21's). +# - incremental_root: `rand-node genesis --tokens-incremental-root` (v0.6.9 on). +# - Every one of them ships in v0.8.2, and a build before it refuses each section that +# carries one (`deny_unknown_fields` on PerpsConfig, MultisigConfig, ProgramStateConfig), +# so ONE gate decides them: `rand-node genesis --help` lists --program-state-refuse-panics +# and `rand perp image-hc` prints `engine_program_log_height`. The real cut REFUSES a build +# without them; DRY_RUN skips all of them, LOUDLY (AUDIT_V10_SKIPPED), as chain 21's did +# its sections. +# * CHAIN 21'S STATE THAT CHAIN 21'S SCRIPT NEVER HAD TO CARRY, read by `snapshot` and refused +# at the cut unless the operator says otherwise (OPEN 3–5): the multisig register's RAND +# (MULTISIG_NOT_CARRIED_OK), the perps exchange (PERPS_STATE_NOT_CARRIED_OK), and RPL-2 program +# vaults' RAND (rand_getSupply.program_rand_held — chain 21's record dropped "the programs' +# state", but its script never counted it; PROGRAM_VAULTS_DROPPED_OK). Each, when set, must be +# named on the cut record's `drops:` line. +# * EVERYTHING ELSE IS CHAIN 21'S, ASSERTED EQUAL: what chain 21's script switched on — `fees` +# {burn_base, burn_floor}; `perps` (BTC-PERP on zUSD, the pinned engine f286a611…, tier 18, 24 +# inputs, 64 blocks, min deposit 1 zUSD — and its genesis_root, re-derived by perp-prover, must +# equal chain 21's da0e3a53…); `multisig` create_fee 1 RAND and one treasury, 2 of 3; +# hc_auth_multisig 9705f8e2… (the file's last field) with 6 MiB proofs and 19 MiB blocks (still +# pending the measured production msauth proof, MSA-1/2); and chain 20's shape before it +# (testnet, binding_domain 1, proof_window_blocks 1024, the gas section with ceilings and the +# paying byte load, bridge.rotation, bridge.fees 10/10 bps to the fingerprinted recipient, +# staking's 2500-bps budget and admission by vote, program_state cell_fee 10000000) — each still +# asserted at its value, and the finished file compared field by field with +# deploy/genesis-chain21.json (the new fields excused, each asserted on its own). +# * THE BRIDGE IS CHAIN 21'S, NOT RE-DEPLOYED: EMITTER_2..5 default to chain 21's genesis +# `bridge.emitters` (the 2026-09-30 endpoints chain 20 also trusted), checked against +# deploy/genesis-chain21.json, refused otherwise unless EMITTERS_CHANGED=1; the 2026-09-19 +# endpoints are refused outright. Floors as chain 21's: `auto` = each endpoint's next sequence +# at the snapshot, never below chain 21's own (2:3 3:5 4:3 5:7); burn sequence chain 21's live. +# * OPS-7 as chain 21's: `refuse_reused_chain_id`, `require_cut_record`, and the record must name +# the treasury and each issue the cut closes (PST-1, PERP-6, PERP-101 on `reason:` or +# `carries:`). No deploy/cutover-fleet-chain22.sh exists yet: derive it from chain 21's. +# * NODE must report rand-node $EXPECT_NODE_VERSION (no default, OPEN 7). `balances` runs with +# chain 21's own build, v0.8.2 (WALLET). +# +# The inputs outside the repository (chain 21's, re-pointed at ~/.rand-chain22 where the cut writes): +# PERP_IMAGE / EXPECT_ENGINE_HC / PERP_PROVER as chain 21's (f286a611…; durian.market's perp-prover, +# built from the commit that pinned the image or later: state layout version 2). +# TREASURY default ~/.rand-chain22/treasury.txt, chain 21's format: `signer <2624 +# hex>` × 3 in order, `threshold 2`, `balance ` (OPEN 3). Public keys only. +# FEE_RECIPIENT_FILE default ~/.rand-chain20/fee-recipient-address.txt — chain 20's and chain +# 21's recipient, fingerprint 89DS-4Q4X-HXSX-MBYW (it never moved). +# +# Operations (not checked here; the cut record's `clients:` and the launch checklist): as chain +# 21's (NTP, msauth-vk-production.bin beside every rand-node, a perp-view service and a prover +# host) plus: durian.market's perp-prover must build SPARSE jobs on chain 22 (durian 28cebfb walks +# pending_heights within max_window_heights) and `rand perp prove` proves at the canonical shape by +# default once the engine pin is set (tier = max_tier 18: the prover host must fit a tier-18 proof); +# a validator with less than 8 GB should not run a max_tier-18 perps chain (docs/perps.md, CON-60). +# +# Traps carried from the chain-17 to 21 cuts (AGENTS.md): +# - `balances` scans CURATED directories of wallet key files, `$WALLETS_DIRS` = +# ~/.rand-chain17/alloc-wallets (symlinks: shielded-1..5 and the relayer → +# ~/.rand-chain14/wallets/relayer.key.json; that link went missing once and the scan then listed +# its alloc as "uncovered"), ~/.rand-chain18/wallets, ~/.rand-chain19/wallets, +# ~/.rand-chain20/wallets and ~/.rand-chain21/wallets. Never a checkout's `wallets/`. CHECK +# BEFORE THE SCAN that every wallet holding RAND on chain 21 has its key file (or a symlink) in +# one of them; the scan also lists chain 21's genesis allocs that no scanned wallet covers, and +# the cut refuses while that list is non-empty. +# - `balances` refuses to overwrite /balances.json and $ALLOC_ADDRESSES: move a first scan +# aside to re-scan. +# - The public RPC (Cloudflare) answers Python's urllib with 403: point CHAIN21_RPC at an SSH +# tunnel to an archive's RPC (`prune_floor` 0), e.g. +# `ssh -N -L 8545:127.0.0.1:8545 root@203.0.113.29` → CHAIN21_RPC=http://127.0.0.1:8545. +# The tunnel died twice in the hour of the chain-18 cut (once silently); this script refuses +# to start `snapshot` or `balances` on a dead one — re-open it and re-run. +# - Take the snapshot with the SAME EMITTER_* the cut uses (the defaults): custody and sequences +# are read at those addresses, and the cut refuses a snapshot read anywhere else. +# - `rand-node genesis` writes no bridge section: the hash that matters is the one `rand-node +# init` prints on the FINISHED file (this script's last lines), never the base file's. +# +# The carry-over rule (chain 21's, unchanged): zUSD per-backing `locked` = chain 21's at the +# snapshot with one fresh genesis note per $ZUSD_CARRY line (Σ notes == Σ locked == source custody); +# RAND = one genesis note per operator wallet the `balances` scan found holding RAND, at its +# chain-21 balance (Σ alloc == Σ scanned); a validator's unwithdrawn rewards are refused unless +# REWARDS_DROPPED_OK=1 (never carried); pending notes refused unless PENDING_OK=1; uncovered +# chain-21 genesis allocs refused unless UNCOVERED_ALLOCS_OK=1; tokens other than zUSD refused +# unless ALLOW_DROPPED_TOKENS=1. SHIELDED NOTES OF WALLETS THE OPERATOR DOES NOT HOLD ARE NOT +# CARRIED — the cut record's `drops:` line must say so. The treasury is new issuance beside the +# carry, never inside it (OPEN 3). +# +# Run from the repo root. Re-running produces a DIFFERENT genesis hash (fresh note randomness, a +# fresh treasury salt and a fresh timestamp). Cut once, distribute the file byte-identically, +# launch within minutes. +set -euo pipefail +cd "$(dirname "$0")/.." +# shellcheck disable=SC1091 # sourced from the repo root (the cd above); run shellcheck -x to follow +. deploy/lib/key-guard.sh +# shellcheck disable=SC1091 +. deploy/lib/cut-policy.sh + +NODE=${NODE:-target/release/rand-node} +WALLET=${WALLET:-target/release/rand} +CHAIN_ID=${CHAIN_ID:-22} +OUT=${OUT:-deploy/genesis-chain22.json} +CUT_RECORD=${CUT_RECORD:-$HOME/.rand-chain22/cut-record.txt} # deploy/cut-record.template, filled in and published before the cut +EXPECT_NODE_VERSION=${EXPECT_NODE_VERSION:-} # no default (OPEN 7): v0.8.2 is the first release with the audit-v10 fields; v0.8.3 is untagged +CHAIN21_GENESIS=${CHAIN21_GENESIS:-deploy/genesis-chain21.json} +CHAIN21_HASH=${CHAIN21_HASH:-ca76c2766ed6090ac6ba5dad86b724dd5d2b80c0edfaed287cd8b129e663ca9a} +CHAIN21_GENESIS_SHA256=${CHAIN21_GENESIS_SHA256:-88d42b38b76338e6d47d9486e8afd25eb651ec9f69f474aa80bc0aceee028ca1} +# chain 21's treasury, deploy/cut-records/chain21.record `treasury-id:` (re-derived from the committed +# genesis by NODE at the cut, and read live by `snapshot`) +CHAIN21_TREASURY_ID=${CHAIN21_TREASURY_ID:-d5fd188308af5322b234b199ae6193fa686ae1453e6af39720638b1f441b1958} +CHAIN21_RPC=${CHAIN21_RPC:-http://127.0.0.1:8545} # snapshot/balances: an SSH tunnel to an archive's RPC (Cloudflare 403s urllib) +CHAIN21_SNAPSHOT=${CHAIN21_SNAPSHOT:-} # the cut: the snapshot directory + +# ── public inputs, all outside the repository ───────────────────────────────────────────────── +VALIDATORS_TSV=${VALIDATORS_TSV:-$HOME/.rand-chain14/public/validators.tsv} # name addr pk peer payout (18) +REGISTRATIONS=${REGISTRATIONS:-$HOME/.rand-chain15/registrations} # .txt, one per bonded validator (8) +BONDED=${BONDED:-obs1 archive2 g1 g2 g3 g4 g5 g6} +GENESIS_NAMES=${GENESIS_NAMES:-a b c d e f lon1 sfo3 tor1 blr1 syd1 atl1 ams3 nyc1 nyc2 sfo2 mkc1 mem1} +FAUCET_MINTERS=${FAUCET_MINTERS:-$GENESIS_NAMES} # chain 21's list; another one needs FAUCET_MINTERS_CHANGED=1 +FAUCET_RECIPIENTS=${FAUCET_RECIPIENTS:-} # unset: chain 21's genesis allowlist; a file (" rand1…") changes it +STAKE_RAND=${STAKE_RAND:-1000} +ALLOC_ADDRESSES=${ALLOC_ADDRESSES:-$HOME/.rand-chain22/alloc-rand.txt} # "