v0.3.10-pre.006
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
// file: crates/ksp-raw-transaction-lib/unit_tests/signature.rs
|
||||
// version: 2
|
||||
// version: 3
|
||||
|
||||
use base64::Engine; // rust-rules: trait-import
|
||||
|
||||
#[test]
|
||||
fn pre_002_signature_parser_accepts_exact_sixty_four_zero_bytes() {
|
||||
@@ -60,3 +62,20 @@ fn pre_004_embedded_signature_rejects_invalid_base64_noncanonical_short_vec_and_
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_006_embedded_signature_extracts_terminal_v1_signature_and_rejects_trailing_bytes() {
|
||||
let encoded = "gQEAAR8AAABRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUQECQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQgcAAAAAAAAACAAAAAkAAAAAgAAAAQEDAAABAgOqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq";
|
||||
let signature = crate::extract_raw_transaction_signature_from_binary_base64(encoded);
|
||||
assert!(signature.is_ok());
|
||||
if let std::result::Result::Ok(signature) = signature {
|
||||
assert_eq!(signature.as_bytes(), &[0xaa_u8; 64]);
|
||||
}
|
||||
let decoded = base64::engine::general_purpose::STANDARD.decode(encoded);
|
||||
assert!(decoded.is_ok());
|
||||
if let std::result::Result::Ok(mut decoded) = decoded {
|
||||
decoded.push(0);
|
||||
let trailing = base64::engine::general_purpose::STANDARD.encode(decoded);
|
||||
assert!(crate::extract_raw_transaction_signature_from_binary_base64(trailing.as_str()).is_err());
|
||||
}
|
||||
}
|
||||
|
||||
122
crates/ksp-raw-transaction-lib/unit_tests/wire.rs
Normal file
122
crates/ksp-raw-transaction-lib/unit_tests/wire.rs
Normal file
@@ -0,0 +1,122 @@
|
||||
// file: crates/ksp-raw-transaction-lib/unit_tests/wire.rs
|
||||
// version: 1
|
||||
|
||||
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_eq!(legacy.as_deref(), std::result::Result::Ok(LEGACY_GOLDEN_BASE64));
|
||||
assert_eq!(v0.as_deref(), std::result::Result::Ok(V0_GOLDEN_BASE64));
|
||||
assert_eq!(v1.as_deref(), std::result::Result::Ok(V1_GOLDEN_BASE64));
|
||||
assert_eq!(v1_empty.as_deref(), std::result::Result::Ok(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());
|
||||
}
|
||||
Reference in New Issue
Block a user