From 06a9d6c722dd3e324d81ea5b9c2b65ab9f171a34 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E5=BF=97=E5=AE=87?= Date: Sun, 11 Aug 2024 08:50:54 +0000 Subject: [PATCH] feat(chain,wallet)!: publicize `.init_sqlite_tables` changeset methods Changeset methods `.persist_to_sqlite` and `from_sqlite` no longer internally call `.init_sqlite_tables`. Instead, it is up to the caller to call `.init_sqlite_tables` beforehand. This allows us to utilize `WalletPersister::initialize`, instead of calling `.init_sqlite_tables` every time we persist/load. --- crates/chain/src/rusqlite_impl.rs | 30 +++++++++++++-------------- crates/wallet/src/wallet/changeset.rs | 16 +++++++------- crates/wallet/src/wallet/persisted.rs | 6 +++++- crates/wallet/tests/wallet.rs | 6 +++++- 4 files changed, 34 insertions(+), 24 deletions(-) diff --git a/crates/chain/src/rusqlite_impl.rs b/crates/chain/src/rusqlite_impl.rs index a52c491c..d8ef65c4 100644 --- a/crates/chain/src/rusqlite_impl.rs +++ b/crates/chain/src/rusqlite_impl.rs @@ -225,7 +225,7 @@ where pub const ANCHORS_TABLE_NAME: &'static str = "bdk_anchors"; /// Initialize sqlite tables. - fn init_sqlite_tables(db_tx: &rusqlite::Transaction) -> rusqlite::Result<()> { + pub fn init_sqlite_tables(db_tx: &rusqlite::Transaction) -> rusqlite::Result<()> { let schema_v0: &[&str] = &[ // full transactions &format!( @@ -264,9 +264,9 @@ where } /// Construct a [`TxGraph`] from an sqlite database. + /// + /// Remember to call [`Self::init_sqlite_tables`] beforehand. pub fn from_sqlite(db_tx: &rusqlite::Transaction) -> rusqlite::Result { - Self::init_sqlite_tables(db_tx)?; - let mut changeset = Self::default(); let mut statement = db_tx.prepare(&format!( @@ -332,9 +332,9 @@ where } /// Persist `changeset` to the sqlite database. + /// + /// Remember to call [`Self::init_sqlite_tables`] beforehand. pub fn persist_to_sqlite(&self, db_tx: &rusqlite::Transaction) -> rusqlite::Result<()> { - Self::init_sqlite_tables(db_tx)?; - let mut statement = db_tx.prepare_cached(&format!( "INSERT INTO {}(txid, raw_tx) VALUES(:txid, :raw_tx) ON CONFLICT(txid) DO UPDATE SET raw_tx=:raw_tx", Self::TXS_TABLE_NAME, @@ -396,7 +396,7 @@ impl local_chain::ChangeSet { pub const BLOCKS_TABLE_NAME: &'static str = "bdk_blocks"; /// Initialize sqlite tables for persisting [`local_chain::LocalChain`]. - fn init_sqlite_tables(db_tx: &rusqlite::Transaction) -> rusqlite::Result<()> { + pub fn init_sqlite_tables(db_tx: &rusqlite::Transaction) -> rusqlite::Result<()> { let schema_v0: &[&str] = &[ // blocks &format!( @@ -411,9 +411,9 @@ impl local_chain::ChangeSet { } /// Construct a [`LocalChain`](local_chain::LocalChain) from sqlite database. + /// + /// Remember to call [`Self::init_sqlite_tables`] beforehand. pub fn from_sqlite(db_tx: &rusqlite::Transaction) -> rusqlite::Result { - Self::init_sqlite_tables(db_tx)?; - let mut changeset = Self::default(); let mut statement = db_tx.prepare(&format!( @@ -435,9 +435,9 @@ impl local_chain::ChangeSet { } /// Persist `changeset` to the sqlite database. + /// + /// Remember to call [`Self::init_sqlite_tables`] beforehand. pub fn persist_to_sqlite(&self, db_tx: &rusqlite::Transaction) -> rusqlite::Result<()> { - Self::init_sqlite_tables(db_tx)?; - let mut replace_statement = db_tx.prepare_cached(&format!( "REPLACE INTO {}(block_height, block_hash) VALUES(:block_height, :block_hash)", Self::BLOCKS_TABLE_NAME, @@ -471,7 +471,7 @@ impl keychain_txout::ChangeSet { /// Initialize sqlite tables for persisting /// [`KeychainTxOutIndex`](keychain_txout::KeychainTxOutIndex). - fn init_sqlite_tables(db_tx: &rusqlite::Transaction) -> rusqlite::Result<()> { + pub fn init_sqlite_tables(db_tx: &rusqlite::Transaction) -> rusqlite::Result<()> { let schema_v0: &[&str] = &[ // last revealed &format!( @@ -487,9 +487,9 @@ impl keychain_txout::ChangeSet { /// Construct [`KeychainTxOutIndex`](keychain_txout::KeychainTxOutIndex) from sqlite database /// and given parameters. + /// + /// Remember to call [`Self::init_sqlite_tables`] beforehand. pub fn from_sqlite(db_tx: &rusqlite::Transaction) -> rusqlite::Result { - Self::init_sqlite_tables(db_tx)?; - let mut changeset = Self::default(); let mut statement = db_tx.prepare(&format!( @@ -511,9 +511,9 @@ impl keychain_txout::ChangeSet { } /// Persist `changeset` to the sqlite database. + /// + /// Remember to call [`Self::init_sqlite_tables`] beforehand. pub fn persist_to_sqlite(&self, db_tx: &rusqlite::Transaction) -> rusqlite::Result<()> { - Self::init_sqlite_tables(db_tx)?; - let mut statement = db_tx.prepare_cached(&format!( "REPLACE INTO {}(descriptor_id, last_revealed) VALUES(:descriptor_id, :last_revealed)", Self::LAST_REVEALED_TABLE_NAME, diff --git a/crates/wallet/src/wallet/changeset.rs b/crates/wallet/src/wallet/changeset.rs index 5f3b9b3d..2d4b700e 100644 --- a/crates/wallet/src/wallet/changeset.rs +++ b/crates/wallet/src/wallet/changeset.rs @@ -72,10 +72,8 @@ impl ChangeSet { /// Name of table to store wallet descriptors and network. pub const WALLET_TABLE_NAME: &'static str = "bdk_wallet"; - /// Initialize sqlite tables for wallet schema & table. - fn init_wallet_sqlite_tables( - db_tx: &chain::rusqlite::Transaction, - ) -> chain::rusqlite::Result<()> { + /// Initialize sqlite tables for wallet tables. + pub fn init_sqlite_tables(db_tx: &chain::rusqlite::Transaction) -> chain::rusqlite::Result<()> { let schema_v0: &[&str] = &[&format!( "CREATE TABLE {} ( \ id INTEGER PRIMARY KEY NOT NULL CHECK (id = 0), \ @@ -85,12 +83,17 @@ impl ChangeSet { ) STRICT;", Self::WALLET_TABLE_NAME, )]; - crate::rusqlite_impl::migrate_schema(db_tx, Self::WALLET_SCHEMA_NAME, &[schema_v0]) + crate::rusqlite_impl::migrate_schema(db_tx, Self::WALLET_SCHEMA_NAME, &[schema_v0])?; + + bdk_chain::local_chain::ChangeSet::init_sqlite_tables(db_tx)?; + bdk_chain::tx_graph::ChangeSet::::init_sqlite_tables(db_tx)?; + bdk_chain::keychain_txout::ChangeSet::init_sqlite_tables(db_tx)?; + + Ok(()) } /// Recover a [`ChangeSet`] from sqlite database. pub fn from_sqlite(db_tx: &chain::rusqlite::Transaction) -> chain::rusqlite::Result { - Self::init_wallet_sqlite_tables(db_tx)?; use chain::rusqlite::OptionalExtension; use chain::Impl; @@ -129,7 +132,6 @@ impl ChangeSet { &self, db_tx: &chain::rusqlite::Transaction, ) -> chain::rusqlite::Result<()> { - Self::init_wallet_sqlite_tables(db_tx)?; use chain::rusqlite::named_params; use chain::Impl; diff --git a/crates/wallet/src/wallet/persisted.rs b/crates/wallet/src/wallet/persisted.rs index a7181a3c..bef34a1f 100644 --- a/crates/wallet/src/wallet/persisted.rs +++ b/crates/wallet/src/wallet/persisted.rs @@ -237,6 +237,7 @@ impl<'c> WalletPersister for bdk_chain::rusqlite::Transaction<'c> { type Error = bdk_chain::rusqlite::Error; fn initialize(persister: &mut Self) -> Result { + ChangeSet::init_sqlite_tables(&*persister)?; ChangeSet::from_sqlite(persister) } @@ -251,6 +252,7 @@ impl WalletPersister for bdk_chain::rusqlite::Connection { fn initialize(persister: &mut Self) -> Result { let db_tx = persister.transaction()?; + ChangeSet::init_sqlite_tables(&db_tx)?; let changeset = ChangeSet::from_sqlite(&db_tx)?; db_tx.commit()?; Ok(changeset) @@ -299,7 +301,9 @@ impl WalletPersister for bdk_file_store::Store { } fn persist(persister: &mut Self, changeset: &ChangeSet) -> Result<(), Self::Error> { - persister.append_changeset(changeset).map_err(FileStoreError::Write) + persister + .append_changeset(changeset) + .map_err(FileStoreError::Write) } } diff --git a/crates/wallet/tests/wallet.rs b/crates/wallet/tests/wallet.rs index 32b7a0f7..53edd821 100644 --- a/crates/wallet/tests/wallet.rs +++ b/crates/wallet/tests/wallet.rs @@ -249,7 +249,11 @@ fn wallet_load_checks() -> anyhow::Result<()> { run( "store.db", - |path| Ok(bdk_file_store::Store::::create_new(DB_MAGIC, path)?), + |path| { + Ok(bdk_file_store::Store::::create_new( + DB_MAGIC, path, + )?) + }, |path| Ok(bdk_file_store::Store::::open(DB_MAGIC, path)?), )?; run( -- 2.49.0