@fireproof/core 0.0.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.
- package/index.js +5 -0
- package/package.json +70 -0
- package/scripts/propernames/gen.sh +3 -0
- package/scripts/randomcid.js +12 -0
- package/scripts/words/gen.js +55 -0
- package/src/block.js +75 -0
- package/src/blockstore.js +246 -0
- package/src/clock.js +352 -0
- package/src/db-index.js +196 -0
- package/src/fireproof.js +209 -0
- package/src/link.d.ts +3 -0
- package/src/listener.js +111 -0
- package/src/prolly.js +235 -0
- package/src/valet.js +142 -0
- package/test/clock.test.js +725 -0
- package/test/db-index.test.js +214 -0
- package/test/fireproof.test.js +287 -0
- package/test/helpers.js +45 -0
- package/test/listener.test.js +102 -0
- package/test/prolly.test.js +203 -0
@@ -0,0 +1,725 @@
|
|
1
|
+
import { describe, it } from 'mocha'
|
2
|
+
import assert from 'node:assert'
|
3
|
+
import { advance, EventBlock, findCommonAncestorWithSortedEvents, findUnknownSortedEvents, decodeEventBlock, findEventsToSync } from '../src/clock.js'
|
4
|
+
// import { vis } from '../src/clock.js'
|
5
|
+
import { Blockstore, seqEventData, setSeq } from './helpers.js'
|
6
|
+
|
7
|
+
async function visHead (blocks, head) {
|
8
|
+
// const values =
|
9
|
+
head.map(async (cid) => {
|
10
|
+
const block = await blocks.get(cid)
|
11
|
+
return (await decodeEventBlock(block.bytes)).value?.data?.value
|
12
|
+
})
|
13
|
+
// console.log('visHead', head, await Promise.all(values))
|
14
|
+
}
|
15
|
+
|
16
|
+
async function makeNext (blocks, parent, eventData) {
|
17
|
+
const event = await EventBlock.create(eventData, parent)
|
18
|
+
await blocks.put(event.cid, event.bytes)
|
19
|
+
const head = await advance(blocks, parent, event.cid)
|
20
|
+
return { event, head }
|
21
|
+
}
|
22
|
+
|
23
|
+
describe('Clock', () => {
|
24
|
+
it('create a new clock', async () => {
|
25
|
+
const blocks = new Blockstore()
|
26
|
+
// don't do this, create it with the first data block
|
27
|
+
const event = await EventBlock.create({})
|
28
|
+
|
29
|
+
await blocks.put(event.cid, event.bytes)
|
30
|
+
const head = await advance(blocks, [], event.cid)
|
31
|
+
|
32
|
+
// for await (const line of vis(blocks, head)) console.log(line)
|
33
|
+
assert.equal(head.length, 1)
|
34
|
+
assert.equal(head[0].toString(), event.cid.toString())
|
35
|
+
|
36
|
+
const sinceHead = head
|
37
|
+
const toSync = await findUnknownSortedEvents(blocks, sinceHead, await findCommonAncestorWithSortedEvents(blocks, sinceHead))
|
38
|
+
assert.equal(toSync.length, 0)
|
39
|
+
})
|
40
|
+
|
41
|
+
it('add events sequentially', async () => {
|
42
|
+
setSeq(0)
|
43
|
+
const blocks = new Blockstore()
|
44
|
+
const emptyhead = [] // this makes head0 the root
|
45
|
+
|
46
|
+
/*
|
47
|
+
* Create event0 for alice, with emptyhead as parent
|
48
|
+
*/
|
49
|
+
const { event: event0, head: head0 } = await makeNext(blocks, emptyhead, seqEventData('alice'))
|
50
|
+
assert(head0.length, 1)
|
51
|
+
assert.equal(head0[0].toString(), event0.cid.toString())
|
52
|
+
|
53
|
+
/*
|
54
|
+
* Create event1 for bob, with head0 as parent
|
55
|
+
*/
|
56
|
+
const { event: event1, head: head1 } = await makeNext(blocks, head0, seqEventData('bob'))
|
57
|
+
|
58
|
+
assert.equal(head1.length, 1)
|
59
|
+
assert.equal(head1[0].toString(), event1.cid.toString())
|
60
|
+
|
61
|
+
const toSync1 = await findEventsToSync(blocks, head1)
|
62
|
+
|
63
|
+
assert.equal(toSync1.length, 0)
|
64
|
+
|
65
|
+
/*
|
66
|
+
* Create event2 for carol, with head1 as parent
|
67
|
+
*/
|
68
|
+
const { event: event2, head: head2 } = await makeNext(blocks, head1, seqEventData('carol'))
|
69
|
+
|
70
|
+
assert.equal(head2.length, 1)
|
71
|
+
assert.equal(head2[0].toString(), event2.cid.toString())
|
72
|
+
|
73
|
+
const toSync2 = await findEventsToSync(blocks, head2)
|
74
|
+
assert.equal(toSync2.length, 0)
|
75
|
+
|
76
|
+
const toSync1b = await findEventsToSync(blocks, [...head2, ...head0])
|
77
|
+
|
78
|
+
assert.equal(toSync1b.length, 2)
|
79
|
+
assert.equal(toSync1b[0].value.data.value, 'event1bob')
|
80
|
+
assert.equal(toSync1b[1].value.data.value, 'event2carol')
|
81
|
+
|
82
|
+
/*
|
83
|
+
* Create event3 for dave, with head2 as parent
|
84
|
+
*/
|
85
|
+
|
86
|
+
const { event: event3, head: head3 } = await makeNext(blocks, head2, seqEventData('dave'))
|
87
|
+
|
88
|
+
assert.equal(head3.length, 1)
|
89
|
+
assert.equal(head3[0].toString(), event3.cid.toString())
|
90
|
+
|
91
|
+
const toSync3 = await findEventsToSync(blocks, [...head3, ...head0])
|
92
|
+
assert.equal(toSync3.length, 3)
|
93
|
+
assert.equal(toSync3[0].value.data.value, 'event1bob')
|
94
|
+
assert.equal(toSync3[1].value.data.value, 'event2carol')
|
95
|
+
assert.equal(toSync3[2].value.data.value, 'event3dave')
|
96
|
+
|
97
|
+
const toSync3B = await findEventsToSync(blocks, [...head3, ...head1])
|
98
|
+
assert.equal(toSync3B.length, 2)
|
99
|
+
assert.equal(toSync3B[0].value.data.value, 'event2carol')
|
100
|
+
assert.equal(toSync3B[1].value.data.value, 'event3dave')
|
101
|
+
|
102
|
+
/*
|
103
|
+
* Create event4 for eve, with head3 as parent
|
104
|
+
*/
|
105
|
+
const { event: event4, head: head4 } = await makeNext(blocks, head3, seqEventData('eve'))
|
106
|
+
|
107
|
+
assert.equal(head4.length, 1)
|
108
|
+
assert.equal(head4[0].toString(), event4.cid.toString())
|
109
|
+
|
110
|
+
const toSync4 = await findEventsToSync(blocks, [...head4, ...head0])
|
111
|
+
assert.equal(toSync4.length, 4)
|
112
|
+
assert.equal(toSync4[0].value.data.value, 'event1bob')
|
113
|
+
assert.equal(toSync4[1].value.data.value, 'event2carol')
|
114
|
+
assert.equal(toSync4[2].value.data.value, 'event3dave')
|
115
|
+
assert.equal(toSync4[3].value.data.value, 'event4eve')
|
116
|
+
|
117
|
+
const toSync4B = await findEventsToSync(blocks, [...head4, ...head1])
|
118
|
+
|
119
|
+
assert.equal(toSync4B.length, 3)
|
120
|
+
assert.equal(toSync4B[0].value.data.value, 'event2carol')
|
121
|
+
assert.equal(toSync4B[1].value.data.value, 'event3dave')
|
122
|
+
assert.equal(toSync4B[2].value.data.value, 'event4eve')
|
123
|
+
|
124
|
+
const toSync4C = await findEventsToSync(blocks, [...head4, ...head2])
|
125
|
+
|
126
|
+
assert.equal(toSync4C.length, 2)
|
127
|
+
assert.equal(toSync4C[0].value.data.value, 'event3dave')
|
128
|
+
assert.equal(toSync4C[1].value.data.value, 'event4eve')
|
129
|
+
|
130
|
+
// don't ask if you already know
|
131
|
+
// const toSync4D = await findEventsToSync(blocks, [...head4, ...head3])
|
132
|
+
// assert.equal(toSync4D.length, 0)
|
133
|
+
|
134
|
+
/*
|
135
|
+
* Create event5 for frank, with head4 as parent
|
136
|
+
*/
|
137
|
+
const { event: event5, head: head5 } = await makeNext(blocks, head4, seqEventData('frank'))
|
138
|
+
|
139
|
+
assert.equal(head5.length, 1)
|
140
|
+
assert.equal(head5[0].toString(), event5.cid.toString())
|
141
|
+
const toSync5 = await findEventsToSync(blocks, [...head5, ...head0])
|
142
|
+
assert.equal(toSync5.length, 5)
|
143
|
+
assert.equal(toSync5[0].value.data.value, 'event1bob')
|
144
|
+
assert.equal(toSync5[1].value.data.value, 'event2carol')
|
145
|
+
assert.equal(toSync5[2].value.data.value, 'event3dave')
|
146
|
+
assert.equal(toSync5[3].value.data.value, 'event4eve')
|
147
|
+
assert.equal(toSync5[4].value.data.value, 'event5frank')
|
148
|
+
|
149
|
+
const toSync5B = await findEventsToSync(blocks, [...head5, ...head1])
|
150
|
+
|
151
|
+
assert.equal(toSync5B.length, 4)
|
152
|
+
assert.equal(toSync5B[0].value.data.value, 'event2carol')
|
153
|
+
assert.equal(toSync5B[1].value.data.value, 'event3dave')
|
154
|
+
assert.equal(toSync5B[2].value.data.value, 'event4eve')
|
155
|
+
assert.equal(toSync5B[3].value.data.value, 'event5frank')
|
156
|
+
|
157
|
+
const toSync5C = await findEventsToSync(blocks, [...head5, ...head2])
|
158
|
+
assert(toSync5C.length > 0, 'should have 3 events, has ' + toSync5C.length)
|
159
|
+
assert.equal(toSync5C[0].value.data.value, 'event3dave')
|
160
|
+
assert.equal(toSync5C[1].value.data.value, 'event4eve')
|
161
|
+
assert.equal(toSync5C[2].value.data.value, 'event5frank')
|
162
|
+
|
163
|
+
const toSync5D = await findEventsToSync(blocks, [...head5, ...head3])
|
164
|
+
assert.equal(toSync5D.length, 2) // 4
|
165
|
+
assert.equal(toSync5D[0].value.data.value, 'event4eve')
|
166
|
+
assert.equal(toSync5D[1].value.data.value, 'event5frank')
|
167
|
+
|
168
|
+
const toSync5E = await findEventsToSync(blocks, [...head5, ...head4])
|
169
|
+
assert.equal(toSync5E.length, 1) // 5
|
170
|
+
assert.equal(toSync5E[0].value.data.value, 'event5frank')
|
171
|
+
|
172
|
+
/*
|
173
|
+
* Create event6 for grace, with head5 as parent
|
174
|
+
*/
|
175
|
+
const { event: event6, head: head6 } = await makeNext(blocks, head5, seqEventData('grace'))
|
176
|
+
|
177
|
+
assert.equal(head6.length, 1)
|
178
|
+
assert.equal(head6[0].toString(), event6.cid.toString())
|
179
|
+
|
180
|
+
const toSync6 = await findEventsToSync(blocks, [...head6, ...head0])
|
181
|
+
assert.equal(toSync6.length, 6) // 1
|
182
|
+
assert.equal(toSync6[0].value.data.value, 'event1bob')
|
183
|
+
assert.equal(toSync6[1].value.data.value, 'event2carol')
|
184
|
+
assert.equal(toSync6[2].value.data.value, 'event3dave')
|
185
|
+
assert.equal(toSync6[3].value.data.value, 'event4eve')
|
186
|
+
assert.equal(toSync6[4].value.data.value, 'event5frank')
|
187
|
+
assert.equal(toSync6[5].value.data.value, 'event6grace')
|
188
|
+
|
189
|
+
const toSync6B = await findEventsToSync(blocks, [...head6, ...head1])
|
190
|
+
assert.equal(toSync6B.length, 5) // 2
|
191
|
+
assert.equal(toSync6B[0].value.data.value, 'event2carol')
|
192
|
+
assert.equal(toSync6B[1].value.data.value, 'event3dave')
|
193
|
+
assert.equal(toSync6B[2].value.data.value, 'event4eve')
|
194
|
+
assert.equal(toSync6B[3].value.data.value, 'event5frank')
|
195
|
+
assert.equal(toSync6B[4].value.data.value, 'event6grace')
|
196
|
+
|
197
|
+
const toSync6C = await findEventsToSync(blocks, [...head6, ...head2])
|
198
|
+
assert.equal(toSync6C.length, 4) // 3
|
199
|
+
assert.equal(toSync6C[0].value.data.value, 'event3dave')
|
200
|
+
assert.equal(toSync6C[1].value.data.value, 'event4eve')
|
201
|
+
assert.equal(toSync6C[2].value.data.value, 'event5frank')
|
202
|
+
assert.equal(toSync6C[3].value.data.value, 'event6grace')
|
203
|
+
|
204
|
+
const toSync6D = await findEventsToSync(blocks, [...head6, ...head3])
|
205
|
+
assert.equal(toSync6D.length, 3) // 4
|
206
|
+
assert.equal(toSync6D[0].value.data.value, 'event4eve')
|
207
|
+
assert.equal(toSync6D[1].value.data.value, 'event5frank')
|
208
|
+
assert.equal(toSync6D[2].value.data.value, 'event6grace')
|
209
|
+
|
210
|
+
const toSync6E = await findEventsToSync(blocks, [...head6, ...head4])
|
211
|
+
assert.equal(toSync6E.length, 2) // 5
|
212
|
+
assert.equal(toSync6E[0].value.data.value, 'event5frank')
|
213
|
+
assert.equal(toSync6E[1].value.data.value, 'event6grace')
|
214
|
+
|
215
|
+
const toSync6F = await findEventsToSync(blocks, [...head6, ...head5])
|
216
|
+
assert.equal(toSync6F.length, 1)
|
217
|
+
assert.equal(toSync6F[0].value.data.value, 'event6grace')
|
218
|
+
|
219
|
+
/*
|
220
|
+
* Create event7 for grace, with head6 as parent
|
221
|
+
*/
|
222
|
+
const { event: event7, head: head7 } = await makeNext(blocks, head6, seqEventData('holly'))
|
223
|
+
|
224
|
+
assert.equal(head7.length, 1)
|
225
|
+
assert.equal(head7[0].toString(), event7.cid.toString())
|
226
|
+
|
227
|
+
const toSync7 = await findEventsToSync(blocks, [...head7, ...head0])
|
228
|
+
assert.equal(toSync7.length, 7)
|
229
|
+
assert.equal(toSync7[0].value.data.value, 'event1bob')
|
230
|
+
assert.equal(toSync7[1].value.data.value, 'event2carol')
|
231
|
+
assert.equal(toSync7[2].value.data.value, 'event3dave')
|
232
|
+
assert.equal(toSync7[3].value.data.value, 'event4eve')
|
233
|
+
assert.equal(toSync7[4].value.data.value, 'event5frank')
|
234
|
+
assert.equal(toSync7[5].value.data.value, 'event6grace')
|
235
|
+
assert.equal(toSync7[6].value.data.value, 'event7holly')
|
236
|
+
|
237
|
+
const toSync7B = await findEventsToSync(blocks, [...head7, ...head1])
|
238
|
+
assert.equal(toSync7B.length, 6)
|
239
|
+
assert.equal(toSync7B[0].value.data.value, 'event2carol')
|
240
|
+
assert.equal(toSync7B[1].value.data.value, 'event3dave')
|
241
|
+
assert.equal(toSync7B[2].value.data.value, 'event4eve')
|
242
|
+
assert.equal(toSync7B[3].value.data.value, 'event5frank')
|
243
|
+
assert.equal(toSync7B[4].value.data.value, 'event6grace')
|
244
|
+
|
245
|
+
const toSync7C = await findEventsToSync(blocks, [...head7, ...head2])
|
246
|
+
assert.equal(toSync7C.length, 5)
|
247
|
+
assert.equal(toSync7C[0].value.data.value, 'event3dave')
|
248
|
+
assert.equal(toSync7C[1].value.data.value, 'event4eve')
|
249
|
+
assert.equal(toSync7C[2].value.data.value, 'event5frank')
|
250
|
+
assert.equal(toSync7C[3].value.data.value, 'event6grace')
|
251
|
+
assert.equal(toSync7C[4].value.data.value, 'event7holly')
|
252
|
+
|
253
|
+
const toSync7D = await findEventsToSync(blocks, [...head7, ...head3])
|
254
|
+
assert.equal(toSync7D.length, 4)
|
255
|
+
assert.equal(toSync7D[0].value.data.value, 'event4eve')
|
256
|
+
assert.equal(toSync7D[1].value.data.value, 'event5frank')
|
257
|
+
assert.equal(toSync7D[2].value.data.value, 'event6grace')
|
258
|
+
assert.equal(toSync7D[3].value.data.value, 'event7holly')
|
259
|
+
|
260
|
+
const toSync7E = await findEventsToSync(blocks, [...head7, ...head4])
|
261
|
+
assert.equal(toSync7E.length, 3)
|
262
|
+
assert.equal(toSync7E[0].value.data.value, 'event5frank')
|
263
|
+
assert.equal(toSync7E[1].value.data.value, 'event6grace')
|
264
|
+
assert.equal(toSync7E[2].value.data.value, 'event7holly')
|
265
|
+
|
266
|
+
const toSync7F = await findEventsToSync(blocks, [...head7, ...head5])
|
267
|
+
assert.equal(toSync7F.length, 2)
|
268
|
+
assert.equal(toSync7F[0].value.data.value, 'event6grace')
|
269
|
+
assert.equal(toSync7F[1].value.data.value, 'event7holly')
|
270
|
+
|
271
|
+
/*
|
272
|
+
* Create event8 for isaac, with head7 as parent
|
273
|
+
*/
|
274
|
+
const { event: event8, head: head8 } = await makeNext(blocks, head7, seqEventData('isaac'))
|
275
|
+
|
276
|
+
assert.equal(head8.length, 1)
|
277
|
+
assert.equal(head8[0].toString(), event8.cid.toString())
|
278
|
+
|
279
|
+
const toSync8 = await findEventsToSync(blocks, [...head8, ...head0])
|
280
|
+
assert.equal(toSync8.length, 8)
|
281
|
+
assert.equal(toSync8[0].value.data.value, 'event1bob')
|
282
|
+
assert.equal(toSync8[1].value.data.value, 'event2carol')
|
283
|
+
assert.equal(toSync8[2].value.data.value, 'event3dave')
|
284
|
+
assert.equal(toSync8[3].value.data.value, 'event4eve')
|
285
|
+
assert.equal(toSync8[4].value.data.value, 'event5frank')
|
286
|
+
assert.equal(toSync8[5].value.data.value, 'event6grace')
|
287
|
+
assert.equal(toSync8[6].value.data.value, 'event7holly')
|
288
|
+
assert.equal(toSync8[7].value.data.value, 'event8isaac')
|
289
|
+
|
290
|
+
const toSync8B = await findEventsToSync(blocks, [...head8, ...head1])
|
291
|
+
assert.equal(toSync8B.length, 7)
|
292
|
+
assert.equal(toSync8B[0].value.data.value, 'event2carol')
|
293
|
+
assert.equal(toSync8B[1].value.data.value, 'event3dave')
|
294
|
+
assert.equal(toSync8B[2].value.data.value, 'event4eve')
|
295
|
+
assert.equal(toSync8B[3].value.data.value, 'event5frank')
|
296
|
+
assert.equal(toSync8B[4].value.data.value, 'event6grace')
|
297
|
+
assert.equal(toSync8B[5].value.data.value, 'event7holly')
|
298
|
+
assert.equal(toSync8B[6].value.data.value, 'event8isaac')
|
299
|
+
|
300
|
+
const toSync8C = await findEventsToSync(blocks, [...head8, ...head2])
|
301
|
+
assert.equal(toSync8C.length, 6) // 3
|
302
|
+
assert.equal(toSync8C[0].value.data.value, 'event3dave')
|
303
|
+
assert.equal(toSync8C[1].value.data.value, 'event4eve')
|
304
|
+
assert.equal(toSync8C[2].value.data.value, 'event5frank')
|
305
|
+
assert.equal(toSync8C[3].value.data.value, 'event6grace')
|
306
|
+
assert.equal(toSync8C[4].value.data.value, 'event7holly')
|
307
|
+
assert.equal(toSync8C[5].value.data.value, 'event8isaac')
|
308
|
+
|
309
|
+
const toSync8D = await findEventsToSync(blocks, [...head8, ...head3])
|
310
|
+
assert.equal(toSync8D.length, 5) // 4
|
311
|
+
assert.equal(toSync8D[0].value.data.value, 'event4eve')
|
312
|
+
assert.equal(toSync8D[1].value.data.value, 'event5frank')
|
313
|
+
assert.equal(toSync8D[2].value.data.value, 'event6grace')
|
314
|
+
assert.equal(toSync8D[3].value.data.value, 'event7holly')
|
315
|
+
assert.equal(toSync8D[4].value.data.value, 'event8isaac')
|
316
|
+
|
317
|
+
const toSync8E = await findEventsToSync(blocks, [...head8, ...head4])
|
318
|
+
assert.equal(toSync8E.length, 4) // 5
|
319
|
+
assert.equal(toSync8E[0].value.data.value, 'event5frank')
|
320
|
+
assert.equal(toSync8E[1].value.data.value, 'event6grace')
|
321
|
+
assert.equal(toSync8E[2].value.data.value, 'event7holly')
|
322
|
+
assert.equal(toSync8E[3].value.data.value, 'event8isaac')
|
323
|
+
|
324
|
+
const toSync8F = await findEventsToSync(blocks, [...head8, ...head5])
|
325
|
+
assert.equal(toSync8F.length, 3) // 6
|
326
|
+
assert.equal(toSync8F[0].value.data.value, 'event6grace')
|
327
|
+
assert.equal(toSync8F[1].value.data.value, 'event7holly')
|
328
|
+
assert.equal(toSync8F[2].value.data.value, 'event8isaac')
|
329
|
+
|
330
|
+
/*
|
331
|
+
* Create event9 for jen, with head8 as parent
|
332
|
+
*/
|
333
|
+
const { event: event9, head: head9 } = await makeNext(blocks, head8, seqEventData('jen'))
|
334
|
+
|
335
|
+
assert.equal(head9.length, 1)
|
336
|
+
assert.equal(head9[0].toString(), event9.cid.toString())
|
337
|
+
|
338
|
+
const toSync9 = await findEventsToSync(blocks, [...head9, ...head0])
|
339
|
+
assert.equal(toSync9.length, 9)
|
340
|
+
assert.equal(toSync9[0].value.data.value, 'event1bob')
|
341
|
+
assert.equal(toSync9[1].value.data.value, 'event2carol')
|
342
|
+
assert.equal(toSync9[2].value.data.value, 'event3dave')
|
343
|
+
assert.equal(toSync9[3].value.data.value, 'event4eve')
|
344
|
+
assert.equal(toSync9[4].value.data.value, 'event5frank')
|
345
|
+
assert.equal(toSync9[5].value.data.value, 'event6grace')
|
346
|
+
assert.equal(toSync9[6].value.data.value, 'event7holly')
|
347
|
+
assert.equal(toSync9[7].value.data.value, 'event8isaac')
|
348
|
+
assert.equal(toSync9[8].value.data.value, 'event9jen')
|
349
|
+
|
350
|
+
const toSync9B = await findEventsToSync(blocks, [...head9, ...head1])
|
351
|
+
assert.equal(toSync9B.length, 8)
|
352
|
+
assert.equal(toSync9B[0].value.data.value, 'event2carol')
|
353
|
+
assert.equal(toSync9B[1].value.data.value, 'event3dave')
|
354
|
+
assert.equal(toSync9B[2].value.data.value, 'event4eve')
|
355
|
+
assert.equal(toSync9B[3].value.data.value, 'event5frank')
|
356
|
+
assert.equal(toSync9B[4].value.data.value, 'event6grace')
|
357
|
+
assert.equal(toSync9B[5].value.data.value, 'event7holly')
|
358
|
+
assert.equal(toSync9B[6].value.data.value, 'event8isaac')
|
359
|
+
assert.equal(toSync9B[7].value.data.value, 'event9jen')
|
360
|
+
|
361
|
+
const toSync9C = await findEventsToSync(blocks, [...head9, ...head2])
|
362
|
+
assert.equal(toSync9C.length, 7)
|
363
|
+
assert.equal(toSync9C[0].value.data.value, 'event3dave')
|
364
|
+
assert.equal(toSync9C[1].value.data.value, 'event4eve')
|
365
|
+
assert.equal(toSync9C[2].value.data.value, 'event5frank')
|
366
|
+
assert.equal(toSync9C[3].value.data.value, 'event6grace')
|
367
|
+
assert.equal(toSync9C[4].value.data.value, 'event7holly')
|
368
|
+
assert.equal(toSync9C[5].value.data.value, 'event8isaac')
|
369
|
+
assert.equal(toSync9C[6].value.data.value, 'event9jen')
|
370
|
+
|
371
|
+
const toSync9D = await findEventsToSync(blocks, [...head9, ...head3])
|
372
|
+
assert.equal(toSync9D.length, 6)
|
373
|
+
assert.equal(toSync9D[0].value.data.value, 'event4eve')
|
374
|
+
assert.equal(toSync9D[1].value.data.value, 'event5frank')
|
375
|
+
assert.equal(toSync9D[2].value.data.value, 'event6grace')
|
376
|
+
assert.equal(toSync9D[3].value.data.value, 'event7holly')
|
377
|
+
assert.equal(toSync9D[4].value.data.value, 'event8isaac')
|
378
|
+
assert.equal(toSync9D[5].value.data.value, 'event9jen')
|
379
|
+
|
380
|
+
const toSync9E = await findEventsToSync(blocks, [...head9, ...head4])
|
381
|
+
assert.equal(toSync9E.length, 5)
|
382
|
+
assert.equal(toSync9E[0].value.data.value, 'event5frank')
|
383
|
+
assert.equal(toSync9E[1].value.data.value, 'event6grace')
|
384
|
+
assert.equal(toSync9E[2].value.data.value, 'event7holly')
|
385
|
+
assert.equal(toSync9E[3].value.data.value, 'event8isaac')
|
386
|
+
assert.equal(toSync9E[4].value.data.value, 'event9jen')
|
387
|
+
|
388
|
+
// for await (const line of vis(blocks, head8)) console.log(line)
|
389
|
+
})
|
390
|
+
|
391
|
+
it('add two events with shared parents', async () => {
|
392
|
+
setSeq(-1)
|
393
|
+
const blocks = new Blockstore()
|
394
|
+
const root = await EventBlock.create(seqEventData('root'))
|
395
|
+
await blocks.put(root.cid, root.bytes)
|
396
|
+
|
397
|
+
/** @type {import('../src/clock').EventLink<any>[]} */
|
398
|
+
let head = await advance(blocks, [], root.cid)
|
399
|
+
assert.equal(head.length, 1)
|
400
|
+
assert.equal(head[0], root.cid)
|
401
|
+
|
402
|
+
const parents = head
|
403
|
+
|
404
|
+
const event0 = await EventBlock.create(seqEventData(), parents)
|
405
|
+
await blocks.put(event0.cid, event0.bytes)
|
406
|
+
|
407
|
+
head = await advance(blocks, parents, event0.cid)
|
408
|
+
const head0 = head
|
409
|
+
|
410
|
+
const event1 = await EventBlock.create(seqEventData(), parents)
|
411
|
+
await blocks.put(event1.cid, event1.bytes)
|
412
|
+
head = await advance(blocks, head, event1.cid)
|
413
|
+
const head1 = head
|
414
|
+
|
415
|
+
// for await (const line of vis(blocks, head)) console.log(line)
|
416
|
+
assert.equal(head.length, 2)
|
417
|
+
assert.equal(head[0].toString(), event0.cid.toString())
|
418
|
+
assert.equal(head[1].toString(), event1.cid.toString())
|
419
|
+
|
420
|
+
let sinceHead = head1
|
421
|
+
let toSync = await findUnknownSortedEvents(blocks, sinceHead, await findCommonAncestorWithSortedEvents(blocks, sinceHead))
|
422
|
+
// assert.equal(toSync.length, 1) // 0
|
423
|
+
// assert.equal(toSync[0].cid.toString(), event0.cid.toString())
|
424
|
+
|
425
|
+
const event2 = await EventBlock.create(seqEventData(), head1)
|
426
|
+
await blocks.put(event2.cid, event2.bytes)
|
427
|
+
head = await advance(blocks, head, event2.cid)
|
428
|
+
const head2 = head
|
429
|
+
|
430
|
+
assert.equal(head.length, 1)
|
431
|
+
|
432
|
+
sinceHead = head2
|
433
|
+
toSync = await findUnknownSortedEvents(blocks, sinceHead, await findCommonAncestorWithSortedEvents(blocks, sinceHead))
|
434
|
+
assert.equal(toSync.length, 0)
|
435
|
+
|
436
|
+
// todo do these since heads make sense?
|
437
|
+
sinceHead = [...head0, ...head2]
|
438
|
+
toSync = await findUnknownSortedEvents(blocks, sinceHead, await findCommonAncestorWithSortedEvents(blocks, sinceHead))
|
439
|
+
// console.log('need', toSync.map(b => b.value.data))
|
440
|
+
// assert.equal(toSync.length, 2) // 0
|
441
|
+
// assert.equal(toSync[0].cid.toString(), event1.cid.toString())
|
442
|
+
// assert.equal(toSync[1].cid.toString(), event2.cid.toString())
|
443
|
+
})
|
444
|
+
|
445
|
+
it('add two events with some shared parents', async () => {
|
446
|
+
const blocks = new Blockstore()
|
447
|
+
const root = await EventBlock.create(seqEventData())
|
448
|
+
await blocks.put(root.cid, root.bytes)
|
449
|
+
|
450
|
+
/** @type {import('../src/clock').EventLink<any>[]} */
|
451
|
+
let head = [root.cid]
|
452
|
+
const parents0 = head
|
453
|
+
|
454
|
+
const event0 = await EventBlock.create(seqEventData(), parents0)
|
455
|
+
await blocks.put(event0.cid, event0.bytes)
|
456
|
+
head = await advance(blocks, head, event0.cid)
|
457
|
+
|
458
|
+
const event1 = await EventBlock.create(seqEventData(), parents0)
|
459
|
+
await blocks.put(event1.cid, event1.bytes)
|
460
|
+
head = await advance(blocks, head, event1.cid)
|
461
|
+
|
462
|
+
const event2 = await EventBlock.create(seqEventData(), parents0)
|
463
|
+
await blocks.put(event2.cid, event2.bytes)
|
464
|
+
head = await advance(blocks, head, event2.cid)
|
465
|
+
|
466
|
+
const event3 = await EventBlock.create(seqEventData(), [event0.cid, event1.cid])
|
467
|
+
await blocks.put(event3.cid, event3.bytes)
|
468
|
+
head = await advance(blocks, head, event3.cid)
|
469
|
+
// const parentz = head
|
470
|
+
|
471
|
+
const event4 = await EventBlock.create(seqEventData(), [event2.cid])
|
472
|
+
await blocks.put(event4.cid, event4.bytes)
|
473
|
+
head = await advance(blocks, head, event4.cid)
|
474
|
+
|
475
|
+
// console.log('add two events with some shared parents')
|
476
|
+
// for await (const line of vis(blocks, head)) console.log(line)
|
477
|
+
assert.equal(head.length, 2)
|
478
|
+
assert.equal(head[0].toString(), event3.cid.toString())
|
479
|
+
assert.equal(head[1].toString(), event4.cid.toString())
|
480
|
+
// console.log('since', parentz)
|
481
|
+
// for await (const block of since(blocks, parentz)) {
|
482
|
+
// if (block?.value) console.log(block.value.data)
|
483
|
+
// }
|
484
|
+
// const { ancestor, sorted } = await findCommonAncestorWithSortedEvents(blocks, parentz)
|
485
|
+
// console.log('findCommonAncestorWithSortedEvents', ancestor, sorted.map(b => b.value.data))
|
486
|
+
})
|
487
|
+
|
488
|
+
it('converge when multi-root', async () => {
|
489
|
+
setSeq(-1)
|
490
|
+
const blocks = new Blockstore()
|
491
|
+
const root = await EventBlock.create(seqEventData())
|
492
|
+
await blocks.put(root.cid, root.bytes)
|
493
|
+
|
494
|
+
/** @type {import('../src/clock').EventLink<any>[]} */
|
495
|
+
let head = [root.cid]
|
496
|
+
const parents0 = head
|
497
|
+
|
498
|
+
const event0 = await EventBlock.create(seqEventData(), parents0)
|
499
|
+
await blocks.put(event0.cid, event0.bytes)
|
500
|
+
head = await advance(blocks, head, event0.cid)
|
501
|
+
|
502
|
+
const event1 = await EventBlock.create(seqEventData(), parents0)
|
503
|
+
await blocks.put(event1.cid, event1.bytes)
|
504
|
+
head = await advance(blocks, head, event1.cid)
|
505
|
+
|
506
|
+
const event1head = head
|
507
|
+
|
508
|
+
const event2 = await EventBlock.create(seqEventData(), event1head)
|
509
|
+
await blocks.put(event2.cid, event2.bytes)
|
510
|
+
head = await advance(blocks, head, event2.cid)
|
511
|
+
|
512
|
+
const event3 = await EventBlock.create(seqEventData(), event1head)
|
513
|
+
await blocks.put(event3.cid, event3.bytes)
|
514
|
+
head = await advance(blocks, head, event3.cid)
|
515
|
+
|
516
|
+
const event3head = head
|
517
|
+
|
518
|
+
const event4 = await EventBlock.create(seqEventData(), event1head)
|
519
|
+
await blocks.put(event4.cid, event4.bytes)
|
520
|
+
head = await advance(blocks, head, event4.cid)
|
521
|
+
const event4head = head
|
522
|
+
await visHead(blocks, event4head)
|
523
|
+
|
524
|
+
const event5 = await EventBlock.create(seqEventData(), event3head)
|
525
|
+
await blocks.put(event5.cid, event5.bytes)
|
526
|
+
head = await advance(blocks, head, event5.cid)
|
527
|
+
const event5head = head
|
528
|
+
await visHead(blocks, event5head)
|
529
|
+
|
530
|
+
const event6 = await EventBlock.create(seqEventData(), event5head)
|
531
|
+
await blocks.put(event6.cid, event6.bytes)
|
532
|
+
head = await advance(blocks, head, event6.cid)
|
533
|
+
const event6head = head
|
534
|
+
await visHead(blocks, event6head)
|
535
|
+
|
536
|
+
const event7 = await EventBlock.create(seqEventData(), event6head)
|
537
|
+
await blocks.put(event7.cid, event7.bytes)
|
538
|
+
head = await advance(blocks, head, event7.cid)
|
539
|
+
const event7head = head
|
540
|
+
await visHead(blocks, event7head)
|
541
|
+
|
542
|
+
const event8 = await EventBlock.create(seqEventData(), event7head)
|
543
|
+
await blocks.put(event8.cid, event8.bytes)
|
544
|
+
head = await advance(blocks, head, event8.cid)
|
545
|
+
const event8head = head
|
546
|
+
await visHead(blocks, event8head)
|
547
|
+
|
548
|
+
const event9 = await EventBlock.create(seqEventData(), event7head)
|
549
|
+
await blocks.put(event9.cid, event9.bytes)
|
550
|
+
head = await advance(blocks, head, event9.cid)
|
551
|
+
const event9head = head
|
552
|
+
await visHead(blocks, event9head)
|
553
|
+
|
554
|
+
const event10 = await EventBlock.create(seqEventData(), event9head)
|
555
|
+
await blocks.put(event10.cid, event10.bytes)
|
556
|
+
head = await advance(blocks, head, event10.cid)
|
557
|
+
const event10head = head
|
558
|
+
await visHead(blocks, event10head)
|
559
|
+
|
560
|
+
// console.log('converge when multi-root')
|
561
|
+
// for await (const line of vis(blocks, event10head)) console.log(line)
|
562
|
+
|
563
|
+
assert.equal(event10head.length, 1)
|
564
|
+
assert.equal(event10head[0].toString(), event10.cid.toString())
|
565
|
+
|
566
|
+
// todo do these roots make sense?
|
567
|
+
// const { ancestor, sorted } = await findCommonAncestorWithSortedEvents(blocks, [event5.cid, event2.cid])
|
568
|
+
// const toSync = await findUnknownSortedEvents(blocks, [event5.cid, event2.cid], { ancestor, sorted })
|
569
|
+
// assert.equal(toSync.length, 0)
|
570
|
+
// assert.equal(toSync[0].value.data.value, 'event3')
|
571
|
+
// assert.equal(toSync[1].value.data.value, 'event5')
|
572
|
+
|
573
|
+
// todo do these roots make sense?
|
574
|
+
// const ancestorWithSorted = await findCommonAncestorWithSortedEvents(blocks, [event6.cid, event2.cid])
|
575
|
+
// const toSync2 = await findUnknownSortedEvents(blocks, [event6.cid, event2.cid], ancestorWithSorted)
|
576
|
+
// assert.equal(toSync2.length, 0)
|
577
|
+
|
578
|
+
// assert.equal(toSync2[0].value.data.value, 'event3')
|
579
|
+
// assert.equal(toSync2[1].value.data.value, 'event5')
|
580
|
+
// assert.equal(toSync2[2].value.data.value, 'event4')
|
581
|
+
// assert.equal(toSync2[3].value.data.value, 'event6')
|
582
|
+
// const ancestorBlock = await blocks.get(ancestor)
|
583
|
+
// const ancestorDecoded = await decodeEventBlock(ancestorBlock.bytes)
|
584
|
+
const ancestorWithSorted2 = await findCommonAncestorWithSortedEvents(blocks, [event7.cid, event10.cid])
|
585
|
+
const toSync3 = await findUnknownSortedEvents(blocks, [event7.cid, event10.cid], ancestorWithSorted2)
|
586
|
+
assert.equal(toSync3[0].value.data.value, 'event9')
|
587
|
+
assert.equal(toSync3[1].value.data.value, 'event8')
|
588
|
+
assert.equal(toSync3[2].value.data.value, 'event10')
|
589
|
+
})
|
590
|
+
|
591
|
+
it('add an old event', async () => {
|
592
|
+
const blocks = new Blockstore()
|
593
|
+
const root = await EventBlock.create(seqEventData())
|
594
|
+
await blocks.put(root.cid, root.bytes)
|
595
|
+
|
596
|
+
/** @type {import('../src/clock').EventLink<any>[]} */
|
597
|
+
let head = [root.cid]
|
598
|
+
const parents0 = head
|
599
|
+
|
600
|
+
const event0 = await EventBlock.create(seqEventData(), parents0)
|
601
|
+
await blocks.put(event0.cid, event0.bytes)
|
602
|
+
head = await advance(blocks, head, event0.cid)
|
603
|
+
|
604
|
+
const event1 = await EventBlock.create(seqEventData(), parents0)
|
605
|
+
await blocks.put(event1.cid, event1.bytes)
|
606
|
+
head = await advance(blocks, head, event1.cid)
|
607
|
+
|
608
|
+
const event1head = head
|
609
|
+
|
610
|
+
const event2 = await EventBlock.create(seqEventData(), event1head)
|
611
|
+
await blocks.put(event2.cid, event2.bytes)
|
612
|
+
head = await advance(blocks, head, event2.cid)
|
613
|
+
|
614
|
+
const event3 = await EventBlock.create(seqEventData(), event1head)
|
615
|
+
await blocks.put(event3.cid, event3.bytes)
|
616
|
+
head = await advance(blocks, head, event3.cid)
|
617
|
+
|
618
|
+
const event4 = await EventBlock.create(seqEventData(), event1head)
|
619
|
+
await blocks.put(event4.cid, event4.bytes)
|
620
|
+
head = await advance(blocks, head, event4.cid)
|
621
|
+
|
622
|
+
const parents2 = head
|
623
|
+
|
624
|
+
const event5 = await EventBlock.create(seqEventData(), parents2)
|
625
|
+
await blocks.put(event5.cid, event5.bytes)
|
626
|
+
head = await advance(blocks, head, event5.cid)
|
627
|
+
|
628
|
+
// now very old one
|
629
|
+
const event6 = await EventBlock.create(seqEventData(), parents0)
|
630
|
+
await blocks.put(event6.cid, event6.bytes)
|
631
|
+
head = await advance(blocks, head, event6.cid)
|
632
|
+
|
633
|
+
// for await (const line of vis(blocks, head)) console.log(line)
|
634
|
+
assert.equal(head.length, 2)
|
635
|
+
assert.equal(head[0].toString(), event5.cid.toString())
|
636
|
+
assert.equal(head[1].toString(), event6.cid.toString())
|
637
|
+
})
|
638
|
+
|
639
|
+
it('add an event with missing parents', async () => {
|
640
|
+
setSeq(-1)
|
641
|
+
const blocks = new Blockstore()
|
642
|
+
const root = await EventBlock.create(seqEventData())
|
643
|
+
await blocks.put(root.cid, root.bytes)
|
644
|
+
|
645
|
+
/** @type {import('../src/clock').EventLink<any>[]} */
|
646
|
+
let head = [root.cid]
|
647
|
+
|
648
|
+
const event0 = await EventBlock.create(seqEventData(), head)
|
649
|
+
await blocks.put(event0.cid, event0.bytes)
|
650
|
+
|
651
|
+
const event1 = await EventBlock.create(seqEventData(), [event0.cid])
|
652
|
+
await blocks.put(event1.cid, event1.bytes)
|
653
|
+
|
654
|
+
head = await advance(blocks, head, event1.cid)
|
655
|
+
|
656
|
+
// for await (const line of vis(blocks, head)) console.log(line)
|
657
|
+
assert.equal(head.length, 1)
|
658
|
+
assert.equal(head[0].toString(), event1.cid.toString())
|
659
|
+
})
|
660
|
+
|
661
|
+
it('reproduce the issue from fireproof docs since update test', async () => {
|
662
|
+
setSeq(-1)
|
663
|
+
const blocks = new Blockstore()
|
664
|
+
// alice
|
665
|
+
const root = await EventBlock.create(seqEventData('alice'))
|
666
|
+
await blocks.put(root.cid, root.bytes)
|
667
|
+
let head = await advance(blocks, [], root.cid)
|
668
|
+
const roothead = head
|
669
|
+
// db root
|
670
|
+
let sinceHead = [...roothead]
|
671
|
+
let toSync = await findUnknownSortedEvents(blocks, sinceHead, await findCommonAncestorWithSortedEvents(blocks, sinceHead))
|
672
|
+
assert.equal(toSync.length, 0) // we use all docs for first query in Fireproof
|
673
|
+
|
674
|
+
// create bob
|
675
|
+
const event0 = await EventBlock.create(seqEventData('bob'), head)
|
676
|
+
await blocks.put(event0.cid, event0.bytes)
|
677
|
+
// console.log('new event0', event0.cid)
|
678
|
+
|
679
|
+
head = await advance(blocks, head, event0.cid)
|
680
|
+
|
681
|
+
const event0head = head
|
682
|
+
sinceHead = event0head
|
683
|
+
toSync = await findUnknownSortedEvents(blocks, sinceHead, await findCommonAncestorWithSortedEvents(blocks, sinceHead))
|
684
|
+
assert.equal(toSync.length, 0)
|
685
|
+
|
686
|
+
sinceHead = [...roothead, ...event0head]
|
687
|
+
toSync = await findUnknownSortedEvents(blocks, sinceHead, await findCommonAncestorWithSortedEvents(blocks, sinceHead))
|
688
|
+
assert.equal(toSync.length, 1)
|
689
|
+
|
690
|
+
// create carol
|
691
|
+
const event1 = await EventBlock.create(seqEventData('carol'), head)
|
692
|
+
await blocks.put(event1.cid, event1.bytes)
|
693
|
+
head = await advance(blocks, head, event1.cid)
|
694
|
+
const event1head = head
|
695
|
+
|
696
|
+
sinceHead = [...event0head, ...event1head]
|
697
|
+
// sinceHead = event0head
|
698
|
+
const sigil = await findCommonAncestorWithSortedEvents(blocks, sinceHead)
|
699
|
+
// console.log('ancestor', (await decodeEventBlock((await blocks.get(sigil.ancestor)).bytes)).value)
|
700
|
+
|
701
|
+
toSync = await findUnknownSortedEvents(blocks, sinceHead, sigil)
|
702
|
+
|
703
|
+
assert.equal(toSync.length, 1)
|
704
|
+
|
705
|
+
// for await (const line of vis(blocks, head)) console.log(line)
|
706
|
+
|
707
|
+
sinceHead = [...event1head, ...roothead]
|
708
|
+
toSync = await findUnknownSortedEvents(blocks, sinceHead, await findCommonAncestorWithSortedEvents(blocks, sinceHead))
|
709
|
+
|
710
|
+
assert.equal(toSync.length, 2)
|
711
|
+
|
712
|
+
const event2 = await EventBlock.create(seqEventData('xxx'), head)
|
713
|
+
await blocks.put(event2.cid, event2.bytes)
|
714
|
+
head = await advance(blocks, head, event2.cid)
|
715
|
+
const event2head = head
|
716
|
+
|
717
|
+
sinceHead = [...event2head, ...event0head]
|
718
|
+
toSync = await findUnknownSortedEvents(blocks, sinceHead, await findCommonAncestorWithSortedEvents(blocks, sinceHead))
|
719
|
+
assert.equal(toSync.length, 2)
|
720
|
+
|
721
|
+
sinceHead = [...event2head, ...event1head]
|
722
|
+
toSync = await findUnknownSortedEvents(blocks, sinceHead, await findCommonAncestorWithSortedEvents(blocks, sinceHead))
|
723
|
+
assert.equal(toSync.length, 1)
|
724
|
+
})
|
725
|
+
})
|