mirror of
https://github.com/jwinterm/grin-wallet.git
synced 2026-10-17 07:11:36 +02:00
Optimize tor sync flow (#763)
This commit is contained in:
+28
-11
@@ -24,6 +24,7 @@ use crate::libwallet::{
|
||||
use crate::try_slatepack_sync_workflow;
|
||||
use crate::util::secp::key::SecretKey;
|
||||
use crate::util::Mutex;
|
||||
use libwallet::api_impl::types::update_tx_slate_state;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// ForeignAPI Middleware Check callback
|
||||
@@ -370,18 +371,34 @@ where
|
||||
)?;
|
||||
match r_addr {
|
||||
Some(a) => {
|
||||
let tor_config_lock = self.tor_config.lock();
|
||||
let res = try_slatepack_sync_workflow(
|
||||
&ret_slate,
|
||||
&a,
|
||||
tor_config_lock.clone(),
|
||||
None,
|
||||
true,
|
||||
self.doctest_mode,
|
||||
);
|
||||
let tc = self.tor_config.lock();
|
||||
let can_send = if let Some(tc) = tc.as_ref() {
|
||||
tc.send_tor(None)
|
||||
} else {
|
||||
false
|
||||
};
|
||||
if self.doctest_mode || !can_send {
|
||||
return Ok(ret_slate);
|
||||
}
|
||||
let res = try_slatepack_sync_workflow(&ret_slate, &a, tc.clone(), None, true);
|
||||
match res {
|
||||
Ok(s) => Ok(s.unwrap()),
|
||||
Err(_) => Ok(ret_slate),
|
||||
Ok(s) => {
|
||||
let parent_key_id = w.parent_key_id();
|
||||
match update_tx_slate_state(
|
||||
w,
|
||||
(&self.keychain_mask).as_ref(),
|
||||
&parent_key_id,
|
||||
&s,
|
||||
) {
|
||||
Ok(_) => {}
|
||||
Err(e) => error!("Error on updating slate state: {}", e),
|
||||
}
|
||||
Ok(s)
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Error on sending over Tor: {}", e);
|
||||
Ok(ret_slate)
|
||||
}
|
||||
}
|
||||
}
|
||||
None => Ok(ret_slate),
|
||||
|
||||
+111
-85
@@ -37,7 +37,10 @@ use crate::util::logger::LoggingConfig;
|
||||
use crate::util::secp::{key::SecretKey, pedersen::Commitment};
|
||||
use crate::util::{from_hex, static_secp_instance, Mutex, ZeroingString};
|
||||
use grin_wallet_util::OnionV3Address;
|
||||
use libwallet::api_impl::types::update_tx_slate_state;
|
||||
use std::convert::TryFrom;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::mpsc::{channel, Sender};
|
||||
use std::sync::Arc;
|
||||
@@ -673,28 +676,20 @@ where
|
||||
Some(sa) => {
|
||||
let tor_config_lock = self.tor_config.lock();
|
||||
let tc = tor_config_lock.clone();
|
||||
let tc = match tc {
|
||||
Some(mut c) => {
|
||||
if let Some(skip_tor) = sa.skip_tor {
|
||||
c.skip_send_attempt = Some(skip_tor);
|
||||
}
|
||||
Some(c)
|
||||
}
|
||||
None => None,
|
||||
let can_send = if let Some(tc) = tc.as_ref() {
|
||||
tc.send_tor(sa.skip_tor)
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let res = try_slatepack_sync_workflow(
|
||||
&slate,
|
||||
&sa.dest,
|
||||
tc,
|
||||
None,
|
||||
false,
|
||||
self.doctest_mode,
|
||||
);
|
||||
if self.doctest_mode || !can_send {
|
||||
return Ok(slate);
|
||||
}
|
||||
let res = try_slatepack_sync_workflow(&slate, &sa.dest, tc, None, false);
|
||||
match res {
|
||||
Ok(Some(s)) => {
|
||||
Ok(s) => {
|
||||
self.tx_lock_outputs(keychain_mask, &s)?;
|
||||
let ret_slate = self.finalize_tx(keychain_mask, &s)?;
|
||||
if sa.post_tx {
|
||||
self.tx_lock_outputs(keychain_mask, &s)?;
|
||||
let ret_slate = self.finalize_tx(keychain_mask, &s)?;
|
||||
let result = self.post_tx(keychain_mask, &ret_slate, sa.fluff);
|
||||
match result {
|
||||
Ok(_) => {
|
||||
@@ -707,13 +702,13 @@ where
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.tx_lock_outputs(keychain_mask, &s)?;
|
||||
let ret_slate = self.finalize_tx(keychain_mask, &s)?;
|
||||
Ok(ret_slate)
|
||||
}
|
||||
}
|
||||
Ok(None) => Ok(slate),
|
||||
Err(_) => Ok(slate),
|
||||
Err(e) => {
|
||||
error!("Error on sending over Tor: {}", e);
|
||||
Ok(slate)
|
||||
}
|
||||
}
|
||||
}
|
||||
None => Ok(slate),
|
||||
@@ -832,35 +827,49 @@ where
|
||||
slate: &Slate,
|
||||
args: InitTxArgs,
|
||||
) -> Result<Slate, Error> {
|
||||
let mut w_lock = self.wallet_inst.lock();
|
||||
let w = w_lock.lc_provider()?.wallet_inst()?;
|
||||
let send_args = args.send_args.clone();
|
||||
let slate = owner::process_invoice_tx(w, keychain_mask, slate, args, self.doctest_mode)?;
|
||||
let slate = {
|
||||
let mut w_lock = self.wallet_inst.lock();
|
||||
let w = w_lock.lc_provider()?.wallet_inst()?;
|
||||
owner::process_invoice_tx(w, keychain_mask, slate, args, self.doctest_mode)?
|
||||
};
|
||||
// Helper functionality. If send arguments exist, attempt to send
|
||||
match send_args {
|
||||
Some(sa) => {
|
||||
let tor_config_lock = self.tor_config.lock();
|
||||
let tc = tor_config_lock.clone();
|
||||
let tc = match tc {
|
||||
Some(mut c) => {
|
||||
if let Some(skip_tor) = sa.skip_tor {
|
||||
c.skip_send_attempt = Some(skip_tor);
|
||||
}
|
||||
Some(c)
|
||||
}
|
||||
None => None,
|
||||
let can_send = if let Some(tc) = tc.as_ref() {
|
||||
tc.send_tor(sa.skip_tor)
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let res = try_slatepack_sync_workflow(
|
||||
&slate,
|
||||
&sa.dest,
|
||||
tc,
|
||||
None,
|
||||
true,
|
||||
self.doctest_mode,
|
||||
);
|
||||
if self.doctest_mode || !can_send {
|
||||
return Ok(slate);
|
||||
}
|
||||
let res = try_slatepack_sync_workflow(&slate, &sa.dest, tc, None, true);
|
||||
match res {
|
||||
Ok(s) => Ok(s.unwrap()),
|
||||
Err(_) => Ok(slate),
|
||||
Ok(s) => {
|
||||
// Update slate state.
|
||||
{
|
||||
let mut w_lock = self.wallet_inst.lock();
|
||||
let w = w_lock.lc_provider()?.wallet_inst()?;
|
||||
let parent_key_id = w.parent_key_id();
|
||||
match update_tx_slate_state(w, keychain_mask, &parent_key_id, &s) {
|
||||
Ok(_) => {}
|
||||
Err(e) => error!("Error on updating slate state: {}", e),
|
||||
}
|
||||
}
|
||||
// Output slatepack message to file.
|
||||
match output_slatepack_file(&self, keychain_mask, &s, &sa.dest) {
|
||||
Ok(_) => {}
|
||||
Err(e) => error!("Error on saving output slatepack message: {}", e),
|
||||
}
|
||||
Ok(s)
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Error on sending over Tor: {}", e);
|
||||
Ok(slate)
|
||||
}
|
||||
}
|
||||
}
|
||||
None => Ok(slate),
|
||||
@@ -2497,13 +2506,7 @@ pub fn try_slatepack_sync_workflow(
|
||||
tor_config: Option<TorConfig>,
|
||||
tor_sender: Option<TorSlateSender>,
|
||||
send_to_finalize: bool,
|
||||
test_mode: bool,
|
||||
) -> Result<Option<Slate>, Error> {
|
||||
if let Some(tc) = &tor_config {
|
||||
if tc.skip_send_attempt == Some(true) {
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
) -> Result<Slate, Error> {
|
||||
let mut ret_slate = Slate::blank(2, false);
|
||||
let mut send_sync = |mut sender: TorSlateSender, method_str: &str| match sender
|
||||
.send_tx(&slate, send_to_finalize)
|
||||
@@ -2521,55 +2524,43 @@ pub fn try_slatepack_sync_workflow(
|
||||
}
|
||||
};
|
||||
|
||||
// Try parsing Slatepack address
|
||||
// Try parsing Slatepack address.
|
||||
match SlatepackAddress::try_from(dest) {
|
||||
Ok(address) => {
|
||||
let tor_addr = OnionV3Address::try_from(&address).unwrap();
|
||||
// Try sending to the destination via TOR
|
||||
let tor_addr = OnionV3Address::try_from(&address).map_err(|_| {
|
||||
Error::SlatepackAddress(format!(
|
||||
"Destination {} is not a valid Onion address.",
|
||||
dest
|
||||
))
|
||||
})?;
|
||||
// Try sending to the destination via Tor.
|
||||
let sender = match tor_sender {
|
||||
None => {
|
||||
if test_mode {
|
||||
None
|
||||
} else {
|
||||
if let Some(tc) = tor_config {
|
||||
match TorSlateSender::new(&tor_addr.to_http_str(), tc) {
|
||||
Ok(s) => Some(s),
|
||||
Err(e) => {
|
||||
debug!("Send (TOR): Cannot create TOR Slate sender {:?}", e);
|
||||
None
|
||||
}
|
||||
if let Some(tc) = tor_config {
|
||||
match TorSlateSender::new(&tor_addr.to_http_str(), tc) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
debug!("Send (Tor): Cannot create TOR Slate sender {:?}", e);
|
||||
return Err(e);
|
||||
}
|
||||
} else {
|
||||
return Err(Error::TorConfig("Tor config is not set".to_string()));
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(s) => {
|
||||
if test_mode {
|
||||
None
|
||||
} else {
|
||||
Some(s)
|
||||
return Err(Error::TorConfig("Tor config is not set".to_string()));
|
||||
}
|
||||
}
|
||||
Some(s) => s,
|
||||
};
|
||||
if let Some(s) = sender {
|
||||
warn!("Attempting to send transaction via TOR");
|
||||
match send_sync(s, "TOR") {
|
||||
Ok(_) => return Ok(Some(ret_slate)),
|
||||
Err(e) => {
|
||||
debug!("Unable to send via TOR: {}", e);
|
||||
warn!("Unable to send transaction via TOR");
|
||||
}
|
||||
}
|
||||
warn!("Attempting to send transaction via Tor");
|
||||
match send_sync(sender, "Tor") {
|
||||
Ok(_) => Ok(ret_slate),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
debug!("Send (TOR): Destination is not SlatepackAddress {:?}", e);
|
||||
warn!("Destination is not a valid Slatepack address. Will output Slatepack.")
|
||||
error!("Destination {} is not a valid Slatepack address.", dest);
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
@@ -2637,3 +2628,38 @@ macro_rules! doctest_helper_setup_doc_env {
|
||||
let mut $wallet = Arc::new(Mutex::new(wallet));
|
||||
};
|
||||
}
|
||||
|
||||
/// Output slatepack message to file.
|
||||
fn output_slatepack_file<L, C, K>(
|
||||
api: &Owner<L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
slate: &Slate,
|
||||
dest: &str,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
L: WalletLCProvider<'static, C, K> + 'static,
|
||||
C: NodeClient + 'static,
|
||||
K: Keychain + 'static,
|
||||
{
|
||||
let address = match SlatepackAddress::try_from(dest) {
|
||||
Ok(a) => Some(a),
|
||||
Err(_) => None,
|
||||
};
|
||||
// encrypt for recipient by default
|
||||
let recipients = match address.clone() {
|
||||
Some(a) => vec![a],
|
||||
None => vec![],
|
||||
};
|
||||
let message = api.create_slatepack_message(keychain_mask, &slate, Some(0), recipients)?;
|
||||
let tld = api.get_top_level_directory()?;
|
||||
|
||||
// Create a directory to which files will be output.
|
||||
let slate_dir = format!("{}/{}", tld, "slatepack");
|
||||
let _ = std::fs::create_dir_all(slate_dir.clone());
|
||||
let out_file_name = format!("{}/{}.{}.slatepack", slate_dir, slate.id, slate.state);
|
||||
|
||||
let mut output = File::create(out_file_name.clone())?;
|
||||
output.write_all(&message.as_bytes())?;
|
||||
output.sync_all()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
+14
-4
@@ -164,18 +164,18 @@ impl From<io::Error> for ConfigError {
|
||||
pub struct TorConfig {
|
||||
/// whether to use integrated Tor library
|
||||
pub use_integrated: Option<bool>,
|
||||
/// whether to skip any attempts to send via TOR
|
||||
/// whether to skip any attempts to send via Tor
|
||||
pub skip_send_attempt: Option<bool>,
|
||||
/// Whether to start tor listener on listener startup (default true)
|
||||
/// Whether to start Tor listener on listener startup (default true)
|
||||
pub use_tor_listener: bool,
|
||||
/// Just the address of the socks proxy for now
|
||||
pub socks_proxy_addr: String,
|
||||
/// Send configuration directory
|
||||
pub send_config_dir: String,
|
||||
/// tor bridge config
|
||||
/// Tor bridge config
|
||||
#[serde(default)]
|
||||
pub bridge: TorBridgeConfig,
|
||||
/// tor proxy config
|
||||
/// Tor proxy config
|
||||
#[serde(default)]
|
||||
pub proxy: TorProxyConfig,
|
||||
}
|
||||
@@ -194,6 +194,16 @@ impl Default for TorConfig {
|
||||
}
|
||||
}
|
||||
|
||||
impl TorConfig {
|
||||
/// Check if attempt to send over Tor is needed using provided possible argument at priority.
|
||||
pub fn send_tor(&self, skip_arg: Option<bool>) -> bool {
|
||||
if let Some(skip_tor) = skip_arg {
|
||||
return !skip_tor;
|
||||
}
|
||||
!self.skip_send_attempt.unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
||||
/// Tor Bridge Config
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||
pub struct TorBridgeConfig {
|
||||
|
||||
+104
-55
@@ -40,6 +40,7 @@ use std::sync::Arc;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use uuid::Uuid;
|
||||
use grin_wallet_libwallet::api_impl::types::update_tx_slate_state;
|
||||
|
||||
fn show_recovery_phrase(phrase: ZeroingString) {
|
||||
println!("Your recovery phrase is:");
|
||||
@@ -431,18 +432,37 @@ where
|
||||
if let Some(b) = args.bridge.clone() {
|
||||
c.bridge.bridge_line = Some(b);
|
||||
}
|
||||
if let Some(s) = args.skip_tor {
|
||||
c.skip_send_attempt = Some(s);
|
||||
}
|
||||
Some(c)
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
|
||||
let res = try_slatepack_sync_workflow(&slate, &args.dest, tor_config, None, false, test_mode);
|
||||
let output_sp = || -> Result<(), Error> {
|
||||
Ok(output_slatepack(
|
||||
owner_api,
|
||||
keychain_mask,
|
||||
&slate,
|
||||
args.dest.as_str(),
|
||||
args.outfile,
|
||||
true,
|
||||
false,
|
||||
args.slatepack_qr,
|
||||
)?)
|
||||
};
|
||||
|
||||
let can_send = if let Some(tc) = tor_config.as_ref() {
|
||||
tc.send_tor(args.skip_tor)
|
||||
} else {
|
||||
false
|
||||
};
|
||||
if test_mode || !can_send {
|
||||
return output_sp();
|
||||
}
|
||||
|
||||
let res = try_slatepack_sync_workflow(&slate, &args.dest, tor_config, None, false);
|
||||
|
||||
match res {
|
||||
Ok(Some(s)) => {
|
||||
Ok(s) => {
|
||||
controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| {
|
||||
api.tx_lock_outputs(m, &s)?;
|
||||
let ret_slate = api.finalize_tx(m, &s)?;
|
||||
@@ -459,19 +479,10 @@ where
|
||||
}
|
||||
})?;
|
||||
}
|
||||
Ok(None) => {
|
||||
output_slatepack(
|
||||
owner_api,
|
||||
keychain_mask,
|
||||
&slate,
|
||||
args.dest.as_str(),
|
||||
args.outfile,
|
||||
true,
|
||||
false,
|
||||
args.slatepack_qr,
|
||||
)?;
|
||||
Err(e) => {
|
||||
error!("Error sending slate sync: {}", e);
|
||||
output_sp()?;
|
||||
}
|
||||
Err(e) => return Err(e.into()),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -668,9 +679,6 @@ where
|
||||
if let Some(b) = args.bridge {
|
||||
c.bridge.bridge_line = Some(b);
|
||||
}
|
||||
if let Some(s) = args.skip_tor {
|
||||
c.skip_send_attempt = Some(s);
|
||||
}
|
||||
Some(c)
|
||||
}
|
||||
None => None,
|
||||
@@ -686,33 +694,55 @@ where
|
||||
None => String::from(""),
|
||||
};
|
||||
|
||||
let res = try_slatepack_sync_workflow(&slate, &dest, tor_config, None, true, test_mode);
|
||||
let output_sp = || -> Result<(), Error> {
|
||||
Ok(output_slatepack(
|
||||
owner_api,
|
||||
keychain_mask,
|
||||
&slate,
|
||||
&dest,
|
||||
args.outfile,
|
||||
false,
|
||||
false,
|
||||
args.slatepack_qr,
|
||||
)?)
|
||||
};
|
||||
|
||||
let can_send = if let Some(tc) = tor_config.as_ref() {
|
||||
tc.send_tor(args.skip_tor)
|
||||
} else {
|
||||
false
|
||||
};
|
||||
if test_mode || !can_send {
|
||||
return output_sp();
|
||||
}
|
||||
|
||||
let res = try_slatepack_sync_workflow(&slate, &dest, tor_config, None, true);
|
||||
|
||||
match res {
|
||||
Ok(Some(_)) => {
|
||||
Ok(s) => {
|
||||
// Update slate state.
|
||||
{
|
||||
let mut w_lock = owner_api.wallet_inst.lock();
|
||||
let w = w_lock.lc_provider()?.wallet_inst()?;
|
||||
let parent_key_id = w.parent_key_id();
|
||||
match update_tx_slate_state(w, keychain_mask, &parent_key_id, &s) {
|
||||
Ok(_) => {}
|
||||
Err(e) => error!("Error on updating slate state: {}", e),
|
||||
}
|
||||
}
|
||||
println!();
|
||||
println!(
|
||||
"Transaction received and sent back to sender at {} for finalization.",
|
||||
dest
|
||||
);
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
Ok(None) => {
|
||||
output_slatepack(
|
||||
owner_api,
|
||||
keychain_mask,
|
||||
&slate,
|
||||
&dest,
|
||||
args.outfile,
|
||||
false,
|
||||
false,
|
||||
args.slatepack_qr,
|
||||
)?;
|
||||
Ok(())
|
||||
Err(e) => {
|
||||
error!("Error sending slate sync: {}", e);
|
||||
output_sp()?;
|
||||
}
|
||||
Err(e) => Err(e.into()),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn unpack<L, C, K>(
|
||||
@@ -1012,41 +1042,60 @@ where
|
||||
if let Some(b) = args.bridge {
|
||||
c.bridge.bridge_line = Some(b);
|
||||
}
|
||||
if let Some(skip_tor) = args.skip_tor {
|
||||
c.skip_send_attempt = Some(skip_tor);
|
||||
}
|
||||
Some(c)
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
|
||||
let res = try_slatepack_sync_workflow(&slate, &dest, tor_config, None, true, test_mode);
|
||||
let output_sp = || -> Result<(), Error> {
|
||||
Ok(output_slatepack(
|
||||
owner_api,
|
||||
keychain_mask,
|
||||
&slate,
|
||||
&dest,
|
||||
args.outfile,
|
||||
true,
|
||||
false,
|
||||
args.slatepack_qr,
|
||||
)?)
|
||||
};
|
||||
|
||||
let can_send = if let Some(tc) = tor_config.as_ref() {
|
||||
tc.send_tor(args.skip_tor)
|
||||
} else {
|
||||
false
|
||||
};
|
||||
if test_mode || !can_send {
|
||||
return output_sp();
|
||||
}
|
||||
|
||||
let res = try_slatepack_sync_workflow(&slate, &dest, tor_config, None, true);
|
||||
|
||||
match res {
|
||||
Ok(Some(_)) => {
|
||||
Ok(s) => {
|
||||
// Update slate state.
|
||||
{
|
||||
let mut w_lock = owner_api.wallet_inst.lock();
|
||||
let w = w_lock.lc_provider()?.wallet_inst()?;
|
||||
let parent_key_id = w.parent_key_id();
|
||||
match update_tx_slate_state(w, keychain_mask, &parent_key_id, &s) {
|
||||
Ok(_) => {}
|
||||
Err(e) => error!("Error on updating slate state: {}", e),
|
||||
}
|
||||
}
|
||||
println!();
|
||||
println!(
|
||||
"Transaction paid and sent back to initiator at {} for finalization.",
|
||||
dest
|
||||
);
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
Ok(None) => {
|
||||
output_slatepack(
|
||||
owner_api,
|
||||
keychain_mask,
|
||||
&slate,
|
||||
&dest,
|
||||
args.outfile,
|
||||
true,
|
||||
false,
|
||||
args.slatepack_qr,
|
||||
)?;
|
||||
Ok(())
|
||||
Err(e) => {
|
||||
error!("Error sending slate sync: {}", e);
|
||||
output_sp()?;
|
||||
}
|
||||
Err(e) => Err(e.into()),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Info command args
|
||||
|
||||
@@ -300,9 +300,7 @@ fn init_client(
|
||||
cached_client_config.replace((client.clone(), config.clone()));
|
||||
Ok((client, config))
|
||||
}
|
||||
Err(e) => {
|
||||
Err(e)
|
||||
},
|
||||
Err(e) => Err(e),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
|
||||
//! Generic implementation of owner API functions
|
||||
|
||||
use grin_keychain::Identifier;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
use super::owner::tx_lock_outputs;
|
||||
use crate::api_impl::owner::{check_ttl, post_tx};
|
||||
use crate::api_impl::types::update_tx_slate_state;
|
||||
use crate::backend::WalletBackend;
|
||||
use crate::grin_core::core::FeeFields;
|
||||
use crate::grin_keychain::Keychain;
|
||||
@@ -236,39 +236,3 @@ where
|
||||
}
|
||||
Ok(sl)
|
||||
}
|
||||
|
||||
/// Update transaction slate state.
|
||||
fn update_tx_slate_state<C, K>(
|
||||
wallet: &mut WalletBackend<C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
parent_key_id: &Identifier,
|
||||
slate: &Slate,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
C: NodeClient,
|
||||
K: Keychain,
|
||||
{
|
||||
let mut bad_records = 0;
|
||||
let tx = wallet
|
||||
.tx_log_iter()?
|
||||
.filter(|tx| {
|
||||
if tx.is_err() {
|
||||
bad_records += 1;
|
||||
}
|
||||
tx.is_ok()
|
||||
})
|
||||
.map(|tx| tx.unwrap())
|
||||
.find(|tx| tx.tx_slate_id == Some(slate.id));
|
||||
if let Some(mut tx) = tx {
|
||||
let mut batch = wallet.batch(keychain_mask)?;
|
||||
tx.tx_slate_state = Some(slate.state.clone());
|
||||
batch.save_tx_log_entry(tx.clone(), parent_key_id)?;
|
||||
batch.commit()?;
|
||||
} else {
|
||||
return Err(Error::Backend(format!(
|
||||
"Tx log entry with slate id {} not found, there are {} bad tx log records",
|
||||
slate.id, bad_records
|
||||
)));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -21,10 +21,12 @@ use crate::grin_util::secp::pedersen;
|
||||
use crate::slate_versions::ser as dalek_ser;
|
||||
use crate::slate_versions::SlateVersion;
|
||||
use crate::types::OutputData;
|
||||
use crate::SlatepackAddress;
|
||||
use crate::{Error, NodeClient, Slate, SlatepackAddress, WalletBackend};
|
||||
|
||||
use chrono::prelude::*;
|
||||
use ed25519_dalek::Signature as DalekSignature;
|
||||
use grin_keychain::Keychain;
|
||||
use grin_util::secp::SecretKey;
|
||||
|
||||
pub use crate::mwixnet::{Hop, MixnetReqCreationParams, SwapReq};
|
||||
|
||||
@@ -344,3 +346,39 @@ pub struct BuiltOutput {
|
||||
/// Output
|
||||
pub output: Output,
|
||||
}
|
||||
|
||||
/// Update transaction slate state.
|
||||
pub fn update_tx_slate_state<C, K>(
|
||||
wallet: &mut WalletBackend<C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
parent_key_id: &Identifier,
|
||||
slate: &Slate,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
C: NodeClient,
|
||||
K: Keychain,
|
||||
{
|
||||
let mut bad_records = 0;
|
||||
let tx = wallet
|
||||
.tx_log_iter()?
|
||||
.filter(|tx| {
|
||||
if tx.is_err() {
|
||||
bad_records += 1;
|
||||
}
|
||||
tx.is_ok()
|
||||
})
|
||||
.map(|tx| tx.unwrap())
|
||||
.find(|tx| tx.tx_slate_id == Some(slate.id));
|
||||
if let Some(mut tx) = tx {
|
||||
let mut batch = wallet.batch(keychain_mask)?;
|
||||
tx.tx_slate_state = Some(slate.state.clone());
|
||||
batch.save_tx_log_entry(tx.clone(), parent_key_id)?;
|
||||
batch.commit()?;
|
||||
} else {
|
||||
return Err(Error::Backend(format!(
|
||||
"Tx log entry with slate id {} not found, there are {} bad tx log records",
|
||||
slate.id, bad_records
|
||||
)));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user