Skip to content

Commit

Permalink
Store XORed wallet seed in-mem (mimblewimble#200)
Browse files Browse the repository at this point in the history
* experimental xor token work

* rustfmt

* test implementation of build_coinbase_t function

* rustfmt

* add separate foreign_rpc_s interface for secure functions

* rustfmt

* rustfmt

* fix http scheme to allow https as well

* add tokenized owner API, modify all functions to use token

* rustfmt

* fix for api doctests, tests passing up to api crate

* rustfmt

* controller crate compilation

* rustfmt

* controller tests passing and modified some to use masked keychains

* rustfmt

* fix wallet tests

* rustfmt

* build from github

* rustfmt
  • Loading branch information
yeastplume authored Aug 6, 2019
1 parent 461d022 commit 23b12e2
Show file tree
Hide file tree
Showing 38 changed files with 3,671 additions and 1,250 deletions.
808 changes: 430 additions & 378 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ failure = "0.1"
failure_derive = "0.1"
log = "0.4"
uuid = { version = "0.7", features = ["serde", "v4"] }
serde = "1"
serde_derive = "1"
serde_json = "1"
easy-jsonrpc = "0.5.1"
chrono = { version = "0.4.4", features = ["serde"] }
Expand Down
44 changes: 32 additions & 12 deletions api/src/foreign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use crate::libwallet::{
BlockFees, CbData, Error, NodeClient, NodeVersionInfo, Slate, VersionInfo, WalletInst,
WalletLCProvider,
};
use crate::util::secp::key::SecretKey;
use crate::util::Mutex;
use std::sync::Arc;

Expand Down Expand Up @@ -67,6 +68,8 @@ where
pub doctest_mode: bool,
/// foreign check middleware
middleware: Option<ForeignCheckMiddleware>,
/// Stored keychain mask (in case the stored wallet seed is tokenized)
keychain_mask: Option<SecretKey>,
}

impl<'a, L, C, K> Foreign<'a, L, C, K>
Expand All @@ -86,6 +89,9 @@ where
/// # Arguments
/// * `wallet_in` - A reference-counted mutex containing an implementation of the
/// [`WalletBackend`](../grin_wallet_libwallet/types/trait.WalletBackend.html) trait.
/// * `keychain_mask` - Mask value stored internally to use when calling a wallet
/// whose seed has been XORed with a token value (such as when running the foreign
/// and owner listeners in the same instance)
/// * middleware - Option middleware which containts the NodeVersionInfo and can call
/// a predefined function with the slate to check if the operation should continue
///
Expand Down Expand Up @@ -142,24 +148,26 @@ where
///
/// // Wallet must be opened with the password (TBD)
/// let pw = ZeroingString::from("wallet_password");
/// lc.open_wallet(None, pw);
/// lc.open_wallet(None, pw, false, false);
///
/// // 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);
/// let api_foreign = Foreign::new(wallet.clone(), None, None);
/// // .. perform wallet operations
///
/// ```
pub fn new(
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
keychain_mask: Option<SecretKey>,
middleware: Option<ForeignCheckMiddleware>,
) -> Self {
Foreign {
wallet_inst,
doctest_mode: false,
middleware,
keychain_mask,
}
}

Expand All @@ -173,7 +181,7 @@ where
/// ```
/// # grin_wallet_api::doctest_helper_setup_doc_env_foreign!(wallet, wallet_config);
///
/// let mut api_foreign = Foreign::new(wallet.clone(), None);
/// let mut api_foreign = Foreign::new(wallet.clone(), None, None);
///
/// let version_info = api_foreign.check_version();
/// // check and proceed accordingly
Expand Down Expand Up @@ -225,7 +233,7 @@ where
/// ```
/// # grin_wallet_api::doctest_helper_setup_doc_env_foreign!(wallet, wallet_config);
///
/// let mut api_foreign = Foreign::new(wallet.clone(), None);
/// let mut api_foreign = Foreign::new(wallet.clone(), None, None);
///
/// let block_fees = BlockFees {
/// fees: 800000,
Expand All @@ -252,7 +260,12 @@ where
None,
)?;
}
foreign::build_coinbase(&mut **w, block_fees, self.doctest_mode)
foreign::build_coinbase(
&mut **w,
(&self.keychain_mask).as_ref(),
block_fees,
self.doctest_mode,
)
}

/// Verifies all messages in the slate match their public keys.
Expand All @@ -276,7 +289,7 @@ where
/// ```
/// # grin_wallet_api::doctest_helper_setup_doc_env_foreign!(wallet, wallet_config);
///
/// let mut api_foreign = Foreign::new(wallet.clone(), None);
/// let mut api_foreign = Foreign::new(wallet.clone(), None, None);
///
/// # let slate = Slate::blank(2);
/// // Receive a slate via some means
Expand Down Expand Up @@ -349,7 +362,7 @@ where
/// ```
/// # grin_wallet_api::doctest_helper_setup_doc_env_foreign!(wallet, wallet_config);
///
/// let mut api_foreign = Foreign::new(wallet.clone(), None);
/// let mut api_foreign = Foreign::new(wallet.clone(), None, None);
/// # let slate = Slate::blank(2);
///
/// // . . .
Expand Down Expand Up @@ -377,7 +390,14 @@ where
Some(slate),
)?;
}
foreign::receive_tx(&mut **w, slate, dest_acct_name, message, self.doctest_mode)
foreign::receive_tx(
&mut **w,
(&self.keychain_mask).as_ref(),
slate,
dest_acct_name,
message,
self.doctest_mode,
)
}

/// Finalizes an invoice transaction initiated by this wallet's Owner api.
Expand Down Expand Up @@ -408,15 +428,15 @@ where
/// # grin_wallet_api::doctest_helper_setup_doc_env_foreign!(wallet, wallet_config);
///
/// let mut api_owner = Owner::new(wallet.clone());
/// let mut api_foreign = Foreign::new(wallet.clone(), None);
/// let mut api_foreign = Foreign::new(wallet.clone(), None, None);
///
/// // . . .
/// // Issue the invoice tx via the owner API
/// let args = IssueInvoiceTxArgs {
/// amount: 10_000_000_000,
/// ..Default::default()
/// };
/// let result = api_owner.issue_invoice_tx(args);
/// let result = api_owner.issue_invoice_tx(None, args);
///
/// // If result okay, send to payer, who will apply the transaction via their
/// // owner API, then send back the slate
Expand All @@ -437,7 +457,7 @@ where
Some(slate),
)?;
}
foreign::finalize_invoice_tx(&mut **w, slate)
foreign::finalize_invoice_tx(&mut **w, (&self.keychain_mask).as_ref(), slate)
}
}

Expand Down Expand Up @@ -487,7 +507,7 @@ macro_rules! doctest_helper_setup_doc_env_foreign {
>;
let lc = wallet.lc_provider().unwrap();
lc.set_wallet_directory(&wallet_config.data_file_dir);
lc.open_wallet(None, pw);
lc.open_wallet(None, pw, false, false);
let mut $wallet = Arc::new(Mutex::new(wallet));
};
}
64 changes: 46 additions & 18 deletions api/src/foreign_rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,13 @@ pub trait ForeignRpc {
}
}
# "#
# , 0, false, false);
# ,false, 0, false, false);
```
*/
fn check_version(&self) -> Result<VersionInfo, ErrorKind>;

/**
Networked version of [Foreign::build_coinbase](struct.Foreign.html#method.build_coinbase).
Networked Legacy (non-secure token) version of [Foreign::build_coinbase](struct.Foreign.html#method.build_coinbase).
# Json rpc example
Expand Down Expand Up @@ -108,9 +108,10 @@ pub trait ForeignRpc {
}
}
# "#
# , 4, false, false);
# ,false, 4, false, false);
```
*/

fn build_coinbase(&self, block_fees: &BlockFees) -> Result<CbData, ErrorKind>;

/**
Expand Down Expand Up @@ -188,7 +189,7 @@ pub trait ForeignRpc {
}
}
# "#
# ,1 ,false, false);
# ,false, 1 ,false, false);
```
*/
fn verify_slate_messages(&self, slate: &Slate) -> Result<(), ErrorKind>;
Expand Down Expand Up @@ -341,7 +342,7 @@ pub trait ForeignRpc {
}
}
# "#
# , 5, true, false);
# ,false, 5, true, false);
```
*/
fn receive_tx(
Expand Down Expand Up @@ -509,7 +510,7 @@ pub trait ForeignRpc {
}
}
# "#
# , 5, false, true);
# ,false, 5, false, true);
```
*/
fn finalize_invoice_tx(&self, slate: &Slate) -> Result<Slate, ErrorKind>;
Expand Down Expand Up @@ -571,6 +572,7 @@ fn test_check_middleware(
pub fn run_doctest_foreign(
request: serde_json::Value,
test_dir: &str,
use_token: bool,
blocks_to_mine: u64,
init_tx: bool,
init_invoice_tx: bool,
Expand Down Expand Up @@ -622,10 +624,21 @@ pub fn run_doctest_foreign(
lc.set_wallet_directory(&format!("{}/wallet1", test_dir));
lc.create_wallet(None, Some(rec_phrase_1), 32, empty_string.clone())
.unwrap();
lc.open_wallet(None, empty_string.clone()).unwrap();
let mask1 = lc
.open_wallet(None, empty_string.clone(), use_token, true)
.unwrap();
let wallet1 = Arc::new(Mutex::new(wallet1));

wallet_proxy.add_wallet("wallet1", client1.get_send_instance(), wallet1.clone());
if mask1.is_some() {
println!("WALLET 1 MASK: {:?}", mask1.clone().unwrap());
}

wallet_proxy.add_wallet(
"wallet1",
client1.get_send_instance(),
wallet1.clone(),
mask1.clone(),
);

let rec_phrase_2 = util::ZeroingString::from(
"hour kingdom ripple lunch razor inquiry coyote clay stamp mean \
Expand All @@ -646,10 +659,17 @@ pub fn run_doctest_foreign(
lc.set_wallet_directory(&format!("{}/wallet2", test_dir));
lc.create_wallet(None, Some(rec_phrase_2), 32, empty_string.clone())
.unwrap();
lc.open_wallet(None, empty_string.clone()).unwrap();
let mask2 = lc
.open_wallet(None, empty_string.clone(), use_token, true)
.unwrap();
let wallet2 = Arc::new(Mutex::new(wallet2));

wallet_proxy.add_wallet("wallet2", client2.get_send_instance(), wallet2.clone());
wallet_proxy.add_wallet(
"wallet2",
client2.get_send_instance(),
wallet2.clone(),
mask2.clone(),
);

// Set the wallet proxy listener running
thread::spawn(move || {
Expand All @@ -660,12 +680,18 @@ pub fn run_doctest_foreign(

// Mine a few blocks to wallet 1 so there's something to send
for _ in 0..blocks_to_mine {
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 1 as usize, false);
let _ = test_framework::award_blocks_to_wallet(
&chain,
wallet1.clone(),
(&mask1).as_ref(),
1 as usize,
false,
);
//update local outputs after each block, so transaction IDs stay consistent
let mut w_lock = wallet1.lock();
let w = w_lock.lc_provider().unwrap().wallet_inst().unwrap();
let (wallet_refreshed, _) =
api_impl::owner::retrieve_summary_info(&mut **w, true, 1).unwrap();
api_impl::owner::retrieve_summary_info(&mut **w, (&mask1).as_ref(), true, 1).unwrap();
assert!(wallet_refreshed);
}

Expand All @@ -678,7 +704,7 @@ pub fn run_doctest_foreign(
amount,
..Default::default()
};
api_impl::owner::issue_invoice_tx(&mut **w, args, true).unwrap()
api_impl::owner::issue_invoice_tx(&mut **w, (&mask2).as_ref(), args, true).unwrap()
};
slate = {
let mut w_lock = wallet1.lock();
Expand All @@ -692,7 +718,8 @@ pub fn run_doctest_foreign(
selection_strategy_is_use_all: true,
..Default::default()
};
api_impl::owner::process_invoice_tx(&mut **w, &slate, args, true).unwrap()
api_impl::owner::process_invoice_tx(&mut **w, (&mask1).as_ref(), &slate, args, true)
.unwrap()
};
println!("INIT INVOICE SLATE");
// Spit out slate for input to finalize_invoice_tx
Expand All @@ -712,15 +739,15 @@ pub fn run_doctest_foreign(
selection_strategy_is_use_all: true,
..Default::default()
};
let slate = api_impl::owner::init_send_tx(&mut **w, args, true).unwrap();
let slate = api_impl::owner::init_send_tx(&mut **w, (&mask1).as_ref(), args, true).unwrap();
println!("INIT SLATE");
// Spit out slate for input to finalize_tx
println!("{}", serde_json::to_string_pretty(&slate).unwrap());
}

let mut api_foreign = match init_invoice_tx {
false => Foreign::new(wallet1, Some(test_check_middleware)),
true => Foreign::new(wallet2, Some(test_check_middleware)),
false => Foreign::new(wallet1, mask1, Some(test_check_middleware)),
true => Foreign::new(wallet2, mask2, Some(test_check_middleware)),
};
api_foreign.doctest_mode = true;
let foreign_api = &api_foreign as &dyn ForeignRpc;
Expand All @@ -730,7 +757,7 @@ pub fn run_doctest_foreign(
#[doc(hidden)]
#[macro_export]
macro_rules! doctest_helper_json_rpc_foreign_assert_response {
($request:expr, $expected_response:expr, $blocks_to_mine:expr, $init_tx:expr, $init_invoice_tx:expr) => {
($request:expr, $expected_response:expr, $use_token:expr, $blocks_to_mine:expr, $init_tx:expr, $init_invoice_tx:expr) => {
// create temporary wallet, run jsonrpc request on owner api of wallet, delete wallet, return
// json response.
// In order to prevent leaking tempdirs, This function should not panic.
Expand All @@ -752,6 +779,7 @@ macro_rules! doctest_helper_json_rpc_foreign_assert_response {
let response = run_doctest_foreign(
request_val,
dir,
$use_token,
$blocks_to_mine,
$init_tx,
$init_invoice_tx,
Expand Down
15 changes: 15 additions & 0 deletions api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ extern crate grin_wallet_impls as impls;
extern crate grin_wallet_libwallet as libwallet;

extern crate failure_derive;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

#[macro_use]
Expand All @@ -39,12 +41,25 @@ mod foreign_rpc;

mod owner;
mod owner_rpc;
mod owner_rpc_s;

pub use crate::foreign::{Foreign, ForeignCheckMiddleware, ForeignCheckMiddlewareFn};
pub use crate::foreign_rpc::ForeignRpc;
pub use crate::owner::Owner;
pub use crate::owner_rpc::OwnerRpc;
pub use crate::owner_rpc_s::OwnerRpcS;

pub use crate::foreign_rpc::foreign_rpc as foreign_rpc_client;
pub use crate::foreign_rpc::run_doctest_foreign;
pub use crate::owner_rpc::run_doctest_owner;

use grin_wallet_util::grin_core::libtx::secp_ser;
use util::secp::key::SecretKey;

/// Wrapper for API Tokens
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(transparent)]
pub struct Token {
#[serde(with = "secp_ser::option_seckey_serde")]
keychain_mask: Option<SecretKey>,
}
Loading

0 comments on commit 23b12e2

Please sign in to comment.