Codec.hs (25538B)
1 {-# OPTIONS_HADDOCK hide #-} 2 {-# LANGUAGE BangPatterns #-} 3 {-# LANGUAGE DeriveGeneric #-} 4 5 -- | 6 -- Module: Lightning.Protocol.BOLT7.Codec 7 -- Copyright: (c) 2025 Jared Tobin 8 -- License: MIT 9 -- Maintainer: Jared Tobin <jared@ppad.tech> 10 -- 11 -- Encoding and decoding of BOLT #7 messages. 12 13 module Lightning.Protocol.BOLT7.Codec ( 14 EncodeError(..) 15 , DecodeError(..) 16 , encode_message 17 , decode_message 18 , encode_channel_announcement 19 , decode_channel_announcement 20 , encode_node_announcement 21 , decode_node_announcement 22 , encode_channel_update 23 , decode_channel_update 24 , encode_announcement_signatures 25 , decode_announcement_signatures 26 , encode_query_short_channel_ids 27 , decode_query_short_channel_ids 28 , encode_reply_short_channel_ids_end 29 , decode_reply_short_channel_ids_end 30 , encode_query_channel_range 31 , decode_query_channel_range 32 , encode_reply_channel_range 33 , decode_reply_channel_range 34 , encode_gossip_timestamp_filter 35 , decode_gossip_timestamp_filter 36 ) where 37 38 import Control.DeepSeq (NFData) 39 import qualified Data.ByteString as BS 40 import Data.Word (Word8, Word16, Word32, Word64) 41 import GHC.Generics (Generic) 42 import Lightning.Protocol.BOLT1 43 ( ChainHash, MilliSatoshi, Point, ShortChannelId, Signature 44 , TlvError, TlvRecord(..), TlvStream ) 45 import qualified Lightning.Protocol.BOLT1 as BOLT1 46 import qualified Lightning.Protocol.BOLT9 as BOLT9 47 import Lightning.Protocol.BOLT7.Messages 48 import Lightning.Protocol.BOLT7.Types 49 50 -- errors --------------------------------------------------------------------- 51 52 -- | Why a message failed to encode. 53 data EncodeError 54 = EncodeLengthOverflow 55 -- ^ a length-prefixed field exceeds 65535 bytes 56 | EncodeInvalidTlvs 57 -- ^ a @_tlvs@ field holds a record of a type the message defines 58 | EncodeCountMismatch 59 -- ^ query flags, timestamps or checksums don't number one per 60 -- short channel id 61 | EncodeInvalidAddresses 62 -- ^ 'na_unknown_addresses' begins with a descriptor of a known type 63 deriving (Eq, Show, Generic) 64 65 instance NFData EncodeError 66 67 -- | Why a message failed to decode. 68 data DecodeError 69 = DecodeInsufficientBytes 70 -- ^ the input ended before a field did 71 | DecodeInvalidPoint 72 -- ^ a point lacks a compressed-encoding prefix (0x02 or 0x03) 73 | DecodeInvalidAmount 74 -- ^ an amount exceeds 21 million BTC 75 | DecodeInvalidBool 76 -- ^ a boolean byte is neither 0 nor 1 77 | DecodeInvalidShortChannelIds 78 -- ^ @encoded_short_ids@ lacks an encoding type, or isn't a whole 79 -- number of short channel ids 80 | DecodeUnknownEncoding !Word8 81 -- ^ an encoded array uses an unknown encoding type (type 1, zlib, 82 -- is no longer allowed) 83 | DecodeCountMismatch 84 -- ^ query flags, timestamps or checksums don't number one per 85 -- short channel id 86 | DecodeTlvError !TlvError 87 -- ^ the message's TLV stream is malformed 88 | DecodeInvalidTlvValue !Word64 89 -- ^ a known TLV record (of the given type) has a malformed value 90 | DecodeUnknownType !Word16 91 -- ^ the message type is not one of BOLT #7's 92 deriving (Eq, Show, Generic) 93 94 instance NFData DecodeError 95 96 -- messages ------------------------------------------------------------------- 97 98 -- | Encode a 'Message' payload (excluding the 2-byte message type; see 99 -- 'message_type'). Frame the result with 100 -- 'Lightning.Protocol.BOLT1.encode_envelope', which enforces the 101 -- 65535-byte message limit. 102 encode_message :: Message -> Either EncodeError BS.ByteString 103 encode_message m = case m of 104 MsgChannelAnnouncement a -> encode_channel_announcement a 105 MsgNodeAnnouncement a -> encode_node_announcement a 106 MsgChannelUpdate a -> Right (encode_channel_update a) 107 MsgAnnouncementSignatures a -> Right (encode_announcement_signatures a) 108 MsgQueryShortChannelIds a -> encode_query_short_channel_ids a 109 MsgReplyShortChannelIdsEnd a -> Right (encode_reply_short_channel_ids_end a) 110 MsgQueryChannelRange a -> encode_query_channel_range a 111 MsgReplyChannelRange a -> encode_reply_channel_range a 112 MsgGossipTimestampFilter a -> Right (encode_gossip_timestamp_filter a) 113 114 -- | Decode a message payload, given its message type (as split off by 115 -- 'Lightning.Protocol.BOLT1.decode_envelope'). 116 -- 117 -- >>> decode_message 260 "\NUL" 118 -- Left (DecodeUnknownType 260) 119 decode_message :: Word16 -> BS.ByteString -> Either DecodeError Message 120 decode_message t bs = case t of 121 256 -> MsgChannelAnnouncement <$> decode_channel_announcement bs 122 257 -> MsgNodeAnnouncement <$> decode_node_announcement bs 123 258 -> MsgChannelUpdate <$> decode_channel_update bs 124 259 -> MsgAnnouncementSignatures <$> decode_announcement_signatures bs 125 261 -> MsgQueryShortChannelIds <$> decode_query_short_channel_ids bs 126 262 -> MsgReplyShortChannelIdsEnd <$> decode_reply_short_channel_ids_end bs 127 263 -> MsgQueryChannelRange <$> decode_query_channel_range bs 128 264 -> MsgReplyChannelRange <$> decode_reply_channel_range bs 129 265 -> MsgGossipTimestampFilter <$> decode_gossip_timestamp_filter bs 130 _ -> Left (DecodeUnknownType t) 131 132 -- channel_announcement ------------------------------------------------------- 133 134 -- | Encode a t'ChannelAnnouncement' payload. Fails if the features exceed 135 -- 65535 bytes. 136 encode_channel_announcement 137 :: ChannelAnnouncement -> Either EncodeError BS.ByteString 138 encode_channel_announcement m = do 139 f <- prefixed (BOLT9.render (ca_features m)) 140 pure $ mconcat 141 [ BOLT1.un_signature (ca_node_signature_1 m) 142 , BOLT1.un_signature (ca_node_signature_2 m) 143 , BOLT1.un_signature (ca_bitcoin_signature_1 m) 144 , BOLT1.un_signature (ca_bitcoin_signature_2 m) 145 , f 146 , BOLT1.un_chain_hash (ca_chain_hash m) 147 , BOLT1.encode_short_channel_id (ca_short_channel_id m) 148 , BOLT1.un_point (ca_node_id_1 m) 149 , BOLT1.un_point (ca_node_id_2 m) 150 , BOLT1.un_point (ca_bitcoin_key_1 m) 151 , BOLT1.un_point (ca_bitcoin_key_2 m) 152 , BOLT1.encode_tlv_stream (ca_tlvs m) 153 ] 154 155 -- | Decode a t'ChannelAnnouncement' payload. 156 decode_channel_announcement 157 :: BS.ByteString -> Either DecodeError ChannelAnnouncement 158 decode_channel_announcement b0 = do 159 (ns1, b1) <- signature b0 160 (ns2, b2) <- signature b1 161 (bs1, b3) <- signature b2 162 (bs2, b4) <- signature b3 163 (f, b5) <- u16_prefixed b4 164 (ch, b6) <- chain_hash b5 165 (s, b7) <- short_channel_id b6 166 (n1, b8) <- point b7 167 (n2, b9) <- point b8 168 (bk1, b10) <- point b9 169 (bk2, b11) <- point b10 170 ext <- extension b11 171 pure ChannelAnnouncement 172 { ca_node_signature_1 = ns1 173 , ca_node_signature_2 = ns2 174 , ca_bitcoin_signature_1 = bs1 175 , ca_bitcoin_signature_2 = bs2 176 , ca_features = BOLT9.parse f 177 , ca_chain_hash = ch 178 , ca_short_channel_id = s 179 , ca_node_id_1 = n1 180 , ca_node_id_2 = n2 181 , ca_bitcoin_key_1 = bk1 182 , ca_bitcoin_key_2 = bk2 183 , ca_tlvs = ext 184 } 185 186 -- node_announcement ---------------------------------------------------------- 187 188 -- | Encode a t'NodeAnnouncement' payload. Fails if the features or the 189 -- addresses exceed 65535 bytes, or if 'na_unknown_addresses' begins 190 -- with a descriptor of a known type. 191 encode_node_announcement 192 :: NodeAnnouncement -> Either EncodeError BS.ByteString 193 encode_node_announcement m = do 194 f <- prefixed (BOLT9.render (na_features m)) 195 let unknown = na_unknown_addresses m 196 case BS.uncons unknown of 197 Just (t, _) | t >= 1 && t <= 5 -> Left EncodeInvalidAddresses 198 _ -> pure () 199 as <- prefixed (foldMap encode_address (na_addresses m) <> unknown) 200 let RgbColor r g b = na_rgb_color m 201 Alias al = na_alias m 202 pure $ mconcat 203 [ BOLT1.un_signature (na_signature m) 204 , f 205 , BOLT1.encode_u32 (na_timestamp m) 206 , BOLT1.un_point (na_node_id m) 207 , BS.pack [r, g, b] 208 , al 209 , as 210 , BOLT1.encode_tlv_stream (na_tlvs m) 211 ] 212 213 encode_address :: Address -> BS.ByteString 214 encode_address a = case a of 215 AddrIPv4 (IPv4Addr b) p -> BS.cons 1 (b <> BOLT1.encode_u16 p) 216 AddrIPv6 (IPv6Addr b) p -> BS.cons 2 (b <> BOLT1.encode_u16 p) 217 AddrTorV2 (TorV2Addr b) -> BS.cons 3 b 218 AddrTorV3 (TorV3Addr b) p -> BS.cons 4 (b <> BOLT1.encode_u16 p) 219 AddrDNS (Hostname h) p -> 220 BS.cons 5 (BS.cons (fromIntegral (BS.length h)) (h <> BOLT1.encode_u16 p)) 221 222 -- | Decode a t'NodeAnnouncement' payload. 223 -- 224 -- Address descriptors are parsed up to the first one of an unknown 225 -- type; it and the bytes after it are kept in 'na_unknown_addresses'. 226 -- A truncated descriptor of a known type is an error. 227 decode_node_announcement 228 :: BS.ByteString -> Either DecodeError NodeAnnouncement 229 decode_node_announcement b0 = do 230 (sig, b1) <- signature b0 231 (f, b2) <- u16_prefixed b1 232 (ts, b3) <- u32 b2 233 (nid, b4) <- point b3 234 (r, b5) <- u8 b4 235 (g, b6) <- u8 b5 236 (b, b7) <- u8 b6 237 (al, b8) <- bytes 32 b7 238 (as, b9) <- u16_prefixed b8 239 (known, unknown) <- addresses as 240 ext <- extension b9 241 pure NodeAnnouncement 242 { na_signature = sig 243 , na_features = BOLT9.parse f 244 , na_timestamp = ts 245 , na_node_id = nid 246 , na_rgb_color = RgbColor r g b 247 , na_alias = Alias al 248 , na_addresses = known 249 , na_unknown_addresses = unknown 250 , na_tlvs = ext 251 } 252 253 -- parse address descriptors, stopping at the first of an unknown type 254 addresses 255 :: BS.ByteString -> Either DecodeError ([Address], BS.ByteString) 256 addresses = go [] 257 where 258 go !acc !bs = case BS.uncons bs of 259 Nothing -> Right (reverse acc, BS.empty) 260 Just (t, r) -> case t of 261 1 -> with_port acc 4 (AddrIPv4 . IPv4Addr) r 262 2 -> with_port acc 16 (AddrIPv6 . IPv6Addr) r 263 3 -> do 264 (a, r1) <- bytes 12 r 265 go (AddrTorV2 (TorV2Addr a) : acc) r1 266 4 -> with_port acc 35 (AddrTorV3 . TorV3Addr) r 267 5 -> do 268 (n, r1) <- u8 r 269 (h, r2) <- bytes (fromIntegral n) r1 270 (p, r3) <- u16 r2 271 go (AddrDNS (Hostname h) p : acc) r3 272 _ -> Right (reverse acc, bs) 273 274 with_port acc n mk r = do 275 (a, r1) <- bytes n r 276 (p, r2) <- u16 r1 277 go (mk a p : acc) r2 278 279 -- channel_update ------------------------------------------------------------- 280 281 -- | Encode a t'ChannelUpdate' payload. 282 encode_channel_update :: ChannelUpdate -> BS.ByteString 283 encode_channel_update m = 284 let MessageFlags mf = cu_message_flags m 285 ChannelFlags cf = cu_channel_flags m 286 in mconcat 287 [ BOLT1.un_signature (cu_signature m) 288 , BOLT1.un_chain_hash (cu_chain_hash m) 289 , BOLT1.encode_short_channel_id (cu_short_channel_id m) 290 , BOLT1.encode_u32 (cu_timestamp m) 291 , BS.pack [mf, cf] 292 , BOLT1.encode_u16 (cu_cltv_expiry_delta m) 293 , BOLT1.encode_milli_satoshi (cu_htlc_minimum_msat m) 294 , BOLT1.encode_u32 (cu_fee_base_msat m) 295 , BOLT1.encode_u32 (cu_fee_proportional_millionths m) 296 , BOLT1.encode_milli_satoshi (cu_htlc_maximum_msat m) 297 , BOLT1.encode_tlv_stream (cu_tlvs m) 298 ] 299 300 -- | Decode a t'ChannelUpdate' payload. 301 -- 302 -- @htlc_maximum_msat@ is always present; the @must_be_one@ bit of 303 -- @message_flags@ is kept but not interpreted. 304 decode_channel_update :: BS.ByteString -> Either DecodeError ChannelUpdate 305 decode_channel_update b0 = do 306 (sig, b1) <- signature b0 307 (ch, b2) <- chain_hash b1 308 (s, b3) <- short_channel_id b2 309 (ts, b4) <- u32 b3 310 (mf, b5) <- u8 b4 311 (cf, b6) <- u8 b5 312 (cltv, b7) <- u16 b6 313 (hmin, b8) <- milli_satoshi b7 314 (fb, b9) <- u32 b8 315 (fp, b10) <- u32 b9 316 (hmax, b11) <- milli_satoshi b10 317 ext <- extension b11 318 pure ChannelUpdate 319 { cu_signature = sig 320 , cu_chain_hash = ch 321 , cu_short_channel_id = s 322 , cu_timestamp = ts 323 , cu_message_flags = MessageFlags mf 324 , cu_channel_flags = ChannelFlags cf 325 , cu_cltv_expiry_delta = cltv 326 , cu_htlc_minimum_msat = hmin 327 , cu_fee_base_msat = fb 328 , cu_fee_proportional_millionths = fp 329 , cu_htlc_maximum_msat = hmax 330 , cu_tlvs = ext 331 } 332 333 -- announcement_signatures ---------------------------------------------------- 334 335 -- | Encode an t'AnnouncementSignatures' payload. 336 encode_announcement_signatures :: AnnouncementSignatures -> BS.ByteString 337 encode_announcement_signatures m = mconcat 338 [ BOLT1.un_channel_id (as_channel_id m) 339 , BOLT1.encode_short_channel_id (as_short_channel_id m) 340 , BOLT1.un_signature (as_node_signature m) 341 , BOLT1.un_signature (as_bitcoin_signature m) 342 , BOLT1.encode_tlv_stream (as_tlvs m) 343 ] 344 345 -- | Decode an t'AnnouncementSignatures' payload. 346 decode_announcement_signatures 347 :: BS.ByteString -> Either DecodeError AnnouncementSignatures 348 decode_announcement_signatures b0 = do 349 (cid, b1) <- need (BOLT1.decode_channel_id b0) 350 (s, b2) <- short_channel_id b1 351 (ns, b3) <- signature b2 352 (bs, b4) <- signature b3 353 ext <- extension b4 354 pure (AnnouncementSignatures cid s ns bs ext) 355 356 -- query_short_channel_ids ---------------------------------------------------- 357 358 -- | Encode a t'QueryShortChannelIds' payload. Fails if the short channel 359 -- ids exceed the u16 length limit (8191 of them), if the query flags 360 -- don't number one per short channel id, or if 'qsci_tlvs' holds a 361 -- record of type 1. 362 encode_query_short_channel_ids 363 :: QueryShortChannelIds -> Either EncodeError BS.ByteString 364 encode_query_short_channel_ids m = do 365 let scids = qsci_short_channel_ids m 366 ids <- prefixed (encode_short_ids scids) 367 flags <- case qsci_query_flags m of 368 Nothing -> pure [] 369 Just fs 370 | length fs /= length scids -> Left EncodeCountMismatch 371 | otherwise -> pure 372 [TlvRecord 1 (BS.cons 0 (foldMap (\(QueryFlags w) -> 373 BOLT1.encode_bigsize w) fs))] 374 t <- merge [1] flags (qsci_tlvs m) 375 pure (BOLT1.un_chain_hash (qsci_chain_hash m) <> ids <> t) 376 377 -- | Decode a t'QueryShortChannelIds' payload. 378 -- 379 -- Fails on an unknown encoding type (including the deprecated zlib 380 -- encoding), on @encoded_short_ids@ that isn't a whole number of short 381 -- channel ids, and on query flags that don't number one per short 382 -- channel id. 383 -- 384 -- >>> let zlib = BS.replicate 32 0 <> "\NUL\STX\SOHx" 385 -- >>> decode_query_short_channel_ids zlib 386 -- Left (DecodeUnknownEncoding 1) 387 decode_query_short_channel_ids 388 :: BS.ByteString -> Either DecodeError QueryShortChannelIds 389 decode_query_short_channel_ids b0 = do 390 (ch, b1) <- chain_hash b0 391 (ids, b2) <- u16_prefixed b1 392 scids <- short_ids ids 393 s <- tlvs [1] b2 394 flags <- traverse (query_flags_value (length scids)) 395 (BOLT1.lookup_tlv 1 s) 396 pure QueryShortChannelIds 397 { qsci_chain_hash = ch 398 , qsci_short_channel_ids = scids 399 , qsci_query_flags = flags 400 , qsci_tlvs = BOLT1.filter_tlv_stream (/= 1) s 401 } 402 403 query_flags_value :: Int -> BS.ByteString -> Either DecodeError [QueryFlags] 404 query_flags_value n v = case BS.uncons v of 405 Nothing -> Left (DecodeInvalidTlvValue 1) 406 Just (0, r) -> do 407 fs <- bigsizes r 408 if length fs /= n 409 then Left DecodeCountMismatch 410 else Right (map QueryFlags fs) 411 Just (e, _) -> Left (DecodeUnknownEncoding e) 412 where 413 bigsizes !r 414 | BS.null r = Right [] 415 | otherwise = case BOLT1.decode_bigsize r of 416 Nothing -> Left (DecodeInvalidTlvValue 1) 417 Just (w, r1) -> (w :) <$> bigsizes r1 418 419 -- reply_short_channel_ids_end ------------------------------------------------ 420 421 -- | Encode a t'ReplyShortChannelIdsEnd' payload. 422 encode_reply_short_channel_ids_end 423 :: ReplyShortChannelIdsEnd -> BS.ByteString 424 encode_reply_short_channel_ids_end m = mconcat 425 [ BOLT1.un_chain_hash (rsce_chain_hash m) 426 , encode_bool (rsce_full_information m) 427 , BOLT1.encode_tlv_stream (rsce_tlvs m) 428 ] 429 430 -- | Decode a t'ReplyShortChannelIdsEnd' payload. 431 -- 432 -- >>> decode_reply_short_channel_ids_end (BS.replicate 32 0 <> "\STX") 433 -- Left DecodeInvalidBool 434 decode_reply_short_channel_ids_end 435 :: BS.ByteString -> Either DecodeError ReplyShortChannelIdsEnd 436 decode_reply_short_channel_ids_end b0 = do 437 (ch, b1) <- chain_hash b0 438 (full, b2) <- bool b1 439 ext <- extension b2 440 pure (ReplyShortChannelIdsEnd ch full ext) 441 442 -- query_channel_range -------------------------------------------------------- 443 444 -- | Encode a t'QueryChannelRange' payload. Fails if 'qcr_tlvs' holds a 445 -- record of type 1. 446 encode_query_channel_range 447 :: QueryChannelRange -> Either EncodeError BS.ByteString 448 encode_query_channel_range m = do 449 let opt = case qcr_query_option m of 450 Nothing -> [] 451 Just (QueryOption w) -> [TlvRecord 1 (BOLT1.encode_bigsize w)] 452 t <- merge [1] opt (qcr_tlvs m) 453 pure $ mconcat 454 [ BOLT1.un_chain_hash (qcr_chain_hash m) 455 , BOLT1.encode_u32 (qcr_first_blocknum m) 456 , BOLT1.encode_u32 (qcr_number_of_blocks m) 457 , t 458 ] 459 460 -- | Decode a t'QueryChannelRange' payload. 461 decode_query_channel_range 462 :: BS.ByteString -> Either DecodeError QueryChannelRange 463 decode_query_channel_range b0 = do 464 (ch, b1) <- chain_hash b0 465 (first, b2) <- u32 b1 466 (num, b3) <- u32 b2 467 s <- tlvs [1] b3 468 opt <- traverse option (BOLT1.lookup_tlv 1 s) 469 pure QueryChannelRange 470 { qcr_chain_hash = ch 471 , qcr_first_blocknum = first 472 , qcr_number_of_blocks = num 473 , qcr_query_option = opt 474 , qcr_tlvs = BOLT1.filter_tlv_stream (/= 1) s 475 } 476 where 477 option v = case BOLT1.decode_bigsize v of 478 Just (w, r) | BS.null r -> Right (QueryOption w) 479 _ -> Left (DecodeInvalidTlvValue 1) 480 481 -- reply_channel_range -------------------------------------------------------- 482 483 -- | Encode a t'ReplyChannelRange' payload. Fails if the short channel ids 484 -- exceed the u16 length limit (8191 of them), if the timestamps or 485 -- checksums don't number one per short channel id, or if 'rcr_tlvs' 486 -- holds a record of type 1 or 3. 487 encode_reply_channel_range 488 :: ReplyChannelRange -> Either EncodeError BS.ByteString 489 encode_reply_channel_range m = do 490 let scids = rcr_short_channel_ids m 491 n = length scids 492 count xs 493 | length xs /= n = Left EncodeCountMismatch 494 | otherwise = Right () 495 ids <- prefixed (encode_short_ids scids) 496 ts <- case rcr_timestamps m of 497 Nothing -> pure [] 498 Just xs -> do 499 count xs 500 pure [TlvRecord 1 (BS.cons 0 (foldMap 501 (\(ChannelUpdateTimestamps a b) -> pair a b) xs))] 502 cs <- case rcr_checksums m of 503 Nothing -> pure [] 504 Just xs -> do 505 count xs 506 pure [TlvRecord 3 (foldMap 507 (\(ChannelUpdateChecksums a b) -> pair a b) xs)] 508 t <- merge [1, 3] (ts <> cs) (rcr_tlvs m) 509 pure $ mconcat 510 [ BOLT1.un_chain_hash (rcr_chain_hash m) 511 , BOLT1.encode_u32 (rcr_first_blocknum m) 512 , BOLT1.encode_u32 (rcr_number_of_blocks m) 513 , encode_bool (rcr_sync_complete m) 514 , ids 515 , t 516 ] 517 where 518 pair a b = BOLT1.encode_u32 a <> BOLT1.encode_u32 b 519 520 -- | Decode a t'ReplyChannelRange' payload. 521 -- 522 -- Fails on an unknown encoding type (including the deprecated zlib 523 -- encoding), on @encoded_short_ids@ that isn't a whole number of short 524 -- channel ids, and on timestamps or checksums that don't number one 525 -- per short channel id. 526 decode_reply_channel_range 527 :: BS.ByteString -> Either DecodeError ReplyChannelRange 528 decode_reply_channel_range b0 = do 529 (ch, b1) <- chain_hash b0 530 (first, b2) <- u32 b1 531 (num, b3) <- u32 b2 532 (sync, b4) <- bool b3 533 (ids, b5) <- u16_prefixed b4 534 scids <- short_ids ids 535 s <- tlvs [1, 3] b5 536 let n = length scids 537 ts <- traverse (timestamps n) (BOLT1.lookup_tlv 1 s) 538 cs <- traverse (pairs 3 ChannelUpdateChecksums n) (BOLT1.lookup_tlv 3 s) 539 pure ReplyChannelRange 540 { rcr_chain_hash = ch 541 , rcr_first_blocknum = first 542 , rcr_number_of_blocks = num 543 , rcr_sync_complete = sync 544 , rcr_short_channel_ids = scids 545 , rcr_timestamps = ts 546 , rcr_checksums = cs 547 , rcr_tlvs = 548 BOLT1.filter_tlv_stream (\t -> t /= 1 && t /= 3) s 549 } 550 where 551 timestamps n v = case BS.uncons v of 552 Nothing -> Left (DecodeInvalidTlvValue 1) 553 Just (0, r) -> pairs 1 ChannelUpdateTimestamps n r 554 Just (e, _) -> Left (DecodeUnknownEncoding e) 555 556 -- decode an array of u32 pairs holding n elements 557 pairs 558 :: Word64 -> (Word32 -> Word32 -> a) -> Int -> BS.ByteString 559 -> Either DecodeError [a] 560 pairs t mk n r 561 | BS.length r `rem` 8 /= 0 = Left (DecodeInvalidTlvValue t) 562 | BS.length r `quot` 8 /= n = Left DecodeCountMismatch 563 | otherwise = Right (go r) 564 where 565 go !bs = case BOLT1.decode_u32 bs of 566 Nothing -> [] 567 Just (a, r1) -> case BOLT1.decode_u32 r1 of 568 Nothing -> [] 569 Just (b, r2) -> mk a b : go r2 570 571 -- gossip_timestamp_filter ---------------------------------------------------- 572 573 -- | Encode a t'GossipTimestampFilter' payload. 574 encode_gossip_timestamp_filter :: GossipTimestampFilter -> BS.ByteString 575 encode_gossip_timestamp_filter m = mconcat 576 [ BOLT1.un_chain_hash (gtf_chain_hash m) 577 , BOLT1.encode_u32 (gtf_first_timestamp m) 578 , BOLT1.encode_u32 (gtf_timestamp_range m) 579 , BOLT1.encode_tlv_stream (gtf_tlvs m) 580 ] 581 582 -- | Decode a t'GossipTimestampFilter' payload. 583 decode_gossip_timestamp_filter 584 :: BS.ByteString -> Either DecodeError GossipTimestampFilter 585 decode_gossip_timestamp_filter b0 = do 586 (ch, b1) <- chain_hash b0 587 (first, b2) <- u32 b1 588 (range, b3) <- u32 b2 589 ext <- extension b3 590 pure (GossipTimestampFilter ch first range ext) 591 592 -- encoded short channel ids -------------------------------------------------- 593 594 -- encoding type 0 (uncompressed), the only one allowed 595 encode_short_ids :: [ShortChannelId] -> BS.ByteString 596 encode_short_ids = BS.cons 0 . foldMap BOLT1.encode_short_channel_id 597 598 short_ids :: BS.ByteString -> Either DecodeError [ShortChannelId] 599 short_ids bs = case BS.uncons bs of 600 Nothing -> Left DecodeInvalidShortChannelIds 601 Just (0, r) 602 | BS.length r `rem` 8 == 0 -> Right (go r) 603 | otherwise -> Left DecodeInvalidShortChannelIds 604 Just (e, _) -> Left (DecodeUnknownEncoding e) 605 where 606 go !r = case BOLT1.decode_short_channel_id r of 607 Nothing -> [] 608 Just (s, r1) -> s : go r1 609 610 -- helpers -------------------------------------------------------------------- 611 612 need :: Maybe a -> Either DecodeError a 613 need = maybe (Left DecodeInsufficientBytes) Right 614 {-# INLINE need #-} 615 616 u8 :: BS.ByteString -> Either DecodeError (Word8, BS.ByteString) 617 u8 = need . BS.uncons 618 {-# INLINE u8 #-} 619 620 u16 :: BS.ByteString -> Either DecodeError (Word16, BS.ByteString) 621 u16 = need . BOLT1.decode_u16 622 {-# INLINE u16 #-} 623 624 u32 :: BS.ByteString -> Either DecodeError (Word32, BS.ByteString) 625 u32 = need . BOLT1.decode_u32 626 {-# INLINE u32 #-} 627 628 bytes 629 :: Int -> BS.ByteString 630 -> Either DecodeError (BS.ByteString, BS.ByteString) 631 bytes n bs 632 | BS.length bs < n = Left DecodeInsufficientBytes 633 | otherwise = Right (BS.splitAt n bs) 634 {-# INLINE bytes #-} 635 636 u16_prefixed 637 :: BS.ByteString -> Either DecodeError (BS.ByteString, BS.ByteString) 638 u16_prefixed = need . BOLT1.decode_u16_prefixed 639 {-# INLINE u16_prefixed #-} 640 641 bool :: BS.ByteString -> Either DecodeError (Bool, BS.ByteString) 642 bool bs = do 643 (b, r) <- u8 bs 644 case b of 645 0 -> Right (False, r) 646 1 -> Right (True, r) 647 _ -> Left DecodeInvalidBool 648 649 signature :: BS.ByteString -> Either DecodeError (Signature, BS.ByteString) 650 signature = need . BOLT1.decode_signature 651 {-# INLINE signature #-} 652 653 chain_hash :: BS.ByteString -> Either DecodeError (ChainHash, BS.ByteString) 654 chain_hash = need . BOLT1.decode_chain_hash 655 {-# INLINE chain_hash #-} 656 657 short_channel_id 658 :: BS.ByteString -> Either DecodeError (ShortChannelId, BS.ByteString) 659 short_channel_id = need . BOLT1.decode_short_channel_id 660 {-# INLINE short_channel_id #-} 661 662 point :: BS.ByteString -> Either DecodeError (Point, BS.ByteString) 663 point bs = do 664 (b, r) <- bytes 33 bs 665 case BOLT1.point b of 666 Nothing -> Left DecodeInvalidPoint 667 Just p -> Right (p, r) 668 669 milli_satoshi 670 :: BS.ByteString -> Either DecodeError (MilliSatoshi, BS.ByteString) 671 milli_satoshi bs = do 672 (w, r) <- need (BOLT1.decode_u64 bs) 673 case BOLT1.milli_satoshi w of 674 Nothing -> Left DecodeInvalidAmount 675 Just a -> Right (a, r) 676 677 -- a TLV stream with the given known types 678 tlvs :: [Word64] -> BS.ByteString -> Either DecodeError TlvStream 679 tlvs known bs = either (Left . DecodeTlvError) Right 680 (BOLT1.decode_tlv_stream (`elem` known) bs) 681 682 -- an extension stream, in which no types are known 683 extension :: BS.ByteString -> Either DecodeError TlvStream 684 extension = tlvs [] 685 {-# INLINE extension #-} 686 687 prefixed :: BS.ByteString -> Either EncodeError BS.ByteString 688 prefixed bs = 689 maybe (Left EncodeLengthOverflow) Right (BOLT1.encode_u16_prefixed bs) 690 {-# INLINE prefixed #-} 691 692 encode_bool :: Bool -> BS.ByteString 693 encode_bool b = BS.singleton (if b then 1 else 0) 694 {-# INLINE encode_bool #-} 695 696 -- encode typed records together with the extra records of a @_tlvs@ 697 -- field, which mustn't use any of the message's known types 698 merge 699 :: [Word64] -> [TlvRecord] -> TlvStream -> Either EncodeError BS.ByteString 700 merge known typed extra 701 | any ((`elem` known) . tlv_type) rs = Left EncodeInvalidTlvs 702 | otherwise = 703 maybe (Left EncodeInvalidTlvs) (Right . BOLT1.encode_tlv_stream) 704 (BOLT1.tlv_stream (typed <> rs)) 705 where 706 rs = BOLT1.un_tlv_stream extra