mirror of
https://github.com/mimblewimble/grin.git
synced 2025-02-01 08:51:08 +03:00
parent
236fe56f60
commit
5a06f5dac7
23 changed files with 545 additions and 344 deletions
|
@ -13,10 +13,9 @@
|
|||
// limitations under the License.
|
||||
|
||||
//! PMMR tests
|
||||
#[macro_use]
|
||||
extern crate grin_core as core;
|
||||
extern crate chrono;
|
||||
extern crate croaring;
|
||||
extern crate grin_core as core;
|
||||
|
||||
mod vec_backend;
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ the code is organized into the following components (from highest-level to lowes
|
|||
* **libTx** - Library that provides lower-level transaction building, rangeproof and signing functions, highly-reusable by wallet implementors.
|
||||
* **Wallet Traits** - A set of generic traits defined within libWallet and the `keychain` crate . A wallet implementation such as Grin's current
|
||||
default only needs to implement these traits in order to provide a wallet:
|
||||
* **WalletClient** - Defines communication between the wallet, a running grin node and/or other wallets
|
||||
* **WalletToNodeClient** - Defines communication between the wallet, a running grin node and/or other wallets
|
||||
* **WalletBackend** - Defines the storage implementation of the wallet
|
||||
* **KeyChain** - Defines key derivation operations
|
||||
|
||||
|
@ -66,22 +66,22 @@ pub fn retrieve_outputs<T: ?Sized, C, K>(
|
|||
) -> Result<Vec<OutputData>, Error>
|
||||
where
|
||||
!·T: WalletBackend<C, K>,
|
||||
!·C: WalletClient,
|
||||
!·C: WalletToNodeClient,
|
||||
!·K: Keychain,
|
||||
{
|
||||
```
|
||||
|
||||
With `T` in this instance being a class that implements the `WalletBackend` trait, which is further parameterized with implementations of
|
||||
`WalletClient` and `Keychain`.
|
||||
`WalletToNodeClient` and `Keychain`.
|
||||
|
||||
There is currently only a single implementation of the Keychain trait within the Grin code, in the `keychain` crate exported as `ExtKeyChain`.
|
||||
The `Keychain` trait makes several assumptions about the underlying implementation, particularly that it will adhere to a
|
||||
[BIP-38 style](https://github.com/bitcoin/bips/blob/master/bip-0038.mediawiki) 'master key -> child key' model.
|
||||
|
||||
There are two implementations of `WalletClient` within the code, the main version being the `HTTPWalletClient` found within `wallet/src/client.rs` and
|
||||
the seconds a test client that communicates with an in-process instance of a chain. The WalletClient isolates all network calls, so upgrading wallet
|
||||
There are two implementations of `WalletToNodeClient` within the code, the main version being the `HTTPWalletToNodeClient` found within `wallet/src/client.rs` and
|
||||
the seconds a test client that communicates with an in-process instance of a chain. The WalletToNodeClient isolates all network calls, so upgrading wallet
|
||||
communication from the current simple http interaction to a more secure protocol (or allowing for many options) should be a simple
|
||||
matter of dropping in different `WalletClient` implementations.
|
||||
matter of dropping in different `WalletToNodeClient` implementations.
|
||||
|
||||
There are also two implementations of `WalletBackend` within the code at the base of the `wallet` crate. `LMDBBackend` found within
|
||||
`wallet/src/lmdb_wallet.rs` is the main implementation, and is now used by all grin wallet commands. The earlier `FileWallet` still exists
|
||||
|
|
|
@ -40,7 +40,7 @@ folder "Provided by Grin" as services {
|
|||
package "Traits Implemented by Wallets" as traits {
|
||||
database "WalletBackend" as wallet_backend
|
||||
database "KeyChain" as keychain
|
||||
component "WalletClient" as wallet_client
|
||||
component "WalletToNodeClient" as wallet_client
|
||||
}
|
||||
|
||||
note left of wallet_client
|
||||
|
|
|
@ -30,7 +30,7 @@ use std::{fs, thread, time};
|
|||
use util::Mutex;
|
||||
|
||||
use framework::keychain::Keychain;
|
||||
use wallet::{HTTPWalletClient, LMDBBackend, WalletConfig};
|
||||
use wallet::{HTTPWalletToNodeClient, HTTPWalletToWalletClient, LMDBBackend, WalletConfig};
|
||||
|
||||
/// Just removes all results from previous runs
|
||||
pub fn clean_all_output(test_name_dir: &str) {
|
||||
|
@ -265,19 +265,27 @@ impl LocalServerContainer {
|
|||
let _ = fs::create_dir_all(self.wallet_config.clone().data_file_dir);
|
||||
let r = wallet::WalletSeed::init_file(&self.wallet_config);
|
||||
|
||||
let client = HTTPWalletClient::new(&self.wallet_config.check_node_api_http_addr, None);
|
||||
let client_n =
|
||||
HTTPWalletToNodeClient::new(&self.wallet_config.check_node_api_http_addr, None);
|
||||
let client_w = HTTPWalletToWalletClient::new();
|
||||
|
||||
if let Err(_e) = r {
|
||||
//panic!("Error initializing wallet seed: {}", e);
|
||||
}
|
||||
|
||||
let wallet: LMDBBackend<HTTPWalletClient, keychain::ExtKeychain> =
|
||||
LMDBBackend::new(self.wallet_config.clone(), "", client).unwrap_or_else(|e| {
|
||||
panic!(
|
||||
"Error creating wallet: {:?} Config: {:?}",
|
||||
e, self.wallet_config
|
||||
)
|
||||
});
|
||||
let wallet: LMDBBackend<
|
||||
HTTPWalletToNodeClient,
|
||||
HTTPWalletToWalletClient,
|
||||
keychain::ExtKeychain,
|
||||
> =
|
||||
LMDBBackend::new(self.wallet_config.clone(), "", client_n, client_w).unwrap_or_else(
|
||||
|e| {
|
||||
panic!(
|
||||
"Error creating wallet: {:?} Config: {:?}",
|
||||
e, self.wallet_config
|
||||
)
|
||||
},
|
||||
);
|
||||
|
||||
wallet::controller::foreign_listener(
|
||||
Arc::new(Mutex::new(wallet)),
|
||||
|
@ -308,8 +316,9 @@ impl LocalServerContainer {
|
|||
let keychain: keychain::ExtKeychain = wallet_seed
|
||||
.derive_keychain("")
|
||||
.expect("Failed to derive keychain from seed file and passphrase.");
|
||||
let client = HTTPWalletClient::new(&config.check_node_api_http_addr, None);
|
||||
let mut wallet = LMDBBackend::new(config.clone(), "", client)
|
||||
let client_n = HTTPWalletToNodeClient::new(&config.check_node_api_http_addr, None);
|
||||
let client_w = HTTPWalletToWalletClient::new();
|
||||
let mut wallet = LMDBBackend::new(config.clone(), "", client_n, client_w)
|
||||
.unwrap_or_else(|e| panic!("Error creating wallet: {:?} Config: {:?}", e, config));
|
||||
wallet.keychain = Some(keychain);
|
||||
let parent_id = keychain::ExtKeychain::derive_key_id(2, 0, 0, 0, 0);
|
||||
|
@ -335,12 +344,13 @@ impl LocalServerContainer {
|
|||
.derive_keychain("")
|
||||
.expect("Failed to derive keychain from seed file and passphrase.");
|
||||
|
||||
let client = HTTPWalletClient::new(&config.check_node_api_http_addr, None);
|
||||
let client_n = HTTPWalletToNodeClient::new(&config.check_node_api_http_addr, None);
|
||||
let client_w = HTTPWalletToWalletClient::new();
|
||||
|
||||
let max_outputs = 500;
|
||||
let change_outputs = 1;
|
||||
|
||||
let mut wallet = LMDBBackend::new(config.clone(), "", client)
|
||||
let mut wallet = LMDBBackend::new(config.clone(), "", client_n, client_w)
|
||||
.unwrap_or_else(|e| panic!("Error creating wallet: {:?} Config: {:?}", e, config));
|
||||
wallet.keychain = Some(keychain);
|
||||
let _ = wallet::controller::owner_single_use(Arc::new(Mutex::new(wallet)), |api| {
|
||||
|
|
|
@ -40,8 +40,8 @@ use wallet::controller;
|
|||
use wallet::libtx::slate::Slate;
|
||||
use wallet::libwallet::types::{WalletBackend, WalletInst};
|
||||
use wallet::lmdb_wallet::LMDBBackend;
|
||||
use wallet::HTTPWalletClient;
|
||||
use wallet::WalletConfig;
|
||||
use wallet::{HTTPWalletToNodeClient, HTTPWalletToWalletClient};
|
||||
|
||||
use framework::{
|
||||
config, stop_all_servers, LocalServerContainerConfig, LocalServerContainerPool,
|
||||
|
@ -880,15 +880,19 @@ fn long_fork_test_case_6(s: &Vec<servers::Server>) {
|
|||
|
||||
pub fn create_wallet(
|
||||
dir: &str,
|
||||
client: HTTPWalletClient,
|
||||
) -> Arc<Mutex<WalletInst<HTTPWalletClient, keychain::ExtKeychain>>> {
|
||||
client_n: HTTPWalletToNodeClient,
|
||||
client_w: HTTPWalletToWalletClient,
|
||||
) -> Arc<Mutex<WalletInst<HTTPWalletToNodeClient, HTTPWalletToWalletClient, keychain::ExtKeychain>>>
|
||||
{
|
||||
let mut wallet_config = WalletConfig::default();
|
||||
wallet_config.data_file_dir = String::from(dir);
|
||||
let _ = wallet::WalletSeed::init_file(&wallet_config);
|
||||
let mut wallet: LMDBBackend<HTTPWalletClient, keychain::ExtKeychain> =
|
||||
LMDBBackend::new(wallet_config.clone(), "", client).unwrap_or_else(|e| {
|
||||
panic!("Error creating wallet: {:?} Config: {:?}", e, wallet_config)
|
||||
});
|
||||
let mut wallet: LMDBBackend<
|
||||
HTTPWalletToNodeClient,
|
||||
HTTPWalletToWalletClient,
|
||||
keychain::ExtKeychain,
|
||||
> = LMDBBackend::new(wallet_config.clone(), "", client_n, client_w)
|
||||
.unwrap_or_else(|e| panic!("Error creating wallet: {:?} Config: {:?}", e, wallet_config));
|
||||
wallet.open_with_credentials().unwrap_or_else(|e| {
|
||||
panic!(
|
||||
"Error initializing wallet: {:?} Config: {:?}",
|
||||
|
@ -908,16 +912,26 @@ fn replicate_tx_fluff_failure() {
|
|||
|
||||
// Create Wallet 1 (Mining Input) and start it listening
|
||||
// Wallet 1 post to another node, just for fun
|
||||
let client1 = HTTPWalletClient::new("http://127.0.0.1:23003", None);
|
||||
let wallet1 = create_wallet("target/tmp/tx_fluff/wallet1", client1.clone());
|
||||
let client1 = HTTPWalletToNodeClient::new("http://127.0.0.1:23003", None);
|
||||
let client1_w = HTTPWalletToWalletClient::new();
|
||||
let wallet1 = create_wallet(
|
||||
"target/tmp/tx_fluff/wallet1",
|
||||
client1.clone(),
|
||||
client1_w.clone(),
|
||||
);
|
||||
let wallet1_handle = thread::spawn(move || {
|
||||
controller::foreign_listener(wallet1, "127.0.0.1:33000", None)
|
||||
.unwrap_or_else(|e| panic!("Error creating wallet1 listener: {:?}", e,));
|
||||
});
|
||||
|
||||
// Create Wallet 2 (Recipient) and launch
|
||||
let client2 = HTTPWalletClient::new("http://127.0.0.1:23001", None);
|
||||
let wallet2 = create_wallet("target/tmp/tx_fluff/wallet2", client2.clone());
|
||||
let client2 = HTTPWalletToNodeClient::new("http://127.0.0.1:23001", None);
|
||||
let client2_w = HTTPWalletToWalletClient::new();
|
||||
let wallet2 = create_wallet(
|
||||
"target/tmp/tx_fluff/wallet2",
|
||||
client2.clone(),
|
||||
client2_w.clone(),
|
||||
);
|
||||
let wallet2_handle = thread::spawn(move || {
|
||||
controller::foreign_listener(wallet2, "127.0.0.1:33001", None)
|
||||
.unwrap_or_else(|e| panic!("Error creating wallet2 listener: {:?}", e,));
|
||||
|
@ -957,7 +971,11 @@ fn replicate_tx_fluff_failure() {
|
|||
thread::sleep(time::Duration::from_secs(10));
|
||||
|
||||
// get another instance of wallet1 (to update contents and perform a send)
|
||||
let wallet1 = create_wallet("target/tmp/tx_fluff/wallet1", client1.clone());
|
||||
let wallet1 = create_wallet(
|
||||
"target/tmp/tx_fluff/wallet1",
|
||||
client1.clone(),
|
||||
client1_w.clone(),
|
||||
);
|
||||
|
||||
let amount = 30_000_000_000;
|
||||
let mut slate = Slate::blank(1);
|
||||
|
@ -980,7 +998,11 @@ fn replicate_tx_fluff_failure() {
|
|||
thread::sleep(time::Duration::from_secs(200));
|
||||
|
||||
// get another instance of wallet (to check contents)
|
||||
let wallet2 = create_wallet("target/tmp/tx_fluff/wallet2", client2.clone());
|
||||
let wallet2 = create_wallet(
|
||||
"target/tmp/tx_fluff/wallet2",
|
||||
client2.clone(),
|
||||
client2_w.clone(),
|
||||
);
|
||||
|
||||
wallet::controller::owner_single_use(wallet2, |api| {
|
||||
let res = api.retrieve_summary_info(true).unwrap();
|
||||
|
|
|
@ -29,7 +29,8 @@ use core::{core, global};
|
|||
use grin_wallet::libwallet::ErrorKind;
|
||||
use grin_wallet::{self, controller, display, libwallet};
|
||||
use grin_wallet::{
|
||||
HTTPWalletClient, LMDBBackend, WalletBackend, WalletConfig, WalletInst, WalletSeed,
|
||||
HTTPWalletToNodeClient, HTTPWalletToWalletClient, LMDBBackend, WalletBackend, WalletConfig,
|
||||
WalletInst, WalletSeed,
|
||||
};
|
||||
use keychain;
|
||||
use servers::start_webwallet_server;
|
||||
|
@ -56,10 +57,13 @@ pub fn instantiate_wallet(
|
|||
passphrase: &str,
|
||||
account: &str,
|
||||
node_api_secret: Option<String>,
|
||||
) -> Arc<Mutex<WalletInst<HTTPWalletClient, keychain::ExtKeychain>>> {
|
||||
let client = HTTPWalletClient::new(&wallet_config.check_node_api_http_addr, node_api_secret);
|
||||
let mut db_wallet =
|
||||
LMDBBackend::new(wallet_config.clone(), passphrase, client).unwrap_or_else(|e| {
|
||||
) -> Arc<Mutex<WalletInst<HTTPWalletToNodeClient, HTTPWalletToWalletClient, keychain::ExtKeychain>>>
|
||||
{
|
||||
let client_n =
|
||||
HTTPWalletToNodeClient::new(&wallet_config.check_node_api_http_addr, node_api_secret);
|
||||
let client_w = HTTPWalletToWalletClient::new();
|
||||
let mut db_wallet = LMDBBackend::new(wallet_config.clone(), passphrase, client_n, client_w)
|
||||
.unwrap_or_else(|e| {
|
||||
panic!(
|
||||
"Error creating DB wallet: {} Config: {:?}",
|
||||
e, wallet_config
|
||||
|
@ -105,15 +109,19 @@ pub fn wallet_command(wallet_args: &ArgMatches, config: GlobalWalletConfig) -> i
|
|||
if let ("init", Some(_)) = wallet_args.subcommand() {
|
||||
WalletSeed::init_file(&wallet_config).expect("Failed to init wallet seed file.");
|
||||
info!("Wallet seed file created");
|
||||
let client =
|
||||
HTTPWalletClient::new(&wallet_config.check_node_api_http_addr, node_api_secret);
|
||||
let _: LMDBBackend<HTTPWalletClient, keychain::ExtKeychain> =
|
||||
LMDBBackend::new(wallet_config.clone(), "", client).unwrap_or_else(|e| {
|
||||
panic!(
|
||||
"Error creating DB for wallet: {} Config: {:?}",
|
||||
e, wallet_config
|
||||
);
|
||||
});
|
||||
let client_n =
|
||||
HTTPWalletToNodeClient::new(&wallet_config.check_node_api_http_addr, node_api_secret);
|
||||
let client_w = HTTPWalletToWalletClient::new();
|
||||
let _: LMDBBackend<
|
||||
HTTPWalletToNodeClient,
|
||||
HTTPWalletToWalletClient,
|
||||
keychain::ExtKeychain,
|
||||
> = LMDBBackend::new(wallet_config.clone(), "", client_n, client_w).unwrap_or_else(|e| {
|
||||
panic!(
|
||||
"Error creating DB for wallet: {} Config: {:?}",
|
||||
e, wallet_config
|
||||
);
|
||||
});
|
||||
info!("Wallet database backend created");
|
||||
// give logging thread a moment to catch up
|
||||
thread::sleep(Duration::from_millis(200));
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Client functions, implementations of the WalletClient trait
|
||||
//! Client functions, implementations of the WalletToNodeClient trait
|
||||
//! specific to the FileWallet
|
||||
|
||||
use failure::ResultExt;
|
||||
|
@ -30,22 +30,22 @@ use util;
|
|||
use util::secp::pedersen;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct HTTPWalletClient {
|
||||
pub struct HTTPWalletToNodeClient {
|
||||
node_url: String,
|
||||
node_api_secret: Option<String>,
|
||||
}
|
||||
|
||||
impl HTTPWalletClient {
|
||||
impl HTTPWalletToNodeClient {
|
||||
/// Create a new client that will communicate with the given grin node
|
||||
pub fn new(node_url: &str, node_api_secret: Option<String>) -> HTTPWalletClient {
|
||||
HTTPWalletClient {
|
||||
pub fn new(node_url: &str, node_api_secret: Option<String>) -> HTTPWalletToNodeClient {
|
||||
HTTPWalletToNodeClient {
|
||||
node_url: node_url.to_owned(),
|
||||
node_api_secret: node_api_secret,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WalletClient for HTTPWalletClient {
|
||||
impl WalletToNodeClient for HTTPWalletToNodeClient {
|
||||
fn node_url(&self) -> &str {
|
||||
&self.node_url
|
||||
}
|
||||
|
@ -53,50 +53,6 @@ impl WalletClient for HTTPWalletClient {
|
|||
self.node_api_secret.clone()
|
||||
}
|
||||
|
||||
/// Call the wallet API to create a coinbase output for the given
|
||||
/// block_fees. Will retry based on default "retry forever with backoff"
|
||||
/// behavior.
|
||||
fn create_coinbase(
|
||||
&self,
|
||||
dest: &str,
|
||||
block_fees: &BlockFees,
|
||||
) -> Result<CbData, libwallet::Error> {
|
||||
let url = format!("{}/v1/wallet/foreign/build_coinbase", dest);
|
||||
match single_create_coinbase(&url, &block_fees) {
|
||||
Err(e) => {
|
||||
error!(
|
||||
"Failed to get coinbase from {}. Run grin wallet listen?",
|
||||
url
|
||||
);
|
||||
error!("Underlying Error: {}", e.cause().unwrap());
|
||||
error!("Backtrace: {}", e.backtrace().unwrap());
|
||||
Err(libwallet::ErrorKind::ClientCallback(
|
||||
"Failed to get coinbase",
|
||||
))?
|
||||
}
|
||||
Ok(res) => Ok(res),
|
||||
}
|
||||
}
|
||||
|
||||
/// Send the slate to a listening wallet instance
|
||||
fn send_tx_slate(&self, dest: &str, slate: &Slate) -> Result<Slate, libwallet::Error> {
|
||||
if &dest[..4] != "http" {
|
||||
let err_str = format!(
|
||||
"dest formatted as {} but send -d expected stdout or http://IP:port",
|
||||
dest
|
||||
);
|
||||
error!("{}", err_str,);
|
||||
Err(libwallet::ErrorKind::Uri)?
|
||||
}
|
||||
let url = format!("{}/v1/wallet/foreign/receive_tx", dest);
|
||||
debug!("Posting transaction slate to {}", url);
|
||||
|
||||
let res = api::client::post(url.as_str(), None, slate).context(
|
||||
libwallet::ErrorKind::ClientCallback("Posting transaction slate"),
|
||||
)?;
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
/// Posts a transaction to a grin node
|
||||
fn post_tx(&self, tx: &TxWrapper, fluff: bool) -> Result<(), libwallet::Error> {
|
||||
let url;
|
||||
|
@ -219,6 +175,63 @@ impl WalletClient for HTTPWalletClient {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct HTTPWalletToWalletClient {}
|
||||
|
||||
impl HTTPWalletToWalletClient {
|
||||
/// Create a new client that will communicate other wallets
|
||||
pub fn new() -> HTTPWalletToWalletClient {
|
||||
HTTPWalletToWalletClient {}
|
||||
}
|
||||
}
|
||||
|
||||
impl WalletToWalletClient for HTTPWalletToWalletClient {
|
||||
/// Call the wallet API to create a coinbase output for the given
|
||||
/// block_fees. Will retry based on default "retry forever with backoff"
|
||||
/// behavior.
|
||||
fn create_coinbase(
|
||||
&self,
|
||||
dest: &str,
|
||||
block_fees: &BlockFees,
|
||||
) -> Result<CbData, libwallet::Error> {
|
||||
let url = format!("{}/v1/wallet/foreign/build_coinbase", dest);
|
||||
match single_create_coinbase(&url, &block_fees) {
|
||||
Err(e) => {
|
||||
error!(
|
||||
"Failed to get coinbase from {}. Run grin wallet listen?",
|
||||
url
|
||||
);
|
||||
error!("Underlying Error: {}", e.cause().unwrap());
|
||||
error!("Backtrace: {}", e.backtrace().unwrap());
|
||||
Err(libwallet::ErrorKind::ClientCallback(
|
||||
"Failed to get coinbase",
|
||||
))?
|
||||
}
|
||||
Ok(res) => Ok(res),
|
||||
}
|
||||
}
|
||||
|
||||
/// Send the slate to a listening wallet instance
|
||||
fn send_tx_slate(&self, dest: &str, slate: &Slate) -> Result<Slate, libwallet::Error> {
|
||||
if &dest[..4] != "http" {
|
||||
let err_str = format!(
|
||||
"dest formatted as {} but send -d expected stdout or http://IP:port",
|
||||
dest
|
||||
);
|
||||
error!("{}", err_str,);
|
||||
Err(libwallet::ErrorKind::Uri)?
|
||||
}
|
||||
let url = format!("{}/v1/wallet/foreign/receive_tx", dest);
|
||||
debug!("Posting transaction slate to {}", url);
|
||||
|
||||
let res = api::client::post(url.as_str(), None, slate).context(
|
||||
libwallet::ErrorKind::ClientCallback("Posting transaction slate"),
|
||||
)?;
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
/// Call the wallet API to create a coinbase output for the given block_fees.
|
||||
/// Will retry based on default "retry forever with backoff" behavior.
|
||||
pub fn create_coinbase(dest: &str, block_fees: &BlockFees) -> Result<CbData, Error> {
|
||||
|
|
|
@ -53,11 +53,12 @@ pub mod libwallet;
|
|||
pub mod lmdb_wallet;
|
||||
mod types;
|
||||
|
||||
pub use client::{create_coinbase, HTTPWalletClient};
|
||||
pub use client::{create_coinbase, HTTPWalletToNodeClient, HTTPWalletToWalletClient};
|
||||
pub use error::{Error, ErrorKind};
|
||||
pub use libwallet::controller;
|
||||
pub use libwallet::types::{
|
||||
BlockFees, CbData, WalletBackend, WalletClient, WalletInfo, WalletInst,
|
||||
BlockFees, CbData, WalletBackend, WalletInfo, WalletInst, WalletToNodeClient,
|
||||
WalletToWalletClient,
|
||||
};
|
||||
pub use lmdb_wallet::{wallet_db_exists, LMDBBackend};
|
||||
pub use types::{WalletConfig, WalletSeed, SEED_FILE};
|
||||
|
|
|
@ -33,7 +33,7 @@ use libtx::slate::Slate;
|
|||
use libwallet::internal::{keys, selection, tx, updater};
|
||||
use libwallet::types::{
|
||||
AcctPathMapping, BlockFees, CbData, OutputData, TxLogEntry, TxWrapper, WalletBackend,
|
||||
WalletClient, WalletInfo,
|
||||
WalletInfo, WalletToNodeClient, WalletToWalletClient,
|
||||
};
|
||||
use libwallet::{Error, ErrorKind};
|
||||
use util;
|
||||
|
@ -41,10 +41,11 @@ use util::secp::pedersen;
|
|||
|
||||
/// Wrapper around internal API functions, containing a reference to
|
||||
/// the wallet/keychain that they're acting upon
|
||||
pub struct APIOwner<W: ?Sized, C, K>
|
||||
pub struct APIOwner<W: ?Sized, C, L, K>
|
||||
where
|
||||
W: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
W: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
/// Wallet, contains its keychain (TODO: Split these up into 2 traits
|
||||
|
@ -52,12 +53,14 @@ where
|
|||
pub wallet: Arc<Mutex<W>>,
|
||||
phantom: PhantomData<K>,
|
||||
phantom_c: PhantomData<C>,
|
||||
phantom_l: PhantomData<L>,
|
||||
}
|
||||
|
||||
impl<W: ?Sized, C, K> APIOwner<W, C, K>
|
||||
impl<W: ?Sized, C, L, K> APIOwner<W, C, L, K>
|
||||
where
|
||||
W: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
W: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
/// Create new API instance
|
||||
|
@ -66,6 +69,7 @@ where
|
|||
wallet: wallet_in,
|
||||
phantom: PhantomData,
|
||||
phantom_c: PhantomData,
|
||||
phantom_l: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,7 +176,7 @@ where
|
|||
let mut slate_out: Slate;
|
||||
let lock_fn_out;
|
||||
|
||||
client = w.client().clone();
|
||||
client = w.w2w_client().clone();
|
||||
let (slate, context, lock_fn) = tx::create_send_tx(
|
||||
&mut *w,
|
||||
amount,
|
||||
|
@ -352,7 +356,8 @@ where
|
|||
&parent_key_id,
|
||||
)?;
|
||||
let tx_hex = util::to_hex(ser::ser_vec(&tx_burn).unwrap());
|
||||
w.client().post_tx(&TxWrapper { tx_hex: tx_hex }, false)?;
|
||||
w.w2n_client()
|
||||
.post_tx(&TxWrapper { tx_hex: tx_hex }, false)?;
|
||||
w.close()?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -362,7 +367,7 @@ where
|
|||
let tx_hex = util::to_hex(ser::ser_vec(&slate.tx).unwrap());
|
||||
let client = {
|
||||
let mut w = self.wallet.lock();
|
||||
w.client().clone()
|
||||
w.w2n_client().clone()
|
||||
};
|
||||
let res = client.post_tx(&TxWrapper { tx_hex: tx_hex }, fluff);
|
||||
if let Err(e) = res {
|
||||
|
@ -423,7 +428,7 @@ where
|
|||
let mut w = self.wallet.lock();
|
||||
w.open_with_credentials()?;
|
||||
let parent_key_id = w.parent_key_id();
|
||||
client = w.client().clone();
|
||||
client = w.w2n_client().clone();
|
||||
let res = tx::retrieve_tx_hex(&mut *w, &parent_key_id, tx_id)?;
|
||||
w.close()?;
|
||||
res
|
||||
|
@ -475,7 +480,7 @@ where
|
|||
let res = {
|
||||
let mut w = self.wallet.lock();
|
||||
w.open_with_credentials()?;
|
||||
w.client().get_chain_height()
|
||||
w.w2n_client().get_chain_height()
|
||||
};
|
||||
match res {
|
||||
Ok(height) => Ok((height, true)),
|
||||
|
@ -502,10 +507,11 @@ where
|
|||
|
||||
/// Wrapper around external API functions, intended to communicate
|
||||
/// with other parties
|
||||
pub struct APIForeign<W: ?Sized, C, K>
|
||||
pub struct APIForeign<W: ?Sized, C, L, K>
|
||||
where
|
||||
W: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
W: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
/// Wallet, contains its keychain (TODO: Split these up into 2 traits
|
||||
|
@ -513,12 +519,14 @@ where
|
|||
pub wallet: Arc<Mutex<W>>,
|
||||
phantom: PhantomData<K>,
|
||||
phantom_c: PhantomData<C>,
|
||||
phantom_l: PhantomData<L>,
|
||||
}
|
||||
|
||||
impl<'a, W: ?Sized, C, K> APIForeign<W, C, K>
|
||||
impl<'a, W: ?Sized, C, L, K> APIForeign<W, C, L, K>
|
||||
where
|
||||
W: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
W: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
/// Create new API instance
|
||||
|
@ -527,6 +535,7 @@ where
|
|||
wallet: wallet_in,
|
||||
phantom: PhantomData,
|
||||
phantom_c: PhantomData,
|
||||
phantom_l: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,8 @@ use keychain::Keychain;
|
|||
use libtx::slate::Slate;
|
||||
use libwallet::api::{APIForeign, APIOwner};
|
||||
use libwallet::types::{
|
||||
CbData, OutputData, SendTXArgs, TxLogEntry, WalletBackend, WalletClient, WalletInfo,
|
||||
CbData, OutputData, SendTXArgs, TxLogEntry, WalletBackend, WalletInfo, WalletToNodeClient,
|
||||
WalletToWalletClient,
|
||||
};
|
||||
use libwallet::{Error, ErrorKind};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -41,11 +42,12 @@ use util::Mutex;
|
|||
|
||||
/// Instantiate wallet Owner API for a single-use (command line) call
|
||||
/// Return a function containing a loaded API context to call
|
||||
pub fn owner_single_use<F, T: ?Sized, C, K>(wallet: Arc<Mutex<T>>, f: F) -> Result<(), Error>
|
||||
pub fn owner_single_use<F, T: ?Sized, C, L, K>(wallet: Arc<Mutex<T>>, f: F) -> Result<(), Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
F: FnOnce(&mut APIOwner<T, C, K>) -> Result<(), Error>,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K>,
|
||||
F: FnOnce(&mut APIOwner<T, C, L, K>) -> Result<(), Error>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
f(&mut APIOwner::new(wallet.clone()))?;
|
||||
|
@ -54,11 +56,12 @@ where
|
|||
|
||||
/// Instantiate wallet Foreign API for a single-use (command line) call
|
||||
/// Return a function containing a loaded API context to call
|
||||
pub fn foreign_single_use<F, T: ?Sized, C, K>(wallet: Arc<Mutex<T>>, f: F) -> Result<(), Error>
|
||||
pub fn foreign_single_use<F, T: ?Sized, C, L, K>(wallet: Arc<Mutex<T>>, f: F) -> Result<(), Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
F: FnOnce(&mut APIForeign<T, C, K>) -> Result<(), Error>,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K>,
|
||||
F: FnOnce(&mut APIForeign<T, C, L, K>) -> Result<(), Error>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
f(&mut APIForeign::new(wallet.clone()))?;
|
||||
|
@ -67,16 +70,17 @@ where
|
|||
|
||||
/// Listener version, providing same API but listening for requests on a
|
||||
/// port and wrapping the calls
|
||||
pub fn owner_listener<T: ?Sized, C, K>(
|
||||
pub fn owner_listener<T: ?Sized, C, L, K>(
|
||||
wallet: Arc<Mutex<T>>,
|
||||
addr: &str,
|
||||
api_secret: Option<String>,
|
||||
tls_config: Option<TLSConfig>,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
T: WalletBackend<C, K> + Send + Sync + 'static,
|
||||
OwnerAPIHandler<T, C, K>: Handler,
|
||||
C: WalletClient + 'static,
|
||||
T: WalletBackend<C, L, K> + Send + Sync + 'static,
|
||||
OwnerAPIHandler<T, C, L, K>: Handler,
|
||||
C: WalletToNodeClient + 'static,
|
||||
L: WalletToWalletClient + 'static,
|
||||
K: Keychain + 'static,
|
||||
{
|
||||
let api_handler = OwnerAPIHandler::new(wallet);
|
||||
|
@ -108,14 +112,15 @@ where
|
|||
|
||||
/// Listener version, providing same API but listening for requests on a
|
||||
/// port and wrapping the calls
|
||||
pub fn foreign_listener<T: ?Sized, C, K>(
|
||||
pub fn foreign_listener<T: ?Sized, C, L, K>(
|
||||
wallet: Arc<Mutex<T>>,
|
||||
addr: &str,
|
||||
tls_config: Option<TLSConfig>,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
T: WalletBackend<C, K> + Send + Sync + 'static,
|
||||
C: WalletClient + 'static,
|
||||
T: WalletBackend<C, L, K> + Send + Sync + 'static,
|
||||
C: WalletToNodeClient + 'static,
|
||||
L: WalletToWalletClient + 'static,
|
||||
K: Keychain + 'static,
|
||||
{
|
||||
let api_handler = ForeignAPIHandler::new(wallet);
|
||||
|
@ -142,37 +147,41 @@ where
|
|||
type WalletResponseFuture = Box<Future<Item = Response<Body>, Error = Error> + Send>;
|
||||
|
||||
/// API Handler/Wrapper for owner functions
|
||||
pub struct OwnerAPIHandler<T: ?Sized, C, K>
|
||||
pub struct OwnerAPIHandler<T: ?Sized, C, L, K>
|
||||
where
|
||||
T: WalletBackend<C, K> + Send + Sync + 'static,
|
||||
C: WalletClient + 'static,
|
||||
T: WalletBackend<C, L, K> + Send + Sync + 'static,
|
||||
C: WalletToNodeClient + 'static,
|
||||
L: WalletToWalletClient + 'static,
|
||||
K: Keychain + 'static,
|
||||
{
|
||||
/// Wallet instance
|
||||
pub wallet: Arc<Mutex<T>>,
|
||||
phantom: PhantomData<K>,
|
||||
phantom_c: PhantomData<C>,
|
||||
phantom_l: PhantomData<L>,
|
||||
}
|
||||
|
||||
impl<T: ?Sized, C, K> OwnerAPIHandler<T, C, K>
|
||||
impl<T: ?Sized, C, L, K> OwnerAPIHandler<T, C, L, K>
|
||||
where
|
||||
T: WalletBackend<C, K> + Send + Sync + 'static,
|
||||
C: WalletClient + 'static,
|
||||
T: WalletBackend<C, L, K> + Send + Sync + 'static,
|
||||
C: WalletToNodeClient + 'static,
|
||||
L: WalletToWalletClient + 'static,
|
||||
K: Keychain + 'static,
|
||||
{
|
||||
/// Create a new owner API handler for GET methods
|
||||
pub fn new(wallet: Arc<Mutex<T>>) -> OwnerAPIHandler<T, C, K> {
|
||||
pub fn new(wallet: Arc<Mutex<T>>) -> OwnerAPIHandler<T, C, L, K> {
|
||||
OwnerAPIHandler {
|
||||
wallet,
|
||||
phantom: PhantomData,
|
||||
phantom_c: PhantomData,
|
||||
phantom_l: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
fn retrieve_outputs(
|
||||
&self,
|
||||
req: &Request<Body>,
|
||||
api: APIOwner<T, C, K>,
|
||||
api: APIOwner<T, C, L, K>,
|
||||
) -> Result<(bool, Vec<(OutputData, pedersen::Commitment)>), Error> {
|
||||
let mut update_from_node = false;
|
||||
let mut id = None;
|
||||
|
@ -196,7 +205,7 @@ where
|
|||
fn retrieve_txs(
|
||||
&self,
|
||||
req: &Request<Body>,
|
||||
api: APIOwner<T, C, K>,
|
||||
api: APIOwner<T, C, L, K>,
|
||||
) -> Result<(bool, Vec<TxLogEntry>), Error> {
|
||||
let mut id = None;
|
||||
let mut update_from_node = false;
|
||||
|
@ -217,7 +226,7 @@ where
|
|||
fn dump_stored_tx(
|
||||
&self,
|
||||
req: &Request<Body>,
|
||||
api: APIOwner<T, C, K>,
|
||||
api: APIOwner<T, C, L, K>,
|
||||
) -> Result<Transaction, Error> {
|
||||
let params = parse_params(req);
|
||||
if let Some(id_string) = params.get("id") {
|
||||
|
@ -246,7 +255,7 @@ where
|
|||
fn retrieve_summary_info(
|
||||
&self,
|
||||
req: &Request<Body>,
|
||||
mut api: APIOwner<T, C, K>,
|
||||
mut api: APIOwner<T, C, L, K>,
|
||||
) -> Result<(bool, WalletInfo), Error> {
|
||||
let update_from_node = param_exists(req, "refresh");
|
||||
api.retrieve_summary_info(update_from_node)
|
||||
|
@ -255,7 +264,7 @@ where
|
|||
fn node_height(
|
||||
&self,
|
||||
_req: &Request<Body>,
|
||||
mut api: APIOwner<T, C, K>,
|
||||
mut api: APIOwner<T, C, L, K>,
|
||||
) -> Result<(u64, bool), Error> {
|
||||
api.node_height()
|
||||
}
|
||||
|
@ -283,7 +292,7 @@ where
|
|||
fn issue_send_tx(
|
||||
&self,
|
||||
req: Request<Body>,
|
||||
mut api: APIOwner<T, C, K>,
|
||||
mut api: APIOwner<T, C, L, K>,
|
||||
) -> Box<Future<Item = Slate, Error = Error> + Send> {
|
||||
Box::new(parse_body(req).and_then(move |args: SendTXArgs| {
|
||||
if args.method == "http" {
|
||||
|
@ -315,7 +324,7 @@ where
|
|||
fn finalize_tx(
|
||||
&self,
|
||||
req: Request<Body>,
|
||||
mut api: APIOwner<T, C, K>,
|
||||
mut api: APIOwner<T, C, L, K>,
|
||||
) -> Box<Future<Item = Slate, Error = Error> + Send> {
|
||||
Box::new(
|
||||
parse_body(req).and_then(move |mut slate| match api.finalize_tx(&mut slate) {
|
||||
|
@ -331,7 +340,7 @@ where
|
|||
fn cancel_tx(
|
||||
&self,
|
||||
req: Request<Body>,
|
||||
mut api: APIOwner<T, C, K>,
|
||||
mut api: APIOwner<T, C, L, K>,
|
||||
) -> Box<Future<Item = (), Error = Error> + Send> {
|
||||
let params = parse_params(&req);
|
||||
if let Some(id_string) = params.get("id") {
|
||||
|
@ -360,7 +369,7 @@ where
|
|||
fn post_tx(
|
||||
&self,
|
||||
req: Request<Body>,
|
||||
api: APIOwner<T, C, K>,
|
||||
api: APIOwner<T, C, L, K>,
|
||||
) -> Box<Future<Item = (), Error = Error> + Send> {
|
||||
let params = match req.uri().query() {
|
||||
Some(query_string) => form_urlencoded::parse(query_string.as_bytes())
|
||||
|
@ -386,7 +395,7 @@ where
|
|||
fn issue_burn_tx(
|
||||
&self,
|
||||
_req: Request<Body>,
|
||||
mut api: APIOwner<T, C, K>,
|
||||
mut api: APIOwner<T, C, L, K>,
|
||||
) -> Box<Future<Item = (), Error = Error> + Send> {
|
||||
// TODO: Args
|
||||
Box::new(match api.issue_burn_tx(60, 10, 1000) {
|
||||
|
@ -432,10 +441,11 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized, C, K> Handler for OwnerAPIHandler<T, C, K>
|
||||
impl<T: ?Sized, C, L, K> Handler for OwnerAPIHandler<T, C, L, K>
|
||||
where
|
||||
T: WalletBackend<C, K> + Send + Sync + 'static,
|
||||
C: WalletClient + 'static,
|
||||
T: WalletBackend<C, L, K> + Send + Sync + 'static,
|
||||
C: WalletToNodeClient + 'static,
|
||||
L: WalletToWalletClient + 'static,
|
||||
K: Keychain + 'static,
|
||||
{
|
||||
fn get(&self, req: Request<Body>) -> ResponseFuture {
|
||||
|
@ -466,37 +476,41 @@ where
|
|||
|
||||
/// API Handler/Wrapper for foreign functions
|
||||
|
||||
pub struct ForeignAPIHandler<T: ?Sized, C, K>
|
||||
pub struct ForeignAPIHandler<T: ?Sized, C, L, K>
|
||||
where
|
||||
T: WalletBackend<C, K> + Send + Sync + 'static,
|
||||
C: WalletClient + 'static,
|
||||
T: WalletBackend<C, L, K> + Send + Sync + 'static,
|
||||
C: WalletToNodeClient + 'static,
|
||||
L: WalletToWalletClient + 'static,
|
||||
K: Keychain + 'static,
|
||||
{
|
||||
/// Wallet instance
|
||||
pub wallet: Arc<Mutex<T>>,
|
||||
phantom: PhantomData<K>,
|
||||
phantom_c: PhantomData<C>,
|
||||
phantom_l: PhantomData<L>,
|
||||
}
|
||||
|
||||
impl<T: ?Sized, C, K> ForeignAPIHandler<T, C, K>
|
||||
impl<T: ?Sized, C, L, K> ForeignAPIHandler<T, C, L, K>
|
||||
where
|
||||
T: WalletBackend<C, K> + Send + Sync + 'static,
|
||||
C: WalletClient + 'static,
|
||||
T: WalletBackend<C, L, K> + Send + Sync + 'static,
|
||||
C: WalletToNodeClient + 'static,
|
||||
L: WalletToWalletClient + 'static,
|
||||
K: Keychain + 'static,
|
||||
{
|
||||
/// create a new api handler
|
||||
pub fn new(wallet: Arc<Mutex<T>>) -> ForeignAPIHandler<T, C, K> {
|
||||
pub fn new(wallet: Arc<Mutex<T>>) -> ForeignAPIHandler<T, C, L, K> {
|
||||
ForeignAPIHandler {
|
||||
wallet,
|
||||
phantom: PhantomData,
|
||||
phantom_c: PhantomData,
|
||||
phantom_l: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
fn build_coinbase(
|
||||
&self,
|
||||
req: Request<Body>,
|
||||
mut api: APIForeign<T, C, K>,
|
||||
mut api: APIForeign<T, C, L, K>,
|
||||
) -> Box<Future<Item = CbData, Error = Error> + Send> {
|
||||
Box::new(parse_body(req).and_then(move |block_fees| api.build_coinbase(&block_fees)))
|
||||
}
|
||||
|
@ -504,7 +518,7 @@ where
|
|||
fn receive_tx(
|
||||
&self,
|
||||
req: Request<Body>,
|
||||
mut api: APIForeign<T, C, K>,
|
||||
mut api: APIForeign<T, C, L, K>,
|
||||
) -> Box<Future<Item = Slate, Error = Error> + Send> {
|
||||
Box::new(
|
||||
parse_body(req).and_then(move |mut slate| match api.receive_tx(&mut slate) {
|
||||
|
@ -539,10 +553,11 @@ where
|
|||
}
|
||||
}
|
||||
}
|
||||
impl<T: ?Sized, C, K> Handler for ForeignAPIHandler<T, C, K>
|
||||
impl<T: ?Sized, C, L, K> Handler for ForeignAPIHandler<T, C, L, K>
|
||||
where
|
||||
T: WalletBackend<C, K> + Send + Sync + 'static,
|
||||
C: WalletClient + Send + Sync + 'static,
|
||||
T: WalletBackend<C, L, K> + Send + Sync + 'static,
|
||||
C: WalletToNodeClient + Send + Sync + 'static,
|
||||
L: WalletToWalletClient + Send + Sync + 'static,
|
||||
K: Keychain + 'static,
|
||||
{
|
||||
fn post(&self, req: Request<Body>) -> ResponseFuture {
|
||||
|
|
|
@ -15,13 +15,14 @@
|
|||
//! Wallet key management functions
|
||||
use keychain::{ChildNumber, ExtKeychain, Identifier, Keychain};
|
||||
use libwallet::error::{Error, ErrorKind};
|
||||
use libwallet::types::{AcctPathMapping, WalletBackend, WalletClient};
|
||||
use libwallet::types::{AcctPathMapping, WalletBackend, WalletToNodeClient, WalletToWalletClient};
|
||||
|
||||
/// Get next available key in the wallet for a given parent
|
||||
pub fn next_available_key<T: ?Sized, C, K>(wallet: &mut T) -> Result<Identifier, Error>
|
||||
pub fn next_available_key<T: ?Sized, C, L, K>(wallet: &mut T) -> Result<Identifier, Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
let child = wallet.next_child()?;
|
||||
|
@ -29,13 +30,14 @@ where
|
|||
}
|
||||
|
||||
/// Retrieve an existing key from a wallet
|
||||
pub fn retrieve_existing_key<T: ?Sized, C, K>(
|
||||
pub fn retrieve_existing_key<T: ?Sized, C, L, K>(
|
||||
wallet: &T,
|
||||
key_id: Identifier,
|
||||
) -> Result<(Identifier, u32), Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
let existing = wallet.get(&key_id)?;
|
||||
|
@ -45,20 +47,22 @@ where
|
|||
}
|
||||
|
||||
/// Returns a list of account to BIP32 path mappings
|
||||
pub fn accounts<T: ?Sized, C, K>(wallet: &mut T) -> Result<Vec<AcctPathMapping>, Error>
|
||||
pub fn accounts<T: ?Sized, C, L, K>(wallet: &mut T) -> Result<Vec<AcctPathMapping>, Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
Ok(wallet.acct_path_iter().collect())
|
||||
}
|
||||
|
||||
/// Adds an new parent account path with a given label
|
||||
pub fn new_acct_path<T: ?Sized, C, K>(wallet: &mut T, label: &str) -> Result<Identifier, Error>
|
||||
pub fn new_acct_path<T: ?Sized, C, L, K>(wallet: &mut T, label: &str) -> Result<Identifier, Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
let label = label.to_owned();
|
||||
|
@ -96,14 +100,15 @@ where
|
|||
}
|
||||
|
||||
/// Adds/sets a particular account path with a given label
|
||||
pub fn set_acct_path<T: ?Sized, C, K>(
|
||||
pub fn set_acct_path<T: ?Sized, C, L, K>(
|
||||
wallet: &mut T,
|
||||
label: &str,
|
||||
path: &Identifier,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
let label = label.to_owned();
|
||||
|
|
|
@ -42,13 +42,14 @@ struct OutputResult {
|
|||
pub blinding: SecretKey,
|
||||
}
|
||||
|
||||
fn identify_utxo_outputs<T, C, K>(
|
||||
fn identify_utxo_outputs<T, C, L, K>(
|
||||
wallet: &mut T,
|
||||
outputs: Vec<(pedersen::Commitment, pedersen::RangeProof, bool, u64)>,
|
||||
) -> Result<Vec<OutputResult>, Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
let mut wallet_outputs: Vec<OutputResult> = Vec::new();
|
||||
|
@ -98,10 +99,11 @@ where
|
|||
}
|
||||
|
||||
/// Restore a wallet
|
||||
pub fn restore<T, C, K>(wallet: &mut T) -> Result<(), Error>
|
||||
pub fn restore<T, C, L, K>(wallet: &mut T) -> Result<(), Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
// Don't proceed if wallet_data has anything in it
|
||||
|
@ -118,7 +120,7 @@ where
|
|||
let mut result_vec: Vec<OutputResult> = vec![];
|
||||
loop {
|
||||
let (highest_index, last_retrieved_index, outputs) = wallet
|
||||
.client()
|
||||
.w2n_client()
|
||||
.get_outputs_by_pmmr_index(start_index, batch_size)?;
|
||||
info!(
|
||||
"Retrieved {} outputs, up to index {}. (Highest index: {})",
|
||||
|
|
|
@ -25,7 +25,7 @@ use libwallet::types::*;
|
|||
/// and saves the private wallet identifiers of our selected outputs
|
||||
/// into our transaction context
|
||||
|
||||
pub fn build_send_tx_slate<T: ?Sized, C, K>(
|
||||
pub fn build_send_tx_slate<T: ?Sized, C, L, K>(
|
||||
wallet: &mut T,
|
||||
num_participants: usize,
|
||||
amount: u64,
|
||||
|
@ -46,8 +46,9 @@ pub fn build_send_tx_slate<T: ?Sized, C, K>(
|
|||
Error,
|
||||
>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
let (elems, inputs, change_amounts_derivations, amount, fee) = select_send_tx(
|
||||
|
@ -144,7 +145,7 @@ where
|
|||
/// returning the key of the fresh output and a closure
|
||||
/// that actually performs the addition of the output to the
|
||||
/// wallet
|
||||
pub fn build_recipient_output_with_slate<T: ?Sized, C, K>(
|
||||
pub fn build_recipient_output_with_slate<T: ?Sized, C, L, K>(
|
||||
wallet: &mut T,
|
||||
slate: &mut Slate,
|
||||
parent_key_id: Identifier,
|
||||
|
@ -158,8 +159,9 @@ pub fn build_recipient_output_with_slate<T: ?Sized, C, K>(
|
|||
Error,
|
||||
>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
// Create a potential output for this transaction
|
||||
|
@ -217,7 +219,7 @@ where
|
|||
/// Builds a transaction to send to someone from the HD seed associated with the
|
||||
/// wallet and the amount to send. Handles reading through the wallet data file,
|
||||
/// selecting outputs to spend and building the change.
|
||||
pub fn select_send_tx<T: ?Sized, C, K>(
|
||||
pub fn select_send_tx<T: ?Sized, C, L, K>(
|
||||
wallet: &mut T,
|
||||
amount: u64,
|
||||
current_height: u64,
|
||||
|
@ -238,8 +240,9 @@ pub fn select_send_tx<T: ?Sized, C, K>(
|
|||
Error,
|
||||
>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
// select some spendable coins from the wallet
|
||||
|
@ -326,7 +329,7 @@ where
|
|||
}
|
||||
|
||||
/// Selects inputs and change for a transaction
|
||||
pub fn inputs_and_change<T: ?Sized, C, K>(
|
||||
pub fn inputs_and_change<T: ?Sized, C, L, K>(
|
||||
coins: &Vec<OutputData>,
|
||||
wallet: &mut T,
|
||||
amount: u64,
|
||||
|
@ -334,8 +337,9 @@ pub fn inputs_and_change<T: ?Sized, C, K>(
|
|||
num_change_outputs: usize,
|
||||
) -> Result<(Vec<Box<build::Append<K>>>, Vec<(u64, Identifier)>), Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
let mut parts = vec![];
|
||||
|
@ -397,7 +401,7 @@ where
|
|||
/// we should pass something other than a bool in.
|
||||
/// TODO: Possibly move this into another trait to be owned by a wallet?
|
||||
|
||||
pub fn select_coins<T: ?Sized, C, K>(
|
||||
pub fn select_coins<T: ?Sized, C, L, K>(
|
||||
wallet: &mut T,
|
||||
amount: u64,
|
||||
current_height: u64,
|
||||
|
@ -408,8 +412,9 @@ pub fn select_coins<T: ?Sized, C, K>(
|
|||
) -> (usize, Vec<OutputData>)
|
||||
// max_outputs_available, Outputs
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
// first find all eligible outputs based on number of confirmations
|
||||
|
|
|
@ -23,20 +23,23 @@ use keychain::{Identifier, Keychain};
|
|||
use libtx::slate::Slate;
|
||||
use libtx::{build, tx_fee};
|
||||
use libwallet::internal::{selection, updater};
|
||||
use libwallet::types::{Context, TxLogEntryType, WalletBackend, WalletClient};
|
||||
use libwallet::types::{
|
||||
Context, TxLogEntryType, WalletBackend, WalletToNodeClient, WalletToWalletClient,
|
||||
};
|
||||
use libwallet::{Error, ErrorKind};
|
||||
|
||||
/// Receive a transaction, modifying the slate accordingly (which can then be
|
||||
/// sent back to sender for posting)
|
||||
pub fn receive_tx<T: ?Sized, C, K>(
|
||||
pub fn receive_tx<T: ?Sized, C, L, K>(
|
||||
wallet: &mut T,
|
||||
slate: &mut Slate,
|
||||
parent_key_id: &Identifier,
|
||||
is_self: bool,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
// create an output using the amount in the slate
|
||||
|
@ -66,7 +69,7 @@ where
|
|||
|
||||
/// Issue a new transaction to the provided sender by spending some of our
|
||||
/// wallet
|
||||
pub fn create_send_tx<T: ?Sized, C, K>(
|
||||
pub fn create_send_tx<T: ?Sized, C, L, K>(
|
||||
wallet: &mut T,
|
||||
amount: u64,
|
||||
minimum_confirmations: u64,
|
||||
|
@ -84,12 +87,13 @@ pub fn create_send_tx<T: ?Sized, C, K>(
|
|||
Error,
|
||||
>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
// Get lock height
|
||||
let current_height = wallet.client().get_chain_height()?;
|
||||
let current_height = wallet.w2n_client().get_chain_height()?;
|
||||
// ensure outputs we're selecting are up to date
|
||||
updater::refresh_outputs(wallet, parent_key_id)?;
|
||||
|
||||
|
@ -130,14 +134,15 @@ where
|
|||
}
|
||||
|
||||
/// Complete a transaction as the sender
|
||||
pub fn complete_tx<T: ?Sized, C, K>(
|
||||
pub fn complete_tx<T: ?Sized, C, L, K>(
|
||||
wallet: &mut T,
|
||||
slate: &mut Slate,
|
||||
context: &Context,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
let _ = slate.fill_round_2(wallet.keychain(), &context.sec_key, &context.sec_nonce, 0)?;
|
||||
|
@ -150,14 +155,15 @@ where
|
|||
}
|
||||
|
||||
/// Rollback outputs associated with a transaction in the wallet
|
||||
pub fn cancel_tx<T: ?Sized, C, K>(
|
||||
pub fn cancel_tx<T: ?Sized, C, L, K>(
|
||||
wallet: &mut T,
|
||||
parent_key_id: &Identifier,
|
||||
tx_id: u32,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
let tx_vec = updater::retrieve_txs(wallet, Some(tx_id), &parent_key_id)?;
|
||||
|
@ -180,14 +186,15 @@ where
|
|||
|
||||
/// Retrieve the associated stored finalised hex Transaction for a given transaction Id
|
||||
/// as well as whether it's been confirmed
|
||||
pub fn retrieve_tx_hex<T: ?Sized, C, K>(
|
||||
pub fn retrieve_tx_hex<T: ?Sized, C, L, K>(
|
||||
wallet: &mut T,
|
||||
parent_key_id: &Identifier,
|
||||
tx_id: u32,
|
||||
) -> Result<(bool, Option<String>), Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
let tx_vec = updater::retrieve_txs(wallet, Some(tx_id), parent_key_id)?;
|
||||
|
@ -199,7 +206,7 @@ where
|
|||
}
|
||||
|
||||
/// Issue a burn tx
|
||||
pub fn issue_burn_tx<T: ?Sized, C, K>(
|
||||
pub fn issue_burn_tx<T: ?Sized, C, L, K>(
|
||||
wallet: &mut T,
|
||||
amount: u64,
|
||||
minimum_confirmations: u64,
|
||||
|
@ -207,8 +214,9 @@ pub fn issue_burn_tx<T: ?Sized, C, K>(
|
|||
parent_key_id: &Identifier,
|
||||
) -> Result<Transaction, Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
// TODO
|
||||
|
@ -216,7 +224,7 @@ where
|
|||
// &Identifier::zero());
|
||||
let keychain = wallet.keychain().clone();
|
||||
|
||||
let current_height = wallet.client().get_chain_height()?;
|
||||
let current_height = wallet.w2n_client().get_chain_height()?;
|
||||
|
||||
let _ = updater::refresh_outputs(wallet, parent_key_id);
|
||||
|
||||
|
|
|
@ -28,21 +28,22 @@ use libwallet::error::{Error, ErrorKind};
|
|||
use libwallet::internal::keys;
|
||||
use libwallet::types::{
|
||||
BlockFees, CbData, OutputData, OutputStatus, TxLogEntry, TxLogEntryType, WalletBackend,
|
||||
WalletClient, WalletInfo,
|
||||
WalletInfo, WalletToNodeClient, WalletToWalletClient,
|
||||
};
|
||||
use util;
|
||||
use util::secp::pedersen;
|
||||
|
||||
/// Retrieve all of the outputs (doesn't attempt to update from node)
|
||||
pub fn retrieve_outputs<T: ?Sized, C, K>(
|
||||
pub fn retrieve_outputs<T: ?Sized, C, L, K>(
|
||||
wallet: &mut T,
|
||||
show_spent: bool,
|
||||
tx_id: Option<u32>,
|
||||
parent_key_id: &Identifier,
|
||||
) -> Result<Vec<(OutputData, pedersen::Commitment)>, Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
// just read the wallet here, no need for a write lock
|
||||
|
@ -77,14 +78,15 @@ where
|
|||
}
|
||||
|
||||
/// Retrieve all of the transaction entries, or a particular entry
|
||||
pub fn retrieve_txs<T: ?Sized, C, K>(
|
||||
pub fn retrieve_txs<T: ?Sized, C, L, K>(
|
||||
wallet: &mut T,
|
||||
tx_id: Option<u32>,
|
||||
parent_key_id: &Identifier,
|
||||
) -> Result<Vec<TxLogEntry>, Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
// just read the wallet here, no need for a write lock
|
||||
|
@ -106,29 +108,31 @@ where
|
|||
}
|
||||
/// Refreshes the outputs in a wallet with the latest information
|
||||
/// from a node
|
||||
pub fn refresh_outputs<T: ?Sized, C, K>(
|
||||
pub fn refresh_outputs<T: ?Sized, C, L, K>(
|
||||
wallet: &mut T,
|
||||
parent_key_id: &Identifier,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
let height = wallet.client().get_chain_height()?;
|
||||
let height = wallet.w2n_client().get_chain_height()?;
|
||||
refresh_output_state(wallet, height, parent_key_id)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// build a local map of wallet outputs keyed by commit
|
||||
/// and a list of outputs we want to query the node for
|
||||
pub fn map_wallet_outputs<T: ?Sized, C, K>(
|
||||
pub fn map_wallet_outputs<T: ?Sized, C, L, K>(
|
||||
wallet: &mut T,
|
||||
parent_key_id: &Identifier,
|
||||
) -> Result<HashMap<pedersen::Commitment, Identifier>, Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
let mut wallet_outputs: HashMap<pedersen::Commitment, Identifier> = HashMap::new();
|
||||
|
@ -144,15 +148,16 @@ where
|
|||
}
|
||||
|
||||
/// Cancel transaction and associated outputs
|
||||
pub fn cancel_tx_and_outputs<T: ?Sized, C, K>(
|
||||
pub fn cancel_tx_and_outputs<T: ?Sized, C, L, K>(
|
||||
wallet: &mut T,
|
||||
tx: TxLogEntry,
|
||||
outputs: Vec<OutputData>,
|
||||
parent_key_id: &Identifier,
|
||||
) -> Result<(), libwallet::Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
let mut batch = wallet.batch()?;
|
||||
|
@ -180,7 +185,7 @@ where
|
|||
}
|
||||
|
||||
/// Apply refreshed API output data to the wallet
|
||||
pub fn apply_api_outputs<T: ?Sized, C, K>(
|
||||
pub fn apply_api_outputs<T: ?Sized, C, L, K>(
|
||||
wallet: &mut T,
|
||||
wallet_outputs: &HashMap<pedersen::Commitment, Identifier>,
|
||||
api_outputs: &HashMap<pedersen::Commitment, (String, u64)>,
|
||||
|
@ -188,8 +193,9 @@ pub fn apply_api_outputs<T: ?Sized, C, K>(
|
|||
parent_key_id: &Identifier,
|
||||
) -> Result<(), libwallet::Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
// now for each commit, find the output in the wallet and the corresponding
|
||||
|
@ -260,14 +266,15 @@ where
|
|||
|
||||
/// Builds a single api query to retrieve the latest output data from the node.
|
||||
/// So we can refresh the local wallet outputs.
|
||||
fn refresh_output_state<T: ?Sized, C, K>(
|
||||
fn refresh_output_state<T: ?Sized, C, L, K>(
|
||||
wallet: &mut T,
|
||||
height: u64,
|
||||
parent_key_id: &Identifier,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
debug!("Refreshing wallet outputs");
|
||||
|
@ -278,16 +285,19 @@ where
|
|||
|
||||
let wallet_output_keys = wallet_outputs.keys().map(|commit| commit.clone()).collect();
|
||||
|
||||
let api_outputs = wallet.client().get_outputs_from_node(wallet_output_keys)?;
|
||||
let api_outputs = wallet
|
||||
.w2n_client()
|
||||
.get_outputs_from_node(wallet_output_keys)?;
|
||||
apply_api_outputs(wallet, &wallet_outputs, &api_outputs, height, parent_key_id)?;
|
||||
clean_old_unconfirmed(wallet, height)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn clean_old_unconfirmed<T: ?Sized, C, K>(wallet: &mut T, height: u64) -> Result<(), Error>
|
||||
fn clean_old_unconfirmed<T: ?Sized, C, L, K>(wallet: &mut T, height: u64) -> Result<(), Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
if height < 500 {
|
||||
|
@ -309,13 +319,14 @@ where
|
|||
|
||||
/// Retrieve summary info about the wallet
|
||||
/// caller should refresh first if desired
|
||||
pub fn retrieve_info<T: ?Sized, C, K>(
|
||||
pub fn retrieve_info<T: ?Sized, C, L, K>(
|
||||
wallet: &mut T,
|
||||
parent_key_id: &Identifier,
|
||||
) -> Result<WalletInfo, Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
let current_height = wallet.last_confirmed_height()?;
|
||||
|
@ -353,13 +364,14 @@ where
|
|||
}
|
||||
|
||||
/// Build a coinbase output and insert into wallet
|
||||
pub fn build_coinbase<T: ?Sized, C, K>(
|
||||
pub fn build_coinbase<T: ?Sized, C, L, K>(
|
||||
wallet: &mut T,
|
||||
block_fees: &BlockFees,
|
||||
) -> Result<CbData, Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
let (out, kern, block_fees) = receive_coinbase(wallet, block_fees).context(ErrorKind::Node)?;
|
||||
|
@ -382,13 +394,14 @@ where
|
|||
|
||||
//TODO: Split up the output creation and the wallet insertion
|
||||
/// Build a coinbase output and the corresponding kernel
|
||||
pub fn receive_coinbase<T: ?Sized, C, K>(
|
||||
pub fn receive_coinbase<T: ?Sized, C, L, K>(
|
||||
wallet: &mut T,
|
||||
block_fees: &BlockFees,
|
||||
) -> Result<(Output, TxKernel, BlockFees), Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K>,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
let height = block_fees.height;
|
||||
|
|
|
@ -38,16 +38,18 @@ use util::secp::key::{PublicKey, SecretKey};
|
|||
use util::secp::{self, pedersen, Secp256k1};
|
||||
|
||||
/// Combined trait to allow dynamic wallet dispatch
|
||||
pub trait WalletInst<C, K>: WalletBackend<C, K> + Send + Sync + 'static
|
||||
pub trait WalletInst<C, L, K>: WalletBackend<C, L, K> + Send + Sync + 'static
|
||||
where
|
||||
C: WalletClient,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
}
|
||||
impl<T, C, K> WalletInst<C, K> for T
|
||||
impl<T, C, L, K> WalletInst<C, L, K> for T
|
||||
where
|
||||
T: WalletBackend<C, K> + Send + Sync + 'static,
|
||||
C: WalletClient,
|
||||
T: WalletBackend<C, L, K> + Send + Sync + 'static,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{}
|
||||
|
||||
|
@ -55,9 +57,10 @@ where
|
|||
/// Wallets should implement this backend for their storage. All functions
|
||||
/// here expect that the wallet instance has instantiated itself or stored
|
||||
/// whatever credentials it needs
|
||||
pub trait WalletBackend<C, K>
|
||||
pub trait WalletBackend<C, L, K>
|
||||
where
|
||||
C: WalletClient,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
/// Initialize with whatever stored credentials we have
|
||||
|
@ -69,8 +72,11 @@ where
|
|||
/// Return the keychain being used
|
||||
fn keychain(&mut self) -> &mut K;
|
||||
|
||||
/// Return the client being used
|
||||
fn client(&mut self) -> &mut C;
|
||||
/// Return the client being used to communicate with the node
|
||||
fn w2n_client(&mut self) -> &mut C;
|
||||
|
||||
/// Return the client being used to communicate with other wallets
|
||||
fn w2w_client(&mut self) -> &mut L;
|
||||
|
||||
/// Set parent key id by stored account name
|
||||
fn set_parent_key_id_by_name(&mut self, label: &str) -> Result<(), Error>;
|
||||
|
@ -181,21 +187,15 @@ where
|
|||
fn commit(&self) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
/// Encapsulate all communication functions. No functions within libwallet
|
||||
/// Encapsulate all wallet-node communication functions. No functions within libwallet
|
||||
/// should care about communication details
|
||||
pub trait WalletClient: Sync + Send + Clone {
|
||||
pub trait WalletToNodeClient: Sync + Send + Clone {
|
||||
/// Return the URL of the check node
|
||||
fn node_url(&self) -> &str;
|
||||
|
||||
/// Return the node api secret
|
||||
fn node_api_secret(&self) -> Option<String>;
|
||||
|
||||
/// Call the wallet API to create a coinbase transaction
|
||||
fn create_coinbase(&self, dest: &str, block_fees: &BlockFees) -> Result<CbData, Error>;
|
||||
|
||||
/// Send a transaction slate to another listening wallet and return result
|
||||
/// TODO: Probably need a slate wrapper type
|
||||
fn send_tx_slate(&self, addr: &str, slate: &Slate) -> Result<Slate, Error>;
|
||||
|
||||
/// Posts a transaction to a grin node
|
||||
fn post_tx(&self, tx: &TxWrapper, fluff: bool) -> Result<(), Error>;
|
||||
|
||||
|
@ -228,6 +228,16 @@ pub trait WalletClient: Sync + Send + Clone {
|
|||
>;
|
||||
}
|
||||
|
||||
/// Encapsulate wallet to wallet communication functions
|
||||
pub trait WalletToWalletClient: Sync + Send + Clone {
|
||||
/// Call the wallet API to create a coinbase transaction
|
||||
fn create_coinbase(&self, dest: &str, block_fees: &BlockFees) -> Result<CbData, Error>;
|
||||
|
||||
/// Send a transaction slate to another listening wallet and return result
|
||||
/// TODO: Probably need a slate wrapper type
|
||||
fn send_tx_slate(&self, addr: &str, slate: &Slate) -> Result<Slate, Error>;
|
||||
}
|
||||
|
||||
/// Information about an output that's being tracked by the wallet. Must be
|
||||
/// enough to reconstruct the commitment associated with the ouput when the
|
||||
/// root private key is known.
|
||||
|
|
|
@ -51,7 +51,7 @@ pub fn wallet_db_exists(config: WalletConfig) -> bool {
|
|||
db_path.exists()
|
||||
}
|
||||
|
||||
pub struct LMDBBackend<C, K> {
|
||||
pub struct LMDBBackend<C, L, K> {
|
||||
db: store::Store,
|
||||
config: WalletConfig,
|
||||
/// passphrase: TODO better ways of dealing with this other than storing
|
||||
|
@ -60,12 +60,19 @@ pub struct LMDBBackend<C, K> {
|
|||
pub keychain: Option<K>,
|
||||
/// Parent path to use by default for output operations
|
||||
parent_key_id: Identifier,
|
||||
/// client
|
||||
client: C,
|
||||
/// wallet to node client
|
||||
w2n_client: C,
|
||||
/// w2w client
|
||||
w2w_client: L,
|
||||
}
|
||||
|
||||
impl<C, K> LMDBBackend<C, K> {
|
||||
pub fn new(config: WalletConfig, passphrase: &str, client: C) -> Result<Self, Error> {
|
||||
impl<C, L, K> LMDBBackend<C, L, K> {
|
||||
pub fn new(
|
||||
config: WalletConfig,
|
||||
passphrase: &str,
|
||||
n_client: C,
|
||||
w_client: L,
|
||||
) -> Result<Self, Error> {
|
||||
let db_path = path::Path::new(&config.data_file_dir).join(DB_DIR);
|
||||
fs::create_dir_all(&db_path).expect("Couldn't create wallet backend directory!");
|
||||
|
||||
|
@ -75,7 +82,7 @@ impl<C, K> LMDBBackend<C, K> {
|
|||
// Make sure default wallet derivation path always exists
|
||||
let default_account = AcctPathMapping {
|
||||
label: "default".to_owned(),
|
||||
path: LMDBBackend::<C, K>::default_path(),
|
||||
path: LMDBBackend::<C, L, K>::default_path(),
|
||||
};
|
||||
let acct_key = to_key(
|
||||
ACCOUNT_PATH_MAPPING_PREFIX,
|
||||
|
@ -93,8 +100,9 @@ impl<C, K> LMDBBackend<C, K> {
|
|||
config: config.clone(),
|
||||
passphrase: String::from(passphrase),
|
||||
keychain: None,
|
||||
parent_key_id: LMDBBackend::<C, K>::default_path(),
|
||||
client: client,
|
||||
parent_key_id: LMDBBackend::<C, L, K>::default_path(),
|
||||
w2n_client: n_client,
|
||||
w2w_client: w_client,
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
|
@ -114,9 +122,10 @@ impl<C, K> LMDBBackend<C, K> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<C, K> WalletBackend<C, K> for LMDBBackend<C, K>
|
||||
impl<C, L, K> WalletBackend<C, L, K> for LMDBBackend<C, L, K>
|
||||
where
|
||||
C: WalletClient,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
/// Initialise with whatever stored credentials we have
|
||||
|
@ -141,9 +150,14 @@ where
|
|||
self.keychain.as_mut().unwrap()
|
||||
}
|
||||
|
||||
/// Return the client being used
|
||||
fn client(&mut self) -> &mut C {
|
||||
&mut self.client
|
||||
/// Return the node client being used
|
||||
fn w2n_client(&mut self) -> &mut C {
|
||||
&mut self.w2n_client
|
||||
}
|
||||
|
||||
/// Return the wallet to wallet client being used
|
||||
fn w2w_client(&mut self) -> &mut L {
|
||||
&mut self.w2w_client
|
||||
}
|
||||
|
||||
/// Set parent path by account name
|
||||
|
@ -278,21 +292,21 @@ where
|
|||
|
||||
/// An atomic batch in which all changes can be committed all at once or
|
||||
/// discarded on error.
|
||||
pub struct Batch<'a, C: 'a, K: 'a>
|
||||
pub struct Batch<'a, C: 'a, L: 'a, K: 'a>
|
||||
where
|
||||
C: WalletClient,
|
||||
C: WalletToNodeClient,
|
||||
K: Keychain,
|
||||
{
|
||||
_store: &'a LMDBBackend<C, K>,
|
||||
_store: &'a LMDBBackend<C, L, K>,
|
||||
db: RefCell<Option<store::Batch<'a>>>,
|
||||
/// Keychain
|
||||
keychain: Option<K>,
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
impl<'a, C, K> WalletOutputBatch<K> for Batch<'a, C, K>
|
||||
impl<'a, C, L, K> WalletOutputBatch<K> for Batch<'a, C, L, K>
|
||||
where
|
||||
C: WalletClient,
|
||||
C: WalletToNodeClient,
|
||||
K: Keychain,
|
||||
{
|
||||
fn keychain(&mut self) -> &mut K {
|
||||
|
|
|
@ -51,17 +51,26 @@ fn setup(test_dir: &str) {
|
|||
fn accounts_test_impl(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||
setup(test_dir);
|
||||
// Create a new proxy to simulate server and wallet responses
|
||||
let mut wallet_proxy: WalletProxy<LocalWalletClient, ExtKeychain> = WalletProxy::new(test_dir);
|
||||
let mut wallet_proxy: WalletProxy<LocalWalletClient, LocalWalletClient, ExtKeychain> =
|
||||
WalletProxy::new(test_dir);
|
||||
let chain = wallet_proxy.chain.clone();
|
||||
|
||||
// Create a new wallet test client, and set its queues to communicate with the
|
||||
// proxy
|
||||
let client = LocalWalletClient::new("wallet1", wallet_proxy.tx.clone());
|
||||
let wallet1 = common::create_wallet(&format!("{}/wallet1", test_dir), client.clone());
|
||||
let wallet1 = common::create_wallet(
|
||||
&format!("{}/wallet1", test_dir),
|
||||
client.clone(),
|
||||
client.clone(),
|
||||
);
|
||||
wallet_proxy.add_wallet("wallet1", client.get_send_instance(), wallet1.clone());
|
||||
|
||||
// define recipient wallet, add to proxy
|
||||
let wallet2 = common::create_wallet(&format!("{}/wallet2", test_dir), client.clone());
|
||||
let wallet2 = common::create_wallet(
|
||||
&format!("{}/wallet2", test_dir),
|
||||
client.clone(),
|
||||
client.clone(),
|
||||
);
|
||||
let client = LocalWalletClient::new("wallet2", wallet_proxy.tx.clone());
|
||||
wallet_proxy.add_wallet("wallet2", client.get_send_instance(), wallet2.clone());
|
||||
|
||||
|
|
|
@ -29,7 +29,9 @@ use chain::Chain;
|
|||
use core::core::{OutputFeatures, OutputIdentifier, Transaction};
|
||||
use core::{consensus, global, pow, ser};
|
||||
use wallet::libwallet;
|
||||
use wallet::libwallet::types::{BlockFees, CbData, WalletClient, WalletInst};
|
||||
use wallet::libwallet::types::{
|
||||
BlockFees, CbData, WalletInst, WalletToNodeClient, WalletToWalletClient,
|
||||
};
|
||||
use wallet::lmdb_wallet::LMDBBackend;
|
||||
use wallet::{WalletBackend, WalletConfig};
|
||||
|
||||
|
@ -113,13 +115,14 @@ pub fn add_block_with_reward(chain: &Chain, txs: Vec<&Transaction>, reward: CbDa
|
|||
/// adds a reward output to a wallet, includes that reward in a block, mines
|
||||
/// the block and adds it to the chain, with option transactions included.
|
||||
/// Helpful for building up precise wallet balances for testing.
|
||||
pub fn award_block_to_wallet<C, K>(
|
||||
pub fn award_block_to_wallet<C, L, K>(
|
||||
chain: &Chain,
|
||||
txs: Vec<&Transaction>,
|
||||
wallet: Arc<Mutex<WalletInst<C, K>>>,
|
||||
wallet: Arc<Mutex<WalletInst<C, L, K>>>,
|
||||
) -> Result<(), libwallet::Error>
|
||||
where
|
||||
C: WalletClient,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: keychain::Keychain,
|
||||
{
|
||||
// build block fees
|
||||
|
@ -140,13 +143,14 @@ where
|
|||
}
|
||||
|
||||
/// Award a blocks to a wallet directly
|
||||
pub fn award_blocks_to_wallet<C, K>(
|
||||
pub fn award_blocks_to_wallet<C, L, K>(
|
||||
chain: &Chain,
|
||||
wallet: Arc<Mutex<WalletInst<C, K>>>,
|
||||
wallet: Arc<Mutex<WalletInst<C, L, K>>>,
|
||||
number: usize,
|
||||
) -> Result<(), libwallet::Error>
|
||||
where
|
||||
C: WalletClient,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: keychain::Keychain,
|
||||
{
|
||||
for _ in 0..number {
|
||||
|
@ -156,15 +160,20 @@ where
|
|||
}
|
||||
|
||||
/// dispatch a db wallet
|
||||
pub fn create_wallet<C, K>(dir: &str, client: C) -> Arc<Mutex<WalletInst<C, K>>>
|
||||
pub fn create_wallet<C, L, K>(
|
||||
dir: &str,
|
||||
n_client: C,
|
||||
w_client: L,
|
||||
) -> Arc<Mutex<WalletInst<C, L, K>>>
|
||||
where
|
||||
C: WalletClient + 'static,
|
||||
C: WalletToNodeClient + 'static,
|
||||
L: WalletToWalletClient + 'static,
|
||||
K: keychain::Keychain + 'static,
|
||||
{
|
||||
let mut wallet_config = WalletConfig::default();
|
||||
wallet_config.data_file_dir = String::from(dir);
|
||||
let _ = wallet::WalletSeed::init_file(&wallet_config);
|
||||
let mut wallet = LMDBBackend::new(wallet_config.clone(), "", client)
|
||||
let mut wallet = LMDBBackend::new(wallet_config.clone(), "", n_client, w_client)
|
||||
.unwrap_or_else(|e| panic!("Error creating wallet: {:?} Config: {:?}", e, wallet_config));
|
||||
wallet.open_with_credentials().unwrap_or_else(|e| {
|
||||
panic!(
|
||||
|
|
|
@ -63,9 +63,10 @@ pub struct WalletProxyMessage {
|
|||
|
||||
/// communicates with a chain instance or other wallet
|
||||
/// listener APIs via message queues
|
||||
pub struct WalletProxy<C, K>
|
||||
pub struct WalletProxy<C, L, K>
|
||||
where
|
||||
C: WalletClient,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
/// directory to create the chain in
|
||||
|
@ -77,7 +78,7 @@ where
|
|||
String,
|
||||
(
|
||||
Sender<WalletProxyMessage>,
|
||||
Arc<Mutex<WalletInst<LocalWalletClient, K>>>,
|
||||
Arc<Mutex<WalletInst<LocalWalletClient, LocalWalletClient, K>>>,
|
||||
),
|
||||
>,
|
||||
/// simulate json send to another client
|
||||
|
@ -91,11 +92,14 @@ where
|
|||
phantom_c: PhantomData<C>,
|
||||
/// Phantom
|
||||
phantom_k: PhantomData<K>,
|
||||
/// Phantom
|
||||
phantom_l: PhantomData<L>,
|
||||
}
|
||||
|
||||
impl<C, K> WalletProxy<C, K>
|
||||
impl<C, L, K> WalletProxy<C, L, K>
|
||||
where
|
||||
C: WalletClient,
|
||||
C: WalletToNodeClient,
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
/// Create a new client that will communicate with the given grin node
|
||||
|
@ -124,6 +128,7 @@ where
|
|||
running: Arc::new(AtomicBool::new(false)),
|
||||
phantom_c: PhantomData,
|
||||
phantom_k: PhantomData,
|
||||
phantom_l: PhantomData,
|
||||
};
|
||||
retval
|
||||
}
|
||||
|
@ -133,7 +138,7 @@ where
|
|||
&mut self,
|
||||
addr: &str,
|
||||
tx: Sender<WalletProxyMessage>,
|
||||
wallet: Arc<Mutex<WalletInst<LocalWalletClient, K>>>,
|
||||
wallet: Arc<Mutex<WalletInst<LocalWalletClient, LocalWalletClient, K>>>,
|
||||
) {
|
||||
self.wallets.insert(addr.to_owned(), (tx, wallet));
|
||||
}
|
||||
|
@ -311,14 +316,7 @@ impl LocalWalletClient {
|
|||
}
|
||||
}
|
||||
|
||||
impl WalletClient for LocalWalletClient {
|
||||
fn node_url(&self) -> &str {
|
||||
"node"
|
||||
}
|
||||
fn node_api_secret(&self) -> Option<String> {
|
||||
None
|
||||
}
|
||||
|
||||
impl WalletToWalletClient for LocalWalletClient {
|
||||
/// Call the wallet API to create a coinbase output for the given
|
||||
/// block_fees. Will retry based on default "retry forever with backoff"
|
||||
/// behavior.
|
||||
|
@ -352,6 +350,15 @@ impl WalletClient for LocalWalletClient {
|
|||
))?,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl WalletToNodeClient for LocalWalletClient {
|
||||
fn node_url(&self) -> &str {
|
||||
"node"
|
||||
}
|
||||
fn node_api_secret(&self) -> Option<String> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Posts a transaction to a grin node
|
||||
/// In this case it will create a new block with award rewarded to
|
||||
|
|
|
@ -56,10 +56,11 @@ fn restore_wallet(base_dir: &str, wallet_dir: &str) -> Result<(), libwallet::Err
|
|||
let dest_seed = format!("{}/wallet.seed", dest_dir);
|
||||
fs::copy(source_seed, dest_seed)?;
|
||||
|
||||
let mut wallet_proxy: WalletProxy<LocalWalletClient, ExtKeychain> = WalletProxy::new(base_dir);
|
||||
let mut wallet_proxy: WalletProxy<LocalWalletClient, LocalWalletClient, ExtKeychain> =
|
||||
WalletProxy::new(base_dir);
|
||||
let client = LocalWalletClient::new(wallet_dir, wallet_proxy.tx.clone());
|
||||
|
||||
let wallet = common::create_wallet(&dest_dir, client.clone());
|
||||
let wallet = common::create_wallet(&dest_dir, client.clone(), client.clone());
|
||||
|
||||
wallet_proxy.add_wallet(wallet_dir, client.get_send_instance(), wallet.clone());
|
||||
|
||||
|
@ -89,10 +90,11 @@ fn compare_wallet_restore(
|
|||
let source_dir = format!("{}/{}", base_dir, wallet_dir);
|
||||
let dest_dir = format!("{}/{}", base_dir, restore_name);
|
||||
|
||||
let mut wallet_proxy: WalletProxy<LocalWalletClient, ExtKeychain> = WalletProxy::new(base_dir);
|
||||
let mut wallet_proxy: WalletProxy<LocalWalletClient, LocalWalletClient, ExtKeychain> =
|
||||
WalletProxy::new(base_dir);
|
||||
|
||||
let client = LocalWalletClient::new(wallet_dir, wallet_proxy.tx.clone());
|
||||
let wallet_source = common::create_wallet(&source_dir, client.clone());
|
||||
let wallet_source = common::create_wallet(&source_dir, client.clone(), client.clone());
|
||||
wallet_proxy.add_wallet(
|
||||
&wallet_dir,
|
||||
client.get_send_instance(),
|
||||
|
@ -100,7 +102,7 @@ fn compare_wallet_restore(
|
|||
);
|
||||
|
||||
let client = LocalWalletClient::new(&restore_name, wallet_proxy.tx.clone());
|
||||
let wallet_dest = common::create_wallet(&dest_dir, client.clone());
|
||||
let wallet_dest = common::create_wallet(&dest_dir, client.clone(), client.clone());
|
||||
wallet_proxy.add_wallet(
|
||||
&restore_name,
|
||||
client.get_send_instance(),
|
||||
|
@ -182,18 +184,27 @@ fn compare_wallet_restore(
|
|||
fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||
setup(test_dir);
|
||||
// Create a new proxy to simulate server and wallet responses
|
||||
let mut wallet_proxy: WalletProxy<LocalWalletClient, ExtKeychain> = WalletProxy::new(test_dir);
|
||||
let mut wallet_proxy: WalletProxy<LocalWalletClient, LocalWalletClient, ExtKeychain> =
|
||||
WalletProxy::new(test_dir);
|
||||
let chain = wallet_proxy.chain.clone();
|
||||
|
||||
// Create a new wallet test client, and set its queues to communicate with the
|
||||
// proxy
|
||||
let client = LocalWalletClient::new("wallet1", wallet_proxy.tx.clone());
|
||||
let wallet1 = common::create_wallet(&format!("{}/wallet1", test_dir), client.clone());
|
||||
let wallet1 = common::create_wallet(
|
||||
&format!("{}/wallet1", test_dir),
|
||||
client.clone(),
|
||||
client.clone(),
|
||||
);
|
||||
wallet_proxy.add_wallet("wallet1", client.get_send_instance(), wallet1.clone());
|
||||
|
||||
// define recipient wallet, add to proxy
|
||||
let client = LocalWalletClient::new("wallet2", wallet_proxy.tx.clone());
|
||||
let wallet2 = common::create_wallet(&format!("{}/wallet2", test_dir), client.clone());
|
||||
let wallet2 = common::create_wallet(
|
||||
&format!("{}/wallet2", test_dir),
|
||||
client.clone(),
|
||||
client.clone(),
|
||||
);
|
||||
wallet_proxy.add_wallet("wallet2", client.get_send_instance(), wallet2.clone());
|
||||
|
||||
// wallet 2 will use another account
|
||||
|
@ -211,7 +222,11 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
|
||||
// Another wallet
|
||||
let client = LocalWalletClient::new("wallet3", wallet_proxy.tx.clone());
|
||||
let wallet3 = common::create_wallet(&format!("{}/wallet3", test_dir), client.clone());
|
||||
let wallet3 = common::create_wallet(
|
||||
&format!("{}/wallet3", test_dir),
|
||||
client.clone(),
|
||||
client.clone(),
|
||||
);
|
||||
wallet_proxy.add_wallet("wallet3", client.get_send_instance(), wallet3.clone());
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
|
|
|
@ -51,17 +51,26 @@ fn setup(test_dir: &str) {
|
|||
fn self_send_test_impl(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||
setup(test_dir);
|
||||
// Create a new proxy to simulate server and wallet responses
|
||||
let mut wallet_proxy: WalletProxy<LocalWalletClient, ExtKeychain> = WalletProxy::new(test_dir);
|
||||
let mut wallet_proxy: WalletProxy<LocalWalletClient, LocalWalletClient, ExtKeychain> =
|
||||
WalletProxy::new(test_dir);
|
||||
let chain = wallet_proxy.chain.clone();
|
||||
|
||||
// Create a new wallet test client, and set its queues to communicate with the
|
||||
// proxy
|
||||
let client = LocalWalletClient::new("wallet1", wallet_proxy.tx.clone());
|
||||
let wallet1 = common::create_wallet(&format!("{}/wallet1", test_dir), client.clone());
|
||||
let wallet1 = common::create_wallet(
|
||||
&format!("{}/wallet1", test_dir),
|
||||
client.clone(),
|
||||
client.clone(),
|
||||
);
|
||||
wallet_proxy.add_wallet("wallet1", client.get_send_instance(), wallet1.clone());
|
||||
|
||||
// define recipient wallet, add to proxy
|
||||
let wallet2 = common::create_wallet(&format!("{}/wallet2", test_dir), client.clone());
|
||||
let wallet2 = common::create_wallet(
|
||||
&format!("{}/wallet2", test_dir),
|
||||
client.clone(),
|
||||
client.clone(),
|
||||
);
|
||||
let client = LocalWalletClient::new("wallet2", wallet_proxy.tx.clone());
|
||||
wallet_proxy.add_wallet("wallet2", client.get_send_instance(), wallet2.clone());
|
||||
|
||||
|
|
|
@ -49,23 +49,32 @@ fn setup(test_dir: &str) {
|
|||
global::set_mining_mode(ChainTypes::AutomatedTesting);
|
||||
}
|
||||
|
||||
/// Exercises the Transaction API fully with a test WalletClient operating
|
||||
/// Exercises the Transaction API fully with a test WalletToNodeClient operating
|
||||
/// directly on a chain instance
|
||||
/// Callable with any type of wallet
|
||||
fn basic_transaction_api(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||
setup(test_dir);
|
||||
// Create a new proxy to simulate server and wallet responses
|
||||
let mut wallet_proxy: WalletProxy<LocalWalletClient, ExtKeychain> = WalletProxy::new(test_dir);
|
||||
let mut wallet_proxy: WalletProxy<LocalWalletClient, LocalWalletClient, ExtKeychain> =
|
||||
WalletProxy::new(test_dir);
|
||||
let chain = wallet_proxy.chain.clone();
|
||||
|
||||
// Create a new wallet test client, and set its queues to communicate with the
|
||||
// proxy
|
||||
let client = LocalWalletClient::new("wallet1", wallet_proxy.tx.clone());
|
||||
let wallet1 = common::create_wallet(&format!("{}/wallet1", test_dir), client.clone());
|
||||
let wallet1 = common::create_wallet(
|
||||
&format!("{}/wallet1", test_dir),
|
||||
client.clone(),
|
||||
client.clone(),
|
||||
);
|
||||
wallet_proxy.add_wallet("wallet1", client.get_send_instance(), wallet1.clone());
|
||||
|
||||
// define recipient wallet, add to proxy
|
||||
let wallet2 = common::create_wallet(&format!("{}/wallet2", test_dir), client.clone());
|
||||
let wallet2 = common::create_wallet(
|
||||
&format!("{}/wallet2", test_dir),
|
||||
client.clone(),
|
||||
client.clone(),
|
||||
);
|
||||
let client = LocalWalletClient::new("wallet2", wallet_proxy.tx.clone());
|
||||
wallet_proxy.add_wallet("wallet2", client.get_send_instance(), wallet2.clone());
|
||||
|
||||
|
@ -296,18 +305,27 @@ fn basic_transaction_api(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
fn tx_rollback(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||
setup(test_dir);
|
||||
// Create a new proxy to simulate server and wallet responses
|
||||
let mut wallet_proxy: WalletProxy<LocalWalletClient, ExtKeychain> = WalletProxy::new(test_dir);
|
||||
let mut wallet_proxy: WalletProxy<LocalWalletClient, LocalWalletClient, ExtKeychain> =
|
||||
WalletProxy::new(test_dir);
|
||||
let chain = wallet_proxy.chain.clone();
|
||||
|
||||
// Create a new wallet test client, and set its queues to communicate with the
|
||||
// proxy
|
||||
let client = LocalWalletClient::new("wallet1", wallet_proxy.tx.clone());
|
||||
let wallet1 = common::create_wallet(&format!("{}/wallet1", test_dir), client.clone());
|
||||
let wallet1 = common::create_wallet(
|
||||
&format!("{}/wallet1", test_dir),
|
||||
client.clone(),
|
||||
client.clone(),
|
||||
);
|
||||
wallet_proxy.add_wallet("wallet1", client.get_send_instance(), wallet1.clone());
|
||||
|
||||
// define recipient wallet, add to proxy
|
||||
let client = LocalWalletClient::new("wallet2", wallet_proxy.tx.clone());
|
||||
let wallet2 = common::create_wallet(&format!("{}/wallet2", test_dir), client.clone());
|
||||
let wallet2 = common::create_wallet(
|
||||
&format!("{}/wallet2", test_dir),
|
||||
client.clone(),
|
||||
client.clone(),
|
||||
);
|
||||
wallet_proxy.add_wallet("wallet2", client.get_send_instance(), wallet2.clone());
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
|
|
Loading…
Reference in a new issue