[db] Add the last_sync_time
database entry
This will be used to store the height and timestamp after every sync.
This commit is contained in:
parent
aa075f0b2f
commit
2892edf94b
@ -144,6 +144,9 @@ impl BatchOperations for AnyDatabase {
|
|||||||
fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error> {
|
fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error> {
|
||||||
impl_inner_method!(AnyDatabase, self, set_last_index, keychain, value)
|
impl_inner_method!(AnyDatabase, self, set_last_index, keychain, value)
|
||||||
}
|
}
|
||||||
|
fn set_last_sync_time(&mut self, last_sync_time: ConfirmationTime) -> Result<(), Error> {
|
||||||
|
impl_inner_method!(AnyDatabase, self, set_last_sync_time, last_sync_time)
|
||||||
|
}
|
||||||
|
|
||||||
fn del_script_pubkey_from_path(
|
fn del_script_pubkey_from_path(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -180,6 +183,9 @@ impl BatchOperations for AnyDatabase {
|
|||||||
fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
|
fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
|
||||||
impl_inner_method!(AnyDatabase, self, del_last_index, keychain)
|
impl_inner_method!(AnyDatabase, self, del_last_index, keychain)
|
||||||
}
|
}
|
||||||
|
fn del_last_sync_time(&mut self) -> Result<Option<ConfirmationTime>, Error> {
|
||||||
|
impl_inner_method!(AnyDatabase, self, del_last_sync_time)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Database for AnyDatabase {
|
impl Database for AnyDatabase {
|
||||||
@ -241,6 +247,9 @@ impl Database for AnyDatabase {
|
|||||||
fn get_last_index(&self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
|
fn get_last_index(&self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
|
||||||
impl_inner_method!(AnyDatabase, self, get_last_index, keychain)
|
impl_inner_method!(AnyDatabase, self, get_last_index, keychain)
|
||||||
}
|
}
|
||||||
|
fn get_last_sync_time(&self) -> Result<Option<ConfirmationTime>, Error> {
|
||||||
|
impl_inner_method!(AnyDatabase, self, get_last_sync_time)
|
||||||
|
}
|
||||||
|
|
||||||
fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error> {
|
fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error> {
|
||||||
impl_inner_method!(AnyDatabase, self, increment_last_index, keychain)
|
impl_inner_method!(AnyDatabase, self, increment_last_index, keychain)
|
||||||
@ -272,6 +281,9 @@ impl BatchOperations for AnyBatch {
|
|||||||
fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error> {
|
fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error> {
|
||||||
impl_inner_method!(AnyBatch, self, set_last_index, keychain, value)
|
impl_inner_method!(AnyBatch, self, set_last_index, keychain, value)
|
||||||
}
|
}
|
||||||
|
fn set_last_sync_time(&mut self, last_sync_time: ConfirmationTime) -> Result<(), Error> {
|
||||||
|
impl_inner_method!(AnyBatch, self, set_last_sync_time, last_sync_time)
|
||||||
|
}
|
||||||
|
|
||||||
fn del_script_pubkey_from_path(
|
fn del_script_pubkey_from_path(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -302,6 +314,9 @@ impl BatchOperations for AnyBatch {
|
|||||||
fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
|
fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
|
||||||
impl_inner_method!(AnyBatch, self, del_last_index, keychain)
|
impl_inner_method!(AnyBatch, self, del_last_index, keychain)
|
||||||
}
|
}
|
||||||
|
fn del_last_sync_time(&mut self) -> Result<Option<ConfirmationTime>, Error> {
|
||||||
|
impl_inner_method!(AnyBatch, self, del_last_sync_time)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BatchDatabase for AnyDatabase {
|
impl BatchDatabase for AnyDatabase {
|
||||||
|
@ -82,6 +82,13 @@ macro_rules! impl_batch_operations {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_last_sync_time(&mut self, ct: ConfirmationTime) -> Result<(), Error> {
|
||||||
|
let key = MapKey::LastSyncTime.as_map_key();
|
||||||
|
self.insert(key, serde_json::to_vec(&ct)?)$($after_insert)*;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn del_script_pubkey_from_path(&mut self, keychain: KeychainKind, path: u32) -> Result<Option<Script>, Error> {
|
fn del_script_pubkey_from_path(&mut self, keychain: KeychainKind, path: u32) -> Result<Option<Script>, Error> {
|
||||||
let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
|
let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
|
||||||
let res = self.remove(key);
|
let res = self.remove(key);
|
||||||
@ -168,6 +175,14 @@ macro_rules! impl_batch_operations {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn del_last_sync_time(&mut self) -> Result<Option<ConfirmationTime>, Error> {
|
||||||
|
let key = MapKey::LastSyncTime.as_map_key();
|
||||||
|
let res = self.remove(key);
|
||||||
|
let res = $process_delete!(res);
|
||||||
|
|
||||||
|
Ok(res.map(|b| serde_json::from_slice(&b)).transpose()?)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,6 +357,14 @@ impl Database for Tree {
|
|||||||
.transpose()
|
.transpose()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_last_sync_time(&self) -> Result<Option<ConfirmationTime>, Error> {
|
||||||
|
let key = MapKey::LastSyncTime.as_map_key();
|
||||||
|
Ok(self
|
||||||
|
.get(key)?
|
||||||
|
.map(|b| serde_json::from_slice(&b))
|
||||||
|
.transpose()?)
|
||||||
|
}
|
||||||
|
|
||||||
// inserts 0 if not present
|
// inserts 0 if not present
|
||||||
fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error> {
|
fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error> {
|
||||||
let key = MapKey::LastIndex(keychain).as_map_key();
|
let key = MapKey::LastIndex(keychain).as_map_key();
|
||||||
@ -470,4 +493,9 @@ mod test {
|
|||||||
fn test_last_index() {
|
fn test_last_index() {
|
||||||
crate::database::test::test_last_index(get_tree());
|
crate::database::test::test_last_index(get_tree());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_last_sync_time() {
|
||||||
|
crate::database::test::test_last_sync_time(get_tree());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ use crate::types::*;
|
|||||||
// transactions t<txid> -> tx details
|
// transactions t<txid> -> tx details
|
||||||
// deriv indexes c{i,e} -> u32
|
// deriv indexes c{i,e} -> u32
|
||||||
// descriptor checksum d{i,e} -> vec<u8>
|
// descriptor checksum d{i,e} -> vec<u8>
|
||||||
|
// last sync time l -> { height, timestamp }
|
||||||
|
|
||||||
pub(crate) enum MapKey<'a> {
|
pub(crate) enum MapKey<'a> {
|
||||||
Path((Option<KeychainKind>, Option<u32>)),
|
Path((Option<KeychainKind>, Option<u32>)),
|
||||||
@ -41,6 +42,7 @@ pub(crate) enum MapKey<'a> {
|
|||||||
RawTx(Option<&'a Txid>),
|
RawTx(Option<&'a Txid>),
|
||||||
Transaction(Option<&'a Txid>),
|
Transaction(Option<&'a Txid>),
|
||||||
LastIndex(KeychainKind),
|
LastIndex(KeychainKind),
|
||||||
|
LastSyncTime,
|
||||||
DescriptorChecksum(KeychainKind),
|
DescriptorChecksum(KeychainKind),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,6 +61,7 @@ impl MapKey<'_> {
|
|||||||
MapKey::RawTx(_) => b"r".to_vec(),
|
MapKey::RawTx(_) => b"r".to_vec(),
|
||||||
MapKey::Transaction(_) => b"t".to_vec(),
|
MapKey::Transaction(_) => b"t".to_vec(),
|
||||||
MapKey::LastIndex(st) => [b"c", st.as_ref()].concat(),
|
MapKey::LastIndex(st) => [b"c", st.as_ref()].concat(),
|
||||||
|
MapKey::LastSyncTime => b"l".to_vec(),
|
||||||
MapKey::DescriptorChecksum(st) => [b"d", st.as_ref()].concat(),
|
MapKey::DescriptorChecksum(st) => [b"d", st.as_ref()].concat(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -180,6 +183,12 @@ impl BatchOperations for MemoryDatabase {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
fn set_last_sync_time(&mut self, ct: ConfirmationTime) -> Result<(), Error> {
|
||||||
|
let key = MapKey::LastSyncTime.as_map_key();
|
||||||
|
self.map.insert(key, Box::new(ct));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn del_script_pubkey_from_path(
|
fn del_script_pubkey_from_path(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -270,6 +279,13 @@ impl BatchOperations for MemoryDatabase {
|
|||||||
Some(b) => Ok(Some(*b.downcast_ref().unwrap())),
|
Some(b) => Ok(Some(*b.downcast_ref().unwrap())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn del_last_sync_time(&mut self) -> Result<Option<ConfirmationTime>, Error> {
|
||||||
|
let key = MapKey::LastSyncTime.as_map_key();
|
||||||
|
let res = self.map.remove(&key);
|
||||||
|
self.deleted_keys.push(key);
|
||||||
|
|
||||||
|
Ok(res.map(|b| b.downcast_ref().cloned().unwrap()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Database for MemoryDatabase {
|
impl Database for MemoryDatabase {
|
||||||
@ -407,6 +423,14 @@ impl Database for MemoryDatabase {
|
|||||||
Ok(self.map.get(&key).map(|b| *b.downcast_ref().unwrap()))
|
Ok(self.map.get(&key).map(|b| *b.downcast_ref().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_last_sync_time(&self) -> Result<Option<ConfirmationTime>, Error> {
|
||||||
|
let key = MapKey::LastSyncTime.as_map_key();
|
||||||
|
Ok(self
|
||||||
|
.map
|
||||||
|
.get(&key)
|
||||||
|
.map(|b| b.downcast_ref().cloned().unwrap()))
|
||||||
|
}
|
||||||
|
|
||||||
// inserts 0 if not present
|
// inserts 0 if not present
|
||||||
fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error> {
|
fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error> {
|
||||||
let key = MapKey::LastIndex(keychain).as_map_key();
|
let key = MapKey::LastIndex(keychain).as_map_key();
|
||||||
@ -590,4 +614,9 @@ mod test {
|
|||||||
fn test_last_index() {
|
fn test_last_index() {
|
||||||
crate::database::test::test_last_index(get_tree());
|
crate::database::test::test_last_index(get_tree());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_last_sync_time() {
|
||||||
|
crate::database::test::test_last_sync_time(get_tree());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,6 +64,8 @@ pub trait BatchOperations {
|
|||||||
fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error>;
|
fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error>;
|
||||||
/// Store the last derivation index for a given keychain.
|
/// Store the last derivation index for a given keychain.
|
||||||
fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error>;
|
fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error>;
|
||||||
|
/// Store the sync time in terms of block height and timestamp
|
||||||
|
fn set_last_sync_time(&mut self, last_sync_time: ConfirmationTime) -> Result<(), Error>;
|
||||||
|
|
||||||
/// Delete a script_pubkey given the keychain and its child number.
|
/// Delete a script_pubkey given the keychain and its child number.
|
||||||
fn del_script_pubkey_from_path(
|
fn del_script_pubkey_from_path(
|
||||||
@ -89,6 +91,10 @@ pub trait BatchOperations {
|
|||||||
) -> Result<Option<TransactionDetails>, Error>;
|
) -> Result<Option<TransactionDetails>, Error>;
|
||||||
/// Delete the last derivation index for a keychain.
|
/// Delete the last derivation index for a keychain.
|
||||||
fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error>;
|
fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error>;
|
||||||
|
/// Reset the last sync time to `None`
|
||||||
|
///
|
||||||
|
/// Returns the removed value
|
||||||
|
fn del_last_sync_time(&mut self) -> Result<Option<ConfirmationTime>, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait for reading data from a database
|
/// Trait for reading data from a database
|
||||||
@ -134,6 +140,8 @@ pub trait Database: BatchOperations {
|
|||||||
fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error>;
|
fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error>;
|
||||||
/// Return the last defivation index for a keychain.
|
/// Return the last defivation index for a keychain.
|
||||||
fn get_last_index(&self, keychain: KeychainKind) -> Result<Option<u32>, Error>;
|
fn get_last_index(&self, keychain: KeychainKind) -> Result<Option<u32>, Error>;
|
||||||
|
/// Return the last sync time, if present
|
||||||
|
fn get_last_sync_time(&self) -> Result<Option<ConfirmationTime>, Error>;
|
||||||
|
|
||||||
/// Increment the last derivation index for a keychain and return it
|
/// Increment the last derivation index for a keychain and return it
|
||||||
///
|
///
|
||||||
@ -377,5 +385,23 @@ pub mod test {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn test_last_sync_time<D: Database>(mut tree: D) {
|
||||||
|
assert!(tree.get_last_sync_time().unwrap().is_none());
|
||||||
|
|
||||||
|
tree.set_last_sync_time(ConfirmationTime {
|
||||||
|
height: 100,
|
||||||
|
timestamp: 1000,
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let extracted = tree.get_last_sync_time().unwrap();
|
||||||
|
assert!(extracted.is_some());
|
||||||
|
assert_eq!(extracted.as_ref().unwrap().height, 100);
|
||||||
|
assert_eq!(extracted.as_ref().unwrap().timestamp, 1000);
|
||||||
|
|
||||||
|
tree.del_last_sync_time().unwrap();
|
||||||
|
assert!(tree.get_last_sync_time().unwrap().is_none());
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: more tests...
|
// TODO: more tests...
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ static MIGRATIONS: &[&str] = &[
|
|||||||
"CREATE UNIQUE INDEX idx_indices_keychain ON last_derivation_indices(keychain);",
|
"CREATE UNIQUE INDEX idx_indices_keychain ON last_derivation_indices(keychain);",
|
||||||
"CREATE TABLE checksums (keychain TEXT, checksum BLOB);",
|
"CREATE TABLE checksums (keychain TEXT, checksum BLOB);",
|
||||||
"CREATE INDEX idx_checksums_keychain ON checksums(keychain);",
|
"CREATE INDEX idx_checksums_keychain ON checksums(keychain);",
|
||||||
|
"CREATE TABLE last_sync_time (id INTEGER PRIMARY KEY, height INTEGER, timestamp INTEGER);"
|
||||||
];
|
];
|
||||||
|
|
||||||
/// Sqlite database stored on filesystem
|
/// Sqlite database stored on filesystem
|
||||||
@ -205,6 +206,19 @@ impl SqliteDatabase {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn update_last_sync_time(&self, ct: ConfirmationTime) -> Result<i64, Error> {
|
||||||
|
let mut statement = self.connection.prepare_cached(
|
||||||
|
"INSERT INTO last_sync_time (id, height, timestamp) VALUES (0, :height, :timestamp) ON CONFLICT(id) DO UPDATE SET height=:height, timestamp=:timestamp WHERE id = 0",
|
||||||
|
)?;
|
||||||
|
|
||||||
|
statement.execute(named_params! {
|
||||||
|
":height": ct.height,
|
||||||
|
":timestamp": ct.timestamp,
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(self.connection.last_insert_rowid())
|
||||||
|
}
|
||||||
|
|
||||||
fn select_script_pubkeys(&self) -> Result<Vec<Script>, Error> {
|
fn select_script_pubkeys(&self) -> Result<Vec<Script>, Error> {
|
||||||
let mut statement = self
|
let mut statement = self
|
||||||
.connection
|
.connection
|
||||||
@ -487,6 +501,20 @@ impl SqliteDatabase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn select_last_sync_time(&self) -> Result<Option<ConfirmationTime>, Error> {
|
||||||
|
let mut statement = self
|
||||||
|
.connection
|
||||||
|
.prepare_cached("SELECT height, timestamp FROM last_sync_time WHERE id = 0")?;
|
||||||
|
let mut rows = statement.query_map([], |row| {
|
||||||
|
Ok(ConfirmationTime {
|
||||||
|
height: row.get(0)?,
|
||||||
|
timestamp: row.get(1)?,
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(rows.next().transpose()?)
|
||||||
|
}
|
||||||
|
|
||||||
fn select_checksum_by_keychain(&self, keychain: String) -> Result<Option<Vec<u8>>, Error> {
|
fn select_checksum_by_keychain(&self, keychain: String) -> Result<Option<Vec<u8>>, Error> {
|
||||||
let mut statement = self
|
let mut statement = self
|
||||||
.connection
|
.connection
|
||||||
@ -563,6 +591,14 @@ impl SqliteDatabase {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn delete_last_sync_time(&self) -> Result<(), Error> {
|
||||||
|
let mut statement = self
|
||||||
|
.connection
|
||||||
|
.prepare_cached("DELETE FROM last_sync_time WHERE id = 0")?;
|
||||||
|
statement.execute([])?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BatchOperations for SqliteDatabase {
|
impl BatchOperations for SqliteDatabase {
|
||||||
@ -622,6 +658,11 @@ impl BatchOperations for SqliteDatabase {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_last_sync_time(&mut self, ct: ConfirmationTime) -> Result<(), Error> {
|
||||||
|
self.update_last_sync_time(ct)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn del_script_pubkey_from_path(
|
fn del_script_pubkey_from_path(
|
||||||
&mut self,
|
&mut self,
|
||||||
keychain: KeychainKind,
|
keychain: KeychainKind,
|
||||||
@ -707,6 +748,17 @@ impl BatchOperations for SqliteDatabase {
|
|||||||
None => Ok(None),
|
None => Ok(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn del_last_sync_time(&mut self) -> Result<Option<ConfirmationTime>, Error> {
|
||||||
|
match self.select_last_sync_time()? {
|
||||||
|
Some(value) => {
|
||||||
|
self.delete_last_sync_time()?;
|
||||||
|
|
||||||
|
Ok(Some(value))
|
||||||
|
}
|
||||||
|
None => Ok(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Database for SqliteDatabase {
|
impl Database for SqliteDatabase {
|
||||||
@ -818,6 +870,10 @@ impl Database for SqliteDatabase {
|
|||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_last_sync_time(&self) -> Result<Option<ConfirmationTime>, Error> {
|
||||||
|
self.select_last_sync_time()
|
||||||
|
}
|
||||||
|
|
||||||
fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error> {
|
fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error> {
|
||||||
let keychain_string = serde_json::to_string(&keychain)?;
|
let keychain_string = serde_json::to_string(&keychain)?;
|
||||||
match self.get_last_index(keychain)? {
|
match self.get_last_index(keychain)? {
|
||||||
@ -965,4 +1021,9 @@ pub mod test {
|
|||||||
fn test_last_index() {
|
fn test_last_index() {
|
||||||
crate::database::test::test_last_index(get_database());
|
crate::database::test::test_last_index(get_database());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_last_sync_time() {
|
||||||
|
crate::database::test::test_last_sync_time(get_database());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user