lib: couple block height and time
This commit is contained in:
parent
943cc16e77
commit
4cb6d2dc69
@ -60,8 +60,7 @@ fn update_coins(
|
||||
amount,
|
||||
derivation_index,
|
||||
is_change,
|
||||
block_height: None,
|
||||
block_time: None,
|
||||
block_info: None,
|
||||
spend_txid: None,
|
||||
spend_block: None,
|
||||
};
|
||||
@ -85,7 +84,7 @@ fn update_coins(
|
||||
.values()
|
||||
.chain(received.iter())
|
||||
.filter_map(|coin| {
|
||||
if coin.block_height.is_none() {
|
||||
if coin.block_info.is_none() {
|
||||
Some(coin.outpoint)
|
||||
} else {
|
||||
None
|
||||
|
||||
@ -293,7 +293,7 @@ impl DaemonControl {
|
||||
let Coin {
|
||||
amount,
|
||||
outpoint,
|
||||
block_height,
|
||||
block_info,
|
||||
spend_txid,
|
||||
spend_block,
|
||||
..
|
||||
@ -302,6 +302,7 @@ impl DaemonControl {
|
||||
txid,
|
||||
height: spend_block.map(|b| b.height),
|
||||
});
|
||||
let block_height = block_info.map(|b| b.height);
|
||||
ListCoinsEntry {
|
||||
amount,
|
||||
outpoint,
|
||||
@ -712,8 +713,8 @@ impl DaemonControl {
|
||||
.into_iter()
|
||||
.filter(|(_, c)| {
|
||||
// We are interested in coins available at the *next* block
|
||||
c.block_height
|
||||
.map(|h| current_height + 1 >= h + timelock)
|
||||
c.block_info
|
||||
.map(|b| current_height + 1 >= b.height + timelock)
|
||||
.unwrap_or(false)
|
||||
});
|
||||
|
||||
@ -867,7 +868,11 @@ pub struct CreateRecoveryResult {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{bitcoin::Block, database::SpendBlock, testutils::*};
|
||||
use crate::{
|
||||
bitcoin::Block,
|
||||
database::{BlockInfo, SpendBlock},
|
||||
testutils::*,
|
||||
};
|
||||
|
||||
use bitcoin::{
|
||||
blockdata::transaction::{TxIn, TxOut},
|
||||
@ -959,8 +964,7 @@ mod tests {
|
||||
let mut db_conn = control.db().lock().unwrap().connection();
|
||||
db_conn.new_unspent_coins(&[Coin {
|
||||
outpoint: dummy_op,
|
||||
block_height: None,
|
||||
block_time: None,
|
||||
block_info: None,
|
||||
amount: bitcoin::Amount::from_sat(100_000),
|
||||
derivation_index: bip32::ChildNumber::from(13),
|
||||
is_change: false,
|
||||
@ -1065,8 +1069,7 @@ mod tests {
|
||||
};
|
||||
db_conn.new_unspent_coins(&[Coin {
|
||||
outpoint: dummy_op_dup,
|
||||
block_height: None,
|
||||
block_time: None,
|
||||
block_info: None,
|
||||
amount: bitcoin::Amount::from_sat(400_000),
|
||||
derivation_index: bip32::ChildNumber::from(42),
|
||||
is_change: false,
|
||||
@ -1112,8 +1115,7 @@ mod tests {
|
||||
db_conn.new_unspent_coins(&[
|
||||
Coin {
|
||||
outpoint: dummy_op_a,
|
||||
block_height: None,
|
||||
block_time: None,
|
||||
block_info: None,
|
||||
amount: bitcoin::Amount::from_sat(100_000),
|
||||
derivation_index: bip32::ChildNumber::from(13),
|
||||
is_change: false,
|
||||
@ -1122,8 +1124,7 @@ mod tests {
|
||||
},
|
||||
Coin {
|
||||
outpoint: dummy_op_b,
|
||||
block_height: None,
|
||||
block_time: None,
|
||||
block_info: None,
|
||||
amount: bitcoin::Amount::from_sat(115_680),
|
||||
derivation_index: bip32::ChildNumber::from(34),
|
||||
is_change: false,
|
||||
@ -1294,8 +1295,7 @@ mod tests {
|
||||
txid: deposit1.txid(),
|
||||
vout: 0,
|
||||
},
|
||||
block_time: Some(1),
|
||||
block_height: Some(1),
|
||||
block_info: Some(BlockInfo { height: 1, time: 1 }),
|
||||
spend_block: Some(SpendBlock { time: 3, height: 3 }),
|
||||
derivation_index: ChildNumber::from(0),
|
||||
amount: bitcoin::Amount::from_sat(100_000_000),
|
||||
@ -1308,8 +1308,7 @@ mod tests {
|
||||
txid: deposit2.txid(),
|
||||
vout: 0,
|
||||
},
|
||||
block_time: Some(2),
|
||||
block_height: Some(2),
|
||||
block_info: Some(BlockInfo { height: 2, time: 2 }),
|
||||
spend_block: None,
|
||||
derivation_index: ChildNumber::from(1),
|
||||
amount: bitcoin::Amount::from_sat(2000),
|
||||
@ -1319,8 +1318,7 @@ mod tests {
|
||||
Coin {
|
||||
is_change: true,
|
||||
outpoint: OutPoint::new(spend_tx.txid(), 1),
|
||||
block_time: Some(3),
|
||||
block_height: Some(3),
|
||||
block_info: Some(BlockInfo { height: 3, time: 3 }),
|
||||
spend_block: None,
|
||||
derivation_index: ChildNumber::from(2),
|
||||
amount: bitcoin::Amount::from_sat(100_000_000 - 4000 - 1000),
|
||||
@ -1333,8 +1331,7 @@ mod tests {
|
||||
txid: deposit3.txid(),
|
||||
vout: 0,
|
||||
},
|
||||
block_time: Some(4),
|
||||
block_height: Some(4),
|
||||
block_info: Some(BlockInfo { height: 4, time: 4 }),
|
||||
spend_block: None,
|
||||
derivation_index: ChildNumber::from(3),
|
||||
amount: bitcoin::Amount::from_sat(3000),
|
||||
|
||||
@ -6,7 +6,7 @@ pub mod sqlite;
|
||||
use crate::{
|
||||
bitcoin::BlockChainTip,
|
||||
database::sqlite::{
|
||||
schema::{DbCoin, DbSpendBlock, DbTip},
|
||||
schema::{DbBlockInfo, DbCoin, DbSpendBlock, DbTip},
|
||||
SqliteConn, SqliteDb,
|
||||
},
|
||||
};
|
||||
@ -276,11 +276,25 @@ impl From<DbSpendBlock> for SpendBlock {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct BlockInfo {
|
||||
pub height: i32,
|
||||
pub time: u32,
|
||||
}
|
||||
|
||||
impl From<DbBlockInfo> for BlockInfo {
|
||||
fn from(b: DbBlockInfo) -> BlockInfo {
|
||||
BlockInfo {
|
||||
height: b.height,
|
||||
time: b.time,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct Coin {
|
||||
pub outpoint: bitcoin::OutPoint,
|
||||
pub block_height: Option<i32>,
|
||||
pub block_time: Option<u32>,
|
||||
pub block_info: Option<BlockInfo>,
|
||||
pub amount: bitcoin::Amount,
|
||||
pub derivation_index: bip32::ChildNumber,
|
||||
pub is_change: bool,
|
||||
@ -292,8 +306,7 @@ impl std::convert::From<DbCoin> for Coin {
|
||||
fn from(db_coin: DbCoin) -> Coin {
|
||||
let DbCoin {
|
||||
outpoint,
|
||||
block_height,
|
||||
block_time,
|
||||
block_info,
|
||||
amount,
|
||||
derivation_index,
|
||||
is_change,
|
||||
@ -303,8 +316,7 @@ impl std::convert::From<DbCoin> for Coin {
|
||||
} = db_coin;
|
||||
Coin {
|
||||
outpoint,
|
||||
block_height,
|
||||
block_time,
|
||||
block_info: block_info.map(BlockInfo::from),
|
||||
amount,
|
||||
derivation_index,
|
||||
is_change,
|
||||
@ -316,7 +328,7 @@ impl std::convert::From<DbCoin> for Coin {
|
||||
|
||||
impl Coin {
|
||||
pub fn is_confirmed(&self) -> bool {
|
||||
self.block_height.is_some()
|
||||
self.block_info.is_some()
|
||||
}
|
||||
|
||||
pub fn is_spent(&self) -> bool {
|
||||
|
||||
@ -585,7 +585,7 @@ impl SqliteConn {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::database::SpendBlock;
|
||||
use crate::database::{BlockInfo, DbBlockInfo, SpendBlock};
|
||||
use crate::testutils::*;
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
@ -709,8 +709,7 @@ mod tests {
|
||||
"6f0dc85a369b44458eba3a1f0ea5b5935d563afb6994f70f5b0094e05be1676c:1",
|
||||
)
|
||||
.unwrap(),
|
||||
block_height: None,
|
||||
block_time: None,
|
||||
block_info: None,
|
||||
amount: bitcoin::Amount::from_sat(98765),
|
||||
derivation_index: bip32::ChildNumber::from_normal_idx(10).unwrap(),
|
||||
is_change: false,
|
||||
@ -742,8 +741,7 @@ mod tests {
|
||||
"61db3e276b095e5b05f1849dd6bfffb4e7e5ec1c4a4210099b98fce01571936f:12",
|
||||
)
|
||||
.unwrap(),
|
||||
block_height: None,
|
||||
block_time: None,
|
||||
block_info: None,
|
||||
amount: bitcoin::Amount::from_sat(1111),
|
||||
derivation_index: bip32::ChildNumber::from_normal_idx(103).unwrap(),
|
||||
is_change: true,
|
||||
@ -780,10 +778,8 @@ mod tests {
|
||||
let time = 174500;
|
||||
conn.confirm_coins(&[(coin_a.outpoint, height, time)]);
|
||||
let coins = conn.coins(CoinType::All);
|
||||
assert_eq!(coins[0].block_height, Some(height));
|
||||
assert_eq!(coins[0].block_time, Some(time));
|
||||
assert!(coins[1].block_height.is_none());
|
||||
assert!(coins[1].block_time.is_none());
|
||||
assert_eq!(coins[0].block_info, Some(DbBlockInfo { height, time }));
|
||||
assert!(coins[1].block_info.is_none());
|
||||
|
||||
// Now if we spend one, it'll be marked as such.
|
||||
conn.spend_coins(&[(
|
||||
@ -969,8 +965,7 @@ mod tests {
|
||||
"6f0dc85a369b44458eba3a1f0ea5b5935d563afb6994f70f5b0094e05be1676c:1",
|
||||
)
|
||||
.unwrap(),
|
||||
block_height: None,
|
||||
block_time: None,
|
||||
block_info: None,
|
||||
amount: bitcoin::Amount::from_sat(98765),
|
||||
derivation_index: bip32::ChildNumber::from_normal_idx(10).unwrap(),
|
||||
is_change: false,
|
||||
@ -982,8 +977,10 @@ mod tests {
|
||||
"c449539458c60bee6c0d8905ba1dadb20b9187b82045d306a408b894cea492b0:2",
|
||||
)
|
||||
.unwrap(),
|
||||
block_height: Some(101_095),
|
||||
block_time: Some(1_111_899),
|
||||
block_info: Some(BlockInfo {
|
||||
height: 101_095,
|
||||
time: 1_111_899,
|
||||
}),
|
||||
amount: bitcoin::Amount::from_sat(98765),
|
||||
derivation_index: bip32::ChildNumber::from_normal_idx(100).unwrap(),
|
||||
is_change: false,
|
||||
@ -995,8 +992,10 @@ mod tests {
|
||||
"f0801fd9ca8bca0624c230ab422b2e2c4c8dc995e4e1dbc6412510959cce1e4f:3",
|
||||
)
|
||||
.unwrap(),
|
||||
block_height: Some(101_099),
|
||||
block_time: Some(1_121_899),
|
||||
block_info: Some(BlockInfo {
|
||||
height: 101_099,
|
||||
time: 1_121_899,
|
||||
}),
|
||||
amount: bitcoin::Amount::from_sat(98765),
|
||||
derivation_index: bip32::ChildNumber::from_normal_idx(1000).unwrap(),
|
||||
is_change: false,
|
||||
@ -1016,8 +1015,10 @@ mod tests {
|
||||
"19f56e65069f0a7a3bfb00c6a7085cc0669e03e91befeca1ee9891c9e737b2fb:4",
|
||||
)
|
||||
.unwrap(),
|
||||
block_height: Some(101_100),
|
||||
block_time: Some(1_131_899),
|
||||
block_info: Some(BlockInfo {
|
||||
height: 101_100,
|
||||
time: 1_131_899,
|
||||
}),
|
||||
amount: bitcoin::Amount::from_sat(98765),
|
||||
derivation_index: bip32::ChildNumber::from_normal_idx(10000).unwrap(),
|
||||
is_change: false,
|
||||
@ -1029,8 +1030,10 @@ mod tests {
|
||||
"ed6c8f1af9325f84de521e785e7ddfd33dc28c9ada4d687dcd3850100bde54e9:5",
|
||||
)
|
||||
.unwrap(),
|
||||
block_height: Some(101_102),
|
||||
block_time: Some(1_134_899),
|
||||
block_info: Some(BlockInfo {
|
||||
height: 101_102,
|
||||
time: 1_134_899,
|
||||
}),
|
||||
amount: bitcoin::Amount::from_sat(98765),
|
||||
derivation_index: bip32::ChildNumber::from_normal_idx(100000).unwrap(),
|
||||
is_change: false,
|
||||
@ -1050,10 +1053,7 @@ mod tests {
|
||||
conn.confirm_coins(
|
||||
&coins
|
||||
.iter()
|
||||
.filter_map(|c| {
|
||||
c.block_height
|
||||
.map(|b| (c.outpoint, b, c.block_time.unwrap()))
|
||||
})
|
||||
.filter_map(|c| c.block_info.map(|b| (c.outpoint, b.height, b.time)))
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
conn.confirm_spend(
|
||||
@ -1115,13 +1115,11 @@ mod tests {
|
||||
assert_eq!(db_coins[&coins[2].outpoint], coin);
|
||||
// The fourth one got its own confirmation info wiped
|
||||
let mut coin = coins[3];
|
||||
coin.block_height = None;
|
||||
coin.block_time = None;
|
||||
coin.block_info = None;
|
||||
assert_eq!(db_coins[&coins[3].outpoint], coin);
|
||||
// The fourth one got both is own confirmation and spend confirmation info wiped
|
||||
let mut coin = coins[4];
|
||||
coin.block_height = None;
|
||||
coin.block_time = None;
|
||||
coin.block_info = None;
|
||||
coin.spend_block = None;
|
||||
assert_eq!(db_coins[&coins[4].outpoint], coin);
|
||||
}
|
||||
@ -1180,8 +1178,7 @@ mod tests {
|
||||
"6f0dc85a369b44458eba3a1f0ea5b5935d563afb6994f70f5b0094e05be1676c:1",
|
||||
)
|
||||
.unwrap(),
|
||||
block_height: None,
|
||||
block_time: None,
|
||||
block_info: None,
|
||||
amount: bitcoin::Amount::from_sat(98765),
|
||||
derivation_index: bip32::ChildNumber::from_normal_idx(10).unwrap(),
|
||||
is_change: false,
|
||||
@ -1193,8 +1190,10 @@ mod tests {
|
||||
"c449539458c60bee6c0d8905ba1dadb20b9187b82045d306a408b894cea492b0:2",
|
||||
)
|
||||
.unwrap(),
|
||||
block_height: Some(101_095),
|
||||
block_time: Some(1_121_000),
|
||||
block_info: Some(BlockInfo {
|
||||
height: 101_095,
|
||||
time: 1_121_000,
|
||||
}),
|
||||
amount: bitcoin::Amount::from_sat(98765),
|
||||
derivation_index: bip32::ChildNumber::from_normal_idx(100).unwrap(),
|
||||
is_change: false,
|
||||
@ -1206,8 +1205,10 @@ mod tests {
|
||||
"f0801fd9ca8bca0624c230ab422b2e2c4c8dc995e4e1dbc6412510959cce1e4f:3",
|
||||
)
|
||||
.unwrap(),
|
||||
block_height: Some(101_099),
|
||||
block_time: Some(1_122_000),
|
||||
block_info: Some(BlockInfo {
|
||||
height: 101_099,
|
||||
time: 1_122_000,
|
||||
}),
|
||||
amount: bitcoin::Amount::from_sat(98765),
|
||||
derivation_index: bip32::ChildNumber::from_normal_idx(1000).unwrap(),
|
||||
is_change: false,
|
||||
@ -1227,8 +1228,10 @@ mod tests {
|
||||
"19f56e65069f0a7a3bfb00c6a7085cc0669e03e91befeca1ee9891c9e737b2fb:4",
|
||||
)
|
||||
.unwrap(),
|
||||
block_height: Some(101_100),
|
||||
block_time: Some(1_124_000),
|
||||
block_info: Some(BlockInfo {
|
||||
height: 101_100,
|
||||
time: 1_124_000,
|
||||
}),
|
||||
amount: bitcoin::Amount::from_sat(98765),
|
||||
derivation_index: bip32::ChildNumber::from_normal_idx(10000).unwrap(),
|
||||
is_change: false,
|
||||
@ -1240,8 +1243,10 @@ mod tests {
|
||||
"ed6c8f1af9325f84de521e785e7ddfd33dc28c9ada4d687dcd3850100bde54e9:5",
|
||||
)
|
||||
.unwrap(),
|
||||
block_height: Some(101_102),
|
||||
block_time: Some(1_125_000),
|
||||
block_info: Some(BlockInfo {
|
||||
height: 101_102,
|
||||
time: 1_125_000,
|
||||
}),
|
||||
amount: bitcoin::Amount::from_sat(98765),
|
||||
derivation_index: bip32::ChildNumber::from_normal_idx(100000).unwrap(),
|
||||
is_change: false,
|
||||
@ -1261,10 +1266,7 @@ mod tests {
|
||||
conn.confirm_coins(
|
||||
&coins
|
||||
.iter()
|
||||
.filter_map(|c| {
|
||||
c.block_height
|
||||
.map(|b| (c.outpoint, b, c.block_time.unwrap()))
|
||||
})
|
||||
.filter_map(|c| c.block_info.map(|b| (c.outpoint, b.height, b.time)))
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
conn.confirm_spend(
|
||||
|
||||
@ -153,13 +153,18 @@ pub struct DbSpendBlock {
|
||||
pub time: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct DbBlockInfo {
|
||||
pub height: i32,
|
||||
pub time: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct DbCoin {
|
||||
pub id: i64,
|
||||
pub wallet_id: i64,
|
||||
pub outpoint: bitcoin::OutPoint,
|
||||
pub block_height: Option<i32>,
|
||||
pub block_time: Option<u32>,
|
||||
pub block_info: Option<DbBlockInfo>,
|
||||
pub amount: bitcoin::Amount,
|
||||
pub derivation_index: bip32::ChildNumber,
|
||||
pub is_change: bool,
|
||||
@ -174,8 +179,13 @@ impl TryFrom<&rusqlite::Row<'_>> for DbCoin {
|
||||
let id = row.get(0)?;
|
||||
let wallet_id = row.get(1)?;
|
||||
|
||||
let block_height = row.get(2)?;
|
||||
let block_time = row.get(3)?;
|
||||
let block_height: Option<i32> = row.get(2)?;
|
||||
let block_time: Option<u32> = row.get(3)?;
|
||||
assert_eq!(block_height.is_none(), block_time.is_none());
|
||||
let block_info = block_height.map(|height| DbBlockInfo {
|
||||
height,
|
||||
time: block_time.expect("Must be there if height is"),
|
||||
});
|
||||
let txid: Vec<u8> = row.get(4)?;
|
||||
let txid: bitcoin::Txid = encode::deserialize(&txid).expect("We only store valid txids");
|
||||
let vout = row.get(5)?;
|
||||
@ -202,8 +212,7 @@ impl TryFrom<&rusqlite::Row<'_>> for DbCoin {
|
||||
id,
|
||||
wallet_id,
|
||||
outpoint,
|
||||
block_height,
|
||||
block_time,
|
||||
block_info,
|
||||
amount,
|
||||
derivation_index,
|
||||
is_change,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
bitcoin::{BitcoinInterface, Block, BlockChainTip, UTxO},
|
||||
config::{BitcoinConfig, Config},
|
||||
database::{Coin, CoinType, DatabaseConnection, DatabaseInterface, SpendBlock},
|
||||
database::{BlockInfo, Coin, CoinType, DatabaseConnection, DatabaseInterface, SpendBlock},
|
||||
descriptors, DaemonHandle,
|
||||
};
|
||||
|
||||
@ -233,10 +233,11 @@ impl DatabaseConnection for DummyDatabase {
|
||||
for (op, height, time) in outpoints {
|
||||
let mut db = self.db.write().unwrap();
|
||||
let coin = &mut db.coins.get_mut(op).unwrap();
|
||||
assert!(coin.block_height.is_none());
|
||||
assert!(coin.block_time.is_none());
|
||||
coin.block_height = Some(*height);
|
||||
coin.block_time = Some(*time);
|
||||
assert!(coin.block_info.is_none());
|
||||
coin.block_info = Some(BlockInfo {
|
||||
height: *height,
|
||||
time: *time,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -335,7 +336,7 @@ impl DatabaseConnection for DummyDatabase {
|
||||
// Get txid and block time of every transactions that happened between start and end
|
||||
// timestamps.
|
||||
for coin in coins.values() {
|
||||
if let Some(time) = coin.block_time {
|
||||
if let Some(time) = coin.block_info.map(|b| b.time) {
|
||||
if time >= start && time <= end {
|
||||
let row = (coin.outpoint.txid, time);
|
||||
if !txids_and_time.contains(&row) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user