diff --git a/src/database/sqlite/mod.rs b/src/database/sqlite/mod.rs index 3b672df4..50c92f4d 100644 --- a/src/database/sqlite/mod.rs +++ b/src/database/sqlite/mod.rs @@ -238,17 +238,22 @@ impl SqliteConn { // Update the address to derivation index mapping. // TODO: have this as a helper in descriptors.rs let next_la_index = next_index + LOOK_AHEAD_LIMIT - 1; - let next_la_address = db_wallet + let next_receive_address = db_wallet .main_descriptor .receive_descriptor() .derive(next_la_index.into(), secp) .address(network); - db_tx - .execute( - "INSERT INTO addresses (address, derivation_index) VALUES (?1, ?2)", - rusqlite::params![next_la_address.to_string(), next_la_index], - ) - .map(|_| ()) + let next_change_address = db_wallet + .main_descriptor + .change_descriptor() + .derive(next_la_index.into(), secp) + .address(network); + db_tx.execute( + "INSERT INTO addresses (receive_address, change_address, derivation_index) VALUES (?1, ?2, ?3)", + rusqlite::params![next_receive_address.to_string(), next_change_address.to_string(), next_la_index], + )?; + + Ok(()) }) .expect("Database must be available") } @@ -363,7 +368,7 @@ impl SqliteConn { pub fn db_address(&mut self, address: &bitcoin::Address) -> Option { db_query( &mut self.conn, - "SELECT * FROM addresses WHERE address = ?1", + "SELECT * FROM addresses WHERE receive_address = ?1 OR change_address = ?1", rusqlite::params![address.to_string()], |row| row.try_into(), ) @@ -721,6 +726,15 @@ mod tests { let db_addr = conn.db_address(&addr).unwrap(); assert_eq!(db_addr.derivation_index, 0.into()); + // And also for the change address + let addr = options + .main_descriptor + .change_descriptor() + .derive(0.into(), &secp) + .address(options.bitcoind_network); + let db_addr = conn.db_address(&addr).unwrap(); + assert_eq!(db_addr.derivation_index, 0.into()); + // There is the index for the 199th index (look-ahead limit) let addr = options .main_descriptor @@ -742,6 +756,15 @@ mod tests { conn.increment_derivation_index(&secp); let db_addr = conn.db_address(&addr).unwrap(); assert_eq!(db_addr.derivation_index, 200.into()); + + // Same for the change descriptor. + let addr = options + .main_descriptor + .change_descriptor() + .derive(200.into(), &secp) + .address(options.bitcoind_network); + let db_addr = conn.db_address(&addr).unwrap(); + assert_eq!(db_addr.derivation_index, 200.into()); } fs::remove_dir_all(&tmp_dir).unwrap(); diff --git a/src/database/sqlite/schema.rs b/src/database/sqlite/schema.rs index 99975e48..87c55bb5 100644 --- a/src/database/sqlite/schema.rs +++ b/src/database/sqlite/schema.rs @@ -57,7 +57,8 @@ CREATE TABLE coins ( * we can get the derivation index from the parent descriptor from bitcoind. */ CREATE TABLE addresses ( - address TEXT NOT NULL UNIQUE, + receive_address TEXT NOT NULL UNIQUE, + change_address TEXT NOT NULL UNIQUE, derivation_index INTEGER NOT NULL UNIQUE ); @@ -195,7 +196,8 @@ impl TryFrom<&rusqlite::Row<'_>> for DbCoin { #[derive(Debug, Clone, PartialEq, Eq)] pub struct DbAddress { - pub address: bitcoin::Address, + pub receive_address: bitcoin::Address, + pub change_address: bitcoin::Address, pub derivation_index: bip32::ChildNumber, } @@ -203,15 +205,21 @@ impl TryFrom<&rusqlite::Row<'_>> for DbAddress { type Error = rusqlite::Error; fn try_from(row: &rusqlite::Row) -> Result { - let address: String = row.get(0)?; - let address = bitcoin::Address::from_str(&address).expect("We only store valid addresses"); + let receive_address: String = row.get(0)?; + let receive_address = + bitcoin::Address::from_str(&receive_address).expect("We only store valid addresses"); - let derivation_index: u32 = row.get(1)?; + let change_address: String = row.get(1)?; + let change_address = + bitcoin::Address::from_str(&change_address).expect("We only store valid addresses"); + + let derivation_index: u32 = row.get(2)?; let derivation_index = bip32::ChildNumber::from(derivation_index); assert!(derivation_index.is_normal()); Ok(DbAddress { - address, + receive_address, + change_address, derivation_index, }) } diff --git a/src/database/sqlite/utils.rs b/src/database/sqlite/utils.rs index 43a3102c..82d09d84 100644 --- a/src/database/sqlite/utils.rs +++ b/src/database/sqlite/utils.rs @@ -95,15 +95,19 @@ pub fn create_fresh_db( // necessarily 0. let mut query = String::with_capacity(100 * LOOK_AHEAD_LIMIT as usize); for index in 0..LOOK_AHEAD_LIMIT { - // TODO: have this as a helper in descriptors.rs - let address = options + let receive_address = options .main_descriptor .receive_descriptor() .derive(index.into(), secp) .address(options.bitcoind_network); + let change_address = options + .main_descriptor + .change_descriptor() + .derive(index.into(), secp) + .address(options.bitcoind_network); query += &format!( - "INSERT INTO addresses (address, derivation_index) VALUES (\"{}\", {});\n", - address, index + "INSERT INTO addresses (receive_address, change_address, derivation_index) VALUES (\"{}\", \"{}\", {});\n", + receive_address, change_address, index ); }