This document summarizes the implementation of four credential management tasks.
The batch_issue_credentials function enables issuing credentials to multiple subjects in a single transaction.
Function Signature:
pub fn batch_issue_credentials(
env: Env,
issuer: Address,
subjects: Vec<Address>,
credential_types: Vec<u32>,
metadata_hashes: Vec<soroban_sdk::Bytes>,
expires_at: Option<u64>,
) -> Vec<u64>Features:
- Returns vector of credential IDs in exact order as input subjects
- Sequential ID assignment via monotonic increment from CredentialCount
- Atomic issuance with rollback on validation failure
- Supports batch up to MAX_BATCH_SIZE (50 credentials)
- Proper duplicate detection and blacklist checking per subject
- Event emission for each credential
Implements expiry management for professional certifications requiring renewal.
New Functions:
pub fn is_credential_expired(env: Env, credential_id: u64) -> boolReturns true if credential has passed its expires_at timestamp.
Existing Functions Used:
renew_credential(env, issuer, credential_id, new_expires_at)- issuer-only renewalexpires_at: Option<u64>field in Credential struct
Features:
- Optional expiry timestamps (None = permanent)
- Renewal extends expiry allowing continuous certification
- Works with check_credential_validity for full validity checking
- Supports grace periods and expiry notifications
Implements reversible suspension with audit trail, distinct from permanent revocation.
Updated Function:
pub fn suspend_credential(
env: Env,
issuer: Address,
credential_id: u64,
reason: Option<soroban_sdk::Bytes>,
)Features:
- Accepts optional suspension reason for audit trail
- Reversible via existing
resume_credentialfunction - Stores reason in DataKey::SuspensionReason
- Emits SuspensionEventData with timestamp
- Status field uses CredentialStatus enum (Active, ExpiringSoon, Expired)
- Invalidates verification caches on suspension state changes
- Issuer-only suspension capability
Complementary Functions:
resume_credential- reverses suspension, restores Active status
Allows correcting incorrect credential data while maintaining audit trail.
New Functions:
pub fn amend_credential(
env: Env,
issuer: Address,
credential_id: u64,
new_metadata_hash: soroban_sdk::Bytes,
)
pub fn get_amendment_history(env: Env, credential_id: u64) -> Vec<AmendmentEntry>Data Structures:
#[contracttype]
pub struct AmendmentEntry {
pub credential_id: u64,
pub amendment_id: u64,
pub previous_metadata_hash: soroban_sdk::Bytes,
pub new_metadata_hash: soroban_sdk::Bytes,
pub amended_by: Address,
pub amended_at: u64,
}Features:
- Corrects incorrect credential data (e.g., wrong graduation date)
- Preserves credential continuity (no revocation/re-issuance needed)
- Maintains complete amendment history with timestamps
- Records amendment ID, previous/new hashes, and amender
- Emits AmendmentEventData event for on-chain auditability
- Versioning incremented on each amendment
- Issuer-only amendment capability
- Cannot amend revoked credentials
Storage:
- AmendmentHistory(credential_id) -> Vec
- SuspensionReason(credential_id) -> Option
- AmendmentCount (global counter)
All functions follow the contract's authorization model:
- Issuer-only operations require
issuer.require_auth() - All state changes extend TTL with STANDARD_TTL and EXTENDED_TTL
- Events published for all state-changing operations
- Verification caches invalidated on state changes
- Post-conditions verified where applicable
New event topics added:
TOPIC_SUSPENSION = "CredentialSuspended"TOPIC_AMENDMENT = "CredentialAmended"
- Batch Issuance: Verify order preservation, sequential ID assignment, atomic failure
- Expiry: Test grace periods, renewal after expiry, multiple renewals
- Suspension: Test reversibility, reason tracking, authorization, cache invalidation
- Amendment: Test history tracking, non-revocation constraint, version increment
The amendment feature allows issuers to correct incorrect credential data while maintaining credential continuity and preserving a complete audit trail.
- Before: Credentials with errors required revocation + re-issuance (loses history)
- After: Amendments correct data in-place (preserves ID + adds audit trail)
- Issuer calls amend_credential with credential_id and new_metadata_hash
- System validates issuer authorization and credential not revoked
- New amendment ID assigned from global AmendmentCount counter
- AmendmentEntry created with: previous_hash, new_hash, amender, timestamp
- Amendment stored in AmendmentHistory vector for that credential
- Credential metadata_hash updated and version incremented
- Verification caches invalidated for re-validation
- AmendmentEventData published to event log
- Metadata audit log updated via record_metadata_audit
pub fn get_amendment_history(env: Env, credential_id: u64) -> Vec<AmendmentEntry>Returns complete amendment history with:
- amendment_id: Unique sequential ID for this amendment
- previous_metadata_hash: Hash before this amendment
- new_metadata_hash: Hash after this amendment
- amended_by: Address of issuer who made the amendment
- amended_at: Ledger timestamp of amendment
- Complete audit trail enables regulatory verification of all changes
- Timestamps allow temporal analysis of credential modifications
- Amendment history distinguishes corrections from version updates
- Supports compliance with data governance requirements
- Cannot amend revoked credentials (must re-issue)
- Only original issuer can amend
- Empty metadata hash rejected
- Version number incremented for each amendment
All four credential management tasks have been successfully implemented in a single PR:
- Task #1219: Batch issuance in
lib.rs- batch_issue_credentials function - Task #1220: Expiry & renewal in
lib.rs- is_credential_expired query function - Task #1221: Suspension in
lib.rs- enhanced suspend_credential with reason tracking - Task #1222: Amendment in
lib.rs- amend_credential function with history
The implementation includes:
- 3 new public functions (is_credential_expired, amend_credential, get_amendment_history)
- 3 new DataKey variants for storage
- 4 new event data structures
- 2 new event topics for on-chain auditability
- Enhanced existing functions (suspend_credential) with new parameters
All changes maintain backward compatibility and follow the existing authorization and event emission patterns in the contract.
- Core implementations: contracts/quorum_proof/src/lib.rs
- Lines: Event data structures, DataKey variants, function implementations
- Documentation: TASK_IMPLEMENTATIONS.md (this file)
- Expiry & Renewal (Task #1220)
- Suspension (Task #1221)
- Batch Issuance (Task #1219)
- Amendment (Task #1222)