From 0cb5fc36aecd989bc4b75c81676418233c8371ed Mon Sep 17 00:00:00 2001 From: Ondrej Prazak Date: Thu, 29 Feb 2024 15:11:43 +0100 Subject: [PATCH] feat: add wallet migration to askar Signed-off-by: Ondrej Prazak --- .github/workflows/main.yml | 19 +- Cargo.lock | 44 ++ aries/aries_vcx_core/Cargo.toml | 4 +- .../src/wallet/askar/askar_did_wallet.rs | 10 +- .../src/wallet/askar/askar_utils.rs | 32 +- .../src/wallet/askar/key_value.rs | 13 - aries/aries_vcx_core/src/wallet/askar/mod.rs | 26 +- aries/aries_vcx_core/src/wallet/askar/pack.rs | 12 +- .../src/wallet/askar/packing_types.rs | 33 +- .../src/wallet/askar/partial_record.rs | 6 +- .../aries_vcx_core/src/wallet/askar/unpack.rs | 9 +- .../src/wallet/base_wallet/base58_string.rs | 32 + .../src/wallet/base_wallet/base64_string.rs | 34 + .../src/wallet/base_wallet/key_value.rs | 23 + .../src/wallet/base_wallet/migrate.rs | 215 ++++--- .../src/wallet/base_wallet/mod.rs | 33 +- .../src/wallet/base_wallet/record.rs | 10 +- .../src/wallet/base_wallet/record_category.rs | 2 +- .../src/wallet/indy/indy_wallet_config.rs | 113 +--- aries/aries_vcx_core/src/wallet/indy/mod.rs | 72 ++- aries/aries_vcx_core/src/wallet/utils.rs | 19 +- aries/misc/test_utils/src/mock_wallet.rs | 10 + aries/misc/wallet_migrator/Cargo.toml | 10 +- .../src/credx2anoncreds/conv.rs | 43 -- .../src/credx2anoncreds/mod.rs | 1 - aries/misc/wallet_migrator/src/error.rs | 5 +- aries/misc/wallet_migrator/src/lib.rs | 45 +- .../wallet_migrator/src/migrate2askar/mod.rs | 583 +++++++++++++++++ .../src/vdrtools2credx/conv.rs | 107 ---- .../wallet_migrator/src/vdrtools2credx/mod.rs | 599 ------------------ .../wrappers/uniffi-aries-vcx/core/Cargo.toml | 2 +- aries/wrappers/uniffi-aries-vcx/core/build.rs | 5 +- .../wrappers/uniffi-aries-vcx/core/src/lib.rs | 2 +- .../core/src/{vcx.udl => vcx_indy.udl} | 0 justfile | 8 +- 35 files changed, 1134 insertions(+), 1047 deletions(-) delete mode 100644 aries/aries_vcx_core/src/wallet/askar/key_value.rs create mode 100644 aries/aries_vcx_core/src/wallet/base_wallet/base58_string.rs create mode 100644 aries/aries_vcx_core/src/wallet/base_wallet/base64_string.rs create mode 100644 aries/aries_vcx_core/src/wallet/base_wallet/key_value.rs delete mode 100644 aries/misc/wallet_migrator/src/credx2anoncreds/conv.rs delete mode 100644 aries/misc/wallet_migrator/src/credx2anoncreds/mod.rs create mode 100644 aries/misc/wallet_migrator/src/migrate2askar/mod.rs delete mode 100644 aries/misc/wallet_migrator/src/vdrtools2credx/conv.rs delete mode 100644 aries/misc/wallet_migrator/src/vdrtools2credx/mod.rs rename aries/wrappers/uniffi-aries-vcx/core/src/{vcx.udl => vcx_indy.udl} (100%) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index eac96b933e..d14f4d245f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -115,7 +115,7 @@ jobs: sudo apt-get update -y sudo apt-get install -y libsodium-dev libssl-dev libzmq3-dev sudo snap install --edge --classic just - - name: "Verify clippy across the entire workspace with default features" + - name: "Verify clippy across the entire workspace" run: just clippy-workspace ${{ matrix.wallet }} aries_vcx_clippy: @@ -277,6 +277,23 @@ jobs: - name: "Run workspace unit tests" run: just test-unit + test-wallet-migrator: + needs: workflow-setup + runs-on: ubuntu-20.04 + steps: + - name: "Git checkout" + uses: actions/checkout@v3 + - name: "Setup rust testing environment" + uses: ./.github/actions/setup-testing-rust + with: + rust-toolchain-version: ${{ env.RUST_TOOLCHAIN_VERSION }} + default: true + skip-docker-setup: true + - name: "Install just" + run: sudo snap install --edge --classic just + - name: "Run wallet migration tests" + run: just test-wallet-migrator + test-intergation-aries-vcx-core: needs: workflow-setup runs-on: ubuntu-20.04 diff --git a/Cargo.lock b/Cargo.lock index 31dbc9343a..4f1f8e385b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2092,6 +2092,15 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "env_filter" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" +dependencies = [ + "log", +] + [[package]] name = "env_logger" version = "0.9.3" @@ -2118,6 +2127,16 @@ dependencies = [ "termcolor", ] +[[package]] +name = "env_logger" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c012a26a7f605efc424dd53697843a72be7dc86ad2d01f7814337794a12231d" +dependencies = [ + "env_filter", + "log", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -5182,6 +5201,27 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" +[[package]] +name = "test-log" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b319995299c65d522680decf80f2c108d85b861d81dfe340a10d16cee29d9e6" +dependencies = [ + "env_logger 0.11.2", + "test-log-macros", +] + +[[package]] +name = "test-log-macros" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8f546451eaa38373f549093fe9fd05e7d2bade739e2ddf834b9968621d60107" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "test_utils" version = "0.62.0" @@ -5828,9 +5868,13 @@ dependencies = [ "indy-credx", "libvdrtools", "log", + "public_key", + "serde", "serde_json", + "test-log", "thiserror", "tokio", + "uuid", ] [[package]] diff --git a/aries/aries_vcx_core/Cargo.toml b/aries/aries_vcx_core/Cargo.toml index 9b37410e86..348f3b1d44 100644 --- a/aries/aries_vcx_core/Cargo.toml +++ b/aries/aries_vcx_core/Cargo.toml @@ -13,11 +13,11 @@ vdr_proxy_ledger = ["credx", "dep:indy-vdr-proxy-client"] # Feature flag to allow legacy proof verification legacy_proof = [] -askar_wallet = ["dep:aries-askar", "dep:bs58"] +askar_wallet = ["dep:aries-askar"] [dependencies] aries-askar = { version = "=0.3.0", optional = true } -bs58 = { version = "0.5", optional = true } +bs58 = { version = "0.5" } indy-vdr = { git = "https://github.com/hyperledger/indy-vdr.git", rev = "c143268", default-features = false, features = ["log"] } indy-credx = { git = "https://github.com/hyperledger/indy-shared-rs", tag = "v1.1.0", optional = true } # anoncreds = { git = "https://github.com/hyperledger/anoncreds-rs", tag = "v0.2.0-dev.5", optional = true } diff --git a/aries/aries_vcx_core/src/wallet/askar/askar_did_wallet.rs b/aries/aries_vcx_core/src/wallet/askar/askar_did_wallet.rs index 261b556771..71940c781d 100644 --- a/aries/aries_vcx_core/src/wallet/askar/askar_did_wallet.rs +++ b/aries/aries_vcx_core/src/wallet/askar/askar_did_wallet.rs @@ -18,7 +18,6 @@ use crate::{ wallet::{ base_wallet::{did_data::DidData, did_wallet::DidWallet, record_category::RecordCategory}, structs_io::UnpackMessageOutput, - utils::did_from_key, }, }; @@ -112,8 +111,7 @@ impl DidWallet for AskarWallet { let mut tx = self.transaction().await?; if let Some(did_value) = self.find_did(&mut tx, did, RecordCategory::TmpDid).await? { tx.remove(&RecordCategory::TmpDid.to_string(), did).await?; - tx.remove_key(&did_from_key(did_value.verkey().clone())) - .await?; + tx.remove_key(&did_value.verkey().base58()).await?; self.update_did( &mut tx, did, @@ -136,7 +134,7 @@ impl DidWallet for AskarWallet { if let Some(key) = self .session() .await? - .fetch_key(&did_from_key(key.to_owned()), false) + .fetch_key(&key.base58(), false) .await? { let local_key = key.load_local_key()?; @@ -154,7 +152,7 @@ impl DidWallet for AskarWallet { if let Some(key) = self .session() .await? - .fetch_key(&did_from_key(key.to_owned()), false) + .fetch_key(&key.base58(), false) .await? { let local_key = key.load_local_key()?; @@ -183,7 +181,7 @@ impl DidWallet for AskarWallet { let mut session = self.session().await?; let my_key = self - .fetch_local_key(&mut session, &did_from_key(sender_verkey)) + .fetch_local_key(&mut session, &sender_verkey.base58()) .await?; enc_key.pack_authcrypt(recipient_keys, my_key)? } else { diff --git a/aries/aries_vcx_core/src/wallet/askar/askar_utils.rs b/aries/aries_vcx_core/src/wallet/askar/askar_utils.rs index 80bdfbf966..69d6bafdb4 100644 --- a/aries/aries_vcx_core/src/wallet/askar/askar_utils.rs +++ b/aries/aries_vcx_core/src/wallet/askar/askar_utils.rs @@ -7,20 +7,17 @@ use serde::Deserialize; use crate::{ errors::error::{AriesVcxCoreErrorKind, VcxCoreResult}, - wallet::{askar::AriesVcxCoreError, utils::random_seed}, + wallet::{ + askar::AriesVcxCoreError, base_wallet::base58_string::Base58String, utils::random_seed, + }, }; -pub fn local_key_to_bs58_name(local_key: &LocalKey) -> VcxCoreResult { - let res = local_key_to_bs58_public_key(local_key)?; - Ok(res[0..16].to_string()) +pub fn local_key_to_bs58_public_key(local_key: &LocalKey) -> VcxCoreResult { + Ok(Base58String::from_bytes(&local_key.to_public_bytes()?)) } -pub fn local_key_to_bs58_public_key(local_key: &LocalKey) -> VcxCoreResult { - Ok(bs58::encode(local_key.to_public_bytes()?).into_string()) -} - -pub fn local_key_to_bs58_private_key(local_key: &LocalKey) -> VcxCoreResult { - Ok(bs58::encode(local_key.to_secret_bytes()?).into_string()) +pub fn local_key_to_bs58_private_key(local_key: &LocalKey) -> VcxCoreResult { + Ok(Base58String::from_bytes(&local_key.to_secret_bytes()?)) } pub fn local_key_to_public_key(local_key: &LocalKey) -> VcxCoreResult { @@ -46,21 +43,6 @@ pub fn from_json_str Deserialize<'a>>(json: &str) -> VcxCoreResult .map_err(|err| AriesVcxCoreError::from_msg(AriesVcxCoreErrorKind::InvalidJson, err)) } -pub fn bytes_to_bs58(bytes: &[u8]) -> String { - bs58::encode(bytes).into_string() -} - -pub fn bs58_to_bytes(key: &[u8]) -> VcxCoreResult> { - bs58::decode(key) - .into_vec() - .map_err(|err| AriesVcxCoreError::from_msg(AriesVcxCoreErrorKind::WalletError, err)) -} - -pub fn bytes_to_string(vec: Vec) -> VcxCoreResult { - String::from_utf8(vec) - .map_err(|err| AriesVcxCoreError::from_msg(AriesVcxCoreErrorKind::InvalidInput, err)) -} - pub fn value_from_entry(entry: Entry) -> VcxCoreResult { Ok(std::str::from_utf8(&entry.value) .map_err(|err| AriesVcxCoreError::from_msg(AriesVcxCoreErrorKind::WalletError, err))? diff --git a/aries/aries_vcx_core/src/wallet/askar/key_value.rs b/aries/aries_vcx_core/src/wallet/askar/key_value.rs deleted file mode 100644 index 23b09c0c9e..0000000000 --- a/aries/aries_vcx_core/src/wallet/askar/key_value.rs +++ /dev/null @@ -1,13 +0,0 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Debug, Deserialize, Serialize)] -pub struct KeyValue { - verkey: String, - signkey: String, -} - -impl KeyValue { - pub fn new(signkey: String, verkey: String) -> Self { - Self { signkey, verkey } - } -} diff --git a/aries/aries_vcx_core/src/wallet/askar/mod.rs b/aries/aries_vcx_core/src/wallet/askar/mod.rs index 983bfe0f37..9fc3d97d3d 100644 --- a/aries/aries_vcx_core/src/wallet/askar/mod.rs +++ b/aries/aries_vcx_core/src/wallet/askar/mod.rs @@ -7,10 +7,15 @@ use async_trait::async_trait; use public_key::Key; use self::{ - askar_utils::local_key_to_bs58_name, askar_wallet_config::AskarWalletConfig, + askar_utils::local_key_to_bs58_public_key, askar_wallet_config::AskarWalletConfig, rng_method::RngMethod, }; -use super::base_wallet::{did_value::DidValue, record_category::RecordCategory, BaseWallet}; +use super::{ + base_wallet::{ + did_value::DidValue, key_value::KeyValue, record_category::RecordCategory, BaseWallet, + }, + record_tags::RecordTags, +}; use crate::errors::error::{AriesVcxCoreError, AriesVcxCoreErrorKind, VcxCoreResult}; mod all_askar_records; @@ -22,7 +27,6 @@ pub mod askar_wallet_config; mod entry; mod entry_tags; pub mod key_method; -mod key_value; mod pack; mod packing_types; mod partial_record; @@ -45,6 +49,20 @@ impl BaseWallet for AskarWallet { async fn close_wallet(&self) -> VcxCoreResult<()> { todo!() } + + async fn create_key( + &self, + name: &str, + value: KeyValue, + tags: &RecordTags, + ) -> VcxCoreResult<()> { + let mut session = self.session().await?; + let tg: Vec<_> = tags.clone().into(); + let key = LocalKey::from_secret_bytes(KeyAlg::Ed25519, &value.signkey().decode()?[0..32])?; + Ok(session + .insert_key(name, &key, None, Some(&tg), None) + .await?) + } } impl AskarWallet { @@ -112,7 +130,7 @@ impl AskarWallet { rng_method: RngMethod, ) -> Result<(String, LocalKey), AriesVcxCoreError> { let key = LocalKey::from_seed(alg, seed, rng_method.into())?; - let key_name = local_key_to_bs58_name(&key)?; + let key_name = local_key_to_bs58_public_key(&key)?.into_inner(); session .insert_key(&key_name, &key, None, None, None) .await?; diff --git a/aries/aries_vcx_core/src/wallet/askar/pack.rs b/aries/aries_vcx_core/src/wallet/askar/pack.rs index 9d1200e4ca..08b665b175 100644 --- a/aries/aries_vcx_core/src/wallet/askar/pack.rs +++ b/aries/aries_vcx_core/src/wallet/askar/pack.rs @@ -4,12 +4,18 @@ use aries_askar::kms::{ use public_key::Key; use super::{ - askar_utils::{bs58_to_bytes, bytes_to_bs58, ed25519_to_x25519}, + askar_utils::ed25519_to_x25519, packing_types::{ - Base64String, Jwe, JweAlg, ProtectedData, ProtectedHeaderEnc, ProtectedHeaderTyp, Recipient, + Jwe, JweAlg, ProtectedData, ProtectedHeaderEnc, ProtectedHeaderTyp, Recipient, + }, +}; +use crate::{ + errors::error::{AriesVcxCoreError, AriesVcxCoreErrorKind, VcxCoreResult}, + wallet::{ + base_wallet::base64_string::Base64String, + utils::{bs58_to_bytes, bytes_to_bs58}, }, }; -use crate::errors::error::{AriesVcxCoreError, AriesVcxCoreErrorKind, VcxCoreResult}; fn check_supported_key_alg(key: &LocalKey) -> VcxCoreResult<()> { let supported_algs = vec![Ed25519]; diff --git a/aries/aries_vcx_core/src/wallet/askar/packing_types.rs b/aries/aries_vcx_core/src/wallet/askar/packing_types.rs index 8ce9e065b2..5141b15cbe 100644 --- a/aries/aries_vcx_core/src/wallet/askar/packing_types.rs +++ b/aries/aries_vcx_core/src/wallet/askar/packing_types.rs @@ -1,10 +1,6 @@ -use indy_vdr::utils::base64::{decode_urlsafe, encode_urlsafe}; use serde::{de::Unexpected, Deserialize, Serialize}; -use crate::{ - errors::error::{AriesVcxCoreError, AriesVcxCoreErrorKind, VcxCoreResult}, - wallet::askar::askar_utils::bytes_to_string, -}; +use crate::wallet::base_wallet::base64_string::Base64String; pub const PROTECTED_HEADER_ENC: &str = "xchacha20poly1305_ietf"; pub const PROTECTED_HEADER_TYP: &str = "JWM/1.0"; @@ -75,29 +71,6 @@ impl<'de> Deserialize<'de> for ProtectedHeaderTyp { } } -#[derive(Serialize, Deserialize, Debug)] -#[serde(transparent)] -pub struct Base64String(String); - -impl Base64String { - pub fn from_bytes(content: &[u8]) -> Self { - Self(encode_urlsafe(content)) - } - - pub fn decode(&self) -> VcxCoreResult> { - decode_urlsafe(&self.0) - .map_err(|e| AriesVcxCoreError::from_msg(AriesVcxCoreErrorKind::InvalidJson, e)) - } - - pub fn decode_to_string(&self) -> VcxCoreResult { - bytes_to_string(self.decode()?) - } - - pub fn as_bytes(&self) -> Vec { - self.0.as_bytes().into() - } -} - #[derive(Serialize, Deserialize, Debug)] pub struct Jwe { pub protected: Base64String, @@ -157,10 +130,6 @@ impl Recipient { Self::Authcrypt(inner) => &inner.header.kid, } } - - pub fn key_name(&self) -> &str { - &self.unwrap_kid()[0..16] - } } #[derive(Serialize, Deserialize, Debug)] diff --git a/aries/aries_vcx_core/src/wallet/askar/partial_record.rs b/aries/aries_vcx_core/src/wallet/askar/partial_record.rs index 5665de0485..e2cf4aa051 100644 --- a/aries/aries_vcx_core/src/wallet/askar/partial_record.rs +++ b/aries/aries_vcx_core/src/wallet/askar/partial_record.rs @@ -1,9 +1,11 @@ -use super::{askar_utils::value_from_entry, key_value::KeyValue}; +use super::askar_utils::value_from_entry; use crate::{ errors::error::VcxCoreResult, wallet::{ askar::askar_utils::{local_key_to_bs58_private_key, local_key_to_bs58_public_key}, - base_wallet::{record::PartialRecord, record_category::RecordCategory}, + base_wallet::{ + key_value::KeyValue, record::PartialRecord, record_category::RecordCategory, + }, }, }; diff --git a/aries/aries_vcx_core/src/wallet/askar/unpack.rs b/aries/aries_vcx_core/src/wallet/askar/unpack.rs index 9f2486d6b3..b6fe6b7eb4 100644 --- a/aries/aries_vcx_core/src/wallet/askar/unpack.rs +++ b/aries/aries_vcx_core/src/wallet/askar/unpack.rs @@ -10,12 +10,15 @@ use aries_askar::{ use public_key::{Key, KeyType}; use super::{ - askar_utils::{bs58_to_bytes, bytes_to_string, ed25519_to_x25519, from_json_str}, + askar_utils::{ed25519_to_x25519, from_json_str}, packing_types::{AnoncryptRecipient, AuthcryptRecipient, Jwe, ProtectedData, Recipient}, }; use crate::{ errors::error::{AriesVcxCoreError, AriesVcxCoreErrorKind, VcxCoreResult}, - wallet::structs_io::UnpackMessageOutput, + wallet::{ + structs_io::UnpackMessageOutput, + utils::{bs58_to_bytes, bytes_to_string}, + }, }; trait Unpack { @@ -111,7 +114,7 @@ async fn find_recipient_key<'a>( session: &mut Session, ) -> VcxCoreResult<(&'a Recipient, KeyEntry)> { for recipient in protected_data.recipients.iter() { - if let Some(key_entry) = session.fetch_key(recipient.key_name(), false).await? { + if let Some(key_entry) = session.fetch_key(recipient.unwrap_kid(), false).await? { return Ok((recipient, key_entry)); }; } diff --git a/aries/aries_vcx_core/src/wallet/base_wallet/base58_string.rs b/aries/aries_vcx_core/src/wallet/base_wallet/base58_string.rs new file mode 100644 index 0000000000..fcf46511df --- /dev/null +++ b/aries/aries_vcx_core/src/wallet/base_wallet/base58_string.rs @@ -0,0 +1,32 @@ +use serde::{Deserialize, Serialize}; + +use crate::{ + errors::error::VcxCoreResult, + wallet::utils::{bs58_to_bytes, bytes_to_bs58, bytes_to_string}, +}; + +#[derive(Serialize, Deserialize, Debug)] +#[serde(transparent)] +pub struct Base58String(String); + +impl Base58String { + pub fn from_bytes(content: &[u8]) -> Self { + Self(bytes_to_bs58(content)) + } + + pub fn decode(&self) -> VcxCoreResult> { + bs58_to_bytes(self.0.as_bytes()) + } + + pub fn decode_to_string(&self) -> VcxCoreResult { + bytes_to_string(self.decode()?) + } + + pub fn into_inner(self) -> String { + self.0 + } + + pub fn as_bytes(&self) -> Vec { + self.0.as_bytes().into() + } +} diff --git a/aries/aries_vcx_core/src/wallet/base_wallet/base64_string.rs b/aries/aries_vcx_core/src/wallet/base_wallet/base64_string.rs new file mode 100644 index 0000000000..c5444c722a --- /dev/null +++ b/aries/aries_vcx_core/src/wallet/base_wallet/base64_string.rs @@ -0,0 +1,34 @@ +use indy_vdr::utils::base64::{decode_urlsafe, encode_urlsafe}; +use serde::{Deserialize, Serialize}; + +use crate::{ + errors::error::{AriesVcxCoreError, AriesVcxCoreErrorKind, VcxCoreResult}, + wallet::utils::bytes_to_string, +}; + +#[derive(Serialize, Deserialize, Debug)] +#[serde(transparent)] +pub struct Base64String(String); + +impl Base64String { + pub fn from_bytes(content: &[u8]) -> Self { + Self(encode_urlsafe(content)) + } + + pub fn decode(&self) -> VcxCoreResult> { + decode_urlsafe(&self.0) + .map_err(|e| AriesVcxCoreError::from_msg(AriesVcxCoreErrorKind::InvalidJson, e)) + } + + pub fn decode_to_string(&self) -> VcxCoreResult { + bytes_to_string(self.decode()?) + } + + pub fn into_inner(self) -> String { + self.0 + } + + pub fn as_bytes(&self) -> Vec { + self.0.as_bytes().into() + } +} diff --git a/aries/aries_vcx_core/src/wallet/base_wallet/key_value.rs b/aries/aries_vcx_core/src/wallet/base_wallet/key_value.rs new file mode 100644 index 0000000000..098a46cd62 --- /dev/null +++ b/aries/aries_vcx_core/src/wallet/base_wallet/key_value.rs @@ -0,0 +1,23 @@ +use serde::{Deserialize, Serialize}; + +use super::base58_string::Base58String; + +#[derive(Debug, Deserialize, Serialize)] +pub struct KeyValue { + pub verkey: Base58String, + pub signkey: Base58String, +} + +impl KeyValue { + pub fn new(signkey: Base58String, verkey: Base58String) -> Self { + Self { signkey, verkey } + } + + pub fn signkey(&self) -> &Base58String { + &self.signkey + } + + pub fn verkey(&self) -> &Base58String { + &self.verkey + } +} diff --git a/aries/aries_vcx_core/src/wallet/base_wallet/migrate.rs b/aries/aries_vcx_core/src/wallet/base_wallet/migrate.rs index d3fdd087f8..d1e7a29d23 100644 --- a/aries/aries_vcx_core/src/wallet/base_wallet/migrate.rs +++ b/aries/aries_vcx_core/src/wallet/base_wallet/migrate.rs @@ -1,15 +1,20 @@ -use super::{record::Record, BaseWallet}; +use std::str::FromStr; + +use super::{ + record::{PartialRecord, Record}, + BaseWallet, +}; use crate::{ errors::error::{AriesVcxCoreErrorKind, VcxCoreResult}, - wallet::record_tags::RecordTags, + wallet::{base_wallet::record_category::RecordCategory, record_tags::RecordTags}, }; #[derive(Debug)] pub struct MigrationStats { - migrated: u32, - skipped: u32, - duplicated: u32, - failed: u32, + pub migrated: u32, + pub skipped: u32, + pub duplicated: u32, + pub failed: u32, } pub async fn migrate_records( @@ -21,10 +26,10 @@ where E: std::fmt::Display, { let mut records = src_wallet.all_records().await?; - let total = records.total_count(); + let total = records.total_count()?; info!("Migrating {total:?} records"); let mut num_record = 0; - let mut migration_result = MigrationStats { + let mut migration_stats = MigrationStats { migrated: 0, skipped: 0, duplicated: 0, @@ -36,85 +41,143 @@ where if num_record % 1000 == 1 { warn!( "Migrating wallet record number {num_record} / {total:?}, intermediary migration \ - result: ${migration_result:?}" + result: ${migration_stats:?}" ); } - trace!("Migrating record: {:?}", source_record); - let unwrapped_category = match &source_record.category() { - None => { - warn!( - "Skipping item missing 'category' field, record ({num_record}): \ - {source_record:?}" - ); - migration_result.skipped += 1; - continue; - } - Some(type_) => type_.clone(), - }; - let unwrapped_value = match &source_record.value() { - None => { - warn!( - "Skipping item missing 'value' field, record ({num_record}): {source_record:?}" - ); - migration_result.skipped += 1; - continue; - } - Some(value) => value.clone(), - }; - let unwrapped_tags = match &source_record.tags() { - None => RecordTags::default(), - Some(tags) => tags.clone(), - }; - let record = Record::builder() - .category(unwrapped_category.parse()?) - .name(source_record.name().to_string()) - .value(unwrapped_value) - .tags(unwrapped_tags) - .build(); + trace!("Migrating record: {:?}", source_record); + let maybe_record = + transform_record(num_record, source_record.clone(), &mut migration_stats); - let migrated_record = match migrate_fn(record) { - Ok(record) => match record { - None => { - warn!("Skipping non-migratable record ({num_record}): {source_record:?}"); - migration_result.skipped += 1; + if let Some(some_record) = maybe_record { + let migrated_record = match migrate_fn(some_record) { + Ok(record) => match record { + None => { + warn!("Skipping non-migratable record ({num_record}): {source_record:?}"); + migration_stats.skipped += 1; + continue; + } + Some(record) => record, + }, + Err(err) => { + warn!( + "Skipping item due failed item migration, record ({num_record}): \ + {source_record:?}, err: {err}" + ); + migration_stats.failed += 1; continue; } - Some(record) => record, - }, - Err(err) => { + }; + + if migrated_record.is_key() { + add_key(dest_wallet, &mut migration_stats, migrated_record).await + } else { + add_record(dest_wallet, &mut migration_stats, migrated_record).await + } + } + } + + warn!("Migration of total {total:?} records completed, result: ${migration_stats:?}"); + Ok(migration_stats) +} + +fn transform_record( + num_record: i32, + source_record: PartialRecord, + migration_stats: &mut MigrationStats, +) -> Option { + let category = match &source_record.category() { + None => { + warn!("Skipping item missing 'type' field, record ({num_record}): {source_record:?}"); + migration_stats.skipped += 1; + return None; + } + Some(cat) => match RecordCategory::from_str(cat) { + Ok(record_category) => record_category, + Err(_) => { warn!( - "Skipping item due failed item migration, record ({num_record}): \ - {source_record:?}, err: {err}" + "Skipping item due to invalid category, record ({num_record}): \ + {source_record:?}" ); - migration_result.failed += 1; - continue; + migration_stats.skipped += 1; + return None; } - }; + }, + }; + let value = match &source_record.value() { + None => { + warn!("Skipping item missing 'value' field, record ({num_record}): {source_record:?}"); + migration_stats.skipped += 1; + return None; + } + Some(value) => value.clone(), + }; + let tags = match source_record.tags() { + None => RecordTags::default(), + Some(tags) => tags.clone(), + }; - match dest_wallet.add_record(migrated_record.clone()).await { - Err(err) => match err.kind() { - AriesVcxCoreErrorKind::DuplicationWalletRecord => { - trace!( - "Record type: {migrated_record:?} already exists in destination wallet, \ - skipping" - ); - migration_result.duplicated += 1; - continue; - } - _ => { - error!( - "Error adding record {migrated_record:?} to destination wallet: {err:?}" - ); - migration_result.failed += 1; - return Err(err); - } - }, - Ok(()) => { - migration_result.migrated += 1; + let record = Record::builder() + .category(category) + .name(source_record.name().into()) + .value(value) + .tags(tags) + .build(); + + info!("Migrating wallet record {record:?}"); + + Some(record) +} + +async fn add_key( + new_wallet: &impl BaseWallet, + migration_stats: &mut MigrationStats, + key_record: Record, +) { + let key_value = match key_record.key_value() { + Ok(val) => val, + Err(err) => { + error!("Error parsing key value for {key_record:?}, is this record a key?: {err:?}"); + migration_stats.failed += 1; + return; + } + }; + + match new_wallet + .create_key(key_record.name(), key_value, key_record.tags()) + .await + { + Err(err) => { + error!("Error adding key {key_record:?} to destination wallet: {err:?}"); + migration_stats.failed += 1; + } + Ok(_) => { + migration_stats.migrated += 1; + } + } +} + +async fn add_record( + new_wallet: &impl BaseWallet, + migration_stats: &mut MigrationStats, + record: Record, +) { + match new_wallet.add_record(record.clone()).await { + Err(err) => match err.kind() { + AriesVcxCoreErrorKind::CredDefAlreadyCreated + | AriesVcxCoreErrorKind::DuplicationSchema + | AriesVcxCoreErrorKind::DuplicationWalletRecord + | AriesVcxCoreErrorKind::DuplicationDid => { + trace!("Record type: {record:?} already exists in destination wallet, skipping"); + migration_stats.duplicated += 1; + } + _ => { + error!("Error adding record {record:?} to destination wallet: {err:?}"); + migration_stats.failed += 1; } + }, + Ok(()) => { + migration_stats.migrated += 1; } } - warn!("Migration of total {total:?} records completed, result: ${migration_result:?}"); - Ok(migration_result) } diff --git a/aries/aries_vcx_core/src/wallet/base_wallet/mod.rs b/aries/aries_vcx_core/src/wallet/base_wallet/mod.rs index 6c69388b23..0666f4bcde 100644 --- a/aries/aries_vcx_core/src/wallet/base_wallet/mod.rs +++ b/aries/aries_vcx_core/src/wallet/base_wallet/mod.rs @@ -1,12 +1,19 @@ use async_trait::async_trait; -use self::{did_wallet::DidWallet, issuer_config::IssuerConfig, record_wallet::RecordWallet}; +use self::{ + did_wallet::DidWallet, issuer_config::IssuerConfig, key_value::KeyValue, + record_wallet::RecordWallet, +}; +use super::record_tags::RecordTags; use crate::errors::error::VcxCoreResult; +pub mod base58_string; +pub mod base64_string; pub mod did_data; pub mod did_value; pub mod did_wallet; pub mod issuer_config; +pub mod key_value; pub mod migrate; pub mod record; pub mod record_category; @@ -44,6 +51,9 @@ pub trait BaseWallet: RecordWallet + DidWallet + Send + Sync + std::fmt::Debug { .to_string(), }) } + + async fn create_key(&self, name: &str, value: KeyValue, tags: &RecordTags) + -> VcxCoreResult<()>; } #[cfg(test)] @@ -59,7 +69,7 @@ mod tests { record_wallet::RecordWallet, }, record_tags::{RecordTag, RecordTags}, - utils::{did_from_key, random_seed}, + utils::random_seed, }, }; @@ -131,10 +141,7 @@ mod tests { let new_verkey = wallet.key_for_did(first_data.did()).await.unwrap(); assert_eq!(new_verkey.key().len(), 32); - assert_eq!( - did_from_key(new_key.clone()), - did_from_key(new_verkey.clone()) - ); + assert_eq!(new_key.base58(), new_verkey.base58()); assert_eq!(new_key.key(), new_verkey.key()); } @@ -156,7 +163,7 @@ mod tests { let new_verkey = wallet.key_for_did(first_data.did()).await.unwrap(); - assert_eq!(did_from_key(new_key), did_from_key(new_verkey)); + assert_eq!(new_key.base58(), new_verkey.base58()); let second_new_key = wallet .replace_did_key_start(first_data.did(), Some(&random_seed())) @@ -170,10 +177,7 @@ mod tests { let second_new_verkey = wallet.key_for_did(first_data.did()).await.unwrap(); - assert_eq!( - did_from_key(second_new_key), - did_from_key(second_new_verkey) - ); + assert_eq!(second_new_key.base58(), second_new_verkey.base58()); } #[tokio::test] @@ -209,11 +213,8 @@ mod tests { let first_new_verkey = wallet.key_for_did(first_data.did()).await.unwrap(); let second_new_verkey = wallet.key_for_did(second_data.did()).await.unwrap(); - assert_eq!(did_from_key(first_new_key), did_from_key(first_new_verkey)); - assert_eq!( - did_from_key(second_new_key), - did_from_key(second_new_verkey) - ); + assert_eq!(first_new_key.base58(), first_new_verkey.base58()); + assert_eq!(second_new_key.base58(), second_new_verkey.base58()); } #[tokio::test] diff --git a/aries/aries_vcx_core/src/wallet/base_wallet/record.rs b/aries/aries_vcx_core/src/wallet/base_wallet/record.rs index ab483825c7..36504b084a 100644 --- a/aries/aries_vcx_core/src/wallet/base_wallet/record.rs +++ b/aries/aries_vcx_core/src/wallet/base_wallet/record.rs @@ -1,7 +1,7 @@ use async_trait::async_trait; use typed_builder::TypedBuilder; -use super::record_category::RecordCategory; +use super::{key_value::KeyValue, record_category::RecordCategory}; use crate::{errors::error::VcxCoreResult, wallet::record_tags::RecordTags}; #[derive(Debug, Default, Clone, TypedBuilder)] @@ -29,6 +29,14 @@ impl Record { pub fn tags(&self) -> &RecordTags { &self.tags } + + pub fn is_key(&self) -> bool { + self.category == RecordCategory::Key + } + + pub fn key_value(&self) -> VcxCoreResult { + Ok(serde_json::from_str(&self.value)?) + } } #[derive(Debug, Default, Clone, TypedBuilder)] diff --git a/aries/aries_vcx_core/src/wallet/base_wallet/record_category.rs b/aries/aries_vcx_core/src/wallet/base_wallet/record_category.rs index c830106573..98e43982b6 100644 --- a/aries/aries_vcx_core/src/wallet/base_wallet/record_category.rs +++ b/aries/aries_vcx_core/src/wallet/base_wallet/record_category.rs @@ -21,7 +21,7 @@ const DID: &str = "Indy::Did"; const TMP_DID: &str = "Indy::TemporaryDid"; const KEY: &str = "Indy::Key"; -#[derive(Clone, Copy, Debug, Default)] +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] pub enum RecordCategory { #[default] LinkSecret, diff --git a/aries/aries_vcx_core/src/wallet/indy/indy_wallet_config.rs b/aries/aries_vcx_core/src/wallet/indy/indy_wallet_config.rs index e0f29eda74..188b124a3e 100644 --- a/aries/aries_vcx_core/src/wallet/indy/indy_wallet_config.rs +++ b/aries/aries_vcx_core/src/wallet/indy/indy_wallet_config.rs @@ -1,5 +1,8 @@ use async_trait::async_trait; -use indy_api_types::{domain::wallet::default_key_derivation_method, errors::IndyErrorKind}; +use indy_api_types::{ + domain::wallet::{default_key_derivation_method, Config, Credentials}, + errors::IndyErrorKind, +}; use serde::{Deserialize, Serialize}; use typed_builder::TypedBuilder; use vdrtools::Locator; @@ -33,12 +36,9 @@ pub struct IndyWalletConfig { pub rekey_derivation_method: Option, } -#[async_trait] -impl ManageWallet for IndyWalletConfig { - type ManagedWalletType = IndySdkWallet; - - async fn create_wallet(&self) -> VcxCoreResult { - let credentials = vdrtools::types::domain::wallet::Credentials { +impl IndyWalletConfig { + pub fn to_config_and_creds(&self) -> VcxCoreResult<(Config, Credentials)> { + let creds = Credentials { key: self.wallet_key.clone(), key_derivation_method: parse_key_derivation_method(&self.wallet_key_derivation)?, @@ -52,21 +52,31 @@ impl ManageWallet for IndyWalletConfig { .transpose()?, }; + let config = Config { + id: self.wallet_name.clone(), + storage_type: self.wallet_type.clone(), + storage_config: self + .storage_config + .as_deref() + .map(serde_json::from_str) + .transpose()?, + cache: None, + }; + + Ok((config, creds)) + } +} + +#[async_trait] +impl ManageWallet for IndyWalletConfig { + type ManagedWalletType = IndySdkWallet; + + async fn create_wallet(&self) -> VcxCoreResult { + let (config, creds) = self.to_config_and_creds()?; + let res = Locator::instance() .wallet_controller - .create( - vdrtools::types::domain::wallet::Config { - id: self.wallet_name.clone(), - storage_type: self.wallet_type.clone(), - storage_config: self - .storage_config - .as_deref() - .map(serde_json::from_str) - .transpose()?, - cache: None, - }, - credentials, - ) + .create(config, creds) .await; match res { @@ -88,75 +98,22 @@ impl ManageWallet for IndyWalletConfig { } async fn open_wallet(&self) -> VcxCoreResult { + let (config, creds) = self.to_config_and_creds()?; + let handle = Locator::instance() .wallet_controller - .open( - vdrtools::types::domain::wallet::Config { - id: self.wallet_name.clone(), - storage_type: self.wallet_type.clone(), - storage_config: self - .storage_config - .as_deref() - .map(serde_json::from_str) - .transpose()?, - cache: None, - }, - vdrtools::types::domain::wallet::Credentials { - key: self.wallet_key.clone(), - key_derivation_method: parse_key_derivation_method( - &self.wallet_key_derivation, - )?, - - rekey: self.rekey.clone(), - rekey_derivation_method: self - .rekey_derivation_method - .as_deref() - .map(parse_key_derivation_method) - .transpose()? - .unwrap_or_else(default_key_derivation_method), - - storage_credentials: self - .storage_credentials - .as_deref() - .map(serde_json::from_str) - .transpose()?, - }, - ) + .open(config, creds) .await?; Ok(IndySdkWallet::new(handle)) } async fn delete_wallet(&self) -> VcxCoreResult<()> { - let credentials = vdrtools::types::domain::wallet::Credentials { - key: self.wallet_key.clone(), - key_derivation_method: parse_key_derivation_method(&self.wallet_key_derivation)?, - - rekey: None, - rekey_derivation_method: default_key_derivation_method(), - - storage_credentials: self - .storage_credentials - .as_deref() - .map(serde_json::from_str) - .transpose()?, - }; + let (config, creds) = self.to_config_and_creds()?; let res = Locator::instance() .wallet_controller - .delete( - vdrtools::types::domain::wallet::Config { - id: self.wallet_name.clone(), - storage_type: self.wallet_type.clone(), - storage_config: self - .storage_config - .as_deref() - .map(serde_json::from_str) - .transpose()?, - cache: None, - }, - credentials, - ) + .delete(config, creds) .await; match res { diff --git a/aries/aries_vcx_core/src/wallet/indy/mod.rs b/aries/aries_vcx_core/src/wallet/indy/mod.rs index 914a2816aa..3972dfacfc 100644 --- a/aries/aries_vcx_core/src/wallet/indy/mod.rs +++ b/aries/aries_vcx_core/src/wallet/indy/mod.rs @@ -1,14 +1,21 @@ use std::str::FromStr; use async_trait::async_trait; -use indy_api_types::domain::wallet::{default_key_derivation_method, IndyRecord}; +use indy_api_types::{ + domain::wallet::{default_key_derivation_method, IndyRecord}, + errors::IndyErrorKind, +}; use serde::Deserialize; use serde_json::Value; use vdrtools::Locator; -use self::indy_tags::IndyTags; -use super::base_wallet::{ - record::Record, record_category::RecordCategory, search_filter::SearchFilter, BaseWallet, +use self::{indy_tags::IndyTags, indy_wallet_config::IndyWalletConfig}; +use super::{ + base_wallet::{ + key_value::KeyValue, record::Record, record_category::RecordCategory, + record_wallet::RecordWallet, search_filter::SearchFilter, BaseWallet, + }, + record_tags::RecordTags, }; use crate::{ errors::error::{AriesVcxCoreError, AriesVcxCoreErrorKind, VcxCoreResult}, @@ -57,6 +64,46 @@ impl IndySdkWallet { IndySdkWallet { wallet_handle } } + pub async fn create(wallet_config: &IndyWalletConfig) -> VcxCoreResult { + let (config, creds) = wallet_config.to_config_and_creds()?; + + let res = Locator::instance() + .wallet_controller + .create(config, creds) + .await; + + match res { + Ok(()) => Self::open(wallet_config).await, + + Err(err) if err.kind() == IndyErrorKind::WalletAlreadyExists => { + warn!( + "wallet \"{}\" already exists. skipping creation", + wallet_config.wallet_name + ); + Self::open(wallet_config).await + } + + Err(err) => Err(AriesVcxCoreError::from_msg( + AriesVcxCoreErrorKind::WalletCreate, + format!( + "could not create wallet {}: {}", + wallet_config.wallet_name, err, + ), + )), + } + } + + async fn open(wallet_config: &IndyWalletConfig) -> VcxCoreResult { + let (config, creds) = wallet_config.to_config_and_creds()?; + + let handle = Locator::instance() + .wallet_controller + .open(config, creds) + .await?; + + Ok(Self::new(handle)) + } + pub fn get_wallet_handle(&self) -> WalletHandle { self.wallet_handle } @@ -146,6 +193,23 @@ impl BaseWallet for IndySdkWallet { Ok(()) } + + async fn create_key( + &self, + name: &str, + value: KeyValue, + tags: &RecordTags, + ) -> VcxCoreResult<()> { + let value = serde_json::to_string(&value)?; + let record = Record::builder() + .name(name.into()) + .value(value) + .category(RecordCategory::Key) + .tags(tags.clone()) + .build(); + + Ok(self.add_record(record).await?) + } } #[cfg(test)] diff --git a/aries/aries_vcx_core/src/wallet/utils.rs b/aries/aries_vcx_core/src/wallet/utils.rs index 13c550c40e..510a49560d 100644 --- a/aries/aries_vcx_core/src/wallet/utils.rs +++ b/aries/aries_vcx_core/src/wallet/utils.rs @@ -1,6 +1,7 @@ -use public_key::Key; use rand::{distributions::Alphanumeric, Rng}; +use crate::errors::error::{AriesVcxCoreError, AriesVcxCoreErrorKind, VcxCoreResult}; + #[allow(dead_code)] pub fn random_seed() -> String { rand::thread_rng() @@ -10,7 +11,17 @@ pub fn random_seed() -> String { .collect() } -#[allow(dead_code)] -pub fn did_from_key(key: Key) -> String { - key.base58()[0..16].to_string() +pub fn bytes_to_string(vec: Vec) -> VcxCoreResult { + String::from_utf8(vec) + .map_err(|err| AriesVcxCoreError::from_msg(AriesVcxCoreErrorKind::InvalidInput, err)) +} + +pub fn bytes_to_bs58(bytes: &[u8]) -> String { + bs58::encode(bytes).into_string() +} + +pub fn bs58_to_bytes(key: &[u8]) -> VcxCoreResult> { + bs58::decode(key) + .into_vec() + .map_err(|err| AriesVcxCoreError::from_msg(AriesVcxCoreErrorKind::InvalidInput, err)) } diff --git a/aries/misc/test_utils/src/mock_wallet.rs b/aries/misc/test_utils/src/mock_wallet.rs index 555ac7abc6..f7ac3779bd 100644 --- a/aries/misc/test_utils/src/mock_wallet.rs +++ b/aries/misc/test_utils/src/mock_wallet.rs @@ -5,6 +5,7 @@ use aries_vcx_core::{ did_data::DidData, did_wallet::DidWallet, issuer_config::IssuerConfig, + key_value::KeyValue, record::{AllRecords, PartialRecord, Record}, record_category::RecordCategory, record_wallet::RecordWallet, @@ -48,6 +49,15 @@ impl BaseWallet for MockWallet { async fn configure_issuer(&self, key_seed: &str) -> VcxCoreResult { Ok(IssuerConfig::builder().build()) } + + async fn create_key( + &self, + name: &str, + value: KeyValue, + tags: &RecordTags, + ) -> VcxCoreResult<()> { + Ok(()) + } } pub const DID: &str = "FhrSrYtQcw3p9xwf7NYemf"; diff --git a/aries/misc/wallet_migrator/Cargo.toml b/aries/misc/wallet_migrator/Cargo.toml index d5a91b00ff..fc1930ccdf 100644 --- a/aries/misc/wallet_migrator/Cargo.toml +++ b/aries/misc/wallet_migrator/Cargo.toml @@ -4,14 +4,22 @@ version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +vdrtools_wallet = ["aries_vcx_core/vdrtools_wallet"] +askar_wallet = ["aries_vcx_core/askar_wallet"] [dependencies] -aries_vcx_core = { path = "../../aries_vcx_core", features = ["credx", "vdrtools_wallet"] } +aries_vcx_core = { path = "../../aries_vcx_core", features = ["credx"] } credx = { package = "indy-credx", git = "https://github.com/hyperledger/indy-shared-rs", tag = "v1.1.0" } vdrtools = { package = "libvdrtools", path = "../legacy/libvdrtools" } +serde = { version = "1.0.159", features = ["derive"] } serde_json = "1.0.96" thiserror = "1.0.40" log = "0.4.19" +public_key = { path = "../../../did_core/public_key"} [dev-dependencies] tokio = { version = "1.28.2", features = ["macros", "rt"] } +uuid = { version = "1.3.0", default-features = false, features = ["v4"] } +test-log = "0.2.14" + diff --git a/aries/misc/wallet_migrator/src/credx2anoncreds/conv.rs b/aries/misc/wallet_migrator/src/credx2anoncreds/conv.rs deleted file mode 100644 index e30267ef93..0000000000 --- a/aries/misc/wallet_migrator/src/credx2anoncreds/conv.rs +++ /dev/null @@ -1,43 +0,0 @@ -use vdrtools::types::domain::wallet::IndyRecord; - -use crate::error::MigrationResult; - -pub fn convert_master_secret(record: IndyRecord) -> MigrationResult { - Ok(record) -} - -pub fn convert_cred(record: IndyRecord) -> MigrationResult { - Ok(record) -} - -pub fn convert_cred_def(record: IndyRecord) -> MigrationResult { - Ok(record) -} - -pub fn convert_cred_def_priv_key(record: IndyRecord) -> MigrationResult { - Ok(record) -} - -pub fn convert_cred_def_correctness_proof(record: IndyRecord) -> MigrationResult { - Ok(record) -} - -pub fn convert_schema(record: IndyRecord) -> MigrationResult { - Ok(record) -} - -pub fn convert_rev_reg(record: IndyRecord) -> MigrationResult { - Ok(record) -} - -pub fn convert_rev_reg_delta(record: IndyRecord) -> MigrationResult { - Ok(record) -} - -pub fn convert_rev_reg_def(record: IndyRecord) -> MigrationResult { - Ok(record) -} - -pub fn convert_rev_reg_def_priv(record: IndyRecord) -> MigrationResult { - Ok(record) -} diff --git a/aries/misc/wallet_migrator/src/credx2anoncreds/mod.rs b/aries/misc/wallet_migrator/src/credx2anoncreds/mod.rs deleted file mode 100644 index e906693400..0000000000 --- a/aries/misc/wallet_migrator/src/credx2anoncreds/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod conv; diff --git a/aries/misc/wallet_migrator/src/error.rs b/aries/misc/wallet_migrator/src/error.rs index b7cd400526..823bd354f2 100644 --- a/aries/misc/wallet_migrator/src/error.rs +++ b/aries/misc/wallet_migrator/src/error.rs @@ -1,7 +1,6 @@ use aries_vcx_core::errors::error::AriesVcxCoreError; use serde_json::Error as JsonError; use thiserror::Error as ThisError; -use vdrtools::IndyError; pub type MigrationResult = Result; @@ -9,8 +8,8 @@ pub type MigrationResult = Result; pub enum MigrationError { #[error("JSON error: {0}")] Json(#[from] JsonError), - #[error("Indy error: {0}")] - Indy(#[from] IndyError), #[error("VcxCore error: {0}")] VcxCore(#[from] AriesVcxCoreError), + #[error("Unsupported wallet migration")] + Unsupported, } diff --git a/aries/misc/wallet_migrator/src/lib.rs b/aries/misc/wallet_migrator/src/lib.rs index 442ff675bf..b1f6c2c4ac 100644 --- a/aries/misc/wallet_migrator/src/lib.rs +++ b/aries/misc/wallet_migrator/src/lib.rs @@ -1,35 +1,50 @@ -pub mod credx2anoncreds; pub mod error; -pub mod vdrtools2credx; +pub mod migrate2askar; -use std::fmt::Display; - -use aries_vcx_core::wallet::base_wallet::{migrate::migrate_records, record::Record, BaseWallet}; -use error::MigrationResult; +use aries_vcx_core::wallet::base_wallet::{ + migrate::{migrate_records, MigrationStats}, + record::Record, + BaseWallet, +}; +use error::{MigrationError, MigrationResult}; use log::info; +use migrate2askar::migrate_any_record_to_askar; pub use vdrtools::types::domain::wallet::IndyRecord; +pub enum MigrationKind { + ToAskar, + Unknown, +} + +impl MigrationKind { + pub fn select_migrate_fn( + &self, + ) -> MigrationResult Result, MigrationError>> { + match self { + MigrationKind::ToAskar => Ok(migrate_any_record_to_askar), + MigrationKind::Unknown => Err(error::MigrationError::Unsupported), + } + } +} + /// Retrieves all records from the source wallet and migrates them /// by applying the `migrate_fn` argument. The records are then /// placed in the destination wallet. -pub async fn migrate_wallet( +pub async fn migrate_wallet( src_wallet: &impl BaseWallet, dest_wallet: &impl BaseWallet, - migrate_fn: impl FnMut(Record) -> Result, E>, -) -> MigrationResult<()> -where - E: Display, -{ + migration_kind: MigrationKind, +) -> MigrationResult { info!("Starting wallet migration"); info!( "Migrating records from wallet with handle {src_wallet:?} to wallet with handle \ {dest_wallet:?}" ); - - migrate_records(src_wallet, dest_wallet, migrate_fn).await?; + let migrate_fn = migration_kind.select_migrate_fn()?; + let res = migrate_records(src_wallet, dest_wallet, migrate_fn).await?; info!("Migration completed"); - Ok(()) + Ok(res) } diff --git a/aries/misc/wallet_migrator/src/migrate2askar/mod.rs b/aries/misc/wallet_migrator/src/migrate2askar/mod.rs new file mode 100644 index 0000000000..30434f3e4c --- /dev/null +++ b/aries/misc/wallet_migrator/src/migrate2askar/mod.rs @@ -0,0 +1,583 @@ +use aries_vcx_core::wallet::base_wallet::{ + did_value::DidValue, record::Record, record_category::RecordCategory, +}; +use public_key::{Key, KeyType}; +use serde::Deserialize; + +use crate::error::MigrationResult; + +pub fn migrate_any_record_to_askar(record: Record) -> MigrationResult> { + Ok(match record.category() { + RecordCategory::Did => transform_did(record, RecordCategory::Did), + RecordCategory::TmpDid => transform_did(record, RecordCategory::TmpDid), + _ => Some(record), + }) +} + +#[derive(Deserialize, Debug)] +pub struct DidDataDeserializable { + pub did: String, + pub verkey: String, +} + +fn transform_did(record: Record, category: RecordCategory) -> Option { + let val = match serde_json::from_str::(record.value()) { + Ok(res) => res, + Err(_) => return None, + }; + + let key = match Key::from_base58(&val.verkey, KeyType::Ed25519) { + Ok(key_content) => key_content, + Err(_) => return None, + }; + + let value = match serde_json::to_string(&DidValue::new(&key)) { + Ok(res) => res, + Err(_) => return None, + }; + + Some( + Record::builder() + .category(category) + .name(record.name().to_owned()) + .tags(record.tags().clone()) + .value(value) + .build(), + ) +} + +#[cfg(test)] +#[cfg(all(feature = "vdrtools_wallet", feature = "askar_wallet"))] +mod compat_tests { + use std::collections::{HashMap, HashSet}; + + use aries_vcx_core::wallet::{ + askar::{askar_wallet_config::AskarWalletConfig, key_method::KeyMethod, AskarWallet}, + base_wallet::{ + did_wallet::DidWallet, record::Record, record_category::RecordCategory, + record_wallet::RecordWallet, + }, + indy::{indy_wallet_config::IndyWalletConfig, IndySdkWallet}, + }; + use serde_json::json; + use uuid::Uuid; + use vdrtools::Locator; + + use crate::{migrate_wallet, MigrationKind}; + + type TestDataVec = Vec<(RecordCategory, String, u32)>; + struct TestData { + data_vec: TestDataVec, + expected_count: u32, + } + + fn make_dummy_master_secret() -> String { + json!({ + "value": { + "ms": "1234567890" + } + }) + .to_string() + } + + fn make_dummy_cred() -> String { + let cred_sig_str = json!({ + "p_credential": { + "m_2": "1234567890", + "a": "1234567890", + "e": "1234567890", + "v": "1234567890" + }, + "r_credential": null + }) + .to_string(); + + let sig_cor_proof_str = json!({ + "se": "1234567890", + "c": "1234567890" + }) + .to_string(); + + serde_json::to_string(&vdrtools::Credential { + schema_id: vdrtools::SchemaId("test_schema_id".to_owned()), + cred_def_id: vdrtools::CredentialDefinitionId("test_cred_def_id".to_owned()), + rev_reg_id: Some(vdrtools::RevocationRegistryId("test_rev_reg_id".to_owned())), + values: vdrtools::CredentialValues(HashMap::new()), + signature: serde_json::from_str(&cred_sig_str).unwrap(), + signature_correctness_proof: serde_json::from_str(&sig_cor_proof_str).unwrap(), + rev_reg: None, + witness: None, + }) + .unwrap() + } + + fn make_dummy_cred_def() -> String { + let primary = json!({ + "n": "1234567890", + "s": "1234567890", + "r": {}, + "rctxt": "1234567890", + "z": "1234567890", + }) + .to_string(); + + serde_json::to_string(&vdrtools::CredentialDefinition::CredentialDefinitionV1( + vdrtools::CredentialDefinitionV1 { + id: vdrtools::CredentialDefinitionId("test_cred_def_id".to_owned()), + schema_id: vdrtools::SchemaId("test_schema_id".to_owned()), + signature_type: vdrtools::SignatureType::CL, + tag: "{}".to_owned(), + value: vdrtools::CredentialDefinitionData { + primary: serde_json::from_str(&primary).unwrap(), + revocation: None, + }, + }, + )) + .unwrap() + } + + fn make_dummy_cred_def_priv_key() -> String { + let priv_key = json!({ + "p_key": { + "p": "1234567890", + "q": "1234567890" + } + }) + .to_string(); + + serde_json::to_string(&vdrtools::CredentialDefinitionPrivateKey { + value: serde_json::from_str(&priv_key).unwrap(), + }) + .unwrap() + } + + fn make_dummy_cred_def_correctness_proof() -> String { + let cor_proof = json!({ + "c": "1234567890", + "xz_cap": "1234567890", + "xr_cap": [] + }) + .to_string(); + + serde_json::to_string(&vdrtools::CredentialDefinitionCorrectnessProof { + value: serde_json::from_str(&cor_proof).unwrap(), + }) + .unwrap() + } + + fn make_dummy_schema() -> String { + serde_json::to_string(&vdrtools::Schema::SchemaV1(vdrtools::SchemaV1 { + id: vdrtools::SchemaId("test_schema_id".to_owned()), + name: "test_schema_name".to_owned(), + version: "test_schema_version".to_owned(), + attr_names: vdrtools::AttributeNames(HashSet::new()), + seq_no: None, + })) + .unwrap() + } + + fn make_dummy_schema_id() -> String { + "test_schema_id".to_owned() + } + + fn make_dummy_rev_reg() -> String { + let rev_reg = json!({ + "accum": "21 11ED98357F9B9B3077E633D35A72CECEF107F85DA7BBFBF2873E2EE7E0F27D326 21 1371CDA6174D6F01A39157428768D328B4B80088EB14AA0AAB7F046B645E1A235 6 65BBFAC37012790BB8B283F164BE3C0585AB60CD7B72123E4DC43DDA7A6A4E6D 4 3BB64FAF922865095CD5AA4349C0437D04EA30FB7592D932531732F2DCB83DB8 6 77039B80A78AB4A2476373C6F8ECC5E2D94B8F37F924549AFA247E2D6EE86DEE 4 24E94FB6B5233B22BDF47745AA821A1797BC6504BC11D5B825B4F8137F1E307F" + }).to_string(); + + serde_json::to_string(&vdrtools::RevocationRegistry::RevocationRegistryV1( + vdrtools::RevocationRegistryV1 { + value: serde_json::from_str(&rev_reg).unwrap(), + }, + )) + .unwrap() + } + + fn make_dummy_rev_reg_delta() -> String { + let rev_reg = json!({ + "prevAccum": "21 11ED98357F9B9B3077E633D35A72CECEF107F85DA7BBFBF2873E2EE7E0F27D326 21 1371CDA6174D6F01A39157428768D328B4B80088EB14AA0AAB7F046B645E1A235 6 65BBFAC37012790BB8B283F164BE3C0585AB60CD7B72123E4DC43DDA7A6A4E6D 4 3BB64FAF922865095CD5AA4349C0437D04EA30FB7592D932531732F2DCB83DB8 6 77039B80A78AB4A2476373C6F8ECC5E2D94B8F37F924549AFA247E2D6EE86DEE 4 24E94FB6B5233B22BDF47745AA821A1797BC6504BC11D5B825B4F8137F1E307F", + "accum": "21 11ED98357F9B9B3077E633D35A72CECEF107F85DA7BBFBF2873E2EE7E0F27D326 21 1371CDA6174D6F01A39157428768D328B4B80088EB14AA0AAB7F046B645E1A235 6 65BBFAC37012790BB8B283F164BE3C0585AB60CD7B72123E4DC43DDA7A6A4E6D 4 3BB64FAF922865095CD5AA4349C0437D04EA30FB7592D932531732F2DCB83DB8 6 77039B80A78AB4A2476373C6F8ECC5E2D94B8F37F924549AFA247E2D6EE86DEE 4 24E94FB6B5233B22BDF47745AA821A1797BC6504BC11D5B825B4F8137F1E307F", + "issued": [], + "revoked": [] + }).to_string(); + + let rev_reg_delta = vdrtools::RevocationRegistryDelta::RevocationRegistryDeltaV1( + vdrtools::RevocationRegistryDeltaV1 { + value: serde_json::from_str(&rev_reg).unwrap(), + }, + ); + + json!(rev_reg_delta).to_string() + } + + fn make_dummy_rev_reg_info() -> String { + serde_json::to_string(&vdrtools::RevocationRegistryInfo { + id: vdrtools::RevocationRegistryId("test_rev_reg_id".to_owned()), + curr_id: 1, + used_ids: HashSet::new(), + }) + .unwrap() + } + + fn make_dummy_rev_reg_def() -> String { + let accum_key = json!({ + "z": "1 042CDA7AA76FFD05D0EA1C97F0F238A579AAE4348442298B7F8513277A21D671 1 04C49DDECC3731B11BC98A1495C39DF7F94A297EA6D691DADAF1493300D2977E 1 0D78B673DE9F1CE37FA98E0765B69D963BFF9973317722981943797EFEF1F628 1 1F4DFD2C1ED2BD80D9D92600AB7A1B2911180B4B44C6BC42962084AC4C042385 1 07724871AD4FFC1C30BCAEFE289FAF6F2F322203C34D8D2D3C36DFD816AF9430 1 050F4014E2AFD680A67C197B39D35CA4D03332D6C6922A4D991EC1402B7FF4E6 1 07C0DCAF303CF4B0741447A1A808C8C2BAE6CD30397AAF834428848FEE70FC3D 1 1C028C08BD426B053942A4409F71A5215B6B0B58FF651C72303F1B4C5DDB84C4 1 22DE20332A0E1B0C58F76CBADBF73D0B6875A5F3479AC0E3C4D27A605656BF6E 1 1F461563E404002F9AFE37D09FA98F34B4666D1A4424C89B3C8CE7E85DE23B8A 1 096DA55063F6ABA1B578471DEBDEACA5DE485994F99099BBBB6E326DDF8C3DD2 1 12FFCEFF31CE5781FF6BB9AB279BF8A100E97D43B0F6C31E6FCD6373227E34FD" + }).to_string(); + + serde_json::to_string( + &vdrtools::RevocationRegistryDefinition::RevocationRegistryDefinitionV1( + vdrtools::RevocationRegistryDefinitionV1 { + id: vdrtools::RevocationRegistryId("test_rev_reg_id".to_owned()), + revoc_def_type: vdrtools::RegistryType::CL_ACCUM, + tag: "{}".to_owned(), + cred_def_id: vdrtools::CredentialDefinitionId("test_cred_def_id".to_owned()), + value: vdrtools::RevocationRegistryDefinitionValue { + issuance_type: vdrtools::IssuanceType::ISSUANCE_BY_DEFAULT, + max_cred_num: 10, + public_keys: vdrtools::RevocationRegistryDefinitionValuePublicKeys { + accum_key: serde_json::from_str(&accum_key).unwrap(), + }, + tails_hash: "abc".to_owned(), + tails_location: "/dev/null".to_owned(), + }, + }, + ), + ) + .unwrap() + } + + fn make_dummy_rev_reg_def_priv() -> String { + let rev_key_priv = json!({ + "gamma": "12345" + }) + .to_string(); + + serde_json::to_string(&vdrtools::RevocationRegistryDefinitionPrivate { + value: serde_json::from_str(&rev_key_priv).unwrap(), + }) + .unwrap() + } + + fn generate_test_data() -> TestData { + let master_secret_count = 1; + let indy_cred_count = 1; + let indy_cred_def_count = 1; + let indy_cred_def_priv_count = 1; + let indy_cred_def_cr_proof_count = 1; + let indy_schema_count = 1; + let indy_schema_id_count = 1; + let indy_rev_reg_count = 1; + let indy_rev_reg_delta_count = 1; + let indy_rev_reg_info_count = 1; + let infy_rev_reg_def_count = 1; + let indy_rev_reg_def_priv_count = 1; + + let wallet_items = vec![ + ( + RecordCategory::LinkSecret, + make_dummy_master_secret(), + master_secret_count, + ), + (RecordCategory::Cred, make_dummy_cred(), indy_cred_count), + ( + RecordCategory::CredDef, + make_dummy_cred_def(), + indy_cred_def_count, + ), + ( + RecordCategory::CredDefPriv, + make_dummy_cred_def_priv_key(), + indy_cred_def_priv_count, + ), + ( + RecordCategory::CredKeyCorrectnessProof, + make_dummy_cred_def_correctness_proof(), + indy_cred_def_cr_proof_count, + ), + ( + RecordCategory::CredSchema, + make_dummy_schema(), + indy_schema_count, + ), + ( + RecordCategory::CredMapSchemaId, + make_dummy_schema_id(), + indy_schema_id_count, + ), + ( + RecordCategory::RevReg, + make_dummy_rev_reg(), + indy_rev_reg_count, + ), + ( + RecordCategory::RevRegDelta, + make_dummy_rev_reg_delta(), + indy_rev_reg_delta_count, + ), + ( + RecordCategory::RevRegInfo, + make_dummy_rev_reg_info(), + indy_rev_reg_info_count, + ), + ( + RecordCategory::RevRegDef, + make_dummy_rev_reg_def(), + infy_rev_reg_def_count, + ), + ( + RecordCategory::RevRegDefPriv, + make_dummy_rev_reg_def_priv(), + indy_rev_reg_def_priv_count, + ), + ]; + + let expected_count = indy_cred_count + + indy_cred_def_count + + indy_cred_def_priv_count + + indy_cred_def_cr_proof_count + + indy_schema_count + + indy_schema_id_count + + indy_rev_reg_count + + indy_rev_reg_delta_count + + indy_rev_reg_info_count + + infy_rev_reg_def_count + + indy_rev_reg_def_priv_count + + master_secret_count; + + TestData { + expected_count, + data_vec: wallet_items, + } + } + + async fn create_test_data(indy_wallet: &IndySdkWallet, data_vec: TestDataVec) { + for (category, value, count) in data_vec { + for _ in 0..count { + let record = Record::builder() + .category(category) + .name(Uuid::new_v4().to_string()) + .value(value.clone()) + .build(); + indy_wallet.add_record(record).await.unwrap() + } + } + } + + fn setup_indy_wallet_config() -> IndyWalletConfig { + IndyWalletConfig { + wallet_name: format!("wallet_{}", uuid::Uuid::new_v4()), + wallet_key: "8dvfYSt5d1taSd6yJdpjq4emkwsPDDLYxkNFysFD2cZY".into(), + wallet_key_derivation: "RAW".into(), + wallet_type: None, + storage_config: None, + storage_credentials: None, + rekey: None, + rekey_derivation_method: None, + } + } + + async fn setup_indy_wallet(wallet_config: &IndyWalletConfig) -> IndySdkWallet { + IndySdkWallet::create(wallet_config).await.unwrap() + } + + async fn setup_askar_wallet() -> AskarWallet { + let config = AskarWalletConfig::new( + "sqlite://:memory:", + KeyMethod::Unprotected, + "", + &Uuid::new_v4().to_string(), + ); + + AskarWallet::create(&config, true).await.unwrap() + } + + async fn teardown_indy_wallet(wallet: &IndySdkWallet, wallet_config: &IndyWalletConfig) { + let (config, creds) = wallet_config.to_config_and_creds().unwrap(); + + Locator::instance() + .wallet_controller + .close(wallet.get_wallet_handle()) + .await + .unwrap(); + + Locator::instance() + .wallet_controller + .delete(config, creds) + .await + .unwrap(); + } + + #[test_log::test(tokio::test)] + async fn wallet_compatibility_migration_to_askar() { + let askar_wallet = setup_askar_wallet().await; + let indy_config = setup_indy_wallet_config(); + let indy_wallet = setup_indy_wallet(&indy_config).await; + + let data = generate_test_data(); + create_test_data(&indy_wallet, data.data_vec).await; + + let res = migrate_wallet(&indy_wallet, &askar_wallet, MigrationKind::ToAskar) + .await + .unwrap(); + + teardown_indy_wallet(&indy_wallet, &indy_config).await; + + assert_eq!(data.expected_count, res.migrated); + } + + #[test_log::test(tokio::test)] + async fn wallet_compatibility_test_create_and_store_my_did() { + let indy_config = setup_indy_wallet_config(); + let indy_wallet = setup_indy_wallet(&indy_config).await; + let askar_wallet = setup_askar_wallet().await; + + let did_data = indy_wallet + .create_and_store_my_did(None, None) + .await + .unwrap(); + + assert_eq!(0, askar_wallet.key_count().await.unwrap()); + migrate_wallet(&indy_wallet, &askar_wallet, MigrationKind::ToAskar) + .await + .unwrap(); + + teardown_indy_wallet(&indy_wallet, &indy_config).await; + + let res = askar_wallet.key_for_did(did_data.did()).await.unwrap(); + + assert_eq!(did_data.verkey().base58(), res.base58()); + assert_eq!(1, askar_wallet.key_count().await.unwrap()) + } + + #[test_log::test(tokio::test)] + async fn wallet_compatibility_test_replace_key() { + let indy_config = setup_indy_wallet_config(); + let indy_wallet = setup_indy_wallet(&indy_config).await; + let askar_wallet = setup_askar_wallet().await; + + let did_data = indy_wallet + .create_and_store_my_did(None, None) + .await + .unwrap(); + + indy_wallet + .replace_did_key_start(did_data.did(), None) + .await + .unwrap(); + + migrate_wallet(&indy_wallet, &askar_wallet, MigrationKind::ToAskar) + .await + .unwrap(); + + teardown_indy_wallet(&indy_wallet, &indy_config).await; + + askar_wallet + .replace_did_key_apply(did_data.did()) + .await + .unwrap(); + + let res = askar_wallet.key_for_did(did_data.did()).await.unwrap(); + + assert_ne!(did_data.verkey().base58(), res.base58()); + } + + #[test_log::test(tokio::test)] + async fn wallet_compatibility_test_sign_and_verify() { + let indy_config = setup_indy_wallet_config(); + let indy_wallet = setup_indy_wallet(&indy_config).await; + let askar_wallet = setup_askar_wallet().await; + + let did_data = indy_wallet + .create_and_store_my_did(None, None) + .await + .unwrap(); + + let msg = "sign this message"; + let sig = indy_wallet + .sign(did_data.verkey(), msg.as_bytes()) + .await + .unwrap(); + + migrate_wallet(&indy_wallet, &askar_wallet, MigrationKind::ToAskar) + .await + .unwrap(); + + teardown_indy_wallet(&indy_wallet, &indy_config).await; + + assert!(askar_wallet + .verify(did_data.verkey(), msg.as_bytes(), &sig) + .await + .unwrap()); + } + + #[test_log::test(tokio::test)] + async fn wallet_compatibility_test_pack_and_unpack_authcrypt() { + let indy_config = setup_indy_wallet_config(); + let indy_wallet = setup_indy_wallet(&indy_config).await; + let askar_wallet = setup_askar_wallet().await; + + let sender_did_data = indy_wallet + .create_and_store_my_did(None, None) + .await + .unwrap(); + + let recipient_did_data = indy_wallet + .create_and_store_my_did(None, None) + .await + .unwrap(); + + let msg = "pack me"; + + let data = indy_wallet + .pack_message( + Some(sender_did_data.verkey().to_owned()), + vec![recipient_did_data.verkey().to_owned()], + msg.as_bytes(), + ) + .await + .unwrap(); + + migrate_wallet(&indy_wallet, &askar_wallet, MigrationKind::ToAskar) + .await + .unwrap(); + + teardown_indy_wallet(&indy_wallet, &indy_config).await; + + let res = askar_wallet.unpack_message(&data).await.unwrap(); + + assert_eq!(res.message, msg); + } + + #[test_log::test(tokio::test)] + async fn wallet_compatibility_test_pack_and_unpack_anoncrypt() { + let indy_config = setup_indy_wallet_config(); + let indy_wallet = setup_indy_wallet(&indy_config).await; + let askar_wallet = setup_askar_wallet().await; + + let recipient_did_data = indy_wallet + .create_and_store_my_did(None, None) + .await + .unwrap(); + + let msg = "pack me"; + + let data = indy_wallet + .pack_message( + None, + vec![recipient_did_data.verkey().to_owned()], + msg.as_bytes(), + ) + .await + .unwrap(); + + migrate_wallet(&indy_wallet, &askar_wallet, MigrationKind::ToAskar) + .await + .unwrap(); + + teardown_indy_wallet(&indy_wallet, &indy_config).await; + + let res = askar_wallet.unpack_message(&data).await.unwrap(); + + assert_eq!(res.message, msg); + } +} diff --git a/aries/misc/wallet_migrator/src/vdrtools2credx/conv.rs b/aries/misc/wallet_migrator/src/vdrtools2credx/conv.rs deleted file mode 100644 index 987c74d9b4..0000000000 --- a/aries/misc/wallet_migrator/src/vdrtools2credx/conv.rs +++ /dev/null @@ -1,107 +0,0 @@ -use aries_vcx_core::{ - anoncreds::credx_anoncreds::RevocationRegistryInfo, - wallet::base_wallet::record_category::RecordCategory, -}; -use vdrtools::{types::domain::wallet::IndyRecord, IndyError}; - -use crate::error::MigrationResult; - -// The deltas in libvdrtools are prefixed. For absolutely no reason. -const REV_REG_DELTA_ID_PREFIX: &str = "rev_reg_delta:"; - -pub fn convert_master_secret(mut record: IndyRecord) -> MigrationResult { - let master_secret: vdrtools::MasterSecret = serde_json::from_str(&record.value)?; - - record.value = master_secret - .value - .value() - .map_err(IndyError::from)? - .to_dec() - .map_err(IndyError::from)?; - - record.type_ = RecordCategory::LinkSecret.to_string(); - - Ok(record) -} - -pub fn convert_cred(mut record: IndyRecord) -> MigrationResult { - record.type_ = RecordCategory::Cred.to_string(); - let _: credx::types::Credential = serde_json::from_str(&record.value)?; - Ok(record) -} - -pub fn convert_cred_def(mut record: IndyRecord) -> MigrationResult { - record.type_ = RecordCategory::CredDef.to_string(); - let _: credx::types::CredentialDefinition = serde_json::from_str(&record.value)?; - Ok(record) -} - -pub fn convert_cred_def_priv_key(mut record: IndyRecord) -> MigrationResult { - record.type_ = RecordCategory::CredDefPriv.to_string(); - let _: credx::types::CredentialDefinitionPrivate = serde_json::from_str(&record.value)?; - Ok(record) -} - -pub fn convert_cred_def_correctness_proof(mut record: IndyRecord) -> MigrationResult { - record.type_ = RecordCategory::CredKeyCorrectnessProof.to_string(); - let old: vdrtools::CredentialDefinitionCorrectnessProof = serde_json::from_str(&record.value)?; - let old_value = serde_json::to_string(&old.value)?; - let new_value = serde_json::from_str(&old_value)?; - let new = credx::types::CredentialKeyCorrectnessProof { value: new_value }; - record.value = serde_json::to_string(&new)?; - Ok(record) -} - -pub fn convert_schema(mut record: IndyRecord) -> MigrationResult { - record.type_ = RecordCategory::CredSchema.to_string(); - let _: credx::types::Schema = serde_json::from_str(&record.value)?; - Ok(record) -} - -pub fn convert_schema_id(mut record: IndyRecord) -> MigrationResult { - record.type_ = RecordCategory::CredMapSchemaId.to_string(); - // The plain ID is stored as a String, - // so not that much to check. - let _ = credx::types::SchemaId(record.value.clone()); - Ok(record) -} - -pub fn convert_rev_reg(mut record: IndyRecord) -> MigrationResult { - record.type_ = RecordCategory::RevReg.to_string(); - let _: credx::types::RevocationRegistry = serde_json::from_str(&record.value)?; - Ok(record) -} - -pub fn convert_rev_reg_delta(mut record: IndyRecord) -> MigrationResult { - record.type_ = RecordCategory::RevRegDelta.to_string(); - - // Shave off the useless prefix, if found. - record.id = record - .id - .strip_prefix(REV_REG_DELTA_ID_PREFIX) - .map(ToOwned::to_owned) - .unwrap_or(record.id); - - // Them indy devs serializing a String to JSON... - record.value = serde_json::from_str(&record.value)?; - let _: credx::types::RevocationRegistryDelta = serde_json::from_str(&record.value)?; - Ok(record) -} - -pub fn convert_rev_reg_info(mut record: IndyRecord) -> MigrationResult { - record.type_ = RecordCategory::RevRegInfo.to_string(); - let _: RevocationRegistryInfo = serde_json::from_str(&record.value)?; - Ok(record) -} - -pub fn convert_rev_reg_def(mut record: IndyRecord) -> MigrationResult { - record.type_ = RecordCategory::RevRegDef.to_string(); - let _: credx::types::RevocationRegistryDefinition = serde_json::from_str(&record.value)?; - Ok(record) -} - -pub fn convert_rev_reg_def_priv(mut record: IndyRecord) -> MigrationResult { - record.type_ = RecordCategory::RevRegDefPriv.to_string(); - let _: credx::types::RevocationRegistryDefinitionPrivate = serde_json::from_str(&record.value)?; - Ok(record) -} diff --git a/aries/misc/wallet_migrator/src/vdrtools2credx/mod.rs b/aries/misc/wallet_migrator/src/vdrtools2credx/mod.rs deleted file mode 100644 index b427ec507d..0000000000 --- a/aries/misc/wallet_migrator/src/vdrtools2credx/mod.rs +++ /dev/null @@ -1,599 +0,0 @@ -pub mod conv; - -use aries_vcx_core::wallet::base_wallet::record::Record; -use log::trace; - -use crate::error::MigrationResult; - -pub(crate) const INDY_DID: &str = "Indy::Did"; -pub(crate) const INDY_KEY: &str = "Indy::Key"; -pub(crate) const INDY_MASTER_SECRET: &str = "Indy::MasterSecret"; -pub(crate) const INDY_CRED: &str = "Indy::Credential"; -pub(crate) const INDY_CRED_DEF: &str = "Indy::CredentialDefinition"; -pub(crate) const INDY_CRED_DEF_PRIV: &str = "Indy::CredentialDefinitionPrivateKey"; -pub(crate) const INDY_CRED_DEF_CR_PROOF: &str = "Indy::CredentialDefinitionCorrectnessProof"; -pub(crate) const INDY_SCHEMA: &str = "Indy::Schema"; -pub(crate) const INDY_SCHEMA_ID: &str = "Indy::SchemaId"; -pub(crate) const INDY_REV_REG: &str = "Indy::RevocationRegistry"; -pub(crate) const INDY_REV_REG_DELTA: &str = "cache"; // very intuitive, indy devs -pub(crate) const INDY_REV_REG_INFO: &str = "Indy::RevocationRegistryInfo"; -pub(crate) const INDY_REV_REG_DEF: &str = "Indy::RevocationRegistryDefinition"; -pub(crate) const INDY_REV_REG_DEF_PRIV: &str = "Indy::RevocationRegistryDefinitionPrivate"; - -/// Contains the logic for record mapping and migration. -pub fn migrate_any_record(record: Record) -> MigrationResult> { - trace!("Migrating wallet record {record:?}"); - - let record = match record.category().to_string().as_str() { - // Indy wallet records - to be left alone! - INDY_DID | INDY_KEY => Ok(Some(record)), - // Master secret - INDY_MASTER_SECRET => Ok(Some(Record::try_from_indy_record( - conv::convert_master_secret(record.into())?, - )?)), - // Credential - INDY_CRED => Ok(Some(Record::try_from_indy_record(conv::convert_cred( - record.into(), - )?)?)), - INDY_CRED_DEF => Ok(Some(Record::try_from_indy_record(conv::convert_cred_def( - record.into(), - )?)?)), - INDY_CRED_DEF_PRIV => Ok(Some(Record::try_from_indy_record( - conv::convert_cred_def_priv_key(record.into())?, - )?)), - INDY_CRED_DEF_CR_PROOF => Ok(Some(Record::try_from_indy_record( - conv::convert_cred_def_correctness_proof(record.into())?, - )?)), - // Schema - INDY_SCHEMA => Ok(Some(Record::try_from_indy_record(conv::convert_schema( - record.into(), - )?)?)), - INDY_SCHEMA_ID => Ok(Some(Record::try_from_indy_record( - conv::convert_schema_id(record.into())?, - )?)), - // Revocation registry - INDY_REV_REG => Ok(Some(Record::try_from_indy_record(conv::convert_rev_reg( - record.into(), - )?)?)), - INDY_REV_REG_DELTA => Ok(Some(Record::try_from_indy_record( - conv::convert_rev_reg_delta(record.into())?, - )?)), - INDY_REV_REG_INFO => Ok(Some(Record::try_from_indy_record( - conv::convert_rev_reg_info(record.into())?, - )?)), - INDY_REV_REG_DEF => Ok(Some(Record::try_from_indy_record( - conv::convert_rev_reg_def(record.into())?, - )?)), - INDY_REV_REG_DEF_PRIV => Ok(Some(Record::try_from_indy_record( - conv::convert_rev_reg_def_priv(record.into())?, - )?)), - _ => Ok(None), // Ignore unknown/uninteresting records - }; - - trace!("Converted wallet record to {record:?}"); - record -} - -#[cfg(test)] -mod tests { - use std::collections::{HashMap, HashSet}; - - use aries_vcx_core::{ - anoncreds::credx_anoncreds::RevocationRegistryInfo, - wallet::{base_wallet::record_category::RecordCategory, indy::IndySdkWallet}, - }; - use credx::{ - anoncreds_clsignatures::{bn::BigNumber, LinkSecret as ClLinkSecret}, - types::LinkSecret, - }; - use serde_json::json; - use vdrtools::{ - types::domain::wallet::{Config, Credentials, IndyRecord, KeyDerivationMethod}, - Locator, WalletHandle, - }; - - use super::*; - use crate::migrate_wallet; - - const WALLET_KEY: &str = "8dvfYSt5d1taSd6yJdpjq4emkwsPDDLYxkNFysFD2cZY"; - - #[tokio::test] - async fn test_sqlite_migration() { - let (credentials, config) = make_wallet_reqs("wallet_test_migration".to_owned()); - let (new_credentials, new_config) = make_wallet_reqs("new_better_wallet".to_owned()); - - test_migration(credentials, config, new_credentials, new_config).await; - } - - #[tokio::test] - async fn test_mysql_migration() { - let wallet_name = "wallet_test_migration"; - let new_wallet_name = "new_better_wallet"; - - let (mut credentials, mut config) = make_wallet_reqs(wallet_name.to_owned()); - let (mut new_credentials, mut new_config) = make_wallet_reqs(new_wallet_name.to_owned()); - - config.storage_type = Some("mysql".to_owned()); - new_config.storage_type = Some("mysql".to_owned()); - - let storage_config = json!({ - "read_host": "localhost", - "write_host": "localhost", - "port": 3306, - "db_name": wallet_name, - "default_connection_limit": 50 - }); - - let new_storage_config = json!({ - "read_host": "localhost", - "write_host": "localhost", - "port": 3306, - "db_name": new_wallet_name, - "default_connection_limit": 50 - }); - - let storage_credentials = json!({ - "user": "root", - "pass": "mysecretpassword" - }); - - config.storage_config = Some(storage_config); - credentials.storage_credentials = Some(storage_credentials.clone()); - - new_config.storage_config = Some(new_storage_config); - new_credentials.storage_credentials = Some(storage_credentials); - - test_migration(credentials, config, new_credentials, new_config).await; - } - - macro_rules! add_wallet_item { - ($wh:expr, $category:expr, $val:expr) => { - Locator::instance() - .non_secret_controller - .add_record( - $wh, - $category.to_owned(), - "test_id".to_owned(), - serde_json::to_string(&$val).unwrap(), - None, - ) - .await - .unwrap(); - }; - } - - macro_rules! get_wallet_item { - ($wh:expr, $category:expr, $res:ty) => {{ - let val = get_wallet_item_raw($wh, $category).await; - serde_json::from_str::<$res>(&val).unwrap() - }}; - } - - async fn test_migration( - credentials: Credentials, - config: Config, - new_credentials: Credentials, - new_config: Config, - ) { - // Removes old wallet if it already exists - Locator::instance() - .wallet_controller - .delete(config.clone(), credentials.clone()) - .await - .ok(); - - // Create and open the old wallet - // where we'll store old indy anoncreds types - Locator::instance() - .wallet_controller - .create(config.clone(), credentials.clone()) - .await - .unwrap(); - - let src_wallet_handle = Locator::instance() - .wallet_controller - .open(config.clone(), credentials.clone()) - .await - .unwrap(); - - // Construct and add legacy indy records - // These are dummy records with dummy values - // and are NOT expected to be functional - // - // ################# Ingestion start ################# - - // Master secret - add_wallet_item!( - src_wallet_handle, - INDY_MASTER_SECRET, - make_dummy_master_secret() - ); - - // Credential - add_wallet_item!(src_wallet_handle, INDY_CRED, make_dummy_cred()); - add_wallet_item!(src_wallet_handle, INDY_CRED_DEF, make_dummy_cred_def()); - add_wallet_item!( - src_wallet_handle, - INDY_CRED_DEF_PRIV, - make_dummy_cred_def_priv_key() - ); - add_wallet_item!( - src_wallet_handle, - INDY_CRED_DEF_CR_PROOF, - make_dummy_cred_def_correctness_proof() - ); - - // Schema - add_wallet_item!(src_wallet_handle, INDY_SCHEMA, make_dummy_schema()); - add_wallet_item!(src_wallet_handle, INDY_SCHEMA_ID, make_dummy_schema_id()); - - // Revocation registry - add_wallet_item!(src_wallet_handle, INDY_REV_REG, make_dummy_rev_reg()); - add_wallet_item!( - src_wallet_handle, - INDY_REV_REG_DELTA, - make_dummy_rev_reg_delta() - ); - add_wallet_item!( - src_wallet_handle, - INDY_REV_REG_INFO, - make_dummy_rev_reg_info() - ); - add_wallet_item!( - src_wallet_handle, - INDY_REV_REG_DEF, - make_dummy_rev_reg_def() - ); - add_wallet_item!( - src_wallet_handle, - INDY_REV_REG_DEF_PRIV, - make_dummy_rev_reg_def_priv() - ); - - // ################# Ingestion end ################# - - // Remove new wallet if it already exists - Locator::instance() - .wallet_controller - .delete(new_config.clone(), new_credentials.clone()) - .await - .ok(); - - Locator::instance() - .wallet_controller - .create(new_config.clone(), new_credentials.clone()) - .await - .unwrap(); - - let dest_wallet_handle = Locator::instance() - .wallet_controller - .open(new_config.clone(), new_credentials.clone()) - .await - .unwrap(); - - let src_wallet = IndySdkWallet::new(src_wallet_handle); - let dest_wallet = IndySdkWallet::new(dest_wallet_handle); - - // Migrate the records - migrate_wallet(&src_wallet, &dest_wallet, migrate_any_record) - .await - .unwrap(); - - // Old wallet cleanup - Locator::instance() - .wallet_controller - .close(src_wallet_handle) - .await - .unwrap(); - - Locator::instance() - .wallet_controller - .delete(config, credentials) - .await - .unwrap(); - - // ################# Retrieval start ################# - - // Master secret - get_master_secret(dest_wallet_handle).await; - - // Credential - get_wallet_item!( - dest_wallet_handle, - &RecordCategory::Cred.to_string(), - credx::types::Credential - ); - get_wallet_item!( - dest_wallet_handle, - &RecordCategory::CredDef.to_string(), - credx::types::CredentialDefinition - ); - get_wallet_item!( - dest_wallet_handle, - &RecordCategory::CredDefPriv.to_string(), - credx::types::CredentialDefinitionPrivate - ); - get_wallet_item!( - dest_wallet_handle, - &RecordCategory::CredKeyCorrectnessProof.to_string(), - credx::types::CredentialKeyCorrectnessProof - ); - - // Schema - get_wallet_item!( - dest_wallet_handle, - &RecordCategory::CredSchema.to_string(), - credx::types::Schema - ); - get_wallet_item!( - dest_wallet_handle, - &RecordCategory::CredMapSchemaId.to_string(), - credx::types::SchemaId - ); - - // Revocation registry - get_wallet_item!( - dest_wallet_handle, - &RecordCategory::RevReg.to_string(), - credx::types::RevocationRegistry - ); - get_wallet_item!( - dest_wallet_handle, - &RecordCategory::RevRegDelta.to_string(), - credx::types::RevocationRegistryDelta - ); - get_wallet_item!( - dest_wallet_handle, - &RecordCategory::RevRegInfo.to_string(), - RevocationRegistryInfo - ); - get_wallet_item!( - dest_wallet_handle, - &RecordCategory::RevRegDef.to_string(), - credx::types::RevocationRegistryDefinition - ); - get_wallet_item!( - dest_wallet_handle, - &RecordCategory::RevRegDefPriv.to_string(), - credx::types::RevocationRegistryDefinitionPrivate - ); - - // ################# Retrieval end ################# - - // New wallet cleanup - Locator::instance() - .wallet_controller - .close(dest_wallet_handle) - .await - .unwrap(); - - Locator::instance() - .wallet_controller - .delete(new_config, new_credentials) - .await - .unwrap(); - } - - fn make_wallet_reqs(wallet_name: String) -> (Credentials, Config) { - let credentials = Credentials { - key: WALLET_KEY.to_owned(), - key_derivation_method: KeyDerivationMethod::RAW, - rekey: None, - rekey_derivation_method: KeyDerivationMethod::ARGON2I_MOD, - storage_credentials: None, - }; - - let config = Config { - id: wallet_name, - storage_type: None, - storage_config: None, - cache: None, - }; - - (credentials, config) - } - - async fn get_wallet_item_raw(wallet_handle: WalletHandle, category: &str) -> String { - let options = r#"{"retrieveType": true, "retrieveValue": true, "retrieveTags": true}"#; - - let record_str = Locator::instance() - .non_secret_controller - .get_record( - wallet_handle, - category.to_owned(), - "test_id".to_owned(), - options.to_owned(), - ) - .await - .unwrap(); - - let record: IndyRecord = serde_json::from_str(&record_str).unwrap(); - record.value - } - - // MasterSecret needs special processing - async fn get_master_secret(wallet_handle: WalletHandle) { - let ms_decimal = - get_wallet_item_raw(wallet_handle, &RecordCategory::LinkSecret.to_string()).await; - let ms_bn = BigNumber::from_dec(&ms_decimal).unwrap(); - - let ursa_ms: ClLinkSecret = serde_json::from_value(json!({ "ms": ms_bn })).unwrap(); - let _ = LinkSecret { value: ursa_ms }; - } - - fn make_dummy_master_secret() -> vdrtools::MasterSecret { - let ms_str = json!({ - "value": { - "ms": "1234567890" - } - }) - .to_string(); - - serde_json::from_str(&ms_str).unwrap() - } - - fn make_dummy_cred() -> vdrtools::Credential { - let cred_sig_str = json!({ - "p_credential": { - "m_2": "1234567890", - "a": "1234567890", - "e": "1234567890", - "v": "1234567890" - }, - "r_credential": null - }) - .to_string(); - - let sig_cor_proof_str = json!({ - "se": "1234567890", - "c": "1234567890" - }) - .to_string(); - - vdrtools::Credential { - schema_id: vdrtools::SchemaId("test_schema_id".to_owned()), - cred_def_id: vdrtools::CredentialDefinitionId("test_cred_def_id".to_owned()), - rev_reg_id: Some(vdrtools::RevocationRegistryId("test_rev_reg_id".to_owned())), - values: vdrtools::CredentialValues(HashMap::new()), - signature: serde_json::from_str(&cred_sig_str).unwrap(), - signature_correctness_proof: serde_json::from_str(&sig_cor_proof_str).unwrap(), - rev_reg: None, - witness: None, - } - } - - fn make_dummy_cred_def() -> vdrtools::CredentialDefinition { - let primary = json!({ - "n": "1234567890", - "s": "1234567890", - "r": {}, - "rctxt": "1234567890", - "z": "1234567890", - }) - .to_string(); - - vdrtools::CredentialDefinition::CredentialDefinitionV1(vdrtools::CredentialDefinitionV1 { - id: vdrtools::CredentialDefinitionId("test_cred_def_id".to_owned()), - schema_id: vdrtools::SchemaId("test_schema_id".to_owned()), - signature_type: vdrtools::SignatureType::CL, - tag: "{}".to_owned(), - value: vdrtools::CredentialDefinitionData { - primary: serde_json::from_str(&primary).unwrap(), - revocation: None, - }, - }) - } - - fn make_dummy_cred_def_priv_key() -> vdrtools::CredentialDefinitionPrivateKey { - let priv_key = json!({ - "p_key": { - "p": "1234567890", - "q": "1234567890" - } - }) - .to_string(); - - vdrtools::CredentialDefinitionPrivateKey { - value: serde_json::from_str(&priv_key).unwrap(), - } - } - - fn make_dummy_cred_def_correctness_proof() -> vdrtools::CredentialDefinitionCorrectnessProof { - let cor_proof = json!({ - "c": "1234567890", - "xz_cap": "1234567890", - "xr_cap": [] - }) - .to_string(); - - vdrtools::CredentialDefinitionCorrectnessProof { - value: serde_json::from_str(&cor_proof).unwrap(), - } - } - - fn make_dummy_schema() -> vdrtools::Schema { - vdrtools::Schema::SchemaV1(vdrtools::SchemaV1 { - id: vdrtools::SchemaId("test_schema_id".to_owned()), - name: "test_schema_name".to_owned(), - version: "test_schema_version".to_owned(), - attr_names: vdrtools::AttributeNames(HashSet::new()), - seq_no: None, - }) - } - - fn make_dummy_schema_id() -> vdrtools::SchemaId { - vdrtools::SchemaId("test_schema_id".to_owned()) - } - - fn make_dummy_rev_reg() -> vdrtools::RevocationRegistry { - let rev_reg = json!({ - "accum": "21 11ED98357F9B9B3077E633D35A72CECEF107F85DA7BBFBF2873E2EE7E0F27D326 21 1371CDA6174D6F01A39157428768D328B4B80088EB14AA0AAB7F046B645E1A235 6 65BBFAC37012790BB8B283F164BE3C0585AB60CD7B72123E4DC43DDA7A6A4E6D 4 3BB64FAF922865095CD5AA4349C0437D04EA30FB7592D932531732F2DCB83DB8 6 77039B80A78AB4A2476373C6F8ECC5E2D94B8F37F924549AFA247E2D6EE86DEE 4 24E94FB6B5233B22BDF47745AA821A1797BC6504BC11D5B825B4F8137F1E307F" - }).to_string(); - - vdrtools::RevocationRegistry::RevocationRegistryV1(vdrtools::RevocationRegistryV1 { - value: serde_json::from_str(&rev_reg).unwrap(), - }) - } - - fn make_dummy_rev_reg_delta() -> String { - let rev_reg = json!({ - "prevAccum": "21 11ED98357F9B9B3077E633D35A72CECEF107F85DA7BBFBF2873E2EE7E0F27D326 21 1371CDA6174D6F01A39157428768D328B4B80088EB14AA0AAB7F046B645E1A235 6 65BBFAC37012790BB8B283F164BE3C0585AB60CD7B72123E4DC43DDA7A6A4E6D 4 3BB64FAF922865095CD5AA4349C0437D04EA30FB7592D932531732F2DCB83DB8 6 77039B80A78AB4A2476373C6F8ECC5E2D94B8F37F924549AFA247E2D6EE86DEE 4 24E94FB6B5233B22BDF47745AA821A1797BC6504BC11D5B825B4F8137F1E307F", - "accum": "21 11ED98357F9B9B3077E633D35A72CECEF107F85DA7BBFBF2873E2EE7E0F27D326 21 1371CDA6174D6F01A39157428768D328B4B80088EB14AA0AAB7F046B645E1A235 6 65BBFAC37012790BB8B283F164BE3C0585AB60CD7B72123E4DC43DDA7A6A4E6D 4 3BB64FAF922865095CD5AA4349C0437D04EA30FB7592D932531732F2DCB83DB8 6 77039B80A78AB4A2476373C6F8ECC5E2D94B8F37F924549AFA247E2D6EE86DEE 4 24E94FB6B5233B22BDF47745AA821A1797BC6504BC11D5B825B4F8137F1E307F", - "issued": [], - "revoked": [] - }).to_string(); - - let rev_reg_delta = vdrtools::RevocationRegistryDelta::RevocationRegistryDeltaV1( - vdrtools::RevocationRegistryDeltaV1 { - value: serde_json::from_str(&rev_reg).unwrap(), - }, - ); - - // Vdrtools serializes this to String. - // Sad, I know... - json!(rev_reg_delta).to_string() - } - - fn make_dummy_rev_reg_info() -> vdrtools::RevocationRegistryInfo { - vdrtools::RevocationRegistryInfo { - id: vdrtools::RevocationRegistryId("test_rev_reg_id".to_owned()), - curr_id: 1, - used_ids: HashSet::new(), - } - } - - fn make_dummy_rev_reg_def() -> vdrtools::RevocationRegistryDefinition { - let accum_key = json!({ - "z": "1 042CDA7AA76FFD05D0EA1C97F0F238A579AAE4348442298B7F8513277A21D671 1 04C49DDECC3731B11BC98A1495C39DF7F94A297EA6D691DADAF1493300D2977E 1 0D78B673DE9F1CE37FA98E0765B69D963BFF9973317722981943797EFEF1F628 1 1F4DFD2C1ED2BD80D9D92600AB7A1B2911180B4B44C6BC42962084AC4C042385 1 07724871AD4FFC1C30BCAEFE289FAF6F2F322203C34D8D2D3C36DFD816AF9430 1 050F4014E2AFD680A67C197B39D35CA4D03332D6C6922A4D991EC1402B7FF4E6 1 07C0DCAF303CF4B0741447A1A808C8C2BAE6CD30397AAF834428848FEE70FC3D 1 1C028C08BD426B053942A4409F71A5215B6B0B58FF651C72303F1B4C5DDB84C4 1 22DE20332A0E1B0C58F76CBADBF73D0B6875A5F3479AC0E3C4D27A605656BF6E 1 1F461563E404002F9AFE37D09FA98F34B4666D1A4424C89B3C8CE7E85DE23B8A 1 096DA55063F6ABA1B578471DEBDEACA5DE485994F99099BBBB6E326DDF8C3DD2 1 12FFCEFF31CE5781FF6BB9AB279BF8A100E97D43B0F6C31E6FCD6373227E34FD" - }).to_string(); - - vdrtools::RevocationRegistryDefinition::RevocationRegistryDefinitionV1( - vdrtools::RevocationRegistryDefinitionV1 { - id: vdrtools::RevocationRegistryId("test_rev_reg_id".to_owned()), - revoc_def_type: vdrtools::RegistryType::CL_ACCUM, - tag: "{}".to_owned(), - cred_def_id: vdrtools::CredentialDefinitionId("test_cred_def_id".to_owned()), - value: vdrtools::RevocationRegistryDefinitionValue { - issuance_type: vdrtools::IssuanceType::ISSUANCE_BY_DEFAULT, - max_cred_num: 10, - public_keys: vdrtools::RevocationRegistryDefinitionValuePublicKeys { - accum_key: serde_json::from_str(&accum_key).unwrap(), - }, - tails_hash: "abc".to_owned(), - tails_location: "/dev/null".to_owned(), - }, - }, - ) - } - - fn make_dummy_rev_reg_def_priv() -> vdrtools::RevocationRegistryDefinitionPrivate { - let rev_key_priv = json!({ - "gamma": "12345" - }) - .to_string(); - - vdrtools::RevocationRegistryDefinitionPrivate { - value: serde_json::from_str(&rev_key_priv).unwrap(), - } - } -} diff --git a/aries/wrappers/uniffi-aries-vcx/core/Cargo.toml b/aries/wrappers/uniffi-aries-vcx/core/Cargo.toml index 78b2c2991a..d897d898f6 100644 --- a/aries/wrappers/uniffi-aries-vcx/core/Cargo.toml +++ b/aries/wrappers/uniffi-aries-vcx/core/Cargo.toml @@ -17,8 +17,8 @@ path = "uniffi-bindgen.rs" [features] default = ["vdrtools_wallet"] -vdrtools_wallet = ["aries_vcx/vdrtools_wallet"] askar_wallet = ["aries_vcx/askar_wallet"] +vdrtools_wallet = ["aries_vcx/vdrtools_wallet"] [dependencies] uniffi = { version = "0.23.0", features = ["cli"] } diff --git a/aries/wrappers/uniffi-aries-vcx/core/build.rs b/aries/wrappers/uniffi-aries-vcx/core/build.rs index 409190cb72..aec22a6174 100644 --- a/aries/wrappers/uniffi-aries-vcx/core/build.rs +++ b/aries/wrappers/uniffi-aries-vcx/core/build.rs @@ -1,6 +1,9 @@ fn main() { + #[cfg(all(feature = "vdrtools_wallet", feature = "askar_wallet"))] + compile_error!("features `vdrtools_wallet` and `askar_wallet` are mutually exclusive"); + #[cfg(feature = "vdrtools_wallet")] - uniffi::generate_scaffolding("./src/vcx.udl").unwrap(); + uniffi::generate_scaffolding("./src/vcx_indy.udl").unwrap(); #[cfg(feature = "askar_wallet")] uniffi::generate_scaffolding("./src/vcx_askar.udl").unwrap(); diff --git a/aries/wrappers/uniffi-aries-vcx/core/src/lib.rs b/aries/wrappers/uniffi-aries-vcx/core/src/lib.rs index 1c4e0f454b..0ef407db70 100644 --- a/aries/wrappers/uniffi-aries-vcx/core/src/lib.rs +++ b/aries/wrappers/uniffi-aries-vcx/core/src/lib.rs @@ -1,5 +1,5 @@ #[cfg(feature = "vdrtools_wallet")] -uniffi::include_scaffolding!("vcx"); +uniffi::include_scaffolding!("vcx_indy"); #[cfg(feature = "askar_wallet")] uniffi::include_scaffolding!("vcx_askar"); diff --git a/aries/wrappers/uniffi-aries-vcx/core/src/vcx.udl b/aries/wrappers/uniffi-aries-vcx/core/src/vcx_indy.udl similarity index 100% rename from aries/wrappers/uniffi-aries-vcx/core/src/vcx.udl rename to aries/wrappers/uniffi-aries-vcx/core/src/vcx_indy.udl diff --git a/justfile b/justfile index 589bf33007..ae938d3bbe 100644 --- a/justfile +++ b/justfile @@ -43,6 +43,9 @@ test-integration-aries-vcx-core features: test-compatibility-aries-vcx-core: cargo test --manifest-path="aries/aries_vcx_core/Cargo.toml" -F vdrtools_wallet,askar_wallet wallet_compatibility_ +test-wallet-migrator: + cargo test --manifest-path="aries/misc/wallet_migrator/Cargo.toml" -F vdrtools_wallet,askar_wallet + test-integration-aries-vcx features test_name="": cargo test --manifest-path="aries/aries_vcx/Cargo.toml" -F {{features}} -- --ignored {{test_name}} @@ -50,13 +53,10 @@ test-integration-aries-vcx-anoncreds-rs test_name="": cargo test --manifest-path="aries/aries_vcx/Cargo.toml" -F anoncreds --test test_revocations --test test_proof_presentation --test test_anoncreds --test test_verifier -- --ignored {{test_name}} test-integration-aries-vcx-mysql test_name="": - cargo test --manifest-path="aries/aries_vcx/Cargo.toml" test_mysql -- --include-ignored {{test_name}} + cargo test --manifest-path="aries/aries_vcx/Cargo.toml" -F vdrtools_wallet test_mysql -- --include-ignored {{test_name}} test-integration-aries-vcx-vdrproxy test_name="": cargo test --manifest-path="aries/aries_vcx/Cargo.toml" -F vdr_proxy_ledger,credx -- --ignored {{test_name}} -test-integration-libvcx wallet test_name="": - RUST_TEST_THREADS=1 cargo test --manifest-path="aries/misc/legacy/libvcx_core/Cargo.toml" -F {{wallet}} -- --include-ignored {{test_name}} - test-integration-did-crate test_name="": cargo test --examples -p did_doc -p did_parser -p did_resolver -p did_resolver_registry -p did_resolver_sov -p did_resolver_web -p did_key -p did_peer --test "*"