Skip to content

Commit

Permalink
47: add support for handling name bytes if they have nul
Browse files Browse the repository at this point in the history
 - fixes documentation
 - add documentation test to ci
  • Loading branch information
jac18281828 committed Feb 14, 2024
1 parent 64b6ca7 commit d297d6e
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 18 deletions.
8 changes: 6 additions & 2 deletions .github/workflows/github-pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,14 @@ jobs:
- name: Invoke cargo doc
run: |
rm -rf ./_site
cargo doc --workspace --no-deps
RUSTDOCFLAGS="-D warnings" cargo doc --workspace --all-features --no-deps
rm -f target/doc/.lock
cp -r target/doc _site
echo "<meta http-equiv=\"refresh\" content=\"0; url=didethresolver\">" > _site/index.html
if [ ! -d _site/lib_didethresolver ]; then
echo "Error: _site/lib_didethresolver does not exist"
exit 1
fi
echo "<meta http-equiv=\"refresh\" content=\"0; url=lib_didethresolver\">" > _site/index.html
echo "Taking care of pedantic permissions requirements required by GitHub Pages"
chmod -R +rX _site
id: docgen
Expand Down
4 changes: 3 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
"cargo": {
"args": [
"build",
"--bin=resolver",
"--package=resolver"
],
"filter": {
Expand All @@ -38,6 +37,9 @@
}
},
"args": [],
"env": {
"RPC_URL": "wss://eth-sepolia.g.alchemy.com/v2/uoO_-LFYsnyxFuDC1amzK6e_EPPz8Sh8",
},
"cwd": "${workspaceFolder}"
},
]
Expand Down
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ RUN cargo check --all-features
RUN cargo fmt --check --all
RUN cargo clippy --all-features --no-deps -- -D warnings
RUN cargo test --workspace --all-features
ENV RUSTDOCFLAGS="-D warnings"
RUN cargo doc --all-features --workspace --no-deps
RUN CARGO_TARGET_DIR=/workspaces/${PROJECT}/target cargo install --path resolver --bin=resolver --root ~${USER}/.cargo/
RUN valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose ~${USER}/.cargo/bin/resolver --help

Expand Down
6 changes: 6 additions & 0 deletions lib/src/resolver/did_registry.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//! Generated ABI Functions, along with some extra to make it easier to interact with the registry.
use std::ffi::CStr;

use crate::error::RegistrySignerError;
use ethers::{
Expand Down Expand Up @@ -56,6 +57,11 @@ impl DidattributeChangedFilter {

/// Get the name of the attribute as a string. non-UTF8 bytes will be replaced with the unicode replacement character, �.
pub fn name_string_lossy(&self) -> String {
let is_cstr = self.name.iter().rev().any(|&c| c == 0);
if is_cstr {
let cstr = unsafe { CStr::from_ptr(self.name.as_ptr()) };
return cstr.to_string_lossy().to_string();
}
String::from_utf8_lossy(self.name.as_ref()).to_string()
}

Expand Down
30 changes: 29 additions & 1 deletion lib/src/types/did_parser.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//! Parsing Expression Grammer (PEG) parsing rules for parts of a Decentralized Identifier

use ethers::types::Address;

use crate::types::*;
Expand Down Expand Up @@ -235,8 +234,11 @@ peg::parser! {

#[cfg(test)]
mod tests {

use super::*;

use std::ffi::CStr;

#[test]
fn test_did_attribute_parser() {
let keys = [
Expand Down Expand Up @@ -285,6 +287,32 @@ mod tests {
}
}

#[test]
fn test_parse_hex_c_string_svc() {
let decoded_data =
hex::decode("6469642f7376632f4d6573736167696e67536572766963650000000000000000")
.unwrap();
let cstr = CStr::from_bytes_until_nul(decoded_data.as_slice()).unwrap();
let parsed = parse_attribute(&cstr.as_ref().to_str().unwrap());
assert_eq!(parsed, Ok(Attribute::Service(ServiceType::Messaging)));
}

#[test]
fn test_parse_hex_c_string_pub() {
let decoded_data =
hex::decode("6469642f7075622f456432353531392f766572694b65792f62617365353800").unwrap();
let cstr = CStr::from_bytes_until_nul(decoded_data.as_slice()).unwrap();
let parsed = parse_attribute(&cstr.as_ref().to_str().unwrap());
assert_eq!(
parsed,
Ok(Attribute::PublicKey(PublicKey {
key_type: KeyType::Ed25519VerificationKey2020,
purpose: KeyPurpose::VerificationKey,
encoding: KeyEncoding::Base58
}))
);
}

#[test]
fn test_did_xmtp_attribute_parser() {
let keys = [
Expand Down
6 changes: 3 additions & 3 deletions lib/src/types/did_url.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ pub struct DidUrl {
pub fragment: Option<String>,
}

/// The `did` part of a [did:ethr](https://github.com/decentralized-identity/ethr-did-resolver/blob/master/doc/did-method-spec.md) URL. returned by [`parse_ethr_did`]
/// The `did` part of a [did:ethr](https://github.com/decentralized-identity/ethr-did-resolver/blob/master/doc/did-method-spec.md) URL. returned by [`super::parse_ethr_did`]
#[derive(Debug, Clone, PartialEq, Eq, SmartDefault)]
pub struct Did {
pub method: Method,
Expand Down Expand Up @@ -245,7 +245,7 @@ impl DidUrl {
/// Retrieves the chainId for an DID:ETHR URL, as defined in the [did-ethr](https://github.com/decentralized-identity/ethr-did-resolver/blob/master/doc/did-method-spec.md).
///
/// # Returns
/// A enum [`ChainId`] indicating the chain this DID belongs to.
/// A enum [`Network`] indicating the chain this DID belongs to.
///
/// # Examples
/// ```
Expand All @@ -261,7 +261,7 @@ impl DidUrl {
/// Retrieves the identity part from the DID URL, as defined in the [did-ethr spec](https://github.com/decentralized-identity/ethr-did-resolver/blob/master/doc/did-method-spec.md)).
///
/// # Returns
/// A Enum [`AddressOrHexKey`] which identifies the DID. This can be either an 20-byte [`Address`] or a 33-byte [`Vec<u8>`].
/// A Enum [`Account`] which identifies the DID. This can be either an 20-byte [`Address`] or a 33-byte [`Vec<u8>`].
///
/// # Examples
/// ```
Expand Down
87 changes: 77 additions & 10 deletions lib/src/types/ethr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,16 +182,19 @@ impl EthrBuilder {
event: DidattributeChangedFilter,
) -> Result<(), EthrBuilderError> {
let name = event.name_string_lossy();
let attribute = types::parse_attribute(&name).unwrap_or(Attribute::Other(name.to_string()));

log::trace!(
"Attribute Event name={}, value={}, now={}, valid_to={}, attr={:?}",
name,
event.value,
self.now,
event.valid_to,
attribute
);

if log::log_enabled!(log::Level::Trace) {
log::trace!(
"Attribute Event name={}, value={}, now={}, valid_to={}",
name.clone(),
event.value_string_lossy(),
self.now,
event.valid_to
);
}

let attribute =
types::parse_attribute(&name).unwrap_or_else(|_err| Attribute::Other(name.to_owned()));

let key = Key::Attribute {
name: event.name,
Expand Down Expand Up @@ -520,6 +523,40 @@ pub(crate) mod tests {
);
}

#[test]
fn test_attribute_changed_ed25519_from_hex_bytes() {
let identity = address("0x7e575682a8e450e33eb0493f9972821ae333cd7f");
let name_from_hex_str =
hex::decode("6469642f7075622f456432353531392f766572694b65792f6261736535380000")
.unwrap();
let name_bytes: [u8; 32] = name_from_hex_str.try_into().unwrap();

let event = DidattributeChangedFilter {
name: name_bytes,
value: b"b97c30de767f084ce3080168ee293053ba33b235d7116a3263d29f1450936b71".into(),
..base_attr_changed(identity, None)
};

let mut builder = EthrBuilder::default();
builder.account_address(&identity).unwrap();
builder.now(U256::zero());
builder.attribute_event(event).unwrap();
let doc = builder.build().unwrap();
assert_eq!(
doc.verification_method[1],
VerificationMethod {
id: DidUrl::parse("did:ethr:0x7e575682a8e450e33eb0493f9972821ae333cd7f#delegate-0")
.unwrap(),
verification_type: KeyType::Ed25519VerificationKey2020,
controller: DidUrl::parse("did:ethr:0x7e575682a8e450e33eb0493f9972821ae333cd7f")
.unwrap(),
verification_properties: Some(VerificationMethodProperties::PublicKeyBase58 {
public_key_base58: "DV4G2kpBKjE6zxKor7Cj21iL9x9qyXb6emqjszBXcuhz".into()
}),
}
);
}

#[test]
fn test_attribute_changed_x25519() {
let identity = address("0x7e575682a8e450e33eb0493f9972821ae333cd7f");
Expand Down Expand Up @@ -576,6 +613,36 @@ pub(crate) mod tests {
);
}

#[test]
fn test_attribute_changed_service_from_hex_bytes() {
let name_data =
hex::decode("6469642f7376632f4d6573736167696e67536572766963650000000000000000")
.unwrap();
let name_bytes: [u8; 32] = name_data.try_into().unwrap();
let identity = address("0x7e575682a8e450e33eb0493f9972821ae333cd7f");
let event = DidattributeChangedFilter {
name: name_bytes,
value: b"https://xmtp.com/resolver".into(),
..base_attr_changed(identity, None)
};

let mut builder = EthrBuilder::default();
builder.account_address(&identity).unwrap();
builder.now(U256::zero());
builder.attribute_event(event).unwrap();
let doc = builder.build().unwrap();
assert_eq!(
doc.service,
vec![Service {
id: DidUrl::parse("did:ethr:0x7e575682a8e450e33eb0493f9972821ae333cd7f#service-0")
.unwrap(),
service_type: ServiceType::Messaging,
service_endpoint: Url::parse("https://xmtp.com/resolver").unwrap(),
recipient_keys: "".into(),
}]
);
}

#[test]
fn test_attribute_increments_correctly() {
let identity = address("0x7e575682a8e450e33eb0493f9972821ae333cd7f");
Expand Down
7 changes: 6 additions & 1 deletion resolver/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
//! ### Endpoint
//!
//! ```text
//! POST /api/v1/resolveDid
//! POST
//! ```
//!
//! ### Request Format
Expand Down Expand Up @@ -74,6 +74,11 @@
//! - All requests must be made over HTTPS.
//! - Rate limiting is applied to prevent abuse.
//!
//! ### Example
//!
//! ```bash
//! curl -H "Content-Type: application/json" -d '{"id":1, "jsonrpc":"2.0", "method":"did_resolveDid", "params": { "publicKey":"x"} }' http://localhost:8080
//! ```
//!
//! ### Support
//!
Expand Down

0 comments on commit d297d6e

Please sign in to comment.