From 96b0fe10c88677953dc0cd2b3dc34932c4f85f31 Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Mon, 25 Mar 2024 19:25:55 -0700 Subject: [PATCH 1/2] Receipts as invocations --- src/ability/ucan/assert.rs | 11 ++--- src/delegation/policy/selector/filter.rs | 2 +- src/delegation/policy/selector/select.rs | 61 ++++++++++++++---------- 3 files changed, 43 insertions(+), 31 deletions(-) diff --git a/src/ability/ucan/assert.rs b/src/ability/ucan/assert.rs index 62946c23..5fe7c874 100644 --- a/src/ability/ucan/assert.rs +++ b/src/ability/ucan/assert.rs @@ -1,6 +1,6 @@ use crate::ability::command::Command; use crate::task::Task; -use libipld_core::{cid::Cid, ipld::Ipld}; +use libipld_core::cid::Cid; // Things that you can assert include content and receipts @@ -8,12 +8,11 @@ use libipld_core::{cid::Cid, ipld::Ipld}; pub struct Ran { ran: Cid, out: Box>, - fx: Vec, // FIXME may be more than "just" a task + next: Vec, // FIXME may be more than "just" a task } impl Command for Ran { - const COMMAND: &'static str = "/ucan/assert/ran"; - // const COMMAND: &'static str = "/ucan/ran";???? + const COMMAND: &'static str = "/ucan/ran"; } /////////////// @@ -23,8 +22,8 @@ impl Command for Ran { #[derive(Debug, PartialEq)] pub struct Claim { claim: T, -} // Where Ipld: From +} impl Command for Claim { - const COMMAND: &'static str = "/ucan/assert/claim"; + const COMMAND: &'static str = "/ucan/claim"; } diff --git a/src/delegation/policy/selector/filter.rs b/src/delegation/policy/selector/filter.rs index 96343a5a..7e69ec8e 100644 --- a/src/delegation/policy/selector/filter.rs +++ b/src/delegation/policy/selector/filter.rs @@ -297,7 +297,7 @@ mod tests { use super::*; proptest! { - #[test] + #[test_log::test] fn test_filter_round_trip(filter: Filter) { let serialized = filter.to_string(); let deserialized = serialized.parse(); diff --git a/src/delegation/policy/selector/select.rs b/src/delegation/policy/selector/select.rs index 7506cc63..9d5270ed 100644 --- a/src/delegation/policy/selector/select.rs +++ b/src/delegation/policy/selector/select.rs @@ -1,7 +1,6 @@ -use super::Selector; // FIXME cycle? +use super::Selector; use super::{error::SelectorErrorReason, filter::Filter, Selectable, SelectorError}; use libipld_core::ipld::Ipld; -use serde::{Deserialize, Serialize}; use std::cmp::Ordering; use std::fmt; use std::str::FromStr; @@ -200,27 +199,35 @@ mod tests { use proptest::prelude::*; use testresult::TestResult; + fn simple() -> Ipld { + libipld::ipld!({ + "foo": 42, + "bar": "baz", + "qux": true + }) + } + + fn email() -> Ipld { + libipld::ipld!({ + "from": "alice@example.com", + "to": ["bob@example.com", "fraud@example.com"], + "cc": ["carol@example.com"], + "subject": "Quarterly Reports", + "body": "Here's Q2 the reports ..." + }) + } + + fn nested_data() -> Ipld { + libipld::ipld!({ + "name": "Alice", + "age": 42, + "friends": ["Bob", "Charlie"] + }) + } + mod get { use super::*; - fn nested_data() -> Ipld { - Ipld::Map( - vec![ - ("name".to_string(), Ipld::String("Alice".to_string())), - ("age".to_string(), Ipld::Integer(42)), - ( - "friends".to_string(), - Ipld::List(vec![ - Ipld::String("Bob".to_string()), - Ipld::String("Charlie".to_string()), - ]), - ), - ] - .into_iter() - .collect(), - ) - } - proptest! { #[test_log::test] fn test_identity(data: ipld::Newtype) { @@ -248,13 +255,19 @@ mod tests { let selector: Select = Select::new(filters); let cleaned_data = match data.0.clone() { - Ipld::Map(mut m) => { - m.remove("foo").map_or(Ipld::Null, |v| v) - } - ipld => ipld + Ipld::Map(mut m) => m.remove("foo").map_or(Ipld::Null, |v| v), + ipld => ipld, }; prop_assert_eq!(selector.get(&cleaned_data)?, Ipld::Null); } } + + #[test_log::test] + fn test_eq_dot_field_ending_try_null() -> TestResult { + let s = Select::from_str(".from.not?")?; + + pretty::assert_eq!(s.get(&email()), Ok(Ipld::Null)); + Ok(()) + } } } From 4913ad0d6c4c389c0374773b97de546c0c91f428 Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Mon, 25 Mar 2024 19:42:35 -0700 Subject: [PATCH 2/2] Require Subject on get_chain --- src/ability/ucan/assert.rs | 11 +++-- src/delegation/agent.rs | 38 +++++++-------- src/delegation/policy/selector/filter.rs | 2 +- src/delegation/policy/selector/select.rs | 61 ++++++++++-------------- src/delegation/store/memory.rs | 32 ++++++------- src/delegation/store/traits.rs | 8 ++-- src/invocation/agent.rs | 4 +- 7 files changed, 68 insertions(+), 88 deletions(-) diff --git a/src/ability/ucan/assert.rs b/src/ability/ucan/assert.rs index 5fe7c874..62946c23 100644 --- a/src/ability/ucan/assert.rs +++ b/src/ability/ucan/assert.rs @@ -1,6 +1,6 @@ use crate::ability::command::Command; use crate::task::Task; -use libipld_core::cid::Cid; +use libipld_core::{cid::Cid, ipld::Ipld}; // Things that you can assert include content and receipts @@ -8,11 +8,12 @@ use libipld_core::cid::Cid; pub struct Ran { ran: Cid, out: Box>, - next: Vec, // FIXME may be more than "just" a task + fx: Vec, // FIXME may be more than "just" a task } impl Command for Ran { - const COMMAND: &'static str = "/ucan/ran"; + const COMMAND: &'static str = "/ucan/assert/ran"; + // const COMMAND: &'static str = "/ucan/ran";???? } /////////////// @@ -22,8 +23,8 @@ impl Command for Ran { #[derive(Debug, PartialEq)] pub struct Claim { claim: T, -} +} // Where Ipld: From impl Command for Claim { - const COMMAND: &'static str = "/ucan/claim"; + const COMMAND: &'static str = "/ucan/assert/claim"; } diff --git a/src/delegation/agent.rs b/src/delegation/agent.rs index 16482c14..23c1b0cf 100644 --- a/src/delegation/agent.rs +++ b/src/delegation/agent.rs @@ -62,7 +62,7 @@ where pub fn delegate( &self, audience: DID, - subject: Option, + subject: &DID, via: Option, command: String, new_policy: Vec, @@ -75,25 +75,21 @@ where let mut salt = self.did.clone().to_string().into_bytes(); let nonce = Nonce::generate_12(&mut salt); - if let Some(ref sub) = subject { - if sub == &self.did { - let payload: Payload = Payload { - issuer: self.did.clone(), - audience, - subject, - via, - command, - metadata, - nonce, - expiration: expiration.into(), - not_before: not_before.map(Into::into), - policy: new_policy, - }; - - return Ok( - Delegation::try_sign(&self.signer, varsig_header, payload).expect("FIXME") - ); - } + if *subject == self.did { + let payload: Payload = Payload { + issuer: self.did.clone(), + audience, + subject: Some(subject.clone()), + via, + command, + metadata, + nonce, + expiration: expiration.into(), + not_before: not_before.map(Into::into), + policy: new_policy, + }; + + return Ok(Delegation::try_sign(&self.signer, varsig_header, payload).expect("FIXME")); } let proofs = &self @@ -109,7 +105,7 @@ where let payload: Payload = Payload { issuer: self.did.clone(), audience, - subject, + subject: Some(subject.clone()), via, command, policy, diff --git a/src/delegation/policy/selector/filter.rs b/src/delegation/policy/selector/filter.rs index 7e69ec8e..96343a5a 100644 --- a/src/delegation/policy/selector/filter.rs +++ b/src/delegation/policy/selector/filter.rs @@ -297,7 +297,7 @@ mod tests { use super::*; proptest! { - #[test_log::test] + #[test] fn test_filter_round_trip(filter: Filter) { let serialized = filter.to_string(); let deserialized = serialized.parse(); diff --git a/src/delegation/policy/selector/select.rs b/src/delegation/policy/selector/select.rs index 9d5270ed..7506cc63 100644 --- a/src/delegation/policy/selector/select.rs +++ b/src/delegation/policy/selector/select.rs @@ -1,6 +1,7 @@ -use super::Selector; +use super::Selector; // FIXME cycle? use super::{error::SelectorErrorReason, filter::Filter, Selectable, SelectorError}; use libipld_core::ipld::Ipld; +use serde::{Deserialize, Serialize}; use std::cmp::Ordering; use std::fmt; use std::str::FromStr; @@ -199,35 +200,27 @@ mod tests { use proptest::prelude::*; use testresult::TestResult; - fn simple() -> Ipld { - libipld::ipld!({ - "foo": 42, - "bar": "baz", - "qux": true - }) - } - - fn email() -> Ipld { - libipld::ipld!({ - "from": "alice@example.com", - "to": ["bob@example.com", "fraud@example.com"], - "cc": ["carol@example.com"], - "subject": "Quarterly Reports", - "body": "Here's Q2 the reports ..." - }) - } - - fn nested_data() -> Ipld { - libipld::ipld!({ - "name": "Alice", - "age": 42, - "friends": ["Bob", "Charlie"] - }) - } - mod get { use super::*; + fn nested_data() -> Ipld { + Ipld::Map( + vec![ + ("name".to_string(), Ipld::String("Alice".to_string())), + ("age".to_string(), Ipld::Integer(42)), + ( + "friends".to_string(), + Ipld::List(vec![ + Ipld::String("Bob".to_string()), + Ipld::String("Charlie".to_string()), + ]), + ), + ] + .into_iter() + .collect(), + ) + } + proptest! { #[test_log::test] fn test_identity(data: ipld::Newtype) { @@ -255,19 +248,13 @@ mod tests { let selector: Select = Select::new(filters); let cleaned_data = match data.0.clone() { - Ipld::Map(mut m) => m.remove("foo").map_or(Ipld::Null, |v| v), - ipld => ipld, + Ipld::Map(mut m) => { + m.remove("foo").map_or(Ipld::Null, |v| v) + } + ipld => ipld }; prop_assert_eq!(selector.get(&cleaned_data)?, Ipld::Null); } } - - #[test_log::test] - fn test_eq_dot_field_ending_try_null() -> TestResult { - let s = Select::from_str(".from.not?")?; - - pretty::assert_eq!(s.get(&email()), Ok(Ipld::Null)); - Ok(()) - } } } diff --git a/src/delegation/store/memory.rs b/src/delegation/store/memory.rs index a0cd4ec1..bdc7e6e7 100644 --- a/src/delegation/store/memory.rs +++ b/src/delegation/store/memory.rs @@ -198,11 +198,10 @@ where Ok(()) } - // FIXME take a PayloadBuilder fn get_chain( &self, aud: &DID, - subject: &Option, + subject: &DID, command: String, policy: Vec, now: SystemTime, @@ -213,7 +212,10 @@ where let read_tx = self.read(); let all_powerlines = read_tx.index.get(&None).unwrap_or(&blank_map); - let all_aud_for_subject = read_tx.index.get(subject).unwrap_or(&blank_map); + let all_aud_for_subject = read_tx + .index + .get(&Some(subject.clone())) + .unwrap_or(&blank_map); let powerline_candidates = all_powerlines.get(aud).unwrap_or(&blank_set); let sub_candidates = all_aud_for_subject.get(aud).unwrap_or(&blank_set); @@ -411,13 +413,14 @@ mod tests { #[test_log::test] fn test_simple_fail() -> TestResult { let (server, _server_signer) = gen_did(); + let (nope, _nope_signer) = gen_did(); let store = MemoryStore::< did::preset::Verifier, varsig::header::Preset, varsig::encoding::Preset, >::default(); - let got = store.get_chain(&server, &None, "/".into(), vec![], SystemTime::now())?; + let got = store.get_chain(&server, &nope, "/".into(), vec![], SystemTime::now())?; pretty::assert_eq!(got, None); Ok(()) @@ -449,7 +452,7 @@ mod tests { store.insert(deleg.clone())?; - let got = store.get_chain(&bob, &Some(alice), "/".into(), vec![], SystemTime::now())?; + let got = store.get_chain(&bob, &alice, "/".into(), vec![], SystemTime::now())?; pretty::assert_eq!(got, Some(nonempty![(deleg.cid()?, Arc::new(deleg))].into())); Ok(()) } @@ -509,7 +512,7 @@ mod tests { store.insert(more_noise.clone())?; - let got = store.get_chain(&bob, &Some(alice), "/".into(), vec![], SystemTime::now())?; + let got = store.get_chain(&bob, &alice, "/".into(), vec![], SystemTime::now())?; pretty::assert_eq!(got, Some(nonempty![(deleg.cid()?, Arc::new(deleg))].into())); Ok(()) } @@ -555,8 +558,7 @@ mod tests { store.insert(deleg_2.clone())?; - let got = - store.get_chain(&carol, &Some(alice), "/".into(), vec![], SystemTime::now())?; + let got = store.get_chain(&carol, &alice, "/".into(), vec![], SystemTime::now())?; pretty::assert_eq!( got, @@ -614,7 +616,7 @@ mod tests { let got = store.get_chain( &carol, - &Some(alice), + &alice, "/test/me/now".into(), vec![], SystemTime::now(), @@ -677,7 +679,7 @@ mod tests { let got = store.get_chain( &carol, - &Some(alice), + &alice, "/test/me/now".into(), vec![], SystemTime::now(), @@ -751,7 +753,7 @@ mod tests { store.insert(alice_to_bob.clone())?; let got: Vec = store - .get_chain(&dave, &Some(alice), "/".into(), vec![], SystemTime::now()) + .get_chain(&dave, &alice, "/".into(), vec![], SystemTime::now()) .map_err(|e| e.to_string())? .ok_or("failed during proof lookup")? .iter() @@ -835,13 +837,7 @@ mod tests { store.insert(alice_to_bob.clone())?; let got: Vec = store - .get_chain( - &dave, - &Some(alice.clone()), - "/".into(), - vec![], - SystemTime::now(), - ) + .get_chain(&dave, &alice.clone(), "/".into(), vec![], SystemTime::now()) .map_err(|e| e.to_string())? .ok_or("failed during proof lookup")? .iter() diff --git a/src/delegation/store/traits.rs b/src/delegation/store/traits.rs index 0e79f1fe..0ace1c73 100644 --- a/src/delegation/store/traits.rs +++ b/src/delegation/store/traits.rs @@ -49,7 +49,7 @@ where fn get_chain( &self, audience: &DID, - subject: &Option, + subject: &DID, command: String, policy: Vec, now: SystemTime, @@ -58,7 +58,7 @@ where fn get_chain_cids( &self, audience: &DID, - subject: &Option, + subject: &DID, command: String, policy: Vec, now: SystemTime, @@ -75,7 +75,7 @@ where policy: Vec, now: SystemTime, ) -> Result { - self.get_chain(audience, &Some(issuer), command, policy, now) + self.get_chain(audience, &issuer, command, policy, now) .map(|chain| chain.is_some()) } @@ -124,7 +124,7 @@ where fn get_chain( &self, audience: &DID, - subject: &Option, + subject: &DID, command: String, policy: Vec, now: SystemTime, diff --git a/src/invocation/agent.rs b/src/invocation/agent.rs index 158f49c2..3929e728 100644 --- a/src/invocation/agent.rs +++ b/src/invocation/agent.rs @@ -104,7 +104,7 @@ where self.delegation_store .get_chain( &self.did, - &Some(subject.clone()), + &subject.clone(), ability.to_command(), vec![], now, @@ -695,7 +695,7 @@ mod tests { let chain_for_dnslink: Vec = del_store .get_chain( &device, - &Some(dnslink.clone()), + &dnslink.clone(), "/".into(), vec![], SystemTime::now(),