| Copyright | (c) 2025 Jared Tobin |
|---|---|
| License | MIT |
| Maintainer | Jared Tobin <jared@ppad.tech> |
| Safe Haskell | None |
| Language | Haskell2010 |
Bitcoin.Prim.Tx.Sighash
Description
Sighash computation for legacy, BIP143 segwit, and BIP341 taproot transactions.
Synopsis
- data SighashType
- encode_sighash :: SighashType -> Word32
- sighash_legacy :: Tx -> Int -> ByteString -> Word32 -> ByteString
- sighash_segwit :: Tx -> Int -> ByteString -> Word64 -> Word32 -> Maybe ByteString
- sighash_taproot_keypath :: Tx -> Int -> [Word64] -> [ByteString] -> Maybe ByteString -> Word8 -> Maybe ByteString
- sighash_taproot_scriptpath :: Tx -> Int -> [Word64] -> [ByteString] -> Maybe ByteString -> ByteString -> Word32 -> Word8 -> Maybe ByteString
- strip_codeseparators :: ByteString -> ByteString
Sighash Types
data SighashType Source #
Canonical sighash type flags.
The Bitcoin consensus rules commit the full 32-bit hashType to
the signature preimage and only use its low byte for behavioral
dispatch (low 5 bits select base type; bit 0x80 selects
ANYONECANPAY). SighashType enumerates the six canonical
single-byte hashTypes; pass arbitrary 32-bit values directly when
reproducing non-canonical hashes.
Constructors
| SIGHASH_ALL | |
| SIGHASH_NONE | |
| SIGHASH_SINGLE | |
| SIGHASH_ALL_ANYONECANPAY | |
| SIGHASH_NONE_ANYONECANPAY | |
| SIGHASH_SINGLE_ANYONECANPAY |
Instances
| Generic SighashType Source # | |||||
Defined in Bitcoin.Prim.Tx.Sighash Associated Types
| |||||
| Show SighashType Source # | |||||
Defined in Bitcoin.Prim.Tx.Sighash Methods showsPrec :: Int -> SighashType -> ShowS # show :: SighashType -> String # showList :: [SighashType] -> ShowS # | |||||
| Eq SighashType Source # | |||||
Defined in Bitcoin.Prim.Tx.Sighash | |||||
| type Rep SighashType Source # | |||||
Defined in Bitcoin.Prim.Tx.Sighash type Rep SighashType = D1 ('MetaData "SighashType" "Bitcoin.Prim.Tx.Sighash" "ppad-tx-0.1.0-21zhDlOjEJY2BsybwwnJrp" 'False) ((C1 ('MetaCons "SIGHASH_ALL" 'PrefixI 'False) (U1 :: Type -> Type) :+: (C1 ('MetaCons "SIGHASH_NONE" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "SIGHASH_SINGLE" 'PrefixI 'False) (U1 :: Type -> Type))) :+: (C1 ('MetaCons "SIGHASH_ALL_ANYONECANPAY" 'PrefixI 'False) (U1 :: Type -> Type) :+: (C1 ('MetaCons "SIGHASH_NONE_ANYONECANPAY" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "SIGHASH_SINGLE_ANYONECANPAY" 'PrefixI 'False) (U1 :: Type -> Type)))) | |||||
encode_sighash :: SighashType -> Word32 Source #
Encode a canonical SighashType to its 32-bit hashType value.
encode_sighash SIGHASH_ALL == 0x01 encode_sighash SIGHASH_SINGLE_ANYONECANPAY == 0x83
Legacy Sighash
Arguments
| :: Tx | |
| -> Int | input index |
| -> ByteString | scriptPubKey being spent |
| -> Word32 | hashType |
| -> ByteString | 32-byte hash |
Compute legacy sighash for P2PKH/P2SH inputs.
Modifies a copy of the transaction based on hashType flags, appends
the 4-byte little-endian hashType, and double SHA256s. The
hashType is committed to the preimage verbatim; only its low byte
determines behavior (see base_type, is_anyonecanpay).
-- sign input 0 with SIGHASH_ALL let hash = sighash_legacy tx 0 scriptPubKey (encode_sighash SIGHASH_ALL) -- non-canonical hashType (consensus-valid, committed raw) let hash = sighash_legacy tx 0 scriptPubKey 0x6f29291f
For base SIGHASH_SINGLE with input index >= output count, returns the special "sighash single bug" value (0x01 followed by 31 zero bytes).
The input index is not validated against the input count; an
out-of-range idx produces a deterministic but
consensus-undefined hash. Matches Bitcoin Core, which asserts on
the same precondition. Contrast sighash_segwit, which validates
and returns Nothing.
BIP143 Segwit Sighash
Arguments
| :: Tx | |
| -> Int | input index |
| -> ByteString | scriptCode |
| -> Word64 | value being spent (satoshis) |
| -> Word32 | hashType |
| -> Maybe ByteString | 32-byte hash, or Nothing if index invalid |
Compute BIP143 segwit sighash.
Required for signing segwit inputs (P2WPKH, P2WSH). Unlike legacy
sighash, this commits to the value being spent, preventing fee
manipulation attacks. The hashType is committed to the preimage
verbatim; only its low byte determines behavior.
Returns Nothing if the input index is out of range.
-- sign P2WPKH input 0
let scriptCode = ... -- P2WPKH scriptCode
let hash = sighash_segwit tx 0 scriptCode inputValue
(encode_sighash SIGHASH_ALL)
-- use hash with ECDSA signing (after checking Just)
BIP341 Taproot Sighash
sighash_taproot_keypath Source #
Arguments
| :: Tx | |
| -> Int | input index |
| -> [Word64] | amounts for all inputs (in order) |
| -> [ByteString] | scriptPubKeys for all inputs (in order) |
| -> Maybe ByteString | optional annex (including 0x50 prefix) |
| -> Word8 | hash type |
| -> Maybe ByteString | 32-byte hash, or Nothing on invalid input |
Compute BIP341 taproot sighash for a key-path spend.
The caller must supply, in input order, the amount and
scriptPubKey of every previous output being spent (the entire
set is committed to the preimage when not using
SIGHASH_ANYONECANPAY).
The annex, if present, must include the mandatory 0x50 prefix byte (as it appears in the witness).
Returns Nothing if any of the following holds:
hash_typeis not a canonical taproot value- the input index is out of range
amountsorscriptPubKeysdoes not match the input count- an annex is supplied without the 0x50 prefix or is empty
hash_typeisSIGHASH_SINGLE(or its ACP variant) and the input index has no corresponding output (such a signature would be consensus-invalid per BIP341)
sighash_taproot_keypath tx 0 amounts scriptPubKeys Nothing 0x00
sighash_taproot_scriptpath Source #
Arguments
| :: Tx | |
| -> Int | input index |
| -> [Word64] | amounts for all inputs (in order) |
| -> [ByteString] | scriptPubKeys for all inputs (in order) |
| -> Maybe ByteString | optional annex (including 0x50 prefix) |
| -> ByteString | tap leaf hash (32 bytes) |
| -> Word32 | codeseparator position |
| -> Word8 | hash type |
| -> Maybe ByteString |
Compute BIP341 taproot sighash for a script-path (tapscript) spend.
In addition to the key-path inputs, takes:
- the 32-byte tap leaf hash (BIP342: tagged hash of
leaf_ver || ser_string(script)), computed by the caller - the codeseparator position (0xffffffff if none was executed)
Returns Nothing under the same conditions as
sighash_taproot_keypath, plus when tap_leaf_hash is not
exactly 32 bytes.
Internal
strip_codeseparators :: ByteString -> ByteString Source #
Strip OP_CODESEPARATOR (0xab) opcodes from a script, skipping
push-data sections so that data bytes equal to 0xab are preserved.
This is consensus-required preprocessing for the legacy sighash
scriptCode (see Bitcoin Core's CTransactionSignatureSerializer).
BIP143 segwit sighash does not perform this stripping; for
segwit, the caller is responsible for trimming the scriptCode to
the portion after the last executed OP_CODESEPARATOR.
On a malformed script (truncated push data), the malformed tail is copied verbatim without further codeseparator processing.