Skip to content

Commit 1087bf0

Browse files
committed
f BDK: Account for persistence changes 2: add WalletPersister
1 parent 111ee78 commit 1087bf0

File tree

4 files changed

+392
-1
lines changed

4 files changed

+392
-1
lines changed

src/io/mod.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,45 @@ pub(crate) const LATEST_RGS_SYNC_TIMESTAMP_KEY: &str = "latest_rgs_sync_timestam
4242
pub(crate) const LATEST_NODE_ANN_BCAST_TIMESTAMP_PRIMARY_NAMESPACE: &str = "";
4343
pub(crate) const LATEST_NODE_ANN_BCAST_TIMESTAMP_SECONDARY_NAMESPACE: &str = "";
4444
pub(crate) const LATEST_NODE_ANN_BCAST_TIMESTAMP_KEY: &str = "latest_node_ann_bcast_timestamp";
45+
46+
/// The BDK wallet's [`ChangeSet::descriptor`] will be persisted under this key.
47+
///
48+
/// [`ChangeSet::descriptor`]: bdk_wallet::ChangeSet::descriptor
49+
pub(crate) const BDK_WALLET_DESCRIPTOR_PRIMARY_NAMESPACE: &str = "bdk_wallet";
50+
pub(crate) const BDK_WALLET_DESCRIPTOR_SECONDARY_NAMESPACE: &str = "";
51+
pub(crate) const BDK_WALLET_DESCRIPTOR_KEY: &str = "descriptor";
52+
53+
/// The BDK wallet's [`ChangeSet::change_descriptor`] will be persisted under this key.
54+
///
55+
/// [`ChangeSet::change_descriptor`]: bdk_wallet::ChangeSet::change_descriptor
56+
pub(crate) const BDK_WALLET_CHANGE_DESCRIPTOR_PRIMARY_NAMESPACE: &str = "bdk_wallet";
57+
pub(crate) const BDK_WALLET_CHANGE_DESCRIPTOR_SECONDARY_NAMESPACE: &str = "";
58+
pub(crate) const BDK_WALLET_CHANGE_DESCRIPTOR_KEY: &str = "change_descriptor";
59+
60+
/// The BDK wallet's [`ChangeSet::network`] will be persisted under this key.
61+
///
62+
/// [`ChangeSet::network`]: bdk_wallet::ChangeSet::network
63+
pub(crate) const BDK_WALLET_NETWORK_PRIMARY_NAMESPACE: &str = "bdk_wallet";
64+
pub(crate) const BDK_WALLET_NETWORK_SECONDARY_NAMESPACE: &str = "";
65+
pub(crate) const BDK_WALLET_NETWORK_KEY: &str = "network";
66+
67+
/// The BDK wallet's [`ChangeSet::local_chain`] will be persisted under this key.
68+
///
69+
/// [`ChangeSet::local_chain`]: bdk_wallet::ChangeSet::local_chain
70+
pub(crate) const BDK_WALLET_LOCAL_CHAIN_PRIMARY_NAMESPACE: &str = "bdk_wallet";
71+
pub(crate) const BDK_WALLET_LOCAL_CHAIN_SECONDARY_NAMESPACE: &str = "";
72+
pub(crate) const BDK_WALLET_LOCAL_CHAIN_KEY: &str = "local_chain";
73+
74+
/// The BDK wallet's [`ChangeSet::tx_graph`] will be persisted under this key.
75+
///
76+
/// [`ChangeSet::tx_graph`]: bdk_wallet::ChangeSet::tx_graph
77+
pub(crate) const BDK_WALLET_TX_GRAPH_PRIMARY_NAMESPACE: &str = "bdk_wallet";
78+
pub(crate) const BDK_WALLET_TX_GRAPH_SECONDARY_NAMESPACE: &str = "";
79+
pub(crate) const BDK_WALLET_TX_GRAPH_KEY: &str = "tx_graph";
80+
81+
/// The BDK wallet's [`ChangeSet::indexer`] will be persisted under this key.
82+
///
83+
/// [`ChangeSet::indexer`]: bdk_wallet::ChangeSet::indexer
84+
pub(crate) const BDK_WALLET_INDEXER_PRIMARY_NAMESPACE: &str = "bdk_wallet";
85+
pub(crate) const BDK_WALLET_INDEXER_SECONDARY_NAMESPACE: &str = "";
86+
pub(crate) const BDK_WALLET_INDEXER_KEY: &str = "indexer";

src/io/utils.rs

Lines changed: 169 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ use crate::logger::{log_error, FilesystemLogger};
1212
use crate::peer_store::PeerStore;
1313
use crate::sweep::DeprecatedSpendableOutputInfo;
1414
use crate::types::{Broadcaster, ChainSource, DynStore, FeeEstimator, KeysManager, Sweeper};
15+
use crate::wallet::ser::{ChangeSetDeserWrapper, ChangeSetSerWrapper};
1516
use crate::{Error, EventQueue, PaymentDetails};
1617

1718
use lightning::io::Cursor;
19+
use lightning::ln::msgs::DecodeError;
1820
use lightning::routing::gossip::NetworkGraph;
1921
use lightning::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringDecayParameters};
2022
use lightning::util::logger::Logger;
@@ -27,9 +29,17 @@ use lightning::util::persist::{
2729
};
2830
use lightning::util::ser::{Readable, ReadableArgs, Writeable};
2931
use lightning::util::string::PrintableString;
32+
use lightning::util::sweep::{OutputSpendStatus, OutputSweeper};
33+
34+
use bdk_chain::indexer::keychain_txout::ChangeSet as BdkIndexerChangeSet;
35+
use bdk_chain::local_chain::ChangeSet as BdkLocalChainChangeSet;
36+
use bdk_chain::miniscript::{Descriptor, DescriptorPublicKey};
37+
use bdk_chain::tx_graph::ChangeSet as BdkTxGraphChangeSet;
38+
use bdk_chain::ConfirmationBlockTime;
39+
use bdk_wallet::ChangeSet as BdkWalletChangeSet;
3040

3141
use bip39::Mnemonic;
32-
use lightning::util::sweep::{OutputSpendStatus, OutputSweeper};
42+
use bitcoin::Network;
3343
use rand::{thread_rng, RngCore};
3444

3545
use std::fs;
@@ -519,6 +529,164 @@ pub(crate) fn check_namespace_key_validity(
519529
Ok(())
520530
}
521531

532+
macro_rules! impl_read_write_change_set_type {
533+
( $read_name: ident, $write_name: ident, $change_set_type:ty, $primary_namespace: expr, $secondary_namespace: expr, $key: expr ) => {
534+
pub(crate) fn $read_name<L: Deref>(
535+
kv_store: Arc<DynStore>, logger: L,
536+
) -> Result<Option<$change_set_type>, std::io::Error>
537+
where
538+
L::Target: Logger,
539+
{
540+
let bytes = match kv_store.read($primary_namespace, $secondary_namespace, $key) {
541+
Ok(bytes) => bytes,
542+
Err(e) => {
543+
if e.kind() == lightning::io::ErrorKind::NotFound {
544+
return Ok(None);
545+
} else {
546+
log_error!(
547+
logger,
548+
"Reading data from key {}/{}/{} failed due to: {}",
549+
$primary_namespace,
550+
$secondary_namespace,
551+
$key,
552+
e
553+
);
554+
return Err(e.into());
555+
}
556+
},
557+
};
558+
559+
let mut reader = Cursor::new(bytes);
560+
let res: Result<ChangeSetDeserWrapper<$change_set_type>, DecodeError> =
561+
Readable::read(&mut reader);
562+
match res {
563+
Ok(res) => Ok(Some(res.0)),
564+
Err(e) => {
565+
log_error!(logger, "Failed to deserialize BDK wallet field: {}", e);
566+
Err(std::io::Error::new(
567+
std::io::ErrorKind::InvalidData,
568+
"Failed to deserialize BDK wallet field",
569+
))
570+
},
571+
}
572+
}
573+
574+
pub(crate) fn $write_name<L: Deref>(
575+
value: &$change_set_type, kv_store: Arc<DynStore>, logger: L,
576+
) -> Result<(), std::io::Error>
577+
where
578+
L::Target: Logger,
579+
{
580+
let data = ChangeSetSerWrapper(value).encode();
581+
kv_store.write($primary_namespace, $secondary_namespace, $key, &data).map_err(|e| {
582+
log_error!(
583+
logger,
584+
"Writing data to key {}/{}/{} failed due to: {}",
585+
$primary_namespace,
586+
$secondary_namespace,
587+
$key,
588+
e
589+
);
590+
e.into()
591+
})
592+
}
593+
};
594+
}
595+
596+
impl_read_write_change_set_type!(
597+
read_bdk_wallet_descriptor,
598+
write_bdk_wallet_descriptor,
599+
Descriptor<DescriptorPublicKey>,
600+
BDK_WALLET_DESCRIPTOR_PRIMARY_NAMESPACE,
601+
BDK_WALLET_DESCRIPTOR_SECONDARY_NAMESPACE,
602+
BDK_WALLET_DESCRIPTOR_KEY
603+
);
604+
605+
impl_read_write_change_set_type!(
606+
read_bdk_wallet_change_descriptor,
607+
write_bdk_wallet_change_descriptor,
608+
Descriptor<DescriptorPublicKey>,
609+
BDK_WALLET_CHANGE_DESCRIPTOR_PRIMARY_NAMESPACE,
610+
BDK_WALLET_CHANGE_DESCRIPTOR_SECONDARY_NAMESPACE,
611+
BDK_WALLET_CHANGE_DESCRIPTOR_KEY
612+
);
613+
614+
impl_read_write_change_set_type!(
615+
read_bdk_wallet_network,
616+
write_bdk_wallet_network,
617+
Network,
618+
BDK_WALLET_NETWORK_PRIMARY_NAMESPACE,
619+
BDK_WALLET_NETWORK_SECONDARY_NAMESPACE,
620+
BDK_WALLET_NETWORK_KEY
621+
);
622+
623+
impl_read_write_change_set_type!(
624+
read_bdk_wallet_local_chain,
625+
write_bdk_wallet_local_chain,
626+
BdkLocalChainChangeSet,
627+
BDK_WALLET_LOCAL_CHAIN_PRIMARY_NAMESPACE,
628+
BDK_WALLET_LOCAL_CHAIN_SECONDARY_NAMESPACE,
629+
BDK_WALLET_LOCAL_CHAIN_KEY
630+
);
631+
632+
impl_read_write_change_set_type!(
633+
read_bdk_wallet_tx_graph,
634+
write_bdk_wallet_tx_graph,
635+
BdkTxGraphChangeSet<ConfirmationBlockTime>,
636+
BDK_WALLET_TX_GRAPH_PRIMARY_NAMESPACE,
637+
BDK_WALLET_TX_GRAPH_SECONDARY_NAMESPACE,
638+
BDK_WALLET_TX_GRAPH_KEY
639+
);
640+
641+
impl_read_write_change_set_type!(
642+
read_bdk_wallet_indexer,
643+
write_bdk_wallet_indexer,
644+
BdkIndexerChangeSet,
645+
BDK_WALLET_INDEXER_PRIMARY_NAMESPACE,
646+
BDK_WALLET_INDEXER_SECONDARY_NAMESPACE,
647+
BDK_WALLET_INDEXER_KEY
648+
);
649+
650+
// Reads the full BdkWalletChangeSet or returns default fields
651+
pub(crate) fn read_bdk_wallet_change_set(
652+
kv_store: Arc<DynStore>, logger: Arc<FilesystemLogger>,
653+
) -> Result<Option<BdkWalletChangeSet>, std::io::Error> {
654+
let mut change_set = BdkWalletChangeSet::default();
655+
656+
// We require a descriptor and return `None` to signal creation of a new wallet otherwise.
657+
if let Some(descriptor) =
658+
read_bdk_wallet_descriptor(Arc::clone(&kv_store), Arc::clone(&logger))?
659+
{
660+
change_set.descriptor = Some(descriptor);
661+
} else {
662+
return Ok(None);
663+
}
664+
665+
// We require a change_descriptor and return `None` to signal creation of a new wallet otherwise.
666+
if let Some(change_descriptor) =
667+
read_bdk_wallet_change_descriptor(Arc::clone(&kv_store), Arc::clone(&logger))?
668+
{
669+
change_set.change_descriptor = Some(change_descriptor);
670+
} else {
671+
return Ok(None);
672+
}
673+
674+
// We require a network and return `None` to signal creation of a new wallet otherwise.
675+
if let Some(network) = read_bdk_wallet_network(Arc::clone(&kv_store), Arc::clone(&logger))? {
676+
change_set.network = Some(network);
677+
} else {
678+
return Ok(None);
679+
}
680+
681+
read_bdk_wallet_local_chain(Arc::clone(&kv_store), Arc::clone(&logger))?
682+
.map(|local_chain| change_set.local_chain = local_chain);
683+
read_bdk_wallet_tx_graph(Arc::clone(&kv_store), Arc::clone(&logger))?
684+
.map(|tx_graph| change_set.tx_graph = tx_graph);
685+
read_bdk_wallet_indexer(Arc::clone(&kv_store), Arc::clone(&logger))?
686+
.map(|indexer| change_set.indexer = indexer);
687+
Ok(Some(change_set))
688+
}
689+
522690
#[cfg(test)]
523691
mod tests {
524692
use super::*;

src/wallet/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ use std::ops::{Deref, DerefMut};
4545
use std::sync::{Arc, Mutex};
4646
use std::time::Duration;
4747

48+
pub(crate) mod persist;
4849
pub(crate) mod ser;
4950

5051
enum WalletSyncStatus {

0 commit comments

Comments
 (0)