ldk_node/io/
utils.rs

1// This file is Copyright its original authors, visible in version control history.
2//
3// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. You may not use this file except in
6// accordance with one or both of these licenses.
7
8use super::*;
9use crate::config::WALLET_KEYS_SEED_LEN;
10
11use crate::chain::ChainSource;
12use crate::fee_estimator::OnchainFeeEstimator;
13use crate::io::{
14	NODE_METRICS_KEY, NODE_METRICS_PRIMARY_NAMESPACE, NODE_METRICS_SECONDARY_NAMESPACE,
15};
16use crate::logger::{log_error, LdkLogger, Logger};
17use crate::peer_store::PeerStore;
18use crate::sweep::DeprecatedSpendableOutputInfo;
19use crate::types::{Broadcaster, DynStore, KeysManager, Sweeper};
20use crate::wallet::ser::{ChangeSetDeserWrapper, ChangeSetSerWrapper};
21use crate::{Error, EventQueue, NodeMetrics, PaymentDetails};
22
23use lightning::io::Cursor;
24use lightning::ln::msgs::DecodeError;
25use lightning::routing::gossip::NetworkGraph;
26use lightning::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringDecayParameters};
27use lightning::util::persist::{
28	KVSTORE_NAMESPACE_KEY_ALPHABET, KVSTORE_NAMESPACE_KEY_MAX_LEN, NETWORK_GRAPH_PERSISTENCE_KEY,
29	NETWORK_GRAPH_PERSISTENCE_PRIMARY_NAMESPACE, NETWORK_GRAPH_PERSISTENCE_SECONDARY_NAMESPACE,
30	OUTPUT_SWEEPER_PERSISTENCE_KEY, OUTPUT_SWEEPER_PERSISTENCE_PRIMARY_NAMESPACE,
31	OUTPUT_SWEEPER_PERSISTENCE_SECONDARY_NAMESPACE, SCORER_PERSISTENCE_KEY,
32	SCORER_PERSISTENCE_PRIMARY_NAMESPACE, SCORER_PERSISTENCE_SECONDARY_NAMESPACE,
33};
34use lightning::util::ser::{Readable, ReadableArgs, Writeable};
35use lightning::util::string::PrintableString;
36use lightning::util::sweep::{OutputSpendStatus, OutputSweeper};
37
38use bdk_chain::indexer::keychain_txout::ChangeSet as BdkIndexerChangeSet;
39use bdk_chain::local_chain::ChangeSet as BdkLocalChainChangeSet;
40use bdk_chain::miniscript::{Descriptor, DescriptorPublicKey};
41use bdk_chain::tx_graph::ChangeSet as BdkTxGraphChangeSet;
42use bdk_chain::ConfirmationBlockTime;
43use bdk_wallet::ChangeSet as BdkWalletChangeSet;
44
45use bip39::Mnemonic;
46use bitcoin::Network;
47use rand::{thread_rng, RngCore};
48
49use std::fs;
50use std::io::Write;
51use std::ops::Deref;
52use std::path::Path;
53use std::sync::Arc;
54
55/// Generates a random [BIP 39] mnemonic.
56///
57/// The result may be used to initialize the [`Node`] entropy, i.e., can be given to
58/// [`Builder::set_entropy_bip39_mnemonic`].
59///
60/// [BIP 39]: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
61/// [`Node`]: crate::Node
62/// [`Builder::set_entropy_bip39_mnemonic`]: crate::Builder::set_entropy_bip39_mnemonic
63pub fn generate_entropy_mnemonic() -> Mnemonic {
64	// bip39::Mnemonic supports 256 bit entropy max
65	let mut entropy = [0; 32];
66	thread_rng().fill_bytes(&mut entropy);
67	Mnemonic::from_entropy(&entropy).unwrap()
68}
69
70pub(crate) fn read_or_generate_seed_file<L: Deref>(
71	keys_seed_path: &str, logger: L,
72) -> std::io::Result<[u8; WALLET_KEYS_SEED_LEN]>
73where
74	L::Target: LdkLogger,
75{
76	if Path::new(&keys_seed_path).exists() {
77		let seed = fs::read(keys_seed_path).map_err(|e| {
78			log_error!(logger, "Failed to read keys seed file: {}", keys_seed_path);
79			e
80		})?;
81
82		if seed.len() != WALLET_KEYS_SEED_LEN {
83			log_error!(
84				logger,
85				"Failed to read keys seed file due to invalid length: {}",
86				keys_seed_path
87			);
88			return Err(std::io::Error::new(
89				std::io::ErrorKind::InvalidData,
90				"Failed to read keys seed file due to invalid length",
91			));
92		}
93
94		let mut key = [0; WALLET_KEYS_SEED_LEN];
95		key.copy_from_slice(&seed);
96		Ok(key)
97	} else {
98		let mut key = [0; WALLET_KEYS_SEED_LEN];
99		thread_rng().fill_bytes(&mut key);
100
101		if let Some(parent_dir) = Path::new(&keys_seed_path).parent() {
102			fs::create_dir_all(parent_dir).map_err(|e| {
103				log_error!(
104					logger,
105					"Failed to create parent directory for key seed file: {}.",
106					keys_seed_path
107				);
108				e
109			})?;
110		}
111
112		let mut f = fs::File::create(keys_seed_path).map_err(|e| {
113			log_error!(logger, "Failed to create keys seed file: {}", keys_seed_path);
114			e
115		})?;
116
117		f.write_all(&key).map_err(|e| {
118			log_error!(logger, "Failed to write node keys seed to disk: {}", keys_seed_path);
119			e
120		})?;
121
122		f.sync_all().map_err(|e| {
123			log_error!(logger, "Failed to sync node keys seed to disk: {}", keys_seed_path);
124			e
125		})?;
126
127		Ok(key)
128	}
129}
130
131/// Read a previously persisted [`NetworkGraph`] from the store.
132pub(crate) fn read_network_graph<L: Deref + Clone>(
133	kv_store: Arc<DynStore>, logger: L,
134) -> Result<NetworkGraph<L>, std::io::Error>
135where
136	L::Target: LdkLogger,
137{
138	let mut reader = Cursor::new(kv_store.read(
139		NETWORK_GRAPH_PERSISTENCE_PRIMARY_NAMESPACE,
140		NETWORK_GRAPH_PERSISTENCE_SECONDARY_NAMESPACE,
141		NETWORK_GRAPH_PERSISTENCE_KEY,
142	)?);
143	NetworkGraph::read(&mut reader, logger.clone()).map_err(|e| {
144		log_error!(logger, "Failed to deserialize NetworkGraph: {}", e);
145		std::io::Error::new(std::io::ErrorKind::InvalidData, "Failed to deserialize NetworkGraph")
146	})
147}
148
149/// Read a previously persisted [`ProbabilisticScorer`] from the store.
150pub(crate) fn read_scorer<G: Deref<Target = NetworkGraph<L>>, L: Deref + Clone>(
151	kv_store: Arc<DynStore>, network_graph: G, logger: L,
152) -> Result<ProbabilisticScorer<G, L>, std::io::Error>
153where
154	L::Target: LdkLogger,
155{
156	let params = ProbabilisticScoringDecayParameters::default();
157	let mut reader = Cursor::new(kv_store.read(
158		SCORER_PERSISTENCE_PRIMARY_NAMESPACE,
159		SCORER_PERSISTENCE_SECONDARY_NAMESPACE,
160		SCORER_PERSISTENCE_KEY,
161	)?);
162	let args = (params, network_graph, logger.clone());
163	ProbabilisticScorer::read(&mut reader, args).map_err(|e| {
164		log_error!(logger, "Failed to deserialize scorer: {}", e);
165		std::io::Error::new(std::io::ErrorKind::InvalidData, "Failed to deserialize Scorer")
166	})
167}
168
169/// Read previously persisted events from the store.
170pub(crate) fn read_event_queue<L: Deref + Clone>(
171	kv_store: Arc<DynStore>, logger: L,
172) -> Result<EventQueue<L>, std::io::Error>
173where
174	L::Target: LdkLogger,
175{
176	let mut reader = Cursor::new(kv_store.read(
177		EVENT_QUEUE_PERSISTENCE_PRIMARY_NAMESPACE,
178		EVENT_QUEUE_PERSISTENCE_SECONDARY_NAMESPACE,
179		EVENT_QUEUE_PERSISTENCE_KEY,
180	)?);
181	EventQueue::read(&mut reader, (kv_store, logger.clone())).map_err(|e| {
182		log_error!(logger, "Failed to deserialize event queue: {}", e);
183		std::io::Error::new(std::io::ErrorKind::InvalidData, "Failed to deserialize EventQueue")
184	})
185}
186
187/// Read previously persisted peer info from the store.
188pub(crate) fn read_peer_info<L: Deref + Clone>(
189	kv_store: Arc<DynStore>, logger: L,
190) -> Result<PeerStore<L>, std::io::Error>
191where
192	L::Target: LdkLogger,
193{
194	let mut reader = Cursor::new(kv_store.read(
195		PEER_INFO_PERSISTENCE_PRIMARY_NAMESPACE,
196		PEER_INFO_PERSISTENCE_SECONDARY_NAMESPACE,
197		PEER_INFO_PERSISTENCE_KEY,
198	)?);
199	PeerStore::read(&mut reader, (kv_store, logger.clone())).map_err(|e| {
200		log_error!(logger, "Failed to deserialize peer store: {}", e);
201		std::io::Error::new(std::io::ErrorKind::InvalidData, "Failed to deserialize PeerStore")
202	})
203}
204
205/// Read previously persisted payments information from the store.
206pub(crate) fn read_payments<L: Deref>(
207	kv_store: Arc<DynStore>, logger: L,
208) -> Result<Vec<PaymentDetails>, std::io::Error>
209where
210	L::Target: LdkLogger,
211{
212	let mut res = Vec::new();
213
214	for stored_key in kv_store.list(
215		PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE,
216		PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE,
217	)? {
218		let mut reader = Cursor::new(kv_store.read(
219			PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE,
220			PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE,
221			&stored_key,
222		)?);
223		let payment = PaymentDetails::read(&mut reader).map_err(|e| {
224			log_error!(logger, "Failed to deserialize PaymentDetails: {}", e);
225			std::io::Error::new(
226				std::io::ErrorKind::InvalidData,
227				"Failed to deserialize PaymentDetails",
228			)
229		})?;
230		res.push(payment);
231	}
232	Ok(res)
233}
234
235/// Read `OutputSweeper` state from the store.
236pub(crate) fn read_output_sweeper(
237	broadcaster: Arc<Broadcaster>, fee_estimator: Arc<OnchainFeeEstimator>,
238	chain_data_source: Arc<ChainSource>, keys_manager: Arc<KeysManager>, kv_store: Arc<DynStore>,
239	logger: Arc<Logger>,
240) -> Result<Sweeper, std::io::Error> {
241	let mut reader = Cursor::new(kv_store.read(
242		OUTPUT_SWEEPER_PERSISTENCE_PRIMARY_NAMESPACE,
243		OUTPUT_SWEEPER_PERSISTENCE_SECONDARY_NAMESPACE,
244		OUTPUT_SWEEPER_PERSISTENCE_KEY,
245	)?);
246	let args = (
247		broadcaster,
248		fee_estimator,
249		Some(chain_data_source),
250		Arc::clone(&keys_manager),
251		keys_manager,
252		kv_store,
253		logger.clone(),
254	);
255	OutputSweeper::read(&mut reader, args).map_err(|e| {
256		log_error!(logger, "Failed to deserialize OutputSweeper: {}", e);
257		std::io::Error::new(std::io::ErrorKind::InvalidData, "Failed to deserialize OutputSweeper")
258	})
259}
260
261/// Read previously persisted spendable output information from the store and migrate to the
262/// upstreamed `OutputSweeper`.
263///
264/// We first iterate all `DeprecatedSpendableOutputInfo`s and have them tracked by the new
265/// `OutputSweeper`. In order to be certain the initial output spends will happen in a single
266/// transaction (and safe on-chain fees), we batch them to happen at current height plus two
267/// blocks. Lastly, we remove the previously persisted data once we checked they are tracked and
268/// awaiting their initial spend at the correct height.
269///
270/// Note that this migration will be run in the `Builder`, i.e., at the time when the migration is
271/// happening no background sync is ongoing, so we shouldn't have a risk of interleaving block
272/// connections during the migration.
273pub(crate) fn migrate_deprecated_spendable_outputs<L: Deref>(
274	sweeper: Arc<Sweeper>, kv_store: Arc<DynStore>, logger: L,
275) -> Result<(), std::io::Error>
276where
277	L::Target: LdkLogger,
278{
279	let best_block = sweeper.current_best_block();
280
281	for stored_key in kv_store.list(
282		DEPRECATED_SPENDABLE_OUTPUT_INFO_PERSISTENCE_PRIMARY_NAMESPACE,
283		DEPRECATED_SPENDABLE_OUTPUT_INFO_PERSISTENCE_SECONDARY_NAMESPACE,
284	)? {
285		let mut reader = Cursor::new(kv_store.read(
286			DEPRECATED_SPENDABLE_OUTPUT_INFO_PERSISTENCE_PRIMARY_NAMESPACE,
287			DEPRECATED_SPENDABLE_OUTPUT_INFO_PERSISTENCE_SECONDARY_NAMESPACE,
288			&stored_key,
289		)?);
290		let output = DeprecatedSpendableOutputInfo::read(&mut reader).map_err(|e| {
291			log_error!(logger, "Failed to deserialize SpendableOutputInfo: {}", e);
292			std::io::Error::new(
293				std::io::ErrorKind::InvalidData,
294				"Failed to deserialize SpendableOutputInfo",
295			)
296		})?;
297		let descriptors = vec![output.descriptor.clone()];
298		let spend_delay = Some(best_block.height + 2);
299		sweeper
300			.track_spendable_outputs(descriptors, output.channel_id, true, spend_delay)
301			.map_err(|_| {
302				log_error!(logger, "Failed to track spendable outputs. Aborting migration, will retry in the future.");
303				std::io::Error::new(
304					std::io::ErrorKind::InvalidData,
305					"Failed to track spendable outputs. Aborting migration, will retry in the future.",
306				)
307			})?;
308
309		if let Some(tracked_spendable_output) =
310			sweeper.tracked_spendable_outputs().iter().find(|o| o.descriptor == output.descriptor)
311		{
312			match tracked_spendable_output.status {
313				OutputSpendStatus::PendingInitialBroadcast { delayed_until_height } => {
314					if delayed_until_height == spend_delay {
315						kv_store.remove(
316							DEPRECATED_SPENDABLE_OUTPUT_INFO_PERSISTENCE_PRIMARY_NAMESPACE,
317							DEPRECATED_SPENDABLE_OUTPUT_INFO_PERSISTENCE_SECONDARY_NAMESPACE,
318							&stored_key,
319							false,
320						)?;
321					} else {
322						debug_assert!(false, "Unexpected status in OutputSweeper migration.");
323						log_error!(logger, "Unexpected status in OutputSweeper migration.");
324						return Err(std::io::Error::new(
325							std::io::ErrorKind::Other,
326							"Failed to migrate OutputSweeper state.",
327						));
328					}
329				},
330				_ => {
331					debug_assert!(false, "Unexpected status in OutputSweeper migration.");
332					log_error!(logger, "Unexpected status in OutputSweeper migration.");
333					return Err(std::io::Error::new(
334						std::io::ErrorKind::Other,
335						"Failed to migrate OutputSweeper state.",
336					));
337				},
338			}
339		} else {
340			debug_assert!(
341				false,
342				"OutputSweeper failed to track and persist outputs during migration."
343			);
344			log_error!(
345				logger,
346				"OutputSweeper failed to track and persist outputs during migration."
347			);
348			return Err(std::io::Error::new(
349				std::io::ErrorKind::Other,
350				"Failed to migrate OutputSweeper state.",
351			));
352		}
353	}
354
355	Ok(())
356}
357
358pub(crate) fn read_node_metrics<L: Deref>(
359	kv_store: Arc<DynStore>, logger: L,
360) -> Result<NodeMetrics, std::io::Error>
361where
362	L::Target: LdkLogger,
363{
364	let mut reader = Cursor::new(kv_store.read(
365		NODE_METRICS_PRIMARY_NAMESPACE,
366		NODE_METRICS_SECONDARY_NAMESPACE,
367		NODE_METRICS_KEY,
368	)?);
369	NodeMetrics::read(&mut reader).map_err(|e| {
370		log_error!(logger, "Failed to deserialize NodeMetrics: {}", e);
371		std::io::Error::new(std::io::ErrorKind::InvalidData, "Failed to deserialize NodeMetrics")
372	})
373}
374
375pub(crate) fn write_node_metrics<L: Deref>(
376	node_metrics: &NodeMetrics, kv_store: Arc<DynStore>, logger: L,
377) -> Result<(), Error>
378where
379	L::Target: LdkLogger,
380{
381	let data = node_metrics.encode();
382	kv_store
383		.write(
384			NODE_METRICS_PRIMARY_NAMESPACE,
385			NODE_METRICS_SECONDARY_NAMESPACE,
386			NODE_METRICS_KEY,
387			&data,
388		)
389		.map_err(|e| {
390			log_error!(
391				logger,
392				"Writing data to key {}/{}/{} failed due to: {}",
393				NODE_METRICS_PRIMARY_NAMESPACE,
394				NODE_METRICS_SECONDARY_NAMESPACE,
395				NODE_METRICS_KEY,
396				e
397			);
398			Error::PersistenceFailed
399		})
400}
401
402pub(crate) fn is_valid_kvstore_str(key: &str) -> bool {
403	key.len() <= KVSTORE_NAMESPACE_KEY_MAX_LEN
404		&& key.chars().all(|c| KVSTORE_NAMESPACE_KEY_ALPHABET.contains(c))
405}
406
407pub(crate) fn check_namespace_key_validity(
408	primary_namespace: &str, secondary_namespace: &str, key: Option<&str>, operation: &str,
409) -> Result<(), std::io::Error> {
410	if let Some(key) = key {
411		if key.is_empty() {
412			debug_assert!(
413				false,
414				"Failed to {} {}/{}/{}: key may not be empty.",
415				operation,
416				PrintableString(primary_namespace),
417				PrintableString(secondary_namespace),
418				PrintableString(key)
419			);
420			let msg = format!(
421				"Failed to {} {}/{}/{}: key may not be empty.",
422				operation,
423				PrintableString(primary_namespace),
424				PrintableString(secondary_namespace),
425				PrintableString(key)
426			);
427			return Err(std::io::Error::new(std::io::ErrorKind::Other, msg));
428		}
429
430		if primary_namespace.is_empty() && !secondary_namespace.is_empty() {
431			debug_assert!(false,
432				"Failed to {} {}/{}/{}: primary namespace may not be empty if a non-empty secondary namespace is given.",
433				operation,
434				PrintableString(primary_namespace), PrintableString(secondary_namespace), PrintableString(key));
435			let msg = format!(
436				"Failed to {} {}/{}/{}: primary namespace may not be empty if a non-empty secondary namespace is given.", operation,
437				PrintableString(primary_namespace), PrintableString(secondary_namespace), PrintableString(key));
438			return Err(std::io::Error::new(std::io::ErrorKind::Other, msg));
439		}
440
441		if !is_valid_kvstore_str(primary_namespace)
442			|| !is_valid_kvstore_str(secondary_namespace)
443			|| !is_valid_kvstore_str(key)
444		{
445			debug_assert!(
446				false,
447				"Failed to {} {}/{}/{}: primary namespace, secondary namespace, and key must be valid.",
448				operation,
449				PrintableString(primary_namespace),
450				PrintableString(secondary_namespace),
451				PrintableString(key)
452			);
453			let msg = format!(
454				"Failed to {} {}/{}/{}: primary namespace, secondary namespace, and key must be valid.",
455				operation,
456				PrintableString(primary_namespace),
457				PrintableString(secondary_namespace),
458				PrintableString(key)
459			);
460			return Err(std::io::Error::new(std::io::ErrorKind::Other, msg));
461		}
462	} else {
463		if primary_namespace.is_empty() && !secondary_namespace.is_empty() {
464			debug_assert!(false,
465				"Failed to {} {}/{}: primary namespace may not be empty if a non-empty secondary namespace is given.",
466				operation, PrintableString(primary_namespace), PrintableString(secondary_namespace));
467			let msg = format!(
468				"Failed to {} {}/{}: primary namespace may not be empty if a non-empty secondary namespace is given.",
469				operation, PrintableString(primary_namespace), PrintableString(secondary_namespace));
470			return Err(std::io::Error::new(std::io::ErrorKind::Other, msg));
471		}
472		if !is_valid_kvstore_str(primary_namespace) || !is_valid_kvstore_str(secondary_namespace) {
473			debug_assert!(
474				false,
475				"Failed to {} {}/{}: primary namespace and secondary namespace must be valid.",
476				operation,
477				PrintableString(primary_namespace),
478				PrintableString(secondary_namespace)
479			);
480			let msg = format!(
481				"Failed to {} {}/{}: primary namespace and secondary namespace must be valid.",
482				operation,
483				PrintableString(primary_namespace),
484				PrintableString(secondary_namespace)
485			);
486			return Err(std::io::Error::new(std::io::ErrorKind::Other, msg));
487		}
488	}
489
490	Ok(())
491}
492
493macro_rules! impl_read_write_change_set_type {
494	( $read_name: ident, $write_name: ident, $change_set_type:ty, $primary_namespace: expr, $secondary_namespace: expr, $key: expr ) => {
495		pub(crate) fn $read_name<L: Deref>(
496			kv_store: Arc<DynStore>, logger: L,
497		) -> Result<Option<$change_set_type>, std::io::Error>
498		where
499			L::Target: LdkLogger,
500		{
501			let bytes = match kv_store.read($primary_namespace, $secondary_namespace, $key) {
502				Ok(bytes) => bytes,
503				Err(e) => {
504					if e.kind() == lightning::io::ErrorKind::NotFound {
505						return Ok(None);
506					} else {
507						log_error!(
508							logger,
509							"Reading data from key {}/{}/{} failed due to: {}",
510							$primary_namespace,
511							$secondary_namespace,
512							$key,
513							e
514						);
515						return Err(e.into());
516					}
517				},
518			};
519
520			let mut reader = Cursor::new(bytes);
521			let res: Result<ChangeSetDeserWrapper<$change_set_type>, DecodeError> =
522				Readable::read(&mut reader);
523			match res {
524				Ok(res) => Ok(Some(res.0)),
525				Err(e) => {
526					log_error!(logger, "Failed to deserialize BDK wallet field: {}", e);
527					Err(std::io::Error::new(
528						std::io::ErrorKind::InvalidData,
529						"Failed to deserialize BDK wallet field",
530					))
531				},
532			}
533		}
534
535		pub(crate) fn $write_name<L: Deref>(
536			value: &$change_set_type, kv_store: Arc<DynStore>, logger: L,
537		) -> Result<(), std::io::Error>
538		where
539			L::Target: LdkLogger,
540		{
541			let data = ChangeSetSerWrapper(value).encode();
542			kv_store.write($primary_namespace, $secondary_namespace, $key, &data).map_err(|e| {
543				log_error!(
544					logger,
545					"Writing data to key {}/{}/{} failed due to: {}",
546					$primary_namespace,
547					$secondary_namespace,
548					$key,
549					e
550				);
551				e.into()
552			})
553		}
554	};
555}
556
557impl_read_write_change_set_type!(
558	read_bdk_wallet_descriptor,
559	write_bdk_wallet_descriptor,
560	Descriptor<DescriptorPublicKey>,
561	BDK_WALLET_DESCRIPTOR_PRIMARY_NAMESPACE,
562	BDK_WALLET_DESCRIPTOR_SECONDARY_NAMESPACE,
563	BDK_WALLET_DESCRIPTOR_KEY
564);
565
566impl_read_write_change_set_type!(
567	read_bdk_wallet_change_descriptor,
568	write_bdk_wallet_change_descriptor,
569	Descriptor<DescriptorPublicKey>,
570	BDK_WALLET_CHANGE_DESCRIPTOR_PRIMARY_NAMESPACE,
571	BDK_WALLET_CHANGE_DESCRIPTOR_SECONDARY_NAMESPACE,
572	BDK_WALLET_CHANGE_DESCRIPTOR_KEY
573);
574
575impl_read_write_change_set_type!(
576	read_bdk_wallet_network,
577	write_bdk_wallet_network,
578	Network,
579	BDK_WALLET_NETWORK_PRIMARY_NAMESPACE,
580	BDK_WALLET_NETWORK_SECONDARY_NAMESPACE,
581	BDK_WALLET_NETWORK_KEY
582);
583
584impl_read_write_change_set_type!(
585	read_bdk_wallet_local_chain,
586	write_bdk_wallet_local_chain,
587	BdkLocalChainChangeSet,
588	BDK_WALLET_LOCAL_CHAIN_PRIMARY_NAMESPACE,
589	BDK_WALLET_LOCAL_CHAIN_SECONDARY_NAMESPACE,
590	BDK_WALLET_LOCAL_CHAIN_KEY
591);
592
593impl_read_write_change_set_type!(
594	read_bdk_wallet_tx_graph,
595	write_bdk_wallet_tx_graph,
596	BdkTxGraphChangeSet<ConfirmationBlockTime>,
597	BDK_WALLET_TX_GRAPH_PRIMARY_NAMESPACE,
598	BDK_WALLET_TX_GRAPH_SECONDARY_NAMESPACE,
599	BDK_WALLET_TX_GRAPH_KEY
600);
601
602impl_read_write_change_set_type!(
603	read_bdk_wallet_indexer,
604	write_bdk_wallet_indexer,
605	BdkIndexerChangeSet,
606	BDK_WALLET_INDEXER_PRIMARY_NAMESPACE,
607	BDK_WALLET_INDEXER_SECONDARY_NAMESPACE,
608	BDK_WALLET_INDEXER_KEY
609);
610
611// Reads the full BdkWalletChangeSet or returns default fields
612pub(crate) fn read_bdk_wallet_change_set(
613	kv_store: Arc<DynStore>, logger: Arc<Logger>,
614) -> Result<Option<BdkWalletChangeSet>, std::io::Error> {
615	let mut change_set = BdkWalletChangeSet::default();
616
617	// We require a descriptor and return `None` to signal creation of a new wallet otherwise.
618	if let Some(descriptor) =
619		read_bdk_wallet_descriptor(Arc::clone(&kv_store), Arc::clone(&logger))?
620	{
621		change_set.descriptor = Some(descriptor);
622	} else {
623		return Ok(None);
624	}
625
626	// We require a change_descriptor and return `None` to signal creation of a new wallet otherwise.
627	if let Some(change_descriptor) =
628		read_bdk_wallet_change_descriptor(Arc::clone(&kv_store), Arc::clone(&logger))?
629	{
630		change_set.change_descriptor = Some(change_descriptor);
631	} else {
632		return Ok(None);
633	}
634
635	// We require a network and return `None` to signal creation of a new wallet otherwise.
636	if let Some(network) = read_bdk_wallet_network(Arc::clone(&kv_store), Arc::clone(&logger))? {
637		change_set.network = Some(network);
638	} else {
639		return Ok(None);
640	}
641
642	read_bdk_wallet_local_chain(Arc::clone(&kv_store), Arc::clone(&logger))?
643		.map(|local_chain| change_set.local_chain = local_chain);
644	read_bdk_wallet_tx_graph(Arc::clone(&kv_store), Arc::clone(&logger))?
645		.map(|tx_graph| change_set.tx_graph = tx_graph);
646	read_bdk_wallet_indexer(Arc::clone(&kv_store), Arc::clone(&logger))?
647		.map(|indexer| change_set.indexer = indexer);
648	Ok(Some(change_set))
649}
650
651#[cfg(test)]
652mod tests {
653	use super::*;
654
655	#[test]
656	fn mnemonic_to_entropy_to_mnemonic() {
657		let mnemonic = generate_entropy_mnemonic();
658
659		let entropy = mnemonic.to_entropy();
660		assert_eq!(mnemonic, Mnemonic::from_entropy(&entropy).unwrap());
661	}
662}