1use serde::{Deserialize, Serialize};
18
19pub use blvm_consensus::config::NetworkMessageLimits;
22pub use blvm_consensus::error::{ConsensusError, Result as ConsensusResult};
23pub use blvm_consensus::types::{
24 Block, BlockHeader, ByteString, Hash, Integer, Natural, OutPoint, Transaction,
25 TransactionInput, TransactionOutput, UtxoSet, ValidationResult, Witness, UTXO,
26};
27pub use blvm_consensus::ConsensusProof;
28
29#[cfg(all(feature = "production", feature = "benchmarking"))]
30pub use blvm_consensus::config::{reset_assume_valid_height, set_assume_valid_height};
31pub use blvm_consensus::{
33 BIP112_CSV_ACTIVATION_MAINNET, BIP112_CSV_ACTIVATION_REGTEST, BIP112_CSV_ACTIVATION_TESTNET,
34 GENESIS_BLOCK_HASH_INTERNAL, SEGWIT_ACTIVATION_MAINNET, SEGWIT_ACTIVATION_TESTNET,
35 TAPROOT_ACTIVATION_MAINNET, TAPROOT_ACTIVATION_TESTNET,
36};
37
38#[cfg(feature = "production")]
40pub use smallvec;
41#[cfg(feature = "production")]
43pub use lru;
44#[cfg(feature = "production")]
45pub use rayon;
46
47#[macro_export]
50macro_rules! profile_log {
51 ($($arg:tt)*) => {
52 ::blvm_consensus::profile_log!($($arg)*)
53 };
54}
55
56pub use error::{ProtocolError, Result};
58
59pub mod mempool {
61 pub use blvm_consensus::mempool::*;
62}
63pub mod segwit {
64 pub use blvm_consensus::segwit::*;
65}
66pub mod block {
67 pub use blvm_consensus::block::*;
68
69 use crate::types::{BlockHeader, Network};
70
71 #[inline]
75 pub fn block_validation_context_for_connect_ibd<H: AsRef<BlockHeader>>(
76 recent_headers: Option<&[H]>,
77 network_time: u64,
78 network: Network,
79 ) -> BlockValidationContext {
80 BlockValidationContext::from_connect_block_ibd_args(
81 recent_headers,
82 network_time,
83 network,
84 None,
85 None,
86 )
87 }
88}
89pub mod mining {
90 pub use blvm_consensus::mining::*;
91}
92pub mod pow {
93 pub use blvm_consensus::pow::*;
94}
95
96pub mod witness {
97 pub use blvm_consensus::witness::*;
98}
99
100pub mod crypto {
101 pub use blvm_consensus::crypto::*;
102}
103
104pub mod transaction {
105 pub use blvm_consensus::transaction::*;
106}
107
108pub mod script {
110 pub use blvm_consensus::script::*;
111}
112
113pub mod transaction_hash {
115 pub use blvm_consensus::transaction_hash::*;
116}
117
118#[cfg(feature = "production")]
120pub mod optimizations {
121 pub use blvm_consensus::optimizations::*;
122}
123
124pub mod constants {
126 pub use blvm_consensus::constants::*;
127}
128
129pub mod bip113 {
130 pub use blvm_consensus::bip113::*;
131}
132
133pub mod bip_validation {
134 pub use blvm_consensus::bip_validation::*;
135}
136
137pub mod utxo_overlay {
138 pub use blvm_consensus::utxo_overlay::*;
139}
140
141pub mod version_bits {
142 pub use blvm_consensus::version_bits::*;
143}
144
145pub mod activation {
146 pub use blvm_consensus::activation::*;
147}
148
149pub mod consensus_config {
151 pub use blvm_consensus::config::*;
152}
153
154#[cfg(feature = "test-utils")]
155pub mod test_utils {
156 pub use blvm_consensus::test_utils::*;
157}
158
159pub use blvm_consensus::opcodes;
161
162pub mod sigop {
163 pub use blvm_consensus::sigop::*;
164}
165
166#[cfg(feature = "utxo-commitments")]
167pub mod utxo_commitments;
168
169pub mod spam_filter;
171pub mod serialization {
172 pub use blvm_consensus::serialization::*;
173}
174pub mod commons;
175pub mod network;
176pub mod node_tcp;
178
179pub use node_tcp::{ProtocolMessage, TcpFramedParser};
180pub mod p2p_commands;
181pub mod p2p_frame;
182pub mod p2p_framing;
183pub mod service_flags;
184pub mod varint;
185
186#[cfg(all(
188 feature = "bip324",
189 any(target_arch = "x86_64", target_arch = "aarch64")
190))]
191pub mod v2_transport;
192
193pub use commons::{
195 BanListMessage,
196 FilterPreferences,
198 FilteredBlockMessage,
200 GetBanListMessage,
201 GetFilteredBlockMessage,
202 GetUTXOProofMessage,
204 GetUTXOSetMessage,
205 UTXOCommitment,
207 UTXOProofMessage,
208 UTXOSetMessage,
209};
210pub use config::{
211 ProtocolConfig, ProtocolFeaturesConfig, ProtocolValidationConfig, ServiceFlagsConfig,
212};
213pub use network::{BlockMessage, CompactBlockMessage, TxMessage};
214pub use service_flags::{commons as service_flags_commons, standard as service_flags_standard};
215pub mod wire;
217
218#[cfg(test)]
219mod bip155_serialization_tests;
220pub mod types {
221 pub use blvm_consensus::types::*;
222}
223#[cfg(feature = "production")]
225pub use blvm_consensus::tx_inputs;
226#[cfg(not(feature = "production"))]
227pub use blvm_consensus::tx_inputs;
228#[cfg(feature = "production")]
229pub use blvm_consensus::tx_outputs;
230#[cfg(not(feature = "production"))]
231pub use blvm_consensus::tx_outputs;
232pub mod error;
233
234pub use economic::EconomicParameters;
236pub use features::{ActivationMethod, FeatureActivation, FeatureContext, FeatureRegistry};
237
238pub mod config;
239pub mod economic;
240pub mod features;
241pub mod genesis;
242pub mod network_params;
243pub mod validation;
244pub mod variants;
245
246pub mod address; #[cfg(feature = "ctv")]
249pub mod bip119 {
250 pub use blvm_consensus::bip119::*;
251}
252pub mod bip152; pub mod bip157; pub mod bip158; pub mod fibre;
256pub mod payment; pub mod time;
258
259pub struct BitcoinProtocolEngine {
264 consensus: ConsensusProof,
265 protocol_version: ProtocolVersion,
266 network_params: NetworkParameters,
267 config: ProtocolConfig,
268}
269
270#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
272pub enum ProtocolVersion {
273 BitcoinV1,
275 Testnet3,
277 Regtest,
279}
280
281#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
283pub struct NetworkParameters {
284 pub magic_bytes: [u8; 4],
286 pub default_port: u16,
288 pub genesis_block: Block,
290 pub max_target: u32,
292 pub halving_interval: u64,
294 pub network_name: String,
296 pub is_testnet: bool,
298}
299
300impl BitcoinProtocolEngine {
301 pub fn new(version: ProtocolVersion) -> Result<Self> {
303 Self::with_config(version, ProtocolConfig::default())
304 }
305
306 pub fn with_config(version: ProtocolVersion, config: ProtocolConfig) -> Result<Self> {
308 let consensus = ConsensusProof::new();
309 let network_params = NetworkParameters::for_version(version)?;
310
311 Ok(BitcoinProtocolEngine {
312 consensus,
313 protocol_version: version,
314 network_params,
315 config,
316 })
317 }
318
319 pub fn get_config(&self) -> &ProtocolConfig {
321 &self.config
322 }
323
324 pub fn get_config_mut(&mut self) -> &mut ProtocolConfig {
326 &mut self.config
327 }
328
329 pub fn get_protocol_version(&self) -> ProtocolVersion {
331 self.protocol_version
332 }
333
334 pub fn get_network_params(&self) -> &NetworkParameters {
336 &self.network_params
337 }
338
339 pub fn validate_block(
341 &self,
342 block: &Block,
343 utxos: &UtxoSet,
344 height: u64,
345 ) -> Result<ValidationResult> {
346 let (result, _) = self
347 .consensus
348 .validate_block(block, utxos.clone(), height)
349 .map_err(ProtocolError::from)?;
350 Ok(result)
351 }
352
353 pub fn validate_transaction(&self, tx: &Transaction) -> Result<ValidationResult> {
355 self.consensus
356 .validate_transaction(tx)
357 .map_err(ProtocolError::from)
358 }
359
360 pub fn validate_and_connect_block(
418 &self,
419 block: &Block,
420 witnesses: &[Vec<segwit::Witness>], utxos: &UtxoSet,
424 height: u64,
425 recent_headers: Option<&[BlockHeader]>,
426 context: &validation::ProtocolValidationContext,
427 ) -> Result<(ValidationResult, UtxoSet)> {
428 let protocol_result = self.validate_block_with_protocol(block, utxos, height, context)?;
430 if !matches!(protocol_result, ValidationResult::Valid) {
431 return Ok((protocol_result, utxos.clone()));
432 }
433
434 let network = match self.protocol_version {
437 ProtocolVersion::BitcoinV1 => types::Network::Mainnet,
438 ProtocolVersion::Testnet3 => types::Network::Testnet,
439 ProtocolVersion::Regtest => types::Network::Regtest,
440 };
441 let network_time = crate::time::current_timestamp();
442 let context = crate::block::block_validation_context_for_connect_ibd(
443 recent_headers,
444 network_time,
445 network,
446 );
447 let (result, new_utxo_set, _undo_log) = blvm_consensus::block::connect_block(
448 block,
449 witnesses,
450 utxos.clone(),
451 height,
452 &context,
453 )?;
454
455 Ok((result, new_utxo_set))
456 }
457
458 pub fn supports_feature(&self, feature: &str) -> bool {
460 match self.protocol_version {
461 ProtocolVersion::BitcoinV1 => {
462 matches!(feature, "segwit" | "taproot" | "rbf" | "ctv")
463 }
464 ProtocolVersion::Testnet3 => {
465 matches!(feature, "segwit" | "taproot" | "rbf" | "ctv")
466 }
467 ProtocolVersion::Regtest => {
468 matches!(
469 feature,
470 "segwit" | "taproot" | "rbf" | "ctv" | "fast_mining"
471 )
472 }
473 }
474 }
475
476 pub fn is_feature_active(&self, feature: &str, height: u64, timestamp: u64) -> bool {
478 let registry = features::FeatureRegistry::for_protocol(self.protocol_version);
479 registry.is_feature_active(feature, height, timestamp)
480 }
481
482 pub fn get_economic_parameters(&self) -> economic::EconomicParameters {
484 economic::EconomicParameters::for_protocol(self.protocol_version)
485 }
486
487 pub fn get_feature_registry(&self) -> features::FeatureRegistry {
489 features::FeatureRegistry::for_protocol(self.protocol_version)
490 }
491
492 pub fn feature_context(&self, height: u64, timestamp: u64) -> features::FeatureContext {
495 let registry = features::FeatureRegistry::for_protocol(self.protocol_version);
496 registry.create_context(height, timestamp)
497 }
498}
499
500impl NetworkParameters {
501 pub fn for_version(version: ProtocolVersion) -> Result<Self> {
503 match version {
504 ProtocolVersion::BitcoinV1 => Self::mainnet(),
505 ProtocolVersion::Testnet3 => Self::testnet(),
506 ProtocolVersion::Regtest => Self::regtest(),
507 }
508 }
509
510 pub fn mainnet() -> Result<Self> {
512 Ok(NetworkParameters {
513 magic_bytes: [0xf9, 0xbe, 0xb4, 0xd9], default_port: 8333,
515 genesis_block: genesis::mainnet_genesis(),
516 max_target: 0x1d00ffff,
517 halving_interval: 210000,
518 network_name: "mainnet".to_string(),
519 is_testnet: false,
520 })
521 }
522
523 pub fn testnet() -> Result<Self> {
525 Ok(NetworkParameters {
526 magic_bytes: [0x0b, 0x11, 0x09, 0x07], default_port: 18333,
528 genesis_block: genesis::testnet_genesis(),
529 max_target: 0x1d00ffff,
530 halving_interval: 210000,
531 network_name: "testnet".to_string(),
532 is_testnet: true,
533 })
534 }
535
536 pub fn regtest() -> Result<Self> {
538 Ok(NetworkParameters {
539 magic_bytes: [0xfa, 0xbf, 0xb5, 0xda], default_port: 18444,
541 genesis_block: genesis::regtest_genesis(),
542 max_target: 0x207fffff, halving_interval: 150, network_name: "regtest".to_string(),
545 is_testnet: true,
546 })
547 }
548}
549
550#[cfg(test)]
551mod tests {
552 use super::*;
553 use blvm_consensus::types::{BlockHeader, OutPoint, TransactionInput, TransactionOutput};
554
555 #[test]
556 fn test_blvm_protocol_creation() {
557 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
558 assert_eq!(engine.get_protocol_version(), ProtocolVersion::BitcoinV1);
559 assert_eq!(engine.get_network_params().network_name, "mainnet");
560 }
561
562 #[test]
563 fn test_blvm_protocol_creation_all_variants() {
564 let mainnet = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
566 assert_eq!(mainnet.get_protocol_version(), ProtocolVersion::BitcoinV1);
567 assert_eq!(mainnet.get_network_params().network_name, "mainnet");
568 assert!(!mainnet.get_network_params().is_testnet);
569
570 let testnet = BitcoinProtocolEngine::new(ProtocolVersion::Testnet3).unwrap();
572 assert_eq!(testnet.get_protocol_version(), ProtocolVersion::Testnet3);
573 assert_eq!(testnet.get_network_params().network_name, "testnet");
574 assert!(testnet.get_network_params().is_testnet);
575
576 let regtest = BitcoinProtocolEngine::new(ProtocolVersion::Regtest).unwrap();
578 assert_eq!(regtest.get_protocol_version(), ProtocolVersion::Regtest);
579 assert_eq!(regtest.get_network_params().network_name, "regtest");
580 assert!(regtest.get_network_params().is_testnet);
581 }
582
583 #[test]
584 fn test_network_parameters() {
585 let mainnet = NetworkParameters::mainnet().unwrap();
586 assert_eq!(mainnet.magic_bytes, [0xf9, 0xbe, 0xb4, 0xd9]);
587 assert_eq!(mainnet.default_port, 8333);
588 assert!(!mainnet.is_testnet);
589
590 let testnet = NetworkParameters::testnet().unwrap();
591 assert_eq!(testnet.magic_bytes, [0x0b, 0x11, 0x09, 0x07]);
592 assert_eq!(testnet.default_port, 18333);
593 assert!(testnet.is_testnet);
594
595 let regtest = NetworkParameters::regtest().unwrap();
596 assert_eq!(regtest.magic_bytes, [0xfa, 0xbf, 0xb5, 0xda]);
597 assert_eq!(regtest.default_port, 18444);
598 assert!(regtest.is_testnet);
599 }
600
601 #[test]
602 fn test_network_parameters_consistency() {
603 let mainnet = NetworkParameters::mainnet().unwrap();
604 assert_eq!(mainnet.max_target, 0x1d00ffff);
605 assert_eq!(mainnet.halving_interval, 210000);
606
607 let testnet = NetworkParameters::testnet().unwrap();
608 assert_eq!(testnet.max_target, 0x1d00ffff);
609 assert_eq!(testnet.halving_interval, 210000);
610
611 let regtest = NetworkParameters::regtest().unwrap();
612 assert_eq!(regtest.max_target, 0x207fffff); assert_eq!(regtest.halving_interval, 150); }
615
616 #[test]
617 fn test_feature_support() {
618 let mainnet = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
619 assert!(mainnet.supports_feature("segwit"));
620 assert!(mainnet.supports_feature("taproot"));
621 assert!(mainnet.supports_feature("rbf"));
622 assert!(mainnet.supports_feature("ctv"));
623 assert!(!mainnet.supports_feature("fast_mining"));
624 assert!(!mainnet.supports_feature("nonexistent"));
625
626 let testnet = BitcoinProtocolEngine::new(ProtocolVersion::Testnet3).unwrap();
627 assert!(testnet.supports_feature("segwit"));
628 assert!(testnet.supports_feature("taproot"));
629 assert!(testnet.supports_feature("rbf"));
630 assert!(testnet.supports_feature("ctv"));
631 assert!(!testnet.supports_feature("fast_mining"));
632
633 let regtest = BitcoinProtocolEngine::new(ProtocolVersion::Regtest).unwrap();
634 assert!(regtest.supports_feature("segwit"));
635 assert!(regtest.supports_feature("taproot"));
636 assert!(regtest.supports_feature("rbf"));
637 assert!(regtest.supports_feature("ctv"));
638 assert!(regtest.supports_feature("fast_mining"));
639 }
640
641 #[test]
642 fn test_block_validation_empty_utxos() {
643 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
644 let utxos = UtxoSet::default();
645
646 let coinbase_tx = Transaction {
648 version: 1,
649 inputs: blvm_consensus::tx_inputs![TransactionInput {
650 prevout: OutPoint {
651 hash: [0u8; 32],
652 index: 0xffffffff,
653 },
654 script_sig: vec![0x01, 0x00], sequence: 0xffffffff,
656 }],
657 outputs: blvm_consensus::tx_outputs![TransactionOutput {
658 value: 50_0000_0000,
659 script_pubkey: vec![
660 blvm_consensus::opcodes::OP_DUP,
661 blvm_consensus::opcodes::OP_HASH160,
662 blvm_consensus::opcodes::PUSH_20_BYTES,
663 0x00,
664 0x00,
665 0x00,
666 0x00,
667 0x00,
668 0x00,
669 0x00,
670 0x00,
671 0x00,
672 0x00,
673 0x00,
674 0x00,
675 0x00,
676 0x00,
677 0x00,
678 0x00,
679 0x00,
680 0x00,
681 0x00,
682 0x00,
683 blvm_consensus::opcodes::OP_EQUALVERIFY,
684 blvm_consensus::opcodes::OP_CHECKSIG,
685 ], }],
687 lock_time: 0,
688 };
689
690 let merkle_root = blvm_consensus::mining::calculate_merkle_root(&[coinbase_tx.clone()])
692 .expect("Should calculate merkle root");
693
694 let block = Block {
695 header: BlockHeader {
696 version: 1,
697 prev_block_hash: [0u8; 32],
698 merkle_root,
699 timestamp: 1231006505,
700 bits: 0x1d00ffff,
701 nonce: 0,
702 },
703 transactions: vec![coinbase_tx].into_boxed_slice(),
704 };
705
706 let result = engine.validate_block(&block, &utxos, 0);
708 assert!(result.is_ok());
709 }
710
711 #[test]
712 fn test_transaction_validation() {
713 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
714
715 let tx = Transaction {
717 version: 1,
718 inputs: vec![TransactionInput {
719 prevout: OutPoint {
720 hash: [0u8; 32],
721 index: 0,
722 },
723 script_sig: vec![blvm_consensus::opcodes::PUSH_65_BYTES, 0x04],
724 sequence: 0xffffffff,
725 }]
726 .into(),
727 outputs: vec![TransactionOutput {
728 value: 50_0000_0000,
729 script_pubkey: vec![
730 blvm_consensus::opcodes::OP_DUP,
731 blvm_consensus::opcodes::OP_HASH160,
732 blvm_consensus::opcodes::PUSH_20_BYTES,
733 0x00,
734 0x00,
735 0x00,
736 0x00,
737 0x00,
738 0x00,
739 0x00,
740 0x00,
741 0x00,
742 0x00,
743 0x00,
744 0x00,
745 0x00,
746 0x00,
747 0x00,
748 0x00,
749 0x00,
750 0x00,
751 0x00,
752 0x00,
753 blvm_consensus::opcodes::OP_EQUALVERIFY,
754 blvm_consensus::opcodes::OP_CHECKSIG,
755 ], }]
757 .into(),
758 lock_time: 0,
759 };
760
761 let result = engine.validate_transaction(&tx);
762 assert!(result.is_ok());
763 }
764
765 #[test]
766 fn test_cross_protocol_validation() {
767 let mainnet_engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
768 let testnet_engine = BitcoinProtocolEngine::new(ProtocolVersion::Testnet3).unwrap();
769
770 assert_eq!(
772 mainnet_engine.supports_feature("segwit"),
773 testnet_engine.supports_feature("segwit")
774 );
775 assert_eq!(
776 mainnet_engine.supports_feature("taproot"),
777 testnet_engine.supports_feature("taproot")
778 );
779
780 assert_ne!(
782 mainnet_engine.get_network_params().magic_bytes,
783 testnet_engine.get_network_params().magic_bytes
784 );
785 assert_ne!(
786 mainnet_engine.get_network_params().default_port,
787 testnet_engine.get_network_params().default_port
788 );
789 }
790
791 #[test]
792 fn test_protocol_version_switching() {
793 let versions = vec![
795 ProtocolVersion::BitcoinV1,
796 ProtocolVersion::Testnet3,
797 ProtocolVersion::Regtest,
798 ];
799
800 for version in versions {
801 let engine = BitcoinProtocolEngine::new(version).unwrap();
802 assert_eq!(engine.get_protocol_version(), version);
803 }
804 }
805
806 #[test]
807 fn test_network_parameters_serialization() {
808 let mainnet = NetworkParameters::mainnet().unwrap();
809 let testnet = NetworkParameters::testnet().unwrap();
810 let regtest = NetworkParameters::regtest().unwrap();
811
812 let mainnet_json = serde_json::to_string(&mainnet).unwrap();
814 let mainnet_deserialized: NetworkParameters = serde_json::from_str(&mainnet_json).unwrap();
815 assert_eq!(mainnet.magic_bytes, mainnet_deserialized.magic_bytes);
816 assert_eq!(mainnet.default_port, mainnet_deserialized.default_port);
817 assert_eq!(mainnet.network_name, mainnet_deserialized.network_name);
818 assert_eq!(mainnet.is_testnet, mainnet_deserialized.is_testnet);
819
820 let testnet_json = serde_json::to_string(&testnet).unwrap();
821 let testnet_deserialized: NetworkParameters = serde_json::from_str(&testnet_json).unwrap();
822 assert_eq!(testnet.magic_bytes, testnet_deserialized.magic_bytes);
823
824 let regtest_json = serde_json::to_string(®test).unwrap();
825 let regtest_deserialized: NetworkParameters = serde_json::from_str(®test_json).unwrap();
826 assert_eq!(regtest.magic_bytes, regtest_deserialized.magic_bytes);
827 }
828
829 #[test]
830 fn test_protocol_version_serialization() {
831 let versions = vec![
832 ProtocolVersion::BitcoinV1,
833 ProtocolVersion::Testnet3,
834 ProtocolVersion::Regtest,
835 ];
836
837 for version in versions {
838 let json = serde_json::to_string(&version).unwrap();
839 let deserialized: ProtocolVersion = serde_json::from_str(&json).unwrap();
840 assert_eq!(version, deserialized);
841 }
842 }
843
844 #[test]
845 fn test_network_parameters_equality() {
846 let mainnet1 = NetworkParameters::mainnet().unwrap();
847 let mainnet2 = NetworkParameters::mainnet().unwrap();
848 let testnet = NetworkParameters::testnet().unwrap();
849
850 assert_eq!(mainnet1, mainnet2);
851 assert_ne!(mainnet1, testnet);
852 }
853
854 #[test]
855 fn test_protocol_version_equality() {
856 assert_eq!(ProtocolVersion::BitcoinV1, ProtocolVersion::BitcoinV1);
857 assert_ne!(ProtocolVersion::BitcoinV1, ProtocolVersion::Testnet3);
858 assert_ne!(ProtocolVersion::Testnet3, ProtocolVersion::Regtest);
859 }
860
861 #[test]
862 fn test_feature_activation_by_height() {
863 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
864
865 assert!(!engine.is_feature_active("segwit", 481_823, 1503539000));
867 assert!(engine.is_feature_active("segwit", 481_824, 1503539857));
868 assert!(engine.is_feature_active("segwit", 500_000, 1504000000));
869
870 assert!(!engine.is_feature_active("taproot", 709_631, 1636934000));
872 assert!(engine.is_feature_active("taproot", 709_632, 1636934400));
873 assert!(engine.is_feature_active("taproot", 800_000, 1640000000));
874 }
875
876 #[test]
877 fn test_economic_parameters_access() {
878 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
879 let params = engine.get_economic_parameters();
880
881 assert_eq!(params.initial_subsidy, 50_0000_0000);
882 assert_eq!(params.halving_interval, 210_000);
883 assert_eq!(params.coinbase_maturity, 100);
884
885 assert_eq!(params.get_block_subsidy(0), 50_0000_0000);
887 assert_eq!(params.get_block_subsidy(210_000), 25_0000_0000);
888 }
889
890 #[test]
891 fn test_feature_registry_access() {
892 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
893 let registry = engine.get_feature_registry();
894
895 assert!(registry.get_feature("segwit").is_some());
896 assert!(registry.get_feature("taproot").is_some());
897 assert!(registry.get_feature("nonexistent").is_none());
898
899 let features = registry.list_features();
900 assert!(features.contains(&"segwit".to_string()));
901 assert!(features.contains(&"taproot".to_string()));
902 }
903}