Skip to content

Commit 7cdc985

Browse files
committed
Merge #198: docs(wallet): provide guidance on use of ChangeSet
43b6725 docs(wallet): provide guidance on use of `ChangeSet` (valued mammal) Pull request description: This work in progress PR is meant to expand on and clarify the documentation for `bdk_wallet::ChangeSet`. fixes #9 ### Changelog notice TBD ### Checklists #### All Submissions: * [x] I've signed all my commits * [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md) * [x] I ran `cargo fmt` and `cargo clippy` before committing ACKs for top commit: notmandatory: ACK 43b6725 Tree-SHA512: fb43884c5cc3a52755d9df916e3e0bc8097bd77924c550e7ff333d468ca2fcfa8ab4563e405531f64a17d39a2f67608ef0b5479f0214b34e6e6dc42f00fcdffc
2 parents 48f6f7a + 43b6725 commit 7cdc985

File tree

2 files changed

+96
-3
lines changed

2 files changed

+96
-3
lines changed

wallet/src/wallet/changeset.rs

+95-2
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,105 @@ use bdk_chain::{
22
indexed_tx_graph, keychain_txout, local_chain, tx_graph, ConfirmationBlockTime, Merge,
33
};
44
use miniscript::{Descriptor, DescriptorPublicKey};
5+
use serde::{Deserialize, Serialize};
56

67
type IndexedTxGraphChangeSet =
78
indexed_tx_graph::ChangeSet<ConfirmationBlockTime, keychain_txout::ChangeSet>;
89

9-
/// A changeset for [`Wallet`](crate::Wallet).
10-
#[derive(Default, Debug, Clone, PartialEq, serde::Deserialize, serde::Serialize)]
10+
/// A change set for [`Wallet`]
11+
///
12+
/// ## Definition
13+
///
14+
/// The change set is responsible for transmiting data between the persistent storage layer and the
15+
/// core library components. Specifically, it serves two primary functions:
16+
///
17+
/// 1) Recording incremental changes to the in-memory representation that need to be persisted
18+
/// to disk
19+
/// 2) Applying aggregate changes from the persistence layer to the in-memory representation at
20+
/// startup
21+
///
22+
/// ## Contract
23+
///
24+
/// The change set maintains and enforces the following properties:
25+
///
26+
/// * Change sets must implement [`Serialize`] and [`Deserialize`] to meet the definition from
27+
/// above.
28+
/// * Change sets must implement [`Default`] as a way of instantiating new empty objects.
29+
/// * Change sets must implement [`Merge`] so that many instances can be aggregated into a single
30+
/// instance.
31+
/// * A change set is composed of a number of individual "sub-change sets" that adhere to the same
32+
/// rules as above. This is for increased modularity and portability. For example the core
33+
/// modules each have their own change set (`tx_graph`, `local_chain`, etc).
34+
///
35+
/// ## Members and required fields
36+
///
37+
/// The change set has certain required fields without which a `Wallet` cannot function.
38+
/// These include the [`descriptor`] and the [`network`] in use. These are required to be non-empty
39+
/// *in the aggregate*, meaning the field must be present and non-null in the union of all
40+
/// persisted changes, but may be empty in any one change set, where "empty" is defined by the
41+
/// [`Merge`](Merge::is_empty) implementation of that change set. This requirement also applies to
42+
/// the [`local_chain`] field in that the aggregate change set must include a genesis block.
43+
///
44+
/// For example, the descriptor and network are present in the first change set after wallet
45+
/// creation, but are usually omitted in subsequent updates, as they are not permitted to change
46+
/// at any point thereafter.
47+
///
48+
/// Other fields of the change set are not required to be non-empty, that is they may be empty even
49+
/// in the aggregate. However in practice they should contain the data needed to recover a wallet
50+
/// state between sessions. These include:
51+
/// * [`tx_graph`](Self::tx_graph)
52+
/// * [`indexer`](Self::indexer)
53+
///
54+
/// The [`change_descriptor`] is special in that its presence is optional, however the value of the
55+
/// change descriptor should be defined at wallet creation time and respected for the life of the
56+
/// wallet, meaning that if a change descriptor is originally defined, it must also be present in
57+
/// the aggregate change set.
58+
///
59+
/// ## Staging
60+
///
61+
/// For greater efficiency the [`Wallet`] is able to *stage* the to-be-persisted changes. Many
62+
/// operations result in staged changes which require persistence on the part of the user. These
63+
/// include address revelation, applying an [`Update`], and introducing transactions and chain
64+
/// data to the wallet. To get the staged changes see [`Wallet::staged`] and similar methods. Once
65+
/// the changes are committed to the persistence layer the contents of the stage should be
66+
/// discarded.
67+
///
68+
/// Users should persist early and often generally speaking, however in principle there is no
69+
/// limit to the number or type of changes that can be staged prior to persisting or the order in
70+
/// which they're staged. This is because change sets are designed to be [merged]. The change
71+
/// that is ultimately persisted will encompass the combined effect of each change individually.
72+
///
73+
/// ## Extensibility
74+
///
75+
/// Existing fields may be extended in the future with additional sub-fields. New top-level fields
76+
/// are likely to be added as new features and core components are implemented. Existing fields may
77+
/// be removed in future versions of the library.
78+
///
79+
/// The authors reserve the right to make breaking changes to the [`ChangeSet`] structure in
80+
/// a major version release. API changes affecting the types of data persisted will display
81+
/// prominently in the release notes. Users are advised to look for such changes and update their
82+
/// application accordingly.
83+
///
84+
/// The resulting interface is designed to give the user more control of what to persist and when
85+
/// to persist it. Custom implementations should consider and account for the possibility of
86+
/// partial or repeat writes, the atomicity of persistence operations, and the order of reads and
87+
/// writes among the fields of the change set. BDK comes with support for [SQLite] that handles
88+
/// the details for you and is recommended for many users. If implementing your own persistence,
89+
/// please refer to the documentation for [`WalletPersister`] and [`PersistedWallet`] for more
90+
/// information.
91+
///
92+
/// [`change_descriptor`]: Self::change_descriptor
93+
/// [`descriptor`]: Self::descriptor
94+
/// [`local_chain`]: Self::local_chain
95+
/// [merged]: bdk_chain::Merge
96+
/// [`network`]: Self::network
97+
/// [`PersistedWallet`]: crate::PersistedWallet
98+
/// [SQLite]: bdk_chain::rusqlite_impl
99+
/// [`Update`]: crate::Update
100+
/// [`WalletPersister`]: crate::WalletPersister
101+
/// [`Wallet::staged`]: crate::Wallet::staged
102+
/// [`Wallet`]: crate::Wallet
103+
#[derive(Default, Debug, Clone, PartialEq, Deserialize, Serialize)]
11104
pub struct ChangeSet {
12105
/// Descriptor for recipient addresses.
13106
pub descriptor: Option<Descriptor<DescriptorPublicKey>>,

wallet/src/wallet/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ impl Wallet {
478478

479479
/// Load [`Wallet`] from the given previously persisted [`ChangeSet`] and `params`.
480480
///
481-
/// Refer to [`Wallet::load`] for more.
481+
/// Returns `Ok(None)` if the changeset is empty. Refer to [`Wallet::load`] for more.
482482
pub fn load_with_params(
483483
changeset: ChangeSet,
484484
params: LoadParams,

0 commit comments

Comments
 (0)