55package store
66
77import (
8+ "bytes"
89 "context"
910 "encoding/json"
11+ "slices"
1012 "sort"
1113
1214 cid "github.com/ipfs/go-cid"
@@ -46,21 +48,26 @@ func init() {
4648 LensBlockSchema , LensBlockSchemaPrototype = mustSetSchema (
4749 "lensBlock" ,
4850 & LensBlock {},
51+ & Chunks {},
4952 )
5053}
5154
52- func mustSetSchema (schemaName string , schema schemaDefinition ) (schema.Type , ipld.NodePrototype ) {
53- ts , err := ipld .LoadSchemaBytes (schema .IPLDSchemaBytes ())
55+ func mustSetSchema (schemaName string , schemas ... schemaDefinition ) (schema.Type , ipld.NodePrototype ) {
56+ schemaBytes := make ([][]byte , 0 , len (schemas ))
57+ for _ , s := range schemas {
58+ schemaBytes = append (schemaBytes , s .IPLDSchemaBytes ())
59+ }
60+
61+ ts , err := ipld .LoadSchemaBytes (bytes .Join (schemaBytes , nil ))
5462 if err != nil {
5563 panic (err )
5664 }
57-
5865 schemaType := ts .TypeByName (schemaName )
5966
6067 // Calling bindnode.Prototype here ensure that [Block] and all the types it contains
6168 // are compatible with the IPLD schema defined by [schemaDefinition].
6269 // If [Block] and [schemaType] do not match, this will panic.
63- proto := bindnode .Prototype (schema , schemaType )
70+ proto := bindnode .Prototype (schemas [ 0 ] , schemaType )
6471
6572 return schemaType , proto .Representation ()
6673}
@@ -107,8 +114,84 @@ var _ schemaDefinition = (*ModuleBlock)(nil)
107114//
108115// A single LensBlock maybe referenced by an unlimited number of lens modules/configurations.
109116type LensBlock struct {
117+ // If the total number of bytes is deemed too large for ipfs to transport we chunk the block
118+ // into multiple child blocks.
119+ //
120+ // This is governed by our `maxBlockSize` parameter/option.
121+ Chunks * Chunks
122+
110123 // WasmBytes is the executable wasm binary of the lens.
111- WasmBytes []byte
124+ //
125+ // Or, if the bytes are too large for ipfs to transport, a chunk of those bytes.
126+ WasmBytes * []byte
127+ }
128+
129+ var _ schemaDefinition = (* LensBlock )(nil )
130+
131+ type Chunks []datamodel.Link
132+
133+ var _ schemaDefinition = (* Chunks )(nil )
134+
135+ func storeLensBlock (
136+ ctx context.Context ,
137+ linkSys * linking.LinkSystem ,
138+ wasmBytes []byte ,
139+ maxBlockSize int ,
140+ ) (datamodel.Link , error ) {
141+ chunkBytes := [][]byte {}
142+ for chunk := range slices .Chunk (wasmBytes , maxBlockSize ) {
143+ chunkBytes = append (chunkBytes , chunk )
144+ }
145+
146+ if len (chunkBytes ) == 1 {
147+ block := LensBlock {
148+ WasmBytes : & chunkBytes [0 ],
149+ }
150+ return linkSys .Store (linking.LinkContext {Ctx : ctx }, getLinkPrototype (), block .generateNode ())
151+ }
152+
153+ links := []datamodel.Link {}
154+ for _ , chunk := range chunkBytes {
155+ block := & LensBlock {
156+ WasmBytes : & chunk ,
157+ }
158+
159+ link , err := linkSys .Store (linking.LinkContext {Ctx : ctx }, getLinkPrototype (), block .generateNode ())
160+ if err != nil {
161+ return nil , err
162+ }
163+
164+ links = append (links , link )
165+ }
166+
167+ chunkLinks := Chunks (links )
168+ block := LensBlock {
169+ Chunks : & chunkLinks ,
170+ }
171+ return linkSys .Store (linking.LinkContext {Ctx : ctx }, getLinkPrototype (), block .generateNode ())
172+ }
173+
174+ func (b * LensBlock ) Bytes (ctx context.Context , linkSys * linking.LinkSystem ) ([]byte , error ) {
175+ switch {
176+ case b .WasmBytes != nil :
177+ return * b .WasmBytes , nil
178+ case b .Chunks != nil :
179+ var buf bytes.Buffer
180+ for _ , chunk := range * b .Chunks {
181+ lensNode , err := linkSys .Load (linking.LinkContext {Ctx : ctx }, chunk , LensBlockSchemaPrototype )
182+ if err != nil {
183+ return nil , err
184+ }
185+ lensBlock := bindnode .Unwrap (lensNode ).(* LensBlock )
186+ b , err := lensBlock .Bytes (ctx , linkSys )
187+ if err != nil {
188+ return nil , err
189+ }
190+ buf .Write (b )
191+ }
192+ return buf .Bytes (), nil
193+ }
194+ return nil , nil
112195}
113196
114197var _ schemaDefinition = (* LensBlock )(nil )
@@ -137,9 +220,16 @@ func (b *ModuleBlock) IPLDSchemaBytes() []byte {
137220
138221func (b * LensBlock ) IPLDSchemaBytes () []byte {
139222 return []byte (`
140- type lensBlock struct {
141- wasmBytes Bytes
142- }
223+ type lensBlock union {
224+ | chunks "chunks"
225+ | Bytes "wasmBytes"
226+ } representation keyed
227+ ` )
228+ }
229+
230+ func (b * Chunks ) IPLDSchemaBytes () []byte {
231+ return []byte (`
232+ type chunks [Link]
143233 ` )
144234}
145235
@@ -185,15 +275,20 @@ func LoadLensModel(ctx context.Context, linkSys *linking.LinkSystem, cid cid.Cid
185275 }
186276 }
187277
188- lensNode , err := linkSys .Load (ipld .LinkContext {Ctx : ctx }, moduleBlock .Lens , LensBlockSchemaPrototype )
278+ lensNode , err := linkSys .Load (linking .LinkContext {Ctx : ctx }, moduleBlock .Lens , LensBlockSchemaPrototype )
189279 if err != nil {
190280 return model.Lens {}, err
191281 }
192282 lensBlock := bindnode .Unwrap (lensNode ).(* LensBlock )
193283
284+ wasmBytes , err := lensBlock .Bytes (ctx , linkSys )
285+ if err != nil {
286+ return model.Lens {}, err
287+ }
288+
194289 var path string
195- if len (lensBlock . WasmBytes ) != 0 {
196- path = "data:application/octet-stream," + string (lensBlock . WasmBytes )
290+ if len (wasmBytes ) != 0 {
291+ path = "data:application/octet-stream," + string (wasmBytes )
197292 }
198293
199294 result .Lenses = append (result .Lenses , model.LensModule {
@@ -209,6 +304,7 @@ func LoadLensModel(ctx context.Context, linkSys *linking.LinkSystem, cid cid.Cid
209304func writeConfigBlock (
210305 ctx context.Context ,
211306 linkSys * linking.LinkSystem ,
307+ maxBlockSize int ,
212308 cfg model.Lens ,
213309) (datamodel.Link , error ) {
214310 moduleLinks := make ([]datamodel.Link , 0 , len (cfg .Lenses ))
@@ -218,11 +314,8 @@ func writeConfigBlock(
218314 if err != nil {
219315 return nil , err
220316 }
221- lensBlock := LensBlock {
222- WasmBytes : wasmBytes ,
223- }
224317
225- lensLink , err := linkSys . Store (linking. LinkContext { Ctx : ctx }, getLinkPrototype (), lensBlock . generateNode () )
318+ lensLink , err := storeLensBlock ( ctx , linkSys , wasmBytes , maxBlockSize )
226319 if err != nil {
227320 return nil , err
228321 }
0 commit comments