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