Types.hs (12557B)
1 {-# OPTIONS_HADDOCK prune #-} 2 {-# LANGUAGE BangPatterns #-} 3 {-# LANGUAGE DeriveGeneric #-} 4 {-# LANGUAGE GeneralizedNewtypeDeriving #-} 5 6 -- | 7 -- Module: Lightning.Protocol.BOLT3.Types 8 -- Copyright: (c) 2025 Jared Tobin 9 -- License: MIT 10 -- Maintainer: Jared Tobin <jared@ppad.tech> 11 -- 12 -- Core types for BOLT #3 transaction and script formats. 13 14 module Lightning.Protocol.BOLT3.Types ( 15 -- * Monetary amounts 16 Satoshi(..) 17 , MilliSatoshi(..) 18 , msat_to_sat 19 , sat_to_msat 20 21 -- * Keys and points 22 , Pubkey(..) 23 , pubkey 24 , Seckey(..) 25 , seckey 26 , Point(..) 27 , point 28 29 -- * Hashes 30 , PaymentHash(..) 31 , payment_hash 32 , PaymentPreimage(..) 33 , payment_preimage 34 35 -- * Transaction primitives 36 , TxId(..) 37 , mkTxId 38 , OutPoint(..) 39 , Sequence(..) 40 , Locktime(..) 41 42 -- * Channel parameters 43 , CommitmentNumber(..) 44 , commitment_number 45 , ToSelfDelay(..) 46 , CltvExpiry(..) 47 , DustLimit(..) 48 , FeeratePerKw(..) 49 50 -- * HTLC types 51 , HTLC(..) 52 , HTLCDirection(..) 53 54 -- * Basepoints 55 , Basepoints(..) 56 , PerCommitmentPoint(..) 57 , PerCommitmentSecret(..) 58 , per_commitment_secret 59 , RevocationBasepoint(..) 60 , PaymentBasepoint(..) 61 , DelayedPaymentBasepoint(..) 62 , HtlcBasepoint(..) 63 64 -- * Derived keys 65 , LocalPubkey(..) 66 , RemotePubkey(..) 67 , LocalDelayedPubkey(..) 68 , RemoteDelayedPubkey(..) 69 , LocalHtlcPubkey(..) 70 , RemoteHtlcPubkey(..) 71 , RevocationPubkey(..) 72 , FundingPubkey(..) 73 74 -- * Script 75 , Script(..) 76 77 -- * Witness (re-exported from ppad-tx) 78 , Witness(..) 79 80 -- * Channel options 81 , ChannelFeatures(..) 82 , has_anchors 83 84 -- * Transaction weights (constants) 85 , commitment_weight_no_anchors 86 , commitment_weight_anchors 87 , htlc_timeout_weight_no_anchors 88 , htlc_timeout_weight_anchors 89 , htlc_success_weight_no_anchors 90 , htlc_success_weight_anchors 91 , htlc_output_weight 92 93 -- * Dust thresholds (constants) 94 , dust_p2pkh 95 , dust_p2sh 96 , dust_p2wpkh 97 , dust_p2wsh 98 , anchor_output_value 99 ) where 100 101 import Bitcoin.Prim.Tx (TxId(..), mkTxId, OutPoint(..), Witness(..)) 102 import Data.Word (Word16, Word32, Word64) 103 import qualified Data.ByteString as BS 104 import GHC.Generics (Generic) 105 106 -- monetary amounts ------------------------------------------------------------ 107 108 -- | Amount in satoshis. 109 newtype Satoshi = Satoshi { unSatoshi :: Word64 } 110 deriving (Eq, Ord, Show, Generic, Num) 111 112 -- | Amount in millisatoshis. 113 newtype MilliSatoshi = MilliSatoshi { unMilliSatoshi :: Word64 } 114 deriving (Eq, Ord, Show, Generic, Num) 115 116 -- | Convert millisatoshis to satoshis (rounds down). 117 msat_to_sat :: MilliSatoshi -> Satoshi 118 msat_to_sat (MilliSatoshi m) = Satoshi (m `div` 1000) 119 {-# INLINE msat_to_sat #-} 120 121 -- | Convert satoshis to millisatoshis. 122 sat_to_msat :: Satoshi -> MilliSatoshi 123 sat_to_msat (Satoshi s) = MilliSatoshi (s * 1000) 124 {-# INLINE sat_to_msat #-} 125 126 -- keys and points ------------------------------------------------------------- 127 128 -- | Compressed public key (33 bytes). 129 newtype Pubkey = Pubkey { unPubkey :: BS.ByteString } 130 deriving (Eq, Ord, Show, Generic) 131 132 -- | Parse a 33-byte compressed public key. 133 -- 134 -- Returns Nothing if the input is not exactly 33 bytes. 135 -- 136 -- >>> pubkey (BS.replicate 33 0x02) 137 -- Just (Pubkey ...) 138 -- >>> pubkey (BS.replicate 32 0x02) 139 -- Nothing 140 pubkey :: BS.ByteString -> Maybe Pubkey 141 pubkey bs 142 | BS.length bs == 33 = Just (Pubkey bs) 143 | otherwise = Nothing 144 {-# INLINE pubkey #-} 145 146 -- | Secret key (32 bytes). 147 newtype Seckey = Seckey { unSeckey :: BS.ByteString } 148 deriving (Eq, Generic) 149 150 -- Don't show secret keys 151 instance Show Seckey where 152 show _ = "Seckey <redacted>" 153 154 -- | Parse a 32-byte secret key. 155 -- 156 -- Returns Nothing if the input is not exactly 32 bytes. 157 seckey :: BS.ByteString -> Maybe Seckey 158 seckey bs 159 | BS.length bs == 32 = Just (Seckey bs) 160 | otherwise = Nothing 161 {-# INLINE seckey #-} 162 163 -- | Elliptic curve point (33-byte compressed form). 164 newtype Point = Point { unPoint :: BS.ByteString } 165 deriving (Eq, Ord, Show, Generic) 166 167 -- | Parse a 33-byte elliptic curve point. 168 -- 169 -- Returns Nothing if the input is not exactly 33 bytes. 170 point :: BS.ByteString -> Maybe Point 171 point bs 172 | BS.length bs == 33 = Just (Point bs) 173 | otherwise = Nothing 174 {-# INLINE point #-} 175 176 -- hashes ---------------------------------------------------------------------- 177 178 -- | Payment hash (32 bytes, SHA256 of preimage). 179 newtype PaymentHash = PaymentHash { unPaymentHash :: BS.ByteString } 180 deriving (Eq, Ord, Show, Generic) 181 182 -- | Parse a 32-byte payment hash. 183 -- 184 -- Returns Nothing if the input is not exactly 32 bytes. 185 payment_hash :: BS.ByteString -> Maybe PaymentHash 186 payment_hash bs 187 | BS.length bs == 32 = Just (PaymentHash bs) 188 | otherwise = Nothing 189 {-# INLINE payment_hash #-} 190 191 -- | Payment preimage (32 bytes). 192 newtype PaymentPreimage = PaymentPreimage { unPaymentPreimage :: BS.ByteString } 193 deriving (Eq, Generic) 194 195 instance Show PaymentPreimage where 196 show _ = "PaymentPreimage <redacted>" 197 198 -- | Parse a 32-byte payment preimage. 199 -- 200 -- Returns Nothing if the input is not exactly 32 bytes. 201 payment_preimage :: BS.ByteString -> Maybe PaymentPreimage 202 payment_preimage bs 203 | BS.length bs == 32 = Just (PaymentPreimage bs) 204 | otherwise = Nothing 205 {-# INLINE payment_preimage #-} 206 207 -- transaction primitives ------------------------------------------------------ 208 209 -- | Transaction input sequence number. 210 newtype Sequence = Sequence { unSequence :: Word32 } 211 deriving (Eq, Ord, Show, Generic, Num) 212 213 -- | Transaction locktime. 214 newtype Locktime = Locktime { unLocktime :: Word32 } 215 deriving (Eq, Ord, Show, Generic, Num) 216 217 -- channel parameters ---------------------------------------------------------- 218 219 -- | 48-bit commitment number. 220 newtype CommitmentNumber = CommitmentNumber { unCommitmentNumber :: Word64 } 221 deriving (Eq, Ord, Show, Generic, Num) 222 223 -- | Parse a 48-bit commitment number. 224 -- 225 -- Returns Nothing if the value exceeds 2^48 - 1. 226 commitment_number :: Word64 -> Maybe CommitmentNumber 227 commitment_number n 228 | n <= 281474976710655 = Just (CommitmentNumber n) 229 | otherwise = Nothing 230 {-# INLINE commitment_number #-} 231 232 -- | CSV delay for to_local outputs. 233 newtype ToSelfDelay = ToSelfDelay { unToSelfDelay :: Word16 } 234 deriving (Eq, Ord, Show, Generic, Num) 235 236 -- | CLTV expiry for HTLCs. 237 newtype CltvExpiry = CltvExpiry { unCltvExpiry :: Word32 } 238 deriving (Eq, Ord, Show, Generic, Num) 239 240 -- | Dust limit threshold. 241 newtype DustLimit = DustLimit { unDustLimit :: Satoshi } 242 deriving (Eq, Ord, Show, Generic) 243 244 -- | Fee rate in satoshis per 1000 weight units. 245 newtype FeeratePerKw = FeeratePerKw { unFeeratePerKw :: Word32 } 246 deriving (Eq, Ord, Show, Generic, Num) 247 248 -- HTLC types ------------------------------------------------------------------ 249 250 -- | Direction of an HTLC from the commitment tx owner's perspective. 251 data HTLCDirection 252 = HTLCOffered -- ^ We offered this HTLC (outgoing) 253 | HTLCReceived -- ^ We received this HTLC (incoming) 254 deriving (Eq, Ord, Show, Generic) 255 256 -- | HTLC output details. 257 -- 258 -- NOTE: No Ord instance is provided. BOLT #3 requires output ordering by 259 -- amount then scriptPubKey, but scriptPubKey depends on derived keys which 260 -- are not available here. Use 'sort_outputs' in Tx module for proper BIP69 261 -- output ordering. 262 data HTLC = HTLC 263 { htlc_direction :: !HTLCDirection 264 , htlc_amount_msat :: {-# UNPACK #-} !MilliSatoshi 265 , htlc_payment_hash :: {-# UNPACK #-} !PaymentHash 266 , htlc_cltv_expiry :: {-# UNPACK #-} !CltvExpiry 267 } deriving (Eq, Show, Generic) 268 269 -- basepoints ------------------------------------------------------------------ 270 271 -- | Per-commitment point (used to derive keys). 272 newtype PerCommitmentPoint = PerCommitmentPoint { unPerCommitmentPoint :: Point } 273 deriving (Eq, Ord, Show, Generic) 274 275 -- | Per-commitment secret (32 bytes). 276 newtype PerCommitmentSecret = PerCommitmentSecret 277 { unPerCommitmentSecret :: BS.ByteString } 278 deriving (Eq, Generic) 279 280 instance Show PerCommitmentSecret where 281 show _ = "PerCommitmentSecret <redacted>" 282 283 -- | Parse a 32-byte per-commitment secret. 284 -- 285 -- Returns Nothing if the input is not exactly 32 bytes. 286 per_commitment_secret :: BS.ByteString -> Maybe PerCommitmentSecret 287 per_commitment_secret bs 288 | BS.length bs == 32 = Just (PerCommitmentSecret bs) 289 | otherwise = Nothing 290 {-# INLINE per_commitment_secret #-} 291 292 -- | Revocation basepoint. 293 newtype RevocationBasepoint = RevocationBasepoint 294 { unRevocationBasepoint :: Point } 295 deriving (Eq, Ord, Show, Generic) 296 297 -- | Payment basepoint. 298 newtype PaymentBasepoint = PaymentBasepoint 299 { unPaymentBasepoint :: Point } 300 deriving (Eq, Ord, Show, Generic) 301 302 -- | Delayed payment basepoint. 303 newtype DelayedPaymentBasepoint = DelayedPaymentBasepoint 304 { unDelayedPaymentBasepoint :: Point } 305 deriving (Eq, Ord, Show, Generic) 306 307 -- | HTLC basepoint. 308 newtype HtlcBasepoint = HtlcBasepoint { unHtlcBasepoint :: Point } 309 deriving (Eq, Ord, Show, Generic) 310 311 -- | Collection of all basepoints for one party. 312 data Basepoints = Basepoints 313 { bp_revocation :: !RevocationBasepoint 314 , bp_payment :: !PaymentBasepoint 315 , bp_delayed_payment :: !DelayedPaymentBasepoint 316 , bp_htlc :: !HtlcBasepoint 317 } deriving (Eq, Show, Generic) 318 319 -- derived keys ---------------------------------------------------------------- 320 321 -- | Local pubkey (derived from payment_basepoint + per_commitment_point). 322 newtype LocalPubkey = LocalPubkey { unLocalPubkey :: Pubkey } 323 deriving (Eq, Ord, Show, Generic) 324 325 -- | Remote pubkey (simply the remote's payment_basepoint). 326 newtype RemotePubkey = RemotePubkey { unRemotePubkey :: Pubkey } 327 deriving (Eq, Ord, Show, Generic) 328 329 -- | Local delayed pubkey. 330 newtype LocalDelayedPubkey = LocalDelayedPubkey 331 { unLocalDelayedPubkey :: Pubkey } 332 deriving (Eq, Ord, Show, Generic) 333 334 -- | Remote delayed pubkey. 335 newtype RemoteDelayedPubkey = RemoteDelayedPubkey 336 { unRemoteDelayedPubkey :: Pubkey } 337 deriving (Eq, Ord, Show, Generic) 338 339 -- | Local HTLC pubkey. 340 newtype LocalHtlcPubkey = LocalHtlcPubkey { unLocalHtlcPubkey :: Pubkey } 341 deriving (Eq, Ord, Show, Generic) 342 343 -- | Remote HTLC pubkey. 344 newtype RemoteHtlcPubkey = RemoteHtlcPubkey { unRemoteHtlcPubkey :: Pubkey } 345 deriving (Eq, Ord, Show, Generic) 346 347 -- | Revocation pubkey (derived from revocation_basepoint + per_commitment). 348 newtype RevocationPubkey = RevocationPubkey { unRevocationPubkey :: Pubkey } 349 deriving (Eq, Ord, Show, Generic) 350 351 -- | Funding pubkey (used in 2-of-2 multisig). 352 newtype FundingPubkey = FundingPubkey { unFundingPubkey :: Pubkey } 353 deriving (Eq, Ord, Show, Generic) 354 355 -- script ---------------------------------------------------------------------- 356 357 -- | Bitcoin script (serialized). 358 newtype Script = Script { unScript :: BS.ByteString } 359 deriving (Eq, Ord, Show, Generic) 360 361 -- channel options ------------------------------------------------------------- 362 363 -- | Channel feature flags relevant to BOLT #3. 364 data ChannelFeatures = ChannelFeatures 365 { cf_option_anchors :: !Bool 366 } deriving (Eq, Show, Generic) 367 368 -- | Check if option_anchors is enabled. 369 has_anchors :: ChannelFeatures -> Bool 370 has_anchors = cf_option_anchors 371 {-# INLINE has_anchors #-} 372 373 -- transaction weights (constants from spec) ----------------------------------- 374 375 -- | Base commitment tx weight without option_anchors. 376 commitment_weight_no_anchors :: Word64 377 commitment_weight_no_anchors = 724 378 379 -- | Base commitment tx weight with option_anchors. 380 commitment_weight_anchors :: Word64 381 commitment_weight_anchors = 1124 382 383 -- | HTLC-timeout tx weight without option_anchors. 384 htlc_timeout_weight_no_anchors :: Word64 385 htlc_timeout_weight_no_anchors = 663 386 387 -- | HTLC-timeout tx weight with option_anchors. 388 htlc_timeout_weight_anchors :: Word64 389 htlc_timeout_weight_anchors = 666 390 391 -- | HTLC-success tx weight without option_anchors. 392 htlc_success_weight_no_anchors :: Word64 393 htlc_success_weight_no_anchors = 703 394 395 -- | HTLC-success tx weight with option_anchors. 396 htlc_success_weight_anchors :: Word64 397 htlc_success_weight_anchors = 706 398 399 -- | Weight added per HTLC output in commitment tx. 400 htlc_output_weight :: Word64 401 htlc_output_weight = 172 402 403 -- dust thresholds (constants from Bitcoin Core) ------------------------------- 404 405 -- | P2PKH dust threshold (546 satoshis). 406 dust_p2pkh :: Satoshi 407 dust_p2pkh = Satoshi 546 408 409 -- | P2SH dust threshold (540 satoshis). 410 dust_p2sh :: Satoshi 411 dust_p2sh = Satoshi 540 412 413 -- | P2WPKH dust threshold (294 satoshis). 414 dust_p2wpkh :: Satoshi 415 dust_p2wpkh = Satoshi 294 416 417 -- | P2WSH dust threshold (330 satoshis). 418 dust_p2wsh :: Satoshi 419 dust_p2wsh = Satoshi 330 420 421 -- | Fixed anchor output value (330 satoshis). 422 anchor_output_value :: Satoshi 423 anchor_output_value = Satoshi 330