Main.hs (12704B)
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 scidFromBytes 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 scidFromBytes (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 , chanUpdateChanFlags = ChannelFlags NodeOne Enabled 177 , chanUpdateCltvExpDelta = CltvExpiryDelta 144 178 , chanUpdateHtlcMinMsat = HtlcMinimumMsat 1000 179 , chanUpdateFeeBaseMsat = FeeBaseMsat 1000 180 , chanUpdateFeeProportional = FeeProportionalMillionths 100 181 , chanUpdateHtlcMaxMsat = Just (HtlcMaximumMsat 1000000000) 182 } 183 {-# NOINLINE testChannelUpdate #-} 184 185 -- | Encoded ChannelUpdate for decode benchmarks. 186 encodedChannelUpdate :: BS.ByteString 187 encodedChannelUpdate = encodeChannelUpdate testChannelUpdate 188 {-# NOINLINE encodedChannelUpdate #-} 189 190 -- | Test AnnouncementSignatures message. 191 testAnnouncementSignatures :: AnnouncementSignatures 192 testAnnouncementSignatures = AnnouncementSignatures 193 { annSigChannelId = testChannelId 194 , annSigShortChanId = testShortChannelId 195 , annSigNodeSig = testSignature 196 , annSigBitcoinSig = testSignature 197 } 198 {-# NOINLINE testAnnouncementSignatures #-} 199 200 -- | Encoded AnnouncementSignatures for decode benchmarks. 201 encodedAnnouncementSignatures :: BS.ByteString 202 encodedAnnouncementSignatures = 203 encodeAnnouncementSignatures testAnnouncementSignatures 204 {-# NOINLINE encodedAnnouncementSignatures #-} 205 206 -- | Test QueryShortChannelIds message. 207 testQueryShortChannelIds :: QueryShortChannelIds 208 testQueryShortChannelIds = QueryShortChannelIds 209 { queryScidsChainHash = testChainHash 210 , queryScidsData = encodeShortChannelIdList [testShortChannelId] 211 , queryScidsTlvs = emptyTlvs 212 } 213 {-# NOINLINE testQueryShortChannelIds #-} 214 215 -- | Encoded QueryShortChannelIds for decode benchmarks. 216 encodedQueryShortChannelIds :: BS.ByteString 217 encodedQueryShortChannelIds = 218 case encodeQueryShortChannelIds testQueryShortChannelIds of 219 Right bs -> bs 220 Left _ -> error "encodedQueryShortChannelIds: encode failed" 221 {-# NOINLINE encodedQueryShortChannelIds #-} 222 223 -- | Test ReplyShortChannelIdsEnd message. 224 testReplyShortChannelIdsEnd :: ReplyShortChannelIdsEnd 225 testReplyShortChannelIdsEnd = ReplyShortChannelIdsEnd 226 { replyScidsChainHash = testChainHash 227 , replyScidsFullInfo = 1 228 } 229 {-# NOINLINE testReplyShortChannelIdsEnd #-} 230 231 -- | Encoded ReplyShortChannelIdsEnd for decode benchmarks. 232 encodedReplyShortChannelIdsEnd :: BS.ByteString 233 encodedReplyShortChannelIdsEnd = 234 encodeReplyShortChannelIdsEnd testReplyShortChannelIdsEnd 235 {-# NOINLINE encodedReplyShortChannelIdsEnd #-} 236 237 -- | Test QueryChannelRange message. 238 testQueryChannelRange :: QueryChannelRange 239 testQueryChannelRange = QueryChannelRange 240 { queryRangeChainHash = testChainHash 241 , queryRangeFirstBlock = BlockHeight 700000 242 , queryRangeNumBlocks = BlockCount 10000 243 , queryRangeTlvs = emptyTlvs 244 } 245 {-# NOINLINE testQueryChannelRange #-} 246 247 -- | Encoded QueryChannelRange for decode benchmarks. 248 encodedQueryChannelRange :: BS.ByteString 249 encodedQueryChannelRange = encodeQueryChannelRange testQueryChannelRange 250 {-# NOINLINE encodedQueryChannelRange #-} 251 252 -- | Test ReplyChannelRange message. 253 testReplyChannelRange :: ReplyChannelRange 254 testReplyChannelRange = ReplyChannelRange 255 { replyRangeChainHash = testChainHash 256 , replyRangeFirstBlock = BlockHeight 700000 257 , replyRangeNumBlocks = BlockCount 10000 258 , replyRangeSyncComplete = 1 259 , replyRangeData = encodeShortChannelIdList [testShortChannelId] 260 , replyRangeTlvs = emptyTlvs 261 } 262 {-# NOINLINE testReplyChannelRange #-} 263 264 -- | Encoded ReplyChannelRange for decode benchmarks. 265 encodedReplyChannelRange :: BS.ByteString 266 encodedReplyChannelRange = case encodeReplyChannelRange testReplyChannelRange of 267 Right bs -> bs 268 Left _ -> error "encodedReplyChannelRange: encode failed" 269 {-# NOINLINE encodedReplyChannelRange #-} 270 271 -- | Test GossipTimestampFilter message. 272 testGossipTimestampFilter :: GossipTimestampFilter 273 testGossipTimestampFilter = GossipTimestampFilter 274 { gossipFilterChainHash = testChainHash 275 , gossipFilterFirstTimestamp = 1609459200 276 , gossipFilterTimestampRange = 86400 277 } 278 {-# NOINLINE testGossipTimestampFilter #-} 279 280 -- | Encoded GossipTimestampFilter for decode benchmarks. 281 encodedGossipTimestampFilter :: BS.ByteString 282 encodedGossipTimestampFilter = 283 encodeGossipTimestampFilter testGossipTimestampFilter 284 {-# NOINLINE encodedGossipTimestampFilter #-} 285 286 -- Benchmark groups ------------------------------------------------------------ 287 288 main :: IO () 289 main = defaultMain 290 [ bgroup "channel_announcement" 291 [ bench "encode" $ nf encodeChannelAnnouncement testChannelAnnouncement 292 , bench "decode" $ nf decodeChannelAnnouncement encodedChannelAnnouncement 293 ] 294 , bgroup "node_announcement" 295 [ bench "encode" $ nf encodeNodeAnnouncement testNodeAnnouncement 296 , bench "decode" $ nf decodeNodeAnnouncement encodedNodeAnnouncement 297 ] 298 , bgroup "channel_update" 299 [ bench "encode" $ nf encodeChannelUpdate testChannelUpdate 300 , bench "decode" $ nf decodeChannelUpdate encodedChannelUpdate 301 ] 302 , bgroup "announcement_signatures" 303 [ bench "encode" $ 304 nf encodeAnnouncementSignatures testAnnouncementSignatures 305 , bench "decode" $ 306 nf decodeAnnouncementSignatures encodedAnnouncementSignatures 307 ] 308 , bgroup "query_short_channel_ids" 309 [ bench "encode" $ 310 nf encodeQueryShortChannelIds testQueryShortChannelIds 311 , bench "decode" $ 312 nf decodeQueryShortChannelIds encodedQueryShortChannelIds 313 ] 314 , bgroup "reply_short_channel_ids_end" 315 [ bench "encode" $ 316 nf encodeReplyShortChannelIdsEnd testReplyShortChannelIdsEnd 317 , bench "decode" $ 318 nf decodeReplyShortChannelIdsEnd encodedReplyShortChannelIdsEnd 319 ] 320 , bgroup "query_channel_range" 321 [ bench "encode" $ nf encodeQueryChannelRange testQueryChannelRange 322 , bench "decode" $ nf decodeQueryChannelRange encodedQueryChannelRange 323 ] 324 , bgroup "reply_channel_range" 325 [ bench "encode" $ nf encodeReplyChannelRange testReplyChannelRange 326 , bench "decode" $ nf decodeReplyChannelRange encodedReplyChannelRange 327 ] 328 , bgroup "gossip_timestamp_filter" 329 [ bench "encode" $ 330 nf encodeGossipTimestampFilter testGossipTimestampFilter 331 , bench "decode" $ 332 nf decodeGossipTimestampFilter encodedGossipTimestampFilter 333 ] 334 , bgroup "scid_list" 335 [ bench "encode (100)" $ nf encodeShortChannelIdList testScidList 336 , bench "decode (100)" $ nf decodeShortChannelIdList encodedScidList 337 ] 338 , bgroup "hash" 339 [ bench "channelAnnouncementHash" $ 340 nf channelAnnouncementHash encodedChannelAnnouncement 341 , bench "nodeAnnouncementHash" $ 342 nf nodeAnnouncementHash encodedNodeAnnouncement 343 , bench "channelUpdateHash" $ 344 nf channelUpdateHash encodedChannelUpdate 345 , bench "channelUpdateChecksum" $ 346 nf channelUpdateChecksum encodedChannelUpdate 347 ] 348 , bgroup "validate" 349 [ bench "channelAnnouncement" $ 350 nf validateChannelAnnouncement testChannelAnnouncement 351 , bench "nodeAnnouncement" $ 352 nf validateNodeAnnouncement testNodeAnnouncement 353 , bench "channelUpdate" $ 354 nf validateChannelUpdate testChannelUpdate 355 , bench "queryChannelRange" $ 356 nf validateQueryChannelRange testQueryChannelRange 357 , bench "replyChannelRange" $ 358 nf validateReplyChannelRange testReplyChannelRange 359 ] 360 ]