20260626_2 优化child证书缓存并修复远端发布
This commit is contained in:
@@ -1464,6 +1464,7 @@ mod tests {
|
||||
child_ca_certificate_rsync_uri: "rsync://example.test/repo/child.cer".to_string(),
|
||||
child_ca_certificate_sha256_hex: "00".repeat(32),
|
||||
},
|
||||
child_entry_projection: None,
|
||||
};
|
||||
|
||||
runtime
|
||||
|
||||
@@ -196,10 +196,16 @@ pub struct PublicationPointRunResult {
|
||||
pub discovered_children: Vec<DiscoveredChildCaInstance>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct DiscoveredChildEntryProjection {
|
||||
pub child_ski: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct DiscoveredChildCaInstance {
|
||||
pub handle: CaInstanceHandle,
|
||||
pub discovered_from: DiscoveredFrom,
|
||||
pub child_entry_projection: Option<DiscoveredChildEntryProjection>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
@@ -495,6 +501,7 @@ mod tests {
|
||||
.to_string(),
|
||||
child_ca_certificate_sha256_hex: "00".repeat(32),
|
||||
},
|
||||
child_entry_projection: None,
|
||||
}]
|
||||
} else {
|
||||
Vec::new()
|
||||
|
||||
@@ -2444,6 +2444,7 @@ mod tests {
|
||||
.to_string(),
|
||||
child_ca_certificate_sha256_hex: "55".repeat(32),
|
||||
},
|
||||
child_entry_projection: None,
|
||||
});
|
||||
let output = FreshPublicationPointFinalizeOutput {
|
||||
result,
|
||||
|
||||
@@ -57,8 +57,8 @@ use crate::validation::objects::{
|
||||
};
|
||||
use crate::validation::publication_point::PublicationPointSnapshot;
|
||||
use crate::validation::tree::{
|
||||
CaCertificateRef, CaInstanceHandle, DiscoveredChildCaInstance, PublicationPointRunResult,
|
||||
PublicationPointRunner,
|
||||
CaCertificateRef, CaInstanceHandle, DiscoveredChildCaInstance, DiscoveredChildEntryProjection,
|
||||
PublicationPointRunResult, PublicationPointRunner,
|
||||
};
|
||||
use sha2::Digest;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
@@ -2689,6 +2689,7 @@ fn discover_children_from_fresh_snapshot_with_audit_cached_with_issuer_der<
|
||||
match &projection.payload {
|
||||
ChildCertificateCachePayload::ChildCa {
|
||||
child_manifest_rsync_uri,
|
||||
child_ski,
|
||||
child_rsync_base_uri,
|
||||
child_publication_point_rsync_uri,
|
||||
child_rrdp_notification_uri,
|
||||
@@ -2735,6 +2736,11 @@ fn discover_children_from_fresh_snapshot_with_audit_cached_with_issuer_der<
|
||||
child_ca_certificate_sha256_hex:
|
||||
child_cert_sha256_hex.clone(),
|
||||
},
|
||||
child_entry_projection: Some(
|
||||
DiscoveredChildEntryProjection {
|
||||
child_ski: child_ski.clone(),
|
||||
},
|
||||
),
|
||||
});
|
||||
ca_ok = ca_ok.saturating_add(1);
|
||||
child_cert_cache_hit =
|
||||
@@ -3145,6 +3151,15 @@ fn discover_children_from_fresh_snapshot_with_audit_cached_with_issuer_der<
|
||||
child_ca_certificate_rsync_uri: f.rsync_uri.clone(),
|
||||
child_ca_certificate_sha256_hex: child_cert_sha256_hex.clone(),
|
||||
},
|
||||
child_entry_projection: validated
|
||||
.child_ca
|
||||
.tbs
|
||||
.extensions
|
||||
.subject_key_identifier
|
||||
.as_ref()
|
||||
.map(|child_ski| DiscoveredChildEntryProjection {
|
||||
child_ski: hex::encode(child_ski),
|
||||
}),
|
||||
});
|
||||
enqueue_nanos =
|
||||
enqueue_nanos.saturating_add(t3.elapsed().as_nanos().min(u128::from(u64::MAX)) as u64);
|
||||
@@ -4857,6 +4872,9 @@ fn restore_children_from_vcir(
|
||||
child_ca_certificate_rsync_uri: child.child_cert_rsync_uri.clone(),
|
||||
child_ca_certificate_sha256_hex: child.child_cert_hash.clone(),
|
||||
},
|
||||
child_entry_projection: Some(DiscoveredChildEntryProjection {
|
||||
child_ski: child.child_ski.clone(),
|
||||
}),
|
||||
});
|
||||
audits.push(ObjectAuditEntry {
|
||||
rsync_uri: child.child_cert_rsync_uri.clone(),
|
||||
@@ -5073,6 +5091,9 @@ fn publication_point_cache_discovered_child(
|
||||
child_ca_certificate_rsync_uri: child.child_cert_rsync_uri.clone(),
|
||||
child_ca_certificate_sha256_hex: child.child_cert_hash.clone(),
|
||||
},
|
||||
child_entry_projection: Some(DiscoveredChildEntryProjection {
|
||||
child_ski: child.child_ski.clone(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5713,15 +5734,21 @@ fn build_vcir_child_entries(
|
||||
) -> Result<Vec<VcirChildEntry>, String> {
|
||||
let mut out = Vec::with_capacity(discovered_children.len());
|
||||
for child in discovered_children {
|
||||
let child_der = child.handle.ca_certificate_der(store)?;
|
||||
let child_cert = ResourceCertificate::decode_der(child_der.as_ref())
|
||||
.map_err(|e| format!("decode child certificate for VCIR failed: {e}"))?;
|
||||
let child_ski = child_cert
|
||||
.tbs
|
||||
.extensions
|
||||
.subject_key_identifier
|
||||
.as_ref()
|
||||
.ok_or_else(|| "child certificate missing SubjectKeyIdentifier".to_string())?;
|
||||
let child_ski = match child.child_entry_projection.as_ref() {
|
||||
Some(projection) => projection.child_ski.clone(),
|
||||
None => {
|
||||
let child_der = child.handle.ca_certificate_der(store)?;
|
||||
let child_cert = ResourceCertificate::decode_der(child_der.as_ref())
|
||||
.map_err(|e| format!("decode child certificate for VCIR failed: {e}"))?;
|
||||
let child_ski = child_cert
|
||||
.tbs
|
||||
.extensions
|
||||
.subject_key_identifier
|
||||
.as_ref()
|
||||
.ok_or_else(|| "child certificate missing SubjectKeyIdentifier".to_string())?;
|
||||
hex::encode(child_ski)
|
||||
}
|
||||
};
|
||||
out.push(VcirChildEntry {
|
||||
child_manifest_rsync_uri: child.handle.manifest_rsync_uri.clone(),
|
||||
child_cert_rsync_uri: child.discovered_from.child_ca_certificate_rsync_uri.clone(),
|
||||
@@ -5729,7 +5756,7 @@ fn build_vcir_child_entries(
|
||||
.discovered_from
|
||||
.child_ca_certificate_sha256_hex
|
||||
.clone(),
|
||||
child_ski: hex::encode(child_ski),
|
||||
child_ski,
|
||||
child_rsync_base_uri: child.handle.rsync_base_uri.clone(),
|
||||
child_publication_point_rsync_uri: child.handle.publication_point_rsync_uri.clone(),
|
||||
child_rrdp_notification_uri: child.handle.rrdp_notification_uri.clone(),
|
||||
|
||||
@@ -13,7 +13,7 @@ use crate::storage::{
|
||||
};
|
||||
use crate::sync::rrdp::Fetcher;
|
||||
use crate::validation::publication_point::PublicationPointSnapshot;
|
||||
use crate::validation::tree::PublicationPointRunner;
|
||||
use crate::validation::tree::{DiscoveredChildEntryProjection, PublicationPointRunner};
|
||||
|
||||
use std::process::Command;
|
||||
use std::sync::Arc;
|
||||
@@ -1210,6 +1210,45 @@ fn build_vcir_ccr_manifest_projection_from_fresh_real_snapshot_matches_manifest_
|
||||
assert_eq!(projection.subordinate_skis, expected_subordinate_skis);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_vcir_child_entries_uses_projection_without_repo_bytes() {
|
||||
let store_dir = tempfile::tempdir().expect("store dir");
|
||||
let store = RocksStore::open(store_dir.path()).expect("open rocksdb");
|
||||
let validation_time = time::OffsetDateTime::parse(
|
||||
"2026-06-26T00:00:00Z",
|
||||
&time::format_description::well_known::Rfc3339,
|
||||
)
|
||||
.expect("parse time");
|
||||
let child = DiscoveredChildCaInstance {
|
||||
handle: CaInstanceHandle {
|
||||
depth: 1,
|
||||
tal_id: "test-tal".to_string(),
|
||||
parent_manifest_rsync_uri: Some("rsync://example.test/repo/root.mft".to_string()),
|
||||
ca_certificate: CaCertificateRef::repo_bytes("aa".repeat(32)),
|
||||
ca_certificate_rsync_uri: Some("rsync://example.test/repo/child.cer".to_string()),
|
||||
effective_ip_resources: None,
|
||||
effective_as_resources: None,
|
||||
rsync_base_uri: "rsync://example.test/repo/child/".to_string(),
|
||||
manifest_rsync_uri: "rsync://example.test/repo/child/child.mft".to_string(),
|
||||
publication_point_rsync_uri: "rsync://example.test/repo/child/".to_string(),
|
||||
rrdp_notification_uri: Some("https://example.test/notify.xml".to_string()),
|
||||
},
|
||||
discovered_from: crate::audit::DiscoveredFrom {
|
||||
parent_manifest_rsync_uri: "rsync://example.test/repo/root.mft".to_string(),
|
||||
child_ca_certificate_rsync_uri: "rsync://example.test/repo/child.cer".to_string(),
|
||||
child_ca_certificate_sha256_hex: "aa".repeat(32),
|
||||
},
|
||||
child_entry_projection: Some(DiscoveredChildEntryProjection {
|
||||
child_ski: "11".repeat(20),
|
||||
}),
|
||||
};
|
||||
|
||||
let entries = build_vcir_child_entries(&store, &[child], validation_time)
|
||||
.expect("projection should avoid repo-bytes load");
|
||||
assert_eq!(entries.len(), 1);
|
||||
assert_eq!(entries[0].child_ski, "11".repeat(20));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_vcir_related_artifacts_classifies_snapshot_files_and_audit_statuses() {
|
||||
let manifest_bytes = std::fs::read(
|
||||
@@ -5036,3 +5075,448 @@ fn runner_dedup_paths_execute_with_timing_enabled() {
|
||||
"rsync://example.test/repo/"
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct RipeRootFinalizeFixtureEvent {
|
||||
event_type: String,
|
||||
validation_time: String,
|
||||
pp_manifest_uri: Option<String>,
|
||||
object_uri: Option<String>,
|
||||
sha256: Option<String>,
|
||||
object_type: Option<String>,
|
||||
result: Option<String>,
|
||||
reason: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct RipeRootFinalizeObject {
|
||||
uri: String,
|
||||
sha256_hex: String,
|
||||
object_type: String,
|
||||
result: String,
|
||||
reason: Option<String>,
|
||||
}
|
||||
|
||||
struct RipeRootFinalizeFixture {
|
||||
manifest_uri: String,
|
||||
publication_point_uri: String,
|
||||
validation_time: time::OffsetDateTime,
|
||||
manifest_sha256_hex: String,
|
||||
objects: Vec<RipeRootFinalizeObject>,
|
||||
}
|
||||
|
||||
fn load_ripe_root_finalize_fixture(
|
||||
fixture_root: &std::path::Path,
|
||||
run_id: &str,
|
||||
) -> RipeRootFinalizeFixture {
|
||||
let events_path = fixture_root
|
||||
.join(format!("run_{run_id}"))
|
||||
.join("ripe-root-events.jsonl");
|
||||
let file = std::fs::File::open(&events_path)
|
||||
.unwrap_or_else(|e| panic!("open fixture events {} failed: {e}", events_path.display()));
|
||||
let reader = std::io::BufReader::new(file);
|
||||
let mut manifest_uri = None;
|
||||
let mut validation_time = None;
|
||||
let mut manifest_sha256_hex = None;
|
||||
let mut objects = Vec::new();
|
||||
|
||||
for line in std::io::BufRead::lines(reader) {
|
||||
let line = line.expect("read fixture event line");
|
||||
let event: RipeRootFinalizeFixtureEvent =
|
||||
serde_json::from_str(&line).expect("decode fixture event");
|
||||
if event.event_type == "publication_point" {
|
||||
manifest_uri = event.pp_manifest_uri;
|
||||
validation_time = Some(
|
||||
time::OffsetDateTime::parse(
|
||||
&event.validation_time,
|
||||
&time::format_description::well_known::Rfc3339,
|
||||
)
|
||||
.expect("parse validation_time"),
|
||||
);
|
||||
continue;
|
||||
}
|
||||
if event.event_type != "object" {
|
||||
continue;
|
||||
}
|
||||
let uri = event.object_uri.expect("fixture object uri");
|
||||
let sha256_hex = event.sha256.expect("fixture object sha256");
|
||||
let object_type = event.object_type.expect("fixture object type");
|
||||
let result = event.result.expect("fixture object result");
|
||||
if object_type == "manifest" {
|
||||
manifest_sha256_hex = Some(sha256_hex.clone());
|
||||
}
|
||||
objects.push(RipeRootFinalizeObject {
|
||||
uri,
|
||||
sha256_hex,
|
||||
object_type,
|
||||
result,
|
||||
reason: event.reason,
|
||||
});
|
||||
}
|
||||
|
||||
let manifest_uri = manifest_uri.expect("fixture publication_point event");
|
||||
let publication_point_uri = manifest_uri
|
||||
.rsplit_once('/')
|
||||
.map(|(parent, _)| format!("{parent}/"))
|
||||
.expect("manifest uri parent");
|
||||
RipeRootFinalizeFixture {
|
||||
manifest_uri,
|
||||
publication_point_uri,
|
||||
validation_time: validation_time.expect("fixture validation_time"),
|
||||
manifest_sha256_hex: manifest_sha256_hex.expect("fixture manifest object"),
|
||||
objects,
|
||||
}
|
||||
}
|
||||
|
||||
fn pack_file_from_fixture_object(
|
||||
object: &RipeRootFinalizeObject,
|
||||
repo_bytes: &Arc<crate::blob_store::ExternalRepoBytesDb>,
|
||||
) -> PackFile {
|
||||
PackFile::from_lazy_repo_bytes(
|
||||
object.uri.clone(),
|
||||
object.sha256_hex.clone(),
|
||||
sha256_hex_to_32(&object.sha256_hex),
|
||||
repo_bytes.clone(),
|
||||
)
|
||||
}
|
||||
|
||||
fn child_audit_from_fixture_object(object: &RipeRootFinalizeObject) -> ObjectAuditEntry {
|
||||
ObjectAuditEntry {
|
||||
rsync_uri: object.uri.clone(),
|
||||
sha256_hex: object.sha256_hex.clone(),
|
||||
kind: AuditObjectKind::Certificate,
|
||||
result: match object.result.as_str() {
|
||||
"ok" => AuditObjectResult::Ok,
|
||||
"skipped" => AuditObjectResult::Skipped,
|
||||
_ => AuditObjectResult::Error,
|
||||
},
|
||||
detail: object.reason.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn discovered_child_from_fixture_object(
|
||||
issuer: &CaInstanceHandle,
|
||||
object: &RipeRootFinalizeObject,
|
||||
child_entry_projection: Option<DiscoveredChildEntryProjection>,
|
||||
) -> DiscoveredChildCaInstance {
|
||||
let stem = object
|
||||
.uri
|
||||
.rsplit_once('/')
|
||||
.map(|(_, file)| file.trim_end_matches(".cer"))
|
||||
.unwrap_or("child");
|
||||
let child_publication_point = format!("{}synthetic-child-{stem}/", issuer.rsync_base_uri);
|
||||
let child_manifest = format!("{child_publication_point}child.mft");
|
||||
DiscoveredChildCaInstance {
|
||||
handle: CaInstanceHandle {
|
||||
depth: issuer.depth + 1,
|
||||
tal_id: issuer.tal_id.clone(),
|
||||
parent_manifest_rsync_uri: Some(issuer.manifest_rsync_uri.clone()),
|
||||
ca_certificate: CaCertificateRef::repo_bytes(object.sha256_hex.clone()),
|
||||
ca_certificate_rsync_uri: Some(object.uri.clone()),
|
||||
effective_ip_resources: None,
|
||||
effective_as_resources: None,
|
||||
rsync_base_uri: child_publication_point.clone(),
|
||||
manifest_rsync_uri: child_manifest,
|
||||
publication_point_rsync_uri: child_publication_point,
|
||||
rrdp_notification_uri: issuer.rrdp_notification_uri.clone(),
|
||||
},
|
||||
discovered_from: crate::audit::DiscoveredFrom {
|
||||
parent_manifest_rsync_uri: issuer.manifest_rsync_uri.clone(),
|
||||
child_ca_certificate_rsync_uri: object.uri.clone(),
|
||||
child_ca_certificate_sha256_hex: object.sha256_hex.clone(),
|
||||
},
|
||||
child_entry_projection,
|
||||
}
|
||||
}
|
||||
|
||||
fn child_entry_projection_from_fixture_object(
|
||||
store: &RocksStore,
|
||||
object: &RipeRootFinalizeObject,
|
||||
) -> DiscoveredChildEntryProjection {
|
||||
let child_der = store
|
||||
.get_blob_bytes(&object.sha256_hex)
|
||||
.expect("load child certificate bytes for projection")
|
||||
.expect("child certificate bytes exist for projection");
|
||||
let child_cert =
|
||||
ResourceCertificate::decode_der(&child_der).expect("decode child certificate projection");
|
||||
let child_ski = child_cert
|
||||
.tbs
|
||||
.extensions
|
||||
.subject_key_identifier
|
||||
.as_ref()
|
||||
.expect("child certificate projection SKI");
|
||||
DiscoveredChildEntryProjection {
|
||||
child_ski: hex::encode(child_ski),
|
||||
}
|
||||
}
|
||||
|
||||
struct RipeRootChildEntryProfile {
|
||||
count: usize,
|
||||
load_der_nanos: u128,
|
||||
decode_cert_nanos: u128,
|
||||
build_entry_nanos: u128,
|
||||
}
|
||||
|
||||
fn profile_ripe_root_child_entry_build(
|
||||
store: &RocksStore,
|
||||
discovered_children: &[DiscoveredChildCaInstance],
|
||||
validation_time: time::OffsetDateTime,
|
||||
) -> Result<RipeRootChildEntryProfile, String> {
|
||||
let mut out = Vec::with_capacity(discovered_children.len());
|
||||
let mut load_der_nanos = 0;
|
||||
let mut decode_cert_nanos = 0;
|
||||
let mut build_entry_nanos = 0;
|
||||
for child in discovered_children {
|
||||
let load_started = std::time::Instant::now();
|
||||
let child_der = child.handle.ca_certificate_der(store)?;
|
||||
load_der_nanos += load_started.elapsed().as_nanos();
|
||||
|
||||
let decode_started = std::time::Instant::now();
|
||||
let child_cert = ResourceCertificate::decode_der(child_der.as_ref())
|
||||
.map_err(|e| format!("decode child certificate for VCIR failed: {e}"))?;
|
||||
decode_cert_nanos += decode_started.elapsed().as_nanos();
|
||||
|
||||
let build_started = std::time::Instant::now();
|
||||
let child_ski = child_cert
|
||||
.tbs
|
||||
.extensions
|
||||
.subject_key_identifier
|
||||
.as_ref()
|
||||
.ok_or_else(|| "child certificate missing SubjectKeyIdentifier".to_string())?;
|
||||
out.push(VcirChildEntry {
|
||||
child_manifest_rsync_uri: child.handle.manifest_rsync_uri.clone(),
|
||||
child_cert_rsync_uri: child.discovered_from.child_ca_certificate_rsync_uri.clone(),
|
||||
child_cert_hash: child
|
||||
.discovered_from
|
||||
.child_ca_certificate_sha256_hex
|
||||
.clone(),
|
||||
child_ski: hex::encode(child_ski),
|
||||
child_rsync_base_uri: child.handle.rsync_base_uri.clone(),
|
||||
child_publication_point_rsync_uri: child.handle.publication_point_rsync_uri.clone(),
|
||||
child_rrdp_notification_uri: child.handle.rrdp_notification_uri.clone(),
|
||||
child_effective_ip_resources: child.handle.effective_ip_resources.clone(),
|
||||
child_effective_as_resources: child.handle.effective_as_resources.clone(),
|
||||
accepted_at_validation_time: PackTime::from_utc_offset_datetime(validation_time),
|
||||
});
|
||||
build_entry_nanos += build_started.elapsed().as_nanos();
|
||||
}
|
||||
Ok(RipeRootChildEntryProfile {
|
||||
count: out.len(),
|
||||
load_der_nanos,
|
||||
decode_cert_nanos,
|
||||
build_entry_nanos,
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "manual performance repro: requires target/ripe-root-finalize-repro repo-bytes fixture"]
|
||||
fn ripe_root_finalize_repro_from_remote_fixture() {
|
||||
let fixture_root = std::env::var("RPKI_RIPE_ROOT_FINALIZE_FIXTURE")
|
||||
.map(std::path::PathBuf::from)
|
||||
.unwrap_or_else(|_| {
|
||||
std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("target/ripe-root-finalize-repro")
|
||||
});
|
||||
let run_id = std::env::var("RPKI_RIPE_ROOT_FINALIZE_RUN").unwrap_or_else(|_| "0262".into());
|
||||
assert!(
|
||||
fixture_root.exists(),
|
||||
"fixture root missing: {}; expected copied remote fixture",
|
||||
fixture_root.display()
|
||||
);
|
||||
|
||||
let fixture = load_ripe_root_finalize_fixture(&fixture_root, &run_id);
|
||||
let repo_bytes_db = fixture_root.join("db/repo-bytes.db");
|
||||
assert!(
|
||||
repo_bytes_db.exists(),
|
||||
"repo-bytes fixture missing: {}",
|
||||
repo_bytes_db.display()
|
||||
);
|
||||
|
||||
let store_dir = tempfile::tempdir().expect("store dir");
|
||||
let work_db = store_dir.path().join("work-db");
|
||||
let store = RocksStore::open_with_external_repo_bytes(&work_db, &repo_bytes_db)
|
||||
.expect("open work-db with external repo-bytes");
|
||||
let repo_bytes = Arc::new(
|
||||
store
|
||||
.external_repo_bytes_ref()
|
||||
.expect("external repo bytes")
|
||||
.clone(),
|
||||
);
|
||||
|
||||
let manifest_bytes = store
|
||||
.get_blob_bytes(&fixture.manifest_sha256_hex)
|
||||
.expect("load fixture manifest bytes")
|
||||
.expect("fixture manifest bytes exist");
|
||||
let manifest = ManifestObject::decode_der(&manifest_bytes).expect("decode fixture manifest");
|
||||
let mut files = Vec::with_capacity(fixture.objects.len().saturating_sub(1));
|
||||
let mut child_audits = Vec::new();
|
||||
let current_ca_hash = "007ad0c291b01ede4bd60e1204074ce3f7192186a022c9577cef5d8e91d5171a";
|
||||
let current_ca_uri = "rsync://rpki.ripe.net/repository/aca/KpSo3VVK5wEHIJnHC2QHVV3d5mk.cer";
|
||||
let parent_manifest_uri =
|
||||
"rsync://rpki.ripe.net/repository/aca/7DNNDzoYvgAht7joQih2Qayxcxo.mft";
|
||||
let ca = CaInstanceHandle {
|
||||
depth: 1,
|
||||
tal_id: "ripe-ncc".to_string(),
|
||||
parent_manifest_rsync_uri: Some(parent_manifest_uri.to_string()),
|
||||
ca_certificate: CaCertificateRef::repo_bytes(current_ca_hash.to_string()),
|
||||
ca_certificate_rsync_uri: Some(current_ca_uri.to_string()),
|
||||
effective_ip_resources: None,
|
||||
effective_as_resources: None,
|
||||
rsync_base_uri: fixture.publication_point_uri.clone(),
|
||||
manifest_rsync_uri: fixture.manifest_uri.clone(),
|
||||
publication_point_rsync_uri: fixture.publication_point_uri.clone(),
|
||||
rrdp_notification_uri: Some("https://rrdp.ripe.net/notification.xml".to_string()),
|
||||
};
|
||||
let mut discovered_children = Vec::new();
|
||||
let use_child_projection = std::env::var("RPKI_RIPE_ROOT_FINALIZE_USE_CHILD_PROJECTION")
|
||||
.map(|value| value != "0" && value.to_ascii_lowercase() != "false")
|
||||
.unwrap_or(false);
|
||||
for object in &fixture.objects {
|
||||
if object.uri == fixture.manifest_uri {
|
||||
continue;
|
||||
}
|
||||
files.push(pack_file_from_fixture_object(object, &repo_bytes));
|
||||
if object.object_type == "certificate" {
|
||||
child_audits.push(child_audit_from_fixture_object(object));
|
||||
if object.result == "ok" {
|
||||
let child_entry_projection = use_child_projection
|
||||
.then(|| child_entry_projection_from_fixture_object(&store, object));
|
||||
discovered_children.push(discovered_child_from_fixture_object(
|
||||
&ca,
|
||||
object,
|
||||
child_entry_projection,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
if std::env::var("RPKI_RIPE_ROOT_FINALIZE_PROFILE_CHILD").is_ok() {
|
||||
let profile_children = fixture
|
||||
.objects
|
||||
.iter()
|
||||
.filter(|object| object.object_type == "certificate" && object.result == "ok")
|
||||
.map(|object| discovered_child_from_fixture_object(&ca, object, None))
|
||||
.collect::<Vec<_>>();
|
||||
let profile_started = std::time::Instant::now();
|
||||
let profile =
|
||||
profile_ripe_root_child_entry_build(&store, &profile_children, fixture.validation_time)
|
||||
.expect("profile child entry build");
|
||||
eprintln!(
|
||||
"ripe root child-entry profile: run={} count={} total_ms={} load_der_ms={:.3} decode_cert_ms={:.3} build_entry_ms={:.3}",
|
||||
run_id,
|
||||
profile.count,
|
||||
profile_started.elapsed().as_millis(),
|
||||
profile.load_der_nanos as f64 / 1_000_000.0,
|
||||
profile.decode_cert_nanos as f64 / 1_000_000.0,
|
||||
profile.build_entry_nanos as f64 / 1_000_000.0,
|
||||
);
|
||||
if std::env::var("RPKI_RIPE_ROOT_FINALIZE_ONLY_CHILD_PROFILE").is_ok() {
|
||||
assert!(profile.count > 22_000);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let fresh_point = FreshValidatedPublicationPoint {
|
||||
manifest_rsync_uri: fixture.manifest_uri.clone(),
|
||||
publication_point_rsync_uri: fixture.publication_point_uri.clone(),
|
||||
manifest_number_be: manifest.manifest.manifest_number.bytes_be.clone(),
|
||||
this_update: PackTime::from_utc_offset_datetime(manifest.manifest.this_update),
|
||||
next_update: PackTime::from_utc_offset_datetime(manifest.manifest.next_update),
|
||||
verified_at: PackTime::from_utc_offset_datetime(fixture.validation_time),
|
||||
manifest_bytes,
|
||||
files,
|
||||
};
|
||||
let policy = Policy::default();
|
||||
let enable_ccr_accumulator = std::env::var("RPKI_RIPE_ROOT_FINALIZE_CCR")
|
||||
.map(|value| value != "0" && value.to_ascii_lowercase() != "false")
|
||||
.unwrap_or(true);
|
||||
let runner = Rpkiv1PublicationPointRunner {
|
||||
store: &store,
|
||||
policy: &policy,
|
||||
http_fetcher: &NeverHttpFetcher,
|
||||
rsync_fetcher: &FailingRsyncFetcher,
|
||||
validation_time: fixture.validation_time,
|
||||
timing: None,
|
||||
download_log: None,
|
||||
replay_archive_index: None,
|
||||
replay_delta_index: None,
|
||||
rrdp_dedup: false,
|
||||
rrdp_repo_cache: Mutex::new(HashMap::new()),
|
||||
rsync_dedup: false,
|
||||
rsync_repo_cache: Mutex::new(HashMap::new()),
|
||||
current_repo_index: None,
|
||||
repo_sync_runtime: None,
|
||||
parallel_phase2_config: None,
|
||||
parallel_roa_worker_pool: None,
|
||||
ccr_accumulator: enable_ccr_accumulator
|
||||
.then(|| Mutex::new(CcrAccumulator::new(Vec::new()))),
|
||||
persist_vcir: true,
|
||||
enable_roa_validation_cache: false,
|
||||
enable_child_certificate_validation_cache: true,
|
||||
publication_point_cache_observe_only: false,
|
||||
enable_publication_point_validation_cache: true,
|
||||
};
|
||||
|
||||
eprintln!(
|
||||
"ripe root finalize repro setup: run={} ccr_accumulator={} child_projection={} objects={} files={} child_audits={} discovered_children={}",
|
||||
run_id,
|
||||
enable_ccr_accumulator,
|
||||
use_child_projection,
|
||||
fixture.objects.len(),
|
||||
fresh_point.files.len(),
|
||||
child_audits.len(),
|
||||
discovered_children.len()
|
||||
);
|
||||
let started = std::time::Instant::now();
|
||||
let output = runner
|
||||
.finalize_fresh_publication_point_from_reducer(
|
||||
&ca,
|
||||
&fresh_point,
|
||||
Vec::new(),
|
||||
empty_objects_output(),
|
||||
child_audits,
|
||||
discovered_children,
|
||||
Some("rrdp"),
|
||||
Some("rrdp_ok"),
|
||||
0,
|
||||
None,
|
||||
)
|
||||
.expect("finalize fixture publication point");
|
||||
let finalize_ms = started.elapsed().as_millis();
|
||||
eprintln!(
|
||||
"ripe root finalize repro timing: run={} finalize_ms={} snapshot_pack_ms={} persist_vcir_ms={} build_vcir_ms={} child_entries_ms={} related_artifacts_ms={} replace_vcir_ms={} replace_vcir_encode_ms={} replace_vcir_write_batch_ms={} ccr_projection_build_ms={} audit_build_ms={}",
|
||||
run_id,
|
||||
finalize_ms,
|
||||
output.snapshot_pack_ms,
|
||||
output.persist_vcir_ms,
|
||||
output.persist_vcir_timing.build_vcir_ms,
|
||||
output.persist_vcir_timing.build_vcir.child_entries_ms,
|
||||
output.persist_vcir_timing.build_vcir.related_artifacts_ms,
|
||||
output.persist_vcir_timing.replace_vcir_ms,
|
||||
output.persist_vcir_timing.replace_vcir.vcir_encode_ms,
|
||||
output.persist_vcir_timing.replace_vcir.write_batch_ms,
|
||||
output.ccr_projection_build_ms,
|
||||
output.audit_build_ms,
|
||||
);
|
||||
eprintln!(
|
||||
"ripe root finalize repro result: audit_objects={} discovered_children={} ccr_manifest_count={}",
|
||||
output.result.audit.objects.len(),
|
||||
output.result.discovered_children.len(),
|
||||
runner
|
||||
.ccr_accumulator_snapshot()
|
||||
.map(|snapshot| snapshot.manifest_count())
|
||||
.unwrap_or(0),
|
||||
);
|
||||
|
||||
assert!(fresh_point.files.len() > 22_000);
|
||||
assert!(output.result.discovered_children.len() > 22_000);
|
||||
if enable_ccr_accumulator {
|
||||
assert_eq!(
|
||||
runner
|
||||
.ccr_accumulator_snapshot()
|
||||
.expect("ccr snapshot")
|
||||
.manifest_count(),
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user