Change check_repair + certain functions to lock more granularly (#252)

* Rename check-repair -> scan, make lock logic more granular

* rustfmt

* update owner api implementations where to allow granular locking where required

* rustfmt

* store init state on startup to determine whether full utxo scan is required for new wallets

* rustfmt

* fix for init status persist

* add start height argument to scan

* rustfmt
This commit is contained in:
Yeastplume
2019-11-06 10:04:42 +00:00
committed by GitHub
parent c518f35c8d
commit 021c34bf89
19 changed files with 415 additions and 932 deletions
+35 -30
View File
@@ -21,7 +21,6 @@ use std::io::{Read, Write};
use std::marker::PhantomData;
use std::path::Path;
use failure::ResultExt;
use uuid::Uuid;
use crate::blake2::blake2b::{Blake2b, Blake2bResult};
@@ -31,10 +30,9 @@ use crate::store::{self, option_to_not_found, to_key, to_key_u64};
use crate::core::core::Transaction;
use crate::core::ser;
use crate::libwallet::{check_repair, restore};
use crate::libwallet::{
AcctPathMapping, Context, Error, ErrorKind, NodeClient, OutputData, ScannedBlockInfo,
TxLogEntry, WalletBackend, WalletOutputBatch,
TxLogEntry, WalletBackend, WalletInitStatus, WalletOutputBatch,
};
use crate::util::secp::constants::SECRET_KEY_SIZE;
use crate::util::secp::key::SecretKey;
@@ -55,6 +53,8 @@ const TX_LOG_ID_PREFIX: u8 = 'i' as u8;
const ACCOUNT_PATH_MAPPING_PREFIX: u8 = 'a' as u8;
const LAST_SCANNED_BLOCK: u8 = 'l' as u8;
const LAST_SCANNED_KEY: &str = "LAST_SCANNED_KEY";
const WALLET_INIT_STATUS: u8 = 'w' as u8;
const WALLET_INIT_STATUS_KEY: &str = "WALLET_INIT_STATUS";
/// test to see if database files exist in the current directory. If so,
/// use a DB backend for all operations
@@ -397,6 +397,14 @@ where
}))
}
fn batch_no_mask<'a>(&'a mut self) -> Result<Box<dyn WalletOutputBatch<K> + 'a>, Error> {
Ok(Box::new(Batch {
_store: self,
db: RefCell::new(Some(self.db.batch()?)),
keychain: None,
}))
}
fn current_child_index<'a>(&mut self, parent_key_id: &Identifier) -> Result<u32, Error> {
let index = {
let batch = self.db.batch()?;
@@ -460,33 +468,17 @@ where
Ok(last_scanned_block)
}
fn restore(
&mut self,
keychain_mask: Option<&SecretKey>,
to_height: u64,
) -> Result<Option<ScannedBlockInfo>, Error> {
let res = restore(self, keychain_mask, to_height).context(ErrorKind::Restore)?;
Ok(res)
}
fn check_repair(
&mut self,
keychain_mask: Option<&SecretKey>,
delete_unconfirmed: bool,
start_height: u64,
end_height: u64,
status_fn: fn(&str),
) -> Result<ScannedBlockInfo, Error> {
let res = check_repair(
self,
keychain_mask,
delete_unconfirmed,
start_height,
end_height,
status_fn,
)
.context(ErrorKind::Restore)?;
Ok(res)
fn init_status<'a>(&mut self) -> Result<WalletInitStatus, Error> {
let batch = self.db.batch()?;
let init_status_key = to_key(
WALLET_INIT_STATUS,
&mut WALLET_INIT_STATUS_KEY.as_bytes().to_vec(),
);
let status = match batch.get_ser(&init_status_key)? {
Some(s) => s,
None => WalletInitStatus::InitComplete,
};
Ok(status)
}
}
@@ -618,6 +610,19 @@ where
Ok(())
}
fn save_init_status(&mut self, value: WalletInitStatus) -> Result<(), Error> {
let init_status_key = to_key(
WALLET_INIT_STATUS,
&mut WALLET_INIT_STATUS_KEY.as_bytes().to_vec(),
);
self.db
.borrow()
.as_ref()
.unwrap()
.put_ser(&init_status_key, &value)?;
Ok(())
}
fn save_child_index(&mut self, parent_id: &Identifier, child_n: u32) -> Result<(), Error> {
let deriv_key = to_key(DERIV_PREFIX, &mut parent_id.to_bytes().to_vec());
self.db
+12 -3
View File
@@ -19,7 +19,9 @@ use crate::config::{
};
use crate::core::global;
use crate::keychain::Keychain;
use crate::libwallet::{Error, ErrorKind, NodeClient, WalletBackend, WalletLCProvider};
use crate::libwallet::{
Error, ErrorKind, NodeClient, WalletBackend, WalletInitStatus, WalletLCProvider,
};
use crate::lifecycle::seed::WalletSeed;
use crate::util::secp::key::SecretKey;
use crate::util::ZeroingString;
@@ -181,9 +183,9 @@ where
return Err(ErrorKind::WalletSeedExists(msg))?;
}
}
let _ = WalletSeed::init_file(&data_dir_name, mnemonic_length, mnemonic, password);
let _ = WalletSeed::init_file(&data_dir_name, mnemonic_length, mnemonic.clone(), password);
info!("Wallet seed file created");
let _wallet: LMDBBackend<'a, C, K> =
let mut wallet: LMDBBackend<'a, C, K> =
match LMDBBackend::new(&data_dir_name, self.node_client.clone()) {
Err(e) => {
let msg = format!("Error creating wallet: {}, Data Dir: {}", e, &data_dir_name);
@@ -192,6 +194,13 @@ where
}
Ok(d) => d,
};
// Save init status of this wallet, to determine whether it needs a full UTXO scan
let mut batch = wallet.batch_no_mask()?;
match mnemonic {
Some(_) => batch.save_init_status(WalletInitStatus::InitNeedsScanning)?,
None => batch.save_init_status(WalletInitStatus::InitNoScanning)?,
};
batch.commit()?;
info!("Wallet database backend created at {}", data_dir_name);
Ok(())
}
+1 -3
View File
@@ -243,10 +243,8 @@ where
C: NodeClient + 'a,
K: keychain::Keychain + 'a,
{
let mut w_lock = wallet.lock();
let w = w_lock.lc_provider()?.wallet_inst()?;
let (wallet_refreshed, wallet_info) =
owner::retrieve_summary_info(&mut **w, keychain_mask, true, 1)?;
owner::retrieve_summary_info(wallet, keychain_mask, true, 1)?;
assert!(wallet_refreshed);
Ok(wallet_info)
}