Skip to content

Add mwixnet code to master #726

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 3 additions & 19 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

74 changes: 72 additions & 2 deletions api/src/owner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

use chrono::prelude::*;
use ed25519_dalek::SecretKey as DalekSecretKey;
use grin_wallet_libwallet::mwixnet::{MixnetReqCreationParams, SwapReq};
use grin_wallet_libwallet::RetrieveTxQueryArgs;
use uuid::Uuid;

Expand All @@ -33,7 +34,7 @@ use crate::libwallet::{
TxLogEntry, ViewWallet, WalletInfo, WalletInst, WalletLCProvider,
};
use crate::util::logger::LoggingConfig;
use crate::util::secp::key::SecretKey;
use crate::util::secp::{key::SecretKey, pedersen::Commitment};
use crate::util::{from_hex, static_secp_instance, Mutex, ZeroingString};
use grin_wallet_util::OnionV3Address;
use std::convert::TryFrom;
Expand Down Expand Up @@ -2423,6 +2424,71 @@ where
let w = w_lock.lc_provider()?.wallet_inst()?;
owner::build_output(&mut **w, keychain_mask, features, amount)
}

// MWIXNET

/// Creates an mwixnet request [SwapReq](../grin_wallet_libwallet/api_impl/types/struct.SwapReq.html)
/// from a given output commitment under this wallet's control.
///
/// # Arguments
/// * `keychain_mask` - Wallet secret mask to XOR against the stored wallet seed before using, if
/// being used.
/// * `params` - A [MixnetReqCreationParams](../grin_wallet_libwallet/api_impl/types/struct.MixnetReqCreationParams.html)
/// struct containing the parameters for the request, which include:
/// `server_keys` - The public keys of the servers participating in the mixnet (each encoded internally as a `SecretKey`)
/// `fee_per_hop` - The fee to be paid to each server for each hop in the mixnet
/// * `commitment` - The commitment of the output to be mixed
/// * `lock_output` - Whether to lock the referenced output after creating the request
///
/// # Returns
/// * Ok([SwapReq](../grin_wallet_libwallet/api_impl/types/struct.SwapReq.html)) if successful
/// * or [`libwallet::Error`](../grin_wallet_libwallet/struct.Error.html) if an error is encountered
///
/// # Example
/// Set up as in [`new`](struct.Owner.html#method.new) method above.
/// ```
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
///
/// let api_owner = Owner::new(wallet.clone(), None);
/// let keychain_mask = None;
/// let params = MixnetReqCreationParams {
/// server_keys: vec![], // Public keys here in secret key representation
/// fee_per_hop: 100,
/// };
///
/// let commitment = Commitment::from_vec(vec![0; 32]);
/// let lock_output = true;
///
/// let result = api_owner.create_mwixnet_req(
/// keychain_mask,
/// &params,
/// &commitment,
/// lock_output,
/// );
///
/// if let Ok(req) = result {
/// //...
/// }
/// ```

pub fn create_mwixnet_req(
&self,
keychain_mask: Option<&SecretKey>,
params: &MixnetReqCreationParams,
commitment: &Commitment,
lock_output: bool, // use_test_rng: bool,
) -> Result<SwapReq, Error> {
let mut w_lock = self.wallet_inst.lock();
let w = w_lock.lc_provider()?.wallet_inst()?;
owner::create_mwixnet_req(
&mut **w,
keychain_mask,
params,
commitment,
lock_output,
self.doctest_mode,
)
}
}

/// attempt to send slate synchronously with TOR
Expand Down Expand Up @@ -2524,13 +2590,17 @@ macro_rules! doctest_helper_setup_doc_env {
use keychain::ExtKeychain;
use tempfile::tempdir;

use grin_util::secp::pedersen::Commitment;
use std::sync::Arc;
use util::{Mutex, ZeroingString};

use api::{Foreign, Owner};
use config::WalletConfig;
use impls::{DefaultLCProvider, DefaultWalletImpl, HTTPNodeClient};
use libwallet::{BlockFees, InitTxArgs, IssueInvoiceTxArgs, Slate, WalletInst};
use libwallet::{
mwixnet::MixnetReqCreationParams, BlockFees, InitTxArgs, IssueInvoiceTxArgs, Slate,
WalletInst,
};

use uuid::Uuid;

Expand Down
107 changes: 102 additions & 5 deletions api/src/owner_rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,23 @@

//! JSON-RPC Stub generation for the Owner API
use grin_wallet_libwallet::RetrieveTxQueryArgs;
use libwallet::mwixnet::SwapReq;
use uuid::Uuid;

use crate::config::{TorConfig, WalletConfig};
use crate::core::core::OutputFeatures;
use crate::core::global;
use crate::keychain::{Identifier, Keychain};
use crate::libwallet::{
AcctPathMapping, Amount, BuiltOutput, Error, InitTxArgs, IssueInvoiceTxArgs, NodeClient,
NodeHeightResult, OutputCommitMapping, PaymentProof, Slate, SlateVersion, Slatepack,
SlatepackAddress, StatusMessage, TxLogEntry, VersionedSlate, ViewWallet, WalletInfo,
WalletLCProvider,
mwixnet::MixnetReqCreationParams, AcctPathMapping, Amount, BuiltOutput, Error, InitTxArgs,
IssueInvoiceTxArgs, NodeClient, NodeHeightResult, OutputCommitMapping, PaymentProof, Slate,
SlateVersion, Slatepack, SlatepackAddress, StatusMessage, TxLogEntry, VersionedSlate,
ViewWallet, WalletInfo, WalletLCProvider,
};
use crate::util::logger::LoggingConfig;
use crate::util::secp::key::{PublicKey, SecretKey};
use crate::util::{static_secp_instance, Mutex, ZeroingString};
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;
Expand Down Expand Up @@ -1963,6 +1965,63 @@ pub trait OwnerRpc {
features: OutputFeatures,
amount: Amount,
) -> Result<BuiltOutput, Error>;

/**
Networked version of [Owner::build_output](struct.Owner.html#method.create_mwixnet_req).
```
# grin_wallet_api::doctest_helper_json_rpc_owner_assert_response!(
# r#"
{
"jsonrpc": "2.0",
"method": "create_mwixnet_req",
"params": {
"token": "d202964900000000d302964900000000d402964900000000d502964900000000",
"commitment": "08e1da9e6dc4d6e808a718b2f110a991dd775d65ce5ae408a4e1f002a4961aa9e7",
"fee_per_hop": "5000000",
"lock_output": true,
"server_keys": [
"97444ae673bb92c713c1a2f7b8882ffbfc1c67401a280a775dce1a8651584332",
"0c9414341f2140ed34a5a12a6479bf5a6404820d001ab81d9d3e8cc38f049b4e",
"b58ece97d60e71bb7e53218400b0d67bfe6a3cb7d3b4a67a44f8fb7c525cbca5"
]
},
"id": 1
}
# "#
# ,
# r#"
{
"id": 1,
"jsonrpc": "2.0",
"result": {
"Ok": {
"comsig": "099561ed0be59f6502ee358ee4f6760cd16d6be04d58d7a2c1bf2fd09dd7fd2d291beaae5483c6f18d1ceaae6321f06f9ba129a1ee9e7d15f152c67397a621538b5c10bbeb95140dee815c02657c91152939afe389458dc59af095e8e8e5c81a08",
"onion": {
"commit": "08e1da9e6dc4d6e808a718b2f110a991dd775d65ce5ae408a4e1f002a4961aa9e7",
"data": [
"37f68116475e1aa6b58fc911addbd0e04e7aa19ab3e82e7b5cfcaf57d82cf35e7388ce51711cc5ef8cf7630f7dc7229878f91c7ec85991a7fc0051a7bbc66569db3a3aa89ef490055f3c",
"b9ff8c0c1699808efce46d581647c65764a28e813023ae677d688282422a07505ae1a051037d7ba58f3279846d0300800fc1c5bfcc548dab815e9fd2f29df9515170c41fa6e4e44b8bcb",
"62ea6b8369686a0415e1e752b9b4d6e66cf5b6066a2d3c60d8818890a55f3adff4601466f4c6e6b646568b99ae93549a3595b7a7b4be815ced87d9297cabbd69518d7b2ed6edd14007528fd346aaea765a1165fe886666627ebcab9588b8ee1c9e98395ae67913c48eb6e924581b40182fce807f97312fb07fd5e216d99941f2b488babce4078a50cd66b28b30a66c4f54fcc127437408a99b30ffd6c3d0d8c7d39e864fc04e321b8c10138c8852d4cad0a4f2780412b9dadcc6e0f2657b7803a81bccb809ca392464be2e01755be7377d0e815698ad6ea51d4617cc92c3ccf852f038e33cc9c90992438ba5c49cca7cc188b682da684e2f4c9733a84a7b64ac5c2216ebf5926f0ee67b664fb5bab799109cbee755ce1aebc8cd352fea51cd84c333cb958093c53544c3f3ab05dba64d8f041c3b179796b476ec04b11044e39db6994ab767315e52cc0ef023432ec88ade2911612db7e74e0923889f765b58b00e3869c5072a4e882c1b721913f63bda986b8c97b7ae575f0d4be596a1ac3cd0db96ce6074ee000b32018b3bda16d7dba34a13ba9c3ce983946414c16e278351a3411cb8ef2cb8ef5b6e1667c4c58bc797c0324ae4fec8960d684e561c0e833ee4c3331c6c439b59042a62993535e23cc8a8a4cf705c0f9b1d62db4e3d76c22c01138800414b143ddff471e4df4413e842a1b41f43cc9647e47145fd6c86d4d1a34fb2f62f5a55b31c9353ee34743c548eff955f2d2143c1a86cbcb452104f96d0142db31153021bbeed995c71a92de8fb1f97269533a508085c543fcb3ee57000bb265e74187b858403aa97b6c7b085e5d5b6025cbfe5f6926d33c835f90e60fc62013e80bbe0a855da5938b4b8f83ac29c5e8251827795356222079a6d1612e2fdf93bd7836d1613c7a353ada48ce256f880bbbb3108e037e3b5647101bd4d549101b0ee73d2248a932a802a3b1beb0b69d777c4285d57e91d83e96fe2f8a1a2f182fe2c6ca37b18460cf8d7f56c201147b9be19f1d01f8ad305c1e9c4dd79b5d8719d6550432352cf737082b1e9de7a083ffbe1"
],
"pubkey": "e7ee7d51b11d09f268ade98bc9d7ae9be3c4ac124ce1c3a40e50d34460fa5f08"
}
}
}
}
# "#
# , 5, true, true, false, false);
```
*
*/

fn create_mwixnet_req(
&self,
token: Token,
commitment: String,
fee_per_hop: String,
lock_output: bool,
server_keys: Vec<String>,
) -> Result<SwapReq, Error>;
}

impl<L, C, K> OwnerRpc for Owner<L, C, K>
Expand Down Expand Up @@ -2372,6 +2431,44 @@ where
) -> Result<BuiltOutput, Error> {
Owner::build_output(self, (&token.keychain_mask).as_ref(), features, amount.0)
}

fn create_mwixnet_req(
&self,
token: Token,
commitment: String,
fee_per_hop: String,
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 secp_inst = static_secp_instance();
let secp = secp_inst.lock();

let mut keys = vec![];
for key in server_keys {
keys.push(SecretKey::from_slice(
&secp,
&grin_util::from_hex(&key).map_err(|e| Error::ServerKeyDeser(e))?,
)?)
}

let req_params = MixnetReqCreationParams {
server_keys: keys,
fee_per_hop: fee_per_hop
.parse::<u64>()
.map_err(|_| Error::U64Deser(fee_per_hop))?,
};

Owner::create_mwixnet_req(
self,
(&token.keychain_mask).as_ref(),
&req_params,
&commit,
lock_output,
)
}
}

/// helper to set up a real environment to run integrated doctests
Expand Down
20 changes: 10 additions & 10 deletions controller/tests/invoice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,16 +82,16 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
wallet_inst!(wallet1, w);
w.set_parent_key_id_by_name("mining")?;
}
let mut bh = 10u64;
let mut _bh = 10u64;
let _ =
test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, bh as usize, false);
test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, _bh as usize, false);

// Sanity check wallet 1 contents
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
assert!(wallet1_refreshed);
assert_eq!(wallet1_info.last_confirmed_height, bh);
assert_eq!(wallet1_info.total, bh * reward);
assert_eq!(wallet1_info.last_confirmed_height, _bh);
assert_eq!(wallet1_info.total, _bh * reward);
Ok(())
})?;

Expand Down Expand Up @@ -138,10 +138,10 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
api.post_tx(m, &slate, false)?;
Ok(())
})?;
bh += 1;
_bh += 1;

let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 3, false);
bh += 3;
_bh += 3;

// Check transaction log for wallet 2
wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |api, m| {
Expand All @@ -151,7 +151,7 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
assert!(txs.len() == 1);
println!(
"last confirmed height: {}, bh: {}",
wallet2_info.last_confirmed_height, bh
wallet2_info.last_confirmed_height, _bh
);
assert!(refreshed);
Ok(())
Expand All @@ -163,10 +163,10 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
let (_, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
let (refreshed, txs) = api.retrieve_txs(m, true, None, None, None)?;
assert!(refreshed);
assert_eq!(txs.len() as u64, bh + 1);
assert_eq!(txs.len() as u64, _bh + 1);
println!(
"Wallet 1: last confirmed height: {}, bh: {}",
wallet1_info.last_confirmed_height, bh
wallet1_info.last_confirmed_height, _bh
);
Ok(())
})?;
Expand Down Expand Up @@ -248,7 +248,7 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {

// test that payee can only cancel once
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 3, false);
bh += 3;
_bh += 3;

wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |api, m| {
// Wallet 2 inititates an invoice transaction, requesting payment
Expand Down
Loading
Loading