2021-06-29 00:04:12 -07:00
use crate ::chain ::{ Nf , NfRef } ;
2021-06-26 02:52:03 -07:00
use crate ::{ CTree , Witness } ;
use rusqlite ::{ params , Connection , OptionalExtension , NO_PARAMS } ;
use std ::collections ::HashMap ;
use zcash_primitives ::consensus ::{ NetworkUpgrade , Parameters } ;
use zcash_primitives ::merkle_tree ::IncrementalWitness ;
use zcash_primitives ::sapling ::{ Diversifier , Node , Note , Rseed } ;
2021-07-07 21:22:34 -07:00
use zcash_primitives ::zip32 ::{ ExtendedFullViewingKey , DiversifierIndex } ;
2021-06-26 02:52:03 -07:00
#[ allow(dead_code) ]
pub const DEFAULT_DB_PATH : & str = " zec.db " ;
2021-06-21 17:33:13 -07:00
pub struct DbAdapter {
2021-06-28 21:49:00 -07:00
pub connection : Connection ,
2021-06-21 17:33:13 -07:00
}
pub struct ReceivedNote {
2021-06-29 00:04:12 -07:00
pub account : u32 ,
2021-06-21 17:33:13 -07:00
pub height : u32 ,
pub output_index : u32 ,
pub diversifier : Vec < u8 > ,
pub value : u64 ,
pub rcm : Vec < u8 > ,
pub nf : Vec < u8 > ,
2021-06-24 05:08:20 -07:00
pub spent : Option < u32 > ,
}
pub struct SpendableNote {
2021-06-28 21:49:00 -07:00
pub id : u32 ,
2021-06-24 05:08:20 -07:00
pub note : Note ,
pub diversifier : Diversifier ,
pub witness : IncrementalWitness < Node > ,
2021-06-21 17:33:13 -07:00
}
impl DbAdapter {
pub fn new ( db_path : & str ) -> anyhow ::Result < DbAdapter > {
let connection = Connection ::open ( db_path ) ? ;
2021-06-26 02:52:03 -07:00
Ok ( DbAdapter { connection } )
2021-06-21 17:33:13 -07:00
}
pub fn init_db ( & self ) -> anyhow ::Result < ( ) > {
2021-06-26 02:52:03 -07:00
self . connection . execute (
" CREATE TABLE IF NOT EXISTS accounts (
2021-06-24 05:08:20 -07:00
id_account INTEGER PRIMARY KEY ,
2021-06-29 00:04:12 -07:00
name TEXT NOT NULL ,
seed TEXT ,
sk TEXT ,
ivk TEXT NOT NULL UNIQUE ,
2021-06-26 02:52:03 -07:00
address TEXT NOT NULL ) " ,
NO_PARAMS ,
) ? ;
2021-06-24 05:08:20 -07:00
2021-06-26 02:52:03 -07:00
self . connection . execute (
" CREATE TABLE IF NOT EXISTS blocks (
2021-06-21 17:33:13 -07:00
height INTEGER PRIMARY KEY ,
hash BLOB NOT NULL ,
2021-06-26 02:52:03 -07:00
timestamp INTEGER NOT NULL ,
sapling_tree BLOB NOT NULL ) " ,
NO_PARAMS ,
) ? ;
2021-06-21 17:33:13 -07:00
2021-06-26 02:52:03 -07:00
self . connection . execute (
" CREATE TABLE IF NOT EXISTS transactions (
2021-06-21 17:33:13 -07:00
id_tx INTEGER PRIMARY KEY ,
2021-06-29 00:04:12 -07:00
account INTEGER NOT NULL ,
2021-06-21 17:33:13 -07:00
txid BLOB NOT NULL UNIQUE ,
2021-06-26 02:52:03 -07:00
height INTEGER NOT NULL ,
timestamp INTEGER NOT NULL ,
value INTEGER NOT NULL ,
tx_index INTEGER ) " ,
NO_PARAMS ,
) ? ;
2021-06-21 17:33:13 -07:00
2021-06-26 02:52:03 -07:00
self . connection . execute (
" CREATE TABLE IF NOT EXISTS received_notes (
2021-06-21 17:33:13 -07:00
id_note INTEGER PRIMARY KEY ,
2021-06-29 00:04:12 -07:00
account INTEGER NOT NULL ,
2021-06-21 17:33:13 -07:00
position INTEGER NOT NULL ,
tx INTEGER NOT NULL ,
height INTEGER NOT NULL ,
output_index INTEGER NOT NULL ,
diversifier BLOB NOT NULL ,
value INTEGER NOT NULL ,
rcm BLOB NOT NULL ,
nf BLOB NOT NULL UNIQUE ,
spent INTEGER ,
2021-06-26 02:52:03 -07:00
CONSTRAINT tx_output UNIQUE ( tx , output_index ) ) " ,
NO_PARAMS ,
) ? ;
2021-06-21 17:33:13 -07:00
2021-06-26 02:52:03 -07:00
self . connection . execute (
" CREATE TABLE IF NOT EXISTS sapling_witnesses (
2021-06-21 17:33:13 -07:00
id_witness INTEGER PRIMARY KEY ,
note INTEGER NOT NULL ,
height INTEGER NOT NULL ,
witness BLOB NOT NULL ,
2021-06-26 02:52:03 -07:00
CONSTRAINT witness_height UNIQUE ( note , height ) ) " ,
NO_PARAMS ,
) ? ;
2021-06-24 05:08:20 -07:00
2021-07-07 21:22:34 -07:00
self . connection . execute (
" CREATE TABLE IF NOT EXISTS diversifiers (
account INTEGER PRIMARY KEY NOT NULL ,
diversifier_index BLOB NOT NULL ) " ,
NO_PARAMS ,
) ? ;
2021-06-24 05:08:20 -07:00
Ok ( ( ) )
}
2021-06-21 17:33:13 -07:00
2021-06-29 00:04:12 -07:00
pub fn store_account ( & self , name : & str , seed : Option < & str > , sk : Option < & str > , ivk : & str , address : & str ) -> anyhow ::Result < u32 > {
2021-06-26 02:52:03 -07:00
self . connection . execute (
2021-06-29 00:04:12 -07:00
" INSERT INTO accounts(name, seed, sk, ivk, address) VALUES (?1, ?2, ?3, ?4, ?5)
2021-06-26 02:52:03 -07:00
ON CONFLICT DO NOTHING " ,
2021-06-29 00:04:12 -07:00
params! [ name , seed , sk , ivk , address ] ,
2021-06-26 02:52:03 -07:00
) ? ;
2021-06-29 00:04:12 -07:00
let id_tx : u32 = self . connection . query_row (
" SELECT id_account FROM accounts WHERE sk = ?1 " ,
params! [ sk ] ,
| row | row . get ( 0 ) ,
) ? ;
Ok ( id_tx )
2021-06-21 17:33:13 -07:00
}
2021-06-29 00:04:12 -07:00
pub fn get_fvks ( & self ) -> anyhow ::Result < HashMap < u32 , String > > {
let mut statement = self . connection . prepare ( " SELECT id_account, ivk FROM accounts " ) ? ;
let rows = statement . query_map ( NO_PARAMS , | row | {
let account : u32 = row . get ( 0 ) ? ;
let ivk : String = row . get ( 1 ) ? ;
Ok ( ( account , ivk ) )
} ) ? ;
let mut fvks : HashMap < u32 , String > = HashMap ::new ( ) ;
for r in rows {
let row = r ? ;
fvks . insert ( row . 0 , row . 1 ) ;
}
Ok ( fvks )
2021-06-26 02:52:03 -07:00
}
2021-06-21 17:33:13 -07:00
pub fn trim_to_height ( & mut self , height : u32 ) -> anyhow ::Result < ( ) > {
let tx = self . connection . transaction ( ) ? ;
tx . execute ( " DELETE FROM blocks WHERE height >= ?1 " , params! [ height ] ) ? ;
2021-06-26 02:52:03 -07:00
tx . execute (
" DELETE FROM sapling_witnesses WHERE height >= ?1 " ,
params! [ height ] ,
) ? ;
tx . execute (
" DELETE FROM received_notes WHERE height >= ?1 " ,
params! [ height ] ,
) ? ;
tx . execute (
" DELETE FROM transactions WHERE height >= ?1 " ,
params! [ height ] ,
) ? ;
2021-06-21 17:33:13 -07:00
tx . commit ( ) ? ;
Ok ( ( ) )
}
2021-06-26 02:52:03 -07:00
pub fn store_block (
& self ,
height : u32 ,
hash : & [ u8 ] ,
timestamp : u32 ,
tree : & CTree ,
) -> anyhow ::Result < ( ) > {
log ::debug! ( " +block " ) ;
2021-06-21 17:33:13 -07:00
let mut bb : Vec < u8 > = vec! [ ] ;
tree . write ( & mut bb ) ? ;
2021-06-26 02:52:03 -07:00
self . connection . execute (
" INSERT INTO blocks(height, hash, timestamp, sapling_tree)
VALUES ( ? 1 , ? 2 , ? 3 , ? 4 )
ON CONFLICT DO NOTHING " ,
params! [ height , hash , timestamp , & bb ] ,
) ? ;
log ::debug! ( " -block " ) ;
2021-06-21 17:33:13 -07:00
Ok ( ( ) )
}
2021-06-26 02:52:03 -07:00
pub fn store_transaction (
& self ,
txid : & [ u8 ] ,
2021-06-29 00:04:12 -07:00
account : u32 ,
2021-06-26 02:52:03 -07:00
height : u32 ,
timestamp : u32 ,
tx_index : u32 ,
) -> anyhow ::Result < u32 > {
log ::debug! ( " +transaction " ) ;
self . connection . execute (
2021-06-29 00:04:12 -07:00
" INSERT INTO transactions(account, txid, height, timestamp, tx_index, value)
VALUES ( ? 1 , ? 2 , ? 3 , ? 4 , ? 5 , 0 )
2021-06-26 02:52:03 -07:00
ON CONFLICT DO NOTHING " ,
2021-06-29 00:04:12 -07:00
params! [ account , txid , height , timestamp , tx_index ] ,
2021-06-26 02:52:03 -07:00
) ? ;
let id_tx : u32 = self . connection . query_row (
" SELECT id_tx FROM transactions WHERE txid = ?1 " ,
params! [ txid ] ,
| row | row . get ( 0 ) ,
) ? ;
log ::debug! ( " -transaction {} " , id_tx ) ;
2021-06-21 17:33:13 -07:00
Ok ( id_tx )
}
2021-06-26 02:52:03 -07:00
pub fn store_received_note (
& self ,
note : & ReceivedNote ,
id_tx : u32 ,
position : usize ,
) -> anyhow ::Result < u32 > {
log ::debug! ( " +received_note {} " , id_tx ) ;
2021-06-29 00:04:12 -07:00
self . connection . execute ( " INSERT INTO received_notes(account, tx, height, position, output_index, diversifier, value, rcm, nf, spent)
VALUES ( ? 1 , ? 2 , ? 3 , ? 4 , ? 5 , ? 6 , ? 7 , ? 8 , ? 9 , ? 10 )
ON CONFLICT DO NOTHING " , params![note.account, id_tx, note.height, position as u32, note.output_index, note.diversifier, note.value as i64, note.rcm, note.nf, note.spent])?;
2021-06-26 02:52:03 -07:00
let id_note : u32 = self . connection . query_row (
" SELECT id_note FROM received_notes WHERE tx = ?1 AND output_index = ?2 " ,
params! [ id_tx , note . output_index ] ,
| row | row . get ( 0 ) ,
) ? ;
log ::debug! ( " -received_note " ) ;
2021-06-21 17:33:13 -07:00
Ok ( id_note )
}
2021-06-26 02:52:03 -07:00
pub fn store_witnesses (
& self ,
witness : & Witness ,
height : u32 ,
id_note : u32 ,
) -> anyhow ::Result < ( ) > {
log ::debug! ( " +witnesses " ) ;
2021-06-21 17:33:13 -07:00
let mut bb : Vec < u8 > = vec! [ ] ;
witness . write ( & mut bb ) ? ;
2021-06-26 02:52:03 -07:00
self . connection . execute (
" INSERT INTO sapling_witnesses(note, height, witness) VALUES (?1, ?2, ?3)
ON CONFLICT DO NOTHING " ,
params! [ id_note , height , bb ] ,
) ? ;
log ::debug! ( " -witnesses " ) ;
Ok ( ( ) )
}
pub fn add_value ( & self , id_tx : u32 , value : i64 ) -> anyhow ::Result < ( ) > {
self . connection . execute (
" UPDATE transactions SET value = value + ?2 WHERE id_tx = ?1 " ,
params! [ id_tx , value ] ,
) ? ;
2021-06-21 17:33:13 -07:00
Ok ( ( ) )
}
2021-06-29 00:04:12 -07:00
pub fn get_received_note_value ( & self , nf : & Nf ) -> anyhow ::Result < ( u32 , i64 ) > {
let ( account , value ) = self . connection . query_row (
" SELECT account, value FROM received_notes WHERE nf = ?1 " ,
2021-06-26 02:52:03 -07:00
params! [ nf . 0. to_vec ( ) ] ,
2021-06-29 00:04:12 -07:00
| row | {
let account : u32 = row . get ( 0 ) ? ;
let value : i64 = row . get ( 1 ) ? ;
Ok ( ( account , value ) )
} ,
2021-06-26 02:52:03 -07:00
) ? ;
2021-06-29 00:04:12 -07:00
Ok ( ( account , value ) )
2021-06-26 02:52:03 -07:00
}
2021-06-29 00:04:12 -07:00
pub fn get_balance ( & self , account : u32 ) -> anyhow ::Result < u64 > {
2021-06-26 02:52:03 -07:00
let balance : Option < i64 > = self . connection . query_row (
2021-06-29 00:04:12 -07:00
" SELECT SUM(value) FROM received_notes WHERE (spent IS NULL OR spent = 0) AND account = ?1 " ,
params! [ account ] ,
2021-06-26 02:52:03 -07:00
| row | row . get ( 0 ) ,
) ? ;
Ok ( balance . unwrap_or ( 0 ) as u64 )
}
2021-06-29 00:04:12 -07:00
pub fn get_spendable_balance ( & self , account : u32 , anchor_height : u32 ) -> anyhow ::Result < u64 > {
2021-06-26 02:52:03 -07:00
let balance : Option < i64 > = self . connection . query_row (
2021-06-29 00:04:12 -07:00
" SELECT SUM(value) FROM received_notes WHERE spent IS NULL AND height <= ?1 AND account = ?2 " ,
params! [ anchor_height , account ] ,
2021-06-26 02:52:03 -07:00
| row | row . get ( 0 ) ,
) ? ;
2021-06-24 05:08:20 -07:00
Ok ( balance . unwrap_or ( 0 ) as u64 )
2021-06-21 17:33:13 -07:00
}
2021-06-24 05:08:20 -07:00
pub fn get_last_sync_height ( & self ) -> anyhow ::Result < Option < u32 > > {
2021-06-26 02:52:03 -07:00
let height : Option < u32 > =
self . connection
. query_row ( " SELECT MAX(height) FROM blocks " , NO_PARAMS , | row | {
row . get ( 0 )
} ) ? ;
2021-06-24 05:08:20 -07:00
Ok ( height )
}
pub fn get_db_height ( & self ) -> anyhow ::Result < u32 > {
let height : u32 = self . get_last_sync_height ( ) ? . unwrap_or_else ( | | {
crate ::NETWORK
. activation_height ( NetworkUpgrade ::Sapling )
. unwrap ( )
. into ( )
} ) ;
2021-06-21 17:33:13 -07:00
Ok ( height )
}
2021-06-26 02:52:03 -07:00
pub fn get_db_hash ( & self , height : u32 ) -> anyhow ::Result < Option < [ u8 ; 32 ] > > {
let hash : Option < Vec < u8 > > = self . connection . query_row ( " SELECT hash FROM blocks WHERE height = ?1 " , params! [ height ] , | row | row . get ( 0 ) ) . optional ( ) ? ;
Ok ( hash . map ( | h | {
let mut hash = [ 0 u8 ; 32 ] ;
hash . copy_from_slice ( & h ) ;
hash
} ) )
}
2021-06-21 17:33:13 -07:00
pub fn get_tree ( & self ) -> anyhow ::Result < ( CTree , Vec < Witness > ) > {
let res = self . connection . query_row (
" SELECT height, sapling_tree FROM blocks WHERE height = (SELECT MAX(height) FROM blocks) " ,
2021-06-24 05:08:20 -07:00
NO_PARAMS , | row | {
2021-06-21 17:33:13 -07:00
let height : u32 = row . get ( 0 ) ? ;
let tree : Vec < u8 > = row . get ( 1 ) ? ;
Ok ( ( height , tree ) )
} ) . optional ( ) ? ;
Ok ( match res {
Some ( ( height , tree ) ) = > {
let tree = CTree ::read ( & * tree ) ? ;
let mut statement = self . connection . prepare (
2021-06-29 00:04:12 -07:00
" SELECT id_note, witness FROM sapling_witnesses w, received_notes n WHERE w.height = ?1 AND w.note = n.id_note AND (n.spent IS NULL OR n.spent = 0) " ) ? ;
2021-06-21 17:33:13 -07:00
let ws = statement . query_map ( params! [ height ] , | row | {
let id_note : u32 = row . get ( 0 ) ? ;
2021-06-28 21:49:00 -07:00
let witness : Vec < u8 > = row . get ( 1 ) ? ;
Ok ( Witness ::read ( id_note , & * witness ) . unwrap ( ) )
2021-06-21 17:33:13 -07:00
} ) ? ;
let mut witnesses : Vec < Witness > = vec! [ ] ;
for w in ws {
witnesses . push ( w ? ) ;
}
( tree , witnesses )
2021-06-26 02:52:03 -07:00
}
None = > ( CTree ::new ( ) , vec! [ ] ) ,
2021-06-21 17:33:13 -07:00
} )
}
2021-06-24 05:08:20 -07:00
2021-06-29 00:04:12 -07:00
pub fn get_nullifiers ( & self ) -> anyhow ::Result < HashMap < Nf , NfRef > > {
2021-06-26 02:52:03 -07:00
let mut statement = self
. connection
2021-06-29 00:04:12 -07:00
. prepare ( " SELECT id_note, account, nf FROM received_notes WHERE spent IS NULL OR spent = 0 " ) ? ;
2021-06-24 05:08:20 -07:00
let nfs_res = statement . query_map ( NO_PARAMS , | row | {
let id_note : u32 = row . get ( 0 ) ? ;
2021-06-29 00:04:12 -07:00
let account : u32 = row . get ( 1 ) ? ;
let nf_vec : Vec < u8 > = row . get ( 2 ) ? ;
2021-06-24 05:08:20 -07:00
let mut nf = [ 0 u8 ; 32 ] ;
nf . clone_from_slice ( & nf_vec ) ;
2021-06-29 00:04:12 -07:00
let nf_ref = NfRef {
id_note ,
2021-07-07 21:22:34 -07:00
account ,
2021-06-29 00:04:12 -07:00
} ;
Ok ( ( nf_ref , nf ) )
2021-06-24 05:08:20 -07:00
} ) ? ;
2021-06-29 00:04:12 -07:00
let mut nfs : HashMap < Nf , NfRef > = HashMap ::new ( ) ;
2021-06-24 05:08:20 -07:00
for n in nfs_res {
let n = n ? ;
nfs . insert ( Nf ( n . 1 ) , n . 0 ) ;
}
Ok ( nfs )
}
2021-06-29 00:04:12 -07:00
pub fn get_nullifier_amounts ( & self , account : u32 ) -> anyhow ::Result < HashMap < Vec < u8 > , u64 > > {
2021-06-26 02:52:03 -07:00
let mut statement = self
. connection
2021-06-29 00:04:12 -07:00
. prepare ( " SELECT value, nf FROM received_notes WHERE account = ?1 AND (spent IS NULL OR spent = 0) " ) ? ;
let nfs_res = statement . query_map ( params! [ account ] , | row | {
2021-06-26 02:52:03 -07:00
let amount : i64 = row . get ( 0 ) ? ;
let nf : Vec < u8 > = row . get ( 1 ) ? ;
Ok ( ( amount , nf ) )
} ) ? ;
let mut nfs : HashMap < Vec < u8 > , u64 > = HashMap ::new ( ) ;
for n in nfs_res {
let n = n ? ;
nfs . insert ( n . 1 , n . 0 as u64 ) ;
}
Ok ( nfs )
}
pub fn get_spendable_notes (
& self ,
2021-06-29 00:04:12 -07:00
account : u32 ,
2021-06-26 02:52:03 -07:00
anchor_height : u32 ,
fvk : & ExtendedFullViewingKey ,
) -> anyhow ::Result < Vec < SpendableNote > > {
2021-06-24 05:08:20 -07:00
let mut statement = self . connection . prepare (
2021-06-29 00:04:12 -07:00
" SELECT id_note, diversifier, value, rcm, witness FROM received_notes r, sapling_witnesses w WHERE spent IS NULL AND account = ?2
2021-06-24 05:08:20 -07:00
AND w . height = (
SELECT MAX ( height ) FROM sapling_witnesses WHERE height < = ? 1
) AND r . id_note = w . note " )?;
2021-06-29 00:04:12 -07:00
let notes = statement . query_map ( params! [ anchor_height , account ] , | row | {
2021-06-28 21:49:00 -07:00
let id_note : u32 = row . get ( 0 ) ? ;
let diversifier : Vec < u8 > = row . get ( 1 ) ? ;
let value : i64 = row . get ( 2 ) ? ;
let rcm : Vec < u8 > = row . get ( 3 ) ? ;
let witness : Vec < u8 > = row . get ( 4 ) ? ;
2021-06-24 05:08:20 -07:00
let mut diversifer_bytes = [ 0 u8 ; 11 ] ;
diversifer_bytes . copy_from_slice ( & diversifier ) ;
let diversifier = Diversifier ( diversifer_bytes ) ;
let mut rcm_bytes = [ 0 u8 ; 32 ] ;
rcm_bytes . copy_from_slice ( & rcm ) ;
let rcm = jubjub ::Fr ::from_bytes ( & rcm_bytes ) . unwrap ( ) ;
let rseed = Rseed ::BeforeZip212 ( rcm ) ;
let witness = IncrementalWitness ::< Node > ::read ( & * witness ) . unwrap ( ) ;
let pa = fvk . fvk . vk . to_payment_address ( diversifier ) . unwrap ( ) ;
let note = pa . create_note ( value as u64 , rseed ) . unwrap ( ) ;
Ok ( SpendableNote {
2021-06-28 21:49:00 -07:00
id : id_note ,
2021-06-24 05:08:20 -07:00
note ,
diversifier ,
2021-06-26 02:52:03 -07:00
witness ,
2021-06-24 05:08:20 -07:00
} )
} ) ? ;
let mut spendable_notes : Vec < SpendableNote > = vec! [ ] ;
for n in notes {
spendable_notes . push ( n ? ) ;
}
Ok ( spendable_notes )
}
pub fn mark_spent ( & self , id : u32 , height : u32 ) -> anyhow ::Result < ( ) > {
2021-06-26 02:52:03 -07:00
log ::debug! ( " +mark_spent " ) ;
self . connection . execute (
" UPDATE received_notes SET spent = ?1 WHERE id_note = ?2 " ,
params! [ height , id ] ,
) ? ;
log ::debug! ( " -mark_spent " ) ;
2021-06-24 05:08:20 -07:00
Ok ( ( ) )
}
2021-06-29 00:04:12 -07:00
pub fn get_backup ( & self , account : u32 ) -> anyhow ::Result < ( Option < String > , Option < String > , String ) > {
log ::debug! ( " +get_backup " ) ;
let ( seed , sk , ivk ) = self . connection . query_row (
" SELECT seed, sk, ivk FROM accounts WHERE id_account = ?1 " ,
2021-06-28 21:49:00 -07:00
params! [ account ] ,
| row | {
2021-06-29 00:04:12 -07:00
let seed : Option < String > = row . get ( 0 ) ? ;
let sk : Option < String > = row . get ( 0 ) ? ;
2021-06-28 21:49:00 -07:00
let ivk : String = row . get ( 0 ) ? ;
2021-06-29 00:04:12 -07:00
Ok ( ( seed , sk , ivk ) )
2021-06-28 21:49:00 -07:00
} ,
) ? ;
2021-06-29 00:04:12 -07:00
log ::debug! ( " -get_backup " ) ;
Ok ( ( seed , sk , ivk ) )
2021-06-28 21:49:00 -07:00
}
2021-06-24 05:08:20 -07:00
pub fn get_sk ( & self , account : u32 ) -> anyhow ::Result < String > {
2021-06-29 00:04:12 -07:00
log ::info! ( " +get_sk " ) ;
let sk = self . connection . query_row (
2021-06-26 02:52:03 -07:00
" SELECT sk FROM accounts WHERE id_account = ?1 " ,
params! [ account ] ,
| row | {
2021-06-29 00:04:12 -07:00
let sk : String = row . get ( 0 ) ? ;
Ok ( sk )
2021-06-26 02:52:03 -07:00
} ,
) ? ;
2021-06-29 00:04:12 -07:00
log ::info! ( " -get_sk " ) ;
Ok ( sk )
2021-06-24 05:08:20 -07:00
}
pub fn get_ivk ( & self , account : u32 ) -> anyhow ::Result < String > {
2021-06-26 02:52:03 -07:00
log ::debug! ( " +get_ivk " ) ;
let ivk = self . connection . query_row (
" SELECT ivk FROM accounts WHERE id_account = ?1 " ,
params! [ account ] ,
| row | {
let ivk : String = row . get ( 0 ) ? ;
Ok ( ivk )
} ,
) ? ;
log ::debug! ( " -get_ivk " ) ;
2021-06-24 05:08:20 -07:00
Ok ( ivk )
}
2021-07-07 21:22:34 -07:00
pub fn get_diversifier ( & self , account : u32 ) -> anyhow ::Result < DiversifierIndex > {
let diversifier_index = self . connection . query_row (
" SELECT diversifier_index FROM diversifiers WHERE account = ?1 " ,
params! [ account ] ,
| row | {
let d : Vec < u8 > = row . get ( 0 ) ? ;
let mut div = [ 0 u8 ; 11 ] ;
div . copy_from_slice ( & d ) ;
Ok ( div )
}
) . optional ( ) ? . unwrap_or_else ( | | [ 0 u8 ; 11 ] ) ;
Ok ( DiversifierIndex ( diversifier_index ) )
}
pub fn store_diversifier ( & self , account : u32 , diversifier_index : & DiversifierIndex ) -> anyhow ::Result < ( ) > {
let diversifier_bytes = diversifier_index . 0. to_vec ( ) ;
self . connection . execute (
" INSERT INTO diversifiers(account, diversifier_index) VALUES (?1, ?2) ON CONFLICT \
( account ) DO UPDATE SET diversifier_index = excluded . diversifier_index " ,
params! [ account , diversifier_bytes ] ) ? ;
Ok ( ( ) )
}
2021-06-21 17:33:13 -07:00
}
#[ cfg(test) ]
mod tests {
2021-06-26 02:52:03 -07:00
use crate ::db ::{ DbAdapter , ReceivedNote , DEFAULT_DB_PATH } ;
use crate ::{ CTree , Witness } ;
2021-06-21 17:33:13 -07:00
#[ test ]
fn test_db ( ) {
2021-06-26 02:52:03 -07:00
let mut db = DbAdapter ::new ( DEFAULT_DB_PATH ) . unwrap ( ) ;
2021-06-21 17:33:13 -07:00
db . init_db ( ) . unwrap ( ) ;
db . trim_to_height ( 0 ) . unwrap ( ) ;
2021-06-26 02:52:03 -07:00
db . store_block ( 1 , & [ 0 u8 ; 32 ] , 0 , & CTree ::new ( ) ) . unwrap ( ) ;
2021-06-29 00:04:12 -07:00
let id_tx = db . store_transaction ( & [ 0 ; 32 ] , 1 , 1 , 0 , 20 ) . unwrap ( ) ;
2021-06-26 02:52:03 -07:00
db . store_received_note (
& ReceivedNote {
2021-06-29 00:04:12 -07:00
account : 1 ,
2021-06-26 02:52:03 -07:00
height : 1 ,
output_index : 0 ,
diversifier : vec ! [ ] ,
value : 0 ,
rcm : vec ! [ ] ,
nf : vec ! [ ] ,
spent : None ,
} ,
id_tx ,
5 ,
)
2021-06-29 00:04:12 -07:00
. unwrap ( ) ;
2021-06-21 17:33:13 -07:00
let witness = Witness {
position : 10 ,
id_note : 0 ,
note : None ,
tree : CTree ::new ( ) ,
filled : vec ! [ ] ,
cursor : CTree ::new ( ) ,
} ;
db . store_witnesses ( & witness , 1000 , 1 ) . unwrap ( ) ;
}
#[ test ]
fn test_balance ( ) {
2021-06-26 02:52:03 -07:00
let db = DbAdapter ::new ( DEFAULT_DB_PATH ) . unwrap ( ) ;
2021-06-29 00:04:12 -07:00
let balance = db . get_balance ( 1 ) . unwrap ( ) ;
2021-06-21 17:33:13 -07:00
println! ( " {} " , balance ) ;
}
}