Files
wikideck/README.md
T
2026-10-19 16:47:27 -04:00

16 KiB
Raw Blame History

Wikideck

Mine knowledge. Collect the extraordinary. An independent, experimental RandomX testnet with native NFTs, independently validating nodes, and recoverable P-256 wallets. Built with React, TypeScript, Express, Web Crypto, and a pinned native RandomX engine.

Not a public mainnet. No public bootnodes or deployed public network are supplied. Test assets have no promised value; launch with no funds. This is not Monero mining, an Ethereum/ERC-721 NFT, an ASIC-proof claim, or an audited security product. Old browser-mined demo assets and wallets are separate: there is no migration.

Quick start: three local validators

Install Docker Desktop with Linux containers and Compose v2. From the repository root:

docker compose -f compose.testnet.yaml up --build -d
docker compose -f compose.testnet.yaml ps
docker compose -f compose.testnet.yaml logs -f node-a

Open http://127.0.0.1:3101 (node-a); node-b and node-c are at 3102 and 3103. Each independently validates blocks and has its own named volume: testnet-a, testnet-b, testnet-c (Compose prefixes actual volume names). No miner starts automatically. A healthy node is not proof of connected peers; inspect the UI peer count or /api/peers.

Stop with docker compose -f compose.testnet.yaml down; restart with the first command. Volumes survive ordinary shutdown and rebuilds. Adding -v deletes all three ledgers. Stop nodes before making consistent volume backups; never share one writable data directory between nodes. Back up wallets separately.

The default compose.yaml instead runs one node at http://127.0.0.1:3001, with a different wikideck-data volume; it is not the three-node setup. Existing project-local demo data is excluded from the image and is not imported. Current nodes write a separate testnet ledger, not the old demo chain.

Host build: Windows or Linux

Use Node.js 24 LTS, npm, Git, CMake 3.24+, and a compatible C/C++17 toolchain. Initial native configuration fetches pinned RandomX over HTTPS. On Windows, put CMake, Git, the MinGW compiler, make, and compiler runtime DLLs on PATH; use a consistent 64-bit toolchain. From a terminal in the repository root:

npm install
npm run native:configure -- -G "MinGW Makefiles"
npm run native:build
npm run test:native
npm run build
npm start

Open http://127.0.0.1:3001. In PowerShell, use npm.cmd in place of npm if execution policy blocks the npm PowerShell shim. Do not bypass a managed policy. The optional Windows script also requires permission to run: ./scripts/build-randomx.ps1 -Generator 'MinGW Makefiles' -Test. The npm commands above invoke CMake directly rather than that script. Do not switch generators inside an existing native build directory; use a fresh build directory when changing toolchains.

On Linux, install the distribution's C/C++ build tools, CMake and Git; run npm install, sh scripts/build-randomx.sh --test, npm run build, then npm start. MSVC requires a developer terminal with C++/MASM tooling; omit the MinGW generator and review upstream PowerShell build requirements. See native build, memory, and line-protocol details. The current node and CLI use that engine, with no fake production fallback.

For development, npm run dev starts the loopback API on 3001 and Vite on 5173; open http://127.0.0.1:5173. Build the native engine first. Never expose Vite publicly. Stop conflicting servers before reusing a port.

Wallet backup and recovery

  1. Open the wallet button, then Wallet backup & recovery. The browser creates an exportable ECDSA P-256 key in IndexedDB; its address is SHA-256 of the canonical SPKI public key.
  2. Download the encrypted backup with a strong, unique password (12–1024 characters). Confirm the download actually saved; store the file outside the repository/Docker build context, separately from its password. Do not commit either.
  3. Test recovery in another browser profile: choose the backup, enter its password, confirm replacement of any active wallet, and recover. Check the receive address matches. Back up the replaced wallet first; reload other open tabs before signing.

Portable backups use AES-256-GCM with authenticated headers, a fresh 16-byte salt and 12-byte IV, and PBKDF2-SHA256, 600,000 iterations. Export/import happens locally; this is control of a signing key, not a server login. No node endpoint accepts private keys, backups, or passwords. Public keys, addresses and signatures are shared normally.

IndexedDB itself is not password-encrypted. Same-origin scripts/XSS or browser-profile access may use or export the key. A backup password protects the portable file, not an unlocked browser or miner. Anyone with file and password controls the wallet. Lost passwords cannot be reset; clearing site data without a usable backup loses access.

Use a consistent browser scheme + hostname + port. localhost, 127.0.0.1, 5173, 3001 and 3101–3103 are different origins with separate wallet storage. Restore the backup at another origin to use the same identity; recovery does not move assets between chains. The UI uses same-origin RPC (Vite proxies it in development), trusts that node's reported state, and is not an SPV or independently verifying browser client.

Mine explicitly, outside the browser

After building the native engine, use the browser's encrypted backup in an interactive terminal:

npm run miner -- --wallet "path/to/encrypted-backup.json" --consent --node http://127.0.0.1:3101 --blocks 3

Replace the quoted path with your saved file. Enter the backup password at the hidden local prompt: never put passwords in environment variables or command-line arguments. The backup/password are not sent to the node. --consent is required; defaults are one worker, light mode, one block, and node port 3001. Add --fast only after budgeting memory. Ctrl+C stops mining; closing the browser does not. The page never mines or launches native programs.

  • Light mode: 256 MiB cache, about 2 MiB scratchpad, plus process overhead.
  • Fast mode: about 2080 MiB dataset plus the retained 256 MiB cache, scratchpad and overhead: budget over 2.3 GiB per miner process. Each validating node also needs its own light-mode cache. CPU, heat, energy and initialization costs are real; the Compose nodes' 1 GiB limits are not fast-miner budgets.
  • Use HTTPS for remote miner endpoints. The CLI rejects non-loopback HTTP unless explicitly overridden; do not weaken this for public connections.

The Docker runtime image includes the native engine and can run the TypeScript miner directly with Node 24; it has no runtime tsx/development dependencies. Container mining is manual, needs an interactive TTY, a read-only mounted backup, and a container-reachable node URL. A host-run CLI as above avoids Windows host-networking pitfalls. Do not bake wallets into an image or start mining as a node service.

Collect, transfer, and inspect

Each canonical block mints one native NFT; the same article may be minted repeatedly with different token IDs. Preview cards are not owned. Card details and the explorer distinguish NFT token ID, block ID and RandomX proof hash. Rarity/stats are proof-derived game values, not Wikipedia facts or a fair economic lottery.

Use another profile or a second wallet to receive a transfer. Signing submits it to the mempool: HTTP 202 is pending, not changed ownership. Ownership changes only after inclusion in the canonical chain. A mint at height h can first transfer in block h+2; the pool may accept it at tip h+1 for next-block inclusion. Confirmations count the mint block itself. Reorganizations can remove mints, reverse ownership and change confirmations; there is no fixed finality or undo for a wrong address.

Metadata is a fixed four-article catalog of original starter summaries, not a live Wikipedia API feed. The catalog is genesis-bound; expanding it currently requires a new genesis/chain. Page IDs agree across catalog and state. See consensus, identifiers, peer RPC and limits.

Live Wikipedia card insights

Cards also display optional off-chain enrichment, separate from the minted snapshot: human-readable description, visible Wikipedia categories (up to 50), article size in bytes, other-language links (up to 500, labeled as a lower bound if truncated), Wikidata ID, current revision, and six complete UTC months of Wikimedia page views. The details show the latest monthly count, daily average, six-month total, month-over-month change, and a readership chart. Counts use English Wikipedia, all access methods, and Analytics' user traffic classification; classified automated traffic is excluded. Article renames can affect title-based history. Missing/incomplete API data is shown as unavailable, never invented zeroes.

Three live scores range from 0–100, rounded and capped: Attention = log₁₀(latest complete month's views + 1) / 6 × 100; Depth = log₁₀(article bytes + 1) / 6 × 100; Reach = log₁₀(language links + 1) / 3 × 100. Depth is a size proxy, not article quality. These scores may change; the original proof-derived Power/Defense/Knowledge, rarity, NFT ownership, and consensus do not. Live revision and retrieval time are shown explicitly, with Wikipedia/Wikimedia attribution.

GET /api/wikipedia/:pageId only enriches current catalog IDs. The node contacts fixed Wikimedia HTTPS hosts with no redirects, bounded time/response sizes, four concurrent jobs, per-article request deduplication, and a bounded cache (up to six hours; shorter for partial failures). API outages do not block mining, validation, or transfers. No live enrichment is written into blocks, NFT state, or the genesis manifest; existing chains remain compatible. Rebuild the Docker image to serve this feature from containers.

Connect your own independent nodes

Operators must provision their own nodes, separate storage and connectivity; multiple containers on one machine are not independent security domains. Configure WIKIDECK_PEERS as a comma-separated list of fixed peer origins, for example https://peer-a.example.org,https://peer-b.example.org after replacing these placeholders with actual operator-controlled endpoints. Default policy requires HTTPS and public IP/DNS answers; credentials, paths, queries, fragments and redirects are rejected. At most 16 peers; no bootnodes, DHT, discovery or peer-list expansion.

WIKIDECK_ALLOW_PRIVATE_PEERS=1 explicitly permits private addresses and HTTP; the three-node Compose file uses this only for its private Docker test network. Do not carry that exception into public peer configuration. Peer URLs are operator settings, never accepted from remote peers.

For a remote experiment, choose your own public domain and HTTPS origin, reverse proxy the intended node port, and set PUBLIC_ORIGIN to that exact frontend origin. Set HOST deliberately if not loopback, firewall backend ports and configure peers on each node. This describes required operator work, not an already-deployed or production-ready public network; HTTPS and origin checks do not provide consensus/economic security or authentication.

Setting Current behavior
HOST, PORT Host defaults: 127.0.0.1, 3001; image binds 0.0.0.0:3001 inside container.
WIKIDECK_DATA_DIR Defaults to project data; image uses /app/data; testnet ledger lives in its testnet subdirectory.
RANDOMX_BINARY Optional trusted executable override; otherwise host native build output. Image sets its packaged binary.
PUBLIC_ORIGIN Additional exact allowed POST origin; not a browser RPC node selector or login.
WIKIDECK_PEERS, WIKIDECK_ALLOW_PRIVATE_PEERS Explicit outbound allowlist and opt-in private/HTTP permission; empty peers means isolated.
WIKIDECK_PORT Default Compose host-port interpolation only; does not change fixed 3101–3103 testnet mappings.

Validation and operational limits

npm run build type-checks client/server and builds the UI. npm test uses a test-only fake PoW for fast fork/ledger tests, plus real native HTTP integration when the executable exists (otherwise that test skips). Production has no fake selector/fallback. npm run test:native runs the upstream known vector after native configuration with tests enabled; the Docker build also builds RandomX and runs CTest. These checks do not certify consensus safety or a successful deployment on every platform.

For an explicitly opted-in live check against the three local Docker nodes, run node --experimental-strip-types scripts/testnet-smoke.ts --consent after building the host native engine. This mines three real testnet blocks with disposable, non-recoverable test identities, submits and mines an NFT transfer, and asserts all nodes agree on work, tip, and ownership. It changes the test network; it is never run automatically. Docker restart durability has also been exercised on the three-node setup. Fork-choice/reorg tests use the labeled fast test engine; the HTTP and live-container tests use actual RandomX.

Storage is deliberately bounded: 128 MiB ledger, 10,000 total DAG blocks including forks, 256 pending transfers. Every DAG node retains a complete NFT state; memory can grow quadratically despite disk caps. Whole-ledger atomic rewrites and full startup revalidation are unsuitable for a long-lived public chain. Corrupt/mismatched data fails closed rather than resetting. The HTTP process exclusively creates a data-directory lock; after a crash, stop/verify all owning processes are gone before manually removing the stale lock. There is no automatic stale-lock recovery.

The image runs nonroot; Compose uses loopback publishing, separate volumes, read-only roots, dropped capabilities, no-new-privileges and resource limits. There are no admin mint keys; ownership requires valid mint/transfer signatures, and private keys stay local. These measures are not a security audit. No fees or economic security exist; spam/DoS, eclipse and majority-hashpower (51%) attacks, censorship, rollback and reorgs remain material risks. Obtain independent protocol/cryptographic audits, adversarial network testing, hardened storage/abuse controls and recovery procedures before any broader launch. No funds or valuable assets.

Run npm audit, rebuild regularly, and scan the actual container/base OS and native dependencies for CVEs. Zero npm advisories is not an OS-image/native-code vulnerability guarantee; known-vector success is not an audit.

Appearance and attribution

Official Catppuccin flavors: Mocha (default), Macchiato, Frappé, and light Latte. The top-bar selector saves the flavor locally, restores it before paint, and synchronizes same-origin tabs. With blocked storage it still switches for the page; themes never change wallets or chain state.

Independent experiment, not affiliated with Wikipedia or the Wikimedia Foundation. Current starter summaries are original, explicitly labeled, and link real articles. Wikipedia contributor text, where reused, is CC BY-SA 4.0; Commons images have file-specific licenses and credits—open Image & license before reuse. Native NFT ownership grants no copyright or exclusive rights to article text/images. Linked Wikipedia content may be unsuitable for some audiences; no age filtering is provided.