bolt4

Onion routing protocol, per BOLT #4 (docs.ppad.tech/bolt4).
git clone git://git.ppad.tech/bolt4.git
Log | Files | Refs | README | LICENSE

Types.hs (8645B)


      1 {-# OPTIONS_HADDOCK prune #-}
      2 {-# LANGUAGE BangPatterns #-}
      3 {-# LANGUAGE DeriveGeneric #-}
      4 {-# LANGUAGE PatternSynonyms #-}
      5 
      6 -- |
      7 -- Module: Lightning.Protocol.BOLT4.Types
      8 -- Copyright: (c) 2025 Jared Tobin
      9 -- License: MIT
     10 -- Maintainer: Jared Tobin <jared@ppad.tech>
     11 --
     12 -- Core data types for BOLT4 onion routing.
     13 
     14 module Lightning.Protocol.BOLT4.Types (
     15     -- * Packet types
     16     OnionPacket(..)
     17   , HopPayload(..)
     18   , ShortChannelId(..)
     19   , PaymentData(..)
     20   , TlvRecord(..)
     21 
     22     -- * Error types
     23   , FailureMessage(..)
     24   , FailureCode(..)
     25     -- ** Flag bits
     26   , pattern BADONION
     27   , pattern PERM
     28   , pattern NODE
     29   , pattern UPDATE
     30     -- ** Common failure codes
     31   , pattern InvalidRealm
     32   , pattern TemporaryNodeFailure
     33   , pattern PermanentNodeFailure
     34   , pattern RequiredNodeFeatureMissing
     35   , pattern InvalidOnionVersion
     36   , pattern InvalidOnionHmac
     37   , pattern InvalidOnionKey
     38   , pattern TemporaryChannelFailure
     39   , pattern PermanentChannelFailure
     40   , pattern AmountBelowMinimum
     41   , pattern FeeInsufficient
     42   , pattern IncorrectCltvExpiry
     43   , pattern ExpiryTooSoon
     44   , pattern IncorrectOrUnknownPaymentDetails
     45   , pattern FinalIncorrectCltvExpiry
     46   , pattern FinalIncorrectHtlcAmount
     47   , pattern ChannelDisabled
     48   , pattern ExpiryTooFar
     49   , pattern InvalidOnionPayload
     50   , pattern MppTimeout
     51 
     52     -- * Processing results
     53   , ProcessResult(..)
     54   , ForwardInfo(..)
     55   , ReceiveInfo(..)
     56 
     57     -- * Constants
     58   , onionPacketSize
     59   , hopPayloadsSize
     60   , hmacSize
     61   , pubkeySize
     62   , versionByte
     63   , maxPayloadSize
     64   ) where
     65 
     66 import Data.Bits ((.&.), (.|.))
     67 import qualified Data.ByteString as BS
     68 import Data.Word (Word8, Word16, Word32, Word64)
     69 import GHC.Generics (Generic)
     70 
     71 -- Packet types -------------------------------------------------------------
     72 
     73 -- | Complete onion packet (1366 bytes).
     74 data OnionPacket = OnionPacket
     75   { opVersion      :: {-# UNPACK #-} !Word8
     76   , opEphemeralKey :: !BS.ByteString  -- ^ 33 bytes, compressed pubkey
     77   , opHopPayloads  :: !BS.ByteString  -- ^ 1300 bytes
     78   , opHmac         :: !BS.ByteString  -- ^ 32 bytes
     79   } deriving (Eq, Show, Generic)
     80 
     81 -- | Parsed hop payload after decryption.
     82 data HopPayload = HopPayload
     83   { hpAmtToForward   :: !(Maybe Word64)         -- ^ TLV type 2
     84   , hpOutgoingCltv   :: !(Maybe Word32)         -- ^ TLV type 4
     85   , hpShortChannelId :: !(Maybe ShortChannelId) -- ^ TLV type 6
     86   , hpPaymentData    :: !(Maybe PaymentData)    -- ^ TLV type 8
     87   , hpEncryptedData  :: !(Maybe BS.ByteString)  -- ^ TLV type 10
     88   , hpCurrentPathKey :: !(Maybe BS.ByteString)  -- ^ TLV type 12
     89   , hpUnknownTlvs    :: ![TlvRecord]            -- ^ Unknown types
     90   } deriving (Eq, Show, Generic)
     91 
     92 -- | Short channel ID (8 bytes): block height, tx index, output index.
     93 data ShortChannelId = ShortChannelId
     94   { sciBlockHeight :: {-# UNPACK #-} !Word32  -- ^ 3 bytes in encoding
     95   , sciTxIndex     :: {-# UNPACK #-} !Word32  -- ^ 3 bytes in encoding
     96   , sciOutputIndex :: {-# UNPACK #-} !Word16  -- ^ 2 bytes in encoding
     97   } deriving (Eq, Show, Generic)
     98 
     99 -- | Payment data for final hop (TLV type 8).
    100 data PaymentData = PaymentData
    101   { pdPaymentSecret :: !BS.ByteString         -- ^ 32 bytes
    102   , pdTotalMsat     :: {-# UNPACK #-} !Word64
    103   } deriving (Eq, Show, Generic)
    104 
    105 -- | Generic TLV record for unknown/extension types.
    106 data TlvRecord = TlvRecord
    107   { tlvType  :: {-# UNPACK #-} !Word64
    108   , tlvValue :: !BS.ByteString
    109   } deriving (Eq, Show, Generic)
    110 
    111 -- Error types --------------------------------------------------------------
    112 
    113 -- | Failure message from intermediate or final node.
    114 data FailureMessage = FailureMessage
    115   { fmCode :: {-# UNPACK #-} !FailureCode
    116   , fmData :: !BS.ByteString
    117   , fmTlvs :: ![TlvRecord]
    118   } deriving (Eq, Show, Generic)
    119 
    120 -- | 2-byte failure code with flag bits.
    121 newtype FailureCode = FailureCode Word16
    122   deriving (Eq, Show)
    123 
    124 -- Flag bits
    125 
    126 -- | BADONION flag (0x8000): error was in parsing the onion.
    127 pattern BADONION :: Word16
    128 pattern BADONION = 0x8000
    129 
    130 -- | PERM flag (0x4000): permanent failure, do not retry.
    131 pattern PERM :: Word16
    132 pattern PERM = 0x4000
    133 
    134 -- | NODE flag (0x2000): node failure rather than channel.
    135 pattern NODE :: Word16
    136 pattern NODE = 0x2000
    137 
    138 -- | UPDATE flag (0x1000): channel update is attached.
    139 pattern UPDATE :: Word16
    140 pattern UPDATE = 0x1000
    141 
    142 -- Common failure codes
    143 
    144 -- | Invalid realm byte in onion.
    145 pattern InvalidRealm :: FailureCode
    146 pattern InvalidRealm = FailureCode 0x4001  -- PERM .|. 1
    147 
    148 -- | Temporary node failure.
    149 pattern TemporaryNodeFailure :: FailureCode
    150 pattern TemporaryNodeFailure = FailureCode 0x2002  -- NODE .|. 2
    151 
    152 -- | Permanent node failure.
    153 pattern PermanentNodeFailure :: FailureCode
    154 pattern PermanentNodeFailure = FailureCode 0x6002  -- PERM .|. NODE .|. 2
    155 
    156 -- | Required node feature missing.
    157 pattern RequiredNodeFeatureMissing :: FailureCode
    158 pattern RequiredNodeFeatureMissing = FailureCode 0x6003  -- PERM .|. NODE .|. 3
    159 
    160 -- | Invalid onion version.
    161 pattern InvalidOnionVersion :: FailureCode
    162 pattern InvalidOnionVersion = FailureCode 0xC004  -- BADONION .|. PERM .|. 4
    163 
    164 -- | Invalid HMAC in onion.
    165 pattern InvalidOnionHmac :: FailureCode
    166 pattern InvalidOnionHmac = FailureCode 0xC005  -- BADONION .|. PERM .|. 5
    167 
    168 -- | Invalid ephemeral key in onion.
    169 pattern InvalidOnionKey :: FailureCode
    170 pattern InvalidOnionKey = FailureCode 0xC006  -- BADONION .|. PERM .|. 6
    171 
    172 -- | Temporary channel failure.
    173 pattern TemporaryChannelFailure :: FailureCode
    174 pattern TemporaryChannelFailure = FailureCode 0x1007  -- UPDATE .|. 7
    175 
    176 -- | Permanent channel failure.
    177 pattern PermanentChannelFailure :: FailureCode
    178 pattern PermanentChannelFailure = FailureCode 0x4008  -- PERM .|. 8
    179 
    180 -- | Amount below minimum for channel.
    181 pattern AmountBelowMinimum :: FailureCode
    182 pattern AmountBelowMinimum = FailureCode 0x100B  -- UPDATE .|. 11
    183 
    184 -- | Fee insufficient.
    185 pattern FeeInsufficient :: FailureCode
    186 pattern FeeInsufficient = FailureCode 0x100C  -- UPDATE .|. 12
    187 
    188 -- | Incorrect CLTV expiry.
    189 pattern IncorrectCltvExpiry :: FailureCode
    190 pattern IncorrectCltvExpiry = FailureCode 0x100D  -- UPDATE .|. 13
    191 
    192 -- | Expiry too soon.
    193 pattern ExpiryTooSoon :: FailureCode
    194 pattern ExpiryTooSoon = FailureCode 0x100E  -- UPDATE .|. 14
    195 
    196 -- | Payment details incorrect or unknown.
    197 pattern IncorrectOrUnknownPaymentDetails :: FailureCode
    198 pattern IncorrectOrUnknownPaymentDetails = FailureCode 0x400F  -- PERM .|. 15
    199 
    200 -- | Final incorrect CLTV expiry.
    201 pattern FinalIncorrectCltvExpiry :: FailureCode
    202 pattern FinalIncorrectCltvExpiry = FailureCode 18  -- 0x12
    203 
    204 -- | Final incorrect HTLC amount.
    205 pattern FinalIncorrectHtlcAmount :: FailureCode
    206 pattern FinalIncorrectHtlcAmount = FailureCode 19  -- 0x13
    207 
    208 -- | Channel disabled.
    209 pattern ChannelDisabled :: FailureCode
    210 pattern ChannelDisabled = FailureCode 0x1014  -- UPDATE .|. 20
    211 
    212 -- | Expiry too far.
    213 pattern ExpiryTooFar :: FailureCode
    214 pattern ExpiryTooFar = FailureCode 21  -- 0x15
    215 
    216 -- | Invalid onion payload.
    217 pattern InvalidOnionPayload :: FailureCode
    218 pattern InvalidOnionPayload = FailureCode 0x4016  -- PERM .|. 22
    219 
    220 -- | MPP timeout.
    221 pattern MppTimeout :: FailureCode
    222 pattern MppTimeout = FailureCode 23  -- 0x17
    223 
    224 -- Processing results -------------------------------------------------------
    225 
    226 -- | Result of processing an onion packet.
    227 data ProcessResult
    228   = Forward !ForwardInfo  -- ^ Forward to next hop
    229   | Receive !ReceiveInfo  -- ^ Final destination reached
    230   deriving (Eq, Show, Generic)
    231 
    232 -- | Information for forwarding to next hop.
    233 data ForwardInfo = ForwardInfo
    234   { fiNextPacket   :: !OnionPacket
    235   , fiPayload      :: !HopPayload
    236   , fiSharedSecret :: !BS.ByteString  -- ^ For error attribution
    237   } deriving (Eq, Show, Generic)
    238 
    239 -- | Information for receiving at final destination.
    240 data ReceiveInfo = ReceiveInfo
    241   { riPayload      :: !HopPayload
    242   , riSharedSecret :: !BS.ByteString
    243   } deriving (Eq, Show, Generic)
    244 
    245 -- Constants ----------------------------------------------------------------
    246 
    247 -- | Total onion packet size (1366 bytes).
    248 onionPacketSize :: Int
    249 onionPacketSize = 1366
    250 {-# INLINE onionPacketSize #-}
    251 
    252 -- | Hop payloads section size (1300 bytes).
    253 hopPayloadsSize :: Int
    254 hopPayloadsSize = 1300
    255 {-# INLINE hopPayloadsSize #-}
    256 
    257 -- | HMAC size (32 bytes).
    258 hmacSize :: Int
    259 hmacSize = 32
    260 {-# INLINE hmacSize #-}
    261 
    262 -- | Compressed public key size (33 bytes).
    263 pubkeySize :: Int
    264 pubkeySize = 33
    265 {-# INLINE pubkeySize #-}
    266 
    267 -- | Version byte for onion packets.
    268 versionByte :: Word8
    269 versionByte = 0x00
    270 {-# INLINE versionByte #-}
    271 
    272 -- | Maximum payload size (1300 - 32 - 1 = 1267 bytes).
    273 maxPayloadSize :: Int
    274 maxPayloadSize = hopPayloadsSize - hmacSize - 1
    275 {-# INLINE maxPayloadSize #-}
    276 
    277 -- Silence unused import warning
    278 _useBits :: Word16
    279 _useBits = BADONION .&. PERM .|. NODE .|. UPDATE