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

-- |
-- Module: Lightning.Protocol.BOLT5.Types
-- Copyright: (c) 2025 Jared Tobin
-- License: MIT
-- Maintainer: Jared Tobin <jared@ppad.tech>
--
-- Types for BOLT #5 on-chain transaction handling.

module Lightning.Protocol.BOLT5.Types (
    -- * Close identification
    CloseType(..)

    -- * Output classification
  , UnresolvedOutput(..)
  , OutputResolution(..)

    -- * HTLC output type
  , HTLCOutputType(..)
  , htlcOutputType
  , htlcOutputTypeWeight

    -- * Spending transactions
  , SpendingTx(..)

    -- * Penalty batching
  , RevokedOutput(..)
  , RevokedOutputType(..)
  , PenaltyContext(..)
  , revoked_output_weight

    -- * Weight constants (Appendix A)
  , to_local_penalty_witness_weight
  , offered_htlc_penalty_witness_weight
  , accepted_htlc_penalty_witness_weight
  , to_local_penalty_input_weight
  , offered_htlc_penalty_input_weight
  , accepted_htlc_penalty_input_weight
  , to_remote_input_weight
  , penalty_tx_base_weight
  , max_standard_weight

    -- * Fee calculation
  , spending_fee
  ) where

import Bitcoin.Prim.Tx (Tx(..))
import Bitcoin.Prim.Tx.Sighash (SighashType(..))
import Data.List.NonEmpty (NonEmpty)
import Data.Word (Word64)
import GHC.Generics (Generic)
import Lightning.Protocol.BOLT3.Types
import Lightning.Protocol.BOLT3.Tx (
    CommitmentKeys(..)
  , OutputType(..)
  )

-- close identification -----------------------------------------------

-- | What kind of close was detected on chain.
data CloseType
  = MutualClose
    -- ^ Cooperative closure agreed by both parties.
  | LocalCommitClose
    -- ^ Our commitment transaction was broadcast.
  | RemoteCommitClose
    -- ^ The remote party's commitment transaction was broadcast.
  | RevokedCommitClose
    -- ^ A revoked (outdated) commitment transaction was broadcast.
  deriving (CloseType -> CloseType -> Bool
(CloseType -> CloseType -> Bool)
-> (CloseType -> CloseType -> Bool) -> Eq CloseType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CloseType -> CloseType -> Bool
== :: CloseType -> CloseType -> Bool
$c/= :: CloseType -> CloseType -> Bool
/= :: CloseType -> CloseType -> Bool
Eq, Int -> CloseType -> ShowS
[CloseType] -> ShowS
CloseType -> String
(Int -> CloseType -> ShowS)
-> (CloseType -> String)
-> ([CloseType] -> ShowS)
-> Show CloseType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> CloseType -> ShowS
showsPrec :: Int -> CloseType -> ShowS
$cshow :: CloseType -> String
show :: CloseType -> String
$cshowList :: [CloseType] -> ShowS
showList :: [CloseType] -> ShowS
Show, (forall x. CloseType -> Rep CloseType x)
-> (forall x. Rep CloseType x -> CloseType) -> Generic CloseType
forall x. Rep CloseType x -> CloseType
forall x. CloseType -> Rep CloseType x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. CloseType -> Rep CloseType x
from :: forall x. CloseType -> Rep CloseType x
$cto :: forall x. Rep CloseType x -> CloseType
to :: forall x. Rep CloseType x -> CloseType
Generic)

-- output classification ----------------------------------------------

-- | An unresolved commitment transaction output.
data UnresolvedOutput = UnresolvedOutput
  { UnresolvedOutput -> OutPoint
uo_outpoint :: !OutPoint
  , UnresolvedOutput -> Satoshi
uo_value    :: {-# UNPACK #-} !Satoshi
  , UnresolvedOutput -> OutputResolution
uo_type     :: !OutputResolution
  } deriving (UnresolvedOutput -> UnresolvedOutput -> Bool
(UnresolvedOutput -> UnresolvedOutput -> Bool)
-> (UnresolvedOutput -> UnresolvedOutput -> Bool)
-> Eq UnresolvedOutput
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: UnresolvedOutput -> UnresolvedOutput -> Bool
== :: UnresolvedOutput -> UnresolvedOutput -> Bool
$c/= :: UnresolvedOutput -> UnresolvedOutput -> Bool
/= :: UnresolvedOutput -> UnresolvedOutput -> Bool
Eq, Int -> UnresolvedOutput -> ShowS
[UnresolvedOutput] -> ShowS
UnresolvedOutput -> String
(Int -> UnresolvedOutput -> ShowS)
-> (UnresolvedOutput -> String)
-> ([UnresolvedOutput] -> ShowS)
-> Show UnresolvedOutput
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> UnresolvedOutput -> ShowS
showsPrec :: Int -> UnresolvedOutput -> ShowS
$cshow :: UnresolvedOutput -> String
show :: UnresolvedOutput -> String
$cshowList :: [UnresolvedOutput] -> ShowS
showList :: [UnresolvedOutput] -> ShowS
Show, (forall x. UnresolvedOutput -> Rep UnresolvedOutput x)
-> (forall x. Rep UnresolvedOutput x -> UnresolvedOutput)
-> Generic UnresolvedOutput
forall x. Rep UnresolvedOutput x -> UnresolvedOutput
forall x. UnresolvedOutput -> Rep UnresolvedOutput x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. UnresolvedOutput -> Rep UnresolvedOutput x
from :: forall x. UnresolvedOutput -> Rep UnresolvedOutput x
$cto :: forall x. Rep UnresolvedOutput x -> UnresolvedOutput
to :: forall x. Rep UnresolvedOutput x -> UnresolvedOutput
Generic)

-- | How to resolve an output, per BOLT #5 rules.
data OutputResolution
  = Resolved
    -- ^ Already resolved (e.g. to_remote on local commit).
  | SpendToLocal
      !ToSelfDelay !RevocationPubkey !LocalDelayedPubkey
    -- ^ Spend to_local after CSV delay.
  | SpendHTLCTimeout
      !HTLC !CommitmentKeys !ChannelFeatures
    -- ^ Spend via HTLC-timeout second-stage tx (local commit,
    --   local offer).
  | SpendHTLCSuccess
      !HTLC !CommitmentKeys !ChannelFeatures
    -- ^ Spend via HTLC-success second-stage tx (local commit,
    --   remote offer).
  | SpendHTLCTimeoutDirect !HTLC
    -- ^ Spend HTLC directly after timeout (remote commit,
    --   local offer).
  | SpendHTLCPreimageDirect !HTLC
    -- ^ Spend HTLC directly with preimage (remote commit,
    --   remote offer).
  | Revoke !RevocationPubkey
    -- ^ Spend revoked to_local with revocation key.
  | RevokeHTLC !RevocationPubkey !HTLCOutputType
    -- ^ Spend revoked HTLC output with revocation key.
  | AnchorSpend !FundingPubkey
    -- ^ Spend anchor output.
  deriving (OutputResolution -> OutputResolution -> Bool
(OutputResolution -> OutputResolution -> Bool)
-> (OutputResolution -> OutputResolution -> Bool)
-> Eq OutputResolution
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: OutputResolution -> OutputResolution -> Bool
== :: OutputResolution -> OutputResolution -> Bool
$c/= :: OutputResolution -> OutputResolution -> Bool
/= :: OutputResolution -> OutputResolution -> Bool
Eq, Int -> OutputResolution -> ShowS
[OutputResolution] -> ShowS
OutputResolution -> String
(Int -> OutputResolution -> ShowS)
-> (OutputResolution -> String)
-> ([OutputResolution] -> ShowS)
-> Show OutputResolution
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> OutputResolution -> ShowS
showsPrec :: Int -> OutputResolution -> ShowS
$cshow :: OutputResolution -> String
show :: OutputResolution -> String
$cshowList :: [OutputResolution] -> ShowS
showList :: [OutputResolution] -> ShowS
Show, (forall x. OutputResolution -> Rep OutputResolution x)
-> (forall x. Rep OutputResolution x -> OutputResolution)
-> Generic OutputResolution
forall x. Rep OutputResolution x -> OutputResolution
forall x. OutputResolution -> Rep OutputResolution x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. OutputResolution -> Rep OutputResolution x
from :: forall x. OutputResolution -> Rep OutputResolution x
$cto :: forall x. Rep OutputResolution x -> OutputResolution
to :: forall x. Rep OutputResolution x -> OutputResolution
Generic)

-- HTLC output type -------------------------------------------------

-- | Type of HTLC output, restricted to only HTLC variants.
--
-- Unlike bolt3's 'OutputType' which includes all six output
-- types, this ADT makes it impossible to confuse HTLC outputs
-- with to_local, to_remote, or anchor outputs.
data HTLCOutputType
  = HTLCOfferedOutput {-# UNPACK #-} !CltvExpiry
    -- ^ Offered HTLC output with CLTV expiry.
  | HTLCReceivedOutput {-# UNPACK #-} !CltvExpiry
    -- ^ Received HTLC output with CLTV expiry.
  deriving (HTLCOutputType -> HTLCOutputType -> Bool
(HTLCOutputType -> HTLCOutputType -> Bool)
-> (HTLCOutputType -> HTLCOutputType -> Bool) -> Eq HTLCOutputType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: HTLCOutputType -> HTLCOutputType -> Bool
== :: HTLCOutputType -> HTLCOutputType -> Bool
$c/= :: HTLCOutputType -> HTLCOutputType -> Bool
/= :: HTLCOutputType -> HTLCOutputType -> Bool
Eq, Int -> HTLCOutputType -> ShowS
[HTLCOutputType] -> ShowS
HTLCOutputType -> String
(Int -> HTLCOutputType -> ShowS)
-> (HTLCOutputType -> String)
-> ([HTLCOutputType] -> ShowS)
-> Show HTLCOutputType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> HTLCOutputType -> ShowS
showsPrec :: Int -> HTLCOutputType -> ShowS
$cshow :: HTLCOutputType -> String
show :: HTLCOutputType -> String
$cshowList :: [HTLCOutputType] -> ShowS
showList :: [HTLCOutputType] -> ShowS
Show, (forall x. HTLCOutputType -> Rep HTLCOutputType x)
-> (forall x. Rep HTLCOutputType x -> HTLCOutputType)
-> Generic HTLCOutputType
forall x. Rep HTLCOutputType x -> HTLCOutputType
forall x. HTLCOutputType -> Rep HTLCOutputType x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. HTLCOutputType -> Rep HTLCOutputType x
from :: forall x. HTLCOutputType -> Rep HTLCOutputType x
$cto :: forall x. Rep HTLCOutputType x -> HTLCOutputType
to :: forall x. Rep HTLCOutputType x -> HTLCOutputType
Generic)

-- | Extract an 'HTLCOutputType' from a bolt3 'OutputType'.
--
-- Returns 'Nothing' for non-HTLC output types.
--
-- >>> htlcOutputType (OutputOfferedHTLC (CltvExpiry 500))
-- Just (HTLCOfferedOutput (CltvExpiry ...))
-- >>> htlcOutputType OutputToLocal
-- Nothing
htlcOutputType :: OutputType -> Maybe HTLCOutputType
htlcOutputType :: OutputType -> Maybe HTLCOutputType
htlcOutputType (OutputOfferedHTLC CltvExpiry
e) =
  HTLCOutputType -> Maybe HTLCOutputType
forall a. a -> Maybe a
Just (CltvExpiry -> HTLCOutputType
HTLCOfferedOutput CltvExpiry
e)
htlcOutputType (OutputReceivedHTLC CltvExpiry
e) =
  HTLCOutputType -> Maybe HTLCOutputType
forall a. a -> Maybe a
Just (CltvExpiry -> HTLCOutputType
HTLCReceivedOutput CltvExpiry
e)
htlcOutputType OutputType
_ = Maybe HTLCOutputType
forall a. Maybe a
Nothing
{-# INLINE htlcOutputType #-}

-- | Penalty input weight for an HTLC output type.
htlcOutputTypeWeight :: HTLCOutputType -> Word64
htlcOutputTypeWeight :: HTLCOutputType -> Word64
htlcOutputTypeWeight (HTLCOfferedOutput CltvExpiry
_) =
  Word64
offered_htlc_penalty_input_weight
htlcOutputTypeWeight (HTLCReceivedOutput CltvExpiry
_) =
  Word64
accepted_htlc_penalty_input_weight
{-# INLINE htlcOutputTypeWeight #-}

-- spending transactions ----------------------------------------------

-- | Unsigned spending transaction, ready for caller to sign.
--
-- The caller uses bolt3 witness constructors to assemble the
-- final witness after signing.
data SpendingTx = SpendingTx
  { SpendingTx -> Tx
stx_tx           :: !Tx
    -- ^ The unsigned transaction.
  , SpendingTx -> Script
stx_input_script :: !Script
    -- ^ Witness script for the input being spent.
  , SpendingTx -> Satoshi
stx_input_value  :: {-# UNPACK #-} !Satoshi
    -- ^ Value of the input being spent (for sighash).
  , SpendingTx -> SighashType
stx_sighash_type :: !SighashType
    -- ^ Sighash type to use when signing.
  } deriving (SpendingTx -> SpendingTx -> Bool
(SpendingTx -> SpendingTx -> Bool)
-> (SpendingTx -> SpendingTx -> Bool) -> Eq SpendingTx
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SpendingTx -> SpendingTx -> Bool
== :: SpendingTx -> SpendingTx -> Bool
$c/= :: SpendingTx -> SpendingTx -> Bool
/= :: SpendingTx -> SpendingTx -> Bool
Eq, Int -> SpendingTx -> ShowS
[SpendingTx] -> ShowS
SpendingTx -> String
(Int -> SpendingTx -> ShowS)
-> (SpendingTx -> String)
-> ([SpendingTx] -> ShowS)
-> Show SpendingTx
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SpendingTx -> ShowS
showsPrec :: Int -> SpendingTx -> ShowS
$cshow :: SpendingTx -> String
show :: SpendingTx -> String
$cshowList :: [SpendingTx] -> ShowS
showList :: [SpendingTx] -> ShowS
Show, (forall x. SpendingTx -> Rep SpendingTx x)
-> (forall x. Rep SpendingTx x -> SpendingTx) -> Generic SpendingTx
forall x. Rep SpendingTx x -> SpendingTx
forall x. SpendingTx -> Rep SpendingTx x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. SpendingTx -> Rep SpendingTx x
from :: forall x. SpendingTx -> Rep SpendingTx x
$cto :: forall x. Rep SpendingTx x -> SpendingTx
to :: forall x. Rep SpendingTx x -> SpendingTx
Generic)

-- penalty batching ---------------------------------------------------

-- | A revoked output that can be swept with a revocation key.
--
-- This type restricts penalty transaction inputs to only
-- valid revocation targets: to_local outputs and HTLC outputs.
-- Other output types (to_remote, anchors) cannot appear in
-- penalty transactions.
data RevokedOutput = RevokedOutput
  { RevokedOutput -> OutPoint
ro_outpoint :: !OutPoint
  , RevokedOutput -> Satoshi
ro_value    :: {-# UNPACK #-} !Satoshi
  , RevokedOutput -> RevokedOutputType
ro_type     :: !RevokedOutputType
  } deriving (RevokedOutput -> RevokedOutput -> Bool
(RevokedOutput -> RevokedOutput -> Bool)
-> (RevokedOutput -> RevokedOutput -> Bool) -> Eq RevokedOutput
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: RevokedOutput -> RevokedOutput -> Bool
== :: RevokedOutput -> RevokedOutput -> Bool
$c/= :: RevokedOutput -> RevokedOutput -> Bool
/= :: RevokedOutput -> RevokedOutput -> Bool
Eq, Int -> RevokedOutput -> ShowS
[RevokedOutput] -> ShowS
RevokedOutput -> String
(Int -> RevokedOutput -> ShowS)
-> (RevokedOutput -> String)
-> ([RevokedOutput] -> ShowS)
-> Show RevokedOutput
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> RevokedOutput -> ShowS
showsPrec :: Int -> RevokedOutput -> ShowS
$cshow :: RevokedOutput -> String
show :: RevokedOutput -> String
$cshowList :: [RevokedOutput] -> ShowS
showList :: [RevokedOutput] -> ShowS
Show, (forall x. RevokedOutput -> Rep RevokedOutput x)
-> (forall x. Rep RevokedOutput x -> RevokedOutput)
-> Generic RevokedOutput
forall x. Rep RevokedOutput x -> RevokedOutput
forall x. RevokedOutput -> Rep RevokedOutput x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. RevokedOutput -> Rep RevokedOutput x
from :: forall x. RevokedOutput -> Rep RevokedOutput x
$cto :: forall x. Rep RevokedOutput x -> RevokedOutput
to :: forall x. Rep RevokedOutput x -> RevokedOutput
Generic)

-- | What kind of revoked output is being swept.
data RevokedOutputType
  = RevokedToLocal
    -- ^ Revoked to_local output.
  | RevokedHTLC !HTLCOutputType
    -- ^ Revoked HTLC output.
  deriving (RevokedOutputType -> RevokedOutputType -> Bool
(RevokedOutputType -> RevokedOutputType -> Bool)
-> (RevokedOutputType -> RevokedOutputType -> Bool)
-> Eq RevokedOutputType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: RevokedOutputType -> RevokedOutputType -> Bool
== :: RevokedOutputType -> RevokedOutputType -> Bool
$c/= :: RevokedOutputType -> RevokedOutputType -> Bool
/= :: RevokedOutputType -> RevokedOutputType -> Bool
Eq, Int -> RevokedOutputType -> ShowS
[RevokedOutputType] -> ShowS
RevokedOutputType -> String
(Int -> RevokedOutputType -> ShowS)
-> (RevokedOutputType -> String)
-> ([RevokedOutputType] -> ShowS)
-> Show RevokedOutputType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> RevokedOutputType -> ShowS
showsPrec :: Int -> RevokedOutputType -> ShowS
$cshow :: RevokedOutputType -> String
show :: RevokedOutputType -> String
$cshowList :: [RevokedOutputType] -> ShowS
showList :: [RevokedOutputType] -> ShowS
Show, (forall x. RevokedOutputType -> Rep RevokedOutputType x)
-> (forall x. Rep RevokedOutputType x -> RevokedOutputType)
-> Generic RevokedOutputType
forall x. Rep RevokedOutputType x -> RevokedOutputType
forall x. RevokedOutputType -> Rep RevokedOutputType x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. RevokedOutputType -> Rep RevokedOutputType x
from :: forall x. RevokedOutputType -> Rep RevokedOutputType x
$cto :: forall x. Rep RevokedOutputType x -> RevokedOutputType
to :: forall x. Rep RevokedOutputType x -> RevokedOutputType
Generic)

-- | Penalty input weight for a revoked output.
revoked_output_weight :: RevokedOutput -> Word64
revoked_output_weight :: RevokedOutput -> Word64
revoked_output_weight !RevokedOutput
ro = case RevokedOutput -> RevokedOutputType
ro_type RevokedOutput
ro of
  RevokedOutputType
RevokedToLocal ->
    Word64
to_local_penalty_input_weight
  RevokedHTLC !HTLCOutputType
htype ->
    HTLCOutputType -> Word64
htlcOutputTypeWeight HTLCOutputType
htype
{-# INLINE revoked_output_weight #-}

-- | Context for constructing batched penalty transactions.
data PenaltyContext = PenaltyContext
  { PenaltyContext -> NonEmpty RevokedOutput
pc_outputs        :: !(NonEmpty RevokedOutput)
    -- ^ Revoked outputs to sweep (must be non-empty).
  , PenaltyContext -> RevocationPubkey
pc_revocation_key :: !RevocationPubkey
    -- ^ Revocation pubkey for all outputs.
  , PenaltyContext -> Script
pc_destination    :: !Script
    -- ^ Destination scriptPubKey.
  , PenaltyContext -> FeeratePerKw
pc_feerate        :: !FeeratePerKw
    -- ^ Fee rate for the penalty transaction.
  } deriving (PenaltyContext -> PenaltyContext -> Bool
(PenaltyContext -> PenaltyContext -> Bool)
-> (PenaltyContext -> PenaltyContext -> Bool) -> Eq PenaltyContext
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PenaltyContext -> PenaltyContext -> Bool
== :: PenaltyContext -> PenaltyContext -> Bool
$c/= :: PenaltyContext -> PenaltyContext -> Bool
/= :: PenaltyContext -> PenaltyContext -> Bool
Eq, Int -> PenaltyContext -> ShowS
[PenaltyContext] -> ShowS
PenaltyContext -> String
(Int -> PenaltyContext -> ShowS)
-> (PenaltyContext -> String)
-> ([PenaltyContext] -> ShowS)
-> Show PenaltyContext
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PenaltyContext -> ShowS
showsPrec :: Int -> PenaltyContext -> ShowS
$cshow :: PenaltyContext -> String
show :: PenaltyContext -> String
$cshowList :: [PenaltyContext] -> ShowS
showList :: [PenaltyContext] -> ShowS
Show, (forall x. PenaltyContext -> Rep PenaltyContext x)
-> (forall x. Rep PenaltyContext x -> PenaltyContext)
-> Generic PenaltyContext
forall x. Rep PenaltyContext x -> PenaltyContext
forall x. PenaltyContext -> Rep PenaltyContext x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. PenaltyContext -> Rep PenaltyContext x
from :: forall x. PenaltyContext -> Rep PenaltyContext x
$cto :: forall x. Rep PenaltyContext x -> PenaltyContext
to :: forall x. Rep PenaltyContext x -> PenaltyContext
Generic)

-- weight constants (BOLT #5 Appendix A) ------------------------------

-- | Expected weight of the to_local penalty transaction witness
--   (160 bytes).
to_local_penalty_witness_weight :: Word64
to_local_penalty_witness_weight :: Word64
to_local_penalty_witness_weight = Word64
160

-- | Expected weight of the offered_htlc penalty transaction
--   witness (243 bytes).
offered_htlc_penalty_witness_weight :: Word64
offered_htlc_penalty_witness_weight :: Word64
offered_htlc_penalty_witness_weight = Word64
243

-- | Expected weight of the accepted_htlc penalty transaction
--   witness (249 bytes).
accepted_htlc_penalty_witness_weight :: Word64
accepted_htlc_penalty_witness_weight :: Word64
accepted_htlc_penalty_witness_weight = Word64
249

-- | Weight of a to_local penalty input (164 + 160 = 324 bytes).
to_local_penalty_input_weight :: Word64
to_local_penalty_input_weight :: Word64
to_local_penalty_input_weight = Word64
324

-- | Weight of an offered_htlc penalty input
--   (164 + 243 = 407 bytes).
offered_htlc_penalty_input_weight :: Word64
offered_htlc_penalty_input_weight :: Word64
offered_htlc_penalty_input_weight = Word64
407

-- | Weight of an accepted_htlc penalty input
--   (164 + 249 = 413 bytes).
accepted_htlc_penalty_input_weight :: Word64
accepted_htlc_penalty_input_weight :: Word64
accepted_htlc_penalty_input_weight = Word64
413

-- | Weight of a to_remote P2WPKH input
--   (108 + 164 = 272 bytes).
to_remote_input_weight :: Word64
to_remote_input_weight :: Word64
to_remote_input_weight = Word64
272

-- | Base weight of a penalty transaction (4*53 + 2 = 214 bytes).
--
-- Non-witness: version(4) + input_count(1) + output_count(1) +
-- value(8) + script_len(1) + p2wsh_script(34) + locktime(4) = 53
-- Witness header: 2 bytes.
penalty_tx_base_weight :: Word64
penalty_tx_base_weight :: Word64
penalty_tx_base_weight = Word64
214

-- | Maximum standard transaction weight (400,000 bytes).
max_standard_weight :: Word64
max_standard_weight :: Word64
max_standard_weight = Word64
400000

-- fee calculation ----------------------------------------------------

-- | Calculate the fee for a spending transaction given its weight.
--
-- @fee = feerate_per_kw * weight / 1000@
spending_fee :: FeeratePerKw -> Word64 -> Satoshi
spending_fee :: FeeratePerKw -> Word64 -> Satoshi
spending_fee (FeeratePerKw !Word32
rate) !Word64
weight =
  Word64 -> Satoshi
Satoshi ((Word32 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
rate Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
weight) Word64 -> Word64 -> Word64
forall a. Integral a => a -> a -> a
`div` Word64
1000)
{-# INLINE spending_fee #-}