From e07071721f85c1bacaa13fb8a687e8fd2d0f6d7f Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Thu, 15 Aug 2024 13:48:01 +1000 Subject: [PATCH 01/50] try permissions in CI Signed-off-by: George Mulhearn --- .github/workflows/main.yml | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a9baffc82f..f44733e366 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -146,9 +146,12 @@ jobs: # todo: move to indy-vdr repo build-docker-vdrproxy: + runs-on: ubuntu-20.04 + permissions: + content: read + packages: write needs: [ workflow-setup ] if: ${{ needs.workflow-setup.outputs.SKIP_CI != 'true' }} - runs-on: ubuntu-20.04 env: DOCKER_IMG_CACHED: ${{ needs.workflow-setup.outputs.DOCKER_IMG_CACHED_VDRPROXY }} BRANCH_NAME: ${{ needs.workflow-setup.outputs.BRANCH_NAME }} @@ -176,9 +179,12 @@ jobs: # builds and publishes main branch AATH backchannels build-docker-aath-backchannel: - needs: [ workflow-setup ] - if: ${{ needs.workflow-setup.outputs.IS_MAIN_BRANCH == 'true' }} runs-on: ubuntu-20.04 + permissions: + content: read + packages: write + needs: [ workflow-setup ] + # if: ${{ needs.workflow-setup.outputs.IS_MAIN_BRANCH == 'true' }} env: DOCKER_IMG_CACHED: ${{ needs.workflow-setup.outputs.DOCKER_IMG_CACHED_AATH }} BRANCH_NAME: ${{ needs.workflow-setup.outputs.BRANCH_NAME }} @@ -209,6 +215,9 @@ jobs: publish-docker-vdrproxy: runs-on: ubuntu-20.04 + permissions: + content: read + packages: write needs: [ workflow-setup, build-docker-vdrproxy ] if: ${{ needs.workflow-setup.outputs.SKIP_CI != 'true' }} env: @@ -237,6 +246,9 @@ jobs: # additional publish of the AATH backchannel image with tagged versions for tags publish-docker-aath-backchannel: runs-on: ubuntu-20.04 + permissions: + content: read + packages: write needs: [ workflow-setup, build-docker-aath-backchannel ] if: ${{ needs.workflow-setup.outputs.RELEASE == 'true' || needs.workflow-setup.outputs.PRERELEASE == 'true' }} env: From 1693dd59fb7f7431e114a368b9ca1efee843349d Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Mon, 25 Nov 2024 09:54:12 +1000 Subject: [PATCH 02/50] new crate Signed-off-by: George Mulhearn --- Cargo.lock | 12 +++++++ Cargo.toml | 1 + did_core/did_methods/did_cheqd/Cargo.toml | 15 +++++++++ .../did_methods/did_cheqd/src/error/mod.rs | 10 ++++++ did_core/did_methods/did_cheqd/src/lib.rs | 2 ++ .../did_cheqd/src/resolution/mod.rs | 1 + .../did_cheqd/src/resolution/resolver.rs | 31 +++++++++++++++++++ 7 files changed, 72 insertions(+) create mode 100644 did_core/did_methods/did_cheqd/Cargo.toml create mode 100644 did_core/did_methods/did_cheqd/src/error/mod.rs create mode 100644 did_core/did_methods/did_cheqd/src/lib.rs create mode 100644 did_core/did_methods/did_cheqd/src/resolution/mod.rs create mode 100644 did_core/did_methods/did_cheqd/src/resolution/resolver.rs diff --git a/Cargo.lock b/Cargo.lock index 6e6cd06648..d1c9605ee1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1894,6 +1894,18 @@ dependencies = [ "syn 2.0.72", ] +[[package]] +name = "did_cheqd" +version = "0.1.0" +dependencies = [ + "aries_vcx_ledger", + "async-trait", + "did_resolver", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "did_doc" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index fbcdea788c..b996c1766d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,7 @@ members = [ "did_core/public_key", "misc/simple_message_relay", "misc/display_as_json", + "did_core/did_methods/did_cheqd", ] [workspace.package] diff --git a/did_core/did_methods/did_cheqd/Cargo.toml b/did_core/did_methods/did_cheqd/Cargo.toml new file mode 100644 index 0000000000..9e40eb0a52 --- /dev/null +++ b/did_core/did_methods/did_cheqd/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "did_cheqd" +authors.workspace = true +description.workspace = true +license.workspace = true +version = "0.1.0" +edition = "2021" + +[dependencies] +did_resolver = { path = "../../did_resolver" } +aries_vcx_ledger = { path = "../../../aries/aries_vcx_ledger" } +async-trait = "0.1.68" +serde_json = "1.0.96" +serde = { version = "1.0.160", features = ["derive"] } +thiserror = "1.0.40" diff --git a/did_core/did_methods/did_cheqd/src/error/mod.rs b/did_core/did_methods/did_cheqd/src/error/mod.rs new file mode 100644 index 0000000000..ce9f18bc80 --- /dev/null +++ b/did_core/did_methods/did_cheqd/src/error/mod.rs @@ -0,0 +1,10 @@ +use thiserror::Error; + +pub type DidCheqdResult = Result; + +#[derive(Error, Debug)] +#[non_exhaustive] +pub enum DidCheqdError { + #[error(transparent)] + Other(#[from] Box), +} diff --git a/did_core/did_methods/did_cheqd/src/lib.rs b/did_core/did_methods/did_cheqd/src/lib.rs new file mode 100644 index 0000000000..bd1d464699 --- /dev/null +++ b/did_core/did_methods/did_cheqd/src/lib.rs @@ -0,0 +1,2 @@ +pub mod error; +pub mod resolution; diff --git a/did_core/did_methods/did_cheqd/src/resolution/mod.rs b/did_core/did_methods/did_cheqd/src/resolution/mod.rs new file mode 100644 index 0000000000..e755804162 --- /dev/null +++ b/did_core/did_methods/did_cheqd/src/resolution/mod.rs @@ -0,0 +1 @@ +pub mod resolver; diff --git a/did_core/did_methods/did_cheqd/src/resolution/resolver.rs b/did_core/did_methods/did_cheqd/src/resolution/resolver.rs new file mode 100644 index 0000000000..0b59eeca24 --- /dev/null +++ b/did_core/did_methods/did_cheqd/src/resolution/resolver.rs @@ -0,0 +1,31 @@ +use async_trait::async_trait; +use did_resolver::{ + did_doc::schema::did_doc::DidDocument, + did_parser_nom::Did, + error::GenericError, + traits::resolvable::{resolution_output::DidResolutionOutput, DidResolvable}, +}; + +use crate::error::DidCheqdResult; + +pub struct DidCheqdResolver; + +#[async_trait] +impl DidResolvable for DidCheqdResolver { + type DidResolutionOptions = (); + + async fn resolve( + &self, + did: &Did, + _: &Self::DidResolutionOptions, + ) -> Result { + let doc = self.resolve_did(did).await?; + Ok(DidResolutionOutput::builder(doc).build()) + } +} + +impl DidCheqdResolver { + pub async fn resolve_did(&self, _did: &Did) -> DidCheqdResult { + todo!() + } +} From d40d9c7107a0c88728f1a6c64792b3efcef85be2 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Mon, 25 Nov 2024 14:38:27 +1000 Subject: [PATCH 03/50] resolution working Signed-off-by: George Mulhearn --- Cargo.lock | 219 ++- did_core/did_doc/src/schema/utils/mod.rs | 9 + .../verification_method_type.rs | 8 + did_core/did_methods/did_cheqd/Cargo.toml | 19 +- did_core/did_methods/did_cheqd/build.rs | 12 + .../did_cheqd/proto/cheqd/did/v2/diddoc.proto | 138 ++ .../did_cheqd/proto/cheqd/did/v2/query.proto | 87 ++ .../proto/cheqd/resource/v2/query.proto | 79 + .../proto/cheqd/resource/v2/resource.proto | 89 ++ .../base/query/v1beta1/pagination.proto | 48 + .../did_cheqd/proto/gogoproto/gogo.proto | 144 ++ .../proto/google/api/annotations.proto | 31 + .../did_cheqd/proto/google/api/http.proto | 371 +++++ .../proto/google/protobuf/descriptor.proto | 1307 +++++++++++++++++ .../proto/google/protobuf/timestamp.proto | 144 ++ .../did_methods/did_cheqd/proto/greeter.proto | 15 + .../did_methods/did_cheqd/src/error/mod.rs | 5 + .../did_cheqd/src/error/parsing.rs | 40 + did_core/did_methods/did_cheqd/src/lib.rs | 1 + did_core/did_methods/did_cheqd/src/proto.rs | 22 + .../did_cheqd/src/resolution/mod.rs | 1 + .../did_cheqd/src/resolution/resolver.rs | 122 +- .../did_cheqd/src/resolution/transformer.rs | 124 ++ .../did_methods/did_cheqd/tests/resolution.rs | 13 + 24 files changed, 3026 insertions(+), 22 deletions(-) create mode 100644 did_core/did_methods/did_cheqd/build.rs create mode 100644 did_core/did_methods/did_cheqd/proto/cheqd/did/v2/diddoc.proto create mode 100644 did_core/did_methods/did_cheqd/proto/cheqd/did/v2/query.proto create mode 100644 did_core/did_methods/did_cheqd/proto/cheqd/resource/v2/query.proto create mode 100644 did_core/did_methods/did_cheqd/proto/cheqd/resource/v2/resource.proto create mode 100644 did_core/did_methods/did_cheqd/proto/cosmos/base/query/v1beta1/pagination.proto create mode 100644 did_core/did_methods/did_cheqd/proto/gogoproto/gogo.proto create mode 100644 did_core/did_methods/did_cheqd/proto/google/api/annotations.proto create mode 100644 did_core/did_methods/did_cheqd/proto/google/api/http.proto create mode 100644 did_core/did_methods/did_cheqd/proto/google/protobuf/descriptor.proto create mode 100644 did_core/did_methods/did_cheqd/proto/google/protobuf/timestamp.proto create mode 100644 did_core/did_methods/did_cheqd/proto/greeter.proto create mode 100644 did_core/did_methods/did_cheqd/src/error/parsing.rs create mode 100644 did_core/did_methods/did_cheqd/src/proto.rs create mode 100644 did_core/did_methods/did_cheqd/src/resolution/transformer.rs create mode 100644 did_core/did_methods/did_cheqd/tests/resolution.rs diff --git a/Cargo.lock b/Cargo.lock index d1c9605ee1..2f6772686b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1234,9 +1234,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "bytestring" @@ -1516,11 +1516,21 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "core2" @@ -1898,12 +1908,16 @@ dependencies = [ name = "did_cheqd" version = "0.1.0" dependencies = [ - "aries_vcx_ledger", "async-trait", "did_resolver", + "prost", + "prost-types", "serde", "serde_json", "thiserror", + "tokio", + "tonic", + "tonic-build", ] [[package]] @@ -2424,6 +2438,12 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + [[package]] name = "flate2" version = "1.0.30" @@ -3004,6 +3024,19 @@ dependencies = [ "tower-service", ] +[[package]] +name = "hyper-timeout" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" +dependencies = [ + "hyper 1.4.1", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + [[package]] name = "hyper-tls" version = "0.5.0" @@ -3035,9 +3068,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.6" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ "bytes", "futures-channel", @@ -3048,7 +3081,6 @@ dependencies = [ "pin-project-lite", "socket2 0.5.7", "tokio", - "tower", "tower-service", "tracing", ] @@ -3778,6 +3810,12 @@ dependencies = [ "data-encoding-macro", ] +[[package]] +name = "multimap" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" + [[package]] name = "native-tls" version = "0.2.12" @@ -3790,7 +3828,7 @@ dependencies = [ "openssl-probe", "openssl-sys", "schannel", - "security-framework", + "security-framework 2.11.1", "security-framework-sys", "tempfile", ] @@ -4122,6 +4160,16 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset", + "indexmap 2.2.6", +] + [[package]] name = "phf" version = "0.11.2" @@ -4312,6 +4360,16 @@ dependencies = [ "yansi", ] +[[package]] +name = "prettyplease" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" +dependencies = [ + "proc-macro2", + "syn 2.0.72", +] + [[package]] name = "primeorder" version = "0.13.6" @@ -4354,6 +4412,59 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "prost" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-build" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c1318b19085f08681016926435853bbf7858f9c082d0999b80550ff5d9abe15" +dependencies = [ + "bytes", + "heck 0.5.0", + "itertools", + "log", + "multimap", + "once_cell", + "petgraph", + "prettyplease", + "prost", + "prost-types", + "regex", + "syn 2.0.72", + "tempfile", +] + +[[package]] +name = "prost-derive" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 2.0.72", +] + +[[package]] +name = "prost-types" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4759aa0d3a6232fb8dbdb97b61de2c20047c68aca932c7ed76da9d788508d670" +dependencies = [ + "prost", +] + [[package]] name = "public_key" version = "0.1.0" @@ -4739,13 +4850,27 @@ version = "0.23.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4828ea528154ae444e5a642dbb7d5623354030dc9822b83fd9bb79683c7399d0" dependencies = [ + "log", "once_cell", + "ring", "rustls-pki-types", "rustls-webpki 0.102.6", "subtle", "zeroize", ] +[[package]] +name = "rustls-native-certs" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework 3.0.1", +] + [[package]] name = "rustls-pemfile" version = "1.0.4" @@ -4767,9 +4892,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.7.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" [[package]] name = "rustls-webpki" @@ -4878,7 +5003,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ "bitflags 2.6.0", - "core-foundation", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1415a607e92bec364ea2cf9264646dcce0f91e6d65281bd6f2819cca3bf39c8" +dependencies = [ + "bitflags 2.6.0", + "core-foundation 0.10.0", "core-foundation-sys", "libc", "security-framework-sys", @@ -4886,9 +5024,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.1" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2" dependencies = [ "core-foundation-sys", "libc", @@ -5488,7 +5626,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.4", "system-configuration-sys", ] @@ -5734,9 +5872,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" dependencies = [ "futures-core", "pin-project-lite", @@ -5784,6 +5922,49 @@ dependencies = [ "serde", ] +[[package]] +name = "tonic" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" +dependencies = [ + "async-trait", + "base64 0.22.1", + "bytes", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.4.1", + "hyper-timeout", + "hyper-util", + "percent-encoding", + "pin-project", + "prost", + "rustls-native-certs", + "rustls-pemfile 2.1.2", + "tokio", + "tokio-rustls", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tonic-build" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9557ce109ea773b399c9b9e5dca39294110b74f1f342cb347a80d1fce8c26a11" +dependencies = [ + "prettyplease", + "proc-macro2", + "prost-build", + "prost-types", + "quote", + "syn 2.0.72", +] + [[package]] name = "tower" version = "0.4.13" @@ -5792,9 +5973,13 @@ checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ "futures-core", "futures-util", + "indexmap 1.9.3", "pin-project", "pin-project-lite", + "rand 0.8.5", + "slab", "tokio", + "tokio-util", "tower-layer", "tower-service", "tracing", diff --git a/did_core/did_doc/src/schema/utils/mod.rs b/did_core/did_doc/src/schema/utils/mod.rs index 6149b43584..8df0309e83 100644 --- a/did_core/did_doc/src/schema/utils/mod.rs +++ b/did_core/did_doc/src/schema/utils/mod.rs @@ -19,6 +19,15 @@ pub enum OneOrList { List(Vec), } +impl From> for OneOrList { + fn from(mut value: Vec) -> Self { + match value.len() { + 1 => OneOrList::One(value.remove(0)), + _ => OneOrList::List(value), + } + } +} + impl OneOrList { pub fn first(&self) -> Option { match self { diff --git a/did_core/did_doc/src/schema/verification_method/verification_method_type.rs b/did_core/did_doc/src/schema/verification_method/verification_method_type.rs index 9d41289141..e48d672467 100644 --- a/did_core/did_doc/src/schema/verification_method/verification_method_type.rs +++ b/did_core/did_doc/src/schema/verification_method/verification_method_type.rs @@ -7,18 +7,26 @@ use crate::error::DidDocumentBuilderError; #[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq)] pub enum VerificationMethodType { + /// https://w3id.org/security/suites/jws-2020/v1 JsonWebKey2020, + /// https://w3id.org/security/suites/secp256k1-2019/v1 EcdsaSecp256k1VerificationKey2019, + /// https://w3id.org/security/suites/ed25519-2018/v1 Ed25519VerificationKey2018, Ed25519VerificationKey2020, + /// https://w3c.github.io/vc-di-bbs/contexts/v1/ Bls12381G1Key2020, + /// https://w3c.github.io/vc-di-bbs/contexts/v1/ Bls12381G2Key2020, PgpVerificationKey2021, RsaVerificationKey2018, + /// https://ns.did.ai/suites/x25519-2019/v1/ X25519KeyAgreementKey2019, + /// https://ns.did.ai/suites/x25519-2020/v1/ X25519KeyAgreementKey2020, EcdsaSecp256k1RecoveryMethod2020, /// https://www.w3.org/TR/vc-data-integrity/#multikey + /// https://w3id.org/security/multikey/v1 Multikey, } diff --git a/did_core/did_methods/did_cheqd/Cargo.toml b/did_core/did_methods/did_cheqd/Cargo.toml index 9e40eb0a52..819af9d16a 100644 --- a/did_core/did_methods/did_cheqd/Cargo.toml +++ b/did_core/did_methods/did_cheqd/Cargo.toml @@ -8,8 +8,25 @@ edition = "2021" [dependencies] did_resolver = { path = "../../did_resolver" } -aries_vcx_ledger = { path = "../../../aries/aries_vcx_ledger" } +tonic = { version = "0.12.3", default-features = false, features = [ + "codegen", + "prost", + "channel", + "tls-native-roots", +] } +prost = { version = "0.13.3", default-features = false } +prost-types = "0.13.3" async-trait = "0.1.68" serde_json = "1.0.96" serde = { version = "1.0.160", features = ["derive"] } thiserror = "1.0.40" +tokio = { version = "1.38.0" } + +[dev-dependencies] +tokio = { version = "1.38.0", default-features = false, features = [ + "macros", + "rt", +] } + +[build-dependencies] +tonic-build = "0.12.3" diff --git a/did_core/did_methods/did_cheqd/build.rs b/did_core/did_methods/did_cheqd/build.rs new file mode 100644 index 0000000000..73dfbc9cf5 --- /dev/null +++ b/did_core/did_methods/did_cheqd/build.rs @@ -0,0 +1,12 @@ +fn main() -> Result<(), Box> { + tonic_build::configure() + .build_server(false) + .compile_protos( + &[ + "proto/cheqd/did/v2/query.proto", + "proto/cheqd/resource/v2/query.proto", + ], + &["proto"], + )?; + Ok(()) +} diff --git a/did_core/did_methods/did_cheqd/proto/cheqd/did/v2/diddoc.proto b/did_core/did_methods/did_cheqd/proto/cheqd/did/v2/diddoc.proto new file mode 100644 index 0000000000..ba08ea6f58 --- /dev/null +++ b/did_core/did_methods/did_cheqd/proto/cheqd/did/v2/diddoc.proto @@ -0,0 +1,138 @@ +syntax = "proto3"; + +package cheqd.did.v2; + +import "gogoproto/gogo.proto"; +import "google/protobuf/timestamp.proto"; + +option go_package = "github.com/cheqd/cheqd-node/x/did/types"; + +// DidDoc defines a DID Document, as defined in the DID Core specification. +// Documentation: https://www.w3.org/TR/did-core/ +message DidDoc { + // context is a list of URIs used to identify the context of the DID document. + // Default: https://www.w3.org/ns/did/v1 + repeated string context = 1; + + // id is the DID of the DID document. + // Format: did:cheqd:: + string id = 2; + + // controller is a list of DIDs that are allowed to control the DID document. + repeated string controller = 3; + + // verificationMethod is a list of verification methods that can be used to + // verify a digital signature or cryptographic proof. + repeated VerificationMethod verification_method = 4; + + // authentication is a list of verification methods that can be used to + // authenticate as the DID subject. + repeated string authentication = 5; + + // assertionMethod is a list of verification methods that can be used to + // assert statements as the DID subject. + repeated string assertion_method = 6; + + // capabilityInvocation is a list of verification methods that can be used to + // invoke capabilities as the DID subject. + repeated string capability_invocation = 7; + + // capabilityDelegation is a list of verification methods that can be used to + // delegate capabilities as the DID subject. + repeated string capability_delegation = 8; + + // keyAgreement is a list of verification methods that can be used to perform + // key agreement as the DID subject. + repeated string key_agreement = 9; + + // service is a list of services that can be used to interact with the DID subject. + repeated Service service = 10; + + // alsoKnownAs is a list of DIDs that are known to refer to the same DID subject. + repeated string also_known_as = 11; +} + +// VerificationMethod defines a verification method, as defined in the DID Core specification. +// Documentation: https://www.w3.org/TR/did-core/#verification-methods +message VerificationMethod { + // id is the unique identifier of the verification method. + // Format: did:cheqd::# + string id = 1; + + // type is the type of the verification method. + // Example: Ed25519VerificationKey2020 + string verification_method_type = 2 [(gogoproto.jsontag) = "type,omitempty"]; + + // controller is the DID of the controller of the verification method. + // Format: did:cheqd:: + string controller = 3; + + // verification_material is the public key of the verification method. + // Commonly used verification material types: publicJwk, publicKeyBase58, publicKeyMultibase + string verification_material = 4; +} + +// Service defines a service, as defined in the DID Core specification. +// Documentation: https://www.w3.org/TR/did-core/#services +message Service { + // id is the unique identifier of the service. + // Format: did:cheqd::# + string id = 1; + + // type is the type of the service. + // Example: LinkedResource + string service_type = 2 [(gogoproto.jsontag) = "type,omitempty"]; + + // serviceEndpoint is the endpoint of the service. + // Example: https://example.com/endpoint + repeated string service_endpoint = 3; +} + +// DidDocWithMetadata defines a DID Document with metadata, as defined in the DID Core specification. +// Contains the DID Document, as well as DID Document metadata. +message DidDocWithMetadata { + // didDocument is the DID Document. + DidDoc did_doc = 1 [(gogoproto.jsontag) = "didDocument"]; + + // didDocumentMetadata is the DID Document metadata. + Metadata metadata = 2 [(gogoproto.jsontag) = "didDocumentMetadata"]; +} + +// Metadata defines DID Document metadata, as defined in the DID Core specification. +// Documentation: https://www.w3.org/TR/did-core/#did-document-metadata-properties +message Metadata { + // created is the timestamp of the creation of the DID Document. + // Format: RFC3339 + // Example: 2021-03-10T15:16:17Z + google.protobuf.Timestamp created = 1 [ + (gogoproto.nullable) = false, + (gogoproto.stdtime) = true + ]; + + // updated is the timestamp of the last update of the DID Document. + // Format: RFC3339 + // Example: 2021-03-10T15:16:17Z + google.protobuf.Timestamp updated = 2 [ + (gogoproto.nullable) = true, + (gogoproto.stdtime) = true + ]; + + // deactivated is a flag that indicates whether the DID Document is deactivated. + // Default: false + bool deactivated = 3; + + // version_id is the version identifier of the DID Document. + // Format: UUID + // Example: 123e4567-e89b-12d3-a456-426655440000 + string version_id = 4; + + // next_version_id is the version identifier of the next version of the DID Document. + // Format: UUID + // Example: 123e4567-e89b-12d3-a456-426655440000 + string next_version_id = 5 [(gogoproto.nullable) = true]; + + // previous_version_id is the version identifier of the previous version of the DID Document. + // Format: UUID + // Example: 123e4567-e89b-12d3-a456-426655440000 + string previous_version_id = 6 [(gogoproto.nullable) = true]; +} \ No newline at end of file diff --git a/did_core/did_methods/did_cheqd/proto/cheqd/did/v2/query.proto b/did_core/did_methods/did_cheqd/proto/cheqd/did/v2/query.proto new file mode 100644 index 0000000000..0bbfdc52e2 --- /dev/null +++ b/did_core/did_methods/did_cheqd/proto/cheqd/did/v2/query.proto @@ -0,0 +1,87 @@ +syntax = "proto3"; +package cheqd.did.v2; +import "cheqd/did/v2/diddoc.proto"; +import "cosmos/base/query/v1beta1/pagination.proto"; +import "google/api/annotations.proto"; +option go_package = "github.com/cheqd/cheqd-node/x/did/types"; +// Query defines the gRPC querier service for the DID module +service Query { + // Fetch latest version of a DID Document for a given DID + rpc DidDoc(QueryDidDocRequest) returns (QueryDidDocResponse) { + option (google.api.http) = {get: "/cheqd/did/v2/{id}"}; + } + // Fetch specific version of a DID Document for a given DID + rpc DidDocVersion(QueryDidDocVersionRequest) returns (QueryDidDocVersionResponse) { + option (google.api.http) = {get: "/cheqd/did/v2/{id}/version/{version}"}; + } + // Fetch list of all versions of DID Documents for a given DID + rpc AllDidDocVersionsMetadata(QueryAllDidDocVersionsMetadataRequest) returns (QueryAllDidDocVersionsMetadataResponse) { + option (google.api.http) = {get: "/cheqd/did/v2/{id}/versions"}; + } +} +// QueryDidDocRequest is the request type for the Query/DidDoc method +message QueryDidDocRequest { + // DID unique identifier of the DID Document to fetch. + // UUID-style DIDs as well as Indy-style DID are supported. + // + // Format: did:cheqd:: + // + // Examples: + // - did:cheqd:mainnet:c82f2b02-bdab-4dd7-b833-3e143745d612 + // - did:cheqd:testnet:wGHEXrZvJxR8vw5P3UWH1j + string id = 1; +} +// QueryDidDocResponse is the response type for the Query/DidDoc method +message QueryDidDocResponse { + // Successful resolution of the DID Document returns the following: + // - did_doc is the latest version of the DID Document + // - metadata is is the DID Document metadata associated with the latest version of the DID Document + DidDocWithMetadata value = 1; +} +// QueryDidDocVersionRequest is the request type for the Query/DidDocVersion method +message QueryDidDocVersionRequest { + // DID unique identifier of the DID Document to fetch. + // UUID-style DIDs as well as Indy-style DID are supported. + // + // Format: did:cheqd:: + // + // Examples: + // - did:cheqd:mainnet:c82f2b02-bdab-4dd7-b833-3e143745d612 + // - did:cheqd:testnet:wGHEXrZvJxR8vw5P3UWH1j + string id = 1; + // Unique version identifier of the DID Document to fetch. + // Returns the specified version of the DID Document. + // + // Format: + // + // Example: 93f2573c-eca9-4098-96cb-a1ec676a29ed + string version = 2; +} +// QueryDidDocVersionResponse is the response type for the Query/DidDocVersion method +message QueryDidDocVersionResponse { + // Successful resolution of the DID Document returns the following: + // - did_doc is the requested version of the DID Document + // - metadata is DID Document metadata associated with the requested version of the DID Document + DidDocWithMetadata value = 1; +} +// QueryAllDidDocVersionsMetadataRequest is the request type for the Query/AllDidDocVersionsMetadata method +message QueryAllDidDocVersionsMetadataRequest { + // DID unique identifier of the DID Document to fetch version metadata. + // UUID-style DIDs as well as Indy-style DID are supported. + // + // Format: did:cheqd:: + // + // Examples: + // - did:cheqd:mainnet:c82f2b02-bdab-4dd7-b833-3e143745d612 + // - did:cheqd:testnet:wGHEXrZvJxR8vw5P3UWH1j + string id = 1; + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 2; +} +// QueryAllDidDocVersionsMetadataResponse is the response type for the Query/AllDidDocVersionsMetadata method +message QueryAllDidDocVersionsMetadataResponse { + // versions is the list of all versions of the requested DID Document + repeated Metadata versions = 1; + // pagination defines the pagination in the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} diff --git a/did_core/did_methods/did_cheqd/proto/cheqd/resource/v2/query.proto b/did_core/did_methods/did_cheqd/proto/cheqd/resource/v2/query.proto new file mode 100644 index 0000000000..b9a0097dd1 --- /dev/null +++ b/did_core/did_methods/did_cheqd/proto/cheqd/resource/v2/query.proto @@ -0,0 +1,79 @@ +syntax = "proto3"; +package cheqd.resource.v2; +import "cheqd/resource/v2/resource.proto"; +import "cosmos/base/query/v1beta1/pagination.proto"; +import "gogoproto/gogo.proto"; +import "google/api/annotations.proto"; +option go_package = "github.com/cheqd/cheqd-node/x/resource/types"; +// Query defines the gRPC querier service for the resource module +service Query { + // Fetch data/payload for a specific resource (without metadata) + rpc Resource(QueryResourceRequest) returns (QueryResourceResponse) { + option (google.api.http).get = "/cheqd/resource/v2/{collection_id}/resources/{id}"; + } + // Fetch only metadata for a specific resource + rpc ResourceMetadata(QueryResourceMetadataRequest) returns (QueryResourceMetadataResponse) { + option (google.api.http).get = "/cheqd/resource/v2/{collection_id}/resources/{id}/metadata"; + } + // Fetch metadata for all resources in a collection + rpc CollectionResources(QueryCollectionResourcesRequest) returns (QueryCollectionResourcesResponse) { + option (google.api.http).get = "/cheqd/resource/v2/{collection_id}/metadata"; + } +} +// QueryResourceRequest is the request type for the Query/Resource RPC method +message QueryResourceRequest { + // collection_id is an identifier of the DidDocument the resource belongs to. + // Format: + // + // Examples: + // - c82f2b02-bdab-4dd7-b833-3e143745d612 + // - wGHEXrZvJxR8vw5P3UWH1j + string collection_id = 1; + // id is a unique id of the resource. + // Format: + string id = 2; +} +// QueryResourceResponse is the response type for the Query/Resource RPC method +message QueryResourceResponse { + // Successful resolution of the resource returns the following: + // - resource is the requested resource + // - metadata is the resource metadata associated with the requested resource + ResourceWithMetadata resource = 1; +} +// QueryResourceMetadataRequest is the request type for the Query/ResourceMetadata RPC method +message QueryResourceMetadataRequest { + // collection_id is an identifier of the DidDocument the resource belongs to. + // Format: + // + // Examples: + // - c82f2b02-bdab-4dd7-b833-3e143745d612 + // - wGHEXrZvJxR8vw5P3UWH1j + string collection_id = 1; + // id is a unique id of the resource. + // Format: + string id = 2; +} +// QueryResourceMetadataResponse is the response type for the Query/ResourceMetadata RPC method +message QueryResourceMetadataResponse { + // resource is the requested resource metadata + Metadata resource = 1 [(gogoproto.jsontag) = "linkedResourceMetadata"]; +} +// QueryCollectionResourcesRequest is the request type for the Query/CollectionResources RPC method +message QueryCollectionResourcesRequest { + // collection_id is an identifier of the DidDocument the resource belongs to. + // Format: + // + // Examples: + // - c82f2b02-bdab-4dd7-b833-3e143745d612 + // - wGHEXrZvJxR8vw5P3UWH1j + string collection_id = 1; + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 2; +} +// QueryCollectionResourcesResponse is the response type for the Query/CollectionResources RPC method +message QueryCollectionResourcesResponse { + // resources is the requested collection of resource metadata + repeated Metadata resources = 1 [(gogoproto.jsontag) = "linkedResourceMetadata"]; + // pagination defines the pagination in the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} \ No newline at end of file diff --git a/did_core/did_methods/did_cheqd/proto/cheqd/resource/v2/resource.proto b/did_core/did_methods/did_cheqd/proto/cheqd/resource/v2/resource.proto new file mode 100644 index 0000000000..96ab371c95 --- /dev/null +++ b/did_core/did_methods/did_cheqd/proto/cheqd/resource/v2/resource.proto @@ -0,0 +1,89 @@ +syntax = "proto3"; +package cheqd.resource.v2; +import "gogoproto/gogo.proto"; +import "google/protobuf/timestamp.proto"; +option go_package = "github.com/cheqd/cheqd-node/x/resource/types"; +// Resource stores the contents of a DID-Linked Resource +message Resource { + // bytes is the raw data of the Resource + bytes data = 1; +} +// Metadata stores the metadata of a DID-Linked Resource +message Metadata { + // collection_id is the ID of the collection that the Resource belongs to. Defined client-side. + // This field is the unique identifier of the DID linked to this Resource + // Format: + // + // Examples: + // - c82f2b02-bdab-4dd7-b833-3e143745d612 + // - wGHEXrZvJxR8vw5P3UWH1j + string collection_id = 1 [(gogoproto.jsontag) = "resourceCollectionId"]; + // id is the ID of the Resource. Defined client-side. + // This field is a unique identifier for this specific version of the Resource. + // Format: + string id = 2 [(gogoproto.jsontag) = "resourceId"]; + // name is a human-readable name for the Resource. Defined client-side. + // Does not change between different versions. + // Example: PassportSchema, EducationTrustRegistry + string name = 3 [(gogoproto.jsontag) = "resourceName"]; + // version is a human-readable semantic version for the Resource. Defined client-side. + // Stored as a string. OPTIONAL. + // Example: 1.0.0, v2.1.0 + string version = 4 [ + (gogoproto.jsontag) = "resourceVersion", + (gogoproto.nullable) = true + ]; + // resource_type is a Resource type that identifies what the Resource is. Defined client-side. + // This is NOT the same as the resource's media type. + // Example: AnonCredsSchema, StatusList2021 + string resource_type = 5 [(gogoproto.jsontag) = "resourceType"]; + // List of alternative URIs for the SAME Resource. + repeated AlternativeUri also_known_as = 6 [ + (gogoproto.jsontag) = "resourceAlternativeUri", + (gogoproto.nullable) = true + ]; + // media_type is IANA media type of the Resource. Defined ledger-side. + // Example: application/json, image/png + string media_type = 7; + // created is the time at which the Resource was created. Defined ledger-side. + // Format: RFC3339 + // Example: 2021-01-01T00:00:00Z + google.protobuf.Timestamp created = 8 [ + (gogoproto.nullable) = false, + (gogoproto.stdtime) = true + ]; + // checksum is a SHA-256 checksum hash of the Resource. Defined ledger-side. + // Example: d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f + string checksum = 9; + // previous_version_id is the ID of the previous version of the Resource. Defined ledger-side. + // This is based on the Resource's name and Resource type to determine whether it's the same Resource. + // Format: + string previous_version_id = 10 [(gogoproto.nullable) = true]; + // next_version_id is the ID of the next version of the Resource. Defined ledger-side. + // This is based on the Resource's name and Resource type to determine whether it's the same Resource. + // Format: + string next_version_id = 11 [(gogoproto.nullable) = true]; +} +// AlternativeUri are alternative URIs that can be used to access the Resource. +// By default, at least the DID URI equivalent of the Resource is populated. +message AlternativeUri { + // uri is the URI of the Resource. + // Examples: + // - did:cheqd:testnet:MjYxNzYKMjYxNzYK/resources/4600ea35-8916-4ac4-b412-55b8f49dd94e + // - https://resolver..cheqd.net/1.0/identifiers/did:cheqd:testnet:MjYxNzYKMjYxNzYK/resources/4600ea35-8916-4ac4-b412-55b8f49dd94e + // - https://example.com/example.json + // - https://gateway.ipfs.io/ipfs/bafybeihetj2ng3d74k7t754atv2s5dk76pcqtvxls6dntef3xa6rax25xe + // - ipfs://bafybeihetj2ng3d74k7t754atv2s5dk76pcqtvxls6dntef3xa6rax25xe + string uri = 1; + // description is a human-readable description of the URI. Defined client-side. + // Examples: + // - did-uri + // - http-uri + // - ipfs-uri + string description = 2; +} +// ResourceWithMetadata describes the overall structure of a DID-Linked Resource +message ResourceWithMetadata { + Resource resource = 1 [(gogoproto.jsontag) = "linkedResource"]; + Metadata metadata = 2 [(gogoproto.jsontag) = "linkedResourceMetadata"]; +} diff --git a/did_core/did_methods/did_cheqd/proto/cosmos/base/query/v1beta1/pagination.proto b/did_core/did_methods/did_cheqd/proto/cosmos/base/query/v1beta1/pagination.proto new file mode 100644 index 0000000000..a532fc38a0 --- /dev/null +++ b/did_core/did_methods/did_cheqd/proto/cosmos/base/query/v1beta1/pagination.proto @@ -0,0 +1,48 @@ +syntax = "proto3"; +package cosmos.base.query.v1beta1; +option go_package = "github.com/cosmos/cosmos-sdk/types/query"; +// PageRequest is to be embedded in gRPC request messages for efficient +// pagination. Ex: +// +// message SomeRequest { +// Foo some_parameter = 1; +// PageRequest pagination = 2; +// } +message PageRequest { + // key is a value returned in PageResponse.next_key to begin + // querying the next page most efficiently. Only one of offset or key + // should be set. + bytes key = 1; + // offset is a numeric offset that can be used when key is unavailable. + // It is less efficient than using key. Only one of offset or key should + // be set. + uint64 offset = 2; + // limit is the total number of results to be returned in the result page. + // If left empty it will default to a value to be set by each app. + uint64 limit = 3; + // count_total is set to true to indicate that the result set should include + // a count of the total number of items available for pagination in UIs. + // count_total is only respected when offset is used. It is ignored when key + // is set. + bool count_total = 4; + // reverse is set to true if results are to be returned in the descending order. + // + // Since: cosmos-sdk 0.43 + bool reverse = 5; +} +// PageResponse is to be embedded in gRPC response messages where the +// corresponding request message has used PageRequest. +// +// message SomeResponse { +// repeated Bar results = 1; +// PageResponse page = 2; +// } +message PageResponse { + // next_key is the key to be passed to PageRequest.key to + // query the next page most efficiently. It will be empty if + // there are no more results. + bytes next_key = 1; + // total is total number of results available if PageRequest.count_total + // was set, its value is undefined otherwise + uint64 total = 2; +} diff --git a/did_core/did_methods/did_cheqd/proto/gogoproto/gogo.proto b/did_core/did_methods/did_cheqd/proto/gogoproto/gogo.proto new file mode 100644 index 0000000000..8947d90aa5 --- /dev/null +++ b/did_core/did_methods/did_cheqd/proto/gogoproto/gogo.proto @@ -0,0 +1,144 @@ +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2013, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; +package gogoproto; + +import "google/protobuf/descriptor.proto"; + +option java_package = "com.google.protobuf"; +option java_outer_classname = "GoGoProtos"; +option go_package = "github.com/gogo/protobuf/gogoproto"; + +extend google.protobuf.EnumOptions { + optional bool goproto_enum_prefix = 62001; + optional bool goproto_enum_stringer = 62021; + optional bool enum_stringer = 62022; + optional string enum_customname = 62023; + optional bool enumdecl = 62024; +} + +extend google.protobuf.EnumValueOptions { + optional string enumvalue_customname = 66001; +} + +extend google.protobuf.FileOptions { + optional bool goproto_getters_all = 63001; + optional bool goproto_enum_prefix_all = 63002; + optional bool goproto_stringer_all = 63003; + optional bool verbose_equal_all = 63004; + optional bool face_all = 63005; + optional bool gostring_all = 63006; + optional bool populate_all = 63007; + optional bool stringer_all = 63008; + optional bool onlyone_all = 63009; + + optional bool equal_all = 63013; + optional bool description_all = 63014; + optional bool testgen_all = 63015; + optional bool benchgen_all = 63016; + optional bool marshaler_all = 63017; + optional bool unmarshaler_all = 63018; + optional bool stable_marshaler_all = 63019; + + optional bool sizer_all = 63020; + + optional bool goproto_enum_stringer_all = 63021; + optional bool enum_stringer_all = 63022; + + optional bool unsafe_marshaler_all = 63023; + optional bool unsafe_unmarshaler_all = 63024; + + optional bool goproto_extensions_map_all = 63025; + optional bool goproto_unrecognized_all = 63026; + optional bool gogoproto_import = 63027; + optional bool protosizer_all = 63028; + optional bool compare_all = 63029; + optional bool typedecl_all = 63030; + optional bool enumdecl_all = 63031; + + optional bool goproto_registration = 63032; + optional bool messagename_all = 63033; + + optional bool goproto_sizecache_all = 63034; + optional bool goproto_unkeyed_all = 63035; +} + +extend google.protobuf.MessageOptions { + optional bool goproto_getters = 64001; + optional bool goproto_stringer = 64003; + optional bool verbose_equal = 64004; + optional bool face = 64005; + optional bool gostring = 64006; + optional bool populate = 64007; + optional bool stringer = 67008; + optional bool onlyone = 64009; + + optional bool equal = 64013; + optional bool description = 64014; + optional bool testgen = 64015; + optional bool benchgen = 64016; + optional bool marshaler = 64017; + optional bool unmarshaler = 64018; + optional bool stable_marshaler = 64019; + + optional bool sizer = 64020; + + optional bool unsafe_marshaler = 64023; + optional bool unsafe_unmarshaler = 64024; + + optional bool goproto_extensions_map = 64025; + optional bool goproto_unrecognized = 64026; + + optional bool protosizer = 64028; + optional bool compare = 64029; + + optional bool typedecl = 64030; + + optional bool messagename = 64033; + + optional bool goproto_sizecache = 64034; + optional bool goproto_unkeyed = 64035; +} + +extend google.protobuf.FieldOptions { + optional bool nullable = 65001; + optional bool embed = 65002; + optional string customtype = 65003; + optional string customname = 65004; + optional string jsontag = 65005; + optional string moretags = 65006; + optional string casttype = 65007; + optional string castkey = 65008; + optional string castvalue = 65009; + + optional bool stdtime = 65010; + optional bool stdduration = 65011; + optional bool wktpointer = 65012; + +} \ No newline at end of file diff --git a/did_core/did_methods/did_cheqd/proto/google/api/annotations.proto b/did_core/did_methods/did_cheqd/proto/google/api/annotations.proto new file mode 100644 index 0000000000..b17b345600 --- /dev/null +++ b/did_core/did_methods/did_cheqd/proto/google/api/annotations.proto @@ -0,0 +1,31 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +import "google/api/http.proto"; +import "google/protobuf/descriptor.proto"; + +option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; +option java_multiple_files = true; +option java_outer_classname = "AnnotationsProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +extend google.protobuf.MethodOptions { + // See `HttpRule`. + HttpRule http = 72295728; +} \ No newline at end of file diff --git a/did_core/did_methods/did_cheqd/proto/google/api/http.proto b/did_core/did_methods/did_cheqd/proto/google/api/http.proto new file mode 100644 index 0000000000..c9b7fdc3f1 --- /dev/null +++ b/did_core/did_methods/did_cheqd/proto/google/api/http.proto @@ -0,0 +1,371 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; +option java_multiple_files = true; +option java_outer_classname = "HttpProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// Defines the HTTP configuration for an API service. It contains a list of +// [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method +// to one or more HTTP REST API methods. +message Http { + // A list of HTTP configuration rules that apply to individual API methods. + // + // **NOTE:** All service configuration rules follow "last one wins" order. + repeated HttpRule rules = 1; + + // When set to true, URL path parameters will be fully URI-decoded except in + // cases of single segment matches in reserved expansion, where "%2F" will be + // left encoded. + // + // The default behavior is to not decode RFC 6570 reserved characters in multi + // segment matches. + bool fully_decode_reserved_expansion = 2; +} + +// gRPC Transcoding +// +// gRPC Transcoding is a feature for mapping between a gRPC method and one or +// more HTTP REST endpoints. It allows developers to build a single API service +// that supports both gRPC APIs and REST APIs. Many systems, including [Google +// APIs](https://github.com/googleapis/googleapis), +// [Cloud Endpoints](https://cloud.google.com/endpoints), [gRPC +// Gateway](https://github.com/grpc-ecosystem/grpc-gateway), +// and [Envoy](https://github.com/envoyproxy/envoy) proxy support this feature +// and use it for large scale production services. +// +// `HttpRule` defines the schema of the gRPC/REST mapping. The mapping specifies +// how different portions of the gRPC request message are mapped to the URL +// path, URL query parameters, and HTTP request body. It also controls how the +// gRPC response message is mapped to the HTTP response body. `HttpRule` is +// typically specified as an `google.api.http` annotation on the gRPC method. +// +// Each mapping specifies a URL path template and an HTTP method. The path +// template may refer to one or more fields in the gRPC request message, as long +// as each field is a non-repeated field with a primitive (non-message) type. +// The path template controls how fields of the request message are mapped to +// the URL path. +// +// Example: +// +// service Messaging { +// rpc GetMessage(GetMessageRequest) returns (Message) { +// option (google.api.http) = { +// get: "/v1/{name=messages/*}" +// }; +// } +// } +// message GetMessageRequest { +// string name = 1; // Mapped to URL path. +// } +// message Message { +// string text = 1; // The resource content. +// } +// +// This enables an HTTP REST to gRPC mapping as below: +// +// - HTTP: `GET /v1/messages/123456` +// - gRPC: `GetMessage(name: "messages/123456")` +// +// Any fields in the request message which are not bound by the path template +// automatically become HTTP query parameters if there is no HTTP request body. +// For example: +// +// service Messaging { +// rpc GetMessage(GetMessageRequest) returns (Message) { +// option (google.api.http) = { +// get:"/v1/messages/{message_id}" +// }; +// } +// } +// message GetMessageRequest { +// message SubMessage { +// string subfield = 1; +// } +// string message_id = 1; // Mapped to URL path. +// int64 revision = 2; // Mapped to URL query parameter `revision`. +// SubMessage sub = 3; // Mapped to URL query parameter `sub.subfield`. +// } +// +// This enables a HTTP JSON to RPC mapping as below: +// +// - HTTP: `GET /v1/messages/123456?revision=2&sub.subfield=foo` +// - gRPC: `GetMessage(message_id: "123456" revision: 2 sub: +// SubMessage(subfield: "foo"))` +// +// Note that fields which are mapped to URL query parameters must have a +// primitive type or a repeated primitive type or a non-repeated message type. +// In the case of a repeated type, the parameter can be repeated in the URL +// as `...?param=A¶m=B`. In the case of a message type, each field of the +// message is mapped to a separate parameter, such as +// `...?foo.a=A&foo.b=B&foo.c=C`. +// +// For HTTP methods that allow a request body, the `body` field +// specifies the mapping. Consider a REST update method on the +// message resource collection: +// +// service Messaging { +// rpc UpdateMessage(UpdateMessageRequest) returns (Message) { +// option (google.api.http) = { +// patch: "/v1/messages/{message_id}" +// body: "message" +// }; +// } +// } +// message UpdateMessageRequest { +// string message_id = 1; // mapped to the URL +// Message message = 2; // mapped to the body +// } +// +// The following HTTP JSON to RPC mapping is enabled, where the +// representation of the JSON in the request body is determined by +// protos JSON encoding: +// +// - HTTP: `PATCH /v1/messages/123456 { "text": "Hi!" }` +// - gRPC: `UpdateMessage(message_id: "123456" message { text: "Hi!" })` +// +// The special name `*` can be used in the body mapping to define that +// every field not bound by the path template should be mapped to the +// request body. This enables the following alternative definition of +// the update method: +// +// service Messaging { +// rpc UpdateMessage(Message) returns (Message) { +// option (google.api.http) = { +// patch: "/v1/messages/{message_id}" +// body: "*" +// }; +// } +// } +// message Message { +// string message_id = 1; +// string text = 2; +// } +// +// +// The following HTTP JSON to RPC mapping is enabled: +// +// - HTTP: `PATCH /v1/messages/123456 { "text": "Hi!" }` +// - gRPC: `UpdateMessage(message_id: "123456" text: "Hi!")` +// +// Note that when using `*` in the body mapping, it is not possible to +// have HTTP parameters, as all fields not bound by the path end in +// the body. This makes this option more rarely used in practice when +// defining REST APIs. The common usage of `*` is in custom methods +// which don't use the URL at all for transferring data. +// +// It is possible to define multiple HTTP methods for one RPC by using +// the `additional_bindings` option. Example: +// +// service Messaging { +// rpc GetMessage(GetMessageRequest) returns (Message) { +// option (google.api.http) = { +// get: "/v1/messages/{message_id}" +// additional_bindings { +// get: "/v1/users/{user_id}/messages/{message_id}" +// } +// }; +// } +// } +// message GetMessageRequest { +// string message_id = 1; +// string user_id = 2; +// } +// +// This enables the following two alternative HTTP JSON to RPC mappings: +// +// - HTTP: `GET /v1/messages/123456` +// - gRPC: `GetMessage(message_id: "123456")` +// +// - HTTP: `GET /v1/users/me/messages/123456` +// - gRPC: `GetMessage(user_id: "me" message_id: "123456")` +// +// Rules for HTTP mapping +// +// 1. Leaf request fields (recursive expansion nested messages in the request +// message) are classified into three categories: +// - Fields referred by the path template. They are passed via the URL path. +// - Fields referred by the [HttpRule.body][google.api.HttpRule.body]. They +// are passed via the HTTP +// request body. +// - All other fields are passed via the URL query parameters, and the +// parameter name is the field path in the request message. A repeated +// field can be represented as multiple query parameters under the same +// name. +// 2. If [HttpRule.body][google.api.HttpRule.body] is "*", there is no URL +// query parameter, all fields +// are passed via URL path and HTTP request body. +// 3. If [HttpRule.body][google.api.HttpRule.body] is omitted, there is no HTTP +// request body, all +// fields are passed via URL path and URL query parameters. +// +// Path template syntax +// +// Template = "/" Segments [ Verb ] ; +// Segments = Segment { "/" Segment } ; +// Segment = "*" | "**" | LITERAL | Variable ; +// Variable = "{" FieldPath [ "=" Segments ] "}" ; +// FieldPath = IDENT { "." IDENT } ; +// Verb = ":" LITERAL ; +// +// The syntax `*` matches a single URL path segment. The syntax `**` matches +// zero or more URL path segments, which must be the last part of the URL path +// except the `Verb`. +// +// The syntax `Variable` matches part of the URL path as specified by its +// template. A variable template must not contain other variables. If a variable +// matches a single path segment, its template may be omitted, e.g. `{var}` +// is equivalent to `{var=*}`. +// +// The syntax `LITERAL` matches literal text in the URL path. If the `LITERAL` +// contains any reserved character, such characters should be percent-encoded +// before the matching. +// +// If a variable contains exactly one path segment, such as `"{var}"` or +// `"{var=*}"`, when such a variable is expanded into a URL path on the client +// side, all characters except `[-_.~0-9a-zA-Z]` are percent-encoded. The +// server side does the reverse decoding. Such variables show up in the +// [Discovery +// Document](https://developers.google.com/discovery/v1/reference/apis) as +// `{var}`. +// +// If a variable contains multiple path segments, such as `"{var=foo/*}"` +// or `"{var=**}"`, when such a variable is expanded into a URL path on the +// client side, all characters except `[-_.~/0-9a-zA-Z]` are percent-encoded. +// The server side does the reverse decoding, except "%2F" and "%2f" are left +// unchanged. Such variables show up in the +// [Discovery +// Document](https://developers.google.com/discovery/v1/reference/apis) as +// `{+var}`. +// +// Using gRPC API Service Configuration +// +// gRPC API Service Configuration (service config) is a configuration language +// for configuring a gRPC service to become a user-facing product. The +// service config is simply the YAML representation of the `google.api.Service` +// proto message. +// +// As an alternative to annotating your proto file, you can configure gRPC +// transcoding in your service config YAML files. You do this by specifying a +// `HttpRule` that maps the gRPC method to a REST endpoint, achieving the same +// effect as the proto annotation. This can be particularly useful if you +// have a proto that is reused in multiple services. Note that any transcoding +// specified in the service config will override any matching transcoding +// configuration in the proto. +// +// The following example selects a gRPC method and applies an `HttpRule` to it: +// +// http: +// rules: +// - selector: example.v1.Messaging.GetMessage +// get: /v1/messages/{message_id}/{sub.subfield} +// +// Special notes +// +// When gRPC Transcoding is used to map a gRPC to JSON REST endpoints, the +// proto to JSON conversion must follow the [proto3 +// specification](https://developers.google.com/protocol-buffers/docs/proto3#json). +// +// While the single segment variable follows the semantics of +// [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.2 Simple String +// Expansion, the multi segment variable **does not** follow RFC 6570 Section +// 3.2.3 Reserved Expansion. The reason is that the Reserved Expansion +// does not expand special characters like `?` and `#`, which would lead +// to invalid URLs. As the result, gRPC Transcoding uses a custom encoding +// for multi segment variables. +// +// The path variables **must not** refer to any repeated or mapped field, +// because client libraries are not capable of handling such variable expansion. +// +// The path variables **must not** capture the leading "/" character. The reason +// is that the most common use case "{var}" does not capture the leading "/" +// character. For consistency, all path variables must share the same behavior. +// +// Repeated message fields must not be mapped to URL query parameters, because +// no client library can support such complicated mapping. +// +// If an API needs to use a JSON array for request or response body, it can map +// the request or response body to a repeated field. However, some gRPC +// Transcoding implementations may not support this feature. +message HttpRule { + // Selects a method to which this rule applies. + // + // Refer to [selector][google.api.DocumentationRule.selector] for syntax + // details. + string selector = 1; + + // Determines the URL pattern is matched by this rules. This pattern can be + // used with any of the {get|put|post|delete|patch} methods. A custom method + // can be defined using the 'custom' field. + oneof pattern { + // Maps to HTTP GET. Used for listing and getting information about + // resources. + string get = 2; + + // Maps to HTTP PUT. Used for replacing a resource. + string put = 3; + + // Maps to HTTP POST. Used for creating a resource or performing an action. + string post = 4; + + // Maps to HTTP DELETE. Used for deleting a resource. + string delete = 5; + + // Maps to HTTP PATCH. Used for updating a resource. + string patch = 6; + + // The custom pattern is used for specifying an HTTP method that is not + // included in the `pattern` field, such as HEAD, or "*" to leave the + // HTTP method unspecified for this rule. The wild-card rule is useful + // for services that provide content to Web (HTML) clients. + CustomHttpPattern custom = 8; + } + + // The name of the request field whose value is mapped to the HTTP request + // body, or `*` for mapping all request fields not captured by the path + // pattern to the HTTP body, or omitted for not having any HTTP request body. + // + // NOTE: the referred field must be present at the top-level of the request + // message type. + string body = 7; + + // Optional. The name of the response field whose value is mapped to the HTTP + // response body. When omitted, the entire response message will be used + // as the HTTP response body. + // + // NOTE: The referred field must be present at the top-level of the response + // message type. + string response_body = 12; + + // Additional HTTP bindings for the selector. Nested bindings must + // not contain an `additional_bindings` field themselves (that is, + // the nesting may only be one level deep). + repeated HttpRule additional_bindings = 11; +} + +// A custom pattern is used for defining custom HTTP verb. +message CustomHttpPattern { + // The name of this custom HTTP verb. + string kind = 1; + + // The path matched by this custom verb. + string path = 2; +} \ No newline at end of file diff --git a/did_core/did_methods/did_cheqd/proto/google/protobuf/descriptor.proto b/did_core/did_methods/did_cheqd/proto/google/protobuf/descriptor.proto new file mode 100644 index 0000000000..14e7db7b44 --- /dev/null +++ b/did_core/did_methods/did_cheqd/proto/google/protobuf/descriptor.proto @@ -0,0 +1,1307 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// The messages in this file describe the definitions found in .proto files. +// A valid .proto file can be translated directly to a FileDescriptorProto +// without any other information (e.g. without reading its imports). + +syntax = "proto2"; + +package google.protobuf; + +option go_package = "google.golang.org/protobuf/types/descriptorpb"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "DescriptorProtos"; +option csharp_namespace = "Google.Protobuf.Reflection"; +option objc_class_prefix = "GPB"; +option cc_enable_arenas = true; + +// descriptor.proto must be optimized for speed because reflection-based +// algorithms don't work during bootstrapping. +option optimize_for = SPEED; + +// The protocol compiler can output a FileDescriptorSet containing the .proto +// files it parses. +message FileDescriptorSet { + repeated FileDescriptorProto file = 1; + + // Extensions for tooling. + extensions 536000000 [declaration = { + number: 536000000 + type: ".buf.descriptor.v1.FileDescriptorSetExtension" + full_name: ".buf.descriptor.v1.buf_file_descriptor_set_extension" + }]; +} + +// The full set of known editions. +enum Edition { + // A placeholder for an unknown edition value. + EDITION_UNKNOWN = 0; + + // A placeholder edition for specifying default behaviors *before* a feature + // was first introduced. This is effectively an "infinite past". + EDITION_LEGACY = 900; + + // Legacy syntax "editions". These pre-date editions, but behave much like + // distinct editions. These can't be used to specify the edition of proto + // files, but feature definitions must supply proto2/proto3 defaults for + // backwards compatibility. + EDITION_PROTO2 = 998; + EDITION_PROTO3 = 999; + + // Editions that have been released. The specific values are arbitrary and + // should not be depended on, but they will always be time-ordered for easy + // comparison. + EDITION_2023 = 1000; + EDITION_2024 = 1001; + + // Placeholder editions for testing feature resolution. These should not be + // used or relied on outside of tests. + EDITION_1_TEST_ONLY = 1; + EDITION_2_TEST_ONLY = 2; + EDITION_99997_TEST_ONLY = 99997; + EDITION_99998_TEST_ONLY = 99998; + EDITION_99999_TEST_ONLY = 99999; + + // Placeholder for specifying unbounded edition support. This should only + // ever be used by plugins that can expect to never require any changes to + // support a new edition. + EDITION_MAX = 0x7FFFFFFF; +} + +// Describes a complete .proto file. +message FileDescriptorProto { + optional string name = 1; // file name, relative to root of source tree + optional string package = 2; // e.g. "foo", "foo.bar", etc. + + // Names of files imported by this file. + repeated string dependency = 3; + // Indexes of the public imported files in the dependency list above. + repeated int32 public_dependency = 10; + // Indexes of the weak imported files in the dependency list. + // For Google-internal migration only. Do not use. + repeated int32 weak_dependency = 11; + + // All top-level definitions in this file. + repeated DescriptorProto message_type = 4; + repeated EnumDescriptorProto enum_type = 5; + repeated ServiceDescriptorProto service = 6; + repeated FieldDescriptorProto extension = 7; + + optional FileOptions options = 8; + + // This field contains optional information about the original source code. + // You may safely remove this entire field without harming runtime + // functionality of the descriptors -- the information is needed only by + // development tools. + optional SourceCodeInfo source_code_info = 9; + + // The syntax of the proto file. + // The supported values are "proto2", "proto3", and "editions". + // + // If `edition` is present, this value must be "editions". + optional string syntax = 12; + + // The edition of the proto file. + optional Edition edition = 14; +} + +// Describes a message type. +message DescriptorProto { + optional string name = 1; + + repeated FieldDescriptorProto field = 2; + repeated FieldDescriptorProto extension = 6; + + repeated DescriptorProto nested_type = 3; + repeated EnumDescriptorProto enum_type = 4; + + message ExtensionRange { + optional int32 start = 1; // Inclusive. + optional int32 end = 2; // Exclusive. + + optional ExtensionRangeOptions options = 3; + } + repeated ExtensionRange extension_range = 5; + + repeated OneofDescriptorProto oneof_decl = 8; + + optional MessageOptions options = 7; + + // Range of reserved tag numbers. Reserved tag numbers may not be used by + // fields or extension ranges in the same message. Reserved ranges may + // not overlap. + message ReservedRange { + optional int32 start = 1; // Inclusive. + optional int32 end = 2; // Exclusive. + } + repeated ReservedRange reserved_range = 9; + // Reserved field names, which may not be used by fields in the same message. + // A given name may only be reserved once. + repeated string reserved_name = 10; +} + +message ExtensionRangeOptions { + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + message Declaration { + // The extension number declared within the extension range. + optional int32 number = 1; + + // The fully-qualified name of the extension field. There must be a leading + // dot in front of the full name. + optional string full_name = 2; + + // The fully-qualified type name of the extension field. Unlike + // Metadata.type, Declaration.type must have a leading dot for messages + // and enums. + optional string type = 3; + + // If true, indicates that the number is reserved in the extension range, + // and any extension field with the number will fail to compile. Set this + // when a declared extension field is deleted. + optional bool reserved = 5; + + // If true, indicates that the extension must be defined as repeated. + // Otherwise the extension must be defined as optional. + optional bool repeated = 6; + + reserved 4; // removed is_repeated + } + + // For external users: DO NOT USE. We are in the process of open sourcing + // extension declaration and executing internal cleanups before it can be + // used externally. + repeated Declaration declaration = 2 [retention = RETENTION_SOURCE]; + + // Any features defined in the specific edition. + optional FeatureSet features = 50; + + // The verification state of the extension range. + enum VerificationState { + // All the extensions of the range must be declared. + DECLARATION = 0; + UNVERIFIED = 1; + } + + // The verification state of the range. + // TODO: flip the default to DECLARATION once all empty ranges + // are marked as UNVERIFIED. + optional VerificationState verification = 3 + [default = UNVERIFIED, retention = RETENTION_SOURCE]; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +// Describes a field within a message. +message FieldDescriptorProto { + enum Type { + // 0 is reserved for errors. + // Order is weird for historical reasons. + TYPE_DOUBLE = 1; + TYPE_FLOAT = 2; + // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if + // negative values are likely. + TYPE_INT64 = 3; + TYPE_UINT64 = 4; + // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if + // negative values are likely. + TYPE_INT32 = 5; + TYPE_FIXED64 = 6; + TYPE_FIXED32 = 7; + TYPE_BOOL = 8; + TYPE_STRING = 9; + // Tag-delimited aggregate. + // Group type is deprecated and not supported after google.protobuf. However, Proto3 + // implementations should still be able to parse the group wire format and + // treat group fields as unknown fields. In Editions, the group wire format + // can be enabled via the `message_encoding` feature. + TYPE_GROUP = 10; + TYPE_MESSAGE = 11; // Length-delimited aggregate. + + // New in version 2. + TYPE_BYTES = 12; + TYPE_UINT32 = 13; + TYPE_ENUM = 14; + TYPE_SFIXED32 = 15; + TYPE_SFIXED64 = 16; + TYPE_SINT32 = 17; // Uses ZigZag encoding. + TYPE_SINT64 = 18; // Uses ZigZag encoding. + } + + enum Label { + // 0 is reserved for errors + LABEL_OPTIONAL = 1; + LABEL_REPEATED = 3; + // The required label is only allowed in google.protobuf. In proto3 and Editions + // it's explicitly prohibited. In Editions, the `field_presence` feature + // can be used to get this behavior. + LABEL_REQUIRED = 2; + } + + optional string name = 1; + optional int32 number = 3; + optional Label label = 4; + + // If type_name is set, this need not be set. If both this and type_name + // are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP. + optional Type type = 5; + + // For message and enum types, this is the name of the type. If the name + // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping + // rules are used to find the type (i.e. first the nested types within this + // message are searched, then within the parent, on up to the root + // namespace). + optional string type_name = 6; + + // For extensions, this is the name of the type being extended. It is + // resolved in the same manner as type_name. + optional string extendee = 2; + + // For numeric types, contains the original text representation of the value. + // For booleans, "true" or "false". + // For strings, contains the default text contents (not escaped in any way). + // For bytes, contains the C escaped value. All bytes >= 128 are escaped. + optional string default_value = 7; + + // If set, gives the index of a oneof in the containing type's oneof_decl + // list. This field is a member of that oneof. + optional int32 oneof_index = 9; + + // JSON name of this field. The value is set by protocol compiler. If the + // user has set a "json_name" option on this field, that option's value + // will be used. Otherwise, it's deduced from the field's name by converting + // it to camelCase. + optional string json_name = 10; + + optional FieldOptions options = 8; + + // If true, this is a proto3 "optional". When a proto3 field is optional, it + // tracks presence regardless of field type. + // + // When proto3_optional is true, this field must belong to a oneof to signal + // to old proto3 clients that presence is tracked for this field. This oneof + // is known as a "synthetic" oneof, and this field must be its sole member + // (each proto3 optional field gets its own synthetic oneof). Synthetic oneofs + // exist in the descriptor only, and do not generate any API. Synthetic oneofs + // must be ordered after all "real" oneofs. + // + // For message fields, proto3_optional doesn't create any semantic change, + // since non-repeated message fields always track presence. However it still + // indicates the semantic detail of whether the user wrote "optional" or not. + // This can be useful for round-tripping the .proto file. For consistency we + // give message fields a synthetic oneof also, even though it is not required + // to track presence. This is especially important because the parser can't + // tell if a field is a message or an enum, so it must always create a + // synthetic oneof. + // + // Proto2 optional fields do not set this flag, because they already indicate + // optional with `LABEL_OPTIONAL`. + optional bool proto3_optional = 17; +} + +// Describes a oneof. +message OneofDescriptorProto { + optional string name = 1; + optional OneofOptions options = 2; +} + +// Describes an enum type. +message EnumDescriptorProto { + optional string name = 1; + + repeated EnumValueDescriptorProto value = 2; + + optional EnumOptions options = 3; + + // Range of reserved numeric values. Reserved values may not be used by + // entries in the same enum. Reserved ranges may not overlap. + // + // Note that this is distinct from DescriptorProto.ReservedRange in that it + // is inclusive such that it can appropriately represent the entire int32 + // domain. + message EnumReservedRange { + optional int32 start = 1; // Inclusive. + optional int32 end = 2; // Inclusive. + } + + // Range of reserved numeric values. Reserved numeric values may not be used + // by enum values in the same enum declaration. Reserved ranges may not + // overlap. + repeated EnumReservedRange reserved_range = 4; + + // Reserved enum value names, which may not be reused. A given name may only + // be reserved once. + repeated string reserved_name = 5; +} + +// Describes a value within an enum. +message EnumValueDescriptorProto { + optional string name = 1; + optional int32 number = 2; + + optional EnumValueOptions options = 3; +} + +// Describes a service. +message ServiceDescriptorProto { + optional string name = 1; + repeated MethodDescriptorProto method = 2; + + optional ServiceOptions options = 3; +} + +// Describes a method of a service. +message MethodDescriptorProto { + optional string name = 1; + + // Input and output type names. These are resolved in the same way as + // FieldDescriptorProto.type_name, but must refer to a message type. + optional string input_type = 2; + optional string output_type = 3; + + optional MethodOptions options = 4; + + // Identifies if client streams multiple client messages + optional bool client_streaming = 5 [default = false]; + // Identifies if server streams multiple server messages + optional bool server_streaming = 6 [default = false]; +} + +// =================================================================== +// Options + +// Each of the definitions above may have "options" attached. These are +// just annotations which may cause code to be generated slightly differently +// or may contain hints for code that manipulates protocol messages. +// +// Clients may define custom options as extensions of the *Options messages. +// These extensions may not yet be known at parsing time, so the parser cannot +// store the values in them. Instead it stores them in a field in the *Options +// message called uninterpreted_option. This field must have the same name +// across all *Options messages. We then use this field to populate the +// extensions when we build a descriptor, at which point all protos have been +// parsed and so all extensions are known. +// +// Extension numbers for custom options may be chosen as follows: +// * For options which will only be used within a single application or +// organization, or for experimental options, use field numbers 50000 +// through 99999. It is up to you to ensure that you do not use the +// same number for multiple options. +// * For options which will be published and used publicly by multiple +// independent entities, e-mail protobuf-global-extension-registry@google.com +// to reserve extension numbers. Simply provide your project name (e.g. +// Objective-C plugin) and your project website (if available) -- there's no +// need to explain how you intend to use them. Usually you only need one +// extension number. You can declare multiple options with only one extension +// number by putting them in a sub-message. See the Custom Options section of +// the docs for examples: +// https://developers.google.com/protocol-buffers/docs/proto#options +// If this turns out to be popular, a web service will be set up +// to automatically assign option numbers. + +message FileOptions { + + // Sets the Java package where classes generated from this .proto will be + // placed. By default, the proto package is used, but this is often + // inappropriate because proto packages do not normally start with backwards + // domain names. + optional string java_package = 1; + + // Controls the name of the wrapper Java class generated for the .proto file. + // That class will always contain the .proto file's getDescriptor() method as + // well as any top-level extensions defined in the .proto file. + // If java_multiple_files is disabled, then all the other classes from the + // .proto file will be nested inside the single wrapper outer class. + optional string java_outer_classname = 8; + + // If enabled, then the Java code generator will generate a separate .java + // file for each top-level message, enum, and service defined in the .proto + // file. Thus, these types will *not* be nested inside the wrapper class + // named by java_outer_classname. However, the wrapper class will still be + // generated to contain the file's getDescriptor() method as well as any + // top-level extensions defined in the file. + optional bool java_multiple_files = 10 [default = false]; + + // This option does nothing. + optional bool java_generate_equals_and_hash = 20 [deprecated=true]; + + // A proto2 file can set this to true to opt in to UTF-8 checking for Java, + // which will throw an exception if invalid UTF-8 is parsed from the wire or + // assigned to a string field. + // + // TODO: clarify exactly what kinds of field types this option + // applies to, and update these docs accordingly. + // + // Proto3 files already perform these checks. Setting the option explicitly to + // false has no effect: it cannot be used to opt proto3 files out of UTF-8 + // checks. + optional bool java_string_check_utf8 = 27 [default = false]; + + // Generated classes can be optimized for speed or code size. + enum OptimizeMode { + SPEED = 1; // Generate complete code for parsing, serialization, + // etc. + CODE_SIZE = 2; // Use ReflectionOps to implement these methods. + LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. + } + optional OptimizeMode optimize_for = 9 [default = SPEED]; + + // Sets the Go package where structs generated from this .proto will be + // placed. If omitted, the Go package will be derived from the following: + // - The basename of the package import path, if provided. + // - Otherwise, the package statement in the .proto file, if present. + // - Otherwise, the basename of the .proto file, without extension. + optional string go_package = 11; + + // Should generic services be generated in each language? "Generic" services + // are not specific to any particular RPC system. They are generated by the + // main code generators in each language (without additional plugins). + // Generic services were the only kind of service generation supported by + // early versions of google.protobuf. + // + // Generic services are now considered deprecated in favor of using plugins + // that generate code specific to your particular RPC system. Therefore, + // these default to false. Old code which depends on generic services should + // explicitly set them to true. + optional bool cc_generic_services = 16 [default = false]; + optional bool java_generic_services = 17 [default = false]; + optional bool py_generic_services = 18 [default = false]; + reserved 42; // removed php_generic_services + reserved "php_generic_services"; + + // Is this file deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for everything in the file, or it will be completely ignored; in the very + // least, this is a formalization for deprecating files. + optional bool deprecated = 23 [default = false]; + + // Enables the use of arenas for the proto messages in this file. This applies + // only to generated classes for C++. + optional bool cc_enable_arenas = 31 [default = true]; + + // Sets the objective c class prefix which is prepended to all objective c + // generated classes from this .proto. There is no default. + optional string objc_class_prefix = 36; + + // Namespace for generated classes; defaults to the package. + optional string csharp_namespace = 37; + + // By default Swift generators will take the proto package and CamelCase it + // replacing '.' with underscore and use that to prefix the types/symbols + // defined. When this options is provided, they will use this value instead + // to prefix the types/symbols defined. + optional string swift_prefix = 39; + + // Sets the php class prefix which is prepended to all php generated classes + // from this .proto. Default is empty. + optional string php_class_prefix = 40; + + // Use this option to change the namespace of php generated classes. Default + // is empty. When this option is empty, the package name will be used for + // determining the namespace. + optional string php_namespace = 41; + + // Use this option to change the namespace of php generated metadata classes. + // Default is empty. When this option is empty, the proto file name will be + // used for determining the namespace. + optional string php_metadata_namespace = 44; + + // Use this option to change the package of ruby generated classes. Default + // is empty. When this option is not set, the package name will be used for + // determining the ruby package. + optional string ruby_package = 45; + + // Any features defined in the specific edition. + optional FeatureSet features = 50; + + // The parser stores options it doesn't recognize here. + // See the documentation for the "Options" section above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. + // See the documentation for the "Options" section above. + extensions 1000 to max; + + reserved 38; +} + +message MessageOptions { + // Set true to use the old proto1 MessageSet wire format for extensions. + // This is provided for backwards-compatibility with the MessageSet wire + // format. You should not use this for any other reason: It's less + // efficient, has fewer features, and is more complicated. + // + // The message must be defined exactly as follows: + // message Foo { + // option message_set_wire_format = true; + // extensions 4 to max; + // } + // Note that the message cannot have any defined fields; MessageSets only + // have extensions. + // + // All extensions of your type must be singular messages; e.g. they cannot + // be int32s, enums, or repeated messages. + // + // Because this is an option, the above two restrictions are not enforced by + // the protocol compiler. + optional bool message_set_wire_format = 1 [default = false]; + + // Disables the generation of the standard "descriptor()" accessor, which can + // conflict with a field of the same name. This is meant to make migration + // from proto1 easier; new code should avoid fields named "descriptor". + optional bool no_standard_descriptor_accessor = 2 [default = false]; + + // Is this message deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the message, or it will be completely ignored; in the very least, + // this is a formalization for deprecating messages. + optional bool deprecated = 3 [default = false]; + + reserved 4, 5, 6; + + // Whether the message is an automatically generated map entry type for the + // maps field. + // + // For maps fields: + // map map_field = 1; + // The parsed descriptor looks like: + // message MapFieldEntry { + // option map_entry = true; + // optional KeyType key = 1; + // optional ValueType value = 2; + // } + // repeated MapFieldEntry map_field = 1; + // + // Implementations may choose not to generate the map_entry=true message, but + // use a native map in the target language to hold the keys and values. + // The reflection APIs in such implementations still need to work as + // if the field is a repeated message field. + // + // NOTE: Do not set the option in .proto files. Always use the maps syntax + // instead. The option should only be implicitly set by the proto compiler + // parser. + optional bool map_entry = 7; + + reserved 8; // javalite_serializable + reserved 9; // javanano_as_lite + + // Enable the legacy handling of JSON field name conflicts. This lowercases + // and strips underscored from the fields before comparison in proto3 only. + // The new behavior takes `json_name` into account and applies to proto2 as + // well. + // + // This should only be used as a temporary measure against broken builds due + // to the change in behavior for JSON field name conflicts. + // + // TODO This is legacy behavior we plan to remove once downstream + // teams have had time to migrate. + optional bool deprecated_legacy_json_field_conflicts = 11 [deprecated = true]; + + // Any features defined in the specific edition. + optional FeatureSet features = 12; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message FieldOptions { + // NOTE: ctype is deprecated. Use `features.(pb.cpp).string_type` instead. + // The ctype option instructs the C++ code generator to use a different + // representation of the field than it normally would. See the specific + // options below. This option is only implemented to support use of + // [ctype=CORD] and [ctype=STRING] (the default) on non-repeated fields of + // type "bytes" in the open source release. + // TODO: make ctype actually deprecated. + optional CType ctype = 1 [/*deprecated = true,*/ default = STRING]; + enum CType { + // Default mode. + STRING = 0; + + // The option [ctype=CORD] may be applied to a non-repeated field of type + // "bytes". It indicates that in C++, the data should be stored in a Cord + // instead of a string. For very large strings, this may reduce memory + // fragmentation. It may also allow better performance when parsing from a + // Cord, or when parsing with aliasing enabled, as the parsed Cord may then + // alias the original buffer. + CORD = 1; + + STRING_PIECE = 2; + } + // The packed option can be enabled for repeated primitive fields to enable + // a more efficient representation on the wire. Rather than repeatedly + // writing the tag and type for each element, the entire array is encoded as + // a single length-delimited blob. In proto3, only explicit setting it to + // false will avoid using packed encoding. This option is prohibited in + // Editions, but the `repeated_field_encoding` feature can be used to control + // the behavior. + optional bool packed = 2; + + // The jstype option determines the JavaScript type used for values of the + // field. The option is permitted only for 64 bit integral and fixed types + // (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING + // is represented as JavaScript string, which avoids loss of precision that + // can happen when a large value is converted to a floating point JavaScript. + // Specifying JS_NUMBER for the jstype causes the generated JavaScript code to + // use the JavaScript "number" type. The behavior of the default option + // JS_NORMAL is implementation dependent. + // + // This option is an enum to permit additional types to be added, e.g. + // goog.math.Integer. + optional JSType jstype = 6 [default = JS_NORMAL]; + enum JSType { + // Use the default type. + JS_NORMAL = 0; + + // Use JavaScript strings. + JS_STRING = 1; + + // Use JavaScript numbers. + JS_NUMBER = 2; + } + + // Should this field be parsed lazily? Lazy applies only to message-type + // fields. It means that when the outer message is initially parsed, the + // inner message's contents will not be parsed but instead stored in encoded + // form. The inner message will actually be parsed when it is first accessed. + // + // This is only a hint. Implementations are free to choose whether to use + // eager or lazy parsing regardless of the value of this option. However, + // setting this option true suggests that the protocol author believes that + // using lazy parsing on this field is worth the additional bookkeeping + // overhead typically needed to implement it. + // + // This option does not affect the public interface of any generated code; + // all method signatures remain the same. Furthermore, thread-safety of the + // interface is not affected by this option; const methods remain safe to + // call from multiple threads concurrently, while non-const methods continue + // to require exclusive access. + // + // Note that lazy message fields are still eagerly verified to check + // ill-formed wireformat or missing required fields. Calling IsInitialized() + // on the outer message would fail if the inner message has missing required + // fields. Failed verification would result in parsing failure (except when + // uninitialized messages are acceptable). + optional bool lazy = 5 [default = false]; + + // unverified_lazy does no correctness checks on the byte stream. This should + // only be used where lazy with verification is prohibitive for performance + // reasons. + optional bool unverified_lazy = 15 [default = false]; + + // Is this field deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for accessors, or it will be completely ignored; in the very least, this + // is a formalization for deprecating fields. + optional bool deprecated = 3 [default = false]; + + // For Google-internal migration only. Do not use. + optional bool weak = 10 [default = false]; + + // Indicate that the field value should not be printed out when using debug + // formats, e.g. when the field contains sensitive credentials. + optional bool debug_redact = 16 [default = false]; + + // If set to RETENTION_SOURCE, the option will be omitted from the binary. + enum OptionRetention { + RETENTION_UNKNOWN = 0; + RETENTION_RUNTIME = 1; + RETENTION_SOURCE = 2; + } + + optional OptionRetention retention = 17; + + // This indicates the types of entities that the field may apply to when used + // as an option. If it is unset, then the field may be freely used as an + // option on any kind of entity. + enum OptionTargetType { + TARGET_TYPE_UNKNOWN = 0; + TARGET_TYPE_FILE = 1; + TARGET_TYPE_EXTENSION_RANGE = 2; + TARGET_TYPE_MESSAGE = 3; + TARGET_TYPE_FIELD = 4; + TARGET_TYPE_ONEOF = 5; + TARGET_TYPE_ENUM = 6; + TARGET_TYPE_ENUM_ENTRY = 7; + TARGET_TYPE_SERVICE = 8; + TARGET_TYPE_METHOD = 9; + } + + repeated OptionTargetType targets = 19; + + message EditionDefault { + optional Edition edition = 3; + optional string value = 2; // Textproto value. + } + repeated EditionDefault edition_defaults = 20; + + // Any features defined in the specific edition. + optional FeatureSet features = 21; + + // Information about the support window of a feature. + message FeatureSupport { + // The edition that this feature was first available in. In editions + // earlier than this one, the default assigned to EDITION_LEGACY will be + // used, and proto files will not be able to override it. + optional Edition edition_introduced = 1; + + // The edition this feature becomes deprecated in. Using this after this + // edition may trigger warnings. + optional Edition edition_deprecated = 2; + + // The deprecation warning text if this feature is used after the edition it + // was marked deprecated in. + optional string deprecation_warning = 3; + + // The edition this feature is no longer available in. In editions after + // this one, the last default assigned will be used, and proto files will + // not be able to override it. + optional Edition edition_removed = 4; + } + optional FeatureSupport feature_support = 22; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; + + reserved 4; // removed jtype + reserved 18; // reserve target, target_obsolete_do_not_use +} + +message OneofOptions { + // Any features defined in the specific edition. + optional FeatureSet features = 1; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumOptions { + + // Set this option to true to allow mapping different tag names to the same + // value. + optional bool allow_alias = 2; + + // Is this enum deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the enum, or it will be completely ignored; in the very least, this + // is a formalization for deprecating enums. + optional bool deprecated = 3 [default = false]; + + reserved 5; // javanano_as_lite + + // Enable the legacy handling of JSON field name conflicts. This lowercases + // and strips underscored from the fields before comparison in proto3 only. + // The new behavior takes `json_name` into account and applies to proto2 as + // well. + // TODO Remove this legacy behavior once downstream teams have + // had time to migrate. + optional bool deprecated_legacy_json_field_conflicts = 6 [deprecated = true]; + + // Any features defined in the specific edition. + optional FeatureSet features = 7; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumValueOptions { + // Is this enum value deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the enum value, or it will be completely ignored; in the very least, + // this is a formalization for deprecating enum values. + optional bool deprecated = 1 [default = false]; + + // Any features defined in the specific edition. + optional FeatureSet features = 2; + + // Indicate that fields annotated with this enum value should not be printed + // out when using debug formats, e.g. when the field contains sensitive + // credentials. + optional bool debug_redact = 3 [default = false]; + + // Information about the support window of a feature value. + optional FieldOptions.FeatureSupport feature_support = 4; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message ServiceOptions { + + // Any features defined in the specific edition. + optional FeatureSet features = 34; + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // Is this service deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the service, or it will be completely ignored; in the very least, + // this is a formalization for deprecating services. + optional bool deprecated = 33 [default = false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message MethodOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // Is this method deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the method, or it will be completely ignored; in the very least, + // this is a formalization for deprecating methods. + optional bool deprecated = 33 [default = false]; + + // Is this method side-effect-free (or safe in HTTP parlance), or idempotent, + // or neither? HTTP based RPC implementation may choose GET verb for safe + // methods, and PUT verb for idempotent methods instead of the default POST. + enum IdempotencyLevel { + IDEMPOTENCY_UNKNOWN = 0; + NO_SIDE_EFFECTS = 1; // implies idempotent + IDEMPOTENT = 2; // idempotent, but may have side effects + } + optional IdempotencyLevel idempotency_level = 34 + [default = IDEMPOTENCY_UNKNOWN]; + + // Any features defined in the specific edition. + optional FeatureSet features = 35; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +// A message representing a option the parser does not recognize. This only +// appears in options protos created by the compiler::Parser class. +// DescriptorPool resolves these when building Descriptor objects. Therefore, +// options protos in descriptor objects (e.g. returned by Descriptor::options(), +// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions +// in them. +message UninterpretedOption { + // The name of the uninterpreted option. Each string represents a segment in + // a dot-separated name. is_extension is true iff a segment represents an + // extension (denoted with parentheses in options specs in .proto files). + // E.g.,{ ["foo", false], ["bar.baz", true], ["moo", false] } represents + // "foo.(bar.baz).moo". + message NamePart { + required string name_part = 1; + required bool is_extension = 2; + } + repeated NamePart name = 2; + + // The value of the uninterpreted option, in whatever type the tokenizer + // identified it as during parsing. Exactly one of these should be set. + optional string identifier_value = 3; + optional uint64 positive_int_value = 4; + optional int64 negative_int_value = 5; + optional double double_value = 6; + optional bytes string_value = 7; + optional string aggregate_value = 8; +} + +// =================================================================== +// Features + +// TODO Enums in C++ gencode (and potentially other languages) are +// not well scoped. This means that each of the feature enums below can clash +// with each other. The short names we've chosen maximize call-site +// readability, but leave us very open to this scenario. A future feature will +// be designed and implemented to handle this, hopefully before we ever hit a +// conflict here. +message FeatureSet { + enum FieldPresence { + FIELD_PRESENCE_UNKNOWN = 0; + EXPLICIT = 1; + IMPLICIT = 2; + LEGACY_REQUIRED = 3; + } + optional FieldPresence field_presence = 1 [ + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_FIELD, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2023, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "EXPLICIT" }, + edition_defaults = { edition: EDITION_PROTO3, value: "IMPLICIT" }, + edition_defaults = { edition: EDITION_2023, value: "EXPLICIT" } + ]; + + enum EnumType { + ENUM_TYPE_UNKNOWN = 0; + OPEN = 1; + CLOSED = 2; + } + optional EnumType enum_type = 2 [ + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_ENUM, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2023, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "CLOSED" }, + edition_defaults = { edition: EDITION_PROTO3, value: "OPEN" } + ]; + + enum RepeatedFieldEncoding { + REPEATED_FIELD_ENCODING_UNKNOWN = 0; + PACKED = 1; + EXPANDED = 2; + } + optional RepeatedFieldEncoding repeated_field_encoding = 3 [ + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_FIELD, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2023, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "EXPANDED" }, + edition_defaults = { edition: EDITION_PROTO3, value: "PACKED" } + ]; + + enum Utf8Validation { + UTF8_VALIDATION_UNKNOWN = 0; + VERIFY = 2; + NONE = 3; + reserved 1; + } + optional Utf8Validation utf8_validation = 4 [ + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_FIELD, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2023, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "NONE" }, + edition_defaults = { edition: EDITION_PROTO3, value: "VERIFY" } + ]; + + enum MessageEncoding { + MESSAGE_ENCODING_UNKNOWN = 0; + LENGTH_PREFIXED = 1; + DELIMITED = 2; + } + optional MessageEncoding message_encoding = 5 [ + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_FIELD, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2023, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "LENGTH_PREFIXED" } + ]; + + enum JsonFormat { + JSON_FORMAT_UNKNOWN = 0; + ALLOW = 1; + LEGACY_BEST_EFFORT = 2; + } + optional JsonFormat json_format = 6 [ + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_MESSAGE, + targets = TARGET_TYPE_ENUM, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2023, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "LEGACY_BEST_EFFORT" }, + edition_defaults = { edition: EDITION_PROTO3, value: "ALLOW" } + ]; + + reserved 999; + + extensions 1000 to 9994 [ + declaration = { + number: 1000, + full_name: ".pb.cpp", + type: ".pb.CppFeatures" + }, + declaration = { + number: 1001, + full_name: ".pb.java", + type: ".pb.JavaFeatures" + }, + declaration = { number: 1002, full_name: ".pb.go", type: ".pb.GoFeatures" }, + declaration = { + number: 9990, + full_name: ".pb.proto1", + type: ".pb.Proto1Features" + } + ]; + + extensions 9995 to 9999; // For internal testing + extensions 10000; // for https://github.com/bufbuild/protobuf-es +} + +// A compiled specification for the defaults of a set of features. These +// messages are generated from FeatureSet extensions and can be used to seed +// feature resolution. The resolution with this object becomes a simple search +// for the closest matching edition, followed by proto merges. +message FeatureSetDefaults { + // A map from every known edition with a unique set of defaults to its + // defaults. Not all editions may be contained here. For a given edition, + // the defaults at the closest matching edition ordered at or before it should + // be used. This field must be in strict ascending order by edition. + message FeatureSetEditionDefault { + optional Edition edition = 3; + + // Defaults of features that can be overridden in this edition. + optional FeatureSet overridable_features = 4; + + // Defaults of features that can't be overridden in this edition. + optional FeatureSet fixed_features = 5; + + reserved 1, 2; + reserved "features"; + } + repeated FeatureSetEditionDefault defaults = 1; + + // The minimum supported edition (inclusive) when this was constructed. + // Editions before this will not have defaults. + optional Edition minimum_edition = 4; + + // The maximum known edition (inclusive) when this was constructed. Editions + // after this will not have reliable defaults. + optional Edition maximum_edition = 5; +} + +// =================================================================== +// Optional source code info + +// Encapsulates information about the original source file from which a +// FileDescriptorProto was generated. +message SourceCodeInfo { + // A Location identifies a piece of source code in a .proto file which + // corresponds to a particular definition. This information is intended + // to be useful to IDEs, code indexers, documentation generators, and similar + // tools. + // + // For example, say we have a file like: + // message Foo { + // optional string foo = 1; + // } + // Let's look at just the field definition: + // optional string foo = 1; + // ^ ^^ ^^ ^ ^^^ + // a bc de f ghi + // We have the following locations: + // span path represents + // [a,i) [ 4, 0, 2, 0 ] The whole field definition. + // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). + // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). + // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). + // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). + // + // Notes: + // - A location may refer to a repeated field itself (i.e. not to any + // particular index within it). This is used whenever a set of elements are + // logically enclosed in a single code segment. For example, an entire + // extend block (possibly containing multiple extension definitions) will + // have an outer location whose path refers to the "extensions" repeated + // field without an index. + // - Multiple locations may have the same path. This happens when a single + // logical declaration is spread out across multiple places. The most + // obvious example is the "extend" block again -- there may be multiple + // extend blocks in the same scope, each of which will have the same path. + // - A location's span is not always a subset of its parent's span. For + // example, the "extendee" of an extension declaration appears at the + // beginning of the "extend" block and is shared by all extensions within + // the block. + // - Just because a location's span is a subset of some other location's span + // does not mean that it is a descendant. For example, a "group" defines + // both a type and a field in a single declaration. Thus, the locations + // corresponding to the type and field and their components will overlap. + // - Code which tries to interpret locations should probably be designed to + // ignore those that it doesn't understand, as more types of locations could + // be recorded in the future. + repeated Location location = 1; + message Location { + // Identifies which part of the FileDescriptorProto was defined at this + // location. + // + // Each element is a field number or an index. They form a path from + // the root FileDescriptorProto to the place where the definition appears. + // For example, this path: + // [ 4, 3, 2, 7, 1 ] + // refers to: + // file.message_type(3) // 4, 3 + // .field(7) // 2, 7 + // .name() // 1 + // This is because FileDescriptorProto.message_type has field number 4: + // repeated DescriptorProto message_type = 4; + // and DescriptorProto.field has field number 2: + // repeated FieldDescriptorProto field = 2; + // and FieldDescriptorProto.name has field number 1: + // optional string name = 1; + // + // Thus, the above path gives the location of a field name. If we removed + // the last element: + // [ 4, 3, 2, 7 ] + // this path refers to the whole field declaration (from the beginning + // of the label to the terminating semicolon). + repeated int32 path = 1 [packed = true]; + + // Always has exactly three or four elements: start line, start column, + // end line (optional, otherwise assumed same as start line), end column. + // These are packed into a single field for efficiency. Note that line + // and column numbers are zero-based -- typically you will want to add + // 1 to each before displaying to a user. + repeated int32 span = 2 [packed = true]; + + // If this SourceCodeInfo represents a complete declaration, these are any + // comments appearing before and after the declaration which appear to be + // attached to the declaration. + // + // A series of line comments appearing on consecutive lines, with no other + // tokens appearing on those lines, will be treated as a single comment. + // + // leading_detached_comments will keep paragraphs of comments that appear + // before (but not connected to) the current element. Each paragraph, + // separated by empty lines, will be one comment element in the repeated + // field. + // + // Only the comment content is provided; comment markers (e.g. //) are + // stripped out. For block comments, leading whitespace and an asterisk + // will be stripped from the beginning of each line other than the first. + // Newlines are included in the output. + // + // Examples: + // + // optional int32 foo = 1; // Comment attached to foo. + // // Comment attached to bar. + // optional int32 bar = 2; + // + // optional string baz = 3; + // // Comment attached to baz. + // // Another line attached to baz. + // + // // Comment attached to moo. + // // + // // Another line attached to moo. + // optional double moo = 4; + // + // // Detached comment for corge. This is not leading or trailing comments + // // to moo or corge because there are blank lines separating it from + // // both. + // + // // Detached comment for corge paragraph 2. + // + // optional string corge = 5; + // /* Block comment attached + // * to corge. Leading asterisks + // * will be removed. */ + // /* Block comment attached to + // * grault. */ + // optional int32 grault = 6; + // + // // ignored detached comments. + optional string leading_comments = 3; + optional string trailing_comments = 4; + repeated string leading_detached_comments = 6; + } + + // Extensions for tooling. + extensions 536000000 [declaration = { + number: 536000000 + type: ".buf.descriptor.v1.SourceCodeInfoExtension" + full_name: ".buf.descriptor.v1.buf_source_code_info_extension" + }]; +} + +// Describes the relationship between generated code and its original source +// file. A GeneratedCodeInfo message is associated with only one generated +// source file, but may contain references to different source .proto files. +message GeneratedCodeInfo { + // An Annotation connects some span of text in generated code to an element + // of its generating .proto file. + repeated Annotation annotation = 1; + message Annotation { + // Identifies the element in the original source .proto file. This field + // is formatted the same as SourceCodeInfo.Location.path. + repeated int32 path = 1 [packed = true]; + + // Identifies the filesystem path to the original source .proto. + optional string source_file = 2; + + // Identifies the starting offset in bytes in the generated code + // that relates to the identified object. + optional int32 begin = 3; + + // Identifies the ending offset in bytes in the generated code that + // relates to the identified object. The end offset should be one past + // the last relevant byte (so the length of the text = end - begin). + optional int32 end = 4; + + // Represents the identified object's effect on the element in the original + // .proto file. + enum Semantic { + // There is no effect or the effect is indescribable. + NONE = 0; + // The element is set or otherwise mutated. + SET = 1; + // An alias to the element is returned. + ALIAS = 2; + } + optional Semantic semantic = 5; + } +} \ No newline at end of file diff --git a/did_core/did_methods/did_cheqd/proto/google/protobuf/timestamp.proto b/did_core/did_methods/did_cheqd/proto/google/protobuf/timestamp.proto new file mode 100644 index 0000000000..d0698db680 --- /dev/null +++ b/did_core/did_methods/did_cheqd/proto/google/protobuf/timestamp.proto @@ -0,0 +1,144 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package google.protobuf; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/protobuf/types/known/timestamppb"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "TimestampProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; + +// A Timestamp represents a point in time independent of any time zone or local +// calendar, encoded as a count of seconds and fractions of seconds at +// nanosecond resolution. The count is relative to an epoch at UTC midnight on +// January 1, 1970, in the proleptic Gregorian calendar which extends the +// Gregorian calendar backwards to year one. +// +// All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap +// second table is needed for interpretation, using a [24-hour linear +// smear](https://developers.google.com/time/smear). +// +// The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By +// restricting to that range, we ensure that we can convert to and from [RFC +// 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. +// +// # Examples +// +// Example 1: Compute Timestamp from POSIX `time()`. +// +// Timestamp timestamp; +// timestamp.set_seconds(time(NULL)); +// timestamp.set_nanos(0); +// +// Example 2: Compute Timestamp from POSIX `gettimeofday()`. +// +// struct timeval tv; +// gettimeofday(&tv, NULL); +// +// Timestamp timestamp; +// timestamp.set_seconds(tv.tv_sec); +// timestamp.set_nanos(tv.tv_usec * 1000); +// +// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. +// +// FILETIME ft; +// GetSystemTimeAsFileTime(&ft); +// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; +// +// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z +// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. +// Timestamp timestamp; +// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); +// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); +// +// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. +// +// long millis = System.currentTimeMillis(); +// +// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) +// .setNanos((int) ((millis % 1000) * 1000000)).build(); +// +// Example 5: Compute Timestamp from Java `Instant.now()`. +// +// Instant now = Instant.now(); +// +// Timestamp timestamp = +// Timestamp.newBuilder().setSeconds(now.getEpochSecond()) +// .setNanos(now.getNano()).build(); +// +// Example 6: Compute Timestamp from current time in Python. +// +// timestamp = Timestamp() +// timestamp.GetCurrentTime() +// +// # JSON Mapping +// +// In JSON format, the Timestamp type is encoded as a string in the +// [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the +// format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" +// where {year} is always expressed using four digits while {month}, {day}, +// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional +// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), +// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone +// is required. A proto3 JSON serializer should always use UTC (as indicated by +// "Z") when printing the Timestamp type and a proto3 JSON parser should be +// able to accept both UTC and other timezones (as indicated by an offset). +// +// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past +// 01:30 UTC on January 15, 2017. +// +// In JavaScript, one can convert a Date object to this format using the +// standard +// [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) +// method. In Python, a standard `datetime.datetime` object can be converted +// to this format using +// [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with +// the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use +// the Joda Time's [`ISODateTimeFormat.dateTime()`]( +// http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime() +// ) to obtain a formatter capable of generating timestamps in this format. +// +message Timestamp { + // Represents seconds of UTC time since Unix epoch + // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to + // 9999-12-31T23:59:59Z inclusive. + int64 seconds = 1; + + // Non-negative fractions of a second at nanosecond resolution. Negative + // second values with fractions must still have non-negative nanos values + // that count forward in time. Must be from 0 to 999,999,999 + // inclusive. + int32 nanos = 2; +} \ No newline at end of file diff --git a/did_core/did_methods/did_cheqd/proto/greeter.proto b/did_core/did_methods/did_cheqd/proto/greeter.proto new file mode 100644 index 0000000000..7adcec0643 --- /dev/null +++ b/did_core/did_methods/did_cheqd/proto/greeter.proto @@ -0,0 +1,15 @@ +syntax = "proto3"; + +package greeter; + +service Greeter { + rpc SayHello (HelloRequest) returns (HelloResponse); +} + +message HelloRequest { + string name = 1; +} + +message HelloResponse { + string message = 1; +} diff --git a/did_core/did_methods/did_cheqd/src/error/mod.rs b/did_core/did_methods/did_cheqd/src/error/mod.rs index ce9f18bc80..83659b8c6c 100644 --- a/did_core/did_methods/did_cheqd/src/error/mod.rs +++ b/did_core/did_methods/did_cheqd/src/error/mod.rs @@ -1,10 +1,15 @@ +use parsing::ParsingErrorSource; use thiserror::Error; +pub mod parsing; + pub type DidCheqdResult = Result; #[derive(Error, Debug)] #[non_exhaustive] pub enum DidCheqdError { + #[error("Parsing error: {0}")] + ParsingError(#[from] ParsingErrorSource), #[error(transparent)] Other(#[from] Box), } diff --git a/did_core/did_methods/did_cheqd/src/error/parsing.rs b/did_core/did_methods/did_cheqd/src/error/parsing.rs new file mode 100644 index 0000000000..5b4a704c11 --- /dev/null +++ b/did_core/did_methods/did_cheqd/src/error/parsing.rs @@ -0,0 +1,40 @@ +use did_resolver::{did_doc::schema::types::uri::UriWrapperError, did_parser_nom}; +use thiserror::Error; + +use super::DidCheqdError; + +#[derive(Error, Debug)] +pub enum ParsingErrorSource { + #[error("DID document parsing error: {0}")] + DidDocumentParsingError(#[from] did_parser_nom::ParseError), + #[error("DID document parsing URI error: {0}")] + DidDocumentParsingUriError(#[from] UriWrapperError), + #[error("JSON parsing error: {0}")] + JsonError(#[from] serde_json::Error), + #[error("Invalid encoding: {0}")] + Utf8Error(#[from] std::string::FromUtf8Error), +} + +impl From for DidCheqdError { + fn from(error: did_parser_nom::ParseError) -> Self { + DidCheqdError::ParsingError(ParsingErrorSource::DidDocumentParsingError(error)) + } +} + +impl From for DidCheqdError { + fn from(error: UriWrapperError) -> Self { + DidCheqdError::ParsingError(ParsingErrorSource::DidDocumentParsingUriError(error)) + } +} + +impl From for DidCheqdError { + fn from(error: serde_json::Error) -> Self { + DidCheqdError::ParsingError(ParsingErrorSource::JsonError(error)) + } +} + +impl From for DidCheqdError { + fn from(error: std::string::FromUtf8Error) -> Self { + DidCheqdError::ParsingError(ParsingErrorSource::Utf8Error(error)) + } +} diff --git a/did_core/did_methods/did_cheqd/src/lib.rs b/did_core/did_methods/did_cheqd/src/lib.rs index bd1d464699..bbdc21ae3f 100644 --- a/did_core/did_methods/did_cheqd/src/lib.rs +++ b/did_core/did_methods/did_cheqd/src/lib.rs @@ -1,2 +1,3 @@ pub mod error; pub mod resolution; +pub mod proto; diff --git a/did_core/did_methods/did_cheqd/src/proto.rs b/did_core/did_methods/did_cheqd/src/proto.rs new file mode 100644 index 0000000000..386671f18f --- /dev/null +++ b/did_core/did_methods/did_cheqd/src/proto.rs @@ -0,0 +1,22 @@ +pub mod cheqd { + pub mod did { + pub mod v2 { + tonic::include_proto!("cheqd.did.v2"); + } + } + pub mod resource { + pub mod v2 { + tonic::include_proto!("cheqd.resource.v2"); + } + } +} + +pub mod cosmos { + pub mod base { + pub mod query { + pub mod v1beta1 { + tonic::include_proto!("cosmos.base.query.v1beta1"); + } + } + } +} diff --git a/did_core/did_methods/did_cheqd/src/resolution/mod.rs b/did_core/did_methods/did_cheqd/src/resolution/mod.rs index e755804162..a6972f6fd1 100644 --- a/did_core/did_methods/did_cheqd/src/resolution/mod.rs +++ b/did_core/did_methods/did_cheqd/src/resolution/mod.rs @@ -1 +1,2 @@ pub mod resolver; +pub mod transformer; diff --git a/did_core/did_methods/did_cheqd/src/resolution/resolver.rs b/did_core/did_methods/did_cheqd/src/resolution/resolver.rs index 0b59eeca24..bf3f42f7de 100644 --- a/did_core/did_methods/did_cheqd/src/resolution/resolver.rs +++ b/did_core/did_methods/did_cheqd/src/resolution/resolver.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use async_trait::async_trait; use did_resolver::{ did_doc::schema::did_doc::DidDocument, @@ -5,10 +7,68 @@ use did_resolver::{ error::GenericError, traits::resolvable::{resolution_output::DidResolutionOutput, DidResolvable}, }; +use tokio::sync::Mutex; +use tonic::transport::{Channel, Endpoint}; + +use crate::{ + error::DidCheqdResult, + proto::cheqd::{ + did::v2::{query_client::QueryClient as DidQueryClient, QueryDidDocRequest}, + resource::v2::query_client::QueryClient as ResourceQueryClient, + }, +}; + +const MAINNET_NAMESPACE: &str = "mainnet"; +const MAINNET_DEFAULT_GRPC: &str = "https://grpc.cheqd.net:443"; +const TESTNET_NAMESPACE: &str = "testnet"; +const TESTNET_DEFAULT_GRPC: &str = "https://rpc.cheqd.network:443"; + +pub struct DidCheqdResolverConfiguration { + networks: Vec, +} + +impl Default for DidCheqdResolverConfiguration { + fn default() -> Self { + Self { + networks: vec![ + NetworkConfiguration::mainnet(), + NetworkConfiguration::testnet(), + ], + } + } +} + +pub struct NetworkConfiguration { + grpc_url: String, + namespace: String, +} + +impl NetworkConfiguration { + pub fn mainnet() -> Self { + Self { + grpc_url: String::from(MAINNET_DEFAULT_GRPC), + namespace: String::from(MAINNET_NAMESPACE), + } + } -use crate::error::DidCheqdResult; + pub fn testnet() -> Self { + Self { + grpc_url: String::from(TESTNET_DEFAULT_GRPC), + namespace: String::from(TESTNET_NAMESPACE), + } + } +} -pub struct DidCheqdResolver; +#[derive(Clone)] +struct CheqdGrpcClient { + did: DidQueryClient, + _resources: ResourceQueryClient, +} + +pub struct DidCheqdResolver { + networks: Vec, + network_clients: Mutex>, +} #[async_trait] impl DidResolvable for DidCheqdResolver { @@ -25,7 +85,61 @@ impl DidResolvable for DidCheqdResolver { } impl DidCheqdResolver { - pub async fn resolve_did(&self, _did: &Did) -> DidCheqdResult { - todo!() + pub fn new(configuration: DidCheqdResolverConfiguration) -> Self { + Self { + networks: configuration.networks, + network_clients: Default::default(), + } + } + + /// lazily get the client, initializing if not already + async fn client_for_network(&self, network: &str) -> DidCheqdResult { + let mut lock = self.network_clients.lock().await; + if let Some(client) = lock.get(network) { + return Ok(client.clone()); + } + + let network_config = self + .networks + .iter() + .find(|n| n.namespace == network) + .unwrap(); // TODO + + // initialize new + let conn = Endpoint::new(network_config.grpc_url.clone()) + .unwrap() // TODO + .connect() + .await + .unwrap(); // TODO + + let did_client = DidQueryClient::new(conn.clone()); + let resource_client = ResourceQueryClient::new(conn); + + let client = CheqdGrpcClient { + did: did_client, + _resources: resource_client, + }; + + lock.insert(network.to_owned(), client.clone()); + + Ok(client) + } + + pub async fn resolve_did(&self, did: &Did) -> DidCheqdResult { + let network = did.namespace().unwrap_or(MAINNET_NAMESPACE); + let mut client = self.client_for_network(network).await.unwrap(); + // TODO - mainnet vs testnet + // TODO - return doc metadata + // TODO - doc versions + let did = did.did().to_owned(); + + let request = tonic::Request::new(QueryDidDocRequest { id: did }); + let response = client.did.did_doc(request).await.unwrap(); + + let query_response = response.into_inner(); + let query_doc_res = query_response.value.unwrap(); // TODO + let query_doc = query_doc_res.did_doc.unwrap(); // TODO + + DidDocument::try_from(query_doc) } } diff --git a/did_core/did_methods/did_cheqd/src/resolution/transformer.rs b/did_core/did_methods/did_cheqd/src/resolution/transformer.rs new file mode 100644 index 0000000000..99eb768067 --- /dev/null +++ b/did_core/did_methods/did_cheqd/src/resolution/transformer.rs @@ -0,0 +1,124 @@ +use std::str::FromStr; + +use did_resolver::{ + did_doc::schema::{ + did_doc::DidDocument, + types::uri::Uri, + utils::OneOrList, + verification_method::{PublicKeyField, VerificationMethod, VerificationMethodType}, + }, + did_parser_nom::Did, +}; +use serde_json::json; + +use crate::{ + error::DidCheqdError, + proto::cheqd::did::v2::{DidDoc as CheqdDidDoc, VerificationMethod as CheqdVerificationMethod}, +}; + +impl TryFrom for DidDocument { + type Error = DidCheqdError; + + fn try_from(value: CheqdDidDoc) -> Result { + let mut doc = DidDocument::new(value.id.parse()?); + doc.set_extra_field(String::from("@context"), json!(value.context)); + + let controller: Vec<_> = value + .controller + .into_iter() + .map(Did::parse) + .collect::>()?; + doc.set_controller(OneOrList::from(controller)); + + for vm in value.verification_method { + let vm = VerificationMethod::try_from(vm)?; + doc.add_verification_method(vm); + // TODO - would be nice to append relevant contexts too + } + + for vm_id in value.authentication { + doc.add_authentication_ref(vm_id.parse()?); + } + for vm_id in value.assertion_method { + doc.add_assertion_method_ref(vm_id.parse()?); + } + for vm_id in value.capability_invocation { + doc.add_capability_invocation_ref(vm_id.parse()?); + } + for vm_id in value.capability_delegation { + doc.add_capability_delegation_ref(vm_id.parse()?); + } + for vm_id in value.key_agreement { + doc.add_key_agreement_ref(vm_id.parse()?); + } + + let aka: Vec<_> = value + .also_known_as + .iter() + .map(|aka| Uri::from_str(aka)) + .collect::>()?; + doc.set_also_known_as(aka); + + Ok(doc) + } +} + +impl TryFrom for VerificationMethod { + type Error = DidCheqdError; + + fn try_from(value: CheqdVerificationMethod) -> Result { + let vm_type: VerificationMethodType = + serde_json::from_value(json!(value.verification_method_type))?; + + let vm_key_encoded = value.verification_material; + + let pk = match vm_type { + VerificationMethodType::Ed25519VerificationKey2020 => PublicKeyField::Multibase { + public_key_multibase: vm_key_encoded, + }, + VerificationMethodType::JsonWebKey2020 => PublicKeyField::Jwk { + public_key_jwk: serde_json::from_str(&vm_key_encoded)?, + }, + VerificationMethodType::Ed25519VerificationKey2018 => PublicKeyField::Base58 { + public_key_base58: vm_key_encoded, + }, + // https://w3c.github.io/vc-di-bbs/contexts/v1/ + VerificationMethodType::Bls12381G1Key2020 => PublicKeyField::Base58 { + public_key_base58: vm_key_encoded, + }, + // https://w3c.github.io/vc-di-bbs/contexts/v1/ + VerificationMethodType::Bls12381G2Key2020 => PublicKeyField::Base58 { + public_key_base58: vm_key_encoded, + }, + // https://ns.did.ai/suites/x25519-2019/v1/ + VerificationMethodType::X25519KeyAgreementKey2019 => PublicKeyField::Base58 { + public_key_base58: vm_key_encoded, + }, + // https://ns.did.ai/suites/x25519-2020/v1/ + VerificationMethodType::X25519KeyAgreementKey2020 => PublicKeyField::Multibase { + public_key_multibase: vm_key_encoded, + }, + // https://w3c.github.io/vc-data-integrity/contexts/multikey/v1.jsonld + VerificationMethodType::Multikey => PublicKeyField::Multibase { + public_key_multibase: vm_key_encoded, + }, + // cannot infer encoding type from vm type, as multiple are supported: https://ns.did.ai/suites/secp256k1-2019/v1/ + VerificationMethodType::EcdsaSecp256k1VerificationKey2019 => todo!(), + // not supported + VerificationMethodType::PgpVerificationKey2021 => todo!(), + // not supported + VerificationMethodType::RsaVerificationKey2018 => todo!(), + // cannot infer encoding type from vm type: https://identity.foundation/EcdsaSecp256k1RecoverySignature2020/lds-ecdsa-secp256k1-recovery2020-0.0.jsonld + VerificationMethodType::EcdsaSecp256k1RecoveryMethod2020 => todo!(), + }; + + let vm = VerificationMethod::builder() + .id(value.id.parse()?) + .verification_method_type(vm_type) + .controller(value.controller.parse()?) + .public_key(pk) + .build(); + + Ok(vm) + } +} diff --git a/did_core/did_methods/did_cheqd/tests/resolution.rs b/did_core/did_methods/did_cheqd/tests/resolution.rs new file mode 100644 index 0000000000..c31f0533fa --- /dev/null +++ b/did_core/did_methods/did_cheqd/tests/resolution.rs @@ -0,0 +1,13 @@ +use did_cheqd::resolution::resolver::{DidCheqdResolver, DidCheqdResolverConfiguration}; + +#[tokio::test] +async fn test_resolve_known_testnet_vector() { + // let did = "did:cheqd:testnet:BttdoaxtC5JkYJoLeGV8ny".parse().unwrap(); + let did = "did:cheqd:mainnet:e536be60-880a-4d10-bd95-e84d13d7db6d" + .parse() + .unwrap(); + dbg!(&did); + let resolver = DidCheqdResolver::new(DidCheqdResolverConfiguration::default()); + let doc = resolver.resolve_did(&did).await.unwrap(); + dbg!(doc); +} From b39bc4ce00bb21d5815b4f5fd254a4a38f8b3f11 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Mon, 25 Nov 2024 16:59:22 +1000 Subject: [PATCH 04/50] check in the proto types and have a standalone generator helper (rather than generate at build time) Signed-off-by: George Mulhearn --- Cargo.lock | 8 +- Cargo.toml | 1 + did_core/did_methods/did_cheqd/Cargo.toml | 7 +- did_core/did_methods/did_cheqd/README.md | 3 + did_core/did_methods/did_cheqd/build.rs | 12 - .../did_cheqd/cheqd_proto_gen/Cargo.toml | 11 + .../proto/cheqd/did/v2/diddoc.proto | 0 .../proto/cheqd/did/v2/query.proto | 0 .../proto/cheqd/resource/v2/query.proto | 0 .../proto/cheqd/resource/v2/resource.proto | 0 .../base/query/v1beta1/pagination.proto | 0 .../proto/gogoproto/gogo.proto | 0 .../proto/google/api/annotations.proto | 0 .../proto/google/api/http.proto | 0 .../proto/google/protobuf/descriptor.proto | 0 .../proto/google/protobuf/timestamp.proto | 0 .../did_cheqd/cheqd_proto_gen/src/main.rs | 16 + .../did_methods/did_cheqd/proto/greeter.proto | 15 - .../did_cheqd/src/proto/cheqd.did.v2.rs | 387 ++++++++++++++++++ .../did_cheqd/src/proto/cheqd.resource.v2.rs | 344 ++++++++++++++++ .../src/proto/cosmos.base.query.v1beta1.rs | 55 +++ .../did_cheqd/src/proto/google.api.rs | 360 ++++++++++++++++ .../did_cheqd/src/{proto.rs => proto/mod.rs} | 8 +- 23 files changed, 1193 insertions(+), 34 deletions(-) create mode 100644 did_core/did_methods/did_cheqd/README.md delete mode 100644 did_core/did_methods/did_cheqd/build.rs create mode 100644 did_core/did_methods/did_cheqd/cheqd_proto_gen/Cargo.toml rename did_core/did_methods/did_cheqd/{ => cheqd_proto_gen}/proto/cheqd/did/v2/diddoc.proto (100%) rename did_core/did_methods/did_cheqd/{ => cheqd_proto_gen}/proto/cheqd/did/v2/query.proto (100%) rename did_core/did_methods/did_cheqd/{ => cheqd_proto_gen}/proto/cheqd/resource/v2/query.proto (100%) rename did_core/did_methods/did_cheqd/{ => cheqd_proto_gen}/proto/cheqd/resource/v2/resource.proto (100%) rename did_core/did_methods/did_cheqd/{ => cheqd_proto_gen}/proto/cosmos/base/query/v1beta1/pagination.proto (100%) rename did_core/did_methods/did_cheqd/{ => cheqd_proto_gen}/proto/gogoproto/gogo.proto (100%) rename did_core/did_methods/did_cheqd/{ => cheqd_proto_gen}/proto/google/api/annotations.proto (100%) rename did_core/did_methods/did_cheqd/{ => cheqd_proto_gen}/proto/google/api/http.proto (100%) rename did_core/did_methods/did_cheqd/{ => cheqd_proto_gen}/proto/google/protobuf/descriptor.proto (100%) rename did_core/did_methods/did_cheqd/{ => cheqd_proto_gen}/proto/google/protobuf/timestamp.proto (100%) create mode 100644 did_core/did_methods/did_cheqd/cheqd_proto_gen/src/main.rs delete mode 100644 did_core/did_methods/did_cheqd/proto/greeter.proto create mode 100644 did_core/did_methods/did_cheqd/src/proto/cheqd.did.v2.rs create mode 100644 did_core/did_methods/did_cheqd/src/proto/cheqd.resource.v2.rs create mode 100644 did_core/did_methods/did_cheqd/src/proto/cosmos.base.query.v1beta1.rs create mode 100644 did_core/did_methods/did_cheqd/src/proto/google.api.rs rename did_core/did_methods/did_cheqd/src/{proto.rs => proto/mod.rs} (55%) diff --git a/Cargo.lock b/Cargo.lock index 2f6772686b..509641e36e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1328,6 +1328,13 @@ dependencies = [ "zeroize", ] +[[package]] +name = "cheqd_proto_gen" +version = "0.1.0" +dependencies = [ + "tonic-build", +] + [[package]] name = "chrono" version = "0.4.38" @@ -1917,7 +1924,6 @@ dependencies = [ "thiserror", "tokio", "tonic", - "tonic-build", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index b996c1766d..b53c85c997 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,7 @@ members = [ "misc/simple_message_relay", "misc/display_as_json", "did_core/did_methods/did_cheqd", + "did_core/did_methods/did_cheqd/cheqd_proto_gen", ] [workspace.package] diff --git a/did_core/did_methods/did_cheqd/Cargo.toml b/did_core/did_methods/did_cheqd/Cargo.toml index 819af9d16a..8c8569735c 100644 --- a/did_core/did_methods/did_cheqd/Cargo.toml +++ b/did_core/did_methods/did_cheqd/Cargo.toml @@ -6,6 +6,10 @@ license.workspace = true version = "0.1.0" edition = "2021" +[lib] +name = "did_cheqd" +path = "src/lib.rs" + [dependencies] did_resolver = { path = "../../did_resolver" } tonic = { version = "0.12.3", default-features = false, features = [ @@ -27,6 +31,3 @@ tokio = { version = "1.38.0", default-features = false, features = [ "macros", "rt", ] } - -[build-dependencies] -tonic-build = "0.12.3" diff --git a/did_core/did_methods/did_cheqd/README.md b/did_core/did_methods/did_cheqd/README.md new file mode 100644 index 0000000000..d68f4eff01 --- /dev/null +++ b/did_core/did_methods/did_cheqd/README.md @@ -0,0 +1,3 @@ +# DID Cheqd Resolver + +TODO - explain dev maintainence of generated protos \ No newline at end of file diff --git a/did_core/did_methods/did_cheqd/build.rs b/did_core/did_methods/did_cheqd/build.rs deleted file mode 100644 index 73dfbc9cf5..0000000000 --- a/did_core/did_methods/did_cheqd/build.rs +++ /dev/null @@ -1,12 +0,0 @@ -fn main() -> Result<(), Box> { - tonic_build::configure() - .build_server(false) - .compile_protos( - &[ - "proto/cheqd/did/v2/query.proto", - "proto/cheqd/resource/v2/query.proto", - ], - &["proto"], - )?; - Ok(()) -} diff --git a/did_core/did_methods/did_cheqd/cheqd_proto_gen/Cargo.toml b/did_core/did_methods/did_cheqd/cheqd_proto_gen/Cargo.toml new file mode 100644 index 0000000000..4efd515880 --- /dev/null +++ b/did_core/did_methods/did_cheqd/cheqd_proto_gen/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "cheqd_proto_gen" +version = "0.1.0" +edition = "2021" + +[[bin]] +name = "cheqd-proto-gen" +path = "src/main.rs" + +[dependencies] +tonic-build = "0.12.3" diff --git a/did_core/did_methods/did_cheqd/proto/cheqd/did/v2/diddoc.proto b/did_core/did_methods/did_cheqd/cheqd_proto_gen/proto/cheqd/did/v2/diddoc.proto similarity index 100% rename from did_core/did_methods/did_cheqd/proto/cheqd/did/v2/diddoc.proto rename to did_core/did_methods/did_cheqd/cheqd_proto_gen/proto/cheqd/did/v2/diddoc.proto diff --git a/did_core/did_methods/did_cheqd/proto/cheqd/did/v2/query.proto b/did_core/did_methods/did_cheqd/cheqd_proto_gen/proto/cheqd/did/v2/query.proto similarity index 100% rename from did_core/did_methods/did_cheqd/proto/cheqd/did/v2/query.proto rename to did_core/did_methods/did_cheqd/cheqd_proto_gen/proto/cheqd/did/v2/query.proto diff --git a/did_core/did_methods/did_cheqd/proto/cheqd/resource/v2/query.proto b/did_core/did_methods/did_cheqd/cheqd_proto_gen/proto/cheqd/resource/v2/query.proto similarity index 100% rename from did_core/did_methods/did_cheqd/proto/cheqd/resource/v2/query.proto rename to did_core/did_methods/did_cheqd/cheqd_proto_gen/proto/cheqd/resource/v2/query.proto diff --git a/did_core/did_methods/did_cheqd/proto/cheqd/resource/v2/resource.proto b/did_core/did_methods/did_cheqd/cheqd_proto_gen/proto/cheqd/resource/v2/resource.proto similarity index 100% rename from did_core/did_methods/did_cheqd/proto/cheqd/resource/v2/resource.proto rename to did_core/did_methods/did_cheqd/cheqd_proto_gen/proto/cheqd/resource/v2/resource.proto diff --git a/did_core/did_methods/did_cheqd/proto/cosmos/base/query/v1beta1/pagination.proto b/did_core/did_methods/did_cheqd/cheqd_proto_gen/proto/cosmos/base/query/v1beta1/pagination.proto similarity index 100% rename from did_core/did_methods/did_cheqd/proto/cosmos/base/query/v1beta1/pagination.proto rename to did_core/did_methods/did_cheqd/cheqd_proto_gen/proto/cosmos/base/query/v1beta1/pagination.proto diff --git a/did_core/did_methods/did_cheqd/proto/gogoproto/gogo.proto b/did_core/did_methods/did_cheqd/cheqd_proto_gen/proto/gogoproto/gogo.proto similarity index 100% rename from did_core/did_methods/did_cheqd/proto/gogoproto/gogo.proto rename to did_core/did_methods/did_cheqd/cheqd_proto_gen/proto/gogoproto/gogo.proto diff --git a/did_core/did_methods/did_cheqd/proto/google/api/annotations.proto b/did_core/did_methods/did_cheqd/cheqd_proto_gen/proto/google/api/annotations.proto similarity index 100% rename from did_core/did_methods/did_cheqd/proto/google/api/annotations.proto rename to did_core/did_methods/did_cheqd/cheqd_proto_gen/proto/google/api/annotations.proto diff --git a/did_core/did_methods/did_cheqd/proto/google/api/http.proto b/did_core/did_methods/did_cheqd/cheqd_proto_gen/proto/google/api/http.proto similarity index 100% rename from did_core/did_methods/did_cheqd/proto/google/api/http.proto rename to did_core/did_methods/did_cheqd/cheqd_proto_gen/proto/google/api/http.proto diff --git a/did_core/did_methods/did_cheqd/proto/google/protobuf/descriptor.proto b/did_core/did_methods/did_cheqd/cheqd_proto_gen/proto/google/protobuf/descriptor.proto similarity index 100% rename from did_core/did_methods/did_cheqd/proto/google/protobuf/descriptor.proto rename to did_core/did_methods/did_cheqd/cheqd_proto_gen/proto/google/protobuf/descriptor.proto diff --git a/did_core/did_methods/did_cheqd/proto/google/protobuf/timestamp.proto b/did_core/did_methods/did_cheqd/cheqd_proto_gen/proto/google/protobuf/timestamp.proto similarity index 100% rename from did_core/did_methods/did_cheqd/proto/google/protobuf/timestamp.proto rename to did_core/did_methods/did_cheqd/cheqd_proto_gen/proto/google/protobuf/timestamp.proto diff --git a/did_core/did_methods/did_cheqd/cheqd_proto_gen/src/main.rs b/did_core/did_methods/did_cheqd/cheqd_proto_gen/src/main.rs new file mode 100644 index 0000000000..0c2126a9c7 --- /dev/null +++ b/did_core/did_methods/did_cheqd/cheqd_proto_gen/src/main.rs @@ -0,0 +1,16 @@ +//! Binary for re-generating the cheqd proto types +fn main() -> Result<(), Box> { + let crate_dir = env!("CARGO_MANIFEST_DIR").to_string(); + + tonic_build::configure() + .build_server(false) + .out_dir(crate_dir.clone() + "/../src/proto") + .compile_protos( + &[ + crate_dir.clone() + "/proto/cheqd/did/v2/query.proto", + crate_dir.clone() + "/proto/cheqd/resource/v2/query.proto", + ], + &[crate_dir + "/proto"], + )?; + Ok(()) +} diff --git a/did_core/did_methods/did_cheqd/proto/greeter.proto b/did_core/did_methods/did_cheqd/proto/greeter.proto deleted file mode 100644 index 7adcec0643..0000000000 --- a/did_core/did_methods/did_cheqd/proto/greeter.proto +++ /dev/null @@ -1,15 +0,0 @@ -syntax = "proto3"; - -package greeter; - -service Greeter { - rpc SayHello (HelloRequest) returns (HelloResponse); -} - -message HelloRequest { - string name = 1; -} - -message HelloResponse { - string message = 1; -} diff --git a/did_core/did_methods/did_cheqd/src/proto/cheqd.did.v2.rs b/did_core/did_methods/did_cheqd/src/proto/cheqd.did.v2.rs new file mode 100644 index 0000000000..58e4eefc60 --- /dev/null +++ b/did_core/did_methods/did_cheqd/src/proto/cheqd.did.v2.rs @@ -0,0 +1,387 @@ +// This file is @generated by prost-build. +/// DidDoc defines a DID Document, as defined in the DID Core specification. +/// Documentation: +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DidDoc { + /// context is a list of URIs used to identify the context of the DID document. + /// Default: + #[prost(string, repeated, tag = "1")] + pub context: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// id is the DID of the DID document. + /// Format: did:cheqd:: + #[prost(string, tag = "2")] + pub id: ::prost::alloc::string::String, + /// controller is a list of DIDs that are allowed to control the DID document. + #[prost(string, repeated, tag = "3")] + pub controller: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// verificationMethod is a list of verification methods that can be used to + /// verify a digital signature or cryptographic proof. + #[prost(message, repeated, tag = "4")] + pub verification_method: ::prost::alloc::vec::Vec, + /// authentication is a list of verification methods that can be used to + /// authenticate as the DID subject. + #[prost(string, repeated, tag = "5")] + pub authentication: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// assertionMethod is a list of verification methods that can be used to + /// assert statements as the DID subject. + #[prost(string, repeated, tag = "6")] + pub assertion_method: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// capabilityInvocation is a list of verification methods that can be used to + /// invoke capabilities as the DID subject. + #[prost(string, repeated, tag = "7")] + pub capability_invocation: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// capabilityDelegation is a list of verification methods that can be used to + /// delegate capabilities as the DID subject. + #[prost(string, repeated, tag = "8")] + pub capability_delegation: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// keyAgreement is a list of verification methods that can be used to perform + /// key agreement as the DID subject. + #[prost(string, repeated, tag = "9")] + pub key_agreement: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// service is a list of services that can be used to interact with the DID subject. + #[prost(message, repeated, tag = "10")] + pub service: ::prost::alloc::vec::Vec, + /// alsoKnownAs is a list of DIDs that are known to refer to the same DID subject. + #[prost(string, repeated, tag = "11")] + pub also_known_as: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, +} +/// VerificationMethod defines a verification method, as defined in the DID Core specification. +/// Documentation: +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct VerificationMethod { + /// id is the unique identifier of the verification method. + /// Format: did:cheqd::# + #[prost(string, tag = "1")] + pub id: ::prost::alloc::string::String, + /// type is the type of the verification method. + /// Example: Ed25519VerificationKey2020 + #[prost(string, tag = "2")] + pub verification_method_type: ::prost::alloc::string::String, + /// controller is the DID of the controller of the verification method. + /// Format: did:cheqd:: + #[prost(string, tag = "3")] + pub controller: ::prost::alloc::string::String, + /// verification_material is the public key of the verification method. + /// Commonly used verification material types: publicJwk, publicKeyBase58, publicKeyMultibase + #[prost(string, tag = "4")] + pub verification_material: ::prost::alloc::string::String, +} +/// Service defines a service, as defined in the DID Core specification. +/// Documentation: +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Service { + /// id is the unique identifier of the service. + /// Format: did:cheqd::# + #[prost(string, tag = "1")] + pub id: ::prost::alloc::string::String, + /// type is the type of the service. + /// Example: LinkedResource + #[prost(string, tag = "2")] + pub service_type: ::prost::alloc::string::String, + /// serviceEndpoint is the endpoint of the service. + /// Example: + #[prost(string, repeated, tag = "3")] + pub service_endpoint: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, +} +/// DidDocWithMetadata defines a DID Document with metadata, as defined in the DID Core specification. +/// Contains the DID Document, as well as DID Document metadata. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DidDocWithMetadata { + /// didDocument is the DID Document. + #[prost(message, optional, tag = "1")] + pub did_doc: ::core::option::Option, + /// didDocumentMetadata is the DID Document metadata. + #[prost(message, optional, tag = "2")] + pub metadata: ::core::option::Option, +} +/// Metadata defines DID Document metadata, as defined in the DID Core specification. +/// Documentation: +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Metadata { + /// created is the timestamp of the creation of the DID Document. + /// Format: RFC3339 + /// Example: 2021-03-10T15:16:17Z + #[prost(message, optional, tag = "1")] + pub created: ::core::option::Option<::prost_types::Timestamp>, + /// updated is the timestamp of the last update of the DID Document. + /// Format: RFC3339 + /// Example: 2021-03-10T15:16:17Z + #[prost(message, optional, tag = "2")] + pub updated: ::core::option::Option<::prost_types::Timestamp>, + /// deactivated is a flag that indicates whether the DID Document is deactivated. + /// Default: false + #[prost(bool, tag = "3")] + pub deactivated: bool, + /// version_id is the version identifier of the DID Document. + /// Format: UUID + /// Example: 123e4567-e89b-12d3-a456-426655440000 + #[prost(string, tag = "4")] + pub version_id: ::prost::alloc::string::String, + /// next_version_id is the version identifier of the next version of the DID Document. + /// Format: UUID + /// Example: 123e4567-e89b-12d3-a456-426655440000 + #[prost(string, tag = "5")] + pub next_version_id: ::prost::alloc::string::String, + /// previous_version_id is the version identifier of the previous version of the DID Document. + /// Format: UUID + /// Example: 123e4567-e89b-12d3-a456-426655440000 + #[prost(string, tag = "6")] + pub previous_version_id: ::prost::alloc::string::String, +} +/// QueryDidDocRequest is the request type for the Query/DidDoc method +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryDidDocRequest { + /// DID unique identifier of the DID Document to fetch. + /// UUID-style DIDs as well as Indy-style DID are supported. + /// + /// Format: did:cheqd:: + /// + /// Examples: + /// - did:cheqd:mainnet:c82f2b02-bdab-4dd7-b833-3e143745d612 + /// - did:cheqd:testnet:wGHEXrZvJxR8vw5P3UWH1j + #[prost(string, tag = "1")] + pub id: ::prost::alloc::string::String, +} +/// QueryDidDocResponse is the response type for the Query/DidDoc method +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryDidDocResponse { + /// Successful resolution of the DID Document returns the following: + /// - did_doc is the latest version of the DID Document + /// - metadata is is the DID Document metadata associated with the latest version of the DID Document + #[prost(message, optional, tag = "1")] + pub value: ::core::option::Option, +} +/// QueryDidDocVersionRequest is the request type for the Query/DidDocVersion method +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryDidDocVersionRequest { + /// DID unique identifier of the DID Document to fetch. + /// UUID-style DIDs as well as Indy-style DID are supported. + /// + /// Format: did:cheqd:: + /// + /// Examples: + /// - did:cheqd:mainnet:c82f2b02-bdab-4dd7-b833-3e143745d612 + /// - did:cheqd:testnet:wGHEXrZvJxR8vw5P3UWH1j + #[prost(string, tag = "1")] + pub id: ::prost::alloc::string::String, + /// Unique version identifier of the DID Document to fetch. + /// Returns the specified version of the DID Document. + /// + /// Format: + /// + /// Example: 93f2573c-eca9-4098-96cb-a1ec676a29ed + #[prost(string, tag = "2")] + pub version: ::prost::alloc::string::String, +} +/// QueryDidDocVersionResponse is the response type for the Query/DidDocVersion method +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryDidDocVersionResponse { + /// Successful resolution of the DID Document returns the following: + /// - did_doc is the requested version of the DID Document + /// - metadata is DID Document metadata associated with the requested version of the DID Document + #[prost(message, optional, tag = "1")] + pub value: ::core::option::Option, +} +/// QueryAllDidDocVersionsMetadataRequest is the request type for the Query/AllDidDocVersionsMetadata method +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryAllDidDocVersionsMetadataRequest { + /// DID unique identifier of the DID Document to fetch version metadata. + /// UUID-style DIDs as well as Indy-style DID are supported. + /// + /// Format: did:cheqd:: + /// + /// Examples: + /// - did:cheqd:mainnet:c82f2b02-bdab-4dd7-b833-3e143745d612 + /// - did:cheqd:testnet:wGHEXrZvJxR8vw5P3UWH1j + #[prost(string, tag = "1")] + pub id: ::prost::alloc::string::String, + /// pagination defines an optional pagination for the request. + #[prost(message, optional, tag = "2")] + pub pagination: ::core::option::Option< + super::super::super::cosmos::base::query::v1beta1::PageRequest, + >, +} +/// QueryAllDidDocVersionsMetadataResponse is the response type for the Query/AllDidDocVersionsMetadata method +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryAllDidDocVersionsMetadataResponse { + /// versions is the list of all versions of the requested DID Document + #[prost(message, repeated, tag = "1")] + pub versions: ::prost::alloc::vec::Vec, + /// pagination defines the pagination in the response. + #[prost(message, optional, tag = "2")] + pub pagination: ::core::option::Option< + super::super::super::cosmos::base::query::v1beta1::PageResponse, + >, +} +/// Generated client implementations. +pub mod query_client { + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value, + )] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + /// Query defines the gRPC querier service for the DID module + #[derive(Debug, Clone)] + pub struct QueryClient { + inner: tonic::client::Grpc, + } + impl QueryClient { + /// Attempt to create a new client by connecting to a given endpoint. + pub async fn connect(dst: D) -> Result + where + D: TryInto, + D::Error: Into, + { + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(Self::new(conn)) + } + } + impl QueryClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + std::marker::Send + 'static, + ::Error: Into + std::marker::Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> QueryClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + std::marker::Send + std::marker::Sync, + { + QueryClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + /// Fetch latest version of a DID Document for a given DID + pub async fn did_doc( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cheqd.did.v2.Query/DidDoc", + ); + let mut req = request.into_request(); + req.extensions_mut().insert(GrpcMethod::new("cheqd.did.v2.Query", "DidDoc")); + self.inner.unary(req, path, codec).await + } + /// Fetch specific version of a DID Document for a given DID + pub async fn did_doc_version( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cheqd.did.v2.Query/DidDocVersion", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("cheqd.did.v2.Query", "DidDocVersion")); + self.inner.unary(req, path, codec).await + } + /// Fetch list of all versions of DID Documents for a given DID + pub async fn all_did_doc_versions_metadata( + &mut self, + request: impl tonic::IntoRequest< + super::QueryAllDidDocVersionsMetadataRequest, + >, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cheqd.did.v2.Query/AllDidDocVersionsMetadata", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("cheqd.did.v2.Query", "AllDidDocVersionsMetadata"), + ); + self.inner.unary(req, path, codec).await + } + } +} diff --git a/did_core/did_methods/did_cheqd/src/proto/cheqd.resource.v2.rs b/did_core/did_methods/did_cheqd/src/proto/cheqd.resource.v2.rs new file mode 100644 index 0000000000..52c1b7d2e2 --- /dev/null +++ b/did_core/did_methods/did_cheqd/src/proto/cheqd.resource.v2.rs @@ -0,0 +1,344 @@ +// This file is @generated by prost-build. +/// Resource stores the contents of a DID-Linked Resource +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Resource { + /// bytes is the raw data of the Resource + #[prost(bytes = "vec", tag = "1")] + pub data: ::prost::alloc::vec::Vec, +} +/// Metadata stores the metadata of a DID-Linked Resource +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Metadata { + /// collection_id is the ID of the collection that the Resource belongs to. Defined client-side. + /// This field is the unique identifier of the DID linked to this Resource + /// Format: + /// + /// Examples: + /// - c82f2b02-bdab-4dd7-b833-3e143745d612 + /// - wGHEXrZvJxR8vw5P3UWH1j + #[prost(string, tag = "1")] + pub collection_id: ::prost::alloc::string::String, + /// id is the ID of the Resource. Defined client-side. + /// This field is a unique identifier for this specific version of the Resource. + /// Format: + #[prost(string, tag = "2")] + pub id: ::prost::alloc::string::String, + /// name is a human-readable name for the Resource. Defined client-side. + /// Does not change between different versions. + /// Example: PassportSchema, EducationTrustRegistry + #[prost(string, tag = "3")] + pub name: ::prost::alloc::string::String, + /// version is a human-readable semantic version for the Resource. Defined client-side. + /// Stored as a string. OPTIONAL. + /// Example: 1.0.0, v2.1.0 + #[prost(string, tag = "4")] + pub version: ::prost::alloc::string::String, + /// resource_type is a Resource type that identifies what the Resource is. Defined client-side. + /// This is NOT the same as the resource's media type. + /// Example: AnonCredsSchema, StatusList2021 + #[prost(string, tag = "5")] + pub resource_type: ::prost::alloc::string::String, + /// List of alternative URIs for the SAME Resource. + #[prost(message, repeated, tag = "6")] + pub also_known_as: ::prost::alloc::vec::Vec, + /// media_type is IANA media type of the Resource. Defined ledger-side. + /// Example: application/json, image/png + #[prost(string, tag = "7")] + pub media_type: ::prost::alloc::string::String, + /// created is the time at which the Resource was created. Defined ledger-side. + /// Format: RFC3339 + /// Example: 2021-01-01T00:00:00Z + #[prost(message, optional, tag = "8")] + pub created: ::core::option::Option<::prost_types::Timestamp>, + /// checksum is a SHA-256 checksum hash of the Resource. Defined ledger-side. + /// Example: d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f + #[prost(string, tag = "9")] + pub checksum: ::prost::alloc::string::String, + /// previous_version_id is the ID of the previous version of the Resource. Defined ledger-side. + /// This is based on the Resource's name and Resource type to determine whether it's the same Resource. + /// Format: + #[prost(string, tag = "10")] + pub previous_version_id: ::prost::alloc::string::String, + /// next_version_id is the ID of the next version of the Resource. Defined ledger-side. + /// This is based on the Resource's name and Resource type to determine whether it's the same Resource. + /// Format: + #[prost(string, tag = "11")] + pub next_version_id: ::prost::alloc::string::String, +} +/// AlternativeUri are alternative URIs that can be used to access the Resource. +/// By default, at least the DID URI equivalent of the Resource is populated. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct AlternativeUri { + /// uri is the URI of the Resource. + /// Examples: + /// - did:cheqd:testnet:MjYxNzYKMjYxNzYK/resources/4600ea35-8916-4ac4-b412-55b8f49dd94e + /// - + /// - + /// - + /// - ipfs://bafybeihetj2ng3d74k7t754atv2s5dk76pcqtvxls6dntef3xa6rax25xe + #[prost(string, tag = "1")] + pub uri: ::prost::alloc::string::String, + /// description is a human-readable description of the URI. Defined client-side. + /// Examples: + /// - did-uri + /// - http-uri + /// - ipfs-uri + #[prost(string, tag = "2")] + pub description: ::prost::alloc::string::String, +} +/// ResourceWithMetadata describes the overall structure of a DID-Linked Resource +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ResourceWithMetadata { + #[prost(message, optional, tag = "1")] + pub resource: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub metadata: ::core::option::Option, +} +/// QueryResourceRequest is the request type for the Query/Resource RPC method +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryResourceRequest { + /// collection_id is an identifier of the DidDocument the resource belongs to. + /// Format: + /// + /// Examples: + /// - c82f2b02-bdab-4dd7-b833-3e143745d612 + /// - wGHEXrZvJxR8vw5P3UWH1j + #[prost(string, tag = "1")] + pub collection_id: ::prost::alloc::string::String, + /// id is a unique id of the resource. + /// Format: + #[prost(string, tag = "2")] + pub id: ::prost::alloc::string::String, +} +/// QueryResourceResponse is the response type for the Query/Resource RPC method +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryResourceResponse { + /// Successful resolution of the resource returns the following: + /// - resource is the requested resource + /// - metadata is the resource metadata associated with the requested resource + #[prost(message, optional, tag = "1")] + pub resource: ::core::option::Option, +} +/// QueryResourceMetadataRequest is the request type for the Query/ResourceMetadata RPC method +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryResourceMetadataRequest { + /// collection_id is an identifier of the DidDocument the resource belongs to. + /// Format: + /// + /// Examples: + /// - c82f2b02-bdab-4dd7-b833-3e143745d612 + /// - wGHEXrZvJxR8vw5P3UWH1j + #[prost(string, tag = "1")] + pub collection_id: ::prost::alloc::string::String, + /// id is a unique id of the resource. + /// Format: + #[prost(string, tag = "2")] + pub id: ::prost::alloc::string::String, +} +/// QueryResourceMetadataResponse is the response type for the Query/ResourceMetadata RPC method +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryResourceMetadataResponse { + /// resource is the requested resource metadata + #[prost(message, optional, tag = "1")] + pub resource: ::core::option::Option, +} +/// QueryCollectionResourcesRequest is the request type for the Query/CollectionResources RPC method +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryCollectionResourcesRequest { + /// collection_id is an identifier of the DidDocument the resource belongs to. + /// Format: + /// + /// Examples: + /// - c82f2b02-bdab-4dd7-b833-3e143745d612 + /// - wGHEXrZvJxR8vw5P3UWH1j + #[prost(string, tag = "1")] + pub collection_id: ::prost::alloc::string::String, + /// pagination defines an optional pagination for the request. + #[prost(message, optional, tag = "2")] + pub pagination: ::core::option::Option< + super::super::super::cosmos::base::query::v1beta1::PageRequest, + >, +} +/// QueryCollectionResourcesResponse is the response type for the Query/CollectionResources RPC method +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryCollectionResourcesResponse { + /// resources is the requested collection of resource metadata + #[prost(message, repeated, tag = "1")] + pub resources: ::prost::alloc::vec::Vec, + /// pagination defines the pagination in the response. + #[prost(message, optional, tag = "2")] + pub pagination: ::core::option::Option< + super::super::super::cosmos::base::query::v1beta1::PageResponse, + >, +} +/// Generated client implementations. +pub mod query_client { + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value, + )] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + /// Query defines the gRPC querier service for the resource module + #[derive(Debug, Clone)] + pub struct QueryClient { + inner: tonic::client::Grpc, + } + impl QueryClient { + /// Attempt to create a new client by connecting to a given endpoint. + pub async fn connect(dst: D) -> Result + where + D: TryInto, + D::Error: Into, + { + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(Self::new(conn)) + } + } + impl QueryClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + std::marker::Send + 'static, + ::Error: Into + std::marker::Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> QueryClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + std::marker::Send + std::marker::Sync, + { + QueryClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + /// Fetch data/payload for a specific resource (without metadata) + pub async fn resource( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cheqd.resource.v2.Query/Resource", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("cheqd.resource.v2.Query", "Resource")); + self.inner.unary(req, path, codec).await + } + /// Fetch only metadata for a specific resource + pub async fn resource_metadata( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cheqd.resource.v2.Query/ResourceMetadata", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("cheqd.resource.v2.Query", "ResourceMetadata")); + self.inner.unary(req, path, codec).await + } + /// Fetch metadata for all resources in a collection + pub async fn collection_resources( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cheqd.resource.v2.Query/CollectionResources", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("cheqd.resource.v2.Query", "CollectionResources"), + ); + self.inner.unary(req, path, codec).await + } + } +} diff --git a/did_core/did_methods/did_cheqd/src/proto/cosmos.base.query.v1beta1.rs b/did_core/did_methods/did_cheqd/src/proto/cosmos.base.query.v1beta1.rs new file mode 100644 index 0000000000..22ce08b530 --- /dev/null +++ b/did_core/did_methods/did_cheqd/src/proto/cosmos.base.query.v1beta1.rs @@ -0,0 +1,55 @@ +// This file is @generated by prost-build. +/// PageRequest is to be embedded in gRPC request messages for efficient +/// pagination. Ex: +/// +/// message SomeRequest { +/// Foo some_parameter = 1; +/// PageRequest pagination = 2; +/// } +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PageRequest { + /// key is a value returned in PageResponse.next_key to begin + /// querying the next page most efficiently. Only one of offset or key + /// should be set. + #[prost(bytes = "vec", tag = "1")] + pub key: ::prost::alloc::vec::Vec, + /// offset is a numeric offset that can be used when key is unavailable. + /// It is less efficient than using key. Only one of offset or key should + /// be set. + #[prost(uint64, tag = "2")] + pub offset: u64, + /// limit is the total number of results to be returned in the result page. + /// If left empty it will default to a value to be set by each app. + #[prost(uint64, tag = "3")] + pub limit: u64, + /// count_total is set to true to indicate that the result set should include + /// a count of the total number of items available for pagination in UIs. + /// count_total is only respected when offset is used. It is ignored when key + /// is set. + #[prost(bool, tag = "4")] + pub count_total: bool, + /// reverse is set to true if results are to be returned in the descending order. + /// + /// Since: cosmos-sdk 0.43 + #[prost(bool, tag = "5")] + pub reverse: bool, +} +/// PageResponse is to be embedded in gRPC response messages where the +/// corresponding request message has used PageRequest. +/// +/// message SomeResponse { +/// repeated Bar results = 1; +/// PageResponse page = 2; +/// } +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PageResponse { + /// next_key is the key to be passed to PageRequest.key to + /// query the next page most efficiently. It will be empty if + /// there are no more results. + #[prost(bytes = "vec", tag = "1")] + pub next_key: ::prost::alloc::vec::Vec, + /// total is total number of results available if PageRequest.count_total + /// was set, its value is undefined otherwise + #[prost(uint64, tag = "2")] + pub total: u64, +} diff --git a/did_core/did_methods/did_cheqd/src/proto/google.api.rs b/did_core/did_methods/did_cheqd/src/proto/google.api.rs new file mode 100644 index 0000000000..635ce371a6 --- /dev/null +++ b/did_core/did_methods/did_cheqd/src/proto/google.api.rs @@ -0,0 +1,360 @@ +// This file is @generated by prost-build. +/// Defines the HTTP configuration for an API service. It contains a list of +/// [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method +/// to one or more HTTP REST API methods. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Http { + /// A list of HTTP configuration rules that apply to individual API methods. + /// + /// **NOTE:** All service configuration rules follow "last one wins" order. + #[prost(message, repeated, tag = "1")] + pub rules: ::prost::alloc::vec::Vec, + /// When set to true, URL path parameters will be fully URI-decoded except in + /// cases of single segment matches in reserved expansion, where "%2F" will be + /// left encoded. + /// + /// The default behavior is to not decode RFC 6570 reserved characters in multi + /// segment matches. + #[prost(bool, tag = "2")] + pub fully_decode_reserved_expansion: bool, +} +/// gRPC Transcoding +/// +/// gRPC Transcoding is a feature for mapping between a gRPC method and one or +/// more HTTP REST endpoints. It allows developers to build a single API service +/// that supports both gRPC APIs and REST APIs. Many systems, including [Google +/// APIs](), +/// [Cloud Endpoints](), [gRPC +/// Gateway](), +/// and [Envoy]() proxy support this feature +/// and use it for large scale production services. +/// +/// `HttpRule` defines the schema of the gRPC/REST mapping. The mapping specifies +/// how different portions of the gRPC request message are mapped to the URL +/// path, URL query parameters, and HTTP request body. It also controls how the +/// gRPC response message is mapped to the HTTP response body. `HttpRule` is +/// typically specified as an `google.api.http` annotation on the gRPC method. +/// +/// Each mapping specifies a URL path template and an HTTP method. The path +/// template may refer to one or more fields in the gRPC request message, as long +/// as each field is a non-repeated field with a primitive (non-message) type. +/// The path template controls how fields of the request message are mapped to +/// the URL path. +/// +/// Example: +/// +/// service Messaging { +/// rpc GetMessage(GetMessageRequest) returns (Message) { +/// option (google.api.http) = { +/// get: "/v1/{name=messages/*}" +/// }; +/// } +/// } +/// message GetMessageRequest { +/// string name = 1; // Mapped to URL path. +/// } +/// message Message { +/// string text = 1; // The resource content. +/// } +/// +/// This enables an HTTP REST to gRPC mapping as below: +/// +/// - HTTP: `GET /v1/messages/123456` +/// - gRPC: `GetMessage(name: "messages/123456")` +/// +/// Any fields in the request message which are not bound by the path template +/// automatically become HTTP query parameters if there is no HTTP request body. +/// For example: +/// +/// service Messaging { +/// rpc GetMessage(GetMessageRequest) returns (Message) { +/// option (google.api.http) = { +/// get:"/v1/messages/{message_id}" +/// }; +/// } +/// } +/// message GetMessageRequest { +/// message SubMessage { +/// string subfield = 1; +/// } +/// string message_id = 1; // Mapped to URL path. +/// int64 revision = 2; // Mapped to URL query parameter `revision`. +/// SubMessage sub = 3; // Mapped to URL query parameter `sub.subfield`. +/// } +/// +/// This enables a HTTP JSON to RPC mapping as below: +/// +/// - HTTP: `GET /v1/messages/123456?revision=2&sub.subfield=foo` +/// - gRPC: `GetMessage(message_id: "123456" revision: 2 sub: +/// SubMessage(subfield: "foo"))` +/// +/// Note that fields which are mapped to URL query parameters must have a +/// primitive type or a repeated primitive type or a non-repeated message type. +/// In the case of a repeated type, the parameter can be repeated in the URL +/// as `...?param=A¶m=B`. In the case of a message type, each field of the +/// message is mapped to a separate parameter, such as +/// `...?foo.a=A&foo.b=B&foo.c=C`. +/// +/// For HTTP methods that allow a request body, the `body` field +/// specifies the mapping. Consider a REST update method on the +/// message resource collection: +/// +/// service Messaging { +/// rpc UpdateMessage(UpdateMessageRequest) returns (Message) { +/// option (google.api.http) = { +/// patch: "/v1/messages/{message_id}" +/// body: "message" +/// }; +/// } +/// } +/// message UpdateMessageRequest { +/// string message_id = 1; // mapped to the URL +/// Message message = 2; // mapped to the body +/// } +/// +/// The following HTTP JSON to RPC mapping is enabled, where the +/// representation of the JSON in the request body is determined by +/// protos JSON encoding: +/// +/// - HTTP: `PATCH /v1/messages/123456 { "text": "Hi!" }` +/// - gRPC: `UpdateMessage(message_id: "123456" message { text: "Hi!" })` +/// +/// The special name `*` can be used in the body mapping to define that +/// every field not bound by the path template should be mapped to the +/// request body. This enables the following alternative definition of +/// the update method: +/// +/// service Messaging { +/// rpc UpdateMessage(Message) returns (Message) { +/// option (google.api.http) = { +/// patch: "/v1/messages/{message_id}" +/// body: "*" +/// }; +/// } +/// } +/// message Message { +/// string message_id = 1; +/// string text = 2; +/// } +/// +/// +/// The following HTTP JSON to RPC mapping is enabled: +/// +/// - HTTP: `PATCH /v1/messages/123456 { "text": "Hi!" }` +/// - gRPC: `UpdateMessage(message_id: "123456" text: "Hi!")` +/// +/// Note that when using `*` in the body mapping, it is not possible to +/// have HTTP parameters, as all fields not bound by the path end in +/// the body. This makes this option more rarely used in practice when +/// defining REST APIs. The common usage of `*` is in custom methods +/// which don't use the URL at all for transferring data. +/// +/// It is possible to define multiple HTTP methods for one RPC by using +/// the `additional_bindings` option. Example: +/// +/// service Messaging { +/// rpc GetMessage(GetMessageRequest) returns (Message) { +/// option (google.api.http) = { +/// get: "/v1/messages/{message_id}" +/// additional_bindings { +/// get: "/v1/users/{user_id}/messages/{message_id}" +/// } +/// }; +/// } +/// } +/// message GetMessageRequest { +/// string message_id = 1; +/// string user_id = 2; +/// } +/// +/// This enables the following two alternative HTTP JSON to RPC mappings: +/// +/// - HTTP: `GET /v1/messages/123456` +/// - gRPC: `GetMessage(message_id: "123456")` +/// +/// - HTTP: `GET /v1/users/me/messages/123456` +/// - gRPC: `GetMessage(user_id: "me" message_id: "123456")` +/// +/// Rules for HTTP mapping +/// +/// 1. Leaf request fields (recursive expansion nested messages in the request +/// message) are classified into three categories: +/// - Fields referred by the path template. They are passed via the URL path. +/// - Fields referred by the [HttpRule.body][google.api.HttpRule.body]. They +/// are passed via the HTTP +/// request body. +/// - All other fields are passed via the URL query parameters, and the +/// parameter name is the field path in the request message. A repeated +/// field can be represented as multiple query parameters under the same +/// name. +/// 2. If [HttpRule.body][google.api.HttpRule.body] is "*", there is no URL +/// query parameter, all fields +/// are passed via URL path and HTTP request body. +/// 3. If [HttpRule.body][google.api.HttpRule.body] is omitted, there is no HTTP +/// request body, all +/// fields are passed via URL path and URL query parameters. +/// +/// Path template syntax +/// +/// Template = "/" Segments \[ Verb \] ; +/// Segments = Segment { "/" Segment } ; +/// Segment = "*" | "**" | LITERAL | Variable ; +/// Variable = "{" FieldPath \[ "=" Segments \] "}" ; +/// FieldPath = IDENT { "." IDENT } ; +/// Verb = ":" LITERAL ; +/// +/// The syntax `*` matches a single URL path segment. The syntax `**` matches +/// zero or more URL path segments, which must be the last part of the URL path +/// except the `Verb`. +/// +/// The syntax `Variable` matches part of the URL path as specified by its +/// template. A variable template must not contain other variables. If a variable +/// matches a single path segment, its template may be omitted, e.g. `{var}` +/// is equivalent to `{var=*}`. +/// +/// The syntax `LITERAL` matches literal text in the URL path. If the `LITERAL` +/// contains any reserved character, such characters should be percent-encoded +/// before the matching. +/// +/// If a variable contains exactly one path segment, such as `"{var}"` or +/// `"{var=*}"`, when such a variable is expanded into a URL path on the client +/// side, all characters except `\[-_.~0-9a-zA-Z\]` are percent-encoded. The +/// server side does the reverse decoding. Such variables show up in the +/// [Discovery +/// Document]() as +/// `{var}`. +/// +/// If a variable contains multiple path segments, such as `"{var=foo/*}"` +/// or `"{var=**}"`, when such a variable is expanded into a URL path on the +/// client side, all characters except `\[-_.~/0-9a-zA-Z\]` are percent-encoded. +/// The server side does the reverse decoding, except "%2F" and "%2f" are left +/// unchanged. Such variables show up in the +/// [Discovery +/// Document]() as +/// `{+var}`. +/// +/// Using gRPC API Service Configuration +/// +/// gRPC API Service Configuration (service config) is a configuration language +/// for configuring a gRPC service to become a user-facing product. The +/// service config is simply the YAML representation of the `google.api.Service` +/// proto message. +/// +/// As an alternative to annotating your proto file, you can configure gRPC +/// transcoding in your service config YAML files. You do this by specifying a +/// `HttpRule` that maps the gRPC method to a REST endpoint, achieving the same +/// effect as the proto annotation. This can be particularly useful if you +/// have a proto that is reused in multiple services. Note that any transcoding +/// specified in the service config will override any matching transcoding +/// configuration in the proto. +/// +/// The following example selects a gRPC method and applies an `HttpRule` to it: +/// +/// http: +/// rules: +/// - selector: example.v1.Messaging.GetMessage +/// get: /v1/messages/{message_id}/{sub.subfield} +/// +/// Special notes +/// +/// When gRPC Transcoding is used to map a gRPC to JSON REST endpoints, the +/// proto to JSON conversion must follow the [proto3 +/// specification](). +/// +/// While the single segment variable follows the semantics of +/// [RFC 6570]() Section 3.2.2 Simple String +/// Expansion, the multi segment variable **does not** follow RFC 6570 Section +/// 3.2.3 Reserved Expansion. The reason is that the Reserved Expansion +/// does not expand special characters like `?` and `#`, which would lead +/// to invalid URLs. As the result, gRPC Transcoding uses a custom encoding +/// for multi segment variables. +/// +/// The path variables **must not** refer to any repeated or mapped field, +/// because client libraries are not capable of handling such variable expansion. +/// +/// The path variables **must not** capture the leading "/" character. The reason +/// is that the most common use case "{var}" does not capture the leading "/" +/// character. For consistency, all path variables must share the same behavior. +/// +/// Repeated message fields must not be mapped to URL query parameters, because +/// no client library can support such complicated mapping. +/// +/// If an API needs to use a JSON array for request or response body, it can map +/// the request or response body to a repeated field. However, some gRPC +/// Transcoding implementations may not support this feature. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct HttpRule { + /// Selects a method to which this rule applies. + /// + /// Refer to [selector][google.api.DocumentationRule.selector] for syntax + /// details. + #[prost(string, tag = "1")] + pub selector: ::prost::alloc::string::String, + /// The name of the request field whose value is mapped to the HTTP request + /// body, or `*` for mapping all request fields not captured by the path + /// pattern to the HTTP body, or omitted for not having any HTTP request body. + /// + /// NOTE: the referred field must be present at the top-level of the request + /// message type. + #[prost(string, tag = "7")] + pub body: ::prost::alloc::string::String, + /// Optional. The name of the response field whose value is mapped to the HTTP + /// response body. When omitted, the entire response message will be used + /// as the HTTP response body. + /// + /// NOTE: The referred field must be present at the top-level of the response + /// message type. + #[prost(string, tag = "12")] + pub response_body: ::prost::alloc::string::String, + /// Additional HTTP bindings for the selector. Nested bindings must + /// not contain an `additional_bindings` field themselves (that is, + /// the nesting may only be one level deep). + #[prost(message, repeated, tag = "11")] + pub additional_bindings: ::prost::alloc::vec::Vec, + /// Determines the URL pattern is matched by this rules. This pattern can be + /// used with any of the {get|put|post|delete|patch} methods. A custom method + /// can be defined using the 'custom' field. + #[prost(oneof = "http_rule::Pattern", tags = "2, 3, 4, 5, 6, 8")] + pub pattern: ::core::option::Option, +} +/// Nested message and enum types in `HttpRule`. +pub mod http_rule { + /// Determines the URL pattern is matched by this rules. This pattern can be + /// used with any of the {get|put|post|delete|patch} methods. A custom method + /// can be defined using the 'custom' field. + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Pattern { + /// Maps to HTTP GET. Used for listing and getting information about + /// resources. + #[prost(string, tag = "2")] + Get(::prost::alloc::string::String), + /// Maps to HTTP PUT. Used for replacing a resource. + #[prost(string, tag = "3")] + Put(::prost::alloc::string::String), + /// Maps to HTTP POST. Used for creating a resource or performing an action. + #[prost(string, tag = "4")] + Post(::prost::alloc::string::String), + /// Maps to HTTP DELETE. Used for deleting a resource. + #[prost(string, tag = "5")] + Delete(::prost::alloc::string::String), + /// Maps to HTTP PATCH. Used for updating a resource. + #[prost(string, tag = "6")] + Patch(::prost::alloc::string::String), + /// The custom pattern is used for specifying an HTTP method that is not + /// included in the `pattern` field, such as HEAD, or "*" to leave the + /// HTTP method unspecified for this rule. The wild-card rule is useful + /// for services that provide content to Web (HTML) clients. + #[prost(message, tag = "8")] + Custom(super::CustomHttpPattern), + } +} +/// A custom pattern is used for defining custom HTTP verb. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CustomHttpPattern { + /// The name of this custom HTTP verb. + #[prost(string, tag = "1")] + pub kind: ::prost::alloc::string::String, + /// The path matched by this custom verb. + #[prost(string, tag = "2")] + pub path: ::prost::alloc::string::String, +} diff --git a/did_core/did_methods/did_cheqd/src/proto.rs b/did_core/did_methods/did_cheqd/src/proto/mod.rs similarity index 55% rename from did_core/did_methods/did_cheqd/src/proto.rs rename to did_core/did_methods/did_cheqd/src/proto/mod.rs index 386671f18f..70748162f3 100644 --- a/did_core/did_methods/did_cheqd/src/proto.rs +++ b/did_core/did_methods/did_cheqd/src/proto/mod.rs @@ -1,12 +1,14 @@ +//! module structure wrapper over the generated proto types + pub mod cheqd { pub mod did { pub mod v2 { - tonic::include_proto!("cheqd.did.v2"); + include!("cheqd.did.v2.rs"); } } pub mod resource { pub mod v2 { - tonic::include_proto!("cheqd.resource.v2"); + include!("cheqd.resource.v2.rs"); } } } @@ -15,7 +17,7 @@ pub mod cosmos { pub mod base { pub mod query { pub mod v1beta1 { - tonic::include_proto!("cosmos.base.query.v1beta1"); + include!("cosmos.base.query.v1beta1.rs"); } } } From 8d0fd4fcfca7845a095f34645926135dbab42853 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Tue, 26 Nov 2024 08:32:32 +1000 Subject: [PATCH 05/50] regen lock Signed-off-by: George Mulhearn --- Cargo.lock | 1400 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 828 insertions(+), 572 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7c42380c1d..929f74f5a7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,9 +21,9 @@ dependencies = [ [[package]] name = "actix-http" -version = "3.8.0" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae682f693a9cd7b058f2b0b5d9a6d7728a8555779bedbbc35dd88528611d020" +checksum = "d48f96fc3003717aeb9856ca3d02a8c7de502667ad76eeacd830b48d2e91fac4" dependencies = [ "actix-codec", "actix-rt", @@ -65,7 +65,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] @@ -95,17 +95,17 @@ dependencies = [ [[package]] name = "actix-server" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b02303ce8d4e8be5b855af6cf3c3a08f3eff26880faad82bab679c22d3650cb5" +checksum = "7ca2549781d8dd6d75c40cf6b6051260a2cc2f3c62343d761a969a0640646894" dependencies = [ "actix-rt", "actix-service", "actix-utils", "futures-core", "futures-util", - "mio", - "socket2 0.5.7", + "mio 1.0.2", + "socket2", "tokio", "tracing", ] @@ -133,9 +133,9 @@ dependencies = [ [[package]] name = "actix-web" -version = "4.8.0" +version = "4.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1988c02af8d2b718c05bc4aeb6a66395b7cdf32858c2c71131e5637a8c05a9ff" +checksum = "9180d76e5cc7ccbc4d60a506f2c727730b154010262df5b910eb17dbe4b8cb38" dependencies = [ "actix-codec", "actix-http", @@ -155,6 +155,7 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", + "impl-more", "itoa", "language-tags", "log", @@ -167,7 +168,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "smallvec", - "socket2 0.5.7", + "socket2", "time 0.3.20", "url", ] @@ -181,23 +182,23 @@ dependencies = [ "actix-router", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] name = "addr2line" -version = "0.22.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "aead" @@ -273,9 +274,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.18" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" [[package]] name = "amcl" @@ -394,9 +395,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.14" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -409,43 +410,43 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.7" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.3" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] name = "arc-swap" @@ -473,7 +474,7 @@ checksum = "61df62c8f62c0f850805c2b65f85633cb2c0e334b1376ce98aaaf30616e4657e" dependencies = [ "askar-crypto", "askar-storage", - "async-lock 3.4.0", + "async-lock", "env_logger 0.10.2", "ffi-support", "log", @@ -516,13 +517,13 @@ dependencies = [ "actix-web", "anoncreds_types", "aries-vcx-agent", - "clap 4.5.9", + "clap 4.5.21", "derive_more", "display_as_json", - "env_logger 0.11.3", + "env_logger 0.11.5", "log", "rand 0.8.5", - "reqwest 0.12.5", + "reqwest 0.12.9", "serde", "serde_derive", "serde_json", @@ -552,7 +553,7 @@ dependencies = [ "did_resolver_registry", "did_resolver_sov", "diddoc_legacy", - "env_logger 0.11.3", + "env_logger 0.11.5", "futures", "lazy_static", "log", @@ -731,15 +732,15 @@ checksum = "d9b82a5c62e62075c68e4504ecc281fccce88f4692df43d50194cbbf918179ee" dependencies = [ "arc-swap", "askar-crypto", - "async-lock 3.4.0", + "async-lock", "async-stream", "bs58", "chrono", "digest", - "futures-lite 2.3.0", + "futures-lite", "hex", "hmac", - "itertools", + "itertools 0.12.1", "log", "once_cell", "percent-encoding", @@ -790,14 +791,14 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7ebdfa2ebdab6b1760375fa7d6f382b9f486eac35fc994625a00e89280bdbb7" +checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" dependencies = [ "async-task", "concurrent-queue", - "fastrand 2.1.0", - "futures-lite 2.3.0", + "fastrand", + "futures-lite", "slab", ] @@ -809,59 +810,30 @@ checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" dependencies = [ "async-channel 2.3.1", "async-executor", - "async-io 2.3.3", - "async-lock 3.4.0", + "async-io", + "async-lock", "blocking", - "futures-lite 2.3.0", + "futures-lite", "once_cell", ] [[package]] name = "async-io" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" -dependencies = [ - "async-lock 2.8.0", - "autocfg", - "cfg-if", - "concurrent-queue", - "futures-lite 1.13.0", - "log", - "parking", - "polling 2.8.0", - "rustix 0.37.27", - "slab", - "socket2 0.4.10", - "waker-fn", -] - -[[package]] -name = "async-io" -version = "2.3.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6baa8f0178795da0e71bc42c9e5d13261aac7ee549853162e66a241ba17964" +checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059" dependencies = [ - "async-lock 3.4.0", + "async-lock", "cfg-if", "concurrent-queue", "futures-io", - "futures-lite 2.3.0", + "futures-lite", "parking", - "polling 3.7.2", - "rustix 0.38.34", + "polling", + "rustix", "slab", "tracing", - "windows-sys 0.52.0", -] - -[[package]] -name = "async-lock" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" -dependencies = [ - "event-listener 2.5.3", + "windows-sys 0.59.0", ] [[package]] @@ -877,20 +849,20 @@ dependencies = [ [[package]] name = "async-std" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" +checksum = "c634475f29802fde2b8f0b505b1bd00dfe4df7d4a000f0b36f7671197d5c3615" dependencies = [ "async-attributes", "async-channel 1.9.0", "async-global-executor", - "async-io 1.13.0", - "async-lock 2.8.0", + "async-io", + "async-lock", "crossbeam-utils", "futures-channel", "futures-core", "futures-io", - "futures-lite 1.13.0", + "futures-lite", "gloo-timers", "kv-log-macro", "log", @@ -904,9 +876,9 @@ dependencies = [ [[package]] name = "async-stream" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" dependencies = [ "async-stream-impl", "futures-core", @@ -915,13 +887,13 @@ dependencies = [ [[package]] name = "async-stream-impl" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] @@ -932,13 +904,13 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.81" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] @@ -969,15 +941,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "axum" -version = "0.7.5" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" +checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" dependencies = [ "async-trait", "axum-core", @@ -986,7 +958,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.1", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.1", "hyper-util", "itoa", "matchit", @@ -999,9 +971,9 @@ dependencies = [ "serde_json", "serde_path_to_error", "serde_urlencoded", - "sync_wrapper 1.0.1", + "sync_wrapper 1.0.2", "tokio", - "tower", + "tower 0.5.1", "tower-layer", "tower-service", "tracing", @@ -1009,9 +981,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" dependencies = [ "async-trait", "bytes", @@ -1022,7 +994,7 @@ dependencies = [ "mime", "pin-project-lite", "rustversion", - "sync_wrapper 0.1.2", + "sync_wrapper 1.0.2", "tower-layer", "tower-service", "tracing", @@ -1030,29 +1002,28 @@ dependencies = [ [[package]] name = "axum-macros" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00c055ee2d014ae5981ce1016374e8213682aa14d9bf40e48ab48b5f3ef20eaa" +checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce" dependencies = [ - "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -1173,7 +1144,7 @@ dependencies = [ "async-channel 2.3.1", "async-task", "futures-io", - "futures-lite 2.3.0", + "futures-lite", "piper", ] @@ -1240,18 +1211,18 @@ checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "bytestring" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d80203ea6b29df88012294f62733de21cfeab47f17b41af3a38bc30a03ee72" +checksum = "e465647ae23b2823b0753f50decb2d5a86d2bb2cac04788fafd1f80e45378e5f" dependencies = [ "bytes", ] [[package]] name = "camino" -version = "1.1.7" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" dependencies = [ "serde", ] @@ -1290,12 +1261,13 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.6" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aba8f4e9906c7ce3c73463f62a7f0c65183ada1a2d47e397cc8810827f9694f" +checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" dependencies = [ "jobserver", "libc", + "shlex", ] [[package]] @@ -1380,23 +1352,23 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.9" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64acc1846d54c1fe936a78dc189c34e28d3f5afc348403f28ecf53660b9b8462" +checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" dependencies = [ "clap_builder", - "clap_derive 4.5.8", + "clap_derive 4.5.18", ] [[package]] name = "clap_builder" -version = "4.5.9" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8393d67ba2e7bfaf28a23458e4e2b543cc73a99595511eb207fdb8aede942" +checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" dependencies = [ "anstream", "anstyle", - "clap_lex 0.7.1", + "clap_lex 0.7.3", "strsim 0.11.1", ] @@ -1415,14 +1387,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.8" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] @@ -1436,9 +1408,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" +checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" [[package]] name = "client-tui" @@ -1451,25 +1423,25 @@ dependencies = [ "log", "mediator", "messages", - "reqwest 0.12.5", + "reqwest 0.12.9", "serde_json", "tokio", ] [[package]] name = "cmake" -version = "0.1.50" +version = "0.1.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" +checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a" dependencies = [ "cc", ] [[package]] name = "colorchoice" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "concurrent-queue" @@ -1550,9 +1522,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" dependencies = [ "libc", ] @@ -1623,7 +1595,7 @@ dependencies = [ "bitflags 1.3.2", "crossterm_winapi", "libc", - "mio", + "mio 0.8.11", "parking_lot 0.12.3", "signal-hook", "signal-hook-mio", @@ -1766,7 +1738,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] @@ -1814,7 +1786,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] @@ -1836,7 +1808,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core 0.20.10", "quote", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] @@ -1878,33 +1850,33 @@ dependencies = [ [[package]] name = "derive_builder" -version = "0.20.0" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0350b5cb0331628a5916d6c5c0b72e97393b8b6b03b47a9284f4e7f5a405ffd7" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" dependencies = [ "derive_builder_macro", ] [[package]] name = "derive_builder_core" -version = "0.20.0" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d48cda787f839151732d396ac69e3473923d54312c070ee21e9effcaa8ca0b1d" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" dependencies = [ "darling 0.20.10", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] name = "derive_builder_macro" -version = "0.20.0" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] @@ -1917,7 +1889,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] @@ -1944,7 +1916,7 @@ dependencies = [ "did_key", "did_parser_nom", "display_as_json", - "env_logger 0.11.3", + "env_logger 0.11.5", "hex", "log", "multibase", @@ -1974,7 +1946,7 @@ dependencies = [ name = "did_parser_nom" version = "0.1.0" dependencies = [ - "env_logger 0.11.3", + "env_logger 0.11.5", "log", "nom", "serde", @@ -1992,7 +1964,7 @@ dependencies = [ "did_parser_nom", "did_resolver", "display_as_json", - "env_logger 0.11.3", + "env_logger 0.11.5", "log", "multibase", "once_cell", @@ -2061,7 +2033,7 @@ version = "0.1.0" dependencies = [ "async-trait", "did_resolver", - "hyper 0.14.30", + "hyper 0.14.31", "hyper-tls 0.5.0", "serde_json", "thiserror", @@ -2129,7 +2101,18 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "syn 2.0.72", + "syn 2.0.89", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", ] [[package]] @@ -2215,9 +2198,9 @@ dependencies = [ [[package]] name = "encoding_rs" -version = "0.8.34" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ "cfg-if", ] @@ -2239,7 +2222,7 @@ checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] @@ -2260,14 +2243,14 @@ dependencies = [ "darling 0.20.10", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] name = "env_filter" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" dependencies = [ "log", "regex", @@ -2301,9 +2284,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.3" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9" +checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" dependencies = [ "anstream", "anstyle", @@ -2409,23 +2392,14 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.109", - "synstructure", -] - -[[package]] -name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", + "synstructure 0.12.6", ] [[package]] name = "fastrand" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" [[package]] name = "ff" @@ -2461,9 +2435,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.30" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", "miniz_oxide", @@ -2471,9 +2445,9 @@ dependencies = [ [[package]] name = "flume" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" dependencies = [ "futures-core", "futures-sink", @@ -2486,6 +2460,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" + [[package]] name = "foreign-types" version = "0.3.2" @@ -2543,9 +2523,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -2558,9 +2538,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -2568,15 +2548,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -2597,32 +2577,17 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" -dependencies = [ - "fastrand 1.9.0", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] - -[[package]] -name = "futures-lite" -version = "2.3.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +checksum = "cef40d21ae2c515b51041df9ed313ed21e572df340ea58a922a0aefe7e8891a1" dependencies = [ - "fastrand 2.1.0", + "fastrand", "futures-core", "futures-io", "parking", @@ -2631,32 +2596,32 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -2726,9 +2691,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.29.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "glass_pumpkin" @@ -2752,9 +2717,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "gloo-timers" -version = "0.2.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" dependencies = [ "futures-channel", "futures-core", @@ -2796,7 +2761,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.2.6", + "indexmap 2.6.0", "slab", "tokio", "tokio-util", @@ -2805,9 +2770,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" +checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e" dependencies = [ "atomic-waker", "bytes", @@ -2815,7 +2780,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.1.0", - "indexmap 2.2.6", + "indexmap 2.6.0", "slab", "tokio", "tokio-util", @@ -2844,6 +2809,17 @@ dependencies = [ "allocator-api2", ] +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + [[package]] name = "hashlink" version = "0.8.4" @@ -2980,9 +2956,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -2998,9 +2974,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.30" +version = "0.14.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" +checksum = "8c08302e8fa335b151b788c775ff56e7a03ae64ff85c548ee820fecb70356e85" dependencies = [ "bytes", "futures-channel", @@ -3013,7 +2989,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.5.7", + "socket2", "tokio", "tower-service", "tracing", @@ -3022,14 +2998,14 @@ dependencies = [ [[package]] name = "hyper" -version = "1.4.1" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "97818827ef4f364230e16705d4706e2897df2bb60617d6ca15d598025a3c481f" dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.5", + "h2 0.4.7", "http 1.1.0", "http-body 1.0.1", "httparse", @@ -3043,15 +3019,15 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.2" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ "futures-util", "http 1.1.0", - "hyper 1.4.1", + "hyper 1.5.1", "hyper-util", - "rustls 0.23.11", + "rustls 0.23.18", "rustls-pki-types", "tokio", "tokio-rustls", @@ -3064,7 +3040,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" dependencies = [ - "hyper 1.4.1", + "hyper 1.5.1", "hyper-util", "pin-project-lite", "tokio", @@ -3078,7 +3054,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", - "hyper 0.14.30", + "hyper 0.14.31", "native-tls", "tokio", "tokio-native-tls", @@ -3092,7 +3068,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.1", "hyper-util", "native-tls", "tokio", @@ -3111,9 +3087,9 @@ dependencies = [ "futures-util", "http 1.1.0", "http-body 1.0.1", - "hyper 1.4.1", + "hyper 1.5.1", "pin-project-lite", - "socket2 0.5.7", + "socket2", "tokio", "tower-service", "tracing", @@ -3121,9 +3097,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -3142,6 +3118,124 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -3150,14 +3244,31 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.5.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "idna_adapter", + "smallvec", + "utf8_iter", ] +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "impl-more" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aae21c3177a27788957044151cc2800043d127acaa460a47ebb9b84dfa2c6aa0" + [[package]] name = "indexmap" version = "1.9.3" @@ -3170,12 +3281,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.6" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown 0.15.2", ] [[package]] @@ -3394,39 +3505,28 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b33c9a5c599d67d051c4dc25eb1b6b4ef715d1763c20c85c688717a1734f204e" -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi 0.3.9", - "libc", - "windows-sys 0.48.0", -] - [[package]] name = "ipnet" -version = "2.9.0" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" [[package]] name = "is-terminal" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" dependencies = [ - "hermit-abi 0.3.9", + "hermit-abi 0.4.0", "libc", "windows-sys 0.52.0", ] [[package]] name = "is_terminal_polyfill" -version = "1.70.0" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "isolang" @@ -3446,35 +3546,44 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jobserver" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] [[package]] name = "k256" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" dependencies = [ "cfg-if", "ecdsa", @@ -3517,15 +3626,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.155" +version = "0.2.165" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "fcb4d3d38eab6c5239a362fa8bae48c03baf980a6e7079f063942d563ef3533e" [[package]] name = "libm" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "libredox" @@ -3586,15 +3695,15 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.3.8" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] -name = "linux-raw-sys" -version = "0.4.14" +name = "litemap" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" [[package]] name = "local-channel" @@ -3646,11 +3755,11 @@ dependencies = [ [[package]] name = "lru" -version = "0.12.3" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.14.5", + "hashbrown 0.15.2", ] [[package]] @@ -3698,11 +3807,11 @@ dependencies = [ "chrono", "diddoc_legacy", "dotenvy", - "env_logger 0.11.3", + "env_logger 0.11.5", "futures", "log", "messages", - "reqwest 0.12.5", + "reqwest 0.12.9", "serde", "serde_json", "sqlx", @@ -3751,7 +3860,7 @@ dependencies = [ "proc-macro2", "quote", "shared", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] @@ -3789,11 +3898,11 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.4" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", + "adler2", ] [[package]] @@ -3808,11 +3917,24 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "log", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.52.0", +] + [[package]] name = "mockall" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c28b3fb6d753d28c20e826cd46ee611fda1cf3cde03a443a974043247c065a" +checksum = "39a6bfcc6c8c7eed5ee98b9c3e33adc726054389233e201c95dab2d41a3839d2" dependencies = [ "cfg-if", "downcast", @@ -3824,14 +3946,14 @@ dependencies = [ [[package]] name = "mockall_derive" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "341014e7f530314e9a1fdbc7400b244efea7122662c96bfa248c31da5bfb2020" +checksum = "25ca3004c2efe9011bd4e461bd8256445052b9615405b4f7ea43fc8ca5c20898" dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] @@ -4010,18 +4132,18 @@ dependencies = [ [[package]] name = "object" -version = "0.36.1" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "opaque-debug" @@ -4031,9 +4153,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.66" +version = "0.10.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" dependencies = [ "bitflags 2.6.0", "cfg-if", @@ -4052,7 +4174,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] @@ -4063,9 +4185,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.103" +version = "0.9.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" dependencies = [ "cc", "libc", @@ -4126,9 +4248,9 @@ dependencies = [ [[package]] name = "parking" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" @@ -4173,7 +4295,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.3", + "redox_syscall 0.5.7", "smallvec", "windows-targets 0.52.6", ] @@ -4227,7 +4349,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.2.6", + "indexmap 2.6.0", ] [[package]] @@ -4250,29 +4372,29 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.5" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.5" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -4282,12 +4404,12 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "piper" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1d5c74c9876f070d3e8fd503d748c7d974c3e48da8f41350fa5222ef9b4391" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" dependencies = [ "atomic-waker", - "fastrand 2.1.0", + "fastrand", "futures-io", ] @@ -4314,9 +4436,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "plain" @@ -4326,33 +4448,17 @@ checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" [[package]] name = "polling" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" -dependencies = [ - "autocfg", - "bitflags 1.3.2", - "cfg-if", - "concurrent-queue", - "libc", - "log", - "pin-project-lite", - "windows-sys 0.48.0", -] - -[[package]] -name = "polling" -version = "3.7.2" +version = "3.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3ed00ed3fbf728b5816498ecd316d1716eecaced9c0c8d2c5a6740ca214985b" +checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" dependencies = [ "cfg-if", "concurrent-queue", "hermit-abi 0.4.0", "pin-project-lite", - "rustix 0.38.34", + "rustix", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -4380,15 +4486,18 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "predicates" -version = "3.1.0" +version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b87bfd4605926cdfefc1c3b5f8fe560e3feca9d5552cf68c466d3d8236c7e8" +checksum = "7e9086cc7640c29a356d1a29fd134380bee9d8f79a17410aa76e7ad295f42c97" dependencies = [ "anstyle", "predicates-core", @@ -4396,15 +4505,15 @@ dependencies = [ [[package]] name = "predicates-core" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" +checksum = "ae8177bee8e75d6846599c6b9ff679ed51e882816914eec639944d7c9aa11931" [[package]] name = "predicates-tree" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf" +checksum = "41b740d195ed3166cd147c8047ec98db0e22ec019eb8eeb76d343b795304fb13" dependencies = [ "predicates-core", "termtree", @@ -4412,9 +4521,9 @@ dependencies = [ [[package]] name = "pretty_assertions" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" dependencies = [ "diff", "yansi", @@ -4422,12 +4531,12 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.20" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" +checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" dependencies = [ "proc-macro2", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] @@ -4465,9 +4574,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -4490,7 +4599,7 @@ checksum = "0c1318b19085f08681016926435853bbf7858f9c082d0999b80550ff5d9abe15" dependencies = [ "bytes", "heck 0.5.0", - "itertools", + "itertools 0.13.0", "log", "multimap", "once_cell", @@ -4499,7 +4608,7 @@ dependencies = [ "prost", "prost-types", "regex", - "syn 2.0.72", + "syn 2.0.89", "tempfile", ] @@ -4510,10 +4619,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5" dependencies = [ "anyhow", - "itertools", + "itertools 0.13.0", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] @@ -4541,9 +4650,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -4636,27 +4745,18 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.5.3" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ "bitflags 2.6.0", ] [[package]] name = "redox_users" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom 0.2.15", "libredox", @@ -4665,14 +4765,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.5" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.7", - "regex-syntax 0.8.4", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", ] [[package]] @@ -4686,13 +4786,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.4", + "regex-syntax 0.8.5", ] [[package]] @@ -4709,9 +4809,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" @@ -4727,7 +4827,7 @@ dependencies = [ "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.30", + "hyper 0.14.31", "ipnet", "js-sys", "log", @@ -4739,21 +4839,21 @@ dependencies = [ "serde_json", "serde_urlencoded", "sync_wrapper 0.1.2", - "system-configuration", + "system-configuration 0.5.1", "tokio", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "winreg 0.50.0", + "winreg", ] [[package]] name = "reqwest" -version = "0.12.5" +version = "0.12.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" +checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" dependencies = [ "base64 0.22.1", "bytes", @@ -4761,11 +4861,11 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2 0.4.5", + "h2 0.4.7", "http 1.1.0", "http-body 1.0.1", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.1", "hyper-rustls", "hyper-tls 0.6.0", "hyper-util", @@ -4778,12 +4878,12 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls-pemfile 2.1.2", + "rustls-pemfile 2.2.0", "serde", "serde_json", "serde_urlencoded", - "sync_wrapper 1.0.1", - "system-configuration", + "sync_wrapper 1.0.2", + "system-configuration 0.6.1", "tokio", "tokio-native-tls", "tower-service", @@ -4791,7 +4891,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "winreg 0.52.0", + "windows-registry", ] [[package]] @@ -4869,37 +4969,23 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustix" -version = "0.37.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" -dependencies = [ - "bitflags 1.3.2", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys 0.3.8", - "windows-sys 0.48.0", -] - -[[package]] -name = "rustix" -version = "0.38.34" +version = "0.38.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" dependencies = [ "bitflags 2.6.0", "errno", "libc", - "linux-raw-sys 0.4.14", + "linux-raw-sys", "windows-sys 0.52.0", ] @@ -4916,15 +5002,15 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.11" +version = "0.23.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4828ea528154ae444e5a642dbb7d5623354030dc9822b83fd9bb79683c7399d0" +checksum = "9c9cc1d47e243d655ace55ed38201c19ae02c148ae56412ab8750e8f0166ab7f" dependencies = [ "log", "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.102.6", + "rustls-webpki 0.102.8", "subtle", "zeroize", ] @@ -4952,11 +5038,10 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ - "base64 0.22.1", "rustls-pki-types", ] @@ -4978,9 +5063,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.102.6" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring", "rustls-pki-types", @@ -4989,9 +5074,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "ryu" @@ -5010,11 +5095,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.23" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -5040,7 +5125,7 @@ checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] @@ -5113,9 +5198,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.204" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] @@ -5142,22 +5227,23 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.204" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] name = "serde_json" -version = "1.0.120" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -5174,9 +5260,9 @@ dependencies = [ [[package]] name = "serde_test" -version = "1.0.176" +version = "1.0.177" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a2f49ace1498612d14f7e0b8245519584db8299541dfe31a06374a828d620ab" +checksum = "7f901ee573cab6b3060453d2d5f0bae4e6d628c23c0a962ff9b5f1d7c8d4f1ed" dependencies = [ "serde", ] @@ -5242,12 +5328,18 @@ dependencies = [ "lazy_static", "log", "regex", - "reqwest 0.12.5", + "reqwest 0.12.9", "serde", "serde_json", "thiserror", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signal-hook" version = "0.3.17" @@ -5260,12 +5352,12 @@ dependencies = [ [[package]] name = "signal-hook-mio" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" +checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" dependencies = [ "libc", - "mio", + "mio 0.8.11", "signal-hook", ] @@ -5332,16 +5424,6 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" -[[package]] -name = "socket2" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "socket2" version = "0.5.7" @@ -5384,9 +5466,9 @@ dependencies = [ [[package]] name = "sqlformat" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f895e3734318cc55f1fe66258926c9b910c124d47520339efecbb6c59cec7c1f" +checksum = "7bba3a93db0cc4f7bdece8bb09e77e2e785c20bfebf79eb8340ed80708048790" dependencies = [ "nom", "unicode_categories", @@ -5427,7 +5509,7 @@ dependencies = [ "futures-util", "hashlink", "hex", - "indexmap 2.2.6", + "indexmap 2.6.0", "log", "memchr", "once_cell", @@ -5650,7 +5732,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] @@ -5672,9 +5754,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.72" +version = "2.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" dependencies = [ "proc-macro2", "quote", @@ -5689,9 +5771,12 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "sync_wrapper" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] [[package]] name = "synstructure" @@ -5705,6 +5790,17 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "system-configuration" version = "0.5.1" @@ -5713,7 +5809,18 @@ checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", "core-foundation 0.9.4", - "system-configuration-sys", + "system-configuration-sys 0.5.0", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags 2.6.0", + "core-foundation 0.9.4", + "system-configuration-sys 0.6.0", ] [[package]] @@ -5726,6 +5833,16 @@ dependencies = [ "libc", ] +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "tap" version = "1.0.1" @@ -5734,14 +5851,15 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.10.1" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ "cfg-if", - "fastrand 2.1.0", - "rustix 0.38.34", - "windows-sys 0.52.0", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", ] [[package]] @@ -5775,7 +5893,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dffced63c2b5c7be278154d76b479f9f9920ed34e7574201407f0b14e2bbb93" dependencies = [ - "env_logger 0.11.3", + "env_logger 0.11.5", "test-log-macros", "tracing-subscriber", ] @@ -5788,7 +5906,7 @@ checksum = "5999e24eaa32083191ba4e425deb75cdf25efefabe5aaccb7446dd0d4122a3f5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] @@ -5802,7 +5920,7 @@ dependencies = [ "async-trait", "chrono", "did_parser_nom", - "env_logger 0.11.3", + "env_logger 0.11.5", "indy-ledger-response-parser", "indy-vdr-proxy-client", "lazy_static", @@ -5822,22 +5940,22 @@ checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] @@ -5890,6 +6008,16 @@ dependencies = [ "time-core", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinyvec" version = "1.8.0" @@ -5907,32 +6035,31 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.38.1" +version = "1.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb2caba9f80616f438e09748d5acda951967e1ea58508ef53d9c6402485a46df" +checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" dependencies = [ "backtrace", "bytes", "libc", - "mio", - "num_cpus", + "mio 1.0.2", "parking_lot 0.12.3", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.7", + "socket2", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "tokio-macros" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] @@ -5951,7 +6078,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.11", + "rustls 0.23.18", "rustls-pki-types", "tokio", ] @@ -5982,9 +6109,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", @@ -6020,18 +6147,18 @@ dependencies = [ "http 1.1.0", "http-body 1.0.1", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.1", "hyper-timeout", "hyper-util", "percent-encoding", "pin-project", "prost", "rustls-native-certs", - "rustls-pemfile 2.1.2", + "rustls-pemfile 2.2.0", "tokio", "tokio-rustls", "tokio-stream", - "tower", + "tower 0.4.13", "tower-layer", "tower-service", "tracing", @@ -6048,7 +6175,7 @@ dependencies = [ "prost-build", "prost-types", "quote", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] @@ -6071,6 +6198,22 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper 0.1.2", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "tower-http" version = "0.5.2" @@ -6091,15 +6234,15 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -6121,14 +6264,14 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", "valuable", @@ -6170,7 +6313,7 @@ checksum = "cea6980daec8f45217d2cc7205c62578c8f2a8b830a4f381949347a0bc1425b4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] @@ -6196,7 +6339,7 @@ checksum = "f9534daa9fd3ed0bd911d462a37f172228077e7abf18c18a5f67199d959205f8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] @@ -6207,57 +6350,54 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicase" -version = "2.7.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] +checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" [[package]] name = "unicode-bidi" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-normalization" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] [[package]] name = "unicode-properties" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4259d9d4425d9f0661581b804cb85fe66a4c631cadd8f490d1c13a35d5d9291" +checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" [[package]] name = "unicode-segmentation" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-width" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "unicode-xid" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "unicode_categories" @@ -6444,9 +6584,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.2" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", @@ -6483,6 +6623,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" @@ -6491,9 +6643,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" dependencies = [ "getrandom 0.2.15", "serde", @@ -6507,9 +6659,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "value-bag" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101" +checksum = "3ef4c4aa54d5d05a279399bfa921ec387b7aba77caf7a682ae8d86785b8fdad2" [[package]] name = "vcpkg" @@ -6519,15 +6671,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "waker-fn" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "wallet_migrator" @@ -6581,11 +6727,12 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if", + "once_cell", "serde", "serde_json", "wasm-bindgen-macro", @@ -6593,24 +6740,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.89", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.42" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" dependencies = [ "cfg-if", "js-sys", @@ -6620,9 +6767,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -6630,28 +6777,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.89", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "web-sys" -version = "0.3.69" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" dependencies = [ "js-sys", "wasm-bindgen", @@ -6674,11 +6821,11 @@ dependencies = [ [[package]] name = "whoami" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44ab49fad634e88f55bf8f9bb3abd2f27d7204172a112c7c9987e01c1c94ea9" +checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" dependencies = [ - "redox_syscall 0.4.1", + "redox_syscall 0.5.7", "wasite", ] @@ -6700,11 +6847,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -6722,6 +6869,36 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -6740,6 +6917,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -6872,14 +7058,16 @@ dependencies = [ ] [[package]] -name = "winreg" -version = "0.52.0" +name = "write16" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" [[package]] name = "wyz" @@ -6909,9 +7097,33 @@ checksum = "a67300977d3dc3f8034dae89778f502b6ba20b269527b3223ba59c0cf393bb8a" [[package]] name = "yansi" -version = "0.5.1" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" + +[[package]] +name = "yoke" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", + "synstructure 0.13.1", +] [[package]] name = "zerocopy" @@ -6919,6 +7131,7 @@ version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] @@ -6930,7 +7143,28 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.89", +] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", + "synstructure 0.13.1", ] [[package]] @@ -6950,7 +7184,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.89", ] [[package]] @@ -6962,6 +7196,28 @@ dependencies = [ "cmake", ] +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "zmq" version = "0.9.2" @@ -6996,18 +7252,18 @@ dependencies = [ [[package]] name = "zstd-safe" -version = "7.2.0" +version = "7.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa556e971e7b568dc775c136fc9de8c779b1c2fc3a63defaafadffdbd3181afa" +checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" dependencies = [ "zstd-sys", ] [[package]] name = "zstd-sys" -version = "2.0.12+zstd.1.5.6" +version = "2.0.13+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a4e40c320c3cb459d9a9ff6de98cff88f4751ee9275d140e2be94a2b74e4c13" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" dependencies = [ "cc", "pkg-config", From d0bf0afca3140b935a67d273ed0d2b22518530fe Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Tue, 26 Nov 2024 10:33:23 +1000 Subject: [PATCH 06/50] cheqd did parser Signed-off-by: George Mulhearn --- .../src/did/parsing/did_cheqd.rs | 68 +++++++++++++++++++ .../did_parser_nom/src/did/parsing/mod.rs | 4 ++ did_core/did_parser_nom/tests/did/negative.rs | 28 +++++++- did_core/did_parser_nom/tests/did/positive.rs | 10 +++ 4 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 did_core/did_parser_nom/src/did/parsing/did_cheqd.rs diff --git a/did_core/did_parser_nom/src/did/parsing/did_cheqd.rs b/did_core/did_parser_nom/src/did/parsing/did_cheqd.rs new file mode 100644 index 0000000000..2223e37cc4 --- /dev/null +++ b/did_core/did_parser_nom/src/did/parsing/did_cheqd.rs @@ -0,0 +1,68 @@ +//! https://docs.cheqd.io/product/architecture/adr-list/adr-001-cheqd-did-method#syntax-for-did-cheqd-method + +use nom::{ + branch::alt, + bytes::complete::tag, + character::complete::{alphanumeric1, char, one_of}, + combinator::{cut, recognize}, + multi::count, + sequence::{delimited, terminated, tuple}, + IResult, +}; + +use super::{did_sov::parse_unqualified_sovrin_did, DidPart, HEX_DIGIT_CHARS}; + +// namespace = 1*namespace-char ":" ... +fn did_cheqd_namespace(input: &str) -> IResult<&str, &str> { + terminated(alphanumeric1, tag(":"))(input) +} + +// Parser for a single hexDigit +fn hex_digit_char(input: &str) -> IResult<&str, char> { + one_of(HEX_DIGIT_CHARS)(input) +} + +// Parser for hexOctet (2 hex digits) +fn parse_hex_octet(input: &str) -> IResult<&str, &str> { + recognize(count(hex_digit_char, 2))(input) +} + +// https://datatracker.ietf.org/doc/html/rfc4122#section-3 +fn parse_uuid(input: &str) -> IResult<&str, &str> { + recognize(tuple(( + count(parse_hex_octet, 4), // time-low + tag("-"), + count(parse_hex_octet, 2), // time mid + tag("-"), + count(parse_hex_octet, 2), // time high & version + tag("-"), + count(parse_hex_octet, 1), // clock sequence and reserved + count(parse_hex_octet, 1), // clock sequence low + tag("-"), + count(parse_hex_octet, 6), // node + )))(input) +} + +// unique-id = *id-char / UUID +// id-char = ALPHA / DIGIT +// > Note: The *id-char unique-id must be 16 bytes of Indy-style base58 encoded identifier. +fn parse_did_cheqd_unique_id(input: &str) -> IResult<&str, &str> { + alt(( + recognize(parse_unqualified_sovrin_did), // indy-style DID ID + recognize(parse_uuid), // UUID-style DID ID + ))(input) +} + +pub(super) fn parse_did_cheqd(input: &str) -> IResult<&str, DidPart> { + fn did_cheqd_method(input: &str) -> IResult<&str, &str> { + delimited(char(':'), tag("cheqd"), char(':'))(input) + } + let (input_left, (prefix, method, namespace, id)) = tuple(( + tag("did"), + did_cheqd_method, + cut(did_cheqd_namespace), + cut(parse_did_cheqd_unique_id), + ))(input)?; + + Ok((input_left, (prefix, method, Some(namespace), id))) +} diff --git a/did_core/did_parser_nom/src/did/parsing/mod.rs b/did_core/did_parser_nom/src/did/parsing/mod.rs index 148ef6d17d..3b5f616566 100644 --- a/did_core/did_parser_nom/src/did/parsing/mod.rs +++ b/did_core/did_parser_nom/src/did/parsing/mod.rs @@ -1,9 +1,11 @@ +mod did_cheqd; mod did_core; mod did_key; mod did_peer_4; mod did_sov; mod did_web; +use did_cheqd::parse_did_cheqd; use nom::{ branch::alt, combinator::{all_consuming, map}, @@ -22,6 +24,7 @@ type DidPart<'a> = (&'a str, &'a str, Option<&'a str>, &'a str); pub type DidRanges = (Option, Option, Option); static BASE58CHARS: &str = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; +static HEX_DIGIT_CHARS: &str = "0123456789abcdefABCDEF"; fn to_id_range(id: &str) -> DidRanges { (None, None, Some(0..id.len())) @@ -66,6 +69,7 @@ pub fn parse_did_ranges(input: &str) -> IResult<&str, DidRanges> { map(parse_did_peer_4, to_did_ranges), map(parse_did_web, to_did_ranges), map(parse_did_key, to_did_ranges), + map(parse_did_cheqd, to_did_ranges), map(parse_qualified_sovrin_did, to_did_ranges), map(parse_qualified_did, to_did_ranges), map(parse_unqualified_sovrin_did, to_id_range), diff --git a/did_core/did_parser_nom/tests/did/negative.rs b/did_core/did_parser_nom/tests/did/negative.rs index 6a52f6a33b..85b9984979 100644 --- a/did_core/did_parser_nom/tests/did/negative.rs +++ b/did_core/did_parser_nom/tests/did/negative.rs @@ -18,7 +18,7 @@ test_cases_negative! { "not-a-did" no_method_specific_id: "did:example" - unqalified_invalid_len: + unqualified_invalid_len: "2ZHFFhtTD6hJqzux" indy_non_method_specific_id_char_in_namespace: "did:indy:s@vrin:7Tqg6BwSSWapxgUDm9KKgg" @@ -28,12 +28,34 @@ test_cases_negative! { "did:sov:2wJPyULfLLnYTEFYzByf" sov_invalid_char: "did:sov:2wJPyULfOLnYTEFYzByfUR" - sov_unqalified_invalid_len: + sov_unqualified_invalid_len: "2wJPyULfLLnYTEFYzByf" - sov_unqalified_invalid_char: + sov_unqualified_invalid_char: "2wJPyULfOLnYTEFYzByfUR" key_non_mb_value_char: "did:key:zWA8Ta6fesJIxeYku6cbA" key_non_base58_btc_encoded: "did:key:6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK" + cheqd_no_namespace_did: + "did:cheqd:de9786cd-ec53-458c-857c-9342cf264f80" + cheqd_empty_namespace_did: + "did:cheqd::de9786cd-ec53-458c-857c-9342cf264f80" + cheqd_sub_namespace_did: + "did:cheqd:mainnet:foo:de9786cd-ec53-458c-857c-9342cf264f80" + cheqd_invalid_namespace_character: + "did:cheqd:m@innet:de9786cd-ec53-458c-857c-9342cf264f80" + cheqd_short_indy_style_id: + "did:cheqd:mainnet:TAwT8WVt3dz2DBAifwuS" + cheqd_long_indy_style_id: + "did:cheqd:mainnet:TAwT8WVt3dz2DBAifwuSknT" + cheqd_non_base58_indy_style_char: + "did:cheqd:mainnet:TAwT8WVt0dz2DBAifwuSkn" + cheqd_invalid_uuid_style_id_1: + "did:cheqd:mainnet:de9786cd-ec53-458c-857c-9342cf264f8" + cheqd_invalid_uuid_style_id_2: + "did:cheqd:mainnet:de9786cd-ec53-458c-857c9342cf264f80" + cheqd_invalid_uuid_style_id_3: + "did:cheqd:mainnet:de9786cd-ec53-458c-857c9342cf2-64f80" + cheqd_non_alpha_uuid_style_char: + "did:cheqd:mainnet:qe9786cd-ec53-458c-857c-9342cf264f80" } diff --git a/did_core/did_parser_nom/tests/did/positive.rs b/did_core/did_parser_nom/tests/did/positive.rs index 6a0a34fa62..9c859b47e4 100644 --- a/did_core/did_parser_nom/tests/did/positive.rs +++ b/did_core/did_parser_nom/tests/did/positive.rs @@ -81,4 +81,14 @@ test_cases_positive! { Some("peer"), None, "4z84UjLJ6ugExV8TJ5gJUtZap5q67uD34LU26m1Ljo2u9PZ4xHa9XnknHLc3YMST5orPXh3LKi6qEYSHdNSgRMvassKP:z27uFkiqJVwvvn2ke5M19UCvByS79r5NppqwjiGAJzkj1EM4sf2JmiUySkANKy4YNu8M7yKjSmvPJTqbcyhPrJs9TASzDs2fWE1vFegmaRJxHRF5M9wGTPwGR1NbPkLGsvcnXum7aN2f8kX3BnhWWWp" + test_did_cheqd: + "did:cheqd:mainnet:de9786cd-ec53-458c-857c-9342cf264f80", + Some("cheqd"), + Some("mainnet"), + "de9786cd-ec53-458c-857c-9342cf264f80" + test_did_cheqd_indy_style: + "did:cheqd:testnet:TAwT8WVt3dz2DBAifwuSkn", + Some("cheqd"), + Some("testnet"), + "TAwT8WVt3dz2DBAifwuSkn" } From 881410ec5fa6a70665a17b17cfc7cbf866710456 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Tue, 26 Nov 2024 10:42:33 +1000 Subject: [PATCH 07/50] cheqd did url tests Signed-off-by: George Mulhearn --- .../did_parser_nom/tests/did_url/positive.rs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/did_core/did_parser_nom/tests/did_url/positive.rs b/did_core/did_parser_nom/tests/did_url/positive.rs index fea2099559..ced17a3b35 100644 --- a/did_core/did_parser_nom/tests/did_url/positive.rs +++ b/did_core/did_parser_nom/tests/did_url/positive.rs @@ -361,4 +361,27 @@ test_cases_positive! { Some("/anoncreds/v0/REV_REG_DEF/56495/npdb/TAG1"), None, HashMap::new() + test_case28: + "did:cheqd:testnet:d8ac0372-0d4b-413e-8ef5-8e8f07822b2c/resources/40829caf-b415-4b1d-91a3-b56dfb6374f4", + Some("did:cheqd:testnet:d8ac0372-0d4b-413e-8ef5-8e8f07822b2c"), + Some("cheqd"), + Some("testnet"), + Some("d8ac0372-0d4b-413e-8ef5-8e8f07822b2c"), + Some("/resources/40829caf-b415-4b1d-91a3-b56dfb6374f4"), + None, + HashMap::new() + test_case29: + "did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J?resourceName=universityDegree&resourceType=anonCredsCredDef", + Some("did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J"), + Some("cheqd"), + Some("mainnet"), + Some("zF7rhDBfUt9d1gJPjx7s1J"), + None, + None, + { + vec![ + ("resourceName".to_string(), "universityDegree".to_string()), + ("resourceType".to_string(), "anonCredsCredDef".to_string()), + ].into_iter().collect() + } } From 96d74e90b2f894171b4503e618e957ce69277805 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Tue, 26 Nov 2024 10:47:59 +1000 Subject: [PATCH 08/50] re-gen lock Signed-off-by: George Mulhearn --- Cargo.lock | 788 ++++++++++++++++++----------------------------------- 1 file changed, 261 insertions(+), 527 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 929f74f5a7..041e7b19d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -65,7 +65,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] @@ -182,14 +182,14 @@ dependencies = [ "actix-router", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] name = "addr2line" -version = "0.24.2" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" dependencies = [ "gimli", ] @@ -274,9 +274,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.20" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "amcl" @@ -395,9 +395,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.18" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" dependencies = [ "anstyle", "anstyle-parse", @@ -410,43 +410,43 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anstyle-parse" -version = "0.2.6" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.2" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.6" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" dependencies = [ "anstyle", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] name = "anyhow" -version = "1.0.93" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" [[package]] name = "arc-swap" @@ -517,13 +517,13 @@ dependencies = [ "actix-web", "anoncreds_types", "aries-vcx-agent", - "clap 4.5.21", + "clap 4.5.19", "derive_more", "display_as_json", "env_logger 0.11.5", "log", "rand 0.8.5", - "reqwest 0.12.9", + "reqwest 0.12.8", "serde", "serde_derive", "serde_json", @@ -740,7 +740,7 @@ dependencies = [ "futures-lite", "hex", "hmac", - "itertools 0.12.1", + "itertools", "log", "once_cell", "percent-encoding", @@ -819,9 +819,9 @@ dependencies = [ [[package]] name = "async-io" -version = "2.4.0" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059" +checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" dependencies = [ "async-lock", "cfg-if", @@ -893,7 +893,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] @@ -910,7 +910,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] @@ -947,9 +947,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "axum" -version = "0.7.9" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" +checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" dependencies = [ "async-trait", "axum-core", @@ -958,7 +958,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.1", "http-body-util", - "hyper 1.5.1", + "hyper 1.4.1", "hyper-util", "itoa", "matchit", @@ -971,7 +971,7 @@ dependencies = [ "serde_json", "serde_path_to_error", "serde_urlencoded", - "sync_wrapper 1.0.2", + "sync_wrapper 1.0.1", "tokio", "tower 0.5.1", "tower-layer", @@ -994,7 +994,7 @@ dependencies = [ "mime", "pin-project-lite", "rustversion", - "sync_wrapper 1.0.2", + "sync_wrapper 1.0.1", "tower-layer", "tower-service", "tracing", @@ -1008,7 +1008,7 @@ checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] @@ -1205,15 +1205,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.8.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "bytestring" -version = "1.4.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e465647ae23b2823b0753f50decb2d5a86d2bb2cac04788fafd1f80e45378e5f" +checksum = "74d80203ea6b29df88012294f62733de21cfeab47f17b41af3a38bc30a03ee72" dependencies = [ "bytes", ] @@ -1261,9 +1261,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.1" +version = "1.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" +checksum = "812acba72f0a070b003d3697490d2b55b837230ae7c6c6497f05cc2ddbb8d938" dependencies = [ "jobserver", "libc", @@ -1352,9 +1352,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.21" +version = "4.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" +checksum = "7be5744db7978a28d9df86a214130d106a89ce49644cbc4e3f0c22c3fba30615" dependencies = [ "clap_builder", "clap_derive 4.5.18", @@ -1362,13 +1362,13 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.21" +version = "4.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" +checksum = "a5fbc17d3ef8278f55b282b2a2e75ae6f6c7d4bb70ed3d0382375104bfafdb4b" dependencies = [ "anstream", "anstyle", - "clap_lex 0.7.3", + "clap_lex 0.7.2", "strsim 0.11.1", ] @@ -1394,7 +1394,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] @@ -1408,9 +1408,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.3" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "client-tui" @@ -1423,7 +1423,7 @@ dependencies = [ "log", "mediator", "messages", - "reqwest 0.12.9", + "reqwest 0.12.8", "serde_json", "tokio", ] @@ -1439,9 +1439,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" [[package]] name = "concurrent-queue" @@ -1522,9 +1522,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.16" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] @@ -1738,7 +1738,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] @@ -1786,7 +1786,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] @@ -1808,7 +1808,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core 0.20.10", "quote", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] @@ -1850,33 +1850,33 @@ dependencies = [ [[package]] name = "derive_builder" -version = "0.20.2" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" +checksum = "cd33f37ee6a119146a1781d3356a7c26028f83d779b2e04ecd45fdc75c76877b" dependencies = [ "derive_builder_macro", ] [[package]] name = "derive_builder_core" -version = "0.20.2" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" +checksum = "7431fa049613920234f22c47fdc33e6cf3ee83067091ea4277a3f8c4587aae38" dependencies = [ "darling 0.20.10", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] name = "derive_builder_macro" -version = "0.20.2" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" +checksum = "4abae7035bf79b9877b779505d8cf3749285b80c43941eda66604841889451dc" dependencies = [ "derive_builder_core", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] @@ -1889,7 +1889,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] @@ -2033,7 +2033,7 @@ version = "0.1.0" dependencies = [ "async-trait", "did_resolver", - "hyper 0.14.31", + "hyper 0.14.30", "hyper-tls 0.5.0", "serde_json", "thiserror", @@ -2101,18 +2101,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "syn 2.0.89", -] - -[[package]] -name = "displaydoc" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] @@ -2198,9 +2187,9 @@ dependencies = [ [[package]] name = "encoding_rs" -version = "0.8.35" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ "cfg-if", ] @@ -2222,7 +2211,7 @@ checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] @@ -2243,7 +2232,7 @@ dependencies = [ "darling 0.20.10", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] @@ -2392,14 +2381,14 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.109", - "synstructure 0.12.6", + "synstructure", ] [[package]] name = "fastrand" -version = "2.2.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "ff" @@ -2435,9 +2424,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.35" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" dependencies = [ "crc32fast", "miniz_oxide", @@ -2445,9 +2434,9 @@ dependencies = [ [[package]] name = "flume" -version = "0.11.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" dependencies = [ "futures-core", "futures-sink", @@ -2460,12 +2449,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foldhash" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" - [[package]] name = "foreign-types" version = "0.3.2" @@ -2523,9 +2506,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", @@ -2538,9 +2521,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -2548,15 +2531,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -2577,15 +2560,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-lite" -version = "2.5.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cef40d21ae2c515b51041df9ed313ed21e572df340ea58a922a0aefe7e8891a1" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" dependencies = [ "fastrand", "futures-core", @@ -2596,32 +2579,32 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-channel", "futures-core", @@ -2691,9 +2674,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.31.1" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" [[package]] name = "glass_pumpkin" @@ -2770,9 +2753,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.7" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" dependencies = [ "atomic-waker", "bytes", @@ -2811,14 +2794,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" -dependencies = [ - "allocator-api2", - "equivalent", - "foldhash", -] +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] name = "hashlink" @@ -2974,9 +2952,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.31" +version = "0.14.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c08302e8fa335b151b788c775ff56e7a03ae64ff85c548ee820fecb70356e85" +checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" dependencies = [ "bytes", "futures-channel", @@ -2998,14 +2976,14 @@ dependencies = [ [[package]] name = "hyper" -version = "1.5.1" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97818827ef4f364230e16705d4706e2897df2bb60617d6ca15d598025a3c481f" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.7", + "h2 0.4.6", "http 1.1.0", "http-body 1.0.1", "httparse", @@ -3025,9 +3003,9 @@ checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ "futures-util", "http 1.1.0", - "hyper 1.5.1", + "hyper 1.4.1", "hyper-util", - "rustls 0.23.18", + "rustls 0.23.13", "rustls-pki-types", "tokio", "tokio-rustls", @@ -3040,7 +3018,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" dependencies = [ - "hyper 1.5.1", + "hyper 1.4.1", "hyper-util", "pin-project-lite", "tokio", @@ -3054,7 +3032,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", - "hyper 0.14.31", + "hyper 0.14.30", "native-tls", "tokio", "tokio-native-tls", @@ -3068,7 +3046,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.5.1", + "hyper 1.4.1", "hyper-util", "native-tls", "tokio", @@ -3087,7 +3065,7 @@ dependencies = [ "futures-util", "http 1.1.0", "http-body 1.0.1", - "hyper 1.5.1", + "hyper 1.4.1", "pin-project-lite", "socket2", "tokio", @@ -3118,124 +3096,6 @@ dependencies = [ "cc", ] -[[package]] -name = "icu_collections" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locid" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" - -[[package]] -name = "icu_normalizer" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "utf16_iter", - "utf8_iter", - "write16", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" - -[[package]] -name = "icu_properties" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_locid_transform", - "icu_properties_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" - -[[package]] -name = "icu_provider" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_provider_macros", - "stable_deref_trait", - "tinystr", - "writeable", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.89", -] - [[package]] name = "ident_case" version = "1.0.1" @@ -3244,30 +3104,19 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" -dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", -] - -[[package]] -name = "idna_adapter" -version = "1.2.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ - "icu_normalizer", - "icu_properties", + "unicode-bidi", + "unicode-normalization", ] [[package]] name = "impl-more" -version = "0.1.8" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aae21c3177a27788957044151cc2800043d127acaa460a47ebb9b84dfa2c6aa0" +checksum = "206ca75c9c03ba3d4ace2460e57b189f39f43de612c2f85836e65c929701bb2d" [[package]] name = "indexmap" @@ -3286,7 +3135,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.15.2", + "hashbrown 0.15.0", ] [[package]] @@ -3507,9 +3356,9 @@ checksum = "b33c9a5c599d67d051c4dc25eb1b6b4ef715d1763c20c85c688717a1734f204e" [[package]] name = "ipnet" -version = "2.10.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" +checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" [[package]] name = "is-terminal" @@ -3546,20 +3395,11 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] - [[package]] name = "itoa" -version = "1.0.14" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jobserver" @@ -3572,9 +3412,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.72" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" dependencies = [ "wasm-bindgen", ] @@ -3626,15 +3466,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.165" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb4d3d38eab6c5239a362fa8bae48c03baf980a6e7079f063942d563ef3533e" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "libm" -version = "0.2.11" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "libredox" @@ -3699,12 +3539,6 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" -[[package]] -name = "litemap" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" - [[package]] name = "local-channel" version = "0.1.5" @@ -3755,11 +3589,11 @@ dependencies = [ [[package]] name = "lru" -version = "0.12.5" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" +checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" dependencies = [ - "hashbrown 0.15.2", + "hashbrown 0.14.5", ] [[package]] @@ -3811,7 +3645,7 @@ dependencies = [ "futures", "log", "messages", - "reqwest 0.12.9", + "reqwest 0.12.8", "serde", "serde_json", "sqlx", @@ -3860,7 +3694,7 @@ dependencies = [ "proc-macro2", "quote", "shared", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] @@ -3932,9 +3766,9 @@ dependencies = [ [[package]] name = "mockall" -version = "0.13.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39a6bfcc6c8c7eed5ee98b9c3e33adc726054389233e201c95dab2d41a3839d2" +checksum = "d4c28b3fb6d753d28c20e826cd46ee611fda1cf3cde03a443a974043247c065a" dependencies = [ "cfg-if", "downcast", @@ -3946,14 +3780,14 @@ dependencies = [ [[package]] name = "mockall_derive" -version = "0.13.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25ca3004c2efe9011bd4e461bd8256445052b9615405b4f7ea43fc8ca5c20898" +checksum = "341014e7f530314e9a1fdbc7400b244efea7122662c96bfa248c31da5bfb2020" dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] @@ -4132,18 +3966,21 @@ dependencies = [ [[package]] name = "object" -version = "0.36.5" +version = "0.36.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.20.2" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +checksum = "82881c4be219ab5faaf2ad5e5e5ecdff8c66bd7402ca3160975c93b24961afd1" +dependencies = [ + "portable-atomic", +] [[package]] name = "opaque-debug" @@ -4153,9 +3990,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.68" +version = "0.10.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" dependencies = [ "bitflags 2.6.0", "cfg-if", @@ -4174,7 +4011,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] @@ -4185,9 +4022,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.104" +version = "0.9.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" dependencies = [ "cc", "libc", @@ -4387,14 +4224,14 @@ checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] name = "pin-project-lite" -version = "0.2.15" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -4448,9 +4285,9 @@ checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" [[package]] name = "polling" -version = "3.7.4" +version = "3.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" +checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" dependencies = [ "cfg-if", "concurrent-queue", @@ -4484,6 +4321,12 @@ dependencies = [ "universal-hash", ] +[[package]] +name = "portable-atomic" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" + [[package]] name = "ppv-lite86" version = "0.2.20" @@ -4531,12 +4374,12 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.25" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" +checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" dependencies = [ "proc-macro2", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] @@ -4574,9 +4417,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.92" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -4599,7 +4442,7 @@ checksum = "0c1318b19085f08681016926435853bbf7858f9c082d0999b80550ff5d9abe15" dependencies = [ "bytes", "heck 0.5.0", - "itertools 0.13.0", + "itertools", "log", "multimap", "once_cell", @@ -4608,7 +4451,7 @@ dependencies = [ "prost", "prost-types", "regex", - "syn 2.0.89", + "syn 2.0.79", "tempfile", ] @@ -4619,10 +4462,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5" dependencies = [ "anyhow", - "itertools 0.13.0", + "itertools", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] @@ -4765,13 +4608,13 @@ dependencies = [ [[package]] name = "regex" -version = "1.11.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.9", + "regex-automata 0.4.8", "regex-syntax 0.8.5", ] @@ -4786,9 +4629,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", @@ -4827,7 +4670,7 @@ dependencies = [ "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.31", + "hyper 0.14.30", "ipnet", "js-sys", "log", @@ -4851,9 +4694,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.9" +version = "0.12.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" dependencies = [ "base64 0.22.1", "bytes", @@ -4861,11 +4704,11 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2 0.4.7", + "h2 0.4.6", "http 1.1.0", "http-body 1.0.1", "http-body-util", - "hyper 1.5.1", + "hyper 1.4.1", "hyper-rustls", "hyper-tls 0.6.0", "hyper-util", @@ -4882,7 +4725,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "sync_wrapper 1.0.2", + "sync_wrapper 1.0.1", "system-configuration 0.6.1", "tokio", "tokio-native-tls", @@ -4978,9 +4821,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.41" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ "bitflags 2.6.0", "errno", @@ -5002,9 +4845,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.18" +version = "0.23.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9cc1d47e243d655ace55ed38201c19ae02c148ae56412ab8750e8f0166ab7f" +checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" dependencies = [ "log", "once_cell", @@ -5074,9 +4917,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.18" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "ryu" @@ -5095,9 +4938,9 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.27" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" dependencies = [ "windows-sys 0.59.0", ] @@ -5125,7 +4968,7 @@ checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] @@ -5179,9 +5022,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.12.1" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" dependencies = [ "core-foundation-sys", "libc", @@ -5198,9 +5041,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.215" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] @@ -5227,20 +5070,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.215" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] name = "serde_json" -version = "1.0.133" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa", "memchr", @@ -5328,7 +5171,7 @@ dependencies = [ "lazy_static", "log", "regex", - "reqwest 0.12.9", + "reqwest 0.12.8", "serde", "serde_json", "thiserror", @@ -5732,7 +5575,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] @@ -5754,9 +5597,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.89" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", @@ -5771,9 +5614,9 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "sync_wrapper" -version = "1.0.2" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" dependencies = [ "futures-core", ] @@ -5790,17 +5633,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "synstructure" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.89", -] - [[package]] name = "system-configuration" version = "0.5.1" @@ -5851,9 +5683,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.14.0" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" dependencies = [ "cfg-if", "fastrand", @@ -5906,7 +5738,7 @@ checksum = "5999e24eaa32083191ba4e425deb75cdf25efefabe5aaccb7446dd0d4122a3f5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] @@ -5940,22 +5772,22 @@ checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" [[package]] name = "thiserror" -version = "1.0.69" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.69" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] @@ -6008,16 +5840,6 @@ dependencies = [ "time-core", ] -[[package]] -name = "tinystr" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" -dependencies = [ - "displaydoc", - "zerovec", -] - [[package]] name = "tinyvec" version = "1.8.0" @@ -6035,9 +5857,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.41.1" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "bytes", @@ -6059,7 +5881,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] @@ -6078,7 +5900,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.18", + "rustls 0.23.13", "rustls-pki-types", "tokio", ] @@ -6147,7 +5969,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.1", "http-body-util", - "hyper 1.5.1", + "hyper 1.4.1", "hyper-timeout", "hyper-util", "percent-encoding", @@ -6175,7 +5997,7 @@ dependencies = [ "prost-build", "prost-types", "quote", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] @@ -6264,14 +6086,14 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] name = "tracing-core" -version = "0.1.33" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", @@ -6313,7 +6135,7 @@ checksum = "cea6980daec8f45217d2cc7205c62578c8f2a8b830a4f381949347a0bc1425b4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] @@ -6339,7 +6161,7 @@ checksum = "f9534daa9fd3ed0bd911d462a37f172228077e7abf18c18a5f67199d959205f8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] @@ -6350,21 +6172,24 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicase" -version = "2.8.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" +dependencies = [ + "version_check", +] [[package]] name = "unicode-bidi" -version = "0.3.17" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" -version = "1.0.14" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-normalization" @@ -6584,9 +6409,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.4" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", @@ -6623,18 +6448,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - [[package]] name = "utf8parse" version = "0.2.2" @@ -6643,9 +6456,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.11.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" dependencies = [ "getrandom 0.2.15", "serde", @@ -6659,9 +6472,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "value-bag" -version = "1.10.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ef4c4aa54d5d05a279399bfa921ec387b7aba77caf7a682ae8d86785b8fdad2" +checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101" [[package]] name = "vcpkg" @@ -6727,9 +6540,9 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.95" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", "once_cell", @@ -6740,24 +6553,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.95" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.79", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.45" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" dependencies = [ "cfg-if", "js-sys", @@ -6767,9 +6580,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.95" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -6777,28 +6590,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.95" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.79", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.95" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "web-sys" -version = "0.3.72" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" dependencies = [ "js-sys", "wasm-bindgen", @@ -7057,18 +6870,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - -[[package]] -name = "writeable" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" - [[package]] name = "wyz" version = "0.5.1" @@ -7101,30 +6902,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" -[[package]] -name = "yoke" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" -dependencies = [ - "serde", - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.89", - "synstructure 0.13.1", -] - [[package]] name = "zerocopy" version = "0.7.35" @@ -7143,28 +6920,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", -] - -[[package]] -name = "zerofrom" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.89", - "synstructure 0.13.1", + "syn 2.0.79", ] [[package]] @@ -7184,7 +6940,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.79", ] [[package]] @@ -7196,28 +6952,6 @@ dependencies = [ "cmake", ] -[[package]] -name = "zerovec" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.89", -] - [[package]] name = "zmq" version = "0.9.2" From a98803aed0dae7663951083de05e55e8badd3f37 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Tue, 26 Nov 2024 11:24:19 +1000 Subject: [PATCH 09/50] resolver system tests are working Signed-off-by: George Mulhearn --- .../did_cheqd/src/resolution/resolver.rs | 2 +- .../did_cheqd/src/resolution/transformer.rs | 34 +++++++- .../did_methods/did_cheqd/tests/resolution.rs | 80 ++++++++++++++++++- 3 files changed, 109 insertions(+), 7 deletions(-) diff --git a/did_core/did_methods/did_cheqd/src/resolution/resolver.rs b/did_core/did_methods/did_cheqd/src/resolution/resolver.rs index bf3f42f7de..345ba93e13 100644 --- a/did_core/did_methods/did_cheqd/src/resolution/resolver.rs +++ b/did_core/did_methods/did_cheqd/src/resolution/resolver.rs @@ -21,7 +21,7 @@ use crate::{ const MAINNET_NAMESPACE: &str = "mainnet"; const MAINNET_DEFAULT_GRPC: &str = "https://grpc.cheqd.net:443"; const TESTNET_NAMESPACE: &str = "testnet"; -const TESTNET_DEFAULT_GRPC: &str = "https://rpc.cheqd.network:443"; +const TESTNET_DEFAULT_GRPC: &str = "https://grpc.cheqd.network:443"; pub struct DidCheqdResolverConfiguration { networks: Vec, diff --git a/did_core/did_methods/did_cheqd/src/resolution/transformer.rs b/did_core/did_methods/did_cheqd/src/resolution/transformer.rs index 99eb768067..2d88925789 100644 --- a/did_core/did_methods/did_cheqd/src/resolution/transformer.rs +++ b/did_core/did_methods/did_cheqd/src/resolution/transformer.rs @@ -3,6 +3,7 @@ use std::str::FromStr; use did_resolver::{ did_doc::schema::{ did_doc::DidDocument, + service::Service, types::uri::Uri, utils::OneOrList, verification_method::{PublicKeyField, VerificationMethod, VerificationMethodType}, @@ -13,7 +14,10 @@ use serde_json::json; use crate::{ error::DidCheqdError, - proto::cheqd::did::v2::{DidDoc as CheqdDidDoc, VerificationMethod as CheqdVerificationMethod}, + proto::cheqd::did::v2::{ + DidDoc as CheqdDidDoc, Service as CheqdService, + VerificationMethod as CheqdVerificationMethod, + }, }; impl TryFrom for DidDocument { @@ -28,7 +32,9 @@ impl TryFrom for DidDocument { .into_iter() .map(Did::parse) .collect::>()?; - doc.set_controller(OneOrList::from(controller)); + if controller.len() > 0 { + doc.set_controller(OneOrList::from(controller)); + } for vm in value.verification_method { let vm = VerificationMethod::try_from(vm)?; @@ -52,6 +58,11 @@ impl TryFrom for DidDocument { doc.add_key_agreement_ref(vm_id.parse()?); } + for svc in value.service { + let svc = Service::try_from(svc)?; + doc.add_service(svc); + } + let aka: Vec<_> = value .also_known_as .iter() @@ -72,6 +83,7 @@ impl TryFrom for VerificationMethod { let vm_key_encoded = value.verification_material; + // TODO - lots of todo!()s let pk = match vm_type { VerificationMethodType::Ed25519VerificationKey2020 => PublicKeyField::Multibase { public_key_multibase: vm_key_encoded, @@ -122,3 +134,21 @@ impl TryFrom for VerificationMethod { Ok(vm) } } + +impl TryFrom for Service { + type Error = DidCheqdError; + + fn try_from(value: CheqdService) -> Result { + // TODO #1301 - fix mapping: https://github.com/hyperledger/aries-vcx/issues/1301 + let endpoint = value.service_endpoint.into_iter().next().unwrap(); // TODO + + let svc = Service::new( + Uri::from_str(&value.id)?, + endpoint.parse().unwrap(), // TODO + serde_json::from_value(json!(value.service_type))?, + Default::default(), + ); + + Ok(svc) + } +} diff --git a/did_core/did_methods/did_cheqd/tests/resolution.rs b/did_core/did_methods/did_cheqd/tests/resolution.rs index c31f0533fa..38abccdd59 100644 --- a/did_core/did_methods/did_cheqd/tests/resolution.rs +++ b/did_core/did_methods/did_cheqd/tests/resolution.rs @@ -1,13 +1,85 @@ use did_cheqd::resolution::resolver::{DidCheqdResolver, DidCheqdResolverConfiguration}; +use serde_json::json; + +#[tokio::test] +async fn test_resolve_known_mainnet_vector() { + // sample from https://dev.uniresolver.io/ + let did = "did:cheqd:mainnet:Ps1ysXP2Ae6GBfxNhNQNKN".parse().unwrap(); + // NOTE: modifications from uni-resolver: + // *remove contexts, + // make serviceEndpoints into single item (not array) + let expected_doc = json!({ + "@context": [], + "id": "did:cheqd:mainnet:Ps1ysXP2Ae6GBfxNhNQNKN", + "verificationMethod": [ + { + "id": "did:cheqd:mainnet:Ps1ysXP2Ae6GBfxNhNQNKN#key1", + "type": "Ed25519VerificationKey2020", + "controller": "did:cheqd:mainnet:Ps1ysXP2Ae6GBfxNhNQNKN", + "publicKeyMultibase": "z6Mkta7joRuvDh7UnoESdgpr9dDUMh5LvdoECDi3WGrJoscA" + } + ], + "authentication": [ + "did:cheqd:mainnet:Ps1ysXP2Ae6GBfxNhNQNKN#key1" + ], + "service": [ + { + "id": "did:cheqd:mainnet:Ps1ysXP2Ae6GBfxNhNQNKN#website", + "type": "LinkedDomains", + "serviceEndpoint": "https://www.cheqd.io/" + }, + { + "id": "did:cheqd:mainnet:Ps1ysXP2Ae6GBfxNhNQNKN#non-fungible-image", + "type": "LinkedDomains", + "serviceEndpoint": "https://gateway.ipfs.io/ipfs/bafybeihetj2ng3d74k7t754atv2s5dk76pcqtvxls6dntef3xa6rax25xe" + }, + { + "id": "did:cheqd:mainnet:Ps1ysXP2Ae6GBfxNhNQNKN#twitter", + "type": "LinkedDomains", + "serviceEndpoint": "https://twitter.com/cheqd_io" + }, + { + "id": "did:cheqd:mainnet:Ps1ysXP2Ae6GBfxNhNQNKN#linkedin", + "type": "LinkedDomains", + "serviceEndpoint": "https://www.linkedin.com/company/cheqd-identity/" + } + ] + }); + + let resolver = DidCheqdResolver::new(DidCheqdResolverConfiguration::default()); + let doc = resolver.resolve_did(&did).await.unwrap(); + assert_eq!(serde_json::to_value(doc.clone()).unwrap(), expected_doc); + assert_eq!(doc, serde_json::from_value(expected_doc).unwrap()); +} #[tokio::test] async fn test_resolve_known_testnet_vector() { - // let did = "did:cheqd:testnet:BttdoaxtC5JkYJoLeGV8ny".parse().unwrap(); - let did = "did:cheqd:mainnet:e536be60-880a-4d10-bd95-e84d13d7db6d" + // sample from https://dev.uniresolver.io/ + let did = "did:cheqd:testnet:55dbc8bf-fba3-4117-855c-1e0dc1d3bb47" .parse() .unwrap(); - dbg!(&did); + // NOTE: modifications from uni-resolver: + // * remove contexts, + // * made controller a single item + let expected_doc = json!({ + "@context": [], + "id": "did:cheqd:testnet:55dbc8bf-fba3-4117-855c-1e0dc1d3bb47", + "controller": "did:cheqd:testnet:55dbc8bf-fba3-4117-855c-1e0dc1d3bb47", + "verificationMethod": [ + { + "id": "did:cheqd:testnet:55dbc8bf-fba3-4117-855c-1e0dc1d3bb47#key-1", + "type": "Ed25519VerificationKey2020", + "controller": "did:cheqd:testnet:55dbc8bf-fba3-4117-855c-1e0dc1d3bb47", + "publicKeyMultibase": "z6MkkVbyHJLLjdjU5B62DaJ4mkdMdUkttf9UqySSkA9bVTeZ" + } + ], + "authentication": [ + "did:cheqd:testnet:55dbc8bf-fba3-4117-855c-1e0dc1d3bb47#key-1" + ] + }); + let resolver = DidCheqdResolver::new(DidCheqdResolverConfiguration::default()); let doc = resolver.resolve_did(&did).await.unwrap(); - dbg!(doc); + assert_eq!(serde_json::to_value(doc.clone()).unwrap(), expected_doc); + assert_eq!(doc, serde_json::from_value(expected_doc).unwrap()); } From accc65dfc44bc12e9350cd50f2f211b75d520b44 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Tue, 26 Nov 2024 11:30:46 +1000 Subject: [PATCH 10/50] run int tests in CI Signed-off-by: George Mulhearn --- justfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/justfile b/justfile index cd4d455b9d..cf9777c52c 100644 --- a/justfile +++ b/justfile @@ -44,4 +44,4 @@ 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-did-crate test_name="": - cargo test --examples -p did_doc -p did_parser_nom -p did_resolver -p did_resolver_registry -p did_resolver_sov -p did_resolver_web -p did_key -p did_peer -F did_doc/jwk --test "*" + cargo test --examples -p did_doc -p did_parser_nom -p did_resolver -p did_resolver_registry -p did_resolver_sov -p did_resolver_web -p did_key -p did_peer -p did_cheqd -F did_doc/jwk --test "*" From dcbb8a5310324f42496abd1400c33586467e5658 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Tue, 26 Nov 2024 14:50:15 +1000 Subject: [PATCH 11/50] clippy Signed-off-by: George Mulhearn --- did_core/did_methods/did_cheqd/src/lib.rs | 2 +- did_core/did_methods/did_cheqd/src/resolution/transformer.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/did_core/did_methods/did_cheqd/src/lib.rs b/did_core/did_methods/did_cheqd/src/lib.rs index bbdc21ae3f..31400edaff 100644 --- a/did_core/did_methods/did_cheqd/src/lib.rs +++ b/did_core/did_methods/did_cheqd/src/lib.rs @@ -1,3 +1,3 @@ pub mod error; -pub mod resolution; pub mod proto; +pub mod resolution; diff --git a/did_core/did_methods/did_cheqd/src/resolution/transformer.rs b/did_core/did_methods/did_cheqd/src/resolution/transformer.rs index 2d88925789..d5763fc315 100644 --- a/did_core/did_methods/did_cheqd/src/resolution/transformer.rs +++ b/did_core/did_methods/did_cheqd/src/resolution/transformer.rs @@ -32,7 +32,7 @@ impl TryFrom for DidDocument { .into_iter() .map(Did::parse) .collect::>()?; - if controller.len() > 0 { + if !controller.is_empty() { doc.set_controller(OneOrList::from(controller)); } From 8ae721c971dd4e5b2fa137393f8691969307ac98 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Tue, 26 Nov 2024 15:37:02 +1000 Subject: [PATCH 12/50] resolution with contexts Signed-off-by: George Mulhearn --- did_core/did_doc/src/schema/mod.rs | 16 ++++++++ .../verification_method_type.rs | 38 +++++++++++++++---- .../did_cheqd/src/resolution/transformer.rs | 25 +++++++++--- .../did_methods/did_cheqd/tests/resolution.rs | 12 ++++-- 4 files changed, 74 insertions(+), 17 deletions(-) diff --git a/did_core/did_doc/src/schema/mod.rs b/did_core/did_doc/src/schema/mod.rs index bca3088b80..9ea5bd7174 100644 --- a/did_core/did_doc/src/schema/mod.rs +++ b/did_core/did_doc/src/schema/mod.rs @@ -3,3 +3,19 @@ pub mod service; pub mod types; pub mod utils; pub mod verification_method; + +/// Module of commonly used DID-related JSON-LD contexts +pub mod contexts { + pub const W3C_DID_V1: &str = "https://www.w3.org/ns/did/v1"; + pub const W3C_SUITE_ED25519_2020: &str = "https://w3id.org/security/suites/ed25519-2020/v1"; + pub const W3C_SUITE_ED25519_2018: &str = "https://w3id.org/security/suites/ed25519-2018/v1"; + pub const W3C_SUITE_JWS_2020: &str = "https://w3id.org/security/suites/jws-2020/v1"; + pub const W3C_SUITE_SECP256K1_2019: &str = "https://w3id.org/security/suites/secp256k1-2019/v1"; + pub const W3C_BBS_V1: &str = "https://w3id.org/security/bbs/v1"; + pub const W3C_PGP_V1: &str = "https://w3id.org/pgp/v1"; + pub const W3C_SUITE_X25519_2019: &str = "https://w3id.org/security/suites/x25519-2019/v1"; + pub const W3C_SUITE_X25519_2020: &str = "https://w3id.org/security/suites/x25519-2020/v1"; + pub const W3C_SUITE_SECP259K1_RECOVERY_2020: &str = + "https://w3id.org/security/suites/secp256k1recovery-2020/v2"; + pub const W3C_MULTIKEY_V1: &str = "https://w3id.org/security/multikey/v1"; +} diff --git a/did_core/did_doc/src/schema/verification_method/verification_method_type.rs b/did_core/did_doc/src/schema/verification_method/verification_method_type.rs index a14549eed2..4e30b75835 100644 --- a/did_core/did_doc/src/schema/verification_method/verification_method_type.rs +++ b/did_core/did_doc/src/schema/verification_method/verification_method_type.rs @@ -3,7 +3,7 @@ use std::fmt::Display; use public_key::KeyType; use serde::{Deserialize, Serialize}; -use crate::error::DidDocumentBuilderError; +use crate::{error::DidDocumentBuilderError, schema::contexts}; #[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq)] pub enum VerificationMethodType { @@ -13,23 +13,48 @@ pub enum VerificationMethodType { EcdsaSecp256k1VerificationKey2019, /// https://w3id.org/security/suites/ed25519-2018/v1 Ed25519VerificationKey2018, + /// https://w3id.org/security/suites/ed25519-2020/v1 Ed25519VerificationKey2020, - /// https://w3c.github.io/vc-di-bbs/contexts/v1/ + /// https://w3id.org/security/bbs/v1 Bls12381G1Key2020, - /// https://w3c.github.io/vc-di-bbs/contexts/v1/ + /// https://w3id.org/security/bbs/v1 Bls12381G2Key2020, + /// https://w3id.org/pgp/v1 PgpVerificationKey2021, - RsaVerificationKey2018, - /// https://ns.did.ai/suites/x25519-2019/v1/ + /// https://w3id.org/security/suites/x25519-2019/v1 X25519KeyAgreementKey2019, - /// https://ns.did.ai/suites/x25519-2020/v1/ + /// https://w3id.org/security/suites/x25519-2020/v1 X25519KeyAgreementKey2020, + /// https://identity.foundation/EcdsaSecp256k1RecoverySignature2020/lds-ecdsa-secp256k1-recovery2020-0.0.jsonld EcdsaSecp256k1RecoveryMethod2020, /// https://www.w3.org/TR/vc-data-integrity/#multikey /// https://w3id.org/security/multikey/v1 Multikey, } +impl VerificationMethodType { + /// Return the JSON-LD context URL for which this type comes from + pub fn context_for_type(&self) -> &str { + match self { + VerificationMethodType::JsonWebKey2020 => contexts::W3C_SUITE_JWS_2020, + VerificationMethodType::EcdsaSecp256k1VerificationKey2019 => { + contexts::W3C_SUITE_SECP256K1_2019 + } + VerificationMethodType::Ed25519VerificationKey2018 => contexts::W3C_SUITE_ED25519_2018, + VerificationMethodType::Ed25519VerificationKey2020 => contexts::W3C_SUITE_ED25519_2020, + VerificationMethodType::Bls12381G1Key2020 => contexts::W3C_BBS_V1, + VerificationMethodType::Bls12381G2Key2020 => contexts::W3C_BBS_V1, + VerificationMethodType::PgpVerificationKey2021 => contexts::W3C_PGP_V1, + VerificationMethodType::X25519KeyAgreementKey2019 => contexts::W3C_SUITE_X25519_2019, + VerificationMethodType::X25519KeyAgreementKey2020 => contexts::W3C_SUITE_X25519_2020, + VerificationMethodType::EcdsaSecp256k1RecoveryMethod2020 => { + contexts::W3C_SUITE_SECP259K1_RECOVERY_2020 + } + VerificationMethodType::Multikey => contexts::W3C_MULTIKEY_V1, + } + } +} + impl Display for VerificationMethodType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { @@ -46,7 +71,6 @@ impl Display for VerificationMethodType { VerificationMethodType::Bls12381G1Key2020 => write!(f, "Bls12381G1Key2020"), VerificationMethodType::Bls12381G2Key2020 => write!(f, "Bls12381G2Key2020"), VerificationMethodType::PgpVerificationKey2021 => write!(f, "PgpVerificationKey2021"), - VerificationMethodType::RsaVerificationKey2018 => write!(f, "RsaVerificationKey2018"), VerificationMethodType::X25519KeyAgreementKey2019 => { write!(f, "X25519KeyAgreementKey2019") } diff --git a/did_core/did_methods/did_cheqd/src/resolution/transformer.rs b/did_core/did_methods/did_cheqd/src/resolution/transformer.rs index d5763fc315..ca2bf2d4f2 100644 --- a/did_core/did_methods/did_cheqd/src/resolution/transformer.rs +++ b/did_core/did_methods/did_cheqd/src/resolution/transformer.rs @@ -2,6 +2,7 @@ use std::str::FromStr; use did_resolver::{ did_doc::schema::{ + contexts, did_doc::DidDocument, service::Service, types::uri::Uri, @@ -25,7 +26,12 @@ impl TryFrom for DidDocument { fn try_from(value: CheqdDidDoc) -> Result { let mut doc = DidDocument::new(value.id.parse()?); - doc.set_extra_field(String::from("@context"), json!(value.context)); + let mut context = value.context; + + // insert default context + if !context.iter().any(|ctx| ctx == contexts::W3C_DID_V1) { + context.push(contexts::W3C_DID_V1.to_owned()); + } let controller: Vec<_> = value .controller @@ -38,8 +44,12 @@ impl TryFrom for DidDocument { for vm in value.verification_method { let vm = VerificationMethod::try_from(vm)?; + let vm_ctx = vm.verification_method_type().context_for_type(); + if !context.iter().any(|ctx| ctx == vm_ctx) { + context.push(vm_ctx.to_owned()); + } + doc.add_verification_method(vm); - // TODO - would be nice to append relevant contexts too } for vm_id in value.authentication { @@ -70,6 +80,9 @@ impl TryFrom for DidDocument { .collect::>()?; doc.set_also_known_as(aka); + // add in all contexts + doc.set_extra_field(String::from("@context"), json!(context)); + Ok(doc) } } @@ -114,12 +127,12 @@ impl TryFrom for VerificationMethod { VerificationMethodType::Multikey => PublicKeyField::Multibase { public_key_multibase: vm_key_encoded, }, + // https://w3id.org/pgp/v1 + VerificationMethodType::PgpVerificationKey2021 => PublicKeyField::Pgp { + public_key_pgp: vm_key_encoded, + }, // cannot infer encoding type from vm type, as multiple are supported: https://ns.did.ai/suites/secp256k1-2019/v1/ VerificationMethodType::EcdsaSecp256k1VerificationKey2019 => todo!(), - // not supported - VerificationMethodType::PgpVerificationKey2021 => todo!(), - // not supported - VerificationMethodType::RsaVerificationKey2018 => todo!(), // cannot infer encoding type from vm type: https://identity.foundation/EcdsaSecp256k1RecoverySignature2020/lds-ecdsa-secp256k1-recovery2020-0.0.jsonld VerificationMethodType::EcdsaSecp256k1RecoveryMethod2020 => todo!(), }; diff --git a/did_core/did_methods/did_cheqd/tests/resolution.rs b/did_core/did_methods/did_cheqd/tests/resolution.rs index 38abccdd59..2eb417e06d 100644 --- a/did_core/did_methods/did_cheqd/tests/resolution.rs +++ b/did_core/did_methods/did_cheqd/tests/resolution.rs @@ -6,10 +6,12 @@ async fn test_resolve_known_mainnet_vector() { // sample from https://dev.uniresolver.io/ let did = "did:cheqd:mainnet:Ps1ysXP2Ae6GBfxNhNQNKN".parse().unwrap(); // NOTE: modifications from uni-resolver: - // *remove contexts, // make serviceEndpoints into single item (not array) let expected_doc = json!({ - "@context": [], + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/ed25519-2020/v1" + ], "id": "did:cheqd:mainnet:Ps1ysXP2Ae6GBfxNhNQNKN", "verificationMethod": [ { @@ -59,10 +61,12 @@ async fn test_resolve_known_testnet_vector() { .parse() .unwrap(); // NOTE: modifications from uni-resolver: - // * remove contexts, // * made controller a single item let expected_doc = json!({ - "@context": [], + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/ed25519-2020/v1" + ], "id": "did:cheqd:testnet:55dbc8bf-fba3-4117-855c-1e0dc1d3bb47", "controller": "did:cheqd:testnet:55dbc8bf-fba3-4117-855c-1e0dc1d3bb47", "verificationMethod": [ From c9464cbf6b030dc25289ca1a7ea3e81a6e1a6ec0 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Tue, 26 Nov 2024 17:21:14 +1000 Subject: [PATCH 13/50] finish some TODOs, and add doc metadata Signed-off-by: George Mulhearn --- Cargo.lock | 2 + did_core/did_methods/did_cheqd/Cargo.toml | 2 + .../did_methods/did_cheqd/src/error/mod.rs | 14 +++++ .../did_cheqd/src/error/parsing.rs | 16 +++++ .../did_cheqd/src/resolution/resolver.rs | 41 ++++++++----- .../did_cheqd/src/resolution/transformer.rs | 59 ++++++++++++++++--- .../did_methods/did_cheqd/tests/resolution.rs | 7 ++- 7 files changed, 116 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 041e7b19d8..ae2d63bb81 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1897,6 +1897,7 @@ name = "did_cheqd" version = "0.1.0" dependencies = [ "async-trait", + "chrono", "did_resolver", "prost", "prost-types", @@ -1905,6 +1906,7 @@ dependencies = [ "thiserror", "tokio", "tonic", + "url", ] [[package]] diff --git a/did_core/did_methods/did_cheqd/Cargo.toml b/did_core/did_methods/did_cheqd/Cargo.toml index 8c8569735c..4a5dc294b2 100644 --- a/did_core/did_methods/did_cheqd/Cargo.toml +++ b/did_core/did_methods/did_cheqd/Cargo.toml @@ -25,6 +25,8 @@ serde_json = "1.0.96" serde = { version = "1.0.160", features = ["derive"] } thiserror = "1.0.40" tokio = { version = "1.38.0" } +chrono = { version = "0.4.24", default-features = false } +url = { version = "2.3.1", default-features = false } [dev-dependencies] tokio = { version = "1.38.0", default-features = false, features = [ diff --git a/did_core/did_methods/did_cheqd/src/error/mod.rs b/did_core/did_methods/did_cheqd/src/error/mod.rs index 83659b8c6c..fe3d49efdc 100644 --- a/did_core/did_methods/did_cheqd/src/error/mod.rs +++ b/did_core/did_methods/did_cheqd/src/error/mod.rs @@ -8,6 +8,20 @@ pub type DidCheqdResult = Result; #[derive(Error, Debug)] #[non_exhaustive] pub enum DidCheqdError { + #[error("DID method not supported: {0}")] + MethodNotSupported(String), + #[error("Cheqd network not supported: {0}")] + NetworkNotSupported(String), + #[error("Bad configuration: {0}")] + BadConfiguration(String), + #[error("Transport error: {0}")] + TransportError(#[from] tonic::transport::Error), + #[error("Non-success resolver response: {0}")] + NonSuccessResponse(#[from] tonic::Status), + #[error("Response from resolver is invalid: {0}")] + InvalidResponse(String), + #[error("Invalid DID Document structure resolved: {0}")] + InvalidDidDocument(String), #[error("Parsing error: {0}")] ParsingError(#[from] ParsingErrorSource), #[error(transparent)] diff --git a/did_core/did_methods/did_cheqd/src/error/parsing.rs b/did_core/did_methods/did_cheqd/src/error/parsing.rs index 5b4a704c11..e2c0079ddf 100644 --- a/did_core/did_methods/did_cheqd/src/error/parsing.rs +++ b/did_core/did_methods/did_cheqd/src/error/parsing.rs @@ -11,8 +11,12 @@ pub enum ParsingErrorSource { DidDocumentParsingUriError(#[from] UriWrapperError), #[error("JSON parsing error: {0}")] JsonError(#[from] serde_json::Error), + #[error("Invalid URL: {0}")] + UrlParsingError(url::ParseError), #[error("Invalid encoding: {0}")] Utf8Error(#[from] std::string::FromUtf8Error), + #[error("Invalid encoding: {0}")] + IntConversionError(#[from] std::num::TryFromIntError), } impl From for DidCheqdError { @@ -33,8 +37,20 @@ impl From for DidCheqdError { } } +impl From for DidCheqdError { + fn from(error: url::ParseError) -> Self { + DidCheqdError::ParsingError(ParsingErrorSource::UrlParsingError(error)) + } +} + impl From for DidCheqdError { fn from(error: std::string::FromUtf8Error) -> Self { DidCheqdError::ParsingError(ParsingErrorSource::Utf8Error(error)) } } + +impl From for DidCheqdError { + fn from(error: std::num::TryFromIntError) -> Self { + DidCheqdError::ParsingError(ParsingErrorSource::IntConversionError(error)) + } +} diff --git a/did_core/did_methods/did_cheqd/src/resolution/resolver.rs b/did_core/did_methods/did_cheqd/src/resolution/resolver.rs index 345ba93e13..3cbc69abb1 100644 --- a/did_core/did_methods/did_cheqd/src/resolution/resolver.rs +++ b/did_core/did_methods/did_cheqd/src/resolution/resolver.rs @@ -5,13 +5,14 @@ use did_resolver::{ did_doc::schema::did_doc::DidDocument, did_parser_nom::Did, error::GenericError, + shared_types::did_document_metadata::DidDocumentMetadata, traits::resolvable::{resolution_output::DidResolutionOutput, DidResolvable}, }; use tokio::sync::Mutex; use tonic::transport::{Channel, Endpoint}; use crate::{ - error::DidCheqdResult, + error::{DidCheqdError, DidCheqdResult}, proto::cheqd::{ did::v2::{query_client::QueryClient as DidQueryClient, QueryDidDocRequest}, resource::v2::query_client::QueryClient as ResourceQueryClient, @@ -79,8 +80,7 @@ impl DidResolvable for DidCheqdResolver { did: &Did, _: &Self::DidResolutionOptions, ) -> Result { - let doc = self.resolve_did(did).await?; - Ok(DidResolutionOutput::builder(doc).build()) + Ok(self.resolve_did(did).await?) } } @@ -103,14 +103,13 @@ impl DidCheqdResolver { .networks .iter() .find(|n| n.namespace == network) - .unwrap(); // TODO + .ok_or(DidCheqdError::NetworkNotSupported(network.to_owned()))?; // initialize new let conn = Endpoint::new(network_config.grpc_url.clone()) - .unwrap() // TODO + .map_err(|e| DidCheqdError::BadConfiguration(e.to_string()))? .connect() - .await - .unwrap(); // TODO + .await?; let did_client = DidQueryClient::new(conn.clone()); let resource_client = ResourceQueryClient::new(conn); @@ -125,21 +124,31 @@ impl DidCheqdResolver { Ok(client) } - pub async fn resolve_did(&self, did: &Did) -> DidCheqdResult { + pub async fn resolve_did(&self, did: &Did) -> DidCheqdResult { let network = did.namespace().unwrap_or(MAINNET_NAMESPACE); - let mut client = self.client_for_network(network).await.unwrap(); - // TODO - mainnet vs testnet - // TODO - return doc metadata - // TODO - doc versions + let mut client = self.client_for_network(network).await?; let did = did.did().to_owned(); let request = tonic::Request::new(QueryDidDocRequest { id: did }); - let response = client.did.did_doc(request).await.unwrap(); + let response = client.did.did_doc(request).await?; let query_response = response.into_inner(); - let query_doc_res = query_response.value.unwrap(); // TODO - let query_doc = query_doc_res.did_doc.unwrap(); // TODO + let query_doc_res = query_response.value.ok_or(DidCheqdError::InvalidResponse( + "DIDDoc query did not return a value".into(), + ))?; + dbg!(&query_doc_res); + let query_doc = query_doc_res.did_doc.ok_or(DidCheqdError::InvalidResponse( + "DIDDoc query did not return a DIDDoc".into(), + ))?; + + let mut output_builder = DidResolutionOutput::builder(DidDocument::try_from(query_doc)?); + + if let Some(query_metadata) = query_doc_res.metadata { + // FUTURE - append linked resources to metadata + output_builder = output_builder + .did_document_metadata(DidDocumentMetadata::try_from(query_metadata)?); + } - DidDocument::try_from(query_doc) + Ok(output_builder.build()) } } diff --git a/did_core/did_methods/did_cheqd/src/resolution/transformer.rs b/did_core/did_methods/did_cheqd/src/resolution/transformer.rs index ca2bf2d4f2..7154d8dd96 100644 --- a/did_core/did_methods/did_cheqd/src/resolution/transformer.rs +++ b/did_core/did_methods/did_cheqd/src/resolution/transformer.rs @@ -1,5 +1,6 @@ use std::str::FromStr; +use chrono::{DateTime, Utc}; use did_resolver::{ did_doc::schema::{ contexts, @@ -10,13 +11,14 @@ use did_resolver::{ verification_method::{PublicKeyField, VerificationMethod, VerificationMethodType}, }, did_parser_nom::Did, + shared_types::did_document_metadata::DidDocumentMetadata, }; use serde_json::json; use crate::{ - error::DidCheqdError, + error::{DidCheqdError, DidCheqdResult}, proto::cheqd::did::v2::{ - DidDoc as CheqdDidDoc, Service as CheqdService, + DidDoc as CheqdDidDoc, Metadata as CheqdDidDocMetadata, Service as CheqdService, VerificationMethod as CheqdVerificationMethod, }, }; @@ -96,7 +98,6 @@ impl TryFrom for VerificationMethod { let vm_key_encoded = value.verification_material; - // TODO - lots of todo!()s let pk = match vm_type { VerificationMethodType::Ed25519VerificationKey2020 => PublicKeyField::Multibase { public_key_multibase: vm_key_encoded, @@ -132,9 +133,19 @@ impl TryFrom for VerificationMethod { public_key_pgp: vm_key_encoded, }, // cannot infer encoding type from vm type, as multiple are supported: https://ns.did.ai/suites/secp256k1-2019/v1/ - VerificationMethodType::EcdsaSecp256k1VerificationKey2019 => todo!(), + VerificationMethodType::EcdsaSecp256k1VerificationKey2019 => { + return Err(DidCheqdError::InvalidDidDocument( + "DidDocument uses VM type of EcdsaSecp256k1VerificationKey2019, cannot process" + .into(), + )) + } // cannot infer encoding type from vm type: https://identity.foundation/EcdsaSecp256k1RecoverySignature2020/lds-ecdsa-secp256k1-recovery2020-0.0.jsonld - VerificationMethodType::EcdsaSecp256k1RecoveryMethod2020 => todo!(), + VerificationMethodType::EcdsaSecp256k1RecoveryMethod2020 => { + return Err(DidCheqdError::InvalidDidDocument( + "DidDocument uses VM type of EcdsaSecp256k1RecoveryMethod2020, cannot process" + .into(), + )) + } }; let vm = VerificationMethod::builder() @@ -153,11 +164,18 @@ impl TryFrom for Service { fn try_from(value: CheqdService) -> Result { // TODO #1301 - fix mapping: https://github.com/hyperledger/aries-vcx/issues/1301 - let endpoint = value.service_endpoint.into_iter().next().unwrap(); // TODO + let endpoint = + value + .service_endpoint + .into_iter() + .next() + .ok_or(DidCheqdError::InvalidDidDocument( + "DID Document Service is missing an endpoint".into(), + ))?; let svc = Service::new( Uri::from_str(&value.id)?, - endpoint.parse().unwrap(), // TODO + endpoint.parse()?, serde_json::from_value(json!(value.service_type))?, Default::default(), ); @@ -165,3 +183,30 @@ impl TryFrom for Service { Ok(svc) } } + +impl TryFrom for DidDocumentMetadata { + type Error = DidCheqdError; + + fn try_from(value: CheqdDidDocMetadata) -> Result { + let mut builder = DidDocumentMetadata::builder(); + if let Some(timestamp) = value.created { + builder = builder.created(prost_timestamp_to_dt(timestamp)?); + } + if let Some(timestamp) = value.updated { + builder = builder.updated(prost_timestamp_to_dt(timestamp)?); + } + builder = builder + .deactivated(value.deactivated) + .version_id(value.version_id) + .next_version_id(value.next_version_id); + + Ok(builder.build()) + } +} + +fn prost_timestamp_to_dt(mut timestamp: prost_types::Timestamp) -> DidCheqdResult> { + timestamp.normalize(); + DateTime::from_timestamp(timestamp.seconds, timestamp.nanos.try_into()?).ok_or( + DidCheqdError::Other(format!("Unknown error, bad timestamp: {timestamp:?}").into()), + ) +} diff --git a/did_core/did_methods/did_cheqd/tests/resolution.rs b/did_core/did_methods/did_cheqd/tests/resolution.rs index 2eb417e06d..cea9a7f457 100644 --- a/did_core/did_methods/did_cheqd/tests/resolution.rs +++ b/did_core/did_methods/did_cheqd/tests/resolution.rs @@ -1,4 +1,5 @@ use did_cheqd::resolution::resolver::{DidCheqdResolver, DidCheqdResolverConfiguration}; +use did_resolver::traits::resolvable::DidResolvable; use serde_json::json; #[tokio::test] @@ -49,7 +50,8 @@ async fn test_resolve_known_mainnet_vector() { }); let resolver = DidCheqdResolver::new(DidCheqdResolverConfiguration::default()); - let doc = resolver.resolve_did(&did).await.unwrap(); + let output = resolver.resolve(&did, &()).await.unwrap(); + let doc = output.did_document; assert_eq!(serde_json::to_value(doc.clone()).unwrap(), expected_doc); assert_eq!(doc, serde_json::from_value(expected_doc).unwrap()); } @@ -83,7 +85,8 @@ async fn test_resolve_known_testnet_vector() { }); let resolver = DidCheqdResolver::new(DidCheqdResolverConfiguration::default()); - let doc = resolver.resolve_did(&did).await.unwrap(); + let output = resolver.resolve(&did, &()).await.unwrap(); + let doc = output.did_document; assert_eq!(serde_json::to_value(doc.clone()).unwrap(), expected_doc); assert_eq!(doc, serde_json::from_value(expected_doc).unwrap()); } From 0353b0267870d387788e7c6b59ae0bdcb245fac9 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Tue, 26 Nov 2024 17:38:13 +1000 Subject: [PATCH 14/50] update readme Signed-off-by: George Mulhearn --- did_core/did_methods/did_cheqd/README.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/did_core/did_methods/did_cheqd/README.md b/did_core/did_methods/did_cheqd/README.md index d68f4eff01..f609b759e8 100644 --- a/did_core/did_methods/did_cheqd/README.md +++ b/did_core/did_methods/did_cheqd/README.md @@ -1,3 +1,14 @@ # DID Cheqd Resolver +This crate contains a resolver for DIDs of the [did:cheqd](https://docs.cheqd.io/product/architecture/adr-list/adr-001-cheqd-did-method) method. The implementation resolves DIDs via gRPC network requests to the configured nodes. Default nodes for cheqd's `mainnet` & `testnet` can be used, or custom nodes can be opt-in by supplying a different gRPC URL configuration. -TODO - explain dev maintainence of generated protos \ No newline at end of file +The implementations in this crate are largely inspired from cheqd's own typescript [sdk](https://github.com/cheqd/sdk/blob/main/src/modules/did.ts). + +This crate uses gRPC types and clients generated using [tonic](https://github.com/hyperium/tonic). The generated rust code is checked-in to this repository for monitoring, [see here](./src/proto/mod.rs). These generated rust files are checked-in alongside the V2 cheqd proto files & dependencies, [here](./cheqd_proto_gen/proto/), which are sourced from [cheqd's Buf registry](https://buf.build/cheqd/proto/docs). + +Since the generated code & proto files are not relatively large nor overwhelming in content, they are checked-in rather than pulled and/or generated at build time. The benefit is that the contents of the files can be monitored with each update, making supply-chain attacks obvious. The drawback is that it introduces some more manual maintainence. + +## Crate Maintainence +If there is an update to the `.proto` files, or `tonic` had a breaking update, the checked-in files may be due for a manual update. To do so, update any proto files in the [proto dir](./cheqd_proto_gen/proto/), then re-generate the rust files by using the [cheqd-proto-gen](./cheqd_proto_gen/) binary within this directory: +``` +cargo run --bin cheqd-proto-gen +``` \ No newline at end of file From d1692e1379946b93d8aa9862eabec19cc70b220f Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Tue, 26 Nov 2024 17:53:48 +1000 Subject: [PATCH 15/50] try bumping rust ver on vdrproxy Signed-off-by: George Mulhearn --- .github/ci/vdrproxy.dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ci/vdrproxy.dockerfile b/.github/ci/vdrproxy.dockerfile index 95c2b3da47..c5dc96ef1a 100644 --- a/.github/ci/vdrproxy.dockerfile +++ b/.github/ci/vdrproxy.dockerfile @@ -18,7 +18,7 @@ RUN apk update && apk upgrade && \ USER indy WORKDIR /home/indy -ARG RUST_VER="1.70.0" +ARG RUST_VER="1.79.0" RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain $RUST_VER --default-host x86_64-unknown-linux-musl ENV PATH="/home/indy/.cargo/bin:$PATH" From 8d46987b277915120208c1440e12116ff8543ff0 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Wed, 27 Nov 2024 08:25:52 +1000 Subject: [PATCH 16/50] lock auto update Signed-off-by: George Mulhearn --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 8e8adc90df..d60f27cf1a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5391,7 +5391,7 @@ dependencies = [ "indexmap 1.9.3", "pin-project", "pin-project-lite", - "rand 0.8.5", + "rand", "slab", "tokio", "tokio-util", From f0908aa2336e962cd6f16ea099b3d1b36736ea33 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Wed, 27 Nov 2024 10:45:25 +1000 Subject: [PATCH 17/50] readme updates Signed-off-by: George Mulhearn --- README.md | 1 + did_core/did_methods/did_cheqd/README.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 11a2560a82..0c868bdb99 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ The repository contains Rust crates to build - [`did_parser`](did_core/did_parser_nom) - Building and parsing [DIDs](https://w3c.github.io/did-core/) - [`did_peer`](did_core/did_methods/did_peer) - https://identity.foundation/peer-did-method-spec/ - [`did_sov`](did_core/did_methods/did_resolver_sov) - https://sovrin-foundation.github.io/sovrin/spec/did-method-spec-template.html + - [`did_cheqd`](did_core/did_methods/did_cheqd) - https://docs.cheqd.io/product/architecture/adr-list/adr-001-cheqd-did-method - [`did_web`](did_core/did_methods/did_resolver_web) - https://w3c-ccg.github.io/did-method-web/ - [`did_key`](did_core/did_methods/did_key) - https://w3c-ccg.github.io/did-method-key/ diff --git a/did_core/did_methods/did_cheqd/README.md b/did_core/did_methods/did_cheqd/README.md index f609b759e8..3c62ecd4e6 100644 --- a/did_core/did_methods/did_cheqd/README.md +++ b/did_core/did_methods/did_cheqd/README.md @@ -5,7 +5,7 @@ The implementations in this crate are largely inspired from cheqd's own typescri This crate uses gRPC types and clients generated using [tonic](https://github.com/hyperium/tonic). The generated rust code is checked-in to this repository for monitoring, [see here](./src/proto/mod.rs). These generated rust files are checked-in alongside the V2 cheqd proto files & dependencies, [here](./cheqd_proto_gen/proto/), which are sourced from [cheqd's Buf registry](https://buf.build/cheqd/proto/docs). -Since the generated code & proto files are not relatively large nor overwhelming in content, they are checked-in rather than pulled and/or generated at build time. The benefit is that the contents of the files can be monitored with each update, making supply-chain attacks obvious. The drawback is that it introduces some more manual maintainence. +Since the generated code & proto files are not relatively large nor overwhelming in content, they are checked-in rather than pulled and/or generated at build time. The benefit is that the contents of the files can be monitored with each update, making supply-chain attacks obvious. It also reduces the build time complexity for consumers - such as reducing requirements for any 3rd party build tools to be installed (`protobuf`). The drawback is that it introduces some more manual maintainence. ## Crate Maintainence If there is an update to the `.proto` files, or `tonic` had a breaking update, the checked-in files may be due for a manual update. To do so, update any proto files in the [proto dir](./cheqd_proto_gen/proto/), then re-generate the rust files by using the [cheqd-proto-gen](./cheqd_proto_gen/) binary within this directory: From cb57bc9887678608e34573997dddb2cad9870fb2 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Wed, 27 Nov 2024 11:52:30 +1000 Subject: [PATCH 18/50] remove some debugs Signed-off-by: George Mulhearn --- aries/messages/src/msg_types/protocols/did_exchange.rs | 1 - did_core/did_methods/did_cheqd/src/resolution/resolver.rs | 1 - .../did_methods/did_peer/src/peer_did/numalgos/numalgo2/mod.rs | 1 - 3 files changed, 3 deletions(-) diff --git a/aries/messages/src/msg_types/protocols/did_exchange.rs b/aries/messages/src/msg_types/protocols/did_exchange.rs index ff9eb294e1..e73567c96d 100644 --- a/aries/messages/src/msg_types/protocols/did_exchange.rs +++ b/aries/messages/src/msg_types/protocols/did_exchange.rs @@ -64,7 +64,6 @@ mod tests { #[test] fn test_protocol_didexchange_v1_1() { let x = Protocol::from(DidExchangeTypeV1::new_v1_1()); - dbg!(x); test_utils::test_serde( Protocol::from(DidExchangeTypeV1::new_v1_1()), json!("https://didcomm.org/didexchange/1.1"), diff --git a/did_core/did_methods/did_cheqd/src/resolution/resolver.rs b/did_core/did_methods/did_cheqd/src/resolution/resolver.rs index 3cbc69abb1..a91db7ac7f 100644 --- a/did_core/did_methods/did_cheqd/src/resolution/resolver.rs +++ b/did_core/did_methods/did_cheqd/src/resolution/resolver.rs @@ -136,7 +136,6 @@ impl DidCheqdResolver { let query_doc_res = query_response.value.ok_or(DidCheqdError::InvalidResponse( "DIDDoc query did not return a value".into(), ))?; - dbg!(&query_doc_res); let query_doc = query_doc_res.did_doc.ok_or(DidCheqdError::InvalidResponse( "DIDDoc query did not return a DIDDoc".into(), ))?; diff --git a/did_core/did_methods/did_peer/src/peer_did/numalgos/numalgo2/mod.rs b/did_core/did_methods/did_peer/src/peer_did/numalgos/numalgo2/mod.rs index 49d70f189a..bff5e7a5e9 100644 --- a/did_core/did_methods/did_peer/src/peer_did/numalgos/numalgo2/mod.rs +++ b/did_core/did_methods/did_peer/src/peer_did/numalgos/numalgo2/mod.rs @@ -123,7 +123,6 @@ mod test { let ddo_decoded: DidDocument = did_peer .to_did_doc_builder(PublicKeyEncoding::Multibase) .unwrap(); - dbg!(&ddo_decoded); assert_eq!(ddo_original, ddo_decoded); } From e722982e32e2c6fd1d7c5916f4aa8eceb02f623c Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Wed, 27 Nov 2024 14:52:09 +1000 Subject: [PATCH 19/50] more error info Signed-off-by: George Mulhearn --- did_core/did_methods/did_cheqd/src/resolution/resolver.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/did_core/did_methods/did_cheqd/src/resolution/resolver.rs b/did_core/did_methods/did_cheqd/src/resolution/resolver.rs index a91db7ac7f..858c7a7034 100644 --- a/did_core/did_methods/did_cheqd/src/resolution/resolver.rs +++ b/did_core/did_methods/did_cheqd/src/resolution/resolver.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::{collections::HashMap, error::Error}; use async_trait::async_trait; use did_resolver::{ @@ -107,7 +107,7 @@ impl DidCheqdResolver { // initialize new let conn = Endpoint::new(network_config.grpc_url.clone()) - .map_err(|e| DidCheqdError::BadConfiguration(e.to_string()))? + .map_err(|e| DidCheqdError::BadConfiguration(format!("{e} {:?}", e.source())))? .connect() .await?; From fd2c00950da6e8cff6640437fddf1879ae1cc935 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Wed, 27 Nov 2024 16:14:29 +1000 Subject: [PATCH 20/50] updated hyper in did:web. fixes clients Signed-off-by: George Mulhearn --- Cargo.lock | 45 ++++++--------- .../did_methods/did_resolver_web/Cargo.toml | 14 +++-- .../did_resolver_web/src/error/mod.rs | 6 +- .../src/resolution/resolver.rs | 22 +++++-- .../did_resolver_web/tests/resolution.rs | 57 +++++++++++++++---- 5 files changed, 92 insertions(+), 52 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d60f27cf1a..205ebe6e06 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -853,7 +853,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.1", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.1", "hyper-util", "itoa", "matchit", @@ -1872,8 +1872,10 @@ version = "0.1.0" dependencies = [ "async-trait", "did_resolver", - "hyper 0.14.30", - "hyper-tls 0.5.0", + "http-body-util", + "hyper 1.5.1", + "hyper-tls", + "hyper-util", "serde_json", "thiserror", "tokio", @@ -2722,9 +2724,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.30" +version = "0.14.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" +checksum = "8c08302e8fa335b151b788c775ff56e7a03ae64ff85c548ee820fecb70356e85" dependencies = [ "bytes", "futures-channel", @@ -2746,9 +2748,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.4.1" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "97818827ef4f364230e16705d4706e2897df2bb60617d6ca15d598025a3c481f" dependencies = [ "bytes", "futures-channel", @@ -2773,7 +2775,7 @@ checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ "futures-util", "http 1.1.0", - "hyper 1.4.1", + "hyper 1.5.1", "hyper-util", "rustls 0.23.13", "rustls-pki-types", @@ -2788,26 +2790,13 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" dependencies = [ - "hyper 1.4.1", + "hyper 1.5.1", "hyper-util", "pin-project-lite", "tokio", "tower-service", ] -[[package]] -name = "hyper-tls" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" -dependencies = [ - "bytes", - "hyper 0.14.30", - "native-tls", - "tokio", - "tokio-native-tls", -] - [[package]] name = "hyper-tls" version = "0.6.0" @@ -2816,7 +2805,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.1", "hyper-util", "native-tls", "tokio", @@ -2835,7 +2824,7 @@ dependencies = [ "futures-util", "http 1.1.0", "http-body 1.0.1", - "hyper 1.4.1", + "hyper 1.5.1", "pin-project-lite", "socket2", "tokio", @@ -4131,7 +4120,7 @@ dependencies = [ "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.30", + "hyper 0.14.31", "ipnet", "js-sys", "log", @@ -4169,9 +4158,9 @@ dependencies = [ "http 1.1.0", "http-body 1.0.1", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.1", "hyper-rustls", - "hyper-tls 0.6.0", + "hyper-tls", "hyper-util", "ipnet", "js-sys", @@ -5349,7 +5338,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.1", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.1", "hyper-timeout", "hyper-util", "percent-encoding", diff --git a/did_core/did_methods/did_resolver_web/Cargo.toml b/did_core/did_methods/did_resolver_web/Cargo.toml index eb4c6f1ee5..16cd429759 100644 --- a/did_core/did_methods/did_resolver_web/Cargo.toml +++ b/did_core/did_methods/did_resolver_web/Cargo.toml @@ -10,10 +10,16 @@ did_resolver = { path = "../../did_resolver" } async-trait = "0.1.68" serde_json = "1.0.96" thiserror = "1.0.40" -hyper = { version = "0.14.26", features = ["client", "http2"] } -hyper-tls = "0.5.0" +hyper = { version = "1.5.1" } +hyper-tls = "0.6.0" +hyper-util = { version = "0.1.10", features = ["client-legacy", "http1", "http2"] } +http-body-util = "0.1.2" [dev-dependencies] -hyper = { version = "0.14.26", features = ["server"] } -tokio = { version = "1.38.0", default-features = false, features = ["macros", "rt"] } +hyper = { version = "1.5.1", features = ["server"] } +hyper-util = { version = "0.1.10", features = ["server"] } +tokio = { version = "1.38.0", default-features = false, features = [ + "macros", + "rt", +] } tokio-test = "0.4.2" diff --git a/did_core/did_methods/did_resolver_web/src/error/mod.rs b/did_core/did_methods/did_resolver_web/src/error/mod.rs index be189d6ed3..5532aa2c28 100644 --- a/did_core/did_methods/did_resolver_web/src/error/mod.rs +++ b/did_core/did_methods/did_resolver_web/src/error/mod.rs @@ -16,8 +16,10 @@ pub enum DidWebError { InvalidDid(String), #[error("Parsing error: {0}")] ParsingError(#[from] ParsingErrorSource), - #[error("URL parsing error: {0}")] - HttpError(#[from] hyper::Error), + #[error("Network error: {0}")] + NetworkError(#[from] hyper::Error), + #[error("Network error: {0}")] + NetworkClientError(#[from] hyper_util::client::legacy::Error), #[error("Non-success server response: {0}")] NonSuccessResponse(StatusCode), #[error(transparent)] diff --git a/did_core/did_methods/did_resolver_web/src/resolution/resolver.rs b/did_core/did_methods/did_resolver_web/src/resolution/resolver.rs index bbd19497d6..d7494c9bc7 100644 --- a/did_core/did_methods/did_resolver_web/src/resolution/resolver.rs +++ b/did_core/did_methods/did_resolver_web/src/resolution/resolver.rs @@ -8,12 +8,20 @@ use did_resolver::{ DidResolvable, }, }; +use http_body_util::{combinators::BoxBody, BodyExt as _}; use hyper::{ - client::{connect::Connect, HttpConnector}, + body::Bytes, http::uri::{self, Scheme}, - Body, Client, Uri, + Uri, }; use hyper_tls::HttpsConnector; +use hyper_util::{ + client::legacy::{ + connect::{Connect, HttpConnector}, + Client, + }, + rt::TokioExecutor, +}; use crate::error::DidWebError; @@ -21,14 +29,15 @@ pub struct DidWebResolver where C: Connect + Send + Sync + Clone + 'static, { - client: Client, + client: Client>, scheme: Scheme, } impl DidWebResolver { pub fn http() -> DidWebResolver { DidWebResolver { - client: Client::builder().build::<_, Body>(HttpConnector::new()), + client: Client::builder(TokioExecutor::new()) + .build::<_, BoxBody>(HttpConnector::new()), scheme: Scheme::HTTP, } } @@ -37,7 +46,8 @@ impl DidWebResolver { impl DidWebResolver> { pub fn https() -> DidWebResolver> { DidWebResolver { - client: Client::builder().build::<_, Body>(HttpsConnector::new()), + client: Client::builder(TokioExecutor::new()) + .build::<_, BoxBody>(HttpsConnector::new()), scheme: Scheme::HTTPS, } } @@ -54,7 +64,7 @@ where return Err(DidWebError::NonSuccessResponse(res.status())); } - let body = hyper::body::to_bytes(res.into_body()).await?; + let body = res.into_body().collect().await?.to_bytes(); String::from_utf8(body.to_vec()).map_err(|err| err.into()) } diff --git a/did_core/did_methods/did_resolver_web/tests/resolution.rs b/did_core/did_methods/did_resolver_web/tests/resolution.rs index 76681c8cf3..65949563a3 100644 --- a/did_core/did_methods/did_resolver_web/tests/resolution.rs +++ b/did_core/did_methods/did_resolver_web/tests/resolution.rs @@ -1,4 +1,4 @@ -use std::{convert::Infallible, net::SocketAddr}; +use std::convert::Infallible; use did_resolver::{ did_doc::schema::did_doc::DidDocument, @@ -6,10 +6,17 @@ use did_resolver::{ traits::resolvable::{resolution_output::DidResolutionOutput, DidResolvable}, }; use did_resolver_web::resolution::resolver::DidWebResolver; +use http_body_util::{combinators::BoxBody, BodyExt, Full}; use hyper::{ - service::{make_service_fn, service_fn}, - Body, Request, Response, Server, + body::{Bytes, Incoming}, + service::service_fn, + Request, Response, }; +use hyper_util::{ + rt::{TokioExecutor, TokioIo}, + server::conn::auto::Builder, +}; +use tokio::{net::TcpListener, task::JoinSet}; use tokio_test::assert_ok; const DID_DOCUMENT: &str = r#" @@ -66,12 +73,16 @@ const DID_DOCUMENT: &str = r#" ] }"#; -async fn mock_server_handler(req: Request) -> Result, Infallible> { +async fn mock_server_handler( + req: Request, +) -> Result>, Infallible> { let response = match req.uri().path() { - "/.well-known/did.json" | "/user/alice/did.json" => Response::new(Body::from(DID_DOCUMENT)), + "/.well-known/did.json" | "/user/alice/did.json" => { + Response::new(Full::new(Bytes::from(DID_DOCUMENT)).boxed()) + } _ => Response::builder() .status(404) - .body(Body::from("Not Found")) + .body(Full::new(Bytes::from("Not Found")).boxed()) .unwrap(), }; @@ -79,14 +90,36 @@ async fn mock_server_handler(req: Request) -> Result, Infal } async fn create_mock_server(port: u16) -> String { - let make_svc = - make_service_fn(|_conn| async { Ok::<_, Infallible>(service_fn(mock_server_handler)) }); - - let addr = SocketAddr::from(([127, 0, 0, 1], port)); - let server = Server::bind(&addr).serve(make_svc); + let listen_addr = format!("127.0.0.1:{port}"); + let tcp_listener = TcpListener::bind(listen_addr).await.unwrap(); tokio::spawn(async move { - server.await.unwrap(); + let mut join_set = JoinSet::new(); + loop { + let (stream, addr) = match tcp_listener.accept().await { + Ok(x) => x, + Err(e) => { + eprintln!("failed to accept connection: {e}"); + continue; + } + }; + + let serve_connection = async move { + println!("handling a request from {addr}"); + + let result = Builder::new(TokioExecutor::new()) + .serve_connection(TokioIo::new(stream), service_fn(mock_server_handler)) + .await; + + if let Err(e) = result { + eprintln!("error serving {addr}: {e}"); + } + + println!("handled a request from {addr}"); + }; + + join_set.spawn(serve_connection); + } }); "localhost".to_string() From 25c10ee9bfe152a47982e5ce0e8498acc8f9c032 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Mon, 2 Dec 2024 09:52:36 +1000 Subject: [PATCH 21/50] fix up tls. works on android Signed-off-by: George Mulhearn --- Cargo.lock | 57 ++++-------------- .../src/msg_types/protocols/did_exchange.rs | 1 - did_core/did_methods/did_cheqd/Cargo.toml | 6 +- .../did_cheqd/src/resolution/resolver.rs | 58 +++++++++++++++---- 4 files changed, 63 insertions(+), 59 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 205ebe6e06..84f3967e40 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1087,9 +1087,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "bytestring" @@ -1367,16 +1367,6 @@ dependencies = [ "libc", ] -[[package]] -name = "core-foundation" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -1734,8 +1724,13 @@ name = "did_cheqd" version = "0.1.0" dependencies = [ "async-trait", + "bytes", "chrono", "did_resolver", + "http-body-util", + "hyper-tls", + "hyper-util", + "native-tls", "prost", "prost-types", "serde", @@ -3394,7 +3389,7 @@ dependencies = [ "openssl-probe", "openssl-sys", "schannel", - "security-framework 2.11.1", + "security-framework", "security-framework-sys", "tempfile", ] @@ -4299,27 +4294,13 @@ version = "0.23.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" dependencies = [ - "log", "once_cell", - "ring", "rustls-pki-types", "rustls-webpki 0.102.8", "subtle", "zeroize", ] -[[package]] -name = "rustls-native-certs" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" -dependencies = [ - "openssl-probe", - "rustls-pki-types", - "schannel", - "security-framework 3.0.1", -] - [[package]] name = "rustls-pemfile" version = "1.0.4" @@ -4451,20 +4432,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ "bitflags 2.6.0", - "core-foundation 0.9.4", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1415a607e92bec364ea2cf9264646dcce0f91e6d65281bd6f2819cca3bf39c8" -dependencies = [ - "bitflags 2.6.0", - "core-foundation 0.10.0", + "core-foundation", "core-foundation-sys", "libc", "security-framework-sys", @@ -5052,7 +5020,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", - "core-foundation 0.9.4", + "core-foundation", "system-configuration-sys 0.5.0", ] @@ -5063,7 +5031,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ "bitflags 2.6.0", - "core-foundation 0.9.4", + "core-foundation", "system-configuration-sys 0.6.0", ] @@ -5344,10 +5312,7 @@ dependencies = [ "percent-encoding", "pin-project", "prost", - "rustls-native-certs", - "rustls-pemfile 2.2.0", "tokio", - "tokio-rustls", "tokio-stream", "tower 0.4.13", "tower-layer", diff --git a/aries/messages/src/msg_types/protocols/did_exchange.rs b/aries/messages/src/msg_types/protocols/did_exchange.rs index e73567c96d..8f5d522ef2 100644 --- a/aries/messages/src/msg_types/protocols/did_exchange.rs +++ b/aries/messages/src/msg_types/protocols/did_exchange.rs @@ -63,7 +63,6 @@ mod tests { #[test] fn test_protocol_didexchange_v1_1() { - let x = Protocol::from(DidExchangeTypeV1::new_v1_1()); test_utils::test_serde( Protocol::from(DidExchangeTypeV1::new_v1_1()), json!("https://didcomm.org/didexchange/1.1"), diff --git a/did_core/did_methods/did_cheqd/Cargo.toml b/did_core/did_methods/did_cheqd/Cargo.toml index 4a5dc294b2..371e6724f2 100644 --- a/did_core/did_methods/did_cheqd/Cargo.toml +++ b/did_core/did_methods/did_cheqd/Cargo.toml @@ -16,10 +16,13 @@ tonic = { version = "0.12.3", default-features = false, features = [ "codegen", "prost", "channel", - "tls-native-roots", ] } prost = { version = "0.13.3", default-features = false } prost-types = "0.13.3" +native-tls = { version = "0.2.12", features = ["alpn"] } +hyper-tls = "0.6.0" +hyper-util = { version = "0.1.10", features = ["client-legacy", "http2"] } +http-body-util = "0.1.2" async-trait = "0.1.68" serde_json = "1.0.96" serde = { version = "1.0.160", features = ["derive"] } @@ -27,6 +30,7 @@ thiserror = "1.0.40" tokio = { version = "1.38.0" } chrono = { version = "0.4.24", default-features = false } url = { version = "2.3.1", default-features = false } +bytes = "1.8.0" [dev-dependencies] tokio = { version = "1.38.0", default-features = false, features = [ diff --git a/did_core/did_methods/did_cheqd/src/resolution/resolver.rs b/did_core/did_methods/did_cheqd/src/resolution/resolver.rs index 858c7a7034..2e3d6f7574 100644 --- a/did_core/did_methods/did_cheqd/src/resolution/resolver.rs +++ b/did_core/did_methods/did_cheqd/src/resolution/resolver.rs @@ -1,6 +1,7 @@ -use std::{collections::HashMap, error::Error}; +use std::{collections::HashMap, str::FromStr}; use async_trait::async_trait; +use bytes::Bytes; use did_resolver::{ did_doc::schema::did_doc::DidDocument, did_parser_nom::Did, @@ -8,8 +9,14 @@ use did_resolver::{ shared_types::did_document_metadata::DidDocumentMetadata, traits::resolvable::{resolution_output::DidResolutionOutput, DidResolvable}, }; +use http_body_util::combinators::UnsyncBoxBody; +use hyper_tls::HttpsConnector; +use hyper_util::{ + client::legacy::{connect::HttpConnector, Client}, + rt::TokioExecutor, +}; use tokio::sync::Mutex; -use tonic::transport::{Channel, Endpoint}; +use tonic::{transport::Uri, Status}; use crate::{ error::{DidCheqdError, DidCheqdResult}, @@ -60,10 +67,12 @@ impl NetworkConfiguration { } } +type HyperClient = Client, UnsyncBoxBody>; + #[derive(Clone)] struct CheqdGrpcClient { - did: DidQueryClient, - _resources: ResourceQueryClient, + did: DidQueryClient, + _resources: ResourceQueryClient, } pub struct DidCheqdResolver { @@ -105,14 +114,16 @@ impl DidCheqdResolver { .find(|n| n.namespace == network) .ok_or(DidCheqdError::NetworkNotSupported(network.to_owned()))?; - // initialize new - let conn = Endpoint::new(network_config.grpc_url.clone()) - .map_err(|e| DidCheqdError::BadConfiguration(format!("{e} {:?}", e.source())))? - .connect() - .await?; + let client = native_tls_hyper_client()?; + let origin = Uri::from_str(&network_config.grpc_url).map_err(|e| { + DidCheqdError::BadConfiguration(format!( + "GRPC URL is not a URI: {} {e}", + network_config.grpc_url + )) + })?; - let did_client = DidQueryClient::new(conn.clone()); - let resource_client = ResourceQueryClient::new(conn); + let did_client = DidQueryClient::with_origin(client.clone(), origin.clone()); + let resource_client = ResourceQueryClient::with_origin(client, origin); let client = CheqdGrpcClient { did: did_client, @@ -124,7 +135,13 @@ impl DidCheqdResolver { Ok(client) } + /// Resolve a cheqd DID. pub async fn resolve_did(&self, did: &Did) -> DidCheqdResult { + let method = did.method(); + if method != Some("cheqd") { + return Err(DidCheqdError::MethodNotSupported(format!("{method:?}"))); + } + let network = did.namespace().unwrap_or(MAINNET_NAMESPACE); let mut client = self.client_for_network(network).await?; let did = did.did().to_owned(); @@ -151,3 +168,22 @@ impl DidCheqdResolver { Ok(output_builder.build()) } } + +/// Assembles a hyper client which: +/// * uses native TLS +/// * supports HTTP2 only (gRPC) +fn native_tls_hyper_client() -> DidCheqdResult { + let tls = native_tls::TlsConnector::builder() + .request_alpns(&["h2"]) + .build() + .map_err(|e| { + DidCheqdError::BadConfiguration(format!("Failed to build TlsConnector: {e}")) + })?; + let mut http = HttpConnector::new(); + http.enforce_http(false); + let connector = HttpsConnector::from((http, tls.into())); + + Ok(Client::builder(TokioExecutor::new()) + .http2_only(true) + .build(connector)) +} From b3e183e89368e3d9a0d0f9ab61f301092da37748 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Mon, 2 Dec 2024 10:19:12 +1000 Subject: [PATCH 22/50] some cleaning Signed-off-by: George Mulhearn --- .../did_cheqd/src/resolution/resolver.rs | 70 ++++++++++++++++--- 1 file changed, 61 insertions(+), 9 deletions(-) diff --git a/did_core/did_methods/did_cheqd/src/resolution/resolver.rs b/did_core/did_methods/did_cheqd/src/resolution/resolver.rs index 2e3d6f7574..4b063e35db 100644 --- a/did_core/did_methods/did_cheqd/src/resolution/resolver.rs +++ b/did_core/did_methods/did_cheqd/src/resolution/resolver.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, str::FromStr}; +use std::collections::HashMap; use async_trait::async_trait; use bytes::Bytes; @@ -26,13 +26,19 @@ use crate::{ }, }; -const MAINNET_NAMESPACE: &str = "mainnet"; -const MAINNET_DEFAULT_GRPC: &str = "https://grpc.cheqd.net:443"; -const TESTNET_NAMESPACE: &str = "testnet"; -const TESTNET_DEFAULT_GRPC: &str = "https://grpc.cheqd.network:443"; +/// default namespace for the cheqd "mainnet". as it would appear in a DID. +pub const MAINNET_NAMESPACE: &str = "mainnet"; +/// default gRPC URL for the cheqd "mainnet". +pub const MAINNET_DEFAULT_GRPC: &str = "https://grpc.cheqd.net:443"; +/// default namespace for the cheqd "testnet". as it would appear in a DID. +pub const TESTNET_NAMESPACE: &str = "testnet"; +/// default gRPC URL for the cheqd "testnet". +pub const TESTNET_DEFAULT_GRPC: &str = "https://grpc.cheqd.network:443"; +/// Configuration for the [DidCheqdResolver] resolver pub struct DidCheqdResolverConfiguration { - networks: Vec, + /// Configuration for which networks are resolvable + pub networks: Vec, } impl Default for DidCheqdResolverConfiguration { @@ -46,12 +52,16 @@ impl Default for DidCheqdResolverConfiguration { } } +/// Configuration for a cheqd network. Defining details such as where to resolve DIDs from. pub struct NetworkConfiguration { - grpc_url: String, - namespace: String, + /// the cheqd nodes gRPC URL + pub grpc_url: String, + /// the namespace of the network - as it would appear in a DID (did:cheqd:namespace:123) + pub namespace: String, } impl NetworkConfiguration { + /// default configuration for cheqd mainnet pub fn mainnet() -> Self { Self { grpc_url: String::from(MAINNET_DEFAULT_GRPC), @@ -59,6 +69,7 @@ impl NetworkConfiguration { } } + /// default configuration for cheqd testnet pub fn testnet() -> Self { Self { grpc_url: String::from(TESTNET_DEFAULT_GRPC), @@ -72,6 +83,7 @@ type HyperClient = Client, UnsyncBoxBody, + // FUTURE - not used yet _resources: ResourceQueryClient, } @@ -94,6 +106,10 @@ impl DidResolvable for DidCheqdResolver { } impl DidCheqdResolver { + /// Assemble a new resolver with the given config. + /// + /// [DidCheqdResolverConfiguration::default] can be used if default mainnet & testnet + /// configurations are suitable. pub fn new(configuration: DidCheqdResolverConfiguration) -> Self { Self { networks: configuration.networks, @@ -115,7 +131,7 @@ impl DidCheqdResolver { .ok_or(DidCheqdError::NetworkNotSupported(network.to_owned()))?; let client = native_tls_hyper_client()?; - let origin = Uri::from_str(&network_config.grpc_url).map_err(|e| { + let origin: Uri = network_config.grpc_url.parse().map_err(|e| { DidCheqdError::BadConfiguration(format!( "GRPC URL is not a URI: {} {e}", network_config.grpc_url @@ -187,3 +203,39 @@ fn native_tls_hyper_client() -> DidCheqdResult { .http2_only(true) .build(connector)) } + +#[cfg(test)] +mod unit_tests { + use super::*; + + #[tokio::test] + async fn test_resolve_fails_if_wrong_method() { + let did = "did:notcheqd:abc".parse().unwrap(); + let resolver = DidCheqdResolver::new(Default::default()); + let e = resolver.resolve_did(&did).await.unwrap_err(); + assert!(matches!(e, DidCheqdError::MethodNotSupported(_))); + } + + #[tokio::test] + async fn test_resolve_fails_if_no_network_config() { + let did = "did:cheqd:devnet:Ps1ysXP2Ae6GBfxNhNQNKN".parse().unwrap(); + let resolver = DidCheqdResolver::new(Default::default()); + let e = resolver.resolve_did(&did).await.unwrap_err(); + assert!(matches!(e, DidCheqdError::NetworkNotSupported(_))); + } + + #[tokio::test] + async fn test_resolve_fails_if_bad_network_uri() { + let did = "did:cheqd:devnet:Ps1ysXP2Ae6GBfxNhNQNKN".parse().unwrap(); + let config = DidCheqdResolverConfiguration { + networks: vec![NetworkConfiguration { + grpc_url: "@baduri://.".into(), + namespace: "devnet".into(), + }], + }; + + let resolver = DidCheqdResolver::new(config); + let e = resolver.resolve_did(&did).await.unwrap_err(); + assert!(matches!(e, DidCheqdError::BadConfiguration(_))); + } +} From ecb736ce591183ce73b024bc7851fbbef801d90f Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Tue, 3 Dec 2024 13:29:15 +1000 Subject: [PATCH 23/50] begin. schema & cred def working in edge agent test Signed-off-by: George Mulhearn --- Cargo.lock | 2 + aries/aries_vcx/src/errors/mapping_ledger.rs | 2 +- aries/aries_vcx_ledger/Cargo.toml | 7 +- aries/aries_vcx_ledger/src/errors/error.rs | 4 +- .../src/errors/mapping_cheqd.rs | 31 ++++ .../src/errors/mapping_indyvdr.rs | 2 +- .../src/errors/mapping_indyvdr_proxy.rs | 4 +- .../errors/mapping_ledger_response_parser.rs | 2 +- aries/aries_vcx_ledger/src/errors/mod.rs | 2 + .../aries_vcx_ledger/src/ledger/cheqd/mod.rs | 155 ++++++++++++++++++ .../src/ledger/cheqd/models.rs | 37 +++++ .../src/ledger/indy_vdr_ledger.rs | 2 +- aries/aries_vcx_ledger/src/ledger/mod.rs | 2 + .../cred_issuance/v2/issue_credential.rs | 2 + .../cred_issuance/v2/offer_credential.rs | 2 + .../cred_issuance/v2/propose_credential.rs | 2 + .../cred_issuance/v2/request_credential.rs | 2 + .../did_methods/did_cheqd/src/error/mod.rs | 2 + .../did_cheqd/src/resolution/resolver.rs | 70 +++++++- 19 files changed, 317 insertions(+), 15 deletions(-) create mode 100644 aries/aries_vcx_ledger/src/errors/mapping_cheqd.rs create mode 100644 aries/aries_vcx_ledger/src/ledger/cheqd/mod.rs create mode 100644 aries/aries_vcx_ledger/src/ledger/cheqd/models.rs diff --git a/Cargo.lock b/Cargo.lock index 84f3967e40..63206dfb1f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -603,6 +603,8 @@ dependencies = [ "anoncreds_types", "aries_vcx_wallet", "async-trait", + "chrono", + "did_cheqd", "did_parser_nom", "indy-ledger-response-parser", "indy-vdr", diff --git a/aries/aries_vcx/src/errors/mapping_ledger.rs b/aries/aries_vcx/src/errors/mapping_ledger.rs index deacc40b9a..229afc49ee 100644 --- a/aries/aries_vcx/src/errors/mapping_ledger.rs +++ b/aries/aries_vcx/src/errors/mapping_ledger.rs @@ -8,7 +8,7 @@ impl From for AriesVcxError { VcxLedgerError::LedgerItemNotFound => { Self::from_msg(AriesVcxErrorKind::LedgerItemNotFound, value) } - VcxLedgerError::InvalidLedgerResponse => { + VcxLedgerError::InvalidLedgerResponse(_) => { Self::from_msg(AriesVcxErrorKind::InvalidLedgerResponse, value) } VcxLedgerError::DuplicationSchema => { diff --git a/aries/aries_vcx_ledger/Cargo.toml b/aries/aries_vcx_ledger/Cargo.toml index d5a726ee86..153c9df51e 100644 --- a/aries/aries_vcx_ledger/Cargo.toml +++ b/aries/aries_vcx_ledger/Cargo.toml @@ -9,6 +9,7 @@ edition.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] vdr_proxy_ledger = ["dep:indy-vdr-proxy-client"] +cheqd = ["dep:did_cheqd"] [dependencies] aries_vcx_wallet = { path = "../aries_vcx_wallet" } @@ -17,12 +18,14 @@ did_parser_nom = { path = "../../did_core/did_parser_nom" } thiserror = "1.0.40" indy-vdr.workspace = true indy-vdr-proxy-client = { workspace = true, optional = true } +did_cheqd = { path = "../../did_core/did_methods/did_cheqd", optional = true } serde_json = "1.0.95" -public_key = { path = "../../did_core/public_key"} +public_key = { path = "../../did_core/public_key" } async-trait = "0.1.68" time = "0.3.20" indy-ledger-response-parser = { path = "../misc/indy_ledger_response_parser" } log = "0.4.17" serde = { version = "1.0.159", features = ["derive"] } -lru = { version = "0.12.0" } +lru = { version = "0.12.0" } tokio = { version = "1.38" } +chrono = { version = "0.4", default-features = false } diff --git a/aries/aries_vcx_ledger/src/errors/error.rs b/aries/aries_vcx_ledger/src/errors/error.rs index 9031cfdda4..826607c706 100644 --- a/aries/aries_vcx_ledger/src/errors/error.rs +++ b/aries/aries_vcx_ledger/src/errors/error.rs @@ -15,8 +15,8 @@ pub enum VcxLedgerError { IOError(#[source] VdrError), #[error("Ledger item not found")] LedgerItemNotFound, - #[error("Invalid ledger response")] - InvalidLedgerResponse, + #[error("Invalid ledger response {0}")] + InvalidLedgerResponse(String), #[error("Duplicated schema")] DuplicationSchema, #[error("Invalid JSON: {0}")] diff --git a/aries/aries_vcx_ledger/src/errors/mapping_cheqd.rs b/aries/aries_vcx_ledger/src/errors/mapping_cheqd.rs new file mode 100644 index 0000000000..5d00b7cec8 --- /dev/null +++ b/aries/aries_vcx_ledger/src/errors/mapping_cheqd.rs @@ -0,0 +1,31 @@ +use did_cheqd::error::{parsing::ParsingErrorSource, DidCheqdError}; + +use super::error::VcxLedgerError; + +impl From for VcxLedgerError { + fn from(value: DidCheqdError) -> Self { + match value { + DidCheqdError::MethodNotSupported(_) => VcxLedgerError::InvalidInput(value.to_string()), + DidCheqdError::NetworkNotSupported(_) => { + VcxLedgerError::InvalidInput(value.to_string()) + } + DidCheqdError::BadConfiguration(_) => VcxLedgerError::InvalidInput(value.to_string()), + DidCheqdError::TransportError(_) => { + VcxLedgerError::InvalidLedgerResponse(value.to_string()) + } + DidCheqdError::NonSuccessResponse(_) => { + VcxLedgerError::InvalidLedgerResponse(value.to_string()) + } + DidCheqdError::InvalidResponse(_) => { + VcxLedgerError::InvalidLedgerResponse(value.to_string()) + } + DidCheqdError::InvalidDidDocument(_) => VcxLedgerError::InvalidInput(value.to_string()), + DidCheqdError::InvalidDidUrl(_) => VcxLedgerError::InvalidInput(value.to_string()), + DidCheqdError::ParsingError(ParsingErrorSource::DidDocumentParsingError(e)) => { + VcxLedgerError::ParseError(e) + } + DidCheqdError::Other(_) => VcxLedgerError::UnknownError(value.to_string()), + _ => todo!(), + } + } +} diff --git a/aries/aries_vcx_ledger/src/errors/mapping_indyvdr.rs b/aries/aries_vcx_ledger/src/errors/mapping_indyvdr.rs index fd28bf51e5..9c4cbf0957 100644 --- a/aries/aries_vcx_ledger/src/errors/mapping_indyvdr.rs +++ b/aries/aries_vcx_ledger/src/errors/mapping_indyvdr.rs @@ -19,7 +19,7 @@ impl From for VcxLedgerError { | VdrErrorKind::PoolNoConsensus | VdrErrorKind::Resolver | VdrErrorKind::PoolTimeout => Self::UnknownError(err.to_string()), - VdrErrorKind::PoolRequestFailed(_) => Self::InvalidLedgerResponse, + VdrErrorKind::PoolRequestFailed(_) => Self::InvalidLedgerResponse(err.to_string()), } } } diff --git a/aries/aries_vcx_ledger/src/errors/mapping_indyvdr_proxy.rs b/aries/aries_vcx_ledger/src/errors/mapping_indyvdr_proxy.rs index a1527997a4..afabe18fc0 100644 --- a/aries/aries_vcx_ledger/src/errors/mapping_indyvdr_proxy.rs +++ b/aries/aries_vcx_ledger/src/errors/mapping_indyvdr_proxy.rs @@ -3,7 +3,7 @@ use indy_vdr_proxy_client::error::VdrProxyClientError; use super::error::VcxLedgerError; impl From for VcxLedgerError { - fn from(_err: VdrProxyClientError) -> Self { - Self::InvalidLedgerResponse + fn from(err: VdrProxyClientError) -> Self { + Self::InvalidLedgerResponse(err.to_string()) } } diff --git a/aries/aries_vcx_ledger/src/errors/mapping_ledger_response_parser.rs b/aries/aries_vcx_ledger/src/errors/mapping_ledger_response_parser.rs index c895ec383f..d1831e7b6d 100644 --- a/aries/aries_vcx_ledger/src/errors/mapping_ledger_response_parser.rs +++ b/aries/aries_vcx_ledger/src/errors/mapping_ledger_response_parser.rs @@ -8,7 +8,7 @@ impl From for VcxLedgerError { LedgerResponseParserError::JsonError(err) => VcxLedgerError::InvalidJson(err), LedgerResponseParserError::LedgerItemNotFound(_) => VcxLedgerError::LedgerItemNotFound, LedgerResponseParserError::InvalidTransaction(_) => { - VcxLedgerError::InvalidLedgerResponse + VcxLedgerError::InvalidLedgerResponse(err.to_string()) } } } diff --git a/aries/aries_vcx_ledger/src/errors/mod.rs b/aries/aries_vcx_ledger/src/errors/mod.rs index 22f23fcf66..ba15f6fe37 100644 --- a/aries/aries_vcx_ledger/src/errors/mod.rs +++ b/aries/aries_vcx_ledger/src/errors/mod.rs @@ -1,4 +1,6 @@ pub mod error; +#[cfg(feature = "cheqd")] +mod mapping_cheqd; mod mapping_indyvdr; #[cfg(feature = "vdr_proxy_ledger")] mod mapping_indyvdr_proxy; diff --git a/aries/aries_vcx_ledger/src/ledger/cheqd/mod.rs b/aries/aries_vcx_ledger/src/ledger/cheqd/mod.rs new file mode 100644 index 0000000000..f45bbb3545 --- /dev/null +++ b/aries/aries_vcx_ledger/src/ledger/cheqd/mod.rs @@ -0,0 +1,155 @@ +use std::{fmt::Debug, sync::Arc}; + +use anoncreds_types::data_types::{ + identifiers::{ + cred_def_id::CredentialDefinitionId, issuer_id::IssuerId, + rev_reg_def_id::RevocationRegistryDefinitionId, schema_id::SchemaId, + }, + ledger::{ + cred_def::CredentialDefinition, + rev_reg::RevocationRegistry, + rev_reg_def::RevocationRegistryDefinition, + rev_reg_delta::RevocationRegistryDelta, + rev_status_list::RevocationStatusList, + schema::{AttributeNames, Schema}, + }, +}; +use async_trait::async_trait; +use chrono::{DateTime, Utc}; +use did_cheqd::resolution::resolver::DidCheqdResolver; +use did_parser_nom::{Did, DidUrl}; +use models::{ + CheqdAnoncredsCredentialDefinition, CheqdAnoncredsRevocationRegistryDefinition, + CheqdAnoncredsSchema, +}; + +use super::base_ledger::AnoncredsLedgerRead; +use crate::errors::error::{VcxLedgerError, VcxLedgerResult}; + +mod models; + +const STATUS_LIST_RESOURCE_TYPE: &str = "anonCredsStatusList"; + +pub struct CheqdAnoncredsLedgerRead { + resolver: Arc, +} + +impl CheqdAnoncredsLedgerRead { + pub fn new(resolver: Arc) -> Self { + Self { resolver } + } +} + +// TODO - issue with our anoncreds-types conversions - we are missing `issuerId`, so we make +// issuerId from the resource ID - which assumes it is a legacy sovrin identifier for the resource. +// i.e. split(":")[0]. FIX! we could fix the indyvdr type conversions to include the `issuerId`, and +// make `issuerId` required in our anoncreds-types UPDATE - actually ^, check what credo is doing + +#[async_trait] +impl AnoncredsLedgerRead for CheqdAnoncredsLedgerRead { + async fn get_schema(&self, schema_id: &SchemaId, _: Option<&Did>) -> VcxLedgerResult { + let url = DidUrl::parse(schema_id.to_string())?; + let resource = self.resolver.resolve_resource(&url).await?; + let data: CheqdAnoncredsSchema = serde_json::from_slice(&resource)?; + Ok(Schema { + id: schema_id.to_owned(), + seq_no: None, + name: data.name, + version: data.version, + attr_names: AttributeNames(data.attr_names), + issuer_id: extract_issuer_id(&url)?, + }) + } + + async fn get_cred_def( + &self, + cred_def_id: &CredentialDefinitionId, + _: Option<&Did>, + ) -> VcxLedgerResult { + let url = DidUrl::parse(cred_def_id.to_string())?; + let resource = self.resolver.resolve_resource(&url).await?; + let data: CheqdAnoncredsCredentialDefinition = serde_json::from_slice(&resource)?; + Ok(CredentialDefinition { + id: cred_def_id.to_owned(), + schema_id: data.schema_id, + signature_type: data.signature_type, + tag: data.tag, + value: data.value, + issuer_id: extract_issuer_id(&url)?, + }) + } + + async fn get_rev_reg_def_json( + &self, + rev_reg_id: &RevocationRegistryDefinitionId, + ) -> VcxLedgerResult { + let url = DidUrl::parse(rev_reg_id.to_string())?; + let resource = self.resolver.resolve_resource(&url).await?; + let data: CheqdAnoncredsRevocationRegistryDefinition = serde_json::from_slice(&resource)?; + Ok(RevocationRegistryDefinition { + id: rev_reg_id.to_owned(), + revoc_def_type: data.revoc_def_type, + tag: data.tag, + cred_def_id: data.cred_def_id, + value: data.value, + }) + } + + async fn get_rev_reg_delta_json( + &self, + rev_reg_id: &RevocationRegistryDefinitionId, + // TODO - explain why we ignore `from` + _from: Option, + to: Option, + ) -> VcxLedgerResult<(RevocationRegistryDelta, u64)> { + let url = DidUrl::parse(rev_reg_id.to_string())?; + let data = self.resolver.resolve_resource(&url).await?; + let rev_reg_def: RevocationRegistryDefinition = serde_json::from_slice(&data)?; + let name = rev_reg_def.tag; // TODO - credo-ts uses the metadata.name or fails (https://docs.cheqd.io/product/advanced/anoncreds/revocation-status-list#same-resource-name-different-resource-type) + + let did = url.did().ok_or(VcxLedgerError::InvalidInput(format!( + "DID URL missing DID {url}" + )))?; + + let resource_dt = to + .and_then(|epoch| DateTime::from_timestamp(epoch as i64, 0)) + .unwrap_or(Utc::now()); + let xml_dt = resource_dt.to_rfc3339_opts(chrono::SecondsFormat::Millis, true); + let query = format!( + "{did}?resourceType={STATUS_LIST_RESOURCE_TYPE}&resourceName={name}&\ + resourceVersionTime={xml_dt}" + ); + let query_url = DidUrl::parse(query)?; + + let data = self.resolver.resolve_resource(&query_url).await?; + // TODO - data may be missing issuerId + let _status_list: RevocationStatusList = serde_json::from_slice(&data)?; + + // TODO - statuslist to delta since 0 + // TODO - return `.1` based on the reported metadata timestamp + todo!() + } + + async fn get_rev_reg( + &self, + _rev_reg_id: &RevocationRegistryDefinitionId, + _timestamp: u64, + ) -> VcxLedgerResult<(RevocationRegistry, u64)> { + // + todo!() + } +} + +fn extract_issuer_id(url: &DidUrl) -> VcxLedgerResult { + let did = url.did().ok_or(VcxLedgerError::InvalidInput(format!( + "DID URL is missing a DID: {url}" + )))?; + IssuerId::new(did) + .map_err(|e| VcxLedgerError::InvalidInput(format!("DID is not an IssuerId {e}"))) +} + +impl Debug for CheqdAnoncredsLedgerRead { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "CheqdAnoncredsLedgerRead instance") + } +} diff --git a/aries/aries_vcx_ledger/src/ledger/cheqd/models.rs b/aries/aries_vcx_ledger/src/ledger/cheqd/models.rs new file mode 100644 index 0000000000..7d2c5c9760 --- /dev/null +++ b/aries/aries_vcx_ledger/src/ledger/cheqd/models.rs @@ -0,0 +1,37 @@ +//! Cheqd Ledger data models, derived from https://docs.cheqd.io/product/advanced/anoncreds + +use anoncreds_types::data_types::{ + identifiers::{cred_def_id::CredentialDefinitionId, schema_id::SchemaId}, + ledger::{ + cred_def::{CredentialDefinitionData, SignatureType}, + rev_reg_def::{RegistryType, RevocationRegistryDefinitionValue}, + }, +}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct CheqdAnoncredsSchema { + pub name: String, + pub version: String, + pub attr_names: Vec, +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct CheqdAnoncredsCredentialDefinition { + pub schema_id: SchemaId, + #[serde(rename = "type")] + pub signature_type: SignatureType, + pub tag: String, + pub value: CredentialDefinitionData, +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct CheqdAnoncredsRevocationRegistryDefinition { + pub revoc_def_type: RegistryType, + pub cred_def_id: CredentialDefinitionId, + pub tag: String, + pub value: RevocationRegistryDefinitionValue, +} diff --git a/aries/aries_vcx_ledger/src/ledger/indy_vdr_ledger.rs b/aries/aries_vcx_ledger/src/ledger/indy_vdr_ledger.rs index 4e55fea7d5..1fe17a52ac 100644 --- a/aries/aries_vcx_ledger/src/ledger/indy_vdr_ledger.rs +++ b/aries/aries_vcx_ledger/src/ledger/indy_vdr_ledger.rs @@ -596,7 +596,7 @@ where .sign_and_submit_request(wallet, submitter_did, request) .await; - if let Err(VcxLedgerError::InvalidLedgerResponse) = &sign_result { + if matches!(sign_result, Err(VcxLedgerError::InvalidLedgerResponse(_))) { return Err(VcxLedgerError::DuplicationSchema); } sign_result.map(|_| ()) diff --git a/aries/aries_vcx_ledger/src/ledger/mod.rs b/aries/aries_vcx_ledger/src/ledger/mod.rs index 32d9c595ad..f22a2191b2 100644 --- a/aries/aries_vcx_ledger/src/ledger/mod.rs +++ b/aries/aries_vcx_ledger/src/ledger/mod.rs @@ -5,6 +5,8 @@ pub mod common; pub mod indy; pub mod indy_vdr_ledger; +#[cfg(feature = "cheqd")] +pub mod cheqd; mod type_conversion; pub mod request_submitter; diff --git a/aries/messages/src/msg_fields/protocols/cred_issuance/v2/issue_credential.rs b/aries/messages/src/msg_fields/protocols/cred_issuance/v2/issue_credential.rs index 6a92d04031..99c22e1de4 100644 --- a/aries/messages/src/msg_fields/protocols/cred_issuance/v2/issue_credential.rs +++ b/aries/messages/src/msg_fields/protocols/cred_issuance/v2/issue_credential.rs @@ -43,6 +43,8 @@ pub struct IssueCredentialV2Decorators { pub enum IssueCredentialAttachmentFormatType { #[serde(rename = "aries/ld-proof-vc@v1.0")] AriesLdProofVc1_0, + #[serde(rename = "anoncreds/cred@v2.0")] + AnoncredsCredential2_0, #[serde(rename = "hlindy/cred@v2.0")] HyperledgerIndyCredential2_0, } diff --git a/aries/messages/src/msg_fields/protocols/cred_issuance/v2/offer_credential.rs b/aries/messages/src/msg_fields/protocols/cred_issuance/v2/offer_credential.rs index 39a499a3e3..3f42354653 100644 --- a/aries/messages/src/msg_fields/protocols/cred_issuance/v2/offer_credential.rs +++ b/aries/messages/src/msg_fields/protocols/cred_issuance/v2/offer_credential.rs @@ -45,6 +45,8 @@ pub enum OfferCredentialAttachmentFormatType { DifCredentialManifest1_0, #[serde(rename = "hlindy/cred-abstract@v2.0")] HyperledgerIndyCredentialAbstract2_0, + #[serde(rename = "anoncreds/cred-abstract@v2.0")] + AnoncredsCredentialAbstract2_0, #[serde(rename = "aries/ld-proof-vc-detail@v1.0")] AriesLdProofVcDetail1_0, } diff --git a/aries/messages/src/msg_fields/protocols/cred_issuance/v2/propose_credential.rs b/aries/messages/src/msg_fields/protocols/cred_issuance/v2/propose_credential.rs index f197c90783..f71cfd3630 100644 --- a/aries/messages/src/msg_fields/protocols/cred_issuance/v2/propose_credential.rs +++ b/aries/messages/src/msg_fields/protocols/cred_issuance/v2/propose_credential.rs @@ -44,6 +44,8 @@ pub enum ProposeCredentialAttachmentFormatType { DifCredentialManifest1_0, #[serde(rename = "aries/ld-proof-vc-detail@v1.0")] AriesLdProofVcDetail1_0, + #[serde(rename = "anoncreds/cred-filter@v2.0")] + AnoncredCredentialFilter2_0, #[serde(rename = "hlindy/cred-filter@v2.0")] HyperledgerIndyCredentialFilter2_0, } diff --git a/aries/messages/src/msg_fields/protocols/cred_issuance/v2/request_credential.rs b/aries/messages/src/msg_fields/protocols/cred_issuance/v2/request_credential.rs index 210c5ad0e3..933523c54d 100644 --- a/aries/messages/src/msg_fields/protocols/cred_issuance/v2/request_credential.rs +++ b/aries/messages/src/msg_fields/protocols/cred_issuance/v2/request_credential.rs @@ -40,6 +40,8 @@ pub enum RequestCredentialAttachmentFormatType { DifCredentialManifest1_0, #[serde(rename = "hlindy/cred-req@v2.0")] HyperledgerIndyCredentialRequest2_0, + #[serde(rename = "anoncreds/cred-req@v2.0")] + AnoncredsCredentialRequest2_0, #[serde(rename = "aries/ld-proof-vc-detail@v1.0")] AriesLdProofVcDetail1_0, } diff --git a/did_core/did_methods/did_cheqd/src/error/mod.rs b/did_core/did_methods/did_cheqd/src/error/mod.rs index fe3d49efdc..35f88e2940 100644 --- a/did_core/did_methods/did_cheqd/src/error/mod.rs +++ b/did_core/did_methods/did_cheqd/src/error/mod.rs @@ -22,6 +22,8 @@ pub enum DidCheqdError { InvalidResponse(String), #[error("Invalid DID Document structure resolved: {0}")] InvalidDidDocument(String), + #[error("Invalid DID Url: {0}")] + InvalidDidUrl(String), #[error("Parsing error: {0}")] ParsingError(#[from] ParsingErrorSource), #[error(transparent)] diff --git a/did_core/did_methods/did_cheqd/src/resolution/resolver.rs b/did_core/did_methods/did_cheqd/src/resolution/resolver.rs index 4b063e35db..cbc48430b6 100644 --- a/did_core/did_methods/did_cheqd/src/resolution/resolver.rs +++ b/did_core/did_methods/did_cheqd/src/resolution/resolver.rs @@ -4,7 +4,7 @@ use async_trait::async_trait; use bytes::Bytes; use did_resolver::{ did_doc::schema::did_doc::DidDocument, - did_parser_nom::Did, + did_parser_nom::{Did, DidUrl}, error::GenericError, shared_types::did_document_metadata::DidDocumentMetadata, traits::resolvable::{resolution_output::DidResolutionOutput, DidResolvable}, @@ -22,7 +22,7 @@ use crate::{ error::{DidCheqdError, DidCheqdResult}, proto::cheqd::{ did::v2::{query_client::QueryClient as DidQueryClient, QueryDidDocRequest}, - resource::v2::query_client::QueryClient as ResourceQueryClient, + resource::v2::{query_client::QueryClient as ResourceQueryClient, QueryResourceRequest}, }, }; @@ -83,8 +83,7 @@ type HyperClient = Client, UnsyncBoxBody, - // FUTURE - not used yet - _resources: ResourceQueryClient, + resources: ResourceQueryClient, } pub struct DidCheqdResolver { @@ -143,7 +142,7 @@ impl DidCheqdResolver { let client = CheqdGrpcClient { did: did_client, - _resources: resource_client, + resources: resource_client, }; lock.insert(network.to_owned(), client.clone()); @@ -183,6 +182,67 @@ impl DidCheqdResolver { Ok(output_builder.build()) } + + // TODO - better return structure + pub async fn resolve_resource(&self, url: &DidUrl) -> DidCheqdResult> { + let method = url.method(); + if method != Some("cheqd") { + return Err(DidCheqdError::MethodNotSupported(format!("{method:?}"))); + } + + let network = url.namespace().unwrap_or(MAINNET_NAMESPACE); + + // 1. resolve by exact reference: /reference/asdf + if let Some(path) = url.path() { + let Some(resource_id) = path.strip_prefix("/resources/") else { + // TODO + todo!() + }; + let did_id = url + .id() + .ok_or(DidCheqdError::InvalidDidUrl(format!("missing ID {url}")))?; + + return self + .resolve_resource_by_id(did_id, resource_id, network) + .await; + } + + // 2. resolve by name & type + // 2.a. resolve by name & type & `version` + // 2.b. resolve by name & type & closest to `resourceVersion` + // 2.c. resolve by name & type & closest to `now` + todo!() + } + + async fn resolve_resource_by_id( + &self, + did_id: &str, + resource_id: &str, + network: &str, + ) -> DidCheqdResult> { + let mut client = self.client_for_network(network).await?; + + let request = QueryResourceRequest { + collection_id: did_id.to_owned(), + id: resource_id.to_owned(), + }; + let response = client.resources.resource(request).await?; + + let query_response = response.into_inner(); + let query_response = query_response + .resource + .ok_or(DidCheqdError::InvalidResponse( + "Resource query did not return a value".into(), + ))?; + let query_resource = query_response + .resource + .ok_or(DidCheqdError::InvalidResponse( + "Resource query did not return a resource".into(), + ))?; + // TODO - metadata + + Ok(query_resource.data) + } } /// Assembles a hyper client which: From 25e766c766b2bd3432cd831911da1080fef8b91f Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Wed, 4 Dec 2024 08:21:01 +1000 Subject: [PATCH 24/50] temporarily include new format vers Signed-off-by: George Mulhearn --- .../src/msg_fields/protocols/present_proof/v2/present.rs | 3 +++ .../src/msg_fields/protocols/present_proof/v2/propose.rs | 3 +++ .../src/msg_fields/protocols/present_proof/v2/request.rs | 3 +++ 3 files changed, 9 insertions(+) diff --git a/aries/messages/src/msg_fields/protocols/present_proof/v2/present.rs b/aries/messages/src/msg_fields/protocols/present_proof/v2/present.rs index 1409dc48ec..473f77e135 100644 --- a/aries/messages/src/msg_fields/protocols/present_proof/v2/present.rs +++ b/aries/messages/src/msg_fields/protocols/present_proof/v2/present.rs @@ -42,6 +42,9 @@ pub struct PresentationV2Decorators { pub enum PresentationAttachmentFormatType { #[serde(rename = "hlindy/proof@v2.0")] HyperledgerIndyProof2_0, + // TODO - FIX - wrong ver, match acapy + #[serde(rename = "anoncreds/proof@v2.0")] + AnoncredsProof2_0, #[serde(rename = "dif/presentation-exchange/submission@v1.0")] DifPresentationExchangeSubmission1_0, } diff --git a/aries/messages/src/msg_fields/protocols/present_proof/v2/propose.rs b/aries/messages/src/msg_fields/protocols/present_proof/v2/propose.rs index 97386b4817..0e2adc3e1a 100644 --- a/aries/messages/src/msg_fields/protocols/present_proof/v2/propose.rs +++ b/aries/messages/src/msg_fields/protocols/present_proof/v2/propose.rs @@ -43,6 +43,9 @@ pub enum ProposePresentationAttachmentFormatType { DifPresentationExchangeDefinitions1_0, #[serde(rename = "hlindy/proof-req@v2.0")] HyperledgerIndyProofRequest2_0, + // TODO - FIX - wrong ver, match acapy + #[serde(rename = "anoncreds/proof-req@v2.0")] + AnoncredsProofRequest2_0, } #[cfg(test)] diff --git a/aries/messages/src/msg_fields/protocols/present_proof/v2/request.rs b/aries/messages/src/msg_fields/protocols/present_proof/v2/request.rs index d07fb10699..5dd52b9a27 100644 --- a/aries/messages/src/msg_fields/protocols/present_proof/v2/request.rs +++ b/aries/messages/src/msg_fields/protocols/present_proof/v2/request.rs @@ -44,6 +44,9 @@ pub struct RequestPresentationV2Decorators { pub enum PresentationRequestAttachmentFormatType { #[serde(rename = "hlindy/proof-req@v2.0")] HyperledgerIndyProofRequest2_0, + // TODO - FIX - wrong ver, match acapy + #[serde(rename = "anoncreds/proof-req@v2.0")] + AnoncredsProofRequest2_0, #[serde(rename = "dif/presentation-exchange/definitions@v1.0")] DifPresentationExchangeDefinitions1_0, } From ab7becbe696440c7477f3244c288d2c48adbc954 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Wed, 4 Dec 2024 10:09:21 +1000 Subject: [PATCH 25/50] issuer id Signed-off-by: George Mulhearn --- .../anoncreds/anoncreds/type_conversion.rs | 6 ++- .../aries_vcx_ledger/src/ledger/cheqd/mod.rs | 1 + .../src/ledger/type_conversion.rs | 43 ++++++++++--------- .../src/data_types/ledger/rev_reg_def.rs | 7 +-- 4 files changed, 32 insertions(+), 25 deletions(-) diff --git a/aries/aries_vcx_anoncreds/src/anoncreds/anoncreds/type_conversion.rs b/aries/aries_vcx_anoncreds/src/anoncreds/anoncreds/type_conversion.rs index 35c0762685..664b717aa3 100644 --- a/aries/aries_vcx_anoncreds/src/anoncreds/anoncreds/type_conversion.rs +++ b/aries/aries_vcx_anoncreds/src/anoncreds/anoncreds/type_conversion.rs @@ -264,9 +264,8 @@ impl Convert for OurRevocationRegistryDefinition { type Error = Box; fn convert(self, (): Self::Args) -> Result { - let issuer_id = self.id.to_string().split(':').next().unwrap().to_string(); Ok(AnoncredsRevocationRegistryDefinition { - issuer_id: AnoncredsIssuerId::new(issuer_id)?, + issuer_id: self.issuer_id.convert(())?, revoc_def_type: self.revoc_def_type.convert(())?, tag: self.tag, cred_def_id: AnoncredsCredentialDefinitionId::new(self.cred_def_id.to_string())?, @@ -288,6 +287,7 @@ impl Convert for AnoncredsRevocationRegistryDefinition { fn convert(self, (rev_reg_def_id,): Self::Args) -> Result { Ok(OurRevocationRegistryDefinition { id: OurRevocationRegistryDefinitionId::new(rev_reg_def_id)?, + issuer_id: self.issuer_id.convert(())?, revoc_def_type: self.revoc_def_type.convert(())?, tag: self.tag, cred_def_id: OurCredentialDefinitionId::new(self.cred_def_id.to_string())?, @@ -492,6 +492,7 @@ impl Convert for HashMap Result { match self { IndyVdrCredentialDefinition::CredentialDefinitionV1(cred_def) => { - if let Some((_method, issuer_id, _sig_type, _schema_id, _tag)) = cred_def.id.parts() - { - Ok(OurCredentialDefinition { - id: OurCredentialDefinitionId::new(cred_def.id.to_string())?, - schema_id: OurSchemaId::new_unchecked(cred_def.schema_id.to_string()), - signature_type: OurSignatureType::CL, - tag: cred_def.tag, - value: OurCredentialDefinitionData { - primary: serde_json::from_value(cred_def.value.primary)?, - revocation: cred_def - .value - .revocation - .map(serde_json::from_value) - .transpose()?, - }, - issuer_id: IssuerId::new(issuer_id.to_string())?, - }) - } else { - todo!() - } + let Some((_method, issuer_id, _sig_type, _schema_id, _tag)) = cred_def.id.parts() + else { + return Err(format!("cred def ID is not valid: {}", cred_def.id).into()); + }; + Ok(OurCredentialDefinition { + id: OurCredentialDefinitionId::new(cred_def.id.to_string())?, + schema_id: OurSchemaId::new_unchecked(cred_def.schema_id.to_string()), + signature_type: OurSignatureType::CL, + tag: cred_def.tag, + value: OurCredentialDefinitionData { + primary: serde_json::from_value(cred_def.value.primary)?, + revocation: cred_def + .value + .revocation + .map(serde_json::from_value) + .transpose()?, + }, + issuer_id: IssuerId::new(issuer_id.to_string())?, + }) } } } @@ -233,8 +232,12 @@ impl Convert for IndyVdrRevocationRegistryDefinition { fn convert(self, (): Self::Args) -> Result { match self { IndyVdrRevocationRegistryDefinition::RevocationRegistryDefinitionV1(rev_reg_def) => { + let Some((issuer_id, _cred_def, _type, _tag)) = rev_reg_def.id.parts() else { + return Err(format!("rev reg id is not valid: {}", rev_reg_def.id).into()); + }; Ok(OurRevocationRegistryDefinition { id: OurRevocationRegistryDefinitionId::new(rev_reg_def.id.to_string())?, + issuer_id: IssuerId::new(issuer_id.to_string())?, revoc_def_type: anoncreds_types::data_types::ledger::rev_reg_def::RegistryType::CL_ACCUM, tag: rev_reg_def.tag, diff --git a/aries/misc/anoncreds_types/src/data_types/ledger/rev_reg_def.rs b/aries/misc/anoncreds_types/src/data_types/ledger/rev_reg_def.rs index 61a25eb3fd..44633e6803 100644 --- a/aries/misc/anoncreds_types/src/data_types/ledger/rev_reg_def.rs +++ b/aries/misc/anoncreds_types/src/data_types/ledger/rev_reg_def.rs @@ -5,7 +5,8 @@ use anoncreds_clsignatures::RevocationKeyPrivate; use crate::{ cl::RevocationKeyPublic, data_types::identifiers::{ - cred_def_id::CredentialDefinitionId, rev_reg_def_id::RevocationRegistryDefinitionId, + cred_def_id::CredentialDefinitionId, issuer_id::IssuerId, + rev_reg_def_id::RevocationRegistryDefinitionId, }, utils::validation::Validatable, }; @@ -51,7 +52,7 @@ pub struct RevocationRegistryDefinitionValuePublicKeys { #[serde(rename_all = "camelCase")] pub struct RevocationRegistryDefinition { pub id: RevocationRegistryDefinitionId, - // pub issuer_id: IssuerId, // This is not on ledger + pub issuer_id: IssuerId, pub revoc_def_type: RegistryType, pub tag: String, pub cred_def_id: CredentialDefinitionId, @@ -61,7 +62,7 @@ pub struct RevocationRegistryDefinition { impl Validatable for RevocationRegistryDefinition { fn validate(&self) -> Result<(), crate::error::Error> { self.cred_def_id.validate()?; - // self.issuer_id.validate()?; + self.issuer_id.validate()?; Ok(()) } From 6c823284f3993338da3a12c72fb86a3a4c261a39 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Wed, 4 Dec 2024 11:41:15 +1000 Subject: [PATCH 26/50] move delta -> status list conversion as a ledger responsibility Signed-off-by: George Mulhearn --- .../common/proofs/prover/prover_internal.rs | 16 +- .../src/anoncreds/anoncreds/mod.rs | 138 +++++++----------- .../anoncreds/anoncreds/type_conversion.rs | 22 +-- .../src/anoncreds/base_anoncreds.rs | 5 +- .../src/ledger/base_ledger.rs | 9 +- .../aries_vcx_ledger/src/ledger/cheqd/mod.rs | 9 ++ .../src/ledger/indy_vdr_ledger.rs | 50 +++++-- .../anoncreds_types/src/utils/conversions.rs | 40 +++++ aries/misc/anoncreds_types/src/utils/mod.rs | 2 + aries/misc/test_utils/src/constants.rs | 1 + .../test_utils/src/mockdata/mock_anoncreds.rs | 4 +- .../test_utils/src/mockdata/mock_ledger.rs | 16 +- 12 files changed, 183 insertions(+), 129 deletions(-) create mode 100644 aries/misc/anoncreds_types/src/utils/conversions.rs diff --git a/aries/aries_vcx/src/common/proofs/prover/prover_internal.rs b/aries/aries_vcx/src/common/proofs/prover/prover_internal.rs index 1f78080675..2013074671 100644 --- a/aries/aries_vcx/src/common/proofs/prover/prover_internal.rs +++ b/aries/aries_vcx/src/common/proofs/prover/prover_internal.rs @@ -12,6 +12,7 @@ use aries_vcx_anoncreds::anoncreds::base_anoncreds::{ BaseAnonCreds, CredentialDefinitionsMap, RevocationStatesMap, SchemasMap, }; use aries_vcx_ledger::ledger::base_ledger::AnoncredsLedgerRead; +use chrono::Utc; use crate::errors::error::prelude::*; @@ -160,26 +161,25 @@ pub async fn build_rev_states_json( if !rtn.contains_key(rev_reg_id) { // Does this make sense in case cred_info's for same rev_reg_ids have different // revocation intervals - let (from, to) = if let Some(ref interval) = cred_info.revocation_interval { + let (_from, to) = if let Some(ref interval) = cred_info.revocation_interval { (interval.from, interval.to) } else { (None, None) }; - let rev_reg_def_json = ledger_read - .get_rev_reg_def_json(&rev_reg_id.to_owned().try_into()?) - .await?; + let parsed_id = &rev_reg_id.to_owned().try_into()?; + let rev_reg_def_json = ledger_read.get_rev_reg_def_json(parsed_id).await?; - let (rev_reg_delta_json, timestamp) = ledger_read - .get_rev_reg_delta_json(&rev_reg_id.to_owned().try_into()?, from, to) + let on_or_before = to.unwrap_or(Utc::now().timestamp() as u64); + let (rev_status_list, timestamp) = ledger_read + .get_rev_status_list(parsed_id, on_or_before, Some(&rev_reg_def_json)) .await?; let rev_state_json = anoncreds .create_revocation_state( Path::new(tails_dir), rev_reg_def_json, - rev_reg_delta_json, - timestamp, + rev_status_list, *cred_rev_id, ) .await?; diff --git a/aries/aries_vcx_anoncreds/src/anoncreds/anoncreds/mod.rs b/aries/aries_vcx_anoncreds/src/anoncreds/anoncreds/mod.rs index d32a9114cd..7108ee99e7 100644 --- a/aries/aries_vcx_anoncreds/src/anoncreds/anoncreds/mod.rs +++ b/aries/aries_vcx_anoncreds/src/anoncreds/anoncreds/mod.rs @@ -33,39 +33,41 @@ use anoncreds::{ RevocationRegistryDefinition as AnoncredsRevocationRegistryDefinition, }, }; -use anoncreds_types::data_types::{ - identifiers::{ - cred_def_id::CredentialDefinitionId, rev_reg_def_id::RevocationRegistryDefinitionId, - schema_id::SchemaId, - }, - ledger::{ - cred_def::{CredentialDefinition, SignatureType}, - rev_reg::RevocationRegistry, - rev_reg_def::RevocationRegistryDefinition, - rev_reg_delta::{RevocationRegistryDelta, RevocationRegistryDeltaValue}, - rev_status_list::RevocationStatusList, - schema::{AttributeNames, Schema}, - }, - messages::{ - cred_definition_config::CredentialDefinitionConfig, - cred_offer::CredentialOffer, - cred_request::{CredentialRequest, CredentialRequestMetadata}, - cred_selection::{ - RetrievedCredentialForReferent, RetrievedCredentialInfo, RetrievedCredentials, +use anoncreds_types::{ + data_types::{ + identifiers::{ + cred_def_id::CredentialDefinitionId, rev_reg_def_id::RevocationRegistryDefinitionId, + schema_id::SchemaId, + }, + ledger::{ + cred_def::{CredentialDefinition, SignatureType}, + rev_reg::RevocationRegistry, + rev_reg_def::RevocationRegistryDefinition, + rev_reg_delta::{RevocationRegistryDelta, RevocationRegistryDeltaValue}, + rev_status_list::RevocationStatusList, + schema::{AttributeNames, Schema}, + }, + messages::{ + cred_definition_config::CredentialDefinitionConfig, + cred_offer::CredentialOffer, + cred_request::{CredentialRequest, CredentialRequestMetadata}, + cred_selection::{ + RetrievedCredentialForReferent, RetrievedCredentialInfo, RetrievedCredentials, + }, + credential::{Credential, CredentialValues}, + nonce::Nonce, + pres_request::PresentationRequest, + presentation::{Presentation, RequestedCredentials}, + revocation_state::CredentialRevocationState, }, - credential::{Credential, CredentialValues}, - nonce::Nonce, - pres_request::PresentationRequest, - presentation::{Presentation, RequestedCredentials}, - revocation_state::CredentialRevocationState, }, + utils::conversions::from_revocation_registry_delta_to_revocation_status_list, }; use aries_vcx_wallet::wallet::{ base_wallet::{record::Record, record_category::RecordCategory, BaseWallet}, record_tags::{RecordTag, RecordTags}, }; use async_trait::async_trait; -use bitvec::bitvec; use did_parser_nom::Did; use log::warn; use serde::{de::DeserializeOwned, Deserialize, Serialize}; @@ -82,36 +84,6 @@ use crate::{ errors::error::{VcxAnoncredsError, VcxAnoncredsResult}, }; -fn from_revocation_registry_delta_to_revocation_status_list( - delta: &RevocationRegistryDeltaValue, - rev_reg_def: &AnoncredsRevocationRegistryDefinition, - rev_reg_def_id: &RevocationRegistryDefinitionId, - timestamp: Option, - issuance_by_default: bool, -) -> VcxAnoncredsResult { - let default_state = if issuance_by_default { 0 } else { 1 }; - let mut revocation_list = bitvec![default_state; rev_reg_def.value.max_cred_num as usize]; - - for issued in &delta.issued { - revocation_list.insert(*issued as usize, false); - } - - for revoked in &delta.revoked { - revocation_list.insert(*revoked as usize, true); - } - - let accum = delta.accum.into(); - - RevocationStatusList::new( - Some(&rev_reg_def_id.to_string()), - rev_reg_def.issuer_id.clone().convert(())?, - revocation_list, - Some(accum), - timestamp, - ) - .map_err(Into::into) -} - fn from_revocation_status_list_to_revocation_registry_delta( rev_status_list: &RevocationStatusList, prev_accum: Option, @@ -288,17 +260,37 @@ impl BaseAnonCreds for Anoncreds { let cred_defs: HashMap = credential_defs_json.convert(())?; + // tack on issuerId for ease of processing status lists + let rev_regs_map_with_issuer_ids: Option> = + match (rev_regs_json, &rev_reg_defs_json) { + (Some(regs), Some(defs)) => Some( + regs.into_iter() + .filter_map(|(k, v)| { + let Some(def) = defs.get(&k) else { + return None; + }; + Some((k, (v, def.issuer_id.clone()))) + }) + .collect(), + ), + _ => None, + }; + let rev_reg_defs: Option< HashMap, > = rev_reg_defs_json.map(|v| v.convert(())).transpose()?; + let rev_status_lists = rev_regs_map_with_issuer_ids + .map(|r| r.convert(())) + .transpose()?; + Ok(anoncreds::verifier::verify_presentation( &presentation, &pres_req, &schemas, &cred_defs, rev_reg_defs.as_ref(), - rev_regs_json.map(|r| r.convert(())).transpose()?, + rev_status_lists, None, // no idea what this is )?) } @@ -947,18 +939,9 @@ impl BaseAnonCreds for Anoncreds { &self, tails_dir: &Path, rev_reg_def_json: RevocationRegistryDefinition, - rev_reg_delta_json: RevocationRegistryDelta, - timestamp: u64, + rev_status_list: RevocationStatusList, cred_rev_id: u32, ) -> VcxAnoncredsResult { - let cred_def_id = rev_reg_def_json.cred_def_id.to_string(); - let max_cred_num = rev_reg_def_json.value.max_cred_num; - let rev_reg_def_id = rev_reg_def_json.id.to_string(); - let (_cred_def_method, issuer_did, _signature_type, _schema_num, _tag) = - cred_def_parts(&cred_def_id).ok_or(VcxAnoncredsError::InvalidSchema(format!( - "Could not process cred_def_id {cred_def_id} as parts." - )))?; - let revoc_reg_def: AnoncredsRevocationRegistryDefinition = rev_reg_def_json.convert(())?; let tails_file_hash = revoc_reg_def.value.tails_hash.as_str(); @@ -970,25 +953,6 @@ impl BaseAnonCreds for Anoncreds { VcxAnoncredsError::InvalidOption("tails file is not an unicode string".into()) })?; - let RevocationRegistryDeltaValue { accum, revoked, .. } = rev_reg_delta_json.value; - - let issuer_id = IssuerId::new(issuer_did.did()).unwrap(); - let mut revocation_list = bitvec!(0; max_cred_num as usize); - revoked.into_iter().for_each(|id| { - revocation_list - .get_mut(id as usize) - .map(|mut b| *b = true) - .unwrap_or_default() - }); - let registry = CryptoRevocationRegistry { accum }; - - let rev_status_list = RevocationStatusList::new( - Some(&rev_reg_def_id), - issuer_id.convert(())?, - revocation_list, - Some(registry), - Some(timestamp), - )?; let rev_state = anoncreds::prover::create_or_update_revocation_state( tails_path, &revoc_reg_def, @@ -1164,10 +1128,8 @@ impl BaseAnonCreds for Anoncreds { let current_time = OffsetDateTime::now_utc().unix_timestamp() as u64; let rev_status_list = from_revocation_registry_delta_to_revocation_status_list( &last_rev_reg_delta.value, - &rev_reg_def.clone().convert(())?, - rev_reg_id, + &rev_reg_def, Some(current_time), - true, )?; let cred_def = self diff --git a/aries/aries_vcx_anoncreds/src/anoncreds/anoncreds/type_conversion.rs b/aries/aries_vcx_anoncreds/src/anoncreds/anoncreds/type_conversion.rs index 664b717aa3..ef0958b3fc 100644 --- a/aries/aries_vcx_anoncreds/src/anoncreds/anoncreds/type_conversion.rs +++ b/aries/aries_vcx_anoncreds/src/anoncreds/anoncreds/type_conversion.rs @@ -483,32 +483,26 @@ impl Convert for HashMap> { +impl Convert + for HashMap< + OurRevocationRegistryDefinitionId, + (HashMap, OurIssuerId), + > +{ type Args = (); type Target = Vec; type Error = Box; fn convert(self, _args: Self::Args) -> Result { let mut lists = Vec::new(); - for (rev_reg_def_id, timestamp_map) in self.into_iter() { + for (rev_reg_def_id, (timestamp_map, issuer_id)) in self.into_iter() { for (timestamp, entry) in timestamp_map { - // TODO - bad splitting - let issuer_id = AnoncredsIssuerId::new( - rev_reg_def_id - .to_string() - .split(':') - .next() - .unwrap() - .to_string(), - ) - .unwrap(); let OurRevocationRegistry { value } = entry; let registry = CryptoRevocationRegistry { accum: value.accum }; let rev_status_list = OurRevocationStatusList::new( Some(&rev_reg_def_id.to_string()), - issuer_id.convert(())?, - // TODO - this seems incorrect. + issuer_id.clone(), Default::default(), Some(registry), Some(timestamp), diff --git a/aries/aries_vcx_anoncreds/src/anoncreds/base_anoncreds.rs b/aries/aries_vcx_anoncreds/src/anoncreds/base_anoncreds.rs index 28cbb0a221..8cb009c22d 100644 --- a/aries/aries_vcx_anoncreds/src/anoncreds/base_anoncreds.rs +++ b/aries/aries_vcx_anoncreds/src/anoncreds/base_anoncreds.rs @@ -10,6 +10,7 @@ use anoncreds_types::data_types::{ rev_reg::RevocationRegistry, rev_reg_def::RevocationRegistryDefinition, rev_reg_delta::RevocationRegistryDelta, + rev_status_list::RevocationStatusList, schema::{AttributeNames, Schema}, }, messages::{ @@ -138,8 +139,7 @@ pub trait BaseAnonCreds: std::fmt::Debug + Send + Sync { &self, tails_dir: &Path, rev_reg_def_json: RevocationRegistryDefinition, - rev_reg_delta_json: RevocationRegistryDelta, - timestamp: u64, + rev_status_list: RevocationStatusList, cred_rev_id: u32, ) -> VcxAnoncredsResult; @@ -174,6 +174,7 @@ pub trait BaseAnonCreds: std::fmt::Debug + Send + Sync { // TODO - FUTURE - think about moving this to somewhere else, as it aggregates other calls (not // PURE Anoncreds) + // TODO - review functionality below and convert to using statuslists // ^ YES async fn revoke_credential_local( &self, diff --git a/aries/aries_vcx_ledger/src/ledger/base_ledger.rs b/aries/aries_vcx_ledger/src/ledger/base_ledger.rs index 3c34983cd5..e072427fe8 100644 --- a/aries/aries_vcx_ledger/src/ledger/base_ledger.rs +++ b/aries/aries_vcx_ledger/src/ledger/base_ledger.rs @@ -8,7 +8,7 @@ use anoncreds_types::data_types::{ ledger::{ cred_def::CredentialDefinition, rev_reg::RevocationRegistry, rev_reg_def::RevocationRegistryDefinition, rev_reg_delta::RevocationRegistryDelta, - schema::Schema, + rev_status_list::RevocationStatusList, schema::Schema, }, }; use aries_vcx_wallet::wallet::base_wallet::BaseWallet; @@ -95,6 +95,13 @@ pub trait AnoncredsLedgerRead: Debug + Send + Sync { from: Option, to: Option, ) -> VcxLedgerResult<(RevocationRegistryDelta, u64)>; + /// TODO - describe + async fn get_rev_status_list( + &self, + rev_reg_id: &RevocationRegistryDefinitionId, + timestamp: u64, + pre_fetched_rev_reg_def: Option<&RevocationRegistryDefinition>, + ) -> VcxLedgerResult<(RevocationStatusList, u64)>; async fn get_rev_reg( &self, rev_reg_id: &RevocationRegistryDefinitionId, diff --git a/aries/aries_vcx_ledger/src/ledger/cheqd/mod.rs b/aries/aries_vcx_ledger/src/ledger/cheqd/mod.rs index f7a0663d3f..a79ca65692 100644 --- a/aries/aries_vcx_ledger/src/ledger/cheqd/mod.rs +++ b/aries/aries_vcx_ledger/src/ledger/cheqd/mod.rs @@ -131,6 +131,15 @@ impl AnoncredsLedgerRead for CheqdAnoncredsLedgerRead { todo!() } + async fn get_rev_status_list( + &self, + _rev_reg_id: &RevocationRegistryDefinitionId, + _timestamp: u64, + _: Option<&RevocationRegistryDefinition>, + ) -> VcxLedgerResult<(RevocationStatusList, u64)> { + todo!() + } + async fn get_rev_reg( &self, _rev_reg_id: &RevocationRegistryDefinitionId, diff --git a/aries/aries_vcx_ledger/src/ledger/indy_vdr_ledger.rs b/aries/aries_vcx_ledger/src/ledger/indy_vdr_ledger.rs index 1fe17a52ac..76be156d35 100644 --- a/aries/aries_vcx_ledger/src/ledger/indy_vdr_ledger.rs +++ b/aries/aries_vcx_ledger/src/ledger/indy_vdr_ledger.rs @@ -4,16 +4,19 @@ use std::{ sync::RwLock, }; -use anoncreds_types::data_types::{ - identifiers::{ - cred_def_id::CredentialDefinitionId, rev_reg_def_id::RevocationRegistryDefinitionId, - schema_id::SchemaId, - }, - ledger::{ - cred_def::CredentialDefinition, rev_reg::RevocationRegistry, - rev_reg_def::RevocationRegistryDefinition, rev_reg_delta::RevocationRegistryDelta, - schema::Schema, +use anoncreds_types::{ + data_types::{ + identifiers::{ + cred_def_id::CredentialDefinitionId, rev_reg_def_id::RevocationRegistryDefinitionId, + schema_id::SchemaId, + }, + ledger::{ + cred_def::CredentialDefinition, rev_reg::RevocationRegistry, + rev_reg_def::RevocationRegistryDefinition, rev_reg_delta::RevocationRegistryDelta, + rev_status_list::RevocationStatusList, schema::Schema, + }, }, + utils::conversions::from_revocation_registry_delta_to_revocation_status_list, }; use aries_vcx_wallet::wallet::base_wallet::BaseWallet; use async_trait::async_trait; @@ -541,6 +544,35 @@ where Ok((revoc_reg_delta.convert(())?, timestamp)) } + async fn get_rev_status_list( + &self, + rev_reg_id: &RevocationRegistryDefinitionId, + timestamp: u64, + pre_fetched_rev_reg_def: Option<&RevocationRegistryDefinition>, + ) -> VcxLedgerResult<(RevocationStatusList, u64)> { + let (delta, entry_time) = self + .get_rev_reg_delta_json(rev_reg_id, Some(0), Some(timestamp)) + .await?; + + let rev_reg_def = match pre_fetched_rev_reg_def { + Some(x) => x, + None => &self.get_rev_reg_def_json(rev_reg_id).await?, + }; + + let status_list = from_revocation_registry_delta_to_revocation_status_list( + &delta.value, + &rev_reg_def, + Some(entry_time), + ) + .map_err(|e| { + VcxLedgerError::InvalidLedgerResponse(format!( + "received rev status delta could not be translated to status list: {e} {delta:?}" + )) + })?; + + Ok((status_list, entry_time)) + } + async fn get_rev_reg( &self, rev_reg_id: &RevocationRegistryDefinitionId, diff --git a/aries/misc/anoncreds_types/src/utils/conversions.rs b/aries/misc/anoncreds_types/src/utils/conversions.rs new file mode 100644 index 0000000000..b392eadb2f --- /dev/null +++ b/aries/misc/anoncreds_types/src/utils/conversions.rs @@ -0,0 +1,40 @@ +use bitvec::bitvec; + +use crate::data_types::ledger::{ + rev_reg_def::RevocationRegistryDefinition, rev_reg_delta::RevocationRegistryDeltaValue, + rev_status_list::RevocationStatusList, +}; + +/// TODO - explain +pub fn from_revocation_registry_delta_to_revocation_status_list( + delta: &RevocationRegistryDeltaValue, + rev_reg_def: &RevocationRegistryDefinition, + timestamp: Option, +) -> Result { + // no way to derive this value here. So we assume true, as false (ISSAUNCE_ON_DEAMAND) is not + // recomended by anoncreds: https://hyperledger.github.io/anoncreds-spec/#anoncreds-issuer-setup-with-revocation + let issuance_by_default = true; + let default_state = if issuance_by_default { 0 } else { 1 }; + let mut revocation_list = bitvec![default_state; rev_reg_def.value.max_cred_num as usize]; + + for issued in &delta.issued { + // TODO - bounds + revocation_list.insert(*issued as usize, false); + } + + for revoked in &delta.revoked { + // TODO - bounds + revocation_list.insert(*revoked as usize, true); + } + + let accum = delta.accum.into(); + + RevocationStatusList::new( + Some(&rev_reg_def.id.to_string()), + rev_reg_def.issuer_id.clone(), + revocation_list, + Some(accum), + timestamp, + ) + .map_err(Into::into) +} diff --git a/aries/misc/anoncreds_types/src/utils/mod.rs b/aries/misc/anoncreds_types/src/utils/mod.rs index c5dc163117..b2e7a35f49 100644 --- a/aries/misc/anoncreds_types/src/utils/mod.rs +++ b/aries/misc/anoncreds_types/src/utils/mod.rs @@ -1,2 +1,4 @@ +/// VCX utility additon +pub mod conversions; pub mod query; pub mod validation; diff --git a/aries/misc/test_utils/src/constants.rs b/aries/misc/test_utils/src/constants.rs index 7e7e780ee1..416c725527 100644 --- a/aries/misc/test_utils/src/constants.rs +++ b/aries/misc/test_utils/src/constants.rs @@ -57,6 +57,7 @@ pub static LICENCE_CRED_ID: &str = "92556f60-d290-4b58-9a43-05c25aac214e"; pub static REV_REG_ID: &str = r#"V4SGRU86Z58d6TV7PBUe6f:4:V4SGRU86Z58d6TV7PBUe6f:3:CL:1281:tag1:CL_ACCUM:tag1"#; pub static REV_REG_DELTA_JSON: &str = r#"{"ver":"1.0","value":{"accum":"2 0A0752AD393CCA8E840459E79BCF48F16ECEF17C00E9B639AC6CE2CCC93954C9 2 242D07E4AE3284C1E499D98E4EDF65ACFC0392E64C2BFF55192AC3AE51C3657C 2 165A2D44CAEE9717F1F52CC1BA6F72F39B21F969B3C4CDCA4FB501880F7AD297 2 1B08C9BB4876353F70E4A639F3B41593488B9964D4A56B61B0E1FF8B0FB0A1E7 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8 1 0000000000000000000000000000000000000000000000000000000000000000"}}"#; +pub static REV_STATUS_LIST_JSON: &str = r#"{"revRegDefId": "4xE68b6S5VRFrKMMG1U95M:4:4xE68b6S5VRFrKMMG1U95M:3:CL:59232:default:CL_ACCUM:4ae1cc6c-f6bd-486c-8057-88f2ce74e960","issuerId": "did:web:example.org","revocationList": [0, 1, 1, 0],"currentAccumulator": "21 124C594B6B20E41B681E92B2C43FD165EA9E68BC3C9D63A82C8893124983CAE94 21 124C5341937827427B0A3A32113BD5E64FB7AB39BD3E5ABDD7970874501CA4897 6 5438CB6F442E2F807812FD9DC0C39AFF4A86B1E6766DBB5359E86A4D70401B0F 4 39D1CA5C4716FFC4FE0853C4FF7F081DFD8DF8D2C2CA79705211680AC77BF3A1 6 70504A5493F89C97C225B68310811A41AD9CD889301F238E93C95AD085E84191 4 39582252194D756D5D86D0EED02BF1B95CE12AED2FA5CD3C53260747D891993C","timestamp": 1669640864487}"#; pub static REV_STATE_JSON: &str = r#"{"rev_reg":{"accum":"1 0000000000000000000000000000000000000000000000000000000000000000 1 0000000000000000000000000000000000000000000000000000000000000000 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8 1 0000000000000000000000000000000000000000000000000000000000000000 1 0000000000000000000000000000000000000000000000000000000000000000 1 0000000000000000000000000000000000000000000000000000000000000000"},"timestamp":100,"witness":{"omega":"1 0000000000000000000000000000000000000000000000000000000000000000 1 0000000000000000000000000000000000000000000000000000000000000000 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8 1 0000000000000000000000000000000000000000000000000000000000000000 1 0000000000000000000000000000000000000000000000000000000000000000 1 0000000000000000000000000000000000000000000000000000000000000000"}}"#; pub static REV_REG_JSON: &str = r#"{"value":{"accum":"2 0204F2D2B1F2B705A11AAFEEE73C9BA084C12AF1179294529AC4D14CA54E87F3 2 222BAE38FAF2673F7BCBB86D8DE1A327F5065BDC892E9A122164260C97BC0C63 2 1565105F8BA53037978B66E0CC9F53205F189DEEB6B7168744456DD98D2F4E88 2 1AC9E76B2868141A42329778831C14AEAAF7A9981209C1D96AECA4E69CAFB243 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8 1 0000000000000000000000000000000000000000000000000000000000000000"}}"#; pub static TEST_TAILS_LOCATION: &str = r#"/var/folders/kr/9gkxsj_s01b6fvx_72trl3mm0000gp/T/tails_file/5R6BWXL3vPrbJPKe9FsHAVG9hqKdDvVxonBuj3ETYuZh"#; diff --git a/aries/misc/test_utils/src/mockdata/mock_anoncreds.rs b/aries/misc/test_utils/src/mockdata/mock_anoncreds.rs index 6f2cf5cdac..696dce466f 100644 --- a/aries/misc/test_utils/src/mockdata/mock_anoncreds.rs +++ b/aries/misc/test_utils/src/mockdata/mock_anoncreds.rs @@ -10,6 +10,7 @@ use anoncreds_types::data_types::{ rev_reg::RevocationRegistry, rev_reg_def::RevocationRegistryDefinition, rev_reg_delta::RevocationRegistryDelta, + rev_status_list::RevocationStatusList, schema::{AttributeNames, Schema}, }, messages::{ @@ -178,8 +179,7 @@ impl BaseAnonCreds for MockAnoncreds { &self, _tails_dir: &Path, _rev_reg_def_json: RevocationRegistryDefinition, - _rev_reg_delta_json: RevocationRegistryDelta, - _timestamp: u64, + _rev_status_list: RevocationStatusList, _cred_rev_id: u32, ) -> VcxAnoncredsResult { Ok(serde_json::from_str(REV_STATE_JSON)?) diff --git a/aries/misc/test_utils/src/mockdata/mock_ledger.rs b/aries/misc/test_utils/src/mockdata/mock_ledger.rs index 0297255088..b27290ff3c 100644 --- a/aries/misc/test_utils/src/mockdata/mock_ledger.rs +++ b/aries/misc/test_utils/src/mockdata/mock_ledger.rs @@ -4,9 +4,7 @@ use anoncreds_types::data_types::{ schema_id::SchemaId, }, ledger::{ - cred_def::CredentialDefinition, rev_reg::RevocationRegistry, - rev_reg_def::RevocationRegistryDefinition, rev_reg_delta::RevocationRegistryDelta, - schema::Schema, + cred_def::CredentialDefinition, rev_reg::RevocationRegistry, rev_reg_def::RevocationRegistryDefinition, rev_reg_delta::RevocationRegistryDelta, rev_status_list::RevocationStatusList, schema::Schema }, }; use aries_vcx_ledger::{ @@ -22,8 +20,7 @@ use did_parser_nom::Did; use public_key::Key; use crate::constants::{ - rev_def_json, CRED_DEF_JSON, DEFAULT_AUTHOR_AGREEMENT, REQUEST_WITH_ENDORSER, - REV_REG_DELTA_JSON, REV_REG_JSON, SCHEMA_JSON, + rev_def_json, CRED_DEF_JSON, DEFAULT_AUTHOR_AGREEMENT, REQUEST_WITH_ENDORSER, REV_REG_DELTA_JSON, REV_REG_JSON, REV_STATUS_LIST_JSON, SCHEMA_JSON }; #[derive(Debug)] @@ -147,6 +144,15 @@ impl AnoncredsLedgerRead for MockLedger { Ok((serde_json::from_str(REV_REG_DELTA_JSON).unwrap(), 1)) } + async fn get_rev_status_list( + &self, + rev_reg_id: &RevocationRegistryDefinitionId, + timestamp: u64, + pre_fetched_rev_reg_def: Option<&RevocationRegistryDefinition>, + ) -> VcxLedgerResult<(RevocationStatusList, u64)> { + Ok((serde_json::from_str(REV_STATUS_LIST_JSON).unwrap(), 1)) + } + async fn get_rev_reg( &self, rev_reg_id: &RevocationRegistryDefinitionId, From c08b2c1cbc13878877d928905a6458c86ef03d59 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Wed, 4 Dec 2024 13:43:31 +1000 Subject: [PATCH 27/50] cheqd get rev status list Signed-off-by: George Mulhearn --- Cargo.lock | 1 + aries/aries_vcx_ledger/Cargo.toml | 1 + .../aries_vcx_ledger/src/ledger/cheqd/mod.rs | 94 ++++++++++++------- .../src/ledger/cheqd/models.rs | 15 ++- .../src/data_types/ledger/rev_status_list.rs | 10 +- 5 files changed, 82 insertions(+), 39 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f4197bd64d..9829922293 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -603,6 +603,7 @@ dependencies = [ "anoncreds_types", "aries_vcx_wallet", "async-trait", + "bitvec", "chrono", "did_cheqd", "did_parser_nom", diff --git a/aries/aries_vcx_ledger/Cargo.toml b/aries/aries_vcx_ledger/Cargo.toml index 153c9df51e..9ebacd9f87 100644 --- a/aries/aries_vcx_ledger/Cargo.toml +++ b/aries/aries_vcx_ledger/Cargo.toml @@ -29,3 +29,4 @@ serde = { version = "1.0.159", features = ["derive"] } lru = { version = "0.12.0" } tokio = { version = "1.38" } chrono = { version = "0.4", default-features = false } +bitvec = "1.0.1" diff --git a/aries/aries_vcx_ledger/src/ledger/cheqd/mod.rs b/aries/aries_vcx_ledger/src/ledger/cheqd/mod.rs index a79ca65692..10b3f98569 100644 --- a/aries/aries_vcx_ledger/src/ledger/cheqd/mod.rs +++ b/aries/aries_vcx_ledger/src/ledger/cheqd/mod.rs @@ -15,12 +15,12 @@ use anoncreds_types::data_types::{ }, }; use async_trait::async_trait; -use chrono::{DateTime, Utc}; +use chrono::DateTime; use did_cheqd::resolution::resolver::DidCheqdResolver; use did_parser_nom::{Did, DidUrl}; use models::{ CheqdAnoncredsCredentialDefinition, CheqdAnoncredsRevocationRegistryDefinition, - CheqdAnoncredsSchema, + CheqdAnoncredsRevocationStatusList, CheqdAnoncredsSchema, }; use super::base_ledger::AnoncredsLedgerRead; @@ -98,23 +98,41 @@ impl AnoncredsLedgerRead for CheqdAnoncredsLedgerRead { async fn get_rev_reg_delta_json( &self, - rev_reg_id: &RevocationRegistryDefinitionId, - // TODO - explain why we ignore `from` + _rev_reg_id: &RevocationRegistryDefinitionId, _from: Option, - to: Option, + _to: Option, ) -> VcxLedgerResult<(RevocationRegistryDelta, u64)> { - let url = DidUrl::parse(rev_reg_id.to_string())?; - let data = self.resolver.resolve_resource(&url).await?; - let rev_reg_def: RevocationRegistryDefinition = serde_json::from_slice(&data)?; - let name = rev_reg_def.tag; // TODO - credo-ts uses the metadata.name or fails (https://docs.cheqd.io/product/advanced/anoncreds/revocation-status-list#same-resource-name-different-resource-type) + // unsupported, to be removed: https://github.com/hyperledger/aries-vcx/issues/1309 + Err(VcxLedgerError::UnimplementedFeature( + "get_rev_reg_delta_json not supported for cheqd".into(), + )) + } + + async fn get_rev_status_list( + &self, + rev_reg_id: &RevocationRegistryDefinitionId, + timestamp: u64, + pre_fetched_rev_reg_def: Option<&RevocationRegistryDefinition>, + ) -> VcxLedgerResult<(RevocationStatusList, u64)> { + let rev_reg_def_url = DidUrl::parse(rev_reg_id.to_string())?; + + let rev_reg_def = match pre_fetched_rev_reg_def { + Some(v) => v, + None => &self.get_rev_reg_def_json(rev_reg_id).await?, + }; + + let name = &rev_reg_def.tag; // TODO - credo-ts uses the metadata.name or fails (https://docs.cheqd.io/product/advanced/anoncreds/revocation-status-list#same-resource-name-different-resource-type) - let did = url.did().ok_or(VcxLedgerError::InvalidInput(format!( - "DID URL missing DID {url}" - )))?; + let did = rev_reg_def_url + .did() + .ok_or(VcxLedgerError::InvalidInput(format!( + "DID URL missing DID {rev_reg_def_url}" + )))?; - let resource_dt = to - .and_then(|epoch| DateTime::from_timestamp(epoch as i64, 0)) - .unwrap_or(Utc::now()); + let resource_dt = + DateTime::from_timestamp(timestamp as i64, 0).ok_or(VcxLedgerError::InvalidInput( + format!("input status list timestamp is not valid {timestamp}"), + ))?; let xml_dt = resource_dt.to_rfc3339_opts(chrono::SecondsFormat::Millis, true); let query = format!( "{did}?resourceType={STATUS_LIST_RESOURCE_TYPE}&resourceName={name}&\ @@ -122,31 +140,41 @@ impl AnoncredsLedgerRead for CheqdAnoncredsLedgerRead { ); let query_url = DidUrl::parse(query)?; - let data = self.resolver.resolve_resource(&query_url).await?; - // TODO - data may be missing issuerId - let _status_list: RevocationStatusList = serde_json::from_slice(&data)?; + let resource = self.resolver.resolve_resource(&query_url).await?; + let data: CheqdAnoncredsRevocationStatusList = serde_json::from_slice(&resource)?; + let timestamp = 0; // TODO - from metadata - // TODO - statuslist to delta since 0 - // TODO - return `.1` based on the reported metadata timestamp - todo!() - } + let status_list = RevocationStatusList { + rev_reg_def_id: Some(rev_reg_id.to_owned()), + issuer_id: extract_issuer_id(&rev_reg_def_url)?, + revocation_list: data.revocation_list, + accum: data.accum, + timestamp: Some(timestamp), + }; - async fn get_rev_status_list( - &self, - _rev_reg_id: &RevocationRegistryDefinitionId, - _timestamp: u64, - _: Option<&RevocationRegistryDefinition>, - ) -> VcxLedgerResult<(RevocationStatusList, u64)> { - todo!() + Ok((status_list, timestamp)) } async fn get_rev_reg( &self, - _rev_reg_id: &RevocationRegistryDefinitionId, - _timestamp: u64, + rev_reg_id: &RevocationRegistryDefinitionId, + timestamp: u64, ) -> VcxLedgerResult<(RevocationRegistry, u64)> { - // - todo!() + let (list, last_updated) = self + .get_rev_status_list(rev_reg_id, timestamp, None) + .await?; + + let accum = list + .accum + .ok_or(VcxLedgerError::InvalidLedgerResponse(format!( + "response status list is missing an accumulator: {list:?}" + )))?; + + let reg = RevocationRegistry { + value: accum.into(), + }; + + Ok((reg, last_updated)) } } diff --git a/aries/aries_vcx_ledger/src/ledger/cheqd/models.rs b/aries/aries_vcx_ledger/src/ledger/cheqd/models.rs index 7d2c5c9760..83ad010415 100644 --- a/aries/aries_vcx_ledger/src/ledger/cheqd/models.rs +++ b/aries/aries_vcx_ledger/src/ledger/cheqd/models.rs @@ -4,7 +4,7 @@ use anoncreds_types::data_types::{ identifiers::{cred_def_id::CredentialDefinitionId, schema_id::SchemaId}, ledger::{ cred_def::{CredentialDefinitionData, SignatureType}, - rev_reg_def::{RegistryType, RevocationRegistryDefinitionValue}, + rev_reg_def::{RegistryType, RevocationRegistryDefinitionValue}, rev_status_list::serde_revocation_list, }, }; use serde::{Deserialize, Serialize}; @@ -35,3 +35,16 @@ pub struct CheqdAnoncredsRevocationRegistryDefinition { pub tag: String, pub value: RevocationRegistryDefinitionValue, } + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct CheqdAnoncredsRevocationStatusList { + #[serde(with = "serde_revocation_list")] + pub revocation_list: bitvec::vec::BitVec, + #[serde( + rename = "currentAccumulator", + alias = "accum", + skip_serializing_if = "Option::is_none" + )] + pub accum: Option, +} diff --git a/aries/misc/anoncreds_types/src/data_types/ledger/rev_status_list.rs b/aries/misc/anoncreds_types/src/data_types/ledger/rev_status_list.rs index 6d735fa27a..8ce242e44c 100644 --- a/aries/misc/anoncreds_types/src/data_types/ledger/rev_status_list.rs +++ b/aries/misc/anoncreds_types/src/data_types/ledger/rev_status_list.rs @@ -13,18 +13,18 @@ use crate::{ #[serde(rename_all = "camelCase")] pub struct RevocationStatusList { #[serde(skip_serializing_if = "Option::is_none")] - rev_reg_def_id: Option, - issuer_id: IssuerId, + pub rev_reg_def_id: Option, + pub issuer_id: IssuerId, #[serde(with = "serde_revocation_list")] - revocation_list: bitvec::vec::BitVec, + pub revocation_list: bitvec::vec::BitVec, #[serde( rename = "currentAccumulator", alias = "accum", skip_serializing_if = "Option::is_none" )] - accum: Option, + pub accum: Option, #[serde(skip_serializing_if = "Option::is_none")] - timestamp: Option, + pub timestamp: Option, } impl From<&RevocationStatusList> for Option { From 19d4e21f8b5f78800eda5d6b570a7633190ed77a Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Wed, 4 Dec 2024 16:07:04 +1000 Subject: [PATCH 28/50] return metadata Signed-off-by: George Mulhearn --- Cargo.lock | 2 + aries/aries_vcx_ledger/Cargo.toml | 3 +- .../aries_vcx_ledger/src/ledger/cheqd/mod.rs | 81 +++++++++++++------ .../did_cheqd/src/resolution/resolver.rs | 28 +++++-- .../did_cheqd/src/resolution/transformer.rs | 67 ++++++++++++++- did_core/did_resolver/Cargo.toml | 1 + .../src/shared_types/did_resource.rs | 61 ++++++++++++++ did_core/did_resolver/src/shared_types/mod.rs | 1 + 8 files changed, 208 insertions(+), 36 deletions(-) create mode 100644 did_core/did_resolver/src/shared_types/did_resource.rs diff --git a/Cargo.lock b/Cargo.lock index 9829922293..176528c72e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -607,6 +607,7 @@ dependencies = [ "chrono", "did_cheqd", "did_parser_nom", + "did_resolver", "indy-ledger-response-parser", "indy-vdr", "indy-vdr-proxy-client", @@ -1844,6 +1845,7 @@ dependencies = [ "did_parser_nom", "serde", "serde_json", + "typed-builder", ] [[package]] diff --git a/aries/aries_vcx_ledger/Cargo.toml b/aries/aries_vcx_ledger/Cargo.toml index 9ebacd9f87..ee1a3b4774 100644 --- a/aries/aries_vcx_ledger/Cargo.toml +++ b/aries/aries_vcx_ledger/Cargo.toml @@ -9,7 +9,7 @@ edition.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] vdr_proxy_ledger = ["dep:indy-vdr-proxy-client"] -cheqd = ["dep:did_cheqd"] +cheqd = ["dep:did_cheqd", "dep:did_resolver"] [dependencies] aries_vcx_wallet = { path = "../aries_vcx_wallet" } @@ -19,6 +19,7 @@ thiserror = "1.0.40" indy-vdr.workspace = true indy-vdr-proxy-client = { workspace = true, optional = true } did_cheqd = { path = "../../did_core/did_methods/did_cheqd", optional = true } +did_resolver = { path = "../../did_core/did_resolver", optional = true } serde_json = "1.0.95" public_key = { path = "../../did_core/public_key" } async-trait = "0.1.68" diff --git a/aries/aries_vcx_ledger/src/ledger/cheqd/mod.rs b/aries/aries_vcx_ledger/src/ledger/cheqd/mod.rs index 10b3f98569..fdfecdd391 100644 --- a/aries/aries_vcx_ledger/src/ledger/cheqd/mod.rs +++ b/aries/aries_vcx_ledger/src/ledger/cheqd/mod.rs @@ -18,6 +18,7 @@ use async_trait::async_trait; use chrono::DateTime; use did_cheqd::resolution::resolver::DidCheqdResolver; use did_parser_nom::{Did, DidUrl}; +use did_resolver::shared_types::did_resource::{DidResource, DidResourceMetadata}; use models::{ CheqdAnoncredsCredentialDefinition, CheqdAnoncredsRevocationRegistryDefinition, CheqdAnoncredsRevocationStatusList, CheqdAnoncredsSchema, @@ -28,6 +29,9 @@ use crate::errors::error::{VcxLedgerError, VcxLedgerResult}; mod models; +const SCHEMA_RESOURCE_TYPE: &str = "anonCredsSchema"; +const CRED_DEF_RESOURCE_TYPE: &str = "anonCredsCredDef"; +const REV_REG_DEF_RESOURCE_TYPE: &str = "anonCredsRevocRegDef"; const STATUS_LIST_RESOURCE_TYPE: &str = "anonCredsStatusList"; pub struct CheqdAnoncredsLedgerRead { @@ -38,19 +42,49 @@ impl CheqdAnoncredsLedgerRead { pub fn new(resolver: Arc) -> Self { Self { resolver } } -} -// TODO - issue with our anoncreds-types conversions - we are missing `issuerId`, so we make -// issuerId from the resource ID - which assumes it is a legacy sovrin identifier for the resource. -// i.e. split(":")[0]. FIX! we could fix the indyvdr type conversions to include the `issuerId`, and -// make `issuerId` required in our anoncreds-types UPDATE - actually ^, check what credo is doing + fn check_resource_type(&self, resource: &DidResource, expected: &str) -> VcxLedgerResult<()> { + let rtyp = &resource.metadata.resource_type; + if rtyp != expected { + return Err(VcxLedgerError::InvalidLedgerResponse(format!( + "Returned resource is not expected type. Got {rtyp}, expected: {expected}" + ))); + } + Ok(()) + } + + async fn get_rev_reg_def_with_metadata( + &self, + rev_reg_id: &RevocationRegistryDefinitionId, + ) -> VcxLedgerResult<(RevocationRegistryDefinition, DidResourceMetadata)> { + let url = DidUrl::parse(rev_reg_id.to_string())?; + let resource = self.resolver.resolve_resource(&url).await?; + self.check_resource_type(&resource, REV_REG_DEF_RESOURCE_TYPE)?; + + let data: CheqdAnoncredsRevocationRegistryDefinition = + serde_json::from_slice(&resource.content)?; + Ok(( + RevocationRegistryDefinition { + id: rev_reg_id.to_owned(), + revoc_def_type: data.revoc_def_type, + tag: data.tag, + cred_def_id: data.cred_def_id, + value: data.value, + issuer_id: extract_issuer_id(&url)?, + }, + resource.metadata, + )) + } +} #[async_trait] impl AnoncredsLedgerRead for CheqdAnoncredsLedgerRead { async fn get_schema(&self, schema_id: &SchemaId, _: Option<&Did>) -> VcxLedgerResult { let url = DidUrl::parse(schema_id.to_string())?; let resource = self.resolver.resolve_resource(&url).await?; - let data: CheqdAnoncredsSchema = serde_json::from_slice(&resource)?; + self.check_resource_type(&resource, SCHEMA_RESOURCE_TYPE)?; + + let data: CheqdAnoncredsSchema = serde_json::from_slice(&resource.content)?; Ok(Schema { id: schema_id.to_owned(), seq_no: None, @@ -68,7 +102,9 @@ impl AnoncredsLedgerRead for CheqdAnoncredsLedgerRead { ) -> VcxLedgerResult { let url = DidUrl::parse(cred_def_id.to_string())?; let resource = self.resolver.resolve_resource(&url).await?; - let data: CheqdAnoncredsCredentialDefinition = serde_json::from_slice(&resource)?; + self.check_resource_type(&resource, CRED_DEF_RESOURCE_TYPE)?; + + let data: CheqdAnoncredsCredentialDefinition = serde_json::from_slice(&resource.content)?; Ok(CredentialDefinition { id: cred_def_id.to_owned(), schema_id: data.schema_id, @@ -83,17 +119,9 @@ impl AnoncredsLedgerRead for CheqdAnoncredsLedgerRead { &self, rev_reg_id: &RevocationRegistryDefinitionId, ) -> VcxLedgerResult { - let url = DidUrl::parse(rev_reg_id.to_string())?; - let resource = self.resolver.resolve_resource(&url).await?; - let data: CheqdAnoncredsRevocationRegistryDefinition = serde_json::from_slice(&resource)?; - Ok(RevocationRegistryDefinition { - id: rev_reg_id.to_owned(), - revoc_def_type: data.revoc_def_type, - tag: data.tag, - cred_def_id: data.cred_def_id, - value: data.value, - issuer_id: extract_issuer_id(&url)?, - }) + self.get_rev_reg_def_with_metadata(rev_reg_id) + .await + .map(|v| v.0) } async fn get_rev_reg_delta_json( @@ -112,16 +140,15 @@ impl AnoncredsLedgerRead for CheqdAnoncredsLedgerRead { &self, rev_reg_id: &RevocationRegistryDefinitionId, timestamp: u64, - pre_fetched_rev_reg_def: Option<&RevocationRegistryDefinition>, + // unused, we need to fetch anyway for resourceName + _pre_fetched_rev_reg_def: Option<&RevocationRegistryDefinition>, ) -> VcxLedgerResult<(RevocationStatusList, u64)> { let rev_reg_def_url = DidUrl::parse(rev_reg_id.to_string())?; - let rev_reg_def = match pre_fetched_rev_reg_def { - Some(v) => v, - None => &self.get_rev_reg_def_json(rev_reg_id).await?, - }; + let (_def, rev_reg_def_metadata) = self.get_rev_reg_def_with_metadata(rev_reg_id).await?; - let name = &rev_reg_def.tag; // TODO - credo-ts uses the metadata.name or fails (https://docs.cheqd.io/product/advanced/anoncreds/revocation-status-list#same-resource-name-different-resource-type) + //credo-ts uses the metadata.name or fails (https://docs.cheqd.io/product/advanced/anoncreds/revocation-status-list#same-resource-name-different-resource-type) + let name = &rev_reg_def_metadata.resource_name; let did = rev_reg_def_url .did() @@ -141,8 +168,10 @@ impl AnoncredsLedgerRead for CheqdAnoncredsLedgerRead { let query_url = DidUrl::parse(query)?; let resource = self.resolver.resolve_resource(&query_url).await?; - let data: CheqdAnoncredsRevocationStatusList = serde_json::from_slice(&resource)?; - let timestamp = 0; // TODO - from metadata + self.check_resource_type(&resource, STATUS_LIST_RESOURCE_TYPE)?; + + let data: CheqdAnoncredsRevocationStatusList = serde_json::from_slice(&resource.content)?; + let timestamp = resource.metadata.created.timestamp() as u64; let status_list = RevocationStatusList { rev_reg_def_id: Some(rev_reg_id.to_owned()), diff --git a/did_core/did_methods/did_cheqd/src/resolution/resolver.rs b/did_core/did_methods/did_cheqd/src/resolution/resolver.rs index cbc48430b6..287f983158 100644 --- a/did_core/did_methods/did_cheqd/src/resolution/resolver.rs +++ b/did_core/did_methods/did_cheqd/src/resolution/resolver.rs @@ -6,7 +6,10 @@ use did_resolver::{ did_doc::schema::did_doc::DidDocument, did_parser_nom::{Did, DidUrl}, error::GenericError, - shared_types::did_document_metadata::DidDocumentMetadata, + shared_types::{ + did_document_metadata::DidDocumentMetadata, + did_resource::{DidResource, DidResourceMetadata}, + }, traits::resolvable::{resolution_output::DidResolutionOutput, DidResolvable}, }; use http_body_util::combinators::UnsyncBoxBody; @@ -18,6 +21,7 @@ use hyper_util::{ use tokio::sync::Mutex; use tonic::{transport::Uri, Status}; +use super::transformer::CheqdResourceMetadataWithUri; use crate::{ error::{DidCheqdError, DidCheqdResult}, proto::cheqd::{ @@ -184,7 +188,7 @@ impl DidCheqdResolver { } // TODO - better return structure - pub async fn resolve_resource(&self, url: &DidUrl) -> DidCheqdResult> { + pub async fn resolve_resource(&self, url: &DidUrl) -> DidCheqdResult { let method = url.method(); if method != Some("cheqd") { return Err(DidCheqdError::MethodNotSupported(format!("{method:?}"))); @@ -219,7 +223,7 @@ impl DidCheqdResolver { did_id: &str, resource_id: &str, network: &str, - ) -> DidCheqdResult> { + ) -> DidCheqdResult { let mut client = self.client_for_network(network).await?; let request = QueryResourceRequest { @@ -239,9 +243,23 @@ impl DidCheqdResolver { .ok_or(DidCheqdError::InvalidResponse( "Resource query did not return a resource".into(), ))?; - // TODO - metadata + let query_metadata = query_response + .metadata + .ok_or(DidCheqdError::InvalidResponse( + "Resource query did not return metadata".into(), + ))?; + let metadata = DidResourceMetadata::try_from(CheqdResourceMetadataWithUri { + uri: format!( + "did:cheqd:{network}:{}/resources/{}", + query_metadata.collection_id, query_metadata.id + ), + meta: query_metadata, + })?; - Ok(query_resource.data) + Ok(DidResource { + content: query_resource.data, + metadata, + }) } } diff --git a/did_core/did_methods/did_cheqd/src/resolution/transformer.rs b/did_core/did_methods/did_cheqd/src/resolution/transformer.rs index 7154d8dd96..fa45618228 100644 --- a/did_core/did_methods/did_cheqd/src/resolution/transformer.rs +++ b/did_core/did_methods/did_cheqd/src/resolution/transformer.rs @@ -11,15 +11,20 @@ use did_resolver::{ verification_method::{PublicKeyField, VerificationMethod, VerificationMethodType}, }, did_parser_nom::Did, - shared_types::did_document_metadata::DidDocumentMetadata, + shared_types::{ + did_document_metadata::DidDocumentMetadata, did_resource::DidResourceMetadata, + }, }; use serde_json::json; use crate::{ error::{DidCheqdError, DidCheqdResult}, - proto::cheqd::did::v2::{ - DidDoc as CheqdDidDoc, Metadata as CheqdDidDocMetadata, Service as CheqdService, - VerificationMethod as CheqdVerificationMethod, + proto::cheqd::{ + did::v2::{ + DidDoc as CheqdDidDoc, Metadata as CheqdDidDocMetadata, Service as CheqdService, + VerificationMethod as CheqdVerificationMethod, + }, + resource::v2::Metadata as CheqdResourceMetadata, }, }; @@ -204,6 +209,60 @@ impl TryFrom for DidDocumentMetadata { } } +pub(super) struct CheqdResourceMetadataWithUri { + pub uri: String, + pub meta: CheqdResourceMetadata, +} + +impl TryFrom for DidResourceMetadata { + type Error = DidCheqdError; + + fn try_from(value: CheqdResourceMetadataWithUri) -> Result { + let uri = value.uri; + let value = value.meta; + + let Some(created) = value.created else { + return Err(DidCheqdError::InvalidDidDocument(format!( + "created field missing from resource: {value:?}" + )))?; + }; + + let version = (!value.version.trim().is_empty()).then_some(value.version); + let previous_version_id = + (!value.previous_version_id.trim().is_empty()).then_some(value.previous_version_id); + let next_version_id = + (!value.next_version_id.trim().is_empty()).then_some(value.next_version_id); + + let also_known_as = value + .also_known_as + .into_iter() + .map(|aka| { + json!({ + "uri": aka.uri, + "description": aka.description + }) + }) + .collect(); + + DidResourceMetadata::builder() + .resource_uri(uri) + .resource_collection_id(value.collection_id) + .resource_id(value.id) + .resource_name(value.name) + .resource_type(value.resource_type) + .resource_version(version) + .also_known_as(Some(also_known_as)) + .media_type(value.media_type) + .created(prost_timestamp_to_dt(created)?) + .updated(None) + .checksum(value.checksum) + .previous_version_id(previous_version_id) + .next_version_id(next_version_id) + .build(); + todo!() + } +} + fn prost_timestamp_to_dt(mut timestamp: prost_types::Timestamp) -> DidCheqdResult> { timestamp.normalize(); DateTime::from_timestamp(timestamp.seconds, timestamp.nanos.try_into()?).ok_or( diff --git a/did_core/did_resolver/Cargo.toml b/did_core/did_resolver/Cargo.toml index aebe69e1ed..de135ca6bb 100644 --- a/did_core/did_resolver/Cargo.toml +++ b/did_core/did_resolver/Cargo.toml @@ -13,3 +13,4 @@ async-trait = "0.1.68" chrono = { version = "0.4.24", default-features = false, features = ["serde"] } serde = { version = "1.0.160", default-features = false, features = ["derive"] } serde_json = "1.0.103" +typed-builder = "0.19.1" diff --git a/did_core/did_resolver/src/shared_types/did_resource.rs b/did_core/did_resolver/src/shared_types/did_resource.rs new file mode 100644 index 0000000000..7d675855d3 --- /dev/null +++ b/did_core/did_resolver/src/shared_types/did_resource.rs @@ -0,0 +1,61 @@ +use chrono::{DateTime, Utc}; +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use typed_builder::TypedBuilder; + +/// https://w3c-ccg.github.io/DID-Linked-Resources/ +#[derive(Clone, Debug, PartialEq, Default)] +pub struct DidResource { + pub content: Vec, + pub metadata: DidResourceMetadata, +} + +/// https://w3c-ccg.github.io/DID-Linked-Resources/ +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default, TypedBuilder)] +#[serde(default)] +#[serde(rename_all = "camelCase")] +pub struct DidResourceMetadata { + // FUTURE - could be a map according to spec + /// A string or a map that conforms to the rules of RFC3986 URIs which SHOULD directly lead to + /// a location where the resource can be accessed. + /// For example: + /// did:example:46e2af9a-2ea0-4815-999d-730a6778227c/resources/ + /// 0f964a80-5d18-4867-83e3-b47f5a756f02. + pub resource_uri: String, + /// A string that conforms to a method-specific supported unique identifier format. + /// For example, a UUID: 46e2af9a-2ea0-4815-999d-730a6778227c. + pub resource_collection_id: String, + /// A string that uniquely identifies the resource. + /// For example, a UUID: 0f964a80-5d18-4867-83e3-b47f5a756f02. + pub resource_id: String, + /// A string that uniquely names and identifies a resource. This property, along with the + /// resourceType below, can be used to track version changes within a resource. + pub resource_name: String, + /// A string that identifies the type of resource. This property, along with the resourceName + /// above, can be used to track version changes within a resource. Not to be confused with + /// mediaType. + pub resource_type: String, + /// (Optional) A string that identifies the version of the resource. + /// This property is provided by the client and can be any value. + #[serde(skip_serializing_if = "Option::is_none")] + pub resource_version: Option, + /// (Optional) An array that describes alternative URIs for the resource. + #[serde(skip_serializing_if = "Option::is_none")] + pub also_known_as: Option>, + /// A string that identifies the IANA-media type of the resource. + pub media_type: String, + // TODO - check datetime serializes into XML-date-time + /// A string that identifies the time the resource was created, as an XML date-time. + pub created: DateTime, + /// (Optional) A string that identifies the time the resource was updated, as an XML date-time. + #[serde(skip_serializing_if = "Option::is_none")] + pub updated: Option>, + /// A string that may be used to prove that the resource has not been tampered with. + pub checksum: String, + /// (Optional) A string that identifies the previous version of the resource. + #[serde(skip_serializing_if = "Option::is_none")] + pub previous_version_id: Option, + /// (Optional) A string that identifies the next version of the resource. + #[serde(skip_serializing_if = "Option::is_none")] + pub next_version_id: Option, +} diff --git a/did_core/did_resolver/src/shared_types/mod.rs b/did_core/did_resolver/src/shared_types/mod.rs index 4073fd7ad9..cd45b70522 100644 --- a/did_core/did_resolver/src/shared_types/mod.rs +++ b/did_core/did_resolver/src/shared_types/mod.rs @@ -1,2 +1,3 @@ pub mod did_document_metadata; +pub mod did_resource; pub mod media_type; From e78657157c241810fc79b8049df96a606aa2de74 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Thu, 5 Dec 2024 13:31:26 +1000 Subject: [PATCH 29/50] rev status list and resource query working Signed-off-by: George Mulhearn --- aries/aries_vcx_ledger/Cargo.toml | 9 +- aries/aries_vcx_ledger/tests/test_cheqd.rs | 210 ++++++++++++++++++ .../did_methods/did_cheqd/src/error/mod.rs | 2 + .../did_cheqd/src/resolution/resolver.rs | 156 +++++++++++-- .../did_cheqd/src/resolution/transformer.rs | 9 +- 5 files changed, 366 insertions(+), 20 deletions(-) create mode 100644 aries/aries_vcx_ledger/tests/test_cheqd.rs diff --git a/aries/aries_vcx_ledger/Cargo.toml b/aries/aries_vcx_ledger/Cargo.toml index ee1a3b4774..3f5e991960 100644 --- a/aries/aries_vcx_ledger/Cargo.toml +++ b/aries/aries_vcx_ledger/Cargo.toml @@ -29,5 +29,12 @@ log = "0.4.17" serde = { version = "1.0.159", features = ["derive"] } lru = { version = "0.12.0" } tokio = { version = "1.38" } -chrono = { version = "0.4", default-features = false } +chrono = { version = "0.4", default-features = false, features = ["alloc"] } bitvec = "1.0.1" + +[dev-dependencies] +tokio = { version = "1.38.0", default-features = false, features = [ + "macros", + "rt", +] } +chrono = { version = "0.4", default-features = true } diff --git a/aries/aries_vcx_ledger/tests/test_cheqd.rs b/aries/aries_vcx_ledger/tests/test_cheqd.rs new file mode 100644 index 0000000000..5933dfdc5d --- /dev/null +++ b/aries/aries_vcx_ledger/tests/test_cheqd.rs @@ -0,0 +1,210 @@ +use std::sync::Arc; + +use anoncreds_types::data_types::identifiers::{ + cred_def_id::CredentialDefinitionId, rev_reg_def_id::RevocationRegistryDefinitionId, + schema_id::SchemaId, +}; +use aries_vcx_ledger::ledger::{base_ledger::AnoncredsLedgerRead, cheqd::CheqdAnoncredsLedgerRead}; +use chrono::{DateTime, Utc}; +use did_cheqd::resolution::resolver::DidCheqdResolver; +use serde_json::json; + +#[tokio::test] +async fn test_resolve_schema_vector() { + let id = "did:cheqd:testnet:d37eba59-513d-42d3-8f9f-d1df0548b675/resources/\ + a7e2fc0b-5f6c-466d-911f-3ed9909f98a0"; + + let reader = CheqdAnoncredsLedgerRead::new(Arc::new(DidCheqdResolver::new(Default::default()))); + let schema = reader + .get_schema(&SchemaId::new_unchecked(id), None) + .await + .unwrap(); + + assert_eq!( + schema.id.0, + "did:cheqd:testnet:d37eba59-513d-42d3-8f9f-d1df0548b675/resources/\ + a7e2fc0b-5f6c-466d-911f-3ed9909f98a0" + ); + assert!(schema.seq_no.is_none()); + assert_eq!( + schema.name, + "Faber College221a463c-9160-41bd-839c-26c0154e64b4" + ); + assert_eq!(schema.version, "1.0.0"); + assert_eq!( + schema.attr_names.0, + vec!["name".to_string(), "degree".to_string(), "date".to_string()] + ); + assert_eq!( + schema.issuer_id.0, + "did:cheqd:testnet:d37eba59-513d-42d3-8f9f-d1df0548b675" + ); +} + +#[tokio::test] +async fn test_resolve_cred_def_vector() { + let id = "did:cheqd:testnet:e5d13e49-9f5d-4ec1-b0f6-43e43e211fdc/resources/\ + 796f4d32-ceb2-4549-ac2f-5270442066ee"; + + let reader = CheqdAnoncredsLedgerRead::new(Arc::new(DidCheqdResolver::new(Default::default()))); + let cred_def = reader + .get_cred_def(&CredentialDefinitionId::new_unchecked(id), None) + .await + .unwrap(); + + let expected_cred_def = json!({ + "id": "did:cheqd:testnet:e5d13e49-9f5d-4ec1-b0f6-43e43e211fdc/resources/796f4d32-ceb2-4549-ac2f-5270442066ee", + "schemaId": "did:cheqd:testnet:e5d13e49-9f5d-4ec1-b0f6-43e43e211fdc/resources/441dd8ac-5132-4f64-a899-b95e6631861e", + "issuerId": "did:cheqd:testnet:e5d13e49-9f5d-4ec1-b0f6-43e43e211fdc", + "type": "CL", + "tag": "default", + "value": { + "primary": { + "n": "101775425686705322446321729042513323885366249575341827532852151406029439141945446540758073370857140650173543806620665009319990704696336867406228341102050525062347572470125847326218665243292282264450928863478570405137509031729993280909749863406879170040618211281523178059425360274769809374009133917080596452472404002929533556061638640203000980751755775872098282217341230637597866343991247907713086791452810236342936381540330526648988208357641862302546515645514361066795780511377402835905056549804798920667891392124801399775162573084938362756949887199195057995844386465801420665147294058855188546320799079663835174965161", + "s": "87624888798698822624423723118022809956578348937987561814948126500576219529138836392203224198856904274580002516694066594875873709134352028429835540535481267491635062762312964551217817275494607969045880749427396603031296648191143611156088073589185938269488488710758969627092198856856923016111781105026554515570693238770759473619839075955094865571664244739744514364819888950198503617844415579864953624998989292124086306326904837728507294638098267220789662137529137088453854836926570472177996704875536555330577801472880881494686752967061366433608898978631273502532992063649958617359359105975313298611541375812686478449038", + "r": { + "master_secret": "91924390643616684447850600547636799126754942750676961814085841416767517190041327602185387580658201961018441581408151006589910605450989653472590754296936606411587277500591300185962955561382125964973024308169242022915814560288197996510864084499323589139928149142636050230482921777834206450457769957179088070681863843269743734589083210580654397696548923614457471055030224454430850991434040684872112181784382757277123431379517419634053875223449800478697799219665093330299855414452721993787344846427989123844376930340324838760730841881922239261134345165306574342224223006710126470962389247658692615899692622733364593917564", + "dataload": "67714311012680607861506009159005649926100729749085079545683454286626632138688065577440485138428200490485338821059098371694307470028480026620243200576189622077496672555428629091259952610415973355058680447309063025743992477107070451623444621247413013233746035427316025697312475570466580668335703497887313077562889740624862997672438829468032595482449521331150586223865869041877654993640507137080181293240650234816519778512756819260970205819993241324592879273813227162717013131055606974830594578099412351827306325727807837670155477487273346541222802392212114521431844422126972523175992819888243089660896279345668836709183" + }, + "rctxt": "70939857802453506951149531957606930306640909143475371737027498474152925628494791068427574134203017421399121411176717498176846791145767680818780201808144435771494206471213311901071561885391866584823165735626586292923926605780832222900819531483444405585980754893162270863536237119860353096313485759974542267053904367917010014776300492094349532540865655521444795825149399229035168301897753439893554059797022750502266578483363311220307405821402958792359030164217593034199227560018630509640528678991350608730838863727066178052927862093157207477972326979317508513953451471067387162273207269626177777770178388199904693271885", + "z": "67232321822071084762251502223976923452971987672236221455852097322998038231254751227728590284858878856391984973291870462921522030038401971062122863827666305436738444365691249161806642192223615405177957760215302017704093487843885193856291620515859197624091514138527124658905269978674424356277491558952327833769860308310713639320922734643110516571614031976998124656051686500162012298658320291610287606636134513132238361082981123202624198501889516057149568201642936231925672511435865393828765935813568402464860650327397205857299165873490962876370815478186692229961439123671741775783729284710421491763990499547934996243081" + } + } + }); + assert_eq!(serde_json::to_value(cred_def).unwrap(), expected_cred_def); +} + +// https://testnet-explorer.cheqd.io/transactions/92C31ED20512FEE73EA4D8A6C8E63E652AA61A14D4F8C00203312EA185419CB9 +#[tokio::test] +async fn test_resolve_rev_reg_def_vector() { + let id = "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b/resources/\ + 4f265d83-4657-4c37-ba80-c66cc399457e"; + + let reader = CheqdAnoncredsLedgerRead::new(Arc::new(DidCheqdResolver::new(Default::default()))); + let rev_reg_def = reader + .get_rev_reg_def_json(&RevocationRegistryDefinitionId::new_unchecked(id)) + .await + .unwrap(); + + let expected_rev_reg_def = json!({ + "id": id, + "issuerId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b", + "credDefId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b/resources/8372c1bc-907d-44a9-86be-ac3672b26e2e", + "revocDefType": "CL_ACCUM", + "tag": "1.0", + "value": { + "maxCredNum": 5, + "publicKeys": { + "accumKey": { + "z": "1 10D3560CAE0591EEA7D7A63E1A362FC31448EF321E04FD75F248BBAF02DE9749 1 118C4B0C7F3D86D46C22D62BAE7E613B137A879B50EFDFC56451AB9012BA57A0 1 23D6952F9D058744D4930D1DE6D79548BDCA3EE8BAAF64B712668E52A1290547 1 14C4C4389D92A99C4DA7E6CC2BD0C82E2809D3CD202CD2F0AD6C33D75AA39049 1 174EACBC7981492A791A72D57C6CB9FE488A679C4A5674E4F3C247D73A827384 1 0172B8961122D4D825B282CA1CD1BBC3B8DC459994C9FE2827CDF74B3AB08D38 1 181159044E453DC59FF320E9E08C666176F6B9309E162E2DA4FC1DB3156F7B1F 1 2323CEBFB26C6D28CBAF5F87F155362C6FA14AFA0EBA7DE2B4154FE4082E30FD 1 2354CB1624B42A284B41E5B3B4489C2795DBA9B88A725005555FB698AFF97260 1 07EEEF48EF52E5B15FD4AC28F0DAEDE0A259A27500855992307518A0DBE29A83 1 00FE73BCDB27D1DAD37E4F0E424372CA9548F11B4EC977DCCCC53D99A5C66F36 1 07E9DC0DD2163A66EDA84CD6BF282C7E18CB821762B6047CA1AB9FBE94DC6546" + } + }, + "tailsHash": "GW1bmjcMmtHnLwbWrabX4sWYVopJMEvQWgYMAEDmbJS3", + "tailsLocation": "GW1bmjcMmtHnLwbWrabX4sWYVopJMEvQWgYMAEDmbJS3" + } + }); + assert_eq!( + serde_json::to_value(rev_reg_def).unwrap(), + expected_rev_reg_def + ); +} + +// https://resolver.cheqd.net/1.0/identifiers/did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b?resourceName=275990cc056b46176a7122cfd888f46a2bd8e3d45a71d5ff20764a874ed02edd&resourceType=anonCredsStatusList&resourceMetadata=true +// reset: https://testnet-explorer.cheqd.io/transactions/356F65125E585B9F439C423F2AD7DE73ADF4DC9A0811AA8EE5D03D63B1872DC0 +// 2024-12-04T22:14:55Z +// update 1: https://testnet-explorer.cheqd.io/transactions/ADF7D562A5005576FA6EF8DC864DAA306EB62C40911FEB5B30C8F98968AE7B51 +// 2024-12-04T22:15:07Z +// update 2: https://testnet-explorer.cheqd.io/transactions/222FF2D023C2C9A097BB38F3875F072DF8DEC7B0CBD46AC3459C9B4C3C74382F +// 2024-12-04T22:15:18Z +// update 3: https://testnet-explorer.cheqd.io/transactions/791D57B8C49C270B3EDA0E9E7E00811CA828190C2D6517FDE8E40CD8FE445E1C +// 2024-12-04T22:15:30Z +#[tokio::test] +async fn test_resolve_rev_status_list_versions() { + let def_id = "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b/resources/\ + 4f265d83-4657-4c37-ba80-c66cc399457e"; + let def_id = RevocationRegistryDefinitionId::new_unchecked(def_id); + + let init_time = DateTime::parse_from_rfc3339("2024-12-04T22:14:55Z") + .unwrap() + .timestamp() as u64; + let update1_time = DateTime::parse_from_rfc3339("2024-12-04T22:15:07Z") + .unwrap() + .timestamp() as u64; + let update2_time = DateTime::parse_from_rfc3339("2024-12-04T22:15:18Z") + .unwrap() + .timestamp() as u64; + let update3_time = DateTime::parse_from_rfc3339("2024-12-04T22:15:30Z") + .unwrap() + .timestamp() as u64; + + let reader = CheqdAnoncredsLedgerRead::new(Arc::new(DidCheqdResolver::new(Default::default()))); + + // scenario 1: get most recent + let now = Utc::now().timestamp() as u64; + let (status_list, update_time) = reader + .get_rev_status_list(&def_id, now, None) + .await + .unwrap(); + assert_eq!(update_time, update3_time); + assert_eq!( + serde_json::to_value(status_list).unwrap(), + json!({ + "issuerId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b", + "revRegDefId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b/resources/4f265d83-4657-4c37-ba80-c66cc399457e", + "revocationList": [1,1,1,1,0], + "currentAccumulator": "21 114BE4F2BBAAF18F07E994D74B28347FA0BEC500A616B47F57F2E0B0864F7602E 21 12AB68E307C5F2AA30F34A03ADB298C7F4C02555649E510919979C2AEB49CCDF1 6 5FB9FB957339A842130C84FC98240A163E56DC58B96423F1EFD53E9106671B94 4 28F2F8297E345FFF55CDEE87C83DE471486826C91EBBA2C39570A46013B5BFBA 6 565A830A4358E1F6F21A10804C23E36D739B5630C6A188D760F4B6F434D1311D 4 14F87165B42A780974AC70669DC3CF629F1103DF73AE15AC11A1151883A91941", + "timestamp": update3_time + }) + ); + + // scenario 2: between update 2 & 3 + let (status_list, update_time) = reader + .get_rev_status_list(&def_id, update2_time + 3, None) + .await + .unwrap(); + assert_eq!(update_time, update2_time); + assert_eq!( + serde_json::to_value(status_list).unwrap(), + json!({ + "issuerId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b", + "currentAccumulator": "21 125DF938B3B772619CB43E561D69004CF09667376E9CD53C818D84860BAE3D1D9 21 11ECFC5F9B469AC74E2A0E329F86C6E60B423A53CAC5AE7A4DBE7A978BFFC0DA1 6 6FAD628FED470FF640BF2C5DB57C2C18D009645DBEF15D4AF710739D2AD93E2D 4 22093A3300411B059B8BB7A8C3296A2ED9C4C8E00106C3B2BAD76E25AC792063 6 71D70ECA81BCE610D1C22CADE688AF4A122C8258E8B306635A111D0A35A7238A 4 1E80F38ABA3A966B8657D722D4E956F076BB2F5CCF36AA8942E65500F8898FF3", + "revRegDefId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b/resources/4f265d83-4657-4c37-ba80-c66cc399457e", + "revocationList": [1,1,1,0,0], + "timestamp": update2_time + }) + ); + + // scenario 3: between update 1 & 2 + let (status_list, update_time) = reader + .get_rev_status_list(&def_id, update1_time + 3, None) + .await + .unwrap(); + assert_eq!(update_time, update1_time); + assert_eq!( + serde_json::to_value(status_list).unwrap(), + json!({ + "issuerId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b", + "currentAccumulator": "21 136FA865B5CD0AEA1DA05BE412C6E06C23066C338D39C5B79C5E1AE1D5BA20AAA 21 124182E098BE418B9DBECF600EEA3D070EDB85D6B412EE75B4B43C440FEA2E631 6 669D66FB3BC245B4EF892B8DB5A330ACA6A4CE6706FB58D9B487C0487DBB5C04 4 2C5C9551DFE2A4AE71D355DD3A981F155F51B9BCF8E2ED8B8263726DDF60D09C 6 7243CF31A80313C254F51D2B0A3573320B885178F36F4AE1E8FF4A520EF9CDCA 4 1B8DBE9563FAD9FBF8B75BCE41C9425E1D15EE0B3D195D0A86AD8A2C91D5BB73", + "revRegDefId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b/resources/4f265d83-4657-4c37-ba80-c66cc399457e", + "revocationList": [1,1,0,0,0], + "timestamp": update1_time + }) + ); + + // scenario 4: between init & update 1 + let (status_list, update_time) = reader + .get_rev_status_list(&def_id, init_time + 3, None) + .await + .unwrap(); + assert_eq!(update_time, init_time); + assert_eq!( + serde_json::to_value(status_list).unwrap(), + json!({ + "issuerId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b", + "currentAccumulator": "1 0443A0BC791EE82B8F34066404B36E81E0CE68B64BD2A48A55587E4585B16CCA 1 0343A5D644B28DCC0EAF9C6D3E104DC0F61FCD711AFE93DB67031905DAA5F654 1 02CE577295DF112BB2C7F16250D4593FC922B074436EC0F4F124E2409EF99785 1 1692EE5DFE9885809DA503A2EEDC4EECDA5D7D415C743E3931576EFD72FB51AC 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8 1 0000000000000000000000000000000000000000000000000000000000000000", + "revRegDefId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b/resources/4f265d83-4657-4c37-ba80-c66cc399457e", + "revocationList": [0,0,0,0,0], + "timestamp": init_time + }) + ); +} diff --git a/did_core/did_methods/did_cheqd/src/error/mod.rs b/did_core/did_methods/did_cheqd/src/error/mod.rs index 35f88e2940..a60cbf775b 100644 --- a/did_core/did_methods/did_cheqd/src/error/mod.rs +++ b/did_core/did_methods/did_cheqd/src/error/mod.rs @@ -24,6 +24,8 @@ pub enum DidCheqdError { InvalidDidDocument(String), #[error("Invalid DID Url: {0}")] InvalidDidUrl(String), + #[error("Resource could not be found: {0}")] + ResourceNotFound(String), #[error("Parsing error: {0}")] ParsingError(#[from] ParsingErrorSource), #[error(transparent)] diff --git a/did_core/did_methods/did_cheqd/src/resolution/resolver.rs b/did_core/did_methods/did_cheqd/src/resolution/resolver.rs index 287f983158..a50b40c7cb 100644 --- a/did_core/did_methods/did_cheqd/src/resolution/resolver.rs +++ b/did_core/did_methods/did_cheqd/src/resolution/resolver.rs @@ -1,7 +1,8 @@ -use std::collections::HashMap; +use std::{cmp::Ordering, collections::HashMap}; use async_trait::async_trait; use bytes::Bytes; +use chrono::{DateTime, Utc}; use did_resolver::{ did_doc::schema::did_doc::DidDocument, did_parser_nom::{Did, DidUrl}, @@ -26,7 +27,10 @@ use crate::{ error::{DidCheqdError, DidCheqdResult}, proto::cheqd::{ did::v2::{query_client::QueryClient as DidQueryClient, QueryDidDocRequest}, - resource::v2::{query_client::QueryClient as ResourceQueryClient, QueryResourceRequest}, + resource::v2::{ + query_client::QueryClient as ResourceQueryClient, Metadata as CheqdResourceMetadata, + QueryCollectionResourcesRequest, QueryResourceRequest, + }, }, }; @@ -187,7 +191,7 @@ impl DidCheqdResolver { Ok(output_builder.build()) } - // TODO - better return structure + /// TODO - explain what is and isn't supported pub async fn resolve_resource(&self, url: &DidUrl) -> DidCheqdResult { let method = url.method(); if method != Some("cheqd") { @@ -195,27 +199,50 @@ impl DidCheqdResolver { } let network = url.namespace().unwrap_or(MAINNET_NAMESPACE); + let did_id = url + .id() + .ok_or(DidCheqdError::InvalidDidUrl(format!("missing ID {url}")))?; // 1. resolve by exact reference: /reference/asdf if let Some(path) = url.path() { let Some(resource_id) = path.strip_prefix("/resources/") else { - // TODO - todo!() + return Err(DidCheqdError::InvalidDidUrl(format!( + "DID Resource URL has a path without `/resources/`: {path}" + ))); }; - let did_id = url - .id() - .ok_or(DidCheqdError::InvalidDidUrl(format!("missing ID {url}")))?; return self .resolve_resource_by_id(did_id, resource_id, network) .await; } - // 2. resolve by name & type - // 2.a. resolve by name & type & `version` - // 2.b. resolve by name & type & closest to `resourceVersion` - // 2.c. resolve by name & type & closest to `now` - todo!() + // 2. resolve by name & type & time (if any) + let params = url.queries(); + let resource_name = params.get("resourceName"); + let resource_type = params.get("resourceType"); + let version_time = params.get("resourceVersionTime"); + + let (Some(resource_name), Some(resource_type)) = (resource_name, resource_type) else { + return Err(DidCheqdError::InvalidDidUrl(format!( + "Resolver can only resolve by resource ID or name+type combination" + )))?; + }; + // determine desired version_time, either from param, or *now* + let version_time = match version_time { + Some(v) => DateTime::parse_from_rfc3339(v) + .map_err(|e| DidCheqdError::InvalidDidUrl(e.to_string()))? + .to_utc(), + None => Utc::now(), + }; + + self.resolve_resource_by_name_type_and_time( + did_id, + resource_name, + resource_type, + version_time, + network, + ) + .await } async fn resolve_resource_by_id( @@ -261,6 +288,43 @@ impl DidCheqdResolver { metadata, }) } + + async fn resolve_resource_by_name_type_and_time( + &self, + did_id: &str, + name: &str, + rtyp: &str, + time: DateTime, + network: &str, + ) -> DidCheqdResult { + let mut client = self.client_for_network(network).await?; + + let response = client + .resources + .collection_resources(QueryCollectionResourcesRequest { + collection_id: did_id.to_owned(), + // FUTURE - pagination + pagination: None, + }) + .await?; + + let query_response = response.into_inner(); + let resources = query_response.resources; + let mut filtered: Vec<_> = + filter_resources_by_name_and_type(resources.iter(), name, rtyp).collect(); + filtered.sort_by(|a, b| desc_chronological_sort_resources(*a, *b)); + + let resource_meta = find_resource_just_before_time(filtered.into_iter(), time); + + let Some(meta) = resource_meta else { + return Err(DidCheqdError::ResourceNotFound(format!( + "network: {network}, collection: {did_id}, name: {name}, type: {rtyp}, time: \ + {time}" + ))); + }; + + self.resolve_resource_by_id(did_id, &meta.id, network).await + } } /// Assembles a hyper client which: @@ -282,6 +346,72 @@ fn native_tls_hyper_client() -> DidCheqdResult { .build(connector)) } +fn filter_resources_by_name_and_type<'a>( + resources: impl Iterator + 'a, + name: &'a str, + rtyp: &'a str, +) -> impl Iterator + 'a { + resources.filter(move |r| r.name == name && r.resource_type == rtyp) +} + +fn desc_chronological_sort_resources( + b: &CheqdResourceMetadata, + a: &CheqdResourceMetadata, +) -> Ordering { + let (a_secs, a_ns) = a + .created + .map(|v| { + let v = v.normalized(); + (v.seconds, v.nanos) + }) + .unwrap_or((0, 0)); + let (b_secs, b_ns) = b + .created + .map(|v| { + let v = v.normalized(); + (v.seconds, v.nanos) + }) + .unwrap_or((0, 0)); + + match a_secs.cmp(&b_secs) { + Ordering::Equal => a_ns.cmp(&b_ns), + res => res, + } +} + +/// assuming `resources` is sorted by `.created` time in descending order, find +/// the resource which is closest to `before_time`, but NOT after. +/// +/// Returns a reference to this resource if it exists. +/// +/// e.g.: +/// resources: [{created: 20}, {created: 15}, {created: 10}, {created: 5}] +/// before_time: 14 +/// returns: {created: 10} +/// +/// resources: [{created: 20}, {created: 15}, {created: 10}, {created: 5}] +/// before_time: 4 +/// returns: None +fn find_resource_just_before_time<'a>( + resources: impl Iterator, + before_time: DateTime, +) -> Option<&'a CheqdResourceMetadata> { + let before_epoch = before_time.timestamp(); + + for r in resources { + let Some(created) = r.created else { + continue; + }; + + let created_epoch = created.normalized().seconds; + if created_epoch < before_epoch { + return Some(r); + } + } + + None +} + #[cfg(test)] mod unit_tests { use super::*; diff --git a/did_core/did_methods/did_cheqd/src/resolution/transformer.rs b/did_core/did_methods/did_cheqd/src/resolution/transformer.rs index fa45618228..c9ce01df37 100644 --- a/did_core/did_methods/did_cheqd/src/resolution/transformer.rs +++ b/did_core/did_methods/did_cheqd/src/resolution/transformer.rs @@ -11,9 +11,7 @@ use did_resolver::{ verification_method::{PublicKeyField, VerificationMethod, VerificationMethodType}, }, did_parser_nom::Did, - shared_types::{ - did_document_metadata::DidDocumentMetadata, did_resource::DidResourceMetadata, - }, + shared_types::{did_document_metadata::DidDocumentMetadata, did_resource::DidResourceMetadata}, }; use serde_json::json; @@ -244,7 +242,7 @@ impl TryFrom for DidResourceMetadata { }) .collect(); - DidResourceMetadata::builder() + Ok(DidResourceMetadata::builder() .resource_uri(uri) .resource_collection_id(value.collection_id) .resource_id(value.id) @@ -258,8 +256,7 @@ impl TryFrom for DidResourceMetadata { .checksum(value.checksum) .previous_version_id(previous_version_id) .next_version_id(next_version_id) - .build(); - todo!() + .build()) } } From 3461fc0c05773edfb90d95538b1bdf320d4b185d Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Thu, 5 Dec 2024 15:10:00 +1000 Subject: [PATCH 30/50] some bounds and comments Signed-off-by: George Mulhearn --- aries/aries_vcx_ledger/tests/test_cheqd.rs | 1 + .../anoncreds_types/src/utils/conversions.rs | 23 +++++++++++++++++-- .../did_cheqd/src/resolution/resolver.rs | 2 ++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/aries/aries_vcx_ledger/tests/test_cheqd.rs b/aries/aries_vcx_ledger/tests/test_cheqd.rs index 5933dfdc5d..aba9757d74 100644 --- a/aries/aries_vcx_ledger/tests/test_cheqd.rs +++ b/aries/aries_vcx_ledger/tests/test_cheqd.rs @@ -109,6 +109,7 @@ async fn test_resolve_rev_reg_def_vector() { ); } +// test status list resolution from credo-ts uploaded vectors // https://resolver.cheqd.net/1.0/identifiers/did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b?resourceName=275990cc056b46176a7122cfd888f46a2bd8e3d45a71d5ff20764a874ed02edd&resourceType=anonCredsStatusList&resourceMetadata=true // reset: https://testnet-explorer.cheqd.io/transactions/356F65125E585B9F439C423F2AD7DE73ADF4DC9A0811AA8EE5D03D63B1872DC0 // 2024-12-04T22:14:55Z diff --git a/aries/misc/anoncreds_types/src/utils/conversions.rs b/aries/misc/anoncreds_types/src/utils/conversions.rs index b392eadb2f..72228c678c 100644 --- a/aries/misc/anoncreds_types/src/utils/conversions.rs +++ b/aries/misc/anoncreds_types/src/utils/conversions.rs @@ -16,14 +16,33 @@ pub fn from_revocation_registry_delta_to_revocation_status_list( let issuance_by_default = true; let default_state = if issuance_by_default { 0 } else { 1 }; let mut revocation_list = bitvec![default_state; rev_reg_def.value.max_cred_num as usize]; + let revocation_len = revocation_list.len(); for issued in &delta.issued { - // TODO - bounds + if revocation_len <= *issued as usize { + return Err(crate::Error::from_msg( + crate::ErrorKind::ConversionError, + format!( + "Error whilst constructing a revocation status list from the ledger's delta. \ + Ledger delta reported an issuance for cred_rev_id '{issued}', but the \ + revocation_list max size is {revocation_len}" + ), + )); + } revocation_list.insert(*issued as usize, false); } for revoked in &delta.revoked { - // TODO - bounds + if revocation_len <= *revoked as usize { + return Err(crate::Error::from_msg( + crate::ErrorKind::ConversionError, + format!( + "Error whilst constructing a revocation status list from the ledger's delta. \ + Ledger delta reported an revocation for cred_rev_id '{revoked}', but the \ + revocation_list max size is {revocation_len}" + ), + )); + } revocation_list.insert(*revoked as usize, true); } diff --git a/did_core/did_methods/did_cheqd/src/resolution/resolver.rs b/did_core/did_methods/did_cheqd/src/resolution/resolver.rs index a50b40c7cb..48851bf4b9 100644 --- a/did_core/did_methods/did_cheqd/src/resolution/resolver.rs +++ b/did_core/did_methods/did_cheqd/src/resolution/resolver.rs @@ -446,4 +446,6 @@ mod unit_tests { let e = resolver.resolve_did(&did).await.unwrap_err(); assert!(matches!(e, DidCheqdError::BadConfiguration(_))); } + + // TODO - unit test resources etc } From 10695cd879449c113eb28b959f2deeadce0d2a7b Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Thu, 5 Dec 2024 16:39:32 +1000 Subject: [PATCH 31/50] fmt typing Signed-off-by: George Mulhearn --- .../protocols/cred_issuance/v2/issue_credential.rs | 7 +++++-- .../protocols/cred_issuance/v2/offer_credential.rs | 8 ++++++-- .../protocols/cred_issuance/v2/propose_credential.rs | 8 ++++++-- .../protocols/cred_issuance/v2/request_credential.rs | 8 ++++++-- .../src/msg_fields/protocols/present_proof/v2/present.rs | 9 ++++++--- .../src/msg_fields/protocols/present_proof/v2/propose.rs | 9 ++++++--- .../src/msg_fields/protocols/present_proof/v2/request.rs | 9 ++++++--- 7 files changed, 41 insertions(+), 17 deletions(-) diff --git a/aries/messages/src/msg_fields/protocols/cred_issuance/v2/issue_credential.rs b/aries/messages/src/msg_fields/protocols/cred_issuance/v2/issue_credential.rs index 99c22e1de4..528124ccb8 100644 --- a/aries/messages/src/msg_fields/protocols/cred_issuance/v2/issue_credential.rs +++ b/aries/messages/src/msg_fields/protocols/cred_issuance/v2/issue_credential.rs @@ -43,8 +43,11 @@ pub struct IssueCredentialV2Decorators { pub enum IssueCredentialAttachmentFormatType { #[serde(rename = "aries/ld-proof-vc@v1.0")] AriesLdProofVc1_0, - #[serde(rename = "anoncreds/cred@v2.0")] - AnoncredsCredential2_0, + #[serde( + rename = "anoncreds/credential@v1.0", + alias = "anoncreds/cred@v2.0" // TODO - this is wrong, fix once acapy fixes + )] + AnoncredsCredential1_0, #[serde(rename = "hlindy/cred@v2.0")] HyperledgerIndyCredential2_0, } diff --git a/aries/messages/src/msg_fields/protocols/cred_issuance/v2/offer_credential.rs b/aries/messages/src/msg_fields/protocols/cred_issuance/v2/offer_credential.rs index 3f42354653..413898845a 100644 --- a/aries/messages/src/msg_fields/protocols/cred_issuance/v2/offer_credential.rs +++ b/aries/messages/src/msg_fields/protocols/cred_issuance/v2/offer_credential.rs @@ -45,8 +45,12 @@ pub enum OfferCredentialAttachmentFormatType { DifCredentialManifest1_0, #[serde(rename = "hlindy/cred-abstract@v2.0")] HyperledgerIndyCredentialAbstract2_0, - #[serde(rename = "anoncreds/cred-abstract@v2.0")] - AnoncredsCredentialAbstract2_0, + #[serde( + rename = "anoncreds/credential-offer@v1.0", + alias = "anoncreds/cred-abstract@v2.0", // TODO - remove after acapy fix + alias = "anoncreds/credential@v1.0" // TODO - remove after credo-ts fix + )] + AnoncredsCredentialOffer1_0, #[serde(rename = "aries/ld-proof-vc-detail@v1.0")] AriesLdProofVcDetail1_0, } diff --git a/aries/messages/src/msg_fields/protocols/cred_issuance/v2/propose_credential.rs b/aries/messages/src/msg_fields/protocols/cred_issuance/v2/propose_credential.rs index f71cfd3630..3a5d8282dc 100644 --- a/aries/messages/src/msg_fields/protocols/cred_issuance/v2/propose_credential.rs +++ b/aries/messages/src/msg_fields/protocols/cred_issuance/v2/propose_credential.rs @@ -44,8 +44,12 @@ pub enum ProposeCredentialAttachmentFormatType { DifCredentialManifest1_0, #[serde(rename = "aries/ld-proof-vc-detail@v1.0")] AriesLdProofVcDetail1_0, - #[serde(rename = "anoncreds/cred-filter@v2.0")] - AnoncredCredentialFilter2_0, + #[serde( + rename = "anoncreds/credential-filter@v1.0", + // TODO - this is wrong, fix once acapy fixes + alias = "anoncreds/cred-filter@v2.0" + )] + AnoncredCredentialFilter1_0, #[serde(rename = "hlindy/cred-filter@v2.0")] HyperledgerIndyCredentialFilter2_0, } diff --git a/aries/messages/src/msg_fields/protocols/cred_issuance/v2/request_credential.rs b/aries/messages/src/msg_fields/protocols/cred_issuance/v2/request_credential.rs index 933523c54d..1cefa9c2ed 100644 --- a/aries/messages/src/msg_fields/protocols/cred_issuance/v2/request_credential.rs +++ b/aries/messages/src/msg_fields/protocols/cred_issuance/v2/request_credential.rs @@ -40,8 +40,12 @@ pub enum RequestCredentialAttachmentFormatType { DifCredentialManifest1_0, #[serde(rename = "hlindy/cred-req@v2.0")] HyperledgerIndyCredentialRequest2_0, - #[serde(rename = "anoncreds/cred-req@v2.0")] - AnoncredsCredentialRequest2_0, + #[serde( + rename = "anoncreds/credential-request@v1.0", + // TODO - this is wrong, fix once acapy fixes + alias = "anoncreds/cred-req@v2.0", + )] + AnoncredsCredentialRequest1_0, #[serde(rename = "aries/ld-proof-vc-detail@v1.0")] AriesLdProofVcDetail1_0, } diff --git a/aries/messages/src/msg_fields/protocols/present_proof/v2/present.rs b/aries/messages/src/msg_fields/protocols/present_proof/v2/present.rs index 473f77e135..43179185a4 100644 --- a/aries/messages/src/msg_fields/protocols/present_proof/v2/present.rs +++ b/aries/messages/src/msg_fields/protocols/present_proof/v2/present.rs @@ -42,9 +42,12 @@ pub struct PresentationV2Decorators { pub enum PresentationAttachmentFormatType { #[serde(rename = "hlindy/proof@v2.0")] HyperledgerIndyProof2_0, - // TODO - FIX - wrong ver, match acapy - #[serde(rename = "anoncreds/proof@v2.0")] - AnoncredsProof2_0, + #[serde( + rename = "anoncreds/proof@v1.0", + // TODO - FIX - wrong ver, match acapy + alias = "anoncreds/proof@v2.0" + )] + AnoncredsProof1_0, #[serde(rename = "dif/presentation-exchange/submission@v1.0")] DifPresentationExchangeSubmission1_0, } diff --git a/aries/messages/src/msg_fields/protocols/present_proof/v2/propose.rs b/aries/messages/src/msg_fields/protocols/present_proof/v2/propose.rs index 0e2adc3e1a..e2c2f539b2 100644 --- a/aries/messages/src/msg_fields/protocols/present_proof/v2/propose.rs +++ b/aries/messages/src/msg_fields/protocols/present_proof/v2/propose.rs @@ -43,9 +43,12 @@ pub enum ProposePresentationAttachmentFormatType { DifPresentationExchangeDefinitions1_0, #[serde(rename = "hlindy/proof-req@v2.0")] HyperledgerIndyProofRequest2_0, - // TODO - FIX - wrong ver, match acapy - #[serde(rename = "anoncreds/proof-req@v2.0")] - AnoncredsProofRequest2_0, + #[serde( + rename = "anoncreds/proof-request@v1.0", + // TODO - FIX - wrong ver, match acapy + alias = "anoncreds/proof-req@v2.0" + )] + AnoncredsProofRequest1_0, } #[cfg(test)] diff --git a/aries/messages/src/msg_fields/protocols/present_proof/v2/request.rs b/aries/messages/src/msg_fields/protocols/present_proof/v2/request.rs index 5dd52b9a27..3b677dea3b 100644 --- a/aries/messages/src/msg_fields/protocols/present_proof/v2/request.rs +++ b/aries/messages/src/msg_fields/protocols/present_proof/v2/request.rs @@ -44,9 +44,12 @@ pub struct RequestPresentationV2Decorators { pub enum PresentationRequestAttachmentFormatType { #[serde(rename = "hlindy/proof-req@v2.0")] HyperledgerIndyProofRequest2_0, - // TODO - FIX - wrong ver, match acapy - #[serde(rename = "anoncreds/proof-req@v2.0")] - AnoncredsProofRequest2_0, + #[serde( + rename = "anoncreds/proof-request@v1.0", + // TODO - FIX - wrong ver, match acapy + alias = "anoncreds/proof-req@v2.0" + )] + AnoncredsProofRequest1_0, #[serde(rename = "dif/presentation-exchange/definitions@v1.0")] DifPresentationExchangeDefinitions1_0, } From b9111aaae98b012b38369c287d792c07aec2d0ad Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Mon, 9 Dec 2024 10:15:06 +1000 Subject: [PATCH 32/50] optimize with metadata Signed-off-by: George Mulhearn --- .../common/proofs/prover/prover_internal.rs | 4 +- .../proofs/verifier/verifier_internal.rs | 2 +- .../issuance/holder/state_machine.rs | 2 +- .../src/anoncreds/anoncreds/mod.rs | 4 +- .../src/ledger/base_ledger.rs | 26 +++++++++++-- .../aries_vcx_ledger/src/ledger/cheqd/mod.rs | 37 ++++++++++++++----- .../src/ledger/indy_vdr_ledger.rs | 36 ++++++++++++++---- aries/aries_vcx_ledger/tests/test_cheqd.rs | 17 ++++++--- .../anoncreds_types/src/utils/conversions.rs | 16 ++++---- .../test_utils/src/mockdata/mock_ledger.rs | 15 +++++--- 10 files changed, 117 insertions(+), 42 deletions(-) diff --git a/aries/aries_vcx/src/common/proofs/prover/prover_internal.rs b/aries/aries_vcx/src/common/proofs/prover/prover_internal.rs index 2013074671..72947ffb37 100644 --- a/aries/aries_vcx/src/common/proofs/prover/prover_internal.rs +++ b/aries/aries_vcx/src/common/proofs/prover/prover_internal.rs @@ -168,11 +168,11 @@ pub async fn build_rev_states_json( }; let parsed_id = &rev_reg_id.to_owned().try_into()?; - let rev_reg_def_json = ledger_read.get_rev_reg_def_json(parsed_id).await?; + let (rev_reg_def_json, meta) = ledger_read.get_rev_reg_def_json(parsed_id).await?; let on_or_before = to.unwrap_or(Utc::now().timestamp() as u64); let (rev_status_list, timestamp) = ledger_read - .get_rev_status_list(parsed_id, on_or_before, Some(&rev_reg_def_json)) + .get_rev_status_list(parsed_id, on_or_before, Some(&meta)) .await?; let rev_state_json = anoncreds diff --git a/aries/aries_vcx/src/common/proofs/verifier/verifier_internal.rs b/aries/aries_vcx/src/common/proofs/verifier/verifier_internal.rs index 5a474f6b79..bcd7fd31b6 100644 --- a/aries/aries_vcx/src/common/proofs/verifier/verifier_internal.rs +++ b/aries/aries_vcx/src/common/proofs/verifier/verifier_internal.rs @@ -167,7 +167,7 @@ pub async fn build_rev_reg_defs_json( ))?; if rev_reg_defs_json.get(rev_reg_id).is_none() { - let json = ledger + let (json, _meta) = ledger .get_rev_reg_def_json(&rev_reg_id.to_string().try_into()?) .await?; let rev_reg_def_json = serde_json::to_value(&json).or(Err(AriesVcxError::from_msg( diff --git a/aries/aries_vcx/src/protocols/issuance/holder/state_machine.rs b/aries/aries_vcx/src/protocols/issuance/holder/state_machine.rs index 7b534dd140..d0b9270320 100644 --- a/aries/aries_vcx/src/protocols/issuance/holder/state_machine.rs +++ b/aries/aries_vcx/src/protocols/issuance/holder/state_machine.rs @@ -561,7 +561,7 @@ async fn _store_credential( let rev_reg_id = _parse_rev_reg_id_from_credential(&credential_json)?; let rev_reg_def_json = if let Some(rev_reg_id) = rev_reg_id { - let json = ledger.get_rev_reg_def_json(&rev_reg_id.try_into()?).await?; + let (json, _meta) = ledger.get_rev_reg_def_json(&rev_reg_id.try_into()?).await?; Some(json) } else { None diff --git a/aries/aries_vcx_anoncreds/src/anoncreds/anoncreds/mod.rs b/aries/aries_vcx_anoncreds/src/anoncreds/anoncreds/mod.rs index 7108ee99e7..2a8a11a0a5 100644 --- a/aries/aries_vcx_anoncreds/src/anoncreds/anoncreds/mod.rs +++ b/aries/aries_vcx_anoncreds/src/anoncreds/anoncreds/mod.rs @@ -1128,8 +1128,10 @@ impl BaseAnonCreds for Anoncreds { let current_time = OffsetDateTime::now_utc().unix_timestamp() as u64; let rev_status_list = from_revocation_registry_delta_to_revocation_status_list( &last_rev_reg_delta.value, - &rev_reg_def, Some(current_time), + &rev_reg_def.id, + rev_reg_def.value.max_cred_num as usize, + rev_reg_def.issuer_id.clone(), )?; let cred_def = self diff --git a/aries/aries_vcx_ledger/src/ledger/base_ledger.rs b/aries/aries_vcx_ledger/src/ledger/base_ledger.rs index e072427fe8..abf4409665 100644 --- a/aries/aries_vcx_ledger/src/ledger/base_ledger.rs +++ b/aries/aries_vcx_ledger/src/ledger/base_ledger.rs @@ -73,8 +73,16 @@ pub trait IndyLedgerWrite: Debug + Send + Sync { ) -> VcxLedgerResult; } +/// Trait for reading anoncreds-related objects from some ledger/s. #[async_trait] pub trait AnoncredsLedgerRead: Debug + Send + Sync { + /// Opaque additional metadata associated with retrieving a revocation registry definition. + /// Returned as part of `get_rev_reg_def_json`, and optionally passed into + /// `get_rev_status_list`. Depending on the ledger anoncreds-method, this metadata may be + /// used in the subsequent revocation status list fetch as an optimization (e.g. to save an + /// additional ledger call). + type RevocationRegistryDefinitionAdditionalMetadata; + async fn get_schema( &self, schema_id: &SchemaId, @@ -85,22 +93,34 @@ pub trait AnoncredsLedgerRead: Debug + Send + Sync { cred_def_id: &CredentialDefinitionId, submitter_did: Option<&Did>, ) -> VcxLedgerResult; + + /// Get the anoncreds [RevocationRegistryDefinition] associated with the given ID. + /// Also returns any trait-specific additional metadata for the rev reg. async fn get_rev_reg_def_json( &self, rev_reg_id: &RevocationRegistryDefinitionId, - ) -> VcxLedgerResult; + ) -> VcxLedgerResult<( + RevocationRegistryDefinition, + Self::RevocationRegistryDefinitionAdditionalMetadata, + )>; async fn get_rev_reg_delta_json( &self, rev_reg_id: &RevocationRegistryDefinitionId, from: Option, to: Option, ) -> VcxLedgerResult<(RevocationRegistryDelta, u64)>; - /// TODO - describe + + /// Fetch the revocation status list associated with the ID at the given epoch second + /// `timestamp`. Optionally, metadata from a revocation registry definition fetch can be + /// passed in to optimize required ledger calls. + /// + /// Returns the complete [RevocationStatusList] closest to (at or before) the timestamp, and + /// also returns the actual timestamp that the returned status list entry was made. async fn get_rev_status_list( &self, rev_reg_id: &RevocationRegistryDefinitionId, timestamp: u64, - pre_fetched_rev_reg_def: Option<&RevocationRegistryDefinition>, + rev_reg_def_meta: Option<&Self::RevocationRegistryDefinitionAdditionalMetadata>, ) -> VcxLedgerResult<(RevocationStatusList, u64)>; async fn get_rev_reg( &self, diff --git a/aries/aries_vcx_ledger/src/ledger/cheqd/mod.rs b/aries/aries_vcx_ledger/src/ledger/cheqd/mod.rs index fdfecdd391..1a68e0238e 100644 --- a/aries/aries_vcx_ledger/src/ledger/cheqd/mod.rs +++ b/aries/aries_vcx_ledger/src/ledger/cheqd/mod.rs @@ -53,7 +53,7 @@ impl CheqdAnoncredsLedgerRead { Ok(()) } - async fn get_rev_reg_def_with_metadata( + async fn get_rev_reg_def_with_resource_metadata( &self, rev_reg_id: &RevocationRegistryDefinitionId, ) -> VcxLedgerResult<(RevocationRegistryDefinition, DidResourceMetadata)> { @@ -77,8 +77,15 @@ impl CheqdAnoncredsLedgerRead { } } +pub struct RevocationRegistryDefinitionAdditionalMetadata { + pub resource_name: String, +} + #[async_trait] impl AnoncredsLedgerRead for CheqdAnoncredsLedgerRead { + type RevocationRegistryDefinitionAdditionalMetadata = + RevocationRegistryDefinitionAdditionalMetadata; + async fn get_schema(&self, schema_id: &SchemaId, _: Option<&Did>) -> VcxLedgerResult { let url = DidUrl::parse(schema_id.to_string())?; let resource = self.resolver.resolve_resource(&url).await?; @@ -118,10 +125,19 @@ impl AnoncredsLedgerRead for CheqdAnoncredsLedgerRead { async fn get_rev_reg_def_json( &self, rev_reg_id: &RevocationRegistryDefinitionId, - ) -> VcxLedgerResult { - self.get_rev_reg_def_with_metadata(rev_reg_id) - .await - .map(|v| v.0) + ) -> VcxLedgerResult<( + RevocationRegistryDefinition, + RevocationRegistryDefinitionAdditionalMetadata, + )> { + let (rev_reg_def, resource_meta) = self + .get_rev_reg_def_with_resource_metadata(rev_reg_id) + .await?; + + let meta = RevocationRegistryDefinitionAdditionalMetadata { + resource_name: resource_meta.resource_name, + }; + + Ok((rev_reg_def, meta)) } async fn get_rev_reg_delta_json( @@ -140,15 +156,18 @@ impl AnoncredsLedgerRead for CheqdAnoncredsLedgerRead { &self, rev_reg_id: &RevocationRegistryDefinitionId, timestamp: u64, - // unused, we need to fetch anyway for resourceName - _pre_fetched_rev_reg_def: Option<&RevocationRegistryDefinition>, + rev_reg_def_meta: Option<&RevocationRegistryDefinitionAdditionalMetadata>, ) -> VcxLedgerResult<(RevocationStatusList, u64)> { let rev_reg_def_url = DidUrl::parse(rev_reg_id.to_string())?; - let (_def, rev_reg_def_metadata) = self.get_rev_reg_def_with_metadata(rev_reg_id).await?; + // refetch if needed + let rev_reg_def_meta = match rev_reg_def_meta { + Some(v) => v, + None => &self.get_rev_reg_def_json(rev_reg_id).await?.1, + }; //credo-ts uses the metadata.name or fails (https://docs.cheqd.io/product/advanced/anoncreds/revocation-status-list#same-resource-name-different-resource-type) - let name = &rev_reg_def_metadata.resource_name; + let name = &rev_reg_def_meta.resource_name; let did = rev_reg_def_url .did() diff --git a/aries/aries_vcx_ledger/src/ledger/indy_vdr_ledger.rs b/aries/aries_vcx_ledger/src/ledger/indy_vdr_ledger.rs index 76be156d35..ef6e9da189 100644 --- a/aries/aries_vcx_ledger/src/ledger/indy_vdr_ledger.rs +++ b/aries/aries_vcx_ledger/src/ledger/indy_vdr_ledger.rs @@ -7,8 +7,8 @@ use std::{ use anoncreds_types::{ data_types::{ identifiers::{ - cred_def_id::CredentialDefinitionId, rev_reg_def_id::RevocationRegistryDefinitionId, - schema_id::SchemaId, + cred_def_id::CredentialDefinitionId, issuer_id::IssuerId, + rev_reg_def_id::RevocationRegistryDefinitionId, schema_id::SchemaId, }, ledger::{ cred_def::CredentialDefinition, rev_reg::RevocationRegistry, @@ -445,12 +445,20 @@ where } } +pub struct RevocationRegistryDefinitionAdditionalMetadata { + pub max_cred_num: usize, + pub issuer_id: IssuerId, +} + #[async_trait] impl AnoncredsLedgerRead for IndyVdrLedgerRead where T: RequestSubmitter + Send + Sync, V: ResponseCacher + Send + Sync, { + type RevocationRegistryDefinitionAdditionalMetadata = + RevocationRegistryDefinitionAdditionalMetadata; + async fn get_schema( &self, schema_id: &SchemaId, @@ -496,7 +504,10 @@ where async fn get_rev_reg_def_json( &self, rev_reg_id: &RevocationRegistryDefinitionId, - ) -> VcxLedgerResult { + ) -> VcxLedgerResult<( + RevocationRegistryDefinition, + RevocationRegistryDefinitionAdditionalMetadata, + )> { debug!("get_rev_reg_def_json >> rev_reg_id: {rev_reg_id}"); let id = RevocationRegistryId::from_str(&rev_reg_id.to_string())?; let request = self @@ -509,7 +520,14 @@ where let rev_reg_def = self .response_parser .parse_get_revoc_reg_def_response(&response)?; - Ok(rev_reg_def.convert(())?) + let def = rev_reg_def.convert(())?; + + let meta = RevocationRegistryDefinitionAdditionalMetadata { + max_cred_num: def.value.max_cred_num as usize, + issuer_id: def.issuer_id.clone(), + }; + + Ok((def, meta)) } async fn get_rev_reg_delta_json( @@ -548,21 +566,23 @@ where &self, rev_reg_id: &RevocationRegistryDefinitionId, timestamp: u64, - pre_fetched_rev_reg_def: Option<&RevocationRegistryDefinition>, + rev_reg_def_meta: Option<&RevocationRegistryDefinitionAdditionalMetadata>, ) -> VcxLedgerResult<(RevocationStatusList, u64)> { let (delta, entry_time) = self .get_rev_reg_delta_json(rev_reg_id, Some(0), Some(timestamp)) .await?; - let rev_reg_def = match pre_fetched_rev_reg_def { + let rev_reg_def_meta = match rev_reg_def_meta { Some(x) => x, - None => &self.get_rev_reg_def_json(rev_reg_id).await?, + None => &self.get_rev_reg_def_json(rev_reg_id).await?.1, }; let status_list = from_revocation_registry_delta_to_revocation_status_list( &delta.value, - &rev_reg_def, Some(entry_time), + &rev_reg_id, + rev_reg_def_meta.max_cred_num, + rev_reg_def_meta.issuer_id.clone(), ) .map_err(|e| { VcxLedgerError::InvalidLedgerResponse(format!( diff --git a/aries/aries_vcx_ledger/tests/test_cheqd.rs b/aries/aries_vcx_ledger/tests/test_cheqd.rs index aba9757d74..119f9b111e 100644 --- a/aries/aries_vcx_ledger/tests/test_cheqd.rs +++ b/aries/aries_vcx_ledger/tests/test_cheqd.rs @@ -81,7 +81,7 @@ async fn test_resolve_rev_reg_def_vector() { 4f265d83-4657-4c37-ba80-c66cc399457e"; let reader = CheqdAnoncredsLedgerRead::new(Arc::new(DidCheqdResolver::new(Default::default()))); - let rev_reg_def = reader + let (rev_reg_def, meta) = reader .get_rev_reg_def_json(&RevocationRegistryDefinitionId::new_unchecked(id)) .await .unwrap(); @@ -107,6 +107,11 @@ async fn test_resolve_rev_reg_def_vector() { serde_json::to_value(rev_reg_def).unwrap(), expected_rev_reg_def ); + + assert_eq!( + meta.resource_name, + "275990cc056b46176a7122cfd888f46a2bd8e3d45a71d5ff20764a874ed02edd" + ); } // test status list resolution from credo-ts uploaded vectors @@ -140,10 +145,12 @@ async fn test_resolve_rev_status_list_versions() { let reader = CheqdAnoncredsLedgerRead::new(Arc::new(DidCheqdResolver::new(Default::default()))); + let def_meta = reader.get_rev_reg_def_json(&def_id).await.unwrap().1; + // scenario 1: get most recent let now = Utc::now().timestamp() as u64; let (status_list, update_time) = reader - .get_rev_status_list(&def_id, now, None) + .get_rev_status_list(&def_id, now, Some(&def_meta)) .await .unwrap(); assert_eq!(update_time, update3_time); @@ -160,7 +167,7 @@ async fn test_resolve_rev_status_list_versions() { // scenario 2: between update 2 & 3 let (status_list, update_time) = reader - .get_rev_status_list(&def_id, update2_time + 3, None) + .get_rev_status_list(&def_id, update2_time + 3, Some(&def_meta)) .await .unwrap(); assert_eq!(update_time, update2_time); @@ -177,7 +184,7 @@ async fn test_resolve_rev_status_list_versions() { // scenario 3: between update 1 & 2 let (status_list, update_time) = reader - .get_rev_status_list(&def_id, update1_time + 3, None) + .get_rev_status_list(&def_id, update1_time + 3, Some(&def_meta)) .await .unwrap(); assert_eq!(update_time, update1_time); @@ -194,7 +201,7 @@ async fn test_resolve_rev_status_list_versions() { // scenario 4: between init & update 1 let (status_list, update_time) = reader - .get_rev_status_list(&def_id, init_time + 3, None) + .get_rev_status_list(&def_id, init_time + 3, Some(&def_meta)) .await .unwrap(); assert_eq!(update_time, init_time); diff --git a/aries/misc/anoncreds_types/src/utils/conversions.rs b/aries/misc/anoncreds_types/src/utils/conversions.rs index 72228c678c..ecad6a14c7 100644 --- a/aries/misc/anoncreds_types/src/utils/conversions.rs +++ b/aries/misc/anoncreds_types/src/utils/conversions.rs @@ -1,21 +1,23 @@ use bitvec::bitvec; -use crate::data_types::ledger::{ - rev_reg_def::RevocationRegistryDefinition, rev_reg_delta::RevocationRegistryDeltaValue, - rev_status_list::RevocationStatusList, +use crate::data_types::{ + identifiers::{issuer_id::IssuerId, rev_reg_def_id::RevocationRegistryDefinitionId}, + ledger::{rev_reg_delta::RevocationRegistryDeltaValue, rev_status_list::RevocationStatusList}, }; /// TODO - explain pub fn from_revocation_registry_delta_to_revocation_status_list( delta: &RevocationRegistryDeltaValue, - rev_reg_def: &RevocationRegistryDefinition, timestamp: Option, + rev_reg_id: &RevocationRegistryDefinitionId, + max_cred_num: usize, + issuer_id: IssuerId, ) -> Result { // no way to derive this value here. So we assume true, as false (ISSAUNCE_ON_DEAMAND) is not // recomended by anoncreds: https://hyperledger.github.io/anoncreds-spec/#anoncreds-issuer-setup-with-revocation let issuance_by_default = true; let default_state = if issuance_by_default { 0 } else { 1 }; - let mut revocation_list = bitvec![default_state; rev_reg_def.value.max_cred_num as usize]; + let mut revocation_list = bitvec![default_state; max_cred_num]; let revocation_len = revocation_list.len(); for issued in &delta.issued { @@ -49,8 +51,8 @@ pub fn from_revocation_registry_delta_to_revocation_status_list( let accum = delta.accum.into(); RevocationStatusList::new( - Some(&rev_reg_def.id.to_string()), - rev_reg_def.issuer_id.clone(), + Some(&rev_reg_id.to_string()), + issuer_id, revocation_list, Some(accum), timestamp, diff --git a/aries/misc/test_utils/src/mockdata/mock_ledger.rs b/aries/misc/test_utils/src/mockdata/mock_ledger.rs index b27290ff3c..ee90a29610 100644 --- a/aries/misc/test_utils/src/mockdata/mock_ledger.rs +++ b/aries/misc/test_utils/src/mockdata/mock_ledger.rs @@ -4,7 +4,9 @@ use anoncreds_types::data_types::{ schema_id::SchemaId, }, ledger::{ - cred_def::CredentialDefinition, rev_reg::RevocationRegistry, rev_reg_def::RevocationRegistryDefinition, rev_reg_delta::RevocationRegistryDelta, rev_status_list::RevocationStatusList, schema::Schema + cred_def::CredentialDefinition, rev_reg::RevocationRegistry, + rev_reg_def::RevocationRegistryDefinition, rev_reg_delta::RevocationRegistryDelta, + rev_status_list::RevocationStatusList, schema::Schema, }, }; use aries_vcx_ledger::{ @@ -20,7 +22,8 @@ use did_parser_nom::Did; use public_key::Key; use crate::constants::{ - rev_def_json, CRED_DEF_JSON, DEFAULT_AUTHOR_AGREEMENT, REQUEST_WITH_ENDORSER, REV_REG_DELTA_JSON, REV_REG_JSON, REV_STATUS_LIST_JSON, SCHEMA_JSON + rev_def_json, CRED_DEF_JSON, DEFAULT_AUTHOR_AGREEMENT, REQUEST_WITH_ENDORSER, + REV_REG_DELTA_JSON, REV_REG_JSON, REV_STATUS_LIST_JSON, SCHEMA_JSON, }; #[derive(Debug)] @@ -112,6 +115,8 @@ impl IndyLedgerWrite for MockLedger { #[allow(unused)] #[async_trait] impl AnoncredsLedgerRead for MockLedger { + type RevocationRegistryDefinitionAdditionalMetadata = (); + async fn get_schema( &self, schema_id: &SchemaId, @@ -131,8 +136,8 @@ impl AnoncredsLedgerRead for MockLedger { async fn get_rev_reg_def_json( &self, rev_reg_id: &RevocationRegistryDefinitionId, - ) -> VcxLedgerResult { - Ok(rev_def_json()) + ) -> VcxLedgerResult<(RevocationRegistryDefinition, ())> { + Ok((rev_def_json(), ())) } async fn get_rev_reg_delta_json( @@ -148,7 +153,7 @@ impl AnoncredsLedgerRead for MockLedger { &self, rev_reg_id: &RevocationRegistryDefinitionId, timestamp: u64, - pre_fetched_rev_reg_def: Option<&RevocationRegistryDefinition>, + meta: Option<&()>, ) -> VcxLedgerResult<(RevocationStatusList, u64)> { Ok((serde_json::from_str(REV_STATUS_LIST_JSON).unwrap(), 1)) } From fbe30549682e6c3fd2792efccc8edc2ebe8ca781 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Mon, 9 Dec 2024 14:49:24 +1000 Subject: [PATCH 33/50] multi ledger aggregation Signed-off-by: George Mulhearn --- Cargo.lock | 10 +- aries/aries_vcx/src/errors/mapping_ledger.rs | 4 +- aries/aries_vcx_ledger/Cargo.toml | 3 + aries/aries_vcx_ledger/src/errors/error.rs | 2 + .../src/ledger/base_ledger.rs | 8 + .../aries_vcx_ledger/src/ledger/cheqd/mod.rs | 123 +++- .../src/ledger/indy_vdr_ledger.rs | 147 +++- aries/aries_vcx_ledger/src/ledger/mod.rs | 5 +- .../src/ledger/multi_ledger.rs | 669 ++++++++++++++++++ .../tests/test_multi_ledger.rs | 44 ++ aries/misc/test_utils/src/constants.rs | 2 +- 11 files changed, 1007 insertions(+), 10 deletions(-) create mode 100644 aries/aries_vcx_ledger/src/ledger/multi_ledger.rs create mode 100644 aries/aries_vcx_ledger/tests/test_multi_ledger.rs diff --git a/Cargo.lock b/Cargo.lock index 176528c72e..5a29115de0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -613,12 +613,14 @@ dependencies = [ "indy-vdr-proxy-client", "log", "lru", + "mockall", "public_key", "serde", "serde_json", "thiserror", "time", "tokio", + "uuid", ] [[package]] @@ -3357,9 +3359,9 @@ dependencies = [ [[package]] name = "mockall" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c28b3fb6d753d28c20e826cd46ee611fda1cf3cde03a443a974043247c065a" +checksum = "39a6bfcc6c8c7eed5ee98b9c3e33adc726054389233e201c95dab2d41a3839d2" dependencies = [ "cfg-if", "downcast", @@ -3371,9 +3373,9 @@ dependencies = [ [[package]] name = "mockall_derive" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "341014e7f530314e9a1fdbc7400b244efea7122662c96bfa248c31da5bfb2020" +checksum = "25ca3004c2efe9011bd4e461bd8256445052b9615405b4f7ea43fc8ca5c20898" dependencies = [ "cfg-if", "proc-macro2", diff --git a/aries/aries_vcx/src/errors/mapping_ledger.rs b/aries/aries_vcx/src/errors/mapping_ledger.rs index 229afc49ee..3b540b3214 100644 --- a/aries/aries_vcx/src/errors/mapping_ledger.rs +++ b/aries/aries_vcx/src/errors/mapping_ledger.rs @@ -33,7 +33,9 @@ impl From for AriesVcxError { Self::from_msg(AriesVcxErrorKind::PoolLedgerConnect, value) } VcxLedgerError::IOError(_) => Self::from_msg(AriesVcxErrorKind::IOError, value), - VcxLedgerError::InvalidInput(_) | VcxLedgerError::IndyVdrValidation(_) => { + VcxLedgerError::InvalidInput(_) + | VcxLedgerError::IndyVdrValidation(_) + | VcxLedgerError::UnsupportedLedgerIdentifier(_) => { Self::from_msg(AriesVcxErrorKind::InvalidInput, value) } VcxLedgerError::UnknownError(_) => { diff --git a/aries/aries_vcx_ledger/Cargo.toml b/aries/aries_vcx_ledger/Cargo.toml index 3f5e991960..8466743fcb 100644 --- a/aries/aries_vcx_ledger/Cargo.toml +++ b/aries/aries_vcx_ledger/Cargo.toml @@ -38,3 +38,6 @@ tokio = { version = "1.38.0", default-features = false, features = [ "rt", ] } chrono = { version = "0.4", default-features = true } +mockall = "0.13.1" +uuid = { version = "1.4.1", default-features = false, features = ["v4"] } + diff --git a/aries/aries_vcx_ledger/src/errors/error.rs b/aries/aries_vcx_ledger/src/errors/error.rs index 826607c706..d4281e542c 100644 --- a/aries/aries_vcx_ledger/src/errors/error.rs +++ b/aries/aries_vcx_ledger/src/errors/error.rs @@ -29,6 +29,8 @@ pub enum VcxLedgerError { InvalidOption(String), #[error("Invalid input: {0}")] InvalidInput(String), + #[error("Unsupported ledger identifier: {0}")] + UnsupportedLedgerIdentifier(String), #[error("Unknown error: {0}")] UnknownError(String), #[error("Indy Vdr Validation error: {0}")] diff --git a/aries/aries_vcx_ledger/src/ledger/base_ledger.rs b/aries/aries_vcx_ledger/src/ledger/base_ledger.rs index abf4409665..fb3e4bb607 100644 --- a/aries/aries_vcx_ledger/src/ledger/base_ledger.rs +++ b/aries/aries_vcx_ledger/src/ledger/base_ledger.rs @@ -159,6 +159,14 @@ pub trait AnoncredsLedgerWrite: Debug + Send + Sync { ) -> VcxLedgerResult<()>; } +/// Simple utility trait to determine whether the implementor can support reading/writing +/// the specific identifier types. +pub trait AnoncredsLedgerSupport { + fn supports_schema(&self, id: &SchemaId) -> bool; + fn supports_credential_definition(&self, id: &CredentialDefinitionId) -> bool; + fn supports_revocation_registry(&self, id: &RevocationRegistryDefinitionId) -> bool; +} + pub trait TaaConfigurator: Debug + Send + Sync { fn set_txn_author_agreement_options( &self, diff --git a/aries/aries_vcx_ledger/src/ledger/cheqd/mod.rs b/aries/aries_vcx_ledger/src/ledger/cheqd/mod.rs index 1a68e0238e..d2cfb6fded 100644 --- a/aries/aries_vcx_ledger/src/ledger/cheqd/mod.rs +++ b/aries/aries_vcx_ledger/src/ledger/cheqd/mod.rs @@ -23,8 +23,9 @@ use models::{ CheqdAnoncredsCredentialDefinition, CheqdAnoncredsRevocationRegistryDefinition, CheqdAnoncredsRevocationStatusList, CheqdAnoncredsSchema, }; +use serde::{Deserialize, Serialize}; -use super::base_ledger::AnoncredsLedgerRead; +use super::base_ledger::{AnoncredsLedgerRead, AnoncredsLedgerSupport}; use crate::errors::error::{VcxLedgerError, VcxLedgerResult}; mod models; @@ -34,6 +35,10 @@ const CRED_DEF_RESOURCE_TYPE: &str = "anonCredsCredDef"; const REV_REG_DEF_RESOURCE_TYPE: &str = "anonCredsRevocRegDef"; const STATUS_LIST_RESOURCE_TYPE: &str = "anonCredsStatusList"; +/// Struct for resolving anoncreds objects from cheqd ledgers using the cheqd +/// anoncreds object method: https://docs.cheqd.io/product/advanced/anoncreds. +/// +/// Relies on a cheqd DID resolver ([DidCheqdResolver]) to fetch DID resources. pub struct CheqdAnoncredsLedgerRead { resolver: Arc, } @@ -77,6 +82,7 @@ impl CheqdAnoncredsLedgerRead { } } +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct RevocationRegistryDefinitionAdditionalMetadata { pub resource_name: String, } @@ -234,8 +240,123 @@ fn extract_issuer_id(url: &DidUrl) -> VcxLedgerResult { .map_err(|e| VcxLedgerError::InvalidInput(format!("DID is not an IssuerId {e}"))) } +impl AnoncredsLedgerSupport for CheqdAnoncredsLedgerRead { + fn supports_schema(&self, id: &SchemaId) -> bool { + let Ok(url) = DidUrl::parse(id.to_string()) else { + return false; + }; + url.method() == Some("cheqd") + } + + fn supports_credential_definition(&self, id: &CredentialDefinitionId) -> bool { + let Ok(url) = DidUrl::parse(id.to_string()) else { + return false; + }; + url.method() == Some("cheqd") + } + + fn supports_revocation_registry(&self, id: &RevocationRegistryDefinitionId) -> bool { + let Ok(url) = DidUrl::parse(id.to_string()) else { + return false; + }; + url.method() == Some("cheqd") + } +} + impl Debug for CheqdAnoncredsLedgerRead { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "CheqdAnoncredsLedgerRead instance") } } + +#[cfg(test)] +mod unit_tests { + use super::*; + + fn default_cheqd_reader() -> CheqdAnoncredsLedgerRead { + CheqdAnoncredsLedgerRead::new(Arc::new(DidCheqdResolver::new(Default::default()))) + } + + #[test] + fn test_anoncreds_schema_support() { + let reader = default_cheqd_reader(); + + // qualified cheqd + assert!(reader.supports_schema( + &SchemaId::new( + "did:cheqd:mainnet:7BPMqYgYLQni258J8JPS8K/resources/\ + 6259d357-eeb1-4b98-8bee-12a8390d3497" + ) + .unwrap() + )); + + // unqualified + assert!(!reader.supports_schema( + &SchemaId::new("7BPMqYgYLQni258J8JPS8K:2:degree schema:46.58.87").unwrap() + )); + // qualified sov + assert!(!reader.supports_schema( + &SchemaId::new("did:sov:7BPMqYgYLQni258J8JPS8K:2:degree schema:46.58.87").unwrap() + )); + } + + #[test] + fn test_anoncreds_cred_def_support() { + let reader = default_cheqd_reader(); + + // qualified cheqd + assert!(reader.supports_credential_definition( + &CredentialDefinitionId::new( + "did:cheqd:mainnet:7BPMqYgYLQni258J8JPS8K/resources/\ + 6259d357-eeb1-4b98-8bee-12a8390d3497" + ) + .unwrap() + )); + + // unqualified + assert!(!reader.supports_credential_definition( + &CredentialDefinitionId::new( + "7BPMqYgYLQni258J8JPS8K:3:CL:70:faber.agent.degree_schema" + ) + .unwrap() + )); + // qualified sov + assert!(!reader.supports_credential_definition( + &CredentialDefinitionId::new( + "did:sov:7BPMqYgYLQni258J8JPS8K:3:CL:70:faber.agent.degree_schema" + ) + .unwrap() + )); + } + + #[test] + fn test_anoncreds_rev_reg_support() { + let reader = default_cheqd_reader(); + + // qualified cheqd + assert!(reader.supports_revocation_registry( + &RevocationRegistryDefinitionId::new( + "did:cheqd:mainnet:7BPMqYgYLQni258J8JPS8K/resources/\ + 6259d357-eeb1-4b98-8bee-12a8390d3497" + ) + .unwrap() + )); + + // unqualified + assert!(!reader.supports_revocation_registry( + &RevocationRegistryDefinitionId::new( + "7BPMqYgYLQni258J8JPS8K:4:7BPMqYgYLQni258J8JPS8K:3:CL:70:faber.agent.\ + degree_schema:CL_ACCUM:61d5a381-30be-4120-9307-b150b49c203c" + ) + .unwrap() + )); + // qualified sov + assert!(!reader.supports_revocation_registry( + &RevocationRegistryDefinitionId::new( + "did:sov:7BPMqYgYLQni258J8JPS8K:4:7BPMqYgYLQni258J8JPS8K:3:CL:70:faber.agent.\ + degree_schema:CL_ACCUM:61d5a381-30be-4120-9307-b150b49c203c" + ) + .unwrap() + )); + } +} diff --git a/aries/aries_vcx_ledger/src/ledger/indy_vdr_ledger.rs b/aries/aries_vcx_ledger/src/ledger/indy_vdr_ledger.rs index ef6e9da189..1c1c40d661 100644 --- a/aries/aries_vcx_ledger/src/ledger/indy_vdr_ledger.rs +++ b/aries/aries_vcx_ledger/src/ledger/indy_vdr_ledger.rs @@ -28,6 +28,7 @@ use indy_ledger_response_parser::{ use indy_vdr as vdr; use log::{debug, trace}; use public_key::Key; +use serde::{Deserialize, Serialize}; use serde_json::Value; use time::OffsetDateTime; use vdr::{ @@ -48,7 +49,10 @@ pub use vdr::{ }; use super::{ - base_ledger::{AnoncredsLedgerRead, AnoncredsLedgerWrite, IndyLedgerRead, IndyLedgerWrite}, + base_ledger::{ + AnoncredsLedgerRead, AnoncredsLedgerSupport, AnoncredsLedgerWrite, IndyLedgerRead, + IndyLedgerWrite, + }, map_error_not_found_to_none, request_submitter::{ vdr_ledger::{IndyVdrLedgerPool, IndyVdrSubmitter}, @@ -445,6 +449,7 @@ where } } +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct RevocationRegistryDefinitionAdditionalMetadata { pub max_cred_num: usize, pub issuer_id: IssuerId, @@ -621,6 +626,41 @@ where } } +impl AnoncredsLedgerSupport for IndyVdrLedgerRead { + fn supports_schema(&self, id: &SchemaId) -> bool { + if id.is_legacy() { + // unqualified + return true; + } + did_method_is_supported(&id.0) + } + + fn supports_credential_definition(&self, id: &CredentialDefinitionId) -> bool { + if id.is_legacy_cred_def_identifier() { + // unqualified + return true; + } + did_method_is_supported(&id.0) + } + + fn supports_revocation_registry(&self, id: &RevocationRegistryDefinitionId) -> bool { + if id.is_legacy() { + // unqualified + return true; + } + did_method_is_supported(&id.0) + } +} + +fn did_method_is_supported(id: &String) -> bool { + let is_sov = id.starts_with("did:sov:"); + let is_unqualified = !id.starts_with("did"); + + // FUTURE - indy & namespace + + is_sov || is_unqualified +} + #[async_trait] impl AnoncredsLedgerWrite for IndyVdrLedgerWrite where @@ -764,3 +804,108 @@ pub fn build_ledger_components( Ok((ledger_read, ledger_write)) } + +#[cfg(test)] +mod unit_tests { + use mockall::mock; + + use super::*; + use crate::ledger::response_cacher::noop::NoopResponseCacher; + + mock! { + pub RequestSubmitter {} + #[async_trait] + impl RequestSubmitter for RequestSubmitter { + async fn submit(&self, request: indy_vdr::pool::PreparedRequest) -> VcxLedgerResult; + } + } + + fn dummy_indy_vdr_reader() -> IndyVdrLedgerRead { + IndyVdrLedgerRead::new(IndyVdrLedgerReadConfig { + request_submitter: MockRequestSubmitter::new(), + response_parser: indy_ledger_response_parser::ResponseParser, + response_cacher: NoopResponseCacher, + protocol_version: ProtocolVersion::Node1_4, + }) + } + + #[test] + fn test_anoncreds_schema_support() { + let reader = dummy_indy_vdr_reader(); + + // legacy + assert!(reader.supports_schema( + &SchemaId::new("7BPMqYgYLQni258J8JPS8K:2:degree schema:46.58.87").unwrap() + )); + // qualified sov + assert!(reader.supports_schema( + &SchemaId::new("did:sov:7BPMqYgYLQni258J8JPS8K:2:degree schema:46.58.87").unwrap() + )); + // qualified cheqd + assert!(!reader.supports_schema( + &SchemaId::new( + "did:cheqd:mainnet:7BPMqYgYLQni258J8JPS8K/resources/\ + 6259d357-eeb1-4b98-8bee-12a8390d3497" + ) + .unwrap() + )); + } + + #[test] + fn test_anoncreds_cred_def_support() { + let reader = dummy_indy_vdr_reader(); + + // legacy + assert!(reader.supports_credential_definition( + &CredentialDefinitionId::new( + "7BPMqYgYLQni258J8JPS8K:3:CL:70:faber.agent.degree_schema" + ) + .unwrap() + )); + // qualified sov + assert!(reader.supports_credential_definition( + &CredentialDefinitionId::new( + "did:sov:7BPMqYgYLQni258J8JPS8K:3:CL:70:faber.agent.degree_schema" + ) + .unwrap() + )); + // qualified cheqd + assert!(!reader.supports_credential_definition( + &CredentialDefinitionId::new( + "did:cheqd:mainnet:7BPMqYgYLQni258J8JPS8K/resources/\ + 6259d357-eeb1-4b98-8bee-12a8390d3497" + ) + .unwrap() + )); + } + + #[test] + fn test_anoncreds_rev_reg_support() { + let reader = dummy_indy_vdr_reader(); + + // legacy + assert!(reader.supports_revocation_registry( + &RevocationRegistryDefinitionId::new( + "7BPMqYgYLQni258J8JPS8K:4:7BPMqYgYLQni258J8JPS8K:3:CL:70:faber.agent.\ + degree_schema:CL_ACCUM:61d5a381-30be-4120-9307-b150b49c203c" + ) + .unwrap() + )); + // qualified sov + assert!(reader.supports_revocation_registry( + &RevocationRegistryDefinitionId::new( + "did:sov:7BPMqYgYLQni258J8JPS8K:4:7BPMqYgYLQni258J8JPS8K:3:CL:70:faber.agent.\ + degree_schema:CL_ACCUM:61d5a381-30be-4120-9307-b150b49c203c" + ) + .unwrap() + )); + // qualified cheqd + assert!(!reader.supports_revocation_registry( + &RevocationRegistryDefinitionId::new( + "did:cheqd:mainnet:7BPMqYgYLQni258J8JPS8K/resources/\ + 6259d357-eeb1-4b98-8bee-12a8390d3497" + ) + .unwrap() + )); + } +} diff --git a/aries/aries_vcx_ledger/src/ledger/mod.rs b/aries/aries_vcx_ledger/src/ledger/mod.rs index f22a2191b2..eb8abc4e8c 100644 --- a/aries/aries_vcx_ledger/src/ledger/mod.rs +++ b/aries/aries_vcx_ledger/src/ledger/mod.rs @@ -3,10 +3,11 @@ use crate::errors::error::VcxLedgerError; pub mod base_ledger; pub mod common; -pub mod indy; -pub mod indy_vdr_ledger; #[cfg(feature = "cheqd")] pub mod cheqd; +pub mod indy; +pub mod indy_vdr_ledger; +pub mod multi_ledger; mod type_conversion; pub mod request_submitter; diff --git a/aries/aries_vcx_ledger/src/ledger/multi_ledger.rs b/aries/aries_vcx_ledger/src/ledger/multi_ledger.rs new file mode 100644 index 0000000000..9fb3b318ac --- /dev/null +++ b/aries/aries_vcx_ledger/src/ledger/multi_ledger.rs @@ -0,0 +1,669 @@ +use std::fmt::Debug; + +use anoncreds_types::data_types::{ + identifiers::{ + cred_def_id::CredentialDefinitionId, rev_reg_def_id::RevocationRegistryDefinitionId, + schema_id::SchemaId, + }, + ledger::{ + cred_def::CredentialDefinition, rev_reg::RevocationRegistry, + rev_reg_def::RevocationRegistryDefinition, rev_reg_delta::RevocationRegistryDelta, + rev_status_list::RevocationStatusList, schema::Schema, + }, +}; +use async_trait::async_trait; +use did_parser_nom::Did; +use serde::{Deserialize, Serialize}; +use serde_json::Value; + +use super::base_ledger::{AnoncredsLedgerRead, AnoncredsLedgerSupport}; +use crate::errors::error::{VcxLedgerError, VcxLedgerResult}; + +/// Struct to aggregate multiple [AnoncredsLedgerRead] implementations into a single +/// [AnoncredsLedgerRead]. The child [AnoncredsLedgerRead] implementations are +/// utiliized depending on whether or not they support resolution of the given object ID +/// (e.g. based on the DID Method). +#[derive(Default, Debug)] +pub struct MultiLedgerAnoncredsRead { + readers: Vec>, +} + +#[async_trait] +impl AnoncredsLedgerRead for MultiLedgerAnoncredsRead { + type RevocationRegistryDefinitionAdditionalMetadata = Value; + + async fn get_schema( + &self, + schema_id: &SchemaId, + submitter_did: Option<&Did>, + ) -> VcxLedgerResult { + let reader = self + .readers + .iter() + .find(|r| r.supports_schema(schema_id)) + .ok_or(VcxLedgerError::UnsupportedLedgerIdentifier( + schema_id.to_string(), + ))?; + + reader.get_schema(schema_id, submitter_did).await + } + + async fn get_cred_def( + &self, + cred_def_id: &CredentialDefinitionId, + submitter_did: Option<&Did>, + ) -> VcxLedgerResult { + let reader = self + .readers + .iter() + .find(|r| r.supports_credential_definition(cred_def_id)) + .ok_or(VcxLedgerError::UnsupportedLedgerIdentifier( + cred_def_id.to_string(), + ))?; + + reader.get_cred_def(cred_def_id, submitter_did).await + } + + async fn get_rev_reg_def_json( + &self, + rev_reg_id: &RevocationRegistryDefinitionId, + ) -> VcxLedgerResult<( + RevocationRegistryDefinition, + Self::RevocationRegistryDefinitionAdditionalMetadata, + )> { + let reader = self + .readers + .iter() + .find(|r| r.supports_revocation_registry(rev_reg_id)) + .ok_or(VcxLedgerError::UnsupportedLedgerIdentifier( + rev_reg_id.to_string(), + ))?; + + reader.get_rev_reg_def_json(rev_reg_id).await + } + async fn get_rev_reg_delta_json( + &self, + rev_reg_id: &RevocationRegistryDefinitionId, + from: Option, + to: Option, + ) -> VcxLedgerResult<(RevocationRegistryDelta, u64)> { + let reader = self + .readers + .iter() + .find(|r| r.supports_revocation_registry(rev_reg_id)) + .ok_or(VcxLedgerError::UnsupportedLedgerIdentifier( + rev_reg_id.to_string(), + ))?; + + reader.get_rev_reg_delta_json(rev_reg_id, from, to).await + } + + async fn get_rev_status_list( + &self, + rev_reg_id: &RevocationRegistryDefinitionId, + timestamp: u64, + rev_reg_def_meta: Option<&Self::RevocationRegistryDefinitionAdditionalMetadata>, + ) -> VcxLedgerResult<(RevocationStatusList, u64)> { + let reader = self + .readers + .iter() + .find(|r| r.supports_revocation_registry(rev_reg_id)) + .ok_or(VcxLedgerError::UnsupportedLedgerIdentifier( + rev_reg_id.to_string(), + ))?; + + reader + .get_rev_status_list(rev_reg_id, timestamp, rev_reg_def_meta) + .await + } + + async fn get_rev_reg( + &self, + rev_reg_id: &RevocationRegistryDefinitionId, + timestamp: u64, + ) -> VcxLedgerResult<(RevocationRegistry, u64)> { + let reader = self + .readers + .iter() + .find(|r| r.supports_revocation_registry(rev_reg_id)) + .ok_or(VcxLedgerError::UnsupportedLedgerIdentifier( + rev_reg_id.to_string(), + ))?; + + reader.get_rev_reg(rev_reg_id, timestamp).await + } +} + +impl MultiLedgerAnoncredsRead { + pub fn new() -> Self { + Self::default() + } + + pub fn register_reader(mut self, reader: T) -> Self + where + T: AnoncredsLedgerRead + AnoncredsLedgerSupport + 'static, + for<'de> ::RevocationRegistryDefinitionAdditionalMetadata: + Serialize + Deserialize<'de> + Send + Sync, + { + let adaptor = AnoncredsLedgerReadAdaptor { inner: reader }; + self.readers.push(Box::new(adaptor)); + self + } +} + +impl AnoncredsLedgerSupport for MultiLedgerAnoncredsRead { + fn supports_schema(&self, id: &SchemaId) -> bool { + self.readers.iter().any(|r| r.supports_schema(id)) + } + + fn supports_credential_definition(&self, id: &CredentialDefinitionId) -> bool { + self.readers + .iter() + .any(|r| r.supports_credential_definition(id)) + } + + fn supports_revocation_registry(&self, id: &RevocationRegistryDefinitionId) -> bool { + self.readers + .iter() + .any(|r| r.supports_revocation_registry(id)) + } +} + +#[derive(Debug)] +pub struct AnoncredsLedgerReadAdaptor { + inner: T, +} + +pub trait AnoncredsLedgerReadAdaptorTrait: + AnoncredsLedgerRead + AnoncredsLedgerSupport +{ +} + +impl AnoncredsLedgerSupport for AnoncredsLedgerReadAdaptor +where + T: AnoncredsLedgerSupport, +{ + fn supports_schema(&self, id: &SchemaId) -> bool { + self.inner.supports_schema(id) + } + fn supports_credential_definition(&self, id: &CredentialDefinitionId) -> bool { + self.inner.supports_credential_definition(id) + } + fn supports_revocation_registry(&self, id: &RevocationRegistryDefinitionId) -> bool { + self.inner.supports_revocation_registry(id) + } +} + +#[async_trait] +impl AnoncredsLedgerRead for AnoncredsLedgerReadAdaptor +where + T: AnoncredsLedgerRead, + T::RevocationRegistryDefinitionAdditionalMetadata: + Serialize + for<'de> Deserialize<'de> + Send + Sync, +{ + type RevocationRegistryDefinitionAdditionalMetadata = Value; + + async fn get_schema( + &self, + schema_id: &SchemaId, + submitter_did: Option<&Did>, + ) -> VcxLedgerResult { + self.inner.get_schema(schema_id, submitter_did).await + } + + async fn get_cred_def( + &self, + cred_def_id: &CredentialDefinitionId, + submitter_did: Option<&Did>, + ) -> VcxLedgerResult { + self.inner.get_cred_def(cred_def_id, submitter_did).await + } + + async fn get_rev_reg_def_json( + &self, + rev_reg_id: &RevocationRegistryDefinitionId, + ) -> VcxLedgerResult<( + RevocationRegistryDefinition, + Self::RevocationRegistryDefinitionAdditionalMetadata, + )> { + let (reg, meta) = self.inner.get_rev_reg_def_json(rev_reg_id).await?; + + Ok((reg, serde_json::to_value(meta)?)) + } + async fn get_rev_reg_delta_json( + &self, + rev_reg_id: &RevocationRegistryDefinitionId, + from: Option, + to: Option, + ) -> VcxLedgerResult<(RevocationRegistryDelta, u64)> { + self.inner + .get_rev_reg_delta_json(rev_reg_id, from, to) + .await + } + + async fn get_rev_status_list( + &self, + rev_reg_id: &RevocationRegistryDefinitionId, + timestamp: u64, + rev_reg_def_meta: Option<&Self::RevocationRegistryDefinitionAdditionalMetadata>, + ) -> VcxLedgerResult<(RevocationStatusList, u64)> { + let meta = match rev_reg_def_meta { + Some(v) => Some(serde_json::from_value(v.to_owned())?), + None => None, + }; + + self.inner + .get_rev_status_list(rev_reg_id, timestamp, meta.as_ref()) + .await + } + async fn get_rev_reg( + &self, + rev_reg_id: &RevocationRegistryDefinitionId, + timestamp: u64, + ) -> VcxLedgerResult<(RevocationRegistry, u64)> { + self.inner.get_rev_reg(rev_reg_id, timestamp).await + } +} + +impl AnoncredsLedgerReadAdaptorTrait for AnoncredsLedgerReadAdaptor +where + T: AnoncredsLedgerRead + AnoncredsLedgerSupport, + T::RevocationRegistryDefinitionAdditionalMetadata: + Serialize + for<'de> Deserialize<'de> + Send + Sync, +{ +} + +#[cfg(test)] +mod unit_tests { + use async_trait::async_trait; + use mockall::{mock, predicate::eq}; + use serde_json::json; + + use super::*; + + mock! { + #[derive(Debug)] + pub Reader {} + #[async_trait] + impl AnoncredsLedgerRead for Reader { + type RevocationRegistryDefinitionAdditionalMetadata = Value; + + fn get_schema<'life0,'life1,'life2,'async_trait>(&'life0 self,schema_id: &'life1 SchemaId,submitter_did:Option< &'life2 Did> ,) -> ::core::pin::Pin > + ::core::marker::Send+'async_trait> >where 'life0:'async_trait,'life1:'async_trait,'life2:'async_trait,Self:'async_trait; + fn get_cred_def<'life0,'life1,'life2,'async_trait>(&'life0 self,cred_def_id: &'life1 CredentialDefinitionId,submitter_did:Option< &'life2 Did> ,) -> ::core::pin::Pin > + ::core::marker::Send+'async_trait> >where 'life0:'async_trait,'life1:'async_trait,'life2:'async_trait,Self:'async_trait; + async fn get_rev_reg_def_json(&self, rev_reg_id: &RevocationRegistryDefinitionId) -> VcxLedgerResult<(RevocationRegistryDefinition, Value)>; + async fn get_rev_reg_delta_json(&self, rev_reg_id: &RevocationRegistryDefinitionId, from: Option, to: Option) -> VcxLedgerResult<(RevocationRegistryDelta, u64)>; + fn get_rev_status_list<'life0,'life1,'life2,'async_trait>(&'life0 self,rev_reg_id: &'life1 RevocationRegistryDefinitionId,timestamp:u64,rev_reg_def_meta:Option< &'life2 Value>) -> ::core::pin::Pin > + ::core::marker::Send+'async_trait> >where 'life0:'async_trait,'life1:'async_trait,'life2:'async_trait,Self:'async_trait; + async fn get_rev_reg(&self, rev_reg_id: &RevocationRegistryDefinitionId, timestamp: u64) -> VcxLedgerResult<(RevocationRegistry, u64)>; + } + impl AnoncredsLedgerSupport for Reader { + fn supports_schema(&self, id: &SchemaId) -> bool; + fn supports_credential_definition(&self, id: &CredentialDefinitionId) -> bool; + fn supports_revocation_registry(&self, id: &RevocationRegistryDefinitionId) -> bool; + } + } + + #[test] + fn test_anoncreds_supports_schema_if_any_support() { + let mut reader1 = MockReader::new(); + reader1.expect_supports_schema().return_const(false); + let mut reader2 = MockReader::new(); + reader2.expect_supports_schema().return_const(false); + let mut reader3 = MockReader::new(); + reader3.expect_supports_schema().return_const(true); + + // no readers + let mut reader = MultiLedgerAnoncredsRead::new(); + assert!(!reader.supports_schema(&SchemaId::new_unchecked(""))); + + // with reader 1 + reader = reader.register_reader(reader1); + assert!(!reader.supports_schema(&SchemaId::new_unchecked(""))); + + // with reader 1,2 + reader = reader.register_reader(reader2); + assert!(!reader.supports_schema(&SchemaId::new_unchecked(""))); + + // with reader 1,2,3 + reader = reader.register_reader(reader3); + assert!(reader.supports_schema(&SchemaId::new_unchecked(""))); + } + + #[test] + fn test_anoncreds_supports_cred_def_if_any_support() { + let mut reader1 = MockReader::new(); + reader1 + .expect_supports_credential_definition() + .return_const(false); + let mut reader2 = MockReader::new(); + reader2 + .expect_supports_credential_definition() + .return_const(false); + let mut reader3 = MockReader::new(); + reader3 + .expect_supports_credential_definition() + .return_const(true); + + // no readers + let mut reader = MultiLedgerAnoncredsRead::new(); + assert!(!reader.supports_credential_definition(&CredentialDefinitionId::new_unchecked(""))); + + // with reader 1 + reader = reader.register_reader(reader1); + assert!(!reader.supports_credential_definition(&CredentialDefinitionId::new_unchecked(""))); + + // with reader 1,2 + reader = reader.register_reader(reader2); + assert!(!reader.supports_credential_definition(&CredentialDefinitionId::new_unchecked(""))); + + // with reader 1,2,3 + reader = reader.register_reader(reader3); + assert!(reader.supports_credential_definition(&CredentialDefinitionId::new_unchecked(""))); + } + + #[test] + fn test_anoncreds_supports_rev_reg_if_any_support() { + let mut reader1 = MockReader::new(); + reader1 + .expect_supports_revocation_registry() + .return_const(false); + let mut reader2 = MockReader::new(); + reader2 + .expect_supports_revocation_registry() + .return_const(false); + let mut reader3 = MockReader::new(); + reader3 + .expect_supports_revocation_registry() + .return_const(true); + + // no readers + let mut reader = MultiLedgerAnoncredsRead::new(); + assert!(!reader + .supports_revocation_registry(&RevocationRegistryDefinitionId::new_unchecked(""))); + + // with reader 1 + reader = reader.register_reader(reader1); + assert!(!reader + .supports_revocation_registry(&RevocationRegistryDefinitionId::new_unchecked(""))); + + // with reader 1,2 + reader = reader.register_reader(reader2); + assert!(!reader + .supports_revocation_registry(&RevocationRegistryDefinitionId::new_unchecked(""))); + + // with reader 1,2,3 + reader = reader.register_reader(reader3); + assert!( + reader.supports_revocation_registry(&RevocationRegistryDefinitionId::new_unchecked("")) + ); + } + + #[tokio::test] + async fn test_get_schema_proxy() { + let id = SchemaId::new_unchecked(uuid::Uuid::new_v4().to_string()); + let schema: Schema = serde_json::from_value(json!({ + "id": "2hoqvcwupRTUNkXn6ArYzs:2:test-licence:4.4.4", + "issuerId": "https://example.org/issuers/74acabe2-0edc-415e-ad3d-c259bac04c15", + "name": "Example schema", + "version": "0.0.1", + "attrNames": ["name", "age", "vmax"] + })) + .unwrap(); + + let mut reader1 = MockReader::new(); + reader1.expect_supports_schema().return_const(false); + let mut reader2 = MockReader::new(); + reader2.expect_supports_schema().return_const(true); + + let return_schema = schema.clone(); + let expected_id = id.clone(); + reader2 + .expect_get_schema() + .times(1) + .withf(move |id, _| id == &expected_id) + .return_once(move |_, _| { + let schema = return_schema.clone(); + Box::pin(async { Ok(schema) }) + }); + + let reader = MultiLedgerAnoncredsRead::new() + .register_reader(reader1) + .register_reader(reader2); + + let actual_schema = reader.get_schema(&id, None).await.unwrap(); + assert_eq!(actual_schema, schema); + } + + #[tokio::test] + async fn test_get_cred_def_proxy() { + let id = CredentialDefinitionId::new_unchecked(uuid::Uuid::new_v4().to_string()); + let cred_def: CredentialDefinition = serde_json::from_value(json!({ + "issuerId":"2hoqvcwupRTUNkXn6ArYzs", + "id":"V4SGRU86Z58d6TV7PBUe6f:3:CL:47:tag1", + "schemaId":"47", + "type":"CL", + "tag":"tag1", + "value":{"primary":{"n":"84315068910733942941538809865498212264459549000792879639194636554256493686411316918356364554212859153177297904254803226691261360163017568975126644984686667408908554649062870983454913573717132685671583694031717814141080679830350673819424952039249083306114176943232365022146274429759329160659813641353420711789491657407711667921406386914492317126931232096716361835185621871614892278526459017279649489759883446875710292582916862323180484745724279188511139859961558899492420881308319897939707149225665665750089691347075452237689762438550797003970061912118059748053097698671091262939106899007559343210815224380894488995113","s":"59945496099091529683010866609186265795684084593915879677365915314463441987443154552461559065352420479185095999059693986296256981985940684025427266913415378231498151267007158809467729823827861060943249985214295565954619712884813475078876243461567805408186530126430117091175878433493470477405243290350006589531746383498912735958116529589160259765518623375993634632483497463706818065357079852866706817198531892216731574724567574484572625164896490617904130456390333434781688685711531389963108606060826034467848677030185954836450146848456029587966315982491265726825962242361193382187200762212532433623355158921675478443655","r":{"date":"4530952538742033870264476947349521164360569832293598526413037147348444667070532579011380195228953804587892910083371419619205239227176615305655903664544843027114068926732016634797988559479373173420379032359085866159812396874183493337593923986352373367443489125306598512961937690050408637316178808308468698130916843726350286470498112647012795872536655274223930769557053638433983185163528151238000191689201476902211980373037910868763273992732059619082351273391415938130689371576452787378432526477108387174464183508295202268819673712009207498503854885022563424081101176507778361451123464434452487512804710607807387159128","age":"15503562420190113779412573443648670692955804417106499721072073114914016752313409982751974380400397358007517489487316569306402072592113120841927939614225596950574350717260042735712458756920802142037678828871321635736672163943850608100354921834523463955560137056697629609048487954091228011758465160630168342803951659774432090950114225268433943738713511960512519720523823132697152235977167573478225681125743108316237901888395175219199986619980202460002105538052202194307901021813863765169429019328213794814861353730831662815923471654084390063142965516688500592978949402225958824367010905689069418109693434050714606537583","master_secret":"14941959991861844203640254789113219741444241402376608919648803136983822447657869566295932734574583636024573117873598134469823095273660720727015649700465955361130129864938450014649937111357170711555934174503723640116145690157792143484339964157425981213977310483344564302214614951542098664609872435210449645226834832312148045998264085006307562873923691290268448463268834055489643805348568651181211925383052438130996893167066397253030164424601706641019876113890399331369874738474583032456630131756536716380809815371596958967704560484978381009830921031570414600773593753852611696648360844881738828836829723309887344258937","degree":"67311842668657630299931187112088054454211766880915366228670112262543717421860411017794917555864962789983330613927578732076546462151555711446970436129702520726176833537897538147071443776547628756352432432835899834656529545556299956904072273738406120215054506535933414063527222201017224487746551625599741110865905908376807007226016794285559868443574843566769079505217003255193711592800832900528743423878219697996298053773029816576222817010079313631823474213756143038164999157352990720891769630050634864109412199796030812795554794690666251581638175258059399898533412136730015599390155694930639754604259112806273788686507","name":"40219920836667226846980595968749841377080664270433982561850197901597771608457272395564987365558822976616985553706043669221173208652485993987057610703687751081160705282278075965587059598006922553243119778614657332904443210949022832267152413602769950017196241603290054807405460837019722951966510572795690156337466164027728801433988397914462240536123226066351251559900540164628048512242681757179461134506191038056117474598282470153495944204106741140156797129717000379741035610651103388047392025454843123388667794650989667119908702980140953817053781064048661940525040691050449058181790166453523432033421772638164421440685"},"rctxt":"82211384518226913414705883468527183492640036595481131419387459490531641219140075943570487048949702495964452189878216535351106872901004288800618738558792099255633906919332859771231971995964089510050225371749467514963769062274472125808020747444043470829002911273221886787637565057381007986495929400181408859710441856354570835196999403016572481694010972193591132652075787983469256801030377358546763251500115728919042442285672299538383497028946509014399210152856456151424115321673276206158701693427269192935107281015760959764697283756967072538997471422184132520456634304294669685041869025373789168601981777301930702142717","z":"597630352445077967631363625241310742422278192985165396805410934637833378871905757950406233560527227666603560941363695352019306999881059381981398160064772044355803827657704204341958693819520622597159046224481967205282164000142449330594352761829061889177257816365267888924702641013893644925126158726833651215929952524830180400844722456288706452674387695005404773156271263201912761375013255052598817079064887267420056304601888709527771529363399401864219168554878211931445812982845627741042319366707757767391990264005995464401655063121998656818808854159318505715730088491626077711079755220554530286586303737320102790443"},"revocation":{"g":"1 163FAAD4EB9AA0DF02C19EAC9E91DAFF5C9EEC50B13D59613BB03AC57A864724 1 091121B3A92D2C48A12FB2B6904AFDA9708EAC9CBDF4E9BF988C9071BB4CFEC2 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8","g_dash":"1 165E30BED89E08D23FC61685E5F38A65A74342EDF75283BE2E3D7A84D036AC1F 1 07D4894035E05420317656B39B0104E2E6CF372024C8DA9B5E69C05D073DEE17 1 2408458D7F1B790AC27A05055FB7DB562BD51E2597BC3CA5713589716A128647 1 1965D421EA07B38C9C287348BC6AAC53B7FF6E44DE6AC3202F4E62B147019FB3 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8 1 0000000000000000000000000000000000000000000000000000000000000000","h":"1 1EC742963B128F781DEC49BF60E9D7D627BE75EE6DB6FC7EC0A4388EB6EDDD5E 1 0A98F72733982BF22B83E40FB03AA339C990424498DFF7D227B75F442F089E71 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8","h0":"1 1EBE1D3B82473D8435B13E1B22B9B8A3FFD8251F3FACF423CE3CF0A63AF81D6B 1 10890876E36CCB96308ED4C284CDC4B2B014AE67404207E73F287EC86ACFE809 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8","h1":"1 21F6A9DA5A812DB4840340A817788CC84EB3C079E07C9908E9637C0A00F2DD56 1 1B1A0005E895B479500E818FC2280B6D06C088788CCF44C07E94B55941EE85F6 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8","h2":"1 180ADD04BFF577BCC49D09F97A9C11347C7A0359A0347DE9F138393CAF5F1F93 1 1044FFDF4AC72BBD8B6CC38D918A7C64A441E53D4561A7F5799B68D48E355294 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8","htilde":"1 031D6DDE2A7B05F29EFB574973E6D54AE36B79EBDD0599CD5AD2DF93BDBD0661 1 23A358FEC4883CE1EF44EEC1640B4D4C27FF5C7D64E9798BBF2C5A0D414D1AB5 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8","h_cap":"1 1536F787B8F6676E31B769543085CC12E484D6B9A136A29E05723DE993E52C78 1 05EF3C2E5AC1F62132E1F62AC715588203902BCBA8D40203606E6834F9065BB5 1 09878859092CA40C7D5AB4D42F6AFC16987CC90C361F161F9383BCD70F0BD7F0 1 2472E732278D393032B33DEDD2F38F84C3D05E109819E97D462D55822FD14DAA 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8 1 0000000000000000000000000000000000000000000000000000000000000000","u":"1 11523B940E760339BBDA36AE6B2DDA570E9CCC2E9314744FCB6C767DF022C5CF 1 1DADE6A6EBFFB2D329A691DB51C3A862F5FBD7D6BD5E594216E613BE882DBC02 1 0E4DE16A4C7514B7F1E09D1253F79B1D3127FD45AB2E535717BA2912F048D587 1 14A1436619A0C1B02302D66D78CE66027A1AAF44FC6FA0BA605E045526A76B76 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8 1 0000000000000000000000000000000000000000000000000000000000000000","pk":"1 0CBF9F57DD1607305F2D6297E85CA9B1D71BCBDCE26E10329224C4EC3C0299D6 1 01EE49B4D07D933E518E9647105408758B1D7E977E66E976E4FE4A2E66F8E734 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8","y":"1 1D2618B8EA3B4E1C5C8D0382940E34DA19425E3CE69C2F6A55F10352ABDF7BD9 1 1F45619B4247A65FDFE577B6AE40474F53E94A83551622859795E71B44920FA0 1 21324A71042C04555C2C89881F297E6E4FB10BA3949B0C3C345B4E5EE4C48100 1 0FAF04961F119E50C72FF39E7E7198EBE46C2217A87A47C6A6A5BFAB6D39E1EE 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8 1 0000000000000000000000000000000000000000000000000000000000000000"}} + })) + .unwrap(); + + let mut reader1 = MockReader::new(); + reader1 + .expect_supports_credential_definition() + .return_const(false); + let mut reader2 = MockReader::new(); + reader2 + .expect_supports_credential_definition() + .return_const(true); + + let return_cred_def = cred_def.try_clone().unwrap(); + let expected_id = id.clone(); + reader2 + .expect_get_cred_def() + .times(1) + .withf(move |id, _| id == &expected_id) + .return_once(move |_, _| { + let cred_def = return_cred_def.try_clone().unwrap(); + Box::pin(async { Ok(cred_def) }) + }); + + let reader = MultiLedgerAnoncredsRead::new() + .register_reader(reader1) + .register_reader(reader2); + + let actual_cred_def = reader.get_cred_def(&id, None).await.unwrap(); + assert_eq!( + serde_json::to_value(actual_cred_def).unwrap(), + serde_json::to_value(cred_def).unwrap() + ); + } + + #[tokio::test] + async fn test_get_rev_reg_def_proxy() { + let id = RevocationRegistryDefinitionId::new_unchecked(uuid::Uuid::new_v4().to_string()); + let rev_reg_def: RevocationRegistryDefinition = serde_json::from_value(json!({ + "id": id, + "issuerId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b", + "credDefId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b/resources/8372c1bc-907d-44a9-86be-ac3672b26e2e", + "revocDefType": "CL_ACCUM", + "tag": "1.0", + "value": { + "maxCredNum": 5, + "publicKeys": { + "accumKey": { + "z": "1 10D3560CAE0591EEA7D7A63E1A362FC31448EF321E04FD75F248BBAF02DE9749 1 118C4B0C7F3D86D46C22D62BAE7E613B137A879B50EFDFC56451AB9012BA57A0 1 23D6952F9D058744D4930D1DE6D79548BDCA3EE8BAAF64B712668E52A1290547 1 14C4C4389D92A99C4DA7E6CC2BD0C82E2809D3CD202CD2F0AD6C33D75AA39049 1 174EACBC7981492A791A72D57C6CB9FE488A679C4A5674E4F3C247D73A827384 1 0172B8961122D4D825B282CA1CD1BBC3B8DC459994C9FE2827CDF74B3AB08D38 1 181159044E453DC59FF320E9E08C666176F6B9309E162E2DA4FC1DB3156F7B1F 1 2323CEBFB26C6D28CBAF5F87F155362C6FA14AFA0EBA7DE2B4154FE4082E30FD 1 2354CB1624B42A284B41E5B3B4489C2795DBA9B88A725005555FB698AFF97260 1 07EEEF48EF52E5B15FD4AC28F0DAEDE0A259A27500855992307518A0DBE29A83 1 00FE73BCDB27D1DAD37E4F0E424372CA9548F11B4EC977DCCCC53D99A5C66F36 1 07E9DC0DD2163A66EDA84CD6BF282C7E18CB821762B6047CA1AB9FBE94DC6546" + } + }, + "tailsHash": "GW1bmjcMmtHnLwbWrabX4sWYVopJMEvQWgYMAEDmbJS3", + "tailsLocation": "GW1bmjcMmtHnLwbWrabX4sWYVopJMEvQWgYMAEDmbJS3" + } + })) + .unwrap(); + let meta = json!({ + "foo": "bar", + uuid::Uuid::new_v4().to_string(): [uuid::Uuid::new_v4().to_string()], + }); + + let mut reader1 = MockReader::new(); + reader1 + .expect_supports_revocation_registry() + .return_const(false); + let mut reader2 = MockReader::new(); + reader2 + .expect_supports_revocation_registry() + .return_const(true); + + let return_def = rev_reg_def.clone(); + let return_meta = meta.clone(); + reader2 + .expect_get_rev_reg_def_json() + .times(1) + .with(eq(id.clone())) + .return_once(move |_| Ok((return_def, return_meta))); + + let reader = MultiLedgerAnoncredsRead::new() + .register_reader(reader1) + .register_reader(reader2); + + let (actual_def, actual_meta) = reader.get_rev_reg_def_json(&id).await.unwrap(); + assert_eq!( + serde_json::to_value(actual_def).unwrap(), + serde_json::to_value(rev_reg_def).unwrap() + ); + assert_eq!( + serde_json::to_value(actual_meta).unwrap(), + serde_json::to_value(meta).unwrap() + ); + } + + #[tokio::test] + async fn test_get_rev_status_list_proxy() { + let id = RevocationRegistryDefinitionId::new_unchecked(uuid::Uuid::new_v4().to_string()); + let input_timestamp = 978; + let meta = json!({ + "foo": "bar", + uuid::Uuid::new_v4().to_string(): [uuid::Uuid::new_v4().to_string()], + }); + let rev_status_list: RevocationStatusList = serde_json::from_value(json!({ + "issuerId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b", + "revRegDefId": "4xE68b6S5VRFrKMMG1U95M:4:4xE68b6S5VRFrKMMG1U95M:3:CL:59232:default:CL_ACCUM:4ae1cc6c-f6bd-486c-8057-88f2ce74e960", + "revocationList": [0, 1, 1, 0], + "currentAccumulator": "21 124C594B6B20E41B681E92B2C43FD165EA9E68BC3C9D63A82C8893124983CAE94 21 124C5341937827427B0A3A32113BD5E64FB7AB39BD3E5ABDD7970874501CA4897 6 5438CB6F442E2F807812FD9DC0C39AFF4A86B1E6766DBB5359E86A4D70401B0F 4 39D1CA5C4716FFC4FE0853C4FF7F081DFD8DF8D2C2CA79705211680AC77BF3A1 6 70504A5493F89C97C225B68310811A41AD9CD889301F238E93C95AD085E84191 4 39582252194D756D5D86D0EED02BF1B95CE12AED2FA5CD3C53260747D891993C", + "timestamp": 1669640864 as u64 + })) + .unwrap(); + let output_timestamp = 876; + + let mut reader1 = MockReader::new(); + reader1 + .expect_supports_revocation_registry() + .return_const(false); + let mut reader2 = MockReader::new(); + reader2 + .expect_supports_revocation_registry() + .return_const(true); + + let return_list = rev_status_list.clone(); + let expected_id = id.clone(); + let expected_meta = meta.clone(); + reader2 + .expect_get_rev_status_list() + .times(1) + .withf(move |id, ts, meta| { + id == &expected_id && ts == &input_timestamp && meta == &Some(&expected_meta) + }) + .return_once(move |_, _, _| { + Box::pin(async move { Ok((return_list, output_timestamp)) }) + }); + + let reader = MultiLedgerAnoncredsRead::new() + .register_reader(reader1) + .register_reader(reader2); + + let (actual_list, actual_timestamp) = reader + .get_rev_status_list(&id, input_timestamp, Some(&meta)) + .await + .unwrap(); + assert_eq!( + serde_json::to_value(actual_list).unwrap(), + serde_json::to_value(rev_status_list).unwrap() + ); + assert_eq!( + serde_json::to_value(actual_timestamp).unwrap(), + serde_json::to_value(output_timestamp).unwrap() + ); + } + + #[tokio::test] + async fn test_get_rev_reg_delta_proxy() { + let id = RevocationRegistryDefinitionId::new_unchecked(uuid::Uuid::new_v4().to_string()); + let rev_reg_delta: RevocationRegistryDelta = serde_json::from_value(json!({ + "value":{"accum":"2 0A0752AD393CCA8E840459E79BCF48F16ECEF17C00E9B639AC6CE2CCC93954C9 2 242D07E4AE3284C1E499D98E4EDF65ACFC0392E64C2BFF55192AC3AE51C3657C 2 165A2D44CAEE9717F1F52CC1BA6F72F39B21F969B3C4CDCA4FB501880F7AD297 2 1B08C9BB4876353F70E4A639F3B41593488B9964D4A56B61B0E1FF8B0FB0A1E7 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8 1 0000000000000000000000000000000000000000000000000000000000000000"} + })) + .unwrap(); + let from = 123; + let to = 345; + let timestamp = 678; + + let mut reader1 = MockReader::new(); + reader1 + .expect_supports_revocation_registry() + .return_const(false); + let mut reader2 = MockReader::new(); + reader2 + .expect_supports_revocation_registry() + .return_const(true); + + let return_delta = rev_reg_delta.clone(); + reader2 + .expect_get_rev_reg_delta_json() + .times(1) + .with(eq(id.clone()), eq(Some(from)), eq(Some(to))) + .return_once(move |_, _, _| Ok((return_delta, timestamp))); + + let reader = MultiLedgerAnoncredsRead::new() + .register_reader(reader1) + .register_reader(reader2); + + let (actual_delta, actual_timestamp) = reader + .get_rev_reg_delta_json(&id, Some(from), Some(to)) + .await + .unwrap(); + assert_eq!(actual_delta, rev_reg_delta); + assert_eq!(actual_timestamp, timestamp); + } + + #[tokio::test] + async fn test_get_rev_reg_proxy() { + let id = RevocationRegistryDefinitionId::new_unchecked(uuid::Uuid::new_v4().to_string()); + let rev_reg: RevocationRegistry = serde_json::from_value(json!({ + "value":{"accum":"2 0A0752AD393CCA8E840459E79BCF48F16ECEF17C00E9B639AC6CE2CCC93954C9 2 242D07E4AE3284C1E499D98E4EDF65ACFC0392E64C2BFF55192AC3AE51C3657C 2 165A2D44CAEE9717F1F52CC1BA6F72F39B21F969B3C4CDCA4FB501880F7AD297 2 1B08C9BB4876353F70E4A639F3B41593488B9964D4A56B61B0E1FF8B0FB0A1E7 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8 1 0000000000000000000000000000000000000000000000000000000000000000"} + })) + .unwrap(); + let to = 345; + let timestamp = 678; + + let mut reader1 = MockReader::new(); + reader1 + .expect_supports_revocation_registry() + .return_const(false); + let mut reader2 = MockReader::new(); + reader2 + .expect_supports_revocation_registry() + .return_const(true); + + let return_reg = rev_reg.clone(); + reader2 + .expect_get_rev_reg() + .times(1) + .with(eq(id.clone()), eq(to)) + .return_once(move |_, _| Ok((return_reg, timestamp))); + + let reader = MultiLedgerAnoncredsRead::new() + .register_reader(reader1) + .register_reader(reader2); + + let (actual_reg, actual_timestamp) = reader.get_rev_reg(&id, to).await.unwrap(); + assert_eq!(actual_reg, rev_reg); + assert_eq!(actual_timestamp, timestamp); + } +} diff --git a/aries/aries_vcx_ledger/tests/test_multi_ledger.rs b/aries/aries_vcx_ledger/tests/test_multi_ledger.rs new file mode 100644 index 0000000000..69c8279027 --- /dev/null +++ b/aries/aries_vcx_ledger/tests/test_multi_ledger.rs @@ -0,0 +1,44 @@ +use std::sync::Arc; + +use aries_vcx_ledger::{ + errors::error::VcxLedgerResult, + ledger::{ + cheqd::CheqdAnoncredsLedgerRead, + indy_vdr_ledger::{IndyVdrLedgerRead, IndyVdrLedgerReadConfig}, + multi_ledger::MultiLedgerAnoncredsRead, + request_submitter::RequestSubmitter, + response_cacher::noop::NoopResponseCacher, + }, +}; +use async_trait::async_trait; +use did_cheqd::resolution::resolver::DidCheqdResolver; +use indy_vdr::pool::ProtocolVersion; +use mockall::mock; + +mock! { + pub RequestSubmitter {} + #[async_trait] + impl RequestSubmitter for RequestSubmitter { + async fn submit(&self, request: indy_vdr::pool::PreparedRequest) -> VcxLedgerResult; + } +} + +fn dummy_indy_vdr_reader() -> IndyVdrLedgerRead { + IndyVdrLedgerRead::new(IndyVdrLedgerReadConfig { + request_submitter: MockRequestSubmitter::new(), + response_parser: indy_ledger_response_parser::ResponseParser, + response_cacher: NoopResponseCacher, + protocol_version: ProtocolVersion::Node1_4, + }) +} + +// asserts the successful construction using our defined anoncreds ledger readers. +#[test] +fn test_construction() { + let cheqd = CheqdAnoncredsLedgerRead::new(Arc::new(DidCheqdResolver::new(Default::default()))); + let indy = dummy_indy_vdr_reader(); + + let _multi_ledger = MultiLedgerAnoncredsRead::new() + .register_reader(cheqd) + .register_reader(indy); +} diff --git a/aries/misc/test_utils/src/constants.rs b/aries/misc/test_utils/src/constants.rs index 416c725527..feec1bcdf3 100644 --- a/aries/misc/test_utils/src/constants.rs +++ b/aries/misc/test_utils/src/constants.rs @@ -57,7 +57,7 @@ pub static LICENCE_CRED_ID: &str = "92556f60-d290-4b58-9a43-05c25aac214e"; pub static REV_REG_ID: &str = r#"V4SGRU86Z58d6TV7PBUe6f:4:V4SGRU86Z58d6TV7PBUe6f:3:CL:1281:tag1:CL_ACCUM:tag1"#; pub static REV_REG_DELTA_JSON: &str = r#"{"ver":"1.0","value":{"accum":"2 0A0752AD393CCA8E840459E79BCF48F16ECEF17C00E9B639AC6CE2CCC93954C9 2 242D07E4AE3284C1E499D98E4EDF65ACFC0392E64C2BFF55192AC3AE51C3657C 2 165A2D44CAEE9717F1F52CC1BA6F72F39B21F969B3C4CDCA4FB501880F7AD297 2 1B08C9BB4876353F70E4A639F3B41593488B9964D4A56B61B0E1FF8B0FB0A1E7 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8 1 0000000000000000000000000000000000000000000000000000000000000000"}}"#; -pub static REV_STATUS_LIST_JSON: &str = r#"{"revRegDefId": "4xE68b6S5VRFrKMMG1U95M:4:4xE68b6S5VRFrKMMG1U95M:3:CL:59232:default:CL_ACCUM:4ae1cc6c-f6bd-486c-8057-88f2ce74e960","issuerId": "did:web:example.org","revocationList": [0, 1, 1, 0],"currentAccumulator": "21 124C594B6B20E41B681E92B2C43FD165EA9E68BC3C9D63A82C8893124983CAE94 21 124C5341937827427B0A3A32113BD5E64FB7AB39BD3E5ABDD7970874501CA4897 6 5438CB6F442E2F807812FD9DC0C39AFF4A86B1E6766DBB5359E86A4D70401B0F 4 39D1CA5C4716FFC4FE0853C4FF7F081DFD8DF8D2C2CA79705211680AC77BF3A1 6 70504A5493F89C97C225B68310811A41AD9CD889301F238E93C95AD085E84191 4 39582252194D756D5D86D0EED02BF1B95CE12AED2FA5CD3C53260747D891993C","timestamp": 1669640864487}"#; +pub static REV_STATUS_LIST_JSON: &str = r#"{"revRegDefId": "4xE68b6S5VRFrKMMG1U95M:4:4xE68b6S5VRFrKMMG1U95M:3:CL:59232:default:CL_ACCUM:4ae1cc6c-f6bd-486c-8057-88f2ce74e960","issuerId": "did:web:example.org","revocationList": [0, 1, 1, 0],"currentAccumulator": "21 124C594B6B20E41B681E92B2C43FD165EA9E68BC3C9D63A82C8893124983CAE94 21 124C5341937827427B0A3A32113BD5E64FB7AB39BD3E5ABDD7970874501CA4897 6 5438CB6F442E2F807812FD9DC0C39AFF4A86B1E6766DBB5359E86A4D70401B0F 4 39D1CA5C4716FFC4FE0853C4FF7F081DFD8DF8D2C2CA79705211680AC77BF3A1 6 70504A5493F89C97C225B68310811A41AD9CD889301F238E93C95AD085E84191 4 39582252194D756D5D86D0EED02BF1B95CE12AED2FA5CD3C53260747D891993C","timestamp": 1669640864}"#; pub static REV_STATE_JSON: &str = r#"{"rev_reg":{"accum":"1 0000000000000000000000000000000000000000000000000000000000000000 1 0000000000000000000000000000000000000000000000000000000000000000 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8 1 0000000000000000000000000000000000000000000000000000000000000000 1 0000000000000000000000000000000000000000000000000000000000000000 1 0000000000000000000000000000000000000000000000000000000000000000"},"timestamp":100,"witness":{"omega":"1 0000000000000000000000000000000000000000000000000000000000000000 1 0000000000000000000000000000000000000000000000000000000000000000 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8 1 0000000000000000000000000000000000000000000000000000000000000000 1 0000000000000000000000000000000000000000000000000000000000000000 1 0000000000000000000000000000000000000000000000000000000000000000"}}"#; pub static REV_REG_JSON: &str = r#"{"value":{"accum":"2 0204F2D2B1F2B705A11AAFEEE73C9BA084C12AF1179294529AC4D14CA54E87F3 2 222BAE38FAF2673F7BCBB86D8DE1A327F5065BDC892E9A122164260C97BC0C63 2 1565105F8BA53037978B66E0CC9F53205F189DEEB6B7168744456DD98D2F4E88 2 1AC9E76B2868141A42329778831C14AEAAF7A9981209C1D96AECA4E69CAFB243 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8 1 0000000000000000000000000000000000000000000000000000000000000000"}}"#; pub static TEST_TAILS_LOCATION: &str = r#"/var/folders/kr/9gkxsj_s01b6fvx_72trl3mm0000gp/T/tails_file/5R6BWXL3vPrbJPKe9FsHAVG9hqKdDvVxonBuj3ETYuZh"#; From c48f329a831af5e049076f72c0c630e50e483213 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Mon, 9 Dec 2024 15:59:56 +1000 Subject: [PATCH 34/50] some more testing and todos Signed-off-by: George Mulhearn --- .../src/anoncreds/anoncreds/mod.rs | 2 +- .../src/anoncreds/base_anoncreds.rs | 2 +- .../src/errors/mapping_cheqd.rs | 2 +- .../src/ledger/indy_vdr_ledger.rs | 2 +- .../anoncreds_types/src/utils/conversions.rs | 10 ++- did_core/did_methods/did_cheqd/Cargo.toml | 2 +- .../did_cheqd/src/resolution/resolver.rs | 64 ++++++++++++++- .../did_methods/did_cheqd/tests/resolution.rs | 81 ++++++++++++++++++- .../src/shared_types/did_resource.rs | 57 ++++++++++++- 9 files changed, 206 insertions(+), 16 deletions(-) diff --git a/aries/aries_vcx_anoncreds/src/anoncreds/anoncreds/mod.rs b/aries/aries_vcx_anoncreds/src/anoncreds/anoncreds/mod.rs index 2a8a11a0a5..3828e3cf74 100644 --- a/aries/aries_vcx_anoncreds/src/anoncreds/anoncreds/mod.rs +++ b/aries/aries_vcx_anoncreds/src/anoncreds/anoncreds/mod.rs @@ -1128,7 +1128,7 @@ impl BaseAnonCreds for Anoncreds { let current_time = OffsetDateTime::now_utc().unix_timestamp() as u64; let rev_status_list = from_revocation_registry_delta_to_revocation_status_list( &last_rev_reg_delta.value, - Some(current_time), + current_time, &rev_reg_def.id, rev_reg_def.value.max_cred_num as usize, rev_reg_def.issuer_id.clone(), diff --git a/aries/aries_vcx_anoncreds/src/anoncreds/base_anoncreds.rs b/aries/aries_vcx_anoncreds/src/anoncreds/base_anoncreds.rs index 8cb009c22d..49163b6c73 100644 --- a/aries/aries_vcx_anoncreds/src/anoncreds/base_anoncreds.rs +++ b/aries/aries_vcx_anoncreds/src/anoncreds/base_anoncreds.rs @@ -174,8 +174,8 @@ pub trait BaseAnonCreds: std::fmt::Debug + Send + Sync { // TODO - FUTURE - think about moving this to somewhere else, as it aggregates other calls (not // PURE Anoncreds) - // TODO - review functionality below and convert to using statuslists // ^ YES + // TODO - review functionality below and convert to using statuslists (https://github.com/hyperledger/aries-vcx/issues/1309) async fn revoke_credential_local( &self, wallet: &impl BaseWallet, diff --git a/aries/aries_vcx_ledger/src/errors/mapping_cheqd.rs b/aries/aries_vcx_ledger/src/errors/mapping_cheqd.rs index 5d00b7cec8..ded7c36f89 100644 --- a/aries/aries_vcx_ledger/src/errors/mapping_cheqd.rs +++ b/aries/aries_vcx_ledger/src/errors/mapping_cheqd.rs @@ -25,7 +25,7 @@ impl From for VcxLedgerError { VcxLedgerError::ParseError(e) } DidCheqdError::Other(_) => VcxLedgerError::UnknownError(value.to_string()), - _ => todo!(), + _ => VcxLedgerError::UnknownError(value.to_string()), } } } diff --git a/aries/aries_vcx_ledger/src/ledger/indy_vdr_ledger.rs b/aries/aries_vcx_ledger/src/ledger/indy_vdr_ledger.rs index 1c1c40d661..270cfe2d8b 100644 --- a/aries/aries_vcx_ledger/src/ledger/indy_vdr_ledger.rs +++ b/aries/aries_vcx_ledger/src/ledger/indy_vdr_ledger.rs @@ -584,7 +584,7 @@ where let status_list = from_revocation_registry_delta_to_revocation_status_list( &delta.value, - Some(entry_time), + entry_time, &rev_reg_id, rev_reg_def_meta.max_cred_num, rev_reg_def_meta.issuer_id.clone(), diff --git a/aries/misc/anoncreds_types/src/utils/conversions.rs b/aries/misc/anoncreds_types/src/utils/conversions.rs index ecad6a14c7..1230753994 100644 --- a/aries/misc/anoncreds_types/src/utils/conversions.rs +++ b/aries/misc/anoncreds_types/src/utils/conversions.rs @@ -5,10 +5,14 @@ use crate::data_types::{ ledger::{rev_reg_delta::RevocationRegistryDeltaValue, rev_status_list::RevocationStatusList}, }; -/// TODO - explain +/// Converts from a [RevocationRegistryDeltaValue] into a completed [RevocationStatusList] +/// (newer format). +/// +/// NOTE: this conversion only works if the delta was calculated from START (timestamp 0/None) +/// to `timestamp`. pub fn from_revocation_registry_delta_to_revocation_status_list( delta: &RevocationRegistryDeltaValue, - timestamp: Option, + timestamp: u64, rev_reg_id: &RevocationRegistryDefinitionId, max_cred_num: usize, issuer_id: IssuerId, @@ -55,7 +59,7 @@ pub fn from_revocation_registry_delta_to_revocation_status_list( issuer_id, revocation_list, Some(accum), - timestamp, + Some(timestamp), ) .map_err(Into::into) } diff --git a/did_core/did_methods/did_cheqd/Cargo.toml b/did_core/did_methods/did_cheqd/Cargo.toml index 371e6724f2..22bf389252 100644 --- a/did_core/did_methods/did_cheqd/Cargo.toml +++ b/did_core/did_methods/did_cheqd/Cargo.toml @@ -28,7 +28,7 @@ serde_json = "1.0.96" serde = { version = "1.0.160", features = ["derive"] } thiserror = "1.0.40" tokio = { version = "1.38.0" } -chrono = { version = "0.4.24", default-features = false } +chrono = { version = "0.4.24", default-features = false, features = ["now"] } url = { version = "2.3.1", default-features = false } bytes = "1.8.0" diff --git a/did_core/did_methods/did_cheqd/src/resolution/resolver.rs b/did_core/did_methods/did_cheqd/src/resolution/resolver.rs index 48851bf4b9..6ba71137ed 100644 --- a/did_core/did_methods/did_cheqd/src/resolution/resolver.rs +++ b/did_core/did_methods/did_cheqd/src/resolution/resolver.rs @@ -191,7 +191,15 @@ impl DidCheqdResolver { Ok(output_builder.build()) } - /// TODO - explain what is and isn't supported + /// Resolve a cheqd DID resource & associated metadata from the given [DidUrl]. + /// Resolution is done according to the [DID-Linked Resources](https://w3c-ccg.github.io/DID-Linked-Resources/) + /// specification, however only a subset of query types are supported currently: + /// * by resource path: `did:example:/resources/` + /// * by name & type: `did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J?resourceName=universityDegree& + /// resourceType=anonCredsStatusList` + /// * by name & type & time: + /// `did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J?resourceName=universityDegree& + /// resourceType=anonCredsStatusList&versionTime=2022-08-21T08:40:00Z` pub async fn resolve_resource(&self, url: &DidUrl) -> DidCheqdResult { let method = url.method(); if method != Some("cheqd") { @@ -203,7 +211,7 @@ impl DidCheqdResolver { .id() .ok_or(DidCheqdError::InvalidDidUrl(format!("missing ID {url}")))?; - // 1. resolve by exact reference: /reference/asdf + // 1. resolve by exact reference: /resources/asdf if let Some(path) = url.path() { let Some(resource_id) = path.strip_prefix("/resources/") else { return Err(DidCheqdError::InvalidDidUrl(format!( @@ -245,6 +253,7 @@ impl DidCheqdResolver { .await } + /// Resolve a resource from a collection (did_id) and network by an exact id. async fn resolve_resource_by_id( &self, did_id: &str, @@ -289,6 +298,8 @@ impl DidCheqdResolver { }) } + /// Resolve a resource from a given collection (did_id) & network, that has a given name & type, + /// as of a given time. async fn resolve_resource_by_name_type_and_time( &self, did_id: &str, @@ -346,6 +357,7 @@ fn native_tls_hyper_client() -> DidCheqdResult { .build(connector)) } +/// Filter for resources which have a matching name and type fn filter_resources_by_name_and_type<'a>( resources: impl Iterator + 'a, name: &'a str, @@ -354,6 +366,7 @@ fn filter_resources_by_name_and_type<'a>( resources.filter(move |r| r.name == name && r.resource_type == rtyp) } +/// Sort resources chronologically by their created timestamps fn desc_chronological_sort_resources( b: &CheqdResourceMetadata, a: &CheqdResourceMetadata, @@ -446,6 +459,49 @@ mod unit_tests { let e = resolver.resolve_did(&did).await.unwrap_err(); assert!(matches!(e, DidCheqdError::BadConfiguration(_))); } - - // TODO - unit test resources etc + + #[tokio::test] + async fn test_resolve_resource_fails_if_wrong_method() { + let url = "did:notcheqd:zF7rhDBfUt9d1gJPjx7s1J/resources/123" + .parse() + .unwrap(); + let resolver = DidCheqdResolver::new(Default::default()); + let e = resolver.resolve_resource(&url).await.unwrap_err(); + assert!(matches!(e, DidCheqdError::MethodNotSupported(_))); + } + + #[tokio::test] + async fn test_resolve_resource_fails_if_wrong_path() { + let url = "did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J/resource/123" + .parse() + .unwrap(); + let resolver = DidCheqdResolver::new(Default::default()); + let e = resolver.resolve_resource(&url).await.unwrap_err(); + assert!(matches!(e, DidCheqdError::InvalidDidUrl(_))); + } + + #[tokio::test] + async fn test_resolve_resource_fails_if_no_query() { + let url = "did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J".parse().unwrap(); + let resolver = DidCheqdResolver::new(Default::default()); + let e = resolver.resolve_resource(&url).await.unwrap_err(); + assert!(matches!(e, DidCheqdError::InvalidDidUrl(_))); + } + + #[tokio::test] + async fn test_resolve_resource_fails_if_incomplete_query() { + let url = "did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J?resourceName=asdf".parse().unwrap(); + let resolver = DidCheqdResolver::new(Default::default()); + let e = resolver.resolve_resource(&url).await.unwrap_err(); + assert!(matches!(e, DidCheqdError::InvalidDidUrl(_))); + } + + #[tokio::test] + async fn test_resolve_resource_fails_if_invalid_resource_time() { + // use epoch instead of XML DateTime + let url = "did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J?resourceName=asdf&resourceType=fdsa&resourceVersionTime=12341234".parse().unwrap(); + let resolver = DidCheqdResolver::new(Default::default()); + let e = resolver.resolve_resource(&url).await.unwrap_err(); + assert!(matches!(e, DidCheqdError::InvalidDidUrl(_))); + } } diff --git a/did_core/did_methods/did_cheqd/tests/resolution.rs b/did_core/did_methods/did_cheqd/tests/resolution.rs index cea9a7f457..41739b8826 100644 --- a/did_core/did_methods/did_cheqd/tests/resolution.rs +++ b/did_core/did_methods/did_cheqd/tests/resolution.rs @@ -1,9 +1,9 @@ use did_cheqd::resolution::resolver::{DidCheqdResolver, DidCheqdResolverConfiguration}; use did_resolver::traits::resolvable::DidResolvable; -use serde_json::json; +use serde_json::{json, Value}; #[tokio::test] -async fn test_resolve_known_mainnet_vector() { +async fn test_resolve_known_mainnet_did_vector() { // sample from https://dev.uniresolver.io/ let did = "did:cheqd:mainnet:Ps1ysXP2Ae6GBfxNhNQNKN".parse().unwrap(); // NOTE: modifications from uni-resolver: @@ -57,7 +57,7 @@ async fn test_resolve_known_mainnet_vector() { } #[tokio::test] -async fn test_resolve_known_testnet_vector() { +async fn test_resolve_known_testnet_did_vector() { // sample from https://dev.uniresolver.io/ let did = "did:cheqd:testnet:55dbc8bf-fba3-4117-855c-1e0dc1d3bb47" .parse() @@ -90,3 +90,78 @@ async fn test_resolve_known_testnet_vector() { assert_eq!(serde_json::to_value(doc.clone()).unwrap(), expected_doc); assert_eq!(doc, serde_json::from_value(expected_doc).unwrap()); } + +#[tokio::test] +async fn test_resolve_known_mainnet_resource_vector() { + let url = "did:cheqd:mainnet:e18756b4-25e6-42bb-b1e9-ea48cbe3c360/resources/\ + e8af40f9-3df2-40dc-b50d-d1a7e764b52d" + .parse() + .unwrap(); + + let expected_content = json!({ + "name": "Test cheqd anoncreds", + "version": "1.0", + "attrNames": ["test"] + }); + let expected_meta = json!({ + "alsoKnownAs": [{ "description": "did-url", "uri": "did:cheqd:mainnet:e18756b4-25e6-42bb-b1e9-ea48cbe3c360/resources/e8af40f9-3df2-40dc-b50d-d1a7e764b52d" }], + "resourceUri": "did:cheqd:mainnet:e18756b4-25e6-42bb-b1e9-ea48cbe3c360/resources/e8af40f9-3df2-40dc-b50d-d1a7e764b52d", + "resourceCollectionId": "e18756b4-25e6-42bb-b1e9-ea48cbe3c360", + "resourceId": "e8af40f9-3df2-40dc-b50d-d1a7e764b52d", + "resourceName": "Test cheqd anoncreds-Schema", + "resourceType": "anonCredsSchema", + "mediaType": "application/json", + "resourceVersion": "1.0", + "created": "2024-09-26T10:25:07Z", + "checksum": "01a38743e6f482c998ee8a5b84e1c7e116623a6c9b58c16125eebdf254d24da5" + }); + + let resolver = DidCheqdResolver::new(DidCheqdResolverConfiguration::default()); + let output = resolver.resolve_resource(&url).await.unwrap(); + let json_content: Value = serde_json::from_slice(&output.content).unwrap(); + assert_eq!(json_content, expected_content); + let json_meta = serde_json::to_value(output.metadata).unwrap(); + assert_eq!(json_meta, expected_meta); +} + +#[tokio::test] +async fn test_resolve_known_testnet_resource_query() { + // https://testnet-explorer.cheqd.io/transactions/222FF2D023C2C9A097BB38F3875F072DF8DEC7B0CBD46AC3459C9B4C3C74382F + + let name = "275990cc056b46176a7122cfd888f46a2bd8e3d45a71d5ff20764a874ed02edd"; + let typ = "anonCredsStatusList"; + let time = "2024-12-04T22:15:20Z"; + let url = format!( + "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b?resourceName={name}&\ + resourceType={typ}&resourceVersionTime={time}" + ) + .parse() + .unwrap(); + + let expected_content = json!({ + "currentAccumulator": "21 125DF938B3B772619CB43E561D69004CF09667376E9CD53C818D84860BAE3D1D9 21 11ECFC5F9B469AC74E2A0E329F86C6E60B423A53CAC5AE7A4DBE7A978BFFC0DA1 6 6FAD628FED470FF640BF2C5DB57C2C18D009645DBEF15D4AF710739D2AD93E2D 4 22093A3300411B059B8BB7A8C3296A2ED9C4C8E00106C3B2BAD76E25AC792063 6 71D70ECA81BCE610D1C22CADE688AF4A122C8258E8B306635A111D0A35A7238A 4 1E80F38ABA3A966B8657D722D4E956F076BB2F5CCF36AA8942E65500F8898FF3", + "revRegDefId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b/resources/4f265d83-4657-4c37-ba80-c66cc399457e", + "revocationList": [1,1,1,0,0] + }); + let expected_meta = json!({ + "alsoKnownAs": [{ "description": "did-url", "uri": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b/resources/d08596a8-c655-45cd-88d7-ac27e8f7d183" }], + "resourceUri": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b/resources/d08596a8-c655-45cd-88d7-ac27e8f7d183", + "resourceCollectionId": "8bbd2026-03f5-42c7-bf80-09f46fc4d67b", + "resourceId": "d08596a8-c655-45cd-88d7-ac27e8f7d183", + "resourceName": name, + "resourceType": typ, + "mediaType": "application/json", + "resourceVersion": "1669c51f-a382-4a35-a3cc-10f6a278950e", + "created": "2024-12-04T22:15:18Z", + "checksum": "0c9b32ad86c21001fb158e0b19ef6ade10f054d8b0a63cc49f12efc46bcd6ce4", + "nextVersionId": "8e93fa1c-6ee8-4416-8aeb-8ff52cc676ab", + "previousVersionId": "942f1817-a592-44c2-b5c2-bb6579527da5" + }); + + let resolver = DidCheqdResolver::new(DidCheqdResolverConfiguration::default()); + let output = resolver.resolve_resource(&url).await.unwrap(); + let json_content: Value = serde_json::from_slice(&output.content).unwrap(); + assert_eq!(json_content, expected_content); + let json_meta = serde_json::to_value(output.metadata).unwrap(); + assert_eq!(json_meta, expected_meta); +} diff --git a/did_core/did_resolver/src/shared_types/did_resource.rs b/did_core/did_resolver/src/shared_types/did_resource.rs index 7d675855d3..1ba8d077bf 100644 --- a/did_core/did_resolver/src/shared_types/did_resource.rs +++ b/did_core/did_resolver/src/shared_types/did_resource.rs @@ -44,11 +44,12 @@ pub struct DidResourceMetadata { pub also_known_as: Option>, /// A string that identifies the IANA-media type of the resource. pub media_type: String, - // TODO - check datetime serializes into XML-date-time /// A string that identifies the time the resource was created, as an XML date-time. + #[serde(with = "xml_datetime")] pub created: DateTime, /// (Optional) A string that identifies the time the resource was updated, as an XML date-time. #[serde(skip_serializing_if = "Option::is_none")] + #[serde(with = "xml_datetime::optional")] pub updated: Option>, /// A string that may be used to prove that the resource has not been tampered with. pub checksum: String, @@ -59,3 +60,57 @@ pub struct DidResourceMetadata { #[serde(skip_serializing_if = "Option::is_none")] pub next_version_id: Option, } + +/// Custom serialization module for XMLDateTime format. +/// Uses Z and removes subsecond precision +mod xml_datetime { + use chrono::{DateTime, SecondsFormat, Utc}; + use serde::{self, Deserialize, Deserializer, Serializer}; + + pub fn serialize(dt: &DateTime, serializer: S) -> Result + where + S: Serializer, + { + let s = dt.to_rfc3339_opts(SecondsFormat::Secs, true); + serializer.serialize_str(&s) + } + + pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> + where + D: Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + s.parse::>().map_err(serde::de::Error::custom) + } + + pub mod optional { + use chrono::{DateTime, Utc}; + use serde::{self, Deserialize, Deserializer, Serializer}; + + pub fn serialize(dt: &Option>, serializer: S) -> Result + where + S: Serializer, + { + match dt { + Some(dt) => super::serialize(dt, serializer), + None => serializer.serialize_none(), + } + } + + pub fn deserialize<'de, D>(deserializer: D) -> Result>, D::Error> + where + D: Deserializer<'de>, + { + let s = Option::::deserialize(deserializer)?; + match s { + Some(s) => { + let parsed = s + .parse::>() + .map_err(serde::de::Error::custom)?; + Ok(Some(parsed)) + } + None => Ok(None), + } + } + } +} From 7c31d583c7e640ca36b51dfd64fdec5a83dd70ae Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Mon, 9 Dec 2024 16:02:34 +1000 Subject: [PATCH 35/50] rm aliases Signed-off-by: George Mulhearn --- .../protocols/cred_issuance/v2/issue_credential.rs | 5 +---- .../protocols/cred_issuance/v2/offer_credential.rs | 6 +----- .../protocols/cred_issuance/v2/propose_credential.rs | 6 +----- .../protocols/cred_issuance/v2/request_credential.rs | 6 +----- .../src/msg_fields/protocols/present_proof/v2/present.rs | 6 +----- .../src/msg_fields/protocols/present_proof/v2/propose.rs | 6 +----- .../src/msg_fields/protocols/present_proof/v2/request.rs | 6 +----- 7 files changed, 7 insertions(+), 34 deletions(-) diff --git a/aries/messages/src/msg_fields/protocols/cred_issuance/v2/issue_credential.rs b/aries/messages/src/msg_fields/protocols/cred_issuance/v2/issue_credential.rs index 528124ccb8..a4b7323a7b 100644 --- a/aries/messages/src/msg_fields/protocols/cred_issuance/v2/issue_credential.rs +++ b/aries/messages/src/msg_fields/protocols/cred_issuance/v2/issue_credential.rs @@ -43,10 +43,7 @@ pub struct IssueCredentialV2Decorators { pub enum IssueCredentialAttachmentFormatType { #[serde(rename = "aries/ld-proof-vc@v1.0")] AriesLdProofVc1_0, - #[serde( - rename = "anoncreds/credential@v1.0", - alias = "anoncreds/cred@v2.0" // TODO - this is wrong, fix once acapy fixes - )] + #[serde(rename = "anoncreds/credential@v1.0")] AnoncredsCredential1_0, #[serde(rename = "hlindy/cred@v2.0")] HyperledgerIndyCredential2_0, diff --git a/aries/messages/src/msg_fields/protocols/cred_issuance/v2/offer_credential.rs b/aries/messages/src/msg_fields/protocols/cred_issuance/v2/offer_credential.rs index 413898845a..4bf242e348 100644 --- a/aries/messages/src/msg_fields/protocols/cred_issuance/v2/offer_credential.rs +++ b/aries/messages/src/msg_fields/protocols/cred_issuance/v2/offer_credential.rs @@ -45,11 +45,7 @@ pub enum OfferCredentialAttachmentFormatType { DifCredentialManifest1_0, #[serde(rename = "hlindy/cred-abstract@v2.0")] HyperledgerIndyCredentialAbstract2_0, - #[serde( - rename = "anoncreds/credential-offer@v1.0", - alias = "anoncreds/cred-abstract@v2.0", // TODO - remove after acapy fix - alias = "anoncreds/credential@v1.0" // TODO - remove after credo-ts fix - )] + #[serde(rename = "anoncreds/credential-offer@v1.0")] AnoncredsCredentialOffer1_0, #[serde(rename = "aries/ld-proof-vc-detail@v1.0")] AriesLdProofVcDetail1_0, diff --git a/aries/messages/src/msg_fields/protocols/cred_issuance/v2/propose_credential.rs b/aries/messages/src/msg_fields/protocols/cred_issuance/v2/propose_credential.rs index 3a5d8282dc..2c60094f25 100644 --- a/aries/messages/src/msg_fields/protocols/cred_issuance/v2/propose_credential.rs +++ b/aries/messages/src/msg_fields/protocols/cred_issuance/v2/propose_credential.rs @@ -44,11 +44,7 @@ pub enum ProposeCredentialAttachmentFormatType { DifCredentialManifest1_0, #[serde(rename = "aries/ld-proof-vc-detail@v1.0")] AriesLdProofVcDetail1_0, - #[serde( - rename = "anoncreds/credential-filter@v1.0", - // TODO - this is wrong, fix once acapy fixes - alias = "anoncreds/cred-filter@v2.0" - )] + #[serde(rename = "anoncreds/credential-filter@v1.0")] AnoncredCredentialFilter1_0, #[serde(rename = "hlindy/cred-filter@v2.0")] HyperledgerIndyCredentialFilter2_0, diff --git a/aries/messages/src/msg_fields/protocols/cred_issuance/v2/request_credential.rs b/aries/messages/src/msg_fields/protocols/cred_issuance/v2/request_credential.rs index 1cefa9c2ed..436ee9db70 100644 --- a/aries/messages/src/msg_fields/protocols/cred_issuance/v2/request_credential.rs +++ b/aries/messages/src/msg_fields/protocols/cred_issuance/v2/request_credential.rs @@ -40,11 +40,7 @@ pub enum RequestCredentialAttachmentFormatType { DifCredentialManifest1_0, #[serde(rename = "hlindy/cred-req@v2.0")] HyperledgerIndyCredentialRequest2_0, - #[serde( - rename = "anoncreds/credential-request@v1.0", - // TODO - this is wrong, fix once acapy fixes - alias = "anoncreds/cred-req@v2.0", - )] + #[serde(rename = "anoncreds/credential-request@v1.0")] AnoncredsCredentialRequest1_0, #[serde(rename = "aries/ld-proof-vc-detail@v1.0")] AriesLdProofVcDetail1_0, diff --git a/aries/messages/src/msg_fields/protocols/present_proof/v2/present.rs b/aries/messages/src/msg_fields/protocols/present_proof/v2/present.rs index 43179185a4..226728abf1 100644 --- a/aries/messages/src/msg_fields/protocols/present_proof/v2/present.rs +++ b/aries/messages/src/msg_fields/protocols/present_proof/v2/present.rs @@ -42,11 +42,7 @@ pub struct PresentationV2Decorators { pub enum PresentationAttachmentFormatType { #[serde(rename = "hlindy/proof@v2.0")] HyperledgerIndyProof2_0, - #[serde( - rename = "anoncreds/proof@v1.0", - // TODO - FIX - wrong ver, match acapy - alias = "anoncreds/proof@v2.0" - )] + #[serde(rename = "anoncreds/proof@v1.0")] AnoncredsProof1_0, #[serde(rename = "dif/presentation-exchange/submission@v1.0")] DifPresentationExchangeSubmission1_0, diff --git a/aries/messages/src/msg_fields/protocols/present_proof/v2/propose.rs b/aries/messages/src/msg_fields/protocols/present_proof/v2/propose.rs index e2c2f539b2..38652489f5 100644 --- a/aries/messages/src/msg_fields/protocols/present_proof/v2/propose.rs +++ b/aries/messages/src/msg_fields/protocols/present_proof/v2/propose.rs @@ -43,11 +43,7 @@ pub enum ProposePresentationAttachmentFormatType { DifPresentationExchangeDefinitions1_0, #[serde(rename = "hlindy/proof-req@v2.0")] HyperledgerIndyProofRequest2_0, - #[serde( - rename = "anoncreds/proof-request@v1.0", - // TODO - FIX - wrong ver, match acapy - alias = "anoncreds/proof-req@v2.0" - )] + #[serde(rename = "anoncreds/proof-request@v1.0")] AnoncredsProofRequest1_0, } diff --git a/aries/messages/src/msg_fields/protocols/present_proof/v2/request.rs b/aries/messages/src/msg_fields/protocols/present_proof/v2/request.rs index 3b677dea3b..af86c18d5c 100644 --- a/aries/messages/src/msg_fields/protocols/present_proof/v2/request.rs +++ b/aries/messages/src/msg_fields/protocols/present_proof/v2/request.rs @@ -44,11 +44,7 @@ pub struct RequestPresentationV2Decorators { pub enum PresentationRequestAttachmentFormatType { #[serde(rename = "hlindy/proof-req@v2.0")] HyperledgerIndyProofRequest2_0, - #[serde( - rename = "anoncreds/proof-request@v1.0", - // TODO - FIX - wrong ver, match acapy - alias = "anoncreds/proof-req@v2.0" - )] + #[serde(rename = "anoncreds/proof-request@v1.0")] AnoncredsProofRequest1_0, #[serde(rename = "dif/presentation-exchange/definitions@v1.0")] DifPresentationExchangeDefinitions1_0, From 56c282f1e5a3d47c0a37f2eabcc8866741f1ddc8 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Mon, 9 Dec 2024 16:16:53 +1000 Subject: [PATCH 36/50] test and CI fixing Signed-off-by: George Mulhearn --- .github/workflows/main.yml | 16 ++++++++++++++++ aries/misc/test_utils/src/constants.rs | 1 + justfile | 7 +++++-- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 276634dd93..72f961c155 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -342,6 +342,22 @@ jobs: with: name: "docker-services-${{ github.job }}" + test-integration-aries-vcx-ledger: + needs: workflow-setup + if: ${{ needs.workflow-setup.outputs.SKIP_CI != 'true' }} + 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 }} + - name: "Install just" + run: sudo snap install --edge --classic just + - name: "Run aries-vcx-ledger integration tests" + run: just test-integration-aries-vcx-ledger + test-integration-did-crate: needs: workflow-setup if: ${{ needs.workflow-setup.outputs.SKIP_CI != 'true' }} diff --git a/aries/misc/test_utils/src/constants.rs b/aries/misc/test_utils/src/constants.rs index feec1bcdf3..ea5070f056 100644 --- a/aries/misc/test_utils/src/constants.rs +++ b/aries/misc/test_utils/src/constants.rs @@ -67,6 +67,7 @@ pub static REQUEST_WITH_ENDORSER: &str = r#"{"seqNo":344,"reqId":152286672972686 pub fn rev_def_json() -> RevocationRegistryDefinition { serde_json::from_value(json!({ + "issuerId": INSTITUTION_DID, "ver":"1.0", "id": REV_REG_ID.to_string(), "revocDefType":"CL_ACCUM", diff --git a/justfile b/justfile index 609f68a7b5..45a323e90d 100644 --- a/justfile +++ b/justfile @@ -8,7 +8,7 @@ fmt-check: cargo +nightly-2023-05-08 fmt --check clippy-workspace wallet: - cargo clippy --examples --tests --no-default-features -F anoncreds,vdr_proxy_ledger,legacy_proof,{{wallet}} + cargo clippy --examples --tests --no-default-features -F anoncreds,vdr_proxy_ledger,legacy_proof,cheqd,{{wallet}} clippy-aries-vcx features: cargo clippy -p aries_vcx --features legacy_proof --features {{features}} --no-default-features @@ -20,7 +20,7 @@ check-aries-vcx-anoncreds: cargo test --manifest-path="aries/aries_vcx/Cargo.toml" -F askar_wallet,anoncreds --tests test-unit test_name="": - RUST_TEST_THREADS=1 cargo test --workspace --lib --exclude aries-vcx-agent --exclude mediator {{test_name}} -F did_doc/jwk -F public_key/jwk + RUST_TEST_THREADS=1 cargo test --workspace --lib --exclude aries-vcx-agent --exclude mediator {{test_name}} -F did_doc/jwk -F public_key/jwk -F aries_vcx_ledger/cheqd test-integration-aries-vcx features test_name="": cargo test --manifest-path="aries/aries_vcx/Cargo.toml" -F {{features}} -- --ignored {{test_name}} @@ -28,5 +28,8 @@ test-integration-aries-vcx features test_name="": test-integration-aries-vcx-vdrproxy test_name="": cargo test --manifest-path="aries/aries_vcx/Cargo.toml" -F vdr_proxy_ledger,anoncreds -- --ignored {{test_name}} +test-integration-aries-vcx-ledger: + cargo test --manifest-path="aries/aries_vcx_ledger/Cargo.toml" -F cheqd + test-integration-did-crate test_name="": cargo test --examples -p did_doc -p did_parser_nom -p did_resolver -p did_resolver_registry -p did_resolver_sov -p did_resolver_web -p did_key -p did_peer -p did_jwk -p did_cheqd -F did_doc/jwk --test "*" \ No newline at end of file From 9b13ff738a4ad609e088a3a089cbe4eb440a0b52 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Mon, 9 Dec 2024 16:23:49 +1000 Subject: [PATCH 37/50] fmt Signed-off-by: George Mulhearn --- aries/aries_vcx_ledger/src/ledger/cheqd/models.rs | 3 ++- .../did_methods/did_cheqd/src/resolution/resolver.rs | 9 +++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/aries/aries_vcx_ledger/src/ledger/cheqd/models.rs b/aries/aries_vcx_ledger/src/ledger/cheqd/models.rs index 83ad010415..e6a8b7496a 100644 --- a/aries/aries_vcx_ledger/src/ledger/cheqd/models.rs +++ b/aries/aries_vcx_ledger/src/ledger/cheqd/models.rs @@ -4,7 +4,8 @@ use anoncreds_types::data_types::{ identifiers::{cred_def_id::CredentialDefinitionId, schema_id::SchemaId}, ledger::{ cred_def::{CredentialDefinitionData, SignatureType}, - rev_reg_def::{RegistryType, RevocationRegistryDefinitionValue}, rev_status_list::serde_revocation_list, + rev_reg_def::{RegistryType, RevocationRegistryDefinitionValue}, + rev_status_list::serde_revocation_list, }, }; use serde::{Deserialize, Serialize}; diff --git a/did_core/did_methods/did_cheqd/src/resolution/resolver.rs b/did_core/did_methods/did_cheqd/src/resolution/resolver.rs index 6ba71137ed..0a67a2ad91 100644 --- a/did_core/did_methods/did_cheqd/src/resolution/resolver.rs +++ b/did_core/did_methods/did_cheqd/src/resolution/resolver.rs @@ -490,7 +490,9 @@ mod unit_tests { #[tokio::test] async fn test_resolve_resource_fails_if_incomplete_query() { - let url = "did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J?resourceName=asdf".parse().unwrap(); + let url = "did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J?resourceName=asdf" + .parse() + .unwrap(); let resolver = DidCheqdResolver::new(Default::default()); let e = resolver.resolve_resource(&url).await.unwrap_err(); assert!(matches!(e, DidCheqdError::InvalidDidUrl(_))); @@ -499,7 +501,10 @@ mod unit_tests { #[tokio::test] async fn test_resolve_resource_fails_if_invalid_resource_time() { // use epoch instead of XML DateTime - let url = "did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J?resourceName=asdf&resourceType=fdsa&resourceVersionTime=12341234".parse().unwrap(); + let url = "did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J?resourceName=asdf&resourceType=fdsa&\ + resourceVersionTime=12341234" + .parse() + .unwrap(); let resolver = DidCheqdResolver::new(Default::default()); let e = resolver.resolve_resource(&url).await.unwrap_err(); assert!(matches!(e, DidCheqdError::InvalidDidUrl(_))); From 269df996c58afc1a982e24759a02c86e811aadd5 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Mon, 9 Dec 2024 16:29:00 +1000 Subject: [PATCH 38/50] clippys and fmts Signed-off-by: George Mulhearn --- aries/aries_vcx_anoncreds/src/anoncreds/anoncreds/mod.rs | 4 +--- aries/aries_vcx_ledger/src/ledger/indy_vdr_ledger.rs | 4 ++-- aries/aries_vcx_ledger/src/ledger/multi_ledger.rs | 3 ++- did_core/did_methods/did_cheqd/src/resolution/resolver.rs | 4 ++-- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/aries/aries_vcx_anoncreds/src/anoncreds/anoncreds/mod.rs b/aries/aries_vcx_anoncreds/src/anoncreds/anoncreds/mod.rs index 3828e3cf74..41ad7fb9cf 100644 --- a/aries/aries_vcx_anoncreds/src/anoncreds/anoncreds/mod.rs +++ b/aries/aries_vcx_anoncreds/src/anoncreds/anoncreds/mod.rs @@ -266,9 +266,7 @@ impl BaseAnonCreds for Anoncreds { (Some(regs), Some(defs)) => Some( regs.into_iter() .filter_map(|(k, v)| { - let Some(def) = defs.get(&k) else { - return None; - }; + let def = defs.get(&k)?; Some((k, (v, def.issuer_id.clone()))) }) .collect(), diff --git a/aries/aries_vcx_ledger/src/ledger/indy_vdr_ledger.rs b/aries/aries_vcx_ledger/src/ledger/indy_vdr_ledger.rs index 270cfe2d8b..39ee62e1d4 100644 --- a/aries/aries_vcx_ledger/src/ledger/indy_vdr_ledger.rs +++ b/aries/aries_vcx_ledger/src/ledger/indy_vdr_ledger.rs @@ -585,7 +585,7 @@ where let status_list = from_revocation_registry_delta_to_revocation_status_list( &delta.value, entry_time, - &rev_reg_id, + rev_reg_id, rev_reg_def_meta.max_cred_num, rev_reg_def_meta.issuer_id.clone(), ) @@ -652,7 +652,7 @@ impl AnoncredsLedgerSupport for IndyVdrL } } -fn did_method_is_supported(id: &String) -> bool { +fn did_method_is_supported(id: &str) -> bool { let is_sov = id.starts_with("did:sov:"); let is_unqualified = !id.starts_with("did"); diff --git a/aries/aries_vcx_ledger/src/ledger/multi_ledger.rs b/aries/aries_vcx_ledger/src/ledger/multi_ledger.rs index 9fb3b318ac..5911b4c4fa 100644 --- a/aries/aries_vcx_ledger/src/ledger/multi_ledger.rs +++ b/aries/aries_vcx_ledger/src/ledger/multi_ledger.rs @@ -292,6 +292,7 @@ mod unit_tests { fn get_cred_def<'life0,'life1,'life2,'async_trait>(&'life0 self,cred_def_id: &'life1 CredentialDefinitionId,submitter_did:Option< &'life2 Did> ,) -> ::core::pin::Pin > + ::core::marker::Send+'async_trait> >where 'life0:'async_trait,'life1:'async_trait,'life2:'async_trait,Self:'async_trait; async fn get_rev_reg_def_json(&self, rev_reg_id: &RevocationRegistryDefinitionId) -> VcxLedgerResult<(RevocationRegistryDefinition, Value)>; async fn get_rev_reg_delta_json(&self, rev_reg_id: &RevocationRegistryDefinitionId, from: Option, to: Option) -> VcxLedgerResult<(RevocationRegistryDelta, u64)>; + #[allow(clippy::type_complexity)] // generated fn get_rev_status_list<'life0,'life1,'life2,'async_trait>(&'life0 self,rev_reg_id: &'life1 RevocationRegistryDefinitionId,timestamp:u64,rev_reg_def_meta:Option< &'life2 Value>) -> ::core::pin::Pin > + ::core::marker::Send+'async_trait> >where 'life0:'async_trait,'life1:'async_trait,'life2:'async_trait,Self:'async_trait; async fn get_rev_reg(&self, rev_reg_id: &RevocationRegistryDefinitionId, timestamp: u64) -> VcxLedgerResult<(RevocationRegistry, u64)>; } @@ -548,7 +549,7 @@ mod unit_tests { "revRegDefId": "4xE68b6S5VRFrKMMG1U95M:4:4xE68b6S5VRFrKMMG1U95M:3:CL:59232:default:CL_ACCUM:4ae1cc6c-f6bd-486c-8057-88f2ce74e960", "revocationList": [0, 1, 1, 0], "currentAccumulator": "21 124C594B6B20E41B681E92B2C43FD165EA9E68BC3C9D63A82C8893124983CAE94 21 124C5341937827427B0A3A32113BD5E64FB7AB39BD3E5ABDD7970874501CA4897 6 5438CB6F442E2F807812FD9DC0C39AFF4A86B1E6766DBB5359E86A4D70401B0F 4 39D1CA5C4716FFC4FE0853C4FF7F081DFD8DF8D2C2CA79705211680AC77BF3A1 6 70504A5493F89C97C225B68310811A41AD9CD889301F238E93C95AD085E84191 4 39582252194D756D5D86D0EED02BF1B95CE12AED2FA5CD3C53260747D891993C", - "timestamp": 1669640864 as u64 + "timestamp": 1669640864 })) .unwrap(); let output_timestamp = 876; diff --git a/did_core/did_methods/did_cheqd/src/resolution/resolver.rs b/did_core/did_methods/did_cheqd/src/resolution/resolver.rs index 0a67a2ad91..98cb8b5255 100644 --- a/did_core/did_methods/did_cheqd/src/resolution/resolver.rs +++ b/did_core/did_methods/did_cheqd/src/resolution/resolver.rs @@ -232,7 +232,7 @@ impl DidCheqdResolver { let (Some(resource_name), Some(resource_type)) = (resource_name, resource_type) else { return Err(DidCheqdError::InvalidDidUrl(format!( - "Resolver can only resolve by resource ID or name+type combination" + "Resolver can only resolve by exact resource ID or name+type combination {url}" )))?; }; // determine desired version_time, either from param, or *now* @@ -323,7 +323,7 @@ impl DidCheqdResolver { let resources = query_response.resources; let mut filtered: Vec<_> = filter_resources_by_name_and_type(resources.iter(), name, rtyp).collect(); - filtered.sort_by(|a, b| desc_chronological_sort_resources(*a, *b)); + filtered.sort_by(|a, b| desc_chronological_sort_resources(a, b)); let resource_meta = find_resource_just_before_time(filtered.into_iter(), time); From a12393652bbffbc95998fee676deb20de07ba4d0 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Tue, 10 Dec 2024 09:19:34 +1000 Subject: [PATCH 39/50] wrap sys tests in cheqd feature Signed-off-by: George Mulhearn --- aries/aries_vcx_ledger/tests/test_cheqd.rs | 439 +++++++++--------- .../tests/test_multi_ledger.rs | 78 ++-- 2 files changed, 265 insertions(+), 252 deletions(-) diff --git a/aries/aries_vcx_ledger/tests/test_cheqd.rs b/aries/aries_vcx_ledger/tests/test_cheqd.rs index 119f9b111e..65fa3561b2 100644 --- a/aries/aries_vcx_ledger/tests/test_cheqd.rs +++ b/aries/aries_vcx_ledger/tests/test_cheqd.rs @@ -1,218 +1,227 @@ -use std::sync::Arc; - -use anoncreds_types::data_types::identifiers::{ - cred_def_id::CredentialDefinitionId, rev_reg_def_id::RevocationRegistryDefinitionId, - schema_id::SchemaId, -}; -use aries_vcx_ledger::ledger::{base_ledger::AnoncredsLedgerRead, cheqd::CheqdAnoncredsLedgerRead}; -use chrono::{DateTime, Utc}; -use did_cheqd::resolution::resolver::DidCheqdResolver; -use serde_json::json; - -#[tokio::test] -async fn test_resolve_schema_vector() { - let id = "did:cheqd:testnet:d37eba59-513d-42d3-8f9f-d1df0548b675/resources/\ - a7e2fc0b-5f6c-466d-911f-3ed9909f98a0"; - - let reader = CheqdAnoncredsLedgerRead::new(Arc::new(DidCheqdResolver::new(Default::default()))); - let schema = reader - .get_schema(&SchemaId::new_unchecked(id), None) - .await - .unwrap(); - - assert_eq!( - schema.id.0, - "did:cheqd:testnet:d37eba59-513d-42d3-8f9f-d1df0548b675/resources/\ - a7e2fc0b-5f6c-466d-911f-3ed9909f98a0" - ); - assert!(schema.seq_no.is_none()); - assert_eq!( - schema.name, - "Faber College221a463c-9160-41bd-839c-26c0154e64b4" - ); - assert_eq!(schema.version, "1.0.0"); - assert_eq!( - schema.attr_names.0, - vec!["name".to_string(), "degree".to_string(), "date".to_string()] - ); - assert_eq!( - schema.issuer_id.0, - "did:cheqd:testnet:d37eba59-513d-42d3-8f9f-d1df0548b675" - ); -} - -#[tokio::test] -async fn test_resolve_cred_def_vector() { - let id = "did:cheqd:testnet:e5d13e49-9f5d-4ec1-b0f6-43e43e211fdc/resources/\ - 796f4d32-ceb2-4549-ac2f-5270442066ee"; - - let reader = CheqdAnoncredsLedgerRead::new(Arc::new(DidCheqdResolver::new(Default::default()))); - let cred_def = reader - .get_cred_def(&CredentialDefinitionId::new_unchecked(id), None) - .await - .unwrap(); - - let expected_cred_def = json!({ - "id": "did:cheqd:testnet:e5d13e49-9f5d-4ec1-b0f6-43e43e211fdc/resources/796f4d32-ceb2-4549-ac2f-5270442066ee", - "schemaId": "did:cheqd:testnet:e5d13e49-9f5d-4ec1-b0f6-43e43e211fdc/resources/441dd8ac-5132-4f64-a899-b95e6631861e", - "issuerId": "did:cheqd:testnet:e5d13e49-9f5d-4ec1-b0f6-43e43e211fdc", - "type": "CL", - "tag": "default", - "value": { - "primary": { - "n": "101775425686705322446321729042513323885366249575341827532852151406029439141945446540758073370857140650173543806620665009319990704696336867406228341102050525062347572470125847326218665243292282264450928863478570405137509031729993280909749863406879170040618211281523178059425360274769809374009133917080596452472404002929533556061638640203000980751755775872098282217341230637597866343991247907713086791452810236342936381540330526648988208357641862302546515645514361066795780511377402835905056549804798920667891392124801399775162573084938362756949887199195057995844386465801420665147294058855188546320799079663835174965161", - "s": "87624888798698822624423723118022809956578348937987561814948126500576219529138836392203224198856904274580002516694066594875873709134352028429835540535481267491635062762312964551217817275494607969045880749427396603031296648191143611156088073589185938269488488710758969627092198856856923016111781105026554515570693238770759473619839075955094865571664244739744514364819888950198503617844415579864953624998989292124086306326904837728507294638098267220789662137529137088453854836926570472177996704875536555330577801472880881494686752967061366433608898978631273502532992063649958617359359105975313298611541375812686478449038", - "r": { - "master_secret": "91924390643616684447850600547636799126754942750676961814085841416767517190041327602185387580658201961018441581408151006589910605450989653472590754296936606411587277500591300185962955561382125964973024308169242022915814560288197996510864084499323589139928149142636050230482921777834206450457769957179088070681863843269743734589083210580654397696548923614457471055030224454430850991434040684872112181784382757277123431379517419634053875223449800478697799219665093330299855414452721993787344846427989123844376930340324838760730841881922239261134345165306574342224223006710126470962389247658692615899692622733364593917564", - "dataload": "67714311012680607861506009159005649926100729749085079545683454286626632138688065577440485138428200490485338821059098371694307470028480026620243200576189622077496672555428629091259952610415973355058680447309063025743992477107070451623444621247413013233746035427316025697312475570466580668335703497887313077562889740624862997672438829468032595482449521331150586223865869041877654993640507137080181293240650234816519778512756819260970205819993241324592879273813227162717013131055606974830594578099412351827306325727807837670155477487273346541222802392212114521431844422126972523175992819888243089660896279345668836709183" - }, - "rctxt": "70939857802453506951149531957606930306640909143475371737027498474152925628494791068427574134203017421399121411176717498176846791145767680818780201808144435771494206471213311901071561885391866584823165735626586292923926605780832222900819531483444405585980754893162270863536237119860353096313485759974542267053904367917010014776300492094349532540865655521444795825149399229035168301897753439893554059797022750502266578483363311220307405821402958792359030164217593034199227560018630509640528678991350608730838863727066178052927862093157207477972326979317508513953451471067387162273207269626177777770178388199904693271885", - "z": "67232321822071084762251502223976923452971987672236221455852097322998038231254751227728590284858878856391984973291870462921522030038401971062122863827666305436738444365691249161806642192223615405177957760215302017704093487843885193856291620515859197624091514138527124658905269978674424356277491558952327833769860308310713639320922734643110516571614031976998124656051686500162012298658320291610287606636134513132238361082981123202624198501889516057149568201642936231925672511435865393828765935813568402464860650327397205857299165873490962876370815478186692229961439123671741775783729284710421491763990499547934996243081" - } - } - }); - assert_eq!(serde_json::to_value(cred_def).unwrap(), expected_cred_def); -} - -// https://testnet-explorer.cheqd.io/transactions/92C31ED20512FEE73EA4D8A6C8E63E652AA61A14D4F8C00203312EA185419CB9 -#[tokio::test] -async fn test_resolve_rev_reg_def_vector() { - let id = "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b/resources/\ - 4f265d83-4657-4c37-ba80-c66cc399457e"; - - let reader = CheqdAnoncredsLedgerRead::new(Arc::new(DidCheqdResolver::new(Default::default()))); - let (rev_reg_def, meta) = reader - .get_rev_reg_def_json(&RevocationRegistryDefinitionId::new_unchecked(id)) - .await - .unwrap(); - - let expected_rev_reg_def = json!({ - "id": id, - "issuerId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b", - "credDefId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b/resources/8372c1bc-907d-44a9-86be-ac3672b26e2e", - "revocDefType": "CL_ACCUM", - "tag": "1.0", - "value": { - "maxCredNum": 5, - "publicKeys": { - "accumKey": { - "z": "1 10D3560CAE0591EEA7D7A63E1A362FC31448EF321E04FD75F248BBAF02DE9749 1 118C4B0C7F3D86D46C22D62BAE7E613B137A879B50EFDFC56451AB9012BA57A0 1 23D6952F9D058744D4930D1DE6D79548BDCA3EE8BAAF64B712668E52A1290547 1 14C4C4389D92A99C4DA7E6CC2BD0C82E2809D3CD202CD2F0AD6C33D75AA39049 1 174EACBC7981492A791A72D57C6CB9FE488A679C4A5674E4F3C247D73A827384 1 0172B8961122D4D825B282CA1CD1BBC3B8DC459994C9FE2827CDF74B3AB08D38 1 181159044E453DC59FF320E9E08C666176F6B9309E162E2DA4FC1DB3156F7B1F 1 2323CEBFB26C6D28CBAF5F87F155362C6FA14AFA0EBA7DE2B4154FE4082E30FD 1 2354CB1624B42A284B41E5B3B4489C2795DBA9B88A725005555FB698AFF97260 1 07EEEF48EF52E5B15FD4AC28F0DAEDE0A259A27500855992307518A0DBE29A83 1 00FE73BCDB27D1DAD37E4F0E424372CA9548F11B4EC977DCCCC53D99A5C66F36 1 07E9DC0DD2163A66EDA84CD6BF282C7E18CB821762B6047CA1AB9FBE94DC6546" - } +#[cfg(feature = "cheqd")] +mod test_cheqd { + use std::sync::Arc; + + use anoncreds_types::data_types::identifiers::{ + cred_def_id::CredentialDefinitionId, rev_reg_def_id::RevocationRegistryDefinitionId, + schema_id::SchemaId, + }; + use aries_vcx_ledger::ledger::{ + base_ledger::AnoncredsLedgerRead, cheqd::CheqdAnoncredsLedgerRead, + }; + use chrono::{DateTime, Utc}; + use did_cheqd::resolution::resolver::DidCheqdResolver; + use serde_json::json; + + #[tokio::test] + async fn test_resolve_schema_vector() { + let id = "did:cheqd:testnet:d37eba59-513d-42d3-8f9f-d1df0548b675/resources/\ + a7e2fc0b-5f6c-466d-911f-3ed9909f98a0"; + + let reader = + CheqdAnoncredsLedgerRead::new(Arc::new(DidCheqdResolver::new(Default::default()))); + let schema = reader + .get_schema(&SchemaId::new_unchecked(id), None) + .await + .unwrap(); + + assert_eq!( + schema.id.0, + "did:cheqd:testnet:d37eba59-513d-42d3-8f9f-d1df0548b675/resources/\ + a7e2fc0b-5f6c-466d-911f-3ed9909f98a0" + ); + assert!(schema.seq_no.is_none()); + assert_eq!( + schema.name, + "Faber College221a463c-9160-41bd-839c-26c0154e64b4" + ); + assert_eq!(schema.version, "1.0.0"); + assert_eq!( + schema.attr_names.0, + vec!["name".to_string(), "degree".to_string(), "date".to_string()] + ); + assert_eq!( + schema.issuer_id.0, + "did:cheqd:testnet:d37eba59-513d-42d3-8f9f-d1df0548b675" + ); + } + + #[tokio::test] + async fn test_resolve_cred_def_vector() { + let id = "did:cheqd:testnet:e5d13e49-9f5d-4ec1-b0f6-43e43e211fdc/resources/\ + 796f4d32-ceb2-4549-ac2f-5270442066ee"; + + let reader = + CheqdAnoncredsLedgerRead::new(Arc::new(DidCheqdResolver::new(Default::default()))); + let cred_def = reader + .get_cred_def(&CredentialDefinitionId::new_unchecked(id), None) + .await + .unwrap(); + + let expected_cred_def = json!({ + "id": "did:cheqd:testnet:e5d13e49-9f5d-4ec1-b0f6-43e43e211fdc/resources/796f4d32-ceb2-4549-ac2f-5270442066ee", + "schemaId": "did:cheqd:testnet:e5d13e49-9f5d-4ec1-b0f6-43e43e211fdc/resources/441dd8ac-5132-4f64-a899-b95e6631861e", + "issuerId": "did:cheqd:testnet:e5d13e49-9f5d-4ec1-b0f6-43e43e211fdc", + "type": "CL", + "tag": "default", + "value": { + "primary": { + "n": "101775425686705322446321729042513323885366249575341827532852151406029439141945446540758073370857140650173543806620665009319990704696336867406228341102050525062347572470125847326218665243292282264450928863478570405137509031729993280909749863406879170040618211281523178059425360274769809374009133917080596452472404002929533556061638640203000980751755775872098282217341230637597866343991247907713086791452810236342936381540330526648988208357641862302546515645514361066795780511377402835905056549804798920667891392124801399775162573084938362756949887199195057995844386465801420665147294058855188546320799079663835174965161", + "s": "87624888798698822624423723118022809956578348937987561814948126500576219529138836392203224198856904274580002516694066594875873709134352028429835540535481267491635062762312964551217817275494607969045880749427396603031296648191143611156088073589185938269488488710758969627092198856856923016111781105026554515570693238770759473619839075955094865571664244739744514364819888950198503617844415579864953624998989292124086306326904837728507294638098267220789662137529137088453854836926570472177996704875536555330577801472880881494686752967061366433608898978631273502532992063649958617359359105975313298611541375812686478449038", + "r": { + "master_secret": "91924390643616684447850600547636799126754942750676961814085841416767517190041327602185387580658201961018441581408151006589910605450989653472590754296936606411587277500591300185962955561382125964973024308169242022915814560288197996510864084499323589139928149142636050230482921777834206450457769957179088070681863843269743734589083210580654397696548923614457471055030224454430850991434040684872112181784382757277123431379517419634053875223449800478697799219665093330299855414452721993787344846427989123844376930340324838760730841881922239261134345165306574342224223006710126470962389247658692615899692622733364593917564", + "dataload": "67714311012680607861506009159005649926100729749085079545683454286626632138688065577440485138428200490485338821059098371694307470028480026620243200576189622077496672555428629091259952610415973355058680447309063025743992477107070451623444621247413013233746035427316025697312475570466580668335703497887313077562889740624862997672438829468032595482449521331150586223865869041877654993640507137080181293240650234816519778512756819260970205819993241324592879273813227162717013131055606974830594578099412351827306325727807837670155477487273346541222802392212114521431844422126972523175992819888243089660896279345668836709183" }, - "tailsHash": "GW1bmjcMmtHnLwbWrabX4sWYVopJMEvQWgYMAEDmbJS3", - "tailsLocation": "GW1bmjcMmtHnLwbWrabX4sWYVopJMEvQWgYMAEDmbJS3" - } - }); - assert_eq!( - serde_json::to_value(rev_reg_def).unwrap(), - expected_rev_reg_def - ); - - assert_eq!( - meta.resource_name, - "275990cc056b46176a7122cfd888f46a2bd8e3d45a71d5ff20764a874ed02edd" - ); -} - -// test status list resolution from credo-ts uploaded vectors -// https://resolver.cheqd.net/1.0/identifiers/did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b?resourceName=275990cc056b46176a7122cfd888f46a2bd8e3d45a71d5ff20764a874ed02edd&resourceType=anonCredsStatusList&resourceMetadata=true -// reset: https://testnet-explorer.cheqd.io/transactions/356F65125E585B9F439C423F2AD7DE73ADF4DC9A0811AA8EE5D03D63B1872DC0 -// 2024-12-04T22:14:55Z -// update 1: https://testnet-explorer.cheqd.io/transactions/ADF7D562A5005576FA6EF8DC864DAA306EB62C40911FEB5B30C8F98968AE7B51 -// 2024-12-04T22:15:07Z -// update 2: https://testnet-explorer.cheqd.io/transactions/222FF2D023C2C9A097BB38F3875F072DF8DEC7B0CBD46AC3459C9B4C3C74382F -// 2024-12-04T22:15:18Z -// update 3: https://testnet-explorer.cheqd.io/transactions/791D57B8C49C270B3EDA0E9E7E00811CA828190C2D6517FDE8E40CD8FE445E1C -// 2024-12-04T22:15:30Z -#[tokio::test] -async fn test_resolve_rev_status_list_versions() { - let def_id = "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b/resources/\ + "rctxt": "70939857802453506951149531957606930306640909143475371737027498474152925628494791068427574134203017421399121411176717498176846791145767680818780201808144435771494206471213311901071561885391866584823165735626586292923926605780832222900819531483444405585980754893162270863536237119860353096313485759974542267053904367917010014776300492094349532540865655521444795825149399229035168301897753439893554059797022750502266578483363311220307405821402958792359030164217593034199227560018630509640528678991350608730838863727066178052927862093157207477972326979317508513953451471067387162273207269626177777770178388199904693271885", + "z": "67232321822071084762251502223976923452971987672236221455852097322998038231254751227728590284858878856391984973291870462921522030038401971062122863827666305436738444365691249161806642192223615405177957760215302017704093487843885193856291620515859197624091514138527124658905269978674424356277491558952327833769860308310713639320922734643110516571614031976998124656051686500162012298658320291610287606636134513132238361082981123202624198501889516057149568201642936231925672511435865393828765935813568402464860650327397205857299165873490962876370815478186692229961439123671741775783729284710421491763990499547934996243081" + } + } + }); + assert_eq!(serde_json::to_value(cred_def).unwrap(), expected_cred_def); + } + + // https://testnet-explorer.cheqd.io/transactions/92C31ED20512FEE73EA4D8A6C8E63E652AA61A14D4F8C00203312EA185419CB9 + #[tokio::test] + async fn test_resolve_rev_reg_def_vector() { + let id = "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b/resources/\ 4f265d83-4657-4c37-ba80-c66cc399457e"; - let def_id = RevocationRegistryDefinitionId::new_unchecked(def_id); - - let init_time = DateTime::parse_from_rfc3339("2024-12-04T22:14:55Z") - .unwrap() - .timestamp() as u64; - let update1_time = DateTime::parse_from_rfc3339("2024-12-04T22:15:07Z") - .unwrap() - .timestamp() as u64; - let update2_time = DateTime::parse_from_rfc3339("2024-12-04T22:15:18Z") - .unwrap() - .timestamp() as u64; - let update3_time = DateTime::parse_from_rfc3339("2024-12-04T22:15:30Z") - .unwrap() - .timestamp() as u64; - - let reader = CheqdAnoncredsLedgerRead::new(Arc::new(DidCheqdResolver::new(Default::default()))); - - let def_meta = reader.get_rev_reg_def_json(&def_id).await.unwrap().1; - - // scenario 1: get most recent - let now = Utc::now().timestamp() as u64; - let (status_list, update_time) = reader - .get_rev_status_list(&def_id, now, Some(&def_meta)) - .await - .unwrap(); - assert_eq!(update_time, update3_time); - assert_eq!( - serde_json::to_value(status_list).unwrap(), - json!({ - "issuerId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b", - "revRegDefId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b/resources/4f265d83-4657-4c37-ba80-c66cc399457e", - "revocationList": [1,1,1,1,0], - "currentAccumulator": "21 114BE4F2BBAAF18F07E994D74B28347FA0BEC500A616B47F57F2E0B0864F7602E 21 12AB68E307C5F2AA30F34A03ADB298C7F4C02555649E510919979C2AEB49CCDF1 6 5FB9FB957339A842130C84FC98240A163E56DC58B96423F1EFD53E9106671B94 4 28F2F8297E345FFF55CDEE87C83DE471486826C91EBBA2C39570A46013B5BFBA 6 565A830A4358E1F6F21A10804C23E36D739B5630C6A188D760F4B6F434D1311D 4 14F87165B42A780974AC70669DC3CF629F1103DF73AE15AC11A1151883A91941", - "timestamp": update3_time - }) - ); - - // scenario 2: between update 2 & 3 - let (status_list, update_time) = reader - .get_rev_status_list(&def_id, update2_time + 3, Some(&def_meta)) - .await - .unwrap(); - assert_eq!(update_time, update2_time); - assert_eq!( - serde_json::to_value(status_list).unwrap(), - json!({ - "issuerId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b", - "currentAccumulator": "21 125DF938B3B772619CB43E561D69004CF09667376E9CD53C818D84860BAE3D1D9 21 11ECFC5F9B469AC74E2A0E329F86C6E60B423A53CAC5AE7A4DBE7A978BFFC0DA1 6 6FAD628FED470FF640BF2C5DB57C2C18D009645DBEF15D4AF710739D2AD93E2D 4 22093A3300411B059B8BB7A8C3296A2ED9C4C8E00106C3B2BAD76E25AC792063 6 71D70ECA81BCE610D1C22CADE688AF4A122C8258E8B306635A111D0A35A7238A 4 1E80F38ABA3A966B8657D722D4E956F076BB2F5CCF36AA8942E65500F8898FF3", - "revRegDefId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b/resources/4f265d83-4657-4c37-ba80-c66cc399457e", - "revocationList": [1,1,1,0,0], - "timestamp": update2_time - }) - ); - - // scenario 3: between update 1 & 2 - let (status_list, update_time) = reader - .get_rev_status_list(&def_id, update1_time + 3, Some(&def_meta)) - .await - .unwrap(); - assert_eq!(update_time, update1_time); - assert_eq!( - serde_json::to_value(status_list).unwrap(), - json!({ - "issuerId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b", - "currentAccumulator": "21 136FA865B5CD0AEA1DA05BE412C6E06C23066C338D39C5B79C5E1AE1D5BA20AAA 21 124182E098BE418B9DBECF600EEA3D070EDB85D6B412EE75B4B43C440FEA2E631 6 669D66FB3BC245B4EF892B8DB5A330ACA6A4CE6706FB58D9B487C0487DBB5C04 4 2C5C9551DFE2A4AE71D355DD3A981F155F51B9BCF8E2ED8B8263726DDF60D09C 6 7243CF31A80313C254F51D2B0A3573320B885178F36F4AE1E8FF4A520EF9CDCA 4 1B8DBE9563FAD9FBF8B75BCE41C9425E1D15EE0B3D195D0A86AD8A2C91D5BB73", - "revRegDefId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b/resources/4f265d83-4657-4c37-ba80-c66cc399457e", - "revocationList": [1,1,0,0,0], - "timestamp": update1_time - }) - ); - - // scenario 4: between init & update 1 - let (status_list, update_time) = reader - .get_rev_status_list(&def_id, init_time + 3, Some(&def_meta)) - .await - .unwrap(); - assert_eq!(update_time, init_time); - assert_eq!( - serde_json::to_value(status_list).unwrap(), - json!({ - "issuerId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b", - "currentAccumulator": "1 0443A0BC791EE82B8F34066404B36E81E0CE68B64BD2A48A55587E4585B16CCA 1 0343A5D644B28DCC0EAF9C6D3E104DC0F61FCD711AFE93DB67031905DAA5F654 1 02CE577295DF112BB2C7F16250D4593FC922B074436EC0F4F124E2409EF99785 1 1692EE5DFE9885809DA503A2EEDC4EECDA5D7D415C743E3931576EFD72FB51AC 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8 1 0000000000000000000000000000000000000000000000000000000000000000", - "revRegDefId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b/resources/4f265d83-4657-4c37-ba80-c66cc399457e", - "revocationList": [0,0,0,0,0], - "timestamp": init_time - }) - ); + + let reader = + CheqdAnoncredsLedgerRead::new(Arc::new(DidCheqdResolver::new(Default::default()))); + let (rev_reg_def, meta) = reader + .get_rev_reg_def_json(&RevocationRegistryDefinitionId::new_unchecked(id)) + .await + .unwrap(); + + let expected_rev_reg_def = json!({ + "id": id, + "issuerId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b", + "credDefId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b/resources/8372c1bc-907d-44a9-86be-ac3672b26e2e", + "revocDefType": "CL_ACCUM", + "tag": "1.0", + "value": { + "maxCredNum": 5, + "publicKeys": { + "accumKey": { + "z": "1 10D3560CAE0591EEA7D7A63E1A362FC31448EF321E04FD75F248BBAF02DE9749 1 118C4B0C7F3D86D46C22D62BAE7E613B137A879B50EFDFC56451AB9012BA57A0 1 23D6952F9D058744D4930D1DE6D79548BDCA3EE8BAAF64B712668E52A1290547 1 14C4C4389D92A99C4DA7E6CC2BD0C82E2809D3CD202CD2F0AD6C33D75AA39049 1 174EACBC7981492A791A72D57C6CB9FE488A679C4A5674E4F3C247D73A827384 1 0172B8961122D4D825B282CA1CD1BBC3B8DC459994C9FE2827CDF74B3AB08D38 1 181159044E453DC59FF320E9E08C666176F6B9309E162E2DA4FC1DB3156F7B1F 1 2323CEBFB26C6D28CBAF5F87F155362C6FA14AFA0EBA7DE2B4154FE4082E30FD 1 2354CB1624B42A284B41E5B3B4489C2795DBA9B88A725005555FB698AFF97260 1 07EEEF48EF52E5B15FD4AC28F0DAEDE0A259A27500855992307518A0DBE29A83 1 00FE73BCDB27D1DAD37E4F0E424372CA9548F11B4EC977DCCCC53D99A5C66F36 1 07E9DC0DD2163A66EDA84CD6BF282C7E18CB821762B6047CA1AB9FBE94DC6546" + } + }, + "tailsHash": "GW1bmjcMmtHnLwbWrabX4sWYVopJMEvQWgYMAEDmbJS3", + "tailsLocation": "GW1bmjcMmtHnLwbWrabX4sWYVopJMEvQWgYMAEDmbJS3" + } + }); + assert_eq!( + serde_json::to_value(rev_reg_def).unwrap(), + expected_rev_reg_def + ); + + assert_eq!( + meta.resource_name, + "275990cc056b46176a7122cfd888f46a2bd8e3d45a71d5ff20764a874ed02edd" + ); + } + + // test status list resolution from credo-ts uploaded vectors + // https://resolver.cheqd.net/1.0/identifiers/did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b?resourceName=275990cc056b46176a7122cfd888f46a2bd8e3d45a71d5ff20764a874ed02edd&resourceType=anonCredsStatusList&resourceMetadata=true + // reset: https://testnet-explorer.cheqd.io/transactions/356F65125E585B9F439C423F2AD7DE73ADF4DC9A0811AA8EE5D03D63B1872DC0 + // 2024-12-04T22:14:55Z + // update 1: https://testnet-explorer.cheqd.io/transactions/ADF7D562A5005576FA6EF8DC864DAA306EB62C40911FEB5B30C8F98968AE7B51 + // 2024-12-04T22:15:07Z + // update 2: https://testnet-explorer.cheqd.io/transactions/222FF2D023C2C9A097BB38F3875F072DF8DEC7B0CBD46AC3459C9B4C3C74382F + // 2024-12-04T22:15:18Z + // update 3: https://testnet-explorer.cheqd.io/transactions/791D57B8C49C270B3EDA0E9E7E00811CA828190C2D6517FDE8E40CD8FE445E1C + // 2024-12-04T22:15:30Z + #[tokio::test] + async fn test_resolve_rev_status_list_versions() { + let def_id = "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b/resources/\ + 4f265d83-4657-4c37-ba80-c66cc399457e"; + let def_id = RevocationRegistryDefinitionId::new_unchecked(def_id); + + let init_time = DateTime::parse_from_rfc3339("2024-12-04T22:14:55Z") + .unwrap() + .timestamp() as u64; + let update1_time = DateTime::parse_from_rfc3339("2024-12-04T22:15:07Z") + .unwrap() + .timestamp() as u64; + let update2_time = DateTime::parse_from_rfc3339("2024-12-04T22:15:18Z") + .unwrap() + .timestamp() as u64; + let update3_time = DateTime::parse_from_rfc3339("2024-12-04T22:15:30Z") + .unwrap() + .timestamp() as u64; + + let reader = + CheqdAnoncredsLedgerRead::new(Arc::new(DidCheqdResolver::new(Default::default()))); + + let def_meta = reader.get_rev_reg_def_json(&def_id).await.unwrap().1; + + // scenario 1: get most recent + let now = Utc::now().timestamp() as u64; + let (status_list, update_time) = reader + .get_rev_status_list(&def_id, now, Some(&def_meta)) + .await + .unwrap(); + assert_eq!(update_time, update3_time); + assert_eq!( + serde_json::to_value(status_list).unwrap(), + json!({ + "issuerId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b", + "revRegDefId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b/resources/4f265d83-4657-4c37-ba80-c66cc399457e", + "revocationList": [1,1,1,1,0], + "currentAccumulator": "21 114BE4F2BBAAF18F07E994D74B28347FA0BEC500A616B47F57F2E0B0864F7602E 21 12AB68E307C5F2AA30F34A03ADB298C7F4C02555649E510919979C2AEB49CCDF1 6 5FB9FB957339A842130C84FC98240A163E56DC58B96423F1EFD53E9106671B94 4 28F2F8297E345FFF55CDEE87C83DE471486826C91EBBA2C39570A46013B5BFBA 6 565A830A4358E1F6F21A10804C23E36D739B5630C6A188D760F4B6F434D1311D 4 14F87165B42A780974AC70669DC3CF629F1103DF73AE15AC11A1151883A91941", + "timestamp": update3_time + }) + ); + + // scenario 2: between update 2 & 3 + let (status_list, update_time) = reader + .get_rev_status_list(&def_id, update2_time + 3, Some(&def_meta)) + .await + .unwrap(); + assert_eq!(update_time, update2_time); + assert_eq!( + serde_json::to_value(status_list).unwrap(), + json!({ + "issuerId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b", + "currentAccumulator": "21 125DF938B3B772619CB43E561D69004CF09667376E9CD53C818D84860BAE3D1D9 21 11ECFC5F9B469AC74E2A0E329F86C6E60B423A53CAC5AE7A4DBE7A978BFFC0DA1 6 6FAD628FED470FF640BF2C5DB57C2C18D009645DBEF15D4AF710739D2AD93E2D 4 22093A3300411B059B8BB7A8C3296A2ED9C4C8E00106C3B2BAD76E25AC792063 6 71D70ECA81BCE610D1C22CADE688AF4A122C8258E8B306635A111D0A35A7238A 4 1E80F38ABA3A966B8657D722D4E956F076BB2F5CCF36AA8942E65500F8898FF3", + "revRegDefId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b/resources/4f265d83-4657-4c37-ba80-c66cc399457e", + "revocationList": [1,1,1,0,0], + "timestamp": update2_time + }) + ); + + // scenario 3: between update 1 & 2 + let (status_list, update_time) = reader + .get_rev_status_list(&def_id, update1_time + 3, Some(&def_meta)) + .await + .unwrap(); + assert_eq!(update_time, update1_time); + assert_eq!( + serde_json::to_value(status_list).unwrap(), + json!({ + "issuerId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b", + "currentAccumulator": "21 136FA865B5CD0AEA1DA05BE412C6E06C23066C338D39C5B79C5E1AE1D5BA20AAA 21 124182E098BE418B9DBECF600EEA3D070EDB85D6B412EE75B4B43C440FEA2E631 6 669D66FB3BC245B4EF892B8DB5A330ACA6A4CE6706FB58D9B487C0487DBB5C04 4 2C5C9551DFE2A4AE71D355DD3A981F155F51B9BCF8E2ED8B8263726DDF60D09C 6 7243CF31A80313C254F51D2B0A3573320B885178F36F4AE1E8FF4A520EF9CDCA 4 1B8DBE9563FAD9FBF8B75BCE41C9425E1D15EE0B3D195D0A86AD8A2C91D5BB73", + "revRegDefId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b/resources/4f265d83-4657-4c37-ba80-c66cc399457e", + "revocationList": [1,1,0,0,0], + "timestamp": update1_time + }) + ); + + // scenario 4: between init & update 1 + let (status_list, update_time) = reader + .get_rev_status_list(&def_id, init_time + 3, Some(&def_meta)) + .await + .unwrap(); + assert_eq!(update_time, init_time); + assert_eq!( + serde_json::to_value(status_list).unwrap(), + json!({ + "issuerId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b", + "currentAccumulator": "1 0443A0BC791EE82B8F34066404B36E81E0CE68B64BD2A48A55587E4585B16CCA 1 0343A5D644B28DCC0EAF9C6D3E104DC0F61FCD711AFE93DB67031905DAA5F654 1 02CE577295DF112BB2C7F16250D4593FC922B074436EC0F4F124E2409EF99785 1 1692EE5DFE9885809DA503A2EEDC4EECDA5D7D415C743E3931576EFD72FB51AC 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8 1 0000000000000000000000000000000000000000000000000000000000000000", + "revRegDefId": "did:cheqd:testnet:8bbd2026-03f5-42c7-bf80-09f46fc4d67b/resources/4f265d83-4657-4c37-ba80-c66cc399457e", + "revocationList": [0,0,0,0,0], + "timestamp": init_time + }) + ); + } } diff --git a/aries/aries_vcx_ledger/tests/test_multi_ledger.rs b/aries/aries_vcx_ledger/tests/test_multi_ledger.rs index 69c8279027..85c86decf4 100644 --- a/aries/aries_vcx_ledger/tests/test_multi_ledger.rs +++ b/aries/aries_vcx_ledger/tests/test_multi_ledger.rs @@ -1,44 +1,48 @@ -use std::sync::Arc; +#[cfg(feature = "cheqd")] +mod test_cheqd { + use std::sync::Arc; -use aries_vcx_ledger::{ - errors::error::VcxLedgerResult, - ledger::{ - cheqd::CheqdAnoncredsLedgerRead, - indy_vdr_ledger::{IndyVdrLedgerRead, IndyVdrLedgerReadConfig}, - multi_ledger::MultiLedgerAnoncredsRead, - request_submitter::RequestSubmitter, - response_cacher::noop::NoopResponseCacher, - }, -}; -use async_trait::async_trait; -use did_cheqd::resolution::resolver::DidCheqdResolver; -use indy_vdr::pool::ProtocolVersion; -use mockall::mock; + use aries_vcx_ledger::{ + errors::error::VcxLedgerResult, + ledger::{ + cheqd::CheqdAnoncredsLedgerRead, + indy_vdr_ledger::{IndyVdrLedgerRead, IndyVdrLedgerReadConfig}, + multi_ledger::MultiLedgerAnoncredsRead, + request_submitter::RequestSubmitter, + response_cacher::noop::NoopResponseCacher, + }, + }; + use async_trait::async_trait; + use did_cheqd::resolution::resolver::DidCheqdResolver; + use indy_vdr::pool::ProtocolVersion; + use mockall::mock; -mock! { - pub RequestSubmitter {} - #[async_trait] - impl RequestSubmitter for RequestSubmitter { - async fn submit(&self, request: indy_vdr::pool::PreparedRequest) -> VcxLedgerResult; + mock! { + pub RequestSubmitter {} + #[async_trait] + impl RequestSubmitter for RequestSubmitter { + async fn submit(&self, request: indy_vdr::pool::PreparedRequest) -> VcxLedgerResult; + } } -} -fn dummy_indy_vdr_reader() -> IndyVdrLedgerRead { - IndyVdrLedgerRead::new(IndyVdrLedgerReadConfig { - request_submitter: MockRequestSubmitter::new(), - response_parser: indy_ledger_response_parser::ResponseParser, - response_cacher: NoopResponseCacher, - protocol_version: ProtocolVersion::Node1_4, - }) -} + fn dummy_indy_vdr_reader() -> IndyVdrLedgerRead { + IndyVdrLedgerRead::new(IndyVdrLedgerReadConfig { + request_submitter: MockRequestSubmitter::new(), + response_parser: indy_ledger_response_parser::ResponseParser, + response_cacher: NoopResponseCacher, + protocol_version: ProtocolVersion::Node1_4, + }) + } -// asserts the successful construction using our defined anoncreds ledger readers. -#[test] -fn test_construction() { - let cheqd = CheqdAnoncredsLedgerRead::new(Arc::new(DidCheqdResolver::new(Default::default()))); - let indy = dummy_indy_vdr_reader(); + // asserts the successful construction using our defined anoncreds ledger readers. + #[test] + fn test_construction() { + let cheqd = + CheqdAnoncredsLedgerRead::new(Arc::new(DidCheqdResolver::new(Default::default()))); + let indy = dummy_indy_vdr_reader(); - let _multi_ledger = MultiLedgerAnoncredsRead::new() - .register_reader(cheqd) - .register_reader(indy); + let _multi_ledger = MultiLedgerAnoncredsRead::new() + .register_reader(cheqd) + .register_reader(indy); + } } From 3e4f1a2592bb0f3d5dffc80020563afa6661c211 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Tue, 10 Dec 2024 15:51:38 +1000 Subject: [PATCH 40/50] refine did-url handling (percent encoding queries) Signed-off-by: George Mulhearn --- Cargo.lock | 2 + aries/aries_vcx_ledger/Cargo.toml | 4 +- .../aries_vcx_ledger/src/ledger/cheqd/mod.rs | 16 ++++--- did_core/did_parser_nom/Cargo.toml | 1 + did_core/did_parser_nom/src/did_url/mod.rs | 12 +++++- .../did_parser_nom/src/did_url/parsing.rs | 43 +++++++++++++------ .../did_parser_nom/tests/did_url/negative.rs | 4 ++ .../did_parser_nom/tests/did_url/positive.rs | 30 +++++++++++++ 8 files changed, 89 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fd4a5a83c2..ed0a9ef616 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -620,6 +620,7 @@ dependencies = [ "thiserror", "time", "tokio", + "url", "uuid", ] @@ -1805,6 +1806,7 @@ dependencies = [ "env_logger 0.11.5", "log", "nom", + "percent-encoding", "serde", "serde_test", ] diff --git a/aries/aries_vcx_ledger/Cargo.toml b/aries/aries_vcx_ledger/Cargo.toml index 8466743fcb..8ddca850b0 100644 --- a/aries/aries_vcx_ledger/Cargo.toml +++ b/aries/aries_vcx_ledger/Cargo.toml @@ -9,7 +9,7 @@ edition.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] vdr_proxy_ledger = ["dep:indy-vdr-proxy-client"] -cheqd = ["dep:did_cheqd", "dep:did_resolver"] +cheqd = ["dep:did_cheqd", "dep:did_resolver", "dep:url"] [dependencies] aries_vcx_wallet = { path = "../aries_vcx_wallet" } @@ -20,6 +20,7 @@ indy-vdr.workspace = true indy-vdr-proxy-client = { workspace = true, optional = true } did_cheqd = { path = "../../did_core/did_methods/did_cheqd", optional = true } did_resolver = { path = "../../did_core/did_resolver", optional = true } +url = { version = "2.4.1", optional = true } serde_json = "1.0.95" public_key = { path = "../../did_core/public_key" } async-trait = "0.1.68" @@ -40,4 +41,3 @@ tokio = { version = "1.38.0", default-features = false, features = [ chrono = { version = "0.4", default-features = true } mockall = "0.13.1" uuid = { version = "1.4.1", default-features = false, features = ["v4"] } - diff --git a/aries/aries_vcx_ledger/src/ledger/cheqd/mod.rs b/aries/aries_vcx_ledger/src/ledger/cheqd/mod.rs index d2cfb6fded..f7480d80f6 100644 --- a/aries/aries_vcx_ledger/src/ledger/cheqd/mod.rs +++ b/aries/aries_vcx_ledger/src/ledger/cheqd/mod.rs @@ -24,6 +24,7 @@ use models::{ CheqdAnoncredsRevocationStatusList, CheqdAnoncredsSchema, }; use serde::{Deserialize, Serialize}; +use url::Url; use super::base_ledger::{AnoncredsLedgerRead, AnoncredsLedgerSupport}; use crate::errors::error::{VcxLedgerError, VcxLedgerResult}; @@ -185,12 +186,17 @@ impl AnoncredsLedgerRead for CheqdAnoncredsLedgerRead { DateTime::from_timestamp(timestamp as i64, 0).ok_or(VcxLedgerError::InvalidInput( format!("input status list timestamp is not valid {timestamp}"), ))?; + + // assemble query let xml_dt = resource_dt.to_rfc3339_opts(chrono::SecondsFormat::Millis, true); - let query = format!( - "{did}?resourceType={STATUS_LIST_RESOURCE_TYPE}&resourceName={name}&\ - resourceVersionTime={xml_dt}" - ); - let query_url = DidUrl::parse(query)?; + let mut query = Url::parse(did) + .map_err(|e| VcxLedgerError::InvalidInput(format!("cannot parse DID as URL: {e}")))?; + query + .query_pairs_mut() + .append_pair("resourceType", STATUS_LIST_RESOURCE_TYPE) + .append_pair("resourceName", name) + .append_pair("resourceVersionTime", &xml_dt); + let query_url = DidUrl::parse(query.to_string())?; let resource = self.resolver.resolve_resource(&query_url).await?; self.check_resource_type(&resource, STATUS_LIST_RESOURCE_TYPE)?; diff --git a/did_core/did_parser_nom/Cargo.toml b/did_core/did_parser_nom/Cargo.toml index 8b8908db41..dfc4f9eb7e 100644 --- a/did_core/did_parser_nom/Cargo.toml +++ b/did_core/did_parser_nom/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" nom = "7.1.3" serde = "1.0.160" log = "0.4.16" +percent-encoding = "2" [dev-dependencies] serde_test = "1.0.176" diff --git a/did_core/did_parser_nom/src/did_url/mod.rs b/did_core/did_parser_nom/src/did_url/mod.rs index 763f9a34f2..0f733ad6b2 100644 --- a/did_core/did_parser_nom/src/did_url/mod.rs +++ b/did_core/did_parser_nom/src/did_url/mod.rs @@ -59,8 +59,8 @@ impl DidUrl { .iter() .map(|(k, v)| { ( - self.did_url[k.clone()].to_string(), - self.did_url[v.clone()].to_string(), + query_percent_decode(&self.did_url[k.clone()]), + query_percent_decode(&self.did_url[v.clone()]), ) }) .collect() @@ -109,6 +109,14 @@ impl DidUrl { } } +/// Decode percent-encoded URL query item (application/x-www-form-urlencoded encoded). +/// Primary difference from general percent encoding is encoding of ' ' as '+' +fn query_percent_decode(input: &str) -> String { + percent_encoding::percent_decode_str(&input.replace('+', " ")) + .decode_utf8_lossy() + .into_owned() +} + impl TryFrom for DidUrl { type Error = ParseError; diff --git a/did_core/did_parser_nom/src/did_url/parsing.rs b/did_core/did_parser_nom/src/did_url/parsing.rs index cfede9c507..58a25fc648 100644 --- a/did_core/did_parser_nom/src/did_url/parsing.rs +++ b/did_core/did_parser_nom/src/did_url/parsing.rs @@ -3,11 +3,11 @@ use std::collections::HashMap; use nom::{ branch::alt, bytes::complete::{tag, take_while1}, - character::complete::{char, one_of}, + character::complete::{char, one_of, satisfy}, combinator::{all_consuming, cut, opt, recognize, success}, - multi::{many0, separated_list0}, - sequence::{preceded, separated_pair}, - IResult, + multi::{many0, many1, separated_list0}, + sequence::{preceded, separated_pair, tuple}, + AsChar, IResult, }; type UrlPart<'a> = (&'a str, Option>, Option<&'a str>); @@ -27,14 +27,29 @@ fn is_sub_delims(c: char) -> bool { "!$&'()*+,;=".contains(c) } +// pct-encoded = "%" HEXDIG HEXDIG +fn pct_encoded(input: &str) -> IResult<&str, &str> { + recognize(tuple(( + tag("%"), + satisfy(|c| c.is_hex_digit()), + satisfy(|c| c.is_hex_digit()), + )))(input) +} + // pchar = unreserved / pct-encoded / sub-delims / ":" / "@" -fn is_pchar(c: char) -> bool { - is_unreserved(c) || is_sub_delims(c) || ":@".contains(c) +fn pchar(input: &str) -> IResult<&str, &str> { + alt(( + recognize(satisfy(is_unreserved)), + pct_encoded, + recognize(satisfy(is_sub_delims)), + tag(":"), + tag("@"), + ))(input) } // segment = *pchar fn segment(input: &str) -> IResult<&str, &str> { - take_while1(is_pchar)(input) + recognize(many1(pchar))(input) } // path-abempty = *( "/" segment ) @@ -44,17 +59,17 @@ fn path_abempty(input: &str) -> IResult<&str, &str> { // fragment = *( pchar / "/" / "?" ) pub(super) fn fragment_parser(input: &str) -> IResult<&str, &str> { - fn is_fragment_char(c: char) -> bool { - is_pchar(c) || "/?".contains(c) + fn fragment_element(input: &str) -> IResult<&str, &str> { + alt(((pchar), tag("/"), tag("?")))(input) } - take_while1(is_fragment_char)(input) + recognize(many1(fragment_element))(input) } // query = *( pchar / "/" / "?" ) fn query_key_value_pair(input: &str) -> IResult<&str, (&str, &str)> { - fn is_query_char(c: char) -> bool { - is_pchar(c) || "/?".contains(c) + fn query_element(input: &str) -> IResult<&str, &str> { + alt(((pchar), tag("/"), tag("?")))(input) } let (remaining, (key, value)) = cut(separated_pair( @@ -63,9 +78,9 @@ fn query_key_value_pair(input: &str) -> IResult<&str, (&str, &str)> { alt((take_while1(|c| !"&#?".contains(c)), success(""))), ))(input)?; - cut(all_consuming(take_while1(is_query_char)))(key)?; + cut(all_consuming(many1(query_element)))(key)?; if !value.is_empty() { - cut(all_consuming(take_while1(is_query_char)))(value)?; + cut(all_consuming(many1(query_element)))(value)?; } Ok((remaining, (key, value))) diff --git a/did_core/did_parser_nom/tests/did_url/negative.rs b/did_core/did_parser_nom/tests/did_url/negative.rs index d2e55533c9..d1123a4b74 100644 --- a/did_core/did_parser_nom/tests/did_url/negative.rs +++ b/did_core/did_parser_nom/tests/did_url/negative.rs @@ -32,6 +32,10 @@ test_cases_negative! { "did:example:123456789abcdefghi&query1=value1" query_invalid_char: "did:example:123456789abcdefghi?query1=v^lue1" + query_unfinished_pct_encoding: + "did:example:123456789?query=a%3&query2=b" + query_invalid_space_char: + "did:example:123456789?query=a b" relative_empty_path: "/" relative_empty_path_and_query: "/?" relative_empty_path_and_fragment: "/#" diff --git a/did_core/did_parser_nom/tests/did_url/positive.rs b/did_core/did_parser_nom/tests/did_url/positive.rs index ced17a3b35..9213bc1fdd 100644 --- a/did_core/did_parser_nom/tests/did_url/positive.rs +++ b/did_core/did_parser_nom/tests/did_url/positive.rs @@ -384,4 +384,34 @@ test_cases_positive! { ("resourceType".to_string(), "anonCredsCredDef".to_string()), ].into_iter().collect() } + test_case30: + "did:cheqd:testnet:36e695a3-f133-46ec-ac1e-79900a927f67?resourceType=anonCredsStatusList&resourceName=Example+schema-default-0&resourceVersionTime=2024-12-10T04%3A13%3A50.000Z", + Some("did:cheqd:testnet:36e695a3-f133-46ec-ac1e-79900a927f67"), + Some("cheqd"), + Some("testnet"), + Some("36e695a3-f133-46ec-ac1e-79900a927f67"), + None, + None, + { + vec![ + ("resourceName".to_string(), "Example schema-default-0".to_string()), + ("resourceType".to_string(), "anonCredsStatusList".to_string()), + ("resourceVersionTime".to_string(), "2024-12-10T04:13:50.000Z".to_string()), + ].into_iter().collect() + } + test_case31: + "did:example:123?foo+bar=123&bar%20foo=123%20123&h3%21%210%20=w%40rld%3D%3D", + Some("did:example:123"), + Some("example"), + None, + Some("123"), + None, + None, + { + vec![ + ("foo bar".to_string(), "123".to_string()), + ("bar foo".to_string(), "123 123".to_string()), + ("h3!!0 ".to_string(), "w@rld==".to_string()) + ].into_iter().collect() + } } From e48f23b4a352146a056bfa77cb6135930bf728ec Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Wed, 11 Dec 2024 10:44:12 +1000 Subject: [PATCH 41/50] add deprecated flag for rev reg delta Signed-off-by: George Mulhearn --- aries/aries_vcx/src/common/credentials/mod.rs | 1 + aries/aries_vcx/src/common/primitives/revocation_registry.rs | 1 + aries/aries_vcx/src/handlers/issuance/issuer.rs | 1 + aries/aries_vcx/tests/test_anoncreds.rs | 1 + aries/aries_vcx/tests/test_credentials.rs | 1 + aries/aries_vcx/tests/test_pool.rs | 1 + aries/aries_vcx_ledger/src/ledger/base_ledger.rs | 2 ++ aries/aries_vcx_ledger/src/ledger/indy_vdr_ledger.rs | 1 + aries/aries_vcx_ledger/src/ledger/multi_ledger.rs | 5 ++++- 9 files changed, 13 insertions(+), 1 deletion(-) diff --git a/aries/aries_vcx/src/common/credentials/mod.rs b/aries/aries_vcx/src/common/credentials/mod.rs index f95cccb2eb..7b127273b6 100644 --- a/aries/aries_vcx/src/common/credentials/mod.rs +++ b/aries/aries_vcx/src/common/credentials/mod.rs @@ -25,6 +25,7 @@ pub async fn is_cred_revoked( rev_id: u32, ) -> VcxResult { let to = Some(OffsetDateTime::now_utc().unix_timestamp() as u64 + 100); + #[allow(deprecated)] // TODO - https://github.com/hyperledger/aries-vcx/issues/1309 let (rev_reg_delta, _) = ledger .get_rev_reg_delta_json(&rev_reg_id.try_into()?, None, to) .await?; diff --git a/aries/aries_vcx/src/common/primitives/revocation_registry.rs b/aries/aries_vcx/src/common/primitives/revocation_registry.rs index 1b117e119c..46244915ae 100644 --- a/aries/aries_vcx/src/common/primitives/revocation_registry.rs +++ b/aries/aries_vcx/src/common/primitives/revocation_registry.rs @@ -234,6 +234,7 @@ impl RevocationRegistry { ledger: &impl AnoncredsLedgerRead, cred_rev_id: u32, ) -> VcxResult<()> { + #[allow(deprecated)] // TODO - https://github.com/hyperledger/aries-vcx/issues/1309 let rev_reg_delta_json = ledger .get_rev_reg_delta_json(&self.rev_reg_id.to_string().try_into()?, None, None) .await? diff --git a/aries/aries_vcx/src/handlers/issuance/issuer.rs b/aries/aries_vcx/src/handlers/issuance/issuer.rs index cec5e72733..df490f6847 100644 --- a/aries/aries_vcx/src/handlers/issuance/issuer.rs +++ b/aries/aries_vcx/src/handlers/issuance/issuer.rs @@ -241,6 +241,7 @@ impl Issuer { revocation_info.rev_reg_id, revocation_info.tails_file, ) { + #[allow(deprecated)] // TODO - https://github.com/hyperledger/aries-vcx/issues/1309 let rev_reg_delta_json = ledger .get_rev_reg_delta_json(&rev_reg_id.to_owned().try_into()?, None, None) .await? diff --git a/aries/aries_vcx/tests/test_anoncreds.rs b/aries/aries_vcx/tests/test_anoncreds.rs index 4f742bd327..a1ec7631a0 100644 --- a/aries/aries_vcx/tests/test_anoncreds.rs +++ b/aries/aries_vcx/tests/test_anoncreds.rs @@ -73,6 +73,7 @@ async fn test_pool_proof_req_attribute_names() -> Result<(), Box> { Ok(()) } +#[allow(deprecated)] // TODO - https://github.com/hyperledger/aries-vcx/issues/1309 #[tokio::test] #[ignore] async fn test_pool_revoke_credential() -> Result<(), Box> { diff --git a/aries/aries_vcx/tests/test_credentials.rs b/aries/aries_vcx/tests/test_credentials.rs index c0191e74eb..91f6df1f77 100644 --- a/aries/aries_vcx/tests/test_credentials.rs +++ b/aries/aries_vcx/tests/test_credentials.rs @@ -110,6 +110,7 @@ async fn test_pool_is_cred_revoked() -> Result<(), Box> { assert!(!is_cred_revoked(&setup.ledger_read, &rev_reg.rev_reg_id, cred_rev_id).await?); + #[allow(deprecated)] // TODO - https://github.com/hyperledger/aries-vcx/issues/1309 let rev_reg_delta_json = setup .ledger_read .get_rev_reg_delta_json(&rev_reg.rev_reg_id.to_owned().try_into()?, None, None) diff --git a/aries/aries_vcx/tests/test_pool.rs b/aries/aries_vcx/tests/test_pool.rs index 87a44db890..ac2cfe5b1d 100644 --- a/aries/aries_vcx/tests/test_pool.rs +++ b/aries/aries_vcx/tests/test_pool.rs @@ -475,6 +475,7 @@ async fn test_pool_get_rev_reg_delta_json() -> Result<(), Box> { .await?; let ledger = &setup.ledger_read; + #[allow(deprecated)] // TODO - https://github.com/hyperledger/aries-vcx/issues/1309 let (_delta, _timestamp) = ledger .get_rev_reg_delta_json(&rev_reg.rev_reg_id.to_owned().try_into()?, None, None) .await?; diff --git a/aries/aries_vcx_ledger/src/ledger/base_ledger.rs b/aries/aries_vcx_ledger/src/ledger/base_ledger.rs index fb3e4bb607..b7460be6ea 100644 --- a/aries/aries_vcx_ledger/src/ledger/base_ledger.rs +++ b/aries/aries_vcx_ledger/src/ledger/base_ledger.rs @@ -103,6 +103,8 @@ pub trait AnoncredsLedgerRead: Debug + Send + Sync { RevocationRegistryDefinition, Self::RevocationRegistryDefinitionAdditionalMetadata, )>; + + #[deprecated(note = "use revocation status lists instead")] async fn get_rev_reg_delta_json( &self, rev_reg_id: &RevocationRegistryDefinitionId, diff --git a/aries/aries_vcx_ledger/src/ledger/indy_vdr_ledger.rs b/aries/aries_vcx_ledger/src/ledger/indy_vdr_ledger.rs index 39ee62e1d4..77e0d82968 100644 --- a/aries/aries_vcx_ledger/src/ledger/indy_vdr_ledger.rs +++ b/aries/aries_vcx_ledger/src/ledger/indy_vdr_ledger.rs @@ -573,6 +573,7 @@ where timestamp: u64, rev_reg_def_meta: Option<&RevocationRegistryDefinitionAdditionalMetadata>, ) -> VcxLedgerResult<(RevocationStatusList, u64)> { + #[allow(deprecated)] // TODO - https://github.com/hyperledger/aries-vcx/issues/1309 let (delta, entry_time) = self .get_rev_reg_delta_json(rev_reg_id, Some(0), Some(timestamp)) .await?; diff --git a/aries/aries_vcx_ledger/src/ledger/multi_ledger.rs b/aries/aries_vcx_ledger/src/ledger/multi_ledger.rs index 5911b4c4fa..adde6687d5 100644 --- a/aries/aries_vcx_ledger/src/ledger/multi_ledger.rs +++ b/aries/aries_vcx_ledger/src/ledger/multi_ledger.rs @@ -21,7 +21,7 @@ use crate::errors::error::{VcxLedgerError, VcxLedgerResult}; /// Struct to aggregate multiple [AnoncredsLedgerRead] implementations into a single /// [AnoncredsLedgerRead]. The child [AnoncredsLedgerRead] implementations are -/// utiliized depending on whether or not they support resolution of the given object ID +/// utilized depending on whether or not they support resolution of the given object ID /// (e.g. based on the DID Method). #[derive(Default, Debug)] pub struct MultiLedgerAnoncredsRead { @@ -95,6 +95,7 @@ impl AnoncredsLedgerRead for MultiLedgerAnoncredsRead { rev_reg_id.to_string(), ))?; + #[allow(deprecated)] // TODO - https://github.com/hyperledger/aries-vcx/issues/1309 reader.get_rev_reg_delta_json(rev_reg_id, from, to).await } @@ -236,6 +237,7 @@ where from: Option, to: Option, ) -> VcxLedgerResult<(RevocationRegistryDelta, u64)> { + #[allow(deprecated)] // TODO - https://github.com/hyperledger/aries-vcx/issues/1309 self.inner .get_rev_reg_delta_json(rev_reg_id, from, to) .await @@ -594,6 +596,7 @@ mod unit_tests { ); } + #[allow(deprecated)] // TODO - https://github.com/hyperledger/aries-vcx/issues/1309 #[tokio::test] async fn test_get_rev_reg_delta_proxy() { let id = RevocationRegistryDefinitionId::new_unchecked(uuid::Uuid::new_v4().to_string()); From 3cd9e86d11d4d753a09b3bf884e2513c1554d381 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Wed, 11 Dec 2024 10:51:20 +1000 Subject: [PATCH 42/50] dev note on multi ledger Signed-off-by: George Mulhearn --- aries/aries_vcx_ledger/src/ledger/multi_ledger.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/aries/aries_vcx_ledger/src/ledger/multi_ledger.rs b/aries/aries_vcx_ledger/src/ledger/multi_ledger.rs index adde6687d5..379446c3b4 100644 --- a/aries/aries_vcx_ledger/src/ledger/multi_ledger.rs +++ b/aries/aries_vcx_ledger/src/ledger/multi_ledger.rs @@ -19,6 +19,16 @@ use serde_json::Value; use super::base_ledger::{AnoncredsLedgerRead, AnoncredsLedgerSupport}; use crate::errors::error::{VcxLedgerError, VcxLedgerResult}; +// FUTURE - this multi-ledger anoncreds reader finds the first impl that supports the identifier +// and attempts to use it. This behaviour may need some enhancements in the future when +// considering coordination of unqualified object resolution, when multiple capable anoncreds +// readers are available (e.g. sovrin testnet & sovrin mainnet). +// Enhancements may include: +// * priority system - try A resolver before B if A & B both support the identifier +// * fallback/chain system - try A resolver, if it fails, try B resolver +// Alternatively these enhancements can be skipped if qualified DIDs/objects are used instead, +// e.g. did:indy:a:123, did:indy:b:123 + /// Struct to aggregate multiple [AnoncredsLedgerRead] implementations into a single /// [AnoncredsLedgerRead]. The child [AnoncredsLedgerRead] implementations are /// utilized depending on whether or not they support resolution of the given object ID From 47cccec21ab06ba0770fb8396f90860e95e5601d Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Wed, 11 Dec 2024 10:53:04 +1000 Subject: [PATCH 43/50] fmt Signed-off-by: George Mulhearn --- aries/aries_vcx_ledger/src/ledger/multi_ledger.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aries/aries_vcx_ledger/src/ledger/multi_ledger.rs b/aries/aries_vcx_ledger/src/ledger/multi_ledger.rs index 379446c3b4..245cd08ede 100644 --- a/aries/aries_vcx_ledger/src/ledger/multi_ledger.rs +++ b/aries/aries_vcx_ledger/src/ledger/multi_ledger.rs @@ -20,9 +20,9 @@ use super::base_ledger::{AnoncredsLedgerRead, AnoncredsLedgerSupport}; use crate::errors::error::{VcxLedgerError, VcxLedgerResult}; // FUTURE - this multi-ledger anoncreds reader finds the first impl that supports the identifier -// and attempts to use it. This behaviour may need some enhancements in the future when +// and attempts to use it. This behaviour may need some enhancements in the future when // considering coordination of unqualified object resolution, when multiple capable anoncreds -// readers are available (e.g. sovrin testnet & sovrin mainnet). +// readers are available (e.g. sovrin testnet & sovrin mainnet). // Enhancements may include: // * priority system - try A resolver before B if A & B both support the identifier // * fallback/chain system - try A resolver, if it fails, try B resolver From 4af894ce1dda00fc8205706d38adb0301326a8e9 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Wed, 11 Dec 2024 11:21:52 +1000 Subject: [PATCH 44/50] try arc wrapper Signed-off-by: George Mulhearn --- aries/aries_vcx_ledger/src/ledger/arc.rs | 100 ++++++++++++++++++ .../src/ledger/base_ledger.rs | 2 +- aries/aries_vcx_ledger/src/ledger/mod.rs | 1 + 3 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 aries/aries_vcx_ledger/src/ledger/arc.rs diff --git a/aries/aries_vcx_ledger/src/ledger/arc.rs b/aries/aries_vcx_ledger/src/ledger/arc.rs new file mode 100644 index 0000000000..9f181d8bab --- /dev/null +++ b/aries/aries_vcx_ledger/src/ledger/arc.rs @@ -0,0 +1,100 @@ +//! Contains convenience wrappers for the aries_vcx_ledger traits when working with [Arc]s. +use std::sync::Arc; + +use anoncreds_types::data_types::{ + identifiers::{ + cred_def_id::CredentialDefinitionId, rev_reg_def_id::RevocationRegistryDefinitionId, + schema_id::SchemaId, + }, + ledger::{ + cred_def::CredentialDefinition, rev_reg::RevocationRegistry, + rev_reg_def::RevocationRegistryDefinition, rev_reg_delta::RevocationRegistryDelta, + rev_status_list::RevocationStatusList, schema::Schema, + }, +}; +use async_trait::async_trait; +use did_parser_nom::Did; + +use super::base_ledger::AnoncredsLedgerRead; +use crate::errors::error::VcxLedgerResult; + +/// Convenience trait to convert something into an [AnoncredsLedgerRead] implementation. +pub trait IntoAnoncredsLedgerRead { + fn into_impl(self) -> impl AnoncredsLedgerRead; +} + +/// Convenience to convert any Arc into AnoncredsLedgerRead. +/// This is possible because all methods of [AnoncredsLedgerRead] only require a reference +/// of self. +impl IntoAnoncredsLedgerRead for Arc +where + T: AnoncredsLedgerRead, +{ + fn into_impl(self) -> impl AnoncredsLedgerRead { + ArcAnoncredsLedgerRead(self) + } +} + +#[derive(Debug)] +struct ArcAnoncredsLedgerRead(Arc); + +#[async_trait] +impl AnoncredsLedgerRead for ArcAnoncredsLedgerRead +where + T: AnoncredsLedgerRead, +{ + type RevocationRegistryDefinitionAdditionalMetadata = + T::RevocationRegistryDefinitionAdditionalMetadata; + + async fn get_schema( + &self, + schema_id: &SchemaId, + submitter_did: Option<&Did>, + ) -> VcxLedgerResult { + self.0.get_schema(schema_id, submitter_did).await + } + + async fn get_cred_def( + &self, + cred_def_id: &CredentialDefinitionId, + submitter_did: Option<&Did>, + ) -> VcxLedgerResult { + self.get_cred_def(cred_def_id, submitter_did).await + } + async fn get_rev_reg_def_json( + &self, + rev_reg_id: &RevocationRegistryDefinitionId, + ) -> VcxLedgerResult<( + RevocationRegistryDefinition, + Self::RevocationRegistryDefinitionAdditionalMetadata, + )> { + self.get_rev_reg_def_json(rev_reg_id).await + } + + async fn get_rev_reg_delta_json( + &self, + rev_reg_id: &RevocationRegistryDefinitionId, + from: Option, + to: Option, + ) -> VcxLedgerResult<(RevocationRegistryDelta, u64)> { + #[allow(deprecated)] + self.get_rev_reg_delta_json(rev_reg_id, from, to).await + } + + async fn get_rev_status_list( + &self, + rev_reg_id: &RevocationRegistryDefinitionId, + timestamp: u64, + rev_reg_def_meta: Option<&Self::RevocationRegistryDefinitionAdditionalMetadata>, + ) -> VcxLedgerResult<(RevocationStatusList, u64)> { + self.get_rev_status_list(rev_reg_id, timestamp, rev_reg_def_meta) + .await + } + async fn get_rev_reg( + &self, + rev_reg_id: &RevocationRegistryDefinitionId, + timestamp: u64, + ) -> VcxLedgerResult<(RevocationRegistry, u64)> { + self.get_rev_reg(rev_reg_id, timestamp).await + } +} diff --git a/aries/aries_vcx_ledger/src/ledger/base_ledger.rs b/aries/aries_vcx_ledger/src/ledger/base_ledger.rs index b7460be6ea..d068b62b11 100644 --- a/aries/aries_vcx_ledger/src/ledger/base_ledger.rs +++ b/aries/aries_vcx_ledger/src/ledger/base_ledger.rs @@ -81,7 +81,7 @@ pub trait AnoncredsLedgerRead: Debug + Send + Sync { /// `get_rev_status_list`. Depending on the ledger anoncreds-method, this metadata may be /// used in the subsequent revocation status list fetch as an optimization (e.g. to save an /// additional ledger call). - type RevocationRegistryDefinitionAdditionalMetadata; + type RevocationRegistryDefinitionAdditionalMetadata: Send + Sync; async fn get_schema( &self, diff --git a/aries/aries_vcx_ledger/src/ledger/mod.rs b/aries/aries_vcx_ledger/src/ledger/mod.rs index eb8abc4e8c..3a80c32684 100644 --- a/aries/aries_vcx_ledger/src/ledger/mod.rs +++ b/aries/aries_vcx_ledger/src/ledger/mod.rs @@ -1,5 +1,6 @@ use crate::errors::error::VcxLedgerError; +pub mod arc; pub mod base_ledger; pub mod common; From f0d93dde764233bd183f87ba6bb516a3f607cc32 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Wed, 11 Dec 2024 11:55:34 +1000 Subject: [PATCH 45/50] more generic trait Signed-off-by: George Mulhearn --- aries/aries_vcx_ledger/src/ledger/arc.rs | 49 ++++++++++++++++-------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/aries/aries_vcx_ledger/src/ledger/arc.rs b/aries/aries_vcx_ledger/src/ledger/arc.rs index 9f181d8bab..4b26e895b7 100644 --- a/aries/aries_vcx_ledger/src/ledger/arc.rs +++ b/aries/aries_vcx_ledger/src/ledger/arc.rs @@ -15,31 +15,33 @@ use anoncreds_types::data_types::{ use async_trait::async_trait; use did_parser_nom::Did; -use super::base_ledger::AnoncredsLedgerRead; +use super::base_ledger::{AnoncredsLedgerRead, AnoncredsLedgerSupport}; use crate::errors::error::VcxLedgerResult; -/// Convenience trait to convert something into an [AnoncredsLedgerRead] implementation. -pub trait IntoAnoncredsLedgerRead { - fn into_impl(self) -> impl AnoncredsLedgerRead; -} - -/// Convenience to convert any Arc into AnoncredsLedgerRead. -/// This is possible because all methods of [AnoncredsLedgerRead] only require a reference -/// of self. -impl IntoAnoncredsLedgerRead for Arc +/// Trait designed to convert [Arc] into [ArcLedgerTraitWrapper], such that +/// [Arc] can inherit any trait implementation of [ArcLedgerTraitWrapper]. (e.g. +/// [AnoncredsLedgerRead], [AnoncredsLedgerSupport]). +pub trait IntoArcLedgerTrait where - T: AnoncredsLedgerRead, + Self: Sized, { - fn into_impl(self) -> impl AnoncredsLedgerRead { - ArcAnoncredsLedgerRead(self) + fn into_impl(self) -> ArcLedgerTraitWrapper; +} + +impl IntoArcLedgerTrait for Arc { + fn into_impl(self) -> ArcLedgerTraitWrapper { + ArcLedgerTraitWrapper(self) } } +/// Thin wrapper over some [Arc]. Designed to implement relevant aries_vcx_ledger +/// traits on behalf of [Arc], if [T] implements those traits. Necessary since [Arc] +/// would not inherit those implementations automatically. #[derive(Debug)] -struct ArcAnoncredsLedgerRead(Arc); +pub struct ArcLedgerTraitWrapper(Arc); #[async_trait] -impl AnoncredsLedgerRead for ArcAnoncredsLedgerRead +impl AnoncredsLedgerRead for ArcLedgerTraitWrapper where T: AnoncredsLedgerRead, { @@ -98,3 +100,20 @@ where self.get_rev_reg(rev_reg_id, timestamp).await } } + +impl AnoncredsLedgerSupport for ArcLedgerTraitWrapper +where + T: AnoncredsLedgerSupport, +{ + fn supports_schema(&self, id: &SchemaId) -> bool { + self.0.supports_schema(id) + } + + fn supports_credential_definition(&self, id: &CredentialDefinitionId) -> bool { + self.0.supports_credential_definition(id) + } + + fn supports_revocation_registry(&self, id: &RevocationRegistryDefinitionId) -> bool { + self.0.supports_revocation_registry(id) + } +} From ecc7c81e8f8e6940852ddff5ef64179461cf6a96 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Wed, 11 Dec 2024 12:05:45 +1000 Subject: [PATCH 46/50] whoops! Signed-off-by: George Mulhearn --- aries/aries_vcx_ledger/src/ledger/arc.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/aries/aries_vcx_ledger/src/ledger/arc.rs b/aries/aries_vcx_ledger/src/ledger/arc.rs index 4b26e895b7..9ca3568dca 100644 --- a/aries/aries_vcx_ledger/src/ledger/arc.rs +++ b/aries/aries_vcx_ledger/src/ledger/arc.rs @@ -61,7 +61,7 @@ where cred_def_id: &CredentialDefinitionId, submitter_did: Option<&Did>, ) -> VcxLedgerResult { - self.get_cred_def(cred_def_id, submitter_did).await + self.0.get_cred_def(cred_def_id, submitter_did).await } async fn get_rev_reg_def_json( &self, @@ -70,7 +70,7 @@ where RevocationRegistryDefinition, Self::RevocationRegistryDefinitionAdditionalMetadata, )> { - self.get_rev_reg_def_json(rev_reg_id).await + self.0.get_rev_reg_def_json(rev_reg_id).await } async fn get_rev_reg_delta_json( @@ -80,7 +80,7 @@ where to: Option, ) -> VcxLedgerResult<(RevocationRegistryDelta, u64)> { #[allow(deprecated)] - self.get_rev_reg_delta_json(rev_reg_id, from, to).await + self.0.get_rev_reg_delta_json(rev_reg_id, from, to).await } async fn get_rev_status_list( @@ -89,7 +89,8 @@ where timestamp: u64, rev_reg_def_meta: Option<&Self::RevocationRegistryDefinitionAdditionalMetadata>, ) -> VcxLedgerResult<(RevocationStatusList, u64)> { - self.get_rev_status_list(rev_reg_id, timestamp, rev_reg_def_meta) + self.0 + .get_rev_status_list(rev_reg_id, timestamp, rev_reg_def_meta) .await } async fn get_rev_reg( @@ -97,7 +98,7 @@ where rev_reg_id: &RevocationRegistryDefinitionId, timestamp: u64, ) -> VcxLedgerResult<(RevocationRegistry, u64)> { - self.get_rev_reg(rev_reg_id, timestamp).await + self.0.get_rev_reg(rev_reg_id, timestamp).await } } From 06f9afd40f86523a10754d675555c6c44d1a5c44 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Thu, 12 Dec 2024 17:01:12 +1000 Subject: [PATCH 47/50] pipe thru schema to prover store credential Signed-off-by: George Mulhearn --- .../issuance/holder/state_machine.rs | 39 ++++-- .../issuance/holder/states/request_set.rs | 1 + aries/aries_vcx/tests/test_anoncreds.rs | 1 + .../tests/test_credential_retrieval.rs | 1 + aries/aries_vcx/tests/test_credentials.rs | 2 + .../tests/test_proof_presentation.rs | 1 + aries/aries_vcx/tests/test_verifier.rs | 1 + aries/aries_vcx/tests/utils/mod.rs | 2 + .../src/anoncreds/anoncreds/mod.rs | 119 +++--------------- .../src/anoncreds/base_anoncreds.rs | 9 +- .../test_utils/src/mockdata/mock_anoncreds.rs | 9 +- 11 files changed, 62 insertions(+), 123 deletions(-) diff --git a/aries/aries_vcx/src/protocols/issuance/holder/state_machine.rs b/aries/aries_vcx/src/protocols/issuance/holder/state_machine.rs index d0b9270320..3f07a9d727 100644 --- a/aries/aries_vcx/src/protocols/issuance/holder/state_machine.rs +++ b/aries/aries_vcx/src/protocols/issuance/holder/state_machine.rs @@ -224,11 +224,12 @@ impl HolderSM { ) .await { - Ok((msg_credential_request, req_meta, cred_def_json)) => { + Ok((msg_credential_request, req_meta, cred_def_json, schema_id)) => { HolderFullState::RequestSet(RequestSetState { msg_credential_request, req_meta, cred_def_json, + schema_id, }) } Err(err) => { @@ -276,6 +277,10 @@ impl HolderSM { trace!("HolderSM::receive_credential >>"); let state = match self.state { HolderFullState::RequestSet(state_data) => { + let schema = ledger + .get_schema(&state_data.schema_id.clone().try_into()?, None) + .await?; + let schema_json = serde_json::to_string(&schema)?; match _store_credential( wallet, ledger, @@ -283,6 +288,7 @@ impl HolderSM { &credential, &state_data.req_meta, &state_data.cred_def_json, + &schema_json, ) .await { @@ -549,6 +555,7 @@ async fn _store_credential( credential: &IssueCredentialV1, req_meta: &str, cred_def_json: &str, + schema_json: &str, ) -> VcxResult<(String, Option)> { trace!( "Holder::_store_credential >>> credential: {:?}, req_meta: {}, cred_def_json: {}", @@ -572,6 +579,7 @@ async fn _store_credential( wallet, serde_json::from_str(req_meta)?, serde_json::from_str(&credential_json)?, + serde_json::from_str(schema_json)?, serde_json::from_str(cred_def_json)?, rev_reg_def_json.clone(), ) @@ -585,6 +593,7 @@ async fn _store_credential( )) } +/// On success, returns: credential request, request metadata, cred_def_id, cred def, schema_id pub async fn create_anoncreds_credential_request( wallet: &impl BaseWallet, ledger: &impl AnoncredsLedgerRead, @@ -592,7 +601,7 @@ pub async fn create_anoncreds_credential_request( cred_def_id: &str, prover_did: &Did, cred_offer: &str, -) -> VcxResult<(String, String, String, String)> { +) -> VcxResult<(String, String, String, String, String)> { let cred_def_json = ledger .get_cred_def(&cred_def_id.to_string().try_into()?, None) .await?; @@ -619,10 +628,13 @@ pub async fn create_anoncreds_credential_request( serde_json::to_string(&s2).unwrap(), cred_def_id.to_string(), serde_json::to_string(&cred_def_json).unwrap(), + cred_def_json.schema_id.to_string(), ) }) } +/// On success, returns: message with cred request, request metadata, cred def (for caching), +/// schema_id async fn build_credential_request_msg( wallet: &impl BaseWallet, ledger: &impl AnoncredsLedgerRead, @@ -630,7 +642,7 @@ async fn build_credential_request_msg( thread_id: String, my_pw_did: Did, offer: &OfferCredentialV1, -) -> VcxResult<(RequestCredentialV1, String, String)> { +) -> VcxResult<(RequestCredentialV1, String, String, String)> { trace!( "Holder::_make_credential_request >>> my_pw_did: {:?}, offer: {:?}", my_pw_did, @@ -641,16 +653,17 @@ async fn build_credential_request_msg( trace!("Parsed cred offer attachment: {}", cred_offer); let cred_def_id = parse_cred_def_id_from_cred_offer(&cred_offer)?; - let (req, req_meta, _cred_def_id, cred_def_json) = create_anoncreds_credential_request( - wallet, - ledger, - anoncreds, - &cred_def_id, - &my_pw_did, - &cred_offer, - ) - .await?; + let (req, req_meta, _cred_def_id, cred_def_json, schema_id) = + create_anoncreds_credential_request( + wallet, + ledger, + anoncreds, + &cred_def_id, + &my_pw_did, + &cred_offer, + ) + .await?; trace!("Created cred def json: {}", cred_def_json); let credential_request_msg = _build_credential_request_msg(req, &thread_id); - Ok((credential_request_msg, req_meta, cred_def_json)) + Ok((credential_request_msg, req_meta, cred_def_json, schema_id)) } diff --git a/aries/aries_vcx/src/protocols/issuance/holder/states/request_set.rs b/aries/aries_vcx/src/protocols/issuance/holder/states/request_set.rs index e348378872..586a75b2c6 100644 --- a/aries/aries_vcx/src/protocols/issuance/holder/states/request_set.rs +++ b/aries/aries_vcx/src/protocols/issuance/holder/states/request_set.rs @@ -11,6 +11,7 @@ use crate::{ pub struct RequestSetState { pub req_meta: String, pub cred_def_json: String, + pub schema_id: String, pub msg_credential_request: RequestCredentialV1, } diff --git a/aries/aries_vcx/tests/test_anoncreds.rs b/aries/aries_vcx/tests/test_anoncreds.rs index a1ec7631a0..6155deb463 100644 --- a/aries/aries_vcx/tests/test_anoncreds.rs +++ b/aries/aries_vcx/tests/test_anoncreds.rs @@ -110,6 +110,7 @@ async fn test_pool_revoke_credential() -> Result<(), Box> { &setup.anoncreds, &setup.anoncreds, &setup.institution_did, + &schema, &cred_def, Some(&rev_reg), ) diff --git a/aries/aries_vcx/tests/test_credential_retrieval.rs b/aries/aries_vcx/tests/test_credential_retrieval.rs index e43af06c3c..12cfbe5d15 100644 --- a/aries/aries_vcx/tests/test_credential_retrieval.rs +++ b/aries/aries_vcx/tests/test_credential_retrieval.rs @@ -147,6 +147,7 @@ async fn test_agency_pool_case_for_proof_req_doesnt_matter_for_retrieve_creds( &setup.anoncreds, &setup.anoncreds, &setup.institution_did, + &schema, &cred_def, None, ) diff --git a/aries/aries_vcx/tests/test_credentials.rs b/aries/aries_vcx/tests/test_credentials.rs index 91f6df1f77..cd5ef078b9 100644 --- a/aries/aries_vcx/tests/test_credentials.rs +++ b/aries/aries_vcx/tests/test_credentials.rs @@ -48,6 +48,7 @@ async fn test_pool_prover_get_credential() -> Result<(), Box> { &setup.anoncreds, &setup.anoncreds, &setup.institution_did, + &schema, &cred_def, Some(&rev_reg), ) @@ -102,6 +103,7 @@ async fn test_pool_is_cred_revoked() -> Result<(), Box> { &setup.anoncreds, &setup.anoncreds, &setup.institution_did, + &schema, &cred_def, Some(&rev_reg), ) diff --git a/aries/aries_vcx/tests/test_proof_presentation.rs b/aries/aries_vcx/tests/test_proof_presentation.rs index 3053450abd..2609da0175 100644 --- a/aries/aries_vcx/tests/test_proof_presentation.rs +++ b/aries/aries_vcx/tests/test_proof_presentation.rs @@ -71,6 +71,7 @@ async fn test_agency_pool_generate_proof_with_predicates() -> Result<(), Box, ) -> String { @@ -159,6 +160,7 @@ pub async fn create_and_write_credential( wallet_holder, req_meta, cred, + schema.schema_json.clone(), cred_def.get_cred_def_json().try_clone().unwrap(), rev_reg_def_json .as_deref() diff --git a/aries/aries_vcx_anoncreds/src/anoncreds/anoncreds/mod.rs b/aries/aries_vcx_anoncreds/src/anoncreds/anoncreds/mod.rs index 41ad7fb9cf..5b83239d47 100644 --- a/aries/aries_vcx_anoncreds/src/anoncreds/anoncreds/mod.rs +++ b/aries/aries_vcx_anoncreds/src/anoncreds/anoncreds/mod.rs @@ -966,26 +966,21 @@ impl BaseAnonCreds for Anoncreds { async fn prover_store_credential( &self, wallet: &impl BaseWallet, - cred_req_metadata_json: CredentialRequestMetadata, - cred_json: Credential, - cred_def_json: CredentialDefinition, - rev_reg_def_json: Option, + cred_req_metadata: CredentialRequestMetadata, + unprocessed_cred: Credential, + schema: Schema, + cred_def: CredentialDefinition, + rev_reg_def: Option, ) -> VcxAnoncredsResult { - let mut credential: AnoncredsCredential = cred_json.convert(())?; - - let cred_def_id = credential.cred_def_id.to_string(); - let (_cred_def_method, issuer_did, _signature_type, _schema_num, _tag) = - cred_def_parts(&cred_def_id).ok_or(VcxAnoncredsError::InvalidSchema( - "Could not process credential.cred_def_id as parts.".into(), - ))?; + let mut credential: AnoncredsCredential = unprocessed_cred.convert(())?; let cred_request_metadata: AnoncredsCredentialRequestMetadata = - cred_req_metadata_json.convert(())?; + cred_req_metadata.convert(())?; let link_secret_id = &cred_request_metadata.link_secret_name; let link_secret = self.get_link_secret(wallet, link_secret_id).await?; - let cred_def: AnoncredsCredentialDefinition = cred_def_json.convert(())?; + let cred_def: AnoncredsCredentialDefinition = cred_def.convert(())?; let rev_reg_def: Option = - if let Some(rev_reg_def_json) = rev_reg_def_json { + if let Some(rev_reg_def_json) = rev_reg_def { Some(rev_reg_def_json.convert(())?) } else { None @@ -1000,19 +995,20 @@ impl BaseAnonCreds for Anoncreds { )?; let schema_id = &credential.schema_id; + let cred_def_id = &credential.cred_def_id; + let issuer_did = &cred_def.issuer_id; - let (_schema_method, schema_issuer_did, schema_name, schema_version) = - schema_parts(schema_id.0.as_str()).ok_or(VcxAnoncredsError::InvalidSchema(format!( - "Could not process credential.schema_id {schema_id} as parts." - )))?; + let schema_issuer_did = schema.issuer_id; + let schema_name = schema.name; + let schema_version = schema.version; let mut tags = RecordTags::new(vec![ RecordTag::new("schema_id", &schema_id.0), - RecordTag::new("schema_issuer_did", schema_issuer_did.did()), + RecordTag::new("schema_issuer_did", &schema_issuer_did.0), RecordTag::new("schema_name", &schema_name), RecordTag::new("schema_version", &schema_version), - RecordTag::new("issuer_did", issuer_did.did()), - RecordTag::new("cred_def_id", &cred_def_id), + RecordTag::new("issuer_did", &issuer_did.0), + RecordTag::new("cred_def_id", &cred_def_id.0), ]); if let Some(rev_reg_id) = &credential.rev_reg_id { @@ -1403,84 +1399,3 @@ pub fn schema_parts(id: &str) -> Option<(Option<&str>, Did, String, String)> { None } - -pub fn cred_def_parts(id: &str) -> Option<(Option<&str>, Did, String, SchemaId, String)> { - let parts = id.split_terminator(':').collect::>(); - - if parts.len() == 4 { - // Th7MpTaRZVRYnPiabds81Y:3:CL:1 - let did = parts[0].to_string(); - let Ok(did) = Did::parse(did) else { - return None; - }; - let signature_type = parts[2].to_string(); - let schema_id = parts[3].to_string(); - let tag = String::new(); - return Some((None, did, signature_type, SchemaId(schema_id), tag)); - } - - if parts.len() == 5 { - // Th7MpTaRZVRYnPiabds81Y:3:CL:1:tag - let did = parts[0].to_string(); - let Ok(did) = Did::parse(did) else { - return None; - }; - let signature_type = parts[2].to_string(); - let schema_id = parts[3].to_string(); - let tag = parts[4].to_string(); - return Some((None, did, signature_type, SchemaId(schema_id), tag)); - } - - if parts.len() == 7 { - // NcYxiDXkpYi6ov5FcYDi1e:3:CL:NcYxiDXkpYi6ov5FcYDi1e:2:gvt:1.0 - let did = parts[0].to_string(); - let Ok(did) = Did::parse(did) else { - return None; - }; - let signature_type = parts[2].to_string(); - let schema_id = parts[3..7].join(":"); - let tag = String::new(); - return Some((None, did, signature_type, SchemaId(schema_id), tag)); - } - - if parts.len() == 8 { - // NcYxiDXkpYi6ov5FcYDi1e:3:CL:NcYxiDXkpYi6ov5FcYDi1e:2:gvt:1.0:tag - let did = parts[0].to_string(); - let Ok(did) = Did::parse(did) else { - return None; - }; - let signature_type = parts[2].to_string(); - let schema_id = parts[3..7].join(":"); - let tag = parts[7].to_string(); - return Some((None, did, signature_type, SchemaId(schema_id), tag)); - } - - if parts.len() == 9 { - // creddef:sov:did:sov:NcYxiDXkpYi6ov5FcYDi1e:3:CL:3:tag - let method = parts[1]; - let did = parts[2..5].join(":"); - let Ok(did) = Did::parse(did) else { - return None; - }; - let signature_type = parts[6].to_string(); - let schema_id = parts[7].to_string(); - let tag = parts[8].to_string(); - return Some((Some(method), did, signature_type, SchemaId(schema_id), tag)); - } - - if parts.len() == 16 { - // creddef:sov:did:sov:NcYxiDXkpYi6ov5FcYDi1e:3:CL:schema:sov:did:sov: - // NcYxiDXkpYi6ov5FcYDi1e:2:gvt:1.0:tag - let method = parts[1]; - let did = parts[2..5].join(":"); - let Ok(did) = Did::parse(did) else { - return None; - }; - let signature_type = parts[6].to_string(); - let schema_id = parts[7..15].join(":"); - let tag = parts[15].to_string(); - return Some((Some(method), did, signature_type, SchemaId(schema_id), tag)); - } - - None -} diff --git a/aries/aries_vcx_anoncreds/src/anoncreds/base_anoncreds.rs b/aries/aries_vcx_anoncreds/src/anoncreds/base_anoncreds.rs index 49163b6c73..0dac88a6ef 100644 --- a/aries/aries_vcx_anoncreds/src/anoncreds/base_anoncreds.rs +++ b/aries/aries_vcx_anoncreds/src/anoncreds/base_anoncreds.rs @@ -146,10 +146,11 @@ pub trait BaseAnonCreds: std::fmt::Debug + Send + Sync { async fn prover_store_credential( &self, wallet: &impl BaseWallet, - cred_req_metadata_json: CredentialRequestMetadata, - cred_json: Credential, - cred_def_json: CredentialDefinition, - rev_reg_def_json: Option, + cred_req_metadata: CredentialRequestMetadata, + unprocessed_cred: Credential, + schema: Schema, + cred_def: CredentialDefinition, + rev_reg_def: Option, ) -> VcxAnoncredsResult; async fn prover_delete_credential( diff --git a/aries/misc/test_utils/src/mockdata/mock_anoncreds.rs b/aries/misc/test_utils/src/mockdata/mock_anoncreds.rs index 696dce466f..e09d19f949 100644 --- a/aries/misc/test_utils/src/mockdata/mock_anoncreds.rs +++ b/aries/misc/test_utils/src/mockdata/mock_anoncreds.rs @@ -188,10 +188,11 @@ impl BaseAnonCreds for MockAnoncreds { async fn prover_store_credential( &self, _wallet: &impl BaseWallet, - _cred_req_metadata_json: CredentialRequestMetadata, - _cred_json: Credential, - _cred_def_json: CredentialDefinition, - _rev_reg_def_json: Option, + _cred_req_metadata: CredentialRequestMetadata, + _cred: Credential, + _schema: Schema, + _cred_def: CredentialDefinition, + _rev_reg_def: Option, ) -> VcxAnoncredsResult { Ok("cred_id".to_string()) } From a4eb40bb263beaa66aadc3207ba0d0b4fd9e0693 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Thu, 12 Dec 2024 17:34:13 +1000 Subject: [PATCH 48/50] type the schema id to avoid parsing issues with legacy identifiers Signed-off-by: George Mulhearn --- .../src/protocols/issuance/holder/state_machine.rs | 11 +++++------ .../protocols/issuance/holder/states/request_set.rs | 3 ++- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/aries/aries_vcx/src/protocols/issuance/holder/state_machine.rs b/aries/aries_vcx/src/protocols/issuance/holder/state_machine.rs index 3f07a9d727..5d0ee06aa9 100644 --- a/aries/aries_vcx/src/protocols/issuance/holder/state_machine.rs +++ b/aries/aries_vcx/src/protocols/issuance/holder/state_machine.rs @@ -1,5 +1,6 @@ use std::fmt; +use anoncreds_types::data_types::identifiers::schema_id::SchemaId; use aries_vcx_anoncreds::anoncreds::base_anoncreds::BaseAnonCreds; use aries_vcx_ledger::ledger::base_ledger::AnoncredsLedgerRead; use aries_vcx_wallet::wallet::base_wallet::BaseWallet; @@ -277,9 +278,7 @@ impl HolderSM { trace!("HolderSM::receive_credential >>"); let state = match self.state { HolderFullState::RequestSet(state_data) => { - let schema = ledger - .get_schema(&state_data.schema_id.clone().try_into()?, None) - .await?; + let schema = ledger.get_schema(&state_data.schema_id, None).await?; let schema_json = serde_json::to_string(&schema)?; match _store_credential( wallet, @@ -601,7 +600,7 @@ pub async fn create_anoncreds_credential_request( cred_def_id: &str, prover_did: &Did, cred_offer: &str, -) -> VcxResult<(String, String, String, String, String)> { +) -> VcxResult<(String, String, String, String, SchemaId)> { let cred_def_json = ledger .get_cred_def(&cred_def_id.to_string().try_into()?, None) .await?; @@ -628,7 +627,7 @@ pub async fn create_anoncreds_credential_request( serde_json::to_string(&s2).unwrap(), cred_def_id.to_string(), serde_json::to_string(&cred_def_json).unwrap(), - cred_def_json.schema_id.to_string(), + cred_def_json.schema_id, ) }) } @@ -642,7 +641,7 @@ async fn build_credential_request_msg( thread_id: String, my_pw_did: Did, offer: &OfferCredentialV1, -) -> VcxResult<(RequestCredentialV1, String, String, String)> { +) -> VcxResult<(RequestCredentialV1, String, String, SchemaId)> { trace!( "Holder::_make_credential_request >>> my_pw_did: {:?}, offer: {:?}", my_pw_did, diff --git a/aries/aries_vcx/src/protocols/issuance/holder/states/request_set.rs b/aries/aries_vcx/src/protocols/issuance/holder/states/request_set.rs index 586a75b2c6..b92044d3f3 100644 --- a/aries/aries_vcx/src/protocols/issuance/holder/states/request_set.rs +++ b/aries/aries_vcx/src/protocols/issuance/holder/states/request_set.rs @@ -1,3 +1,4 @@ +use anoncreds_types::data_types::identifiers::schema_id::SchemaId; use messages::msg_fields::protocols::cred_issuance::v1::{ issue_credential::IssueCredentialV1, request_credential::RequestCredentialV1, }; @@ -11,7 +12,7 @@ use crate::{ pub struct RequestSetState { pub req_meta: String, pub cred_def_json: String, - pub schema_id: String, + pub schema_id: SchemaId, pub msg_credential_request: RequestCredentialV1, } From 7f69365ae970815488149b1d014ac5bbb3f89618 Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Thu, 12 Dec 2024 18:34:10 +1000 Subject: [PATCH 49/50] move around schema id a bit Signed-off-by: George Mulhearn --- .../issuance/holder/state_machine.rs | 30 ++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/aries/aries_vcx/src/protocols/issuance/holder/state_machine.rs b/aries/aries_vcx/src/protocols/issuance/holder/state_machine.rs index 5d0ee06aa9..f44a236f1d 100644 --- a/aries/aries_vcx/src/protocols/issuance/holder/state_machine.rs +++ b/aries/aries_vcx/src/protocols/issuance/holder/state_machine.rs @@ -1,6 +1,8 @@ use std::fmt; -use anoncreds_types::data_types::identifiers::schema_id::SchemaId; +use anoncreds_types::data_types::{ + identifiers::schema_id::SchemaId, messages::cred_offer::CredentialOffer, +}; use aries_vcx_anoncreds::anoncreds::base_anoncreds::BaseAnonCreds; use aries_vcx_ledger::ledger::base_ledger::AnoncredsLedgerRead; use aries_vcx_wallet::wallet::base_wallet::BaseWallet; @@ -597,20 +599,22 @@ pub async fn create_anoncreds_credential_request( wallet: &impl BaseWallet, ledger: &impl AnoncredsLedgerRead, anoncreds: &impl BaseAnonCreds, - cred_def_id: &str, prover_did: &Did, cred_offer: &str, ) -> VcxResult<(String, String, String, String, SchemaId)> { - let cred_def_json = ledger - .get_cred_def(&cred_def_id.to_string().try_into()?, None) - .await?; + let offer: CredentialOffer = serde_json::from_str(cred_offer)?; + + let schema_id = offer.schema_id.clone(); + let cred_def_id = offer.cred_def_id.clone(); + + let cred_def_json = ledger.get_cred_def(&cred_def_id, None).await?; let master_secret_id = settings::DEFAULT_LINK_SECRET_ALIAS; anoncreds .prover_create_credential_req( wallet, prover_did, - serde_json::from_str(cred_offer)?, + offer, cred_def_json.try_clone()?, &master_secret_id.to_string(), ) @@ -627,7 +631,7 @@ pub async fn create_anoncreds_credential_request( serde_json::to_string(&s2).unwrap(), cred_def_id.to_string(), serde_json::to_string(&cred_def_json).unwrap(), - cred_def_json.schema_id, + schema_id, ) }) } @@ -651,17 +655,9 @@ async fn build_credential_request_msg( let cred_offer = get_attach_as_string!(&offer.content.offers_attach); trace!("Parsed cred offer attachment: {}", cred_offer); - let cred_def_id = parse_cred_def_id_from_cred_offer(&cred_offer)?; let (req, req_meta, _cred_def_id, cred_def_json, schema_id) = - create_anoncreds_credential_request( - wallet, - ledger, - anoncreds, - &cred_def_id, - &my_pw_did, - &cred_offer, - ) - .await?; + create_anoncreds_credential_request(wallet, ledger, anoncreds, &my_pw_did, &cred_offer) + .await?; trace!("Created cred def json: {}", cred_def_json); let credential_request_msg = _build_credential_request_msg(req, &thread_id); Ok((credential_request_msg, req_meta, cred_def_json, schema_id)) From 19d0430ff42da0fdc329e00d1c9c9b24addc457c Mon Sep 17 00:00:00 2001 From: George Mulhearn Date: Tue, 17 Dec 2024 10:30:15 +1000 Subject: [PATCH 50/50] comment on weird typing Signed-off-by: George Mulhearn --- aries/aries_vcx_ledger/src/ledger/multi_ledger.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aries/aries_vcx_ledger/src/ledger/multi_ledger.rs b/aries/aries_vcx_ledger/src/ledger/multi_ledger.rs index 245cd08ede..fa00035e5b 100644 --- a/aries/aries_vcx_ledger/src/ledger/multi_ledger.rs +++ b/aries/aries_vcx_ledger/src/ledger/multi_ledger.rs @@ -300,6 +300,8 @@ mod unit_tests { impl AnoncredsLedgerRead for Reader { type RevocationRegistryDefinitionAdditionalMetadata = Value; + // NOTE: these method signatures were generated as a result of the expanded #[async_trait] form. + // this was needed to escape some #[async_trait] compiling issues fn get_schema<'life0,'life1,'life2,'async_trait>(&'life0 self,schema_id: &'life1 SchemaId,submitter_did:Option< &'life2 Did> ,) -> ::core::pin::Pin > + ::core::marker::Send+'async_trait> >where 'life0:'async_trait,'life1:'async_trait,'life2:'async_trait,Self:'async_trait; fn get_cred_def<'life0,'life1,'life2,'async_trait>(&'life0 self,cred_def_id: &'life1 CredentialDefinitionId,submitter_did:Option< &'life2 Did> ,) -> ::core::pin::Pin > + ::core::marker::Send+'async_trait> >where 'life0:'async_trait,'life1:'async_trait,'life2:'async_trait,Self:'async_trait; async fn get_rev_reg_def_json(&self, rev_reg_id: &RevocationRegistryDefinitionId) -> VcxLedgerResult<(RevocationRegistryDefinition, Value)>;