From: nymius <155548262+nymius@users.noreply.github.com> Date: Wed, 27 Nov 2024 01:05:08 +0000 (-0300) Subject: refactor(chain)!: impl sqlite for ConfirmationBlockTime anchored changesets X-Git-Tag: v1.0.0-beta.6~3^2~8 X-Git-Url: http://internal-gitweb-vhost/script/%22https:/struct.EncoderStringWriter.html?a=commitdiff_plain;h=b587b0fcadcc61b9f46336ffee5621363e409092;p=bdk 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. --- 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, })?; }