mirror of
https://github.com/jwinterm/grin-wallet.git
synced 2026-11-10 17:53:53 +01:00
Merge branch 'master' into contracts
Bring the contracts feature branch up to current master, which has since landed rust 1.80 support (#722), the canonical mwixnet onion code (#726), and node-client proxy support (#738). Conflict resolution: - libwallet/src/mwixnet/*: take master's (#726), dropping the contracts branch's older divergent copy. owner.rs::create_mwixnet_req updated to master's API (use_test_rng) and master's flat re-export imports. - Cargo manifests/lock/.cargo: master's deps & version; re-add serde_with for Slate v5; keep contracts' .cargo/config.toml (Windows static-CRT). - lib.rs: keep serde_derive AND serde_with macro_use; single mwixnet decl. - error.rs: union of master + contracts variants; flat mwixnet re-exports. - api/libwallet owner.rs: master's #738 + create_mwixnet_req plus the contract_* entry points; drop duplicate older create_mwixnet_req method. - slatepack/armor.rs, node_clients/resp_types.rs: take master's. Workspace builds; libwallet lib tests pass (34/34). The Slate version() bug, issue #729 fix, and de-panicking follow in subsequent commits.
This commit is contained in:
@@ -24,23 +24,22 @@ use crate::grin_core::libtx::proof;
|
||||
use crate::grin_keychain::ViewKey;
|
||||
use crate::grin_util::secp::key::SecretKey;
|
||||
use crate::grin_util::secp::pedersen;
|
||||
use crate::grin_util::secp::pedersen::Commitment;
|
||||
use crate::grin_util::{static_secp_instance, Mutex, ToHex};
|
||||
use crate::util::{OnionV3Address, OnionV3AddressError};
|
||||
|
||||
use crate::api_impl::owner_updater::StatusMessage;
|
||||
use crate::contract::types::{ContractNewArgsAPI, ContractRevokeArgsAPI, ContractSetupArgsAPI};
|
||||
use crate::grin_keychain::{BlindingFactor, Identifier, Keychain, SwitchCommitmentType};
|
||||
use crate::mwixnet::onion::create_onion;
|
||||
use crate::mwixnet::types::{
|
||||
add_excess, new_hop, random_secret, ComSignature, Hop, MixnetReqCreationParams, SwapReq,
|
||||
};
|
||||
|
||||
use crate::internal::{keys, scan, selection, tx, updater};
|
||||
use crate::slate::{PaymentInfo, Slate, SlateState};
|
||||
use crate::types::{AcctPathMapping, NodeClient, TxLogEntry, WalletBackend, WalletInfo};
|
||||
use crate::Error;
|
||||
use crate::{
|
||||
address, contract, wallet_lock, BuiltOutput, InitTxArgs, IssueInvoiceTxArgs, NodeHeightResult,
|
||||
address, contract,
|
||||
mwixnet::{create_onion, ComSignature, Hop, MixnetReqCreationParams, SwapReq},
|
||||
wallet_lock, BuiltOutput, InitTxArgs, IssueInvoiceTxArgs, NodeHeightResult,
|
||||
OutputCommitMapping, PaymentProof, RetrieveTxQueryArgs, ScannedBlockInfo, Slatepack,
|
||||
SlatepackAddress, Slatepacker, SlatepackerArgs, TxLogEntryType, ViewWallet, WalletInitStatus,
|
||||
WalletInst, WalletLCProvider,
|
||||
@@ -1609,8 +1608,9 @@ pub fn create_mwixnet_req<'a, T: ?Sized, C, K>(
|
||||
w: &mut T,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
params: &MixnetReqCreationParams,
|
||||
commitment: &pedersen::Commitment,
|
||||
commitment: &Commitment,
|
||||
lock_output: bool,
|
||||
use_test_rng: bool,
|
||||
) -> Result<SwapReq, Error>
|
||||
where
|
||||
T: WalletBackend<'a, C, K>,
|
||||
@@ -1668,7 +1668,12 @@ where
|
||||
rangeproof: Some(new_output.output.proof.clone()),
|
||||
}
|
||||
} else {
|
||||
let hop_excess = BlindingFactor::rand(&secp);
|
||||
let hop_excess;
|
||||
if use_test_rng {
|
||||
hop_excess = BlindingFactor::zero();
|
||||
} else {
|
||||
hop_excess = BlindingFactor::rand(&secp);
|
||||
}
|
||||
blind_sum = blind_sum.split(&hop_excess, &secp).unwrap();
|
||||
Hop {
|
||||
server_pubkey: p.clone(),
|
||||
@@ -1680,8 +1685,14 @@ where
|
||||
})
|
||||
.collect();
|
||||
|
||||
let onion = create_onion(&commitment, &hops).unwrap();
|
||||
let comsig = ComSignature::sign(amount, &input_blind, &onion.serialize().unwrap()).unwrap();
|
||||
let onion = create_onion(&commitment, &hops, use_test_rng).unwrap();
|
||||
let comsig = ComSignature::sign(
|
||||
amount,
|
||||
&input_blind,
|
||||
&onion.serialize().unwrap(),
|
||||
use_test_rng,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Lock output if requested
|
||||
if lock_output {
|
||||
|
||||
@@ -26,6 +26,8 @@ use crate::SlatepackAddress;
|
||||
use chrono::prelude::*;
|
||||
use ed25519_dalek::Signature as DalekSignature;
|
||||
|
||||
pub use crate::mwixnet::{Hop, MixnetReqCreationParams, SwapReq};
|
||||
|
||||
/// Type for storing amounts (in nanogrins).
|
||||
/// Serializes as a string but can deserialize from a string or u64.
|
||||
#[derive(Serialize, Deserialize)]
|
||||
|
||||
+14
-2
@@ -67,11 +67,11 @@ pub enum Error {
|
||||
|
||||
/// Comsig error
|
||||
#[error("Comsig error: {0}")]
|
||||
ComSig(#[from] crate::mwixnet::onion::crypto::comsig::ComSigError),
|
||||
ComSig(#[from] crate::mwixnet::ComSigError),
|
||||
|
||||
/// mwixnet Onion error
|
||||
#[error("Onion error: {0}")]
|
||||
Onion(#[from] crate::mwixnet::onion::onion::OnionError),
|
||||
Onion(#[from] crate::mwixnet::OnionError),
|
||||
|
||||
/// Callback implementation error conversion
|
||||
#[error("Trait Implementation error")]
|
||||
@@ -189,6 +189,18 @@ pub enum Error {
|
||||
#[error("Committed Error: {0}")]
|
||||
Commit(String),
|
||||
|
||||
/// Error Deserializing commit
|
||||
#[error("Commit Deserialize Error: {0}")]
|
||||
CommitDeser(String),
|
||||
|
||||
/// Error Deserializing key
|
||||
#[error("Server Key Deserialize Error: {0}")]
|
||||
ServerKeyDeser(String),
|
||||
|
||||
/// Parsing integert
|
||||
#[error("Can't parse as u64: {0}")]
|
||||
U64Deser(String),
|
||||
|
||||
/// Can't parse slate version
|
||||
#[error("Can't parse slate version")]
|
||||
SlateVersionParse,
|
||||
|
||||
@@ -32,6 +32,8 @@ use grin_wallet_util as util;
|
||||
|
||||
use blake2_rfc as blake2;
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
#[macro_use]
|
||||
extern crate serde_with;
|
||||
#[macro_use]
|
||||
@@ -48,11 +50,10 @@ pub mod api_impl;
|
||||
pub mod contract;
|
||||
mod error;
|
||||
mod internal;
|
||||
pub mod mwixnet;
|
||||
mod slate;
|
||||
pub mod slate_versions;
|
||||
pub mod slatepack;
|
||||
|
||||
pub mod mwixnet;
|
||||
mod types;
|
||||
|
||||
pub use crate::error::Error;
|
||||
|
||||
@@ -13,5 +13,12 @@
|
||||
// limitations under the License.
|
||||
|
||||
//! Onion modules for mxmixnet
|
||||
pub mod onion;
|
||||
pub mod types;
|
||||
mod onion;
|
||||
mod types;
|
||||
|
||||
pub use onion::{
|
||||
create_onion, onion::Onion, onion::OnionError, util as onion_util, ComSigError, ComSignature,
|
||||
MwixnetPublicKey,
|
||||
};
|
||||
|
||||
pub use types::{Hop, MixnetReqCreationParams, SwapReq};
|
||||
|
||||
@@ -14,12 +14,14 @@
|
||||
|
||||
//! Comsig modules for mxmixnet
|
||||
|
||||
use secp256k1zkp::{self, pedersen::Commitment, ContextFlag, Secp256k1, SecretKey};
|
||||
use grin_util::secp::{
|
||||
self as secp256k1zkp, pedersen::Commitment, rand::thread_rng, ContextFlag, Secp256k1, SecretKey,
|
||||
};
|
||||
|
||||
use blake2_rfc::blake2b::Blake2b;
|
||||
use byteorder::{BigEndian, ByteOrder};
|
||||
use grin_core::ser::{self, Readable, Reader, Writeable, Writer};
|
||||
use secp256k1zkp::rand::thread_rng;
|
||||
use rand::rngs::mock::StepRng;
|
||||
use thiserror::Error;
|
||||
|
||||
/// A generalized Schnorr signature with a pedersen commitment value & blinding factors as the keys
|
||||
@@ -33,8 +35,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),
|
||||
}
|
||||
@@ -46,6 +50,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(),
|
||||
@@ -54,25 +59,41 @@ impl ComSignature {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
/// Sign commitment with amount, blinding factor, and message
|
||||
pub fn sign(
|
||||
amount: u64,
|
||||
blind: &SecretKey,
|
||||
msg: &Vec<u8>,
|
||||
use_test_rng: bool,
|
||||
) -> Result<ComSignature, ComSigError> {
|
||||
let secp = Secp256k1::with_caps(ContextFlag::Commit);
|
||||
|
||||
let mut amt_bytes = [0; 32];
|
||||
BigEndian::write_u64(&mut amt_bytes[24..32], amount);
|
||||
let k_amt = SecretKey::from_slice(&secp, &amt_bytes)?;
|
||||
let k_1;
|
||||
let k_2;
|
||||
|
||||
let k_1 = SecretKey::new(&secp, &mut thread_rng());
|
||||
let k_2 = SecretKey::new(&secp, &mut thread_rng());
|
||||
if use_test_rng {
|
||||
// allow for consistent test results
|
||||
let mut test_rng = StepRng::new(1_234_567_890_u64, 1);
|
||||
k_1 = SecretKey::new(&secp, &mut test_rng);
|
||||
k_2 = SecretKey::new(&secp, &mut test_rng);
|
||||
} else {
|
||||
k_1 = SecretKey::new(&secp, &mut thread_rng());
|
||||
k_2 = SecretKey::new(&secp, &mut thread_rng());
|
||||
}
|
||||
|
||||
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)?;
|
||||
let e = ComSignature::calc_challenge(
|
||||
&secp,
|
||||
&commitment,
|
||||
&nonce_commitment,
|
||||
&msg,
|
||||
use_test_rng,
|
||||
)?;
|
||||
|
||||
// s = k_1 + (e * amount)
|
||||
let mut s = k_amt.clone();
|
||||
@@ -87,20 +108,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 e = ComSignature::calc_challenge(&secp, &commit, &self.pub_nonce, &msg)?;
|
||||
Ce.mul_assign(&secp, &e)?;
|
||||
let mut ce = commit.to_pubkey(&secp)?;
|
||||
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 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);
|
||||
}
|
||||
|
||||
@@ -112,8 +133,12 @@ impl ComSignature {
|
||||
commit: &Commitment,
|
||||
nonce_commit: &Commitment,
|
||||
msg: &Vec<u8>,
|
||||
use_test_rng: bool,
|
||||
) -> Result<SecretKey, ComSigError> {
|
||||
let mut challenge_hasher = Blake2b::new(32);
|
||||
if use_test_rng {
|
||||
return Ok(super::secp::random_secret(use_test_rng));
|
||||
}
|
||||
challenge_hasher.update(&commit.0);
|
||||
challenge_hasher.update(&nonce_commit.0);
|
||||
challenge_hasher.update(msg);
|
||||
@@ -178,8 +203,8 @@ impl Writeable for ComSignature {
|
||||
mod tests {
|
||||
use super::{ComSigError, ComSignature, ContextFlag, Secp256k1, SecretKey};
|
||||
|
||||
use grin_util::secp::rand::{thread_rng, RngCore};
|
||||
use rand::Rng;
|
||||
use secp256k1zkp::rand::{thread_rng, RngCore};
|
||||
|
||||
/// Test signing and verification of ComSignatures
|
||||
#[test]
|
||||
@@ -189,7 +214,7 @@ mod tests {
|
||||
let amount = thread_rng().next_u64();
|
||||
let blind = SecretKey::new(&secp, &mut thread_rng());
|
||||
let msg: [u8; 16] = rand::thread_rng().gen();
|
||||
let comsig = ComSignature::sign(amount, &blind, &msg.to_vec())?;
|
||||
let comsig = ComSignature::sign(amount, &blind, &msg.to_vec(), false)?;
|
||||
|
||||
let commit = secp.commit(amount, blind.clone())?;
|
||||
assert!(comsig.verify(&commit, &msg.to_vec()).is_ok());
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
|
||||
//! Dalek key wrapper for mwixnet primitives
|
||||
|
||||
use super::secp::SecretKey;
|
||||
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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2023 The Grin Developers
|
||||
// Copyright 2024 The Grin Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -17,3 +17,5 @@
|
||||
pub mod comsig;
|
||||
pub mod dalek;
|
||||
pub mod secp;
|
||||
|
||||
pub use comsig::{comsig_serde, ComSigError, ComSignature};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2023 The Grin Developers
|
||||
// Copyright 2024 The Grin Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -12,26 +12,30 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! SECP wrapper functions for onion/comsig
|
||||
//! TODO: Likely redundant stuff in here, trim
|
||||
//! SECP operations for comsig
|
||||
|
||||
pub use secp256k1zkp::aggsig;
|
||||
pub use secp256k1zkp::constants::{
|
||||
AGG_SIGNATURE_SIZE, COMPRESSED_PUBLIC_KEY_SIZE, MAX_PROOF_SIZE, PEDERSEN_COMMITMENT_SIZE,
|
||||
SECRET_KEY_SIZE,
|
||||
pub use grin_util::secp::{
|
||||
self as secp256k1zkp,
|
||||
constants::SECRET_KEY_SIZE,
|
||||
key::{SecretKey, ZERO_KEY},
|
||||
pedersen::Commitment,
|
||||
rand::thread_rng,
|
||||
ContextFlag, Secp256k1,
|
||||
};
|
||||
pub use secp256k1zkp::ecdh::SharedSecret;
|
||||
pub use secp256k1zkp::key::{PublicKey, SecretKey, ZERO_KEY};
|
||||
pub use secp256k1zkp::pedersen::{Commitment, RangeProof};
|
||||
pub use secp256k1zkp::{ContextFlag, Message, Secp256k1, Signature};
|
||||
|
||||
use grin_core::ser::{self, Reader};
|
||||
use secp256k1zkp::rand::thread_rng;
|
||||
use rand::rngs::mock::StepRng;
|
||||
|
||||
/// Generate a random SecretKey.
|
||||
pub fn random_secret() -> SecretKey {
|
||||
pub fn random_secret(use_test_rng: bool) -> SecretKey {
|
||||
let secp = Secp256k1::new();
|
||||
SecretKey::new(&secp, &mut thread_rng())
|
||||
if use_test_rng {
|
||||
// allow for consistent test results
|
||||
let mut test_rng = StepRng::new(1_234_567_890_u64, 1);
|
||||
SecretKey::new(&secp, &mut test_rng)
|
||||
} else {
|
||||
SecretKey::new(&secp, &mut thread_rng())
|
||||
}
|
||||
}
|
||||
|
||||
/// Deserialize a SecretKey from a Reader
|
||||
@@ -43,6 +47,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())?;
|
||||
@@ -71,9 +76,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)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2023 The Grin Developers
|
||||
// Copyright 2024 The Grin Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -14,19 +14,26 @@
|
||||
|
||||
//! Onion module definition
|
||||
|
||||
pub mod crypto;
|
||||
mod crypto;
|
||||
pub mod onion;
|
||||
pub mod util;
|
||||
|
||||
use crypto::secp::{random_secret, Commitment, SecretKey};
|
||||
use onion::{new_stream_cipher, Onion, OnionError, Payload, RawBytes};
|
||||
pub use crypto::{
|
||||
comsig_serde, dalek::DalekPublicKey as MwixnetPublicKey, ComSigError, ComSignature,
|
||||
};
|
||||
|
||||
use chacha20::cipher::StreamCipher;
|
||||
use grin_core::core::FeeFields;
|
||||
use secp256k1zkp::pedersen::RangeProof;
|
||||
use grin_util::secp::{
|
||||
pedersen::{Commitment, RangeProof},
|
||||
SecretKey,
|
||||
};
|
||||
use x25519_dalek::PublicKey as xPublicKey;
|
||||
use x25519_dalek::{SharedSecret, StaticSecret};
|
||||
|
||||
use crypto::secp::random_secret;
|
||||
use onion::{new_stream_cipher, Onion, OnionError, Payload, RawBytes};
|
||||
|
||||
/// Onion hop struct
|
||||
#[derive(Clone)]
|
||||
pub struct Hop {
|
||||
@@ -41,6 +48,7 @@ pub struct Hop {
|
||||
}
|
||||
|
||||
/// Crate a new hop
|
||||
#[cfg(test)]
|
||||
pub fn new_hop(
|
||||
server_key: &SecretKey,
|
||||
hop_excess: &SecretKey,
|
||||
@@ -56,7 +64,11 @@ 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>) -> Result<Onion, OnionError> {
|
||||
pub fn create_onion(
|
||||
commitment: &Commitment,
|
||||
hops: &Vec<Hop>,
|
||||
use_test_rng: bool,
|
||||
) -> Result<Onion, OnionError> {
|
||||
if hops.is_empty() {
|
||||
return Ok(Onion {
|
||||
ephemeral_pubkey: xPublicKey::from([0u8; 32]),
|
||||
@@ -67,14 +79,14 @@ pub fn create_onion(commitment: &Commitment, hops: &Vec<Hop>) -> Result<Onion, O
|
||||
|
||||
let mut shared_secrets: Vec<SharedSecret> = Vec::new();
|
||||
let mut enc_payloads: Vec<RawBytes> = Vec::new();
|
||||
let mut ephemeral_sk = StaticSecret::from(random_secret().0);
|
||||
let mut ephemeral_sk = StaticSecret::from(random_secret(use_test_rng).0);
|
||||
let onion_ephemeral_pk = xPublicKey::from(&ephemeral_sk);
|
||||
for i in 0..hops.len() {
|
||||
let hop = &hops[i];
|
||||
let shared_secret = ephemeral_sk.diffie_hellman(&hop.server_pubkey);
|
||||
shared_secrets.push(shared_secret);
|
||||
|
||||
ephemeral_sk = StaticSecret::from(random_secret().0);
|
||||
ephemeral_sk = StaticSecret::from(random_secret(use_test_rng).0);
|
||||
let next_ephemeral_pk = if i < (hops.len() - 1) {
|
||||
xPublicKey::from(&ephemeral_sk)
|
||||
} else {
|
||||
@@ -106,16 +118,17 @@ 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;
|
||||
use crypto::secp;
|
||||
|
||||
use grin_core::core::hash::Hash;
|
||||
use grin_util::secp::Secp256k1;
|
||||
use grin_util::ToHex;
|
||||
use rand::{thread_rng, RngCore};
|
||||
use secp256k1zkp::Secp256k1;
|
||||
|
||||
pub fn rand_onion() -> Onion {
|
||||
let commit = rand_commit();
|
||||
@@ -128,32 +141,32 @@ pub mod test_util {
|
||||
None
|
||||
};
|
||||
let hop = new_hop(
|
||||
&random_secret(),
|
||||
&random_secret(),
|
||||
&random_secret(false),
|
||||
&random_secret(false),
|
||||
thread_rng().next_u32(),
|
||||
rangeproof,
|
||||
);
|
||||
hops.push(hop);
|
||||
}
|
||||
|
||||
create_onion(&commit, &hops).unwrap()
|
||||
create_onion(&commit, &hops, false).unwrap()
|
||||
}
|
||||
|
||||
pub fn rand_commit() -> Commitment {
|
||||
secp::commit(rand::thread_rng().next_u64(), &secp::random_secret()).unwrap()
|
||||
secp::commit(rand::thread_rng().next_u64(), &secp::random_secret(false)).unwrap()
|
||||
}
|
||||
|
||||
pub fn rand_hash() -> Hash {
|
||||
Hash::from_hex(secp::random_secret().to_hex().as_str()).unwrap()
|
||||
Hash::from_hex(secp::random_secret(false).to_hex().as_str()).unwrap()
|
||||
}
|
||||
|
||||
pub fn rand_proof() -> RangeProof {
|
||||
let secp = Secp256k1::new();
|
||||
secp.bullet_proof(
|
||||
rand::thread_rng().next_u64(),
|
||||
secp::random_secret(),
|
||||
secp::random_secret(),
|
||||
secp::random_secret(),
|
||||
secp::random_secret(false),
|
||||
secp::random_secret(false),
|
||||
secp::random_secret(false),
|
||||
None,
|
||||
None,
|
||||
)
|
||||
@@ -177,8 +190,8 @@ pub mod test_util {
|
||||
let rp = secp.bullet_proof(
|
||||
out_value,
|
||||
blind.clone(),
|
||||
secp::random_secret(),
|
||||
secp::random_secret(),
|
||||
secp::random_secret(false),
|
||||
secp::random_secret(false),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
@@ -187,7 +200,7 @@ pub mod test_util {
|
||||
}
|
||||
|
||||
pub fn rand_keypair() -> (SecretKey, DalekPublicKey) {
|
||||
let sk = random_secret();
|
||||
let sk = random_secret(false);
|
||||
let pk = DalekPublicKey::from_secret(&sk);
|
||||
(sk, pk)
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
//! Onion defn for mwixnet
|
||||
|
||||
use super::crypto::secp::{self, Commitment, RangeProof, SecretKey};
|
||||
use super::util::{read_optional, vec_to_array, write_optional};
|
||||
|
||||
use std::convert::TryFrom;
|
||||
@@ -26,6 +25,11 @@ use chacha20::cipher::{NewCipher, StreamCipher};
|
||||
use chacha20::{ChaCha20, Key, Nonce};
|
||||
use grin_core::core::FeeFields;
|
||||
use grin_core::ser::{self, Readable, Reader, Writeable, Writer};
|
||||
use grin_util::secp::{
|
||||
self as secp256k1zkp,
|
||||
key::SecretKey,
|
||||
pedersen::{Commitment, RangeProof},
|
||||
};
|
||||
use grin_util::{self, ToHex};
|
||||
use hmac::digest::InvalidLength;
|
||||
use hmac::{Hmac, Mac};
|
||||
@@ -35,6 +39,8 @@ use sha2::Sha256;
|
||||
use thiserror::Error;
|
||||
use x25519_dalek::{PublicKey as xPublicKey, SharedSecret, StaticSecret};
|
||||
|
||||
use super::crypto::secp;
|
||||
|
||||
type HmacSha256 = Hmac<Sha256>;
|
||||
/// Raw bytes alias
|
||||
pub type RawBytes = Vec<u8>;
|
||||
@@ -374,7 +380,7 @@ pub mod tests {
|
||||
let fee_per_hop: u32 = 2;
|
||||
let in_value: u64 = 1000;
|
||||
let out_value: u64 = in_value - total_fee;
|
||||
let blind = random_secret();
|
||||
let blind = random_secret(false);
|
||||
let commitment = secp::commit(in_value, &blind).unwrap();
|
||||
|
||||
let mut hops: Vec<Hop> = Vec::new();
|
||||
@@ -382,15 +388,15 @@ pub mod tests {
|
||||
let mut final_commit = secp::commit(out_value, &blind).unwrap();
|
||||
let mut final_blind = blind.clone();
|
||||
for i in 0..5 {
|
||||
keys.push(random_secret());
|
||||
keys.push(random_secret(false));
|
||||
|
||||
let excess = random_secret();
|
||||
let excess = random_secret(false);
|
||||
|
||||
let secp = secp256k1zkp::Secp256k1::with_caps(secp256k1zkp::ContextFlag::Commit);
|
||||
final_blind.add_assign(&secp, &excess).unwrap();
|
||||
final_commit = secp::add_excess(&final_commit, &excess).unwrap();
|
||||
let proof = if i == 4 {
|
||||
let n1 = random_secret();
|
||||
let n1 = random_secret(false);
|
||||
let rp = secp.bullet_proof(
|
||||
out_value,
|
||||
final_blind.clone(),
|
||||
@@ -409,11 +415,12 @@ pub mod tests {
|
||||
hops.push(hop);
|
||||
}
|
||||
|
||||
let mut onion_packet = crate::mwixnet::onion::create_onion(&commitment, &hops).unwrap();
|
||||
let mut onion_packet =
|
||||
crate::mwixnet::onion::create_onion(&commitment, &hops, false).unwrap();
|
||||
|
||||
let mut payload = Payload {
|
||||
next_ephemeral_pk: onion_packet.ephemeral_pubkey.clone(),
|
||||
excess: random_secret(),
|
||||
excess: random_secret(false),
|
||||
fee: FeeFields::from(fee_per_hop),
|
||||
rangeproof: None,
|
||||
};
|
||||
|
||||
@@ -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());
|
||||
@@ -106,7 +106,7 @@ pub fn read_optional<O: Readable, R: Reader>(reader: &mut R) -> Result<Option<O>
|
||||
/// # 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]);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2022 The Grin Developers
|
||||
// Copyright 2024 The Grin Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -15,28 +15,29 @@
|
||||
//! Types related to mwixnet requests required by rest of lib crate apis
|
||||
//! Should rexport all needed types here
|
||||
|
||||
pub use super::onion::crypto::comsig::{self, ComSignature};
|
||||
pub use super::onion::crypto::secp::{add_excess, random_secret};
|
||||
pub use super::onion::onion::Onion;
|
||||
pub use super::onion::{new_hop, Hop};
|
||||
use crate::grin_util::secp::key::SecretKey;
|
||||
use super::onion::comsig_serde;
|
||||
use grin_core::libtx::secp_ser::string_or_u64;
|
||||
use grin_util::secp::key::SecretKey;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub use super::onion::{onion::Onion, ComSignature, Hop};
|
||||
|
||||
/// A Swap request
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct SwapReq {
|
||||
/// Com signature
|
||||
#[serde(with = "comsig::comsig_serde")]
|
||||
#[serde(with = "comsig_serde")]
|
||||
pub comsig: ComSignature,
|
||||
/// Onion
|
||||
pub onion: Onion,
|
||||
}
|
||||
|
||||
/// 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,
|
||||
#[serde(with = "string_or_u64")]
|
||||
pub fee_per_hop: u64,
|
||||
}
|
||||
|
||||
@@ -188,11 +188,11 @@ fn format_slatepack(slatepack: &str) -> Result<String, Error> {
|
||||
|
||||
// Returns the first four bytes of a double sha256 hash of some bytes
|
||||
fn generate_check(payload: &[u8]) -> Result<Vec<u8>, Error> {
|
||||
let mut first_hash = Sha256::new();
|
||||
first_hash.update(payload);
|
||||
let mut second_hash = Sha256::new();
|
||||
second_hash.update(first_hash.finalize());
|
||||
let checksum = second_hash.finalize();
|
||||
let mut first_hasher = Sha256::new();
|
||||
first_hasher.update(payload);
|
||||
let mut second_hasher = Sha256::new();
|
||||
second_hasher.update(first_hasher.finalize());
|
||||
let checksum = second_hasher.finalize();
|
||||
let check_bytes: Vec<u8> = checksum[0..4].to_vec();
|
||||
Ok(check_bytes)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user