// PROBE (viability of Mechanism A): can a FRESH store, holding the same writable keypair as an existing
// populated core, BACKFILL that core from a peer (instead of forking it), then continue at the tip?
//
// This is the linchpin for healing a poisoned CREATOR: its genesis writer key is deterministic
// (_gsKeyPair), so a fresh corestore re-opens the SAME writable core EMPTY. If hypercore lets that empty
// writable core replicate the existing history from a peer (the healthy copy tabertron holds) BEFORE any
// local append, the creator can CONTINUE the one history (no fork). If hypercore REFUSES to backfill a
// writable core, Mechanism A is dead and we must rebuild from CAR (Mechanism B).
import '../lib/bare-globals.js'
import test from 'brittle'
import Hypercore from 'hypercore'
import crypto from 'hypercore-crypto'
import b4a from 'b4a'
import fs from 'bare-fs'
const sleep = (ms) => new Promise((r) => setTimeout(r, ms))
const tmp = () => { const d = '/tmp/hpp-backfill-' + Math.floor(Math.random() * 1e9); fs.mkdirSync(d, { recursive: true }); return d }
test('fresh writable core can BACKFILL its own history from a peer before continuing (Mechanism A viability)', { timeout: 60000 }, async (t) => {
const kp = crypto.keyPair() // the deterministic _gsKeyPair analog (shared genesis writer key)
// P = the existing populated genesis-writer core (the healthy copy a peer holds)
const P = new Hypercore(tmp(), { keyPair: kp })
await P.ready()
for (let i = 0; i < 5; i++) await P.append(b4a.from('block-' + i))
t.is(P.length, 5, 'peer P holds the genesis writer at length 5')
// F = a FRESH store opening the SAME writable key, EMPTY (the resync side store's genesis writer)
const F = new Hypercore(tmp(), { keyPair: kp })
await F.ready()
t.is(F.length, 0, 'fresh F opens the same writable key at length 0')
t.ok(F.writable, 'F is writable (holds the keypair)')
// Replicate P <-> F BEFORE F writes anything. Does F backfill to 5?
const s1 = P.replicate(true); const s2 = F.replicate(false)
s1.pipe(s2).pipe(s1)
s1.on('error', () => {}); s2.on('error', () => {})
let backfilled = false
for (let i = 0; i < 30 && !backfilled; i++) {
await F.update().catch(() => {})
if (F.length >= 5) backfilled = true; else await sleep(300)
}
t.ok(backfilled, 'RESULT: F backfilled its own writable core from P to length 5 (Mechanism A is viable)')
if (backfilled) {
let ok = true
for (let i = 0; i < 5; i++) { const b = await F.get(i).catch(() => null); if (!b || b4a.toString(b) !== 'block-' + i) ok = false }
t.ok(ok, 'F reads back the peer\'s 5 blocks correctly (same history, not a fork)')
// continue at the tip
let appended = false
try { await F.append(b4a.from('block-5')); appended = true } catch (e) { t.comment('append after backfill threw: ' + e.message) }
t.ok(appended && F.length === 6, 'F continued the SINGLE history at the tip (length 6) — no fork')
// P must accept F's continuation (no conflict)
let pGot6 = false
for (let i = 0; i < 20 && !pGot6; i++) { await P.update().catch(() => {}); if (P.length >= 6) pGot6 = true; else await sleep(300) }
t.ok(pGot6, 'P received F\'s continuation (length 6) — the two agree, no conflict')
}
await P.close(); await F.close()
})