OverviewFilesCommitsIssuesDocsReleasesPeers

favela-peer / probe-optimistic.mjs

69 lines · javascript ref:
// Does an optimistic block from a NON-WRITER reach the other peer at all?
// If it does not, claims from strangers have never crossed a wire — which is most of the design.
import Corestore from 'corestore'
import b4a from 'b4a'
import fs from '#node:fs'
import os from '#node:os'
import { join } from '#node:path'
import { Namespace } from './lib/namespace.js'
import { identity } from './test/helpers.js'

const tmp = () => fs.mkdtempSync(join(os.tmpdir(), 'probe-opt-'))
const feed = (c) => String(c).repeat(64).slice(0, 64)

const idA = await identity(); const devA = await idA.device()
const idB = await identity(); const devB = await idB.device()

const one = new Namespace(new Corestore(tmp()).namespace('names'), null)
await one.ready()
await one.found(devA)
await one.update()

const two = new Namespace(new Corestore(tmp()).namespace('names'), one.key)
await two.ready()

const s1 = one.base.replicate(true); const s2 = two.base.replicate(false)
s1.pipe(s2).pipe(s1)

const until = async (fn, ms = 8000) => {
  const end = Date.now() + ms
  while (Date.now() < end) { const v = await fn(); if (v) return v; await new Promise(r => setTimeout(r, 50)) }
  return null
}

console.log('two sees admins:', await until(async () => { await two.update(); const a = await two.admins(); return a.length ? a : null }))

// B claims a name as a total stranger — the open-namespace path
await two.claim('bob', feed('b'), devB)
await two.update()
console.log('two resolves own claim:', !!(await two.resolve('bob0')))

const seen = await until(async () => { await one.update(); return await one.resolve('bob0') })
console.log('ONE sees the stranger claim:', !!seen)

// ── now the admin sequence, step by step ──
const twoWriter = b4a.toString(two.base.local.key, 'hex')
const mw = async (n, w) => { const i = await n.base.system.get(b4a.from(w, 'hex')); return i ? i.maxWeight : null }

await one.grantAdmin(idB.rootHex, devA)
await one.update()
console.log('one admins after grant:', (await one.admins()).length)
console.log('two sees grant:', await until(async () => { await two.update(); return (await two.admins()).length === 2 || null }))

await two.admit(devB)
console.log('two writable:', await until(async () => { await two.update(); return two.base.writable || null }))
console.log('two sees own maxWeight:', await mw(two, twoWriter))
console.log('two writers():', JSON.stringify(await two.writers()))

const onSaw = await until(async () => { await one.update(); const w = await one.writers(); return w.length ? w : null })
console.log('ONE writers():', JSON.stringify(onSaw))
console.log('ONE maxWeight for two:', await mw(one, twoWriter))

// ── the inverse: the FOUNDER carries the admit (its block has weight 2) ──
await one.admitWriter(twoWriter, devA)
await one.update()
console.log('after FOUNDER-carried admit -> ONE maxWeight for two:', await mw(one, twoWriter))
console.log('  two sees:', await until(async () => { await two.update(); const v = await mw(two, twoWriter); return v ? v : null }))
console.log('  two.isIndexer:', two.base.isIndexer, ' writable:', two.base.writable)
await one.close(); await two.close()