@@ -4,13 +4,16 @@ use revault_tx::{
44 bitcoin:: { secp256k1, util:: bip32, Amount , BlockHash , Network , OutPoint } ,
55 scripts:: { CpfpDescriptor , DepositDescriptor , UnvaultDescriptor } ,
66} ;
7- use schema:: { DbInstance , DbSignature , DbVault , SigTxType , SCHEMA } ;
7+ use schema:: { DbFeerate , DbInstance , DbSignature , DbVault , SigTxType , SCHEMA } ;
88
99use std:: { collections, convert:: TryInto , fs, io, os:: unix:: fs:: OpenOptionsExt , path, time} ;
1010
1111use rusqlite:: params;
1212
1313pub const DB_VERSION : u32 = 0 ;
14+ // FIXME: Use correct values
15+ pub const INIT_VAULT_RESERVE_FEERATE : u64 = 1000 ;
16+ pub const INIT_VAULT_RESERVE_HEIGHT : i32 = 680000 ;
1417
1518#[ derive( Debug ) ]
1619pub enum DatabaseError {
@@ -22,6 +25,8 @@ pub enum DatabaseError {
2225 DescriptorMismatch ( String , String ) ,
2326 /// An operation was requested on a vault that doesn't exist
2427 UnknownVault ( Box < dyn std:: fmt:: Debug > ) ,
28+ /// Vault reserve feerate not found
29+ VaultReserveFeerateNotFound ( String ) ,
2530}
2631
2732impl std:: fmt:: Display for DatabaseError {
@@ -43,6 +48,9 @@ impl std::fmt::Display for DatabaseError {
4348 "Operation requested on vault at '{:?}' but no such vault exist in database." ,
4449 * id
4550 ) ,
51+ Self :: VaultReserveFeerateNotFound ( ref e) => {
52+ write ! ( f, "Vault reserve feerate not found: {}" , e)
53+ }
4654 }
4755 }
4856}
@@ -412,6 +420,41 @@ pub fn db_cancel_signatures(
412420 db_sigs_by_type ( db_path, vault_id, SigTxType :: Cancel )
413421}
414422
423+ pub fn db_update_vault_reserve_feerate (
424+ db_path : & path:: Path ,
425+ last_update : i32 ,
426+ vault_reserve_feerate : u64 ,
427+ ) -> Result < ( ) , DatabaseError > {
428+ db_exec ( db_path, |db_tx| {
429+ db_tx. execute (
430+ "UPDATE feerates
431+ SET last_update = (?1),
432+ vault_reserve_feerate = (?2)" ,
433+ params ! [ last_update, vault_reserve_feerate] ,
434+ ) ?;
435+ Ok ( ( ) )
436+ } )
437+ }
438+
439+ pub fn db_vault_reserve_feerate ( db_path : & path:: Path ) -> Result < DbFeerate , DatabaseError > {
440+ let res: Option < DbFeerate > = db_query (
441+ db_path,
442+ "SELECT * FROM feerates ORDER BY last_update DESC LIMIT 1" ,
443+ [ ] ,
444+ |row| row. try_into ( ) ,
445+ ) ?
446+ . pop ( ) ;
447+
448+ match res {
449+ Some ( db_feerate) => Ok ( db_feerate) ,
450+ None => {
451+ return Err ( DatabaseError :: VaultReserveFeerateNotFound ( String :: from (
452+ "Feerates table not correctly initialised." ,
453+ ) ) )
454+ }
455+ }
456+ }
457+
415458// Create the db file with RW permissions only for the user
416459fn create_db_file ( db_path : & path:: Path ) -> Result < ( ) , DatabaseError > {
417460 let mut options = fs:: OpenOptions :: new ( ) ;
@@ -460,7 +503,19 @@ fn create_db(
460503 vec![ 0u8 ; 32 ] ,
461504 ] ,
462505 ) ?;
463-
506+ if network == Network :: Bitcoin {
507+ tx. execute (
508+ "INSERT INTO feerates (last_update, vault_reserve_feerate)
509+ VALUES (?1,?2)" ,
510+ params ! [ INIT_VAULT_RESERVE_HEIGHT , INIT_VAULT_RESERVE_FEERATE ] ,
511+ ) ?;
512+ } else {
513+ tx. execute (
514+ "INSERT INTO feerates (last_update, vault_reserve_feerate)
515+ VALUES (?1,?2)" ,
516+ params ! [ 0 , INIT_VAULT_RESERVE_FEERATE ] ,
517+ ) ?;
518+ }
464519 Ok ( ( ) )
465520 } )
466521}
@@ -547,7 +602,7 @@ mod tests {
547602 use super :: * ;
548603
549604 // Create a dummy database and return its path (to be deleted by the caller)
550- fn get_db ( ) -> path:: PathBuf {
605+ fn get_db ( network : Network ) -> path:: PathBuf {
551606 let db_path: path:: PathBuf =
552607 format ! ( "scratch_test_{:?}.sqlite3" , thread:: current( ) . id( ) ) . into ( ) ;
553608 let deposit_desc = DepositDescriptor :: from_str ( "wsh(multi(2,xpub6AHA9hZDN11k2ijHMeS5QqHx2KP9aMBRhTDqANMnwVtdyw2TDYRmF8PjpvwUFcL1Et8Hj59S3gTSMcUQ5gAqTz3Wd8EsMTmF3DChhqPQBnU/*,xpub6AaffFGfH6WXfm6pwWzmUMuECQnoLeB3agMKaLyEBZ5ZVfwtnS5VJKqXBt8o5ooCWVy2H87GsZshp7DeKE25eWLyd1Ccuh2ZubQUkgpiVux/*))#n3cj9mhy" ) . unwrap ( ) ;
@@ -557,14 +612,7 @@ mod tests {
557612 // Remove any potential leftover from a previous crashed session
558613 fs:: remove_file ( & db_path) . unwrap_or_else ( |_| ( ) ) ;
559614
560- setup_db (
561- & db_path,
562- & deposit_desc,
563- & unvault_desc,
564- & cpfp_desc,
565- Network :: Bitcoin ,
566- )
567- . unwrap ( ) ;
615+ setup_db ( & db_path, & deposit_desc, & unvault_desc, & cpfp_desc, network) . unwrap ( ) ;
568616
569617 db_path
570618 }
@@ -698,7 +746,7 @@ mod tests {
698746 // Sanity check we can create, delegate and delete a vault
699747 #[ test]
700748 fn db_vault_creation ( ) {
701- let db_path = get_db ( ) ;
749+ let db_path = get_db ( Network :: Bitcoin ) ;
702750 let outpoint_a = OutPoint :: from_str (
703751 "5bebdb97b54e2268b3fccd4aeea99419d87a92f88f27e906ceea5e863946a731:0" ,
704752 )
@@ -974,7 +1022,7 @@ mod tests {
9741022
9751023 #[ test]
9761024 fn db_tip_update ( ) {
977- let db_path = get_db ( ) ;
1025+ let db_path = get_db ( Network :: Bitcoin ) ;
9781026
9791027 let height = 21 ;
9801028 let hash =
@@ -997,4 +1045,32 @@ mod tests {
9971045 // Cleanup
9981046 fs:: remove_file ( & db_path) . unwrap ( ) ;
9991047 }
1048+
1049+ #[ test]
1050+ fn db_feerates_table ( ) {
1051+ let db_path = get_db ( Network :: Testnet ) ;
1052+ let vault_reserve_feerate = 1001 ;
1053+ let test_feerate = 1337 ;
1054+
1055+ let init_feerate = db_vault_reserve_feerate ( & db_path)
1056+ . unwrap ( )
1057+ . vault_reserve_feerate ;
1058+ assert_eq ! ( init_feerate, INIT_VAULT_RESERVE_FEERATE ) ;
1059+
1060+ for last_update in 1 ..=10 {
1061+ if last_update < 10 {
1062+ db_update_vault_reserve_feerate ( & db_path, last_update, vault_reserve_feerate)
1063+ . unwrap ( ) ;
1064+ } else {
1065+ db_update_vault_reserve_feerate ( & db_path, last_update, test_feerate) . unwrap ( ) ;
1066+ }
1067+ }
1068+
1069+ let row = db_vault_reserve_feerate ( & db_path) . unwrap ( ) ;
1070+
1071+ assert_eq ! ( row. last_update, 10 ) ;
1072+ assert_eq ! ( row. vault_reserve_feerate, test_feerate) ;
1073+
1074+ fs:: remove_file ( & db_path) . unwrap ( ) ;
1075+ }
10001076}
0 commit comments