]> Untitled Git - bdk-cli/commit
Merge bitcoindevkit/bdk-cli#230: Refactor sync_kyoto_client
authormerge-script <withtvpeter@gmail.com>
Tue, 24 Feb 2026 01:21:13 +0000 (02:21 +0100)
committermerge-script <withtvpeter@gmail.com>
Tue, 24 Feb 2026 01:21:13 +0000 (02:21 +0100)
commit368b8b4cb96fcfbfcf43d16d5e2081fa07362594
tree5d04ca7e19d3db20b1a1c3105b7286816cdeec8b
parentb9cf2acc5f10db46fa30777ff0910b8610a5fc33
parent974c8d56602085a31c1252c8a7c2ae4f6e413599
Merge bitcoindevkit/bdk-cli#230: Refactor sync_kyoto_client

974c8d56602085a31c1252c8a7c2ae4f6e413599 refactor(payjoin): add payjoin error variants to BDKCliError (Mshehu5)
35d831329a9c52ad561ae7ee1a5a085c282adddb refactor(payjoin): implement polling-based monitoring with timeout (Mshehu5)
b88426adcdafa7c327465be6dfd9d8a6d03d89be refactor: use BlockchainClient as references (Mshehu5)
99b71fdaede31dd89aa10f153294bfb3e90d5e6f refactor: use handle pattern for Kyoto client (Mshehu5)

Pull request description:

  <!-- You can erase any parts of this template not applicable to your Pull Request. -->

  ### Description

  <!-- Describe the purpose of this PR, what's being adding and/or fixed -->
  This PR addresses issues encountered while implementing persistence for Payjoin specifically around the BlockchainClient only being an owned variable rather than being able to be borrowed/referenced as &Blockchainclient.
  While working on persistence I ran into problems while working on resume command which needs a blockchain client to resume states such as monitor_payjoin_proposal (receiver) and process_payjoin_proposal (sender)
  Because BlockchainClient can only be owned the current design will require a function signature of passing two separate clients to resume sender and receiver states. I initially considered splitting the command into resume_send and resume_receive but this does not fully solve the issue. In particular the sender’s process_payjoin_proposal may call broadcast_transaction and potentially broadcast multiple transactions for persisted send entries stored in the database which still requires reusable access to the client.

  This Ownership issue was previously mentioned in #200 and is also noted in a comment at the top of monitor_payjoin_proposal. It prevents the function from being able to resync multiple times and reliably detect when a transaction appears in the mempool. The root cause is that the Kyoto client Box<LightClient> is destructured and spawned into other tasks when passed through sync_kyoto_client making it unusable afterward.

  What this PR changes
  This PR fixes the issue by refactoring sync_kyoto_client

  - The logic responsible for running the Kyoto node and logger is moved into new_blockchain_client. This makes it that node is started at start of command and not during every sync

  - Instead of returning a Box<lightClient> the function now returns a KyotoClientHandle. Previously the boxed client takes ownership when destructured inside sync_kyoto_client, preventing reuse/reference.
  With the new design sync_kyoto_client takes &KyotoClientHandle, allowing the client to be Refrenced which can be used  for syncing and broadcasting transactions without being owned

  - Additionally monitor_payjoin_proposal is refactored to support resyncing demonstrating that the Kyoto client refactor successfully resolves the original limitations

  ### Notes to the reviewers

  <!-- In this section you can include notes directed to the reviewers, like explaining why some parts
  of the PR were done in a specific way -->
  After refactor I tested the kyoto client on regtest (Cause I do not have access to a signet) I had to set a trusted peer in the code to connect with a cbf count of 1 this worked and I also made transaction using the steps below:
  N.B Payjoin was also tested for the monitor_payjoin_proposal refactor using steps in project readme
  ```
  bitcoin.conf

  regtest=1
  server=1
  rpcuser=user
  rpcpassword=password
  rpcallowip=127.0.0.1
  blockfilterindex=1
  listen=1
  fallbackfee=0.001

  [regtest]
  bind=127.0.0.1
  port=18444
  peerblockfilters=1
  ```

  Step 1: Create transaction
  ```
  PSBT=$(cargo run --features cbf,sqlite -- \
    --network $NETWORK \
    wallet \
    --wallet sender_wallet \
    --ext-descriptor "$SENDER_EXT_DESC" \
    --int-descriptor "$SENDER_INT_DESC" \
    --database-type $DATABASE_TYPE \
    create_tx --to $RECEIVER_ADDR:50000 --fee_rate 1.0 | jq -r '.psbt')
  ```

  Step 2: Sign transaction
  ```
  SIGNED_PSBT=$(cargo run --features cbf,sqlite -- \
    --network $NETWORK \
    wallet \
    --wallet sender_wallet \
    --ext-descriptor "$SENDER_EXT_DESC" \
    --int-descriptor "$SENDER_INT_DESC" \
    --database-type $DATABASE_TYPE \
    sign "$PSBT" | jq -r '.psbt')
  ```

  Step 3: Broadcast transaction
  ```
  cargo run --features cbf,sqlite -- \
    --network $NETWORK \
    wallet \
    --wallet sender_wallet \
    --ext-descriptor "$SENDER_EXT_DESC" \
    --int-descriptor "$SENDER_INT_DESC" \
    --database-type $DATABASE_TYPE \
    --client-type $CLIENT_TYPE \
    --cbf-peer $CBF_PEER \
    --cbf-conn-count $CBF_CONN_COUNT \
    broadcast --psbt "$SIGNED_PSBT"
  ```
   Mine a block to confirm
  `bitcoin-cli -regtest generatetoaddress 1 $(bitcoin-cli -regtest getnewaddress)`

  Checking Transaction Status
  After broadcasting, wait a moment and sync your wallet:
  Sync wallet
  ```
  cargo run --features cbf,sqlite -- \
    --network $NETWORK \
    wallet \
    --wallet receiver_wallet \
    --ext-descriptor "$RECEIVER_EXT_DESC" \
    --int-descriptor "$RECEIVER_INT_DESC" \
    --database-type $DATABASE_TYPE \
    --client-type $CLIENT_TYPE \
    --cbf-peer $CBF_PEER \
    --cbf-conn-count $CBF_CONN_COUNT \
    sync
  ```

  Check balance
  ```
  cargo run --features cbf,sqlite -- \
    --network $NETWORK \
    wallet \
    --wallet receiver_wallet \
    --ext-descriptor "$RECEIVER_EXT_DESC" \
    --int-descriptor "$RECEIVER_INT_DESC" \
    --database-type $DATABASE_TYPE \
    balance
  ```

  List recent transactions
  ```
  cargo run --features cbf,sqlite -- \
    --network $NETWORK \
    wallet \
    --wallet sender_wallet \
    --ext-descriptor "$SENDER_EXT_DESC" \
    --int-descriptor "$SENDER_INT_DESC" \
    --database-type $DATABASE_TYPE \
    transactions
  ```

  ### Checklists

  #### All Submissions:

  * [x] I've signed all my commits
  * [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk-cli/blob/master/CONTRIBUTING.md)
  * [x] I ran `cargo fmt` and `cargo clippy` before committing

ACKs for top commit:
  tvpeter:
    ACK 974c8d56602085a31c1252c8a7c2ae4f6e413599
  notmandatory:
    ACK 974c8d56602085a31c1252c8a7c2ae4f6e413599

Tree-SHA512: 823eefdde1900fd03fc698466bce414bdba0aceae428d6fbb5af7ef0a0962a0e16948d58badc24b6f99ff9498727c912131d29f46468b421cd54d663e3ec0e8b