This commit is contained in:
2026-10-19 21:47:38 -04:00
parent f8eeae826f
commit b1d2b5c10e
17 changed files with 549 additions and 92 deletions
+10 -7
View File
@@ -3,8 +3,8 @@ import { request as httpsRequest } from 'node:https';
import dns from 'node:dns/promises';
import { BlockList, isIP } from 'node:net';
import { z } from 'zod';
import { NETWORK, type TestnetBlock, type NftTransfer } from '../../shared/testnet.ts';
import { CHAIN_ID, blockSchema, transferId, transferSchema } from './consensus.ts';
import { NETWORK, type TestnetBlock, type TestnetTransaction } from '../../shared/testnet.ts';
import { CHAIN_ID, blockSchema, transactionId, transactionSchema } from './consensus.ts';
import type { Ledger } from './ledger.ts';
const MAX_BODY = 2 * 1024 * 1024;
@@ -27,7 +27,7 @@ const remoteStatus = z.object({ network: z.literal(NETWORK), chainId: z.literal(
size: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER), tip: z.string().regex(/^[a-f0-9]{64}$/).optional() }).strict();
const pageSchema = z.object({ blocks: z.array(blockSchema).max(32),
next: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER).nullable() }).strict();
const poolSchema = z.object({ transactions: z.array(transferSchema).max(256) }).strict();
const poolSchema = z.object({ transactions: z.array(transactionSchema).max(256) }).strict();
type Peer = { url: string; connected: boolean; error?: string; offset: number; busy: boolean };
/** Outbound-only fixed allowlist. HTTP routes are deliberately left to the caller.
@@ -90,10 +90,13 @@ export class PeerNetwork {
if (!known) throw new Error('Cannot broadcast an unaccepted block');
await this.broadcast('/p2p/block', known);
}
async broadcastTransfer(tx: NftTransfer): Promise<void> {
const id = transferId(transferSchema.parse(tx));
async broadcastTransfer(tx: TestnetTransaction): Promise<void> {
return this.broadcastTransaction(tx);
}
async broadcastTransaction(tx: TestnetTransaction): Promise<void> {
const id = transactionId(transactionSchema.parse(tx));
const snapshot = this.ledger.snapshot();
const known = [...snapshot.pendingTransfers, ...snapshot.transfers].find(t => transferId(t) === id);
const known = [...snapshot.pendingTransfers, ...snapshot.transfers].find(t => transactionId(t) === id);
if (!known) throw new Error('Cannot broadcast an unaccepted transfer');
await this.broadcast('/p2p/transaction', known);
}
@@ -134,7 +137,7 @@ export class PeerNetwork {
for (const tx of pool.transactions) {
if (this.closed) throw new Error('Peer network closed');
// Valid remote transactions may be immature/conflicting on our current tip.
try { await this.ledger.submitTransfer(tx); } catch { /* Independently reject; do not relay. */ }
try { await this.ledger.submitTransaction(tx); } catch { /* Independently reject; do not relay. */ }
}
}