bolt9

Lightning feature flags, per BOLT #9 (docs.ppad.tech/bolt9).
git clone git://git.ppad.tech/bolt9.git
Log | Files | Refs | README | LICENSE

commit fd0e1329a1cce2e437a081fa59b5fbee06ac2f08
parent 710798bbc64d9aad92da076b5a56896a53fbd847
Author: Jared Tobin <jared@jtobin.io>
Date:   Sat, 10 Oct 2026 13:28:21 +0400

bench: cover the new API

Benchmarks union, bit and feature operations, validation (including a
maximum-length vector) and channel types.

Diffstat:
Mbench/Fixtures.hs | 71+++++++++++++++++++++++++----------------------------------------------
Mbench/Main.hs | 56+++++++++++++++++++++++++++++++-------------------------
Mbench/Weight.hs | 25+++++++++++--------------
3 files changed, 67 insertions(+), 85 deletions(-)

diff --git a/bench/Fixtures.hs b/bench/Fixtures.hs @@ -1,57 +1,36 @@ module Fixtures ( - -- * ByteString fixtures - typicalBytes - , emptyBytes - , largeBytes - - -- * FeatureVector fixtures - , typicalFV - , emptyFV - , validFV - , unknownBitsFV + typical + , padded + , large + , maximal + , zeroconf_type + , zeroconf_type_features ) where -import Data.ByteString (ByteString) import qualified Data.ByteString as BS import qualified Lightning.Protocol.BOLT9 as B9 --- ByteString fixtures -------------------------------------------------------- - --- | A typical 8-byte feature vector with several common features set: --- basic_mpp (bit 17), option_anchors (bit 23), option_route_blinding (bit 25) -typicalBytes :: ByteString -typicalBytes = BS.pack [0x02, 0x82, 0x00, 0x00] - --- | Empty ByteString for parsing. -emptyBytes :: ByteString -emptyBytes = BS.empty - --- | Large 64-byte feature vector for stress testing. -largeBytes :: ByteString -largeBytes = BS.pack $ replicate 64 0xAA +-- | An init feature vector of the sort deployed nodes send (8 bytes). +typical :: B9.FeatureVector +typical = foldr B9.set_bit B9.empty + [1, 5, 7, 8, 11, 12, 14, 17, 23, 25, 27, 35, 39, 45, 47, 51, 61] --- FeatureVector fixtures ----------------------------------------------------- +-- | 'typical' with four leading zero bytes. +padded :: B9.FeatureVector +padded = B9.parse (BS.replicate 4 0 <> B9.render typical) --- | A typical feature vector with common features set (optional bits): --- basic_mpp (17), option_anchors (23), option_route_blinding (25) -typicalFV :: B9.FeatureVector -typicalFV = B9.parse typicalBytes +-- | 64 bytes with every odd bit set. +large :: B9.FeatureVector +large = B9.parse (BS.replicate 64 0xAA) --- | Empty feature vector. -emptyFV :: B9.FeatureVector -emptyFV = B9.empty +-- | A maximum-length (65535-byte) vector with every bit set. +maximal :: B9.FeatureVector +maximal = B9.parse (BS.replicate 65535 0xFF) --- | A valid feature vector for validation benchmarks. --- Sets payment_secret (required for basic_mpp dependency) and basic_mpp. -validFV :: B9.FeatureVector -validFV = B9.setBit 15 -- payment_secret (optional) - $ B9.setBit 17 -- basic_mpp (optional) - $ B9.setBit 23 -- option_anchors (optional) - $ B9.empty +-- | An anchors channel type with both variations. +zeroconf_type :: B9.ChannelType +zeroconf_type = B9.ChannelType B9.BasicAnchors True True --- | A feature vector with unknown bits for remote validation. --- Contains a known feature plus an unknown odd bit (safe to ignore). -unknownBitsFV :: B9.FeatureVector -unknownBitsFV = B9.setBit 15 -- payment_secret (optional, known) - $ B9.setBit 99 -- unknown odd bit (should be ignored) - $ B9.empty +-- | The vector for 'zeroconf_type'. +zeroconf_type_features :: B9.FeatureVector +zeroconf_type_features = B9.channel_type_features zeroconf_type diff --git a/bench/Main.hs b/bench/Main.hs @@ -1,42 +1,48 @@ module Main where import Criterion.Main -import Data.Maybe (fromJust) import qualified Lightning.Protocol.BOLT9 as B9 import Fixtures -basic_mpp :: B9.Feature -basic_mpp = fromJust (B9.featureByName "basic_mpp") - main :: IO () main = defaultMain [ - bgroup "parse" [ - bench "typical (8 bytes)" $ nf B9.parse typicalBytes - , bench "empty" $ nf B9.parse emptyBytes - , bench "large (64 bytes)" $ nf B9.parse largeBytes - ] - - , bgroup "render" [ - bench "typical" $ nf B9.render typicalFV - , bench "empty" $ nf B9.render emptyFV + bgroup "vector" [ + bench "union" $ nf (B9.union typical) large + , bench "set_bit" $ nf (B9.set_bit 101) typical + , bench "clear_bit" $ nf (B9.clear_bit 17) typical + , bench "test_bit" $ nf (B9.test_bit 17) typical + , bench "set_bits" $ nf B9.set_bits typical + , bench "== (leading zeros)" $ nf (== typical) padded ] - , bgroup "bit-ops" [ - bench "setBit" $ nf (B9.setBit 50) typicalFV - , bench "testBit" $ nf (B9.testBit 17) typicalFV - , bench "hasFeature" $ - nf (flip B9.hasFeature typicalFV) basic_mpp + , bgroup "feature" [ + bench "set_feature" $ + nf (B9.set_feature B9.OptionSplice B9.Optional) typical + , bench "set_feature_with_deps" $ + nf (B9.set_feature_with_deps B9.OptionZeroconf B9.Optional) + B9.empty + , bench "test_feature" $ nf (B9.test_feature B9.BasicMpp) typical + , bench "list_features" $ nf B9.list_features typical + , bench "feature_by_bit" $ nf B9.feature_by_bit 51 ] , bgroup "validate" [ - bench "validateLocal (valid)" $ - nf (B9.validateLocal B9.Init) validFV - , bench "validateRemote (unknown bits)" $ - nf (B9.validateRemote B9.Init) unknownBitsFV + bench "validate_local (init)" $ + nf (B9.validate_local B9.InitContext) typical + , bench "validate_remote (init)" $ + nf (B9.validate_remote B9.InitContext) typical + , bench "validate_remote (init, 64 bytes)" $ + nf (B9.validate_remote B9.InitContext) large + , bench "validate_remote (init, 65535 bytes)" $ + nf (B9.validate_remote B9.InitContext) maximal + , bench "validate_remote (channel_type)" $ + nf (B9.validate_remote B9.ChannelTypeContext) + zeroconf_type_features ] - , bgroup "lookup" [ - bench "featureByBit" $ nf B9.featureByBit 16 - , bench "featureByName" $ nf B9.featureByName "basic_mpp" + , bgroup "channel type" [ + bench "channel_type" $ nf B9.channel_type zeroconf_type_features + , bench "channel_type_features" $ + nf B9.channel_type_features zeroconf_type ] ] diff --git a/bench/Weight.hs b/bench/Weight.hs @@ -1,21 +1,18 @@ module Main where -import Weigh import qualified Lightning.Protocol.BOLT9 as B9 +import Weigh import Fixtures main :: IO () main = mainWith $ do - func "FeatureVector (5 features)" mkFiveFeatures () - func "validateLocal" (B9.validateLocal B9.Init) validFV - func "listFeatures" B9.listFeatures validFV - --- | Create a FeatureVector with 5 features set. -mkFiveFeatures :: () -> B9.FeatureVector -mkFiveFeatures _ = - B9.setBit 15 -- payment_secret - $ B9.setBit 17 -- basic_mpp - $ B9.setBit 23 -- option_anchors - $ B9.setBit 25 -- option_route_blinding - $ B9.setBit 27 -- option_shutdown_anysegwit - $ B9.empty + func "union" (B9.union typical) large + func "set_feature" (B9.set_feature B9.OptionSplice B9.Optional) typical + func "set_feature_with_deps" + (B9.set_feature_with_deps B9.OptionZeroconf B9.Optional) B9.empty + func "list_features" B9.list_features typical + func "validate_local (init)" (B9.validate_local B9.InitContext) typical + func "validate_remote (init)" (B9.validate_remote B9.InitContext) typical + func "validate_remote (init, 64 bytes)" + (B9.validate_remote B9.InitContext) large + func "channel_type" B9.channel_type zeroconf_type_features