Skip to content

Commit

Permalink
Modify get_stored_tx functions + tests (#454)
Browse files Browse the repository at this point in the history
  • Loading branch information
yeastplume committed Jun 25, 2020
1 parent 99c2505 commit f8ea767
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 60 deletions.
26 changes: 16 additions & 10 deletions api/src/owner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ use ed25519_dalek::SecretKey as DalekSecretKey;
use uuid::Uuid;

use crate::config::{TorConfig, WalletConfig};
use crate::core::core::Transaction;
use crate::core::global;
use crate::impls::HttpSlateSender;
use crate::impls::SlateSender as _;
Expand Down Expand Up @@ -1129,18 +1128,24 @@ where
}

/// Retrieves the stored transaction associated with a TxLogEntry. Can be used even after the
/// transaction has completed.
/// transaction has completed. Either the Transaction Log ID or the Slate UUID must be supplied.
/// If both are supplied, the Transaction Log ID is preferred.
///
/// # Arguments
///
/// * `keychain_mask` - Wallet secret mask to XOR against the stored wallet seed before using, if
/// being used.
/// * `tx_log_entry` - A [`TxLogEntry`](../grin_wallet_libwallet/types/struct.TxLogEntry.html)
/// * `tx_id` - The id of the transaction in the wallet's Transaction Log. Either this or
/// `slate_id` must be provided.
/// * `slate_id` - The UUID of the Transaction Slate to find. Either this or `tx_id` must be
/// provided
///
/// # Returns
/// * Ok with the stored [`Transaction`](../grin_core/core/transaction/struct.Transaction.html)
/// if successful
/// * or [`libwallet::Error`](../grin_wallet_libwallet/struct.Error.html) if an error is encountered.
/// * Ok(Some([Slate](../grin_wallet_libwallet/slate/struct.Slate.html)) containing the stored
/// transaction, if successful. Note that this Slate will not contain all of the fields used by
/// the original Slate that resulted in the transaction.
/// * Ok(None) if the stored Transaction isn't found.
/// * [`libwallet::Error`](../grin_wallet_libwallet/struct.Error.html) if an error is encountered.
///
/// # Example
/// Set up as in [`new`](struct.Owner.html#method.new) method above.
Expand All @@ -1156,21 +1161,22 @@ where
/// let result = api_owner.retrieve_txs(None, update_from_node, tx_id, tx_slate_id);
///
/// if let Ok((was_updated, tx_log_entries)) = result {
/// let stored_tx = api_owner.get_stored_tx(None, tx_log_entries[0].tx_slate_id.unwrap()).unwrap();
/// let stored_tx = api_owner.get_stored_tx(None, Some(tx_log_entries[0].id), None).unwrap();
/// //...
/// }
/// ```

pub fn get_stored_tx(
&self,
keychain_mask: Option<&SecretKey>,
tx_id: Uuid,
) -> Result<Option<Transaction>, Error> {
tx_id: Option<u32>,
slate_id: Option<&Uuid>,
) -> Result<Option<Slate>, Error> {
let mut w_lock = self.wallet_inst.lock();
let w = w_lock.lc_provider()?.wallet_inst()?;
// Test keychain mask, to keep API consistent
let _ = w.keychain(keychain_mask)?;
owner::get_stored_tx(&**w, &tx_id)
owner::get_stored_tx(&**w, tx_id, slate_id)
}

/// Scans the entire UTXO set from the node, identify which outputs belong to the given wallet
Expand Down
68 changes: 41 additions & 27 deletions api/src/owner_rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
use uuid::Uuid;

use crate::config::{TorConfig, WalletConfig};
use crate::core::core::Transaction;
use crate::core::global;
use crate::keychain::{Identifier, Keychain};
use crate::libwallet::{
Expand Down Expand Up @@ -805,7 +804,8 @@ pub trait OwnerRpc {
"id": 1,
"params": {
"token": "d202964900000000d302964900000000d402964900000000d502964900000000",
"id": "0436430c-2b02-624c-2032-570501212b00"
"id": null,
"slate_id": "0436430c-2b02-624c-2032-570501212b00"
}
}
# "#
Expand All @@ -816,36 +816,30 @@ pub trait OwnerRpc {
"id": 1,
"result": {
"Ok": {
"body": {
"inputs": [],
"kernels": [
{
"excess": "000000000000000000000000000000000000000000000000000000000000000000",
"excess_sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"features": {
"Plain": {
"fee": 7000000
}
}
}
],
"outputs": [
{
"commit": "099b48cfb1f80a2347dc89818449e68e76a3c6817a532a8e9ef2b4a5ccf4363850",
"features": "Plain",
"proof": "29701ceae262cac77b79b868c883a292e61e6de8192b868edcd1300b0973d91396b156ace6bd673402a303de10ddd8a5e6b7f17ba6557a574a672bd04cc273ab04ed8e2ca80bac483345c0ec843f521814ce1301ec9adc38956a12b4d948acce71295a4f52bcdeb8a1c9f2d6b2da5d731262a5e9c0276ef904df9ef8d48001420cd59f75a2f1ae5c7a1c7c6b9f140e7613e52ef9e249f29f9340b7efb80699e460164324616f98fd4cde3db52497c919e95222fffeacb7e65deca7e368a80ce713c19de7da5369726228ee336f5bd494538c12ccbffeb1b9bfd5fc8906d1c64245b516f103fa96d9c56975837652c1e0fa5803d7ccf1147d8f927e36da717f7ad79471dbe192f5f50f87a79fc3fe030dba569b634b92d2cf307993cce545633af263897cd7e6ebf4dcafb176d07358bdc38d03e45a49dfa9c8c6517cd68d167ffbf6c3b4de0e2dd21909cbad4c467b84e5700be473a39ac59c669d7c155c4bcab9b8026eea3431c779cd277e4922d2b9742e1f6678cbe869ec3b5b7ef4132ddb6cdd06cf27dbeb28be72b949fa897610e48e3a0d789fd2eea75abc97b3dc7e00e5c8b3d24e40c6f24112adb72352b89a2bef0599345338e9e76202a3c46efa6370952b2aca41aadbae0ea32531acafcdab6dd066d769ebf50cf4f3c0a59d2d5fa79600a207b9417c623f76ad05e8cccfcd4038f9448bc40f127ca7c0d372e46074e334fe49f5a956ec0056f4da601e6af80eb1a6c4951054869e665b296d8c14f344ca2dc5fdd5df4a3652536365a1615ad9b422165c77bf8fe65a835c8e0c41e070014eb66ef8c525204e990b3a3d663c1e42221b496895c37a2f0c1bf05e91235409c3fe3d89a9a79d6c78609ab18a463311911f71fa37bb73b15fcd38143d1404fd2ce81004dc7ff89cf1115dcc0c35ce1c1bf9941586fb959770f2618ccb7118a7"
}
]
},
"offset": "0000000000000000000000000000000000000000000000000000000000000000"
"coms": [
{
"c": "CZtIz7H4CiNH3ImBhEnmjnajxoF6UyqOnvK0pcz0NjhQ",
"p": "KXAc6uJiysd7ebhoyIOikuYebegZK4aO3NEwCwlz2ROWsVas5r1nNAKjA94Q3dil5rfxe6ZVeldKZyvQTMJzqwTtjiyoC6xIM0XA7IQ/UhgUzhMB7JrcOJVqErTZSKzOcSlaT1K83rihyfLWstpdcxJipenAJ275BN+e+NSAAUIM1Z91ovGuXHocfGufFA52E+Uu+eJJ8p+TQLfvuAaZ5GAWQyRhb5j9TN49tSSXyRnpUiL//qy35l3sp+NoqAznE8Gd59pTaXJiKO4zb1vUlFOMEsy//rG5v9X8iQbRxkJFtRbxA/qW2cVpdYN2UsHg+lgD18zxFH2Pkn422nF/eteUcdvhkvX1D4enn8P+Aw26VptjS5LSzzB5k8zlRWM68mOJfNfm6/Tcr7F20HNYvcONA+RaSd+pyMZRfNaNFn/79sO03g4t0hkJy61MRnuE5XAL5HOjmsWcZp18FVxLyrm4Am7qNDHHec0nfkki0rl0Lh9meMvoaew7W370Ey3bbN0Gzyfb6yi+crlJ+ol2EOSOOg14n9Lup1q8l7PcfgDlyLPSTkDG8kESrbcjUriaK+8FmTRTOOnnYgKjxG76Y3CVKyrKQarbrg6jJTGsr82rbdBm12nr9Qz088ClnS1fp5YAoge5QXxiP3atBejMz81AOPlEi8QPEnynwNNy5GB04zT+SfWpVuwAVvTaYB5q+A6xpsSVEFSGnmZbKW2MFPNEyi3F/dXfSjZSU2NloWFa2bQiFlx3v4/mWoNcjgxB4HABTrZu+MUlIE6ZCzo9ZjweQiIbSWiVw3ovDBvwXpEjVAnD/j2JqaedbHhgmrGKRjMRkR9x+je7c7FfzTgUPRQE/SzoEATcf/ic8RFdzAw1zhwb+ZQVhvuVl3DyYYzLcRin"
}
],
"fee": "7000000",
"id": "0436430c-2b02-624c-2032-570501212b00",
"sigs": [],
"sta": "S3",
"ver": "4:3"
}
}
}
# "#
# , 5, true, true, false, false);
```
*/
fn get_stored_tx(&self, token: Token, id: Uuid) -> Result<Option<Transaction>, ErrorKind>;
fn get_stored_tx(
&self,
token: Token,
id: Option<u32>,
slate_id: Option<Uuid>,
) -> Result<Option<VersionedSlate>, ErrorKind>;

/**
Networked version of [Owner::scan](struct.Owner.html#method.scan).
Expand Down Expand Up @@ -1873,8 +1867,28 @@ where
.map_err(|e| e.kind())
}

fn get_stored_tx(&self, token: Token, uuid: Uuid) -> Result<Option<Transaction>, ErrorKind> {
Owner::get_stored_tx(self, (&token.keychain_mask).as_ref(), uuid).map_err(|e| e.kind())
fn get_stored_tx(
&self,
token: Token,
id: Option<u32>,
slate_id: Option<Uuid>,
) -> Result<Option<VersionedSlate>, ErrorKind> {
let out_slate = Owner::get_stored_tx(
self,
(&token.keychain_mask).as_ref(),
id,
(&slate_id).as_ref(),
)
.map_err(|e| e.kind())?;
match out_slate {
Some(s) => {
let version = SlateVersion::V4;
Ok(Some(
VersionedSlate::into_version(s, version).map_err(|e| e.kind())?,
))
}
None => Ok(None),
}
}

fn post_tx(&self, token: Token, slate: VersionedSlate, fluff: bool) -> Result<(), ErrorKind> {
Expand Down
39 changes: 26 additions & 13 deletions controller/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1269,15 +1269,17 @@ where
K: keychain::Keychain + 'static,
{
controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| {
let stored_tx_slate = match api.get_stored_tx(m, Some(args.id), None)? {
None => {
error!(
"Transaction with id {} does not have transaction data. Not reposting.",
args.id
);
return Ok(());
}
Some(s) => s,
};
let (_, txs) = api.retrieve_txs(m, true, Some(args.id), None)?;
let stored_tx = api.get_stored_tx(m, txs[0].tx_slate_id.unwrap())?;
if stored_tx.is_none() {
error!(
"Transaction with id {} does not have transaction data. Not reposting.",
args.id
);
return Ok(());
}
match args.dump_file {
None => {
if txs[0].confirmed {
Expand All @@ -1287,15 +1289,26 @@ where
);
return Ok(());
}
let mut slate = Slate::blank(2, false);
slate.tx = Some(stored_tx.unwrap());
api.post_tx(m, &slate, args.fluff)?;
info!("Reposted transaction at {}", args.id);
if libwallet::sig_is_blank(
&stored_tx_slate.tx.as_ref().unwrap().kernels()[0].excess_sig,
) {
error!("Transaction at {} has not been finalized.", args.id);
return Ok(());
}

match api.post_tx(m, &stored_tx_slate, args.fluff) {
Ok(_) => info!("Reposted transaction at {}", args.id),
Err(e) => error!("Could not repost transaction at {}. Reason: {}", args.id, e),
}
return Ok(());
}
Some(f) => {
let mut tx_file = File::create(f.clone())?;
tx_file.write_all(json::to_string(&stored_tx).unwrap().as_bytes())?;
tx_file.write_all(
json::to_string(&stored_tx_slate.tx.unwrap())
.unwrap()
.as_bytes(),
)?;
tx_file.sync_all()?;
info!("Dumped transaction data for tx {} to {}", args.id, f);
return Ok(());
Expand Down
7 changes: 3 additions & 4 deletions controller/tests/repost.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
let (_, txs) = api.retrieve_txs(m, true, None, Some(slate.id))?;
println!("TXS[0]: {:?}", txs[0]);
let stored_tx = api.get_stored_tx(m, txs[0].tx_slate_id.unwrap())?;
let stored_tx = api.get_stored_tx(m, None, Some(&txs[0].tx_slate_id.unwrap()))?;
println!("Stored tx: {:?}", stored_tx);
api.post_tx(m, &slate, false)?;
bh += 1;
Expand Down Expand Up @@ -225,9 +225,8 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
// Now repost from cached
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
let (_, txs) = api.retrieve_txs(m, true, None, Some(slate.id))?;
let stored_tx = api.get_stored_tx(m, txs[0].tx_slate_id.unwrap())?;
slate.tx = stored_tx;
api.post_tx(m, &slate, false)?;
let stored_tx_slate = api.get_stored_tx(m, Some(txs[0].id), None)?.unwrap();
api.post_tx(m, &stored_tx_slate, false)?;
bh += 1;
Ok(())
})?;
Expand Down
7 changes: 4 additions & 3 deletions controller/tests/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,9 +317,10 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
.iter()
.find(|t| t.tx_slate_id == Some(slate.id))
.unwrap();
let stored_tx = sender_api.get_stored_tx(m, tx.tx_slate_id.unwrap())?;
slate.tx = stored_tx;
sender_api.post_tx(m, &slate, false)?;
let stored_tx_slate = sender_api
.get_stored_tx(m, None, Some(&tx.tx_slate_id.unwrap()))?
.unwrap();
sender_api.post_tx(m, &stored_tx_slate, false)?;
let (_, wallet1_info) = sender_api.retrieve_summary_info(m, true, 1)?;
// should be mined now
assert_eq!(
Expand Down
41 changes: 39 additions & 2 deletions libwallet/src/api_impl/owner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -823,13 +823,50 @@ where
}

/// get stored tx
pub fn get_stored_tx<'a, T: ?Sized, C, K>(w: &T, id: &Uuid) -> Result<Option<Transaction>, Error>
pub fn get_stored_tx<'a, T: ?Sized, C, K>(
w: &T,
tx_id: Option<u32>,
slate_id: Option<&Uuid>,
) -> Result<Option<Slate>, Error>
where
T: WalletBackend<'a, C, K>,
C: NodeClient + 'a,
K: Keychain + 'a,
{
w.get_stored_tx(&format!("{}", id))
let mut uuid = None;
if let Some(i) = tx_id {
let tx = w.tx_log_iter().find(|t| t.id == i);
if let Some(t) = tx {
uuid = t.tx_slate_id;
}
}
if uuid.is_none() {
if let Some(sid) = slate_id {
uuid = Some(sid.to_owned());
}
}
let id = match uuid {
Some(u) => u,
None => {
return Err(ErrorKind::StoredTx(
"Both the provided Transaction Id and Slate UUID are invalid.".to_owned(),
)
.into());
}
};
let tx_res = w.get_stored_tx(&format!("{}", id))?;
match tx_res {
Some(tx) => {
let mut slate = Slate::blank(2, false);
slate.tx = Some(tx.clone());
slate.fee = tx.fee();
slate.id = id.clone();
slate.offset = tx.offset;
slate.state = SlateState::Standard3;
Ok(Some(slate))
}
None => Ok(None),
}
}

/// Posts a transaction to the chain
Expand Down
4 changes: 4 additions & 0 deletions libwallet/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,10 @@ pub enum ErrorKind {
#[fail(display = "SlatepackAddress error: {}", _0)]
SlatepackAddress(String),

/// Retrieving Stored Tx
#[fail(display = "Stored Tx error: {}", _0)]
StoredTx(String),

/// Other
#[fail(display = "Generic error: {}", _0)]
GenericError(String),
Expand Down
1 change: 1 addition & 0 deletions libwallet/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ mod types;

pub use crate::error::{Error, ErrorKind};
pub use crate::slate::{ParticipantData, Slate, SlateState};
pub use crate::slate_versions::v4::sig_is_blank;
pub use crate::slate_versions::{
SlateVersion, VersionedBinSlate, VersionedCoinbase, VersionedSlate, CURRENT_SLATE_VERSION,
GRIN_BLOCK_HEADER_VERSION,
Expand Down
2 changes: 1 addition & 1 deletion libwallet/src/slate_versions/v4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ fn default_sig() -> secp::Signature {
Signature::from_raw_data(&[0; 64]).unwrap()
}

fn sig_is_blank(s: &secp::Signature) -> bool {
pub fn sig_is_blank(s: &secp::Signature) -> bool {
for b in s.to_raw_data().iter() {
if *b != 0 {
return false;
Expand Down

0 comments on commit f8ea767

Please sign in to comment.