feat(chain,wallet)!: Change persist-traits to be "safer"
Previously, `Persist{Async}With::persist` can be directly called as a
method on the type (i.e. `Wallet`). However, the `db: Db` (which is an
input) may not be initialized. We want a design which makes it harder
for the caller to make this mistake.
We change `Persist{Async}With::persist` to be an "associated function"
which takes two inputs: `db: &mut Db` and `changeset`. However, the
implementer cannot take directly from `Self` (as it's no longer an
input). So we introduce a new trait `Staged` which defines the staged
changeset type and a method that gives us a `&mut` of the staged
changes.
This commit is contained in:
@@ -42,6 +42,7 @@ use bitcoin::{
|
||||
use bitcoin::{consensus::encode::serialize, transaction, BlockHash, Psbt};
|
||||
use bitcoin::{constants::genesis_block, Amount};
|
||||
use bitcoin::{secp256k1::Secp256k1, Weight};
|
||||
use chain::Staged;
|
||||
use core::fmt;
|
||||
use core::mem;
|
||||
use core::ops::Deref;
|
||||
@@ -119,6 +120,14 @@ pub struct Wallet {
|
||||
secp: SecpCtx,
|
||||
}
|
||||
|
||||
impl Staged for Wallet {
|
||||
type ChangeSet = ChangeSet;
|
||||
|
||||
fn staged(&mut self) -> &mut Self::ChangeSet {
|
||||
&mut self.stage
|
||||
}
|
||||
}
|
||||
|
||||
/// An update to [`Wallet`].
|
||||
///
|
||||
/// It updates [`KeychainTxOutIndex`], [`bdk_chain::TxGraph`] and [`local_chain::LocalChain`] atomically.
|
||||
|
||||
@@ -41,14 +41,10 @@ impl<'c> chain::PersistWith<bdk_chain::sqlite::Transaction<'c>> for Wallet {
|
||||
}
|
||||
|
||||
fn persist(
|
||||
&mut self,
|
||||
conn: &mut bdk_chain::sqlite::Transaction,
|
||||
) -> Result<bool, Self::PersistError> {
|
||||
if let Some(changeset) = self.take_staged() {
|
||||
changeset.persist_to_sqlite(conn)?;
|
||||
return Ok(true);
|
||||
}
|
||||
Ok(false)
|
||||
db: &mut bdk_chain::sqlite::Transaction<'c>,
|
||||
changeset: &<Self as chain::Staged>::ChangeSet,
|
||||
) -> Result<(), Self::PersistError> {
|
||||
changeset.persist_to_sqlite(db)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,13 +78,12 @@ impl chain::PersistWith<bdk_chain::sqlite::Connection> for Wallet {
|
||||
}
|
||||
|
||||
fn persist(
|
||||
&mut self,
|
||||
db: &mut bdk_chain::sqlite::Connection,
|
||||
) -> Result<bool, Self::PersistError> {
|
||||
let mut db_tx = db.transaction()?;
|
||||
let has_changes = chain::PersistWith::persist(self, &mut db_tx)?;
|
||||
db_tx.commit()?;
|
||||
Ok(has_changes)
|
||||
changeset: &<Self as chain::Staged>::ChangeSet,
|
||||
) -> Result<(), Self::PersistError> {
|
||||
let db_tx = db.transaction()?;
|
||||
changeset.persist_to_sqlite(&db_tx)?;
|
||||
db_tx.commit()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,14 +121,10 @@ impl chain::PersistWith<bdk_file_store::Store<crate::ChangeSet>> for Wallet {
|
||||
}
|
||||
|
||||
fn persist(
|
||||
&mut self,
|
||||
db: &mut bdk_file_store::Store<crate::ChangeSet>,
|
||||
) -> Result<bool, Self::PersistError> {
|
||||
if let Some(changeset) = self.take_staged() {
|
||||
db.append_changeset(&changeset)?;
|
||||
return Ok(true);
|
||||
}
|
||||
Ok(false)
|
||||
changeset: &<Self as chain::Staged>::ChangeSet,
|
||||
) -> Result<(), Self::PersistError> {
|
||||
db.append_changeset(changeset)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user