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

-- |
-- Module: Lightning.Protocol.BOLT2.Codec
-- Copyright: (c) 2025 Jared Tobin
-- License: MIT
-- Maintainer: Jared Tobin <jared@ppad.tech>
--
-- Encode/decode functions for BOLT #2 messages.

module Lightning.Protocol.BOLT2.Codec (
  -- * Error types
    EncodeError(..)
  , DecodeError(..)

  -- * Channel establishment v1
  , encodeOpenChannel
  , decodeOpenChannel
  , encodeAcceptChannel
  , decodeAcceptChannel
  , encodeFundingCreated
  , decodeFundingCreated
  , encodeFundingSigned
  , decodeFundingSigned
  , encodeChannelReady
  , decodeChannelReady

  -- * Channel establishment v2 (interactive-tx)
  , encodeOpenChannel2
  , decodeOpenChannel2
  , encodeAcceptChannel2
  , decodeAcceptChannel2
  , encodeTxAddInput
  , decodeTxAddInput
  , encodeTxAddOutput
  , decodeTxAddOutput
  , encodeTxRemoveInput
  , decodeTxRemoveInput
  , encodeTxRemoveOutput
  , decodeTxRemoveOutput
  , encodeTxComplete
  , decodeTxComplete
  , encodeTxSignatures
  , decodeTxSignatures
  , encodeTxInitRbf
  , decodeTxInitRbf
  , encodeTxAckRbf
  , decodeTxAckRbf
  , encodeTxAbort
  , decodeTxAbort

  -- * Channel close
  , encodeStfu
  , decodeStfu
  , encodeShutdown
  , decodeShutdown
  , encodeClosingSigned
  , decodeClosingSigned
  , encodeClosingComplete
  , decodeClosingComplete
  , encodeClosingSig
  , decodeClosingSig

  -- * Normal operation
  , encodeUpdateAddHtlc
  , decodeUpdateAddHtlc
  , encodeUpdateFulfillHtlc
  , decodeUpdateFulfillHtlc
  , encodeUpdateFailHtlc
  , decodeUpdateFailHtlc
  , encodeUpdateFailMalformedHtlc
  , decodeUpdateFailMalformedHtlc
  , encodeCommitmentSigned
  , decodeCommitmentSigned
  , encodeRevokeAndAck
  , decodeRevokeAndAck
  , encodeUpdateFee
  , decodeUpdateFee

  -- * Channel reestablishment
  , encodeChannelReestablish
  , decodeChannelReestablish
  ) where

import Control.DeepSeq (NFData)
import Control.Monad (unless)
import qualified Data.ByteString as BS
import Data.Word (Word8, Word16, Word32)
import GHC.Generics (Generic)
import Lightning.Protocol.BOLT1
  ( TlvStream
  , unsafeTlvStream
  , TlvError
  , encodeU16
  , encodeU32
  , encodeU64
  , decodeU16
  , decodeU32
  , decodeU64
  , encodeTlvStream
  , decodeTlvStreamRaw
  )
import Lightning.Protocol.BOLT2.Types
import Lightning.Protocol.BOLT2.Messages

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

-- | Encoding errors.
data EncodeError
  = EncodeLengthOverflow  -- ^ Payload exceeds u16 max (65535 bytes)
  deriving stock (EncodeError -> EncodeError -> Bool
(EncodeError -> EncodeError -> Bool)
-> (EncodeError -> EncodeError -> Bool) -> Eq EncodeError
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: EncodeError -> EncodeError -> Bool
== :: EncodeError -> EncodeError -> Bool
$c/= :: EncodeError -> EncodeError -> Bool
/= :: EncodeError -> EncodeError -> Bool
Eq, Int -> EncodeError -> ShowS
[EncodeError] -> ShowS
EncodeError -> String
(Int -> EncodeError -> ShowS)
-> (EncodeError -> String)
-> ([EncodeError] -> ShowS)
-> Show EncodeError
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> EncodeError -> ShowS
showsPrec :: Int -> EncodeError -> ShowS
$cshow :: EncodeError -> String
show :: EncodeError -> String
$cshowList :: [EncodeError] -> ShowS
showList :: [EncodeError] -> ShowS
Show, (forall x. EncodeError -> Rep EncodeError x)
-> (forall x. Rep EncodeError x -> EncodeError)
-> Generic EncodeError
forall x. Rep EncodeError x -> EncodeError
forall x. EncodeError -> Rep EncodeError x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. EncodeError -> Rep EncodeError x
from :: forall x. EncodeError -> Rep EncodeError x
$cto :: forall x. Rep EncodeError x -> EncodeError
to :: forall x. Rep EncodeError x -> EncodeError
Generic)

instance NFData EncodeError

-- | Decoding errors.
data DecodeError
  = DecodeInsufficientBytes
  | DecodeInvalidLength
  | DecodeInvalidChannelId
  | DecodeInvalidChainHash
  | DecodeInvalidSignature
  | DecodeInvalidPoint
  | DecodeInvalidTxId
  | DecodeInvalidPaymentHash
  | DecodeInvalidPaymentPreimage
  | DecodeInvalidOnionPacket
  | DecodeInvalidSecret
  | DecodeTlvError !TlvError
  deriving stock (DecodeError -> DecodeError -> Bool
(DecodeError -> DecodeError -> Bool)
-> (DecodeError -> DecodeError -> Bool) -> Eq DecodeError
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: DecodeError -> DecodeError -> Bool
== :: DecodeError -> DecodeError -> Bool
$c/= :: DecodeError -> DecodeError -> Bool
/= :: DecodeError -> DecodeError -> Bool
Eq, Int -> DecodeError -> ShowS
[DecodeError] -> ShowS
DecodeError -> String
(Int -> DecodeError -> ShowS)
-> (DecodeError -> String)
-> ([DecodeError] -> ShowS)
-> Show DecodeError
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> DecodeError -> ShowS
showsPrec :: Int -> DecodeError -> ShowS
$cshow :: DecodeError -> String
show :: DecodeError -> String
$cshowList :: [DecodeError] -> ShowS
showList :: [DecodeError] -> ShowS
Show, (forall x. DecodeError -> Rep DecodeError x)
-> (forall x. Rep DecodeError x -> DecodeError)
-> Generic DecodeError
forall x. Rep DecodeError x -> DecodeError
forall x. DecodeError -> Rep DecodeError x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. DecodeError -> Rep DecodeError x
from :: forall x. DecodeError -> Rep DecodeError x
$cto :: forall x. Rep DecodeError x -> DecodeError
to :: forall x. Rep DecodeError x -> DecodeError
Generic)

instance NFData DecodeError

-- Helpers ---------------------------------------------------------------------

-- | Decode a single byte.
decodeU8 :: BS.ByteString -> Maybe (Word8, BS.ByteString)
decodeU8 :: ByteString -> Maybe (Word8, ByteString)
decodeU8 !ByteString
bs
  | ByteString -> Bool
BS.null ByteString
bs = Maybe (Word8, ByteString)
forall a. Maybe a
Nothing
  | Bool
otherwise  = (Word8, ByteString) -> Maybe (Word8, ByteString)
forall a. a -> Maybe a
Just (HasCallStack => ByteString -> Int -> Word8
ByteString -> Int -> Word8
BS.index ByteString
bs Int
0, Int -> ByteString -> ByteString
BS.drop Int
1 ByteString
bs)
{-# INLINE decodeU8 #-}

-- | Decode fixed-size bytes.
decodeBytes :: Int -> BS.ByteString -> Maybe (BS.ByteString, BS.ByteString)
decodeBytes :: Int -> ByteString -> Maybe (ByteString, ByteString)
decodeBytes !Int
n !ByteString
bs
  | ByteString -> Int
BS.length ByteString
bs Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
n = Maybe (ByteString, ByteString)
forall a. Maybe a
Nothing
  | Bool
otherwise        = (ByteString, ByteString) -> Maybe (ByteString, ByteString)
forall a. a -> Maybe a
Just (Int -> ByteString -> ByteString
BS.take Int
n ByteString
bs, Int -> ByteString -> ByteString
BS.drop Int
n ByteString
bs)
{-# INLINE decodeBytes #-}

-- | Decode a ChannelId (32 bytes).
decodeChannelIdBytes
  :: BS.ByteString -> Either DecodeError (ChannelId, BS.ByteString)
decodeChannelIdBytes :: ByteString -> Either DecodeError (ChannelId, ByteString)
decodeChannelIdBytes !ByteString
bs = do
  (raw, rest) <- Either DecodeError (ByteString, ByteString)
-> ((ByteString, ByteString)
    -> Either DecodeError (ByteString, ByteString))
-> Maybe (ByteString, ByteString)
-> Either DecodeError (ByteString, ByteString)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (DecodeError -> Either DecodeError (ByteString, ByteString)
forall a b. a -> Either a b
Left DecodeError
DecodeInsufficientBytes) (ByteString, ByteString)
-> Either DecodeError (ByteString, ByteString)
forall a b. b -> Either a b
Right
                   (Int -> ByteString -> Maybe (ByteString, ByteString)
decodeBytes Int
channelIdLen ByteString
bs)
  cid <- maybe (Left DecodeInvalidChannelId) Right (channelId raw)
  Right (cid, rest)
{-# INLINE decodeChannelIdBytes #-}

-- | Decode a ChainHash (32 bytes).
decodeChainHashBytes
  :: BS.ByteString -> Either DecodeError (ChainHash, BS.ByteString)
decodeChainHashBytes :: ByteString -> Either DecodeError (ChainHash, ByteString)
decodeChainHashBytes !ByteString
bs = do
  (raw, rest) <- Either DecodeError (ByteString, ByteString)
-> ((ByteString, ByteString)
    -> Either DecodeError (ByteString, ByteString))
-> Maybe (ByteString, ByteString)
-> Either DecodeError (ByteString, ByteString)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (DecodeError -> Either DecodeError (ByteString, ByteString)
forall a b. a -> Either a b
Left DecodeError
DecodeInsufficientBytes) (ByteString, ByteString)
-> Either DecodeError (ByteString, ByteString)
forall a b. b -> Either a b
Right
                   (Int -> ByteString -> Maybe (ByteString, ByteString)
decodeBytes Int
chainHashLen ByteString
bs)
  ch <- maybe (Left DecodeInvalidChainHash) Right (chainHash raw)
  Right (ch, rest)
{-# INLINE decodeChainHashBytes #-}

-- | Decode a Signature (64 bytes).
decodeSignatureBytes
  :: BS.ByteString -> Either DecodeError (Signature, BS.ByteString)
decodeSignatureBytes :: ByteString -> Either DecodeError (Signature, ByteString)
decodeSignatureBytes !ByteString
bs = do
  (raw, rest) <- Either DecodeError (ByteString, ByteString)
-> ((ByteString, ByteString)
    -> Either DecodeError (ByteString, ByteString))
-> Maybe (ByteString, ByteString)
-> Either DecodeError (ByteString, ByteString)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (DecodeError -> Either DecodeError (ByteString, ByteString)
forall a b. a -> Either a b
Left DecodeError
DecodeInsufficientBytes) (ByteString, ByteString)
-> Either DecodeError (ByteString, ByteString)
forall a b. b -> Either a b
Right
                   (Int -> ByteString -> Maybe (ByteString, ByteString)
decodeBytes Int
signatureLen ByteString
bs)
  sig <- maybe (Left DecodeInvalidSignature) Right (signature raw)
  Right (sig, rest)
{-# INLINE decodeSignatureBytes #-}

-- | Decode a Point (33 bytes).
decodePointBytes
  :: BS.ByteString -> Either DecodeError (Point, BS.ByteString)
decodePointBytes :: ByteString -> Either DecodeError (Point, ByteString)
decodePointBytes !ByteString
bs = do
  (raw, rest) <- Either DecodeError (ByteString, ByteString)
-> ((ByteString, ByteString)
    -> Either DecodeError (ByteString, ByteString))
-> Maybe (ByteString, ByteString)
-> Either DecodeError (ByteString, ByteString)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (DecodeError -> Either DecodeError (ByteString, ByteString)
forall a b. a -> Either a b
Left DecodeError
DecodeInsufficientBytes) (ByteString, ByteString)
-> Either DecodeError (ByteString, ByteString)
forall a b. b -> Either a b
Right
                   (Int -> ByteString -> Maybe (ByteString, ByteString)
decodeBytes Int
pointLen ByteString
bs)
  pt <- maybe (Left DecodeInvalidPoint) Right (point raw)
  Right (pt, rest)
{-# INLINE decodePointBytes #-}

-- | Decode a TxId (32 bytes).
decodeTxIdBytes
  :: BS.ByteString -> Either DecodeError (TxId, BS.ByteString)
decodeTxIdBytes :: ByteString -> Either DecodeError (TxId, ByteString)
decodeTxIdBytes !ByteString
bs = do
  (raw, rest) <- Either DecodeError (ByteString, ByteString)
-> ((ByteString, ByteString)
    -> Either DecodeError (ByteString, ByteString))
-> Maybe (ByteString, ByteString)
-> Either DecodeError (ByteString, ByteString)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (DecodeError -> Either DecodeError (ByteString, ByteString)
forall a b. a -> Either a b
Left DecodeError
DecodeInsufficientBytes) (ByteString, ByteString)
-> Either DecodeError (ByteString, ByteString)
forall a b. b -> Either a b
Right
                   (Int -> ByteString -> Maybe (ByteString, ByteString)
decodeBytes Int
txIdLen ByteString
bs)
  tid <- maybe (Left DecodeInvalidTxId) Right (txId raw)
  Right (tid, rest)
{-# INLINE decodeTxIdBytes #-}

-- | Decode a u16 with error handling.
decodeU16E :: BS.ByteString -> Either DecodeError (Word16, BS.ByteString)
decodeU16E :: ByteString -> Either DecodeError (Word16, ByteString)
decodeU16E !ByteString
bs = Either DecodeError (Word16, ByteString)
-> ((Word16, ByteString)
    -> Either DecodeError (Word16, ByteString))
-> Maybe (Word16, ByteString)
-> Either DecodeError (Word16, ByteString)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (DecodeError -> Either DecodeError (Word16, ByteString)
forall a b. a -> Either a b
Left DecodeError
DecodeInsufficientBytes) (Word16, ByteString) -> Either DecodeError (Word16, ByteString)
forall a b. b -> Either a b
Right (ByteString -> Maybe (Word16, ByteString)
decodeU16 ByteString
bs)
{-# INLINE decodeU16E #-}

-- | Decode a u32 with error handling.
decodeU32E :: BS.ByteString -> Either DecodeError (Word32, BS.ByteString)
decodeU32E :: ByteString -> Either DecodeError (Word32, ByteString)
decodeU32E !ByteString
bs = Either DecodeError (Word32, ByteString)
-> ((Word32, ByteString)
    -> Either DecodeError (Word32, ByteString))
-> Maybe (Word32, ByteString)
-> Either DecodeError (Word32, ByteString)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (DecodeError -> Either DecodeError (Word32, ByteString)
forall a b. a -> Either a b
Left DecodeError
DecodeInsufficientBytes) (Word32, ByteString) -> Either DecodeError (Word32, ByteString)
forall a b. b -> Either a b
Right (ByteString -> Maybe (Word32, ByteString)
decodeU32 ByteString
bs)
{-# INLINE decodeU32E #-}

-- | Decode a u64 as Satoshis.
decodeSatoshis
  :: BS.ByteString -> Either DecodeError (Satoshis, BS.ByteString)
decodeSatoshis :: ByteString -> Either DecodeError (Satoshis, ByteString)
decodeSatoshis !ByteString
bs = do
  (val, rest) <- Either DecodeError (Word64, ByteString)
-> ((Word64, ByteString)
    -> Either DecodeError (Word64, ByteString))
-> Maybe (Word64, ByteString)
-> Either DecodeError (Word64, ByteString)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (DecodeError -> Either DecodeError (Word64, ByteString)
forall a b. a -> Either a b
Left DecodeError
DecodeInsufficientBytes) (Word64, ByteString) -> Either DecodeError (Word64, ByteString)
forall a b. b -> Either a b
Right (ByteString -> Maybe (Word64, ByteString)
decodeU64 ByteString
bs)
  Right (Satoshis val, rest)
{-# INLINE decodeSatoshis #-}

-- | Decode a u64 as MilliSatoshis.
decodeMilliSatoshis
  :: BS.ByteString -> Either DecodeError (MilliSatoshis, BS.ByteString)
decodeMilliSatoshis :: ByteString -> Either DecodeError (MilliSatoshis, ByteString)
decodeMilliSatoshis !ByteString
bs = do
  (val, rest) <- Either DecodeError (Word64, ByteString)
-> ((Word64, ByteString)
    -> Either DecodeError (Word64, ByteString))
-> Maybe (Word64, ByteString)
-> Either DecodeError (Word64, ByteString)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (DecodeError -> Either DecodeError (Word64, ByteString)
forall a b. a -> Either a b
Left DecodeError
DecodeInsufficientBytes) (Word64, ByteString) -> Either DecodeError (Word64, ByteString)
forall a b. b -> Either a b
Right (ByteString -> Maybe (Word64, ByteString)
decodeU64 ByteString
bs)
  Right (MilliSatoshis val, rest)
{-# INLINE decodeMilliSatoshis #-}

-- | Decode optional TLV stream from remaining bytes.
decodeTlvs :: BS.ByteString -> Either DecodeError TlvStream
decodeTlvs :: ByteString -> Either DecodeError TlvStream
decodeTlvs !ByteString
bs
  | ByteString -> Bool
BS.null ByteString
bs = TlvStream -> Either DecodeError TlvStream
forall a b. b -> Either a b
Right ([TlvRecord] -> TlvStream
unsafeTlvStream [])
  | Bool
otherwise  = (TlvError -> Either DecodeError TlvStream)
-> (TlvStream -> Either DecodeError TlvStream)
-> Either TlvError TlvStream
-> Either DecodeError TlvStream
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (DecodeError -> Either DecodeError TlvStream
forall a b. a -> Either a b
Left (DecodeError -> Either DecodeError TlvStream)
-> (TlvError -> DecodeError)
-> TlvError
-> Either DecodeError TlvStream
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TlvError -> DecodeError
DecodeTlvError) TlvStream -> Either DecodeError TlvStream
forall a b. b -> Either a b
Right (ByteString -> Either TlvError TlvStream
decodeTlvStreamRaw ByteString
bs)
{-# INLINE decodeTlvs #-}

-- | Decode a length-prefixed script (u16 length prefix).
decodeScriptPubKey
  :: BS.ByteString -> Either DecodeError (ScriptPubKey, BS.ByteString)
decodeScriptPubKey :: ByteString -> Either DecodeError (ScriptPubKey, ByteString)
decodeScriptPubKey !ByteString
bs = do
  (len, rest1) <- ByteString -> Either DecodeError (Word16, ByteString)
decodeU16E ByteString
bs
  let !scriptLen = Word16 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word16
len
  unless (BS.length rest1 >= scriptLen) $ Left DecodeInsufficientBytes
  let !script = Int -> ByteString -> ByteString
BS.take Int
scriptLen ByteString
rest1
      !rest2 = Int -> ByteString -> ByteString
BS.drop Int
scriptLen ByteString
rest1
  Right (scriptPubKey script, rest2)
{-# INLINE decodeScriptPubKey #-}

-- | Decode a PaymentHash (32 bytes).
decodePaymentHashBytes
  :: BS.ByteString -> Either DecodeError (PaymentHash, BS.ByteString)
decodePaymentHashBytes :: ByteString -> Either DecodeError (PaymentHash, ByteString)
decodePaymentHashBytes !ByteString
bs = do
  (raw, rest) <- Either DecodeError (ByteString, ByteString)
-> ((ByteString, ByteString)
    -> Either DecodeError (ByteString, ByteString))
-> Maybe (ByteString, ByteString)
-> Either DecodeError (ByteString, ByteString)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (DecodeError -> Either DecodeError (ByteString, ByteString)
forall a b. a -> Either a b
Left DecodeError
DecodeInsufficientBytes) (ByteString, ByteString)
-> Either DecodeError (ByteString, ByteString)
forall a b. b -> Either a b
Right
                   (Int -> ByteString -> Maybe (ByteString, ByteString)
decodeBytes Int
paymentHashLen ByteString
bs)
  ph <- maybe (Left DecodeInvalidPaymentHash) Right (paymentHash raw)
  Right (ph, rest)
{-# INLINE decodePaymentHashBytes #-}

-- | Decode a PaymentPreimage (32 bytes).
decodePaymentPreimageBytes
  :: BS.ByteString -> Either DecodeError (PaymentPreimage, BS.ByteString)
decodePaymentPreimageBytes :: ByteString -> Either DecodeError (PaymentPreimage, ByteString)
decodePaymentPreimageBytes !ByteString
bs = do
  (raw, rest) <- Either DecodeError (ByteString, ByteString)
-> ((ByteString, ByteString)
    -> Either DecodeError (ByteString, ByteString))
-> Maybe (ByteString, ByteString)
-> Either DecodeError (ByteString, ByteString)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (DecodeError -> Either DecodeError (ByteString, ByteString)
forall a b. a -> Either a b
Left DecodeError
DecodeInsufficientBytes) (ByteString, ByteString)
-> Either DecodeError (ByteString, ByteString)
forall a b. b -> Either a b
Right
                   (Int -> ByteString -> Maybe (ByteString, ByteString)
decodeBytes Int
paymentPreimageLen ByteString
bs)
  pp <- maybe (Left DecodeInvalidPaymentPreimage) Right (paymentPreimage raw)
  Right (pp, rest)
{-# INLINE decodePaymentPreimageBytes #-}

-- | Decode an OnionPacket (1366 bytes).
decodeOnionPacketBytes
  :: BS.ByteString -> Either DecodeError (OnionPacket, BS.ByteString)
decodeOnionPacketBytes :: ByteString -> Either DecodeError (OnionPacket, ByteString)
decodeOnionPacketBytes !ByteString
bs = do
  (raw, rest) <- Either DecodeError (ByteString, ByteString)
-> ((ByteString, ByteString)
    -> Either DecodeError (ByteString, ByteString))
-> Maybe (ByteString, ByteString)
-> Either DecodeError (ByteString, ByteString)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (DecodeError -> Either DecodeError (ByteString, ByteString)
forall a b. a -> Either a b
Left DecodeError
DecodeInsufficientBytes) (ByteString, ByteString)
-> Either DecodeError (ByteString, ByteString)
forall a b. b -> Either a b
Right
                   (Int -> ByteString -> Maybe (ByteString, ByteString)
decodeBytes Int
onionPacketLen ByteString
bs)
  op <- maybe (Left DecodeInvalidOnionPacket) Right (onionPacket raw)
  Right (op, rest)
{-# INLINE decodeOnionPacketBytes #-}

-- | Decode a Secret (32 bytes).
decodeSecretBytes
  :: BS.ByteString -> Either DecodeError (Secret, BS.ByteString)
decodeSecretBytes :: ByteString -> Either DecodeError (Secret, ByteString)
decodeSecretBytes !ByteString
bs = do
  (raw, rest) <- Either DecodeError (ByteString, ByteString)
-> ((ByteString, ByteString)
    -> Either DecodeError (ByteString, ByteString))
-> Maybe (ByteString, ByteString)
-> Either DecodeError (ByteString, ByteString)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (DecodeError -> Either DecodeError (ByteString, ByteString)
forall a b. a -> Either a b
Left DecodeError
DecodeInsufficientBytes) (ByteString, ByteString)
-> Either DecodeError (ByteString, ByteString)
forall a b. b -> Either a b
Right
                   (Int -> ByteString -> Maybe (ByteString, ByteString)
decodeBytes Int
secretLen ByteString
bs)
  sec <- maybe (Left DecodeInvalidSecret) Right (secret raw)
  Right (sec, rest)
{-# INLINE decodeSecretBytes #-}

-- | Encode a u16-prefixed byte string with bounds checking.
encodeU16BytesE :: BS.ByteString -> Either EncodeError BS.ByteString
encodeU16BytesE :: ByteString -> Either EncodeError ByteString
encodeU16BytesE !ByteString
bs
  | ByteString -> Int
BS.length ByteString
bs Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
65535 = EncodeError -> Either EncodeError ByteString
forall a b. a -> Either a b
Left EncodeError
EncodeLengthOverflow
  | Bool
otherwise = ByteString -> Either EncodeError ByteString
forall a b. b -> Either a b
Right (ByteString -> Either EncodeError ByteString)
-> ByteString -> Either EncodeError ByteString
forall a b. (a -> b) -> a -> b
$! Word16 -> ByteString
encodeU16 (Int -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString -> Int
BS.length ByteString
bs)) ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
bs
{-# INLINE encodeU16BytesE #-}

-- | Check that a list count fits in u16.
checkListCountU16 :: Int -> Either EncodeError Word16
checkListCountU16 :: Int -> Either EncodeError Word16
checkListCountU16 !Int
n
  | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
65535 = EncodeError -> Either EncodeError Word16
forall a b. a -> Either a b
Left EncodeError
EncodeLengthOverflow
  | Bool
otherwise = Word16 -> Either EncodeError Word16
forall a b. b -> Either a b
Right (Word16 -> Either EncodeError Word16)
-> Word16 -> Either EncodeError Word16
forall a b. (a -> b) -> a -> b
$! Int -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n
{-# INLINE checkListCountU16 #-}

-- | Decode a u16-prefixed byte string.
decodeU16Bytes
  :: BS.ByteString -> Either DecodeError (BS.ByteString, BS.ByteString)
decodeU16Bytes :: ByteString -> Either DecodeError (ByteString, ByteString)
decodeU16Bytes !ByteString
bs = do
  (len, rest1) <- ByteString -> Either DecodeError (Word16, ByteString)
decodeU16E ByteString
bs
  let !n = Word16 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word16
len
  unless (BS.length rest1 >= n) $ Left DecodeInsufficientBytes
  Right (BS.take n rest1, BS.drop n rest1)
{-# INLINE decodeU16Bytes #-}

-- | Decode optional trailing TLV stream.
decodeOptionalTlvs
  :: BS.ByteString -> Either DecodeError (TlvStream, BS.ByteString)
decodeOptionalTlvs :: ByteString -> Either DecodeError (TlvStream, ByteString)
decodeOptionalTlvs !ByteString
bs
  | ByteString -> Bool
BS.null ByteString
bs = (TlvStream, ByteString)
-> Either DecodeError (TlvStream, ByteString)
forall a b. b -> Either a b
Right ([TlvRecord] -> TlvStream
unsafeTlvStream [], ByteString
BS.empty)
  | Bool
otherwise  = case ByteString -> Either TlvError TlvStream
decodeTlvStreamRaw ByteString
bs of
      Left TlvError
e  -> DecodeError -> Either DecodeError (TlvStream, ByteString)
forall a b. a -> Either a b
Left (TlvError -> DecodeError
DecodeTlvError TlvError
e)
      Right TlvStream
t -> (TlvStream, ByteString)
-> Either DecodeError (TlvStream, ByteString)
forall a b. b -> Either a b
Right (TlvStream
t, ByteString
BS.empty)
{-# INLINE decodeOptionalTlvs #-}

-- Channel establishment v1 ----------------------------------------------------

-- | Encode an OpenChannel message (type 32).
--
-- Wire format:
-- - chain_hash: 32 bytes
-- - temporary_channel_id: 32 bytes
-- - funding_satoshis: u64
-- - push_msat: u64
-- - dust_limit_satoshis: u64
-- - max_htlc_value_in_flight_msat: u64
-- - channel_reserve_satoshis: u64
-- - htlc_minimum_msat: u64
-- - feerate_per_kw: u32
-- - to_self_delay: u16
-- - max_accepted_htlcs: u16
-- - funding_pubkey: 33 bytes
-- - revocation_basepoint: 33 bytes
-- - payment_basepoint: 33 bytes
-- - delayed_payment_basepoint: 33 bytes
-- - htlc_basepoint: 33 bytes
-- - first_per_commitment_point: 33 bytes
-- - channel_flags: 1 byte
-- - tlvs: TLV stream
encodeOpenChannel :: OpenChannel -> BS.ByteString
encodeOpenChannel :: OpenChannel -> ByteString
encodeOpenChannel !OpenChannel
msg = [ByteString] -> ByteString
forall a. Monoid a => [a] -> a
mconcat
  [ ChainHash -> ByteString
unChainHash (OpenChannel -> ChainHash
openChannelChainHash OpenChannel
msg)
  , ChannelId -> ByteString
unChannelId (OpenChannel -> ChannelId
openChannelTempChannelId OpenChannel
msg)
  , Word64 -> ByteString
encodeU64 (Satoshis -> Word64
unSatoshis (OpenChannel -> Satoshis
openChannelFundingSatoshis OpenChannel
msg))
  , Word64 -> ByteString
encodeU64 (MilliSatoshis -> Word64
unMilliSatoshis (OpenChannel -> MilliSatoshis
openChannelPushMsat OpenChannel
msg))
  , Word64 -> ByteString
encodeU64 (Satoshis -> Word64
unSatoshis (OpenChannel -> Satoshis
openChannelDustLimitSatoshis OpenChannel
msg))
  , Word64 -> ByteString
encodeU64 (MilliSatoshis -> Word64
unMilliSatoshis (OpenChannel -> MilliSatoshis
openChannelMaxHtlcValueInFlight OpenChannel
msg))
  , Word64 -> ByteString
encodeU64 (Satoshis -> Word64
unSatoshis (OpenChannel -> Satoshis
openChannelChannelReserveSat OpenChannel
msg))
  , Word64 -> ByteString
encodeU64 (MilliSatoshis -> Word64
unMilliSatoshis (OpenChannel -> MilliSatoshis
openChannelHtlcMinimumMsat OpenChannel
msg))
  , Word32 -> ByteString
encodeU32 (OpenChannel -> Word32
openChannelFeeratePerKw OpenChannel
msg)
  , Word16 -> ByteString
encodeU16 (OpenChannel -> Word16
openChannelToSelfDelay OpenChannel
msg)
  , Word16 -> ByteString
encodeU16 (OpenChannel -> Word16
openChannelMaxAcceptedHtlcs OpenChannel
msg)
  , Point -> ByteString
unPoint (OpenChannel -> Point
openChannelFundingPubkey OpenChannel
msg)
  , Point -> ByteString
unPoint (OpenChannel -> Point
openChannelRevocationBasepoint OpenChannel
msg)
  , Point -> ByteString
unPoint (OpenChannel -> Point
openChannelPaymentBasepoint OpenChannel
msg)
  , Point -> ByteString
unPoint (OpenChannel -> Point
openChannelDelayedPaymentBase OpenChannel
msg)
  , Point -> ByteString
unPoint (OpenChannel -> Point
openChannelHtlcBasepoint OpenChannel
msg)
  , Point -> ByteString
unPoint (OpenChannel -> Point
openChannelFirstPerCommitPoint OpenChannel
msg)
  , Word8 -> ByteString
BS.singleton (OpenChannel -> Word8
openChannelChannelFlags OpenChannel
msg)
  , TlvStream -> ByteString
encodeTlvStream (OpenChannel -> TlvStream
openChannelTlvs OpenChannel
msg)
  ]

-- | Decode an OpenChannel message (type 32).
decodeOpenChannel
  :: BS.ByteString -> Either DecodeError (OpenChannel, BS.ByteString)
decodeOpenChannel :: ByteString -> Either DecodeError (OpenChannel, ByteString)
decodeOpenChannel !ByteString
bs = do
  (chainHash', rest1) <- ByteString -> Either DecodeError (ChainHash, ByteString)
decodeChainHashBytes ByteString
bs
  (tempChanId, rest2) <- decodeChannelIdBytes rest1
  (fundingSats, rest3) <- decodeSatoshis rest2
  (pushMsat, rest4) <- decodeMilliSatoshis rest3
  (dustLimit, rest5) <- decodeSatoshis rest4
  (maxHtlcVal, rest6) <- decodeMilliSatoshis rest5
  (chanReserve, rest7) <- decodeSatoshis rest6
  (htlcMin, rest8) <- decodeMilliSatoshis rest7
  (feerate, rest9) <- decodeU32E rest8
  (toSelfDelay, rest10) <- decodeU16E rest9
  (maxHtlcs, rest11) <- decodeU16E rest10
  (fundingPk, rest12) <- decodePointBytes rest11
  (revocBase, rest13) <- decodePointBytes rest12
  (paymentBase, rest14) <- decodePointBytes rest13
  (delayedBase, rest15) <- decodePointBytes rest14
  (htlcBase, rest16) <- decodePointBytes rest15
  (firstCommit, rest17) <- decodePointBytes rest16
  (flags, rest18) <- maybe (Left DecodeInsufficientBytes) Right
                       (decodeU8 rest17)
  tlvs <- decodeTlvs rest18
  let !msg = OpenChannel
        { openChannelChainHash :: ChainHash
openChannelChainHash            = ChainHash
chainHash'
        , openChannelTempChannelId :: ChannelId
openChannelTempChannelId        = ChannelId
tempChanId
        , openChannelFundingSatoshis :: Satoshis
openChannelFundingSatoshis      = Satoshis
fundingSats
        , openChannelPushMsat :: MilliSatoshis
openChannelPushMsat             = MilliSatoshis
pushMsat
        , openChannelDustLimitSatoshis :: Satoshis
openChannelDustLimitSatoshis    = Satoshis
dustLimit
        , openChannelMaxHtlcValueInFlight :: MilliSatoshis
openChannelMaxHtlcValueInFlight = MilliSatoshis
maxHtlcVal
        , openChannelChannelReserveSat :: Satoshis
openChannelChannelReserveSat    = Satoshis
chanReserve
        , openChannelHtlcMinimumMsat :: MilliSatoshis
openChannelHtlcMinimumMsat      = MilliSatoshis
htlcMin
        , openChannelFeeratePerKw :: Word32
openChannelFeeratePerKw         = Word32
feerate
        , openChannelToSelfDelay :: Word16
openChannelToSelfDelay          = Word16
toSelfDelay
        , openChannelMaxAcceptedHtlcs :: Word16
openChannelMaxAcceptedHtlcs     = Word16
maxHtlcs
        , openChannelFundingPubkey :: Point
openChannelFundingPubkey        = Point
fundingPk
        , openChannelRevocationBasepoint :: Point
openChannelRevocationBasepoint  = Point
revocBase
        , openChannelPaymentBasepoint :: Point
openChannelPaymentBasepoint     = Point
paymentBase
        , openChannelDelayedPaymentBase :: Point
openChannelDelayedPaymentBase   = Point
delayedBase
        , openChannelHtlcBasepoint :: Point
openChannelHtlcBasepoint        = Point
htlcBase
        , openChannelFirstPerCommitPoint :: Point
openChannelFirstPerCommitPoint  = Point
firstCommit
        , openChannelChannelFlags :: Word8
openChannelChannelFlags         = Word8
flags
        , openChannelTlvs :: TlvStream
openChannelTlvs                 = TlvStream
tlvs
        }
  Right (msg, BS.empty)

-- | Encode an AcceptChannel message (type 33).
--
-- Wire format:
-- - temporary_channel_id: 32 bytes
-- - dust_limit_satoshis: u64
-- - max_htlc_value_in_flight_msat: u64
-- - channel_reserve_satoshis: u64
-- - htlc_minimum_msat: u64
-- - minimum_depth: u32
-- - to_self_delay: u16
-- - max_accepted_htlcs: u16
-- - funding_pubkey: 33 bytes
-- - revocation_basepoint: 33 bytes
-- - payment_basepoint: 33 bytes
-- - delayed_payment_basepoint: 33 bytes
-- - htlc_basepoint: 33 bytes
-- - first_per_commitment_point: 33 bytes
-- - tlvs: TLV stream
encodeAcceptChannel :: AcceptChannel -> BS.ByteString
encodeAcceptChannel :: AcceptChannel -> ByteString
encodeAcceptChannel !AcceptChannel
msg = [ByteString] -> ByteString
forall a. Monoid a => [a] -> a
mconcat
  [ ChannelId -> ByteString
unChannelId (AcceptChannel -> ChannelId
acceptChannelTempChannelId AcceptChannel
msg)
  , Word64 -> ByteString
encodeU64 (Satoshis -> Word64
unSatoshis (AcceptChannel -> Satoshis
acceptChannelDustLimitSatoshis AcceptChannel
msg))
  , Word64 -> ByteString
encodeU64 (MilliSatoshis -> Word64
unMilliSatoshis (AcceptChannel -> MilliSatoshis
acceptChannelMaxHtlcValueInFlight AcceptChannel
msg))
  , Word64 -> ByteString
encodeU64 (Satoshis -> Word64
unSatoshis (AcceptChannel -> Satoshis
acceptChannelChannelReserveSat AcceptChannel
msg))
  , Word64 -> ByteString
encodeU64 (MilliSatoshis -> Word64
unMilliSatoshis (AcceptChannel -> MilliSatoshis
acceptChannelHtlcMinimumMsat AcceptChannel
msg))
  , Word32 -> ByteString
encodeU32 (AcceptChannel -> Word32
acceptChannelMinimumDepth AcceptChannel
msg)
  , Word16 -> ByteString
encodeU16 (AcceptChannel -> Word16
acceptChannelToSelfDelay AcceptChannel
msg)
  , Word16 -> ByteString
encodeU16 (AcceptChannel -> Word16
acceptChannelMaxAcceptedHtlcs AcceptChannel
msg)
  , Point -> ByteString
unPoint (AcceptChannel -> Point
acceptChannelFundingPubkey AcceptChannel
msg)
  , Point -> ByteString
unPoint (AcceptChannel -> Point
acceptChannelRevocationBasepoint AcceptChannel
msg)
  , Point -> ByteString
unPoint (AcceptChannel -> Point
acceptChannelPaymentBasepoint AcceptChannel
msg)
  , Point -> ByteString
unPoint (AcceptChannel -> Point
acceptChannelDelayedPaymentBase AcceptChannel
msg)
  , Point -> ByteString
unPoint (AcceptChannel -> Point
acceptChannelHtlcBasepoint AcceptChannel
msg)
  , Point -> ByteString
unPoint (AcceptChannel -> Point
acceptChannelFirstPerCommitPoint AcceptChannel
msg)
  , TlvStream -> ByteString
encodeTlvStream (AcceptChannel -> TlvStream
acceptChannelTlvs AcceptChannel
msg)
  ]

-- | Decode an AcceptChannel message (type 33).
decodeAcceptChannel
  :: BS.ByteString -> Either DecodeError (AcceptChannel, BS.ByteString)
decodeAcceptChannel :: ByteString -> Either DecodeError (AcceptChannel, ByteString)
decodeAcceptChannel !ByteString
bs = do
  (tempChanId, rest1) <- ByteString -> Either DecodeError (ChannelId, ByteString)
decodeChannelIdBytes ByteString
bs
  (dustLimit, rest2) <- decodeSatoshis rest1
  (maxHtlcVal, rest3) <- decodeMilliSatoshis rest2
  (chanReserve, rest4) <- decodeSatoshis rest3
  (htlcMin, rest5) <- decodeMilliSatoshis rest4
  (minDepth, rest6) <- decodeU32E rest5
  (toSelfDelay, rest7) <- decodeU16E rest6
  (maxHtlcs, rest8) <- decodeU16E rest7
  (fundingPk, rest9) <- decodePointBytes rest8
  (revocBase, rest10) <- decodePointBytes rest9
  (paymentBase, rest11) <- decodePointBytes rest10
  (delayedBase, rest12) <- decodePointBytes rest11
  (htlcBase, rest13) <- decodePointBytes rest12
  (firstCommit, rest14) <- decodePointBytes rest13
  tlvs <- decodeTlvs rest14
  let !msg = AcceptChannel
        { acceptChannelTempChannelId :: ChannelId
acceptChannelTempChannelId        = ChannelId
tempChanId
        , acceptChannelDustLimitSatoshis :: Satoshis
acceptChannelDustLimitSatoshis    = Satoshis
dustLimit
        , acceptChannelMaxHtlcValueInFlight :: MilliSatoshis
acceptChannelMaxHtlcValueInFlight = MilliSatoshis
maxHtlcVal
        , acceptChannelChannelReserveSat :: Satoshis
acceptChannelChannelReserveSat    = Satoshis
chanReserve
        , acceptChannelHtlcMinimumMsat :: MilliSatoshis
acceptChannelHtlcMinimumMsat      = MilliSatoshis
htlcMin
        , acceptChannelMinimumDepth :: Word32
acceptChannelMinimumDepth         = Word32
minDepth
        , acceptChannelToSelfDelay :: Word16
acceptChannelToSelfDelay          = Word16
toSelfDelay
        , acceptChannelMaxAcceptedHtlcs :: Word16
acceptChannelMaxAcceptedHtlcs     = Word16
maxHtlcs
        , acceptChannelFundingPubkey :: Point
acceptChannelFundingPubkey        = Point
fundingPk
        , acceptChannelRevocationBasepoint :: Point
acceptChannelRevocationBasepoint  = Point
revocBase
        , acceptChannelPaymentBasepoint :: Point
acceptChannelPaymentBasepoint     = Point
paymentBase
        , acceptChannelDelayedPaymentBase :: Point
acceptChannelDelayedPaymentBase   = Point
delayedBase
        , acceptChannelHtlcBasepoint :: Point
acceptChannelHtlcBasepoint        = Point
htlcBase
        , acceptChannelFirstPerCommitPoint :: Point
acceptChannelFirstPerCommitPoint  = Point
firstCommit
        , acceptChannelTlvs :: TlvStream
acceptChannelTlvs                 = TlvStream
tlvs
        }
  Right (msg, BS.empty)

-- | Encode a FundingCreated message (type 34).
--
-- Wire format:
-- - temporary_channel_id: 32 bytes
-- - funding_txid: 32 bytes
-- - funding_output_index: u16
-- - signature: 64 bytes
encodeFundingCreated :: FundingCreated -> BS.ByteString
encodeFundingCreated :: FundingCreated -> ByteString
encodeFundingCreated !FundingCreated
msg = [ByteString] -> ByteString
forall a. Monoid a => [a] -> a
mconcat
  [ ChannelId -> ByteString
unChannelId (FundingCreated -> ChannelId
fundingCreatedTempChannelId FundingCreated
msg)
  , TxId -> ByteString
unTxId (FundingCreated -> TxId
fundingCreatedFundingTxid FundingCreated
msg)
  , Word16 -> ByteString
encodeU16 (FundingCreated -> Word16
fundingCreatedFundingOutIdx FundingCreated
msg)
  , Signature -> ByteString
unSignature (FundingCreated -> Signature
fundingCreatedSignature FundingCreated
msg)
  ]

-- | Decode a FundingCreated message (type 34).
decodeFundingCreated
  :: BS.ByteString -> Either DecodeError (FundingCreated, BS.ByteString)
decodeFundingCreated :: ByteString -> Either DecodeError (FundingCreated, ByteString)
decodeFundingCreated !ByteString
bs = do
  (tempChanId, rest1) <- ByteString -> Either DecodeError (ChannelId, ByteString)
decodeChannelIdBytes ByteString
bs
  (fundingTxid, rest2) <- decodeTxIdBytes rest1
  (outIdx, rest3) <- decodeU16E rest2
  (sig, rest4) <- decodeSignatureBytes rest3
  let !msg = FundingCreated
        { fundingCreatedTempChannelId :: ChannelId
fundingCreatedTempChannelId = ChannelId
tempChanId
        , fundingCreatedFundingTxid :: TxId
fundingCreatedFundingTxid   = TxId
fundingTxid
        , fundingCreatedFundingOutIdx :: Word16
fundingCreatedFundingOutIdx = Word16
outIdx
        , fundingCreatedSignature :: Signature
fundingCreatedSignature     = Signature
sig
        }
  Right (msg, rest4)

-- | Encode a FundingSigned message (type 35).
--
-- Wire format:
-- - channel_id: 32 bytes
-- - signature: 64 bytes
encodeFundingSigned :: FundingSigned -> BS.ByteString
encodeFundingSigned :: FundingSigned -> ByteString
encodeFundingSigned !FundingSigned
msg = [ByteString] -> ByteString
forall a. Monoid a => [a] -> a
mconcat
  [ ChannelId -> ByteString
unChannelId (FundingSigned -> ChannelId
fundingSignedChannelId FundingSigned
msg)
  , Signature -> ByteString
unSignature (FundingSigned -> Signature
fundingSignedSignature FundingSigned
msg)
  ]

-- | Decode a FundingSigned message (type 35).
decodeFundingSigned
  :: BS.ByteString -> Either DecodeError (FundingSigned, BS.ByteString)
decodeFundingSigned :: ByteString -> Either DecodeError (FundingSigned, ByteString)
decodeFundingSigned !ByteString
bs = do
  (chanId, rest1) <- ByteString -> Either DecodeError (ChannelId, ByteString)
decodeChannelIdBytes ByteString
bs
  (sig, rest2) <- decodeSignatureBytes rest1
  let !msg = FundingSigned
        { fundingSignedChannelId :: ChannelId
fundingSignedChannelId = ChannelId
chanId
        , fundingSignedSignature :: Signature
fundingSignedSignature = Signature
sig
        }
  Right (msg, rest2)

-- | Encode a ChannelReady message (type 36).
--
-- Wire format:
-- - channel_id: 32 bytes
-- - second_per_commitment_point: 33 bytes
-- - tlvs: TLV stream
encodeChannelReady :: ChannelReady -> BS.ByteString
encodeChannelReady :: ChannelReady -> ByteString
encodeChannelReady !ChannelReady
msg = [ByteString] -> ByteString
forall a. Monoid a => [a] -> a
mconcat
  [ ChannelId -> ByteString
unChannelId (ChannelReady -> ChannelId
channelReadyChannelId ChannelReady
msg)
  , Point -> ByteString
unPoint (ChannelReady -> Point
channelReadySecondPerCommitPoint ChannelReady
msg)
  , TlvStream -> ByteString
encodeTlvStream (ChannelReady -> TlvStream
channelReadyTlvs ChannelReady
msg)
  ]

-- | Decode a ChannelReady message (type 36).
decodeChannelReady
  :: BS.ByteString -> Either DecodeError (ChannelReady, BS.ByteString)
decodeChannelReady :: ByteString -> Either DecodeError (ChannelReady, ByteString)
decodeChannelReady !ByteString
bs = do
  (chanId, rest1) <- ByteString -> Either DecodeError (ChannelId, ByteString)
decodeChannelIdBytes ByteString
bs
  (secondCommit, rest2) <- decodePointBytes rest1
  tlvs <- decodeTlvs rest2
  let !msg = ChannelReady
        { channelReadyChannelId :: ChannelId
channelReadyChannelId            = ChannelId
chanId
        , channelReadySecondPerCommitPoint :: Point
channelReadySecondPerCommitPoint = Point
secondCommit
        , channelReadyTlvs :: TlvStream
channelReadyTlvs                 = TlvStream
tlvs
        }
  Right (msg, BS.empty)

-- Channel close ---------------------------------------------------------------

-- | Encode a Stfu message (type 2).
--
-- Wire format:
-- - channel_id: 32 bytes
-- - initiator: 1 byte
encodeStfu :: Stfu -> BS.ByteString
encodeStfu :: Stfu -> ByteString
encodeStfu !Stfu
msg = [ByteString] -> ByteString
forall a. Monoid a => [a] -> a
mconcat
  [ ChannelId -> ByteString
unChannelId (Stfu -> ChannelId
stfuChannelId Stfu
msg)
  , Word8 -> ByteString
BS.singleton (Stfu -> Word8
stfuInitiator Stfu
msg)
  ]

-- | Decode a Stfu message (type 2).
decodeStfu :: BS.ByteString -> Either DecodeError (Stfu, BS.ByteString)
decodeStfu :: ByteString -> Either DecodeError (Stfu, ByteString)
decodeStfu !ByteString
bs = do
  (chanId, rest1) <- ByteString -> Either DecodeError (ChannelId, ByteString)
decodeChannelIdBytes ByteString
bs
  (initiator, rest2) <- maybe (Left DecodeInsufficientBytes) Right
                          (decodeU8 rest1)
  let !msg = Stfu
        { stfuChannelId :: ChannelId
stfuChannelId = ChannelId
chanId
        , stfuInitiator :: Word8
stfuInitiator = Word8
initiator
        }
  Right (msg, rest2)

-- | Encode a Shutdown message (type 38).
--
-- Wire format:
-- - channel_id: 32 bytes
-- - len: u16
-- - scriptpubkey: len bytes
encodeShutdown :: Shutdown -> Either EncodeError BS.ByteString
encodeShutdown :: Shutdown -> Either EncodeError ByteString
encodeShutdown !Shutdown
msg = do
  let !script :: ByteString
script = ScriptPubKey -> ByteString
unScriptPubKey (Shutdown -> ScriptPubKey
shutdownScriptPubkey Shutdown
msg)
      !scriptLen :: Int
scriptLen = ByteString -> Int
BS.length ByteString
script
  if Int
scriptLen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
65535
    then EncodeError -> Either EncodeError ByteString
forall a b. a -> Either a b
Left EncodeError
EncodeLengthOverflow
    else ByteString -> Either EncodeError ByteString
forall a b. b -> Either a b
Right (ByteString -> Either EncodeError ByteString)
-> ByteString -> Either EncodeError ByteString
forall a b. (a -> b) -> a -> b
$ [ByteString] -> ByteString
forall a. Monoid a => [a] -> a
mconcat
           [ ChannelId -> ByteString
unChannelId (Shutdown -> ChannelId
shutdownChannelId Shutdown
msg)
           , Word16 -> ByteString
encodeU16 (Int -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
scriptLen)
           , ByteString
script
           ]

-- | Decode a Shutdown message (type 38).
decodeShutdown
  :: BS.ByteString -> Either DecodeError (Shutdown, BS.ByteString)
decodeShutdown :: ByteString -> Either DecodeError (Shutdown, ByteString)
decodeShutdown !ByteString
bs = do
  (chanId, rest1) <- ByteString -> Either DecodeError (ChannelId, ByteString)
decodeChannelIdBytes ByteString
bs
  (script, rest2) <- decodeScriptPubKey rest1
  let !msg = Shutdown
        { shutdownChannelId :: ChannelId
shutdownChannelId    = ChannelId
chanId
        , shutdownScriptPubkey :: ScriptPubKey
shutdownScriptPubkey = ScriptPubKey
script
        }
  Right (msg, rest2)

-- | Encode a ClosingSigned message (type 39).
--
-- Wire format:
-- - channel_id: 32 bytes
-- - fee_satoshis: u64
-- - signature: 64 bytes
-- - tlvs: TLV stream
encodeClosingSigned :: ClosingSigned -> BS.ByteString
encodeClosingSigned :: ClosingSigned -> ByteString
encodeClosingSigned !ClosingSigned
msg = [ByteString] -> ByteString
forall a. Monoid a => [a] -> a
mconcat
  [ ChannelId -> ByteString
unChannelId (ClosingSigned -> ChannelId
closingSignedChannelId ClosingSigned
msg)
  , Word64 -> ByteString
encodeU64 (Satoshis -> Word64
unSatoshis (ClosingSigned -> Satoshis
closingSignedFeeSatoshis ClosingSigned
msg))
  , Signature -> ByteString
unSignature (ClosingSigned -> Signature
closingSignedSignature ClosingSigned
msg)
  , TlvStream -> ByteString
encodeTlvStream (ClosingSigned -> TlvStream
closingSignedTlvs ClosingSigned
msg)
  ]

-- | Decode a ClosingSigned message (type 39).
decodeClosingSigned
  :: BS.ByteString -> Either DecodeError (ClosingSigned, BS.ByteString)
decodeClosingSigned :: ByteString -> Either DecodeError (ClosingSigned, ByteString)
decodeClosingSigned !ByteString
bs = do
  (chanId, rest1) <- ByteString -> Either DecodeError (ChannelId, ByteString)
decodeChannelIdBytes ByteString
bs
  (feeSats, rest2) <- decodeSatoshis rest1
  (sig, rest3) <- decodeSignatureBytes rest2
  tlvs <- decodeTlvs rest3
  let !msg = ClosingSigned
        { closingSignedChannelId :: ChannelId
closingSignedChannelId   = ChannelId
chanId
        , closingSignedFeeSatoshis :: Satoshis
closingSignedFeeSatoshis = Satoshis
feeSats
        , closingSignedSignature :: Signature
closingSignedSignature   = Signature
sig
        , closingSignedTlvs :: TlvStream
closingSignedTlvs        = TlvStream
tlvs
        }
  Right (msg, BS.empty)

-- | Encode a ClosingComplete message (type 40).
--
-- Wire format:
-- - channel_id: 32 bytes
-- - len: u16 (closer script length)
-- - closer_script: len bytes
-- - len: u16 (closee script length)
-- - closee_script: len bytes
-- - fee_satoshis: u64
-- - locktime: u32
-- - tlvs: TLV stream
encodeClosingComplete :: ClosingComplete -> Either EncodeError BS.ByteString
encodeClosingComplete :: ClosingComplete -> Either EncodeError ByteString
encodeClosingComplete !ClosingComplete
msg = do
  let !closerScript :: ByteString
closerScript = ScriptPubKey -> ByteString
unScriptPubKey (ClosingComplete -> ScriptPubKey
closingCompleteCloserScript ClosingComplete
msg)
      !closeeScript :: ByteString
closeeScript = ScriptPubKey -> ByteString
unScriptPubKey (ClosingComplete -> ScriptPubKey
closingCompleteCloseeScript ClosingComplete
msg)
      !closerLen :: Int
closerLen = ByteString -> Int
BS.length ByteString
closerScript
      !closeeLen :: Int
closeeLen = ByteString -> Int
BS.length ByteString
closeeScript
  if Int
closerLen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
65535 Bool -> Bool -> Bool
|| Int
closeeLen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
65535
    then EncodeError -> Either EncodeError ByteString
forall a b. a -> Either a b
Left EncodeError
EncodeLengthOverflow
    else ByteString -> Either EncodeError ByteString
forall a b. b -> Either a b
Right (ByteString -> Either EncodeError ByteString)
-> ByteString -> Either EncodeError ByteString
forall a b. (a -> b) -> a -> b
$ [ByteString] -> ByteString
forall a. Monoid a => [a] -> a
mconcat
           [ ChannelId -> ByteString
unChannelId (ClosingComplete -> ChannelId
closingCompleteChannelId ClosingComplete
msg)
           , Word16 -> ByteString
encodeU16 (Int -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
closerLen)
           , ByteString
closerScript
           , Word16 -> ByteString
encodeU16 (Int -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
closeeLen)
           , ByteString
closeeScript
           , Word64 -> ByteString
encodeU64 (Satoshis -> Word64
unSatoshis (ClosingComplete -> Satoshis
closingCompleteFeeSatoshis ClosingComplete
msg))
           , Word32 -> ByteString
encodeU32 (ClosingComplete -> Word32
closingCompleteLocktime ClosingComplete
msg)
           , TlvStream -> ByteString
encodeTlvStream (ClosingComplete -> TlvStream
closingCompleteTlvs ClosingComplete
msg)
           ]

-- | Decode a ClosingComplete message (type 40).
decodeClosingComplete
  :: BS.ByteString -> Either DecodeError (ClosingComplete, BS.ByteString)
decodeClosingComplete :: ByteString -> Either DecodeError (ClosingComplete, ByteString)
decodeClosingComplete !ByteString
bs = do
  (chanId, rest1) <- ByteString -> Either DecodeError (ChannelId, ByteString)
decodeChannelIdBytes ByteString
bs
  (closerScript, rest2) <- decodeScriptPubKey rest1
  (closeeScript, rest3) <- decodeScriptPubKey rest2
  (feeSats, rest4) <- decodeSatoshis rest3
  (locktime, rest5) <- decodeU32E rest4
  tlvs <- decodeTlvs rest5
  let !msg = ClosingComplete
        { closingCompleteChannelId :: ChannelId
closingCompleteChannelId    = ChannelId
chanId
        , closingCompleteCloserScript :: ScriptPubKey
closingCompleteCloserScript = ScriptPubKey
closerScript
        , closingCompleteCloseeScript :: ScriptPubKey
closingCompleteCloseeScript = ScriptPubKey
closeeScript
        , closingCompleteFeeSatoshis :: Satoshis
closingCompleteFeeSatoshis  = Satoshis
feeSats
        , closingCompleteLocktime :: Word32
closingCompleteLocktime     = Word32
locktime
        , closingCompleteTlvs :: TlvStream
closingCompleteTlvs         = TlvStream
tlvs
        }
  Right (msg, BS.empty)

-- | Encode a ClosingSig message (type 41).
--
-- Wire format:
-- - channel_id: 32 bytes
-- - len: u16 (closer script length)
-- - closer_script: len bytes
-- - len: u16 (closee script length)
-- - closee_script: len bytes
-- - fee_satoshis: u64
-- - locktime: u32
-- - tlvs: TLV stream
encodeClosingSig :: ClosingSig -> Either EncodeError BS.ByteString
encodeClosingSig :: ClosingSig -> Either EncodeError ByteString
encodeClosingSig !ClosingSig
msg = do
  let !closerScript :: ByteString
closerScript = ScriptPubKey -> ByteString
unScriptPubKey (ClosingSig -> ScriptPubKey
closingSigCloserScript ClosingSig
msg)
      !closeeScript :: ByteString
closeeScript = ScriptPubKey -> ByteString
unScriptPubKey (ClosingSig -> ScriptPubKey
closingSigCloseeScript ClosingSig
msg)
      !closerLen :: Int
closerLen = ByteString -> Int
BS.length ByteString
closerScript
      !closeeLen :: Int
closeeLen = ByteString -> Int
BS.length ByteString
closeeScript
  if Int
closerLen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
65535 Bool -> Bool -> Bool
|| Int
closeeLen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
65535
    then EncodeError -> Either EncodeError ByteString
forall a b. a -> Either a b
Left EncodeError
EncodeLengthOverflow
    else ByteString -> Either EncodeError ByteString
forall a b. b -> Either a b
Right (ByteString -> Either EncodeError ByteString)
-> ByteString -> Either EncodeError ByteString
forall a b. (a -> b) -> a -> b
$ [ByteString] -> ByteString
forall a. Monoid a => [a] -> a
mconcat
           [ ChannelId -> ByteString
unChannelId (ClosingSig -> ChannelId
closingSigChannelId ClosingSig
msg)
           , Word16 -> ByteString
encodeU16 (Int -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
closerLen)
           , ByteString
closerScript
           , Word16 -> ByteString
encodeU16 (Int -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
closeeLen)
           , ByteString
closeeScript
           , Word64 -> ByteString
encodeU64 (Satoshis -> Word64
unSatoshis (ClosingSig -> Satoshis
closingSigFeeSatoshis ClosingSig
msg))
           , Word32 -> ByteString
encodeU32 (ClosingSig -> Word32
closingSigLocktime ClosingSig
msg)
           , TlvStream -> ByteString
encodeTlvStream (ClosingSig -> TlvStream
closingSigTlvs ClosingSig
msg)
           ]

-- | Decode a ClosingSig message (type 41).
decodeClosingSig
  :: BS.ByteString -> Either DecodeError (ClosingSig, BS.ByteString)
decodeClosingSig :: ByteString -> Either DecodeError (ClosingSig, ByteString)
decodeClosingSig !ByteString
bs = do
  (chanId, rest1) <- ByteString -> Either DecodeError (ChannelId, ByteString)
decodeChannelIdBytes ByteString
bs
  (closerScript, rest2) <- decodeScriptPubKey rest1
  (closeeScript, rest3) <- decodeScriptPubKey rest2
  (feeSats, rest4) <- decodeSatoshis rest3
  (locktime, rest5) <- decodeU32E rest4
  tlvs <- decodeTlvs rest5
  let !msg = ClosingSig
        { closingSigChannelId :: ChannelId
closingSigChannelId    = ChannelId
chanId
        , closingSigCloserScript :: ScriptPubKey
closingSigCloserScript = ScriptPubKey
closerScript
        , closingSigCloseeScript :: ScriptPubKey
closingSigCloseeScript = ScriptPubKey
closeeScript
        , closingSigFeeSatoshis :: Satoshis
closingSigFeeSatoshis  = Satoshis
feeSats
        , closingSigLocktime :: Word32
closingSigLocktime     = Word32
locktime
        , closingSigTlvs :: TlvStream
closingSigTlvs         = TlvStream
tlvs
        }
  Right (msg, BS.empty)

-- Channel establishment v2 (interactive-tx) -----------------------------------

-- | Encode an OpenChannel2 message (type 64).
encodeOpenChannel2 :: OpenChannel2 -> BS.ByteString
encodeOpenChannel2 :: OpenChannel2 -> ByteString
encodeOpenChannel2 !OpenChannel2
msg = [ByteString] -> ByteString
forall a. Monoid a => [a] -> a
mconcat
  [ ChainHash -> ByteString
unChainHash (OpenChannel2 -> ChainHash
openChannel2ChainHash OpenChannel2
msg)
  , ChannelId -> ByteString
unChannelId (OpenChannel2 -> ChannelId
openChannel2TempChannelId OpenChannel2
msg)
  , Word32 -> ByteString
encodeU32 (OpenChannel2 -> Word32
openChannel2FundingFeeratePerkw OpenChannel2
msg)
  , Word32 -> ByteString
encodeU32 (OpenChannel2 -> Word32
openChannel2CommitFeeratePerkw OpenChannel2
msg)
  , Word64 -> ByteString
encodeU64 (Satoshis -> Word64
unSatoshis (OpenChannel2 -> Satoshis
openChannel2FundingSatoshis OpenChannel2
msg))
  , Word64 -> ByteString
encodeU64 (Satoshis -> Word64
unSatoshis (OpenChannel2 -> Satoshis
openChannel2DustLimitSatoshis OpenChannel2
msg))
  , Word64 -> ByteString
encodeU64 (MilliSatoshis -> Word64
unMilliSatoshis (OpenChannel2 -> MilliSatoshis
openChannel2MaxHtlcValueInFlight OpenChannel2
msg))
  , Word64 -> ByteString
encodeU64 (MilliSatoshis -> Word64
unMilliSatoshis (OpenChannel2 -> MilliSatoshis
openChannel2HtlcMinimumMsat OpenChannel2
msg))
  , Word16 -> ByteString
encodeU16 (OpenChannel2 -> Word16
openChannel2ToSelfDelay OpenChannel2
msg)
  , Word16 -> ByteString
encodeU16 (OpenChannel2 -> Word16
openChannel2MaxAcceptedHtlcs OpenChannel2
msg)
  , Word32 -> ByteString
encodeU32 (OpenChannel2 -> Word32
openChannel2Locktime OpenChannel2
msg)
  , Point -> ByteString
unPoint (OpenChannel2 -> Point
openChannel2FundingPubkey OpenChannel2
msg)
  , Point -> ByteString
unPoint (OpenChannel2 -> Point
openChannel2RevocationBasepoint OpenChannel2
msg)
  , Point -> ByteString
unPoint (OpenChannel2 -> Point
openChannel2PaymentBasepoint OpenChannel2
msg)
  , Point -> ByteString
unPoint (OpenChannel2 -> Point
openChannel2DelayedPaymentBase OpenChannel2
msg)
  , Point -> ByteString
unPoint (OpenChannel2 -> Point
openChannel2HtlcBasepoint OpenChannel2
msg)
  , Point -> ByteString
unPoint (OpenChannel2 -> Point
openChannel2FirstPerCommitPoint OpenChannel2
msg)
  , Point -> ByteString
unPoint (OpenChannel2 -> Point
openChannel2SecondPerCommitPoint OpenChannel2
msg)
  , Word8 -> ByteString
BS.singleton (OpenChannel2 -> Word8
openChannel2ChannelFlags OpenChannel2
msg)
  , TlvStream -> ByteString
encodeTlvStream (OpenChannel2 -> TlvStream
openChannel2Tlvs OpenChannel2
msg)
  ]

-- | Decode an OpenChannel2 message (type 64).
decodeOpenChannel2
  :: BS.ByteString -> Either DecodeError (OpenChannel2, BS.ByteString)
decodeOpenChannel2 :: ByteString -> Either DecodeError (OpenChannel2, ByteString)
decodeOpenChannel2 !ByteString
bs = do
  (ch, rest1) <- ByteString -> Either DecodeError (ChainHash, ByteString)
decodeChainHashBytes ByteString
bs
  (tempCid, rest2) <- decodeChannelIdBytes rest1
  (fundingFeerate, rest3) <- decodeU32E rest2
  (commitFeerate, rest4) <- decodeU32E rest3
  (fundingSats, rest5) <- decodeSatoshis rest4
  (dustLimit, rest6) <- decodeSatoshis rest5
  (maxHtlcVal, rest7) <- decodeMilliSatoshis rest6
  (htlcMin, rest8) <- decodeMilliSatoshis rest7
  (toSelfDelay, rest9) <- decodeU16E rest8
  (maxHtlcs, rest10) <- decodeU16E rest9
  (locktime, rest11) <- decodeU32E rest10
  (fundingPk, rest12) <- decodePointBytes rest11
  (revBase, rest13) <- decodePointBytes rest12
  (payBase, rest14) <- decodePointBytes rest13
  (delayBase, rest15) <- decodePointBytes rest14
  (htlcBase, rest16) <- decodePointBytes rest15
  (firstPt, rest17) <- decodePointBytes rest16
  (secondPt, rest18) <- decodePointBytes rest17
  (flags, rest19) <- maybe (Left DecodeInsufficientBytes) Right (decodeU8 rest18)
  tlvs <- decodeTlvs rest19
  let !msg = OpenChannel2
        { openChannel2ChainHash :: ChainHash
openChannel2ChainHash            = ChainHash
ch
        , openChannel2TempChannelId :: ChannelId
openChannel2TempChannelId        = ChannelId
tempCid
        , openChannel2FundingFeeratePerkw :: Word32
openChannel2FundingFeeratePerkw  = Word32
fundingFeerate
        , openChannel2CommitFeeratePerkw :: Word32
openChannel2CommitFeeratePerkw   = Word32
commitFeerate
        , openChannel2FundingSatoshis :: Satoshis
openChannel2FundingSatoshis      = Satoshis
fundingSats
        , openChannel2DustLimitSatoshis :: Satoshis
openChannel2DustLimitSatoshis    = Satoshis
dustLimit
        , openChannel2MaxHtlcValueInFlight :: MilliSatoshis
openChannel2MaxHtlcValueInFlight = MilliSatoshis
maxHtlcVal
        , openChannel2HtlcMinimumMsat :: MilliSatoshis
openChannel2HtlcMinimumMsat      = MilliSatoshis
htlcMin
        , openChannel2ToSelfDelay :: Word16
openChannel2ToSelfDelay          = Word16
toSelfDelay
        , openChannel2MaxAcceptedHtlcs :: Word16
openChannel2MaxAcceptedHtlcs     = Word16
maxHtlcs
        , openChannel2Locktime :: Word32
openChannel2Locktime             = Word32
locktime
        , openChannel2FundingPubkey :: Point
openChannel2FundingPubkey        = Point
fundingPk
        , openChannel2RevocationBasepoint :: Point
openChannel2RevocationBasepoint  = Point
revBase
        , openChannel2PaymentBasepoint :: Point
openChannel2PaymentBasepoint     = Point
payBase
        , openChannel2DelayedPaymentBase :: Point
openChannel2DelayedPaymentBase   = Point
delayBase
        , openChannel2HtlcBasepoint :: Point
openChannel2HtlcBasepoint        = Point
htlcBase
        , openChannel2FirstPerCommitPoint :: Point
openChannel2FirstPerCommitPoint  = Point
firstPt
        , openChannel2SecondPerCommitPoint :: Point
openChannel2SecondPerCommitPoint = Point
secondPt
        , openChannel2ChannelFlags :: Word8
openChannel2ChannelFlags         = Word8
flags
        , openChannel2Tlvs :: TlvStream
openChannel2Tlvs                 = TlvStream
tlvs
        }
  Right (msg, BS.empty)

-- | Encode an AcceptChannel2 message (type 65).
encodeAcceptChannel2 :: AcceptChannel2 -> BS.ByteString
encodeAcceptChannel2 :: AcceptChannel2 -> ByteString
encodeAcceptChannel2 !AcceptChannel2
msg = [ByteString] -> ByteString
forall a. Monoid a => [a] -> a
mconcat
  [ ChannelId -> ByteString
unChannelId (AcceptChannel2 -> ChannelId
acceptChannel2TempChannelId AcceptChannel2
msg)
  , Word64 -> ByteString
encodeU64 (Satoshis -> Word64
unSatoshis (AcceptChannel2 -> Satoshis
acceptChannel2FundingSatoshis AcceptChannel2
msg))
  , Word64 -> ByteString
encodeU64 (Satoshis -> Word64
unSatoshis (AcceptChannel2 -> Satoshis
acceptChannel2DustLimitSatoshis AcceptChannel2
msg))
  , Word64 -> ByteString
encodeU64 (MilliSatoshis -> Word64
unMilliSatoshis (AcceptChannel2 -> MilliSatoshis
acceptChannel2MaxHtlcValueInFlight AcceptChannel2
msg))
  , Word64 -> ByteString
encodeU64 (MilliSatoshis -> Word64
unMilliSatoshis (AcceptChannel2 -> MilliSatoshis
acceptChannel2HtlcMinimumMsat AcceptChannel2
msg))
  , Word32 -> ByteString
encodeU32 (AcceptChannel2 -> Word32
acceptChannel2MinimumDepth AcceptChannel2
msg)
  , Word16 -> ByteString
encodeU16 (AcceptChannel2 -> Word16
acceptChannel2ToSelfDelay AcceptChannel2
msg)
  , Word16 -> ByteString
encodeU16 (AcceptChannel2 -> Word16
acceptChannel2MaxAcceptedHtlcs AcceptChannel2
msg)
  , Point -> ByteString
unPoint (AcceptChannel2 -> Point
acceptChannel2FundingPubkey AcceptChannel2
msg)
  , Point -> ByteString
unPoint (AcceptChannel2 -> Point
acceptChannel2RevocationBasepoint AcceptChannel2
msg)
  , Point -> ByteString
unPoint (AcceptChannel2 -> Point
acceptChannel2PaymentBasepoint AcceptChannel2
msg)
  , Point -> ByteString
unPoint (AcceptChannel2 -> Point
acceptChannel2DelayedPaymentBase AcceptChannel2
msg)
  , Point -> ByteString
unPoint (AcceptChannel2 -> Point
acceptChannel2HtlcBasepoint AcceptChannel2
msg)
  , Point -> ByteString
unPoint (AcceptChannel2 -> Point
acceptChannel2FirstPerCommitPoint AcceptChannel2
msg)
  , Point -> ByteString
unPoint (AcceptChannel2 -> Point
acceptChannel2SecondPerCommitPoint AcceptChannel2
msg)
  , TlvStream -> ByteString
encodeTlvStream (AcceptChannel2 -> TlvStream
acceptChannel2Tlvs AcceptChannel2
msg)
  ]

-- | Decode an AcceptChannel2 message (type 65).
decodeAcceptChannel2
  :: BS.ByteString -> Either DecodeError (AcceptChannel2, BS.ByteString)
decodeAcceptChannel2 :: ByteString -> Either DecodeError (AcceptChannel2, ByteString)
decodeAcceptChannel2 !ByteString
bs = do
  (tempCid, rest1) <- ByteString -> Either DecodeError (ChannelId, ByteString)
decodeChannelIdBytes ByteString
bs
  (fundingSats, rest2) <- decodeSatoshis rest1
  (dustLimit, rest3) <- decodeSatoshis rest2
  (maxHtlcVal, rest4) <- decodeMilliSatoshis rest3
  (htlcMin, rest5) <- decodeMilliSatoshis rest4
  (minDepth, rest6) <- decodeU32E rest5
  (toSelfDelay, rest7) <- decodeU16E rest6
  (maxHtlcs, rest8) <- decodeU16E rest7
  (fundingPk, rest9) <- decodePointBytes rest8
  (revBase, rest10) <- decodePointBytes rest9
  (payBase, rest11) <- decodePointBytes rest10
  (delayBase, rest12) <- decodePointBytes rest11
  (htlcBase, rest13) <- decodePointBytes rest12
  (firstPt, rest14) <- decodePointBytes rest13
  (secondPt, rest15) <- decodePointBytes rest14
  tlvs <- decodeTlvs rest15
  let !msg = AcceptChannel2
        { acceptChannel2TempChannelId :: ChannelId
acceptChannel2TempChannelId        = ChannelId
tempCid
        , acceptChannel2FundingSatoshis :: Satoshis
acceptChannel2FundingSatoshis      = Satoshis
fundingSats
        , acceptChannel2DustLimitSatoshis :: Satoshis
acceptChannel2DustLimitSatoshis    = Satoshis
dustLimit
        , acceptChannel2MaxHtlcValueInFlight :: MilliSatoshis
acceptChannel2MaxHtlcValueInFlight = MilliSatoshis
maxHtlcVal
        , acceptChannel2HtlcMinimumMsat :: MilliSatoshis
acceptChannel2HtlcMinimumMsat      = MilliSatoshis
htlcMin
        , acceptChannel2MinimumDepth :: Word32
acceptChannel2MinimumDepth         = Word32
minDepth
        , acceptChannel2ToSelfDelay :: Word16
acceptChannel2ToSelfDelay          = Word16
toSelfDelay
        , acceptChannel2MaxAcceptedHtlcs :: Word16
acceptChannel2MaxAcceptedHtlcs     = Word16
maxHtlcs
        , acceptChannel2FundingPubkey :: Point
acceptChannel2FundingPubkey        = Point
fundingPk
        , acceptChannel2RevocationBasepoint :: Point
acceptChannel2RevocationBasepoint  = Point
revBase
        , acceptChannel2PaymentBasepoint :: Point
acceptChannel2PaymentBasepoint     = Point
payBase
        , acceptChannel2DelayedPaymentBase :: Point
acceptChannel2DelayedPaymentBase   = Point
delayBase
        , acceptChannel2HtlcBasepoint :: Point
acceptChannel2HtlcBasepoint        = Point
htlcBase
        , acceptChannel2FirstPerCommitPoint :: Point
acceptChannel2FirstPerCommitPoint  = Point
firstPt
        , acceptChannel2SecondPerCommitPoint :: Point
acceptChannel2SecondPerCommitPoint = Point
secondPt
        , acceptChannel2Tlvs :: TlvStream
acceptChannel2Tlvs                 = TlvStream
tlvs
        }
  Right (msg, BS.empty)

-- | Encode a TxAddInput message (type 66).
encodeTxAddInput :: TxAddInput -> Either EncodeError BS.ByteString
encodeTxAddInput :: TxAddInput -> Either EncodeError ByteString
encodeTxAddInput !TxAddInput
msg = do
  prevTxEnc <- ByteString -> Either EncodeError ByteString
encodeU16BytesE (TxAddInput -> ByteString
txAddInputPrevTx TxAddInput
msg)
  Right $! mconcat
    [ unChannelId (txAddInputChannelId msg)
    , encodeU64 (txAddInputSerialId msg)
    , prevTxEnc
    , encodeU32 (txAddInputPrevVout msg)
    , encodeU32 (txAddInputSequence msg)
    ]

-- | Decode a TxAddInput message (type 66).
decodeTxAddInput
  :: BS.ByteString -> Either DecodeError (TxAddInput, BS.ByteString)
decodeTxAddInput :: ByteString -> Either DecodeError (TxAddInput, ByteString)
decodeTxAddInput !ByteString
bs = do
  (cid, rest1) <- ByteString -> Either DecodeError (ChannelId, ByteString)
decodeChannelIdBytes ByteString
bs
  (serialId, rest2) <- maybe (Left DecodeInsufficientBytes) Right
                         (decodeU64 rest1)
  (prevTx, rest3) <- decodeU16Bytes rest2
  (prevVout, rest4) <- decodeU32E rest3
  (seqNum, rest5) <- decodeU32E rest4
  let !msg = TxAddInput
        { txAddInputChannelId :: ChannelId
txAddInputChannelId = ChannelId
cid
        , txAddInputSerialId :: Word64
txAddInputSerialId  = Word64
serialId
        , txAddInputPrevTx :: ByteString
txAddInputPrevTx    = ByteString
prevTx
        , txAddInputPrevVout :: Word32
txAddInputPrevVout  = Word32
prevVout
        , txAddInputSequence :: Word32
txAddInputSequence  = Word32
seqNum
        }
  Right (msg, rest5)

-- | Encode a TxAddOutput message (type 67).
encodeTxAddOutput :: TxAddOutput -> Either EncodeError BS.ByteString
encodeTxAddOutput :: TxAddOutput -> Either EncodeError ByteString
encodeTxAddOutput !TxAddOutput
msg = do
  scriptEnc <- ByteString -> Either EncodeError ByteString
encodeU16BytesE (ScriptPubKey -> ByteString
unScriptPubKey (TxAddOutput -> ScriptPubKey
txAddOutputScript TxAddOutput
msg))
  Right $! mconcat
    [ unChannelId (txAddOutputChannelId msg)
    , encodeU64 (txAddOutputSerialId msg)
    , encodeU64 (unSatoshis (txAddOutputSats msg))
    , scriptEnc
    ]

-- | Decode a TxAddOutput message (type 67).
decodeTxAddOutput
  :: BS.ByteString -> Either DecodeError (TxAddOutput, BS.ByteString)
decodeTxAddOutput :: ByteString -> Either DecodeError (TxAddOutput, ByteString)
decodeTxAddOutput !ByteString
bs = do
  (cid, rest1) <- ByteString -> Either DecodeError (ChannelId, ByteString)
decodeChannelIdBytes ByteString
bs
  (serialId, rest2) <- maybe (Left DecodeInsufficientBytes) Right
                         (decodeU64 rest1)
  (sats, rest3) <- decodeSatoshis rest2
  (scriptBs, rest4) <- decodeU16Bytes rest3
  let !msg = TxAddOutput
        { txAddOutputChannelId :: ChannelId
txAddOutputChannelId = ChannelId
cid
        , txAddOutputSerialId :: Word64
txAddOutputSerialId  = Word64
serialId
        , txAddOutputSats :: Satoshis
txAddOutputSats      = Satoshis
sats
        , txAddOutputScript :: ScriptPubKey
txAddOutputScript    = ByteString -> ScriptPubKey
scriptPubKey ByteString
scriptBs
        }
  Right (msg, rest4)

-- | Encode a TxRemoveInput message (type 68).
encodeTxRemoveInput :: TxRemoveInput -> BS.ByteString
encodeTxRemoveInput :: TxRemoveInput -> ByteString
encodeTxRemoveInput !TxRemoveInput
msg = [ByteString] -> ByteString
forall a. Monoid a => [a] -> a
mconcat
  [ ChannelId -> ByteString
unChannelId (TxRemoveInput -> ChannelId
txRemoveInputChannelId TxRemoveInput
msg)
  , Word64 -> ByteString
encodeU64 (TxRemoveInput -> Word64
txRemoveInputSerialId TxRemoveInput
msg)
  ]

-- | Decode a TxRemoveInput message (type 68).
decodeTxRemoveInput
  :: BS.ByteString -> Either DecodeError (TxRemoveInput, BS.ByteString)
decodeTxRemoveInput :: ByteString -> Either DecodeError (TxRemoveInput, ByteString)
decodeTxRemoveInput !ByteString
bs = do
  (cid, rest1) <- ByteString -> Either DecodeError (ChannelId, ByteString)
decodeChannelIdBytes ByteString
bs
  (serialId, rest2) <- maybe (Left DecodeInsufficientBytes) Right
                         (decodeU64 rest1)
  let !msg = TxRemoveInput
        { txRemoveInputChannelId :: ChannelId
txRemoveInputChannelId = ChannelId
cid
        , txRemoveInputSerialId :: Word64
txRemoveInputSerialId  = Word64
serialId
        }
  Right (msg, rest2)

-- | Encode a TxRemoveOutput message (type 69).
encodeTxRemoveOutput :: TxRemoveOutput -> BS.ByteString
encodeTxRemoveOutput :: TxRemoveOutput -> ByteString
encodeTxRemoveOutput !TxRemoveOutput
msg = [ByteString] -> ByteString
forall a. Monoid a => [a] -> a
mconcat
  [ ChannelId -> ByteString
unChannelId (TxRemoveOutput -> ChannelId
txRemoveOutputChannelId TxRemoveOutput
msg)
  , Word64 -> ByteString
encodeU64 (TxRemoveOutput -> Word64
txRemoveOutputSerialId TxRemoveOutput
msg)
  ]

-- | Decode a TxRemoveOutput message (type 69).
decodeTxRemoveOutput
  :: BS.ByteString -> Either DecodeError (TxRemoveOutput, BS.ByteString)
decodeTxRemoveOutput :: ByteString -> Either DecodeError (TxRemoveOutput, ByteString)
decodeTxRemoveOutput !ByteString
bs = do
  (cid, rest1) <- ByteString -> Either DecodeError (ChannelId, ByteString)
decodeChannelIdBytes ByteString
bs
  (serialId, rest2) <- maybe (Left DecodeInsufficientBytes) Right
                         (decodeU64 rest1)
  let !msg = TxRemoveOutput
        { txRemoveOutputChannelId :: ChannelId
txRemoveOutputChannelId = ChannelId
cid
        , txRemoveOutputSerialId :: Word64
txRemoveOutputSerialId  = Word64
serialId
        }
  Right (msg, rest2)

-- | Encode a TxComplete message (type 70).
encodeTxComplete :: TxComplete -> BS.ByteString
encodeTxComplete :: TxComplete -> ByteString
encodeTxComplete !TxComplete
msg = ChannelId -> ByteString
unChannelId (TxComplete -> ChannelId
txCompleteChannelId TxComplete
msg)

-- | Decode a TxComplete message (type 70).
decodeTxComplete
  :: BS.ByteString -> Either DecodeError (TxComplete, BS.ByteString)
decodeTxComplete :: ByteString -> Either DecodeError (TxComplete, ByteString)
decodeTxComplete !ByteString
bs = do
  (cid, rest) <- ByteString -> Either DecodeError (ChannelId, ByteString)
decodeChannelIdBytes ByteString
bs
  let !msg = TxComplete { txCompleteChannelId :: ChannelId
txCompleteChannelId = ChannelId
cid }
  Right (msg, rest)

-- | Encode a single witness with bounds checking.
encodeWitnessE :: Witness -> Either EncodeError BS.ByteString
encodeWitnessE :: Witness -> Either EncodeError ByteString
encodeWitnessE (Witness !ByteString
wdata) = ByteString -> Either EncodeError ByteString
encodeU16BytesE ByteString
wdata

-- | Decode a single witness.
decodeWitness :: BS.ByteString -> Either DecodeError (Witness, BS.ByteString)
decodeWitness :: ByteString -> Either DecodeError (Witness, ByteString)
decodeWitness !ByteString
bs = do
  (wdata, rest) <- ByteString -> Either DecodeError (ByteString, ByteString)
decodeU16Bytes ByteString
bs
  Right (Witness wdata, rest)

-- | Encode a TxSignatures message (type 71).
encodeTxSignatures :: TxSignatures -> Either EncodeError BS.ByteString
encodeTxSignatures :: TxSignatures -> Either EncodeError ByteString
encodeTxSignatures !TxSignatures
msg = do
  let !witnesses :: [Witness]
witnesses = TxSignatures -> [Witness]
txSignaturesWitnesses TxSignatures
msg
  numWit <- Int -> Either EncodeError Word16
checkListCountU16 ([Witness] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Witness]
witnesses)
  encodedWits <- traverse encodeWitnessE witnesses
  Right $! mconcat $
    [ unChannelId (txSignaturesChannelId msg)
    , unTxId (txSignaturesTxid msg)
    , encodeU16 numWit
    ] ++ encodedWits

-- | Decode a TxSignatures message (type 71).
decodeTxSignatures
  :: BS.ByteString -> Either DecodeError (TxSignatures, BS.ByteString)
decodeTxSignatures :: ByteString -> Either DecodeError (TxSignatures, ByteString)
decodeTxSignatures !ByteString
bs = do
  (cid, rest1) <- ByteString -> Either DecodeError (ChannelId, ByteString)
decodeChannelIdBytes ByteString
bs
  (tid, rest2) <- decodeTxIdBytes rest1
  (numWit, rest3) <- decodeU16E rest2
  (witnesses, rest4) <- decodeWitnesses (fromIntegral numWit) rest3
  let !msg = TxSignatures
        { txSignaturesChannelId :: ChannelId
txSignaturesChannelId = ChannelId
cid
        , txSignaturesTxid :: TxId
txSignaturesTxid      = TxId
tid
        , txSignaturesWitnesses :: [Witness]
txSignaturesWitnesses = [Witness]
witnesses
        }
  Right (msg, rest4)
  where
    decodeWitnesses :: Int -> BS.ByteString
                    -> Either DecodeError ([Witness], BS.ByteString)
    decodeWitnesses :: Int -> ByteString -> Either DecodeError ([Witness], ByteString)
decodeWitnesses Int
0 !ByteString
rest = ([Witness], ByteString)
-> Either DecodeError ([Witness], ByteString)
forall a b. b -> Either a b
Right ([], ByteString
rest)
    decodeWitnesses !Int
n !ByteString
rest = do
      (w, rest') <- ByteString -> Either DecodeError (Witness, ByteString)
decodeWitness ByteString
rest
      (ws, rest'') <- decodeWitnesses (n - 1) rest'
      Right (w : ws, rest'')

-- | Encode a TxInitRbf message (type 72).
encodeTxInitRbf :: TxInitRbf -> BS.ByteString
encodeTxInitRbf :: TxInitRbf -> ByteString
encodeTxInitRbf !TxInitRbf
msg = [ByteString] -> ByteString
forall a. Monoid a => [a] -> a
mconcat
  [ ChannelId -> ByteString
unChannelId (TxInitRbf -> ChannelId
txInitRbfChannelId TxInitRbf
msg)
  , Word32 -> ByteString
encodeU32 (TxInitRbf -> Word32
txInitRbfLocktime TxInitRbf
msg)
  , Word32 -> ByteString
encodeU32 (TxInitRbf -> Word32
txInitRbfFeerate TxInitRbf
msg)
  , TlvStream -> ByteString
encodeTlvStream (TxInitRbf -> TlvStream
txInitRbfTlvs TxInitRbf
msg)
  ]

-- | Decode a TxInitRbf message (type 72).
decodeTxInitRbf
  :: BS.ByteString -> Either DecodeError (TxInitRbf, BS.ByteString)
decodeTxInitRbf :: ByteString -> Either DecodeError (TxInitRbf, ByteString)
decodeTxInitRbf !ByteString
bs = do
  (cid, rest1) <- ByteString -> Either DecodeError (ChannelId, ByteString)
decodeChannelIdBytes ByteString
bs
  (locktime, rest2) <- decodeU32E rest1
  (feerate, rest3) <- decodeU32E rest2
  tlvs <- decodeTlvs rest3
  let !msg = TxInitRbf
        { txInitRbfChannelId :: ChannelId
txInitRbfChannelId = ChannelId
cid
        , txInitRbfLocktime :: Word32
txInitRbfLocktime  = Word32
locktime
        , txInitRbfFeerate :: Word32
txInitRbfFeerate   = Word32
feerate
        , txInitRbfTlvs :: TlvStream
txInitRbfTlvs      = TlvStream
tlvs
        }
  Right (msg, BS.empty)

-- | Encode a TxAckRbf message (type 73).
encodeTxAckRbf :: TxAckRbf -> BS.ByteString
encodeTxAckRbf :: TxAckRbf -> ByteString
encodeTxAckRbf !TxAckRbf
msg = [ByteString] -> ByteString
forall a. Monoid a => [a] -> a
mconcat
  [ ChannelId -> ByteString
unChannelId (TxAckRbf -> ChannelId
txAckRbfChannelId TxAckRbf
msg)
  , TlvStream -> ByteString
encodeTlvStream (TxAckRbf -> TlvStream
txAckRbfTlvs TxAckRbf
msg)
  ]

-- | Decode a TxAckRbf message (type 73).
decodeTxAckRbf
  :: BS.ByteString -> Either DecodeError (TxAckRbf, BS.ByteString)
decodeTxAckRbf :: ByteString -> Either DecodeError (TxAckRbf, ByteString)
decodeTxAckRbf !ByteString
bs = do
  (cid, rest1) <- ByteString -> Either DecodeError (ChannelId, ByteString)
decodeChannelIdBytes ByteString
bs
  tlvs <- decodeTlvs rest1
  let !msg = TxAckRbf
        { txAckRbfChannelId :: ChannelId
txAckRbfChannelId = ChannelId
cid
        , txAckRbfTlvs :: TlvStream
txAckRbfTlvs      = TlvStream
tlvs
        }
  Right (msg, BS.empty)

-- | Encode a TxAbort message (type 74).
encodeTxAbort :: TxAbort -> Either EncodeError BS.ByteString
encodeTxAbort :: TxAbort -> Either EncodeError ByteString
encodeTxAbort !TxAbort
msg = do
  dataEnc <- ByteString -> Either EncodeError ByteString
encodeU16BytesE (TxAbort -> ByteString
txAbortData TxAbort
msg)
  Right $! mconcat
    [ unChannelId (txAbortChannelId msg)
    , dataEnc
    ]

-- | Decode a TxAbort message (type 74).
decodeTxAbort
  :: BS.ByteString -> Either DecodeError (TxAbort, BS.ByteString)
decodeTxAbort :: ByteString -> Either DecodeError (TxAbort, ByteString)
decodeTxAbort !ByteString
bs = do
  (cid, rest1) <- ByteString -> Either DecodeError (ChannelId, ByteString)
decodeChannelIdBytes ByteString
bs
  (dat, rest2) <- decodeU16Bytes rest1
  let !msg = TxAbort
        { txAbortChannelId :: ChannelId
txAbortChannelId = ChannelId
cid
        , txAbortData :: ByteString
txAbortData      = ByteString
dat
        }
  Right (msg, rest2)

-- Normal operation ------------------------------------------------------------

-- | Encode an UpdateAddHtlc message (type 128).
encodeUpdateAddHtlc :: UpdateAddHtlc -> BS.ByteString
encodeUpdateAddHtlc :: UpdateAddHtlc -> ByteString
encodeUpdateAddHtlc !UpdateAddHtlc
m = [ByteString] -> ByteString
forall a. Monoid a => [a] -> a
mconcat
  [ ChannelId -> ByteString
unChannelId (UpdateAddHtlc -> ChannelId
updateAddHtlcChannelId UpdateAddHtlc
m)
  , Word64 -> ByteString
encodeU64 (UpdateAddHtlc -> Word64
updateAddHtlcId UpdateAddHtlc
m)
  , Word64 -> ByteString
encodeU64 (MilliSatoshis -> Word64
unMilliSatoshis (UpdateAddHtlc -> MilliSatoshis
updateAddHtlcAmountMsat UpdateAddHtlc
m))
  , PaymentHash -> ByteString
unPaymentHash (UpdateAddHtlc -> PaymentHash
updateAddHtlcPaymentHash UpdateAddHtlc
m)
  , Word32 -> ByteString
encodeU32 (UpdateAddHtlc -> Word32
updateAddHtlcCltvExpiry UpdateAddHtlc
m)
  , OnionPacket -> ByteString
unOnionPacket (UpdateAddHtlc -> OnionPacket
updateAddHtlcOnionPacket UpdateAddHtlc
m)
  , TlvStream -> ByteString
encodeTlvStream (UpdateAddHtlc -> TlvStream
updateAddHtlcTlvs UpdateAddHtlc
m)
  ]
{-# INLINABLE encodeUpdateAddHtlc #-}

-- | Decode an UpdateAddHtlc message (type 128).
decodeUpdateAddHtlc
  :: BS.ByteString -> Either DecodeError (UpdateAddHtlc, BS.ByteString)
decodeUpdateAddHtlc :: ByteString -> Either DecodeError (UpdateAddHtlc, ByteString)
decodeUpdateAddHtlc !ByteString
bs = do
  (cid, rest1) <- ByteString -> Either DecodeError (ChannelId, ByteString)
decodeChannelIdBytes ByteString
bs
  (htlcId, rest2) <- maybe (Left DecodeInsufficientBytes) Right
                       (decodeU64 rest1)
  (amtMsat, rest3) <- maybe (Left DecodeInsufficientBytes) Right
                        (decodeU64 rest2)
  (pHash, rest4) <- decodePaymentHashBytes rest3
  (cltvExp, rest5) <- decodeU32E rest4
  (onion, rest6) <- decodeOnionPacketBytes rest5
  (tlvs, rest7) <- decodeOptionalTlvs rest6
  let !msg = UpdateAddHtlc
        { updateAddHtlcChannelId :: ChannelId
updateAddHtlcChannelId   = ChannelId
cid
        , updateAddHtlcId :: Word64
updateAddHtlcId          = Word64
htlcId
        , updateAddHtlcAmountMsat :: MilliSatoshis
updateAddHtlcAmountMsat  = Word64 -> MilliSatoshis
MilliSatoshis Word64
amtMsat
        , updateAddHtlcPaymentHash :: PaymentHash
updateAddHtlcPaymentHash = PaymentHash
pHash
        , updateAddHtlcCltvExpiry :: Word32
updateAddHtlcCltvExpiry  = Word32
cltvExp
        , updateAddHtlcOnionPacket :: OnionPacket
updateAddHtlcOnionPacket = OnionPacket
onion
        , updateAddHtlcTlvs :: TlvStream
updateAddHtlcTlvs        = TlvStream
tlvs
        }
  Right (msg, rest7)
{-# INLINABLE decodeUpdateAddHtlc #-}

-- | Encode an UpdateFulfillHtlc message (type 130).
encodeUpdateFulfillHtlc :: UpdateFulfillHtlc -> BS.ByteString
encodeUpdateFulfillHtlc :: UpdateFulfillHtlc -> ByteString
encodeUpdateFulfillHtlc !UpdateFulfillHtlc
m = [ByteString] -> ByteString
forall a. Monoid a => [a] -> a
mconcat
  [ ChannelId -> ByteString
unChannelId (UpdateFulfillHtlc -> ChannelId
updateFulfillHtlcChannelId UpdateFulfillHtlc
m)
  , Word64 -> ByteString
encodeU64 (UpdateFulfillHtlc -> Word64
updateFulfillHtlcId UpdateFulfillHtlc
m)
  , PaymentPreimage -> ByteString
unPaymentPreimage (UpdateFulfillHtlc -> PaymentPreimage
updateFulfillHtlcPaymentPreimage UpdateFulfillHtlc
m)
  , TlvStream -> ByteString
encodeTlvStream (UpdateFulfillHtlc -> TlvStream
updateFulfillHtlcTlvs UpdateFulfillHtlc
m)
  ]

-- | Decode an UpdateFulfillHtlc message (type 130).
decodeUpdateFulfillHtlc
  :: BS.ByteString -> Either DecodeError (UpdateFulfillHtlc, BS.ByteString)
decodeUpdateFulfillHtlc :: ByteString -> Either DecodeError (UpdateFulfillHtlc, ByteString)
decodeUpdateFulfillHtlc !ByteString
bs = do
  (cid, rest1) <- ByteString -> Either DecodeError (ChannelId, ByteString)
decodeChannelIdBytes ByteString
bs
  (htlcId, rest2) <- maybe (Left DecodeInsufficientBytes) Right
                       (decodeU64 rest1)
  (preimage, rest3) <- decodePaymentPreimageBytes rest2
  (tlvs, rest4) <- decodeOptionalTlvs rest3
  let !msg = UpdateFulfillHtlc
        { updateFulfillHtlcChannelId :: ChannelId
updateFulfillHtlcChannelId       = ChannelId
cid
        , updateFulfillHtlcId :: Word64
updateFulfillHtlcId              = Word64
htlcId
        , updateFulfillHtlcPaymentPreimage :: PaymentPreimage
updateFulfillHtlcPaymentPreimage = PaymentPreimage
preimage
        , updateFulfillHtlcTlvs :: TlvStream
updateFulfillHtlcTlvs            = TlvStream
tlvs
        }
  Right (msg, rest4)

-- | Encode an UpdateFailHtlc message (type 131).
encodeUpdateFailHtlc :: UpdateFailHtlc -> Either EncodeError BS.ByteString
encodeUpdateFailHtlc :: UpdateFailHtlc -> Either EncodeError ByteString
encodeUpdateFailHtlc !UpdateFailHtlc
m = do
  reasonEnc <- ByteString -> Either EncodeError ByteString
encodeU16BytesE (UpdateFailHtlc -> ByteString
updateFailHtlcReason UpdateFailHtlc
m)
  Right $! mconcat
    [ unChannelId (updateFailHtlcChannelId m)
    , encodeU64 (updateFailHtlcId m)
    , reasonEnc
    , encodeTlvStream (updateFailHtlcTlvs m)
    ]

-- | Decode an UpdateFailHtlc message (type 131).
decodeUpdateFailHtlc
  :: BS.ByteString -> Either DecodeError (UpdateFailHtlc, BS.ByteString)
decodeUpdateFailHtlc :: ByteString -> Either DecodeError (UpdateFailHtlc, ByteString)
decodeUpdateFailHtlc !ByteString
bs = do
  (cid, rest1) <- ByteString -> Either DecodeError (ChannelId, ByteString)
decodeChannelIdBytes ByteString
bs
  (htlcId, rest2) <- maybe (Left DecodeInsufficientBytes) Right
                       (decodeU64 rest1)
  (reason, rest3) <- decodeU16Bytes rest2
  (tlvs, rest4) <- decodeOptionalTlvs rest3
  let !msg = UpdateFailHtlc
        { updateFailHtlcChannelId :: ChannelId
updateFailHtlcChannelId = ChannelId
cid
        , updateFailHtlcId :: Word64
updateFailHtlcId        = Word64
htlcId
        , updateFailHtlcReason :: ByteString
updateFailHtlcReason    = ByteString
reason
        , updateFailHtlcTlvs :: TlvStream
updateFailHtlcTlvs      = TlvStream
tlvs
        }
  Right (msg, rest4)

-- | Encode an UpdateFailMalformedHtlc message (type 135).
encodeUpdateFailMalformedHtlc :: UpdateFailMalformedHtlc -> BS.ByteString
encodeUpdateFailMalformedHtlc :: UpdateFailMalformedHtlc -> ByteString
encodeUpdateFailMalformedHtlc !UpdateFailMalformedHtlc
m = [ByteString] -> ByteString
forall a. Monoid a => [a] -> a
mconcat
  [ ChannelId -> ByteString
unChannelId (UpdateFailMalformedHtlc -> ChannelId
updateFailMalformedHtlcChannelId UpdateFailMalformedHtlc
m)
  , Word64 -> ByteString
encodeU64 (UpdateFailMalformedHtlc -> Word64
updateFailMalformedHtlcId UpdateFailMalformedHtlc
m)
  , PaymentHash -> ByteString
unPaymentHash (UpdateFailMalformedHtlc -> PaymentHash
updateFailMalformedHtlcSha256Onion UpdateFailMalformedHtlc
m)
  , Word16 -> ByteString
encodeU16 (UpdateFailMalformedHtlc -> Word16
updateFailMalformedHtlcFailureCode UpdateFailMalformedHtlc
m)
  ]

-- | Decode an UpdateFailMalformedHtlc message (type 135).
decodeUpdateFailMalformedHtlc
  :: BS.ByteString -> Either DecodeError (UpdateFailMalformedHtlc, BS.ByteString)
decodeUpdateFailMalformedHtlc :: ByteString
-> Either DecodeError (UpdateFailMalformedHtlc, ByteString)
decodeUpdateFailMalformedHtlc !ByteString
bs = do
  (cid, rest1) <- ByteString -> Either DecodeError (ChannelId, ByteString)
decodeChannelIdBytes ByteString
bs
  (htlcId, rest2) <- maybe (Left DecodeInsufficientBytes) Right
                       (decodeU64 rest1)
  (sha256Onion, rest3) <- decodePaymentHashBytes rest2
  (failCode, rest4) <- decodeU16E rest3
  let !msg = UpdateFailMalformedHtlc
        { updateFailMalformedHtlcChannelId :: ChannelId
updateFailMalformedHtlcChannelId   = ChannelId
cid
        , updateFailMalformedHtlcId :: Word64
updateFailMalformedHtlcId          = Word64
htlcId
        , updateFailMalformedHtlcSha256Onion :: PaymentHash
updateFailMalformedHtlcSha256Onion = PaymentHash
sha256Onion
        , updateFailMalformedHtlcFailureCode :: Word16
updateFailMalformedHtlcFailureCode = Word16
failCode
        }
  Right (msg, rest4)

-- | Encode a CommitmentSigned message (type 132).
encodeCommitmentSigned :: CommitmentSigned -> Either EncodeError BS.ByteString
encodeCommitmentSigned :: CommitmentSigned -> Either EncodeError ByteString
encodeCommitmentSigned !CommitmentSigned
m = do
  let !sigs :: [Signature]
sigs = CommitmentSigned -> [Signature]
commitmentSignedHtlcSignatures CommitmentSigned
m
  numHtlcs <- Int -> Either EncodeError Word16
checkListCountU16 ([Signature] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Signature]
sigs)
  Right $! mconcat $
    [ unChannelId (commitmentSignedChannelId m)
    , unSignature (commitmentSignedSignature m)
    , encodeU16 numHtlcs
    ] ++ map unSignature sigs
{-# INLINABLE encodeCommitmentSigned #-}

-- | Decode a CommitmentSigned message (type 132).
decodeCommitmentSigned
  :: BS.ByteString -> Either DecodeError (CommitmentSigned, BS.ByteString)
decodeCommitmentSigned :: ByteString -> Either DecodeError (CommitmentSigned, ByteString)
decodeCommitmentSigned !ByteString
bs = do
  (cid, rest1) <- ByteString -> Either DecodeError (ChannelId, ByteString)
decodeChannelIdBytes ByteString
bs
  (sig, rest2) <- decodeSignatureBytes rest1
  (numHtlcs, rest3) <- decodeU16E rest2
  (htlcSigs, rest4) <- decodeSignatures (fromIntegral numHtlcs) rest3
  let !msg = CommitmentSigned
        { commitmentSignedChannelId :: ChannelId
commitmentSignedChannelId      = ChannelId
cid
        , commitmentSignedSignature :: Signature
commitmentSignedSignature      = Signature
sig
        , commitmentSignedHtlcSignatures :: [Signature]
commitmentSignedHtlcSignatures = [Signature]
htlcSigs
        }
  Right (msg, rest4)
  where
    decodeSignatures :: Int -> BS.ByteString
                     -> Either DecodeError ([Signature], BS.ByteString)
    decodeSignatures :: Int -> ByteString -> Either DecodeError ([Signature], ByteString)
decodeSignatures !Int
n !ByteString
input = Int
-> ByteString
-> [Signature]
-> Either DecodeError ([Signature], ByteString)
go Int
n ByteString
input []
      where
        go :: Int -> BS.ByteString -> [Signature]
           -> Either DecodeError ([Signature], BS.ByteString)
        go :: Int
-> ByteString
-> [Signature]
-> Either DecodeError ([Signature], ByteString)
go Int
0 !ByteString
remaining ![Signature]
acc = ([Signature], ByteString)
-> Either DecodeError ([Signature], ByteString)
forall a b. b -> Either a b
Right ([Signature] -> [Signature]
forall a. [a] -> [a]
reverse [Signature]
acc, ByteString
remaining)
        go !Int
count !ByteString
remaining ![Signature]
acc = do
          (s, rest) <- ByteString -> Either DecodeError (Signature, ByteString)
decodeSignatureBytes ByteString
remaining
          go (count - 1) rest (s : acc)
{-# INLINABLE decodeCommitmentSigned #-}

-- | Encode a RevokeAndAck message (type 133).
encodeRevokeAndAck :: RevokeAndAck -> BS.ByteString
encodeRevokeAndAck :: RevokeAndAck -> ByteString
encodeRevokeAndAck !RevokeAndAck
m = [ByteString] -> ByteString
forall a. Monoid a => [a] -> a
mconcat
  [ ChannelId -> ByteString
unChannelId (RevokeAndAck -> ChannelId
revokeAndAckChannelId RevokeAndAck
m)
  , Secret -> ByteString
unSecret (RevokeAndAck -> Secret
revokeAndAckPerCommitmentSecret RevokeAndAck
m)
  , Point -> ByteString
unPoint (RevokeAndAck -> Point
revokeAndAckNextPerCommitPoint RevokeAndAck
m)
  ]

-- | Decode a RevokeAndAck message (type 133).
decodeRevokeAndAck
  :: BS.ByteString -> Either DecodeError (RevokeAndAck, BS.ByteString)
decodeRevokeAndAck :: ByteString -> Either DecodeError (RevokeAndAck, ByteString)
decodeRevokeAndAck !ByteString
bs = do
  (cid, rest1) <- ByteString -> Either DecodeError (ChannelId, ByteString)
decodeChannelIdBytes ByteString
bs
  (sec, rest2) <- decodeSecretBytes rest1
  (nextPoint, rest3) <- decodePointBytes rest2
  let !msg = RevokeAndAck
        { revokeAndAckChannelId :: ChannelId
revokeAndAckChannelId           = ChannelId
cid
        , revokeAndAckPerCommitmentSecret :: Secret
revokeAndAckPerCommitmentSecret = Secret
sec
        , revokeAndAckNextPerCommitPoint :: Point
revokeAndAckNextPerCommitPoint  = Point
nextPoint
        }
  Right (msg, rest3)

-- | Encode an UpdateFee message (type 134).
encodeUpdateFee :: UpdateFee -> BS.ByteString
encodeUpdateFee :: UpdateFee -> ByteString
encodeUpdateFee !UpdateFee
m = [ByteString] -> ByteString
forall a. Monoid a => [a] -> a
mconcat
  [ ChannelId -> ByteString
unChannelId (UpdateFee -> ChannelId
updateFeeChannelId UpdateFee
m)
  , Word32 -> ByteString
encodeU32 (UpdateFee -> Word32
updateFeeFeeratePerKw UpdateFee
m)
  ]

-- | Decode an UpdateFee message (type 134).
decodeUpdateFee
  :: BS.ByteString -> Either DecodeError (UpdateFee, BS.ByteString)
decodeUpdateFee :: ByteString -> Either DecodeError (UpdateFee, ByteString)
decodeUpdateFee !ByteString
bs = do
  (cid, rest1) <- ByteString -> Either DecodeError (ChannelId, ByteString)
decodeChannelIdBytes ByteString
bs
  (feerate, rest2) <- decodeU32E rest1
  let !msg = UpdateFee
        { updateFeeChannelId :: ChannelId
updateFeeChannelId    = ChannelId
cid
        , updateFeeFeeratePerKw :: Word32
updateFeeFeeratePerKw = Word32
feerate
        }
  Right (msg, rest2)

-- Channel reestablishment -----------------------------------------------------

-- | Encode a ChannelReestablish message (type 136).
encodeChannelReestablish :: ChannelReestablish -> BS.ByteString
encodeChannelReestablish :: ChannelReestablish -> ByteString
encodeChannelReestablish !ChannelReestablish
m = [ByteString] -> ByteString
forall a. Monoid a => [a] -> a
mconcat
  [ ChannelId -> ByteString
unChannelId (ChannelReestablish -> ChannelId
channelReestablishChannelId ChannelReestablish
m)
  , Word64 -> ByteString
encodeU64 (ChannelReestablish -> Word64
channelReestablishNextCommitNum ChannelReestablish
m)
  , Word64 -> ByteString
encodeU64 (ChannelReestablish -> Word64
channelReestablishNextRevocationNum ChannelReestablish
m)
  , Secret -> ByteString
unSecret (ChannelReestablish -> Secret
channelReestablishYourLastCommitSecret ChannelReestablish
m)
  , Point -> ByteString
unPoint (ChannelReestablish -> Point
channelReestablishMyCurrentCommitPoint ChannelReestablish
m)
  , TlvStream -> ByteString
encodeTlvStream (ChannelReestablish -> TlvStream
channelReestablishTlvs ChannelReestablish
m)
  ]

-- | Decode a ChannelReestablish message (type 136).
decodeChannelReestablish
  :: BS.ByteString -> Either DecodeError (ChannelReestablish, BS.ByteString)
decodeChannelReestablish :: ByteString -> Either DecodeError (ChannelReestablish, ByteString)
decodeChannelReestablish !ByteString
bs = do
  (cid, rest1) <- ByteString -> Either DecodeError (ChannelId, ByteString)
decodeChannelIdBytes ByteString
bs
  (nextCommit, rest2) <- maybe (Left DecodeInsufficientBytes) Right
                           (decodeU64 rest1)
  (nextRevoke, rest3) <- maybe (Left DecodeInsufficientBytes) Right
                           (decodeU64 rest2)
  (sec, rest4) <- decodeSecretBytes rest3
  (myPoint, rest5) <- decodePointBytes rest4
  (tlvs, rest6) <- decodeOptionalTlvs rest5
  let !msg = ChannelReestablish
        { channelReestablishChannelId :: ChannelId
channelReestablishChannelId            = ChannelId
cid
        , channelReestablishNextCommitNum :: Word64
channelReestablishNextCommitNum        = Word64
nextCommit
        , channelReestablishNextRevocationNum :: Word64
channelReestablishNextRevocationNum    = Word64
nextRevoke
        , channelReestablishYourLastCommitSecret :: Secret
channelReestablishYourLastCommitSecret = Secret
sec
        , channelReestablishMyCurrentCommitPoint :: Point
channelReestablishMyCurrentCommitPoint = Point
myPoint
        , channelReestablishTlvs :: TlvStream
channelReestablishTlvs                 = TlvStream
tlvs
        }
  Right (msg, rest6)