Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
403 changes: 403 additions & 0 deletions EVENTS.md

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ proof once and caches the result; every protocol afterwards reads
## Architecture & Overview

For a detailed architectural description with diagrams, see the [Architecture Documentation](docs/ARCHITECTURE.md).
For the authoritative specification of contract events, topic schemas, and indexer integration, see [EVENTS.md](EVENTS.md).

---

Expand Down Expand Up @@ -105,6 +106,7 @@ services/
scripts/deploy.sh deploy + wire + register issuer + install all VKs on testnet
scripts/benchmark.sh measure instruction budget for every public function on testnet
BENCHMARKS.md per-function instruction counts, ledger I/O, and fee estimates
EVENTS.md authoritative contract event topic & payload schemas
```

All five credential circuits share one commitment scheme,
Expand Down
4 changes: 2 additions & 2 deletions contracts/credential_verifier/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use ultrahonk_soroban_verifier::{UltraHonkVerifier, PROOF_BYTES};
/// Payload emitted when a verification key is registered or replaced.
/// Topics: ("cred_ver", "vk_set", credential_type)
#[contracttype]
#[derive(Clone)]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct EventVkSet {
/// The admin address that performed the update.
pub admin: Address,
Expand All @@ -41,7 +41,7 @@ pub struct EventVkSet {
/// Payload emitted when an obsolete verification key is removed.
/// Topics: ("cred_ver", "vk_pruned", credential_type)
#[contracttype]
#[derive(Clone)]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct EventVkPruned {
pub admin: Address,
pub version: u32,
Expand Down
79 changes: 79 additions & 0 deletions contracts/credential_verifier/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,85 @@ fn deprecation_timestamp_is_contract_time() {
assert_eq!(env.as_contract(&c.address, || env.storage().persistent().get::<_, u64>(&DataKey::DeprecatedAt(symbol_short!("kyc"), 1)).unwrap()), 123_456);
}

// ── Event schema & drift tests (Issue #429) ──────────────────────────────────

#[test]
fn prune_version_emits_expected_event() {
let env = Env::default();
env.mock_all_auths();
let admin = Address::generate(&env);
let id = env.register(CredentialVerifier, (admin.clone(),));
let c = CredentialVerifierClient::new(&env, &id);

c.set_vk(&symbol_short!("kyc"), &1, &Bytes::from_slice(&env, fixture!("kyc", "vk")));
// Drains the set_vk event
let _ = env.events().all();

c.deprecate_version(&symbol_short!("kyc"), &1);

let deprecated_at = env.as_contract(&c.address, || {
env.storage().persistent().get::<_, u64>(&DataKey::DeprecatedAt(symbol_short!("kyc"), 1)).unwrap()
});
env.ledger().with_mut(|li| li.timestamp = deprecated_at + MAX_PROOF_VALIDITY_SECONDS);

c.prune_version(&symbol_short!("kyc"), &1);

let all_events = env.events().all().filter_by_contract(&c.address);
assert_eq!(
all_events,
vec![
&env,
(
c.address.clone(),
(
symbol_short!("cred_ver"),
symbol_short!("vk_pruned"),
symbol_short!("kyc"),
)
.into_val(&env),
EventVkPruned {
admin: admin.clone(),
version: 1,
}
.into_val(&env),
),
],
);
}

#[test]
fn deprecate_version_emits_no_events() {
let env = Env::default();
env.mock_all_auths();
let admin = Address::generate(&env);
let id = env.register(CredentialVerifier, (admin.clone(),));
let c = CredentialVerifierClient::new(&env, &id);

c.set_vk(&symbol_short!("kyc"), &1, &Bytes::from_slice(&env, fixture!("kyc", "vk")));
let expected = vec![
&env,
(
c.address.clone(),
(
symbol_short!("cred_ver"),
symbol_short!("vk_set"),
symbol_short!("kyc"),
)
.into_val(&env),
EventVkSet {
admin,
}
.into_val(&env),
),
];
// Drains the set_vk event
assert_eq!(env.events().all().filter_by_contract(&c.address), expected);

c.deprecate_version(&symbol_short!("kyc"), &1);
// Deprecation modifies storage status and emits no new events
assert_eq!(env.events().all().filter_by_contract(&c.address), vec![&env]);
}

// ── RBAC tests (Issue #123) ─────────────────────────────────────────────────

#[test]
Expand Down
Loading