Skip to main content

bitcoin_rs_consensus/
lib.rs

1//! Consensus validation surfaces for bitcoin-rs.
2//!
3//! The `kernel` feature enables a bitcoinkernel-backed authority path. With the
4//! feature off, the crate builds a portable Rust validation path that delegates
5//! script execution to `bitcoin-rs-script` and keeps consensus-facing rule checks
6//! in small, testable modules.
7
8#![forbid(unsafe_op_in_unsafe_fn)]
9
10/// BIP112 sequence-lock checks.
11pub mod bip112;
12/// BIP113 median-time-past checks.
13pub mod bip113;
14/// BIP141 segwit checks.
15pub mod bip141;
16/// BIP143 segwit-v0 sighash checks.
17pub mod bip143;
18/// BIP30 duplicate-transaction checks.
19pub mod bip30;
20/// BIP34 coinbase height checks.
21pub mod bip34;
22/// BIP341 taproot checks.
23pub mod bip341;
24/// BIP342 tapscript checks.
25pub mod bip342;
26/// BIP65 locktime checks.
27pub mod bip65;
28/// BIP66 DER-signature checks.
29pub mod bip66;
30/// BIP68 relative-locktime checks.
31pub mod bip68;
32/// BIP9 versionbits checks.
33pub mod bip9;
34/// Dual-path block connection.
35pub mod connect_block;
36/// Feature-gated bitcoinkernel wrapper.
37pub mod kernel;
38/// Portable Rust validator.
39pub mod rust_path;
40/// Block rule checks.
41pub mod verify_block;
42/// Transaction rule checks.
43pub mod verify_tx;
44
45pub use bip9::{DeploymentContext, DeploymentParams, DeploymentState, compute_state};
46pub use connect_block::connect_block_dual_path;
47pub use rust_path::{BlockState, RustValidator, TipState, UtxoView};
48pub use verify_block::{
49    BlockRuleContext, verify_block_rules, verify_block_rules_borrowed,
50    verify_block_rules_borrowed_contextual, verify_block_rules_borrowed_contextual_with_txids,
51    verify_block_rules_borrowed_contextual_with_txids_and_witness_hint,
52    verify_block_rules_contextual,
53};
54pub use verify_tx::{
55    is_final_tx, verify_coinbase_script_sig_size, verify_transaction, verify_transaction_borrowed,
56    verify_transaction_borrowed_non_script_with_mtp, verify_transaction_borrowed_with_mtp,
57    verify_transaction_with_mtp,
58};
59
60use thiserror::Error;
61
62/// Consensus validation error.
63#[derive(Debug, Error, Clone, PartialEq, Eq)]
64pub enum ConsensusError {
65    /// A transaction has no inputs.
66    #[error("transaction has no inputs")]
67    EmptyInputs,
68    /// A transaction has no outputs.
69    #[error("transaction has no outputs")]
70    EmptyOutputs,
71    /// Coinbase scriptSig length is outside the consensus-allowed 2..=100 byte range.
72    #[error("coinbase scriptSig length {len} outside allowed range 2..=100 bytes")]
73    CoinbaseScriptSigSize {
74        /// Observed coinbase scriptSig length in bytes.
75        len: usize,
76    },
77    /// A non-coinbase transaction contains a null previous output.
78    #[error("non-coinbase transaction input {input_index} spends a null outpoint")]
79    NullPrevout {
80        /// Input index containing the null outpoint.
81        input_index: usize,
82    },
83    /// A transaction spends the same previous output more than once.
84    #[error("transaction contains duplicate input {input_index}")]
85    DuplicateInput {
86        /// Input index that repeats an earlier outpoint.
87        input_index: usize,
88    },
89    /// A required UTXO was not present in the supplied view.
90    #[error("missing prevout for input {input_index}")]
91    MissingPrevout {
92        /// Input index whose previous output is unavailable.
93        input_index: usize,
94    },
95    /// Total output value exceeds Bitcoin's maximum money supply.
96    #[error("transaction output value exceeds max money")]
97    OutputValueOverflow,
98    /// Total input value is smaller than total output value.
99    #[error("transaction spends {input_value} sats but creates {output_value} sats")]
100    InputsLessThanOutputs {
101        /// Total input value in satoshis.
102        input_value: u64,
103        /// Total output value in satoshis.
104        output_value: u64,
105    },
106    /// Script verification failed.
107    #[error("script verification failed at input {input_index}: {reason}")]
108    Script {
109        /// Input index that failed script verification.
110        input_index: usize,
111        /// Script failure reason.
112        reason: String,
113    },
114    /// Sigop cost exceeds consensus maximum.
115    #[error("sigop cost {cost} exceeds max {max}")]
116    SigopsLimit {
117        /// Observed sigop cost.
118        cost: u32,
119        /// Consensus maximum.
120        max: u32,
121    },
122    /// Block has no transactions.
123    #[error("block has no transactions")]
124    EmptyBlock,
125    /// First transaction is not coinbase.
126    #[error("block first transaction is not coinbase")]
127    MissingCoinbase,
128    /// A non-first transaction is coinbase.
129    #[error("block transaction {tx_index} is coinbase outside position 0")]
130    ExtraCoinbase {
131        /// Transaction index.
132        tx_index: usize,
133    },
134    /// Block merkle tree has a duplicate subtree mutation.
135    #[error("block merkle tree contains a duplicate transaction mutation")]
136    MerkleMutation,
137    /// Block merkle root does not match transaction ids.
138    #[error("block merkle root mismatch")]
139    MerkleRoot,
140    /// Block witness commitment does not match.
141    #[error("block witness commitment mismatch")]
142    WitnessCommitment,
143    /// Block weight exceeds consensus maximum.
144    #[error("block weight {weight} exceeds max {max}")]
145    BlockWeight {
146        /// Observed block weight.
147        weight: u64,
148        /// Consensus maximum block weight.
149        max: u64,
150    },
151    /// BIP rule check failed.
152    #[error("{bip}: {reason}")]
153    Bip {
154        /// BIP identifier.
155        bip: &'static str,
156        /// Failure reason.
157        reason: String,
158    },
159    /// Kernel path failed or is not configured for the requested operation.
160    #[error("kernel validation failed: {0}")]
161    Kernel(String),
162    /// Consensus encoding or decoding failed.
163    #[error("consensus encoding failed: {0}")]
164    Encoding(String),
165}
166
167/// Maximum valid money supply in satoshis.
168pub const MAX_MONEY: u64 = 21_000_000 * 100_000_000;
169
170/// Maximum block sigop cost after segwit scaling.
171pub const MAX_BLOCK_SIGOPS_COST: u32 = 80_000;