11package blockstore
22
33import (
4- "bytes"
54 "context"
65 "errors"
76 "fmt"
@@ -146,19 +145,19 @@ func NewForge(cfg ForgeConfig) (*Forge, error) {
146145// empty 200 when it can't resolve a did:plc principal in the proof chain)
147146// otherwise surfaces only as a bare client-side EOF mid-body, with nothing
148147// attributable in ingot's own logs.
149- // off/n select a sub-range of the located bytes: stored bytes [off, off+n)
150- // of the blob. n < 0 retrieves the locator's whole range (the entire blob,
148+ // start/end select an inclusive sub-range of the located bytes (HTTP Range
149+ // semantics). end < 0 retrieves the locator's whole range (the entire blob,
151150// for a body blob).
152- func (f * Forge ) retrieve (ctx context.Context , space did.DID , digest mh.Multihash , off , n int64 ) (io.ReadCloser , int64 , error ) {
153- rc , got , err := f .doRetrieve (ctx , space , digest , off , n )
151+ func (f * Forge ) retrieve (ctx context.Context , space did.DID , digest mh.Multihash , start , end int64 ) (io.ReadCloser , int64 , error ) {
152+ rc , got , err := f .doRetrieve (ctx , space , digest , start , end )
154153 if err != nil && ! errors .Is (err , ErrNotFound ) {
155154 f .logger .Warn ("forge: retrieve failed" ,
156155 zap .Stringer ("space" , space ), zap .String ("digest" , digestutil .Format (digest )), zap .Error (err ))
157156 }
158157 return rc , got , err
159158}
160159
161- func (f * Forge ) doRetrieve (ctx context.Context , space did.DID , digest mh.Multihash , off , n int64 ) (io.ReadCloser , int64 , error ) {
160+ func (f * Forge ) doRetrieve (ctx context.Context , space did.DID , digest mh.Multihash , start , end int64 ) (io.ReadCloser , int64 , error ) {
162161 locations , err := f .locator .Locate (ctx , []did.DID {space }, digest )
163162 if err != nil {
164163 var nf locator.NotFoundError
@@ -178,21 +177,21 @@ func (f *Forge) doRetrieve(ctx context.Context, space did.DID, digest mh.Multiha
178177 }
179178 target := cm .Location [0 ]
180179
181- // Narrow the located range to the caller's sub-range. loc.Range is
182- // inclusive and, for a whole blob, starts at 0 — so the sub-range is
183- // [ Start+off, Start+off+n-1 ], clamped to the located end. The decrypting
184- // read path uses this to fetch only the ciphertext chunks it needs.
185- if n >= 0 {
186- start := loc . Range . Start + off
187- if start > loc .Range .End || n == 0 {
188- // Nothing to fetch; an empty body keeps the contract simple.
189- return io . NopCloser ( bytes . NewReader ( nil )) , 0 , nil
180+ // Narrow the located range to the caller's inclusive sub-range. loc.Range
181+ // is inclusive too and, for a whole blob, starts at 0 — so the sub-range
182+ // maps to [Range. Start+start, Range. Start+end ], with the end clamped to
183+ // the located end (HTTP Range semantics). The decrypting read path uses
184+ // this to fetch only the ciphertext chunks it needs.
185+ if end >= 0 {
186+ first := loc .Range .Start + start
187+ if start < 0 || end < start || first > loc . Range . End {
188+ return nil , 0 , fmt . Errorf ( "forge: range [%d,%d] of %s is unsatisfiable" , start , end , digestutil . Format ( digest ))
190189 }
191- end := start + n - 1
192- if end > loc .Range .End {
193- end = loc .Range .End
190+ last := loc . Range . Start + end
191+ if last > loc .Range .End {
192+ last = loc .Range .End
194193 }
195- loc .Range = blobindex.Range {Start : start , End : end }
194+ loc .Range = blobindex.Range {Start : first , End : last }
196195 }
197196
198197 // The commitment's space scopes the retrieve capability; fall back to
@@ -286,11 +285,12 @@ func (f *Forge) OpenBlob(ctx context.Context, space did.DID, digest mh.Multihash
286285 return rc , err
287286}
288287
289- // OpenBlobRange streams stored bytes [off, off+n) of an object-body blob from
290- // piri — a ranged /content/retrieve, so the decrypting read path fetches only
291- // the ciphertext chunks a plaintext range needs rather than the whole blob.
292- func (f * Forge ) OpenBlobRange (ctx context.Context , space did.DID , digest mh.Multihash , off , n int64 ) (io.ReadCloser , error ) {
293- rc , _ , err := f .retrieve (ctx , space , digest , off , n )
288+ // OpenBlobRange streams stored bytes [start, end] (inclusive) of an
289+ // object-body blob from piri — a ranged /content/retrieve, so the decrypting
290+ // read path fetches only the ciphertext chunks a plaintext range needs
291+ // rather than the whole blob.
292+ func (f * Forge ) OpenBlobRange (ctx context.Context , space did.DID , digest mh.Multihash , start , end int64 ) (io.ReadCloser , error ) {
293+ rc , _ , err := f .retrieve (ctx , space , digest , start , end )
294294 return rc , err
295295}
296296
0 commit comments