commit f206f2b3870a44a6b8592edbcb681fb0902f0cca
parent f2ac5cfa92776112fe03cf08487633e203e6eeeb
Author: Jared Tobin <jared@jtobin.io>
Date: Sun, 25 Jan 2026 15:36:16 +0400
Merge impl/bench: Phase 7 complete benchmarks
Add comprehensive benchmark coverage for all BOLT #7 operations:
Criterion timing benchmarks (bench/Main.hs):
- All 9 message types: encode/decode
- SCID list encoding/decoding (100 items)
- Hash functions: channelAnnouncementHash, nodeAnnouncementHash,
channelUpdateHash, channelUpdateChecksum
- Validation functions for all message types
Weigh allocation benchmarks (bench/Weight.hs):
- All message types: construct/encode/decode
- SCID list encoding/decoding
- Hash functions
- Validation functions
Diffstat:
| M | bench/Main.hs | | | 164 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- |
| M | bench/Weight.hs | | | 154 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- |
2 files changed, 310 insertions(+), 8 deletions(-)
diff --git a/bench/Main.hs b/bench/Main.hs
@@ -63,14 +63,14 @@ testChannelId = case channelId zeroBytes32 of
Nothing -> error "testChannelId: invalid"
{-# NOINLINE testChannelId #-}
--- | 33-byte node ID.
+-- | 33-byte node ID (03 prefix).
testNodeId :: NodeId
testNodeId = case nodeId (BS.cons 0x03 zeroBytes32) of
Just n -> n
Nothing -> error "testNodeId: invalid"
{-# NOINLINE testNodeId #-}
--- | Second node ID.
+-- | Second node ID (02 prefix, lexicographically smaller).
testNodeId2 :: NodeId
testNodeId2 = case nodeId (BS.cons 0x02 zeroBytes32) of
Just n -> n
@@ -91,6 +91,13 @@ testAlias = case alias zeroBytes32 of
Nothing -> error "testAlias: invalid"
{-# NOINLINE testAlias #-}
+-- | IPv4 address.
+testIPv4 :: IPv4Addr
+testIPv4 = case ipv4Addr (BS.pack [127, 0, 0, 1]) of
+ Just a -> a
+ Nothing -> error "testIPv4: invalid"
+{-# NOINLINE testIPv4 #-}
+
-- | Empty TLV stream.
emptyTlvs :: TlvStream
emptyTlvs = unsafeTlvStream []
@@ -101,6 +108,20 @@ emptyFeatures :: FeatureBits
emptyFeatures = featureBits BS.empty
{-# NOINLINE emptyFeatures #-}
+-- | List of test SCIDs for list encoding benchmarks.
+testScidList :: [ShortChannelId]
+testScidList = map mkScid [1..100]
+ where
+ mkScid n = case shortChannelId (BS.pack [0, 0, 0, n, 0, 0, 0, n]) of
+ Just s -> s
+ Nothing -> error "mkScid: invalid"
+{-# NOINLINE testScidList #-}
+
+-- | Encoded SCID list for decode benchmarks.
+encodedScidList :: BS.ByteString
+encodedScidList = encodeShortChannelIdList testScidList
+{-# NOINLINE encodedScidList #-}
+
-- Test messages ---------------------------------------------------------------
-- | Test ChannelAnnouncement message.
@@ -113,8 +134,8 @@ testChannelAnnouncement = ChannelAnnouncement
, channelAnnFeatures = emptyFeatures
, channelAnnChainHash = testChainHash
, channelAnnShortChanId = testShortChannelId
- , channelAnnNodeId1 = testNodeId
- , channelAnnNodeId2 = testNodeId2
+ , channelAnnNodeId1 = testNodeId2 -- 02... (smaller)
+ , channelAnnNodeId2 = testNodeId -- 03... (larger)
, channelAnnBitcoinKey1 = testPoint
, channelAnnBitcoinKey2 = testPoint
}
@@ -125,6 +146,26 @@ encodedChannelAnnouncement :: BS.ByteString
encodedChannelAnnouncement = encodeChannelAnnouncement testChannelAnnouncement
{-# NOINLINE encodedChannelAnnouncement #-}
+-- | Test NodeAnnouncement message.
+testNodeAnnouncement :: NodeAnnouncement
+testNodeAnnouncement = NodeAnnouncement
+ { nodeAnnSignature = testSignature
+ , nodeAnnFeatures = emptyFeatures
+ , nodeAnnTimestamp = 1234567890
+ , nodeAnnNodeId = testNodeId
+ , nodeAnnRgbColor = testRgbColor
+ , nodeAnnAlias = testAlias
+ , nodeAnnAddresses = [AddrIPv4 testIPv4 9735]
+ }
+{-# NOINLINE testNodeAnnouncement #-}
+
+-- | Encoded NodeAnnouncement for decode benchmarks.
+encodedNodeAnnouncement :: BS.ByteString
+encodedNodeAnnouncement = case encodeNodeAnnouncement testNodeAnnouncement of
+ Right bs -> bs
+ Left _ -> error "encodedNodeAnnouncement: encode failed"
+{-# NOINLINE encodedNodeAnnouncement #-}
+
-- | Test ChannelUpdate message.
testChannelUpdate :: ChannelUpdate
testChannelUpdate = ChannelUpdate
@@ -163,6 +204,71 @@ encodedAnnouncementSignatures =
encodeAnnouncementSignatures testAnnouncementSignatures
{-# NOINLINE encodedAnnouncementSignatures #-}
+-- | Test QueryShortChannelIds message.
+testQueryShortChannelIds :: QueryShortChannelIds
+testQueryShortChannelIds = QueryShortChannelIds
+ { queryScidsChainHash = testChainHash
+ , queryScidsData = encodeShortChannelIdList [testShortChannelId]
+ , queryScidsTlvs = emptyTlvs
+ }
+{-# NOINLINE testQueryShortChannelIds #-}
+
+-- | Encoded QueryShortChannelIds for decode benchmarks.
+encodedQueryShortChannelIds :: BS.ByteString
+encodedQueryShortChannelIds =
+ case encodeQueryShortChannelIds testQueryShortChannelIds of
+ Right bs -> bs
+ Left _ -> error "encodedQueryShortChannelIds: encode failed"
+{-# NOINLINE encodedQueryShortChannelIds #-}
+
+-- | Test ReplyShortChannelIdsEnd message.
+testReplyShortChannelIdsEnd :: ReplyShortChannelIdsEnd
+testReplyShortChannelIdsEnd = ReplyShortChannelIdsEnd
+ { replyScidsChainHash = testChainHash
+ , replyScidsFullInfo = 1
+ }
+{-# NOINLINE testReplyShortChannelIdsEnd #-}
+
+-- | Encoded ReplyShortChannelIdsEnd for decode benchmarks.
+encodedReplyShortChannelIdsEnd :: BS.ByteString
+encodedReplyShortChannelIdsEnd =
+ encodeReplyShortChannelIdsEnd testReplyShortChannelIdsEnd
+{-# NOINLINE encodedReplyShortChannelIdsEnd #-}
+
+-- | Test QueryChannelRange message.
+testQueryChannelRange :: QueryChannelRange
+testQueryChannelRange = QueryChannelRange
+ { queryRangeChainHash = testChainHash
+ , queryRangeFirstBlock = 700000
+ , queryRangeNumBlocks = 10000
+ , queryRangeTlvs = emptyTlvs
+ }
+{-# NOINLINE testQueryChannelRange #-}
+
+-- | Encoded QueryChannelRange for decode benchmarks.
+encodedQueryChannelRange :: BS.ByteString
+encodedQueryChannelRange = encodeQueryChannelRange testQueryChannelRange
+{-# NOINLINE encodedQueryChannelRange #-}
+
+-- | Test ReplyChannelRange message.
+testReplyChannelRange :: ReplyChannelRange
+testReplyChannelRange = ReplyChannelRange
+ { replyRangeChainHash = testChainHash
+ , replyRangeFirstBlock = 700000
+ , replyRangeNumBlocks = 10000
+ , replyRangeSyncComplete = 1
+ , replyRangeData = encodeShortChannelIdList [testShortChannelId]
+ , replyRangeTlvs = emptyTlvs
+ }
+{-# NOINLINE testReplyChannelRange #-}
+
+-- | Encoded ReplyChannelRange for decode benchmarks.
+encodedReplyChannelRange :: BS.ByteString
+encodedReplyChannelRange = case encodeReplyChannelRange testReplyChannelRange of
+ Right bs -> bs
+ Left _ -> error "encodedReplyChannelRange: encode failed"
+{-# NOINLINE encodedReplyChannelRange #-}
+
-- | Test GossipTimestampFilter message.
testGossipTimestampFilter :: GossipTimestampFilter
testGossipTimestampFilter = GossipTimestampFilter
@@ -186,6 +292,10 @@ main = defaultMain
[ bench "encode" $ nf encodeChannelAnnouncement testChannelAnnouncement
, bench "decode" $ nf decodeChannelAnnouncement encodedChannelAnnouncement
]
+ , bgroup "node_announcement"
+ [ bench "encode" $ nf encodeNodeAnnouncement testNodeAnnouncement
+ , bench "decode" $ nf decodeNodeAnnouncement encodedNodeAnnouncement
+ ]
, bgroup "channel_update"
[ bench "encode" $ nf encodeChannelUpdate testChannelUpdate
, bench "decode" $ nf decodeChannelUpdate encodedChannelUpdate
@@ -196,10 +306,56 @@ main = defaultMain
, bench "decode" $
nf decodeAnnouncementSignatures encodedAnnouncementSignatures
]
+ , bgroup "query_short_channel_ids"
+ [ bench "encode" $
+ nf encodeQueryShortChannelIds testQueryShortChannelIds
+ , bench "decode" $
+ nf decodeQueryShortChannelIds encodedQueryShortChannelIds
+ ]
+ , bgroup "reply_short_channel_ids_end"
+ [ bench "encode" $
+ nf encodeReplyShortChannelIdsEnd testReplyShortChannelIdsEnd
+ , bench "decode" $
+ nf decodeReplyShortChannelIdsEnd encodedReplyShortChannelIdsEnd
+ ]
+ , bgroup "query_channel_range"
+ [ bench "encode" $ nf encodeQueryChannelRange testQueryChannelRange
+ , bench "decode" $ nf decodeQueryChannelRange encodedQueryChannelRange
+ ]
+ , bgroup "reply_channel_range"
+ [ bench "encode" $ nf encodeReplyChannelRange testReplyChannelRange
+ , bench "decode" $ nf decodeReplyChannelRange encodedReplyChannelRange
+ ]
, bgroup "gossip_timestamp_filter"
[ bench "encode" $
nf encodeGossipTimestampFilter testGossipTimestampFilter
, bench "decode" $
nf decodeGossipTimestampFilter encodedGossipTimestampFilter
]
+ , bgroup "scid_list"
+ [ bench "encode (100)" $ nf encodeShortChannelIdList testScidList
+ , bench "decode (100)" $ nf decodeShortChannelIdList encodedScidList
+ ]
+ , bgroup "hash"
+ [ bench "channelAnnouncementHash" $
+ nf channelAnnouncementHash encodedChannelAnnouncement
+ , bench "nodeAnnouncementHash" $
+ nf nodeAnnouncementHash encodedNodeAnnouncement
+ , bench "channelUpdateHash" $
+ nf channelUpdateHash encodedChannelUpdate
+ , bench "channelUpdateChecksum" $
+ nf channelUpdateChecksum encodedChannelUpdate
+ ]
+ , bgroup "validate"
+ [ bench "channelAnnouncement" $
+ nf validateChannelAnnouncement testChannelAnnouncement
+ , bench "nodeAnnouncement" $
+ nf validateNodeAnnouncement testNodeAnnouncement
+ , bench "channelUpdate" $
+ nf validateChannelUpdate testChannelUpdate
+ , bench "queryChannelRange" $
+ nf validateQueryChannelRange testQueryChannelRange
+ , bench "replyChannelRange" $
+ nf validateReplyChannelRange testReplyChannelRange
+ ]
]
diff --git a/bench/Weight.hs b/bench/Weight.hs
@@ -12,6 +12,7 @@
module Main where
import qualified Data.ByteString as BS
+import Lightning.Protocol.BOLT1 (TlvStream, unsafeTlvStream)
import Lightning.Protocol.BOLT7
import Weigh
@@ -62,25 +63,65 @@ testChannelId = case channelId zeroBytes32 of
Nothing -> error "testChannelId: invalid"
{-# NOINLINE testChannelId #-}
--- | 33-byte node ID.
+-- | 33-byte node ID (03 prefix).
testNodeId :: NodeId
testNodeId = case nodeId (BS.cons 0x03 zeroBytes32) of
Just n -> n
Nothing -> error "testNodeId: invalid"
{-# NOINLINE testNodeId #-}
--- | Second node ID.
+-- | Second node ID (02 prefix, lexicographically smaller).
testNodeId2 :: NodeId
testNodeId2 = case nodeId (BS.cons 0x02 zeroBytes32) of
Just n -> n
Nothing -> error "testNodeId2: invalid"
{-# NOINLINE testNodeId2 #-}
+-- | RGB color.
+testRgbColor :: RgbColor
+testRgbColor = case rgbColor (BS.pack [0xff, 0x00, 0x00]) of
+ Just c -> c
+ Nothing -> error "testRgbColor: invalid"
+{-# NOINLINE testRgbColor #-}
+
+-- | 32-byte alias.
+testAlias :: Alias
+testAlias = case alias zeroBytes32 of
+ Just a -> a
+ Nothing -> error "testAlias: invalid"
+{-# NOINLINE testAlias #-}
+
+-- | IPv4 address.
+testIPv4 :: IPv4Addr
+testIPv4 = case ipv4Addr (BS.pack [127, 0, 0, 1]) of
+ Just a -> a
+ Nothing -> error "testIPv4: invalid"
+{-# NOINLINE testIPv4 #-}
+
-- | Empty feature bits.
emptyFeatures :: FeatureBits
emptyFeatures = featureBits BS.empty
{-# NOINLINE emptyFeatures #-}
+-- | Empty TLV stream.
+emptyTlvs :: TlvStream
+emptyTlvs = unsafeTlvStream []
+{-# NOINLINE emptyTlvs #-}
+
+-- | List of test SCIDs for list encoding benchmarks.
+testScidList :: [ShortChannelId]
+testScidList = map mkScid [1..100]
+ where
+ mkScid n = case shortChannelId (BS.pack [0, 0, 0, n, 0, 0, 0, n]) of
+ Just s -> s
+ Nothing -> error "mkScid: invalid"
+{-# NOINLINE testScidList #-}
+
+-- | Encoded SCID list for decode benchmarks.
+encodedScidList :: BS.ByteString
+encodedScidList = encodeShortChannelIdList testScidList
+{-# NOINLINE encodedScidList #-}
+
-- Message constructors --------------------------------------------------------
-- | Construct ChannelAnnouncement message.
@@ -103,6 +144,20 @@ mkChannelAnnouncement !ns1 !ns2 !ch !scid !nid1 !nid2 !bk1 !bk2 !feat =
, channelAnnBitcoinKey2 = bk2
}
+-- | Construct NodeAnnouncement message.
+mkNodeAnnouncement
+ :: Signature -> FeatureBits -> NodeId -> RgbColor -> Alias
+ -> [Address] -> NodeAnnouncement
+mkNodeAnnouncement !sig !feat !nid !col !al !addrs = NodeAnnouncement
+ { nodeAnnSignature = sig
+ , nodeAnnFeatures = feat
+ , nodeAnnTimestamp = 1234567890
+ , nodeAnnNodeId = nid
+ , nodeAnnRgbColor = col
+ , nodeAnnAlias = al
+ , nodeAnnAddresses = addrs
+ }
+
-- | Construct ChannelUpdate message.
mkChannelUpdate :: Signature -> ChainHash -> ShortChannelId -> ChannelUpdate
mkChannelUpdate !sig !ch !scid = ChannelUpdate
@@ -137,13 +192,33 @@ mkGossipTimestampFilter !ch = GossipTimestampFilter
, gossipFilterTimestampRange = 86400
}
+-- | Construct QueryChannelRange message.
+mkQueryChannelRange :: ChainHash -> TlvStream -> QueryChannelRange
+mkQueryChannelRange !ch !tlvs = QueryChannelRange
+ { queryRangeChainHash = ch
+ , queryRangeFirstBlock = 700000
+ , queryRangeNumBlocks = 10000
+ , queryRangeTlvs = tlvs
+ }
+
+-- | Construct ReplyChannelRange message.
+mkReplyChannelRange :: ChainHash -> TlvStream -> ReplyChannelRange
+mkReplyChannelRange !ch !tlvs = ReplyChannelRange
+ { replyRangeChainHash = ch
+ , replyRangeFirstBlock = 700000
+ , replyRangeNumBlocks = 10000
+ , replyRangeSyncComplete = 1
+ , replyRangeData = encodeShortChannelIdList [testShortChannelId]
+ , replyRangeTlvs = tlvs
+ }
+
-- Pre-constructed messages ----------------------------------------------------
-- | Test ChannelAnnouncement message.
testChannelAnnouncement :: ChannelAnnouncement
testChannelAnnouncement = mkChannelAnnouncement
testSignature testSignature testChainHash testShortChannelId
- testNodeId testNodeId2 testPoint testPoint emptyFeatures
+ testNodeId2 testNodeId testPoint testPoint emptyFeatures
{-# NOINLINE testChannelAnnouncement #-}
-- | Encoded ChannelAnnouncement for decode benchmarks.
@@ -151,6 +226,20 @@ encodedChannelAnnouncement :: BS.ByteString
encodedChannelAnnouncement = encodeChannelAnnouncement testChannelAnnouncement
{-# NOINLINE encodedChannelAnnouncement #-}
+-- | Test NodeAnnouncement message.
+testNodeAnnouncement :: NodeAnnouncement
+testNodeAnnouncement = mkNodeAnnouncement
+ testSignature emptyFeatures testNodeId testRgbColor testAlias
+ [AddrIPv4 testIPv4 9735]
+{-# NOINLINE testNodeAnnouncement #-}
+
+-- | Encoded NodeAnnouncement for decode benchmarks.
+encodedNodeAnnouncement :: BS.ByteString
+encodedNodeAnnouncement = case encodeNodeAnnouncement testNodeAnnouncement of
+ Right bs -> bs
+ Left _ -> error "encodedNodeAnnouncement: encode failed"
+{-# NOINLINE encodedNodeAnnouncement #-}
+
-- | Test ChannelUpdate message.
testChannelUpdate :: ChannelUpdate
testChannelUpdate = mkChannelUpdate testSignature testChainHash testShortChannelId
@@ -184,6 +273,28 @@ encodedGossipTimestampFilter =
encodeGossipTimestampFilter testGossipTimestampFilter
{-# NOINLINE encodedGossipTimestampFilter #-}
+-- | Test QueryChannelRange message.
+testQueryChannelRange :: QueryChannelRange
+testQueryChannelRange = mkQueryChannelRange testChainHash emptyTlvs
+{-# NOINLINE testQueryChannelRange #-}
+
+-- | Encoded QueryChannelRange for decode benchmarks.
+encodedQueryChannelRange :: BS.ByteString
+encodedQueryChannelRange = encodeQueryChannelRange testQueryChannelRange
+{-# NOINLINE encodedQueryChannelRange #-}
+
+-- | Test ReplyChannelRange message.
+testReplyChannelRange :: ReplyChannelRange
+testReplyChannelRange = mkReplyChannelRange testChainHash emptyTlvs
+{-# NOINLINE testReplyChannelRange #-}
+
+-- | Encoded ReplyChannelRange for decode benchmarks.
+encodedReplyChannelRange :: BS.ByteString
+encodedReplyChannelRange = case encodeReplyChannelRange testReplyChannelRange of
+ Right bs -> bs
+ Left _ -> error "encodedReplyChannelRange: encode failed"
+{-# NOINLINE encodedReplyChannelRange #-}
+
-- Weigh benchmarks ------------------------------------------------------------
main :: IO ()
@@ -191,10 +302,17 @@ main = mainWith $ do
wgroup "channel_announcement" $ do
func "construct" (mkChannelAnnouncement
testSignature testSignature testChainHash testShortChannelId
- testNodeId testNodeId2 testPoint testPoint) emptyFeatures
+ testNodeId2 testNodeId testPoint testPoint) emptyFeatures
func "encode" encodeChannelAnnouncement testChannelAnnouncement
func "decode" decodeChannelAnnouncement encodedChannelAnnouncement
+ wgroup "node_announcement" $ do
+ func "construct" (mkNodeAnnouncement
+ testSignature emptyFeatures testNodeId testRgbColor testAlias)
+ [AddrIPv4 testIPv4 9735]
+ func "encode" encodeNodeAnnouncement testNodeAnnouncement
+ func "decode" decodeNodeAnnouncement encodedNodeAnnouncement
+
wgroup "channel_update" $ do
func "construct" (mkChannelUpdate testSignature testChainHash)
testShortChannelId
@@ -207,7 +325,35 @@ main = mainWith $ do
func "encode" encodeAnnouncementSignatures testAnnouncementSignatures
func "decode" decodeAnnouncementSignatures encodedAnnouncementSignatures
+ wgroup "query_channel_range" $ do
+ func "construct" (mkQueryChannelRange testChainHash) emptyTlvs
+ func "encode" encodeQueryChannelRange testQueryChannelRange
+ func "decode" decodeQueryChannelRange encodedQueryChannelRange
+
+ wgroup "reply_channel_range" $ do
+ func "construct" (mkReplyChannelRange testChainHash) emptyTlvs
+ func "encode" encodeReplyChannelRange testReplyChannelRange
+ func "decode" decodeReplyChannelRange encodedReplyChannelRange
+
wgroup "gossip_timestamp_filter" $ do
func "construct" mkGossipTimestampFilter testChainHash
func "encode" encodeGossipTimestampFilter testGossipTimestampFilter
func "decode" decodeGossipTimestampFilter encodedGossipTimestampFilter
+
+ wgroup "scid_list" $ do
+ func "encode (100)" encodeShortChannelIdList testScidList
+ func "decode (100)" decodeShortChannelIdList encodedScidList
+
+ wgroup "hash" $ do
+ func "channelAnnouncementHash" channelAnnouncementHash
+ encodedChannelAnnouncement
+ func "nodeAnnouncementHash" nodeAnnouncementHash encodedNodeAnnouncement
+ func "channelUpdateHash" channelUpdateHash encodedChannelUpdate
+ func "channelUpdateChecksum" channelUpdateChecksum encodedChannelUpdate
+
+ wgroup "validate" $ do
+ func "channelAnnouncement" validateChannelAnnouncement testChannelAnnouncement
+ func "nodeAnnouncement" validateNodeAnnouncement testNodeAnnouncement
+ func "channelUpdate" validateChannelUpdate testChannelUpdate
+ func "queryChannelRange" validateQueryChannelRange testQueryChannelRange
+ func "replyChannelRange" validateReplyChannelRange testReplyChannelRange