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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions