Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Full Lifecycle API Support #184

Merged
merged 39 commits into from Jul 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
89e83cd
refactoring wallet lib traits
yeastplume Jul 9, 2019
60d89ca
rustfmt
yeastplume Jul 9, 2019
c0410d2
rustfmt
yeastplume Jul 9, 2019
82e6cf1
add new files
yeastplume Jul 9, 2019
1c938ac
explicit lifetime specifiers on all wallet traits
yeastplume Jul 9, 2019
d0d5907
rustfmt
yeastplume Jul 9, 2019
5e491aa
modify apis to use new walletinst
yeastplume Jul 9, 2019
ba4a2a7
rustfmt
yeastplume Jul 9, 2019
8094669
converting controller crate
yeastplume Jul 10, 2019
e84d60f
rustfmt
yeastplume Jul 10, 2019
dd17ce0
controller crate compiling
yeastplume Jul 10, 2019
2274435
rustfmt
yeastplume Jul 10, 2019
6b41858
compilation
yeastplume Jul 10, 2019
628eb4f
rustfmt
yeastplume Jul 10, 2019
1deaceb
Remove config from wallet, implement open_wallet, close_wallet in lif…
yeastplume Jul 10, 2019
3092863
rustfmt
yeastplume Jul 10, 2019
b0304ed
full compilation, changing recovery + init to new model
yeastplume Jul 11, 2019
1541f18
rustfmt
yeastplume Jul 11, 2019
22fc769
wallet initialisation working, init command output and flow identical…
yeastplume Jul 12, 2019
bba7196
rustfmt
yeastplume Jul 12, 2019
b43ed4f
fix listener and owner api startup
yeastplume Jul 12, 2019
29b3e79
rustfmt
yeastplume Jul 12, 2019
f7a587c
merge from 2.1.0 upstream
yeastplume Jul 15, 2019
fe2dc09
rustfmt
yeastplume Jul 15, 2019
5ccc4a8
move encryption test
yeastplume Jul 15, 2019
59cb6bc
rustfmt
yeastplume Jul 15, 2019
1f0dbed
fix api doctests
yeastplume Jul 15, 2019
ccfdb68
rustfmt
yeastplume Jul 15, 2019
363ee07
fix for most tests in controller crate
yeastplume Jul 15, 2019
d2c72c8
rustfmt
yeastplume Jul 15, 2019
3453480
fix for check tests in controller crate
yeastplume Jul 15, 2019
9866ce6
fix main wallet tests
yeastplume Jul 15, 2019
0870c03
rustfmt
yeastplume Jul 15, 2019
af83011
add explicit functions to handle mnemonic recovery, fix CLI recovery …
yeastplume Jul 23, 2019
e157854
rustfmt
yeastplume Jul 23, 2019
c1c9779
update keybase adapter to use new wallet format
yeastplume Jul 23, 2019
e267ce1
rustfmt
yeastplume Jul 23, 2019
d712bb2
test fix
yeastplume Jul 23, 2019
82854c3
remove debug output
yeastplume Jul 25, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
127 changes: 74 additions & 53 deletions api/src/foreign.rs
Expand Up @@ -17,10 +17,10 @@
use crate::keychain::Keychain;
use crate::libwallet::api_impl::foreign;
use crate::libwallet::{
BlockFees, CbData, Error, NodeClient, NodeVersionInfo, Slate, VersionInfo, WalletBackend,
BlockFees, CbData, Error, NodeClient, NodeVersionInfo, Slate, VersionInfo, WalletInst,
WalletLCProvider,
};
use crate::util::Mutex;
use std::marker::PhantomData;
use std::sync::Arc;

/// ForeignAPI Middleware Check callback
Expand Down Expand Up @@ -55,30 +55,25 @@ pub enum ForeignCheckMiddlewareFn {
/// its operation, then 'close' the wallet (unloading references to the keychain and master
/// seed).

pub struct Foreign<W: ?Sized, C, K>
pub struct Foreign<'a, L, C, K>
where
W: WalletBackend<C, K>,
C: NodeClient,
K: Keychain,
L: WalletLCProvider<'a, C, K>,
C: NodeClient + 'a,
K: Keychain + 'a,
{
/// Wallet, contains its keychain (TODO: Split these up into 2 traits
/// perhaps)
pub wallet: Arc<Mutex<W>>,
/// Wallet instance
pub wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
/// Flag to normalize some output during testing. Can mostly be ignored.
pub doctest_mode: bool,
/// phantom
phantom: PhantomData<K>,
/// phantom
phantom_c: PhantomData<C>,
/// foreign check middleware
middleware: Option<ForeignCheckMiddleware>,
}

impl<'a, W: ?Sized, C, K> Foreign<W, C, K>
impl<'a, L, C, K> Foreign<'a, L, C, K>
where
W: WalletBackend<C, K>,
C: NodeClient,
K: Keychain,
L: WalletLCProvider<'a, C, K>,
C: NodeClient + 'a,
K: Keychain + 'a,
{
/// Create a new API instance with the given wallet instance. All subsequent
/// API calls will operate on this instance of the wallet.
Expand Down Expand Up @@ -110,12 +105,12 @@ where
/// use tempfile::tempdir;
///
/// use std::sync::Arc;
/// use util::Mutex;
/// use util::{Mutex, ZeroingString};
///
/// use api::Foreign;
/// use config::WalletConfig;
/// use impls::{HTTPNodeClient, LMDBBackend};
/// use libwallet::WalletBackend;
/// use impls::{DefaultWalletImpl, DefaultLCProvider, HTTPNodeClient};
/// use libwallet::WalletInst;
///
/// let mut wallet_config = WalletConfig::default();
/// # let dir = tempdir().map_err(|e| format!("{:#?}", e)).unwrap();
Expand All @@ -128,24 +123,42 @@ where
///
/// // A NodeClient must first be created to handle communication between
/// // the wallet and the node.
///
/// let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None);
/// let mut wallet:Arc<Mutex<WalletBackend<HTTPNodeClient, ExtKeychain>>> =
/// Arc::new(Mutex::new(
/// LMDBBackend::new(wallet_config.clone(), "", node_client).unwrap()
/// ));
///
/// // impls::DefaultWalletImpl is provided for convenience in instantiating the wallet
/// // It contains the LMDBBackend, DefaultLCProvider (lifecycle) and ExtKeychain used
/// // by the reference wallet implementation.
/// // These traits can be replaced with alternative implementations if desired
///
/// let mut wallet = Box::new(DefaultWalletImpl::<'static, HTTPNodeClient>::new(node_client.clone()).unwrap())
/// as Box<WalletInst<'static, DefaultLCProvider<HTTPNodeClient, ExtKeychain>, HTTPNodeClient, ExtKeychain>>;
///
/// // Wallet LifeCycle Provider provides all functions init wallet and work with seeds, etc...
/// let lc = wallet.lc_provider().unwrap();
///
/// // The top level wallet directory should be set manually (in the reference implementation,
/// // this is provided in the WalletConfig)
/// lc.set_wallet_directory(&wallet_config.data_file_dir);
///
/// // Wallet must be opened with the password (TBD)
/// let pw = ZeroingString::from("wallet_password");
/// lc.open_wallet(None, pw);
///
/// // 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);
/// // .. perform wallet operations
///
/// ```

pub fn new(wallet_in: Arc<Mutex<W>>, middleware: Option<ForeignCheckMiddleware>) -> Self {
pub fn new(
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
middleware: Option<ForeignCheckMiddleware>,
) -> Self {
Foreign {
wallet: wallet_in,
wallet_inst,
doctest_mode: false,
phantom: PhantomData,
phantom_c: PhantomData,
middleware,
}
}
Expand All @@ -168,7 +181,8 @@ where

pub fn check_version(&self) -> Result<VersionInfo, Error> {
if let Some(m) = self.middleware.as_ref() {
let mut w = self.wallet.lock();
let mut w_lock = self.wallet_inst.lock();
let w = w_lock.lc_provider()?.wallet_inst()?;
m(
ForeignCheckMiddlewareFn::CheckVersion,
w.w2n_client().get_version_info(),
Expand Down Expand Up @@ -229,18 +243,16 @@ where
/// ```

pub fn build_coinbase(&self, block_fees: &BlockFees) -> Result<CbData, Error> {
let mut w = self.wallet.lock();
let mut w_lock = self.wallet_inst.lock();
let w = w_lock.lc_provider()?.wallet_inst()?;
if let Some(m) = self.middleware.as_ref() {
m(
ForeignCheckMiddlewareFn::BuildCoinbase,
w.w2n_client().get_version_info(),
None,
)?;
}
w.open_with_credentials()?;
let res = foreign::build_coinbase(&mut *w, block_fees, self.doctest_mode);
w.close()?;
res
foreign::build_coinbase(&mut **w, block_fees, self.doctest_mode)
}

/// Verifies all messages in the slate match their public keys.
Expand Down Expand Up @@ -283,7 +295,8 @@ where

pub fn verify_slate_messages(&self, slate: &Slate) -> Result<(), Error> {
if let Some(m) = self.middleware.as_ref() {
let mut w = self.wallet.lock();
let mut w_lock = self.wallet_inst.lock();
let w = w_lock.lc_provider()?.wallet_inst()?;
m(
ForeignCheckMiddlewareFn::VerifySlateMessages,
w.w2n_client().get_version_info(),
Expand Down Expand Up @@ -355,18 +368,16 @@ where
dest_acct_name: Option<&str>,
message: Option<String>,
) -> Result<Slate, Error> {
let mut w = self.wallet.lock();
let mut w_lock = self.wallet_inst.lock();
let w = w_lock.lc_provider()?.wallet_inst()?;
if let Some(m) = self.middleware.as_ref() {
m(
ForeignCheckMiddlewareFn::ReceiveTx,
w.w2n_client().get_version_info(),
Some(slate),
)?;
}
w.open_with_credentials()?;
let res = foreign::receive_tx(&mut *w, slate, dest_acct_name, message, self.doctest_mode);
w.close()?;
res
foreign::receive_tx(&mut **w, slate, dest_acct_name, message, self.doctest_mode)
}

/// Finalizes an invoice transaction initiated by this wallet's Owner api.
Expand Down Expand Up @@ -417,18 +428,16 @@ where
/// ```

pub fn finalize_invoice_tx(&self, slate: &Slate) -> Result<Slate, Error> {
let mut w = self.wallet.lock();
let mut w_lock = self.wallet_inst.lock();
let w = w_lock.lc_provider()?.wallet_inst()?;
if let Some(m) = self.middleware.as_ref() {
m(
ForeignCheckMiddlewareFn::FinalizeInvoiceTx,
w.w2n_client().get_version_info(),
Some(slate),
)?;
}
w.open_with_credentials()?;
let res = foreign::finalize_invoice_tx(&mut *w, slate);
w.close()?;
res
foreign::finalize_invoice_tx(&mut **w, slate)
}
}

Expand All @@ -447,12 +456,12 @@ macro_rules! doctest_helper_setup_doc_env_foreign {
use tempfile::tempdir;

use std::sync::Arc;
use util::Mutex;
use util::{Mutex, ZeroingString};

use api::{Foreign, Owner};
use config::WalletConfig;
use impls::{HTTPNodeClient, LMDBBackend, WalletSeed};
use libwallet::{BlockFees, IssueInvoiceTxArgs, Slate, WalletBackend};
use impls::{DefaultLCProvider, DefaultWalletImpl, HTTPNodeClient};
use libwallet::{BlockFees, IssueInvoiceTxArgs, Slate, WalletInst};

let dir = tempdir().map_err(|e| format!("{:#?}", e)).unwrap();
let dir = dir
Expand All @@ -462,11 +471,23 @@ macro_rules! doctest_helper_setup_doc_env_foreign {
.unwrap();
let mut wallet_config = WalletConfig::default();
wallet_config.data_file_dir = dir.to_owned();
let pw = "";
let pw = ZeroingString::from("");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would be cool to see a lazy static for this. C# for example has string.Empty etc

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think this is okay, it's just test setup


let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None);
let mut $wallet: Arc<Mutex<WalletBackend<HTTPNodeClient, ExtKeychain>>> = Arc::new(
Mutex::new(LMDBBackend::new(wallet_config.clone(), pw, node_client).unwrap()),
);
let mut wallet = Box::new(
DefaultWalletImpl::<'static, HTTPNodeClient>::new(node_client.clone()).unwrap(),
)
as Box<
WalletInst<
'static,
DefaultLCProvider<HTTPNodeClient, ExtKeychain>,
HTTPNodeClient,
ExtKeychain,
>,
>;
let lc = wallet.lc_provider().unwrap();
lc.set_wallet_directory(&wallet_config.data_file_dir);
lc.open_wallet(None, pw);
let mut $wallet = Arc::new(Mutex::new(wallet));
};
}