diff --git a/.github/workflows/codegen.yml b/.github/workflows/codegen.yml new file mode 100644 index 0000000..eebb65f --- /dev/null +++ b/.github/workflows/codegen.yml @@ -0,0 +1,29 @@ +name: Codegen + +on: + pull_request: + push: + branches: ["main"] + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event_name == 'push' && github.sha || github.ref }} + cancel-in-progress: true + +jobs: + codegen: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version-file: go.mod + # Compile the generators under the `codegen` build tag. The reusable + # go-check/go-test workflows build without this tag, so a generator that + # no longer compiles would otherwise slip through CI. + - run: make codegen-build + # Run `go generate` and fail if the committed generated files are stale. + - run: make gen-check diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..485dee6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea diff --git a/Makefile b/Makefile index fa76d41..776d134 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,26 @@ -.PHONY: gen +.PHONY: gen build test codegen-build gen-check ci gen: go generate ./... + +build: + go build ./... + +test: + go test ./... + +# Compile the code generators under the `codegen` build tag they actually run +# with. A normal `go build ./...` never sets this tag, so a generator that no +# longer compiles (e.g. it references a renamed or removed type) would otherwise +# go unnoticed until someone runs `go generate`. +codegen-build: + go build -tags codegen $(shell go list ./... | grep '/gen$$') + +# Regenerate everything and fail if the committed output changed, catching both +# generators that no longer compile and generated files that are out of date. +gen-check: gen + @git diff --exit-code -- '*_gen.go' '*_gen.*.go' || \ + { echo "generated files are out of date; run 'make gen' and commit the result" >&2; exit 1; } + +# Aggregate target suitable for CI. +ci: build codegen-build gen-check test diff --git a/commands/access/cbor_gen.go b/commands/access/cbor_gen.go index 644c288..faf7e5d 100644 --- a/commands/access/cbor_gen.go +++ b/commands/access/cbor_gen.go @@ -930,3 +930,188 @@ func (t *DelegateArguments) UnmarshalCBOR(r io.Reader) (err error) { return nil } +func (t *GrantArguments) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + + cw := cbg.NewCborWriter(w) + fieldCount := 2 + + if t.Cause == nil { + fieldCount-- + } + + if _, err := cw.Write(cbg.CborEncodeMajorType(cbg.MajMap, uint64(fieldCount))); err != nil { + return err + } + + // t.Attenuations ([]access.CapabilityRequest) (slice) + if len("att") > 8192 { + return xerrors.Errorf("Value in field \"att\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("att"))); err != nil { + return err + } + if _, err := cw.WriteString(string("att")); err != nil { + return err + } + + if len(t.Attenuations) > 8192 { + return xerrors.Errorf("Slice value in field t.Attenuations was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajArray, uint64(len(t.Attenuations))); err != nil { + return err + } + for _, v := range t.Attenuations { + if err := v.MarshalCBOR(cw); err != nil { + return err + } + + } + + // t.Cause (cid.Cid) (struct) + if t.Cause != nil { + + if len("cause") > 8192 { + return xerrors.Errorf("Value in field \"cause\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("cause"))); err != nil { + return err + } + if _, err := cw.WriteString(string("cause")); err != nil { + return err + } + + if t.Cause == nil { + if _, err := cw.Write(cbg.CborNull); err != nil { + return err + } + } else { + if err := cbg.WriteCid(cw, *t.Cause); err != nil { + return xerrors.Errorf("failed to write cid field t.Cause: %w", err) + } + } + + } + return nil +} + +func (t *GrantArguments) UnmarshalCBOR(r io.Reader) (err error) { + *t = GrantArguments{} + + cr := cbg.NewCborReader(r) + + maj, extra, err := cr.ReadHeader() + if err != nil { + return err + } + defer func() { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + }() + + if maj != cbg.MajMap { + return fmt.Errorf("cbor input should be of type map") + } + + if extra > cbg.MaxLength { + return fmt.Errorf("GrantArguments: map struct too large (%d)", extra) + } + + n := extra + + nameBuf := make([]byte, 5) + for i := uint64(0); i < n; i++ { + nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 8192) + if err != nil { + return err + } + + if !ok { + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil { + return err + } + continue + } + + switch string(nameBuf[:nameLen]) { + // t.Attenuations ([]access.CapabilityRequest) (slice) + case "att": + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if extra > 8192 { + return fmt.Errorf("t.Attenuations: array too large (%d)", extra) + } + + if maj != cbg.MajArray { + return fmt.Errorf("expected cbor array") + } + + if extra > 0 { + t.Attenuations = make([]CapabilityRequest, extra) + } + + for i := 0; i < int(extra); i++ { + { + var maj byte + var extra uint64 + var err error + _ = maj + _ = extra + _ = err + + { + + if err := t.Attenuations[i].UnmarshalCBOR(cr); err != nil { + return xerrors.Errorf("unmarshaling t.Attenuations[i]: %w", err) + } + + } + + } + } + // t.Cause (cid.Cid) (struct) + case "cause": + + { + + b, err := cr.ReadByte() + if err != nil { + return err + } + if b != cbg.CborNull[0] { + if err := cr.UnreadByte(); err != nil { + return err + } + + c, err := cbg.ReadCid(cr) + if err != nil { + return xerrors.Errorf("failed to read cid field t.Cause: %w", err) + } + + t.Cause = &c + } + + } + + default: + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil { + return err + } + } + } + + return nil +} diff --git a/commands/access/gen/main.go b/commands/access/gen/main.go index 61b8217..b1ab1d3 100644 --- a/commands/access/gen/main.go +++ b/commands/access/gen/main.go @@ -30,6 +30,7 @@ func main() { access.ClaimOK{}, access.ConfirmArguments{}, access.DelegateArguments{}, + access.GrantArguments{}, } const ( cborFile = "../cbor_gen.go" diff --git a/commands/access/grant.go b/commands/access/grant.go new file mode 100644 index 0000000..a03037f --- /dev/null +++ b/commands/access/grant.go @@ -0,0 +1,36 @@ +//go:build !codegen + +package access + +import ( + "github.com/fil-forge/ucantone/errors" + + "github.com/fil-forge/libforge/commands" +) + +const GrantCommand = "/access/grant" + +// GrantOK mirrors ClaimOK / ConfirmOK: a successful grant resolves into a +// bundle of delegation CIDs. The actual delegation envelopes ride in the +// receipt response container as metadata. +type GrantOK = ClaimOK + +// Grant can be invoked by an agent to request that a set of capabilities be +// granted directly. Unlike Request -> Confirm, Grant is one-shot: the +// executor decides immediately whether to issue the delegation. +var Grant = commands.MustParse[*GrantArguments](GrantCommand) + +const ( + UnknownAbilityErrorName = "UnknownAbility" + MissingCapabilityErrorName = "MissingCapability" + UnknownCauseErrorName = "UnknownCause" + MissingCauseErrorName = "MissingCause" + InvalidCauseErrorName = "InvalidCause" + UnauthorizedCauseErrorName = "UnauthorizedCause" +) + +var ( + ErrMissingCapability = errors.New(MissingCapabilityErrorName, "grant requires one or more capabilities") + ErrMissingCause = errors.New(MissingCauseErrorName, "grant requires a supporting contextual invocation") + ErrUnknownCause = errors.New(UnknownCauseErrorName, "unknown cause invocation") +) diff --git a/commands/access/json_gen.go b/commands/access/json_gen.go index 0215a19..12f7185 100644 --- a/commands/access/json_gen.go +++ b/commands/access/json_gen.go @@ -985,3 +985,192 @@ func (t *DelegateArguments) UnmarshalDagJSON(r io.Reader) (err error) { return nil } +func (t *GrantArguments) MarshalDagJSON(w io.Writer) error { + jw := jsg.NewDagJsonWriter(w) + if t == nil { + err := jw.WriteNull() + return err + } + if err := jw.WriteObjectOpen(); err != nil { + return err + } + written := 0 + + // t.Attenuations ([]access.CapabilityRequest) (slice) + if len("att") > 8192 { + return fmt.Errorf("string in field \"att\" was too long") + } + if err := jw.WriteString(string("att")); err != nil { + return fmt.Errorf("writing string for field \"att\": %w", err) + } + if err := jw.WriteObjectColon(); err != nil { + return err + } + if len(t.Attenuations) > 8192 { + return fmt.Errorf("slice value in field t.Attenuations was too long") + } + + if err := jw.WriteArrayOpen(); err != nil { + return fmt.Errorf("writing array open for field t.Attenuations: %w", err) + } + for i, v := range t.Attenuations { + if i > 0 { + if err := jw.WriteComma(); err != nil { + return fmt.Errorf("writing comma for field t.Attenuations: %w", err) + } + } + if err := v.MarshalDagJSON(jw); err != nil { + return fmt.Errorf("marshaling field v: %w", err) + } + } + if err := jw.WriteArrayClose(); err != nil { + return fmt.Errorf("writing array close for field t.Attenuations: %w", err) + } + + written++ + if t.Cause != nil { + if written > 0 { + if err := jw.WriteComma(); err != nil { + return err + } + } + } + + // t.Cause (cid.Cid) (struct) + if t.Cause != nil { + if len("cause") > 8192 { + return fmt.Errorf("string in field \"cause\" was too long") + } + if err := jw.WriteString(string("cause")); err != nil { + return fmt.Errorf("writing string for field \"cause\": %w", err) + } + if err := jw.WriteObjectColon(); err != nil { + return err + } + + if t.Cause == nil { + if err := jw.WriteNull(); err != nil { + return fmt.Errorf("writing null for field t.Cause: %w", err) + } + } else { + if err := jw.WriteCid(*t.Cause); err != nil { + return fmt.Errorf("writing CID for field t.Cause: %w", err) + } + } + + written++ + } + if err := jw.WriteObjectClose(); err != nil { + return err + } + return nil +} +func (t *GrantArguments) UnmarshalDagJSON(r io.Reader) (err error) { + *t = GrantArguments{} + + jr := jsg.NewDagJsonReader(r) + defer func() { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + }() + if err := jr.ReadObjectOpen(); err != nil { + return fmt.Errorf("reading object open for GrantArguments: %w", err) + } + close, err := jr.PeekObjectClose() + if err != nil { + return fmt.Errorf("peeking object close for GrantArguments: %w", err) + } + if close { + if err := jr.ReadObjectClose(); err != nil { + return fmt.Errorf("reading object close for GrantArguments: %w", err) + } + } else { + for i := uint64(0); i < 8192; i++ { + name, err := jr.ReadString(8192) + if err != nil { + if errors.Is(err, jsg.ErrLimitExceeded) { + return fmt.Errorf("reading string for field GrantArguments: string too large") + } + return fmt.Errorf("reading string for field GrantArguments: %w", err) + } + if err := jr.ReadObjectColon(); err != nil { + return fmt.Errorf("reading object colon for field GrantArguments: %w", err) + } + switch name { + + // t.Attenuations ([]access.CapabilityRequest) (slice) + case "att": + { + + if err := jr.ReadArrayOpen(); err != nil { + return fmt.Errorf("reading array open for field t.Attenuations: %w", err) + } + + close, err := jr.PeekArrayClose() + if err != nil { + return fmt.Errorf("peeking array close for field t.Attenuations: %w", err) + } + if close { + if err := jr.ReadArrayClose(); err != nil { + return fmt.Errorf("reading array close for field t.Attenuations: %w", err) + } + + } else { + for i := 0; i < 8192; i++ { + item := make([]CapabilityRequest, 1) + + if err := item[0].UnmarshalDagJSON(jr); err != nil { + return fmt.Errorf("unmarshaling item[0]: %w", err) + } + + t.Attenuations = append(t.Attenuations, item[0]) + + close, err := jr.ReadArrayCloseOrComma() + if err != nil { + return fmt.Errorf("reading array close or comma for field t.Attenuations: %w", err) + } + if close { + break + } + if i == 8192-1 { + return fmt.Errorf("reading array for field t.Attenuations: slice too large") + } + } + } + + } + + // t.Cause (cid.Cid) (struct) + case "cause": + { + + c, err := jr.ReadCidOrNull() + if err != nil { + return fmt.Errorf("reading CID or null for field t.Cause: %w", err) + } + t.Cause = c + + } + default: + // Field doesn't exist on this type, so ignore it + if err := jr.DiscardType(); err != nil { + return fmt.Errorf("ignoring field %s for GrantArguments: %w", name, err) + } + } + + close, err := jr.ReadObjectCloseOrComma() + if err != nil { + return fmt.Errorf("reading object close or comma for field GrantArguments: %w", err) + } + if close { + break + } + if i == 8192-1 { + return fmt.Errorf("map too large for GrantArguments") + } + } + } + + return nil +} diff --git a/commands/access/types.go b/commands/access/types.go index 07d0599..a7e78f3 100644 --- a/commands/access/types.go +++ b/commands/access/types.go @@ -43,3 +43,12 @@ type DelegateArguments struct { // The delegations to store. Delegations []cid.Cid `cborgen:"delegations" dagjsongen:"delegations"` } + +type GrantArguments struct { + // Attenuations are the capabilities the agent wishes to be granted. + Attenuations []CapabilityRequest `cborgen:"att" dagjsongen:"att"` + // Cause optionally links to a UCAN invocation that contextualizes the + // grant request. Leave nil when no cause is needed; otherwise the + // linked invocation MUST be present in the request container. + Cause *cid.Cid `cborgen:"cause,omitempty" dagjsongen:"cause,omitempty"` +} diff --git a/commands/blob/replica/cbor_gen.go b/commands/blob/replica/cbor_gen.go index 7c442c8..04fc07e 100644 --- a/commands/blob/replica/cbor_gen.go +++ b/commands/blob/replica/cbor_gen.go @@ -32,7 +32,7 @@ func (t *AllocateArguments) MarshalCBOR(w io.Writer) error { return err } - // t.Blob (replica.Blob) (struct) + // t.Blob (blob.Blob) (struct) if len("blob") > 8192 { return xerrors.Errorf("Value in field \"blob\" was too long") } @@ -124,7 +124,7 @@ func (t *AllocateArguments) UnmarshalCBOR(r io.Reader) (err error) { } switch string(nameBuf[:nameLen]) { - // t.Blob (replica.Blob) (struct) + // t.Blob (blob.Blob) (struct) case "blob": { @@ -171,150 +171,6 @@ func (t *AllocateArguments) UnmarshalCBOR(r io.Reader) (err error) { return nil } -func (t *Blob) MarshalCBOR(w io.Writer) error { - if t == nil { - _, err := w.Write(cbg.CborNull) - return err - } - - cw := cbg.NewCborWriter(w) - - if _, err := cw.Write([]byte{162}); err != nil { - return err - } - - // t.Size (uint64) (uint64) - if len("size") > 8192 { - return xerrors.Errorf("Value in field \"size\" was too long") - } - - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("size"))); err != nil { - return err - } - if _, err := cw.WriteString(string("size")); err != nil { - return err - } - - if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.Size)); err != nil { - return err - } - - // t.Digest (multihash.Multihash) (slice) - if len("digest") > 8192 { - return xerrors.Errorf("Value in field \"digest\" was too long") - } - - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("digest"))); err != nil { - return err - } - if _, err := cw.WriteString(string("digest")); err != nil { - return err - } - - if len(t.Digest) > 2097152 { - return xerrors.Errorf("Byte array in field t.Digest was too long") - } - - if err := cw.WriteMajorTypeHeader(cbg.MajByteString, uint64(len(t.Digest))); err != nil { - return err - } - - if _, err := cw.Write(t.Digest); err != nil { - return err - } - - return nil -} - -func (t *Blob) UnmarshalCBOR(r io.Reader) (err error) { - *t = Blob{} - - cr := cbg.NewCborReader(r) - - maj, extra, err := cr.ReadHeader() - if err != nil { - return err - } - defer func() { - if err == io.EOF { - err = io.ErrUnexpectedEOF - } - }() - - if maj != cbg.MajMap { - return fmt.Errorf("cbor input should be of type map") - } - - if extra > cbg.MaxLength { - return fmt.Errorf("Blob: map struct too large (%d)", extra) - } - - n := extra - - nameBuf := make([]byte, 6) - for i := uint64(0); i < n; i++ { - nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 8192) - if err != nil { - return err - } - - if !ok { - // Field doesn't exist on this type, so ignore it - if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil { - return err - } - continue - } - - switch string(nameBuf[:nameLen]) { - // t.Size (uint64) (uint64) - case "size": - - { - - maj, extra, err = cr.ReadHeader() - if err != nil { - return err - } - if maj != cbg.MajUnsignedInt { - return fmt.Errorf("wrong type for uint64 field") - } - t.Size = uint64(extra) - - } - // t.Digest (multihash.Multihash) (slice) - case "digest": - - maj, extra, err = cr.ReadHeader() - if err != nil { - return err - } - - if extra > 2097152 { - return fmt.Errorf("t.Digest: byte array too large (%d)", extra) - } - if maj != cbg.MajByteString { - return fmt.Errorf("expected byte array") - } - - if extra > 0 { - t.Digest = make([]uint8, extra) - } - - if _, err := io.ReadFull(cr, t.Digest); err != nil { - return err - } - - default: - // Field doesn't exist on this type, so ignore it - if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil { - return err - } - } - } - - return nil -} func (t *AllocateOK) MarshalCBOR(w io.Writer) error { if t == nil { _, err := w.Write(cbg.CborNull) @@ -419,7 +275,7 @@ func (t *TransferArguments) MarshalCBOR(w io.Writer) error { return err } - // t.Blob (replica.Blob) (struct) + // t.Blob (blob.Blob) (struct) if len("blob") > 8192 { return xerrors.Errorf("Value in field \"blob\" was too long") } @@ -511,7 +367,7 @@ func (t *TransferArguments) UnmarshalCBOR(r io.Reader) (err error) { } switch string(nameBuf[:nameLen]) { - // t.Blob (replica.Blob) (struct) + // t.Blob (blob.Blob) (struct) case "blob": { diff --git a/commands/blob/replica/gen/main.go b/commands/blob/replica/gen/main.go index 9fea00f..ffe356e 100644 --- a/commands/blob/replica/gen/main.go +++ b/commands/blob/replica/gen/main.go @@ -16,7 +16,7 @@ func tag(path string) { if err != nil { panic(err) } - if err := os.WriteFile(path, append([]byte(buildTag), data...), 0644); err != nil { + if err := os.WriteFile(path, append([]byte(buildTag), data...), 0o644); err != nil { panic(err) } } @@ -25,7 +25,6 @@ func main() { const cborFile = "../cbor_gen.go" if err := cbg.WriteMapEncodersToFile(cborFile, "replica", replica.AllocateArguments{}, - replica.Blob{}, replica.AllocateOK{}, replica.TransferArguments{}, replica.TransferOK{}, diff --git a/commands/blob/replica/types.go b/commands/blob/replica/types.go index e0bb2d5..c09894a 100644 --- a/commands/blob/replica/types.go +++ b/commands/blob/replica/types.go @@ -3,17 +3,13 @@ package replica import ( "github.com/fil-forge/ucantone/ucan/promise" "github.com/ipfs/go-cid" - "github.com/multiformats/go-multihash" -) -type Blob struct { - Digest multihash.Multihash `cborgen:"digest"` - Size uint64 `cborgen:"size"` -} + "github.com/fil-forge/libforge/commands/blob" +) type AllocateArguments struct { // Blob is the blob to be allocated. - Blob Blob `cborgen:"blob"` + Blob blob.Blob `cborgen:"blob"` // Site is a link to a location commitment indicating where the Blob must be // fetched from. Site cid.Cid `cborgen:"site"` @@ -29,7 +25,7 @@ type AllocateOK struct { type TransferArguments struct { // Blob is the blob to be transferred. - Blob Blob `cborgen:"blob"` + Blob blob.Blob `cborgen:"blob"` // Site is a link to a location commitment indicating where the Blob must be // fetched from. Site cid.Cid `cborgen:"site"` diff --git a/commands/pdp/accept.go b/commands/pdp/accept.go new file mode 100644 index 0000000..91df730 --- /dev/null +++ b/commands/pdp/accept.go @@ -0,0 +1,7 @@ +//go:build !codegen + +package pdp + +import "github.com/fil-forge/libforge/commands" + +var Accept = commands.MustParse[*AcceptArguments]("/pdp/accept") diff --git a/commands/pdp/cbor_gen.go b/commands/pdp/cbor_gen.go new file mode 100644 index 0000000..1146d33 --- /dev/null +++ b/commands/pdp/cbor_gen.go @@ -0,0 +1,679 @@ +//go:build !codegen + +// Code generated by github.com/whyrusleeping/cbor-gen. DO NOT EDIT. + +package pdp + +import ( + "fmt" + "io" + "math" + "sort" + + cid "github.com/ipfs/go-cid" + cbg "github.com/whyrusleeping/cbor-gen" + xerrors "golang.org/x/xerrors" +) + +var _ = xerrors.Errorf +var _ = cid.Undef +var _ = math.E +var _ = sort.Sort + +func (t *AcceptArguments) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + + cw := cbg.NewCborWriter(w) + + if _, err := cw.Write([]byte{161}); err != nil { + return err + } + + // t.Blob (multihash.Multihash) (slice) + if len("blob") > 8192 { + return xerrors.Errorf("Value in field \"blob\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("blob"))); err != nil { + return err + } + if _, err := cw.WriteString(string("blob")); err != nil { + return err + } + + if len(t.Blob) > 2097152 { + return xerrors.Errorf("Byte array in field t.Blob was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajByteString, uint64(len(t.Blob))); err != nil { + return err + } + + if _, err := cw.Write(t.Blob); err != nil { + return err + } + + return nil +} + +func (t *AcceptArguments) UnmarshalCBOR(r io.Reader) (err error) { + *t = AcceptArguments{} + + cr := cbg.NewCborReader(r) + + maj, extra, err := cr.ReadHeader() + if err != nil { + return err + } + defer func() { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + }() + + if maj != cbg.MajMap { + return fmt.Errorf("cbor input should be of type map") + } + + if extra > cbg.MaxLength { + return fmt.Errorf("AcceptArguments: map struct too large (%d)", extra) + } + + n := extra + + nameBuf := make([]byte, 4) + for i := uint64(0); i < n; i++ { + nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 8192) + if err != nil { + return err + } + + if !ok { + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil { + return err + } + continue + } + + switch string(nameBuf[:nameLen]) { + // t.Blob (multihash.Multihash) (slice) + case "blob": + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if extra > 2097152 { + return fmt.Errorf("t.Blob: byte array too large (%d)", extra) + } + if maj != cbg.MajByteString { + return fmt.Errorf("expected byte array") + } + + if extra > 0 { + t.Blob = make([]uint8, extra) + } + + if _, err := io.ReadFull(cr, t.Blob); err != nil { + return err + } + + default: + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil { + return err + } + } + } + + return nil +} +func (t *AcceptOK) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + + cw := cbg.NewCborWriter(w) + + if _, err := cw.Write([]byte{163}); err != nil { + return err + } + + // t.Piece (cid.Cid) (struct) + if len("piece") > 8192 { + return xerrors.Errorf("Value in field \"piece\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("piece"))); err != nil { + return err + } + if _, err := cw.WriteString(string("piece")); err != nil { + return err + } + + if err := cbg.WriteCid(cw, t.Piece); err != nil { + return xerrors.Errorf("failed to write cid field t.Piece: %w", err) + } + + // t.Aggregate (cid.Cid) (struct) + if len("aggregate") > 8192 { + return xerrors.Errorf("Value in field \"aggregate\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("aggregate"))); err != nil { + return err + } + if _, err := cw.WriteString(string("aggregate")); err != nil { + return err + } + + if err := cbg.WriteCid(cw, t.Aggregate); err != nil { + return xerrors.Errorf("failed to write cid field t.Aggregate: %w", err) + } + + // t.InclusionProof (merkletree.ProofData) (struct) + if len("inclusionProof") > 8192 { + return xerrors.Errorf("Value in field \"inclusionProof\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("inclusionProof"))); err != nil { + return err + } + if _, err := cw.WriteString(string("inclusionProof")); err != nil { + return err + } + + if err := t.InclusionProof.MarshalCBOR(cw); err != nil { + return err + } + return nil +} + +func (t *AcceptOK) UnmarshalCBOR(r io.Reader) (err error) { + *t = AcceptOK{} + + cr := cbg.NewCborReader(r) + + maj, extra, err := cr.ReadHeader() + if err != nil { + return err + } + defer func() { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + }() + + if maj != cbg.MajMap { + return fmt.Errorf("cbor input should be of type map") + } + + if extra > cbg.MaxLength { + return fmt.Errorf("AcceptOK: map struct too large (%d)", extra) + } + + n := extra + + nameBuf := make([]byte, 14) + for i := uint64(0); i < n; i++ { + nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 8192) + if err != nil { + return err + } + + if !ok { + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil { + return err + } + continue + } + + switch string(nameBuf[:nameLen]) { + // t.Piece (cid.Cid) (struct) + case "piece": + + { + + c, err := cbg.ReadCid(cr) + if err != nil { + return xerrors.Errorf("failed to read cid field t.Piece: %w", err) + } + + t.Piece = c + + } + // t.Aggregate (cid.Cid) (struct) + case "aggregate": + + { + + c, err := cbg.ReadCid(cr) + if err != nil { + return xerrors.Errorf("failed to read cid field t.Aggregate: %w", err) + } + + t.Aggregate = c + + } + // t.InclusionProof (merkletree.ProofData) (struct) + case "inclusionProof": + + { + + if err := t.InclusionProof.UnmarshalCBOR(cr); err != nil { + return xerrors.Errorf("unmarshaling t.InclusionProof: %w", err) + } + + } + + default: + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil { + return err + } + } + } + + return nil +} +func (t *InfoArguments) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + + cw := cbg.NewCborWriter(w) + + if _, err := cw.Write([]byte{161}); err != nil { + return err + } + + // t.Blob (multihash.Multihash) (slice) + if len("blob") > 8192 { + return xerrors.Errorf("Value in field \"blob\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("blob"))); err != nil { + return err + } + if _, err := cw.WriteString(string("blob")); err != nil { + return err + } + + if len(t.Blob) > 2097152 { + return xerrors.Errorf("Byte array in field t.Blob was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajByteString, uint64(len(t.Blob))); err != nil { + return err + } + + if _, err := cw.Write(t.Blob); err != nil { + return err + } + + return nil +} + +func (t *InfoArguments) UnmarshalCBOR(r io.Reader) (err error) { + *t = InfoArguments{} + + cr := cbg.NewCborReader(r) + + maj, extra, err := cr.ReadHeader() + if err != nil { + return err + } + defer func() { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + }() + + if maj != cbg.MajMap { + return fmt.Errorf("cbor input should be of type map") + } + + if extra > cbg.MaxLength { + return fmt.Errorf("InfoArguments: map struct too large (%d)", extra) + } + + n := extra + + nameBuf := make([]byte, 4) + for i := uint64(0); i < n; i++ { + nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 8192) + if err != nil { + return err + } + + if !ok { + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil { + return err + } + continue + } + + switch string(nameBuf[:nameLen]) { + // t.Blob (multihash.Multihash) (slice) + case "blob": + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if extra > 2097152 { + return fmt.Errorf("t.Blob: byte array too large (%d)", extra) + } + if maj != cbg.MajByteString { + return fmt.Errorf("expected byte array") + } + + if extra > 0 { + t.Blob = make([]uint8, extra) + } + + if _, err := io.ReadFull(cr, t.Blob); err != nil { + return err + } + + default: + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil { + return err + } + } + } + + return nil +} +func (t *InfoAcceptedAggregate) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + + cw := cbg.NewCborWriter(w) + + if _, err := cw.Write([]byte{162}); err != nil { + return err + } + + // t.Aggregate (cid.Cid) (struct) + if len("aggregate") > 8192 { + return xerrors.Errorf("Value in field \"aggregate\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("aggregate"))); err != nil { + return err + } + if _, err := cw.WriteString(string("aggregate")); err != nil { + return err + } + + if err := cbg.WriteCid(cw, t.Aggregate); err != nil { + return xerrors.Errorf("failed to write cid field t.Aggregate: %w", err) + } + + // t.InclusionProof (merkletree.ProofData) (struct) + if len("inclusionProof") > 8192 { + return xerrors.Errorf("Value in field \"inclusionProof\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("inclusionProof"))); err != nil { + return err + } + if _, err := cw.WriteString(string("inclusionProof")); err != nil { + return err + } + + if err := t.InclusionProof.MarshalCBOR(cw); err != nil { + return err + } + return nil +} + +func (t *InfoAcceptedAggregate) UnmarshalCBOR(r io.Reader) (err error) { + *t = InfoAcceptedAggregate{} + + cr := cbg.NewCborReader(r) + + maj, extra, err := cr.ReadHeader() + if err != nil { + return err + } + defer func() { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + }() + + if maj != cbg.MajMap { + return fmt.Errorf("cbor input should be of type map") + } + + if extra > cbg.MaxLength { + return fmt.Errorf("InfoAcceptedAggregate: map struct too large (%d)", extra) + } + + n := extra + + nameBuf := make([]byte, 14) + for i := uint64(0); i < n; i++ { + nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 8192) + if err != nil { + return err + } + + if !ok { + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil { + return err + } + continue + } + + switch string(nameBuf[:nameLen]) { + // t.Aggregate (cid.Cid) (struct) + case "aggregate": + + { + + c, err := cbg.ReadCid(cr) + if err != nil { + return xerrors.Errorf("failed to read cid field t.Aggregate: %w", err) + } + + t.Aggregate = c + + } + // t.InclusionProof (merkletree.ProofData) (struct) + case "inclusionProof": + + { + + if err := t.InclusionProof.UnmarshalCBOR(cr); err != nil { + return xerrors.Errorf("unmarshaling t.InclusionProof: %w", err) + } + + } + + default: + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil { + return err + } + } + } + + return nil +} +func (t *InfoOK) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + + cw := cbg.NewCborWriter(w) + + if _, err := cw.Write([]byte{162}); err != nil { + return err + } + + // t.Piece (cid.Cid) (struct) + if len("piece") > 8192 { + return xerrors.Errorf("Value in field \"piece\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("piece"))); err != nil { + return err + } + if _, err := cw.WriteString(string("piece")); err != nil { + return err + } + + if err := cbg.WriteCid(cw, t.Piece); err != nil { + return xerrors.Errorf("failed to write cid field t.Piece: %w", err) + } + + // t.Aggregates ([]pdp.InfoAcceptedAggregate) (slice) + if len("aggregates") > 8192 { + return xerrors.Errorf("Value in field \"aggregates\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("aggregates"))); err != nil { + return err + } + if _, err := cw.WriteString(string("aggregates")); err != nil { + return err + } + + if len(t.Aggregates) > 8192 { + return xerrors.Errorf("Slice value in field t.Aggregates was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajArray, uint64(len(t.Aggregates))); err != nil { + return err + } + for _, v := range t.Aggregates { + if err := v.MarshalCBOR(cw); err != nil { + return err + } + + } + return nil +} + +func (t *InfoOK) UnmarshalCBOR(r io.Reader) (err error) { + *t = InfoOK{} + + cr := cbg.NewCborReader(r) + + maj, extra, err := cr.ReadHeader() + if err != nil { + return err + } + defer func() { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + }() + + if maj != cbg.MajMap { + return fmt.Errorf("cbor input should be of type map") + } + + if extra > cbg.MaxLength { + return fmt.Errorf("InfoOK: map struct too large (%d)", extra) + } + + n := extra + + nameBuf := make([]byte, 10) + for i := uint64(0); i < n; i++ { + nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 8192) + if err != nil { + return err + } + + if !ok { + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil { + return err + } + continue + } + + switch string(nameBuf[:nameLen]) { + // t.Piece (cid.Cid) (struct) + case "piece": + + { + + c, err := cbg.ReadCid(cr) + if err != nil { + return xerrors.Errorf("failed to read cid field t.Piece: %w", err) + } + + t.Piece = c + + } + // t.Aggregates ([]pdp.InfoAcceptedAggregate) (slice) + case "aggregates": + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if extra > 8192 { + return fmt.Errorf("t.Aggregates: array too large (%d)", extra) + } + + if maj != cbg.MajArray { + return fmt.Errorf("expected cbor array") + } + + if extra > 0 { + t.Aggregates = make([]InfoAcceptedAggregate, extra) + } + + for i := 0; i < int(extra); i++ { + { + var maj byte + var extra uint64 + var err error + _ = maj + _ = extra + _ = err + + { + + if err := t.Aggregates[i].UnmarshalCBOR(cr); err != nil { + return xerrors.Errorf("unmarshaling t.Aggregates[i]: %w", err) + } + + } + + } + } + + default: + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil { + return err + } + } + } + + return nil +} diff --git a/commands/pdp/gen/main.go b/commands/pdp/gen/main.go new file mode 100644 index 0000000..97c347d --- /dev/null +++ b/commands/pdp/gen/main.go @@ -0,0 +1,40 @@ +//go:generate go run -tags codegen . + +package main + +import ( + "os" + + cbg "github.com/whyrusleeping/cbor-gen" + + "github.com/fil-forge/libforge/commands/pdp" +) + +const buildTag = "//go:build !codegen\n\n" + +func tag(path string) { + data, err := os.ReadFile(path) + if err != nil { + panic(err) + } + if err := os.WriteFile(path, append([]byte(buildTag), data...), 0644); err != nil { + panic(err) + } +} + +func main() { + models := []any{ + pdp.AcceptArguments{}, + pdp.AcceptOK{}, + pdp.InfoArguments{}, + pdp.InfoAcceptedAggregate{}, + pdp.InfoOK{}, + } + const cborFile = "../cbor_gen.go" + // merkletree.ProofData implements CBOR but not dag-json, and the stack is + // CBOR-only on the wire, so we don't generate dag-json codecs here. + if err := cbg.WriteMapEncodersToFile(cborFile, "pdp", models...); err != nil { + panic(err) + } + tag(cborFile) +} diff --git a/commands/pdp/info.go b/commands/pdp/info.go new file mode 100644 index 0000000..31d694a --- /dev/null +++ b/commands/pdp/info.go @@ -0,0 +1,9 @@ +//go:build !codegen + +package pdp + +import "github.com/fil-forge/libforge/commands" + +const InfoCommand = "/pdp/info" + +var Info = commands.MustParse[*InfoArguments]("/pdp/info") diff --git a/commands/pdp/sign/cbor_gen.go b/commands/pdp/sign/cbor_gen.go new file mode 100644 index 0000000..9921ed1 --- /dev/null +++ b/commands/pdp/sign/cbor_gen.go @@ -0,0 +1,1712 @@ +//go:build !codegen + +// Code generated by github.com/whyrusleeping/cbor-gen. DO NOT EDIT. + +package sign + +import ( + "fmt" + "io" + "math" + "sort" + + cid "github.com/ipfs/go-cid" + cbg "github.com/whyrusleeping/cbor-gen" + xerrors "golang.org/x/xerrors" + big "math/big" +) + +var _ = xerrors.Errorf +var _ = cid.Undef +var _ = math.E +var _ = sort.Sort + +func (t *AuthSignature) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + + cw := cbg.NewCborWriter(w) + + if _, err := cw.Write([]byte{166}); err != nil { + return err + } + + // t.R ([]uint8) (slice) + if len("r") > 8192 { + return xerrors.Errorf("Value in field \"r\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("r"))); err != nil { + return err + } + if _, err := cw.WriteString(string("r")); err != nil { + return err + } + + if len(t.R) > 2097152 { + return xerrors.Errorf("Byte array in field t.R was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajByteString, uint64(len(t.R))); err != nil { + return err + } + + if _, err := cw.Write(t.R); err != nil { + return err + } + + // t.S ([]uint8) (slice) + if len("s") > 8192 { + return xerrors.Errorf("Value in field \"s\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("s"))); err != nil { + return err + } + if _, err := cw.WriteString(string("s")); err != nil { + return err + } + + if len(t.S) > 2097152 { + return xerrors.Errorf("Byte array in field t.S was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajByteString, uint64(len(t.S))); err != nil { + return err + } + + if _, err := cw.Write(t.S); err != nil { + return err + } + + // t.V (uint8) (uint8) + if len("v") > 8192 { + return xerrors.Errorf("Value in field \"v\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("v"))); err != nil { + return err + } + if _, err := cw.WriteString(string("v")); err != nil { + return err + } + + if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.V)); err != nil { + return err + } + + // t.Signer ([]uint8) (slice) + if len("signer") > 8192 { + return xerrors.Errorf("Value in field \"signer\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("signer"))); err != nil { + return err + } + if _, err := cw.WriteString(string("signer")); err != nil { + return err + } + + if len(t.Signer) > 2097152 { + return xerrors.Errorf("Byte array in field t.Signer was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajByteString, uint64(len(t.Signer))); err != nil { + return err + } + + if _, err := cw.Write(t.Signer); err != nil { + return err + } + + // t.Signature ([]uint8) (slice) + if len("signature") > 8192 { + return xerrors.Errorf("Value in field \"signature\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("signature"))); err != nil { + return err + } + if _, err := cw.WriteString(string("signature")); err != nil { + return err + } + + if len(t.Signature) > 2097152 { + return xerrors.Errorf("Byte array in field t.Signature was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajByteString, uint64(len(t.Signature))); err != nil { + return err + } + + if _, err := cw.Write(t.Signature); err != nil { + return err + } + + // t.SignedData ([]uint8) (slice) + if len("signedData") > 8192 { + return xerrors.Errorf("Value in field \"signedData\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("signedData"))); err != nil { + return err + } + if _, err := cw.WriteString(string("signedData")); err != nil { + return err + } + + if len(t.SignedData) > 2097152 { + return xerrors.Errorf("Byte array in field t.SignedData was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajByteString, uint64(len(t.SignedData))); err != nil { + return err + } + + if _, err := cw.Write(t.SignedData); err != nil { + return err + } + + return nil +} + +func (t *AuthSignature) UnmarshalCBOR(r io.Reader) (err error) { + *t = AuthSignature{} + + cr := cbg.NewCborReader(r) + + maj, extra, err := cr.ReadHeader() + if err != nil { + return err + } + defer func() { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + }() + + if maj != cbg.MajMap { + return fmt.Errorf("cbor input should be of type map") + } + + if extra > cbg.MaxLength { + return fmt.Errorf("AuthSignature: map struct too large (%d)", extra) + } + + n := extra + + nameBuf := make([]byte, 10) + for i := uint64(0); i < n; i++ { + nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 8192) + if err != nil { + return err + } + + if !ok { + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil { + return err + } + continue + } + + switch string(nameBuf[:nameLen]) { + // t.R ([]uint8) (slice) + case "r": + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if extra > 2097152 { + return fmt.Errorf("t.R: byte array too large (%d)", extra) + } + if maj != cbg.MajByteString { + return fmt.Errorf("expected byte array") + } + + if extra > 0 { + t.R = make([]uint8, extra) + } + + if _, err := io.ReadFull(cr, t.R); err != nil { + return err + } + + // t.S ([]uint8) (slice) + case "s": + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if extra > 2097152 { + return fmt.Errorf("t.S: byte array too large (%d)", extra) + } + if maj != cbg.MajByteString { + return fmt.Errorf("expected byte array") + } + + if extra > 0 { + t.S = make([]uint8, extra) + } + + if _, err := io.ReadFull(cr, t.S); err != nil { + return err + } + + // t.V (uint8) (uint8) + case "v": + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + if maj != cbg.MajUnsignedInt { + return fmt.Errorf("wrong type for uint8 field") + } + if extra > math.MaxUint8 { + return fmt.Errorf("integer in input was too large for uint8 field") + } + t.V = uint8(extra) + // t.Signer ([]uint8) (slice) + case "signer": + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if extra > 2097152 { + return fmt.Errorf("t.Signer: byte array too large (%d)", extra) + } + if maj != cbg.MajByteString { + return fmt.Errorf("expected byte array") + } + + if extra > 0 { + t.Signer = make([]uint8, extra) + } + + if _, err := io.ReadFull(cr, t.Signer); err != nil { + return err + } + + // t.Signature ([]uint8) (slice) + case "signature": + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if extra > 2097152 { + return fmt.Errorf("t.Signature: byte array too large (%d)", extra) + } + if maj != cbg.MajByteString { + return fmt.Errorf("expected byte array") + } + + if extra > 0 { + t.Signature = make([]uint8, extra) + } + + if _, err := io.ReadFull(cr, t.Signature); err != nil { + return err + } + + // t.SignedData ([]uint8) (slice) + case "signedData": + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if extra > 2097152 { + return fmt.Errorf("t.SignedData: byte array too large (%d)", extra) + } + if maj != cbg.MajByteString { + return fmt.Errorf("expected byte array") + } + + if extra > 0 { + t.SignedData = make([]uint8, extra) + } + + if _, err := io.ReadFull(cr, t.SignedData); err != nil { + return err + } + + default: + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil { + return err + } + } + } + + return nil +} +func (t *Metadata) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + + cw := cbg.NewCborWriter(w) + + if _, err := cw.Write([]byte{162}); err != nil { + return err + } + + // t.Keys ([]string) (slice) + if len("keys") > 8192 { + return xerrors.Errorf("Value in field \"keys\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("keys"))); err != nil { + return err + } + if _, err := cw.WriteString(string("keys")); err != nil { + return err + } + + if len(t.Keys) > 8192 { + return xerrors.Errorf("Slice value in field t.Keys was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajArray, uint64(len(t.Keys))); err != nil { + return err + } + for _, v := range t.Keys { + if len(v) > 8192 { + return xerrors.Errorf("Value in field v was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(v))); err != nil { + return err + } + if _, err := cw.WriteString(string(v)); err != nil { + return err + } + + } + + // t.Values (map[string]string) (map) + if len("values") > 8192 { + return xerrors.Errorf("Value in field \"values\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("values"))); err != nil { + return err + } + if _, err := cw.WriteString(string("values")); err != nil { + return err + } + + { + if len(t.Values) > 4096 { + return xerrors.Errorf("cannot marshal t.Values map too large") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajMap, uint64(len(t.Values))); err != nil { + return err + } + + keys := make([]string, 0, len(t.Values)) + for k := range t.Values { + keys = append(keys, k) + } + sort.Strings(keys) + for _, k := range keys { + v := t.Values[k] + + if len(k) > 8192 { + return xerrors.Errorf("Value in field k was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(k))); err != nil { + return err + } + if _, err := cw.WriteString(string(k)); err != nil { + return err + } + + if len(v) > 8192 { + return xerrors.Errorf("Value in field v was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(v))); err != nil { + return err + } + if _, err := cw.WriteString(string(v)); err != nil { + return err + } + + } + } + return nil +} + +func (t *Metadata) UnmarshalCBOR(r io.Reader) (err error) { + *t = Metadata{} + + cr := cbg.NewCborReader(r) + + maj, extra, err := cr.ReadHeader() + if err != nil { + return err + } + defer func() { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + }() + + if maj != cbg.MajMap { + return fmt.Errorf("cbor input should be of type map") + } + + if extra > cbg.MaxLength { + return fmt.Errorf("Metadata: map struct too large (%d)", extra) + } + + n := extra + + nameBuf := make([]byte, 6) + for i := uint64(0); i < n; i++ { + nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 8192) + if err != nil { + return err + } + + if !ok { + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil { + return err + } + continue + } + + switch string(nameBuf[:nameLen]) { + // t.Keys ([]string) (slice) + case "keys": + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if extra > 8192 { + return fmt.Errorf("t.Keys: array too large (%d)", extra) + } + + if maj != cbg.MajArray { + return fmt.Errorf("expected cbor array") + } + + if extra > 0 { + t.Keys = make([]string, extra) + } + + for i := 0; i < int(extra); i++ { + { + var maj byte + var extra uint64 + var err error + _ = maj + _ = extra + _ = err + + { + sval, err := cbg.ReadStringWithMax(cr, 8192) + if err != nil { + return err + } + + t.Keys[i] = string(sval) + } + + } + } + // t.Values (map[string]string) (map) + case "values": + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + if maj != cbg.MajMap { + return fmt.Errorf("expected a map (major type 5)") + } + if extra > 4096 { + return fmt.Errorf("t.Values: map too large") + } + + t.Values = make(map[string]string, extra) + + for i, l := 0, int(extra); i < l; i++ { + + var k string + + { + sval, err := cbg.ReadStringWithMax(cr, 8192) + if err != nil { + return err + } + + k = string(sval) + } + + var v string + + { + sval, err := cbg.ReadStringWithMax(cr, 8192) + if err != nil { + return err + } + + v = string(sval) + } + + t.Values[k] = v + + } + + default: + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil { + return err + } + } + } + + return nil +} +func (t *PieceProofs) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + + cw := cbg.NewCborWriter(w) + + if _, err := cw.Write([]byte{161}); err != nil { + return err + } + + // t.Proofs ([]cid.Cid) (slice) + if len("proofs") > 8192 { + return xerrors.Errorf("Value in field \"proofs\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("proofs"))); err != nil { + return err + } + if _, err := cw.WriteString(string("proofs")); err != nil { + return err + } + + if len(t.Proofs) > 8192 { + return xerrors.Errorf("Slice value in field t.Proofs was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajArray, uint64(len(t.Proofs))); err != nil { + return err + } + for _, v := range t.Proofs { + + if err := cbg.WriteCid(cw, v); err != nil { + return xerrors.Errorf("failed to write cid field v: %w", err) + } + + } + return nil +} + +func (t *PieceProofs) UnmarshalCBOR(r io.Reader) (err error) { + *t = PieceProofs{} + + cr := cbg.NewCborReader(r) + + maj, extra, err := cr.ReadHeader() + if err != nil { + return err + } + defer func() { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + }() + + if maj != cbg.MajMap { + return fmt.Errorf("cbor input should be of type map") + } + + if extra > cbg.MaxLength { + return fmt.Errorf("PieceProofs: map struct too large (%d)", extra) + } + + n := extra + + nameBuf := make([]byte, 6) + for i := uint64(0); i < n; i++ { + nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 8192) + if err != nil { + return err + } + + if !ok { + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil { + return err + } + continue + } + + switch string(nameBuf[:nameLen]) { + // t.Proofs ([]cid.Cid) (slice) + case "proofs": + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if extra > 8192 { + return fmt.Errorf("t.Proofs: array too large (%d)", extra) + } + + if maj != cbg.MajArray { + return fmt.Errorf("expected cbor array") + } + + if extra > 0 { + t.Proofs = make([]cid.Cid, extra) + } + + for i := 0; i < int(extra); i++ { + { + var maj byte + var extra uint64 + var err error + _ = maj + _ = extra + _ = err + + { + + c, err := cbg.ReadCid(cr) + if err != nil { + return xerrors.Errorf("failed to read cid field t.Proofs[i]: %w", err) + } + + t.Proofs[i] = c + + } + + } + } + + default: + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil { + return err + } + } + } + + return nil +} +func (t *DataSetCreateArguments) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + + cw := cbg.NewCborWriter(w) + + if _, err := cw.Write([]byte{163}); err != nil { + return err + } + + // t.Payee ([]uint8) (slice) + if len("payee") > 8192 { + return xerrors.Errorf("Value in field \"payee\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("payee"))); err != nil { + return err + } + if _, err := cw.WriteString(string("payee")); err != nil { + return err + } + + if len(t.Payee) > 2097152 { + return xerrors.Errorf("Byte array in field t.Payee was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajByteString, uint64(len(t.Payee))); err != nil { + return err + } + + if _, err := cw.Write(t.Payee); err != nil { + return err + } + + // t.DataSet (big.Int) (struct) + if len("dataSet") > 8192 { + return xerrors.Errorf("Value in field \"dataSet\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("dataSet"))); err != nil { + return err + } + if _, err := cw.WriteString(string("dataSet")); err != nil { + return err + } + + { + if t.DataSet != nil && t.DataSet.Sign() < 0 { + return xerrors.Errorf("Value in field t.DataSet was a negative big-integer (not supported)") + } + if err := cw.CborWriteHeader(cbg.MajTag, 2); err != nil { + return err + } + var b []byte + if t.DataSet != nil { + b = t.DataSet.Bytes() + } + + if err := cw.CborWriteHeader(cbg.MajByteString, uint64(len(b))); err != nil { + return err + } + if _, err := cw.Write(b); err != nil { + return err + } + } + + // t.Metadata (sign.Metadata) (struct) + if len("metadata") > 8192 { + return xerrors.Errorf("Value in field \"metadata\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("metadata"))); err != nil { + return err + } + if _, err := cw.WriteString(string("metadata")); err != nil { + return err + } + + if err := t.Metadata.MarshalCBOR(cw); err != nil { + return err + } + return nil +} + +func (t *DataSetCreateArguments) UnmarshalCBOR(r io.Reader) (err error) { + *t = DataSetCreateArguments{} + + cr := cbg.NewCborReader(r) + + maj, extra, err := cr.ReadHeader() + if err != nil { + return err + } + defer func() { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + }() + + if maj != cbg.MajMap { + return fmt.Errorf("cbor input should be of type map") + } + + if extra > cbg.MaxLength { + return fmt.Errorf("DataSetCreateArguments: map struct too large (%d)", extra) + } + + n := extra + + nameBuf := make([]byte, 8) + for i := uint64(0); i < n; i++ { + nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 8192) + if err != nil { + return err + } + + if !ok { + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil { + return err + } + continue + } + + switch string(nameBuf[:nameLen]) { + // t.Payee ([]uint8) (slice) + case "payee": + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if extra > 2097152 { + return fmt.Errorf("t.Payee: byte array too large (%d)", extra) + } + if maj != cbg.MajByteString { + return fmt.Errorf("expected byte array") + } + + if extra > 0 { + t.Payee = make([]uint8, extra) + } + + if _, err := io.ReadFull(cr, t.Payee); err != nil { + return err + } + + // t.DataSet (big.Int) (struct) + case "dataSet": + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if maj != cbg.MajTag || extra != 2 { + return fmt.Errorf("big ints should be cbor bignums") + } + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if maj != cbg.MajByteString { + return fmt.Errorf("big ints should be tagged cbor byte strings") + } + + if extra > 256 { + return fmt.Errorf("t.DataSet: cbor bignum was too large") + } + + if extra > 0 { + buf := make([]byte, extra) + if _, err := io.ReadFull(cr, buf); err != nil { + return err + } + t.DataSet = big.NewInt(0).SetBytes(buf) + } else { + t.DataSet = big.NewInt(0) + } + // t.Metadata (sign.Metadata) (struct) + case "metadata": + + { + + if err := t.Metadata.UnmarshalCBOR(cr); err != nil { + return xerrors.Errorf("unmarshaling t.Metadata: %w", err) + } + + } + + default: + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil { + return err + } + } + } + + return nil +} +func (t *DataSetDeleteArguments) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + + cw := cbg.NewCborWriter(w) + + if _, err := cw.Write([]byte{161}); err != nil { + return err + } + + // t.DataSet (big.Int) (struct) + if len("dataSet") > 8192 { + return xerrors.Errorf("Value in field \"dataSet\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("dataSet"))); err != nil { + return err + } + if _, err := cw.WriteString(string("dataSet")); err != nil { + return err + } + + { + if t.DataSet != nil && t.DataSet.Sign() < 0 { + return xerrors.Errorf("Value in field t.DataSet was a negative big-integer (not supported)") + } + if err := cw.CborWriteHeader(cbg.MajTag, 2); err != nil { + return err + } + var b []byte + if t.DataSet != nil { + b = t.DataSet.Bytes() + } + + if err := cw.CborWriteHeader(cbg.MajByteString, uint64(len(b))); err != nil { + return err + } + if _, err := cw.Write(b); err != nil { + return err + } + } + return nil +} + +func (t *DataSetDeleteArguments) UnmarshalCBOR(r io.Reader) (err error) { + *t = DataSetDeleteArguments{} + + cr := cbg.NewCborReader(r) + + maj, extra, err := cr.ReadHeader() + if err != nil { + return err + } + defer func() { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + }() + + if maj != cbg.MajMap { + return fmt.Errorf("cbor input should be of type map") + } + + if extra > cbg.MaxLength { + return fmt.Errorf("DataSetDeleteArguments: map struct too large (%d)", extra) + } + + n := extra + + nameBuf := make([]byte, 7) + for i := uint64(0); i < n; i++ { + nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 8192) + if err != nil { + return err + } + + if !ok { + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil { + return err + } + continue + } + + switch string(nameBuf[:nameLen]) { + // t.DataSet (big.Int) (struct) + case "dataSet": + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if maj != cbg.MajTag || extra != 2 { + return fmt.Errorf("big ints should be cbor bignums") + } + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if maj != cbg.MajByteString { + return fmt.Errorf("big ints should be tagged cbor byte strings") + } + + if extra > 256 { + return fmt.Errorf("t.DataSet: cbor bignum was too large") + } + + if extra > 0 { + buf := make([]byte, extra) + if _, err := io.ReadFull(cr, buf); err != nil { + return err + } + t.DataSet = big.NewInt(0).SetBytes(buf) + } else { + t.DataSet = big.NewInt(0) + } + + default: + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil { + return err + } + } + } + + return nil +} +func (t *PiecesAddArguments) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + + cw := cbg.NewCborWriter(w) + + if _, err := cw.Write([]byte{165}); err != nil { + return err + } + + // t.Nonce (big.Int) (struct) + if len("nonce") > 8192 { + return xerrors.Errorf("Value in field \"nonce\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("nonce"))); err != nil { + return err + } + if _, err := cw.WriteString(string("nonce")); err != nil { + return err + } + + { + if t.Nonce != nil && t.Nonce.Sign() < 0 { + return xerrors.Errorf("Value in field t.Nonce was a negative big-integer (not supported)") + } + if err := cw.CborWriteHeader(cbg.MajTag, 2); err != nil { + return err + } + var b []byte + if t.Nonce != nil { + b = t.Nonce.Bytes() + } + + if err := cw.CborWriteHeader(cbg.MajByteString, uint64(len(b))); err != nil { + return err + } + if _, err := cw.Write(b); err != nil { + return err + } + } + + // t.Proofs ([]sign.PieceProofs) (slice) + if len("proofs") > 8192 { + return xerrors.Errorf("Value in field \"proofs\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("proofs"))); err != nil { + return err + } + if _, err := cw.WriteString(string("proofs")); err != nil { + return err + } + + if len(t.Proofs) > 8192 { + return xerrors.Errorf("Slice value in field t.Proofs was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajArray, uint64(len(t.Proofs))); err != nil { + return err + } + for _, v := range t.Proofs { + if err := v.MarshalCBOR(cw); err != nil { + return err + } + + } + + // t.DataSet (big.Int) (struct) + if len("dataSet") > 8192 { + return xerrors.Errorf("Value in field \"dataSet\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("dataSet"))); err != nil { + return err + } + if _, err := cw.WriteString(string("dataSet")); err != nil { + return err + } + + { + if t.DataSet != nil && t.DataSet.Sign() < 0 { + return xerrors.Errorf("Value in field t.DataSet was a negative big-integer (not supported)") + } + if err := cw.CborWriteHeader(cbg.MajTag, 2); err != nil { + return err + } + var b []byte + if t.DataSet != nil { + b = t.DataSet.Bytes() + } + + if err := cw.CborWriteHeader(cbg.MajByteString, uint64(len(b))); err != nil { + return err + } + if _, err := cw.Write(b); err != nil { + return err + } + } + + // t.Metadata ([]sign.Metadata) (slice) + if len("metadata") > 8192 { + return xerrors.Errorf("Value in field \"metadata\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("metadata"))); err != nil { + return err + } + if _, err := cw.WriteString(string("metadata")); err != nil { + return err + } + + if len(t.Metadata) > 8192 { + return xerrors.Errorf("Slice value in field t.Metadata was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajArray, uint64(len(t.Metadata))); err != nil { + return err + } + for _, v := range t.Metadata { + if err := v.MarshalCBOR(cw); err != nil { + return err + } + + } + + // t.PieceData ([][]uint8) (slice) + if len("pieceData") > 8192 { + return xerrors.Errorf("Value in field \"pieceData\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("pieceData"))); err != nil { + return err + } + if _, err := cw.WriteString(string("pieceData")); err != nil { + return err + } + + if len(t.PieceData) > 8192 { + return xerrors.Errorf("Slice value in field t.PieceData was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajArray, uint64(len(t.PieceData))); err != nil { + return err + } + for _, v := range t.PieceData { + if len(v) > 2097152 { + return xerrors.Errorf("Byte array in field v was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajByteString, uint64(len(v))); err != nil { + return err + } + + if _, err := cw.Write(v); err != nil { + return err + } + + } + return nil +} + +func (t *PiecesAddArguments) UnmarshalCBOR(r io.Reader) (err error) { + *t = PiecesAddArguments{} + + cr := cbg.NewCborReader(r) + + maj, extra, err := cr.ReadHeader() + if err != nil { + return err + } + defer func() { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + }() + + if maj != cbg.MajMap { + return fmt.Errorf("cbor input should be of type map") + } + + if extra > cbg.MaxLength { + return fmt.Errorf("PiecesAddArguments: map struct too large (%d)", extra) + } + + n := extra + + nameBuf := make([]byte, 9) + for i := uint64(0); i < n; i++ { + nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 8192) + if err != nil { + return err + } + + if !ok { + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil { + return err + } + continue + } + + switch string(nameBuf[:nameLen]) { + // t.Nonce (big.Int) (struct) + case "nonce": + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if maj != cbg.MajTag || extra != 2 { + return fmt.Errorf("big ints should be cbor bignums") + } + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if maj != cbg.MajByteString { + return fmt.Errorf("big ints should be tagged cbor byte strings") + } + + if extra > 256 { + return fmt.Errorf("t.Nonce: cbor bignum was too large") + } + + if extra > 0 { + buf := make([]byte, extra) + if _, err := io.ReadFull(cr, buf); err != nil { + return err + } + t.Nonce = big.NewInt(0).SetBytes(buf) + } else { + t.Nonce = big.NewInt(0) + } + // t.Proofs ([]sign.PieceProofs) (slice) + case "proofs": + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if extra > 8192 { + return fmt.Errorf("t.Proofs: array too large (%d)", extra) + } + + if maj != cbg.MajArray { + return fmt.Errorf("expected cbor array") + } + + if extra > 0 { + t.Proofs = make([]PieceProofs, extra) + } + + for i := 0; i < int(extra); i++ { + { + var maj byte + var extra uint64 + var err error + _ = maj + _ = extra + _ = err + + { + + if err := t.Proofs[i].UnmarshalCBOR(cr); err != nil { + return xerrors.Errorf("unmarshaling t.Proofs[i]: %w", err) + } + + } + + } + } + // t.DataSet (big.Int) (struct) + case "dataSet": + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if maj != cbg.MajTag || extra != 2 { + return fmt.Errorf("big ints should be cbor bignums") + } + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if maj != cbg.MajByteString { + return fmt.Errorf("big ints should be tagged cbor byte strings") + } + + if extra > 256 { + return fmt.Errorf("t.DataSet: cbor bignum was too large") + } + + if extra > 0 { + buf := make([]byte, extra) + if _, err := io.ReadFull(cr, buf); err != nil { + return err + } + t.DataSet = big.NewInt(0).SetBytes(buf) + } else { + t.DataSet = big.NewInt(0) + } + // t.Metadata ([]sign.Metadata) (slice) + case "metadata": + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if extra > 8192 { + return fmt.Errorf("t.Metadata: array too large (%d)", extra) + } + + if maj != cbg.MajArray { + return fmt.Errorf("expected cbor array") + } + + if extra > 0 { + t.Metadata = make([]Metadata, extra) + } + + for i := 0; i < int(extra); i++ { + { + var maj byte + var extra uint64 + var err error + _ = maj + _ = extra + _ = err + + { + + if err := t.Metadata[i].UnmarshalCBOR(cr); err != nil { + return xerrors.Errorf("unmarshaling t.Metadata[i]: %w", err) + } + + } + + } + } + // t.PieceData ([][]uint8) (slice) + case "pieceData": + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if extra > 8192 { + return fmt.Errorf("t.PieceData: array too large (%d)", extra) + } + + if maj != cbg.MajArray { + return fmt.Errorf("expected cbor array") + } + + if extra > 0 { + t.PieceData = make([][]uint8, extra) + } + + for i := 0; i < int(extra); i++ { + { + var maj byte + var extra uint64 + var err error + _ = maj + _ = extra + _ = err + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if extra > 2097152 { + return fmt.Errorf("t.PieceData[i]: byte array too large (%d)", extra) + } + if maj != cbg.MajByteString { + return fmt.Errorf("expected byte array") + } + + if extra > 0 { + t.PieceData[i] = make([]uint8, extra) + } + + if _, err := io.ReadFull(cr, t.PieceData[i]); err != nil { + return err + } + + } + } + + default: + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil { + return err + } + } + } + + return nil +} +func (t *PiecesRemoveScheduleArguments) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + + cw := cbg.NewCborWriter(w) + + if _, err := cw.Write([]byte{162}); err != nil { + return err + } + + // t.Pieces ([]*big.Int) (slice) + if len("pieces") > 8192 { + return xerrors.Errorf("Value in field \"pieces\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("pieces"))); err != nil { + return err + } + if _, err := cw.WriteString(string("pieces")); err != nil { + return err + } + + if len(t.Pieces) > 8192 { + return xerrors.Errorf("Slice value in field t.Pieces was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajArray, uint64(len(t.Pieces))); err != nil { + return err + } + for _, v := range t.Pieces { + { + if v != nil && v.Sign() < 0 { + return xerrors.Errorf("Value in field v was a negative big-integer (not supported)") + } + if err := cw.CborWriteHeader(cbg.MajTag, 2); err != nil { + return err + } + var b []byte + if v != nil { + b = v.Bytes() + } + + if err := cw.CborWriteHeader(cbg.MajByteString, uint64(len(b))); err != nil { + return err + } + if _, err := cw.Write(b); err != nil { + return err + } + } + + } + + // t.DataSet (big.Int) (struct) + if len("dataSet") > 8192 { + return xerrors.Errorf("Value in field \"dataSet\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("dataSet"))); err != nil { + return err + } + if _, err := cw.WriteString(string("dataSet")); err != nil { + return err + } + + { + if t.DataSet != nil && t.DataSet.Sign() < 0 { + return xerrors.Errorf("Value in field t.DataSet was a negative big-integer (not supported)") + } + if err := cw.CborWriteHeader(cbg.MajTag, 2); err != nil { + return err + } + var b []byte + if t.DataSet != nil { + b = t.DataSet.Bytes() + } + + if err := cw.CborWriteHeader(cbg.MajByteString, uint64(len(b))); err != nil { + return err + } + if _, err := cw.Write(b); err != nil { + return err + } + } + return nil +} + +func (t *PiecesRemoveScheduleArguments) UnmarshalCBOR(r io.Reader) (err error) { + *t = PiecesRemoveScheduleArguments{} + + cr := cbg.NewCborReader(r) + + maj, extra, err := cr.ReadHeader() + if err != nil { + return err + } + defer func() { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + }() + + if maj != cbg.MajMap { + return fmt.Errorf("cbor input should be of type map") + } + + if extra > cbg.MaxLength { + return fmt.Errorf("PiecesRemoveScheduleArguments: map struct too large (%d)", extra) + } + + n := extra + + nameBuf := make([]byte, 7) + for i := uint64(0); i < n; i++ { + nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 8192) + if err != nil { + return err + } + + if !ok { + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil { + return err + } + continue + } + + switch string(nameBuf[:nameLen]) { + // t.Pieces ([]*big.Int) (slice) + case "pieces": + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if extra > 8192 { + return fmt.Errorf("t.Pieces: array too large (%d)", extra) + } + + if maj != cbg.MajArray { + return fmt.Errorf("expected cbor array") + } + + if extra > 0 { + t.Pieces = make([]*big.Int, extra) + } + + for i := 0; i < int(extra); i++ { + { + var maj byte + var extra uint64 + var err error + _ = maj + _ = extra + _ = err + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if maj != cbg.MajTag || extra != 2 { + return fmt.Errorf("big ints should be cbor bignums") + } + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if maj != cbg.MajByteString { + return fmt.Errorf("big ints should be tagged cbor byte strings") + } + + if extra > 256 { + return fmt.Errorf("t.Pieces[i]: cbor bignum was too large") + } + + if extra > 0 { + buf := make([]byte, extra) + if _, err := io.ReadFull(cr, buf); err != nil { + return err + } + t.Pieces[i] = big.NewInt(0).SetBytes(buf) + } else { + t.Pieces[i] = big.NewInt(0) + } + + } + } + // t.DataSet (big.Int) (struct) + case "dataSet": + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if maj != cbg.MajTag || extra != 2 { + return fmt.Errorf("big ints should be cbor bignums") + } + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if maj != cbg.MajByteString { + return fmt.Errorf("big ints should be tagged cbor byte strings") + } + + if extra > 256 { + return fmt.Errorf("t.DataSet: cbor bignum was too large") + } + + if extra > 0 { + buf := make([]byte, extra) + if _, err := io.ReadFull(cr, buf); err != nil { + return err + } + t.DataSet = big.NewInt(0).SetBytes(buf) + } else { + t.DataSet = big.NewInt(0) + } + + default: + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil { + return err + } + } + } + + return nil +} diff --git a/commands/pdp/sign/gen/main.go b/commands/pdp/sign/gen/main.go new file mode 100644 index 0000000..98aa1d0 --- /dev/null +++ b/commands/pdp/sign/gen/main.go @@ -0,0 +1,49 @@ +//go:generate go run -tags codegen . + +package main + +import ( + "os" + + cbg "github.com/whyrusleeping/cbor-gen" + + "github.com/fil-forge/libforge/commands/pdp/sign" +) + +// The parent sign package has bindcap.New calls that require codec methods +// to exist on the argument types. Those codecs are what this tool +// generates. To break the bootstrap, bindings and generated codec files +// carry `//go:build !codegen`; this tool is built with `-tags codegen`, so +// the import of `sign` here only pulls in the wire types from types.go. +// +// After cbor-gen writes the codec file, we re-tag it with the same +// constraint so subsequent codegen runs are stale-safe. +const buildTag = "//go:build !codegen\n\n" + +func tag(path string) { + data, err := os.ReadFile(path) + if err != nil { + panic(err) + } + if err := os.WriteFile(path, append([]byte(buildTag), data...), 0644); err != nil { + panic(err) + } +} + +func main() { + models := []any{ + sign.AuthSignature{}, + sign.Metadata{}, + sign.PieceProofs{}, + sign.DataSetCreateArguments{}, + sign.DataSetDeleteArguments{}, + sign.PiecesAddArguments{}, + sign.PiecesRemoveScheduleArguments{}, + } + const cborFile = "../cbor_gen.go" + // The stack is CBOR-only on the wire, so we don't generate dag-json codecs. + if err := cbg.WriteMapEncodersToFile(cborFile, "sign", models...); err != nil { + panic(err) + } + tag(cborFile) +} diff --git a/commands/pdp/sign/sign.go b/commands/pdp/sign/sign.go new file mode 100644 index 0000000..fcd462c --- /dev/null +++ b/commands/pdp/sign/sign.go @@ -0,0 +1,23 @@ +//go:build !codegen + +package sign + +import ( + "github.com/fil-forge/libforge/commands" +) + +// Every /pdp/sign/* operation returns the same shape; these per-operation +// labels exist so call sites can keep the operation name in the type. +type ( + DataSetCreateOK = AuthSignature + DataSetDeleteOK = AuthSignature + PiecesAddOK = AuthSignature + PiecesRemoveScheduleOK = AuthSignature +) + +var ( + DataSetCreate = commands.MustParse[*DataSetCreateArguments]("/pdp/sign/dataset/create") + DataSetDelete = commands.MustParse[*DataSetDeleteArguments]("/pdp/sign/dataset/delete") + PiecesAdd = commands.MustParse[*PiecesAddArguments]("/pdp/sign/pieces/add") + PiecesRemoveSchedule = commands.MustParse[*PiecesRemoveScheduleArguments]("/pdp/sign/pieces/remove/schedule") +) diff --git a/commands/pdp/sign/types.go b/commands/pdp/sign/types.go new file mode 100644 index 0000000..ef5cd2a --- /dev/null +++ b/commands/pdp/sign/types.go @@ -0,0 +1,88 @@ +// Package sign exposes the four /pdp/sign/* UCAN capabilities used by piri +// to drive an eip712 signing service: +// +// - /pdp/sign/dataset/create +// - /pdp/sign/dataset/delete +// - /pdp/sign/pieces/add +// - /pdp/sign/pieces/remove/schedule +// +// Each returns an [AuthSignature] (an eip712-signed bytes payload). +// +// Wire-level conventions: +// +// - `*big.Int` fields (DataSet, Nonce, Pieces) are encoded as CBOR +// bignums (tag 2). cbor-gen does not support negative bignums; the +// domain (dataset IDs, nonces, piece IDs) is non-negative. +// +// - `common.Address` (20 bytes) and `common.Hash` (32 bytes) are plain +// `[]byte`; length validation is left to the caller. +package sign + +import ( + "math/big" + + "github.com/ipfs/go-cid" +) + +// AuthSignature is the eip712 auth signature returned from every +// /pdp/sign/* invocation. Field semantics mirror +// filecoin-services/go/eip712.AuthSignature. +type AuthSignature struct { + Signature []byte `cborgen:"signature" dagjsongen:"signature"` + V uint8 `cborgen:"v" dagjsongen:"v"` + R []byte `cborgen:"r" dagjsongen:"r"` + S []byte `cborgen:"s" dagjsongen:"s"` + SignedData []byte `cborgen:"signedData" dagjsongen:"signedData"` + Signer []byte `cborgen:"signer" dagjsongen:"signer"` +} + +// Metadata is the eip712 metadata bag attached to dataset & piece signing +// requests. Keys carries insertion order so the wire encoding is +// deterministic across implementations. +type Metadata struct { + Keys []string `cborgen:"keys" dagjsongen:"keys"` + Values map[string]string `cborgen:"values" dagjsongen:"values"` +} + +// PieceProofs wraps the list of `blob/accept` invocation links proving the +// sub-pieces of one piece in a /pdp/sign/pieces/add request. cborgen does +// not natively encode `[][]cid.Cid`, so this single-level wrapper turns +// the outer slice into `[]PieceProofs`. +type PieceProofs struct { + Proofs []cid.Cid `cborgen:"proofs" dagjsongen:"proofs"` +} + +// DataSetCreateArguments are the arguments for /pdp/sign/dataset/create. +type DataSetCreateArguments struct { + DataSet *big.Int `cborgen:"dataSet" dagjsongen:"dataSet"` + Payee []byte `cborgen:"payee" dagjsongen:"payee"` + Metadata Metadata `cborgen:"metadata" dagjsongen:"metadata"` +} + +// DataSetDeleteArguments are the arguments for /pdp/sign/dataset/delete. +type DataSetDeleteArguments struct { + DataSet *big.Int `cborgen:"dataSet" dagjsongen:"dataSet"` +} + +// PiecesAddArguments are the arguments for /pdp/sign/pieces/add. +// +// Each entry in PieceData has a matching Metadata entry and a matching +// Proofs entry. The Proofs[i].Proofs list links to `blob/accept` +// invocations for every sub-piece of piece i. Each `blob/accept` receipt +// MUST include the corresponding `pdp/accept` effect receipt; all receipt +// data MUST be attached to the signing invocation's container as proof +// blocks. +type PiecesAddArguments struct { + DataSet *big.Int `cborgen:"dataSet" dagjsongen:"dataSet"` + Nonce *big.Int `cborgen:"nonce" dagjsongen:"nonce"` + PieceData [][]byte `cborgen:"pieceData" dagjsongen:"pieceData"` + Metadata []Metadata `cborgen:"metadata" dagjsongen:"metadata"` + Proofs []PieceProofs `cborgen:"proofs" dagjsongen:"proofs"` +} + +// PiecesRemoveScheduleArguments are the arguments for +// /pdp/sign/pieces/remove/schedule. +type PiecesRemoveScheduleArguments struct { + DataSet *big.Int `cborgen:"dataSet" dagjsongen:"dataSet"` + Pieces []*big.Int `cborgen:"pieces" dagjsongen:"pieces"` +} diff --git a/commands/pdp/types.go b/commands/pdp/types.go new file mode 100644 index 0000000..4c614b2 --- /dev/null +++ b/commands/pdp/types.go @@ -0,0 +1,31 @@ +package pdp + +import ( + "github.com/filecoin-project/go-data-segment/merkletree" + "github.com/ipfs/go-cid" + "github.com/multiformats/go-multihash" +) + +type AcceptArguments struct { + Blob multihash.Multihash `cborgen:"blob" dagjsongen:"blob"` +} + +type AcceptOK struct { + Aggregate cid.Cid `cborgen:"aggregate" dagjsongen:"aggregate"` + InclusionProof merkletree.ProofData `cborgen:"inclusionProof" dagjsongen:"inclusionProof"` + Piece cid.Cid `cborgen:"piece" dagjsongen:"piece"` +} + +type InfoArguments struct { + Blob multihash.Multihash `cborgen:"blob" dagjsongen:"blob"` +} + +type InfoAcceptedAggregate struct { + Aggregate cid.Cid `cborgen:"aggregate" dagjsongen:"aggregate"` + InclusionProof merkletree.ProofData `cborgen:"inclusionProof" dagjsongen:"inclusionProof"` +} + +type InfoOK struct { + Piece cid.Cid `cborgen:"piece" dagjsongen:"piece"` + Aggregates []InfoAcceptedAggregate `cborgen:"aggregates" dagjsongen:"aggregates"` +} diff --git a/go.mod b/go.mod index 9b346ee..f93e16d 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/alanshaw/dag-json-gen v0.0.5 github.com/fil-forge/automobile v0.0.1 github.com/fil-forge/ucantone v0.0.0-20260519193222-ad31490eaa10 + github.com/filecoin-project/go-data-segment v0.0.1 github.com/gobwas/glob v0.2.3 github.com/ipfs/go-cid v0.6.1 github.com/ipfs/go-log/v2 v2.9.1 @@ -33,6 +34,7 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.1 // indirect golang.org/x/crypto v0.50.0 // indirect + golang.org/x/exp v0.0.0-20230418202329-0354be287a23 // indirect golang.org/x/sys v0.43.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect lukechampine.com/blake3 v1.4.1 // indirect diff --git a/go.sum b/go.sum index 2278b41..7a817f3 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,10 @@ github.com/fil-forge/automobile v0.0.1 h1:9xB3yc4l5b9EdRJSJcNwudgBFNHoMPEAdcb7Gf github.com/fil-forge/automobile v0.0.1/go.mod h1:TsO7jlO8ykJZY5tF8j4GsUcu3F02lEzxO7ULoB61hRA= github.com/fil-forge/ucantone v0.0.0-20260519193222-ad31490eaa10 h1:ApgWAIpXjCYjZw/yDxLn8IA9WrH/ENPRWCWPT/MoCvU= github.com/fil-forge/ucantone v0.0.0-20260519193222-ad31490eaa10/go.mod h1:vqgVEsy6LEEsY24Zyjxem0vSofj1XTIx29GbV635f+I= +github.com/filecoin-project/go-data-segment v0.0.1 h1:1wmDxOG4ubWQm3ZC1XI5nCon5qgSq7Ra3Rb6Dbu10Gs= +github.com/filecoin-project/go-data-segment v0.0.1/go.mod h1:H0/NKbsRxmRFBcLibmABv+yFNHdmtl5AyplYLnb0Zv4= +github.com/filecoin-project/go-fil-commcid v0.1.0 h1:3R4ds1A9r6cr8mvZBfMYxTS88OqLYEo6roi+GiIeOh8= +github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/ipfs/go-cid v0.6.1 h1:T5TnNb08+ueovG76Z5gx1L4Y7QOaGTXHg1F6raWFxIc= @@ -60,6 +64,8 @@ go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= +golang.org/x/exp v0.0.0-20230418202329-0354be287a23 h1:4NKENAGIctmZYLK9W+X1kDK8ObBFqOSCJM6WE7CvkJY= +golang.org/x/exp v0.0.0-20230418202329-0354be287a23/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= diff --git a/ucan/retrieval/client_test.go b/ucan/retrieval/client_test.go index ef3b3dc..beb73e2 100644 --- a/ucan/retrieval/client_test.go +++ b/ucan/retrieval/client_test.go @@ -9,7 +9,6 @@ import ( "net/url" "testing" - "github.com/fil-forge/libforge/ucan/retrieval" "github.com/fil-forge/ucantone/execution" "github.com/fil-forge/ucantone/ipld/datamodel" "github.com/fil-forge/ucantone/principal" @@ -18,6 +17,8 @@ import ( "github.com/fil-forge/ucantone/ucan/container" "github.com/fil-forge/ucantone/ucan/invocation" "github.com/stretchr/testify/require" + + "github.com/fil-forge/libforge/ucan/retrieval" ) // startTestServer spins up a retrieval server that registers the given @@ -58,7 +59,7 @@ func TestClient(t *testing.T) { inv, err := contentRetrieve.Invoke( alice, alice.DID(), - datamodel.Map{}, + &datamodel.Map{}, invocation.WithAudience(service.DID()), ) require.NoError(t, err) @@ -107,7 +108,7 @@ func TestClient(t *testing.T) { inv, err := contentRetrieve.Invoke( alice, alice.DID(), - datamodel.Map{}, + &datamodel.Map{}, invocation.WithAudience(service.DID()), ) require.NoError(t, err) @@ -132,7 +133,7 @@ func TestClient(t *testing.T) { inv, err := contentRetrieve.Invoke( alice, alice.DID(), - datamodel.Map{}, + &datamodel.Map{}, invocation.WithAudience(service.DID()), ) require.NoError(t, err) @@ -163,7 +164,7 @@ func TestClient(t *testing.T) { inv, err := contentRetrieve.Invoke( alice, alice.DID(), - datamodel.Map{}, + &datamodel.Map{}, invocation.WithAudience(service.DID()), ) require.NoError(t, err) diff --git a/ucan/retrieval/server_test.go b/ucan/retrieval/server_test.go index 1286883..9b02d3b 100644 --- a/ucan/retrieval/server_test.go +++ b/ucan/retrieval/server_test.go @@ -8,7 +8,6 @@ import ( "net/url" "testing" - "github.com/fil-forge/libforge/ucan/retrieval" "github.com/fil-forge/ucantone/execution" "github.com/fil-forge/ucantone/ipld/datamodel" "github.com/fil-forge/ucantone/testutil" @@ -16,9 +15,11 @@ import ( "github.com/fil-forge/ucantone/ucan/invocation" "github.com/fil-forge/ucantone/validator/bindcom" "github.com/stretchr/testify/require" + + "github.com/fil-forge/libforge/ucan/retrieval" ) -var contentRetrieve, _ = bindcom.Parse[datamodel.Map]("/content/retrieve") +var contentRetrieve, _ = bindcom.Parse[*datamodel.Map]("/content/retrieve") func TestServer(t *testing.T) { service := testutil.RandomSigner(t) @@ -62,7 +63,7 @@ func TestServer(t *testing.T) { inv, err := contentRetrieve.Invoke( alice, alice.DID(), - datamodel.Map{}, + &datamodel.Map{}, invocation.WithAudience(service.DID()), ) require.NoError(t, err)