OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-proto-peer commits / 0df59f2

scripts: isolate the @core/auth encoding drop behind the frozen-flag bug
hypercore-frozen-repro.mjs proves the user-visible behaviour (freeze lost across reopen, same fork re-detected). This adds the one-step mechanism underneath it: encode -> decode a @core/auth record carrying frozen:true and show the field is gone, with the five surviving fields printed. No hypercore, no fork, no replication, no storage — a maintainer can run it in seconds against any checkout, which is what an upstream report needs as its opening exhibit. node scripts/hypercore-frozen-encoding.mjs "$PWD/node_modules" Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
0df59f21e40b467fb2a2e62a7121bfeb4743c030
by plankatron <fleeky@gmail.com> · 2026-08-11T16:48:06.000Z

Changed files (1) +66 -0

scripts/hypercore-frozen-encoding.mjs +66 -0
……@@ -0,0 +1,66 @@
1// REPRO part 1 — the mechanism, in isolation. No network, no fork, no hypercore.
2//
3// hypercore/lib/core.js (conflict detection) persists the fork flag like this:
4//
5// this.header.frozen = true
6// tx.setAuth({ key, discoveryKey, manifest, keyPair, frozen: true })
7// await this.state.flush()
8//
9// hypercore-storage/lib/tx.js:31 encodes that object through
10// const CORE_AUTH = schema.getEncoding('@core/auth')
11// and @core/auth declares exactly five fields:
12// key, discoveryKey, manifest, keyPair, encryptionKey
13//
14// So `frozen` is not part of the struct and hyperschema drops it. The write
15// "succeeds", flushes, and the flag is gone. This script proves that with a
16// straight encode -> decode round-trip.
17//
18// Run: node 1-encoding.mjs /path/to/node_modules
19
20import { createRequire } from 'node:module'
21import path from 'node:path'
22
23const modules = process.argv[2]
24if (!modules) {
25 console.error('usage: node 1-encoding.mjs <path-to-node_modules>')
26 process.exit(2)
27}
28
29const require = createRequire(path.join(modules, 'x.js'))
30const storagePkg = require('hypercore-storage/package.json')
31// same path tx.js itself uses (hypercore-storage/lib/tx.js:5)
32const schema = require('hypercore-storage/encoding/spec/hyperschema')
33
34console.log('hypercore-storage', storagePkg.version)
35
36const CORE_AUTH = schema.getEncoding('@core/auth')
37
38// A minimal but structurally valid auth record, plus the flag core.js sets.
39const auth = {
40 key: Buffer.alloc(32, 1),
41 discoveryKey: Buffer.alloc(32, 2),
42 manifest: null,
43 keyPair: null,
44 encryptionKey: null,
45 frozen: true
46}
47
48const c = require('compact-encoding')
49const buf = c.encode(CORE_AUTH, auth)
50const out = c.decode(CORE_AUTH, buf)
51
52console.log('\nwrote frozen =', auth.frozen)
53console.log('read frozen =', out.frozen)
54console.log('fields round-tripped:', Object.keys(out).join(', '))
55
56if (out.frozen === true) {
57 console.log('\nPASS — frozen survives the encoding (bug is fixed)')
58 process.exit(0)
59}
60
61console.log('\nFAIL — frozen was silently dropped by @core/auth.')
62console.log(' The write in hypercore/lib/core.js can never persist, so on')
63console.log(' reopen getCoreInfo() spreads an authInfo with no `frozen`,')
64console.log(' header.frozen is undefined, and Replicator.Peer.isActive()')
65console.log(' (the ONLY reader of the flag in hypercore) never sees it.')
66process.exit(1)