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
55#[cfg(feature = "spec-lock")]
56use blvm_spec_lock::spec_locked;
57#[cfg(all(feature = "production", feature = "benchmarking"))]
58pub use config::{reset_assume_valid_height, set_assume_valid_height};
59#[cfg(feature = "production")]
60pub use script::batch_verify_signatures;
61#[cfg(all(feature = "production", feature = "benchmarking"))]
62pub use script::{
63 clear_all_caches, clear_hash_cache, clear_script_cache, clear_stack_pool, disable_caching,
64 reset_benchmarking_state,
65};
66#[cfg(all(feature = "production", feature = "benchmarking"))]
67pub use transaction_hash::clear_sighash_templates;
68
69pub use blvm_primitives::constants;
71pub use blvm_primitives::crypto;
72pub use blvm_primitives::opcodes;
73pub use blvm_primitives::serialization;
74pub use blvm_primitives::{error, types};
75pub use blvm_primitives::{tx_inputs, tx_outputs};
76pub use constants::*;
77pub use error::ConsensusError;
78pub use types::*;
79
80pub(crate) fn script_err_as_false(error: ConsensusError) -> error::Result<bool> {
82 match error {
83 ConsensusError::ScriptExecution(_) | ConsensusError::ScriptErrorWithCode { .. } => {
84 Ok(false)
85 }
86 other => Err(other),
87 }
88}
89
90pub mod orange_paper_constants {
92 pub use crate::constants::{C, H, L_ELEMENT, L_OPS, L_SCRIPT, L_STACK, M_MAX, R, S_MAX, W_MAX};
93}
94
95#[doc(hidden)]
99pub mod orange_paper_property_helpers;
100
101pub mod config;
102
103pub mod activation;
104pub mod bip113;
105#[cfg(feature = "ctv")]
106pub mod bip119;
107#[cfg(any(feature = "csfs", feature = "production"))]
108pub mod bip348;
109pub mod bip_validation;
110pub mod block;
111#[cfg(all(feature = "production", feature = "rayon"))]
112pub mod checkqueue;
113#[cfg(all(feature = "production", feature = "blvm-secp256k1"))]
114pub mod ecdsa_batch;
115pub mod ecdsa_timers;
116#[cfg(all(feature = "production", feature = "blvm-secp256k1"))]
117pub mod ecdsa_wave;
118pub mod economic;
119pub mod locktime;
120pub mod mempool;
121pub mod mining;
122pub mod optimizations;
123pub mod pow;
124pub mod reorganization;
125#[cfg(all(feature = "production", feature = "rayon"))]
126pub(crate) mod script_exec_cache;
127pub mod secp256k1_backend;
128pub mod segwit;
129pub mod sequence_locks;
130pub mod signet;
131pub mod sigop;
132pub(crate) mod spec_witnesses;
133pub mod taproot;
134pub mod utxo_overlay;
135pub mod version_bits;
136pub mod witness;
137
138pub mod test_utils;
141
142#[cfg(feature = "profile")]
143pub mod profile_log;
144#[cfg(all(feature = "production", feature = "profile"))]
145pub mod script_profile;
146
147#[derive(Debug, Clone, Copy, Default)]
152pub struct ConsensusProof;
153
154impl ConsensusProof {
155 pub fn new() -> Self {
157 Self
158 }
159
160 #[cfg_attr(feature = "spec-lock", spec_locked("5.1", "CheckTransaction"))]
162 #[cfg_attr(feature = "spec-lock", blvm_spec_lock::ensures(result == true || result == false))]
163 pub fn validate_transaction(
164 &self,
165 tx: &types::Transaction,
166 ) -> error::Result<types::ValidationResult> {
167 transaction::check_transaction(tx)
168 }
169
170 #[cfg_attr(feature = "spec-lock", spec_locked("5.1", "CheckTxInputs"))]
172 #[cfg_attr(feature = "spec-lock", blvm_spec_lock::ensures(result_0 == true || result_0 == false))]
173 pub fn validate_tx_inputs(
174 &self,
175 tx: &types::Transaction,
176 utxo_set: &types::UtxoSet,
177 height: types::Natural,
178 ) -> error::Result<(types::ValidationResult, types::Integer)> {
179 transaction::check_tx_inputs(tx, utxo_set, height)
180 }
181
182 #[deprecated(
188 since = "0.1.33",
189 note = "Use validate_block_with_time_context with explicit witnesses, network, and TimeContext"
190 )]
191 #[cfg_attr(feature = "spec-lock", spec_locked("5.3", "ConnectBlock"))]
192 #[cfg_attr(feature = "spec-lock", blvm_spec_lock::ensures(result_0 == true || result_0 == false))]
193 pub fn validate_block(
194 &self,
195 block: &types::Block,
196 utxo_set: types::UtxoSet,
197 height: types::Natural,
198 ) -> error::Result<(types::ValidationResult, types::UtxoSet)> {
199 let witnesses: Vec<Vec<segwit::Witness>> =
201 block.transactions.iter().map(|_| Vec::new()).collect();
202 let network_time = std::time::SystemTime::now()
206 .duration_since(std::time::UNIX_EPOCH)
207 .unwrap_or(std::time::Duration::ZERO)
208 .as_secs();
209 let context = block::block_validation_context_for_connect_ibd(
210 None::<&[types::BlockHeader]>,
211 network_time,
212 types::Network::Mainnet,
213 );
214 let (result, new_utxo_set, _undo_log) =
215 block::connect_block(block, &witnesses, utxo_set, height, &context)?;
216 Ok((result, new_utxo_set))
217 }
218
219 #[cfg_attr(feature = "spec-lock", spec_locked("5.3", "ConnectBlock"))]
221 #[cfg_attr(feature = "spec-lock", blvm_spec_lock::ensures(result_0 == true || result_0 == false))]
222 pub fn validate_block_with_time_context(
223 &self,
224 block: &types::Block,
225 witnesses: &[Vec<segwit::Witness>],
226 utxo_set: types::UtxoSet,
227 height: types::Natural,
228 time_context: Option<types::TimeContext>,
229 network: types::Network,
230 ) -> error::Result<(types::ValidationResult, types::UtxoSet)> {
231 let context = block::BlockValidationContext::from_time_context_and_network(
232 time_context,
233 network,
234 None,
235 );
236 let (result, new_utxo_set, _undo_log) =
237 block::connect_block(block, witnesses, utxo_set, height, &context)?;
238 Ok((result, new_utxo_set))
239 }
240
241 #[deprecated(
243 since = "0.1.33",
244 note = "Use verify_script_with_context via script module for witness-aware verification"
245 )]
246 #[cfg_attr(feature = "spec-lock", spec_locked("5.2", "VerifyScript"))]
247 #[cfg_attr(feature = "spec-lock", blvm_spec_lock::ensures(result == true || result == false))]
248 pub fn verify_script(
249 &self,
250 script_sig: &types::ByteString,
251 script_pubkey: &types::ByteString,
252 witness: Option<&types::ByteString>,
253 flags: u32,
254 ) -> error::Result<bool> {
255 #[allow(deprecated)]
256 {
257 script::verify_script(script_sig, script_pubkey, witness, flags)
258 }
259 }
260
261 #[cfg_attr(feature = "spec-lock", spec_locked("7.2", "CheckProofOfWork"))]
263 #[cfg_attr(feature = "spec-lock", blvm_spec_lock::ensures(result == true || result == false))]
264 pub fn check_proof_of_work(&self, header: &types::BlockHeader) -> error::Result<bool> {
265 pow::check_proof_of_work(header)
266 }
267
268 #[cfg_attr(feature = "spec-lock", spec_locked("6.1", "GetBlockSubsidy"))]
270 #[cfg_attr(feature = "spec-lock", blvm_spec_lock::ensures(result >= 0))]
271 #[cfg_attr(feature = "spec-lock", blvm_spec_lock::axiom(result <= INITIAL_SUBSIDY))]
272 pub fn get_block_subsidy(&self, height: types::Natural) -> types::Integer {
273 economic::get_block_subsidy(height)
274 }
275
276 pub fn get_block_subsidy_for_network(
278 &self,
279 height: types::Natural,
280 network: types::Network,
281 ) -> types::Integer {
282 economic::get_block_subsidy_for_network(height, network)
283 }
284
285 #[cfg_attr(feature = "spec-lock", spec_locked("6.2", "TotalSupply"))]
287 #[cfg_attr(feature = "spec-lock", blvm_spec_lock::ensures(result >= 0))]
288 pub fn total_supply(&self, height: types::Natural) -> types::Integer {
289 economic::total_supply(height)
290 }
291
292 #[cfg_attr(feature = "spec-lock", spec_locked("7.1", "GetNextWorkRequired"))]
294 #[cfg_attr(feature = "spec-lock", blvm_spec_lock::ensures(result >= 0))]
295 pub fn get_next_work_required(
296 &self,
297 current_header: &types::BlockHeader,
298 prev_headers: &[types::BlockHeader],
299 ) -> error::Result<types::Natural> {
300 pow::get_next_work_required(current_header, prev_headers)
301 }
302
303 pub fn accept_to_memory_pool(
305 &self,
306 tx: &types::Transaction,
307 utxo_set: &types::UtxoSet,
308 mempool: &mempool::Mempool,
309 height: types::Natural,
310 time_context: Option<types::TimeContext>,
311 network: types::Network,
312 ) -> error::Result<mempool::MempoolResult> {
313 self.accept_to_memory_pool_with_witness(
314 tx,
315 None,
316 utxo_set,
317 mempool,
318 height,
319 time_context,
320 network,
321 )
322 }
323
324 pub fn accept_to_memory_pool_with_witness(
326 &self,
327 tx: &types::Transaction,
328 witnesses: Option<&[segwit::Witness]>,
329 utxo_set: &types::UtxoSet,
330 mempool: &mempool::Mempool,
331 height: types::Natural,
332 time_context: Option<types::TimeContext>,
333 network: types::Network,
334 ) -> error::Result<mempool::MempoolResult> {
335 mempool::accept_to_memory_pool(
336 tx,
337 witnesses,
338 utxo_set,
339 mempool,
340 height,
341 time_context,
342 network,
343 None,
344 )
345 }
346
347 pub fn is_standard_tx(&self, tx: &types::Transaction) -> error::Result<bool> {
349 mempool::is_standard_tx(tx)
350 }
351
352 pub fn replacement_checks(
354 &self,
355 new_tx: &types::Transaction,
356 existing_tx: &types::Transaction,
357 utxo_set: &types::UtxoSet,
358 mempool: &mempool::Mempool,
359 ) -> error::Result<bool> {
360 mempool::replacement_checks(new_tx, existing_tx, utxo_set, mempool)
361 }
362
363 #[allow(clippy::too_many_arguments)]
365 pub fn create_new_block(
366 &self,
367 utxo_set: &types::UtxoSet,
368 mempool_txs: &[types::Transaction],
369 height: types::Natural,
370 prev_header: &types::BlockHeader,
371 prev_headers: &[types::BlockHeader],
372 coinbase_script: &types::ByteString,
373 coinbase_address: &types::ByteString,
374 ) -> error::Result<types::Block> {
375 mining::create_new_block(
376 utxo_set,
377 mempool_txs,
378 height,
379 prev_header,
380 prev_headers,
381 coinbase_script,
382 coinbase_address,
383 )
384 }
385
386 #[allow(clippy::too_many_arguments)]
388 pub fn create_new_block_with_time(
389 &self,
390 utxo_set: &types::UtxoSet,
391 mempool_txs: &[types::Transaction],
392 height: types::Natural,
393 prev_header: &types::BlockHeader,
394 prev_headers: &[types::BlockHeader],
395 coinbase_script: &types::ByteString,
396 coinbase_address: &types::ByteString,
397 block_time: types::Natural,
398 network: types::Network,
399 mempool_witnesses: Option<&[Option<Vec<segwit::Witness>>]>,
400 ) -> error::Result<types::Block> {
401 mining::create_new_block_with_time(
402 utxo_set,
403 mempool_txs,
404 height,
405 prev_header,
406 prev_headers,
407 coinbase_script,
408 coinbase_address,
409 block_time,
410 network,
411 mempool_witnesses,
412 )
413 }
414
415 pub fn mine_block(
417 &self,
418 block: types::Block,
419 max_attempts: types::Natural,
420 ) -> error::Result<(types::Block, mining::MiningResult)> {
421 mining::mine_block(block, max_attempts)
422 }
423
424 #[allow(clippy::too_many_arguments)]
426 pub fn create_block_template(
427 &self,
428 utxo_set: &types::UtxoSet,
429 mempool_txs: &[types::Transaction],
430 height: types::Natural,
431 prev_header: &types::BlockHeader,
432 prev_headers: &[types::BlockHeader],
433 coinbase_script: &types::ByteString,
434 coinbase_address: &types::ByteString,
435 network: types::Network,
436 mempool_witnesses: Option<&[Option<Vec<segwit::Witness>>]>,
437 ) -> error::Result<mining::BlockTemplate> {
438 mining::create_block_template(
439 utxo_set,
440 mempool_txs,
441 height,
442 prev_header,
443 prev_headers,
444 coinbase_script,
445 coinbase_address,
446 network,
447 mempool_witnesses,
448 )
449 }
450
451 #[allow(clippy::too_many_arguments)]
454 pub fn create_block_template_with_outputs(
455 &self,
456 utxo_set: &types::UtxoSet,
457 mempool_txs: &[types::Transaction],
458 height: types::Natural,
459 prev_header: &types::BlockHeader,
460 prev_headers: &[types::BlockHeader],
461 coinbase_script: &types::ByteString,
462 coinbase_outputs: &[(types::Integer, types::ByteString)],
463 network: types::Network,
464 mempool_witnesses: Option<&[Option<Vec<segwit::Witness>>]>,
465 ) -> error::Result<mining::BlockTemplate> {
466 mining::create_block_template_with_outputs(
467 utxo_set,
468 mempool_txs,
469 height,
470 prev_header,
471 prev_headers,
472 coinbase_script,
473 coinbase_outputs,
474 network,
475 mempool_witnesses,
476 )
477 }
478
479 #[allow(clippy::too_many_arguments)]
481 pub fn create_block_template_declared(
482 &self,
483 utxo_set: &types::UtxoSet,
484 mempool_txs: &[types::Transaction],
485 declared_txids: &[types::Hash],
486 height: types::Natural,
487 prev_header: &types::BlockHeader,
488 prev_headers: &[types::BlockHeader],
489 coinbase_script: &types::ByteString,
490 coinbase_outputs: &[(types::Integer, types::ByteString)],
491 network: types::Network,
492 mempool_witnesses: Option<&[Option<Vec<segwit::Witness>>]>,
493 ) -> error::Result<mining::BlockTemplate> {
494 mining::create_block_template_declared(
495 utxo_set,
496 mempool_txs,
497 declared_txids,
498 height,
499 prev_header,
500 prev_headers,
501 coinbase_script,
502 coinbase_outputs,
503 network,
504 mempool_witnesses,
505 )
506 }
507
508 #[deprecated(
510 since = "0.1.33",
511 note = "Use reorganize_chain_with_witnesses with explicit witness data for SegWit chains"
512 )]
513 #[cfg_attr(feature = "spec-lock", spec_locked("11.3"))]
514 #[cfg_attr(feature = "spec-lock", blvm_spec_lock::ensures(result >= 0))]
515 pub fn reorganize_chain(
516 &self,
517 new_chain: &[types::Block],
518 current_chain: &[types::Block],
519 current_utxo_set: types::UtxoSet,
520 current_height: types::Natural,
521 network: types::Network,
522 ) -> error::Result<reorganization::ReorganizationResult> {
523 use crate::segwit::{Witness, is_segwit_transaction};
524 use crate::transaction::is_coinbase;
525
526 for block in new_chain {
527 for tx in &block.transactions {
528 if !is_coinbase(tx) && is_segwit_transaction(tx) {
529 return Err(error::ConsensusError::BlockValidation(
530 "reorganize_chain: SegWit transactions require reorganize_chain_with_witnesses"
531 .into(),
532 ));
533 }
534 }
535 }
536
537 let witnesses: Vec<Vec<Vec<Witness>>> = new_chain
538 .iter()
539 .map(|block| {
540 block
541 .transactions
542 .iter()
543 .map(|tx| tx.inputs.iter().map(|_| Vec::new()).collect())
544 .collect()
545 })
546 .collect();
547 let network_time = new_chain
548 .iter()
549 .map(|b| b.header.timestamp)
550 .max()
551 .unwrap_or(0)
552 .saturating_add(crate::constants::MAX_FUTURE_BLOCK_TIME);
553
554 reorganization::reorganize_chain_with_witnesses(
555 new_chain,
556 &witnesses,
557 None,
558 current_chain,
559 current_utxo_set,
560 current_height,
561 None::<fn(&types::Block) -> Option<Vec<segwit::Witness>>>,
562 None::<fn(types::Natural) -> Option<Vec<types::BlockHeader>>>,
563 None::<fn(&types::Hash) -> Option<reorganization::BlockUndoLog>>,
564 None::<fn(&types::Hash, &reorganization::BlockUndoLog) -> error::Result<()>>,
565 network_time,
566 network,
567 None,
568 )
569 }
570
571 #[cfg_attr(feature = "spec-lock", spec_locked("11.3"))]
573 pub fn reorganize_chain_with_witnesses(
574 &self,
575 new_chain: &[types::Block],
576 new_chain_witnesses: &[Vec<Vec<segwit::Witness>>],
577 new_chain_headers: Option<&[types::BlockHeader]>,
578 current_chain: &[types::Block],
579 current_utxo_set: types::UtxoSet,
580 current_height: types::Natural,
581 network_time: types::Natural,
582 network: types::Network,
583 ) -> error::Result<reorganization::ReorganizationResult> {
584 reorganization::reorganize_chain_with_witnesses(
585 new_chain,
586 new_chain_witnesses,
587 new_chain_headers,
588 current_chain,
589 current_utxo_set,
590 current_height,
591 None::<fn(&types::Block) -> Option<Vec<segwit::Witness>>>,
592 None::<fn(types::Natural) -> Option<Vec<types::BlockHeader>>>,
593 None::<fn(&types::Hash) -> Option<reorganization::BlockUndoLog>>,
594 None::<fn(&types::Hash, &reorganization::BlockUndoLog) -> error::Result<()>>,
595 network_time,
596 network,
597 None,
598 )
599 }
600
601 #[cfg_attr(feature = "spec-lock", spec_locked("11.3", "ShouldReorganize"))]
603 #[cfg_attr(feature = "spec-lock", blvm_spec_lock::ensures(result == true || result == false))]
604 pub fn should_reorganize(
605 &self,
606 new_chain: &[types::Block],
607 current_chain: &[types::Block],
608 ) -> error::Result<bool> {
609 reorganization::should_reorganize(new_chain, current_chain)
610 }
611
612 #[cfg_attr(
614 feature = "spec-lock",
615 spec_locked("11.1.1", "CalculateTransactionWeight")
616 )]
617 #[cfg_attr(feature = "spec-lock", blvm_spec_lock::ensures(result >= 0))]
618 pub fn calculate_transaction_weight(
619 &self,
620 tx: &types::Transaction,
621 witness: Option<&segwit::Witness>,
622 ) -> error::Result<types::Natural> {
623 segwit::calculate_transaction_weight(tx, witness)
624 }
625
626 #[cfg_attr(feature = "spec-lock", spec_locked("11.1.7", "ValidateSegWitBlock"))]
628 #[cfg_attr(feature = "spec-lock", blvm_spec_lock::ensures(result == true || result == false))]
629 pub fn validate_segwit_block(
630 &self,
631 block: &types::Block,
632 witnesses: &[segwit::Witness],
633 max_block_weight: types::Natural,
634 ) -> error::Result<bool> {
635 segwit::validate_segwit_block(block, witnesses, max_block_weight)
636 }
637
638 #[cfg_attr(
640 feature = "spec-lock",
641 spec_locked("11.2.5", "ValidateTaprootTransaction")
642 )]
643 #[cfg_attr(feature = "spec-lock", blvm_spec_lock::ensures(result == true || result == false))]
644 pub fn validate_taproot_transaction(
645 &self,
646 tx: &types::Transaction,
647 witness: Option<&segwit::Witness>,
648 ) -> error::Result<bool> {
649 taproot::validate_taproot_transaction(tx, witness)
650 }
651
652 #[cfg_attr(feature = "spec-lock", spec_locked("11.2.1", "IsTaprootOutput"))]
654 #[cfg_attr(feature = "spec-lock", blvm_spec_lock::ensures(result == true || result == false))]
655 pub fn is_taproot_output(&self, output: &types::TransactionOutput) -> bool {
656 taproot::is_taproot_output(output)
657 }
658}
659
660#[cfg(test)]
661mod tests {
662 use crate::transaction::check_transaction;
663 use crate::types::Transaction;
664
665 #[test]
666 fn test_validate_transaction() {
667 let tx = Transaction {
668 version: 1,
669 inputs: vec![].into(),
670 outputs: vec![].into(),
671 lock_time: 0,
672 };
673 let result = check_transaction(&tx);
674 assert!(result.is_ok());
675 }
676}