bitcoindevkit / bdk-reserves

Proof-of-reserves for bitcoin-dev-kit
Other
15 stars 9 forks source link

Getting insufficient funds error when trying to create a proof of reserves #18

Closed sebastianmontero closed 1 year ago

sebastianmontero commented 1 year ago

Hi I'm trying to create a proof of reserves for a mutisig wallet, and I'm getting the following error: thread 'rocket-worker-thread' panicked at 'called `Result::unwrap()` on an `Err` value: InsufficientFunds { needed: 546, available: 0 }', /home/sebastian/.cargo/registry/src/github.com-1ecc6299db9ec823/bdk-reserves-0.24.0/src/reserves.rs:137:49

The wallets balance is: 194170

Why might this be?

ulrichard commented 1 year ago

One possible explanation could be that the funds are not confirmed in blocks. Otherwise would you provide more details?

sebastianmontero commented 1 year ago

@ulrichard All the balance is confirmed, this is the balance as returned by the wallet: Balance: Balance { immature: 0, trusted_pending: 0, untrusted_pending: 0, confirmed: 194170 } Please let me know what other details you need. Thanks

sebastianmontero commented 1 year ago

@ulrichard these are the output descriptors of the wallet I'm trying to create a proof of reserves for:

    "descriptor": "wsh(sortedmulti(2,tpubD9zJG3Z4c9LLBCTeEcq64yFtVtfDHffWspDxKLY3apTbu4ocjFoD4vXz4XV2tfMAEQ8p9Km6CiEHBYqVhhG3qPPEcBZqPnwYuWx9RVmiVLz/0/*,tpubDA5kZcnunRMnATJYbo9ar5CR5zFCs5SsHmP69noNWEFwyhSPnCDmuwUND3qAvsqyBwUtm2BGurKz5nFvACpHkFzwvmupdsbznAFMNypghFB/0/*))#3xvsph9g",
    "change_descriptor": "wsh(sortedmulti(2,tpubD9zJG3Z4c9LLBCTeEcq64yFtVtfDHffWspDxKLY3apTbu4ocjFoD4vXz4XV2tfMAEQ8p9Km6CiEHBYqVhhG3qPPEcBZqPnwYuWx9RVmiVLz/1/*,tpubDA5kZcnunRMnATJYbo9ar5CR5zFCs5SsHmP69noNWEFwyhSPnCDmuwUND3qAvsqyBwUtm2BGurKz5nFvACpHkFzwvmupdsbznAFMNypghFB/1/*))#jxu9yn3m"
}
ulrichard commented 1 year ago

This works for me with your descriptor:

use bdk::{
    bitcoin::{consensus::Encodable, util::psbt::PartiallySignedTransaction, Network},
    blockchain::ElectrumBlockchain,
    database::MemoryDatabase,
    electrum_client::Client,
    wallet::AddressIndex,
    SyncOptions, Wallet,
};
use bdk_reserves::reserves::ProofOfReserves;

fn main() {
    let message = "This is a test message";
    let network = Network::Testnet;
    let url = "ssl://electrum.blockstream.info:60002";
    let descriptors = ("wsh(sortedmulti(2,tpubD9zJG3Z4c9LLBCTeEcq64yFtVtfDHffWspDxKLY3apTbu4ocjFoD4vXz4XV2tfMAEQ8p9Km6CiEHBYqVhhG3qPPEcBZqPnwYuWx9RVmiVLz/0/*,tpubDA5kZcnunRMnATJYbo9ar5CR5zFCs5SsHmP69noNWEFwyhSPnCDmuwUND3qAvsqyBwUtm2BGurKz5nFvACpHkFzwvmupdsbznAFMNypghFB/0/*))#3xvsph9g",
    "wsh(sortedmulti(2,tpubD9zJG3Z4c9LLBCTeEcq64yFtVtfDHffWspDxKLY3apTbu4ocjFoD4vXz4XV2tfMAEQ8p9Km6CiEHBYqVhhG3qPPEcBZqPnwYuWx9RVmiVLz/1/*,tpubDA5kZcnunRMnATJYbo9ar5CR5zFCs5SsHmP69noNWEFwyhSPnCDmuwUND3qAvsqyBwUtm2BGurKz5nFvACpHkFzwvmupdsbznAFMNypghFB/1/*))#jxu9yn3m");

    let wallet = Wallet::new(
        descriptors.0,
        Some(descriptors.1),
        network,
        MemoryDatabase::default(),
    )
    .unwrap();

    let client = Client::new(url).unwrap();
    let blockchain = ElectrumBlockchain::from(client);
    wallet.sync(&blockchain, SyncOptions::default()).unwrap();

    let addr = wallet.get_address(AddressIndex::New).unwrap().to_string();
    println!("Address: {}", addr);

    match wallet.get_balance() {
        Ok(bal) => println!("Wallet balance: {}", bal),
        Err(e) => println!("Unable to determine the balance: {:?}", e),
    }

    let proof_psbt = wallet.create_proof(message).unwrap();

    //  ... after signing ...
    //    let amount = wallet.verify_proof(&proof_psbt, message, None).unwrap();
    //  ... or ...
    //    let amount = bdk_reserves::reserves::verify_proof(&proof_psbt, &message, vec![address], network).unwrap();
    //    println!("The proof is valid for {} sats", amount);

    let psbt = encode_tx(proof_psbt);
    let psbt = std::str::from_utf8(&psbt).unwrap();
    println!("proof PSBT: {}", psbt);
}

/// Encodes a partially signed transaction as base64 and returns the  bytes of the resulting string.
fn encode_tx(psbt: PartiallySignedTransaction) -> Vec<u8> {
    let mut encoded = Vec::<u8>::new();
    psbt.consensus_encode(&mut encoded).unwrap();
    let tx = base64::encode(encoded);
    tx.as_bytes().to_vec()
}
sebastianmontero commented 1 year ago

Thanks @ulrichard! Sorry, it seems the issue was that I wasn't syncing the wallet before creating the proof

sebastianmontero commented 1 year ago

Thanks @ulrichard! Sorry, it seems the issue was that I wasn't syncing the wallet before creating the proof