Skip to content

feat: add incremental computation for STX:BTC ratio#6965

Open
brice-stacks wants to merge 50 commits intostacks-network:pox-5-integrationfrom
brice-stacks:feat/stx-btc-ratio-incremental
Open

feat: add incremental computation for STX:BTC ratio#6965
brice-stacks wants to merge 50 commits intostacks-network:pox-5-integrationfrom
brice-stacks:feat/stx-btc-ratio-incremental

Conversation

@brice-stacks
Copy link
Copy Markdown
Contributor

Description

Build on #6950, adding a cache and incremental computation for the STX:BTC ratio computation.

Applicable issues

Additional info (benefits, drawbacks, caveats)

Checklist

  • Test coverage for new or modified code paths
  • For new Clarity features or consensus changes, add property tests (see docs/property-testing.md)
  • Changelog is updated
  • Required documentation changes (e.g., rpc/openapi.yaml for RPC endpoints, event-dispatcher.md for new events)
  • New clarity functions have corresponding PR in clarity-benchmarking repo

Uses the miner spending (in BTC) and miner earning (in STX) to compute a
reasonable price ratio. Then, to smooth this price, to prevent miner
actions from causing disruptions, we compute a weighted geometric mean
over the last 5 cycles. This computation is currently available via
`stacks-inspect` with the `get-stx-btc-ratio` command, and via RPC at
the `/v3/stx_btc_ratio/` endpoint.
We'll need this for the STX/BTC pricing ratio calculation.
The median can't easily be computed, so retrieve it from the Bitcoin
node with a new RPC interface.
This is an "expected" or estimated fee, not the actual fee. For our
STX:BTC pricing, we only care about this expected fee.
In order to ensure nodes are all collecting the same data, gate the
inclusion of the missed commit "burn" and the "expected" BTC fees for
all commits. This can be enabled once we are sure that the changes to
record these values in the DB have been guaranteed by a hard fork
(likely 3.5).
Later, when we cache these ratios, this auth can be removed.
It is no longer expensive with the changes to compute it incrementally.
@brice-stacks brice-stacks force-pushed the feat/stx-btc-ratio-incremental branch from 353bfd7 to 3a30bf9 Compare March 7, 2026 15:46
@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 7, 2026

Codecov Report

❌ Patch coverage is 48.07692% with 1026 lines in your changes missing coverage. Please review.
✅ Project coverage is 60.07%. Comparing base (995ebd0) to head (def5609).

Files with missing lines Patch % Lines
stackslib/src/chainstate/nakamoto/mod.rs 53.60% 663 Missing ⚠️
stackslib/src/net/api/getstxbtcratio.rs 8.82% 124 Missing ⚠️
stackslib/src/burnchains/bitcoin/blocks.rs 29.86% 101 Missing ⚠️
stackslib/src/chainstate/burn/db/sortdb.rs 44.96% 71 Missing ⚠️
.../chainstate/burn/operations/leader_block_commit.rs 40.90% 26 Missing ⚠️
stackslib/src/config/chain_data.rs 8.33% 11 Missing ⚠️
stackslib/src/burnchains/bitcoin/indexer.rs 69.56% 7 Missing ⚠️
...lib/src/chainstate/burn/operations/delegate_stx.rs 14.28% 6 Missing ⚠️
stackslib/src/chainstate/burn/distribution.rs 50.00% 3 Missing ⚠️
...ckslib/src/chainstate/burn/operations/stack_stx.rs 40.00% 3 Missing ⚠️
... and 7 more
Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #6965      +/-   ##
===========================================
- Coverage    68.63%   60.07%   -8.57%     
===========================================
  Files          412      413       +1     
  Lines       219013   220878    +1865     
  Branches       338      338              
===========================================
- Hits        150330   132697   -17633     
- Misses       68683    88181   +19498     
Files with missing lines Coverage Δ
stacks-common/src/types/mod.rs 75.81% <100.00%> (-4.54%) ⬇️
...cks-node/src/burnchains/bitcoin/core_controller.rs 91.75% <ø> (-3.10%) ⬇️
stacks-node/src/burnchains/mocknet_controller.rs 69.26% <100.00%> (+0.14%) ⬆️
stacks-node/src/burnchains/mod.rs 62.50% <ø> (ø)
stacks-node/src/nakamoto_node/relayer.rs 75.80% <100.00%> (+1.73%) ⬆️
stacks-node/src/neon_node.rs 79.29% <100.00%> (+5.51%) ⬆️
stacks-node/src/node.rs 87.32% <100.00%> (+0.01%) ⬆️
stackslib/src/burnchains/bitcoin/mod.rs 38.66% <ø> (-1.34%) ⬇️
...hains/bitcoin/rpc/bitcoin_rpc_client/test_utils.rs 91.66% <ø> (ø)
...ib/src/burnchains/bitcoin/rpc/rpc_transport/mod.rs 93.33% <100.00%> (ø)
... and 22 more

... and 274 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 995ebd0...def5609. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@brice-stacks
Copy link
Copy Markdown
Contributor Author

Doing some testing on a live mainnet node and it is looking pretty good:

$ curl -s http://localhost:20443/v3/stx_btc_ratio/129 | jq .
{
  "reward_cycle": 129,
  "tenure_count": 1848,
  "stx_earned_ustx": 2104226244168,
  "btc_spent_sats": 740000000,
  "stx_btc_ratio": 2843,
  "smoothed_stx_btc_ratio": 2945
}

I did notice an issue with the cycle in which we update the node -- it needs some logic to know that it does not have all of the information for that cycle instead of thinking that it is up-to-date, because the last_tenure_ch is the latest, but actually, it is missing all of the tenures in this cycle before it started.

I think it either needs to calculate the current cycle on startup, or not cache anything until the first run of the complete check... I'll work on this.

@brice-stacks
Copy link
Copy Markdown
Contributor Author

with the latest fix, I'm running this on a live mainnet node and it is looking good.

@hstove-stacks hstove-stacks self-requested a review March 11, 2026 14:24
@coveralls
Copy link
Copy Markdown

coveralls commented Mar 25, 2026

Coverage Report for CI Build 24478307557

Coverage increased (+39.0%) to 85.679%

Details

  • Coverage increased (+39.0%) from the base build.
  • Patch coverage: 143 uncovered changes across 5 files (1786 of 1929 lines covered, 92.59%).
  • 1244 coverage regressions across 40 files.

Uncovered Changes

File Changed Covered %
stackslib/src/chainstate/nakamoto/mod.rs 1317 1191 90.43%
stackslib/src/net/api/getstxbtcratio.rs 133 120 90.23%
stackslib/src/burnchains/bitcoin/blocks.rs 183 181 98.91%
stackslib/src/chainstate/burn/operations/test/mod.rs 2 1 50.0%
stackslib/src/config/chain_data.rs 12 11 91.67%

Coverage Regressions

1244 previously-covered lines in 40 files lost coverage.

Top 10 Files by Coverage Loss Lines Losing Coverage Coverage
stackslib/src/config/mod.rs 214 68.77%
stackslib/src/chainstate/nakamoto/signer_set.rs 158 72.84%
clarity/src/vm/database/structures.rs 139 80.85%
clarity/src/vm/database/clarity_db.rs 110 80.95%
stackslib/src/chainstate/coordinator/mod.rs 107 81.95%
stackslib/src/chainstate/stacks/boot/mod.rs 88 94.53%
stackslib/src/chainstate/stacks/db/transactions.rs 81 97.04%
pox-locking/src/events.rs 49 81.07%
clarity/src/vm/functions/assets.rs 48 84.78%
stacks-node/src/burnchains/bitcoin_regtest_controller.rs 46 92.43%

Coverage Stats

Coverage Status
Relevant Lines: 223026
Covered Lines: 191087
Line Coverage: 85.68%
Coverage Strength: 17341400.18 hits per line

💛 - Coveralls

if totals.tenure_count == 0 || totals.btc_spent_sats == 0 {
return None;
}
Some(totals.stx_earned_ustx / u128::from(totals.btc_spent_sats))
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this integer floor division becomes a problem if the STX price is >1% of the BTC price. That would be a great problem to have.

Comment thread stackslib/src/burnchains/bitcoin/blocks.rs Outdated
Comment on lines +4854 to +4855
let smoothed_ratio = low >> FIXED_POINT_SHIFT;
Some(uint256_to_u128_saturating(&smoothed_ratio))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it feasible to just hold on to the fractional bits? When this gets consumed by the reward set calculation, it can handle scaling the fixed point appropriately, then we won't lose much precision when the ratio declines.

@brice-stacks brice-stacks changed the base branch from develop to pox-5-integration April 15, 2026 18:43
@brice-stacks
Copy link
Copy Markdown
Contributor Author

I'll come back to this later as it will not be necessary in the first iteration of the design.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants