OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-proto-peer / test / firehose-write.test.js

74 lines · javascript ref:
// Phase B (firehose): offline validation of the signer's #commit emission (buildCommitWrite).
// The lease-holder emits a firehose #commit per sign; the membrane reads it to project to bsky.
// Validated OFFLINE (no relay): the covering-proof path must agree with the Phase-A-proven
// whole-view materialize on the data root + commit, carry a MINIMAL proof (not the whole tree),
// chain continuously (prevData/prev), verify against the did:key, and frame into a #commit whose
// CAR carries the signed commit. firehoseProofBlocks internally asserts the proof INVERTS to the
// old root — so a successful buildCommitWrite is itself proof the frame is relay-invertible.

import '../lib/bare-globals.js'
import test from 'brittle'
import * as dagCbor from '@ipld/dag-cbor'
import { materialize, buildCommitWrite } from 'atproto-room/lib/signer.js'
import { commitFrame } from 'atproto-store/lib/firehose.js'
import { writeCar, readCar, loadCommit } from 'atproto-repo/lib/repo.js'
import { verifyCommit } from 'atproto-repo/lib/commit.js'
import { cidForBytesSync } from 'atproto-repo/lib/cid.js'
import { deriveAtprotoKey } from 'atproto-identity'
import { decodeDidKey } from 'atproto-identity/lib/did-key.js'

const MNEMONIC = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'
const DID = 'did:plc:yu4kgcktm7qtrwo5ofyiaf4c'
const key = deriveAtprotoKey(MNEMONIC)
const { pubkey } = decodeDidKey(key.didKey)
const REV1 = '3mmwu7vak2222'
const REV2 = '3mmwu7vak2322'
const R = (rkey, text) => ({ collection: 'app.bsky.feed.post', rkey, record: { $type: 'app.bsky.feed.post', text, createdAt: '2026-07-01T00:00:00.000Z' } })
const A = R('3mmwu7vak2000', 'a'); const B = R('3mmwu7vak2001', 'b'); const C = R('3mmwu7vak2002', 'c'); const D = R('3mmwu7vak2003', 'd')
const cidOf = (rec) => cidForBytesSync(dagCbor.encode(rec.record)).toString()

test('genesis #commit: agrees with materialize, all-create ops, verifies', (t) => {
  const after = [A, B, C]
  const w = buildCommitWrite([], after, { did: DID, rev: REV1, prev: null, privateKey: key.privateKey })
  const mv = materialize(after, { did: DID, rev: REV1, prev: null, privateKey: key.privateKey })
  t.ok(w.dataCid.equals(mv.dataCid), 'firehose data root == whole-view materialize data root')
  t.ok(w.commitCid.equals(mv.commitCid), 'commit CID matches materialize')
  t.is(w.ops.length, 3, 'three ops')
  t.ok(w.ops.every((o) => o.action === 'create'), 'genesis: all create ops')
  t.ok(verifyCommit(w.signedCommit, pubkey), 'signed commit verifies against the did:key')
})

test('update #commit: minimal covering proof, continuity, verifies', (t) => {
  const before = [A, B, C]
  const g = buildCommitWrite([], before, { did: DID, rev: REV1, prev: null, privateKey: key.privateKey })
  const w = buildCommitWrite(before, [A, B, C, D], { did: DID, rev: REV2, prev: g.commitCid, since: REV1, privateKey: key.privateKey })
  t.ok(w.prevData.equals(g.dataCid), 'continuity: prevData == previous data root')
  t.ok(w.signedCommit.prev && w.signedCommit.prev.equals(g.commitCid), 'commit.prev == previous commit CID')
  t.is(w.ops.length, 1, 'one op (the single added record)')
  t.is(w.ops[0].action, 'create', 'create op')
  const blockCids = new Set(w.newBlocks.map((b) => b.cid.toString()))
  t.ok(blockCids.has(cidOf(D)), 'proof carries the NEW record block')
  t.ok(!blockCids.has(cidOf(A)) && !blockCids.has(cidOf(B)) && !blockCids.has(cidOf(C)), 'minimal: proof omits the unchanged record blocks')
  t.ok(verifyCommit(w.signedCommit, pubkey), 'continued commit verifies against the did:key')
})

test('delete #commit: delete op carries prev, proof inverts, verifies', (t) => {
  const before = [A, B, C]
  const g = buildCommitWrite([], before, { did: DID, rev: REV1, prev: null, privateKey: key.privateKey })
  const w = buildCommitWrite(before, [A, C], { did: DID, rev: REV2, prev: g.commitCid, since: REV1, privateKey: key.privateKey })
  t.is(w.ops.length, 1, 'one op')
  t.is(w.ops[0].action, 'delete', 'delete op')
  t.ok(w.ops[0].prev && w.ops[0].prev.toString() === cidOf(B), 'delete op carries prior CID (relay can invert)')
  t.ok(!w.dataCid.equals(g.dataCid), 'data root changed')
  t.ok(verifyCommit(w.signedCommit, pubkey), 'commit verifies')
})

test('commitFrame emits a #commit frame whose CAR carries the signed commit', async (t) => {
  const w = buildCommitWrite([], [A, B, C], { did: DID, rev: REV1, prev: null, privateKey: key.privateKey })
  const frameBytes = await commitFrame(w, { seq: 1, time: '2026-07-04T00:00:00.000Z' })
  t.ok(frameBytes instanceof Uint8Array && frameBytes.length > 0, 'commitFrame produced a framed message')
  const car = await readCar(await writeCar(w.commitCid, [w.commitBlock, ...w.newBlocks]))
  const commit = loadCommit(car)
  t.ok(commit.cid.equals(w.commitCid) && commit.value.did === DID && commit.value.data.equals(w.dataCid), 'frame blocks form a valid commit CAR (did + data root)')
})