commit 5c168f3f037616a3c64986d82bb5b0c4f0317d2b
Author: Jared Tobin <jared@jtobin.io>
Date: Sun, 11 Jan 2026 09:35:45 +0400
lib: initial commit
Diffstat:
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 ()