20260605 移除audit rule index和DB trace

This commit is contained in:
2026-06-05 16:02:25 +08:00
parent 9579f65501
commit e597c7c124
29 changed files with 4032 additions and 2298 deletions

View File

@@ -1,12 +1,13 @@
use super::*;
use crate::data_model::rc::ResourceCertificate;
use crate::data_model::roa::RoaAfi;
use crate::fetch::rsync::LocalDirRsyncFetcher;
use crate::fetch::rsync::{RsyncFetchError, RsyncFetcher};
use crate::storage::{
PackFile, PackTime, RawByHashEntry, RocksStore, ValidatedCaInstanceResult,
ValidatedManifestMeta, VcirArtifactKind, VcirArtifactRole, VcirArtifactValidationStatus,
VcirAuditSummary, VcirChildEntry, VcirInstanceGate, VcirLocalOutput, VcirOutputType,
VcirRelatedArtifact, VcirSummary,
VcirAuditSummary, VcirChildEntry, VcirInstanceGate, VcirLocalOutput, VcirLocalOutputPayload,
VcirOutputType, VcirRelatedArtifact, VcirSourceObjectType, VcirSummary,
};
use crate::sync::rrdp::Fetcher;
use crate::validation::publication_point::PublicationPointSnapshot;
@@ -16,6 +17,16 @@ use std::process::Command;
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
fn sha256_32(input: &[u8]) -> [u8; 32] {
sha256_hex_to_32(&sha256_hex(input))
}
fn ipv4_addr(octets: [u8; 4]) -> [u8; 16] {
let mut addr = [0u8; 16];
addr[..4].copy_from_slice(&octets);
addr
}
struct NeverHttpFetcher;
impl Fetcher for NeverHttpFetcher {
fn fetch(&self, _uri: &str) -> Result<Vec<u8>, String> {
@@ -534,138 +545,147 @@ fn sample_vcir_for_projection(
subordinate_skis: vec![vec![0x33; 20]],
};
ValidatedCaInstanceResult {
manifest_rsync_uri: manifest_uri.clone(),
parent_manifest_rsync_uri: None,
tal_id: "test-tal".to_string(),
ca_subject_name: "CN=Issuer".to_string(),
ca_ski: "11".repeat(20),
issuer_ski: "22".repeat(20),
last_successful_validation_time: PackTime::from_utc_offset_datetime(now),
current_manifest_rsync_uri: manifest_uri.clone(),
current_crl_rsync_uri: current_crl_uri.clone(),
validated_manifest_meta: ValidatedManifestMeta {
validated_manifest_number: vec![1],
validated_manifest_this_update: PackTime::from_utc_offset_datetime(now),
validated_manifest_next_update: gate_until.clone(),
manifest_rsync_uri: manifest_uri.clone(),
parent_manifest_rsync_uri: None,
tal_id: "test-tal".to_string(),
ca_subject_name: "CN=Issuer".to_string(),
ca_ski: "11".repeat(20),
issuer_ski: "22".repeat(20),
last_successful_validation_time: PackTime::from_utc_offset_datetime(now),
current_manifest_rsync_uri: manifest_uri.clone(),
current_crl_rsync_uri: current_crl_uri.clone(),
validated_manifest_meta: ValidatedManifestMeta {
validated_manifest_number: vec![1],
validated_manifest_this_update: PackTime::from_utc_offset_datetime(now),
validated_manifest_next_update: gate_until.clone(),
},
ccr_manifest_projection,
instance_gate: VcirInstanceGate {
manifest_next_update: gate_until.clone(),
current_crl_next_update: gate_until.clone(),
self_ca_not_after: PackTime::from_utc_offset_datetime(now + time::Duration::hours(2)),
instance_effective_until: gate_until.clone(),
},
child_entries: vec![VcirChildEntry {
child_manifest_rsync_uri: child_manifest_uri,
child_cert_rsync_uri: child_cert_uri.clone(),
child_cert_hash: child_cert_hash.to_string(),
child_ski: "33".repeat(20),
child_rsync_base_uri: "rsync://example.test/repo/child/".to_string(),
child_publication_point_rsync_uri: "rsync://example.test/repo/child/".to_string(),
child_rrdp_notification_uri: Some("https://example.test/child-notify.xml".to_string()),
child_effective_ip_resources: None,
child_effective_as_resources: None,
accepted_at_validation_time: PackTime::from_utc_offset_datetime(now),
}],
local_outputs: vec![
VcirLocalOutput {
output_type: VcirOutputType::Vrp,
item_effective_until: PackTime::from_utc_offset_datetime(
now + time::Duration::minutes(30),
),
source_object_uri: roa_uri.clone(),
source_object_type: VcirSourceObjectType::Roa,
source_object_hash: sha256_hex_to_32(&roa_hash),
source_ee_cert_hash: sha256_hex_to_32(&ee_hash),
payload: VcirLocalOutputPayload::Vrp {
asn: 64496,
afi: RoaAfi::Ipv4,
prefix_len: 24,
addr: ipv4_addr([203, 0, 113, 0]),
max_length: 24,
},
rule_hash: sha256_32(b"roa-rule"),
},
ccr_manifest_projection,
instance_gate: VcirInstanceGate {
manifest_next_update: gate_until.clone(),
current_crl_next_update: gate_until.clone(),
self_ca_not_after: PackTime::from_utc_offset_datetime(now + time::Duration::hours(2)),
instance_effective_until: gate_until.clone(),
VcirLocalOutput {
output_type: VcirOutputType::Aspa,
item_effective_until: PackTime::from_utc_offset_datetime(
now + time::Duration::minutes(30),
),
source_object_uri: aspa_uri.clone(),
source_object_type: VcirSourceObjectType::Aspa,
source_object_hash: sha256_hex_to_32(&aspa_hash),
source_ee_cert_hash: sha256_hex_to_32(&ee_hash),
payload: VcirLocalOutputPayload::Aspa {
customer_as_id: 64496,
provider_as_ids: vec![64497, 64498],
},
rule_hash: sha256_32(b"aspa-rule"),
},
child_entries: vec![VcirChildEntry {
child_manifest_rsync_uri: child_manifest_uri,
child_cert_rsync_uri: child_cert_uri.clone(),
child_cert_hash: child_cert_hash.to_string(),
child_ski: "33".repeat(20),
child_rsync_base_uri: "rsync://example.test/repo/child/".to_string(),
child_publication_point_rsync_uri: "rsync://example.test/repo/child/".to_string(),
child_rrdp_notification_uri: Some("https://example.test/child-notify.xml".to_string()),
child_effective_ip_resources: None,
child_effective_as_resources: None,
accepted_at_validation_time: PackTime::from_utc_offset_datetime(now),
}],
local_outputs: vec![
VcirLocalOutput {
output_id: sha256_hex(b"vrp-out"),
output_type: VcirOutputType::Vrp,
item_effective_until: PackTime::from_utc_offset_datetime(now + time::Duration::minutes(30)),
source_object_uri: roa_uri.clone(),
source_object_type: "roa".to_string(),
source_object_hash: roa_hash.clone(),
source_ee_cert_hash: ee_hash.clone(),
payload_json: serde_json::json!({"asn": 64496, "prefix": "203.0.113.0/24", "max_length": 24}).to_string(),
rule_hash: sha256_hex(b"roa-rule"),
validation_path_hint: vec![manifest_uri.clone(), roa_uri.clone()],
VcirLocalOutput {
output_type: VcirOutputType::RouterKey,
item_effective_until: PackTime::from_utc_offset_datetime(
now + time::Duration::minutes(30),
),
source_object_uri: router_uri.clone(),
source_object_type: VcirSourceObjectType::RouterKey,
source_object_hash: sha256_hex_to_32(&router_hash),
source_ee_cert_hash: sha256_hex_to_32(&router_hash),
payload: VcirLocalOutputPayload::RouterKey {
as_id: 64496,
ski: vec![0x11; 20],
spki_der: vec![0x30, 0x00],
},
VcirLocalOutput {
output_id: sha256_hex(b"aspa-out"),
output_type: VcirOutputType::Aspa,
item_effective_until: PackTime::from_utc_offset_datetime(now + time::Duration::minutes(30)),
source_object_uri: aspa_uri.clone(),
source_object_type: "aspa".to_string(),
source_object_hash: aspa_hash.clone(),
source_ee_cert_hash: ee_hash,
payload_json: serde_json::json!({"customer_as_id": 64496, "provider_as_ids": [64497, 64498]}).to_string(),
rule_hash: sha256_hex(b"aspa-rule"),
validation_path_hint: vec![manifest_uri.clone(), aspa_uri.clone()],
},
VcirLocalOutput {
output_id: sha256_hex(b"router-key-out"),
output_type: VcirOutputType::RouterKey,
item_effective_until: PackTime::from_utc_offset_datetime(now + time::Duration::minutes(30)),
source_object_uri: router_uri.clone(),
source_object_type: "router_key".to_string(),
source_object_hash: router_hash.clone(),
source_ee_cert_hash: router_hash.clone(),
payload_json: serde_json::json!({
"as_id": 64496,
"ski_hex": "11".repeat(20),
"spki_der_base64": base64::engine::general_purpose::STANDARD.encode([0x30u8, 0x00]),
}).to_string(),
rule_hash: sha256_hex(b"router-key-rule"),
validation_path_hint: vec![manifest_uri.clone(), router_uri.clone()],
},
],
related_artifacts: vec![
VcirRelatedArtifact {
artifact_role: VcirArtifactRole::Manifest,
artifact_kind: VcirArtifactKind::Mft,
uri: Some(manifest_uri.clone()),
sha256: manifest_hash,
object_type: Some("mft".to_string()),
validation_status: VcirArtifactValidationStatus::Accepted,
},
VcirRelatedArtifact {
artifact_role: VcirArtifactRole::CurrentCrl,
artifact_kind: VcirArtifactKind::Crl,
uri: Some(current_crl_uri),
sha256: current_crl_hash,
object_type: Some("crl".to_string()),
validation_status: VcirArtifactValidationStatus::Accepted,
},
VcirRelatedArtifact {
artifact_role: VcirArtifactRole::ChildCaCert,
artifact_kind: VcirArtifactKind::Cer,
uri: Some(child_cert_uri),
sha256: child_cert_hash.to_string(),
object_type: Some("cer".to_string()),
validation_status: VcirArtifactValidationStatus::Accepted,
},
VcirRelatedArtifact {
artifact_role: VcirArtifactRole::SignedObject,
artifact_kind: VcirArtifactKind::Roa,
uri: Some(roa_uri),
sha256: roa_hash,
object_type: Some("roa".to_string()),
validation_status: VcirArtifactValidationStatus::Accepted,
},
VcirRelatedArtifact {
artifact_role: VcirArtifactRole::SignedObject,
artifact_kind: VcirArtifactKind::Aspa,
uri: Some(aspa_uri),
sha256: aspa_hash,
object_type: Some("aspa".to_string()),
validation_status: VcirArtifactValidationStatus::Accepted,
},
],
summary: VcirSummary {
local_vrp_count: 1,
local_aspa_count: 1,
local_router_key_count: 1,
child_count: 1,
accepted_object_count: 4,
rejected_object_count: 0,
rule_hash: sha256_32(b"router-key-rule"),
},
audit_summary: VcirAuditSummary {
failed_fetch_eligible: true,
last_failed_fetch_reason: None,
warning_count: 0,
audit_flags: Vec::new(),
],
related_artifacts: vec![
VcirRelatedArtifact {
artifact_role: VcirArtifactRole::Manifest,
artifact_kind: VcirArtifactKind::Mft,
uri: Some(manifest_uri.clone()),
sha256: manifest_hash,
object_type: Some("mft".to_string()),
validation_status: VcirArtifactValidationStatus::Accepted,
},
}
VcirRelatedArtifact {
artifact_role: VcirArtifactRole::CurrentCrl,
artifact_kind: VcirArtifactKind::Crl,
uri: Some(current_crl_uri),
sha256: current_crl_hash,
object_type: Some("crl".to_string()),
validation_status: VcirArtifactValidationStatus::Accepted,
},
VcirRelatedArtifact {
artifact_role: VcirArtifactRole::ChildCaCert,
artifact_kind: VcirArtifactKind::Cer,
uri: Some(child_cert_uri),
sha256: child_cert_hash.to_string(),
object_type: Some("cer".to_string()),
validation_status: VcirArtifactValidationStatus::Accepted,
},
VcirRelatedArtifact {
artifact_role: VcirArtifactRole::SignedObject,
artifact_kind: VcirArtifactKind::Roa,
uri: Some(roa_uri),
sha256: roa_hash,
object_type: Some("roa".to_string()),
validation_status: VcirArtifactValidationStatus::Accepted,
},
VcirRelatedArtifact {
artifact_role: VcirArtifactRole::SignedObject,
artifact_kind: VcirArtifactKind::Aspa,
uri: Some(aspa_uri),
sha256: aspa_hash,
object_type: Some("aspa".to_string()),
validation_status: VcirArtifactValidationStatus::Accepted,
},
],
summary: VcirSummary {
local_vrp_count: 1,
local_aspa_count: 1,
local_router_key_count: 1,
child_count: 1,
accepted_object_count: 4,
rejected_object_count: 0,
},
audit_summary: VcirAuditSummary {
failed_fetch_eligible: true,
last_failed_fetch_reason: None,
warning_count: 0,
audit_flags: Vec::new(),
},
}
}
#[test]
@@ -716,16 +736,20 @@ fn build_vcir_local_outputs_prefers_cached_outputs() {
rrdp_notification_uri: None,
};
let cached = vec![VcirLocalOutput {
output_id: "cached-output".to_string(),
output_type: VcirOutputType::Vrp,
item_effective_until: pack.next_update.clone(),
source_object_uri: "rsync://example.test/repo/issuer/a.roa".to_string(),
source_object_type: "roa".to_string(),
source_object_hash: sha256_hex(b"cached-roa"),
source_ee_cert_hash: sha256_hex(b"cached-ee"),
payload_json: "{\"asn\":64500}".to_string(),
rule_hash: sha256_hex(b"cached-rule"),
validation_path_hint: vec![pack.manifest_rsync_uri.clone()],
source_object_type: VcirSourceObjectType::Roa,
source_object_hash: sha256_32(b"cached-roa"),
source_ee_cert_hash: sha256_32(b"cached-ee"),
payload: VcirLocalOutputPayload::Vrp {
asn: 64500,
afi: RoaAfi::Ipv4,
prefix_len: 24,
addr: ipv4_addr([203, 0, 113, 0]),
max_length: 24,
},
rule_hash: sha256_32(b"cached-rule"),
}];
let outputs = build_vcir_local_outputs(
&ca,
@@ -801,7 +825,7 @@ fn persist_vcir_non_repository_evidence_stores_current_ca_cert_only() {
.expect("first local output");
assert!(
store
.get_raw_by_hash_entry(&first_output.source_ee_cert_hash)
.get_raw_by_hash_entry(&first_output.source_ee_cert_hash_hex())
.expect("load source ee raw")
.is_none()
);
@@ -838,8 +862,11 @@ fn build_router_key_local_outputs_encodes_router_key_payloads() {
);
assert_eq!(outputs.len(), 1);
assert_eq!(outputs[0].output_type, VcirOutputType::RouterKey);
assert_eq!(outputs[0].source_object_type, "router_key");
assert!(outputs[0].payload_json.contains("spki_der_base64"));
assert_eq!(
outputs[0].source_object_type,
VcirSourceObjectType::RouterKey
);
assert!(outputs[0].payload_json().contains("spki_der_base64"));
}
#[test]
@@ -996,7 +1023,7 @@ fn finalize_fresh_publication_point_releases_local_outputs_cache_after_persist()
}
#[test]
fn persist_vcir_for_fresh_result_stores_vcir_and_audit_indexes_for_real_snapshot() {
fn persist_vcir_for_fresh_result_stores_vcir_and_replay_meta_for_real_snapshot() {
let (pack, issuer_ca_der, validation_time) = cernet_publication_point_snapshot_for_vcir_tests();
let issuer_ca = ResourceCertificate::decode_der(&issuer_ca_der).expect("decode issuer ca");
let objects = crate::validation::objects::process_publication_point_snapshot_for_issuer(
@@ -1029,8 +1056,18 @@ fn persist_vcir_for_fresh_result_stores_vcir_and_audit_indexes_for_real_snapshot
rrdp_notification_uri: None,
};
persist_vcir_for_fresh_result(&store, &ca, &pack, &objects, &[], &[], &[], validation_time)
.expect("persist vcir for fresh result");
let mut objects = objects;
persist_vcir_for_fresh_result(
&store,
&ca,
&pack,
&mut objects,
&[],
&[],
&[],
validation_time,
)
.expect("persist vcir for fresh result");
let vcir = store
.get_vcir(&pack.manifest_rsync_uri)
@@ -1054,12 +1091,15 @@ fn persist_vcir_for_fresh_result_stores_vcir_and_audit_indexes_for_real_snapshot
vcir.ccr_manifest_projection.manifest_size,
pack.manifest_bytes.len() as u64
);
let first_output = vcir.local_outputs.first().expect("local outputs stored");
assert!(
store
.get_audit_rule_index_entry(crate::storage::AuditRuleKind::Roa, &first_output.rule_hash)
.expect("get audit rule index entry")
.is_some()
assert!(vcir.local_outputs.first().is_some(), "local outputs stored");
let replay_meta = store
.get_manifest_replay_meta(&pack.manifest_rsync_uri)
.expect("get replay meta")
.expect("replay meta exists");
assert_eq!(replay_meta.manifest_rsync_uri, pack.manifest_rsync_uri);
assert_eq!(
replay_meta.manifest_sha256,
sha2::Sha256::digest(&pack.manifest_bytes).to_vec()
);
}
@@ -1531,26 +1571,16 @@ fn runner_offline_rsync_fixture_produces_pack_and_warnings() {
.iter()
.find(|output| output.output_type == crate::storage::VcirOutputType::Vrp)
.expect("first VCIR VRP output");
let audit_rule = store
.get_audit_rule_index_entry(crate::storage::AuditRuleKind::Roa, &first_vrp.rule_hash)
.expect("get audit rule index")
.expect("audit rule index exists");
assert_eq!(audit_rule.manifest_rsync_uri, manifest_rsync_uri);
assert_eq!(audit_rule.output_id, first_vrp.output_id);
let trace = crate::audit_trace::trace_rule_to_root(
&store,
crate::storage::AuditRuleKind::Roa,
&first_vrp.rule_hash,
)
.expect("trace rule")
.expect("trace exists");
assert_eq!(trace.chain_leaf_to_root.len(), 1);
assert!(!first_vrp.rule_hash_hex().is_empty());
assert!(!first_vrp.output_id().is_empty());
let replay_meta = store
.get_manifest_replay_meta(&manifest_rsync_uri)
.expect("get replay meta")
.expect("replay meta exists");
assert_eq!(
trace.chain_leaf_to_root[0].manifest_rsync_uri,
replay_meta.manifest_rsync_uri,
manifest_rsync_uri
);
assert!(trace.source_object_raw.raw_present);
assert!(trace.source_ee_cert_raw.raw_present);
}
#[test]
@@ -2791,10 +2821,11 @@ fn fresh_and_reuse_paths_produce_equivalent_ccr_manifest_projection() {
let child_discovery =
discover_children_from_fresh_snapshot_with_audit(&ca, &pack, validation_time, None)
.expect("discover children");
let mut objects = empty_objects_output();
let fresh_vcir = build_vcir_from_fresh_result(
&ca,
&pack,
&empty_objects_output(),
&mut objects,
&[],
&child_discovery.audits,
&child_discovery.children,
@@ -2913,70 +2944,77 @@ fn build_objects_output_from_vcir_tracks_expired_and_invalid_cached_outputs() {
}
vcir.local_outputs.push(VcirLocalOutput {
output_id: sha256_hex(b"bad-time"),
output_type: VcirOutputType::Vrp,
item_effective_until: PackTime {
rfc3339_utc: "bad-time-value".to_string(),
},
source_object_uri: bad_time_uri.clone(),
source_object_type: "roa".to_string(),
source_object_hash: sha256_hex(b"bad-time-src"),
source_ee_cert_hash: sha256_hex(b"bad-time-ee"),
payload_json:
serde_json::json!({"asn": 64496, "prefix": "203.0.113.0/24", "max_length": 24})
.to_string(),
rule_hash: sha256_hex(b"bad-time-rule"),
validation_path_hint: vec![vcir.manifest_rsync_uri.clone(), bad_time_uri.clone()],
source_object_type: VcirSourceObjectType::Roa,
source_object_hash: sha256_32(b"bad-time-src"),
source_ee_cert_hash: sha256_32(b"bad-time-ee"),
payload: VcirLocalOutputPayload::Vrp {
asn: 64496,
afi: RoaAfi::Ipv4,
prefix_len: 24,
addr: ipv4_addr([203, 0, 113, 0]),
max_length: 24,
},
rule_hash: sha256_32(b"bad-time-rule"),
});
vcir.local_outputs.push(VcirLocalOutput {
output_id: sha256_hex(b"expired"),
output_type: VcirOutputType::Aspa,
item_effective_until: PackTime::from_utc_offset_datetime(now - time::Duration::minutes(1)),
source_object_uri: expired_uri.clone(),
source_object_type: "aspa".to_string(),
source_object_hash: sha256_hex(b"expired-src"),
source_ee_cert_hash: sha256_hex(b"expired-ee"),
payload_json: serde_json::json!({"customer_as_id": 64500, "provider_as_ids": [64501]})
.to_string(),
rule_hash: sha256_hex(b"expired-rule"),
validation_path_hint: vec![vcir.manifest_rsync_uri.clone(), expired_uri.clone()],
source_object_type: VcirSourceObjectType::Aspa,
source_object_hash: sha256_32(b"expired-src"),
source_ee_cert_hash: sha256_32(b"expired-ee"),
payload: VcirLocalOutputPayload::Aspa {
customer_as_id: 64500,
provider_as_ids: vec![64501],
},
rule_hash: sha256_32(b"expired-rule"),
});
vcir.local_outputs.push(VcirLocalOutput {
output_id: sha256_hex(b"bad-json"),
output_type: VcirOutputType::Vrp,
item_effective_until: PackTime::from_utc_offset_datetime(now + time::Duration::minutes(5)),
source_object_uri: bad_json_uri.clone(),
source_object_type: "roa".to_string(),
source_object_hash: sha256_hex(b"bad-json-src"),
source_ee_cert_hash: sha256_hex(b"bad-json-ee"),
payload_json: "{not-json".to_string(),
rule_hash: sha256_hex(b"bad-json-rule"),
validation_path_hint: vec![vcir.manifest_rsync_uri.clone(), bad_json_uri.clone()],
source_object_type: VcirSourceObjectType::Roa,
source_object_hash: sha256_32(b"bad-json-src"),
source_ee_cert_hash: sha256_32(b"bad-json-ee"),
payload: VcirLocalOutputPayload::Aspa {
customer_as_id: 64510,
provider_as_ids: vec![64511],
},
rule_hash: sha256_32(b"bad-json-rule"),
});
vcir.local_outputs.push(VcirLocalOutput {
output_id: sha256_hex(b"bad-prefix"),
output_type: VcirOutputType::Vrp,
item_effective_until: PackTime::from_utc_offset_datetime(now + time::Duration::minutes(5)),
source_object_uri: bad_prefix_uri.clone(),
source_object_type: "roa".to_string(),
source_object_hash: sha256_hex(b"bad-prefix-src"),
source_ee_cert_hash: sha256_hex(b"bad-prefix-ee"),
payload_json: serde_json::json!({"asn": 64510, "prefix": "203.0.113.0", "max_length": 24})
.to_string(),
rule_hash: sha256_hex(b"bad-prefix-rule"),
validation_path_hint: vec![vcir.manifest_rsync_uri.clone(), bad_prefix_uri.clone()],
source_object_type: VcirSourceObjectType::Roa,
source_object_hash: sha256_32(b"bad-prefix-src"),
source_ee_cert_hash: sha256_32(b"bad-prefix-ee"),
payload: VcirLocalOutputPayload::Aspa {
customer_as_id: 64512,
provider_as_ids: vec![64513],
},
rule_hash: sha256_32(b"bad-prefix-rule"),
});
vcir.local_outputs.push(VcirLocalOutput {
output_id: sha256_hex(b"bad-aspa"),
output_type: VcirOutputType::Aspa,
item_effective_until: PackTime::from_utc_offset_datetime(now + time::Duration::minutes(5)),
source_object_uri: bad_aspa_uri.clone(),
source_object_type: "aspa".to_string(),
source_object_hash: sha256_hex(b"bad-aspa-src"),
source_ee_cert_hash: sha256_hex(b"bad-aspa-ee"),
payload_json: serde_json::json!({"customer_as_id": 64520}).to_string(),
rule_hash: sha256_hex(b"bad-aspa-rule"),
validation_path_hint: vec![vcir.manifest_rsync_uri.clone(), bad_aspa_uri.clone()],
source_object_type: VcirSourceObjectType::Aspa,
source_object_hash: sha256_32(b"bad-aspa-src"),
source_ee_cert_hash: sha256_32(b"bad-aspa-ee"),
payload: VcirLocalOutputPayload::Vrp {
asn: 64520,
afi: RoaAfi::Ipv4,
prefix_len: 24,
addr: ipv4_addr([198, 51, 100, 0]),
max_length: 24,
},
rule_hash: sha256_32(b"bad-aspa-rule"),
});
let mut warnings = Vec::new();