diff --git a/.github/actions/setup-testing-rust/action.yml b/.github/actions/setup-testing-rust/action.yml index 5809850d3c..01e7a5e7b3 100644 --- a/.github/actions/setup-testing-rust/action.yml +++ b/.github/actions/setup-testing-rust/action.yml @@ -6,6 +6,10 @@ inputs: description: 'If true, skip spinning up docker containers' required: false default: false + skip-vdrproxy-setup: + description: 'If true, skip spinning up vdrproxy' + required: false + default: true runs: using: "composite" @@ -27,3 +31,8 @@ runs: docker run --rm -d --name indypool --network host ${{ env.DOCKER_IMAGE_POOL }} sleep 5 docker-compose -f ./ci/agency/docker-compose.yml up -d + - name: "Start vdrproxy" + if: ${{ inputs.skip-vdrproxy-setup != 'true' }} + shell: bash + run: | + docker run --rm -d --name vdrproxy --network host ${{ env.DOCKER_IMAGE_VDRPROXY }} -p ${{ env.VDR_PROXY_PORT }} -g ${{ env.GENESIS_URL }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9feb290645..88a38a7183 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -18,6 +18,7 @@ env: DOCKER_REPO_LOCAL_ALPINE_CORE: alpine-core DOCKER_REPO_LOCAL_LIBVCX: libvcx DOCKER_REPO_LOCAL_ANDROID: android-test + DOCKER_REPO_LOCAL_VDRPROXY: vdrproxy RUST_TOOLCHAIN_VERSON: 1.65.0 NODE_VERSION: 18.x @@ -53,6 +54,7 @@ jobs: DOCKER_IMG_CACHED_ALPINE_CORE: ${{ steps.docker-imgs.outputs.DOCKER_IMG_CACHED_ALPINE_CORE }} DOCKER_IMG_CACHED_LIBVCX: ${{ steps.docker-imgs.outputs.DOCKER_IMG_CACHED_LIBVCX }} DOCKER_IMG_CACHED_ANDROID: ${{ steps.docker-imgs.outputs.DOCKER_IMG_CACHED_ANDROID }} + DOCKER_IMG_CACHED_VDRPROXY: ${{ steps.docker-imgs.outputs.DOCKER_IMG_CACHED_VDRPROXY }} steps: - name: "Git checkout" uses: actions/checkout@v1 @@ -72,6 +74,7 @@ jobs: HASH_DOCKERFILE_ALPINE_CORE=${{ hashFiles('ci/alpine_core.dockerfile')}} HASH_DOCKERFILE_LIBVCX=${{ hashFiles('ci/libvcx.dockerfile') }} + HASH_DOCKERFILE_VDRPROXY=${{ hashFiles('ci/vdrproxy.dockerfile') }} HASH_SRC_LIBVDRTOOLS=${{ hashFiles('libvdrtools') }} HASH_SRC_LIBVCX=${{ hashFiles('libvcx') }} HASH_SRC_ARIESVCX=${{ hashFiles('aries_vcx') }} @@ -79,10 +82,9 @@ jobs: HASH_SRC_AGENCYCLIENT=${{ hashFiles('agency_client') }} HASH_SRC_DIDDOC=${{ hashFiles('diddoc') }} HASH_SRC_MESSAGES=${{ hashFiles('messages') }} - HASH_SRC_MESSAGES_2=${{ hashFiles('messages2') }} HASH_SRC_WRAPPER_JAVA=${{ hashFiles('wrappers/java') }} - SEED_HASH_ARIESVCX=${HASH_SRC_LIBVDRTOOLS:0:11}-${HASH_SRC_ARIESVCX_CORE:0:11}-${HASH_SRC_ARIESVCX:0:11}-${HASH_SRC_AGENCYCLIENT:0:11}-${HASH_SRC_DIDDOC:0:11}-${HASH_SRC_MESSAGES:0:11}-${HASH_SRC_MESSAGES_2:0:11} + SEED_HASH_ARIESVCX=${HASH_SRC_LIBVDRTOOLS:0:11}-${HASH_SRC_ARIESVCX_CORE:0:11}-${HASH_SRC_ARIESVCX:0:11}-${HASH_SRC_AGENCYCLIENT:0:11}-${HASH_SRC_DIDDOC:0:11}-${HASH_SRC_MESSAGES:0:11}} HASH_ARIESVCX=$(echo -n "$SEED_HASH_ARIESVCX" | sha256sum | awk '{print $1}') SEED_HASH_DOCKER_LIBVCX=${HASH_ARIESVCX:0:11}-${HASH_DOCKERFILE_LIBVCX:0:11}-${HASH_SRC_LIBVCX:0:11} @@ -94,6 +96,7 @@ jobs: echo "DOCKER_IMG_CACHED_ALPINE_CORE=$DOCKER_REPO_LOCAL_ALPINE_CORE:$HASH_DOCKERFILE_ALPINE_CORE" >> $GITHUB_OUTPUT echo "DOCKER_IMG_CACHED_LIBVCX=$DOCKER_REPO_LOCAL_LIBVCX:$HASH_DOCKER_LIBVCX" >> $GITHUB_OUTPUT echo "DOCKER_IMG_CACHED_ANDROID=$DOCKER_REPO_LOCAL_ANDROID:$HASH_DOCKER_ANDROID" >> $GITHUB_OUTPUT + echo "DOCKER_IMG_CACHED_VDRPROXY=$DOCKER_REPO_LOCAL_VDRPROXY:$HASH_DOCKERFILE_VDRPROXY" >> $GITHUB_OUTPUT workflow-setup-check: runs-on: ubuntu-20.04 @@ -113,6 +116,7 @@ jobs: echo "DOCKER_IMG_CACHED_ALPINE_CORE ${{ needs.workflow-setup.outputs.DOCKER_IMG_CACHED_ALPINE_CORE }}" echo "DOCKER_IMG_CACHED_LIBVCX ${{ needs.workflow-setup.outputs.DOCKER_IMG_CACHED_LIBVCX }}" echo "DOCKER_IMG_CACHED_ANDROID ${{ needs.workflow-setup.outputs.DOCKER_IMG_CACHED_ANDROID }}" + echo "DOCKER_IMG_CACHED_VDRPROXY ${{ needs.workflow-setup.outputs.DOCKER_IMG_CACHED_VDRPROXY }}" clippy-aries-vcx: runs-on: ubuntu-20.04 @@ -171,6 +175,7 @@ jobs: cargo check --no-default-features cargo check --features vdrtools --no-default-features cargo check --features modular_libs --no-default-features + cargo check --features vdr_proxy_ledger --no-default-features ########################################################################################## ############################## DOCKER BUILD ########################################## @@ -256,6 +261,38 @@ jobs: branch-main: ${{ env.MAIN_BRANCH }} docker-repo-local-name: ${{ env.DOCKER_REPO_LOCAL_ANDROID }} + build-docker-vdrproxy: + needs: [ workflow-setup, build-docker-alpine-core ] + if: ${{ needs.workflow-setup.outputs.SKIP_CI != 'true' }} + runs-on: ubuntu-20.04 + env: + DOCKER_IMG_CACHED_ALPINE_CORE: ${{ needs.workflow-setup.outputs.DOCKER_IMG_CACHED_ALPINE_CORE }} + DOCKER_IMG_CACHED: ${{ needs.workflow-setup.outputs.DOCKER_IMG_CACHED_VDRPROXY }} + BRANCH_NAME: ${{ needs.workflow-setup.outputs.BRANCH_NAME }} + outputs: + image-name: ${{ steps.meta.outputs.tags }} + steps: + - name: "Git checkout" + uses: actions/checkout@v3 + - name: Login to GitHub Container Registry + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: "Load alpine core image" + uses: ./.github/actions/load-image + with: + docker-img: ${{ env.DOCKER_IMG_CACHED_ALPINE_CORE }} + - name: "Build and cache image" + uses: ./.github/actions/build-image + with: + docker-img: ${{ env.DOCKER_IMG_CACHED }} + dockerfile-path: "ci/vdrproxy.dockerfile" + build-arg: "ALPINE_CORE_IMAGE=$DOCKER_IMG_CACHED_ALPINE_CORE" + branch-name: ${{ env.BRANCH_NAME }} + branch-main: ${{ env.MAIN_BRANCH }} + docker-repo-local-name: ${{ env.DOCKER_REPO_LOCAL_VDRPROXY }} ########################################################################################## ############################## DOCKER PUBLISH ######################################## @@ -420,6 +457,29 @@ jobs: - name: "Run aries-vcx tests: mysql_test" run: RUST_TEST_THREADS=1 cargo test --manifest-path="aries_vcx/Cargo.toml" test_mysql -- --include-ignored; + test-integration-aries-vcx-vdrproxy: + needs: [workflow-setup, build-docker-vdrproxy] + runs-on: ubuntu-20.04 + env: + RUST_TEST_THREADS: 1 + VDR_PROXY_CLIENT_URL: http://127.0.0.1:3030 + DOCKER_IMAGE_VDRPROXY: ${{ needs.workflow-setup.outputs.DOCKER_IMG_CACHED_VDRPROXY }} + GENESIS_URL: https://raw.githubusercontent.com/AbsaOSS/sovrin-networks/master/genesis/127.0.0.1 + VDR_PROXY_PORT: 3030 + steps: + - name: "Git checkout" + uses: actions/checkout@v3 + - name: "Load android image" + uses: ./.github/actions/load-image + with: + docker-img: ${{ env.DOCKER_IMAGE_VDRPROXY }} + - name: "Setup rust testing environment" + uses: ./.github/actions/setup-testing-rust + with: + skip-vdrproxy-setup: false + - name: "Run aries-vcx tests: vdrproxy_test" + run: cargo test --manifest-path="aries_vcx/Cargo.toml" -F vdr_proxy_ledger -- --ignored + test-integration-libvcx: needs: workflow-setup if: ${{ needs.workflow-setup.outputs.SKIP_CI != 'true' }} diff --git a/Cargo.lock b/Cargo.lock index 7179666ba6..294c2a00bd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -243,6 +243,7 @@ dependencies = [ "futures", "indy-credx", "indy-vdr", + "indy-vdr-proxy-client", "lazy_static", "libvdrtools", "log", @@ -849,6 +850,15 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "cmake" +version = "0.1.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" +dependencies = [ + "cc", +] + [[package]] name = "codespan-reporting" version = "0.11.1" @@ -2393,6 +2403,17 @@ dependencies = [ "zmq", ] +[[package]] +name = "indy-vdr-proxy-client" +version = "0.1.0" +source = "git+https://github.com/mirgee/indy-vdr.git?rev=fab0535#fab0535832d87f8194cf49acc897ac6b004c38c4" +dependencies = [ + "indy-vdr", + "reqwest", + "serde_json", + "url", +] + [[package]] name = "indy-wallet" version = "0.1.0" @@ -3647,9 +3668,9 @@ checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" [[package]] name = "reqwest" -version = "0.11.16" +version = "0.11.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b71749df584b7f4cac2c426c127a7c785a5106cc98f7a8feb044115f0fa254" +checksum = "13293b639a097af28fc8a90f22add145a9c954e49d77da06263d58cf44d5fb91" dependencies = [ "base64 0.21.0", "bytes", @@ -5396,6 +5417,15 @@ dependencies = [ "syn 2.0.15", ] +[[package]] +name = "zeromq-src" +version = "0.1.10+4.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9133d366817fcffe22e4356043ba187ae122ec5db63d7ce73d1e6a18efa2f1" +dependencies = [ + "cmake", +] + [[package]] name = "zmq" version = "0.9.2" @@ -5416,4 +5446,5 @@ checksum = "d33a2c51dde24d5b451a2ed4b488266df221a5eaee2ee519933dc46b9a9b3648" dependencies = [ "libc", "metadeps", + "zeromq-src", ] diff --git a/aries_vcx/Cargo.toml b/aries_vcx/Cargo.toml index 2c4ea0bf18..4ac2b0c9d3 100644 --- a/aries_vcx/Cargo.toml +++ b/aries_vcx/Cargo.toml @@ -15,7 +15,9 @@ default = ["vdrtools"] vdrtools = ["aries_vcx_core/vdrtools"] # Feature flag to include the 'modular library' dependencies (vdrtools alternatives; indy-vdr, indy-credx) modular_libs = ["aries_vcx_core/modular_libs"] - +# TODO: Remove using "vdrtools" feature flag for vdr_proxy_ledger once IndyCredxAnonCreds +# is fully implemented +vdr_proxy_ledger = ["aries_vcx_core/vdr_proxy_ledger", "vdrtools"] [dependencies] agency_client = { path = "../agency_client" } diff --git a/aries_vcx/src/common/keys.rs b/aries_vcx/src/common/keys.rs index 47452f1936..22f4bed3d8 100644 --- a/aries_vcx/src/common/keys.rs +++ b/aries_vcx/src/common/keys.rs @@ -84,6 +84,7 @@ mod test { #[tokio::test] #[ignore] + #[cfg(not(feature = "vdr_proxy_ledger"))] async fn test_pool_rotate_verkey_fails() { SetupProfile::run_indy(|setup| async move { enable_pool_mocks(); diff --git a/aries_vcx/src/common/ledger/transactions.rs b/aries_vcx/src/common/ledger/transactions.rs index 94f32ec0cb..864046692e 100644 --- a/aries_vcx/src/common/ledger/transactions.rs +++ b/aries_vcx/src/common/ledger/transactions.rs @@ -80,9 +80,10 @@ pub async fn add_new_did( let ledger = Arc::clone(profile).inject_ledger(); - ledger + let res = ledger .publish_nym(submitter_did, &did, Some(&verkey), None, role) .await?; + check_response(&res)?; Ok((did, verkey)) } diff --git a/aries_vcx/src/common/primitives/credential_definition.rs b/aries_vcx/src/common/primitives/credential_definition.rs index c3db10c061..cfbd6481c7 100644 --- a/aries_vcx/src/common/primitives/credential_definition.rs +++ b/aries_vcx/src/common/primitives/credential_definition.rs @@ -292,7 +292,7 @@ pub mod integration_tests { let ledger = Arc::clone(&setup.profile).inject_ledger(); let schema_json = ledger.get_schema(&schema_id, None).await.unwrap(); - let (_, cred_def_json) = generate_cred_def( + let (cred_def_id, cred_def_json_local) = generate_cred_def( &setup.profile, &setup.institution_did, &schema_json, @@ -304,9 +304,19 @@ pub mod integration_tests { .unwrap(); ledger - .publish_cred_def(&cred_def_json, &setup.institution_did) + .publish_cred_def(&cred_def_json_local, &setup.institution_did) + .await + .unwrap(); + + std::thread::sleep(std::time::Duration::from_secs(2)); + + let cred_def_json_ledger = ledger + .get_cred_def(&cred_def_id, Some(&setup.institution_did)) .await .unwrap(); + + assert!(cred_def_json_local.contains(&cred_def_id)); + assert!(cred_def_json_ledger.contains(&cred_def_id)); }) .await; } diff --git a/aries_vcx/src/common/primitives/mod.rs b/aries_vcx/src/common/primitives/mod.rs index 74878fac6a..4220c19fbd 100644 --- a/aries_vcx/src/common/primitives/mod.rs +++ b/aries_vcx/src/common/primitives/mod.rs @@ -116,8 +116,8 @@ pub mod integration_tests { #[tokio::test] #[ignore] - async fn test_pool_from_pool_ledger_with_id() { - SetupProfile::run_indy(|setup| async move { + async fn test_pool_create_and_get_schema() { + SetupProfile::run(|setup| async move { let (schema_id, _schema_json) = create_and_write_test_schema(&setup.profile, &setup.institution_did, DEFAULT_SCHEMA_ATTRS).await; diff --git a/aries_vcx/src/core/profile/mod.rs b/aries_vcx/src/core/profile/mod.rs index c7a8be0061..2264c82d07 100644 --- a/aries_vcx/src/core/profile/mod.rs +++ b/aries_vcx/src/core/profile/mod.rs @@ -1,5 +1,7 @@ #[cfg(feature = "modular_libs")] pub mod modular_libs_profile; pub mod profile; +#[cfg(feature = "vdr_proxy_ledger")] +pub mod vdr_proxy_profile; #[cfg(feature = "vdrtools")] pub mod vdrtools_profile; diff --git a/aries_vcx/src/core/profile/modular_libs_profile.rs b/aries_vcx/src/core/profile/modular_libs_profile.rs index 0481b3c631..0fd20e637f 100644 --- a/aries_vcx/src/core/profile/modular_libs_profile.rs +++ b/aries_vcx/src/core/profile/modular_libs_profile.rs @@ -3,7 +3,8 @@ use std::sync::Arc; use aries_vcx_core::anoncreds::base_anoncreds::BaseAnonCreds; use aries_vcx_core::anoncreds::credx_anoncreds::IndyCredxAnonCreds; use aries_vcx_core::ledger::base_ledger::BaseLedger; -use aries_vcx_core::ledger::indy_vdr_ledger::{IndyVdrLedger, IndyVdrLedgerPool, LedgerPoolConfig}; +use aries_vcx_core::ledger::indy_vdr_ledger::IndyVdrLedger; +use aries_vcx_core::ledger::request_submitter::vdr_ledger::{IndyVdrLedgerPool, IndyVdrSubmitter, LedgerPoolConfig}; use aries_vcx_core::wallet::base_wallet::BaseWallet; use crate::errors::error::VcxResult; @@ -21,7 +22,8 @@ pub struct ModularLibsProfile { impl ModularLibsProfile { pub fn new(wallet: Arc, ledger_pool_config: LedgerPoolConfig) -> VcxResult { let ledger_pool = Arc::new(IndyVdrLedgerPool::new(ledger_pool_config)?); - let ledger = Arc::new(IndyVdrLedger::new(Arc::clone(&wallet), ledger_pool)); + let submitter = Arc::new(IndyVdrSubmitter::new(ledger_pool)); + let ledger = Arc::new(IndyVdrLedger::new(Arc::clone(&wallet), submitter)); let anoncreds = Arc::new(IndyCredxAnonCreds::new(Arc::clone(&wallet))); Ok(ModularLibsProfile { wallet, diff --git a/aries_vcx/src/core/profile/vdr_proxy_profile.rs b/aries_vcx/src/core/profile/vdr_proxy_profile.rs new file mode 100644 index 0000000000..3e64f4c574 --- /dev/null +++ b/aries_vcx/src/core/profile/vdr_proxy_profile.rs @@ -0,0 +1,47 @@ +use std::sync::Arc; + +use aries_vcx_core::{ + anoncreds::{base_anoncreds::BaseAnonCreds, indy_anoncreds::IndySdkAnonCreds}, + ledger::{ + base_ledger::BaseLedger, indy_vdr_ledger::IndyVdrLedger, request_submitter::vdr_proxy::VdrProxySubmitter, + }, + wallet::{base_wallet::BaseWallet, indy_wallet::IndySdkWallet}, + VdrProxyClient, WalletHandle, +}; + +use super::profile::Profile; + +#[derive(Debug)] +pub struct VdrProxyProfile { + wallet: Arc, + ledger: Arc, + anoncreds: Arc, +} + +impl VdrProxyProfile { + pub fn new(wallet_handle: WalletHandle, client: VdrProxyClient) -> Self { + let wallet = Arc::new(IndySdkWallet::new(wallet_handle)); + let submitter = Arc::new(VdrProxySubmitter::new(Arc::new(client))); + let ledger = Arc::new(IndyVdrLedger::new(wallet.clone(), submitter)); + let anoncreds = Arc::new(IndySdkAnonCreds::new(wallet_handle)); + VdrProxyProfile { + wallet, + ledger, + anoncreds, + } + } +} + +impl Profile for VdrProxyProfile { + fn inject_ledger(self: Arc) -> Arc { + Arc::clone(&self.ledger) + } + + fn inject_anoncreds(self: Arc) -> Arc { + Arc::clone(&self.anoncreds) + } + + fn inject_wallet(&self) -> Arc { + Arc::clone(&self.wallet) + } +} diff --git a/aries_vcx/src/utils/devsetup.rs b/aries_vcx/src/utils/devsetup.rs index 10be78beb0..e7109445ec 100644 --- a/aries_vcx/src/utils/devsetup.rs +++ b/aries_vcx/src/utils/devsetup.rs @@ -17,7 +17,7 @@ use aries_vcx_core::indy::wallet::{ }; #[cfg(feature = "modular_libs")] -use aries_vcx_core::ledger::indy_vdr_ledger::LedgerPoolConfig; +use aries_vcx_core::ledger::request_submitter::vdr_ledger::LedgerPoolConfig; use aries_vcx_core::wallet::base_wallet::BaseWallet; use aries_vcx_core::wallet::indy_wallet::IndySdkWallet; use aries_vcx_core::{PoolHandle, WalletHandle}; @@ -380,6 +380,12 @@ impl SetupProfile { SetupProfile::init_modular().await }; + #[cfg(feature = "vdr_proxy_ledger")] + return { + info!("SetupProfile >> using vdr proxy profile"); + SetupProfile::init_vdr_proxy_ledger().await + }; + #[cfg(feature = "vdrtools")] return { info!("SetupProfile >> using indy profile"); @@ -445,7 +451,33 @@ impl SetupProfile { } } - #[cfg(any(feature = "modular_libs", feature = "vdrtools"))] + #[cfg(feature = "vdr_proxy_ledger")] + async fn init_vdr_proxy_ledger() -> SetupProfile { + use std::env; + + use crate::core::profile::vdr_proxy_profile::VdrProxyProfile; + use aries_vcx_core::VdrProxyClient; + + let (institution_did, wallet_handle) = setup_issuer_wallet().await; + + // TODO: Test configuration should be handled uniformly + let client_url = env::var("VDR_PROXY_CLIENT_URL").unwrap_or_else(|_| "http://127.0.0.1:3030".to_string()); + let client = VdrProxyClient::new(&client_url).unwrap(); + + let profile: Arc = Arc::new(VdrProxyProfile::new(wallet_handle, client)); + + async fn vdr_proxy_teardown() { + // nothing to do + } + + SetupProfile { + institution_did, + profile, + teardown: Arc::new(move || Box::pin(vdr_proxy_teardown())), + } + } + + #[cfg(any(feature = "modular_libs", feature = "vdrtools", feature = "vdr_proxy_ledger"))] pub async fn run(f: impl FnOnce(Self) -> F) where F: Future, @@ -463,11 +495,15 @@ impl SetupProfile { // FUTURE - ideally no tests should be using this method, they should be using the generic run // after modular profile Anoncreds/Ledger methods have all been implemented, all tests should use run() - #[cfg(feature = "vdrtools")] + #[cfg(any(feature = "vdrtools", feature = "vdr_proxy_ledger"))] pub async fn run_indy(f: impl FnOnce(Self) -> F) where F: Future, { + #[cfg(feature = "vdr_proxy_ledger")] + let init = Self::init_vdr_proxy_ledger().await; + + #[cfg(all(feature = "vdrtools", not(feature = "vdr_proxy_ledger")))] let init = Self::init_indy().await; let teardown = Arc::clone(&init.teardown); diff --git a/aries_vcx/tests/test_creds_proofs.rs b/aries_vcx/tests/test_creds_proofs.rs index bc61064a4a..44f8ac69c0 100644 --- a/aries_vcx/tests/test_creds_proofs.rs +++ b/aries_vcx/tests/test_creds_proofs.rs @@ -29,7 +29,6 @@ mod integration_tests { #[tokio::test] #[ignore] async fn test_agency_pool_retrieve_credentials() { - // todo - use SetupProfile::run after modular impls SetupProfile::run_indy(|setup| async move { let holder_setup = init_holder_setup_in_indy_context(&setup).await; @@ -68,7 +67,6 @@ mod integration_tests { #[tokio::test] #[ignore] async fn test_agency_pool_get_credential_def() { - // todo - use SetupProfile::run after modular impls SetupProfile::run_indy(|setup| async move { let (_, _, cred_def_id, cred_def_json, _) = create_and_store_nonrevocable_credential_def( &setup.profile, @@ -90,7 +88,6 @@ mod integration_tests { #[tokio::test] #[ignore] async fn test_agency_pool_retrieve_credentials_empty() { - // todo - use SetupProfile::run after modular impls SetupProfile::run_indy(|setup| async move { let mut req = json!({ "nonce":"123432421212", @@ -147,7 +144,6 @@ mod integration_tests { #[tokio::test] #[ignore] async fn test_agency_pool_case_for_proof_req_doesnt_matter_for_retrieve_creds() { - // todo - use SetupProfile::run after modular impls SetupProfile::run_indy(|setup| async move { create_and_store_nonrevocable_credential( &setup.profile, @@ -244,7 +240,6 @@ mod integration_tests { #[tokio::test] #[ignore] async fn test_agency_pool_generate_proof() { - // todo - use SetupProfile::run after modular impls SetupProfile::run_indy(|setup| async move { create_and_store_credential( &setup.profile, @@ -325,7 +320,6 @@ mod integration_tests { #[tokio::test] #[ignore] async fn test_agency_pool_generate_proof_with_predicates() { - // todo - use SetupProfile::run after modular impls SetupProfile::run_indy(|setup| async move { create_and_store_credential( &setup.profile, @@ -410,7 +404,6 @@ mod integration_tests { #[tokio::test] #[ignore] async fn test_agency_pool_generate_self_attested_proof() { - // todo - use SetupProfile::run after modular impls SetupProfile::run_indy(|setup| async move { let indy_proof_req = json!({ "nonce":"123432421212", diff --git a/aries_vcx/tests/utils/devsetup_agent.rs b/aries_vcx/tests/utils/devsetup_agent.rs index 3ee386cb39..7a8f2b19bb 100644 --- a/aries_vcx/tests/utils/devsetup_agent.rs +++ b/aries_vcx/tests/utils/devsetup_agent.rs @@ -16,7 +16,7 @@ pub mod test_utils { IssuerConfig, WalletConfig, }; #[cfg(feature = "modular_libs")] - use aries_vcx_core::ledger::indy_vdr_ledger::LedgerPoolConfig; + use aries_vcx_core::ledger::request_submitter::vdr_ledger::LedgerPoolConfig; use aries_vcx_core::wallet::base_wallet::BaseWallet; use aries_vcx_core::wallet::indy_wallet::IndySdkWallet; use aries_vcx_core::{PoolHandle, WalletHandle}; diff --git a/aries_vcx_core/Cargo.toml b/aries_vcx_core/Cargo.toml index 121e2440e5..9f0eb5bfc5 100644 --- a/aries_vcx_core/Cargo.toml +++ b/aries_vcx_core/Cargo.toml @@ -9,6 +9,7 @@ edition = "2021" vdrtools = ["dep:libvdrtools"] # Feature flag to include the 'modular library' dependencies (vdrtools alternatives; indy-vdr, indy-credx) modular_libs = ["dep:indy-vdr", "dep:indy-credx"] +vdr_proxy_ledger = ["dep:indy-vdr", "dep:indy-credx", "dep:indy-vdr-proxy-client"] [dependencies] agency_client = { path = "../agency_client" } @@ -39,6 +40,8 @@ lazy_static = "1.4.0" derive_builder = "0.12.0" uuid = { version = "1.3.0", default-features = false, features = ["v4"] } tokio = { version = "1.20" } +# TODO: Point to the official repo if / when vdr-proxy-client PR is merged: https://github.com/hyperledger/indy-vdr/pull/184 +indy-vdr-proxy-client = { git = "https://github.com/mirgee/indy-vdr.git", rev = "fab0535", optional = true } [dev-dependencies] tokio = { version = "1.20", features = ["rt", "macros", "rt-multi-thread"] } diff --git a/aries_vcx_core/src/anoncreds/mod.rs b/aries_vcx_core/src/anoncreds/mod.rs index fec6fc4aed..d8a16ba8b4 100644 --- a/aries_vcx_core/src/anoncreds/mod.rs +++ b/aries_vcx_core/src/anoncreds/mod.rs @@ -1,5 +1,5 @@ pub mod base_anoncreds; -#[cfg(feature = "modular_libs")] +#[cfg(any(feature = "modular_libs", feature = "vdr_proxy_ledger"))] pub mod credx_anoncreds; #[cfg(feature = "vdrtools")] pub mod indy_anoncreds; diff --git a/aries_vcx_core/src/errors/mapping_indyvdr_proxy.rs b/aries_vcx_core/src/errors/mapping_indyvdr_proxy.rs new file mode 100644 index 0000000000..0a441b1f32 --- /dev/null +++ b/aries_vcx_core/src/errors/mapping_indyvdr_proxy.rs @@ -0,0 +1,12 @@ +use indy_vdr_proxy_client::error::VdrProxyClientError; + +use super::error::{AriesVcxCoreError, AriesVcxCoreErrorKind}; + +impl From for AriesVcxCoreError { + fn from(err: VdrProxyClientError) -> Self { + AriesVcxCoreError::from_msg( + AriesVcxCoreErrorKind::InvalidLedgerResponse, + format!("VdrProxyClient error: {:?}", err), + ) + } +} diff --git a/aries_vcx_core/src/errors/mod.rs b/aries_vcx_core/src/errors/mod.rs index 765403d8dc..abdf7777b6 100644 --- a/aries_vcx_core/src/errors/mod.rs +++ b/aries_vcx_core/src/errors/mod.rs @@ -1,9 +1,11 @@ pub mod error; mod mapping_agency_client; -#[cfg(feature = "modular_libs")] +#[cfg(any(feature = "modular_libs", feature = "vdr_proxy_ledger"))] mod mapping_credx; -#[cfg(feature = "modular_libs")] +#[cfg(any(feature = "modular_libs", feature = "vdr_proxy_ledger"))] mod mapping_indyvdr; +#[cfg(feature = "vdr_proxy_ledger")] +mod mapping_indyvdr_proxy; mod mapping_others; #[cfg(feature = "vdrtools")] mod mapping_vdrtools; diff --git a/aries_vcx_core/src/ledger/indy_vdr_ledger.rs b/aries_vcx_core/src/ledger/indy_vdr_ledger.rs index 0c2e90294c..0587f5b964 100644 --- a/aries_vcx_core/src/ledger/indy_vdr_ledger.rs +++ b/aries_vcx_core/src/ledger/indy_vdr_ledger.rs @@ -1,21 +1,19 @@ +use indy_credx::ursa::cl::RevocationRegistryDelta as UrsaRevocationRegistryDelta; use indy_vdr as vdr; -use std::collections::hash_map::RandomState; -use std::collections::HashMap; use std::fmt::{Debug, Formatter}; use std::sync::Arc; use time::OffsetDateTime; +use vdr::ledger::requests::cred_def::CredentialDefinitionV1; +use vdr::ledger::requests::rev_reg::{RevocationRegistryDelta, RevocationRegistryDeltaV1}; +use vdr::ledger::requests::rev_reg_def::{RegistryType, RevocationRegistryDefinition, RevocationRegistryDefinitionV1}; use vdr::ledger::requests::schema::{AttributeNames, Schema, SchemaV1}; use async_trait::async_trait; use serde_json::Value; -use tokio::sync::oneshot; -use vdr::common::error::VdrError; -use vdr::config::PoolConfig as IndyVdrPoolConfig; use vdr::ledger::identifiers::{CredentialDefinitionId, RevocationRegistryId, SchemaId}; -use vdr::ledger::requests::author_agreement::TxnAuthrAgrmtAcceptanceData; +use vdr::ledger::requests::{author_agreement::TxnAuthrAgrmtAcceptanceData, cred_def::CredentialDefinition}; use vdr::ledger::RequestBuilder; -use vdr::pool::{PoolBuilder, PoolTransactions}; -use vdr::pool::{PoolRunner, PreparedRequest, ProtocolVersion, RequestResult}; +use vdr::pool::{LedgerType, PreparedRequest, ProtocolVersion}; use vdr::utils::did::DidValue; use vdr::utils::Qualifiable; @@ -27,47 +25,25 @@ use crate::utils::json::{AsTypeOrDeserializationError, TryGetIndex}; use crate::wallet::base_wallet::BaseWallet; use super::base_ledger::BaseLedger; +use super::request_submitter::RequestSubmitter; -pub struct LedgerPoolConfig { - pub genesis_file_path: String, -} - -pub struct IndyVdrLedgerPool { - // visibility strictly for internal unit testing - pub(self) runner: Option, -} - -impl IndyVdrLedgerPool { - pub fn new_from_runner(runner: PoolRunner) -> Self { - IndyVdrLedgerPool { runner: Some(runner) } - } - - pub fn new(config: LedgerPoolConfig) -> VcxCoreResult { - let vdr_config = IndyVdrPoolConfig::default(); - let txns = PoolTransactions::from_json_file(config.genesis_file_path)?; - - let runner = PoolBuilder::from(vdr_config).transactions(txns)?.into_runner()?; - - Ok(IndyVdrLedgerPool { runner: Some(runner) }) - } -} - -impl Debug for IndyVdrLedgerPool { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - f.debug_struct("IndyVdrLedgerPool") - .field("runner", &"PoolRunner") - .finish() - } -} - -pub struct IndyVdrLedger { +pub struct IndyVdrLedger +where + T: RequestSubmitter + Send + Sync, +{ wallet: Arc, - pool: Arc, + request_submitter: Arc, } -impl IndyVdrLedger { - pub fn new(wallet: Arc, pool: Arc) -> Self { - IndyVdrLedger { wallet, pool } +impl IndyVdrLedger +where + T: RequestSubmitter + Send + Sync, +{ + pub fn new(wallet: Arc, request_submitter: Arc) -> Self { + IndyVdrLedger { + wallet, + request_submitter, + } } pub fn request_builder(&self) -> VcxCoreResult { @@ -78,40 +54,7 @@ impl IndyVdrLedger { } async fn _submit_request(&self, request: PreparedRequest) -> VcxCoreResult { - // indyvdr send_request is Async via a callback. - // Use oneshot channel to send result from callback, converting the fn to future. - type VdrSendRequestResult = - Result<(RequestResult, Option>), VdrError>; - let (sender, recv) = oneshot::channel::(); - self.pool - .runner - .as_ref() - .ok_or( - // should not happen - strictly for unit testing - AriesVcxCoreError::from_msg( - AriesVcxCoreErrorKind::NoPoolOpen, - "IndyVdrLedgerPool runner was not provided", - ), - )? - .send_request( - request, - Box::new(move |result| { - // unable to handle a failure from `send` here - sender.send(result).ok(); - }), - )?; - - let send_req_result: VdrSendRequestResult = recv - .await - .map_err(|e| AriesVcxCoreError::from_msg(AriesVcxCoreErrorKind::InvalidState, e))?; - let (result, _) = send_req_result?; - - let reply = match result { - RequestResult::Reply(reply) => Ok(reply), - RequestResult::Failed(failed) => Err(failed), - }; - - Ok(reply?) + self.request_submitter.submit(request).await } async fn _sign_and_submit_request(&self, submitter_did: &str, request: PreparedRequest) -> VcxCoreResult { @@ -132,11 +75,7 @@ impl IndyVdrLedger { submitter_did: Option<&str>, cred_def_id: &str, ) -> VcxCoreResult { - let identifier = if let Some(did) = submitter_did { - Some(DidValue::from_str(did)?) - } else { - None - }; + let identifier = submitter_did.map(DidValue::from_str).transpose()?; let id = CredentialDefinitionId::from_str(cred_def_id)?; Ok(self .request_builder()? @@ -182,16 +121,74 @@ impl IndyVdrLedger { .request_builder()? .build_attrib_request(&identifier, &dest, None, attrib_json.as_ref(), None)?) } + + fn _build_schema_request(&self, submitter_did: &str, schema_data: &str) -> VcxCoreResult { + let identifier = DidValue::from_str(submitter_did)?; + let schema_data: SchemaV1 = serde_json::from_str(schema_data)?; + Ok(self + .request_builder()? + .build_schema_request(&identifier, Schema::SchemaV1(schema_data))?) + } + + fn _build_cred_def_request(&self, submitter_did: &str, cred_def_data: &str) -> VcxCoreResult { + let identifier = DidValue::from_str(submitter_did)?; + let cred_def_data: CredentialDefinitionV1 = serde_json::from_str(cred_def_data)?; + Ok(self + .request_builder()? + .build_cred_def_request(&identifier, CredentialDefinition::CredentialDefinitionV1(cred_def_data))?) + } + + fn _build_rev_reg_def_request( + &self, + submitter_did: &str, + rev_reg_def_data: &str, + ) -> VcxCoreResult { + let identifier = DidValue::from_str(submitter_did)?; + let rev_reg_def_data: RevocationRegistryDefinitionV1 = serde_json::from_str(rev_reg_def_data)?; + Ok(self.request_builder()?.build_revoc_reg_def_request( + &identifier, + RevocationRegistryDefinition::RevocationRegistryDefinitionV1(rev_reg_def_data), + )?) + } + + fn _build_rev_reg_delta_request( + &self, + submitter_did: &str, + rev_reg_id: &str, + rev_reg_delta_data: &str, + ) -> VcxCoreResult { + let identifier = DidValue::from_str(submitter_did)?; + let rev_reg_delta_data: RevocationRegistryDeltaV1 = serde_json::from_str(rev_reg_delta_data)?; + Ok(self.request_builder()?.build_revoc_reg_entry_request( + &identifier, + &RevocationRegistryId::from_str(rev_reg_id)?, + &RegistryType::CL_ACCUM, + RevocationRegistryDelta::RevocationRegistryDeltaV1(rev_reg_delta_data), + )?) + } + + fn _build_get_txn_request(&self, submitter_did: Option<&str>, seq_no: i32) -> VcxCoreResult { + let identifier = submitter_did.map(DidValue::from_str).transpose()?; + Ok(self + .request_builder()? + .build_get_txn_request(identifier.as_ref(), LedgerType::DOMAIN.to_id(), seq_no)?) + } } -impl Debug for IndyVdrLedger { +impl Debug for IndyVdrLedger +where + T: RequestSubmitter + Send + Sync, +{ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "IndyVdrLedger instance") } } #[async_trait] -impl BaseLedger for IndyVdrLedger { +impl BaseLedger for IndyVdrLedger +where + T: RequestSubmitter + Send + Sync, +{ async fn sign_and_submit_request(&self, submitter_did: &str, request_json: &str) -> VcxCoreResult { let request = PreparedRequest::from_request_json(request_json)?; @@ -432,18 +429,42 @@ impl BaseLedger for IndyVdrLedger { } async fn get_rev_reg(&self, rev_reg_id: &str, timestamp: u64) -> VcxCoreResult<(String, String, u64)> { - let _ = (rev_reg_id, timestamp); - Err(unimplemented_method_err("indy_vdr get_rev_reg")) + let revoc_reg_def_id = RevocationRegistryId::from_str(rev_reg_id)?; + + let request = self.request_builder()?.build_get_revoc_reg_request( + None, + &revoc_reg_def_id, + timestamp.try_into().unwrap(), + )?; + let res = self._submit_request(request).await?; + + let res_data = _get_response_json_data_field(&res)?; + + let rev_reg_def_id = res_data["revocRegDefId"] + .as_str() + .ok_or(AriesVcxCoreError::from_msg( + AriesVcxCoreErrorKind::InvalidJson, + "Error parsing revocRegDefId value as string", + ))? + .to_string(); + + let timestamp = res_data["txnTime"].as_u64().ok_or(AriesVcxCoreError::from_msg( + AriesVcxCoreErrorKind::InvalidJson, + "Error parsing txnTime value as u64", + ))?; + + Ok((rev_reg_def_id, res_data["value"].to_string(), timestamp)) } async fn get_ledger_txn(&self, seq_no: i32, submitter_did: Option<&str>) -> VcxCoreResult { - let _ = (seq_no, submitter_did); - Err(unimplemented_method_err("indy_vdr get_ledger_txn")) + let request = self._build_get_txn_request(submitter_did, seq_no)?; + self._submit_request(request).await } async fn build_schema_request(&self, submitter_did: &str, schema_json: &str) -> VcxCoreResult { - let _ = (submitter_did, schema_json); - Err(unimplemented_method_err("indy_vdr build_schema_request")) + let request = self._build_schema_request(submitter_did, schema_json)?; + let request = _append_txn_author_agreement_to_request(request).await?; + Ok(request.req_json.to_string()) } async fn publish_schema( @@ -452,18 +473,24 @@ impl BaseLedger for IndyVdrLedger { submitter_did: &str, endorser_did: Option, ) -> VcxCoreResult<()> { - let _ = (schema_json, submitter_did, endorser_did); - Err(unimplemented_method_err("indy_vdr publish_schema")) + let request = self._build_schema_request(submitter_did, schema_json)?; + let request = _append_txn_author_agreement_to_request(request).await?; + self._sign_and_submit_request(submitter_did, request).await?; + Ok(()) } async fn publish_cred_def(&self, cred_def_json: &str, submitter_did: &str) -> VcxCoreResult<()> { - let _ = (cred_def_json, submitter_did); - Err(unimplemented_method_err("indy_vdr publish_cred_def")) + let request = self._build_cred_def_request(submitter_did, cred_def_json)?; + let request = _append_txn_author_agreement_to_request(request).await?; + self._sign_and_submit_request(submitter_did, request).await?; + Ok(()) } async fn publish_rev_reg_def(&self, rev_reg_def: &str, submitter_did: &str) -> VcxCoreResult<()> { - let _ = (rev_reg_def, submitter_did); - Err(unimplemented_method_err("indy_vdr publish_rev_reg_def")) + let request = self._build_rev_reg_def_request(submitter_did, rev_reg_def)?; + let request = _append_txn_author_agreement_to_request(request).await?; + self._sign_and_submit_request(submitter_did, request).await?; + Ok(()) } async fn publish_rev_reg_delta( @@ -472,8 +499,10 @@ impl BaseLedger for IndyVdrLedger { rev_reg_entry_json: &str, submitter_did: &str, ) -> VcxCoreResult<()> { - let _ = (rev_reg_entry_json, rev_reg_id, submitter_did); - Err(unimplemented_method_err("indy_vdr publish_rev_reg_delta")) + let request = self._build_rev_reg_delta_request(submitter_did, rev_reg_id, rev_reg_entry_json)?; + let request = _append_txn_author_agreement_to_request(request).await?; + self._sign_and_submit_request(submitter_did, request).await?; + Ok(()) } } @@ -508,42 +537,13 @@ async fn _append_txn_author_agreement_to_request(request: PreparedRequest) -> Vc fn _get_response_json_data_field(response_json: &str) -> VcxCoreResult { let res: Value = serde_json::from_str(response_json)?; let result = (&res).try_get("result")?; - Ok(result.try_get("data")?.to_owned()) -} - -#[cfg(test)] -mod unit_tests { - use std::sync::Arc; - - use crate::errors::error::{AriesVcxCoreErrorKind, VcxCoreResult}; - use crate::{ - common::test_utils::mock_profile, - plugins::ledger::{base_ledger::BaseLedger, indy_vdr_ledger::IndyVdrLedgerPool}, - }; - - use super::IndyVdrLedger; - - #[tokio::test] - #[ignore] - async fn test_pool_unimplemented_methods() { - // test used to assert which methods are unimplemented currently, can be removed after all methods implemented - - fn assert_unimplemented(result: VcxCoreResult) { - assert_eq!(result.unwrap_err().kind(), AriesVcxCoreErrorKind::UnimplementedFeature) - } - - let profile = mock_profile(); - let pool = Arc::new(IndyVdrLedgerPool { runner: None }); - let ledger: Box = Box::new(IndyVdrLedger::new(profile.inject_wallet(), pool)); - - assert_unimplemented(ledger.endorse_transaction("", "").await); - assert_unimplemented(ledger.set_endorser("", "", "").await); - assert_unimplemented(ledger.get_txn_author_agreement().await); - assert_unimplemented(ledger.get_rev_reg("", 0).await); - assert_unimplemented(ledger.get_ledger_txn(0, None).await); - assert_unimplemented(ledger.build_schema_request("", "").await); - assert_unimplemented(ledger.publish_schema("", "", None).await); - assert_unimplemented(ledger.publish_cred_def("", "").await); - assert_unimplemented(ledger.publish_rev_reg_def("", "").await); + let data = result.try_get("data")?.to_owned(); + if data.is_null() { + Err(AriesVcxCoreError::from_msg( + AriesVcxCoreErrorKind::LedgerItemNotFound, + "No data in response", + )) + } else { + Ok(data) } } diff --git a/aries_vcx_core/src/ledger/mod.rs b/aries_vcx_core/src/ledger/mod.rs index 911d544c08..3b3296a77a 100644 --- a/aries_vcx_core/src/ledger/mod.rs +++ b/aries_vcx_core/src/ledger/mod.rs @@ -1,5 +1,7 @@ pub mod base_ledger; #[cfg(feature = "vdrtools")] pub mod indy_ledger; -#[cfg(feature = "modular_libs")] +#[cfg(any(feature = "modular_libs", feature = "vdr_proxy_ledger"))] pub mod indy_vdr_ledger; +#[cfg(any(feature = "modular_libs", feature = "vdr_proxy_ledger"))] +pub mod request_submitter; diff --git a/aries_vcx_core/src/ledger/request_submitter/mod.rs b/aries_vcx_core/src/ledger/request_submitter/mod.rs new file mode 100644 index 0000000000..8d26b3afc7 --- /dev/null +++ b/aries_vcx_core/src/ledger/request_submitter/mod.rs @@ -0,0 +1,14 @@ +use async_trait::async_trait; +use indy_vdr::pool::PreparedRequest; + +use crate::errors::error::VcxCoreResult; + +#[cfg(feature = "modular_libs")] +pub mod vdr_ledger; +#[cfg(feature = "vdr_proxy_ledger")] +pub mod vdr_proxy; + +#[async_trait] +pub trait RequestSubmitter { + async fn submit(&self, request: PreparedRequest) -> VcxCoreResult; +} diff --git a/aries_vcx_core/src/ledger/request_submitter/vdr_ledger.rs b/aries_vcx_core/src/ledger/request_submitter/vdr_ledger.rs new file mode 100644 index 0000000000..1a105ab9e6 --- /dev/null +++ b/aries_vcx_core/src/ledger/request_submitter/vdr_ledger.rs @@ -0,0 +1,101 @@ +use std::{ + collections::{hash_map::RandomState, HashMap}, + fmt::{Debug, Formatter}, + sync::Arc, +}; + +use async_trait::async_trait; +use indy_vdr::{ + common::error::VdrError, + pool::{PoolTransactions, RequestResult}, +}; +use indy_vdr::{ + config::PoolConfig, + pool::{PoolBuilder, PoolRunner, PreparedRequest}, +}; +use tokio::sync::oneshot; + +use crate::errors::error::{AriesVcxCoreError, AriesVcxCoreErrorKind, VcxCoreResult}; + +use super::RequestSubmitter; + +pub struct LedgerPoolConfig { + pub genesis_file_path: String, +} + +pub struct IndyVdrLedgerPool { + pub(self) runner: Option, +} + +impl IndyVdrLedgerPool { + pub fn new_from_runner(runner: PoolRunner) -> Self { + IndyVdrLedgerPool { runner: Some(runner) } + } + + pub fn new(config: LedgerPoolConfig) -> VcxCoreResult { + let vdr_config = PoolConfig::default(); + let txns = PoolTransactions::from_json_file(config.genesis_file_path)?; + + let runner = PoolBuilder::from(vdr_config).transactions(txns)?.into_runner()?; + + Ok(IndyVdrLedgerPool { runner: Some(runner) }) + } +} + +impl Debug for IndyVdrLedgerPool { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("IndyVdrLedgerPool") + .field("runner", &"PoolRunner") + .finish() + } +} + +pub struct IndyVdrSubmitter { + pool: Arc, +} + +impl IndyVdrSubmitter { + pub fn new(pool: Arc) -> Self { + Self { pool } + } +} + +#[async_trait] +impl RequestSubmitter for IndyVdrSubmitter { + async fn submit(&self, request: PreparedRequest) -> VcxCoreResult { + // indyvdr send_request is Async via a callback. + // Use oneshot channel to send result from callback, converting the fn to future. + type VdrSendRequestResult = + Result<(RequestResult, Option>), VdrError>; + let (sender, recv) = oneshot::channel::(); + self.pool + .runner + .as_ref() + .ok_or( + // should not happen - strictly for unit testing + AriesVcxCoreError::from_msg( + AriesVcxCoreErrorKind::NoPoolOpen, + "IndyVdrLedgerPool runner was not provided", + ), + )? + .send_request( + request, + Box::new(move |result| { + // unable to handle a failure from `send` here + sender.send(result).ok(); + }), + )?; + + let send_req_result: VdrSendRequestResult = recv + .await + .map_err(|e| AriesVcxCoreError::from_msg(AriesVcxCoreErrorKind::InvalidState, e))?; + let (result, _) = send_req_result?; + + let reply = match result { + RequestResult::Reply(reply) => Ok(reply), + RequestResult::Failed(failed) => Err(failed), + }; + + Ok(reply?) + } +} diff --git a/aries_vcx_core/src/ledger/request_submitter/vdr_proxy.rs b/aries_vcx_core/src/ledger/request_submitter/vdr_proxy.rs new file mode 100644 index 0000000000..efe28ded33 --- /dev/null +++ b/aries_vcx_core/src/ledger/request_submitter/vdr_proxy.rs @@ -0,0 +1,26 @@ +use std::sync::Arc; + +use async_trait::async_trait; +use indy_vdr::pool::PreparedRequest; +use indy_vdr_proxy_client::VdrProxyClient; + +use crate::errors::error::VcxCoreResult; + +use super::RequestSubmitter; + +pub struct VdrProxySubmitter { + client: Arc, +} + +impl VdrProxySubmitter { + pub fn new(client: Arc) -> Self { + Self { client } + } +} + +#[async_trait] +impl RequestSubmitter for VdrProxySubmitter { + async fn submit(&self, request: PreparedRequest) -> VcxCoreResult { + self.client.post(request).await.map_err(|e| e.into()) + } +} diff --git a/aries_vcx_core/src/lib.rs b/aries_vcx_core/src/lib.rs index 252dbf6eb1..ca95cbe6d6 100644 --- a/aries_vcx_core/src/lib.rs +++ b/aries_vcx_core/src/lib.rs @@ -40,3 +40,6 @@ pub mod wallet; pub use vdrtools::{ PoolHandle, SearchHandle, WalletHandle, INVALID_POOL_HANDLE, INVALID_SEARCH_HANDLE, INVALID_WALLET_HANDLE, }; + +#[cfg(feature = "vdr_proxy_ledger")] +pub use indy_vdr_proxy_client::VdrProxyClient; diff --git a/ci/vdrproxy.dockerfile b/ci/vdrproxy.dockerfile new file mode 100644 index 0000000000..24e2234d82 --- /dev/null +++ b/ci/vdrproxy.dockerfile @@ -0,0 +1,21 @@ +ARG ALPINE_CORE_IMAGE +FROM ${ALPINE_CORE_IMAGE} AS builder + +USER root +RUN apk update && apk upgrade && \ + apk add --no-cache \ + git + +USER indy +RUN git clone https://github.com/hyperledger/indy-vdr.git +WORKDIR /home/indy/indy-vdr/indy-vdr-proxy +RUN cargo build --release + +FROM alpine:3.18 +RUN apk update && apk upgrade && \ + apk add --no-cache \ + libstdc++ \ + libgcc + +COPY --from=builder /home/indy/indy-vdr/target/release/indy-vdr-proxy indy-vdr-proxy +ENTRYPOINT ["./indy-vdr-proxy"] diff --git a/did_resolver_sov/src/reader/vdr_reader.rs b/did_resolver_sov/src/reader/vdr_reader.rs index 0de0c3cf5d..64ac7abeea 100644 --- a/did_resolver_sov/src/reader/vdr_reader.rs +++ b/did_resolver_sov/src/reader/vdr_reader.rs @@ -2,7 +2,10 @@ use std::sync::Arc; use crate::error::DidSovError; use aries_vcx_core::{ - ledger::indy_vdr_ledger::{IndyVdrLedger, IndyVdrLedgerPool, LedgerPoolConfig}, + ledger::{ + indy_vdr_ledger::IndyVdrLedger, + request_submitter::vdr_ledger::{IndyVdrLedgerPool, IndyVdrSubmitter, LedgerPoolConfig}, + }, wallet::{base_wallet::BaseWallet, indy_wallet::IndySdkWallet}, INVALID_WALLET_HANDLE, }; @@ -15,8 +18,8 @@ impl TryFrom for ConcreteAttrReader { fn try_from(pool_config: LedgerPoolConfig) -> Result { let wallet = Arc::new(IndySdkWallet::new(INVALID_WALLET_HANDLE)) as Arc; let ledger_pool = Arc::new(IndyVdrLedgerPool::new(pool_config)?); - Ok(Self { - ledger: Arc::new(IndyVdrLedger::new(Arc::clone(&wallet), ledger_pool)), - }) + let submitter = Arc::new(IndyVdrSubmitter::new(ledger_pool)); + let ledger = Arc::new(IndyVdrLedger::new(Arc::clone(&wallet), submitter)); + Ok(Self { ledger }) } }