CLAUDE.md (4372B)
1 # ppad-bolt2 2 3 Haskell implementation of BOLT #2 (Lightning Network peer protocol). 4 5 Specification: https://github.com/lightning/bolts/blob/master/02-peer-protocol.md 6 7 ## Project Structure 8 9 - `lib/` - library source (Lightning.Protocol.BOLT2) 10 - `test/` - tests (tasty + tasty-hunit) 11 - `bench/` - benchmarks (criterion for timing, weigh for allocations) 12 - `etc/` - reference materials (BOLT spec) 13 - `flake.nix` - nix flake for dependency and build management 14 - `ppad-bolt2.cabal` - cabal package definition 15 - `CLAUDE.md` / `AGENTS.md` - keep these in sync 16 17 ## Build and Test 18 19 Enter devshell and use cabal: 20 21 ``` 22 nix develop 23 cabal build 24 cabal test 25 cabal bench 26 ``` 27 28 Do not use stack. All dependency and build management via nix. 29 30 ## Dependencies 31 32 ### ppad libraries (use freely) 33 34 Use ppad libraries (github.com/ppad-tech, git.ppad.tech) liberally. 35 Current dependencies: ppad-bolt1 (for primitive encoding/decoding, TLV), 36 ppad-tx (for TxId and OutPoint types). 37 38 ### External libraries 39 40 Use only minimal external dependencies. Prefer GHC's core/boot libraries 41 (base, bytestring, primitive, etc.). 42 43 **Ask for explicit confirmation before adding any library outside of:** 44 - GHC boot/core libraries 45 - ppad-* libraries 46 - Test dependencies (tasty, QuickCheck, etc. for test-suite only) 47 - Benchmark dependencies (criterion, weigh for benchmark only) 48 49 ## Code Style 50 51 ### Performance 52 53 - Use strictness annotations (BangPatterns) liberally 54 - Prefer UNPACK for strict record fields 55 - Use MagicHash, UnboxedTuples, GHC.Exts for hot paths 56 - Do not rely on UNBOX pragmas; implement primitives directly with 57 MagicHash and GHC.Exts when needed 58 - Use INLINE pragmas for small functions 59 - Refer to ppad-sha256 and ppad-fixed for low-level patterns 60 61 ### Type safety 62 63 - Encode invariants into the type system 64 - Use newtypes liberally (e.g., ChannelId, Satoshis, Signature) 65 - Use ADTs to make illegal states unrepresentable 66 - Prefer smart constructors that validate inputs 67 68 ### Safety 69 70 - Never use partial Prelude functions (head, tail, !!, etc.) 71 - Avoid brittle partials in tests too (e.g., unchecked indexing). Prefer 72 bounds checks or total helpers even in test code. 73 - Avoid non-exhaustive pattern matches and unsafe behavior; use total 74 helpers and make all constructors explicit. 75 - Use Maybe/Either for fallible operations 76 - Validate all inputs at system boundaries 77 78 ### Formatting 79 80 - Keep lines under 80 characters 81 - Use Haskell2010 82 - Module header with copyright, license, maintainer 83 - OPTIONS_HADDOCK prune for public modules 84 - Haddock examples for exported functions 85 86 ## Testing 87 88 Use tasty to wrap all tests: 89 - tasty-hunit for unit tests with known vectors 90 - tasty-quickcheck for property-based tests 91 - Source test vectors from specifications (RFC, BOLT spec, Wycheproof, etc.) 92 93 Property tests should enforce invariants that can't be encoded in types. 94 95 ## Benchmarking 96 97 Always maintain benchmark suites: 98 - `bench/Main.hs` - criterion for wall-time benchmarks 99 - `bench/Weight.hs` - weigh for allocation tracking 100 101 Define NFData instances for types that need benchmarking. 102 103 ## Git Workflow 104 105 - Feature branches for development; commit freely there 106 - Logical, atomic commits on feature branches 107 - Master should be mostly merge commits 108 - Merge to master with `--no-ff` after validation 109 - Always build and test before creating a merge commit 110 - Write detailed merge commit messages summarising changes 111 112 ### Worktree flow (for planned work) 113 114 When starting work on an implementation plan: 115 116 ``` 117 git worktree add ./impl-<desc> -b impl/<desc> master 118 # work in that worktree 119 # merge to master when complete 120 git worktree remove ./impl-<desc> 121 ``` 122 123 ### Commits 124 125 - Higher-level descriptions in merge commits 126 - Never update git config 127 - Never use destructive git commands (push --force, hard reset) without 128 explicit request 129 - Never skip hooks unless explicitly requested 130 131 ## Planning 132 133 When planning work: 134 - Highlight which steps can be done independently 135 - Consider forking subagents for concurrent work on independent steps 136 - Write implementation plans to `plans/IMPL<n>.md` if the project uses 137 this convention 138 - Record outstanding design decisions and deferred work to `plans/TODO` 139 140 ## Flake Structure 141 142 The flake.nix follows ppad conventions: 143 - Uses ppad-nixpkgs as base 144 - Follows references to avoid duplication 145 - Supports LLVM backend via cabal flag 146 - Provides devShell with ghc, cabal, cc, llvm