1use serde::{Deserialize, Serialize};
18
19pub use blvm_consensus::ConsensusProof;
22pub use blvm_consensus::config::NetworkMessageLimits;
23pub use blvm_consensus::error::{ConsensusError, Result as ConsensusResult};
24pub use blvm_consensus::types::{
25 Block, BlockHeader, ByteString, Hash, Integer, Natural, OutPoint, Transaction,
26 TransactionInput, TransactionOutput, UTXO, UtxoSet, ValidationResult, Witness,
27};
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 Signet,
280}
281
282impl ProtocolVersion {
283 pub fn consensus_network(self) -> types::Network {
285 match self {
286 ProtocolVersion::BitcoinV1 => types::Network::Mainnet,
287 ProtocolVersion::Testnet3 => types::Network::Testnet,
288 ProtocolVersion::Regtest => types::Network::Regtest,
289 ProtocolVersion::Signet => types::Network::Signet,
290 }
291 }
292}
293
294#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
296pub struct NetworkParameters {
297 pub magic_bytes: [u8; 4],
299 pub default_port: u16,
301 pub genesis_block: Block,
303 pub max_target: u32,
305 pub halving_interval: u64,
307 pub network_name: String,
309 pub is_testnet: bool,
311 #[serde(default, skip_serializing_if = "Option::is_none")]
313 pub signet_challenge: Option<ByteString>,
314}
315
316impl BitcoinProtocolEngine {
317 pub fn new(version: ProtocolVersion) -> Result<Self> {
319 Self::with_config(version, ProtocolConfig::default())
320 }
321
322 pub fn with_config(version: ProtocolVersion, config: ProtocolConfig) -> Result<Self> {
324 let consensus = ConsensusProof::new();
325 let network_params = NetworkParameters::for_version(version)?;
326
327 Ok(BitcoinProtocolEngine {
328 consensus,
329 protocol_version: version,
330 network_params,
331 config,
332 })
333 }
334
335 pub fn get_config(&self) -> &ProtocolConfig {
337 &self.config
338 }
339
340 pub fn get_config_mut(&mut self) -> &mut ProtocolConfig {
342 &mut self.config
343 }
344
345 pub fn get_protocol_version(&self) -> ProtocolVersion {
347 self.protocol_version
348 }
349
350 pub fn get_network_params(&self) -> &NetworkParameters {
352 &self.network_params
353 }
354
355 pub fn with_signet_challenge(mut self, script: Option<Vec<u8>>) -> Self {
357 self.network_params.signet_challenge = script;
358 self
359 }
360
361 pub fn connect_block_validation_context<H: AsRef<BlockHeader>>(
363 &self,
364 recent_headers: Option<&[H]>,
365 network_time: u64,
366 ) -> block::BlockValidationContext {
367 let mut ctx = block::block_validation_context_for_connect_ibd(
368 recent_headers,
369 network_time,
370 self.protocol_version.consensus_network(),
371 );
372 ctx.signet_challenge = self.network_params.signet_challenge.clone();
373 ctx
374 }
375
376 #[deprecated(
388 since = "0.1.0",
389 note = "Use validate_and_connect_block with explicit witnesses and a ProtocolValidationContext"
390 )]
391 pub fn validate_block(
392 &self,
393 block: &Block,
394 utxos: &UtxoSet,
395 height: u64,
396 ) -> Result<ValidationResult> {
397 let network = self.protocol_version.consensus_network();
398 let witnesses: Vec<Vec<blvm_consensus::segwit::Witness>> = block
402 .transactions
403 .iter()
404 .map(|tx| tx.inputs.iter().map(|_| Vec::new()).collect())
405 .collect();
406 let now_secs = std::time::SystemTime::now()
409 .duration_since(std::time::UNIX_EPOCH)
410 .unwrap_or_default()
411 .as_secs();
412 let time_ctx = blvm_consensus::types::TimeContext {
413 network_time: now_secs,
414 median_time_past: now_secs,
417 };
418 let (result, _) = self
419 .consensus
420 .validate_block_with_time_context(
421 block,
422 &witnesses,
423 utxos.clone(),
424 height,
425 Some(time_ctx),
426 network,
427 )
428 .map_err(ProtocolError::from)?;
429 Ok(result)
430 }
431
432 pub fn validate_transaction(&self, tx: &Transaction) -> Result<ValidationResult> {
434 self.consensus
435 .validate_transaction(tx)
436 .map_err(ProtocolError::from)
437 }
438
439 pub fn validate_and_connect_block(
497 &self,
498 block: &Block,
499 witnesses: &[Vec<segwit::Witness>], utxos: &UtxoSet,
503 height: u64,
504 recent_headers: Option<&[BlockHeader]>,
505 context: &validation::ProtocolValidationContext,
506 ) -> Result<(ValidationResult, UtxoSet)> {
507 let protocol_result = self
509 .validate_block_with_protocol_and_witnesses(block, witnesses, utxos, height, context)?;
510 if !matches!(protocol_result, ValidationResult::Valid) {
511 return Ok((protocol_result, utxos.clone()));
512 }
513
514 let network_time = crate::time::current_timestamp();
516 let context = self.connect_block_validation_context(recent_headers, network_time);
517 let (result, new_utxo_set, _undo_log) = blvm_consensus::block::connect_block(
518 block,
519 witnesses,
520 utxos.clone(),
521 height,
522 &context,
523 )?;
524
525 Ok((result, new_utxo_set))
526 }
527
528 pub fn supports_feature(&self, feature: &str) -> bool {
530 match self.protocol_version {
531 ProtocolVersion::BitcoinV1 => {
532 matches!(feature, "segwit" | "taproot" | "rbf" | "ctv")
533 }
534 ProtocolVersion::Testnet3 => {
535 matches!(feature, "segwit" | "taproot" | "rbf" | "ctv")
536 }
537 ProtocolVersion::Regtest => {
538 matches!(
539 feature,
540 "segwit" | "taproot" | "rbf" | "ctv" | "fast_mining"
541 )
542 }
543 ProtocolVersion::Signet => {
544 matches!(feature, "segwit" | "taproot" | "rbf" | "ctv" | "signet")
545 }
546 }
547 }
548
549 pub fn is_feature_active(&self, feature: &str, height: u64, timestamp: u64) -> bool {
551 let registry = features::FeatureRegistry::for_protocol(self.protocol_version);
552 registry.is_feature_active(feature, height, timestamp)
553 }
554
555 pub fn get_economic_parameters(&self) -> economic::EconomicParameters {
557 economic::EconomicParameters::for_protocol(self.protocol_version)
558 }
559
560 pub fn get_feature_registry(&self) -> features::FeatureRegistry {
562 features::FeatureRegistry::for_protocol(self.protocol_version)
563 }
564
565 pub fn feature_context(&self, height: u64, timestamp: u64) -> features::FeatureContext {
568 let registry = features::FeatureRegistry::for_protocol(self.protocol_version);
569 registry.create_context(height, timestamp)
570 }
571}
572
573impl NetworkParameters {
574 pub fn for_version(version: ProtocolVersion) -> Result<Self> {
576 match version {
577 ProtocolVersion::BitcoinV1 => Self::mainnet(),
578 ProtocolVersion::Testnet3 => Self::testnet(),
579 ProtocolVersion::Regtest => Self::regtest(),
580 ProtocolVersion::Signet => Self::signet(),
581 }
582 }
583
584 pub fn mainnet() -> Result<Self> {
586 Ok(NetworkParameters {
587 magic_bytes: [0xf9, 0xbe, 0xb4, 0xd9], default_port: 8333,
589 genesis_block: genesis::mainnet_genesis(),
590 max_target: 0x1d00ffff,
591 halving_interval: 210000,
592 network_name: "mainnet".to_string(),
593 is_testnet: false,
594 signet_challenge: None,
595 })
596 }
597
598 pub fn testnet() -> Result<Self> {
600 Ok(NetworkParameters {
601 magic_bytes: [0x0b, 0x11, 0x09, 0x07], default_port: 18333,
603 genesis_block: genesis::testnet_genesis(),
604 max_target: 0x1d00ffff,
605 halving_interval: 210000,
606 network_name: "testnet".to_string(),
607 is_testnet: true,
608 signet_challenge: None,
609 })
610 }
611
612 pub fn regtest() -> Result<Self> {
614 Ok(NetworkParameters {
615 magic_bytes: [0xfa, 0xbf, 0xb5, 0xda], default_port: 18444,
617 genesis_block: genesis::regtest_genesis(),
618 max_target: 0x207fffff, halving_interval: 150, network_name: "regtest".to_string(),
621 is_testnet: true,
622 signet_challenge: None,
623 })
624 }
625
626 pub fn signet() -> Result<Self> {
628 Ok(NetworkParameters {
629 magic_bytes: [0x0f, 0x1b, 0xf2, 0xe1],
630 default_port: 38333,
631 genesis_block: genesis::signet_genesis(),
632 max_target: 0x1e0377ae,
633 halving_interval: 210_000,
634 network_name: "signet".to_string(),
635 is_testnet: true,
636 signet_challenge: None,
637 })
638 }
639}
640
641#[cfg(test)]
642mod tests {
643 use super::*;
644 use blvm_consensus::types::{BlockHeader, OutPoint, TransactionInput, TransactionOutput};
645
646 #[test]
647 fn test_blvm_protocol_creation() {
648 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
649 assert_eq!(engine.get_protocol_version(), ProtocolVersion::BitcoinV1);
650 assert_eq!(engine.get_network_params().network_name, "mainnet");
651 }
652
653 #[test]
654 fn test_blvm_protocol_creation_all_variants() {
655 let mainnet = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
657 assert_eq!(mainnet.get_protocol_version(), ProtocolVersion::BitcoinV1);
658 assert_eq!(mainnet.get_network_params().network_name, "mainnet");
659 assert!(!mainnet.get_network_params().is_testnet);
660
661 let testnet = BitcoinProtocolEngine::new(ProtocolVersion::Testnet3).unwrap();
663 assert_eq!(testnet.get_protocol_version(), ProtocolVersion::Testnet3);
664 assert_eq!(testnet.get_network_params().network_name, "testnet");
665 assert!(testnet.get_network_params().is_testnet);
666
667 let regtest = BitcoinProtocolEngine::new(ProtocolVersion::Regtest).unwrap();
669 assert_eq!(regtest.get_protocol_version(), ProtocolVersion::Regtest);
670 assert_eq!(regtest.get_network_params().network_name, "regtest");
671 assert!(regtest.get_network_params().is_testnet);
672
673 let signet = BitcoinProtocolEngine::new(ProtocolVersion::Signet).unwrap();
675 assert_eq!(signet.get_protocol_version(), ProtocolVersion::Signet);
676 assert_eq!(signet.get_network_params().network_name, "signet");
677 assert!(signet.get_network_params().is_testnet);
678 assert_eq!(signet.get_network_params().default_port, 38333);
679 }
680
681 #[test]
682 fn test_network_parameters() {
683 let mainnet = NetworkParameters::mainnet().unwrap();
684 assert_eq!(mainnet.magic_bytes, [0xf9, 0xbe, 0xb4, 0xd9]);
685 assert_eq!(mainnet.default_port, 8333);
686 assert!(!mainnet.is_testnet);
687
688 let testnet = NetworkParameters::testnet().unwrap();
689 assert_eq!(testnet.magic_bytes, [0x0b, 0x11, 0x09, 0x07]);
690 assert_eq!(testnet.default_port, 18333);
691 assert!(testnet.is_testnet);
692
693 let regtest = NetworkParameters::regtest().unwrap();
694 assert_eq!(regtest.magic_bytes, [0xfa, 0xbf, 0xb5, 0xda]);
695 assert_eq!(regtest.default_port, 18444);
696 assert!(regtest.is_testnet);
697 }
698
699 #[test]
700 fn test_network_parameters_consistency() {
701 let mainnet = NetworkParameters::mainnet().unwrap();
702 assert_eq!(mainnet.max_target, 0x1d00ffff);
703 assert_eq!(mainnet.halving_interval, 210000);
704
705 let testnet = NetworkParameters::testnet().unwrap();
706 assert_eq!(testnet.max_target, 0x1d00ffff);
707 assert_eq!(testnet.halving_interval, 210000);
708
709 let regtest = NetworkParameters::regtest().unwrap();
710 assert_eq!(regtest.max_target, 0x207fffff); assert_eq!(regtest.halving_interval, 150); }
713
714 #[test]
715 fn test_feature_support() {
716 let mainnet = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
717 assert!(mainnet.supports_feature("segwit"));
718 assert!(mainnet.supports_feature("taproot"));
719 assert!(mainnet.supports_feature("rbf"));
720 assert!(mainnet.supports_feature("ctv"));
721 assert!(!mainnet.supports_feature("fast_mining"));
722 assert!(!mainnet.supports_feature("nonexistent"));
723
724 let testnet = BitcoinProtocolEngine::new(ProtocolVersion::Testnet3).unwrap();
725 assert!(testnet.supports_feature("segwit"));
726 assert!(testnet.supports_feature("taproot"));
727 assert!(testnet.supports_feature("rbf"));
728 assert!(testnet.supports_feature("ctv"));
729 assert!(!testnet.supports_feature("fast_mining"));
730
731 let regtest = BitcoinProtocolEngine::new(ProtocolVersion::Regtest).unwrap();
732 assert!(regtest.supports_feature("segwit"));
733 assert!(regtest.supports_feature("taproot"));
734 assert!(regtest.supports_feature("rbf"));
735 assert!(regtest.supports_feature("ctv"));
736 assert!(regtest.supports_feature("fast_mining"));
737
738 let signet = BitcoinProtocolEngine::new(ProtocolVersion::Signet).unwrap();
739 assert!(signet.supports_feature("segwit"));
740 assert!(signet.supports_feature("taproot"));
741 assert!(signet.supports_feature("signet"));
742 assert!(!signet.supports_feature("fast_mining"));
743 }
744
745 #[test]
746 fn test_signet_challenge_override_on_engine() {
747 let engine = BitcoinProtocolEngine::new(ProtocolVersion::Signet)
748 .unwrap()
749 .with_signet_challenge(Some(vec![0x51]));
750 assert_eq!(
751 engine
752 .get_network_params()
753 .signet_challenge
754 .as_ref()
755 .map(|b| b.as_ref()),
756 Some([0x51].as_slice())
757 );
758 let ctx = engine.connect_block_validation_context(None::<&[BlockHeader]>, 0);
759 assert_eq!(
760 ctx.signet_challenge.as_ref().map(|b| b.as_ref()),
761 Some([0x51].as_slice())
762 );
763 }
764
765 #[test]
766 fn test_block_validation_empty_utxos() {
767 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
768 let utxos = UtxoSet::default();
769
770 let coinbase_tx = Transaction {
772 version: 1,
773 inputs: blvm_consensus::tx_inputs![TransactionInput {
774 prevout: OutPoint {
775 hash: [0u8; 32],
776 index: 0xffffffff,
777 },
778 script_sig: vec![0x01, 0x00], sequence: 0xffffffff,
780 }],
781 outputs: blvm_consensus::tx_outputs![TransactionOutput {
782 value: 50_0000_0000,
783 script_pubkey: vec![
784 blvm_consensus::opcodes::OP_DUP,
785 blvm_consensus::opcodes::OP_HASH160,
786 blvm_consensus::opcodes::PUSH_20_BYTES,
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 0x00,
800 0x00,
801 0x00,
802 0x00,
803 0x00,
804 0x00,
805 0x00,
806 0x00,
807 blvm_consensus::opcodes::OP_EQUALVERIFY,
808 blvm_consensus::opcodes::OP_CHECKSIG,
809 ], }],
811 lock_time: 0,
812 };
813
814 let merkle_root = blvm_consensus::mining::calculate_merkle_root(&[coinbase_tx.clone()])
816 .expect("Should calculate merkle root");
817
818 let block = Block {
819 header: BlockHeader {
820 version: 1,
821 prev_block_hash: [0u8; 32],
822 merkle_root,
823 timestamp: 1231006505,
824 bits: 0x1d00ffff,
825 nonce: 0,
826 },
827 transactions: vec![coinbase_tx].into_boxed_slice(),
828 };
829
830 let result = engine.validate_block(&block, &utxos, 0);
832 assert!(result.is_ok());
833 }
834
835 #[test]
836 fn test_transaction_validation() {
837 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
838
839 let tx = Transaction {
841 version: 1,
842 inputs: vec![TransactionInput {
843 prevout: OutPoint {
844 hash: [0u8; 32],
845 index: 0,
846 },
847 script_sig: vec![blvm_consensus::opcodes::PUSH_65_BYTES, 0x04],
848 sequence: 0xffffffff,
849 }]
850 .into(),
851 outputs: vec![TransactionOutput {
852 value: 50_0000_0000,
853 script_pubkey: vec![
854 blvm_consensus::opcodes::OP_DUP,
855 blvm_consensus::opcodes::OP_HASH160,
856 blvm_consensus::opcodes::PUSH_20_BYTES,
857 0x00,
858 0x00,
859 0x00,
860 0x00,
861 0x00,
862 0x00,
863 0x00,
864 0x00,
865 0x00,
866 0x00,
867 0x00,
868 0x00,
869 0x00,
870 0x00,
871 0x00,
872 0x00,
873 0x00,
874 0x00,
875 0x00,
876 0x00,
877 blvm_consensus::opcodes::OP_EQUALVERIFY,
878 blvm_consensus::opcodes::OP_CHECKSIG,
879 ], }]
881 .into(),
882 lock_time: 0,
883 };
884
885 let result = engine.validate_transaction(&tx);
886 assert!(result.is_ok());
887 }
888
889 #[test]
890 fn test_cross_protocol_validation() {
891 let mainnet_engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
892 let testnet_engine = BitcoinProtocolEngine::new(ProtocolVersion::Testnet3).unwrap();
893
894 assert_eq!(
896 mainnet_engine.supports_feature("segwit"),
897 testnet_engine.supports_feature("segwit")
898 );
899 assert_eq!(
900 mainnet_engine.supports_feature("taproot"),
901 testnet_engine.supports_feature("taproot")
902 );
903
904 assert_ne!(
906 mainnet_engine.get_network_params().magic_bytes,
907 testnet_engine.get_network_params().magic_bytes
908 );
909 assert_ne!(
910 mainnet_engine.get_network_params().default_port,
911 testnet_engine.get_network_params().default_port
912 );
913 }
914
915 #[test]
916 fn test_protocol_version_switching() {
917 let versions = vec![
919 ProtocolVersion::BitcoinV1,
920 ProtocolVersion::Testnet3,
921 ProtocolVersion::Regtest,
922 ProtocolVersion::Signet,
923 ];
924
925 for version in versions {
926 let engine = BitcoinProtocolEngine::new(version).unwrap();
927 assert_eq!(engine.get_protocol_version(), version);
928 }
929 }
930
931 #[test]
932 fn test_network_parameters_serialization() {
933 let mainnet = NetworkParameters::mainnet().unwrap();
934 let testnet = NetworkParameters::testnet().unwrap();
935 let regtest = NetworkParameters::regtest().unwrap();
936
937 let mainnet_json = serde_json::to_string(&mainnet).unwrap();
939 let mainnet_deserialized: NetworkParameters = serde_json::from_str(&mainnet_json).unwrap();
940 assert_eq!(mainnet.magic_bytes, mainnet_deserialized.magic_bytes);
941 assert_eq!(mainnet.default_port, mainnet_deserialized.default_port);
942 assert_eq!(mainnet.network_name, mainnet_deserialized.network_name);
943 assert_eq!(mainnet.is_testnet, mainnet_deserialized.is_testnet);
944
945 let testnet_json = serde_json::to_string(&testnet).unwrap();
946 let testnet_deserialized: NetworkParameters = serde_json::from_str(&testnet_json).unwrap();
947 assert_eq!(testnet.magic_bytes, testnet_deserialized.magic_bytes);
948
949 let regtest_json = serde_json::to_string(®test).unwrap();
950 let regtest_deserialized: NetworkParameters = serde_json::from_str(®test_json).unwrap();
951 assert_eq!(regtest.magic_bytes, regtest_deserialized.magic_bytes);
952 }
953
954 #[test]
955 fn test_protocol_version_serialization() {
956 let versions = vec![
957 ProtocolVersion::BitcoinV1,
958 ProtocolVersion::Testnet3,
959 ProtocolVersion::Regtest,
960 ProtocolVersion::Signet,
961 ];
962
963 for version in versions {
964 let json = serde_json::to_string(&version).unwrap();
965 let deserialized: ProtocolVersion = serde_json::from_str(&json).unwrap();
966 assert_eq!(version, deserialized);
967 }
968 }
969
970 #[test]
971 fn test_network_parameters_equality() {
972 let mainnet1 = NetworkParameters::mainnet().unwrap();
973 let mainnet2 = NetworkParameters::mainnet().unwrap();
974 let testnet = NetworkParameters::testnet().unwrap();
975
976 assert_eq!(mainnet1, mainnet2);
977 assert_ne!(mainnet1, testnet);
978 }
979
980 #[test]
981 fn test_protocol_version_equality() {
982 assert_eq!(ProtocolVersion::BitcoinV1, ProtocolVersion::BitcoinV1);
983 assert_ne!(ProtocolVersion::BitcoinV1, ProtocolVersion::Testnet3);
984 assert_ne!(ProtocolVersion::Testnet3, ProtocolVersion::Regtest);
985 }
986
987 #[test]
988 fn test_feature_activation_by_height() {
989 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
990
991 assert!(!engine.is_feature_active("segwit", 481_823, 1503539000));
993 assert!(engine.is_feature_active("segwit", 481_824, 1503539857));
994 assert!(engine.is_feature_active("segwit", 500_000, 1504000000));
995
996 assert!(!engine.is_feature_active("taproot", 709_631, 1636934000));
998 assert!(engine.is_feature_active("taproot", 709_632, 1636934400));
999 assert!(engine.is_feature_active("taproot", 800_000, 1640000000));
1000 }
1001
1002 #[test]
1003 fn test_economic_parameters_access() {
1004 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
1005 let params = engine.get_economic_parameters();
1006
1007 assert_eq!(params.initial_subsidy, 50_0000_0000);
1008 assert_eq!(params.halving_interval, 210_000);
1009 assert_eq!(params.coinbase_maturity, 100);
1010
1011 assert_eq!(params.get_block_subsidy(0), 50_0000_0000);
1013 assert_eq!(params.get_block_subsidy(210_000), 25_0000_0000);
1014 }
1015
1016 #[test]
1017 fn test_feature_registry_access() {
1018 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
1019 let registry = engine.get_feature_registry();
1020
1021 assert!(registry.get_feature("segwit").is_some());
1022 assert!(registry.get_feature("taproot").is_some());
1023 assert!(registry.get_feature("nonexistent").is_none());
1024
1025 let features = registry.list_features();
1026 assert!(features.contains(&"segwit".to_string()));
1027 assert!(features.contains(&"taproot".to_string()));
1028 }
1029}