diff --git a/src/database/keyvalue.rs b/src/database/keyvalue.rs index e10ada1f..f586ebeb 100644 --- a/src/database/keyvalue.rs +++ b/src/database/keyvalue.rs @@ -492,4 +492,44 @@ mod test { fn test_sync_time() { crate::database::test::test_sync_time(get_tree()); } + + #[test] + fn test_iter_raw_txs() { + crate::database::test::test_iter_raw_txs(get_tree()); + } + + #[test] + fn test_del_path_from_script_pubkey() { + crate::database::test::test_del_path_from_script_pubkey(get_tree()); + } + + #[test] + fn test_iter_script_pubkeys() { + crate::database::test::test_iter_script_pubkeys(get_tree()); + } + + #[test] + fn test_del_utxo() { + crate::database::test::test_del_utxo(get_tree()); + } + + #[test] + fn test_del_raw_tx() { + crate::database::test::test_del_raw_tx(get_tree()); + } + + #[test] + fn test_del_tx() { + crate::database::test::test_del_tx(get_tree()); + } + + #[test] + fn test_del_last_index() { + crate::database::test::test_del_last_index(get_tree()); + } + + #[test] + fn test_check_descriptor_checksum() { + crate::database::test::test_check_descriptor_checksum(get_tree()); + } } diff --git a/src/database/memory.rs b/src/database/memory.rs index eff5ecf1..691e7eb1 100644 --- a/src/database/memory.rs +++ b/src/database/memory.rs @@ -647,4 +647,44 @@ mod test { fn test_sync_time() { crate::database::test::test_sync_time(get_tree()); } + + #[test] + fn test_iter_raw_txs() { + crate::database::test::test_iter_raw_txs(get_tree()); + } + + #[test] + fn test_del_path_from_script_pubkey() { + crate::database::test::test_del_path_from_script_pubkey(get_tree()); + } + + #[test] + fn test_iter_script_pubkeys() { + crate::database::test::test_iter_script_pubkeys(get_tree()); + } + + #[test] + fn test_del_utxo() { + crate::database::test::test_del_utxo(get_tree()); + } + + #[test] + fn test_del_raw_tx() { + crate::database::test::test_del_raw_tx(get_tree()); + } + + #[test] + fn test_del_tx() { + crate::database::test::test_del_tx(get_tree()); + } + + #[test] + fn test_del_last_index() { + crate::database::test::test_del_last_index(get_tree()); + } + + #[test] + fn test_check_descriptor_checksum() { + crate::database::test::test_check_descriptor_checksum(get_tree()); + } } diff --git a/src/database/mod.rs b/src/database/mod.rs index c7ff1795..711dea7e 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -217,6 +217,7 @@ pub mod test { use std::str::FromStr; use bitcoin::consensus::encode::deserialize; + use bitcoin::consensus::serialize; use bitcoin::hashes::hex::*; use bitcoin::*; @@ -322,8 +323,24 @@ pub mod test { } pub fn test_raw_tx(mut tree: D) { - let hex_tx = Vec::::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); - let tx: Transaction = deserialize(&hex_tx).unwrap(); + let hex_tx = Vec::::from_hex("02000000000101f58c18a90d7a76b30c7e47d4e817adfdd79a6a589a615ef36e360f913adce2cd0000000000feffffff0210270000000000001600145c9a1816d38db5cbdd4b067b689dc19eb7d930e2cf70aa2b080000001600140f48b63160043047f4f60f7f8f551f80458f693f024730440220413f42b7bc979945489a38f5221e5527d4b8e3aa63eae2099e01945896ad6c10022024ceec492d685c31d8adb64e935a06933877c5ae0e21f32efe029850914c5bad012102361caae96f0e9f3a453d354bb37a5c3244422fb22819bf0166c0647a38de39f21fca2300").unwrap(); + let mut tx: Transaction = deserialize(&hex_tx).unwrap(); + + tree.set_raw_tx(&tx).unwrap(); + + let txid = tx.txid(); + + assert_eq!(tree.get_raw_tx(&txid).unwrap(), Some(tx.clone())); + + // mutate transaction's witnesses + for tx_in in tx.input.iter_mut() { + tx_in.witness = Witness::new(); + } + + let updated_hex_tx = serialize(&tx); + + // verify that mutation was successful + assert_ne!(hex_tx, updated_hex_tx); tree.set_raw_tx(&tx).unwrap(); @@ -441,5 +458,203 @@ pub mod test { assert!(tree.get_sync_time().unwrap().is_none()); } + pub fn test_iter_raw_txs(mut db: D) { + let txs = db.iter_raw_txs().unwrap(); + assert!(txs.is_empty()); + + let hex_tx = Vec::::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); + let first_tx: Transaction = deserialize(&hex_tx).unwrap(); + + let hex_tx = Vec::::from_hex("02000000000101f58c18a90d7a76b30c7e47d4e817adfdd79a6a589a615ef36e360f913adce2cd0000000000feffffff0210270000000000001600145c9a1816d38db5cbdd4b067b689dc19eb7d930e2cf70aa2b080000001600140f48b63160043047f4f60f7f8f551f80458f693f024730440220413f42b7bc979945489a38f5221e5527d4b8e3aa63eae2099e01945896ad6c10022024ceec492d685c31d8adb64e935a06933877c5ae0e21f32efe029850914c5bad012102361caae96f0e9f3a453d354bb37a5c3244422fb22819bf0166c0647a38de39f21fca2300").unwrap(); + let second_tx: Transaction = deserialize(&hex_tx).unwrap(); + + db.set_raw_tx(&first_tx).unwrap(); + db.set_raw_tx(&second_tx).unwrap(); + + let txs = db.iter_raw_txs().unwrap(); + + assert!(txs.contains(&first_tx)); + assert!(txs.contains(&second_tx)); + assert_eq!(txs.len(), 2); + } + + pub fn test_del_path_from_script_pubkey(mut db: D) { + let keychain = KeychainKind::External; + + let script = Script::from( + Vec::::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(), + ); + let path = 42; + + let res = db.del_path_from_script_pubkey(&script).unwrap(); + + assert!(res.is_none()); + + let _res = db.set_script_pubkey(&script, keychain, path); + let (chain, child) = db.del_path_from_script_pubkey(&script).unwrap().unwrap(); + + assert_eq!(chain, keychain); + assert_eq!(child, path); + + let res = db.get_path_from_script_pubkey(&script).unwrap(); + assert!(res.is_none()); + } + + pub fn test_iter_script_pubkeys(mut db: D) { + let keychain = KeychainKind::External; + let scripts = db.iter_script_pubkeys(Some(keychain)).unwrap(); + assert!(scripts.is_empty()); + + let first_script = Script::from( + Vec::::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(), + ); + let path = 42; + + db.set_script_pubkey(&first_script, keychain, path).unwrap(); + + let second_script = Script::from( + Vec::::from_hex("00145c9a1816d38db5cbdd4b067b689dc19eb7d930e2").unwrap(), + ); + let path = 57; + + db.set_script_pubkey(&second_script, keychain, path) + .unwrap(); + let scripts = db.iter_script_pubkeys(Some(keychain)).unwrap(); + + assert!(scripts.contains(&first_script)); + assert!(scripts.contains(&second_script)); + assert_eq!(scripts.len(), 2); + } + + pub fn test_del_utxo(mut db: D) { + let outpoint = OutPoint::from_str( + "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:0", + ) + .unwrap(); + let script = Script::from( + Vec::::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(), + ); + let txout = TxOut { + value: 133742, + script_pubkey: script, + }; + let utxo = LocalUtxo { + txout, + outpoint, + keychain: KeychainKind::External, + is_spent: true, + }; + + let res = db.del_utxo(&outpoint).unwrap(); + assert!(res.is_none()); + + db.set_utxo(&utxo).unwrap(); + + let res = db.del_utxo(&outpoint).unwrap(); + + assert_eq!(res.unwrap(), utxo); + + let res = db.get_utxo(&outpoint).unwrap(); + assert!(res.is_none()); + } + + pub fn test_del_raw_tx(mut db: D) { + let hex_tx = Vec::::from_hex("02000000000101f58c18a90d7a76b30c7e47d4e817adfdd79a6a589a615ef36e360f913adce2cd0000000000feffffff0210270000000000001600145c9a1816d38db5cbdd4b067b689dc19eb7d930e2cf70aa2b080000001600140f48b63160043047f4f60f7f8f551f80458f693f024730440220413f42b7bc979945489a38f5221e5527d4b8e3aa63eae2099e01945896ad6c10022024ceec492d685c31d8adb64e935a06933877c5ae0e21f32efe029850914c5bad012102361caae96f0e9f3a453d354bb37a5c3244422fb22819bf0166c0647a38de39f21fca2300").unwrap(); + let tx: Transaction = deserialize(&hex_tx).unwrap(); + + let res = db.del_raw_tx(&tx.txid()).unwrap(); + + assert!(res.is_none()); + + db.set_raw_tx(&tx).unwrap(); + + let res = db.del_raw_tx(&tx.txid()).unwrap(); + + assert_eq!(res.unwrap(), tx); + + let res = db.get_raw_tx(&tx.txid()).unwrap(); + assert!(res.is_none()); + } + + pub fn test_del_tx(mut db: D) { + let hex_tx = Vec::::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); + let tx: Transaction = deserialize(&hex_tx).unwrap(); + let txid = tx.txid(); + let mut tx_details = TransactionDetails { + transaction: Some(tx.clone()), + txid, + received: 1337, + sent: 420420, + fee: Some(140), + confirmation_time: Some(BlockTime { + timestamp: 123456, + height: 1000, + }), + }; + + let res = db.del_tx(&tx.txid(), true).unwrap(); + + assert!(res.is_none()); + + db.set_tx(&tx_details).unwrap(); + + let res = db.del_tx(&tx.txid(), false).unwrap(); + tx_details.transaction = None; + assert_eq!(res.unwrap(), tx_details); + + let res = db.get_tx(&tx.txid(), true).unwrap(); + assert!(res.is_none()); + + let res = db.get_raw_tx(&tx.txid()).unwrap(); + assert_eq!(res.unwrap(), tx); + + db.set_tx(&tx_details).unwrap(); + let res = db.del_tx(&tx.txid(), true).unwrap(); + tx_details.transaction = Some(tx.clone()); + assert_eq!(res.unwrap(), tx_details); + + let res = db.get_tx(&tx.txid(), true).unwrap(); + assert!(res.is_none()); + + let res = db.get_raw_tx(&tx.txid()).unwrap(); + assert!(res.is_none()); + } + + pub fn test_del_last_index(mut db: D) { + let keychain = KeychainKind::External; + + let _res = db.increment_last_index(keychain); + + let res = db.get_last_index(keychain).unwrap().unwrap(); + + assert_eq!(res, 0); + + let _res = db.increment_last_index(keychain); + + let res = db.del_last_index(keychain).unwrap().unwrap(); + + assert_eq!(res, 1); + + let res = db.get_last_index(keychain).unwrap(); + assert!(res.is_none()); + } + + pub fn test_check_descriptor_checksum(mut db: D) { + // insert checksum associated to keychain + let checksum = "1cead456".as_bytes(); + let keychain = KeychainKind::External; + let _res = db.check_descriptor_checksum(keychain, checksum); + + // check if `check_descriptor_checksum` throws + // `Error::ChecksumMismatch` error if the + // function is passed a checksum that does + // not match the one initially inserted + let checksum = "1cead454".as_bytes(); + let keychain = KeychainKind::External; + let res = db.check_descriptor_checksum(keychain, checksum); + + assert!(res.is_err()); + } + // TODO: more tests... } diff --git a/src/database/sqlite.rs b/src/database/sqlite.rs index a9cbe1a7..bec6dd48 100644 --- a/src/database/sqlite.rs +++ b/src/database/sqlite.rs @@ -1038,4 +1038,44 @@ pub mod test { fn test_txs() { crate::database::test::test_list_transaction(get_database()); } + + #[test] + fn test_iter_raw_txs() { + crate::database::test::test_iter_raw_txs(get_database()); + } + + #[test] + fn test_del_path_from_script_pubkey() { + crate::database::test::test_del_path_from_script_pubkey(get_database()); + } + + #[test] + fn test_iter_script_pubkeys() { + crate::database::test::test_iter_script_pubkeys(get_database()); + } + + #[test] + fn test_del_utxo() { + crate::database::test::test_del_utxo(get_database()); + } + + #[test] + fn test_del_raw_tx() { + crate::database::test::test_del_raw_tx(get_database()); + } + + #[test] + fn test_del_tx() { + crate::database::test::test_del_tx(get_database()); + } + + #[test] + fn test_del_last_index() { + crate::database::test::test_del_last_index(get_database()); + } + + #[test] + fn test_check_descriptor_checksum() { + crate::database::test::test_check_descriptor_checksum(get_database()); + } }