bolt8

Encrypted and authenticated transport, per BOLT #8.
git clone git://git.ppad.tech/bolt8.git
Log | Files | Refs | README | LICENSE

commit 5c168f3f037616a3c64986d82bb5b0c4f0317d2b
Author: Jared Tobin <jared@jtobin.io>
Date:   Sun, 11 Jan 2026 09:35:45 +0400

lib: initial commit

Diffstat:
A.gitignore | 1+
ACHANGELOG | 0
ALICENSE | 20++++++++++++++++++++
Abench/Main.hs | 4++++
Aflake.lock | 480+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aflake.nix | 105+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/Lightning/Protocol/BOLT8.hs | 4++++
Appad-bolt8.cabal | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atest/Main.hs | 4++++
9 files changed, 685 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1 @@ +dist-newstyle/ diff --git a/CHANGELOG b/CHANGELOG diff --git a/LICENSE b/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2025 Jared Tobin + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/bench/Main.hs b/bench/Main.hs @@ -0,0 +1,4 @@ +module Main where + +main :: IO () +main = pure () diff --git a/flake.lock b/flake.lock @@ -0,0 +1,480 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1725910328, + "narHash": "sha256-n9pCtzGZ0httmTwMuEbi5E78UQ4ZbQMr1pzi5N0LAG8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "5775c2583f1801df7b790bf7f7d710a19bac66f4", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "ppad-aead": { + "inputs": { + "flake-utils": [ + "ppad-aead", + "ppad-nixpkgs", + "flake-utils" + ], + "nixpkgs": [ + "ppad-aead", + "ppad-nixpkgs", + "nixpkgs" + ], + "ppad-base16": "ppad-base16", + "ppad-chacha": "ppad-chacha", + "ppad-nixpkgs": [ + "ppad-nixpkgs" + ], + "ppad-poly1305": "ppad-poly1305" + }, + "locked": { + "lastModified": 1750618428, + "narHash": "sha256-+f/DFAyB6nN89QlQDWbSKPyb6/eYsUiXjp1OZC4Q/7g=", + "ref": "master", + "rev": "55d52287a32462bfad65008771c9949eb9dea0b6", + "revCount": 19, + "type": "git", + "url": "git://git.ppad.tech/aead.git" + }, + "original": { + "ref": "master", + "type": "git", + "url": "git://git.ppad.tech/aead.git" + } + }, + "ppad-base16": { + "inputs": { + "flake-utils": [ + "ppad-aead", + "ppad-base16", + "ppad-nixpkgs", + "flake-utils" + ], + "nixpkgs": [ + "ppad-aead", + "ppad-base16", + "ppad-nixpkgs", + "nixpkgs" + ], + "ppad-nixpkgs": [ + "ppad-aead", + "ppad-nixpkgs" + ] + }, + "locked": { + "lastModified": 1741625558, + "narHash": "sha256-ZBDXRD5fsVqA5bGrAlcnhiu67Eo50q0M9614nR3NBwY=", + "ref": "master", + "rev": "fb63457f2e894eda28250dfe65d0fcd1d195ac2f", + "revCount": 24, + "type": "git", + "url": "git://git.ppad.tech/base16.git" + }, + "original": { + "ref": "master", + "type": "git", + "url": "git://git.ppad.tech/base16.git" + } + }, + "ppad-base16_2": { + "inputs": { + "flake-utils": [ + "ppad-secp256k1", + "ppad-base16", + "ppad-nixpkgs", + "flake-utils" + ], + "nixpkgs": [ + "ppad-secp256k1", + "ppad-base16", + "ppad-nixpkgs", + "nixpkgs" + ], + "ppad-nixpkgs": [ + "ppad-secp256k1", + "ppad-nixpkgs" + ] + }, + "locked": { + "lastModified": 1741625558, + "narHash": "sha256-ZBDXRD5fsVqA5bGrAlcnhiu67Eo50q0M9614nR3NBwY=", + "ref": "master", + "rev": "fb63457f2e894eda28250dfe65d0fcd1d195ac2f", + "revCount": 24, + "type": "git", + "url": "git://git.ppad.tech/base16.git" + }, + "original": { + "ref": "master", + "type": "git", + "url": "git://git.ppad.tech/base16.git" + } + }, + "ppad-base16_3": { + "inputs": { + "flake-utils": [ + "ppad-sha256", + "ppad-base16", + "ppad-nixpkgs", + "flake-utils" + ], + "nixpkgs": [ + "ppad-sha256", + "ppad-base16", + "ppad-nixpkgs", + "nixpkgs" + ], + "ppad-nixpkgs": [ + "ppad-sha256", + "ppad-nixpkgs" + ] + }, + "locked": { + "lastModified": 1741625558, + "narHash": "sha256-ZBDXRD5fsVqA5bGrAlcnhiu67Eo50q0M9614nR3NBwY=", + "ref": "master", + "rev": "fb63457f2e894eda28250dfe65d0fcd1d195ac2f", + "revCount": 24, + "type": "git", + "url": "git://git.ppad.tech/base16.git" + }, + "original": { + "ref": "master", + "type": "git", + "url": "git://git.ppad.tech/base16.git" + } + }, + "ppad-chacha": { + "inputs": { + "flake-utils": [ + "ppad-aead", + "ppad-chacha", + "ppad-nixpkgs", + "flake-utils" + ], + "nixpkgs": [ + "ppad-aead", + "ppad-chacha", + "ppad-nixpkgs", + "nixpkgs" + ], + "ppad-base16": [ + "ppad-aead", + "ppad-base16" + ], + "ppad-nixpkgs": [ + "ppad-aead", + "ppad-nixpkgs" + ] + }, + "locked": { + "lastModified": 1750501666, + "narHash": "sha256-vIZrbi7ozlsZ0yMUxz7BAX7KsgTvsWS+MfCJEfGxu+o=", + "ref": "master", + "rev": "9adca9651d3098b8fa2ce48f663c5ac6105dc90e", + "revCount": 20, + "type": "git", + "url": "git://git.ppad.tech/chacha.git" + }, + "original": { + "ref": "master", + "type": "git", + "url": "git://git.ppad.tech/chacha.git" + } + }, + "ppad-hmac-drbg": { + "inputs": { + "flake-utils": [ + "ppad-secp256k1", + "ppad-hmac-drbg", + "ppad-nixpkgs", + "flake-utils" + ], + "nixpkgs": [ + "ppad-secp256k1", + "ppad-hmac-drbg", + "ppad-nixpkgs", + "nixpkgs" + ], + "ppad-nixpkgs": [ + "ppad-secp256k1", + "ppad-nixpkgs" + ], + "ppad-sha256": [ + "ppad-secp256k1", + "ppad-sha256" + ], + "ppad-sha512": [ + "ppad-secp256k1", + "ppad-sha512" + ] + }, + "locked": { + "lastModified": 1740802952, + "narHash": "sha256-rYWQAzoXmxWQqBA2iPiRkSnb3xDjDt5aq3Fe0UyoS38=", + "ref": "master", + "rev": "567288a1f3a558a69a6ee10a26e44f00310692f9", + "revCount": 51, + "type": "git", + "url": "git://git.ppad.tech/hmac-drbg.git" + }, + "original": { + "ref": "master", + "type": "git", + "url": "git://git.ppad.tech/hmac-drbg.git" + } + }, + "ppad-nixpkgs": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1737297101, + "narHash": "sha256-EnXnq+JLflbWt+DvaGGnY2gfAqsGNOm5vPgHh3hkfwQ=", + "ref": "master", + "rev": "f29823875250bc99b3891f7373535ccde9a29a44", + "revCount": 1, + "type": "git", + "url": "git://git.ppad.tech/nixpkgs.git" + }, + "original": { + "ref": "master", + "type": "git", + "url": "git://git.ppad.tech/nixpkgs.git" + } + }, + "ppad-poly1305": { + "inputs": { + "flake-utils": [ + "ppad-aead", + "ppad-poly1305", + "ppad-nixpkgs", + "flake-utils" + ], + "nixpkgs": [ + "ppad-aead", + "ppad-poly1305", + "ppad-nixpkgs", + "nixpkgs" + ], + "ppad-base16": [ + "ppad-aead", + "ppad-base16" + ], + "ppad-nixpkgs": [ + "ppad-aead", + "ppad-nixpkgs" + ] + }, + "locked": { + "lastModified": 1750502056, + "narHash": "sha256-0KJgniap/pyKsEvTh2SgA/D4zzX194P/oAzJv3fSVdM=", + "ref": "master", + "rev": "9a67f66c8d0a9292aa5b86a620be6c4d8c7d66d2", + "revCount": 17, + "type": "git", + "url": "git://git.ppad.tech/poly1305.git" + }, + "original": { + "ref": "master", + "type": "git", + "url": "git://git.ppad.tech/poly1305.git" + } + }, + "ppad-secp256k1": { + "inputs": { + "flake-utils": [ + "ppad-secp256k1", + "ppad-nixpkgs", + "flake-utils" + ], + "nixpkgs": [ + "ppad-secp256k1", + "ppad-nixpkgs", + "nixpkgs" + ], + "ppad-base16": "ppad-base16_2", + "ppad-hmac-drbg": "ppad-hmac-drbg", + "ppad-nixpkgs": [ + "ppad-nixpkgs" + ], + "ppad-sha256": "ppad-sha256", + "ppad-sha512": "ppad-sha512" + }, + "locked": { + "lastModified": 1750737058, + "narHash": "sha256-sf9Rvd+wMZu1r530O+TkKj8RCwQxU+2ZUgFnEIQhFtY=", + "ref": "master", + "rev": "45e61f28b444664fda12222b2e32b54901907194", + "revCount": 176, + "type": "git", + "url": "git://git.ppad.tech/secp256k1.git" + }, + "original": { + "ref": "master", + "type": "git", + "url": "git://git.ppad.tech/secp256k1.git" + } + }, + "ppad-sha256": { + "inputs": { + "flake-utils": [ + "ppad-secp256k1", + "ppad-sha256", + "ppad-nixpkgs", + "flake-utils" + ], + "nixpkgs": [ + "ppad-secp256k1", + "ppad-sha256", + "ppad-nixpkgs", + "nixpkgs" + ], + "ppad-nixpkgs": [ + "ppad-secp256k1", + "ppad-nixpkgs" + ] + }, + "locked": { + "lastModified": 1740802974, + "narHash": "sha256-GTD9UrxwMa5zY7hxzDSXjKXKUwMK4r3FBHLG0nvgapk=", + "ref": "master", + "rev": "ab0957e305dff0243dcab11e381470585849fd20", + "revCount": 94, + "type": "git", + "url": "git://git.ppad.tech/sha256.git" + }, + "original": { + "ref": "master", + "type": "git", + "url": "git://git.ppad.tech/sha256.git" + } + }, + "ppad-sha256_2": { + "inputs": { + "flake-utils": [ + "ppad-sha256", + "ppad-nixpkgs", + "flake-utils" + ], + "nixpkgs": [ + "ppad-sha256", + "ppad-nixpkgs", + "nixpkgs" + ], + "ppad-base16": "ppad-base16_3", + "ppad-nixpkgs": [ + "ppad-nixpkgs" + ] + }, + "locked": { + "lastModified": 1750583530, + "narHash": "sha256-elc+wo2v26SW9WWqZ+36nlrEHTCIotUbbPU0eeMaKLc=", + "ref": "master", + "rev": "282fa90825bbc04c324c58186da473cb380d0fc2", + "revCount": 95, + "type": "git", + "url": "git://git.ppad.tech/sha256.git" + }, + "original": { + "ref": "master", + "type": "git", + "url": "git://git.ppad.tech/sha256.git" + } + }, + "ppad-sha512": { + "inputs": { + "flake-utils": [ + "ppad-secp256k1", + "ppad-sha512", + "ppad-nixpkgs", + "flake-utils" + ], + "nixpkgs": [ + "ppad-secp256k1", + "ppad-sha512", + "ppad-nixpkgs", + "nixpkgs" + ], + "ppad-nixpkgs": [ + "ppad-secp256k1", + "ppad-nixpkgs" + ] + }, + "locked": { + "lastModified": 1740802979, + "narHash": "sha256-6VAXmA1XiIT/WFcP+eFb6uK3YyfgVqIgDv3ASNIoCMs=", + "ref": "master", + "rev": "ff165b29fb21b99749460ae7e3fdca42a85c822b", + "revCount": 28, + "type": "git", + "url": "git://git.ppad.tech/sha512.git" + }, + "original": { + "ref": "master", + "type": "git", + "url": "git://git.ppad.tech/sha512.git" + } + }, + "root": { + "inputs": { + "flake-utils": [ + "ppad-nixpkgs", + "flake-utils" + ], + "nixpkgs": [ + "ppad-nixpkgs", + "nixpkgs" + ], + "ppad-aead": "ppad-aead", + "ppad-nixpkgs": "ppad-nixpkgs", + "ppad-secp256k1": "ppad-secp256k1", + "ppad-sha256": "ppad-sha256_2" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix @@ -0,0 +1,105 @@ +{ + description = "A Haskell implementation of BOLT #8."; + + inputs = { + ppad-aead = { + type = "git"; + url = "git://git.ppad.tech/aead.git"; + ref = "master"; + inputs.ppad-nixpkgs.follows = "ppad-nixpkgs"; + }; + ppad-secp256k1 = { + type = "git"; + url = "git://git.ppad.tech/secp256k1.git"; + ref = "master"; + inputs.ppad-nixpkgs.follows = "ppad-nixpkgs"; + inputs.ppad-sha256.follows = "ppad-sha256"; + }; + ppad-sha256 = { + type = "git"; + url = "git://git.ppad.tech/sha256.git"; + ref = "master"; + inputs.ppad-nixpkgs.follows = "ppad-nixpkgs"; + }; + ppad-nixpkgs = { + type = "git"; + url = "git://git.ppad.tech/nixpkgs.git"; + ref = "master"; + }; + flake-utils.follows = "ppad-nixpkgs/flake-utils"; + nixpkgs.follows = "ppad-nixpkgs/nixpkgs"; + }; + + outputs = { self, nixpkgs, flake-utils, ppad-nixpkgs + , ppad-aead, ppad-secp256k1, ppad-sha256 + }: + flake-utils.lib.eachDefaultSystem (system: + let + lib = "ppad-bolt8"; + + pkgs = import nixpkgs { inherit system; }; + hlib = pkgs.haskell.lib; + llvm = pkgs.llvmPackages_19.llvm; + clang = pkgs.llvmPackages_19.clang; + + aead = ppad-aead.packages.${system}.default; + aead-llvm = + hlib.addBuildTools + (hlib.enableCabalFlag aead "llvm") + [ llvm clang ]; + + secp256k1 = ppad-secp256k1.packages.${system}.default; + secp256k1-llvm = + hlib.addBuildTools + (hlib.enableCabalFlag secp256k1 "llvm") + [ llvm clang ]; + + sha256 = ppad-sha256.packages.${system}.default; + sha256-llvm = + hlib.addBuildTools + (hlib.enableCabalFlag sha256 "llvm") + [ llvm clang ]; + + hpkgs = pkgs.haskell.packages.ghc910.extend (new: old: { + ppad-aead = aead-llvm; + ppad-secp256k1 = secp256k1-llvm; + ppad-sha256 = sha256-llvm; + ${lib} = new.callCabal2nix lib ./. { + ppad-aead = new.ppad-aead; + ppad-secp256k1 = new.ppad-secp256k1; + ppad-sha256 = new.ppad-sha256; + }; + }); + + cc = pkgs.stdenv.cc; + ghc = hpkgs.ghc; + cabal = hpkgs.cabal-install; + in + { + packages.default = hpkgs.${lib}; + + packages.haddock = hpkgs.${lib}.doc; + + devShells.default = hpkgs.shellFor { + packages = p: [ + (hlib.doBenchmark p.${lib}) + ]; + + buildInputs = [ + cabal + cc + llvm + ]; + + shellHook = '' + PS1="[${lib}] \w$ " + echo "entering ${system} shell, using" + echo "cc: $(${cc}/bin/cc --version)" + echo "ghc: $(${ghc}/bin/ghc --version)" + echo "cabal: $(${cabal}/bin/cabal --version)" + ''; + }; + } + ); +} + diff --git a/lib/Lightning/Protocol/BOLT8.hs b/lib/Lightning/Protocol/BOLT8.hs @@ -0,0 +1,4 @@ + +module Lightning.Protocol.BOLT8 where + + diff --git a/ppad-bolt8.cabal b/ppad-bolt8.cabal @@ -0,0 +1,67 @@ +cabal-version: 3.0 +name: ppad-bolt8 +version: 0.2.0 +synopsis: Encrypted and authenticated transport per BOLT #8 +license: MIT +license-file: LICENSE +author: Jared Tobin +maintainer: jared@ppad.tech +category: Cryptography +build-type: Simple +tested-with: GHC == 9.8.1 +extra-doc-files: CHANGELOG +description: + Encrypted and authenticated transport, per + [BOLT #8](https://github.com/lightning/bolts/blob/master/08-transport.md). + +source-repository head + type: git + location: git.ppad.tech/bolt8.git + +library + default-language: Haskell2010 + hs-source-dirs: lib + ghc-options: + -Wall + exposed-modules: + Lightning.Protocol.BOLT8 + build-depends: + base >= 4.9 && < 5 + , bytestring >= 0.9 && < 0.13 + , ppad-aead >= 0.2 && < 0.3 + , ppad-secp256k1 >= 0.4 && < 0.5 + , ppad-sha256 >= 0.2 && < 0.3 + +test-suite bolt8-tests + type: exitcode-stdio-1.0 + default-language: Haskell2010 + hs-source-dirs: test + main-is: Main.hs + + ghc-options: + -rtsopts -Wall -O2 + + build-depends: + base + , bytestring + , ppad-bolt8 + , tasty + , tasty-hunit + , text + +benchmark bolt8-bench + type: exitcode-stdio-1.0 + default-language: Haskell2010 + hs-source-dirs: bench + main-is: Main.hs + + ghc-options: + -rtsopts -O2 -Wall + + build-depends: + base + , bytestring + , criterion + , deepseq + , ppad-bolt8 + diff --git a/test/Main.hs b/test/Main.hs @@ -0,0 +1,4 @@ +module Main where + +main :: IO () +main = pure ()