mirror of
https://github.com/jwinterm/grin-wallet.git
synced 2026-10-17 15:21:39 +02:00
Slatepack Workflow (#423)
* debugging tor sends * use fixed yeast version of hyper-socks2 * send command working according to slatepack * changes to handling proof address * modifications of recieve command to work with slatepack and to attempt to return to sender via TOR * finalize command tested * attempting to add invoice processing * fixes to tests, propagation of test mode where needed * modify return values of api functions that can send as sync * cleanup, testing and post_tx function * revert changes to API, many test fixes * deprecate http on the command-line warning
This commit is contained in:
+77
-19
@@ -14,12 +14,14 @@
|
||||
|
||||
//! Foreign API External Definition
|
||||
|
||||
use crate::config::TorConfig;
|
||||
use crate::keychain::Keychain;
|
||||
use crate::libwallet::api_impl::foreign;
|
||||
use crate::libwallet::{
|
||||
BlockFees, CbData, Error, NodeClient, NodeVersionInfo, Slate, VersionInfo, WalletInst,
|
||||
WalletLCProvider,
|
||||
};
|
||||
use crate::try_slatepack_sync_workflow;
|
||||
use crate::util::secp::key::SecretKey;
|
||||
use crate::util::Mutex;
|
||||
use std::sync::Arc;
|
||||
@@ -38,8 +40,10 @@ pub enum ForeignCheckMiddlewareFn {
|
||||
VerifySlateMessages,
|
||||
/// receive_tx
|
||||
ReceiveTx,
|
||||
/// finalize_invoice_tx
|
||||
/// finalize_invoice_tx (delete HF3)
|
||||
FinalizeInvoiceTx,
|
||||
/// finalize_tx
|
||||
FinalizeTx,
|
||||
}
|
||||
|
||||
/// Main interface into all wallet API functions.
|
||||
@@ -70,6 +74,9 @@ where
|
||||
middleware: Option<ForeignCheckMiddleware>,
|
||||
/// Stored keychain mask (in case the stored wallet seed is tokenized)
|
||||
keychain_mask: Option<SecretKey>,
|
||||
/// Optional TOR configuration, holding address of sender and
|
||||
/// data directory
|
||||
tor_config: Mutex<Option<TorConfig>>,
|
||||
}
|
||||
|
||||
impl<'a, L, C, K> Foreign<'a, L, C, K>
|
||||
@@ -158,7 +165,7 @@ where
|
||||
/// // All wallet functions operate on an Arc::Mutex to allow multithreading where needed
|
||||
/// let mut wallet = Arc::new(Mutex::new(wallet));
|
||||
///
|
||||
/// let api_foreign = Foreign::new(wallet.clone(), None, None);
|
||||
/// let api_foreign = Foreign::new(wallet.clone(), None, None, false);
|
||||
/// // .. perform wallet operations
|
||||
///
|
||||
/// ```
|
||||
@@ -167,15 +174,30 @@ where
|
||||
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
keychain_mask: Option<SecretKey>,
|
||||
middleware: Option<ForeignCheckMiddleware>,
|
||||
doctest_mode: bool,
|
||||
) -> Self {
|
||||
Foreign {
|
||||
wallet_inst,
|
||||
doctest_mode: false,
|
||||
doctest_mode,
|
||||
middleware,
|
||||
keychain_mask,
|
||||
tor_config: Mutex::new(None),
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the TOR configuration for this instance of the ForeignAPI, used during
|
||||
/// `recieve_tx` when a return address is specified
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `tor_config` - The optional [TorConfig](#) to use
|
||||
/// # Returns
|
||||
/// * Nothing
|
||||
|
||||
pub fn set_tor_config(&self, tor_config: Option<TorConfig>) {
|
||||
let mut lock = self.tor_config.lock();
|
||||
*lock = tor_config;
|
||||
}
|
||||
|
||||
/// Return the version capabilities of the running ForeignApi Node
|
||||
/// # Arguments
|
||||
/// None
|
||||
@@ -186,7 +208,7 @@ where
|
||||
/// ```
|
||||
/// # grin_wallet_api::doctest_helper_setup_doc_env_foreign!(wallet, wallet_config);
|
||||
///
|
||||
/// let mut api_foreign = Foreign::new(wallet.clone(), None, None);
|
||||
/// let mut api_foreign = Foreign::new(wallet.clone(), None, None, false);
|
||||
///
|
||||
/// let version_info = api_foreign.check_version();
|
||||
/// // check and proceed accordingly
|
||||
@@ -238,7 +260,7 @@ where
|
||||
/// ```
|
||||
/// # grin_wallet_api::doctest_helper_setup_doc_env_foreign!(wallet, wallet_config);
|
||||
///
|
||||
/// let mut api_foreign = Foreign::new(wallet.clone(), None, None);
|
||||
/// let mut api_foreign = Foreign::new(wallet.clone(), None, None, false);
|
||||
///
|
||||
/// let block_fees = BlockFees {
|
||||
/// fees: 800000,
|
||||
@@ -294,6 +316,9 @@ where
|
||||
/// excess value).
|
||||
/// * `dest_acct_name` - The name of the account into which the slate should be received. If
|
||||
/// `None`, the default account is used.
|
||||
/// * `r_addr` - If included, attempt to send the slate back to the sender using the slatepack sync
|
||||
/// send (TOR). If providing this argument, check the `state` field of the slate to see if the
|
||||
/// sync_send was successful (it should be S3 if the synced send sent successfully).
|
||||
///
|
||||
/// # Returns
|
||||
/// * a result containing:
|
||||
@@ -310,12 +335,12 @@ where
|
||||
/// ```
|
||||
/// # grin_wallet_api::doctest_helper_setup_doc_env_foreign!(wallet, wallet_config);
|
||||
///
|
||||
/// let mut api_foreign = Foreign::new(wallet.clone(), None, None);
|
||||
/// let mut api_foreign = Foreign::new(wallet.clone(), None, None, false);
|
||||
/// # let slate = Slate::blank(2, false);
|
||||
///
|
||||
/// // . . .
|
||||
/// // Obtain a sent slate somehow
|
||||
/// let result = api_foreign.receive_tx(&slate, None);
|
||||
/// let result = api_foreign.receive_tx(&slate, None, None);
|
||||
///
|
||||
/// if let Ok(slate) = result {
|
||||
/// // Send back to recipient somehow
|
||||
@@ -323,7 +348,12 @@ where
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
pub fn receive_tx(&self, slate: &Slate, dest_acct_name: Option<&str>) -> Result<Slate, Error> {
|
||||
pub fn receive_tx(
|
||||
&self,
|
||||
slate: &Slate,
|
||||
dest_acct_name: Option<&str>,
|
||||
r_addr: Option<String>,
|
||||
) -> Result<Slate, Error> {
|
||||
let mut w_lock = self.wallet_inst.lock();
|
||||
let w = w_lock.lc_provider()?.wallet_inst()?;
|
||||
if let Some(m) = self.middleware.as_ref() {
|
||||
@@ -333,23 +363,41 @@ where
|
||||
Some(slate),
|
||||
)?;
|
||||
}
|
||||
foreign::receive_tx(
|
||||
let ret_slate = foreign::receive_tx(
|
||||
&mut **w,
|
||||
(&self.keychain_mask).as_ref(),
|
||||
slate,
|
||||
dest_acct_name,
|
||||
self.doctest_mode,
|
||||
)
|
||||
)?;
|
||||
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,
|
||||
);
|
||||
match res {
|
||||
Ok(s) => return Ok(s.unwrap()),
|
||||
Err(_) => return Ok(ret_slate),
|
||||
}
|
||||
}
|
||||
None => Ok(ret_slate),
|
||||
}
|
||||
}
|
||||
|
||||
/// Finalizes an invoice transaction initiated by this wallet's Owner api.
|
||||
/// Finalizes a (standard or invoice) transaction initiated by this wallet's Owner api.
|
||||
/// This step assumes the paying party has completed round 1 and 2 of slate
|
||||
/// creation, and added their partial signatures. The invoicer will verify
|
||||
/// creation, and added their partial signatures. This wallet will verify
|
||||
/// and add their partial sig, then create the finalized transaction,
|
||||
/// ready to post to a node.
|
||||
///
|
||||
/// Note that this function DOES NOT POST the transaction to a node
|
||||
/// for validation. This is done in separately via the
|
||||
/// This function posts to the node if the `post_automatically`
|
||||
/// argument is sent to true. Posting can be done in separately via the
|
||||
/// [`post_tx`](struct.Owner.html#method.post_tx) function.
|
||||
///
|
||||
/// This function also stores the final transaction in the user's wallet files for retrieval
|
||||
@@ -357,7 +405,8 @@ where
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `slate` - The transaction [`Slate`](../grin_wallet_libwallet/slate/struct.Slate.html). The
|
||||
/// payer should have filled in round 1 and 2.
|
||||
/// * `post_automatically` - If true, post the finalized transaction to the configured listening
|
||||
/// node
|
||||
///
|
||||
/// # Returns
|
||||
/// * Ok([`slate`](../grin_wallet_libwallet/slate/struct.Slate.html)) if successful,
|
||||
@@ -370,7 +419,7 @@ where
|
||||
/// # grin_wallet_api::doctest_helper_setup_doc_env_foreign!(wallet, wallet_config);
|
||||
///
|
||||
/// let mut api_owner = Owner::new(wallet.clone(), None);
|
||||
/// let mut api_foreign = Foreign::new(wallet.clone(), None, None);
|
||||
/// let mut api_foreign = Foreign::new(wallet.clone(), None, None, false);
|
||||
///
|
||||
/// // . . .
|
||||
/// // Issue the invoice tx via the owner API
|
||||
@@ -385,11 +434,11 @@ where
|
||||
/// // ...
|
||||
/// # let slate = Slate::blank(2, true);
|
||||
///
|
||||
/// let slate = api_foreign.finalize_invoice_tx(&slate);
|
||||
/// let slate = api_foreign.finalize_tx(&slate, true);
|
||||
/// // if okay, then post via the owner API
|
||||
/// ```
|
||||
|
||||
pub fn finalize_invoice_tx(&self, slate: &Slate) -> Result<Slate, Error> {
|
||||
pub fn finalize_tx(&self, slate: &Slate, post_automatically: bool) -> Result<Slate, Error> {
|
||||
let mut w_lock = self.wallet_inst.lock();
|
||||
let w = w_lock.lc_provider()?.wallet_inst()?;
|
||||
if let Some(m) = self.middleware.as_ref() {
|
||||
@@ -399,7 +448,16 @@ where
|
||||
Some(slate),
|
||||
)?;
|
||||
}
|
||||
foreign::finalize_invoice_tx(&mut **w, (&self.keychain_mask).as_ref(), slate)
|
||||
let post_automatically = match self.doctest_mode {
|
||||
true => false,
|
||||
false => post_automatically,
|
||||
};
|
||||
foreign::finalize_tx(
|
||||
&mut **w,
|
||||
(&self.keychain_mask).as_ref(),
|
||||
slate,
|
||||
post_automatically,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+19
-9
@@ -183,13 +183,12 @@ pub trait ForeignRpc {
|
||||
&self,
|
||||
slate: VersionedSlate,
|
||||
dest_acct_name: Option<String>,
|
||||
//TODO: Remove post-HF3
|
||||
message: Option<String>,
|
||||
dest: Option<String>,
|
||||
) -> Result<VersionedSlate, ErrorKind>;
|
||||
|
||||
/**
|
||||
|
||||
Networked version of [Foreign::finalize_invoice_tx](struct.Foreign.html#method.finalize_invoice_tx).
|
||||
Networked version of [Foreign::finalize_tx](struct.Foreign.html#method.finalize_tx).
|
||||
|
||||
# Json rpc example
|
||||
|
||||
@@ -198,7 +197,7 @@ pub trait ForeignRpc {
|
||||
# r#"
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "finalize_invoice_tx",
|
||||
"method": "finalize_tx",
|
||||
"id": 1,
|
||||
"params": [{
|
||||
"ver": "4:2",
|
||||
@@ -279,6 +278,9 @@ pub trait ForeignRpc {
|
||||
# ,false, 5, false, true);
|
||||
```
|
||||
*/
|
||||
fn finalize_tx(&self, slate: VersionedSlate) -> Result<VersionedSlate, ErrorKind>;
|
||||
|
||||
/// For backwards-compatibility. Remove HF3
|
||||
fn finalize_invoice_tx(&self, slate: VersionedSlate) -> Result<VersionedSlate, ErrorKind>;
|
||||
}
|
||||
|
||||
@@ -301,8 +303,7 @@ where
|
||||
&self,
|
||||
in_slate: VersionedSlate,
|
||||
dest_acct_name: Option<String>,
|
||||
//TODO: Remove post HF3
|
||||
_message: Option<String>,
|
||||
dest: Option<String>,
|
||||
) -> Result<VersionedSlate, ErrorKind> {
|
||||
let version = in_slate.version();
|
||||
let slate_from = Slate::from(in_slate);
|
||||
@@ -310,15 +311,24 @@ where
|
||||
self,
|
||||
&slate_from,
|
||||
dest_acct_name.as_ref().map(String::as_str),
|
||||
dest,
|
||||
)
|
||||
.map_err(|e| e.kind())?;
|
||||
Ok(VersionedSlate::into_version(out_slate, version).map_err(|e| e.kind())?)
|
||||
}
|
||||
|
||||
fn finalize_tx(&self, in_slate: VersionedSlate) -> Result<VersionedSlate, ErrorKind> {
|
||||
let version = in_slate.version();
|
||||
let out_slate =
|
||||
Foreign::finalize_tx(self, &Slate::from(in_slate), true).map_err(|e| e.kind())?;
|
||||
Ok(VersionedSlate::into_version(out_slate, version).map_err(|e| e.kind())?)
|
||||
}
|
||||
|
||||
//TODO: Delete HF3
|
||||
fn finalize_invoice_tx(&self, in_slate: VersionedSlate) -> Result<VersionedSlate, ErrorKind> {
|
||||
let version = in_slate.version();
|
||||
let out_slate =
|
||||
Foreign::finalize_invoice_tx(self, &Slate::from(in_slate)).map_err(|e| e.kind())?;
|
||||
Foreign::finalize_tx(self, &Slate::from(in_slate), false).map_err(|e| e.kind())?;
|
||||
Ok(VersionedSlate::into_version(out_slate, version).map_err(|e| e.kind())?)
|
||||
}
|
||||
}
|
||||
@@ -513,8 +523,8 @@ pub fn run_doctest_foreign(
|
||||
}
|
||||
|
||||
let mut api_foreign = match init_invoice_tx {
|
||||
false => Foreign::new(wallet1, mask1, Some(test_check_middleware)),
|
||||
true => Foreign::new(wallet2, mask2, Some(test_check_middleware)),
|
||||
false => Foreign::new(wallet1, mask1, Some(test_check_middleware), true),
|
||||
true => Foreign::new(wallet2, mask2, Some(test_check_middleware), true),
|
||||
};
|
||||
api_foreign.doctest_mode = true;
|
||||
let foreign_api = &api_foreign as &dyn ForeignRpc;
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ mod types;
|
||||
|
||||
pub use crate::foreign::{Foreign, ForeignCheckMiddleware, ForeignCheckMiddlewareFn};
|
||||
pub use crate::foreign_rpc::ForeignRpc;
|
||||
pub use crate::owner::Owner;
|
||||
pub use crate::owner::{try_slatepack_sync_workflow, Owner};
|
||||
pub use crate::owner_rpc::OwnerRpc;
|
||||
|
||||
pub use crate::foreign_rpc::foreign_rpc as foreign_rpc_client;
|
||||
|
||||
+169
-34
@@ -21,18 +21,21 @@ use uuid::Uuid;
|
||||
use crate::config::{TorConfig, WalletConfig};
|
||||
use crate::core::core::Transaction;
|
||||
use crate::core::global;
|
||||
use crate::impls::create_sender;
|
||||
use crate::impls::HttpSlateSender;
|
||||
use crate::impls::SlateSender as _;
|
||||
use crate::keychain::{Identifier, Keychain};
|
||||
use crate::libwallet::api_impl::owner_updater::{start_updater_log_thread, StatusMessage};
|
||||
use crate::libwallet::api_impl::{owner, owner_updater};
|
||||
use crate::libwallet::{
|
||||
AcctPathMapping, Error, ErrorKind, InitTxArgs, IssueInvoiceTxArgs, NodeClient,
|
||||
NodeHeightResult, OutputCommitMapping, PaymentProof, Slate, Slatepack, SlatepackAddress,
|
||||
TxLogEntry, WalletInfo, WalletInst, WalletLCProvider,
|
||||
AcctPathMapping, Error, InitTxArgs, IssueInvoiceTxArgs, NodeClient, NodeHeightResult,
|
||||
OutputCommitMapping, PaymentProof, Slate, Slatepack, SlatepackAddress, TxLogEntry, WalletInfo,
|
||||
WalletInst, WalletLCProvider,
|
||||
};
|
||||
use crate::util::logger::LoggingConfig;
|
||||
use crate::util::secp::key::SecretKey;
|
||||
use crate::util::{from_hex, static_secp_instance, Mutex, ZeroingString};
|
||||
use grin_wallet_util::OnionV3Address;
|
||||
use std::convert::TryFrom;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::mpsc::{channel, Sender};
|
||||
use std::sync::Arc;
|
||||
@@ -63,6 +66,8 @@ where
|
||||
pub wallet_inst: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>,
|
||||
/// Flag to normalize some output during testing. Can mostly be ignored.
|
||||
pub doctest_mode: bool,
|
||||
/// retail TLD during doctest
|
||||
pub doctest_retain_tld: bool,
|
||||
/// Share ECDH key
|
||||
pub shared_key: Arc<Mutex<Option<SecretKey>>>,
|
||||
/// Update thread
|
||||
@@ -189,6 +194,7 @@ where
|
||||
Owner {
|
||||
wallet_inst,
|
||||
doctest_mode: false,
|
||||
doctest_retain_tld: false,
|
||||
shared_key: Arc::new(Mutex::new(None)),
|
||||
updater,
|
||||
updater_running,
|
||||
@@ -586,9 +592,10 @@ where
|
||||
///
|
||||
/// If the `send_args` [`InitTxSendArgs`](../grin_wallet_libwallet/types/struct.InitTxSendArgs.html),
|
||||
/// of the [`args`](../grin_wallet_libwallet/types/struct.InitTxArgs.html), field is Some, this
|
||||
/// function will attempt to perform a synchronous send to the recipient specified in the `dest`
|
||||
/// field according to the `method` field, and will also finalize and post the transaction if
|
||||
/// the `finalize` field is set.
|
||||
/// function will attempt to send the slate back to the sender using the slatepack sync
|
||||
/// send (TOR). If providing this argument, check the `state` field of the slate to see if the
|
||||
/// sync_send was successful (it should be S2 if the sync sent successfully). It will also post
|
||||
/// the transction if the `post_tx` field is set.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `keychain_mask` - Wallet secret mask to XOR against the stored wallet seed before using, if
|
||||
@@ -648,39 +655,47 @@ where
|
||||
args: InitTxArgs,
|
||||
) -> Result<Slate, Error> {
|
||||
let send_args = args.send_args.clone();
|
||||
let mut slate = {
|
||||
let slate = {
|
||||
let mut w_lock = self.wallet_inst.lock();
|
||||
let w = w_lock.lc_provider()?.wallet_inst()?;
|
||||
owner::init_send_tx(&mut **w, keychain_mask, args, self.doctest_mode)?
|
||||
};
|
||||
// Helper functionality. If send arguments exist, attempt to send
|
||||
// Helper functionality. If send arguments exist, attempt to send sync and
|
||||
// finalize
|
||||
match send_args {
|
||||
Some(sa) => {
|
||||
//TODO: in case of keybase, the response might take 60s and leave the service hanging
|
||||
match sa.method.as_ref() {
|
||||
"http" | "keybase" => {}
|
||||
_ => {
|
||||
error!("unsupported payment method: {}", sa.method);
|
||||
return Err(ErrorKind::ClientCallback(
|
||||
"unsupported payment method".to_owned(),
|
||||
)
|
||||
.into());
|
||||
}
|
||||
};
|
||||
let tor_config_lock = self.tor_config.lock();
|
||||
let comm_adapter = create_sender(&sa.method, &sa.dest, tor_config_lock.clone())
|
||||
.map_err(|e| ErrorKind::GenericError(format!("{}", e)))?;
|
||||
slate = comm_adapter.send_tx(&slate)?;
|
||||
self.tx_lock_outputs(keychain_mask, &slate)?;
|
||||
let slate = match sa.finalize {
|
||||
true => self.finalize_tx(keychain_mask, &slate)?,
|
||||
false => slate,
|
||||
};
|
||||
|
||||
if sa.post_tx {
|
||||
self.post_tx(keychain_mask, &slate, sa.fluff)?;
|
||||
let res = try_slatepack_sync_workflow(
|
||||
&slate,
|
||||
&sa.dest,
|
||||
tor_config_lock.clone(),
|
||||
None,
|
||||
false,
|
||||
self.doctest_mode,
|
||||
);
|
||||
match res {
|
||||
Ok(Some(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(_) => {
|
||||
info!("Tx sent ok",);
|
||||
return Ok(ret_slate);
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Tx sent fail: {}", e);
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Ok(slate);
|
||||
}
|
||||
}
|
||||
Ok(None) => Ok(slate),
|
||||
Err(_) => Ok(slate),
|
||||
}
|
||||
Ok(slate)
|
||||
}
|
||||
None => Ok(slate),
|
||||
}
|
||||
@@ -742,6 +757,12 @@ where
|
||||
/// it is up to the caller to present the request for payment to the user
|
||||
/// and verify that payment should go ahead.
|
||||
///
|
||||
/// If the `send_args` [`InitTxSendArgs`](../grin_wallet_libwallet/types/struct.InitTxSendArgs.html),
|
||||
/// of the [`args`](../grin_wallet_libwallet/types/struct.InitTxArgs.html), field is Some, this
|
||||
/// function will attempt to send the slate back to the initiator using the slatepack sync
|
||||
/// send (TOR). If providing this argument, check the `state` field of the slate to see if the
|
||||
/// sync_send was successful (it should be I3 if the sync sent successfully).
|
||||
///
|
||||
/// This function also stores the final transaction in the user's wallet files for retrieval
|
||||
/// via the [`get_stored_tx`](struct.Owner.html#method.get_stored_tx) function.
|
||||
///
|
||||
@@ -794,7 +815,28 @@ where
|
||||
) -> Result<Slate, Error> {
|
||||
let mut w_lock = self.wallet_inst.lock();
|
||||
let w = w_lock.lc_provider()?.wallet_inst()?;
|
||||
owner::process_invoice_tx(&mut **w, keychain_mask, slate, args, self.doctest_mode)
|
||||
let send_args = args.send_args.clone();
|
||||
let slate =
|
||||
owner::process_invoice_tx(&mut **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 res = try_slatepack_sync_workflow(
|
||||
&slate,
|
||||
&sa.dest,
|
||||
tor_config_lock.clone(),
|
||||
None,
|
||||
true,
|
||||
self.doctest_mode,
|
||||
);
|
||||
match res {
|
||||
Ok(s) => Ok(s.unwrap()),
|
||||
Err(_) => Ok(slate),
|
||||
}
|
||||
}
|
||||
None => Ok(slate),
|
||||
}
|
||||
}
|
||||
|
||||
/// Locks the outputs associated with the inputs to the transaction in the given
|
||||
@@ -1277,7 +1319,7 @@ where
|
||||
pub fn get_top_level_directory(&self) -> Result<String, Error> {
|
||||
let mut w_lock = self.wallet_inst.lock();
|
||||
let lc = w_lock.lc_provider()?;
|
||||
if self.doctest_mode {
|
||||
if self.doctest_mode && !self.doctest_retain_tld {
|
||||
Ok("/doctest/dir".to_owned())
|
||||
} else {
|
||||
lc.get_top_level_directory()
|
||||
@@ -2249,6 +2291,99 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// attempt to send slate synchronously, starting with TOR and downgrading to HTTP
|
||||
pub fn try_slatepack_sync_workflow(
|
||||
slate: &Slate,
|
||||
dest: &str,
|
||||
tor_config: Option<TorConfig>,
|
||||
tor_sender: Option<HttpSlateSender>,
|
||||
send_to_finalize: bool,
|
||||
test_mode: bool,
|
||||
) -> Result<Option<Slate>, libwallet::Error> {
|
||||
let mut ret_slate = Slate::blank(2, false);
|
||||
let mut send_sync = |mut sender: HttpSlateSender, method_str: &str| match sender
|
||||
.send_tx(&slate, send_to_finalize)
|
||||
{
|
||||
Ok(s) => {
|
||||
ret_slate = s;
|
||||
return Ok(());
|
||||
}
|
||||
Err(e) => {
|
||||
debug!(
|
||||
"Send ({}): Could not send Slate via {}: {}",
|
||||
method_str, method_str, e
|
||||
);
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
||||
// First, try TOR
|
||||
match SlatepackAddress::try_from(dest) {
|
||||
Ok(address) => {
|
||||
let tor_addr = OnionV3Address::try_from(&address).unwrap();
|
||||
// Try sending to the destination via TOR
|
||||
let sender = match tor_sender {
|
||||
None => {
|
||||
if test_mode {
|
||||
None
|
||||
} else {
|
||||
match HttpSlateSender::with_socks_proxy(
|
||||
&tor_addr.to_http_str(),
|
||||
&tor_config.as_ref().unwrap().socks_proxy_addr,
|
||||
&tor_config.as_ref().unwrap().send_config_dir,
|
||||
) {
|
||||
Ok(s) => Some(s),
|
||||
Err(e) => {
|
||||
debug!("Send (TOR): Cannot create TOR Slate sender {:?}", e);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(s) => {
|
||||
if test_mode {
|
||||
None
|
||||
} else {
|
||||
Some(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. Attempting alternate methods.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
debug!("Send (TOR): Destination is not SlatepackAddress {:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Try Fallback to HTTP for deprecation period
|
||||
match HttpSlateSender::new(&dest) {
|
||||
Ok(sender) => {
|
||||
println!("Attempting to send transaction via HTTP (deprecated)");
|
||||
match send_sync(sender, "HTTP") {
|
||||
Ok(_) => return Ok(Some(ret_slate)),
|
||||
Err(e) => {
|
||||
debug!("Unable to send via HTTP: {}", e);
|
||||
warn!("Unable to send transaction via HTTP. Will output Slatepack.");
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
debug!("Send (HTTP): Cannot create HTTP Slate sender {:?}", e);
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! doctest_helper_setup_doc_env {
|
||||
|
||||
Reference in New Issue
Block a user