Skip to main content

Crate cdk_bdk

Crate cdk_bdk 

Source
Expand description

CDK onchain backend using BDK

§CDK BDK

CDK onchain payment backend using BDK (Bitcoin Development Kit), providing on-chain Bitcoin payment functionality for CDK mint operations.

§Features

  • On-chain Bitcoin payments (receive and send)
  • BIP84 (Native SegWit) key derivation from a BIP39 mnemonic
  • SQLite-backed wallet persistence via BDK
  • Blockchain sync via Bitcoin Core RPC, Electrum, or Esplora
  • Confirmation tracking for incoming and outgoing transactions
  • Pending transaction persistence via KV store

§Chain Sources

SourceStatus
Bitcoin Core RPCSupported
ElectrumSupported
EsploraSupported

Electrum sources accept tcp:// and ssl:// server URLs:

let chain_source = ChainSource::Electrum(ElectrumConfig {
    url: "ssl://electrum.example.com:50002".to_string(),
    batch_size: 5,
});

§Usage

use cdk_bdk::{BatchConfig, BitcoinRpcConfig, CdkBdk, ChainSource, SyncConfig};

let chain_source = ChainSource::BitcoinRpc(BitcoinRpcConfig {
    host: "127.0.0.1".to_string(),
    port: 18443,
    user: "user".to_string(),
    password: "password".to_string(),
    wallet_rescan_from_height: None,
});

let backend = CdkBdk::new(
    mnemonic,
    Network::Regtest,
    chain_source,
    "/path/to/storage".to_string(),
    fee_reserve,
    kv_store,
    Some(BatchConfig::default()),
    num_confs,
    min_receive_amount_sat,
    min_send_amount_sat,
    sync_interval_secs,
    Some(30),                    // shutdown_timeout_secs
    Some(SyncConfig::default()),
)?;

§Shutdown

stop() cancels background sync and batch tasks, then awaits their exit up to a bounded timeout (default 30 seconds; configurable via shutdown_timeout_secs). If the timeout is exceeded the tasks are aborted. start() returns Error::AlreadyStarted if called while tasks are already running.

§Fee Estimation

Fee rates are estimated per-tier from the configured chain source:

TierTarget blocks
Immediate1
Standard6
Economy144

Rates are cached with a configurable TTL (default 60 seconds). On estimation failure, the configured fallback sat/vB value is used and a warning is logged – get_payment_quote does not fail due to transient estimation outages.

§Sync

The blockchain sync loop applies blocks in configurable chunks (default 16 blocks per wallet-lock acquisition) so user-facing operations like address reveal and batch construction are not blocked during long chain catch-ups. Chain-source clients are reused across sync iterations and rebuilt only on error.

Esplora sync, broadcast, and fee-estimation requests have a 10-second timeout. Esplora’s parallel_requests must be greater than zero. Missed polling ticks are skipped so a slow sync does not trigger a burst of catch-up polls.

Fresh Bitcoin Core wallets checkpoint at the current chain tip instead of scanning from genesis. When restoring from a mnemonic, set BitcoinRpcConfig::wallet_rescan_from_height to the wallet’s known birthday height. This setting only affects wallet creation and never rewinds persisted wallet state.

On reorgs, Bitcoin Core sync follows the orphaned branch’s block headers to find the actual common ancestor, including ancestors absent from the wallet’s stored checkpoints. It then replays all replacement blocks after that ancestor, even below the original birthday. The birthday controls wallet creation, not reorg recovery. Normal catch-up still resumes from the latest checkpoint. Missing headers or required block data fail the sync tick and are retried; sync does not skip affected blocks or substitute a genesis rescan for missing history. A rollback with no replacement block is retried rather than reported as completed recovery.

§Finality and Confirmation Policy

  • Finalization is policy-based: once a send or receive reaches num_confs, it is treated as final and is not reopened after deep reorgs
  • Incoming payment tracking is confirmed-only; unconfirmed tracked outputs are intentionally ignored until they satisfy the configured confirmation threshold

§Known Limitations

  • Tiered batching is scaffolded but not reachable via the standard melt flow. PaymentTier::Standard and PaymentTier::Economy are accepted by make_payment and drive the internal batch processor, but the cdk melt pipeline currently passes tier: None at execute time. All melts are effectively treated as Immediate until the upstream plumbing lands in cdk-common and cdk. See TODO(#TBD) in crates/cdk-common/src/payment.rs (from_melt_quote_with_fee) and crates/cdk/src/mint/melt/mod.rs (get_melt_onchain_quote_impl).

Re-exports§

pub use crate::chain::BitcoinRpcConfig;
pub use crate::chain::ChainSource;
pub use crate::chain::ElectrumConfig;
pub use crate::chain::EsploraConfig;
pub use crate::error::Error;
pub use crate::storage::BdkStorage;
pub use crate::storage::FinalizedReceiveIntentRecord;
pub use crate::storage::FinalizedSendIntentRecord;
pub use crate::types::BatchConfig;
pub use crate::types::FeeEstimationConfig;
pub use crate::types::PaymentMetadata;
pub use crate::types::PaymentTier;
pub use crate::types::SyncConfig;
pub use crate::types::DEFAULT_TARGET_BLOCK_TIME_SECS;
pub use crate::wallet_info::WalletAddress;
pub use crate::wallet_info::WalletBalance;
pub use crate::wallet_info::WalletKeychain;
pub use crate::wallet_info::WalletPage;
pub use crate::wallet_info::WalletTransaction;
pub use crate::wallet_info::WalletTransactionInput;
pub use crate::wallet_info::WalletTransactionOutput;

Modules§

chain
error
CDK BDK onchain backend errors
receive
Receive saga types and modules
send
On-chain send saga for batched Bitcoin transactions
storage
BDK storage operations using KV store
types
wallet_info
Read-only wallet information for operator interfaces.

Structs§

CdkBdk
CDK onchain payment backend using BDK (Bitcoin Development Kit)

Functions§

validate_existing_wallet
Verify that an existing BDK wallet is present and belongs to the configured mnemonic and network without modifying its database.