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(feature = "bip324")]
188pub mod v2_transport;
189
190pub use commons::{
192 BanListMessage,
193 FilterPreferences,
195 FilteredBlockMessage,
197 GetBanListMessage,
198 GetFilteredBlockMessage,
199 GetUTXOProofMessage,
201 GetUTXOSetMessage,
202 UTXOCommitment,
204 UTXOProofMessage,
205 UTXOSetMessage,
206};
207pub use config::{
208 ProtocolConfig, ProtocolFeaturesConfig, ProtocolValidationConfig, ServiceFlagsConfig,
209};
210pub use network::{BlockMessage, CompactBlockMessage, TxMessage};
211pub use service_flags::{commons as service_flags_commons, standard as service_flags_standard};
212pub mod wire;
214
215#[cfg(test)]
216mod bip155_serialization_tests;
217pub mod types {
218 pub use blvm_consensus::types::*;
219}
220#[cfg(feature = "production")]
222pub use blvm_consensus::tx_inputs;
223#[cfg(not(feature = "production"))]
224pub use blvm_consensus::tx_inputs;
225#[cfg(feature = "production")]
226pub use blvm_consensus::tx_outputs;
227#[cfg(not(feature = "production"))]
228pub use blvm_consensus::tx_outputs;
229pub mod error;
230
231pub use economic::EconomicParameters;
233pub use features::{ActivationMethod, FeatureActivation, FeatureContext, FeatureRegistry};
234
235pub mod config;
236pub mod economic;
237pub mod features;
238pub mod genesis;
239pub mod network_params;
240pub mod validation;
241pub mod variants;
242
243pub mod address; #[cfg(feature = "ctv")]
246pub mod bip119 {
247 pub use blvm_consensus::bip119::*;
248}
249pub mod bip152; pub mod bip157; pub mod bip158; pub mod fibre;
253pub mod payment; pub mod time;
255
256pub struct BitcoinProtocolEngine {
261 consensus: ConsensusProof,
262 protocol_version: ProtocolVersion,
263 network_params: NetworkParameters,
264 config: ProtocolConfig,
265}
266
267#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
269pub enum ProtocolVersion {
270 BitcoinV1,
272 Testnet3,
274 Regtest,
276}
277
278#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
280pub struct NetworkParameters {
281 pub magic_bytes: [u8; 4],
283 pub default_port: u16,
285 pub genesis_block: Block,
287 pub max_target: u32,
289 pub halving_interval: u64,
291 pub network_name: String,
293 pub is_testnet: bool,
295}
296
297impl BitcoinProtocolEngine {
298 pub fn new(version: ProtocolVersion) -> Result<Self> {
300 Self::with_config(version, ProtocolConfig::default())
301 }
302
303 pub fn with_config(version: ProtocolVersion, config: ProtocolConfig) -> Result<Self> {
305 let consensus = ConsensusProof::new();
306 let network_params = NetworkParameters::for_version(version)?;
307
308 Ok(BitcoinProtocolEngine {
309 consensus,
310 protocol_version: version,
311 network_params,
312 config,
313 })
314 }
315
316 pub fn get_config(&self) -> &ProtocolConfig {
318 &self.config
319 }
320
321 pub fn get_config_mut(&mut self) -> &mut ProtocolConfig {
323 &mut self.config
324 }
325
326 pub fn get_protocol_version(&self) -> ProtocolVersion {
328 self.protocol_version
329 }
330
331 pub fn get_network_params(&self) -> &NetworkParameters {
333 &self.network_params
334 }
335
336 pub fn validate_block(
338 &self,
339 block: &Block,
340 utxos: &UtxoSet,
341 height: u64,
342 ) -> Result<ValidationResult> {
343 let (result, _) = self
344 .consensus
345 .validate_block(block, utxos.clone(), height)
346 .map_err(ProtocolError::from)?;
347 Ok(result)
348 }
349
350 pub fn validate_transaction(&self, tx: &Transaction) -> Result<ValidationResult> {
352 self.consensus
353 .validate_transaction(tx)
354 .map_err(ProtocolError::from)
355 }
356
357 pub fn validate_and_connect_block(
415 &self,
416 block: &Block,
417 witnesses: &[Vec<segwit::Witness>], utxos: &UtxoSet,
421 height: u64,
422 recent_headers: Option<&[BlockHeader]>,
423 context: &validation::ProtocolValidationContext,
424 ) -> Result<(ValidationResult, UtxoSet)> {
425 let protocol_result = self.validate_block_with_protocol(block, utxos, height, context)?;
427 if !matches!(protocol_result, ValidationResult::Valid) {
428 return Ok((protocol_result, utxos.clone()));
429 }
430
431 let network = match self.protocol_version {
434 ProtocolVersion::BitcoinV1 => types::Network::Mainnet,
435 ProtocolVersion::Testnet3 => types::Network::Testnet,
436 ProtocolVersion::Regtest => types::Network::Regtest,
437 };
438 let network_time = crate::time::current_timestamp();
439 let context = crate::block::block_validation_context_for_connect_ibd(
440 recent_headers,
441 network_time,
442 network,
443 );
444 let (result, new_utxo_set, _undo_log) = blvm_consensus::block::connect_block(
445 block,
446 witnesses,
447 utxos.clone(),
448 height,
449 &context,
450 )?;
451
452 Ok((result, new_utxo_set))
453 }
454
455 pub fn supports_feature(&self, feature: &str) -> bool {
457 match self.protocol_version {
458 ProtocolVersion::BitcoinV1 => {
459 matches!(feature, "segwit" | "taproot" | "rbf" | "ctv")
460 }
461 ProtocolVersion::Testnet3 => {
462 matches!(feature, "segwit" | "taproot" | "rbf" | "ctv")
463 }
464 ProtocolVersion::Regtest => {
465 matches!(
466 feature,
467 "segwit" | "taproot" | "rbf" | "ctv" | "fast_mining"
468 )
469 }
470 }
471 }
472
473 pub fn is_feature_active(&self, feature: &str, height: u64, timestamp: u64) -> bool {
475 let registry = features::FeatureRegistry::for_protocol(self.protocol_version);
476 registry.is_feature_active(feature, height, timestamp)
477 }
478
479 pub fn get_economic_parameters(&self) -> economic::EconomicParameters {
481 economic::EconomicParameters::for_protocol(self.protocol_version)
482 }
483
484 pub fn get_feature_registry(&self) -> features::FeatureRegistry {
486 features::FeatureRegistry::for_protocol(self.protocol_version)
487 }
488
489 pub fn feature_context(&self, height: u64, timestamp: u64) -> features::FeatureContext {
492 let registry = features::FeatureRegistry::for_protocol(self.protocol_version);
493 registry.create_context(height, timestamp)
494 }
495}
496
497impl NetworkParameters {
498 pub fn for_version(version: ProtocolVersion) -> Result<Self> {
500 match version {
501 ProtocolVersion::BitcoinV1 => Self::mainnet(),
502 ProtocolVersion::Testnet3 => Self::testnet(),
503 ProtocolVersion::Regtest => Self::regtest(),
504 }
505 }
506
507 pub fn mainnet() -> Result<Self> {
509 Ok(NetworkParameters {
510 magic_bytes: [0xf9, 0xbe, 0xb4, 0xd9], default_port: 8333,
512 genesis_block: genesis::mainnet_genesis(),
513 max_target: 0x1d00ffff,
514 halving_interval: 210000,
515 network_name: "mainnet".to_string(),
516 is_testnet: false,
517 })
518 }
519
520 pub fn testnet() -> Result<Self> {
522 Ok(NetworkParameters {
523 magic_bytes: [0x0b, 0x11, 0x09, 0x07], default_port: 18333,
525 genesis_block: genesis::testnet_genesis(),
526 max_target: 0x1d00ffff,
527 halving_interval: 210000,
528 network_name: "testnet".to_string(),
529 is_testnet: true,
530 })
531 }
532
533 pub fn regtest() -> Result<Self> {
535 Ok(NetworkParameters {
536 magic_bytes: [0xfa, 0xbf, 0xb5, 0xda], default_port: 18444,
538 genesis_block: genesis::regtest_genesis(),
539 max_target: 0x207fffff, halving_interval: 150, network_name: "regtest".to_string(),
542 is_testnet: true,
543 })
544 }
545}
546
547#[cfg(test)]
548mod tests {
549 use super::*;
550 use blvm_consensus::types::{BlockHeader, OutPoint, TransactionInput, TransactionOutput};
551
552 #[test]
553 fn test_blvm_protocol_creation() {
554 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
555 assert_eq!(engine.get_protocol_version(), ProtocolVersion::BitcoinV1);
556 assert_eq!(engine.get_network_params().network_name, "mainnet");
557 }
558
559 #[test]
560 fn test_blvm_protocol_creation_all_variants() {
561 let mainnet = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
563 assert_eq!(mainnet.get_protocol_version(), ProtocolVersion::BitcoinV1);
564 assert_eq!(mainnet.get_network_params().network_name, "mainnet");
565 assert!(!mainnet.get_network_params().is_testnet);
566
567 let testnet = BitcoinProtocolEngine::new(ProtocolVersion::Testnet3).unwrap();
569 assert_eq!(testnet.get_protocol_version(), ProtocolVersion::Testnet3);
570 assert_eq!(testnet.get_network_params().network_name, "testnet");
571 assert!(testnet.get_network_params().is_testnet);
572
573 let regtest = BitcoinProtocolEngine::new(ProtocolVersion::Regtest).unwrap();
575 assert_eq!(regtest.get_protocol_version(), ProtocolVersion::Regtest);
576 assert_eq!(regtest.get_network_params().network_name, "regtest");
577 assert!(regtest.get_network_params().is_testnet);
578 }
579
580 #[test]
581 fn test_network_parameters() {
582 let mainnet = NetworkParameters::mainnet().unwrap();
583 assert_eq!(mainnet.magic_bytes, [0xf9, 0xbe, 0xb4, 0xd9]);
584 assert_eq!(mainnet.default_port, 8333);
585 assert!(!mainnet.is_testnet);
586
587 let testnet = NetworkParameters::testnet().unwrap();
588 assert_eq!(testnet.magic_bytes, [0x0b, 0x11, 0x09, 0x07]);
589 assert_eq!(testnet.default_port, 18333);
590 assert!(testnet.is_testnet);
591
592 let regtest = NetworkParameters::regtest().unwrap();
593 assert_eq!(regtest.magic_bytes, [0xfa, 0xbf, 0xb5, 0xda]);
594 assert_eq!(regtest.default_port, 18444);
595 assert!(regtest.is_testnet);
596 }
597
598 #[test]
599 fn test_network_parameters_consistency() {
600 let mainnet = NetworkParameters::mainnet().unwrap();
601 assert_eq!(mainnet.max_target, 0x1d00ffff);
602 assert_eq!(mainnet.halving_interval, 210000);
603
604 let testnet = NetworkParameters::testnet().unwrap();
605 assert_eq!(testnet.max_target, 0x1d00ffff);
606 assert_eq!(testnet.halving_interval, 210000);
607
608 let regtest = NetworkParameters::regtest().unwrap();
609 assert_eq!(regtest.max_target, 0x207fffff); assert_eq!(regtest.halving_interval, 150); }
612
613 #[test]
614 fn test_feature_support() {
615 let mainnet = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
616 assert!(mainnet.supports_feature("segwit"));
617 assert!(mainnet.supports_feature("taproot"));
618 assert!(mainnet.supports_feature("rbf"));
619 assert!(mainnet.supports_feature("ctv"));
620 assert!(!mainnet.supports_feature("fast_mining"));
621 assert!(!mainnet.supports_feature("nonexistent"));
622
623 let testnet = BitcoinProtocolEngine::new(ProtocolVersion::Testnet3).unwrap();
624 assert!(testnet.supports_feature("segwit"));
625 assert!(testnet.supports_feature("taproot"));
626 assert!(testnet.supports_feature("rbf"));
627 assert!(testnet.supports_feature("ctv"));
628 assert!(!testnet.supports_feature("fast_mining"));
629
630 let regtest = BitcoinProtocolEngine::new(ProtocolVersion::Regtest).unwrap();
631 assert!(regtest.supports_feature("segwit"));
632 assert!(regtest.supports_feature("taproot"));
633 assert!(regtest.supports_feature("rbf"));
634 assert!(regtest.supports_feature("ctv"));
635 assert!(regtest.supports_feature("fast_mining"));
636 }
637
638 #[test]
639 fn test_block_validation_empty_utxos() {
640 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
641 let utxos = UtxoSet::default();
642
643 let coinbase_tx = Transaction {
645 version: 1,
646 inputs: blvm_consensus::tx_inputs![TransactionInput {
647 prevout: OutPoint {
648 hash: [0u8; 32],
649 index: 0xffffffff,
650 },
651 script_sig: vec![0x01, 0x00], sequence: 0xffffffff,
653 }],
654 outputs: blvm_consensus::tx_outputs![TransactionOutput {
655 value: 50_0000_0000,
656 script_pubkey: vec![
657 blvm_consensus::opcodes::OP_DUP,
658 blvm_consensus::opcodes::OP_HASH160,
659 blvm_consensus::opcodes::PUSH_20_BYTES,
660 0x00,
661 0x00,
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 blvm_consensus::opcodes::OP_EQUALVERIFY,
681 blvm_consensus::opcodes::OP_CHECKSIG,
682 ], }],
684 lock_time: 0,
685 };
686
687 let merkle_root = blvm_consensus::mining::calculate_merkle_root(&[coinbase_tx.clone()])
689 .expect("Should calculate merkle root");
690
691 let block = Block {
692 header: BlockHeader {
693 version: 1,
694 prev_block_hash: [0u8; 32],
695 merkle_root,
696 timestamp: 1231006505,
697 bits: 0x1d00ffff,
698 nonce: 0,
699 },
700 transactions: vec![coinbase_tx].into_boxed_slice(),
701 };
702
703 let result = engine.validate_block(&block, &utxos, 0);
705 assert!(result.is_ok());
706 }
707
708 #[test]
709 fn test_transaction_validation() {
710 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
711
712 let tx = Transaction {
714 version: 1,
715 inputs: vec![TransactionInput {
716 prevout: OutPoint {
717 hash: [0u8; 32],
718 index: 0,
719 },
720 script_sig: vec![blvm_consensus::opcodes::PUSH_65_BYTES, 0x04],
721 sequence: 0xffffffff,
722 }]
723 .into(),
724 outputs: vec![TransactionOutput {
725 value: 50_0000_0000,
726 script_pubkey: vec![
727 blvm_consensus::opcodes::OP_DUP,
728 blvm_consensus::opcodes::OP_HASH160,
729 blvm_consensus::opcodes::PUSH_20_BYTES,
730 0x00,
731 0x00,
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 blvm_consensus::opcodes::OP_EQUALVERIFY,
751 blvm_consensus::opcodes::OP_CHECKSIG,
752 ], }]
754 .into(),
755 lock_time: 0,
756 };
757
758 let result = engine.validate_transaction(&tx);
759 assert!(result.is_ok());
760 }
761
762 #[test]
763 fn test_cross_protocol_validation() {
764 let mainnet_engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
765 let testnet_engine = BitcoinProtocolEngine::new(ProtocolVersion::Testnet3).unwrap();
766
767 assert_eq!(
769 mainnet_engine.supports_feature("segwit"),
770 testnet_engine.supports_feature("segwit")
771 );
772 assert_eq!(
773 mainnet_engine.supports_feature("taproot"),
774 testnet_engine.supports_feature("taproot")
775 );
776
777 assert_ne!(
779 mainnet_engine.get_network_params().magic_bytes,
780 testnet_engine.get_network_params().magic_bytes
781 );
782 assert_ne!(
783 mainnet_engine.get_network_params().default_port,
784 testnet_engine.get_network_params().default_port
785 );
786 }
787
788 #[test]
789 fn test_protocol_version_switching() {
790 let versions = vec![
792 ProtocolVersion::BitcoinV1,
793 ProtocolVersion::Testnet3,
794 ProtocolVersion::Regtest,
795 ];
796
797 for version in versions {
798 let engine = BitcoinProtocolEngine::new(version).unwrap();
799 assert_eq!(engine.get_protocol_version(), version);
800 }
801 }
802
803 #[test]
804 fn test_network_parameters_serialization() {
805 let mainnet = NetworkParameters::mainnet().unwrap();
806 let testnet = NetworkParameters::testnet().unwrap();
807 let regtest = NetworkParameters::regtest().unwrap();
808
809 let mainnet_json = serde_json::to_string(&mainnet).unwrap();
811 let mainnet_deserialized: NetworkParameters = serde_json::from_str(&mainnet_json).unwrap();
812 assert_eq!(mainnet.magic_bytes, mainnet_deserialized.magic_bytes);
813 assert_eq!(mainnet.default_port, mainnet_deserialized.default_port);
814 assert_eq!(mainnet.network_name, mainnet_deserialized.network_name);
815 assert_eq!(mainnet.is_testnet, mainnet_deserialized.is_testnet);
816
817 let testnet_json = serde_json::to_string(&testnet).unwrap();
818 let testnet_deserialized: NetworkParameters = serde_json::from_str(&testnet_json).unwrap();
819 assert_eq!(testnet.magic_bytes, testnet_deserialized.magic_bytes);
820
821 let regtest_json = serde_json::to_string(®test).unwrap();
822 let regtest_deserialized: NetworkParameters = serde_json::from_str(®test_json).unwrap();
823 assert_eq!(regtest.magic_bytes, regtest_deserialized.magic_bytes);
824 }
825
826 #[test]
827 fn test_protocol_version_serialization() {
828 let versions = vec![
829 ProtocolVersion::BitcoinV1,
830 ProtocolVersion::Testnet3,
831 ProtocolVersion::Regtest,
832 ];
833
834 for version in versions {
835 let json = serde_json::to_string(&version).unwrap();
836 let deserialized: ProtocolVersion = serde_json::from_str(&json).unwrap();
837 assert_eq!(version, deserialized);
838 }
839 }
840
841 #[test]
842 fn test_network_parameters_equality() {
843 let mainnet1 = NetworkParameters::mainnet().unwrap();
844 let mainnet2 = NetworkParameters::mainnet().unwrap();
845 let testnet = NetworkParameters::testnet().unwrap();
846
847 assert_eq!(mainnet1, mainnet2);
848 assert_ne!(mainnet1, testnet);
849 }
850
851 #[test]
852 fn test_protocol_version_equality() {
853 assert_eq!(ProtocolVersion::BitcoinV1, ProtocolVersion::BitcoinV1);
854 assert_ne!(ProtocolVersion::BitcoinV1, ProtocolVersion::Testnet3);
855 assert_ne!(ProtocolVersion::Testnet3, ProtocolVersion::Regtest);
856 }
857
858 #[test]
859 fn test_feature_activation_by_height() {
860 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
861
862 assert!(!engine.is_feature_active("segwit", 481_823, 1503539000));
864 assert!(engine.is_feature_active("segwit", 481_824, 1503539857));
865 assert!(engine.is_feature_active("segwit", 500_000, 1504000000));
866
867 assert!(!engine.is_feature_active("taproot", 709_631, 1636934000));
869 assert!(engine.is_feature_active("taproot", 709_632, 1636934400));
870 assert!(engine.is_feature_active("taproot", 800_000, 1640000000));
871 }
872
873 #[test]
874 fn test_economic_parameters_access() {
875 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
876 let params = engine.get_economic_parameters();
877
878 assert_eq!(params.initial_subsidy, 50_0000_0000);
879 assert_eq!(params.halving_interval, 210_000);
880 assert_eq!(params.coinbase_maturity, 100);
881
882 assert_eq!(params.get_block_subsidy(0), 50_0000_0000);
884 assert_eq!(params.get_block_subsidy(210_000), 25_0000_0000);
885 }
886
887 #[test]
888 fn test_feature_registry_access() {
889 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
890 let registry = engine.get_feature_registry();
891
892 assert!(registry.get_feature("segwit").is_some());
893 assert!(registry.get_feature("taproot").is_some());
894 assert!(registry.get_feature("nonexistent").is_none());
895
896 let features = registry.list_features();
897 assert!(features.contains(&"segwit".to_string()));
898 assert!(features.contains(&"taproot".to_string()));
899 }
900}