Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve backend trait #348

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion api/src/owner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ where
) -> Result<Identifier, Error> {
let mut w_lock = self.wallet_inst.lock();
let w = w_lock.lc_provider()?.wallet_inst()?;
owner::create_account_path(&mut **w, keychain_mask, label)
owner::create_account_path(&mut **w, keychain_mask, label.to_string())
}

/// Sets the wallet's currently active account. This sets the
Expand Down
65 changes: 56 additions & 9 deletions impls/src/backends/lmdb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,13 +274,11 @@ where

/// Set parent path by account name
fn set_parent_key_id_by_name(&mut self, label: &str) -> Result<(), Error> {
let label = label.to_owned();
let res = self.acct_path_iter().find(|l| l.label == label);
if let Some(a) = res {
if let Some(a) = self.get_acct_path(label)? {
self.set_parent_key_id(a.path);
Ok(())
} else {
Err(ErrorKind::UnknownAccountLabel(label).into())
Err(ErrorKind::UnknownAccountLabel(label.to_string()).into())
}
}

Expand All @@ -302,17 +300,66 @@ where
.map_err(|e| e.into())
}

fn iter<'a>(&'a self) -> Box<dyn Iterator<Item = OutputData> + 'a> {
Box::new(self.db.iter(&[OUTPUT_PREFIX]).unwrap().map(|o| o.1))
fn iter<'a>(
&'a self,
parent_key_id: Option<&Identifier>,
tx_id: Option<u32>,
) -> Box<dyn Iterator<Item = OutputData> + 'a> {
let parent_key_id = parent_key_id.cloned();
Box::new(
self.db
.iter(&[OUTPUT_PREFIX])
.unwrap()
.map(|o: (_, OutputData)| o.1)
.filter(move |o| {
parent_key_id
.as_ref()
.map(|id| o.root_key_id == *id)
.unwrap_or(true)
})
.filter(move |o| tx_id.map(|id| o.tx_log_entry == Some(id)).unwrap_or(true)),
)
}

fn get_tx_log_entry(&self, u: &Uuid) -> Result<Option<TxLogEntry>, Error> {
let key = to_key(TX_LOG_ENTRY_PREFIX, &mut u.as_bytes().to_vec());
self.db.get_ser(&key).map_err(|e| e.into())
}

fn tx_log_iter<'a>(&'a self) -> Box<dyn Iterator<Item = TxLogEntry> + 'a> {
Box::new(self.db.iter(&[TX_LOG_ENTRY_PREFIX]).unwrap().map(|o| o.1))
fn tx_log_iter<'a>(
&'a self,
parent_key_id: Option<&Identifier>,
tx_id: Option<u32>,
tx_slate_id: Option<Uuid>,
outstanding_only: bool,
) -> Box<dyn Iterator<Item = TxLogEntry> + 'a> {
use crate::libwallet::TxLogEntryType::*;
let parent_key_id = parent_key_id.cloned();
Box::new(
self.db
.iter(&[TX_LOG_ENTRY_PREFIX])
.unwrap()
.map(|o: (_, TxLogEntry)| o.1)
.filter(move |tx| {
parent_key_id
.as_ref()
.map(|id| tx.parent_key_id == *id)
.unwrap_or(true)
})
.filter(move |tx| tx_id.map(|id| tx.id == id).unwrap_or(true))
.filter(move |tx| {
tx_slate_id
.map(|id| tx.tx_slate_id == Some(id))
.unwrap_or(true)
})
.filter(move |tx| {
if outstanding_only {
!tx.confirmed && (tx.tx_type == TxReceived || tx.tx_type == TxSent)
} else {
true
}
}),
)
}

fn get_private_context(
Expand Down Expand Up @@ -350,7 +397,7 @@ where
)
}

fn get_acct_path(&self, label: String) -> Result<Option<AcctPathMapping>, Error> {
fn get_acct_path(&self, label: &str) -> Result<Option<AcctPathMapping>, Error> {
let acct_key = to_key(ACCOUNT_PATH_MAPPING_PREFIX, &mut label.as_bytes().to_vec());
self.db.get_ser(&acct_key).map_err(|e| e.into())
}
Expand Down
2 changes: 1 addition & 1 deletion libwallet/src/api_impl/foreign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ where
check_ttl(w, &ret_slate)?;
let parent_key_id = match dest_acct_name {
Some(d) => {
let pm = w.get_acct_path(d.to_owned())?;
let pm = w.get_acct_path(d)?;
match pm {
Some(p) => p.path,
None => w.parent_key_id(),
Expand Down
8 changes: 4 additions & 4 deletions libwallet/src/api_impl/owner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ where
pub fn create_account_path<'a, T: ?Sized, C, K>(
w: &mut T,
keychain_mask: Option<&SecretKey>,
label: &str,
label: String,
) -> Result<Identifier, Error>
where
T: WalletBackend<'a, C, K>,
Expand Down Expand Up @@ -311,7 +311,7 @@ where
{
let parent_key_id = match args.src_acct_name {
Some(d) => {
let pm = w.get_acct_path(d)?;
let pm = w.get_acct_path(&d)?;
match pm {
Some(p) => p.path,
None => w.parent_key_id(),
Expand Down Expand Up @@ -411,7 +411,7 @@ where
{
let parent_key_id = match args.dest_acct_name {
Some(d) => {
let pm = w.get_acct_path(d)?;
let pm = w.get_acct_path(&d)?;
match pm {
Some(p) => p.path,
None => w.parent_key_id(),
Expand Down Expand Up @@ -473,7 +473,7 @@ where
check_ttl(w, &ret_slate)?;
let parent_key_id = match args.src_acct_name {
Some(d) => {
let pm = w.get_acct_path(d)?;
let pm = w.get_acct_path(&d)?;
match pm {
Some(p) => p.path,
None => w.parent_key_id(),
Expand Down
12 changes: 3 additions & 9 deletions libwallet/src/internal/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,28 +63,22 @@ where
pub fn new_acct_path<'a, T: ?Sized, C, K>(
wallet: &mut T,
keychain_mask: Option<&SecretKey>,
label: &str,
label: String,
) -> Result<Identifier, Error>
where
T: WalletBackend<'a, C, K>,
C: NodeClient + 'a,
K: Keychain + 'a,
{
let label = label.to_owned();
if wallet.acct_path_iter().any(|l| l.label == label) {
if wallet.get_acct_path(&label)?.is_some() {
return Err(ErrorKind::AccountLabelAlreadyExists(label).into());
}

// We're always using paths at m/k/0 for parent keys for output derivations
// so find the highest of those, then increment (to conform with external/internal
// derivation chains in BIP32 spec)

let highest_entry = wallet.acct_path_iter().max_by(|a, b| {
<u32>::from(a.path.to_path().path[0]).cmp(&<u32>::from(b.path.to_path().path[0]))
});

let return_id = {
if let Some(e) = highest_entry {
if let Some(e) = wallet.highest_acct_path() {
let mut p = e.path.to_path();
p.path[0] = ChildNumber::from(<u32>::from(p.path[0]) + 1);
p.to_identifier()
Expand Down
6 changes: 1 addition & 5 deletions libwallet/src/internal/selection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -539,11 +539,7 @@ where
{
// first find all eligible outputs based on number of confirmations
let mut eligible = wallet
.iter()
.filter(|out| {
out.root_key_id == *parent_key_id
&& out.eligible_to_spend(current_height, minimum_confirmations)
})
.eligible_outputs(parent_key_id, current_height, minimum_confirmations)
.collect::<Vec<OutputData>>();

let max_available = eligible.len();
Expand Down
82 changes: 14 additions & 68 deletions libwallet/src/internal/updater.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,26 +49,12 @@ where
K: Keychain + 'a,
{
// just read the wallet here, no need for a write lock
let mut outputs = wallet
.iter()
.filter(|out| show_spent || out.status != OutputStatus::Spent)
.collect::<Vec<_>>();

// only include outputs with a given tx_id if provided
if let Some(id) = tx_id {
outputs = outputs
.into_iter()
.filter(|out| out.tx_log_entry == Some(id))
.collect::<Vec<_>>();
}

if let Some(k) = parent_key_id {
outputs = outputs
.iter()
.filter(|o| o.root_key_id == *k)
.cloned()
.collect()
}
let mut outputs: Vec<_> = if show_spent {
wallet.iter(parent_key_id, tx_id).collect()
} else {
wallet.unspent_outputs(parent_key_id, tx_id).collect()
};

outputs.sort_by_key(|out| out.n_child);
let keychain = wallet.keychain(keychain_mask)?;
Expand Down Expand Up @@ -102,31 +88,8 @@ where
C: NodeClient + 'a,
K: Keychain + 'a,
{
let mut txs: Vec<TxLogEntry> = wallet
.tx_log_iter()
.filter(|tx_entry| {
let f_pk = match parent_key_id {
Some(k) => tx_entry.parent_key_id == *k,
None => true,
};
let f_tx_id = match tx_id {
Some(i) => tx_entry.id == i,
None => true,
};
let f_txs = match tx_slate_id {
Some(t) => tx_entry.tx_slate_id == Some(t),
None => true,
};
let f_outstanding = match outstanding_only {
true => {
!tx_entry.confirmed
&& (tx_entry.tx_type == TxLogEntryType::TxReceived
|| tx_entry.tx_type == TxLogEntryType::TxSent)
}
false => true,
};
f_pk && f_tx_id && f_txs && f_outstanding
})
let mut txs: Vec<_> = wallet
.tx_log_iter(parent_key_id, tx_id, tx_slate_id, outstanding_only)
.collect();
txs.sort_by_key(|tx| tx.creation_ts);
Ok(txs)
Expand Down Expand Up @@ -166,23 +129,12 @@ where
let mut wallet_outputs: HashMap<pedersen::Commitment, (Identifier, Option<u64>)> =
HashMap::new();
let keychain = wallet.keychain(keychain_mask)?;
let unspents: Vec<OutputData> = wallet
.iter()
.filter(|x| x.root_key_id == *parent_key_id && x.status != OutputStatus::Spent)
.collect();

let tx_entries = retrieve_txs(wallet, None, None, Some(&parent_key_id), true)?;

// Only select outputs that are actually involved in an outstanding transaction
let unspents: Vec<OutputData> = match update_all {
false => unspents
.into_iter()
.filter(|x| match x.tx_log_entry.as_ref() {
Some(t) => tx_entries.iter().any(|te| te.id == *t),
None => true,
})
.collect(),
true => unspents,
let unspents: Vec<_> = if update_all {
wallet.unspent_outputs(Some(parent_key_id), None).collect()
} else {
wallet.outstanding_outputs(Some(parent_key_id)).collect()
};

for out in unspents {
Expand Down Expand Up @@ -375,12 +327,8 @@ where
return Ok(());
}
let mut ids_to_del = vec![];
for out in wallet.iter() {
if out.status == OutputStatus::Unconfirmed
&& out.height > 0
&& out.height < height - 50
&& out.is_coinbase
{
for out in wallet.unconfirmed_outputs(None) {
if out.height > 0 && out.height < height - 50 && out.is_coinbase {
ids_to_del.push(out.key_id.clone())
}
}
Expand All @@ -405,9 +353,7 @@ where
K: Keychain + 'a,
{
let current_height = wallet.last_confirmed_height()?;
let outputs = wallet
.iter()
.filter(|out| out.root_key_id == *parent_key_id);
let outputs = wallet.iter(Some(parent_key_id), None);

let mut unspent_total = 0;
let mut immature_total = 0;
Expand Down
Loading