Merge rust-bitcoin/rust-bitcoin#956: Improve docs in `sighash` and `psbt/mod.rs`
9896f27eae
psbt: Improve documentation (Tobin C. Harding)33a50831ce
sighash: Improve documentation (Tobin Harding) Pull request description: Done while working on sighash and PSBT signing. Just the usual docs fixes. Note, does not do the whole `psbt` module just the file mentioned. ACKs for top commit: apoelstra: ACK9896f27eae
Tree-SHA512: 5fbfa258cdb216189922a49a42b7ab9fb78faeee72d82f8cb99a1b3d930d170074013e317b0e7af259a404ac4db93841b4d2b525e933c5e145da71e7522800fd
This commit is contained in:
commit
fcb035fb4f
|
@ -53,13 +53,12 @@ pub type Psbt = PartiallySignedTransaction;
|
|||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct PartiallySignedTransaction {
|
||||
/// The unsigned transaction, scriptSigs and witnesses for each input must be
|
||||
/// empty.
|
||||
/// The unsigned transaction, scriptSigs and witnesses for each input must be empty.
|
||||
pub unsigned_tx: Transaction,
|
||||
/// The version number of this PSBT. If omitted, the version number is 0.
|
||||
pub version: u32,
|
||||
/// A global map from extended public keys to the used key fingerprint and
|
||||
/// derivation path as defined by BIP 32
|
||||
/// derivation path as defined by BIP 32.
|
||||
pub xpub: BTreeMap<ExtendedPubKey, KeySource>,
|
||||
/// Global proprietary key-value pairs.
|
||||
#[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq_byte_values"))]
|
||||
|
@ -68,11 +67,9 @@ pub struct PartiallySignedTransaction {
|
|||
#[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq_byte_values"))]
|
||||
pub unknown: BTreeMap<raw::Key, Vec<u8>>,
|
||||
|
||||
/// The corresponding key-value map for each input in the unsigned
|
||||
/// transaction.
|
||||
/// The corresponding key-value map for each input in the unsigned transaction.
|
||||
pub inputs: Vec<Input>,
|
||||
/// The corresponding key-value map for each output in the unsigned
|
||||
/// transaction.
|
||||
/// The corresponding key-value map for each output in the unsigned transaction.
|
||||
pub outputs: Vec<Output>,
|
||||
}
|
||||
|
||||
|
@ -103,8 +100,7 @@ impl PartiallySignedTransaction {
|
|||
})
|
||||
}
|
||||
|
||||
/// Checks that unsigned transaction does not have scriptSig's or witness
|
||||
/// data
|
||||
/// Checks that unsigned transaction does not have scriptSig's or witness data.
|
||||
fn unsigned_tx_checks(&self) -> Result<(), Error> {
|
||||
for txin in &self.unsigned_tx.input {
|
||||
if !txin.script_sig.is_empty() {
|
||||
|
@ -119,8 +115,11 @@ impl PartiallySignedTransaction {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Create a PartiallySignedTransaction from an unsigned transaction, error
|
||||
/// if not unsigned
|
||||
/// Creates a PSBT from an unsigned transaction.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// If transactions is not unsigned.
|
||||
pub fn from_unsigned_tx(tx: Transaction) -> Result<Self, Error> {
|
||||
let psbt = PartiallySignedTransaction {
|
||||
inputs: vec![Default::default(); tx.input.len()],
|
||||
|
@ -136,8 +135,7 @@ impl PartiallySignedTransaction {
|
|||
Ok(psbt)
|
||||
}
|
||||
|
||||
/// Extract the Transaction from a PartiallySignedTransaction by filling in
|
||||
/// the available signature information in place.
|
||||
/// Extracts the `Transaction` from a PSBT by filling in the available signature information.
|
||||
pub fn extract_tx(self) -> Transaction {
|
||||
let mut tx: Transaction = self.unsigned_tx;
|
||||
|
||||
|
@ -222,13 +220,13 @@ mod display_from_str {
|
|||
use crate::consensus::encode::{Error, self};
|
||||
use base64::display::Base64Display;
|
||||
|
||||
/// Error happening during PSBT decoding from Base64 string
|
||||
/// Error encountered during PSBT decoding from Base64 string.
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "base64")))]
|
||||
pub enum PsbtParseError {
|
||||
/// Error in internal PSBT data structure
|
||||
/// Error in internal PSBT data structure.
|
||||
PsbtEncoding(Error),
|
||||
/// Error in PSBT Base64 encoding
|
||||
/// Error in PSBT Base64 encoding.
|
||||
Base64Encoding(::base64::DecodeError)
|
||||
}
|
||||
|
||||
|
|
|
@ -39,33 +39,33 @@ use super::taproot::LeafVersion;
|
|||
/// Efficiently calculates signature hash message for legacy, segwit and taproot inputs.
|
||||
#[derive(Debug)]
|
||||
pub struct SighashCache<T: Deref<Target=Transaction>> {
|
||||
/// Access to transaction required for various introspection, moreover type
|
||||
/// `T: Deref<Target=Transaction>` allows to accept borrow and mutable borrow, the
|
||||
/// latter in particular is necessary for [`SighashCache::witness_mut`]
|
||||
/// Access to transaction required for transaction introspection. Moreover, type
|
||||
/// `T: Deref<Target=Transaction>` allows us to use borrowed and mutable borrowed types,
|
||||
/// the latter in particular is necessary for [`SighashCache::witness_mut`].
|
||||
tx: T,
|
||||
|
||||
/// Common cache for taproot and segwit inputs. It's an option because it's not needed for legacy inputs
|
||||
/// Common cache for taproot and segwit inputs, `None` for legacy inputs.
|
||||
common_cache: Option<CommonCache>,
|
||||
|
||||
/// Cache for segwit v0 inputs, it's the result of another round of sha256 on `common_cache`
|
||||
/// Cache for segwit v0 inputs (the result of another round of sha256 on `common_cache`).
|
||||
segwit_cache: Option<SegwitCache>,
|
||||
|
||||
/// Cache for taproot v1 inputs
|
||||
/// Cache for taproot v1 inputs.
|
||||
taproot_cache: Option<TaprootCache>,
|
||||
}
|
||||
|
||||
/// Values cached common between segwit and taproot inputs
|
||||
/// Common values cached between segwit and taproot inputs.
|
||||
#[derive(Debug)]
|
||||
struct CommonCache {
|
||||
prevouts: sha256::Hash,
|
||||
sequences: sha256::Hash,
|
||||
|
||||
/// in theory, `outputs` could be `Option` since `NONE` and `SINGLE` doesn't need it, but since
|
||||
/// `ALL` is the mostly used variant by large, we don't bother
|
||||
/// In theory `outputs` could be an `Option` since `SIGHASH_NONE` and `SIGHASH_SINGLE` do not
|
||||
/// need it, but since `SIGHASH_ALL` is by far the most used variant we don't bother.
|
||||
outputs: sha256::Hash,
|
||||
}
|
||||
|
||||
/// Values cached for segwit inputs, it's equal to [`CommonCache`] plus another round of `sha256`
|
||||
/// Values cached for segwit inputs, equivalent to [`CommonCache`] plus another round of `sha256`.
|
||||
#[derive(Debug)]
|
||||
struct SegwitCache {
|
||||
prevouts: sha256d::Hash,
|
||||
|
@ -73,29 +73,29 @@ struct SegwitCache {
|
|||
outputs: sha256d::Hash,
|
||||
}
|
||||
|
||||
/// Values cached for taproot inputs
|
||||
/// Values cached for taproot inputs.
|
||||
#[derive(Debug)]
|
||||
struct TaprootCache {
|
||||
amounts: sha256::Hash,
|
||||
script_pubkeys: sha256::Hash,
|
||||
}
|
||||
|
||||
/// Contains outputs of previous transactions.
|
||||
/// In the case [`SchnorrSighashType`] variant is `ANYONECANPAY`, [`Prevouts::One`] may be provided
|
||||
/// Contains outputs of previous transactions. In the case [`SchnorrSighashType`] variant is
|
||||
/// `SIGHASH_ANYONECANPAY`, [`Prevouts::One`] may be used.
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
pub enum Prevouts<'u, T> where T: 'u + Borrow<TxOut> {
|
||||
/// `One` variant allows to provide the single Prevout needed. It's useful for example
|
||||
/// when modifier `ANYONECANPAY` is provided, only prevout of the current input is needed.
|
||||
/// `One` variant allows provision of the single prevout needed. It's useful, for example, when
|
||||
/// modifier `SIGHASH_ANYONECANPAY` is provided, only prevout of the current input is needed.
|
||||
/// The first `usize` argument is the input index this [`TxOut`] is referring to.
|
||||
One(usize, T),
|
||||
/// When `ANYONECANPAY` is not provided, or the caller is handy giving all prevouts so the same
|
||||
/// variable can be used for multiple inputs.
|
||||
/// When `SIGHASH_ANYONECANPAY` is not provided, or when the caller is giving all prevouts so
|
||||
/// the same variable can be used for multiple inputs.
|
||||
All(&'u [T]),
|
||||
}
|
||||
|
||||
const KEY_VERSION_0: u8 = 0u8;
|
||||
|
||||
/// Information related to the script path spending
|
||||
/// Information related to the script path spending.
|
||||
///
|
||||
/// This can be hashed into a [`TapLeafHash`].
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
|
@ -104,29 +104,29 @@ pub struct ScriptPath<'s> {
|
|||
leaf_version: LeafVersion,
|
||||
}
|
||||
|
||||
/// Hashtype of an input's signature, encoded in the last byte of the signature
|
||||
/// Fixed values so they can be casted as integer types for encoding
|
||||
/// Hashtype of an input's signature, encoded in the last byte of the signature.
|
||||
/// Fixed values so they can be cast as integer types for encoding.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
pub enum SchnorrSighashType {
|
||||
/// 0x0: Used when not explicitly specified, defaulting to [`SchnorrSighashType::All`]
|
||||
/// 0x0: Used when not explicitly specified, defaults to [`SchnorrSighashType::All`]
|
||||
Default = 0x00,
|
||||
/// 0x1: Sign all outputs
|
||||
/// 0x1: Sign all outputs.
|
||||
All = 0x01,
|
||||
/// 0x2: Sign no outputs --- anyone can choose the destination
|
||||
/// 0x2: Sign no outputs --- anyone can choose the destination.
|
||||
None = 0x02,
|
||||
/// 0x3: Sign the output whose index matches this input's index. If none exists,
|
||||
/// sign the hash `0000000000000000000000000000000000000000000000000000000000000001`.
|
||||
/// (This rule is probably an unintentional C++ism, but it's consensus so we have
|
||||
/// to follow it.)
|
||||
Single = 0x03,
|
||||
/// 0x81: Sign all outputs but only this input
|
||||
/// 0x81: Sign all outputs but only this input.
|
||||
AllPlusAnyoneCanPay = 0x81,
|
||||
/// 0x82: Sign no outputs and only this input
|
||||
/// 0x82: Sign no outputs and only this input.
|
||||
NonePlusAnyoneCanPay = 0x82,
|
||||
/// 0x83: Sign one output and only this input (see `Single` for what "one output" means)
|
||||
/// 0x83: Sign one output and only this input (see `Single` for what "one output" means).
|
||||
SinglePlusAnyoneCanPay = 0x83,
|
||||
|
||||
/// Reserved for future use, `#[non_exhaustive]` is not available with current MSRV
|
||||
/// Reserved for future use, `#[non_exhaustive]` is not available with MSRV 1.29.0
|
||||
Reserved = 0xFF,
|
||||
}
|
||||
serde_string_impl!(SchnorrSighashType, "a SchnorrSighashType data");
|
||||
|
@ -165,45 +165,46 @@ impl str::FromStr for SchnorrSighashType {
|
|||
}
|
||||
}
|
||||
|
||||
/// Possible errors in computing the signature message
|
||||
/// Possible errors in computing the signature message.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
pub enum Error {
|
||||
/// Could happen only by using `*_encode_signing_*` methods with custom writers, engines writers
|
||||
/// like the ones used in methods `*_signature_hash` don't error
|
||||
/// like the ones used in methods `*_signature_hash` do not error.
|
||||
Io(io::ErrorKind),
|
||||
|
||||
/// Requested index is greater or equal than the number of inputs in the transaction
|
||||
/// Requested index is greater or equal than the number of inputs in the transaction.
|
||||
IndexOutOfInputsBounds {
|
||||
/// Requested index
|
||||
/// Requested index.
|
||||
index: usize,
|
||||
/// Number of transaction inputs
|
||||
/// Number of transaction inputs.
|
||||
inputs_size: usize,
|
||||
},
|
||||
|
||||
/// Using SIGHASH_SINGLE without a "corresponding output" (an output with the same index as the
|
||||
/// input being verified) is a validation failure
|
||||
/// Using `SIGHASH_SINGLE` without a "corresponding output" (an output with the same index as
|
||||
/// the input being verified) is a validation failure.
|
||||
SingleWithoutCorrespondingOutput {
|
||||
/// Requested index
|
||||
/// Requested index.
|
||||
index: usize,
|
||||
/// Number of transaction outputs
|
||||
/// Number of transaction outputs.
|
||||
outputs_size: usize,
|
||||
},
|
||||
|
||||
/// There are mismatches in the number of prevouts provided compared with the number of
|
||||
/// inputs in the transaction
|
||||
/// There are mismatches in the number of prevouts provided compared to the number of inputs in
|
||||
/// the transaction.
|
||||
PrevoutsSize,
|
||||
|
||||
/// Requested a prevout index which is greater than the number of prevouts provided or a
|
||||
/// [`Prevouts::One`] with different index
|
||||
/// [`Prevouts::One`] with different index.
|
||||
PrevoutIndex,
|
||||
|
||||
/// A single prevout has been provided but all prevouts are needed without `ANYONECANPAY`
|
||||
/// A single prevout has been provided but all prevouts are needed unless using
|
||||
/// `SIGHASH_ANYONECANPAY`.
|
||||
PrevoutKind,
|
||||
|
||||
/// Annex must be at least one byte long and the first bytes must be `0x50`
|
||||
/// Annex must be at least one byte long and the first bytes must be `0x50`.
|
||||
WrongAnnex,
|
||||
|
||||
/// Invalid Sighash type
|
||||
/// Invalid Sighash type.
|
||||
InvalidSighashType(u32),
|
||||
}
|
||||
|
||||
|
@ -260,18 +261,18 @@ impl<'u, T> Prevouts<'u, T> where T: Borrow<TxOut> {
|
|||
}
|
||||
|
||||
impl<'s> ScriptPath<'s> {
|
||||
/// Create a new ScriptPath structure
|
||||
/// Creates a new `ScriptPath` structure.
|
||||
pub fn new(script: &'s Script, leaf_version: LeafVersion) -> Self {
|
||||
ScriptPath {
|
||||
script,
|
||||
leaf_version,
|
||||
}
|
||||
}
|
||||
/// Create a new ScriptPath structure using default leaf version value
|
||||
/// Creates a new `ScriptPath` structure using default leaf version value.
|
||||
pub fn with_defaults(script: &'s Script) -> Self {
|
||||
Self::new(script, LeafVersion::TapScript)
|
||||
}
|
||||
/// Compute the leaf hash
|
||||
/// Computes the leaf hash for this `ScriptPath`.
|
||||
pub fn leaf_hash(&self) -> TapLeafHash {
|
||||
let mut enc = TapLeafHash::engine();
|
||||
|
||||
|
@ -302,7 +303,7 @@ impl From<EcdsaSighashType> for SchnorrSighashType {
|
|||
}
|
||||
|
||||
impl SchnorrSighashType {
|
||||
/// Break the sighash flag into the "real" sighash flag and the ANYONECANPAY boolean
|
||||
/// Breaks the sighash flag into the "real" sighash flag and the `SIGHASH_ANYONECANPAY` boolean.
|
||||
pub(crate) fn split_anyonecanpay_flag(self) -> (SchnorrSighashType, bool) {
|
||||
match self {
|
||||
SchnorrSighashType::Default => (SchnorrSighashType::Default, false),
|
||||
|
@ -316,7 +317,7 @@ impl SchnorrSighashType {
|
|||
}
|
||||
}
|
||||
|
||||
/// Create a [`SchnorrSighashType`] from raw `u8`
|
||||
/// Creates a [`SchnorrSighashType`] from raw `u8`.
|
||||
pub fn from_u8(hash_ty: u8) -> Result<Self, Error> {
|
||||
match hash_ty {
|
||||
0x00 => Ok(SchnorrSighashType::Default),
|
||||
|
@ -332,11 +333,12 @@ impl SchnorrSighashType {
|
|||
}
|
||||
}
|
||||
|
||||
impl<R: Deref<Target=Transaction>> SighashCache<R> {
|
||||
/// Compute the sighash components from an unsigned transaction and auxiliary
|
||||
/// in a lazy manner when required.
|
||||
/// For the generated sighashes to be valid, no fields in the transaction may change except for
|
||||
/// script_sig and witnesses.
|
||||
impl<R: Deref<Target = Transaction>> SighashCache<R> {
|
||||
/// Constructs a new `SighashCache` from an unsigned transaction.
|
||||
///
|
||||
/// The sighash components are computed in a lazy manner when required. For the generated
|
||||
/// sighashes to be valid, no fields in the transaction may change except for script_sig and
|
||||
/// witness.
|
||||
pub fn new(tx: R) -> Self {
|
||||
SighashCache {
|
||||
tx,
|
||||
|
@ -346,8 +348,8 @@ impl<R: Deref<Target=Transaction>> SighashCache<R> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Encode the BIP341 signing data for any flag type into a given object implementing a
|
||||
/// io::Write trait.
|
||||
/// Encodes the BIP341 signing data for any flag type into a given object implementing a
|
||||
/// [`io::Write`] trait.
|
||||
pub fn taproot_encode_signing_data_to<Write: io::Write, T: Borrow<TxOut>>(
|
||||
&mut self,
|
||||
mut writer: Write,
|
||||
|
@ -477,7 +479,7 @@ impl<R: Deref<Target=Transaction>> SighashCache<R> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Compute the BIP341 sighash for any flag type.
|
||||
/// Computes the BIP341 sighash for any flag type.
|
||||
pub fn taproot_signature_hash<T: Borrow<TxOut>>(
|
||||
&mut self,
|
||||
input_index: usize,
|
||||
|
@ -498,7 +500,7 @@ impl<R: Deref<Target=Transaction>> SighashCache<R> {
|
|||
Ok(TapSighashHash::from_engine(enc))
|
||||
}
|
||||
|
||||
/// Compute the BIP341 sighash for a key spend
|
||||
/// Computes the BIP341 sighash for a key spend.
|
||||
pub fn taproot_key_spend_signature_hash<T: Borrow<TxOut>>(
|
||||
&mut self,
|
||||
input_index: usize,
|
||||
|
@ -517,7 +519,7 @@ impl<R: Deref<Target=Transaction>> SighashCache<R> {
|
|||
Ok(TapSighashHash::from_engine(enc))
|
||||
}
|
||||
|
||||
/// Compute the BIP341 sighash for a script spend
|
||||
/// Computes the BIP341 sighash for a script spend.
|
||||
///
|
||||
/// Assumes the default `OP_CODESEPARATOR` position of `0xFFFFFFFF`. Custom values can be
|
||||
/// provided through the more fine-grained API of [`SighashCache::taproot_encode_signing_data_to`].
|
||||
|
@ -540,7 +542,7 @@ impl<R: Deref<Target=Transaction>> SighashCache<R> {
|
|||
Ok(TapSighashHash::from_engine(enc))
|
||||
}
|
||||
|
||||
/// Encode the BIP143 signing data for any flag type into a given object implementing a
|
||||
/// Encodes the BIP143 signing data for any flag type into a given object implementing a
|
||||
/// [`std::io::Write`] trait.
|
||||
pub fn segwit_encode_signing_data_to<Write: io::Write>(
|
||||
&mut self,
|
||||
|
@ -605,7 +607,7 @@ impl<R: Deref<Target=Transaction>> SighashCache<R> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Compute the BIP143 sighash for any flag type.
|
||||
/// Computes the BIP143 sighash for any flag type.
|
||||
pub fn segwit_signature_hash(
|
||||
&mut self,
|
||||
input_index: usize,
|
||||
|
@ -624,8 +626,8 @@ impl<R: Deref<Target=Transaction>> SighashCache<R> {
|
|||
Ok(Sighash::from_engine(enc))
|
||||
}
|
||||
|
||||
/// Encode the legacy signing data for any flag type into a given object implementing a
|
||||
/// [`std::io::Write`] trait. Internally calls [`Transaction::encode_signing_data_to`]
|
||||
/// Encodes the legacy signing data for any flag type into a given object implementing a
|
||||
/// [`std::io::Write`] trait. Internally calls [`Transaction::encode_signing_data_to`].
|
||||
pub fn legacy_encode_signing_data_to<Write: io::Write, U: Into<u32>>(
|
||||
&self,
|
||||
mut writer: Write,
|
||||
|
@ -645,7 +647,7 @@ impl<R: Deref<Target=Transaction>> SighashCache<R> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Computes the legacy sighash for any sighash type.
|
||||
/// Computes the legacy sighash for any `sighash_type`.
|
||||
pub fn legacy_signature_hash(
|
||||
&self,
|
||||
input_index: usize,
|
||||
|
@ -730,8 +732,8 @@ impl<R: Deref<Target=Transaction>> SighashCache<R> {
|
|||
}
|
||||
|
||||
impl<R: DerefMut<Target=Transaction>> SighashCache<R> {
|
||||
/// When the SighashCache is initialized with a mutable reference to a transaction instead of a
|
||||
/// regular reference, this method is available to allow modification to the witnesses.
|
||||
/// When the `SighashCache` is initialized with a mutable reference to a transaction instead of
|
||||
/// a regular reference, this method is available to allow modification to the witnesses.
|
||||
///
|
||||
/// This allows in-line signing such as
|
||||
/// ```
|
||||
|
@ -761,12 +763,12 @@ impl From<io::Error> for Error {
|
|||
}
|
||||
}
|
||||
|
||||
/// The `Annex` struct is a slice wrapper enforcing first byte to be `0x50`.
|
||||
/// The `Annex` struct is a slice wrapper enforcing first byte is `0x50`.
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub struct Annex<'a>(&'a [u8]);
|
||||
|
||||
impl<'a> Annex<'a> {
|
||||
/// Creates a new `Annex` struct checking the first byte is `0x50`
|
||||
/// Creates a new `Annex` struct checking the first byte is `0x50`.
|
||||
pub fn new(annex_bytes: &'a [u8]) -> Result<Self, Error> {
|
||||
if annex_bytes.first() == Some(&TAPROOT_ANNEX_PREFIX) {
|
||||
Ok(Annex(annex_bytes))
|
||||
|
@ -775,7 +777,7 @@ impl<'a> Annex<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the Annex bytes data (including first byte `0x50`)
|
||||
/// Returns the Annex bytes data (including first byte `0x50`).
|
||||
pub fn as_bytes(&self) -> &[u8] {
|
||||
&*self.0
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue