-
-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Delegation Builder #20
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## v1.0-rc.1 #20 +/- ##
=============================================
+ Coverage 12.84% 13.67% +0.82%
=============================================
Files 68 68
Lines 5620 5711 +91
Branches 2703 2724 +21
=============================================
+ Hits 722 781 +59
Misses 4307 4307
- Partials 591 623 +32
|
Good call on not doing it in this PR. IMO I still want to find a solution so it's a little less visual noise eventually. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like it.
I see why we need both DelegationRequired
and DelegationBuilder
(because both are still not signed, and Delegation
is then signed and "finalized").
Also here's a soft-proposal (I don't expect this PR needs any changes):
Renames:
Delegation
->SignedDelegation
DelegationRequired
->Delegation
to_builder
->builder
(IMO I liked this kind of naming from tokio & iroh)try_finalize
->try_sign
And then make builder
a required call & explicit. And remove all with_
calls from DelegationRequired
. So you end up with this:
Delegation {
subject: Subject::Known(alice),
issuer: alice,
audience: bob,
command: "/".to_string(),
signer: alice_signer,
codec: encoding::Preset::DagCbor,
varsig_header: header::Preset::EdDsa(header::EdDsaHeader {
codec: encoding::Preset::DagCbor,
})
}::builder()
.with_via(carol)
.with_policy(vec![])
.with_metadata(BTreeMap::from_iter([("foo".into(), 123.into())]))
.try_sign()
That said, it's kinda unfortunate to use the Delegation
name to an unimportant struct like that.
pub fn subject(&self) -> &Subject<DID> { | ||
&self.payload.subject | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we change this, then a petition to keep it consistent with how via()
, not_before()
and expiration()
work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How's that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah. There are two changes at the same time: From Option
-> Subject
and from T<&S>
to &T<S>
. I missed the first.
Can we implement Subject::as_ref(&self) -> Subject<&T>
and make this return Subject<&DID>
?
pub audience: DID, | ||
pub command: String, | ||
|
||
pub codec: PhantomData<C>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we absolutely need the codec
PhantomData
? Can't rust figure out that it's "inside" the V: varsig::Header<C>
? Just double-checking.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I'm also not happy about it. I've tried a bunch of things, but I don't think it's possible. Open to ideas!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah. Weird. It's not needed in Delegation::try_sign
. I guess the inference in functions is better than in structs. :/
I've tried to avoid similar in the spec, because its not "done" until it's signed — I want to make sure that people don't skip this step, and making it the simple term helps imply that. Also I've noticed that the ergonomics are different in construction vs consumption: on construction the "main thing" you interact with is unsigned, but on consumption the main thing must be signed. |
I've seen this pattern as |
Oh, that's what I had originally: I thought you wanted the |
Hmmm 🤔 |
Sooo pub fn not_before(mut self, not_before: Timestamp) -> DelegationBuilder<DID, V, C> {
self.not_before = Some(not_before);
self
} Why not just let d = DelegationRequired {
subject: Subject::Known(alice),
issuer: alice,
audience: bob,
command: "/".to_string(),
signer: alice_signer,
codec: encoding::Preset::DagCbor,
varsig_header: header::Preset::EdDsa(header::EdDsaHeader {
codec: encoding::Preset::DagCbor,
})
}.to_builder();
d.via = Some(carol);
d.policy = vec![];
d.metadata = BTreeMap::from_iter([("foo".into(), 123.into())]);
d.try_finalize() |
It would've kinda made sense together with the rename from
Yeah - I changed my mind about that. Another FWIW, this is how I create delegations in fission-server tests right now (not depending on this PR yet): let ucan = Delegation::try_sign(
&issuer,
varsig_header(),
delegation::PayloadBuilder::default()
.issuer(issuer_did)
.audience(audience_did)
.subject(Some(resource_did))
.command("/".to_string())
.build()?,
)?; ( |
We can change the naming, but figured let's do one of these to figure out how we want to manage this pattern going forward. Overall I like where it landed, though I did the boiler-plate-y thing and made the interface extremely OO with some methods on
DelegationRequired
that implicitly convert toDelegationBuilder
without requiring an explicit call to.to_builder()
.I attempted to automatically build the varsig header from the signer + codec, but that won't work super well once we have more than the simplest of signature types, so I reverted those changes.
This code also uses the more common by-ownership version of builder, which lets you easily chain the calls. I previously has this as a series of
&mut
s, but it was less ergonomic; it can be useful in some cases, but I doubt that we'll need to reuse partially-built delegations as a factory.