OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-proto-peer / test / reanchor-unsigned-writes.test.mjs

57 lines · javascript ref:
// RE-ANCHOR WITH UNSIGNED LOCAL WRITES — the forward-only gate must not swallow them.
//
// When sign() finds a network head newer than its own, it re-anchors (head = the net frame). It used to
// set the diff baseline to the device's CURRENT VIEW at that moment. If the device already held a local
// write the net head does not have, that write went into the signed data root with NO op in any frame:
// the before/after diff was empty, so no #commit frame was appended at all, yet head advanced to the
// unpublished commit. An ops-only consumer (the reference bsky AppView applies ops and nothing else)
// never learns that record, and the next frame's prevData points at a root no frame ever published.
//
// The baseline after a re-anchor must be the record set the NET HEAD commits to (the firehose replay),
// so the local write is diffed as an op.

import '../lib/bare-globals.js'
import test from 'brittle'
import b4a from 'b4a'
import { SwarmDevice } from '../lib/swarm-device.js'

const DID = 'did:plc:reanchorunsigned'
const KEY = (() => { const k = b4a.alloc(32); k[31] = 7; return k })()
const post = (text) => ({ $type: 'app.bsky.feed.post', text, createdAt: '2026-10-13T00:00:00.000Z' })

class MemKV {
  constructor (m) { this.m = new Map(m || []) }
  async set (k, v) { this.m.set(k, v) }
  async get (k) { return this.m.has(k) ? this.m.get(k) : null }
  async getNow (k) { return this.get(k) }
  async del (k) { this.m.delete(k) }
  async list (prefix = '') { const o = {}; for (const [k, v] of this.m) if (k.startsWith(prefix)) o[k] = v; return o }
  async listNow (prefix = '') { return this.list(prefix) }
}

test('re-anchor: a local write the net head lacks is published as an op, not absorbed', async (t) => {
  const sb = new MemKV()
  const A = new SwarmDevice(sb, { did: DID, privateKey: KEY, self: 'A', firehose: true })
  const B = new SwarmDevice(sb, { did: DID, privateKey: KEY, self: 'B', firehose: true })

  await A.putRecord('app.bsky.feed.post', 'r1', post('one'))
  const h1 = await A.sign({ force: true })
  t.ok(await B.sign() === null && B.head && B.head.rev === h1.rev, 'B anchored at the first commit')

  // A moves the chain on; B is now behind it.
  await A.putRecord('app.bsky.feed.post', 'r2', post('two'))
  const h2 = await A.sign()
  t.ok(h2 && h2.rev > h1.rev, 'A signed a newer head')

  // B writes locally BEFORE its next sign, so that sign both re-anchors and has a new record.
  await B.putRecord('app.bsky.feed.post', 'r3', post('three'))
  const h3 = await B.sign()
  t.ok(h3 && h3.rev > h2.rev, 'B signed forward from the net head')

  const frames = Object.values(await sb.listNow('__commit__/'))
  const published = frames.flatMap((f) => (f.ops || []).map((o) => o.path))
  t.ok(published.includes('app.bsky.feed.post/r3'), 'r3 reached the firehose as an op')
  const head = frames.find((f) => f.commitCid === h3.commitCid.toString())
  t.ok(head, 'the commit B signed was appended as a frame (head never points at an unpublished commit)')
})