diff --git a/contracts/stellar-id/src/lib.rs b/contracts/stellar-id/src/lib.rs index 9d12fe4..2e3aee6 100644 --- a/contracts/stellar-id/src/lib.rs +++ b/contracts/stellar-id/src/lib.rs @@ -1,6 +1,6 @@ #![no_std] use soroban_sdk::{ - contract, contractimpl, contracttype, Address, Bytes, BytesN, Env, String, Symbol, Vec, + contract, contractimpl, contracttype, xdr::ToXdr, Address, Bytes, BytesN, Env, String, Symbol, Vec, }; // ============================================================ @@ -30,6 +30,7 @@ pub struct Credential { pub issued_at: u64, pub expires_at: u64, // 0 = no expiry pub revoked: bool, + pub credential_hash: BytesN<32>, } /// A credential schema defining a type of credential @@ -460,6 +461,15 @@ impl StellarIdContract { .unwrap_or(0); let credential_id = count + 1; + let credential_hash = Self::compute_expected_hash( + env.clone(), + schema_id, + subject.clone(), + issuer.clone(), + now, + expires_at, + ); + let credential = Credential { id: credential_id, subject: subject.clone(), @@ -468,6 +478,7 @@ impl StellarIdContract { issued_at: now, expires_at, revoked: false, + credential_hash, }; env.storage() @@ -566,6 +577,15 @@ impl StellarIdContract { count += 1; let credential_id = count; + let credential_hash = Self::compute_expected_hash( + env.clone(), + schema_id, + subject.clone(), + issuer.clone(), + now, + expires_at, + ); + let credential = Credential { id: credential_id, subject: subject.clone(), @@ -574,6 +594,7 @@ impl StellarIdContract { issued_at: now, expires_at, revoked: false, + credential_hash, }; env.storage() @@ -689,6 +710,15 @@ impl StellarIdContract { 0 }; + let credential_hash = Self::compute_expected_hash( + env.clone(), + schema_id, + subject.clone(), + operator.clone(), + now, + expires_at, + ); + let credential = Credential { id: credential_id, subject: subject.clone(), @@ -697,6 +727,7 @@ impl StellarIdContract { issued_at: now, expires_at, revoked: false, + credential_hash, }; env.storage() @@ -1435,6 +1466,15 @@ impl StellarIdContract { rec.map(|r| r.trust_level).unwrap_or(1) }; + let credential_hash = Self::compute_expected_hash( + env.clone(), + request.schema_id, + request.subject.clone(), + issuer.clone(), + now, + request.expires_at, + ); + let credential = Credential { id: credential_id, subject: request.subject.clone(), @@ -1443,6 +1483,7 @@ impl StellarIdContract { issued_at: now, expires_at: request.expires_at, revoked: false, + credential_hash, }; env.storage() @@ -1498,6 +1539,76 @@ impl StellarIdContract { (request_id, credential_id, request.subject, request.schema_id), ); } + + // -------------------------------------------------------- + // Issue #64: Credential Hash Registry & EIP-712-style Hashing + // -------------------------------------------------------- + + pub fn compute_expected_hash( + env: Env, + schema_id: u32, + subject: Address, + issuer: Address, + issued_at: u64, + expires_at: u64, + ) -> BytesN<32> { + let contract_addr = env.current_contract_address(); + let contract_bytes = Self::address_to_bytes(&env, &contract_addr); + + let mut domain_buf = Bytes::new(&env); + domain_buf.append(&Bytes::from_slice(&env, b"StellarID:v1:")); + domain_buf.append(&contract_bytes); + let domain_separator = env.crypto().sha256(&domain_buf).to_bytes(); + + let mut buf = Bytes::new(&env); + buf.append(&Bytes::from_slice(&env, &domain_separator.to_array())); + buf.append(&Bytes::from_slice(&env, &schema_id.to_be_bytes())); + buf.append(&Self::address_to_bytes(&env, &subject)); + buf.append(&Self::address_to_bytes(&env, &issuer)); + buf.append(&Bytes::from_slice(&env, &issued_at.to_be_bytes())); + buf.append(&Bytes::from_slice(&env, &expires_at.to_be_bytes())); + + env.crypto().sha256(&buf).to_bytes() + } + + pub fn get_credential_hash(env: Env, credential_id: u64) -> BytesN<32> { + let cred: Credential = env + .storage() + .persistent() + .get(&DataKey::Credential(credential_id)) + .expect("Credential not found"); + cred.credential_hash + } + + pub fn verify_credential_hash(env: Env, credential_id: u64) -> bool { + let cred: Credential = match env.storage().persistent().get(&DataKey::Credential(credential_id)) { + Some(c) => c, + None => return false, + }; + let expected = Self::compute_expected_hash( + env.clone(), + cred.schema_id, + cred.subject.clone(), + cred.issuer.clone(), + cred.issued_at, + cred.expires_at, + ); + cred.credential_hash == expected + } + + fn address_to_bytes(env: &Env, address: &Address) -> Bytes { + let xdr = address.to_xdr(env); + if xdr.len() >= 32 { + xdr.slice(xdr.len() - 32..xdr.len()) + } else { + let mut b = Bytes::new(env); + for _ in 0..(32 - xdr.len()) { + b.push_back(0); + } + b.append(&xdr); + b + } + } } // ============================================================ @@ -2747,4 +2858,54 @@ mod tests { &0u64, ); } + + // -------------------------------------------------------- + // Issue #64 Tests: Credential Hash Registry + // -------------------------------------------------------- + + #[test] + fn test_credential_hash_calculation_and_verification() { + let env = Env::default(); + let (admin, client) = setup(&env); + let issuer = register_issuer_helper(&env, &client, &admin); + let schema_id = register_schema_helper(&env, &client, &issuer); + let subject = Address::generate(&env); + + let cred_id = client.issue_credential(&issuer, &subject, &schema_id, &3600); + let stored_hash = client.get_credential_hash(&cred_id); + + let cred = client.get_credential(&cred_id); + let expected_hash = client.compute_expected_hash( + &cred.schema_id, + &cred.subject, + &cred.issuer, + &cred.issued_at, + &cred.expires_at, + ); + + assert_eq!(stored_hash, expected_hash); + assert!(client.verify_credential_hash(&cred_id)); + } + + #[test] + fn test_credential_hash_modifying_field_changes_hash() { + let env = Env::default(); + let (admin, client) = setup(&env); + let issuer = register_issuer_helper(&env, &client, &admin); + let schema_id = register_schema_helper(&env, &client, &issuer); + let subject = Address::generate(&env); + + let cred_id = client.issue_credential(&issuer, &subject, &schema_id, &3600); + let cred = client.get_credential(&cred_id); + + let tampered_hash = client.compute_expected_hash( + &cred.schema_id, + &cred.subject, + &cred.issuer, + &cred.issued_at, + &(cred.expires_at + 10), + ); + + assert_ne!(cred.credential_hash, tampered_hash); + } } diff --git a/contracts/stellar-id/test_snapshots/tests/test_batch_issue_credentials.1.json b/contracts/stellar-id/test_snapshots/tests/test_batch_issue_credentials.1.json index 9a03dab..0869f33 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_batch_issue_credentials.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_batch_issue_credentials.1.json @@ -236,6 +236,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "bf4df37fe528bbe814b24f1950a75e2c3451a63a4a11f58cae2e648175f7b53c" + } + }, { "key": { "symbol": "expires_at" @@ -338,6 +346,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "0b93b383d9682673c63c8abb15ff6e9c74ad5aab17df344fbe9b90cd9f2a9861" + } + }, { "key": { "symbol": "expires_at" @@ -440,6 +456,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "f471508673872b250c10aeb3fc318cb707202a953b20f4806a73a34f6491841c" + } + }, { "key": { "symbol": "expires_at" @@ -1636,6 +1660,14 @@ ], "data": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "bf4df37fe528bbe814b24f1950a75e2c3451a63a4a11f58cae2e648175f7b53c" + } + }, { "key": { "symbol": "expires_at" @@ -1742,6 +1774,14 @@ ], "data": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "0b93b383d9682673c63c8abb15ff6e9c74ad5aab17df344fbe9b90cd9f2a9861" + } + }, { "key": { "symbol": "expires_at" @@ -1848,6 +1888,14 @@ ], "data": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "f471508673872b250c10aeb3fc318cb707202a953b20f4806a73a34f6491841c" + } + }, { "key": { "symbol": "expires_at" diff --git a/contracts/stellar-id/test_snapshots/tests/test_batch_issue_credentials_updates_multiple_identities.1.json b/contracts/stellar-id/test_snapshots/tests/test_batch_issue_credentials_updates_multiple_identities.1.json index e8f937b..a65528d 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_batch_issue_credentials_updates_multiple_identities.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_batch_issue_credentials_updates_multiple_identities.1.json @@ -284,6 +284,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "f48a63c61e655c2136dbbfac1456d532aacfd8d3107042d0c966756a29a01d98" + } + }, { "key": { "symbol": "expires_at" @@ -386,6 +394,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "1a5d0761c0722083639fc11055b64d8751b33f4927297dcb7d59c790cc552bb0" + } + }, { "key": { "symbol": "expires_at" @@ -488,6 +504,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "2ee75b4e23833716ab0a1753262678e7b75e98147e1b8934c9c282328dd214c4" + } + }, { "key": { "symbol": "expires_at" diff --git a/contracts/stellar-id/test_snapshots/tests/test_batch_issue_credentials_with_expiry.1.json b/contracts/stellar-id/test_snapshots/tests/test_batch_issue_credentials_with_expiry.1.json index 33b7b20..6ed2cbb 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_batch_issue_credentials_with_expiry.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_batch_issue_credentials_with_expiry.1.json @@ -227,6 +227,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "3c4f8994bdf19134f16ec18e05fee43bc0b771e6675afd1c4364e723d846b677" + } + }, { "key": { "symbol": "expires_at" @@ -329,6 +337,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "fb16654310808fcab695fa707edb9fadb39923f7c0236d916853b1cf91b1d5a4" + } + }, { "key": { "symbol": "expires_at" @@ -1345,6 +1361,14 @@ ], "data": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "3c4f8994bdf19134f16ec18e05fee43bc0b771e6675afd1c4364e723d846b677" + } + }, { "key": { "symbol": "expires_at" @@ -1451,6 +1475,14 @@ ], "data": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "fb16654310808fcab695fa707edb9fadb39923f7c0236d916853b1cf91b1d5a4" + } + }, { "key": { "symbol": "expires_at" diff --git a/contracts/stellar-id/test_snapshots/tests/test_bridge_credential_authorized.1.json b/contracts/stellar-id/test_snapshots/tests/test_bridge_credential_authorized.1.json index 2e557df..b944ade 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_bridge_credential_authorized.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_bridge_credential_authorized.1.json @@ -518,6 +518,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "c5cbb3c28d9cdf1609ed10476bb6f01da0aee4d71a6b3b897c8c258b75f6e5ee" + } + }, { "key": { "symbol": "expires_at" @@ -1578,6 +1586,14 @@ ], "data": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "c5cbb3c28d9cdf1609ed10476bb6f01da0aee4d71a6b3b897c8c258b75f6e5ee" + } + }, { "key": { "symbol": "expires_at" diff --git a/contracts/stellar-id/test_snapshots/tests/test_bridge_credential_duplicate_panics.1.json b/contracts/stellar-id/test_snapshots/tests/test_bridge_credential_duplicate_panics.1.json index 759309c..4909533 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_bridge_credential_duplicate_panics.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_bridge_credential_duplicate_panics.1.json @@ -516,6 +516,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "c5cbb3c28d9cdf1609ed10476bb6f01da0aee4d71a6b3b897c8c258b75f6e5ee" + } + }, { "key": { "symbol": "expires_at" @@ -1639,7 +1647,7 @@ "data": { "vec": [ { - "string": "caught panic 'Attestation already bridged' from contract function 'Symbol(obj#289)'" + "string": "caught panic 'Attestation already bridged' from contract function 'Symbol(obj#339)'" }, { "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" diff --git a/contracts/stellar-id/test_snapshots/tests/test_credential_hash_calculation_and_verification.1.json b/contracts/stellar-id/test_snapshots/tests/test_credential_hash_calculation_and_verification.1.json new file mode 100644 index 0000000..19778c5 --- /dev/null +++ b/contracts/stellar-id/test_snapshots/tests/test_credential_hash_calculation_and_verification.1.json @@ -0,0 +1,1343 @@ +{ + "generators": { + "address": 4, + "nonce": 0 + }, + "auth": [ + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "function_name": "register_issuer", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "string": "Test Issuer" + }, + { + "u32": 80 + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "function_name": "register_schema", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "string": "KYC Verified" + }, + { + "string": "Basic KYC verification credential" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "function_name": "issue_credential", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + { + "u32": 1 + }, + { + "u64": 3600 + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [], + [], + [] + ], + "ledger": { + "protocol_version": 21, + "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": [ + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": 5541220902715666415 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": 5541220902715666415 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "Credential" + }, + { + "u64": 1 + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "Credential" + }, + { + "u64": 1 + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "860fdbf74ccf80aedaaf110b9908881c37e6cdafd25c23015db29ec4db08ada9" + } + }, + { + "key": { + "symbol": "expires_at" + }, + "val": { + "u64": 3600 + } + }, + { + "key": { + "symbol": "id" + }, + "val": { + "u64": 1 + } + }, + { + "key": { + "symbol": "issued_at" + }, + "val": { + "u64": 0 + } + }, + { + "key": { + "symbol": "issuer" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "revoked" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "schema_id" + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "symbol": "subject" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + } + ] + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "Identity" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "Identity" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "created_at" + }, + "val": { + "u64": 0 + } + }, + { + "key": { + "symbol": "credential_count" + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "symbol": "reputation_score" + }, + "val": { + "u32": 8 + } + }, + { + "key": { + "symbol": "subject" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + } + ] + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "Issuer" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "Issuer" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "active" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "address" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "credential_count" + }, + "val": { + "u64": 1 + } + }, + { + "key": { + "symbol": "name" + }, + "val": { + "string": "Test Issuer" + } + }, + { + "key": { + "symbol": "trust_level" + }, + "val": { + "u32": 80 + } + } + ] + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "Schema" + }, + { + "u32": 1 + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "Schema" + }, + { + "u32": 1 + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "active" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "description" + }, + "val": { + "string": "Basic KYC verification credential" + } + }, + { + "key": { + "symbol": "id" + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "symbol": "issuer" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "name" + }, + "val": { + "string": "KYC Verified" + } + } + ] + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "SubjectCredentials" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "SubjectCredentials" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + ] + }, + "durability": "persistent", + "val": { + "vec": [ + { + "u64": 1 + } + ] + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "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": [ + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "vec": [ + { + "symbol": "CredentialCount" + } + ] + }, + "val": { + "u64": 1 + } + }, + { + "key": { + "vec": [ + { + "symbol": "SchemaCount" + } + ] + }, + "val": { + "u32": 1 + } + } + ] + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": 1033654523790656264 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": 1033654523790656264 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": 4837995959683129791 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": 4837995959683129791 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_code": { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + 4095 + ] + ] + ] + }, + "events": [ + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + }, + { + "symbol": "initialize" + } + ], + "data": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000002", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "initialize" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + }, + { + "symbol": "register_issuer" + } + ], + "data": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "string": "Test Issuer" + }, + { + "u32": 80 + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000002", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "issuer_registered" + } + ], + "data": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000002", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "register_issuer" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + }, + { + "symbol": "register_schema" + } + ], + "data": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "string": "KYC Verified" + }, + { + "string": "Basic KYC verification credential" + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000002", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "schema_registered" + } + ], + "data": { + "vec": [ + { + "u32": 1 + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000002", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "register_schema" + } + ], + "data": { + "u32": 1 + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + }, + { + "symbol": "issue_credential" + } + ], + "data": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + { + "u32": 1 + }, + { + "u64": 3600 + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000002", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "credential_issued" + } + ], + "data": { + "vec": [ + { + "u64": 1 + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000002", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "issue_credential" + } + ], + "data": { + "u64": 1 + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + }, + { + "symbol": "get_credential_hash" + } + ], + "data": { + "u64": 1 + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000002", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "get_credential_hash" + } + ], + "data": { + "bytes": "860fdbf74ccf80aedaaf110b9908881c37e6cdafd25c23015db29ec4db08ada9" + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + }, + { + "symbol": "get_credential" + } + ], + "data": { + "u64": 1 + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000002", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "get_credential" + } + ], + "data": { + "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "860fdbf74ccf80aedaaf110b9908881c37e6cdafd25c23015db29ec4db08ada9" + } + }, + { + "key": { + "symbol": "expires_at" + }, + "val": { + "u64": 3600 + } + }, + { + "key": { + "symbol": "id" + }, + "val": { + "u64": 1 + } + }, + { + "key": { + "symbol": "issued_at" + }, + "val": { + "u64": 0 + } + }, + { + "key": { + "symbol": "issuer" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "revoked" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "schema_id" + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "symbol": "subject" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + }, + { + "symbol": "compute_expected_hash" + } + ], + "data": { + "vec": [ + { + "u32": 1 + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "u64": 0 + }, + { + "u64": 3600 + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000002", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "compute_expected_hash" + } + ], + "data": { + "bytes": "860fdbf74ccf80aedaaf110b9908881c37e6cdafd25c23015db29ec4db08ada9" + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + }, + { + "symbol": "verify_credential_hash" + } + ], + "data": { + "u64": 1 + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000002", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "verify_credential_hash" + } + ], + "data": { + "bool": true + } + } + } + }, + "failed_call": false + } + ] +} \ No newline at end of file diff --git a/contracts/stellar-id/test_snapshots/tests/test_credential_hash_modifying_field_changes_hash.1.json b/contracts/stellar-id/test_snapshots/tests/test_credential_hash_modifying_field_changes_hash.1.json new file mode 100644 index 0000000..29be808 --- /dev/null +++ b/contracts/stellar-id/test_snapshots/tests/test_credential_hash_modifying_field_changes_hash.1.json @@ -0,0 +1,1243 @@ +{ + "generators": { + "address": 4, + "nonce": 0 + }, + "auth": [ + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "function_name": "register_issuer", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "string": "Test Issuer" + }, + { + "u32": 80 + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "function_name": "register_schema", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "string": "KYC Verified" + }, + { + "string": "Basic KYC verification credential" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "function_name": "issue_credential", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + { + "u32": 1 + }, + { + "u64": 3600 + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [] + ], + "ledger": { + "protocol_version": 21, + "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": [ + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": 5541220902715666415 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": 5541220902715666415 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "Credential" + }, + { + "u64": 1 + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "Credential" + }, + { + "u64": 1 + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "860fdbf74ccf80aedaaf110b9908881c37e6cdafd25c23015db29ec4db08ada9" + } + }, + { + "key": { + "symbol": "expires_at" + }, + "val": { + "u64": 3600 + } + }, + { + "key": { + "symbol": "id" + }, + "val": { + "u64": 1 + } + }, + { + "key": { + "symbol": "issued_at" + }, + "val": { + "u64": 0 + } + }, + { + "key": { + "symbol": "issuer" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "revoked" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "schema_id" + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "symbol": "subject" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + } + ] + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "Identity" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "Identity" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "created_at" + }, + "val": { + "u64": 0 + } + }, + { + "key": { + "symbol": "credential_count" + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "symbol": "reputation_score" + }, + "val": { + "u32": 8 + } + }, + { + "key": { + "symbol": "subject" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + } + ] + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "Issuer" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "Issuer" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "active" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "address" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "credential_count" + }, + "val": { + "u64": 1 + } + }, + { + "key": { + "symbol": "name" + }, + "val": { + "string": "Test Issuer" + } + }, + { + "key": { + "symbol": "trust_level" + }, + "val": { + "u32": 80 + } + } + ] + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "Schema" + }, + { + "u32": 1 + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "Schema" + }, + { + "u32": 1 + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "active" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "description" + }, + "val": { + "string": "Basic KYC verification credential" + } + }, + { + "key": { + "symbol": "id" + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "symbol": "issuer" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "name" + }, + "val": { + "string": "KYC Verified" + } + } + ] + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "SubjectCredentials" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "SubjectCredentials" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + ] + }, + "durability": "persistent", + "val": { + "vec": [ + { + "u64": 1 + } + ] + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "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": [ + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "vec": [ + { + "symbol": "CredentialCount" + } + ] + }, + "val": { + "u64": 1 + } + }, + { + "key": { + "vec": [ + { + "symbol": "SchemaCount" + } + ] + }, + "val": { + "u32": 1 + } + } + ] + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": 1033654523790656264 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": 1033654523790656264 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": 4837995959683129791 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": 4837995959683129791 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_code": { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + 4095 + ] + ] + ] + }, + "events": [ + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + }, + { + "symbol": "initialize" + } + ], + "data": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000002", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "initialize" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + }, + { + "symbol": "register_issuer" + } + ], + "data": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "string": "Test Issuer" + }, + { + "u32": 80 + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000002", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "issuer_registered" + } + ], + "data": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000002", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "register_issuer" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + }, + { + "symbol": "register_schema" + } + ], + "data": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "string": "KYC Verified" + }, + { + "string": "Basic KYC verification credential" + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000002", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "schema_registered" + } + ], + "data": { + "vec": [ + { + "u32": 1 + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000002", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "register_schema" + } + ], + "data": { + "u32": 1 + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + }, + { + "symbol": "issue_credential" + } + ], + "data": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + { + "u32": 1 + }, + { + "u64": 3600 + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000002", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "credential_issued" + } + ], + "data": { + "vec": [ + { + "u64": 1 + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000002", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "issue_credential" + } + ], + "data": { + "u64": 1 + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + }, + { + "symbol": "get_credential" + } + ], + "data": { + "u64": 1 + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000002", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "get_credential" + } + ], + "data": { + "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "860fdbf74ccf80aedaaf110b9908881c37e6cdafd25c23015db29ec4db08ada9" + } + }, + { + "key": { + "symbol": "expires_at" + }, + "val": { + "u64": 3600 + } + }, + { + "key": { + "symbol": "id" + }, + "val": { + "u64": 1 + } + }, + { + "key": { + "symbol": "issued_at" + }, + "val": { + "u64": 0 + } + }, + { + "key": { + "symbol": "issuer" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "revoked" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "schema_id" + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "symbol": "subject" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + }, + { + "symbol": "compute_expected_hash" + } + ], + "data": { + "vec": [ + { + "u32": 1 + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "u64": 0 + }, + { + "u64": 3610 + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000002", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "compute_expected_hash" + } + ], + "data": { + "bytes": "95e51a0ac842bb11de79dc7dab8f2d68f9f5c0353b6283a050814afbd978680b" + } + } + } + }, + "failed_call": false + } + ] +} \ No newline at end of file diff --git a/contracts/stellar-id/test_snapshots/tests/test_credential_with_expiry.1.json b/contracts/stellar-id/test_snapshots/tests/test_credential_with_expiry.1.json index f76c6c8..2962fb3 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_credential_with_expiry.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_credential_with_expiry.1.json @@ -219,6 +219,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "3c4f8994bdf19134f16ec18e05fee43bc0b771e6675afd1c4364e723d846b677" + } + }, { "key": { "symbol": "expires_at" @@ -1094,6 +1102,14 @@ ], "data": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "3c4f8994bdf19134f16ec18e05fee43bc0b771e6675afd1c4364e723d846b677" + } + }, { "key": { "symbol": "expires_at" diff --git a/contracts/stellar-id/test_snapshots/tests/test_existing_credentials_remain_valid_after_schema_deactivation.1.json b/contracts/stellar-id/test_snapshots/tests/test_existing_credentials_remain_valid_after_schema_deactivation.1.json index 76dde9f..d42ae72 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_existing_credentials_remain_valid_after_schema_deactivation.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_existing_credentials_remain_valid_after_schema_deactivation.1.json @@ -243,6 +243,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "f48a63c61e655c2136dbbfac1456d532aacfd8d3107042d0c966756a29a01d98" + } + }, { "key": { "symbol": "expires_at" @@ -1344,6 +1352,14 @@ ], "data": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "f48a63c61e655c2136dbbfac1456d532aacfd8d3107042d0c966756a29a01d98" + } + }, { "key": { "symbol": "expires_at" diff --git a/contracts/stellar-id/test_snapshots/tests/test_get_subject_credentials.1.json b/contracts/stellar-id/test_snapshots/tests/test_get_subject_credentials.1.json index 92c10ff..73c341b 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_get_subject_credentials.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_get_subject_credentials.1.json @@ -272,6 +272,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "f48a63c61e655c2136dbbfac1456d532aacfd8d3107042d0c966756a29a01d98" + } + }, { "key": { "symbol": "expires_at" @@ -374,6 +382,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "1a5d0761c0722083639fc11055b64d8751b33f4927297dcb7d59c790cc552bb0" + } + }, { "key": { "symbol": "expires_at" diff --git a/contracts/stellar-id/test_snapshots/tests/test_has_credential_from_issuer.1.json b/contracts/stellar-id/test_snapshots/tests/test_has_credential_from_issuer.1.json index 9c8090d..765b757 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_has_credential_from_issuer.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_has_credential_from_issuer.1.json @@ -220,6 +220,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "f48a63c61e655c2136dbbfac1456d532aacfd8d3107042d0c966756a29a01d98" + } + }, { "key": { "symbol": "expires_at" diff --git a/contracts/stellar-id/test_snapshots/tests/test_has_valid_commitment_no_commitment_submitted.1.json b/contracts/stellar-id/test_snapshots/tests/test_has_valid_commitment_no_commitment_submitted.1.json index 57e66f7..ce15122 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_has_valid_commitment_no_commitment_submitted.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_has_valid_commitment_no_commitment_submitted.1.json @@ -219,6 +219,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "f48a63c61e655c2136dbbfac1456d532aacfd8d3107042d0c966756a29a01d98" + } + }, { "key": { "symbol": "expires_at" diff --git a/contracts/stellar-id/test_snapshots/tests/test_has_valid_credential_expired.1.json b/contracts/stellar-id/test_snapshots/tests/test_has_valid_credential_expired.1.json index ca82e51..07cfbc7 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_has_valid_credential_expired.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_has_valid_credential_expired.1.json @@ -219,6 +219,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "188813d3cd197854444babfc369c64545db3fb430bd44101ecefa63e8f9785d7" + } + }, { "key": { "symbol": "expires_at" diff --git a/contracts/stellar-id/test_snapshots/tests/test_has_valid_credential_expires_at_now_boundary.1.json b/contracts/stellar-id/test_snapshots/tests/test_has_valid_credential_expires_at_now_boundary.1.json index 5cc4870..521be97 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_has_valid_credential_expires_at_now_boundary.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_has_valid_credential_expires_at_now_boundary.1.json @@ -219,6 +219,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "188813d3cd197854444babfc369c64545db3fb430bd44101ecefa63e8f9785d7" + } + }, { "key": { "symbol": "expires_at" diff --git a/contracts/stellar-id/test_snapshots/tests/test_has_valid_credential_true.1.json b/contracts/stellar-id/test_snapshots/tests/test_has_valid_credential_true.1.json index bc5fec9..85565dd 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_has_valid_credential_true.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_has_valid_credential_true.1.json @@ -220,6 +220,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "f48a63c61e655c2136dbbfac1456d532aacfd8d3107042d0c966756a29a01d98" + } + }, { "key": { "symbol": "expires_at" diff --git a/contracts/stellar-id/test_snapshots/tests/test_identity_created_on_first_credential.1.json b/contracts/stellar-id/test_snapshots/tests/test_identity_created_on_first_credential.1.json index 32eadfa..6b01143 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_identity_created_on_first_credential.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_identity_created_on_first_credential.1.json @@ -219,6 +219,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "f48a63c61e655c2136dbbfac1456d532aacfd8d3107042d0c966756a29a01d98" + } + }, { "key": { "symbol": "expires_at" diff --git a/contracts/stellar-id/test_snapshots/tests/test_issue_credential.1.json b/contracts/stellar-id/test_snapshots/tests/test_issue_credential.1.json index b37a626..996d823 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_issue_credential.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_issue_credential.1.json @@ -220,6 +220,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "f48a63c61e655c2136dbbfac1456d532aacfd8d3107042d0c966756a29a01d98" + } + }, { "key": { "symbol": "expires_at" @@ -1142,6 +1150,14 @@ ], "data": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "f48a63c61e655c2136dbbfac1456d532aacfd8d3107042d0c966756a29a01d98" + } + }, { "key": { "symbol": "expires_at" diff --git a/contracts/stellar-id/test_snapshots/tests/test_multiple_credentials_same_schema_one_expired_one_valid.1.json b/contracts/stellar-id/test_snapshots/tests/test_multiple_credentials_same_schema_one_expired_one_valid.1.json index 796660c..04df1b3 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_multiple_credentials_same_schema_one_expired_one_valid.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_multiple_credentials_same_schema_one_expired_one_valid.1.json @@ -247,6 +247,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "e93afabe65926a545de4a6d8f389545764e0b07d7bfd779ed332370c485188cd" + } + }, { "key": { "symbol": "expires_at" @@ -349,6 +357,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "38587bcbee93ee3b0360fe1d924b3da6f0c0c920a88ecb4676e466025a5e5304" + } + }, { "key": { "symbol": "expires_at" diff --git a/contracts/stellar-id/test_snapshots/tests/test_multisig_2_of_3_flow.1.json b/contracts/stellar-id/test_snapshots/tests/test_multisig_2_of_3_flow.1.json index bb5a74a..71a6558 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_multisig_2_of_3_flow.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_multisig_2_of_3_flow.1.json @@ -383,6 +383,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "3d5dbe74e7837eb6afa204db85c6c76e35f8f3b3abb3784c6993e2a6c0bbc27f" + } + }, { "key": { "symbol": "expires_at" @@ -2190,6 +2198,14 @@ ], "data": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "3d5dbe74e7837eb6afa204db85c6c76e35f8f3b3abb3784c6993e2a6c0bbc27f" + } + }, { "key": { "symbol": "expires_at" diff --git a/contracts/stellar-id/test_snapshots/tests/test_multisig_3_of_3_flow.1.json b/contracts/stellar-id/test_snapshots/tests/test_multisig_3_of_3_flow.1.json index ff74d0a..f05dd10 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_multisig_3_of_3_flow.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_multisig_3_of_3_flow.1.json @@ -404,6 +404,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "3d5dbe74e7837eb6afa204db85c6c76e35f8f3b3abb3784c6993e2a6c0bbc27f" + } + }, { "key": { "symbol": "expires_at" diff --git a/contracts/stellar-id/test_snapshots/tests/test_multisig_threshold_triggers_issuance_and_identity_update.1.json b/contracts/stellar-id/test_snapshots/tests/test_multisig_threshold_triggers_issuance_and_identity_update.1.json index 2bf7efe..6df8d00 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_multisig_threshold_triggers_issuance_and_identity_update.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_multisig_threshold_triggers_issuance_and_identity_update.1.json @@ -319,6 +319,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "d89d81e65e1f7c765b010a96de8a4c6cec8abc7137efec948dc338be542abad9" + } + }, { "key": { "symbol": "expires_at" @@ -1766,6 +1774,14 @@ ], "data": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "d89d81e65e1f7c765b010a96de8a4c6cec8abc7137efec948dc338be542abad9" + } + }, { "key": { "symbol": "expires_at" diff --git a/contracts/stellar-id/test_snapshots/tests/test_non_expiring_credential_indefinite.1.json b/contracts/stellar-id/test_snapshots/tests/test_non_expiring_credential_indefinite.1.json index a9dfad4..8c300b4 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_non_expiring_credential_indefinite.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_non_expiring_credential_indefinite.1.json @@ -220,6 +220,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "f48a63c61e655c2136dbbfac1456d532aacfd8d3107042d0c966756a29a01d98" + } + }, { "key": { "symbol": "expires_at" @@ -1095,6 +1103,14 @@ ], "data": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "f48a63c61e655c2136dbbfac1456d532aacfd8d3107042d0c966756a29a01d98" + } + }, { "key": { "symbol": "expires_at" diff --git a/contracts/stellar-id/test_snapshots/tests/test_non_issuer_cannot_revoke.1.json b/contracts/stellar-id/test_snapshots/tests/test_non_issuer_cannot_revoke.1.json index f4f369c..77a124c 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_non_issuer_cannot_revoke.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_non_issuer_cannot_revoke.1.json @@ -219,6 +219,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "f48a63c61e655c2136dbbfac1456d532aacfd8d3107042d0c966756a29a01d98" + } + }, { "key": { "symbol": "expires_at" @@ -1099,7 +1107,7 @@ "data": { "vec": [ { - "string": "caught panic 'Only the original issuer can revoke' from contract function 'Symbol(obj#241)'" + "string": "caught panic 'Only the original issuer can revoke' from contract function 'Symbol(obj#291)'" }, { "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" diff --git a/contracts/stellar-id/test_snapshots/tests/test_random_address_cannot_revoke_other_issuers_credential.1.json b/contracts/stellar-id/test_snapshots/tests/test_random_address_cannot_revoke_other_issuers_credential.1.json index f4f369c..77a124c 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_random_address_cannot_revoke_other_issuers_credential.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_random_address_cannot_revoke_other_issuers_credential.1.json @@ -219,6 +219,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "f48a63c61e655c2136dbbfac1456d532aacfd8d3107042d0c966756a29a01d98" + } + }, { "key": { "symbol": "expires_at" @@ -1099,7 +1107,7 @@ "data": { "vec": [ { - "string": "caught panic 'Only the original issuer can revoke' from contract function 'Symbol(obj#241)'" + "string": "caught panic 'Only the original issuer can revoke' from contract function 'Symbol(obj#291)'" }, { "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" diff --git a/contracts/stellar-id/test_snapshots/tests/test_renew_credential.1.json b/contracts/stellar-id/test_snapshots/tests/test_renew_credential.1.json index d1012f9..c0bbe11 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_renew_credential.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_renew_credential.1.json @@ -246,6 +246,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "3c4f8994bdf19134f16ec18e05fee43bc0b771e6675afd1c4364e723d846b677" + } + }, { "key": { "symbol": "expires_at" @@ -1154,6 +1162,14 @@ ], "data": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "3c4f8994bdf19134f16ec18e05fee43bc0b771e6675afd1c4364e723d846b677" + } + }, { "key": { "symbol": "expires_at" @@ -1344,6 +1360,14 @@ ], "data": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "3c4f8994bdf19134f16ec18e05fee43bc0b771e6675afd1c4364e723d846b677" + } + }, { "key": { "symbol": "expires_at" diff --git a/contracts/stellar-id/test_snapshots/tests/test_renew_credential_multiple_times.1.json b/contracts/stellar-id/test_snapshots/tests/test_renew_credential_multiple_times.1.json index 707d6d0..7af0739 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_renew_credential_multiple_times.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_renew_credential_multiple_times.1.json @@ -270,6 +270,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "f8031f2e129036b09b327e5e774bf683efc326aa61ebe4dd03dbbb9b9cfdcb89" + } + }, { "key": { "symbol": "expires_at" @@ -1295,6 +1303,14 @@ ], "data": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "f8031f2e129036b09b327e5e774bf683efc326aa61ebe4dd03dbbb9b9cfdcb89" + } + }, { "key": { "symbol": "expires_at" @@ -1485,6 +1501,14 @@ ], "data": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "f8031f2e129036b09b327e5e774bf683efc326aa61ebe4dd03dbbb9b9cfdcb89" + } + }, { "key": { "symbol": "expires_at" diff --git a/contracts/stellar-id/test_snapshots/tests/test_renew_credential_non_expiring_panics.1.json b/contracts/stellar-id/test_snapshots/tests/test_renew_credential_non_expiring_panics.1.json index ea72906..d0d2823 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_renew_credential_non_expiring_panics.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_renew_credential_non_expiring_panics.1.json @@ -219,6 +219,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "f48a63c61e655c2136dbbfac1456d532aacfd8d3107042d0c966756a29a01d98" + } + }, { "key": { "symbol": "expires_at" @@ -1102,7 +1110,7 @@ "data": { "vec": [ { - "string": "caught panic 'Cannot renew a non-expiring credential' from contract function 'Symbol(obj#239)'" + "string": "caught panic 'Cannot renew a non-expiring credential' from contract function 'Symbol(obj#289)'" }, { "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" diff --git a/contracts/stellar-id/test_snapshots/tests/test_renew_credential_non_issuer_rejected.1.json b/contracts/stellar-id/test_snapshots/tests/test_renew_credential_non_issuer_rejected.1.json index ebb1bd2..b9128b0 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_renew_credential_non_issuer_rejected.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_renew_credential_non_issuer_rejected.1.json @@ -219,6 +219,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "3c4f8994bdf19134f16ec18e05fee43bc0b771e6675afd1c4364e723d846b677" + } + }, { "key": { "symbol": "expires_at" @@ -1102,7 +1110,7 @@ "data": { "vec": [ { - "string": "caught panic 'Only the original issuer can renew' from contract function 'Symbol(obj#241)'" + "string": "caught panic 'Only the original issuer can renew' from contract function 'Symbol(obj#291)'" }, { "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" diff --git a/contracts/stellar-id/test_snapshots/tests/test_renew_credential_restores_validity.1.json b/contracts/stellar-id/test_snapshots/tests/test_renew_credential_restores_validity.1.json index 476f1b5..e86e5ee 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_renew_credential_restores_validity.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_renew_credential_restores_validity.1.json @@ -246,6 +246,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "188813d3cd197854444babfc369c64545db3fb430bd44101ecefa63e8f9785d7" + } + }, { "key": { "symbol": "expires_at" diff --git a/contracts/stellar-id/test_snapshots/tests/test_renew_credential_revoked_rejected.1.json b/contracts/stellar-id/test_snapshots/tests/test_renew_credential_revoked_rejected.1.json index 952976b..4ef086a 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_renew_credential_revoked_rejected.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_renew_credential_revoked_rejected.1.json @@ -241,6 +241,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "3c4f8994bdf19134f16ec18e05fee43bc0b771e6675afd1c4364e723d846b677" + } + }, { "key": { "symbol": "expires_at" @@ -1238,7 +1246,7 @@ "data": { "vec": [ { - "string": "caught panic 'Cannot renew a revoked credential' from contract function 'Symbol(obj#275)'" + "string": "caught panic 'Cannot renew a revoked credential' from contract function 'Symbol(obj#331)'" }, { "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" diff --git a/contracts/stellar-id/test_snapshots/tests/test_renew_credential_zero_additional_seconds_panics.1.json b/contracts/stellar-id/test_snapshots/tests/test_renew_credential_zero_additional_seconds_panics.1.json index 78efa5b..365296a 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_renew_credential_zero_additional_seconds_panics.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_renew_credential_zero_additional_seconds_panics.1.json @@ -219,6 +219,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "3c4f8994bdf19134f16ec18e05fee43bc0b771e6675afd1c4364e723d846b677" + } + }, { "key": { "symbol": "expires_at" @@ -1102,7 +1110,7 @@ "data": { "vec": [ { - "string": "caught panic 'additional_seconds must be greater than zero' from contract function 'Symbol(obj#239)'" + "string": "caught panic 'additional_seconds must be greater than zero' from contract function 'Symbol(obj#289)'" }, { "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" diff --git a/contracts/stellar-id/test_snapshots/tests/test_reputation_increases_with_credentials.1.json b/contracts/stellar-id/test_snapshots/tests/test_reputation_increases_with_credentials.1.json index e25e93d..260c0ff 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_reputation_increases_with_credentials.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_reputation_increases_with_credentials.1.json @@ -273,6 +273,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "f48a63c61e655c2136dbbfac1456d532aacfd8d3107042d0c966756a29a01d98" + } + }, { "key": { "symbol": "expires_at" @@ -375,6 +383,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "1a5d0761c0722083639fc11055b64d8751b33f4927297dcb7d59c790cc552bb0" + } + }, { "key": { "symbol": "expires_at" diff --git a/contracts/stellar-id/test_snapshots/tests/test_revoke_credential.1.json b/contracts/stellar-id/test_snapshots/tests/test_revoke_credential.1.json index b68a802..3fbfe2f 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_revoke_credential.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_revoke_credential.1.json @@ -243,6 +243,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "f48a63c61e655c2136dbbfac1456d532aacfd8d3107042d0c966756a29a01d98" + } + }, { "key": { "symbol": "expires_at" @@ -1288,6 +1296,14 @@ ], "data": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "f48a63c61e655c2136dbbfac1456d532aacfd8d3107042d0c966756a29a01d98" + } + }, { "key": { "symbol": "expires_at" diff --git a/contracts/stellar-id/test_snapshots/tests/test_submit_and_verify_commitment_valid.1.json b/contracts/stellar-id/test_snapshots/tests/test_submit_and_verify_commitment_valid.1.json index 67f3fc7..634d227 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_submit_and_verify_commitment_valid.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_submit_and_verify_commitment_valid.1.json @@ -329,6 +329,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "f48a63c61e655c2136dbbfac1456d532aacfd8d3107042d0c966756a29a01d98" + } + }, { "key": { "symbol": "expires_at" diff --git a/contracts/stellar-id/test_snapshots/tests/test_verify_commitment_expired_credential.1.json b/contracts/stellar-id/test_snapshots/tests/test_verify_commitment_expired_credential.1.json index 1fbb34c..4148194 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_verify_commitment_expired_credential.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_verify_commitment_expired_credential.1.json @@ -329,6 +329,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "188813d3cd197854444babfc369c64545db3fb430bd44101ecefa63e8f9785d7" + } + }, { "key": { "symbol": "expires_at" diff --git a/contracts/stellar-id/test_snapshots/tests/test_verify_commitment_revoked_credential.1.json b/contracts/stellar-id/test_snapshots/tests/test_verify_commitment_revoked_credential.1.json index 3c02964..852bf97 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_verify_commitment_revoked_credential.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_verify_commitment_revoked_credential.1.json @@ -351,6 +351,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "f48a63c61e655c2136dbbfac1456d532aacfd8d3107042d0c966756a29a01d98" + } + }, { "key": { "symbol": "expires_at" diff --git a/contracts/stellar-id/test_snapshots/tests/test_verify_commitment_tampered_commitment.1.json b/contracts/stellar-id/test_snapshots/tests/test_verify_commitment_tampered_commitment.1.json index 9010894..09f19eb 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_verify_commitment_tampered_commitment.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_verify_commitment_tampered_commitment.1.json @@ -328,6 +328,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "f48a63c61e655c2136dbbfac1456d532aacfd8d3107042d0c966756a29a01d98" + } + }, { "key": { "symbol": "expires_at" diff --git a/contracts/stellar-id/test_snapshots/tests/test_verify_commitment_wrong_blinding_factor.1.json b/contracts/stellar-id/test_snapshots/tests/test_verify_commitment_wrong_blinding_factor.1.json index b6df8ad..85a937f 100644 --- a/contracts/stellar-id/test_snapshots/tests/test_verify_commitment_wrong_blinding_factor.1.json +++ b/contracts/stellar-id/test_snapshots/tests/test_verify_commitment_wrong_blinding_factor.1.json @@ -328,6 +328,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "f48a63c61e655c2136dbbfac1456d532aacfd8d3107042d0c966756a29a01d98" + } + }, { "key": { "symbol": "expires_at" diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 2207ade..5b8ea86 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -42,7 +42,8 @@ Credential (persistent storage, keyed by credential_id u64) ├── schema_id ├── issued_at ├── expires_at (0 = no expiry) - └── revoked + ├── revoked + └── credential_hash (BytesN<32>) Identity (persistent storage, keyed by subject Address) ├── credential_count @@ -101,26 +102,27 @@ The score increases as more trusted issuers credential the subject. It caps at 1 StellarID credentials are stored in plaintext. The commitment layer lets a subject prove they hold a valid credential without revealing which one. -### How it works +--- -1. **Commit** — the subject picks a random 32-byte blinding factor `r` and computes: - ``` - commitment = SHA-256(credential_id_as_8_le_bytes || r) - ``` - They call `submit_commitment(subject, schema_id, commitment)`. Only the hash goes on-chain. +## Canonical Credential Hashing Standard (EIP-712 Style) -2. **Prove** — when a verifier calls `verify_commitment(subject, schema_id, credential_id, r)`, the contract recomputes the hash and checks it matches the stored commitment. It also checks the credential is valid (not revoked, not expired, owned by subject). +Credential authenticity in StellarID supports off-chain verification using an EIP-712-style deterministic typed structured data hashing scheme. -3. **Query** — `has_valid_commitment(subject, schema_id)` returns whether a commitment exists and the subject holds at least one live credential for that schema, without revealing which credential. - -### Security properties - -- **Hiding** — SHA-256 is a one-way function; the commitment reveals nothing about `credential_id` or `r`. -- **Binding** — it is computationally infeasible to find a different `(credential_id', r')` that produces the same commitment. -- **Privacy** — observers on-chain see only the hash, not the credential ID or issuer. - -### Limitations +### Domain Separator +``` +domain_separator = SHA-256( ASCII("StellarID:v1:") || contract_address_32_bytes ) +``` -- `has_valid_commitment` is a weaker guarantee than `verify_commitment`. It confirms a commitment exists and a live credential exists for the schema, but does not bind the two together. Full binding requires the subject to reveal the opening via `verify_commitment`. -- The commitment is per `(subject, schema_id)`. Submitting again overwrites the previous commitment. +### Credential Encoding +``` +credential_hash = SHA-256( + domain_separator (32 bytes) || + schema_id (4 bytes big-endian u32) || + subject_address (32 bytes) || + issuer_address (32 bytes) || + issued_at (8 bytes big-endian u64) || + expires_at (8 bytes big-endian u64) +) +``` +All field byte encodings are fixed-width big-endian values. Address values are converted into 32-byte fixed representation. Off-chain verifiers can reproduce this hash using the issuer's public key and credential metadata without querying Stellar. diff --git a/examples/gated-vault/test_snapshots/tests/test_deposit_accepts_kyc_wallet.1.json b/examples/gated-vault/test_snapshots/tests/test_deposit_accepts_kyc_wallet.1.json index e40d355..def5cfb 100644 --- a/examples/gated-vault/test_snapshots/tests/test_deposit_accepts_kyc_wallet.1.json +++ b/examples/gated-vault/test_snapshots/tests/test_deposit_accepts_kyc_wallet.1.json @@ -266,6 +266,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "3d5dbe74e7837eb6afa204db85c6c76e35f8f3b3abb3784c6993e2a6c0bbc27f" + } + }, { "key": { "symbol": "expires_at" diff --git a/examples/gated-vault/test_snapshots/tests/test_deposit_rejects_expired_kyc.1.json b/examples/gated-vault/test_snapshots/tests/test_deposit_rejects_expired_kyc.1.json index a889f27..a1d51ec 100644 --- a/examples/gated-vault/test_snapshots/tests/test_deposit_rejects_expired_kyc.1.json +++ b/examples/gated-vault/test_snapshots/tests/test_deposit_rejects_expired_kyc.1.json @@ -244,6 +244,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "f422469f9793572e848b9c83fa6c34410cdafe9034d9a71a72c8cfcb49148463" + } + }, { "key": { "symbol": "expires_at" diff --git a/examples/gated-vault/test_snapshots/tests/test_deposit_rejects_revoked_kyc.1.json b/examples/gated-vault/test_snapshots/tests/test_deposit_rejects_revoked_kyc.1.json index 7839a81..1918fbb 100644 --- a/examples/gated-vault/test_snapshots/tests/test_deposit_rejects_revoked_kyc.1.json +++ b/examples/gated-vault/test_snapshots/tests/test_deposit_rejects_revoked_kyc.1.json @@ -267,6 +267,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "3d5dbe74e7837eb6afa204db85c6c76e35f8f3b3abb3784c6993e2a6c0bbc27f" + } + }, { "key": { "symbol": "expires_at" diff --git a/examples/gated-vault/test_snapshots/tests/test_deposit_rejects_wrong_schema_credential.1.json b/examples/gated-vault/test_snapshots/tests/test_deposit_rejects_wrong_schema_credential.1.json index b674750..86c92d7 100644 --- a/examples/gated-vault/test_snapshots/tests/test_deposit_rejects_wrong_schema_credential.1.json +++ b/examples/gated-vault/test_snapshots/tests/test_deposit_rejects_wrong_schema_credential.1.json @@ -269,6 +269,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "f7fb1febaced306bf92c83b71adb6618ffd6bbe5f15433af3ad5edd50042da08" + } + }, { "key": { "symbol": "expires_at" diff --git a/examples/gated-vault/test_snapshots/tests/test_gated_vault_end_to_end.1.json b/examples/gated-vault/test_snapshots/tests/test_gated_vault_end_to_end.1.json index 662ac0b..f60c321 100644 --- a/examples/gated-vault/test_snapshots/tests/test_gated_vault_end_to_end.1.json +++ b/examples/gated-vault/test_snapshots/tests/test_gated_vault_end_to_end.1.json @@ -289,6 +289,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "3d5dbe74e7837eb6afa204db85c6c76e35f8f3b3abb3784c6993e2a6c0bbc27f" + } + }, { "key": { "symbol": "expires_at" diff --git a/examples/gated-vault/test_snapshots/tests/test_withdraw_with_valid_kyc.1.json b/examples/gated-vault/test_snapshots/tests/test_withdraw_with_valid_kyc.1.json index c8e4c19..e5b616c 100644 --- a/examples/gated-vault/test_snapshots/tests/test_withdraw_with_valid_kyc.1.json +++ b/examples/gated-vault/test_snapshots/tests/test_withdraw_with_valid_kyc.1.json @@ -288,6 +288,14 @@ "durability": "persistent", "val": { "map": [ + { + "key": { + "symbol": "credential_hash" + }, + "val": { + "bytes": "3d5dbe74e7837eb6afa204db85c6c76e35f8f3b3abb3784c6993e2a6c0bbc27f" + } + }, { "key": { "symbol": "expires_at"