bolt7

Routing gossip protocol, per BOLT #7 (docs.ppad.tech/bolt7).
git clone git://git.ppad.tech/bolt7.git
Log | Files | Refs | README | LICENSE

README.md (4804B)


      1 # ppad-bolt7
      2 
      3 [![](https://img.shields.io/hackage/v/ppad-bolt7?color=blue)](https://hackage.haskell.org/package/ppad-bolt7)
      4 ![](https://img.shields.io/badge/license-MIT-brightgreen)
      5 [![](https://img.shields.io/badge/haddock-bolt7-lightblue)](https://docs.ppad.tech/bolt7)
      6 
      7 A pure Haskell implementation of Lightning Network routing gossip,
      8 [BOLT #7][bolt7]: the `channel_announcement`, `node_announcement`,
      9 `channel_update` and `announcement_signatures` messages, the gossip
     10 queries, signature digests and verification, and `channel_update`
     11 checksums.
     12 
     13 Decoding keeps every byte of a message (unassigned flag bits, unknown
     14 address descriptors, extension TLV records), so a decoded message
     15 re-encodes exactly and its signatures still verify.
     16 
     17 ## Usage
     18 
     19 A sample GHCi session:
     20 
     21 ```
     22   > :set -XOverloadedStrings
     23   > import qualified Data.ByteString as BS
     24   > import qualified Data.ByteString.Base16 as B16
     25   > import qualified Lightning.Protocol.BOLT1 as BOLT1
     26   > import Lightning.Protocol.BOLT7
     27   >
     28   > -- a channel_update payload from mainnet gossip
     29   > :{
     30   | let Just wire = B16.decode $ mconcat
     31   |       [ "1c3f0859cb3f4494919c3dcc80d22bbf1e25e378bd95f071530833c2371c33d7"
     32   |       , "0766012ebef1cd79b299a54d0d29bea2ef6feca1d6cfa188864c95d7eea7e9a4"
     33   |       , "6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000"
     34   |       , "0cf884000bb000016a0a1c760100006400000000000003e80000000000001388"
     35   |       , "00000000b1069a80fdd9030800000000ffffffed" ]
     36   | :}
     37   > let Right upd = decode_channel_update wire
     38   > format_short_channel_id (cu_short_channel_id upd)
     39   "850052x2992x1"
     40   > channel_flags_direction (cu_channel_flags upd)
     41   NodeOne
     42   > cu_fee_proportional_millionths upd
     43   5000
     44   >
     45   > -- extension records (here LND's inbound fees) are kept, so the
     46   > -- update re-encodes exactly and its signature verifies
     47   > BOLT1.un_tlv_stream (cu_tlvs upd)
     48   [TlvRecord {tlv_type = 55555, tlv_value = "\NUL\NUL\NUL\NUL\255\255\255\237"}]
     49   > encode_channel_update upd == wire
     50   True
     51   > :{
     52   | let Just node_1 = BOLT1.point =<< B16.decode
     53   |       "02bb5e47ee26aca1654ce092d9d06eac15d953210c737f2220e2d7e54c4f108677"
     54   | :}
     55   > verify_channel_update node_1 upd
     56   True
     57   > verify_channel_update node_1 upd { cu_fee_base_msat = 1 }
     58   False
     59   >
     60   > -- dispatch on a message type, as split off by BOLT1.decode_envelope
     61   > fmap message_type (decode_message 258 wire)
     62   Right 258
     63   >
     64   > -- gossip queries have typed fields
     65   > let Just chain = BOLT1.chain_hash (BS.replicate 32 0)
     66   > let opt = Just (query_option [WantTimestamps])
     67   > let q = QueryChannelRange chain 800000 1000 opt BOLT1.empty_tlv_stream
     68   > let Right payload = encode_query_channel_range q
     69   > decode_query_channel_range payload == Right q
     70   True
     71   >
     72   > -- the deprecated zlib encoding is rejected
     73   > decode_reply_channel_range (BS.replicate 41 0 <> "\NUL\STX\SOHx")
     74   Left (DecodeUnknownEncoding 1)
     75 ```
     76 
     77 ## Documentation
     78 
     79 Haddocks (API documentation, etc.) are hosted at
     80 [docs.ppad.tech/bolt7](https://docs.ppad.tech/bolt7).
     81 
     82 ## Specification
     83 
     84 This library implements BOLT #7 as of lightning/bolts commit
     85 [1aadb719][spec] (2026-09-21); a copy lives in `etc/`. Fundamental
     86 types come from [ppad-bolt1][bolt1] and feature vectors from
     87 [ppad-bolt9][bolt9].
     88 
     89 Not implemented:
     90 
     91 * The zlib encoding (type 1) of `encoded_short_ids` and its kin, which
     92   the specification forbids; messages using it fail to decode.
     93 * Signing. The digest functions give what a node signs, with e.g.
     94   [ppad-secp256k1][secp], to create announcements and updates.
     95 * Rules that need state or chain access: timestamp ordering,
     96   blacklisting, funding output checks, chain hash filtering, rebroadcast
     97   and pruning policy. Feature-bit rules are left to ppad-bolt9.
     98 
     99 Checksums cover a `channel_update`'s extension records, per the
    100 specification's wording.
    101 
    102 ## Performance
    103 
    104 The aim is best-in-class performance for pure Haskell code. Run the
    105 benchmarks with:
    106 
    107 ```
    108 $ cabal bench
    109 ```
    110 
    111 ## Security
    112 
    113 This library has received no security audit. Decoding validates every
    114 field the specification constrains, and rejects unknown even TLV types.
    115 Signature verification uses ppad-secp256k1 and, like libsecp256k1,
    116 accepts only low-s signatures.
    117 
    118 ## Development
    119 
    120 You'll require [Nix][nixos] with [flake][flake] support enabled. Enter a
    121 development shell with:
    122 
    123 ```
    124 $ nix develop
    125 ```
    126 
    127 Then do e.g.:
    128 
    129 ```
    130 $ cabal repl ppad-bolt7
    131 ```
    132 
    133 to get a REPL for the main library.
    134 
    135 [bolt7]: https://github.com/lightning/bolts/blob/master/07-routing-gossip.md
    136 [bolt1]: https://git.ppad.tech/bolt1
    137 [bolt9]: https://git.ppad.tech/bolt9
    138 [secp]: https://git.ppad.tech/secp256k1
    139 [spec]: https://github.com/lightning/bolts/tree/1aadb719b4007c4cea0ba6e36b08c4fb53788dee
    140 [nixos]: https://nixos.org/
    141 [flake]: https://nixos.org/manual/nix/unstable/command-ref/new-cli/nix3-flake.html