packages feed

ppad-bolt2-0.1.0: lib/Lightning/Protocol/BOLT2/Messages.hs

{-# OPTIONS_HADDOCK hide #-}
{-# LANGUAGE DeriveGeneric #-}

-- |
-- Module: Lightning.Protocol.BOLT2.Messages
-- Copyright: (c) 2025 Jared Tobin
-- License: MIT
-- Maintainer: Jared Tobin <jared@ppad.tech>
--
-- The messages defined by BOLT #2.

module Lightning.Protocol.BOLT2.Messages (
    Message(..)
  , message_type

  , OpenChannel(..)
  , AcceptChannel(..)
  , FundingCreated(..)
  , FundingSigned(..)
  , ChannelReady(..)

  , OpenChannel2(..)
  , AcceptChannel2(..)
  , TxAddInput(..)
  , TxAddOutput(..)
  , TxRemoveInput(..)
  , TxRemoveOutput(..)
  , TxComplete(..)
  , TxSignatures(..)
  , TxInitRbf(..)
  , TxAckRbf(..)
  , TxAbort(..)

  , Stfu(..)

  , Shutdown(..)
  , ClosingComplete(..)
  , ClosingSig(..)
  , ClosingSigned(..)

  , UpdateAddHtlc(..)
  , UpdateFulfillHtlc(..)
  , UpdateFailHtlc(..)
  , UpdateFailMalformedHtlc(..)
  , CommitmentSigned(..)
  , RevokeAndAck(..)
  , UpdateFee(..)

  , ChannelReestablish(..)
  ) where

import Bitcoin.Prim.Tx (TxId)
import Control.DeepSeq (NFData)
import qualified Data.ByteString as BS
import Data.Int (Int64)
import Data.Word (Word8, Word16, Word32, Word64)
import GHC.Generics (Generic)
import Lightning.Protocol.BOLT1
  ( ChainHash, ChannelId, Signature, Point, PaymentHash, PaymentPreimage
  , PerCommitmentSecret, ShortChannelId, Satoshi, MilliSatoshi, TlvStream )
import qualified Lightning.Protocol.BOLT9 as BOLT9
import Lightning.Protocol.BOLT2.Types

-- channel establishment v1 ---------------------------------------------------

-- | The @open_channel@ message (type 32).
data OpenChannel = OpenChannel
  { open_channel_chain_hash                    :: !ChainHash
  , open_channel_temporary_channel_id          :: !ChannelId
  , open_channel_funding_satoshis              :: {-# UNPACK #-} !Satoshi
  , open_channel_push_msat                     :: {-# UNPACK #-} !MilliSatoshi
  , open_channel_dust_limit_satoshis           :: {-# UNPACK #-} !Satoshi
  , open_channel_max_htlc_value_in_flight_msat :: {-# UNPACK #-} !Word64
    -- ^ a cap, often @maxBound@, so not a bounded amount
  , open_channel_channel_reserve_satoshis      :: {-# UNPACK #-} !Satoshi
  , open_channel_htlc_minimum_msat             :: {-# UNPACK #-} !MilliSatoshi
  , open_channel_feerate_per_kw                :: {-# UNPACK #-} !Word32
  , open_channel_to_self_delay                 :: {-# UNPACK #-} !Word16
  , open_channel_max_accepted_htlcs            :: {-# UNPACK #-} !Word16
  , open_channel_funding_pubkey                :: !Point
  , open_channel_revocation_basepoint          :: !Point
  , open_channel_payment_basepoint             :: !Point
  , open_channel_delayed_payment_basepoint     :: !Point
  , open_channel_htlc_basepoint                :: !Point
  , open_channel_first_per_commitment_point    :: !Point
  , open_channel_channel_flags                 :: {-# UNPACK #-} !Word8
    -- ^ bit 0: @announce_channel@
  , open_channel_upfront_shutdown_script       :: !(Maybe ScriptPubKey)
    -- ^ TLV type 0; an empty script commits to no particular script
  , open_channel_channel_type                  :: !(Maybe BOLT9.FeatureVector)
    -- ^ TLV type 1
  , open_channel_tlvs                          :: !TlvStream
    -- ^ unknown TLV records
  } deriving (Eq, Show, Generic)

instance NFData OpenChannel

-- | The @accept_channel@ message (type 33).
data AcceptChannel = AcceptChannel
  { accept_channel_temporary_channel_id          :: !ChannelId
  , accept_channel_dust_limit_satoshis           :: {-# UNPACK #-} !Satoshi
  , accept_channel_max_htlc_value_in_flight_msat :: {-# UNPACK #-} !Word64
    -- ^ a cap, often @maxBound@, so not a bounded amount
  , accept_channel_channel_reserve_satoshis      :: {-# UNPACK #-} !Satoshi
  , accept_channel_htlc_minimum_msat
      :: {-# UNPACK #-} !MilliSatoshi
  , accept_channel_minimum_depth                :: {-# UNPACK #-} !Word32
  , accept_channel_to_self_delay                 :: {-# UNPACK #-} !Word16
  , accept_channel_max_accepted_htlcs            :: {-# UNPACK #-} !Word16
  , accept_channel_funding_pubkey                :: !Point
  , accept_channel_revocation_basepoint          :: !Point
  , accept_channel_payment_basepoint             :: !Point
  , accept_channel_delayed_payment_basepoint     :: !Point
  , accept_channel_htlc_basepoint                :: !Point
  , accept_channel_first_per_commitment_point    :: !Point
  , accept_channel_upfront_shutdown_script       :: !(Maybe ScriptPubKey)
    -- ^ TLV type 0; an empty script commits to no particular script
  , accept_channel_channel_type
      :: !(Maybe BOLT9.FeatureVector)
    -- ^ TLV type 1
  , accept_channel_tlvs                          :: !TlvStream
    -- ^ unknown TLV records
  } deriving (Eq, Show, Generic)

instance NFData AcceptChannel

-- | The @funding_created@ message (type 34).
data FundingCreated = FundingCreated
  { funding_created_temporary_channel_id :: !ChannelId
  , funding_created_funding_txid         :: !TxId
  , funding_created_funding_output_index :: {-# UNPACK #-} !Word16
  , funding_created_signature            :: !Signature
  , funding_created_tlvs                 :: !TlvStream
    -- ^ unknown TLV records
  } deriving (Eq, Show, Generic)

instance NFData FundingCreated

-- | The @funding_signed@ message (type 35).
data FundingSigned = FundingSigned
  { funding_signed_channel_id :: !ChannelId
  , funding_signed_signature  :: !Signature
  , funding_signed_tlvs       :: !TlvStream
    -- ^ unknown TLV records
  } deriving (Eq, Show, Generic)

instance NFData FundingSigned

-- | The @channel_ready@ message (type 36).
data ChannelReady = ChannelReady
  { channel_ready_channel_id                  :: !ChannelId
  , channel_ready_second_per_commitment_point :: !Point
  , channel_ready_alias                       :: !(Maybe ShortChannelId)
    -- ^ the @short_channel_id@ record (TLV type 1)
  , channel_ready_tlvs                        :: !TlvStream
    -- ^ unknown TLV records
  } deriving (Eq, Show, Generic)

instance NFData ChannelReady

-- channel establishment v2 ---------------------------------------------------

-- | The @open_channel2@ message (type 64).
data OpenChannel2 = OpenChannel2
  { open_channel2_chain_hash                    :: !ChainHash
  , open_channel2_temporary_channel_id          :: !ChannelId
  , open_channel2_funding_feerate_perkw         :: {-# UNPACK #-} !Word32
  , open_channel2_commitment_feerate_perkw      :: {-# UNPACK #-} !Word32
  , open_channel2_funding_satoshis              :: {-# UNPACK #-} !Satoshi
  , open_channel2_dust_limit_satoshis           :: {-# UNPACK #-} !Satoshi
  , open_channel2_max_htlc_value_in_flight_msat :: {-# UNPACK #-} !Word64
    -- ^ a cap, often @maxBound@, so not a bounded amount
  , open_channel2_htlc_minimum_msat
      :: {-# UNPACK #-} !MilliSatoshi
  , open_channel2_to_self_delay                 :: {-# UNPACK #-} !Word16
  , open_channel2_max_accepted_htlcs            :: {-# UNPACK #-} !Word16
  , open_channel2_locktime                      :: {-# UNPACK #-} !Word32
  , open_channel2_funding_pubkey                :: !Point
  , open_channel2_revocation_basepoint          :: !Point
  , open_channel2_payment_basepoint             :: !Point
  , open_channel2_delayed_payment_basepoint     :: !Point
  , open_channel2_htlc_basepoint                :: !Point
  , open_channel2_first_per_commitment_point    :: !Point
  , open_channel2_second_per_commitment_point   :: !Point
  , open_channel2_channel_flags                 :: {-# UNPACK #-} !Word8
    -- ^ bit 0: @announce_channel@
  , open_channel2_upfront_shutdown_script       :: !(Maybe ScriptPubKey)
    -- ^ TLV type 0; an empty script commits to no particular script
  , open_channel2_channel_type
      :: !(Maybe BOLT9.FeatureVector)
    -- ^ TLV type 1
  , open_channel2_require_confirmed_inputs      :: !Bool
    -- ^ TLV type 2
  , open_channel2_tlvs                          :: !TlvStream
    -- ^ unknown TLV records
  } deriving (Eq, Show, Generic)

instance NFData OpenChannel2

-- | The @accept_channel2@ message (type 65).
data AcceptChannel2 = AcceptChannel2
  { accept_channel2_temporary_channel_id          :: !ChannelId
  , accept_channel2_funding_satoshis              :: {-# UNPACK #-} !Satoshi
  , accept_channel2_dust_limit_satoshis           :: {-# UNPACK #-} !Satoshi
  , accept_channel2_max_htlc_value_in_flight_msat :: {-# UNPACK #-} !Word64
    -- ^ a cap, often @maxBound@, so not a bounded amount
  , accept_channel2_htlc_minimum_msat
      :: {-# UNPACK #-} !MilliSatoshi
  , accept_channel2_minimum_depth                 :: {-# UNPACK #-} !Word32
  , accept_channel2_to_self_delay                 :: {-# UNPACK #-} !Word16
  , accept_channel2_max_accepted_htlcs            :: {-# UNPACK #-} !Word16
  , accept_channel2_funding_pubkey                :: !Point
  , accept_channel2_revocation_basepoint          :: !Point
  , accept_channel2_payment_basepoint             :: !Point
  , accept_channel2_delayed_payment_basepoint     :: !Point
  , accept_channel2_htlc_basepoint                :: !Point
  , accept_channel2_first_per_commitment_point    :: !Point
  , accept_channel2_second_per_commitment_point   :: !Point
  , accept_channel2_upfront_shutdown_script
      :: !(Maybe ScriptPubKey)
    -- ^ TLV type 0; an empty script commits to no particular script
  , accept_channel2_channel_type
      :: !(Maybe BOLT9.FeatureVector)
    -- ^ TLV type 1
  , accept_channel2_require_confirmed_inputs      :: !Bool
    -- ^ TLV type 2
  , accept_channel2_tlvs                          :: !TlvStream
    -- ^ unknown TLV records
  } deriving (Eq, Show, Generic)

instance NFData AcceptChannel2

-- | The @tx_add_input@ message (type 66).
data TxAddInput = TxAddInput
  { tx_add_input_channel_id  :: !ChannelId
  , tx_add_input_serial_id   :: !SerialId
  , tx_add_input_prevtx      :: !BS.ByteString
    -- ^ the serialized previous transaction
  , tx_add_input_prevtx_vout :: {-# UNPACK #-} !Word32
  , tx_add_input_sequence    :: {-# UNPACK #-} !Word32
  , tx_add_input_tlvs        :: !TlvStream
    -- ^ unknown TLV records
  } deriving (Eq, Show, Generic)

instance NFData TxAddInput

-- | The @tx_add_output@ message (type 67).
data TxAddOutput = TxAddOutput
  { tx_add_output_channel_id :: !ChannelId
  , tx_add_output_serial_id  :: !SerialId
  , tx_add_output_sats       :: {-# UNPACK #-} !Satoshi
  , tx_add_output_script     :: !ScriptPubKey
  , tx_add_output_tlvs       :: !TlvStream
    -- ^ unknown TLV records
  } deriving (Eq, Show, Generic)

instance NFData TxAddOutput

-- | The @tx_remove_input@ message (type 68).
data TxRemoveInput = TxRemoveInput
  { tx_remove_input_channel_id :: !ChannelId
  , tx_remove_input_serial_id  :: !SerialId
  , tx_remove_input_tlvs       :: !TlvStream
    -- ^ unknown TLV records
  } deriving (Eq, Show, Generic)

instance NFData TxRemoveInput

-- | The @tx_remove_output@ message (type 69).
data TxRemoveOutput = TxRemoveOutput
  { tx_remove_output_channel_id :: !ChannelId
  , tx_remove_output_serial_id  :: !SerialId
  , tx_remove_output_tlvs       :: !TlvStream
    -- ^ unknown TLV records
  } deriving (Eq, Show, Generic)

instance NFData TxRemoveOutput

-- | The @tx_complete@ message (type 70).
data TxComplete = TxComplete
  { tx_complete_channel_id :: !ChannelId
  , tx_complete_tlvs       :: !TlvStream
    -- ^ unknown TLV records
  } deriving (Eq, Show, Generic)

instance NFData TxComplete

-- | The @tx_signatures@ message (type 71).
data TxSignatures = TxSignatures
  { tx_signatures_channel_id :: !ChannelId
  , tx_signatures_txid       :: !TxId
  , tx_signatures_witnesses  :: ![Witness]
    -- ^ ordered by the @serial_id@ of the inputs they spend
  , tx_signatures_tlvs       :: !TlvStream
    -- ^ unknown TLV records
  } deriving (Eq, Show, Generic)

instance NFData TxSignatures

-- | The @tx_init_rbf@ message (type 72).
data TxInitRbf = TxInitRbf
  { tx_init_rbf_channel_id                  :: !ChannelId
  , tx_init_rbf_locktime                    :: {-# UNPACK #-} !Word32
  , tx_init_rbf_feerate                     :: {-# UNPACK #-} !Word32
  , tx_init_rbf_funding_output_contribution :: !(Maybe Int64)
    -- ^ TLV type 0, in satoshis
  , tx_init_rbf_require_confirmed_inputs    :: !Bool
    -- ^ TLV type 2
  , tx_init_rbf_tlvs                        :: !TlvStream
    -- ^ unknown TLV records
  } deriving (Eq, Show, Generic)

instance NFData TxInitRbf

-- | The @tx_ack_rbf@ message (type 73).
data TxAckRbf = TxAckRbf
  { tx_ack_rbf_channel_id                  :: !ChannelId
  , tx_ack_rbf_funding_output_contribution :: !(Maybe Int64)
    -- ^ TLV type 0, in satoshis
  , tx_ack_rbf_require_confirmed_inputs    :: !Bool
    -- ^ TLV type 2
  , tx_ack_rbf_tlvs                        :: !TlvStream
    -- ^ unknown TLV records
  } deriving (Eq, Show, Generic)

instance NFData TxAckRbf

-- | The @tx_abort@ message (type 74).
data TxAbort = TxAbort
  { tx_abort_channel_id :: !ChannelId
  , tx_abort_data       :: !BS.ByteString
  , tx_abort_tlvs       :: !TlvStream
    -- ^ unknown TLV records
  } deriving (Eq, Show, Generic)

instance NFData TxAbort

-- channel quiescence ---------------------------------------------------------

-- | The @stfu@ message (type 2).
data Stfu = Stfu
  { stfu_channel_id :: !ChannelId
  , stfu_initiator  :: !Bool
    -- ^ whether the sender initiated quiescence (sent as 1 or 0)
  , stfu_tlvs       :: !TlvStream
    -- ^ unknown TLV records
  } deriving (Eq, Show, Generic)

instance NFData Stfu

-- channel close --------------------------------------------------------------

-- | The @shutdown@ message (type 38).
data Shutdown = Shutdown
  { shutdown_channel_id   :: !ChannelId
  , shutdown_scriptpubkey :: !ScriptPubKey
  , shutdown_tlvs         :: !TlvStream
    -- ^ unknown TLV records
  } deriving (Eq, Show, Generic)

instance NFData Shutdown

-- | The @closing_complete@ message (type 40).
data ClosingComplete = ClosingComplete
  { closing_complete_channel_id                :: !ChannelId
  , closing_complete_closer_scriptpubkey       :: !ScriptPubKey
  , closing_complete_closee_scriptpubkey       :: !ScriptPubKey
  , closing_complete_fee_satoshis              :: {-# UNPACK #-} !Satoshi
  , closing_complete_locktime                  :: {-# UNPACK #-} !Word32
  , closing_complete_closer_output_only        :: !(Maybe Signature)
    -- ^ TLV type 1
  , closing_complete_closee_output_only        :: !(Maybe Signature)
    -- ^ TLV type 2
  , closing_complete_closer_and_closee_outputs :: !(Maybe Signature)
    -- ^ TLV type 3
  , closing_complete_tlvs                      :: !TlvStream
    -- ^ unknown TLV records
  } deriving (Eq, Show, Generic)

instance NFData ClosingComplete

-- | The @closing_sig@ message (type 41). A valid @closing_sig@ carries
--   exactly one signature, in a field set in the @closing_complete@ it
--   answers; checking that is left to the caller.
data ClosingSig = ClosingSig
  { closing_sig_channel_id                :: !ChannelId
  , closing_sig_closer_scriptpubkey       :: !ScriptPubKey
  , closing_sig_closee_scriptpubkey       :: !ScriptPubKey
  , closing_sig_fee_satoshis              :: {-# UNPACK #-} !Satoshi
  , closing_sig_locktime                  :: {-# UNPACK #-} !Word32
  , closing_sig_closer_output_only        :: !(Maybe Signature)
    -- ^ TLV type 1
  , closing_sig_closee_output_only        :: !(Maybe Signature)
    -- ^ TLV type 2
  , closing_sig_closer_and_closee_outputs :: !(Maybe Signature)
    -- ^ TLV type 3
  , closing_sig_tlvs                      :: !TlvStream
    -- ^ unknown TLV records
  } deriving (Eq, Show, Generic)

instance NFData ClosingSig

-- | The legacy @closing_signed@ message (type 39), used when
--   @option_simple_close@ is not negotiated.
data ClosingSigned = ClosingSigned
  { closing_signed_channel_id   :: !ChannelId
  , closing_signed_fee_satoshis :: {-# UNPACK #-} !Satoshi
  , closing_signed_signature    :: !Signature
  , closing_signed_fee_range    :: !(Maybe FeeRange)
    -- ^ TLV type 1
  , closing_signed_tlvs         :: !TlvStream
    -- ^ unknown TLV records
  } deriving (Eq, Show, Generic)

instance NFData ClosingSigned

-- normal operation -----------------------------------------------------------

-- | The @update_add_htlc@ message (type 128).
data UpdateAddHtlc = UpdateAddHtlc
  { update_add_htlc_channel_id           :: !ChannelId
  , update_add_htlc_id                   :: !HtlcId
  , update_add_htlc_amount_msat          :: {-# UNPACK #-} !MilliSatoshi
  , update_add_htlc_payment_hash         :: !PaymentHash
  , update_add_htlc_cltv_expiry          :: {-# UNPACK #-} !Word32
  , update_add_htlc_onion_routing_packet :: !OnionRoutingPacket
  , update_add_htlc_path_key             :: !(Maybe Point)
    -- ^ the @blinded_path@ record (TLV type 0)
  , update_add_htlc_tlvs                 :: !TlvStream
    -- ^ unknown TLV records
  } deriving (Eq, Show, Generic)

instance NFData UpdateAddHtlc

-- | The @update_fulfill_htlc@ message (type 130).
data UpdateFulfillHtlc = UpdateFulfillHtlc
  { update_fulfill_htlc_channel_id          :: !ChannelId
  , update_fulfill_htlc_id                  :: !HtlcId
  , update_fulfill_htlc_payment_preimage    :: !PaymentPreimage
  , update_fulfill_htlc_attribution_data    :: !(Maybe AttributionData)
    -- ^ TLV type 1
  , update_fulfill_htlc_fulfillment_payload :: !(Maybe BS.ByteString)
    -- ^ TLV type 3
  , update_fulfill_htlc_tlvs                :: !TlvStream
    -- ^ unknown TLV records
  } deriving (Eq, Show, Generic)

instance NFData UpdateFulfillHtlc

-- | The @update_fail_htlc@ message (type 131).
data UpdateFailHtlc = UpdateFailHtlc
  { update_fail_htlc_channel_id       :: !ChannelId
  , update_fail_htlc_id               :: !HtlcId
  , update_fail_htlc_reason           :: !BS.ByteString
  , update_fail_htlc_attribution_data :: !(Maybe AttributionData)
    -- ^ TLV type 1
  , update_fail_htlc_tlvs             :: !TlvStream
    -- ^ unknown TLV records
  } deriving (Eq, Show, Generic)

instance NFData UpdateFailHtlc

-- | The @update_fail_malformed_htlc@ message (type 135).
data UpdateFailMalformedHtlc = UpdateFailMalformedHtlc
  { update_fail_malformed_htlc_channel_id      :: !ChannelId
  , update_fail_malformed_htlc_id              :: !HtlcId
  , update_fail_malformed_htlc_sha256_of_onion :: !OnionHash
  , update_fail_malformed_htlc_failure_code    :: {-# UNPACK #-} !Word16
  , update_fail_malformed_htlc_tlvs            :: !TlvStream
    -- ^ unknown TLV records
  } deriving (Eq, Show, Generic)

instance NFData UpdateFailMalformedHtlc

-- | The @commitment_signed@ message (type 132).
data CommitmentSigned = CommitmentSigned
  { commitment_signed_channel_id      :: !ChannelId
  , commitment_signed_signature       :: !Signature
  , commitment_signed_htlc_signatures :: ![Signature]
  , commitment_signed_funding_txid    :: !(Maybe TxId)
    -- ^ TLV type 1
  , commitment_signed_tlvs            :: !TlvStream
    -- ^ unknown TLV records
  } deriving (Eq, Show, Generic)

instance NFData CommitmentSigned

-- | The @revoke_and_ack@ message (type 133).
data RevokeAndAck = RevokeAndAck
  { revoke_and_ack_channel_id                :: !ChannelId
  , revoke_and_ack_per_commitment_secret     :: !PerCommitmentSecret
  , revoke_and_ack_next_per_commitment_point :: !Point
  , revoke_and_ack_tlvs                      :: !TlvStream
    -- ^ unknown TLV records
  } deriving (Eq, Show, Generic)

instance NFData RevokeAndAck

-- | The @update_fee@ message (type 134).
data UpdateFee = UpdateFee
  { update_fee_channel_id     :: !ChannelId
  , update_fee_feerate_per_kw :: {-# UNPACK #-} !Word32
  , update_fee_tlvs           :: !TlvStream
    -- ^ unknown TLV records
  } deriving (Eq, Show, Generic)

instance NFData UpdateFee

-- message retransmission -----------------------------------------------------

-- | The @channel_reestablish@ message (type 136).
data ChannelReestablish = ChannelReestablish
  { channel_reestablish_channel_id                      :: !ChannelId
  , channel_reestablish_next_commitment_number
      :: {-# UNPACK #-} !Word64
  , channel_reestablish_next_revocation_number
      :: {-# UNPACK #-} !Word64
  , channel_reestablish_your_last_per_commitment_secret
      :: !PerCommitmentSecret
  , channel_reestablish_my_current_per_commitment_point :: !Point
  , channel_reestablish_next_funding
      :: !(Maybe NextFunding)
    -- ^ TLV type 1
  , channel_reestablish_tlvs                            :: !TlvStream
    -- ^ unknown TLV records
  } deriving (Eq, Show, Generic)

instance NFData ChannelReestablish

-- messages -------------------------------------------------------------------

-- | A BOLT #2 message.
data Message
  = MsgOpenChannel !OpenChannel
  | MsgAcceptChannel !AcceptChannel
  | MsgFundingCreated !FundingCreated
  | MsgFundingSigned !FundingSigned
  | MsgChannelReady !ChannelReady
  | MsgOpenChannel2 !OpenChannel2
  | MsgAcceptChannel2 !AcceptChannel2
  | MsgTxAddInput !TxAddInput
  | MsgTxAddOutput !TxAddOutput
  | MsgTxRemoveInput !TxRemoveInput
  | MsgTxRemoveOutput !TxRemoveOutput
  | MsgTxComplete !TxComplete
  | MsgTxSignatures !TxSignatures
  | MsgTxInitRbf !TxInitRbf
  | MsgTxAckRbf !TxAckRbf
  | MsgTxAbort !TxAbort
  | MsgStfu !Stfu
  | MsgShutdown !Shutdown
  | MsgClosingComplete !ClosingComplete
  | MsgClosingSig !ClosingSig
  | MsgClosingSigned !ClosingSigned
  | MsgUpdateAddHtlc !UpdateAddHtlc
  | MsgUpdateFulfillHtlc !UpdateFulfillHtlc
  | MsgUpdateFailHtlc !UpdateFailHtlc
  | MsgUpdateFailMalformedHtlc !UpdateFailMalformedHtlc
  | MsgCommitmentSigned !CommitmentSigned
  | MsgRevokeAndAck !RevokeAndAck
  | MsgUpdateFee !UpdateFee
  | MsgChannelReestablish !ChannelReestablish
  deriving (Eq, Show, Generic)

instance NFData Message

-- | The wire type of a 'Message'.
--
--   >>> message_type (MsgTxComplete (TxComplete cid BOLT1.empty_tlv_stream))
--   70
message_type :: Message -> Word16
message_type m = case m of
  MsgOpenChannel {}             -> 32
  MsgAcceptChannel {}           -> 33
  MsgFundingCreated {}          -> 34
  MsgFundingSigned {}           -> 35
  MsgChannelReady {}            -> 36
  MsgOpenChannel2 {}            -> 64
  MsgAcceptChannel2 {}          -> 65
  MsgTxAddInput {}              -> 66
  MsgTxAddOutput {}             -> 67
  MsgTxRemoveInput {}           -> 68
  MsgTxRemoveOutput {}          -> 69
  MsgTxComplete {}              -> 70
  MsgTxSignatures {}            -> 71
  MsgTxInitRbf {}               -> 72
  MsgTxAckRbf {}                -> 73
  MsgTxAbort {}                 -> 74
  MsgStfu {}                    -> 2
  MsgShutdown {}                -> 38
  MsgClosingComplete {}         -> 40
  MsgClosingSig {}              -> 41
  MsgClosingSigned {}           -> 39
  MsgUpdateAddHtlc {}           -> 128
  MsgUpdateFulfillHtlc {}       -> 130
  MsgUpdateFailHtlc {}          -> 131
  MsgUpdateFailMalformedHtlc {} -> 135
  MsgCommitmentSigned {}        -> 132
  MsgRevokeAndAck {}            -> 133
  MsgUpdateFee {}               -> 134
  MsgChannelReestablish {}      -> 136