0.3.16-pre.005
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-store-api/unit_tests/model/raw_transaction.rs
|
||||
// version: 3
|
||||
// version: 5
|
||||
|
||||
fn network() -> std::option::Option<crate::RawNetworkId> {
|
||||
return match crate::RawNetworkId::new("mainnet".to_owned()) {
|
||||
@@ -140,3 +140,121 @@ fn transaction_variant_codes_and_outcomes_are_stable_backend_neutral_contracts()
|
||||
assert_ne!(crate::RawTransactionVariantWriteOutcome::QuarantinedConflict, crate::RawTransactionVariantWriteOutcome::PromotedCompatibleMoreComplete);
|
||||
return;
|
||||
}
|
||||
|
||||
fn comparison_transaction(payload_bytes: &[u8], hash_byte: u8) -> std::option::Option<crate::RawTransaction> {
|
||||
let network = match network() {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return std::option::Option::None,
|
||||
};
|
||||
let format = match crate::RawFormatId::new("ksp.solana.raw_transaction".to_owned()) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return std::option::Option::None,
|
||||
};
|
||||
let payload = match crate::RawPayload::try_new(format, 1, payload_bytes.to_vec().into_boxed_slice(), crate::RawContentHash::new([hash_byte; 32])) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return std::option::Option::None,
|
||||
};
|
||||
let reference = crate::RawTransactionReference::new(network, crate::RawTransactionSignature::new([21_u8; 64]));
|
||||
return std::option::Option::Some(crate::RawTransaction::new(reference, 88, std::option::Option::None, payload));
|
||||
}
|
||||
|
||||
fn comparison_relation(
|
||||
canonical_payload: &[u8],
|
||||
canonical_hash: u8,
|
||||
incoming_payload: &[u8],
|
||||
incoming_hash: u8,
|
||||
) -> std::option::Option<crate::RawTransactionVariantComparison> {
|
||||
let canonical = match comparison_transaction(canonical_payload, canonical_hash) {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return std::option::Option::None,
|
||||
};
|
||||
let incoming = match comparison_transaction(incoming_payload, incoming_hash) {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return std::option::Option::None,
|
||||
};
|
||||
return crate::compare_raw_transaction_variants(&canonical, &incoming).ok();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn v0_3_16_pre_005_comparator_proves_bidirectional_log_messages_truncation_only() {
|
||||
let full = br#"{"transaction":["AQID","base64"],"meta":{"err":null,"fee":5000,"logMessages":["Program Vote111 invoke [1]","Program log: stable","Program Vote111 success"],"rewards":[]},"version":0,"transactionIndex":7}"#;
|
||||
let truncated = br#"{"transaction":["AQID","base64"],"meta":{"err":null,"fee":5000,"logMessages":["Program Vote111 invoke [1]","Program log: stable","Log truncated"],"rewards":[]},"version":0,"transactionIndex":7}"#;
|
||||
let less = match comparison_relation(full, 31, truncated, 32) {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return,
|
||||
};
|
||||
assert_eq!(less.relation(), crate::RawTransactionVariantRelation::CompatibleLessComplete);
|
||||
assert_eq!(less.reason(), crate::RawTransactionVariantRelationReason::IncomingLogMessagesTruncated);
|
||||
let more = match comparison_relation(truncated, 32, full, 31) {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return,
|
||||
};
|
||||
assert_eq!(more.relation(), crate::RawTransactionVariantRelation::CompatibleMoreComplete);
|
||||
assert_eq!(more.reason(), crate::RawTransactionVariantRelationReason::CanonicalLogMessagesTruncated);
|
||||
return;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn v0_3_16_pre_005_comparator_rejects_unproved_log_shortening_and_marker_shapes() {
|
||||
let full = br#"{"transaction":["AQID","base64"],"meta":{"err":null,"fee":5000,"logMessages":["a","b","c"],"rewards":[]},"version":0}"#;
|
||||
let shorter = br#"{"transaction":["AQID","base64"],"meta":{"err":null,"fee":5000,"logMessages":["a","b"],"rewards":[]},"version":0}"#;
|
||||
let marker_not_last =
|
||||
br#"{"transaction":["AQID","base64"],"meta":{"err":null,"fee":5000,"logMessages":["a","Log truncated","c"],"rewards":[]},"version":0}"#;
|
||||
let marker_not_exact =
|
||||
br#"{"transaction":["AQID","base64"],"meta":{"err":null,"fee":5000,"logMessages":["a","b","Log truncated by provider"],"rewards":[]},"version":0}"#;
|
||||
let bad_prefix =
|
||||
br#"{"transaction":["AQID","base64"],"meta":{"err":null,"fee":5000,"logMessages":["a","changed","Log truncated"],"rewards":[]},"version":0}"#;
|
||||
let candidates: [&[u8]; 4] = [shorter, marker_not_last, marker_not_exact, bad_prefix];
|
||||
for (index, candidate) in candidates.iter().enumerate() {
|
||||
let hash_offset = match u8::try_from(index) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return,
|
||||
};
|
||||
let comparison = match comparison_relation(full, 40, candidate, 41 + hash_offset) {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return,
|
||||
};
|
||||
assert_eq!(comparison.relation(), crate::RawTransactionVariantRelation::Conflict);
|
||||
assert_eq!(comparison.reason(), crate::RawTransactionVariantRelationReason::CanonicalPayloadConflict);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn v0_3_16_pre_005_comparator_is_fail_closed_for_optional_and_other_payload_differences() {
|
||||
let canonical = br#"{"transaction":["AQID","base64"],"meta":{"fee":5000,"logMessages":["a"],"returnData":null},"version":0}"#;
|
||||
let optional_value =
|
||||
br#"{"transaction":["AQID","base64"],"meta":{"fee":5000,"logMessages":["a"],"returnData":{"data":["","base64"],"programId":"Vote111"}},"version":0}"#;
|
||||
let concrete_conflict = br#"{"transaction":["AQID","base64"],"meta":{"fee":5001,"logMessages":["a"],"returnData":null},"version":0}"#;
|
||||
let optional = match comparison_relation(canonical, 50, optional_value, 51) {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return,
|
||||
};
|
||||
assert_eq!(optional.relation(), crate::RawTransactionVariantRelation::Incomparable);
|
||||
assert_eq!(optional.reason(), crate::RawTransactionVariantRelationReason::UnsupportedCanonicalDifference);
|
||||
let conflict = match comparison_relation(canonical, 50, concrete_conflict, 52) {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return,
|
||||
};
|
||||
assert_eq!(conflict.relation(), crate::RawTransactionVariantRelation::Conflict);
|
||||
assert_eq!(conflict.reason(), crate::RawTransactionVariantRelationReason::CanonicalPayloadConflict);
|
||||
return;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn v0_3_16_pre_005_comparator_uses_exact_bytes_and_detects_hash_collision_without_hash_equality_shortcut() {
|
||||
let canonical = br#"{"transaction":["AQID","base64"],"meta":{"logMessages":["a"]}}"#;
|
||||
let same_bytes = match comparison_relation(canonical, 60, canonical, 61) {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return,
|
||||
};
|
||||
assert_eq!(same_bytes.relation(), crate::RawTransactionVariantRelation::Exact);
|
||||
let different = br#"{"transaction":["AQID","base64"],"meta":{"logMessages":["b"]}}"#;
|
||||
let collision = match comparison_relation(canonical, 62, different, 62) {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return,
|
||||
};
|
||||
assert_eq!(collision.relation(), crate::RawTransactionVariantRelation::Conflict);
|
||||
assert_eq!(collision.reason(), crate::RawTransactionVariantRelationReason::ContentHashCollision);
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user