Skip to content

Verify the CBTC deposit address locally - #14

Open
sosaucily wants to merge 1 commit into
mainfrom
fix/verify-deposit-address
Open

sosaucily wants to merge 1 commit into
mainfrom
fix/verify-deposit-address

Conversation

@sosaucily

Copy link
Copy Markdown

What

cbtc::mint::get_bitcoin_address now checks the address that the BitSafe API returns. The lib derives the address itself from public inputs and fails when the two differ. get_deposit_account_status gets the same check, because it calls get_bitcoin_address.

Closes #10. Part of the plan in DLC-link/dlc-attestor-stack#835.

Why

Before this change, the lib returned whatever address the API sent. TLS does not help when the API itself is compromised, or when someone hijacks the bitsafe.finance domain and gets a valid certificate. A merchant would then fund an address that the attestors do not control. That BTC cannot be recovered.

How it works

  • src/tokens/cbtc/deposit_address.rs mirrors generate_taproot_output_info in the attestor (attestor/src/attestor/cbtc_bitcoin.rs). The internal key is the BIP-341 unspendable point with chain code SHA-256(id), derived at m/0/0. The one script leaf is <group key> OP_CHECKSIG. The output is P2TR.
  • The lib pins the attestor group key for each network as the xpub string that the attestors publish at /cbtc/v1/address-calculation-data. An operator can compare the pinned value with that endpoint by eye.
  • Devnet maps to Bitcoin regtest, testnet to testnet, and mainnet to Bitcoin.

Key decisions

  • The lib still calls the API. After a new DKG, the API returns addresses for the new key, and the old pinned key no longer matches. The mismatch error stops a merchant from funding an address that the new group cannot spend. A local-only derivation would fund the old address silently.
  • A new DKG needs a new release. The changelog says so. Please confirm on #835 that resharing keeps the group key.
  • The derivation is copied, not shared. It is about 40 lines. A shared crate would tie this lib to the attestor's bitcoin 0.29. The test vectors come from the live attestors, so any drift fails a test.
  • New dependency: bitcoin 0.32. It is rust-bitcoin, the standard maintained crate for this work, and it brings secp256k1. This lib's deny.toml checks advisories only. The crate's CC0 license needs no change.
  • derive stays private. A public version would let callers skip the API check.

How tested

  • Unit tests: six live vectors (a real account and the change id on each network), a swapped address, and the right account on the wrong network.
  • An ignored live test, pinned_keys_match_the_live_attestors, checks the pinned xpub and all 901 published addresses on devnet, testnet and mainnet. It passes. Run it before a release and after any DKG: cargo test --lib -- --ignored pinned_keys_match_the_live_attestors.
  • I also checked /cbtc/v1/bitcoin-address/{id} by hand on each network. The returned addresses match the local derivation.
  • cargo fmt --check, cargo clippy --all-targets and cargo test pass. cargo-deny runs in CI.

Author: Claude Code (Claude Opus 5.5), working for Jesse.

🤖 Generated with Claude Code

get_bitcoin_address returned whatever address the BitSafe API sent.
A compromised API or a hijacked API domain could hand out an address
that the attestors do not control.

The lib now derives the address from the attestor group key that it
pins per network, the same way the attestors do, and fails when the
API returns a different one. It still asks the API, so a new attestor
key after a DKG causes an error instead of a deposit to an old-key
address.

Closes #10.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@socket-security

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedbitcoin@​0.32.1027710090100100

View full report

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.

Verify the CBTC deposit address before returning it

1 participant