Skip to content

Commit f4bb002

Browse files
author
bay
committed
Split wallet locks for init_send_tx api. Add global lock for this api call, so send request processed sequentually.
1 parent b741ed6 commit f4bb002

File tree

4 files changed

+68
-44
lines changed

4 files changed

+68
-44
lines changed

Cargo.lock

Lines changed: 1 addition & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,8 @@ chrono = { version = "0.4.11", features = ["serde"] }
2020
ring = "0.16"
2121
base64 = "0.12"
2222
ed25519-dalek = "1.0.0-pre.4"
23-
colored = "1.6"
24-
x25519-dalek = "0.6"
2523
easy-jsonrpc-mwc = { git = "https://github.com/mwcproject/easy-jsonrpc-mwc", version = "0.5.5", branch = "master" }
24+
lazy_static = "1.4"
2625

2726
mwc_wallet_libwallet = { path = "../libwallet", version = "5.3.6" }
2827
mwc_wallet_config = { path = "../config", version = "5.3.6" }

api/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ extern crate serde_json;
3535

3636
#[macro_use]
3737
extern crate log;
38+
#[macro_use]
39+
extern crate lazy_static;
3840

3941
mod foreign;
4042
mod foreign_rpc;

api/src/owner.rs

Lines changed: 64 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,15 @@ use std::thread;
5252
use std::thread::JoinHandle;
5353
use std::time::Duration;
5454

55+
lazy_static! {
56+
// Flag that send call is in the progress. init_send_tx is not atomic because we don't want
57+
// wallet to be blocked during send attempt that can take up to 2 minutes is we are using mwcmqs and other wallet is offline.
58+
// Also we don't wantot to lock outputs before send and cancel on failure.
59+
// That is we are introducing a simple flag for the send. Only one instance will be ready to go through
60+
// send workflow with owner API. Ownser API ans command can act together, in worst case it will throw lock error
61+
pub static ref INIT_SEND_TX_LOCK: Arc<Mutex<u32>> = Arc::new(Mutex::new(0));
62+
}
63+
5564
/// Main interface into all wallet API functions.
5665
/// Wallet APIs are split into two seperate blocks of functionality
5766
/// called the ['Owner'](struct.Owner.html) and ['Foreign'](struct.Foreign.html) APIs
@@ -705,8 +714,6 @@ where
705714
) -> Result<Slate, Error> {
706715
let address = args.address.clone();
707716

708-
wallet_lock!(self.wallet_inst, w);
709-
owner::update_wallet_state(&mut **w, keychain_mask, &None)?;
710717
let send_args = args.send_args.clone();
711718
//minimum_confirmations cannot be zero.
712719
let minimum_confirmations = args.minimum_confirmations.clone();
@@ -766,23 +773,32 @@ where
766773
None
767774
};
768775

769-
let mut slate =
770-
{ owner::init_send_tx(&mut **w, keychain_mask, &args, self.doctest_mode, routputs)? };
776+
// Using it as a global lock for the API
777+
// Without usage it still works until the end of the block
778+
let mut _send_lock = INIT_SEND_TX_LOCK.lock();
779+
780+
let (mut slate, slatepack_secret, height, secp) = {
781+
wallet_lock!(self.wallet_inst, w);
782+
owner::update_wallet_state(&mut **w, keychain_mask, &None)?;
783+
784+
let slate = {
785+
owner::init_send_tx(&mut **w, keychain_mask, &args, self.doctest_mode, routputs)?
786+
};
787+
788+
let keychain = w.keychain(keychain_mask)?;
789+
let (height, _, _) = w.w2n_client().get_chain_tip()?;
790+
let slatepack_secret =
791+
proofaddress::payment_proof_address_dalek_secret(&keychain, None)?;
771792

772-
match send_args {
793+
(slate, slatepack_secret, height, keychain.secp().clone())
794+
};
795+
796+
let res = match send_args {
773797
Some(sa) => {
774798
let original_slate = slate.clone();
775799

776800
match sender_info {
777801
Some((sender, other_wallet_info)) => {
778-
let (slatepack_secret, height, secp) = {
779-
let keychain = w.keychain(keychain_mask)?;
780-
let (height, _, _) = w.w2n_client().get_chain_tip()?;
781-
let slatepack_secret =
782-
proofaddress::payment_proof_address_dalek_secret(&keychain, None)?;
783-
(slatepack_secret, height, keychain.secp().clone())
784-
};
785-
786802
slate = sender
787803
.send_tx(
788804
true,
@@ -822,35 +838,41 @@ where
822838
e
823839
})?;
824840

825-
owner::tx_lock_outputs(
826-
&mut **w,
827-
keychain_mask,
828-
&slate,
829-
address,
830-
0,
831-
self.doctest_mode,
832-
)?;
833-
834-
slate = match sa.finalize {
835-
true => {
836-
let (slate_res, _context) = owner::finalize_tx(
837-
&mut **w,
838-
keychain_mask,
839-
&slate,
840-
true,
841-
self.doctest_mode,
842-
)?;
843-
slate_res
844-
}
845-
false => slate,
841+
let w2n_client = {
842+
wallet_lock!(self.wallet_inst, w);
843+
844+
owner::tx_lock_outputs(
845+
&mut **w,
846+
keychain_mask,
847+
&slate,
848+
address,
849+
0,
850+
self.doctest_mode,
851+
)?;
852+
853+
slate = match sa.finalize {
854+
true => {
855+
let (slate_res, _context) = owner::finalize_tx(
856+
&mut **w,
857+
keychain_mask,
858+
&slate,
859+
true,
860+
self.doctest_mode,
861+
)?;
862+
slate_res
863+
}
864+
false => slate,
865+
};
866+
println!(
867+
"slate [{}] finalized successfully in owner_api",
868+
slate.id.to_string()
869+
);
870+
871+
w.w2n_client().clone()
846872
};
847-
println!(
848-
"slate [{}] finalized successfully in owner_api",
849-
slate.id.to_string()
850-
);
851873

852874
if sa.post_tx {
853-
owner::post_tx(w.w2n_client(), slate.tx_or_err()?, sa.fluff)?;
875+
owner::post_tx(&w2n_client, slate.tx_or_err()?, sa.fluff)?;
854876
}
855877
println!(
856878
"slate [{}] posted successfully in owner_api",
@@ -859,7 +881,9 @@ where
859881
Ok(slate)
860882
}
861883
None => Ok(slate),
862-
}
884+
};
885+
886+
res
863887
}
864888

865889
/// Issues a new invoice transaction slate, essentially a `request for payment`.

0 commit comments

Comments
 (0)