miniledger 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/miniledger.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/index.ts","../../src/cli/commands/init.ts","../../src/identity/keypair.ts","../../src/utils.ts","../../src/identity/signer.ts","../../src/identity/keystore.ts","../../src/constants.ts","../../src/config/defaults.ts","../../src/config/schema.ts","../../src/config/loader.ts","../../src/errors.ts","../../src/storage/database.ts","../../src/storage/migrations.ts","../../src/core/serialization.ts","../../src/storage/queries.ts","../../src/storage/block-store.ts","../../src/core/hash.ts","../../src/core/merkle.ts","../../src/core/block.ts","../../src/core/chain.ts","../../src/cli/commands/start.ts","../../src/node.ts","../../src/types.ts","../../src/core/transaction.ts","../../src/storage/state-store.ts","../../src/storage/tx-store.ts","../../src/network/peer-manager.ts","../../src/network/ws-server.ts","../../src/network/protocol.ts","../../src/network/peer.ts","../../src/network/ws-client.ts","../../src/network/router.ts","../../src/network/sync.ts","../../src/consensus/raft/raft-node.ts","../../src/consensus/raft/raft-timer.ts","../../src/consensus/raft/raft-log.ts","../../src/contracts/context.ts","../../src/contracts/runtime.ts","../../src/contracts/registry.ts","../../src/contracts/builtins.ts","../../src/governance/proposal.ts","../../src/governance/voting.ts","../../src/governance/governor.ts","../../src/api/server.ts","../../src/api/middleware/logging.ts","../../src/api/routes/health.ts","../../src/api/routes/blocks.ts","../../src/api/routes/transactions.ts","../../src/api/routes/state.ts","../../src/api/routes/identity.ts","../../src/api/routes/network.ts","../../src/api/routes/governance.ts","../../src/cli/commands/join.ts","../../src/cli/commands/status.ts","../../src/cli/commands/tx.ts","../../src/cli/commands/query.ts","../../src/cli/commands/keys.ts","../../src/cli/commands/peers.ts","../../src/cli/commands/demo.ts","../../src/cli/commands/demo-utils.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { registerInit } from \"./commands/init.js\";\nimport { registerStart } from \"./commands/start.js\";\nimport { registerJoin } from \"./commands/join.js\";\nimport { registerStatus } from \"./commands/status.js\";\nimport { registerTx } from \"./commands/tx.js\";\nimport { registerQuery } from \"./commands/query.js\";\nimport { registerKeys } from \"./commands/keys.js\";\nimport { registerPeers } from \"./commands/peers.js\";\nimport { registerDemo } from \"./commands/demo.js\";\n\nexport function createCLI(): Command {\n const program = new Command();\n\n program\n .name(\"miniledger\")\n .description(\"The SQLite of private blockchains\")\n .version(\"0.1.0\");\n\n registerInit(program);\n registerStart(program);\n registerJoin(program);\n registerStatus(program);\n registerTx(program);\n registerQuery(program);\n registerKeys(program);\n registerPeers(program);\n registerDemo(program);\n\n return program;\n}\n\n// Direct execution\nconst program = createCLI();\nprogram.parse();\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { Command } from \"commander\";\nimport { generateKeyPair, encryptKeystore, serializeKeystore } from \"../../identity/index.js\";\nimport { DEFAULT_CONFIG } from \"../../config/index.js\";\nimport { GENESIS_PROPOSER } from \"../../constants.js\";\nimport { MiniLedgerDB } from \"../../storage/database.js\";\nimport { BlockStore } from \"../../storage/block-store.js\";\nimport { Chain } from \"../../core/chain.js\";\n\nexport function registerInit(program: Command): void {\n program\n .command(\"init\")\n .description(\"Initialize a new MiniLedger node\")\n .option(\"-d, --data-dir <path>\", \"Data directory\", DEFAULT_CONFIG.dataDir)\n .option(\"-n, --name <name>\", \"Node name\", DEFAULT_CONFIG.node.name)\n .option(\"-o, --org <orgId>\", \"Organization ID\", DEFAULT_CONFIG.node.orgId)\n .action((opts) => {\n const dataDir = opts.dataDir as string;\n\n if (fs.existsSync(path.join(dataDir, \"ledger.db\"))) {\n console.log(`Node already initialized at ${dataDir}`);\n return;\n }\n\n // Create data directory\n fs.mkdirSync(dataDir, { recursive: true });\n\n // Generate keypair\n const keyPair = generateKeyPair();\n const ks = encryptKeystore(keyPair, \"\", opts.org, opts.name);\n fs.writeFileSync(path.join(dataDir, \"keystore.json\"), serializeKeystore(ks));\n\n // Save config\n const config = {\n ...DEFAULT_CONFIG,\n dataDir,\n node: {\n ...DEFAULT_CONFIG.node,\n name: opts.name,\n orgId: opts.org,\n },\n };\n fs.writeFileSync(path.join(dataDir, \"miniledger.json\"), JSON.stringify(config, null, 2));\n\n // Create database and genesis block\n const db = new MiniLedgerDB(path.join(dataDir, \"ledger.db\"));\n db.migrate();\n\n const blockStore = new BlockStore(db.raw());\n const chain = new Chain();\n const genesis = chain.createGenesis(GENESIS_PROPOSER);\n blockStore.insert(genesis);\n db.close();\n\n console.log(`MiniLedger initialized at ${dataDir}`);\n console.log(` Node ID: ${keyPair.publicKey.substring(0, 16)}`);\n console.log(` Public Key: ${keyPair.publicKey}`);\n console.log(` Org: ${opts.org}`);\n console.log(` Genesis: ${genesis.hash.substring(0, 16)}...`);\n console.log(`\\nStart with: miniledger start -d ${dataDir}`);\n });\n}\n","import * as ed from \"@noble/ed25519\";\nimport { sha512 } from \"@noble/hashes/sha512\";\nimport { toHex, fromHex } from \"../utils.js\";\n\n// ed25519 requires sha512\ned.etc.sha512Sync = (...m: Uint8Array[]) => {\n const h = sha512.create();\n for (const msg of m) h.update(msg);\n return h.digest();\n};\n\nexport interface KeyPair {\n publicKey: string; // hex\n privateKey: string; // hex\n}\n\n/** Generate a new Ed25519 keypair. */\nexport function generateKeyPair(): KeyPair {\n const privateKey = ed.utils.randomPrivateKey();\n const publicKey = ed.getPublicKey(privateKey);\n return {\n publicKey: toHex(publicKey),\n privateKey: toHex(privateKey),\n };\n}\n\n/** Derive public key from a private key. */\nexport function getPublicKey(privateKeyHex: string): string {\n return toHex(ed.getPublicKey(fromHex(privateKeyHex)));\n}\n\n/** Export keypair to JSON-serializable format. */\nexport function exportKeyPair(kp: KeyPair): { publicKey: string; privateKey: string } {\n return { publicKey: kp.publicKey, privateKey: kp.privateKey };\n}\n\n/** Import keypair from hex strings. */\nexport function importKeyPair(publicKey: string, privateKey: string): KeyPair {\n return { publicKey, privateKey };\n}\n","export function toHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\nexport function fromHex(hex: string): Uint8Array {\n const bytes = new Uint8Array(hex.length / 2);\n for (let i = 0; i < hex.length; i += 2) {\n bytes[i / 2] = Number.parseInt(hex.substring(i, i + 2), 16);\n }\n return bytes;\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport function nowMs(): number {\n return Date.now();\n}\n\nexport function shortId(publicKey: string): string {\n return publicKey.substring(0, 16);\n}\n\nexport function isValidHex(str: string, expectedLength?: number): boolean {\n if (expectedLength !== undefined && str.length !== expectedLength) {\n return false;\n }\n return /^[0-9a-f]+$/.test(str);\n}\n","import * as ed from \"@noble/ed25519\";\nimport { fromHex, toHex } from \"../utils.js\";\n\n/** Sign a message (hex string or raw string) with a private key. Returns hex signature. */\nexport function sign(message: string, privateKeyHex: string): string {\n const msgBytes = new TextEncoder().encode(message);\n const sig = ed.sign(msgBytes, fromHex(privateKeyHex));\n return toHex(sig);\n}\n\n/** Verify a signature against a message and public key. */\nexport function verify(message: string, signatureHex: string, publicKeyHex: string): boolean {\n try {\n const msgBytes = new TextEncoder().encode(message);\n return ed.verify(fromHex(signatureHex), msgBytes, fromHex(publicKeyHex));\n } catch {\n return false;\n }\n}\n","import { sha256 } from \"@noble/hashes/sha256\";\nimport { toHex, fromHex } from \"../utils.js\";\nimport type { KeyPair } from \"./keypair.js\";\n\ninterface KeystoreFile {\n version: 1;\n publicKey: string;\n encryptedPrivateKey: string;\n salt: string;\n orgId: string;\n name: string;\n}\n\n/**\n * Simple keystore: XOR the private key with a password-derived key.\n * This is a minimal implementation for M1. A production version would use\n * AES-256-GCM with scrypt key derivation.\n */\nfunction deriveKey(password: string, salt: Uint8Array): Uint8Array {\n // Simple PBKDF: hash(password + salt) repeated\n let key = sha256(new TextEncoder().encode(password + toHex(salt)));\n for (let i = 0; i < 10000; i++) {\n key = sha256(key);\n }\n return key;\n}\n\nexport function encryptKeystore(\n keyPair: KeyPair,\n password: string,\n orgId: string,\n name: string,\n): KeystoreFile {\n const salt = crypto.getRandomValues(new Uint8Array(16));\n const derived = deriveKey(password, salt);\n const privBytes = fromHex(keyPair.privateKey);\n const encrypted = new Uint8Array(privBytes.length);\n for (let i = 0; i < privBytes.length; i++) {\n encrypted[i] = privBytes[i]! ^ derived[i % derived.length]!;\n }\n\n return {\n version: 1,\n publicKey: keyPair.publicKey,\n encryptedPrivateKey: toHex(encrypted),\n salt: toHex(salt),\n orgId,\n name,\n };\n}\n\nexport function decryptKeystore(keystore: KeystoreFile, password: string): KeyPair {\n const salt = fromHex(keystore.salt);\n const derived = deriveKey(password, salt);\n const encrypted = fromHex(keystore.encryptedPrivateKey);\n const decrypted = new Uint8Array(encrypted.length);\n for (let i = 0; i < encrypted.length; i++) {\n decrypted[i] = encrypted[i]! ^ derived[i % derived.length]!;\n }\n\n return {\n publicKey: keystore.publicKey,\n privateKey: toHex(decrypted),\n };\n}\n\nexport function serializeKeystore(keystore: KeystoreFile): string {\n return JSON.stringify(keystore, null, 2);\n}\n\nexport function deserializeKeystore(data: string): KeystoreFile {\n return JSON.parse(data) as KeystoreFile;\n}\n","export const PROTOCOL_VERSION = 1;\nexport const GENESIS_PREVIOUS_HASH = \"0\".repeat(64);\nexport const GENESIS_TIMESTAMP = 0;\n\nexport const DEFAULT_P2P_PORT = 4440;\nexport const DEFAULT_API_PORT = 4441;\nexport const DEFAULT_DATA_DIR = \"./miniledger-data\";\n\nexport const MAX_TX_PER_BLOCK = 500;\nexport const BLOCK_TIME_MS = 1000;\nexport const MAX_TX_SIZE_BYTES = 1024 * 256; // 256KB\nexport const MAX_BLOCK_SIZE_BYTES = 1024 * 1024 * 10; // 10MB\n\nexport const EMPTY_MERKLE_ROOT = \"0\".repeat(64);\n\n// Fixed genesis proposer key so all nodes produce identical genesis blocks\nexport const GENESIS_PROPOSER = \"0\".repeat(64);\n\nexport const NONCE_TABLE = \"_miniledger_nonces\";\nexport const META_TABLE = \"_miniledger_meta\";\n","import {\n DEFAULT_API_PORT,\n DEFAULT_DATA_DIR,\n DEFAULT_P2P_PORT,\n BLOCK_TIME_MS,\n MAX_TX_PER_BLOCK,\n} from \"../constants.js\";\n\nexport interface MiniLedgerConfig {\n dataDir: string;\n node: {\n name: string;\n orgId: string;\n role: \"validator\" | \"observer\";\n };\n network: {\n listenAddress: string;\n p2pPort: number;\n apiPort: number;\n peers: string[];\n maxPeers: number;\n };\n consensus: {\n algorithm: \"raft\" | \"solo\";\n blockTimeMs: number;\n maxTxPerBlock: number;\n };\n api: {\n enabled: boolean;\n cors: boolean;\n };\n logging: {\n level: \"debug\" | \"info\" | \"warn\" | \"error\";\n };\n}\n\nexport const DEFAULT_CONFIG: MiniLedgerConfig = {\n dataDir: DEFAULT_DATA_DIR,\n node: {\n name: \"node-1\",\n orgId: \"org-1\",\n role: \"validator\",\n },\n network: {\n listenAddress: \"0.0.0.0\",\n p2pPort: DEFAULT_P2P_PORT,\n apiPort: DEFAULT_API_PORT,\n peers: [],\n maxPeers: 50,\n },\n consensus: {\n algorithm: \"solo\",\n blockTimeMs: BLOCK_TIME_MS,\n maxTxPerBlock: MAX_TX_PER_BLOCK,\n },\n api: {\n enabled: true,\n cors: true,\n },\n logging: {\n level: \"info\",\n },\n};\n","import { z } from \"zod\";\n\nexport const configSchema = z.object({\n dataDir: z.string(),\n node: z.object({\n name: z.string(),\n orgId: z.string(),\n role: z.enum([\"validator\", \"observer\"]),\n }),\n network: z.object({\n listenAddress: z.string(),\n p2pPort: z.number().int().min(1).max(65535),\n apiPort: z.number().int().min(1).max(65535),\n peers: z.array(z.string()),\n maxPeers: z.number().int().min(1),\n }),\n consensus: z.object({\n algorithm: z.enum([\"raft\", \"solo\"]),\n blockTimeMs: z.number().int().min(100),\n maxTxPerBlock: z.number().int().min(1),\n }),\n api: z.object({\n enabled: z.boolean(),\n cors: z.boolean(),\n }),\n logging: z.object({\n level: z.enum([\"debug\", \"info\", \"warn\", \"error\"]),\n }),\n});\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { ConfigError } from \"../errors.js\";\nimport { type MiniLedgerConfig, DEFAULT_CONFIG } from \"./defaults.js\";\nimport { configSchema } from \"./schema.js\";\n\n/** Deep merge two objects (b overrides a). */\nfunction deepMerge<T extends Record<string, unknown>>(a: T, b: Partial<T>): T {\n const result = { ...a };\n for (const key of Object.keys(b) as (keyof T)[]) {\n const val = b[key];\n if (val !== undefined && typeof val === \"object\" && val !== null && !Array.isArray(val)) {\n result[key] = deepMerge(\n (a[key] ?? {}) as Record<string, unknown>,\n val as Record<string, unknown>,\n ) as T[keyof T];\n } else if (val !== undefined) {\n result[key] = val as T[keyof T];\n }\n }\n return result;\n}\n\n/** Load config from file, merging with defaults. */\nexport function loadConfig(overrides: Partial<MiniLedgerConfig> = {}): MiniLedgerConfig {\n // Start with defaults\n let config = { ...DEFAULT_CONFIG };\n\n // Check for config file in data dir\n const dataDir = overrides.dataDir ?? config.dataDir;\n const configPath = path.join(dataDir, \"miniledger.json\");\n\n if (fs.existsSync(configPath)) {\n try {\n const fileContent = JSON.parse(fs.readFileSync(configPath, \"utf-8\"));\n config = deepMerge(config, fileContent);\n } catch (err) {\n throw new ConfigError(`Failed to parse config file ${configPath}: ${err}`);\n }\n }\n\n // Apply overrides\n config = deepMerge(config, overrides as Partial<typeof config>);\n\n // Validate\n const result = configSchema.safeParse(config);\n if (!result.success) {\n throw new ConfigError(`Invalid configuration: ${result.error.message}`);\n }\n\n return result.data as MiniLedgerConfig;\n}\n\n/** Save config to the data directory. */\nexport function saveConfig(config: MiniLedgerConfig): void {\n const configPath = path.join(config.dataDir, \"miniledger.json\");\n fs.mkdirSync(config.dataDir, { recursive: true });\n fs.writeFileSync(configPath, JSON.stringify(config, null, 2));\n}\n","export class MiniLedgerError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"MiniLedgerError\";\n }\n}\n\nexport class ChainError extends MiniLedgerError {\n constructor(message: string) {\n super(message);\n this.name = \"ChainError\";\n }\n}\n\nexport class ValidationError extends MiniLedgerError {\n constructor(message: string) {\n super(message);\n this.name = \"ValidationError\";\n }\n}\n\nexport class StorageError extends MiniLedgerError {\n constructor(message: string) {\n super(message);\n this.name = \"StorageError\";\n }\n}\n\nexport class ConsensusError extends MiniLedgerError {\n constructor(message: string) {\n super(message);\n this.name = \"ConsensusError\";\n }\n}\n\nexport class NetworkError extends MiniLedgerError {\n constructor(message: string) {\n super(message);\n this.name = \"NetworkError\";\n }\n}\n\nexport class IdentityError extends MiniLedgerError {\n constructor(message: string) {\n super(message);\n this.name = \"IdentityError\";\n }\n}\n\nexport class ConfigError extends MiniLedgerError {\n constructor(message: string) {\n super(message);\n this.name = \"ConfigError\";\n }\n}\n","import Database from \"better-sqlite3\";\nimport { StorageError } from \"../errors.js\";\nimport { MIGRATIONS } from \"./migrations.js\";\n\nexport class MiniLedgerDB {\n private db: Database.Database;\n\n constructor(dbPath: string) {\n try {\n this.db = new Database(dbPath);\n this.db.pragma(\"journal_mode = WAL\");\n this.db.pragma(\"synchronous = NORMAL\");\n this.db.pragma(\"foreign_keys = ON\");\n this.db.pragma(\"busy_timeout = 5000\");\n } catch (err) {\n throw new StorageError(`Failed to open database: ${err}`);\n }\n }\n\n /** Run all pending migrations. */\n migrate(): void {\n // Create migrations tracking table\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS _migrations (\n version INTEGER PRIMARY KEY,\n applied_at INTEGER NOT NULL\n );\n `);\n\n const applied = this.db\n .prepare(\"SELECT version FROM _migrations ORDER BY version\")\n .all() as { version: number }[];\n const appliedVersions = new Set(applied.map((r) => r.version));\n\n for (const migration of MIGRATIONS) {\n if (!appliedVersions.has(migration.version)) {\n this.db.transaction(() => {\n this.db.exec(migration.sql);\n this.db.prepare(\"INSERT INTO _migrations (version, applied_at) VALUES (?, ?)\").run(\n migration.version,\n Date.now(),\n );\n })();\n }\n }\n }\n\n /** Get the underlying better-sqlite3 Database instance. */\n raw(): Database.Database {\n return this.db;\n }\n\n close(): void {\n this.db.close();\n }\n}\n","export const MIGRATIONS: { version: number; sql: string }[] = [\n {\n version: 1,\n sql: `\n CREATE TABLE IF NOT EXISTS blocks (\n height INTEGER PRIMARY KEY,\n hash TEXT UNIQUE NOT NULL,\n prev_hash TEXT NOT NULL,\n timestamp INTEGER NOT NULL,\n merkle_root TEXT NOT NULL,\n state_root TEXT NOT NULL,\n proposer TEXT NOT NULL,\n signature TEXT NOT NULL DEFAULT '',\n raw TEXT NOT NULL\n );\n\n CREATE TABLE IF NOT EXISTS transactions (\n hash TEXT PRIMARY KEY,\n type TEXT NOT NULL,\n sender TEXT NOT NULL,\n nonce INTEGER NOT NULL,\n timestamp INTEGER NOT NULL,\n payload TEXT NOT NULL,\n signature TEXT NOT NULL DEFAULT '',\n block_height INTEGER REFERENCES blocks(height),\n position INTEGER,\n status TEXT NOT NULL DEFAULT 'confirmed'\n );\n\n CREATE TABLE IF NOT EXISTS world_state (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL,\n version INTEGER NOT NULL DEFAULT 1,\n updated_at INTEGER NOT NULL,\n updated_by TEXT NOT NULL,\n block_height INTEGER NOT NULL\n );\n\n CREATE TABLE IF NOT EXISTS peers (\n id TEXT PRIMARY KEY,\n public_key TEXT UNIQUE NOT NULL,\n address TEXT NOT NULL,\n org_id TEXT NOT NULL,\n role TEXT NOT NULL DEFAULT 'validator',\n added_at INTEGER NOT NULL\n );\n\n CREATE TABLE IF NOT EXISTS tx_pool (\n hash TEXT PRIMARY KEY,\n raw TEXT NOT NULL,\n received INTEGER NOT NULL,\n priority INTEGER DEFAULT 0\n );\n\n CREATE TABLE IF NOT EXISTS nonces (\n sender TEXT PRIMARY KEY,\n nonce INTEGER NOT NULL DEFAULT 0\n );\n\n CREATE TABLE IF NOT EXISTS meta (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n );\n\n CREATE INDEX IF NOT EXISTS idx_tx_sender ON transactions(sender);\n CREATE INDEX IF NOT EXISTS idx_tx_block ON transactions(block_height);\n CREATE INDEX IF NOT EXISTS idx_tx_type ON transactions(type);\n CREATE INDEX IF NOT EXISTS idx_state_updated ON world_state(updated_at);\n CREATE INDEX IF NOT EXISTS idx_state_block ON world_state(block_height);\n `,\n },\n];\n","/** Deterministic JSON serialization with sorted keys. */\nexport function canonicalize(obj: unknown): string {\n return JSON.stringify(obj, (_key, value) => {\n if (value !== null && typeof value === \"object\" && !Array.isArray(value)) {\n return Object.keys(value as Record<string, unknown>)\n .sort()\n .reduce(\n (sorted, k) => {\n sorted[k] = (value as Record<string, unknown>)[k];\n return sorted;\n },\n {} as Record<string, unknown>,\n );\n }\n return value;\n });\n}\n","import type Database from \"better-sqlite3\";\n\n/**\n * Cached prepared statement helper.\n * Lazily prepares and caches statements for reuse.\n */\nexport class QueryCache {\n private cache = new Map<string, Database.Statement>();\n\n constructor(private db: Database.Database) {}\n\n prepare(sql: string): Database.Statement {\n let stmt = this.cache.get(sql);\n if (!stmt) {\n stmt = this.db.prepare(sql);\n this.cache.set(sql, stmt);\n }\n return stmt;\n }\n\n clear(): void {\n this.cache.clear();\n }\n}\n","import type Database from \"better-sqlite3\";\nimport type { Block } from \"../types.js\";\nimport { canonicalize } from \"../core/serialization.js\";\nimport { QueryCache } from \"./queries.js\";\n\nexport class BlockStore {\n private q: QueryCache;\n\n constructor(db: Database.Database) {\n this.q = new QueryCache(db);\n }\n\n insert(block: Block): void {\n const raw = canonicalize(block);\n this.q\n .prepare(\n `INSERT INTO blocks (height, hash, prev_hash, timestamp, merkle_root, state_root, proposer, signature, raw)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n block.height,\n block.hash,\n block.previousHash,\n block.timestamp,\n block.merkleRoot,\n block.stateRoot,\n block.proposer,\n block.signature,\n raw,\n );\n\n // Insert transactions\n const txStmt = this.q.prepare(\n `INSERT OR IGNORE INTO transactions (hash, type, sender, nonce, timestamp, payload, signature, block_height, position, status)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 'confirmed')`,\n );\n for (let i = 0; i < block.transactions.length; i++) {\n const tx = block.transactions[i]!;\n txStmt.run(\n tx.hash,\n tx.type,\n tx.sender,\n tx.nonce,\n tx.timestamp,\n canonicalize(tx.payload),\n tx.signature,\n block.height,\n i,\n );\n }\n }\n\n getByHeight(height: number): Block | null {\n const row = this.q.prepare(\"SELECT raw FROM blocks WHERE height = ?\").get(height) as\n | { raw: string }\n | undefined;\n return row ? (JSON.parse(row.raw) as Block) : null;\n }\n\n getByHash(hash: string): Block | null {\n const row = this.q.prepare(\"SELECT raw FROM blocks WHERE hash = ?\").get(hash) as\n | { raw: string }\n | undefined;\n return row ? (JSON.parse(row.raw) as Block) : null;\n }\n\n getLatest(): Block | null {\n const row = this.q\n .prepare(\"SELECT raw FROM blocks ORDER BY height DESC LIMIT 1\")\n .get() as { raw: string } | undefined;\n return row ? (JSON.parse(row.raw) as Block) : null;\n }\n\n getRange(fromHeight: number, toHeight: number): Block[] {\n const rows = this.q\n .prepare(\"SELECT raw FROM blocks WHERE height >= ? AND height <= ? ORDER BY height ASC\")\n .all(fromHeight, toHeight) as { raw: string }[];\n return rows.map((r) => JSON.parse(r.raw) as Block);\n }\n\n getHeight(): number {\n const row = this.q.prepare(\"SELECT MAX(height) as h FROM blocks\").get() as\n | { h: number | null }\n | undefined;\n return row?.h ?? -1;\n }\n}\n","import { sha256 } from \"@noble/hashes/sha256\";\nimport { toHex } from \"../utils.js\";\n\nexport function sha256Hex(data: string | Uint8Array): string {\n const input = typeof data === \"string\" ? new TextEncoder().encode(data) : data;\n return toHex(sha256(input));\n}\n\nexport function sha256Bytes(data: string | Uint8Array): Uint8Array {\n const input = typeof data === \"string\" ? new TextEncoder().encode(data) : data;\n return sha256(input);\n}\n","import { EMPTY_MERKLE_ROOT } from \"../constants.js\";\nimport { sha256Hex } from \"./hash.js\";\n\n/** Compute Merkle root from a list of transaction hashes. */\nexport function computeMerkleRoot(hashes: string[]): string {\n if (hashes.length === 0) return EMPTY_MERKLE_ROOT;\n if (hashes.length === 1) return hashes[0]!;\n\n let level = [...hashes];\n\n while (level.length > 1) {\n const next: string[] = [];\n for (let i = 0; i < level.length; i += 2) {\n const left = level[i]!;\n const right = i + 1 < level.length ? level[i + 1]! : left;\n next.push(sha256Hex(left + right));\n }\n level = next;\n }\n\n return level[0]!;\n}\n","import type { Block, HexString, Transaction } from \"../types.js\";\nimport { GENESIS_PREVIOUS_HASH, GENESIS_TIMESTAMP, EMPTY_MERKLE_ROOT } from \"../constants.js\";\nimport { ValidationError } from \"../errors.js\";\nimport { sha256Hex } from \"./hash.js\";\nimport { computeMerkleRoot } from \"./merkle.js\";\nimport { canonicalize } from \"./serialization.js\";\n\nexport interface CreateBlockParams {\n height: number;\n previousHash: HexString;\n transactions: Transaction[];\n proposer: HexString;\n stateRoot: HexString;\n timestamp?: number;\n}\n\n/** Compute the canonical hash of a block header (excludes hash and signature). */\nexport function computeBlockHash(params: {\n height: number;\n previousHash: string;\n timestamp: number;\n merkleRoot: string;\n stateRoot: string;\n proposer: string;\n}): string {\n const canonical = canonicalize({\n height: params.height,\n previousHash: params.previousHash,\n timestamp: params.timestamp,\n merkleRoot: params.merkleRoot,\n stateRoot: params.stateRoot,\n proposer: params.proposer,\n });\n return sha256Hex(canonical);\n}\n\n/** Create an unsigned block. Signature must be added separately. */\nexport function createBlock(params: CreateBlockParams): Omit<Block, \"signature\"> & { signature: \"\" } {\n const timestamp = params.timestamp ?? Date.now();\n const merkleRoot = computeMerkleRoot(params.transactions.map((tx) => tx.hash));\n\n const hash = computeBlockHash({\n height: params.height,\n previousHash: params.previousHash,\n timestamp,\n merkleRoot,\n stateRoot: params.stateRoot,\n proposer: params.proposer,\n });\n\n return {\n height: params.height,\n hash,\n previousHash: params.previousHash,\n timestamp,\n merkleRoot,\n stateRoot: params.stateRoot,\n proposer: params.proposer,\n signature: \"\",\n transactions: params.transactions,\n };\n}\n\n/** Create the genesis block (height 0, no transactions). */\nexport function createGenesisBlock(proposer: HexString): Block {\n const merkleRoot = EMPTY_MERKLE_ROOT;\n const stateRoot = EMPTY_MERKLE_ROOT;\n const timestamp = GENESIS_TIMESTAMP;\n\n const hash = computeBlockHash({\n height: 0,\n previousHash: GENESIS_PREVIOUS_HASH,\n timestamp,\n merkleRoot,\n stateRoot,\n proposer,\n });\n\n return {\n height: 0,\n hash,\n previousHash: GENESIS_PREVIOUS_HASH,\n timestamp,\n merkleRoot,\n stateRoot,\n proposer,\n signature: \"\",\n transactions: [],\n };\n}\n\n/** Validate a block's structural integrity (does not verify signature). */\nexport function validateBlock(block: Block, previousBlock?: Block): void {\n if (block.height < 0 || !Number.isInteger(block.height)) {\n throw new ValidationError(`Invalid block height: ${block.height}`);\n }\n\n if (previousBlock) {\n if (block.height !== previousBlock.height + 1) {\n throw new ValidationError(\n `Block height ${block.height} does not follow ${previousBlock.height}`,\n );\n }\n if (block.previousHash !== previousBlock.hash) {\n throw new ValidationError(\"Block previousHash does not match previous block hash\");\n }\n if (block.timestamp < previousBlock.timestamp) {\n throw new ValidationError(\"Block timestamp is before previous block\");\n }\n }\n\n // Verify merkle root\n const expectedMerkle = computeMerkleRoot(block.transactions.map((tx) => tx.hash));\n if (expectedMerkle !== block.merkleRoot) {\n throw new ValidationError(\"Block merkle root mismatch\");\n }\n\n // Verify block hash\n const expectedHash = computeBlockHash({\n height: block.height,\n previousHash: block.previousHash,\n timestamp: block.timestamp,\n merkleRoot: block.merkleRoot,\n stateRoot: block.stateRoot,\n proposer: block.proposer,\n });\n if (expectedHash !== block.hash) {\n throw new ValidationError(\"Block hash mismatch\");\n }\n}\n","import type { Block, HexString, Transaction } from \"../types.js\";\nimport { ChainError } from \"../errors.js\";\nimport { createGenesisBlock, createBlock, validateBlock } from \"./block.js\";\n\n/**\n * In-memory chain manager. Tracks the current chain tip and validates new blocks.\n * Backed by a storage layer for persistence.\n */\nexport class Chain {\n private tip: Block | null = null;\n private height = -1;\n\n /** Initialize chain with genesis block or restore from latest block. */\n init(latestBlock?: Block): void {\n if (latestBlock) {\n this.tip = latestBlock;\n this.height = latestBlock.height;\n }\n }\n\n /** Create and return a genesis block. */\n createGenesis(proposer: HexString): Block {\n if (this.height >= 0) {\n throw new ChainError(\"Chain already initialized\");\n }\n const genesis = createGenesisBlock(proposer);\n this.tip = genesis;\n this.height = 0;\n return genesis;\n }\n\n /** Propose a new block with the given transactions. Returns unsigned block. */\n proposeBlock(\n transactions: Transaction[],\n proposer: HexString,\n stateRoot: HexString,\n ): Block {\n if (!this.tip) {\n throw new ChainError(\"Chain not initialized\");\n }\n const block = createBlock({\n height: this.tip.height + 1,\n previousHash: this.tip.hash,\n transactions,\n proposer,\n stateRoot,\n });\n return block as Block;\n }\n\n /** Validate and append a block to the chain. */\n appendBlock(block: Block): void {\n validateBlock(block, this.tip ?? undefined);\n this.tip = block;\n this.height = block.height;\n }\n\n getTip(): Block | null {\n return this.tip;\n }\n\n getHeight(): number {\n return this.height;\n }\n}\n","import { serve } from \"@hono/node-server\";\nimport type { Command } from \"commander\";\nimport { DEFAULT_CONFIG } from \"../../config/index.js\";\nimport { MiniLedgerNode } from \"../../node.js\";\nimport { createApp } from \"../../api/server.js\";\n\nexport function registerStart(program: Command): void {\n program\n .command(\"start\")\n .description(\"Start the MiniLedger node\")\n .option(\"-d, --data-dir <path>\", \"Data directory\", DEFAULT_CONFIG.dataDir)\n .option(\"-p, --api-port <port>\", \"API port\", String(DEFAULT_CONFIG.network.apiPort))\n .option(\"--p2p-port <port>\", \"P2P port\", String(DEFAULT_CONFIG.network.p2pPort))\n .option(\"--peers <addresses>\", \"Comma-separated peer addresses (ws://host:port)\")\n .option(\"--consensus <algo>\", \"Consensus algorithm (solo|raft)\", DEFAULT_CONFIG.consensus.algorithm)\n .option(\"--no-api\", \"Disable REST API\")\n .action(async (opts) => {\n const peers = opts.peers ? (opts.peers as string).split(\",\").map((s: string) => s.trim()) : [];\n\n const node = await MiniLedgerNode.create({\n dataDir: opts.dataDir,\n config: {\n network: {\n ...DEFAULT_CONFIG.network,\n apiPort: Number.parseInt(opts.apiPort, 10),\n p2pPort: Number.parseInt(opts.p2pPort, 10),\n peers,\n },\n consensus: {\n ...DEFAULT_CONFIG.consensus,\n algorithm: opts.consensus as \"solo\" | \"raft\",\n },\n api: {\n ...DEFAULT_CONFIG.api,\n enabled: opts.api !== false,\n },\n },\n });\n\n await node.init();\n await node.start();\n\n // Start HTTP API\n if (node.config.api.enabled) {\n const app = createApp(node);\n serve({\n fetch: app.fetch,\n port: node.config.network.apiPort,\n });\n\n console.log(`REST API listening on http://localhost:${node.config.network.apiPort}`);\n }\n\n const status = node.getStatus();\n console.log(`\\nMiniLedger node running`);\n console.log(` Node ID: ${status.nodeId}`);\n console.log(` Consensus: ${node.config.consensus.algorithm}`);\n console.log(` Height: ${status.chainHeight}`);\n if (node.config.consensus.algorithm === \"raft\") {\n console.log(` P2P Port: ${node.config.network.p2pPort}`);\n if (peers.length > 0) console.log(` Peers: ${peers.join(\", \")}`);\n }\n console.log(`\\nPress Ctrl+C to stop\\n`);\n\n // Graceful shutdown\n const shutdown = async () => {\n console.log(\"\\nShutting down...\");\n await node.stop();\n process.exit(0);\n };\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n });\n}\n","import * as path from \"node:path\";\nimport * as fs from \"node:fs\";\nimport { EventEmitter } from \"node:events\";\nimport pino from \"pino\";\nimport type { Block, Transaction, NodeStatus, StateEntry, TxType } from \"./types.js\";\nimport { TxType as TxTypeEnum } from \"./types.js\";\nimport { PROTOCOL_VERSION, GENESIS_PROPOSER } from \"./constants.js\";\nimport { Chain, createTransaction, validateTransaction } from \"./core/index.js\";\nimport { MiniLedgerDB, BlockStore, StateStore, TxStore } from \"./storage/index.js\";\nimport {\n generateKeyPair,\n sign,\n verify,\n serializeKeystore,\n deserializeKeystore,\n encryptKeystore,\n decryptKeystore,\n type KeyPair,\n} from \"./identity/index.js\";\nimport { type MiniLedgerConfig, loadConfig } from \"./config/index.js\";\nimport { PeerManager } from \"./network/peer-manager.js\";\nimport { BlockSync } from \"./network/sync.js\";\nimport {\n MessageType,\n createMessage,\n type BlockAnnouncePayload,\n type TxBroadcastPayload,\n} from \"./network/protocol.js\";\nimport { RaftNode } from \"./consensus/raft/raft-node.js\";\nimport { shortId } from \"./utils.js\";\nimport { ContractRegistry, createContractContext } from \"./contracts/index.js\";\nimport { Governor } from \"./governance/governor.js\";\nimport { ProposalType } from \"./governance/proposal.js\";\n\n// Events: block:created, block:received, tx:submitted, tx:confirmed, started, stopped, error\n\nexport interface CreateNodeOptions {\n dataDir?: string;\n config?: Partial<MiniLedgerConfig>;\n}\n\nexport class MiniLedgerNode extends EventEmitter {\n readonly config: MiniLedgerConfig;\n readonly log: pino.Logger;\n\n private db!: MiniLedgerDB;\n private blockStore!: BlockStore;\n private stateStore!: StateStore;\n private txStore!: TxStore;\n private chain!: Chain;\n private keyPair!: KeyPair;\n private nodeId!: string;\n\n // Solo mode timer\n private blockTimer: ReturnType<typeof setInterval> | null = null;\n\n // Networking (M2)\n private peerManager: PeerManager | null = null;\n private blockSync: BlockSync | null = null;\n private raft: RaftNode | null = null;\n private raftBlockTimer: ReturnType<typeof setInterval> | null = null;\n\n // M3: Contracts + Governance\n private contractRegistry!: ContractRegistry;\n private governor!: Governor;\n\n private startedAt = 0;\n private running = false;\n\n constructor(config: MiniLedgerConfig) {\n super();\n this.config = config;\n this.log = pino({\n level: config.logging.level,\n transport: {\n target: \"pino/file\",\n options: { destination: 1 }, // stdout\n },\n });\n }\n\n /** Create a new MiniLedgerNode with optional overrides. */\n static async create(options: CreateNodeOptions = {}): Promise<MiniLedgerNode> {\n const config = loadConfig({\n dataDir: options.dataDir,\n ...options.config,\n });\n const node = new MiniLedgerNode(config);\n return node;\n }\n\n /** Initialize the node: open DB, load or create identity, restore chain. */\n async init(): Promise<void> {\n // Ensure data directory exists\n fs.mkdirSync(this.config.dataDir, { recursive: true });\n\n // Open database\n const dbPath = path.join(this.config.dataDir, \"ledger.db\");\n this.db = new MiniLedgerDB(dbPath);\n this.db.migrate();\n\n this.blockStore = new BlockStore(this.db.raw());\n this.stateStore = new StateStore(this.db.raw());\n this.txStore = new TxStore(this.db.raw());\n this.contractRegistry = new ContractRegistry(this.stateStore);\n this.governor = new Governor(this.stateStore);\n\n // Load or create keypair\n const keystorePath = path.join(this.config.dataDir, \"keystore.json\");\n if (fs.existsSync(keystorePath)) {\n const data = fs.readFileSync(keystorePath, \"utf-8\");\n const ks = deserializeKeystore(data);\n this.keyPair = decryptKeystore(ks, \"\");\n } else {\n this.keyPair = generateKeyPair();\n const ks = encryptKeystore(\n this.keyPair,\n \"\",\n this.config.node.orgId,\n this.config.node.name,\n );\n fs.writeFileSync(keystorePath, serializeKeystore(ks));\n }\n\n this.nodeId = shortId(this.keyPair.publicKey);\n\n // Initialize chain\n this.chain = new Chain();\n const latestBlock = this.blockStore.getLatest();\n if (latestBlock) {\n this.chain.init(latestBlock);\n this.log.info({ height: latestBlock.height }, \"Restored chain from storage\");\n } else {\n // Create genesis block\n const genesis = this.chain.createGenesis(GENESIS_PROPOSER);\n this.db.raw().transaction(() => {\n this.blockStore.insert(genesis);\n })();\n this.log.info(\"Created genesis block\");\n }\n }\n\n /** Start the node: begin producing blocks and serving API. */\n async start(): Promise<void> {\n if (this.running) return;\n this.running = true;\n this.startedAt = Date.now();\n\n if (this.config.consensus.algorithm === \"solo\") {\n // Solo mode: simple block production timer\n this.blockTimer = setInterval(() => {\n this.produceBlock().catch((err) => {\n this.log.error({ err }, \"Block production error\");\n this.emit(\"error\", err as Error);\n });\n }, this.config.consensus.blockTimeMs);\n } else if (this.config.consensus.algorithm === \"raft\") {\n // Raft mode: set up P2P + consensus\n await this.startNetworking();\n this.startRaftConsensus();\n }\n\n this.log.info(\n {\n nodeId: this.nodeId,\n consensus: this.config.consensus.algorithm,\n apiPort: this.config.api.enabled ? this.config.network.apiPort : \"disabled\",\n p2pPort: this.config.consensus.algorithm === \"raft\" ? this.config.network.p2pPort : \"disabled\",\n },\n \"Node started\",\n );\n this.emit(\"started\");\n }\n\n /** Stop the node. */\n async stop(): Promise<void> {\n if (!this.running) return;\n this.running = false;\n\n if (this.blockTimer) {\n clearInterval(this.blockTimer);\n this.blockTimer = null;\n }\n\n if (this.raftBlockTimer) {\n clearInterval(this.raftBlockTimer);\n this.raftBlockTimer = null;\n }\n\n if (this.raft) {\n this.raft.stop();\n this.raft = null;\n }\n\n if (this.peerManager) {\n this.peerManager.stop();\n this.peerManager = null;\n }\n\n this.blockSync = null;\n\n this.db.close();\n this.log.info(\"Node stopped\");\n this.emit(\"stopped\");\n }\n\n // ── Networking ──────────────────────────────────────────────────\n\n private async startNetworking(): Promise<void> {\n this.peerManager = new PeerManager({\n nodeId: this.nodeId,\n publicKey: this.keyPair.publicKey,\n orgId: this.config.node.orgId,\n p2pPort: this.config.network.p2pPort,\n listenAddress: this.config.network.listenAddress,\n log: this.log,\n getChainHeight: () => this.chain.getHeight(),\n });\n\n // Set up block announce handler\n this.peerManager.router.on(MessageType.BlockAnnounce, (msg) => {\n const payload = msg.payload as BlockAnnouncePayload;\n this.handleBlockAnnounce(payload.block);\n });\n\n // Set up tx broadcast handler\n this.peerManager.router.on(MessageType.TxBroadcast, (msg) => {\n const payload = msg.payload as TxBroadcastPayload;\n this.handleTxBroadcast(payload.transaction);\n });\n\n // Set up peer events\n this.peerManager.on(\"peer:connected\", (peerId: string) => {\n this.log.info({ peerId }, \"Peer connected\");\n // Trigger sync if the new peer might have blocks we don't\n if (this.blockSync) {\n this.blockSync.syncFromPeers().catch((err) => {\n this.log.warn({ err }, \"Sync after peer connect failed\");\n });\n }\n });\n\n // Set up block sync\n this.blockSync = new BlockSync({\n nodeId: this.nodeId,\n log: this.log,\n peerManager: this.peerManager,\n getChainHeight: () => this.chain.getHeight(),\n getBlocks: (from, to) => this.blockStore.getRange(from, to),\n applyBlock: (block) => this.applyReceivedBlock(block),\n });\n\n await this.peerManager.start();\n\n // Connect to initial peers\n for (const addr of this.config.network.peers) {\n this.peerManager.connectTo(addr);\n }\n }\n\n private startRaftConsensus(): void {\n if (!this.peerManager) return;\n\n this.raft = new RaftNode({\n nodeId: this.nodeId,\n peerManager: this.peerManager,\n log: this.log,\n blockTimeMs: this.config.consensus.blockTimeMs,\n });\n\n // When raft commits a block, apply it\n this.raft.onBlockCommitted = (block: Block) => {\n this.applyReceivedBlock(block);\n };\n\n // When raft receives a forwarded tx, add to pending pool\n this.raft.onTransactionReceived = (tx: Transaction) => {\n this.txStore.addToPending(tx);\n };\n\n // When we become leader, start block production\n this.raft.on(\"leader\", () => {\n this.log.info(\"This node is now the Raft leader — starting block production\");\n if (this.raftBlockTimer) clearInterval(this.raftBlockTimer);\n this.raftBlockTimer = setInterval(() => {\n this.produceRaftBlock().catch((err) => {\n this.log.error({ err }, \"Raft block production error\");\n });\n }, this.config.consensus.blockTimeMs);\n });\n\n this.raft.start();\n }\n\n // ── Block handling ──────────────────────────────────────────────\n\n private handleBlockAnnounce(block: Block): void {\n // In Raft mode, blocks come through consensus, not direct announce\n // This handler is for future non-Raft modes\n if (this.config.consensus.algorithm !== \"raft\") {\n this.applyReceivedBlock(block);\n }\n }\n\n private handleTxBroadcast(tx: Transaction): void {\n // Don't re-add if we already have it\n const existing = this.txStore.getByHash(tx.hash);\n if (existing) return;\n\n // Validate\n try {\n validateTransaction(tx);\n if (!verify(tx.hash, tx.signature, tx.sender)) return;\n } catch {\n return;\n }\n\n this.txStore.addToPending(tx);\n }\n\n /** Apply a block received from network/consensus. */\n private applyReceivedBlock(block: Block): void {\n try {\n // Apply transactions to state\n this.db.raw().transaction(() => {\n for (const tx of block.transactions) {\n this.applyTransaction(tx, block.height);\n }\n\n this.chain.appendBlock(block);\n this.blockStore.insert(block);\n\n // Remove confirmed tx from pending pool\n this.txStore.removePending(block.transactions.map((tx) => tx.hash));\n for (const tx of block.transactions) {\n this.txStore.updateNonce(tx.sender, tx.nonce);\n }\n })();\n\n this.log.info({ height: block.height, txCount: block.transactions.length }, \"Block applied\");\n this.emit(\"block:received\", block);\n } catch (err) {\n this.log.warn({ err, height: block.height }, \"Failed to apply received block\");\n }\n }\n\n // ── Transaction submission ──────────────────────────────────────\n\n /** Submit a transaction to the node. */\n async submit(params: {\n type?: TxType;\n key?: string;\n value?: unknown;\n payload?: Transaction[\"payload\"];\n }): Promise<Transaction> {\n const sender = this.keyPair.publicKey;\n const nonce = this.txStore.getNextNonce(sender);\n\n let payload: Transaction[\"payload\"];\n if (params.payload) {\n payload = params.payload;\n } else if (params.key !== undefined) {\n if (params.value === undefined || params.value === null) {\n payload = { kind: \"state:delete\", key: params.key };\n } else {\n payload = { kind: \"state:set\", key: params.key, value: params.value };\n }\n } else {\n throw new Error(\"Either payload or key must be provided\");\n }\n\n const txType = params.type ?? (payload.kind === \"state:delete\" ? TxTypeEnum.StateDelete : TxTypeEnum.StateSet);\n\n const unsignedTx = createTransaction({\n type: txType,\n sender,\n nonce,\n payload,\n });\n\n // Sign\n const signature = sign(unsignedTx.hash, this.keyPair.privateKey);\n const tx: Transaction = { ...unsignedTx, signature };\n\n // Validate\n validateTransaction(tx);\n\n // Verify signature\n if (!verify(tx.hash, tx.signature, tx.sender)) {\n throw new Error(\"Transaction signature verification failed\");\n }\n\n // Add to pending pool\n this.txStore.addToPending(tx);\n\n // In Raft mode, if we're not the leader, forward to leader\n if (this.raft && !this.raft.isLeader()) {\n this.raft.forwardToLeader(tx);\n }\n\n // Broadcast to peers\n if (this.peerManager) {\n this.peerManager.broadcast(\n createMessage(MessageType.TxBroadcast, this.nodeId, { transaction: tx } as TxBroadcastPayload),\n );\n }\n\n this.emit(\"tx:submitted\", tx);\n this.log.debug({ hash: tx.hash, type: tx.type }, \"Transaction submitted\");\n\n return tx;\n }\n\n // ── Block production ────────────────────────────────────────────\n\n /** Produce a block in solo mode. */\n private async produceBlock(): Promise<Block | null> {\n const pending = this.txStore.getPending(this.config.consensus.maxTxPerBlock);\n\n const applied: Transaction[] = [];\n this.db.raw().transaction(() => {\n for (const tx of pending) {\n try {\n this.applyTransaction(tx, this.chain.getHeight() + 1);\n applied.push(tx);\n } catch (err) {\n this.log.warn({ hash: tx.hash, err }, \"Failed to apply transaction\");\n }\n }\n\n if (applied.length === 0) return;\n\n const stateRoot = this.stateStore.computeStateRoot();\n const block = this.chain.proposeBlock(applied, this.keyPair.publicKey, stateRoot);\n const signature = sign(block.hash, this.keyPair.privateKey);\n const signedBlock: Block = { ...block, signature };\n\n this.chain.appendBlock(signedBlock);\n this.blockStore.insert(signedBlock);\n this.txStore.removePending(applied.map((tx) => tx.hash));\n\n for (const tx of applied) {\n this.txStore.updateNonce(tx.sender, tx.nonce);\n }\n\n this.log.info({ height: signedBlock.height, txCount: applied.length }, \"Block produced\");\n this.emit(\"block:created\", signedBlock);\n })();\n\n return this.chain.getTip();\n }\n\n /** Produce a block as Raft leader — propose it through consensus. */\n private async produceRaftBlock(): Promise<void> {\n if (!this.raft || !this.raft.isLeader()) return;\n\n const pending = this.txStore.getPending(this.config.consensus.maxTxPerBlock);\n if (pending.length === 0) return;\n\n // Build the block\n const stateRoot = this.stateStore.computeStateRoot();\n const block = this.chain.proposeBlock(pending, this.keyPair.publicKey, stateRoot);\n const signature = sign(block.hash, this.keyPair.privateKey);\n const signedBlock: Block = { ...block, signature };\n\n // Propose through Raft — will be applied when committed via onBlockCommitted callback\n this.raft.proposeBlock(signedBlock);\n }\n\n // ── State application ───────────────────────────────────────────\n\n /** Apply a single transaction to the world state. */\n private applyTransaction(tx: Transaction, blockHeight: number): void {\n const { payload } = tx;\n\n switch (payload.kind) {\n case \"state:set\":\n this.stateStore.set(payload.key, payload.value, tx.sender, blockHeight);\n break;\n case \"state:delete\":\n this.stateStore.delete(payload.key);\n break;\n case \"contract:deploy\":\n this.contractRegistry.deploy(\n payload.name,\n payload.version,\n payload.code,\n tx.sender,\n blockHeight,\n );\n this.log.info({ contract: payload.name, version: payload.version }, \"Contract deployed\");\n break;\n case \"contract:invoke\": {\n const ctx = createContractContext({\n stateStore: this.stateStore,\n sender: tx.sender,\n blockHeight,\n timestamp: tx.timestamp,\n });\n this.contractRegistry.invoke(payload.contract, payload.method, ctx, payload.args);\n break;\n }\n case \"governance:propose\":\n this.governor.propose({\n type: (payload.action?.type as ProposalType) ?? ProposalType.Custom,\n title: payload.title,\n description: payload.description,\n proposer: tx.sender,\n action: payload.action,\n blockHeight,\n });\n this.log.info({ title: payload.title }, \"Proposal created\");\n break;\n case \"governance:vote\":\n this.governor.vote(payload.proposalId, tx.sender, payload.vote, blockHeight);\n break;\n default:\n this.log.warn({ type: tx.type }, \"Unhandled transaction type\");\n }\n }\n\n // ── Queries ─────────────────────────────────────────────────────\n\n async query(sql: string, params: unknown[] = []): Promise<Record<string, unknown>[]> {\n return this.stateStore.query(sql, params);\n }\n\n async getState(key: string): Promise<StateEntry | null> {\n return this.stateStore.get(key);\n }\n\n async getBlock(height: number): Promise<Block | null> {\n return this.blockStore.getByHeight(height);\n }\n\n async getLatestBlock(): Promise<Block | null> {\n return this.blockStore.getLatest();\n }\n\n async getTransaction(hash: string): Promise<Transaction | null> {\n return this.txStore.getByHash(hash);\n }\n\n getStatus(): NodeStatus {\n const tip = this.chain.getTip();\n return {\n nodeId: this.nodeId,\n publicKey: this.keyPair.publicKey,\n chainHeight: this.chain.getHeight(),\n latestBlockHash: tip?.hash ?? \"\",\n peerCount: this.peerManager?.getPeerCount() ?? 0,\n txPoolSize: this.txStore.pendingCount(),\n uptime: this.running ? Date.now() - this.startedAt : 0,\n version: PROTOCOL_VERSION,\n };\n }\n\n getPublicKey(): string {\n return this.keyPair.publicKey;\n }\n\n getNodeId(): string {\n return this.nodeId;\n }\n\n getStores() {\n return {\n blocks: this.blockStore,\n state: this.stateStore,\n txs: this.txStore,\n };\n }\n\n getDatabase() {\n return this.db;\n }\n\n getPeerManager(): PeerManager | null {\n return this.peerManager;\n }\n\n getRaft(): RaftNode | null {\n return this.raft;\n }\n\n getContractRegistry(): ContractRegistry {\n return this.contractRegistry;\n }\n\n getGovernor(): Governor {\n return this.governor;\n }\n\n isRunning(): boolean {\n return this.running;\n }\n}\n","export type HexString = string;\n\nexport enum TxType {\n StateSet = \"state:set\",\n StateDelete = \"state:delete\",\n ContractDeploy = \"contract:deploy\",\n ContractInvoke = \"contract:invoke\",\n GovernancePropose = \"governance:propose\",\n GovernanceVote = \"governance:vote\",\n}\n\nexport interface StateSetPayload {\n kind: \"state:set\";\n key: string;\n value: unknown;\n}\n\nexport interface StateDeletePayload {\n kind: \"state:delete\";\n key: string;\n}\n\nexport interface ContractDeployPayload {\n kind: \"contract:deploy\";\n name: string;\n version: string;\n code: string;\n}\n\nexport interface ContractInvokePayload {\n kind: \"contract:invoke\";\n contract: string;\n method: string;\n args: unknown[];\n}\n\nexport interface GovernanceProposePayload {\n kind: \"governance:propose\";\n title: string;\n description: string;\n action: Record<string, unknown>;\n}\n\nexport interface GovernanceVotePayload {\n kind: \"governance:vote\";\n proposalId: string;\n vote: boolean;\n}\n\nexport type TxPayload =\n | StateSetPayload\n | StateDeletePayload\n | ContractDeployPayload\n | ContractInvokePayload\n | GovernanceProposePayload\n | GovernanceVotePayload;\n\nexport interface Transaction {\n hash: HexString;\n type: TxType;\n sender: HexString;\n nonce: number;\n timestamp: number;\n payload: TxPayload;\n signature: HexString;\n}\n\nexport interface Block {\n height: number;\n hash: HexString;\n previousHash: HexString;\n timestamp: number;\n merkleRoot: HexString;\n stateRoot: HexString;\n proposer: HexString;\n signature: HexString;\n transactions: Transaction[];\n}\n\nexport interface StateEntry {\n key: string;\n value: unknown;\n version: number;\n updatedAt: number;\n updatedBy: HexString;\n blockHeight: number;\n}\n\nexport interface PeerInfo {\n id: string;\n publicKey: HexString;\n address: string;\n orgId: string;\n role: \"validator\" | \"observer\";\n status: \"connected\" | \"disconnected\" | \"syncing\";\n lastSeen: number;\n chainHeight: number;\n}\n\nexport interface NodeIdentity {\n publicKey: HexString;\n nodeId: string;\n orgId: string;\n name: string;\n role: \"admin\" | \"member\" | \"observer\";\n createdAt: number;\n}\n\nexport interface NodeStatus {\n nodeId: string;\n publicKey: HexString;\n chainHeight: number;\n latestBlockHash: HexString;\n peerCount: number;\n txPoolSize: number;\n uptime: number;\n version: number;\n}\n","import type { HexString, Transaction, TxPayload, TxType } from \"../types.js\";\nimport { ValidationError } from \"../errors.js\";\nimport { nowMs } from \"../utils.js\";\nimport { sha256Hex } from \"./hash.js\";\nimport { canonicalize } from \"./serialization.js\";\n\nexport interface CreateTxParams {\n type: TxType;\n sender: HexString;\n nonce: number;\n payload: TxPayload;\n timestamp?: number;\n}\n\n/** Compute the canonical hash of a transaction (excludes hash and signature fields). */\nexport function computeTxHash(tx: CreateTxParams): string {\n const canonical = canonicalize({\n type: tx.type,\n sender: tx.sender,\n nonce: tx.nonce,\n timestamp: tx.timestamp,\n payload: tx.payload,\n });\n return sha256Hex(canonical);\n}\n\n/** Create an unsigned transaction. Signature must be added separately. */\nexport function createTransaction(params: CreateTxParams): Omit<Transaction, \"signature\"> & { signature: \"\" } {\n const timestamp = params.timestamp ?? nowMs();\n const withTimestamp = { ...params, timestamp };\n const hash = computeTxHash(withTimestamp);\n return {\n hash,\n type: params.type,\n sender: params.sender,\n nonce: params.nonce,\n timestamp,\n payload: params.payload,\n signature: \"\",\n };\n}\n\n/** Validate a transaction's structural integrity (does not check signature). */\nexport function validateTransaction(tx: Transaction): void {\n if (!tx.hash || tx.hash.length !== 64) {\n throw new ValidationError(\"Invalid transaction hash\");\n }\n if (!tx.sender || tx.sender.length !== 64) {\n throw new ValidationError(\"Invalid sender public key\");\n }\n if (tx.nonce < 0 || !Number.isInteger(tx.nonce)) {\n throw new ValidationError(\"Invalid nonce\");\n }\n if (!tx.payload || !tx.payload.kind) {\n throw new ValidationError(\"Missing transaction payload\");\n }\n\n // Verify hash matches content\n const expectedHash = computeTxHash({\n type: tx.type,\n sender: tx.sender,\n nonce: tx.nonce,\n timestamp: tx.timestamp,\n payload: tx.payload,\n });\n if (expectedHash !== tx.hash) {\n throw new ValidationError(\"Transaction hash mismatch\");\n }\n}\n","import type Database from \"better-sqlite3\";\nimport type { StateEntry } from \"../types.js\";\nimport { canonicalize } from \"../core/serialization.js\";\nimport { sha256Hex } from \"../core/hash.js\";\nimport { QueryCache } from \"./queries.js\";\n\nexport class StateStore {\n private q: QueryCache;\n private db: Database.Database;\n\n constructor(db: Database.Database) {\n this.db = db;\n this.q = new QueryCache(db);\n }\n\n get(key: string): StateEntry | null {\n const row = this.q.prepare(\"SELECT * FROM world_state WHERE key = ?\").get(key) as\n | {\n key: string;\n value: string;\n version: number;\n updated_at: number;\n updated_by: string;\n block_height: number;\n }\n | undefined;\n if (!row) return null;\n return {\n key: row.key,\n value: JSON.parse(row.value),\n version: row.version,\n updatedAt: row.updated_at,\n updatedBy: row.updated_by,\n blockHeight: row.block_height,\n };\n }\n\n set(\n key: string,\n value: unknown,\n updatedBy: string,\n blockHeight: number,\n ): void {\n const existing = this.q\n .prepare(\"SELECT version FROM world_state WHERE key = ?\")\n .get(key) as { version: number } | undefined;\n\n const version = existing ? existing.version + 1 : 1;\n const serialized = canonicalize(value);\n\n this.q\n .prepare(\n `INSERT INTO world_state (key, value, version, updated_at, updated_by, block_height)\n VALUES (?, ?, ?, ?, ?, ?)\n ON CONFLICT(key) DO UPDATE SET\n value = excluded.value,\n version = excluded.version,\n updated_at = excluded.updated_at,\n updated_by = excluded.updated_by,\n block_height = excluded.block_height`,\n )\n .run(key, serialized, version, Date.now(), updatedBy, blockHeight);\n }\n\n delete(key: string): boolean {\n const result = this.q.prepare(\"DELETE FROM world_state WHERE key = ?\").run(key);\n return result.changes > 0;\n }\n\n /** Execute a read-only SQL query against the world_state table. */\n query(sql: string, params: unknown[] = []): Record<string, unknown>[] {\n // Only allow SELECT queries for safety\n const trimmed = sql.trim().toUpperCase();\n if (!trimmed.startsWith(\"SELECT\")) {\n throw new Error(\"Only SELECT queries are allowed\");\n }\n return this.db.prepare(sql).all(...params) as Record<string, unknown>[];\n }\n\n /** Compute a hash of the entire world state (for stateRoot). */\n computeStateRoot(): string {\n const rows = this.q\n .prepare(\"SELECT key, value, version FROM world_state ORDER BY key ASC\")\n .all() as { key: string; value: string; version: number }[];\n\n if (rows.length === 0) {\n return \"0\".repeat(64);\n }\n\n const stateString = rows\n .map((r) => `${r.key}:${r.value}:${r.version}`)\n .join(\"|\");\n return sha256Hex(stateString);\n }\n\n count(): number {\n const row = this.q.prepare(\"SELECT COUNT(*) as c FROM world_state\").get() as { c: number };\n return row.c;\n }\n}\n","import type Database from \"better-sqlite3\";\nimport type { Transaction } from \"../types.js\";\nimport { canonicalize } from \"../core/serialization.js\";\nimport { QueryCache } from \"./queries.js\";\n\nexport class TxStore {\n private q: QueryCache;\n\n constructor(db: Database.Database) {\n this.q = new QueryCache(db);\n }\n\n getByHash(hash: string): Transaction | null {\n const row = this.q.prepare(\"SELECT * FROM transactions WHERE hash = ?\").get(hash) as\n | {\n hash: string;\n type: string;\n sender: string;\n nonce: number;\n timestamp: number;\n payload: string;\n signature: string;\n block_height: number | null;\n position: number | null;\n status: string;\n }\n | undefined;\n if (!row) return null;\n return {\n hash: row.hash,\n type: row.type as Transaction[\"type\"],\n sender: row.sender,\n nonce: row.nonce,\n timestamp: row.timestamp,\n payload: JSON.parse(row.payload),\n signature: row.signature,\n };\n }\n\n getBySender(sender: string, limit = 100): Transaction[] {\n const rows = this.q\n .prepare(\n \"SELECT * FROM transactions WHERE sender = ? ORDER BY timestamp DESC LIMIT ?\",\n )\n .all(sender, limit) as {\n hash: string;\n type: string;\n sender: string;\n nonce: number;\n timestamp: number;\n payload: string;\n signature: string;\n }[];\n\n return rows.map((r) => ({\n hash: r.hash,\n type: r.type as Transaction[\"type\"],\n sender: r.sender,\n nonce: r.nonce,\n timestamp: r.timestamp,\n payload: JSON.parse(r.payload),\n signature: r.signature,\n }));\n }\n\n /** Add a transaction to the pending pool. */\n addToPending(tx: Transaction): void {\n this.q\n .prepare(\"INSERT OR IGNORE INTO tx_pool (hash, raw, received, priority) VALUES (?, ?, ?, 0)\")\n .run(tx.hash, canonicalize(tx), Date.now());\n }\n\n /** Get all pending transactions, ordered by received time. */\n getPending(limit = 500): Transaction[] {\n const rows = this.q\n .prepare(\"SELECT raw FROM tx_pool ORDER BY priority DESC, received ASC LIMIT ?\")\n .all(limit) as { raw: string }[];\n return rows.map((r) => JSON.parse(r.raw) as Transaction);\n }\n\n /** Remove transactions from the pending pool (after inclusion in a block). */\n removePending(hashes: string[]): void {\n if (hashes.length === 0) return;\n const placeholders = hashes.map(() => \"?\").join(\",\");\n this.q.prepare(`DELETE FROM tx_pool WHERE hash IN (${placeholders})`).run(...hashes);\n }\n\n pendingCount(): number {\n const row = this.q.prepare(\"SELECT COUNT(*) as c FROM tx_pool\").get() as { c: number };\n return row.c;\n }\n\n /** Get the next nonce for a sender. */\n getNextNonce(sender: string): number {\n const row = this.q.prepare(\"SELECT nonce FROM nonces WHERE sender = ?\").get(sender) as\n | { nonce: number }\n | undefined;\n return row ? row.nonce + 1 : 0;\n }\n\n /** Update the nonce tracker for a sender. */\n updateNonce(sender: string, nonce: number): void {\n this.q\n .prepare(\n \"INSERT INTO nonces (sender, nonce) VALUES (?, ?) ON CONFLICT(sender) DO UPDATE SET nonce = excluded.nonce\",\n )\n .run(sender, nonce);\n }\n}\n","import type pino from \"pino\";\nimport { EventEmitter } from \"node:events\";\nimport { Peer, type PeerState } from \"./peer.js\";\nimport { WsServer } from \"./ws-server.js\";\nimport { WsClient } from \"./ws-client.js\";\nimport { MessageRouter } from \"./router.js\";\nimport {\n type MessageEnvelope,\n MessageType,\n createMessage,\n type HandshakePayload,\n type HandshakeAckPayload,\n type PingPayload,\n type PongPayload,\n type PeerListPayload,\n} from \"./protocol.js\";\nimport type { HexString } from \"../types.js\";\n\nexport interface PeerManagerOptions {\n nodeId: string;\n publicKey: HexString;\n orgId: string;\n p2pPort: number;\n listenAddress: string;\n log: pino.Logger;\n getChainHeight: () => number;\n}\n\n// Events: peer:connected, peer:disconnected, peer:handshake, message:<MessageType>\nexport class PeerManager extends EventEmitter {\n readonly router: MessageRouter;\n private server: WsServer;\n private client: WsClient;\n private peers = new Map<string, Peer>(); // nodeId -> Peer\n private opts: PeerManagerOptions;\n private healthTimer: ReturnType<typeof setInterval> | null = null;\n\n constructor(opts: PeerManagerOptions) {\n super();\n this.opts = opts;\n this.router = new MessageRouter();\n\n // Wire up built-in message handlers\n this.router.on(MessageType.Handshake, this.handleHandshake.bind(this));\n this.router.on(MessageType.HandshakeAck, this.handleHandshakeAck.bind(this));\n this.router.on(MessageType.Ping, this.handlePing.bind(this));\n this.router.on(MessageType.Pong, this.handlePong.bind(this));\n this.router.on(MessageType.PeerList, this.handlePeerList.bind(this));\n\n // Create server and client\n this.server = new WsServer({\n port: opts.p2pPort,\n host: opts.listenAddress,\n log: opts.log,\n router: this.router,\n onPeerConnected: (peer) => this.onRawPeerConnected(peer),\n onPeerDisconnected: (peer) => this.onRawPeerDisconnected(peer),\n });\n\n this.client = new WsClient({\n log: opts.log,\n router: this.router,\n onPeerConnected: (peer) => {\n this.onRawPeerConnected(peer);\n // Outbound connections send handshake first\n this.sendHandshake(peer);\n },\n onPeerDisconnected: (peer) => this.onRawPeerDisconnected(peer),\n });\n }\n\n async start(): Promise<void> {\n await this.server.start();\n\n // Periodic health check / ping\n this.healthTimer = setInterval(() => {\n this.pingAll();\n }, 5000);\n }\n\n stop(): void {\n if (this.healthTimer) {\n clearInterval(this.healthTimer);\n this.healthTimer = null;\n }\n this.client.stop();\n this.server.stop();\n for (const peer of this.peers.values()) {\n peer.close();\n }\n this.peers.clear();\n }\n\n /** Connect to a peer by address (ws://host:port). */\n connectTo(address: string): void {\n this.client.connect(address);\n }\n\n /** Broadcast a message to all connected peers. */\n broadcast(msg: MessageEnvelope): void {\n for (const peer of this.peers.values()) {\n if (peer.status === \"connected\") {\n peer.send(msg);\n }\n }\n }\n\n /** Send a message to a specific peer by nodeId. */\n sendTo(nodeId: string, msg: MessageEnvelope): void {\n const peer = this.peers.get(nodeId);\n if (peer && peer.status === \"connected\") {\n peer.send(msg);\n }\n }\n\n /** Send to leader or a specific peer. */\n sendToPeer(peer: Peer, msg: MessageEnvelope): void {\n peer.send(msg);\n }\n\n getPeer(nodeId: string): Peer | undefined {\n return this.peers.get(nodeId);\n }\n\n getConnectedPeers(): Peer[] {\n return Array.from(this.peers.values()).filter((p) => p.status === \"connected\");\n }\n\n getPeerStates(): PeerState[] {\n return Array.from(this.peers.values()).map((p) => p.toInfo());\n }\n\n getPeerCount(): number {\n return this.getConnectedPeers().length;\n }\n\n /** Get all known node IDs (for Raft voter list). */\n getKnownNodeIds(): string[] {\n return Array.from(this.peers.values())\n .filter((p) => p.status === \"connected\")\n .map((p) => p.nodeId);\n }\n\n // ── Internal handlers ──────────────────────────────────────────\n\n private onRawPeerConnected(peer: Peer): void {\n this.opts.log.debug({ peerId: peer.nodeId, address: peer.address }, \"Raw peer connected\");\n }\n\n private onRawPeerDisconnected(peer: Peer): void {\n const knownPeer = this.peers.get(peer.nodeId);\n if (knownPeer) {\n this.peers.delete(peer.nodeId);\n this.opts.log.info({ peerId: peer.nodeId }, \"Peer disconnected\");\n this.emit(\"peer:disconnected\", peer.nodeId);\n }\n }\n\n private sendHandshake(peer: Peer): void {\n const payload: HandshakePayload = {\n nodeId: this.opts.nodeId,\n publicKey: this.opts.publicKey,\n orgId: this.opts.orgId,\n chainHeight: this.opts.getChainHeight(),\n listenPort: this.opts.p2pPort,\n };\n peer.send(createMessage(MessageType.Handshake, this.opts.nodeId, payload));\n }\n\n private handleHandshake(msg: MessageEnvelope, peer: Peer): void {\n const payload = msg.payload as HandshakePayload;\n\n // Reject self-connections\n if (payload.nodeId === this.opts.nodeId) {\n peer.close();\n return;\n }\n\n // Reject duplicate connections\n if (this.peers.has(payload.nodeId)) {\n peer.close();\n return;\n }\n\n // Update peer info from handshake\n peer.publicKey = payload.publicKey;\n peer.orgId = payload.orgId;\n peer.chainHeight = payload.chainHeight;\n\n // Build the peer's listen address from handshake info\n if (payload.listenPort) {\n const host = payload.listenAddress || peer.address.replace(/^ws:\\/\\//, \"\").split(\":\")[0] || \"127.0.0.1\";\n peer.address = `ws://${host}:${payload.listenPort}`;\n }\n\n // Replace temp nodeId with real one\n const realNodeId = payload.nodeId;\n (peer as any).nodeId = realNodeId;\n\n // Register peer\n peer.status = \"connected\";\n this.peers.set(realNodeId, peer);\n\n // Send ack\n const ack: HandshakeAckPayload = {\n nodeId: this.opts.nodeId,\n publicKey: this.opts.publicKey,\n orgId: this.opts.orgId,\n chainHeight: this.opts.getChainHeight(),\n accepted: true,\n };\n peer.send(createMessage(MessageType.HandshakeAck, this.opts.nodeId, ack));\n\n this.opts.log.info({ peerId: realNodeId, orgId: payload.orgId, height: payload.chainHeight }, \"Peer handshake complete (inbound)\");\n this.emit(\"peer:connected\", realNodeId, peer);\n\n // Share peer list\n this.sharePeerList(peer);\n }\n\n private handleHandshakeAck(msg: MessageEnvelope, peer: Peer): void {\n const payload = msg.payload as HandshakeAckPayload;\n\n if (!payload.accepted) {\n this.opts.log.warn({ reason: payload.reason }, \"Handshake rejected\");\n peer.close();\n return;\n }\n\n // Update peer info\n peer.publicKey = payload.publicKey;\n peer.orgId = payload.orgId;\n peer.chainHeight = payload.chainHeight;\n\n const realNodeId = payload.nodeId;\n (peer as any).nodeId = realNodeId;\n\n peer.status = \"connected\";\n this.peers.set(realNodeId, peer);\n\n this.opts.log.info({ peerId: realNodeId, orgId: payload.orgId, height: payload.chainHeight }, \"Peer handshake complete (outbound)\");\n this.emit(\"peer:connected\", realNodeId, peer);\n }\n\n private handlePing(msg: MessageEnvelope, peer: Peer): void {\n const payload = msg.payload as PingPayload;\n peer.chainHeight = payload.chainHeight;\n peer.send(createMessage(MessageType.Pong, this.opts.nodeId, {\n chainHeight: this.opts.getChainHeight(),\n } as PongPayload));\n }\n\n private handlePong(msg: MessageEnvelope, peer: Peer): void {\n const payload = msg.payload as PongPayload;\n peer.chainHeight = payload.chainHeight;\n }\n\n private handlePeerList(msg: MessageEnvelope, _peer: Peer): void {\n const payload = msg.payload as PeerListPayload;\n for (const p of payload.peers) {\n // Don't connect to ourselves or already-known peers\n if (p.nodeId === this.opts.nodeId) continue;\n if (this.peers.has(p.nodeId)) continue;\n if (p.address) {\n this.opts.log.debug({ address: p.address, nodeId: p.nodeId }, \"Discovered peer from peer list\");\n this.connectTo(p.address);\n }\n }\n }\n\n private sharePeerList(peer: Peer): void {\n const peerList: PeerListPayload = {\n peers: Array.from(this.peers.values())\n .filter((p) => p.nodeId !== peer.nodeId && p.status === \"connected\")\n .map((p) => ({\n nodeId: p.nodeId,\n publicKey: p.publicKey,\n address: p.address,\n orgId: p.orgId,\n })),\n };\n peer.send(createMessage(MessageType.PeerList, this.opts.nodeId, peerList));\n }\n\n private pingAll(): void {\n const payload: PingPayload = { chainHeight: this.opts.getChainHeight() };\n const msg = createMessage(MessageType.Ping, this.opts.nodeId, payload);\n this.broadcast(msg);\n }\n}\n","import { WebSocketServer, type WebSocket as WS } from \"ws\";\nimport type pino from \"pino\";\nimport { deserializeMessage } from \"./protocol.js\";\nimport { Peer } from \"./peer.js\";\nimport type { MessageRouter } from \"./router.js\";\n\nexport interface WsServerOptions {\n port: number;\n host: string;\n log: pino.Logger;\n router: MessageRouter;\n onPeerConnected: (peer: Peer) => void;\n onPeerDisconnected: (peer: Peer) => void;\n}\n\n/**\n * WebSocket server that accepts incoming peer connections.\n */\nexport class WsServer {\n private wss: WebSocketServer | null = null;\n private opts: WsServerOptions;\n\n constructor(opts: WsServerOptions) {\n this.opts = opts;\n }\n\n start(): Promise<void> {\n return new Promise((resolve, reject) => {\n this.wss = new WebSocketServer({\n port: this.opts.port,\n host: this.opts.host,\n });\n\n this.wss.on(\"listening\", () => {\n this.opts.log.info({ port: this.opts.port }, \"P2P server listening\");\n resolve();\n });\n\n this.wss.on(\"error\", (err) => {\n this.opts.log.error({ err }, \"P2P server error\");\n reject(err);\n });\n\n this.wss.on(\"connection\", (ws: WS, req) => {\n const remoteAddr = req.socket.remoteAddress ?? \"unknown\";\n const tempId = `inbound-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;\n\n const peer = new Peer(ws, {\n nodeId: tempId,\n address: remoteAddr,\n isInbound: true,\n });\n\n this.setupPeerHandlers(peer);\n this.opts.onPeerConnected(peer);\n });\n });\n }\n\n stop(): void {\n if (this.wss) {\n this.wss.close();\n this.wss = null;\n }\n }\n\n private setupPeerHandlers(peer: Peer): void {\n const ws = peer.getSocket();\n\n ws.on(\"message\", async (data: Buffer) => {\n try {\n const msg = deserializeMessage(data.toString());\n peer.updateSeen();\n await this.opts.router.dispatch(msg, peer);\n } catch (err) {\n this.opts.log.warn({ err, peer: peer.nodeId }, \"Failed to handle message\");\n }\n });\n\n ws.on(\"close\", () => {\n peer.status = \"disconnected\";\n this.opts.onPeerDisconnected(peer);\n });\n\n ws.on(\"error\", (err) => {\n this.opts.log.warn({ err, peer: peer.nodeId }, \"Peer connection error\");\n peer.status = \"disconnected\";\n });\n }\n}\n","import type { Block, Transaction, HexString } from \"../types.js\";\nimport { PROTOCOL_VERSION } from \"../constants.js\";\n\n// ── Message types ──────────────────────────────────────────────────\n\nexport enum MessageType {\n // Handshake\n Handshake = \"HANDSHAKE\",\n HandshakeAck = \"HANDSHAKE_ACK\",\n\n // Block propagation\n BlockAnnounce = \"BLOCK_ANNOUNCE\",\n BlockRequest = \"BLOCK_REQUEST\",\n BlockResponse = \"BLOCK_RESPONSE\",\n\n // Transaction propagation\n TxBroadcast = \"TX_BROADCAST\",\n TxForward = \"TX_FORWARD\", // Forward tx to leader\n\n // Consensus (Raft)\n ConsensusRequestVote = \"CONSENSUS_REQUEST_VOTE\",\n ConsensusRequestVoteReply = \"CONSENSUS_REQUEST_VOTE_REPLY\",\n ConsensusAppendEntries = \"CONSENSUS_APPEND_ENTRIES\",\n ConsensusAppendEntriesReply = \"CONSENSUS_APPEND_ENTRIES_REPLY\",\n\n // Sync\n SyncRequest = \"SYNC_REQUEST\",\n SyncResponse = \"SYNC_RESPONSE\",\n\n // Peer management\n PeerList = \"PEER_LIST\",\n\n // Heartbeat\n Ping = \"PING\",\n Pong = \"PONG\",\n}\n\n// ── Message envelope ───────────────────────────────────────────────\n\nexport interface MessageEnvelope<T = unknown> {\n version: number;\n type: MessageType;\n from: string; // sender nodeId (short 16-char)\n timestamp: number;\n payload: T;\n}\n\nexport function createMessage<T>(type: MessageType, from: string, payload: T): MessageEnvelope<T> {\n return {\n version: PROTOCOL_VERSION,\n type,\n from,\n timestamp: Date.now(),\n payload,\n };\n}\n\nexport function serializeMessage(msg: MessageEnvelope): string {\n return JSON.stringify(msg);\n}\n\nexport function deserializeMessage(data: string): MessageEnvelope {\n const msg = JSON.parse(data) as MessageEnvelope;\n if (!msg.type || !msg.from || msg.version === undefined) {\n throw new Error(\"Invalid message format\");\n }\n return msg;\n}\n\n// ── Payload types ──────────────────────────────────────────────────\n\nexport interface HandshakePayload {\n nodeId: string;\n publicKey: HexString;\n orgId: string;\n chainHeight: number;\n listenPort: number;\n listenAddress?: string;\n}\n\nexport interface HandshakeAckPayload {\n nodeId: string;\n publicKey: HexString;\n orgId: string;\n chainHeight: number;\n accepted: boolean;\n reason?: string;\n}\n\nexport interface BlockAnnouncePayload {\n block: Block;\n}\n\nexport interface BlockRequestPayload {\n fromHeight: number;\n toHeight: number;\n}\n\nexport interface BlockResponsePayload {\n blocks: Block[];\n}\n\nexport interface TxBroadcastPayload {\n transaction: Transaction;\n}\n\nexport interface TxForwardPayload {\n transaction: Transaction;\n}\n\nexport interface SyncRequestPayload {\n fromHeight: number;\n toHeight: number;\n}\n\nexport interface SyncResponsePayload {\n blocks: Block[];\n hasMore: boolean;\n}\n\nexport interface PeerListPayload {\n peers: {\n nodeId: string;\n publicKey: HexString;\n address: string;\n orgId: string;\n }[];\n}\n\nexport interface PingPayload {\n chainHeight: number;\n}\n\nexport interface PongPayload {\n chainHeight: number;\n}\n\n// ── Raft consensus payloads ────────────────────────────────────────\n\nexport interface RequestVotePayload {\n term: number;\n candidateId: string;\n lastLogIndex: number;\n lastLogTerm: number;\n}\n\nexport interface RequestVoteReplyPayload {\n term: number;\n voteGranted: boolean;\n}\n\nexport interface AppendEntriesPayload {\n term: number;\n leaderId: string;\n prevLogIndex: number;\n prevLogTerm: number;\n entries: RaftLogEntry[];\n leaderCommit: number;\n}\n\nexport interface AppendEntriesReplyPayload {\n term: number;\n success: boolean;\n matchIndex: number;\n}\n\nexport interface RaftLogEntry {\n term: number;\n index: number;\n block: Block;\n}\n","import type WebSocket from \"ws\";\nimport type { HexString } from \"../types.js\";\nimport {\n type MessageEnvelope,\n serializeMessage,\n} from \"./protocol.js\";\n\nexport interface PeerState {\n nodeId: string;\n publicKey: HexString;\n orgId: string;\n address: string;\n chainHeight: number;\n status: \"connecting\" | \"connected\" | \"disconnected\";\n lastSeen: number;\n isInbound: boolean;\n}\n\nexport class Peer {\n readonly nodeId: string;\n publicKey: HexString;\n orgId: string;\n address: string;\n chainHeight: number;\n status: \"connecting\" | \"connected\" | \"disconnected\";\n lastSeen: number;\n isInbound: boolean;\n\n private ws: WebSocket;\n\n constructor(ws: WebSocket, info: Partial<PeerState> & { nodeId: string; isInbound: boolean }) {\n this.ws = ws;\n this.nodeId = info.nodeId;\n this.publicKey = info.publicKey ?? \"\";\n this.orgId = info.orgId ?? \"\";\n this.address = info.address ?? \"\";\n this.chainHeight = info.chainHeight ?? 0;\n this.status = \"connecting\";\n this.lastSeen = Date.now();\n this.isInbound = info.isInbound;\n }\n\n send(msg: MessageEnvelope): void {\n if (this.ws.readyState === this.ws.OPEN) {\n this.ws.send(serializeMessage(msg));\n }\n }\n\n close(): void {\n this.status = \"disconnected\";\n if (this.ws.readyState === this.ws.OPEN || this.ws.readyState === this.ws.CONNECTING) {\n this.ws.close();\n }\n }\n\n getSocket(): WebSocket {\n return this.ws;\n }\n\n updateSeen(): void {\n this.lastSeen = Date.now();\n }\n\n toInfo(): PeerState {\n return {\n nodeId: this.nodeId,\n publicKey: this.publicKey,\n orgId: this.orgId,\n address: this.address,\n chainHeight: this.chainHeight,\n status: this.status,\n lastSeen: this.lastSeen,\n isInbound: this.isInbound,\n };\n }\n}\n","import WebSocket from \"ws\";\nimport type pino from \"pino\";\nimport { deserializeMessage } from \"./protocol.js\";\nimport { Peer } from \"./peer.js\";\nimport type { MessageRouter } from \"./router.js\";\n\nexport interface WsClientOptions {\n log: pino.Logger;\n router: MessageRouter;\n onPeerConnected: (peer: Peer) => void;\n onPeerDisconnected: (peer: Peer) => void;\n reconnectIntervalMs?: number;\n maxReconnectMs?: number;\n}\n\n/**\n * WebSocket client that connects to a remote peer with auto-reconnect.\n */\nexport class WsClient {\n private opts: WsClientOptions;\n private peers = new Map<string, { peer: Peer; reconnectTimer: ReturnType<typeof setTimeout> | null; attempt: number }>();\n private stopped = false;\n\n constructor(opts: WsClientOptions) {\n this.opts = opts;\n }\n\n /** Connect to a peer address. Returns immediately; connection is async. */\n connect(address: string): void {\n if (this.peers.has(address)) return; // Already connecting/connected\n\n this.peers.set(address, { peer: null as unknown as Peer, reconnectTimer: null, attempt: 0 });\n this.doConnect(address);\n }\n\n disconnect(address: string): void {\n const entry = this.peers.get(address);\n if (!entry) return;\n if (entry.reconnectTimer) clearTimeout(entry.reconnectTimer);\n entry.peer?.close();\n this.peers.delete(address);\n }\n\n stop(): void {\n this.stopped = true;\n for (const [, entry] of this.peers) {\n if (entry.reconnectTimer) clearTimeout(entry.reconnectTimer);\n entry.peer?.close();\n }\n this.peers.clear();\n }\n\n private doConnect(address: string): void {\n if (this.stopped) return;\n const entry = this.peers.get(address);\n if (!entry) return;\n\n const ws = new WebSocket(address);\n const tempId = `outbound-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;\n const peer = new Peer(ws, {\n nodeId: tempId,\n address,\n isInbound: false,\n });\n entry.peer = peer;\n\n ws.on(\"open\", () => {\n peer.status = \"connected\";\n entry.attempt = 0;\n this.opts.onPeerConnected(peer);\n });\n\n ws.on(\"message\", async (data: Buffer) => {\n try {\n const msg = deserializeMessage(data.toString());\n peer.updateSeen();\n await this.opts.router.dispatch(msg, peer);\n } catch (err) {\n this.opts.log.warn({ err, peer: peer.nodeId }, \"Failed to handle message from peer\");\n }\n });\n\n ws.on(\"close\", () => {\n peer.status = \"disconnected\";\n this.opts.onPeerDisconnected(peer);\n this.scheduleReconnect(address);\n });\n\n ws.on(\"error\", (err) => {\n this.opts.log.debug({ err: err.message, address }, \"Peer connection error\");\n // 'close' event will fire after this, triggering reconnect\n });\n }\n\n private scheduleReconnect(address: string): void {\n if (this.stopped) return;\n const entry = this.peers.get(address);\n if (!entry) return;\n\n entry.attempt++;\n const baseMs = this.opts.reconnectIntervalMs ?? 1000;\n const maxMs = this.opts.maxReconnectMs ?? 30000;\n const delay = Math.min(baseMs * Math.pow(1.5, entry.attempt - 1), maxMs);\n const jitter = delay * 0.2 * Math.random();\n\n this.opts.log.debug({ address, delay: Math.round(delay + jitter) }, \"Scheduling reconnect\");\n\n entry.reconnectTimer = setTimeout(() => {\n entry.reconnectTimer = null;\n this.doConnect(address);\n }, delay + jitter);\n }\n}\n","import { type MessageEnvelope, MessageType } from \"./protocol.js\";\nimport type { Peer } from \"./peer.js\";\n\nexport type MessageHandler = (msg: MessageEnvelope, peer: Peer) => void | Promise<void>;\n\n/**\n * Routes incoming messages to registered handlers by message type.\n */\nexport class MessageRouter {\n private handlers = new Map<MessageType, MessageHandler[]>();\n\n on(type: MessageType, handler: MessageHandler): void {\n const list = this.handlers.get(type) ?? [];\n list.push(handler);\n this.handlers.set(type, list);\n }\n\n off(type: MessageType, handler: MessageHandler): void {\n const list = this.handlers.get(type);\n if (!list) return;\n const idx = list.indexOf(handler);\n if (idx >= 0) list.splice(idx, 1);\n }\n\n async dispatch(msg: MessageEnvelope, peer: Peer): Promise<void> {\n const handlers = this.handlers.get(msg.type);\n if (!handlers || handlers.length === 0) return;\n for (const handler of handlers) {\n await handler(msg, peer);\n }\n }\n}\n","import type pino from \"pino\";\nimport type { Block } from \"../types.js\";\nimport type { PeerManager } from \"./peer-manager.js\";\nimport type { Peer } from \"./peer.js\";\nimport {\n MessageType,\n createMessage,\n type SyncRequestPayload,\n type SyncResponsePayload,\n type MessageEnvelope,\n} from \"./protocol.js\";\n\nconst SYNC_BATCH_SIZE = 50;\n\nexport interface SyncOptions {\n nodeId: string;\n log: pino.Logger;\n peerManager: PeerManager;\n getChainHeight: () => number;\n getBlocks: (from: number, to: number) => Block[];\n applyBlock: (block: Block) => void;\n}\n\n/**\n * Block sync protocol. Fetches missing blocks from peers to catch up.\n */\nexport class BlockSync {\n private opts: SyncOptions;\n private syncing = false;\n private pendingResolve: ((blocks: Block[]) => void) | null = null;\n\n constructor(opts: SyncOptions) {\n this.opts = opts;\n\n // Register handlers on the peer manager's router\n opts.peerManager.router.on(MessageType.SyncRequest, this.handleSyncRequest.bind(this));\n opts.peerManager.router.on(MessageType.SyncResponse, this.handleSyncResponse.bind(this));\n }\n\n /** Sync from peers if they have a higher chain. */\n async syncFromPeers(): Promise<void> {\n if (this.syncing) return;\n\n const peers = this.opts.peerManager.getConnectedPeers();\n if (peers.length === 0) return;\n\n // Find the peer with highest chain\n let bestPeer: Peer | null = null;\n let bestHeight = this.opts.getChainHeight();\n\n for (const peer of peers) {\n if (peer.chainHeight > bestHeight) {\n bestHeight = peer.chainHeight;\n bestPeer = peer;\n }\n }\n\n if (!bestPeer) return; // We're already at the highest\n\n this.syncing = true;\n this.opts.log.info(\n { peerId: bestPeer.nodeId, peerHeight: bestHeight, localHeight: this.opts.getChainHeight() },\n \"Starting sync\",\n );\n\n try {\n let currentHeight = this.opts.getChainHeight();\n\n while (currentHeight < bestHeight) {\n const from = currentHeight + 1;\n const to = Math.min(from + SYNC_BATCH_SIZE - 1, bestHeight);\n\n const blocks = await this.requestBlocks(bestPeer, from, to);\n if (blocks.length === 0) break;\n\n for (const block of blocks) {\n this.opts.applyBlock(block);\n }\n\n currentHeight = this.opts.getChainHeight();\n this.opts.log.debug({ height: currentHeight, target: bestHeight }, \"Sync progress\");\n }\n\n this.opts.log.info({ height: this.opts.getChainHeight() }, \"Sync complete\");\n } catch (err) {\n this.opts.log.error({ err }, \"Sync failed\");\n } finally {\n this.syncing = false;\n }\n }\n\n isSyncing(): boolean {\n return this.syncing;\n }\n\n /** Request blocks from a specific peer. Returns a promise that resolves when response arrives. */\n private requestBlocks(peer: Peer, fromHeight: number, toHeight: number): Promise<Block[]> {\n return new Promise((resolve) => {\n // Set up one-shot response handler\n this.pendingResolve = resolve;\n\n const payload: SyncRequestPayload = { fromHeight, toHeight };\n peer.send(createMessage(MessageType.SyncRequest, this.opts.nodeId, payload));\n\n // Timeout after 10 seconds\n setTimeout(() => {\n if (this.pendingResolve === resolve) {\n this.pendingResolve = null;\n resolve([]);\n }\n }, 10000);\n });\n }\n\n /** Handle incoming sync request: send requested blocks. */\n private handleSyncRequest(msg: MessageEnvelope, peer: Peer): void {\n const payload = msg.payload as SyncRequestPayload;\n const blocks = this.opts.getBlocks(payload.fromHeight, payload.toHeight);\n\n const response: SyncResponsePayload = {\n blocks,\n hasMore: payload.toHeight < this.opts.getChainHeight(),\n };\n\n peer.send(createMessage(MessageType.SyncResponse, this.opts.nodeId, response));\n }\n\n /** Handle incoming sync response: resolve pending request. */\n private handleSyncResponse(msg: MessageEnvelope, _peer: Peer): void {\n const payload = msg.payload as SyncResponsePayload;\n if (this.pendingResolve) {\n const resolve = this.pendingResolve;\n this.pendingResolve = null;\n resolve(payload.blocks);\n }\n }\n}\n","import type pino from \"pino\";\nimport { EventEmitter } from \"node:events\";\nimport type { Block, Transaction } from \"../../types.js\";\nimport { RaftRole, type ConsensusState, type IConsensus } from \"../types.js\";\nimport { RaftTimer } from \"./raft-timer.js\";\nimport { RaftLog } from \"./raft-log.js\";\nimport type { PeerManager } from \"../../network/peer-manager.js\";\nimport {\n MessageType,\n createMessage,\n type MessageEnvelope,\n type RequestVotePayload,\n type RequestVoteReplyPayload,\n type AppendEntriesPayload,\n type AppendEntriesReplyPayload,\n type RaftLogEntry,\n type TxForwardPayload,\n} from \"../../network/protocol.js\";\n\nexport interface RaftNodeOptions {\n nodeId: string;\n peerManager: PeerManager;\n log: pino.Logger;\n blockTimeMs: number;\n}\n\n/**\n * Raft consensus implementation.\n *\n * Key simplification: Raft log entries ARE block proposals.\n * A committed entry directly becomes a finalized block.\n */\nexport class RaftNode extends EventEmitter implements IConsensus {\n private opts: RaftNodeOptions;\n\n // Raft state\n private role: RaftRole = RaftRole.Follower;\n private currentTerm = 0;\n private votedFor: string | null = null;\n private leaderId: string | null = null;\n private raftLog = new RaftLog();\n private commitIndex = 0;\n private lastApplied = 0;\n\n // Leader state\n private nextIndex = new Map<string, number>(); // peer -> next log index to send\n private matchIndex = new Map<string, number>(); // peer -> highest replicated log index\n\n // Components\n private timer: RaftTimer;\n private blockProposalTimer: ReturnType<typeof setInterval> | null = null;\n\n // Callbacks set by the node orchestrator\n onBlockCommitted: ((block: Block) => void) | null = null;\n onTransactionReceived: ((tx: Transaction) => void) | null = null;\n\n constructor(opts: RaftNodeOptions) {\n super();\n this.opts = opts;\n\n this.timer = new RaftTimer({\n onElectionTimeout: () => this.startElection(),\n onHeartbeat: () => this.sendHeartbeats(),\n });\n\n // Register consensus message handlers\n const router = opts.peerManager.router;\n router.on(MessageType.ConsensusRequestVote, (msg) => this.handleRequestVote(msg));\n router.on(MessageType.ConsensusRequestVoteReply, (msg) => this.handleRequestVoteReply(msg));\n router.on(MessageType.ConsensusAppendEntries, (msg) => this.handleAppendEntries(msg));\n router.on(MessageType.ConsensusAppendEntriesReply, (msg) => this.handleAppendEntriesReply(msg));\n router.on(MessageType.TxForward, (msg, _peer) => {\n const payload = msg.payload as TxForwardPayload;\n if (this.role === RaftRole.Leader && this.onTransactionReceived) {\n this.onTransactionReceived(payload.transaction);\n }\n });\n }\n\n start(): void {\n this.role = RaftRole.Follower;\n this.timer.resetElectionTimer();\n this.opts.log.info({ nodeId: this.opts.nodeId }, \"Raft started as follower\");\n }\n\n stop(): void {\n this.timer.stopAll();\n if (this.blockProposalTimer) {\n clearInterval(this.blockProposalTimer);\n this.blockProposalTimer = null;\n }\n }\n\n isLeader(): boolean {\n return this.role === RaftRole.Leader;\n }\n\n getLeaderId(): string | null {\n return this.leaderId;\n }\n\n getState(): ConsensusState {\n return {\n role: this.role,\n term: this.currentTerm,\n leaderId: this.leaderId,\n votedFor: this.votedFor,\n commitIndex: this.commitIndex,\n };\n }\n\n /** Called by the node to propose a block (only works when leader). */\n proposeBlock(block: Block): void {\n if (this.role !== RaftRole.Leader) return;\n\n const entry: RaftLogEntry = {\n term: this.currentTerm,\n index: this.raftLog.getLastIndex() + 1,\n block,\n };\n\n this.raftLog.append(entry);\n\n // Update own matchIndex\n this.matchIndex.set(this.opts.nodeId, entry.index);\n\n // Replicate to peers immediately\n this.sendHeartbeats();\n\n // Check if we can commit (single-node cluster commits immediately)\n this.advanceCommitIndex();\n }\n\n /** Forward a transaction to the current leader. */\n forwardToLeader(tx: Transaction): void {\n if (this.leaderId && this.leaderId !== this.opts.nodeId) {\n const payload: TxForwardPayload = { transaction: tx };\n this.opts.peerManager.sendTo(\n this.leaderId,\n createMessage(MessageType.TxForward, this.opts.nodeId, payload),\n );\n }\n }\n\n // ── Election ────────────────────────────────────────────────────\n\n private startElection(): void {\n this.currentTerm++;\n this.role = RaftRole.Candidate;\n this.votedFor = this.opts.nodeId;\n this.leaderId = null;\n\n const peers = this.opts.peerManager.getKnownNodeIds();\n const totalVoters = peers.length + 1; // +1 for self\n let votesReceived = 1; // Vote for self\n\n this.opts.log.info({ term: this.currentTerm, voters: totalVoters }, \"Starting election\");\n\n // Single-node: win immediately\n if (totalVoters === 1) {\n this.becomeLeader();\n return;\n }\n\n // Store vote handler so we can track votes for this term\n const electionTerm = this.currentTerm;\n\n // Override the RequestVoteReply handler for this election\n this._voteCallback = (granted: boolean) => {\n if (this.currentTerm !== electionTerm || this.role !== RaftRole.Candidate) return;\n if (granted) votesReceived++;\n const majority = Math.floor(totalVoters / 2) + 1;\n if (votesReceived >= majority) {\n this.becomeLeader();\n }\n };\n\n // Send RequestVote to all peers\n const payload: RequestVotePayload = {\n term: this.currentTerm,\n candidateId: this.opts.nodeId,\n lastLogIndex: this.raftLog.getLastIndex(),\n lastLogTerm: this.raftLog.getLastTerm(),\n };\n\n for (const peerId of peers) {\n this.opts.peerManager.sendTo(\n peerId,\n createMessage(MessageType.ConsensusRequestVote, this.opts.nodeId, payload),\n );\n }\n\n // Reset election timer for next election if this one fails\n this.timer.resetElectionTimer();\n }\n\n private _voteCallback: ((granted: boolean) => void) | null = null;\n\n private becomeLeader(): void {\n this.role = RaftRole.Leader;\n this.leaderId = this.opts.nodeId;\n this.timer.stopElectionTimer();\n this.timer.startHeartbeatTimer();\n\n // Initialize leader state\n const nextIdx = this.raftLog.getLastIndex() + 1;\n const peers = this.opts.peerManager.getKnownNodeIds();\n for (const peerId of peers) {\n this.nextIndex.set(peerId, nextIdx);\n this.matchIndex.set(peerId, 0);\n }\n this.matchIndex.set(this.opts.nodeId, this.raftLog.getLastIndex());\n\n this.opts.log.info({ term: this.currentTerm }, \"Became leader\");\n this.emit(\"leader\");\n\n // Send initial heartbeat immediately\n this.sendHeartbeats();\n }\n\n private stepDown(newTerm: number): void {\n this.currentTerm = newTerm;\n this.role = RaftRole.Follower;\n this.votedFor = null;\n this.timer.stopHeartbeatTimer();\n if (this.blockProposalTimer) {\n clearInterval(this.blockProposalTimer);\n this.blockProposalTimer = null;\n }\n this.timer.resetElectionTimer();\n }\n\n // ── RequestVote ─────────────────────────────────────────────────\n\n private handleRequestVote(msg: MessageEnvelope): void {\n const payload = msg.payload as RequestVotePayload;\n let voteGranted = false;\n\n // If the request has a higher term, step down\n if (payload.term > this.currentTerm) {\n this.stepDown(payload.term);\n }\n\n // Grant vote if: same term, haven't voted or voted for this candidate,\n // and candidate's log is at least as up-to-date as ours\n if (\n payload.term === this.currentTerm &&\n (this.votedFor === null || this.votedFor === payload.candidateId) &&\n this.isLogUpToDate(payload.lastLogIndex, payload.lastLogTerm)\n ) {\n voteGranted = true;\n this.votedFor = payload.candidateId;\n this.timer.resetElectionTimer();\n }\n\n const reply: RequestVoteReplyPayload = {\n term: this.currentTerm,\n voteGranted,\n };\n\n this.opts.peerManager.sendTo(\n msg.from,\n createMessage(MessageType.ConsensusRequestVoteReply, this.opts.nodeId, reply),\n );\n }\n\n private handleRequestVoteReply(msg: MessageEnvelope): void {\n const payload = msg.payload as RequestVoteReplyPayload;\n\n if (payload.term > this.currentTerm) {\n this.stepDown(payload.term);\n return;\n }\n\n if (this._voteCallback) {\n this._voteCallback(payload.voteGranted);\n }\n }\n\n private isLogUpToDate(lastLogIndex: number, lastLogTerm: number): boolean {\n const myLastTerm = this.raftLog.getLastTerm();\n const myLastIndex = this.raftLog.getLastIndex();\n\n if (lastLogTerm !== myLastTerm) {\n return lastLogTerm > myLastTerm;\n }\n return lastLogIndex >= myLastIndex;\n }\n\n // ── AppendEntries ───────────────────────────────────────────────\n\n private sendHeartbeats(): void {\n if (this.role !== RaftRole.Leader) return;\n\n const peers = this.opts.peerManager.getKnownNodeIds();\n for (const peerId of peers) {\n this.sendAppendEntries(peerId);\n }\n }\n\n private sendAppendEntries(peerId: string): void {\n const nextIdx = this.nextIndex.get(peerId) ?? this.raftLog.getLastIndex() + 1;\n const prevLogIndex = nextIdx - 1;\n const prevLogTerm = this.raftLog.getTermAt(prevLogIndex);\n const entries = this.raftLog.getEntriesFrom(nextIdx);\n\n const payload: AppendEntriesPayload = {\n term: this.currentTerm,\n leaderId: this.opts.nodeId,\n prevLogIndex,\n prevLogTerm,\n entries,\n leaderCommit: this.commitIndex,\n };\n\n this.opts.peerManager.sendTo(\n peerId,\n createMessage(MessageType.ConsensusAppendEntries, this.opts.nodeId, payload),\n );\n }\n\n private handleAppendEntries(msg: MessageEnvelope): void {\n const payload = msg.payload as AppendEntriesPayload;\n\n // If the leader has a higher term, update\n if (payload.term > this.currentTerm) {\n this.stepDown(payload.term);\n }\n\n // Reject if term is outdated\n if (payload.term < this.currentTerm) {\n this.sendAppendEntriesReply(msg.from, false, 0);\n return;\n }\n\n // Valid leader heartbeat — reset election timer\n this.leaderId = payload.leaderId;\n if (this.role === RaftRole.Candidate) {\n this.role = RaftRole.Follower;\n }\n this.timer.resetElectionTimer();\n\n // Check log consistency\n if (payload.prevLogIndex > 0) {\n const prevTerm = this.raftLog.getTermAt(payload.prevLogIndex);\n if (prevTerm !== payload.prevLogTerm) {\n // Log inconsistency — tell leader to back up\n this.sendAppendEntriesReply(msg.from, false, 0);\n return;\n }\n }\n\n // Append new entries\n for (const entry of payload.entries) {\n const existing = this.raftLog.getEntry(entry.index);\n if (existing) {\n if (existing.term !== entry.term) {\n // Conflict: truncate from here\n this.raftLog.truncateFrom(entry.index);\n this.raftLog.append(entry);\n }\n // Else: already have this entry, skip\n } else {\n this.raftLog.append(entry);\n }\n }\n\n // Update commit index\n if (payload.leaderCommit > this.commitIndex) {\n this.commitIndex = Math.min(payload.leaderCommit, this.raftLog.getLastIndex());\n this.applyCommitted();\n }\n\n this.sendAppendEntriesReply(msg.from, true, this.raftLog.getLastIndex());\n }\n\n private sendAppendEntriesReply(to: string, success: boolean, matchIndex: number): void {\n const reply: AppendEntriesReplyPayload = {\n term: this.currentTerm,\n success,\n matchIndex,\n };\n this.opts.peerManager.sendTo(\n to,\n createMessage(MessageType.ConsensusAppendEntriesReply, this.opts.nodeId, reply),\n );\n }\n\n private handleAppendEntriesReply(msg: MessageEnvelope): void {\n if (this.role !== RaftRole.Leader) return;\n\n const payload = msg.payload as AppendEntriesReplyPayload;\n\n if (payload.term > this.currentTerm) {\n this.stepDown(payload.term);\n return;\n }\n\n if (payload.success) {\n this.nextIndex.set(msg.from, payload.matchIndex + 1);\n this.matchIndex.set(msg.from, payload.matchIndex);\n this.advanceCommitIndex();\n } else {\n // Decrement nextIndex and retry\n const current = this.nextIndex.get(msg.from) ?? 1;\n this.nextIndex.set(msg.from, Math.max(1, current - 1));\n // Retry immediately\n this.sendAppendEntries(msg.from);\n }\n }\n\n // ── Commit & Apply ──────────────────────────────────────────────\n\n private advanceCommitIndex(): void {\n if (this.role !== RaftRole.Leader) return;\n\n const allNodeIds = [...this.opts.peerManager.getKnownNodeIds(), this.opts.nodeId];\n const total = allNodeIds.length;\n const majority = Math.floor(total / 2) + 1;\n\n // Find the highest index replicated on a majority\n for (let n = this.raftLog.getLastIndex(); n > this.commitIndex; n--) {\n const entry = this.raftLog.getEntry(n);\n if (!entry || entry.term !== this.currentTerm) continue;\n\n let replicatedCount = 0;\n for (const nodeId of allNodeIds) {\n const match = nodeId === this.opts.nodeId\n ? this.raftLog.getLastIndex()\n : (this.matchIndex.get(nodeId) ?? 0);\n if (match >= n) replicatedCount++;\n }\n\n if (replicatedCount >= majority) {\n this.commitIndex = n;\n this.applyCommitted();\n break;\n }\n }\n }\n\n private applyCommitted(): void {\n while (this.lastApplied < this.commitIndex) {\n this.lastApplied++;\n const entry = this.raftLog.getEntry(this.lastApplied);\n if (entry && this.onBlockCommitted) {\n this.onBlockCommitted(entry.block);\n }\n }\n }\n}\n","/**\n * Raft timer with randomized election timeout and heartbeat.\n */\nexport class RaftTimer {\n private electionTimer: ReturnType<typeof setTimeout> | null = null;\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n\n private electionTimeoutMinMs: number;\n private electionTimeoutMaxMs: number;\n private heartbeatIntervalMs: number;\n\n private onElectionTimeout: () => void;\n private onHeartbeat: () => void;\n\n constructor(opts: {\n electionTimeoutMinMs?: number;\n electionTimeoutMaxMs?: number;\n heartbeatIntervalMs?: number;\n onElectionTimeout: () => void;\n onHeartbeat: () => void;\n }) {\n this.electionTimeoutMinMs = opts.electionTimeoutMinMs ?? 1500;\n this.electionTimeoutMaxMs = opts.electionTimeoutMaxMs ?? 3000;\n this.heartbeatIntervalMs = opts.heartbeatIntervalMs ?? 500;\n this.onElectionTimeout = opts.onElectionTimeout;\n this.onHeartbeat = opts.onHeartbeat;\n }\n\n /** Reset the election timeout (called on heartbeat received or vote granted). */\n resetElectionTimer(): void {\n this.stopElectionTimer();\n const timeout = this.randomElectionTimeout();\n this.electionTimer = setTimeout(() => {\n this.onElectionTimeout();\n }, timeout);\n }\n\n stopElectionTimer(): void {\n if (this.electionTimer) {\n clearTimeout(this.electionTimer);\n this.electionTimer = null;\n }\n }\n\n /** Start the heartbeat timer (called when becoming leader). */\n startHeartbeatTimer(): void {\n this.stopHeartbeatTimer();\n this.heartbeatTimer = setInterval(() => {\n this.onHeartbeat();\n }, this.heartbeatIntervalMs);\n }\n\n stopHeartbeatTimer(): void {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n }\n\n stopAll(): void {\n this.stopElectionTimer();\n this.stopHeartbeatTimer();\n }\n\n private randomElectionTimeout(): number {\n return (\n this.electionTimeoutMinMs +\n Math.random() * (this.electionTimeoutMaxMs - this.electionTimeoutMinMs)\n );\n }\n}\n","import type { RaftLogEntry } from \"../../network/protocol.js\";\n\n/**\n * In-memory Raft log. Entries are block proposals.\n * Each committed entry becomes a finalized block.\n */\nexport class RaftLog {\n private entries: RaftLogEntry[] = [];\n\n /** Append an entry to the log. */\n append(entry: RaftLogEntry): void {\n this.entries.push(entry);\n }\n\n /** Get entry at a specific index (1-based). */\n getEntry(index: number): RaftLogEntry | undefined {\n return this.entries.find((e) => e.index === index);\n }\n\n /** Get the last log index. */\n getLastIndex(): number {\n return this.entries.length > 0 ? this.entries[this.entries.length - 1]!.index : 0;\n }\n\n /** Get the last log term. */\n getLastTerm(): number {\n return this.entries.length > 0 ? this.entries[this.entries.length - 1]!.term : 0;\n }\n\n /** Get entries from startIndex (inclusive). */\n getEntriesFrom(startIndex: number): RaftLogEntry[] {\n return this.entries.filter((e) => e.index >= startIndex);\n }\n\n /** Get the term at a given index. Returns 0 if index not found. */\n getTermAt(index: number): number {\n if (index === 0) return 0;\n const entry = this.entries.find((e) => e.index === index);\n return entry?.term ?? 0;\n }\n\n /** Truncate log from index (inclusive) onwards. Used when log conflicts detected. */\n truncateFrom(index: number): void {\n this.entries = this.entries.filter((e) => e.index < index);\n }\n\n /** Get number of entries. */\n length(): number {\n return this.entries.length;\n }\n}\n","import type { StateStore } from \"../storage/state-store.js\";\nimport type { ContractContext } from \"./types.js\";\n\nexport interface ContextOptions {\n stateStore: StateStore;\n sender: string;\n blockHeight: number;\n timestamp: number;\n}\n\n/**\n * Creates a ContractContext that contracts use to interact with the ledger.\n * All state mutations go through the StateStore.\n */\nexport function createContractContext(opts: ContextOptions): ContractContext & { getLogs(): string[] } {\n const logs: string[] = [];\n\n return {\n get(key: string): unknown | null {\n const entry = opts.stateStore.get(key);\n return entry ? entry.value : null;\n },\n\n set(key: string, value: unknown): void {\n opts.stateStore.set(key, value, opts.sender, opts.blockHeight);\n },\n\n del(key: string): void {\n opts.stateStore.delete(key);\n },\n\n get sender() {\n return opts.sender;\n },\n\n get blockHeight() {\n return opts.blockHeight;\n },\n\n get timestamp() {\n return opts.timestamp;\n },\n\n log(message: string): void {\n logs.push(message);\n },\n\n getLogs(): string[] {\n return logs;\n },\n };\n}\n","import type { ContractContext, ContractModule } from \"./types.js\";\n\nconst MAX_EXECUTION_MS = 5000;\n\n/**\n * Compile contract source code into a callable module.\n *\n * Contracts are JavaScript/TypeScript functions. The source code should export\n * methods as properties of a returned object. Example:\n *\n * ```\n * return {\n * init(ctx) { ctx.set(\"counter\", 0); },\n * increment(ctx, amount) {\n * const val = ctx.get(\"counter\") || 0;\n * ctx.set(\"counter\", val + amount);\n * return val + amount;\n * }\n * }\n * ```\n */\nexport function compileContract(source: string): ContractModule {\n // Create a sandboxed function with limited globals\n const wrapper = new Function(\n // No arguments — the contract returns its methods\n `\"use strict\";\n // Freeze dangerous globals\n const process = undefined;\n const require = undefined;\n const __dirname = undefined;\n const __filename = undefined;\n const global = undefined;\n const globalThis = undefined;\n const fetch = undefined;\n const setTimeout = undefined;\n const setInterval = undefined;\n const import_meta = undefined;\n\n ${source}`,\n );\n\n const mod = wrapper();\n\n if (!mod || typeof mod !== \"object\") {\n throw new Error(\"Contract must return an object with methods\");\n }\n\n // Validate all exports are functions\n for (const [key, val] of Object.entries(mod)) {\n if (typeof val !== \"function\") {\n throw new Error(`Contract export \"${key}\" must be a function, got ${typeof val}`);\n }\n }\n\n return mod as ContractModule;\n}\n\n/**\n * Execute a contract method with a context and arguments.\n * Enforces a timeout to prevent infinite loops.\n */\nexport function executeContract(\n mod: ContractModule,\n method: string,\n ctx: ContractContext,\n args: unknown[] = [],\n): unknown {\n const fn = mod[method];\n if (!fn) {\n throw new Error(`Contract method \"${method}\" not found`);\n }\n\n // Simple timeout enforcement via synchronous deadline check\n // (True async timeout requires worker_threads; this is adequate for M3)\n const deadline = Date.now() + MAX_EXECUTION_MS;\n\n // Create a proxy on ctx that checks deadline on each state access\n const guardedCtx: ContractContext = {\n get(key: string) {\n if (Date.now() > deadline) throw new Error(\"Contract execution timeout\");\n return ctx.get(key);\n },\n set(key: string, value: unknown) {\n if (Date.now() > deadline) throw new Error(\"Contract execution timeout\");\n ctx.set(key, value);\n },\n del(key: string) {\n if (Date.now() > deadline) throw new Error(\"Contract execution timeout\");\n ctx.del(key);\n },\n get sender() { return ctx.sender; },\n get blockHeight() { return ctx.blockHeight; },\n get timestamp() { return ctx.timestamp; },\n log(message: string) { ctx.log(message); },\n };\n\n return fn(guardedCtx, ...args);\n}\n","import type { StateStore } from \"../storage/state-store.js\";\nimport type { ContractInstance, ContractModule } from \"./types.js\";\nimport { compileContract, executeContract } from \"./runtime.js\";\n\nconst CONTRACT_PREFIX = \"_contract:\";\nconst CONTRACT_CODE_PREFIX = \"_contract_code:\";\n\n/**\n * Manages deployed contracts. Contract metadata and code are stored in world state\n * with reserved key prefixes.\n */\nexport class ContractRegistry {\n private compiled = new Map<string, ContractModule>();\n private stateStore: StateStore;\n\n constructor(stateStore: StateStore) {\n this.stateStore = stateStore;\n }\n\n /** Deploy a new contract or upgrade an existing one. */\n deploy(\n name: string,\n version: string,\n code: string,\n deployedBy: string,\n blockHeight: number,\n ): void {\n // Validate by compiling\n const mod = compileContract(code);\n this.compiled.set(name, mod);\n\n // Store metadata\n const instance: ContractInstance = {\n name,\n version,\n deployedAt: Date.now(),\n deployedBy,\n };\n this.stateStore.set(`${CONTRACT_PREFIX}${name}`, instance, deployedBy, blockHeight);\n this.stateStore.set(`${CONTRACT_CODE_PREFIX}${name}`, code, deployedBy, blockHeight);\n }\n\n /** Get a compiled contract module, loading from state if needed. */\n getModule(name: string): ContractModule | null {\n // Check cache\n let mod = this.compiled.get(name);\n if (mod) return mod;\n\n // Load from state\n const codeEntry = this.stateStore.get(`${CONTRACT_CODE_PREFIX}${name}`);\n if (!codeEntry) return null;\n\n mod = compileContract(codeEntry.value as string);\n this.compiled.set(name, mod);\n return mod;\n }\n\n /** Get contract metadata. */\n getInstance(name: string): ContractInstance | null {\n const entry = this.stateStore.get(`${CONTRACT_PREFIX}${name}`);\n return entry ? (entry.value as ContractInstance) : null;\n }\n\n /** Invoke a method on a deployed contract. */\n invoke(\n contractName: string,\n method: string,\n ctx: import(\"./types.js\").ContractContext,\n args: unknown[] = [],\n ): unknown {\n const mod = this.getModule(contractName);\n if (!mod) {\n throw new Error(`Contract \"${contractName}\" not found`);\n }\n return executeContract(mod, method, ctx, args);\n }\n\n /** List all deployed contracts. */\n listContracts(): ContractInstance[] {\n const results = this.stateStore.query(\n `SELECT value FROM world_state WHERE key LIKE ?`,\n [`${CONTRACT_PREFIX}%`],\n );\n return results\n .map((r) => {\n try {\n return JSON.parse(r.value as string) as ContractInstance;\n } catch {\n return null;\n }\n })\n .filter((c): c is ContractInstance => c !== null);\n }\n\n /** Clear compiled cache (useful after chain reorg). */\n clearCache(): void {\n this.compiled.clear();\n }\n}\n","/**\n * Built-in contract: token transfer.\n *\n * State keys: \"balance:<address>\" -> number\n */\nexport const TRANSFER_CONTRACT = `\nreturn {\n init(ctx, initialBalance) {\n ctx.set(\"balance:\" + ctx.sender, initialBalance || 0);\n ctx.log(\"Account initialized with balance: \" + (initialBalance || 0));\n },\n\n mint(ctx, amount) {\n if (typeof amount !== \"number\" || amount <= 0) throw new Error(\"Invalid amount\");\n const key = \"balance:\" + ctx.sender;\n const current = ctx.get(key) || 0;\n ctx.set(key, current + amount);\n ctx.log(\"Minted \" + amount + \" to \" + ctx.sender);\n return current + amount;\n },\n\n transfer(ctx, to, amount) {\n if (typeof amount !== \"number\" || amount <= 0) throw new Error(\"Invalid amount\");\n if (!to) throw new Error(\"Recipient required\");\n\n const fromKey = \"balance:\" + ctx.sender;\n const toKey = \"balance:\" + to;\n\n const fromBalance = ctx.get(fromKey) || 0;\n if (fromBalance < amount) throw new Error(\"Insufficient balance\");\n\n const toBalance = ctx.get(toKey) || 0;\n ctx.set(fromKey, fromBalance - amount);\n ctx.set(toKey, toBalance + amount);\n ctx.log(\"Transfer \" + amount + \" from \" + ctx.sender + \" to \" + to);\n },\n\n balance(ctx, address) {\n const key = \"balance:\" + (address || ctx.sender);\n return ctx.get(key) || 0;\n }\n}\n`;\n\n/**\n * Built-in contract: simple key-value store with ownership.\n */\nexport const KV_STORE_CONTRACT = `\nreturn {\n set(ctx, key, value) {\n const fullKey = \"kv:\" + key;\n const existing = ctx.get(fullKey + \":owner\");\n if (existing && existing !== ctx.sender) throw new Error(\"Not owner of key: \" + key);\n ctx.set(fullKey, value);\n ctx.set(fullKey + \":owner\", ctx.sender);\n },\n\n get(ctx, key) {\n return ctx.get(\"kv:\" + key);\n },\n\n del(ctx, key) {\n const owner = ctx.get(\"kv:\" + key + \":owner\");\n if (owner && owner !== ctx.sender) throw new Error(\"Not owner of key: \" + key);\n ctx.del(\"kv:\" + key);\n ctx.del(\"kv:\" + key + \":owner\");\n }\n}\n`;\n","export enum ProposalType {\n AddPeer = \"add-peer\",\n RemovePeer = \"remove-peer\",\n UpdateConfig = \"update-config\",\n UpgradeContract = \"upgrade-contract\",\n Custom = \"custom\",\n}\n\nexport enum ProposalStatus {\n Active = \"active\",\n Approved = \"approved\",\n Rejected = \"rejected\",\n Expired = \"expired\",\n}\n\nexport interface Proposal {\n id: string;\n type: ProposalType;\n title: string;\n description: string;\n proposer: string; // public key\n action: Record<string, unknown>; // type-specific action data\n status: ProposalStatus;\n createdAt: number;\n expiresAt: number;\n votes: Record<string, boolean>; // publicKey -> approve/reject\n}\n\nexport function createProposal(opts: {\n type: ProposalType;\n title: string;\n description: string;\n proposer: string;\n action: Record<string, unknown>;\n votingPeriodMs?: number;\n}): Proposal {\n const now = Date.now();\n const votingPeriod = opts.votingPeriodMs ?? 24 * 60 * 60 * 1000; // 24 hours default\n\n return {\n id: `proposal:${now}:${Math.random().toString(36).slice(2, 8)}`,\n type: opts.type,\n title: opts.title,\n description: opts.description,\n proposer: opts.proposer,\n action: opts.action,\n status: ProposalStatus.Active,\n createdAt: now,\n expiresAt: now + votingPeriod,\n votes: { [opts.proposer]: true }, // Proposer auto-votes yes\n };\n}\n","import type { Proposal } from \"./proposal.js\";\nimport { ProposalStatus } from \"./proposal.js\";\n\nexport interface VoteResult {\n approved: number;\n rejected: number;\n total: number;\n quorumReached: boolean;\n passed: boolean;\n}\n\n/**\n * Tally votes on a proposal.\n * @param proposal - The proposal to tally\n * @param totalVoters - Total number of eligible voters in the network\n * @param quorumPercent - Minimum percentage of voters required (default 50%)\n */\nexport function tallyVotes(\n proposal: Proposal,\n totalVoters: number,\n quorumPercent = 50,\n): VoteResult {\n const votes = Object.values(proposal.votes);\n const approved = votes.filter((v) => v === true).length;\n const rejected = votes.filter((v) => v === false).length;\n const total = votes.length;\n\n const quorumNeeded = Math.ceil((totalVoters * quorumPercent) / 100);\n const quorumReached = total >= quorumNeeded;\n const passed = quorumReached && approved > rejected;\n\n return { approved, rejected, total, quorumReached, passed };\n}\n\n/** Add a vote to a proposal. Returns updated proposal. */\nexport function addVote(\n proposal: Proposal,\n voter: string,\n vote: boolean,\n): Proposal {\n if (proposal.status !== ProposalStatus.Active) {\n throw new Error(`Proposal ${proposal.id} is not active (status: ${proposal.status})`);\n }\n if (Date.now() > proposal.expiresAt) {\n throw new Error(`Proposal ${proposal.id} has expired`);\n }\n\n return {\n ...proposal,\n votes: { ...proposal.votes, [voter]: vote },\n };\n}\n\n/** Check if a proposal has expired. */\nexport function isExpired(proposal: Proposal): boolean {\n return Date.now() > proposal.expiresAt;\n}\n","import type { StateStore } from \"../storage/state-store.js\";\nimport {\n type Proposal,\n ProposalStatus,\n ProposalType,\n createProposal,\n} from \"./proposal.js\";\nimport { tallyVotes, addVote, isExpired } from \"./voting.js\";\n\nconst PROPOSAL_PREFIX = \"_gov:proposal:\";\n\n/**\n * Governor: manages the lifecycle of governance proposals.\n * Proposals are stored in world state with a reserved key prefix.\n */\nexport class Governor {\n private stateStore: StateStore;\n\n constructor(stateStore: StateStore) {\n this.stateStore = stateStore;\n }\n\n /** Create and store a new proposal. */\n propose(opts: {\n type: ProposalType;\n title: string;\n description: string;\n proposer: string;\n action: Record<string, unknown>;\n blockHeight: number;\n votingPeriodMs?: number;\n }): Proposal {\n const proposal = createProposal({\n type: opts.type,\n title: opts.title,\n description: opts.description,\n proposer: opts.proposer,\n action: opts.action,\n votingPeriodMs: opts.votingPeriodMs,\n });\n\n this.stateStore.set(\n `${PROPOSAL_PREFIX}${proposal.id}`,\n proposal,\n opts.proposer,\n opts.blockHeight,\n );\n\n return proposal;\n }\n\n /** Cast a vote on a proposal. */\n vote(proposalId: string, voter: string, approve: boolean, blockHeight: number): Proposal {\n const proposal = this.getProposal(proposalId);\n if (!proposal) throw new Error(`Proposal not found: ${proposalId}`);\n\n const updated = addVote(proposal, voter, approve);\n this.stateStore.set(\n `${PROPOSAL_PREFIX}${proposalId}`,\n updated,\n voter,\n blockHeight,\n );\n\n return updated;\n }\n\n /**\n * Evaluate a proposal: check if it should be approved, rejected, or expired.\n * Returns the action to execute if approved, null otherwise.\n */\n evaluate(proposalId: string, totalVoters: number, blockHeight: number): {\n status: ProposalStatus;\n action: Record<string, unknown> | null;\n } {\n const proposal = this.getProposal(proposalId);\n if (!proposal) throw new Error(`Proposal not found: ${proposalId}`);\n\n if (proposal.status !== ProposalStatus.Active) {\n return { status: proposal.status, action: null };\n }\n\n // Check expiration\n if (isExpired(proposal)) {\n const expired = { ...proposal, status: ProposalStatus.Expired };\n this.stateStore.set(\n `${PROPOSAL_PREFIX}${proposalId}`,\n expired,\n proposal.proposer,\n blockHeight,\n );\n return { status: ProposalStatus.Expired, action: null };\n }\n\n // Tally votes\n const result = tallyVotes(proposal, totalVoters);\n\n if (result.quorumReached) {\n const newStatus = result.passed ? ProposalStatus.Approved : ProposalStatus.Rejected;\n const updated = { ...proposal, status: newStatus };\n this.stateStore.set(\n `${PROPOSAL_PREFIX}${proposalId}`,\n updated,\n proposal.proposer,\n blockHeight,\n );\n\n return {\n status: newStatus,\n action: result.passed ? proposal.action : null,\n };\n }\n\n return { status: ProposalStatus.Active, action: null };\n }\n\n /** Get a proposal by ID. */\n getProposal(proposalId: string): Proposal | null {\n const entry = this.stateStore.get(`${PROPOSAL_PREFIX}${proposalId}`);\n return entry ? (entry.value as Proposal) : null;\n }\n\n /** List all proposals. */\n listProposals(): Proposal[] {\n const results = this.stateStore.query(\n `SELECT value FROM world_state WHERE key LIKE ?`,\n [`${PROPOSAL_PREFIX}%`],\n );\n return results\n .map((r) => {\n try {\n return JSON.parse(r.value as string) as Proposal;\n } catch {\n return null;\n }\n })\n .filter((p): p is Proposal => p !== null);\n }\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { Hono } from \"hono\";\nimport { cors } from \"hono/cors\";\nimport type { MiniLedgerNode } from \"../node.js\";\nimport { requestLogger } from \"./middleware/logging.js\";\nimport { healthRoutes } from \"./routes/health.js\";\nimport { blockRoutes } from \"./routes/blocks.js\";\nimport { transactionRoutes } from \"./routes/transactions.js\";\nimport { stateRoutes } from \"./routes/state.js\";\nimport { identityRoutes } from \"./routes/identity.js\";\nimport { networkRoutes } from \"./routes/network.js\";\nimport { governanceRoutes } from \"./routes/governance.js\";\n\n/** Find the dashboard directory — works from both src/ and dist/. */\nfunction findDashboardDir(): string | null {\n // Try relative to this file (in dist/)\n const candidates = [\n path.resolve(import.meta.dirname ?? \".\", \"..\", \"dashboard\"),\n path.resolve(import.meta.dirname ?? \".\", \"..\", \"..\", \"dashboard\"),\n path.resolve(process.cwd(), \"dashboard\"),\n ];\n for (const dir of candidates) {\n if (fs.existsSync(path.join(dir, \"index.html\"))) return dir;\n }\n return null;\n}\n\nconst MIME_TYPES: Record<string, string> = {\n \".html\": \"text/html\",\n \".css\": \"text/css\",\n \".js\": \"application/javascript\",\n \".json\": \"application/json\",\n \".png\": \"image/png\",\n \".svg\": \"image/svg+xml\",\n};\n\nexport function createApp(node: MiniLedgerNode): Hono {\n const app = new Hono();\n\n // Global middleware\n if (node.config.api.cors) {\n app.use(\"*\", cors());\n }\n app.use(\"*\", requestLogger());\n\n // Mount API routes\n app.route(\"/\", healthRoutes(node));\n app.route(\"/\", blockRoutes(node));\n app.route(\"/\", transactionRoutes(node));\n app.route(\"/\", stateRoutes(node));\n app.route(\"/\", identityRoutes(node));\n app.route(\"/\", networkRoutes(node));\n app.route(\"/\", governanceRoutes(node));\n\n // Serve dashboard static files\n const dashboardDir = findDashboardDir();\n if (dashboardDir) {\n app.get(\"/dashboard\", (c) => {\n const html = fs.readFileSync(path.join(dashboardDir, \"index.html\"), \"utf-8\");\n return c.html(html);\n });\n\n app.get(\"/dashboard/:file\", (c) => {\n const file = c.req.param(\"file\");\n const filePath = path.join(dashboardDir, file);\n if (!fs.existsSync(filePath)) return c.notFound();\n const ext = path.extname(file);\n const mime = MIME_TYPES[ext] ?? \"application/octet-stream\";\n const content = fs.readFileSync(filePath, \"utf-8\");\n return c.text(content, 200, { \"Content-Type\": mime });\n });\n }\n\n // Root — redirect to dashboard\n app.get(\"/\", (c) => {\n if (dashboardDir) {\n return c.redirect(\"/dashboard\");\n }\n return c.json({\n name: \"miniledger\",\n version: \"0.1.0\",\n status: node.isRunning() ? \"running\" : \"stopped\",\n });\n });\n\n return app;\n}\n","import type { MiddlewareHandler } from \"hono\";\n\nexport function requestLogger(): MiddlewareHandler {\n return async (c, next) => {\n const start = Date.now();\n await next();\n const ms = Date.now() - start;\n // Only log non-health endpoints to reduce noise\n if (!c.req.path.includes(\"/health\")) {\n console.log(`${c.req.method} ${c.req.path} ${c.res.status} ${ms}ms`);\n }\n };\n}\n","import { Hono } from \"hono\";\nimport type { MiniLedgerNode } from \"../../node.js\";\n\nexport function healthRoutes(node: MiniLedgerNode): Hono {\n const app = new Hono();\n\n app.get(\"/health\", (c) => {\n return c.json({\n status: node.isRunning() ? \"ok\" : \"stopped\",\n timestamp: Date.now(),\n });\n });\n\n app.get(\"/status\", (c) => {\n return c.json(node.getStatus());\n });\n\n return app;\n}\n","import { Hono } from \"hono\";\nimport type { MiniLedgerNode } from \"../../node.js\";\n\nexport function blockRoutes(node: MiniLedgerNode): Hono {\n const app = new Hono();\n\n app.get(\"/blocks/latest\", async (c) => {\n const block = await node.getLatestBlock();\n if (!block) return c.json({ error: \"No blocks\" }, 404);\n return c.json(block);\n });\n\n app.get(\"/blocks/:height\", async (c) => {\n const height = Number.parseInt(c.req.param(\"height\"), 10);\n if (Number.isNaN(height)) return c.json({ error: \"Invalid height\" }, 400);\n const block = await node.getBlock(height);\n if (!block) return c.json({ error: \"Block not found\" }, 404);\n return c.json(block);\n });\n\n app.get(\"/blocks\", async (c) => {\n const stores = node.getStores();\n const currentHeight = stores.blocks.getHeight();\n const from = Math.max(0, currentHeight - 19); // Last 20 blocks\n const blocks = stores.blocks.getRange(from, currentHeight);\n return c.json({ blocks, height: currentHeight });\n });\n\n return app;\n}\n","import { Hono } from \"hono\";\nimport { z } from \"zod\";\nimport type { MiniLedgerNode } from \"../../node.js\";\nimport { TxType } from \"../../types.js\";\n\nconst submitTxSchema = z.object({\n key: z.string().optional(),\n value: z.unknown().optional(),\n type: z.nativeEnum(TxType).optional(),\n payload: z\n .object({\n kind: z.string(),\n })\n .passthrough()\n .optional(),\n});\n\nexport function transactionRoutes(node: MiniLedgerNode): Hono {\n const app = new Hono();\n\n app.post(\"/tx\", async (c) => {\n try {\n const body = await c.req.json();\n const parsed = submitTxSchema.parse(body);\n const tx = await node.submit({\n type: parsed.type,\n key: parsed.key,\n value: parsed.value,\n payload: parsed.payload as any,\n });\n return c.json({ hash: tx.hash, status: \"pending\" }, 201);\n } catch (err) {\n const message = err instanceof Error ? err.message : \"Unknown error\";\n return c.json({ error: message }, 400);\n }\n });\n\n app.get(\"/tx/:hash\", async (c) => {\n const hash = c.req.param(\"hash\");\n const tx = await node.getTransaction(hash);\n if (!tx) return c.json({ error: \"Transaction not found\" }, 404);\n return c.json(tx);\n });\n\n app.get(\"/tx\", (c) => {\n const stores = node.getStores();\n const pending = stores.txs.getPending(100);\n return c.json({ pending, count: pending.length });\n });\n\n return app;\n}\n","import { Hono } from \"hono\";\nimport type { MiniLedgerNode } from \"../../node.js\";\n\nexport function stateRoutes(node: MiniLedgerNode): Hono {\n const app = new Hono();\n\n app.get(\"/state/:key\", async (c) => {\n const key = c.req.param(\"key\");\n const entry = await node.getState(key);\n if (!entry) return c.json({ error: \"Key not found\" }, 404);\n return c.json(entry);\n });\n\n /** Execute a SQL query against the world state. The killer feature. */\n app.post(\"/state/query\", async (c) => {\n try {\n const body = await c.req.json();\n const { sql, params = [] } = body as { sql: string; params?: unknown[] };\n if (!sql) return c.json({ error: \"Missing sql field\" }, 400);\n const results = await node.query(sql, params);\n return c.json({ results, count: results.length });\n } catch (err) {\n const message = err instanceof Error ? err.message : \"Query failed\";\n return c.json({ error: message }, 400);\n }\n });\n\n return app;\n}\n","import { Hono } from \"hono\";\nimport type { MiniLedgerNode } from \"../../node.js\";\n\nexport function identityRoutes(node: MiniLedgerNode): Hono {\n const app = new Hono();\n\n app.get(\"/identity\", (c) => {\n const status = node.getStatus();\n return c.json({\n nodeId: status.nodeId,\n publicKey: status.publicKey,\n });\n });\n\n return app;\n}\n","import { Hono } from \"hono\";\nimport type { MiniLedgerNode } from \"../../node.js\";\n\nexport function networkRoutes(node: MiniLedgerNode): Hono {\n const app = new Hono();\n\n app.get(\"/peers\", (c) => {\n const pm = node.getPeerManager();\n if (!pm) {\n return c.json({ peers: [], count: 0 });\n }\n const peers = pm.getPeerStates().map((p) => ({\n nodeId: p.nodeId,\n publicKey: p.publicKey,\n address: p.address,\n orgId: p.orgId,\n status: p.status,\n chainHeight: p.chainHeight,\n lastSeen: p.lastSeen,\n }));\n return c.json({ peers, count: peers.length });\n });\n\n app.get(\"/consensus\", (c) => {\n const raft = node.getRaft();\n if (!raft) {\n return c.json({ algorithm: node.config.consensus.algorithm, state: null });\n }\n return c.json({\n algorithm: \"raft\",\n state: raft.getState(),\n });\n });\n\n return app;\n}\n","import { Hono } from \"hono\";\nimport type { MiniLedgerNode } from \"../../node.js\";\n\nexport function governanceRoutes(node: MiniLedgerNode): Hono {\n const app = new Hono();\n\n app.get(\"/proposals\", (c) => {\n const proposals = node.getGovernor().listProposals();\n return c.json({ proposals, count: proposals.length });\n });\n\n app.get(\"/proposals/:id\", (c) => {\n const id = c.req.param(\"id\");\n const proposal = node.getGovernor().getProposal(id);\n if (!proposal) return c.json({ error: \"Proposal not found\" }, 404);\n return c.json(proposal);\n });\n\n app.get(\"/contracts\", (c) => {\n const contracts = node.getContractRegistry().listContracts();\n return c.json({ contracts, count: contracts.length });\n });\n\n return app;\n}\n","import { serve } from \"@hono/node-server\";\nimport type { Command } from \"commander\";\nimport { DEFAULT_CONFIG } from \"../../config/index.js\";\nimport { MiniLedgerNode } from \"../../node.js\";\nimport { createApp } from \"../../api/server.js\";\n\nexport function registerJoin(program: Command): void {\n program\n .command(\"join <peer-address>\")\n .description(\"Join an existing network (e.g. miniledger join ws://host:4440)\")\n .option(\"-d, --data-dir <path>\", \"Data directory\", DEFAULT_CONFIG.dataDir)\n .option(\"-p, --api-port <port>\", \"API port\", String(DEFAULT_CONFIG.network.apiPort))\n .option(\"--p2p-port <port>\", \"P2P port\", String(DEFAULT_CONFIG.network.p2pPort))\n .action(async (peerAddress: string, opts) => {\n const node = await MiniLedgerNode.create({\n dataDir: opts.dataDir,\n config: {\n network: {\n ...DEFAULT_CONFIG.network,\n apiPort: Number.parseInt(opts.apiPort, 10),\n p2pPort: Number.parseInt(opts.p2pPort, 10),\n peers: [peerAddress],\n },\n consensus: {\n ...DEFAULT_CONFIG.consensus,\n algorithm: \"raft\",\n },\n },\n });\n\n await node.init();\n await node.start();\n\n if (node.config.api.enabled) {\n const app = createApp(node);\n serve({\n fetch: app.fetch,\n port: node.config.network.apiPort,\n });\n console.log(`REST API listening on http://localhost:${node.config.network.apiPort}`);\n }\n\n const status = node.getStatus();\n console.log(`\\nMiniLedger node joining network via ${peerAddress}`);\n console.log(` Node ID: ${status.nodeId}`);\n console.log(` P2P Port: ${node.config.network.p2pPort}`);\n console.log(` Height: ${status.chainHeight}`);\n console.log(`\\nPress Ctrl+C to stop\\n`);\n\n const shutdown = async () => {\n console.log(\"\\nShutting down...\");\n await node.stop();\n process.exit(0);\n };\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n });\n}\n","import type { Command } from \"commander\";\nimport type { NodeStatus } from \"../../types.js\";\nimport { DEFAULT_CONFIG } from \"../../config/index.js\";\n\nexport function registerStatus(program: Command): void {\n program\n .command(\"status\")\n .description(\"Show node status\")\n .option(\"-p, --api-port <port>\", \"API port\", String(DEFAULT_CONFIG.network.apiPort))\n .action(async (opts) => {\n const port = opts.apiPort;\n try {\n const res = await fetch(`http://localhost:${port}/status`);\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const status = (await res.json()) as NodeStatus;\n console.log(\"Node Status:\");\n console.log(` Node ID: ${status.nodeId}`);\n console.log(` Public Key: ${status.publicKey}`);\n console.log(` Height: ${status.chainHeight}`);\n console.log(` Latest Hash: ${status.latestBlockHash?.substring(0, 16)}...`);\n console.log(` Peers: ${status.peerCount}`);\n console.log(` TX Pool: ${status.txPoolSize}`);\n console.log(` Uptime: ${Math.round(status.uptime / 1000)}s`);\n } catch {\n console.error(`Cannot connect to node at localhost:${port}. Is it running?`);\n process.exit(1);\n }\n });\n}\n","import type { Command } from \"commander\";\nimport { DEFAULT_CONFIG } from \"../../config/index.js\";\n\ninterface TxResult {\n hash?: string;\n status?: string;\n error?: string;\n}\n\nexport function registerTx(program: Command): void {\n const tx = program.command(\"tx\").description(\"Transaction commands\");\n\n tx.command(\"submit <data>\")\n .description(\"Submit a transaction (JSON: {key, value})\")\n .option(\"-p, --api-port <port>\", \"API port\", String(DEFAULT_CONFIG.network.apiPort))\n .action(async (data: string, opts) => {\n try {\n const body = JSON.parse(data);\n const res = await fetch(`http://localhost:${opts.apiPort}/tx`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n const result = (await res.json()) as TxResult;\n if (!res.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n console.log(`Transaction submitted: ${result.hash}`);\n } catch (err) {\n console.error(`Failed: ${err instanceof Error ? err.message : err}`);\n process.exit(1);\n }\n });\n\n tx.command(\"get <hash>\")\n .description(\"Get a transaction by hash\")\n .option(\"-p, --api-port <port>\", \"API port\", String(DEFAULT_CONFIG.network.apiPort))\n .action(async (hash: string, opts) => {\n try {\n const res = await fetch(`http://localhost:${opts.apiPort}/tx/${hash}`);\n const result = (await res.json()) as Record<string, unknown>;\n if (!res.ok) {\n console.error(`Error: ${(result as TxResult).error}`);\n process.exit(1);\n }\n console.log(JSON.stringify(result, null, 2));\n } catch {\n console.error(\"Cannot connect to node. Is it running?\");\n process.exit(1);\n }\n });\n}\n","import type { Command } from \"commander\";\nimport { DEFAULT_CONFIG } from \"../../config/index.js\";\n\ninterface QueryResult {\n results: Record<string, unknown>[];\n count: number;\n error?: string;\n}\n\nexport function registerQuery(program: Command): void {\n program\n .command(\"query <sql>\")\n .description(\"Query world state with SQL\")\n .option(\"-p, --api-port <port>\", \"API port\", String(DEFAULT_CONFIG.network.apiPort))\n .action(async (sql: string, opts) => {\n try {\n const res = await fetch(`http://localhost:${opts.apiPort}/state/query`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ sql }),\n });\n const result = (await res.json()) as QueryResult;\n if (!res.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n if (result.count === 0) {\n console.log(\"No results\");\n return;\n }\n console.table(result.results);\n } catch {\n console.error(\"Cannot connect to node. Is it running?\");\n process.exit(1);\n }\n });\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { Command } from \"commander\";\nimport { generateKeyPair, deserializeKeystore, decryptKeystore } from \"../../identity/index.js\";\nimport { DEFAULT_CONFIG } from \"../../config/index.js\";\n\nexport function registerKeys(program: Command): void {\n const keys = program.command(\"keys\").description(\"Key management\");\n\n keys\n .command(\"generate\")\n .description(\"Generate a new keypair\")\n .action(() => {\n const kp = generateKeyPair();\n console.log(`Public Key: ${kp.publicKey}`);\n console.log(`Private Key: ${kp.privateKey}`);\n });\n\n keys\n .command(\"show\")\n .description(\"Show the node's public key\")\n .option(\"-d, --data-dir <path>\", \"Data directory\", DEFAULT_CONFIG.dataDir)\n .action((opts) => {\n const keystorePath = path.join(opts.dataDir, \"keystore.json\");\n if (!fs.existsSync(keystorePath)) {\n console.error(\"No keystore found. Run 'miniledger init' first.\");\n process.exit(1);\n }\n const ks = deserializeKeystore(fs.readFileSync(keystorePath, \"utf-8\"));\n const kp = decryptKeystore(ks, \"\");\n console.log(`Public Key: ${kp.publicKey}`);\n console.log(`Node ID: ${kp.publicKey.substring(0, 16)}`);\n });\n}\n","import type { Command } from \"commander\";\nimport { DEFAULT_CONFIG } from \"../../config/index.js\";\n\ninterface PeersResult {\n peers: { nodeId: string; address: string; orgId: string; status: string; chainHeight: number }[];\n count: number;\n}\n\nexport function registerPeers(program: Command): void {\n const peers = program.command(\"peers\").description(\"Peer management\");\n\n peers\n .command(\"list\")\n .description(\"List connected peers\")\n .option(\"-p, --api-port <port>\", \"API port\", String(DEFAULT_CONFIG.network.apiPort))\n .action(async (opts) => {\n try {\n const res = await fetch(`http://localhost:${opts.apiPort}/peers`);\n const data = (await res.json()) as PeersResult;\n if (data.count === 0) {\n console.log(\"No connected peers\");\n return;\n }\n console.table(data.peers);\n } catch {\n console.error(\"Cannot connect to node. Is it running?\");\n process.exit(1);\n }\n });\n}\n","import { serve } from \"@hono/node-server\";\nimport { exec } from \"node:child_process\";\nimport type { Command } from \"commander\";\nimport { MiniLedgerNode } from \"../../node.js\";\nimport { TxType } from \"../../types.js\";\nimport { createApp } from \"../../api/server.js\";\nimport { TRANSFER_CONTRACT } from \"../../contracts/builtins.js\";\nimport { createTempDir } from \"./demo-utils.js\";\n\nexport function registerDemo(program: Command): void {\n program\n .command(\"demo\")\n .description(\"Run a 3-node demo cluster with sample data\")\n .option(\"-p, --port <port>\", \"API port for the primary node\", \"4441\")\n .action(async (opts) => {\n const apiPort = Number.parseInt(opts.port, 10);\n console.log(\"\\n MiniLedger Demo\");\n console.log(\" ===============\\n\");\n console.log(\" Starting a 3-node cluster with Raft consensus...\\n\");\n\n const dirs: string[] = [];\n const nodes: MiniLedgerNode[] = [];\n\n try {\n // Create 3 nodes\n for (let i = 0; i < 3; i++) {\n const dir = createTempDir(`miniledger-demo-node${i + 1}-`);\n dirs.push(dir);\n\n const peers = i > 0 ? [`ws://127.0.0.1:${5440}`] : [];\n const node = await MiniLedgerNode.create({\n dataDir: dir,\n config: {\n node: { name: `demo-node-${i + 1}`, orgId: `org-${i + 1}`, role: \"validator\" },\n network: {\n listenAddress: \"127.0.0.1\",\n p2pPort: 5440 + i * 2,\n apiPort: apiPort + i * 2,\n peers,\n maxPeers: 50,\n },\n consensus: { algorithm: \"raft\", blockTimeMs: 1000, maxTxPerBlock: 500 },\n logging: { level: \"warn\" },\n api: { enabled: true, cors: true },\n },\n });\n\n await node.init();\n nodes.push(node);\n }\n\n // Start nodes with slight delay\n for (let i = 0; i < nodes.length; i++) {\n await nodes[i]!.start();\n const app = createApp(nodes[i]!);\n serve({ fetch: app.fetch, port: apiPort + i * 2 });\n console.log(` Node ${i + 1}: http://localhost:${apiPort + i * 2} (P2P: ${5440 + i * 2})`);\n if (i === 0) await sleep(500);\n }\n\n console.log(\"\\n Waiting for leader election...\");\n await sleep(5000);\n\n // Find the leader\n const leader = nodes.find((n) => n.getRaft()?.isLeader()) ?? nodes[0]!;\n console.log(` Leader elected: Node ${nodes.indexOf(leader) + 1}\\n`);\n\n // Submit sample data\n console.log(\" Submitting sample transactions...\\n\");\n\n // Deploy token contract\n await leader.submit({\n type: TxType.ContractDeploy,\n payload: { kind: \"contract:deploy\", name: \"token\", version: \"1.0\", code: TRANSFER_CONTRACT },\n });\n console.log(\" [+] Deployed 'token' contract\");\n\n // Mint tokens\n await leader.submit({\n type: TxType.ContractInvoke,\n payload: { kind: \"contract:invoke\", contract: \"token\", method: \"mint\", args: [10000] },\n });\n console.log(\" [+] Minted 10,000 tokens\");\n\n // Add some state\n await leader.submit({ key: \"company:acme\", value: { name: \"Acme Corp\", industry: \"Manufacturing\", employees: 5000 } });\n await leader.submit({ key: \"company:globex\", value: { name: \"Globex Inc\", industry: \"Finance\", employees: 3200 } });\n await leader.submit({ key: \"company:initech\", value: { name: \"Initech LLC\", industry: \"Technology\", employees: 800 } });\n console.log(\" [+] Added 3 company records\");\n\n // Create a governance proposal\n await leader.submit({\n type: TxType.GovernancePropose,\n payload: {\n kind: \"governance:propose\",\n title: \"Increase block size to 1000 tx\",\n description: \"Proposal to double the max transactions per block for better throughput\",\n action: { type: \"update-config\", maxTxPerBlock: 1000 },\n },\n });\n console.log(\" [+] Created governance proposal\");\n\n await sleep(2000);\n\n const status = leader.getStatus();\n console.log(`\\n Cluster running!`);\n console.log(` Chain height: ${status.chainHeight}`);\n console.log(` Peers: ${status.peerCount}`);\n console.log(`\\n Dashboard: http://localhost:${apiPort}/dashboard`);\n console.log(`\\n Try these:`);\n console.log(` curl http://localhost:${apiPort}/status`);\n console.log(` curl http://localhost:${apiPort}/blocks/latest`);\n console.log(` curl -X POST http://localhost:${apiPort}/state/query -H \"Content-Type: application/json\" -d '{\"sql\":\"SELECT * FROM world_state WHERE key LIKE \\\\'company:%\\\\'\"}'`);\n console.log(`\\n Press Ctrl+C to stop\\n`);\n\n // Try to open browser\n openBrowser(`http://localhost:${apiPort}/dashboard`);\n\n // Graceful shutdown\n const shutdown = async () => {\n console.log(\"\\n Shutting down demo...\");\n for (const node of nodes) await node.stop();\n for (const dir of dirs) {\n try { require(\"node:fs\").rmSync(dir, { recursive: true, force: true }); } catch {}\n }\n process.exit(0);\n };\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n } catch (err) {\n console.error(\" Demo failed:\", err);\n for (const node of nodes) await node.stop().catch(() => {});\n process.exit(1);\n }\n });\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n}\n\nfunction openBrowser(url: string): void {\n const cmd =\n process.platform === \"darwin\" ? \"open\" :\n process.platform === \"win32\" ? \"start\" : \"xdg-open\";\n exec(`${cmd} ${url}`);\n}\n","import * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\n\nexport function createTempDir(prefix = \"miniledger-demo-\"): string {\n return fs.mkdtempSync(path.join(os.tmpdir(), prefix));\n}\n"],"mappings":"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","names":["fs","path","ed","sign","verify","Database","import_sha256","program","path","fs","import_node_events","TxType","resolve","import_ws","WebSocket","resolve","import_node_events","pino","verify","sign","fs","path","import_hono","import_hono","import_hono","import_zod","import_hono","import_hono","import_hono","import_hono","program","import_node_server","program","program","program","program","fs","path","program","program","import_node_server","fs","path","program","program"]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/index.ts","../../src/cli/commands/init.ts","../../src/identity/keypair.ts","../../src/utils.ts","../../src/identity/signer.ts","../../src/identity/keystore.ts","../../src/constants.ts","../../src/config/defaults.ts","../../src/config/schema.ts","../../src/config/loader.ts","../../src/errors.ts","../../src/storage/database.ts","../../src/storage/migrations.ts","../../src/core/serialization.ts","../../src/storage/queries.ts","../../src/storage/block-store.ts","../../src/core/hash.ts","../../src/core/merkle.ts","../../src/core/block.ts","../../src/core/chain.ts","../../src/cli/commands/start.ts","../../src/node.ts","../../src/types.ts","../../src/core/transaction.ts","../../src/storage/state-store.ts","../../src/storage/tx-store.ts","../../src/network/peer-manager.ts","../../src/network/ws-server.ts","../../src/network/protocol.ts","../../src/network/peer.ts","../../src/network/ws-client.ts","../../src/network/router.ts","../../src/network/sync.ts","../../src/consensus/raft/raft-node.ts","../../src/consensus/raft/raft-timer.ts","../../src/consensus/raft/raft-log.ts","../../src/contracts/context.ts","../../src/contracts/runtime.ts","../../src/contracts/registry.ts","../../src/contracts/builtins.ts","../../src/governance/proposal.ts","../../src/governance/voting.ts","../../src/governance/governor.ts","../../src/api/server.ts","../../src/api/middleware/logging.ts","../../src/api/routes/health.ts","../../src/api/routes/blocks.ts","../../src/api/routes/transactions.ts","../../src/api/routes/state.ts","../../src/api/routes/identity.ts","../../src/api/routes/network.ts","../../src/api/routes/governance.ts","../../src/cli/commands/join.ts","../../src/cli/commands/status.ts","../../src/cli/commands/tx.ts","../../src/cli/commands/query.ts","../../src/cli/commands/keys.ts","../../src/cli/commands/peers.ts","../../src/cli/commands/demo.ts","../../src/cli/commands/demo-utils.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { registerInit } from \"./commands/init.js\";\nimport { registerStart } from \"./commands/start.js\";\nimport { registerJoin } from \"./commands/join.js\";\nimport { registerStatus } from \"./commands/status.js\";\nimport { registerTx } from \"./commands/tx.js\";\nimport { registerQuery } from \"./commands/query.js\";\nimport { registerKeys } from \"./commands/keys.js\";\nimport { registerPeers } from \"./commands/peers.js\";\nimport { registerDemo } from \"./commands/demo.js\";\n\nexport function createCLI(): Command {\n const program = new Command();\n\n program\n .name(\"miniledger\")\n .description(\"The SQLite of private blockchains\")\n .version(\"0.1.0\");\n\n registerInit(program);\n registerStart(program);\n registerJoin(program);\n registerStatus(program);\n registerTx(program);\n registerQuery(program);\n registerKeys(program);\n registerPeers(program);\n registerDemo(program);\n\n return program;\n}\n\n// Direct execution\nconst program = createCLI();\nprogram.parse();\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { Command } from \"commander\";\nimport { generateKeyPair, encryptKeystore, serializeKeystore } from \"../../identity/index.js\";\nimport { DEFAULT_CONFIG } from \"../../config/index.js\";\nimport { GENESIS_PROPOSER } from \"../../constants.js\";\nimport { MiniLedgerDB } from \"../../storage/database.js\";\nimport { BlockStore } from \"../../storage/block-store.js\";\nimport { Chain } from \"../../core/chain.js\";\n\nexport function registerInit(program: Command): void {\n program\n .command(\"init\")\n .description(\"Initialize a new MiniLedger node\")\n .option(\"-d, --data-dir <path>\", \"Data directory\", DEFAULT_CONFIG.dataDir)\n .option(\"-n, --name <name>\", \"Node name\", DEFAULT_CONFIG.node.name)\n .option(\"-o, --org <orgId>\", \"Organization ID\", DEFAULT_CONFIG.node.orgId)\n .action((opts) => {\n const dataDir = opts.dataDir as string;\n\n if (fs.existsSync(path.join(dataDir, \"ledger.db\"))) {\n console.log(`Node already initialized at ${dataDir}`);\n return;\n }\n\n // Create data directory\n fs.mkdirSync(dataDir, { recursive: true });\n\n // Generate keypair\n const keyPair = generateKeyPair();\n const ks = encryptKeystore(keyPair, \"\", opts.org, opts.name);\n fs.writeFileSync(path.join(dataDir, \"keystore.json\"), serializeKeystore(ks));\n\n // Save config\n const config = {\n ...DEFAULT_CONFIG,\n dataDir,\n node: {\n ...DEFAULT_CONFIG.node,\n name: opts.name,\n orgId: opts.org,\n },\n };\n fs.writeFileSync(path.join(dataDir, \"miniledger.json\"), JSON.stringify(config, null, 2));\n\n // Create database and genesis block\n const db = new MiniLedgerDB(path.join(dataDir, \"ledger.db\"));\n db.migrate();\n\n const blockStore = new BlockStore(db.raw());\n const chain = new Chain();\n const genesis = chain.createGenesis(GENESIS_PROPOSER);\n blockStore.insert(genesis);\n db.close();\n\n console.log(`MiniLedger initialized at ${dataDir}`);\n console.log(` Node ID: ${keyPair.publicKey.substring(0, 16)}`);\n console.log(` Public Key: ${keyPair.publicKey}`);\n console.log(` Org: ${opts.org}`);\n console.log(` Genesis: ${genesis.hash.substring(0, 16)}...`);\n console.log(`\\nStart with: miniledger start -d ${dataDir}`);\n });\n}\n","import * as ed from \"@noble/ed25519\";\nimport { sha512 } from \"@noble/hashes/sha512\";\nimport { toHex, fromHex } from \"../utils.js\";\n\n// ed25519 requires sha512\ned.etc.sha512Sync = (...m: Uint8Array[]) => {\n const h = sha512.create();\n for (const msg of m) h.update(msg);\n return h.digest();\n};\n\nexport interface KeyPair {\n publicKey: string; // hex\n privateKey: string; // hex\n}\n\n/** Generate a new Ed25519 keypair. */\nexport function generateKeyPair(): KeyPair {\n const privateKey = ed.utils.randomPrivateKey();\n const publicKey = ed.getPublicKey(privateKey);\n return {\n publicKey: toHex(publicKey),\n privateKey: toHex(privateKey),\n };\n}\n\n/** Derive public key from a private key. */\nexport function getPublicKey(privateKeyHex: string): string {\n return toHex(ed.getPublicKey(fromHex(privateKeyHex)));\n}\n\n/** Export keypair to JSON-serializable format. */\nexport function exportKeyPair(kp: KeyPair): { publicKey: string; privateKey: string } {\n return { publicKey: kp.publicKey, privateKey: kp.privateKey };\n}\n\n/** Import keypair from hex strings. */\nexport function importKeyPair(publicKey: string, privateKey: string): KeyPair {\n return { publicKey, privateKey };\n}\n","export function toHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\nexport function fromHex(hex: string): Uint8Array {\n const bytes = new Uint8Array(hex.length / 2);\n for (let i = 0; i < hex.length; i += 2) {\n bytes[i / 2] = Number.parseInt(hex.substring(i, i + 2), 16);\n }\n return bytes;\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport function nowMs(): number {\n return Date.now();\n}\n\nexport function shortId(publicKey: string): string {\n return publicKey.substring(0, 16);\n}\n\nexport function isValidHex(str: string, expectedLength?: number): boolean {\n if (expectedLength !== undefined && str.length !== expectedLength) {\n return false;\n }\n return /^[0-9a-f]+$/.test(str);\n}\n","import * as ed from \"@noble/ed25519\";\nimport { fromHex, toHex } from \"../utils.js\";\n\n/** Sign a message (hex string or raw string) with a private key. Returns hex signature. */\nexport function sign(message: string, privateKeyHex: string): string {\n const msgBytes = new TextEncoder().encode(message);\n const sig = ed.sign(msgBytes, fromHex(privateKeyHex));\n return toHex(sig);\n}\n\n/** Verify a signature against a message and public key. */\nexport function verify(message: string, signatureHex: string, publicKeyHex: string): boolean {\n try {\n const msgBytes = new TextEncoder().encode(message);\n return ed.verify(fromHex(signatureHex), msgBytes, fromHex(publicKeyHex));\n } catch {\n return false;\n }\n}\n","import { sha256 } from \"@noble/hashes/sha256\";\nimport { toHex, fromHex } from \"../utils.js\";\nimport type { KeyPair } from \"./keypair.js\";\n\ninterface KeystoreFile {\n version: 1;\n publicKey: string;\n encryptedPrivateKey: string;\n salt: string;\n orgId: string;\n name: string;\n}\n\n/**\n * Simple keystore: XOR the private key with a password-derived key.\n * This is a minimal implementation for M1. A production version would use\n * AES-256-GCM with scrypt key derivation.\n */\nfunction deriveKey(password: string, salt: Uint8Array): Uint8Array {\n // Simple PBKDF: hash(password + salt) repeated\n let key = sha256(new TextEncoder().encode(password + toHex(salt)));\n for (let i = 0; i < 10000; i++) {\n key = sha256(key);\n }\n return key;\n}\n\nexport function encryptKeystore(\n keyPair: KeyPair,\n password: string,\n orgId: string,\n name: string,\n): KeystoreFile {\n const salt = crypto.getRandomValues(new Uint8Array(16));\n const derived = deriveKey(password, salt);\n const privBytes = fromHex(keyPair.privateKey);\n const encrypted = new Uint8Array(privBytes.length);\n for (let i = 0; i < privBytes.length; i++) {\n encrypted[i] = privBytes[i]! ^ derived[i % derived.length]!;\n }\n\n return {\n version: 1,\n publicKey: keyPair.publicKey,\n encryptedPrivateKey: toHex(encrypted),\n salt: toHex(salt),\n orgId,\n name,\n };\n}\n\nexport function decryptKeystore(keystore: KeystoreFile, password: string): KeyPair {\n const salt = fromHex(keystore.salt);\n const derived = deriveKey(password, salt);\n const encrypted = fromHex(keystore.encryptedPrivateKey);\n const decrypted = new Uint8Array(encrypted.length);\n for (let i = 0; i < encrypted.length; i++) {\n decrypted[i] = encrypted[i]! ^ derived[i % derived.length]!;\n }\n\n return {\n publicKey: keystore.publicKey,\n privateKey: toHex(decrypted),\n };\n}\n\nexport function serializeKeystore(keystore: KeystoreFile): string {\n return JSON.stringify(keystore, null, 2);\n}\n\nexport function deserializeKeystore(data: string): KeystoreFile {\n return JSON.parse(data) as KeystoreFile;\n}\n","export const PROTOCOL_VERSION = 1;\nexport const GENESIS_PREVIOUS_HASH = \"0\".repeat(64);\nexport const GENESIS_TIMESTAMP = 0;\n\nexport const DEFAULT_P2P_PORT = 4440;\nexport const DEFAULT_API_PORT = 4441;\nexport const DEFAULT_DATA_DIR = \"./miniledger-data\";\n\nexport const MAX_TX_PER_BLOCK = 500;\nexport const BLOCK_TIME_MS = 1000;\nexport const MAX_TX_SIZE_BYTES = 1024 * 256; // 256KB\nexport const MAX_BLOCK_SIZE_BYTES = 1024 * 1024 * 10; // 10MB\n\nexport const EMPTY_MERKLE_ROOT = \"0\".repeat(64);\n\n// Fixed genesis proposer key so all nodes produce identical genesis blocks\nexport const GENESIS_PROPOSER = \"0\".repeat(64);\n\nexport const NONCE_TABLE = \"_miniledger_nonces\";\nexport const META_TABLE = \"_miniledger_meta\";\n","import {\n DEFAULT_API_PORT,\n DEFAULT_DATA_DIR,\n DEFAULT_P2P_PORT,\n BLOCK_TIME_MS,\n MAX_TX_PER_BLOCK,\n} from \"../constants.js\";\n\nexport interface MiniLedgerConfig {\n dataDir: string;\n node: {\n name: string;\n orgId: string;\n role: \"validator\" | \"observer\";\n };\n network: {\n listenAddress: string;\n p2pPort: number;\n apiPort: number;\n peers: string[];\n maxPeers: number;\n };\n consensus: {\n algorithm: \"raft\" | \"solo\";\n blockTimeMs: number;\n maxTxPerBlock: number;\n };\n api: {\n enabled: boolean;\n cors: boolean;\n };\n logging: {\n level: \"debug\" | \"info\" | \"warn\" | \"error\";\n };\n}\n\nexport const DEFAULT_CONFIG: MiniLedgerConfig = {\n dataDir: DEFAULT_DATA_DIR,\n node: {\n name: \"node-1\",\n orgId: \"org-1\",\n role: \"validator\",\n },\n network: {\n listenAddress: \"0.0.0.0\",\n p2pPort: DEFAULT_P2P_PORT,\n apiPort: DEFAULT_API_PORT,\n peers: [],\n maxPeers: 50,\n },\n consensus: {\n algorithm: \"solo\",\n blockTimeMs: BLOCK_TIME_MS,\n maxTxPerBlock: MAX_TX_PER_BLOCK,\n },\n api: {\n enabled: true,\n cors: true,\n },\n logging: {\n level: \"info\",\n },\n};\n","import { z } from \"zod\";\n\nexport const configSchema = z.object({\n dataDir: z.string(),\n node: z.object({\n name: z.string(),\n orgId: z.string(),\n role: z.enum([\"validator\", \"observer\"]),\n }),\n network: z.object({\n listenAddress: z.string(),\n p2pPort: z.number().int().min(1).max(65535),\n apiPort: z.number().int().min(1).max(65535),\n peers: z.array(z.string()),\n maxPeers: z.number().int().min(1),\n }),\n consensus: z.object({\n algorithm: z.enum([\"raft\", \"solo\"]),\n blockTimeMs: z.number().int().min(100),\n maxTxPerBlock: z.number().int().min(1),\n }),\n api: z.object({\n enabled: z.boolean(),\n cors: z.boolean(),\n }),\n logging: z.object({\n level: z.enum([\"debug\", \"info\", \"warn\", \"error\"]),\n }),\n});\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { ConfigError } from \"../errors.js\";\nimport { type MiniLedgerConfig, DEFAULT_CONFIG } from \"./defaults.js\";\nimport { configSchema } from \"./schema.js\";\n\n/** Deep merge two objects (b overrides a). */\nfunction deepMerge<T extends Record<string, unknown>>(a: T, b: Partial<T>): T {\n const result = { ...a };\n for (const key of Object.keys(b) as (keyof T)[]) {\n const val = b[key];\n if (val !== undefined && typeof val === \"object\" && val !== null && !Array.isArray(val)) {\n result[key] = deepMerge(\n (a[key] ?? {}) as Record<string, unknown>,\n val as Record<string, unknown>,\n ) as T[keyof T];\n } else if (val !== undefined) {\n result[key] = val as T[keyof T];\n }\n }\n return result;\n}\n\n/** Load config from file, merging with defaults. */\nexport function loadConfig(overrides: Partial<MiniLedgerConfig> = {}): MiniLedgerConfig {\n // Start with defaults\n let config = { ...DEFAULT_CONFIG };\n\n // Check for config file in data dir\n const dataDir = overrides.dataDir ?? config.dataDir;\n const configPath = path.join(dataDir, \"miniledger.json\");\n\n if (fs.existsSync(configPath)) {\n try {\n const fileContent = JSON.parse(fs.readFileSync(configPath, \"utf-8\"));\n config = deepMerge(config, fileContent);\n } catch (err) {\n throw new ConfigError(`Failed to parse config file ${configPath}: ${err}`);\n }\n }\n\n // Apply overrides\n config = deepMerge(config, overrides as Partial<typeof config>);\n\n // Validate\n const result = configSchema.safeParse(config);\n if (!result.success) {\n throw new ConfigError(`Invalid configuration: ${result.error.message}`);\n }\n\n return result.data as MiniLedgerConfig;\n}\n\n/** Save config to the data directory. */\nexport function saveConfig(config: MiniLedgerConfig): void {\n const configPath = path.join(config.dataDir, \"miniledger.json\");\n fs.mkdirSync(config.dataDir, { recursive: true });\n fs.writeFileSync(configPath, JSON.stringify(config, null, 2));\n}\n","export class MiniLedgerError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"MiniLedgerError\";\n }\n}\n\nexport class ChainError extends MiniLedgerError {\n constructor(message: string) {\n super(message);\n this.name = \"ChainError\";\n }\n}\n\nexport class ValidationError extends MiniLedgerError {\n constructor(message: string) {\n super(message);\n this.name = \"ValidationError\";\n }\n}\n\nexport class StorageError extends MiniLedgerError {\n constructor(message: string) {\n super(message);\n this.name = \"StorageError\";\n }\n}\n\nexport class ConsensusError extends MiniLedgerError {\n constructor(message: string) {\n super(message);\n this.name = \"ConsensusError\";\n }\n}\n\nexport class NetworkError extends MiniLedgerError {\n constructor(message: string) {\n super(message);\n this.name = \"NetworkError\";\n }\n}\n\nexport class IdentityError extends MiniLedgerError {\n constructor(message: string) {\n super(message);\n this.name = \"IdentityError\";\n }\n}\n\nexport class ConfigError extends MiniLedgerError {\n constructor(message: string) {\n super(message);\n this.name = \"ConfigError\";\n }\n}\n","import Database from \"better-sqlite3\";\nimport { StorageError } from \"../errors.js\";\nimport { MIGRATIONS } from \"./migrations.js\";\n\nexport class MiniLedgerDB {\n private db: Database.Database;\n\n constructor(dbPath: string) {\n try {\n this.db = new Database(dbPath);\n this.db.pragma(\"journal_mode = WAL\");\n this.db.pragma(\"synchronous = NORMAL\");\n this.db.pragma(\"foreign_keys = ON\");\n this.db.pragma(\"busy_timeout = 5000\");\n } catch (err) {\n throw new StorageError(`Failed to open database: ${err}`);\n }\n }\n\n /** Run all pending migrations. */\n migrate(): void {\n // Create migrations tracking table\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS _migrations (\n version INTEGER PRIMARY KEY,\n applied_at INTEGER NOT NULL\n );\n `);\n\n const applied = this.db\n .prepare(\"SELECT version FROM _migrations ORDER BY version\")\n .all() as { version: number }[];\n const appliedVersions = new Set(applied.map((r) => r.version));\n\n for (const migration of MIGRATIONS) {\n if (!appliedVersions.has(migration.version)) {\n this.db.transaction(() => {\n this.db.exec(migration.sql);\n this.db.prepare(\"INSERT INTO _migrations (version, applied_at) VALUES (?, ?)\").run(\n migration.version,\n Date.now(),\n );\n })();\n }\n }\n }\n\n /** Get the underlying better-sqlite3 Database instance. */\n raw(): Database.Database {\n return this.db;\n }\n\n close(): void {\n this.db.close();\n }\n}\n","export const MIGRATIONS: { version: number; sql: string }[] = [\n {\n version: 1,\n sql: `\n CREATE TABLE IF NOT EXISTS blocks (\n height INTEGER PRIMARY KEY,\n hash TEXT UNIQUE NOT NULL,\n prev_hash TEXT NOT NULL,\n timestamp INTEGER NOT NULL,\n merkle_root TEXT NOT NULL,\n state_root TEXT NOT NULL,\n proposer TEXT NOT NULL,\n signature TEXT NOT NULL DEFAULT '',\n raw TEXT NOT NULL\n );\n\n CREATE TABLE IF NOT EXISTS transactions (\n hash TEXT PRIMARY KEY,\n type TEXT NOT NULL,\n sender TEXT NOT NULL,\n nonce INTEGER NOT NULL,\n timestamp INTEGER NOT NULL,\n payload TEXT NOT NULL,\n signature TEXT NOT NULL DEFAULT '',\n block_height INTEGER REFERENCES blocks(height),\n position INTEGER,\n status TEXT NOT NULL DEFAULT 'confirmed'\n );\n\n CREATE TABLE IF NOT EXISTS world_state (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL,\n version INTEGER NOT NULL DEFAULT 1,\n updated_at INTEGER NOT NULL,\n updated_by TEXT NOT NULL,\n block_height INTEGER NOT NULL\n );\n\n CREATE TABLE IF NOT EXISTS peers (\n id TEXT PRIMARY KEY,\n public_key TEXT UNIQUE NOT NULL,\n address TEXT NOT NULL,\n org_id TEXT NOT NULL,\n role TEXT NOT NULL DEFAULT 'validator',\n added_at INTEGER NOT NULL\n );\n\n CREATE TABLE IF NOT EXISTS tx_pool (\n hash TEXT PRIMARY KEY,\n raw TEXT NOT NULL,\n received INTEGER NOT NULL,\n priority INTEGER DEFAULT 0\n );\n\n CREATE TABLE IF NOT EXISTS nonces (\n sender TEXT PRIMARY KEY,\n nonce INTEGER NOT NULL DEFAULT 0\n );\n\n CREATE TABLE IF NOT EXISTS meta (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n );\n\n CREATE INDEX IF NOT EXISTS idx_tx_sender ON transactions(sender);\n CREATE INDEX IF NOT EXISTS idx_tx_block ON transactions(block_height);\n CREATE INDEX IF NOT EXISTS idx_tx_type ON transactions(type);\n CREATE INDEX IF NOT EXISTS idx_state_updated ON world_state(updated_at);\n CREATE INDEX IF NOT EXISTS idx_state_block ON world_state(block_height);\n `,\n },\n];\n","/** Deterministic JSON serialization with sorted keys. */\nexport function canonicalize(obj: unknown): string {\n return JSON.stringify(obj, (_key, value) => {\n if (value !== null && typeof value === \"object\" && !Array.isArray(value)) {\n return Object.keys(value as Record<string, unknown>)\n .sort()\n .reduce(\n (sorted, k) => {\n sorted[k] = (value as Record<string, unknown>)[k];\n return sorted;\n },\n {} as Record<string, unknown>,\n );\n }\n return value;\n });\n}\n","import type Database from \"better-sqlite3\";\n\n/**\n * Cached prepared statement helper.\n * Lazily prepares and caches statements for reuse.\n */\nexport class QueryCache {\n private cache = new Map<string, Database.Statement>();\n\n constructor(private db: Database.Database) {}\n\n prepare(sql: string): Database.Statement {\n let stmt = this.cache.get(sql);\n if (!stmt) {\n stmt = this.db.prepare(sql);\n this.cache.set(sql, stmt);\n }\n return stmt;\n }\n\n clear(): void {\n this.cache.clear();\n }\n}\n","import type Database from \"better-sqlite3\";\nimport type { Block } from \"../types.js\";\nimport { canonicalize } from \"../core/serialization.js\";\nimport { QueryCache } from \"./queries.js\";\n\nexport class BlockStore {\n private q: QueryCache;\n\n constructor(db: Database.Database) {\n this.q = new QueryCache(db);\n }\n\n insert(block: Block): void {\n const raw = canonicalize(block);\n this.q\n .prepare(\n `INSERT INTO blocks (height, hash, prev_hash, timestamp, merkle_root, state_root, proposer, signature, raw)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n block.height,\n block.hash,\n block.previousHash,\n block.timestamp,\n block.merkleRoot,\n block.stateRoot,\n block.proposer,\n block.signature,\n raw,\n );\n\n // Insert transactions\n const txStmt = this.q.prepare(\n `INSERT OR IGNORE INTO transactions (hash, type, sender, nonce, timestamp, payload, signature, block_height, position, status)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 'confirmed')`,\n );\n for (let i = 0; i < block.transactions.length; i++) {\n const tx = block.transactions[i]!;\n txStmt.run(\n tx.hash,\n tx.type,\n tx.sender,\n tx.nonce,\n tx.timestamp,\n canonicalize(tx.payload),\n tx.signature,\n block.height,\n i,\n );\n }\n }\n\n getByHeight(height: number): Block | null {\n const row = this.q.prepare(\"SELECT raw FROM blocks WHERE height = ?\").get(height) as\n | { raw: string }\n | undefined;\n return row ? (JSON.parse(row.raw) as Block) : null;\n }\n\n getByHash(hash: string): Block | null {\n const row = this.q.prepare(\"SELECT raw FROM blocks WHERE hash = ?\").get(hash) as\n | { raw: string }\n | undefined;\n return row ? (JSON.parse(row.raw) as Block) : null;\n }\n\n getLatest(): Block | null {\n const row = this.q\n .prepare(\"SELECT raw FROM blocks ORDER BY height DESC LIMIT 1\")\n .get() as { raw: string } | undefined;\n return row ? (JSON.parse(row.raw) as Block) : null;\n }\n\n getRange(fromHeight: number, toHeight: number): Block[] {\n const rows = this.q\n .prepare(\"SELECT raw FROM blocks WHERE height >= ? AND height <= ? ORDER BY height ASC\")\n .all(fromHeight, toHeight) as { raw: string }[];\n return rows.map((r) => JSON.parse(r.raw) as Block);\n }\n\n getHeight(): number {\n const row = this.q.prepare(\"SELECT MAX(height) as h FROM blocks\").get() as\n | { h: number | null }\n | undefined;\n return row?.h ?? -1;\n }\n}\n","import { sha256 } from \"@noble/hashes/sha256\";\nimport { toHex } from \"../utils.js\";\n\nexport function sha256Hex(data: string | Uint8Array): string {\n const input = typeof data === \"string\" ? new TextEncoder().encode(data) : data;\n return toHex(sha256(input));\n}\n\nexport function sha256Bytes(data: string | Uint8Array): Uint8Array {\n const input = typeof data === \"string\" ? new TextEncoder().encode(data) : data;\n return sha256(input);\n}\n","import { EMPTY_MERKLE_ROOT } from \"../constants.js\";\nimport { sha256Hex } from \"./hash.js\";\n\n/** Compute Merkle root from a list of transaction hashes. */\nexport function computeMerkleRoot(hashes: string[]): string {\n if (hashes.length === 0) return EMPTY_MERKLE_ROOT;\n if (hashes.length === 1) return hashes[0]!;\n\n let level = [...hashes];\n\n while (level.length > 1) {\n const next: string[] = [];\n for (let i = 0; i < level.length; i += 2) {\n const left = level[i]!;\n const right = i + 1 < level.length ? level[i + 1]! : left;\n next.push(sha256Hex(left + right));\n }\n level = next;\n }\n\n return level[0]!;\n}\n","import type { Block, HexString, Transaction } from \"../types.js\";\nimport { GENESIS_PREVIOUS_HASH, GENESIS_TIMESTAMP, EMPTY_MERKLE_ROOT } from \"../constants.js\";\nimport { ValidationError } from \"../errors.js\";\nimport { sha256Hex } from \"./hash.js\";\nimport { computeMerkleRoot } from \"./merkle.js\";\nimport { canonicalize } from \"./serialization.js\";\n\nexport interface CreateBlockParams {\n height: number;\n previousHash: HexString;\n transactions: Transaction[];\n proposer: HexString;\n stateRoot: HexString;\n timestamp?: number;\n}\n\n/** Compute the canonical hash of a block header (excludes hash and signature). */\nexport function computeBlockHash(params: {\n height: number;\n previousHash: string;\n timestamp: number;\n merkleRoot: string;\n stateRoot: string;\n proposer: string;\n}): string {\n const canonical = canonicalize({\n height: params.height,\n previousHash: params.previousHash,\n timestamp: params.timestamp,\n merkleRoot: params.merkleRoot,\n stateRoot: params.stateRoot,\n proposer: params.proposer,\n });\n return sha256Hex(canonical);\n}\n\n/** Create an unsigned block. Signature must be added separately. */\nexport function createBlock(params: CreateBlockParams): Omit<Block, \"signature\"> & { signature: \"\" } {\n const timestamp = params.timestamp ?? Date.now();\n const merkleRoot = computeMerkleRoot(params.transactions.map((tx) => tx.hash));\n\n const hash = computeBlockHash({\n height: params.height,\n previousHash: params.previousHash,\n timestamp,\n merkleRoot,\n stateRoot: params.stateRoot,\n proposer: params.proposer,\n });\n\n return {\n height: params.height,\n hash,\n previousHash: params.previousHash,\n timestamp,\n merkleRoot,\n stateRoot: params.stateRoot,\n proposer: params.proposer,\n signature: \"\",\n transactions: params.transactions,\n };\n}\n\n/** Create the genesis block (height 0, no transactions). */\nexport function createGenesisBlock(proposer: HexString): Block {\n const merkleRoot = EMPTY_MERKLE_ROOT;\n const stateRoot = EMPTY_MERKLE_ROOT;\n const timestamp = GENESIS_TIMESTAMP;\n\n const hash = computeBlockHash({\n height: 0,\n previousHash: GENESIS_PREVIOUS_HASH,\n timestamp,\n merkleRoot,\n stateRoot,\n proposer,\n });\n\n return {\n height: 0,\n hash,\n previousHash: GENESIS_PREVIOUS_HASH,\n timestamp,\n merkleRoot,\n stateRoot,\n proposer,\n signature: \"\",\n transactions: [],\n };\n}\n\n/** Validate a block's structural integrity (does not verify signature). */\nexport function validateBlock(block: Block, previousBlock?: Block): void {\n if (block.height < 0 || !Number.isInteger(block.height)) {\n throw new ValidationError(`Invalid block height: ${block.height}`);\n }\n\n if (previousBlock) {\n if (block.height !== previousBlock.height + 1) {\n throw new ValidationError(\n `Block height ${block.height} does not follow ${previousBlock.height}`,\n );\n }\n if (block.previousHash !== previousBlock.hash) {\n throw new ValidationError(\"Block previousHash does not match previous block hash\");\n }\n if (block.timestamp < previousBlock.timestamp) {\n throw new ValidationError(\"Block timestamp is before previous block\");\n }\n }\n\n // Verify merkle root\n const expectedMerkle = computeMerkleRoot(block.transactions.map((tx) => tx.hash));\n if (expectedMerkle !== block.merkleRoot) {\n throw new ValidationError(\"Block merkle root mismatch\");\n }\n\n // Verify block hash\n const expectedHash = computeBlockHash({\n height: block.height,\n previousHash: block.previousHash,\n timestamp: block.timestamp,\n merkleRoot: block.merkleRoot,\n stateRoot: block.stateRoot,\n proposer: block.proposer,\n });\n if (expectedHash !== block.hash) {\n throw new ValidationError(\"Block hash mismatch\");\n }\n}\n","import type { Block, HexString, Transaction } from \"../types.js\";\nimport { ChainError } from \"../errors.js\";\nimport { createGenesisBlock, createBlock, validateBlock } from \"./block.js\";\n\n/**\n * In-memory chain manager. Tracks the current chain tip and validates new blocks.\n * Backed by a storage layer for persistence.\n */\nexport class Chain {\n private tip: Block | null = null;\n private height = -1;\n\n /** Initialize chain with genesis block or restore from latest block. */\n init(latestBlock?: Block): void {\n if (latestBlock) {\n this.tip = latestBlock;\n this.height = latestBlock.height;\n }\n }\n\n /** Create and return a genesis block. */\n createGenesis(proposer: HexString): Block {\n if (this.height >= 0) {\n throw new ChainError(\"Chain already initialized\");\n }\n const genesis = createGenesisBlock(proposer);\n this.tip = genesis;\n this.height = 0;\n return genesis;\n }\n\n /** Propose a new block with the given transactions. Returns unsigned block. */\n proposeBlock(\n transactions: Transaction[],\n proposer: HexString,\n stateRoot: HexString,\n ): Block {\n if (!this.tip) {\n throw new ChainError(\"Chain not initialized\");\n }\n const block = createBlock({\n height: this.tip.height + 1,\n previousHash: this.tip.hash,\n transactions,\n proposer,\n stateRoot,\n });\n return block as Block;\n }\n\n /** Validate and append a block to the chain. */\n appendBlock(block: Block): void {\n validateBlock(block, this.tip ?? undefined);\n this.tip = block;\n this.height = block.height;\n }\n\n getTip(): Block | null {\n return this.tip;\n }\n\n getHeight(): number {\n return this.height;\n }\n}\n","import { serve } from \"@hono/node-server\";\nimport type { Command } from \"commander\";\nimport { DEFAULT_CONFIG } from \"../../config/index.js\";\nimport { MiniLedgerNode } from \"../../node.js\";\nimport { createApp } from \"../../api/server.js\";\n\nexport function registerStart(program: Command): void {\n program\n .command(\"start\")\n .description(\"Start the MiniLedger node\")\n .option(\"-d, --data-dir <path>\", \"Data directory\", DEFAULT_CONFIG.dataDir)\n .option(\"-p, --api-port <port>\", \"API port\", String(DEFAULT_CONFIG.network.apiPort))\n .option(\"--p2p-port <port>\", \"P2P port\", String(DEFAULT_CONFIG.network.p2pPort))\n .option(\"--peers <addresses>\", \"Comma-separated peer addresses (ws://host:port)\")\n .option(\"--consensus <algo>\", \"Consensus algorithm (solo|raft)\", DEFAULT_CONFIG.consensus.algorithm)\n .option(\"--no-api\", \"Disable REST API\")\n .action(async (opts) => {\n const peers = opts.peers ? (opts.peers as string).split(\",\").map((s: string) => s.trim()) : [];\n\n const node = await MiniLedgerNode.create({\n dataDir: opts.dataDir,\n config: {\n network: {\n ...DEFAULT_CONFIG.network,\n apiPort: Number.parseInt(opts.apiPort, 10),\n p2pPort: Number.parseInt(opts.p2pPort, 10),\n peers,\n },\n consensus: {\n ...DEFAULT_CONFIG.consensus,\n algorithm: opts.consensus as \"solo\" | \"raft\",\n },\n api: {\n ...DEFAULT_CONFIG.api,\n enabled: opts.api !== false,\n },\n },\n });\n\n await node.init();\n await node.start();\n\n // Start HTTP API\n if (node.config.api.enabled) {\n const app = createApp(node);\n serve({\n fetch: app.fetch,\n port: node.config.network.apiPort,\n });\n\n console.log(`REST API listening on http://localhost:${node.config.network.apiPort}`);\n }\n\n const status = node.getStatus();\n console.log(`\\nMiniLedger node running`);\n console.log(` Node ID: ${status.nodeId}`);\n console.log(` Consensus: ${node.config.consensus.algorithm}`);\n console.log(` Height: ${status.chainHeight}`);\n if (node.config.consensus.algorithm === \"raft\") {\n console.log(` P2P Port: ${node.config.network.p2pPort}`);\n if (peers.length > 0) console.log(` Peers: ${peers.join(\", \")}`);\n }\n console.log(`\\nPress Ctrl+C to stop\\n`);\n\n // Graceful shutdown\n const shutdown = async () => {\n console.log(\"\\nShutting down...\");\n await node.stop();\n process.exit(0);\n };\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n });\n}\n","import * as path from \"node:path\";\nimport * as fs from \"node:fs\";\nimport { EventEmitter } from \"node:events\";\nimport pino from \"pino\";\nimport type { Block, Transaction, NodeStatus, StateEntry, TxType } from \"./types.js\";\nimport { TxType as TxTypeEnum } from \"./types.js\";\nimport { PROTOCOL_VERSION, GENESIS_PROPOSER } from \"./constants.js\";\nimport { Chain, createTransaction, validateTransaction } from \"./core/index.js\";\nimport { MiniLedgerDB, BlockStore, StateStore, TxStore } from \"./storage/index.js\";\nimport {\n generateKeyPair,\n sign,\n verify,\n serializeKeystore,\n deserializeKeystore,\n encryptKeystore,\n decryptKeystore,\n type KeyPair,\n} from \"./identity/index.js\";\nimport { type MiniLedgerConfig, loadConfig } from \"./config/index.js\";\nimport { PeerManager } from \"./network/peer-manager.js\";\nimport { BlockSync } from \"./network/sync.js\";\nimport {\n MessageType,\n createMessage,\n type BlockAnnouncePayload,\n type TxBroadcastPayload,\n} from \"./network/protocol.js\";\nimport { RaftNode } from \"./consensus/raft/raft-node.js\";\nimport { shortId } from \"./utils.js\";\nimport { ContractRegistry, createContractContext } from \"./contracts/index.js\";\nimport { Governor } from \"./governance/governor.js\";\nimport { ProposalType } from \"./governance/proposal.js\";\n\n// Events: block:created, block:received, tx:submitted, tx:confirmed, started, stopped, error\n\nexport interface CreateNodeOptions {\n dataDir?: string;\n config?: Partial<MiniLedgerConfig>;\n}\n\nexport class MiniLedgerNode extends EventEmitter {\n readonly config: MiniLedgerConfig;\n readonly log: pino.Logger;\n\n private db!: MiniLedgerDB;\n private blockStore!: BlockStore;\n private stateStore!: StateStore;\n private txStore!: TxStore;\n private chain!: Chain;\n private keyPair!: KeyPair;\n private nodeId!: string;\n\n // Solo mode timer\n private blockTimer: ReturnType<typeof setInterval> | null = null;\n\n // Networking (M2)\n private peerManager: PeerManager | null = null;\n private blockSync: BlockSync | null = null;\n private raft: RaftNode | null = null;\n private raftBlockTimer: ReturnType<typeof setInterval> | null = null;\n\n // M3: Contracts + Governance\n private contractRegistry!: ContractRegistry;\n private governor!: Governor;\n\n private startedAt = 0;\n private running = false;\n\n constructor(config: MiniLedgerConfig) {\n super();\n this.config = config;\n this.log = pino({\n level: config.logging.level,\n transport: {\n target: \"pino/file\",\n options: { destination: 1 }, // stdout\n },\n });\n }\n\n /** Create a new MiniLedgerNode with optional overrides. */\n static async create(options: CreateNodeOptions = {}): Promise<MiniLedgerNode> {\n const config = loadConfig({\n dataDir: options.dataDir,\n ...options.config,\n });\n const node = new MiniLedgerNode(config);\n return node;\n }\n\n /** Initialize the node: open DB, load or create identity, restore chain. */\n async init(): Promise<void> {\n // Ensure data directory exists\n fs.mkdirSync(this.config.dataDir, { recursive: true });\n\n // Open database\n const dbPath = path.join(this.config.dataDir, \"ledger.db\");\n this.db = new MiniLedgerDB(dbPath);\n this.db.migrate();\n\n this.blockStore = new BlockStore(this.db.raw());\n this.stateStore = new StateStore(this.db.raw());\n this.txStore = new TxStore(this.db.raw());\n this.contractRegistry = new ContractRegistry(this.stateStore);\n this.governor = new Governor(this.stateStore);\n\n // Load or create keypair\n const keystorePath = path.join(this.config.dataDir, \"keystore.json\");\n if (fs.existsSync(keystorePath)) {\n const data = fs.readFileSync(keystorePath, \"utf-8\");\n const ks = deserializeKeystore(data);\n this.keyPair = decryptKeystore(ks, \"\");\n } else {\n this.keyPair = generateKeyPair();\n const ks = encryptKeystore(\n this.keyPair,\n \"\",\n this.config.node.orgId,\n this.config.node.name,\n );\n fs.writeFileSync(keystorePath, serializeKeystore(ks));\n }\n\n this.nodeId = shortId(this.keyPair.publicKey);\n\n // Initialize chain\n this.chain = new Chain();\n const latestBlock = this.blockStore.getLatest();\n if (latestBlock) {\n this.chain.init(latestBlock);\n this.log.info({ height: latestBlock.height }, \"Restored chain from storage\");\n } else {\n // Create genesis block\n const genesis = this.chain.createGenesis(GENESIS_PROPOSER);\n this.db.raw().transaction(() => {\n this.blockStore.insert(genesis);\n })();\n this.log.info(\"Created genesis block\");\n }\n }\n\n /** Start the node: begin producing blocks and serving API. */\n async start(): Promise<void> {\n if (this.running) return;\n this.running = true;\n this.startedAt = Date.now();\n\n if (this.config.consensus.algorithm === \"solo\") {\n // Solo mode: simple block production timer\n this.blockTimer = setInterval(() => {\n this.produceBlock().catch((err) => {\n this.log.error({ err }, \"Block production error\");\n this.emit(\"error\", err as Error);\n });\n }, this.config.consensus.blockTimeMs);\n } else if (this.config.consensus.algorithm === \"raft\") {\n // Raft mode: set up P2P + consensus\n await this.startNetworking();\n this.startRaftConsensus();\n }\n\n this.log.info(\n {\n nodeId: this.nodeId,\n consensus: this.config.consensus.algorithm,\n apiPort: this.config.api.enabled ? this.config.network.apiPort : \"disabled\",\n p2pPort: this.config.consensus.algorithm === \"raft\" ? this.config.network.p2pPort : \"disabled\",\n },\n \"Node started\",\n );\n this.emit(\"started\");\n }\n\n /** Stop the node. */\n async stop(): Promise<void> {\n if (!this.running) return;\n this.running = false;\n\n if (this.blockTimer) {\n clearInterval(this.blockTimer);\n this.blockTimer = null;\n }\n\n if (this.raftBlockTimer) {\n clearInterval(this.raftBlockTimer);\n this.raftBlockTimer = null;\n }\n\n if (this.raft) {\n this.raft.stop();\n this.raft = null;\n }\n\n if (this.peerManager) {\n this.peerManager.stop();\n this.peerManager = null;\n }\n\n this.blockSync = null;\n\n this.db.close();\n this.log.info(\"Node stopped\");\n this.emit(\"stopped\");\n }\n\n // ── Networking ──────────────────────────────────────────────────\n\n private async startNetworking(): Promise<void> {\n this.peerManager = new PeerManager({\n nodeId: this.nodeId,\n publicKey: this.keyPair.publicKey,\n orgId: this.config.node.orgId,\n p2pPort: this.config.network.p2pPort,\n listenAddress: this.config.network.listenAddress,\n log: this.log,\n getChainHeight: () => this.chain.getHeight(),\n });\n\n // Set up block announce handler\n this.peerManager.router.on(MessageType.BlockAnnounce, (msg) => {\n const payload = msg.payload as BlockAnnouncePayload;\n this.handleBlockAnnounce(payload.block);\n });\n\n // Set up tx broadcast handler\n this.peerManager.router.on(MessageType.TxBroadcast, (msg) => {\n const payload = msg.payload as TxBroadcastPayload;\n this.handleTxBroadcast(payload.transaction);\n });\n\n // Set up peer events\n this.peerManager.on(\"peer:connected\", (peerId: string) => {\n this.log.info({ peerId }, \"Peer connected\");\n // Trigger sync if the new peer might have blocks we don't\n if (this.blockSync) {\n this.blockSync.syncFromPeers().catch((err) => {\n this.log.warn({ err }, \"Sync after peer connect failed\");\n });\n }\n });\n\n // Set up block sync\n this.blockSync = new BlockSync({\n nodeId: this.nodeId,\n log: this.log,\n peerManager: this.peerManager,\n getChainHeight: () => this.chain.getHeight(),\n getBlocks: (from, to) => this.blockStore.getRange(from, to),\n applyBlock: (block) => this.applyReceivedBlock(block),\n });\n\n await this.peerManager.start();\n\n // Connect to initial peers\n for (const addr of this.config.network.peers) {\n this.peerManager.connectTo(addr);\n }\n }\n\n private startRaftConsensus(): void {\n if (!this.peerManager) return;\n\n this.raft = new RaftNode({\n nodeId: this.nodeId,\n peerManager: this.peerManager,\n log: this.log,\n blockTimeMs: this.config.consensus.blockTimeMs,\n });\n\n // When raft commits a block, apply it\n this.raft.onBlockCommitted = (block: Block) => {\n this.applyReceivedBlock(block);\n };\n\n // When raft receives a forwarded tx, add to pending pool\n this.raft.onTransactionReceived = (tx: Transaction) => {\n this.txStore.addToPending(tx);\n };\n\n // When we become leader, start block production\n this.raft.on(\"leader\", () => {\n this.log.info(\"This node is now the Raft leader — starting block production\");\n if (this.raftBlockTimer) clearInterval(this.raftBlockTimer);\n this.raftBlockTimer = setInterval(() => {\n this.produceRaftBlock().catch((err) => {\n this.log.error({ err }, \"Raft block production error\");\n });\n }, this.config.consensus.blockTimeMs);\n });\n\n this.raft.start();\n }\n\n // ── Block handling ──────────────────────────────────────────────\n\n private handleBlockAnnounce(block: Block): void {\n // In Raft mode, blocks come through consensus, not direct announce\n // This handler is for future non-Raft modes\n if (this.config.consensus.algorithm !== \"raft\") {\n this.applyReceivedBlock(block);\n }\n }\n\n private handleTxBroadcast(tx: Transaction): void {\n // Don't re-add if we already have it\n const existing = this.txStore.getByHash(tx.hash);\n if (existing) return;\n\n // Validate\n try {\n validateTransaction(tx);\n if (!verify(tx.hash, tx.signature, tx.sender)) return;\n } catch {\n return;\n }\n\n this.txStore.addToPending(tx);\n }\n\n /** Apply a block received from network/consensus. */\n private applyReceivedBlock(block: Block): void {\n try {\n // Apply transactions to state\n this.db.raw().transaction(() => {\n for (const tx of block.transactions) {\n this.applyTransaction(tx, block.height);\n }\n\n this.chain.appendBlock(block);\n this.blockStore.insert(block);\n\n // Remove confirmed tx from pending pool\n this.txStore.removePending(block.transactions.map((tx) => tx.hash));\n for (const tx of block.transactions) {\n this.txStore.updateNonce(tx.sender, tx.nonce);\n }\n })();\n\n this.log.info({ height: block.height, txCount: block.transactions.length }, \"Block applied\");\n this.emit(\"block:received\", block);\n } catch (err) {\n this.log.warn({ err, height: block.height }, \"Failed to apply received block\");\n }\n }\n\n // ── Transaction submission ──────────────────────────────────────\n\n /** Submit a transaction to the node. */\n async submit(params: {\n type?: TxType;\n key?: string;\n value?: unknown;\n payload?: Transaction[\"payload\"];\n }): Promise<Transaction> {\n const sender = this.keyPair.publicKey;\n const nonce = this.txStore.getNextNonce(sender);\n\n let payload: Transaction[\"payload\"];\n if (params.payload) {\n payload = params.payload;\n } else if (params.key !== undefined) {\n if (params.value === undefined || params.value === null) {\n payload = { kind: \"state:delete\", key: params.key };\n } else {\n payload = { kind: \"state:set\", key: params.key, value: params.value };\n }\n } else {\n throw new Error(\"Either payload or key must be provided\");\n }\n\n const txType = params.type ?? (payload.kind === \"state:delete\" ? TxTypeEnum.StateDelete : TxTypeEnum.StateSet);\n\n const unsignedTx = createTransaction({\n type: txType,\n sender,\n nonce,\n payload,\n });\n\n // Sign\n const signature = sign(unsignedTx.hash, this.keyPair.privateKey);\n const tx: Transaction = { ...unsignedTx, signature };\n\n // Validate\n validateTransaction(tx);\n\n // Verify signature\n if (!verify(tx.hash, tx.signature, tx.sender)) {\n throw new Error(\"Transaction signature verification failed\");\n }\n\n // Add to pending pool\n this.txStore.addToPending(tx);\n\n // In Raft mode, if we're not the leader, forward to leader\n if (this.raft && !this.raft.isLeader()) {\n this.raft.forwardToLeader(tx);\n }\n\n // Broadcast to peers\n if (this.peerManager) {\n this.peerManager.broadcast(\n createMessage(MessageType.TxBroadcast, this.nodeId, { transaction: tx } as TxBroadcastPayload),\n );\n }\n\n this.emit(\"tx:submitted\", tx);\n this.log.debug({ hash: tx.hash, type: tx.type }, \"Transaction submitted\");\n\n return tx;\n }\n\n // ── Block production ────────────────────────────────────────────\n\n /** Produce a block in solo mode. */\n private async produceBlock(): Promise<Block | null> {\n const pending = this.txStore.getPending(this.config.consensus.maxTxPerBlock);\n\n const applied: Transaction[] = [];\n this.db.raw().transaction(() => {\n for (const tx of pending) {\n try {\n this.applyTransaction(tx, this.chain.getHeight() + 1);\n applied.push(tx);\n } catch (err) {\n this.log.warn({ hash: tx.hash, err }, \"Failed to apply transaction\");\n }\n }\n\n if (applied.length === 0) return;\n\n const stateRoot = this.stateStore.computeStateRoot();\n const block = this.chain.proposeBlock(applied, this.keyPair.publicKey, stateRoot);\n const signature = sign(block.hash, this.keyPair.privateKey);\n const signedBlock: Block = { ...block, signature };\n\n this.chain.appendBlock(signedBlock);\n this.blockStore.insert(signedBlock);\n this.txStore.removePending(applied.map((tx) => tx.hash));\n\n for (const tx of applied) {\n this.txStore.updateNonce(tx.sender, tx.nonce);\n }\n\n this.log.info({ height: signedBlock.height, txCount: applied.length }, \"Block produced\");\n this.emit(\"block:created\", signedBlock);\n })();\n\n return this.chain.getTip();\n }\n\n /** Produce a block as Raft leader — propose it through consensus. */\n private async produceRaftBlock(): Promise<void> {\n if (!this.raft || !this.raft.isLeader()) return;\n\n const pending = this.txStore.getPending(this.config.consensus.maxTxPerBlock);\n if (pending.length === 0) return;\n\n // Build the block\n const stateRoot = this.stateStore.computeStateRoot();\n const block = this.chain.proposeBlock(pending, this.keyPair.publicKey, stateRoot);\n const signature = sign(block.hash, this.keyPair.privateKey);\n const signedBlock: Block = { ...block, signature };\n\n // Propose through Raft — will be applied when committed via onBlockCommitted callback\n this.raft.proposeBlock(signedBlock);\n }\n\n // ── State application ───────────────────────────────────────────\n\n /** Apply a single transaction to the world state. */\n private applyTransaction(tx: Transaction, blockHeight: number): void {\n const { payload } = tx;\n\n switch (payload.kind) {\n case \"state:set\":\n this.stateStore.set(payload.key, payload.value, tx.sender, blockHeight);\n break;\n case \"state:delete\":\n this.stateStore.delete(payload.key);\n break;\n case \"contract:deploy\":\n this.contractRegistry.deploy(\n payload.name,\n payload.version,\n payload.code,\n tx.sender,\n blockHeight,\n );\n this.log.info({ contract: payload.name, version: payload.version }, \"Contract deployed\");\n break;\n case \"contract:invoke\": {\n const ctx = createContractContext({\n stateStore: this.stateStore,\n sender: tx.sender,\n blockHeight,\n timestamp: tx.timestamp,\n });\n this.contractRegistry.invoke(payload.contract, payload.method, ctx, payload.args);\n break;\n }\n case \"governance:propose\":\n this.governor.propose({\n type: (payload.action?.type as ProposalType) ?? ProposalType.Custom,\n title: payload.title,\n description: payload.description,\n proposer: tx.sender,\n action: payload.action,\n blockHeight,\n });\n this.log.info({ title: payload.title }, \"Proposal created\");\n break;\n case \"governance:vote\":\n this.governor.vote(payload.proposalId, tx.sender, payload.vote, blockHeight);\n break;\n default:\n this.log.warn({ type: tx.type }, \"Unhandled transaction type\");\n }\n }\n\n // ── Queries ─────────────────────────────────────────────────────\n\n async query(sql: string, params: unknown[] = []): Promise<Record<string, unknown>[]> {\n return this.stateStore.query(sql, params);\n }\n\n async getState(key: string): Promise<StateEntry | null> {\n return this.stateStore.get(key);\n }\n\n async getBlock(height: number): Promise<Block | null> {\n return this.blockStore.getByHeight(height);\n }\n\n async getLatestBlock(): Promise<Block | null> {\n return this.blockStore.getLatest();\n }\n\n async getTransaction(hash: string): Promise<Transaction | null> {\n return this.txStore.getByHash(hash);\n }\n\n getStatus(): NodeStatus {\n const tip = this.chain.getTip();\n return {\n nodeId: this.nodeId,\n publicKey: this.keyPair.publicKey,\n chainHeight: this.chain.getHeight(),\n latestBlockHash: tip?.hash ?? \"\",\n peerCount: this.peerManager?.getPeerCount() ?? 0,\n txPoolSize: this.txStore.pendingCount(),\n uptime: this.running ? Date.now() - this.startedAt : 0,\n version: PROTOCOL_VERSION,\n };\n }\n\n getPublicKey(): string {\n return this.keyPair.publicKey;\n }\n\n getNodeId(): string {\n return this.nodeId;\n }\n\n getStores() {\n return {\n blocks: this.blockStore,\n state: this.stateStore,\n txs: this.txStore,\n };\n }\n\n getDatabase() {\n return this.db;\n }\n\n getPeerManager(): PeerManager | null {\n return this.peerManager;\n }\n\n getRaft(): RaftNode | null {\n return this.raft;\n }\n\n getContractRegistry(): ContractRegistry {\n return this.contractRegistry;\n }\n\n getGovernor(): Governor {\n return this.governor;\n }\n\n isRunning(): boolean {\n return this.running;\n }\n}\n","export type HexString = string;\n\nexport enum TxType {\n StateSet = \"state:set\",\n StateDelete = \"state:delete\",\n ContractDeploy = \"contract:deploy\",\n ContractInvoke = \"contract:invoke\",\n GovernancePropose = \"governance:propose\",\n GovernanceVote = \"governance:vote\",\n}\n\nexport interface StateSetPayload {\n kind: \"state:set\";\n key: string;\n value: unknown;\n}\n\nexport interface StateDeletePayload {\n kind: \"state:delete\";\n key: string;\n}\n\nexport interface ContractDeployPayload {\n kind: \"contract:deploy\";\n name: string;\n version: string;\n code: string;\n}\n\nexport interface ContractInvokePayload {\n kind: \"contract:invoke\";\n contract: string;\n method: string;\n args: unknown[];\n}\n\nexport interface GovernanceProposePayload {\n kind: \"governance:propose\";\n title: string;\n description: string;\n action: Record<string, unknown>;\n}\n\nexport interface GovernanceVotePayload {\n kind: \"governance:vote\";\n proposalId: string;\n vote: boolean;\n}\n\nexport type TxPayload =\n | StateSetPayload\n | StateDeletePayload\n | ContractDeployPayload\n | ContractInvokePayload\n | GovernanceProposePayload\n | GovernanceVotePayload;\n\nexport interface Transaction {\n hash: HexString;\n type: TxType;\n sender: HexString;\n nonce: number;\n timestamp: number;\n payload: TxPayload;\n signature: HexString;\n}\n\nexport interface Block {\n height: number;\n hash: HexString;\n previousHash: HexString;\n timestamp: number;\n merkleRoot: HexString;\n stateRoot: HexString;\n proposer: HexString;\n signature: HexString;\n transactions: Transaction[];\n}\n\nexport interface StateEntry {\n key: string;\n value: unknown;\n version: number;\n updatedAt: number;\n updatedBy: HexString;\n blockHeight: number;\n}\n\nexport interface PeerInfo {\n id: string;\n publicKey: HexString;\n address: string;\n orgId: string;\n role: \"validator\" | \"observer\";\n status: \"connected\" | \"disconnected\" | \"syncing\";\n lastSeen: number;\n chainHeight: number;\n}\n\nexport interface NodeIdentity {\n publicKey: HexString;\n nodeId: string;\n orgId: string;\n name: string;\n role: \"admin\" | \"member\" | \"observer\";\n createdAt: number;\n}\n\nexport interface NodeStatus {\n nodeId: string;\n publicKey: HexString;\n chainHeight: number;\n latestBlockHash: HexString;\n peerCount: number;\n txPoolSize: number;\n uptime: number;\n version: number;\n}\n","import type { HexString, Transaction, TxPayload, TxType } from \"../types.js\";\nimport { ValidationError } from \"../errors.js\";\nimport { nowMs } from \"../utils.js\";\nimport { sha256Hex } from \"./hash.js\";\nimport { canonicalize } from \"./serialization.js\";\n\nexport interface CreateTxParams {\n type: TxType;\n sender: HexString;\n nonce: number;\n payload: TxPayload;\n timestamp?: number;\n}\n\n/** Compute the canonical hash of a transaction (excludes hash and signature fields). */\nexport function computeTxHash(tx: CreateTxParams): string {\n const canonical = canonicalize({\n type: tx.type,\n sender: tx.sender,\n nonce: tx.nonce,\n timestamp: tx.timestamp,\n payload: tx.payload,\n });\n return sha256Hex(canonical);\n}\n\n/** Create an unsigned transaction. Signature must be added separately. */\nexport function createTransaction(params: CreateTxParams): Omit<Transaction, \"signature\"> & { signature: \"\" } {\n const timestamp = params.timestamp ?? nowMs();\n const withTimestamp = { ...params, timestamp };\n const hash = computeTxHash(withTimestamp);\n return {\n hash,\n type: params.type,\n sender: params.sender,\n nonce: params.nonce,\n timestamp,\n payload: params.payload,\n signature: \"\",\n };\n}\n\n/** Validate a transaction's structural integrity (does not check signature). */\nexport function validateTransaction(tx: Transaction): void {\n if (!tx.hash || tx.hash.length !== 64) {\n throw new ValidationError(\"Invalid transaction hash\");\n }\n if (!tx.sender || tx.sender.length !== 64) {\n throw new ValidationError(\"Invalid sender public key\");\n }\n if (tx.nonce < 0 || !Number.isInteger(tx.nonce)) {\n throw new ValidationError(\"Invalid nonce\");\n }\n if (!tx.payload || !tx.payload.kind) {\n throw new ValidationError(\"Missing transaction payload\");\n }\n\n // Verify hash matches content\n const expectedHash = computeTxHash({\n type: tx.type,\n sender: tx.sender,\n nonce: tx.nonce,\n timestamp: tx.timestamp,\n payload: tx.payload,\n });\n if (expectedHash !== tx.hash) {\n throw new ValidationError(\"Transaction hash mismatch\");\n }\n}\n","import type Database from \"better-sqlite3\";\nimport type { StateEntry } from \"../types.js\";\nimport { canonicalize } from \"../core/serialization.js\";\nimport { sha256Hex } from \"../core/hash.js\";\nimport { QueryCache } from \"./queries.js\";\n\nexport class StateStore {\n private q: QueryCache;\n private db: Database.Database;\n\n constructor(db: Database.Database) {\n this.db = db;\n this.q = new QueryCache(db);\n }\n\n get(key: string): StateEntry | null {\n const row = this.q.prepare(\"SELECT * FROM world_state WHERE key = ?\").get(key) as\n | {\n key: string;\n value: string;\n version: number;\n updated_at: number;\n updated_by: string;\n block_height: number;\n }\n | undefined;\n if (!row) return null;\n return {\n key: row.key,\n value: JSON.parse(row.value),\n version: row.version,\n updatedAt: row.updated_at,\n updatedBy: row.updated_by,\n blockHeight: row.block_height,\n };\n }\n\n set(\n key: string,\n value: unknown,\n updatedBy: string,\n blockHeight: number,\n ): void {\n const existing = this.q\n .prepare(\"SELECT version FROM world_state WHERE key = ?\")\n .get(key) as { version: number } | undefined;\n\n const version = existing ? existing.version + 1 : 1;\n const serialized = canonicalize(value);\n\n this.q\n .prepare(\n `INSERT INTO world_state (key, value, version, updated_at, updated_by, block_height)\n VALUES (?, ?, ?, ?, ?, ?)\n ON CONFLICT(key) DO UPDATE SET\n value = excluded.value,\n version = excluded.version,\n updated_at = excluded.updated_at,\n updated_by = excluded.updated_by,\n block_height = excluded.block_height`,\n )\n .run(key, serialized, version, Date.now(), updatedBy, blockHeight);\n }\n\n delete(key: string): boolean {\n const result = this.q.prepare(\"DELETE FROM world_state WHERE key = ?\").run(key);\n return result.changes > 0;\n }\n\n /** Execute a read-only SQL query against the world_state table. */\n query(sql: string, params: unknown[] = []): Record<string, unknown>[] {\n // Only allow SELECT queries for safety\n const trimmed = sql.trim().toUpperCase();\n if (!trimmed.startsWith(\"SELECT\")) {\n throw new Error(\"Only SELECT queries are allowed\");\n }\n return this.db.prepare(sql).all(...params) as Record<string, unknown>[];\n }\n\n /** Compute a hash of the entire world state (for stateRoot). */\n computeStateRoot(): string {\n const rows = this.q\n .prepare(\"SELECT key, value, version FROM world_state ORDER BY key ASC\")\n .all() as { key: string; value: string; version: number }[];\n\n if (rows.length === 0) {\n return \"0\".repeat(64);\n }\n\n const stateString = rows\n .map((r) => `${r.key}:${r.value}:${r.version}`)\n .join(\"|\");\n return sha256Hex(stateString);\n }\n\n count(): number {\n const row = this.q.prepare(\"SELECT COUNT(*) as c FROM world_state\").get() as { c: number };\n return row.c;\n }\n}\n","import type Database from \"better-sqlite3\";\nimport type { Transaction } from \"../types.js\";\nimport { canonicalize } from \"../core/serialization.js\";\nimport { QueryCache } from \"./queries.js\";\n\nexport class TxStore {\n private q: QueryCache;\n\n constructor(db: Database.Database) {\n this.q = new QueryCache(db);\n }\n\n getByHash(hash: string): Transaction | null {\n const row = this.q.prepare(\"SELECT * FROM transactions WHERE hash = ?\").get(hash) as\n | {\n hash: string;\n type: string;\n sender: string;\n nonce: number;\n timestamp: number;\n payload: string;\n signature: string;\n block_height: number | null;\n position: number | null;\n status: string;\n }\n | undefined;\n if (!row) return null;\n return {\n hash: row.hash,\n type: row.type as Transaction[\"type\"],\n sender: row.sender,\n nonce: row.nonce,\n timestamp: row.timestamp,\n payload: JSON.parse(row.payload),\n signature: row.signature,\n };\n }\n\n getBySender(sender: string, limit = 100): Transaction[] {\n const rows = this.q\n .prepare(\n \"SELECT * FROM transactions WHERE sender = ? ORDER BY timestamp DESC LIMIT ?\",\n )\n .all(sender, limit) as {\n hash: string;\n type: string;\n sender: string;\n nonce: number;\n timestamp: number;\n payload: string;\n signature: string;\n }[];\n\n return rows.map((r) => ({\n hash: r.hash,\n type: r.type as Transaction[\"type\"],\n sender: r.sender,\n nonce: r.nonce,\n timestamp: r.timestamp,\n payload: JSON.parse(r.payload),\n signature: r.signature,\n }));\n }\n\n /** Add a transaction to the pending pool. */\n addToPending(tx: Transaction): void {\n this.q\n .prepare(\"INSERT OR IGNORE INTO tx_pool (hash, raw, received, priority) VALUES (?, ?, ?, 0)\")\n .run(tx.hash, canonicalize(tx), Date.now());\n }\n\n /** Get all pending transactions, ordered by received time. */\n getPending(limit = 500): Transaction[] {\n const rows = this.q\n .prepare(\"SELECT raw FROM tx_pool ORDER BY priority DESC, received ASC LIMIT ?\")\n .all(limit) as { raw: string }[];\n return rows.map((r) => JSON.parse(r.raw) as Transaction);\n }\n\n /** Remove transactions from the pending pool (after inclusion in a block). */\n removePending(hashes: string[]): void {\n if (hashes.length === 0) return;\n const placeholders = hashes.map(() => \"?\").join(\",\");\n this.q.prepare(`DELETE FROM tx_pool WHERE hash IN (${placeholders})`).run(...hashes);\n }\n\n pendingCount(): number {\n const row = this.q.prepare(\"SELECT COUNT(*) as c FROM tx_pool\").get() as { c: number };\n return row.c;\n }\n\n /** Get the next nonce for a sender. */\n getNextNonce(sender: string): number {\n const row = this.q.prepare(\"SELECT nonce FROM nonces WHERE sender = ?\").get(sender) as\n | { nonce: number }\n | undefined;\n return row ? row.nonce + 1 : 0;\n }\n\n /** Update the nonce tracker for a sender. */\n updateNonce(sender: string, nonce: number): void {\n this.q\n .prepare(\n \"INSERT INTO nonces (sender, nonce) VALUES (?, ?) ON CONFLICT(sender) DO UPDATE SET nonce = excluded.nonce\",\n )\n .run(sender, nonce);\n }\n}\n","import type pino from \"pino\";\nimport { EventEmitter } from \"node:events\";\nimport { Peer, type PeerState } from \"./peer.js\";\nimport { WsServer } from \"./ws-server.js\";\nimport { WsClient } from \"./ws-client.js\";\nimport { MessageRouter } from \"./router.js\";\nimport {\n type MessageEnvelope,\n MessageType,\n createMessage,\n type HandshakePayload,\n type HandshakeAckPayload,\n type PingPayload,\n type PongPayload,\n type PeerListPayload,\n} from \"./protocol.js\";\nimport type { HexString } from \"../types.js\";\n\nexport interface PeerManagerOptions {\n nodeId: string;\n publicKey: HexString;\n orgId: string;\n p2pPort: number;\n listenAddress: string;\n log: pino.Logger;\n getChainHeight: () => number;\n}\n\n// Events: peer:connected, peer:disconnected, peer:handshake, message:<MessageType>\nexport class PeerManager extends EventEmitter {\n readonly router: MessageRouter;\n private server: WsServer;\n private client: WsClient;\n private peers = new Map<string, Peer>(); // nodeId -> Peer\n private opts: PeerManagerOptions;\n private healthTimer: ReturnType<typeof setInterval> | null = null;\n\n constructor(opts: PeerManagerOptions) {\n super();\n this.opts = opts;\n this.router = new MessageRouter();\n\n // Wire up built-in message handlers\n this.router.on(MessageType.Handshake, this.handleHandshake.bind(this));\n this.router.on(MessageType.HandshakeAck, this.handleHandshakeAck.bind(this));\n this.router.on(MessageType.Ping, this.handlePing.bind(this));\n this.router.on(MessageType.Pong, this.handlePong.bind(this));\n this.router.on(MessageType.PeerList, this.handlePeerList.bind(this));\n\n // Create server and client\n this.server = new WsServer({\n port: opts.p2pPort,\n host: opts.listenAddress,\n log: opts.log,\n router: this.router,\n onPeerConnected: (peer) => this.onRawPeerConnected(peer),\n onPeerDisconnected: (peer) => this.onRawPeerDisconnected(peer),\n });\n\n this.client = new WsClient({\n log: opts.log,\n router: this.router,\n onPeerConnected: (peer) => {\n this.onRawPeerConnected(peer);\n // Outbound connections send handshake first\n this.sendHandshake(peer);\n },\n onPeerDisconnected: (peer) => this.onRawPeerDisconnected(peer),\n });\n }\n\n async start(): Promise<void> {\n await this.server.start();\n\n // Periodic health check / ping\n this.healthTimer = setInterval(() => {\n this.pingAll();\n }, 5000);\n }\n\n stop(): void {\n if (this.healthTimer) {\n clearInterval(this.healthTimer);\n this.healthTimer = null;\n }\n this.client.stop();\n this.server.stop();\n for (const peer of this.peers.values()) {\n peer.close();\n }\n this.peers.clear();\n }\n\n /** Connect to a peer by address (ws://host:port). */\n connectTo(address: string): void {\n this.client.connect(address);\n }\n\n /** Broadcast a message to all connected peers. */\n broadcast(msg: MessageEnvelope): void {\n for (const peer of this.peers.values()) {\n if (peer.status === \"connected\") {\n peer.send(msg);\n }\n }\n }\n\n /** Send a message to a specific peer by nodeId. */\n sendTo(nodeId: string, msg: MessageEnvelope): void {\n const peer = this.peers.get(nodeId);\n if (peer && peer.status === \"connected\") {\n peer.send(msg);\n }\n }\n\n /** Send to leader or a specific peer. */\n sendToPeer(peer: Peer, msg: MessageEnvelope): void {\n peer.send(msg);\n }\n\n getPeer(nodeId: string): Peer | undefined {\n return this.peers.get(nodeId);\n }\n\n getConnectedPeers(): Peer[] {\n return Array.from(this.peers.values()).filter((p) => p.status === \"connected\");\n }\n\n getPeerStates(): PeerState[] {\n return Array.from(this.peers.values()).map((p) => p.toInfo());\n }\n\n getPeerCount(): number {\n return this.getConnectedPeers().length;\n }\n\n /** Get all known node IDs (for Raft voter list). */\n getKnownNodeIds(): string[] {\n return Array.from(this.peers.values())\n .filter((p) => p.status === \"connected\")\n .map((p) => p.nodeId);\n }\n\n // ── Internal handlers ──────────────────────────────────────────\n\n private onRawPeerConnected(peer: Peer): void {\n this.opts.log.debug({ peerId: peer.nodeId, address: peer.address }, \"Raw peer connected\");\n }\n\n private onRawPeerDisconnected(peer: Peer): void {\n const knownPeer = this.peers.get(peer.nodeId);\n if (knownPeer) {\n this.peers.delete(peer.nodeId);\n this.opts.log.info({ peerId: peer.nodeId }, \"Peer disconnected\");\n this.emit(\"peer:disconnected\", peer.nodeId);\n }\n }\n\n private sendHandshake(peer: Peer): void {\n const payload: HandshakePayload = {\n nodeId: this.opts.nodeId,\n publicKey: this.opts.publicKey,\n orgId: this.opts.orgId,\n chainHeight: this.opts.getChainHeight(),\n listenPort: this.opts.p2pPort,\n };\n peer.send(createMessage(MessageType.Handshake, this.opts.nodeId, payload));\n }\n\n private handleHandshake(msg: MessageEnvelope, peer: Peer): void {\n const payload = msg.payload as HandshakePayload;\n\n // Reject self-connections\n if (payload.nodeId === this.opts.nodeId) {\n peer.close();\n return;\n }\n\n // Reject duplicate connections\n if (this.peers.has(payload.nodeId)) {\n peer.close();\n return;\n }\n\n // Update peer info from handshake\n peer.publicKey = payload.publicKey;\n peer.orgId = payload.orgId;\n peer.chainHeight = payload.chainHeight;\n\n // Build the peer's listen address from handshake info\n if (payload.listenPort) {\n const host = payload.listenAddress || peer.address.replace(/^ws:\\/\\//, \"\").split(\":\")[0] || \"127.0.0.1\";\n peer.address = `ws://${host}:${payload.listenPort}`;\n }\n\n // Replace temp nodeId with real one\n const realNodeId = payload.nodeId;\n (peer as any).nodeId = realNodeId;\n\n // Register peer\n peer.status = \"connected\";\n this.peers.set(realNodeId, peer);\n\n // Send ack\n const ack: HandshakeAckPayload = {\n nodeId: this.opts.nodeId,\n publicKey: this.opts.publicKey,\n orgId: this.opts.orgId,\n chainHeight: this.opts.getChainHeight(),\n accepted: true,\n };\n peer.send(createMessage(MessageType.HandshakeAck, this.opts.nodeId, ack));\n\n this.opts.log.info({ peerId: realNodeId, orgId: payload.orgId, height: payload.chainHeight }, \"Peer handshake complete (inbound)\");\n this.emit(\"peer:connected\", realNodeId, peer);\n\n // Share peer list\n this.sharePeerList(peer);\n }\n\n private handleHandshakeAck(msg: MessageEnvelope, peer: Peer): void {\n const payload = msg.payload as HandshakeAckPayload;\n\n if (!payload.accepted) {\n this.opts.log.warn({ reason: payload.reason }, \"Handshake rejected\");\n peer.close();\n return;\n }\n\n // Update peer info\n peer.publicKey = payload.publicKey;\n peer.orgId = payload.orgId;\n peer.chainHeight = payload.chainHeight;\n\n const realNodeId = payload.nodeId;\n (peer as any).nodeId = realNodeId;\n\n peer.status = \"connected\";\n this.peers.set(realNodeId, peer);\n\n this.opts.log.info({ peerId: realNodeId, orgId: payload.orgId, height: payload.chainHeight }, \"Peer handshake complete (outbound)\");\n this.emit(\"peer:connected\", realNodeId, peer);\n }\n\n private handlePing(msg: MessageEnvelope, peer: Peer): void {\n const payload = msg.payload as PingPayload;\n peer.chainHeight = payload.chainHeight;\n peer.send(createMessage(MessageType.Pong, this.opts.nodeId, {\n chainHeight: this.opts.getChainHeight(),\n } as PongPayload));\n }\n\n private handlePong(msg: MessageEnvelope, peer: Peer): void {\n const payload = msg.payload as PongPayload;\n peer.chainHeight = payload.chainHeight;\n }\n\n private handlePeerList(msg: MessageEnvelope, _peer: Peer): void {\n const payload = msg.payload as PeerListPayload;\n for (const p of payload.peers) {\n // Don't connect to ourselves or already-known peers\n if (p.nodeId === this.opts.nodeId) continue;\n if (this.peers.has(p.nodeId)) continue;\n if (p.address) {\n this.opts.log.debug({ address: p.address, nodeId: p.nodeId }, \"Discovered peer from peer list\");\n this.connectTo(p.address);\n }\n }\n }\n\n private sharePeerList(peer: Peer): void {\n const peerList: PeerListPayload = {\n peers: Array.from(this.peers.values())\n .filter((p) => p.nodeId !== peer.nodeId && p.status === \"connected\")\n .map((p) => ({\n nodeId: p.nodeId,\n publicKey: p.publicKey,\n address: p.address,\n orgId: p.orgId,\n })),\n };\n peer.send(createMessage(MessageType.PeerList, this.opts.nodeId, peerList));\n }\n\n private pingAll(): void {\n const payload: PingPayload = { chainHeight: this.opts.getChainHeight() };\n const msg = createMessage(MessageType.Ping, this.opts.nodeId, payload);\n this.broadcast(msg);\n }\n}\n","import { WebSocketServer, type WebSocket as WS } from \"ws\";\nimport type pino from \"pino\";\nimport { deserializeMessage } from \"./protocol.js\";\nimport { Peer } from \"./peer.js\";\nimport type { MessageRouter } from \"./router.js\";\n\nexport interface WsServerOptions {\n port: number;\n host: string;\n log: pino.Logger;\n router: MessageRouter;\n onPeerConnected: (peer: Peer) => void;\n onPeerDisconnected: (peer: Peer) => void;\n}\n\n/**\n * WebSocket server that accepts incoming peer connections.\n */\nexport class WsServer {\n private wss: WebSocketServer | null = null;\n private opts: WsServerOptions;\n\n constructor(opts: WsServerOptions) {\n this.opts = opts;\n }\n\n start(): Promise<void> {\n return new Promise((resolve, reject) => {\n this.wss = new WebSocketServer({\n port: this.opts.port,\n host: this.opts.host,\n });\n\n this.wss.on(\"listening\", () => {\n this.opts.log.info({ port: this.opts.port }, \"P2P server listening\");\n resolve();\n });\n\n this.wss.on(\"error\", (err) => {\n this.opts.log.error({ err }, \"P2P server error\");\n reject(err);\n });\n\n this.wss.on(\"connection\", (ws: WS, req) => {\n const remoteAddr = req.socket.remoteAddress ?? \"unknown\";\n const tempId = `inbound-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;\n\n const peer = new Peer(ws, {\n nodeId: tempId,\n address: remoteAddr,\n isInbound: true,\n });\n\n this.setupPeerHandlers(peer);\n this.opts.onPeerConnected(peer);\n });\n });\n }\n\n stop(): void {\n if (this.wss) {\n this.wss.close();\n this.wss = null;\n }\n }\n\n private setupPeerHandlers(peer: Peer): void {\n const ws = peer.getSocket();\n\n ws.on(\"message\", async (data: Buffer) => {\n try {\n const msg = deserializeMessage(data.toString());\n peer.updateSeen();\n await this.opts.router.dispatch(msg, peer);\n } catch (err) {\n this.opts.log.warn({ err, peer: peer.nodeId }, \"Failed to handle message\");\n }\n });\n\n ws.on(\"close\", () => {\n peer.status = \"disconnected\";\n this.opts.onPeerDisconnected(peer);\n });\n\n ws.on(\"error\", (err) => {\n this.opts.log.warn({ err, peer: peer.nodeId }, \"Peer connection error\");\n peer.status = \"disconnected\";\n });\n }\n}\n","import type { Block, Transaction, HexString } from \"../types.js\";\nimport { PROTOCOL_VERSION } from \"../constants.js\";\n\n// ── Message types ──────────────────────────────────────────────────\n\nexport enum MessageType {\n // Handshake\n Handshake = \"HANDSHAKE\",\n HandshakeAck = \"HANDSHAKE_ACK\",\n\n // Block propagation\n BlockAnnounce = \"BLOCK_ANNOUNCE\",\n BlockRequest = \"BLOCK_REQUEST\",\n BlockResponse = \"BLOCK_RESPONSE\",\n\n // Transaction propagation\n TxBroadcast = \"TX_BROADCAST\",\n TxForward = \"TX_FORWARD\", // Forward tx to leader\n\n // Consensus (Raft)\n ConsensusRequestVote = \"CONSENSUS_REQUEST_VOTE\",\n ConsensusRequestVoteReply = \"CONSENSUS_REQUEST_VOTE_REPLY\",\n ConsensusAppendEntries = \"CONSENSUS_APPEND_ENTRIES\",\n ConsensusAppendEntriesReply = \"CONSENSUS_APPEND_ENTRIES_REPLY\",\n\n // Sync\n SyncRequest = \"SYNC_REQUEST\",\n SyncResponse = \"SYNC_RESPONSE\",\n\n // Peer management\n PeerList = \"PEER_LIST\",\n\n // Heartbeat\n Ping = \"PING\",\n Pong = \"PONG\",\n}\n\n// ── Message envelope ───────────────────────────────────────────────\n\nexport interface MessageEnvelope<T = unknown> {\n version: number;\n type: MessageType;\n from: string; // sender nodeId (short 16-char)\n timestamp: number;\n payload: T;\n}\n\nexport function createMessage<T>(type: MessageType, from: string, payload: T): MessageEnvelope<T> {\n return {\n version: PROTOCOL_VERSION,\n type,\n from,\n timestamp: Date.now(),\n payload,\n };\n}\n\nexport function serializeMessage(msg: MessageEnvelope): string {\n return JSON.stringify(msg);\n}\n\nexport function deserializeMessage(data: string): MessageEnvelope {\n const msg = JSON.parse(data) as MessageEnvelope;\n if (!msg.type || !msg.from || msg.version === undefined) {\n throw new Error(\"Invalid message format\");\n }\n return msg;\n}\n\n// ── Payload types ──────────────────────────────────────────────────\n\nexport interface HandshakePayload {\n nodeId: string;\n publicKey: HexString;\n orgId: string;\n chainHeight: number;\n listenPort: number;\n listenAddress?: string;\n}\n\nexport interface HandshakeAckPayload {\n nodeId: string;\n publicKey: HexString;\n orgId: string;\n chainHeight: number;\n accepted: boolean;\n reason?: string;\n}\n\nexport interface BlockAnnouncePayload {\n block: Block;\n}\n\nexport interface BlockRequestPayload {\n fromHeight: number;\n toHeight: number;\n}\n\nexport interface BlockResponsePayload {\n blocks: Block[];\n}\n\nexport interface TxBroadcastPayload {\n transaction: Transaction;\n}\n\nexport interface TxForwardPayload {\n transaction: Transaction;\n}\n\nexport interface SyncRequestPayload {\n fromHeight: number;\n toHeight: number;\n}\n\nexport interface SyncResponsePayload {\n blocks: Block[];\n hasMore: boolean;\n}\n\nexport interface PeerListPayload {\n peers: {\n nodeId: string;\n publicKey: HexString;\n address: string;\n orgId: string;\n }[];\n}\n\nexport interface PingPayload {\n chainHeight: number;\n}\n\nexport interface PongPayload {\n chainHeight: number;\n}\n\n// ── Raft consensus payloads ────────────────────────────────────────\n\nexport interface RequestVotePayload {\n term: number;\n candidateId: string;\n lastLogIndex: number;\n lastLogTerm: number;\n}\n\nexport interface RequestVoteReplyPayload {\n term: number;\n voteGranted: boolean;\n}\n\nexport interface AppendEntriesPayload {\n term: number;\n leaderId: string;\n prevLogIndex: number;\n prevLogTerm: number;\n entries: RaftLogEntry[];\n leaderCommit: number;\n}\n\nexport interface AppendEntriesReplyPayload {\n term: number;\n success: boolean;\n matchIndex: number;\n}\n\nexport interface RaftLogEntry {\n term: number;\n index: number;\n block: Block;\n}\n","import type WebSocket from \"ws\";\nimport type { HexString } from \"../types.js\";\nimport {\n type MessageEnvelope,\n serializeMessage,\n} from \"./protocol.js\";\n\nexport interface PeerState {\n nodeId: string;\n publicKey: HexString;\n orgId: string;\n address: string;\n chainHeight: number;\n status: \"connecting\" | \"connected\" | \"disconnected\";\n lastSeen: number;\n isInbound: boolean;\n}\n\nexport class Peer {\n readonly nodeId: string;\n publicKey: HexString;\n orgId: string;\n address: string;\n chainHeight: number;\n status: \"connecting\" | \"connected\" | \"disconnected\";\n lastSeen: number;\n isInbound: boolean;\n\n private ws: WebSocket;\n\n constructor(ws: WebSocket, info: Partial<PeerState> & { nodeId: string; isInbound: boolean }) {\n this.ws = ws;\n this.nodeId = info.nodeId;\n this.publicKey = info.publicKey ?? \"\";\n this.orgId = info.orgId ?? \"\";\n this.address = info.address ?? \"\";\n this.chainHeight = info.chainHeight ?? 0;\n this.status = \"connecting\";\n this.lastSeen = Date.now();\n this.isInbound = info.isInbound;\n }\n\n send(msg: MessageEnvelope): void {\n if (this.ws.readyState === this.ws.OPEN) {\n this.ws.send(serializeMessage(msg));\n }\n }\n\n close(): void {\n this.status = \"disconnected\";\n if (this.ws.readyState === this.ws.OPEN || this.ws.readyState === this.ws.CONNECTING) {\n this.ws.close();\n }\n }\n\n getSocket(): WebSocket {\n return this.ws;\n }\n\n updateSeen(): void {\n this.lastSeen = Date.now();\n }\n\n toInfo(): PeerState {\n return {\n nodeId: this.nodeId,\n publicKey: this.publicKey,\n orgId: this.orgId,\n address: this.address,\n chainHeight: this.chainHeight,\n status: this.status,\n lastSeen: this.lastSeen,\n isInbound: this.isInbound,\n };\n }\n}\n","import WebSocket from \"ws\";\nimport type pino from \"pino\";\nimport { deserializeMessage } from \"./protocol.js\";\nimport { Peer } from \"./peer.js\";\nimport type { MessageRouter } from \"./router.js\";\n\nexport interface WsClientOptions {\n log: pino.Logger;\n router: MessageRouter;\n onPeerConnected: (peer: Peer) => void;\n onPeerDisconnected: (peer: Peer) => void;\n reconnectIntervalMs?: number;\n maxReconnectMs?: number;\n}\n\n/**\n * WebSocket client that connects to a remote peer with auto-reconnect.\n */\nexport class WsClient {\n private opts: WsClientOptions;\n private peers = new Map<string, { peer: Peer; reconnectTimer: ReturnType<typeof setTimeout> | null; attempt: number }>();\n private stopped = false;\n\n constructor(opts: WsClientOptions) {\n this.opts = opts;\n }\n\n /** Connect to a peer address. Returns immediately; connection is async. */\n connect(address: string): void {\n if (this.peers.has(address)) return; // Already connecting/connected\n\n this.peers.set(address, { peer: null as unknown as Peer, reconnectTimer: null, attempt: 0 });\n this.doConnect(address);\n }\n\n disconnect(address: string): void {\n const entry = this.peers.get(address);\n if (!entry) return;\n if (entry.reconnectTimer) clearTimeout(entry.reconnectTimer);\n entry.peer?.close();\n this.peers.delete(address);\n }\n\n stop(): void {\n this.stopped = true;\n for (const [, entry] of this.peers) {\n if (entry.reconnectTimer) clearTimeout(entry.reconnectTimer);\n entry.peer?.close();\n }\n this.peers.clear();\n }\n\n private doConnect(address: string): void {\n if (this.stopped) return;\n const entry = this.peers.get(address);\n if (!entry) return;\n\n const ws = new WebSocket(address);\n const tempId = `outbound-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;\n const peer = new Peer(ws, {\n nodeId: tempId,\n address,\n isInbound: false,\n });\n entry.peer = peer;\n\n ws.on(\"open\", () => {\n peer.status = \"connected\";\n entry.attempt = 0;\n this.opts.onPeerConnected(peer);\n });\n\n ws.on(\"message\", async (data: Buffer) => {\n try {\n const msg = deserializeMessage(data.toString());\n peer.updateSeen();\n await this.opts.router.dispatch(msg, peer);\n } catch (err) {\n this.opts.log.warn({ err, peer: peer.nodeId }, \"Failed to handle message from peer\");\n }\n });\n\n ws.on(\"close\", () => {\n peer.status = \"disconnected\";\n this.opts.onPeerDisconnected(peer);\n this.scheduleReconnect(address);\n });\n\n ws.on(\"error\", (err) => {\n this.opts.log.debug({ err: err.message, address }, \"Peer connection error\");\n // 'close' event will fire after this, triggering reconnect\n });\n }\n\n private scheduleReconnect(address: string): void {\n if (this.stopped) return;\n const entry = this.peers.get(address);\n if (!entry) return;\n\n entry.attempt++;\n const baseMs = this.opts.reconnectIntervalMs ?? 1000;\n const maxMs = this.opts.maxReconnectMs ?? 30000;\n const delay = Math.min(baseMs * Math.pow(1.5, entry.attempt - 1), maxMs);\n const jitter = delay * 0.2 * Math.random();\n\n this.opts.log.debug({ address, delay: Math.round(delay + jitter) }, \"Scheduling reconnect\");\n\n entry.reconnectTimer = setTimeout(() => {\n entry.reconnectTimer = null;\n this.doConnect(address);\n }, delay + jitter);\n }\n}\n","import { type MessageEnvelope, MessageType } from \"./protocol.js\";\nimport type { Peer } from \"./peer.js\";\n\nexport type MessageHandler = (msg: MessageEnvelope, peer: Peer) => void | Promise<void>;\n\n/**\n * Routes incoming messages to registered handlers by message type.\n */\nexport class MessageRouter {\n private handlers = new Map<MessageType, MessageHandler[]>();\n\n on(type: MessageType, handler: MessageHandler): void {\n const list = this.handlers.get(type) ?? [];\n list.push(handler);\n this.handlers.set(type, list);\n }\n\n off(type: MessageType, handler: MessageHandler): void {\n const list = this.handlers.get(type);\n if (!list) return;\n const idx = list.indexOf(handler);\n if (idx >= 0) list.splice(idx, 1);\n }\n\n async dispatch(msg: MessageEnvelope, peer: Peer): Promise<void> {\n const handlers = this.handlers.get(msg.type);\n if (!handlers || handlers.length === 0) return;\n for (const handler of handlers) {\n await handler(msg, peer);\n }\n }\n}\n","import type pino from \"pino\";\nimport type { Block } from \"../types.js\";\nimport type { PeerManager } from \"./peer-manager.js\";\nimport type { Peer } from \"./peer.js\";\nimport {\n MessageType,\n createMessage,\n type SyncRequestPayload,\n type SyncResponsePayload,\n type MessageEnvelope,\n} from \"./protocol.js\";\n\nconst SYNC_BATCH_SIZE = 50;\n\nexport interface SyncOptions {\n nodeId: string;\n log: pino.Logger;\n peerManager: PeerManager;\n getChainHeight: () => number;\n getBlocks: (from: number, to: number) => Block[];\n applyBlock: (block: Block) => void;\n}\n\n/**\n * Block sync protocol. Fetches missing blocks from peers to catch up.\n */\nexport class BlockSync {\n private opts: SyncOptions;\n private syncing = false;\n private pendingResolve: ((blocks: Block[]) => void) | null = null;\n\n constructor(opts: SyncOptions) {\n this.opts = opts;\n\n // Register handlers on the peer manager's router\n opts.peerManager.router.on(MessageType.SyncRequest, this.handleSyncRequest.bind(this));\n opts.peerManager.router.on(MessageType.SyncResponse, this.handleSyncResponse.bind(this));\n }\n\n /** Sync from peers if they have a higher chain. */\n async syncFromPeers(): Promise<void> {\n if (this.syncing) return;\n\n const peers = this.opts.peerManager.getConnectedPeers();\n if (peers.length === 0) return;\n\n // Find the peer with highest chain\n let bestPeer: Peer | null = null;\n let bestHeight = this.opts.getChainHeight();\n\n for (const peer of peers) {\n if (peer.chainHeight > bestHeight) {\n bestHeight = peer.chainHeight;\n bestPeer = peer;\n }\n }\n\n if (!bestPeer) return; // We're already at the highest\n\n this.syncing = true;\n this.opts.log.info(\n { peerId: bestPeer.nodeId, peerHeight: bestHeight, localHeight: this.opts.getChainHeight() },\n \"Starting sync\",\n );\n\n try {\n let currentHeight = this.opts.getChainHeight();\n\n while (currentHeight < bestHeight) {\n const from = currentHeight + 1;\n const to = Math.min(from + SYNC_BATCH_SIZE - 1, bestHeight);\n\n const blocks = await this.requestBlocks(bestPeer, from, to);\n if (blocks.length === 0) break;\n\n for (const block of blocks) {\n this.opts.applyBlock(block);\n }\n\n currentHeight = this.opts.getChainHeight();\n this.opts.log.debug({ height: currentHeight, target: bestHeight }, \"Sync progress\");\n }\n\n this.opts.log.info({ height: this.opts.getChainHeight() }, \"Sync complete\");\n } catch (err) {\n this.opts.log.error({ err }, \"Sync failed\");\n } finally {\n this.syncing = false;\n }\n }\n\n isSyncing(): boolean {\n return this.syncing;\n }\n\n /** Request blocks from a specific peer. Returns a promise that resolves when response arrives. */\n private requestBlocks(peer: Peer, fromHeight: number, toHeight: number): Promise<Block[]> {\n return new Promise((resolve) => {\n // Set up one-shot response handler\n this.pendingResolve = resolve;\n\n const payload: SyncRequestPayload = { fromHeight, toHeight };\n peer.send(createMessage(MessageType.SyncRequest, this.opts.nodeId, payload));\n\n // Timeout after 10 seconds\n setTimeout(() => {\n if (this.pendingResolve === resolve) {\n this.pendingResolve = null;\n resolve([]);\n }\n }, 10000);\n });\n }\n\n /** Handle incoming sync request: send requested blocks. */\n private handleSyncRequest(msg: MessageEnvelope, peer: Peer): void {\n const payload = msg.payload as SyncRequestPayload;\n const blocks = this.opts.getBlocks(payload.fromHeight, payload.toHeight);\n\n const response: SyncResponsePayload = {\n blocks,\n hasMore: payload.toHeight < this.opts.getChainHeight(),\n };\n\n peer.send(createMessage(MessageType.SyncResponse, this.opts.nodeId, response));\n }\n\n /** Handle incoming sync response: resolve pending request. */\n private handleSyncResponse(msg: MessageEnvelope, _peer: Peer): void {\n const payload = msg.payload as SyncResponsePayload;\n if (this.pendingResolve) {\n const resolve = this.pendingResolve;\n this.pendingResolve = null;\n resolve(payload.blocks);\n }\n }\n}\n","import type pino from \"pino\";\nimport { EventEmitter } from \"node:events\";\nimport type { Block, Transaction } from \"../../types.js\";\nimport { RaftRole, type ConsensusState, type IConsensus } from \"../types.js\";\nimport { RaftTimer } from \"./raft-timer.js\";\nimport { RaftLog } from \"./raft-log.js\";\nimport type { PeerManager } from \"../../network/peer-manager.js\";\nimport {\n MessageType,\n createMessage,\n type MessageEnvelope,\n type RequestVotePayload,\n type RequestVoteReplyPayload,\n type AppendEntriesPayload,\n type AppendEntriesReplyPayload,\n type RaftLogEntry,\n type TxForwardPayload,\n} from \"../../network/protocol.js\";\n\nexport interface RaftNodeOptions {\n nodeId: string;\n peerManager: PeerManager;\n log: pino.Logger;\n blockTimeMs: number;\n}\n\n/**\n * Raft consensus implementation.\n *\n * Key simplification: Raft log entries ARE block proposals.\n * A committed entry directly becomes a finalized block.\n */\nexport class RaftNode extends EventEmitter implements IConsensus {\n private opts: RaftNodeOptions;\n\n // Raft state\n private role: RaftRole = RaftRole.Follower;\n private currentTerm = 0;\n private votedFor: string | null = null;\n private leaderId: string | null = null;\n private raftLog = new RaftLog();\n private commitIndex = 0;\n private lastApplied = 0;\n\n // Leader state\n private nextIndex = new Map<string, number>(); // peer -> next log index to send\n private matchIndex = new Map<string, number>(); // peer -> highest replicated log index\n\n // Components\n private timer: RaftTimer;\n private blockProposalTimer: ReturnType<typeof setInterval> | null = null;\n\n // Callbacks set by the node orchestrator\n onBlockCommitted: ((block: Block) => void) | null = null;\n onTransactionReceived: ((tx: Transaction) => void) | null = null;\n\n constructor(opts: RaftNodeOptions) {\n super();\n this.opts = opts;\n\n this.timer = new RaftTimer({\n onElectionTimeout: () => this.startElection(),\n onHeartbeat: () => this.sendHeartbeats(),\n });\n\n // Register consensus message handlers\n const router = opts.peerManager.router;\n router.on(MessageType.ConsensusRequestVote, (msg) => this.handleRequestVote(msg));\n router.on(MessageType.ConsensusRequestVoteReply, (msg) => this.handleRequestVoteReply(msg));\n router.on(MessageType.ConsensusAppendEntries, (msg) => this.handleAppendEntries(msg));\n router.on(MessageType.ConsensusAppendEntriesReply, (msg) => this.handleAppendEntriesReply(msg));\n router.on(MessageType.TxForward, (msg, _peer) => {\n const payload = msg.payload as TxForwardPayload;\n if (this.role === RaftRole.Leader && this.onTransactionReceived) {\n this.onTransactionReceived(payload.transaction);\n }\n });\n }\n\n start(): void {\n this.role = RaftRole.Follower;\n this.timer.resetElectionTimer();\n this.opts.log.info({ nodeId: this.opts.nodeId }, \"Raft started as follower\");\n }\n\n stop(): void {\n this.timer.stopAll();\n if (this.blockProposalTimer) {\n clearInterval(this.blockProposalTimer);\n this.blockProposalTimer = null;\n }\n }\n\n isLeader(): boolean {\n return this.role === RaftRole.Leader;\n }\n\n getLeaderId(): string | null {\n return this.leaderId;\n }\n\n getState(): ConsensusState {\n return {\n role: this.role,\n term: this.currentTerm,\n leaderId: this.leaderId,\n votedFor: this.votedFor,\n commitIndex: this.commitIndex,\n };\n }\n\n /** Called by the node to propose a block (only works when leader). */\n proposeBlock(block: Block): void {\n if (this.role !== RaftRole.Leader) return;\n\n const entry: RaftLogEntry = {\n term: this.currentTerm,\n index: this.raftLog.getLastIndex() + 1,\n block,\n };\n\n this.raftLog.append(entry);\n\n // Update own matchIndex\n this.matchIndex.set(this.opts.nodeId, entry.index);\n\n // Replicate to peers immediately\n this.sendHeartbeats();\n\n // Check if we can commit (single-node cluster commits immediately)\n this.advanceCommitIndex();\n }\n\n /** Forward a transaction to the current leader. */\n forwardToLeader(tx: Transaction): void {\n if (this.leaderId && this.leaderId !== this.opts.nodeId) {\n const payload: TxForwardPayload = { transaction: tx };\n this.opts.peerManager.sendTo(\n this.leaderId,\n createMessage(MessageType.TxForward, this.opts.nodeId, payload),\n );\n }\n }\n\n // ── Election ────────────────────────────────────────────────────\n\n private startElection(): void {\n this.currentTerm++;\n this.role = RaftRole.Candidate;\n this.votedFor = this.opts.nodeId;\n this.leaderId = null;\n\n const peers = this.opts.peerManager.getKnownNodeIds();\n const totalVoters = peers.length + 1; // +1 for self\n let votesReceived = 1; // Vote for self\n\n this.opts.log.info({ term: this.currentTerm, voters: totalVoters }, \"Starting election\");\n\n // Single-node: win immediately\n if (totalVoters === 1) {\n this.becomeLeader();\n return;\n }\n\n // Store vote handler so we can track votes for this term\n const electionTerm = this.currentTerm;\n\n // Override the RequestVoteReply handler for this election\n this._voteCallback = (granted: boolean) => {\n if (this.currentTerm !== electionTerm || this.role !== RaftRole.Candidate) return;\n if (granted) votesReceived++;\n const majority = Math.floor(totalVoters / 2) + 1;\n if (votesReceived >= majority) {\n this.becomeLeader();\n }\n };\n\n // Send RequestVote to all peers\n const payload: RequestVotePayload = {\n term: this.currentTerm,\n candidateId: this.opts.nodeId,\n lastLogIndex: this.raftLog.getLastIndex(),\n lastLogTerm: this.raftLog.getLastTerm(),\n };\n\n for (const peerId of peers) {\n this.opts.peerManager.sendTo(\n peerId,\n createMessage(MessageType.ConsensusRequestVote, this.opts.nodeId, payload),\n );\n }\n\n // Reset election timer for next election if this one fails\n this.timer.resetElectionTimer();\n }\n\n private _voteCallback: ((granted: boolean) => void) | null = null;\n\n private becomeLeader(): void {\n this.role = RaftRole.Leader;\n this.leaderId = this.opts.nodeId;\n this.timer.stopElectionTimer();\n this.timer.startHeartbeatTimer();\n\n // Initialize leader state\n const nextIdx = this.raftLog.getLastIndex() + 1;\n const peers = this.opts.peerManager.getKnownNodeIds();\n for (const peerId of peers) {\n this.nextIndex.set(peerId, nextIdx);\n this.matchIndex.set(peerId, 0);\n }\n this.matchIndex.set(this.opts.nodeId, this.raftLog.getLastIndex());\n\n this.opts.log.info({ term: this.currentTerm }, \"Became leader\");\n this.emit(\"leader\");\n\n // Send initial heartbeat immediately\n this.sendHeartbeats();\n }\n\n private stepDown(newTerm: number): void {\n this.currentTerm = newTerm;\n this.role = RaftRole.Follower;\n this.votedFor = null;\n this.timer.stopHeartbeatTimer();\n if (this.blockProposalTimer) {\n clearInterval(this.blockProposalTimer);\n this.blockProposalTimer = null;\n }\n this.timer.resetElectionTimer();\n }\n\n // ── RequestVote ─────────────────────────────────────────────────\n\n private handleRequestVote(msg: MessageEnvelope): void {\n const payload = msg.payload as RequestVotePayload;\n let voteGranted = false;\n\n // If the request has a higher term, step down\n if (payload.term > this.currentTerm) {\n this.stepDown(payload.term);\n }\n\n // Grant vote if: same term, haven't voted or voted for this candidate,\n // and candidate's log is at least as up-to-date as ours\n if (\n payload.term === this.currentTerm &&\n (this.votedFor === null || this.votedFor === payload.candidateId) &&\n this.isLogUpToDate(payload.lastLogIndex, payload.lastLogTerm)\n ) {\n voteGranted = true;\n this.votedFor = payload.candidateId;\n this.timer.resetElectionTimer();\n }\n\n const reply: RequestVoteReplyPayload = {\n term: this.currentTerm,\n voteGranted,\n };\n\n this.opts.peerManager.sendTo(\n msg.from,\n createMessage(MessageType.ConsensusRequestVoteReply, this.opts.nodeId, reply),\n );\n }\n\n private handleRequestVoteReply(msg: MessageEnvelope): void {\n const payload = msg.payload as RequestVoteReplyPayload;\n\n if (payload.term > this.currentTerm) {\n this.stepDown(payload.term);\n return;\n }\n\n if (this._voteCallback) {\n this._voteCallback(payload.voteGranted);\n }\n }\n\n private isLogUpToDate(lastLogIndex: number, lastLogTerm: number): boolean {\n const myLastTerm = this.raftLog.getLastTerm();\n const myLastIndex = this.raftLog.getLastIndex();\n\n if (lastLogTerm !== myLastTerm) {\n return lastLogTerm > myLastTerm;\n }\n return lastLogIndex >= myLastIndex;\n }\n\n // ── AppendEntries ───────────────────────────────────────────────\n\n private sendHeartbeats(): void {\n if (this.role !== RaftRole.Leader) return;\n\n const peers = this.opts.peerManager.getKnownNodeIds();\n for (const peerId of peers) {\n this.sendAppendEntries(peerId);\n }\n }\n\n private sendAppendEntries(peerId: string): void {\n const nextIdx = this.nextIndex.get(peerId) ?? this.raftLog.getLastIndex() + 1;\n const prevLogIndex = nextIdx - 1;\n const prevLogTerm = this.raftLog.getTermAt(prevLogIndex);\n const entries = this.raftLog.getEntriesFrom(nextIdx);\n\n const payload: AppendEntriesPayload = {\n term: this.currentTerm,\n leaderId: this.opts.nodeId,\n prevLogIndex,\n prevLogTerm,\n entries,\n leaderCommit: this.commitIndex,\n };\n\n this.opts.peerManager.sendTo(\n peerId,\n createMessage(MessageType.ConsensusAppendEntries, this.opts.nodeId, payload),\n );\n }\n\n private handleAppendEntries(msg: MessageEnvelope): void {\n const payload = msg.payload as AppendEntriesPayload;\n\n // If the leader has a higher term, update\n if (payload.term > this.currentTerm) {\n this.stepDown(payload.term);\n }\n\n // Reject if term is outdated\n if (payload.term < this.currentTerm) {\n this.sendAppendEntriesReply(msg.from, false, 0);\n return;\n }\n\n // Valid leader heartbeat — reset election timer\n this.leaderId = payload.leaderId;\n if (this.role === RaftRole.Candidate) {\n this.role = RaftRole.Follower;\n }\n this.timer.resetElectionTimer();\n\n // Check log consistency\n if (payload.prevLogIndex > 0) {\n const prevTerm = this.raftLog.getTermAt(payload.prevLogIndex);\n if (prevTerm !== payload.prevLogTerm) {\n // Log inconsistency — tell leader to back up\n this.sendAppendEntriesReply(msg.from, false, 0);\n return;\n }\n }\n\n // Append new entries\n for (const entry of payload.entries) {\n const existing = this.raftLog.getEntry(entry.index);\n if (existing) {\n if (existing.term !== entry.term) {\n // Conflict: truncate from here\n this.raftLog.truncateFrom(entry.index);\n this.raftLog.append(entry);\n }\n // Else: already have this entry, skip\n } else {\n this.raftLog.append(entry);\n }\n }\n\n // Update commit index\n if (payload.leaderCommit > this.commitIndex) {\n this.commitIndex = Math.min(payload.leaderCommit, this.raftLog.getLastIndex());\n this.applyCommitted();\n }\n\n this.sendAppendEntriesReply(msg.from, true, this.raftLog.getLastIndex());\n }\n\n private sendAppendEntriesReply(to: string, success: boolean, matchIndex: number): void {\n const reply: AppendEntriesReplyPayload = {\n term: this.currentTerm,\n success,\n matchIndex,\n };\n this.opts.peerManager.sendTo(\n to,\n createMessage(MessageType.ConsensusAppendEntriesReply, this.opts.nodeId, reply),\n );\n }\n\n private handleAppendEntriesReply(msg: MessageEnvelope): void {\n if (this.role !== RaftRole.Leader) return;\n\n const payload = msg.payload as AppendEntriesReplyPayload;\n\n if (payload.term > this.currentTerm) {\n this.stepDown(payload.term);\n return;\n }\n\n if (payload.success) {\n this.nextIndex.set(msg.from, payload.matchIndex + 1);\n this.matchIndex.set(msg.from, payload.matchIndex);\n this.advanceCommitIndex();\n } else {\n // Decrement nextIndex and retry\n const current = this.nextIndex.get(msg.from) ?? 1;\n this.nextIndex.set(msg.from, Math.max(1, current - 1));\n // Retry immediately\n this.sendAppendEntries(msg.from);\n }\n }\n\n // ── Commit & Apply ──────────────────────────────────────────────\n\n private advanceCommitIndex(): void {\n if (this.role !== RaftRole.Leader) return;\n\n const allNodeIds = [...this.opts.peerManager.getKnownNodeIds(), this.opts.nodeId];\n const total = allNodeIds.length;\n const majority = Math.floor(total / 2) + 1;\n\n // Find the highest index replicated on a majority\n for (let n = this.raftLog.getLastIndex(); n > this.commitIndex; n--) {\n const entry = this.raftLog.getEntry(n);\n if (!entry || entry.term !== this.currentTerm) continue;\n\n let replicatedCount = 0;\n for (const nodeId of allNodeIds) {\n const match = nodeId === this.opts.nodeId\n ? this.raftLog.getLastIndex()\n : (this.matchIndex.get(nodeId) ?? 0);\n if (match >= n) replicatedCount++;\n }\n\n if (replicatedCount >= majority) {\n this.commitIndex = n;\n this.applyCommitted();\n break;\n }\n }\n }\n\n private applyCommitted(): void {\n while (this.lastApplied < this.commitIndex) {\n this.lastApplied++;\n const entry = this.raftLog.getEntry(this.lastApplied);\n if (entry && this.onBlockCommitted) {\n this.onBlockCommitted(entry.block);\n }\n }\n }\n}\n","/**\n * Raft timer with randomized election timeout and heartbeat.\n */\nexport class RaftTimer {\n private electionTimer: ReturnType<typeof setTimeout> | null = null;\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n\n private electionTimeoutMinMs: number;\n private electionTimeoutMaxMs: number;\n private heartbeatIntervalMs: number;\n\n private onElectionTimeout: () => void;\n private onHeartbeat: () => void;\n\n constructor(opts: {\n electionTimeoutMinMs?: number;\n electionTimeoutMaxMs?: number;\n heartbeatIntervalMs?: number;\n onElectionTimeout: () => void;\n onHeartbeat: () => void;\n }) {\n this.electionTimeoutMinMs = opts.electionTimeoutMinMs ?? 1500;\n this.electionTimeoutMaxMs = opts.electionTimeoutMaxMs ?? 3000;\n this.heartbeatIntervalMs = opts.heartbeatIntervalMs ?? 500;\n this.onElectionTimeout = opts.onElectionTimeout;\n this.onHeartbeat = opts.onHeartbeat;\n }\n\n /** Reset the election timeout (called on heartbeat received or vote granted). */\n resetElectionTimer(): void {\n this.stopElectionTimer();\n const timeout = this.randomElectionTimeout();\n this.electionTimer = setTimeout(() => {\n this.onElectionTimeout();\n }, timeout);\n }\n\n stopElectionTimer(): void {\n if (this.electionTimer) {\n clearTimeout(this.electionTimer);\n this.electionTimer = null;\n }\n }\n\n /** Start the heartbeat timer (called when becoming leader). */\n startHeartbeatTimer(): void {\n this.stopHeartbeatTimer();\n this.heartbeatTimer = setInterval(() => {\n this.onHeartbeat();\n }, this.heartbeatIntervalMs);\n }\n\n stopHeartbeatTimer(): void {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n }\n\n stopAll(): void {\n this.stopElectionTimer();\n this.stopHeartbeatTimer();\n }\n\n private randomElectionTimeout(): number {\n return (\n this.electionTimeoutMinMs +\n Math.random() * (this.electionTimeoutMaxMs - this.electionTimeoutMinMs)\n );\n }\n}\n","import type { RaftLogEntry } from \"../../network/protocol.js\";\n\n/**\n * In-memory Raft log. Entries are block proposals.\n * Each committed entry becomes a finalized block.\n */\nexport class RaftLog {\n private entries: RaftLogEntry[] = [];\n\n /** Append an entry to the log. */\n append(entry: RaftLogEntry): void {\n this.entries.push(entry);\n }\n\n /** Get entry at a specific index (1-based). */\n getEntry(index: number): RaftLogEntry | undefined {\n return this.entries.find((e) => e.index === index);\n }\n\n /** Get the last log index. */\n getLastIndex(): number {\n return this.entries.length > 0 ? this.entries[this.entries.length - 1]!.index : 0;\n }\n\n /** Get the last log term. */\n getLastTerm(): number {\n return this.entries.length > 0 ? this.entries[this.entries.length - 1]!.term : 0;\n }\n\n /** Get entries from startIndex (inclusive). */\n getEntriesFrom(startIndex: number): RaftLogEntry[] {\n return this.entries.filter((e) => e.index >= startIndex);\n }\n\n /** Get the term at a given index. Returns 0 if index not found. */\n getTermAt(index: number): number {\n if (index === 0) return 0;\n const entry = this.entries.find((e) => e.index === index);\n return entry?.term ?? 0;\n }\n\n /** Truncate log from index (inclusive) onwards. Used when log conflicts detected. */\n truncateFrom(index: number): void {\n this.entries = this.entries.filter((e) => e.index < index);\n }\n\n /** Get number of entries. */\n length(): number {\n return this.entries.length;\n }\n}\n","import type { StateStore } from \"../storage/state-store.js\";\nimport type { ContractContext } from \"./types.js\";\n\nexport interface ContextOptions {\n stateStore: StateStore;\n sender: string;\n blockHeight: number;\n timestamp: number;\n}\n\n/**\n * Creates a ContractContext that contracts use to interact with the ledger.\n * All state mutations go through the StateStore.\n */\nexport function createContractContext(opts: ContextOptions): ContractContext & { getLogs(): string[] } {\n const logs: string[] = [];\n\n return {\n get(key: string): unknown | null {\n const entry = opts.stateStore.get(key);\n return entry ? entry.value : null;\n },\n\n set(key: string, value: unknown): void {\n opts.stateStore.set(key, value, opts.sender, opts.blockHeight);\n },\n\n del(key: string): void {\n opts.stateStore.delete(key);\n },\n\n get sender() {\n return opts.sender;\n },\n\n get blockHeight() {\n return opts.blockHeight;\n },\n\n get timestamp() {\n return opts.timestamp;\n },\n\n log(message: string): void {\n logs.push(message);\n },\n\n getLogs(): string[] {\n return logs;\n },\n };\n}\n","import type { ContractContext, ContractModule } from \"./types.js\";\n\nconst MAX_EXECUTION_MS = 5000;\n\n/**\n * Compile contract source code into a callable module.\n *\n * Contracts are JavaScript/TypeScript functions. The source code should export\n * methods as properties of a returned object. Example:\n *\n * ```\n * return {\n * init(ctx) { ctx.set(\"counter\", 0); },\n * increment(ctx, amount) {\n * const val = ctx.get(\"counter\") || 0;\n * ctx.set(\"counter\", val + amount);\n * return val + amount;\n * }\n * }\n * ```\n */\nexport function compileContract(source: string): ContractModule {\n // Create a sandboxed function with limited globals\n const wrapper = new Function(\n // No arguments — the contract returns its methods\n `\"use strict\";\n // Freeze dangerous globals\n const process = undefined;\n const require = undefined;\n const __dirname = undefined;\n const __filename = undefined;\n const global = undefined;\n const globalThis = undefined;\n const fetch = undefined;\n const setTimeout = undefined;\n const setInterval = undefined;\n const import_meta = undefined;\n\n ${source}`,\n );\n\n const mod = wrapper();\n\n if (!mod || typeof mod !== \"object\") {\n throw new Error(\"Contract must return an object with methods\");\n }\n\n // Validate all exports are functions\n for (const [key, val] of Object.entries(mod)) {\n if (typeof val !== \"function\") {\n throw new Error(`Contract export \"${key}\" must be a function, got ${typeof val}`);\n }\n }\n\n return mod as ContractModule;\n}\n\n/**\n * Execute a contract method with a context and arguments.\n * Enforces a timeout to prevent infinite loops.\n */\nexport function executeContract(\n mod: ContractModule,\n method: string,\n ctx: ContractContext,\n args: unknown[] = [],\n): unknown {\n const fn = mod[method];\n if (!fn) {\n throw new Error(`Contract method \"${method}\" not found`);\n }\n\n // Simple timeout enforcement via synchronous deadline check\n // (True async timeout requires worker_threads; this is adequate for M3)\n const deadline = Date.now() + MAX_EXECUTION_MS;\n\n // Create a proxy on ctx that checks deadline on each state access\n const guardedCtx: ContractContext = {\n get(key: string) {\n if (Date.now() > deadline) throw new Error(\"Contract execution timeout\");\n return ctx.get(key);\n },\n set(key: string, value: unknown) {\n if (Date.now() > deadline) throw new Error(\"Contract execution timeout\");\n ctx.set(key, value);\n },\n del(key: string) {\n if (Date.now() > deadline) throw new Error(\"Contract execution timeout\");\n ctx.del(key);\n },\n get sender() { return ctx.sender; },\n get blockHeight() { return ctx.blockHeight; },\n get timestamp() { return ctx.timestamp; },\n log(message: string) { ctx.log(message); },\n };\n\n return fn(guardedCtx, ...args);\n}\n","import type { StateStore } from \"../storage/state-store.js\";\nimport type { ContractInstance, ContractModule } from \"./types.js\";\nimport { compileContract, executeContract } from \"./runtime.js\";\n\nconst CONTRACT_PREFIX = \"_contract:\";\nconst CONTRACT_CODE_PREFIX = \"_contract_code:\";\n\n/**\n * Manages deployed contracts. Contract metadata and code are stored in world state\n * with reserved key prefixes.\n */\nexport class ContractRegistry {\n private compiled = new Map<string, ContractModule>();\n private stateStore: StateStore;\n\n constructor(stateStore: StateStore) {\n this.stateStore = stateStore;\n }\n\n /** Deploy a new contract or upgrade an existing one. */\n deploy(\n name: string,\n version: string,\n code: string,\n deployedBy: string,\n blockHeight: number,\n ): void {\n // Validate by compiling\n const mod = compileContract(code);\n this.compiled.set(name, mod);\n\n // Store metadata\n const instance: ContractInstance = {\n name,\n version,\n deployedAt: Date.now(),\n deployedBy,\n };\n this.stateStore.set(`${CONTRACT_PREFIX}${name}`, instance, deployedBy, blockHeight);\n this.stateStore.set(`${CONTRACT_CODE_PREFIX}${name}`, code, deployedBy, blockHeight);\n }\n\n /** Get a compiled contract module, loading from state if needed. */\n getModule(name: string): ContractModule | null {\n // Check cache\n let mod = this.compiled.get(name);\n if (mod) return mod;\n\n // Load from state\n const codeEntry = this.stateStore.get(`${CONTRACT_CODE_PREFIX}${name}`);\n if (!codeEntry) return null;\n\n mod = compileContract(codeEntry.value as string);\n this.compiled.set(name, mod);\n return mod;\n }\n\n /** Get contract metadata. */\n getInstance(name: string): ContractInstance | null {\n const entry = this.stateStore.get(`${CONTRACT_PREFIX}${name}`);\n return entry ? (entry.value as ContractInstance) : null;\n }\n\n /** Invoke a method on a deployed contract. */\n invoke(\n contractName: string,\n method: string,\n ctx: import(\"./types.js\").ContractContext,\n args: unknown[] = [],\n ): unknown {\n const mod = this.getModule(contractName);\n if (!mod) {\n throw new Error(`Contract \"${contractName}\" not found`);\n }\n return executeContract(mod, method, ctx, args);\n }\n\n /** List all deployed contracts. */\n listContracts(): ContractInstance[] {\n const results = this.stateStore.query(\n `SELECT value FROM world_state WHERE key LIKE ?`,\n [`${CONTRACT_PREFIX}%`],\n );\n return results\n .map((r) => {\n try {\n return JSON.parse(r.value as string) as ContractInstance;\n } catch {\n return null;\n }\n })\n .filter((c): c is ContractInstance => c !== null);\n }\n\n /** Clear compiled cache (useful after chain reorg). */\n clearCache(): void {\n this.compiled.clear();\n }\n}\n","/**\n * Built-in contract: token transfer.\n *\n * State keys: \"balance:<address>\" -> number\n */\nexport const TRANSFER_CONTRACT = `\nreturn {\n init(ctx, initialBalance) {\n ctx.set(\"balance:\" + ctx.sender, initialBalance || 0);\n ctx.log(\"Account initialized with balance: \" + (initialBalance || 0));\n },\n\n mint(ctx, amount) {\n if (typeof amount !== \"number\" || amount <= 0) throw new Error(\"Invalid amount\");\n const key = \"balance:\" + ctx.sender;\n const current = ctx.get(key) || 0;\n ctx.set(key, current + amount);\n ctx.log(\"Minted \" + amount + \" to \" + ctx.sender);\n return current + amount;\n },\n\n transfer(ctx, to, amount) {\n if (typeof amount !== \"number\" || amount <= 0) throw new Error(\"Invalid amount\");\n if (!to) throw new Error(\"Recipient required\");\n\n const fromKey = \"balance:\" + ctx.sender;\n const toKey = \"balance:\" + to;\n\n const fromBalance = ctx.get(fromKey) || 0;\n if (fromBalance < amount) throw new Error(\"Insufficient balance\");\n\n const toBalance = ctx.get(toKey) || 0;\n ctx.set(fromKey, fromBalance - amount);\n ctx.set(toKey, toBalance + amount);\n ctx.log(\"Transfer \" + amount + \" from \" + ctx.sender + \" to \" + to);\n },\n\n balance(ctx, address) {\n const key = \"balance:\" + (address || ctx.sender);\n return ctx.get(key) || 0;\n }\n}\n`;\n\n/**\n * Built-in contract: simple key-value store with ownership.\n */\nexport const KV_STORE_CONTRACT = `\nreturn {\n set(ctx, key, value) {\n const fullKey = \"kv:\" + key;\n const existing = ctx.get(fullKey + \":owner\");\n if (existing && existing !== ctx.sender) throw new Error(\"Not owner of key: \" + key);\n ctx.set(fullKey, value);\n ctx.set(fullKey + \":owner\", ctx.sender);\n },\n\n get(ctx, key) {\n return ctx.get(\"kv:\" + key);\n },\n\n del(ctx, key) {\n const owner = ctx.get(\"kv:\" + key + \":owner\");\n if (owner && owner !== ctx.sender) throw new Error(\"Not owner of key: \" + key);\n ctx.del(\"kv:\" + key);\n ctx.del(\"kv:\" + key + \":owner\");\n }\n}\n`;\n","export enum ProposalType {\n AddPeer = \"add-peer\",\n RemovePeer = \"remove-peer\",\n UpdateConfig = \"update-config\",\n UpgradeContract = \"upgrade-contract\",\n Custom = \"custom\",\n}\n\nexport enum ProposalStatus {\n Active = \"active\",\n Approved = \"approved\",\n Rejected = \"rejected\",\n Expired = \"expired\",\n}\n\nexport interface Proposal {\n id: string;\n type: ProposalType;\n title: string;\n description: string;\n proposer: string; // public key\n action: Record<string, unknown>; // type-specific action data\n status: ProposalStatus;\n createdAt: number;\n expiresAt: number;\n votes: Record<string, boolean>; // publicKey -> approve/reject\n}\n\nexport function createProposal(opts: {\n type: ProposalType;\n title: string;\n description: string;\n proposer: string;\n action: Record<string, unknown>;\n votingPeriodMs?: number;\n}): Proposal {\n const now = Date.now();\n const votingPeriod = opts.votingPeriodMs ?? 24 * 60 * 60 * 1000; // 24 hours default\n\n return {\n id: `proposal:${now}:${Math.random().toString(36).slice(2, 8)}`,\n type: opts.type,\n title: opts.title,\n description: opts.description,\n proposer: opts.proposer,\n action: opts.action,\n status: ProposalStatus.Active,\n createdAt: now,\n expiresAt: now + votingPeriod,\n votes: { [opts.proposer]: true }, // Proposer auto-votes yes\n };\n}\n","import type { Proposal } from \"./proposal.js\";\nimport { ProposalStatus } from \"./proposal.js\";\n\nexport interface VoteResult {\n approved: number;\n rejected: number;\n total: number;\n quorumReached: boolean;\n passed: boolean;\n}\n\n/**\n * Tally votes on a proposal.\n * @param proposal - The proposal to tally\n * @param totalVoters - Total number of eligible voters in the network\n * @param quorumPercent - Minimum percentage of voters required (default 50%)\n */\nexport function tallyVotes(\n proposal: Proposal,\n totalVoters: number,\n quorumPercent = 50,\n): VoteResult {\n const votes = Object.values(proposal.votes);\n const approved = votes.filter((v) => v === true).length;\n const rejected = votes.filter((v) => v === false).length;\n const total = votes.length;\n\n const quorumNeeded = Math.ceil((totalVoters * quorumPercent) / 100);\n const quorumReached = total >= quorumNeeded;\n const passed = quorumReached && approved > rejected;\n\n return { approved, rejected, total, quorumReached, passed };\n}\n\n/** Add a vote to a proposal. Returns updated proposal. */\nexport function addVote(\n proposal: Proposal,\n voter: string,\n vote: boolean,\n): Proposal {\n if (proposal.status !== ProposalStatus.Active) {\n throw new Error(`Proposal ${proposal.id} is not active (status: ${proposal.status})`);\n }\n if (Date.now() > proposal.expiresAt) {\n throw new Error(`Proposal ${proposal.id} has expired`);\n }\n\n return {\n ...proposal,\n votes: { ...proposal.votes, [voter]: vote },\n };\n}\n\n/** Check if a proposal has expired. */\nexport function isExpired(proposal: Proposal): boolean {\n return Date.now() > proposal.expiresAt;\n}\n","import type { StateStore } from \"../storage/state-store.js\";\nimport {\n type Proposal,\n ProposalStatus,\n ProposalType,\n createProposal,\n} from \"./proposal.js\";\nimport { tallyVotes, addVote, isExpired } from \"./voting.js\";\n\nconst PROPOSAL_PREFIX = \"_gov:proposal:\";\n\n/**\n * Governor: manages the lifecycle of governance proposals.\n * Proposals are stored in world state with a reserved key prefix.\n */\nexport class Governor {\n private stateStore: StateStore;\n\n constructor(stateStore: StateStore) {\n this.stateStore = stateStore;\n }\n\n /** Create and store a new proposal. */\n propose(opts: {\n type: ProposalType;\n title: string;\n description: string;\n proposer: string;\n action: Record<string, unknown>;\n blockHeight: number;\n votingPeriodMs?: number;\n }): Proposal {\n const proposal = createProposal({\n type: opts.type,\n title: opts.title,\n description: opts.description,\n proposer: opts.proposer,\n action: opts.action,\n votingPeriodMs: opts.votingPeriodMs,\n });\n\n this.stateStore.set(\n `${PROPOSAL_PREFIX}${proposal.id}`,\n proposal,\n opts.proposer,\n opts.blockHeight,\n );\n\n return proposal;\n }\n\n /** Cast a vote on a proposal. */\n vote(proposalId: string, voter: string, approve: boolean, blockHeight: number): Proposal {\n const proposal = this.getProposal(proposalId);\n if (!proposal) throw new Error(`Proposal not found: ${proposalId}`);\n\n const updated = addVote(proposal, voter, approve);\n this.stateStore.set(\n `${PROPOSAL_PREFIX}${proposalId}`,\n updated,\n voter,\n blockHeight,\n );\n\n return updated;\n }\n\n /**\n * Evaluate a proposal: check if it should be approved, rejected, or expired.\n * Returns the action to execute if approved, null otherwise.\n */\n evaluate(proposalId: string, totalVoters: number, blockHeight: number): {\n status: ProposalStatus;\n action: Record<string, unknown> | null;\n } {\n const proposal = this.getProposal(proposalId);\n if (!proposal) throw new Error(`Proposal not found: ${proposalId}`);\n\n if (proposal.status !== ProposalStatus.Active) {\n return { status: proposal.status, action: null };\n }\n\n // Check expiration\n if (isExpired(proposal)) {\n const expired = { ...proposal, status: ProposalStatus.Expired };\n this.stateStore.set(\n `${PROPOSAL_PREFIX}${proposalId}`,\n expired,\n proposal.proposer,\n blockHeight,\n );\n return { status: ProposalStatus.Expired, action: null };\n }\n\n // Tally votes\n const result = tallyVotes(proposal, totalVoters);\n\n if (result.quorumReached) {\n const newStatus = result.passed ? ProposalStatus.Approved : ProposalStatus.Rejected;\n const updated = { ...proposal, status: newStatus };\n this.stateStore.set(\n `${PROPOSAL_PREFIX}${proposalId}`,\n updated,\n proposal.proposer,\n blockHeight,\n );\n\n return {\n status: newStatus,\n action: result.passed ? proposal.action : null,\n };\n }\n\n return { status: ProposalStatus.Active, action: null };\n }\n\n /** Get a proposal by ID. */\n getProposal(proposalId: string): Proposal | null {\n const entry = this.stateStore.get(`${PROPOSAL_PREFIX}${proposalId}`);\n return entry ? (entry.value as Proposal) : null;\n }\n\n /** List all proposals. */\n listProposals(): Proposal[] {\n const results = this.stateStore.query(\n `SELECT value FROM world_state WHERE key LIKE ?`,\n [`${PROPOSAL_PREFIX}%`],\n );\n return results\n .map((r) => {\n try {\n return JSON.parse(r.value as string) as Proposal;\n } catch {\n return null;\n }\n })\n .filter((p): p is Proposal => p !== null);\n }\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { Hono } from \"hono\";\nimport { cors } from \"hono/cors\";\nimport type { MiniLedgerNode } from \"../node.js\";\nimport { requestLogger } from \"./middleware/logging.js\";\nimport { healthRoutes } from \"./routes/health.js\";\nimport { blockRoutes } from \"./routes/blocks.js\";\nimport { transactionRoutes } from \"./routes/transactions.js\";\nimport { stateRoutes } from \"./routes/state.js\";\nimport { identityRoutes } from \"./routes/identity.js\";\nimport { networkRoutes } from \"./routes/network.js\";\nimport { governanceRoutes } from \"./routes/governance.js\";\n\n/** Find the dashboard directory — works from both src/ and dist/. */\nfunction findDashboardDir(): string | null {\n // Try relative to this file (in dist/)\n const candidates = [\n path.resolve(import.meta.dirname ?? \".\", \"..\", \"dashboard\"),\n path.resolve(import.meta.dirname ?? \".\", \"..\", \"..\", \"dashboard\"),\n path.resolve(process.cwd(), \"dashboard\"),\n ];\n for (const dir of candidates) {\n if (fs.existsSync(path.join(dir, \"index.html\"))) return dir;\n }\n return null;\n}\n\nconst MIME_TYPES: Record<string, string> = {\n \".html\": \"text/html\",\n \".css\": \"text/css\",\n \".js\": \"application/javascript\",\n \".json\": \"application/json\",\n \".png\": \"image/png\",\n \".svg\": \"image/svg+xml\",\n};\n\nexport function createApp(node: MiniLedgerNode): Hono {\n const app = new Hono();\n\n // Global middleware\n if (node.config.api.cors) {\n app.use(\"*\", cors());\n }\n app.use(\"*\", requestLogger());\n\n // Mount API routes\n app.route(\"/\", healthRoutes(node));\n app.route(\"/\", blockRoutes(node));\n app.route(\"/\", transactionRoutes(node));\n app.route(\"/\", stateRoutes(node));\n app.route(\"/\", identityRoutes(node));\n app.route(\"/\", networkRoutes(node));\n app.route(\"/\", governanceRoutes(node));\n\n // Serve dashboard static files\n const dashboardDir = findDashboardDir();\n if (dashboardDir) {\n app.get(\"/dashboard\", (c) => {\n const html = fs.readFileSync(path.join(dashboardDir, \"index.html\"), \"utf-8\");\n return c.html(html);\n });\n\n app.get(\"/dashboard/:file\", (c) => {\n const file = c.req.param(\"file\");\n const filePath = path.join(dashboardDir, file);\n if (!fs.existsSync(filePath)) return c.notFound();\n const ext = path.extname(file);\n const mime = MIME_TYPES[ext] ?? \"application/octet-stream\";\n const content = fs.readFileSync(filePath, \"utf-8\");\n return c.text(content, 200, { \"Content-Type\": mime });\n });\n }\n\n // Root — redirect to dashboard\n app.get(\"/\", (c) => {\n if (dashboardDir) {\n return c.redirect(\"/dashboard\");\n }\n return c.json({\n name: \"miniledger\",\n version: \"0.1.0\",\n status: node.isRunning() ? \"running\" : \"stopped\",\n });\n });\n\n return app;\n}\n","import type { MiddlewareHandler } from \"hono\";\n\nexport function requestLogger(): MiddlewareHandler {\n return async (c, next) => {\n const start = Date.now();\n await next();\n const ms = Date.now() - start;\n // Only log non-health endpoints to reduce noise\n if (!c.req.path.includes(\"/health\")) {\n console.log(`${c.req.method} ${c.req.path} ${c.res.status} ${ms}ms`);\n }\n };\n}\n","import { Hono } from \"hono\";\nimport type { MiniLedgerNode } from \"../../node.js\";\n\nexport function healthRoutes(node: MiniLedgerNode): Hono {\n const app = new Hono();\n\n app.get(\"/health\", (c) => {\n return c.json({\n status: node.isRunning() ? \"ok\" : \"stopped\",\n timestamp: Date.now(),\n });\n });\n\n app.get(\"/status\", (c) => {\n return c.json(node.getStatus());\n });\n\n return app;\n}\n","import { Hono } from \"hono\";\nimport type { MiniLedgerNode } from \"../../node.js\";\n\nexport function blockRoutes(node: MiniLedgerNode): Hono {\n const app = new Hono();\n\n app.get(\"/blocks/latest\", async (c) => {\n const block = await node.getLatestBlock();\n if (!block) return c.json({ error: \"No blocks\" }, 404);\n return c.json(block);\n });\n\n app.get(\"/blocks/:height\", async (c) => {\n const height = Number.parseInt(c.req.param(\"height\"), 10);\n if (Number.isNaN(height)) return c.json({ error: \"Invalid height\" }, 400);\n const block = await node.getBlock(height);\n if (!block) return c.json({ error: \"Block not found\" }, 404);\n return c.json(block);\n });\n\n app.get(\"/blocks\", async (c) => {\n const stores = node.getStores();\n const currentHeight = stores.blocks.getHeight();\n const from = Math.max(0, currentHeight - 19); // Last 20 blocks\n const blocks = stores.blocks.getRange(from, currentHeight);\n return c.json({ blocks, height: currentHeight });\n });\n\n return app;\n}\n","import { Hono } from \"hono\";\nimport { z } from \"zod\";\nimport type { MiniLedgerNode } from \"../../node.js\";\nimport { TxType } from \"../../types.js\";\n\nconst submitTxSchema = z.object({\n key: z.string().optional(),\n value: z.unknown().optional(),\n type: z.nativeEnum(TxType).optional(),\n payload: z\n .object({\n kind: z.string(),\n })\n .passthrough()\n .optional(),\n});\n\nexport function transactionRoutes(node: MiniLedgerNode): Hono {\n const app = new Hono();\n\n app.post(\"/tx\", async (c) => {\n try {\n const body = await c.req.json();\n const parsed = submitTxSchema.parse(body);\n const tx = await node.submit({\n type: parsed.type,\n key: parsed.key,\n value: parsed.value,\n payload: parsed.payload as any,\n });\n return c.json({ hash: tx.hash, status: \"pending\" }, 201);\n } catch (err) {\n const message = err instanceof Error ? err.message : \"Unknown error\";\n return c.json({ error: message }, 400);\n }\n });\n\n app.get(\"/tx/:hash\", async (c) => {\n const hash = c.req.param(\"hash\");\n const tx = await node.getTransaction(hash);\n if (!tx) return c.json({ error: \"Transaction not found\" }, 404);\n return c.json(tx);\n });\n\n app.get(\"/tx\", (c) => {\n const stores = node.getStores();\n const pending = stores.txs.getPending(100);\n return c.json({ pending, count: pending.length });\n });\n\n return app;\n}\n","import { Hono } from \"hono\";\nimport type { MiniLedgerNode } from \"../../node.js\";\n\nexport function stateRoutes(node: MiniLedgerNode): Hono {\n const app = new Hono();\n\n app.get(\"/state/:key\", async (c) => {\n const key = c.req.param(\"key\");\n const entry = await node.getState(key);\n if (!entry) return c.json({ error: \"Key not found\" }, 404);\n return c.json(entry);\n });\n\n /** Execute a SQL query against the world state. The killer feature. */\n app.post(\"/state/query\", async (c) => {\n try {\n const body = await c.req.json();\n const { sql, params = [] } = body as { sql: string; params?: unknown[] };\n if (!sql) return c.json({ error: \"Missing sql field\" }, 400);\n const results = await node.query(sql, params);\n return c.json({ results, count: results.length });\n } catch (err) {\n const message = err instanceof Error ? err.message : \"Query failed\";\n return c.json({ error: message }, 400);\n }\n });\n\n return app;\n}\n","import { Hono } from \"hono\";\nimport type { MiniLedgerNode } from \"../../node.js\";\n\nexport function identityRoutes(node: MiniLedgerNode): Hono {\n const app = new Hono();\n\n app.get(\"/identity\", (c) => {\n const status = node.getStatus();\n return c.json({\n nodeId: status.nodeId,\n publicKey: status.publicKey,\n });\n });\n\n return app;\n}\n","import { Hono } from \"hono\";\nimport type { MiniLedgerNode } from \"../../node.js\";\n\nexport function networkRoutes(node: MiniLedgerNode): Hono {\n const app = new Hono();\n\n app.get(\"/peers\", (c) => {\n const pm = node.getPeerManager();\n if (!pm) {\n return c.json({ peers: [], count: 0 });\n }\n const peers = pm.getPeerStates().map((p) => ({\n nodeId: p.nodeId,\n publicKey: p.publicKey,\n address: p.address,\n orgId: p.orgId,\n status: p.status,\n chainHeight: p.chainHeight,\n lastSeen: p.lastSeen,\n }));\n return c.json({ peers, count: peers.length });\n });\n\n app.get(\"/consensus\", (c) => {\n const raft = node.getRaft();\n if (!raft) {\n return c.json({ algorithm: node.config.consensus.algorithm, state: null });\n }\n return c.json({\n algorithm: \"raft\",\n state: raft.getState(),\n });\n });\n\n return app;\n}\n","import { Hono } from \"hono\";\nimport type { MiniLedgerNode } from \"../../node.js\";\n\nexport function governanceRoutes(node: MiniLedgerNode): Hono {\n const app = new Hono();\n\n app.get(\"/proposals\", (c) => {\n const proposals = node.getGovernor().listProposals();\n return c.json({ proposals, count: proposals.length });\n });\n\n app.get(\"/proposals/:id\", (c) => {\n const id = c.req.param(\"id\");\n const proposal = node.getGovernor().getProposal(id);\n if (!proposal) return c.json({ error: \"Proposal not found\" }, 404);\n return c.json(proposal);\n });\n\n app.get(\"/contracts\", (c) => {\n const contracts = node.getContractRegistry().listContracts();\n return c.json({ contracts, count: contracts.length });\n });\n\n return app;\n}\n","import { serve } from \"@hono/node-server\";\nimport type { Command } from \"commander\";\nimport { DEFAULT_CONFIG } from \"../../config/index.js\";\nimport { MiniLedgerNode } from \"../../node.js\";\nimport { createApp } from \"../../api/server.js\";\n\nexport function registerJoin(program: Command): void {\n program\n .command(\"join <peer-address>\")\n .description(\"Join an existing network (e.g. miniledger join ws://host:4440)\")\n .option(\"-d, --data-dir <path>\", \"Data directory\", DEFAULT_CONFIG.dataDir)\n .option(\"-p, --api-port <port>\", \"API port\", String(DEFAULT_CONFIG.network.apiPort))\n .option(\"--p2p-port <port>\", \"P2P port\", String(DEFAULT_CONFIG.network.p2pPort))\n .action(async (peerAddress: string, opts) => {\n const node = await MiniLedgerNode.create({\n dataDir: opts.dataDir,\n config: {\n network: {\n ...DEFAULT_CONFIG.network,\n apiPort: Number.parseInt(opts.apiPort, 10),\n p2pPort: Number.parseInt(opts.p2pPort, 10),\n peers: [peerAddress],\n },\n consensus: {\n ...DEFAULT_CONFIG.consensus,\n algorithm: \"raft\",\n },\n },\n });\n\n await node.init();\n await node.start();\n\n if (node.config.api.enabled) {\n const app = createApp(node);\n serve({\n fetch: app.fetch,\n port: node.config.network.apiPort,\n });\n console.log(`REST API listening on http://localhost:${node.config.network.apiPort}`);\n }\n\n const status = node.getStatus();\n console.log(`\\nMiniLedger node joining network via ${peerAddress}`);\n console.log(` Node ID: ${status.nodeId}`);\n console.log(` P2P Port: ${node.config.network.p2pPort}`);\n console.log(` Height: ${status.chainHeight}`);\n console.log(`\\nPress Ctrl+C to stop\\n`);\n\n const shutdown = async () => {\n console.log(\"\\nShutting down...\");\n await node.stop();\n process.exit(0);\n };\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n });\n}\n","import type { Command } from \"commander\";\nimport type { NodeStatus } from \"../../types.js\";\nimport { DEFAULT_CONFIG } from \"../../config/index.js\";\n\nexport function registerStatus(program: Command): void {\n program\n .command(\"status\")\n .description(\"Show node status\")\n .option(\"-p, --api-port <port>\", \"API port\", String(DEFAULT_CONFIG.network.apiPort))\n .action(async (opts) => {\n const port = opts.apiPort;\n try {\n const res = await fetch(`http://localhost:${port}/status`);\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const status = (await res.json()) as NodeStatus;\n console.log(\"Node Status:\");\n console.log(` Node ID: ${status.nodeId}`);\n console.log(` Public Key: ${status.publicKey}`);\n console.log(` Height: ${status.chainHeight}`);\n console.log(` Latest Hash: ${status.latestBlockHash?.substring(0, 16)}...`);\n console.log(` Peers: ${status.peerCount}`);\n console.log(` TX Pool: ${status.txPoolSize}`);\n console.log(` Uptime: ${Math.round(status.uptime / 1000)}s`);\n } catch {\n console.error(`Cannot connect to node at localhost:${port}. Is it running?`);\n process.exit(1);\n }\n });\n}\n","import type { Command } from \"commander\";\nimport { DEFAULT_CONFIG } from \"../../config/index.js\";\n\ninterface TxResult {\n hash?: string;\n status?: string;\n error?: string;\n}\n\nexport function registerTx(program: Command): void {\n const tx = program.command(\"tx\").description(\"Transaction commands\");\n\n tx.command(\"submit <data>\")\n .description(\"Submit a transaction (JSON: {key, value})\")\n .option(\"-p, --api-port <port>\", \"API port\", String(DEFAULT_CONFIG.network.apiPort))\n .action(async (data: string, opts) => {\n try {\n const body = JSON.parse(data);\n const res = await fetch(`http://localhost:${opts.apiPort}/tx`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n const result = (await res.json()) as TxResult;\n if (!res.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n console.log(`Transaction submitted: ${result.hash}`);\n } catch (err) {\n console.error(`Failed: ${err instanceof Error ? err.message : err}`);\n process.exit(1);\n }\n });\n\n tx.command(\"get <hash>\")\n .description(\"Get a transaction by hash\")\n .option(\"-p, --api-port <port>\", \"API port\", String(DEFAULT_CONFIG.network.apiPort))\n .action(async (hash: string, opts) => {\n try {\n const res = await fetch(`http://localhost:${opts.apiPort}/tx/${hash}`);\n const result = (await res.json()) as Record<string, unknown>;\n if (!res.ok) {\n console.error(`Error: ${(result as TxResult).error}`);\n process.exit(1);\n }\n console.log(JSON.stringify(result, null, 2));\n } catch {\n console.error(\"Cannot connect to node. Is it running?\");\n process.exit(1);\n }\n });\n}\n","import type { Command } from \"commander\";\nimport { DEFAULT_CONFIG } from \"../../config/index.js\";\n\ninterface QueryResult {\n results: Record<string, unknown>[];\n count: number;\n error?: string;\n}\n\nexport function registerQuery(program: Command): void {\n program\n .command(\"query <sql>\")\n .description(\"Query world state with SQL\")\n .option(\"-p, --api-port <port>\", \"API port\", String(DEFAULT_CONFIG.network.apiPort))\n .action(async (sql: string, opts) => {\n try {\n const res = await fetch(`http://localhost:${opts.apiPort}/state/query`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ sql }),\n });\n const result = (await res.json()) as QueryResult;\n if (!res.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n if (result.count === 0) {\n console.log(\"No results\");\n return;\n }\n console.table(result.results);\n } catch {\n console.error(\"Cannot connect to node. Is it running?\");\n process.exit(1);\n }\n });\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { Command } from \"commander\";\nimport { generateKeyPair, deserializeKeystore, decryptKeystore } from \"../../identity/index.js\";\nimport { DEFAULT_CONFIG } from \"../../config/index.js\";\n\nexport function registerKeys(program: Command): void {\n const keys = program.command(\"keys\").description(\"Key management\");\n\n keys\n .command(\"generate\")\n .description(\"Generate a new keypair\")\n .action(() => {\n const kp = generateKeyPair();\n console.log(`Public Key: ${kp.publicKey}`);\n console.log(`Private Key: ${kp.privateKey}`);\n });\n\n keys\n .command(\"show\")\n .description(\"Show the node's public key\")\n .option(\"-d, --data-dir <path>\", \"Data directory\", DEFAULT_CONFIG.dataDir)\n .action((opts) => {\n const keystorePath = path.join(opts.dataDir, \"keystore.json\");\n if (!fs.existsSync(keystorePath)) {\n console.error(\"No keystore found. Run 'miniledger init' first.\");\n process.exit(1);\n }\n const ks = deserializeKeystore(fs.readFileSync(keystorePath, \"utf-8\"));\n const kp = decryptKeystore(ks, \"\");\n console.log(`Public Key: ${kp.publicKey}`);\n console.log(`Node ID: ${kp.publicKey.substring(0, 16)}`);\n });\n}\n","import type { Command } from \"commander\";\nimport { DEFAULT_CONFIG } from \"../../config/index.js\";\n\ninterface PeersResult {\n peers: { nodeId: string; address: string; orgId: string; status: string; chainHeight: number }[];\n count: number;\n}\n\nexport function registerPeers(program: Command): void {\n const peers = program.command(\"peers\").description(\"Peer management\");\n\n peers\n .command(\"list\")\n .description(\"List connected peers\")\n .option(\"-p, --api-port <port>\", \"API port\", String(DEFAULT_CONFIG.network.apiPort))\n .action(async (opts) => {\n try {\n const res = await fetch(`http://localhost:${opts.apiPort}/peers`);\n const data = (await res.json()) as PeersResult;\n if (data.count === 0) {\n console.log(\"No connected peers\");\n return;\n }\n console.table(data.peers);\n } catch {\n console.error(\"Cannot connect to node. Is it running?\");\n process.exit(1);\n }\n });\n}\n","import { serve } from \"@hono/node-server\";\nimport { exec } from \"node:child_process\";\nimport type { Command } from \"commander\";\nimport { MiniLedgerNode } from \"../../node.js\";\nimport { TxType } from \"../../types.js\";\nimport { createApp } from \"../../api/server.js\";\nimport { TRANSFER_CONTRACT } from \"../../contracts/builtins.js\";\nimport { createTempDir } from \"./demo-utils.js\";\n\nexport function registerDemo(program: Command): void {\n program\n .command(\"demo\")\n .description(\"Run a 3-node demo cluster with sample data\")\n .option(\"-p, --port <port>\", \"API port for the primary node\", \"4441\")\n .action(async (opts) => {\n const apiPort = Number.parseInt(opts.port, 10);\n console.log(\"\\n MiniLedger Demo\");\n console.log(\" ===============\\n\");\n console.log(\" Starting a 3-node cluster with Raft consensus...\\n\");\n\n const dirs: string[] = [];\n const nodes: MiniLedgerNode[] = [];\n\n try {\n // Create 3 nodes\n for (let i = 0; i < 3; i++) {\n const dir = createTempDir(`miniledger-demo-node${i + 1}-`);\n dirs.push(dir);\n\n const peers = i > 0 ? [`ws://127.0.0.1:${5440}`] : [];\n const node = await MiniLedgerNode.create({\n dataDir: dir,\n config: {\n node: { name: `demo-node-${i + 1}`, orgId: `org-${i + 1}`, role: \"validator\" },\n network: {\n listenAddress: \"127.0.0.1\",\n p2pPort: 5440 + i * 2,\n apiPort: apiPort + i * 2,\n peers,\n maxPeers: 50,\n },\n consensus: { algorithm: \"raft\", blockTimeMs: 1000, maxTxPerBlock: 500 },\n logging: { level: \"warn\" },\n api: { enabled: true, cors: true },\n },\n });\n\n await node.init();\n nodes.push(node);\n }\n\n // Start nodes with slight delay\n for (let i = 0; i < nodes.length; i++) {\n await nodes[i]!.start();\n const app = createApp(nodes[i]!);\n serve({ fetch: app.fetch, port: apiPort + i * 2 });\n console.log(` Node ${i + 1}: http://localhost:${apiPort + i * 2} (P2P: ${5440 + i * 2})`);\n if (i === 0) await sleep(500);\n }\n\n console.log(\"\\n Waiting for leader election...\");\n await sleep(5000);\n\n // Find the leader\n const leader = nodes.find((n) => n.getRaft()?.isLeader()) ?? nodes[0]!;\n console.log(` Leader elected: Node ${nodes.indexOf(leader) + 1}\\n`);\n\n // Submit sample data\n console.log(\" Submitting sample transactions...\\n\");\n\n // Deploy token contract\n await leader.submit({\n type: TxType.ContractDeploy,\n payload: { kind: \"contract:deploy\", name: \"token\", version: \"1.0\", code: TRANSFER_CONTRACT },\n });\n console.log(\" [+] Deployed 'token' contract\");\n\n // Mint tokens\n await leader.submit({\n type: TxType.ContractInvoke,\n payload: { kind: \"contract:invoke\", contract: \"token\", method: \"mint\", args: [10000] },\n });\n console.log(\" [+] Minted 10,000 tokens\");\n\n // Add some state\n await leader.submit({ key: \"company:acme\", value: { name: \"Acme Corp\", industry: \"Manufacturing\", employees: 5000 } });\n await leader.submit({ key: \"company:globex\", value: { name: \"Globex Inc\", industry: \"Finance\", employees: 3200 } });\n await leader.submit({ key: \"company:initech\", value: { name: \"Initech LLC\", industry: \"Technology\", employees: 800 } });\n console.log(\" [+] Added 3 company records\");\n\n // Create a governance proposal\n await leader.submit({\n type: TxType.GovernancePropose,\n payload: {\n kind: \"governance:propose\",\n title: \"Increase block size to 1000 tx\",\n description: \"Proposal to double the max transactions per block for better throughput\",\n action: { type: \"update-config\", maxTxPerBlock: 1000 },\n },\n });\n console.log(\" [+] Created governance proposal\");\n\n await sleep(2000);\n\n const status = leader.getStatus();\n console.log(`\\n Cluster running!`);\n console.log(` Chain height: ${status.chainHeight}`);\n console.log(` Peers: ${status.peerCount}`);\n console.log(`\\n Dashboard: http://localhost:${apiPort}/dashboard`);\n console.log(`\\n Try these:`);\n console.log(` curl http://localhost:${apiPort}/status`);\n console.log(` curl http://localhost:${apiPort}/blocks/latest`);\n console.log(` curl -X POST http://localhost:${apiPort}/state/query -H \"Content-Type: application/json\" -d '{\"sql\":\"SELECT * FROM world_state WHERE key LIKE \\\\'company:%\\\\'\"}'`);\n console.log(`\\n Press Ctrl+C to stop\\n`);\n\n // Try to open browser\n openBrowser(`http://localhost:${apiPort}/dashboard`);\n\n // Graceful shutdown\n const shutdown = async () => {\n console.log(\"\\n Shutting down demo...\");\n for (const node of nodes) await node.stop();\n for (const dir of dirs) {\n try { require(\"node:fs\").rmSync(dir, { recursive: true, force: true }); } catch {}\n }\n process.exit(0);\n };\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n } catch (err) {\n console.error(\" Demo failed:\", err);\n for (const node of nodes) await node.stop().catch(() => {});\n process.exit(1);\n }\n });\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n}\n\nfunction openBrowser(url: string): void {\n const cmd =\n process.platform === \"darwin\" ? \"open\" :\n process.platform === \"win32\" ? \"start\" : \"xdg-open\";\n exec(`${cmd} ${url}`);\n}\n","import * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\n\nexport function createTempDir(prefix = \"miniledger-demo-\"): string {\n return fs.mkdtempSync(path.join(os.tmpdir(), prefix));\n}\n"],"mappings":"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","names":["fs","path","ed","sign","verify","Database","import_sha256","program","path","fs","import_node_events","TxType","resolve","import_ws","WebSocket","resolve","import_node_events","pino","verify","sign","fs","path","import_hono","import_hono","import_hono","import_zod","import_hono","import_hono","import_hono","import_hono","program","import_node_server","program","program","program","program","fs","path","program","program","import_node_server","fs","path","program","program"]}
|