Skip to content
ppad-techPublic

About

Lightning peer protocol.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

ppad-bolt2

A pure Haskell implementation of the Lightning Network peer protocol, BOLT #2: the messages for channel establishment (v1 and v2), interactive transaction construction, quiescence, channel close, normal operation and message retransmission, with their wire codecs.

Usage

A sample GHCi session:

  > :set -XOverloadedStrings
  > import qualified Data.ByteString as BS
  > import qualified Lightning.Protocol.BOLT1 as BOLT1
  > import Lightning.Protocol.BOLT2
  >
  > -- a channel_ready carrying an scid alias (a typed TLV record)
  > let Just cid   = BOLT1.channel_id (BS.replicate 32 0xab)
  > let Just point = BOLT1.point (BS.cons 0x02 (BS.replicate 32 0x11))
  > let alias      = BOLT1.short_channel_id 539268 845 1
  > let ready      = ChannelReady cid point alias BOLT1.empty_tlv_stream
  > let Right wire = encode_message (MsgChannelReady ready)
  > BS.length wire
  77
  > decode_message wire == Right (MsgChannelReady ready)
  True
  >
  > -- unknown odd TLV records are kept, so re-encoding is exact
  > let payload = BS.drop 2 wire
  > let Right ext = decode_channel_ready (payload <> "\x2b\x01\x2a")
  > channel_ready_tlvs ext
  TlvStream [TlvRecord {tlv_type = 43, tlv_value = "*"}]
  > encode_channel_ready ext == Right (payload <> "\x2b\x01\x2a")
  True
  >
  > -- unknown even records and malformed known ones are rejected
  > decode_channel_ready (payload <> "\x2a\x00")
  Left (DecodeTlvError (TlvUnknownEvenType 42))
  > let fixed = BS.take 65 payload
  > decode_channel_ready (fixed <> "\x01\x07" <> BS.replicate 7 0x00)
  Left (DecodeInvalidTlvValue 1)
  >
  > -- messages from other BOLTs (or splicing) aren't BOLT #2's
  > decode_message ("\x00\x50" <> payload)
  Left (DecodeUnknownEvenType 80)

Documentation

Haddocks (API documentation, etc.) are hosted at docs.ppad.tech/bolt2.

Specification

This library implements BOLT #2 as of lightning/bolts commit 1aadb719 (2026-09-21); a copy lives in etc/.

Fundamental types and the TLV format come from ppad-bolt1, transaction ids from ppad-tx, and channel_type feature vectors from ppad-bolt9. Every TLV record the specification defines outside of splicing has a typed field; unknown odd records are kept.

Not implemented:

  • Splicing: the splice_init, splice_ack and splice_locked messages, and the splicing-only TLV records. tx_add_input's shared_input_txid and tx_signatures' shared_input_signature are rejected as unknown even types; channel_reestablish's my_current_funding_locked is kept as an unknown odd record.
  • The start_batch message.
  • Channel-level validation: the library checks what decoding needs (field lengths, point prefixes, amounts of at most 21M BTC, TLV rules), and leaves rules that depend on channel state or negotiated features (reserves, feerates, shutdown script forms, serial_id parity, required TLV records, points being on the curve, etc.) to the caller.
  • Interpretation of the onion routing packet and attribution data, which are kept opaque (see BOLT #4).

Performance

The aim is best-in-class performance for pure Haskell code. Run the benchmarks with:

$ cabal bench

Security

This library has received no security audit. It decodes strictly: every message must be consumed exactly, unknown even TLV records are rejected, and encoding a decoded message reproduces its bytes.

Development

You'll require Nix with flake support enabled. Enter a development shell with:

$ nix develop

Then do e.g.:

$ cabal repl ppad-bolt2

to get a REPL for the main library.

About

Lightning peer protocol.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages