Skip to content

Commit

Permalink
Add fromArchive method
Browse files Browse the repository at this point in the history
  • Loading branch information
gammazero committed May 3, 2024
1 parent 930a159 commit 5dd1ae7
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 21 deletions.
45 changes: 45 additions & 0 deletions packages/blob-index/src/sharded-dag-index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import * as Link from 'multiformats/link'
import { error, Schema, Failure } from '@ucanto/server'
import { sha256 } from 'multiformats/hashes/sha2'

const indexVersion = 'index/sharded/dag@0.1'

export const ShardedDAGIndexSchema = Schema.variant({
'index/sharded/dag@0.1': Schema.struct({
/** DAG root. */
Expand Down Expand Up @@ -148,11 +150,54 @@ export class ShardedDAGIndex {
}
}

/**
* @returns {Promise<ShardedDAGIndex>}
*/
export const fromArchive = async (carData) => {
const model = CAR.decode(carData)
const { cid, bytes } = model.roots[0]
const digest = await sha256.digest(bytes)
const newCID = Link.create(dagCBOR.code, digest)
if (newCID !== cid) {
throw new Error('bad index cid')
}
const { version, index } = dagCBOR.decode(bytes)
if (version !== indexVersion) {
throw new Error('invalid index version')
}
const { content, shardLinks } = index
const dagIndex = new ShardedDAGIndex(content)

const blocks = model.roots[1]
for (const b of blocks) {
const { cidStr, bytes } = b
const digest = await sha256.digest(bytes)
const cid = Link.create(dagCBOR.code, digest)
if (cid.toString() !== cidStr) {
throw new Error('bad block cid')
}
const slices = new DigestMap()
dagIndex.shards.set(digest, slices)
const { shardSliceBytes, slicesArray } = dagCBOR.decode(bytes)
for (const s of slicesArray) {
const entDigestBytes = s[0]
const entData = s[1]
const entDigest = await sha256.digest(entData)
if (entDigest.bytes !== entDigestBytes) {
throw new Error('bad entry digest')
}
slices.set(entDigest, entData)
}
}
return dagIndex
}

/**
* Create a sharded DAG index by indexing blocks in the the passed CAR shards.
*
* @param {API.UnknownLink} content
* @param {Uint8Array[]} shards
* @returns {Promise<ShardedDAGIndex>}
*/
export const fromShardArchives = async (content, shards) => {
const index = new ShardedDAGIndex(content)
Expand Down
28 changes: 7 additions & 21 deletions packages/blob-index/test/blob-index.spec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as assert from 'assert'
import * as blobIndex from '../src/sharded-dag-index.js'
import { CAR } from '@ucanto/core'
//import { CAR } from '@ucanto/core'
import { randomCAR } from './util.js'

describe('blob-index', async () => {
Expand All @@ -17,31 +17,17 @@ async function testBlobIndex(blobIndex, test) {
})

await test('from to archive', async () => {
// Create random CAR and import its contents into a ShardedBlobIndex.
const contentCAR = await randomCAR(32)
const contentCARBytes = new Uint8Array(await contentCAR.arrayBuffer())

const index = await blobIndex.fromShardArchives(contentCAR.roots[0], [
contentCARBytes,
])
try {
const indexCAR = unwrap(await index.toArchive())
assert.deepStrictEqual(indexCAR, contentCARBytes)
//const indexCARBytes = new Uint8Array(await indexCAR.arrayBuffer())
//assert.deepStrictEqual(indexCARBytes, contentCARBytes)
//const indexLink = await CAR.link(indexCAR)
} catch (error) {
if (error != undefined) {
assert.fail(String(error))
}
}

assert.notStrictEqual(index.shards.size, 0)
let i = 0
for (const shard of index.shards.values()) {
assert.notStrictEqual(shard.size, 0)
console.log('shard', i, 'has', shard.size, 'blocks')
i++
}
const indexCAR = unwrap(await index.toArchive())
const newIndex = await blobIndex.fromArchive(indexCAR)
assert.notStrictEqual(newIndex.shards.size, 0)
assert.strictEqual(index.shards.size, newIndex.shards.size)
// TODO: check that each shard.slice from newIndex is in index
})
}

Expand Down

0 comments on commit 5dd1ae7

Please sign in to comment.