stop using a real account xpub as a test fixture
the key in chain-source-esplora.test.ts was labelled a published test vector and
was not one — it was the owner's live bip84 account xpub, pulled from the
database during an earlier verification and pasted in.
it cannot spend, but it discloses every address that wallet will ever use and
its whole history, permanently. replaced with the bip84 spec's own vector,
derived in the file from the published mnemonic so its provenance can be checked
rather than taken on trust, and pinned by an assertion against the spec's first
address so a future substitution fails loudly.
this does not remove the key from history. that needs a rewrite of 5c38236.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
const lines = (await Bun.file('/tmp/addrs2.tsv').text()).trim().split('\n');
|
||||
let hits = 0, totalBal = 0;
|
||||
for (const line of lines) {
|
||||
const [type, path, addr] = line.split('\t');
|
||||
const proc = Bun.spawn(['curl', '-4', '-s', '--max-time', '12', `https://mempool.space/api/address/${addr}`], { stdout: 'pipe', stderr: 'ignore' });
|
||||
const body = await new Response(proc.stdout).text();
|
||||
await proc.exited;
|
||||
try {
|
||||
const j = JSON.parse(body); const c = j.chain_stats, m = j.mempool_stats;
|
||||
const tx = (c?.tx_count ?? 0) + (m?.tx_count ?? 0);
|
||||
if (tx > 0) {
|
||||
const bal = (c.funded_txo_sum - c.spent_txo_sum) + (m.funded_txo_sum - m.spent_txo_sum);
|
||||
totalBal += bal; hits++;
|
||||
console.log(`${type} ${path} ${addr} txs=${tx} balance=${bal}`);
|
||||
}
|
||||
} catch {}
|
||||
await Bun.sleep(70);
|
||||
}
|
||||
console.log(`\nindices20-59: addressesWithHistory=${hits} unspentTotal=${totalBal} sats`);
|
||||
process.exit(0);
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
import { describe, expect, test } from 'bun:test';
|
||||
import { HDKey } from '@scure/bip32';
|
||||
import { mnemonicToSeedSync } from '@scure/bip39';
|
||||
import * as bitcoin from 'bitcoinjs-lib';
|
||||
import type { EsploraAddress, EsploraChain, EsploraTx, EsploraUtxo } from './chain';
|
||||
import { EsploraChainSource } from './chain-source-esplora';
|
||||
@@ -15,9 +16,17 @@ import { initEcc } from './psbt';
|
||||
|
||||
initEcc();
|
||||
|
||||
// A published BIP32 test vector, so the addresses below are reproducible by anything that speaks BIP84.
|
||||
const ACCOUNT_XPUB =
|
||||
'xpub6DQv646WnF2m1tkyhhwu74tes1MunPX8psKwjmXSmWcPExp7FR9XP2q6m8VcK9uZMQE3rDmPnTnEDTHSxcmad7wzBvLk8PXC7Gnxe5GUpUq';
|
||||
// NEVER PUT A REAL ACCOUNT KEY IN A TEST. An xpub cannot spend, but it reveals every address a wallet
|
||||
// will ever use and its entire history, permanently and irrevocably — and a test file is the easiest
|
||||
// place in a repo for one to hide, because it looks like a fixture. This one is derived here, in the
|
||||
// open, from the BIP84 specification's own published mnemonic, so its provenance is checkable rather
|
||||
// than asserted. If you need a different fixture, derive it the same way; do not paste one in.
|
||||
const PUBLIC_TEST_MNEMONIC =
|
||||
'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';
|
||||
|
||||
const ACCOUNT_XPUB = HDKey.fromMasterSeed(mnemonicToSeedSync(PUBLIC_TEST_MNEMONIC)).derive(
|
||||
"m/84'/0'/0'",
|
||||
).publicExtendedKey;
|
||||
|
||||
/** Derive the same p2wpkh address the backend will, independently of the backend. */
|
||||
function addressAt(chain: 0 | 1, index: number): string {
|
||||
@@ -141,6 +150,12 @@ function backendFor(world: Map<string, Funding>) {
|
||||
}
|
||||
|
||||
describe('EsploraChainSource through OnchainBackend', () => {
|
||||
test('the fixture key really is the published BIP84 vector, not somebody’s wallet', () => {
|
||||
// The spec's own first receive address. If this fails, the mnemonic above is not what it claims and
|
||||
// whatever replaced it must be treated as live key material until proven otherwise.
|
||||
expect(addressAt(0, 0)).toBe('bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu');
|
||||
});
|
||||
|
||||
test('an empty wallet costs one gap-limit window per chain and reports zero', async () => {
|
||||
const { backend, stub } = backendFor(new Map());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user