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 payment; pub mod time;
257
258pub struct BitcoinProtocolEngine {
263 consensus: ConsensusProof,
264 protocol_version: ProtocolVersion,
265 network_params: NetworkParameters,
266 config: ProtocolConfig,
267}
268
269#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
271pub enum ProtocolVersion {
272 BitcoinV1,
274 Testnet3,
276 Regtest,
278}
279
280#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
282pub struct NetworkParameters {
283 pub magic_bytes: [u8; 4],
285 pub default_port: u16,
287 pub genesis_block: Block,
289 pub max_target: u32,
291 pub halving_interval: u64,
293 pub network_name: String,
295 pub is_testnet: bool,
297}
298
299impl BitcoinProtocolEngine {
300 pub fn new(version: ProtocolVersion) -> Result<Self> {
302 Self::with_config(version, ProtocolConfig::default())
303 }
304
305 pub fn with_config(version: ProtocolVersion, config: ProtocolConfig) -> Result<Self> {
307 let consensus = ConsensusProof::new();
308 let network_params = NetworkParameters::for_version(version)?;
309
310 Ok(BitcoinProtocolEngine {
311 consensus,
312 protocol_version: version,
313 network_params,
314 config,
315 })
316 }
317
318 pub fn get_config(&self) -> &ProtocolConfig {
320 &self.config
321 }
322
323 pub fn get_config_mut(&mut self) -> &mut ProtocolConfig {
325 &mut self.config
326 }
327
328 pub fn get_protocol_version(&self) -> ProtocolVersion {
330 self.protocol_version
331 }
332
333 pub fn get_network_params(&self) -> &NetworkParameters {
335 &self.network_params
336 }
337
338 pub fn validate_block(
340 &self,
341 block: &Block,
342 utxos: &UtxoSet,
343 height: u64,
344 ) -> Result<ValidationResult> {
345 let (result, _) = self
346 .consensus
347 .validate_block(block, utxos.clone(), height)
348 .map_err(ProtocolError::from)?;
349 Ok(result)
350 }
351
352 pub fn validate_transaction(&self, tx: &Transaction) -> Result<ValidationResult> {
354 self.consensus
355 .validate_transaction(tx)
356 .map_err(ProtocolError::from)
357 }
358
359 pub fn validate_and_connect_block(
417 &self,
418 block: &Block,
419 witnesses: &[Vec<segwit::Witness>], utxos: &UtxoSet,
423 height: u64,
424 recent_headers: Option<&[BlockHeader]>,
425 context: &validation::ProtocolValidationContext,
426 ) -> Result<(ValidationResult, UtxoSet)> {
427 let protocol_result = self.validate_block_with_protocol(block, utxos, height, context)?;
429 if !matches!(protocol_result, ValidationResult::Valid) {
430 return Ok((protocol_result, utxos.clone()));
431 }
432
433 let network = match self.protocol_version {
436 ProtocolVersion::BitcoinV1 => types::Network::Mainnet,
437 ProtocolVersion::Testnet3 => types::Network::Testnet,
438 ProtocolVersion::Regtest => types::Network::Regtest,
439 };
440 let network_time = crate::time::current_timestamp();
441 let context = crate::block::block_validation_context_for_connect_ibd(
442 recent_headers,
443 network_time,
444 network,
445 );
446 let (result, new_utxo_set, _undo_log) = blvm_consensus::block::connect_block(
447 block,
448 witnesses,
449 utxos.clone(),
450 height,
451 &context,
452 )?;
453
454 Ok((result, new_utxo_set))
455 }
456
457 pub fn supports_feature(&self, feature: &str) -> bool {
459 match self.protocol_version {
460 ProtocolVersion::BitcoinV1 => {
461 matches!(feature, "segwit" | "taproot" | "rbf" | "ctv")
462 }
463 ProtocolVersion::Testnet3 => {
464 matches!(feature, "segwit" | "taproot" | "rbf" | "ctv")
465 }
466 ProtocolVersion::Regtest => {
467 matches!(
468 feature,
469 "segwit" | "taproot" | "rbf" | "ctv" | "fast_mining"
470 )
471 }
472 }
473 }
474
475 pub fn is_feature_active(&self, feature: &str, height: u64, timestamp: u64) -> bool {
477 let registry = features::FeatureRegistry::for_protocol(self.protocol_version);
478 registry.is_feature_active(feature, height, timestamp)
479 }
480
481 pub fn get_economic_parameters(&self) -> economic::EconomicParameters {
483 economic::EconomicParameters::for_protocol(self.protocol_version)
484 }
485
486 pub fn get_feature_registry(&self) -> features::FeatureRegistry {
488 features::FeatureRegistry::for_protocol(self.protocol_version)
489 }
490
491 pub fn feature_context(&self, height: u64, timestamp: u64) -> features::FeatureContext {
494 let registry = features::FeatureRegistry::for_protocol(self.protocol_version);
495 registry.create_context(height, timestamp)
496 }
497}
498
499impl NetworkParameters {
500 pub fn for_version(version: ProtocolVersion) -> Result<Self> {
502 match version {
503 ProtocolVersion::BitcoinV1 => Self::mainnet(),
504 ProtocolVersion::Testnet3 => Self::testnet(),
505 ProtocolVersion::Regtest => Self::regtest(),
506 }
507 }
508
509 pub fn mainnet() -> Result<Self> {
511 Ok(NetworkParameters {
512 magic_bytes: [0xf9, 0xbe, 0xb4, 0xd9], default_port: 8333,
514 genesis_block: genesis::mainnet_genesis(),
515 max_target: 0x1d00ffff,
516 halving_interval: 210000,
517 network_name: "mainnet".to_string(),
518 is_testnet: false,
519 })
520 }
521
522 pub fn testnet() -> Result<Self> {
524 Ok(NetworkParameters {
525 magic_bytes: [0x0b, 0x11, 0x09, 0x07], default_port: 18333,
527 genesis_block: genesis::testnet_genesis(),
528 max_target: 0x1d00ffff,
529 halving_interval: 210000,
530 network_name: "testnet".to_string(),
531 is_testnet: true,
532 })
533 }
534
535 pub fn regtest() -> Result<Self> {
537 Ok(NetworkParameters {
538 magic_bytes: [0xfa, 0xbf, 0xb5, 0xda], default_port: 18444,
540 genesis_block: genesis::regtest_genesis(),
541 max_target: 0x207fffff, halving_interval: 150, network_name: "regtest".to_string(),
544 is_testnet: true,
545 })
546 }
547}
548
549#[cfg(test)]
550mod tests {
551 use super::*;
552 use blvm_consensus::types::{BlockHeader, OutPoint, TransactionInput, TransactionOutput};
553
554 #[test]
555 fn test_blvm_protocol_creation() {
556 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
557 assert_eq!(engine.get_protocol_version(), ProtocolVersion::BitcoinV1);
558 assert_eq!(engine.get_network_params().network_name, "mainnet");
559 }
560
561 #[test]
562 fn test_blvm_protocol_creation_all_variants() {
563 let mainnet = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
565 assert_eq!(mainnet.get_protocol_version(), ProtocolVersion::BitcoinV1);
566 assert_eq!(mainnet.get_network_params().network_name, "mainnet");
567 assert!(!mainnet.get_network_params().is_testnet);
568
569 let testnet = BitcoinProtocolEngine::new(ProtocolVersion::Testnet3).unwrap();
571 assert_eq!(testnet.get_protocol_version(), ProtocolVersion::Testnet3);
572 assert_eq!(testnet.get_network_params().network_name, "testnet");
573 assert!(testnet.get_network_params().is_testnet);
574
575 let regtest = BitcoinProtocolEngine::new(ProtocolVersion::Regtest).unwrap();
577 assert_eq!(regtest.get_protocol_version(), ProtocolVersion::Regtest);
578 assert_eq!(regtest.get_network_params().network_name, "regtest");
579 assert!(regtest.get_network_params().is_testnet);
580 }
581
582 #[test]
583 fn test_network_parameters() {
584 let mainnet = NetworkParameters::mainnet().unwrap();
585 assert_eq!(mainnet.magic_bytes, [0xf9, 0xbe, 0xb4, 0xd9]);
586 assert_eq!(mainnet.default_port, 8333);
587 assert!(!mainnet.is_testnet);
588
589 let testnet = NetworkParameters::testnet().unwrap();
590 assert_eq!(testnet.magic_bytes, [0x0b, 0x11, 0x09, 0x07]);
591 assert_eq!(testnet.default_port, 18333);
592 assert!(testnet.is_testnet);
593
594 let regtest = NetworkParameters::regtest().unwrap();
595 assert_eq!(regtest.magic_bytes, [0xfa, 0xbf, 0xb5, 0xda]);
596 assert_eq!(regtest.default_port, 18444);
597 assert!(regtest.is_testnet);
598 }
599
600 #[test]
601 fn test_network_parameters_consistency() {
602 let mainnet = NetworkParameters::mainnet().unwrap();
603 assert_eq!(mainnet.max_target, 0x1d00ffff);
604 assert_eq!(mainnet.halving_interval, 210000);
605
606 let testnet = NetworkParameters::testnet().unwrap();
607 assert_eq!(testnet.max_target, 0x1d00ffff);
608 assert_eq!(testnet.halving_interval, 210000);
609
610 let regtest = NetworkParameters::regtest().unwrap();
611 assert_eq!(regtest.max_target, 0x207fffff); assert_eq!(regtest.halving_interval, 150); }
614
615 #[test]
616 fn test_feature_support() {
617 let mainnet = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
618 assert!(mainnet.supports_feature("segwit"));
619 assert!(mainnet.supports_feature("taproot"));
620 assert!(mainnet.supports_feature("rbf"));
621 assert!(mainnet.supports_feature("ctv"));
622 assert!(!mainnet.supports_feature("fast_mining"));
623 assert!(!mainnet.supports_feature("nonexistent"));
624
625 let testnet = BitcoinProtocolEngine::new(ProtocolVersion::Testnet3).unwrap();
626 assert!(testnet.supports_feature("segwit"));
627 assert!(testnet.supports_feature("taproot"));
628 assert!(testnet.supports_feature("rbf"));
629 assert!(testnet.supports_feature("ctv"));
630 assert!(!testnet.supports_feature("fast_mining"));
631
632 let regtest = BitcoinProtocolEngine::new(ProtocolVersion::Regtest).unwrap();
633 assert!(regtest.supports_feature("segwit"));
634 assert!(regtest.supports_feature("taproot"));
635 assert!(regtest.supports_feature("rbf"));
636 assert!(regtest.supports_feature("ctv"));
637 assert!(regtest.supports_feature("fast_mining"));
638 }
639
640 #[test]
641 fn test_block_validation_empty_utxos() {
642 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
643 let utxos = UtxoSet::default();
644
645 let coinbase_tx = Transaction {
647 version: 1,
648 inputs: blvm_consensus::tx_inputs![TransactionInput {
649 prevout: OutPoint {
650 hash: [0u8; 32],
651 index: 0xffffffff,
652 },
653 script_sig: vec![0x01, 0x00], sequence: 0xffffffff,
655 }],
656 outputs: blvm_consensus::tx_outputs![TransactionOutput {
657 value: 50_0000_0000,
658 script_pubkey: vec![
659 blvm_consensus::opcodes::OP_DUP,
660 blvm_consensus::opcodes::OP_HASH160,
661 blvm_consensus::opcodes::PUSH_20_BYTES,
662 0x00,
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 blvm_consensus::opcodes::OP_EQUALVERIFY,
683 blvm_consensus::opcodes::OP_CHECKSIG,
684 ], }],
686 lock_time: 0,
687 };
688
689 let merkle_root = blvm_consensus::mining::calculate_merkle_root(&[coinbase_tx.clone()])
691 .expect("Should calculate merkle root");
692
693 let block = Block {
694 header: BlockHeader {
695 version: 1,
696 prev_block_hash: [0u8; 32],
697 merkle_root,
698 timestamp: 1231006505,
699 bits: 0x1d00ffff,
700 nonce: 0,
701 },
702 transactions: vec![coinbase_tx].into_boxed_slice(),
703 };
704
705 let result = engine.validate_block(&block, &utxos, 0);
707 assert!(result.is_ok());
708 }
709
710 #[test]
711 fn test_transaction_validation() {
712 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
713
714 let tx = Transaction {
716 version: 1,
717 inputs: vec![TransactionInput {
718 prevout: OutPoint {
719 hash: [0u8; 32],
720 index: 0,
721 },
722 script_sig: vec![blvm_consensus::opcodes::PUSH_65_BYTES, 0x04],
723 sequence: 0xffffffff,
724 }]
725 .into(),
726 outputs: vec![TransactionOutput {
727 value: 50_0000_0000,
728 script_pubkey: vec![
729 blvm_consensus::opcodes::OP_DUP,
730 blvm_consensus::opcodes::OP_HASH160,
731 blvm_consensus::opcodes::PUSH_20_BYTES,
732 0x00,
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 blvm_consensus::opcodes::OP_EQUALVERIFY,
753 blvm_consensus::opcodes::OP_CHECKSIG,
754 ], }]
756 .into(),
757 lock_time: 0,
758 };
759
760 let result = engine.validate_transaction(&tx);
761 assert!(result.is_ok());
762 }
763
764 #[test]
765 fn test_cross_protocol_validation() {
766 let mainnet_engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
767 let testnet_engine = BitcoinProtocolEngine::new(ProtocolVersion::Testnet3).unwrap();
768
769 assert_eq!(
771 mainnet_engine.supports_feature("segwit"),
772 testnet_engine.supports_feature("segwit")
773 );
774 assert_eq!(
775 mainnet_engine.supports_feature("taproot"),
776 testnet_engine.supports_feature("taproot")
777 );
778
779 assert_ne!(
781 mainnet_engine.get_network_params().magic_bytes,
782 testnet_engine.get_network_params().magic_bytes
783 );
784 assert_ne!(
785 mainnet_engine.get_network_params().default_port,
786 testnet_engine.get_network_params().default_port
787 );
788 }
789
790 #[test]
791 fn test_protocol_version_switching() {
792 let versions = vec![
794 ProtocolVersion::BitcoinV1,
795 ProtocolVersion::Testnet3,
796 ProtocolVersion::Regtest,
797 ];
798
799 for version in versions {
800 let engine = BitcoinProtocolEngine::new(version).unwrap();
801 assert_eq!(engine.get_protocol_version(), version);
802 }
803 }
804
805 #[test]
806 fn test_network_parameters_serialization() {
807 let mainnet = NetworkParameters::mainnet().unwrap();
808 let testnet = NetworkParameters::testnet().unwrap();
809 let regtest = NetworkParameters::regtest().unwrap();
810
811 let mainnet_json = serde_json::to_string(&mainnet).unwrap();
813 let mainnet_deserialized: NetworkParameters = serde_json::from_str(&mainnet_json).unwrap();
814 assert_eq!(mainnet.magic_bytes, mainnet_deserialized.magic_bytes);
815 assert_eq!(mainnet.default_port, mainnet_deserialized.default_port);
816 assert_eq!(mainnet.network_name, mainnet_deserialized.network_name);
817 assert_eq!(mainnet.is_testnet, mainnet_deserialized.is_testnet);
818
819 let testnet_json = serde_json::to_string(&testnet).unwrap();
820 let testnet_deserialized: NetworkParameters = serde_json::from_str(&testnet_json).unwrap();
821 assert_eq!(testnet.magic_bytes, testnet_deserialized.magic_bytes);
822
823 let regtest_json = serde_json::to_string(®test).unwrap();
824 let regtest_deserialized: NetworkParameters = serde_json::from_str(®test_json).unwrap();
825 assert_eq!(regtest.magic_bytes, regtest_deserialized.magic_bytes);
826 }
827
828 #[test]
829 fn test_protocol_version_serialization() {
830 let versions = vec![
831 ProtocolVersion::BitcoinV1,
832 ProtocolVersion::Testnet3,
833 ProtocolVersion::Regtest,
834 ];
835
836 for version in versions {
837 let json = serde_json::to_string(&version).unwrap();
838 let deserialized: ProtocolVersion = serde_json::from_str(&json).unwrap();
839 assert_eq!(version, deserialized);
840 }
841 }
842
843 #[test]
844 fn test_network_parameters_equality() {
845 let mainnet1 = NetworkParameters::mainnet().unwrap();
846 let mainnet2 = NetworkParameters::mainnet().unwrap();
847 let testnet = NetworkParameters::testnet().unwrap();
848
849 assert_eq!(mainnet1, mainnet2);
850 assert_ne!(mainnet1, testnet);
851 }
852
853 #[test]
854 fn test_protocol_version_equality() {
855 assert_eq!(ProtocolVersion::BitcoinV1, ProtocolVersion::BitcoinV1);
856 assert_ne!(ProtocolVersion::BitcoinV1, ProtocolVersion::Testnet3);
857 assert_ne!(ProtocolVersion::Testnet3, ProtocolVersion::Regtest);
858 }
859
860 #[test]
861 fn test_feature_activation_by_height() {
862 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
863
864 assert!(!engine.is_feature_active("segwit", 481_823, 1503539000));
866 assert!(engine.is_feature_active("segwit", 481_824, 1503539857));
867 assert!(engine.is_feature_active("segwit", 500_000, 1504000000));
868
869 assert!(!engine.is_feature_active("taproot", 709_631, 1636934000));
871 assert!(engine.is_feature_active("taproot", 709_632, 1636934400));
872 assert!(engine.is_feature_active("taproot", 800_000, 1640000000));
873 }
874
875 #[test]
876 fn test_economic_parameters_access() {
877 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
878 let params = engine.get_economic_parameters();
879
880 assert_eq!(params.initial_subsidy, 50_0000_0000);
881 assert_eq!(params.halving_interval, 210_000);
882 assert_eq!(params.coinbase_maturity, 100);
883
884 assert_eq!(params.get_block_subsidy(0), 50_0000_0000);
886 assert_eq!(params.get_block_subsidy(210_000), 25_0000_0000);
887 }
888
889 #[test]
890 fn test_feature_registry_access() {
891 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
892 let registry = engine.get_feature_registry();
893
894 assert!(registry.get_feature("segwit").is_some());
895 assert!(registry.get_feature("taproot").is_some());
896 assert!(registry.get_feature("nonexistent").is_none());
897
898 let features = registry.list_features();
899 assert!(features.contains(&"segwit".to_string()));
900 assert!(features.contains(&"taproot".to_string()));
901 }
902}