// file: crates/ksp-raw-transaction-lib/unit_tests/wire.rs // version: 2 const LEGACY_GOLDEN_BASE64: &str = "AREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREBAAECISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIjExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExAQEBAAKquw=="; const V0_GOLDEN_BASE64: &str = "ARISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhKAAQAAASMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIBAAEBAcwBJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQBAAA="; const V1_EMPTY_CONFIG_GOLDEN_BASE64: &str = "gQEAAAAAAABSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUgABQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0Orq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6ur"; const V1_GOLDEN_BASE64: &str = "gQEAAR8AAABRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUQECQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQgcAAAAAAAAACAAAAAkAAAAAgAAAAQEDAAABAgOqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq"; fn legacy_wire() -> crate::RawSolanaTransactionWire { let message = crate::RawSolanaTransactionMessage::new( crate::RawSolanaMessageVersion::Legacy, crate::RawSolanaMessageHeader::new(1, 0, 1), vec![[0x21_u8; 32], [0x22_u8; 32]], [0x31_u8; 32], vec![crate::RawSolanaCompiledInstruction::new(1, vec![0], vec![0xaa, 0xbb])], vec![], std::option::Option::None, ); return crate::RawSolanaTransactionWire::new(vec![[0x11_u8; 64]], message); } fn v0_wire() -> crate::RawSolanaTransactionWire { let message = crate::RawSolanaTransactionMessage::new( crate::RawSolanaMessageVersion::V0, crate::RawSolanaMessageHeader::new(1, 0, 0), vec![[0x23_u8; 32]], [0x32_u8; 32], vec![crate::RawSolanaCompiledInstruction::new(0, vec![1], vec![0xcc])], vec![crate::RawSolanaAddressTableLookup::new([0x24_u8; 32], vec![0], vec![])], std::option::Option::None, ); return crate::RawSolanaTransactionWire::new(vec![[0x12_u8; 64]], message); } fn v1_wire() -> crate::RawSolanaTransactionWire { let message = crate::RawSolanaTransactionMessage::new( crate::RawSolanaMessageVersion::V1, crate::RawSolanaMessageHeader::new(1, 0, 1), vec![[0x41_u8; 32], [0x42_u8; 32]], [0x51_u8; 32], vec![crate::RawSolanaCompiledInstruction::new(1, vec![0], vec![1, 2, 3])], vec![], std::option::Option::Some(crate::RawSolanaTransactionConfig::new( std::option::Option::Some(7), std::option::Option::Some(8), std::option::Option::Some(9), std::option::Option::Some(32_768), )), ); return crate::RawSolanaTransactionWire::new(vec![[0xaa_u8; 64]], message); } fn v1_empty_config_wire() -> crate::RawSolanaTransactionWire { let message = crate::RawSolanaTransactionMessage::new( crate::RawSolanaMessageVersion::V1, crate::RawSolanaMessageHeader::new(1, 0, 0), vec![[0x43_u8; 32]], [0x52_u8; 32], vec![], vec![], std::option::Option::Some(crate::RawSolanaTransactionConfig::default()), ); return crate::RawSolanaTransactionWire::new(vec![[0xab_u8; 64]], message); } #[test] fn pre_006_legacy_v0_and_v1_wire_goldens_are_exact() { let legacy = crate::serialize_solana_transaction_wire_base64(&legacy_wire()); let v0 = crate::serialize_solana_transaction_wire_base64(&v0_wire()); let v1 = crate::serialize_solana_transaction_wire_base64(&v1_wire()); let v1_empty = crate::serialize_solana_transaction_wire_base64(&v1_empty_config_wire()); assert!(matches!(legacy.as_deref(), std::result::Result::Ok(value) if value == LEGACY_GOLDEN_BASE64)); assert!(matches!(v0.as_deref(), std::result::Result::Ok(value) if value == V0_GOLDEN_BASE64)); assert!(matches!(v1.as_deref(), std::result::Result::Ok(value) if value == V1_GOLDEN_BASE64)); assert!(matches!(v1_empty.as_deref(), std::result::Result::Ok(value) if value == V1_EMPTY_CONFIG_GOLDEN_BASE64)); let v1_bytes = crate::serialize_solana_transaction_wire(&v1_wire()); assert!(v1_bytes.is_ok()); if let std::result::Result::Ok(v1_bytes) = v1_bytes { assert_eq!(v1_bytes.len(), 198); assert_eq!(v1_bytes.first(), std::option::Option::Some(&0x81)); assert_eq!(v1_bytes.get(v1_bytes.len() - 64..), std::option::Option::Some([0xaa_u8; 64].as_slice())); } } #[test] fn pre_006_v1_structural_guards_reject_alt_duplicates_and_missing_config() { let mut missing_config = v1_wire(); missing_config.message.config = std::option::Option::None; assert!(crate::serialize_solana_transaction_wire(&missing_config).is_err()); let mut with_lookup = v1_wire(); with_lookup.message.address_table_lookups.push(crate::RawSolanaAddressTableLookup::new([9_u8; 32], vec![], vec![])); assert!(crate::serialize_solana_transaction_wire(&with_lookup).is_err()); let mut duplicate = v1_wire(); duplicate.message.account_keys[1] = duplicate.message.account_keys[0]; assert!(crate::serialize_solana_transaction_wire(&duplicate).is_err()); } #[test] fn pre_006_v1_program_index_zero_is_valid_and_bounds_remain_enforced() { let message = crate::RawSolanaTransactionMessage::new( crate::RawSolanaMessageVersion::V1, crate::RawSolanaMessageHeader::new(1, 0, 0), vec![[1_u8; 32]], [2_u8; 32], vec![crate::RawSolanaCompiledInstruction::new(0, vec![0], vec![])], vec![], std::option::Option::Some(crate::RawSolanaTransactionConfig::default()), ); let wire = crate::RawSolanaTransactionWire::new(vec![[3_u8; 64]], message); assert!(crate::serialize_solana_transaction_wire(&wire).is_ok()); let too_many_addresses = crate::RawSolanaTransactionMessage::new( crate::RawSolanaMessageVersion::V1, crate::RawSolanaMessageHeader::new(1, 0, 0), (0_u8..65_u8).map(|value| return [value; 32]).collect(), [2_u8; 32], vec![], vec![], std::option::Option::Some(crate::RawSolanaTransactionConfig::default()), ); let wire = crate::RawSolanaTransactionWire::new(vec![[3_u8; 64]], too_many_addresses); assert!(crate::serialize_solana_transaction_wire(&wire).is_err()); }