Revert "Merge branch 'master' into master"

This reverts commit a63f2c7cea, reversing
changes made to d774272fee.
This commit is contained in:
Gary Yu 2019-04-25 14:59:45 +08:00
parent a63f2c7cea
commit e509405b8a
No known key found for this signature in database
GPG key ID: 6607CD196EE6647D
17 changed files with 26 additions and 772 deletions

View file

@ -1,9 +1,9 @@
[![Build Status](https://img.shields.io/travis/gottstech/grin-wallet/master.svg)](https://travis-ci.org/gottstech/grin-wallet)
[![Coverage Status](https://img.shields.io/codecov/c/github/gottstech/grin-wallet/master.svg)](https://codecov.io/gh/gottstech/grin-wallet)
[![Build Status](https://img.shields.io/travis/mimblewimble/grin-wallet/master.svg)](https://travis-ci.org/mimblewimble/grin-wallet)
[![Coverage Status](https://img.shields.io/codecov/c/github/mimblewimble/grin-wallet/master.svg)](https://codecov.io/gh/mimblewimble/grin-wallet)
[![Chat](https://img.shields.io/gitter/room/grin_community/Lobby.svg)](https://gitter.im/grin_community/Lobby)
[![Support](https://img.shields.io/badge/support-on%20gitter-brightgreen.svg)](https://gitter.im/grin_community/support)
[![Documentation Wiki](https://img.shields.io/badge/doc-wiki-blue.svg)](https://github.com/mimblewimble/docs/wiki)
[![Release Version](https://img.shields.io/github/release/gottstech/grin-wallet.svg)](https://github.com/gottstech/grin-wallet/releases)
[![License](https://img.shields.io/github/license/gottstech/grin-wallet.svg)](https://github.com/gottstech/grin-wallet/blob/master/LICENSE)
[![Release Version](https://img.shields.io/github/release/mimblewimble/grin-wallet.svg)](https://github.com/mimblewimble/grin-wallet/releases)
[![License](https://img.shields.io/github/license/mimblewimble/grin-wallet.svg)](https://github.com/mimblewimble/grin-wallet/blob/master/LICENSE)
# Grin Wallet

View file

@ -24,11 +24,9 @@ use crate::core::core::Transaction;
use crate::impls::{HTTPWalletCommAdapter, KeybaseWalletCommAdapter};
use crate::keychain::{Identifier, Keychain};
use crate::libwallet::api_impl::owner;
use crate::libwallet::slate::Slate;
use crate::libwallet::types::{
AcctPathMapping, Error, ErrorKind, InitTxArgs, NodeClient, NodeHeightResult, OutputCommitMapping,
PaymentCommitMapping, Slate, TxLogEntry, WalletBackend, WalletInfo,
use crate::libwallet::{
AcctPathMapping, Error, ErrorKind, InitTxArgs, NodeClient, NodeHeightResult,
OutputCommitMapping, Slate, TxLogEntry, WalletBackend, WalletInfo,
};
/// Main interface into all wallet API functions.
@ -304,56 +302,6 @@ where
res
}
/// Returns a list of payment outputs from the active account in the wallet.
///
/// # Arguments
/// * `refresh_from_node` - If true, the wallet will attempt to contact
/// a node (via the [`NodeClient`](../grin_wallet_libwallet/types/trait.NodeClient.html)
/// provided during wallet instantiation). If `false`, the results will
/// contain output information that may be out-of-date (from the last time
/// the wallet's output set was refreshed against the node).
/// * `tx_id` - If `Some(i)`, only return the outputs associated with
/// the transaction log entry of id `i`.
///
/// # Returns
/// * `(bool, Vec<PaymentCommitMapping>)` - A tuple:
/// * The first `bool` element indicates whether the data was successfully
/// refreshed from the node (note this may be false even if the `refresh_from_node`
/// argument was set to `true`.
/// * The second element contains a vector of
/// [PaymentCommitMapping](../grin_wallet_libwallet/types/struct.PaymentCommitMapping.html)
/// of which each element is a mapping between the wallet's internal
/// [PaymentData](../grin_wallet_libwallet/types/struct.Output.html)
/// and the Output commitment
///
/// # Example
/// Set up as in [`new`](struct.Owner.html#method.new) method above.
/// ```
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
///
/// let api_owner = Owner::new(wallet.clone());
/// let update_from_node = true;
/// let tx_id = None;
///
/// let result = api_owner.retrieve_payments(update_from_node, tx_id);
///
/// if let Ok((was_updated, payment_mappings)) = result {
/// //...
/// }
/// ```
pub fn retrieve_payments(
&self,
refresh_from_node: bool,
tx_id: Option<Uuid>,
) -> Result<(bool, Vec<PaymentCommitMapping>), Error> {
let mut w = self.wallet.lock();
w.open_with_credentials()?;
let res = owner::retrieve_payments(&mut *w, refresh_from_node, tx_id);
w.close()?;
res
}
/// Returns a list of [Transaction Log Entries](../grin_wallet_libwallet/types/struct.TxLogEntry.html)
/// from the active account in the wallet.
///

View file

@ -160,7 +160,6 @@ pub trait OwnerRpc {
"mmr_index": null,
"n_child": 0,
"root_key_id": "0200000000000000000000000000000000",
"slate_id": null,
"status": "Unspent",
"tx_log_entry": 0,
"value": "60000000000"
@ -177,7 +176,6 @@ pub trait OwnerRpc {
"mmr_index": null,
"n_child": 1,
"root_key_id": "0200000000000000000000000000000000",
"slate_id": null,
"status": "Unspent",
"tx_log_entry": 1,
"value": "60000000000"

View file

@ -433,20 +433,6 @@ pub fn outputs(
Ok(())
}
pub fn payments(
wallet: Arc<Mutex<WalletInst<impl NodeClient + 'static, keychain::ExtKeychain>>>,
g_args: &GlobalArgs,
dark_scheme: bool,
) -> Result<(), Error> {
controller::owner_single_use(wallet.clone(), |api| {
let res = api.node_height()?;
let (validated, outputs) = api.retrieve_payments(true, None)?;
display::payments(&g_args.account, res.height, validated, outputs, dark_scheme)?;
Ok(())
})?;
Ok(())
}
/// Txs command args
pub struct TxsArgs {
pub id: Option<u32>,
@ -476,22 +462,8 @@ pub fn txs(
let (_, outputs) = api.retrieve_outputs(true, false, args.id)?;
display::outputs(&g_args.account, res.height, validated, outputs, dark_scheme)?;
// should only be one here, but just in case
for tx in &txs {
let (_, outputs) = api.retrieve_payments(true, tx.tx_slate_id)?;
if outputs.len() > 0 {
display::payments(
&g_args.account,
res.height,
validated,
outputs,
dark_scheme,
)?;
}
}
// should only be one here, but just in case
for tx in &txs {
display::tx_messages(tx, dark_scheme)?;
for tx in txs {
display::tx_messages(&tx, dark_scheme)?;
}
};
Ok(())

View file

@ -14,10 +14,8 @@
use crate::core::core::{self, amount_to_hr_string};
use crate::core::global;
use crate::libwallet::types::{
AcctPathMapping, Error, OutputCommitMapping, OutputStatus, PaymentCommitMapping, TxLogEntry,
WalletInfo,
use crate::libwallet::{
AcctPathMapping, Error, OutputCommitMapping, OutputStatus, TxLogEntry, WalletInfo,
};
use crate::util;
use prettytable;
@ -120,89 +118,6 @@ pub fn outputs(
Ok(())
}
/// Display payments in a pretty way
pub fn payments(
account: &str,
cur_height: u64,
validated: bool,
outputs: Vec<PaymentCommitMapping>,
dark_background_color_scheme: bool,
) -> Result<(), Error> {
let title = format!(
"Wallet Payments - Account '{}' - Block Height: {}",
account, cur_height
);
println!();
let mut t = term::stdout().unwrap();
t.fg(term::color::MAGENTA).unwrap();
writeln!(t, "{}", title).unwrap();
t.reset().unwrap();
let mut table = table!();
table.set_titles(row![
bMG->"Output Commitment",
bMG->"Block Height",
bMG->"Locked Until",
bMG->"Status",
bMG->"# Confirms",
bMG->"Value",
bMG->"Shared Transaction Id"
]);
for payment in outputs {
let commit = format!("{}", util::to_hex(payment.commit.as_ref().to_vec()));
let out = payment.output;
let height = format!("{}", out.height);
let lock_height = format!("{}", out.lock_height);
let status = format!("{}", out.status);
let num_confirmations = format!("{}", out.num_confirmations(cur_height));
let value = if out.value == 0 {
"unknown".to_owned()
} else {
format!("{}", core::amount_to_hr_string(out.value, false))
};
let slate_id = format!("{}", out.slate_id);
if dark_background_color_scheme {
table.add_row(row![
bFC->commit,
bFB->height,
bFB->lock_height,
bFR->status,
bFB->num_confirmations,
bFG->value,
bFC->slate_id,
]);
} else {
table.add_row(row![
bFD->commit,
bFB->height,
bFB->lock_height,
bFR->status,
bFB->num_confirmations,
bFG->value,
bFD->slate_id,
]);
}
}
table.set_format(*prettytable::format::consts::FORMAT_NO_COLSEP);
table.printstd();
println!();
if !validated {
println!(
"\nWARNING: Wallet failed to verify data. \
The above is from local cache and possibly invalid! \
(is your `grin server` offline or broken?)"
);
}
Ok(())
}
/// Display transaction log in a pretty way
pub fn txs(
account: &str,

View file

@ -429,16 +429,6 @@ fn tx_rollback(test_dir: &str) -> Result<(), libwallet::Error> {
assert_eq!(output_mappings.len(), 3);
assert_eq!(locked_count, 2);
assert_eq!(unconfirmed_count, 1);
// check the payments are as expected
unconfirmed_count = 0;
let (_, payments) = api.retrieve_payments(false, tx.unwrap().tx_slate_id)?;
for p in &payments {
if p.output.status == OutputStatus::Unconfirmed {
unconfirmed_count = unconfirmed_count + 1;
}
}
assert_eq!(payments.len(), 1);
assert_eq!(unconfirmed_count, 1);
Ok(())
})?;
@ -459,16 +449,6 @@ fn tx_rollback(test_dir: &str) -> Result<(), libwallet::Error> {
}
assert_eq!(outputs.len(), 1);
assert_eq!(unconfirmed_count, 1);
// check the payments are as expected: receiver don't have this.
unconfirmed_count = 0;
let (_, payments) = api.retrieve_payments(false, tx.unwrap().tx_slate_id)?;
for p in &payments {
if p.output.status == OutputStatus::Unconfirmed {
unconfirmed_count = unconfirmed_count + 1;
}
}
assert_eq!(payments.len(), 0);
assert_eq!(unconfirmed_count, 0);
let (refreshed, wallet2_info) = api.retrieve_summary_info(true, 1)?;
assert!(refreshed);
assert_eq!(wallet2_info.amount_currently_spendable, 0,);

View file

@ -42,8 +42,6 @@ pub const DB_DIR: &'static str = "db";
pub const TX_SAVE_DIR: &'static str = "saved_txs";
const OUTPUT_PREFIX: u8 = 'o' as u8;
const PAYMENT_PREFIX: u8 = 'P' as u8;
const PAYMENT_COMMITS_PREFIX: u8 = 'Q' as u8;
const DERIV_PREFIX: u8 = 'd' as u8;
const CONFIRMED_HEIGHT_PREFIX: u8 = 'c' as u8;
const PRIVATE_TX_CONTEXT_PREFIX: u8 = 'p' as u8;
@ -240,20 +238,6 @@ where
Box::new(self.db.iter(&[OUTPUT_PREFIX]).unwrap())
}
fn get_payment_log_commits(&self, u: &Uuid) -> Result<Option<PaymentCommits>, Error> {
let key = to_key(PAYMENT_COMMITS_PREFIX, &mut u.as_bytes().to_vec());
self.db.get_ser(&key).map_err(|e| e.into())
}
fn get_payment_log_entry(&self, commit: String) -> Result<Option<PaymentData>, Error> {
let key = to_key(PAYMENT_PREFIX, &mut commit.as_bytes().to_vec());
self.db.get_ser(&key).map_err(|e| e.into())
}
fn payment_log_iter<'a>(&'a self) -> Box<dyn Iterator<Item = PaymentData> + 'a> {
Box::new(self.db.iter(&[PAYMENT_PREFIX]).unwrap())
}
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())
@ -396,7 +380,7 @@ where
}
fn save(&mut self, out: OutputData) -> Result<(), Error> {
// Save the self output data to the db.
// Save the output data to the db.
{
let key = match out.mmr_index {
Some(i) => to_key_u64(OUTPUT_PREFIX, &mut out.key_id.to_bytes().to_vec(), i),
@ -408,27 +392,6 @@ where
Ok(())
}
fn save_payment_commits(&mut self, u: &Uuid, commits: PaymentCommits) -> Result<(), Error> {
// Save the payment commits list data to the db.
{
let key = to_key(PAYMENT_COMMITS_PREFIX, &mut u.as_bytes().to_vec());
self.db.borrow().as_ref().unwrap().put_ser(&key, &commits)?;
}
Ok(())
}
fn save_payment(&mut self, out: PaymentData) -> Result<(), Error> {
// Save the payment output data to the db.
{
let commit = out.commit.clone();
let key = to_key(PAYMENT_PREFIX, &mut commit.as_bytes().to_vec());
self.db.borrow().as_ref().unwrap().put_ser(&key, &out)?;
}
Ok(())
}
fn get(&self, id: &Identifier, mmr_index: &Option<u64>) -> Result<OutputData, Error> {
let key = match mmr_index {
Some(i) => to_key_u64(OUTPUT_PREFIX, &mut id.to_bytes().to_vec(), *i),
@ -441,24 +404,6 @@ where
.map_err(|e| e.into())
}
fn get_payment_commits(&self, u: &Uuid) -> Result<PaymentCommits, Error> {
let key = to_key(PAYMENT_COMMITS_PREFIX, &mut u.as_bytes().to_vec());
option_to_not_found(
self.db.borrow().as_ref().unwrap().get_ser(&key),
&format!("slate_id: {}", u.to_string()),
)
.map_err(|e| e.into())
}
fn get_payment_log_entry(&self, commit: String) -> Result<PaymentData, Error> {
let key = to_key(PAYMENT_PREFIX, &mut commit.as_bytes().to_vec());
option_to_not_found(
self.db.borrow().as_ref().unwrap().get_ser(&key),
&format!("key: {:?}", commit),
)
.map_err(|e| e.into())
}
fn iter(&self) -> Box<dyn Iterator<Item = OutputData>> {
Box::new(
self.db

View file

@ -45,8 +45,6 @@ pub const DB_DIR: &'static str = "db";
pub const TX_SAVE_DIR: &'static str = "saved_txs";
const OUTPUT_PREFIX: u8 = 'o' as u8;
const PAYMENT_PREFIX: u8 = 'P' as u8;
const PAYMENT_COMMITS_PREFIX: u8 = 'Q' as u8;
const DERIV_PREFIX: u8 = 'd' as u8;
const CONFIRMED_HEIGHT_PREFIX: u8 = 'c' as u8;
const PRIVATE_TX_CONTEXT_PREFIX: u8 = 'p' as u8;
@ -243,20 +241,6 @@ where
Box::new(self.db.iter(&[OUTPUT_PREFIX]).unwrap().map(|o| o.1))
}
fn get_payment_log_commits(&self, u: &Uuid) -> Result<Option<PaymentCommits>, Error> {
let key = to_key(PAYMENT_COMMITS_PREFIX, &mut u.as_bytes().to_vec());
self.db.get_ser(&key).map_err(|e| e.into())
}
fn get_payment_log_entry(&self, commit: String) -> Result<Option<PaymentData>, Error> {
let key = to_key(PAYMENT_PREFIX, &mut commit.as_bytes().to_vec());
self.db.get_ser(&key).map_err(|e| e.into())
}
fn payment_log_iter<'a>(&'a self) -> Box<dyn Iterator<Item = PaymentData> + 'a> {
Box::new(self.db.iter(&[PAYMENT_PREFIX]).unwrap().map(|o| o.1))
}
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())
@ -404,7 +388,7 @@ where
}
fn save(&mut self, out: OutputData) -> Result<(), Error> {
// Save the self output data to the db.
// Save the output data to the db.
{
let key = match out.mmr_index {
Some(i) => to_key_u64(OUTPUT_PREFIX, &mut out.key_id.to_bytes().to_vec(), i),
@ -416,27 +400,6 @@ where
Ok(())
}
fn save_payment_commits(&mut self, u: &Uuid, commits: PaymentCommits) -> Result<(), Error> {
// Save the payment commits list data to the db.
{
let key = to_key(PAYMENT_COMMITS_PREFIX, &mut u.as_bytes().to_vec());
self.db.borrow().as_ref().unwrap().put_ser(&key, &commits)?;
}
Ok(())
}
fn save_payment(&mut self, out: PaymentData) -> Result<(), Error> {
// Save the payment output data to the db.
{
let commit = out.commit.clone();
let key = to_key(PAYMENT_PREFIX, &mut commit.as_bytes().to_vec());
self.db.borrow().as_ref().unwrap().put_ser(&key, &out)?;
}
Ok(())
}
fn get(&self, id: &Identifier, mmr_index: &Option<u64>) -> Result<OutputData, Error> {
let key = match mmr_index {
Some(i) => to_key_u64(OUTPUT_PREFIX, &mut id.to_bytes().to_vec(), *i),
@ -449,24 +412,6 @@ where
.map_err(|e| e.into())
}
fn get_payment_commits(&self, u: &Uuid) -> Result<PaymentCommits, Error> {
let key = to_key(PAYMENT_COMMITS_PREFIX, &mut u.as_bytes().to_vec());
option_to_not_found(
self.db.borrow().as_ref().unwrap().get_ser(&key),
&format!("slate_id: {}", u.to_string()),
)
.map_err(|e| e.into())
}
fn get_payment_log_entry(&self, commit: String) -> Result<PaymentData, Error> {
let key = to_key(PAYMENT_PREFIX, &mut commit.as_bytes().to_vec());
option_to_not_found(
self.db.borrow().as_ref().unwrap().get_ser(&key),
&format!("key: {:?}", commit),
)
.map_err(|e| e.into())
}
fn iter(&self) -> Box<dyn Iterator<Item = OutputData>> {
Box::new(
self.db

View file

@ -24,11 +24,9 @@ use crate::grin_util;
use crate::grin_keychain::{Identifier, Keychain};
use crate::internal::{keys, selection, tx, updater};
use crate::slate::Slate;
use crate::types::{
AcctPathMapping, NodeClient, TxLogEntry, TxWrapper, WalletBackend, WalletInfo,
};
use crate::types::{AcctPathMapping, NodeClient, TxLogEntry, TxWrapper, WalletBackend, WalletInfo};
use crate::{Error, ErrorKind};
use crate::{InitTxArgs, NodeHeightResult, OutputCommitMapping, PaymentCommitMapping};
use crate::{InitTxArgs, NodeHeightResult, OutputCommitMapping};
const USER_MESSAGE_MAX_LEN: usize = 256;
@ -83,29 +81,10 @@ where
Ok((
validated,
updater::retrieve_outputs(&mut *w, include_spent, tx_id, None, Some(&parent_key_id))?,
updater::retrieve_outputs(&mut *w, include_spent, tx_id, Some(&parent_key_id))?,
))
}
/// Returns a list of payment outputs from the active account in the wallet.
pub fn retrieve_payments<T: ?Sized, C, K>(
w: &mut T,
refresh_from_node: bool,
tx_id: Option<Uuid>,
) -> Result<(bool, Vec<PaymentCommitMapping>), Error>
where
T: WalletBackend<C, K>,
C: NodeClient,
K: Keychain,
{
let mut validated = false;
if refresh_from_node {
validated = update_outputs(w, false);
}
Ok((validated, updater::retrieve_payments(w, tx_id)?))
}
/// Retrieve txs
pub fn retrieve_txs<T: ?Sized, C, K>(
w: &mut T,

View file

@ -215,7 +215,6 @@ where
lock_height: output.lock_height,
is_coinbase: output.is_coinbase,
tx_log_entry: Some(log_id),
slate_id: None,
});
let max_child_index = found_parents.get(&parent_key_id).unwrap().clone();
@ -284,7 +283,7 @@ where
// Now, get all outputs owned by this wallet (regardless of account)
let wallet_outputs = {
let res = updater::retrieve_outputs(&mut *wallet, true, None, None, None)?;
let res = updater::retrieve_outputs(&mut *wallet, true, None, None)?;
res
};

View file

@ -155,7 +155,6 @@ where
lock_height: 0,
is_coinbase: false,
tx_log_entry: Some(log_id),
slate_id: Some(slate_id.clone()),
})?;
}
batch.save_tx_log_entry(t.clone(), &parent_key_id)?;
@ -225,7 +224,6 @@ where
lock_height: 0,
is_coinbase: false,
tx_log_entry: Some(log_id),
slate_id: Some(slate_id),
})?;
batch.save_tx_log_entry(t, &parent_key_id)?;
batch.commit()?;

View file

@ -17,14 +17,10 @@
use uuid::Uuid;
use crate::grin_keychain::{Identifier, Keychain};
use crate::grin_util::secp::pedersen;
use crate::grin_util::to_hex;
use crate::grin_util::Mutex;
use crate::internal::{selection, updater};
use crate::slate::Slate;
use crate::types::{
Context, NodeClient, OutputStatus, PaymentCommits, PaymentData, TxLogEntryType, WalletBackend,
};
use crate::types::{Context, NodeClient, TxLogEntryType, WalletBackend};
use crate::{Error, ErrorKind};
/// static for incrementing test UUIDs
@ -224,63 +220,6 @@ where
)?;
// Final transaction can be built by anyone at this stage
slate.finalize(wallet.keychain())?;
let parent_key_id = Some(&context.parent_key_id);
// Get the change output/s from database
let changes = updater::retrieve_outputs(wallet, false, None, Some(slate.id), parent_key_id)?;
let change_commits = changes
.iter()
.map(|oc| oc.commit.clone())
.collect::<Vec<pedersen::Commitment>>();
// Find the payment output/s
let mut outputs: Vec<pedersen::Commitment> = Vec::new();
for output in slate.tx.outputs() {
if !change_commits.contains(&output.commit) {
outputs.insert(0, output.commit.clone());
}
}
// sender save the payment output
let mut batch = wallet.batch()?;
batch.save_payment_commits(
&slate.id,
PaymentCommits {
commits: outputs
.iter()
.map(|c| to_hex(c.as_ref().to_vec()))
.collect::<Vec<String>>(),
slate_id: slate.id,
},
)?;
// todo: multiple receivers transaction
if outputs.len() > 1 {
for output in outputs {
let payment_output = to_hex(output.clone().as_ref().to_vec());
batch.save_payment(PaymentData {
commit: payment_output,
value: 0, // '0' means unknown here, since '0' value is impossible for an output.
status: OutputStatus::Unconfirmed,
height: slate.height,
lock_height: 0,
slate_id: slate.id,
})?;
}
} else if outputs.len() == 1 {
let payment_output = to_hex(outputs.first().clone().unwrap().as_ref().to_vec());
batch.save_payment(PaymentData {
commit: payment_output,
value: slate.amount,
status: OutputStatus::Unconfirmed,
height: slate.height,
lock_height: 0,
slate_id: slate.id,
})?;
} else {
warn!("complete_tx - no 'payment' output! is this a sending to self for test purpose?");
}
batch.commit()?;
Ok(())
}
@ -314,7 +253,7 @@ where
return Err(ErrorKind::TransactionNotCancellable(tx_id_string))?;
}
// get outputs associated with tx
let res = updater::retrieve_outputs(wallet, false, Some(tx.id), None, Some(&parent_key_id))?;
let res = updater::retrieve_outputs(wallet, false, Some(tx.id), Some(&parent_key_id))?;
let outputs = res.iter().map(|m| m.output.clone()).collect();
updater::cancel_tx_and_outputs(wallet, tx, outputs, parent_key_id)?;
Ok(())

View file

@ -30,14 +30,13 @@ use crate::internal::keys;
use crate::types::{
NodeClient, OutputData, OutputStatus, TxLogEntry, TxLogEntryType, WalletBackend, WalletInfo,
};
use crate::{BlockFees, CbData, OutputCommitMapping, PaymentCommitMapping};
use crate::{BlockFees, CbData, OutputCommitMapping};
/// Retrieve all of the self outputs (doesn't attempt to update from node)
/// Retrieve all of the outputs (doesn't attempt to update from node)
pub fn retrieve_outputs<T: ?Sized, C, K>(
wallet: &mut T,
show_spent: bool,
tx_id: Option<u32>,
slate_id: Option<Uuid>,
parent_key_id: Option<&Identifier>,
) -> Result<Vec<OutputCommitMapping>, Error>
where
@ -59,14 +58,6 @@ where
.collect::<Vec<_>>();
}
// only include outputs with a given slate_id if provided
if let Some(id) = slate_id {
outputs = outputs
.into_iter()
.filter(|out| out.slate_id == Some(id))
.collect::<Vec<_>>();
}
if let Some(k) = parent_key_id {
outputs = outputs
.iter()
@ -91,38 +82,6 @@ where
Ok(res)
}
/// Retrieve all of the payment outputs (doesn't attempt to update from node)
pub fn retrieve_payments<T: ?Sized, C, K>(
wallet: &mut T,
tx_id: Option<Uuid>,
) -> Result<Vec<PaymentCommitMapping>, Error>
where
T: WalletBackend<C, K>,
C: NodeClient,
K: Keychain,
{
// just read the wallet here, no need for a write lock
let mut outputs = wallet.payment_log_iter().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.slate_id == id)
.collect::<Vec<_>>();
}
let res = outputs
.into_iter()
.map(|output| {
let commit =
pedersen::Commitment::from_vec(util::from_hex(output.commit.clone()).unwrap());
PaymentCommitMapping { output, commit }
})
.collect();
Ok(res)
}
/// Retrieve all of the transaction entries, or a particular entry
/// if `parent_key_id` is set, only return entries from that key
pub fn retrieve_txs<T: ?Sized, C, K>(
@ -332,21 +291,6 @@ where
t.confirmed = true;
batch.save_tx_log_entry(t, &parent_key_id)?;
}
// if there's a related payment output being confirmed, refresh that payment log
if let Some(slate_id) = output.slate_id {
if let Ok(commits) = batch.get_payment_commits(&slate_id) {
for commit in commits.commits {
if let Ok(mut payment) =
batch.get_payment_log_entry(commit.clone())
{
payment.height = o.1;
payment.mark_confirmed();
batch.save_payment(payment)?;
}
}
}
}
}
output.height = o.1;
output.mark_unspent();
@ -469,7 +413,6 @@ where
locked_total += out.value;
}
OutputStatus::Spent => {}
OutputStatus::Confirmed => {}
}
}
@ -547,7 +490,6 @@ where
lock_height: lock_height,
is_coinbase: true,
tx_log_entry: None,
slate_id: None,
})?;
batch.commit()?;
}

View file

@ -85,19 +85,10 @@ where
/// return the parent path
fn parent_key_id(&mut self) -> Identifier;
/// Iterate over all self output data stored by the backend
/// Iterate over all output data stored by the backend
fn iter<'a>(&'a self) -> Box<dyn Iterator<Item = OutputData> + 'a>;
/// Get payment commits list by slate id
fn get_payment_log_commits(&self, u: &Uuid) -> Result<Option<PaymentCommits>, Error>;
/// Get payment output data by commit
fn get_payment_log_entry(&self, commit: String) -> Result<Option<PaymentData>, Error>;
/// Iterate over all payment output data stored by the backend
fn payment_log_iter<'a>(&'a self) -> Box<dyn Iterator<Item = PaymentData> + 'a>;
/// Get self owned output data by id
/// Get output data by id
fn get(&self, id: &Identifier, mmr_index: &Option<u64>) -> Result<OutputData, Error>;
/// Get an (Optional) tx log entry by uuid
@ -149,24 +140,12 @@ where
/// Return the keychain being used
fn keychain(&mut self) -> &mut K;
/// Add or update data about a self owned output to the backend
/// Add or update data about an output to the backend
fn save(&mut self, out: OutputData) -> Result<(), Error>;
/// Add or update data about a payment output to the backend
fn save_payment(&mut self, out: PaymentData) -> Result<(), Error>;
/// Add or update data about a payment commits list to the backend
fn save_payment_commits(&mut self, u: &Uuid, commits: PaymentCommits) -> Result<(), Error>;
/// Gets self owned output data by id
/// Gets output data by id
fn get(&self, id: &Identifier, mmr_index: &Option<u64>) -> Result<OutputData, Error>;
/// Gets payment commits list by slate id
fn get_payment_commits(&self, u: &Uuid) -> Result<PaymentCommits, Error>;
/// Gets payment output data by commit
fn get_payment_log_entry(&self, commit: String) -> Result<PaymentData, Error>;
/// Iterate over all output data stored by the backend
fn iter(&self) -> Box<dyn Iterator<Item = OutputData>>;
@ -291,8 +270,6 @@ pub struct OutputData {
pub is_coinbase: bool,
/// Optional corresponding internal entry in tx entry log
pub tx_log_entry: Option<u32>,
/// Unique transaction ID, selected by sender
pub slate_id: Option<Uuid>,
}
impl ser::Writeable for OutputData {
@ -369,94 +346,6 @@ impl OutputData {
}
}
}
/// Information about a payment output that's being tracked by the wallet.
/// It belongs to the receiver, and it's paid by this wallet.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
pub struct PaymentData {
/// The actual commit
pub commit: String,
/// Value of the output
pub value: u64,
/// Current status of the output
pub status: OutputStatus,
/// Height of the output
pub height: u64,
/// Height we are locked until
pub lock_height: u64,
/// Unique transaction ID, selected by sender
pub slate_id: Uuid,
}
impl ser::Writeable for PaymentData {
fn write<W: ser::Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
writer.write_bytes(&serde_json::to_vec(self).map_err(|_| ser::Error::CorruptedData)?)
}
}
impl ser::Readable for PaymentData {
fn read(reader: &mut dyn ser::Reader) -> Result<PaymentData, ser::Error> {
let data = reader.read_bytes_len_prefix()?;
serde_json::from_slice(&data[..]).map_err(|_| ser::Error::CorruptedData)
}
}
impl PaymentData {
/// How many confirmations has this output received?
/// If height == 0 then we are either Unconfirmed or the output was
/// cut-through
/// so we do not actually know how many confirmations this output had (and
/// never will).
pub fn num_confirmations(&self, current_height: u64) -> u64 {
if self.height > current_height {
return 0;
}
if self.status == OutputStatus::Unconfirmed {
0
} else {
// if an output has height n and we are at block n
// then we have a single confirmation (the block it originated in)
1 + (current_height - self.height)
}
}
/// Marks this output as confirmed if it was previously unconfirmed
pub fn mark_confirmed(&mut self) {
match self.status {
OutputStatus::Unconfirmed => self.status = OutputStatus::Confirmed,
_ => (),
}
}
}
/// Information about the payment commit/s in one tx that's being tracked by the wallet.
/// They belong to the receiver/s, and they're paid by this wallet.
///
/// Note: because lmdb can't have multiple keys to same value, we have to use this to find
/// the commit lists by the slate id, in case we support multiple receivers in one tx in the future.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct PaymentCommits {
/// The actual commit/s
pub commits: Vec<String>,
/// Unique transaction ID, selected by sender
pub slate_id: Uuid,
}
impl ser::Writeable for PaymentCommits {
fn write<W: ser::Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
writer.write_bytes(&serde_json::to_vec(self).map_err(|_| ser::Error::CorruptedData)?)
}
}
impl ser::Readable for PaymentCommits {
fn read(reader: &mut dyn ser::Reader) -> Result<PaymentCommits, ser::Error> {
let data = reader.read_bytes_len_prefix()?;
serde_json::from_slice(&data[..]).map_err(|_| ser::Error::CorruptedData)
}
}
/// Status of an output that's being tracked by the wallet. Can either be
/// unconfirmed, spent, unspent, or locked (when it's been used to generate
/// a transaction but we don't have confirmation that the transaction was
@ -471,8 +360,6 @@ pub enum OutputStatus {
Locked,
/// Spent
Spent,
/// Confirmed
Confirmed,
}
impl fmt::Display for OutputStatus {
@ -482,7 +369,6 @@ impl fmt::Display for OutputStatus {
OutputStatus::Unspent => write!(f, "Unspent"),
OutputStatus::Locked => write!(f, "Locked"),
OutputStatus::Spent => write!(f, "Spent"),
OutputStatus::Confirmed => write!(f, "Confirmed"),
}
}
}
@ -811,181 +697,3 @@ pub struct TxWrapper {
/// hex representation of transaction
pub tx_hex: String,
}
// Types to facilitate API arguments and serialization
/// Send TX API Args
// TODO: This is here to ensure the legacy V1 API remains intact
// remove this when v1 api is removed
#[derive(Clone, Serialize, Deserialize)]
pub struct SendTXArgs {
/// amount to send
pub amount: u64,
/// minimum confirmations
pub minimum_confirmations: u64,
/// payment method
pub method: String,
/// destination url
pub dest: String,
/// Max number of outputs
pub max_outputs: usize,
/// Number of change outputs to generate
pub num_change_outputs: usize,
/// whether to use all outputs (combine)
pub selection_strategy_is_use_all: bool,
/// Optional message, that will be signed
pub message: Option<String>,
/// Optional slate version to target when sending
pub target_slate_version: Option<u16>,
}
/// V2 Init / Send TX API Args
#[derive(Clone, Serialize, Deserialize)]
pub struct InitTxArgs {
/// The human readable account name from which to draw outputs
/// for the transaction, overriding whatever the active account is as set via the
/// [`set_active_account`](../grin_wallet_api/owner/struct.Owner.html#method.set_active_account) method.
pub src_acct_name: Option<String>,
#[serde(with = "secp_ser::string_or_u64")]
/// The amount to send, in nanogrins. (`1 G = 1_000_000_000nG`)
pub amount: u64,
#[serde(with = "secp_ser::string_or_u64")]
/// The minimum number of confirmations an output
/// should have in order to be included in the transaction.
pub minimum_confirmations: u64,
/// By default, the wallet selects as many inputs as possible in a
/// transaction, to reduce the Output set and the fees. The wallet will attempt to spend
/// include up to `max_outputs` in a transaction, however if this is not enough to cover
/// the whole amount, the wallet will include more outputs. This parameter should be considered
/// a soft limit.
pub max_outputs: u32,
/// The target number of change outputs to create in the transaction.
/// The actual number created will be `num_change_outputs` + whatever remainder is needed.
pub num_change_outputs: u32,
/// If `true`, attempt to use up as many outputs as
/// possible to create the transaction, up the 'soft limit' of `max_outputs`. This helps
/// to reduce the size of the UTXO set and the amount of data stored in the wallet, and
/// minimizes fees. This will generally result in many inputs and a large change output(s),
/// usually much larger than the amount being sent. If `false`, the transaction will include
/// as many outputs as are needed to meet the amount, (and no more) starting with the smallest
/// value outputs.
pub selection_strategy_is_use_all: bool,
/// An optional participant message to include alongside the sender's public
/// ParticipantData within the slate. This message will include a signature created with the
/// sender's private excess value, and will be publically verifiable. Note this message is for
/// the convenience of the participants during the exchange; it is not included in the final
/// transaction sent to the chain. The message will be truncated to 256 characters.
pub message: Option<String>,
/// Optionally set the output target slate version (acceptable
/// down to the minimum slate version compatible with the current. If `None` the slate
/// is generated with the latest version.
pub target_slate_version: Option<u16>,
/// If true, just return an estimate of the resulting slate, containing fees and amounts
/// locked without actually locking outputs or creating the transaction. Note if this is set to
/// 'true', the amount field in the slate will contain the total amount locked, not the provided
/// transaction amount
pub estimate_only: Option<bool>,
/// Sender arguments. If present, the underlying function will also attempt to send the
/// transaction to a destination and optionally finalize the result
pub send_args: Option<InitTxSendArgs>,
}
/// Send TX API Args, for convenience functionality that inits the transaction and sends
/// in one go
#[derive(Clone, Serialize, Deserialize)]
pub struct InitTxSendArgs {
/// The transaction method. Can currently be 'http' or 'keybase'.
pub method: String,
/// The destination, contents will depend on the particular method
pub dest: String,
/// Whether to finalize the result immediately if the send was successful
pub finalize: bool,
/// Whether to post the transasction if the send and finalize were successful
pub post_tx: bool,
/// Whether to use dandelion when posting. If false, skip the dandelion relay
pub fluff: bool,
}
impl Default for InitTxArgs {
fn default() -> InitTxArgs {
InitTxArgs {
src_acct_name: None,
amount: 0,
minimum_confirmations: 10,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
message: None,
target_slate_version: None,
estimate_only: Some(false),
send_args: None,
}
}
}
/// Fees in block to use for coinbase amount calculation
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct BlockFees {
/// fees
#[serde(with = "secp_ser::string_or_u64")]
pub fees: u64,
/// height
#[serde(with = "secp_ser::string_or_u64")]
pub height: u64,
/// key id
pub key_id: Option<Identifier>,
}
impl BlockFees {
/// return key id
pub fn key_id(&self) -> Option<Identifier> {
self.key_id.clone()
}
}
/// Response to build a coinbase output.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct CbData {
/// Output
pub output: Output,
/// Kernel
pub kernel: TxKernel,
/// Key Id
pub key_id: Option<Identifier>,
}
/// Map Outputdata to commits
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct OutputCommitMapping {
/// Output Data
pub output: OutputData,
/// The commit
#[serde(
serialize_with = "secp_ser::as_hex",
deserialize_with = "secp_ser::commitment_from_hex"
)]
pub commit: pedersen::Commitment,
}
/// Map PaymentData to commits
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct PaymentCommitMapping {
/// Payment Data
pub output: PaymentData,
/// The commit
#[serde(
serialize_with = "secp_ser::as_hex",
deserialize_with = "secp_ser::commitment_from_hex"
)]
pub commit: pedersen::Commitment,
}
/// Node height result
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct NodeHeightResult {
/// Last known height
#[serde(with = "secp_ser::string_or_u64")]
pub height: u64,
/// Whether this height was updated from the node
pub updated_from_node: bool,
}

View file

@ -624,14 +624,6 @@ pub fn wallet_command(
&global_wallet_args,
wallet_config.dark_background_color_scheme.unwrap_or(true),
),
("payments", Some(_)) => {
info!("payments command received");
command::payments(
inst_wallet(),
&global_wallet_args,
wallet_config.dark_background_color_scheme.unwrap_or(true),
)
}
("txs", Some(args)) => {
let a = arg_parse!(parse_txs_args(&args));
command::txs(

View file

@ -501,10 +501,6 @@ mod wallet_tests {
let arg_vec = vec!["grin-wallet", "-p", "password", "-a", "mining", "outputs"];
execute_command(&app, test_dir, "wallet1", &client1, arg_vec)?;
// payments
let arg_vec = vec!["grin-wallet", "-p", "password", "-a", "mining", "payments"];
execute_command(&app, test_dir, "wallet1", &client1, arg_vec)?;
// let logging finish
thread::sleep(Duration::from_millis(200));
Ok(())

View file

@ -163,9 +163,7 @@ subcommands:
short: f
long: fluff
- outputs:
about: Raw wallet self owned output info (list of outputs)
- payments:
about: Raw wallet payment output info (list of outputs)
about: Raw wallet output info (list of outputs)
- txs:
about: Display transaction information
args: