@atproto/repo 0.8.13 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/block-map.d.ts +15 -16
  3. package/dist/block-map.d.ts.map +1 -1
  4. package/dist/block-map.js +9 -43
  5. package/dist/block-map.js.map +1 -1
  6. package/dist/car.d.ts +8 -8
  7. package/dist/car.d.ts.map +1 -1
  8. package/dist/car.js +18 -15
  9. package/dist/car.js.map +1 -1
  10. package/dist/cid-set.d.ts +8 -7
  11. package/dist/cid-set.d.ts.map +1 -1
  12. package/dist/cid-set.js +11 -4
  13. package/dist/cid-set.js.map +1 -1
  14. package/dist/data-diff.d.ts +10 -10
  15. package/dist/data-diff.d.ts.map +1 -1
  16. package/dist/data-diff.js.map +1 -1
  17. package/dist/error.d.ts +10 -10
  18. package/dist/error.d.ts.map +1 -1
  19. package/dist/error.js.map +1 -1
  20. package/dist/logger.d.ts.map +1 -1
  21. package/dist/logger.js +1 -0
  22. package/dist/logger.js.map +1 -1
  23. package/dist/mst/mst.d.ts +29 -29
  24. package/dist/mst/mst.d.ts.map +1 -1
  25. package/dist/mst/mst.js +12 -12
  26. package/dist/mst/mst.js.map +1 -1
  27. package/dist/mst/util.d.ts +2 -2
  28. package/dist/mst/util.d.ts.map +1 -1
  29. package/dist/mst/util.js +19 -39
  30. package/dist/mst/util.js.map +1 -1
  31. package/dist/parse.d.ts +6 -7
  32. package/dist/parse.d.ts.map +1 -1
  33. package/dist/parse.js +2 -2
  34. package/dist/parse.js.map +1 -1
  35. package/dist/readable-repo.d.ts +6 -7
  36. package/dist/readable-repo.d.ts.map +1 -1
  37. package/dist/readable-repo.js.map +1 -1
  38. package/dist/repo.d.ts +4 -4
  39. package/dist/repo.d.ts.map +1 -1
  40. package/dist/repo.js +11 -9
  41. package/dist/repo.js.map +1 -1
  42. package/dist/storage/memory-blockstore.d.ts +9 -9
  43. package/dist/storage/memory-blockstore.d.ts.map +1 -1
  44. package/dist/storage/memory-blockstore.js.map +1 -1
  45. package/dist/storage/readable-blockstore.d.ts +11 -12
  46. package/dist/storage/readable-blockstore.d.ts.map +1 -1
  47. package/dist/storage/readable-blockstore.js +2 -35
  48. package/dist/storage/readable-blockstore.js.map +1 -1
  49. package/dist/storage/sync-storage.d.ts +5 -5
  50. package/dist/storage/sync-storage.d.ts.map +1 -1
  51. package/dist/storage/sync-storage.js.map +1 -1
  52. package/dist/storage/types.d.ts +25 -26
  53. package/dist/storage/types.d.ts.map +1 -1
  54. package/dist/storage/types.js.map +1 -1
  55. package/dist/sync/consumer.d.ts +3 -3
  56. package/dist/sync/consumer.d.ts.map +1 -1
  57. package/dist/sync/consumer.js +1 -1
  58. package/dist/sync/consumer.js.map +1 -1
  59. package/dist/sync/provider.d.ts +3 -3
  60. package/dist/sync/provider.d.ts.map +1 -1
  61. package/dist/sync/provider.js.map +1 -1
  62. package/dist/types.d.ts +127 -100
  63. package/dist/types.d.ts.map +1 -1
  64. package/dist/types.js +53 -12
  65. package/dist/types.js.map +1 -1
  66. package/dist/util.d.ts +8 -3
  67. package/dist/util.d.ts.map +1 -1
  68. package/dist/util.js +33 -16
  69. package/dist/util.js.map +1 -1
  70. package/package.json +6 -7
  71. package/src/block-map.ts +31 -26
  72. package/src/car.ts +23 -28
  73. package/src/cid-set.ts +16 -10
  74. package/src/data-diff.ts +10 -10
  75. package/src/error.ts +6 -6
  76. package/src/logger.ts +1 -0
  77. package/src/mst/mst.ts +24 -26
  78. package/src/mst/util.ts +24 -9
  79. package/src/parse.ts +8 -8
  80. package/src/readable-repo.ts +6 -7
  81. package/src/repo.ts +13 -10
  82. package/src/storage/memory-blockstore.ts +8 -8
  83. package/src/storage/readable-blockstore.ts +12 -13
  84. package/src/storage/sync-storage.ts +4 -4
  85. package/src/storage/types.ts +25 -25
  86. package/src/sync/consumer.ts +5 -5
  87. package/src/sync/provider.ts +10 -7
  88. package/src/types.ts +82 -41
  89. package/src/util.ts +31 -14
  90. package/tests/_util.ts +28 -12
  91. package/tests/car.test.ts +31 -11
  92. package/tests/commit-proofs.test.ts +3 -3
  93. package/tests/covering-proofs.test.ts +6 -6
  94. package/tests/mst.test.ts +18 -19
  95. package/tests/proofs.test.ts +8 -6
  96. package/tests/repo.test.ts +1 -1
  97. package/tests/sync.test.ts +3 -6
  98. package/bench/mst.bench.ts +0 -165
  99. package/bench/repo.bench.ts +0 -48
package/tests/mst.test.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { CID } from 'multiformats'
1
+ import assert from 'node:assert'
2
+ import { Cid, parseCid } from '@atproto/lex-data'
2
3
  import { DataAdd, DataDelete, DataDiff, DataUpdate } from '../src/data-diff'
3
4
  import { MST } from '../src/mst'
4
5
  import { InvalidMstKeyError, countPrefixLen } from '../src/mst/util'
@@ -8,8 +9,8 @@ import * as util from './_util'
8
9
  describe('Merkle Search Tree', () => {
9
10
  let blockstore: MemoryBlockstore
10
11
  let mst: MST
11
- let mapping: Record<string, CID>
12
- let shuffled: [string, CID][]
12
+ let mapping: Record<string, Cid>
13
+ let shuffled: [string, Cid][]
13
14
 
14
15
  beforeAll(async () => {
15
16
  blockstore = new MemoryBlockstore()
@@ -24,7 +25,8 @@ describe('Merkle Search Tree', () => {
24
25
  }
25
26
  for (const entry of shuffled) {
26
27
  const got = await mst.get(entry[0])
27
- expect(entry[1].equals(got)).toBeTruthy()
28
+ assert(got !== null)
29
+ expect(entry[1].equals(got)).toBe(true)
28
30
  }
29
31
 
30
32
  const totalSize = await mst.leafCount()
@@ -35,7 +37,7 @@ describe('Merkle Search Tree', () => {
35
37
  let editedMst = mst
36
38
  const toEdit = shuffled.slice(0, 100)
37
39
 
38
- const edited: [string, CID][] = []
40
+ const edited: [string, Cid][] = []
39
41
  for (const entry of toEdit) {
40
42
  const newCid = await util.randomCid()
41
43
  editedMst = await editedMst.update(entry[0], newCid)
@@ -44,7 +46,8 @@ describe('Merkle Search Tree', () => {
44
46
 
45
47
  for (const entry of edited) {
46
48
  const got = await editedMst.get(entry[0])
47
- expect(entry[1].equals(got)).toBeTruthy()
49
+ assert(got !== null)
50
+ expect(entry[1].equals(got)).toBe(true)
48
51
  }
49
52
 
50
53
  const totalSize = await editedMst.leafCount()
@@ -68,7 +71,8 @@ describe('Merkle Search Tree', () => {
68
71
  }
69
72
  for (const entry of theRest) {
70
73
  const got = await deletedMst.get(entry[0])
71
- expect(entry[1].equals(got)).toBeTruthy()
74
+ assert(got !== null)
75
+ expect(entry[1].equals(got)).toBe(true)
72
76
  }
73
77
  })
74
78
 
@@ -142,12 +146,7 @@ describe('Merkle Search Tree', () => {
142
146
 
143
147
  // ensure we correctly report all added CIDs
144
148
  for await (const entry of toDiff.walk()) {
145
- let cid: CID
146
- if (entry.isTree()) {
147
- cid = await entry.getPointer()
148
- } else {
149
- cid = entry.value
150
- }
149
+ const cid = entry.isTree() ? await entry.getPointer() : entry.value
151
150
  const found =
152
151
  (await blockstore.has(cid)) ||
153
152
  diff.newMstBlocks.has(cid) ||
@@ -177,12 +176,12 @@ describe('Merkle Search Tree', () => {
177
176
  describe('MST Interop Allowable Keys', () => {
178
177
  let blockstore: MemoryBlockstore
179
178
  let mst: MST
180
- let cid1: CID
179
+ let cid1: Cid
181
180
 
182
181
  beforeAll(async () => {
183
182
  blockstore = new MemoryBlockstore()
184
183
  mst = await MST.create(blockstore)
185
- cid1 = CID.parse(
184
+ cid1 = parseCid(
186
185
  'bafyreie5cvv4h45feadgeuwhbcutmh6t2ceseocckahdoe6uat64zmz454',
187
186
  )
188
187
  })
@@ -257,11 +256,11 @@ describe('Merkle Search Tree', () => {
257
256
  describe('MST Interop Known Maps', () => {
258
257
  let blockstore: MemoryBlockstore
259
258
  let mst: MST
260
- let cid1: CID
259
+ let cid1: Cid
261
260
 
262
261
  beforeAll(async () => {
263
262
  blockstore = new MemoryBlockstore()
264
- cid1 = CID.parse(
263
+ cid1 = parseCid(
265
264
  'bafyreie5cvv4h45feadgeuwhbcutmh6t2ceseocckahdoe6uat64zmz454',
266
265
  )
267
266
  })
@@ -310,11 +309,11 @@ describe('Merkle Search Tree', () => {
310
309
  describe('MST Interop Edge Cases', () => {
311
310
  let blockstore: MemoryBlockstore
312
311
  let mst: MST
313
- let cid1: CID
312
+ let cid1: Cid
314
313
 
315
314
  beforeAll(async () => {
316
315
  blockstore = new MemoryBlockstore()
317
- cid1 = CID.parse(
316
+ cid1 = parseCid(
318
317
  'bafyreie5cvv4h45feadgeuwhbcutmh6t2ceseocckahdoe6uat64zmz454',
319
318
  )
320
319
  })
@@ -1,5 +1,7 @@
1
- import { TID, cidForCbor, streamToBuffer } from '@atproto/common'
1
+ import { TID } from '@atproto/common-web'
2
2
  import * as crypto from '@atproto/crypto'
3
+ import { cidForLex } from '@atproto/lex-cbor'
4
+ import { NsidString } from '@atproto/syntax'
3
5
  import { RecordCidClaim, RecordPath, Repo, RepoContents } from '../src'
4
6
  import { MemoryBlockstore } from '../src/storage'
5
7
  import * as sync from '../src/sync'
@@ -23,7 +25,7 @@ describe('Repo Proofs', () => {
23
25
  })
24
26
 
25
27
  const getProofs = async (claims: RecordPath[]) => {
26
- return streamToBuffer(sync.getRecords(storage, repo.cid, claims))
28
+ return util.toBuffer(sync.getRecords(storage, repo.cid, claims))
27
29
  }
28
30
 
29
31
  const doVerify = (proofs: Uint8Array, claims: RecordCidClaim[]) => {
@@ -34,12 +36,12 @@ describe('Repo Proofs', () => {
34
36
  contents: RepoContents,
35
37
  ): Promise<RecordCidClaim[]> => {
36
38
  const claims: RecordCidClaim[] = []
37
- for (const coll of Object.keys(contents)) {
39
+ for (const coll of Object.keys(contents) as NsidString[]) {
38
40
  for (const rkey of Object.keys(contents[coll])) {
39
41
  claims.push({
40
42
  collection: coll,
41
43
  rkey: rkey,
42
- cid: await cidForCbor(contents[coll][rkey]),
44
+ cid: await cidForLex(contents[coll][rkey]),
43
45
  })
44
46
  }
45
47
  }
@@ -136,7 +138,7 @@ describe('Repo Proofs', () => {
136
138
  throw new Error('Could not find record for claim')
137
139
  }
138
140
  expect(foundClaim.cid).toEqual(
139
- await cidForCbor(repoData[record.collection][record.rkey]),
141
+ await cidForLex(repoData[record.collection][record.rkey]),
140
142
  )
141
143
  }
142
144
  })
@@ -144,7 +146,7 @@ describe('Repo Proofs', () => {
144
146
  it('verifyProofs throws on a bad signature', async () => {
145
147
  const badRepo = await util.addBadCommit(repo, keypair)
146
148
  const claims = await contentsToClaims(repoData)
147
- const proofs = await streamToBuffer(
149
+ const proofs = await util.toBuffer(
148
150
  sync.getRecords(storage, badRepo.cid, claims),
149
151
  )
150
152
  const fn = sync.verifyProofs(proofs, claims, repoDid, keypair.did())
@@ -1,4 +1,4 @@
1
- import { TID } from '@atproto/common'
1
+ import { TID } from '@atproto/common-web'
2
2
  import * as crypto from '@atproto/crypto'
3
3
  import { Secp256k1Keypair } from '@atproto/crypto'
4
4
  import { RepoContents, WriteOpAction, verifyCommitSig } from '../src'
@@ -1,4 +1,3 @@
1
- import { streamToBuffer } from '@atproto/common'
2
1
  import * as crypto from '@atproto/crypto'
3
2
  import {
4
3
  CidSet,
@@ -31,7 +30,7 @@ describe('Repo Sync', () => {
31
30
  })
32
31
 
33
32
  it('sync a full repo', async () => {
34
- const carBytes = await streamToBuffer(sync.getFullRepo(storage, repo.cid))
33
+ const carBytes = await util.toBuffer(sync.getFullRepo(storage, repo.cid))
35
34
  const car = await readCarWithRoot(carBytes)
36
35
  const verified = await sync.verifyRepo(
37
36
  car.blocks,
@@ -54,7 +53,7 @@ describe('Repo Sync', () => {
54
53
  })
55
54
 
56
55
  it('does not sync duplicate blocks', async () => {
57
- const carBytes = await streamToBuffer(sync.getFullRepo(storage, repo.cid))
56
+ const carBytes = await util.toBuffer(sync.getFullRepo(storage, repo.cid))
58
57
  const car = await readCar(carBytes)
59
58
  const cids = new CidSet()
60
59
  car.blocks.forEach((_, cid) => {
@@ -87,9 +86,7 @@ describe('Repo Sync', () => {
87
86
 
88
87
  it('throws on a bad signature', async () => {
89
88
  const badRepo = await util.addBadCommit(repo, keypair)
90
- const carBytes = await streamToBuffer(
91
- sync.getFullRepo(storage, badRepo.cid),
92
- )
89
+ const carBytes = await util.toBuffer(sync.getFullRepo(storage, badRepo.cid))
93
90
  const car = await readCarWithRoot(carBytes)
94
91
  await expect(
95
92
  sync.verifyRepo(car.blocks, car.root, repoDid, keypair.did()),
@@ -1,165 +0,0 @@
1
- import fs from 'node:fs'
2
- import { CID } from 'multiformats'
3
- import { Fanout, MST, MemoryBlockstore, NodeEntry } from '../src'
4
- import * as util from '../tests/_util'
5
-
6
- type BenchmarkData = {
7
- fanout: number
8
- size: number
9
- addTime: string
10
- saveTime: string
11
- walkTime: string
12
- depth: number
13
- maxWidth: number
14
- blockstoreSize: number
15
- largestProofSize: number
16
- avgProofSize: number
17
- widths: Record<number, number>
18
- }
19
-
20
- describe('MST Benchmarks', () => {
21
- let mapping: Record<string, CID>
22
- let shuffled: [string, CID][]
23
-
24
- const size = 500000
25
-
26
- beforeAll(async () => {
27
- mapping = await util.generateBulkDataKeys(size)
28
- shuffled = util.shuffle(Object.entries(mapping))
29
- })
30
-
31
- // const fanouts: Fanout[] = [8, 16, 32]
32
- const fanouts: Fanout[] = [16, 32]
33
- it('benchmarks various fanouts', async () => {
34
- const benches: BenchmarkData[] = []
35
- for (const fanout of fanouts) {
36
- const blockstore = new MemoryBlockstore()
37
- let mst = await MST.create(blockstore, [], { fanout })
38
-
39
- const start = Date.now()
40
-
41
- for (const entry of shuffled) {
42
- mst = await mst.add(entry[0], entry[1])
43
- }
44
-
45
- const doneAdding = Date.now()
46
-
47
- const root = await util.saveMst(blockstore, mst)
48
-
49
- const doneSaving = Date.now()
50
-
51
- const reloaded = await MST.load(blockstore, root, { fanout })
52
- const widthTracker = new NodeWidths()
53
- for await (const entry of reloaded.walk()) {
54
- await widthTracker.trackEntry(entry)
55
- }
56
-
57
- const doneWalking = Date.now()
58
-
59
- const paths = await reloaded.paths()
60
- let largestProof = 0
61
- let combinedProofSizes = 0
62
- for (const path of paths) {
63
- let proofSize = 0
64
- for (const entry of path) {
65
- if (entry.isTree()) {
66
- const bytes = await blockstore.getBytes(entry.pointer)
67
- if (!bytes) {
68
- throw new Error(`Bytes not found: ${entry.pointer}`)
69
- }
70
- proofSize += bytes.byteLength
71
- }
72
- }
73
- largestProof = Math.max(largestProof, proofSize)
74
- combinedProofSizes += proofSize
75
- }
76
- const avgProofSize = Math.ceil(combinedProofSizes / paths.length)
77
-
78
- const blockstoreSize = await blockstore.sizeInBytes()
79
-
80
- benches.push({
81
- fanout,
82
- size,
83
- addTime: secDiff(start, doneAdding),
84
- saveTime: secDiff(doneAdding, doneSaving),
85
- walkTime: secDiff(doneSaving, doneWalking),
86
- depth: await mst.getLayer(),
87
- blockstoreSize,
88
- largestProofSize: largestProof,
89
- avgProofSize: avgProofSize,
90
- maxWidth: widthTracker.max,
91
- widths: widthTracker.data,
92
- })
93
- }
94
- writeBenchData(benches, 'mst-benchmarks')
95
- })
96
- })
97
-
98
- const secDiff = (first: number, second: number): string => {
99
- return ((second - first) / 1000).toFixed(3)
100
- }
101
-
102
- class NodeWidths {
103
- data = {
104
- 0: 0,
105
- 16: 0,
106
- 32: 0,
107
- 48: 0,
108
- 64: 0,
109
- 96: 0,
110
- 128: 0,
111
- 160: 0,
112
- 192: 0,
113
- 224: 0,
114
- 256: 0,
115
- }
116
- max = 0
117
-
118
- async trackEntry(entry: NodeEntry) {
119
- if (!entry.isTree()) return
120
- const entries = await entry.getEntries()
121
- const width = entries.filter((e) => e.isLeaf()).length
122
- this.max = Math.max(this.max, width)
123
- if (width >= 0) this.data[0]++
124
- if (width >= 16) this.data[16]++
125
- if (width >= 32) this.data[32]++
126
- if (width >= 48) this.data[48]++
127
- if (width >= 64) this.data[64]++
128
- if (width >= 96) this.data[96]++
129
- if (width >= 128) this.data[128]++
130
- if (width >= 160) this.data[160]++
131
- if (width >= 192) this.data[192]++
132
- if (width >= 224) this.data[224]++
133
- if (width >= 256) this.data[256]++
134
- }
135
- }
136
-
137
- const writeBenchData = (benches: BenchmarkData[], fileLoc: string) => {
138
- let toWrite = ''
139
- for (const bench of benches) {
140
- toWrite += `Fanout: ${bench.fanout}
141
- ----------------------
142
- Time to add ${bench.size} leaves: ${bench.addTime}s
143
- Time to save tree with ${bench.size} leaves: ${bench.saveTime}s
144
- Time to reconstruct & walk ${bench.size} leaves: ${bench.walkTime}s
145
- Tree depth: ${bench.depth}
146
- Max Node Width (only counting leaves): ${bench.maxWidth}
147
- The total blockstore size is: ${bench.blockstoreSize} bytes
148
- Largest proof size: ${bench.largestProofSize} bytes
149
- Average proof size: ${bench.avgProofSize} bytes
150
- Nodes with >= 0 leaves: ${bench.widths[0]}
151
- Nodes with >= 16 leaves: ${bench.widths[16]}
152
- Nodes with >= 32 leaves: ${bench.widths[32]}
153
- Nodes with >= 48 leaves: ${bench.widths[48]}
154
- Nodes with >= 64 leaves: ${bench.widths[64]}
155
- Nodes with >= 96 leaves: ${bench.widths[96]}
156
- Nodes with >= 128 leaves: ${bench.widths[128]}
157
- Nodes with >= 160 leaves: ${bench.widths[160]}
158
- Nodes with >= 192 leaves: ${bench.widths[192]}
159
- Nodes with >= 224 leaves: ${bench.widths[224]}
160
- Nodes with >= 256 leaves: ${bench.widths[256]}
161
-
162
- `
163
- }
164
- fs.writeFileSync(fileLoc, toWrite)
165
- }
@@ -1,48 +0,0 @@
1
- import { TID } from '@atproto/common'
2
- import * as crypto from '@atproto/crypto'
3
- import { Secp256k1Keypair } from '@atproto/crypto'
4
- import { MemoryBlockstore, Repo, WriteOpAction } from '../src'
5
- import * as util from '../tests/_util'
6
-
7
- describe('Repo Benchmarks', () => {
8
- const size = 10000
9
-
10
- let blockstore: MemoryBlockstore
11
- let keypair: crypto.Keypair
12
- let repo: Repo
13
-
14
- beforeAll(async () => {
15
- blockstore = new MemoryBlockstore()
16
- keypair = await Secp256k1Keypair.create()
17
- repo = await Repo.create(blockstore, await keypair.did(), keypair)
18
- })
19
-
20
- it('calculates size', async () => {
21
- for (let i = 0; i < size; i++) {
22
- if (i % 500 === 0) {
23
- console.log(i)
24
- }
25
-
26
- await repo.applyCommit(
27
- {
28
- action: WriteOpAction.Create,
29
- collection: 'app.bsky.post',
30
- rkey: TID.nextStr(),
31
- value: {
32
- $type: 'app.bsky.post',
33
- text: util.randomStr(150),
34
- reply: {
35
- root: 'at://did:plc:1234abdefeoi23/app.bsky.post/12345678912345',
36
- parent:
37
- 'at://did:plc:1234abdefeoi23/app.bsky.post/12345678912345',
38
- },
39
- createdAt: new Date().toISOString(),
40
- },
41
- },
42
- keypair,
43
- )
44
- }
45
-
46
- console.log('SIZE: ', await blockstore.sizeInBytes())
47
- })
48
- })