ppad-tx-0.1.0: Minimal Bitcoin transaction primitives.
Copyright(c) 2025 Jared Tobin
LicenseMIT
MaintainerJared Tobin <jared@ppad.tech>
Safe HaskellNone
LanguageHaskell2010

Bitcoin.Prim.Tx

Description

Minimal Bitcoin transaction primitives, including raw transaction types, serialisation to/from bytes, and txid computation.

Synopsis

Transaction Types

data Tx Source #

Complete transaction.

Bitcoin requires at least one input and one output, enforced here via NonEmpty lists.

Constructors

Tx 

Fields

Instances

Instances details
Generic Tx Source # 
Instance details

Defined in Bitcoin.Prim.Tx

Associated Types

type Rep Tx 
Instance details

Defined in Bitcoin.Prim.Tx

type Rep Tx = D1 ('MetaData "Tx" "Bitcoin.Prim.Tx" "ppad-tx-0.1.0-55gH9IEpqyC9H1txhCYBkH" 'False) (C1 ('MetaCons "Tx" 'PrefixI 'True) ((S1 ('MetaSel ('Just "tx_version") 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Word32) :*: S1 ('MetaSel ('Just "tx_inputs") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 (NonEmpty TxIn))) :*: (S1 ('MetaSel ('Just "tx_outputs") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 (NonEmpty TxOut)) :*: (S1 ('MetaSel ('Just "tx_witnesses") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 [Witness]) :*: S1 ('MetaSel ('Just "tx_locktime") 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Word32)))))

Methods

from :: Tx -> Rep Tx x #

to :: Rep Tx x -> Tx #

Show Tx Source # 
Instance details

Defined in Bitcoin.Prim.Tx

Methods

showsPrec :: Int -> Tx -> ShowS #

show :: Tx -> String #

showList :: [Tx] -> ShowS #

Eq Tx Source # 
Instance details

Defined in Bitcoin.Prim.Tx

Methods

(==) :: Tx -> Tx -> Bool #

(/=) :: Tx -> Tx -> Bool #

type Rep Tx Source # 
Instance details

Defined in Bitcoin.Prim.Tx

type Rep Tx = D1 ('MetaData "Tx" "Bitcoin.Prim.Tx" "ppad-tx-0.1.0-55gH9IEpqyC9H1txhCYBkH" 'False) (C1 ('MetaCons "Tx" 'PrefixI 'True) ((S1 ('MetaSel ('Just "tx_version") 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Word32) :*: S1 ('MetaSel ('Just "tx_inputs") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 (NonEmpty TxIn))) :*: (S1 ('MetaSel ('Just "tx_outputs") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 (NonEmpty TxOut)) :*: (S1 ('MetaSel ('Just "tx_witnesses") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 [Witness]) :*: S1 ('MetaSel ('Just "tx_locktime") 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Word32)))))

data TxIn Source #

Transaction input.

Instances

Instances details
Generic TxIn Source # 
Instance details

Defined in Bitcoin.Prim.Tx

Associated Types

type Rep TxIn 
Instance details

Defined in Bitcoin.Prim.Tx

type Rep TxIn = D1 ('MetaData "TxIn" "Bitcoin.Prim.Tx" "ppad-tx-0.1.0-55gH9IEpqyC9H1txhCYBkH" 'False) (C1 ('MetaCons "TxIn" 'PrefixI 'True) (S1 ('MetaSel ('Just "txin_prevout") 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 OutPoint) :*: (S1 ('MetaSel ('Just "txin_script_sig") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 ByteString) :*: S1 ('MetaSel ('Just "txin_sequence") 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Word32))))

Methods

from :: TxIn -> Rep TxIn x #

to :: Rep TxIn x -> TxIn #

Show TxIn Source # 
Instance details

Defined in Bitcoin.Prim.Tx

Methods

showsPrec :: Int -> TxIn -> ShowS #

show :: TxIn -> String #

showList :: [TxIn] -> ShowS #

Eq TxIn Source # 
Instance details

Defined in Bitcoin.Prim.Tx

Methods

(==) :: TxIn -> TxIn -> Bool #

(/=) :: TxIn -> TxIn -> Bool #

type Rep TxIn Source # 
Instance details

Defined in Bitcoin.Prim.Tx

type Rep TxIn = D1 ('MetaData "TxIn" "Bitcoin.Prim.Tx" "ppad-tx-0.1.0-55gH9IEpqyC9H1txhCYBkH" 'False) (C1 ('MetaCons "TxIn" 'PrefixI 'True) (S1 ('MetaSel ('Just "txin_prevout") 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 OutPoint) :*: (S1 ('MetaSel ('Just "txin_script_sig") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 ByteString) :*: S1 ('MetaSel ('Just "txin_sequence") 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Word32))))

data TxOut Source #

Transaction output.

Constructors

TxOut 

Instances

Instances details
Generic TxOut Source # 
Instance details

Defined in Bitcoin.Prim.Tx

Associated Types

type Rep TxOut 
Instance details

Defined in Bitcoin.Prim.Tx

type Rep TxOut = D1 ('MetaData "TxOut" "Bitcoin.Prim.Tx" "ppad-tx-0.1.0-55gH9IEpqyC9H1txhCYBkH" 'False) (C1 ('MetaCons "TxOut" 'PrefixI 'True) (S1 ('MetaSel ('Just "txout_value") 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Word64) :*: S1 ('MetaSel ('Just "txout_script_pubkey") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 ByteString)))

Methods

from :: TxOut -> Rep TxOut x #

to :: Rep TxOut x -> TxOut #

Show TxOut Source # 
Instance details

Defined in Bitcoin.Prim.Tx

Methods

showsPrec :: Int -> TxOut -> ShowS #

show :: TxOut -> String #

showList :: [TxOut] -> ShowS #

Eq TxOut Source # 
Instance details

Defined in Bitcoin.Prim.Tx

Methods

(==) :: TxOut -> TxOut -> Bool #

(/=) :: TxOut -> TxOut -> Bool #

type Rep TxOut Source # 
Instance details

Defined in Bitcoin.Prim.Tx

type Rep TxOut = D1 ('MetaData "TxOut" "Bitcoin.Prim.Tx" "ppad-tx-0.1.0-55gH9IEpqyC9H1txhCYBkH" 'False) (C1 ('MetaCons "TxOut" 'PrefixI 'True) (S1 ('MetaSel ('Just "txout_value") 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Word64) :*: S1 ('MetaSel ('Just "txout_script_pubkey") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 ByteString)))

data OutPoint Source #

Transaction outpoint (txid + output index).

Constructors

OutPoint 

Fields

Instances

Instances details
Generic OutPoint Source # 
Instance details

Defined in Bitcoin.Prim.Tx

Associated Types

type Rep OutPoint 
Instance details

Defined in Bitcoin.Prim.Tx

type Rep OutPoint = D1 ('MetaData "OutPoint" "Bitcoin.Prim.Tx" "ppad-tx-0.1.0-55gH9IEpqyC9H1txhCYBkH" 'False) (C1 ('MetaCons "OutPoint" 'PrefixI 'True) (S1 ('MetaSel ('Just "op_txid") 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 TxId) :*: S1 ('MetaSel ('Just "op_vout") 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Word32)))

Methods

from :: OutPoint -> Rep OutPoint x #

to :: Rep OutPoint x -> OutPoint #

Show OutPoint Source # 
Instance details

Defined in Bitcoin.Prim.Tx

Eq OutPoint Source # 
Instance details

Defined in Bitcoin.Prim.Tx

type Rep OutPoint Source # 
Instance details

Defined in Bitcoin.Prim.Tx

type Rep OutPoint = D1 ('MetaData "OutPoint" "Bitcoin.Prim.Tx" "ppad-tx-0.1.0-55gH9IEpqyC9H1txhCYBkH" 'False) (C1 ('MetaCons "OutPoint" 'PrefixI 'True) (S1 ('MetaSel ('Just "op_txid") 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 TxId) :*: S1 ('MetaSel ('Just "op_vout") 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Word32)))

newtype Witness Source #

Witness stack for a single input.

Constructors

Witness [ByteString] 

Instances

Instances details
Generic Witness Source # 
Instance details

Defined in Bitcoin.Prim.Tx

Associated Types

type Rep Witness 
Instance details

Defined in Bitcoin.Prim.Tx

type Rep Witness = D1 ('MetaData "Witness" "Bitcoin.Prim.Tx" "ppad-tx-0.1.0-55gH9IEpqyC9H1txhCYBkH" 'True) (C1 ('MetaCons "Witness" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 [ByteString])))

Methods

from :: Witness -> Rep Witness x #

to :: Rep Witness x -> Witness #

Show Witness Source # 
Instance details

Defined in Bitcoin.Prim.Tx

Eq Witness Source # 
Instance details

Defined in Bitcoin.Prim.Tx

Methods

(==) :: Witness -> Witness -> Bool #

(/=) :: Witness -> Witness -> Bool #

type Rep Witness Source # 
Instance details

Defined in Bitcoin.Prim.Tx

type Rep Witness = D1 ('MetaData "Witness" "Bitcoin.Prim.Tx" "ppad-tx-0.1.0-55gH9IEpqyC9H1txhCYBkH" 'True) (C1 ('MetaCons "Witness" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 [ByteString])))

newtype TxId Source #

Transaction ID (32 bytes, little-endian double-SHA256).

Constructors

TxId ByteString 

Instances

Instances details
Generic TxId Source # 
Instance details

Defined in Bitcoin.Prim.Tx

Associated Types

type Rep TxId 
Instance details

Defined in Bitcoin.Prim.Tx

type Rep TxId = D1 ('MetaData "TxId" "Bitcoin.Prim.Tx" "ppad-tx-0.1.0-55gH9IEpqyC9H1txhCYBkH" 'True) (C1 ('MetaCons "TxId" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 ByteString)))

Methods

from :: TxId -> Rep TxId x #

to :: Rep TxId x -> TxId #

Show TxId Source # 
Instance details

Defined in Bitcoin.Prim.Tx

Methods

showsPrec :: Int -> TxId -> ShowS #

show :: TxId -> String #

showList :: [TxId] -> ShowS #

Eq TxId Source # 
Instance details

Defined in Bitcoin.Prim.Tx

Methods

(==) :: TxId -> TxId -> Bool #

(/=) :: TxId -> TxId -> Bool #

type Rep TxId Source # 
Instance details

Defined in Bitcoin.Prim.Tx

type Rep TxId = D1 ('MetaData "TxId" "Bitcoin.Prim.Tx" "ppad-tx-0.1.0-55gH9IEpqyC9H1txhCYBkH" 'True) (C1 ('MetaCons "TxId" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 ByteString)))

mkTxId :: ByteString -> Maybe TxId Source #

Construct a TxId from a 32-byte ByteString.

Returns Nothing if the input is not exactly 32 bytes.

  mkTxId (BS.replicate 32 0x00) == Just (TxId ...)
  mkTxId (BS.replicate 31 0x00) == Nothing
  

Serialisation

to_bytes :: Tx -> ByteString Source #

Serialise a transaction to bytes.

Uses segwit format if witnesses are present, legacy otherwise.

  -- round-trip
  from_bytes (to_bytes tx) == Just tx
  

from_bytes :: ByteString -> Maybe Tx Source #

Parse a transaction from bytes.

Automatically detects segwit vs legacy format by checking for marker byte 0x00 followed by flag 0x01 after the version field.

Returns Nothing on invalid or truncated input.

  -- round-trip
  from_bytes (to_bytes tx) == Just tx
  

to_bytes_legacy :: Tx -> ByteString Source #

Serialise a transaction to legacy format (no witness data).

Used for txid computation. Excludes witness data even if present.

  -- for legacy tx (no witnesses), same as to_bytes
  to_bytes_legacy legacyTx == to_bytes legacyTx

  -- for segwit tx, strips witnesses
  BS.length (to_bytes_legacy segwitTx) < BS.length (to_bytes segwitTx)
  

to_base16 :: Tx -> ByteString Source #

Serialise a transaction to base16 (hex).

  to_base16 tx = B16.encode (to_bytes tx)
  

from_base16 :: ByteString -> Maybe Tx Source #

Parse a transaction from base16 (hex).

  -- round-trip
  from_base16 (to_base16 tx) == Just tx
  

TxId

txid :: Tx -> TxId Source #

Compute the transaction ID (double SHA256 of legacy serialisation).

The txid is computed from the legacy serialisation, so segwit transactions have the same txid regardless of witness data.

  -- Satoshi->Hal tx (block 170)
  txid satoshiHalTx ==
    TxId "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16"
  

Internal (for Sighash)

put_word32_le :: Word32 -> Builder Source #

Encode a Word32 as little-endian bytes.

put_word64_le :: Word64 -> Builder Source #

Encode a Word64 as little-endian bytes.

put_compact :: Word64 -> Builder Source #

Encode a Word64 as Bitcoin compactSize (varint).

Encoding: - 0x00-0xfc: 1 byte (value itself) - 0xfd-0xffff: 0xfd ++ 2 bytes LE - 0x10000-0xffffffff: 0xfe ++ 4 bytes LE - larger: 0xff ++ 8 bytes LE

put_outpoint :: OutPoint -> Builder Source #

Encode an OutPoint (txid + vout).

put_txout :: TxOut -> Builder Source #

Encode a TxOut.

to_strict :: Builder -> ByteString Source #

Convert a Builder to a strict ByteString.