@atproto/repo 0.2.0 → 0.3.0
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.
- package/dist/data-diff.d.ts +11 -9
- package/dist/index.d.ts +0 -1
- package/dist/index.js +404 -1655
- package/dist/index.js.map +4 -4
- package/dist/mst/mst.d.ts +10 -6
- package/dist/readable-repo.d.ts +1 -1
- package/dist/repo.d.ts +1 -4
- package/dist/storage/index.d.ts +0 -1
- package/dist/storage/memory-blockstore.d.ts +7 -12
- package/dist/storage/types.d.ts +28 -0
- package/dist/sync/consumer.d.ts +13 -17
- package/dist/sync/provider.d.ts +1 -5
- package/dist/types.d.ts +228 -39
- package/dist/util.d.ts +3 -5
- package/package.json +2 -2
- package/src/data-diff.ts +46 -44
- package/src/index.ts +0 -1
- package/src/mst/diff.ts +14 -36
- package/src/mst/mst.ts +14 -4
- package/src/readable-repo.ts +3 -3
- package/src/repo.ts +49 -70
- package/src/storage/index.ts +0 -1
- package/src/storage/memory-blockstore.ts +18 -77
- package/src/storage/types.ts +29 -0
- package/src/sync/consumer.ts +170 -116
- package/src/sync/provider.ts +2 -40
- package/src/types.ts +49 -23
- package/src/util.ts +24 -79
- package/tests/_util.ts +38 -67
- package/tests/mst.test.ts +4 -1
- package/tests/{sync/narrow.test.ts → proofs.test.ts} +9 -20
- package/tests/repo.test.ts +5 -4
- package/tests/sync.test.ts +97 -0
- package/tsconfig.build.tsbuildinfo +1 -1
- package/dist/src/block-map.d.ts +0 -23
- package/dist/src/blockstore/index.d.ts +0 -2
- package/dist/src/blockstore/ipld-store.d.ts +0 -27
- package/dist/src/blockstore/memory-blockstore.d.ts +0 -13
- package/dist/src/blockstore/persistent-blockstore.d.ts +0 -12
- package/dist/src/cid-set.d.ts +0 -14
- package/dist/src/collection.d.ts +0 -22
- package/dist/src/data-diff.d.ts +0 -34
- package/dist/src/error.d.ts +0 -21
- package/dist/src/index.d.ts +0 -7
- package/dist/src/logger.d.ts +0 -2
- package/dist/src/mst/diff.d.ts +0 -33
- package/dist/src/mst/index.d.ts +0 -4
- package/dist/src/mst/mst.d.ts +0 -106
- package/dist/src/mst/util.d.ts +0 -9
- package/dist/src/mst/walker.d.ts +0 -22
- package/dist/src/parse.d.ts +0 -11
- package/dist/src/readable-repo.d.ts +0 -25
- package/dist/src/repo.d.ts +0 -39
- package/dist/src/storage/error.d.ts +0 -22
- package/dist/src/storage/index.d.ts +0 -1
- package/dist/src/storage/memory-blobstore.d.ts +0 -1
- package/dist/src/storage/memory-blockstore.d.ts +0 -28
- package/dist/src/storage/readable-blockstore.d.ts +0 -21
- package/dist/src/storage/repo-storage.d.ts +0 -18
- package/dist/src/storage/sync-storage.d.ts +0 -15
- package/dist/src/storage/types.d.ts +0 -12
- package/dist/src/storage/util.d.ts +0 -17
- package/dist/src/structure.d.ts +0 -39
- package/dist/src/sync/consumer.d.ts +0 -19
- package/dist/src/sync/index.d.ts +0 -2
- package/dist/src/sync/producer.d.ts +0 -13
- package/dist/src/sync/provider.d.ts +0 -11
- package/dist/src/sync.d.ts +0 -9
- package/dist/src/types.d.ts +0 -368
- package/dist/src/util.d.ts +0 -13
- package/dist/src/verify.d.ts +0 -5
- package/dist/storage/repo-storage.d.ts +0 -19
- package/dist/tsconfig.build.tsbuildinfo +0 -1
- package/dist/verify.d.ts +0 -32
- package/src/storage/repo-storage.ts +0 -43
- package/src/verify.ts +0 -268
- package/tests/rebase.test.ts +0 -37
- package/tests/sync/checkout.test.ts +0 -75
- package/tests/sync/diff.test.ts +0 -92
package/src/verify.ts
DELETED
|
@@ -1,268 +0,0 @@
|
|
|
1
|
-
import { CID } from 'multiformats/cid'
|
|
2
|
-
import { MemoryBlockstore, ReadableBlockstore, RepoStorage } from './storage'
|
|
3
|
-
import DataDiff from './data-diff'
|
|
4
|
-
import SyncStorage from './storage/sync-storage'
|
|
5
|
-
import ReadableRepo from './readable-repo'
|
|
6
|
-
import Repo from './repo'
|
|
7
|
-
import CidSet from './cid-set'
|
|
8
|
-
import * as util from './util'
|
|
9
|
-
import { RecordClaim, RepoContents, RepoContentsWithCids } from './types'
|
|
10
|
-
import { def } from './types'
|
|
11
|
-
import { MST } from './mst'
|
|
12
|
-
import { cidForCbor } from '@atproto/common'
|
|
13
|
-
|
|
14
|
-
export type VerifiedCheckout = {
|
|
15
|
-
contents: RepoContents
|
|
16
|
-
newCids: CidSet
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export type VerifiedCheckoutWithCids = {
|
|
20
|
-
commit: CID
|
|
21
|
-
contents: RepoContentsWithCids
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export const verifyCheckout = async (
|
|
25
|
-
storage: ReadableBlockstore,
|
|
26
|
-
head: CID,
|
|
27
|
-
did: string,
|
|
28
|
-
signingKey: string,
|
|
29
|
-
): Promise<VerifiedCheckout> => {
|
|
30
|
-
const repo = await verifyRepoRoot(storage, head, did, signingKey)
|
|
31
|
-
const diff = await DataDiff.of(repo.data, null)
|
|
32
|
-
const newCids = new CidSet([repo.cid]).addSet(diff.newCids)
|
|
33
|
-
|
|
34
|
-
const contents: RepoContents = {}
|
|
35
|
-
for (const add of diff.addList()) {
|
|
36
|
-
const { collection, rkey } = util.parseDataKey(add.key)
|
|
37
|
-
if (!contents[collection]) {
|
|
38
|
-
contents[collection] = {}
|
|
39
|
-
}
|
|
40
|
-
const record = await storage.readRecord(add.cid)
|
|
41
|
-
contents[collection][rkey] = record
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return {
|
|
45
|
-
contents,
|
|
46
|
-
newCids,
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export const verifyCheckoutWithCids = async (
|
|
51
|
-
storage: ReadableBlockstore,
|
|
52
|
-
head: CID,
|
|
53
|
-
did: string,
|
|
54
|
-
signingKey: string,
|
|
55
|
-
): Promise<VerifiedCheckoutWithCids> => {
|
|
56
|
-
const repo = await verifyRepoRoot(storage, head, did, signingKey)
|
|
57
|
-
const diff = await DataDiff.of(repo.data, null)
|
|
58
|
-
|
|
59
|
-
const contents: RepoContentsWithCids = {}
|
|
60
|
-
for (const add of diff.addList()) {
|
|
61
|
-
const { collection, rkey } = util.parseDataKey(add.key)
|
|
62
|
-
contents[collection] ??= {}
|
|
63
|
-
contents[collection][rkey] = {
|
|
64
|
-
cid: add.cid,
|
|
65
|
-
value: await storage.readRecord(add.cid),
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return {
|
|
70
|
-
commit: repo.cid,
|
|
71
|
-
contents,
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// @NOTE only verifies the root, not the repo contents
|
|
76
|
-
const verifyRepoRoot = async (
|
|
77
|
-
storage: ReadableBlockstore,
|
|
78
|
-
head: CID,
|
|
79
|
-
did: string,
|
|
80
|
-
signingKey: string,
|
|
81
|
-
): Promise<ReadableRepo> => {
|
|
82
|
-
const repo = await ReadableRepo.load(storage, head)
|
|
83
|
-
if (repo.did !== did) {
|
|
84
|
-
throw new RepoVerificationError(`Invalid repo did: ${repo.did}`)
|
|
85
|
-
}
|
|
86
|
-
const validSig = await util.verifyCommitSig(repo.commit, signingKey)
|
|
87
|
-
if (!validSig) {
|
|
88
|
-
throw new RepoVerificationError(
|
|
89
|
-
`Invalid signature on commit: ${repo.cid.toString()}`,
|
|
90
|
-
)
|
|
91
|
-
}
|
|
92
|
-
return repo
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export type VerifiedUpdate = {
|
|
96
|
-
commit: CID
|
|
97
|
-
prev: CID | null
|
|
98
|
-
diff: DataDiff
|
|
99
|
-
newCids: CidSet
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
export const verifyFullHistory = async (
|
|
103
|
-
storage: RepoStorage,
|
|
104
|
-
head: CID,
|
|
105
|
-
did: string,
|
|
106
|
-
signingKey: string,
|
|
107
|
-
): Promise<VerifiedUpdate[]> => {
|
|
108
|
-
const commitPath = await storage.getCommitPath(head, null)
|
|
109
|
-
if (commitPath === null) {
|
|
110
|
-
throw new RepoVerificationError('Could not find shared history')
|
|
111
|
-
} else if (commitPath.length < 1) {
|
|
112
|
-
throw new RepoVerificationError('Expected at least one commit')
|
|
113
|
-
}
|
|
114
|
-
const baseRepo = await Repo.load(storage, commitPath[0])
|
|
115
|
-
const baseDiff = await DataDiff.of(baseRepo.data, null)
|
|
116
|
-
const baseRepoCids = new CidSet([baseRepo.cid]).addSet(baseDiff.newCids)
|
|
117
|
-
const init: VerifiedUpdate = {
|
|
118
|
-
commit: baseRepo.cid,
|
|
119
|
-
prev: null,
|
|
120
|
-
diff: baseDiff,
|
|
121
|
-
newCids: baseRepoCids,
|
|
122
|
-
}
|
|
123
|
-
const updates = await verifyCommitPath(
|
|
124
|
-
baseRepo,
|
|
125
|
-
storage,
|
|
126
|
-
commitPath.slice(1),
|
|
127
|
-
did,
|
|
128
|
-
signingKey,
|
|
129
|
-
)
|
|
130
|
-
return [init, ...updates]
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
export const verifyUpdates = async (
|
|
134
|
-
repo: ReadableRepo,
|
|
135
|
-
updateStorage: RepoStorage,
|
|
136
|
-
updateRoot: CID,
|
|
137
|
-
did: string,
|
|
138
|
-
signingKey: string,
|
|
139
|
-
): Promise<VerifiedUpdate[]> => {
|
|
140
|
-
const commitPath = await updateStorage.getCommitPath(updateRoot, repo.cid)
|
|
141
|
-
if (commitPath === null) {
|
|
142
|
-
throw new RepoVerificationError('Could not find shared history')
|
|
143
|
-
}
|
|
144
|
-
const syncStorage = new SyncStorage(updateStorage, repo.storage)
|
|
145
|
-
return verifyCommitPath(repo, syncStorage, commitPath, did, signingKey)
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
export const verifyCommitPath = async (
|
|
149
|
-
baseRepo: ReadableRepo,
|
|
150
|
-
storage: ReadableBlockstore,
|
|
151
|
-
commitPath: CID[],
|
|
152
|
-
did: string,
|
|
153
|
-
signingKey: string,
|
|
154
|
-
): Promise<VerifiedUpdate[]> => {
|
|
155
|
-
const updates: VerifiedUpdate[] = []
|
|
156
|
-
if (commitPath.length === 0) return updates
|
|
157
|
-
let prevRepo = baseRepo
|
|
158
|
-
for (const commit of commitPath) {
|
|
159
|
-
const nextRepo = await ReadableRepo.load(storage, commit)
|
|
160
|
-
const diff = await DataDiff.of(nextRepo.data, prevRepo.data)
|
|
161
|
-
|
|
162
|
-
if (nextRepo.did !== did) {
|
|
163
|
-
throw new RepoVerificationError(`Invalid repo did: ${nextRepo.did}`)
|
|
164
|
-
}
|
|
165
|
-
if (!util.metaEqual(nextRepo.commit, prevRepo.commit)) {
|
|
166
|
-
throw new RepoVerificationError('Not supported: repo metadata updated')
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const validSig = await util.verifyCommitSig(nextRepo.commit, signingKey)
|
|
170
|
-
if (!validSig) {
|
|
171
|
-
throw new RepoVerificationError(
|
|
172
|
-
`Invalid signature on commit: ${nextRepo.cid.toString()}`,
|
|
173
|
-
)
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
const newCids = new CidSet([nextRepo.cid]).addSet(diff.newCids)
|
|
177
|
-
|
|
178
|
-
updates.push({
|
|
179
|
-
commit: nextRepo.cid,
|
|
180
|
-
prev: prevRepo.cid,
|
|
181
|
-
diff,
|
|
182
|
-
newCids,
|
|
183
|
-
})
|
|
184
|
-
prevRepo = nextRepo
|
|
185
|
-
}
|
|
186
|
-
return updates
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
export const verifyProofs = async (
|
|
190
|
-
proofs: Uint8Array,
|
|
191
|
-
claims: RecordClaim[],
|
|
192
|
-
did: string,
|
|
193
|
-
didKey: string,
|
|
194
|
-
): Promise<{ verified: RecordClaim[]; unverified: RecordClaim[] }> => {
|
|
195
|
-
const car = await util.readCarWithRoot(proofs)
|
|
196
|
-
const blockstore = new MemoryBlockstore(car.blocks)
|
|
197
|
-
const commit = await blockstore.readObj(car.root, def.commit)
|
|
198
|
-
if (commit.did !== did) {
|
|
199
|
-
throw new RepoVerificationError(`Invalid repo did: ${commit.did}`)
|
|
200
|
-
}
|
|
201
|
-
const validSig = await util.verifyCommitSig(commit, didKey)
|
|
202
|
-
if (!validSig) {
|
|
203
|
-
throw new RepoVerificationError(
|
|
204
|
-
`Invalid signature on commit: ${car.root.toString()}`,
|
|
205
|
-
)
|
|
206
|
-
}
|
|
207
|
-
const mst = MST.load(blockstore, commit.data)
|
|
208
|
-
const verified: RecordClaim[] = []
|
|
209
|
-
const unverified: RecordClaim[] = []
|
|
210
|
-
for (const claim of claims) {
|
|
211
|
-
const found = await mst.get(
|
|
212
|
-
util.formatDataKey(claim.collection, claim.rkey),
|
|
213
|
-
)
|
|
214
|
-
const record = found ? await blockstore.readObj(found, def.map) : null
|
|
215
|
-
if (claim.record === null) {
|
|
216
|
-
if (record === null) {
|
|
217
|
-
verified.push(claim)
|
|
218
|
-
} else {
|
|
219
|
-
unverified.push(claim)
|
|
220
|
-
}
|
|
221
|
-
} else {
|
|
222
|
-
const expected = await cidForCbor(claim.record)
|
|
223
|
-
if (expected.equals(found)) {
|
|
224
|
-
verified.push(claim)
|
|
225
|
-
} else {
|
|
226
|
-
unverified.push(claim)
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
return { verified, unverified }
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
export const verifyRecords = async (
|
|
234
|
-
proofs: Uint8Array,
|
|
235
|
-
did: string,
|
|
236
|
-
signingKey: string,
|
|
237
|
-
): Promise<RecordClaim[]> => {
|
|
238
|
-
const car = await util.readCarWithRoot(proofs)
|
|
239
|
-
const blockstore = new MemoryBlockstore(car.blocks)
|
|
240
|
-
const commit = await blockstore.readObj(car.root, def.commit)
|
|
241
|
-
if (commit.did !== did) {
|
|
242
|
-
throw new RepoVerificationError(`Invalid repo did: ${commit.did}`)
|
|
243
|
-
}
|
|
244
|
-
const validSig = await util.verifyCommitSig(commit, signingKey)
|
|
245
|
-
if (!validSig) {
|
|
246
|
-
throw new RepoVerificationError(
|
|
247
|
-
`Invalid signature on commit: ${car.root.toString()}`,
|
|
248
|
-
)
|
|
249
|
-
}
|
|
250
|
-
const mst = MST.load(blockstore, commit.data)
|
|
251
|
-
|
|
252
|
-
const records: RecordClaim[] = []
|
|
253
|
-
const leaves = await mst.reachableLeaves()
|
|
254
|
-
for (const leaf of leaves) {
|
|
255
|
-
const { collection, rkey } = util.parseDataKey(leaf.key)
|
|
256
|
-
const record = await blockstore.attemptReadRecord(leaf.value)
|
|
257
|
-
if (record) {
|
|
258
|
-
records.push({
|
|
259
|
-
collection,
|
|
260
|
-
rkey,
|
|
261
|
-
record,
|
|
262
|
-
})
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
return records
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
export class RepoVerificationError extends Error {}
|
package/tests/rebase.test.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import * as crypto from '@atproto/crypto'
|
|
2
|
-
import { Repo } from '../src/repo'
|
|
3
|
-
import { MemoryBlockstore } from '../src/storage'
|
|
4
|
-
import * as util from './_util'
|
|
5
|
-
import { Secp256k1Keypair } from '@atproto/crypto'
|
|
6
|
-
|
|
7
|
-
describe('Rebases', () => {
|
|
8
|
-
let storage: MemoryBlockstore
|
|
9
|
-
let keypair: crypto.Keypair
|
|
10
|
-
let repo: Repo
|
|
11
|
-
|
|
12
|
-
it('fills a repo with data', async () => {
|
|
13
|
-
storage = new MemoryBlockstore()
|
|
14
|
-
keypair = await Secp256k1Keypair.create()
|
|
15
|
-
repo = await Repo.create(storage, keypair.did(), keypair)
|
|
16
|
-
const filled = await util.fillRepo(repo, keypair, 100)
|
|
17
|
-
repo = filled.repo
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
it('rebases the repo & preserves contents', async () => {
|
|
21
|
-
const dataCidBefore = await repo.data.getPointer()
|
|
22
|
-
const contents = await repo.getContents()
|
|
23
|
-
repo = await repo.rebase(keypair)
|
|
24
|
-
const rebasedContents = await repo.getContents()
|
|
25
|
-
expect(rebasedContents).toEqual(contents)
|
|
26
|
-
const dataCidAfter = await repo.data.getPointer()
|
|
27
|
-
expect(dataCidAfter.equals(dataCidBefore)).toBeTruthy()
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
it('only keeps around relevant cids', async () => {
|
|
31
|
-
const allCids = await repo.data.allCids()
|
|
32
|
-
allCids.add(repo.cid)
|
|
33
|
-
for (const cid of storage.blocks.cids()) {
|
|
34
|
-
expect(allCids.has(cid)).toBeTruthy()
|
|
35
|
-
}
|
|
36
|
-
})
|
|
37
|
-
})
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import * as crypto from '@atproto/crypto'
|
|
2
|
-
import { CidSet, Repo, RepoContents, RepoVerificationError } from '../../src'
|
|
3
|
-
import { MemoryBlockstore } from '../../src/storage'
|
|
4
|
-
import * as sync from '../../src/sync'
|
|
5
|
-
|
|
6
|
-
import * as util from '../_util'
|
|
7
|
-
import { streamToBuffer } from '@atproto/common'
|
|
8
|
-
import { CarReader } from '@ipld/car/reader'
|
|
9
|
-
|
|
10
|
-
describe('Checkout Sync', () => {
|
|
11
|
-
let storage: MemoryBlockstore
|
|
12
|
-
let syncStorage: MemoryBlockstore
|
|
13
|
-
let repo: Repo
|
|
14
|
-
let keypair: crypto.Keypair
|
|
15
|
-
let repoData: RepoContents
|
|
16
|
-
|
|
17
|
-
const repoDid = 'did:example:test'
|
|
18
|
-
|
|
19
|
-
beforeAll(async () => {
|
|
20
|
-
storage = new MemoryBlockstore()
|
|
21
|
-
keypair = await crypto.Secp256k1Keypair.create()
|
|
22
|
-
repo = await Repo.create(storage, repoDid, keypair)
|
|
23
|
-
syncStorage = new MemoryBlockstore()
|
|
24
|
-
const filled = await util.fillRepo(repo, keypair, 20)
|
|
25
|
-
repo = filled.repo
|
|
26
|
-
repoData = filled.data
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
it('sync a non-historical repo checkout', async () => {
|
|
30
|
-
const checkoutCar = await streamToBuffer(
|
|
31
|
-
sync.getCheckout(storage, repo.cid),
|
|
32
|
-
)
|
|
33
|
-
const checkout = await sync.loadCheckout(
|
|
34
|
-
syncStorage,
|
|
35
|
-
checkoutCar,
|
|
36
|
-
repoDid,
|
|
37
|
-
keypair.did(),
|
|
38
|
-
)
|
|
39
|
-
const checkoutRepo = await Repo.load(syncStorage, checkout.root)
|
|
40
|
-
const contents = await checkoutRepo.getContents()
|
|
41
|
-
expect(contents).toEqual(repoData)
|
|
42
|
-
expect(checkout.contents).toEqual(repoData)
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
it('does not sync unneeded blocks during checkout', async () => {
|
|
46
|
-
const commitPath = await storage.getCommitPath(repo.cid, null)
|
|
47
|
-
if (!commitPath) {
|
|
48
|
-
throw new Error('Could not get commitPath')
|
|
49
|
-
}
|
|
50
|
-
const hasGenesisCommit = await syncStorage.has(commitPath[0])
|
|
51
|
-
expect(hasGenesisCommit).toBeFalsy()
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
it('does not sync duplicate blocks', async () => {
|
|
55
|
-
const carBytes = await streamToBuffer(sync.getCheckout(storage, repo.cid))
|
|
56
|
-
const car = await CarReader.fromBytes(carBytes)
|
|
57
|
-
const cids = new CidSet()
|
|
58
|
-
for await (const block of car.blocks()) {
|
|
59
|
-
if (cids.has(block.cid)) {
|
|
60
|
-
throw new Error(`duplicate block: :${block.cid.toString()}`)
|
|
61
|
-
}
|
|
62
|
-
cids.add(block.cid)
|
|
63
|
-
}
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
it('throws on a bad signature', async () => {
|
|
67
|
-
const badRepo = await util.addBadCommit(repo, keypair)
|
|
68
|
-
const checkoutCar = await streamToBuffer(
|
|
69
|
-
sync.getCheckout(storage, badRepo.cid),
|
|
70
|
-
)
|
|
71
|
-
await expect(
|
|
72
|
-
sync.loadCheckout(syncStorage, checkoutCar, repoDid, keypair.did()),
|
|
73
|
-
).rejects.toThrow(RepoVerificationError)
|
|
74
|
-
})
|
|
75
|
-
})
|
package/tests/sync/diff.test.ts
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import * as crypto from '@atproto/crypto'
|
|
2
|
-
import { Repo, RepoContents } from '../../src'
|
|
3
|
-
import { MemoryBlockstore } from '../../src/storage'
|
|
4
|
-
import * as sync from '../../src/sync'
|
|
5
|
-
|
|
6
|
-
import * as util from '../_util'
|
|
7
|
-
import { streamToBuffer } from '@atproto/common'
|
|
8
|
-
|
|
9
|
-
describe('Diff Sync', () => {
|
|
10
|
-
let storage: MemoryBlockstore
|
|
11
|
-
let syncStorage: MemoryBlockstore
|
|
12
|
-
let repo: Repo
|
|
13
|
-
let keypair: crypto.Keypair
|
|
14
|
-
let repoData: RepoContents
|
|
15
|
-
|
|
16
|
-
const repoDid = 'did:example:test'
|
|
17
|
-
|
|
18
|
-
beforeAll(async () => {
|
|
19
|
-
storage = new MemoryBlockstore()
|
|
20
|
-
keypair = await crypto.Secp256k1Keypair.create()
|
|
21
|
-
repo = await Repo.create(storage, repoDid, keypair)
|
|
22
|
-
syncStorage = new MemoryBlockstore()
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
let syncRepo: Repo
|
|
26
|
-
|
|
27
|
-
it('syncs an empty repo', async () => {
|
|
28
|
-
const car = await streamToBuffer(sync.getFullRepo(storage, repo.cid))
|
|
29
|
-
const loaded = await sync.loadFullRepo(
|
|
30
|
-
syncStorage,
|
|
31
|
-
car,
|
|
32
|
-
repoDid,
|
|
33
|
-
keypair.did(),
|
|
34
|
-
)
|
|
35
|
-
syncRepo = await Repo.load(syncStorage, loaded.root)
|
|
36
|
-
const data = await syncRepo.data.list(10)
|
|
37
|
-
expect(data.length).toBe(0)
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
it('syncs a repo that is starting from scratch', async () => {
|
|
41
|
-
const filled = await util.fillRepo(repo, keypair, 100)
|
|
42
|
-
repo = filled.repo
|
|
43
|
-
repoData = filled.data
|
|
44
|
-
|
|
45
|
-
const car = await streamToBuffer(sync.getFullRepo(storage, repo.cid))
|
|
46
|
-
const loaded = await sync.loadFullRepo(
|
|
47
|
-
syncStorage,
|
|
48
|
-
car,
|
|
49
|
-
repoDid,
|
|
50
|
-
keypair.did(),
|
|
51
|
-
)
|
|
52
|
-
syncRepo = await Repo.load(syncStorage, loaded.root)
|
|
53
|
-
const contents = await syncRepo.getContents()
|
|
54
|
-
expect(contents).toEqual(repoData)
|
|
55
|
-
await util.verifyRepoDiff(loaded.writeLog, {}, repoData)
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
it('syncs a repo that is behind', async () => {
|
|
59
|
-
// add more to providers's repo & have consumer catch up
|
|
60
|
-
const beforeData = structuredClone(repoData)
|
|
61
|
-
const edited = await util.editRepo(repo, repoData, keypair, {
|
|
62
|
-
adds: 20,
|
|
63
|
-
updates: 20,
|
|
64
|
-
deletes: 20,
|
|
65
|
-
})
|
|
66
|
-
repo = edited.repo
|
|
67
|
-
repoData = edited.data
|
|
68
|
-
const diffCar = await streamToBuffer(
|
|
69
|
-
sync.getCommits(storage, repo.cid, syncRepo.cid),
|
|
70
|
-
)
|
|
71
|
-
const loaded = await sync.loadDiff(
|
|
72
|
-
syncRepo,
|
|
73
|
-
diffCar,
|
|
74
|
-
repoDid,
|
|
75
|
-
keypair.did(),
|
|
76
|
-
)
|
|
77
|
-
syncRepo = await Repo.load(syncStorage, loaded.root)
|
|
78
|
-
const contents = await syncRepo.getContents()
|
|
79
|
-
expect(contents).toEqual(repoData)
|
|
80
|
-
await util.verifyRepoDiff(loaded.writeLog, beforeData, repoData)
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
it('throws on a bad signature', async () => {
|
|
84
|
-
const badRepo = await util.addBadCommit(repo, keypair)
|
|
85
|
-
const diffCar = await streamToBuffer(
|
|
86
|
-
sync.getCommits(storage, badRepo.cid, syncRepo.cid),
|
|
87
|
-
)
|
|
88
|
-
await expect(
|
|
89
|
-
sync.loadDiff(syncRepo, diffCar, repoDid, keypair.did()),
|
|
90
|
-
).rejects.toThrow('Invalid signature on commit')
|
|
91
|
-
})
|
|
92
|
-
})
|