diff --git a/Cargo.lock b/Cargo.lock index 8eaf0317a..7685daefc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -555,16 +555,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "grin_api" version = "1.1.0" +source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#1dd9a874522bd8ffcd4dd320b9ade13ddd3d11c8" dependencies = [ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "grin_chain 1.1.0", - "grin_core 1.1.0", - "grin_p2p 1.1.0", - "grin_pool 1.1.0", - "grin_store 1.1.0", - "grin_util 1.1.0", + "grin_chain 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", + "grin_core 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", + "grin_p2p 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", + "grin_pool 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", + "grin_store 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", + "grin_util 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-rustls 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -586,6 +587,7 @@ dependencies = [ [[package]] name = "grin_chain" version = "1.1.0" +source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#1dd9a874522bd8ffcd4dd320b9ade13ddd3d11c8" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -593,10 +595,10 @@ dependencies = [ "croaring 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "grin_core 1.1.0", - "grin_keychain 1.1.0", - "grin_store 1.1.0", - "grin_util 1.1.0", + "grin_core 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", + "grin_keychain 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", + "grin_store 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", + "grin_util 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -608,6 +610,7 @@ dependencies = [ [[package]] name = "grin_core" version = "1.1.0" +source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#1dd9a874522bd8ffcd4dd320b9ade13ddd3d11c8" dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -616,8 +619,8 @@ dependencies = [ "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "grin_keychain 1.1.0", - "grin_util 1.1.0", + "grin_keychain 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", + "grin_util 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -633,11 +636,12 @@ dependencies = [ [[package]] name = "grin_keychain" version = "1.1.0" +source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#1dd9a874522bd8ffcd4dd320b9ade13ddd3d11c8" dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", - "grin_util 1.1.0", + "grin_util 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", "hmac 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -654,14 +658,15 @@ dependencies = [ [[package]] name = "grin_p2p" version = "1.1.0" +source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#1dd9a874522bd8ffcd4dd320b9ade13ddd3d11c8" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "grin_core 1.1.0", - "grin_store 1.1.0", - "grin_util 1.1.0", + "grin_core 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", + "grin_store 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", + "grin_util 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", @@ -673,15 +678,16 @@ dependencies = [ [[package]] name = "grin_pool" version = "1.1.0" +source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#1dd9a874522bd8ffcd4dd320b9ade13ddd3d11c8" dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "grin_core 1.1.0", - "grin_keychain 1.1.0", - "grin_store 1.1.0", - "grin_util 1.1.0", + "grin_core 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", + "grin_keychain 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", + "grin_store 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", + "grin_util 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", @@ -705,14 +711,15 @@ dependencies = [ [[package]] name = "grin_store" version = "1.1.0" +source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#1dd9a874522bd8ffcd4dd320b9ade13ddd3d11c8" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "croaring 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "grin_core 1.1.0", - "grin_util 1.1.0", + "grin_core 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", + "grin_util 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "lmdb-zero 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -724,6 +731,7 @@ dependencies = [ [[package]] name = "grin_util" version = "1.1.0" +source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#1dd9a874522bd8ffcd4dd320b9ade13ddd3d11c8" dependencies = [ "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -870,12 +878,12 @@ name = "grin_wallet_util" version = "1.1.0" dependencies = [ "dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "grin_api 1.1.0", - "grin_chain 1.1.0", - "grin_core 1.1.0", - "grin_keychain 1.1.0", - "grin_store 1.1.0", - "grin_util 1.1.0", + "grin_api 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", + "grin_chain 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", + "grin_core 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", + "grin_keychain 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", + "grin_store 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", + "grin_util 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2738,7 +2746,15 @@ dependencies = [ "checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" "checksum git2 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "591f8be1674b421644b6c030969520bc3fa12114d2eb467471982ed3e9584e71" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" +"checksum grin_api 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)" = "" +"checksum grin_chain 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)" = "" +"checksum grin_core 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)" = "" +"checksum grin_keychain 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)" = "" +"checksum grin_p2p 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)" = "" +"checksum grin_pool 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)" = "" "checksum grin_secp256k1zkp 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "75e9a265f3eeea4c204470f7262e2c6fe18f3d8ddf5fb24340cb550ac4f909c5" +"checksum grin_store 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)" = "" +"checksum grin_util 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)" = "" "checksum h2 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "910a5e7be6283a9c91b3982fa5188368c8719cce2a3cf3b86048673bf9d9c36b" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum hmac 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "733e1b3ac906631ca01ebb577e9bb0f5e37a454032b9036b5eaea4013ed6f99a" diff --git a/api/src/foreign.rs b/api/src/foreign.rs index bcfa60652..921f04282 100644 --- a/api/src/foreign.rs +++ b/api/src/foreign.rs @@ -12,19 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Main interface into all wallet API functions. -//! Wallet APIs are split into two seperate blocks of functionality -//! called the 'Owner' and 'Foreign' 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. -//! -//! 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). +//! Foreign API External Definition use crate::keychain::Keychain; use crate::libwallet::api_impl::foreign; @@ -35,8 +23,20 @@ use crate::util::Mutex; use std::marker::PhantomData; use std::sync::Arc; -/// Wrapper around external API functions, intended to communicate -/// with other parties +/// Main interface into all wallet API functions. +/// Wallet APIs are split into two seperate blocks of functionality +/// 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. +/// +/// 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 where W: WalletBackend, @@ -58,7 +58,64 @@ where C: NodeClient, K: Keychain, { - /// Create new API instance + /// Create a new API instance with the given wallet instance. All subsequent + /// API calls will operate on this instance of the wallet. + /// + /// Each method will call the [`WalletBackend`](../grin_wallet_libwallet/types/trait.WalletBackend.html)'s + /// [`open_with_credentials`](../grin_wallet_libwallet/types/trait.WalletBackend.html#tymethod.open_with_credentials) + /// (initialising a keychain with the master seed), perform its operation, then close the keychain + /// with a call to [`close`](../grin_wallet_libwallet/types/trait.WalletBackend.html#tymethod.close) + /// + /// # Arguments + /// * `wallet_in` - A reference-counted mutex containing an implementation of the + /// [`WalletBackend`](../grin_wallet_libwallet/types/trait.WalletBackend.html) trait. + /// + /// # Returns + /// * An instance of the ForeignApi holding a reference to the provided wallet + /// + /// # Example + /// ``` + /// use grin_wallet_util::grin_keychain as keychain; + /// use grin_wallet_util::grin_util as util; + /// use grin_wallet_api as api; + /// use grin_wallet_config as config; + /// use grin_wallet_impls as impls; + /// use grin_wallet_libwallet as libwallet; + /// + /// use keychain::ExtKeychain; + /// use tempfile::tempdir; + /// + /// use std::sync::Arc; + /// use util::Mutex; + /// + /// use api::Foreign; + /// use config::WalletConfig; + /// use impls::{HTTPNodeClient, LMDBBackend}; + /// use libwallet::types::WalletBackend; + /// + /// let mut wallet_config = WalletConfig::default(); + /// # let dir = tempdir().map_err(|e| format!("{:#?}", e)).unwrap(); + /// # let dir = dir + /// # .path() + /// # .to_str() + /// # .ok_or("Failed to convert tmpdir path to string.".to_owned()) + /// # .unwrap(); + /// # wallet_config.data_file_dir = dir.to_owned(); + /// + /// // A NodeClient must first be created to handle communication between + /// // the wallet and the node. + /// + /// let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None); + /// let mut wallet:Arc>> = + /// Arc::new(Mutex::new( + /// LMDBBackend::new(wallet_config.clone(), "", node_client).unwrap() + /// )); + /// + /// let api_owner = Foreign::new(wallet.clone()); + /// // .. perform wallet operations + /// + /// ``` + pub fn new(wallet_in: Arc>) -> Self { Foreign { wallet: wallet_in, @@ -68,7 +125,56 @@ where } } - /// Build a new (potential) coinbase transaction in the wallet + /// Builds a new unconfirmed coinbase output in the wallet, generally for inclusion in a + /// potential new block's coinbase output during mining. + /// + /// All potential coinbase outputs are created as 'Unconfirmed' with the coinbase flag set. + /// If a potential coinbase output is found on the chain after a wallet update, it status + /// is set to `Unsent` and a [Transaction Log Entry](../grin_wallet_libwallet/types/struct.TxLogEntry.html) + /// will be created. Note the output will be unspendable until the coinbase maturity period + /// has expired. + /// + /// # Arguments + /// + /// * `block_fees` - A [`BlockFees`](../grin_wallet_libwallet/types/struct.BlockFees.html) + /// struct, set up as follows: + /// + /// `fees` - should contain the sum of all transaction fees included in the potential + /// block + /// + /// `height` - should contain the block height being mined + /// + /// `key_id` - can optionally contain the corresponding keychain ID in the wallet to use + /// to create the output's blinding factor. If this is not provided, the next available key + /// id will be assigned + /// + /// # Returns + /// * `Ok`([`cb_data`](../grin_wallet_libwallet/types/struct.CbData.html)`)` if successful. This + /// 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 + /// Set up as in [`new`](struct.Foreign.html#method.new) method above. + /// ``` + /// # grin_wallet_api::doctest_helper_setup_doc_env_foreign!(wallet, wallet_config); + /// + /// let mut api_foreign = Foreign::new(wallet.clone()); + /// + /// let block_fees = BlockFees { + /// fees: 800000, + /// height: 234323, + /// key_id: None, + /// }; + /// // Build a new coinbase output + /// + /// let res = api_foreign.build_coinbase(&block_fees); + /// + /// if let Ok(cb_data) = res { + /// // cb_data is populated with coinbase output info + /// // ... + /// } + /// ``` + pub fn build_coinbase(&self, block_fees: &BlockFees) -> Result { let mut w = self.wallet.lock(); w.open_with_credentials()?; @@ -77,18 +183,110 @@ where res } - /// Verifies all messages in the slate match their public keys + /// Verifies all messages in the slate match their public keys. + /// + /// The option messages themselves are part of the `participant_data` field within the slate. + /// Messages are signed with the same key used to sign for the paricipant's inputs, and can thus be + /// verified with the public key found in the `public_blind_excess` field. This function is a + /// simple helper to returns whether all signatures in the participant data match their public + /// keys. + /// + /// # Arguments + /// + /// * `slate` - The transaction [`Slate`](../grin_wallet_libwallet/slate/struct.Slate.html). + /// + /// # Returns + /// * `Ok(())` if successful and the signatures validate + /// * or [`libwallet::Error`](../grin_wallet_libwallet/struct.Error.html) if an error is encountered. + /// + /// # Example + /// Set up as in [`new`](struct.Foreign.html#method.new) method above. + /// ``` + /// # grin_wallet_api::doctest_helper_setup_doc_env_foreign!(wallet, wallet_config); + /// + /// let mut api_foreign = Foreign::new(wallet.clone()); + /// + /// # let slate = Slate::blank(2); + /// // Receive a slate via some means + /// + /// let res = api_foreign.verify_slate_messages(&slate); + /// + /// if let Err(e) = res { + /// // Messages don't validate, likely return an error + /// // ... + /// } else { + /// // Slate messages are fine + /// } + /// + /// + /// ``` + pub fn verify_slate_messages(&self, slate: &Slate) -> Result<(), Error> { foreign::verify_slate_messages(slate) } - /// Receive a transaction from a sender + /// Recieve a tranaction created by another party, returning the modified + /// [`Slate`](../grin_wallet_libwallet/slate/struct.Slate.html) object, modified with + /// the recipient's output for the transaction amount, and public signature data. This slate can + /// then be sent back to the sender to finalize the transaction via the + /// [Owner API's `finalize_tx`](struct.Owner.html#method.finalize_tx) method. + /// + /// This function creates a single output for the full amount, set to a status of + /// 'Awaiting finalization'. It will remain in this state until the wallet finds the + /// corresponding output on the chain, at which point it will become 'Unspent'. The slate + /// will be updated with the results of Signing round 1 and 2, adding the recipient's public + /// nonce, public excess value, and partial signature to the slate. + /// + /// Also creates a corresponding [Transaction Log Entry](../grin_wallet_libwallet/types/struct.TxLogEntry.html) + /// in the wallet's transaction log. + /// + /// # 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). + /// * `dest_acct_name` - The name of the account into which the slate should be received. If + /// `None`, the default account is used. + /// * `message` - An optional participant message to include alongside the recipient's public + /// ParticipantData within the slate. This message will include a signature created with the + /// recipient's private excess value, and will be publically verifiable. Note this message is for + /// the convenience of the participants during the exchange; it is not included in the final + /// transaction sent to the chain. The message will be truncated to 256 characters. + /// Validation of this message is optional. + /// + /// # 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. + /// * or [`libwallet::Error`](../grin_wallet_libwallet/struct.Error.html) if an error is encountered. + /// + /// # Remarks + /// + /// * This method will store a partially completed transaction in the wallet's transaction log. + /// + /// # Example + /// Set up as in [new](struct.Foreign.html#method.new) method above. + /// ``` + /// # grin_wallet_api::doctest_helper_setup_doc_env_foreign!(wallet, wallet_config); + /// + /// let mut api_foreign = Foreign::new(wallet.clone()); + /// # let slate = Slate::blank(2); + /// + /// // . . . + /// // Obtain a sent slate somehow + /// let result = api_foreign.receive_tx(&slate, None, None); + /// + /// if let Ok(slate) = result { + /// // Send back to recipient somehow + /// // ... + /// } + /// ``` + pub fn receive_tx( &self, - slate: &mut Slate, + slate: &Slate, dest_acct_name: Option<&str>, message: Option, - ) -> Result<(), Error> { + ) -> Result { let mut w = self.wallet.lock(); w.open_with_credentials()?; let res = foreign::receive_tx(&mut *w, slate, dest_acct_name, message, self.doctest_mode); @@ -96,3 +294,43 @@ where res } } + +#[doc(hidden)] +#[macro_export] +macro_rules! doctest_helper_setup_doc_env_foreign { + ($wallet:ident, $wallet_config:ident) => { + use grin_wallet_api as api; + use grin_wallet_config as config; + use grin_wallet_impls as impls; + use grin_wallet_libwallet as libwallet; + use grin_wallet_util::grin_keychain as keychain; + use grin_wallet_util::grin_util as util; + use libwallet::slate::Slate; + + use keychain::ExtKeychain; + use tempfile::tempdir; + + use std::sync::Arc; + use util::Mutex; + + use api::Foreign; + use config::WalletConfig; + use impls::{HTTPNodeClient, LMDBBackend, WalletSeed}; + use libwallet::types::{BlockFees, WalletBackend}; + + let dir = tempdir().map_err(|e| format!("{:#?}", e)).unwrap(); + let dir = dir + .path() + .to_str() + .ok_or("Failed to convert tmpdir path to string.".to_owned()) + .unwrap(); + let mut wallet_config = WalletConfig::default(); + wallet_config.data_file_dir = dir.to_owned(); + let pw = ""; + + let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None); + let mut $wallet: Arc>> = Arc::new( + Mutex::new(LMDBBackend::new(wallet_config.clone(), pw, node_client).unwrap()), + ); + }; +} diff --git a/api/src/foreign_rpc.rs b/api/src/foreign_rpc.rs index 2a999b290..d43afb977 100644 --- a/api/src/foreign_rpc.rs +++ b/api/src/foreign_rpc.rs @@ -329,13 +329,13 @@ where fn receive_tx( &self, - mut slate: Slate, + slate: Slate, dest_acct_name: Option, message: Option, ) -> Result { - Foreign::receive_tx( + let slate = Foreign::receive_tx( self, - &mut slate, + &slate, dest_acct_name.as_ref().map(String::as_str), message, ) diff --git a/api/src/owner.rs b/api/src/owner.rs index f97588bbf..2af815e9e 100644 --- a/api/src/owner.rs +++ b/api/src/owner.rs @@ -12,19 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Main interface into all wallet API functions. -//! Wallet APIs are split into two seperate blocks of functionality -//! called the 'Owner' and 'Foreign' APIs: -//! -//! * The 'Owner' API is intended to expose methods that are to be -//! used by the wallet owner only. It is vital that this API is not -//! exposed to anyone other than the owner of the wallet (i.e. the -//! person with access to the seed and password. -//! -//! 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). +//! Owner API External Definition use crate::util::Mutex; use chrono::prelude::*; @@ -42,7 +30,20 @@ use crate::libwallet::types::{ }; use crate::libwallet::Error; -/// Functions intended for use by the owner (e.g. master seed holder) of the wallet. +/// Main interface into all wallet API functions. +/// Wallet APIs are split into two seperate blocks of functionality +/// called the ['Owner'](struct.Owner.html) and ['Foreign'](struct.Foreign.html) APIs +/// +/// * The 'Owner' API is intended to expose methods that are to be +/// used by the wallet owner only. It is vital that this API is not +/// exposed to anyone other than the owner of the wallet (i.e. the +/// person with access to the seed and password. +/// +/// 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 Owner where W: WalletBackend, @@ -454,7 +455,7 @@ where /// value outputs. /// * `message` - An optional participant message to include alongside the sender's public /// ParticipantData within the slate. This message will include a signature created with the - /// sender's private keys, and will be publically verifiable. Note this message is for + /// sender's private excess value, and will be publically verifiable. Note this message is for /// the convenience of the participants during the exchange; it is not included in the final /// transaction sent to the chain. The message will be truncated to 256 characters. /// Validation of this message is optional. @@ -668,7 +669,8 @@ where /// outputs (via the [`tx_lock_outputs`](struct.Owner.html#method.tx_lock_outputs) function). /// /// # Returns - /// * `Ok(())` if successful + /// * ``Ok([`slate`](../grin_wallet_libwallet/slate/struct.Slate.html))` if successful, + /// containing the new finalized slate. /// * or [`libwallet::Error`](../grin_wallet_libwallet/struct.Error.html) if an error is encountered. /// /// # Example @@ -868,12 +870,18 @@ where /// Verifies all messages in the slate match their public keys. /// + /// The optional messages themselves are part of the `participant_data` field within the slate. + /// Messages are signed with the same key used to sign for the paricipant's inputs, and can thus be + /// verified with the public key found in the `public_blind_excess` field. This function is a + /// simple helper to returns whether all signatures in the participant data match their public + /// keys. + /// /// # Arguments /// /// * `slate` - The transaction [`Slate`](../grin_wallet_libwallet/slate/struct.Slate.html). /// /// # Returns - /// * Ok(()) if successful and the signatures validate + /// * `Ok(())` if successful and the signatures validate /// * or [`libwallet::Error`](../grin_wallet_libwallet/struct.Error.html) if an error is encountered. /// /// # Example diff --git a/api/src/owner_rpc.rs b/api/src/owner_rpc.rs index 7fb5a1793..c0bf1438f 100644 --- a/api/src/owner_rpc.rs +++ b/api/src/owner_rpc.rs @@ -1257,7 +1257,7 @@ pub fn run_doctest_owner( { let mut w2 = wallet2.lock(); w2.open_with_credentials().unwrap(); - api_impl::foreign::receive_tx(&mut *w2, &mut slate, None, None, true).unwrap(); + slate = api_impl::foreign::receive_tx(&mut *w2, &slate, None, None, true).unwrap(); w2.close().unwrap(); } println!("RECIPIENT SLATE"); diff --git a/controller/src/command.rs b/controller/src/command.rs index b54a1d224..dc28a2ce0 100644 --- a/controller/src/command.rs +++ b/controller/src/command.rs @@ -299,7 +299,7 @@ pub fn send( api.tx_lock_outputs(&slate)?; if args.method == "self" { controller::foreign_single_use(wallet, |api| { - api.receive_tx(&mut slate, Some(&args.dest), None)?; + slate = api.receive_tx(&slate, Some(&args.dest), None)?; Ok(()) })?; } @@ -349,7 +349,7 @@ pub fn receive( error!("Error validating participant messages: {}", e); return Err(e); } - api.receive_tx(&mut slate, Some(&g_args.account), args.message.clone())?; + slate = api.receive_tx(&slate, Some(&g_args.account), args.message.clone())?; Ok(()) })?; let send_tx = format!("{}.response", args.input); diff --git a/controller/tests/file.rs b/controller/tests/file.rs index e1c1863e3..c4474fb19 100644 --- a/controller/tests/file.rs +++ b/controller/tests/file.rs @@ -144,7 +144,7 @@ fn file_exchange_test_impl(test_dir: &str) -> Result<(), libwallet::Error> { // wallet 2 receives file, completes, sends file back wallet::controller::foreign_single_use(wallet2.clone(), |api| { - api.receive_tx(&mut slate, None, Some(sender2_message.clone()))?; + slate = api.receive_tx(&slate, None, Some(sender2_message.clone()))?; adapter.send_tx_async(&receive_file, &mut slate)?; Ok(()) })?; diff --git a/controller/tests/repost.rs b/controller/tests/repost.rs index 9b786b66e..db624bf80 100644 --- a/controller/tests/repost.rs +++ b/controller/tests/repost.rs @@ -132,7 +132,7 @@ fn file_repost_test_impl(test_dir: &str) -> Result<(), libwallet::Error> { wallet::controller::foreign_single_use(wallet1.clone(), |api| { let adapter = FileWalletCommAdapter::new(); slate = adapter.receive_tx_async(&send_file)?; - api.receive_tx(&mut slate, None, None)?; + slate = api.receive_tx(&slate, None, None)?; adapter.send_tx_async(&receive_file, &mut slate)?; Ok(()) })?; diff --git a/controller/tests/self_send.rs b/controller/tests/self_send.rs index ce2571345..37358c249 100644 --- a/controller/tests/self_send.rs +++ b/controller/tests/self_send.rs @@ -99,7 +99,7 @@ fn self_send_test_impl(test_dir: &str) -> Result<(), libwallet::Error> { api.tx_lock_outputs(&slate)?; // Send directly to self wallet::controller::foreign_single_use(wallet1.clone(), |api| { - api.receive_tx(&mut slate, Some("listener"), None)?; + slate = api.receive_tx(&slate, Some("listener"), None)?; Ok(()) })?; slate = api.finalize_tx(&slate)?; diff --git a/impls/src/adapters/keybase.rs b/impls/src/adapters/keybase.rs index 4d7f03e32..b99a43721 100644 --- a/impls/src/adapters/keybase.rs +++ b/impls/src/adapters/keybase.rs @@ -353,7 +353,7 @@ impl WalletCommAdapter for KeybaseWalletCommAdapter { let blob = Slate::deserialize_upgrade(&msg); match blob { Ok(message) => { - let mut slate: Slate = message.clone().into(); + let slate: Slate = message.clone().into(); let tx_uuid = slate.id; // Reject multiple recipients channel for safety @@ -382,15 +382,15 @@ impl WalletCommAdapter for KeybaseWalletCommAdapter { let res = { let mut w = wallet.lock(); w.open_with_credentials()?; - let r = foreign::receive_tx(&mut *w, &mut slate, None, None, false); + let r = foreign::receive_tx(&mut *w, &slate, None, None, false); w.close()?; r }; match res { // Reply to the same channel with topic SLATE_SIGNED - Ok(_) => { - let slate = slate - .serialize_to_version(Some(slate.version_info.orig_version))?; + Ok(s) => { + let slate = + s.serialize_to_version(Some(slate.version_info.orig_version))?; // TODO: Send the same version of slate that was sent to us let success = send(slate, channel, SLATE_SIGNED, TTL); diff --git a/impls/src/test_framework/testclient.rs b/impls/src/test_framework/testclient.rs index d81048611..4e2742419 100644 --- a/impls/src/test_framework/testclient.rs +++ b/impls/src/test_framework/testclient.rs @@ -217,7 +217,7 @@ where let mut w = wallet.1.lock(); w.open_with_credentials()?; // receive tx - foreign::receive_tx(&mut *w, &mut slate, None, None, false)?; + slate = foreign::receive_tx(&mut *w, &slate, None, None, false)?; w.close()?; } diff --git a/libwallet/src/api_impl/foreign.rs b/libwallet/src/api_impl/foreign.rs index 133131fa1..2deadbc66 100644 --- a/libwallet/src/api_impl/foreign.rs +++ b/libwallet/src/api_impl/foreign.rs @@ -44,16 +44,17 @@ pub fn verify_slate_messages(slate: &Slate) -> Result<(), Error> { /// Receive a tx as recipient pub fn receive_tx( w: &mut T, - slate: &mut Slate, + slate: &Slate, dest_acct_name: Option<&str>, message: Option, use_test_rng: bool, -) -> Result<(), Error> +) -> Result where T: WalletBackend, C: NodeClient, K: Keychain, { + let mut ret_slate = slate.clone(); let parent_key_id = match dest_acct_name { Some(d) => { let pm = w.get_acct_path(d.to_owned())?; @@ -68,13 +69,13 @@ where let tx = updater::retrieve_txs( &mut *w, None, - Some(slate.id), + Some(ret_slate.id), Some(&parent_key_id), use_test_rng, )?; for t in &tx { if t.tx_type == TxLogEntryType::TxReceived { - return Err(ErrorKind::TransactionAlreadyReceived(slate.id.to_string()).into()); + return Err(ErrorKind::TransactionAlreadyReceived(ret_slate.id.to_string()).into()); } } @@ -86,7 +87,14 @@ where None => None, }; - tx::add_output_to_slate(&mut *w, slate, &parent_key_id, 1, message, use_test_rng)?; - tx::update_message(&mut *w, slate)?; - Ok(()) + tx::add_output_to_slate( + &mut *w, + &mut ret_slate, + &parent_key_id, + 1, + message, + use_test_rng, + )?; + tx::update_message(&mut *w, &mut ret_slate)?; + Ok(ret_slate) } diff --git a/libwallet/src/types.rs b/libwallet/src/types.rs index 834f8b6fe..2e41d448f 100644 --- a/libwallet/src/types.rs +++ b/libwallet/src/types.rs @@ -549,8 +549,10 @@ impl<'de> serde::de::Visitor<'de> for BlockIdentifierVisitor { #[derive(Serialize, Deserialize, Debug, Clone)] pub struct BlockFees { /// fees + #[serde(with = "secp_ser::string_or_u64")] pub fees: u64, /// height + #[serde(with = "secp_ser::string_or_u64")] pub height: u64, /// key id pub key_id: Option,