Weight.hs (12762B)
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 -- Weigh allocation benchmarks for BOLT #7 gossip codecs. 11 12 module Main where 13 14 import qualified Data.ByteString as BS 15 import Lightning.Protocol.BOLT1 (TlvStream, unsafeTlvStream) 16 import Lightning.Protocol.BOLT7 17 import Weigh 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 feature bits. 102 emptyFeatures :: FeatureBits 103 emptyFeatures = featureBits BS.empty 104 {-# NOINLINE emptyFeatures #-} 105 106 -- | Empty TLV stream. 107 emptyTlvs :: TlvStream 108 emptyTlvs = unsafeTlvStream [] 109 {-# NOINLINE emptyTlvs #-} 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 -- Message constructors -------------------------------------------------------- 126 127 -- | Construct ChannelAnnouncement message. 128 mkChannelAnnouncement 129 :: Signature -> Signature -> ChainHash -> ShortChannelId 130 -> NodeId -> NodeId -> Point -> Point -> FeatureBits 131 -> ChannelAnnouncement 132 mkChannelAnnouncement !ns1 !ns2 !ch !scid !nid1 !nid2 !bk1 !bk2 !feat = 133 ChannelAnnouncement 134 { channelAnnNodeSig1 = ns1 135 , channelAnnNodeSig2 = ns2 136 , channelAnnBitcoinSig1 = ns1 137 , channelAnnBitcoinSig2 = ns2 138 , channelAnnFeatures = feat 139 , channelAnnChainHash = ch 140 , channelAnnShortChanId = scid 141 , channelAnnNodeId1 = nid1 142 , channelAnnNodeId2 = nid2 143 , channelAnnBitcoinKey1 = bk1 144 , channelAnnBitcoinKey2 = bk2 145 } 146 147 -- | Construct NodeAnnouncement message. 148 mkNodeAnnouncement 149 :: Signature -> FeatureBits -> NodeId -> RgbColor -> Alias 150 -> [Address] -> NodeAnnouncement 151 mkNodeAnnouncement !sig !feat !nid !col !al !addrs = NodeAnnouncement 152 { nodeAnnSignature = sig 153 , nodeAnnFeatures = feat 154 , nodeAnnTimestamp = 1234567890 155 , nodeAnnNodeId = nid 156 , nodeAnnRgbColor = col 157 , nodeAnnAlias = al 158 , nodeAnnAddresses = addrs 159 } 160 161 -- | Construct ChannelUpdate message. 162 mkChannelUpdate :: Signature -> ChainHash -> ShortChannelId -> ChannelUpdate 163 mkChannelUpdate !sig !ch !scid = ChannelUpdate 164 { chanUpdateSignature = sig 165 , chanUpdateChainHash = ch 166 , chanUpdateShortChanId = scid 167 , chanUpdateTimestamp = 1234567890 168 , chanUpdateMsgFlags = 0x01 169 , chanUpdateChanFlags = 0x00 170 , chanUpdateCltvExpDelta = 144 171 , chanUpdateHtlcMinMsat = 1000 172 , chanUpdateFeeBaseMsat = 1000 173 , chanUpdateFeeProportional = 100 174 , chanUpdateHtlcMaxMsat = Just 1000000000 175 } 176 177 -- | Construct AnnouncementSignatures message. 178 mkAnnouncementSignatures 179 :: ChannelId -> ShortChannelId -> Signature -> AnnouncementSignatures 180 mkAnnouncementSignatures !cid !scid !sig = AnnouncementSignatures 181 { annSigChannelId = cid 182 , annSigShortChanId = scid 183 , annSigNodeSig = sig 184 , annSigBitcoinSig = sig 185 } 186 187 -- | Construct GossipTimestampFilter message. 188 mkGossipTimestampFilter :: ChainHash -> GossipTimestampFilter 189 mkGossipTimestampFilter !ch = GossipTimestampFilter 190 { gossipFilterChainHash = ch 191 , gossipFilterFirstTimestamp = 1609459200 192 , gossipFilterTimestampRange = 86400 193 } 194 195 -- | Construct QueryChannelRange message. 196 mkQueryChannelRange :: ChainHash -> TlvStream -> QueryChannelRange 197 mkQueryChannelRange !ch !tlvs = QueryChannelRange 198 { queryRangeChainHash = ch 199 , queryRangeFirstBlock = 700000 200 , queryRangeNumBlocks = 10000 201 , queryRangeTlvs = tlvs 202 } 203 204 -- | Construct ReplyChannelRange message. 205 mkReplyChannelRange :: ChainHash -> TlvStream -> ReplyChannelRange 206 mkReplyChannelRange !ch !tlvs = ReplyChannelRange 207 { replyRangeChainHash = ch 208 , replyRangeFirstBlock = 700000 209 , replyRangeNumBlocks = 10000 210 , replyRangeSyncComplete = 1 211 , replyRangeData = encodeShortChannelIdList [testShortChannelId] 212 , replyRangeTlvs = tlvs 213 } 214 215 -- Pre-constructed messages ---------------------------------------------------- 216 217 -- | Test ChannelAnnouncement message. 218 testChannelAnnouncement :: ChannelAnnouncement 219 testChannelAnnouncement = mkChannelAnnouncement 220 testSignature testSignature testChainHash testShortChannelId 221 testNodeId2 testNodeId testPoint testPoint emptyFeatures 222 {-# NOINLINE testChannelAnnouncement #-} 223 224 -- | Encoded ChannelAnnouncement for decode benchmarks. 225 encodedChannelAnnouncement :: BS.ByteString 226 encodedChannelAnnouncement = encodeChannelAnnouncement testChannelAnnouncement 227 {-# NOINLINE encodedChannelAnnouncement #-} 228 229 -- | Test NodeAnnouncement message. 230 testNodeAnnouncement :: NodeAnnouncement 231 testNodeAnnouncement = mkNodeAnnouncement 232 testSignature emptyFeatures testNodeId testRgbColor testAlias 233 [AddrIPv4 testIPv4 9735] 234 {-# NOINLINE testNodeAnnouncement #-} 235 236 -- | Encoded NodeAnnouncement for decode benchmarks. 237 encodedNodeAnnouncement :: BS.ByteString 238 encodedNodeAnnouncement = case encodeNodeAnnouncement testNodeAnnouncement of 239 Right bs -> bs 240 Left _ -> error "encodedNodeAnnouncement: encode failed" 241 {-# NOINLINE encodedNodeAnnouncement #-} 242 243 -- | Test ChannelUpdate message. 244 testChannelUpdate :: ChannelUpdate 245 testChannelUpdate = mkChannelUpdate testSignature testChainHash testShortChannelId 246 {-# NOINLINE testChannelUpdate #-} 247 248 -- | Encoded ChannelUpdate for decode benchmarks. 249 encodedChannelUpdate :: BS.ByteString 250 encodedChannelUpdate = encodeChannelUpdate testChannelUpdate 251 {-# NOINLINE encodedChannelUpdate #-} 252 253 -- | Test AnnouncementSignatures message. 254 testAnnouncementSignatures :: AnnouncementSignatures 255 testAnnouncementSignatures = 256 mkAnnouncementSignatures testChannelId testShortChannelId testSignature 257 {-# NOINLINE testAnnouncementSignatures #-} 258 259 -- | Encoded AnnouncementSignatures for decode benchmarks. 260 encodedAnnouncementSignatures :: BS.ByteString 261 encodedAnnouncementSignatures = 262 encodeAnnouncementSignatures testAnnouncementSignatures 263 {-# NOINLINE encodedAnnouncementSignatures #-} 264 265 -- | Test GossipTimestampFilter message. 266 testGossipTimestampFilter :: GossipTimestampFilter 267 testGossipTimestampFilter = mkGossipTimestampFilter testChainHash 268 {-# NOINLINE testGossipTimestampFilter #-} 269 270 -- | Encoded GossipTimestampFilter for decode benchmarks. 271 encodedGossipTimestampFilter :: BS.ByteString 272 encodedGossipTimestampFilter = 273 encodeGossipTimestampFilter testGossipTimestampFilter 274 {-# NOINLINE encodedGossipTimestampFilter #-} 275 276 -- | Test QueryChannelRange message. 277 testQueryChannelRange :: QueryChannelRange 278 testQueryChannelRange = mkQueryChannelRange testChainHash emptyTlvs 279 {-# NOINLINE testQueryChannelRange #-} 280 281 -- | Encoded QueryChannelRange for decode benchmarks. 282 encodedQueryChannelRange :: BS.ByteString 283 encodedQueryChannelRange = encodeQueryChannelRange testQueryChannelRange 284 {-# NOINLINE encodedQueryChannelRange #-} 285 286 -- | Test ReplyChannelRange message. 287 testReplyChannelRange :: ReplyChannelRange 288 testReplyChannelRange = mkReplyChannelRange testChainHash emptyTlvs 289 {-# NOINLINE testReplyChannelRange #-} 290 291 -- | Encoded ReplyChannelRange for decode benchmarks. 292 encodedReplyChannelRange :: BS.ByteString 293 encodedReplyChannelRange = case encodeReplyChannelRange testReplyChannelRange of 294 Right bs -> bs 295 Left _ -> error "encodedReplyChannelRange: encode failed" 296 {-# NOINLINE encodedReplyChannelRange #-} 297 298 -- Weigh benchmarks ------------------------------------------------------------ 299 300 main :: IO () 301 main = mainWith $ do 302 wgroup "channel_announcement" $ do 303 func "construct" (mkChannelAnnouncement 304 testSignature testSignature testChainHash testShortChannelId 305 testNodeId2 testNodeId testPoint testPoint) emptyFeatures 306 func "encode" encodeChannelAnnouncement testChannelAnnouncement 307 func "decode" decodeChannelAnnouncement encodedChannelAnnouncement 308 309 wgroup "node_announcement" $ do 310 func "construct" (mkNodeAnnouncement 311 testSignature emptyFeatures testNodeId testRgbColor testAlias) 312 [AddrIPv4 testIPv4 9735] 313 func "encode" encodeNodeAnnouncement testNodeAnnouncement 314 func "decode" decodeNodeAnnouncement encodedNodeAnnouncement 315 316 wgroup "channel_update" $ do 317 func "construct" (mkChannelUpdate testSignature testChainHash) 318 testShortChannelId 319 func "encode" encodeChannelUpdate testChannelUpdate 320 func "decode" decodeChannelUpdate encodedChannelUpdate 321 322 wgroup "announcement_signatures" $ do 323 func "construct" (mkAnnouncementSignatures testChannelId testShortChannelId) 324 testSignature 325 func "encode" encodeAnnouncementSignatures testAnnouncementSignatures 326 func "decode" decodeAnnouncementSignatures encodedAnnouncementSignatures 327 328 wgroup "query_channel_range" $ do 329 func "construct" (mkQueryChannelRange testChainHash) emptyTlvs 330 func "encode" encodeQueryChannelRange testQueryChannelRange 331 func "decode" decodeQueryChannelRange encodedQueryChannelRange 332 333 wgroup "reply_channel_range" $ do 334 func "construct" (mkReplyChannelRange testChainHash) emptyTlvs 335 func "encode" encodeReplyChannelRange testReplyChannelRange 336 func "decode" decodeReplyChannelRange encodedReplyChannelRange 337 338 wgroup "gossip_timestamp_filter" $ do 339 func "construct" mkGossipTimestampFilter testChainHash 340 func "encode" encodeGossipTimestampFilter testGossipTimestampFilter 341 func "decode" decodeGossipTimestampFilter encodedGossipTimestampFilter 342 343 wgroup "scid_list" $ do 344 func "encode (100)" encodeShortChannelIdList testScidList 345 func "decode (100)" decodeShortChannelIdList encodedScidList 346 347 wgroup "hash" $ do 348 func "channelAnnouncementHash" channelAnnouncementHash 349 encodedChannelAnnouncement 350 func "nodeAnnouncementHash" nodeAnnouncementHash encodedNodeAnnouncement 351 func "channelUpdateHash" channelUpdateHash encodedChannelUpdate 352 func "channelUpdateChecksum" channelUpdateChecksum encodedChannelUpdate 353 354 wgroup "validate" $ do 355 func "channelAnnouncement" validateChannelAnnouncement testChannelAnnouncement 356 func "nodeAnnouncement" validateNodeAnnouncement testNodeAnnouncement 357 func "channelUpdate" validateChannelUpdate testChannelUpdate 358 func "queryChannelRange" validateQueryChannelRange testQueryChannelRange 359 func "replyChannelRange" validateReplyChannelRange testReplyChannelRange