-
Notifications
You must be signed in to change notification settings - Fork 2
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
Receipt writing #1
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package delegation | ||
|
||
import ( | ||
"github.com/web3-storage/go-ucanto/core/dag/blockstore" | ||
"github.com/web3-storage/go-ucanto/core/ipld" | ||
"github.com/web3-storage/go-ucanto/ucan" | ||
) | ||
|
||
type Proof struct { | ||
delegation Delegation | ||
link ucan.Link | ||
} | ||
|
||
func (p Proof) Delegation() (Delegation, bool) { | ||
return p.delegation, p.delegation != nil | ||
} | ||
|
||
func (p Proof) Link() ucan.Link { | ||
if p.delegation != nil { | ||
return p.delegation.Link() | ||
} | ||
return p.link | ||
} | ||
|
||
func FromDelegation(delegation Delegation) Proof { | ||
return Proof{delegation, nil} | ||
} | ||
|
||
func FromLink(link ucan.Link) Proof { | ||
return Proof{nil, link} | ||
} | ||
|
||
type Proofs []Proof | ||
|
||
func NewProofsView(links []ipld.Link, bs blockstore.BlockReader) Proofs { | ||
proofs := make(Proofs, 0, len(links)) | ||
for _, link := range links { | ||
if delegation, err := NewDelegationView(link, bs); err == nil { | ||
proofs = append(proofs, FromDelegation(delegation)) | ||
} else { | ||
proofs = append(proofs, FromLink(link)) | ||
} | ||
} | ||
return proofs | ||
} | ||
|
||
// Encode writes a set of proofs, some of which may be full delegations to a blockstore | ||
func (proofs Proofs) Encode(bs blockstore.BlockWriter) ([]ipld.Link, error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "Encode" to me is a function that transforms some data structure into another. This function is more like a utility to write a set of blocks into a blockstore as a convenience (I appreciate each block gets encoded as side effect). I'd perhaps rename to That said, it's a little confusing that this may or may not write blocks to a blockstore, depending on whether the instance is backed by an actual delegation. I can imagine it causing bugs that may be tricky to track down. I propose removing this function and instead move the logic to where it is used, so it can be seen to be explicitly handled, I don't think there are multiple usages anyway(?) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. so it's worth noting that all over the JS code this "maybe present" for proofs exists -- also for the invocatin in the receipt. I'd say see if you need it while working on the validator / server. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. note that this is actually present in the JS delegation as well as receipt. I don't quite know what that implies, but it seems the goal is to be able to construct receipts and invocations without every block for every proof. |
||
links := make([]ucan.Link, 0, len(proofs)) | ||
for _, p := range proofs { | ||
links = append(links, p.Link()) | ||
if delegation, isDelegation := p.Delegation(); isDelegation { | ||
err := blockstore.Encode(delegation, bs) | ||
if err != nil { | ||
return nil, err | ||
} | ||
} | ||
} | ||
return links, nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,3 +35,34 @@ type IssuedInvocation interface { | |
func Invoke(issuer ucan.Signer, audience ucan.Principal, capability ucan.Capability[ucan.CaveatBuilder], options ...delegation.Option) (IssuedInvocation, error) { | ||
return delegation.Delegate(issuer, audience, []ucan.Capability[ucan.CaveatBuilder]{capability}, options...) | ||
} | ||
|
||
type Ran struct { | ||
invocation Invocation | ||
link ucan.Link | ||
} | ||
|
||
func (r Ran) Invocation() (Invocation, bool) { | ||
return r.invocation, r.invocation != nil | ||
} | ||
|
||
func (r Ran) Link() ucan.Link { | ||
if r.invocation != nil { | ||
return r.invocation.Link() | ||
} | ||
return r.link | ||
} | ||
|
||
func FromInvocation(invocation Invocation) Ran { | ||
return Ran{invocation, nil} | ||
} | ||
|
||
func FromLink(link ucan.Link) Ran { | ||
return Ran{nil, link} | ||
} | ||
|
||
func (r Ran) Encode(bs blockstore.BlockWriter) (ipld.Link, error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar to my previous comment, this is a "maybe write to blockstore" function - I'd move to where it is used or rename and heavily document. |
||
if invocation, ok := r.Invocation(); ok { | ||
return r.Link(), blockstore.Encode(invocation, bs) | ||
} | ||
return r.Link(), nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,3 +7,4 @@ import ( | |
|
||
type Link = ipld.Link | ||
type Block = block.Block | ||
type Node = ipld.Node |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,7 +7,7 @@ import ( | |
// View represents a materialized IPLD DAG View, which provides a generic | ||
// traversal API. It is useful for encoding (potentially partial) IPLD DAGs | ||
// into content archives (e.g. CARs). | ||
type IPLDView interface { | ||
type View interface { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
// Root is the root block of the IPLD DAG this is the view of. This is the | ||
// block from which all other blocks are linked directly or transitively. | ||
Root() Block | ||
|
@@ -21,3 +21,14 @@ type IPLDView interface { | |
// omitting it when encoding the view into a CAR archive. | ||
Blocks() iterable.Iterator[Block] | ||
} | ||
|
||
// ViewBuilder represents a materializable IPLD DAG View. It is a useful | ||
// abstraction that can be used to defer actual IPLD encoding. | ||
// | ||
// Note that represented DAG could be partial implying that some of the blocks | ||
// may not be included. This by design allowing a user to include whatever | ||
// blocks they want to include. | ||
type ViewBuilder[V View] interface { | ||
// BuildIPLDView encodes all the blocks and creates a new IPLDView instance over them. | ||
BuildIPLDView() V | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,8 +37,8 @@ type MetaModel struct { | |
} | ||
|
||
type ResultModel[O any, X any] struct { | ||
Ok O | ||
Err X | ||
Ok *O | ||
Err *X | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you explain why this is needed please? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So, a union type per bindnode encoding is ALWAYS a pointer type. But the point just encodes whether or not it's present, which is then used to generate the keyed union. You'll note over in go-w3up you're forced to pass pointer types to the receipt. In fact, if you don't the whole code will panic. In my opinion, since no receipt that doesn't have a pointer type will EVER decode or encode properly, it perhaps makes better sense to hide the pointer requirement, which is IPLD specific, from the user. |
||
} | ||
|
||
// NewReceiptModelType creates a new schema.Type for a Receipt. You must | ||
|
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.
Perhaps this should be a
BatchPut
operation thatBlockWriter
implements? This isn't really encoding anything, so I think if notBatchPut
then it needs a rename :)