{-# OPTIONS_HADDOCK prune #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE PatternSynonyms #-}

-- |
-- Module: Lightning.Protocol.BOLT4.Types
-- Copyright: (c) 2025 Jared Tobin
-- License: MIT
-- Maintainer: Jared Tobin <jared@ppad.tech>
--
-- Core data types for BOLT4 onion routing.

module Lightning.Protocol.BOLT4.Types (
    -- * Packet types
    OnionPacket(..)
  , HopPayload(..)
  , ShortChannelId(..)
  , PaymentData(..)
  , TlvRecord(..)

    -- * Error types
  , FailureMessage(..)
  , FailureCode(..)
    -- ** Flag bits
  , pattern BADONION
  , pattern PERM
  , pattern NODE
  , pattern UPDATE
    -- ** Common failure codes
  , pattern InvalidRealm
  , pattern TemporaryNodeFailure
  , pattern PermanentNodeFailure
  , pattern RequiredNodeFeatureMissing
  , pattern InvalidOnionVersion
  , pattern InvalidOnionHmac
  , pattern InvalidOnionKey
  , pattern TemporaryChannelFailure
  , pattern PermanentChannelFailure
  , pattern AmountBelowMinimum
  , pattern FeeInsufficient
  , pattern IncorrectCltvExpiry
  , pattern ExpiryTooSoon
  , pattern IncorrectOrUnknownPaymentDetails
  , pattern FinalIncorrectCltvExpiry
  , pattern FinalIncorrectHtlcAmount
  , pattern ChannelDisabled
  , pattern ExpiryTooFar
  , pattern InvalidOnionPayload
  , pattern MppTimeout

    -- * Processing results
  , ProcessResult(..)
  , ForwardInfo(..)
  , ReceiveInfo(..)

    -- * Constants
  , onionPacketSize
  , hopPayloadsSize
  , hmacSize
  , pubkeySize
  , versionByte
  , maxPayloadSize
  ) where

import Data.Bits ((.&.), (.|.))
import qualified Data.ByteString as BS
import Data.Word (Word8, Word16, Word32, Word64)
import GHC.Generics (Generic)

-- Packet types -------------------------------------------------------------

-- | Complete onion packet (1366 bytes).
data OnionPacket = OnionPacket
  { OnionPacket -> Word8
opVersion      :: {-# UNPACK #-} !Word8
  , OnionPacket -> ByteString
opEphemeralKey :: !BS.ByteString  -- ^ 33 bytes, compressed pubkey
  , OnionPacket -> ByteString
opHopPayloads  :: !BS.ByteString  -- ^ 1300 bytes
  , OnionPacket -> ByteString
opHmac         :: !BS.ByteString  -- ^ 32 bytes
  } deriving (OnionPacket -> OnionPacket -> Bool
(OnionPacket -> OnionPacket -> Bool)
-> (OnionPacket -> OnionPacket -> Bool) -> Eq OnionPacket
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: OnionPacket -> OnionPacket -> Bool
== :: OnionPacket -> OnionPacket -> Bool
$c/= :: OnionPacket -> OnionPacket -> Bool
/= :: OnionPacket -> OnionPacket -> Bool
Eq, Int -> OnionPacket -> ShowS
[OnionPacket] -> ShowS
OnionPacket -> String
(Int -> OnionPacket -> ShowS)
-> (OnionPacket -> String)
-> ([OnionPacket] -> ShowS)
-> Show OnionPacket
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> OnionPacket -> ShowS
showsPrec :: Int -> OnionPacket -> ShowS
$cshow :: OnionPacket -> String
show :: OnionPacket -> String
$cshowList :: [OnionPacket] -> ShowS
showList :: [OnionPacket] -> ShowS
Show, (forall x. OnionPacket -> Rep OnionPacket x)
-> (forall x. Rep OnionPacket x -> OnionPacket)
-> Generic OnionPacket
forall x. Rep OnionPacket x -> OnionPacket
forall x. OnionPacket -> Rep OnionPacket x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. OnionPacket -> Rep OnionPacket x
from :: forall x. OnionPacket -> Rep OnionPacket x
$cto :: forall x. Rep OnionPacket x -> OnionPacket
to :: forall x. Rep OnionPacket x -> OnionPacket
Generic)

-- | Parsed hop payload after decryption.
data HopPayload = HopPayload
  { HopPayload -> Maybe Word64
hpAmtToForward   :: !(Maybe Word64)         -- ^ TLV type 2
  , HopPayload -> Maybe Word32
hpOutgoingCltv   :: !(Maybe Word32)         -- ^ TLV type 4
  , HopPayload -> Maybe ShortChannelId
hpShortChannelId :: !(Maybe ShortChannelId) -- ^ TLV type 6
  , HopPayload -> Maybe PaymentData
hpPaymentData    :: !(Maybe PaymentData)    -- ^ TLV type 8
  , HopPayload -> Maybe ByteString
hpEncryptedData  :: !(Maybe BS.ByteString)  -- ^ TLV type 10
  , HopPayload -> Maybe ByteString
hpCurrentPathKey :: !(Maybe BS.ByteString)  -- ^ TLV type 12
  , HopPayload -> [TlvRecord]
hpUnknownTlvs    :: ![TlvRecord]            -- ^ Unknown types
  } deriving (HopPayload -> HopPayload -> Bool
(HopPayload -> HopPayload -> Bool)
-> (HopPayload -> HopPayload -> Bool) -> Eq HopPayload
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: HopPayload -> HopPayload -> Bool
== :: HopPayload -> HopPayload -> Bool
$c/= :: HopPayload -> HopPayload -> Bool
/= :: HopPayload -> HopPayload -> Bool
Eq, Int -> HopPayload -> ShowS
[HopPayload] -> ShowS
HopPayload -> String
(Int -> HopPayload -> ShowS)
-> (HopPayload -> String)
-> ([HopPayload] -> ShowS)
-> Show HopPayload
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> HopPayload -> ShowS
showsPrec :: Int -> HopPayload -> ShowS
$cshow :: HopPayload -> String
show :: HopPayload -> String
$cshowList :: [HopPayload] -> ShowS
showList :: [HopPayload] -> ShowS
Show, (forall x. HopPayload -> Rep HopPayload x)
-> (forall x. Rep HopPayload x -> HopPayload) -> Generic HopPayload
forall x. Rep HopPayload x -> HopPayload
forall x. HopPayload -> Rep HopPayload x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. HopPayload -> Rep HopPayload x
from :: forall x. HopPayload -> Rep HopPayload x
$cto :: forall x. Rep HopPayload x -> HopPayload
to :: forall x. Rep HopPayload x -> HopPayload
Generic)

-- | Short channel ID (8 bytes): block height, tx index, output index.
data ShortChannelId = ShortChannelId
  { ShortChannelId -> Word32
sciBlockHeight :: {-# UNPACK #-} !Word32  -- ^ 3 bytes in encoding
  , ShortChannelId -> Word32
sciTxIndex     :: {-# UNPACK #-} !Word32  -- ^ 3 bytes in encoding
  , ShortChannelId -> Word16
sciOutputIndex :: {-# UNPACK #-} !Word16  -- ^ 2 bytes in encoding
  } deriving (ShortChannelId -> ShortChannelId -> Bool
(ShortChannelId -> ShortChannelId -> Bool)
-> (ShortChannelId -> ShortChannelId -> Bool) -> Eq ShortChannelId
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ShortChannelId -> ShortChannelId -> Bool
== :: ShortChannelId -> ShortChannelId -> Bool
$c/= :: ShortChannelId -> ShortChannelId -> Bool
/= :: ShortChannelId -> ShortChannelId -> Bool
Eq, Int -> ShortChannelId -> ShowS
[ShortChannelId] -> ShowS
ShortChannelId -> String
(Int -> ShortChannelId -> ShowS)
-> (ShortChannelId -> String)
-> ([ShortChannelId] -> ShowS)
-> Show ShortChannelId
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ShortChannelId -> ShowS
showsPrec :: Int -> ShortChannelId -> ShowS
$cshow :: ShortChannelId -> String
show :: ShortChannelId -> String
$cshowList :: [ShortChannelId] -> ShowS
showList :: [ShortChannelId] -> ShowS
Show, (forall x. ShortChannelId -> Rep ShortChannelId x)
-> (forall x. Rep ShortChannelId x -> ShortChannelId)
-> Generic ShortChannelId
forall x. Rep ShortChannelId x -> ShortChannelId
forall x. ShortChannelId -> Rep ShortChannelId x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. ShortChannelId -> Rep ShortChannelId x
from :: forall x. ShortChannelId -> Rep ShortChannelId x
$cto :: forall x. Rep ShortChannelId x -> ShortChannelId
to :: forall x. Rep ShortChannelId x -> ShortChannelId
Generic)

-- | Payment data for final hop (TLV type 8).
data PaymentData = PaymentData
  { PaymentData -> ByteString
pdPaymentSecret :: !BS.ByteString         -- ^ 32 bytes
  , PaymentData -> Word64
pdTotalMsat     :: {-# UNPACK #-} !Word64
  } deriving (PaymentData -> PaymentData -> Bool
(PaymentData -> PaymentData -> Bool)
-> (PaymentData -> PaymentData -> Bool) -> Eq PaymentData
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PaymentData -> PaymentData -> Bool
== :: PaymentData -> PaymentData -> Bool
$c/= :: PaymentData -> PaymentData -> Bool
/= :: PaymentData -> PaymentData -> Bool
Eq, Int -> PaymentData -> ShowS
[PaymentData] -> ShowS
PaymentData -> String
(Int -> PaymentData -> ShowS)
-> (PaymentData -> String)
-> ([PaymentData] -> ShowS)
-> Show PaymentData
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PaymentData -> ShowS
showsPrec :: Int -> PaymentData -> ShowS
$cshow :: PaymentData -> String
show :: PaymentData -> String
$cshowList :: [PaymentData] -> ShowS
showList :: [PaymentData] -> ShowS
Show, (forall x. PaymentData -> Rep PaymentData x)
-> (forall x. Rep PaymentData x -> PaymentData)
-> Generic PaymentData
forall x. Rep PaymentData x -> PaymentData
forall x. PaymentData -> Rep PaymentData x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. PaymentData -> Rep PaymentData x
from :: forall x. PaymentData -> Rep PaymentData x
$cto :: forall x. Rep PaymentData x -> PaymentData
to :: forall x. Rep PaymentData x -> PaymentData
Generic)

-- | Generic TLV record for unknown/extension types.
data TlvRecord = TlvRecord
  { TlvRecord -> Word64
tlvType  :: {-# UNPACK #-} !Word64
  , TlvRecord -> ByteString
tlvValue :: !BS.ByteString
  } deriving (TlvRecord -> TlvRecord -> Bool
(TlvRecord -> TlvRecord -> Bool)
-> (TlvRecord -> TlvRecord -> Bool) -> Eq TlvRecord
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: TlvRecord -> TlvRecord -> Bool
== :: TlvRecord -> TlvRecord -> Bool
$c/= :: TlvRecord -> TlvRecord -> Bool
/= :: TlvRecord -> TlvRecord -> Bool
Eq, Int -> TlvRecord -> ShowS
[TlvRecord] -> ShowS
TlvRecord -> String
(Int -> TlvRecord -> ShowS)
-> (TlvRecord -> String)
-> ([TlvRecord] -> ShowS)
-> Show TlvRecord
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> TlvRecord -> ShowS
showsPrec :: Int -> TlvRecord -> ShowS
$cshow :: TlvRecord -> String
show :: TlvRecord -> String
$cshowList :: [TlvRecord] -> ShowS
showList :: [TlvRecord] -> ShowS
Show, (forall x. TlvRecord -> Rep TlvRecord x)
-> (forall x. Rep TlvRecord x -> TlvRecord) -> Generic TlvRecord
forall x. Rep TlvRecord x -> TlvRecord
forall x. TlvRecord -> Rep TlvRecord x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. TlvRecord -> Rep TlvRecord x
from :: forall x. TlvRecord -> Rep TlvRecord x
$cto :: forall x. Rep TlvRecord x -> TlvRecord
to :: forall x. Rep TlvRecord x -> TlvRecord
Generic)

-- Error types --------------------------------------------------------------

-- | Failure message from intermediate or final node.
data FailureMessage = FailureMessage
  { FailureMessage -> FailureCode
fmCode :: {-# UNPACK #-} !FailureCode
  , FailureMessage -> ByteString
fmData :: !BS.ByteString
  , FailureMessage -> [TlvRecord]
fmTlvs :: ![TlvRecord]
  } deriving (FailureMessage -> FailureMessage -> Bool
(FailureMessage -> FailureMessage -> Bool)
-> (FailureMessage -> FailureMessage -> Bool) -> Eq FailureMessage
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FailureMessage -> FailureMessage -> Bool
== :: FailureMessage -> FailureMessage -> Bool
$c/= :: FailureMessage -> FailureMessage -> Bool
/= :: FailureMessage -> FailureMessage -> Bool
Eq, Int -> FailureMessage -> ShowS
[FailureMessage] -> ShowS
FailureMessage -> String
(Int -> FailureMessage -> ShowS)
-> (FailureMessage -> String)
-> ([FailureMessage] -> ShowS)
-> Show FailureMessage
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> FailureMessage -> ShowS
showsPrec :: Int -> FailureMessage -> ShowS
$cshow :: FailureMessage -> String
show :: FailureMessage -> String
$cshowList :: [FailureMessage] -> ShowS
showList :: [FailureMessage] -> ShowS
Show, (forall x. FailureMessage -> Rep FailureMessage x)
-> (forall x. Rep FailureMessage x -> FailureMessage)
-> Generic FailureMessage
forall x. Rep FailureMessage x -> FailureMessage
forall x. FailureMessage -> Rep FailureMessage x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. FailureMessage -> Rep FailureMessage x
from :: forall x. FailureMessage -> Rep FailureMessage x
$cto :: forall x. Rep FailureMessage x -> FailureMessage
to :: forall x. Rep FailureMessage x -> FailureMessage
Generic)

-- | 2-byte failure code with flag bits.
newtype FailureCode = FailureCode Word16
  deriving (FailureCode -> FailureCode -> Bool
(FailureCode -> FailureCode -> Bool)
-> (FailureCode -> FailureCode -> Bool) -> Eq FailureCode
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FailureCode -> FailureCode -> Bool
== :: FailureCode -> FailureCode -> Bool
$c/= :: FailureCode -> FailureCode -> Bool
/= :: FailureCode -> FailureCode -> Bool
Eq, Int -> FailureCode -> ShowS
[FailureCode] -> ShowS
FailureCode -> String
(Int -> FailureCode -> ShowS)
-> (FailureCode -> String)
-> ([FailureCode] -> ShowS)
-> Show FailureCode
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> FailureCode -> ShowS
showsPrec :: Int -> FailureCode -> ShowS
$cshow :: FailureCode -> String
show :: FailureCode -> String
$cshowList :: [FailureCode] -> ShowS
showList :: [FailureCode] -> ShowS
Show)

-- Flag bits

-- | BADONION flag (0x8000): error was in parsing the onion.
pattern BADONION :: Word16
pattern $mBADONION :: forall {r}. Word16 -> ((# #) -> r) -> ((# #) -> r) -> r
$bBADONION :: Word16
BADONION = 0x8000

-- | PERM flag (0x4000): permanent failure, do not retry.
pattern PERM :: Word16
pattern $mPERM :: forall {r}. Word16 -> ((# #) -> r) -> ((# #) -> r) -> r
$bPERM :: Word16
PERM = 0x4000

-- | NODE flag (0x2000): node failure rather than channel.
pattern NODE :: Word16
pattern $mNODE :: forall {r}. Word16 -> ((# #) -> r) -> ((# #) -> r) -> r
$bNODE :: Word16
NODE = 0x2000

-- | UPDATE flag (0x1000): channel update is attached.
pattern UPDATE :: Word16
pattern $mUPDATE :: forall {r}. Word16 -> ((# #) -> r) -> ((# #) -> r) -> r
$bUPDATE :: Word16
UPDATE = 0x1000

-- Common failure codes

-- | Invalid realm byte in onion.
pattern InvalidRealm :: FailureCode
pattern $mInvalidRealm :: forall {r}. FailureCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bInvalidRealm :: FailureCode
InvalidRealm = FailureCode 0x4001  -- PERM .|. 1

-- | Temporary node failure.
pattern TemporaryNodeFailure :: FailureCode
pattern $mTemporaryNodeFailure :: forall {r}. FailureCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bTemporaryNodeFailure :: FailureCode
TemporaryNodeFailure = FailureCode 0x2002  -- NODE .|. 2

-- | Permanent node failure.
pattern PermanentNodeFailure :: FailureCode
pattern $mPermanentNodeFailure :: forall {r}. FailureCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bPermanentNodeFailure :: FailureCode
PermanentNodeFailure = FailureCode 0x6002  -- PERM .|. NODE .|. 2

-- | Required node feature missing.
pattern RequiredNodeFeatureMissing :: FailureCode
pattern $mRequiredNodeFeatureMissing :: forall {r}. FailureCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bRequiredNodeFeatureMissing :: FailureCode
RequiredNodeFeatureMissing = FailureCode 0x6003  -- PERM .|. NODE .|. 3

-- | Invalid onion version.
pattern InvalidOnionVersion :: FailureCode
pattern $mInvalidOnionVersion :: forall {r}. FailureCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bInvalidOnionVersion :: FailureCode
InvalidOnionVersion = FailureCode 0xC004  -- BADONION .|. PERM .|. 4

-- | Invalid HMAC in onion.
pattern InvalidOnionHmac :: FailureCode
pattern $mInvalidOnionHmac :: forall {r}. FailureCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bInvalidOnionHmac :: FailureCode
InvalidOnionHmac = FailureCode 0xC005  -- BADONION .|. PERM .|. 5

-- | Invalid ephemeral key in onion.
pattern InvalidOnionKey :: FailureCode
pattern $mInvalidOnionKey :: forall {r}. FailureCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bInvalidOnionKey :: FailureCode
InvalidOnionKey = FailureCode 0xC006  -- BADONION .|. PERM .|. 6

-- | Temporary channel failure.
pattern TemporaryChannelFailure :: FailureCode
pattern $mTemporaryChannelFailure :: forall {r}. FailureCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bTemporaryChannelFailure :: FailureCode
TemporaryChannelFailure = FailureCode 0x1007  -- UPDATE .|. 7

-- | Permanent channel failure.
pattern PermanentChannelFailure :: FailureCode
pattern $mPermanentChannelFailure :: forall {r}. FailureCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bPermanentChannelFailure :: FailureCode
PermanentChannelFailure = FailureCode 0x4008  -- PERM .|. 8

-- | Amount below minimum for channel.
pattern AmountBelowMinimum :: FailureCode
pattern $mAmountBelowMinimum :: forall {r}. FailureCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bAmountBelowMinimum :: FailureCode
AmountBelowMinimum = FailureCode 0x100B  -- UPDATE .|. 11

-- | Fee insufficient.
pattern FeeInsufficient :: FailureCode
pattern $mFeeInsufficient :: forall {r}. FailureCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bFeeInsufficient :: FailureCode
FeeInsufficient = FailureCode 0x100C  -- UPDATE .|. 12

-- | Incorrect CLTV expiry.
pattern IncorrectCltvExpiry :: FailureCode
pattern $mIncorrectCltvExpiry :: forall {r}. FailureCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bIncorrectCltvExpiry :: FailureCode
IncorrectCltvExpiry = FailureCode 0x100D  -- UPDATE .|. 13

-- | Expiry too soon.
pattern ExpiryTooSoon :: FailureCode
pattern $mExpiryTooSoon :: forall {r}. FailureCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bExpiryTooSoon :: FailureCode
ExpiryTooSoon = FailureCode 0x100E  -- UPDATE .|. 14

-- | Payment details incorrect or unknown.
pattern IncorrectOrUnknownPaymentDetails :: FailureCode
pattern $mIncorrectOrUnknownPaymentDetails :: forall {r}. FailureCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bIncorrectOrUnknownPaymentDetails :: FailureCode
IncorrectOrUnknownPaymentDetails = FailureCode 0x400F  -- PERM .|. 15

-- | Final incorrect CLTV expiry.
pattern FinalIncorrectCltvExpiry :: FailureCode
pattern $mFinalIncorrectCltvExpiry :: forall {r}. FailureCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bFinalIncorrectCltvExpiry :: FailureCode
FinalIncorrectCltvExpiry = FailureCode 18  -- 0x12

-- | Final incorrect HTLC amount.
pattern FinalIncorrectHtlcAmount :: FailureCode
pattern $mFinalIncorrectHtlcAmount :: forall {r}. FailureCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bFinalIncorrectHtlcAmount :: FailureCode
FinalIncorrectHtlcAmount = FailureCode 19  -- 0x13

-- | Channel disabled.
pattern ChannelDisabled :: FailureCode
pattern $mChannelDisabled :: forall {r}. FailureCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bChannelDisabled :: FailureCode
ChannelDisabled = FailureCode 0x1014  -- UPDATE .|. 20

-- | Expiry too far.
pattern ExpiryTooFar :: FailureCode
pattern $mExpiryTooFar :: forall {r}. FailureCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bExpiryTooFar :: FailureCode
ExpiryTooFar = FailureCode 21  -- 0x15

-- | Invalid onion payload.
pattern InvalidOnionPayload :: FailureCode
pattern $mInvalidOnionPayload :: forall {r}. FailureCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bInvalidOnionPayload :: FailureCode
InvalidOnionPayload = FailureCode 0x4016  -- PERM .|. 22

-- | MPP timeout.
pattern MppTimeout :: FailureCode
pattern $mMppTimeout :: forall {r}. FailureCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bMppTimeout :: FailureCode
MppTimeout = FailureCode 23  -- 0x17

-- Processing results -------------------------------------------------------

-- | Result of processing an onion packet.
data ProcessResult
  = Forward !ForwardInfo  -- ^ Forward to next hop
  | Receive !ReceiveInfo  -- ^ Final destination reached
  deriving (ProcessResult -> ProcessResult -> Bool
(ProcessResult -> ProcessResult -> Bool)
-> (ProcessResult -> ProcessResult -> Bool) -> Eq ProcessResult
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ProcessResult -> ProcessResult -> Bool
== :: ProcessResult -> ProcessResult -> Bool
$c/= :: ProcessResult -> ProcessResult -> Bool
/= :: ProcessResult -> ProcessResult -> Bool
Eq, Int -> ProcessResult -> ShowS
[ProcessResult] -> ShowS
ProcessResult -> String
(Int -> ProcessResult -> ShowS)
-> (ProcessResult -> String)
-> ([ProcessResult] -> ShowS)
-> Show ProcessResult
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ProcessResult -> ShowS
showsPrec :: Int -> ProcessResult -> ShowS
$cshow :: ProcessResult -> String
show :: ProcessResult -> String
$cshowList :: [ProcessResult] -> ShowS
showList :: [ProcessResult] -> ShowS
Show, (forall x. ProcessResult -> Rep ProcessResult x)
-> (forall x. Rep ProcessResult x -> ProcessResult)
-> Generic ProcessResult
forall x. Rep ProcessResult x -> ProcessResult
forall x. ProcessResult -> Rep ProcessResult x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. ProcessResult -> Rep ProcessResult x
from :: forall x. ProcessResult -> Rep ProcessResult x
$cto :: forall x. Rep ProcessResult x -> ProcessResult
to :: forall x. Rep ProcessResult x -> ProcessResult
Generic)

-- | Information for forwarding to next hop.
data ForwardInfo = ForwardInfo
  { ForwardInfo -> OnionPacket
fiNextPacket   :: !OnionPacket
  , ForwardInfo -> HopPayload
fiPayload      :: !HopPayload
  , ForwardInfo -> ByteString
fiSharedSecret :: !BS.ByteString  -- ^ For error attribution
  } deriving (ForwardInfo -> ForwardInfo -> Bool
(ForwardInfo -> ForwardInfo -> Bool)
-> (ForwardInfo -> ForwardInfo -> Bool) -> Eq ForwardInfo
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ForwardInfo -> ForwardInfo -> Bool
== :: ForwardInfo -> ForwardInfo -> Bool
$c/= :: ForwardInfo -> ForwardInfo -> Bool
/= :: ForwardInfo -> ForwardInfo -> Bool
Eq, Int -> ForwardInfo -> ShowS
[ForwardInfo] -> ShowS
ForwardInfo -> String
(Int -> ForwardInfo -> ShowS)
-> (ForwardInfo -> String)
-> ([ForwardInfo] -> ShowS)
-> Show ForwardInfo
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ForwardInfo -> ShowS
showsPrec :: Int -> ForwardInfo -> ShowS
$cshow :: ForwardInfo -> String
show :: ForwardInfo -> String
$cshowList :: [ForwardInfo] -> ShowS
showList :: [ForwardInfo] -> ShowS
Show, (forall x. ForwardInfo -> Rep ForwardInfo x)
-> (forall x. Rep ForwardInfo x -> ForwardInfo)
-> Generic ForwardInfo
forall x. Rep ForwardInfo x -> ForwardInfo
forall x. ForwardInfo -> Rep ForwardInfo x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. ForwardInfo -> Rep ForwardInfo x
from :: forall x. ForwardInfo -> Rep ForwardInfo x
$cto :: forall x. Rep ForwardInfo x -> ForwardInfo
to :: forall x. Rep ForwardInfo x -> ForwardInfo
Generic)

-- | Information for receiving at final destination.
data ReceiveInfo = ReceiveInfo
  { ReceiveInfo -> HopPayload
riPayload      :: !HopPayload
  , ReceiveInfo -> ByteString
riSharedSecret :: !BS.ByteString
  } deriving (ReceiveInfo -> ReceiveInfo -> Bool
(ReceiveInfo -> ReceiveInfo -> Bool)
-> (ReceiveInfo -> ReceiveInfo -> Bool) -> Eq ReceiveInfo
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ReceiveInfo -> ReceiveInfo -> Bool
== :: ReceiveInfo -> ReceiveInfo -> Bool
$c/= :: ReceiveInfo -> ReceiveInfo -> Bool
/= :: ReceiveInfo -> ReceiveInfo -> Bool
Eq, Int -> ReceiveInfo -> ShowS
[ReceiveInfo] -> ShowS
ReceiveInfo -> String
(Int -> ReceiveInfo -> ShowS)
-> (ReceiveInfo -> String)
-> ([ReceiveInfo] -> ShowS)
-> Show ReceiveInfo
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ReceiveInfo -> ShowS
showsPrec :: Int -> ReceiveInfo -> ShowS
$cshow :: ReceiveInfo -> String
show :: ReceiveInfo -> String
$cshowList :: [ReceiveInfo] -> ShowS
showList :: [ReceiveInfo] -> ShowS
Show, (forall x. ReceiveInfo -> Rep ReceiveInfo x)
-> (forall x. Rep ReceiveInfo x -> ReceiveInfo)
-> Generic ReceiveInfo
forall x. Rep ReceiveInfo x -> ReceiveInfo
forall x. ReceiveInfo -> Rep ReceiveInfo x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. ReceiveInfo -> Rep ReceiveInfo x
from :: forall x. ReceiveInfo -> Rep ReceiveInfo x
$cto :: forall x. Rep ReceiveInfo x -> ReceiveInfo
to :: forall x. Rep ReceiveInfo x -> ReceiveInfo
Generic)

-- Constants ----------------------------------------------------------------

-- | Total onion packet size (1366 bytes).
onionPacketSize :: Int
onionPacketSize :: Int
onionPacketSize = Int
1366
{-# INLINE onionPacketSize #-}

-- | Hop payloads section size (1300 bytes).
hopPayloadsSize :: Int
hopPayloadsSize :: Int
hopPayloadsSize = Int
1300
{-# INLINE hopPayloadsSize #-}

-- | HMAC size (32 bytes).
hmacSize :: Int
hmacSize :: Int
hmacSize = Int
32
{-# INLINE hmacSize #-}

-- | Compressed public key size (33 bytes).
pubkeySize :: Int
pubkeySize :: Int
pubkeySize = Int
33
{-# INLINE pubkeySize #-}

-- | Version byte for onion packets.
versionByte :: Word8
versionByte :: Word8
versionByte = Word8
0x00
{-# INLINE versionByte #-}

-- | Maximum payload size (1300 - 32 - 1 = 1267 bytes).
maxPayloadSize :: Int
maxPayloadSize :: Int
maxPayloadSize = Int
hopPayloadsSize Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
hmacSize Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
{-# INLINE maxPayloadSize #-}

-- Silence unused import warning
_useBits :: Word16
_useBits :: Word16
_useBits = Word16
BADONION Word16 -> Word16 -> Word16
forall a. Bits a => a -> a -> a
.&. Word16
PERM Word16 -> Word16 -> Word16
forall a. Bits a => a -> a -> a
.|. Word16
NODE Word16 -> Word16 -> Word16
forall a. Bits a => a -> a -> a
.|. Word16
UPDATE