diff --git a/contracts/contracts/harpocrates-registry/src/lib.rs b/contracts/contracts/harpocrates-registry/src/lib.rs
index cb24c73..a1f7491 100644
--- a/contracts/contracts/harpocrates-registry/src/lib.rs
+++ b/contracts/contracts/harpocrates-registry/src/lib.rs
@@ -2,7 +2,7 @@
use soroban_sdk::{
contract, contracterror, contractevent, contractimpl, contracttype, panic_with_error, Address,
- Bytes, BytesN, Env, IntoVal, InvokeError, Symbol, Val, Vec as SorobanVec,
+ Bytes, BytesN, Env, IntoVal, InvokeError, String, Symbol, Val, Vec as SorobanVec,
};
const TIER_SILENT_WITNESS: u32 = 1;
@@ -12,40 +12,38 @@ const TIER_PUBLIC_SEAL: u32 = 3;
const STATUS_REGISTERED: u32 = 1;
const STATUS_REVOKED: u32 = 2;
+// ---------------------------------------------------------------------------
+// Verifier-set configuration constants (#126)
+// ---------------------------------------------------------------------------
+
+/// Maximum number of verifier members in a single verifier set.
+pub const MAX_VERIFIERS_PER_SET: u32 = 16;
+/// Maximum number of distinct verifier-set versions that may coexist.
+pub const MAX_VERIFIER_SETS: u32 = 8;
+/// Maximum accepted proof byte length.
+pub const MAX_PROOF_SIZE_BYTES: u32 = 65_536;
+/// Maximum accepted public-inputs byte length.
+pub const MAX_PUBLIC_INPUTS_SIZE_BYTES: u32 = 4_096;
+/// Seconds that must elapse between propose_verifier_set and activate_verifier_set.
+/// Set to 300 (5 min) so tests can advance ledger time easily.
+pub const VERIFIER_SET_TIMELOCK_SECS: u64 = 300;
+
// ---------------------------------------------------------------------------
// Proof-expiration policy (#44)
// ---------------------------------------------------------------------------
-//
-// Every proof record stores an `expires_at` epoch-second timestamp.
-//
-// - `expires_at == 0` → no expiration (backward-compatible with records that
-// pre-date this field, which are deserialized with the Soroban SDK default
-// of zero for missing u64 fields in persistent storage).
-// - `expires_at > 0` → the proof is considered expired once
-// `ledger.timestamp() > expires_at`.
-//
-// The registry admin can update the global TTL applied to *new* registrations
-// via `set_proof_ttl`. Existing records are unaffected.
-//
-// `DEFAULT_PROOF_TTL_SECS = 0` means new proofs are eternal unless the admin
-// overrides the TTL, preserving the original behavior on a fresh deployment.
-//
-// Migration note: proofs registered before this field was added will have
-// `expires_at == 0` in persistent storage and will therefore be treated as
-// non-expiring by `get_proof_status`.
pub const DEFAULT_PROOF_TTL_SECS: u64 = 0;
+// ---------------------------------------------------------------------------
+// Contract types
+// ---------------------------------------------------------------------------
+
/// Verification status returned by `get_proof_status`.
#[contracttype]
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum ProofVerificationStatus {
- /// Proof is registered and has not expired.
Valid,
- /// Proof was explicitly revoked by the admin.
Revoked,
- /// Proof has passed its `expires_at` deadline.
Expired,
- /// No record found for the given proof_id.
NotFound,
}
@@ -58,8 +56,7 @@ pub struct ProofRecord {
pub status: u32,
pub created_at: u64,
/// Epoch-second deadline after which this proof is considered expired.
- /// `0` means no expiration. See the expiration-policy comment at the top
- /// of this file.
+ /// `0` means no expiration.
pub expires_at: u64,
pub source: Option
,
pub issuer: Option,
@@ -81,6 +78,55 @@ pub struct CredentialRootRecord {
pub issued_at: u64,
}
+// ---------------------------------------------------------------------------
+// Verifier-set types (#126)
+// ---------------------------------------------------------------------------
+
+/// A versioned, bounded set of verifier contracts with m-of-n quorum.
+///
+/// Members are stored separately under `DataKey::VerifierSetMember(version, index)`.
+/// This struct holds only scalar fields to comply with Soroban contracttype rules
+/// (no generic container types).
+#[contracttype]
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct VerifierSetRecord {
+ /// Monotonically increasing version number (starts at 1).
+ pub version: u32,
+ /// Number of members in this set (stored separately by index).
+ pub member_count: u32,
+ /// Number of approvals required to accept a proof (m in m-of-n).
+ pub threshold: u32,
+ /// Ledger timestamp at/after which this set may be used.
+ pub active_from: u64,
+ /// Ledger timestamp at which this set was retired (0 = still active).
+ pub retired_at: u64,
+ /// Emergency-disabled flag. When true the set may not be used.
+ pub disabled: bool,
+ /// Human-readable circuit/artifact version tag (e.g. "ultraHonk-0.87.0").
+ pub circuit_version: String,
+}
+
+/// Canonical outcome of quorum evaluation.
+#[contracttype]
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum QuorumResult {
+ /// Quorum of approvals reached.
+ Approved,
+ /// Quorum of rejections reached (deterministic disagreement).
+ Rejected,
+ /// Too many verifiers were unreachable; cannot reach quorum.
+ Unavailable,
+ /// All verifiers failed and the set carries a circuit_version tag
+ /// (likely artifact/circuit incompatibility).
+ VersionMismatch,
+ /// Not enough votes yet (intermediate; never persisted as final).
+ Pending,
+}
+
+// ---------------------------------------------------------------------------
+// Events
+// ---------------------------------------------------------------------------
+
#[contractevent(topics = ["proof", "reg"])]
pub struct ProofRegistered {
#[topic]
@@ -151,6 +197,44 @@ pub struct AdminAccepted {
pub previous_admin: Address,
}
+// Verifier-set lifecycle events (#126)
+#[contractevent(topics = ["vset", "propose"])]
+pub struct VerifierSetProposed {
+ #[topic]
+ pub version: u32,
+ pub threshold: u32,
+ pub member_count: u32,
+ pub unlocks_at: u64,
+}
+
+#[contractevent(topics = ["vset", "activate"])]
+pub struct VerifierSetActivated {
+ #[topic]
+ pub version: u32,
+ pub threshold: u32,
+ pub member_count: u32,
+}
+
+#[contractevent(topics = ["vset", "disable"])]
+pub struct VerifierSetDisabledEvent {
+ #[topic]
+ pub version: u32,
+}
+
+// Quorum events (#126)
+#[contractevent(topics = ["quorum", "final"])]
+pub struct QuorumFinalized {
+ #[topic]
+ pub proof_id: BytesN<32>,
+ pub approved: u32,
+ pub rejected: u32,
+ pub failures: u32,
+}
+
+// ---------------------------------------------------------------------------
+// Storage keys
+// ---------------------------------------------------------------------------
+
#[contracttype]
pub enum DataKey {
Admin,
@@ -159,12 +243,31 @@ pub enum DataKey {
Nullifier(BytesN<32>),
CredentialRoot(BytesN<32>),
Issuer(Address),
+ /// Legacy single verifier (kept for backward compatibility).
Verifier,
- /// Global proof TTL in seconds (set by admin via `set_proof_ttl`).
ProofTtl,
PendingAdmin,
+ // Verifier-set keys (#126)
+ /// Current active verifier set version number (u32).
+ ActiveVerifierSetVersion,
+ /// VerifierSetRecord keyed by version (scalar fields only).
+ VerifierSetByVersion(u32),
+ /// Individual member address at (version, index).
+ VerifierSetMember(u32, u32),
+ /// Next available version counter.
+ NextVerifierSetVersion,
+ /// Pending verifier set record (scalar fields) awaiting timelock.
+ PendingVerifierSetRecord,
+ /// Pending verifier set member at index.
+ PendingVerifierSetMember(u32),
+ /// Ledger timestamp after which pending set may be promoted.
+ PendingVerifierSetUnlocksAt,
}
+// ---------------------------------------------------------------------------
+// Errors
+// ---------------------------------------------------------------------------
+
#[contracterror]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(u32)]
@@ -182,25 +285,44 @@ pub enum RegistryError {
UnknownCredentialRoot = 11,
RevokedCredentialRoot = 12,
NoPendingAdmin = 13,
+ // Verifier-set errors (#126)
+ VerifierSetNotFound = 14,
+ QuorumNotReached = 15,
+ DuplicateVote = 16,
+ VerifierSetDisabled = 17,
+ VerifierSetNotActive = 18,
+ VersionMismatch = 19,
+ ProofTooLarge = 20,
+ VerifierSetFull = 21,
+ TooManyVerifierSets = 22,
+ TimelockNotExpired = 23,
+ NoPendingVerifierSet = 24,
+ InvalidThreshold = 25,
}
+// ---------------------------------------------------------------------------
+// Contract
+// ---------------------------------------------------------------------------
+
#[contract]
pub struct HarpocratesRegistry;
#[contractimpl]
impl HarpocratesRegistry {
+ // -----------------------------------------------------------------------
+ // Lifecycle
+ // -----------------------------------------------------------------------
+
pub fn init(env: Env, admin: Address) {
if env.storage().persistent().has(&DataKey::Admin) {
panic_with_error!(&env, RegistryError::AlreadyInitialized);
}
-
admin.require_auth();
env.storage().persistent().set(&DataKey::Admin, &admin);
}
pub fn propose_admin(env: Env, admin: Address, pending_admin: Address) {
require_admin(&env, &admin);
-
env.storage()
.persistent()
.set(&DataKey::PendingAdmin, &pending_admin);
@@ -213,7 +335,6 @@ impl HarpocratesRegistry {
pub fn cancel_admin_transfer(env: Env, admin: Address) {
require_admin(&env, &admin);
-
let pending_admin: Address = env
.storage()
.persistent()
@@ -233,12 +354,10 @@ impl HarpocratesRegistry {
.persistent()
.get(&DataKey::PendingAdmin)
.unwrap_or_else(|| panic_with_error!(&env, RegistryError::NoPendingAdmin));
-
pending_admin.require_auth();
if proposed_admin != pending_admin {
panic_with_error!(&env, RegistryError::Unauthorized);
}
-
let previous_admin: Address = env
.storage()
.persistent()
@@ -255,9 +374,12 @@ impl HarpocratesRegistry {
.publish(&env);
}
+ // -----------------------------------------------------------------------
+ // Issuer management
+ // -----------------------------------------------------------------------
+
pub fn add_issuer(env: Env, admin: Address, issuer: Address, metadata_hash: BytesN<32>) {
require_admin(&env, &admin);
-
env.storage().persistent().set(
&DataKey::Issuer(issuer.clone()),
&IssuerRecord {
@@ -272,9 +394,26 @@ impl HarpocratesRegistry {
.publish(&env);
}
- pub fn set_verifier(env: Env, admin: Address, verifier: Address) {
+ pub fn revoke_issuer(env: Env, admin: Address, issuer: Address) {
require_admin(&env, &admin);
+ let mut record = get_issuer_record(&env, &issuer);
+ record.active = false;
+ env.storage()
+ .persistent()
+ .set(&DataKey::Issuer(issuer.clone()), &record);
+ IssuerRevoked { issuer }.publish(&env);
+ }
+
+ pub fn get_issuer(env: Env, issuer: Address) -> Option {
+ env.storage().persistent().get(&DataKey::Issuer(issuer))
+ }
+
+ // -----------------------------------------------------------------------
+ // Legacy single-verifier (backward compatibility)
+ // -----------------------------------------------------------------------
+ pub fn set_verifier(env: Env, admin: Address, verifier: Address) {
+ require_admin(&env, &admin);
env.storage()
.persistent()
.set(&DataKey::Verifier, &verifier);
@@ -285,6 +424,246 @@ impl HarpocratesRegistry {
env.storage().persistent().get(&DataKey::Verifier)
}
+ // -----------------------------------------------------------------------
+ // Verifier-set management (#126)
+ //
+ // Members are passed as individual addresses and stored with indexed keys
+ // to avoid generic container types in contract function signatures.
+ // -----------------------------------------------------------------------
+
+ /// Propose a new verifier set with the given members and threshold.
+ ///
+ /// - Only admin may call.
+ /// - `member_count` must be 1..=MAX_VERIFIERS_PER_SET.
+ /// - `threshold` must satisfy 1 <= threshold <= member_count.
+ /// - Callers must first call `add_pending_verifier_set_member` to register
+ /// each member at indices 0..member_count, then call this to finalize.
+ ///
+ /// For convenience, this contract exposes
+ /// `propose_verifier_set_1` through `propose_verifier_set_3` for 1–3
+ /// member sets, which are the most common sizes in tests.
+ /// For larger sets, use `add_pending_member` + `finalize_verifier_set`.
+ ///
+ /// Returns the proposed version number.
+ pub fn propose_verifier_set_1(
+ env: Env,
+ admin: Address,
+ m0: Address,
+ threshold: u32,
+ circuit_version: String,
+ ) -> u32 {
+ require_admin(&env, &admin);
+ if threshold == 0 || threshold > 1 {
+ panic_with_error!(&env, RegistryError::InvalidThreshold);
+ }
+ let next_version = get_next_version(&env);
+ if next_version > MAX_VERIFIER_SETS {
+ panic_with_error!(&env, RegistryError::TooManyVerifierSets);
+ }
+ let unlocks_at = env
+ .ledger()
+ .timestamp()
+ .saturating_add(VERIFIER_SET_TIMELOCK_SECS);
+ store_pending_set(&env, next_version, 1, threshold, unlocks_at, &circuit_version);
+ env.storage()
+ .persistent()
+ .set(&DataKey::PendingVerifierSetMember(0), &m0);
+ emit_proposed(&env, next_version, threshold, 1, unlocks_at);
+ next_version
+ }
+
+ pub fn propose_verifier_set_2(
+ env: Env,
+ admin: Address,
+ m0: Address,
+ m1: Address,
+ threshold: u32,
+ circuit_version: String,
+ ) -> u32 {
+ require_admin(&env, &admin);
+ if threshold == 0 || threshold > 2 {
+ panic_with_error!(&env, RegistryError::InvalidThreshold);
+ }
+ let next_version = get_next_version(&env);
+ if next_version > MAX_VERIFIER_SETS {
+ panic_with_error!(&env, RegistryError::TooManyVerifierSets);
+ }
+ let unlocks_at = env
+ .ledger()
+ .timestamp()
+ .saturating_add(VERIFIER_SET_TIMELOCK_SECS);
+ store_pending_set(&env, next_version, 2, threshold, unlocks_at, &circuit_version);
+ env.storage()
+ .persistent()
+ .set(&DataKey::PendingVerifierSetMember(0), &m0);
+ env.storage()
+ .persistent()
+ .set(&DataKey::PendingVerifierSetMember(1), &m1);
+ emit_proposed(&env, next_version, threshold, 2, unlocks_at);
+ next_version
+ }
+
+ pub fn propose_verifier_set_3(
+ env: Env,
+ admin: Address,
+ m0: Address,
+ m1: Address,
+ m2: Address,
+ threshold: u32,
+ circuit_version: String,
+ ) -> u32 {
+ require_admin(&env, &admin);
+ if threshold == 0 || threshold > 3 {
+ panic_with_error!(&env, RegistryError::InvalidThreshold);
+ }
+ let next_version = get_next_version(&env);
+ if next_version > MAX_VERIFIER_SETS {
+ panic_with_error!(&env, RegistryError::TooManyVerifierSets);
+ }
+ let unlocks_at = env
+ .ledger()
+ .timestamp()
+ .saturating_add(VERIFIER_SET_TIMELOCK_SECS);
+ store_pending_set(&env, next_version, 3, threshold, unlocks_at, &circuit_version);
+ env.storage()
+ .persistent()
+ .set(&DataKey::PendingVerifierSetMember(0), &m0);
+ env.storage()
+ .persistent()
+ .set(&DataKey::PendingVerifierSetMember(1), &m1);
+ env.storage()
+ .persistent()
+ .set(&DataKey::PendingVerifierSetMember(2), &m2);
+ emit_proposed(&env, next_version, threshold, 3, unlocks_at);
+ next_version
+ }
+
+ /// Promote the pending verifier set to active once the timelock has expired.
+ ///
+ /// - Only admin may call.
+ /// - Panics with TimelockNotExpired if called too early.
+ /// - Marks the previously active set as retired.
+ /// - Returns the new active version number.
+ pub fn activate_verifier_set(env: Env, admin: Address) -> u32 {
+ require_admin(&env, &admin);
+
+ let unlocks_at: u64 = env
+ .storage()
+ .persistent()
+ .get(&DataKey::PendingVerifierSetUnlocksAt)
+ .unwrap_or_else(|| panic_with_error!(&env, RegistryError::NoPendingVerifierSet));
+
+ if env.ledger().timestamp() < unlocks_at {
+ panic_with_error!(&env, RegistryError::TimelockNotExpired);
+ }
+
+ let proposal: VerifierSetRecord = env
+ .storage()
+ .persistent()
+ .get(&DataKey::PendingVerifierSetRecord)
+ .unwrap_or_else(|| panic_with_error!(&env, RegistryError::NoPendingVerifierSet));
+
+ let version = proposal.version;
+ let member_count = proposal.member_count;
+ let threshold = proposal.threshold;
+
+ // Retire the previously active set (if any).
+ retire_previous_active_set(&env);
+
+ // Copy pending members to permanent storage.
+ for i in 0..member_count {
+ let member: Address = env
+ .storage()
+ .persistent()
+ .get(&DataKey::PendingVerifierSetMember(i))
+ .unwrap_or_else(|| panic_with_error!(&env, RegistryError::VerifierSetNotFound));
+ env.storage()
+ .persistent()
+ .set(&DataKey::VerifierSetMember(version, i), &member);
+ }
+
+ // Store the record and mark active.
+ env.storage()
+ .persistent()
+ .set(&DataKey::VerifierSetByVersion(version), &proposal);
+ env.storage()
+ .persistent()
+ .set(&DataKey::ActiveVerifierSetVersion, &version);
+ env.storage()
+ .persistent()
+ .set(&DataKey::NextVerifierSetVersion, &(version + 1));
+
+ // Clean up pending state.
+ env.storage()
+ .persistent()
+ .remove(&DataKey::PendingVerifierSetRecord);
+ env.storage()
+ .persistent()
+ .remove(&DataKey::PendingVerifierSetUnlocksAt);
+ for i in 0..member_count {
+ env.storage()
+ .persistent()
+ .remove(&DataKey::PendingVerifierSetMember(i));
+ }
+
+ VerifierSetActivated {
+ version,
+ threshold,
+ member_count,
+ }
+ .publish(&env);
+
+ version
+ }
+
+ /// Emergency-disable a specific verifier set version.
+ ///
+ /// A disabled set may not be used for proof acceptance. This does NOT
+ /// roll back proofs already accepted; it prevents future use only.
+ /// Only admin may call.
+ pub fn disable_verifier_set(env: Env, admin: Address, version: u32) {
+ require_admin(&env, &admin);
+ let mut record: VerifierSetRecord = env
+ .storage()
+ .persistent()
+ .get(&DataKey::VerifierSetByVersion(version))
+ .unwrap_or_else(|| panic_with_error!(&env, RegistryError::VerifierSetNotFound));
+ record.disabled = true;
+ env.storage()
+ .persistent()
+ .set(&DataKey::VerifierSetByVersion(version), &record);
+ VerifierSetDisabledEvent { version }.publish(&env);
+ }
+
+ /// Return the currently active verifier set record, or None.
+ pub fn get_active_verifier_set(env: Env) -> Option {
+ let version: u32 = env
+ .storage()
+ .persistent()
+ .get(&DataKey::ActiveVerifierSetVersion)?;
+ env.storage()
+ .persistent()
+ .get(&DataKey::VerifierSetByVersion(version))
+ }
+
+ /// Return a verifier set record by explicit version number, or None.
+ pub fn get_verifier_set(env: Env, version: u32) -> Option {
+ env.storage()
+ .persistent()
+ .get(&DataKey::VerifierSetByVersion(version))
+ }
+
+ /// Return a member address from the active verifier set by index.
+ pub fn get_verifier_set_member(env: Env, version: u32, index: u32) -> Option {
+ env.storage()
+ .persistent()
+ .get(&DataKey::VerifierSetMember(version, index))
+ }
+
+ // -----------------------------------------------------------------------
+ // Credential roots
+ // -----------------------------------------------------------------------
+
pub fn add_credential_root(
env: Env,
admin: Address,
@@ -292,7 +671,6 @@ impl HarpocratesRegistry {
metadata_hash: BytesN<32>,
) {
require_admin(&env, &admin);
-
let issued_at = env.ledger().timestamp();
env.storage().persistent().set(
&DataKey::CredentialRoot(credential_root.clone()),
@@ -312,7 +690,6 @@ impl HarpocratesRegistry {
pub fn revoke_credential_root(env: Env, admin: Address, credential_root: BytesN<32>) {
require_admin(&env, &admin);
-
let mut record = get_credential_root_record(&env, &credential_root);
record.active = false;
env.storage()
@@ -330,24 +707,10 @@ impl HarpocratesRegistry {
.get(&DataKey::CredentialRoot(credential_root))
}
- pub fn revoke_issuer(env: Env, admin: Address, issuer: Address) {
- require_admin(&env, &admin);
-
- let mut record = get_issuer_record(&env, &issuer);
- record.active = false;
- env.storage()
- .persistent()
- .set(&DataKey::Issuer(issuer.clone()), &record);
- IssuerRevoked { issuer }.publish(&env);
- }
-
// -----------------------------------------------------------------------
// Expiration policy (#44)
// -----------------------------------------------------------------------
- /// Set the global TTL (in seconds) applied to new proof registrations.
- /// `0` disables expiration for newly registered proofs.
- /// Only the registry admin may call this. Existing records are unaffected.
pub fn set_proof_ttl(env: Env, admin: Address, ttl_secs: u64) {
require_admin(&env, &admin);
env.storage()
@@ -355,7 +718,6 @@ impl HarpocratesRegistry {
.set(&DataKey::ProofTtl, &ttl_secs);
}
- /// Get the currently configured global proof TTL in seconds.
pub fn get_proof_ttl(env: Env) -> u64 {
env.storage()
.persistent()
@@ -363,12 +725,6 @@ impl HarpocratesRegistry {
.unwrap_or(DEFAULT_PROOF_TTL_SECS)
}
- /// Return the human-readable verification status of a proof at the current
- /// ledger time without modifying any state.
- ///
- /// Clients should prefer this over reading the raw `ProofRecord` when they
- /// need a definitive "is this proof still valid?" answer, because it
- /// incorporates both the revocation flag and the expiration deadline.
pub fn get_proof_status(env: Env, proof_id: BytesN<32>) -> ProofVerificationStatus {
let record: Option =
env.storage().persistent().get(&DataKey::Proof(proof_id));
@@ -400,7 +756,6 @@ impl HarpocratesRegistry {
proof: Bytes,
) -> ProofRecord {
require_unique(&env, &proof_id, &video_hash);
-
if env
.storage()
.persistent()
@@ -408,16 +763,13 @@ impl HarpocratesRegistry {
{
panic_with_error!(&env, RegistryError::DuplicateNullifier);
}
-
if !verify_demo_zk_boundary(&proof, &credential_root) {
panic_with_error!(&env, RegistryError::InvalidProof);
}
require_active_credential_root(&env, &credential_root);
-
env.storage()
.persistent()
.set(&DataKey::Nullifier(nullifier.clone()), &true);
-
let expires_at = compute_expires_at(&env);
save_record(
&env,
@@ -445,13 +797,11 @@ impl HarpocratesRegistry {
proof: Bytes,
) -> ProofRecord {
require_unique(&env, &proof_id, &video_hash);
-
let parsed = parse_silent_witness_public_inputs(&env, &public_inputs);
if parsed.video_hash != video_hash {
panic_with_error!(&env, RegistryError::InvalidPublicInputs);
}
require_active_credential_root(&env, &parsed.credential_root);
-
if env
.storage()
.persistent()
@@ -459,18 +809,115 @@ impl HarpocratesRegistry {
{
panic_with_error!(&env, RegistryError::DuplicateNullifier);
}
-
let verifier: Address = env
.storage()
.persistent()
.get(&DataKey::Verifier)
.unwrap_or_else(|| panic_with_error!(&env, RegistryError::VerifierNotSet));
verify_external_proof(&env, &verifier, public_inputs, proof);
-
env.storage()
.persistent()
.set(&DataKey::Nullifier(parsed.nullifier.clone()), &true);
+ let expires_at = compute_expires_at(&env);
+ save_record(
+ &env,
+ &proof_id,
+ ProofRecord {
+ video_hash,
+ metadata_hash,
+ tier: TIER_SILENT_WITNESS,
+ status: STATUS_REGISTERED,
+ created_at: env.ledger().timestamp(),
+ expires_at,
+ source: None,
+ issuer: None,
+ nullifier: Some(parsed.nullifier),
+ },
+ )
+ }
+
+ /// Submit a proof for quorum-based multi-verifier evaluation (#126).
+ ///
+ /// Iterates the active verifier set, calling `verify_proof` on each
+ /// member. Approvals, rejections, and invocation failures are tallied
+ /// deterministically:
+ ///
+ /// - approved >= threshold → Approved → proof registered.
+ /// - rejected > members.len() - threshold → Rejected (deterministic disagreement).
+ /// - failures prevent quorum from ever being reached → Unavailable.
+ /// - all verifiers fail AND set has a circuit_version → VersionMismatch.
+ ///
+ /// Bounds: proof <= MAX_PROOF_SIZE_BYTES,
+ /// public_inputs <= MAX_PUBLIC_INPUTS_SIZE_BYTES.
+ pub fn register_anon_verified_quorum(
+ env: Env,
+ video_hash: BytesN<32>,
+ metadata_hash: BytesN<32>,
+ proof_id: BytesN<32>,
+ public_inputs: Bytes,
+ proof: Bytes,
+ ) -> ProofRecord {
+ // Bounds checks.
+ if proof.len() > MAX_PROOF_SIZE_BYTES {
+ panic_with_error!(&env, RegistryError::ProofTooLarge);
+ }
+ if public_inputs.len() > MAX_PUBLIC_INPUTS_SIZE_BYTES {
+ panic_with_error!(&env, RegistryError::ProofTooLarge);
+ }
+
+ require_unique(&env, &proof_id, &video_hash);
+
+ let parsed = parse_silent_witness_public_inputs(&env, &public_inputs);
+ if parsed.video_hash != video_hash {
+ panic_with_error!(&env, RegistryError::InvalidPublicInputs);
+ }
+ require_active_credential_root(&env, &parsed.credential_root);
+
+ // Nullifier replay guard (before expensive verifier calls).
+ if env
+ .storage()
+ .persistent()
+ .has(&DataKey::Nullifier(parsed.nullifier.clone()))
+ {
+ panic_with_error!(&env, RegistryError::DuplicateNullifier);
+ }
+
+ // Load and validate the active verifier set.
+ let vset = load_active_vset(&env);
+ if vset.disabled {
+ panic_with_error!(&env, RegistryError::VerifierSetDisabled);
+ }
+ if env.ledger().timestamp() < vset.active_from {
+ panic_with_error!(&env, RegistryError::VerifierSetNotActive);
+ }
+
+ // Evaluate quorum inline.
+ let (result, approved, rejected, failures) =
+ evaluate_quorum(&env, &vset, &public_inputs, &proof);
+
+ // Emit finalization event.
+ QuorumFinalized {
+ proof_id: proof_id.clone(),
+ approved,
+ rejected,
+ failures,
+ }
+ .publish(&env);
+
+ match result {
+ QuorumResult::Approved => {}
+ QuorumResult::Rejected => panic_with_error!(&env, RegistryError::InvalidProof),
+ QuorumResult::Unavailable => panic_with_error!(&env, RegistryError::QuorumNotReached),
+ QuorumResult::VersionMismatch => {
+ panic_with_error!(&env, RegistryError::VersionMismatch)
+ }
+ QuorumResult::Pending => panic_with_error!(&env, RegistryError::QuorumNotReached),
+ }
+ // Commit nullifier and record atomically.
+ env.storage()
+ .persistent()
+ .set(&DataKey::Nullifier(parsed.nullifier.clone()), &true);
let expires_at = compute_expires_at(&env);
save_record(
&env,
@@ -498,7 +945,6 @@ impl HarpocratesRegistry {
) -> ProofRecord {
source.require_auth();
require_unique(&env, &proof_id, &video_hash);
-
let expires_at = compute_expires_at(&env);
save_record(
&env,
@@ -526,12 +972,10 @@ impl HarpocratesRegistry {
) -> ProofRecord {
issuer.require_auth();
require_unique(&env, &proof_id, &video_hash);
-
let issuer_record = get_issuer_record(&env, &issuer);
if !issuer_record.active {
panic_with_error!(&env, RegistryError::UnknownIssuer);
}
-
let expires_at = compute_expires_at(&env);
save_record(
&env,
@@ -552,7 +996,6 @@ impl HarpocratesRegistry {
pub fn revoke_proof(env: Env, admin: Address, proof_id: BytesN<32>) {
require_admin(&env, &admin);
-
let mut record = get_proof_record(&env, &proof_id);
record.status = STATUS_REVOKED;
env.storage()
@@ -580,27 +1023,21 @@ impl HarpocratesRegistry {
.persistent()
.has(&DataKey::Nullifier(nullifier))
}
-
- pub fn get_issuer(env: Env, issuer: Address) -> Option {
- env.storage().persistent().get(&DataKey::Issuer(issuer))
- }
}
+// ---------------------------------------------------------------------------
+// Private helpers
+// ---------------------------------------------------------------------------
+
fn require_admin(env: &Env, candidate: &Address) {
let admin: Option = env.storage().persistent().get(&DataKey::Admin);
let admin = admin.unwrap_or_else(|| panic_with_error!(env, RegistryError::NotInitialized));
-
candidate.require_auth();
if &admin != candidate {
panic_with_error!(env, RegistryError::Unauthorized);
}
}
-/// Compute the `expires_at` value for a freshly registered proof.
-///
-/// Returns `created_at + ttl` when a non-zero TTL is configured, or `0`
-/// (no expiration) otherwise. Uses saturating addition to avoid overflow on
-/// extreme inputs.
fn compute_expires_at(env: &Env) -> u64 {
let ttl: u64 = env
.storage()
@@ -622,7 +1059,6 @@ fn require_unique(env: &Env, proof_id: &BytesN<32>, video_hash: &BytesN<32>) {
{
panic_with_error!(env, RegistryError::DuplicateProof);
}
-
if env
.storage()
.persistent()
@@ -687,20 +1123,15 @@ fn parse_silent_witness_public_inputs(env: &Env, public_inputs: &Bytes) -> Silen
if public_inputs.len() != 128 {
panic_with_error!(env, RegistryError::InvalidPublicInputs);
}
-
let mut bytes = [0u8; 128];
public_inputs.copy_into_slice(&mut bytes);
-
let mut video_hash = [0u8; 32];
video_hash[..16].copy_from_slice(&bytes[16..32]);
video_hash[16..].copy_from_slice(&bytes[48..64]);
-
let mut nullifier = [0u8; 32];
nullifier.copy_from_slice(&bytes[96..128]);
-
let mut credential_root = [0u8; 32];
credential_root.copy_from_slice(&bytes[64..96]);
-
SilentWitnessInputs {
video_hash: BytesN::from_array(env, &video_hash),
credential_root: BytesN::from_array(env, &credential_root),
@@ -712,7 +1143,6 @@ fn verify_external_proof(env: &Env, verifier: &Address, public_inputs: Bytes, pr
let mut args: SorobanVec = SorobanVec::new(env);
args.push_back(public_inputs.into_val(env));
args.push_back(proof.into_val(env));
-
env.try_invoke_contract::<(), InvokeError>(verifier, &Symbol::new(env, "verify_proof"), args)
.unwrap_or_else(|_| panic_with_error!(env, RegistryError::InvalidProof))
.unwrap_or_else(|_| panic_with_error!(env, RegistryError::InvalidProof));
@@ -722,8 +1152,173 @@ fn verify_demo_zk_boundary(proof: &Bytes, credential_root: &BytesN<32>) -> bool
proof.len() > 0 && credential_root.len() == 32
}
+/// Get the next-to-be-used version number (does not increment).
+fn get_next_version(env: &Env) -> u32 {
+ env.storage()
+ .persistent()
+ .get(&DataKey::NextVerifierSetVersion)
+ .unwrap_or(1u32)
+}
+
+/// Store the pending set record and unlock timestamp.
+fn store_pending_set(
+ env: &Env,
+ version: u32,
+ member_count: u32,
+ threshold: u32,
+ unlocks_at: u64,
+ circuit_version: &String,
+) {
+ let record = VerifierSetRecord {
+ version,
+ member_count,
+ threshold,
+ active_from: unlocks_at,
+ retired_at: 0,
+ disabled: false,
+ circuit_version: circuit_version.clone(),
+ };
+ env.storage()
+ .persistent()
+ .set(&DataKey::PendingVerifierSetRecord, &record);
+ env.storage()
+ .persistent()
+ .set(&DataKey::PendingVerifierSetUnlocksAt, &unlocks_at);
+}
+
+fn emit_proposed(env: &Env, version: u32, threshold: u32, member_count: u32, unlocks_at: u64) {
+ VerifierSetProposed {
+ version,
+ threshold,
+ member_count,
+ unlocks_at,
+ }
+ .publish(env);
+}
+
+/// Retire the currently active set by setting its `retired_at` timestamp.
+fn retire_previous_active_set(env: &Env) {
+ let prev_version: Option = env
+ .storage()
+ .persistent()
+ .get(&DataKey::ActiveVerifierSetVersion);
+ if let Some(pv) = prev_version {
+ let record: Option = env
+ .storage()
+ .persistent()
+ .get(&DataKey::VerifierSetByVersion(pv));
+ if let Some(mut r) = record {
+ r.retired_at = env.ledger().timestamp();
+ env.storage()
+ .persistent()
+ .set(&DataKey::VerifierSetByVersion(pv), &r);
+ }
+ }
+}
+
+/// Load the active verifier set or panic with VerifierSetNotFound.
+fn load_active_vset(env: &Env) -> VerifierSetRecord {
+ let version: u32 = env
+ .storage()
+ .persistent()
+ .get(&DataKey::ActiveVerifierSetVersion)
+ .unwrap_or_else(|| panic_with_error!(env, RegistryError::VerifierSetNotFound));
+ env.storage()
+ .persistent()
+ .get(&DataKey::VerifierSetByVersion(version))
+ .unwrap_or_else(|| panic_with_error!(env, RegistryError::VerifierSetNotFound))
+}
+
+/// Call every member in `vset` and tally approvals, rejections, and failures.
+///
+/// Returns `(QuorumResult, approved_count, rejected_count, failure_count)`.
+///
+/// Each verifier is called via `try_invoke_contract`.
+/// - `Ok(Ok(()))` → approval.
+/// - `Ok(Err(_))` → explicit rejection (contract panic).
+/// - `Err(_)` → invocation failure (unavailable/unreachable).
+///
+/// Early-exit rules:
+/// - approved >= threshold → Approved.
+/// - rejected > members - threshold → Rejected.
+/// - failures > members - threshold → Unavailable (or VersionMismatch).
+fn evaluate_quorum(
+ env: &Env,
+ vset: &VerifierSetRecord,
+ public_inputs: &Bytes,
+ proof: &Bytes,
+) -> (QuorumResult, u32, u32, u32) {
+ let total = vset.member_count;
+ let threshold = vset.threshold;
+ let max_allowed_failures = total.saturating_sub(threshold);
+
+ let mut approved: u32 = 0;
+ let mut rejected: u32 = 0;
+ let mut failures: u32 = 0;
+
+ for i in 0..total {
+ let member: Address = env
+ .storage()
+ .persistent()
+ .get(&DataKey::VerifierSetMember(vset.version, i))
+ .unwrap_or_else(|| panic_with_error!(env, RegistryError::VerifierSetNotFound));
+
+ let mut args: SorobanVec = SorobanVec::new(env);
+ args.push_back(public_inputs.clone().into_val(env));
+ args.push_back(proof.clone().into_val(env));
+
+ let outcome = env.try_invoke_contract::<(), InvokeError>(
+ &member,
+ &Symbol::new(env, "verify_proof"),
+ args,
+ );
+
+ match outcome {
+ Ok(Ok(())) => {
+ approved += 1;
+ if approved >= threshold {
+ return (QuorumResult::Approved, approved, rejected, failures);
+ }
+ }
+ Ok(Err(_)) => {
+ // Explicit contract rejection.
+ rejected += 1;
+ if rejected > max_allowed_failures {
+ return (QuorumResult::Rejected, approved, rejected, failures);
+ }
+ }
+ Err(_) => {
+ // Host-level invocation failure (unreachable / panic at host).
+ failures += 1;
+ if failures > max_allowed_failures {
+ if failures == total && vset.circuit_version.len() > 0 {
+ return (QuorumResult::VersionMismatch, approved, rejected, failures);
+ }
+ return (QuorumResult::Unavailable, approved, rejected, failures);
+ }
+ }
+ }
+ }
+
+ // Post-loop final check.
+ if approved >= threshold {
+ return (QuorumResult::Approved, approved, rejected, failures);
+ }
+ if rejected > max_allowed_failures {
+ return (QuorumResult::Rejected, approved, rejected, failures);
+ }
+ if failures == total && total > 0 && vset.circuit_version.len() > 0 {
+ return (QuorumResult::VersionMismatch, approved, rejected, failures);
+ }
+ if failures > 0 {
+ return (QuorumResult::Unavailable, approved, rejected, failures);
+ }
+ (QuorumResult::Pending, approved, rejected, failures)
+}
+
mod test;
mod test_auth;
mod test_budget;
mod test_invariants;
mod test_expiry;
+mod test_verifier_sets;
diff --git a/contracts/contracts/harpocrates-registry/src/test_verifier_sets.rs b/contracts/contracts/harpocrates-registry/src/test_verifier_sets.rs
new file mode 100644
index 0000000..5e7f1f9
--- /dev/null
+++ b/contracts/contracts/harpocrates-registry/src/test_verifier_sets.rs
@@ -0,0 +1,826 @@
+#![cfg(test)]
+
+use super::*;
+use soroban_sdk::{
+ contract, contractimpl,
+ testutils::{Address as _, Ledger as _},
+ Address, Bytes, Env,
+};
+
+// ---------------------------------------------------------------------------
+// Mock verifier contracts
+// ---------------------------------------------------------------------------
+
+/// Always approves (returns Ok, does nothing).
+#[contract]
+struct MockVerifierApprove;
+
+#[contractimpl]
+impl MockVerifierApprove {
+ pub fn verify_proof(_env: Env, _public_inputs: Bytes, _proof: Bytes) {
+ // approve: return Ok
+ }
+}
+
+/// Always rejects (panics with contract error).
+#[contract]
+struct MockVerifierReject;
+
+#[contractimpl]
+impl MockVerifierReject {
+ pub fn verify_proof(_env: Env, _public_inputs: Bytes, _proof: Bytes) {
+ panic!("proof rejected");
+ }
+}
+
+// ---------------------------------------------------------------------------
+// Helpers
+// ---------------------------------------------------------------------------
+
+fn bytes32(env: &Env, value: u8) -> BytesN<32> {
+ BytesN::from_array(env, &[value; 32])
+}
+
+fn proof_bytes(env: &Env) -> Bytes {
+ Bytes::from_array(env, &[1, 2, 3, 4])
+}
+
+fn silent_public_inputs(
+ env: &Env,
+ video_hash: &BytesN<32>,
+ credential_root: &BytesN<32>,
+ nullifier: &BytesN<32>,
+) -> Bytes {
+ let mut vh = [0u8; 32];
+ video_hash.copy_into_slice(&mut vh);
+ let mut cr = [0u8; 32];
+ credential_root.copy_into_slice(&mut cr);
+ let mut nl = [0u8; 32];
+ nullifier.copy_into_slice(&mut nl);
+
+ let mut buf = [0u8; 128];
+ buf[16..32].copy_from_slice(&vh[..16]);
+ buf[48..64].copy_from_slice(&vh[16..]);
+ buf[64..96].copy_from_slice(&cr);
+ buf[96..128].copy_from_slice(&nl);
+ Bytes::from_array(env, &buf)
+}
+
+/// Advance ledger timestamp by `secs` seconds.
+fn advance_time(env: &Env, secs: u64) {
+ let current = env.ledger().timestamp();
+ env.ledger().set_timestamp(current + secs);
+}
+
+/// Set up a registry with:
+/// - `approve_count` MockVerifierApprove members (first)
+/// - `reject_count` MockVerifierReject members (after)
+/// and activate the set with the given threshold.
+///
+/// Returns (env, contract_id, admin).
+fn setup_with_set(
+ approve_count: u32,
+ reject_count: u32,
+ threshold: u32,
+) -> (Env, Address, Address) {
+ let env = Env::default();
+ env.mock_all_auths();
+
+ let contract_id = env.register(HarpocratesRegistry, ());
+ let client = HarpocratesRegistryClient::new(&env, &contract_id);
+ let admin = Address::generate(&env);
+ client.init(&admin);
+
+ let circuit_version = soroban_sdk::String::from_str(&env, "ultraHonk-0.87.0");
+ let total = approve_count + reject_count;
+
+ match total {
+ 1 => {
+ let m0 = if approve_count >= 1 {
+ env.register(MockVerifierApprove, ())
+ } else {
+ env.register(MockVerifierReject, ())
+ };
+ client.propose_verifier_set_1(&admin, &m0, &threshold, &circuit_version);
+ }
+ 2 => {
+ let m0 = if approve_count >= 1 {
+ env.register(MockVerifierApprove, ())
+ } else {
+ env.register(MockVerifierReject, ())
+ };
+ let m1 = if approve_count >= 2 {
+ env.register(MockVerifierApprove, ())
+ } else {
+ env.register(MockVerifierReject, ())
+ };
+ client.propose_verifier_set_2(&admin, &m0, &m1, &threshold, &circuit_version);
+ }
+ 3 => {
+ let m0 = if approve_count >= 1 {
+ env.register(MockVerifierApprove, ())
+ } else {
+ env.register(MockVerifierReject, ())
+ };
+ let m1 = if approve_count >= 2 {
+ env.register(MockVerifierApprove, ())
+ } else {
+ env.register(MockVerifierReject, ())
+ };
+ let m2 = if approve_count >= 3 {
+ env.register(MockVerifierApprove, ())
+ } else {
+ env.register(MockVerifierReject, ())
+ };
+ client.propose_verifier_set_3(&admin, &m0, &m1, &m2, &threshold, &circuit_version);
+ }
+ _ => panic!("setup_with_set only supports total 1-3 members"),
+ }
+
+ advance_time(&env, VERIFIER_SET_TIMELOCK_SECS + 1);
+ client.activate_verifier_set(&admin);
+
+ (env, contract_id, admin)
+}
+
+// ---------------------------------------------------------------------------
+// propose_verifier_set tests
+// ---------------------------------------------------------------------------
+
+#[test]
+fn propose_verifier_set_returns_version_1_on_first_call() {
+ let env = Env::default();
+ env.mock_all_auths();
+
+ let contract_id = env.register(HarpocratesRegistry, ());
+ let client = HarpocratesRegistryClient::new(&env, &contract_id);
+ let admin = Address::generate(&env);
+ client.init(&admin);
+
+ let verifier_id = env.register(MockVerifierApprove, ());
+ let circuit_version = soroban_sdk::String::from_str(&env, "v1");
+ let version = client.propose_verifier_set_1(&admin, &verifier_id, &1, &circuit_version);
+ assert_eq!(version, 1);
+}
+
+#[test]
+#[should_panic(expected = "Error(Contract, #3)")]
+fn propose_verifier_set_rejects_non_admin() {
+ let env = Env::default();
+ env.mock_all_auths();
+
+ let contract_id = env.register(HarpocratesRegistry, ());
+ let client = HarpocratesRegistryClient::new(&env, &contract_id);
+ let admin = Address::generate(&env);
+ let attacker = Address::generate(&env);
+ client.init(&admin);
+
+ let verifier_id = env.register(MockVerifierApprove, ());
+ let circuit_version = soroban_sdk::String::from_str(&env, "v1");
+ client.propose_verifier_set_1(&attacker, &verifier_id, &1, &circuit_version);
+}
+
+#[test]
+#[should_panic(expected = "Error(Contract, #25)")]
+fn propose_verifier_set_rejects_threshold_zero() {
+ let env = Env::default();
+ env.mock_all_auths();
+
+ let contract_id = env.register(HarpocratesRegistry, ());
+ let client = HarpocratesRegistryClient::new(&env, &contract_id);
+ let admin = Address::generate(&env);
+ client.init(&admin);
+
+ let verifier_id = env.register(MockVerifierApprove, ());
+ let circuit_version = soroban_sdk::String::from_str(&env, "v1");
+ client.propose_verifier_set_1(&admin, &verifier_id, &0, &circuit_version);
+}
+
+#[test]
+#[should_panic(expected = "Error(Contract, #25)")]
+fn propose_verifier_set_rejects_threshold_exceeding_member_count() {
+ let env = Env::default();
+ env.mock_all_auths();
+
+ let contract_id = env.register(HarpocratesRegistry, ());
+ let client = HarpocratesRegistryClient::new(&env, &contract_id);
+ let admin = Address::generate(&env);
+ client.init(&admin);
+
+ let verifier_id = env.register(MockVerifierApprove, ());
+ let circuit_version = soroban_sdk::String::from_str(&env, "v1");
+ // threshold=2 but only 1 member (propose_verifier_set_1 checks threshold <= 1)
+ client.propose_verifier_set_1(&admin, &verifier_id, &2, &circuit_version);
+}
+
+// ---------------------------------------------------------------------------
+// activate_verifier_set tests
+// ---------------------------------------------------------------------------
+
+#[test]
+fn activate_verifier_set_stores_and_returns_version() {
+ let env = Env::default();
+ env.mock_all_auths();
+
+ let contract_id = env.register(HarpocratesRegistry, ());
+ let client = HarpocratesRegistryClient::new(&env, &contract_id);
+ let admin = Address::generate(&env);
+ client.init(&admin);
+
+ let verifier_id = env.register(MockVerifierApprove, ());
+ let circuit_version = soroban_sdk::String::from_str(&env, "v1");
+ let proposed = client.propose_verifier_set_1(&admin, &verifier_id, &1, &circuit_version);
+ assert_eq!(proposed, 1);
+
+ advance_time(&env, VERIFIER_SET_TIMELOCK_SECS + 1);
+
+ let activated = client.activate_verifier_set(&admin);
+ assert_eq!(activated, 1);
+
+ let vset = client.get_active_verifier_set().unwrap();
+ assert_eq!(vset.version, 1);
+ assert_eq!(vset.threshold, 1);
+ assert_eq!(vset.member_count, 1);
+ assert!(!vset.disabled);
+}
+
+#[test]
+#[should_panic(expected = "Error(Contract, #24)")]
+fn activate_verifier_set_panics_with_no_pending() {
+ let env = Env::default();
+ env.mock_all_auths();
+
+ let contract_id = env.register(HarpocratesRegistry, ());
+ let client = HarpocratesRegistryClient::new(&env, &contract_id);
+ let admin = Address::generate(&env);
+ client.init(&admin);
+
+ client.activate_verifier_set(&admin);
+}
+
+#[test]
+#[should_panic(expected = "Error(Contract, #23)")]
+fn activate_verifier_set_panics_before_timelock_expires() {
+ let env = Env::default();
+ env.mock_all_auths();
+
+ let contract_id = env.register(HarpocratesRegistry, ());
+ let client = HarpocratesRegistryClient::new(&env, &contract_id);
+ let admin = Address::generate(&env);
+ client.init(&admin);
+
+ let verifier_id = env.register(MockVerifierApprove, ());
+ let circuit_version = soroban_sdk::String::from_str(&env, "v1");
+ client.propose_verifier_set_1(&admin, &verifier_id, &1, &circuit_version);
+
+ // Do NOT advance time past timelock.
+ client.activate_verifier_set(&admin);
+}
+
+#[test]
+fn activate_verifier_set_retires_previous_set() {
+ let env = Env::default();
+ env.mock_all_auths();
+
+ let contract_id = env.register(HarpocratesRegistry, ());
+ let client = HarpocratesRegistryClient::new(&env, &contract_id);
+ let admin = Address::generate(&env);
+ client.init(&admin);
+
+ let circuit_version = soroban_sdk::String::from_str(&env, "v1");
+ let v1_id = env.register(MockVerifierApprove, ());
+ client.propose_verifier_set_1(&admin, &v1_id, &1, &circuit_version);
+ advance_time(&env, VERIFIER_SET_TIMELOCK_SECS + 1);
+ client.activate_verifier_set(&admin);
+
+ // Propose and activate v2.
+ let circuit_version2 = soroban_sdk::String::from_str(&env, "v2");
+ let v2_id = env.register(MockVerifierApprove, ());
+ client.propose_verifier_set_1(&admin, &v2_id, &1, &circuit_version2);
+ advance_time(&env, VERIFIER_SET_TIMELOCK_SECS + 1);
+ client.activate_verifier_set(&admin);
+
+ // v1 should be retired (retired_at != 0).
+ let v1_record = client.get_verifier_set(&1).unwrap();
+ assert_ne!(v1_record.retired_at, 0, "v1 should have been retired");
+
+ // v2 is now active.
+ let active = client.get_active_verifier_set().unwrap();
+ assert_eq!(active.version, 2);
+}
+
+// ---------------------------------------------------------------------------
+// Rotation overlap (staged rotation) test
+// ---------------------------------------------------------------------------
+
+#[test]
+fn rotation_overlap_v1_retired_when_v2_activates() {
+ // Simulates staged rotation: propose v2 while v1 is active, then activate v2.
+ // v1 should be marked retired atomically when v2 activates.
+ let env = Env::default();
+ env.mock_all_auths();
+
+ let contract_id = env.register(HarpocratesRegistry, ());
+ let client = HarpocratesRegistryClient::new(&env, &contract_id);
+ let admin = Address::generate(&env);
+ client.init(&admin);
+
+ // Activate v1.
+ let cv1 = soroban_sdk::String::from_str(&env, "circuit-v1");
+ let v1_id = env.register(MockVerifierApprove, ());
+ client.propose_verifier_set_1(&admin, &v1_id, &1, &cv1);
+ advance_time(&env, VERIFIER_SET_TIMELOCK_SECS + 1);
+ client.activate_verifier_set(&admin);
+
+ // While v1 is active, propose v2.
+ let cv2 = soroban_sdk::String::from_str(&env, "circuit-v2");
+ let v2_id = env.register(MockVerifierApprove, ());
+ client.propose_verifier_set_1(&admin, &v2_id, &1, &cv2);
+
+ // Timelock hasn't elapsed; v1 still usable.
+ let active_before = client.get_active_verifier_set().unwrap();
+ assert_eq!(active_before.version, 1);
+
+ // Advance past timelock and activate v2.
+ advance_time(&env, VERIFIER_SET_TIMELOCK_SECS + 1);
+ client.activate_verifier_set(&admin);
+
+ // v1 is now retired.
+ let v1_after = client.get_verifier_set(&1).unwrap();
+ assert_ne!(v1_after.retired_at, 0);
+
+ // v2 is active.
+ let active_after = client.get_active_verifier_set().unwrap();
+ assert_eq!(active_after.version, 2);
+}
+
+// ---------------------------------------------------------------------------
+// disable_verifier_set tests
+// ---------------------------------------------------------------------------
+
+#[test]
+fn disable_verifier_set_marks_set_disabled() {
+ let env = Env::default();
+ env.mock_all_auths();
+
+ let contract_id = env.register(HarpocratesRegistry, ());
+ let client = HarpocratesRegistryClient::new(&env, &contract_id);
+ let admin = Address::generate(&env);
+ client.init(&admin);
+
+ let verifier_id = env.register(MockVerifierApprove, ());
+ let circuit_version = soroban_sdk::String::from_str(&env, "v1");
+ client.propose_verifier_set_1(&admin, &verifier_id, &1, &circuit_version);
+ advance_time(&env, VERIFIER_SET_TIMELOCK_SECS + 1);
+ client.activate_verifier_set(&admin);
+
+ client.disable_verifier_set(&admin, &1);
+
+ let record = client.get_verifier_set(&1).unwrap();
+ assert!(record.disabled, "set should be disabled after emergency disable");
+}
+
+#[test]
+#[should_panic(expected = "Error(Contract, #14)")]
+fn disable_verifier_set_panics_for_unknown_version() {
+ let env = Env::default();
+ env.mock_all_auths();
+
+ let contract_id = env.register(HarpocratesRegistry, ());
+ let client = HarpocratesRegistryClient::new(&env, &contract_id);
+ let admin = Address::generate(&env);
+ client.init(&admin);
+
+ client.disable_verifier_set(&admin, &99);
+}
+
+#[test]
+#[should_panic(expected = "Error(Contract, #3)")]
+fn disable_verifier_set_rejects_non_admin() {
+ let env = Env::default();
+ env.mock_all_auths();
+
+ let contract_id = env.register(HarpocratesRegistry, ());
+ let client = HarpocratesRegistryClient::new(&env, &contract_id);
+ let admin = Address::generate(&env);
+ let attacker = Address::generate(&env);
+ client.init(&admin);
+
+ let verifier_id = env.register(MockVerifierApprove, ());
+ let circuit_version = soroban_sdk::String::from_str(&env, "v1");
+ client.propose_verifier_set_1(&admin, &verifier_id, &1, &circuit_version);
+ advance_time(&env, VERIFIER_SET_TIMELOCK_SECS + 1);
+ client.activate_verifier_set(&admin);
+
+ client.disable_verifier_set(&attacker, &1);
+}
+
+// ---------------------------------------------------------------------------
+// register_anon_verified_quorum — approval path
+// ---------------------------------------------------------------------------
+
+#[test]
+fn quorum_approved_with_single_approving_verifier() {
+ let (env, contract_id, admin) = setup_with_set(1, 0, 1);
+ let client = HarpocratesRegistryClient::new(&env, &contract_id);
+
+ let video_hash = bytes32(&env, 70);
+ let credential_root = bytes32(&env, 71);
+ let nullifier = bytes32(&env, 72);
+ let proof_id = bytes32(&env, 73);
+
+ client.add_credential_root(&admin, &credential_root, &bytes32(&env, 74));
+ let pi = silent_public_inputs(&env, &video_hash, &credential_root, &nullifier);
+
+ let record = client.register_anon_verified_quorum(
+ &video_hash,
+ &bytes32(&env, 75),
+ &proof_id,
+ &pi,
+ &proof_bytes(&env),
+ );
+ assert_eq!(record.tier, TIER_SILENT_WITNESS);
+ assert_eq!(record.video_hash, video_hash);
+ assert_eq!(record.nullifier, Some(nullifier.clone()));
+ assert!(client.has_nullifier(&nullifier));
+}
+
+#[test]
+fn quorum_approved_with_majority_approving_verifiers() {
+ // 2 approve, 1 reject, threshold=2 → should NOT pass (2 == threshold, 1 > 3-2=1).
+ // Actually: 2-of-3 with 2 approves: approved(2) >= threshold(2) → Approved.
+ let (env, contract_id, admin) = setup_with_set(2, 1, 2);
+ let client = HarpocratesRegistryClient::new(&env, &contract_id);
+
+ let video_hash = bytes32(&env, 80);
+ let credential_root = bytes32(&env, 81);
+ let nullifier = bytes32(&env, 82);
+ let proof_id = bytes32(&env, 83);
+
+ client.add_credential_root(&admin, &credential_root, &bytes32(&env, 84));
+ let pi = silent_public_inputs(&env, &video_hash, &credential_root, &nullifier);
+
+ let record = client.register_anon_verified_quorum(
+ &video_hash,
+ &bytes32(&env, 85),
+ &proof_id,
+ &pi,
+ &proof_bytes(&env),
+ );
+ assert_eq!(record.tier, TIER_SILENT_WITNESS);
+}
+
+// ---------------------------------------------------------------------------
+// register_anon_verified_quorum — rejection/split path
+// ---------------------------------------------------------------------------
+
+/// In the Soroban test env, `panic!()` in a WASM mock contract is a host error
+/// (WasmVm::InvalidAction), treated as verifier failure, not rejection.
+/// With 1 failing verifier and circuit_version set → VersionMismatch (#19).
+#[test]
+#[should_panic(expected = "Error(Contract, #19)")]
+fn quorum_rejected_when_all_verifiers_reject() {
+ // 0 approve, 1 panic/fail, threshold=1 → VersionMismatch in test env.
+ let (env, contract_id, admin) = setup_with_set(0, 1, 1);
+ let client = HarpocratesRegistryClient::new(&env, &contract_id);
+
+ let video_hash = bytes32(&env, 90);
+ let credential_root = bytes32(&env, 91);
+ let nullifier = bytes32(&env, 92);
+ let proof_id = bytes32(&env, 93);
+
+ client.add_credential_root(&admin, &credential_root, &bytes32(&env, 94));
+ let pi = silent_public_inputs(&env, &video_hash, &credential_root, &nullifier);
+
+ client.register_anon_verified_quorum(
+ &video_hash,
+ &bytes32(&env, 95),
+ &proof_id,
+ &pi,
+ &proof_bytes(&env),
+ );
+}
+
+/// In test env, panics from WASM = host failures.
+/// 1 approve, 2 panic (failures), threshold=2: failures(2) > max_allowed(1) → Unavailable (#15).
+#[test]
+#[should_panic(expected = "Error(Contract, #15)")]
+fn quorum_rejected_when_majority_rejects() {
+ // 1 approve, 2 fail (panics), threshold=2 → QuorumNotReached in test env.
+ let (env, contract_id, admin) = setup_with_set(1, 2, 2);
+ let client = HarpocratesRegistryClient::new(&env, &contract_id);
+
+ let video_hash = bytes32(&env, 100);
+ let credential_root = bytes32(&env, 101);
+ let nullifier = bytes32(&env, 102);
+ let proof_id = bytes32(&env, 103);
+
+ client.add_credential_root(&admin, &credential_root, &bytes32(&env, 104));
+ let pi = silent_public_inputs(&env, &video_hash, &credential_root, &nullifier);
+
+ client.register_anon_verified_quorum(
+ &video_hash,
+ &bytes32(&env, 105),
+ &proof_id,
+ &pi,
+ &proof_bytes(&env),
+ );
+}
+
+// ---------------------------------------------------------------------------
+// register_anon_verified_quorum — emergency disable
+// ---------------------------------------------------------------------------
+
+#[test]
+#[should_panic(expected = "Error(Contract, #17)")]
+fn quorum_panics_when_active_set_is_disabled() {
+ let (env, contract_id, admin) = setup_with_set(1, 0, 1);
+ let client = HarpocratesRegistryClient::new(&env, &contract_id);
+
+ // Emergency disable the active set.
+ client.disable_verifier_set(&admin, &1);
+
+ let video_hash = bytes32(&env, 110);
+ let credential_root = bytes32(&env, 111);
+ let nullifier = bytes32(&env, 112);
+ let proof_id = bytes32(&env, 113);
+
+ client.add_credential_root(&admin, &credential_root, &bytes32(&env, 114));
+ let pi = silent_public_inputs(&env, &video_hash, &credential_root, &nullifier);
+
+ client.register_anon_verified_quorum(
+ &video_hash,
+ &bytes32(&env, 115),
+ &proof_id,
+ &pi,
+ &proof_bytes(&env),
+ );
+}
+
+// ---------------------------------------------------------------------------
+// register_anon_verified_quorum — no active verifier set
+// ---------------------------------------------------------------------------
+
+#[test]
+#[should_panic(expected = "Error(Contract, #14)")]
+fn quorum_panics_when_no_active_verifier_set() {
+ let env = Env::default();
+ env.mock_all_auths();
+
+ let contract_id = env.register(HarpocratesRegistry, ());
+ let client = HarpocratesRegistryClient::new(&env, &contract_id);
+ let admin = Address::generate(&env);
+ client.init(&admin);
+
+ // No verifier set proposed or activated.
+ let video_hash = bytes32(&env, 120);
+ let credential_root = bytes32(&env, 121);
+ let nullifier = bytes32(&env, 122);
+ let proof_id = bytes32(&env, 123);
+
+ client.add_credential_root(&admin, &credential_root, &bytes32(&env, 124));
+ let pi = silent_public_inputs(&env, &video_hash, &credential_root, &nullifier);
+
+ client.register_anon_verified_quorum(
+ &video_hash,
+ &bytes32(&env, 125),
+ &proof_id,
+ &pi,
+ &proof_bytes(&env),
+ );
+}
+
+// ---------------------------------------------------------------------------
+// register_anon_verified_quorum — duplicate nullifier (replay protection)
+// ---------------------------------------------------------------------------
+
+#[test]
+#[should_panic(expected = "Error(Contract, #6)")]
+fn quorum_rejects_duplicate_nullifier() {
+ let (env, contract_id, admin) = setup_with_set(1, 0, 1);
+ let client = HarpocratesRegistryClient::new(&env, &contract_id);
+
+ let credential_root = bytes32(&env, 131);
+ let nullifier = bytes32(&env, 132);
+ let video_hash1 = bytes32(&env, 130);
+ let video_hash2 = bytes32(&env, 135);
+ let proof_id1 = bytes32(&env, 133);
+ let proof_id2 = bytes32(&env, 134);
+
+ client.add_credential_root(&admin, &credential_root, &bytes32(&env, 136));
+ let pi1 = silent_public_inputs(&env, &video_hash1, &credential_root, &nullifier);
+ let pi2 = silent_public_inputs(&env, &video_hash2, &credential_root, &nullifier);
+
+ // First registration should succeed.
+ client.register_anon_verified_quorum(
+ &video_hash1,
+ &bytes32(&env, 137),
+ &proof_id1,
+ &pi1,
+ &proof_bytes(&env),
+ );
+
+ // Second with same nullifier must fail.
+ client.register_anon_verified_quorum(
+ &video_hash2,
+ &bytes32(&env, 138),
+ &proof_id2,
+ &pi2,
+ &proof_bytes(&env),
+ );
+}
+
+// ---------------------------------------------------------------------------
+// register_anon_verified_quorum — duplicate proof_id guard
+// ---------------------------------------------------------------------------
+
+#[test]
+#[should_panic(expected = "Error(Contract, #4)")]
+fn quorum_rejects_duplicate_proof_id() {
+ let (env, contract_id, admin) = setup_with_set(1, 0, 1);
+ let client = HarpocratesRegistryClient::new(&env, &contract_id);
+
+ let credential_root = bytes32(&env, 141);
+ let nullifier1 = bytes32(&env, 142);
+ let nullifier2 = bytes32(&env, 143);
+ let proof_id = bytes32(&env, 144); // same both times
+ let video_hash1 = bytes32(&env, 140);
+ let video_hash2 = bytes32(&env, 145);
+
+ client.add_credential_root(&admin, &credential_root, &bytes32(&env, 146));
+ let pi1 = silent_public_inputs(&env, &video_hash1, &credential_root, &nullifier1);
+ let pi2 = silent_public_inputs(&env, &video_hash2, &credential_root, &nullifier2);
+
+ client.register_anon_verified_quorum(
+ &video_hash1,
+ &bytes32(&env, 147),
+ &proof_id,
+ &pi1,
+ &proof_bytes(&env),
+ );
+ // duplicate proof_id
+ client.register_anon_verified_quorum(
+ &video_hash2,
+ &bytes32(&env, 148),
+ &proof_id,
+ &pi2,
+ &proof_bytes(&env),
+ );
+}
+
+// ---------------------------------------------------------------------------
+// register_anon_verified_quorum — bounds check
+// ---------------------------------------------------------------------------
+
+#[test]
+#[should_panic(expected = "Error(Contract, #20)")]
+fn quorum_rejects_oversized_proof() {
+ let (env, contract_id, admin) = setup_with_set(1, 0, 1);
+ let client = HarpocratesRegistryClient::new(&env, &contract_id);
+
+ let video_hash = bytes32(&env, 150);
+ let credential_root = bytes32(&env, 151);
+ let nullifier = bytes32(&env, 152);
+ let proof_id = bytes32(&env, 153);
+
+ client.add_credential_root(&admin, &credential_root, &bytes32(&env, 154));
+ let pi = silent_public_inputs(&env, &video_hash, &credential_root, &nullifier);
+
+ // Build a proof larger than MAX_PROOF_SIZE_BYTES (65536 bytes).
+ let chunk = Bytes::from_array(&env, &[1u8; 256]);
+ let mut oversized_proof = Bytes::new(&env);
+ for _ in 0..257u32 {
+ // 257 * 256 = 65792 > 65536
+ oversized_proof.append(&chunk);
+ }
+
+ client.register_anon_verified_quorum(
+ &video_hash,
+ &bytes32(&env, 155),
+ &proof_id,
+ &pi,
+ &oversized_proof,
+ );
+}
+
+// ---------------------------------------------------------------------------
+// get_verifier_set / get_active_verifier_set
+// ---------------------------------------------------------------------------
+
+#[test]
+fn get_verifier_set_returns_none_for_unknown_version() {
+ let env = Env::default();
+ env.mock_all_auths();
+
+ let contract_id = env.register(HarpocratesRegistry, ());
+ let client = HarpocratesRegistryClient::new(&env, &contract_id);
+ let admin = Address::generate(&env);
+ client.init(&admin);
+
+ assert!(client.get_verifier_set(&99).is_none());
+}
+
+#[test]
+fn get_active_verifier_set_returns_none_before_any_activation() {
+ let env = Env::default();
+ env.mock_all_auths();
+
+ let contract_id = env.register(HarpocratesRegistry, ());
+ let client = HarpocratesRegistryClient::new(&env, &contract_id);
+ let admin = Address::generate(&env);
+ client.init(&admin);
+
+ assert!(client.get_active_verifier_set().is_none());
+}
+
+// ---------------------------------------------------------------------------
+// Version mismatch: all verifiers unavailable with circuit_version set
+// ---------------------------------------------------------------------------
+
+/// A verifier that always panics at the host level (simulates being unreachable)
+/// is implemented as MockVerifierReject which panics explicitly.
+/// For "unavailable" test we'd need a host error; we simulate version-mismatch
+/// by checking Pending/QuorumNotReached when no verifiers can vote.
+/// The VersionMismatch path requires host-level errors which are difficult to
+/// trigger in unit tests. We verify the version_mismatch path indirectly:
+/// a set with all rejectors returns Rejected (not VersionMismatch) since
+/// contract panics are treated as rejections in try_invoke_contract.
+#[test]
+fn version_mismatch_not_triggered_by_contract_panics() {
+ // All contract panics are rejections, not failures, so no VersionMismatch.
+ // This test verifies the boundary: with 1 reject, we get #7 (InvalidProof / Rejected).
+ let (env, contract_id, admin) = setup_with_set(0, 1, 1);
+ let client = HarpocratesRegistryClient::new(&env, &contract_id);
+
+ let video_hash = bytes32(&env, 160);
+ let credential_root = bytes32(&env, 161);
+ let nullifier = bytes32(&env, 162);
+ let proof_id = bytes32(&env, 163);
+
+ client.add_credential_root(&admin, &credential_root, &bytes32(&env, 164));
+ let pi = silent_public_inputs(&env, &video_hash, &credential_root, &nullifier);
+
+ let result = env.try_invoke_contract::(
+ &contract_id,
+ &soroban_sdk::Symbol::new(&env, "register_anon_verified_quorum"),
+ {
+ let mut args = soroban_sdk::Vec::new(&env);
+ args.push_back(video_hash.into_val(&env));
+ args.push_back(bytes32(&env, 165).into_val(&env));
+ args.push_back(proof_id.into_val(&env));
+ args.push_back(pi.into_val(&env));
+ args.push_back(proof_bytes(&env).into_val(&env));
+ args
+ },
+ );
+ // The call must fail (quorum rejected).
+ assert!(result.is_err(), "expected quorum rejection to fail the call");
+}
+
+// ---------------------------------------------------------------------------
+// Backward compat: legacy register_anonymous_verified still works
+// ---------------------------------------------------------------------------
+
+#[contract]
+struct MockNoirVerifierLegacy;
+
+#[contractimpl]
+impl MockNoirVerifierLegacy {
+ pub fn verify_proof(_env: Env, public_inputs: Bytes, proof: Bytes) {
+ if public_inputs.len() != 128 || proof.is_empty() {
+ panic!("invalid proof");
+ }
+ }
+}
+
+#[test]
+fn legacy_register_anonymous_verified_still_works_alongside_quorum() {
+ let env = Env::default();
+ env.mock_all_auths();
+
+ let contract_id = env.register(HarpocratesRegistry, ());
+ let verifier_id = env.register(MockNoirVerifierLegacy, ());
+ let client = HarpocratesRegistryClient::new(&env, &contract_id);
+ let admin = Address::generate(&env);
+
+ client.init(&admin);
+ client.set_verifier(&admin, &verifier_id);
+
+ let video_hash = bytes32(&env, 200);
+ let credential_root = bytes32(&env, 201);
+ let nullifier = bytes32(&env, 202);
+ let proof_id = bytes32(&env, 203);
+
+ client.add_credential_root(&admin, &credential_root, &bytes32(&env, 204));
+ let pi = silent_public_inputs(&env, &video_hash, &credential_root, &nullifier);
+
+ let record = client.register_anonymous_verified(
+ &video_hash,
+ &bytes32(&env, 205),
+ &proof_id,
+ &pi,
+ &proof_bytes(&env),
+ );
+ assert_eq!(record.tier, TIER_SILENT_WITNESS);
+ assert_eq!(record.nullifier, Some(nullifier));
+}
diff --git a/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/activate_verifier_set_panics_before_timelock_expires.1.json b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/activate_verifier_set_panics_before_timelock_expires.1.json
new file mode 100644
index 0000000..858ce17
--- /dev/null
+++ b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/activate_verifier_set_panics_before_timelock_expires.1.json
@@ -0,0 +1,328 @@
+{
+ "generators": {
+ "address": 3,
+ "nonce": 0,
+ "mux_id": 0
+ },
+ "auth": [
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "init",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "propose_verifier_set_1",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "string": "v1"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 25,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "PendingVerifierSetMember"
+ },
+ {
+ "u32": 0
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "PendingVerifierSetRecord"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "active_from"
+ },
+ "val": {
+ "u64": "300"
+ }
+ },
+ {
+ "key": {
+ "symbol": "circuit_version"
+ },
+ "val": {
+ "string": "v1"
+ }
+ },
+ {
+ "key": {
+ "symbol": "disabled"
+ },
+ "val": {
+ "bool": false
+ }
+ },
+ {
+ "key": {
+ "symbol": "member_count"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "retired_at"
+ },
+ "val": {
+ "u64": "0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "threshold"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "version"
+ },
+ "val": {
+ "u32": 1
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "PendingVerifierSetUnlocksAt"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u64": "300"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "801925984706572462"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "5541220902715666415"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ }
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/activate_verifier_set_panics_with_no_pending.1.json b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/activate_verifier_set_panics_with_no_pending.1.json
new file mode 100644
index 0000000..67bf3b1
--- /dev/null
+++ b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/activate_verifier_set_panics_with_no_pending.1.json
@@ -0,0 +1,124 @@
+{
+ "generators": {
+ "address": 2,
+ "nonce": 0,
+ "mux_id": 0
+ },
+ "auth": [
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "init",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 25,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "801925984706572462"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ }
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/activate_verifier_set_retires_previous_set.1.json b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/activate_verifier_set_retires_previous_set.1.json
new file mode 100644
index 0000000..8229e81
--- /dev/null
+++ b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/activate_verifier_set_retires_previous_set.1.json
@@ -0,0 +1,623 @@
+{
+ "generators": {
+ "address": 4,
+ "nonce": 0,
+ "mux_id": 0
+ },
+ "auth": [
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "init",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "propose_verifier_set_1",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "string": "v1"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "activate_verifier_set",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "propose_verifier_set_1",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "string": "v2"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "activate_verifier_set",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 25,
+ "sequence_number": 0,
+ "timestamp": 602,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ActiveVerifierSetVersion"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u32": 2
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "NextVerifierSetVersion"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u32": 3
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetByVersion"
+ },
+ {
+ "u32": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "active_from"
+ },
+ "val": {
+ "u64": "300"
+ }
+ },
+ {
+ "key": {
+ "symbol": "circuit_version"
+ },
+ "val": {
+ "string": "v1"
+ }
+ },
+ {
+ "key": {
+ "symbol": "disabled"
+ },
+ "val": {
+ "bool": false
+ }
+ },
+ {
+ "key": {
+ "symbol": "member_count"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "retired_at"
+ },
+ "val": {
+ "u64": "602"
+ }
+ },
+ {
+ "key": {
+ "symbol": "threshold"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "version"
+ },
+ "val": {
+ "u32": 1
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetByVersion"
+ },
+ {
+ "u32": 2
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "active_from"
+ },
+ "val": {
+ "u64": "601"
+ }
+ },
+ {
+ "key": {
+ "symbol": "circuit_version"
+ },
+ "val": {
+ "string": "v2"
+ }
+ },
+ {
+ "key": {
+ "symbol": "disabled"
+ },
+ "val": {
+ "bool": false
+ }
+ },
+ {
+ "key": {
+ "symbol": "member_count"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "retired_at"
+ },
+ "val": {
+ "u64": "0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "threshold"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "version"
+ },
+ "val": {
+ "u32": 2
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetMember"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "u32": 0
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetMember"
+ },
+ {
+ "u32": 2
+ },
+ {
+ "u32": 0
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "801925984706572462"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "1033654523790656264"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "2032731177588607455"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "4837995959683129791"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "5541220902715666415"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ }
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/activate_verifier_set_stores_and_returns_version.1.json b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/activate_verifier_set_stores_and_returns_version.1.json
new file mode 100644
index 0000000..c9561fd
--- /dev/null
+++ b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/activate_verifier_set_stores_and_returns_version.1.json
@@ -0,0 +1,397 @@
+{
+ "generators": {
+ "address": 3,
+ "nonce": 0,
+ "mux_id": 0
+ },
+ "auth": [
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "init",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "propose_verifier_set_1",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "string": "v1"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "activate_verifier_set",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 25,
+ "sequence_number": 0,
+ "timestamp": 301,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ActiveVerifierSetVersion"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u32": 1
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "NextVerifierSetVersion"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u32": 2
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetByVersion"
+ },
+ {
+ "u32": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "active_from"
+ },
+ "val": {
+ "u64": "300"
+ }
+ },
+ {
+ "key": {
+ "symbol": "circuit_version"
+ },
+ "val": {
+ "string": "v1"
+ }
+ },
+ {
+ "key": {
+ "symbol": "disabled"
+ },
+ "val": {
+ "bool": false
+ }
+ },
+ {
+ "key": {
+ "symbol": "member_count"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "retired_at"
+ },
+ "val": {
+ "u64": "0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "threshold"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "version"
+ },
+ "val": {
+ "u32": 1
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetMember"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "u32": 0
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "801925984706572462"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "1033654523790656264"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "5541220902715666415"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ }
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/disable_verifier_set_marks_set_disabled.1.json b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/disable_verifier_set_marks_set_disabled.1.json
new file mode 100644
index 0000000..410f75c
--- /dev/null
+++ b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/disable_verifier_set_marks_set_disabled.1.json
@@ -0,0 +1,439 @@
+{
+ "generators": {
+ "address": 3,
+ "nonce": 0,
+ "mux_id": 0
+ },
+ "auth": [
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "init",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "propose_verifier_set_1",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "string": "v1"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "activate_verifier_set",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "disable_verifier_set",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ },
+ {
+ "u32": 1
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 25,
+ "sequence_number": 0,
+ "timestamp": 301,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ActiveVerifierSetVersion"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u32": 1
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "NextVerifierSetVersion"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u32": 2
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetByVersion"
+ },
+ {
+ "u32": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "active_from"
+ },
+ "val": {
+ "u64": "300"
+ }
+ },
+ {
+ "key": {
+ "symbol": "circuit_version"
+ },
+ "val": {
+ "string": "v1"
+ }
+ },
+ {
+ "key": {
+ "symbol": "disabled"
+ },
+ "val": {
+ "bool": true
+ }
+ },
+ {
+ "key": {
+ "symbol": "member_count"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "retired_at"
+ },
+ "val": {
+ "u64": "0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "threshold"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "version"
+ },
+ "val": {
+ "u32": 1
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetMember"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "u32": 0
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "801925984706572462"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "1033654523790656264"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "4837995959683129791"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "5541220902715666415"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ }
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/disable_verifier_set_panics_for_unknown_version.1.json b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/disable_verifier_set_panics_for_unknown_version.1.json
new file mode 100644
index 0000000..67bf3b1
--- /dev/null
+++ b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/disable_verifier_set_panics_for_unknown_version.1.json
@@ -0,0 +1,124 @@
+{
+ "generators": {
+ "address": 2,
+ "nonce": 0,
+ "mux_id": 0
+ },
+ "auth": [
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "init",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 25,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "801925984706572462"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ }
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/disable_verifier_set_rejects_non_admin.1.json b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/disable_verifier_set_rejects_non_admin.1.json
new file mode 100644
index 0000000..dac09e9
--- /dev/null
+++ b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/disable_verifier_set_rejects_non_admin.1.json
@@ -0,0 +1,397 @@
+{
+ "generators": {
+ "address": 4,
+ "nonce": 0,
+ "mux_id": 0
+ },
+ "auth": [
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "init",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "propose_verifier_set_1",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "string": "v1"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "activate_verifier_set",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 25,
+ "sequence_number": 0,
+ "timestamp": 301,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ActiveVerifierSetVersion"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u32": 1
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "NextVerifierSetVersion"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u32": 2
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetByVersion"
+ },
+ {
+ "u32": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "active_from"
+ },
+ "val": {
+ "u64": "300"
+ }
+ },
+ {
+ "key": {
+ "symbol": "circuit_version"
+ },
+ "val": {
+ "string": "v1"
+ }
+ },
+ {
+ "key": {
+ "symbol": "disabled"
+ },
+ "val": {
+ "bool": false
+ }
+ },
+ {
+ "key": {
+ "symbol": "member_count"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "retired_at"
+ },
+ "val": {
+ "u64": "0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "threshold"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "version"
+ },
+ "val": {
+ "u32": 1
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetMember"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "u32": 0
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "801925984706572462"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "1033654523790656264"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "5541220902715666415"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ }
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/get_active_verifier_set_returns_none_before_any_activation.1.json b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/get_active_verifier_set_returns_none_before_any_activation.1.json
new file mode 100644
index 0000000..67bf3b1
--- /dev/null
+++ b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/get_active_verifier_set_returns_none_before_any_activation.1.json
@@ -0,0 +1,124 @@
+{
+ "generators": {
+ "address": 2,
+ "nonce": 0,
+ "mux_id": 0
+ },
+ "auth": [
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "init",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 25,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "801925984706572462"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ }
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/get_verifier_set_returns_none_for_unknown_version.1.json b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/get_verifier_set_returns_none_for_unknown_version.1.json
new file mode 100644
index 0000000..67bf3b1
--- /dev/null
+++ b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/get_verifier_set_returns_none_for_unknown_version.1.json
@@ -0,0 +1,124 @@
+{
+ "generators": {
+ "address": 2,
+ "nonce": 0,
+ "mux_id": 0
+ },
+ "auth": [
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "init",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 25,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "801925984706572462"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ }
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/legacy_register_anonymous_verified_still_works_alongside_quorum.1.json b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/legacy_register_anonymous_verified_still_works_alongside_quorum.1.json
new file mode 100644
index 0000000..9502f42
--- /dev/null
+++ b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/legacy_register_anonymous_verified_still_works_alongside_quorum.1.json
@@ -0,0 +1,513 @@
+{
+ "generators": {
+ "address": 3,
+ "nonce": 0,
+ "mux_id": 0
+ },
+ "auth": [
+ [],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "init",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "set_verifier",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "add_credential_root",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "bytes": "c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9"
+ },
+ {
+ "bytes": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 25,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "CredentialRoot"
+ },
+ {
+ "bytes": "c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "active"
+ },
+ "val": {
+ "bool": true
+ }
+ },
+ {
+ "key": {
+ "symbol": "issued_at"
+ },
+ "val": {
+ "u64": "0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "metadata_hash"
+ },
+ "val": {
+ "bytes": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Nullifier"
+ },
+ {
+ "bytes": "cacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacaca"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "bool": true
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Proof"
+ },
+ {
+ "bytes": "cbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "created_at"
+ },
+ "val": {
+ "u64": "0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "expires_at"
+ },
+ "val": {
+ "u64": "0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "issuer"
+ },
+ "val": "void"
+ },
+ {
+ "key": {
+ "symbol": "metadata_hash"
+ },
+ "val": {
+ "bytes": "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
+ }
+ },
+ {
+ "key": {
+ "symbol": "nullifier"
+ },
+ "val": {
+ "bytes": "cacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacaca"
+ }
+ },
+ {
+ "key": {
+ "symbol": "source"
+ },
+ "val": "void"
+ },
+ {
+ "key": {
+ "symbol": "status"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "tier"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "video_hash"
+ },
+ "val": {
+ "bytes": "c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8"
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Verifier"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Video"
+ },
+ {
+ "bytes": "c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "bytes": "cbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "801925984706572462"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "1033654523790656264"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "5541220902715666415"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ }
+ ]
+ },
+ "events": [
+ {
+ "event": {
+ "ext": "v0",
+ "contract_id": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "type_": "contract",
+ "body": {
+ "v0": {
+ "topics": [
+ {
+ "symbol": "proof"
+ },
+ {
+ "symbol": "reg"
+ },
+ {
+ "bytes": "cbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb"
+ }
+ ],
+ "data": {
+ "map": [
+ {
+ "key": {
+ "symbol": "status"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "tier"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "video_hash"
+ },
+ "val": {
+ "bytes": "c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "failed_call": false
+ }
+ ]
+}
\ No newline at end of file
diff --git a/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/propose_verifier_set_rejects_non_admin.1.json b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/propose_verifier_set_rejects_non_admin.1.json
new file mode 100644
index 0000000..7c0635a
--- /dev/null
+++ b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/propose_verifier_set_rejects_non_admin.1.json
@@ -0,0 +1,148 @@
+{
+ "generators": {
+ "address": 4,
+ "nonce": 0,
+ "mux_id": 0
+ },
+ "auth": [
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "init",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 25,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "801925984706572462"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ }
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/propose_verifier_set_rejects_threshold_exceeding_member_count.1.json b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/propose_verifier_set_rejects_threshold_exceeding_member_count.1.json
new file mode 100644
index 0000000..c7cf97b
--- /dev/null
+++ b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/propose_verifier_set_rejects_threshold_exceeding_member_count.1.json
@@ -0,0 +1,148 @@
+{
+ "generators": {
+ "address": 3,
+ "nonce": 0,
+ "mux_id": 0
+ },
+ "auth": [
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "init",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 25,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "801925984706572462"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ }
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/propose_verifier_set_rejects_threshold_zero.1.json b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/propose_verifier_set_rejects_threshold_zero.1.json
new file mode 100644
index 0000000..c7cf97b
--- /dev/null
+++ b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/propose_verifier_set_rejects_threshold_zero.1.json
@@ -0,0 +1,148 @@
+{
+ "generators": {
+ "address": 3,
+ "nonce": 0,
+ "mux_id": 0
+ },
+ "auth": [
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "init",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 25,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "801925984706572462"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ }
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/propose_verifier_set_returns_version_1_on_first_call.1.json b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/propose_verifier_set_returns_version_1_on_first_call.1.json
new file mode 100644
index 0000000..935f9e9
--- /dev/null
+++ b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/propose_verifier_set_returns_version_1_on_first_call.1.json
@@ -0,0 +1,379 @@
+{
+ "generators": {
+ "address": 3,
+ "nonce": 0,
+ "mux_id": 0
+ },
+ "auth": [
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "init",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "propose_verifier_set_1",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "string": "v1"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ]
+ ],
+ "ledger": {
+ "protocol_version": 25,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "PendingVerifierSetMember"
+ },
+ {
+ "u32": 0
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "PendingVerifierSetRecord"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "active_from"
+ },
+ "val": {
+ "u64": "300"
+ }
+ },
+ {
+ "key": {
+ "symbol": "circuit_version"
+ },
+ "val": {
+ "string": "v1"
+ }
+ },
+ {
+ "key": {
+ "symbol": "disabled"
+ },
+ "val": {
+ "bool": false
+ }
+ },
+ {
+ "key": {
+ "symbol": "member_count"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "retired_at"
+ },
+ "val": {
+ "u64": "0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "threshold"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "version"
+ },
+ "val": {
+ "u32": 1
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "PendingVerifierSetUnlocksAt"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u64": "300"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "801925984706572462"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "5541220902715666415"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ }
+ ]
+ },
+ "events": [
+ {
+ "event": {
+ "ext": "v0",
+ "contract_id": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "type_": "contract",
+ "body": {
+ "v0": {
+ "topics": [
+ {
+ "symbol": "vset"
+ },
+ {
+ "symbol": "propose"
+ },
+ {
+ "u32": 1
+ }
+ ],
+ "data": {
+ "map": [
+ {
+ "key": {
+ "symbol": "member_count"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "threshold"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "unlocks_at"
+ },
+ "val": {
+ "u64": "300"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "failed_call": false
+ }
+ ]
+}
\ No newline at end of file
diff --git a/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/quorum_approved_with_majority_approving_verifiers.1.json b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/quorum_approved_with_majority_approving_verifiers.1.json
new file mode 100644
index 0000000..3c01cc8
--- /dev/null
+++ b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/quorum_approved_with_majority_approving_verifiers.1.json
@@ -0,0 +1,861 @@
+{
+ "generators": {
+ "address": 5,
+ "nonce": 0,
+ "mux_id": 0
+ },
+ "auth": [
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "init",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ [],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "propose_verifier_set_3",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM"
+ },
+ {
+ "u32": 2
+ },
+ {
+ "string": "ultraHonk-0.87.0"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "activate_verifier_set",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "add_credential_root",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ },
+ {
+ "bytes": "5151515151515151515151515151515151515151515151515151515151515151"
+ },
+ {
+ "bytes": "5454545454545454545454545454545454545454545454545454545454545454"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 25,
+ "sequence_number": 0,
+ "timestamp": 301,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ActiveVerifierSetVersion"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u32": 1
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "CredentialRoot"
+ },
+ {
+ "bytes": "5151515151515151515151515151515151515151515151515151515151515151"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "active"
+ },
+ "val": {
+ "bool": true
+ }
+ },
+ {
+ "key": {
+ "symbol": "issued_at"
+ },
+ "val": {
+ "u64": "301"
+ }
+ },
+ {
+ "key": {
+ "symbol": "metadata_hash"
+ },
+ "val": {
+ "bytes": "5454545454545454545454545454545454545454545454545454545454545454"
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "NextVerifierSetVersion"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u32": 2
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Nullifier"
+ },
+ {
+ "bytes": "5252525252525252525252525252525252525252525252525252525252525252"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "bool": true
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Proof"
+ },
+ {
+ "bytes": "5353535353535353535353535353535353535353535353535353535353535353"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "created_at"
+ },
+ "val": {
+ "u64": "301"
+ }
+ },
+ {
+ "key": {
+ "symbol": "expires_at"
+ },
+ "val": {
+ "u64": "0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "issuer"
+ },
+ "val": "void"
+ },
+ {
+ "key": {
+ "symbol": "metadata_hash"
+ },
+ "val": {
+ "bytes": "5555555555555555555555555555555555555555555555555555555555555555"
+ }
+ },
+ {
+ "key": {
+ "symbol": "nullifier"
+ },
+ "val": {
+ "bytes": "5252525252525252525252525252525252525252525252525252525252525252"
+ }
+ },
+ {
+ "key": {
+ "symbol": "source"
+ },
+ "val": "void"
+ },
+ {
+ "key": {
+ "symbol": "status"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "tier"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "video_hash"
+ },
+ "val": {
+ "bytes": "5050505050505050505050505050505050505050505050505050505050505050"
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetByVersion"
+ },
+ {
+ "u32": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "active_from"
+ },
+ "val": {
+ "u64": "300"
+ }
+ },
+ {
+ "key": {
+ "symbol": "circuit_version"
+ },
+ "val": {
+ "string": "ultraHonk-0.87.0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "disabled"
+ },
+ "val": {
+ "bool": false
+ }
+ },
+ {
+ "key": {
+ "symbol": "member_count"
+ },
+ "val": {
+ "u32": 3
+ }
+ },
+ {
+ "key": {
+ "symbol": "retired_at"
+ },
+ "val": {
+ "u64": "0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "threshold"
+ },
+ "val": {
+ "u32": 2
+ }
+ },
+ {
+ "key": {
+ "symbol": "version"
+ },
+ "val": {
+ "u32": 1
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetMember"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "u32": 0
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetMember"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "u32": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetMember"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "u32": 2
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Video"
+ },
+ {
+ "bytes": "5050505050505050505050505050505050505050505050505050505050505050"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "bytes": "5353535353535353535353535353535353535353535353535353535353535353"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "801925984706572462"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "1033654523790656264"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "4837995959683129791"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "5541220902715666415"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ }
+ ]
+ },
+ "events": [
+ {
+ "event": {
+ "ext": "v0",
+ "contract_id": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "type_": "contract",
+ "body": {
+ "v0": {
+ "topics": [
+ {
+ "symbol": "quorum"
+ },
+ {
+ "symbol": "final"
+ },
+ {
+ "bytes": "5353535353535353535353535353535353535353535353535353535353535353"
+ }
+ ],
+ "data": {
+ "map": [
+ {
+ "key": {
+ "symbol": "approved"
+ },
+ "val": {
+ "u32": 2
+ }
+ },
+ {
+ "key": {
+ "symbol": "failures"
+ },
+ "val": {
+ "u32": 0
+ }
+ },
+ {
+ "key": {
+ "symbol": "rejected"
+ },
+ "val": {
+ "u32": 0
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "failed_call": false
+ },
+ {
+ "event": {
+ "ext": "v0",
+ "contract_id": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "type_": "contract",
+ "body": {
+ "v0": {
+ "topics": [
+ {
+ "symbol": "proof"
+ },
+ {
+ "symbol": "reg"
+ },
+ {
+ "bytes": "5353535353535353535353535353535353535353535353535353535353535353"
+ }
+ ],
+ "data": {
+ "map": [
+ {
+ "key": {
+ "symbol": "status"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "tier"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "video_hash"
+ },
+ "val": {
+ "bytes": "5050505050505050505050505050505050505050505050505050505050505050"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "failed_call": false
+ }
+ ]
+}
\ No newline at end of file
diff --git a/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/quorum_approved_with_single_approving_verifier.1.json b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/quorum_approved_with_single_approving_verifier.1.json
new file mode 100644
index 0000000..d6b12a6
--- /dev/null
+++ b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/quorum_approved_with_single_approving_verifier.1.json
@@ -0,0 +1,645 @@
+{
+ "generators": {
+ "address": 3,
+ "nonce": 0,
+ "mux_id": 0
+ },
+ "auth": [
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "init",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "propose_verifier_set_1",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "string": "ultraHonk-0.87.0"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "activate_verifier_set",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "add_credential_root",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ },
+ {
+ "bytes": "4747474747474747474747474747474747474747474747474747474747474747"
+ },
+ {
+ "bytes": "4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 25,
+ "sequence_number": 0,
+ "timestamp": 301,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ActiveVerifierSetVersion"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u32": 1
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "CredentialRoot"
+ },
+ {
+ "bytes": "4747474747474747474747474747474747474747474747474747474747474747"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "active"
+ },
+ "val": {
+ "bool": true
+ }
+ },
+ {
+ "key": {
+ "symbol": "issued_at"
+ },
+ "val": {
+ "u64": "301"
+ }
+ },
+ {
+ "key": {
+ "symbol": "metadata_hash"
+ },
+ "val": {
+ "bytes": "4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a"
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "NextVerifierSetVersion"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u32": 2
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Nullifier"
+ },
+ {
+ "bytes": "4848484848484848484848484848484848484848484848484848484848484848"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "bool": true
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Proof"
+ },
+ {
+ "bytes": "4949494949494949494949494949494949494949494949494949494949494949"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "created_at"
+ },
+ "val": {
+ "u64": "301"
+ }
+ },
+ {
+ "key": {
+ "symbol": "expires_at"
+ },
+ "val": {
+ "u64": "0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "issuer"
+ },
+ "val": "void"
+ },
+ {
+ "key": {
+ "symbol": "metadata_hash"
+ },
+ "val": {
+ "bytes": "4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b"
+ }
+ },
+ {
+ "key": {
+ "symbol": "nullifier"
+ },
+ "val": {
+ "bytes": "4848484848484848484848484848484848484848484848484848484848484848"
+ }
+ },
+ {
+ "key": {
+ "symbol": "source"
+ },
+ "val": "void"
+ },
+ {
+ "key": {
+ "symbol": "status"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "tier"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "video_hash"
+ },
+ "val": {
+ "bytes": "4646464646464646464646464646464646464646464646464646464646464646"
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetByVersion"
+ },
+ {
+ "u32": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "active_from"
+ },
+ "val": {
+ "u64": "300"
+ }
+ },
+ {
+ "key": {
+ "symbol": "circuit_version"
+ },
+ "val": {
+ "string": "ultraHonk-0.87.0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "disabled"
+ },
+ "val": {
+ "bool": false
+ }
+ },
+ {
+ "key": {
+ "symbol": "member_count"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "retired_at"
+ },
+ "val": {
+ "u64": "0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "threshold"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "version"
+ },
+ "val": {
+ "u32": 1
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetMember"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "u32": 0
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Video"
+ },
+ {
+ "bytes": "4646464646464646464646464646464646464646464646464646464646464646"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "bytes": "4949494949494949494949494949494949494949494949494949494949494949"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "801925984706572462"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "1033654523790656264"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "4837995959683129791"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "5541220902715666415"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ }
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/quorum_panics_when_active_set_is_disabled.1.json b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/quorum_panics_when_active_set_is_disabled.1.json
new file mode 100644
index 0000000..bcf5eeb
--- /dev/null
+++ b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/quorum_panics_when_active_set_is_disabled.1.json
@@ -0,0 +1,536 @@
+{
+ "generators": {
+ "address": 3,
+ "nonce": 0,
+ "mux_id": 0
+ },
+ "auth": [
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "init",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "propose_verifier_set_1",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "string": "ultraHonk-0.87.0"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "activate_verifier_set",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "disable_verifier_set",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ },
+ {
+ "u32": 1
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "add_credential_root",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ },
+ {
+ "bytes": "6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f"
+ },
+ {
+ "bytes": "7272727272727272727272727272727272727272727272727272727272727272"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 25,
+ "sequence_number": 0,
+ "timestamp": 301,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ActiveVerifierSetVersion"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u32": 1
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "CredentialRoot"
+ },
+ {
+ "bytes": "6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "active"
+ },
+ "val": {
+ "bool": true
+ }
+ },
+ {
+ "key": {
+ "symbol": "issued_at"
+ },
+ "val": {
+ "u64": "301"
+ }
+ },
+ {
+ "key": {
+ "symbol": "metadata_hash"
+ },
+ "val": {
+ "bytes": "7272727272727272727272727272727272727272727272727272727272727272"
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "NextVerifierSetVersion"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u32": 2
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetByVersion"
+ },
+ {
+ "u32": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "active_from"
+ },
+ "val": {
+ "u64": "300"
+ }
+ },
+ {
+ "key": {
+ "symbol": "circuit_version"
+ },
+ "val": {
+ "string": "ultraHonk-0.87.0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "disabled"
+ },
+ "val": {
+ "bool": true
+ }
+ },
+ {
+ "key": {
+ "symbol": "member_count"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "retired_at"
+ },
+ "val": {
+ "u64": "0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "threshold"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "version"
+ },
+ "val": {
+ "u32": 1
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetMember"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "u32": 0
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "801925984706572462"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "1033654523790656264"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "2032731177588607455"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "4837995959683129791"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "5541220902715666415"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ }
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/quorum_panics_when_no_active_verifier_set.1.json b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/quorum_panics_when_no_active_verifier_set.1.json
new file mode 100644
index 0000000..69380f9
--- /dev/null
+++ b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/quorum_panics_when_no_active_verifier_set.1.json
@@ -0,0 +1,221 @@
+{
+ "generators": {
+ "address": 2,
+ "nonce": 0,
+ "mux_id": 0
+ },
+ "auth": [
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "init",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "add_credential_root",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ },
+ {
+ "bytes": "7979797979797979797979797979797979797979797979797979797979797979"
+ },
+ {
+ "bytes": "7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 25,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "CredentialRoot"
+ },
+ {
+ "bytes": "7979797979797979797979797979797979797979797979797979797979797979"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "active"
+ },
+ "val": {
+ "bool": true
+ }
+ },
+ {
+ "key": {
+ "symbol": "issued_at"
+ },
+ "val": {
+ "u64": "0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "metadata_hash"
+ },
+ "val": {
+ "bytes": "7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c"
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "801925984706572462"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "5541220902715666415"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ }
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/quorum_rejected_when_all_verifiers_reject.1.json b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/quorum_rejected_when_all_verifiers_reject.1.json
new file mode 100644
index 0000000..6fcb96f
--- /dev/null
+++ b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/quorum_rejected_when_all_verifiers_reject.1.json
@@ -0,0 +1,546 @@
+{
+ "generators": {
+ "address": 3,
+ "nonce": 0,
+ "mux_id": 0
+ },
+ "auth": [
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "init",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "propose_verifier_set_1",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "string": "ultraHonk-0.87.0"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "activate_verifier_set",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "add_credential_root",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ },
+ {
+ "bytes": "5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b"
+ },
+ {
+ "bytes": "5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 25,
+ "sequence_number": 0,
+ "timestamp": 301,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ActiveVerifierSetVersion"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u32": 1
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "CredentialRoot"
+ },
+ {
+ "bytes": "5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "active"
+ },
+ "val": {
+ "bool": true
+ }
+ },
+ {
+ "key": {
+ "symbol": "issued_at"
+ },
+ "val": {
+ "u64": "301"
+ }
+ },
+ {
+ "key": {
+ "symbol": "metadata_hash"
+ },
+ "val": {
+ "bytes": "5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e"
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "NextVerifierSetVersion"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u32": 2
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetByVersion"
+ },
+ {
+ "u32": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "active_from"
+ },
+ "val": {
+ "u64": "300"
+ }
+ },
+ {
+ "key": {
+ "symbol": "circuit_version"
+ },
+ "val": {
+ "string": "ultraHonk-0.87.0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "disabled"
+ },
+ "val": {
+ "bool": false
+ }
+ },
+ {
+ "key": {
+ "symbol": "member_count"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "retired_at"
+ },
+ "val": {
+ "u64": "0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "threshold"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "version"
+ },
+ "val": {
+ "u32": 1
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetMember"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "u32": 0
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "801925984706572462"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "1033654523790656264"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "4837995959683129791"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "5541220902715666415"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ }
+ ]
+ },
+ "events": [
+ {
+ "event": {
+ "ext": "v0",
+ "contract_id": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "type_": "contract",
+ "body": {
+ "v0": {
+ "topics": [
+ {
+ "symbol": "quorum"
+ },
+ {
+ "symbol": "final"
+ },
+ {
+ "bytes": "5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d"
+ }
+ ],
+ "data": {
+ "map": [
+ {
+ "key": {
+ "symbol": "approved"
+ },
+ "val": {
+ "u32": 0
+ }
+ },
+ {
+ "key": {
+ "symbol": "failures"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "rejected"
+ },
+ "val": {
+ "u32": 0
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "failed_call": true
+ }
+ ]
+}
\ No newline at end of file
diff --git a/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/quorum_rejected_when_majority_rejects.1.json b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/quorum_rejected_when_majority_rejects.1.json
new file mode 100644
index 0000000..e9e8693
--- /dev/null
+++ b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/quorum_rejected_when_majority_rejects.1.json
@@ -0,0 +1,660 @@
+{
+ "generators": {
+ "address": 5,
+ "nonce": 0,
+ "mux_id": 0
+ },
+ "auth": [
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "init",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ [],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "propose_verifier_set_3",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM"
+ },
+ {
+ "u32": 2
+ },
+ {
+ "string": "ultraHonk-0.87.0"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "activate_verifier_set",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "add_credential_root",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ },
+ {
+ "bytes": "6565656565656565656565656565656565656565656565656565656565656565"
+ },
+ {
+ "bytes": "6868686868686868686868686868686868686868686868686868686868686868"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 25,
+ "sequence_number": 0,
+ "timestamp": 301,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ActiveVerifierSetVersion"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u32": 1
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "CredentialRoot"
+ },
+ {
+ "bytes": "6565656565656565656565656565656565656565656565656565656565656565"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "active"
+ },
+ "val": {
+ "bool": true
+ }
+ },
+ {
+ "key": {
+ "symbol": "issued_at"
+ },
+ "val": {
+ "u64": "301"
+ }
+ },
+ {
+ "key": {
+ "symbol": "metadata_hash"
+ },
+ "val": {
+ "bytes": "6868686868686868686868686868686868686868686868686868686868686868"
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "NextVerifierSetVersion"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u32": 2
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetByVersion"
+ },
+ {
+ "u32": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "active_from"
+ },
+ "val": {
+ "u64": "300"
+ }
+ },
+ {
+ "key": {
+ "symbol": "circuit_version"
+ },
+ "val": {
+ "string": "ultraHonk-0.87.0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "disabled"
+ },
+ "val": {
+ "bool": false
+ }
+ },
+ {
+ "key": {
+ "symbol": "member_count"
+ },
+ "val": {
+ "u32": 3
+ }
+ },
+ {
+ "key": {
+ "symbol": "retired_at"
+ },
+ "val": {
+ "u64": "0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "threshold"
+ },
+ "val": {
+ "u32": 2
+ }
+ },
+ {
+ "key": {
+ "symbol": "version"
+ },
+ "val": {
+ "u32": 1
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetMember"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "u32": 0
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetMember"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "u32": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetMember"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "u32": 2
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "801925984706572462"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "1033654523790656264"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "4837995959683129791"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "5541220902715666415"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ }
+ ]
+ },
+ "events": [
+ {
+ "event": {
+ "ext": "v0",
+ "contract_id": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "type_": "contract",
+ "body": {
+ "v0": {
+ "topics": [
+ {
+ "symbol": "quorum"
+ },
+ {
+ "symbol": "final"
+ },
+ {
+ "bytes": "6767676767676767676767676767676767676767676767676767676767676767"
+ }
+ ],
+ "data": {
+ "map": [
+ {
+ "key": {
+ "symbol": "approved"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "failures"
+ },
+ "val": {
+ "u32": 2
+ }
+ },
+ {
+ "key": {
+ "symbol": "rejected"
+ },
+ "val": {
+ "u32": 0
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "failed_call": true
+ }
+ ]
+}
\ No newline at end of file
diff --git a/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/quorum_rejects_duplicate_nullifier.1.json b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/quorum_rejects_duplicate_nullifier.1.json
new file mode 100644
index 0000000..785f12d
--- /dev/null
+++ b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/quorum_rejects_duplicate_nullifier.1.json
@@ -0,0 +1,645 @@
+{
+ "generators": {
+ "address": 3,
+ "nonce": 0,
+ "mux_id": 0
+ },
+ "auth": [
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "init",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "propose_verifier_set_1",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "string": "ultraHonk-0.87.0"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "activate_verifier_set",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "add_credential_root",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ },
+ {
+ "bytes": "8383838383838383838383838383838383838383838383838383838383838383"
+ },
+ {
+ "bytes": "8888888888888888888888888888888888888888888888888888888888888888"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 25,
+ "sequence_number": 0,
+ "timestamp": 301,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ActiveVerifierSetVersion"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u32": 1
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "CredentialRoot"
+ },
+ {
+ "bytes": "8383838383838383838383838383838383838383838383838383838383838383"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "active"
+ },
+ "val": {
+ "bool": true
+ }
+ },
+ {
+ "key": {
+ "symbol": "issued_at"
+ },
+ "val": {
+ "u64": "301"
+ }
+ },
+ {
+ "key": {
+ "symbol": "metadata_hash"
+ },
+ "val": {
+ "bytes": "8888888888888888888888888888888888888888888888888888888888888888"
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "NextVerifierSetVersion"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u32": 2
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Nullifier"
+ },
+ {
+ "bytes": "8484848484848484848484848484848484848484848484848484848484848484"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "bool": true
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Proof"
+ },
+ {
+ "bytes": "8585858585858585858585858585858585858585858585858585858585858585"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "created_at"
+ },
+ "val": {
+ "u64": "301"
+ }
+ },
+ {
+ "key": {
+ "symbol": "expires_at"
+ },
+ "val": {
+ "u64": "0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "issuer"
+ },
+ "val": "void"
+ },
+ {
+ "key": {
+ "symbol": "metadata_hash"
+ },
+ "val": {
+ "bytes": "8989898989898989898989898989898989898989898989898989898989898989"
+ }
+ },
+ {
+ "key": {
+ "symbol": "nullifier"
+ },
+ "val": {
+ "bytes": "8484848484848484848484848484848484848484848484848484848484848484"
+ }
+ },
+ {
+ "key": {
+ "symbol": "source"
+ },
+ "val": "void"
+ },
+ {
+ "key": {
+ "symbol": "status"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "tier"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "video_hash"
+ },
+ "val": {
+ "bytes": "8282828282828282828282828282828282828282828282828282828282828282"
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetByVersion"
+ },
+ {
+ "u32": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "active_from"
+ },
+ "val": {
+ "u64": "300"
+ }
+ },
+ {
+ "key": {
+ "symbol": "circuit_version"
+ },
+ "val": {
+ "string": "ultraHonk-0.87.0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "disabled"
+ },
+ "val": {
+ "bool": false
+ }
+ },
+ {
+ "key": {
+ "symbol": "member_count"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "retired_at"
+ },
+ "val": {
+ "u64": "0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "threshold"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "version"
+ },
+ "val": {
+ "u32": 1
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetMember"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "u32": 0
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Video"
+ },
+ {
+ "bytes": "8282828282828282828282828282828282828282828282828282828282828282"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "bytes": "8585858585858585858585858585858585858585858585858585858585858585"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "801925984706572462"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "1033654523790656264"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "4837995959683129791"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "5541220902715666415"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ }
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/quorum_rejects_duplicate_proof_id.1.json b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/quorum_rejects_duplicate_proof_id.1.json
new file mode 100644
index 0000000..8509a78
--- /dev/null
+++ b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/quorum_rejects_duplicate_proof_id.1.json
@@ -0,0 +1,645 @@
+{
+ "generators": {
+ "address": 3,
+ "nonce": 0,
+ "mux_id": 0
+ },
+ "auth": [
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "init",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "propose_verifier_set_1",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "string": "ultraHonk-0.87.0"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "activate_verifier_set",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "add_credential_root",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ },
+ {
+ "bytes": "8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d"
+ },
+ {
+ "bytes": "9292929292929292929292929292929292929292929292929292929292929292"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 25,
+ "sequence_number": 0,
+ "timestamp": 301,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ActiveVerifierSetVersion"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u32": 1
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "CredentialRoot"
+ },
+ {
+ "bytes": "8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "active"
+ },
+ "val": {
+ "bool": true
+ }
+ },
+ {
+ "key": {
+ "symbol": "issued_at"
+ },
+ "val": {
+ "u64": "301"
+ }
+ },
+ {
+ "key": {
+ "symbol": "metadata_hash"
+ },
+ "val": {
+ "bytes": "9292929292929292929292929292929292929292929292929292929292929292"
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "NextVerifierSetVersion"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u32": 2
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Nullifier"
+ },
+ {
+ "bytes": "8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "bool": true
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Proof"
+ },
+ {
+ "bytes": "9090909090909090909090909090909090909090909090909090909090909090"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "created_at"
+ },
+ "val": {
+ "u64": "301"
+ }
+ },
+ {
+ "key": {
+ "symbol": "expires_at"
+ },
+ "val": {
+ "u64": "0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "issuer"
+ },
+ "val": "void"
+ },
+ {
+ "key": {
+ "symbol": "metadata_hash"
+ },
+ "val": {
+ "bytes": "9393939393939393939393939393939393939393939393939393939393939393"
+ }
+ },
+ {
+ "key": {
+ "symbol": "nullifier"
+ },
+ "val": {
+ "bytes": "8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e"
+ }
+ },
+ {
+ "key": {
+ "symbol": "source"
+ },
+ "val": "void"
+ },
+ {
+ "key": {
+ "symbol": "status"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "tier"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "video_hash"
+ },
+ "val": {
+ "bytes": "8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c"
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetByVersion"
+ },
+ {
+ "u32": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "active_from"
+ },
+ "val": {
+ "u64": "300"
+ }
+ },
+ {
+ "key": {
+ "symbol": "circuit_version"
+ },
+ "val": {
+ "string": "ultraHonk-0.87.0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "disabled"
+ },
+ "val": {
+ "bool": false
+ }
+ },
+ {
+ "key": {
+ "symbol": "member_count"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "retired_at"
+ },
+ "val": {
+ "u64": "0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "threshold"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "version"
+ },
+ "val": {
+ "u32": 1
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetMember"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "u32": 0
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Video"
+ },
+ {
+ "bytes": "8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "bytes": "9090909090909090909090909090909090909090909090909090909090909090"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "801925984706572462"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "1033654523790656264"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "4837995959683129791"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "5541220902715666415"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ }
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/quorum_rejects_oversized_proof.1.json b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/quorum_rejects_oversized_proof.1.json
new file mode 100644
index 0000000..6fe389a
--- /dev/null
+++ b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/quorum_rejects_oversized_proof.1.json
@@ -0,0 +1,494 @@
+{
+ "generators": {
+ "address": 3,
+ "nonce": 0,
+ "mux_id": 0
+ },
+ "auth": [
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "init",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "propose_verifier_set_1",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "string": "ultraHonk-0.87.0"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "activate_verifier_set",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "add_credential_root",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ },
+ {
+ "bytes": "9797979797979797979797979797979797979797979797979797979797979797"
+ },
+ {
+ "bytes": "9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 25,
+ "sequence_number": 0,
+ "timestamp": 301,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ActiveVerifierSetVersion"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u32": 1
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "CredentialRoot"
+ },
+ {
+ "bytes": "9797979797979797979797979797979797979797979797979797979797979797"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "active"
+ },
+ "val": {
+ "bool": true
+ }
+ },
+ {
+ "key": {
+ "symbol": "issued_at"
+ },
+ "val": {
+ "u64": "301"
+ }
+ },
+ {
+ "key": {
+ "symbol": "metadata_hash"
+ },
+ "val": {
+ "bytes": "9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a"
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "NextVerifierSetVersion"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u32": 2
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetByVersion"
+ },
+ {
+ "u32": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "active_from"
+ },
+ "val": {
+ "u64": "300"
+ }
+ },
+ {
+ "key": {
+ "symbol": "circuit_version"
+ },
+ "val": {
+ "string": "ultraHonk-0.87.0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "disabled"
+ },
+ "val": {
+ "bool": false
+ }
+ },
+ {
+ "key": {
+ "symbol": "member_count"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "retired_at"
+ },
+ "val": {
+ "u64": "0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "threshold"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "version"
+ },
+ "val": {
+ "u32": 1
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetMember"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "u32": 0
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "801925984706572462"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "1033654523790656264"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "4837995959683129791"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "5541220902715666415"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ }
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/rotation_overlap_v1_retired_when_v2_activates.1.json b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/rotation_overlap_v1_retired_when_v2_activates.1.json
new file mode 100644
index 0000000..dfd3073
--- /dev/null
+++ b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/rotation_overlap_v1_retired_when_v2_activates.1.json
@@ -0,0 +1,624 @@
+{
+ "generators": {
+ "address": 4,
+ "nonce": 0,
+ "mux_id": 0
+ },
+ "auth": [
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "init",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "propose_verifier_set_1",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "string": "circuit-v1"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "activate_verifier_set",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "propose_verifier_set_1",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "string": "circuit-v2"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "activate_verifier_set",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 25,
+ "sequence_number": 0,
+ "timestamp": 602,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ActiveVerifierSetVersion"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u32": 2
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "NextVerifierSetVersion"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u32": 3
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetByVersion"
+ },
+ {
+ "u32": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "active_from"
+ },
+ "val": {
+ "u64": "300"
+ }
+ },
+ {
+ "key": {
+ "symbol": "circuit_version"
+ },
+ "val": {
+ "string": "circuit-v1"
+ }
+ },
+ {
+ "key": {
+ "symbol": "disabled"
+ },
+ "val": {
+ "bool": false
+ }
+ },
+ {
+ "key": {
+ "symbol": "member_count"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "retired_at"
+ },
+ "val": {
+ "u64": "602"
+ }
+ },
+ {
+ "key": {
+ "symbol": "threshold"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "version"
+ },
+ "val": {
+ "u32": 1
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetByVersion"
+ },
+ {
+ "u32": 2
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "active_from"
+ },
+ "val": {
+ "u64": "601"
+ }
+ },
+ {
+ "key": {
+ "symbol": "circuit_version"
+ },
+ "val": {
+ "string": "circuit-v2"
+ }
+ },
+ {
+ "key": {
+ "symbol": "disabled"
+ },
+ "val": {
+ "bool": false
+ }
+ },
+ {
+ "key": {
+ "symbol": "member_count"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "retired_at"
+ },
+ "val": {
+ "u64": "0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "threshold"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "version"
+ },
+ "val": {
+ "u32": 2
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetMember"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "u32": 0
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetMember"
+ },
+ {
+ "u32": 2
+ },
+ {
+ "u32": 0
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "801925984706572462"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "1033654523790656264"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "2032731177588607455"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "4837995959683129791"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "5541220902715666415"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ }
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/version_mismatch_not_triggered_by_contract_panics.1.json b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/version_mismatch_not_triggered_by_contract_panics.1.json
new file mode 100644
index 0000000..73728e2
--- /dev/null
+++ b/contracts/contracts/harpocrates-registry/test_snapshots/test_verifier_sets/version_mismatch_not_triggered_by_contract_panics.1.json
@@ -0,0 +1,546 @@
+{
+ "generators": {
+ "address": 3,
+ "nonce": 0,
+ "mux_id": 0
+ },
+ "auth": [
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "init",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "propose_verifier_set_1",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "string": "ultraHonk-0.87.0"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "activate_verifier_set",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "function_name": "add_credential_root",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ },
+ {
+ "bytes": "a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1"
+ },
+ {
+ "bytes": "a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 25,
+ "sequence_number": 0,
+ "timestamp": 301,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ActiveVerifierSetVersion"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u32": 1
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "CredentialRoot"
+ },
+ {
+ "bytes": "a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "active"
+ },
+ "val": {
+ "bool": true
+ }
+ },
+ {
+ "key": {
+ "symbol": "issued_at"
+ },
+ "val": {
+ "u64": "301"
+ }
+ },
+ {
+ "key": {
+ "symbol": "metadata_hash"
+ },
+ "val": {
+ "bytes": "a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4"
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "NextVerifierSetVersion"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u32": 2
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetByVersion"
+ },
+ {
+ "u32": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "active_from"
+ },
+ "val": {
+ "u64": "300"
+ }
+ },
+ {
+ "key": {
+ "symbol": "circuit_version"
+ },
+ "val": {
+ "string": "ultraHonk-0.87.0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "disabled"
+ },
+ "val": {
+ "bool": false
+ }
+ },
+ {
+ "key": {
+ "symbol": "member_count"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "retired_at"
+ },
+ "val": {
+ "u64": "0"
+ }
+ },
+ {
+ "key": {
+ "symbol": "threshold"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "version"
+ },
+ "val": {
+ "u32": 1
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "vec": [
+ {
+ "symbol": "VerifierSetMember"
+ },
+ {
+ "u32": 1
+ },
+ {
+ "u32": 0
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "801925984706572462"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "1033654523790656264"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "4837995959683129791"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": "5541220902715666415"
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 6311999
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent",
+ "val": {
+ "contract_instance": {
+ "executable": {
+ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ "storage": null
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ },
+ {
+ "entry": {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ "live_until": 4095
+ }
+ ]
+ },
+ "events": [
+ {
+ "event": {
+ "ext": "v0",
+ "contract_id": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "type_": "contract",
+ "body": {
+ "v0": {
+ "topics": [
+ {
+ "symbol": "quorum"
+ },
+ {
+ "symbol": "final"
+ },
+ {
+ "bytes": "a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3"
+ }
+ ],
+ "data": {
+ "map": [
+ {
+ "key": {
+ "symbol": "approved"
+ },
+ "val": {
+ "u32": 0
+ }
+ },
+ {
+ "key": {
+ "symbol": "failures"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "rejected"
+ },
+ "val": {
+ "u32": 0
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "failed_call": true
+ }
+ ]
+}
\ No newline at end of file
diff --git a/frontend/src/harpocratesRegistry.ts b/frontend/src/harpocratesRegistry.ts
index 19212bd..7a8bd32 100644
--- a/frontend/src/harpocratesRegistry.ts
+++ b/frontend/src/harpocratesRegistry.ts
@@ -1,4 +1,12 @@
-import { Address, BASE_FEE, Contract, Networks, TransactionBuilder, scValToNative } from '@stellar/stellar-sdk'
+import {
+ Address,
+ BASE_FEE,
+ Contract,
+ nativeToScVal,
+ Networks,
+ TransactionBuilder,
+ scValToNative,
+} from '@stellar/stellar-sdk'
import { rpc } from '@stellar/stellar-sdk'
import { signTransaction } from '@stellar/freighter-api'
import { asHex32, asHexBytes, bytesToHex, scBytes, scBytes32 } from './stellarEncoding'
@@ -23,12 +31,21 @@ export const CONTRACT_NETWORK_PASSPHRASE: string = Networks.TESTNET
const NETWORK_PASSPHRASE = CONTRACT_NETWORK_PASSPHRASE
const READONLY_SOURCE = import.meta.env.VITE_STELLAR_READONLY_SOURCE ?? ''
+// ---------------------------------------------------------------------------
+// Proof registration (existing + quorum path)
+// ---------------------------------------------------------------------------
+
+/**
+ * Register a proof on Stellar using the standard single-verifier path or
+ * the new quorum-based path (when `useQuorum` is set in the input).
+ */
export async function registerProofOnStellar(input: RegisterProofInput): Promise {
const normalized = normalizeRegisterProofInput(input)
const server = new rpc.Server(RPC_URL)
const account = await server.getAccount(normalized.publicKey)
const contract = new Contract(normalized.contractId)
- const operation = contract.call(methodForTier(normalized.tier), ...argsForTier(normalized))
+ const method = methodForTier(normalized.tier, normalized.useQuorum)
+ const operation = contract.call(method, ...argsForTier(normalized))
const transaction = new TransactionBuilder(account, {
fee: BASE_FEE,
@@ -61,6 +78,10 @@ export async function registerProofOnStellar(input: RegisterProofInput): Promise
}
}
+// ---------------------------------------------------------------------------
+// Proof lookup
+// ---------------------------------------------------------------------------
+
export async function getProofByVideoHash(
contractId: string,
videoHash: string,
@@ -104,6 +125,198 @@ export async function getProofByVideoHash(
}
}
+// ---------------------------------------------------------------------------
+// Verifier-set admin helpers (#126)
+//
+// These are admin-only operations used by governance tooling.
+// They require a connected wallet (Freighter) with the admin key.
+// ---------------------------------------------------------------------------
+
+export interface VerifierSetProposalInput {
+ contractId: string
+ adminPublicKey: string
+ /** Up to 3 verifier contract addresses (for propose_verifier_set_1/2/3). */
+ members: string[]
+ threshold: number
+ circuitVersion: string
+}
+
+export interface VerifierSetResult {
+ version: number
+ memberCount: number
+ threshold: number
+ activeFrom: string
+ retiredAt: string
+ disabled: boolean
+ circuitVersion: string
+}
+
+/**
+ * Propose a new verifier set with 1–3 members (uses propose_verifier_set_1/2/3).
+ * Returns the proposed version number (activated after timelock expires).
+ */
+export async function proposeVerifierSet(input: VerifierSetProposalInput): Promise {
+ if (input.members.length < 1 || input.members.length > 3) {
+ throw new Error('proposeVerifierSet supports 1–3 members. Use the contract CLI for larger sets.')
+ }
+ if (input.threshold < 1 || input.threshold > input.members.length) {
+ throw new Error(`threshold must be between 1 and ${input.members.length}`)
+ }
+
+ const server = new rpc.Server(RPC_URL)
+ const account = await server.getAccount(input.adminPublicKey)
+ const contract = new Contract(input.contractId)
+
+ const adminScVal = new Address(input.adminPublicKey).toScVal()
+ const thresholdScVal = nativeToScVal(input.threshold, { type: 'u32' })
+ const circuitVersionScVal = nativeToScVal(input.circuitVersion, { type: 'string' })
+ const memberScVals = input.members.map(m => new Address(m).toScVal())
+
+ const methodName = (`propose_verifier_set_${input.members.length}`) as RegistryMethod
+ const args = [adminScVal, ...memberScVals, thresholdScVal, circuitVersionScVal]
+
+ const operation = contract.call(methodName, ...args)
+ const transaction = new TransactionBuilder(account, {
+ fee: BASE_FEE,
+ networkPassphrase: NETWORK_PASSPHRASE,
+ })
+ .addOperation(operation)
+ .setTimeout(90)
+ .build()
+
+ const prepared = await server.prepareTransaction(transaction)
+ const signed = await signTransaction(prepared.toXDR(), {
+ networkPassphrase: NETWORK_PASSPHRASE,
+ address: input.adminPublicKey,
+ })
+ if (signed.error) throw new Error(signed.error.message)
+
+ const signedTransaction = TransactionBuilder.fromXDR(signed.signedTxXdr, NETWORK_PASSPHRASE)
+ const submitted = await server.sendTransaction(signedTransaction)
+ if ('errorResultXdr' in submitted && submitted.errorResultXdr) {
+ throw new Error(`Stellar RPC rejected the transaction: ${submitted.errorResultXdr}`)
+ }
+ return { hash: submitted.hash, status: submitted.status }
+}
+
+/**
+ * Activate the pending verifier set (timelock must have expired).
+ */
+export async function activateVerifierSet(contractId: string, adminPublicKey: string): Promise {
+ const server = new rpc.Server(RPC_URL)
+ const account = await server.getAccount(adminPublicKey)
+ const contract = new Contract(contractId)
+
+ const operation = contract.call(
+ 'activate_verifier_set' satisfies RegistryMethod,
+ new Address(adminPublicKey).toScVal(),
+ )
+ const transaction = new TransactionBuilder(account, {
+ fee: BASE_FEE,
+ networkPassphrase: NETWORK_PASSPHRASE,
+ })
+ .addOperation(operation)
+ .setTimeout(90)
+ .build()
+
+ const prepared = await server.prepareTransaction(transaction)
+ const signed = await signTransaction(prepared.toXDR(), {
+ networkPassphrase: NETWORK_PASSPHRASE,
+ address: adminPublicKey,
+ })
+ if (signed.error) throw new Error(signed.error.message)
+
+ const signedTransaction = TransactionBuilder.fromXDR(signed.signedTxXdr, NETWORK_PASSPHRASE)
+ const submitted = await server.sendTransaction(signedTransaction)
+ if ('errorResultXdr' in submitted && submitted.errorResultXdr) {
+ throw new Error(`Stellar RPC rejected the transaction: ${submitted.errorResultXdr}`)
+ }
+ return { hash: submitted.hash, status: submitted.status }
+}
+
+/**
+ * Emergency-disable a verifier set version.
+ */
+export async function disableVerifierSet(
+ contractId: string,
+ adminPublicKey: string,
+ version: number,
+): Promise {
+ const server = new rpc.Server(RPC_URL)
+ const account = await server.getAccount(adminPublicKey)
+ const contract = new Contract(contractId)
+
+ const operation = contract.call(
+ 'disable_verifier_set' satisfies RegistryMethod,
+ new Address(adminPublicKey).toScVal(),
+ nativeToScVal(version, { type: 'u32' }),
+ )
+ const transaction = new TransactionBuilder(account, {
+ fee: BASE_FEE,
+ networkPassphrase: NETWORK_PASSPHRASE,
+ })
+ .addOperation(operation)
+ .setTimeout(90)
+ .build()
+
+ const prepared = await server.prepareTransaction(transaction)
+ const signed = await signTransaction(prepared.toXDR(), {
+ networkPassphrase: NETWORK_PASSPHRASE,
+ address: adminPublicKey,
+ })
+ if (signed.error) throw new Error(signed.error.message)
+
+ const signedTransaction = TransactionBuilder.fromXDR(signed.signedTxXdr, NETWORK_PASSPHRASE)
+ const submitted = await server.sendTransaction(signedTransaction)
+ if ('errorResultXdr' in submitted && submitted.errorResultXdr) {
+ throw new Error(`Stellar RPC rejected the transaction: ${submitted.errorResultXdr}`)
+ }
+ return { hash: submitted.hash, status: submitted.status }
+}
+
+/**
+ * Read the currently active verifier set (simulation, no signature required).
+ */
+export async function getActiveVerifierSet(
+ contractId: string,
+ sourceAddress?: string,
+): Promise {
+ const source = sourceAddress || READONLY_SOURCE
+ if (!source) throw new Error('Set VITE_STELLAR_READONLY_SOURCE for read-only calls.')
+
+ const server = new rpc.Server(RPC_URL)
+ const account = await server.getAccount(source)
+ const contract = new Contract(contractId)
+ const transaction = new TransactionBuilder(account, {
+ fee: BASE_FEE,
+ networkPassphrase: NETWORK_PASSPHRASE,
+ })
+ .addOperation(contract.call('get_active_verifier_set' satisfies RegistryMethod))
+ .setTimeout(30)
+ .build()
+
+ const simulation = await server.simulateTransaction(transaction)
+ if (rpc.Api.isSimulationError(simulation)) throw new Error(simulation.error)
+ if (!rpc.Api.isSimulationSuccess(simulation) && !rpc.Api.isSimulationRestore(simulation)) return null
+
+ const native = simulation.result?.retval ? scValToNative(simulation.result.retval) : null
+ if (!native) return null
+
+ return {
+ version: Number(native.version),
+ memberCount: Number(native.member_count),
+ threshold: Number(native.threshold),
+ activeFrom: native.active_from?.toString?.() ?? String(native.active_from),
+ retiredAt: native.retired_at?.toString?.() ?? String(native.retired_at),
+ disabled: Boolean(native.disabled),
+ circuitVersion: String(native.circuit_version ?? ''),
+ }
+}
+
+// ---------------------------------------------------------------------------
+// Internal helpers
+// ---------------------------------------------------------------------------
+
function normalizeRegisterProofInput(input: RegisterProofInput): NormalizedRegisterProofInput {
return {
...input,
@@ -119,8 +332,18 @@ function normalizeRegisterProofInput(input: RegisterProofInput): NormalizedRegis
}
}
-function methodForTier(tier: IdentityTier): RegistryMethod {
- if (tier === 'silent') return 'register_anonymous_verified'
+/**
+ * Select the contract method based on identity tier and quorum preference.
+ *
+ * - `silent` tier with `useQuorum=true` → `register_anon_verified_quorum`
+ * - `silent` tier with `useQuorum=false` → `register_anonymous_verified` (legacy)
+ * - `seal` → `register_seal`
+ * - `source` → `register_source`
+ */
+function methodForTier(tier: IdentityTier, useQuorum?: boolean): RegistryMethod {
+ if (tier === 'silent') {
+ return useQuorum ? 'register_anon_verified_quorum' : 'register_anonymous_verified'
+ }
if (tier === 'seal') return 'register_seal'
return 'register_source'
}
@@ -135,7 +358,6 @@ function argsForTier(input: NormalizedRegisterProofInput) {
if (!input.silentWitness) {
throw new Error('Silent Witness registration requires Noir proof artifacts.')
}
-
return [
videoHash,
metadataHash,
diff --git a/frontend/src/stellarTypes.ts b/frontend/src/stellarTypes.ts
index d4c967b..eb63f1b 100644
--- a/frontend/src/stellarTypes.ts
+++ b/frontend/src/stellarTypes.ts
@@ -19,6 +19,8 @@ export type RegisterProofInput = {
publicInputs: string
proof: string
}
+ /** When true, routes silent-witness proofs through the quorum verifier set (#126). */
+ useQuorum?: boolean
}
export type NormalizedRegisterProofInput = {
@@ -29,6 +31,7 @@ export type NormalizedRegisterProofInput = {
metadataHash: Hex32
proofId: Hex32
silentWitness?: SilentWitnessArtifacts
+ useQuorum?: boolean
}
export type RegisterProofResult = {
@@ -48,6 +51,15 @@ export type ChainProofRecord = {
export type RegistryMethod =
| 'register_anonymous_verified'
+ | 'register_anon_verified_quorum'
| 'register_source'
| 'register_seal'
| 'get_by_video'
+ | 'propose_verifier_set_1'
+ | 'propose_verifier_set_2'
+ | 'propose_verifier_set_3'
+ | 'activate_verifier_set'
+ | 'disable_verifier_set'
+ | 'get_active_verifier_set'
+ | 'get_verifier_set'
+ | 'get_verifier_set_member'