Main.hs (12585B)
1 {-# LANGUAGE BangPatterns #-} 2 {-# LANGUAGE OverloadedStrings #-} 3 4 -- | 5 -- Module: Main 6 -- Copyright: (c) 2025 Jared Tobin 7 -- License: MIT 8 -- Maintainer: Jared Tobin <jared@ppad.tech> 9 -- 10 -- Criterion timing benchmarks for BOLT #7 gossip codecs. 11 12 module Main where 13 14 import Criterion.Main 15 import qualified Data.ByteString as BS 16 import Lightning.Protocol.BOLT1 (TlvStream, unsafeTlvStream) 17 import Lightning.Protocol.BOLT7 18 19 -- Test data construction ------------------------------------------------------ 20 21 -- | 32 zero bytes for chain hashes, etc. 22 zeroBytes32 :: BS.ByteString 23 zeroBytes32 = BS.replicate 32 0x00 24 {-# NOINLINE zeroBytes32 #-} 25 26 -- | 8 zero bytes for short channel IDs. 27 zeroBytes8 :: BS.ByteString 28 zeroBytes8 = BS.replicate 8 0x00 29 {-# NOINLINE zeroBytes8 #-} 30 31 -- | 64-byte signature. 32 testSignature :: Signature 33 testSignature = case signature (BS.replicate 64 0x01) of 34 Just s -> s 35 Nothing -> error "testSignature: invalid" 36 {-# NOINLINE testSignature #-} 37 38 -- | 33-byte compressed public key (02 prefix + 32 zero bytes). 39 testPoint :: Point 40 testPoint = case point (BS.cons 0x02 zeroBytes32) of 41 Just p -> p 42 Nothing -> error "testPoint: invalid" 43 {-# NOINLINE testPoint #-} 44 45 -- | 32-byte chain hash. 46 testChainHash :: ChainHash 47 testChainHash = case chainHash zeroBytes32 of 48 Just h -> h 49 Nothing -> error "testChainHash: invalid" 50 {-# NOINLINE testChainHash #-} 51 52 -- | 8-byte short channel ID. 53 testShortChannelId :: ShortChannelId 54 testShortChannelId = case shortChannelId zeroBytes8 of 55 Just s -> s 56 Nothing -> error "testShortChannelId: invalid" 57 {-# NOINLINE testShortChannelId #-} 58 59 -- | 32-byte channel ID. 60 testChannelId :: ChannelId 61 testChannelId = case channelId zeroBytes32 of 62 Just c -> c 63 Nothing -> error "testChannelId: invalid" 64 {-# NOINLINE testChannelId #-} 65 66 -- | 33-byte node ID (03 prefix). 67 testNodeId :: NodeId 68 testNodeId = case nodeId (BS.cons 0x03 zeroBytes32) of 69 Just n -> n 70 Nothing -> error "testNodeId: invalid" 71 {-# NOINLINE testNodeId #-} 72 73 -- | Second node ID (02 prefix, lexicographically smaller). 74 testNodeId2 :: NodeId 75 testNodeId2 = case nodeId (BS.cons 0x02 zeroBytes32) of 76 Just n -> n 77 Nothing -> error "testNodeId2: invalid" 78 {-# NOINLINE testNodeId2 #-} 79 80 -- | RGB color. 81 testRgbColor :: RgbColor 82 testRgbColor = case rgbColor (BS.pack [0xff, 0x00, 0x00]) of 83 Just c -> c 84 Nothing -> error "testRgbColor: invalid" 85 {-# NOINLINE testRgbColor #-} 86 87 -- | 32-byte alias. 88 testAlias :: Alias 89 testAlias = case alias zeroBytes32 of 90 Just a -> a 91 Nothing -> error "testAlias: invalid" 92 {-# NOINLINE testAlias #-} 93 94 -- | IPv4 address. 95 testIPv4 :: IPv4Addr 96 testIPv4 = case ipv4Addr (BS.pack [127, 0, 0, 1]) of 97 Just a -> a 98 Nothing -> error "testIPv4: invalid" 99 {-# NOINLINE testIPv4 #-} 100 101 -- | Empty TLV stream. 102 emptyTlvs :: TlvStream 103 emptyTlvs = unsafeTlvStream [] 104 {-# NOINLINE emptyTlvs #-} 105 106 -- | Empty feature bits. 107 emptyFeatures :: FeatureBits 108 emptyFeatures = featureBits BS.empty 109 {-# NOINLINE emptyFeatures #-} 110 111 -- | List of test SCIDs for list encoding benchmarks. 112 testScidList :: [ShortChannelId] 113 testScidList = map mkScid [1..100] 114 where 115 mkScid n = case shortChannelId (BS.pack [0, 0, 0, n, 0, 0, 0, n]) of 116 Just s -> s 117 Nothing -> error "mkScid: invalid" 118 {-# NOINLINE testScidList #-} 119 120 -- | Encoded SCID list for decode benchmarks. 121 encodedScidList :: BS.ByteString 122 encodedScidList = encodeShortChannelIdList testScidList 123 {-# NOINLINE encodedScidList #-} 124 125 -- Test messages --------------------------------------------------------------- 126 127 -- | Test ChannelAnnouncement message. 128 testChannelAnnouncement :: ChannelAnnouncement 129 testChannelAnnouncement = ChannelAnnouncement 130 { channelAnnNodeSig1 = testSignature 131 , channelAnnNodeSig2 = testSignature 132 , channelAnnBitcoinSig1 = testSignature 133 , channelAnnBitcoinSig2 = testSignature 134 , channelAnnFeatures = emptyFeatures 135 , channelAnnChainHash = testChainHash 136 , channelAnnShortChanId = testShortChannelId 137 , channelAnnNodeId1 = testNodeId2 -- 02... (smaller) 138 , channelAnnNodeId2 = testNodeId -- 03... (larger) 139 , channelAnnBitcoinKey1 = testPoint 140 , channelAnnBitcoinKey2 = testPoint 141 } 142 {-# NOINLINE testChannelAnnouncement #-} 143 144 -- | Encoded ChannelAnnouncement for decode benchmarks. 145 encodedChannelAnnouncement :: BS.ByteString 146 encodedChannelAnnouncement = encodeChannelAnnouncement testChannelAnnouncement 147 {-# NOINLINE encodedChannelAnnouncement #-} 148 149 -- | Test NodeAnnouncement message. 150 testNodeAnnouncement :: NodeAnnouncement 151 testNodeAnnouncement = NodeAnnouncement 152 { nodeAnnSignature = testSignature 153 , nodeAnnFeatures = emptyFeatures 154 , nodeAnnTimestamp = 1234567890 155 , nodeAnnNodeId = testNodeId 156 , nodeAnnRgbColor = testRgbColor 157 , nodeAnnAlias = testAlias 158 , nodeAnnAddresses = [AddrIPv4 testIPv4 9735] 159 } 160 {-# NOINLINE testNodeAnnouncement #-} 161 162 -- | Encoded NodeAnnouncement for decode benchmarks. 163 encodedNodeAnnouncement :: BS.ByteString 164 encodedNodeAnnouncement = case encodeNodeAnnouncement testNodeAnnouncement of 165 Right bs -> bs 166 Left _ -> error "encodedNodeAnnouncement: encode failed" 167 {-# NOINLINE encodedNodeAnnouncement #-} 168 169 -- | Test ChannelUpdate message. 170 testChannelUpdate :: ChannelUpdate 171 testChannelUpdate = ChannelUpdate 172 { chanUpdateSignature = testSignature 173 , chanUpdateChainHash = testChainHash 174 , chanUpdateShortChanId = testShortChannelId 175 , chanUpdateTimestamp = 1234567890 176 , chanUpdateMsgFlags = 0x01 177 , chanUpdateChanFlags = 0x00 178 , chanUpdateCltvExpDelta = 144 179 , chanUpdateHtlcMinMsat = 1000 180 , chanUpdateFeeBaseMsat = 1000 181 , chanUpdateFeeProportional = 100 182 , chanUpdateHtlcMaxMsat = Just 1000000000 183 } 184 {-# NOINLINE testChannelUpdate #-} 185 186 -- | Encoded ChannelUpdate for decode benchmarks. 187 encodedChannelUpdate :: BS.ByteString 188 encodedChannelUpdate = encodeChannelUpdate testChannelUpdate 189 {-# NOINLINE encodedChannelUpdate #-} 190 191 -- | Test AnnouncementSignatures message. 192 testAnnouncementSignatures :: AnnouncementSignatures 193 testAnnouncementSignatures = AnnouncementSignatures 194 { annSigChannelId = testChannelId 195 , annSigShortChanId = testShortChannelId 196 , annSigNodeSig = testSignature 197 , annSigBitcoinSig = testSignature 198 } 199 {-# NOINLINE testAnnouncementSignatures #-} 200 201 -- | Encoded AnnouncementSignatures for decode benchmarks. 202 encodedAnnouncementSignatures :: BS.ByteString 203 encodedAnnouncementSignatures = 204 encodeAnnouncementSignatures testAnnouncementSignatures 205 {-# NOINLINE encodedAnnouncementSignatures #-} 206 207 -- | Test QueryShortChannelIds message. 208 testQueryShortChannelIds :: QueryShortChannelIds 209 testQueryShortChannelIds = QueryShortChannelIds 210 { queryScidsChainHash = testChainHash 211 , queryScidsData = encodeShortChannelIdList [testShortChannelId] 212 , queryScidsTlvs = emptyTlvs 213 } 214 {-# NOINLINE testQueryShortChannelIds #-} 215 216 -- | Encoded QueryShortChannelIds for decode benchmarks. 217 encodedQueryShortChannelIds :: BS.ByteString 218 encodedQueryShortChannelIds = 219 case encodeQueryShortChannelIds testQueryShortChannelIds of 220 Right bs -> bs 221 Left _ -> error "encodedQueryShortChannelIds: encode failed" 222 {-# NOINLINE encodedQueryShortChannelIds #-} 223 224 -- | Test ReplyShortChannelIdsEnd message. 225 testReplyShortChannelIdsEnd :: ReplyShortChannelIdsEnd 226 testReplyShortChannelIdsEnd = ReplyShortChannelIdsEnd 227 { replyScidsChainHash = testChainHash 228 , replyScidsFullInfo = 1 229 } 230 {-# NOINLINE testReplyShortChannelIdsEnd #-} 231 232 -- | Encoded ReplyShortChannelIdsEnd for decode benchmarks. 233 encodedReplyShortChannelIdsEnd :: BS.ByteString 234 encodedReplyShortChannelIdsEnd = 235 encodeReplyShortChannelIdsEnd testReplyShortChannelIdsEnd 236 {-# NOINLINE encodedReplyShortChannelIdsEnd #-} 237 238 -- | Test QueryChannelRange message. 239 testQueryChannelRange :: QueryChannelRange 240 testQueryChannelRange = QueryChannelRange 241 { queryRangeChainHash = testChainHash 242 , queryRangeFirstBlock = 700000 243 , queryRangeNumBlocks = 10000 244 , queryRangeTlvs = emptyTlvs 245 } 246 {-# NOINLINE testQueryChannelRange #-} 247 248 -- | Encoded QueryChannelRange for decode benchmarks. 249 encodedQueryChannelRange :: BS.ByteString 250 encodedQueryChannelRange = encodeQueryChannelRange testQueryChannelRange 251 {-# NOINLINE encodedQueryChannelRange #-} 252 253 -- | Test ReplyChannelRange message. 254 testReplyChannelRange :: ReplyChannelRange 255 testReplyChannelRange = ReplyChannelRange 256 { replyRangeChainHash = testChainHash 257 , replyRangeFirstBlock = 700000 258 , replyRangeNumBlocks = 10000 259 , replyRangeSyncComplete = 1 260 , replyRangeData = encodeShortChannelIdList [testShortChannelId] 261 , replyRangeTlvs = emptyTlvs 262 } 263 {-# NOINLINE testReplyChannelRange #-} 264 265 -- | Encoded ReplyChannelRange for decode benchmarks. 266 encodedReplyChannelRange :: BS.ByteString 267 encodedReplyChannelRange = case encodeReplyChannelRange testReplyChannelRange of 268 Right bs -> bs 269 Left _ -> error "encodedReplyChannelRange: encode failed" 270 {-# NOINLINE encodedReplyChannelRange #-} 271 272 -- | Test GossipTimestampFilter message. 273 testGossipTimestampFilter :: GossipTimestampFilter 274 testGossipTimestampFilter = GossipTimestampFilter 275 { gossipFilterChainHash = testChainHash 276 , gossipFilterFirstTimestamp = 1609459200 277 , gossipFilterTimestampRange = 86400 278 } 279 {-# NOINLINE testGossipTimestampFilter #-} 280 281 -- | Encoded GossipTimestampFilter for decode benchmarks. 282 encodedGossipTimestampFilter :: BS.ByteString 283 encodedGossipTimestampFilter = 284 encodeGossipTimestampFilter testGossipTimestampFilter 285 {-# NOINLINE encodedGossipTimestampFilter #-} 286 287 -- Benchmark groups ------------------------------------------------------------ 288 289 main :: IO () 290 main = defaultMain 291 [ bgroup "channel_announcement" 292 [ bench "encode" $ nf encodeChannelAnnouncement testChannelAnnouncement 293 , bench "decode" $ nf decodeChannelAnnouncement encodedChannelAnnouncement 294 ] 295 , bgroup "node_announcement" 296 [ bench "encode" $ nf encodeNodeAnnouncement testNodeAnnouncement 297 , bench "decode" $ nf decodeNodeAnnouncement encodedNodeAnnouncement 298 ] 299 , bgroup "channel_update" 300 [ bench "encode" $ nf encodeChannelUpdate testChannelUpdate 301 , bench "decode" $ nf decodeChannelUpdate encodedChannelUpdate 302 ] 303 , bgroup "announcement_signatures" 304 [ bench "encode" $ 305 nf encodeAnnouncementSignatures testAnnouncementSignatures 306 , bench "decode" $ 307 nf decodeAnnouncementSignatures encodedAnnouncementSignatures 308 ] 309 , bgroup "query_short_channel_ids" 310 [ bench "encode" $ 311 nf encodeQueryShortChannelIds testQueryShortChannelIds 312 , bench "decode" $ 313 nf decodeQueryShortChannelIds encodedQueryShortChannelIds 314 ] 315 , bgroup "reply_short_channel_ids_end" 316 [ bench "encode" $ 317 nf encodeReplyShortChannelIdsEnd testReplyShortChannelIdsEnd 318 , bench "decode" $ 319 nf decodeReplyShortChannelIdsEnd encodedReplyShortChannelIdsEnd 320 ] 321 , bgroup "query_channel_range" 322 [ bench "encode" $ nf encodeQueryChannelRange testQueryChannelRange 323 , bench "decode" $ nf decodeQueryChannelRange encodedQueryChannelRange 324 ] 325 , bgroup "reply_channel_range" 326 [ bench "encode" $ nf encodeReplyChannelRange testReplyChannelRange 327 , bench "decode" $ nf decodeReplyChannelRange encodedReplyChannelRange 328 ] 329 , bgroup "gossip_timestamp_filter" 330 [ bench "encode" $ 331 nf encodeGossipTimestampFilter testGossipTimestampFilter 332 , bench "decode" $ 333 nf decodeGossipTimestampFilter encodedGossipTimestampFilter 334 ] 335 , bgroup "scid_list" 336 [ bench "encode (100)" $ nf encodeShortChannelIdList testScidList 337 , bench "decode (100)" $ nf decodeShortChannelIdList encodedScidList 338 ] 339 , bgroup "hash" 340 [ bench "channelAnnouncementHash" $ 341 nf channelAnnouncementHash encodedChannelAnnouncement 342 , bench "nodeAnnouncementHash" $ 343 nf nodeAnnouncementHash encodedNodeAnnouncement 344 , bench "channelUpdateHash" $ 345 nf channelUpdateHash encodedChannelUpdate 346 , bench "channelUpdateChecksum" $ 347 nf channelUpdateChecksum encodedChannelUpdate 348 ] 349 , bgroup "validate" 350 [ bench "channelAnnouncement" $ 351 nf validateChannelAnnouncement testChannelAnnouncement 352 , bench "nodeAnnouncement" $ 353 nf validateNodeAnnouncement testNodeAnnouncement 354 , bench "channelUpdate" $ 355 nf validateChannelUpdate testChannelUpdate 356 , bench "queryChannelRange" $ 357 nf validateQueryChannelRange testQueryChannelRange 358 , bench "replyChannelRange" $ 359 nf validateReplyChannelRange testReplyChannelRange 360 ] 361 ]