rpki/scripts/replay_verify/run_multi_rir_ccr_replay_verify.sh

285 lines
8.8 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
cd "$ROOT_DIR"
usage() {
cat <<'USAGE'
Usage:
run_multi_rir_ccr_replay_verify.sh --rir <rir[,rir...]> [--mode snapshot|delta|both] [--keep-db]
Options:
--rir <list> Comma-separated RIR list, e.g. apnic or apnic,ripe
--mode <mode> snapshot | delta | both (default: both)
--keep-db Keep per-run RocksDB directories (default: remove after verify)
--bundle-root <p> Override bundle root
--out-root <p> Override output root (default: rpki/target/replay)
--run-tag <tag> Override timestamp suffix for all RIR runs
USAGE
}
MODE="both"
KEEP_DB=0
RIR_LIST=""
BUNDLE_ROOT="${BUNDLE_ROOT:-/home/yuyr/dev/rust_playground/routinator/bench/multi_rir_demo/runs/20260316-112341-multi-final3}"
OUT_ROOT="${OUT_ROOT:-$ROOT_DIR/target/replay}"
RUN_TAG="${RUN_TAG:-$(date -u +%Y%m%dT%H%M%SZ)}"
while [[ $# -gt 0 ]]; do
case "$1" in
--rir)
shift
RIR_LIST="${1:-}"
;;
--mode)
shift
MODE="${1:-}"
;;
--keep-db)
KEEP_DB=1
;;
--bundle-root)
shift
BUNDLE_ROOT="${1:-}"
;;
--out-root)
shift
OUT_ROOT="${1:-}"
;;
--run-tag)
shift
RUN_TAG="${1:-}"
;;
-h|--help)
usage
exit 0
;;
*)
echo "unknown argument: $1" >&2
usage >&2
exit 2
;;
esac
shift || true
done
if [[ -z "$RIR_LIST" ]]; then
echo "--rir is required" >&2
usage >&2
exit 2
fi
case "$MODE" in
snapshot|delta|both) ;;
*)
echo "invalid --mode: $MODE" >&2
usage >&2
exit 2
;;
esac
CASE_INFO_SCRIPT="$ROOT_DIR/scripts/payload_replay/multi_rir_case_info.py"
mkdir -p "$OUT_ROOT"
RUN_ROOT="$OUT_ROOT/$RUN_TAG"
mkdir -p "$RUN_ROOT"
cargo build --release --bin rpki --bin ccr_to_routinator_csv --bin ccr_verify >/dev/null
summary_md="$RUN_ROOT/multi_rir_ccr_replay_verify_${RUN_TAG}_summary.md"
summary_json="$RUN_ROOT/multi_rir_ccr_replay_verify_${RUN_TAG}_summary.json"
python3 - <<'PY' >/dev/null
PY
summary_json_tmp="$(mktemp)"
printf '[]' > "$summary_json_tmp"
run_one_mode() {
local rir="$1"
local mode="$2"
local run_dir="$3"
local trust_anchor="$4"
local tal_path="$5"
local ta_path="$6"
local base_archive="$7"
local base_locks="$8"
local base_csv="$9"
local delta_archive="${10}"
local delta_locks="${11}"
local delta_csv="${12}"
local snapshot_validation_time="${13}"
local delta_validation_time="${14}"
local db_dir="$run_dir/${rir}_${mode}_db"
local report_json="$run_dir/${rir}_${mode}_report.json"
local run_log="$run_dir/${rir}_${mode}_run.log"
local ccr_path="$run_dir/${rir}_${mode}.ccr"
local csv_path="$run_dir/${rir}_${mode}_ccr_vrps.csv"
local compare_md="$run_dir/${rir}_${mode}_ccr_compare_summary.md"
local only_ours="$run_dir/${rir}_${mode}_ccr_only_in_ours.csv"
local only_record="$run_dir/${rir}_${mode}_ccr_only_in_record.csv"
local verify_json="$run_dir/${rir}_${mode}_ccr_verify.json"
local meta_json="$run_dir/${rir}_${mode}_meta.json"
rm -rf "$db_dir"
local -a cmd=(target/release/rpki --db "$db_dir" --tal-path "$tal_path" --ta-path "$ta_path")
if [[ "$mode" == "snapshot" ]]; then
cmd+=(--payload-replay-archive "$base_archive" --payload-replay-locks "$base_locks" --validation-time "$snapshot_validation_time")
else
cmd+=(
--payload-base-archive "$base_archive"
--payload-base-locks "$base_locks"
--payload-base-validation-time "$snapshot_validation_time"
--payload-delta-archive "$delta_archive"
--payload-delta-locks "$delta_locks"
--validation-time "$delta_validation_time"
)
fi
cmd+=(--report-json "$report_json" --ccr-out "$ccr_path")
local start_s end_s duration_s
start_s="$(date +%s)"
(
echo "# ${rir} ${mode} command:"
printf '%q ' "${cmd[@]}"
echo
echo
"${cmd[@]}"
) 2>&1 | tee "$run_log" >/dev/null
end_s="$(date +%s)"
duration_s="$((end_s - start_s))"
target/release/ccr_to_routinator_csv \
--ccr "$ccr_path" \
--out "$csv_path" \
--trust-anchor "$trust_anchor" >/dev/null
local record_csv
if [[ "$mode" == "snapshot" ]]; then
record_csv="$base_csv"
else
record_csv="$delta_csv"
fi
./scripts/payload_replay/compare_with_routinator_record.sh \
"$csv_path" \
"$record_csv" \
"$compare_md" \
"$only_ours" \
"$only_record" >/dev/null
target/release/ccr_verify \
--ccr "$ccr_path" \
--db "$db_dir" > "$verify_json"
python3 - "$report_json" "$meta_json" "$mode" "$duration_s" <<'PY'
import json, sys
from pathlib import Path
report = json.loads(Path(sys.argv[1]).read_text(encoding='utf-8'))
meta = {
'mode': sys.argv[3],
'duration_seconds': int(sys.argv[4]),
'validation_time': report.get('validation_time_rfc3339_utc'),
'publication_points_processed': report['tree']['instances_processed'],
'publication_points_failed': report['tree']['instances_failed'],
'vrps': len(report['vrps']),
'aspas': len(report['aspas']),
}
Path(sys.argv[2]).write_text(json.dumps(meta, ensure_ascii=False, indent=2)+'\n', encoding='utf-8')
PY
if [[ "$KEEP_DB" -eq 0 ]]; then
rm -rf "$db_dir"
fi
}
IFS=',' read -r -a RIRS <<< "$RIR_LIST"
for rir in "${RIRS[@]}"; do
rir="$(echo "$rir" | xargs)"
[[ -n "$rir" ]] || continue
eval "$(python3 "$CASE_INFO_SCRIPT" --bundle-root "$BUNDLE_ROOT" --rir "$rir" --format env)"
run_dir="$RUN_ROOT/${rir}_ccr_replay_${RUN_TAG}"
mkdir -p "$run_dir"
if [[ "$MODE" == "snapshot" || "$MODE" == "both" ]]; then
run_one_mode \
"$rir" snapshot "$run_dir" "$TRUST_ANCHOR" "$TAL_PATH" "$TA_PATH" \
"$PAYLOAD_REPLAY_ARCHIVE" "$PAYLOAD_REPLAY_LOCKS" "$ROUTINATOR_BASE_RECORD_CSV" \
"$PAYLOAD_DELTA_ARCHIVE" "$PAYLOAD_DELTA_LOCKS" "$ROUTINATOR_DELTA_RECORD_CSV" \
"$SNAPSHOT_VALIDATION_TIME" "$DELTA_VALIDATION_TIME"
fi
if [[ "$MODE" == "delta" || "$MODE" == "both" ]]; then
run_one_mode \
"$rir" delta "$run_dir" "$TRUST_ANCHOR" "$TAL_PATH" "$TA_PATH" \
"$PAYLOAD_REPLAY_ARCHIVE" "$PAYLOAD_REPLAY_LOCKS" "$ROUTINATOR_BASE_RECORD_CSV" \
"$PAYLOAD_DELTA_ARCHIVE" "$PAYLOAD_DELTA_LOCKS" "$ROUTINATOR_DELTA_RECORD_CSV" \
"$SNAPSHOT_VALIDATION_TIME" "$DELTA_VALIDATION_TIME"
fi
python3 - "$summary_json_tmp" "$run_dir" "$rir" "$MODE" <<'PY'
import json, sys
from pathlib import Path
summary_path = Path(sys.argv[1])
run_dir = Path(sys.argv[2])
rir = sys.argv[3]
mode = sys.argv[4]
rows = json.loads(summary_path.read_text(encoding='utf-8'))
for submode in ['snapshot','delta']:
if mode not in ('both', submode):
continue
compare = run_dir / f'{rir}_{submode}_ccr_compare_summary.md'
meta = run_dir / f'{rir}_{submode}_meta.json'
verify = run_dir / f'{rir}_{submode}_ccr_verify.json'
if not compare.exists() or not meta.exists() or not verify.exists():
continue
compare_text = compare.read_text(encoding='utf-8')
meta_obj = json.loads(meta.read_text(encoding='utf-8'))
verify_obj = json.loads(verify.read_text(encoding='utf-8'))
def metric(name):
prefix = f'| {name} | '
for line in compare_text.splitlines():
if line.startswith(prefix):
return int(line.split('|')[2].strip())
raise SystemExit(f'missing metric {name} in {compare}')
rows.append({
'rir': rir,
'mode': submode,
'run_dir': str(run_dir),
'duration_seconds': meta_obj['duration_seconds'],
'vrps': meta_obj['vrps'],
'aspas': meta_obj['aspas'],
'only_in_ours': metric('only_in_ours'),
'only_in_record': metric('only_in_record'),
'intersection': metric('intersection'),
'state_hashes_ok': verify_obj.get('state_hashes_ok'),
})
summary_path.write_text(json.dumps(rows, ensure_ascii=False, indent=2)+'\n', encoding='utf-8')
PY
done
python3 - "$summary_json_tmp" "$summary_json" "$summary_md" "$RUN_TAG" <<'PY'
import json, sys
from pathlib import Path
rows = json.loads(Path(sys.argv[1]).read_text(encoding='utf-8'))
out_json = Path(sys.argv[2])
out_md = Path(sys.argv[3])
run_tag = sys.argv[4]
out_json.write_text(json.dumps(rows, ensure_ascii=False, indent=2)+'\n', encoding='utf-8')
parts = []
parts.append('# Multi-RIR CCR Replay Verify Summary\n\n')
parts.append(f'- run_tag: `{run_tag}`\n\n')
parts.append('| rir | mode | duration_s | vrps | aspas | only_in_ours | only_in_record | state_hashes_ok |\n')
parts.append('|---|---|---:|---:|---:|---:|---:|---|\n')
for row in rows:
parts.append(f"| {row['rir']} | {row['mode']} | {row['duration_seconds']} | {row['vrps']} | {row['aspas']} | {row['only_in_ours']} | {row['only_in_record']} | {row['state_hashes_ok']} |\n")
out_md.write_text(''.join(parts), encoding='utf-8')
PY
rm -f "$summary_json_tmp"
echo "== multi-rir replay verify complete ==" >&2
echo "- summary: $summary_md" >&2
echo "- summary json: $summary_json" >&2