Skip to content

Commit 128c194

Browse files
authored
fix: sort event parents (#41)
Ensures event blocks are deterministic.
1 parent 5620002 commit 128c194

File tree

2 files changed

+28
-2
lines changed

2 files changed

+28
-2
lines changed

src/clock/index.js

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,30 @@ export class EventFetcher {
9494
* @returns {Promise<API.EventBlockView<T>>}
9595
*/
9696
export const encodeEventBlock = async (value) => {
97-
// TODO: sort parents
98-
const { cid, bytes } = await encode({ value, codec: cbor, hasher: sha256 })
97+
if (typeof value.data === 'undefined' || !Array.isArray(value.parents)) {
98+
throw new Error('invalid event block structure')
99+
}
100+
const { data } = value
101+
const parents = [...value.parents].sort((a, b) => compareBytes(a.bytes, b.bytes))
102+
const { cid, bytes } = await encode({ value: { data, parents }, codec: cbor, hasher: sha256 })
99103
// @ts-expect-error
100104
return new Block({ cid, value, bytes })
101105
}
102106

107+
/**
108+
* @param {Uint8Array} a
109+
* @param {Uint8Array} b
110+
*/
111+
const compareBytes = (a, b) => {
112+
for (let i = 0; i < a.byteLength; i++) {
113+
if (a[i] < b[i]) return -1
114+
if (a[i] > b[i]) return 1
115+
}
116+
if (a.byteLength > b.byteLength) return 1
117+
if (a.byteLength < b.byteLength) return -1
118+
return 0
119+
}
120+
103121
/**
104122
* @template T
105123
* @param {Uint8Array} bytes

test/clock.test.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,4 +292,12 @@ describe('clock', () => {
292292
assert.equal(head[0].toString(), event3.cid.toString())
293293
assert.equal(count - before, 8, 'The number of traversals should be 8 with optimization')
294294
})
295+
296+
it('sorts event links', async () => {
297+
const parent0 = await EventBlock.create(await randomEventData())
298+
const parent1 = await EventBlock.create(await randomEventData())
299+
const child0 = await EventBlock.create({}, [parent0.cid, parent1.cid])
300+
const child1 = await EventBlock.create({}, [parent1.cid, parent0.cid])
301+
assert.deepEqual(child0.bytes, child1.bytes)
302+
})
295303
})

0 commit comments

Comments
 (0)