feat(stats): add daily Bitcoin merge-mining metrics snapshot#258
Open
nicov-iov wants to merge 6 commits into
Open
feat(stats): add daily Bitcoin merge-mining metrics snapshot#258nicov-iov wants to merge 6 commits into
nicov-iov wants to merge 6 commits into
Conversation
Add a daily cron job that samples the latest Bitcoin blocks, detects the RSKBLOCK: merge-mining tag in each coinbase, and persists a snapshot (bitcoin_hashrate, rootstock_secured_hashrate, merge_mining_percentage, bitcoin_blocks_sampled, merge_mined_blocks) to btc_merge_mining_stats. - RSK tag detection scans the coinbase OP_RETURN outputs and input scriptSig, classifying by tag presence alone. - Bitcoin data comes from the mempool.space REST API (no dedicated node); the client treats it as untrusted: bounded timeout, retries on 429/5xx only, throttling, and block-hash validation before path interpolation. - The walk tolerates per-block fetch failures and aborts only if coverage drops below a configurable floor, so the ratio is never skewed by a failing provider.
Dependency ReviewThe following issues were found:
License Issuespackage.json
OpenSSF Scorecard
Scanned Files
|
There was a problem hiding this comment.
Pull request overview
Adds a daily persisted snapshot of Bitcoin merge-mining security metrics so the read API can expose them via /api/v3/stats, backed by a new btc_merge_mining_stats table and a scheduled indexer job.
Changes:
- Introduces merge-mining tag detection (
RSKBLOCK:) and merge-mining stats computation over a sampled BTC block window. - Adds an Esplora-compatible mempool.space client with retries/timeouts/throttling and wires it into a new daily cron upsert.
- Extends the DB schema (Prisma + SQL DDL) to store daily merge-mining metrics.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| test/rskMergeMiningTag.spec.js | Unit tests for RSK merge-mining tag detection (Esplora + Core shapes). |
| test/getMergeMiningStats.spec.js | Unit tests for sampling/coverage math and fail-fast behavior. |
| test/btcMempoolClient.spec.js | Unit tests for retries, non-retryable failures, and input validation. |
| src/lib/rskMergeMiningTag.js | Implements tag detection across coinbase input/output script hex. |
| src/lib/getMergeMiningStats.js | Computes sampled merge-mining percentage and secured hashrate. |
| src/lib/defaultConfig.js | Adds bitcoin config block for mempool API + sampling parameters. |
| src/lib/cronJobs.js | Adds a daily cron job to compute and upsert the snapshot. |
| src/lib/btcMempoolClient.js | Adds a mempool.space REST client with bounded timeout and retries. |
| prisma/schema.prisma | Adds Prisma model for btc_merge_mining_stats. |
| prisma/rsk-explorer-database.sql | Adds DDL for the new btc_merge_mining_stats table. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Reject non-positive sampleSize / out-of-range minCoverage so the ratio can never divide by zero and persist NaN. Use the correct OP_RETURN push opcode (0x29 = RSKBLOCK: + 32 bytes) in the test fixtures.
global.fetch is unavailable on the Node 16 deploy runtime, so the client would throw at runtime. Switch to axios (already a dependency, promoted to runtime) which provides timeout and HTTP-status errors natively, dropping the global fetch/AbortController usage.
Surface bitcoin.mempoolApiUrl in config-example.json so production deploys explicitly set the right network endpoint (mainnet default shown; testnet is https://mempool.space/testnet/api). Defaults for all keys live in src/lib/defaultConfig.js.
Collaborator
Author
|
Note: Closed and reopened PR to force reflect latest branch commit ede8004 (PR got desynced somehow) |
The btc_merge_mining_stats table was added without bumping the schema version header / changelog. Record it as V1.2.6.
- Correct the BTC client header: it retries on network/timeout and 429/5xx (not other 4xx), and axios is used because a fetch global is absent before Node 18. - Stop the block walk early once remaining blocks can no longer reach the minimum coverage, so a provider outage doesn't drag the cron through the whole window.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds a daily snapshot of Bitcoin merge-mining security metrics, persisted by the indexer for the read API (
explorer-api) to expose on/api/v3/stats. Companion PR: rsksmart/explorer-api#256 (same branch name).Metrics persisted to the new
btc_merge_mining_statstable (one row per UTC day):bitcoin_hashrate— estimated Bitcoin network hashratemerge_mining_percentage— share of sampled BTC blocks carrying the RSK tagrootstock_secured_hashrate—bitcoin_hashrate × merge_mining_percentagebitcoin_blocks_sampled,merge_mined_blocks— sampling transparencyHow
src/lib/rskMergeMiningTag.js): scans each coinbase's OP_RETURN outputs and input scriptSig for theRSKBLOCK:tag (RSKIP-110). Classifies by tag presence alone, never by the presence of RSK transactions. Handles both Esplora and Bitcoin Core field shapes.src/lib/btcMempoolClient.js): mempool.space REST API — no dedicated Bitcoin node required. Treated as untrusted input: bounded timeout, retries on 429/5xx only, throttle between calls, and block-hash validation before any path interpolation. Base URL is configurable (src/lib/defaultConfig.js→bitcoin), so testnet or a self-hosted Esplora mirror is a one-line override.src/lib/getMergeMiningStats.js): fetches the network hashrate first (fail fast), walks the latestblocksSample(1000 ≈ 7 days) blocks, tolerates per-block fetch failures, and aborts only if coverage drops belowminCoverage(default 0.9) so a failing provider can't skew the ratio.src/lib/cronJobs.js): a new daily cron (03:20 UTC) computes and upserts the snapshot keyed by date (idempotent). On any failure it logs and leaves the previous snapshot in place.prisma/rsk-explorer-database.sql(DDL source of truth) and mirrored inprisma/schema.prisma.Production database
This repo owns DDL for the shared database. Run once against existing production databases before deploying (the read API depends on this table):
Testing
npx mocha test/rskMergeMiningTag.spec.js test/getMergeMiningStats.spec.js test/btcMempoolClient.spec.js→ 15 passing.npm run lintclean.Follow-up
Configuration (prod)
Set the Bitcoin endpoint per deployment in
config.json(seeconfig-example.json, now includes abitcoinblock). The key that must match the network isbitcoin.mempoolApiUrl:https://mempool.space/api(default)https://mempool.space/testnet/apiAll
bitcoin.*defaults live insrc/lib/defaultConfig.js(sample size, hashrate period,minCoverage, timeouts/retries) — override inconfig.jsononly as needed.Minor doc debt (not addressed here): the config block in
README.mdpredates this change and doesn't list thebitcoinsection, andconfig-example.json'sdbblock is stale from the old stack (server/port27017). Both are pre-existing and out of scope for this PR.