Skip to content
This repository was archived by the owner on Dec 28, 2022. It is now read-only.
This repository was archived by the owner on Dec 28, 2022. It is now read-only.

Emit an event on corrupted hypercores #76

@Nuhvi

Description

@Nuhvi

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 })

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions