mirror of
https://github.com/jwinterm/grin-wallet.git
synced 2026-10-17 15:21:39 +02:00
Add linter to CI (#823)
Co-authored-by: wiesche <wiesche89@googlemail.com>
This commit is contained in:
committed by
GitHub
co-authored by
wiesche
parent
ec1e9910af
commit
fe79256467
@@ -2,6 +2,17 @@ name: Continuous Integration
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
clippy:
|
||||
name: Cargo clippy
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
- run: rustup toolchain install 1.99.0 --profile minimal --component clippy
|
||||
- run: cargo +1.99.0 clippy --workspace --all-targets -- -D warnings
|
||||
|
||||
# Run tests alongside Clippy, even if lint fails
|
||||
linux-tests:
|
||||
name: Linux Tests
|
||||
runs-on: ubuntu-latest
|
||||
@@ -36,4 +47,4 @@ jobs:
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Tests
|
||||
run: cargo test --release --all
|
||||
run: cargo test --release --all
|
||||
|
||||
@@ -14,6 +14,14 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
cargo +1.99.0 clippy --workspace --all-targets -- -D warnings
|
||||
if [ $? != 0 ]; then
|
||||
printf "clippy check failed; check with:\n"
|
||||
printf "cargo +1.99.0 clippy --workspace --all-targets -- -D warnings\n"
|
||||
printf "if clippy is missing: rustup toolchain install 1.99.0 --profile minimal --component clippy\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rustfmt --version &>/dev/null
|
||||
if [ $? != 0 ]; then
|
||||
printf "[pre_commit] \033[0;31merror\033[0m: \"rustfmt\" not available. \n"
|
||||
|
||||
+24
-34
@@ -18,16 +18,12 @@ use crate::keychain::Keychain;
|
||||
use crate::libwallet::api_impl::foreign;
|
||||
use crate::libwallet::api_impl::types::update_tx_slate_state;
|
||||
use crate::libwallet::{
|
||||
BlockFees, CbData, Error, NodeClient, NodeVersionInfo, Slate, VersionInfo, WalletInst,
|
||||
WalletLCProvider,
|
||||
BlockFees, CbData, Error, NodeClient, NodeVersionInfo, Slate, VersionInfo, WalletLCProvider,
|
||||
};
|
||||
use crate::try_slatepack_sync_workflow;
|
||||
use crate::util::secp::key::SecretKey;
|
||||
use crate::util::Mutex;
|
||||
use libwallet::SlatepackAddress;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
/// ForeignAPI Middleware Check callback
|
||||
pub type ForeignCheckMiddleware =
|
||||
fn(ForeignCheckMiddlewareFn, Option<NodeVersionInfo>, Option<&Slate>) -> Result<(), Error>;
|
||||
@@ -51,15 +47,14 @@ pub enum ForeignCheckMiddlewareFn {
|
||||
/// called the ['Owner'](struct.Owner.html) and ['Foreign'](struct.Foreign.html) APIs
|
||||
///
|
||||
/// * The 'Foreign' API contains methods that other wallets will
|
||||
/// use to interact with the owner's wallet. This API can be exposed
|
||||
/// to the outside world, with the consideration as to how that can
|
||||
/// be done securely up to the implementor.
|
||||
/// use to interact with the owner's wallet. This API can be exposed
|
||||
/// to the outside world, with the consideration as to how that can
|
||||
/// be done securely up to the implementor.
|
||||
///
|
||||
/// Methods in both APIs are intended to be 'single use', that is to say each
|
||||
/// method will 'open' the wallet (load the keychain with its master seed), perform
|
||||
/// its operation, then 'close' the wallet (unloading references to the keychain and master
|
||||
/// seed).
|
||||
|
||||
pub struct Foreign<'a, L, C, K>
|
||||
where
|
||||
L: WalletLCProvider<'a, C, K>,
|
||||
@@ -67,7 +62,7 @@ where
|
||||
K: Keychain + 'a,
|
||||
{
|
||||
/// Wallet instance
|
||||
pub wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
pub wallet_inst: grin_wallet_libwallet::WalletHandle<'a, L, C, K>,
|
||||
/// Wallet configuration path
|
||||
config_path: crate::ConfigPath,
|
||||
/// Flag to normalize some output during testing. Can mostly be ignored.
|
||||
@@ -94,13 +89,13 @@ where
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `wallet_in` - A reference-counted mutex containing an implementation of the
|
||||
/// [`WalletBackend`](../grin_wallet_libwallet/types/trait.WalletBackend.html) trait.
|
||||
/// [`WalletBackend`](../grin_wallet_libwallet/types/trait.WalletBackend.html) trait.
|
||||
/// * `config_path` - Path to the wallet configuration file
|
||||
/// * `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)
|
||||
/// 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
|
||||
/// a predefined function with the slate to check if the operation should continue
|
||||
///
|
||||
/// # Returns
|
||||
/// * An instance of the ForeignApi holding a reference to the provided wallet
|
||||
@@ -170,9 +165,8 @@ where
|
||||
/// // .. perform wallet operations
|
||||
///
|
||||
/// ```
|
||||
|
||||
pub fn new<P>(
|
||||
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet_inst: grin_wallet_libwallet::WalletHandle<'a, L, C, K>,
|
||||
config_path: P,
|
||||
keychain_mask: Option<SecretKey>,
|
||||
middleware: Option<ForeignCheckMiddleware>,
|
||||
@@ -205,7 +199,6 @@ where
|
||||
/// let version_info = api_foreign.check_version();
|
||||
/// // check and proceed accordingly
|
||||
/// ```
|
||||
|
||||
pub fn check_version(&self) -> Result<VersionInfo, Error> {
|
||||
if let Some(m) = self.middleware.as_ref() {
|
||||
let mut w_lock = self.wallet_inst.lock();
|
||||
@@ -231,7 +224,7 @@ where
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `block_fees` - A [`BlockFees`](../grin_wallet_libwallet/api_impl/types/struct.BlockFees.html)
|
||||
/// struct, set up as follows:
|
||||
/// struct, set up as follows:
|
||||
///
|
||||
/// `fees` - should contain the sum of all transaction fees included in the potential
|
||||
/// block
|
||||
@@ -244,7 +237,7 @@ where
|
||||
///
|
||||
/// # Returns
|
||||
/// * `Ok`([`cb_data`](../grin_wallet_libwallet/api_impl/types/struct.CbData.html)`)` if successful. This
|
||||
/// will contain the corresponding output, kernel and keyID used to create the coinbase output.
|
||||
/// will contain the corresponding output, kernel and keyID used to create the coinbase output.
|
||||
/// * or [`libwallet::Error`](../grin_wallet_libwallet/struct.Error.html) if an error is encountered.
|
||||
///
|
||||
/// # Example
|
||||
@@ -268,7 +261,6 @@ where
|
||||
/// // ...
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
pub fn build_coinbase(&self, block_fees: &BlockFees) -> Result<CbData, Error> {
|
||||
let mut w_lock = self.wallet_inst.lock();
|
||||
let w = w_lock.lc_provider()?.wallet_inst()?;
|
||||
@@ -281,7 +273,7 @@ where
|
||||
}
|
||||
foreign::build_coinbase(
|
||||
w,
|
||||
(&self.keychain_mask).as_ref(),
|
||||
self.keychain_mask.as_ref(),
|
||||
block_fees,
|
||||
self.doctest_mode,
|
||||
)
|
||||
@@ -304,18 +296,18 @@ where
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `slate` - The transaction [`Slate`](../grin_wallet_libwallet/slate/struct.Slate.html).
|
||||
/// The slate should contain the results of the sender's round 1 (e.g, public nonce and public
|
||||
/// excess value).
|
||||
/// The slate should contain the results of the sender's round 1 (e.g, public nonce and public
|
||||
/// excess value).
|
||||
/// * `dest_acct_name` - The name of the account into which the slate should be received. If
|
||||
/// `None`, the default account is used.
|
||||
/// `None`, the default account is used.
|
||||
/// * `r_addr` - If included, attempt to send the slate back to the sender using the slatepack sync
|
||||
/// send (TOR). If providing this argument, check the `state` field of the slate to see if the
|
||||
/// sync_send was successful (it should be S3 if the synced send sent successfully).
|
||||
/// send (TOR). If providing this argument, check the `state` field of the slate to see if the
|
||||
/// sync_send was successful (it should be S3 if the synced send sent successfully).
|
||||
///
|
||||
/// # Returns
|
||||
/// * a result containing:
|
||||
/// * `Ok`([`slate`](../grin_wallet_libwallet/slate/struct.Slate.html)`)` if successful,
|
||||
/// containing the new slate updated with the recipient's output and public signing information.
|
||||
/// containing the new slate updated with the recipient's output and public signing information.
|
||||
/// * or [`libwallet::Error`](../grin_wallet_libwallet/struct.Error.html) if an error is encountered.
|
||||
///
|
||||
/// # Remarks
|
||||
@@ -339,7 +331,6 @@ where
|
||||
/// // ...
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
pub fn receive_tx(
|
||||
&self,
|
||||
slate: &Slate,
|
||||
@@ -361,7 +352,7 @@ where
|
||||
}
|
||||
let ret_slate = foreign::receive_tx(
|
||||
w,
|
||||
(&self.keychain_mask).as_ref(),
|
||||
self.keychain_mask.as_ref(),
|
||||
slate,
|
||||
dest_acct_name,
|
||||
self.doctest_mode,
|
||||
@@ -381,7 +372,7 @@ where
|
||||
let parent_key_id = w.parent_key_id();
|
||||
match update_tx_slate_state(
|
||||
w,
|
||||
(&self.keychain_mask).as_ref(),
|
||||
self.keychain_mask.as_ref(),
|
||||
&parent_key_id,
|
||||
&s,
|
||||
) {
|
||||
@@ -416,11 +407,11 @@ where
|
||||
/// # Arguments
|
||||
/// * `slate` - The transaction [`Slate`](../grin_wallet_libwallet/slate/struct.Slate.html). The
|
||||
/// * `post_automatically` - If true, post the finalized transaction to the configured listening
|
||||
/// node
|
||||
/// node
|
||||
///
|
||||
/// # Returns
|
||||
/// * Ok([`slate`](../grin_wallet_libwallet/slate/struct.Slate.html)) if successful,
|
||||
/// containing the new finalized slate.
|
||||
/// containing the new finalized slate.
|
||||
/// * or [`libwallet::Error`](../grin_wallet_libwallet/struct.Error.html) if an error is encountered.
|
||||
///
|
||||
/// # Example
|
||||
@@ -447,7 +438,6 @@ where
|
||||
/// let slate = api_foreign.finalize_tx(&slate, true);
|
||||
/// // if okay, then post via the owner API
|
||||
/// ```
|
||||
|
||||
pub fn finalize_tx(&self, slate: &Slate, post_automatically: bool) -> Result<Slate, Error> {
|
||||
let mut w_lock = self.wallet_inst.lock();
|
||||
let w = w_lock.lc_provider()?.wallet_inst()?;
|
||||
@@ -455,7 +445,7 @@ where
|
||||
true => false,
|
||||
false => post_automatically,
|
||||
};
|
||||
foreign::finalize_tx(w, (&self.keychain_mask).as_ref(), slate, post_automatically)
|
||||
foreign::finalize_tx(w, self.keychain_mask.as_ref(), slate, post_automatically)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+11
-23
@@ -20,7 +20,6 @@ use crate::libwallet::{
|
||||
Slate, SlateVersion, VersionInfo, VersionedCoinbase, VersionedSlate, WalletLCProvider,
|
||||
};
|
||||
use crate::{Foreign, ForeignCheckMiddlewareFn};
|
||||
use easy_jsonrpc_mw;
|
||||
use grin_wallet_config::initial_setup_wallet;
|
||||
use libwallet::SlatepackAddress;
|
||||
use std::path::PathBuf;
|
||||
@@ -112,7 +111,6 @@ pub trait ForeignRpc {
|
||||
# ,false, 4, false, false);
|
||||
```
|
||||
*/
|
||||
|
||||
fn build_coinbase(&self, block_fees: &BlockFees) -> Result<VersionedCoinbase, Error>;
|
||||
|
||||
/**
|
||||
@@ -322,19 +320,14 @@ where
|
||||
}
|
||||
},
|
||||
};
|
||||
let out_slate = Foreign::receive_tx(
|
||||
self,
|
||||
&slate_from,
|
||||
dest_acct_name.as_ref().map(String::as_str),
|
||||
dest,
|
||||
)?;
|
||||
Ok(VersionedSlate::into_version(out_slate, version)?)
|
||||
let out_slate = Foreign::receive_tx(self, &slate_from, dest_acct_name.as_deref(), dest)?;
|
||||
VersionedSlate::into_version(out_slate, version)
|
||||
}
|
||||
|
||||
fn finalize_tx(&self, in_slate: VersionedSlate) -> Result<VersionedSlate, Error> {
|
||||
let version = in_slate.version();
|
||||
let out_slate = Foreign::finalize_tx(self, &Slate::from(in_slate), true)?;
|
||||
Ok(VersionedSlate::into_version(out_slate, version)?)
|
||||
VersionedSlate::into_version(out_slate, version)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -467,19 +460,14 @@ pub fn run_doctest_foreign(
|
||||
let _ = test_framework::award_blocks_to_wallet(
|
||||
&chain,
|
||||
wallet1.clone(),
|
||||
(&mask1).as_ref(),
|
||||
1 as usize,
|
||||
mask1.as_ref(),
|
||||
1_usize,
|
||||
false,
|
||||
);
|
||||
//update local outputs after each block, so transaction IDs stay consistent
|
||||
let (wallet_refreshed, _) = api_impl::owner::retrieve_summary_info(
|
||||
wallet1.clone(),
|
||||
(&mask1).as_ref(),
|
||||
&None,
|
||||
true,
|
||||
1,
|
||||
)
|
||||
.unwrap();
|
||||
let (wallet_refreshed, _) =
|
||||
api_impl::owner::retrieve_summary_info(wallet1.clone(), mask1.as_ref(), &None, true, 1)
|
||||
.unwrap();
|
||||
assert!(wallet_refreshed);
|
||||
}
|
||||
|
||||
@@ -492,7 +480,7 @@ pub fn run_doctest_foreign(
|
||||
amount,
|
||||
..Default::default()
|
||||
};
|
||||
api_impl::owner::issue_invoice_tx(w, (&mask2).as_ref(), args, true).unwrap()
|
||||
api_impl::owner::issue_invoice_tx(w, mask2.as_ref(), args, true).unwrap()
|
||||
};
|
||||
slate = {
|
||||
let mut w_lock = wallet1.lock();
|
||||
@@ -506,7 +494,7 @@ pub fn run_doctest_foreign(
|
||||
selection_strategy_is_use_all: true,
|
||||
..Default::default()
|
||||
};
|
||||
api_impl::owner::process_invoice_tx(w, (&mask1).as_ref(), &slate, args, true).unwrap()
|
||||
api_impl::owner::process_invoice_tx(w, mask1.as_ref(), &slate, args, true).unwrap()
|
||||
};
|
||||
println!("INIT INVOICE SLATE");
|
||||
// Spit out slate for input to finalize_tx
|
||||
@@ -526,7 +514,7 @@ pub fn run_doctest_foreign(
|
||||
selection_strategy_is_use_all: true,
|
||||
..Default::default()
|
||||
};
|
||||
let slate = api_impl::owner::init_send_tx(w, (&mask1).as_ref(), args, true).unwrap();
|
||||
let slate = api_impl::owner::init_send_tx(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());
|
||||
|
||||
+189
-238
File diff suppressed because it is too large
Load Diff
+56
-110
@@ -32,7 +32,6 @@ use crate::util::secp::key::{PublicKey, SecretKey};
|
||||
use crate::util::secp::pedersen::Commitment;
|
||||
use crate::util::{from_hex, static_secp_instance, Mutex, ZeroingString};
|
||||
use crate::{ECDHPubkey, Ed25519SecretKey, Owner, Token};
|
||||
use easy_jsonrpc_mw;
|
||||
use grin_wallet_util::OnionV3Address;
|
||||
use rand::thread_rng;
|
||||
use std::convert::TryFrom;
|
||||
@@ -171,6 +170,7 @@ pub trait OwnerRpc {
|
||||
# , 4, false, false, false, false);
|
||||
```
|
||||
*/
|
||||
#[allow(clippy::ptr_arg)]
|
||||
fn create_account_path(&self, token: Token, label: &String) -> Result<Identifier, Error>;
|
||||
|
||||
/**
|
||||
@@ -205,6 +205,7 @@ pub trait OwnerRpc {
|
||||
# , 4, false, false, false, false);
|
||||
```
|
||||
*/
|
||||
#[allow(clippy::ptr_arg)]
|
||||
fn set_active_account(&self, token: Token, label: &String) -> Result<(), Error>;
|
||||
|
||||
/**
|
||||
@@ -276,7 +277,6 @@ pub trait OwnerRpc {
|
||||
# , 2, false, false, false, false);
|
||||
```
|
||||
*/
|
||||
|
||||
fn retrieve_outputs(
|
||||
&self,
|
||||
token: Token,
|
||||
@@ -322,7 +322,6 @@ pub trait OwnerRpc {
|
||||
# , 4, false, false, false, false);
|
||||
```
|
||||
*/
|
||||
|
||||
fn estimate_max_sendable(
|
||||
&self,
|
||||
token: Token,
|
||||
@@ -409,7 +408,6 @@ pub trait OwnerRpc {
|
||||
# , 2, false, false, false, false);
|
||||
```
|
||||
*/
|
||||
|
||||
fn retrieve_txs(
|
||||
&self,
|
||||
token: Token,
|
||||
@@ -503,7 +501,6 @@ pub trait OwnerRpc {
|
||||
```
|
||||
|
||||
*/
|
||||
|
||||
fn query_txs(
|
||||
&self,
|
||||
token: Token,
|
||||
@@ -554,7 +551,6 @@ pub trait OwnerRpc {
|
||||
# , 4, false, false, false, false);
|
||||
```
|
||||
*/
|
||||
|
||||
fn retrieve_summary_info(
|
||||
&self,
|
||||
token: Token,
|
||||
@@ -619,7 +615,6 @@ pub trait OwnerRpc {
|
||||
# , 4, false, false, false, false);
|
||||
```
|
||||
*/
|
||||
|
||||
fn init_send_tx(&self, token: Token, args: InitTxArgs) -> Result<VersionedSlate, Error>;
|
||||
|
||||
/**
|
||||
@@ -666,7 +661,6 @@ pub trait OwnerRpc {
|
||||
# , 4, false, false, false, false);
|
||||
```
|
||||
*/
|
||||
|
||||
fn issue_invoice_tx(
|
||||
&self,
|
||||
token: Token,
|
||||
@@ -750,7 +744,6 @@ pub trait OwnerRpc {
|
||||
# , 4, false, false, false, false);
|
||||
```
|
||||
*/
|
||||
|
||||
fn process_invoice_tx(
|
||||
&self,
|
||||
token: Token,
|
||||
@@ -955,7 +948,6 @@ pub trait OwnerRpc {
|
||||
# , 5, true, true, true, false);
|
||||
```
|
||||
*/
|
||||
|
||||
fn post_tx(&self, token: Token, slate: VersionedSlate, fluff: bool) -> Result<(), Error>;
|
||||
|
||||
/**
|
||||
@@ -1277,7 +1269,6 @@ pub trait OwnerRpc {
|
||||
```
|
||||
|
||||
*/
|
||||
|
||||
fn init_secure_api(&self, ecdh_pubkey: ECDHPubkey) -> Result<ECDHPubkey, Error>;
|
||||
|
||||
/**
|
||||
@@ -1307,7 +1298,6 @@ pub trait OwnerRpc {
|
||||
# , 5, false, false, false, false);
|
||||
```
|
||||
*/
|
||||
|
||||
fn get_top_level_directory(&self) -> Result<String, Error>;
|
||||
|
||||
/**
|
||||
@@ -1340,7 +1330,6 @@ pub trait OwnerRpc {
|
||||
# , 5, false, false, false, false);
|
||||
```
|
||||
*/
|
||||
|
||||
fn set_top_level_directory(&self, dir: String) -> Result<(), Error>;
|
||||
|
||||
/**
|
||||
@@ -1443,7 +1432,6 @@ pub trait OwnerRpc {
|
||||
# , 0, false, false, false, false);
|
||||
```
|
||||
*/
|
||||
|
||||
fn create_wallet(
|
||||
&self,
|
||||
name: Option<String>,
|
||||
@@ -1480,7 +1468,6 @@ pub trait OwnerRpc {
|
||||
# , 0, false, false, false, false);
|
||||
```
|
||||
*/
|
||||
|
||||
fn open_wallet(&self, name: Option<String>, password: String) -> Result<Token, Error>;
|
||||
|
||||
/**
|
||||
@@ -1510,7 +1497,6 @@ pub trait OwnerRpc {
|
||||
# , 0, false, false, false, false);
|
||||
```
|
||||
*/
|
||||
|
||||
fn close_wallet(&self, name: Option<String>) -> Result<(), Error>;
|
||||
|
||||
/**
|
||||
@@ -1541,7 +1527,6 @@ pub trait OwnerRpc {
|
||||
# , 0, false, false, false, false);
|
||||
```
|
||||
*/
|
||||
|
||||
fn get_mnemonic(&self, name: Option<String>, password: String) -> Result<String, Error>;
|
||||
|
||||
/**
|
||||
@@ -1632,7 +1617,6 @@ pub trait OwnerRpc {
|
||||
# , 0, false, false, false, false);
|
||||
```
|
||||
*/
|
||||
|
||||
fn start_updater(&self, token: Token, frequency: u32) -> Result<(), Error>;
|
||||
|
||||
/**
|
||||
@@ -1689,7 +1673,6 @@ pub trait OwnerRpc {
|
||||
# , 0, false, false, false, false);
|
||||
```
|
||||
*/
|
||||
|
||||
fn get_updater_messages(&self, count: u32) -> Result<Vec<StatusMessage>, Error>;
|
||||
|
||||
/**
|
||||
@@ -1720,7 +1703,6 @@ pub trait OwnerRpc {
|
||||
# , 0, false, false, false, false);
|
||||
```
|
||||
*/
|
||||
|
||||
fn get_slatepack_address(
|
||||
&self,
|
||||
token: Token,
|
||||
@@ -1755,7 +1737,6 @@ pub trait OwnerRpc {
|
||||
# , 0, false, false, false, false);
|
||||
```
|
||||
*/
|
||||
|
||||
fn get_slatepack_secret_key(
|
||||
&self,
|
||||
token: Token,
|
||||
@@ -1805,7 +1786,6 @@ pub trait OwnerRpc {
|
||||
# , 0, false, false, false, false);
|
||||
```
|
||||
*/
|
||||
|
||||
fn create_slatepack_message(
|
||||
&self,
|
||||
token: Token,
|
||||
@@ -1860,7 +1840,6 @@ pub trait OwnerRpc {
|
||||
# , 0, false, false, false, false);
|
||||
```
|
||||
*/
|
||||
|
||||
fn slate_from_slatepack_message(
|
||||
&self,
|
||||
token: Token,
|
||||
@@ -1902,7 +1881,6 @@ pub trait OwnerRpc {
|
||||
# , 0, false, false, false, false);
|
||||
```
|
||||
*/
|
||||
|
||||
fn decode_slatepack_message(
|
||||
&self,
|
||||
token: Token,
|
||||
@@ -1947,7 +1925,6 @@ pub trait OwnerRpc {
|
||||
# , 5, true, true, true, true);
|
||||
```
|
||||
*/
|
||||
|
||||
fn retrieve_payment_proof(
|
||||
&self,
|
||||
token: Token,
|
||||
@@ -1994,7 +1971,6 @@ pub trait OwnerRpc {
|
||||
# , 5, true, true, true, true);
|
||||
```
|
||||
*/
|
||||
|
||||
fn verify_payment_proof(
|
||||
&self,
|
||||
token: Token,
|
||||
@@ -2125,7 +2101,6 @@ pub trait OwnerRpc {
|
||||
```
|
||||
*
|
||||
*/
|
||||
|
||||
fn create_mwixnet_req(
|
||||
&self,
|
||||
token: Token,
|
||||
@@ -2143,7 +2118,7 @@ where
|
||||
K: Keychain + 'static,
|
||||
{
|
||||
fn accounts(&self, token: Token) -> Result<Vec<AcctPathMapping>, Error> {
|
||||
Owner::accounts(self, (&token.keychain_mask).as_ref())
|
||||
Owner::accounts(self, token.keychain_mask.as_ref())
|
||||
}
|
||||
|
||||
fn accounts_info(
|
||||
@@ -2151,15 +2126,15 @@ where
|
||||
token: Token,
|
||||
minimum_confirmations: u64,
|
||||
) -> Result<Vec<AcctPathMapping>, Error> {
|
||||
Owner::accounts_info(self, (&token.keychain_mask).as_ref(), minimum_confirmations)
|
||||
Owner::accounts_info(self, token.keychain_mask.as_ref(), minimum_confirmations)
|
||||
}
|
||||
|
||||
fn create_account_path(&self, token: Token, label: &String) -> Result<Identifier, Error> {
|
||||
Owner::create_account_path(self, (&token.keychain_mask).as_ref(), label)
|
||||
Owner::create_account_path(self, token.keychain_mask.as_ref(), label)
|
||||
}
|
||||
|
||||
fn set_active_account(&self, token: Token, label: &String) -> Result<(), Error> {
|
||||
Owner::set_active_account(self, (&token.keychain_mask).as_ref(), label)
|
||||
Owner::set_active_account(self, token.keychain_mask.as_ref(), label)
|
||||
}
|
||||
|
||||
fn retrieve_outputs(
|
||||
@@ -2171,7 +2146,7 @@ where
|
||||
) -> Result<(bool, Vec<OutputCommitMapping>), Error> {
|
||||
Owner::retrieve_outputs(
|
||||
self,
|
||||
(&token.keychain_mask).as_ref(),
|
||||
token.keychain_mask.as_ref(),
|
||||
include_spent,
|
||||
refresh_from_node,
|
||||
tx_id,
|
||||
@@ -2186,7 +2161,7 @@ where
|
||||
) -> Result<(bool, u64, u64, u32), Error> {
|
||||
Owner::estimate_max_sendable(
|
||||
self,
|
||||
(&token.keychain_mask).as_ref(),
|
||||
token.keychain_mask.as_ref(),
|
||||
refresh_from_node,
|
||||
minimum_confirmations,
|
||||
)
|
||||
@@ -2201,7 +2176,7 @@ where
|
||||
) -> Result<(bool, Vec<TxLogEntry>), Error> {
|
||||
Owner::retrieve_txs(
|
||||
self,
|
||||
(&token.keychain_mask).as_ref(),
|
||||
token.keychain_mask.as_ref(),
|
||||
refresh_from_node,
|
||||
tx_id,
|
||||
tx_slate_id,
|
||||
@@ -2217,7 +2192,7 @@ where
|
||||
) -> Result<(bool, Vec<TxLogEntry>), Error> {
|
||||
Owner::retrieve_txs(
|
||||
self,
|
||||
(&token.keychain_mask).as_ref(),
|
||||
token.keychain_mask.as_ref(),
|
||||
refresh_from_node,
|
||||
None,
|
||||
None,
|
||||
@@ -2233,14 +2208,14 @@ where
|
||||
) -> Result<(bool, WalletInfo), Error> {
|
||||
Owner::retrieve_summary_info(
|
||||
self,
|
||||
(&token.keychain_mask).as_ref(),
|
||||
token.keychain_mask.as_ref(),
|
||||
refresh_from_node,
|
||||
minimum_confirmations,
|
||||
)
|
||||
}
|
||||
|
||||
fn init_send_tx(&self, token: Token, args: InitTxArgs) -> Result<VersionedSlate, Error> {
|
||||
let slate = Owner::init_send_tx(self, (&token.keychain_mask).as_ref(), args)?;
|
||||
let slate = Owner::init_send_tx(self, token.keychain_mask.as_ref(), args)?;
|
||||
let version = SlateVersion::V4;
|
||||
VersionedSlate::into_version(slate, version)
|
||||
}
|
||||
@@ -2250,7 +2225,7 @@ where
|
||||
token: Token,
|
||||
args: IssueInvoiceTxArgs,
|
||||
) -> Result<VersionedSlate, Error> {
|
||||
let slate = Owner::issue_invoice_tx(self, (&token.keychain_mask).as_ref(), args)?;
|
||||
let slate = Owner::issue_invoice_tx(self, token.keychain_mask.as_ref(), args)?;
|
||||
let version = SlateVersion::V4;
|
||||
VersionedSlate::into_version(slate, version)
|
||||
}
|
||||
@@ -2263,7 +2238,7 @@ where
|
||||
) -> Result<VersionedSlate, Error> {
|
||||
let out_slate = Owner::process_invoice_tx(
|
||||
self,
|
||||
(&token.keychain_mask).as_ref(),
|
||||
token.keychain_mask.as_ref(),
|
||||
&Slate::from(in_slate),
|
||||
args,
|
||||
)?;
|
||||
@@ -2272,19 +2247,12 @@ where
|
||||
}
|
||||
|
||||
fn tx_lock_outputs(&self, token: Token, in_slate: VersionedSlate) -> Result<(), Error> {
|
||||
Owner::tx_lock_outputs(
|
||||
self,
|
||||
(&token.keychain_mask).as_ref(),
|
||||
&Slate::from(in_slate),
|
||||
)
|
||||
Owner::tx_lock_outputs(self, token.keychain_mask.as_ref(), &Slate::from(in_slate))
|
||||
}
|
||||
|
||||
fn finalize_tx(&self, token: Token, in_slate: VersionedSlate) -> Result<VersionedSlate, Error> {
|
||||
let out_slate = Owner::finalize_tx(
|
||||
self,
|
||||
(&token.keychain_mask).as_ref(),
|
||||
&Slate::from(in_slate),
|
||||
)?;
|
||||
let out_slate =
|
||||
Owner::finalize_tx(self, token.keychain_mask.as_ref(), &Slate::from(in_slate))?;
|
||||
let version = SlateVersion::V4;
|
||||
VersionedSlate::into_version(out_slate, version)
|
||||
}
|
||||
@@ -2292,7 +2260,7 @@ where
|
||||
fn post_tx(&self, token: Token, slate: VersionedSlate, fluff: bool) -> Result<(), Error> {
|
||||
Owner::post_tx(
|
||||
self,
|
||||
(&token.keychain_mask).as_ref(),
|
||||
token.keychain_mask.as_ref(),
|
||||
&Slate::from(slate),
|
||||
fluff,
|
||||
)
|
||||
@@ -2304,7 +2272,7 @@ where
|
||||
tx_id: Option<u32>,
|
||||
tx_slate_id: Option<Uuid>,
|
||||
) -> Result<(), Error> {
|
||||
Owner::cancel_tx(self, (&token.keychain_mask).as_ref(), tx_id, tx_slate_id)
|
||||
Owner::cancel_tx(self, token.keychain_mask.as_ref(), tx_id, tx_slate_id)
|
||||
}
|
||||
|
||||
fn get_stored_tx(
|
||||
@@ -2313,12 +2281,8 @@ where
|
||||
id: Option<u32>,
|
||||
slate_id: Option<Uuid>,
|
||||
) -> Result<Option<VersionedSlate>, Error> {
|
||||
let out_slate = Owner::get_stored_tx(
|
||||
self,
|
||||
(&token.keychain_mask).as_ref(),
|
||||
id,
|
||||
(&slate_id).as_ref(),
|
||||
)?;
|
||||
let out_slate =
|
||||
Owner::get_stored_tx(self, token.keychain_mask.as_ref(), id, slate_id.as_ref())?;
|
||||
match out_slate {
|
||||
Some(s) => {
|
||||
let version = SlateVersion::V4;
|
||||
@@ -2329,7 +2293,7 @@ where
|
||||
}
|
||||
|
||||
fn get_rewind_hash(&self, token: Token) -> Result<String, Error> {
|
||||
Owner::get_rewind_hash(self, (&token.keychain_mask).as_ref())
|
||||
Owner::get_rewind_hash(self, token.keychain_mask.as_ref())
|
||||
}
|
||||
|
||||
fn scan_rewind_hash(
|
||||
@@ -2348,14 +2312,14 @@ where
|
||||
) -> Result<(), Error> {
|
||||
Owner::scan(
|
||||
self,
|
||||
(&token.keychain_mask).as_ref(),
|
||||
token.keychain_mask.as_ref(),
|
||||
start_height,
|
||||
delete_unconfirmed,
|
||||
)
|
||||
}
|
||||
|
||||
fn node_height(&self, token: Token) -> Result<NodeHeightResult, Error> {
|
||||
Owner::node_height(self, (&token.keychain_mask).as_ref())
|
||||
Owner::node_height(self, token.keychain_mask.as_ref())
|
||||
}
|
||||
|
||||
fn init_secure_api(&self, ecdh_pubkey: ECDHPubkey) -> Result<ECDHPubkey, Error> {
|
||||
@@ -2407,16 +2371,13 @@ where
|
||||
mnemonic_length: u32,
|
||||
password: String,
|
||||
) -> Result<(), Error> {
|
||||
let n = name.as_ref().map(|s| s.as_str());
|
||||
let m = match mnemonic {
|
||||
Some(s) => Some(ZeroingString::from(s)),
|
||||
None => None,
|
||||
};
|
||||
let n = name.as_deref();
|
||||
let m = mnemonic.map(ZeroingString::from);
|
||||
Owner::create_wallet(self, n, m, mnemonic_length, ZeroingString::from(password))
|
||||
}
|
||||
|
||||
fn open_wallet(&self, name: Option<String>, password: String) -> Result<Token, Error> {
|
||||
let n = name.as_ref().map(|s| s.as_str());
|
||||
let n = name.as_deref();
|
||||
let sec_key = Owner::open_wallet(self, n, ZeroingString::from(password), true)?;
|
||||
Ok(Token {
|
||||
keychain_mask: sec_key,
|
||||
@@ -2424,30 +2385,30 @@ where
|
||||
}
|
||||
|
||||
fn close_wallet(&self, name: Option<String>) -> Result<(), Error> {
|
||||
let n = name.as_ref().map(|s| s.as_str());
|
||||
let n = name.as_deref();
|
||||
Owner::close_wallet(self, n)
|
||||
}
|
||||
|
||||
fn get_mnemonic(&self, name: Option<String>, password: String) -> Result<String, Error> {
|
||||
let n = name.as_ref().map(|s| s.as_str());
|
||||
let n = name.as_deref();
|
||||
let res = Owner::get_mnemonic(self, n, ZeroingString::from(password))?;
|
||||
Ok((&*res).to_string())
|
||||
Ok((*res).to_string())
|
||||
}
|
||||
|
||||
fn change_password(&self, name: Option<String>, old: String, new: String) -> Result<(), Error> {
|
||||
let n = name.as_ref().map(|s| s.as_str());
|
||||
let n = name.as_deref();
|
||||
Owner::change_password(self, n, ZeroingString::from(old), ZeroingString::from(new))
|
||||
}
|
||||
|
||||
fn delete_wallet(&self, name: Option<String>) -> Result<(), Error> {
|
||||
let n = name.as_ref().map(|s| s.as_str());
|
||||
let n = name.as_deref();
|
||||
Owner::delete_wallet(self, n)
|
||||
}
|
||||
|
||||
fn start_updater(&self, token: Token, frequency: u32) -> Result<(), Error> {
|
||||
Owner::start_updater(
|
||||
self,
|
||||
(&token.keychain_mask).as_ref(),
|
||||
token.keychain_mask.as_ref(),
|
||||
Duration::from_millis(frequency as u64),
|
||||
)
|
||||
}
|
||||
@@ -2465,7 +2426,7 @@ where
|
||||
token: Token,
|
||||
derivation_index: u32,
|
||||
) -> Result<SlatepackAddress, Error> {
|
||||
Owner::get_slatepack_address(self, (&token.keychain_mask).as_ref(), derivation_index)
|
||||
Owner::get_slatepack_address(self, token.keychain_mask.as_ref(), derivation_index)
|
||||
}
|
||||
|
||||
fn get_slatepack_secret_key(
|
||||
@@ -2473,11 +2434,8 @@ where
|
||||
token: Token,
|
||||
derivation_index: u32,
|
||||
) -> Result<Ed25519SecretKey, Error> {
|
||||
let key = Owner::get_slatepack_secret_key(
|
||||
self,
|
||||
(&token.keychain_mask).as_ref(),
|
||||
derivation_index,
|
||||
)?;
|
||||
let key =
|
||||
Owner::get_slatepack_secret_key(self, token.keychain_mask.as_ref(), derivation_index)?;
|
||||
Ok(Ed25519SecretKey { key })
|
||||
}
|
||||
|
||||
@@ -2490,7 +2448,7 @@ where
|
||||
) -> Result<String, Error> {
|
||||
let res = Owner::create_slatepack_message(
|
||||
self,
|
||||
(&token.keychain_mask).as_ref(),
|
||||
token.keychain_mask.as_ref(),
|
||||
&Slate::from(slate),
|
||||
sender_index,
|
||||
recipients,
|
||||
@@ -2506,7 +2464,7 @@ where
|
||||
) -> Result<VersionedSlate, Error> {
|
||||
let slate = Owner::slate_from_slatepack_message(
|
||||
self,
|
||||
(&token.keychain_mask).as_ref(),
|
||||
token.keychain_mask.as_ref(),
|
||||
message,
|
||||
secret_indices,
|
||||
)?;
|
||||
@@ -2520,12 +2478,7 @@ where
|
||||
message: String,
|
||||
secret_indices: Vec<u32>,
|
||||
) -> Result<Slatepack, Error> {
|
||||
Owner::decode_slatepack_message(
|
||||
self,
|
||||
(&token.keychain_mask).as_ref(),
|
||||
message,
|
||||
secret_indices,
|
||||
)
|
||||
Owner::decode_slatepack_message(self, token.keychain_mask.as_ref(), message, secret_indices)
|
||||
}
|
||||
|
||||
fn retrieve_payment_proof(
|
||||
@@ -2537,7 +2490,7 @@ where
|
||||
) -> Result<PaymentProof, Error> {
|
||||
Owner::retrieve_payment_proof(
|
||||
self,
|
||||
(&token.keychain_mask).as_ref(),
|
||||
token.keychain_mask.as_ref(),
|
||||
refresh_from_node,
|
||||
tx_id,
|
||||
tx_slate_id,
|
||||
@@ -2549,7 +2502,7 @@ where
|
||||
token: Token,
|
||||
proof: PaymentProof,
|
||||
) -> Result<(bool, bool), Error> {
|
||||
Owner::verify_payment_proof(self, (&token.keychain_mask).as_ref(), &proof)
|
||||
Owner::verify_payment_proof(self, token.keychain_mask.as_ref(), &proof)
|
||||
}
|
||||
|
||||
fn set_tor_config(&self, tor_config: Option<TorConfig>) -> Result<(), Error> {
|
||||
@@ -2563,7 +2516,7 @@ where
|
||||
features: OutputFeatures,
|
||||
amount: Amount,
|
||||
) -> Result<BuiltOutput, Error> {
|
||||
Owner::build_output(self, (&token.keychain_mask).as_ref(), features, amount.0)
|
||||
Owner::build_output(self, token.keychain_mask.as_ref(), features, amount.0)
|
||||
}
|
||||
|
||||
fn create_mwixnet_req(
|
||||
@@ -2574,8 +2527,7 @@ where
|
||||
lock_output: bool,
|
||||
server_keys: Vec<String>,
|
||||
) -> Result<SwapReq, Error> {
|
||||
let commit =
|
||||
Commitment::from_vec(from_hex(&commitment).map_err(|e| Error::CommitDeser(e))?);
|
||||
let commit = Commitment::from_vec(from_hex(&commitment).map_err(Error::CommitDeser)?);
|
||||
|
||||
let secp_inst = static_secp_instance();
|
||||
let secp = secp_inst.lock();
|
||||
@@ -2584,7 +2536,7 @@ where
|
||||
for key in server_keys {
|
||||
keys.push(SecretKey::from_slice(
|
||||
&secp,
|
||||
&grin_util::from_hex(&key).map_err(|e| Error::ServerKeyDeser(e))?,
|
||||
&grin_util::from_hex(&key).map_err(Error::ServerKeyDeser)?,
|
||||
)?)
|
||||
}
|
||||
|
||||
@@ -2597,7 +2549,7 @@ where
|
||||
|
||||
Owner::create_mwixnet_req(
|
||||
self,
|
||||
(&token.keychain_mask).as_ref(),
|
||||
token.keychain_mask.as_ref(),
|
||||
&req_params,
|
||||
&commit,
|
||||
lock_output,
|
||||
@@ -2730,19 +2682,14 @@ pub fn run_doctest_owner(
|
||||
let _ = test_framework::award_blocks_to_wallet(
|
||||
&chain,
|
||||
wallet1.clone(),
|
||||
(&mask1).as_ref(),
|
||||
1 as usize,
|
||||
mask1.as_ref(),
|
||||
1_usize,
|
||||
false,
|
||||
);
|
||||
//update local outputs after each block, so transaction IDs stay consistent
|
||||
let (wallet_refreshed, _) = api_impl::owner::retrieve_summary_info(
|
||||
wallet1.clone(),
|
||||
(&mask1).as_ref(),
|
||||
&None,
|
||||
true,
|
||||
1,
|
||||
)
|
||||
.unwrap();
|
||||
let (wallet_refreshed, _) =
|
||||
api_impl::owner::retrieve_summary_info(wallet1.clone(), mask1.as_ref(), &None, true, 1)
|
||||
.unwrap();
|
||||
assert!(wallet_refreshed);
|
||||
}
|
||||
|
||||
@@ -2769,25 +2716,24 @@ pub fn run_doctest_owner(
|
||||
payment_proof_recipient_address: proof_address,
|
||||
..Default::default()
|
||||
};
|
||||
let mut slate = api_impl::owner::init_send_tx(w, (&mask1).as_ref(), args, true).unwrap();
|
||||
let mut slate = api_impl::owner::init_send_tx(w, mask1.as_ref(), args, true).unwrap();
|
||||
println!("INITIAL SLATE");
|
||||
println!("{}", serde_json::to_string_pretty(&slate).unwrap());
|
||||
{
|
||||
let mut w_lock = wallet2.lock();
|
||||
let w2 = w_lock.lc_provider().unwrap().wallet_inst().unwrap();
|
||||
slate =
|
||||
api_impl::foreign::receive_tx(w2, (&mask2).as_ref(), &slate, None, true).unwrap();
|
||||
slate = api_impl::foreign::receive_tx(w2, mask2.as_ref(), &slate, None, true).unwrap();
|
||||
w2.close().unwrap();
|
||||
}
|
||||
// Spit out slate for input to finalize_tx
|
||||
if lock_tx {
|
||||
println!("LOCKING TX");
|
||||
api_impl::owner::tx_lock_outputs(w, (&mask1).as_ref(), &slate).unwrap();
|
||||
api_impl::owner::tx_lock_outputs(w, mask1.as_ref(), &slate).unwrap();
|
||||
}
|
||||
println!("RECEIPIENT SLATE");
|
||||
println!("{}", serde_json::to_string_pretty(&slate).unwrap());
|
||||
if finalize_tx {
|
||||
slate = api_impl::owner::finalize_tx(w, (&mask1).as_ref(), &slate).unwrap();
|
||||
slate = api_impl::owner::finalize_tx(w, mask1.as_ref(), &slate).unwrap();
|
||||
error!("FINALIZED TX SLATE");
|
||||
println!("{}", serde_json::to_string_pretty(&slate).unwrap());
|
||||
}
|
||||
@@ -2803,8 +2749,8 @@ pub fn run_doctest_owner(
|
||||
let _ = test_framework::award_blocks_to_wallet(
|
||||
&chain,
|
||||
wallet1.clone(),
|
||||
(&mask1).as_ref(),
|
||||
3 as usize,
|
||||
mask1.as_ref(),
|
||||
3_usize,
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
+13
-11
@@ -18,7 +18,6 @@ use crate::util::secp::key::{PublicKey, SecretKey};
|
||||
use crate::util::{from_hex, ToHex};
|
||||
use ed25519_dalek::SigningKey as DalekSecretKey;
|
||||
|
||||
use base64;
|
||||
use rand::{thread_rng, Rng};
|
||||
use ring::aead;
|
||||
use serde_json::{self, Value};
|
||||
@@ -90,8 +89,10 @@ impl EncryptedBody {
|
||||
aad,
|
||||
&mut to_encrypt,
|
||||
);
|
||||
if let Err(_) = res {
|
||||
return Err(Error::APIEncryption("EncryptedBody: encryption failed".to_owned()).into());
|
||||
if res.is_err() {
|
||||
return Err(Error::APIEncryption(
|
||||
"EncryptedBody: encryption failed".to_owned(),
|
||||
));
|
||||
}
|
||||
|
||||
Ok(EncryptedBody {
|
||||
@@ -129,8 +130,7 @@ impl EncryptedBody {
|
||||
if nonce.len() < 12 {
|
||||
return Err(Error::APIEncryption(
|
||||
"EncryptedBody Dec: Invalid Nonce length".to_string(),
|
||||
)
|
||||
.into());
|
||||
));
|
||||
}
|
||||
let mut n = [0u8; 12];
|
||||
n.copy_from_slice(&nonce[0..12]);
|
||||
@@ -139,8 +139,10 @@ impl EncryptedBody {
|
||||
let aad = aead::Aad::from(&[]);
|
||||
let res =
|
||||
opening_key.open_in_place(aead::Nonce::assume_unique_for_key(n), aad, &mut to_decrypt);
|
||||
if let Err(_) = res {
|
||||
return Err(Error::APIEncryption("EncryptedBody: decryption failed".to_owned()).into());
|
||||
if res.is_err() {
|
||||
return Err(Error::APIEncryption(
|
||||
"EncryptedBody: decryption failed".to_owned(),
|
||||
));
|
||||
}
|
||||
for _ in 0..aead::AES_256_GCM.tag_len() {
|
||||
to_decrypt.pop();
|
||||
@@ -148,8 +150,8 @@ impl EncryptedBody {
|
||||
|
||||
let decrypted = String::from_utf8(to_decrypt)
|
||||
.map_err(|_| Error::APIEncryption("EncryptedBody Dec: Invalid UTF-8".to_string()))?;
|
||||
Ok(serde_json::from_str(&decrypted)
|
||||
.map_err(|_| Error::APIEncryption("EncryptedBody Dec: Invalid JSON".to_string()))?)
|
||||
serde_json::from_str(&decrypted)
|
||||
.map_err(|_| Error::APIEncryption("EncryptedBody Dec: Invalid JSON".to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,9 +277,9 @@ impl EncryptionErrorResponse {
|
||||
pub fn new(id: u64, code: i32, message: &str) -> Self {
|
||||
EncryptionErrorResponse {
|
||||
jsonrpc: "2.0".to_owned(),
|
||||
id: id,
|
||||
id,
|
||||
error: EncryptionError {
|
||||
code: code,
|
||||
code,
|
||||
message: message.to_owned(),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
//use grin_wallet_api::foreign_rpc_client;
|
||||
use grin_wallet_api::run_doctest_foreign;
|
||||
//use grin_wallet_libwallet::VersionedSlate;
|
||||
use serde_json;
|
||||
use serde_json::Value;
|
||||
use tempfile::tempdir;
|
||||
//use grin_wallet_libwallet::slate_versions::v1::SlateV1;
|
||||
|
||||
+14
-15
@@ -170,13 +170,13 @@ pub fn get_wallet_path(
|
||||
// A - Detect grin-wallet.toml in working dir
|
||||
let mut config_path = env::current_dir()?;
|
||||
config_path.push(WALLET_CONFIG_FILE_NAME);
|
||||
if create_path == false && config_path.exists() {
|
||||
if !create_path && config_path.exists() {
|
||||
config_path.pop();
|
||||
println!("Detected 'grin-wallet.toml' in working dir - opening associated wallet");
|
||||
return Ok(config_path);
|
||||
};
|
||||
// B - Select home directory
|
||||
let mut wallet_path = dirs::home_dir().unwrap_or_else(|| PathBuf::new());
|
||||
let mut wallet_path = dirs::home_dir().unwrap_or_default();
|
||||
wallet_path.push(GRIN_HOME);
|
||||
wallet_path.push(chain_type.shortname());
|
||||
// Create if the default path doesn't exist
|
||||
@@ -199,7 +199,7 @@ pub fn get_node_path(
|
||||
data_path: Option<PathBuf>,
|
||||
chain_type: &global::ChainTypes,
|
||||
) -> Result<PathBuf, ConfigError> {
|
||||
let node_path = match data_path {
|
||||
match data_path {
|
||||
// 1) A If top dir provided and api_secret exist, return top dir
|
||||
Some(path) => {
|
||||
let mut node_path = path;
|
||||
@@ -211,7 +211,7 @@ pub fn get_node_path(
|
||||
Ok(node_path)
|
||||
// 1) B If top dir exists, but no api_secret, return home dir
|
||||
} else {
|
||||
let mut node_path = dirs::home_dir().unwrap_or_else(|| PathBuf::new());
|
||||
let mut node_path = dirs::home_dir().unwrap_or_default();
|
||||
node_path.push(GRIN_HOME);
|
||||
node_path.push(chain_type.shortname());
|
||||
Ok(node_path)
|
||||
@@ -219,13 +219,12 @@ pub fn get_node_path(
|
||||
}
|
||||
// 2) If there is no top_dir provided, always return home dir
|
||||
None => {
|
||||
let mut node_path = dirs::home_dir().unwrap_or_else(|| PathBuf::new());
|
||||
let mut node_path = dirs::home_dir().unwrap_or_default();
|
||||
node_path.push(GRIN_HOME);
|
||||
node_path.push(chain_type.shortname());
|
||||
Ok(node_path)
|
||||
}
|
||||
};
|
||||
node_path
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if config in current working dir
|
||||
@@ -297,10 +296,10 @@ fn check_api_secret_file(
|
||||
|
||||
/// Initial wallet setup does the following
|
||||
/// 1) Load wallet config if run without 'init' 2) create wallet if run with 'init'
|
||||
/// Try in this order:
|
||||
/// a) current dir as template,
|
||||
/// b) in top path, or
|
||||
/// c) .grin home
|
||||
/// Try in this order:
|
||||
/// a) current dir as template,
|
||||
/// b) in top path, or
|
||||
/// c) .grin home
|
||||
/// - load default config values
|
||||
/// - update the wallet and node dir to the correct paths
|
||||
/// - if grin-wallet.toml exists, but the wallet data dir does not, load config and continue wallet generation
|
||||
@@ -371,7 +370,7 @@ pub fn initial_setup_wallet(
|
||||
// Return config if not run with init
|
||||
true => {
|
||||
// If run with init and seed do not yet exists, continue, else throw error
|
||||
if data_dir.exists() && create_path == true {
|
||||
if data_dir.exists() && create_path {
|
||||
let msg = format!(
|
||||
"{} already exists in the target directory ({}). Please remove it first",
|
||||
config_path.to_str().unwrap(),
|
||||
@@ -409,9 +408,9 @@ impl Default for GlobalWalletConfigMembers {
|
||||
impl GlobalWalletConfig {
|
||||
/// Same as GlobalConfig::default() but further tweaks parameters to
|
||||
/// apply defaults for each chain type
|
||||
pub fn for_chain(chain_type: &global::ChainTypes, file_path: &PathBuf) -> GlobalWalletConfig {
|
||||
pub fn for_chain(chain_type: &global::ChainTypes, file_path: &Path) -> GlobalWalletConfig {
|
||||
let mut defaults_conf = GlobalWalletConfig {
|
||||
config_file_path: file_path.clone(),
|
||||
config_file_path: file_path.to_path_buf(),
|
||||
members: GlobalWalletConfigMembers::default(),
|
||||
};
|
||||
let defaults = &mut defaults_conf.members.wallet;
|
||||
@@ -484,7 +483,7 @@ impl GlobalWalletConfig {
|
||||
}
|
||||
|
||||
/// Update paths
|
||||
pub fn update_paths(&mut self, wallet_home: &PathBuf, node_home: &Path) {
|
||||
pub fn update_paths(&mut self, wallet_home: &Path, node_home: &Path) {
|
||||
let mut data_file_dir = wallet_home.to_path_buf();
|
||||
let mut node_secret_path = node_home.to_path_buf();
|
||||
let mut secret_path = wallet_home.to_path_buf();
|
||||
|
||||
+3
-25
@@ -112,7 +112,7 @@ impl WalletConfig {
|
||||
/// Accept fee base
|
||||
pub fn accept_fee_base(&self) -> u64 {
|
||||
self.accept_fee_base
|
||||
.unwrap_or_else(|| WalletConfig::default_accept_fee_base())
|
||||
.unwrap_or_else(WalletConfig::default_accept_fee_base)
|
||||
}
|
||||
|
||||
/// Node API requests timeout.
|
||||
@@ -249,7 +249,7 @@ impl TorConfig {
|
||||
}
|
||||
|
||||
/// Tor Bridge Config
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
|
||||
pub struct TorBridgeConfig {
|
||||
/// Path to bridge binary to use with integrated Tor library
|
||||
pub bridge_bin_path: Option<String>,
|
||||
@@ -259,16 +259,6 @@ pub struct TorBridgeConfig {
|
||||
pub client_option: Option<String>,
|
||||
}
|
||||
|
||||
impl Default for TorBridgeConfig {
|
||||
fn default() -> TorBridgeConfig {
|
||||
TorBridgeConfig {
|
||||
bridge_bin_path: None,
|
||||
bridge_line: None,
|
||||
client_option: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for TorBridgeConfig {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
@@ -276,7 +266,7 @@ impl fmt::Display for TorBridgeConfig {
|
||||
}
|
||||
|
||||
/// Tor Proxy configuration (useful for protocols such as shadowsocks)
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
|
||||
pub struct TorProxyConfig {
|
||||
/// socks4 |socks5 | http(s)
|
||||
pub transport: Option<String>,
|
||||
@@ -290,18 +280,6 @@ pub struct TorProxyConfig {
|
||||
pub allowed_port: Option<Vec<u16>>,
|
||||
}
|
||||
|
||||
impl Default for TorProxyConfig {
|
||||
fn default() -> TorProxyConfig {
|
||||
TorProxyConfig {
|
||||
transport: None,
|
||||
address: None,
|
||||
username: None,
|
||||
password: None,
|
||||
allowed_port: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for TorProxyConfig {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
|
||||
+25
-34
@@ -120,7 +120,7 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn rewind_hash<'a, L, C, K>(
|
||||
pub fn rewind_hash<L, C, K>(
|
||||
owner_api: &mut Owner<L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
) -> Result<(), Error>
|
||||
@@ -159,7 +159,7 @@ where
|
||||
let tip_height = owner_api.node_height(None)?.height;
|
||||
let start_height = match args.backwards_from_tip {
|
||||
Some(b) => tip_height.saturating_sub(b),
|
||||
None => args.start_height.unwrap_or_else(|| 1),
|
||||
None => args.start_height.unwrap_or(1),
|
||||
};
|
||||
warn!(
|
||||
"Starting view wallet output scan from height {} ...",
|
||||
@@ -184,6 +184,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn listen<L, C, K>(
|
||||
owner_api: &mut Owner<L, C, K>,
|
||||
keychain_mask: Arc<Mutex<Option<SecretKey>>>,
|
||||
@@ -222,7 +223,7 @@ where
|
||||
if let Ok(t) = api_thread {
|
||||
if !cli_mode {
|
||||
let r = t.join();
|
||||
if let Err(_) = r {
|
||||
if r.is_err() {
|
||||
error!("Error starting listener");
|
||||
return Err(Error::ListenerError);
|
||||
}
|
||||
@@ -424,11 +425,11 @@ where
|
||||
init_args = max_retry_args(init_args, amount, max_inputs);
|
||||
owner_api.init_send_tx(keychain_mask, init_args)?
|
||||
} else {
|
||||
return Err(grin_wallet_libwallet::Error::from(e));
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(grin_wallet_libwallet::Error::from(e));
|
||||
return Err(e);
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -459,20 +460,15 @@ where
|
||||
};
|
||||
let init_send_tx = |init_args: InitTxArgs| -> Result<Slate, libwallet::Error> {
|
||||
let result = owner_api.init_send_tx(keychain_mask, init_args.clone());
|
||||
let slate = match result {
|
||||
Ok(s) => {
|
||||
info!(
|
||||
"Tx created: {} grin to {} (strategy '{}')",
|
||||
core::amount_to_hr_string(init_args.amount, false),
|
||||
dest.as_ref()
|
||||
.map(ToString::to_string)
|
||||
.unwrap_or_else(|| "no destination".to_string()),
|
||||
args.selection_strategy,
|
||||
);
|
||||
s
|
||||
}
|
||||
Err(e) => return Err(e),
|
||||
};
|
||||
let slate = result?;
|
||||
info!(
|
||||
"Tx created: {} grin to {} (strategy '{}')",
|
||||
core::amount_to_hr_string(init_args.amount, false),
|
||||
dest.as_ref()
|
||||
.map(ToString::to_string)
|
||||
.unwrap_or_else(|| "no destination".to_string()),
|
||||
args.selection_strategy,
|
||||
);
|
||||
Ok(slate)
|
||||
};
|
||||
slate = match init_send_tx(init_args.clone()) {
|
||||
@@ -561,6 +557,7 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn output_slatepack<L, C, K>(
|
||||
owner_api: &mut Owner<L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
@@ -582,7 +579,7 @@ where
|
||||
Some(a) => vec![a],
|
||||
None => vec![],
|
||||
};
|
||||
let message = owner_api.create_slatepack_message(keychain_mask, &slate, Some(0), recipients)?;
|
||||
let message = owner_api.create_slatepack_message(keychain_mask, slate, Some(0), recipients)?;
|
||||
let tld = owner_api.get_top_level_directory()?;
|
||||
|
||||
// create a directory to which files will be output
|
||||
@@ -594,12 +591,12 @@ where
|
||||
};
|
||||
|
||||
if lock {
|
||||
owner_api.tx_lock_outputs(keychain_mask, &slate)?;
|
||||
owner_api.tx_lock_outputs(keychain_mask, slate)?;
|
||||
}
|
||||
|
||||
println!("{}", out_file_name);
|
||||
let mut output = File::create(out_file_name.clone())?;
|
||||
output.write_all(&message.as_bytes())?;
|
||||
output.write_all(message.as_bytes())?;
|
||||
output.sync_all()?;
|
||||
|
||||
println!();
|
||||
@@ -695,7 +692,7 @@ where
|
||||
}
|
||||
None => {
|
||||
let msg = "No slate provided via file or direct input";
|
||||
return Err(Error::GenericError(msg.into()).into());
|
||||
return Err(Error::GenericError(msg.into()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -752,10 +749,7 @@ where
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let km = match keychain_mask.as_ref() {
|
||||
None => None,
|
||||
Some(&m) => Some(m.to_owned()),
|
||||
};
|
||||
let km = keychain_mask.as_ref().map(|&m| m.to_owned());
|
||||
|
||||
if let Some(b) = args.bridge {
|
||||
tor_config.bridge.bridge_line = Some(b);
|
||||
@@ -830,7 +824,7 @@ pub fn read_slatepack(args: ReceiveArgs) -> Result<Slatepack, Error> {
|
||||
None => match args.input_slatepack_message {
|
||||
Some(message) => packer.deser_slatepack(message.as_bytes(), false)?,
|
||||
None => {
|
||||
return Err(Error::ArgumentError("Invalid Slatepack Input".into()).into());
|
||||
return Err(Error::ArgumentError("Invalid Slatepack Input".into()));
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -942,10 +936,7 @@ where
|
||||
let is_invoice = slate.state == SlateState::Invoice2;
|
||||
|
||||
if is_invoice {
|
||||
let km = match keychain_mask.as_ref() {
|
||||
None => None,
|
||||
Some(&m) => Some(m.to_owned()),
|
||||
};
|
||||
let km = keychain_mask.as_ref().map(|&m| m.to_owned());
|
||||
controller::foreign_single_use(
|
||||
owner_api.wallet_inst.clone(),
|
||||
owner_api.config_path(),
|
||||
@@ -1258,7 +1249,7 @@ where
|
||||
// Note advanced query args not currently supported by command line client
|
||||
let (validated, txs) =
|
||||
owner_api.retrieve_txs(keychain_mask, true, args.id, args.tx_slate_id, None)?;
|
||||
let include_status = !args.id.is_some() && !args.tx_slate_id.is_some();
|
||||
let include_status = args.id.is_none() && args.tx_slate_id.is_none();
|
||||
// If view count is specified, restrict the TX list to `txs.len() - count`
|
||||
let first_tx = args
|
||||
.count
|
||||
@@ -1455,7 +1446,7 @@ where
|
||||
let tip_height = owner_api.node_height(keychain_mask)?.height;
|
||||
let start_height = match args.backwards_from_tip {
|
||||
Some(b) => tip_height.saturating_sub(b),
|
||||
None => args.start_height.unwrap_or_else(|| 1),
|
||||
None => args.start_height.unwrap_or(1),
|
||||
};
|
||||
warn!("Starting output scan from height {} ...", start_height);
|
||||
let result = owner_api.scan(keychain_mask, Some(start_height), args.delete_unconfirmed);
|
||||
|
||||
@@ -21,8 +21,8 @@ use crate::impls::tor::process as tor_process;
|
||||
use crate::impls::tor::{bridge as tor_bridge, proxy as tor_proxy};
|
||||
use crate::keychain::Keychain;
|
||||
use crate::libwallet::{
|
||||
address, Error, NodeClient, NodeVersionInfo, Slate, SlatepackAddress, WalletInst,
|
||||
WalletLCProvider, GRIN_BLOCK_HEADER_VERSION,
|
||||
address, Error, NodeClient, NodeVersionInfo, Slate, SlatepackAddress, WalletLCProvider,
|
||||
GRIN_BLOCK_HEADER_VERSION,
|
||||
};
|
||||
use crate::util::secp::key::SecretKey;
|
||||
use crate::util::{from_hex, static_secp_instance, to_base64, Mutex};
|
||||
@@ -102,29 +102,23 @@ fn init_tor_listener(
|
||||
let mut hm_tor_bridge: HashMap<String, String> = HashMap::new();
|
||||
if tor_config.bridge.bridge_line.is_some() {
|
||||
let bridge_config = tor_bridge::TorBridge::try_from(tor_config.bridge)
|
||||
.map_err(|e| Error::TorConfig(format!("{}", e).into()))?;
|
||||
.map_err(|e| Error::TorConfig(format!("{}", e)))?;
|
||||
hm_tor_bridge = bridge_config
|
||||
.to_hashmap()
|
||||
.map_err(|e| Error::TorConfig(format!("{}", e).into()))?;
|
||||
.map_err(|e| Error::TorConfig(format!("{}", e)))?;
|
||||
}
|
||||
|
||||
let mut hm_tor_poxy: HashMap<String, String> = HashMap::new();
|
||||
if tor_config.proxy.transport.is_some() || tor_config.proxy.allowed_port.is_some() {
|
||||
let proxy_config = tor_proxy::TorProxy::try_from(tor_config.proxy)
|
||||
.map_err(|e| Error::TorConfig(format!("{}", e).into()))?;
|
||||
.map_err(|e| Error::TorConfig(format!("{}", e)))?;
|
||||
hm_tor_poxy = proxy_config
|
||||
.to_hashmap()
|
||||
.map_err(|e| Error::TorConfig(format!("{}", e).into()))?;
|
||||
.map_err(|e| Error::TorConfig(format!("{}", e)))?;
|
||||
}
|
||||
|
||||
tor_config::output_tor_listener_config(
|
||||
&tor_dir,
|
||||
addr,
|
||||
&vec![sec_key],
|
||||
hm_tor_bridge,
|
||||
hm_tor_poxy,
|
||||
)
|
||||
.map_err(|e| Error::TorConfig(format!("{:?}", e).into()))?;
|
||||
tor_config::output_tor_listener_config(&tor_dir, addr, &[sec_key], hm_tor_bridge, hm_tor_poxy)
|
||||
.map_err(|e| Error::TorConfig(format!("{:?}", e)))?;
|
||||
// Start TOR process
|
||||
process
|
||||
.torrc_path(&format!("{}/torrc", tor_dir))
|
||||
@@ -139,7 +133,7 @@ fn init_tor_listener(
|
||||
/// 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<'a, L, F, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet: grin_wallet_libwallet::WalletHandle<'a, L, C, K>,
|
||||
config_path: PathBuf,
|
||||
keychain_mask: Option<SecretKey>,
|
||||
f: F,
|
||||
@@ -179,9 +173,9 @@ where
|
||||
K: Keychain + 'static,
|
||||
{
|
||||
let mut router = Router::new();
|
||||
if api_secret.is_some() {
|
||||
if let Some(api_secret) = api_secret {
|
||||
let api_basic_auth =
|
||||
"Basic ".to_string() + &to_base64(&("grin:".to_string() + &api_secret.unwrap()));
|
||||
"Basic ".to_string() + &to_base64(&("grin:".to_string() + &api_secret));
|
||||
let basic_auth_middleware = Arc::new(BasicAuthMiddleware::new(
|
||||
api_basic_auth,
|
||||
&GRIN_OWNER_BASIC_REALM,
|
||||
@@ -231,8 +225,9 @@ where
|
||||
|
||||
/// Listener version, providing same API but listening for requests on a
|
||||
/// port and wrapping the calls
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn foreign_listener<L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K> + 'static>>>,
|
||||
wallet: grin_wallet_libwallet::WalletHandle<'static, L, C, K>,
|
||||
config_path: PathBuf,
|
||||
bridge: Option<String>,
|
||||
use_tor: Option<bool>,
|
||||
@@ -258,7 +253,7 @@ where
|
||||
let mut w_lock = wallet.lock();
|
||||
let lc = w_lock.lc_provider()?;
|
||||
let w_inst = lc.wallet_inst()?;
|
||||
let k = w_inst.keychain((&mask).as_ref())?;
|
||||
let k = w_inst.keychain(mask.as_ref())?;
|
||||
let parent_key_id = w_inst.parent_key_id();
|
||||
let sec_key = address::address_from_derivation_path(&k, &parent_key_id, 0)
|
||||
.map_err(|e| Error::TorConfig(format!("{:?}", e)))?;
|
||||
@@ -400,7 +395,7 @@ where
|
||||
K: Keychain + 'static,
|
||||
{
|
||||
/// Wallet instance
|
||||
pub wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K> + 'static>>>,
|
||||
pub wallet: grin_wallet_libwallet::WalletHandle<'static, L, C, K>,
|
||||
|
||||
/// Handle to Owner API
|
||||
owner_api: Arc<Owner<L, C, K>>,
|
||||
@@ -462,7 +457,7 @@ impl OwnerV3Helpers {
|
||||
val: &serde_json::Value,
|
||||
new_key: Option<SecretKey>,
|
||||
) {
|
||||
if let Some(_) = val["result"]["Ok"].as_str() {
|
||||
if val["result"]["Ok"].as_str().is_some() {
|
||||
let mut share_key_ref = key.lock();
|
||||
*share_key_ref = new_key;
|
||||
}
|
||||
@@ -503,7 +498,7 @@ impl OwnerV3Helpers {
|
||||
.as_json_value()
|
||||
})?;
|
||||
let id = enc_req.id.clone();
|
||||
let res = enc_req.decrypt(&shared_key).map_err(|e| {
|
||||
let res = enc_req.decrypt(shared_key).map_err(|e| {
|
||||
EncryptionErrorResponse::new(1, -32002, &format!("Decryption error: {}", e))
|
||||
.as_json_value()
|
||||
})?;
|
||||
@@ -518,7 +513,7 @@ impl OwnerV3Helpers {
|
||||
) -> Result<serde_json::Value, serde_json::Value> {
|
||||
let share_key_ref = key.lock();
|
||||
let shared_key = share_key_ref.as_ref().unwrap();
|
||||
let enc_res = EncryptedResponse::from_json(id, res, &shared_key).map_err(|e| {
|
||||
let enc_res = EncryptedResponse::from_json(id, res, shared_key).map_err(|e| {
|
||||
EncryptionErrorResponse::new(1, -32003, &format!("EncryptionError: {}", e))
|
||||
.as_json_value()
|
||||
})?;
|
||||
@@ -576,10 +571,7 @@ impl OwnerV3Helpers {
|
||||
retval
|
||||
} else if val["result"]["Err"].is_string() {
|
||||
let parsed = serde_json::from_value::<String>(val["result"]["Err"].clone());
|
||||
match parsed {
|
||||
Ok(p) => Some(p),
|
||||
Err(_) => None,
|
||||
}
|
||||
parsed.ok()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@@ -737,7 +729,7 @@ where
|
||||
K: Keychain + 'static,
|
||||
{
|
||||
/// Wallet instance.
|
||||
pub wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K> + 'static>>>,
|
||||
pub wallet: grin_wallet_libwallet::WalletHandle<'static, L, C, K>,
|
||||
/// Wallet configuration path.
|
||||
pub config_path: ConfigPath,
|
||||
/// Keychain mask
|
||||
@@ -754,7 +746,7 @@ where
|
||||
{
|
||||
/// Create a new foreign API handler for GET methods
|
||||
pub fn new(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K> + 'static>>>,
|
||||
wallet: grin_wallet_libwallet::WalletHandle<'static, L, C, K>,
|
||||
config_path: ConfigPath,
|
||||
keychain_mask: Arc<Mutex<Option<SecretKey>>>,
|
||||
test_mode: bool,
|
||||
@@ -785,7 +777,7 @@ where
|
||||
async fn handle_post_request(
|
||||
req: Request<Incoming>,
|
||||
mask: Option<SecretKey>,
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K> + 'static>>>,
|
||||
wallet: grin_wallet_libwallet::WalletHandle<'static, L, C, K>,
|
||||
config_path: ConfigPath,
|
||||
test_mode: bool,
|
||||
) -> Result<Response<ApiBody>, Error> {
|
||||
|
||||
+11
-21
@@ -62,7 +62,7 @@ pub fn outputs(
|
||||
]);
|
||||
|
||||
for m in outputs {
|
||||
let commit = format!("{}", m.commit.as_ref().to_hex());
|
||||
let commit = m.commit.as_ref().to_hex();
|
||||
let index = match m.output.mmr_index {
|
||||
None => "None".to_owned(),
|
||||
Some(t) => t.to_string(),
|
||||
@@ -78,7 +78,7 @@ pub fn outputs(
|
||||
};
|
||||
|
||||
let num_confirmations = format!("{}", m.output.num_confirmations(cur_height));
|
||||
let value = format!("{}", amount_to_hr_string(m.output.value, false));
|
||||
let value = amount_to_hr_string(m.output.value, false);
|
||||
let tx = match m.output.tx_log_entry {
|
||||
None => "".to_owned(),
|
||||
Some(t) => t.to_string(),
|
||||
@@ -196,7 +196,7 @@ pub fn txs(
|
||||
let amount_debited_str = amount_to_hr_string(t.amount_debited, true);
|
||||
let amount_credited_str = amount_to_hr_string(t.amount_credited, true);
|
||||
let fee = match t.fee {
|
||||
Some(f) => format!("{}", amount_to_hr_string(f.fee(), true)),
|
||||
Some(f) => amount_to_hr_string(f.fee(), true),
|
||||
None => "None".to_owned(),
|
||||
};
|
||||
let net_diff = if t.amount_credited >= t.amount_debited {
|
||||
@@ -297,24 +297,17 @@ pub fn txs(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn view_wallet_balance(w: ViewWallet, cur_height: u64, dark_background_color_scheme: bool) {
|
||||
pub fn view_wallet_balance(w: ViewWallet, cur_height: u64, _dark_background_color_scheme: bool) {
|
||||
println!(
|
||||
"\n____ View Wallet Summary Info - Block Height: {} ____\n Rewind Hash - {}\n",
|
||||
cur_height, w.rewind_hash
|
||||
);
|
||||
let mut table = table!();
|
||||
|
||||
if dark_background_color_scheme {
|
||||
table.add_row(row![
|
||||
bFG->"Total Balance",
|
||||
FG->amount_to_hr_string(w.total_balance, false)
|
||||
]);
|
||||
} else {
|
||||
table.add_row(row![
|
||||
bFG->"Total Balance",
|
||||
FG->amount_to_hr_string(w.total_balance, false)
|
||||
]);
|
||||
};
|
||||
table.add_row(row![
|
||||
bFG->"Total Balance",
|
||||
FG->amount_to_hr_string(w.total_balance, false)
|
||||
]);
|
||||
table.set_format(*prettytable::format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR);
|
||||
table.printstd();
|
||||
println!();
|
||||
@@ -351,13 +344,13 @@ pub fn view_wallet_output(
|
||||
]);
|
||||
|
||||
for m in view_wallet.output_result {
|
||||
let commit = format!("{}", m.commit);
|
||||
let commit = m.commit.as_str();
|
||||
let index = m.mmr_index;
|
||||
let height = format!("{}", m.height);
|
||||
let lock_height = format!("{}", m.lock_height);
|
||||
let is_coinbase = format!("{}", m.is_coinbase);
|
||||
let num_confirmations = format!("{}", m.num_confirmations(cur_height));
|
||||
let value = format!("{}", amount_to_hr_string(m.value, false));
|
||||
let value = amount_to_hr_string(m.value, false);
|
||||
|
||||
if dark_background_color_scheme {
|
||||
table.add_row(row![
|
||||
@@ -612,10 +605,7 @@ pub fn payment_proof(tx: &TxLogEntry) -> Result<(), Error> {
|
||||
let amount = if tx.amount_credited >= tx.amount_debited {
|
||||
amount_to_hr_string(tx.amount_credited - tx.amount_debited, true)
|
||||
} else {
|
||||
format!(
|
||||
"{}",
|
||||
amount_to_hr_string(tx.amount_debited - tx.amount_credited - fee, true)
|
||||
)
|
||||
amount_to_hr_string(tx.amount_debited - tx.amount_credited - fee, true)
|
||||
};
|
||||
|
||||
let sender_signature = match pp.sender_signature {
|
||||
|
||||
@@ -52,7 +52,7 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
api1
|
||||
);
|
||||
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
let mask1 = mask1_i.as_ref();
|
||||
|
||||
create_wallet_and_add!(
|
||||
client2,
|
||||
@@ -66,7 +66,7 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
api2
|
||||
);
|
||||
|
||||
let mask2 = (&mask2_i).as_ref();
|
||||
let mask2 = mask2_i.as_ref();
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
thread::spawn(move || {
|
||||
|
||||
@@ -50,7 +50,7 @@ fn build_chain(test_dir: &'static str, block_height: usize) -> Result<(), libwal
|
||||
true,
|
||||
api1
|
||||
);
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
let mask1 = mask1_i.as_ref();
|
||||
debug!("Mask1: {:?}", mask1);
|
||||
create_wallet_and_add!(
|
||||
client2,
|
||||
@@ -63,7 +63,7 @@ fn build_chain(test_dir: &'static str, block_height: usize) -> Result<(), libwal
|
||||
false,
|
||||
api2
|
||||
);
|
||||
let mask2 = (&mask2_i).as_ref();
|
||||
let mask2 = mask2_i.as_ref();
|
||||
debug!("Mask2: {:?}", mask2);
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
|
||||
@@ -55,7 +55,7 @@ fn build_output_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error
|
||||
api1
|
||||
);
|
||||
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
let mask1 = mask1_i.as_ref();
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
thread::spawn(move || {
|
||||
|
||||
+18
-18
@@ -68,7 +68,7 @@ fn scan_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
false,
|
||||
api1
|
||||
);
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
let mask1 = mask1_i.as_ref();
|
||||
create_wallet_and_add!(
|
||||
client2,
|
||||
wallet2,
|
||||
@@ -80,7 +80,7 @@ fn scan_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
false,
|
||||
api2
|
||||
);
|
||||
let mask2 = (&mask2_i).as_ref();
|
||||
let mask2 = mask2_i.as_ref();
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
thread::spawn(move || {
|
||||
@@ -223,7 +223,7 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
false,
|
||||
_m_api
|
||||
);
|
||||
let miner_mask = (&miner_mask_i).as_ref();
|
||||
let miner_mask = miner_mask_i.as_ref();
|
||||
|
||||
// non-mining recipient wallets
|
||||
create_wallet_and_add!(
|
||||
@@ -237,7 +237,7 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
false,
|
||||
api1
|
||||
);
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
let mask1 = mask1_i.as_ref();
|
||||
create_wallet_and_add!(
|
||||
client2,
|
||||
wallet2,
|
||||
@@ -249,7 +249,7 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
false,
|
||||
_api2
|
||||
);
|
||||
let mask2 = (&mask2_i).as_ref();
|
||||
let mask2 = mask2_i.as_ref();
|
||||
// we'll restore into here
|
||||
create_wallet_and_add!(
|
||||
client3,
|
||||
@@ -262,7 +262,7 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
false,
|
||||
api3
|
||||
);
|
||||
let mask3 = (&mask3_i).as_ref();
|
||||
let mask3 = mask3_i.as_ref();
|
||||
// also restore into here
|
||||
create_wallet_and_add!(
|
||||
client4,
|
||||
@@ -275,7 +275,7 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
false,
|
||||
api4
|
||||
);
|
||||
let mask4 = (&mask4_i).as_ref();
|
||||
let mask4 = mask4_i.as_ref();
|
||||
// Simulate a recover from seed without restore into here
|
||||
create_wallet_and_add!(
|
||||
client5,
|
||||
@@ -289,7 +289,7 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
api5
|
||||
);
|
||||
//simulate a recover from seed without restore into here
|
||||
let mask5 = (&mask5_i).as_ref();
|
||||
let mask5 = mask5_i.as_ref();
|
||||
create_wallet_and_add!(
|
||||
client6,
|
||||
wallet6,
|
||||
@@ -301,7 +301,7 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
false,
|
||||
api6
|
||||
);
|
||||
let mask6 = (&mask6_i).as_ref();
|
||||
let mask6 = mask6_i.as_ref();
|
||||
|
||||
create_wallet_and_add!(
|
||||
client7,
|
||||
@@ -314,7 +314,7 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
false,
|
||||
api7
|
||||
);
|
||||
let mask7 = (&mask7_i).as_ref();
|
||||
let mask7 = mask7_i.as_ref();
|
||||
create_wallet_and_add!(
|
||||
client8,
|
||||
wallet8,
|
||||
@@ -326,7 +326,7 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
false,
|
||||
api8
|
||||
);
|
||||
let mask8 = (&mask8_i).as_ref();
|
||||
let mask8 = mask8_i.as_ref();
|
||||
create_wallet_and_add!(
|
||||
client9,
|
||||
wallet9,
|
||||
@@ -338,7 +338,7 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
false,
|
||||
api9
|
||||
);
|
||||
let mask9 = (&mask9_i).as_ref();
|
||||
let mask9 = mask9_i.as_ref();
|
||||
create_wallet_and_add!(
|
||||
client10,
|
||||
wallet10,
|
||||
@@ -350,7 +350,7 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
false,
|
||||
api10
|
||||
);
|
||||
let mask10 = (&mask10_i).as_ref();
|
||||
let mask10 = mask10_i.as_ref();
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
thread::spawn(move || {
|
||||
@@ -380,7 +380,7 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
miner_mask,
|
||||
m_client.clone(),
|
||||
"wallet1",
|
||||
base_amount * 1
|
||||
base_amount
|
||||
)?;
|
||||
send_to_dest!(
|
||||
miner.clone(),
|
||||
@@ -579,7 +579,7 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
miner_mask,
|
||||
m_client.clone(),
|
||||
"wallet7",
|
||||
base_amount * 1
|
||||
base_amount
|
||||
)?;
|
||||
send_to_dest!(
|
||||
miner.clone(),
|
||||
@@ -710,7 +710,7 @@ fn output_scanning_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
false,
|
||||
_api1
|
||||
);
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
let mask1 = mask1_i.as_ref();
|
||||
thread::spawn(move || {
|
||||
if let Err(e) = wallet_proxy.run() {
|
||||
error!("Wallet Proxy error: {}", e);
|
||||
@@ -795,7 +795,7 @@ fn multi_batch_scan_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
false,
|
||||
api1
|
||||
);
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
let mask1 = mask1_i.as_ref();
|
||||
|
||||
thread::spawn(move || {
|
||||
if let Err(e) = wallet_proxy.run() {
|
||||
@@ -886,7 +886,7 @@ fn restore_corrupted_outputs_across_batches_impl(
|
||||
false,
|
||||
api1
|
||||
);
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
let mask1 = mask1_i.as_ref();
|
||||
|
||||
thread::spawn(move || {
|
||||
if let Err(e) = wallet_proxy.run() {
|
||||
|
||||
@@ -109,6 +109,7 @@ pub fn create_wallet_proxy(
|
||||
WalletProxy::new(test_dir)
|
||||
}
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub fn create_local_wallet(
|
||||
test_dir: &str,
|
||||
name: &str,
|
||||
@@ -116,17 +117,11 @@ pub fn create_local_wallet(
|
||||
client: LocalWalletClient,
|
||||
create_mask: bool,
|
||||
) -> (
|
||||
Arc<
|
||||
Mutex<
|
||||
Box<
|
||||
dyn WalletInst<
|
||||
'static,
|
||||
DefaultLCProvider<LocalWalletClient, ExtKeychain>,
|
||||
LocalWalletClient,
|
||||
ExtKeychain,
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
grin_wallet_libwallet::WalletHandle<
|
||||
'static,
|
||||
DefaultLCProvider<LocalWalletClient, ExtKeychain>,
|
||||
LocalWalletClient,
|
||||
ExtKeychain,
|
||||
>,
|
||||
Option<SecretKey>,
|
||||
Owner<DefaultLCProvider<LocalWalletClient, ExtKeychain>, LocalWalletClient, ExtKeychain>,
|
||||
@@ -178,17 +173,11 @@ pub fn open_local_wallet(
|
||||
client: LocalWalletClient,
|
||||
create_mask: bool,
|
||||
) -> (
|
||||
Arc<
|
||||
Mutex<
|
||||
Box<
|
||||
dyn WalletInst<
|
||||
'static,
|
||||
DefaultLCProvider<LocalWalletClient, ExtKeychain>,
|
||||
LocalWalletClient,
|
||||
ExtKeychain,
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
grin_wallet_libwallet::WalletHandle<
|
||||
'static,
|
||||
DefaultLCProvider<LocalWalletClient, ExtKeychain>,
|
||||
LocalWalletClient,
|
||||
ExtKeychain,
|
||||
>,
|
||||
Option<SecretKey>,
|
||||
) {
|
||||
|
||||
@@ -53,7 +53,7 @@ fn file_exchange_test_impl(test_dir: &'static str, use_bin: bool) -> Result<(),
|
||||
false,
|
||||
api1
|
||||
);
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
let mask1 = mask1_i.as_ref();
|
||||
create_wallet_and_add!(
|
||||
client2,
|
||||
wallet2,
|
||||
@@ -65,7 +65,7 @@ fn file_exchange_test_impl(test_dir: &'static str, use_bin: bool) -> Result<(),
|
||||
false,
|
||||
api2
|
||||
);
|
||||
let mask2 = (&mask2_i).as_ref();
|
||||
let mask2 = mask2_i.as_ref();
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
thread::spawn(move || {
|
||||
|
||||
@@ -49,7 +49,7 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
true,
|
||||
api1
|
||||
);
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
let mask1 = mask1_i.as_ref();
|
||||
create_wallet_and_add!(
|
||||
client2,
|
||||
wallet2,
|
||||
@@ -61,7 +61,7 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
true,
|
||||
api2
|
||||
);
|
||||
let mask2 = (&mask2_i).as_ref();
|
||||
let mask2 = mask2_i.as_ref();
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
thread::spawn(move || {
|
||||
|
||||
@@ -49,7 +49,7 @@ fn late_lock_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
false,
|
||||
api1
|
||||
);
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
let mask1 = mask1_i.as_ref();
|
||||
create_wallet_and_add!(
|
||||
client2,
|
||||
wallet2,
|
||||
@@ -61,7 +61,7 @@ fn late_lock_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
false,
|
||||
api2
|
||||
);
|
||||
let mask2 = (&mask2_i).as_ref();
|
||||
let mask2 = mask2_i.as_ref();
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
thread::spawn(move || {
|
||||
|
||||
@@ -53,7 +53,7 @@ fn mwixnet_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
true,
|
||||
api1
|
||||
);
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
let mask1 = mask1_i.as_ref();
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
thread::spawn(move || {
|
||||
@@ -135,11 +135,11 @@ fn mwixnet_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
let server_pubkey_str_2 = "0c9414341f2140ed34a5a12a6479bf5a6404820d001ab81d9d3e8cc38f049b4e";
|
||||
let server_pubkey_str_3 = "b58ece97d60e71bb7e53218400b0d67bfe6a3cb7d3b4a67a44f8fb7c525cbca5";
|
||||
let server_key_1 =
|
||||
SecretKey::from_slice(&secp, &grin_util::from_hex(&server_pubkey_str_1).unwrap())?;
|
||||
SecretKey::from_slice(&secp, &grin_util::from_hex(server_pubkey_str_1).unwrap())?;
|
||||
let server_key_2 =
|
||||
SecretKey::from_slice(&secp, &grin_util::from_hex(&server_pubkey_str_2).unwrap())?;
|
||||
SecretKey::from_slice(&secp, &grin_util::from_hex(server_pubkey_str_2).unwrap())?;
|
||||
let server_key_3 =
|
||||
SecretKey::from_slice(&secp, &grin_util::from_hex(&server_pubkey_str_3).unwrap())?;
|
||||
SecretKey::from_slice(&secp, &grin_util::from_hex(server_pubkey_str_3).unwrap())?;
|
||||
let params = MixnetReqCreationParams {
|
||||
server_keys: vec![server_key_1, server_key_2, server_key_3],
|
||||
fee_per_hop: 50_000_000,
|
||||
|
||||
@@ -48,7 +48,7 @@ fn no_change_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
api1
|
||||
);
|
||||
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
let mask1 = mask1_i.as_ref();
|
||||
|
||||
create_wallet_and_add!(
|
||||
client2,
|
||||
@@ -62,7 +62,7 @@ fn no_change_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
api2
|
||||
);
|
||||
|
||||
let mask2 = (&mask2_i).as_ref();
|
||||
let mask2 = mask2_i.as_ref();
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
thread::spawn(move || {
|
||||
|
||||
@@ -48,7 +48,7 @@ fn payment_proofs_test_impl(test_dir: &'static str) -> Result<(), libwallet::Err
|
||||
api1
|
||||
);
|
||||
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
let mask1 = mask1_i.as_ref();
|
||||
|
||||
create_wallet_and_add!(
|
||||
client2,
|
||||
@@ -62,7 +62,7 @@ fn payment_proofs_test_impl(test_dir: &'static str) -> Result<(), libwallet::Err
|
||||
api2
|
||||
);
|
||||
|
||||
let mask2 = (&mask2_i).as_ref();
|
||||
let mask2 = mask2_i.as_ref();
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
thread::spawn(move || {
|
||||
|
||||
@@ -52,7 +52,7 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
false,
|
||||
api1
|
||||
);
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
let mask1 = mask1_i.as_ref();
|
||||
create_wallet_and_add!(
|
||||
client2,
|
||||
wallet2,
|
||||
@@ -64,7 +64,7 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
false,
|
||||
api2
|
||||
);
|
||||
let mask2 = (&mask2_i).as_ref();
|
||||
let mask2 = mask2_i.as_ref();
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
thread::spawn(move || {
|
||||
|
||||
+13
-15
@@ -23,32 +23,25 @@ use grin_core::core::Transaction;
|
||||
use grin_core::global;
|
||||
use grin_keychain::ExtKeychain;
|
||||
use grin_util::secp::key::SecretKey;
|
||||
use grin_util::Mutex;
|
||||
use grin_wallet_api::Owner;
|
||||
use grin_wallet_impls::test_framework::*;
|
||||
use grin_wallet_impls::{DefaultLCProvider, PathToSlate, SlatePutter};
|
||||
use grin_wallet_libwallet as libwallet;
|
||||
use grin_wallet_libwallet::api_impl::types::InitTxArgs;
|
||||
use grin_wallet_libwallet::WalletInst;
|
||||
use log::error;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
type Wallet = Arc<
|
||||
Mutex<
|
||||
Box<
|
||||
dyn WalletInst<
|
||||
'static,
|
||||
DefaultLCProvider<LocalWalletClient, ExtKeychain>,
|
||||
LocalWalletClient,
|
||||
ExtKeychain,
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
type Wallet = grin_wallet_libwallet::WalletHandle<
|
||||
'static,
|
||||
DefaultLCProvider<LocalWalletClient, ExtKeychain>,
|
||||
LocalWalletClient,
|
||||
ExtKeychain,
|
||||
>;
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
fn revert(
|
||||
test_dir: &'static str,
|
||||
) -> Result<
|
||||
@@ -189,8 +182,13 @@ fn revert(
|
||||
|
||||
// Build 2 blocks at same height: 1 with the tx, 1 without
|
||||
let head = chain.head_header().unwrap();
|
||||
let block_with =
|
||||
create_block_for_wallet(&chain, head.clone(), &[tx.clone()], wallet1.clone(), mask1)?;
|
||||
let block_with = create_block_for_wallet(
|
||||
&chain,
|
||||
head.clone(),
|
||||
std::slice::from_ref(&tx),
|
||||
wallet1.clone(),
|
||||
mask1,
|
||||
)?;
|
||||
let block_without = create_block_for_wallet(&chain, head, &[], wallet1.clone(), mask1)?;
|
||||
|
||||
// Add block with tx to the chain
|
||||
|
||||
@@ -51,7 +51,7 @@ fn self_send_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
true,
|
||||
api1
|
||||
);
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
let mask1 = mask1_i.as_ref();
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
thread::spawn(move || {
|
||||
|
||||
@@ -57,7 +57,7 @@ fn output_slatepack(
|
||||
if armored {
|
||||
file = format!("{}.armored", file);
|
||||
}
|
||||
PathToSlatepack::new(file.into(), &packer, armored).put_tx(&slate, use_bin)
|
||||
PathToSlatepack::new(file.into(), &packer, armored).put_tx(slate, use_bin)
|
||||
}
|
||||
|
||||
fn slate_from_packed(
|
||||
@@ -103,7 +103,7 @@ fn slatepack_exchange_test_impl(
|
||||
false,
|
||||
api1
|
||||
);
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
let mask1 = mask1_i.as_ref();
|
||||
create_wallet_and_add!(
|
||||
client2,
|
||||
wallet2,
|
||||
@@ -115,7 +115,7 @@ fn slatepack_exchange_test_impl(
|
||||
false,
|
||||
api2
|
||||
);
|
||||
let mask2 = (&mask2_i).as_ref();
|
||||
let mask2 = mask2_i.as_ref();
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
thread::spawn(move || {
|
||||
@@ -217,7 +217,7 @@ fn slatepack_exchange_test_impl(
|
||||
}
|
||||
|
||||
let (mut slatepack, mut slate) =
|
||||
slate_from_packed(&send_file, use_armored, (&dec_key_2).as_ref())?;
|
||||
slate_from_packed(&send_file, use_armored, dec_key_2.as_ref())?;
|
||||
|
||||
// wallet 2 receives file, completes, sends file back
|
||||
wallet::controller::foreign_single_use(
|
||||
@@ -243,7 +243,7 @@ fn slatepack_exchange_test_impl(
|
||||
)?;
|
||||
|
||||
// wallet 1 finalizes and posts
|
||||
let (_, mut slate) = slate_from_packed(&receive_file, use_armored, (&dec_key_1).as_ref())?;
|
||||
let (_, mut slate) = slate_from_packed(&receive_file, use_armored, dec_key_1.as_ref())?;
|
||||
slate = api1.finalize_tx(mask1, &slate)?;
|
||||
// Output final file for reference
|
||||
output_slatepack(&slate, &final_file, use_armored, use_bin, None, vec![])?;
|
||||
@@ -303,7 +303,7 @@ fn slatepack_exchange_test_impl(
|
||||
selection_strategy_is_use_all: true,
|
||||
..Default::default()
|
||||
};
|
||||
let res = slate_from_packed(&send_file, use_armored, (&dec_key_1).as_ref())?;
|
||||
let res = slate_from_packed(&send_file, use_armored, dec_key_1.as_ref())?;
|
||||
slatepack = res.0;
|
||||
slate = res.1;
|
||||
slate = api1.process_invoice_tx(mask1, &slate, args)?;
|
||||
@@ -325,7 +325,7 @@ fn slatepack_exchange_test_impl(
|
||||
mask2_i.clone(),
|
||||
|api| {
|
||||
// Wallet 2 receives the invoice transaction
|
||||
let res = slate_from_packed(&receive_file, use_armored, (&dec_key_2).as_ref())?;
|
||||
let res = slate_from_packed(&receive_file, use_armored, dec_key_2.as_ref())?;
|
||||
slate = res.1;
|
||||
slate = api.finalize_tx(&slate, false)?;
|
||||
output_slatepack(&slate, &final_file, use_armored, use_bin, None, vec![])?;
|
||||
@@ -378,7 +378,7 @@ fn slatepack_exchange_test_impl(
|
||||
PathBuf::from(test_dir),
|
||||
mask2_i.clone(),
|
||||
|api| {
|
||||
let res = slate_from_packed(&send_file, use_armored, (&dec_key_2).as_ref())?;
|
||||
let res = slate_from_packed(&send_file, use_armored, dec_key_2.as_ref())?;
|
||||
let slatepack = res.0;
|
||||
slate = res.1;
|
||||
slate = api.receive_tx(&slate, None, None)?;
|
||||
@@ -398,7 +398,7 @@ fn slatepack_exchange_test_impl(
|
||||
)?;
|
||||
|
||||
// wallet 1 finalizes and posts
|
||||
let res = slate_from_packed(&receive_file, use_armored, (&dec_key_1).as_ref())?;
|
||||
let res = slate_from_packed(&receive_file, use_armored, dec_key_1.as_ref())?;
|
||||
slate = res.1;
|
||||
slate = api1.finalize_tx(mask1, &slate)?;
|
||||
// Output final file for reference
|
||||
@@ -432,7 +432,7 @@ fn slatepack_api_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
false,
|
||||
api1
|
||||
);
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
let mask1 = mask1_i.as_ref();
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
thread::spawn(move || {
|
||||
@@ -494,7 +494,7 @@ fn slatepack_address_validation(test_dir: &'static str) -> Result<(), libwallet:
|
||||
false,
|
||||
api1
|
||||
);
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
let mask1 = mask1_i.as_ref();
|
||||
|
||||
create_wallet_and_add!(
|
||||
client2,
|
||||
@@ -507,7 +507,7 @@ fn slatepack_address_validation(test_dir: &'static str) -> Result<(), libwallet:
|
||||
false,
|
||||
api2
|
||||
);
|
||||
let mask2 = (&mask2_i).as_ref();
|
||||
let mask2 = mask2_i.as_ref();
|
||||
|
||||
let proxy_thread = thread::spawn(move || {
|
||||
if let Err(e) = wallet_proxy.run() {
|
||||
|
||||
@@ -56,7 +56,7 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
true,
|
||||
api1
|
||||
);
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
let mask1 = mask1_i.as_ref();
|
||||
println!("Mask1: {:?}", mask1);
|
||||
create_wallet_and_add!(
|
||||
client2,
|
||||
@@ -69,7 +69,7 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
false,
|
||||
api2
|
||||
);
|
||||
let mask2 = (&mask2_i).as_ref();
|
||||
let mask2 = mask2_i.as_ref();
|
||||
println!("Mask2: {:?}", mask2);
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
@@ -530,7 +530,7 @@ fn tx_rollback(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
false,
|
||||
api1
|
||||
);
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
let mask1 = mask1_i.as_ref();
|
||||
create_wallet_and_add!(
|
||||
client2,
|
||||
wallet2,
|
||||
@@ -542,7 +542,7 @@ fn tx_rollback(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
false,
|
||||
api2
|
||||
);
|
||||
let mask2 = (&mask2_i).as_ref();
|
||||
let mask2 = mask2_i.as_ref();
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
thread::spawn(move || {
|
||||
@@ -592,10 +592,10 @@ fn tx_rollback(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
api1.retrieve_outputs(mask1, true, false, Some(tx.unwrap().id))?;
|
||||
for m in output_mappings.clone() {
|
||||
if m.output.status == OutputStatus::Locked {
|
||||
locked_count = locked_count + 1;
|
||||
locked_count += 1;
|
||||
}
|
||||
if m.output.status == OutputStatus::Unconfirmed {
|
||||
unconfirmed_count = unconfirmed_count + 1;
|
||||
unconfirmed_count += 1;
|
||||
}
|
||||
}
|
||||
assert_eq!(output_mappings.len(), 3);
|
||||
@@ -614,7 +614,7 @@ fn tx_rollback(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
let (_, outputs) = api2.retrieve_outputs(mask2, true, false, Some(tx.unwrap().id))?;
|
||||
for m in outputs.clone() {
|
||||
if m.output.status == OutputStatus::Unconfirmed {
|
||||
unconfirmed_count = unconfirmed_count + 1;
|
||||
unconfirmed_count += 1;
|
||||
}
|
||||
}
|
||||
assert_eq!(outputs.len(), 1);
|
||||
@@ -697,7 +697,7 @@ fn big_amount_error(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
true,
|
||||
api1
|
||||
);
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
let mask1 = mask1_i.as_ref();
|
||||
println!("Mask1: {:?}", mask1);
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
@@ -762,16 +762,15 @@ fn big_amount_error(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
|
||||
match result {
|
||||
Ok(_) => {}
|
||||
Err(e) => match e {
|
||||
libwallet::Error::BigAmountError(a, fee, num_inputs) => {
|
||||
Err(e) => {
|
||||
if let libwallet::Error::BigAmountError(a, fee, num_inputs) = e {
|
||||
let (_, e_a, e_fee, e_num_inputs) =
|
||||
api1.estimate_max_sendable(mask1, true, min_confirmations)?;
|
||||
assert_eq!(e_a, a - fee);
|
||||
assert_eq!(e_fee, fee);
|
||||
assert_eq!(e_num_inputs, num_inputs);
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// let logging finish
|
||||
|
||||
@@ -48,7 +48,7 @@ fn ttl_cutoff_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
api1
|
||||
);
|
||||
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
let mask1 = mask1_i.as_ref();
|
||||
|
||||
create_wallet_and_add!(
|
||||
client2,
|
||||
@@ -62,7 +62,7 @@ fn ttl_cutoff_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
api2
|
||||
);
|
||||
|
||||
let mask2 = (&mask2_i).as_ref();
|
||||
let mask2 = mask2_i.as_ref();
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
thread::spawn(move || {
|
||||
|
||||
@@ -50,10 +50,11 @@ fn test_wallet_tx_filtering(
|
||||
assert!(!txs.is_empty());
|
||||
let before_first_tx =
|
||||
txs.iter().map(|tx| tx.creation_ts).min().unwrap() - Duration::from_secs(1);
|
||||
let mut tx_query_args = RetrieveTxQueryArgs::default();
|
||||
|
||||
// Max creation time before all test transactions
|
||||
tx_query_args.max_creation_timestamp = Some(before_first_tx);
|
||||
let mut tx_query_args = RetrieveTxQueryArgs {
|
||||
max_creation_timestamp: Some(before_first_tx),
|
||||
..Default::default()
|
||||
};
|
||||
assert!(query(tx_query_args.clone())?.is_empty());
|
||||
|
||||
// Min confirmation time should not affect creation time
|
||||
@@ -61,8 +62,10 @@ fn test_wallet_tx_filtering(
|
||||
tx_query_args.min_confirmed_timestamp = Some(before_first_tx);
|
||||
assert_eq!(query(tx_query_args)?.len(), txs.len());
|
||||
|
||||
let mut tx_query_args = RetrieveTxQueryArgs::default();
|
||||
tx_query_args.min_id = Some(5);
|
||||
let tx_query_args = RetrieveTxQueryArgs {
|
||||
min_id: Some(5),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
// Min ID
|
||||
let tx_results = api
|
||||
@@ -72,9 +75,11 @@ fn test_wallet_tx_filtering(
|
||||
assert_eq!(tx_results[tx_results.len() - 1].id, 33);
|
||||
|
||||
// Max ID
|
||||
let mut tx_query_args = RetrieveTxQueryArgs::default();
|
||||
tx_query_args.min_id = Some(5);
|
||||
tx_query_args.max_id = Some(20);
|
||||
let tx_query_args = RetrieveTxQueryArgs {
|
||||
min_id: Some(5),
|
||||
max_id: Some(20),
|
||||
..Default::default()
|
||||
};
|
||||
let tx_results = api
|
||||
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
|
||||
.1;
|
||||
@@ -82,109 +87,133 @@ fn test_wallet_tx_filtering(
|
||||
assert_eq!(tx_results[tx_results.len() - 1].id, 20);
|
||||
|
||||
// Exclude 1 canceled
|
||||
let mut tx_query_args = RetrieveTxQueryArgs::default();
|
||||
tx_query_args.exclude_cancelled = Some(true);
|
||||
tx_query_args.min_id = Some(5);
|
||||
tx_query_args.max_id = Some(50);
|
||||
let tx_query_args = RetrieveTxQueryArgs {
|
||||
exclude_cancelled: Some(true),
|
||||
min_id: Some(5),
|
||||
max_id: Some(50),
|
||||
..Default::default()
|
||||
};
|
||||
let tx_results = api
|
||||
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
|
||||
.1;
|
||||
assert_eq!(tx_results.len(), 28);
|
||||
|
||||
// Exclude 1 canceled, show confirmed only
|
||||
let mut tx_query_args = RetrieveTxQueryArgs::default();
|
||||
tx_query_args.exclude_cancelled = Some(true);
|
||||
tx_query_args.include_confirmed_only = Some(true);
|
||||
tx_query_args.min_id = Some(5);
|
||||
tx_query_args.max_id = Some(50);
|
||||
let tx_query_args = RetrieveTxQueryArgs {
|
||||
exclude_cancelled: Some(true),
|
||||
include_confirmed_only: Some(true),
|
||||
min_id: Some(5),
|
||||
max_id: Some(50),
|
||||
..Default::default()
|
||||
};
|
||||
let tx_results = api
|
||||
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
|
||||
.1;
|
||||
assert_eq!(tx_results.len(), 14);
|
||||
|
||||
// show outstanding only (including canceled)
|
||||
let mut tx_query_args = RetrieveTxQueryArgs::default();
|
||||
tx_query_args.exclude_cancelled = Some(false);
|
||||
tx_query_args.include_outstanding_only = Some(true);
|
||||
tx_query_args.min_id = Some(5);
|
||||
tx_query_args.max_id = Some(50);
|
||||
let tx_query_args = RetrieveTxQueryArgs {
|
||||
exclude_cancelled: Some(false),
|
||||
include_outstanding_only: Some(true),
|
||||
min_id: Some(5),
|
||||
max_id: Some(50),
|
||||
..Default::default()
|
||||
};
|
||||
let tx_results = api
|
||||
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
|
||||
.1;
|
||||
assert_eq!(tx_results.len(), 15);
|
||||
|
||||
// outstanding only and confirmed only should give empty set
|
||||
let mut tx_query_args = RetrieveTxQueryArgs::default();
|
||||
tx_query_args.exclude_cancelled = Some(false);
|
||||
tx_query_args.include_outstanding_only = Some(true);
|
||||
tx_query_args.include_confirmed_only = Some(true);
|
||||
tx_query_args.min_id = Some(5);
|
||||
tx_query_args.max_id = Some(50);
|
||||
let tx_query_args = RetrieveTxQueryArgs {
|
||||
exclude_cancelled: Some(false),
|
||||
include_outstanding_only: Some(true),
|
||||
include_confirmed_only: Some(true),
|
||||
min_id: Some(5),
|
||||
max_id: Some(50),
|
||||
..Default::default()
|
||||
};
|
||||
let tx_results = api
|
||||
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
|
||||
.1;
|
||||
assert_eq!(tx_results.len(), 0);
|
||||
|
||||
// include sent only
|
||||
let mut tx_query_args = RetrieveTxQueryArgs::default();
|
||||
tx_query_args.include_sent_only = Some(true);
|
||||
let tx_query_args = RetrieveTxQueryArgs {
|
||||
include_sent_only: Some(true),
|
||||
..Default::default()
|
||||
};
|
||||
let tx_results = api
|
||||
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
|
||||
.1;
|
||||
assert_eq!(tx_results.len(), 15);
|
||||
|
||||
// include received only (none in this set)
|
||||
let mut tx_query_args = RetrieveTxQueryArgs::default();
|
||||
tx_query_args.include_received_only = Some(true);
|
||||
let tx_query_args = RetrieveTxQueryArgs {
|
||||
include_received_only: Some(true),
|
||||
..Default::default()
|
||||
};
|
||||
let tx_results = api
|
||||
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
|
||||
.1;
|
||||
assert_eq!(tx_results.len(), 0);
|
||||
|
||||
// include reverted only (none in this set)
|
||||
let mut tx_query_args = RetrieveTxQueryArgs::default();
|
||||
tx_query_args.include_reverted_only = Some(true);
|
||||
let tx_query_args = RetrieveTxQueryArgs {
|
||||
include_reverted_only: Some(true),
|
||||
..Default::default()
|
||||
};
|
||||
let tx_results = api
|
||||
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
|
||||
.1;
|
||||
assert_eq!(tx_results.len(), 0);
|
||||
|
||||
// include coinbase only
|
||||
let mut tx_query_args = RetrieveTxQueryArgs::default();
|
||||
tx_query_args.include_coinbase_only = Some(true);
|
||||
let tx_query_args = RetrieveTxQueryArgs {
|
||||
include_coinbase_only: Some(true),
|
||||
..Default::default()
|
||||
};
|
||||
let tx_results = api
|
||||
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
|
||||
.1;
|
||||
assert_eq!(tx_results.len(), 19);
|
||||
|
||||
// Amounts
|
||||
let mut tx_query_args = RetrieveTxQueryArgs::default();
|
||||
tx_query_args.min_amount = Some(60_000_000_000 - 59_963_300_000);
|
||||
let tx_query_args = RetrieveTxQueryArgs {
|
||||
min_amount: Some(60_000_000_000 - 59_963_300_000),
|
||||
..Default::default()
|
||||
};
|
||||
let tx_results = api
|
||||
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
|
||||
.1;
|
||||
assert_eq!(tx_results.len(), 27);
|
||||
|
||||
// amount, should see as above with coinbases excluded
|
||||
let mut tx_query_args = RetrieveTxQueryArgs::default();
|
||||
tx_query_args.min_amount = Some(60_000_000_000 - 59_963_300_000);
|
||||
tx_query_args.max_amount = Some(60_000_000_000 - 1);
|
||||
let tx_query_args = RetrieveTxQueryArgs {
|
||||
min_amount: Some(60_000_000_000 - 59_963_300_000),
|
||||
max_amount: Some(60_000_000_000 - 1),
|
||||
..Default::default()
|
||||
};
|
||||
let tx_results = api
|
||||
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
|
||||
.1;
|
||||
assert_eq!(tx_results.len(), 8);
|
||||
|
||||
// Amount - should only see coinbase (incoming)
|
||||
let mut tx_query_args = RetrieveTxQueryArgs::default();
|
||||
tx_query_args.min_amount = Some(60_000_000_000);
|
||||
let tx_query_args = RetrieveTxQueryArgs {
|
||||
min_amount: Some(60_000_000_000),
|
||||
..Default::default()
|
||||
};
|
||||
let tx_results = api
|
||||
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
|
||||
.1;
|
||||
assert_eq!(tx_results.len(), 19);
|
||||
|
||||
// sort order
|
||||
let mut tx_query_args = RetrieveTxQueryArgs::default();
|
||||
tx_query_args.sort_order = Some(libwallet::RetrieveTxQuerySortOrder::Desc);
|
||||
let tx_query_args = RetrieveTxQueryArgs {
|
||||
sort_order: Some(libwallet::RetrieveTxQuerySortOrder::Desc),
|
||||
..Default::default()
|
||||
};
|
||||
let tx_results = api
|
||||
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
|
||||
.1;
|
||||
@@ -193,9 +222,11 @@ fn test_wallet_tx_filtering(
|
||||
assert_eq!(tx_results[tx_results.len() - 1].id, 0);
|
||||
|
||||
// change sort field to amount desc, should have coinbases first
|
||||
let mut tx_query_args = RetrieveTxQueryArgs::default();
|
||||
tx_query_args.sort_order = Some(libwallet::RetrieveTxQuerySortOrder::Desc);
|
||||
tx_query_args.sort_field = Some(RetrieveTxQuerySortField::TotalAmount);
|
||||
let tx_query_args = RetrieveTxQueryArgs {
|
||||
sort_order: Some(libwallet::RetrieveTxQuerySortOrder::Desc),
|
||||
sort_field: Some(RetrieveTxQuerySortField::TotalAmount),
|
||||
..Default::default()
|
||||
};
|
||||
let tx_results = api
|
||||
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
|
||||
.1;
|
||||
@@ -224,7 +255,7 @@ fn build_chain_for_tx_filtering(
|
||||
true,
|
||||
api1
|
||||
);
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
let mask1 = mask1_i.as_ref();
|
||||
debug!("Mask1: {:?}", mask1);
|
||||
create_wallet_and_add!(
|
||||
client2,
|
||||
@@ -237,7 +268,7 @@ fn build_chain_for_tx_filtering(
|
||||
false,
|
||||
api2
|
||||
);
|
||||
let mask2 = (&mask2_i).as_ref();
|
||||
let mask2 = mask2_i.as_ref();
|
||||
debug!("Mask2: {:?}", mask2);
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
|
||||
@@ -49,7 +49,7 @@ fn updater_thread_test_impl(test_dir: &'static str) -> Result<(), libwallet::Err
|
||||
false,
|
||||
api1
|
||||
);
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
let mask1 = mask1_i.as_ref();
|
||||
create_wallet_and_add!(
|
||||
client2,
|
||||
wallet2,
|
||||
@@ -61,7 +61,7 @@ fn updater_thread_test_impl(test_dir: &'static str) -> Result<(), libwallet::Err
|
||||
false,
|
||||
api2
|
||||
);
|
||||
let mask2 = (&mask2_i).as_ref();
|
||||
let mask2 = mask2_i.as_ref();
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
thread::spawn(move || {
|
||||
|
||||
+1
-1
Submodule grin updated: 1425f60329...4182d34221
@@ -111,7 +111,7 @@ mod tests {
|
||||
clean_output_dir(test_dir);
|
||||
}
|
||||
|
||||
const SLATEPACK_DIR: &'static str = "target/test_output/slatepack";
|
||||
const SLATEPACK_DIR: &str = "target/test_output/slatepack";
|
||||
|
||||
#[test]
|
||||
fn pathbuf_get_file_contents() {
|
||||
|
||||
@@ -27,7 +27,7 @@ use serde_json::{json, Value};
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryFrom;
|
||||
use std::net::SocketAddr;
|
||||
use std::path::PathBuf;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -65,7 +65,7 @@ impl TorSlateSender {
|
||||
}
|
||||
|
||||
/// Launch external Tor process.
|
||||
fn launch_tor_process(config: &TorConfig, tor_dir: &PathBuf) -> Result<TorProcess, Error> {
|
||||
fn launch_tor_process(config: &TorConfig, tor_dir: &Path) -> Result<TorProcess, Error> {
|
||||
let mut tor = TorProcess::new();
|
||||
let socks_proxy_addr = SocketAddr::V4(
|
||||
config
|
||||
@@ -101,7 +101,7 @@ impl TorSlateSender {
|
||||
)
|
||||
.map_err(|e| Error::TorConfig(format!("{:?}", e)))?;
|
||||
// Start TOR process
|
||||
let mut path = tor_dir.clone();
|
||||
let mut path = tor_dir.to_path_buf();
|
||||
path.push("torrc");
|
||||
tor.torrc_path(path.to_str().unwrap())
|
||||
.working_dir(tor_dir.to_str().unwrap())
|
||||
@@ -184,8 +184,7 @@ impl TorSlateSender {
|
||||
let client = Client::with_proxy(socks_proxy_addr, "socks5h://", timeout)
|
||||
.map_err(|_| ClientError::Internal("Unable to create http client".into()))?;
|
||||
let req = client.create_post_request(url, None, &input)?;
|
||||
let res = client.send_request(req)?;
|
||||
res
|
||||
client.send_request(req)?
|
||||
} else {
|
||||
tor_post(&self.config, &input, url)
|
||||
.map_err(|e| ClientError::RequestError(format!("{:?}", e)))?
|
||||
|
||||
@@ -19,7 +19,6 @@ use lazy_static::lazy_static;
|
||||
use reqwest::header::{HeaderMap, HeaderValue, ACCEPT, AUTHORIZATION, CONTENT_TYPE, USER_AGENT};
|
||||
use reqwest::{ClientBuilder, Method, Proxy, RequestBuilder};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json;
|
||||
use std::net::SocketAddr;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
@@ -32,6 +31,7 @@ lazy_static! {
|
||||
}
|
||||
|
||||
#[derive(Clone, Eq, thiserror::Error, PartialEq, Debug)]
|
||||
#[allow(clippy::enum_variant_names)]
|
||||
pub enum Error {
|
||||
#[error("Internal error: {0}")]
|
||||
Internal(String),
|
||||
@@ -76,7 +76,7 @@ impl Client {
|
||||
|
||||
if let Some(p) = proxy {
|
||||
let (addr, scheme) = p;
|
||||
let proxy = Proxy::all(&format!("{}{}:{}", scheme, addr.ip(), addr.port()))
|
||||
let proxy = Proxy::all(format!("{}{}:{}", scheme, addr.ip(), addr.port()))
|
||||
.map_err(|e| Error::Internal(format!("Unable to create proxy: {}", e)))?;
|
||||
builder = builder.proxy(proxy);
|
||||
}
|
||||
@@ -91,7 +91,7 @@ impl Client {
|
||||
/// Helper function to easily issue a HTTP GET request against a given URL that
|
||||
/// returns a JSON object. Handles request building, JSON deserialization and
|
||||
/// response code checking.
|
||||
pub fn _get<'a, T>(&self, url: &'a str, api_secret: Option<String>) -> Result<T, Error>
|
||||
pub fn _get<T>(&self, url: &str, api_secret: Option<String>) -> Result<T, Error>
|
||||
where
|
||||
for<'de> T: Deserialize<'de>,
|
||||
{
|
||||
@@ -101,11 +101,7 @@ impl Client {
|
||||
/// Helper function to easily issue an async HTTP GET request against a given
|
||||
/// URL that returns a future. Handles request building, JSON deserialization
|
||||
/// and response code checking.
|
||||
pub async fn _get_async<'a, T>(
|
||||
&self,
|
||||
url: &'a str,
|
||||
api_secret: Option<String>,
|
||||
) -> Result<T, Error>
|
||||
pub async fn _get_async<T>(&self, url: &str, api_secret: Option<String>) -> Result<T, Error>
|
||||
where
|
||||
for<'de> T: Deserialize<'de> + Send + 'static,
|
||||
{
|
||||
|
||||
@@ -22,7 +22,7 @@ use serde_json;
|
||||
pub fn build_request<'a, 'b>(name: &'a str, params: &'b serde_json::Value) -> Request<'a, 'b> {
|
||||
Request {
|
||||
method: name,
|
||||
params: params,
|
||||
params,
|
||||
id: From::from(1),
|
||||
jsonrpc: Some("2.0"),
|
||||
}
|
||||
@@ -133,7 +133,7 @@ impl fmt::Display for Error {
|
||||
write!(f, "duplicate RPC batch response ID: {}", v)
|
||||
}
|
||||
Error::_WrongBatchResponseId(ref v) => write!(f, "wrong RPC batch response ID: {}", v),
|
||||
ref e => f.write_str(&format!("{}", e)),
|
||||
ref e => write!(f, "{:?}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -217,27 +217,27 @@ pub fn _standard_error(code: StandardError, data: Option<serde_json::Value>) ->
|
||||
StandardError::ParseError => RpcError {
|
||||
code: -32700,
|
||||
message: "Parse error".to_string(),
|
||||
data: data,
|
||||
data,
|
||||
},
|
||||
StandardError::InvalidRequest => RpcError {
|
||||
code: -32600,
|
||||
message: "Invalid Request".to_string(),
|
||||
data: data,
|
||||
data,
|
||||
},
|
||||
StandardError::MethodNotFound => RpcError {
|
||||
code: -32601,
|
||||
message: "Method not found".to_string(),
|
||||
data: data,
|
||||
data,
|
||||
},
|
||||
StandardError::InvalidParams => RpcError {
|
||||
code: -32602,
|
||||
message: "Invalid params".to_string(),
|
||||
data: data,
|
||||
data,
|
||||
},
|
||||
StandardError::InternalError => RpcError {
|
||||
code: -32603,
|
||||
message: "Internal error".to_string(),
|
||||
data: data,
|
||||
data,
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -251,13 +251,13 @@ pub fn _result_to_response(
|
||||
Ok(data) => Response {
|
||||
result: Some(data),
|
||||
error: None,
|
||||
id: id,
|
||||
id,
|
||||
jsonrpc: Some(String::from("2.0")),
|
||||
},
|
||||
Err(err) => Response {
|
||||
result: None,
|
||||
error: Some(err),
|
||||
id: id,
|
||||
id,
|
||||
jsonrpc: Some(String::from("2.0")),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -32,9 +32,7 @@ use std::path::MAIN_SEPARATOR;
|
||||
/// Helper function to format paths according to OS, avoids bugs on Linux
|
||||
pub fn fmt_path(path: String) -> String {
|
||||
let sep = &MAIN_SEPARATOR.to_string();
|
||||
let path = path.replace("/", &sep);
|
||||
let path = path.replace("\\", &sep);
|
||||
path
|
||||
path.replace("/", sep).replace("\\", sep)
|
||||
}
|
||||
|
||||
pub struct DefaultLCProvider<C, K>
|
||||
@@ -77,8 +75,8 @@ where
|
||||
let data_dir = self
|
||||
.data_dir
|
||||
.to_owned()
|
||||
.replace("/", &sep)
|
||||
.replace("\\", &sep);
|
||||
.replace("/", sep)
|
||||
.replace("\\", sep);
|
||||
Ok(data_dir)
|
||||
}
|
||||
|
||||
@@ -108,7 +106,7 @@ where
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut default_config = GlobalWalletConfig::for_chain(&chain_type, &config_file_name);
|
||||
let mut default_config = GlobalWalletConfig::for_chain(chain_type, &config_file_name);
|
||||
let config_file_version = default_config.members.config_file_version;
|
||||
let logging = match logging_config.clone() {
|
||||
Some(l) => Some(l),
|
||||
@@ -140,7 +138,7 @@ where
|
||||
absolute_path_wallet.push(self.data_dir.clone());
|
||||
|
||||
// if no config provided, update defaults
|
||||
if update == true {
|
||||
if update {
|
||||
// create top level dir if it doesn't exist
|
||||
let dd = PathBuf::from(self.data_dir.clone());
|
||||
if !dd.exists() {
|
||||
@@ -209,9 +207,9 @@ where
|
||||
let mut wallet: WalletBackend<C, K> =
|
||||
match WalletBackend::new(&data_dir_name, self.node_client.clone()) {
|
||||
Err(e) => {
|
||||
let msg = format!("Error creating wallet: {}, Data Dir: {}", e, &data_dir_name);
|
||||
let msg = format!("Error creating wallet: {}, Data Dir: {}", e, data_dir_name);
|
||||
error!("{}", msg);
|
||||
return Err(Error::Lifecycle(msg).into());
|
||||
return Err(Error::Lifecycle(msg));
|
||||
}
|
||||
Ok(d) => d,
|
||||
};
|
||||
@@ -239,7 +237,7 @@ where
|
||||
let mut wallet: WalletBackend<C, K> =
|
||||
match WalletBackend::new(&data_dir_name, self.node_client.clone()) {
|
||||
Err(e) => {
|
||||
let msg = format!("Error opening wallet: {}, Data Dir: {}", e, &data_dir_name);
|
||||
let msg = format!("Error opening wallet: {}, Data Dir: {}", e, data_dir_name);
|
||||
return Err(Error::Lifecycle(msg));
|
||||
}
|
||||
Ok(d) => d,
|
||||
@@ -271,7 +269,7 @@ where
|
||||
let mut data_dir_name = PathBuf::from(self.data_dir.clone());
|
||||
data_dir_name.push(GRIN_WALLET_DIR);
|
||||
let data_dir_name = data_dir_name.to_str().unwrap();
|
||||
let res = WalletSeed::seed_file_exists(&data_dir_name)
|
||||
let res = WalletSeed::seed_file_exists(data_dir_name)
|
||||
.map_err(|_| Error::CallbackImpl("Error checking for wallet existence"))?;
|
||||
Ok(res)
|
||||
}
|
||||
@@ -322,7 +320,7 @@ where
|
||||
data_dir_name.push(GRIN_WALLET_DIR);
|
||||
let data_dir_name = data_dir_name.to_str().unwrap();
|
||||
// Get seed for later check
|
||||
let orig_wallet_seed = WalletSeed::from_file(&data_dir_name, old)
|
||||
let orig_wallet_seed = WalletSeed::from_file(data_dir_name, old)
|
||||
.map_err(|_| Error::Lifecycle("Error opening wallet seed file".into()))?;
|
||||
let orig_mnemonic = orig_wallet_seed
|
||||
.to_mnemonic()
|
||||
@@ -348,7 +346,7 @@ where
|
||||
);
|
||||
info!("Wallet seed file created");
|
||||
|
||||
let new_wallet_seed = WalletSeed::from_file(&data_dir_name, new)
|
||||
let new_wallet_seed = WalletSeed::from_file(data_dir_name, new)
|
||||
.map_err(|_| Error::Lifecycle("Error opening wallet seed file".into()))?;
|
||||
|
||||
if orig_wallet_seed != new_wallet_seed {
|
||||
@@ -461,7 +459,7 @@ mod tests {
|
||||
.unwrap();
|
||||
let enc_seed_json = serde_json::to_string_pretty(&enc_seed).unwrap();
|
||||
let mut file = File::create(seed_file_path).unwrap();
|
||||
file.write_all(&enc_seed_json.as_bytes()).unwrap();
|
||||
file.write_all(enc_seed_json.as_bytes()).unwrap();
|
||||
|
||||
let error = match provider.get_mnemonic(None, password.clone()) {
|
||||
Ok(_) => panic!("expected missing recovery phrase error"),
|
||||
|
||||
+10
-10
@@ -15,7 +15,6 @@
|
||||
use crate::blake2;
|
||||
use core::num::NonZeroU32;
|
||||
use rand::{thread_rng, Rng};
|
||||
use serde_json;
|
||||
use std::fs::{self, File};
|
||||
use std::io::{Read, Write};
|
||||
use std::path::Path;
|
||||
@@ -55,8 +54,8 @@ impl WalletSeed {
|
||||
}
|
||||
|
||||
pub fn _from_hex(hex: &str) -> Result<WalletSeed, Error> {
|
||||
let bytes = util::from_hex(&hex.to_string())
|
||||
.map_err(|_| Error::GenericError("Invalid hex".to_owned()))?;
|
||||
let bytes =
|
||||
util::from_hex(hex).map_err(|_| Error::GenericError("Invalid hex".to_owned()))?;
|
||||
Ok(WalletSeed::from_bytes(&bytes))
|
||||
}
|
||||
|
||||
@@ -136,7 +135,9 @@ impl WalletSeed {
|
||||
}
|
||||
path.push(backup_seed_file_name.clone());
|
||||
if fs::rename(seed_file_name, backup_seed_file_name.as_str()).is_err() {
|
||||
return Err(Error::GenericError("Can't rename wallet seed file".to_owned()).into());
|
||||
return Err(Error::GenericError(
|
||||
"Can't rename wallet seed file".to_owned(),
|
||||
));
|
||||
}
|
||||
warn!("{} backed up as {}", seed_file_name, backup_seed_file_name);
|
||||
Ok(backup_seed_file_name)
|
||||
@@ -163,14 +164,13 @@ impl WalletSeed {
|
||||
data_file_dir.to_owned(),
|
||||
"To create a new wallet from a recovery phrase, use 'grin-wallet init -r'"
|
||||
.to_owned(),
|
||||
)
|
||||
.into());
|
||||
));
|
||||
}
|
||||
let seed = WalletSeed::from_mnemonic(word_list)?;
|
||||
let enc_seed = EncryptedWalletSeed::from_seed(&seed, password)?;
|
||||
let enc_seed_json = serde_json::to_string_pretty(&enc_seed).map_err(|_| Error::Format)?;
|
||||
let mut file = File::create(seed_file_path).map_err(|_| Error::IO)?;
|
||||
file.write_all(&enc_seed_json.as_bytes())
|
||||
file.write_all(enc_seed_json.as_bytes())
|
||||
.map_err(|_| Error::IO)?;
|
||||
warn!("Seed created from word list");
|
||||
Ok(())
|
||||
@@ -209,7 +209,7 @@ impl WalletSeed {
|
||||
let enc_seed = EncryptedWalletSeed::from_seed(&seed, password)?;
|
||||
let enc_seed_json = serde_json::to_string_pretty(&enc_seed).map_err(|_| Error::Format)?;
|
||||
let mut file = File::create(seed_file_path).map_err(|_| Error::IO)?;
|
||||
file.write_all(&enc_seed_json.as_bytes())
|
||||
file.write_all(enc_seed_json.as_bytes())
|
||||
.map_err(|_| Error::IO)?;
|
||||
Ok(seed)
|
||||
}
|
||||
@@ -307,7 +307,7 @@ impl EncryptedWalletSeed {
|
||||
aad,
|
||||
&mut enc_bytes,
|
||||
);
|
||||
if let Err(_) = res {
|
||||
if res.is_err() {
|
||||
return Err(Error::Encryption);
|
||||
}
|
||||
|
||||
@@ -352,7 +352,7 @@ impl EncryptedWalletSeed {
|
||||
aad,
|
||||
&mut encrypted_seed,
|
||||
);
|
||||
if let Err(_) = res {
|
||||
if res.is_err() {
|
||||
return Err(Error::Encryption);
|
||||
}
|
||||
for _ in 0..aead::AES_256_GCM.tag_len() {
|
||||
|
||||
@@ -213,7 +213,7 @@ impl NodeClient for HTTPNodeClient {
|
||||
// build vec of commits for inclusion in query
|
||||
let query_params: Vec<String> = wallet_outputs
|
||||
.iter()
|
||||
.map(|commit| format!("{}", commit.as_ref().to_hex()))
|
||||
.map(|commit| commit.as_ref().to_hex())
|
||||
.collect();
|
||||
|
||||
// going to leave this here even though we're moving
|
||||
@@ -276,10 +276,9 @@ impl NodeClient for HTTPNodeClient {
|
||||
};
|
||||
|
||||
let rt = RUNTIME.clone();
|
||||
let res: Result<Vec<_>, _> =
|
||||
std::thread::spawn(move || rt.block_on(async move { task.await }))
|
||||
.join()
|
||||
.unwrap();
|
||||
let res: Result<Vec<_>, _> = std::thread::spawn(move || rt.block_on(task))
|
||||
.join()
|
||||
.unwrap();
|
||||
|
||||
let results: Vec<OutputPrintable> = match res {
|
||||
Ok(resps) => {
|
||||
@@ -338,7 +337,7 @@ impl NodeClient for HTTPNodeClient {
|
||||
let params = json!([start_index, end_index, max_outputs, Some(true)]);
|
||||
let res = self.send_json_request::<OutputListing>("get_unspent_outputs", ¶ms)?;
|
||||
// We asked for unspent outputs via the api but defensively filter out spent outputs just in case.
|
||||
for out in res.outputs.into_iter().filter(|out| out.spent == false) {
|
||||
for out in res.outputs.into_iter().filter(|out| !out.spent) {
|
||||
let is_coinbase = match out.output_type {
|
||||
api::OutputType::Coinbase => true,
|
||||
api::OutputType::Transaction => false,
|
||||
|
||||
@@ -20,12 +20,9 @@ use crate::core::core::{Output, Transaction, TxKernel};
|
||||
use crate::core::{consensus, global, pow};
|
||||
use crate::libwallet;
|
||||
use crate::libwallet::api_impl::{foreign, owner};
|
||||
use crate::libwallet::{
|
||||
BlockFees, InitTxArgs, NodeClient, WalletInfo, WalletInst, WalletLCProvider,
|
||||
};
|
||||
use crate::libwallet::{BlockFees, InitTxArgs, NodeClient, WalletInfo, WalletLCProvider};
|
||||
use crate::util::secp::key::SecretKey;
|
||||
use crate::util::secp::pedersen;
|
||||
use crate::util::Mutex;
|
||||
use chrono::Duration;
|
||||
use grin_keychain::Keychain;
|
||||
use std::sync::Arc;
|
||||
@@ -54,7 +51,7 @@ fn get_kernel_local(
|
||||
max_height: Option<u64>,
|
||||
) -> Option<api::LocatedTxKernel> {
|
||||
chain
|
||||
.get_kernel_height(&excess, min_height, max_height)
|
||||
.get_kernel_height(excess, min_height, max_height)
|
||||
.unwrap()
|
||||
.map(|(tx_kernel, height, mmr_index)| api::LocatedTxKernel {
|
||||
tx_kernel,
|
||||
@@ -147,7 +144,7 @@ pub fn create_block_for_wallet<'a, L, C, K>(
|
||||
chain: &Chain,
|
||||
prev: core::core::BlockHeader,
|
||||
txs: &[Transaction],
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet: grin_wallet_libwallet::WalletHandle<'a, L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
) -> Result<core::core::Block, libwallet::Error>
|
||||
where
|
||||
@@ -178,7 +175,7 @@ where
|
||||
pub fn award_block_to_wallet<'a, L, C, K>(
|
||||
chain: &Chain,
|
||||
txs: &[Transaction],
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet: grin_wallet_libwallet::WalletHandle<'a, L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
) -> Result<(), libwallet::Error>
|
||||
where
|
||||
@@ -200,7 +197,7 @@ pub fn process_block(chain: &Chain, block: core::core::Block) {
|
||||
/// Award a blocks to a wallet directly
|
||||
pub fn award_blocks_to_wallet<'a, L, C, K>(
|
||||
chain: &Chain,
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet: grin_wallet_libwallet::WalletHandle<'a, L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
number: usize,
|
||||
pause_between: bool,
|
||||
@@ -221,7 +218,7 @@ where
|
||||
|
||||
/// send an amount to a destination
|
||||
pub fn send_to_dest<'a, L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet: grin_wallet_libwallet::WalletHandle<'a, L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
client: LocalWalletClient,
|
||||
dest: &str,
|
||||
@@ -261,7 +258,7 @@ where
|
||||
|
||||
/// get wallet info totals
|
||||
pub fn wallet_info<'a, L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet: grin_wallet_libwallet::WalletHandle<'a, L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
) -> Result<WalletInfo, libwallet::Error>
|
||||
where
|
||||
|
||||
@@ -26,7 +26,7 @@ use crate::keychain::Keychain;
|
||||
use crate::libwallet;
|
||||
use crate::libwallet::api_impl::foreign;
|
||||
use crate::libwallet::slate_versions::v4::SlateV4;
|
||||
use crate::libwallet::{NodeClient, NodeVersionInfo, Slate, WalletInst, WalletLCProvider};
|
||||
use crate::libwallet::{NodeClient, NodeVersionInfo, Slate, WalletLCProvider};
|
||||
use crate::util;
|
||||
use crate::util::secp::key::SecretKey;
|
||||
use crate::util::secp::pedersen;
|
||||
@@ -66,11 +66,12 @@ where
|
||||
/// handle to chain itself
|
||||
pub chain: Arc<Chain>,
|
||||
/// list of interested wallets
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub wallets: HashMap<
|
||||
String,
|
||||
(
|
||||
Sender<WalletProxyMessage>,
|
||||
Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
grin_wallet_libwallet::WalletHandle<'a, L, C, K>,
|
||||
Option<SecretKey>,
|
||||
),
|
||||
>,
|
||||
@@ -119,7 +120,7 @@ where
|
||||
&mut self,
|
||||
addr: &str,
|
||||
tx: Sender<WalletProxyMessage>,
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet: grin_wallet_libwallet::WalletHandle<'a, L, C, K>,
|
||||
keychain_mask: Option<SecretKey>,
|
||||
) {
|
||||
self.wallets
|
||||
@@ -185,12 +186,7 @@ where
|
||||
libwallet::Error::ClientCallback("Error parsing Transaction".to_owned())
|
||||
})?;
|
||||
|
||||
super::award_block_to_wallet(
|
||||
&self.chain,
|
||||
&[tx],
|
||||
dest_wallet,
|
||||
(&dest_wallet_mask).as_ref(),
|
||||
)?;
|
||||
super::award_block_to_wallet(&self.chain, &[tx], dest_wallet, dest_wallet_mask.as_ref())?;
|
||||
|
||||
Ok(WalletProxyMessage {
|
||||
sender_id: "node".to_owned(),
|
||||
@@ -219,7 +215,7 @@ where
|
||||
let w = w_lock.lc_provider()?.wallet_inst()?;
|
||||
let mask = wallet.2.clone();
|
||||
// receive tx
|
||||
match foreign::receive_tx(w, (&mask).as_ref(), &Slate::from(slate), None, false) {
|
||||
match foreign::receive_tx(w, mask.as_ref(), &Slate::from(slate), None, false) {
|
||||
Err(e) => {
|
||||
return Ok(WalletProxyMessage {
|
||||
sender_id: m.dest,
|
||||
|
||||
+10
-8
@@ -59,12 +59,14 @@ struct TorService {
|
||||
state_lock: PathBuf,
|
||||
}
|
||||
|
||||
type ArtiClientConfig = (Arc<TorClient<TokioNativeTlsRuntime>>, TorClientConfig);
|
||||
|
||||
lazy_static! {
|
||||
/// Arti Tokio runtime.
|
||||
static ref ARTI_RUNTIME: LazyLock<Mutex<Option<ArtiRuntimeWrapper>>> =
|
||||
LazyLock::new(|| Mutex::new(ArtiRuntimeWrapper::create().ok()));
|
||||
/// Arti client and config.
|
||||
static ref ARTI_CLIENT_CONFIG: LazyLock<Mutex<Option<(Arc<TorClient<TokioNativeTlsRuntime>>, TorClientConfig)>>> =
|
||||
static ref ARTI_CLIENT_CONFIG: LazyLock<Mutex<Option<ArtiClientConfig>>> =
|
||||
LazyLock::new(|| Mutex::new(None));
|
||||
/// Running services, where key is onion address.
|
||||
static ref ARTI_PROXY_SERVICES: LazyLock<Mutex<HashMap<String, TorService>>> =
|
||||
@@ -138,7 +140,7 @@ pub fn start_tor_service(key: SecretKey, addr: &str, config: &TorConfig) -> Resu
|
||||
info!("Proxy configuration will be ignored.");
|
||||
}
|
||||
|
||||
let (state_path, cache_path) = state_cache_paths(&config);
|
||||
let (state_path, cache_path) = state_cache_paths(config);
|
||||
let (client, config) = init_client(&state_path, &cache_path, config)?;
|
||||
|
||||
// Add service key to keystore.
|
||||
@@ -151,7 +153,7 @@ pub fn start_tor_service(key: SecretKey, addr: &str, config: &TorConfig) -> Resu
|
||||
let state_lock = state_path
|
||||
.join("hss")
|
||||
.join(format!("{}.lock", onion_address));
|
||||
let _ = add_service_key(config.fs_mistrust(), &key, &hs, keystore_path)?;
|
||||
add_service_key(config.fs_mistrust(), &key, &hs, keystore_path)?;
|
||||
|
||||
// Launch Onion service.
|
||||
let service_config = OnionServiceConfigBuilder::default()
|
||||
@@ -233,7 +235,7 @@ where
|
||||
}
|
||||
.to_string();
|
||||
let timeout = tor_config.request_timeout();
|
||||
let (state_path, cache_path) = state_cache_paths(&tor_config);
|
||||
let (state_path, cache_path) = state_cache_paths(tor_config);
|
||||
let (client, _) = init_client(&state_path, &cache_path, tor_config)?;
|
||||
let res: Result<String, Error> = thread::spawn(move || {
|
||||
let c = client.clone();
|
||||
@@ -286,7 +288,7 @@ where
|
||||
})
|
||||
})
|
||||
.join()
|
||||
.unwrap_or_else(|e| return Err(Error::TorProcess(format!("{:?}", e))))?;
|
||||
.unwrap_or_else(|e| Err(Error::TorProcess(format!("{:?}", e))))?;
|
||||
res
|
||||
}
|
||||
|
||||
@@ -296,7 +298,7 @@ fn init_client(
|
||||
cache_path: &PathBuf,
|
||||
tor_config: &TorConfig,
|
||||
) -> Result<(Arc<TorClient<TokioNativeTlsRuntime>>, TorClientConfig), Error> {
|
||||
let mut builder = TorClientConfigBuilder::from_directories(&state_path, cache_path);
|
||||
let mut builder = TorClientConfigBuilder::from_directories(state_path, cache_path);
|
||||
builder.address_filter().allow_onion_addrs(true);
|
||||
|
||||
// Configure bridge.
|
||||
@@ -345,7 +347,7 @@ fn init_client(
|
||||
*cached_client_config = None;
|
||||
}
|
||||
}
|
||||
let res = launch_client(config.clone(), &tor_config);
|
||||
let res = launch_client(config.clone(), tor_config);
|
||||
match res {
|
||||
Ok(client) => {
|
||||
cached_client_config.replace((client.clone(), config.clone()));
|
||||
@@ -458,7 +460,7 @@ fn add_service_key(
|
||||
Some(expanded_kp) => {
|
||||
key_manager
|
||||
.insert(
|
||||
HsIdKey::from(expanded_kp.public().clone()),
|
||||
HsIdKey::from(*expanded_kp.public()),
|
||||
&HsIdPublicKeySpecifier::new(hs_nickname.clone()),
|
||||
KeystoreSelector::Primary,
|
||||
true,
|
||||
|
||||
+29
-66
@@ -87,8 +87,8 @@ impl<'a> FlagParser<'a> {
|
||||
fn end(&mut self, is_bool_flag: bool, right: &str) -> usize {
|
||||
if is_bool_flag {
|
||||
0
|
||||
} else if right.starts_with('"') {
|
||||
right[1..].find('"').unwrap_or(0) + 2
|
||||
} else if let Some(stripped) = right.strip_prefix('"') {
|
||||
stripped.find('"').unwrap_or(0) + 2
|
||||
} else {
|
||||
right.find(' ').unwrap_or(right.len())
|
||||
}
|
||||
@@ -113,7 +113,7 @@ impl<'a> Iterator for FlagParser<'a> {
|
||||
let end = self.end(self.is_bool_flag, right);
|
||||
let key = left.split_whitespace().last()?;
|
||||
let val = &right[..end];
|
||||
self.line = &right[end..].trim();
|
||||
self.line = right[end..].trim();
|
||||
Some((key, val))
|
||||
}
|
||||
}
|
||||
@@ -121,7 +121,7 @@ impl<'a> Iterator for FlagParser<'a> {
|
||||
/// Every args field that could be in the bridge line
|
||||
/// obfs4 args : https://github.com/Yawning/obfs4/blob/40245c4a1cf221395c59d1f4bf274127045352f9/transports/obfs4/obfs4.go#L86-L91
|
||||
/// meek_lite args : https://github.com/Yawning/obfs4/blob/40245c4a1cf221395c59d1f4bf274127045352f9/transports/meeklite/meek.go#L93-L127
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Default)]
|
||||
pub struct Transport {
|
||||
/// transport type: obfs4, meek_lite, meek, snowflake
|
||||
pub transport: Option<String>,
|
||||
@@ -143,22 +143,6 @@ pub struct Transport {
|
||||
pub disablehpkp: Option<String>,
|
||||
}
|
||||
|
||||
impl Default for Transport {
|
||||
fn default() -> Transport {
|
||||
Transport {
|
||||
transport: None,
|
||||
server: None,
|
||||
fingerprint: None,
|
||||
cert: None,
|
||||
iatmode: None,
|
||||
url: None,
|
||||
front: None,
|
||||
utls: None,
|
||||
disablehpkp: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Transport {
|
||||
/// Parse the server address of the bridge line
|
||||
fn parse_socketaddr_arg(arg: Option<&&str>) -> Result<String, Error> {
|
||||
@@ -170,7 +154,7 @@ impl Transport {
|
||||
Ok(address.to_string())
|
||||
}
|
||||
None => {
|
||||
let msg = format!("Missing bridge server address");
|
||||
let msg = "Missing bridge server address".to_string();
|
||||
Err(Error::TorBridge(msg))
|
||||
}
|
||||
}
|
||||
@@ -202,7 +186,7 @@ impl Transport {
|
||||
})?;
|
||||
if cert_vec.len() != 52 {
|
||||
let msg = format!("Invalid certificate: {}", arg);
|
||||
return Err(Error::TorBridge(msg).into());
|
||||
return Err(Error::TorBridge(msg));
|
||||
}
|
||||
Ok(arg.to_string())
|
||||
}
|
||||
@@ -219,16 +203,17 @@ impl Transport {
|
||||
/// Parse the max value for the arg -max in the client line option (snowflake)
|
||||
fn parse_hpkp_arg(arg: &str) -> Result<String, Error> {
|
||||
let max = arg.parse::<bool>().map_err(|_e| {
|
||||
Error::TorBridge(
|
||||
format!("Invalid -max value: {}, must be \"true\" or \"false\"", arg).into(),
|
||||
)
|
||||
Error::TorBridge(format!(
|
||||
"Invalid -max value: {}, must be \"true\" or \"false\"",
|
||||
arg
|
||||
))
|
||||
})?;
|
||||
Ok(max.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
// Client Plugin such as snowflake or obfs4proxy
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Default)]
|
||||
pub struct PluginClient {
|
||||
// Path plugin client
|
||||
pub path: Option<String>,
|
||||
@@ -236,15 +221,6 @@ pub struct PluginClient {
|
||||
pub option: Option<String>,
|
||||
}
|
||||
|
||||
impl Default for PluginClient {
|
||||
fn default() -> PluginClient {
|
||||
PluginClient {
|
||||
path: None,
|
||||
option: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PluginClient {
|
||||
/// Get the hashmap key(argument) and attached value of the client option line.
|
||||
pub fn get_flags(s: &str) -> HashMap<&str, &str> {
|
||||
@@ -333,7 +309,7 @@ impl PluginClient {
|
||||
"Invalid ICE address: {}. Must be a stun or turn address",
|
||||
addr
|
||||
);
|
||||
return Err(Error::TorBridge(msg).into());
|
||||
return Err(Error::TorBridge(msg));
|
||||
}
|
||||
}
|
||||
Ok(ice_addr.to_string())
|
||||
@@ -372,9 +348,9 @@ impl PluginClient {
|
||||
let (ck_url, ck_ice) = (hm_flags.contains_key("-url"), hm_flags.contains_key("-ice"));
|
||||
if !(ck_url || ck_ice) {
|
||||
let msg = if !ck_url {
|
||||
format!("Missing URL argurment for snowflake transport, specify \"-url\"")
|
||||
"Missing URL argurment for snowflake transport, specify \"-url\"".to_string()
|
||||
} else {
|
||||
format!("Missing ICE argurment for snowflake transport, specify \"-ice\"")
|
||||
"Missing ICE argurment for snowflake transport, specify \"-ice\"".to_string()
|
||||
};
|
||||
return Err(Error::TorBridge(msg));
|
||||
}
|
||||
@@ -410,7 +386,7 @@ impl PluginClient {
|
||||
}
|
||||
|
||||
/// Tor Bridge Field
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Default)]
|
||||
pub struct TorBridge {
|
||||
/// tor bridge (transport field)
|
||||
pub bridge: Transport,
|
||||
@@ -418,15 +394,6 @@ pub struct TorBridge {
|
||||
pub client: PluginClient,
|
||||
}
|
||||
|
||||
impl Default for TorBridge {
|
||||
fn default() -> TorBridge {
|
||||
TorBridge {
|
||||
bridge: Transport::default(),
|
||||
client: PluginClient::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TorBridge {
|
||||
/// Get the hashmap key(argument) and attached value of the bridge line. r
|
||||
pub fn get_flags(s: &str) -> HashMap<&str, &str> {
|
||||
@@ -541,8 +508,8 @@ impl TryFrom<TorBridgeConfig> for TorBridge {
|
||||
let cert = match flags.get_key_value("cert=") {
|
||||
Some(hm) => Transport::parse_cert_arg(hm.1)?,
|
||||
None => {
|
||||
let msg =
|
||||
format!("Missing cert argurment in obfs4 transport, specify \"cert=\"");
|
||||
let msg = "Missing cert argurment in obfs4 transport, specify \"cert=\""
|
||||
.to_string();
|
||||
return Err(Error::TorBridge(msg));
|
||||
}
|
||||
};
|
||||
@@ -559,14 +526,14 @@ impl TryFrom<TorBridgeConfig> for TorBridge {
|
||||
bridge: Transport {
|
||||
transport: Some("obfs4".into()),
|
||||
server: Some(socketaddr.to_string()),
|
||||
fingerprint: fingerprint,
|
||||
cert: Some(cert.into()),
|
||||
fingerprint,
|
||||
cert: Some(cert),
|
||||
iatmode: Some(iatmode),
|
||||
..Transport::default()
|
||||
},
|
||||
client: PluginClient {
|
||||
path: Some(path),
|
||||
option: option,
|
||||
option,
|
||||
},
|
||||
};
|
||||
Ok(tbpc)
|
||||
@@ -578,9 +545,8 @@ impl TryFrom<TorBridgeConfig> for TorBridge {
|
||||
let url = match flags.get_key_value("url=") {
|
||||
Some(hm) => PluginClient::parse_url_arg(hm.1)?,
|
||||
None => {
|
||||
let msg = format!(
|
||||
"Missing url argurment in meek_lite transport, specify \"url=\""
|
||||
);
|
||||
let msg = "Missing url argurment in meek_lite transport, specify \"url=\""
|
||||
.to_string();
|
||||
return Err(Error::TorBridge(msg));
|
||||
}
|
||||
};
|
||||
@@ -588,10 +554,7 @@ impl TryFrom<TorBridgeConfig> for TorBridge {
|
||||
Some(hm) => Some(PluginClient::parse_front_arg(hm.1)?),
|
||||
None => None,
|
||||
};
|
||||
let utls = match flags.get_key_value("utls=") {
|
||||
Some(hm) => Some(hm.1.to_string()),
|
||||
None => None,
|
||||
};
|
||||
let utls = flags.get_key_value("utls=").map(|hm| hm.1.to_string());
|
||||
let disablehpkp = match flags.get_key_value("disablehpkp=") {
|
||||
Some(hm) => Some(Transport::parse_hpkp_arg(hm.1)?),
|
||||
None => None,
|
||||
@@ -605,16 +568,16 @@ impl TryFrom<TorBridgeConfig> for TorBridge {
|
||||
bridge: Transport {
|
||||
transport: Some("meek_lite".into()),
|
||||
server: Some(socketaddr.to_string()),
|
||||
fingerprint: fingerprint,
|
||||
fingerprint,
|
||||
url: Some(url),
|
||||
front: front,
|
||||
utls: utls,
|
||||
disablehpkp: disablehpkp,
|
||||
front,
|
||||
utls,
|
||||
disablehpkp,
|
||||
..Transport::default()
|
||||
},
|
||||
client: PluginClient {
|
||||
path: Some(path),
|
||||
option: option,
|
||||
option,
|
||||
},
|
||||
};
|
||||
Ok(tbpc)
|
||||
@@ -638,7 +601,7 @@ impl TryFrom<TorBridgeConfig> for TorBridge {
|
||||
bridge: Transport {
|
||||
transport: Some("snowflake".into()),
|
||||
server: Some(socketaddr.to_string()),
|
||||
fingerprint: fingerprint,
|
||||
fingerprint,
|
||||
..Transport::default()
|
||||
},
|
||||
client: PluginClient {
|
||||
|
||||
@@ -131,7 +131,7 @@ pub fn create_onion_service_pub_key_file(
|
||||
pub fn create_onion_service_hostname_file(os_directory: &str, hostname: &str) -> Result<(), Error> {
|
||||
let file_path = &format!("{}{}{}", os_directory, MAIN_SEPARATOR, HOSTNAME_FILE);
|
||||
let mut file = File::create(file_path).map_err(|_| Error::IO)?;
|
||||
file.write_all(&format!("{}.onion\n", hostname).as_bytes())
|
||||
file.write_all(format!("{}.onion\n", hostname).as_bytes())
|
||||
.map_err(|_| Error::IO)?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -228,7 +228,7 @@ pub fn output_tor_listener_config(
|
||||
let mut service_dirs = vec![];
|
||||
|
||||
for k in listener_keys {
|
||||
let service_dir = output_onion_service_config(tor_config_directory, &k)?;
|
||||
let service_dir = output_onion_service_config(tor_config_directory, k)?;
|
||||
service_dirs.push(service_dir.to_string());
|
||||
}
|
||||
|
||||
@@ -253,7 +253,7 @@ pub fn output_tor_sender_config(
|
||||
hm_tor_proxy: HashMap<String, String>,
|
||||
) -> Result<(), Error> {
|
||||
// create data directory if it doesn't exist
|
||||
fs::create_dir_all(&tor_config_dir).map_err(|_| Error::IO)?;
|
||||
fs::create_dir_all(tor_config_dir).map_err(|_| Error::IO)?;
|
||||
|
||||
output_torrc(
|
||||
tor_config_dir,
|
||||
@@ -272,7 +272,7 @@ pub fn is_tor_address(input: &str) -> Result<(), Error> {
|
||||
Ok(_) => Ok(()),
|
||||
Err(e) => {
|
||||
let msg = format!("{:?}", e);
|
||||
Err(Error::NotOnion(msg).into())
|
||||
Err(Error::NotOnion(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,6 +90,12 @@ pub struct TorProcess {
|
||||
sys: System,
|
||||
}
|
||||
|
||||
impl Default for TorProcess {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl TorProcess {
|
||||
pub fn new() -> Self {
|
||||
TorProcess {
|
||||
@@ -153,7 +159,7 @@ impl TorProcess {
|
||||
let mut tor = Command::new(&self.tor_cmd);
|
||||
|
||||
if let Some(ref d) = self.working_dir {
|
||||
tor.current_dir(&d);
|
||||
tor.current_dir(d);
|
||||
let pid_file_name = format!("{}{}pid", d, MAIN_SEPARATOR);
|
||||
// kill off PID if its already running
|
||||
if Path::new(&pid_file_name).exists() {
|
||||
@@ -167,7 +173,7 @@ impl TorProcess {
|
||||
}
|
||||
}
|
||||
if let Some(ref torrc_path) = self.torrc_path {
|
||||
tor.args(&vec!["-f", torrc_path]);
|
||||
tor.args(vec!["-f", torrc_path]);
|
||||
}
|
||||
let mut tor_process = tor
|
||||
.args(&self.args)
|
||||
|
||||
+7
-22
@@ -20,7 +20,7 @@ use std::str;
|
||||
use url::Host;
|
||||
|
||||
/// Tor Proxy
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
|
||||
pub struct TorProxy {
|
||||
/// proxy type used for the proxy, eg "socks4", "socks5", "http", "https"
|
||||
pub transport: Option<String>,
|
||||
@@ -34,18 +34,6 @@ pub struct TorProxy {
|
||||
pub allowed_port: Option<Vec<u16>>,
|
||||
}
|
||||
|
||||
impl Default for TorProxy {
|
||||
fn default() -> TorProxy {
|
||||
TorProxy {
|
||||
transport: None,
|
||||
address: None,
|
||||
username: None,
|
||||
password: None,
|
||||
allowed_port: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TorProxy {
|
||||
fn parse_host_port(addr: &str) -> Result<(String, Option<String>), Error> {
|
||||
let host: String;
|
||||
@@ -70,7 +58,7 @@ impl TorProxy {
|
||||
}
|
||||
|
||||
pub fn parse_address(addr: &str) -> Result<(String, Option<u16>), Error> {
|
||||
let (host, str_port) = TorProxy::parse_host_port(&addr)?;
|
||||
let (host, str_port) = TorProxy::parse_host_port(addr)?;
|
||||
let host = Host::parse(&host)
|
||||
.map_err(|_e| Error::TorProxy(format!("Invalid host address: {}", host)))?;
|
||||
let port = if let Some(p) = str_port {
|
||||
@@ -92,13 +80,10 @@ impl TorProxy {
|
||||
for port in ports.clone() {
|
||||
allowed_ports.push_str(format!("*:{}", port).as_str());
|
||||
if port != last_port {
|
||||
allowed_ports.push_str(",");
|
||||
allowed_ports.push(',');
|
||||
}
|
||||
}
|
||||
hm.insert(
|
||||
"ReachableAddresses".to_string(),
|
||||
format!("{}", allowed_ports.clone()),
|
||||
);
|
||||
hm.insert("ReachableAddresses".to_string(), allowed_ports);
|
||||
}
|
||||
|
||||
let transport = match self.transport {
|
||||
@@ -156,7 +141,7 @@ impl TryFrom<TorProxyConfig> for TorProxy {
|
||||
address_addr = host
|
||||
}
|
||||
Ok(TorProxy {
|
||||
transport: Some(transport.into()),
|
||||
transport: Some(transport),
|
||||
address: Some(address_addr),
|
||||
username: tb.username,
|
||||
password: tb.password,
|
||||
@@ -167,7 +152,7 @@ impl TryFrom<TorProxyConfig> for TorProxy {
|
||||
"Missing proxy address: {} - must be <IP:PORT> or <Hostname>",
|
||||
transport
|
||||
);
|
||||
return Err(Error::TorProxy(msg).into());
|
||||
Err(Error::TorProxy(msg))
|
||||
}
|
||||
}
|
||||
// Missing transport type
|
||||
@@ -176,7 +161,7 @@ impl TryFrom<TorProxyConfig> for TorProxy {
|
||||
"Invalid proxy transport: {} - must be socks4/socks5/http(s)",
|
||||
transport
|
||||
);
|
||||
Err(Error::TorProxy(msg).into())
|
||||
Err(Error::TorProxy(msg))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
//! Functions defining wallet 'addresses', i.e. ed2559 keys based on
|
||||
//! a derivation path
|
||||
|
||||
use crate::grin_util::secp::key::SecretKey;
|
||||
use crate::Error;
|
||||
use grin_keychain::{ChildNumber, Identifier, Keychain, SwitchCommitmentType};
|
||||
use grin_util::secp::key::SecretKey;
|
||||
|
||||
use crate::blake2::blake2b::blake2b;
|
||||
|
||||
@@ -50,10 +50,7 @@ where
|
||||
let key_id = address_derivation_path(parent_key_id, index);
|
||||
let sec_key = keychain.derive_key(0, &key_id, SwitchCommitmentType::None)?;
|
||||
let hashed = blake2b(32, &[], &sec_key.0[..]);
|
||||
Ok(SecretKey::from_slice(
|
||||
&keychain.secp(),
|
||||
&hashed.as_bytes()[..],
|
||||
)?)
|
||||
Ok(SecretKey::from_slice(keychain.secp(), hashed.as_bytes())?)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -20,14 +20,14 @@ use super::owner::tx_lock_outputs;
|
||||
use crate::api_impl::owner::{check_ttl, post_tx};
|
||||
use crate::api_impl::types::update_tx_slate_state;
|
||||
use crate::backend::WalletBackend;
|
||||
use crate::grin_core::core::FeeFields;
|
||||
use crate::grin_keychain::Keychain;
|
||||
use crate::grin_util::secp::key::SecretKey;
|
||||
use crate::internal::{selection, tx, updater};
|
||||
use crate::slate_versions::SlateVersion;
|
||||
use crate::{
|
||||
address, BlockFees, CbData, Error, NodeClient, Slate, SlateState, TxLogEntryType, VersionInfo,
|
||||
};
|
||||
use grin_core::core::FeeFields;
|
||||
use grin_keychain::Keychain;
|
||||
use grin_util::secp::key::SecretKey;
|
||||
|
||||
const FOREIGN_API_VERSION: u16 = 2;
|
||||
|
||||
@@ -164,7 +164,7 @@ where
|
||||
selection::repopulate_tx(w, keychain_mask, &mut sl, &temp_ctx, false)?;
|
||||
|
||||
tx::complete_tx(w, keychain_mask, &mut sl, &context)?;
|
||||
tx::update_stored_tx(w, keychain_mask, &context, &mut sl, true)?;
|
||||
tx::update_stored_tx(w, keychain_mask, &context, &sl, true)?;
|
||||
{
|
||||
let mut batch = w.batch(keychain_mask)?;
|
||||
batch.delete_private_context(sl.id.as_bytes())?;
|
||||
|
||||
@@ -18,18 +18,16 @@ use std::cmp;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::api_impl::foreign::finalize_tx as foreign_finalize;
|
||||
use crate::grin_core::core::amount_to_hr_string;
|
||||
use crate::grin_core::core::hash::Hashed;
|
||||
use crate::grin_core::core::{FeeFields, Output, OutputFeatures, Transaction};
|
||||
use crate::grin_core::libtx::proof;
|
||||
use crate::grin_keychain::ViewKey;
|
||||
use crate::grin_util::secp::{key::SecretKey, pedersen::Commitment};
|
||||
use crate::grin_util::Mutex;
|
||||
use crate::grin_util::ToHex;
|
||||
use crate::util::OnionV3Address;
|
||||
use grin_core::core::amount_to_hr_string;
|
||||
use grin_core::core::hash::Hashed;
|
||||
use grin_core::core::{FeeFields, Output, OutputFeatures, Transaction};
|
||||
use grin_core::libtx::proof;
|
||||
use grin_keychain::ViewKey;
|
||||
use grin_util::secp::{key::SecretKey, pedersen::Commitment};
|
||||
use grin_util::ToHex;
|
||||
|
||||
use crate::api_impl::owner_updater::StatusMessage;
|
||||
use crate::grin_keychain::{BlindingFactor, Identifier, Keychain, SwitchCommitmentType};
|
||||
use crate::internal::{keys, scan, selection, tx, updater};
|
||||
use crate::slate::{PaymentInfo, Slate, SlateState};
|
||||
use crate::types::{AcctPathMapping, NodeClient, TxLogEntry, WalletInfo};
|
||||
@@ -39,8 +37,9 @@ use crate::{
|
||||
wallet_lock, BuiltOutput, Error, InitTxArgs, IssueInvoiceTxArgs, NodeHeightResult,
|
||||
OutputCommitMapping, PaymentProof, RetrieveTxQueryArgs, ScannedBlockInfo, Slatepack,
|
||||
SlatepackAddress, Slatepacker, SlatepackerArgs, TxLogEntryType, ViewWallet, WalletBackend,
|
||||
WalletInitStatus, WalletInst, WalletLCProvider,
|
||||
WalletInitStatus, WalletLCProvider,
|
||||
};
|
||||
use grin_keychain::{BlindingFactor, Identifier, Keychain, SwitchCommitmentType};
|
||||
|
||||
use ed25519_dalek::SigningKey as DalekSecretKey;
|
||||
use ed25519_dalek::Verifier;
|
||||
@@ -49,7 +48,6 @@ use x25519_dalek::{PublicKey as xPublicKey, StaticSecret};
|
||||
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::sync::mpsc::Sender;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// List of accounts
|
||||
pub fn accounts<C, K>(
|
||||
@@ -103,7 +101,7 @@ where
|
||||
|
||||
/// Hash of the wallet root public key
|
||||
pub fn get_rewind_hash<'a, L, C, K>(
|
||||
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet_inst: crate::WalletHandle<'a, L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
) -> Result<String, Error>
|
||||
where
|
||||
@@ -121,7 +119,7 @@ where
|
||||
/// Retrieve the slatepack address for the current parent key at
|
||||
/// the given index
|
||||
pub fn get_slatepack_address<'a, L, C, K>(
|
||||
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet_inst: crate::WalletHandle<'a, L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
index: u32,
|
||||
) -> Result<SlatepackAddress, Error>
|
||||
@@ -140,7 +138,7 @@ where
|
||||
/// Retrieve the decryption key for the current parent key
|
||||
/// the given index
|
||||
pub fn get_slatepack_secret_key<'a, L, C, K>(
|
||||
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet_inst: crate::WalletHandle<'a, L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
index: u32,
|
||||
) -> Result<DalekSecretKey, Error>
|
||||
@@ -159,7 +157,7 @@ where
|
||||
|
||||
/// Create a slatepack message from the given slate
|
||||
pub fn create_slatepack_message<'a, L, C, K>(
|
||||
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet_inst: crate::WalletHandle<'a, L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
slate: &Slate,
|
||||
sender_index: Option<u32>,
|
||||
@@ -186,7 +184,7 @@ where
|
||||
/// Unpack a slate from the given slatepack message,
|
||||
/// optionally decrypting
|
||||
pub fn slate_from_slatepack_message<'a, L, C, K>(
|
||||
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet_inst: crate::WalletHandle<'a, L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
slatepack: String,
|
||||
secret_indices: Vec<u32>,
|
||||
@@ -214,7 +212,7 @@ where
|
||||
let packer = Slatepacker::new(SlatepackerArgs {
|
||||
sender: None,
|
||||
recipients: vec![],
|
||||
dec_key: (&dec_key).as_ref(),
|
||||
dec_key: dec_key.as_ref(),
|
||||
});
|
||||
let res = packer.deser_slatepack(slatepack.as_bytes(), true);
|
||||
let slatepack = match res {
|
||||
@@ -228,8 +226,7 @@ where
|
||||
Err(Error::SlatepackDecryption(
|
||||
"Could not decrypt slatepack with any provided index on the address derivation path"
|
||||
.to_owned(),
|
||||
)
|
||||
.into())
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,7 +234,7 @@ where
|
||||
/// Will decrypt if possible, otherwise will return
|
||||
/// undecrypted slatepack
|
||||
pub fn decode_slatepack_message<'a, L, C, K>(
|
||||
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet_inst: crate::WalletHandle<'a, L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
slatepack: String,
|
||||
secret_indices: Vec<u32>,
|
||||
@@ -264,7 +261,7 @@ where
|
||||
let packer = Slatepacker::new(SlatepackerArgs {
|
||||
sender: None,
|
||||
recipients: vec![],
|
||||
dec_key: (&dec_key).as_ref(),
|
||||
dec_key: dec_key.as_ref(),
|
||||
});
|
||||
let res = packer.deser_slatepack(slatepack.as_bytes(), true);
|
||||
let slatepack = match res {
|
||||
@@ -281,7 +278,7 @@ where
|
||||
|
||||
/// retrieve outputs
|
||||
pub fn retrieve_outputs<'a, L, C, K>(
|
||||
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet_inst: crate::WalletHandle<'a, L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
status_send_channel: &Option<Sender<StatusMessage>>,
|
||||
include_spent: bool,
|
||||
@@ -315,7 +312,7 @@ where
|
||||
|
||||
/// Calculate max amount to send.
|
||||
pub fn estimate_max_sendable<'a, L, C, K>(
|
||||
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet_inst: crate::WalletHandle<'a, L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
status_send_channel: &Option<Sender<StatusMessage>>,
|
||||
refresh_from_node: bool,
|
||||
@@ -374,7 +371,7 @@ where
|
||||
|
||||
/// Retrieve txs
|
||||
pub fn retrieve_txs<'a, L, C, K>(
|
||||
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet_inst: crate::WalletHandle<'a, L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
status_send_channel: &Option<Sender<StatusMessage>>,
|
||||
refresh_from_node: bool,
|
||||
@@ -414,7 +411,7 @@ where
|
||||
|
||||
/// Retrieve summary info
|
||||
pub fn retrieve_summary_info<'a, L, C, K>(
|
||||
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet_inst: crate::WalletHandle<'a, L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
status_send_channel: &Option<Sender<StatusMessage>>,
|
||||
refresh_from_node: bool,
|
||||
@@ -444,7 +441,7 @@ where
|
||||
|
||||
/// Retrieve payment proof
|
||||
pub fn retrieve_payment_proof<'a, L, C, K>(
|
||||
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet_inst: crate::WalletHandle<'a, L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
status_send_channel: &Option<Sender<StatusMessage>>,
|
||||
refresh_from_node: bool,
|
||||
@@ -864,7 +861,7 @@ where
|
||||
|
||||
let mut sl = slate.clone();
|
||||
|
||||
if sl.tx == None {
|
||||
if sl.tx.is_none() {
|
||||
sl.tx = Some(Slate::empty_transaction());
|
||||
selection::repopulate_tx(w, keychain_mask, &mut sl, &context, true)?;
|
||||
}
|
||||
@@ -893,7 +890,7 @@ where
|
||||
|
||||
/// cancel tx
|
||||
pub fn cancel_tx<'a, L, C, K>(
|
||||
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet_inst: crate::WalletHandle<'a, L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
status_send_channel: &Option<Sender<StatusMessage>>,
|
||||
tx_id: Option<u32>,
|
||||
@@ -932,11 +929,7 @@ where
|
||||
{
|
||||
let mut uuid = None;
|
||||
if let Some(i) = tx_id {
|
||||
let tx = w
|
||||
.tx_log_iter()?
|
||||
.filter(|tx| tx.is_ok())
|
||||
.map(|tx| tx.unwrap())
|
||||
.find(|t| t.id == i);
|
||||
let tx = w.tx_log_iter()?.flatten().find(|t| t.id == i);
|
||||
if let Some(t) = tx {
|
||||
uuid = t.tx_slate_id;
|
||||
}
|
||||
@@ -992,7 +985,7 @@ where
|
||||
/// Scan outputs with the rewind hash of a third-party wallet.
|
||||
/// Help to retrieve outputs information that belongs it
|
||||
pub fn scan_rewind_hash<'a, L, C, K>(
|
||||
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet_inst: crate::WalletHandle<'a, L, C, K>,
|
||||
rewind_hash: String,
|
||||
start_height: Option<u64>,
|
||||
status_send_channel: &Option<Sender<StatusMessage>>,
|
||||
@@ -1013,7 +1006,7 @@ where
|
||||
w.w2n_client().get_chain_tip()?
|
||||
};
|
||||
|
||||
let start_height = start_height.unwrap_or_else(|| 1);
|
||||
let start_height = start_height.unwrap_or(1);
|
||||
|
||||
let info = scan::scan_rewind_hash(
|
||||
wallet_inst,
|
||||
@@ -1029,7 +1022,7 @@ where
|
||||
/// Accepts a wallet inst instead of a raw wallet so it can
|
||||
/// lock as little as possible
|
||||
pub fn scan<'a, L, C, K>(
|
||||
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet_inst: crate::WalletHandle<'a, L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
start_height: Option<u64>,
|
||||
delete_unconfirmed: bool,
|
||||
@@ -1046,7 +1039,7 @@ where
|
||||
w.w2n_client().get_chain_tip()?
|
||||
};
|
||||
|
||||
let start_height = start_height.unwrap_or_else(|| 1);
|
||||
let start_height = start_height.unwrap_or(1);
|
||||
|
||||
// Scan every 10k heights to save data between batches in case of interruption.
|
||||
let mut total_pmmr_range = None;
|
||||
@@ -1081,7 +1074,7 @@ where
|
||||
|
||||
/// node height
|
||||
pub fn node_height<'a, L, C, K>(
|
||||
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet_inst: crate::WalletHandle<'a, L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
) -> Result<NodeHeightResult, Error>
|
||||
where
|
||||
@@ -1101,12 +1094,7 @@ where
|
||||
}),
|
||||
Err(_) => {
|
||||
let outputs = retrieve_outputs(wallet_inst, keychain_mask, &None, true, false, None)?;
|
||||
let height = outputs
|
||||
.1
|
||||
.iter()
|
||||
.map(|m| m.output.height)
|
||||
.max()
|
||||
.unwrap_or_else(|| 0);
|
||||
let height = outputs.1.iter().map(|m| m.output.height).max().unwrap_or(0);
|
||||
Ok(NodeHeightResult {
|
||||
height,
|
||||
header_hash: "".to_owned(),
|
||||
@@ -1121,7 +1109,7 @@ pub const REORG_RESCAN_WINDOW: u64 = 24 * 60 * 2;
|
||||
|
||||
/// Experimental, wrap the entire definition of how a wallet's state is updated
|
||||
pub fn update_wallet_state<'a, L, C, K>(
|
||||
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet_inst: crate::WalletHandle<'a, L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
status_send_channel: &Option<Sender<StatusMessage>>,
|
||||
update_all: bool,
|
||||
@@ -1275,10 +1263,8 @@ where
|
||||
{
|
||||
// Refuse if TTL is expired
|
||||
let last_confirmed_height = w.last_confirmed_height()?;
|
||||
if slate.ttl_cutoff_height != 0 {
|
||||
if last_confirmed_height >= slate.ttl_cutoff_height {
|
||||
return Err(Error::TransactionExpired);
|
||||
}
|
||||
if slate.ttl_cutoff_height != 0 && last_confirmed_height >= slate.ttl_cutoff_height {
|
||||
return Err(Error::TransactionExpired);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -1286,7 +1272,7 @@ where
|
||||
/// Verify/validate arbitrary payment proof
|
||||
/// Returns (whether this wallet is the sender, whether this wallet is the recipient)
|
||||
pub fn verify_payment_proof<'a, L, C, K>(
|
||||
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet_inst: crate::WalletHandle<'a, L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
proof: &PaymentProof,
|
||||
) -> Result<(bool, bool), Error>
|
||||
@@ -1350,7 +1336,7 @@ where
|
||||
|
||||
/// Attempt to update outputs in wallet, return whether it was successful
|
||||
fn update_outputs<'a, L, C, K>(
|
||||
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet_inst: crate::WalletHandle<'a, L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
update_all: bool,
|
||||
) -> Result<bool, Error>
|
||||
@@ -1374,9 +1360,9 @@ where
|
||||
|
||||
/// Update transactions that need to be validated via kernel lookup
|
||||
fn update_txs_via_kernel<'a, L, C, K>(
|
||||
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet_inst: crate::WalletHandle<'a, L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
txs: &mut Vec<TxLogEntry>,
|
||||
txs: &mut [TxLogEntry],
|
||||
) -> Result<bool, Error>
|
||||
where
|
||||
L: WalletLCProvider<'a, C, K>,
|
||||
@@ -1515,30 +1501,29 @@ where
|
||||
|
||||
let mut blind_sum = new_output
|
||||
.blind
|
||||
.split(&BlindingFactor::from_secret_key(input_blind.clone()), &secp)?;
|
||||
.split(&BlindingFactor::from_secret_key(input_blind.clone()), secp)?;
|
||||
|
||||
let hops = server_pubkeys
|
||||
let hops: Vec<Hop> = server_pubkeys
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, &p)| {
|
||||
if (i + 1) == server_pubkeys.len() {
|
||||
Hop {
|
||||
server_pubkey: p.clone(),
|
||||
excess: blind_sum.secret_key(&secp).unwrap(),
|
||||
server_pubkey: p,
|
||||
excess: blind_sum.secret_key(secp).unwrap(),
|
||||
fee: FeeFields::from(fee as u32),
|
||||
rangeproof: Some(new_output.output.proof.clone()),
|
||||
rangeproof: Some(new_output.output.proof),
|
||||
}
|
||||
} else {
|
||||
let hop_excess;
|
||||
if use_test_rng {
|
||||
hop_excess = BlindingFactor::zero();
|
||||
let hop_excess = if use_test_rng {
|
||||
BlindingFactor::zero()
|
||||
} else {
|
||||
hop_excess = BlindingFactor::rand(&secp);
|
||||
}
|
||||
blind_sum = blind_sum.split(&hop_excess, &secp).unwrap();
|
||||
BlindingFactor::rand(secp)
|
||||
};
|
||||
blind_sum = blind_sum.split(&hop_excess, secp).unwrap();
|
||||
Hop {
|
||||
server_pubkey: p.clone(),
|
||||
excess: hop_excess.secret_key(&secp).unwrap(),
|
||||
server_pubkey: p,
|
||||
excess: hop_excess.secret_key(secp).unwrap(),
|
||||
fee: FeeFields::from(fee as u32),
|
||||
rangeproof: None,
|
||||
}
|
||||
@@ -1546,7 +1531,7 @@ where
|
||||
})
|
||||
.collect();
|
||||
|
||||
let onion = create_onion(&commitment, &hops, use_test_rng).unwrap();
|
||||
let onion = create_onion(commitment, &hops, use_test_rng).unwrap();
|
||||
let comsig = ComSignature::sign(
|
||||
amount,
|
||||
&input_blind,
|
||||
|
||||
@@ -19,14 +19,14 @@ use std::sync::Arc;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::grin_keychain::Keychain;
|
||||
use crate::grin_util::secp::key::SecretKey;
|
||||
use crate::grin_util::Mutex;
|
||||
use grin_keychain::Keychain;
|
||||
use grin_util::secp::key::SecretKey;
|
||||
use grin_util::Mutex;
|
||||
|
||||
use crate::api_impl::owner;
|
||||
use crate::types::NodeClient;
|
||||
use crate::Error;
|
||||
use crate::{WalletInst, WalletLCProvider};
|
||||
use crate::WalletLCProvider;
|
||||
|
||||
const MESSAGE_QUEUE_MAX_LEN: usize = 10_000;
|
||||
|
||||
@@ -101,7 +101,7 @@ where
|
||||
C: NodeClient + 'a,
|
||||
K: Keychain + 'a,
|
||||
{
|
||||
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet_inst: crate::WalletHandle<'a, L, C, K>,
|
||||
is_running: Arc<AtomicBool>,
|
||||
}
|
||||
|
||||
@@ -112,10 +112,7 @@ where
|
||||
K: Keychain + 'a,
|
||||
{
|
||||
/// create a new updater
|
||||
pub fn new(
|
||||
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
is_running: Arc<AtomicBool>,
|
||||
) -> Self {
|
||||
pub fn new(wallet_inst: crate::WalletHandle<'a, L, C, K>, is_running: Arc<AtomicBool>) -> Self {
|
||||
is_running.store(false, Ordering::Relaxed);
|
||||
Updater {
|
||||
wallet_inst,
|
||||
@@ -141,7 +138,7 @@ where
|
||||
if wallet_opened {
|
||||
owner::update_wallet_state(
|
||||
self.wallet_inst.clone(),
|
||||
(&keychain_mask).as_ref(),
|
||||
keychain_mask.as_ref(),
|
||||
status_send_channel,
|
||||
false,
|
||||
)?;
|
||||
|
||||
@@ -14,14 +14,14 @@
|
||||
|
||||
//! Types specific to the wallet api, mostly argument serialization
|
||||
|
||||
use crate::grin_core::core::Output;
|
||||
use crate::grin_core::libtx::secp_ser;
|
||||
use crate::grin_keychain::{BlindingFactor, Identifier};
|
||||
use crate::grin_util::secp::pedersen;
|
||||
use crate::slate_versions::ser as dalek_ser;
|
||||
use crate::slate_versions::SlateVersion;
|
||||
use crate::types::OutputData;
|
||||
use crate::{Error, NodeClient, Slate, SlatepackAddress, WalletBackend};
|
||||
use grin_core::core::Output;
|
||||
use grin_core::libtx::secp_ser;
|
||||
use grin_keychain::{BlindingFactor, Identifier};
|
||||
use grin_util::secp::pedersen;
|
||||
|
||||
use chrono::prelude::*;
|
||||
use ed25519_dalek::Signature as DalekSignature;
|
||||
@@ -132,7 +132,7 @@ impl Default for InitTxArgs {
|
||||
}
|
||||
|
||||
/// V2 Issue Invoice Tx Args
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
#[derive(Clone, Serialize, Deserialize, Default)]
|
||||
pub struct IssueInvoiceTxArgs {
|
||||
/// The human readable account name to which the received funds should be added
|
||||
/// overriding whatever the active account is as set via the
|
||||
@@ -147,16 +147,6 @@ pub struct IssueInvoiceTxArgs {
|
||||
pub target_slate_version: Option<u16>,
|
||||
}
|
||||
|
||||
impl Default for IssueInvoiceTxArgs {
|
||||
fn default() -> IssueInvoiceTxArgs {
|
||||
IssueInvoiceTxArgs {
|
||||
dest_acct_name: None,
|
||||
amount: 0,
|
||||
target_slate_version: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Sort tx retrieval order
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub enum RetrieveTxQuerySortOrder {
|
||||
|
||||
+15
-18
@@ -77,7 +77,7 @@ where
|
||||
// h(root_key|slate_id|"blind")
|
||||
let mut hasher = Blake2b::new(SECRET_KEY_SIZE);
|
||||
hasher.update(&root_key.0[..]);
|
||||
hasher.update(&slate_id[..]);
|
||||
hasher.update(slate_id);
|
||||
hasher.update(&b"blind"[..]);
|
||||
let blind_xor_key = hasher.finalize();
|
||||
let mut ret_blind = [0; SECRET_KEY_SIZE];
|
||||
@@ -86,7 +86,7 @@ where
|
||||
// h(root_key|slate_id|"nonce")
|
||||
let mut hasher = Blake2b::new(SECRET_KEY_SIZE);
|
||||
hasher.update(&root_key.0[..]);
|
||||
hasher.update(&slate_id[..]);
|
||||
hasher.update(slate_id);
|
||||
hasher.update(&b"nonce"[..]);
|
||||
let nonce_xor_key = hasher.finalize();
|
||||
let mut ret_nonce = [0; SECRET_KEY_SIZE];
|
||||
@@ -172,12 +172,9 @@ where
|
||||
};
|
||||
|
||||
// Set current active account
|
||||
let active = res
|
||||
.acct_path_iter()?
|
||||
.filter(|a| a.current.unwrap_or(false))
|
||||
.collect::<Vec<AcctPathMapping>>();
|
||||
if let Some(a) = active.get(0) {
|
||||
res.active_account = a.clone();
|
||||
let active = res.acct_path_iter()?.find(|a| a.current.unwrap_or(false));
|
||||
if let Some(a) = active {
|
||||
res.active_account = a;
|
||||
}
|
||||
|
||||
Ok(res)
|
||||
@@ -210,7 +207,7 @@ where
|
||||
let root_key = k.derive_key(0, &K::root_key_id(), SwitchCommitmentType::Regular)?;
|
||||
let mut hasher = Blake2b::new(SECRET_KEY_SIZE);
|
||||
hasher.update(&root_key.0[..]);
|
||||
self.master_checksum = Box::new(Some(hasher.finalize()));
|
||||
*self.master_checksum = Some(hasher.finalize());
|
||||
|
||||
let mask_value = {
|
||||
match mask {
|
||||
@@ -220,9 +217,9 @@ where
|
||||
let mask_value = match use_test_rng {
|
||||
true => {
|
||||
let mut test_rng = StepRng::new(1_234_567_890_u64, 1);
|
||||
SecretKey::new(&k.secp(), &mut test_rng)
|
||||
SecretKey::new(k.secp(), &mut test_rng)
|
||||
}
|
||||
false => SecretKey::new(&k.secp(), &mut thread_rng()),
|
||||
false => SecretKey::new(k.secp(), &mut thread_rng()),
|
||||
};
|
||||
k.mask_master_key(&mask_value)?;
|
||||
Some(mask_value)
|
||||
@@ -285,7 +282,7 @@ where
|
||||
} else {*/
|
||||
Ok(Some(
|
||||
self.keychain(keychain_mask)?
|
||||
.commit(amount, &id, SwitchCommitmentType::Regular)?
|
||||
.commit(amount, id, SwitchCommitmentType::Regular)?
|
||||
.0
|
||||
.to_vec()
|
||||
.to_hex(), // TODO: proper support for different switch commitment schemes
|
||||
@@ -452,7 +449,7 @@ where
|
||||
let path_buf = Path::new(&path).to_path_buf();
|
||||
let mut stored_tx = File::create(path_buf)?;
|
||||
let tx_hex = ser::ser_vec(tx, ser::ProtocolVersion(1)).unwrap().to_hex();
|
||||
stored_tx.write_all(&tx_hex.as_bytes())?;
|
||||
stored_tx.write_all(tx_hex.as_bytes())?;
|
||||
stored_tx.sync_all()?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -504,7 +501,7 @@ where
|
||||
let batch = self.db.batch()?;
|
||||
batch
|
||||
.get_ser(Some(DERIV_PREFIX), &parent_key_id.to_bytes(), None)?
|
||||
.unwrap_or_else(|| 0)
|
||||
.unwrap_or(0)
|
||||
};
|
||||
Ok(index)
|
||||
}
|
||||
@@ -516,7 +513,7 @@ where
|
||||
let batch = self.db.batch()?;
|
||||
batch
|
||||
.get_ser(Some(DERIV_PREFIX), &parent_key_id.to_bytes(), None)?
|
||||
.unwrap_or_else(|| 0)
|
||||
.unwrap_or(0)
|
||||
};
|
||||
let mut return_path = parent_key_id.to_path();
|
||||
return_path.depth += 1;
|
||||
@@ -546,7 +543,7 @@ where
|
||||
&parent_key_id.to_bytes(),
|
||||
None,
|
||||
)?
|
||||
.unwrap_or_else(|| 0);
|
||||
.unwrap_or(0);
|
||||
Ok(last_confirmed_height)
|
||||
}
|
||||
|
||||
@@ -573,7 +570,7 @@ where
|
||||
WALLET_INIT_STATUS_KEY.as_bytes(),
|
||||
None,
|
||||
)?
|
||||
.unwrap_or_else(|| WalletInitStatus::InitComplete);
|
||||
.unwrap_or(WalletInitStatus::InitComplete);
|
||||
Ok(status)
|
||||
}
|
||||
}
|
||||
@@ -693,7 +690,7 @@ where
|
||||
let last_tx_log_id = self
|
||||
.db
|
||||
.get_ser(Some(TX_LOG_ID_PREFIX), &parent_key_id.to_bytes(), None)?
|
||||
.unwrap_or_else(|| 0);
|
||||
.unwrap_or(0);
|
||||
self.db.put_ser(
|
||||
Some(TX_LOG_ID_PREFIX),
|
||||
&parent_key_id.to_bytes(),
|
||||
|
||||
@@ -14,12 +14,10 @@
|
||||
|
||||
//! Error types for libwallet
|
||||
|
||||
use crate::grin_core::core::{amount_to_hr_string, committed, transaction};
|
||||
use crate::grin_core::libtx;
|
||||
use crate::grin_keychain;
|
||||
use crate::grin_util::secp;
|
||||
use crate::util;
|
||||
use grin_store;
|
||||
use grin_core::core::{amount_to_hr_string, committed, transaction};
|
||||
use grin_core::libtx;
|
||||
use grin_util::secp;
|
||||
|
||||
/// Wallet errors, mostly wrappers around underlying crypto or I/O errors.
|
||||
#[derive(Clone, Eq, PartialEq, Debug, thiserror::Error, Serialize, Deserialize)]
|
||||
@@ -95,7 +93,7 @@ pub enum Error {
|
||||
|
||||
/// Other serialization errors
|
||||
#[error("Ser/Deserialization error")]
|
||||
Deser(crate::grin_core::ser::Error),
|
||||
Deser(grin_core::ser::Error),
|
||||
|
||||
/// IO Error
|
||||
#[error("I/O error {0}")]
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
|
||||
//! Wallet key management functions
|
||||
use crate::error::Error;
|
||||
use crate::grin_keychain::{ChildNumber, ExtKeychain, Identifier, Keychain};
|
||||
use crate::grin_util::secp::key::SecretKey;
|
||||
use crate::types::{AcctPathMapping, NodeClient};
|
||||
use crate::WalletBackend;
|
||||
use grin_keychain::{ChildNumber, ExtKeychain, Identifier, Keychain};
|
||||
use grin_util::secp::key::SecretKey;
|
||||
|
||||
/// Get next available key in the wallet for a given parent
|
||||
pub fn next_available_key<C, K>(
|
||||
|
||||
@@ -14,44 +14,34 @@
|
||||
//! Functions to restore a wallet's outputs from just the master seed
|
||||
|
||||
use crate::api_impl::owner_updater::StatusMessage;
|
||||
use crate::grin_core::consensus::{valid_header_version, WEEK_HEIGHT};
|
||||
use crate::grin_core::core::HeaderVersion;
|
||||
use crate::grin_core::global;
|
||||
use crate::grin_core::libtx::proof;
|
||||
use crate::grin_keychain::{Identifier, Keychain, SwitchCommitmentType};
|
||||
use crate::grin_util::secp::key::SecretKey;
|
||||
use crate::grin_util::secp::pedersen;
|
||||
use crate::grin_util::secp::{ContextFlag, Secp256k1};
|
||||
use crate::grin_util::Mutex;
|
||||
use crate::grin_util::{from_hex, ToHex};
|
||||
use crate::internal::{keys, updater};
|
||||
use crate::types::*;
|
||||
use crate::{wallet_lock, Error, OutputCommitMapping};
|
||||
use blake2_rfc::blake2b::blake2b;
|
||||
use grin_core::consensus::{valid_header_version, WEEK_HEIGHT};
|
||||
use grin_core::core::HeaderVersion;
|
||||
use grin_core::global;
|
||||
use grin_core::libtx::proof;
|
||||
use grin_keychain::{Identifier, Keychain, SwitchCommitmentType};
|
||||
use grin_util::secp::key::SecretKey;
|
||||
use grin_util::secp::pedersen;
|
||||
use grin_util::secp::{ContextFlag, Secp256k1};
|
||||
use grin_util::{from_hex, ToHex};
|
||||
use rayon::prelude::*;
|
||||
use std::cmp;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::mpsc::Sender;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Utility struct for return values from below
|
||||
#[derive(Debug, Clone)]
|
||||
struct OutputResult {
|
||||
///
|
||||
pub commit: pedersen::Commitment,
|
||||
///
|
||||
pub key_id: Identifier,
|
||||
///
|
||||
pub n_child: u32,
|
||||
///
|
||||
pub mmr_index: u64,
|
||||
///
|
||||
pub value: u64,
|
||||
///
|
||||
pub height: u64,
|
||||
///
|
||||
pub lock_height: u64,
|
||||
///
|
||||
pub is_coinbase: bool,
|
||||
}
|
||||
|
||||
@@ -293,7 +283,7 @@ where
|
||||
const MISSING_OUTPUTS_BATCH_SIZE: usize = 1000;
|
||||
|
||||
fn restore_missing_outputs<'a, L, C, K>(
|
||||
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet_inst: crate::WalletHandle<'a, L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
outputs: Vec<OutputResult>,
|
||||
found_parents: &mut HashMap<Identifier, u32>,
|
||||
@@ -359,9 +349,8 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
///
|
||||
fn cancel_tx_log_entry<'a, L, C, K>(
|
||||
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet_inst: crate::WalletHandle<'a, L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
output: &OutputData,
|
||||
) -> Result<(), Error>
|
||||
@@ -406,7 +395,7 @@ where
|
||||
/// Scan outputs with a given rewind hash view wallet.
|
||||
/// Retrieve all outputs information that belongs to it.
|
||||
pub fn scan_rewind_hash<'a, L, C, K>(
|
||||
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet_inst: crate::WalletHandle<'a, L, C, K>,
|
||||
rewind_hash: String,
|
||||
start_height: u64,
|
||||
end_height: u64,
|
||||
@@ -463,8 +452,9 @@ where
|
||||
/// The returned `ScannedBlockInfo` is the progress marker to persist after the
|
||||
/// batch. The returned PMMR range can be passed into the next batch to avoid
|
||||
/// looking up the full range again.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn scan<'a, L, C, K>(
|
||||
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet_inst: crate::WalletHandle<'a, L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
delete_unconfirmed: bool,
|
||||
batch_start_height: u64,
|
||||
@@ -642,7 +632,7 @@ where
|
||||
keys::set_acct_path(w, keychain_mask, &label, path)?;
|
||||
acct_index += 1;
|
||||
}
|
||||
let current_child_index = w.current_child_index(&path)?;
|
||||
let current_child_index = w.current_child_index(path)?;
|
||||
if *max_child_index >= current_child_index {
|
||||
let mut batch = w.batch(keychain_mask)?;
|
||||
debug!("Next child for account {} is {}", path, max_child_index + 1);
|
||||
|
||||
@@ -15,22 +15,22 @@
|
||||
//! Selection of inputs for building transactions
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::grin_core::core::amount_to_hr_string;
|
||||
use crate::grin_core::libtx::{
|
||||
build,
|
||||
proof::{ProofBuild, ProofBuilder},
|
||||
tx_fee,
|
||||
};
|
||||
use crate::grin_keychain::{Identifier, Keychain};
|
||||
use crate::grin_util::secp::key::SecretKey;
|
||||
use crate::grin_util::secp::pedersen;
|
||||
use crate::internal::keys;
|
||||
use crate::slate::Slate;
|
||||
use crate::types::*;
|
||||
use crate::util::OnionV3Address;
|
||||
use crate::{address, WalletBackend};
|
||||
use grin_core::core::amount_to_hr_string;
|
||||
use grin_core::core::Transaction;
|
||||
use grin_core::global;
|
||||
use grin_core::libtx::{
|
||||
build,
|
||||
proof::{ProofBuild, ProofBuilder},
|
||||
tx_fee,
|
||||
};
|
||||
use grin_keychain::{Identifier, Keychain};
|
||||
use grin_util::secp::key::SecretKey;
|
||||
use grin_util::secp::pedersen;
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryInto;
|
||||
|
||||
@@ -38,7 +38,7 @@ use std::convert::TryInto;
|
||||
/// libwallet transaction slate with the appropriate inputs selected,
|
||||
/// and saves the private wallet identifiers of our selected outputs
|
||||
/// into our transaction context
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn build_send_tx<C, K>(
|
||||
wallet: &mut WalletBackend<C, K>,
|
||||
keychain: &K,
|
||||
@@ -109,7 +109,7 @@ where
|
||||
|
||||
// Store change output(s)
|
||||
for (change_amount, id, mmr_index) in &change_amounts_derivations {
|
||||
context.add_output(&id, &mmr_index, *change_amount);
|
||||
context.add_output(id, mmr_index, *change_amount);
|
||||
}
|
||||
|
||||
Ok(context)
|
||||
@@ -136,7 +136,7 @@ where
|
||||
output_commits.insert(
|
||||
id.clone(),
|
||||
(
|
||||
wallet.calc_commit_for_cache(keychain_mask, *change_amount, &id)?,
|
||||
wallet.calc_commit_for_cache(keychain_mask, *change_amount, id)?,
|
||||
*change_amount,
|
||||
),
|
||||
);
|
||||
@@ -191,8 +191,7 @@ where
|
||||
None => {
|
||||
return Err(Error::PaymentProof(
|
||||
"Payment proof derivation index required".to_owned(),
|
||||
)
|
||||
.into());
|
||||
));
|
||||
}
|
||||
};
|
||||
let sender_key = address::address_from_derivation_path(
|
||||
@@ -213,7 +212,7 @@ where
|
||||
// write the output representing our change
|
||||
for (id, _, _) in &context.get_outputs() {
|
||||
t.num_outputs += 1;
|
||||
let (commit, change_amount) = output_commits.get(&id).unwrap().clone();
|
||||
let (commit, change_amount) = output_commits.get(id).unwrap().clone();
|
||||
t.amount_credited += change_amount;
|
||||
batch.save(OutputData {
|
||||
root_key_id: parent_key_id.clone(),
|
||||
@@ -315,6 +314,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.
|
||||
#[allow(clippy::too_many_arguments, clippy::type_complexity)]
|
||||
pub fn select_send_tx<C, K, B>(
|
||||
wallet: &mut WalletBackend<C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
@@ -350,7 +350,7 @@ where
|
||||
max_outputs,
|
||||
change_outputs,
|
||||
selection_strategy_is_use_all,
|
||||
&parent_key_id,
|
||||
parent_key_id,
|
||||
)?;
|
||||
|
||||
// build transaction skeleton with inputs and change
|
||||
@@ -368,6 +368,7 @@ where
|
||||
}
|
||||
|
||||
/// Select outputs and calculating fee.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn select_coins_and_fee<C, K>(
|
||||
wallet: &mut WalletBackend<C, K>,
|
||||
amount: u64,
|
||||
@@ -569,6 +570,7 @@ where
|
||||
}
|
||||
|
||||
/// Selects inputs and change for a transaction
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub fn inputs_and_change<C, K, B>(
|
||||
coins: &[OutputData],
|
||||
wallet: &mut WalletBackend<C, K>,
|
||||
@@ -758,7 +760,7 @@ where
|
||||
let keychain = wallet.keychain(keychain_mask)?;
|
||||
|
||||
// restore my signature data
|
||||
slate.add_participant_info(&keychain, &context, None)?;
|
||||
slate.add_participant_info(&keychain, context, None)?;
|
||||
|
||||
let mut parts = vec![];
|
||||
for (id, mmr_index, value) in &context.get_inputs() {
|
||||
|
||||
@@ -18,11 +18,6 @@ use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
|
||||
use std::io::Cursor;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::grin_core::consensus::header_version;
|
||||
use crate::grin_keychain::{Identifier, Keychain};
|
||||
use crate::grin_util::secp::key::SecretKey;
|
||||
use crate::grin_util::secp::pedersen;
|
||||
use crate::grin_util::Mutex;
|
||||
use crate::internal::{selection, updater};
|
||||
use crate::slate::Slate;
|
||||
use crate::types::{Context, NodeClient, StoredProofInfo, TxLogEntryType};
|
||||
@@ -33,7 +28,12 @@ use ed25519_dalek::Signature as DalekSignature;
|
||||
use ed25519_dalek::SigningKey as DalekSecretKey;
|
||||
use ed25519_dalek::VerifyingKey as DalekPublicKey;
|
||||
use ed25519_dalek::{Signer, Verifier};
|
||||
use grin_core::consensus::header_version;
|
||||
use grin_core::core::FeeFields;
|
||||
use grin_keychain::{Identifier, Keychain};
|
||||
use grin_util::secp::key::SecretKey;
|
||||
use grin_util::secp::pedersen;
|
||||
use grin_util::Mutex;
|
||||
|
||||
// static for incrementing test UUIDs
|
||||
lazy_static! {
|
||||
@@ -79,6 +79,7 @@ where
|
||||
}
|
||||
|
||||
/// Estimates locked amount and fee for the transaction without creating one
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn estimate_send_tx<C, K>(
|
||||
wallet: &mut WalletBackend<C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
@@ -130,6 +131,7 @@ where
|
||||
}
|
||||
|
||||
/// Add inputs to the slate (effectively becoming the sender)
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn add_inputs_to_slate<C, K>(
|
||||
wallet: &mut WalletBackend<C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
@@ -234,7 +236,7 @@ where
|
||||
// update excess in stored transaction
|
||||
let mut batch = wallet.batch(keychain_mask)?;
|
||||
tx.kernel_excess = Some(slate.calc_excess(keychain.secp())?);
|
||||
batch.save_tx_log_entry(tx.clone(), &parent_key_id)?;
|
||||
batch.save_tx_log_entry(tx, parent_key_id)?;
|
||||
batch.commit()?;
|
||||
}
|
||||
|
||||
@@ -271,14 +273,14 @@ where
|
||||
init_tx_args.max_outputs as usize,
|
||||
init_tx_args.num_change_outputs as usize,
|
||||
init_tx_args.selection_strategy_is_use_all,
|
||||
&parent_key_id,
|
||||
parent_key_id,
|
||||
)?;
|
||||
slate.fee_fields = FeeFields::new(0, fee)?;
|
||||
|
||||
let keychain = wallet.keychain(keychain_mask)?;
|
||||
|
||||
// Create our own private context
|
||||
let mut context = Context::new(keychain.secp(), &parent_key_id, use_test_rng, true);
|
||||
let mut context = Context::new(keychain.secp(), parent_key_id, use_test_rng, true);
|
||||
context.fee = Some(slate.fee_fields);
|
||||
context.amount = slate.amount;
|
||||
context.late_lock_args = Some(init_tx_args.clone());
|
||||
@@ -340,14 +342,8 @@ where
|
||||
} else if let Some(tx_slate_id) = tx_slate_id {
|
||||
tx_id_string = tx_slate_id.to_string();
|
||||
}
|
||||
let tx_vec = updater::retrieve_txs(
|
||||
wallet,
|
||||
tx_id,
|
||||
tx_slate_id,
|
||||
None,
|
||||
Some(&parent_key_id),
|
||||
false,
|
||||
)?;
|
||||
let tx_vec =
|
||||
updater::retrieve_txs(wallet, tx_id, tx_slate_id, None, Some(parent_key_id), false)?;
|
||||
if tx_vec.len() != 1 {
|
||||
return Err(Error::TransactionDoesntExist(tx_id_string));
|
||||
}
|
||||
@@ -365,7 +361,7 @@ where
|
||||
keychain_mask,
|
||||
false,
|
||||
Some(tx.id),
|
||||
Some(&parent_key_id),
|
||||
Some(parent_key_id),
|
||||
)?;
|
||||
let outputs = res.iter().map(|m| m.output.clone()).collect();
|
||||
updater::cancel_tx_and_outputs(wallet, keychain_mask, tx, outputs, parent_key_id)?;
|
||||
@@ -409,7 +405,7 @@ where
|
||||
}
|
||||
|
||||
if let Some(ref p) = slate.clone().payment_proof {
|
||||
let derivation_index = context.payment_proof_derivation_index.unwrap_or_else(|| 0);
|
||||
let derivation_index = context.payment_proof_derivation_index.unwrap_or(0);
|
||||
let keychain = wallet.keychain(keychain_mask)?;
|
||||
let parent_key_id = wallet.parent_key_id();
|
||||
let excess = slate.calc_excess(keychain.secp())?;
|
||||
@@ -453,12 +449,12 @@ pub fn _decode_payment_proof_message(
|
||||
let mut rdr = Cursor::new(msg);
|
||||
let amount = rdr.read_u64::<BigEndian>()?;
|
||||
let mut commit_bytes = [0u8; 33];
|
||||
for i in 0..33 {
|
||||
commit_bytes[i] = rdr.read_u8()?;
|
||||
for byte in &mut commit_bytes {
|
||||
*byte = rdr.read_u8()?;
|
||||
}
|
||||
let mut sender_address_bytes = [0u8; 32];
|
||||
for i in 0..32 {
|
||||
sender_address_bytes[i] = rdr.read_u8()?;
|
||||
for byte in &mut sender_address_bytes {
|
||||
*byte = rdr.read_u8()?;
|
||||
}
|
||||
|
||||
Ok((
|
||||
@@ -548,7 +544,7 @@ where
|
||||
}
|
||||
let msg = payment_proof_message(
|
||||
slate.amount,
|
||||
&slate.calc_excess(&keychain.secp())?,
|
||||
&slate.calc_excess(keychain.secp())?,
|
||||
orig_sender_address.to_ed25519()?,
|
||||
)?;
|
||||
let sig = match p.receiver_signature {
|
||||
@@ -572,12 +568,12 @@ mod test {
|
||||
use super::*;
|
||||
use rand::rngs::mock::StepRng;
|
||||
|
||||
use crate::grin_core::core::{FeeFields, KernelFeatures};
|
||||
use crate::grin_core::libtx::{build, ProofBuilder};
|
||||
use crate::grin_keychain::{
|
||||
use grin_core::core::{FeeFields, KernelFeatures};
|
||||
use grin_core::libtx::{build, ProofBuilder};
|
||||
use grin_keychain::{
|
||||
BlindSum, BlindingFactor, ExtKeychain, ExtKeychainPath, Keychain, SwitchCommitmentType,
|
||||
};
|
||||
use crate::grin_util::{secp, static_secp_instance};
|
||||
use grin_util::{secp, static_secp_instance};
|
||||
|
||||
#[test]
|
||||
// demonstrate that input.commitment == referenced output.commitment
|
||||
@@ -637,7 +633,7 @@ mod test {
|
||||
.unwrap();
|
||||
keychain
|
||||
.secp()
|
||||
.commit(0, blinding_factor.secret_key(&keychain.secp()).unwrap())
|
||||
.commit(0, blinding_factor.secret_key(keychain.secp()).unwrap())
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
|
||||
@@ -19,22 +19,23 @@ use std::collections::{HashMap, HashSet};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::grin_core::consensus::reward;
|
||||
use crate::grin_core::core::{Output, TxKernel};
|
||||
use crate::grin_core::global;
|
||||
use crate::grin_core::libtx::proof::ProofBuilder;
|
||||
use crate::grin_core::libtx::reward;
|
||||
use crate::grin_keychain::{Identifier, Keychain, SwitchCommitmentType};
|
||||
use crate::grin_util::secp::key::SecretKey;
|
||||
use crate::grin_util::secp::pedersen;
|
||||
use crate::grin_util::static_secp_instance;
|
||||
use crate::internal::keys;
|
||||
use crate::types::{NodeClient, OutputData, OutputStatus, TxLogEntry, TxLogEntryType, WalletInfo};
|
||||
use crate::{grin_util as util, AcctPathMapping};
|
||||
use crate::AcctPathMapping;
|
||||
use crate::{
|
||||
BlockFees, CbData, OutputCommitMapping, RetrieveTxQueryArgs, RetrieveTxQuerySortField,
|
||||
RetrieveTxQuerySortOrder, WalletBackend,
|
||||
};
|
||||
use grin_core::consensus::reward;
|
||||
use grin_core::core::{Output, TxKernel};
|
||||
use grin_core::global;
|
||||
use grin_core::libtx::proof::ProofBuilder;
|
||||
use grin_core::libtx::reward;
|
||||
use grin_keychain::{Identifier, Keychain, SwitchCommitmentType};
|
||||
use grin_util as util;
|
||||
use grin_util::secp::key::SecretKey;
|
||||
use grin_util::secp::pedersen;
|
||||
use grin_util::static_secp_instance;
|
||||
|
||||
use num_bigint::BigInt;
|
||||
|
||||
@@ -319,11 +320,8 @@ where
|
||||
return_txs.sort_by_key(|tx| tx.id);
|
||||
}
|
||||
|
||||
if let Some(ref s) = query_args.sort_order {
|
||||
match s {
|
||||
RetrieveTxQuerySortOrder::Desc => return_txs.reverse(),
|
||||
_ => {}
|
||||
}
|
||||
if let Some(RetrieveTxQuerySortOrder::Desc) = query_args.sort_order {
|
||||
return_txs.reverse();
|
||||
}
|
||||
|
||||
// Apply limit if requested
|
||||
@@ -351,8 +349,8 @@ where
|
||||
let mut txs;
|
||||
// Adding in new transaction list query logic. If `tx_id` or `tx_slate_id`
|
||||
// is provided, then `query_args` is ignored and old logic is followed.
|
||||
if query_args.is_some() && tx_id.is_none() && tx_slate_id.is_none() {
|
||||
txs = apply_advanced_tx_list_filtering(wallet, parent_key_id, &query_args.unwrap())?
|
||||
if let Some(query_args) = query_args.filter(|_| tx_id.is_none() && tx_slate_id.is_none()) {
|
||||
txs = apply_advanced_tx_list_filtering(wallet, parent_key_id, &query_args)?
|
||||
} else {
|
||||
let mut bad_records = 0;
|
||||
txs = wallet
|
||||
@@ -424,6 +422,7 @@ where
|
||||
/// transactions for the account and outputs without a transaction log entry.
|
||||
/// Returns mapping of output commit to tuple of derived key for output,
|
||||
/// PMMR index, tx entry log identifier and check if output is unspent
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub fn map_wallet_outputs<C, K>(
|
||||
wallet: &mut WalletBackend<C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
@@ -441,7 +440,7 @@ where
|
||||
.filter(|x| x.root_key_id == *parent_key_id && x.status != OutputStatus::Spent)
|
||||
.collect();
|
||||
|
||||
let tx_entries = retrieve_txs(wallet, None, None, None, Some(&parent_key_id), true)?;
|
||||
let tx_entries = retrieve_txs(wallet, None, None, None, Some(parent_key_id), true)?;
|
||||
|
||||
// Only select outputs that are actually involved in an outstanding transaction
|
||||
let unspents = match update_all {
|
||||
@@ -510,6 +509,7 @@ where
|
||||
}
|
||||
|
||||
/// Apply refreshed API output data to the wallet
|
||||
#[allow(clippy::type_complexity)]
|
||||
fn apply_api_outputs<C, K>(
|
||||
wallet: &mut WalletBackend<C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
@@ -541,7 +541,7 @@ where
|
||||
let mut batch = wallet.batch(keychain_mask)?;
|
||||
for (commit, (id, mmr_index, _, _)) in wallet_outputs.iter() {
|
||||
if let Ok(mut output) = batch.get(id, mmr_index) {
|
||||
match api_outputs.get(&commit) {
|
||||
match api_outputs.get(commit) {
|
||||
Some(o) => {
|
||||
// if this is a coinbase tx being confirmed, it's recordable in tx log
|
||||
if output.is_coinbase && output.status == OutputStatus::Unconfirmed {
|
||||
@@ -566,7 +566,7 @@ where
|
||||
}
|
||||
t.update_confirmation_ts();
|
||||
output.tx_log_entry = Some(log_id);
|
||||
batch.save_tx_log_entry(t, &parent_key_id)?;
|
||||
batch.save_tx_log_entry(t, parent_key_id)?;
|
||||
}
|
||||
// also mark the transaction in which this output is involved as confirmed
|
||||
// note that one involved input/output confirmation SHOULD be enough
|
||||
@@ -575,14 +575,10 @@ where
|
||||
&& (output.status == OutputStatus::Unconfirmed
|
||||
|| output.status == OutputStatus::Reverted)
|
||||
{
|
||||
let tx = batch
|
||||
.tx_log_iter()?
|
||||
.filter(|t| t.is_ok())
|
||||
.map(|t| t.unwrap())
|
||||
.find(|t| {
|
||||
Some(t.id) == output.tx_log_entry
|
||||
&& t.parent_key_id == *parent_key_id
|
||||
});
|
||||
let tx = batch.tx_log_iter()?.flatten().find(|t| {
|
||||
Some(t.id) == output.tx_log_entry
|
||||
&& t.parent_key_id == *parent_key_id
|
||||
});
|
||||
if let Some(mut t) = tx {
|
||||
if t.tx_type == TxLogEntryType::TxReverted {
|
||||
t.tx_type = TxLogEntryType::TxReceived;
|
||||
@@ -590,7 +586,7 @@ where
|
||||
}
|
||||
t.update_confirmation_ts();
|
||||
t.confirmed = true;
|
||||
batch.save_tx_log_entry(t, &parent_key_id)?;
|
||||
batch.save_tx_log_entry(t, parent_key_id)?;
|
||||
} else {
|
||||
if let Some(tx_id) = output.tx_log_entry {
|
||||
error!("apply_api_outputs: tx with id {:?} not found", tx_id);
|
||||
@@ -631,7 +627,7 @@ where
|
||||
{
|
||||
if reverted_kernels.contains(&tx.id) && tx.parent_key_id == *parent_key_id {
|
||||
tx.tx_type = TxLogEntryType::TxReverted;
|
||||
tx.reverted_after = tx.confirmation_ts.clone().and_then(|t| {
|
||||
tx.reverted_after = tx.confirmation_ts.and_then(|t| {
|
||||
let now = chrono::Utc::now();
|
||||
(now - t).to_std().ok()
|
||||
});
|
||||
@@ -648,7 +644,7 @@ where
|
||||
}
|
||||
|
||||
for tx in txs_to_save {
|
||||
batch.save_tx_log_entry(tx, &parent_key_id)?;
|
||||
batch.save_tx_log_entry(tx, parent_key_id)?;
|
||||
}
|
||||
|
||||
{
|
||||
@@ -702,6 +698,7 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
fn find_reverted_kernels<C, K>(
|
||||
wallet: &mut WalletBackend<C, K>,
|
||||
wallet_outputs: &HashMap<pedersen::Commitment, (Identifier, Option<u64>, Option<u32>, bool)>,
|
||||
@@ -885,7 +882,7 @@ where
|
||||
let outputs = wallet
|
||||
.iter()?
|
||||
.filter(|out| out.root_key_id == *parent_key_id);
|
||||
let current_height = wallet.last_confirmed_height_for_parent(&parent_key_id)?;
|
||||
let current_height = wallet.last_confirmed_height_for_parent(parent_key_id)?;
|
||||
let info = account_outputs_info(outputs, current_height, minimum_confirmations)?;
|
||||
Ok(info)
|
||||
}
|
||||
|
||||
@@ -24,10 +24,6 @@
|
||||
|
||||
use grin_wallet_config as config;
|
||||
|
||||
use grin_core;
|
||||
use grin_keychain;
|
||||
use grin_util;
|
||||
|
||||
use grin_wallet_util as util;
|
||||
|
||||
use blake2_rfc as blake2;
|
||||
@@ -82,6 +78,10 @@ pub use types::{
|
||||
ViewWallet, WalletInfo, WalletInitStatus, WalletInst, WalletLCProvider,
|
||||
};
|
||||
|
||||
/// Shared wallet handle for APIs and workers
|
||||
pub type WalletHandle<'a, L, C, K> =
|
||||
std::sync::Arc<grin_util::Mutex<Box<dyn WalletInst<'a, L, C, K>>>>;
|
||||
|
||||
/// Helper for taking a lock on the wallet instance
|
||||
#[macro_export]
|
||||
macro_rules! wallet_lock {
|
||||
|
||||
@@ -63,7 +63,7 @@ impl ComSignature {
|
||||
pub fn sign(
|
||||
amount: u64,
|
||||
blind: &SecretKey,
|
||||
msg: &Vec<u8>,
|
||||
msg: &[u8],
|
||||
use_test_rng: bool,
|
||||
) -> Result<ComSignature, ComSigError> {
|
||||
let secp = Secp256k1::with_caps(ContextFlag::Commit);
|
||||
@@ -87,13 +87,8 @@ impl ComSignature {
|
||||
let commitment = secp.commit(amount, blind.clone())?;
|
||||
let nonce_commitment = secp.commit_blind(k_1.clone(), k_2.clone())?;
|
||||
|
||||
let e = ComSignature::calc_challenge(
|
||||
&secp,
|
||||
&commitment,
|
||||
&nonce_commitment,
|
||||
&msg,
|
||||
use_test_rng,
|
||||
)?;
|
||||
let e =
|
||||
ComSignature::calc_challenge(&secp, &commitment, &nonce_commitment, msg, use_test_rng)?;
|
||||
|
||||
// s = k_1 + (e * amount)
|
||||
let mut s = k_amt.clone();
|
||||
@@ -109,16 +104,16 @@ impl ComSignature {
|
||||
}
|
||||
|
||||
/// Verify the commitment signature
|
||||
pub fn verify(&self, commit: &Commitment, msg: &Vec<u8>) -> Result<(), ComSigError> {
|
||||
pub fn verify(&self, commit: &Commitment, msg: &[u8]) -> Result<(), ComSigError> {
|
||||
let secp = Secp256k1::with_caps(ContextFlag::Commit);
|
||||
|
||||
let s1 = secp.commit_blind(self.s.clone(), self.t.clone())?;
|
||||
|
||||
let mut ce = commit.to_pubkey(&secp)?;
|
||||
let e = ComSignature::calc_challenge(&secp, &commit, &self.pub_nonce, &msg, false)?;
|
||||
let e = ComSignature::calc_challenge(&secp, commit, &self.pub_nonce, msg, false)?;
|
||||
ce.mul_assign(&secp, &e)?;
|
||||
|
||||
let commits = vec![Commitment::from_pubkey(&secp, &ce)?, self.pub_nonce.clone()];
|
||||
let commits = vec![Commitment::from_pubkey(&secp, &ce)?, self.pub_nonce];
|
||||
let s2 = secp.commit_sum(commits, Vec::new())?;
|
||||
|
||||
if s1 != s2 {
|
||||
@@ -132,7 +127,7 @@ impl ComSignature {
|
||||
secp: &Secp256k1,
|
||||
commit: &Commitment,
|
||||
nonce_commit: &Commitment,
|
||||
msg: &Vec<u8>,
|
||||
msg: &[u8],
|
||||
use_test_rng: bool,
|
||||
) -> Result<SecretKey, ComSigError> {
|
||||
let mut challenge_hasher = Blake2b::new(32);
|
||||
@@ -146,7 +141,7 @@ impl ComSignature {
|
||||
let mut challenge = [0; 32];
|
||||
challenge.copy_from_slice(challenge_hasher.finalize().as_bytes());
|
||||
|
||||
Ok(SecretKey::from_slice(&secp, &challenge)?)
|
||||
Ok(SecretKey::from_slice(secp, &challenge)?)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,16 +208,16 @@ mod tests {
|
||||
let amount = thread_rng().next_u64();
|
||||
let blind = SecretKey::new(&secp, &mut thread_rng());
|
||||
let msg: [u8; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
|
||||
let comsig = ComSignature::sign(amount, &blind, &msg.to_vec(), false)?;
|
||||
let comsig = ComSignature::sign(amount, &blind, msg.as_ref(), false)?;
|
||||
|
||||
let commit = secp.commit(amount, blind.clone())?;
|
||||
assert!(comsig.verify(&commit, &msg.to_vec()).is_ok());
|
||||
assert!(comsig.verify(&commit, msg.as_ref()).is_ok());
|
||||
|
||||
let wrong_msg: [u8; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17];
|
||||
assert!(comsig.verify(&commit, &wrong_msg.to_vec()).is_err());
|
||||
assert!(comsig.verify(&commit, wrong_msg.as_ref()).is_err());
|
||||
|
||||
let wrong_commit = secp.commit(amount, SecretKey::new(&secp, &mut thread_rng()))?;
|
||||
assert!(comsig.verify(&wrong_commit, &msg.to_vec()).is_err());
|
||||
assert!(comsig.verify(&wrong_commit, msg.as_ref()).is_err());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ pub mod option_dalek_pubkey_serde {
|
||||
use serde::de::Error;
|
||||
use serde::{Deserialize, Deserializer, Serializer};
|
||||
|
||||
///
|
||||
/// Write the Ed25519 public key as hex, or null
|
||||
pub fn serialize<S>(pk: &Option<DalekPublicKey>, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
@@ -87,7 +87,7 @@ pub mod option_dalek_pubkey_serde {
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Read an optional Ed25519 public key from hex
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<DalekPublicKey>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
@@ -95,7 +95,7 @@ pub mod option_dalek_pubkey_serde {
|
||||
Option::<String>::deserialize(deserializer).and_then(|res| match res {
|
||||
Some(string) => DalekPublicKey::from_hex(&string)
|
||||
.map_err(|e| Error::custom(e.to_string()))
|
||||
.and_then(|pk: DalekPublicKey| Ok(Some(pk))),
|
||||
.map(|pk: DalekPublicKey| Some(pk)),
|
||||
None => Ok(None),
|
||||
})
|
||||
}
|
||||
@@ -130,8 +130,7 @@ impl DalekSignature {
|
||||
.map_err(|_| DalekError::HexError(format!("failed to decode {}", hex)))?;
|
||||
let b = <[u8; 64]>::try_from(bytes.as_slice())
|
||||
.map_err(|_| DalekError::HexError(format!("failed to decode {}", hex)))?;
|
||||
let sig = ed25519_dalek::Signature::try_from(b)
|
||||
.map_err(|_| DalekError::HexError(format!("failed to decode {}", hex)))?;
|
||||
let sig = ed25519_dalek::Signature::from(b);
|
||||
Ok(DalekSignature(sig))
|
||||
}
|
||||
|
||||
@@ -139,7 +138,7 @@ impl DalekSignature {
|
||||
#[allow(dead_code)]
|
||||
pub fn verify(&self, pk: &DalekPublicKey, msg: &[u8]) -> Result<(), DalekError> {
|
||||
pk.as_ref()
|
||||
.verify(&msg, &self.0)
|
||||
.verify(msg, &self.0)
|
||||
.map_err(|_| DalekError::SigVerifyFailed)
|
||||
}
|
||||
}
|
||||
@@ -157,7 +156,7 @@ pub mod dalek_sig_serde {
|
||||
use serde::de::Error;
|
||||
use serde::{Deserialize, Deserializer, Serializer};
|
||||
|
||||
///
|
||||
/// Write the Ed25519 signature as hex
|
||||
pub fn serialize<S>(sig: &DalekSignature, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
@@ -165,7 +164,7 @@ pub mod dalek_sig_serde {
|
||||
serializer.serialize_str(&sig.0.to_bytes().to_hex())
|
||||
}
|
||||
|
||||
///
|
||||
/// Read an Ed25519 signature from hex
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<DalekSignature, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
@@ -180,7 +179,7 @@ pub mod dalek_sig_serde {
|
||||
pub fn sign(sk: &SecretKey, message: &[u8]) -> Result<DalekSignature, DalekError> {
|
||||
use ed25519_dalek::{Signer, SigningKey};
|
||||
let secret = SigningKey::from_bytes(&sk.0);
|
||||
let sig = secret.sign(&message);
|
||||
let sig = secret.sign(message);
|
||||
Ok(DalekSignature(sig))
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ pub fn add_excess(
|
||||
let secp = Secp256k1::with_caps(ContextFlag::Commit);
|
||||
let excess_commit: Commitment = secp.commit(0, excess.clone())?;
|
||||
|
||||
let commits = vec![commitment.clone(), excess_commit.clone()];
|
||||
let commits = vec![*commitment, excess_commit];
|
||||
let sum = secp.commit_sum(commits, Vec::new())?;
|
||||
Ok(sum)
|
||||
}
|
||||
@@ -70,7 +70,7 @@ pub fn add_excess(
|
||||
pub fn sub_value(commitment: &Commitment, value: u64) -> Result<Commitment, secp256k1zkp::Error> {
|
||||
let secp = Secp256k1::with_caps(ContextFlag::Commit);
|
||||
let neg_commit: Commitment = secp.commit(value, ZERO_KEY)?;
|
||||
let sum = secp.commit_sum(vec![commitment.clone()], vec![neg_commit.clone()])?;
|
||||
let sum = secp.commit_sum(vec![*commitment], vec![neg_commit])?;
|
||||
Ok(sum)
|
||||
}
|
||||
|
||||
@@ -81,11 +81,11 @@ pub fn sign(
|
||||
msg: &grin_util::secp::Message,
|
||||
) -> Result<grin_util::secp::Signature, secp256k1zkp::Error> {
|
||||
let secp = Secp256k1::with_caps(ContextFlag::Full);
|
||||
let pubkey = grin_util::secp::PublicKey::from_secret_key(&secp, &sk)?;
|
||||
let pubkey = grin_util::secp::PublicKey::from_secret_key(&secp, sk)?;
|
||||
let sig = grin_util::secp::aggsig::sign_single(
|
||||
&secp,
|
||||
&msg,
|
||||
&sk,
|
||||
msg,
|
||||
sk,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
//! Onion module definition
|
||||
|
||||
pub mod crypto;
|
||||
#[allow(clippy::module_inception)]
|
||||
pub mod onion;
|
||||
pub mod util;
|
||||
|
||||
@@ -56,9 +57,9 @@ pub fn new_hop(
|
||||
proof: Option<RangeProof>,
|
||||
) -> Hop {
|
||||
Hop {
|
||||
server_pubkey: xPublicKey::from(&StaticSecret::from(server_key.0.clone())),
|
||||
server_pubkey: xPublicKey::from(&StaticSecret::from(server_key.0)),
|
||||
excess: hop_excess.clone(),
|
||||
fee: FeeFields::from(fee as u32),
|
||||
fee: FeeFields::from(fee),
|
||||
rangeproof: proof,
|
||||
}
|
||||
}
|
||||
@@ -66,13 +67,13 @@ pub fn new_hop(
|
||||
/// Create an Onion for the Commitment, encrypting the payload for each hop
|
||||
pub fn create_onion(
|
||||
commitment: &Commitment,
|
||||
hops: &Vec<Hop>,
|
||||
hops: &[Hop],
|
||||
use_test_rng: bool,
|
||||
) -> Result<Onion, OnionError> {
|
||||
if hops.is_empty() {
|
||||
return Ok(Onion {
|
||||
ephemeral_pubkey: xPublicKey::from([0u8; 32]),
|
||||
commit: commitment.clone(),
|
||||
commit: *commitment,
|
||||
enc_payloads: vec![],
|
||||
});
|
||||
}
|
||||
@@ -96,22 +97,22 @@ pub fn create_onion(
|
||||
let payload = Payload {
|
||||
next_ephemeral_pk,
|
||||
excess: hop.excess.clone(),
|
||||
fee: hop.fee.clone(),
|
||||
rangeproof: hop.rangeproof.clone(),
|
||||
fee: hop.fee,
|
||||
rangeproof: hop.rangeproof,
|
||||
};
|
||||
enc_payloads.push(payload.serialize()?);
|
||||
}
|
||||
|
||||
for i in (0..shared_secrets.len()).rev() {
|
||||
let mut cipher = new_stream_cipher(&shared_secrets[i])?;
|
||||
for j in i..shared_secrets.len() {
|
||||
cipher.apply_keystream(&mut enc_payloads[j]);
|
||||
for payload in enc_payloads.iter_mut().skip(i) {
|
||||
cipher.apply_keystream(payload);
|
||||
}
|
||||
}
|
||||
|
||||
let onion = Onion {
|
||||
ephemeral_pubkey: onion_ephemeral_pk,
|
||||
commit: commitment.clone(),
|
||||
commit: *commitment,
|
||||
enc_payloads,
|
||||
};
|
||||
Ok(onion)
|
||||
@@ -182,7 +183,7 @@ pub mod test_util {
|
||||
|
||||
let mut blind = input_blind.clone();
|
||||
for hop_excess in hop_excesses {
|
||||
blind.add_assign(&secp, &hop_excess).unwrap();
|
||||
blind.add_assign(&secp, hop_excess).unwrap();
|
||||
}
|
||||
|
||||
let out_value = value - (fee as u64);
|
||||
|
||||
@@ -94,7 +94,7 @@ pub struct Payload {
|
||||
|
||||
impl Payload {
|
||||
/// Deserialize
|
||||
pub fn deserialize(bytes: &Vec<u8>) -> Result<Payload, ser::Error> {
|
||||
pub fn deserialize(bytes: &[u8]) -> Result<Payload, ser::Error> {
|
||||
let payload: Payload = ser::deserialize_default(&mut &bytes[..])?;
|
||||
Ok(payload)
|
||||
}
|
||||
@@ -131,7 +131,7 @@ impl Readable for Payload {
|
||||
impl Writeable for Payload {
|
||||
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
|
||||
writer.write_u8(CURRENT_ONION_VERSION)?;
|
||||
writer.write_fixed_bytes(&self.next_ephemeral_pk.as_bytes())?;
|
||||
writer.write_fixed_bytes(self.next_ephemeral_pk.as_bytes())?;
|
||||
writer.write_fixed_bytes(&self.excess)?;
|
||||
writer.write_u64(self.fee.into())?;
|
||||
write_optional(writer, &self.rangeproof)?;
|
||||
@@ -163,8 +163,8 @@ impl Onion {
|
||||
|
||||
let mut decrypted_bytes = self.enc_payloads[0].clone();
|
||||
cipher.apply_keystream(&mut decrypted_bytes);
|
||||
let decrypted_payload = Payload::deserialize(&decrypted_bytes)
|
||||
.map_err(|e| OnionError::DeserializationError(e))?;
|
||||
let decrypted_payload =
|
||||
Payload::deserialize(&decrypted_bytes).map_err(OnionError::DeserializationError)?;
|
||||
|
||||
let enc_payloads: Vec<RawBytes> = self
|
||||
.enc_payloads
|
||||
@@ -178,15 +178,15 @@ impl Onion {
|
||||
})
|
||||
.collect();
|
||||
|
||||
let mut commitment = self.commit.clone();
|
||||
let mut commitment = self.commit;
|
||||
commitment = secp::add_excess(&commitment, &decrypted_payload.excess)
|
||||
.map_err(|e| OnionError::CalcCommitError(e))?;
|
||||
.map_err(OnionError::CalcCommitError)?;
|
||||
commitment = secp::sub_value(&commitment, decrypted_payload.fee.into())
|
||||
.map_err(|e| OnionError::CalcCommitError(e))?;
|
||||
.map_err(OnionError::CalcCommitError)?;
|
||||
|
||||
let peeled_onion = Onion {
|
||||
ephemeral_pubkey: decrypted_payload.next_ephemeral_pk,
|
||||
commit: commitment.clone(),
|
||||
commit: commitment,
|
||||
enc_payloads,
|
||||
};
|
||||
Ok(PeeledOnion {
|
||||
@@ -205,13 +205,13 @@ pub fn new_stream_cipher(shared_secret: &SharedSecret) -> Result<ChaCha20, Onion
|
||||
let key = Key::from_slice(&mukey[0..32]);
|
||||
let nonce = Nonce::from_slice(b"NONCE1234567");
|
||||
|
||||
Ok(ChaCha20::new(&key, &nonce))
|
||||
Ok(ChaCha20::new(key, nonce))
|
||||
}
|
||||
|
||||
impl Writeable for Onion {
|
||||
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
|
||||
writer.write_fixed_bytes(self.ephemeral_pubkey.as_bytes())?;
|
||||
writer.write_fixed_bytes(&self.commit)?;
|
||||
writer.write_fixed_bytes(self.commit)?;
|
||||
writer.write_u64(self.enc_payloads.len() as u64)?;
|
||||
for p in &self.enc_payloads {
|
||||
writer.write_u64(p.len() as u64)?;
|
||||
@@ -326,7 +326,7 @@ impl<'de> serde::de::Deserialize<'de> for Onion {
|
||||
}
|
||||
|
||||
const FIELDS: &[&str] = &["pubkey", "commit", "data"];
|
||||
deserializer.deserialize_struct("Onion", &FIELDS, OnionVisitor)
|
||||
deserializer.deserialize_struct("Onion", FIELDS, OnionVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -419,13 +419,13 @@ mod tests {
|
||||
crate::mwixnet::onion::create_onion(&commitment, &hops, false).unwrap();
|
||||
|
||||
let mut payload = Payload {
|
||||
next_ephemeral_pk: onion_packet.ephemeral_pubkey.clone(),
|
||||
next_ephemeral_pk: onion_packet.ephemeral_pubkey,
|
||||
excess: random_secret(false),
|
||||
fee: FeeFields::from(fee_per_hop),
|
||||
rangeproof: None,
|
||||
};
|
||||
for i in 0..5 {
|
||||
let peeled = onion_packet.peel_layer(&keys[i]).unwrap();
|
||||
for key in &keys {
|
||||
let peeled = onion_packet.peel_layer(key).unwrap();
|
||||
payload = peeled.payload;
|
||||
onion_packet = peeled.onion;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ use std::convert::TryInto;
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use grin_wallet_libwallet::mwixnet::onion_util::write_optional;
|
||||
/// use grin_wallet_libwallet::mwixnet::onion_util::write_optional;
|
||||
/// let mut writer:Vec<u8> = vec![];
|
||||
/// let optional_value: Option<u32> = Some(10);
|
||||
/// //write_optional(&mut writer, &optional_value);
|
||||
@@ -75,7 +75,7 @@ pub fn write_optional<O: Writeable, W: Writer>(
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use grin_wallet_libwallet::mwixnet::onion_util::read_optional;
|
||||
/// use grin_wallet_libwallet::mwixnet::onion_util::read_optional;
|
||||
/// use grin_core::ser::{BinReader, ProtocolVersion, DeserializationMode};
|
||||
/// let mut buf: &[u8] = &[1, 0, 0, 0, 10];
|
||||
/// let mut reader = BinReader::new(&mut buf, ProtocolVersion::local(), DeserializationMode::default());
|
||||
@@ -100,18 +100,18 @@ pub fn read_optional<O: Readable, R: Reader>(reader: &mut R) -> Result<Option<O>
|
||||
/// # Returns
|
||||
///
|
||||
/// * If successful, returns an `Ok` wrapping an array of size `S` containing
|
||||
/// the first `S` bytes of `vec`.
|
||||
/// the first `S` bytes of `vec`.
|
||||
/// * If `vec` is smaller than `S`, returns an `Err` indicating a count error.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use grin_wallet_libwallet::mwixnet::onion_util::vec_to_array;
|
||||
/// use grin_wallet_libwallet::mwixnet::onion_util::vec_to_array;
|
||||
/// let v = vec![0, 1, 2, 3, 4, 5];
|
||||
/// let a = vec_to_array::<4>(&v).unwrap();
|
||||
/// assert_eq!(a, [0, 1, 2, 3]);
|
||||
/// ```
|
||||
pub fn vec_to_array<const S: usize>(vec: &Vec<u8>) -> Result<[u8; S], ser::Error> {
|
||||
pub fn vec_to_array<const S: usize>(vec: &[u8]) -> Result<[u8; S], ser::Error> {
|
||||
if vec.len() < S {
|
||||
return Err(ser::Error::CountError);
|
||||
}
|
||||
|
||||
+49
-77
@@ -16,22 +16,21 @@
|
||||
//! around during an interactive wallet exchange
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::grin_core::core::amount_to_hr_string;
|
||||
use crate::grin_core::core::transaction::{
|
||||
use ed25519_dalek::Signature as DalekSignature;
|
||||
use ed25519_dalek::VerifyingKey as DalekPublicKey;
|
||||
use grin_core::core::amount_to_hr_string;
|
||||
use grin_core::core::transaction::{
|
||||
FeeFields, Input, Inputs, KernelFeatures, NRDRelativeHeight, Output, OutputFeatures,
|
||||
Transaction, TxKernel, Weighting,
|
||||
};
|
||||
use crate::grin_core::libtx::{aggsig, build, proof::ProofBuild, tx_fee};
|
||||
use crate::grin_core::map_vec;
|
||||
use crate::grin_keychain::{BlindSum, BlindingFactor, Keychain, SwitchCommitmentType};
|
||||
use crate::grin_util::secp::key::{PublicKey, SecretKey};
|
||||
use crate::grin_util::secp::pedersen::Commitment;
|
||||
use crate::grin_util::secp::Signature;
|
||||
use crate::grin_util::{secp, static_secp_instance};
|
||||
use ed25519_dalek::Signature as DalekSignature;
|
||||
use ed25519_dalek::VerifyingKey as DalekPublicKey;
|
||||
use grin_core::libtx::{aggsig, build, proof::ProofBuild, tx_fee};
|
||||
use grin_core::map_vec;
|
||||
use grin_keychain::{BlindSum, BlindingFactor, Keychain, SwitchCommitmentType};
|
||||
use grin_util::secp::key::{PublicKey, SecretKey};
|
||||
use grin_util::secp::pedersen::Commitment;
|
||||
use grin_util::secp::Signature;
|
||||
use grin_util::{secp, static_secp_instance};
|
||||
use serde::ser::{Serialize, Serializer};
|
||||
use serde_json;
|
||||
use std::fmt;
|
||||
use uuid::Uuid;
|
||||
|
||||
@@ -110,10 +109,10 @@ pub struct Slate {
|
||||
/// associated outputs
|
||||
pub ttl_cutoff_height: u64,
|
||||
/// Kernel Features flag -
|
||||
/// 0: plain
|
||||
/// 1: coinbase (invalid)
|
||||
/// 2: height_locked
|
||||
/// 3: NRD
|
||||
/// 0: plain
|
||||
/// 1: coinbase (invalid)
|
||||
/// 2: height_locked
|
||||
/// 3: NRD
|
||||
pub kernel_features: u8,
|
||||
/// Offset, needed when posting of transaction is deferred
|
||||
pub offset: BlindingFactor,
|
||||
@@ -167,19 +166,13 @@ impl fmt::Display for SlateState {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
/// Kernel features arguments definition
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
||||
pub struct KernelFeaturesArgs {
|
||||
/// Lock height, for HeightLocked (also NRD relative lock height)
|
||||
pub lock_height: u64,
|
||||
}
|
||||
|
||||
impl Default for KernelFeaturesArgs {
|
||||
fn default() -> KernelFeaturesArgs {
|
||||
KernelFeaturesArgs { lock_height: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
/// Versioning and compatibility info about this slate
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct VersionCompatInfo {
|
||||
@@ -226,9 +219,7 @@ impl Slate {
|
||||
|
||||
/// Upgrade a versioned slate
|
||||
pub fn upgrade(v_slate: VersionedSlate) -> Result<Slate, Error> {
|
||||
let v4: SlateV4 = match v_slate {
|
||||
VersionedSlate::V4(s) => s,
|
||||
};
|
||||
let VersionedSlate::V4(v4) = v_slate;
|
||||
Ok(v4.into())
|
||||
}
|
||||
/// Compact the slate for initial sending, storing the excess + offset explicit
|
||||
@@ -287,8 +278,8 @@ impl Slate {
|
||||
where
|
||||
K: Keychain,
|
||||
{
|
||||
let pub_nonce = PublicKey::from_secret_key(keychain.secp(), &sec_nonce)?;
|
||||
let pub_key = PublicKey::from_secret_key(keychain.secp(), &sec_key)?;
|
||||
let pub_nonce = PublicKey::from_secret_key(keychain.secp(), sec_nonce)?;
|
||||
let pub_key = PublicKey::from_secret_key(keychain.secp(), sec_key)?;
|
||||
self.participant_data = self
|
||||
.participant_data
|
||||
.clone()
|
||||
@@ -357,14 +348,14 @@ impl Slate {
|
||||
fee: self.fee_fields,
|
||||
lock_height: match &self.kernel_features_args {
|
||||
Some(a) => a.lock_height,
|
||||
None => return Err(Error::KernelFeaturesMissing(format!("lock_height"))),
|
||||
None => return Err(Error::KernelFeaturesMissing("lock_height".to_string())),
|
||||
},
|
||||
}),
|
||||
3 => Ok(KernelFeatures::NoRecentDuplicate {
|
||||
fee: self.fee_fields,
|
||||
relative_height: match &self.kernel_features_args {
|
||||
Some(a) => NRDRelativeHeight::new(a.lock_height)?,
|
||||
None => return Err(Error::KernelFeaturesMissing(format!("lock_height"))),
|
||||
None => return Err(Error::KernelFeaturesMissing("lock_height".to_string())),
|
||||
},
|
||||
}),
|
||||
n => Err(Error::UnknownKernelFeatures(n)),
|
||||
@@ -400,8 +391,8 @@ impl Slate {
|
||||
Some(&self.pub_blind_sum(keychain.secp())?),
|
||||
&self.msg_to_sign()?,
|
||||
)?;
|
||||
let pub_excess = PublicKey::from_secret_key(keychain.secp(), &sec_key)?;
|
||||
let pub_nonce = PublicKey::from_secret_key(keychain.secp(), &sec_nonce)?;
|
||||
let pub_excess = PublicKey::from_secret_key(keychain.secp(), sec_key)?;
|
||||
let pub_nonce = PublicKey::from_secret_key(keychain.secp(), sec_nonce)?;
|
||||
for i in 0..self.num_participants() as usize {
|
||||
// find my entry
|
||||
if self.participant_data[i].public_blind_excess == pub_excess
|
||||
@@ -431,8 +422,10 @@ impl Slate {
|
||||
.iter()
|
||||
.map(|p| &p.public_nonce)
|
||||
.collect();
|
||||
if pub_nonces.len() == 0 {
|
||||
return Err(Error::Commit(format!("Participant nonces cannot be empty")));
|
||||
if pub_nonces.is_empty() {
|
||||
return Err(Error::Commit(
|
||||
"Participant nonces cannot be empty".to_string(),
|
||||
));
|
||||
}
|
||||
match PublicKey::from_combination(secp, pub_nonces) {
|
||||
Ok(k) => Ok(k),
|
||||
@@ -447,10 +440,10 @@ impl Slate {
|
||||
.iter()
|
||||
.map(|p| &p.public_blind_excess)
|
||||
.collect();
|
||||
if pub_blinds.len() == 0 {
|
||||
return Err(Error::Commit(format!(
|
||||
"Participant Blind sums cannot be empty"
|
||||
)));
|
||||
if pub_blinds.is_empty() {
|
||||
return Err(Error::Commit(
|
||||
"Participant Blind sums cannot be empty".to_string(),
|
||||
));
|
||||
}
|
||||
match PublicKey::from_combination(secp, pub_blinds) {
|
||||
Ok(k) => Ok(k),
|
||||
@@ -462,8 +455,7 @@ impl Slate {
|
||||
fn part_sigs(&self) -> Vec<&Signature> {
|
||||
self.participant_data
|
||||
.iter()
|
||||
.filter(|p| p.part_sig.is_some())
|
||||
.map(|p| p.part_sig.as_ref().unwrap())
|
||||
.filter_map(|p| p.part_sig.as_ref())
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -493,7 +485,7 @@ impl Slate {
|
||||
.filter(|v| {
|
||||
if v.public_nonce == pub_nonce
|
||||
&& v.public_blind_excess == pub_key
|
||||
&& part_sig == None
|
||||
&& part_sig.is_none()
|
||||
{
|
||||
part_sig = v.part_sig
|
||||
}
|
||||
@@ -504,7 +496,7 @@ impl Slate {
|
||||
self.participant_data.push(ParticipantData {
|
||||
public_blind_excess: pub_key,
|
||||
public_nonce: pub_nonce,
|
||||
part_sig: part_sig,
|
||||
part_sig,
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
@@ -603,7 +595,6 @@ impl Slate {
|
||||
/// fee (= M)
|
||||
///
|
||||
/// Returns completed transaction ready for posting to the chain
|
||||
|
||||
fn finalize_signature(&mut self, secp: &secp::Secp256k1) -> Result<Signature, Error> {
|
||||
self.verify_part_sigs(secp)?;
|
||||
|
||||
@@ -655,7 +646,7 @@ impl Slate {
|
||||
|
||||
let mut kernel = final_tx.kernels()[0];
|
||||
kernel.excess = final_excess;
|
||||
kernel.excess_sig = final_sig.clone();
|
||||
kernel.excess_sig = *final_sig;
|
||||
|
||||
let final_tx = final_tx.clone().replace_kernel(kernel);
|
||||
|
||||
@@ -710,16 +701,10 @@ impl From<Slate> for SlateV4 {
|
||||
payment_proof,
|
||||
kernel_features_args,
|
||||
} = slate.clone();
|
||||
let participant_data = map_vec!(participant_data, |data| ParticipantDataV4::from(data));
|
||||
let participant_data = map_vec!(participant_data, ParticipantDataV4::from);
|
||||
let ver = VersionCompatInfoV4::from(&version_info);
|
||||
let payment_proof = match payment_proof {
|
||||
Some(p) => Some(PaymentInfoV4::from(&p)),
|
||||
None => None,
|
||||
};
|
||||
let feat_args = match kernel_features_args {
|
||||
Some(a) => Some(KernelFeaturesArgsV4::from(&a)),
|
||||
None => None,
|
||||
};
|
||||
let payment_proof = payment_proof.map(|p| PaymentInfoV4::from(&p));
|
||||
let feat_args = kernel_features_args.map(|a| KernelFeaturesArgsV4::from(&a));
|
||||
let sta = SlateStateV4::from(&state);
|
||||
SlateV4 {
|
||||
num_parts,
|
||||
@@ -763,17 +748,13 @@ impl From<&Slate> for SlateV4 {
|
||||
let feat = *kernel_features;
|
||||
let ttl = *ttl;
|
||||
let off = offset.clone();
|
||||
let participant_data = map_vec!(participant_data, |data| ParticipantDataV4::from(data));
|
||||
let participant_data = map_vec!(participant_data, ParticipantDataV4::from);
|
||||
let ver = VersionCompatInfoV4::from(version_info);
|
||||
let payment_proof = match payment_proof {
|
||||
Some(p) => Some(PaymentInfoV4::from(p)),
|
||||
None => None,
|
||||
};
|
||||
let payment_proof = payment_proof.as_ref().map(PaymentInfoV4::from);
|
||||
let sta = SlateStateV4::from(state);
|
||||
let feat_args = match kernel_features_args {
|
||||
Some(a) => Some(KernelFeaturesArgsV4::from(a)),
|
||||
None => None,
|
||||
};
|
||||
let feat_args = kernel_features_args
|
||||
.as_ref()
|
||||
.map(KernelFeaturesArgsV4::from);
|
||||
SlateV4 {
|
||||
num_parts,
|
||||
id,
|
||||
@@ -916,16 +897,10 @@ impl From<SlateV4> for Slate {
|
||||
proof: payment_proof,
|
||||
feat_args,
|
||||
} = slate.clone();
|
||||
let participant_data = map_vec!(participant_data, |data| ParticipantData::from(data));
|
||||
let participant_data = map_vec!(participant_data, ParticipantData::from);
|
||||
let version_info = VersionCompatInfo::from(&ver);
|
||||
let payment_proof = match &payment_proof {
|
||||
Some(p) => Some(PaymentInfo::from(p)),
|
||||
None => None,
|
||||
};
|
||||
let kernel_features_args = match &feat_args {
|
||||
Some(a) => Some(KernelFeaturesArgs::from(a)),
|
||||
None => None,
|
||||
};
|
||||
let payment_proof = payment_proof.as_ref().map(PaymentInfo::from);
|
||||
let kernel_features_args = feat_args.as_ref().map(KernelFeaturesArgs::from);
|
||||
let state = SlateState::from(&sta);
|
||||
Slate {
|
||||
num_participants,
|
||||
@@ -946,10 +921,7 @@ impl From<SlateV4> for Slate {
|
||||
}
|
||||
|
||||
pub fn tx_from_slate_v4(slate: &SlateV4) -> Option<Transaction> {
|
||||
let coms = match slate.coms.as_ref() {
|
||||
Some(c) => c,
|
||||
None => return None,
|
||||
};
|
||||
let coms = slate.coms.as_ref()?;
|
||||
let secp = static_secp_instance();
|
||||
let secp = secp.lock();
|
||||
let mut calc_slate = Slate::blank(2, false);
|
||||
@@ -992,7 +964,7 @@ pub fn tx_from_slate_v4(slate: &SlateV4) -> Option<Transaction> {
|
||||
for c in coms.iter() {
|
||||
match &c.p {
|
||||
Some(p) => {
|
||||
outputs.push(Output::new(c.f.into(), c.c, p.clone()));
|
||||
outputs.push(Output::new(c.f.into(), c.c, *p));
|
||||
}
|
||||
None => {
|
||||
inputs.push(Input {
|
||||
@@ -1095,7 +1067,7 @@ impl From<OutputFeaturesV4> for OutputFeatures {
|
||||
fn from(of: OutputFeaturesV4) -> OutputFeatures {
|
||||
match of.0 {
|
||||
1 => OutputFeatures::Coinbase,
|
||||
0 | _ => OutputFeatures::Plain,
|
||||
_ => OutputFeatures::Plain,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,14 +34,14 @@ where
|
||||
.and_then(|string| base64::decode(&string).map_err(|err| Error::custom(err.to_string())))
|
||||
}
|
||||
|
||||
/// Serializes an Option<secp::Signature> to and from hex
|
||||
/// Optional range proof as hex
|
||||
pub mod option_rangeproof_hex {
|
||||
use crate::grin_util::secp::pedersen::RangeProof;
|
||||
use crate::grin_util::{from_hex, ToHex};
|
||||
use grin_util::secp::pedersen::RangeProof;
|
||||
use grin_util::{from_hex, ToHex};
|
||||
use serde::de::{Error, IntoDeserializer};
|
||||
use serde::{Deserialize, Deserializer, Serializer};
|
||||
|
||||
///
|
||||
/// Write the range proof as hex, or null
|
||||
pub fn serialize<S>(proof: &Option<RangeProof>, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
@@ -52,7 +52,7 @@ pub mod option_rangeproof_hex {
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Read an optional range proof from hex
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<RangeProof>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
@@ -66,7 +66,7 @@ pub mod option_rangeproof_hex {
|
||||
}
|
||||
}
|
||||
|
||||
/// Serializes an OnionV3Address to and from hex
|
||||
/// Optional onion address as text
|
||||
pub mod option_ov3_serde {
|
||||
use serde::de::Error;
|
||||
use serde::{Deserialize, Deserializer, Serializer};
|
||||
@@ -74,7 +74,7 @@ pub mod option_ov3_serde {
|
||||
|
||||
use crate::util::{OnionV3Address, OnionV3AddressError};
|
||||
|
||||
///
|
||||
/// Write the onion address as text, or null
|
||||
pub fn serialize<S>(addr: &Option<OnionV3Address>, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
@@ -85,7 +85,7 @@ pub mod option_ov3_serde {
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Read an optional onion address
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<OnionV3Address>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
@@ -93,13 +93,13 @@ pub mod option_ov3_serde {
|
||||
Option::<String>::deserialize(deserializer).and_then(|res| match res {
|
||||
Some(s) => OnionV3Address::try_from(s.as_str())
|
||||
.map_err(|err: OnionV3AddressError| Error::custom(format!("{:?}", err)))
|
||||
.and_then(|a| Ok(Some(a))),
|
||||
.map(Some),
|
||||
None => Ok(None),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Serializes an OnionV3Address to and from hex
|
||||
/// Onion address as text
|
||||
pub mod ov3_serde {
|
||||
use serde::de::Error;
|
||||
use serde::{Deserialize, Deserializer, Serializer};
|
||||
@@ -107,7 +107,7 @@ pub mod ov3_serde {
|
||||
|
||||
use crate::util::{OnionV3Address, OnionV3AddressError};
|
||||
|
||||
///
|
||||
/// Write the onion address as text
|
||||
pub fn serialize<S>(addr: &OnionV3Address, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
@@ -115,7 +115,7 @@ pub mod ov3_serde {
|
||||
serializer.serialize_str(&addr.to_string())
|
||||
}
|
||||
|
||||
///
|
||||
/// Read an onion address
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<OnionV3Address, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
@@ -123,18 +123,17 @@ pub mod ov3_serde {
|
||||
String::deserialize(deserializer).and_then(|s| {
|
||||
OnionV3Address::try_from(s.as_str())
|
||||
.map_err(|err: OnionV3AddressError| Error::custom(format!("{:?}", err)))
|
||||
.and_then(Ok)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Serializes an ed25519 PublicKey to and from hex
|
||||
/// Ed25519 signing key as hex
|
||||
pub mod dalek_seckey_serde {
|
||||
use crate::grin_util::{from_hex, ToHex};
|
||||
use ed25519_dalek::SigningKey as DalekSecretKey;
|
||||
use grin_util::{from_hex, ToHex};
|
||||
use serde::{Deserialize, Deserializer, Serializer};
|
||||
|
||||
///
|
||||
/// Write the Ed25519 signing key as hex
|
||||
pub fn serialize<S>(key: &DalekSecretKey, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
@@ -142,7 +141,7 @@ pub mod dalek_seckey_serde {
|
||||
serializer.serialize_str(&key.to_bytes().to_hex())
|
||||
}
|
||||
|
||||
///
|
||||
/// Read an Ed25519 signing key from hex
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<DalekSecretKey, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
@@ -160,11 +159,11 @@ pub mod dalek_seckey_serde {
|
||||
|
||||
/// Serializes an ed25519 PublicKey to and from hex
|
||||
pub mod dalek_pubkey_serde {
|
||||
use crate::grin_util::{from_hex, ToHex};
|
||||
use ed25519_dalek::VerifyingKey as DalekPublicKey;
|
||||
use grin_util::{from_hex, ToHex};
|
||||
use serde::{Deserialize, Deserializer, Serializer};
|
||||
|
||||
///
|
||||
/// Write the Ed25519 public key as hex
|
||||
pub fn serialize<S>(key: &DalekPublicKey, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
@@ -172,7 +171,7 @@ pub mod dalek_pubkey_serde {
|
||||
serializer.serialize_str(&key.to_bytes().to_hex())
|
||||
}
|
||||
|
||||
///
|
||||
/// Read an Ed25519 public key from hex
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<DalekPublicKey, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
@@ -193,11 +192,11 @@ pub mod dalek_pubkey_serde {
|
||||
|
||||
/// Serializes a x25519 PublicKey to and from hex
|
||||
pub mod dalek_xpubkey_serde {
|
||||
use crate::grin_util::{from_hex, ToHex};
|
||||
use grin_util::{from_hex, ToHex};
|
||||
use serde::{Deserialize, Deserializer, Serializer};
|
||||
use x25519_dalek::PublicKey as xDalekPublicKey;
|
||||
|
||||
///
|
||||
/// Write the X25519 public key as hex
|
||||
pub fn serialize<S>(key: &xDalekPublicKey, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
@@ -205,7 +204,7 @@ pub mod dalek_xpubkey_serde {
|
||||
serializer.serialize_str(&key.as_bytes().to_hex())
|
||||
}
|
||||
|
||||
///
|
||||
/// Read an X25519 public key from hex
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<xDalekPublicKey, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
@@ -213,10 +212,10 @@ pub mod dalek_xpubkey_serde {
|
||||
use serde::de::Error;
|
||||
String::deserialize(deserializer)
|
||||
.and_then(|string| from_hex(&string).map_err(|err| Error::custom(err.to_string())))
|
||||
.and_then(|bytes: Vec<u8>| {
|
||||
.map(|bytes: Vec<u8>| {
|
||||
let mut b = [0u8; 32];
|
||||
b.copy_from_slice(&bytes[0..32]);
|
||||
Ok(xDalekPublicKey::from(b))
|
||||
xDalekPublicKey::from(b)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -227,7 +226,7 @@ pub mod dalek_pubkey_base64 {
|
||||
use ed25519_dalek::VerifyingKey as DalekPublicKey;
|
||||
use serde::{Deserialize, Deserializer, Serializer};
|
||||
|
||||
///
|
||||
/// Write the Ed25519 public key as base64
|
||||
pub fn serialize<S>(key: &DalekPublicKey, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
@@ -235,7 +234,7 @@ pub mod dalek_pubkey_base64 {
|
||||
serializer.serialize_str(&base64::encode(&key.to_bytes()))
|
||||
}
|
||||
|
||||
///
|
||||
/// Read an Ed25519 public key from base64
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<DalekPublicKey, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
@@ -256,14 +255,14 @@ pub mod dalek_pubkey_base64 {
|
||||
}
|
||||
}
|
||||
|
||||
/// Serializes an Option<ed25519_dalek::PublicKey> to and from hex
|
||||
/// Optional Ed25519 public key as base64
|
||||
pub mod option_dalek_pubkey_base64 {
|
||||
use base64;
|
||||
use ed25519_dalek::VerifyingKey as DalekPublicKey;
|
||||
use serde::de::Error;
|
||||
use serde::{Deserialize, Deserializer, Serializer};
|
||||
|
||||
///
|
||||
/// Write the Ed25519 public key as base64, or null
|
||||
pub fn serialize<S>(key: &Option<DalekPublicKey>, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
@@ -274,7 +273,7 @@ pub mod option_dalek_pubkey_base64 {
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Read an optional Ed25519 public key from base64
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<DalekPublicKey>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
@@ -303,9 +302,9 @@ pub mod option_dalek_pubkey_serde {
|
||||
use serde::de::Error;
|
||||
use serde::{Deserialize, Deserializer, Serializer};
|
||||
|
||||
use crate::grin_util::{from_hex, ToHex};
|
||||
use grin_util::{from_hex, ToHex};
|
||||
|
||||
///
|
||||
/// Write the Ed25519 public key as hex, or null
|
||||
pub fn serialize<S>(key: &Option<DalekPublicKey>, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
@@ -316,7 +315,7 @@ pub mod option_dalek_pubkey_serde {
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Read an optional Ed25519 public key from hex
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<DalekPublicKey>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
@@ -342,9 +341,9 @@ pub mod option_xdalek_pubkey_serde {
|
||||
use serde::{Deserialize, Deserializer, Serializer};
|
||||
use x25519_dalek::PublicKey as xDalekPublicKey;
|
||||
|
||||
use crate::grin_util::{from_hex, ToHex};
|
||||
use grin_util::{from_hex, ToHex};
|
||||
|
||||
///
|
||||
/// Write the X25519 public key as hex, or null
|
||||
pub fn serialize<S>(key: &Option<xDalekPublicKey>, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
@@ -355,7 +354,7 @@ pub mod option_xdalek_pubkey_serde {
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Read an optional X25519 public key from hex
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<xDalekPublicKey>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
@@ -363,10 +362,10 @@ pub mod option_xdalek_pubkey_serde {
|
||||
Option::<String>::deserialize(deserializer).and_then(|res| match res {
|
||||
Some(string) => from_hex(&string)
|
||||
.map_err(|err| Error::custom(err.to_string()))
|
||||
.and_then(|bytes: Vec<u8>| {
|
||||
.map(|bytes: Vec<u8>| {
|
||||
let mut b = [0u8; 32];
|
||||
b.copy_from_slice(&bytes[0..32]);
|
||||
Ok(Some(xDalekPublicKey::from(b)))
|
||||
Some(xDalekPublicKey::from(b))
|
||||
}),
|
||||
None => Ok(None),
|
||||
})
|
||||
@@ -380,9 +379,9 @@ pub mod dalek_sig_serde {
|
||||
use serde::{Deserialize, Deserializer, Serializer};
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use crate::grin_util::{from_hex, ToHex};
|
||||
use grin_util::{from_hex, ToHex};
|
||||
|
||||
///
|
||||
/// Write the Ed25519 signature as hex
|
||||
pub fn serialize<S>(sig: &DalekSignature, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
@@ -390,7 +389,7 @@ pub mod dalek_sig_serde {
|
||||
serializer.serialize_str(&sig.to_bytes().as_ref().to_hex())
|
||||
}
|
||||
|
||||
///
|
||||
/// Read an Ed25519 signature from hex
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<DalekSignature, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
@@ -400,21 +399,21 @@ pub mod dalek_sig_serde {
|
||||
.and_then(|bytes: Vec<u8>| {
|
||||
let b = <[u8; 64]>::try_from(bytes.as_slice())
|
||||
.map_err(|_| Error::custom("invalid signature length"))?;
|
||||
DalekSignature::try_from(b).map_err(|err| Error::custom(err.to_string()))
|
||||
Ok(DalekSignature::from(b))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Serializes an Option<ed25519_dalek::PublicKey> to and from hex
|
||||
/// Optional Ed25519 signature as hex
|
||||
pub mod option_dalek_sig_serde {
|
||||
use ed25519_dalek::Signature as DalekSignature;
|
||||
use serde::de::Error;
|
||||
use serde::{Deserialize, Deserializer, Serializer};
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use crate::grin_util::{from_hex, ToHex};
|
||||
use grin_util::{from_hex, ToHex};
|
||||
|
||||
///
|
||||
/// Write the Ed25519 signature as hex, or null
|
||||
pub fn serialize<S>(sig: &Option<DalekSignature>, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
@@ -425,7 +424,7 @@ pub mod option_dalek_sig_serde {
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Read an optional Ed25519 signature from hex
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<DalekSignature>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
@@ -436,16 +435,14 @@ pub mod option_dalek_sig_serde {
|
||||
.and_then(|bytes: Vec<u8>| {
|
||||
let b = <[u8; 64]>::try_from(bytes.as_slice())
|
||||
.map_err(|_| Error::custom("invalid signature length"))?;
|
||||
DalekSignature::try_from(b)
|
||||
.map(Some)
|
||||
.map_err(|err| Error::custom(err.to_string()))
|
||||
Ok(Some(DalekSignature::from(b)))
|
||||
}),
|
||||
None => Ok(None),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Serializes an Option<ed25519_dalek::PublicKey> to and from base64
|
||||
/// Optional Ed25519 signature as base64
|
||||
pub mod option_dalek_sig_base64 {
|
||||
use base64;
|
||||
use ed25519_dalek::Signature as DalekSignature;
|
||||
@@ -453,7 +450,7 @@ pub mod option_dalek_sig_base64 {
|
||||
use serde::{Deserialize, Deserializer, Serializer};
|
||||
use std::convert::TryFrom;
|
||||
|
||||
///
|
||||
/// Write the Ed25519 signature as base64, or null
|
||||
pub fn serialize<S>(sig: &Option<DalekSignature>, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
@@ -464,7 +461,7 @@ pub mod option_dalek_sig_base64 {
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Read an optional Ed25519 signature from base64
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<DalekSignature>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
@@ -475,9 +472,7 @@ pub mod option_dalek_sig_base64 {
|
||||
.and_then(|bytes: Vec<u8>| {
|
||||
let b = <[u8; 64]>::try_from(bytes.as_slice())
|
||||
.map_err(|_| Error::custom("invalid signature length"))?;
|
||||
DalekSignature::try_from(b)
|
||||
.map(Some)
|
||||
.map_err(|err| Error::custom(err.to_string()))
|
||||
Ok(Some(DalekSignature::from(b)))
|
||||
}),
|
||||
None => Ok(None),
|
||||
})
|
||||
@@ -491,7 +486,7 @@ pub mod version_info_v4 {
|
||||
|
||||
use crate::slate_versions::v4::VersionCompatInfoV4;
|
||||
|
||||
///
|
||||
/// Write the version as `slate_version:block_header_version`
|
||||
pub fn serialize<S>(v: &VersionCompatInfoV4, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
@@ -499,7 +494,7 @@ pub mod version_info_v4 {
|
||||
serializer.serialize_str(&format!("{}:{}", v.version, v.block_header_version))
|
||||
}
|
||||
|
||||
///
|
||||
/// Read `slate_version:block_header_version`
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<VersionCompatInfoV4, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
@@ -513,11 +508,11 @@ pub mod version_info_v4 {
|
||||
if v.len() != 2 {
|
||||
return Err(Error::custom("Cannot parse version"));
|
||||
}
|
||||
match u16::from_str_radix(v[0], 10) {
|
||||
match v[0].parse::<u16>() {
|
||||
Ok(u) => retval.version = u,
|
||||
Err(e) => return Err(Error::custom(format!("Cannot parse version: {}", e))),
|
||||
}
|
||||
match u16::from_str_radix(v[1], 10) {
|
||||
match v[1].parse::<u16>() {
|
||||
Ok(u) => retval.block_header_version = u,
|
||||
Err(e) => return Err(Error::custom(format!("Cannot parse version: {}", e))),
|
||||
}
|
||||
@@ -533,7 +528,7 @@ pub mod slate_state_v4 {
|
||||
|
||||
use crate::slate_versions::v4::SlateStateV4;
|
||||
|
||||
///
|
||||
/// Write the state as `NA`, `S1`–`S3` or `I1`–`I3`
|
||||
pub fn serialize<S>(st: &SlateStateV4, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
@@ -550,7 +545,7 @@ pub mod slate_state_v4 {
|
||||
serializer.serialize_str(label)
|
||||
}
|
||||
|
||||
///
|
||||
/// Read a slate state label
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<SlateStateV4, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
@@ -571,13 +566,13 @@ pub mod slate_state_v4 {
|
||||
}
|
||||
}
|
||||
|
||||
/// Serializes an secp256k1 pubkey to base64
|
||||
/// UUID as base64
|
||||
pub mod uuid_base64 {
|
||||
use base64;
|
||||
use serde::{Deserialize, Deserializer, Serializer};
|
||||
use uuid::Uuid;
|
||||
|
||||
///
|
||||
/// Write the UUID bytes as base64
|
||||
pub fn serialize<S>(id: &Uuid, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
@@ -585,7 +580,7 @@ pub mod uuid_base64 {
|
||||
serializer.serialize_str(&base64::encode(&id.as_bytes()))
|
||||
}
|
||||
|
||||
///
|
||||
/// Read a UUID from base64
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Uuid, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
@@ -595,10 +590,10 @@ pub mod uuid_base64 {
|
||||
.and_then(|string| {
|
||||
base64::decode(&string).map_err(|err| Error::custom(err.to_string()))
|
||||
})
|
||||
.and_then(|bytes: Vec<u8>| {
|
||||
.map(|bytes: Vec<u8>| {
|
||||
let mut b = [0u8; 16];
|
||||
b.copy_from_slice(&bytes[0..16]);
|
||||
Ok(Uuid::from_bytes(b))
|
||||
Uuid::from_bytes(b)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -608,11 +603,11 @@ mod test {
|
||||
use super::*;
|
||||
use rand::rngs::mock::StepRng;
|
||||
|
||||
use crate::grin_util::{secp, static_secp_instance};
|
||||
use ed25519_dalek::Signature as DalekSignature;
|
||||
use ed25519_dalek::Signer;
|
||||
use ed25519_dalek::SigningKey as DalekSecretKey;
|
||||
use ed25519_dalek::VerifyingKey as DalekPublicKey;
|
||||
use grin_util::{secp, static_secp_instance};
|
||||
use serde::Deserialize;
|
||||
|
||||
use serde_json;
|
||||
@@ -642,9 +637,9 @@ mod test {
|
||||
println!("D sig: {:?}", d_sig);
|
||||
|
||||
SerTest {
|
||||
pub_key: d_pub_key.clone(),
|
||||
pub_key: d_pub_key,
|
||||
pub_key_opt: Some(d_pub_key),
|
||||
sig: d_sig.clone(),
|
||||
sig: d_sig,
|
||||
sig_opt: Some(d_sig),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
//! * The feat_args struct is added, which may be populated for non-Plain kernels
|
||||
//! * `proof` may be omitted from the slate if it is None (null),
|
||||
//! * `off` (offset) is added, and will be modified by every participant in the transaction with a random
|
||||
//! value - the value of their inputs' blinding factors
|
||||
//! value - the value of their inputs' blinding factors
|
||||
//!
|
||||
//! #### Participant Data (`sigs`)
|
||||
//!
|
||||
@@ -53,17 +53,17 @@
|
||||
//! * The `receiver_signature` field is renamed to `rsig`
|
||||
//! * `rsig` may be omitted if it has not yet been filled out
|
||||
|
||||
use crate::grin_core::core::FeeFields;
|
||||
use crate::grin_core::core::{Input, Output, TxKernel};
|
||||
use crate::grin_core::libtx::secp_ser;
|
||||
use crate::grin_keychain::{BlindingFactor, Identifier};
|
||||
use crate::grin_util::secp;
|
||||
use crate::grin_util::secp::key::PublicKey;
|
||||
use crate::grin_util::secp::pedersen::{Commitment, RangeProof};
|
||||
use crate::grin_util::secp::Signature;
|
||||
use crate::{slate_versions::ser, CbData};
|
||||
use ed25519_dalek::Signature as DalekSignature;
|
||||
use ed25519_dalek::VerifyingKey as DalekPublicKey;
|
||||
use grin_core::core::FeeFields;
|
||||
use grin_core::core::{Input, Output, TxKernel};
|
||||
use grin_core::libtx::secp_ser;
|
||||
use grin_keychain::{BlindingFactor, Identifier};
|
||||
use grin_util::secp;
|
||||
use grin_util::secp::key::PublicKey;
|
||||
use grin_util::secp::pedersen::{Commitment, RangeProof};
|
||||
use grin_util::secp::Signature;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
|
||||
@@ -14,15 +14,15 @@
|
||||
|
||||
//! Wraps a V4 Slate into a V4 Binary slate
|
||||
|
||||
use crate::grin_core::core::transaction::{FeeFields, OutputFeatures};
|
||||
use crate::grin_core::ser as grin_ser;
|
||||
use crate::grin_core::ser::{Readable, Reader, Writeable, Writer};
|
||||
use crate::grin_keychain::BlindingFactor;
|
||||
use crate::grin_util::secp::key::PublicKey;
|
||||
use crate::grin_util::secp::pedersen::{Commitment, RangeProof};
|
||||
use crate::grin_util::secp::Signature;
|
||||
use ed25519_dalek::Signature as DalekSignature;
|
||||
use ed25519_dalek::VerifyingKey as DalekPublicKey;
|
||||
use grin_core::core::transaction::{FeeFields, OutputFeatures};
|
||||
use grin_core::ser as grin_ser;
|
||||
use grin_core::ser::{Readable, Reader, Writeable, Writer};
|
||||
use grin_keychain::BlindingFactor;
|
||||
use grin_util::secp::key::PublicKey;
|
||||
use grin_util::secp::pedersen::{Commitment, RangeProof};
|
||||
use grin_util::secp::Signature;
|
||||
use std::convert::TryFrom;
|
||||
use uuid::Uuid;
|
||||
|
||||
@@ -68,7 +68,7 @@ struct UuidWrap(Uuid);
|
||||
|
||||
impl Writeable for UuidWrap {
|
||||
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), grin_ser::Error> {
|
||||
writer.write_fixed_bytes(&self.0.as_bytes())
|
||||
writer.write_fixed_bytes(self.0.as_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,7 +211,7 @@ impl Readable for SigsWrap {
|
||||
nonce: PublicKey::read(reader)?,
|
||||
part: match has_partial {
|
||||
1 => Some(Signature::read(reader)?),
|
||||
0 | _ => None,
|
||||
_ => None,
|
||||
},
|
||||
};
|
||||
ret.push(c);
|
||||
@@ -252,10 +252,10 @@ impl<'a> Writeable for SlateOptStructsRef<'a> {
|
||||
};
|
||||
writer.write_u8(status)?;
|
||||
if let Some(c) = self.coms {
|
||||
ComsWrapRef(&c).write(writer)?;
|
||||
ComsWrapRef(c).write(writer)?;
|
||||
}
|
||||
if let Some(p) = self.proof {
|
||||
ProofWrapRef(&p).write(writer)?;
|
||||
ProofWrapRef(p).write(writer)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -314,7 +314,7 @@ impl Readable for ComsWrap {
|
||||
c: Commitment::read(reader)?,
|
||||
p: match is_output {
|
||||
1 => Some(RangeProof::read(reader)?),
|
||||
0 | _ => None,
|
||||
_ => None,
|
||||
},
|
||||
};
|
||||
ret.push(c);
|
||||
@@ -335,7 +335,7 @@ impl<'a> Writeable for ProofWrapRef<'a> {
|
||||
match self.0.rsig {
|
||||
Some(s) => {
|
||||
writer.write_u8(1)?;
|
||||
writer.write_fixed_bytes(&s.to_bytes().to_vec())?;
|
||||
writer.write_fixed_bytes(s.to_bytes())?;
|
||||
}
|
||||
None => writer.write_u8(0)?,
|
||||
}
|
||||
@@ -359,7 +359,7 @@ impl Readable for ProofWrap {
|
||||
|
||||
let rsig = match reader.read_u8()? {
|
||||
0 => None,
|
||||
1 | _ => Some(
|
||||
_ => Some(
|
||||
DalekSignature::try_from(&reader.read_fixed_bytes(64)?[..])
|
||||
.map_err(|_| grin_ser::Error::CorruptedData)?,
|
||||
),
|
||||
@@ -503,11 +503,11 @@ impl Readable for SlateV4Bin {
|
||||
|
||||
#[test]
|
||||
fn slate_v4_serialize_deserialize() {
|
||||
use crate::grin_util::from_hex;
|
||||
use crate::grin_util::secp::key::PublicKey;
|
||||
use crate::Slate;
|
||||
use grin_core::global::{set_local_chain_type, ChainTypes};
|
||||
use grin_keychain::{ExtKeychain, Keychain, SwitchCommitmentType};
|
||||
use grin_util::from_hex;
|
||||
use grin_util::secp::key::PublicKey;
|
||||
|
||||
set_local_chain_type(ChainTypes::Mainnet);
|
||||
let slate = Slate::blank(1, false);
|
||||
@@ -547,11 +547,7 @@ fn slate_v4_serialize_deserialize() {
|
||||
c: Commitment::from_vec([4u8; 1].to_vec()),
|
||||
p: Some(RangeProof::zero()),
|
||||
};
|
||||
let mut coms = vec![];
|
||||
coms.push(com1.clone());
|
||||
coms.push(com1.clone());
|
||||
coms.push(com1.clone());
|
||||
coms.push(com2);
|
||||
let coms = vec![com1, com1, com1, com2];
|
||||
|
||||
v4.coms = Some(coms);
|
||||
v4.amt = 234324899824;
|
||||
@@ -563,7 +559,7 @@ fn slate_v4_serialize_deserialize() {
|
||||
|
||||
let v4_bin = SlateV4Bin(v4);
|
||||
let mut vec = Vec::new();
|
||||
let _ = grin_ser::serialize_default(&mut vec, &v4_bin).expect("serialization failed");
|
||||
grin_ser::serialize_default(&mut vec, &v4_bin).expect("serialization failed");
|
||||
let b4_bin_2: SlateV4Bin = grin_ser::deserialize_default(&mut &vec[..]).unwrap();
|
||||
let v4_2 = b4_bin_2.0.clone();
|
||||
assert_eq!(v4_1.ver, v4_2.ver);
|
||||
@@ -586,15 +582,15 @@ fn slate_v4_serialize_deserialize() {
|
||||
let b = <&[u8; 32]>::try_from(bytes.as_slice()).unwrap();
|
||||
let d_pkey = DalekPublicKey::from_bytes(b.as_array().unwrap()).unwrap();
|
||||
v4.proof = Some(PaymentInfoV4 {
|
||||
raddr: d_pkey.clone(),
|
||||
saddr: d_pkey.clone(),
|
||||
raddr: d_pkey,
|
||||
saddr: d_pkey,
|
||||
rsig: None,
|
||||
});
|
||||
v4.coms = None;
|
||||
let v4_1 = v4.clone();
|
||||
let v4_bin = SlateV4Bin(v4);
|
||||
let mut vec = Vec::new();
|
||||
let _ = grin_ser::serialize_default(&mut vec, &v4_bin).expect("serialization failed");
|
||||
grin_ser::serialize_default(&mut vec, &v4_bin).expect("serialization failed");
|
||||
let b4_bin_2: SlateV4Bin = grin_ser::deserialize_default(&mut &vec[..]).unwrap();
|
||||
let v4_2 = b4_bin_2.0.clone();
|
||||
assert_eq!(v4_1.ver, v4_2.ver);
|
||||
|
||||
@@ -20,11 +20,11 @@ use rand::{thread_rng, Rng};
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use x25519_dalek::PublicKey as xDalekPublicKey;
|
||||
|
||||
use crate::grin_core::global;
|
||||
use crate::grin_core::ser::{self, Readable, Reader, Writeable, Writer};
|
||||
use crate::grin_util::secp::key::SecretKey;
|
||||
use crate::util::OnionV3Address;
|
||||
use crate::Error;
|
||||
use grin_core::global;
|
||||
use grin_core::ser::{self, Readable, Reader, Writeable, Writer};
|
||||
use grin_util::secp::key::SecretKey;
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::fmt::{self, Display};
|
||||
@@ -53,7 +53,7 @@ impl SlatepackAddress {
|
||||
pub fn new(pub_key: &edDalekPublicKey) -> Self {
|
||||
Self {
|
||||
hrp: String::from(slatepack_hrp()),
|
||||
pub_key: pub_key.clone(),
|
||||
pub_key: *pub_key,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ impl SlatepackAddress {
|
||||
pub fn encoded_len(&self) -> Result<usize, Error> {
|
||||
let encoded = String::try_from(self)?;
|
||||
// add length byte
|
||||
Ok(encoded.as_bytes().len() + 1)
|
||||
Ok(encoded.len() + 1)
|
||||
}
|
||||
|
||||
/// utility to construct a public key that can be read by age 0.5+,
|
||||
@@ -97,7 +97,7 @@ impl Display for SlatepackAddress {
|
||||
impl TryFrom<&str> for SlatepackAddress {
|
||||
type Error = Error;
|
||||
fn try_from(encoded: &str) -> Result<Self, Self::Error> {
|
||||
let (hrp, data) = bech32::decode(&encoded)?;
|
||||
let (hrp, data) = bech32::decode(encoded)?;
|
||||
if !valid_network(&hrp) {
|
||||
return Err(Error::SlatepackAddress(format!(
|
||||
"wrong address prefix for chain {:?}",
|
||||
@@ -107,7 +107,7 @@ impl TryFrom<&str> for SlatepackAddress {
|
||||
let bytes = Vec::<u8>::from_base32(&data)?;
|
||||
let b = <&[u8; 32]>::try_from(bytes.as_slice())
|
||||
.map_err(|_| Error::SlatepackAddress("Wrong encoded data".to_string()))?;
|
||||
let pub_key = match edDalekPublicKey::from_bytes(&b) {
|
||||
let pub_key = match edDalekPublicKey::from_bytes(b) {
|
||||
Ok(k) => k,
|
||||
Err(e) => {
|
||||
return Err(Error::ED25519Key(format!("{}", e)));
|
||||
@@ -170,7 +170,6 @@ impl TryFrom<&SecretKey> for SlatepackAddress {
|
||||
|
||||
/// Serializes a SlatepackAddress to a bech32 string
|
||||
impl Serialize for SlatepackAddress {
|
||||
///
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
@@ -232,7 +231,7 @@ impl Writeable for SlatepackAddress {
|
||||
return Err(ser::Error::CorruptedData);
|
||||
}
|
||||
writer.write_u8(bytes.len() as u8)?;
|
||||
writer.write_fixed_bytes(&bytes)
|
||||
writer.write_fixed_bytes(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,11 +50,9 @@ pub fn min_size() -> u64 {
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref HEADER_REGEX: Regex =
|
||||
Regex::new(concat!(r"^[>\n\r\t ]*BEGINSLATEPACK[>\n\r\t ]*$")).unwrap();
|
||||
static ref FOOTER_REGEX: Regex =
|
||||
Regex::new(concat!(r"^[>\n\r\t ]*ENDSLATEPACK[>\n\r\t ]*$")).unwrap();
|
||||
static ref WHITESPACE_LIST: [u8; 5] = [b'>', b'\n', b'\r', b'\t', b' '];
|
||||
static ref HEADER_REGEX: Regex = Regex::new(r"^[>\n\r\t ]*BEGINSLATEPACK[>\n\r\t ]*$").unwrap();
|
||||
static ref FOOTER_REGEX: Regex = Regex::new(r"^[>\n\r\t ]*ENDSLATEPACK[>\n\r\t ]*$").unwrap();
|
||||
static ref WHITESPACE_LIST: [u8; 5] = *b">\n\r\t ";
|
||||
}
|
||||
|
||||
/// Wrapper for associated functions
|
||||
|
||||
@@ -52,7 +52,7 @@ impl<'a> Slatepacker<'a> {
|
||||
// check if data is armored, if so, remove and continue
|
||||
let data_len = data.len() as u64;
|
||||
if data_len < slatepack::min_size() || data_len > slatepack::max_size() {
|
||||
let msg = format!("Data invalid length");
|
||||
let msg = "Data invalid length".to_string();
|
||||
return Err(Error::SlatepackDeser(msg));
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ impl<'a> Slatepacker<'a> {
|
||||
|
||||
/// Armor a slatepack
|
||||
pub fn armor_slatepack(&self, slatepack: &Slatepack) -> Result<String, Error> {
|
||||
SlatepackArmor::encode(&slatepack)
|
||||
SlatepackArmor::encode(slatepack)
|
||||
}
|
||||
|
||||
/// Return/upgrade slate from slatepack
|
||||
@@ -116,6 +116,6 @@ impl<'a> Slatepacker<'a> {
|
||||
let msg = format!("{}", e);
|
||||
Error::SlatepackDeser(msg)
|
||||
})?;
|
||||
Ok(Slate::upgrade(slate_bin.into())?)
|
||||
Slate::upgrade(slate_bin.into())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@ use sha2::{Digest, Sha512};
|
||||
use x25519_dalek::StaticSecret;
|
||||
|
||||
use crate::dalek_ser;
|
||||
use crate::grin_core::ser::{self, Readable, Reader, Writeable, Writer};
|
||||
use crate::Error;
|
||||
use grin_core::ser::{self, Readable, Reader, Writeable, Writer};
|
||||
use grin_wallet_util::byte_ser;
|
||||
|
||||
use super::SlatepackAddress;
|
||||
@@ -155,7 +155,7 @@ impl Slatepack {
|
||||
|
||||
to_encrypt.append(&mut self.payload);
|
||||
|
||||
let rec_keys: Result<Vec<_>, _> = recipients
|
||||
let rec_keys: Result<Vec<_>, Error> = recipients
|
||||
.into_iter()
|
||||
.map(|addr| {
|
||||
let recp_key: age::x25519::Recipient = addr.to_age_pubkey_str()?.parse()?;
|
||||
@@ -163,10 +163,7 @@ impl Slatepack {
|
||||
})
|
||||
.collect();
|
||||
|
||||
let keys = match rec_keys {
|
||||
Ok(k) => k,
|
||||
Err(e) => return Err(e),
|
||||
};
|
||||
let keys = rec_keys?;
|
||||
|
||||
let encryptor = age::Encryptor::with_recipients(keys);
|
||||
let mut encrypted = vec![];
|
||||
@@ -196,7 +193,7 @@ impl Slatepack {
|
||||
|
||||
let x_dec_secret = StaticSecret::from(b);
|
||||
let x_dec_secret_bech32 =
|
||||
bech32::encode("age-secret-key-", (&x_dec_secret).to_bytes().to_base32())?;
|
||||
bech32::encode("age-secret-key-", x_dec_secret.to_bytes().to_base32())?;
|
||||
let key: age::x25519::Identity = x_dec_secret_bech32.parse()?;
|
||||
|
||||
let decryptor = match age::Decryptor::new(&self.payload[..])? {
|
||||
@@ -427,7 +424,7 @@ pub mod slatepack_version {
|
||||
|
||||
use super::SlatepackVersion;
|
||||
|
||||
///
|
||||
/// Write the Slatepack version as `major.minor`
|
||||
pub fn serialize<S>(v: &SlatepackVersion, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
@@ -435,7 +432,7 @@ pub mod slatepack_version {
|
||||
serializer.serialize_str(&format!("{}.{}", v.major, v.minor))
|
||||
}
|
||||
|
||||
///
|
||||
/// Read a `major.minor` Slatepack version
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<SlatepackVersion, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
@@ -446,11 +443,11 @@ pub mod slatepack_version {
|
||||
if v.len() != 2 {
|
||||
return Err(Error::custom("Cannot parse version"));
|
||||
}
|
||||
match u8::from_str_radix(v[0], 10) {
|
||||
match v[0].parse::<u8>() {
|
||||
Ok(u) => retval.major = u,
|
||||
Err(e) => return Err(Error::custom(format!("Cannot parse version: {}", e))),
|
||||
}
|
||||
match u8::from_str_radix(v[1], 10) {
|
||||
match v[1].parse::<u8>() {
|
||||
Ok(u) => retval.minor = u,
|
||||
Err(e) => return Err(Error::custom(format!("Cannot parse version: {}", e))),
|
||||
}
|
||||
@@ -573,7 +570,7 @@ impl Writeable for SlatepackEncMetadataBin {
|
||||
if !inner.recipients.is_empty() {
|
||||
let len = inner.recipients.len();
|
||||
// write number of recipients
|
||||
if len as u16 > std::u16::MAX {
|
||||
if len > u16::MAX as usize {
|
||||
error!("Too many recipients: {}", len);
|
||||
return Err(ser::Error::CorruptedData);
|
||||
}
|
||||
@@ -663,7 +660,7 @@ fn slatepack_bin_basic_ser() -> Result<(), grin_wallet_util::byte_ser::Error> {
|
||||
|
||||
#[test]
|
||||
fn slatepack_bin_opt_fields_ser() -> Result<(), grin_wallet_util::byte_ser::Error> {
|
||||
use crate::grin_core::global;
|
||||
use grin_core::global;
|
||||
use grin_wallet_util::byte_ser;
|
||||
global::set_local_chain_type(global::ChainTypes::AutomatedTesting);
|
||||
let mut payload: Vec<u8> = Vec::with_capacity(243);
|
||||
@@ -688,8 +685,8 @@ fn slatepack_bin_opt_fields_ser() -> Result<(), grin_wallet_util::byte_ser::Erro
|
||||
// ensure that a slatepack with unknown data in the optional fields can be read
|
||||
#[test]
|
||||
fn slatepack_bin_future() -> Result<(), grin_wallet_util::byte_ser::Error> {
|
||||
use crate::grin_core::global;
|
||||
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
|
||||
use grin_core::global;
|
||||
use grin_wallet_util::byte_ser;
|
||||
use rand::{thread_rng, Rng};
|
||||
use std::io::Cursor;
|
||||
@@ -733,9 +730,7 @@ fn slatepack_bin_future() -> Result<(), grin_wallet_util::byte_ser::Error> {
|
||||
|
||||
let end_head_pos = opt_fields_len as usize + 8 + 1;
|
||||
|
||||
for i in 0..end_head_pos {
|
||||
new_bytes.push(ser[i]);
|
||||
}
|
||||
new_bytes.extend_from_slice(&ser[..end_head_pos]);
|
||||
for _ in 0..num_extra_bytes {
|
||||
new_bytes.push(thread_rng().gen());
|
||||
}
|
||||
@@ -753,9 +748,7 @@ fn slatepack_bin_future() -> Result<(), grin_wallet_util::byte_ser::Error> {
|
||||
let mut wtr = vec![];
|
||||
wtr.write_u32::<BigEndian>(opt_fields_len + num_extra_bytes as u32)
|
||||
.unwrap();
|
||||
for i in 0..wtr.len() {
|
||||
new_bytes[5 + i] = wtr[i];
|
||||
}
|
||||
new_bytes[5..(wtr.len() + 5)].copy_from_slice(&wtr[..]);
|
||||
|
||||
let deser = byte_ser::from_bytes::<SlatepackBin>(&new_bytes)?.0;
|
||||
assert_eq!(sp, deser);
|
||||
@@ -766,10 +759,10 @@ fn slatepack_bin_future() -> Result<(), grin_wallet_util::byte_ser::Error> {
|
||||
// if mode == 1
|
||||
#[test]
|
||||
fn slatepack_encrypted_meta() -> Result<(), Error> {
|
||||
use crate::grin_core::global;
|
||||
use crate::{Slate, SlateVersion, VersionedBinSlate, VersionedSlate};
|
||||
use ed25519_dalek::SigningKey as edDalekSecretKey;
|
||||
use ed25519_dalek::VerifyingKey as edDalekPublicKey;
|
||||
use grin_core::global;
|
||||
use rand::{thread_rng, Rng};
|
||||
use std::convert::TryFrom;
|
||||
global::set_local_chain_type(global::ChainTypes::AutomatedTesting);
|
||||
@@ -784,8 +777,10 @@ fn slatepack_encrypted_meta() -> Result<(), Error> {
|
||||
let parsed_addr = SlatepackAddress::try_from(encoded.as_str()).unwrap();
|
||||
assert_eq!(addr, parsed_addr);
|
||||
|
||||
let mut slatepack = super::Slatepack::default();
|
||||
slatepack.sender = Some(SlatepackAddress::random());
|
||||
let mut slatepack = Slatepack {
|
||||
sender: Some(SlatepackAddress::random()),
|
||||
..Default::default()
|
||||
};
|
||||
slatepack.add_recipient(SlatepackAddress::random());
|
||||
slatepack.add_recipient(SlatepackAddress::random());
|
||||
|
||||
@@ -815,10 +810,10 @@ fn slatepack_encrypted_meta() -> Result<(), Error> {
|
||||
// metadata won't break parsing
|
||||
#[test]
|
||||
fn slatepack_encrypted_meta_future() -> Result<(), Error> {
|
||||
use crate::grin_core::global;
|
||||
use crate::{Slate, SlateVersion, VersionedBinSlate, VersionedSlate};
|
||||
use ed25519_dalek::SigningKey as edDalekSecretKey;
|
||||
use ed25519_dalek::VerifyingKey as edDalekPublicKey;
|
||||
use grin_core::global;
|
||||
use rand::{thread_rng, Rng};
|
||||
use std::convert::TryFrom;
|
||||
global::set_local_chain_type(global::ChainTypes::AutomatedTesting);
|
||||
@@ -833,8 +828,10 @@ fn slatepack_encrypted_meta_future() -> Result<(), Error> {
|
||||
let parsed_addr = SlatepackAddress::try_from(encoded.as_str()).unwrap();
|
||||
assert_eq!(addr, parsed_addr);
|
||||
|
||||
let mut slatepack = Slatepack::default();
|
||||
slatepack.sender = Some(SlatepackAddress::random());
|
||||
let mut slatepack = Slatepack {
|
||||
sender: Some(SlatepackAddress::random()),
|
||||
..Default::default()
|
||||
};
|
||||
slatepack.add_recipient(SlatepackAddress::random());
|
||||
slatepack.add_recipient(SlatepackAddress::random());
|
||||
|
||||
@@ -892,12 +889,12 @@ fn encrypt_plaintext_to_slatepack_recipient(
|
||||
|
||||
#[test]
|
||||
fn slatepack_decrypt_rejects_malformed_plaintexts() -> Result<(), Error> {
|
||||
use crate::grin_core::global;
|
||||
use grin_core::global;
|
||||
|
||||
global::set_local_chain_type(global::ChainTypes::AutomatedTesting);
|
||||
let (ed_sec_key, addr) = slatepack_test_decryption_key();
|
||||
|
||||
for plaintext in vec![vec![], vec![0], vec![0, 0, 0], vec![0xff; 4]] {
|
||||
for plaintext in [vec![], vec![0], vec![0, 0, 0], vec![0xff; 4]] {
|
||||
let mut slatepack = Slatepack {
|
||||
mode: 1,
|
||||
payload: encrypt_plaintext_to_slatepack_recipient(&addr, &plaintext)?,
|
||||
|
||||
+24
-26
@@ -17,25 +17,23 @@
|
||||
|
||||
use crate::config::{TorConfig, WalletConfig};
|
||||
use crate::error::Error;
|
||||
use crate::grin_core::core::hash::Hash;
|
||||
use crate::grin_core::core::FeeFields;
|
||||
use crate::grin_core::core::{Output, Transaction, TxKernel};
|
||||
use crate::grin_core::libtx::{aggsig, secp_ser};
|
||||
use crate::grin_core::{global, ser};
|
||||
use crate::grin_keychain::{Identifier, Keychain};
|
||||
use crate::grin_util::logger::LoggingConfig;
|
||||
use crate::grin_util::secp::key::{PublicKey, SecretKey};
|
||||
use crate::grin_util::secp::{pedersen, Secp256k1};
|
||||
use crate::grin_util::{ToHex, ZeroingString};
|
||||
use crate::slate_versions::ser as dalek_ser;
|
||||
use crate::{InitTxArgs, SlateState, WalletBackend};
|
||||
use chrono::prelude::*;
|
||||
use ed25519_dalek::Signature as DalekSignature;
|
||||
use ed25519_dalek::VerifyingKey as DalekPublicKey;
|
||||
use grin_core::core::hash::Hash;
|
||||
use grin_core::core::FeeFields;
|
||||
use grin_core::core::{Output, Transaction, TxKernel};
|
||||
use grin_core::libtx::{aggsig, secp_ser};
|
||||
use grin_core::{global, ser};
|
||||
use grin_keychain::{Identifier, Keychain};
|
||||
use grin_util::logger::LoggingConfig;
|
||||
use grin_util::secp::key::{PublicKey, SecretKey};
|
||||
use grin_util::secp::{pedersen, Secp256k1};
|
||||
use grin_util::{ToHex, ZeroingString};
|
||||
use rand::rngs::mock::StepRng;
|
||||
use rand::thread_rng;
|
||||
use serde;
|
||||
use serde_json;
|
||||
use std::collections::HashMap;
|
||||
use std::time::Duration;
|
||||
use std::{cmp, fmt};
|
||||
@@ -76,7 +74,7 @@ where
|
||||
tor_config: Option<TorConfig>,
|
||||
) -> Result<(), Error>;
|
||||
|
||||
///
|
||||
/// Create the seed file and wallet database from a mnemonic or fresh entropy
|
||||
fn create_wallet(
|
||||
&mut self,
|
||||
name: Option<&str>,
|
||||
@@ -86,7 +84,7 @@ where
|
||||
test_mode: bool,
|
||||
) -> Result<(), Error>;
|
||||
|
||||
///
|
||||
/// Unlock the wallet and optionally mask its keychain
|
||||
fn open_wallet(
|
||||
&mut self,
|
||||
name: Option<&str>,
|
||||
@@ -95,7 +93,7 @@ where
|
||||
use_test_rng: bool,
|
||||
) -> Result<Option<SecretKey>, Error>;
|
||||
|
||||
///
|
||||
/// Close the wallet and drop its stored keychain
|
||||
fn close_wallet(&mut self, name: Option<&str>) -> Result<(), Error>;
|
||||
|
||||
/// whether a wallet exists at the given directory
|
||||
@@ -180,6 +178,7 @@ pub trait NodeClient: Send + Sync + Clone {
|
||||
/// Returns
|
||||
/// (last available output index, last insertion index retrieved,
|
||||
/// outputs(commit, proof, is_coinbase, height, mmr_index))
|
||||
#[allow(clippy::type_complexity)]
|
||||
fn get_outputs_by_pmmr_index(
|
||||
&self,
|
||||
start_height: u64,
|
||||
@@ -322,9 +321,8 @@ impl OutputData {
|
||||
|
||||
/// Mark an output as reverted
|
||||
pub fn mark_reverted(&mut self) {
|
||||
match self.status {
|
||||
OutputStatus::Unspent => self.status = OutputStatus::Reverted,
|
||||
_ => (),
|
||||
if self.status == OutputStatus::Unspent {
|
||||
self.status = OutputStatus::Reverted
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -876,17 +874,17 @@ pub struct ViewWallet {
|
||||
/// Utility struct for return values from below
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ViewWalletOutputResult {
|
||||
///
|
||||
/// Output commitment as hex
|
||||
pub commit: String,
|
||||
///
|
||||
/// Value in nanogrins
|
||||
pub value: u64,
|
||||
///
|
||||
/// Block height of the output
|
||||
pub height: u64,
|
||||
///
|
||||
/// Output position in the PMMR
|
||||
pub mmr_index: u64,
|
||||
///
|
||||
/// Whether this is a mining reward
|
||||
pub is_coinbase: bool,
|
||||
///
|
||||
/// Earliest spendable height
|
||||
pub lock_height: u64,
|
||||
}
|
||||
|
||||
@@ -933,7 +931,7 @@ pub mod option_duration_as_secs {
|
||||
use serde::{Deserialize, Deserializer, Serializer};
|
||||
use std::time::Duration;
|
||||
|
||||
///
|
||||
/// Write whole seconds as a string, or null
|
||||
pub fn serialize<S>(dur: &Option<Duration>, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
@@ -944,7 +942,7 @@ pub mod option_duration_as_secs {
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Read an optional duration from a seconds string
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Duration>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
|
||||
@@ -56,7 +56,7 @@ fn aggsig_sender_receiver_interaction() {
|
||||
|
||||
keychain
|
||||
.secp()
|
||||
.commit(0, blinding_factor.secret_key(&keychain.secp()).unwrap())
|
||||
.commit(0, blinding_factor.secret_key(keychain.secp()).unwrap())
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
@@ -75,10 +75,10 @@ fn aggsig_sender_receiver_interaction() {
|
||||
.blind_sum(&bs.sub_blinding_factor(BlindingFactor::from_secret_key(skey)))
|
||||
.unwrap();
|
||||
|
||||
let blind = blinding_factor.secret_key(&keychain.secp()).unwrap();
|
||||
let blind = blinding_factor.secret_key(keychain.secp()).unwrap();
|
||||
|
||||
s_cx = Context::with_excess(&keychain.secp(), blind, &parent, false);
|
||||
s_cx.get_public_keys(&keychain.secp())
|
||||
s_cx = Context::with_excess(keychain.secp(), blind, &parent, false);
|
||||
s_cx.get_public_keys(keychain.secp())
|
||||
};
|
||||
|
||||
let pub_nonce_sum;
|
||||
@@ -91,8 +91,8 @@ fn aggsig_sender_receiver_interaction() {
|
||||
// let blind = blind_sum.secret_key(&keychain.secp())?;
|
||||
let blind = keychain.derive_key(0, &key_id, switch).unwrap();
|
||||
|
||||
rx_cx = Context::with_excess(&keychain.secp(), blind, &parent, false);
|
||||
let (pub_excess, pub_nonce) = rx_cx.get_public_keys(&keychain.secp());
|
||||
rx_cx = Context::with_excess(keychain.secp(), blind, &parent, false);
|
||||
let (pub_excess, pub_nonce) = rx_cx.get_public_keys(keychain.secp());
|
||||
rx_cx.add_output(&key_id, &None, 0);
|
||||
|
||||
pub_nonce_sum = PublicKey::from_combination(
|
||||
@@ -115,7 +115,7 @@ fn aggsig_sender_receiver_interaction() {
|
||||
|
||||
let msg = kernel_sig_msg();
|
||||
let sig_part = aggsig::calculate_partial_sig(
|
||||
&keychain.secp(),
|
||||
keychain.secp(),
|
||||
&rx_cx.sec_key,
|
||||
&rx_cx.sec_nonce,
|
||||
&pub_nonce_sum,
|
||||
@@ -132,14 +132,14 @@ fn aggsig_sender_receiver_interaction() {
|
||||
let keychain = sender_keychain.clone();
|
||||
let msg = kernel_sig_msg();
|
||||
let sig_verifies = aggsig::verify_partial_sig(
|
||||
&keychain.secp(),
|
||||
keychain.secp(),
|
||||
&rx_sig_part,
|
||||
&pub_nonce_sum,
|
||||
&receiver_pub_excess,
|
||||
Some(&pub_key_sum),
|
||||
&msg,
|
||||
);
|
||||
assert!(!sig_verifies.is_err());
|
||||
assert!(sig_verifies.is_ok());
|
||||
}
|
||||
|
||||
// now sender signs with their key
|
||||
@@ -147,7 +147,7 @@ fn aggsig_sender_receiver_interaction() {
|
||||
let keychain = sender_keychain.clone();
|
||||
let msg = kernel_sig_msg();
|
||||
let sig_part = aggsig::calculate_partial_sig(
|
||||
&keychain.secp(),
|
||||
keychain.secp(),
|
||||
&s_cx.sec_key,
|
||||
&s_cx.sec_nonce,
|
||||
&pub_nonce_sum,
|
||||
@@ -164,14 +164,14 @@ fn aggsig_sender_receiver_interaction() {
|
||||
let keychain = receiver_keychain.clone();
|
||||
let msg = kernel_sig_msg();
|
||||
let sig_verifies = aggsig::verify_partial_sig(
|
||||
&keychain.secp(),
|
||||
keychain.secp(),
|
||||
&sender_sig_part,
|
||||
&pub_nonce_sum,
|
||||
&sender_pub_excess,
|
||||
Some(&pub_key_sum),
|
||||
&msg,
|
||||
);
|
||||
assert!(!sig_verifies.is_err());
|
||||
assert!(sig_verifies.is_ok());
|
||||
}
|
||||
|
||||
// Receiver now builds final signature from sender and receiver parts
|
||||
@@ -180,7 +180,7 @@ fn aggsig_sender_receiver_interaction() {
|
||||
|
||||
let msg = kernel_sig_msg();
|
||||
let our_sig_part = aggsig::calculate_partial_sig(
|
||||
&keychain.secp(),
|
||||
keychain.secp(),
|
||||
&rx_cx.sec_key,
|
||||
&rx_cx.sec_nonce,
|
||||
&pub_nonce_sum,
|
||||
@@ -191,7 +191,7 @@ fn aggsig_sender_receiver_interaction() {
|
||||
|
||||
// Receiver now generates final signature from the two parts
|
||||
let final_sig = aggsig::add_signatures(
|
||||
&keychain.secp(),
|
||||
keychain.secp(),
|
||||
vec![&sender_sig_part, &our_sig_part],
|
||||
&pub_nonce_sum,
|
||||
)
|
||||
@@ -217,13 +217,13 @@ fn aggsig_sender_receiver_interaction() {
|
||||
|
||||
// Receiver check the final signature verifies
|
||||
let sig_verifies = aggsig::verify_completed_sig(
|
||||
&keychain.secp(),
|
||||
keychain.secp(),
|
||||
&final_sig,
|
||||
&final_pubkey,
|
||||
Some(&final_pubkey),
|
||||
&msg,
|
||||
);
|
||||
assert!(!sig_verifies.is_err());
|
||||
assert!(sig_verifies.is_ok());
|
||||
}
|
||||
|
||||
// Check we can verify the sig using the kernel excess
|
||||
@@ -231,9 +231,9 @@ fn aggsig_sender_receiver_interaction() {
|
||||
let keychain = ExtKeychain::from_random_seed(true).unwrap();
|
||||
let msg = kernel_sig_msg();
|
||||
let sig_verifies =
|
||||
aggsig::verify_single_from_commit(&keychain.secp(), &final_sig, &msg, &kernel_excess);
|
||||
aggsig::verify_single_from_commit(keychain.secp(), &final_sig, &msg, &kernel_excess);
|
||||
|
||||
assert!(!sig_verifies.is_err());
|
||||
assert!(sig_verifies.is_ok());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,7 +247,7 @@ fn aggsig_sender_receiver_interaction_offset() {
|
||||
// This is the kernel offset that we use to split the key
|
||||
// Summing these at the block level prevents the
|
||||
// kernels from being used to reconstruct (or identify) individual transactions
|
||||
let kernel_offset = SecretKey::new(&sender_keychain.secp(), &mut thread_rng());
|
||||
let kernel_offset = SecretKey::new(sender_keychain.secp(), &mut thread_rng());
|
||||
|
||||
// Calculate the kernel excess here for convenience.
|
||||
// Normally this would happen during transaction building.
|
||||
@@ -270,7 +270,7 @@ fn aggsig_sender_receiver_interaction_offset() {
|
||||
|
||||
keychain
|
||||
.secp()
|
||||
.commit(0, blinding_factor.secret_key(&keychain.secp()).unwrap())
|
||||
.commit(0, blinding_factor.secret_key(keychain.secp()).unwrap())
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
@@ -294,10 +294,10 @@ fn aggsig_sender_receiver_interaction_offset() {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let blind = blinding_factor.secret_key(&keychain.secp()).unwrap();
|
||||
let blind = blinding_factor.secret_key(keychain.secp()).unwrap();
|
||||
|
||||
s_cx = Context::with_excess(&keychain.secp(), blind, &parent, false);
|
||||
s_cx.get_public_keys(&keychain.secp())
|
||||
s_cx = Context::with_excess(keychain.secp(), blind, &parent, false);
|
||||
s_cx.get_public_keys(keychain.secp())
|
||||
};
|
||||
|
||||
// receiver receives partial tx
|
||||
@@ -309,8 +309,8 @@ fn aggsig_sender_receiver_interaction_offset() {
|
||||
|
||||
let blind = keychain.derive_key(0, &key_id, switch).unwrap();
|
||||
|
||||
rx_cx = Context::with_excess(&keychain.secp(), blind, &parent, false);
|
||||
let (pub_excess, pub_nonce) = rx_cx.get_public_keys(&keychain.secp());
|
||||
rx_cx = Context::with_excess(keychain.secp(), blind, &parent, false);
|
||||
let (pub_excess, pub_nonce) = rx_cx.get_public_keys(keychain.secp());
|
||||
rx_cx.add_output(&key_id, &None, 0);
|
||||
|
||||
pub_nonce_sum = PublicKey::from_combination(
|
||||
@@ -333,7 +333,7 @@ fn aggsig_sender_receiver_interaction_offset() {
|
||||
|
||||
let msg = kernel_sig_msg();
|
||||
let sig_part = aggsig::calculate_partial_sig(
|
||||
&keychain.secp(),
|
||||
keychain.secp(),
|
||||
&rx_cx.sec_key,
|
||||
&rx_cx.sec_nonce,
|
||||
&pub_nonce_sum,
|
||||
@@ -350,14 +350,14 @@ fn aggsig_sender_receiver_interaction_offset() {
|
||||
let keychain = sender_keychain.clone();
|
||||
let msg = kernel_sig_msg();
|
||||
let sig_verifies = aggsig::verify_partial_sig(
|
||||
&keychain.secp(),
|
||||
keychain.secp(),
|
||||
&sig_part,
|
||||
&pub_nonce_sum,
|
||||
&receiver_pub_excess,
|
||||
Some(&pub_key_sum),
|
||||
&msg,
|
||||
);
|
||||
assert!(!sig_verifies.is_err());
|
||||
assert!(sig_verifies.is_ok());
|
||||
}
|
||||
|
||||
// now sender signs with their key
|
||||
@@ -365,7 +365,7 @@ fn aggsig_sender_receiver_interaction_offset() {
|
||||
let keychain = sender_keychain.clone();
|
||||
let msg = kernel_sig_msg();
|
||||
let sig_part = aggsig::calculate_partial_sig(
|
||||
&keychain.secp(),
|
||||
keychain.secp(),
|
||||
&s_cx.sec_key,
|
||||
&s_cx.sec_nonce,
|
||||
&pub_nonce_sum,
|
||||
@@ -382,14 +382,14 @@ fn aggsig_sender_receiver_interaction_offset() {
|
||||
let keychain = receiver_keychain.clone();
|
||||
let msg = kernel_sig_msg();
|
||||
let sig_verifies = aggsig::verify_partial_sig(
|
||||
&keychain.secp(),
|
||||
keychain.secp(),
|
||||
&sender_sig_part,
|
||||
&pub_nonce_sum,
|
||||
&sender_pub_excess,
|
||||
Some(&pub_key_sum),
|
||||
&msg,
|
||||
);
|
||||
assert!(!sig_verifies.is_err());
|
||||
assert!(sig_verifies.is_ok());
|
||||
}
|
||||
|
||||
// Receiver now builds final signature from sender and receiver parts
|
||||
@@ -397,7 +397,7 @@ fn aggsig_sender_receiver_interaction_offset() {
|
||||
let keychain = receiver_keychain.clone();
|
||||
let msg = kernel_sig_msg();
|
||||
let our_sig_part = aggsig::calculate_partial_sig(
|
||||
&keychain.secp(),
|
||||
keychain.secp(),
|
||||
&rx_cx.sec_key,
|
||||
&rx_cx.sec_nonce,
|
||||
&pub_nonce_sum,
|
||||
@@ -408,7 +408,7 @@ fn aggsig_sender_receiver_interaction_offset() {
|
||||
|
||||
// Receiver now generates final signature from the two parts
|
||||
let final_sig = aggsig::add_signatures(
|
||||
&keychain.secp(),
|
||||
keychain.secp(),
|
||||
vec![&sender_sig_part, &our_sig_part],
|
||||
&pub_nonce_sum,
|
||||
)
|
||||
@@ -434,13 +434,13 @@ fn aggsig_sender_receiver_interaction_offset() {
|
||||
|
||||
// Receiver check the final signature verifies
|
||||
let sig_verifies = aggsig::verify_completed_sig(
|
||||
&keychain.secp(),
|
||||
keychain.secp(),
|
||||
&final_sig,
|
||||
&final_pubkey,
|
||||
Some(&final_pubkey),
|
||||
&msg,
|
||||
);
|
||||
assert!(!sig_verifies.is_err());
|
||||
assert!(sig_verifies.is_ok());
|
||||
}
|
||||
|
||||
// Check we can verify the sig using the kernel excess
|
||||
@@ -448,9 +448,9 @@ fn aggsig_sender_receiver_interaction_offset() {
|
||||
let keychain = ExtKeychain::from_random_seed(true).unwrap();
|
||||
let msg = kernel_sig_msg();
|
||||
let sig_verifies =
|
||||
aggsig::verify_single_from_commit(&keychain.secp(), &final_sig, &msg, &kernel_excess);
|
||||
aggsig::verify_single_from_commit(keychain.secp(), &final_sig, &msg, &kernel_excess);
|
||||
|
||||
assert!(!sig_verifies.is_err());
|
||||
assert!(sig_verifies.is_ok());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-15
@@ -58,8 +58,7 @@ pub fn info_strings() -> (String, String) {
|
||||
/// Helper function to format paths according to OS, avoids bugs on Linux
|
||||
pub fn fmt_path(path: String) -> String {
|
||||
let sep = &MAIN_SEPARATOR.to_string();
|
||||
let path = path.replace("/", &sep).replace("\\", &sep);
|
||||
path
|
||||
path.replace("/", sep).replace("\\", sep)
|
||||
}
|
||||
|
||||
fn log_build_info() {
|
||||
@@ -103,16 +102,13 @@ fn real_main() -> i32 {
|
||||
}
|
||||
|
||||
// special cases for certain lifecycle commands
|
||||
match args.subcommand() {
|
||||
("init", Some(init_args)) => {
|
||||
if init_args.is_present("here") {
|
||||
current_dir = Some(env::current_dir().unwrap_or_else(|e| {
|
||||
panic!("Error creating config file: {}", e);
|
||||
}));
|
||||
}
|
||||
create_path = true;
|
||||
if let ("init", Some(init_args)) = args.subcommand() {
|
||||
if init_args.is_present("here") {
|
||||
current_dir = Some(env::current_dir().unwrap_or_else(|e| {
|
||||
panic!("Error creating config file: {}", e);
|
||||
}));
|
||||
}
|
||||
_ => {}
|
||||
create_path = true;
|
||||
}
|
||||
|
||||
// Load relevant config, try and load a wallet config file
|
||||
@@ -136,9 +132,8 @@ fn real_main() -> i32 {
|
||||
// Load logging config
|
||||
let mut l = config.members.logging.clone().unwrap();
|
||||
// no logging to stdout if we're running cli
|
||||
match args.subcommand() {
|
||||
("cli", _) => l.log_to_stdout = true,
|
||||
_ => {}
|
||||
if let ("cli", _) = args.subcommand() {
|
||||
l.log_to_stdout = true
|
||||
};
|
||||
init_logger(Some(l), None);
|
||||
info!(
|
||||
@@ -147,7 +142,7 @@ fn real_main() -> i32 {
|
||||
);
|
||||
log_build_info();
|
||||
|
||||
global::init_global_chain_type(config.members.wallet.chain_type.as_ref().unwrap().clone());
|
||||
global::init_global_chain_type(*config.members.wallet.chain_type.as_ref().unwrap());
|
||||
|
||||
global::init_global_accept_fee_base(config.members.wallet.accept_fee_base());
|
||||
let wallet_config = config.clone().members.wallet;
|
||||
|
||||
+2
-3
@@ -14,7 +14,6 @@
|
||||
|
||||
//! Build hooks to spit out version+build time info
|
||||
|
||||
use built;
|
||||
use std::env;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
@@ -28,12 +27,12 @@ fn main() {
|
||||
|
||||
if cfg!(target_os = "windows") {
|
||||
Command::new("cmd")
|
||||
.args(&["/C", &git_hooks])
|
||||
.args(["/C", &git_hooks])
|
||||
.output()
|
||||
.expect("failed to execute git config for hooks");
|
||||
} else {
|
||||
Command::new("sh")
|
||||
.args(&["-c", &git_hooks])
|
||||
.args(["-c", &git_hooks])
|
||||
.output()
|
||||
.expect("failed to execute git config for hooks");
|
||||
}
|
||||
|
||||
+6
-8
@@ -33,12 +33,11 @@ use rustyline::validate::Validator;
|
||||
use rustyline::{CompletionType, Config, Context, EditMode, Editor, Helper, OutputStreamType};
|
||||
use std::borrow::Cow::{self, Borrowed, Owned};
|
||||
use std::sync::mpsc::{channel, Receiver};
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
const COLORED_PROMPT: &'static str = "\x1b[36mgrin-wallet>\x1b[0m ";
|
||||
const PROMPT: &'static str = "grin-wallet> ";
|
||||
const COLORED_PROMPT: &str = "\x1b[36mgrin-wallet>\x1b[0m ";
|
||||
const PROMPT: &str = "grin-wallet> ";
|
||||
//const HISTORY_PATH: &str = ".history";
|
||||
|
||||
// static for keeping track of current stdin buffer contents
|
||||
@@ -109,7 +108,7 @@ pub fn start_updater_thread(rx: Receiver<StatusMessage>) -> Result<(), Error> {
|
||||
|
||||
pub fn command_loop<L, C, K>(
|
||||
config: GlobalWalletConfig,
|
||||
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>,
|
||||
wallet_inst: grin_wallet_libwallet::WalletHandle<'static, L, C, K>,
|
||||
keychain_mask: Option<SecretKey>,
|
||||
global_wallet_args: &GlobalArgs,
|
||||
test_mode: bool,
|
||||
@@ -155,7 +154,7 @@ where
|
||||
start_updater_thread(rx)?;
|
||||
|
||||
// start the automatic updater
|
||||
owner_api.start_updater((&keychain_mask).as_ref(), Duration::from_secs(30))?;
|
||||
owner_api.start_updater(keychain_mask.as_ref(), Duration::from_secs(30))?;
|
||||
let mut wallet_opened = false;
|
||||
loop {
|
||||
match reader.readline(PROMPT) {
|
||||
@@ -178,8 +177,7 @@ where
|
||||
// Just add 'grin-wallet' to each command behind the scenes
|
||||
// so we don't need to maintain a separate definition file
|
||||
let augmented_command = format!("grin-wallet {}", command);
|
||||
let args =
|
||||
app.get_matches_from_safe_borrow(augmented_command.trim().split_whitespace());
|
||||
let args = app.get_matches_from_safe_borrow(augmented_command.split_whitespace());
|
||||
let done = match args {
|
||||
Ok(args) => {
|
||||
// handle opening /closing separately
|
||||
@@ -230,7 +228,7 @@ where
|
||||
keychain_mask.clone(),
|
||||
&wallet_config,
|
||||
tor_config,
|
||||
&global_wallet_args,
|
||||
global_wallet_args,
|
||||
&args,
|
||||
test_mode,
|
||||
true,
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#[allow(clippy::module_inception)]
|
||||
mod cli;
|
||||
|
||||
pub use cli::command_loop;
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ where
|
||||
C: NodeClient + 'static,
|
||||
{
|
||||
// Check the node version info, and exit with report if we're not compatible
|
||||
let global_wallet_args = wallet_args::parse_global_args(&config.members.wallet, &wallet_args)
|
||||
let global_wallet_args = wallet_args::parse_global_args(&config.members.wallet, wallet_args)
|
||||
.expect("Can't read configuration file");
|
||||
node_client.set_node_api_secret(global_wallet_args.node_api_secret.clone());
|
||||
|
||||
|
||||
+50
-95
@@ -106,7 +106,7 @@ fn prompt_password_confirm() -> Result<ZeroingString, Error> {
|
||||
}
|
||||
|
||||
fn prompt_recovery_phrase<L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>,
|
||||
wallet: grin_wallet_libwallet::WalletHandle<'static, L, C, K>,
|
||||
) -> Result<ZeroingString, ParseError>
|
||||
where
|
||||
DefaultWalletImpl<C>: WalletInst<'static, L, C, K>,
|
||||
@@ -198,7 +198,7 @@ fn prompt_pay_invoice(slate: &Slate, dest: &str) -> Result<bool, ParseError> {
|
||||
"* {} of your wallet funds will be added to the transaction to pay this invoice.",
|
||||
amount
|
||||
);
|
||||
if dest.len() > 0 {
|
||||
if !dest.is_empty() {
|
||||
println!("* The wallet will IMMEDIATELY attempt to send the resulting transaction to the wallet listening at: '{}'.", dest);
|
||||
println!("* If other wallet is not listening, the resulting transaction will output as a slatepack which you can manually send back to the invoice creator.");
|
||||
} else {
|
||||
@@ -239,7 +239,7 @@ fn prompt_pay_invoice(slate: &Slate, dest: &str) -> Result<bool, ParseError> {
|
||||
pub fn inst_wallet<L, C, K>(
|
||||
config: WalletConfig,
|
||||
node_client: C,
|
||||
) -> Result<Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>, ParseError>
|
||||
) -> Result<grin_wallet_libwallet::WalletHandle<'static, L, C, K>, ParseError>
|
||||
where
|
||||
DefaultWalletImpl<C>: WalletInst<'static, L, C, K>,
|
||||
L: WalletLCProvider<'static, C, K>,
|
||||
@@ -294,14 +294,7 @@ fn parse_u64(arg: &str, name: &str) -> Result<u64, ParseError> {
|
||||
|
||||
// As above, but optional
|
||||
fn parse_u64_or_none(arg: Option<&str>) -> Option<u64> {
|
||||
let val = match arg {
|
||||
Some(a) => a.parse::<u64>(),
|
||||
None => return None,
|
||||
};
|
||||
match val {
|
||||
Ok(v) => Some(v),
|
||||
Err(_) => None,
|
||||
}
|
||||
arg?.parse().ok()
|
||||
}
|
||||
|
||||
pub fn parse_global_args(
|
||||
@@ -319,10 +312,7 @@ pub fn parse_global_args(
|
||||
}
|
||||
let api_secret = get_first_line(config.api_secret_path.clone());
|
||||
let node_api_secret = get_first_line(config.node_api_secret_path.clone());
|
||||
let password = match args.value_of("pass") {
|
||||
None => None,
|
||||
Some(p) => Some(ZeroingString::from(p)),
|
||||
};
|
||||
let password = args.value_of("pass").map(ZeroingString::from);
|
||||
|
||||
let tls_conf = match config.tls_certificate_file.clone() {
|
||||
None => None,
|
||||
@@ -349,7 +339,7 @@ pub fn parse_global_args(
|
||||
}
|
||||
|
||||
pub fn parse_init_args<L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>,
|
||||
wallet: grin_wallet_libwallet::WalletHandle<'static, L, C, K>,
|
||||
config: &WalletConfig,
|
||||
g_args: &command::GlobalArgs,
|
||||
args: &ArgMatches,
|
||||
@@ -431,15 +421,9 @@ pub fn parse_scan_rewind_hash_args(
|
||||
}
|
||||
|
||||
pub fn parse_account_args(account_args: &ArgMatches) -> Result<command::AccountArgs, ParseError> {
|
||||
let create = match account_args.value_of("create") {
|
||||
None => None,
|
||||
Some(s) => Some(s.to_owned()),
|
||||
};
|
||||
let create = account_args.value_of("create").map(|s| s.to_owned());
|
||||
|
||||
let active = match account_args.value_of("active") {
|
||||
None => None,
|
||||
Some(s) => Some(s.to_owned()),
|
||||
};
|
||||
let active = account_args.value_of("active").map(|s| s.to_owned());
|
||||
|
||||
if create.is_some() && active.is_some() {
|
||||
let msg = "create and active cannot both be present".to_string();
|
||||
@@ -490,11 +474,7 @@ pub fn parse_send_args(args: &ArgMatches) -> Result<command::SendArgs, ParseErro
|
||||
let late_lock = args.is_present("late_lock");
|
||||
|
||||
// dest
|
||||
let dest = if let Some(dest) = args.value_of("dest") {
|
||||
Some(dest.to_owned())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let dest = args.value_of("dest").map(|dest| dest.to_owned());
|
||||
|
||||
// change_outputs
|
||||
let change_outputs = parse_required(args, "change_outputs")?;
|
||||
@@ -542,10 +522,7 @@ pub fn parse_send_args(args: &ArgMatches) -> Result<command::SendArgs, ParseErro
|
||||
None
|
||||
};
|
||||
|
||||
let bridge = match args.value_of("bridge") {
|
||||
Some(b) => Some(b.to_string()),
|
||||
None => None,
|
||||
};
|
||||
let bridge = args.value_of("bridge").map(|b| b.to_string());
|
||||
|
||||
let slatepack_qr = args.is_present("slatepack_qr");
|
||||
|
||||
@@ -578,7 +555,7 @@ pub fn parse_receive_args(args: &ArgMatches) -> Result<command::ReceiveArgs, Par
|
||||
let file = args.value_of("input").unwrap().to_owned();
|
||||
// validate input
|
||||
if !Path::new(&file).is_file() {
|
||||
let msg = format!("File {} not found.", &file);
|
||||
let msg = format!("File {} not found.", file);
|
||||
return Err(ParseError::ArgumentError(msg));
|
||||
}
|
||||
Some(file)
|
||||
@@ -620,7 +597,7 @@ pub fn parse_unpack_args(args: &ArgMatches) -> Result<command::ReceiveArgs, Pars
|
||||
let file = args.value_of("input").unwrap().to_owned();
|
||||
// validate input
|
||||
if !Path::new(&file).is_file() {
|
||||
let msg = format!("File {} not found.", &file);
|
||||
let msg = format!("File {} not found.", file);
|
||||
return Err(ParseError::ArgumentError(msg));
|
||||
}
|
||||
Some(file)
|
||||
@@ -664,7 +641,7 @@ pub fn parse_finalize_args(args: &ArgMatches) -> Result<command::FinalizeArgs, P
|
||||
let file = args.value_of("input").unwrap().to_owned();
|
||||
// validate input
|
||||
if !Path::new(&file).is_file() {
|
||||
let msg = format!("File {} not found.", &file);
|
||||
let msg = format!("File {} not found.", file);
|
||||
return Err(ParseError::ArgumentError(msg));
|
||||
}
|
||||
Some(file)
|
||||
@@ -719,11 +696,7 @@ pub fn parse_issue_invoice_args(
|
||||
};
|
||||
|
||||
// dest, for encryption
|
||||
let dest = if let Some(dest) = args.value_of("dest") {
|
||||
Some(dest.to_owned())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let dest = args.value_of("dest").map(|dest| dest.to_owned());
|
||||
|
||||
let outfile = parse_optional(args, "outfile")?;
|
||||
|
||||
@@ -756,7 +729,7 @@ where
|
||||
let file = args.value_of("input").unwrap().to_owned();
|
||||
// validate input
|
||||
if !Path::new(&file).is_file() {
|
||||
let msg = format!("File {} not found.", &file);
|
||||
let msg = format!("File {} not found.", file);
|
||||
return Err(Error::GenericError(msg));
|
||||
}
|
||||
Some(file)
|
||||
@@ -823,11 +796,7 @@ pub fn parse_process_invoice_args(
|
||||
|
||||
let slatepack_qr = args.is_present("slatepack_qr");
|
||||
|
||||
let ret_address = if let Some(a) = ret_address {
|
||||
Some(a.to_string())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let ret_address = ret_address.map(|a| a.to_string());
|
||||
|
||||
Ok(command::ProcessInvoiceArgs {
|
||||
minimum_confirmations: min_c,
|
||||
@@ -907,7 +876,7 @@ pub fn parse_post_args(args: &ArgMatches) -> Result<command::PostArgs, ParseErro
|
||||
let file = args.value_of("input").unwrap().to_owned();
|
||||
// validate input
|
||||
if !Path::new(&file).is_file() {
|
||||
let msg = format!("File {} not found.", &file);
|
||||
let msg = format!("File {} not found.", file);
|
||||
return Err(ParseError::ArgumentError(msg));
|
||||
}
|
||||
Some(file)
|
||||
@@ -934,10 +903,7 @@ pub fn parse_repost_args(args: &ArgMatches) -> Result<command::RepostArgs, Parse
|
||||
};
|
||||
|
||||
let fluff = args.is_present("fluff");
|
||||
let dump_file = match args.value_of("dumpfile") {
|
||||
None => None,
|
||||
Some(d) => Some(d.to_owned()),
|
||||
};
|
||||
let dump_file = args.value_of("dumpfile").map(|d| d.to_owned());
|
||||
|
||||
Ok(command::RepostArgs {
|
||||
id: tx_id.unwrap(),
|
||||
@@ -1024,17 +990,11 @@ pub fn wallet_command<C, F>(
|
||||
where
|
||||
C: NodeClient + 'static + Clone,
|
||||
F: FnOnce(
|
||||
Arc<
|
||||
Mutex<
|
||||
Box<
|
||||
dyn WalletInst<
|
||||
'static,
|
||||
DefaultLCProvider<C, keychain::ExtKeychain>,
|
||||
C,
|
||||
keychain::ExtKeychain,
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
grin_wallet_libwallet::WalletHandle<
|
||||
'static,
|
||||
DefaultLCProvider<C, keychain::ExtKeychain>,
|
||||
C,
|
||||
keychain::ExtKeychain,
|
||||
>,
|
||||
),
|
||||
{
|
||||
@@ -1047,7 +1007,7 @@ where
|
||||
wallet_config.check_node_api_http_addr = sa.to_string().clone();
|
||||
}
|
||||
|
||||
let global_wallet_args = arg_parse!(parse_global_args(&wallet_config, &wallet_args));
|
||||
let global_wallet_args = arg_parse!(parse_global_args(&wallet_config, wallet_args));
|
||||
|
||||
node_client.set_node_url(&wallet_config.check_node_api_http_addr);
|
||||
node_client.set_node_api_secret(global_wallet_args.node_api_secret.clone());
|
||||
@@ -1132,7 +1092,7 @@ where
|
||||
&wallet_config,
|
||||
tor_config,
|
||||
&global_wallet_args,
|
||||
&wallet_args,
|
||||
wallet_args,
|
||||
test_mode,
|
||||
false,
|
||||
)
|
||||
@@ -1147,7 +1107,7 @@ where
|
||||
}
|
||||
|
||||
fn open_wallet<L, C, K>(
|
||||
wallet: &Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>,
|
||||
wallet: &grin_wallet_libwallet::WalletHandle<'static, L, C, K>,
|
||||
global_wallet_args: &GlobalArgs,
|
||||
wallet_args: &ArgMatches,
|
||||
) -> Result<Option<SecretKey>, Error>
|
||||
@@ -1171,6 +1131,7 @@ where
|
||||
Ok(mask)
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn parse_and_execute<L, C, K>(
|
||||
owner_api: &mut Owner<L, C, K>,
|
||||
keychain_mask: Option<SecretKey>,
|
||||
@@ -1187,7 +1148,7 @@ where
|
||||
C: NodeClient + 'static,
|
||||
K: keychain::Keychain + 'static,
|
||||
{
|
||||
let km = (&keychain_mask).as_ref();
|
||||
let km = keychain_mask.as_ref();
|
||||
|
||||
if test_mode {
|
||||
owner_api.doctest_mode = true;
|
||||
@@ -1200,13 +1161,13 @@ where
|
||||
owner_api.wallet_inst.clone(),
|
||||
wallet_config,
|
||||
global_wallet_args,
|
||||
&args,
|
||||
args,
|
||||
test_mode,
|
||||
));
|
||||
command::init(owner_api, &global_wallet_args, a, test_mode)
|
||||
command::init(owner_api, global_wallet_args, a, test_mode)
|
||||
}
|
||||
("recover", Some(_)) => {
|
||||
let a = arg_parse!(parse_recover_args(&global_wallet_args,));
|
||||
let a = arg_parse!(parse_recover_args(global_wallet_args,));
|
||||
command::recover(owner_api, a)
|
||||
}
|
||||
("listen", Some(args)) => {
|
||||
@@ -1214,11 +1175,7 @@ where
|
||||
if let Some(port) = args.value_of("port") {
|
||||
c.api_listen_port = port.parse().unwrap();
|
||||
}
|
||||
let bridge = if let Some(bridge) = args.value_of("bridge") {
|
||||
Some(bridge.into())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let bridge = args.value_of("bridge").map(|bridge| bridge.into());
|
||||
let use_tor = if args.is_present("no_tor") {
|
||||
Some(false)
|
||||
} else {
|
||||
@@ -1239,7 +1196,7 @@ where
|
||||
let mut c = wallet_config.clone();
|
||||
let mut g = global_wallet_args.clone();
|
||||
g.tls_conf = None;
|
||||
arg_parse!(parse_owner_api_args(&mut c, &args));
|
||||
arg_parse!(parse_owner_api_args(&mut c, args));
|
||||
command::owner_api(owner_api, keychain_mask, &c, &g, test_mode)
|
||||
}
|
||||
("web", Some(_)) => command::owner_api(
|
||||
@@ -1251,7 +1208,7 @@ where
|
||||
),
|
||||
("rewind_hash", Some(_)) => command::rewind_hash(owner_api, km),
|
||||
("scan_rewind_hash", Some(args)) => {
|
||||
let a = arg_parse!(parse_scan_rewind_hash_args(&args));
|
||||
let a = arg_parse!(parse_scan_rewind_hash_args(args));
|
||||
command::scan_rewind_hash(
|
||||
owner_api,
|
||||
a,
|
||||
@@ -1259,11 +1216,11 @@ where
|
||||
)
|
||||
}
|
||||
("account", Some(args)) => {
|
||||
let a = arg_parse!(parse_account_args(&args));
|
||||
let a = arg_parse!(parse_account_args(args));
|
||||
command::account(owner_api, km, a)
|
||||
}
|
||||
("send", Some(args)) => {
|
||||
let a = arg_parse!(parse_send_args(&args));
|
||||
let a = arg_parse!(parse_send_args(args));
|
||||
command::send(
|
||||
owner_api,
|
||||
km,
|
||||
@@ -1274,29 +1231,27 @@ where
|
||||
)
|
||||
}
|
||||
("receive", Some(args)) => {
|
||||
let a = arg_parse!(parse_receive_args(&args));
|
||||
let a = arg_parse!(parse_receive_args(args));
|
||||
command::receive(owner_api, km, a, tor_config, test_mode)
|
||||
}
|
||||
("unpack", Some(args)) => {
|
||||
let a = arg_parse!(parse_unpack_args(&args));
|
||||
let a = arg_parse!(parse_unpack_args(args));
|
||||
let slatepack = command::read_slatepack(a)?;
|
||||
command::unpack(owner_api, km, slatepack)
|
||||
}
|
||||
("finalize", Some(args)) => {
|
||||
let a = arg_parse!(parse_finalize_args(&args));
|
||||
let a = arg_parse!(parse_finalize_args(args));
|
||||
command::finalize(owner_api, km, a)
|
||||
}
|
||||
("invoice", Some(args)) => {
|
||||
let a = arg_parse!(parse_issue_invoice_args(&args));
|
||||
let a = arg_parse!(parse_issue_invoice_args(args));
|
||||
command::issue_invoice_tx(owner_api, km, a)
|
||||
}
|
||||
("pay", Some(args)) => {
|
||||
// get slate first
|
||||
let (slate, address) = get_slate(owner_api, km, args)?;
|
||||
|
||||
let a = arg_parse!(parse_process_invoice_args(
|
||||
&args, !test_mode, slate, address
|
||||
));
|
||||
let a = arg_parse!(parse_process_invoice_args(args, !test_mode, slate, address));
|
||||
command::process_invoice(
|
||||
owner_api,
|
||||
km,
|
||||
@@ -1307,7 +1262,7 @@ where
|
||||
)
|
||||
}
|
||||
("info", Some(args)) => {
|
||||
let a = arg_parse!(parse_info_args(&args));
|
||||
let a = arg_parse!(parse_info_args(args));
|
||||
command::info(
|
||||
owner_api,
|
||||
km,
|
||||
@@ -1318,11 +1273,11 @@ where
|
||||
("outputs", Some(_)) => command::outputs(
|
||||
owner_api,
|
||||
km,
|
||||
&global_wallet_args,
|
||||
global_wallet_args,
|
||||
wallet_config.dark_background_color_scheme.unwrap_or(true),
|
||||
),
|
||||
("txs", Some(args)) => {
|
||||
let a = arg_parse!(parse_txs_args(&args));
|
||||
let a = arg_parse!(parse_txs_args(args));
|
||||
command::txs(
|
||||
owner_api,
|
||||
km,
|
||||
@@ -1331,28 +1286,28 @@ where
|
||||
)
|
||||
}
|
||||
("post", Some(args)) => {
|
||||
let a = arg_parse!(parse_post_args(&args));
|
||||
let a = arg_parse!(parse_post_args(args));
|
||||
command::post(owner_api, km, a)
|
||||
}
|
||||
("repost", Some(args)) => {
|
||||
let a = arg_parse!(parse_repost_args(&args));
|
||||
let a = arg_parse!(parse_repost_args(args));
|
||||
command::repost(owner_api, km, a)
|
||||
}
|
||||
("cancel", Some(args)) => {
|
||||
let a = arg_parse!(parse_cancel_args(&args));
|
||||
let a = arg_parse!(parse_cancel_args(args));
|
||||
command::cancel(owner_api, km, a)
|
||||
}
|
||||
("export_proof", Some(args)) => {
|
||||
let a = arg_parse!(parse_export_proof_args(&args));
|
||||
let a = arg_parse!(parse_export_proof_args(args));
|
||||
command::proof_export(owner_api, km, a)
|
||||
}
|
||||
("verify_proof", Some(args)) => {
|
||||
let a = arg_parse!(parse_verify_proof_args(&args));
|
||||
let a = arg_parse!(parse_verify_proof_args(args));
|
||||
command::proof_verify(owner_api, km, a)
|
||||
}
|
||||
("address", Some(_)) => command::address(owner_api, km),
|
||||
("scan", Some(args)) => {
|
||||
let a = arg_parse!(parse_check_args(&args));
|
||||
let a = arg_parse!(parse_check_args(args));
|
||||
command::scan(owner_api, km, a)
|
||||
}
|
||||
("open", Some(_)) => {
|
||||
|
||||
+10
-7
@@ -181,7 +181,10 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller::
|
||||
let output = String::from_utf8(output.stdout).unwrap();
|
||||
let accounts: Vec<_> = output
|
||||
.lines()
|
||||
.filter_map(|line| line.strip_prefix("Address for account - "))
|
||||
.filter_map(|line| {
|
||||
line.split_once("Address for account - ")
|
||||
.map(|(_, name)| name)
|
||||
})
|
||||
.collect();
|
||||
assert_eq!(accounts, ["account_1", "default", "account_1"]);
|
||||
|
||||
@@ -203,7 +206,7 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller::
|
||||
let wallet_config1 = config1.clone().members.wallet;
|
||||
let (wallet1, mask1_i) =
|
||||
instantiate_wallet(wallet_config1, client1.clone(), "password1", "default")?;
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
let mask1 = mask1_i.as_ref();
|
||||
let api1 = Owner::new(wallet1.clone(), None, config1.config_file_path.clone());
|
||||
|
||||
api1.set_active_account(mask1, "mining")?;
|
||||
@@ -303,7 +306,7 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller::
|
||||
"password1",
|
||||
"default",
|
||||
)?;
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
let mask1 = mask1_i.as_ref();
|
||||
let api1 = Owner::new(wallet1.clone(), None, config1.config_file_path.clone());
|
||||
|
||||
// Check our transaction log, should have 10 entries
|
||||
@@ -333,7 +336,7 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller::
|
||||
"password2",
|
||||
"default",
|
||||
)?;
|
||||
let mask2 = (&mask2_i).as_ref();
|
||||
let mask2 = mask2_i.as_ref();
|
||||
let api2 = Owner::new(wallet2.clone(), None, config2.config_file_path.clone());
|
||||
|
||||
api2.set_active_account(mask2, "account_1")?;
|
||||
@@ -471,7 +474,7 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller::
|
||||
"password1",
|
||||
"default",
|
||||
)?;
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
let mask1 = mask1_i.as_ref();
|
||||
let api1 = Owner::new(wallet1.clone(), None, config1.config_file_path.clone());
|
||||
|
||||
api1.set_active_account(mask1, "mining")?;
|
||||
@@ -537,7 +540,7 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller::
|
||||
"password1",
|
||||
"default",
|
||||
)?;
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
let mask1 = mask1_i.as_ref();
|
||||
let api1 = Owner::new(wallet1.clone(), None, config1.config_file_path.clone());
|
||||
|
||||
api1.set_active_account(mask1, "mining")?;
|
||||
@@ -678,7 +681,7 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller::
|
||||
// get tx output via -tx parameter
|
||||
api2.set_active_account(mask2, "default")?;
|
||||
let (_, txs) = api2.retrieve_txs(mask2, true, None, None, None)?;
|
||||
let some_tx_id = txs[0].tx_slate_id.clone();
|
||||
let some_tx_id = txs[0].tx_slate_id;
|
||||
assert!(some_tx_id.is_some());
|
||||
let tx_id = some_tx_id.unwrap().to_string().clone();
|
||||
let arg_vec = vec!["grin-wallet", "-p", "password2", "txs", "-t", &tx_id[..]];
|
||||
|
||||
+20
-17
@@ -160,7 +160,7 @@ pub fn config_command_wallet(
|
||||
let mut config_file_name = current_dir.clone();
|
||||
config_file_name.push("grin-wallet.toml");
|
||||
if config_file_name.exists() {
|
||||
return Err(grin_wallet_controller::Error::ArgumentError(
|
||||
Err(grin_wallet_controller::Error::ArgumentError(
|
||||
"grin-wallet.toml already exists in the target directory. Please remove it first"
|
||||
.to_owned(),
|
||||
))?;
|
||||
@@ -217,6 +217,7 @@ fn get_wallet_subcommand<'a>(
|
||||
|
||||
/// Helper to create an instance of the LMDB wallet
|
||||
#[allow(dead_code)]
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub fn instantiate_wallet(
|
||||
mut wallet_config: WalletConfig,
|
||||
node_client: LocalWalletClient,
|
||||
@@ -224,17 +225,11 @@ pub fn instantiate_wallet(
|
||||
account: &str,
|
||||
) -> Result<
|
||||
(
|
||||
Arc<
|
||||
Mutex<
|
||||
Box<
|
||||
dyn WalletInst<
|
||||
'static,
|
||||
DefaultLCProvider<LocalWalletClient, ExtKeychain>,
|
||||
LocalWalletClient,
|
||||
ExtKeychain,
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
grin_wallet_libwallet::WalletHandle<
|
||||
'static,
|
||||
DefaultLCProvider<LocalWalletClient, ExtKeychain>,
|
||||
LocalWalletClient,
|
||||
ExtKeychain,
|
||||
>,
|
||||
Option<SecretKey>,
|
||||
),
|
||||
@@ -292,13 +287,21 @@ pub fn execute_command_no_setup<C, F>(
|
||||
where
|
||||
C: NodeClient + 'static + Clone,
|
||||
F: FnOnce(
|
||||
Arc<Mutex<Box<dyn WalletInst<'static, DefaultLCProvider<C, ExtKeychain>, C, ExtKeychain>>>>,
|
||||
grin_wallet_libwallet::WalletHandle<
|
||||
'static,
|
||||
DefaultLCProvider<C, ExtKeychain>,
|
||||
C,
|
||||
ExtKeychain,
|
||||
>,
|
||||
),
|
||||
{
|
||||
let args = app.clone().get_matches_from(arg_vec);
|
||||
let _ = get_wallet_subcommand(test_dir, wallet_name, args.clone());
|
||||
// Avoid conflicts with local wallets
|
||||
let wallet_dir = PathBuf::from(test_dir).join(format!("{}_bootstrap", wallet_name));
|
||||
let mut config =
|
||||
config::initial_setup_wallet(&ChainTypes::AutomatedTesting, None, true).unwrap();
|
||||
config::initial_setup_wallet(&ChainTypes::AutomatedTesting, Some(wallet_dir), true)
|
||||
.unwrap();
|
||||
let mut wallet_config = config.clone().members.wallet;
|
||||
wallet_config.chain_type = None;
|
||||
wallet_config.api_secret_path = None;
|
||||
@@ -372,7 +375,7 @@ where
|
||||
{
|
||||
let url = Url::parse(dest).unwrap();
|
||||
let req_val: Value = serde_json::from_str(req).unwrap();
|
||||
let req = EncryptedRequest::from_json(sec_req_id, &req_val, &shared_key).unwrap();
|
||||
let req = EncryptedRequest::from_json(sec_req_id, &req_val, shared_key).unwrap();
|
||||
let res = post(&url, None, &req).map_err(|e| {
|
||||
let err_string = format!("{}", e);
|
||||
println!("{}", err_string);
|
||||
@@ -444,7 +447,7 @@ pub fn derive_ecdh_key(sec_key_str: &str, other_pubkey: &PublicKey) -> SecretKey
|
||||
let secp_inst = static_secp_instance();
|
||||
let secp = secp_inst.lock();
|
||||
|
||||
let mut shared_pubkey = other_pubkey.clone();
|
||||
let mut shared_pubkey = *other_pubkey;
|
||||
shared_pubkey.mul_assign(&secp, &sec_key).unwrap();
|
||||
|
||||
let x_coord = shared_pubkey.serialize_vec(&secp, true);
|
||||
@@ -460,7 +463,7 @@ pub struct WalletAPIReturnError {
|
||||
|
||||
impl std::fmt::Display for WalletAPIReturnError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{} - {}", self.code, &self.message)
|
||||
write!(f, "{} - {}", self.code, self.message)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@ use grin_keychain::ExtKeychain;
|
||||
use grin_util::secp::key::SecretKey;
|
||||
use grin_util::{from_hex, static_secp_instance};
|
||||
use grin_wallet_impls::DefaultLCProvider;
|
||||
use serde_json;
|
||||
|
||||
#[macro_use]
|
||||
mod common;
|
||||
@@ -80,7 +79,7 @@ fn owner_v3_init_secure() -> Result<(), grin_wallet_controller::Error> {
|
||||
&JsonId::IntId(1),
|
||||
1,
|
||||
"http://127.0.0.1:33420/v3/owner",
|
||||
&req,
|
||||
req,
|
||||
&sec_key,
|
||||
)?;
|
||||
println!("RES 1: {:?}", res);
|
||||
@@ -88,7 +87,7 @@ fn owner_v3_init_secure() -> Result<(), grin_wallet_controller::Error> {
|
||||
assert_eq!(res.unwrap_err().code, -32001);
|
||||
|
||||
// 2) Call any function on the V3 api without calling 'init_secure_api` first
|
||||
let res = send_request::<String>(1, "http://127.0.0.1:33420/v3/owner", &req)?;
|
||||
let res = send_request::<String>(1, "http://127.0.0.1:33420/v3/owner", req)?;
|
||||
println!("RES 2: {:?}", res);
|
||||
assert!(res.is_err());
|
||||
assert_eq!(res.unwrap_err().code, -32001);
|
||||
@@ -108,7 +107,7 @@ fn owner_v3_init_secure() -> Result<(), grin_wallet_controller::Error> {
|
||||
&JsonId::StrId(String::from("1")),
|
||||
1,
|
||||
"http://127.0.0.1:33420/v3/owner",
|
||||
&req,
|
||||
req,
|
||||
&shared_key,
|
||||
)?;
|
||||
println!("RES 4: {:?}", res);
|
||||
@@ -122,7 +121,7 @@ fn owner_v3_init_secure() -> Result<(), grin_wallet_controller::Error> {
|
||||
&JsonId::StrId(String::from("1")),
|
||||
1,
|
||||
"http://127.0.0.1:33420/v3/owner",
|
||||
&req,
|
||||
req,
|
||||
&bad_key,
|
||||
)?;
|
||||
println!("RES 5: {:?}", res);
|
||||
@@ -164,7 +163,7 @@ fn owner_v3_init_secure() -> Result<(), grin_wallet_controller::Error> {
|
||||
&JsonId::StrId(String::from("1")),
|
||||
1,
|
||||
"http://127.0.0.1:33420/v3/owner",
|
||||
&req.to_string(),
|
||||
req,
|
||||
&shared_key,
|
||||
)?;
|
||||
println!("RES 8: {:?}", res);
|
||||
@@ -178,7 +177,7 @@ fn owner_v3_init_secure() -> Result<(), grin_wallet_controller::Error> {
|
||||
&JsonId::StrId(String::from("1")),
|
||||
1,
|
||||
"http://127.0.0.1:33420/v3/owner",
|
||||
&req,
|
||||
req,
|
||||
&shared_key,
|
||||
)?;
|
||||
println!("RES 9: {:?}", res);
|
||||
@@ -199,7 +198,7 @@ fn owner_v3_init_secure() -> Result<(), grin_wallet_controller::Error> {
|
||||
&JsonId::StrId(String::from("1")),
|
||||
1,
|
||||
"http://127.0.0.1:33420/v3/owner",
|
||||
&req,
|
||||
req,
|
||||
&shared_key,
|
||||
)?;
|
||||
println!("RES 11: {:?}", res);
|
||||
@@ -232,7 +231,7 @@ fn owner_v3_init_secure() -> Result<(), grin_wallet_controller::Error> {
|
||||
&JsonId::StrId(String::from("13")),
|
||||
1,
|
||||
"http://127.0.0.1:33420/v3/owner",
|
||||
&req,
|
||||
req,
|
||||
&shared_key,
|
||||
)?;
|
||||
println!("RES 13: {:?}", res);
|
||||
|
||||
+26
-20
@@ -30,7 +30,6 @@ use grin_keychain::ExtKeychain;
|
||||
use grin_wallet_config::GlobalWalletConfig;
|
||||
use grin_wallet_impls::DefaultLCProvider;
|
||||
use grin_wallet_libwallet::{InitTxArgs, Slate, SlateVersion, VersionedSlate};
|
||||
use serde_json;
|
||||
|
||||
use grin_util::Mutex;
|
||||
use std::path::PathBuf;
|
||||
@@ -55,6 +54,7 @@ fn owner_v3_lifecycle() -> Result<(), grin_wallet_controller::Error> {
|
||||
let app = App::from_yaml(yml);
|
||||
|
||||
// Create a new proxy to simulate server and wallet responses
|
||||
#[allow(clippy::type_complexity)]
|
||||
let wallet_proxy_a: Arc<
|
||||
Mutex<
|
||||
WalletProxy<
|
||||
@@ -122,7 +122,7 @@ fn owner_v3_lifecycle() -> Result<(), grin_wallet_controller::Error> {
|
||||
};
|
||||
// give a bit for wallet to init and populate proxy with wallet via callback in thread above
|
||||
thread::sleep(Duration::from_millis(500));
|
||||
let mask2 = (&mask2_i).as_ref();
|
||||
let mask2 = mask2_i.as_ref();
|
||||
let wallet_proxy = wallet_proxy_a.clone();
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
@@ -148,18 +148,24 @@ fn owner_v3_lifecycle() -> Result<(), grin_wallet_controller::Error> {
|
||||
let value: ECDHPubkey = res.unwrap();
|
||||
let shared_key = derive_ecdh_key(sec_key_str, &value.ecdh_pubkey);
|
||||
|
||||
// 2) get the top level directory, should default to ~/.grin/auto
|
||||
// 2) get the top level directory
|
||||
let req = include_str!("data/v3_reqs/get_top_level.req.json");
|
||||
let res = send_request_enc::<String>(
|
||||
&JsonId::StrId(String::from("1")),
|
||||
1,
|
||||
"http://127.0.0.1:43420/v3/owner",
|
||||
&req,
|
||||
req,
|
||||
&shared_key,
|
||||
)?;
|
||||
println!("RES 2: {:?}", res);
|
||||
assert!(res.is_ok());
|
||||
assert!(res.unwrap().contains("auto"));
|
||||
assert_eq!(
|
||||
PathBuf::from(res.unwrap()).canonicalize().unwrap(),
|
||||
PathBuf::from(test_dir)
|
||||
.join("wallet1_bootstrap")
|
||||
.canonicalize()
|
||||
.unwrap()
|
||||
);
|
||||
|
||||
// 3) now set the top level directory to our test wallet dir
|
||||
let req = serde_json::json!({
|
||||
@@ -186,7 +192,7 @@ fn owner_v3_lifecycle() -> Result<(), grin_wallet_controller::Error> {
|
||||
&JsonId::StrId(String::from("1")),
|
||||
1,
|
||||
"http://127.0.0.1:43420/v3/owner",
|
||||
&req,
|
||||
req,
|
||||
&shared_key,
|
||||
)?;
|
||||
println!("RES 4: {:?}", res);
|
||||
@@ -220,7 +226,7 @@ fn owner_v3_lifecycle() -> Result<(), grin_wallet_controller::Error> {
|
||||
&JsonId::StrId(String::from("1")),
|
||||
1,
|
||||
"http://127.0.0.1:43420/v3/owner",
|
||||
&req,
|
||||
req,
|
||||
&shared_key,
|
||||
)?;
|
||||
println!("RES 5: {:?}", res);
|
||||
@@ -232,7 +238,7 @@ fn owner_v3_lifecycle() -> Result<(), grin_wallet_controller::Error> {
|
||||
&JsonId::StrId(String::from("1")),
|
||||
1,
|
||||
"http://127.0.0.1:43420/v3/owner",
|
||||
&req,
|
||||
req,
|
||||
&shared_key,
|
||||
)?;
|
||||
println!("RES 6: {:?}", res);
|
||||
@@ -244,7 +250,7 @@ fn owner_v3_lifecycle() -> Result<(), grin_wallet_controller::Error> {
|
||||
&JsonId::StrId(String::from("1")),
|
||||
1,
|
||||
"http://127.0.0.1:43420/v3/owner",
|
||||
&req,
|
||||
req,
|
||||
&shared_key,
|
||||
)?;
|
||||
println!("RES 7: {:?}", res);
|
||||
@@ -256,7 +262,7 @@ fn owner_v3_lifecycle() -> Result<(), grin_wallet_controller::Error> {
|
||||
&JsonId::StrId(String::from("1")),
|
||||
1,
|
||||
"http://127.0.0.1:43420/v3/owner",
|
||||
&req,
|
||||
req,
|
||||
&shared_key,
|
||||
)?;
|
||||
println!("RES 8: {:?}", res);
|
||||
@@ -313,7 +319,7 @@ fn owner_v3_lifecycle() -> Result<(), grin_wallet_controller::Error> {
|
||||
&JsonId::StrId(String::from("1")),
|
||||
1,
|
||||
"http://127.0.0.1:43420/v3/owner",
|
||||
&req,
|
||||
req,
|
||||
&shared_key,
|
||||
)?;
|
||||
println!("RES 11: {:?}", res);
|
||||
@@ -347,7 +353,7 @@ fn owner_v3_lifecycle() -> Result<(), grin_wallet_controller::Error> {
|
||||
&JsonId::StrId(String::from("1")),
|
||||
1,
|
||||
"http://127.0.0.1:43420/v3/owner",
|
||||
&req,
|
||||
req,
|
||||
&shared_key,
|
||||
)?;
|
||||
println!("RES 13: {:?}", res);
|
||||
@@ -438,7 +444,7 @@ fn owner_v3_lifecycle() -> Result<(), grin_wallet_controller::Error> {
|
||||
&JsonId::StrId(String::from("1")),
|
||||
1,
|
||||
"http://127.0.0.1:43420/v3/owner",
|
||||
&req,
|
||||
req,
|
||||
&shared_key,
|
||||
)?;
|
||||
println!("RES 17: {:?}", res);
|
||||
@@ -449,7 +455,7 @@ fn owner_v3_lifecycle() -> Result<(), grin_wallet_controller::Error> {
|
||||
&JsonId::StrId(String::from("1")),
|
||||
1,
|
||||
"http://127.0.0.1:43420/v3/owner",
|
||||
&req,
|
||||
req,
|
||||
&shared_key,
|
||||
)?;
|
||||
println!("RES 17a: {:?}", res);
|
||||
@@ -461,7 +467,7 @@ fn owner_v3_lifecycle() -> Result<(), grin_wallet_controller::Error> {
|
||||
&JsonId::StrId(String::from("1")),
|
||||
1,
|
||||
"http://127.0.0.1:43420/v3/owner",
|
||||
&req,
|
||||
req,
|
||||
&shared_key,
|
||||
)?;
|
||||
println!("RES 18: {:?}", res);
|
||||
@@ -579,7 +585,7 @@ fn owner_v3_lifecycle() -> Result<(), grin_wallet_controller::Error> {
|
||||
&JsonId::StrId(String::from("1")),
|
||||
1,
|
||||
"http://127.0.0.1:43420/v3/owner",
|
||||
&req,
|
||||
req,
|
||||
&shared_key,
|
||||
)?;
|
||||
assert!(res.is_ok());
|
||||
@@ -589,7 +595,7 @@ fn owner_v3_lifecycle() -> Result<(), grin_wallet_controller::Error> {
|
||||
&JsonId::StrId(String::from("1")),
|
||||
1,
|
||||
"http://127.0.0.1:43420/v3/owner",
|
||||
&req,
|
||||
req,
|
||||
&shared_key,
|
||||
)?;
|
||||
println!("RES 24: {:?}", res);
|
||||
@@ -601,7 +607,7 @@ fn owner_v3_lifecycle() -> Result<(), grin_wallet_controller::Error> {
|
||||
&JsonId::StrId(String::from("1")),
|
||||
1,
|
||||
"http://127.0.0.1:43420/v3/owner",
|
||||
&req,
|
||||
req,
|
||||
&shared_key,
|
||||
)?;
|
||||
println!("RES 25: {:?}", res);
|
||||
@@ -613,7 +619,7 @@ fn owner_v3_lifecycle() -> Result<(), grin_wallet_controller::Error> {
|
||||
&JsonId::StrId(String::from("1")),
|
||||
1,
|
||||
"http://127.0.0.1:43420/v3/owner",
|
||||
&req,
|
||||
req,
|
||||
&shared_key,
|
||||
)?;
|
||||
println!("RES 26: {:?}", res);
|
||||
@@ -625,7 +631,7 @@ fn owner_v3_lifecycle() -> Result<(), grin_wallet_controller::Error> {
|
||||
&JsonId::StrId(String::from("1")),
|
||||
1,
|
||||
"http://127.0.0.1:43420/v3/owner",
|
||||
&req,
|
||||
req,
|
||||
&shared_key,
|
||||
)?;
|
||||
println!("RES 27: {:?}", res);
|
||||
|
||||
@@ -63,7 +63,7 @@ where
|
||||
Ok(serializer.output)
|
||||
}
|
||||
|
||||
impl<'a> ser::Serializer for &'a mut ByteSerializer {
|
||||
impl ser::Serializer for &mut ByteSerializer {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
type SerializeSeq = Self;
|
||||
@@ -226,7 +226,7 @@ impl<'a> ser::Serializer for &'a mut ByteSerializer {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ser::SerializeSeq for &'a mut ByteSerializer {
|
||||
impl ser::SerializeSeq for &mut ByteSerializer {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
@@ -242,7 +242,7 @@ impl<'a> ser::SerializeSeq for &'a mut ByteSerializer {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ser::SerializeTuple for &'a mut ByteSerializer {
|
||||
impl ser::SerializeTuple for &mut ByteSerializer {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
@@ -258,7 +258,7 @@ impl<'a> ser::SerializeTuple for &'a mut ByteSerializer {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ser::SerializeTupleStruct for &'a mut ByteSerializer {
|
||||
impl ser::SerializeTupleStruct for &mut ByteSerializer {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
@@ -274,7 +274,7 @@ impl<'a> ser::SerializeTupleStruct for &'a mut ByteSerializer {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ser::SerializeTupleVariant for &'a mut ByteSerializer {
|
||||
impl ser::SerializeTupleVariant for &mut ByteSerializer {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
@@ -290,7 +290,7 @@ impl<'a> ser::SerializeTupleVariant for &'a mut ByteSerializer {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ser::SerializeMap for &'a mut ByteSerializer {
|
||||
impl ser::SerializeMap for &mut ByteSerializer {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
@@ -313,7 +313,7 @@ impl<'a> ser::SerializeMap for &'a mut ByteSerializer {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ser::SerializeStruct for &'a mut ByteSerializer {
|
||||
impl ser::SerializeStruct for &mut ByteSerializer {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
@@ -329,7 +329,7 @@ impl<'a> ser::SerializeStruct for &'a mut ByteSerializer {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ser::SerializeStructVariant for &'a mut ByteSerializer {
|
||||
impl ser::SerializeStructVariant for &mut ByteSerializer {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
@@ -366,7 +366,7 @@ where
|
||||
Ok(t)
|
||||
}
|
||||
|
||||
impl<'de, 'a> de::Deserializer<'de> for &'a mut ByteDeserializer<'de> {
|
||||
impl<'de> de::Deserializer<'de> for &mut ByteDeserializer<'de> {
|
||||
type Error = Error;
|
||||
|
||||
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
|
||||
|
||||
Reference in New Issue
Block a user