Skip to content

Commit

Permalink
Addition of JSON-RPC mwixnet function call
Browse files Browse the repository at this point in the history
  • Loading branch information
yeastplume committed Oct 18, 2024
1 parent c266c3b commit 34ce2f7
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 29 deletions.
86 changes: 81 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,62 @@ 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",
"params": {
"server_keys": [
"86cca2aedea7989dfcca62e54477301d098bac260656d11373e314c099f0b26a",
"86cca2aedea7989dfcca62e54477301d098bac260656d11373e314c099f0b26b",
"86cca2aedea7989dfcca62e54477301d098bac260656d11373e314c099f0b26c"
],
"fee_per_hop": "1000000"
},
"commitment": "08e1da9e6dc4d6e808a718b2f110a991dd775d65ce5ae408a4e1f002a4961aa9e7",
"lock_output": true
},
"id": 1
}
# "#
# ,
# r#"
{
"id": 1,
"jsonrpc": "2.0",
"result": {
"Ok": {
"comsig": "0835f4b8b9cd286c9e35475f575c3e4ae71ceb4ff36598504662627afd628a17d6ba7dedb1aa4c47f0fabad026b76fc86d06f3bef8d0621b8ac4601d4b1b98401586ca3374a401508f32049212478ae91cfa474dfaa5ef2c3dd559d5a292e02334",
"onion": {
"commit": "099a8922343f242dd3da29935ba5bbc7e38bf68eccfb8c96aec87aec0535199139",
"data":[
"758bc7339edfe8a1f117ef2ef02de58b33d99e820ffd2c21a3d108f4cbdadfbcbc061b705fc351ae2fb34a855bb64180fe8b4913ea13b3bf826773e4b293166cdad1fdf59cadd7d33f73a8f3fc0f339a849f9c505c573d8cc2f006082d8f5bf2c2c84c18d5873a821d9f60bcdd44cf0566d04d761a1eda005cd19ab0b1c593da4656dd2a09322fe1d725f61e8855c927844ec9e80b9260a58012f7c519c5ca3d9b192ab1104d30ac09fb844bd7f692214e5cf0f6cdf1477c20708c2f3ecb098dce6be661907593918840b0fe8eb5043996dace45f2fb66e8f1e2a732035b4e6447b8904f313badebcba99f75c003e297d8dd815915f534dfa7ed416af0c415b60d2a0186752af6af33b781f31fdd3016aeee3bd2e47743fe2ce391b3354b9036b56ec38ed7539adafbc96bef1dbaf354a805b03ac0df7a0d32cff91716926bce68c8ccebb607340f2ffe09c08a9c9fd282ea19b33c69107ed5c54d4872eb0ed83c38d7e07606722069d7709fb914e1e02ea23323f3ae9252902dbfa6f15bd83a3f64587c9ae23aaf96b2a95e1341da12a6e423cf95375184752e10c1dd1a599db74ac0c3d74ec270c589f6a3bdd0877eb986d9a58a8548b917e22bfb93a4a06c36d7cad8d4a8791a8d1e1dc683429b440b136c43ad2f664dafc5156b808050a3c4d28771877d3f1d3a9daa2585eae259aaa64745c6cd260f577e538e27be3c985db41b7c456b63c5b18d7d17420a277d4abc04ae892ceb26940b09fb322445846c14898f5f59305490b1338c56384cd0c7bf5950a0a403aec4d2c2f5e2378b5eb7b1e7fcdbd8d6cc547f3b5a372b22e50e37d858bb197392a10fb9e6e292d6ed6bd8eab1fef7f2d069b6250a0e3e597ccf9a062e04b68821f5c57328ddab775d141147b71c1764c911bad03d8b88e2e62034bc899395514ecab4dec8ab341ba114f0a4e5d1dcfa182396c0e4826ddee187b07bb524dfeaa5297f7a5465f99eaaaa37f082c787b94811feb15b57d68369e6a7e3761d"
],
"pubkey": "033946e6a495e7278027b38be3d500cfc23d3e0836f1b7e24513841437f316ccb0"
}
}
}
}
# "#
# , 0, false, false, false, false);
```
*
*/

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

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

fn create_mwixnet_req(
&self,
token: Token,
params: MixnetReqCreationParams,
commitment: String,
lock_output: bool,
) -> Result<SwapReq, Error> {
let commit =
Commitment::from_vec(from_hex(&commitment).map_err(|e| Error::CommitDeser(e))?);
Owner::create_mwixnet_req(
self,
(&token.keychain_mask).as_ref(),
&params,
&commit,
lock_output,
)
}
}

/// helper to set up a real environment to run integrated doctests
Expand Down
4 changes: 1 addition & 3 deletions libwallet/src/api_impl/owner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ use crate::types::{AcctPathMapping, NodeClient, TxLogEntry, WalletBackend, Walle
use crate::Error;
use crate::{
address,
mwixnet::{
create_onion, ComSignature, Hop, MixnetReqCreationParams, MwixnetPublicKey, SwapReq,
},
mwixnet::{create_onion, ComSignature, Hop, MixnetReqCreationParams, SwapReq},
wallet_lock, BuiltOutput, InitTxArgs, IssueInvoiceTxArgs, NodeHeightResult,
OutputCommitMapping, PaymentProof, RetrieveTxQueryArgs, ScannedBlockInfo, Slatepack,
SlatepackAddress, Slatepacker, SlatepackerArgs, TxLogEntryType, ViewWallet, WalletInitStatus,
Expand Down
4 changes: 4 additions & 0 deletions libwallet/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,10 @@ pub enum Error {
#[error("Committed Error: {0}")]
Commit(String),

/// Error Deserializing commit
#[error("Commit Deserialize Error: {0}")]
CommitDeser(String),

/// Can't parse slate version
#[error("Can't parse slate version")]
SlateVersionParse,
Expand Down
19 changes: 11 additions & 8 deletions libwallet/src/mwixnet/onion/crypto/comsig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@ pub struct ComSignature {
/// Error types for Commitment Signatures
#[derive(Error, Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
pub enum ComSigError {
/// Invalid commitment signature
#[error("Commitment signature is invalid")]
InvalidSig,
/// Secp256k1zkp error
#[error("Secp256k1zkp error: {0:?}")]
Secp256k1zkp(secp256k1zkp::Error),
}
Expand All @@ -47,6 +49,7 @@ impl From<secp256k1zkp::Error> for ComSigError {
}

impl ComSignature {
/// Create a new ComSignature
pub fn new(pub_nonce: &Commitment, s: &SecretKey, t: &SecretKey) -> ComSignature {
ComSignature {
pub_nonce: pub_nonce.to_owned(),
Expand All @@ -55,7 +58,7 @@ impl ComSignature {
}
}

#[allow(dead_code)]
/// Sign commitment with amount, blinding factor, and message
pub fn sign(
amount: u64,
blind: &SecretKey,
Expand Down Expand Up @@ -88,20 +91,20 @@ impl ComSignature {
Ok(ComSignature::new(&nonce_commitment, &s, &t))
}

#[allow(non_snake_case)]
/// Verify the commitment signature
pub fn verify(&self, commit: &Commitment, msg: &Vec<u8>) -> Result<(), ComSigError> {
let secp = Secp256k1::with_caps(ContextFlag::Commit);

let S1 = secp.commit_blind(self.s.clone(), self.t.clone())?;
let s1 = secp.commit_blind(self.s.clone(), self.t.clone())?;

let mut Ce = commit.to_pubkey(&secp)?;
let mut ce = commit.to_pubkey(&secp)?;
let e = ComSignature::calc_challenge(&secp, &commit, &self.pub_nonce, &msg)?;
Ce.mul_assign(&secp, &e)?;
ce.mul_assign(&secp, &e)?;

let commits = vec![Commitment::from_pubkey(&secp, &Ce)?, self.pub_nonce.clone()];
let S2 = secp.commit_sum(commits, Vec::new())?;
let commits = vec![Commitment::from_pubkey(&secp, &ce)?, self.pub_nonce.clone()];
let s2 = secp.commit_sum(commits, Vec::new())?;

if S1 != S2 {
if s1 != s2 {
return Err(ComSigError::InvalidSig);
}

Expand Down
6 changes: 5 additions & 1 deletion libwallet/src/mwixnet/onion/crypto/dalek.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
use grin_util::secp::key::SecretKey;

use ed25519_dalek::{Keypair, PublicKey, Signature, Signer, Verifier};
use ed25519_dalek::{PublicKey, Signature, Verifier};
use grin_core::ser::{self, Readable, Reader, Writeable, Writer};
use grin_util::ToHex;
use thiserror::Error;
Expand Down Expand Up @@ -68,6 +68,7 @@ impl AsRef<PublicKey> for DalekPublicKey {
}
}

#[cfg(test)]
/// Serializes an Option<DalekPublicKey> to and from hex
pub mod option_dalek_pubkey_serde {
use super::DalekPublicKey;
Expand Down Expand Up @@ -144,6 +145,7 @@ impl AsRef<Signature> for DalekSignature {
}

/// Serializes a DalekSignature to and from hex
#[cfg(test)]
pub mod dalek_sig_serde {
use super::DalekSignature;
use grin_util::ToHex;
Expand Down Expand Up @@ -171,7 +173,9 @@ pub mod dalek_sig_serde {

/// Dalek signature sign wrapper
// TODO: This is likely duplicated throughout crate, check
#[cfg(test)]
pub fn sign(sk: &SecretKey, message: &[u8]) -> Result<DalekSignature, DalekError> {
use ed25519_dalek::{Keypair, Signer};
let secret =
ed25519_dalek::SecretKey::from_bytes(&sk.0).map_err(|_| DalekError::KeyParseError)?;
let public: PublicKey = (&secret).into();
Expand Down
27 changes: 21 additions & 6 deletions libwallet/src/mwixnet/onion/crypto/secp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
//! SECP operations for comsig
pub use grin_util::secp::{
self as secp256k1zkp, aggsig,
self as secp256k1zkp,
constants::SECRET_KEY_SIZE,
key::{PublicKey, SecretKey, ZERO_KEY},
key::{SecretKey, ZERO_KEY},
pedersen::Commitment,
rand::thread_rng,
ContextFlag, Message, Secp256k1, Signature,
ContextFlag, Secp256k1,
};

use grin_core::ser::{self, Reader};
Expand All @@ -40,6 +40,7 @@ pub fn read_secret_key<R: Reader>(reader: &mut R) -> Result<SecretKey, ser::Erro
}

/// Build a Pedersen Commitment using the provided value and blinding factor
#[cfg(test)]
pub fn commit(value: u64, blind: &SecretKey) -> Result<Commitment, secp256k1zkp::Error> {
let secp = Secp256k1::with_caps(ContextFlag::Commit);
let commit = secp.commit(value, blind.clone())?;
Expand Down Expand Up @@ -68,9 +69,23 @@ pub fn sub_value(commitment: &Commitment, value: u64) -> Result<Commitment, secp
}

/// Signs the message with the provided SecretKey
pub fn sign(sk: &SecretKey, msg: &Message) -> Result<Signature, secp256k1zkp::Error> {
#[cfg(test)]
#[allow(dead_code)]
pub fn sign(
sk: &SecretKey,
msg: &grin_util::secp::Message,
) -> Result<grin_util::secp::Signature, secp256k1zkp::Error> {
let secp = Secp256k1::with_caps(ContextFlag::Full);
let pubkey = PublicKey::from_secret_key(&secp, &sk)?;
let sig = aggsig::sign_single(&secp, &msg, &sk, None, None, None, Some(&pubkey), None)?;
let pubkey = grin_util::secp::PublicKey::from_secret_key(&secp, &sk)?;
let sig = grin_util::secp::aggsig::sign_single(
&secp,
&msg,
&sk,
None,
None,
None,
Some(&pubkey),
None,
)?;
Ok(sig)
}
4 changes: 3 additions & 1 deletion libwallet/src/mwixnet/onion/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ pub struct Hop {
}

/// Crate a new hop
#[cfg(test)]
pub fn new_hop(
server_key: &SecretKey,
hop_excess: &SecretKey,
Expand Down Expand Up @@ -113,7 +114,8 @@ pub fn create_onion(commitment: &Commitment, hops: &Vec<Hop>) -> Result<Onion, O
}

/// Internal tests
#[allow(missing_docs)]
#[allow(missing_docs, dead_code)]
#[cfg(test)]
pub mod test_util {
use super::*;
use crypto::dalek::DalekPublicKey;
Expand Down
8 changes: 3 additions & 5 deletions libwallet/src/mwixnet/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ use super::onion::comsig_serde;
use grin_util::secp::key::SecretKey;
use serde::{Deserialize, Serialize};

pub use super::onion::{
create_onion, onion::Onion, onion::OnionError, ComSigError, ComSignature, Hop,
};
pub use super::onion::{onion::Onion, ComSignature, Hop};

/// A Swap request
#[derive(Serialize, Deserialize, Debug)]
Expand All @@ -34,10 +32,10 @@ pub struct SwapReq {
}

/// mwixnetRequest Creation Params
#[derive(Serialize, Deserialize, Debug)]
pub struct MixnetReqCreationParams {
/// List of all the server keys
pub server_keys: Vec<SecretKey>,
/// Fees per hop
pub fee_per_hop: u32,
pub fee_per_hop: u64,
}

0 comments on commit 34ce2f7

Please sign in to comment.