Skip to content

Commit

Permalink
Update Bitstring Status List implementation to Candidate Recommendati…
Browse files Browse the repository at this point in the history
…on Draft 10 June 2024.
  • Loading branch information
timothee-haudebourg committed Sep 5, 2024
1 parent 0b26eac commit 8987e13
Show file tree
Hide file tree
Showing 13 changed files with 477 additions and 167 deletions.
2 changes: 1 addition & 1 deletion crates/status/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ parking_lot = "0.12.1"
flate2 = "1.0.28"

[dev-dependencies]
ssi-jwk = { workspace = true, features = ["secp256r1"] }
ssi-jws = { workspace = true, features = ["secp256r1"] }
ssi-dids.workspace = true
ssi-data-integrity = { workspace = true, features = ["w3c"] }
tokio = { version = "1.0", features = ["macros", "rt"] }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
"proof": {
"@context": "https://w3id.org/security/suites/jws-2020/v1",
"type": "JsonWebSignature2020",
"created": "2024-04-15T14:53:55.745Z",
"created": "2024-09-05T12:10:49.127Z",
"verificationMethod": "did:jwk:eyJhbGciOiJFUzI1NiIsImNydiI6IlAtMjU2Iiwia3R5IjoiRUMiLCJ1c2UiOiJzaWciLCJ4IjoiRnlHbnZLcXJ5cWlzX3gwWHJTbENTbnpFeGlrSk5XLUgzY0hQWnRfZjBmUSIsInkiOiJKZGJUM1BJWllIdHdzNVprZUlLakM5RnhJaGZwYV9rbHVJZms5ekZwczZzIn0#0",
"proofPurpose": "assertionMethod",
"jws": "eyJhbGciOiJFUzI1NiIsImNyaXQiOlsiYjY0Il0sImI2NCI6ZmFsc2V9..VcTAx3Rnt6rHn6EQTOdA1T6bywuySmiq3ik8Ldhbb1TETNFGnrWR80210yikaZKJGtduEdPquQFNTZZ0xvRyiw"
"jws": "eyJhbGciOiJFUzI1NiIsImNyaXQiOlsiYjY0Il0sImI2NCI6ZmFsc2V9..jxE8WqQwJ8FDmkk3njwU80kuVkPsmL_5b5hcMJQO2Tz5D-GqZ_TsTlXMDg2cxPiS1IcK11Gtz2xvK4d0i8U1PA"
}
}
8 changes: 8 additions & 0 deletions crates/status/examples/files/status_list_revocable_1.jsonld
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,13 @@
"credentialSubject": {
"id": "did:example:6789",
"type": "Person"
},
"proof": {
"@context": "https://w3id.org/security/suites/jws-2020/v1",
"type": "JsonWebSignature2020",
"created": "2024-09-05T12:29:55.727Z",
"verificationMethod": "did:jwk:eyJhbGciOiJFUzI1NiIsImNydiI6IlAtMjU2Iiwia3R5IjoiRUMiLCJ1c2UiOiJzaWciLCJ4IjoiRnlHbnZLcXJ5cWlzX3gwWHJTbENTbnpFeGlrSk5XLUgzY0hQWnRfZjBmUSIsInkiOiJKZGJUM1BJWllIdHdzNVprZUlLakM5RnhJaGZwYV9rbHVJZms5ekZwczZzIn0#0",
"proofPurpose": "assertionMethod",
"jws": "eyJhbGciOiJFUzI1NiIsImNyaXQiOlsiYjY0Il0sImI2NCI6ZmFsc2V9..ymlXI3xL878kA_6F160NKkPM1UfdRCe9L-KKD3P0MSuvkV6uJc41VB1-jKdF_Nb8XM8MJLSTVJp3M6aC2Jbp2g"
}
}
8 changes: 8 additions & 0 deletions crates/status/examples/files/status_list_revocable_3.jsonld
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,13 @@
"credentialSubject": {
"id": "did:example:6789",
"type": "Person"
},
"proof": {
"@context": "https://w3id.org/security/suites/jws-2020/v1",
"type": "JsonWebSignature2020",
"created": "2024-09-05T12:30:26.917Z",
"verificationMethod": "did:jwk:eyJhbGciOiJFUzI1NiIsImNydiI6IlAtMjU2Iiwia3R5IjoiRUMiLCJ1c2UiOiJzaWciLCJ4IjoiRnlHbnZLcXJ5cWlzX3gwWHJTbENTbnpFeGlrSk5XLUgzY0hQWnRfZjBmUSIsInkiOiJKZGJUM1BJWllIdHdzNVprZUlLakM5RnhJaGZwYV9rbHVJZms5ekZwczZzIn0#0",
"proofPurpose": "assertionMethod",
"jws": "eyJhbGciOiJFUzI1NiIsImNyaXQiOlsiYjY0Il0sImI2NCI6ZmFsc2V9..XElrILKSLhlRVpzIw_06OxLP4JN-CJKOrHKECr4wOmro8QpmDad9jeSeIvbU9zrt49nIel3c9ztzmBJgfeOv9g"
}
}
18 changes: 11 additions & 7 deletions crates/status/examples/status_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use ssi_dids::{VerificationMethodDIDResolver, DIDJWK};
use ssi_jwk::JWK;
use ssi_status::{
any::AnyStatusMap, bitstring_status_list, EncodedStatusMap, FromBytes, FromBytesOptions,
StatusSizeError,
};
use ssi_verification_methods::{ReferenceOrOwned, SingleSecretSigner};
use std::{
Expand Down Expand Up @@ -62,6 +63,9 @@ enum Command {
/// Input media type.
#[clap(short = 't', long)]
media_type: String,

/// Status size in bits.
status_size: Option<u8>,
},

/// Create a new status list.
Expand Down Expand Up @@ -112,6 +116,7 @@ impl Command {
Self::Read {
filename,
media_type,
status_size,
} => {
let source = filename.map(Source::File).unwrap_or_default();
let bytes = match source.read() {
Expand All @@ -133,7 +138,7 @@ impl Command {
.decode()
.map_err(|e| Error::Decode(source, e))?;

let list: Vec<_> = status_list.iter().collect();
let list: Vec<_> = status_list.iter(status_size)?.collect();

println!("{}", serde_json::to_string_pretty(&list).unwrap());
Ok(())
Expand All @@ -152,7 +157,7 @@ async fn create_bitstring_status_list(
list: Vec<StatusValue>,
key: Option<PathBuf>,
) -> Result<Vec<u8>, Error> {
let mut status_list = bitstring_status_list::StatusList::new(
let mut status_list = bitstring_status_list::SizedStatusList::new(
bitstring_status_list::StatusSize::default(),
bitstring_status_list::TimeToLive::default(),
// list.into_iter().map(|v| v.0).collect(),
Expand All @@ -164,11 +169,7 @@ async fn create_bitstring_status_list(

let credential = bitstring_status_list::BitstringStatusListCredential::new(
Some(id),
status_list.to_credential_subject(
None,
bitstring_status_list::StatusPurpose::Revocation,
Vec::new(),
),
status_list.to_credential_subject(None, bitstring_status_list::StatusPurpose::Revocation),
);

match key {
Expand Down Expand Up @@ -212,6 +213,9 @@ enum Error {

#[error("unable to read key: {0}")]
Key(#[from] KeyError),

#[error(transparent)]
StatusSize(#[from] StatusSizeError),
}

#[derive(Debug, thiserror::Error)]
Expand Down
1 change: 1 addition & 0 deletions crates/status/examples/status_list_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ async fn run(args: Args) -> Result<(), Error> {

let status = status_list
.get_entry(&entry)
.unwrap()
.ok_or(Error::MissingEntry(entry.key()))?;

match status {
Expand Down
44 changes: 29 additions & 15 deletions crates/status/src/impl/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::{
},
token_status_list::{self, StatusListToken},
EncodedStatusMap, FromBytes, FromBytesOptions, StatusMap, StatusMapEntry, StatusMapEntrySet,
StatusSizeError,
};

pub enum AnyStatusMap {
Expand Down Expand Up @@ -108,16 +109,22 @@ pub enum AnyDecodedStatusMap {
}

impl AnyDecodedStatusMap {
pub fn iter(&self) -> AnyDecodedStatusMapIter {
pub fn iter(
&self,
status_size: Option<u8>,
) -> Result<AnyDecodedStatusMapIter, StatusSizeError> {
match self {
Self::BitstringStatusList(m) => AnyDecodedStatusMapIter::BitstringStatusList(m.iter()),
Self::TokenStatusList(m) => AnyDecodedStatusMapIter::TokenStatusList(m.iter()),
Self::BitstringStatusList(m) => Ok(AnyDecodedStatusMapIter::BitstringStatusList(
m.iter(status_size.ok_or(StatusSizeError::Missing)?.try_into()?),
)),
Self::TokenStatusList(m) => Ok(AnyDecodedStatusMapIter::TokenStatusList(m.iter())),
}
}
}

impl StatusMap for AnyDecodedStatusMap {
type Key = usize;
type StatusSize = u8;
type Status = u8;

fn time_to_live(&self) -> Option<std::time::Duration> {
Expand All @@ -127,23 +134,22 @@ impl StatusMap for AnyDecodedStatusMap {
}
}

fn get_by_key(&self, key: Self::Key) -> Option<Self::Status> {
fn get_by_key(
&self,
status_size: Option<u8>,
key: Self::Key,
) -> Result<Option<Self::Status>, StatusSizeError> {
match self {
Self::BitstringStatusList(m) => m.get_by_key(key),
Self::TokenStatusList(m) => m.get_by_key(key),
Self::BitstringStatusList(m) => {
m.get_by_key(status_size.map(TryInto::try_into).transpose()?, key)
}
Self::TokenStatusList(m) => {
m.get_by_key(status_size.map(TryInto::try_into).transpose()?, key)
}
}
}
}

impl<'a> IntoIterator for &'a AnyDecodedStatusMap {
type IntoIter = AnyDecodedStatusMapIter<'a>;
type Item = u8;

fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}

pub enum AnyDecodedStatusMapIter<'a> {
BitstringStatusList(bitstring_status_list::BitStringIter<'a>),
TokenStatusList(token_status_list::BitStringIter<'a>),
Expand Down Expand Up @@ -239,6 +245,7 @@ pub enum AnyStatusMapEntryRef<'a> {

impl<'a> StatusMapEntry for AnyStatusMapEntryRef<'a> {
type Key = usize;
type StatusSize = u8;

fn status_list_url(&self) -> &Uri {
match self {
Expand All @@ -253,4 +260,11 @@ impl<'a> StatusMapEntry for AnyStatusMapEntryRef<'a> {
Self::TokenStatusList(e) => e.key(),
}
}

fn status_size(&self) -> Option<Self::StatusSize> {
match self {
Self::BitstringStatusList(e) => e.status_size().map(Into::into),
Self::TokenStatusList(e) => e.status_size().map(Into::into),
}
}
}
Loading

0 comments on commit 8987e13

Please sign in to comment.