Only create 1 received tx log entry on restore (#2378)

* restore only creates 1 received tx

* restore child index sanity output
This commit is contained in:
Yeastplume 2019-01-14 16:49:34 +00:00 committed by GitHub
parent 9a497f1439
commit 5d257283bd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -45,6 +45,18 @@ struct OutputResult {
pub blinding: SecretKey, pub blinding: SecretKey,
} }
#[derive(Debug, Clone)]
/// Collect stats in case we want to just output a single tx log entry
/// for restored non-coinbase outputs
struct RestoredTxStats {
///
pub log_id: u32,
///
pub amount_credited: u64,
///
pub num_outputs: usize,
}
fn identify_utxo_outputs<T, C, K>( fn identify_utxo_outputs<T, C, K>(
wallet: &mut T, wallet: &mut T,
outputs: Vec<(pedersen::Commitment, pedersen::RangeProof, bool, u64, u64)>, outputs: Vec<(pedersen::Commitment, pedersen::RangeProof, bool, u64, u64)>,
@ -136,6 +148,7 @@ fn restore_missing_output<T, C, K>(
wallet: &mut T, wallet: &mut T,
output: OutputResult, output: OutputResult,
found_parents: &mut HashMap<Identifier, u32>, found_parents: &mut HashMap<Identifier, u32>,
tx_stats: &mut Option<&mut HashMap<Identifier, RestoredTxStats>>,
) -> Result<(), Error> ) -> Result<(), Error>
where where
T: WalletBackend<C, K>, T: WalletBackend<C, K>,
@ -148,21 +161,48 @@ where
let parent_key_id = output.key_id.parent_path(); let parent_key_id = output.key_id.parent_path();
if !found_parents.contains_key(&parent_key_id) { if !found_parents.contains_key(&parent_key_id) {
found_parents.insert(parent_key_id.clone(), 0); found_parents.insert(parent_key_id.clone(), 0);
if let Some(ref mut s) = tx_stats {
s.insert(
parent_key_id.clone(),
RestoredTxStats {
log_id: batch.next_tx_log_id(&parent_key_id)?,
amount_credited: 0,
num_outputs: 0,
},
);
}
} }
let log_id = batch.next_tx_log_id(&parent_key_id)?; let log_id = if tx_stats.is_none() || output.is_coinbase {
let entry_type = match output.is_coinbase { let log_id = batch.next_tx_log_id(&parent_key_id)?;
true => TxLogEntryType::ConfirmedCoinbase, let entry_type = match output.is_coinbase {
false => TxLogEntryType::TxReceived, true => TxLogEntryType::ConfirmedCoinbase,
false => TxLogEntryType::TxReceived,
};
let mut t = TxLogEntry::new(parent_key_id.clone(), entry_type, log_id);
t.confirmed = true;
t.amount_credited = output.value;
t.num_outputs = 1;
t.update_confirmation_ts();
batch.save_tx_log_entry(t, &parent_key_id)?;
log_id
} else {
if let Some(ref mut s) = tx_stats {
let ts = s.get(&parent_key_id).unwrap().clone();
s.insert(
parent_key_id.clone(),
RestoredTxStats {
log_id: ts.log_id,
amount_credited: ts.amount_credited + output.value,
num_outputs: ts.num_outputs + 1,
},
);
ts.log_id
} else {
0
}
}; };
let mut t = TxLogEntry::new(parent_key_id.clone(), entry_type, log_id);
t.confirmed = true;
t.amount_credited = output.value;
t.num_outputs = 1;
t.update_confirmation_ts();
batch.save_tx_log_entry(t, &parent_key_id)?;
let _ = batch.save(OutputData { let _ = batch.save(OutputData {
root_key_id: parent_key_id.clone(), root_key_id: parent_key_id.clone(),
key_id: output.key_id, key_id: output.key_id,
@ -292,7 +332,7 @@ where
Restoring.", Restoring.",
m.value, m.key_id, m.commit, m.value, m.key_id, m.commit,
); );
restore_missing_output(wallet, m, &mut found_parents)?; restore_missing_output(wallet, m, &mut found_parents, &mut None)?;
} }
// Unlock locked outputs // Unlock locked outputs
@ -330,24 +370,19 @@ where
// restore labels, account paths and child derivation indices // restore labels, account paths and child derivation indices
let label_base = "account"; let label_base = "account";
let mut index = 1; let mut acct_index = 1;
for (path, max_child_index) in found_parents.iter() { for (path, max_child_index) in found_parents.iter() {
if *path == ExtKeychain::derive_key_id(2, 0, 0, 0, 0) { // default path already exists
//default path already exists if *path != ExtKeychain::derive_key_id(2, 0, 0, 0, 0) {
continue; let label = format!("{}_{}", label_base, acct_index);
}
let res = wallet.acct_path_iter().find(|e| e.path == *path);
if let None = res {
let label = format!("{}_{}", label_base, index);
keys::set_acct_path(wallet, &label, path)?; keys::set_acct_path(wallet, &label, path)?;
index = index + 1; acct_index += 1;
}
{
let mut batch = wallet.batch()?;
batch.save_child_index(path, max_child_index + 1)?;
} }
let mut batch = wallet.batch()?;
debug!("Next child for account {} is {}", path, max_child_index + 1);
batch.save_child_index(path, max_child_index + 1)?;
batch.commit()?;
} }
Ok(()) Ok(())
} }
@ -375,27 +410,43 @@ where
); );
let mut found_parents: HashMap<Identifier, u32> = HashMap::new(); let mut found_parents: HashMap<Identifier, u32> = HashMap::new();
// Now save what we have let mut restore_stats = HashMap::new();
// Now save what we have
for output in result_vec { for output in result_vec {
restore_missing_output(wallet, output, &mut found_parents)?; restore_missing_output(
wallet,
output,
&mut found_parents,
&mut Some(&mut restore_stats),
)?;
} }
// restore labels, account paths and child derivation indices // restore labels, account paths and child derivation indices
let label_base = "account"; let label_base = "account";
let mut index = 1; let mut acct_index = 1;
for (path, max_child_index) in found_parents.iter() { for (path, max_child_index) in found_parents.iter() {
if *path == ExtKeychain::derive_key_id(2, 0, 0, 0, 0) { // default path already exists
//default path already exists if *path != ExtKeychain::derive_key_id(2, 0, 0, 0, 0) {
continue; let label = format!("{}_{}", label_base, acct_index);
keys::set_acct_path(wallet, &label, path)?;
acct_index += 1;
} }
let label = format!("{}_{}", label_base, index); // restore tx log entry for non-coinbase outputs
keys::set_acct_path(wallet, &label, path)?; if let Some(s) = restore_stats.get(path) {
index = index + 1;
{
let mut batch = wallet.batch()?; let mut batch = wallet.batch()?;
batch.save_child_index(path, max_child_index + 1)?; let mut t = TxLogEntry::new(path.clone(), TxLogEntryType::TxReceived, s.log_id);
t.confirmed = true;
t.amount_credited = s.amount_credited;
t.num_outputs = s.num_outputs;
t.update_confirmation_ts();
batch.save_tx_log_entry(t, &path)?;
batch.commit()?;
} }
let mut batch = wallet.batch()?;
batch.save_child_index(path, max_child_index + 1)?;
debug!("Next child for account {} is {}", path, max_child_index + 1);
batch.commit()?;
} }
Ok(()) Ok(())
} }