sqlite: get and set last poll timestamp

This commit is contained in:
Michael Mallan 2024-10-10 14:32:50 +01:00
parent 8fb74d1cf9
commit a2b79f1b07
No known key found for this signature in database
GPG Key ID: 5177CDCEDB0EABEB
3 changed files with 51 additions and 7 deletions

View File

@ -43,7 +43,7 @@ use miniscript::bitcoin::{
secp256k1,
};
const DB_VERSION: i64 = 5;
const DB_VERSION: i64 = 6;
/// Last database version for which Bitcoin transactions were not stored in database. In practice
/// this meant we relied on the bitcoind watchonly wallet to store them for us.
@ -371,6 +371,20 @@ impl SqliteConn {
.expect("Database must be available");
}
// Sqlite supports i64 integers so we use u32 for the timestamp.
/// Set the last poll timestamp, where `timestamp` is seconds since UNIX epoch.
pub fn set_wallet_last_poll_timestamp(&mut self, timestamp: u32) -> Result<(), SqliteDbError> {
db_exec(&mut self.conn, |db_tx| {
db_tx
.execute(
"UPDATE wallets SET last_poll_timestamp = (?1) WHERE id = (?2)",
rusqlite::params![timestamp, WALLET_ID],
)
.map(|_| ())
})
.map_err(SqliteDbError::Rusqlite)
}
/// Get all the coins from DB, optionally filtered by coin status and/or outpoint.
pub fn coins(
&mut self,
@ -2384,7 +2398,7 @@ CREATE TABLE labels (
}
#[test]
fn v0_to_v5_migration() {
fn v0_to_v6_migration() {
let secp = secp256k1::Secp256k1::verification_only();
// Create a database with version 0, using the old schema.
@ -2490,7 +2504,7 @@ CREATE TABLE labels (
{
let mut conn = db.connection().unwrap();
let version = conn.db_version();
assert_eq!(version, 5);
assert_eq!(version, 6);
}
// We should now be able to insert another PSBT, to query both, and the first PSBT must
// have no associated timestamp.
@ -2552,11 +2566,19 @@ CREATE TABLE labels (
assert_eq!(db_labels[0].value, "hello");
}
// In v6, we can get and set the last poll timestamp.
{
let mut conn = db.connection().unwrap();
assert!(conn.db_wallet().last_poll_timestamp.is_none());
conn.set_wallet_last_poll_timestamp(1234567).unwrap();
assert_eq!(conn.db_wallet().last_poll_timestamp, Some(1234567));
}
fs::remove_dir_all(tmp_dir).unwrap();
}
#[test]
fn v3_to_v5_migration() {
fn v3_to_v6_migration() {
let secp = secp256k1::Secp256k1::verification_only();
// Create a database with version 3, using the old schema.
@ -2718,10 +2740,10 @@ CREATE TABLE labels (
// Migrate the DB.
maybe_apply_migration(&db_path, &bitcoin_txs).unwrap();
assert_eq!(conn.db_version(), 5);
assert_eq!(conn.db_version(), 6);
// Migrating twice will be a no-op. No need to pass `bitcoin_txs` second time.
maybe_apply_migration(&db_path, &[]).unwrap();
assert!(conn.db_version() == 5);
assert!(conn.db_version() == 6);
let coins_post = conn.coins(&[], &[]);
assert_eq!(coins_pre, coins_post);
}

View File

@ -30,7 +30,8 @@ CREATE TABLE wallets (
main_descriptor TEXT NOT NULL,
deposit_derivation_index INTEGER NOT NULL,
change_derivation_index INTEGER NOT NULL,
rescan_timestamp INTEGER
rescan_timestamp INTEGER,
last_poll_timestamp INTEGER
);
/* Our (U)TxOs.
@ -140,6 +141,7 @@ pub struct DbWallet {
pub deposit_derivation_index: bip32::ChildNumber,
pub change_derivation_index: bip32::ChildNumber,
pub rescan_timestamp: Option<u32>,
pub last_poll_timestamp: Option<u32>,
}
impl TryFrom<&rusqlite::Row<'_>> for DbWallet {
@ -159,6 +161,7 @@ impl TryFrom<&rusqlite::Row<'_>> for DbWallet {
let change_derivation_index = bip32::ChildNumber::from(der_idx);
let rescan_timestamp = row.get(5)?;
let last_poll_timestamp = row.get(6)?;
Ok(DbWallet {
id,
@ -167,6 +170,7 @@ impl TryFrom<&rusqlite::Row<'_>> for DbWallet {
deposit_derivation_index,
change_derivation_index,
rescan_timestamp,
last_poll_timestamp,
})
}
}

View File

@ -294,6 +294,19 @@ fn migrate_v4_to_v5(
Ok(())
}
fn migrate_v5_to_v6(conn: &mut rusqlite::Connection) -> Result<(), SqliteDbError> {
db_exec(conn, |tx| {
tx.execute(
"ALTER TABLE wallets ADD COLUMN last_poll_timestamp INTEGER",
rusqlite::params![],
)?;
tx.execute("UPDATE version SET version = 6", rusqlite::params![])?;
Ok(())
})?;
Ok(())
}
/// Check the database version and if necessary apply the migrations to upgrade it to the current
/// one. The `bitcoin_txs` parameter is here for the migration from versions 4 and earlier, which
/// did not store the Bitcoin transactions in database, to versions 5 and later, which do. For a
@ -342,6 +355,11 @@ pub fn maybe_apply_migration(
migrate_v4_to_v5(&mut conn, bitcoin_txs)?;
log::warn!("Migration from database version 4 to version 5 successful.");
}
5 => {
log::warn!("Upgrading database from version 5 to version 6.");
migrate_v5_to_v6(&mut conn)?;
log::warn!("Migration from database version 5 to version 6 successful.");
}
_ => return Err(SqliteDbError::UnsupportedVersion(version)),
}
}