Skip to content

Commit

Permalink
temp: add persisted wallet with flat file store
Browse files Browse the repository at this point in the history
  • Loading branch information
thunderbiscuit committed Jan 4, 2024
1 parent 6bc5fd7 commit a7cebb5
Show file tree
Hide file tree
Showing 8 changed files with 43 additions and 91 deletions.
2 changes: 1 addition & 1 deletion bdk-ffi/src/bdk.udl
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ interface Wallet {
sequence<Transaction> transactions();
};

interface PersistedWallet {
interface WalletPersisted {
[Throws=TempFfiError]
constructor(Descriptor descriptor, Descriptor? change_descriptor, string persistence_backend_path, Network network);

Expand Down
8 changes: 4 additions & 4 deletions bdk-ffi/src/bitcoin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ use bdk::bitcoin::blockdata::transaction::TxOut as BdkTxOut;
use bdk::bitcoin::consensus::Decodable;
use bdk::bitcoin::network::constants::Network as BdkNetwork;
use bdk::bitcoin::psbt::PartiallySignedTransaction as BdkPartiallySignedTransaction;
use bdk::bitcoin::{Address as BdkAddress};
use bdk::bitcoin::Address as BdkAddress;
use bdk::bitcoin::OutPoint as BdkOutPoint;
use bdk::bitcoin::Transaction as BdkTransaction;
use bdk::bitcoin::Txid;

use crate::error::TempFfiError;
use std::io::Cursor;
use std::str::FromStr;
use std::sync::{Arc, Mutex};
use crate::error::TempFfiError;

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Script(pub(crate) BdkScriptBuf);
Expand Down Expand Up @@ -143,8 +143,8 @@ pub struct Transaction {
impl Transaction {
pub fn new(transaction_bytes: Vec<u8>) -> Result<Self, TempFfiError> {
let mut decoder = Cursor::new(transaction_bytes);
let tx: BdkTransaction = BdkTransaction::consensus_decode(&mut decoder)
.map_err(|_| TempFfiError::FfiError)?;
let tx: BdkTransaction =
BdkTransaction::consensus_decode(&mut decoder).map_err(|_| TempFfiError::FfiError)?;
Ok(Transaction { inner: tx })
}

Expand Down
6 changes: 1 addition & 5 deletions bdk-ffi/src/descriptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,10 +279,6 @@ impl Descriptor {
#[cfg(test)]
mod test {
use crate::*;
use assert_matches::assert_matches;

use bdk::descriptor::DescriptorError::Key;
use bdk::keys::KeyError::InvalidNetwork;

fn get_descriptor_secret_key() -> DescriptorSecretKey {
let mnemonic = Mnemonic::from_string("chaos fabric time speed sponsor all flat solution wisdom trophy crack object robot pave observe combine where aware bench orient secret primary cable detect".to_string()).unwrap();
Expand Down Expand Up @@ -397,7 +393,7 @@ mod test {
#[test]
fn test_descriptor_from_string() {
let descriptor1 = Descriptor::new("wpkh(tprv8hwWMmPE4BVNxGdVt3HhEERZhondQvodUY7Ajyseyhudr4WabJqWKWLr4Wi2r26CDaNCQhhxEftEaNzz7dPGhWuKFU4VULesmhEfZYyBXdE/0/*)".to_string(), Network::Testnet);
let descriptor2 = Descriptor::new("wpkh(tprv8hwWMmPE4BVNxGdVt3HhEERZhondQvodUY7Ajyseyhudr4WabJqWKWLr4Wi2r26CDaNCQhhxEftEaNzz7dPGhWuKFU4VULesmhEfZYyBXdE/0/*)".to_string(), Network::Bitcoin);
// let descriptor2 = Descriptor::new("wpkh(tprv8hwWMmPE4BVNxGdVt3HhEERZhondQvodUY7Ajyseyhudr4WabJqWKWLr4Wi2r26CDaNCQhhxEftEaNzz7dPGhWuKFU4VULesmhEfZYyBXdE/0/*)".to_string(), Network::Bitcoin);
// Creating a Descriptor using an extended key that doesn't match the network provided will throw and InvalidNetwork Error
assert!(descriptor1.is_ok());
// assert_matches!(
Expand Down
14 changes: 10 additions & 4 deletions bdk-ffi/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use core::fmt;
use std::convert::Infallible;
use bdk::descriptor::DescriptorError;
use bdk::wallet::error::{BuildFeeBumpError, CreateTxError};
use bdk::wallet::{NewError, NewOrLoadError};
use bdk::wallet::tx_builder::{AddUtxoError, AllowShrinkingError};
use bdk::wallet::{NewError, NewOrLoadError};
use bdk_file_store::{FileError, IterError};
use core::fmt;
use std::convert::Infallible;

#[derive(Debug, thiserror::Error)]
pub enum TempFfiError {
FfiError
FfiError,
}

impl fmt::Display for TempFfiError {
Expand Down Expand Up @@ -70,3 +70,9 @@ impl From<NewOrLoadError<std::io::Error, IterError>> for TempFfiError {
TempFfiError::FfiError
}
}

impl From<CreateTxError<std::io::Error>> for TempFfiError {
fn from(_: CreateTxError<std::io::Error>) -> Self {
TempFfiError::FfiError
}
}
2 changes: 1 addition & 1 deletion bdk-ffi/src/esplora.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use bdk_esplora::esplora_client::{BlockingClient, Builder};
use bdk_esplora::EsploraExt;

use crate::bitcoin::Transaction;
use std::sync::Arc;
use crate::error::TempFfiError;
use std::sync::Arc;

pub struct EsploraClient(BlockingClient);

Expand Down
4 changes: 2 additions & 2 deletions bdk-ffi/src/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ use bdk::keys::{
use bdk::miniscript::descriptor::{DescriptorXKey, Wildcard};
use bdk::miniscript::BareCtx;

use crate::error::TempFfiError;
use std::ops::Deref;
use std::str::FromStr;
use std::sync::{Arc, Mutex};
use crate::error::TempFfiError;

pub(crate) struct Mnemonic {
inner: BdkMnemonic,
Expand Down Expand Up @@ -248,9 +248,9 @@ impl DescriptorPublicKey {
mod test {
use crate::keys::{DerivationPath, DescriptorPublicKey, DescriptorSecretKey, Mnemonic};
// use bdk::bitcoin::hashes::hex::ToHex;
use crate::error::TempFfiError;
use bdk::bitcoin::Network;
use std::sync::Arc;
use crate::error::TempFfiError;

fn get_inner() -> DescriptorSecretKey {
let mnemonic = Mnemonic::from_string("chaos fabric time speed sponsor all flat solution wisdom trophy crack object robot pave observe combine where aware bench orient secret primary cable detect".to_string()).unwrap();
Expand Down
6 changes: 3 additions & 3 deletions bdk-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ extern crate core;

mod bitcoin;
mod descriptor;
mod error;
mod esplora;
mod keys;
mod types;
mod wallet;
mod error;

use crate::bitcoin::Address;
use crate::bitcoin::Network;
Expand All @@ -16,6 +16,7 @@ use crate::bitcoin::Script;
use crate::bitcoin::Transaction;
use crate::bitcoin::TxOut;
use crate::descriptor::Descriptor;
use crate::error::TempFfiError;
use crate::esplora::EsploraClient;
use crate::keys::DerivationPath;
use crate::keys::DescriptorPublicKey;
Expand All @@ -31,8 +32,7 @@ use crate::wallet::SentAndReceivedValues;
use crate::wallet::TxBuilder;
use crate::wallet::Update;
use crate::wallet::Wallet;
use crate::wallet::PersistedWallet;
use crate::error::TempFfiError;
use crate::wallet::WalletPersisted;

use bdk::keys::bip39::WordCount;
use bdk::wallet::tx_builder::ChangeSpendPolicy;
Expand Down
92 changes: 21 additions & 71 deletions bdk-ffi/src/wallet.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::bitcoin::{OutPoint, PartiallySignedTransaction, Transaction};
use crate::descriptor::Descriptor;
use crate::types::{Balance};
use crate::types::Balance;
use crate::types::ScriptAmount;
use crate::Script;
use crate::{AddressIndex, AddressInfo, Network};
Expand All @@ -14,28 +14,24 @@ use bdk::FeeRate;
use bdk::{SignOptions, Wallet as BdkWallet};
use bdk_file_store::Store;

// type BdkPersistedWallet<'a> = bdk::wallet::Wallet<Store<'a, ChangeSet>>;

use crate::error::TempFfiError;
use std::collections::HashSet;
use std::str::FromStr;
use std::sync::{Arc, Mutex, MutexGuard};
use crate::error::TempFfiError;

const MAGIC_BYTES: &[u8] = "bdkffi".as_bytes();

#[derive(Debug)]
pub struct Wallet {
// TODO 8: Do we really need the mutex on the wallet? Could this be an Arc?
inner_mutex: Mutex<BdkWallet>,
}



// TODO: I don't understand well these lifetime parameters yet
pub struct PersistedWallet {
inner_mutex: Mutex<BdkWallet<Arc<Store<ChangeSet>>>>,
pub struct WalletPersisted {
inner_mutex: Mutex<BdkWallet<Store<'static, ChangeSet>>>,
}

// TODO: I don't understand well these lifetime parameters yet
impl PersistedWallet {
impl WalletPersisted {
pub fn new(
descriptor: Arc<Descriptor>,
change_descriptor: Option<Arc<Descriptor>>,
Expand All @@ -44,70 +40,26 @@ impl PersistedWallet {
) -> Result<Self, TempFfiError> {
let descriptor = descriptor.as_string_private();
let change_descriptor = change_descriptor.map(|d| d.as_string_private());
let db = Arc::new(Store::<ChangeSet>::open_or_create_new("testbdkffi".as_bytes(), persistence_backend_path))?;
let db = Store::<ChangeSet>::open_or_create_new(MAGIC_BYTES, persistence_backend_path)?;

let wallet: bdk::wallet::Wallet<Store<ChangeSet>> = BdkWallet::new(
&descriptor,
change_descriptor.as_ref(),
db,
network.into(),
)?;
let wallet: bdk::wallet::Wallet<Store<ChangeSet>> =
BdkWallet::new_or_load(&descriptor, change_descriptor.as_ref(), db, network.into())?;

Ok(PersistedWallet {
Ok(WalletPersisted {
inner_mutex: Mutex::new(wallet),
})
}

pub(crate) fn get_wallet(&self) -> MutexGuard<BdkWallet<Store<ChangeSet>>> {
pub(crate) fn get_wallet(&self) -> MutexGuard<BdkWallet<Store<'static, ChangeSet>>> {
self.inner_mutex.lock().expect("wallet")
}

pub fn get_address(&self, address_index: AddressIndex) -> AddressInfo {
self.get_wallet().try_get_address(address_index.into()).unwrap().into()
self.get_wallet()
.try_get_address(address_index.into())
.unwrap()
.into()
}

// pub fn network(&self) -> Network {
// self.get_wallet().network().into()
// }
//
// pub fn get_internal_address(&self, address_index: AddressIndex) -> AddressInfo {
// self.get_wallet()
// .get_internal_address(address_index.into())
// .into()
// }
//
// pub fn get_balance(&self) -> Balance {
// let bdk_balance: bdk::wallet::Balance = self.get_wallet().get_balance();
// Balance::from(bdk_balance)
// }
//
// pub fn apply_update(&self, update: Arc<Update>) -> Result<(), TempFfiError> {
// self.get_wallet()
// .apply_update(update.0.clone())
// .map_err(|e| TempFfiError::FfiError)
// }
//
// pub fn is_mine(&self, script: &Script) -> bool {
// // TODO: Both of the following lines work. Which is better?
// self.get_wallet().is_mine(&script.0)
// // self.get_wallet().is_mine(script.0.clone().as_script())
// }
//
// pub(crate) fn sign(
// &self,
// psbt: Arc<PartiallySignedTransaction>,
// // sign_options: Option<SignOptions>,
// ) -> Result<bool, TempFfiError> {
// let mut psbt = psbt.inner.lock().unwrap();
// self.get_wallet()
// .sign(&mut psbt, SignOptions::default())
// .map_err(|e| TempFfiError::FfiError)
// }
//
// pub fn sent_and_received(&self, tx: &Transaction) -> SentAndReceivedValues {
// let (sent, received): (u64, u64) = self.get_wallet().sent_and_received(&tx.clone().into());
// SentAndReceivedValues { sent, received }
// }
}

impl Wallet {
Expand Down Expand Up @@ -154,7 +106,7 @@ impl Wallet {
pub fn apply_update(&self, update: Arc<Update>) -> Result<(), TempFfiError> {
self.get_wallet()
.apply_update(update.0.clone())
.map_err(|e| TempFfiError::FfiError)
.map_err(|_| TempFfiError::FfiError)
}

pub fn is_mine(&self, script: &Script) -> bool {
Expand All @@ -171,7 +123,7 @@ impl Wallet {
let mut psbt = psbt.inner.lock().unwrap();
self.get_wallet()
.sign(&mut psbt, SignOptions::default())
.map_err(|e| TempFfiError::FfiError)
.map_err(|_| TempFfiError::FfiError)
}

pub fn sent_and_received(&self, tx: &Transaction) -> SentAndReceivedValues {
Expand Down Expand Up @@ -638,8 +590,7 @@ impl BumpFeeTxBuilder {
&self,
wallet: &Wallet,
) -> Result<Arc<PartiallySignedTransaction>, TempFfiError> {
let txid =
Txid::from_str(self.txid.as_str()).map_err(|e| TempFfiError::FfiError)?;
let txid = Txid::from_str(self.txid.as_str()).map_err(|_| TempFfiError::FfiError)?;
let mut wallet = wallet.get_wallet();
let mut tx_builder = wallet.build_fee_bump(txid)?;
tx_builder.fee_rate(FeeRate::from_sat_per_vb(self.fee_rate));
Expand All @@ -656,9 +607,8 @@ impl BumpFeeTxBuilder {
}
}
}
let psbt: BdkPartiallySignedTransaction = tx_builder
.finish()
.map_err(|e| TempFfiError::FfiError)?;
let psbt: BdkPartiallySignedTransaction =
tx_builder.finish().map_err(|_| TempFfiError::FfiError)?;

Ok(Arc::new(psbt.into()))
}
Expand Down

0 comments on commit a7cebb5

Please sign in to comment.