-
Notifications
You must be signed in to change notification settings - Fork 14
Emit an event on corrupted hypercores #76
Description
By corrupted I mean branched as in The linear history requirement:
... otherwise they will generate branches and "corrupt" the hypercore.
Currently _onfork
is called by default whenever a later fork is received and there is a TODO comment for converting that to an opt-in
behavior.
What is the plan in the case of a discovered fork, in a Hypercore where the user didn't opt-in for reorgs?
I tried to check what is the current behavior in the case of non-linear history in Hypercore ^9.0.0 but couldn't find anything.
Would the following behavior make sense in the context of your plans?:
Emit an event (e.g corrupted
) to notify the consumer that the Hypercore had a fork, as well as the proof of that fork (two signed roots with the same seq, I guess), so applications can keep those proofs in a block-list of duplicitous cores, while purging the core history
// In replicator.js
async ondata (proof, peer) {
// ...
if (peer.state.fork !== this.core.tree.fork) {
if (!this.allowForks) {
this.core.emit("corrupted", this.core.tree.findDiff(proof));
} else if (peer.state.fork > this.core.tree.fork) {
return this._onfork(proof, peer)
}
return
}
//...
}
// In merkle-tree.js
async findDiff (proof) {
const batch = new ReorgBatch(this)
for (const root of batch.roots) {
const existing = await this.get(root.index, false)
if (existing && b4a.equals(existing.hash, root.hash)) continue
return [existing, root]
}
}
So applications can use that as follows:
const blockList = new Map()
const core = new Hypercore(storage, key)
await core.ready()
core.on('corrupted', ([root1, root2]) => {
blocList.set(core.key, [root1, root2]);
await core.close()
core.storage.destroy() // Need to test this, but I hope this is possible.
})
const swarm = new Hyperswarm()
swarm.on('connection', socket => core.replicate(socket))
swarm.join(core.discoveryKey, { server: true, client: true })