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