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

-- |
-- Module: Lightning.Protocol.BOLT1.Prim
-- Copyright: (c) 2025 Jared Tobin
-- License: MIT
-- Maintainer: Jared Tobin <jared@ppad.tech>
--
-- Primitive type encoding and decoding for BOLT #1.

module Lightning.Protocol.BOLT1.Prim (
  -- * Chain hash
    ChainHash(..)
  , chainHash
  , unChainHash

  -- * Channel identifier
  , ChannelId(..)
  , channelId
  , unChannelId
  , allChannels

  -- * Signatures and keys
  , Signature(..)
  , signature
  , unSignature
  , Point(..)
  , point
  , unPoint

  -- * Payment types
  , PaymentHash(..)
  , paymentHash
  , unPaymentHash
  , PaymentPreimage(..)
  , paymentPreimage
  , unPaymentPreimage

  -- * Per-commitment secret
  , PerCommitmentSecret(..)
  , perCommitmentSecret
  , unPerCommitmentSecret

  -- * Short channel identifier
  , ShortChannelId(..)
  , shortChannelId
  , scidWord64
  , scidBlockHeight
  , scidTxIndex
  , scidOutputIndex

  -- * Amounts
  , Satoshi(..)
  , MilliSatoshi(..)
  , satToMsat
  , msatToSat

  -- * Unsigned integer encoding
  , encodeU16
  , encodeU32
  , encodeU64

  -- * Signed integer encoding
  , encodeS8
  , encodeS16
  , encodeS32
  , encodeS64

  -- * Truncated unsigned integer encoding
  , encodeTu16
  , encodeTu32
  , encodeTu64

  -- * Minimal signed integer encoding
  , encodeMinSigned

  -- * BigSize encoding
  , encodeBigSize

  -- * Unsigned integer decoding
  , decodeU16
  , decodeU32
  , decodeU64

  -- * Signed integer decoding
  , decodeS8
  , decodeS16
  , decodeS32
  , decodeS64

  -- * Truncated unsigned integer decoding
  , decodeTu16
  , decodeTu32
  , decodeTu64

  -- * Minimal signed integer decoding
  , decodeMinSigned

  -- * BigSize decoding
  , decodeBigSize

  -- * Internal helpers
  , encodeLength
  ) where

import Control.DeepSeq (NFData)
import Data.Bits (unsafeShiftL, unsafeShiftR, (.&.), (.|.))
import qualified Data.ByteString as BS
import qualified Data.ByteString.Builder as BSB
import qualified Data.ByteString.Lazy as BSL
import Data.Int (Int8, Int16, Int32, Int64)
import Data.Word (Word16, Word32, Word64)
import GHC.Generics (Generic)

-- Chain hash ------------------------------------------------------------------

-- | A chain hash (32-byte hash identifying a blockchain).
newtype ChainHash = ChainHash BS.ByteString
  deriving stock (ChainHash -> ChainHash -> Bool
(ChainHash -> ChainHash -> Bool)
-> (ChainHash -> ChainHash -> Bool) -> Eq ChainHash
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ChainHash -> ChainHash -> Bool
== :: ChainHash -> ChainHash -> Bool
$c/= :: ChainHash -> ChainHash -> Bool
/= :: ChainHash -> ChainHash -> Bool
Eq, Eq ChainHash
Eq ChainHash =>
(ChainHash -> ChainHash -> Ordering)
-> (ChainHash -> ChainHash -> Bool)
-> (ChainHash -> ChainHash -> Bool)
-> (ChainHash -> ChainHash -> Bool)
-> (ChainHash -> ChainHash -> Bool)
-> (ChainHash -> ChainHash -> ChainHash)
-> (ChainHash -> ChainHash -> ChainHash)
-> Ord ChainHash
ChainHash -> ChainHash -> Bool
ChainHash -> ChainHash -> Ordering
ChainHash -> ChainHash -> ChainHash
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: ChainHash -> ChainHash -> Ordering
compare :: ChainHash -> ChainHash -> Ordering
$c< :: ChainHash -> ChainHash -> Bool
< :: ChainHash -> ChainHash -> Bool
$c<= :: ChainHash -> ChainHash -> Bool
<= :: ChainHash -> ChainHash -> Bool
$c> :: ChainHash -> ChainHash -> Bool
> :: ChainHash -> ChainHash -> Bool
$c>= :: ChainHash -> ChainHash -> Bool
>= :: ChainHash -> ChainHash -> Bool
$cmax :: ChainHash -> ChainHash -> ChainHash
max :: ChainHash -> ChainHash -> ChainHash
$cmin :: ChainHash -> ChainHash -> ChainHash
min :: ChainHash -> ChainHash -> ChainHash
Ord, Int -> ChainHash -> ShowS
[ChainHash] -> ShowS
ChainHash -> String
(Int -> ChainHash -> ShowS)
-> (ChainHash -> String)
-> ([ChainHash] -> ShowS)
-> Show ChainHash
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ChainHash -> ShowS
showsPrec :: Int -> ChainHash -> ShowS
$cshow :: ChainHash -> String
show :: ChainHash -> String
$cshowList :: [ChainHash] -> ShowS
showList :: [ChainHash] -> ShowS
Show, (forall x. ChainHash -> Rep ChainHash x)
-> (forall x. Rep ChainHash x -> ChainHash) -> Generic ChainHash
forall x. Rep ChainHash x -> ChainHash
forall x. ChainHash -> Rep ChainHash x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. ChainHash -> Rep ChainHash x
from :: forall x. ChainHash -> Rep ChainHash x
$cto :: forall x. Rep ChainHash x -> ChainHash
to :: forall x. Rep ChainHash x -> ChainHash
Generic)

instance NFData ChainHash

-- | Construct a chain hash from a 32-byte bytestring.
--
-- Returns 'Nothing' if the input is not exactly 32 bytes.
chainHash :: BS.ByteString -> Maybe ChainHash
chainHash :: ByteString -> Maybe ChainHash
chainHash ByteString
bs
  | ByteString -> Int
BS.length ByteString
bs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
32 = ChainHash -> Maybe ChainHash
forall a. a -> Maybe a
Just (ByteString -> ChainHash
ChainHash ByteString
bs)
  | Bool
otherwise = Maybe ChainHash
forall a. Maybe a
Nothing
{-# INLINE chainHash #-}

-- | Extract the raw bytes from a chain hash.
unChainHash :: ChainHash -> BS.ByteString
unChainHash :: ChainHash -> ByteString
unChainHash (ChainHash ByteString
bs) = ByteString
bs
{-# INLINE unChainHash #-}

-- Channel identifier ---------------------------------------------------------

-- | A 32-byte channel identifier.
newtype ChannelId = ChannelId BS.ByteString
  deriving stock (ChannelId -> ChannelId -> Bool
(ChannelId -> ChannelId -> Bool)
-> (ChannelId -> ChannelId -> Bool) -> Eq ChannelId
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ChannelId -> ChannelId -> Bool
== :: ChannelId -> ChannelId -> Bool
$c/= :: ChannelId -> ChannelId -> Bool
/= :: ChannelId -> ChannelId -> Bool
Eq, Eq ChannelId
Eq ChannelId =>
(ChannelId -> ChannelId -> Ordering)
-> (ChannelId -> ChannelId -> Bool)
-> (ChannelId -> ChannelId -> Bool)
-> (ChannelId -> ChannelId -> Bool)
-> (ChannelId -> ChannelId -> Bool)
-> (ChannelId -> ChannelId -> ChannelId)
-> (ChannelId -> ChannelId -> ChannelId)
-> Ord ChannelId
ChannelId -> ChannelId -> Bool
ChannelId -> ChannelId -> Ordering
ChannelId -> ChannelId -> ChannelId
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: ChannelId -> ChannelId -> Ordering
compare :: ChannelId -> ChannelId -> Ordering
$c< :: ChannelId -> ChannelId -> Bool
< :: ChannelId -> ChannelId -> Bool
$c<= :: ChannelId -> ChannelId -> Bool
<= :: ChannelId -> ChannelId -> Bool
$c> :: ChannelId -> ChannelId -> Bool
> :: ChannelId -> ChannelId -> Bool
$c>= :: ChannelId -> ChannelId -> Bool
>= :: ChannelId -> ChannelId -> Bool
$cmax :: ChannelId -> ChannelId -> ChannelId
max :: ChannelId -> ChannelId -> ChannelId
$cmin :: ChannelId -> ChannelId -> ChannelId
min :: ChannelId -> ChannelId -> ChannelId
Ord, Int -> ChannelId -> ShowS
[ChannelId] -> ShowS
ChannelId -> String
(Int -> ChannelId -> ShowS)
-> (ChannelId -> String)
-> ([ChannelId] -> ShowS)
-> Show ChannelId
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ChannelId -> ShowS
showsPrec :: Int -> ChannelId -> ShowS
$cshow :: ChannelId -> String
show :: ChannelId -> String
$cshowList :: [ChannelId] -> ShowS
showList :: [ChannelId] -> ShowS
Show, (forall x. ChannelId -> Rep ChannelId x)
-> (forall x. Rep ChannelId x -> ChannelId) -> Generic ChannelId
forall x. Rep ChannelId x -> ChannelId
forall x. ChannelId -> Rep ChannelId x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. ChannelId -> Rep ChannelId x
from :: forall x. ChannelId -> Rep ChannelId x
$cto :: forall x. Rep ChannelId x -> ChannelId
to :: forall x. Rep ChannelId x -> ChannelId
Generic)

instance NFData ChannelId

-- | Construct a 'ChannelId' from a 32-byte 'BS.ByteString'.
--
-- Returns 'Nothing' if the input is not exactly 32 bytes.
channelId :: BS.ByteString -> Maybe ChannelId
channelId :: ByteString -> Maybe ChannelId
channelId ByteString
bs
  | ByteString -> Int
BS.length ByteString
bs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
32 = ChannelId -> Maybe ChannelId
forall a. a -> Maybe a
Just (ByteString -> ChannelId
ChannelId ByteString
bs)
  | Bool
otherwise          = Maybe ChannelId
forall a. Maybe a
Nothing
{-# INLINE channelId #-}

-- | Extract the raw bytes from a 'ChannelId'.
unChannelId :: ChannelId -> BS.ByteString
unChannelId :: ChannelId -> ByteString
unChannelId (ChannelId ByteString
bs) = ByteString
bs
{-# INLINE unChannelId #-}

-- | The all-zeros channel ID (connection-level errors).
allChannels :: ChannelId
allChannels :: ChannelId
allChannels = ByteString -> ChannelId
ChannelId (Int -> Word8 -> ByteString
BS.replicate Int
32 Word8
0x00)

-- Signatures and keys --------------------------------------------------------

-- | A 64-byte compact ECDSA signature.
newtype Signature = Signature BS.ByteString
  deriving stock (Signature -> Signature -> Bool
(Signature -> Signature -> Bool)
-> (Signature -> Signature -> Bool) -> Eq Signature
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Signature -> Signature -> Bool
== :: Signature -> Signature -> Bool
$c/= :: Signature -> Signature -> Bool
/= :: Signature -> Signature -> Bool
Eq, Eq Signature
Eq Signature =>
(Signature -> Signature -> Ordering)
-> (Signature -> Signature -> Bool)
-> (Signature -> Signature -> Bool)
-> (Signature -> Signature -> Bool)
-> (Signature -> Signature -> Bool)
-> (Signature -> Signature -> Signature)
-> (Signature -> Signature -> Signature)
-> Ord Signature
Signature -> Signature -> Bool
Signature -> Signature -> Ordering
Signature -> Signature -> Signature
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Signature -> Signature -> Ordering
compare :: Signature -> Signature -> Ordering
$c< :: Signature -> Signature -> Bool
< :: Signature -> Signature -> Bool
$c<= :: Signature -> Signature -> Bool
<= :: Signature -> Signature -> Bool
$c> :: Signature -> Signature -> Bool
> :: Signature -> Signature -> Bool
$c>= :: Signature -> Signature -> Bool
>= :: Signature -> Signature -> Bool
$cmax :: Signature -> Signature -> Signature
max :: Signature -> Signature -> Signature
$cmin :: Signature -> Signature -> Signature
min :: Signature -> Signature -> Signature
Ord, Int -> Signature -> ShowS
[Signature] -> ShowS
Signature -> String
(Int -> Signature -> ShowS)
-> (Signature -> String)
-> ([Signature] -> ShowS)
-> Show Signature
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Signature -> ShowS
showsPrec :: Int -> Signature -> ShowS
$cshow :: Signature -> String
show :: Signature -> String
$cshowList :: [Signature] -> ShowS
showList :: [Signature] -> ShowS
Show, (forall x. Signature -> Rep Signature x)
-> (forall x. Rep Signature x -> Signature) -> Generic Signature
forall x. Rep Signature x -> Signature
forall x. Signature -> Rep Signature x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Signature -> Rep Signature x
from :: forall x. Signature -> Rep Signature x
$cto :: forall x. Rep Signature x -> Signature
to :: forall x. Rep Signature x -> Signature
Generic)

instance NFData Signature

-- | Construct a 'Signature' from a 64-byte 'BS.ByteString'.
--
-- Returns 'Nothing' if the input is not exactly 64 bytes.
signature :: BS.ByteString -> Maybe Signature
signature :: ByteString -> Maybe Signature
signature !ByteString
bs
  | ByteString -> Int
BS.length ByteString
bs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
64 = Signature -> Maybe Signature
forall a. a -> Maybe a
Just (ByteString -> Signature
Signature ByteString
bs)
  | Bool
otherwise          = Maybe Signature
forall a. Maybe a
Nothing
{-# INLINE signature #-}

-- | Extract the raw bytes from a 'Signature'.
unSignature :: Signature -> BS.ByteString
unSignature :: Signature -> ByteString
unSignature (Signature ByteString
bs) = ByteString
bs
{-# INLINE unSignature #-}

-- | A 33-byte compressed secp256k1 public key.
newtype Point = Point BS.ByteString
  deriving stock (Point -> Point -> Bool
(Point -> Point -> Bool) -> (Point -> Point -> Bool) -> Eq Point
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Point -> Point -> Bool
== :: Point -> Point -> Bool
$c/= :: Point -> Point -> Bool
/= :: Point -> Point -> Bool
Eq, Eq Point
Eq Point =>
(Point -> Point -> Ordering)
-> (Point -> Point -> Bool)
-> (Point -> Point -> Bool)
-> (Point -> Point -> Bool)
-> (Point -> Point -> Bool)
-> (Point -> Point -> Point)
-> (Point -> Point -> Point)
-> Ord Point
Point -> Point -> Bool
Point -> Point -> Ordering
Point -> Point -> Point
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Point -> Point -> Ordering
compare :: Point -> Point -> Ordering
$c< :: Point -> Point -> Bool
< :: Point -> Point -> Bool
$c<= :: Point -> Point -> Bool
<= :: Point -> Point -> Bool
$c> :: Point -> Point -> Bool
> :: Point -> Point -> Bool
$c>= :: Point -> Point -> Bool
>= :: Point -> Point -> Bool
$cmax :: Point -> Point -> Point
max :: Point -> Point -> Point
$cmin :: Point -> Point -> Point
min :: Point -> Point -> Point
Ord, Int -> Point -> ShowS
[Point] -> ShowS
Point -> String
(Int -> Point -> ShowS)
-> (Point -> String) -> ([Point] -> ShowS) -> Show Point
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Point -> ShowS
showsPrec :: Int -> Point -> ShowS
$cshow :: Point -> String
show :: Point -> String
$cshowList :: [Point] -> ShowS
showList :: [Point] -> ShowS
Show, (forall x. Point -> Rep Point x)
-> (forall x. Rep Point x -> Point) -> Generic Point
forall x. Rep Point x -> Point
forall x. Point -> Rep Point x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Point -> Rep Point x
from :: forall x. Point -> Rep Point x
$cto :: forall x. Rep Point x -> Point
to :: forall x. Rep Point x -> Point
Generic)

instance NFData Point

-- | Construct a 'Point' from a 33-byte 'BS.ByteString'.
--
-- Returns 'Nothing' if the input is not exactly 33 bytes.
point :: BS.ByteString -> Maybe Point
point :: ByteString -> Maybe Point
point !ByteString
bs
  | ByteString -> Int
BS.length ByteString
bs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
33 = Point -> Maybe Point
forall a. a -> Maybe a
Just (ByteString -> Point
Point ByteString
bs)
  | Bool
otherwise          = Maybe Point
forall a. Maybe a
Nothing
{-# INLINE point #-}

-- | Extract the raw bytes from a 'Point'.
unPoint :: Point -> BS.ByteString
unPoint :: Point -> ByteString
unPoint (Point ByteString
bs) = ByteString
bs
{-# INLINE unPoint #-}

-- Payment types --------------------------------------------------------------

-- | A 32-byte SHA256 payment hash.
newtype PaymentHash = PaymentHash BS.ByteString
  deriving stock (PaymentHash -> PaymentHash -> Bool
(PaymentHash -> PaymentHash -> Bool)
-> (PaymentHash -> PaymentHash -> Bool) -> Eq PaymentHash
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PaymentHash -> PaymentHash -> Bool
== :: PaymentHash -> PaymentHash -> Bool
$c/= :: PaymentHash -> PaymentHash -> Bool
/= :: PaymentHash -> PaymentHash -> Bool
Eq, Eq PaymentHash
Eq PaymentHash =>
(PaymentHash -> PaymentHash -> Ordering)
-> (PaymentHash -> PaymentHash -> Bool)
-> (PaymentHash -> PaymentHash -> Bool)
-> (PaymentHash -> PaymentHash -> Bool)
-> (PaymentHash -> PaymentHash -> Bool)
-> (PaymentHash -> PaymentHash -> PaymentHash)
-> (PaymentHash -> PaymentHash -> PaymentHash)
-> Ord PaymentHash
PaymentHash -> PaymentHash -> Bool
PaymentHash -> PaymentHash -> Ordering
PaymentHash -> PaymentHash -> PaymentHash
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: PaymentHash -> PaymentHash -> Ordering
compare :: PaymentHash -> PaymentHash -> Ordering
$c< :: PaymentHash -> PaymentHash -> Bool
< :: PaymentHash -> PaymentHash -> Bool
$c<= :: PaymentHash -> PaymentHash -> Bool
<= :: PaymentHash -> PaymentHash -> Bool
$c> :: PaymentHash -> PaymentHash -> Bool
> :: PaymentHash -> PaymentHash -> Bool
$c>= :: PaymentHash -> PaymentHash -> Bool
>= :: PaymentHash -> PaymentHash -> Bool
$cmax :: PaymentHash -> PaymentHash -> PaymentHash
max :: PaymentHash -> PaymentHash -> PaymentHash
$cmin :: PaymentHash -> PaymentHash -> PaymentHash
min :: PaymentHash -> PaymentHash -> PaymentHash
Ord, Int -> PaymentHash -> ShowS
[PaymentHash] -> ShowS
PaymentHash -> String
(Int -> PaymentHash -> ShowS)
-> (PaymentHash -> String)
-> ([PaymentHash] -> ShowS)
-> Show PaymentHash
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PaymentHash -> ShowS
showsPrec :: Int -> PaymentHash -> ShowS
$cshow :: PaymentHash -> String
show :: PaymentHash -> String
$cshowList :: [PaymentHash] -> ShowS
showList :: [PaymentHash] -> ShowS
Show, (forall x. PaymentHash -> Rep PaymentHash x)
-> (forall x. Rep PaymentHash x -> PaymentHash)
-> Generic PaymentHash
forall x. Rep PaymentHash x -> PaymentHash
forall x. PaymentHash -> Rep PaymentHash x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. PaymentHash -> Rep PaymentHash x
from :: forall x. PaymentHash -> Rep PaymentHash x
$cto :: forall x. Rep PaymentHash x -> PaymentHash
to :: forall x. Rep PaymentHash x -> PaymentHash
Generic)

instance NFData PaymentHash

-- | Construct a 'PaymentHash' from a 32-byte 'BS.ByteString'.
--
-- Returns 'Nothing' if the input is not exactly 32 bytes.
paymentHash :: BS.ByteString -> Maybe PaymentHash
paymentHash :: ByteString -> Maybe PaymentHash
paymentHash !ByteString
bs
  | ByteString -> Int
BS.length ByteString
bs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
32 = PaymentHash -> Maybe PaymentHash
forall a. a -> Maybe a
Just (ByteString -> PaymentHash
PaymentHash ByteString
bs)
  | Bool
otherwise          = Maybe PaymentHash
forall a. Maybe a
Nothing
{-# INLINE paymentHash #-}

-- | Extract the raw bytes from a 'PaymentHash'.
unPaymentHash :: PaymentHash -> BS.ByteString
unPaymentHash :: PaymentHash -> ByteString
unPaymentHash (PaymentHash ByteString
bs) = ByteString
bs
{-# INLINE unPaymentHash #-}

-- | A 32-byte payment preimage.
newtype PaymentPreimage = PaymentPreimage BS.ByteString
  deriving stock (PaymentPreimage -> PaymentPreimage -> Bool
(PaymentPreimage -> PaymentPreimage -> Bool)
-> (PaymentPreimage -> PaymentPreimage -> Bool)
-> Eq PaymentPreimage
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PaymentPreimage -> PaymentPreimage -> Bool
== :: PaymentPreimage -> PaymentPreimage -> Bool
$c/= :: PaymentPreimage -> PaymentPreimage -> Bool
/= :: PaymentPreimage -> PaymentPreimage -> Bool
Eq, Eq PaymentPreimage
Eq PaymentPreimage =>
(PaymentPreimage -> PaymentPreimage -> Ordering)
-> (PaymentPreimage -> PaymentPreimage -> Bool)
-> (PaymentPreimage -> PaymentPreimage -> Bool)
-> (PaymentPreimage -> PaymentPreimage -> Bool)
-> (PaymentPreimage -> PaymentPreimage -> Bool)
-> (PaymentPreimage -> PaymentPreimage -> PaymentPreimage)
-> (PaymentPreimage -> PaymentPreimage -> PaymentPreimage)
-> Ord PaymentPreimage
PaymentPreimage -> PaymentPreimage -> Bool
PaymentPreimage -> PaymentPreimage -> Ordering
PaymentPreimage -> PaymentPreimage -> PaymentPreimage
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: PaymentPreimage -> PaymentPreimage -> Ordering
compare :: PaymentPreimage -> PaymentPreimage -> Ordering
$c< :: PaymentPreimage -> PaymentPreimage -> Bool
< :: PaymentPreimage -> PaymentPreimage -> Bool
$c<= :: PaymentPreimage -> PaymentPreimage -> Bool
<= :: PaymentPreimage -> PaymentPreimage -> Bool
$c> :: PaymentPreimage -> PaymentPreimage -> Bool
> :: PaymentPreimage -> PaymentPreimage -> Bool
$c>= :: PaymentPreimage -> PaymentPreimage -> Bool
>= :: PaymentPreimage -> PaymentPreimage -> Bool
$cmax :: PaymentPreimage -> PaymentPreimage -> PaymentPreimage
max :: PaymentPreimage -> PaymentPreimage -> PaymentPreimage
$cmin :: PaymentPreimage -> PaymentPreimage -> PaymentPreimage
min :: PaymentPreimage -> PaymentPreimage -> PaymentPreimage
Ord, (forall x. PaymentPreimage -> Rep PaymentPreimage x)
-> (forall x. Rep PaymentPreimage x -> PaymentPreimage)
-> Generic PaymentPreimage
forall x. Rep PaymentPreimage x -> PaymentPreimage
forall x. PaymentPreimage -> Rep PaymentPreimage x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. PaymentPreimage -> Rep PaymentPreimage x
from :: forall x. PaymentPreimage -> Rep PaymentPreimage x
$cto :: forall x. Rep PaymentPreimage x -> PaymentPreimage
to :: forall x. Rep PaymentPreimage x -> PaymentPreimage
Generic)

instance NFData PaymentPreimage

instance Show PaymentPreimage where
  show :: PaymentPreimage -> String
show PaymentPreimage
_ = String
"PaymentPreimage <redacted>"

-- | Construct a 'PaymentPreimage' from a 32-byte 'BS.ByteString'.
--
-- Returns 'Nothing' if the input is not exactly 32 bytes.
paymentPreimage :: BS.ByteString -> Maybe PaymentPreimage
paymentPreimage :: ByteString -> Maybe PaymentPreimage
paymentPreimage !ByteString
bs
  | ByteString -> Int
BS.length ByteString
bs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
32 = PaymentPreimage -> Maybe PaymentPreimage
forall a. a -> Maybe a
Just (ByteString -> PaymentPreimage
PaymentPreimage ByteString
bs)
  | Bool
otherwise          = Maybe PaymentPreimage
forall a. Maybe a
Nothing
{-# INLINE paymentPreimage #-}

-- | Extract the raw bytes from a 'PaymentPreimage'.
unPaymentPreimage :: PaymentPreimage -> BS.ByteString
unPaymentPreimage :: PaymentPreimage -> ByteString
unPaymentPreimage (PaymentPreimage ByteString
bs) = ByteString
bs
{-# INLINE unPaymentPreimage #-}

-- Per-commitment secret ------------------------------------------------------

-- | A 32-byte per-commitment secret.
newtype PerCommitmentSecret = PerCommitmentSecret BS.ByteString
  deriving stock (PerCommitmentSecret -> PerCommitmentSecret -> Bool
(PerCommitmentSecret -> PerCommitmentSecret -> Bool)
-> (PerCommitmentSecret -> PerCommitmentSecret -> Bool)
-> Eq PerCommitmentSecret
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PerCommitmentSecret -> PerCommitmentSecret -> Bool
== :: PerCommitmentSecret -> PerCommitmentSecret -> Bool
$c/= :: PerCommitmentSecret -> PerCommitmentSecret -> Bool
/= :: PerCommitmentSecret -> PerCommitmentSecret -> Bool
Eq, Eq PerCommitmentSecret
Eq PerCommitmentSecret =>
(PerCommitmentSecret -> PerCommitmentSecret -> Ordering)
-> (PerCommitmentSecret -> PerCommitmentSecret -> Bool)
-> (PerCommitmentSecret -> PerCommitmentSecret -> Bool)
-> (PerCommitmentSecret -> PerCommitmentSecret -> Bool)
-> (PerCommitmentSecret -> PerCommitmentSecret -> Bool)
-> (PerCommitmentSecret
    -> PerCommitmentSecret -> PerCommitmentSecret)
-> (PerCommitmentSecret
    -> PerCommitmentSecret -> PerCommitmentSecret)
-> Ord PerCommitmentSecret
PerCommitmentSecret -> PerCommitmentSecret -> Bool
PerCommitmentSecret -> PerCommitmentSecret -> Ordering
PerCommitmentSecret -> PerCommitmentSecret -> PerCommitmentSecret
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: PerCommitmentSecret -> PerCommitmentSecret -> Ordering
compare :: PerCommitmentSecret -> PerCommitmentSecret -> Ordering
$c< :: PerCommitmentSecret -> PerCommitmentSecret -> Bool
< :: PerCommitmentSecret -> PerCommitmentSecret -> Bool
$c<= :: PerCommitmentSecret -> PerCommitmentSecret -> Bool
<= :: PerCommitmentSecret -> PerCommitmentSecret -> Bool
$c> :: PerCommitmentSecret -> PerCommitmentSecret -> Bool
> :: PerCommitmentSecret -> PerCommitmentSecret -> Bool
$c>= :: PerCommitmentSecret -> PerCommitmentSecret -> Bool
>= :: PerCommitmentSecret -> PerCommitmentSecret -> Bool
$cmax :: PerCommitmentSecret -> PerCommitmentSecret -> PerCommitmentSecret
max :: PerCommitmentSecret -> PerCommitmentSecret -> PerCommitmentSecret
$cmin :: PerCommitmentSecret -> PerCommitmentSecret -> PerCommitmentSecret
min :: PerCommitmentSecret -> PerCommitmentSecret -> PerCommitmentSecret
Ord, (forall x. PerCommitmentSecret -> Rep PerCommitmentSecret x)
-> (forall x. Rep PerCommitmentSecret x -> PerCommitmentSecret)
-> Generic PerCommitmentSecret
forall x. Rep PerCommitmentSecret x -> PerCommitmentSecret
forall x. PerCommitmentSecret -> Rep PerCommitmentSecret x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. PerCommitmentSecret -> Rep PerCommitmentSecret x
from :: forall x. PerCommitmentSecret -> Rep PerCommitmentSecret x
$cto :: forall x. Rep PerCommitmentSecret x -> PerCommitmentSecret
to :: forall x. Rep PerCommitmentSecret x -> PerCommitmentSecret
Generic)

instance NFData PerCommitmentSecret

instance Show PerCommitmentSecret where
  show :: PerCommitmentSecret -> String
show PerCommitmentSecret
_ = String
"PerCommitmentSecret <redacted>"

-- | Construct a 'PerCommitmentSecret' from a 32-byte
-- 'BS.ByteString'.
--
-- Returns 'Nothing' if the input is not exactly 32 bytes.
perCommitmentSecret :: BS.ByteString -> Maybe PerCommitmentSecret
perCommitmentSecret :: ByteString -> Maybe PerCommitmentSecret
perCommitmentSecret !ByteString
bs
  | ByteString -> Int
BS.length ByteString
bs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
32 = PerCommitmentSecret -> Maybe PerCommitmentSecret
forall a. a -> Maybe a
Just (ByteString -> PerCommitmentSecret
PerCommitmentSecret ByteString
bs)
  | Bool
otherwise          = Maybe PerCommitmentSecret
forall a. Maybe a
Nothing
{-# INLINE perCommitmentSecret #-}

-- | Extract the raw bytes from a 'PerCommitmentSecret'.
unPerCommitmentSecret :: PerCommitmentSecret -> BS.ByteString
unPerCommitmentSecret :: PerCommitmentSecret -> ByteString
unPerCommitmentSecret (PerCommitmentSecret ByteString
bs) = ByteString
bs
{-# INLINE unPerCommitmentSecret #-}

-- Short channel identifier ---------------------------------------------------

-- | A short channel identifier (8 bytes packed as 'Word64').
--
-- Encodes block height (3 bytes), transaction index (3 bytes),
-- and output index (2 bytes).
newtype ShortChannelId = ShortChannelId Word64
  deriving stock (ShortChannelId -> ShortChannelId -> Bool
(ShortChannelId -> ShortChannelId -> Bool)
-> (ShortChannelId -> ShortChannelId -> Bool) -> Eq ShortChannelId
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ShortChannelId -> ShortChannelId -> Bool
== :: ShortChannelId -> ShortChannelId -> Bool
$c/= :: ShortChannelId -> ShortChannelId -> Bool
/= :: ShortChannelId -> ShortChannelId -> Bool
Eq, Eq ShortChannelId
Eq ShortChannelId =>
(ShortChannelId -> ShortChannelId -> Ordering)
-> (ShortChannelId -> ShortChannelId -> Bool)
-> (ShortChannelId -> ShortChannelId -> Bool)
-> (ShortChannelId -> ShortChannelId -> Bool)
-> (ShortChannelId -> ShortChannelId -> Bool)
-> (ShortChannelId -> ShortChannelId -> ShortChannelId)
-> (ShortChannelId -> ShortChannelId -> ShortChannelId)
-> Ord ShortChannelId
ShortChannelId -> ShortChannelId -> Bool
ShortChannelId -> ShortChannelId -> Ordering
ShortChannelId -> ShortChannelId -> ShortChannelId
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: ShortChannelId -> ShortChannelId -> Ordering
compare :: ShortChannelId -> ShortChannelId -> Ordering
$c< :: ShortChannelId -> ShortChannelId -> Bool
< :: ShortChannelId -> ShortChannelId -> Bool
$c<= :: ShortChannelId -> ShortChannelId -> Bool
<= :: ShortChannelId -> ShortChannelId -> Bool
$c> :: ShortChannelId -> ShortChannelId -> Bool
> :: ShortChannelId -> ShortChannelId -> Bool
$c>= :: ShortChannelId -> ShortChannelId -> Bool
>= :: ShortChannelId -> ShortChannelId -> Bool
$cmax :: ShortChannelId -> ShortChannelId -> ShortChannelId
max :: ShortChannelId -> ShortChannelId -> ShortChannelId
$cmin :: ShortChannelId -> ShortChannelId -> ShortChannelId
min :: ShortChannelId -> ShortChannelId -> ShortChannelId
Ord, Int -> ShortChannelId -> ShowS
[ShortChannelId] -> ShowS
ShortChannelId -> String
(Int -> ShortChannelId -> ShowS)
-> (ShortChannelId -> String)
-> ([ShortChannelId] -> ShowS)
-> Show ShortChannelId
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ShortChannelId -> ShowS
showsPrec :: Int -> ShortChannelId -> ShowS
$cshow :: ShortChannelId -> String
show :: ShortChannelId -> String
$cshowList :: [ShortChannelId] -> ShowS
showList :: [ShortChannelId] -> ShowS
Show, (forall x. ShortChannelId -> Rep ShortChannelId x)
-> (forall x. Rep ShortChannelId x -> ShortChannelId)
-> Generic ShortChannelId
forall x. Rep ShortChannelId x -> ShortChannelId
forall x. ShortChannelId -> Rep ShortChannelId x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. ShortChannelId -> Rep ShortChannelId x
from :: forall x. ShortChannelId -> Rep ShortChannelId x
$cto :: forall x. Rep ShortChannelId x -> ShortChannelId
to :: forall x. Rep ShortChannelId x -> ShortChannelId
Generic)

instance NFData ShortChannelId

-- | Construct a 'ShortChannelId' from components.
--
-- Returns 'Nothing' if block height or tx index exceed 24 bits.
shortChannelId
  :: Word32  -- ^ Block height (24 bits max)
  -> Word32  -- ^ Transaction index (24 bits max)
  -> Word16  -- ^ Output index
  -> Maybe ShortChannelId
shortChannelId :: Word32 -> Word32 -> Word16 -> Maybe ShortChannelId
shortChannelId !Word32
blockHeight !Word32
txIndex !Word16
outputIndex
  | Word32
blockHeight Word32 -> Word32 -> Bool
forall a. Ord a => a -> a -> Bool
> Word32
0xFFFFFF = Maybe ShortChannelId
forall a. Maybe a
Nothing
  | Word32
txIndex Word32 -> Word32 -> Bool
forall a. Ord a => a -> a -> Bool
> Word32
0xFFFFFF     = Maybe ShortChannelId
forall a. Maybe a
Nothing
  | Bool
otherwise              = ShortChannelId -> Maybe ShortChannelId
forall a. a -> Maybe a
Just (ShortChannelId -> Maybe ShortChannelId)
-> ShortChannelId -> Maybe ShortChannelId
forall a b. (a -> b) -> a -> b
$! Word64 -> ShortChannelId
ShortChannelId Word64
w
  where
    !w :: Word64
w = (Word32 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
blockHeight Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftL` Int
40)
     Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. (Word32 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
txIndex Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftL` Int
16)
     Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word16 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word16
outputIndex
{-# INLINE shortChannelId #-}

-- | Extract the packed 'Word64' from a 'ShortChannelId'.
scidWord64 :: ShortChannelId -> Word64
scidWord64 :: ShortChannelId -> Word64
scidWord64 (ShortChannelId Word64
w) = Word64
w
{-# INLINE scidWord64 #-}

-- | Extract the block height from a 'ShortChannelId'.
scidBlockHeight :: ShortChannelId -> Word32
scidBlockHeight :: ShortChannelId -> Word32
scidBlockHeight (ShortChannelId !Word64
w) =
  Word64 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> Word32) -> Word64 -> Word32
forall a b. (a -> b) -> a -> b
$! (Word64
w Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
40) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.&. Word64
0xFFFFFF
{-# INLINE scidBlockHeight #-}

-- | Extract the transaction index from a 'ShortChannelId'.
scidTxIndex :: ShortChannelId -> Word32
scidTxIndex :: ShortChannelId -> Word32
scidTxIndex (ShortChannelId !Word64
w) =
  Word64 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> Word32) -> Word64 -> Word32
forall a b. (a -> b) -> a -> b
$! (Word64
w Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
16) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.&. Word64
0xFFFFFF
{-# INLINE scidTxIndex #-}

-- | Extract the output index from a 'ShortChannelId'.
scidOutputIndex :: ShortChannelId -> Word16
scidOutputIndex :: ShortChannelId -> Word16
scidOutputIndex (ShortChannelId !Word64
w) =
  Word64 -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> Word16) -> Word64 -> Word16
forall a b. (a -> b) -> a -> b
$! Word64
w Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.&. Word64
0xFFFF
{-# INLINE scidOutputIndex #-}

-- Amounts --------------------------------------------------------------------

-- | Amount in satoshis.
newtype Satoshi = Satoshi { Satoshi -> Word64
unSatoshi :: Word64 }
  deriving stock (Satoshi -> Satoshi -> Bool
(Satoshi -> Satoshi -> Bool)
-> (Satoshi -> Satoshi -> Bool) -> Eq Satoshi
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Satoshi -> Satoshi -> Bool
== :: Satoshi -> Satoshi -> Bool
$c/= :: Satoshi -> Satoshi -> Bool
/= :: Satoshi -> Satoshi -> Bool
Eq, Eq Satoshi
Eq Satoshi =>
(Satoshi -> Satoshi -> Ordering)
-> (Satoshi -> Satoshi -> Bool)
-> (Satoshi -> Satoshi -> Bool)
-> (Satoshi -> Satoshi -> Bool)
-> (Satoshi -> Satoshi -> Bool)
-> (Satoshi -> Satoshi -> Satoshi)
-> (Satoshi -> Satoshi -> Satoshi)
-> Ord Satoshi
Satoshi -> Satoshi -> Bool
Satoshi -> Satoshi -> Ordering
Satoshi -> Satoshi -> Satoshi
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Satoshi -> Satoshi -> Ordering
compare :: Satoshi -> Satoshi -> Ordering
$c< :: Satoshi -> Satoshi -> Bool
< :: Satoshi -> Satoshi -> Bool
$c<= :: Satoshi -> Satoshi -> Bool
<= :: Satoshi -> Satoshi -> Bool
$c> :: Satoshi -> Satoshi -> Bool
> :: Satoshi -> Satoshi -> Bool
$c>= :: Satoshi -> Satoshi -> Bool
>= :: Satoshi -> Satoshi -> Bool
$cmax :: Satoshi -> Satoshi -> Satoshi
max :: Satoshi -> Satoshi -> Satoshi
$cmin :: Satoshi -> Satoshi -> Satoshi
min :: Satoshi -> Satoshi -> Satoshi
Ord, Int -> Satoshi -> ShowS
[Satoshi] -> ShowS
Satoshi -> String
(Int -> Satoshi -> ShowS)
-> (Satoshi -> String) -> ([Satoshi] -> ShowS) -> Show Satoshi
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Satoshi -> ShowS
showsPrec :: Int -> Satoshi -> ShowS
$cshow :: Satoshi -> String
show :: Satoshi -> String
$cshowList :: [Satoshi] -> ShowS
showList :: [Satoshi] -> ShowS
Show, (forall x. Satoshi -> Rep Satoshi x)
-> (forall x. Rep Satoshi x -> Satoshi) -> Generic Satoshi
forall x. Rep Satoshi x -> Satoshi
forall x. Satoshi -> Rep Satoshi x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Satoshi -> Rep Satoshi x
from :: forall x. Satoshi -> Rep Satoshi x
$cto :: forall x. Rep Satoshi x -> Satoshi
to :: forall x. Rep Satoshi x -> Satoshi
Generic)
  deriving newtype (Satoshi -> ()
(Satoshi -> ()) -> NFData Satoshi
forall a. (a -> ()) -> NFData a
$crnf :: Satoshi -> ()
rnf :: Satoshi -> ()
NFData, Integer -> Satoshi
Satoshi -> Satoshi
Satoshi -> Satoshi -> Satoshi
(Satoshi -> Satoshi -> Satoshi)
-> (Satoshi -> Satoshi -> Satoshi)
-> (Satoshi -> Satoshi -> Satoshi)
-> (Satoshi -> Satoshi)
-> (Satoshi -> Satoshi)
-> (Satoshi -> Satoshi)
-> (Integer -> Satoshi)
-> Num Satoshi
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
$c+ :: Satoshi -> Satoshi -> Satoshi
+ :: Satoshi -> Satoshi -> Satoshi
$c- :: Satoshi -> Satoshi -> Satoshi
- :: Satoshi -> Satoshi -> Satoshi
$c* :: Satoshi -> Satoshi -> Satoshi
* :: Satoshi -> Satoshi -> Satoshi
$cnegate :: Satoshi -> Satoshi
negate :: Satoshi -> Satoshi
$cabs :: Satoshi -> Satoshi
abs :: Satoshi -> Satoshi
$csignum :: Satoshi -> Satoshi
signum :: Satoshi -> Satoshi
$cfromInteger :: Integer -> Satoshi
fromInteger :: Integer -> Satoshi
Num, Int -> Satoshi
Satoshi -> Int
Satoshi -> [Satoshi]
Satoshi -> Satoshi
Satoshi -> Satoshi -> [Satoshi]
Satoshi -> Satoshi -> Satoshi -> [Satoshi]
(Satoshi -> Satoshi)
-> (Satoshi -> Satoshi)
-> (Int -> Satoshi)
-> (Satoshi -> Int)
-> (Satoshi -> [Satoshi])
-> (Satoshi -> Satoshi -> [Satoshi])
-> (Satoshi -> Satoshi -> [Satoshi])
-> (Satoshi -> Satoshi -> Satoshi -> [Satoshi])
-> Enum Satoshi
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: Satoshi -> Satoshi
succ :: Satoshi -> Satoshi
$cpred :: Satoshi -> Satoshi
pred :: Satoshi -> Satoshi
$ctoEnum :: Int -> Satoshi
toEnum :: Int -> Satoshi
$cfromEnum :: Satoshi -> Int
fromEnum :: Satoshi -> Int
$cenumFrom :: Satoshi -> [Satoshi]
enumFrom :: Satoshi -> [Satoshi]
$cenumFromThen :: Satoshi -> Satoshi -> [Satoshi]
enumFromThen :: Satoshi -> Satoshi -> [Satoshi]
$cenumFromTo :: Satoshi -> Satoshi -> [Satoshi]
enumFromTo :: Satoshi -> Satoshi -> [Satoshi]
$cenumFromThenTo :: Satoshi -> Satoshi -> Satoshi -> [Satoshi]
enumFromThenTo :: Satoshi -> Satoshi -> Satoshi -> [Satoshi]
Enum, Num Satoshi
Ord Satoshi
(Num Satoshi, Ord Satoshi) => (Satoshi -> Rational) -> Real Satoshi
Satoshi -> Rational
forall a. (Num a, Ord a) => (a -> Rational) -> Real a
$ctoRational :: Satoshi -> Rational
toRational :: Satoshi -> Rational
Real, Enum Satoshi
Real Satoshi
(Real Satoshi, Enum Satoshi) =>
(Satoshi -> Satoshi -> Satoshi)
-> (Satoshi -> Satoshi -> Satoshi)
-> (Satoshi -> Satoshi -> Satoshi)
-> (Satoshi -> Satoshi -> Satoshi)
-> (Satoshi -> Satoshi -> (Satoshi, Satoshi))
-> (Satoshi -> Satoshi -> (Satoshi, Satoshi))
-> (Satoshi -> Integer)
-> Integral Satoshi
Satoshi -> Integer
Satoshi -> Satoshi -> (Satoshi, Satoshi)
Satoshi -> Satoshi -> Satoshi
forall a.
(Real a, Enum a) =>
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> (a, a))
-> (a -> a -> (a, a))
-> (a -> Integer)
-> Integral a
$cquot :: Satoshi -> Satoshi -> Satoshi
quot :: Satoshi -> Satoshi -> Satoshi
$crem :: Satoshi -> Satoshi -> Satoshi
rem :: Satoshi -> Satoshi -> Satoshi
$cdiv :: Satoshi -> Satoshi -> Satoshi
div :: Satoshi -> Satoshi -> Satoshi
$cmod :: Satoshi -> Satoshi -> Satoshi
mod :: Satoshi -> Satoshi -> Satoshi
$cquotRem :: Satoshi -> Satoshi -> (Satoshi, Satoshi)
quotRem :: Satoshi -> Satoshi -> (Satoshi, Satoshi)
$cdivMod :: Satoshi -> Satoshi -> (Satoshi, Satoshi)
divMod :: Satoshi -> Satoshi -> (Satoshi, Satoshi)
$ctoInteger :: Satoshi -> Integer
toInteger :: Satoshi -> Integer
Integral)

-- | Amount in millisatoshis.
newtype MilliSatoshi = MilliSatoshi
  { MilliSatoshi -> Word64
unMilliSatoshi :: Word64 }
  deriving stock (MilliSatoshi -> MilliSatoshi -> Bool
(MilliSatoshi -> MilliSatoshi -> Bool)
-> (MilliSatoshi -> MilliSatoshi -> Bool) -> Eq MilliSatoshi
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: MilliSatoshi -> MilliSatoshi -> Bool
== :: MilliSatoshi -> MilliSatoshi -> Bool
$c/= :: MilliSatoshi -> MilliSatoshi -> Bool
/= :: MilliSatoshi -> MilliSatoshi -> Bool
Eq, Eq MilliSatoshi
Eq MilliSatoshi =>
(MilliSatoshi -> MilliSatoshi -> Ordering)
-> (MilliSatoshi -> MilliSatoshi -> Bool)
-> (MilliSatoshi -> MilliSatoshi -> Bool)
-> (MilliSatoshi -> MilliSatoshi -> Bool)
-> (MilliSatoshi -> MilliSatoshi -> Bool)
-> (MilliSatoshi -> MilliSatoshi -> MilliSatoshi)
-> (MilliSatoshi -> MilliSatoshi -> MilliSatoshi)
-> Ord MilliSatoshi
MilliSatoshi -> MilliSatoshi -> Bool
MilliSatoshi -> MilliSatoshi -> Ordering
MilliSatoshi -> MilliSatoshi -> MilliSatoshi
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: MilliSatoshi -> MilliSatoshi -> Ordering
compare :: MilliSatoshi -> MilliSatoshi -> Ordering
$c< :: MilliSatoshi -> MilliSatoshi -> Bool
< :: MilliSatoshi -> MilliSatoshi -> Bool
$c<= :: MilliSatoshi -> MilliSatoshi -> Bool
<= :: MilliSatoshi -> MilliSatoshi -> Bool
$c> :: MilliSatoshi -> MilliSatoshi -> Bool
> :: MilliSatoshi -> MilliSatoshi -> Bool
$c>= :: MilliSatoshi -> MilliSatoshi -> Bool
>= :: MilliSatoshi -> MilliSatoshi -> Bool
$cmax :: MilliSatoshi -> MilliSatoshi -> MilliSatoshi
max :: MilliSatoshi -> MilliSatoshi -> MilliSatoshi
$cmin :: MilliSatoshi -> MilliSatoshi -> MilliSatoshi
min :: MilliSatoshi -> MilliSatoshi -> MilliSatoshi
Ord, Int -> MilliSatoshi -> ShowS
[MilliSatoshi] -> ShowS
MilliSatoshi -> String
(Int -> MilliSatoshi -> ShowS)
-> (MilliSatoshi -> String)
-> ([MilliSatoshi] -> ShowS)
-> Show MilliSatoshi
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> MilliSatoshi -> ShowS
showsPrec :: Int -> MilliSatoshi -> ShowS
$cshow :: MilliSatoshi -> String
show :: MilliSatoshi -> String
$cshowList :: [MilliSatoshi] -> ShowS
showList :: [MilliSatoshi] -> ShowS
Show, (forall x. MilliSatoshi -> Rep MilliSatoshi x)
-> (forall x. Rep MilliSatoshi x -> MilliSatoshi)
-> Generic MilliSatoshi
forall x. Rep MilliSatoshi x -> MilliSatoshi
forall x. MilliSatoshi -> Rep MilliSatoshi x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. MilliSatoshi -> Rep MilliSatoshi x
from :: forall x. MilliSatoshi -> Rep MilliSatoshi x
$cto :: forall x. Rep MilliSatoshi x -> MilliSatoshi
to :: forall x. Rep MilliSatoshi x -> MilliSatoshi
Generic)
  deriving newtype (MilliSatoshi -> ()
(MilliSatoshi -> ()) -> NFData MilliSatoshi
forall a. (a -> ()) -> NFData a
$crnf :: MilliSatoshi -> ()
rnf :: MilliSatoshi -> ()
NFData, Integer -> MilliSatoshi
MilliSatoshi -> MilliSatoshi
MilliSatoshi -> MilliSatoshi -> MilliSatoshi
(MilliSatoshi -> MilliSatoshi -> MilliSatoshi)
-> (MilliSatoshi -> MilliSatoshi -> MilliSatoshi)
-> (MilliSatoshi -> MilliSatoshi -> MilliSatoshi)
-> (MilliSatoshi -> MilliSatoshi)
-> (MilliSatoshi -> MilliSatoshi)
-> (MilliSatoshi -> MilliSatoshi)
-> (Integer -> MilliSatoshi)
-> Num MilliSatoshi
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
$c+ :: MilliSatoshi -> MilliSatoshi -> MilliSatoshi
+ :: MilliSatoshi -> MilliSatoshi -> MilliSatoshi
$c- :: MilliSatoshi -> MilliSatoshi -> MilliSatoshi
- :: MilliSatoshi -> MilliSatoshi -> MilliSatoshi
$c* :: MilliSatoshi -> MilliSatoshi -> MilliSatoshi
* :: MilliSatoshi -> MilliSatoshi -> MilliSatoshi
$cnegate :: MilliSatoshi -> MilliSatoshi
negate :: MilliSatoshi -> MilliSatoshi
$cabs :: MilliSatoshi -> MilliSatoshi
abs :: MilliSatoshi -> MilliSatoshi
$csignum :: MilliSatoshi -> MilliSatoshi
signum :: MilliSatoshi -> MilliSatoshi
$cfromInteger :: Integer -> MilliSatoshi
fromInteger :: Integer -> MilliSatoshi
Num, Int -> MilliSatoshi
MilliSatoshi -> Int
MilliSatoshi -> [MilliSatoshi]
MilliSatoshi -> MilliSatoshi
MilliSatoshi -> MilliSatoshi -> [MilliSatoshi]
MilliSatoshi -> MilliSatoshi -> MilliSatoshi -> [MilliSatoshi]
(MilliSatoshi -> MilliSatoshi)
-> (MilliSatoshi -> MilliSatoshi)
-> (Int -> MilliSatoshi)
-> (MilliSatoshi -> Int)
-> (MilliSatoshi -> [MilliSatoshi])
-> (MilliSatoshi -> MilliSatoshi -> [MilliSatoshi])
-> (MilliSatoshi -> MilliSatoshi -> [MilliSatoshi])
-> (MilliSatoshi -> MilliSatoshi -> MilliSatoshi -> [MilliSatoshi])
-> Enum MilliSatoshi
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: MilliSatoshi -> MilliSatoshi
succ :: MilliSatoshi -> MilliSatoshi
$cpred :: MilliSatoshi -> MilliSatoshi
pred :: MilliSatoshi -> MilliSatoshi
$ctoEnum :: Int -> MilliSatoshi
toEnum :: Int -> MilliSatoshi
$cfromEnum :: MilliSatoshi -> Int
fromEnum :: MilliSatoshi -> Int
$cenumFrom :: MilliSatoshi -> [MilliSatoshi]
enumFrom :: MilliSatoshi -> [MilliSatoshi]
$cenumFromThen :: MilliSatoshi -> MilliSatoshi -> [MilliSatoshi]
enumFromThen :: MilliSatoshi -> MilliSatoshi -> [MilliSatoshi]
$cenumFromTo :: MilliSatoshi -> MilliSatoshi -> [MilliSatoshi]
enumFromTo :: MilliSatoshi -> MilliSatoshi -> [MilliSatoshi]
$cenumFromThenTo :: MilliSatoshi -> MilliSatoshi -> MilliSatoshi -> [MilliSatoshi]
enumFromThenTo :: MilliSatoshi -> MilliSatoshi -> MilliSatoshi -> [MilliSatoshi]
Enum, Num MilliSatoshi
Ord MilliSatoshi
(Num MilliSatoshi, Ord MilliSatoshi) =>
(MilliSatoshi -> Rational) -> Real MilliSatoshi
MilliSatoshi -> Rational
forall a. (Num a, Ord a) => (a -> Rational) -> Real a
$ctoRational :: MilliSatoshi -> Rational
toRational :: MilliSatoshi -> Rational
Real, Enum MilliSatoshi
Real MilliSatoshi
(Real MilliSatoshi, Enum MilliSatoshi) =>
(MilliSatoshi -> MilliSatoshi -> MilliSatoshi)
-> (MilliSatoshi -> MilliSatoshi -> MilliSatoshi)
-> (MilliSatoshi -> MilliSatoshi -> MilliSatoshi)
-> (MilliSatoshi -> MilliSatoshi -> MilliSatoshi)
-> (MilliSatoshi -> MilliSatoshi -> (MilliSatoshi, MilliSatoshi))
-> (MilliSatoshi -> MilliSatoshi -> (MilliSatoshi, MilliSatoshi))
-> (MilliSatoshi -> Integer)
-> Integral MilliSatoshi
MilliSatoshi -> Integer
MilliSatoshi -> MilliSatoshi -> (MilliSatoshi, MilliSatoshi)
MilliSatoshi -> MilliSatoshi -> MilliSatoshi
forall a.
(Real a, Enum a) =>
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> (a, a))
-> (a -> a -> (a, a))
-> (a -> Integer)
-> Integral a
$cquot :: MilliSatoshi -> MilliSatoshi -> MilliSatoshi
quot :: MilliSatoshi -> MilliSatoshi -> MilliSatoshi
$crem :: MilliSatoshi -> MilliSatoshi -> MilliSatoshi
rem :: MilliSatoshi -> MilliSatoshi -> MilliSatoshi
$cdiv :: MilliSatoshi -> MilliSatoshi -> MilliSatoshi
div :: MilliSatoshi -> MilliSatoshi -> MilliSatoshi
$cmod :: MilliSatoshi -> MilliSatoshi -> MilliSatoshi
mod :: MilliSatoshi -> MilliSatoshi -> MilliSatoshi
$cquotRem :: MilliSatoshi -> MilliSatoshi -> (MilliSatoshi, MilliSatoshi)
quotRem :: MilliSatoshi -> MilliSatoshi -> (MilliSatoshi, MilliSatoshi)
$cdivMod :: MilliSatoshi -> MilliSatoshi -> (MilliSatoshi, MilliSatoshi)
divMod :: MilliSatoshi -> MilliSatoshi -> (MilliSatoshi, MilliSatoshi)
$ctoInteger :: MilliSatoshi -> Integer
toInteger :: MilliSatoshi -> Integer
Integral)

-- | Convert 'Satoshi' to 'MilliSatoshi'.
satToMsat :: Satoshi -> MilliSatoshi
satToMsat :: Satoshi -> MilliSatoshi
satToMsat (Satoshi !Word64
s) = Word64 -> MilliSatoshi
MilliSatoshi (Word64 -> MilliSatoshi) -> Word64 -> MilliSatoshi
forall a b. (a -> b) -> a -> b
$! Word64
s Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
1000
{-# INLINE satToMsat #-}

-- | Convert 'MilliSatoshi' to 'Satoshi' (rounds down).
msatToSat :: MilliSatoshi -> Satoshi
msatToSat :: MilliSatoshi -> Satoshi
msatToSat (MilliSatoshi !Word64
m) = Word64 -> Satoshi
Satoshi (Word64 -> Satoshi) -> Word64 -> Satoshi
forall a b. (a -> b) -> a -> b
$! Word64
m Word64 -> Word64 -> Word64
forall a. Integral a => a -> a -> a
`div` Word64
1000
{-# INLINE msatToSat #-}

-- Unsigned integer encoding ---------------------------------------------------

-- | Encode a 16-bit unsigned integer (big-endian).
--
-- >>> encodeU16 0x0102
-- "\SOH\STX"
encodeU16 :: Word16 -> BS.ByteString
encodeU16 :: Word16 -> ByteString
encodeU16 = LazyByteString -> ByteString
BSL.toStrict (LazyByteString -> ByteString)
-> (Word16 -> LazyByteString) -> Word16 -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> LazyByteString
BSB.toLazyByteString (Builder -> LazyByteString)
-> (Word16 -> Builder) -> Word16 -> LazyByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word16 -> Builder
BSB.word16BE
{-# INLINE encodeU16 #-}

-- | Encode a 32-bit unsigned integer (big-endian).
--
-- >>> encodeU32 0x01020304
-- "\SOH\STX\ETX\EOT"
encodeU32 :: Word32 -> BS.ByteString
encodeU32 :: Word32 -> ByteString
encodeU32 = LazyByteString -> ByteString
BSL.toStrict (LazyByteString -> ByteString)
-> (Word32 -> LazyByteString) -> Word32 -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> LazyByteString
BSB.toLazyByteString (Builder -> LazyByteString)
-> (Word32 -> Builder) -> Word32 -> LazyByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word32 -> Builder
BSB.word32BE
{-# INLINE encodeU32 #-}

-- | Encode a 64-bit unsigned integer (big-endian).
--
-- >>> encodeU64 0x0102030405060708
-- "\SOH\STX\ETX\EOT\ENQ\ACK\a\b"
encodeU64 :: Word64 -> BS.ByteString
encodeU64 :: Word64 -> ByteString
encodeU64 = LazyByteString -> ByteString
BSL.toStrict (LazyByteString -> ByteString)
-> (Word64 -> LazyByteString) -> Word64 -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> LazyByteString
BSB.toLazyByteString (Builder -> LazyByteString)
-> (Word64 -> Builder) -> Word64 -> LazyByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word64 -> Builder
BSB.word64BE
{-# INLINE encodeU64 #-}

-- Signed integer encoding -----------------------------------------------------

-- | Encode an 8-bit signed integer.
--
-- >>> encodeS8 42
-- "*"
-- >>> encodeS8 (-42)
-- "\214"
encodeS8 :: Int8 -> BS.ByteString
encodeS8 :: Int8 -> ByteString
encodeS8 = Word8 -> ByteString
BS.singleton (Word8 -> ByteString) -> (Int8 -> Word8) -> Int8 -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int8 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral
{-# INLINE encodeS8 #-}

-- | Encode a 16-bit signed integer (big-endian two's complement).
--
-- >>> encodeS16 0x0102
-- "\SOH\STX"
-- >>> encodeS16 (-1)
-- "\255\255"
encodeS16 :: Int16 -> BS.ByteString
encodeS16 :: Int16 -> ByteString
encodeS16 = LazyByteString -> ByteString
BSL.toStrict (LazyByteString -> ByteString)
-> (Int16 -> LazyByteString) -> Int16 -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> LazyByteString
BSB.toLazyByteString (Builder -> LazyByteString)
-> (Int16 -> Builder) -> Int16 -> LazyByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int16 -> Builder
BSB.int16BE
{-# INLINE encodeS16 #-}

-- | Encode a 32-bit signed integer (big-endian two's complement).
--
-- >>> encodeS32 0x01020304
-- "\SOH\STX\ETX\EOT"
-- >>> encodeS32 (-1)
-- "\255\255\255\255"
encodeS32 :: Int32 -> BS.ByteString
encodeS32 :: Int32 -> ByteString
encodeS32 = LazyByteString -> ByteString
BSL.toStrict (LazyByteString -> ByteString)
-> (Int32 -> LazyByteString) -> Int32 -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> LazyByteString
BSB.toLazyByteString (Builder -> LazyByteString)
-> (Int32 -> Builder) -> Int32 -> LazyByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int32 -> Builder
BSB.int32BE
{-# INLINE encodeS32 #-}

-- | Encode a 64-bit signed integer (big-endian two's complement).
--
-- >>> encodeS64 0x0102030405060708
-- "\SOH\STX\ETX\EOT\ENQ\ACK\a\b"
-- >>> encodeS64 (-1)
-- "\255\255\255\255\255\255\255\255"
encodeS64 :: Int64 -> BS.ByteString
encodeS64 :: Int64 -> ByteString
encodeS64 = LazyByteString -> ByteString
BSL.toStrict (LazyByteString -> ByteString)
-> (Int64 -> LazyByteString) -> Int64 -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> LazyByteString
BSB.toLazyByteString (Builder -> LazyByteString)
-> (Int64 -> Builder) -> Int64 -> LazyByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int64 -> Builder
BSB.int64BE
{-# INLINE encodeS64 #-}

-- Truncated unsigned integer encoding -----------------------------------------

-- | Encode a truncated 16-bit unsigned integer (0-2 bytes).
--
-- Leading zeros are omitted per BOLT #1. Zero encodes to empty.
--
-- >>> encodeTu16 0
-- ""
-- >>> encodeTu16 1
-- "\SOH"
-- >>> encodeTu16 256
-- "\SOH\NUL"
encodeTu16 :: Word16 -> BS.ByteString
encodeTu16 :: Word16 -> ByteString
encodeTu16 Word16
0 = ByteString
BS.empty
encodeTu16 !Word16
x
  | Word16
x Word16 -> Word16 -> Bool
forall a. Ord a => a -> a -> Bool
< Word16
0x100 = Word8 -> ByteString
BS.singleton (Word16 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word16
x)
  | Bool
otherwise = Word16 -> ByteString
encodeU16 Word16
x
{-# INLINE encodeTu16 #-}

-- | Encode a truncated 32-bit unsigned integer (0-4 bytes).
--
-- Leading zeros are omitted per BOLT #1. Zero encodes to empty.
--
-- >>> encodeTu32 0
-- ""
-- >>> encodeTu32 1
-- "\SOH"
-- >>> encodeTu32 0x010000
-- "\SOH\NUL\NUL"
encodeTu32 :: Word32 -> BS.ByteString
encodeTu32 :: Word32 -> ByteString
encodeTu32 Word32
0 = ByteString
BS.empty
encodeTu32 !Word32
x
  | Word32
x Word32 -> Word32 -> Bool
forall a. Ord a => a -> a -> Bool
< Word32
0x100       = Word8 -> ByteString
BS.singleton (Word32 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
x)
  | Word32
x Word32 -> Word32 -> Bool
forall a. Ord a => a -> a -> Bool
< Word32
0x10000     = Word16 -> ByteString
encodeU16 (Word32 -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
x)
  | Word32
x Word32 -> Word32 -> Bool
forall a. Ord a => a -> a -> Bool
< Word32
0x1000000   = [Word8] -> ByteString
BS.pack [ Word32 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32
x Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
16)
                              , Word32 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32
x Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
8)
                              , Word32 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
x
                              ]
  | Bool
otherwise       = Word32 -> ByteString
encodeU32 Word32
x
{-# INLINE encodeTu32 #-}

-- | Encode a truncated 64-bit unsigned integer (0-8 bytes).
--
-- Leading zeros are omitted per BOLT #1. Zero encodes to empty.
--
-- >>> encodeTu64 0
-- ""
-- >>> encodeTu64 1
-- "\SOH"
-- >>> encodeTu64 0x0100000000
-- "\SOH\NUL\NUL\NUL\NUL"
encodeTu64 :: Word64 -> BS.ByteString
encodeTu64 :: Word64 -> ByteString
encodeTu64 Word64
0 = ByteString
BS.empty
encodeTu64 !Word64
x
  | Word64
x Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
< Word64
0x100             = Word8 -> ByteString
BS.singleton (Word64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
x)
  | Word64
x Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
< Word64
0x10000           = Word16 -> ByteString
encodeU16 (Word64 -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
x)
  | Word64
x Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
< Word64
0x1000000         = [Word8] -> ByteString
BS.pack [ Word64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
x Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
16)
                                    , Word64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
x Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
8)
                                    , Word64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
x
                                    ]
  | Word64
x Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
< Word64
0x100000000       = Word32 -> ByteString
encodeU32 (Word64 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
x)
  | Word64
x Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
< Word64
0x10000000000     = [Word8] -> ByteString
BS.pack [ Word64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
x Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
32)
                                    , Word64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
x Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
24)
                                    , Word64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
x Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
16)
                                    , Word64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
x Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
8)
                                    , Word64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
x
                                    ]
  | Word64
x Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
< Word64
0x1000000000000   = [Word8] -> ByteString
BS.pack [ Word64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
x Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
40)
                                    , Word64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
x Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
32)
                                    , Word64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
x Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
24)
                                    , Word64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
x Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
16)
                                    , Word64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
x Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
8)
                                    , Word64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
x
                                    ]
  | Word64
x Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
< Word64
0x100000000000000 = [Word8] -> ByteString
BS.pack [ Word64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
x Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
48)
                                    , Word64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
x Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
40)
                                    , Word64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
x Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
32)
                                    , Word64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
x Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
24)
                                    , Word64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
x Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
16)
                                    , Word64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
x Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
8)
                                    , Word64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
x
                                    ]
  | Bool
otherwise             = Word64 -> ByteString
encodeU64 Word64
x
{-# INLINE encodeTu64 #-}

-- Minimal signed integer encoding ---------------------------------------------

-- | Encode a signed 64-bit integer using minimal bytes.
--
-- Uses the smallest number of bytes that can represent the value
-- in two's complement. Per BOLT #1 Appendix D test vectors.
--
-- >>> encodeMinSigned 0
-- "\NUL"
-- >>> encodeMinSigned 127
-- "\DEL"
-- >>> encodeMinSigned 128
-- "\NUL\128"
-- >>> encodeMinSigned (-1)
-- "\255"
-- >>> encodeMinSigned (-128)
-- "\128"
-- >>> encodeMinSigned (-129)
-- "\255\DEL"
encodeMinSigned :: Int64 -> BS.ByteString
encodeMinSigned :: Int64 -> ByteString
encodeMinSigned !Int64
x
  | Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
>= -Int64
128 Bool -> Bool -> Bool
&& Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Int64
127 =
      -- Fits in 1 byte
      Word8 -> ByteString
BS.singleton (Int64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
x)
  | Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
>= -Int64
32768 Bool -> Bool -> Bool
&& Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Int64
32767 =
      -- Fits in 2 bytes
      Int16 -> ByteString
encodeS16 (Int64 -> Int16
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
x)
  | Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
>= -Int64
2147483648 Bool -> Bool -> Bool
&& Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Int64
2147483647 =
      -- Fits in 4 bytes
      Int32 -> ByteString
encodeS32 (Int64 -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
x)
  | Bool
otherwise =
      -- Need 8 bytes
      Int64 -> ByteString
encodeS64 Int64
x
{-# INLINE encodeMinSigned #-}

-- BigSize encoding ------------------------------------------------------------

-- | Encode a BigSize value (variable-length unsigned integer).
--
-- >>> encodeBigSize 0
-- "\NUL"
-- >>> encodeBigSize 252
-- "\252"
-- >>> encodeBigSize 253
-- "\253\NUL\253"
-- >>> encodeBigSize 65536
-- "\254\NUL\SOH\NUL\NUL"
encodeBigSize :: Word64 -> BS.ByteString
encodeBigSize :: Word64 -> ByteString
encodeBigSize !Word64
x
  | Word64
x Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
< Word64
0xfd = Word8 -> ByteString
BS.singleton (Word64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
x)
  | Word64
x Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
< Word64
0x10000 = Word8 -> ByteString -> ByteString
BS.cons Word8
0xfd (Word16 -> ByteString
encodeU16 (Word64 -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
x))
  | Word64
x Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
< Word64
0x100000000 = Word8 -> ByteString -> ByteString
BS.cons Word8
0xfe (Word32 -> ByteString
encodeU32 (Word64 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
x))
  | Bool
otherwise = Word8 -> ByteString -> ByteString
BS.cons Word8
0xff (Word64 -> ByteString
encodeU64 Word64
x)
{-# INLINE encodeBigSize #-}

-- Length encoding -------------------------------------------------------------

-- | Encode a length as u16, checking bounds.
--
-- Returns Nothing if the length exceeds 65535.
encodeLength :: BS.ByteString -> Maybe BS.ByteString
encodeLength :: ByteString -> Maybe ByteString
encodeLength !ByteString
bs
  | ByteString -> Int
BS.length ByteString
bs Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
65535 = Maybe ByteString
forall a. Maybe a
Nothing
  | Bool
otherwise = ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just (Word16 -> ByteString
encodeU16 (Int -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString -> Int
BS.length ByteString
bs)))
{-# INLINE encodeLength #-}

-- Unsigned integer decoding ---------------------------------------------------

-- | Decode a 16-bit unsigned integer (big-endian).
decodeU16 :: BS.ByteString -> Maybe (Word16, BS.ByteString)
decodeU16 :: ByteString -> Maybe (Word16, ByteString)
decodeU16 !ByteString
bs
  | ByteString -> Int
BS.length ByteString
bs Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
2 = Maybe (Word16, ByteString)
forall a. Maybe a
Nothing
  | Bool
otherwise =
      let !b0 :: Word16
b0 = Word8 -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral (HasCallStack => ByteString -> Int -> Word8
ByteString -> Int -> Word8
BS.index ByteString
bs Int
0)
          !b1 :: Word16
b1 = Word8 -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral (HasCallStack => ByteString -> Int -> Word8
ByteString -> Int -> Word8
BS.index ByteString
bs Int
1)
          !val :: Word16
val = (Word16
b0 Word16 -> Int -> Word16
forall a. Bits a => a -> Int -> a
`unsafeShiftL` Int
8) Word16 -> Word16 -> Word16
forall a. Bits a => a -> a -> a
.|. Word16
b1
      in  (Word16, ByteString) -> Maybe (Word16, ByteString)
forall a. a -> Maybe a
Just (Word16
val, Int -> ByteString -> ByteString
BS.drop Int
2 ByteString
bs)
{-# INLINE decodeU16 #-}

-- | Decode a 32-bit unsigned integer (big-endian).
decodeU32 :: BS.ByteString -> Maybe (Word32, BS.ByteString)
decodeU32 :: ByteString -> Maybe (Word32, ByteString)
decodeU32 !ByteString
bs
  | ByteString -> Int
BS.length ByteString
bs Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
4 = Maybe (Word32, ByteString)
forall a. Maybe a
Nothing
  | Bool
otherwise =
      let !b0 :: Word32
b0 = Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (HasCallStack => ByteString -> Int -> Word8
ByteString -> Int -> Word8
BS.index ByteString
bs Int
0)
          !b1 :: Word32
b1 = Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (HasCallStack => ByteString -> Int -> Word8
ByteString -> Int -> Word8
BS.index ByteString
bs Int
1)
          !b2 :: Word32
b2 = Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (HasCallStack => ByteString -> Int -> Word8
ByteString -> Int -> Word8
BS.index ByteString
bs Int
2)
          !b3 :: Word32
b3 = Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (HasCallStack => ByteString -> Int -> Word8
ByteString -> Int -> Word8
BS.index ByteString
bs Int
3)
          !val :: Word32
val = (Word32
b0 Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`unsafeShiftL` Int
24) Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. (Word32
b1 Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`unsafeShiftL` Int
16)
              Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. (Word32
b2 Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`unsafeShiftL` Int
8) Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. Word32
b3
      in  (Word32, ByteString) -> Maybe (Word32, ByteString)
forall a. a -> Maybe a
Just (Word32
val, Int -> ByteString -> ByteString
BS.drop Int
4 ByteString
bs)
{-# INLINE decodeU32 #-}

-- | Decode a 64-bit unsigned integer (big-endian).
decodeU64 :: BS.ByteString -> Maybe (Word64, BS.ByteString)
decodeU64 :: ByteString -> Maybe (Word64, ByteString)
decodeU64 !ByteString
bs
  | ByteString -> Int
BS.length ByteString
bs Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
8 = Maybe (Word64, ByteString)
forall a. Maybe a
Nothing
  | Bool
otherwise =
      let !b0 :: Word64
b0 = Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (HasCallStack => ByteString -> Int -> Word8
ByteString -> Int -> Word8
BS.index ByteString
bs Int
0)
          !b1 :: Word64
b1 = Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (HasCallStack => ByteString -> Int -> Word8
ByteString -> Int -> Word8
BS.index ByteString
bs Int
1)
          !b2 :: Word64
b2 = Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (HasCallStack => ByteString -> Int -> Word8
ByteString -> Int -> Word8
BS.index ByteString
bs Int
2)
          !b3 :: Word64
b3 = Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (HasCallStack => ByteString -> Int -> Word8
ByteString -> Int -> Word8
BS.index ByteString
bs Int
3)
          !b4 :: Word64
b4 = Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (HasCallStack => ByteString -> Int -> Word8
ByteString -> Int -> Word8
BS.index ByteString
bs Int
4)
          !b5 :: Word64
b5 = Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (HasCallStack => ByteString -> Int -> Word8
ByteString -> Int -> Word8
BS.index ByteString
bs Int
5)
          !b6 :: Word64
b6 = Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (HasCallStack => ByteString -> Int -> Word8
ByteString -> Int -> Word8
BS.index ByteString
bs Int
6)
          !b7 :: Word64
b7 = Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (HasCallStack => ByteString -> Int -> Word8
ByteString -> Int -> Word8
BS.index ByteString
bs Int
7)
          !val :: Word64
val = (Word64
b0 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftL` Int
56) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. (Word64
b1 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftL` Int
48)
              Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. (Word64
b2 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftL` Int
40) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. (Word64
b3 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftL` Int
32)
              Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. (Word64
b4 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftL` Int
24) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. (Word64
b5 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftL` Int
16)
              Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. (Word64
b6 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftL` Int
8) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word64
b7
      in  (Word64, ByteString) -> Maybe (Word64, ByteString)
forall a. a -> Maybe a
Just (Word64
val, Int -> ByteString -> ByteString
BS.drop Int
8 ByteString
bs)
{-# INLINE decodeU64 #-}

-- Signed integer decoding -----------------------------------------------------

-- | Decode an 8-bit signed integer.
decodeS8 :: BS.ByteString -> Maybe (Int8, BS.ByteString)
decodeS8 :: ByteString -> Maybe (Int8, ByteString)
decodeS8 !ByteString
bs
  | ByteString -> Bool
BS.null ByteString
bs = Maybe (Int8, ByteString)
forall a. Maybe a
Nothing
  | Bool
otherwise  = (Int8, ByteString) -> Maybe (Int8, ByteString)
forall a. a -> Maybe a
Just (Word8 -> Int8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (HasCallStack => ByteString -> Int -> Word8
ByteString -> Int -> Word8
BS.index ByteString
bs Int
0), Int -> ByteString -> ByteString
BS.drop Int
1 ByteString
bs)
{-# INLINE decodeS8 #-}

-- | Decode a 16-bit signed integer (big-endian two's complement).
decodeS16 :: BS.ByteString -> Maybe (Int16, BS.ByteString)
decodeS16 :: ByteString -> Maybe (Int16, ByteString)
decodeS16 !ByteString
bs = do
  (w, rest) <- ByteString -> Maybe (Word16, ByteString)
decodeU16 ByteString
bs
  Just (fromIntegral w, rest)
{-# INLINE decodeS16 #-}

-- | Decode a 32-bit signed integer (big-endian two's complement).
decodeS32 :: BS.ByteString -> Maybe (Int32, BS.ByteString)
decodeS32 :: ByteString -> Maybe (Int32, ByteString)
decodeS32 !ByteString
bs = do
  (w, rest) <- ByteString -> Maybe (Word32, ByteString)
decodeU32 ByteString
bs
  Just (fromIntegral w, rest)
{-# INLINE decodeS32 #-}

-- | Decode a 64-bit signed integer (big-endian two's complement).
decodeS64 :: BS.ByteString -> Maybe (Int64, BS.ByteString)
decodeS64 :: ByteString -> Maybe (Int64, ByteString)
decodeS64 !ByteString
bs = do
  (w, rest) <- ByteString -> Maybe (Word64, ByteString)
decodeU64 ByteString
bs
  Just (fromIntegral w, rest)
{-# INLINE decodeS64 #-}

-- Truncated unsigned integer decoding -----------------------------------------

-- | Decode a truncated 16-bit unsigned integer (0-2 bytes).
--
-- Returns Nothing if the encoding is non-minimal (has leading zeros).
decodeTu16 :: Int -> BS.ByteString -> Maybe (Word16, BS.ByteString)
decodeTu16 :: Int -> ByteString -> Maybe (Word16, ByteString)
decodeTu16 !Int
len !ByteString
bs
  | Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 Bool -> Bool -> Bool
|| Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
2 = Maybe (Word16, ByteString)
forall a. Maybe a
Nothing
  | ByteString -> Int
BS.length ByteString
bs Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
len = Maybe (Word16, ByteString)
forall a. Maybe a
Nothing
  | Int
len Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = (Word16, ByteString) -> Maybe (Word16, ByteString)
forall a. a -> Maybe a
Just (Word16
0, ByteString
bs)
  | Bool
otherwise =
      let !bytes :: ByteString
bytes = Int -> ByteString -> ByteString
BS.take Int
len ByteString
bs
          !rest :: ByteString
rest = Int -> ByteString -> ByteString
BS.drop Int
len ByteString
bs
      in  if HasCallStack => ByteString -> Int -> Word8
ByteString -> Int -> Word8
BS.index ByteString
bytes Int
0 Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0
            then Maybe (Word16, ByteString)
forall a. Maybe a
Nothing  -- non-minimal: leading zero
            else (Word16, ByteString) -> Maybe (Word16, ByteString)
forall a. a -> Maybe a
Just (ByteString -> Word16
decodeBeWord16 ByteString
bytes, ByteString
rest)
  where
    decodeBeWord16 :: BS.ByteString -> Word16
    decodeBeWord16 :: ByteString -> Word16
decodeBeWord16 ByteString
b = case ByteString -> Int
BS.length ByteString
b of
      Int
1 -> Word8 -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral (HasCallStack => ByteString -> Int -> Word8
ByteString -> Int -> Word8
BS.index ByteString
b Int
0)
      Int
2 -> (Word8 -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral (HasCallStack => ByteString -> Int -> Word8
ByteString -> Int -> Word8
BS.index ByteString
b Int
0) Word16 -> Int -> Word16
forall a. Bits a => a -> Int -> a
`unsafeShiftL` Int
8)
        Word16 -> Word16 -> Word16
forall a. Bits a => a -> a -> a
.|. Word8 -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral (HasCallStack => ByteString -> Int -> Word8
ByteString -> Int -> Word8
BS.index ByteString
b Int
1)
      Int
_ -> Word16
0
{-# INLINE decodeTu16 #-}

-- | Decode a truncated 32-bit unsigned integer (0-4 bytes).
--
-- Returns Nothing if the encoding is non-minimal (has leading zeros).
decodeTu32 :: Int -> BS.ByteString -> Maybe (Word32, BS.ByteString)
decodeTu32 :: Int -> ByteString -> Maybe (Word32, ByteString)
decodeTu32 !Int
len !ByteString
bs
  | Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 Bool -> Bool -> Bool
|| Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
4 = Maybe (Word32, ByteString)
forall a. Maybe a
Nothing
  | ByteString -> Int
BS.length ByteString
bs Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
len = Maybe (Word32, ByteString)
forall a. Maybe a
Nothing
  | Int
len Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = (Word32, ByteString) -> Maybe (Word32, ByteString)
forall a. a -> Maybe a
Just (Word32
0, ByteString
bs)
  | Bool
otherwise =
      let !bytes :: ByteString
bytes = Int -> ByteString -> ByteString
BS.take Int
len ByteString
bs
          !rest :: ByteString
rest = Int -> ByteString -> ByteString
BS.drop Int
len ByteString
bs
      in  if HasCallStack => ByteString -> Int -> Word8
ByteString -> Int -> Word8
BS.index ByteString
bytes Int
0 Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0
            then Maybe (Word32, ByteString)
forall a. Maybe a
Nothing  -- non-minimal: leading zero
            else (Word32, ByteString) -> Maybe (Word32, ByteString)
forall a. a -> Maybe a
Just (Int -> ByteString -> Word32
decodeBeWord32 Int
len ByteString
bytes, ByteString
rest)
  where
    decodeBeWord32 :: Int -> BS.ByteString -> Word32
    decodeBeWord32 :: Int -> ByteString -> Word32
decodeBeWord32 Int
n ByteString
b = Word32 -> Int -> Word32
forall {t}. (Bits t, Num t) => t -> Int -> t
go Word32
0 Int
0
      where
        go :: t -> Int -> t
go !t
acc !Int
i
          | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
n    = t
acc
          | Bool
otherwise = t -> Int -> t
go ((t
acc t -> Int -> t
forall a. Bits a => a -> Int -> a
`unsafeShiftL` Int
8)
                           t -> t -> t
forall a. Bits a => a -> a -> a
.|. Word8 -> t
forall a b. (Integral a, Num b) => a -> b
fromIntegral (HasCallStack => ByteString -> Int -> Word8
ByteString -> Int -> Word8
BS.index ByteString
b Int
i)) (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
{-# INLINE decodeTu32 #-}

-- | Decode a truncated 64-bit unsigned integer (0-8 bytes).
--
-- Returns Nothing if the encoding is non-minimal (has leading zeros).
decodeTu64 :: Int -> BS.ByteString -> Maybe (Word64, BS.ByteString)
decodeTu64 :: Int -> ByteString -> Maybe (Word64, ByteString)
decodeTu64 !Int
len !ByteString
bs
  | Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 Bool -> Bool -> Bool
|| Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
8 = Maybe (Word64, ByteString)
forall a. Maybe a
Nothing
  | ByteString -> Int
BS.length ByteString
bs Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
len = Maybe (Word64, ByteString)
forall a. Maybe a
Nothing
  | Int
len Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = (Word64, ByteString) -> Maybe (Word64, ByteString)
forall a. a -> Maybe a
Just (Word64
0, ByteString
bs)
  | Bool
otherwise =
      let !bytes :: ByteString
bytes = Int -> ByteString -> ByteString
BS.take Int
len ByteString
bs
          !rest :: ByteString
rest = Int -> ByteString -> ByteString
BS.drop Int
len ByteString
bs
      in  if HasCallStack => ByteString -> Int -> Word8
ByteString -> Int -> Word8
BS.index ByteString
bytes Int
0 Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0
            then Maybe (Word64, ByteString)
forall a. Maybe a
Nothing  -- non-minimal: leading zero
            else (Word64, ByteString) -> Maybe (Word64, ByteString)
forall a. a -> Maybe a
Just (Int -> ByteString -> Word64
decodeBeWord64 Int
len ByteString
bytes, ByteString
rest)
  where
    decodeBeWord64 :: Int -> BS.ByteString -> Word64
    decodeBeWord64 :: Int -> ByteString -> Word64
decodeBeWord64 Int
n ByteString
b = Word64 -> Int -> Word64
forall {t}. (Bits t, Num t) => t -> Int -> t
go Word64
0 Int
0
      where
        go :: t -> Int -> t
go !t
acc !Int
i
          | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
n    = t
acc
          | Bool
otherwise = t -> Int -> t
go ((t
acc t -> Int -> t
forall a. Bits a => a -> Int -> a
`unsafeShiftL` Int
8)
                           t -> t -> t
forall a. Bits a => a -> a -> a
.|. Word8 -> t
forall a b. (Integral a, Num b) => a -> b
fromIntegral (HasCallStack => ByteString -> Int -> Word8
ByteString -> Int -> Word8
BS.index ByteString
b Int
i)) (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
{-# INLINE decodeTu64 #-}

-- Minimal signed integer decoding ---------------------------------------------

-- | Decode a minimal signed integer (1, 2, 4, or 8 bytes).
--
-- Validates that the encoding is minimal: the value could not be
-- represented in fewer bytes. Per BOLT #1 Appendix D test vectors.
decodeMinSigned :: Int -> BS.ByteString -> Maybe (Int64, BS.ByteString)
decodeMinSigned :: Int -> ByteString -> Maybe (Int64, ByteString)
decodeMinSigned !Int
len !ByteString
bs
  | ByteString -> Int
BS.length ByteString
bs Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
len = Maybe (Int64, ByteString)
forall a. Maybe a
Nothing
  | Bool
otherwise = case Int
len of
      Int
1 -> do
        (v, rest) <- ByteString -> Maybe (Int8, ByteString)
decodeS8 ByteString
bs
        Just (fromIntegral v, rest)
      Int
2 -> do
        (v, rest) <- ByteString -> Maybe (Int16, ByteString)
decodeS16 ByteString
bs
        -- Must not fit in 1 byte
        if v >= -128 && v <= 127
          then Nothing
          else Just (fromIntegral v, rest)
      Int
4 -> do
        (v, rest) <- ByteString -> Maybe (Int32, ByteString)
decodeS32 ByteString
bs
        -- Must not fit in 2 bytes
        if v >= -32768 && v <= 32767
          then Nothing
          else Just (fromIntegral v, rest)
      Int
8 -> do
        (v, rest) <- ByteString -> Maybe (Int64, ByteString)
decodeS64 ByteString
bs
        -- Must not fit in 4 bytes
        if v >= -2147483648 && v <= 2147483647
          then Nothing
          else Just (v, rest)
      Int
_ -> Maybe (Int64, ByteString)
forall a. Maybe a
Nothing
{-# INLINE decodeMinSigned #-}

-- BigSize decoding ------------------------------------------------------------

-- | Decode a BigSize value with minimality check.
decodeBigSize :: BS.ByteString -> Maybe (Word64, BS.ByteString)
decodeBigSize :: ByteString -> Maybe (Word64, ByteString)
decodeBigSize !ByteString
bs
  | ByteString -> Bool
BS.null ByteString
bs = Maybe (Word64, ByteString)
forall a. Maybe a
Nothing
  | Bool
otherwise = case HasCallStack => ByteString -> Int -> Word8
ByteString -> Int -> Word8
BS.index ByteString
bs Int
0 of
      Word8
0xff -> do
        (val, rest) <- ByteString -> Maybe (Word64, ByteString)
decodeU64 (Int -> ByteString -> ByteString
BS.drop Int
1 ByteString
bs)
        -- Must be >= 0x100000000 for minimal encoding
        if val >= 0x100000000
          then Just (val, rest)
          else Nothing
      Word8
0xfe -> do
        (val, rest) <- ByteString -> Maybe (Word32, ByteString)
decodeU32 (Int -> ByteString -> ByteString
BS.drop Int
1 ByteString
bs)
        -- Must be >= 0x10000 for minimal encoding
        if val >= 0x10000
          then Just (fromIntegral val, rest)
          else Nothing
      Word8
0xfd -> do
        (val, rest) <- ByteString -> Maybe (Word16, ByteString)
decodeU16 (Int -> ByteString -> ByteString
BS.drop Int
1 ByteString
bs)
        -- Must be >= 0xfd for minimal encoding
        if val >= 0xfd
          then Just (fromIntegral val, rest)
          else Nothing
      Word8
b -> (Word64, ByteString) -> Maybe (Word64, ByteString)
forall a. a -> Maybe a
Just (Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b, Int -> ByteString -> ByteString
BS.drop Int
1 ByteString
bs)