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 #[deprecated(
350 since = "0.1.0",
351 note = "Use validate_and_connect_block with explicit witnesses and a ProtocolValidationContext"
352 )]
353 pub fn validate_block(
354 &self,
355 block: &Block,
356 utxos: &UtxoSet,
357 height: u64,
358 ) -> Result<ValidationResult> {
359 let network = match self.protocol_version {
360 ProtocolVersion::BitcoinV1 => types::Network::Mainnet,
361 ProtocolVersion::Testnet3 => types::Network::Testnet,
362 ProtocolVersion::Regtest => types::Network::Regtest,
363 };
364 let witnesses: Vec<Vec<blvm_consensus::segwit::Witness>> = block
368 .transactions
369 .iter()
370 .map(|tx| tx.inputs.iter().map(|_| Vec::new()).collect())
371 .collect();
372 let now_secs = std::time::SystemTime::now()
375 .duration_since(std::time::UNIX_EPOCH)
376 .unwrap_or_default()
377 .as_secs();
378 let time_ctx = blvm_consensus::types::TimeContext {
379 network_time: now_secs,
380 median_time_past: now_secs,
383 };
384 let (result, _) = self
385 .consensus
386 .validate_block_with_time_context(
387 block,
388 &witnesses,
389 utxos.clone(),
390 height,
391 Some(time_ctx),
392 network,
393 )
394 .map_err(ProtocolError::from)?;
395 Ok(result)
396 }
397
398 pub fn validate_transaction(&self, tx: &Transaction) -> Result<ValidationResult> {
400 self.consensus
401 .validate_transaction(tx)
402 .map_err(ProtocolError::from)
403 }
404
405 pub fn validate_and_connect_block(
463 &self,
464 block: &Block,
465 witnesses: &[Vec<segwit::Witness>], utxos: &UtxoSet,
469 height: u64,
470 recent_headers: Option<&[BlockHeader]>,
471 context: &validation::ProtocolValidationContext,
472 ) -> Result<(ValidationResult, UtxoSet)> {
473 let protocol_result = self
475 .validate_block_with_protocol_and_witnesses(block, witnesses, utxos, height, context)?;
476 if !matches!(protocol_result, ValidationResult::Valid) {
477 return Ok((protocol_result, utxos.clone()));
478 }
479
480 let network = match self.protocol_version {
483 ProtocolVersion::BitcoinV1 => types::Network::Mainnet,
484 ProtocolVersion::Testnet3 => types::Network::Testnet,
485 ProtocolVersion::Regtest => types::Network::Regtest,
486 };
487 let network_time = crate::time::current_timestamp();
488 let context = crate::block::block_validation_context_for_connect_ibd(
489 recent_headers,
490 network_time,
491 network,
492 );
493 let (result, new_utxo_set, _undo_log) = blvm_consensus::block::connect_block(
494 block,
495 witnesses,
496 utxos.clone(),
497 height,
498 &context,
499 )?;
500
501 Ok((result, new_utxo_set))
502 }
503
504 pub fn supports_feature(&self, feature: &str) -> bool {
506 match self.protocol_version {
507 ProtocolVersion::BitcoinV1 => {
508 matches!(feature, "segwit" | "taproot" | "rbf" | "ctv")
509 }
510 ProtocolVersion::Testnet3 => {
511 matches!(feature, "segwit" | "taproot" | "rbf" | "ctv")
512 }
513 ProtocolVersion::Regtest => {
514 matches!(
515 feature,
516 "segwit" | "taproot" | "rbf" | "ctv" | "fast_mining"
517 )
518 }
519 }
520 }
521
522 pub fn is_feature_active(&self, feature: &str, height: u64, timestamp: u64) -> bool {
524 let registry = features::FeatureRegistry::for_protocol(self.protocol_version);
525 registry.is_feature_active(feature, height, timestamp)
526 }
527
528 pub fn get_economic_parameters(&self) -> economic::EconomicParameters {
530 economic::EconomicParameters::for_protocol(self.protocol_version)
531 }
532
533 pub fn get_feature_registry(&self) -> features::FeatureRegistry {
535 features::FeatureRegistry::for_protocol(self.protocol_version)
536 }
537
538 pub fn feature_context(&self, height: u64, timestamp: u64) -> features::FeatureContext {
541 let registry = features::FeatureRegistry::for_protocol(self.protocol_version);
542 registry.create_context(height, timestamp)
543 }
544}
545
546impl NetworkParameters {
547 pub fn for_version(version: ProtocolVersion) -> Result<Self> {
549 match version {
550 ProtocolVersion::BitcoinV1 => Self::mainnet(),
551 ProtocolVersion::Testnet3 => Self::testnet(),
552 ProtocolVersion::Regtest => Self::regtest(),
553 }
554 }
555
556 pub fn mainnet() -> Result<Self> {
558 Ok(NetworkParameters {
559 magic_bytes: [0xf9, 0xbe, 0xb4, 0xd9], default_port: 8333,
561 genesis_block: genesis::mainnet_genesis(),
562 max_target: 0x1d00ffff,
563 halving_interval: 210000,
564 network_name: "mainnet".to_string(),
565 is_testnet: false,
566 })
567 }
568
569 pub fn testnet() -> Result<Self> {
571 Ok(NetworkParameters {
572 magic_bytes: [0x0b, 0x11, 0x09, 0x07], default_port: 18333,
574 genesis_block: genesis::testnet_genesis(),
575 max_target: 0x1d00ffff,
576 halving_interval: 210000,
577 network_name: "testnet".to_string(),
578 is_testnet: true,
579 })
580 }
581
582 pub fn regtest() -> Result<Self> {
584 Ok(NetworkParameters {
585 magic_bytes: [0xfa, 0xbf, 0xb5, 0xda], default_port: 18444,
587 genesis_block: genesis::regtest_genesis(),
588 max_target: 0x207fffff, halving_interval: 150, network_name: "regtest".to_string(),
591 is_testnet: true,
592 })
593 }
594}
595
596#[cfg(test)]
597mod tests {
598 use super::*;
599 use blvm_consensus::types::{BlockHeader, OutPoint, TransactionInput, TransactionOutput};
600
601 #[test]
602 fn test_blvm_protocol_creation() {
603 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
604 assert_eq!(engine.get_protocol_version(), ProtocolVersion::BitcoinV1);
605 assert_eq!(engine.get_network_params().network_name, "mainnet");
606 }
607
608 #[test]
609 fn test_blvm_protocol_creation_all_variants() {
610 let mainnet = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
612 assert_eq!(mainnet.get_protocol_version(), ProtocolVersion::BitcoinV1);
613 assert_eq!(mainnet.get_network_params().network_name, "mainnet");
614 assert!(!mainnet.get_network_params().is_testnet);
615
616 let testnet = BitcoinProtocolEngine::new(ProtocolVersion::Testnet3).unwrap();
618 assert_eq!(testnet.get_protocol_version(), ProtocolVersion::Testnet3);
619 assert_eq!(testnet.get_network_params().network_name, "testnet");
620 assert!(testnet.get_network_params().is_testnet);
621
622 let regtest = BitcoinProtocolEngine::new(ProtocolVersion::Regtest).unwrap();
624 assert_eq!(regtest.get_protocol_version(), ProtocolVersion::Regtest);
625 assert_eq!(regtest.get_network_params().network_name, "regtest");
626 assert!(regtest.get_network_params().is_testnet);
627 }
628
629 #[test]
630 fn test_network_parameters() {
631 let mainnet = NetworkParameters::mainnet().unwrap();
632 assert_eq!(mainnet.magic_bytes, [0xf9, 0xbe, 0xb4, 0xd9]);
633 assert_eq!(mainnet.default_port, 8333);
634 assert!(!mainnet.is_testnet);
635
636 let testnet = NetworkParameters::testnet().unwrap();
637 assert_eq!(testnet.magic_bytes, [0x0b, 0x11, 0x09, 0x07]);
638 assert_eq!(testnet.default_port, 18333);
639 assert!(testnet.is_testnet);
640
641 let regtest = NetworkParameters::regtest().unwrap();
642 assert_eq!(regtest.magic_bytes, [0xfa, 0xbf, 0xb5, 0xda]);
643 assert_eq!(regtest.default_port, 18444);
644 assert!(regtest.is_testnet);
645 }
646
647 #[test]
648 fn test_network_parameters_consistency() {
649 let mainnet = NetworkParameters::mainnet().unwrap();
650 assert_eq!(mainnet.max_target, 0x1d00ffff);
651 assert_eq!(mainnet.halving_interval, 210000);
652
653 let testnet = NetworkParameters::testnet().unwrap();
654 assert_eq!(testnet.max_target, 0x1d00ffff);
655 assert_eq!(testnet.halving_interval, 210000);
656
657 let regtest = NetworkParameters::regtest().unwrap();
658 assert_eq!(regtest.max_target, 0x207fffff); assert_eq!(regtest.halving_interval, 150); }
661
662 #[test]
663 fn test_feature_support() {
664 let mainnet = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
665 assert!(mainnet.supports_feature("segwit"));
666 assert!(mainnet.supports_feature("taproot"));
667 assert!(mainnet.supports_feature("rbf"));
668 assert!(mainnet.supports_feature("ctv"));
669 assert!(!mainnet.supports_feature("fast_mining"));
670 assert!(!mainnet.supports_feature("nonexistent"));
671
672 let testnet = BitcoinProtocolEngine::new(ProtocolVersion::Testnet3).unwrap();
673 assert!(testnet.supports_feature("segwit"));
674 assert!(testnet.supports_feature("taproot"));
675 assert!(testnet.supports_feature("rbf"));
676 assert!(testnet.supports_feature("ctv"));
677 assert!(!testnet.supports_feature("fast_mining"));
678
679 let regtest = BitcoinProtocolEngine::new(ProtocolVersion::Regtest).unwrap();
680 assert!(regtest.supports_feature("segwit"));
681 assert!(regtest.supports_feature("taproot"));
682 assert!(regtest.supports_feature("rbf"));
683 assert!(regtest.supports_feature("ctv"));
684 assert!(regtest.supports_feature("fast_mining"));
685 }
686
687 #[test]
688 fn test_block_validation_empty_utxos() {
689 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
690 let utxos = UtxoSet::default();
691
692 let coinbase_tx = Transaction {
694 version: 1,
695 inputs: blvm_consensus::tx_inputs![TransactionInput {
696 prevout: OutPoint {
697 hash: [0u8; 32],
698 index: 0xffffffff,
699 },
700 script_sig: vec![0x01, 0x00], sequence: 0xffffffff,
702 }],
703 outputs: blvm_consensus::tx_outputs![TransactionOutput {
704 value: 50_0000_0000,
705 script_pubkey: vec![
706 blvm_consensus::opcodes::OP_DUP,
707 blvm_consensus::opcodes::OP_HASH160,
708 blvm_consensus::opcodes::PUSH_20_BYTES,
709 0x00,
710 0x00,
711 0x00,
712 0x00,
713 0x00,
714 0x00,
715 0x00,
716 0x00,
717 0x00,
718 0x00,
719 0x00,
720 0x00,
721 0x00,
722 0x00,
723 0x00,
724 0x00,
725 0x00,
726 0x00,
727 0x00,
728 0x00,
729 blvm_consensus::opcodes::OP_EQUALVERIFY,
730 blvm_consensus::opcodes::OP_CHECKSIG,
731 ], }],
733 lock_time: 0,
734 };
735
736 let merkle_root = blvm_consensus::mining::calculate_merkle_root(&[coinbase_tx.clone()])
738 .expect("Should calculate merkle root");
739
740 let block = Block {
741 header: BlockHeader {
742 version: 1,
743 prev_block_hash: [0u8; 32],
744 merkle_root,
745 timestamp: 1231006505,
746 bits: 0x1d00ffff,
747 nonce: 0,
748 },
749 transactions: vec![coinbase_tx].into_boxed_slice(),
750 };
751
752 let result = engine.validate_block(&block, &utxos, 0);
754 assert!(result.is_ok());
755 }
756
757 #[test]
758 fn test_transaction_validation() {
759 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
760
761 let tx = Transaction {
763 version: 1,
764 inputs: vec![TransactionInput {
765 prevout: OutPoint {
766 hash: [0u8; 32],
767 index: 0,
768 },
769 script_sig: vec![blvm_consensus::opcodes::PUSH_65_BYTES, 0x04],
770 sequence: 0xffffffff,
771 }]
772 .into(),
773 outputs: vec![TransactionOutput {
774 value: 50_0000_0000,
775 script_pubkey: vec![
776 blvm_consensus::opcodes::OP_DUP,
777 blvm_consensus::opcodes::OP_HASH160,
778 blvm_consensus::opcodes::PUSH_20_BYTES,
779 0x00,
780 0x00,
781 0x00,
782 0x00,
783 0x00,
784 0x00,
785 0x00,
786 0x00,
787 0x00,
788 0x00,
789 0x00,
790 0x00,
791 0x00,
792 0x00,
793 0x00,
794 0x00,
795 0x00,
796 0x00,
797 0x00,
798 0x00,
799 blvm_consensus::opcodes::OP_EQUALVERIFY,
800 blvm_consensus::opcodes::OP_CHECKSIG,
801 ], }]
803 .into(),
804 lock_time: 0,
805 };
806
807 let result = engine.validate_transaction(&tx);
808 assert!(result.is_ok());
809 }
810
811 #[test]
812 fn test_cross_protocol_validation() {
813 let mainnet_engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
814 let testnet_engine = BitcoinProtocolEngine::new(ProtocolVersion::Testnet3).unwrap();
815
816 assert_eq!(
818 mainnet_engine.supports_feature("segwit"),
819 testnet_engine.supports_feature("segwit")
820 );
821 assert_eq!(
822 mainnet_engine.supports_feature("taproot"),
823 testnet_engine.supports_feature("taproot")
824 );
825
826 assert_ne!(
828 mainnet_engine.get_network_params().magic_bytes,
829 testnet_engine.get_network_params().magic_bytes
830 );
831 assert_ne!(
832 mainnet_engine.get_network_params().default_port,
833 testnet_engine.get_network_params().default_port
834 );
835 }
836
837 #[test]
838 fn test_protocol_version_switching() {
839 let versions = vec![
841 ProtocolVersion::BitcoinV1,
842 ProtocolVersion::Testnet3,
843 ProtocolVersion::Regtest,
844 ];
845
846 for version in versions {
847 let engine = BitcoinProtocolEngine::new(version).unwrap();
848 assert_eq!(engine.get_protocol_version(), version);
849 }
850 }
851
852 #[test]
853 fn test_network_parameters_serialization() {
854 let mainnet = NetworkParameters::mainnet().unwrap();
855 let testnet = NetworkParameters::testnet().unwrap();
856 let regtest = NetworkParameters::regtest().unwrap();
857
858 let mainnet_json = serde_json::to_string(&mainnet).unwrap();
860 let mainnet_deserialized: NetworkParameters = serde_json::from_str(&mainnet_json).unwrap();
861 assert_eq!(mainnet.magic_bytes, mainnet_deserialized.magic_bytes);
862 assert_eq!(mainnet.default_port, mainnet_deserialized.default_port);
863 assert_eq!(mainnet.network_name, mainnet_deserialized.network_name);
864 assert_eq!(mainnet.is_testnet, mainnet_deserialized.is_testnet);
865
866 let testnet_json = serde_json::to_string(&testnet).unwrap();
867 let testnet_deserialized: NetworkParameters = serde_json::from_str(&testnet_json).unwrap();
868 assert_eq!(testnet.magic_bytes, testnet_deserialized.magic_bytes);
869
870 let regtest_json = serde_json::to_string(®test).unwrap();
871 let regtest_deserialized: NetworkParameters = serde_json::from_str(®test_json).unwrap();
872 assert_eq!(regtest.magic_bytes, regtest_deserialized.magic_bytes);
873 }
874
875 #[test]
876 fn test_protocol_version_serialization() {
877 let versions = vec![
878 ProtocolVersion::BitcoinV1,
879 ProtocolVersion::Testnet3,
880 ProtocolVersion::Regtest,
881 ];
882
883 for version in versions {
884 let json = serde_json::to_string(&version).unwrap();
885 let deserialized: ProtocolVersion = serde_json::from_str(&json).unwrap();
886 assert_eq!(version, deserialized);
887 }
888 }
889
890 #[test]
891 fn test_network_parameters_equality() {
892 let mainnet1 = NetworkParameters::mainnet().unwrap();
893 let mainnet2 = NetworkParameters::mainnet().unwrap();
894 let testnet = NetworkParameters::testnet().unwrap();
895
896 assert_eq!(mainnet1, mainnet2);
897 assert_ne!(mainnet1, testnet);
898 }
899
900 #[test]
901 fn test_protocol_version_equality() {
902 assert_eq!(ProtocolVersion::BitcoinV1, ProtocolVersion::BitcoinV1);
903 assert_ne!(ProtocolVersion::BitcoinV1, ProtocolVersion::Testnet3);
904 assert_ne!(ProtocolVersion::Testnet3, ProtocolVersion::Regtest);
905 }
906
907 #[test]
908 fn test_feature_activation_by_height() {
909 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
910
911 assert!(!engine.is_feature_active("segwit", 481_823, 1503539000));
913 assert!(engine.is_feature_active("segwit", 481_824, 1503539857));
914 assert!(engine.is_feature_active("segwit", 500_000, 1504000000));
915
916 assert!(!engine.is_feature_active("taproot", 709_631, 1636934000));
918 assert!(engine.is_feature_active("taproot", 709_632, 1636934400));
919 assert!(engine.is_feature_active("taproot", 800_000, 1640000000));
920 }
921
922 #[test]
923 fn test_economic_parameters_access() {
924 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
925 let params = engine.get_economic_parameters();
926
927 assert_eq!(params.initial_subsidy, 50_0000_0000);
928 assert_eq!(params.halving_interval, 210_000);
929 assert_eq!(params.coinbase_maturity, 100);
930
931 assert_eq!(params.get_block_subsidy(0), 50_0000_0000);
933 assert_eq!(params.get_block_subsidy(210_000), 25_0000_0000);
934 }
935
936 #[test]
937 fn test_feature_registry_access() {
938 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
939 let registry = engine.get_feature_registry();
940
941 assert!(registry.get_feature("segwit").is_some());
942 assert!(registry.get_feature("taproot").is_some());
943 assert!(registry.get_feature("nonexistent").is_none());
944
945 let features = registry.list_features();
946 assert!(features.contains(&"segwit".to_string()));
947 assert!(features.contains(&"taproot".to_string()));
948 }
949}