#[test]
fn test_empty_log_with_nonempty_checkpoint_rejects() {
let dir = tempfile::tempdir().unwrap();
let rules = test_rules();
let mut writer = LogWriter::open(dir.path(), &rules).unwrap();
let mut state = State::default();
writer
.commit(request_proposal(), &rules, &mut state)
.unwrap();
let records = writer.records().to_vec();
let trusted = TrustedCheckpoint::from_verified_log(&records, &rules).unwrap();
let verdict = verify_log(&[], &rules, Some(&trusted));
assert_eq!(verdict.result, VerdictResult::Reject);
assert_eq!(verdict.reason, Some(ReasonCode::InvalidCheckpoint));
let verdict = verify_log(&records[..1], &rules, Some(&trusted));
assert_eq!(verdict.result, VerdictResult::Reject);
assert_eq!(verdict.reason, Some(ReasonCode::InvalidCheckpoint));
assert_eq!(
verify_log(&records, &rules, Some(&trusted)).result,
VerdictResult::Accept
);
assert_eq!(verify_log(&[], &rules, None).result, VerdictResult::Accept);
}
#[test]
fn test_empty_prefix_checkpoint_does_not_exempt_genesis_time() {
let dir = tempfile::tempdir().unwrap();
let rules = test_rules();
let mut writer = LogWriter::open(dir.path(), &rules).unwrap();
let mut state = State::default();
writer
.commit(request_proposal(), &rules, &mut state)
.unwrap();
let records = writer.records().to_vec();
let subject = Record {
time: 100,
..records[0].clone()
}
.with_computed_id()
.unwrap();
let verdict_rec = Record {
time: 101,
refs: vec![Ref {
type_: RefType::Cause,
target: subject.id,
}],
..records[1].clone()
}
.with_computed_id()
.unwrap();
let shifted = vec![subject, verdict_rec];
let empty_cp = TrustedCheckpoint::from_verified_log(&[], &rules).unwrap();
assert_eq!(
verify_log(&shifted, &rules, None).result,
VerdictResult::Reject
);
let verdict = verify_log(&shifted, &rules, Some(&empty_cp));
assert_eq!(verdict.result, VerdictResult::Reject);
assert_eq!(verdict.reason, Some(ReasonCode::InvalidPayload));
assert_eq!(
verify_log(&records, &rules, Some(&empty_cp)).result,
VerdictResult::Accept
);
}
#[test]
fn test_verify_log_scales_linearly() {
let rules = test_rules();
let n_pairs = 5_000usize;
let mut records = Vec::with_capacity(n_pairs * 2);
let verdict_data = encode(&VerdictData {
result: VerdictResult::Accept,
reason: None,
})
.unwrap();
for k in 0..n_pairs {
let data = encode(&RequestData {
objective: format!("request {k}"),
scope: SCOPE,
attachments: vec![],
parent_request_id: None,
})
.unwrap();
let subject = Record {
id: [0u8; 32],
space: SPACE,
thread: THREAD,
time: (k as u64) * 2 + 1,
author: human_author(),
kind: Kind::Request,
schema: schema_id(SCHEMA_REQUEST),
data,
refs: vec![],
evidence: Evidence::Reported,
}
.with_computed_id()
.unwrap();
let verdict = Record {
id: [0u8; 32],
space: SPACE,
thread: THREAD,
time: (k as u64) * 2 + 2,
author: Author {
id: "verifier".into(),
type_: AuthorType::Verifier,
signature: None,
},
kind: Kind::Verdict,
schema: schema_id(SCHEMA_VERDICT),
data: verdict_data.clone(),
refs: vec![Ref {
type_: RefType::Cause,
target: subject.id,
}],
evidence: Evidence::Deterministic,
}
.with_computed_id()
.unwrap();
records.push(subject);
records.push(verdict);
}
let report = verify_log(&records, &rules, None);
assert_eq!(report.result, VerdictResult::Accept);
assert_eq!(report.checked_records, (n_pairs * 2) as u64);
}