Skip to content

Commit 70db4e1

Browse files
authored
Merge pull request #117 from OthmanImam/feat/AdvanceD926
Feat/advance d92
2 parents 458f432 + 3901b50 commit 70db4e1

15 files changed

+2106
-15
lines changed

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ members = [
44
"contracts/governance",
55
"contracts/insurance",
66
"contracts/teachlink",
7-
"contracts/documentation",
7+
"contracts/identity_registry",
8+
"contracts/credential_registry",
89
]
910

1011
[workspace.package]

contracts/IDENTITY_CREDENTIAL.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
**Identity & Credential Contracts (Soroban)**
2+
3+
Overview
4+
- `identity-registry`: on-chain DID registry. Stores DID -> controller, auth methods, recovery address.
5+
- `credential-registry`: on-chain credential index. Stores credential hash -> (issuer DID, subject DID, metadata pointer, expires_at, status).
6+
7+
Key on-chain guarantees
8+
- Deterministic verification can check presence and status of a credential on-chain.
9+
- Full VC JSON and ZK proofs remain off-chain; only hashes/roots and status bits stored on-chain.
10+
11+
Next steps / integration notes
12+
- Wire `credential-registry` to call `identity-registry` for authoritative issuer controller checks.
13+
- Add Merkle/bitmap-based revocation root support for efficient revocation proofs.
14+
- Implement cross-contract calls and auth to allow DID controllers (not raw addresses) to issue/revoke.
15+
- Add off-chain ZK proof verifier support: store verification circuits' commitment roots on-chain and provide helper APIs for verifiers.
16+
- Marketplace, federation, selective-disclosure circuits, and biometric-binding are implemented off-chain; contracts store anchors/roots.
17+
18+
Files added
19+
- `contracts/identity_registry` — Cargo + src/lib.rs
20+
- `contracts/credential_registry` — Cargo + src/lib.rs
21+
22+
Testing & build
23+
- Use the workspace's soroban toolchain and existing patterns (see other `contracts/*` crates) to build and test.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
[package]
2+
name = "credential-registry"
3+
version = "0.1.0"
4+
edition.workspace = true
5+
repository.workspace = true
6+
license.workspace = true
7+
8+
[lib]
9+
crate-type = ["cdylib", "rlib"]
10+
11+
[dependencies]
12+
soroban-sdk.workspace = true
13+
14+
[dev-dependencies]
15+
soroban-sdk = { workspace = true, features = ["testutils"] }
16+
17+
[features]
18+
testutils = ["soroban-sdk/testutils"]
19+
20+
[lints]
21+
workspace = true
22+
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
#![no_std]
2+
3+
use soroban_sdk::{
4+
contract, contractevent, contractimpl, symbol_short, Address, Bytes, BytesN, Env,
5+
};
6+
7+
#[contractevent]
8+
#[derive(Clone, Debug, Eq, PartialEq)]
9+
pub struct Crediss {
10+
pub credential_hash: BytesN<32>,
11+
pub issuer_did: Bytes,
12+
pub subject_did: Bytes,
13+
pub metadata_ptr: Bytes,
14+
pub expires_at: i128,
15+
}
16+
17+
#[contractevent]
18+
#[derive(Clone, Debug, Eq, PartialEq)]
19+
pub struct Credrev {
20+
pub credential_hash: BytesN<32>,
21+
pub issuer_did: Bytes,
22+
pub subject_did: Bytes,
23+
}
24+
#[contract]
25+
pub struct CredentialRegistryContract;
26+
27+
#[derive(Clone)]
28+
pub enum CredentialStatus {
29+
Active,
30+
Revoked,
31+
Expired,
32+
}
33+
34+
#[contractimpl]
35+
impl CredentialRegistryContract {
36+
// Issue a credential by storing its hash and metadata pointer.
37+
// `credential_hash` should be a deterministic hash (e.g., SHA-256) of the full VC JSON.
38+
pub fn issue_credential(
39+
env: &Env,
40+
credential_hash: BytesN<32>,
41+
issuer: Address,
42+
issuer_did: Bytes,
43+
subject_did: Bytes,
44+
metadata_ptr: Bytes,
45+
expires_at: i128,
46+
) {
47+
issuer.require_auth();
48+
let key = (symbol_short!("cred"), credential_hash.clone());
49+
assert!(
50+
!env.storage().persistent().has(&key),
51+
"credential already exists"
52+
);
53+
let record: (Bytes, Bytes, Bytes, i128, i32) = (
54+
issuer_did.clone(),
55+
subject_did.clone(),
56+
metadata_ptr.clone(),
57+
expires_at,
58+
0i32,
59+
);
60+
env.storage().persistent().set(&key, &record);
61+
Crediss {
62+
credential_hash,
63+
issuer_did,
64+
subject_did,
65+
metadata_ptr,
66+
expires_at,
67+
}
68+
.publish(env);
69+
}
70+
71+
// Revoke a credential. Caller must be issuer (signed address)
72+
pub fn revoke_credential(env: &Env, credential_hash: BytesN<32>, issuer: Address) {
73+
issuer.require_auth();
74+
let key = (symbol_short!("cred"), credential_hash.clone());
75+
let opt: Option<(Bytes, Bytes, Bytes, i128, i32)> = env.storage().persistent().get(&key);
76+
match opt {
77+
Some((issuer_did, subject_did, metadata_ptr, expires_at, _status)) => {
78+
let record: (Bytes, Bytes, Bytes, i128, i32) = (
79+
issuer_did.clone(),
80+
subject_did.clone(),
81+
metadata_ptr.clone(),
82+
expires_at,
83+
1i32,
84+
);
85+
env.storage().persistent().set(&key, &record);
86+
Credrev {
87+
credential_hash,
88+
issuer_did,
89+
subject_did,
90+
}
91+
.publish(env);
92+
}
93+
None => panic!("credential not found"),
94+
}
95+
}
96+
97+
// Get credential record: returns (issuer_did, subject_did, metadata_ptr, expires_at, status)
98+
pub fn get_credential(
99+
env: &Env,
100+
credential_hash: BytesN<32>,
101+
) -> Option<(Bytes, Bytes, Bytes, i128, i32)> {
102+
let key = (symbol_short!("cred"), credential_hash.clone());
103+
env.storage().persistent().get(&key)
104+
}
105+
106+
// Check if credential is active (not revoked and not expired)
107+
pub fn is_active(env: &Env, credential_hash: BytesN<32>, now_ts: i128) -> bool {
108+
match Self::get_credential(env, credential_hash.clone()) {
109+
Some((_issuer, _subject, _meta, expires_at, status)) => {
110+
if status == 1 {
111+
return false;
112+
}
113+
if expires_at > 0 && now_ts > expires_at {
114+
return false;
115+
}
116+
true
117+
}
118+
None => false,
119+
}
120+
}
121+
}
122+
123+
fn main() {}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
[package]
2+
name = "identity-registry"
3+
version = "0.1.0"
4+
edition.workspace = true
5+
repository.workspace = true
6+
license.workspace = true
7+
8+
[lib]
9+
crate-type = ["cdylib", "rlib"]
10+
11+
[dependencies]
12+
soroban-sdk.workspace = true
13+
14+
[dev-dependencies]
15+
soroban-sdk = { workspace = true, features = ["testutils"] }
16+
17+
[features]
18+
testutils = ["soroban-sdk/testutils"]
19+
20+
[lints]
21+
workspace = true
22+

0 commit comments

Comments
 (0)