extern crate indy; // Workaround to share some utils code based on indy sdk types between tests and indy sdk use indy::api as api; #[macro_use] extern crate serde_derive; #[macro_use] extern crate serde_json; #[macro_use] extern crate lazy_static; #[macro_use] extern crate log; #[macro_use] mod utils; #[cfg(feature = "local_nodes_pool")] use utils::pool::PoolUtils; use utils::test::TestUtils; use utils::timeout::TimeoutUtils; use indy::api::ErrorCode; use indy::api::anoncreds::{ indy_issuer_create_and_store_claim_def, indy_issuer_create_claim, indy_prover_create_master_secret, indy_prover_create_and_store_claim_req, indy_prover_store_claim, indy_prover_get_claims_for_proof_req, indy_prover_create_proof, indy_verifier_verify_proof }; #[cfg(feature = "local_nodes_pool")] use indy::api::ledger::{ indy_sign_and_submit_request, indy_submit_request, }; #[cfg(feature = "local_nodes_pool")] use indy::api::pool::{ indy_open_pool_ledger, indy_create_pool_ledger_config, }; use indy::api::wallet::{ indy_create_wallet, indy_open_wallet }; use indy::api::signus::{ indy_create_and_store_my_did, indy_sign, indy_verify_signature, indy_store_their_did }; use indy::api::agent::{ indy_agent_listen, indy_agent_add_identity, indy_agent_connect, indy_agent_send }; use utils::callback::CallbackUtils; use std::ptr::null; use std::sync::mpsc::channel; use std::ffi::CString; use utils::types::ProofClaimsJson; #[cfg(feature = "local_nodes_pool")] use std::thread; #[test] fn agent_demo_works() { TestUtils::cleanup_storage(); let endpoint = "127.0.0.1:9801"; let pool_name = "indy_agent_connect_works_for_remote_data"; let listener_wallet_name = "listener_wallet"; let trustee_wallet_name = "trustee_wallet"; let wallet_type = "default"; let c_pool_name = CString::new(pool_name).unwrap(); let (submit_sender, submit_receiver) = channel(); let (create_sender, create_receiver) = channel(); let (open_sender, open_receiver) = channel(); let (create_listener_wallet_sender, create_listener_wallet_receiver) = channel(); let (create_trustee_wallet_sender, create_trustee_wallet_receiver) = channel(); let (open_listener_wallet_sender, open_listener_wallet_receiver) = channel(); let (open_trustee_wallet_sender, open_trustee_wallet_receiver) = channel(); let (create_and_store_listener_did_sender, create_and_store_listener_did_receiver) = channel(); let (create_and_store_trustee_did_sender, create_and_store_trustee_did_receiver) = channel(); let (attrib_sender, attrib_receiver) = channel(); let (listen_sender, listen_receiver) = channel(); let (add_identity_sender, add_identity_receiver) = channel(); let (connect_sender, connect_receiver) = channel(); let (send_sender, send_receiver) = channel(); let create_cb = Box::new(move |err| { create_sender.send(err).unwrap(); }); let open_cb = Box::new(move |err, pool_handle| { open_sender.send((err, pool_handle)).unwrap(); }); let send_cb = Box::new(move |err, resp| { submit_sender.send((err, resp)).unwrap(); }); let create_listener_wallet_cb = Box::new(move |err| { create_listener_wallet_sender.send(err).unwrap(); }); let create_trustee_wallet_cb = Box::new(move |err| { create_trustee_wallet_sender.send(err).unwrap(); }); let open_listener_wallet_cb = Box::new(move |err, handle| { open_listener_wallet_sender.send((err, handle)).unwrap(); }); let open_trustee_wallet_cb = Box::new(move |err, handle| { open_trustee_wallet_sender.send((err, handle)).unwrap(); }); let create_and_store_listener_did_cb = Box::new(move |err, did, verkey, public_key| { create_and_store_listener_did_sender.send((err, did, verkey, public_key)).unwrap(); }); let create_and_store_trustee_did_cb = Box::new(move |err, did, verkey, public_key| { create_and_store_trustee_did_sender.send((err, did, verkey, public_key)).unwrap(); }); let listen_cb = Box::new(move |err, listener_handle| listen_sender.send((err, listener_handle)).unwrap()); let add_identity_cb = Box::new(move |err_code| add_identity_sender.send(err_code).unwrap()); let connect_cb = Box::new(move |err, connection_handle| { connect_sender.send((err, connection_handle)).unwrap(); }); let agent_send_cb = Box::new(move |err_code| send_sender.send(err_code).unwrap()); let (open_command_handle, open_callback) = CallbackUtils::closure_to_open_pool_ledger_cb(open_cb); let (create_command_handle, create_callback) = CallbackUtils::closure_to_create_pool_ledger_cb(create_cb); let (send_command_handle, send_callback) = CallbackUtils::closure_to_send_tx_cb(send_cb); let (create_listener_wallet_command_handle, create_listener_wallet_callback) = CallbackUtils::closure_to_create_wallet_cb(create_listener_wallet_cb); let (create_trustee_wallet_command_handle, create_trustee_wallet_callback) = CallbackUtils::closure_to_create_wallet_cb(create_trustee_wallet_cb); let (open_listener_wallet_command_handle, open_listener_wallet_callback) = CallbackUtils::closure_to_open_wallet_cb(open_listener_wallet_cb); let (open_trustee_wallet_command_handle, open_trustee_wallet_callback) = CallbackUtils::closure_to_open_wallet_cb(open_trustee_wallet_cb); let (create_and_store_listener_did_command_handle, create_and_store_listener_did_callback) = CallbackUtils::closure_to_create_and_store_my_did_cb(create_and_store_listener_did_cb); let (create_and_store_trustee_did_command_handle, create_and_store_trustee_did_callback) = CallbackUtils::closure_to_create_and_store_my_did_cb(create_and_store_trustee_did_cb); let (attrib_command_handle, attrib_callback) = CallbackUtils::closure_to_sign_and_submit_request_cb(Box::new(move |err, request_result_json| { attrib_sender.send((err, request_result_json)).unwrap(); })); let (listen_command_handle, listen_callback) = CallbackUtils::closure_to_agent_listen_cb(listen_cb); let (add_identity_command_handle, add_identity_cb) = CallbackUtils::closure_to_agent_add_identity_cb(add_identity_cb); let (connect_command_hamdle, connect_callback) = CallbackUtils::closure_to_agent_connect_cb(connect_cb); let (agent_send_command_handle, agent_send_callback) = CallbackUtils::closure_to_agent_send_cb(agent_send_cb); // 1. Create ledger config from genesis txn file PoolUtils::create_genesis_txn_file(format!("{}.txn", pool_name).as_str(), None); let pool_config = CString::new(PoolUtils::create_default_pool_config(pool_name)).unwrap(); let err = indy_create_pool_ledger_config(create_command_handle, c_pool_name.as_ptr(), pool_config.as_ptr(), create_callback); assert_eq!(err, ErrorCode::Success); let err = create_receiver.recv_timeout(TimeoutUtils::short_timeout()).unwrap(); assert_eq!(err, ErrorCode::Success); // 2. Open pool ledger let err = indy_open_pool_ledger(open_command_handle, c_pool_name.as_ptr(), null(), open_callback); assert_eq!(err, ErrorCode::Success); let (err, pool_handle) = open_receiver.recv_timeout(TimeoutUtils::short_timeout()).unwrap(); assert_eq!(err, ErrorCode::Success); thread::sleep(TimeoutUtils::short_timeout()); // 3. Create Listener Wallet let err = indy_create_wallet(create_listener_wallet_command_handle, c_pool_name.as_ptr(), CString::new(listener_wallet_name).unwrap().as_ptr(), CString::new(wallet_type).unwrap().as_ptr(), null(), null(), create_listener_wallet_callback); assert_eq!(ErrorCode::Success, err); let err = create_listener_wallet_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); assert_eq!(ErrorCode::Success, err); // 4. Open Listener Wallet. Gets My wallet handle let err = indy_open_wallet(open_listener_wallet_command_handle, CString::new(listener_wallet_name).unwrap().as_ptr(), null(), null(), open_listener_wallet_callback); assert_eq!(ErrorCode::Success, err); let (err, listener_wallet) = open_listener_wallet_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); assert_eq!(ErrorCode::Success, err); // 5. Create Their Wallet (trustee, sender) let err = indy_create_wallet(create_trustee_wallet_command_handle, CString::new(pool_name).unwrap().as_ptr(), CString::new(trustee_wallet_name).unwrap().as_ptr(), CString::new(wallet_type).unwrap().as_ptr(), null(), null(), create_trustee_wallet_callback); assert_eq!(ErrorCode::Success, err); let err = create_trustee_wallet_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); assert_eq!(ErrorCode::Success, err); // 6. Open Their Wallet. Gets Their wallet handle let err = indy_open_wallet(open_trustee_wallet_command_handle, CString::new(trustee_wallet_name).unwrap().as_ptr(), null(), null(), open_trustee_wallet_callback); assert_eq!(ErrorCode::Success, err); let (err, trustee_wallet) = open_trustee_wallet_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); assert_eq!(ErrorCode::Success, err); // 7. Create My DID let listener_did_json = "{}"; let err = indy_create_and_store_my_did(create_and_store_listener_did_command_handle, listener_wallet, CString::new(listener_did_json).unwrap().as_ptr(), create_and_store_listener_did_callback); assert_eq!(ErrorCode::Success, err); let (err, listener_did, listener_vk, listener_pk) = create_and_store_listener_did_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); info!("listener did {:?}", listener_did); info!("listener verkey {:?}", listener_vk); info!("listener pk {:?}", listener_pk); assert_eq!(ErrorCode::Success, err); let listener_did_c = CString::new(listener_did.clone()).unwrap(); // 8. Create Their DID from Trustee1 seed let trustee_did_json = r#"{"seed":"000000000000000000000000Trustee1"}"#; let err = indy_create_and_store_my_did(create_and_store_trustee_did_command_handle, trustee_wallet, CString::new(trustee_did_json).unwrap().as_ptr(), create_and_store_trustee_did_callback); assert_eq!(ErrorCode::Success, err); let (err, trustee_did, trustee_verkey, trustee_pk) = create_and_store_trustee_did_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); info!("sender (trustee) did {:?}", trustee_did); info!("sender (trustee) verkey {:?}", trustee_verkey); info!("sender (trustee) pk {:?}", trustee_pk); assert_eq!(ErrorCode::Success, err); let trustee_did_c = CString::new(trustee_did.clone()).unwrap(); // 9. Prepare NYM transaction let nym_req_id = PoolUtils::get_req_id(); let nym_txn_req = json!({ "identifier": trustee_did, "operation": { "dest": listener_did, "verkey": listener_vk, "type": "1", }, "reqId": nym_req_id, }); // 10. Send NYM request with signing let msg = serde_json::to_string(&nym_txn_req).unwrap(); let req = CString::new(msg).unwrap(); let err = indy_sign_and_submit_request(send_command_handle, pool_handle, trustee_wallet, trustee_did_c.as_ptr(), req.as_ptr(), send_callback); assert_eq!(err, ErrorCode::Success); let (err, _) = submit_receiver.recv_timeout(TimeoutUtils::medium_timeout()).unwrap(); assert_eq!(err, ErrorCode::Success); let sender_did = trustee_did.clone(); let sender_wallet = trustee_wallet; //10. Prepare and send attrib for listener (will be requested from ledger and used by sender at start connection) let req_id = PoolUtils::get_req_id(); let listener_attrib_json = json!({ "identifier": listener_did, "operation": { "dest": listener_did, "raw": format!("{{\"endpoint\":{{\"ha\":\"{}\", \"verkey\":\"{}\"}}}}", endpoint, listener_pk), "type": "100", }, "reqId": req_id }); let listener_attrib_json = serde_json::to_string(&listener_attrib_json).unwrap(); let listener_attrib_json = CString::new(listener_attrib_json).unwrap(); let err = indy_sign_and_submit_request(attrib_command_handle, pool_handle, listener_wallet, listener_did_c.as_ptr(), listener_attrib_json.as_ptr(), attrib_callback); assert_eq!(err, ErrorCode::Success); let (err, _) = attrib_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); assert_eq!(err, ErrorCode::Success); // 10. start listener on endpoint let (wait_msg_from_srv_send, wait_msg_from_srv_recv) = channel(); let on_msg = Box::new(move |conn_handle, err, msg| { info!("On connection {} received (with error {:?}) agent message (CLI->SRV): {}", conn_handle, err, msg); wait_msg_from_srv_send.send(msg).unwrap(); }); let (on_msg_cb_id, on_msg_callback) = CallbackUtils::closure_to_agent_message_cb(on_msg); let on_connect_cb = Box::new(move |listener_handle, err, conn_handle, sender_did, receiver_did| { CallbackUtils::closure_map_ids(on_msg_cb_id, conn_handle); info!("New connection {} on listener {}, err {:?}, sender DID {}, receiver DID {}", conn_handle, listener_handle, err, sender_did, receiver_did); }); let (on_connect_cb_id, on_connect_callback) = CallbackUtils::closure_to_agent_connected_cb(on_connect_cb); let endpoint = CString::new(endpoint).unwrap(); let err = indy_agent_listen(listen_command_handle, endpoint.as_ptr(), listen_callback, on_connect_callback, on_msg_callback); assert_eq!(err, ErrorCode::Success); let (err, agent_listener_handle) = listen_receiver.recv_timeout(TimeoutUtils::short_timeout()).unwrap(); assert_eq!(err, ErrorCode::Success); CallbackUtils::closure_map_ids(on_connect_cb_id, agent_listener_handle); // 11. Allow listener accept incoming connection for specific DID (listener_did) let listener_did = CString::new(listener_did.clone()).unwrap(); let err = indy_agent_add_identity(add_identity_command_handle, agent_listener_handle, pool_handle, listener_wallet, listener_did.as_ptr(), add_identity_cb); assert_eq!(err, ErrorCode::Success); let err = add_identity_receiver.recv_timeout(TimeoutUtils::short_timeout()).unwrap(); assert_eq!(err, ErrorCode::Success); // 12. Initiate connection from sender to listener let (msg_cb_id, msg_callback) = CallbackUtils::closure_to_agent_message_cb(Box::new(move |conn_handle, err, msg| { info!("On connection {} received (with error {:?}) agent message (SRV->CLI): {}", conn_handle, err, msg); })); let sender_did = CString::new(sender_did).unwrap(); let err = indy_agent_connect(connect_command_hamdle, pool_handle, sender_wallet, sender_did.as_ptr(), listener_did.as_ptr(), connect_callback, msg_callback); assert_eq!(err, ErrorCode::Success); let (err, conn_handle_sender_to_listener) = connect_receiver.recv_timeout(TimeoutUtils::medium_timeout()).unwrap(); assert_eq!(err, ErrorCode::Success); CallbackUtils::closure_map_ids(msg_cb_id, conn_handle_sender_to_listener); // 13. Send test message from sender to listener let message = "msg_from_sender_to_listener"; let msg = CString::new(message).unwrap(); let res = indy_agent_send(agent_send_command_handle, conn_handle_sender_to_listener, msg.as_ptr(), agent_send_callback); assert_eq!(res, ErrorCode::Success); let res = send_receiver.recv_timeout(TimeoutUtils::medium_timeout()).unwrap(); assert_eq!(res, ErrorCode::Success); // 14. Check message received assert_eq!(wait_msg_from_srv_recv.recv_timeout(TimeoutUtils::short_timeout()).unwrap(), message); TestUtils::cleanup_storage(); } #[test] fn anoncreds_demo_works() { TestUtils::cleanup_storage(); let (create_wallet_sender, create_wallet_receiver) = channel(); let (open_wallet_sender, open_wallet_receiver) = channel(); let (issuer_create_claim_definition_sender, issuer_create_claim_definition_receiver) = channel(); // TODO: uncomment this for revocation part //let (issuer_create_and_store_revoc_reg_sender, issuer_create_and_store_revoc_reg_receiver) = channel(); let (prover_create_master_secret_sender, prover_create_master_secret_receiver) = channel(); let (prover_create_claim_req_sender, prover_create_claim_req_receiver) = channel(); let (issuer_create_claim_sender, issuer_create_claim_receiver) = channel(); let (prover_store_claim_sender, prover_store_claim_receiver) = channel(); let (prover_get_claims_for_proof_req_sender, prover_get_claims_for_proof_req_receiver) = channel(); let (prover_create_proof_sender, prover_create_proof_receiver) = channel(); let (verifier_verify_proof_sender, verifier_verify_proof_receiver) = channel(); let issuer_create_claim_definition_cb = Box::new(move |err, claim_def_json| { issuer_create_claim_definition_sender.send((err, claim_def_json)).unwrap(); }); let create_wallet_cb = Box::new(move |err| { create_wallet_sender.send(err).unwrap(); }); let open_wallet_cb = Box::new(move |err, handle| { open_wallet_sender.send((err, handle)).unwrap(); }); // TODO: uncomment this for revocation part // let issuer_create_and_store_revoc_reg_cb = Box::new(move |err, revoc_reg_json, revoc_reg_uuid| { // issuer_create_and_store_revoc_reg_sender.send((err, revoc_reg_json, revoc_reg_uuid)).unwrap(); // }); let prover_create_master_secret_cb = Box::new(move |err| { prover_create_master_secret_sender.send(err).unwrap(); }); let prover_create_claim_req_cb = Box::new(move |err, claim_req_json| { prover_create_claim_req_sender.send((err, claim_req_json)).unwrap(); }); let issuer_create_claim_cb = Box::new(move |err, revoc_reg_update_json, xclaim_json| { issuer_create_claim_sender.send((err, revoc_reg_update_json, xclaim_json)).unwrap(); }); let prover_store_claim_cb = Box::new(move |err| { prover_store_claim_sender.send(err).unwrap(); }); let prover_get_claims_for_proof_req_cb = Box::new(move |err, claims_json| { prover_get_claims_for_proof_req_sender.send((err, claims_json)).unwrap(); }); let prover_create_proof_cb = Box::new(move |err, proof_json| { prover_create_proof_sender.send((err, proof_json)).unwrap(); }); let verifier_verify_proof_cb = Box::new(move |err, valid| { verifier_verify_proof_sender.send((err, valid)).unwrap(); }); let (issuer_create_claim_definition_command_handle, create_claim_definition_callback) = CallbackUtils::closure_to_issuer_create_claim_definition_cb(issuer_create_claim_definition_cb); let (create_wallet_command_handle, create_wallet_callback) = CallbackUtils::closure_to_create_wallet_cb(create_wallet_cb); let (open_wallet_command_handle, open_wallet_callback) = CallbackUtils::closure_to_open_wallet_cb(open_wallet_cb); // TODO: uncomment this for revocation part // let (issuer_create_and_store_revoc_reg_command_handle, issuer_create_and_store_revoc_reg_callback) = CallbackUtils::closure_to_issuer_create_and_store_revoc_reg_cb(issuer_create_and_store_revoc_reg_cb); let (prover_create_master_secret_command_handle, prover_create_master_secret_callback) = CallbackUtils::closure_to_prover_create_master_secret_cb(prover_create_master_secret_cb); let (prover_create_claim_req_command_handle, prover_create_claim_req_callback) = CallbackUtils::closure_to_prover_create_claim_req_cb(prover_create_claim_req_cb); let (issuer_create_claim_command_handle, issuer_create_claim_callback) = CallbackUtils::closure_to_issuer_create_claim_cb(issuer_create_claim_cb); let (prover_store_claim_command_handle, prover_store_claim_callback) = CallbackUtils::closure_to_prover_store_claim_cb(prover_store_claim_cb); let (prover_get_claims_for_proof_req_handle, prover_get_claims_for_proof_req_callback) = CallbackUtils::closure_to_prover_get_claims_for_proof_req_cb(prover_get_claims_for_proof_req_cb); let (prover_create_proof_handle, prover_create_proof_callback) = CallbackUtils::closure_to_prover_create_proof_cb(prover_create_proof_cb); let (verifier_verify_proof_handle, verifier_verify_proof_callback) = CallbackUtils::closure_to_verifier_verify_proof_cb(verifier_verify_proof_cb); let pool_name = "pool1"; let wallet_name = "issuer_wallet1"; let xtype = "default"; //TODO CREATE ISSUER, PROVER, VERIFIER WALLETS //1. Create Wallet let err = indy_create_wallet(create_wallet_command_handle, CString::new(pool_name).unwrap().as_ptr(), CString::new(wallet_name).unwrap().as_ptr(), CString::new(xtype).unwrap().as_ptr(), null(), null(), create_wallet_callback); assert_eq!(ErrorCode::Success, err); let err = create_wallet_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); assert_eq!(ErrorCode::Success, err); //2. Open Issuer Wallet. Gets Issuer wallet handle let err = indy_open_wallet(open_wallet_command_handle, CString::new(wallet_name).unwrap().as_ptr(), null(), null(), open_wallet_callback); assert_eq!(ErrorCode::Success, err); let (err, wallet_handle) = open_wallet_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); assert_eq!(ErrorCode::Success, err); let schema_seq_no = 1; let issuer_did = "NcYxiDXkpYi6ov5FcYDi1e"; let schema = format!(r#"{{ "seqNo":{}, "data":{{ "name":"gvt", "version":"1.0", "keys":["age","sex","height","name"] }} }}"#, schema_seq_no); // 3. Issuer create Claim Definition for Schema let err = indy_issuer_create_and_store_claim_def(issuer_create_claim_definition_command_handle, wallet_handle, CString::new(issuer_did.clone()).unwrap().as_ptr(), CString::new(schema.clone()).unwrap().as_ptr(), null(), false, create_claim_definition_callback); assert_eq!(ErrorCode::Success, err); let (err, claim_def_json) = issuer_create_claim_definition_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); println!("claim_def_json {:?}", claim_def_json); assert_eq!(ErrorCode::Success, err); let master_secret_name = "master_secret"; // TODO: uncomment this for revocation part // // Issuer creates a revocation registry // let max_claim_num: i32 = 5; // // let err = indy_issuer_create_and_store_revoc_reg(issuer_create_and_store_revoc_reg_command_handle, // wallet_handle, // issuer_did, // schema_seq_no, // max_claim_num, // issuer_create_and_store_revoc_reg_callback); // assert_eq!(ErrorCode::Success, err); // let (err, revoc_reg_json, revoc_reg_uuid) = issuer_create_and_store_revoc_reg_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); // info!("revocation_reg_json: {:?}", revoc_reg_json); // assert_eq!(ErrorCode::Success, err); // // 5. Prover create Master Secret let err = indy_prover_create_master_secret(prover_create_master_secret_command_handle, wallet_handle, CString::new(master_secret_name).unwrap().as_ptr(), prover_create_master_secret_callback); assert_eq!(ErrorCode::Success, err); let err = prover_create_master_secret_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); assert_eq!(ErrorCode::Success, err); let prover_did = "BzfFCYk"; let claim_offer_json = format!(r#"{{"issuer_did":"NcYxiDXkpYi6ov5FcYDi1e","schema_seq_no":{}}}"#, schema_seq_no); // 6. Prover create Claim Request let err = indy_prover_create_and_store_claim_req(prover_create_claim_req_command_handle, wallet_handle, CString::new(prover_did).unwrap().as_ptr(), CString::new(claim_offer_json).unwrap().as_ptr(), CString::new(claim_def_json.clone()).unwrap().as_ptr(), CString::new(master_secret_name).unwrap().as_ptr(), prover_create_claim_req_callback); assert_eq!(ErrorCode::Success, err); let (err, claim_req_json) = prover_create_claim_req_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); info!("claim_req_json {:?}", claim_req_json); assert_eq!(ErrorCode::Success, err); let claim_json = r#"{ "sex":["male","5944657099558967239210949258394887428692050081607692519917050011144233115103"], "name":["Alex","1139481716457488690172217916278103335"], "height":["175","175"], "age":["28","28"] }"#; // 7. Issuer create Claim for Claim Request let err = indy_issuer_create_claim(issuer_create_claim_command_handle, wallet_handle, CString::new(claim_req_json).unwrap().as_ptr(), CString::new(claim_json).unwrap().as_ptr(), -1, -1, issuer_create_claim_callback); assert_eq!(ErrorCode::Success, err); let (err, _, xclaim_json) = issuer_create_claim_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); info!("xclaim_json {:?}", xclaim_json); assert_eq!(ErrorCode::Success, err); // 7. Prover process and store Claim let err = indy_prover_store_claim(prover_store_claim_command_handle, wallet_handle, CString::new(xclaim_json).unwrap().as_ptr(), prover_store_claim_callback); assert_eq!(ErrorCode::Success, err); let err = prover_store_claim_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); assert_eq!(ErrorCode::Success, err); let proof_req_json = format!(r#"{{ "nonce":"123432421212", "name":"proof_req_1", "version":"0.1", "requested_attrs":{{"attr1_uuid":{{"schema_seq_no":{},"name":"name"}}}}, "requested_predicates":{{"predicate1_uuid":{{"attr_name":"age","p_type":"GE","value":18}}}} }}"#, schema_seq_no); // 8. Prover gets Claims for Proof Request let err = indy_prover_get_claims_for_proof_req(prover_get_claims_for_proof_req_handle, wallet_handle, CString::new(proof_req_json.clone()).unwrap().as_ptr(), prover_get_claims_for_proof_req_callback); assert_eq!(ErrorCode::Success, err); let (err, claims_json) = prover_get_claims_for_proof_req_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); info!("claims_json {:?}", claims_json); assert_eq!(ErrorCode::Success, err); let claims: ProofClaimsJson = serde_json::from_str(&claims_json).unwrap(); let claims_for_attr_1 = claims.attrs.get("attr1_uuid").unwrap(); assert_eq!(1, claims_for_attr_1.len()); let claim = claims_for_attr_1[0].clone(); let requested_claims_json = format!(r#"{{ "self_attested_attributes":{{}}, "requested_attrs":{{"attr1_uuid":["{}",true]}}, "requested_predicates":{{"predicate1_uuid":"{}"}} }}"#, claim.claim_uuid, claim.claim_uuid); let schemas_json = format!(r#"{{"{}":{}}}"#, claim.claim_uuid, schema); let claim_defs_json = format!(r#"{{"{}":{}}}"#, claim.claim_uuid, claim_def_json); let revoc_regs_jsons = "{}"; // TODO: uncomment this for revocation part // let revoc_regs_jsons = format!("{{\"{}\":{}}}", claim.claim_uuid, revoc_reg_update_json); // 9. Prover create Proof for Proof Request let err = indy_prover_create_proof(prover_create_proof_handle, wallet_handle, CString::new(proof_req_json.clone()).unwrap().as_ptr(), CString::new(requested_claims_json).unwrap().as_ptr(), CString::new(schemas_json.clone()).unwrap().as_ptr(), CString::new(master_secret_name).unwrap().as_ptr(), CString::new(claim_defs_json.clone()).unwrap().as_ptr(), CString::new(revoc_regs_jsons.clone()).unwrap().as_ptr(), prover_create_proof_callback); assert_eq!(ErrorCode::Success, err); let (err, proof_json) = prover_create_proof_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); info!("proof_json {:?}", proof_json); assert_eq!(ErrorCode::Success, err); // 10. Verifier verify proof let err = indy_verifier_verify_proof(verifier_verify_proof_handle, CString::new(proof_req_json).unwrap().as_ptr(), CString::new(proof_json).unwrap().as_ptr(), CString::new(schemas_json).unwrap().as_ptr(), CString::new(claim_defs_json).unwrap().as_ptr(), CString::new(revoc_regs_jsons).unwrap().as_ptr(), verifier_verify_proof_callback); assert_eq!(ErrorCode::Success, err); let (err, result) = verifier_verify_proof_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); assert_eq!(ErrorCode::Success, err); assert!(result); TestUtils::cleanup_storage(); } #[test] #[cfg(feature = "local_nodes_pool")] fn ledger_demo_works() { TestUtils::cleanup_storage(); let my_wallet_name = "my_wallet2"; let their_wallet_name = "their_wallet3"; let wallet_type = "default"; let pool_name = "ledger_demo_works"; let c_pool_name = CString::new(pool_name).unwrap(); let (submit_sender, submit_receiver) = channel(); let (get_nym_sender, get_nym_receiver) = channel(); let (create_sender, create_receiver) = channel(); let (open_sender, open_receiver) = channel(); let (create_my_wallet_sender, create_my_wallet_receiver) = channel(); let (create_their_wallet_sender, create_their_wallet_receiver) = channel(); let (open_my_wallet_sender, open_my_wallet_receiver) = channel(); let (open_their_wallet_sender, open_their_wallet_receiver) = channel(); let (create_and_store_my_did_sender, create_and_store_my_did_receiver) = channel(); let (create_and_store_their_did_sender, create_and_store_their_did_receiver) = channel(); let (store_their_did_sender, store_their_did_receiver) = channel(); let create_cb = Box::new(move |err| { create_sender.send(err).unwrap(); }); let open_cb = Box::new(move |err, pool_handle| { open_sender.send((err, pool_handle)).unwrap(); }); let send_cb = Box::new(move |err, resp| { submit_sender.send((err, resp)).unwrap(); }); let get_nym_cb = Box::new(move |err, resp| { get_nym_sender.send((err, resp)).unwrap(); }); let create_my_wallet_cb = Box::new(move |err| { create_my_wallet_sender.send(err).unwrap(); }); let create_their_wallet_cb = Box::new(move |err| { create_their_wallet_sender.send(err).unwrap(); }); let open_my_wallet_cb = Box::new(move |err, handle| { open_my_wallet_sender.send((err, handle)).unwrap(); }); let open_their_wallet_cb = Box::new(move |err, handle| { open_their_wallet_sender.send((err, handle)).unwrap(); }); let create_and_store_my_did_cb = Box::new(move |err, did, verkey, public_key| { create_and_store_my_did_sender.send((err, did, verkey, public_key)).unwrap(); }); let create_and_store_their_did_cb = Box::new(move |err, did, verkey, public_key| { create_and_store_their_did_sender.send((err, did, verkey, public_key)).unwrap(); }); let store_their_did_cb = Box::new(move |err| { store_their_did_sender.send((err)).unwrap(); }); let (open_command_handle, open_callback) = CallbackUtils::closure_to_open_pool_ledger_cb(open_cb); let (create_command_handle, create_callback) = CallbackUtils::closure_to_create_pool_ledger_cb(create_cb); let (send_command_handle, send_callback) = CallbackUtils::closure_to_send_tx_cb(send_cb); let (get_nym_command_handle, get_nym_callback) = CallbackUtils::closure_to_send_tx_cb(get_nym_cb); let (create_my_wallet_command_handle, create_my_wallet_callback) = CallbackUtils::closure_to_create_wallet_cb(create_my_wallet_cb); let (create_their_wallet_command_handle, create_their_wallet_callback) = CallbackUtils::closure_to_create_wallet_cb(create_their_wallet_cb); let (open_my_wallet_command_handle, open_my_wallet_callback) = CallbackUtils::closure_to_open_wallet_cb(open_my_wallet_cb); let (open_their_wallet_command_handle, open_their_wallet_callback) = CallbackUtils::closure_to_open_wallet_cb(open_their_wallet_cb); let (create_and_store_my_did_command_handle, create_and_store_my_did_callback) = CallbackUtils::closure_to_create_and_store_my_did_cb(create_and_store_my_did_cb); let (create_and_store_their_did_command_handle, create_and_store_their_did_callback) = CallbackUtils::closure_to_create_and_store_my_did_cb(create_and_store_their_did_cb); let (store_their_did_command_handle, store_their_did_callback) = CallbackUtils::closure_to_store_their_did_cb(store_their_did_cb); // 1. Create ledger config from genesis txn file PoolUtils::create_genesis_txn_file(format!("{}.txn", pool_name).as_str(), None); let pool_config = CString::new(PoolUtils::create_default_pool_config(pool_name)).unwrap(); let err = indy_create_pool_ledger_config(create_command_handle, c_pool_name.as_ptr(), pool_config.as_ptr(), create_callback); assert_eq!(err, ErrorCode::Success); let err = create_receiver.recv_timeout(TimeoutUtils::short_timeout()).unwrap(); assert_eq!(err, ErrorCode::Success); // 2. Open pool ledger let err = indy_open_pool_ledger(open_command_handle, c_pool_name.as_ptr(), null(), open_callback); assert_eq!(err, ErrorCode::Success); let (err, pool_handle) = open_receiver.recv_timeout(TimeoutUtils::short_timeout()).unwrap(); assert_eq!(err, ErrorCode::Success); thread::sleep(TimeoutUtils::short_timeout()); // 3. Create My Wallet let err = indy_create_wallet(create_my_wallet_command_handle, CString::new(pool_name).unwrap().as_ptr(), CString::new(my_wallet_name).unwrap().as_ptr(), CString::new(wallet_type).unwrap().as_ptr(), null(), null(), create_my_wallet_callback); assert_eq!(ErrorCode::Success, err); let err = create_my_wallet_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); assert_eq!(ErrorCode::Success, err); // 4. Open My Wallet. Gets My wallet handle let err = indy_open_wallet(open_my_wallet_command_handle, CString::new(my_wallet_name).unwrap().as_ptr(), null(), null(), open_my_wallet_callback); assert_eq!(ErrorCode::Success, err); let (err, my_wallet_handle) = open_my_wallet_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); assert_eq!(ErrorCode::Success, err); // 5. Create Their Wallet let err = indy_create_wallet(create_their_wallet_command_handle, CString::new(pool_name).unwrap().as_ptr(), CString::new(their_wallet_name).unwrap().as_ptr(), CString::new(wallet_type).unwrap().as_ptr(), null(), null(), create_their_wallet_callback); assert_eq!(ErrorCode::Success, err); let err = create_their_wallet_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); assert_eq!(ErrorCode::Success, err); // 6. Open Their Wallet. Gets Their wallet handle let err = indy_open_wallet(open_their_wallet_command_handle, CString::new(their_wallet_name).unwrap().as_ptr(), null(), null(), open_their_wallet_callback); assert_eq!(ErrorCode::Success, err); let (err, their_wallet_handle) = open_their_wallet_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); assert_eq!(ErrorCode::Success, err); // 7. Create My DID let my_did_json = "{}"; let err = indy_create_and_store_my_did(create_and_store_my_did_command_handle, my_wallet_handle, CString::new(my_did_json).unwrap().as_ptr(), create_and_store_my_did_callback); assert_eq!(ErrorCode::Success, err); let (err, my_did, my_verkey, my_pk) = create_and_store_my_did_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); info!("did {:?}", my_did); info!("verkey {:?}", my_verkey); info!("pk {:?}", my_pk); assert_eq!(ErrorCode::Success, err); // 8. Create Their DID from Trustee1 seed let their_did_json = r#"{"seed":"000000000000000000000000Trustee1"}"#; let err = indy_create_and_store_my_did(create_and_store_their_did_command_handle, their_wallet_handle, CString::new(their_did_json).unwrap().as_ptr(), create_and_store_their_did_callback); assert_eq!(ErrorCode::Success, err); let (err, their_did, their_verkey, their_pk) = create_and_store_their_did_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); info!("their_did {:?}", their_did); info!("their_verkey {:?}", their_verkey); info!("their_pk {:?}", their_pk); assert_eq!(ErrorCode::Success, err); // 9. Store Their DID let their_identity_json = format!(r#"{{"did":"{}", "pk":"{}", "verkey":"{}" }}"#, their_did, their_pk, their_verkey); let err = indy_store_their_did(store_their_did_command_handle, my_wallet_handle, CString::new(their_identity_json).unwrap().as_ptr(), store_their_did_callback); assert_eq!(ErrorCode::Success, err); let err = store_their_did_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); assert_eq!(ErrorCode::Success, err); // 10. Prepare NYM transaction let nym_req_id = PoolUtils::get_req_id(); let nym_txn_req = Request { identifier: their_did.clone(), operation: Operation { dest: my_did.clone(), type_: "1".to_string(), }, req_id: nym_req_id, signature: None, }; // 11. Send NYM request with signing let msg = serde_json::to_string(&nym_txn_req).unwrap(); let req = CString::new(msg).unwrap(); let did_for_sign = CString::new(their_did).unwrap(); let err = indy_sign_and_submit_request(send_command_handle, pool_handle, their_wallet_handle, did_for_sign.as_ptr(), req.as_ptr(), send_callback); assert_eq!(err, ErrorCode::Success); let (err, resp) = submit_receiver.recv_timeout(TimeoutUtils::medium_timeout()).unwrap(); assert_eq!(err, ErrorCode::Success); let nym_resp: Reply = serde_json::from_str(&resp).unwrap(); info!("nym_resp_raw : {:?}", resp); info!("nym_resp : {:?}", nym_resp); // 12. Prepare and send GET_NYM request let get_nym_req_id = PoolUtils::get_req_id(); let get_nym_txn = Request { req_id: get_nym_req_id, signature: None, identifier: my_verkey.clone(), operation: Operation { type_: "105".to_string(), dest: my_did.clone(), }, }; let request = serde_json::to_string(&get_nym_txn).unwrap(); let req = CString::new(request).unwrap(); let err = indy_submit_request(get_nym_command_handle, pool_handle, req.as_ptr(), get_nym_callback); assert_eq!(err, ErrorCode::Success); let (err, resp) = get_nym_receiver.recv_timeout(TimeoutUtils::medium_timeout()).unwrap(); assert_eq!(err, ErrorCode::Success); let get_nym_resp: Reply = serde_json::from_str(&resp).unwrap(); let get_nym_resp_data: ReplyResultData = serde_json::from_str(&get_nym_resp.result.data.as_ref().unwrap()).unwrap(); info!("get_nym_resp {:?}\n{:?}\n{:?}", resp, get_nym_resp, get_nym_resp_data); assert_eq!(get_nym_resp_data.dest, my_did); TestUtils::cleanup_storage(); #[derive(Serialize, Eq, PartialEq, Debug)] #[serde(rename_all = "camelCase")] struct Request { req_id: u64, identifier: String, operation: Operation, #[serde(skip_serializing_if = "Option::is_none")] signature: Option, } #[derive(Serialize, Eq, PartialEq, Debug)] struct Operation { #[serde(rename = "type")] type_: String, dest: String, } #[derive(Deserialize, Eq, PartialEq, Debug)] struct Reply { op: String, result: ReplyResult, } #[derive(Deserialize, Eq, PartialEq, Debug)] #[serde(rename_all = "camelCase")] struct ReplyResult { identifier: String, req_id: u64, data: Option } #[derive(Deserialize, Eq, PartialEq, Debug)] #[serde(rename_all = "camelCase")] struct ReplyResultData { dest: String, identifier: String, role: Option, } } #[test] fn signus_demo_works() { TestUtils::cleanup_storage(); let (create_my_wallet_sender, create_my_wallet_receiver) = channel(); let (create_their_wallet_sender, create_their_wallet_receiver) = channel(); let (open_my_wallet_sender, open_my_wallet_receiver) = channel(); let (open_their_wallet_sender, open_their_wallet_receiver) = channel(); let (create_and_store_my_did_sender, create_and_store_my_did_receiver) = channel(); let (create_and_store_their_did_sender, create_and_store_their_did_receiver) = channel(); let (store_their_did_sender, store_their_did_receiver) = channel(); let (sign_sender, sign_receiver) = channel(); let (verify_sender, verify_receiver) = channel(); let create_my_wallet_cb = Box::new(move |err| { create_my_wallet_sender.send(err).unwrap(); }); let create_their_wallet_cb = Box::new(move |err| { create_their_wallet_sender.send(err).unwrap(); }); let open_my_wallet_cb = Box::new(move |err, handle| { open_my_wallet_sender.send((err, handle)).unwrap(); }); let open_their_wallet_cb = Box::new(move |err, handle| { open_their_wallet_sender.send((err, handle)).unwrap(); }); let create_and_store_my_did_cb = Box::new(move |err, did, verkey, public_key| { create_and_store_my_did_sender.send((err, did, verkey, public_key)).unwrap(); }); let create_and_store_their_did_cb = Box::new(move |err, did, verkey, public_key| { create_and_store_their_did_sender.send((err, did, verkey, public_key)).unwrap(); }); let sign_cb = Box::new(move |err, signature| { sign_sender.send((err, signature)).unwrap(); }); let store_their_did_cb = Box::new(move |err| { store_their_did_sender.send((err)).unwrap(); }); let verify_cb = Box::new(move |err, valid| { verify_sender.send((err, valid)).unwrap(); }); let (create_my_wallet_command_handle, create_my_wallet_callback) = CallbackUtils::closure_to_create_wallet_cb(create_my_wallet_cb); let (create_their_wallet_command_handle, create_their_wallet_callback) = CallbackUtils::closure_to_create_wallet_cb(create_their_wallet_cb); let (open_my_wallet_command_handle, open_my_wallet_callback) = CallbackUtils::closure_to_open_wallet_cb(open_my_wallet_cb); let (open_their_wallet_command_handle, open_their_wallet_callback) = CallbackUtils::closure_to_open_wallet_cb(open_their_wallet_cb); let (create_and_store_my_did_command_handle, create_and_store_my_did_callback) = CallbackUtils::closure_to_create_and_store_my_did_cb(create_and_store_my_did_cb); let (create_and_store_their_did_command_handle, create_and_store_their_did_callback) = CallbackUtils::closure_to_create_and_store_my_did_cb(create_and_store_their_did_cb); let (store_their_did_command_handle, store_their_did_callback) = CallbackUtils::closure_to_store_their_did_cb(store_their_did_cb); let (sign_command_handle, sign_callback) = CallbackUtils::closure_to_sign_cb(sign_cb); let (verify_command_handle, verify_callback) = CallbackUtils::closure_to_verify_signature_cb(verify_cb); let pool_name = "pool1"; let my_wallet_name = "my_wallet4"; let their_wallet_name = "their_wallet5"; let xtype = "default"; //TODO CREATE ISSUER, PROVER, VERIFIER WALLETS //1. Create My Wallet let err = indy_create_wallet(create_my_wallet_command_handle, CString::new(pool_name).unwrap().as_ptr(), CString::new(my_wallet_name).unwrap().as_ptr(), CString::new(xtype).unwrap().as_ptr(), null(), null(), create_my_wallet_callback); assert_eq!(ErrorCode::Success, err); let err = create_my_wallet_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); assert_eq!(ErrorCode::Success, err); //2. Open My Wallet. Gets My wallet handle let err = indy_open_wallet(open_my_wallet_command_handle, CString::new(my_wallet_name).unwrap().as_ptr(), null(), null(), open_my_wallet_callback); assert_eq!(ErrorCode::Success, err); let (err, my_wallet_handle) = open_my_wallet_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); assert_eq!(ErrorCode::Success, err); //3. Create Their Wallet let err = indy_create_wallet(create_their_wallet_command_handle, CString::new(pool_name).unwrap().as_ptr(), CString::new(their_wallet_name).unwrap().as_ptr(), CString::new(xtype).unwrap().as_ptr(), null(), null(), create_their_wallet_callback); assert_eq!(ErrorCode::Success, err); let err = create_their_wallet_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); assert_eq!(ErrorCode::Success, err); //4. Open Their Wallet. Gets Their wallet handle let err = indy_open_wallet(open_their_wallet_command_handle, CString::new(their_wallet_name).unwrap().as_ptr(), null(), null(), open_their_wallet_callback); assert_eq!(ErrorCode::Success, err); let (err, their_wallet_handle) = open_their_wallet_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); assert_eq!(ErrorCode::Success, err); // 5. Create My DID let my_did_json = "{}"; let err = indy_create_and_store_my_did(create_and_store_my_did_command_handle, my_wallet_handle, CString::new(my_did_json).unwrap().as_ptr(), create_and_store_my_did_callback); assert_eq!(ErrorCode::Success, err); let (err, my_did, my_verkey, my_pk) = create_and_store_my_did_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); info!("did {:?}", my_did); info!("verkey {:?}", my_verkey); info!("pk {:?}", my_pk); assert_eq!(ErrorCode::Success, err); // 6. Create Their DID let their_did_json = "{}"; let err = indy_create_and_store_my_did(create_and_store_their_did_command_handle, their_wallet_handle, CString::new(their_did_json).unwrap().as_ptr(), create_and_store_their_did_callback); assert_eq!(ErrorCode::Success, err); let (err, their_did, their_verkey, their_pk) = create_and_store_their_did_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); info!("their_did {:?}", their_did); info!("their_verkey {:?}", their_verkey); info!("their_pk {:?}", their_pk); assert_eq!(ErrorCode::Success, err); // 7. Store Their DID let their_identity_json = format!(r#"{{"did":"{}", "pk":"{}", "verkey":"{}" }}"#, their_did, their_pk, their_verkey); let err = indy_store_their_did(store_their_did_command_handle, my_wallet_handle, CString::new(their_identity_json).unwrap().as_ptr(), store_their_did_callback); assert_eq!(ErrorCode::Success, err); let err = store_their_did_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); assert_eq!(ErrorCode::Success, err); // 8. Their Sign message let message = r#"{ "reqId":1495034346617224651, "identifier":"GJ1SzoWzavQYfNL9XkaJdrQejfztN4XqdsiV4ct3LXKL", "operation":{ "type":"1", "dest":"4efZu2SXufS556yss7W5k6Po37jt4371RM4whbPKBKdB" } }"#; let err = indy_sign(sign_command_handle, their_wallet_handle, CString::new(their_did.clone()).unwrap().as_ptr(), CString::new(message.clone()).unwrap().as_ptr(), sign_callback); assert_eq!(ErrorCode::Success, err); let (err, signed_msg) = sign_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); info!("signature {:?}", signed_msg); assert_eq!(ErrorCode::Success, err); // 9. I Verify message let err = indy_verify_signature(verify_command_handle, my_wallet_handle, 1, CString::new(their_did).unwrap().as_ptr(), CString::new(signed_msg).unwrap().as_ptr(), verify_callback); assert_eq!(ErrorCode::Success, err); let (err, valid) = verify_receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap(); info!("{:?}", err); assert!(valid); assert_eq!(ErrorCode::Success, err); TestUtils::cleanup_storage(); }