hypercore-protocol / hypercore-next

Hypercore 10 is an append only log with multi-writer primitives built in.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Unable to use autobase.createReadStream({ live:true }) with encrypted hypercores

hexadecible opened this issue · comments

I get the following error when trying to use autobase.createReadStream({ live: true }) on an encrypted hypercore.

TypeError: Cannot read property 'batch' of null
    at Autobase._getInputNode (/Users/gh/Documents/tests/autobase/node_modules/autobase/index.js:88:14)
    at processTicksAndRejections (node:internal/process/task_queues:94:5)
    at async updateAll (/Users/gh/Documents/tests/autobase/node_modules/autobase/index.js:323:29)
    at async _read (/Users/gh/Documents/tests/autobase/node_modules/autobase/index.js:261:11)
Emitted 'error' event on Readable instance at:
    at ReadableState.afterDestroy (/Users/gh/Documents/tests/autobase/node_modules/streamx/index.js:442:19)
    at Readable._destroy (/Users/gh/Documents/tests/autobase/node_modules/streamx/index.js:535:5)
    at ReadableState.updateNonPrimary (/Users/gh/Documents/tests/autobase/node_modules/streamx/index.js:349:16)
    at ReadableState.update (/Users/gh/Documents/tests/autobase/node_modules/streamx/index.js:333:69)
    at ReadableState.updateReadNT (/Users/gh/Documents/tests/autobase/node_modules/streamx/index.js:477:8)
    at processTicksAndRejections (node:internal/process/task_queues:76:11)

Here is a full example to generate the error:

const Hyperbee = require('hyperbee')
const Autobase = require("autobase")
const Hypercore = require("hypercore")
const Hyperswarm = require('hyperswarm')
const ram = require("random-access-memory")

///////////////////////////////////////////////////////
const encryptionKey = Buffer.alloc(32, 'hello world')

const user1 = await create(encryptionKey);
await user1.put('test1', { hello: 'test1' })
await user1.put('test2', { hello: 'test2' })
await user1.put('test3', { hello: 'test3' })

const user2 = await create(encryptionKey);

const peer = new Hypercore(ram, user1.writer.key, { encryptionKey })
await joinSwarm(peer, { server: false, client: true })

const stream = user2.base.createReadStream({ live: true })

stream.on('data', data => {
  console.log('DATA', data)
})

await user2.base.addInput(peer)
///////////////////////////////////////////////////////


async function create(encryptionKey) {
  const writer = new Hypercore(ram, null, { encryptionKey })

  await joinSwarm(writer, { server: true, client: false })

  const autobaseIndex = new Hypercore(ram, null, { encryptionKey })
  const base = new Autobase([writer], { input: writer, indexes: autobaseIndex })
  const index = base.createRebasedIndex({
    unwrap: true,
    apply: _apply.bind(this)
  })

  const bee = new Hyperbee(index, {
    keyEncoding: 'utf-8',
    valueEncoding: 'json',
    extension: false
  })

  const put = async (key, value, opts) => {
    const op = Buffer.from(JSON.stringify({ type: 'put', key, value }))
    return await base.append(op, opts)
  }

  async function _apply(batch) {
    const b = bee.batch({ update: false })
    for (const node of batch) {
      const op = JSON.parse(node.value.toString())
      if (op.type === 'put') await b.put(op.key, op.value)
    }
    await b.flush()
  }

  return {
    writer,
    bee,
    base,
    put
  }
}

async function joinSwarm(core, { server, client }) {
  const swarm = new Hyperswarm()

  await core.ready()

  swarm.on('connection', async (socket, info) => {
    socket.pipe(core.replicate(info.client)).pipe(socket)
  })

  const topic = core.discoveryKey;
  const discovery = swarm.join(topic, { server, client })

  if (server) return await discovery.flushed()

  return await swarm.flush()
}

Note that when the encryptionKey option is commented out createReadStream is error-free.

Thanks! Fixed in alpha 9 :)