1#![allow(unused_doc_comments)] #![allow(unused_variables, unused_assignments, dead_code)] #![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 #[spec_locked("5.3", "ConnectBlock")]
168 #[blvm_spec_lock::ensures(result_0 == true || result_0 == false)]
169 pub fn validate_block(
170 &self,
171 block: &types::Block,
172 utxo_set: types::UtxoSet,
173 height: types::Natural,
174 ) -> error::Result<(types::ValidationResult, types::UtxoSet)> {
175 let witnesses: Vec<Vec<segwit::Witness>> =
177 block.transactions.iter().map(|_| Vec::new()).collect();
178 let network_time = std::time::SystemTime::now()
182 .duration_since(std::time::UNIX_EPOCH)
183 .unwrap_or(std::time::Duration::ZERO)
184 .as_secs();
185 let context = block::block_validation_context_for_connect_ibd(
186 None::<&[types::BlockHeader]>,
187 network_time,
188 types::Network::Mainnet,
189 );
190 let (result, new_utxo_set, _undo_log) =
191 block::connect_block(block, &witnesses, utxo_set, height, &context)?;
192 Ok((result, new_utxo_set))
193 }
194
195 #[spec_locked("5.3", "ConnectBlock")]
197 #[blvm_spec_lock::ensures(result_0 == true || result_0 == false)]
198 pub fn validate_block_with_time_context(
199 &self,
200 block: &types::Block,
201 witnesses: &[Vec<segwit::Witness>],
202 utxo_set: types::UtxoSet,
203 height: types::Natural,
204 time_context: Option<types::TimeContext>,
205 network: types::Network,
206 ) -> error::Result<(types::ValidationResult, types::UtxoSet)> {
207 let context = block::BlockValidationContext::from_time_context_and_network(
208 time_context,
209 network,
210 None,
211 );
212 let (result, new_utxo_set, _undo_log) =
213 block::connect_block(block, witnesses, utxo_set, height, &context)?;
214 Ok((result, new_utxo_set))
215 }
216
217 #[spec_locked("5.2", "VerifyScript")]
219 #[blvm_spec_lock::ensures(result == true || result == false)]
220 pub fn verify_script(
221 &self,
222 script_sig: &types::ByteString,
223 script_pubkey: &types::ByteString,
224 witness: Option<&types::ByteString>,
225 flags: u32,
226 ) -> error::Result<bool> {
227 script::verify_script(script_sig, script_pubkey, witness, flags)
228 }
229
230 #[spec_locked("7.2", "CheckProofOfWork")]
232 #[blvm_spec_lock::ensures(result == true || result == false)]
233 pub fn check_proof_of_work(&self, header: &types::BlockHeader) -> error::Result<bool> {
234 pow::check_proof_of_work(header)
235 }
236
237 #[spec_locked("6.1", "GetBlockSubsidy")]
239 #[blvm_spec_lock::ensures(result >= 0)]
240 #[blvm_spec_lock::axiom(result <= INITIAL_SUBSIDY)]
241 pub fn get_block_subsidy(&self, height: types::Natural) -> types::Integer {
242 economic::get_block_subsidy(height)
243 }
244
245 #[spec_locked("6.2", "TotalSupply")]
247 #[blvm_spec_lock::ensures(result >= 0)]
248 pub fn total_supply(&self, height: types::Natural) -> types::Integer {
249 economic::total_supply(height)
250 }
251
252 #[spec_locked("7.1", "GetNextWorkRequired")]
254 #[blvm_spec_lock::ensures(result >= 0)]
255 pub fn get_next_work_required(
256 &self,
257 current_header: &types::BlockHeader,
258 prev_headers: &[types::BlockHeader],
259 ) -> error::Result<types::Natural> {
260 pow::get_next_work_required(current_header, prev_headers)
261 }
262
263 #[spec_locked("9.1", "AcceptToMemoryPool")]
265 #[blvm_spec_lock::ensures(result == true || result == false)]
266 pub fn accept_to_memory_pool(
267 &self,
268 tx: &types::Transaction,
269 utxo_set: &types::UtxoSet,
270 mempool: &mempool::Mempool,
271 height: types::Natural,
272 time_context: Option<types::TimeContext>,
273 ) -> error::Result<mempool::MempoolResult> {
274 mempool::accept_to_memory_pool(tx, None, utxo_set, mempool, height, time_context)
275 }
276
277 #[spec_locked("9.2", "IsStandardTx")]
279 #[blvm_spec_lock::ensures(result == true || result == false)]
280 pub fn is_standard_tx(&self, tx: &types::Transaction) -> error::Result<bool> {
281 mempool::is_standard_tx(tx)
282 }
283
284 #[spec_locked("9.3", "ReplacementChecks")]
286 #[blvm_spec_lock::ensures(result == true || result == false)]
287 pub fn replacement_checks(
288 &self,
289 new_tx: &types::Transaction,
290 existing_tx: &types::Transaction,
291 utxo_set: &types::UtxoSet,
292 mempool: &mempool::Mempool,
293 ) -> error::Result<bool> {
294 mempool::replacement_checks(new_tx, existing_tx, utxo_set, mempool)
295 }
296
297 #[allow(clippy::too_many_arguments)]
299 #[spec_locked("12.1", "CreateNewBlock")]
300 #[blvm_spec_lock::ensures(result >= 0)]
301 pub fn create_new_block(
302 &self,
303 utxo_set: &types::UtxoSet,
304 mempool_txs: &[types::Transaction],
305 height: types::Natural,
306 prev_header: &types::BlockHeader,
307 prev_headers: &[types::BlockHeader],
308 coinbase_script: &types::ByteString,
309 coinbase_address: &types::ByteString,
310 ) -> error::Result<types::Block> {
311 mining::create_new_block(
312 utxo_set,
313 mempool_txs,
314 height,
315 prev_header,
316 prev_headers,
317 coinbase_script,
318 coinbase_address,
319 )
320 }
321
322 #[spec_locked("12.3", "MineBlock")]
324 #[blvm_spec_lock::ensures(result_0 >= 0)]
325 pub fn mine_block(
326 &self,
327 block: types::Block,
328 max_attempts: types::Natural,
329 ) -> error::Result<(types::Block, mining::MiningResult)> {
330 mining::mine_block(block, max_attempts)
331 }
332
333 #[allow(clippy::too_many_arguments)]
335 #[spec_locked("12.4", "BlockTemplate")]
336 #[blvm_spec_lock::ensures(result >= 0)]
337 pub fn create_block_template(
338 &self,
339 utxo_set: &types::UtxoSet,
340 mempool_txs: &[types::Transaction],
341 height: types::Natural,
342 prev_header: &types::BlockHeader,
343 prev_headers: &[types::BlockHeader],
344 coinbase_script: &types::ByteString,
345 coinbase_address: &types::ByteString,
346 ) -> error::Result<mining::BlockTemplate> {
347 mining::create_block_template(
348 utxo_set,
349 mempool_txs,
350 height,
351 prev_header,
352 prev_headers,
353 coinbase_script,
354 coinbase_address,
355 )
356 }
357
358 #[spec_locked("11.3")]
360 #[blvm_spec_lock::ensures(result >= 0)]
361 pub fn reorganize_chain(
362 &self,
363 new_chain: &[types::Block],
364 current_chain: &[types::Block],
365 current_utxo_set: types::UtxoSet,
366 current_height: types::Natural,
367 network: types::Network,
368 ) -> error::Result<reorganization::ReorganizationResult> {
369 reorganization::reorganize_chain(
370 new_chain,
371 current_chain,
372 current_utxo_set,
373 current_height,
374 network,
375 )
376 }
377
378 #[spec_locked("11.3", "ShouldReorganize")]
380 #[blvm_spec_lock::ensures(result == true || result == false)]
381 pub fn should_reorganize(
382 &self,
383 new_chain: &[types::Block],
384 current_chain: &[types::Block],
385 ) -> error::Result<bool> {
386 reorganization::should_reorganize(new_chain, current_chain)
387 }
388
389 #[spec_locked("11.1.1", "CalculateTransactionWeight")]
391 #[blvm_spec_lock::ensures(result >= 0)]
392 pub fn calculate_transaction_weight(
393 &self,
394 tx: &types::Transaction,
395 witness: Option<&segwit::Witness>,
396 ) -> error::Result<types::Natural> {
397 segwit::calculate_transaction_weight(tx, witness)
398 }
399
400 #[spec_locked("11.1.7", "ValidateSegWitBlock")]
402 #[blvm_spec_lock::ensures(result == true || result == false)]
403 pub fn validate_segwit_block(
404 &self,
405 block: &types::Block,
406 witnesses: &[segwit::Witness],
407 max_block_weight: types::Natural,
408 ) -> error::Result<bool> {
409 segwit::validate_segwit_block(block, witnesses, max_block_weight)
410 }
411
412 #[spec_locked("11.2.5", "ValidateTaprootTransaction")]
414 #[blvm_spec_lock::ensures(result == true || result == false)]
415 pub fn validate_taproot_transaction(
416 &self,
417 tx: &types::Transaction,
418 witness: Option<&segwit::Witness>,
419 ) -> error::Result<bool> {
420 taproot::validate_taproot_transaction(tx, witness)
421 }
422
423 #[spec_locked("11.2.1", "IsTaprootOutput")]
425 #[blvm_spec_lock::ensures(result == true || result == false)]
426 pub fn is_taproot_output(&self, output: &types::TransactionOutput) -> bool {
427 taproot::is_taproot_output(output)
428 }
429}
430
431#[cfg(test)]
432mod tests {
433 use crate::transaction::check_transaction;
434 use crate::types::Transaction;
435
436 #[test]
437 fn test_validate_transaction() {
438 let tx = Transaction {
439 version: 1,
440 inputs: vec![].into(),
441 outputs: vec![].into(),
442 lock_time: 0,
443 };
444 let result = check_transaction(&tx);
445 assert!(result.is_ok());
446 }
447}