Skip to content

Commit

Permalink
Merge pull request hyperledger-archives#6 from mirgee/anoncreds-1.0-r…
Browse files Browse the repository at this point in the history
…ev-aries

Add revocation to libvcx V3
  • Loading branch information
baegjae authored May 25, 2020
2 parents 8753e8e + 8035f3b commit 44d67fb
Show file tree
Hide file tree
Showing 10 changed files with 963 additions and 880 deletions.
1,706 changes: 859 additions & 847 deletions vcx/libvcx/Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion vcx/libvcx/src/issuer_credential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -812,7 +812,7 @@ pub fn revoke_credential(handle: u32) -> VcxResult<()> {
match obj {
IssuerCredentials::Pending(ref mut obj) => obj.revoke_cred(),
IssuerCredentials::V1(ref mut obj) => obj.revoke_cred(),
IssuerCredentials::V3(_) => Err(VcxError::from(VcxErrorKind::NotReady)), // TODO: implement
IssuerCredentials::V3(ref mut obj) => obj.revoke_credential()
}
})
}
Expand Down
12 changes: 6 additions & 6 deletions vcx/libvcx/src/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,12 +474,12 @@ pub fn create_proof(source_id: String,
requested_predicates: String,
revocation_details: String,
name: String) -> VcxResult<u32> {
// // Initiate proof of new format -- redirect to v3 folder
// if settings::is_aries_protocol_set() {
// let verifier = Verifier::create(source_id, requested_attrs, requested_predicates, revocation_details, name)?;
// return PROOF_MAP.add(Proofs::V3(verifier))
// .or(Err(VcxError::from(VcxErrorKind::CreateProof)));
// }
// Initiate proof of new format -- redirect to v3 folder
if settings::is_aries_protocol_set() {
let verifier = Verifier::create(source_id, requested_attrs, requested_predicates, revocation_details, name)?;
return PROOF_MAP.add(Proofs::V3(verifier))
.or(Err(VcxError::from(VcxErrorKind::CreateProof)));
}

trace!("create_proof >>> source_id: {}, requested_attrs: {}, requested_predicates: {}, name: {}", source_id, requested_attrs, requested_predicates, name);

Expand Down
13 changes: 7 additions & 6 deletions vcx/libvcx/src/v3/handlers/issuance/holder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,13 +141,13 @@ impl HolderSM {
CredentialIssuanceMessage::Credential(credential) => {
let result = _store_credential(&credential, &state_data.req_meta, &state_data.cred_def_json);
match result {
Ok(cred_id) => {
Ok((cred_id, rev_reg_def_json)) => {
if credential.please_ack.is_some() {
let ack = CredentialAck::create().set_thread_id(&thread_id);
connection::send_message(state_data.connection_handle, A2AMessage::CredentialAck(ack))?;
}

HolderState::Finished((state_data, cred_id, credential).into())
HolderState::Finished((state_data, cred_id, credential, rev_reg_def_json).into())
}
Err(err) => {
let problem_report = ProblemReport::create()
Expand Down Expand Up @@ -235,7 +235,7 @@ fn _parse_rev_reg_id_from_credential(credential: &str) -> VcxResult<Option<Strin
}

fn _store_credential(credential: &Credential,
req_meta: &str, cred_def_json: &str) -> VcxResult<String> {
req_meta: &str, cred_def_json: &str) -> VcxResult<(String, Option<String>)> {
trace!("Holder::_store_credential >>>");

let credential_json = credential.credentials_attach.content()?;
Expand All @@ -247,11 +247,12 @@ fn _store_credential(credential: &Credential,
None
};

libindy_prover_store_credential(None,
let cred_id = libindy_prover_store_credential(None,
req_meta,
&credential_json,
cred_def_json,
rev_reg_def_json.as_ref().map(String::as_str))
rev_reg_def_json.as_ref().map(String::as_str))?;
Ok((cred_id, rev_reg_def_json))
}

fn _delete_credential(cred_id: &str) -> VcxResult<()> {
Expand Down Expand Up @@ -551,4 +552,4 @@ mod test {
assert_eq!(VcxStateType::VcxStateAccepted as u32, _holder_sm().to_finished_state().state());
}
}
}
}
31 changes: 23 additions & 8 deletions vcx/libvcx/src/v3/handlers/issuance/issuer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use v3::messages::issuance::credential::Credential;
use v3::messages::error::ProblemReport;
use v3::messages::mime_type::MimeType;
use error::{VcxResult, VcxError, VcxErrorKind};
use utils::libindy::anoncreds::{self, libindy_issuer_create_credential_offer};
use utils::libindy::anoncreds::{self, libindy_issuer_create_credential_offer, revoke_credential};
use issuer_credential::encode_attributes;
use v3::messages::status::Status;
use std::collections::HashMap;
Expand Down Expand Up @@ -40,6 +40,20 @@ impl IssuerSM {
}
}

pub fn revoke(&self) -> VcxResult<()> {
match &self.state {
IssuerState::Finished(state) => {
if let (Some(cred_rev_id), Some(rev_reg_id), Some(tails_file)) = (&state.cred_rev_id, &state.rev_reg_id, &state.tails_file) {
revoke_credential(&tails_file, &rev_reg_id, &cred_rev_id)?;
Ok(())
} else {
Err(VcxError::from(VcxErrorKind::InvalidRevocationDetails))
}
},
_ => Err(VcxError::from(VcxErrorKind::NotReady))
}
}

pub fn get_connection_handle(&self) -> u32 {
self.state.get_connection_handle()
}
Expand Down Expand Up @@ -176,10 +190,10 @@ impl IssuerSM {
CredentialIssuanceMessage::CredentialSend() => {
let credential_msg = _create_credential(&state_data.request, &state_data.rev_reg_id, &state_data.tails_file, &state_data.offer, &state_data.cred_data);
match credential_msg {
Ok(credential_msg) => {
Ok((credential_msg, cred_rev_id)) => {
let credential_msg = credential_msg.set_thread_id(&state_data.thread_id);
send_message(state_data.connection_handle, credential_msg.to_a2a_message())?;
IssuerState::Finished(state_data.into())
IssuerState::Finished((state_data, cred_rev_id).into())
}
Err(err) => {
let problem_report = ProblemReport::create()
Expand Down Expand Up @@ -259,20 +273,21 @@ fn _append_credential_preview(cred_offer_msg: CredentialOffer, credential_json:
Ok(new_offer)
}

fn _create_credential(request: &CredentialRequest, rev_reg_id: &Option<String>, tails_file: &Option<String>, offer: &str, cred_data: &str) -> VcxResult<Credential> {
fn _create_credential(request: &CredentialRequest, rev_reg_id: &Option<String>, tails_file: &Option<String>, offer: &str, cred_data: &str) -> VcxResult<(Credential, Option<String>)> {
trace!("Issuer::_create_credential >>> request: {:?}, rev_reg_id: {:?}, tails_file: {:?}, offer: {:?}, cred_data: {:?}", request, rev_reg_id, tails_file, offer, cred_data);

let request = &request.requests_attach.content()?;

let cred_data = encode_attributes(cred_data)?;

let (credential, _, _) = anoncreds::libindy_issuer_create_credential(offer,
let (ser_credential, cred_rev_id, _) = anoncreds::libindy_issuer_create_credential(offer,
&request,
&cred_data,
rev_reg_id.clone(),
tails_file.clone())?;
Credential::create()
.set_credential(credential)
let credential = Credential::create().set_credential(ser_credential)?;

Ok((credential, cred_rev_id))
}

#[cfg(test)]
Expand Down Expand Up @@ -622,4 +637,4 @@ pub mod test {
assert_eq!(VcxStateType::VcxStateAccepted as u32, _issuer_sm().to_finished_state().state());
}
}
}
}
4 changes: 4 additions & 0 deletions vcx/libvcx/src/v3/handlers/issuance/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ impl Issuer {
Ok(self.issuer_sm.get_source_id())
}

pub fn revoke_credential(&self) -> VcxResult<()> {
self.issuer_sm.revoke()
}

pub fn update_status(&mut self, msg: Option<String>) -> VcxResult<()> {
match msg {
Some(msg) => {
Expand Down
39 changes: 34 additions & 5 deletions vcx/libvcx/src/v3/handlers/issuance/states.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,18 @@ pub struct RequestReceivedState {
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct CredentialSentState {
pub connection_handle: u32,
pub rev_reg_id: Option<String>,
pub tails_file: Option<String>,
pub thread_id: String
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct FinishedState {
pub cred_id: Option<String>,
pub thread_id: String,
pub cred_rev_id: Option<String>,
pub rev_reg_id: Option<String>,
pub tails_file: Option<String>,
pub status: Status
}

Expand All @@ -115,6 +120,9 @@ impl From<InitialState> for FinishedState {
FinishedState {
cred_id: None,
thread_id: String::new(),
cred_rev_id: None,
rev_reg_id: None,
tails_file: None,
status: Status::Undefined,
}
}
Expand All @@ -140,6 +148,8 @@ impl From<(RequestReceivedState, MessageId)> for CredentialSentState {
trace!("SM is now in CredentialSent state");
CredentialSentState {
connection_handle: state.connection_handle,
rev_reg_id: state.rev_reg_id,
tails_file: state.tails_file,
thread_id: state.thread_id,
}
}
Expand All @@ -151,6 +161,9 @@ impl From<OfferSentState> for FinishedState {
FinishedState {
cred_id: None,
thread_id: state.thread_id,
cred_rev_id: None,
rev_reg_id: state.rev_reg_id,
tails_file: state.tails_file,
status: Status::Undefined,
}
}
Expand All @@ -162,17 +175,23 @@ impl From<(OfferSentState, ProblemReport)> for FinishedState {
FinishedState {
cred_id: None,
thread_id: state.thread_id,
cred_rev_id: None,
rev_reg_id: state.rev_reg_id,
tails_file: state.tails_file,
status: Status::Failed(err),
}
}
}

impl From<RequestReceivedState> for FinishedState {
fn from(state: RequestReceivedState) -> Self {
impl From<(RequestReceivedState, Option<String>)> for FinishedState {
fn from((state, cred_rev_id): (RequestReceivedState, Option<String>)) -> Self {
trace!("SM is now in Finished state");
FinishedState {
cred_id: None,
thread_id: state.thread_id,
cred_rev_id: cred_rev_id,
rev_reg_id: state.rev_reg_id,
tails_file: state.tails_file,
status: Status::Success,
}
}
Expand All @@ -184,6 +203,9 @@ impl From<(RequestReceivedState, ProblemReport)> for FinishedState {
FinishedState {
cred_id: None,
thread_id: state.thread_id,
cred_rev_id: None,
rev_reg_id: state.rev_reg_id,
tails_file: state.tails_file,
status: Status::Failed(err),
}
}
Expand All @@ -195,6 +217,9 @@ impl From<CredentialSentState> for FinishedState {
FinishedState {
cred_id: None,
thread_id: state.thread_id,
cred_rev_id: None,
rev_reg_id: state.rev_reg_id,
tails_file: state.tails_file,
status: Status::Success,
}
}
Expand Down Expand Up @@ -243,6 +268,7 @@ pub struct FinishedHolderState {
pub cred_id: Option<String>,
pub credential: Option<Credential>,
pub status: Status,
pub rev_reg_def_json: Option<String>
}

impl From<(OfferReceivedState, String, String, u32)> for RequestSentState {
Expand All @@ -256,13 +282,14 @@ impl From<(OfferReceivedState, String, String, u32)> for RequestSentState {
}
}

impl From<(RequestSentState, String, Credential)> for FinishedHolderState {
fn from((_, cred_id, credential): (RequestSentState, String, Credential)) -> Self {
impl From<(RequestSentState, String, Credential, Option<String>)> for FinishedHolderState {
fn from((_, cred_id, credential, rev_reg_def_json): (RequestSentState, String, Credential, Option<String>)) -> Self {
trace!("SM is now in Finished state");
FinishedHolderState {
cred_id: Some(cred_id),
credential: Some(credential),
status: Status::Success,
rev_reg_def_json: rev_reg_def_json
}
}
}
Expand All @@ -274,6 +301,7 @@ impl From<(RequestSentState, ProblemReport)> for FinishedHolderState {
cred_id: None,
credential: None,
status: Status::Failed(problem_report),
rev_reg_def_json: None
}
}
}
Expand All @@ -285,6 +313,7 @@ impl From<(OfferReceivedState, ProblemReport)> for FinishedHolderState {
cred_id: None,
credential: None,
status: Status::Failed(problem_report),
rev_reg_def_json: None
}
}
}
}
13 changes: 9 additions & 4 deletions vcx/wrappers/node/demo/alice.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,11 @@ async function runAlice (options) {
}

logger.info('#22 Poll agency for a proof request')
const requests = await DisclosedProof.getRequests(connectionToFaber)

let requests = await DisclosedProof.getRequests(connectionToFaber)
while (requests.length === 0) {
await sleepPromise(2000)
requests = await DisclosedProof.getRequests(connectionToFaber)
}
logger.info('#23 Create a Disclosed proof object from proof request')
const proof = await DisclosedProof.create({ sourceId: 'proof', request: JSON.stringify(requests[0]) })

Expand All @@ -112,6 +115,7 @@ async function runAlice (options) {
credentials.attrs[attr] = {
credential: credentials.attrs[attr][0]
}
credentials.attrs[attr].tails_file = '/tmp/tails'
}

logger.info('#25 Generate the proof')
Expand All @@ -120,13 +124,14 @@ async function runAlice (options) {
logger.info('#26 Send the proof to faber')
await proof.sendProof(connectionToFaber)

logger.info('#27 Wait for Faber to receive the proof')
let proofState = await proof.getState()
while (proofState !== StateType.Accepted) {
while (proofState !== StateType.Accepted && proofState !== StateType.None) {
await sleepPromise(2000)
await proof.updateState()
proofState = await proof.getState()
}
logger.info('Proof is verified.')
logger.info('Faber received the proof')
process.exit(0)
}

Expand Down
22 changes: 19 additions & 3 deletions vcx/wrappers/node/demo/faber.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,10 @@ async function runFaber (options) {
const data = {
name: 'DemoCredential123',
paymentHandle: 0,
revocation: false,
revocationDetails: {
tailsFile: 'tails.txt'
supportRevocation: true,
tailsFile: '/tmp/tails',
maxCreds: 5
},
schemaId: schemaId,
sourceId: 'testCredentialDefSourceId123'
Expand Down Expand Up @@ -179,6 +180,10 @@ async function runFaber (options) {
}
]

if (options.revocation) {
logger.info('#18.5 Revoking credential')
await credentialForAlice.revokeCredential()
}
const proofPredicates = [
{ name: 'age', p_type: '>=', p_value: 20, restrictions: [{ issuer_did: agentProvision.institution_did }] }
]
Expand All @@ -197,7 +202,12 @@ async function runFaber (options) {

logger.info('#21 Poll agency and wait for alice to provide proof')
let proofState = await proof.getState()
const revokedState = options.revocation ? StateType.None : StateType.Revoked
while (proofState !== StateType.Accepted) {
if (proofState === revokedState) {
logger.info('Alice failed to provide proof, credential revoked')
process.exit(0)
}
await sleepPromise(2000)
await proof.updateState()
proofState = await proof.getState()
Expand All @@ -210,7 +220,7 @@ async function runFaber (options) {
if (proof.proofState === ProofState.Verified) {
logger.info('Proof is verified')
} else {
logger.info('Could not verify proof')
logger.info('Proof verification failed, credential revoked')
}
process.exit(0)
}
Expand All @@ -233,6 +243,12 @@ const optionDefinitions = [
type: Boolean,
description: 'If specified, postresql wallet will be used.',
defaultValue: false
},
{
name: 'revocation',
type: Boolean,
description: 'If specified, the issued credential will be revoked',
defaultValue: false
}
]

Expand Down
Loading

0 comments on commit 44d67fb

Please sign in to comment.