1#![allow(unused_doc_comments)] #![allow(unused_variables, unused_assignments)] #![allow(
46 clippy::too_many_arguments, clippy::type_complexity, clippy::large_enum_variant, )]
50
51pub mod script;
52pub mod transaction;
53pub mod transaction_hash;
54
55use blvm_spec_lock::spec_locked;
56#[cfg(all(feature = "production", feature = "benchmarking"))]
57pub use config::{reset_assume_valid_height, set_assume_valid_height};
58#[cfg(feature = "production")]
59pub use script::batch_verify_signatures;
60#[cfg(all(feature = "production", feature = "benchmarking"))]
61pub use script::{
62 clear_all_caches, clear_hash_cache, clear_script_cache, clear_stack_pool, disable_caching,
63 reset_benchmarking_state,
64};
65#[cfg(all(feature = "production", feature = "benchmarking"))]
66pub use transaction_hash::clear_sighash_templates;
67
68pub use blvm_primitives::constants;
70pub use blvm_primitives::crypto;
71pub use blvm_primitives::opcodes;
72pub use blvm_primitives::serialization;
73pub use blvm_primitives::{error, types};
74pub use blvm_primitives::{tx_inputs, tx_outputs};
75pub use constants::*;
76pub use error::ConsensusError;
77pub use types::*;
78
79pub mod orange_paper_constants {
81 pub use crate::constants::{C, H, L_ELEMENT, L_OPS, L_SCRIPT, L_STACK, M_MAX, R, S_MAX, W_MAX};
82}
83
84#[doc(hidden)]
88pub mod orange_paper_property_helpers;
89
90pub mod config;
91
92pub mod activation;
93pub mod bip113;
94#[cfg(feature = "ctv")]
95pub mod bip119;
96#[cfg(any(feature = "csfs", feature = "production"))]
97pub mod bip348;
98pub mod bip_validation;
99pub mod block;
100#[cfg(all(feature = "production", feature = "rayon"))]
101pub mod checkqueue;
102pub mod economic;
103pub mod locktime;
104pub mod mempool;
105pub mod mining;
106pub mod optimizations;
107pub mod pow;
108pub mod reorganization;
109#[cfg(all(feature = "production", feature = "rayon"))]
110pub(crate) mod script_exec_cache;
111pub mod secp256k1_backend;
112pub mod segwit;
113pub mod sequence_locks;
114pub mod signet;
115pub mod sigop;
116pub(crate) mod spec_witnesses;
117pub mod taproot;
118pub mod utxo_overlay;
119pub mod version_bits;
120pub mod witness;
121
122pub mod test_utils;
125
126#[cfg(feature = "profile")]
127pub mod profile_log;
128#[cfg(all(feature = "production", feature = "profile"))]
129pub mod script_profile;
130
131#[derive(Debug, Clone, Copy, Default)]
136pub struct ConsensusProof;
137
138impl ConsensusProof {
139 pub fn new() -> Self {
141 Self
142 }
143
144 #[spec_locked("5.1", "CheckTransaction")]
146 #[blvm_spec_lock::ensures(result == true || result == false)]
147 pub fn validate_transaction(
148 &self,
149 tx: &types::Transaction,
150 ) -> error::Result<types::ValidationResult> {
151 transaction::check_transaction(tx)
152 }
153
154 #[spec_locked("5.1", "CheckTxInputs")]
156 #[blvm_spec_lock::ensures(result_0 == true || result_0 == false)]
157 pub fn validate_tx_inputs(
158 &self,
159 tx: &types::Transaction,
160 utxo_set: &types::UtxoSet,
161 height: types::Natural,
162 ) -> error::Result<(types::ValidationResult, types::Integer)> {
163 transaction::check_tx_inputs(tx, utxo_set, height)
164 }
165
166 #[deprecated(
172 since = "0.1.33",
173 note = "Use validate_block_with_time_context with explicit witnesses, network, and TimeContext"
174 )]
175 #[spec_locked("5.3", "ConnectBlock")]
176 #[blvm_spec_lock::ensures(result_0 == true || result_0 == false)]
177 pub fn validate_block(
178 &self,
179 block: &types::Block,
180 utxo_set: types::UtxoSet,
181 height: types::Natural,
182 ) -> error::Result<(types::ValidationResult, types::UtxoSet)> {
183 let witnesses: Vec<Vec<segwit::Witness>> =
185 block.transactions.iter().map(|_| Vec::new()).collect();
186 let network_time = std::time::SystemTime::now()
190 .duration_since(std::time::UNIX_EPOCH)
191 .unwrap_or(std::time::Duration::ZERO)
192 .as_secs();
193 let context = block::block_validation_context_for_connect_ibd(
194 None::<&[types::BlockHeader]>,
195 network_time,
196 types::Network::Mainnet,
197 );
198 let (result, new_utxo_set, _undo_log) =
199 block::connect_block(block, &witnesses, utxo_set, height, &context)?;
200 Ok((result, new_utxo_set))
201 }
202
203 #[spec_locked("5.3", "ConnectBlock")]
205 #[blvm_spec_lock::ensures(result_0 == true || result_0 == false)]
206 pub fn validate_block_with_time_context(
207 &self,
208 block: &types::Block,
209 witnesses: &[Vec<segwit::Witness>],
210 utxo_set: types::UtxoSet,
211 height: types::Natural,
212 time_context: Option<types::TimeContext>,
213 network: types::Network,
214 ) -> error::Result<(types::ValidationResult, types::UtxoSet)> {
215 let context = block::BlockValidationContext::from_time_context_and_network(
216 time_context,
217 network,
218 None,
219 );
220 let (result, new_utxo_set, _undo_log) =
221 block::connect_block(block, witnesses, utxo_set, height, &context)?;
222 Ok((result, new_utxo_set))
223 }
224
225 #[deprecated(
227 since = "0.1.33",
228 note = "Use verify_script_with_context via script module for witness-aware verification"
229 )]
230 #[spec_locked("5.2", "VerifyScript")]
231 #[blvm_spec_lock::ensures(result == true || result == false)]
232 pub fn verify_script(
233 &self,
234 script_sig: &types::ByteString,
235 script_pubkey: &types::ByteString,
236 witness: Option<&types::ByteString>,
237 flags: u32,
238 ) -> error::Result<bool> {
239 #[allow(deprecated)]
240 {
241 script::verify_script(script_sig, script_pubkey, witness, flags)
242 }
243 }
244
245 #[spec_locked("7.2", "CheckProofOfWork")]
247 #[blvm_spec_lock::ensures(result == true || result == false)]
248 pub fn check_proof_of_work(&self, header: &types::BlockHeader) -> error::Result<bool> {
249 pow::check_proof_of_work(header)
250 }
251
252 #[spec_locked("6.1", "GetBlockSubsidy")]
254 #[blvm_spec_lock::ensures(result >= 0)]
255 #[blvm_spec_lock::axiom(result <= INITIAL_SUBSIDY)]
256 pub fn get_block_subsidy(&self, height: types::Natural) -> types::Integer {
257 economic::get_block_subsidy(height)
258 }
259
260 #[spec_locked("6.2", "TotalSupply")]
262 #[blvm_spec_lock::ensures(result >= 0)]
263 pub fn total_supply(&self, height: types::Natural) -> types::Integer {
264 economic::total_supply(height)
265 }
266
267 #[spec_locked("7.1", "GetNextWorkRequired")]
269 #[blvm_spec_lock::ensures(result >= 0)]
270 pub fn get_next_work_required(
271 &self,
272 current_header: &types::BlockHeader,
273 prev_headers: &[types::BlockHeader],
274 ) -> error::Result<types::Natural> {
275 pow::get_next_work_required(current_header, prev_headers)
276 }
277
278 #[spec_locked("9.1", "AcceptToMemoryPool")]
280 #[blvm_spec_lock::ensures(result == true || result == false)]
281 pub fn accept_to_memory_pool(
282 &self,
283 tx: &types::Transaction,
284 utxo_set: &types::UtxoSet,
285 mempool: &mempool::Mempool,
286 height: types::Natural,
287 time_context: Option<types::TimeContext>,
288 network: types::Network,
289 ) -> error::Result<mempool::MempoolResult> {
290 mempool::accept_to_memory_pool(tx, None, utxo_set, mempool, height, time_context, network)
291 }
292
293 #[spec_locked("9.2", "IsStandardTx")]
295 #[blvm_spec_lock::ensures(result == true || result == false)]
296 pub fn is_standard_tx(&self, tx: &types::Transaction) -> error::Result<bool> {
297 mempool::is_standard_tx(tx)
298 }
299
300 #[spec_locked("9.3", "ReplacementChecks")]
302 #[blvm_spec_lock::ensures(result == true || result == false)]
303 pub fn replacement_checks(
304 &self,
305 new_tx: &types::Transaction,
306 existing_tx: &types::Transaction,
307 utxo_set: &types::UtxoSet,
308 mempool: &mempool::Mempool,
309 ) -> error::Result<bool> {
310 mempool::replacement_checks(new_tx, existing_tx, utxo_set, mempool)
311 }
312
313 #[allow(clippy::too_many_arguments)]
315 #[spec_locked("12.1", "CreateNewBlock")]
316 #[blvm_spec_lock::ensures(result >= 0)]
317 pub fn create_new_block(
318 &self,
319 utxo_set: &types::UtxoSet,
320 mempool_txs: &[types::Transaction],
321 height: types::Natural,
322 prev_header: &types::BlockHeader,
323 prev_headers: &[types::BlockHeader],
324 coinbase_script: &types::ByteString,
325 coinbase_address: &types::ByteString,
326 ) -> error::Result<types::Block> {
327 mining::create_new_block(
328 utxo_set,
329 mempool_txs,
330 height,
331 prev_header,
332 prev_headers,
333 coinbase_script,
334 coinbase_address,
335 )
336 }
337
338 #[allow(clippy::too_many_arguments)]
340 #[spec_locked("12.1", "CreateNewBlock")]
341 pub fn create_new_block_with_time(
342 &self,
343 utxo_set: &types::UtxoSet,
344 mempool_txs: &[types::Transaction],
345 height: types::Natural,
346 prev_header: &types::BlockHeader,
347 prev_headers: &[types::BlockHeader],
348 coinbase_script: &types::ByteString,
349 coinbase_address: &types::ByteString,
350 block_time: types::Natural,
351 network: types::Network,
352 mempool_witnesses: Option<&[Option<Vec<segwit::Witness>>]>,
353 ) -> error::Result<types::Block> {
354 mining::create_new_block_with_time(
355 utxo_set,
356 mempool_txs,
357 height,
358 prev_header,
359 prev_headers,
360 coinbase_script,
361 coinbase_address,
362 block_time,
363 network,
364 mempool_witnesses,
365 )
366 }
367
368 #[spec_locked("12.3", "MineBlock")]
370 #[blvm_spec_lock::ensures(result_0 >= 0)]
371 pub fn mine_block(
372 &self,
373 block: types::Block,
374 max_attempts: types::Natural,
375 ) -> error::Result<(types::Block, mining::MiningResult)> {
376 mining::mine_block(block, max_attempts)
377 }
378
379 #[allow(clippy::too_many_arguments)]
381 #[spec_locked("12.4", "BlockTemplate")]
382 #[blvm_spec_lock::ensures(result >= 0)]
383 pub fn create_block_template(
384 &self,
385 utxo_set: &types::UtxoSet,
386 mempool_txs: &[types::Transaction],
387 height: types::Natural,
388 prev_header: &types::BlockHeader,
389 prev_headers: &[types::BlockHeader],
390 coinbase_script: &types::ByteString,
391 coinbase_address: &types::ByteString,
392 network: types::Network,
393 mempool_witnesses: Option<&[Option<Vec<segwit::Witness>>]>,
394 ) -> error::Result<mining::BlockTemplate> {
395 mining::create_block_template(
396 utxo_set,
397 mempool_txs,
398 height,
399 prev_header,
400 prev_headers,
401 coinbase_script,
402 coinbase_address,
403 network,
404 mempool_witnesses,
405 )
406 }
407
408 #[deprecated(
410 since = "0.1.33",
411 note = "Use reorganize_chain_with_witnesses with explicit witness data for SegWit chains"
412 )]
413 #[spec_locked("11.3")]
414 #[blvm_spec_lock::ensures(result >= 0)]
415 pub fn reorganize_chain(
416 &self,
417 new_chain: &[types::Block],
418 current_chain: &[types::Block],
419 current_utxo_set: types::UtxoSet,
420 current_height: types::Natural,
421 network: types::Network,
422 ) -> error::Result<reorganization::ReorganizationResult> {
423 use crate::segwit::{Witness, is_segwit_transaction};
424 use crate::transaction::is_coinbase;
425
426 for block in new_chain {
427 for tx in &block.transactions {
428 if !is_coinbase(tx) && is_segwit_transaction(tx) {
429 return Err(error::ConsensusError::BlockValidation(
430 "reorganize_chain: SegWit transactions require reorganize_chain_with_witnesses"
431 .into(),
432 ));
433 }
434 }
435 }
436
437 let witnesses: Vec<Vec<Vec<Witness>>> = new_chain
438 .iter()
439 .map(|block| {
440 block
441 .transactions
442 .iter()
443 .map(|tx| tx.inputs.iter().map(|_| Vec::new()).collect())
444 .collect()
445 })
446 .collect();
447 let network_time = new_chain
448 .iter()
449 .map(|b| b.header.timestamp)
450 .max()
451 .unwrap_or(0)
452 .saturating_add(crate::constants::MAX_FUTURE_BLOCK_TIME);
453
454 reorganization::reorganize_chain_with_witnesses(
455 new_chain,
456 &witnesses,
457 None,
458 current_chain,
459 current_utxo_set,
460 current_height,
461 None::<fn(&types::Block) -> Option<Vec<segwit::Witness>>>,
462 None::<fn(types::Natural) -> Option<Vec<types::BlockHeader>>>,
463 None::<fn(&types::Hash) -> Option<reorganization::BlockUndoLog>>,
464 None::<fn(&types::Hash, &reorganization::BlockUndoLog) -> error::Result<()>>,
465 network_time,
466 network,
467 )
468 }
469
470 #[spec_locked("11.3")]
472 pub fn reorganize_chain_with_witnesses(
473 &self,
474 new_chain: &[types::Block],
475 new_chain_witnesses: &[Vec<Vec<segwit::Witness>>],
476 new_chain_headers: Option<&[types::BlockHeader]>,
477 current_chain: &[types::Block],
478 current_utxo_set: types::UtxoSet,
479 current_height: types::Natural,
480 network_time: types::Natural,
481 network: types::Network,
482 ) -> error::Result<reorganization::ReorganizationResult> {
483 reorganization::reorganize_chain_with_witnesses(
484 new_chain,
485 new_chain_witnesses,
486 new_chain_headers,
487 current_chain,
488 current_utxo_set,
489 current_height,
490 None::<fn(&types::Block) -> Option<Vec<segwit::Witness>>>,
491 None::<fn(types::Natural) -> Option<Vec<types::BlockHeader>>>,
492 None::<fn(&types::Hash) -> Option<reorganization::BlockUndoLog>>,
493 None::<fn(&types::Hash, &reorganization::BlockUndoLog) -> error::Result<()>>,
494 network_time,
495 network,
496 )
497 }
498
499 #[spec_locked("11.3", "ShouldReorganize")]
501 #[blvm_spec_lock::ensures(result == true || result == false)]
502 pub fn should_reorganize(
503 &self,
504 new_chain: &[types::Block],
505 current_chain: &[types::Block],
506 ) -> error::Result<bool> {
507 reorganization::should_reorganize(new_chain, current_chain)
508 }
509
510 #[spec_locked("11.1.1", "CalculateTransactionWeight")]
512 #[blvm_spec_lock::ensures(result >= 0)]
513 pub fn calculate_transaction_weight(
514 &self,
515 tx: &types::Transaction,
516 witness: Option<&segwit::Witness>,
517 ) -> error::Result<types::Natural> {
518 segwit::calculate_transaction_weight(tx, witness)
519 }
520
521 #[spec_locked("11.1.7", "ValidateSegWitBlock")]
523 #[blvm_spec_lock::ensures(result == true || result == false)]
524 pub fn validate_segwit_block(
525 &self,
526 block: &types::Block,
527 witnesses: &[segwit::Witness],
528 max_block_weight: types::Natural,
529 ) -> error::Result<bool> {
530 segwit::validate_segwit_block(block, witnesses, max_block_weight)
531 }
532
533 #[spec_locked("11.2.5", "ValidateTaprootTransaction")]
535 #[blvm_spec_lock::ensures(result == true || result == false)]
536 pub fn validate_taproot_transaction(
537 &self,
538 tx: &types::Transaction,
539 witness: Option<&segwit::Witness>,
540 ) -> error::Result<bool> {
541 taproot::validate_taproot_transaction(tx, witness)
542 }
543
544 #[spec_locked("11.2.1", "IsTaprootOutput")]
546 #[blvm_spec_lock::ensures(result == true || result == false)]
547 pub fn is_taproot_output(&self, output: &types::TransactionOutput) -> bool {
548 taproot::is_taproot_output(output)
549 }
550}
551
552#[cfg(test)]
553mod tests {
554 use crate::transaction::check_transaction;
555 use crate::types::Transaction;
556
557 #[test]
558 fn test_validate_transaction() {
559 let tx = Transaction {
560 version: 1,
561 inputs: vec![].into(),
562 outputs: vec![].into(),
563 lock_time: 0,
564 };
565 let result = check_transaction(&tx);
566 assert!(result.is_ok());
567 }
568}