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}
223pub use blvm_consensus::tx_inputs;
225pub use blvm_consensus::tx_outputs;
226pub mod error;
227
228pub use economic::EconomicParameters;
230pub use features::{ActivationMethod, FeatureActivation, FeatureContext, FeatureRegistry};
231
232pub mod config;
233pub mod economic;
234pub mod features;
235pub mod genesis;
236pub mod network_params;
237pub mod validation;
238pub mod variants;
239
240pub mod address; #[cfg(feature = "ctv")]
243pub mod bip119 {
244 pub use blvm_consensus::bip119::*;
245}
246pub mod bip152; pub mod bip157; pub mod bip158; pub mod payment; pub mod time;
251
252pub struct BitcoinProtocolEngine {
257 consensus: ConsensusProof,
258 protocol_version: ProtocolVersion,
259 network_params: NetworkParameters,
260 config: ProtocolConfig,
261}
262
263#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
265pub enum ProtocolVersion {
266 BitcoinV1,
268 Testnet3,
270 Regtest,
272 Signet,
274}
275
276impl ProtocolVersion {
277 pub fn consensus_network(self) -> types::Network {
279 match self {
280 ProtocolVersion::BitcoinV1 => types::Network::Mainnet,
281 ProtocolVersion::Testnet3 => types::Network::Testnet,
282 ProtocolVersion::Regtest => types::Network::Regtest,
283 ProtocolVersion::Signet => types::Network::Signet,
284 }
285 }
286}
287
288#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
290pub struct NetworkParameters {
291 pub magic_bytes: [u8; 4],
293 pub default_port: u16,
295 pub genesis_block: Block,
297 pub max_target: u32,
299 pub halving_interval: u64,
301 pub network_name: String,
303 pub is_testnet: bool,
305 #[serde(default, skip_serializing_if = "Option::is_none")]
307 pub signet_challenge: Option<ByteString>,
308}
309
310impl BitcoinProtocolEngine {
311 pub fn new(version: ProtocolVersion) -> Result<Self> {
313 Self::with_config(version, ProtocolConfig::default())
314 }
315
316 pub fn with_config(version: ProtocolVersion, config: ProtocolConfig) -> Result<Self> {
318 let consensus = ConsensusProof::new();
319 let network_params = NetworkParameters::for_version(version)?;
320
321 Ok(BitcoinProtocolEngine {
322 consensus,
323 protocol_version: version,
324 network_params,
325 config,
326 })
327 }
328
329 pub fn get_config(&self) -> &ProtocolConfig {
331 &self.config
332 }
333
334 pub fn get_config_mut(&mut self) -> &mut ProtocolConfig {
336 &mut self.config
337 }
338
339 pub fn get_protocol_version(&self) -> ProtocolVersion {
341 self.protocol_version
342 }
343
344 pub fn get_network_params(&self) -> &NetworkParameters {
346 &self.network_params
347 }
348
349 pub fn with_signet_challenge(mut self, script: Option<Vec<u8>>) -> Self {
351 self.network_params.signet_challenge = script;
352 self
353 }
354
355 pub fn connect_block_validation_context<H: AsRef<BlockHeader>>(
357 &self,
358 recent_headers: Option<&[H]>,
359 network_time: u64,
360 ) -> block::BlockValidationContext {
361 let mut ctx = block::block_validation_context_for_connect_ibd(
362 recent_headers,
363 network_time,
364 self.protocol_version.consensus_network(),
365 );
366 ctx.signet_challenge = self.network_params.signet_challenge.clone();
367 ctx
368 }
369
370 #[deprecated(
382 since = "0.1.0",
383 note = "Use validate_and_connect_block with explicit witnesses and a ProtocolValidationContext"
384 )]
385 pub fn validate_block(
386 &self,
387 block: &Block,
388 utxos: &UtxoSet,
389 height: u64,
390 ) -> Result<ValidationResult> {
391 let network = self.protocol_version.consensus_network();
392 let witnesses: Vec<Vec<blvm_consensus::segwit::Witness>> = block
396 .transactions
397 .iter()
398 .map(|tx| tx.inputs.iter().map(|_| Vec::new()).collect())
399 .collect();
400 let now_secs = std::time::SystemTime::now()
403 .duration_since(std::time::UNIX_EPOCH)
404 .unwrap_or_default()
405 .as_secs();
406 let time_ctx = blvm_consensus::types::TimeContext {
407 network_time: now_secs,
408 median_time_past: now_secs,
411 };
412 let (result, _) = self
413 .consensus
414 .validate_block_with_time_context(
415 block,
416 &witnesses,
417 utxos.clone(),
418 height,
419 Some(time_ctx),
420 network,
421 )
422 .map_err(ProtocolError::from)?;
423 Ok(result)
424 }
425
426 pub fn validate_transaction(&self, tx: &Transaction) -> Result<ValidationResult> {
428 self.consensus
429 .validate_transaction(tx)
430 .map_err(ProtocolError::from)
431 }
432
433 pub fn validate_and_connect_block(
491 &self,
492 block: &Block,
493 witnesses: &[Vec<segwit::Witness>], utxos: &UtxoSet,
497 height: u64,
498 recent_headers: Option<&[BlockHeader]>,
499 context: &validation::ProtocolValidationContext,
500 ) -> Result<(ValidationResult, UtxoSet)> {
501 self.validate_and_connect_block_with_difficulty(
502 block,
503 witnesses,
504 utxos,
505 height,
506 recent_headers,
507 context,
508 None,
509 )
510 }
511
512 #[allow(clippy::too_many_arguments)]
517 pub fn validate_and_connect_block_with_difficulty(
518 &self,
519 block: &Block,
520 witnesses: &[Vec<segwit::Witness>],
521 utxos: &UtxoSet,
522 height: u64,
523 recent_headers: Option<&[BlockHeader]>,
524 context: &validation::ProtocolValidationContext,
525 difficulty_ancestor: Option<block::DifficultyAncestor>,
526 ) -> Result<(ValidationResult, UtxoSet)> {
527 let protocol_result = self
529 .validate_block_with_protocol_and_witnesses(block, witnesses, utxos, height, context)?;
530 if !matches!(protocol_result, ValidationResult::Valid) {
531 return Ok((protocol_result, utxos.clone()));
532 }
533
534 let network_time = if context.network_time > 0 {
536 context.network_time
537 } else {
538 crate::time::current_timestamp()
539 };
540 let mut consensus_ctx = if context.median_time_past > 0 {
541 block::BlockValidationContext::from_time_context_and_network(
542 Some(blvm_consensus::types::TimeContext {
543 network_time,
544 median_time_past: context.median_time_past,
545 }),
546 self.protocol_version.consensus_network(),
547 None,
548 )
549 } else {
550 self.connect_block_validation_context(recent_headers, network_time)
551 };
552 consensus_ctx.signet_challenge = self.network_params.signet_challenge.clone();
553 consensus_ctx.difficulty_ancestor = difficulty_ancestor;
554 let (result, new_utxo_set, _undo_log) = blvm_consensus::block::connect_block(
555 block,
556 witnesses,
557 utxos.clone(),
558 height,
559 &consensus_ctx,
560 )?;
561
562 Ok((result, new_utxo_set))
563 }
564
565 pub fn supports_feature(&self, feature: &str) -> bool {
567 match self.protocol_version {
568 ProtocolVersion::BitcoinV1 => {
569 matches!(feature, "segwit" | "taproot" | "rbf" | "ctv")
570 }
571 ProtocolVersion::Testnet3 => {
572 matches!(feature, "segwit" | "taproot" | "rbf" | "ctv")
573 }
574 ProtocolVersion::Regtest => {
575 matches!(
576 feature,
577 "segwit" | "taproot" | "rbf" | "ctv" | "fast_mining"
578 )
579 }
580 ProtocolVersion::Signet => {
581 matches!(feature, "segwit" | "taproot" | "rbf" | "ctv" | "signet")
582 }
583 }
584 }
585
586 pub fn is_feature_active(&self, feature: &str, height: u64, timestamp: u64) -> bool {
588 let registry = features::FeatureRegistry::for_protocol(self.protocol_version);
589 registry.is_feature_active(feature, height, timestamp)
590 }
591
592 pub fn get_economic_parameters(&self) -> economic::EconomicParameters {
594 economic::EconomicParameters::for_protocol(self.protocol_version)
595 }
596
597 pub fn get_feature_registry(&self) -> features::FeatureRegistry {
599 features::FeatureRegistry::for_protocol(self.protocol_version)
600 }
601
602 pub fn feature_context(&self, height: u64, timestamp: u64) -> features::FeatureContext {
605 let registry = features::FeatureRegistry::for_protocol(self.protocol_version);
606 registry.create_context(height, timestamp)
607 }
608}
609
610impl NetworkParameters {
611 pub fn for_version(version: ProtocolVersion) -> Result<Self> {
613 match version {
614 ProtocolVersion::BitcoinV1 => Self::mainnet(),
615 ProtocolVersion::Testnet3 => Self::testnet(),
616 ProtocolVersion::Regtest => Self::regtest(),
617 ProtocolVersion::Signet => Self::signet(),
618 }
619 }
620
621 pub fn mainnet() -> Result<Self> {
623 Ok(NetworkParameters {
624 magic_bytes: [0xf9, 0xbe, 0xb4, 0xd9], default_port: 8333,
626 genesis_block: genesis::mainnet_genesis(),
627 max_target: 0x1d00ffff,
628 halving_interval: 210000,
629 network_name: "mainnet".to_string(),
630 is_testnet: false,
631 signet_challenge: None,
632 })
633 }
634
635 pub fn testnet() -> Result<Self> {
637 Ok(NetworkParameters {
638 magic_bytes: [0x0b, 0x11, 0x09, 0x07], default_port: 18333,
640 genesis_block: genesis::testnet_genesis(),
641 max_target: 0x1d00ffff,
642 halving_interval: 210000,
643 network_name: "testnet".to_string(),
644 is_testnet: true,
645 signet_challenge: None,
646 })
647 }
648
649 pub fn regtest() -> Result<Self> {
651 Ok(NetworkParameters {
652 magic_bytes: [0xfa, 0xbf, 0xb5, 0xda], default_port: 18444,
654 genesis_block: genesis::regtest_genesis(),
655 max_target: 0x207fffff, halving_interval: 150, network_name: "regtest".to_string(),
658 is_testnet: true,
659 signet_challenge: None,
660 })
661 }
662
663 pub fn signet() -> Result<Self> {
665 Ok(NetworkParameters {
666 magic_bytes: [0x0f, 0x1b, 0xf2, 0xe1],
667 default_port: 38333,
668 genesis_block: genesis::signet_genesis(),
669 max_target: 0x1e0377ae,
670 halving_interval: 210_000,
671 network_name: "signet".to_string(),
672 is_testnet: true,
673 signet_challenge: None,
674 })
675 }
676}
677
678#[cfg(test)]
679mod tests {
680 use super::*;
681 use blvm_consensus::types::{BlockHeader, OutPoint, TransactionInput, TransactionOutput};
682
683 #[test]
684 fn test_blvm_protocol_creation() {
685 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
686 assert_eq!(engine.get_protocol_version(), ProtocolVersion::BitcoinV1);
687 assert_eq!(engine.get_network_params().network_name, "mainnet");
688 }
689
690 #[test]
691 fn test_blvm_protocol_creation_all_variants() {
692 let mainnet = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
694 assert_eq!(mainnet.get_protocol_version(), ProtocolVersion::BitcoinV1);
695 assert_eq!(mainnet.get_network_params().network_name, "mainnet");
696 assert!(!mainnet.get_network_params().is_testnet);
697
698 let testnet = BitcoinProtocolEngine::new(ProtocolVersion::Testnet3).unwrap();
700 assert_eq!(testnet.get_protocol_version(), ProtocolVersion::Testnet3);
701 assert_eq!(testnet.get_network_params().network_name, "testnet");
702 assert!(testnet.get_network_params().is_testnet);
703
704 let regtest = BitcoinProtocolEngine::new(ProtocolVersion::Regtest).unwrap();
706 assert_eq!(regtest.get_protocol_version(), ProtocolVersion::Regtest);
707 assert_eq!(regtest.get_network_params().network_name, "regtest");
708 assert!(regtest.get_network_params().is_testnet);
709
710 let signet = BitcoinProtocolEngine::new(ProtocolVersion::Signet).unwrap();
712 assert_eq!(signet.get_protocol_version(), ProtocolVersion::Signet);
713 assert_eq!(signet.get_network_params().network_name, "signet");
714 assert!(signet.get_network_params().is_testnet);
715 assert_eq!(signet.get_network_params().default_port, 38333);
716 }
717
718 #[test]
719 fn test_network_parameters() {
720 let mainnet = NetworkParameters::mainnet().unwrap();
721 assert_eq!(mainnet.magic_bytes, [0xf9, 0xbe, 0xb4, 0xd9]);
722 assert_eq!(mainnet.default_port, 8333);
723 assert!(!mainnet.is_testnet);
724
725 let testnet = NetworkParameters::testnet().unwrap();
726 assert_eq!(testnet.magic_bytes, [0x0b, 0x11, 0x09, 0x07]);
727 assert_eq!(testnet.default_port, 18333);
728 assert!(testnet.is_testnet);
729
730 let regtest = NetworkParameters::regtest().unwrap();
731 assert_eq!(regtest.magic_bytes, [0xfa, 0xbf, 0xb5, 0xda]);
732 assert_eq!(regtest.default_port, 18444);
733 assert!(regtest.is_testnet);
734 }
735
736 #[test]
737 fn test_network_parameters_consistency() {
738 let mainnet = NetworkParameters::mainnet().unwrap();
739 assert_eq!(mainnet.max_target, 0x1d00ffff);
740 assert_eq!(mainnet.halving_interval, 210000);
741
742 let testnet = NetworkParameters::testnet().unwrap();
743 assert_eq!(testnet.max_target, 0x1d00ffff);
744 assert_eq!(testnet.halving_interval, 210000);
745
746 let regtest = NetworkParameters::regtest().unwrap();
747 assert_eq!(regtest.max_target, 0x207fffff); assert_eq!(regtest.halving_interval, 150); }
750
751 #[test]
752 fn test_feature_support() {
753 let mainnet = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
754 assert!(mainnet.supports_feature("segwit"));
755 assert!(mainnet.supports_feature("taproot"));
756 assert!(mainnet.supports_feature("rbf"));
757 assert!(mainnet.supports_feature("ctv"));
758 assert!(!mainnet.supports_feature("fast_mining"));
759 assert!(!mainnet.supports_feature("nonexistent"));
760
761 let testnet = BitcoinProtocolEngine::new(ProtocolVersion::Testnet3).unwrap();
762 assert!(testnet.supports_feature("segwit"));
763 assert!(testnet.supports_feature("taproot"));
764 assert!(testnet.supports_feature("rbf"));
765 assert!(testnet.supports_feature("ctv"));
766 assert!(!testnet.supports_feature("fast_mining"));
767
768 let regtest = BitcoinProtocolEngine::new(ProtocolVersion::Regtest).unwrap();
769 assert!(regtest.supports_feature("segwit"));
770 assert!(regtest.supports_feature("taproot"));
771 assert!(regtest.supports_feature("rbf"));
772 assert!(regtest.supports_feature("ctv"));
773 assert!(regtest.supports_feature("fast_mining"));
774
775 let signet = BitcoinProtocolEngine::new(ProtocolVersion::Signet).unwrap();
776 assert!(signet.supports_feature("segwit"));
777 assert!(signet.supports_feature("taproot"));
778 assert!(signet.supports_feature("signet"));
779 assert!(!signet.supports_feature("fast_mining"));
780 }
781
782 #[test]
783 fn test_signet_challenge_override_on_engine() {
784 let engine = BitcoinProtocolEngine::new(ProtocolVersion::Signet)
785 .unwrap()
786 .with_signet_challenge(Some(vec![0x51]));
787 assert_eq!(
788 engine
789 .get_network_params()
790 .signet_challenge
791 .as_ref()
792 .map(|b| b.as_ref()),
793 Some([0x51].as_slice())
794 );
795 let ctx = engine.connect_block_validation_context(None::<&[BlockHeader]>, 0);
796 assert_eq!(
797 ctx.signet_challenge.as_ref().map(|b| b.as_ref()),
798 Some([0x51].as_slice())
799 );
800 }
801
802 #[test]
803 fn test_block_validation_empty_utxos() {
804 use crate::validation::ProtocolValidationContext;
805 use blvm_consensus::opcodes::OP_1;
806
807 let engine = BitcoinProtocolEngine::new(ProtocolVersion::Regtest).unwrap();
808 let utxos = UtxoSet::default();
809
810 let coinbase_tx = Transaction {
811 version: 2,
812 inputs: blvm_consensus::tx_inputs![TransactionInput {
813 prevout: OutPoint {
814 hash: [0u8; 32],
815 index: 0xffffffff,
816 },
817 script_sig: vec![0x00, 0xff],
818 sequence: 0xffffffff,
819 }],
820 outputs: blvm_consensus::tx_outputs![TransactionOutput {
821 value: 5_000_000_000,
822 script_pubkey: vec![OP_1],
823 }],
824 lock_time: 0,
825 };
826
827 let merkle_root = blvm_consensus::mining::calculate_merkle_root(&[coinbase_tx.clone()])
828 .expect("merkle root");
829
830 let block = Block {
831 header: BlockHeader {
832 version: 4,
833 prev_block_hash: [0u8; 32],
834 merkle_root,
835 timestamp: 1_231_006_505,
836 bits: 0x0300ffff,
837 nonce: 0,
838 },
839 transactions: vec![coinbase_tx].into_boxed_slice(),
840 };
841
842 let witnesses: Vec<Vec<blvm_consensus::segwit::Witness>> = block
843 .transactions
844 .iter()
845 .map(|tx| tx.inputs.iter().map(|_| Vec::new()).collect())
846 .collect();
847 let mut context = ProtocolValidationContext::new(ProtocolVersion::Regtest, 0).unwrap();
848 context.network_time = block.header.timestamp;
849 context.median_time_past = block.header.timestamp - 1;
850
851 let (result, new_utxos) = engine
852 .validate_and_connect_block(&block, &witnesses, &utxos, 0, None, &context)
853 .unwrap();
854 assert_eq!(result, ValidationResult::Valid);
855 assert!(!new_utxos.is_empty());
856 }
857
858 #[test]
859 fn test_transaction_validation() {
860 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
861
862 let tx = Transaction {
864 version: 1,
865 inputs: vec![TransactionInput {
866 prevout: OutPoint {
867 hash: [0u8; 32],
868 index: 0,
869 },
870 script_sig: vec![blvm_consensus::opcodes::PUSH_65_BYTES, 0x04],
871 sequence: 0xffffffff,
872 }]
873 .into(),
874 outputs: vec![TransactionOutput {
875 value: 50_0000_0000,
876 script_pubkey: vec![
877 blvm_consensus::opcodes::OP_DUP,
878 blvm_consensus::opcodes::OP_HASH160,
879 blvm_consensus::opcodes::PUSH_20_BYTES,
880 0x00,
881 0x00,
882 0x00,
883 0x00,
884 0x00,
885 0x00,
886 0x00,
887 0x00,
888 0x00,
889 0x00,
890 0x00,
891 0x00,
892 0x00,
893 0x00,
894 0x00,
895 0x00,
896 0x00,
897 0x00,
898 0x00,
899 0x00,
900 blvm_consensus::opcodes::OP_EQUALVERIFY,
901 blvm_consensus::opcodes::OP_CHECKSIG,
902 ], }]
904 .into(),
905 lock_time: 0,
906 };
907
908 let result = engine.validate_transaction(&tx);
909 assert!(result.is_ok());
910 }
911
912 #[test]
913 fn test_cross_protocol_validation() {
914 let mainnet_engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
915 let testnet_engine = BitcoinProtocolEngine::new(ProtocolVersion::Testnet3).unwrap();
916
917 assert_eq!(
919 mainnet_engine.supports_feature("segwit"),
920 testnet_engine.supports_feature("segwit")
921 );
922 assert_eq!(
923 mainnet_engine.supports_feature("taproot"),
924 testnet_engine.supports_feature("taproot")
925 );
926
927 assert_ne!(
929 mainnet_engine.get_network_params().magic_bytes,
930 testnet_engine.get_network_params().magic_bytes
931 );
932 assert_ne!(
933 mainnet_engine.get_network_params().default_port,
934 testnet_engine.get_network_params().default_port
935 );
936 }
937
938 #[test]
939 fn test_protocol_version_switching() {
940 let versions = vec![
942 ProtocolVersion::BitcoinV1,
943 ProtocolVersion::Testnet3,
944 ProtocolVersion::Regtest,
945 ProtocolVersion::Signet,
946 ];
947
948 for version in versions {
949 let engine = BitcoinProtocolEngine::new(version).unwrap();
950 assert_eq!(engine.get_protocol_version(), version);
951 }
952 }
953
954 #[test]
955 fn test_network_parameters_serialization() {
956 let mainnet = NetworkParameters::mainnet().unwrap();
957 let testnet = NetworkParameters::testnet().unwrap();
958 let regtest = NetworkParameters::regtest().unwrap();
959
960 let mainnet_json = serde_json::to_string(&mainnet).unwrap();
962 let mainnet_deserialized: NetworkParameters = serde_json::from_str(&mainnet_json).unwrap();
963 assert_eq!(mainnet.magic_bytes, mainnet_deserialized.magic_bytes);
964 assert_eq!(mainnet.default_port, mainnet_deserialized.default_port);
965 assert_eq!(mainnet.network_name, mainnet_deserialized.network_name);
966 assert_eq!(mainnet.is_testnet, mainnet_deserialized.is_testnet);
967
968 let testnet_json = serde_json::to_string(&testnet).unwrap();
969 let testnet_deserialized: NetworkParameters = serde_json::from_str(&testnet_json).unwrap();
970 assert_eq!(testnet.magic_bytes, testnet_deserialized.magic_bytes);
971
972 let regtest_json = serde_json::to_string(®test).unwrap();
973 let regtest_deserialized: NetworkParameters = serde_json::from_str(®test_json).unwrap();
974 assert_eq!(regtest.magic_bytes, regtest_deserialized.magic_bytes);
975 }
976
977 #[test]
978 fn test_protocol_version_serialization() {
979 let versions = vec![
980 ProtocolVersion::BitcoinV1,
981 ProtocolVersion::Testnet3,
982 ProtocolVersion::Regtest,
983 ProtocolVersion::Signet,
984 ];
985
986 for version in versions {
987 let json = serde_json::to_string(&version).unwrap();
988 let deserialized: ProtocolVersion = serde_json::from_str(&json).unwrap();
989 assert_eq!(version, deserialized);
990 }
991 }
992
993 #[test]
994 fn test_network_parameters_equality() {
995 let mainnet1 = NetworkParameters::mainnet().unwrap();
996 let mainnet2 = NetworkParameters::mainnet().unwrap();
997 let testnet = NetworkParameters::testnet().unwrap();
998
999 assert_eq!(mainnet1, mainnet2);
1000 assert_ne!(mainnet1, testnet);
1001 }
1002
1003 #[test]
1004 fn test_protocol_version_equality() {
1005 assert_eq!(ProtocolVersion::BitcoinV1, ProtocolVersion::BitcoinV1);
1006 assert_ne!(ProtocolVersion::BitcoinV1, ProtocolVersion::Testnet3);
1007 assert_ne!(ProtocolVersion::Testnet3, ProtocolVersion::Regtest);
1008 }
1009
1010 #[test]
1011 fn test_feature_activation_by_height() {
1012 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
1013
1014 assert!(!engine.is_feature_active("segwit", 481_823, 1503539000));
1016 assert!(engine.is_feature_active("segwit", 481_824, 1503539857));
1017 assert!(engine.is_feature_active("segwit", 500_000, 1504000000));
1018
1019 assert!(!engine.is_feature_active("taproot", 709_631, 1636934000));
1021 assert!(engine.is_feature_active("taproot", 709_632, 1636934400));
1022 assert!(engine.is_feature_active("taproot", 800_000, 1640000000));
1023 }
1024
1025 #[test]
1026 fn test_economic_parameters_access() {
1027 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
1028 let params = engine.get_economic_parameters();
1029
1030 assert_eq!(params.initial_subsidy, 50_0000_0000);
1031 assert_eq!(params.halving_interval, 210_000);
1032 assert_eq!(params.coinbase_maturity, 100);
1033
1034 assert_eq!(params.get_block_subsidy(0), 50_0000_0000);
1036 assert_eq!(params.get_block_subsidy(210_000), 25_0000_0000);
1037 }
1038
1039 #[test]
1040 fn test_feature_registry_access() {
1041 let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
1042 let registry = engine.get_feature_registry();
1043
1044 assert!(registry.get_feature("segwit").is_some());
1045 assert!(registry.get_feature("taproot").is_some());
1046 assert!(registry.get_feature("nonexistent").is_none());
1047
1048 let features = registry.list_features();
1049 assert!(features.contains(&"segwit".to_string()));
1050 assert!(features.contains(&"taproot".to_string()));
1051 }
1052}