From 61e7458d3650bbc62be074f14a69e2d6ee6a7a28 Mon Sep 17 00:00:00 2001 From: Siyuan Ren Date: Wed, 4 Mar 2026 10:05:46 +0000 Subject: [PATCH 1/2] Switch to nanoserde for reduced binary size --- matcher-rs/Cargo.lock | 73 +++++--------------- matcher-rs/Cargo.toml | 3 +- matcher-rs/src/issuance.rs | 105 ++++++++++++++++++++--------- matcher-rs/src/issuance_matcher.rs | 16 ++--- matcher-rs/src/openid4vci.rs | 76 +++++++++------------ 5 files changed, 131 insertions(+), 142 deletions(-) diff --git a/matcher-rs/Cargo.lock b/matcher-rs/Cargo.lock index a75e65c..649e297 100644 --- a/matcher-rs/Cargo.lock +++ b/matcher-rs/Cargo.lock @@ -84,12 +84,6 @@ dependencies = [ "either", ] -[[package]] -name = "itoa" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" - [[package]] name = "libc" version = "0.2.177" @@ -136,8 +130,7 @@ version = "0.1.0" dependencies = [ "bindgen", "lol_alloc", - "serde", - "serde_json", + "nanoserde", ] [[package]] @@ -152,6 +145,21 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "nanoserde" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de9cf844ab1e25a0353525bd74cb889843a6215fa4a0d156fd446f4857a1b99" +dependencies = [ + "nanoserde-derive", +] + +[[package]] +name = "nanoserde-derive" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e943b2c21337b7e3ec6678500687cdc741b7639ad457f234693352075c082204" + [[package]] name = "nom" version = "7.1.3" @@ -225,61 +233,12 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" -[[package]] -name = "ryu" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" - [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "serde" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" -dependencies = [ - "serde_core", - "serde_derive", -] - -[[package]] -name = "serde_core" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.145" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" -dependencies = [ - "itoa", - "memchr", - "ryu", - "serde", - "serde_core", -] - [[package]] name = "shlex" version = "1.3.0" diff --git a/matcher-rs/Cargo.toml b/matcher-rs/Cargo.toml index aa7c445..22d395e 100644 --- a/matcher-rs/Cargo.toml +++ b/matcher-rs/Cargo.toml @@ -10,8 +10,7 @@ crate-type = ["cdylib", "rlib"] [dependencies] lol_alloc = "0.4.1" -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0.145" +nanoserde = "0.1" [dev-dependencies] diff --git a/matcher-rs/src/issuance.rs b/matcher-rs/src/issuance.rs index ca193bd..e092495 100644 --- a/matcher-rs/src/issuance.rs +++ b/matcher-rs/src/issuance.rs @@ -1,9 +1,13 @@ +use std::ffi::CString; + use crate::{ credman::CredmanApi, issuance_matcher::IssuanceMatcherData, openid4vci::{DigitalCredentialCreationRequest, RegularizedOpenId4VciRequestData}, }; +use nanoserde::DeJson; + const ALLOWED_PROTOCOLS: [&str; 4] = [ "openid4vci-1.0", "openid4vci1.0", @@ -14,10 +18,11 @@ const ALLOWED_PROTOCOLS: [&str; 4] = [ pub fn issuance_main(credman: &mut impl CredmanApi) -> Result<(), Box> { let matcher_data_buffer = credman.get_registered_data(); let json_start = u32::from_le_bytes(matcher_data_buffer[..size_of::()].try_into()?); - let matcher_data: IssuanceMatcherData = - serde_json::from_slice(&matcher_data_buffer[json_start.try_into()?..])?; + let matcher_data: IssuanceMatcherData = DeJson::deserialize_json(std::str::from_utf8( + &matcher_data_buffer[json_start.try_into()?..], + )?)?; let request: DigitalCredentialCreationRequest = - serde_json::from_slice(&credman.get_request_buffer())?; + DeJson::deserialize_json(std::str::from_utf8(&credman.get_request_buffer())?)?; if request.requests.iter().any(|r| { ALLOWED_PROTOCOLS.iter().any(|s| r.protocol == *s) && matcher_data @@ -25,11 +30,20 @@ pub fn issuance_main(credman: &mut impl CredmanApi) -> Result<(), Box }, @@ -79,12 +79,12 @@ impl OpenId4VciFilter { } } -#[derive(Deserialize, Debug, Default)] -#[serde(default)] +#[derive(DeJson, Debug, Default)] +#[nserde(default)] pub struct IssuanceMatcherData { - pub entry_id: CString, + pub entry_id: String, pub icon: (usize, usize), - pub title: Option, - pub subtitle: Option, + pub title: Option, + pub subtitle: Option, pub filter: OpenId4VciFilter, } diff --git a/matcher-rs/src/openid4vci.rs b/matcher-rs/src/openid4vci.rs index 1fffef7..30ab32d 100644 --- a/matcher-rs/src/openid4vci.rs +++ b/matcher-rs/src/openid4vci.rs @@ -1,22 +1,22 @@ #![allow(unused)] -use serde::Deserialize; +use nanoserde::DeJson; -#[derive(Deserialize, Debug, Default)] -#[serde(default)] +#[derive(DeJson, Debug, Default)] +#[nserde(default)] pub struct DigitalCredentialCreationRequest { pub requests: Vec, } -#[derive(Deserialize, Debug, Default)] -#[serde(default)] +#[derive(DeJson, Debug, Default)] +#[nserde(default)] pub struct OpenId4VciRequest { pub protocol: String, pub data: OpenId4VciRequestData, } -#[derive(Deserialize, Debug, Default)] -#[serde(default)] +#[derive(DeJson, Debug, Default)] +#[nserde(default)] pub struct OpenId4VciRequestData { pub credential_offer: credential_offer::CredentialOffer, pub credential_issuer_metadata: Option, @@ -57,28 +57,28 @@ impl<'a> From<&'a OpenId4VciRequestData> for RegularizedOpenId4VciRequestData<'a } pub mod credential_offer { - use serde::Deserialize; + use nanoserde::DeJson; use std::collections::HashMap; - #[derive(Deserialize, Debug, Default)] - #[serde(default)] + #[derive(DeJson, Debug, Default)] + #[nserde(default)] pub struct CredentialOffer { pub credential_issuer: String, pub credential_configuration_ids: Vec, pub grants: HashMap, } - #[derive(Deserialize, Debug, Default)] - #[serde(default)] + #[derive(DeJson, Debug, Default)] + #[nserde(default)] pub struct Grant {} } mod credential_issuer_metadata { - use serde::Deserialize; + use nanoserde::DeJson; use std::collections::{HashMap, HashSet}; - #[derive(Deserialize, Debug, Default)] - #[serde(default)] + #[derive(DeJson, Debug, Default)] + #[nserde(default)] pub struct CredentialIssuerMetadata { // pub credential_issuer: String, // pub authorization_servers: Option>, @@ -93,17 +93,17 @@ mod credential_issuer_metadata { pub credential_configurations_supported: HashMap, } - #[derive(Deserialize, Debug, Default)] - #[serde(default)] + #[derive(DeJson, Debug, Default)] + #[nserde(default)] pub struct CredentialRequestEncryption { - // pub jwks: serde_json::Value, + // pub jwks: nanoserde::DeJson, // nanoserde doesn't have a Value type pub enc_values_supported: HashSet, // pub zip_values_supported: Option>, pub encryption_required: bool, } - #[derive(Deserialize, Debug, Default)] - #[serde(default)] + #[derive(DeJson, Debug, Default)] + #[nserde(default)] pub struct CredentialResponseEncryption { pub alg_values_supported: HashSet, pub enc_values_supported: HashSet, @@ -111,58 +111,48 @@ mod credential_issuer_metadata { pub encryption_required: bool, } - #[derive(Deserialize, Debug, Default)] - #[serde(default)] + #[derive(DeJson, Debug, Default)] + #[nserde(default)] pub struct BatchCredentialIssuance { pub batch_size: u32, } - #[derive(Deserialize, Debug, Default)] - #[serde(default)] + #[derive(DeJson, Debug, Default)] + #[nserde(default)] pub struct Display { pub name: String, pub locale: String, pub logo: Option, } - #[derive(Deserialize, Debug, Default)] - #[serde(default)] + #[derive(DeJson, Debug, Default)] + #[nserde(default)] pub struct Logo { pub uri: String, pub alt_text: String, } - #[derive(Deserialize, Debug, Default)] - #[serde(default)] + #[derive(DeJson, Debug, Default)] + #[nserde(default)] pub struct CredentialConfiguration { pub format: String, pub scope: String, pub doctype: String, pub vct: String, - pub credential_signing_alg_values_supported: SiginingAlgs, + pub credential_signing_alg_values_supported: Vec, pub cryptographic_binding_methods_supported: Option>, pub proof_types_supported: HashMap, } - #[derive(Deserialize, Debug)] - #[serde(untagged)] - #[derive(Default)] - pub enum SiginingAlgs { - #[default] - Unspecified, - SringAlgs(Vec), - IntAlgs(Vec), - } - - #[derive(Deserialize, Debug, Default)] - #[serde(default)] + #[derive(DeJson, Debug, Default)] + #[nserde(default)] pub struct ProofType { pub proof_signing_alg_values_supported: Vec, pub key_attestations_required: Option, } - #[derive(Deserialize, Debug, Default)] - #[serde(default)] + #[derive(DeJson, Debug, Default)] + #[nserde(default)] pub struct KeyAttestationsRequired { pub key_storage: Option>, pub user_authentication: Option>, From 67906ede13a063409dbe2b2d77cf6ce9ddea0752 Mon Sep 17 00:00:00 2001 From: Siyuan Ren Date: Tue, 10 Mar 2026 05:50:06 +0000 Subject: [PATCH 2/2] Add a build script to minimize wasm size --- matcher-rs/build.sh | 16 ++++++++ matcher-rs/src/issuance.rs | 77 +++++++++++++------------------------- 2 files changed, 41 insertions(+), 52 deletions(-) create mode 100644 matcher-rs/build.sh diff --git a/matcher-rs/build.sh b/matcher-rs/build.sh new file mode 100644 index 0000000..fcc2900 --- /dev/null +++ b/matcher-rs/build.sh @@ -0,0 +1,16 @@ +# 1. Build with maximum rustc optimizations +CARGO_PROFILE_RELEASE_PANIC=immediate-abort \ +CARGO_PROFILE_RELEASE_OPT_LEVEL="z" \ +CARGO_PROFILE_RELEASE_CODEGEN_UNITS=1 \ +CARGO_PROFILE_RELEASE_STRIP=true \ +cargo +nightly build \ + -Z panic-immediate-abort \ + -Z build-std \ + --target wasm32-unknown-unknown \ + --release + +# 2. Further shrink using wasm-opt (if available) +wasm-opt -Oz --strip-debug --enable-bulk-memory \ + target/wasm32-unknown-unknown/release/issuance.wasm \ + -o target/wasm32-unknown-unknown/release/issuance.wasm + diff --git a/matcher-rs/src/issuance.rs b/matcher-rs/src/issuance.rs index e092495..766b5fa 100644 --- a/matcher-rs/src/issuance.rs +++ b/matcher-rs/src/issuance.rs @@ -315,63 +315,36 @@ mod test { "entry_id": "C", "title": "TTTT", "subtitle": "SSSSS", - "icon": [0, 0], + "icon": [ + 0, + 0 + ], "filter": { - "SupportsMdocDoctype": { - "doctypes": ["org.iso.18013.5.1.mDL"] - } - } -}"#, - icon: Vec::new(), - added_entries: Vec::new(), - }; - - issuance_main(&mut credman).unwrap(); - - assert_eq!(credman.added_entries.len(), 1); - } - - #[test] - fn match_mdoc_with_algs() { - let mut credman = FakeCredman { - request_json: r#" -{ - "requests": [ - { - "protocol": "openid4vci-1.1", - "data": { - "credential_offer": { - "credential_issuer": "https://issuer.my", - "credential_configuration_ids": [ - "FICTITIOUS_STATE_MDL" - ], - "grants": { - "authorization_code": {} + "Or": { + "filters": [ + { + "AllowsConfigurationIds": { + "configuration_ids": [ + "US_SOCIAL_SECURITY_NUMBER", + "EU_AGE" + ] } }, - "credential_issuer_metadata": { - "nonce_endpoint": "https://nonce.my", - "credential_configurations_supported": { - "FICTITIOUS_STATE_MDL": { - "format": "mso_mdoc", - "doctype": "org.iso.18013.5.1.mDL", - "credential_signing_alg_values_supported": ["ES256", "ES384"] - } + { + "AllowsIssuers": { + "issuers": [ + "ccb" + ] + } + }, + { + "SupportsMdocDoctype": { + "doctypes": [ + "org.iso.18013.5.1.mDL" + ] } } - } - } - ] -}"#, - registered_json: r#" -{ - "entry_id": "C", - "title": "TTTT", - "subtitle": "SSSSS", - "icon": [0, 0], - "filter": { - "SupportsMdocDoctype": { - "doctypes": ["org.iso.18013.5.1.mDL"] + ] } } }"#,