diff --git a/CLAUDE.md b/CLAUDE.md index 648db4d2a..e6ba079de 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -97,3 +97,67 @@ Network and Lightning code is heavily async (asyncio). Background tasks run as c - Implementation sweeps: `@needs_test_with_all_aes_implementations`, `@needs_test_with_all_chacha20_implementations` - `FAST_TESTS = True` skips slow implementation variants - Test vectors live alongside tests as JSON files (e.g., `tests/test_vectors/`) + +--- + +## BitcoinPurple (BTCP) Support + +BitcoinPurple is a Bitcoin fork with 1-minute blocks and a shorter difficulty retarget window. The Electrum client has been extended to support it as a first-class network alongside mainnet and testnet. + +### Key Parameters (differ from Bitcoin) + +| Constant | Bitcoin | BTCP | +|----------|---------|------| +| `DIFFICULTY_ADJUSTMENT_INTERVAL` | 2016 blocks | **120 blocks** | +| `POW_TARGET_TIMESPAN` | 1,209,600 s | **7,200 s** | +| `MAX_TARGET` | `0x00000000ffff…` (compact `0x1d00ffff`) | `0x00000ffff…` (compact `0x1e0fffff`) | +| `POW_GENESIS_BITS` | `None` (derived from MAX_TARGET) | **`0x1e0ffff0`** (genesis nBits differ from powLimit) | +| `MAX_ADJUSTMENT_FACTOR` | 4 | 4 | + +`POW_GENESIS_BITS` is non-`None` for BTCP because the genesis block's `nBits` (`0x1e0ffff0`) is stricter than the `powLimit` compact (`0x1e0fffff`). `get_target(-1)` in `blockchain.py` returns `bits_to_target(POW_GENESIS_BITS)` when this is set, so period-0 header verification passes the exact equality check. + +### Retarget Clamping (BTCP only) + +At each 120-block boundary: +``` +actual_timespan = clamp(last.time - first.time, 1800, 28800) # [7200/4, 7200*4] +new_target = old_target * actual_timespan / 7200 +new_target = min(new_target, MAX_TARGET) +``` + +### Critical `blockchain.py` Logic + +`verify_chunk()` has two paths: +- `adj_interval == CHUNK_SIZE` (Bitcoin, 2016): reads old targets from on-disk headers. +- `adj_interval < CHUNK_SIZE` (BTCP, 120): retargets happen *within* a chunk, so headers are still in RAM (the buffer being verified). Uses an internal `_read_hdr(data, i)` helper to read from the buffer instead of `read_header()`. + +### Files + +| Path | Purpose | +|------|---------| +| `electrum/constants.py` | `BitcoinPurple` and `BitcoinPurpleTestnet` classes with all chain params | +| `electrum/blockchain.py` | `verify_chunk`, `get_target`, `can_connect` — all generalised for per-chain PoW constants | +| `electrum/chains/bitcoinpurple/servers.json` | Known ElectrumX servers (TCP 51001, SSL 51002) | +| `electrum/chains/bitcoinpurple/checkpoints.json` | SPV checkpoints (one entry = one 2016-block chunk) | +| `tests/test_bitcoinpurple.py` | 46 BTCP-specific tests (address encoding, difficulty, header verification) | +| `tecnichal-data.md` | Complete BTCP parameter reference (ports, genesis, PoW, LN, ElectrumX) | + +### Running with BitcoinPurple + +```bash +# Mainnet +./run_electrum --bitcoinpurple + +# Testnet +./run_electrum --bitcoinpurple_testnet + +# BitcoinPurple tests only +pytest tests/test_bitcoinpurple.py -v + +# Blockchain + bitcoin + BitcoinPurple together +pytest tests/test_blockchain.py tests/test_bitcoin.py tests/test_bitcoinpurple.py -v +``` + +### LN Block-Scaled Timeouts + +BTCP has 1-minute blocks (10× faster than Bitcoin). All LN timeout values expressed in blocks must be scaled ×10 to preserve the same real-world security windows (e.g. `to_self_delay` 144 → 1440, `cltv_expiry_delta` 40 → 400). See `tecnichal-data.md §8.3` for the full table.