From b587b0fcadcc61b9f46336ffee5621363e409092 Mon Sep 17 00:00:00 2001 From: nymius <155548262+nymius@users.noreply.github.com> Date: Tue, 26 Nov 2024 22:05:08 -0300 Subject: [PATCH] refactor(chain)!: impl sqlite for ConfirmationBlockTime anchored changesets We want to not depend on serde_json. If we keep it around for serializing anchors we won't be able to remove it in the future because it will always be needed to do migrations. Currently there is only one widely used anchor, ConfirmationBlockTime. The desicion was to constrain support to just be for a single anchor type ConfirmationBlockTime. The anchor table will represent all fields of ConfirmationBlockTime, each one in its own column. The reasons: - No one is using rusqlite with any other anchor type, and if they are, they can do something custom anyway. - The anchor representation may change in the future, supporting for multiple Anchor types here will cause more problems for migration later on. --- crates/chain/src/rusqlite_impl.rs | 41 ++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/crates/chain/src/rusqlite_impl.rs b/crates/chain/src/rusqlite_impl.rs index cf3d6bc9..6b722827 100644 --- a/crates/chain/src/rusqlite_impl.rs +++ b/crates/chain/src/rusqlite_impl.rs @@ -211,10 +211,7 @@ fn to_sql_error(err: E) -> rusqlit rusqlite::Error::ToSqlConversionFailure(Box::new(err)) } -impl tx_graph::ChangeSet -where - A: Anchor + Clone + Ord + serde::Serialize + serde::de::DeserializeOwned, -{ +impl tx_graph::ChangeSet { /// Schema name for [`tx_graph::ChangeSet`]. pub const SCHEMA_NAME: &'static str = "bdk_txgraph"; /// Name of table that stores full transactions and `last_seen` timestamps. @@ -260,7 +257,21 @@ where Self::TXS_TABLE_NAME, ), ]; - migrate_schema(db_tx, Self::SCHEMA_NAME, &[schema_v0]) + let schema_v1: &[&str] = &[ + &format!( + "ALTER TABLE {} ADD COLUMN confirmation_time INTEGER DEFAULT -1 NOT NULL", + Self::ANCHORS_TABLE_NAME, + ), + &format!( + "UPDATE {} SET confirmation_time = json_extract(anchor, '$.confirmation_time')", + Self::ANCHORS_TABLE_NAME, + ), + &format!( + "ALTER TABLE {} DROP COLUMN anchor", + Self::ANCHORS_TABLE_NAME, + ), + ]; + migrate_schema(db_tx, Self::SCHEMA_NAME, &[schema_v0, schema_v1]) } /// Construct a [`TxGraph`] from an sqlite database. @@ -314,18 +325,26 @@ where } let mut statement = db_tx.prepare(&format!( - "SELECT json(anchor), txid FROM {}", + "SELECT block_hash, block_height, confirmation_time, txid FROM {}", Self::ANCHORS_TABLE_NAME, ))?; let row_iter = statement.query_map([], |row| { Ok(( - row.get::<_, AnchorImpl>("json(anchor)")?, + row.get::<_, Impl>("block_hash")?, + row.get::<_, u32>("block_height")?, + row.get::<_, u64>("confirmation_time")?, row.get::<_, Impl>("txid")?, )) })?; for row in row_iter { - let (AnchorImpl(anchor), Impl(txid)) = row?; - changeset.anchors.insert((anchor, txid)); + let (hash, height, confirmation_time, Impl(txid)) = row?; + changeset.anchors.insert(( + ConfirmationBlockTime { + block_id: BlockId::from((&height, &hash.0)), + confirmation_time, + }, + txid, + )); } Ok(changeset) @@ -373,7 +392,7 @@ where } let mut statement = db_tx.prepare_cached(&format!( - "REPLACE INTO {}(txid, block_height, block_hash, anchor) VALUES(:txid, :block_height, :block_hash, jsonb(:anchor))", + "REPLACE INTO {}(txid, block_height, block_hash, confirmation_time) VALUES(:txid, :block_height, :block_hash, :confirmation_time)", Self::ANCHORS_TABLE_NAME, ))?; let mut statement_txid = db_tx.prepare_cached(&format!( @@ -389,7 +408,7 @@ where ":txid": Impl(*txid), ":block_height": anchor_block.height, ":block_hash": Impl(anchor_block.hash), - ":anchor": AnchorImpl(anchor.clone()), + ":confirmation_time": anchor.confirmation_time, })?; } -- 2.49.0