147 lines
20 KiB
Markdown
147 lines
20 KiB
Markdown
# Explorer: plan and recommendation
|
|
|
|
5 October 2026, after the founder read WhatToMine's listing requirements ("build it, and do we build our own explorer? who
|
|
built etherscan?"). Branch `explorer`. What exists tonight: the public stats API (`docs/api/public-stats.md`) and the
|
|
first DAG explorer pages on the site, fed by the observer. What is recommended: Blockscout for the EVM side, our own
|
|
DAG and mining pages, one shared search box.
|
|
|
|
## 1. Who built Etherscan, and the open-source routes
|
|
|
|
| Explorer | What it is | Licence and cost | Fit for Igneum |
|
|
|---|---|---|---|
|
|
| Etherscan | Built and launched in 2015 by Matthew Tan (CEO and founder); the office since January 2017 (etherscan.io/aboutus, read 5 October 2026; the page does not name the city, the founder's brief says Kuala Lumpur). Since 2020 it sells "Explorer as a Service", a white-label instance for other chains, 40 clients by 2025 (same page) | Closed source, a private company; a chain pays for an instance. Price not published; not asked | Not for us: closed, paid, and it would show nothing of the DAG, the finality or the proving layer |
|
|
| Blockscout | Open-source EVM explorer: blocks, transactions, accounts, verified contracts, token pages, an API in Etherscan's shape. Elixir (Phoenix) backend, PostgreSQL, a separate frontend; "several hundred chains and rollups" use it (README, read 5 October 2026) | "Blockscout Software Licence" (the README badge; the licence text was not read line by line, so what it permits for a hosted instance is unverified) | The EVM side for free: contracts, transactions, logs, tokens, an API developers already know |
|
|
| Otterscan | "open-source, fast, local, laptop-friendly Ethereum block explorer": a React app over an Erigon archive node, using Erigon's custom `ots_` JSON-RPC methods (github.com/otterscan/otterscan, read 5 October 2026) | MIT (the app); the `ots_` API lives inside Erigon under its licence | Not for us: it needs Erigon's RPC extensions, which the Igneum node does not have, and it has no contract verification |
|
|
|
|
## 2. What Blockscout gives us for free, and what it costs to run
|
|
|
|
Blockscout indexes through standard JSON-RPC. Its documented requirements (docs.blockscout.com, read 5 October 2026):
|
|
|
|
| Item | Blockscout's figure | Igneum node today (`vendor/igneum-node` 0.3.6 fork, `igneum/exec/src/rpc.rs`, 938 lines) |
|
|
|---|---|---|
|
|
| Software | Erlang/OTP 26, Elixir 1.15.x, Postgres 14+, Node.js 18.x.x (docs: setup/requirements/requirements) | n/a |
|
|
| Hardware, the docs' base line | "16 core, 32 thread", "128GB" RAM; the AWS example is one m5a.xlarge (4 vCPU, 16 GB) application server with 8 GB EBS and one db.t3.large RDS Postgres 14+ with 500 GB "depending on chain size" (docs: setup/requirements/resource-requirements) | A devnet at 0 EVM transactions per block needs nothing like the base line; the AWS example is the honest size for a small chain |
|
|
| Database | Ethereum mainnet 21,000 GiB, Sepolia 5,200 GiB, Ethereum Classic 555 GiB, Gnosis Chiado 470 GiB (docs: setup/requirements/database-storage-requirements, figures dated 23 December 2024) | Unmeasured for Igneum. At one chain block per second with empty blocks the row count is 86,400 blocks a day; the byte size per block is the thing to measure in the first week |
|
|
| RPC it needs from every client | `eth_blockNumber`, `eth_call`, `eth_getBalance`, `eth_getCode`, `eth_getBlockByHash`, `eth_getBlockByNumber`, `eth_getTransactionByHash`, `eth_getTransactionByBlockHashAndIndex`, `eth_getTransactionByBlockNumberAndIndex`, `eth_getTransactionReceipt`, `eth_getUncleByBlockHashAndIndex`, `eth_getLogs` (docs: setup/requirements/node-tracing-json-rpc-requirements) | The fork answers `eth_blockNumber`, `eth_call`, `eth_getBalance`, `eth_getCode`, `eth_getBlockByHash`, `eth_getBlockByNumber`, `eth_getTransactionByHash`, `eth_getTransactionByBlockNumberAndIndex`, `eth_getTransactionReceipt`, `eth_getLogs` (the match arms of `rpc.rs`). MISSING: `eth_getTransactionByBlockHashAndIndex`, `eth_getUncleByBlockHashAndIndex` (design 8.2 says uncles are "always empty": the method still has to exist). Also absent from the fork but in the design table: `eth_getStorageAt` is present; `eth_getProof`, `eth_feeHistory` present; `web3_clientVersion`, `net_version`, `net_peerCount`, `net_listening`, `eth_syncing`, `eth_mining`, `eth_protocolVersion`, `eth_accounts`, `eth_getBlockReceipts`, `eth_getBlockTransactionCountByNumber`, `eth_maxPriorityFeePerGas`, `eth_gasPrice`, `eth_estimateGas`, `eth_sendRawTransaction` present |
|
|
| Pending transactions | `txpool_content` (geth, erigon) or `parity_pendingTransactions` | Neither exists in the fork. Blockscout runs without it (the pending view stays empty) |
|
|
| Internal transactions and block rewards | `debug_traceBlockByNumber` and `debug_traceTransaction` with `callTracer` (geth variant), or `trace_replayBlockTransactions` and `trace_block` (erigon, nethermind) | None of the four exist in the fork. Design 8.2 lists them as "Supported, revm inspectors"; `rpc.rs` has no `debug_` or `trace_` method today. Without them Blockscout shows no internal transactions and no block-reward rows, and the indexer's trace fetcher must be switched off (`INDEXER_DISABLE_INTERNAL_TRANSACTIONS_FETCHER`, Blockscout's env; unverified against the current version) |
|
|
|
|
Cost of one instance on Hetzner (the price list the seeds are on, `docs/plans/seed-nodes.md`: cx23 2 vCPU 4 GB at USD 6.49 net a month; larger types not priced here): Blockscout's own AWS example is 4 vCPU 16 GB plus a 2 vCPU 8 GB database. The matching Hetzner shape is one box in the 8 GB to 16 GB class plus Postgres on the same box for a devnet, a second box for the database when the chain carries real traffic. Price it from the Hetzner API when the box is ordered; the figure here is approximate: USD 15 to 40 a month for the single box, under USD 80 for two. Plus an Igneum node on the same box or next to it (Blockscout wants a local, unlimited RPC; the public `rpc.testnet.igneum.network` is rate limited to 20 req/s, `docs/plans/testnet-go.md`).
|
|
|
|
What it costs in work, in hours not weeks: the two missing `eth_` methods (small, same shape as their by-number siblings); a decision on tracing (the `debug_` namespace with revm inspectors, design 8.2, is the larger piece and is not needed to run Blockscout without internal transactions); Blockscout's env file and a Docker compose on the box; the chain's entry in its config (chain id 4463 devnet, 4462 testnet, 4461 mainnet, design 8.1); contract verification through Sourcify or Blockscout's own verifier microservice.
|
|
|
|
## 3. What Igneum needs that must be ours
|
|
|
|
Blockscout shows a chain: numbered blocks, one parent, transactions, accounts. Igneum's execution layer is such a chain (RPC "blocks" are chain blocks, design 8.2), so Blockscout is right for it. Everything the consensus layer adds is invisible to it:
|
|
|
|
| Need | Where it comes from | State tonight |
|
|
|---|---|---|
|
|
| The DAG: every block, its parents, blue or red, pending, the selected chain, the mergeset of each chain block | the observer's `blockAdded` feed (`live_blocks`, `detail.mergeset`) | `/explorer` table and `/block/<hash>` built; the live DAG picture stays on `/live` |
|
|
| Blue score and DAA score per block, the miner's vote key, the engine tag | the block header and coinbase | built |
|
|
| Miners: payout address (the coinbase's `IGNA` tag) and the coinbase address, blocks mined, what they earned, balance | observer columns `evm_miner`, `miner_address`; `eth_getBalance` through `EXPLORER_EVM_RPC` | `/address/<addr>` built; balance shows when the deployment has an EVM RPC (none public for the devnet; `rpc.testnet.igneum.network` for the testnet) |
|
|
| The lottery program per epoch (which generated program is live, the epoch seed, the VDF) | the node reports `epochSeed` per shard plan (`igneum_getShardPlan`); the program id and the epoch boundary are not in any RPC the observer reads | not built; needs an RPC for the current program id and epoch (open) |
|
|
| Finality: checkpoints every 30 blue score, locks at two thirds of all 30-day weight, certificates, voter tables, the in-browser verifier | `live_checkpoints`, `live_certificates`, `/api/checkpoint`, `site/verify` | the block page shows a block's checkpoint state and certificate; a checkpoints list page is not built |
|
|
| Proof records and shards: the plan per chain block, who proved what, lag, payout | `live_proofs`, `igneum_getProofRecords` | the block page shows the shards and the records a block carries; a provers page (per prover: shards, lag, income) is not built |
|
|
| Pool payouts | a public pool does not exist (section 5) | not built |
|
|
| The switches: `difficulty_v2_activation_daa`, `proving_v0_activation_daa`, `fees_v1_activation_daa`, `finality_v3_activation_daa` (`/tmp/igneum-devnet/override-v3.json` on the devnet: 33,000, 84,100, 210,000, 135,200) | the params file; `igneum_getProvingStatus.activationDaa`; no RPC lists them all | not built; a "network parameters" card on `/explorer` reading a params RPC is the clean way |
|
|
|
|
## 4. Recommendation
|
|
|
|
Confirmed from the code and the RPC surface: Blockscout for contracts, transactions and accounts; our own DAG, mining,
|
|
finality and proving pages on the site, fed by the observer; one search box that routes a transaction or contract to
|
|
Blockscout and a block hash, a chain block number or a miner to our pages. Two things qualify it:
|
|
|
|
1. Blockscout cannot run against the fork as it is: `eth_getTransactionByBlockHashAndIndex` and
|
|
`eth_getUncleByBlockHashAndIndex` are missing (an hour), and there is no tracing (`debug_traceTransaction`), so
|
|
internal transactions stay off until the revm inspectors of design 8.2 exist. The execution engineer owns both.
|
|
2. One box of our own and Postgres on it, next to a node with an unlimited local RPC. Not before the public testnet
|
|
has transactions worth looking at; the devnet's blocks are empty and our pages already show them.
|
|
|
|
The search box: `site/lib/explorer.mjs` `classify()` already routes 64-hex to a block (the API falls through to a
|
|
transaction hash in the last 24 hours), 0x40 and bech32 to an address, digits to a chain block number. When Blockscout
|
|
is up, a 64-hex that is not a DAG block and a 0x40 that is a contract go to it instead of a 404.
|
|
|
|
## 5. What was built tonight
|
|
|
|
| Item | Where |
|
|
|---|---|
|
|
| `/api/stats`, `/api/supply` | `site/api/stats.mjs`, `site/api/supply.mjs`, `site/api/_neon.mjs`; the emission rule in `site/lib/emission.mjs`; `docs/api/public-stats.md` with example responses |
|
|
| `/api/explorer` | `site/api/explorer.mjs`: latest blocks, one block, height, address, search |
|
|
| Pages | `site/explorer.html`, `site/block.html`, `site/address.html`; `site/vercel.json` rewrites `/block/:id` and `/address/:addr`; the footer carries an Explorer link (the nav is unchanged: its eight items are measured to fit at 941 px, a ninth is a layout decision for the site owner) |
|
|
| Observer | `tools/observer/observer.mjs`: per-block explorer columns and `detail`, `number` from the shard plan, `rpc_load`, hourly `supply_check` |
|
|
| Preview | `node tools/site-serve.mjs` (clean URLs, the rewrites, the API functions in-process; `LIVE_TABLE_PREFIX`, `EXPLORER_EVM_RPC`, `PORT`) |
|
|
| Tests | `site/lib/explorer.test.mjs` (router, formatters), `site/lib/emission.test.mjs` (the node's own test values from `igneum.rs`, a devnet coinbase, the floor sum against a loop), `site/api/public-stats.test.mjs` (every documented field from a fixture); CI runs them, and on master `tools/ci/public-api-check.mjs https://igneum.network` |
|
|
| Screenshots | `docs/plans/explorer/explorer.png`, `block.png`, `address.png` (local preview against a test observer, 5 October 2026) |
|
|
|
|
### Observer load, measured
|
|
|
|
Two copies of the observer ran side by side against the observer node (`ws://127.0.0.1:28640`, EVM RPC
|
|
`http://127.0.0.1:26790`) with test table prefixes, 19:21 to 19:28 UTC on 5 October 2026: master's code with only a
|
|
call counter added, and this branch. Calls per wall-clock minute, as each process counted them:
|
|
|
|
| Minute (UTC) | Before, wRPC | After, wRPC | Before, EVM | After, EVM |
|
|
|---|---|---|---|---|
|
|
| 19:21 to 19:22 (partial, 50 s) | 283 | 282 | 776 | 785 |
|
|
| 19:22 | 211 | 211 | 2,119 | 2,145 |
|
|
| 19:23 | 252 | 253 | 2,487 | 2,493 |
|
|
| 19:24 | 232 | 232 | 2,487 | 2,492 |
|
|
| 19:25 | 266 | 266 | 2,491 | 2,497 |
|
|
| 19:26 | 210 | 210 | 2,485 | 2,481 |
|
|
|
|
Ratio after to before: 1.00 on both. The explorer reads everything from the notification the observer already
|
|
receives; the only new work is one SQL update per shard-plan batch. The EVM figure is the proving feed's record
|
|
polling (80 blocks per 2 s tick while proving is active, master behaviour); the observer that is live tonight points
|
|
at `http://127.0.0.1:26800` (the app's node, down), so its EVM load is zero and its proving feed reads "unreachable".
|
|
The observer node answers the proving RPCs on 26790 (`eth_chainId` 0x116f, `igneum_getProvingStatus` active); pointing
|
|
`IGNEUM_EVM_RPC` there when the observer is next restarted is a one-line change to the launch environment, not to the code.
|
|
|
|
### Supply check, measured
|
|
|
|
The first sample after start: "21 blocks, payload subsidy = rule 21/21, outputs = merged subsidies 20/20 (1 without a
|
|
verdict)". The rule in `site/lib/emission.mjs` reproduces the node's own test values (`igneum.rs`: 3,168,808,781 at
|
|
DAA 2,592,000; 1,584,404,390 at the first halving; 0 at the 32nd) and the devnet coinbase of block `2622db76` (payload
|
|
subsidy 454,486,399 at DAA 125,064; outputs 363,588,240 + 90,897,059 = 454,485,299 = E(125,063), what its merged
|
|
parent declared: `utxo_validation.rs:176` pays a merged block the subsidy its own payload carries).
|
|
|
|
## 6. A public pool with a stats API (separate item, not built)
|
|
|
|
The app carries a pool mode in the Hive package: the Flight Sheet's Pool URL is `grpc://<your node>:26610` for solo
|
|
mining or `local` to run the bundled node on the rig (`packaging/hive/README.md`); "there is no pool". A public pool
|
|
needs, in order: the pool protocol of `docs/spec/09-pool-protocol.md` implemented (templates, shares, the member's
|
|
own vote key and votes relayed, vardiff, the `stats` message: member `hashrate`, `workers`, `refusals`, `shares`, pool
|
|
`members`, `hashrate`, `blocks_24h`, `declared_share`); a pool server on its own box with a node; a payout scheme (the
|
|
spec leaves PPLNS windows and PPS fees to the pool); a stats API in the shape WhatToMine and MiningPoolStats read
|
|
(pool hashrate, miners, workers, blocks found with heights and times, fee, minimum payout, luck); and a page on the
|
|
site. None of this is in the repo; the stats API of this branch is the network side of what those sites ask for.
|
|
|
|
## 7. Unverified
|
|
|
|
- Vercel's `cleanUrls` with a rewrite destination of `/block` and `/address` (the clean names of `block.html` and
|
|
`address.html`): checked locally through `tools/site-serve.mjs`, not on a Vercel preview, because nothing was pushed.
|
|
- `/api/stats` and `/api/supply` on the live tables: the live observer has not been restarted on this code, so the
|
|
live `live_blocks` has no `number`, `tx_count` or `detail` columns yet; the handlers answer with nulls there until
|
|
the restart (the schema adds itself on start, `ALTER TABLE ... ADD COLUMN IF NOT EXISTS`). The examples in
|
|
`docs/api/public-stats.md` come from the test observer's tables.
|
|
- Blockscout's licence terms for a hosted instance, and the exact env flag that disables its trace fetcher.
|
|
- The database size per Igneum block in Blockscout, and the Hetzner price of the box: approximate above, measure and
|
|
price when ordered.
|
|
- `EXPLORER_EVM_RPC` on Vercel: no public devnet EVM RPC exists, so balances show "no EVM RPC configured" on the devnet
|
|
deployment; the testnet's `https://rpc.testnet.igneum.network` is the value for the testnet.
|
|
|
|
## 8. Devnet 3 explorer (8 October 2026, the explorer lane; the founder's order of 11:00 UK: a public explorer the same day)
|
|
|
|
What serves, all at igneum.network (the host explorer.igneum.network is a CNAME to the same Vercel project with a root rewrite to /explorer):
|
|
|
|
| Page | What it shows | Data |
|
|
|---|---|---|
|
|
| `/explorer` | the Devnet 3 strip (status, height, DAA, hash rate, chain rate, finality, program class, proving), the DAG picture (newest 150 blocks, one lane per miner, parents drawn, lock and paid marks), latest blocks (class, shards paid, final), latest transactions, the proving summary, the API list | `/api/explorer?stats=1`, `?dag=150`, `?blocks=50`, `?txs=30`, `?proving=1` |
|
|
| `/block/<hash>` or `/block/<number>` | header, parents, children, mergeset, coinbase, the EVM transactions it executed (from the indexer), the shard plan with each shard's state and the node's verdict, the checkpoint and certificate, the lock that covers it, the class; **the verified badge**: for a block under a lock the browser fetches `/api/checkpoint?index=N` and runs `site/verify/core.js` (header hashes recomputed, BLS keys aggregated, the signature checked over the weight rule) and the badge reads "verified under lock N in this browser" or the failure reason | `?block=`, `?height=`, `/api/checkpoint?index=` |
|
|
| `/tx/<hash>` | status, value, fee, gas, nonce, type, input, the receipt's Igneum section (miner tip, both burns, pgas, app share, including block and miner), the executing block's lock and shard state, the logs | `?tx=` |
|
|
| `/address/<addr>` | balance, nonce, code (contract or account), sent and received counts, the transactions of the last 7 days, the blocks mined and what they earned | `?address=` (`&before=<number>` pages the transactions) |
|
|
| `/proving` | the node's proving state, the newest 60 chain blocks with their shards by state and median lag, the provers of 24 h with payouts, the block-to-paid latency of the last hour (p50, p90) and the 24-hour totals by state | `?proving=1` |
|
|
|
|
The indexer: `tools/observer/explorer-indexer.mjs`, the observer's sibling on build-1 (unit `igneum-explorer-dn3`, User build, the same env file, `LIVE_TABLE_PREFIX=dn3_`, `IGNEUM_EVM_RPC` on loopback). It reads `eth_getBlockByNumber` with transactions and `eth_getBlockReceipts` per chain block, refreshes `eth_getBalance`, `eth_getTransactionCount` and `eth_getCode` for every address a block touches and for the observer's miners of the last 10 minutes, and keeps `igneum_getNodeInfo` (the class floors and every activation) in `dn3_explorer_state`. Tables `dn3_live_txs`, `dn3_live_accounts`, `dn3_explorer_blocks`, `dn3_explorer_state`; 7 days of transactions. Measured 10:04 to 10:07 UTC: 26,847 chain blocks and 71,218 transactions from genesis in 3 minutes; steady state 0.4 chain blocks per second at 16 percent of one core. Two classes met the same morning, each with its guard: the unit's first start read the first devnet's node for 25 s (the env file's `IGNEUM_EVM_RPC`), so the indexer now refuses any node whose `igneum_getNodeInfo.network` is not `EXPLORER_NETWORK`; and the observer node's restart at 10:21 UTC on 0324-5b673577 re-executed from block 0, so a tip below the indexed number re-reads from the tip and the API settles `chain_now` against the highest number ever indexed, not the current tip.
|
|
|
|
Read against the EVM: a block the observer called a chain block whose number the EVM later gave to another block (tip reorgs on Devnet 3 run to depth 18, `igneum_getBudgets.deepestReorg` at 10:0x UTC) reads "replaced" on the list and the block page. The table prefix default of `/api/explorer`, `/api/stats`, `/api/supply` and `/api/checkpoint` moved to `dn3_` (the live deploy had served the first devnet on those four while `/api/live` served Devnet 3).
|
|
|
|
Not yet: the STARK itself is not re-run in the browser (the node's verdict is shown as the node's; the explorer-verify branch's binding check of proof bytes to records is not merged); `eth_sendRawTransaction` and live balances from the public RPC (`rpc.devnet.igneum.network`, up since 11:08 UK) are not wired into the pages (`EXPLORER_EVM_RPC` on the deployment switches the balance read to live); a checkpoints list page; the program id per epoch (no RPC); internal transactions (no tracing RPC).
|