mirror of
https://github.com/mimblewimble/mwixnet.git
synced 2025-01-20 19:11:09 +03:00
move onion creation to a separate library
This commit is contained in:
parent
d99aa6ec7c
commit
dc3f99ebfa
18 changed files with 374 additions and 265 deletions
37
Cargo.lock
generated
37
Cargo.lock
generated
|
@ -1354,6 +1354,42 @@ dependencies = [
|
|||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "grin_onion"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"blake2-rfc",
|
||||
"byteorder",
|
||||
"bytes 0.5.6",
|
||||
"chacha20",
|
||||
"curve25519-dalek 2.1.3",
|
||||
"ed25519-dalek",
|
||||
"grin_api 5.2.0-alpha.1 (git+https://github.com/mimblewimble/grin)",
|
||||
"grin_chain 5.2.0-alpha.1 (git+https://github.com/mimblewimble/grin)",
|
||||
"grin_core 5.2.0-alpha.1 (git+https://github.com/mimblewimble/grin)",
|
||||
"grin_keychain 5.2.0-alpha.1 (git+https://github.com/mimblewimble/grin)",
|
||||
"grin_secp256k1zkp",
|
||||
"grin_servers",
|
||||
"grin_store 5.2.0-alpha.1 (git+https://github.com/mimblewimble/grin)",
|
||||
"grin_util 5.1.1",
|
||||
"grin_wallet_api",
|
||||
"grin_wallet_impls",
|
||||
"grin_wallet_libwallet",
|
||||
"grin_wallet_util",
|
||||
"hmac 0.12.0",
|
||||
"itertools",
|
||||
"lazy_static",
|
||||
"rand 0.7.3",
|
||||
"rpassword",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"sha2 0.10.0",
|
||||
"thiserror",
|
||||
"toml",
|
||||
"x25519-dalek 0.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "grin_p2p"
|
||||
version = "5.2.0-alpha.1"
|
||||
|
@ -2555,6 +2591,7 @@ dependencies = [
|
|||
"grin_chain 5.2.0-alpha.1 (git+https://github.com/mimblewimble/grin)",
|
||||
"grin_core 5.2.0-alpha.1 (git+https://github.com/mimblewimble/grin)",
|
||||
"grin_keychain 5.2.0-alpha.1 (git+https://github.com/mimblewimble/grin)",
|
||||
"grin_onion",
|
||||
"grin_secp256k1zkp",
|
||||
"grin_servers",
|
||||
"grin_store 5.2.0-alpha.1 (git+https://github.com/mimblewimble/grin)",
|
||||
|
|
|
@ -5,6 +5,9 @@ edition = "2021"
|
|||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[workspace]
|
||||
members = ["onion"]
|
||||
|
||||
[dependencies]
|
||||
blake2 = { package = "blake2-rfc", version = "0.2"}
|
||||
byteorder = "1"
|
||||
|
@ -36,6 +39,7 @@ thiserror = "1.0.31"
|
|||
tokio = { version = "1", features = ["full"] }
|
||||
toml = "0.5"
|
||||
x25519-dalek = "0.6.0"
|
||||
grin_onion = { path = "./onion" }
|
||||
grin_secp256k1zkp = { version = "0.7.11", features = ["bullet-proof-sizing"]}
|
||||
grin_util = "5"
|
||||
grin_api = { git = "https://github.com/mimblewimble/grin", version = "5.2.0-alpha.1" }
|
||||
|
|
38
onion/Cargo.toml
Normal file
38
onion/Cargo.toml
Normal file
|
@ -0,0 +1,38 @@
|
|||
[package]
|
||||
name = "grin_onion"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
blake2 = { package = "blake2-rfc", version = "0.2"}
|
||||
byteorder = "1"
|
||||
bytes = "0.5.6"
|
||||
chacha20 = "0.8.1"
|
||||
curve25519-dalek = "2.1"
|
||||
ed25519-dalek = "1.0.1"
|
||||
hmac = { version = "0.12.0", features = ["std"]}
|
||||
itertools = { version = "0.10.3"}
|
||||
lazy_static = "1"
|
||||
rand = "0.7.3"
|
||||
rpassword = "4.0"
|
||||
serde = { version = "1", features= ["derive"]}
|
||||
serde_derive = "1"
|
||||
serde_json = "1"
|
||||
sha2 = "0.10.0"
|
||||
thiserror = "1.0.31"
|
||||
toml = "0.5"
|
||||
x25519-dalek = "0.6.0"
|
||||
grin_secp256k1zkp = { version = "0.7.11", features = ["bullet-proof-sizing"]}
|
||||
grin_util = "5"
|
||||
grin_api = { git = "https://github.com/mimblewimble/grin", version = "5.2.0-alpha.1" }
|
||||
grin_core = { git = "https://github.com/mimblewimble/grin", version = "5.2.0-alpha.1" }
|
||||
grin_chain = { git = "https://github.com/mimblewimble/grin", version = "5.2.0-alpha.1" }
|
||||
grin_keychain = { git = "https://github.com/mimblewimble/grin", version = "5.2.0-alpha.1" }
|
||||
grin_servers = { git = "https://github.com/mimblewimble/grin", version = "5.2.0-alpha.1" }
|
||||
grin_store = { git = "https://github.com/mimblewimble/grin", version = "5.2.0-alpha.1" }
|
||||
grin_wallet_api = { git = "https://github.com/mimblewimble/grin-wallet", branch = "master" }
|
||||
grin_wallet_impls = { git = "https://github.com/mimblewimble/grin-wallet", branch = "master" }
|
||||
grin_wallet_libwallet = { git = "https://github.com/mimblewimble/grin-wallet", branch = "master" }
|
||||
grin_wallet_util = { git = "https://github.com/mimblewimble/grin-wallet", branch = "master" }
|
|
@ -159,18 +159,6 @@ pub fn sign(sk: &SecretKey, message: &[u8]) -> Result<DalekSignature, DalekError
|
|||
Ok(DalekSignature(sig))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test_util {
|
||||
use super::*;
|
||||
use crate::crypto::secp::random_secret;
|
||||
|
||||
pub fn rand_keypair() -> (SecretKey, DalekPublicKey) {
|
||||
let sk = random_secret();
|
||||
let pk = DalekPublicKey::from_secret(&sk);
|
||||
(sk, pk)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
|
@ -60,58 +60,3 @@ pub fn sign(sk: &SecretKey, msg: &Message) -> Result<Signature, secp256k1zkp::Er
|
|||
let sig = aggsig::sign_single(&secp, &msg, &sk, None, None, None, Some(&pubkey), None)?;
|
||||
Ok(sig)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test_util {
|
||||
use crate::crypto::secp::{self, Commitment, RangeProof, Secp256k1, SecretKey};
|
||||
use grin_core::core::hash::Hash;
|
||||
use grin_util::ToHex;
|
||||
use rand::RngCore;
|
||||
|
||||
pub fn rand_commit() -> Commitment {
|
||||
secp::commit(rand::thread_rng().next_u64(), &secp::random_secret()).unwrap()
|
||||
}
|
||||
|
||||
pub fn rand_hash() -> Hash {
|
||||
Hash::from_hex(secp::random_secret().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(),
|
||||
None,
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn proof(
|
||||
value: u64,
|
||||
fee: u32,
|
||||
input_blind: &SecretKey,
|
||||
hop_excesses: &Vec<&SecretKey>,
|
||||
) -> (Commitment, RangeProof) {
|
||||
let secp = Secp256k1::new();
|
||||
|
||||
let mut blind = input_blind.clone();
|
||||
for hop_excess in hop_excesses {
|
||||
blind.add_assign(&secp, &hop_excess).unwrap();
|
||||
}
|
||||
|
||||
let out_value = value - (fee as u64);
|
||||
|
||||
let rp = secp.bullet_proof(
|
||||
out_value,
|
||||
blind.clone(),
|
||||
secp::random_secret(),
|
||||
secp::random_secret(),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
|
||||
(secp::commit(out_value, &blind).unwrap(), rp)
|
||||
}
|
||||
}
|
170
onion/src/lib.rs
Normal file
170
onion/src/lib.rs
Normal file
|
@ -0,0 +1,170 @@
|
|||
pub mod crypto;
|
||||
pub mod onion;
|
||||
pub mod util;
|
||||
|
||||
use crate::crypto::secp::{random_secret, Commitment, SecretKey};
|
||||
use crate::onion::{new_stream_cipher, Onion, OnionError, Payload, RawBytes};
|
||||
|
||||
use chacha20::cipher::StreamCipher;
|
||||
use grin_core::core::FeeFields;
|
||||
use secp256k1zkp::pedersen::RangeProof;
|
||||
use x25519_dalek::PublicKey as xPublicKey;
|
||||
use x25519_dalek::{SharedSecret, StaticSecret};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Hop {
|
||||
pub server_pubkey: xPublicKey,
|
||||
pub excess: SecretKey,
|
||||
pub fee: FeeFields,
|
||||
pub rangeproof: Option<RangeProof>,
|
||||
}
|
||||
|
||||
pub fn new_hop(
|
||||
server_key: &SecretKey,
|
||||
hop_excess: &SecretKey,
|
||||
fee: u32,
|
||||
proof: Option<RangeProof>,
|
||||
) -> Hop {
|
||||
Hop {
|
||||
server_pubkey: xPublicKey::from(&StaticSecret::from(server_key.0.clone())),
|
||||
excess: hop_excess.clone(),
|
||||
fee: FeeFields::from(fee as u32),
|
||||
rangeproof: proof,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create an Onion for the Commitment, encrypting the payload for each hop
|
||||
pub fn create_onion(commitment: &Commitment, hops: &Vec<Hop>) -> Result<Onion, OnionError> {
|
||||
if hops.is_empty() {
|
||||
return Ok(Onion {
|
||||
ephemeral_pubkey: xPublicKey::from([0u8; 32]),
|
||||
commit: commitment.clone(),
|
||||
enc_payloads: vec![],
|
||||
});
|
||||
}
|
||||
|
||||
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 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);
|
||||
let next_ephemeral_pk = if i < (hops.len() - 1) {
|
||||
xPublicKey::from(&ephemeral_sk)
|
||||
} else {
|
||||
xPublicKey::from([0u8; 32])
|
||||
};
|
||||
|
||||
let payload = Payload {
|
||||
next_ephemeral_pk,
|
||||
excess: hop.excess.clone(),
|
||||
fee: hop.fee.clone(),
|
||||
rangeproof: hop.rangeproof.clone(),
|
||||
};
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
let onion = Onion {
|
||||
ephemeral_pubkey: onion_ephemeral_pk,
|
||||
commit: commitment.clone(),
|
||||
enc_payloads,
|
||||
};
|
||||
Ok(onion)
|
||||
}
|
||||
|
||||
pub mod test_util {
|
||||
use super::*;
|
||||
use crate::crypto::dalek::DalekPublicKey;
|
||||
use crate::crypto::secp;
|
||||
|
||||
use grin_core::core::hash::Hash;
|
||||
use grin_util::ToHex;
|
||||
use rand::{thread_rng, RngCore};
|
||||
use secp256k1zkp::Secp256k1;
|
||||
|
||||
pub fn rand_onion() -> Onion {
|
||||
let commit = rand_commit();
|
||||
let mut hops = Vec::new();
|
||||
let k = (thread_rng().next_u64() % 5) + 1;
|
||||
for i in 0..k {
|
||||
let rangeproof = if i == (k - 1) {
|
||||
Some(rand_proof())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let hop = new_hop(
|
||||
&random_secret(),
|
||||
&random_secret(),
|
||||
thread_rng().next_u32(),
|
||||
rangeproof,
|
||||
);
|
||||
hops.push(hop);
|
||||
}
|
||||
|
||||
create_onion(&commit, &hops).unwrap()
|
||||
}
|
||||
|
||||
pub fn rand_commit() -> Commitment {
|
||||
secp::commit(rand::thread_rng().next_u64(), &secp::random_secret()).unwrap()
|
||||
}
|
||||
|
||||
pub fn rand_hash() -> Hash {
|
||||
Hash::from_hex(secp::random_secret().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(),
|
||||
None,
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn proof(
|
||||
value: u64,
|
||||
fee: u32,
|
||||
input_blind: &SecretKey,
|
||||
hop_excesses: &Vec<&SecretKey>,
|
||||
) -> (Commitment, RangeProof) {
|
||||
let secp = Secp256k1::new();
|
||||
|
||||
let mut blind = input_blind.clone();
|
||||
for hop_excess in hop_excesses {
|
||||
blind.add_assign(&secp, &hop_excess).unwrap();
|
||||
}
|
||||
|
||||
let out_value = value - (fee as u64);
|
||||
|
||||
let rp = secp.bullet_proof(
|
||||
out_value,
|
||||
blind.clone(),
|
||||
secp::random_secret(),
|
||||
secp::random_secret(),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
|
||||
(secp::commit(out_value, &blind).unwrap(), rp)
|
||||
}
|
||||
|
||||
pub fn rand_keypair() -> (SecretKey, DalekPublicKey) {
|
||||
let sk = random_secret();
|
||||
let pk = DalekPublicKey::from_secret(&sk);
|
||||
(sk, pk)
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
use crate::crypto::secp::{self, Commitment, RangeProof, SecretKey};
|
||||
use crate::onion::OnionError::{InvalidKeyLength, SerializationError};
|
||||
use crate::util::{read_optional, vec_to_array, write_optional};
|
||||
|
||||
use chacha20::cipher::{NewCipher, StreamCipher};
|
||||
|
@ -19,7 +18,7 @@ use thiserror::Error;
|
|||
use x25519_dalek::{PublicKey as xPublicKey, SharedSecret, StaticSecret};
|
||||
|
||||
type HmacSha256 = Hmac<Sha256>;
|
||||
type RawBytes = Vec<u8>;
|
||||
pub type RawBytes = Vec<u8>;
|
||||
|
||||
const CURRENT_ONION_VERSION: u8 = 0;
|
||||
|
||||
|
@ -70,7 +69,6 @@ impl Payload {
|
|||
Ok(payload)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn serialize(&self) -> Result<Vec<u8>, ser::Error> {
|
||||
let mut vec = vec![];
|
||||
ser::serialize_default(&mut vec, &self)?;
|
||||
|
@ -166,7 +164,7 @@ impl Onion {
|
|||
}
|
||||
}
|
||||
|
||||
fn new_stream_cipher(shared_secret: &SharedSecret) -> Result<ChaCha20, OnionError> {
|
||||
pub fn new_stream_cipher(shared_secret: &SharedSecret) -> Result<ChaCha20, OnionError> {
|
||||
let mut mu_hmac = HmacSha256::new_from_slice(b"MWIXNET")?;
|
||||
mu_hmac.update(shared_secret.as_bytes());
|
||||
let mukey = mu_hmac.finalize().into_bytes();
|
||||
|
@ -318,129 +316,21 @@ pub enum OnionError {
|
|||
|
||||
impl From<InvalidLength> for OnionError {
|
||||
fn from(_err: InvalidLength) -> OnionError {
|
||||
InvalidKeyLength
|
||||
OnionError::InvalidKeyLength
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ser::Error> for OnionError {
|
||||
fn from(err: ser::Error) -> OnionError {
|
||||
SerializationError(err)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test_util {
|
||||
use super::{Onion, OnionError, Payload, RawBytes};
|
||||
use crate::crypto::secp::test_util::{rand_commit, rand_proof};
|
||||
use crate::crypto::secp::{random_secret, Commitment, SecretKey};
|
||||
|
||||
use chacha20::cipher::StreamCipher;
|
||||
use grin_core::core::FeeFields;
|
||||
use rand::{thread_rng, RngCore};
|
||||
use secp256k1zkp::pedersen::RangeProof;
|
||||
use x25519_dalek::PublicKey as xPublicKey;
|
||||
use x25519_dalek::{SharedSecret, StaticSecret};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Hop {
|
||||
pub server_pubkey: xPublicKey,
|
||||
pub excess: SecretKey,
|
||||
pub fee: FeeFields,
|
||||
pub rangeproof: Option<RangeProof>,
|
||||
}
|
||||
|
||||
pub fn new_hop(
|
||||
server_key: &SecretKey,
|
||||
hop_excess: &SecretKey,
|
||||
fee: u32,
|
||||
proof: Option<RangeProof>,
|
||||
) -> Hop {
|
||||
Hop {
|
||||
server_pubkey: xPublicKey::from(&StaticSecret::from(server_key.0.clone())),
|
||||
excess: hop_excess.clone(),
|
||||
fee: FeeFields::from(fee as u32),
|
||||
rangeproof: proof,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create an Onion for the Commitment, encrypting the payload for each hop
|
||||
pub fn create_onion(commitment: &Commitment, hops: &Vec<Hop>) -> Result<Onion, OnionError> {
|
||||
if hops.is_empty() {
|
||||
return Ok(Onion {
|
||||
ephemeral_pubkey: xPublicKey::from([0u8; 32]),
|
||||
commit: commitment.clone(),
|
||||
enc_payloads: vec![],
|
||||
});
|
||||
}
|
||||
|
||||
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 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);
|
||||
let next_ephemeral_pk = if i < (hops.len() - 1) {
|
||||
xPublicKey::from(&ephemeral_sk)
|
||||
} else {
|
||||
xPublicKey::from([0u8; 32])
|
||||
};
|
||||
|
||||
let payload = Payload {
|
||||
next_ephemeral_pk,
|
||||
excess: hop.excess.clone(),
|
||||
fee: hop.fee.clone(),
|
||||
rangeproof: hop.rangeproof.clone(),
|
||||
};
|
||||
enc_payloads.push(payload.serialize()?);
|
||||
}
|
||||
|
||||
for i in (0..shared_secrets.len()).rev() {
|
||||
let mut cipher = super::new_stream_cipher(&shared_secrets[i])?;
|
||||
for j in i..shared_secrets.len() {
|
||||
cipher.apply_keystream(&mut enc_payloads[j]);
|
||||
}
|
||||
}
|
||||
|
||||
let onion = Onion {
|
||||
ephemeral_pubkey: onion_ephemeral_pk,
|
||||
commit: commitment.clone(),
|
||||
enc_payloads,
|
||||
};
|
||||
Ok(onion)
|
||||
}
|
||||
|
||||
pub fn rand_onion() -> Onion {
|
||||
let commit = rand_commit();
|
||||
let mut hops = Vec::new();
|
||||
let k = (thread_rng().next_u64() % 5) + 1;
|
||||
for i in 0..k {
|
||||
let rangeproof = if i == (k - 1) {
|
||||
Some(rand_proof())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let hop = new_hop(
|
||||
&random_secret(),
|
||||
&random_secret(),
|
||||
thread_rng().next_u32(),
|
||||
rangeproof,
|
||||
);
|
||||
hops.push(hop);
|
||||
}
|
||||
|
||||
create_onion(&commit, &hops).unwrap()
|
||||
OnionError::SerializationError(err)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use super::test_util::{new_hop, Hop};
|
||||
use super::*;
|
||||
use crate::crypto::secp::random_secret;
|
||||
use crate::{new_hop, Hop};
|
||||
|
||||
use grin_core::core::FeeFields;
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
use crate::config::ServerConfig;
|
||||
use crate::crypto::dalek;
|
||||
use crate::onion::Onion;
|
||||
use crate::servers::mix_rpc::MixReq;
|
||||
use crate::tx::TxComponents;
|
||||
use crate::{tor, DalekPublicKey};
|
||||
use grin_onion::onion::Onion;
|
||||
|
||||
use grin_api::client;
|
||||
use grin_api::json_rpc::build_request;
|
||||
|
@ -97,8 +97,8 @@ impl MixClient for MixClientImpl {
|
|||
#[cfg(test)]
|
||||
pub mod mock {
|
||||
use super::{ClientError, MixClient};
|
||||
use crate::onion::Onion;
|
||||
use crate::tx::TxComponents;
|
||||
use grin_onion::onion::Onion;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
|
@ -136,12 +136,12 @@ pub mod test_util {
|
|||
use super::{ClientError, MixClient};
|
||||
use crate::crypto::dalek;
|
||||
use crate::crypto::secp::SecretKey;
|
||||
use crate::onion::Onion;
|
||||
use crate::servers::mix::MixServer;
|
||||
use crate::tx::TxComponents;
|
||||
use crate::DalekPublicKey;
|
||||
use grin_core::ser;
|
||||
use grin_core::ser::ProtocolVersion;
|
||||
use grin_onion::onion::Onion;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Implementation of the 'MixClient' trait that calls a mix server implementation directly.
|
||||
|
|
|
@ -4,12 +4,13 @@ use store::SwapStore;
|
|||
use wallet::HttpWallet;
|
||||
|
||||
use crate::client::{MixClient, MixClientImpl};
|
||||
use crate::crypto::dalek::DalekPublicKey;
|
||||
use crate::node::GrinNode;
|
||||
use crate::store::StoreError;
|
||||
use clap::App;
|
||||
use grin_core::global;
|
||||
use grin_core::global::ChainTypes;
|
||||
use grin_onion::crypto;
|
||||
use grin_onion::crypto::dalek::DalekPublicKey;
|
||||
use grin_util::{StopState, ZeroingString};
|
||||
use rpassword;
|
||||
use std::path::PathBuf;
|
||||
|
@ -21,14 +22,11 @@ extern crate clap;
|
|||
|
||||
mod client;
|
||||
mod config;
|
||||
mod crypto;
|
||||
mod node;
|
||||
mod onion;
|
||||
mod servers;
|
||||
mod store;
|
||||
mod tor;
|
||||
mod tx;
|
||||
mod util;
|
||||
mod wallet;
|
||||
|
||||
const DEFAULT_INTERVAL: u32 = 12 * 60 * 60;
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
use crate::client::MixClient;
|
||||
use crate::config::ServerConfig;
|
||||
use crate::crypto::dalek::{self, DalekSignature};
|
||||
use crate::onion::{Onion, OnionError, PeeledOnion};
|
||||
use crate::tx::TxComponents;
|
||||
use crate::wallet::Wallet;
|
||||
use crate::{node, tx, GrinNode};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use crate::client::MixClient;
|
||||
use crate::tx::TxComponents;
|
||||
use grin_core::core::{Output, OutputFeatures, TransactionBody};
|
||||
use grin_core::global::DEFAULT_ACCEPT_FEE_BASE;
|
||||
use grin_core::ser;
|
||||
use grin_core::ser::ProtocolVersion;
|
||||
use grin_onion::crypto::dalek::{self, DalekSignature};
|
||||
use grin_onion::onion::{Onion, OnionError, PeeledOnion};
|
||||
use itertools::Itertools;
|
||||
use secp256k1zkp::key::ZERO_KEY;
|
||||
use secp256k1zkp::Secp256k1;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::sync::Arc;
|
||||
use thiserror::Error;
|
||||
|
||||
|
@ -320,14 +320,13 @@ mod test_util {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::crypto::dalek;
|
||||
use crate::crypto::secp::{self, Commitment};
|
||||
use crate::node::mock::MockGrinNode;
|
||||
use crate::onion::test_util;
|
||||
use crate::{DalekPublicKey, MixClient};
|
||||
|
||||
use crate::onion::test_util::Hop;
|
||||
use ::function_name::named;
|
||||
use grin_onion::crypto::secp::{self, Commitment};
|
||||
use grin_onion::test_util as onion_test_util;
|
||||
use grin_onion::{create_onion, new_hop, Hop};
|
||||
use secp256k1zkp::pedersen::RangeProof;
|
||||
use secp256k1zkp::SecretKey;
|
||||
use std::collections::HashSet;
|
||||
|
@ -353,7 +352,7 @@ mod tests {
|
|||
|
||||
impl ServerVars {
|
||||
fn new(fee: u32) -> Self {
|
||||
let (sk, pk) = dalek::test_util::rand_keypair();
|
||||
let (sk, pk) = onion_test_util::rand_keypair();
|
||||
let excess = secp::random_secret();
|
||||
ServerVars {
|
||||
fee,
|
||||
|
@ -364,7 +363,7 @@ mod tests {
|
|||
}
|
||||
|
||||
fn build_hop(&self, proof: Option<RangeProof>) -> Hop {
|
||||
test_util::new_hop(&self.sk, &self.excess, self.fee, proof)
|
||||
new_hop(&self.sk, &self.excess, self.fee, proof)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -408,7 +407,7 @@ mod tests {
|
|||
);
|
||||
|
||||
// Build rangeproof
|
||||
let (output_commit, proof) = secp::test_util::proof(
|
||||
let (output_commit, proof) = onion_test_util::proof(
|
||||
input1_value,
|
||||
swap_vars.fee + mix1_vars.fee + mix2_vars.fee,
|
||||
&input1_blind,
|
||||
|
@ -416,7 +415,7 @@ mod tests {
|
|||
);
|
||||
|
||||
// Create Onion
|
||||
let onion = test_util::create_onion(
|
||||
let onion = create_onion(
|
||||
&input1_commit,
|
||||
&vec![
|
||||
swap_vars.build_hop(None),
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use crate::client::MixClient;
|
||||
use crate::config::ServerConfig;
|
||||
use crate::crypto::dalek::{self, DalekSignature};
|
||||
use crate::node::GrinNode;
|
||||
use crate::onion::Onion;
|
||||
use crate::servers::mix::{MixError, MixServer, MixServerImpl};
|
||||
use crate::wallet::Wallet;
|
||||
|
||||
use crate::client::MixClient;
|
||||
use grin_onion::onion::Onion;
|
||||
use grin_util::StopState;
|
||||
use jsonrpc_derive::rpc;
|
||||
use jsonrpc_http_server::jsonrpc_core::{self as jsonrpc, IoHandler};
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
use crate::client::MixClient;
|
||||
use crate::config::ServerConfig;
|
||||
use crate::crypto::comsig::ComSignature;
|
||||
use crate::crypto::secp::{Commitment, Secp256k1, SecretKey};
|
||||
use crate::node::{self, GrinNode};
|
||||
use crate::onion::{Onion, OnionError};
|
||||
use crate::store::{StoreError, SwapData, SwapStatus, SwapStore};
|
||||
use crate::tx;
|
||||
use crate::wallet::Wallet;
|
||||
use std::collections::HashSet;
|
||||
|
||||
use crate::client::MixClient;
|
||||
use grin_core::core::hash::Hashed;
|
||||
use grin_core::core::{Input, Output, OutputFeatures, Transaction, TransactionBody};
|
||||
use grin_core::global::DEFAULT_ACCEPT_FEE_BASE;
|
||||
use grin_onion::onion::{Onion, OnionError};
|
||||
use itertools::Itertools;
|
||||
use secp256k1zkp::key::ZERO_KEY;
|
||||
use std::collections::HashSet;
|
||||
use std::result::Result;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use thiserror::Error;
|
||||
|
@ -268,9 +268,9 @@ impl SwapServer for SwapServerImpl {
|
|||
pub mod mock {
|
||||
use super::{SwapError, SwapServer};
|
||||
use crate::crypto::comsig::ComSignature;
|
||||
use crate::onion::Onion;
|
||||
|
||||
use grin_core::core::Transaction;
|
||||
use grin_onion::onion::Onion;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct MockSwapServer {
|
||||
|
@ -339,12 +339,7 @@ pub mod test_util {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::crypto::comsig::ComSignature;
|
||||
use crate::crypto::dalek;
|
||||
use crate::crypto::secp;
|
||||
use crate::node::mock::MockGrinNode;
|
||||
use crate::onion::test_util::{self, Hop};
|
||||
use crate::onion::Onion;
|
||||
use crate::servers::swap::{SwapError, SwapServer};
|
||||
use crate::store::{SwapData, SwapStatus};
|
||||
use crate::tx::TxComponents;
|
||||
|
@ -353,6 +348,11 @@ mod tests {
|
|||
use ::function_name::named;
|
||||
use grin_core::core::hash::Hashed;
|
||||
use grin_core::core::{Committed, Input, Output, OutputFeatures, Transaction, Weighting};
|
||||
use grin_onion::crypto::comsig::ComSignature;
|
||||
use grin_onion::crypto::secp;
|
||||
use grin_onion::onion::Onion;
|
||||
use grin_onion::test_util as onion_test_util;
|
||||
use grin_onion::{create_onion, new_hop, Hop};
|
||||
use secp256k1zkp::key::ZERO_KEY;
|
||||
use std::sync::Arc;
|
||||
use x25519_dalek::PublicKey as xPublicKey;
|
||||
|
@ -392,10 +392,10 @@ mod tests {
|
|||
|
||||
let server_key = secp::random_secret();
|
||||
let hop_excess = secp::random_secret();
|
||||
let (output_commit, proof) = secp::test_util::proof(value, fee, &blind, &vec![&hop_excess]);
|
||||
let hop = test_util::new_hop(&server_key, &hop_excess, fee, Some(proof));
|
||||
let (output_commit, proof) = onion_test_util::proof(value, fee, &blind, &vec![&hop_excess]);
|
||||
let hop = new_hop(&server_key, &hop_excess, fee, Some(proof));
|
||||
|
||||
let onion = test_util::create_onion(&input_commit, &vec![hop.clone()])?;
|
||||
let onion = create_onion(&input_commit, &vec![hop.clone()])?;
|
||||
let comsig = ComSignature::sign(value, &blind, &onion.serialize()?)?;
|
||||
|
||||
let node: Arc<MockGrinNode> = Arc::new(MockGrinNode::new_with_utxos(&vec![&input_commit]));
|
||||
|
@ -464,24 +464,24 @@ mod tests {
|
|||
|
||||
// Swapper data
|
||||
let swap_fee: u32 = 50_000_000;
|
||||
let (swap_sk, _swap_pk) = dalek::test_util::rand_keypair();
|
||||
let (swap_sk, _swap_pk) = onion_test_util::rand_keypair();
|
||||
let swap_hop_excess = secp::random_secret();
|
||||
let swap_hop = test_util::new_hop(&swap_sk, &swap_hop_excess, swap_fee, None);
|
||||
let swap_hop = new_hop(&swap_sk, &swap_hop_excess, swap_fee, None);
|
||||
|
||||
// Mixer data
|
||||
let mixer_fee: u32 = 30_000_000;
|
||||
let (mixer_sk, mixer_pk) = dalek::test_util::rand_keypair();
|
||||
let (mixer_sk, mixer_pk) = onion_test_util::rand_keypair();
|
||||
let mixer_hop_excess = secp::random_secret();
|
||||
let (output_commit, proof) = secp::test_util::proof(
|
||||
let (output_commit, proof) = onion_test_util::proof(
|
||||
value,
|
||||
swap_fee + mixer_fee,
|
||||
&blind,
|
||||
&vec![&swap_hop_excess, &mixer_hop_excess],
|
||||
);
|
||||
let mixer_hop = test_util::new_hop(&mixer_sk, &mixer_hop_excess, mixer_fee, Some(proof));
|
||||
let mixer_hop = new_hop(&mixer_sk, &mixer_hop_excess, mixer_fee, Some(proof));
|
||||
|
||||
// Create onion
|
||||
let onion = test_util::create_onion(&input_commit, &vec![swap_hop, mixer_hop])?;
|
||||
let onion = create_onion(&input_commit, &vec![swap_hop, mixer_hop])?;
|
||||
let comsig = ComSignature::sign(value, &blind, &onion.serialize()?)?;
|
||||
|
||||
// Mock mixer
|
||||
|
@ -540,11 +540,11 @@ mod tests {
|
|||
let server_key = secp::random_secret();
|
||||
let hop_excess = secp::random_secret();
|
||||
let (_output_commit, proof) =
|
||||
secp::test_util::proof(value, fee, &blind, &vec![&hop_excess]);
|
||||
let hop = test_util::new_hop(&server_key, &hop_excess, fee, Some(proof));
|
||||
onion_test_util::proof(value, fee, &blind, &vec![&hop_excess]);
|
||||
let hop = new_hop(&server_key, &hop_excess, fee, Some(proof));
|
||||
|
||||
let hops: Vec<Hop> = vec![hop.clone(), hop.clone()]; // Multiple payloads
|
||||
let onion = test_util::create_onion(&input_commit, &hops)?;
|
||||
let onion = create_onion(&input_commit, &hops)?;
|
||||
let comsig = ComSignature::sign(value, &blind, &onion.serialize()?)?;
|
||||
|
||||
let node: Arc<MockGrinNode> = Arc::new(MockGrinNode::new_with_utxos(&vec![&input_commit]));
|
||||
|
@ -575,10 +575,10 @@ mod tests {
|
|||
let server_key = secp::random_secret();
|
||||
let hop_excess = secp::random_secret();
|
||||
let (_output_commit, proof) =
|
||||
secp::test_util::proof(value, fee, &blind, &vec![&hop_excess]);
|
||||
let hop = test_util::new_hop(&server_key, &hop_excess, fee, Some(proof));
|
||||
onion_test_util::proof(value, fee, &blind, &vec![&hop_excess]);
|
||||
let hop = new_hop(&server_key, &hop_excess, fee, Some(proof));
|
||||
|
||||
let onion = test_util::create_onion(&input_commit, &vec![hop])?;
|
||||
let onion = create_onion(&input_commit, &vec![hop])?;
|
||||
|
||||
let wrong_blind = secp::random_secret();
|
||||
let comsig = ComSignature::sign(value, &wrong_blind, &onion.serialize()?)?;
|
||||
|
@ -612,10 +612,10 @@ mod tests {
|
|||
let hop_excess = secp::random_secret();
|
||||
let wrong_value = value + 10_000_000;
|
||||
let (_output_commit, proof) =
|
||||
secp::test_util::proof(wrong_value, fee, &blind, &vec![&hop_excess]);
|
||||
let hop = test_util::new_hop(&server_key, &hop_excess, fee, Some(proof));
|
||||
onion_test_util::proof(wrong_value, fee, &blind, &vec![&hop_excess]);
|
||||
let hop = new_hop(&server_key, &hop_excess, fee, Some(proof));
|
||||
|
||||
let onion = test_util::create_onion(&input_commit, &vec![hop])?;
|
||||
let onion = create_onion(&input_commit, &vec![hop])?;
|
||||
let comsig = ComSignature::sign(value, &blind, &onion.serialize()?)?;
|
||||
|
||||
let node: Arc<MockGrinNode> = Arc::new(MockGrinNode::new_with_utxos(&vec![&input_commit]));
|
||||
|
@ -645,9 +645,9 @@ mod tests {
|
|||
|
||||
let server_key = secp::random_secret();
|
||||
let hop_excess = secp::random_secret();
|
||||
let hop = test_util::new_hop(&server_key, &hop_excess, fee, None);
|
||||
let hop = new_hop(&server_key, &hop_excess, fee, None);
|
||||
|
||||
let onion = test_util::create_onion(&input_commit, &vec![hop])?;
|
||||
let onion = create_onion(&input_commit, &vec![hop])?;
|
||||
let comsig = ComSignature::sign(value, &blind, &onion.serialize()?)?;
|
||||
|
||||
let node: Arc<MockGrinNode> = Arc::new(MockGrinNode::new_with_utxos(&vec![&input_commit]));
|
||||
|
@ -678,10 +678,10 @@ mod tests {
|
|||
let server_key = secp::random_secret();
|
||||
let hop_excess = secp::random_secret();
|
||||
let (_output_commit, proof) =
|
||||
secp::test_util::proof(value, fee, &blind, &vec![&hop_excess]);
|
||||
let hop = test_util::new_hop(&server_key, &hop_excess, fee, Some(proof));
|
||||
onion_test_util::proof(value, fee, &blind, &vec![&hop_excess]);
|
||||
let hop = new_hop(&server_key, &hop_excess, fee, Some(proof));
|
||||
|
||||
let onion = test_util::create_onion(&input_commit, &vec![hop])?;
|
||||
let onion = create_onion(&input_commit, &vec![hop])?;
|
||||
let comsig = ComSignature::sign(value, &blind, &onion.serialize()?)?;
|
||||
|
||||
let node: Arc<MockGrinNode> = Arc::new(MockGrinNode::new());
|
||||
|
@ -717,10 +717,10 @@ mod tests {
|
|||
let server_key = secp::random_secret();
|
||||
let hop_excess = secp::random_secret();
|
||||
let (_output_commit, proof) =
|
||||
secp::test_util::proof(value, fee, &blind, &vec![&hop_excess]);
|
||||
let hop = test_util::new_hop(&server_key, &hop_excess, fee, Some(proof));
|
||||
onion_test_util::proof(value, fee, &blind, &vec![&hop_excess]);
|
||||
let hop = new_hop(&server_key, &hop_excess, fee, Some(proof));
|
||||
|
||||
let onion = test_util::create_onion(&input_commit, &vec![hop])?;
|
||||
let onion = create_onion(&input_commit, &vec![hop])?;
|
||||
let comsig = ComSignature::sign(value, &blind, &onion.serialize()?)?;
|
||||
|
||||
let node: Arc<MockGrinNode> = Arc::new(MockGrinNode::new_with_utxos(&vec![&input_commit]));
|
||||
|
@ -753,12 +753,12 @@ mod tests {
|
|||
let server_key = secp::random_secret();
|
||||
let hop_excess = secp::random_secret();
|
||||
let (_output_commit, proof) =
|
||||
secp::test_util::proof(value, fee, &blind, &vec![&hop_excess]);
|
||||
onion_test_util::proof(value, fee, &blind, &vec![&hop_excess]);
|
||||
|
||||
let wrong_server_key = secp::random_secret();
|
||||
let hop = test_util::new_hop(&wrong_server_key, &hop_excess, fee, Some(proof));
|
||||
let hop = new_hop(&wrong_server_key, &hop_excess, fee, Some(proof));
|
||||
|
||||
let onion = test_util::create_onion(&input_commit, &vec![hop])?;
|
||||
let onion = create_onion(&input_commit, &vec![hop])?;
|
||||
let comsig = ComSignature::sign(value, &blind, &onion.serialize()?)?;
|
||||
|
||||
let node: Arc<MockGrinNode> = Arc::new(MockGrinNode::new_with_utxos(&vec![&input_commit]));
|
||||
|
@ -785,10 +785,10 @@ mod tests {
|
|||
let server_key = secp::random_secret();
|
||||
let hop_excess = secp::random_secret();
|
||||
let (_output_commit, proof) =
|
||||
secp::test_util::proof(value, fee, &blind, &vec![&hop_excess]);
|
||||
let hop = test_util::new_hop(&server_key, &hop_excess, fee, Some(proof));
|
||||
onion_test_util::proof(value, fee, &blind, &vec![&hop_excess]);
|
||||
let hop = new_hop(&server_key, &hop_excess, fee, Some(proof));
|
||||
|
||||
let onion = test_util::create_onion(&input_commit, &vec![hop])?;
|
||||
let onion = create_onion(&input_commit, &vec![hop])?;
|
||||
let comsig = ComSignature::sign(value, &blind, &onion.serialize()?)?;
|
||||
|
||||
let node: Arc<MockGrinNode> = Arc::new(MockGrinNode::new_with_utxos(&vec![&input_commit]));
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
use crate::client::MixClient;
|
||||
use crate::config::ServerConfig;
|
||||
use crate::crypto::comsig::{self, ComSignature};
|
||||
use crate::node::GrinNode;
|
||||
use crate::onion::Onion;
|
||||
use crate::servers::swap::{SwapError, SwapServer, SwapServerImpl};
|
||||
use crate::store::SwapStore;
|
||||
use crate::wallet::Wallet;
|
||||
|
||||
use crate::client::MixClient;
|
||||
use grin_onion::crypto::comsig::{self, ComSignature};
|
||||
use grin_onion::onion::Onion;
|
||||
use grin_util::StopState;
|
||||
use jsonrpc_core::Value;
|
||||
use jsonrpc_derive::rpc;
|
||||
|
@ -133,11 +133,11 @@ mod tests {
|
|||
use crate::config::ServerConfig;
|
||||
use crate::crypto::comsig::ComSignature;
|
||||
use crate::crypto::secp;
|
||||
use crate::onion::test_util;
|
||||
use crate::servers::swap::mock::MockSwapServer;
|
||||
use crate::servers::swap::{SwapError, SwapServer};
|
||||
use crate::servers::swap_rpc::{RPCSwapServer, SwapReq};
|
||||
|
||||
use grin_onion::create_onion;
|
||||
use std::net::TcpListener;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
|
@ -208,7 +208,7 @@ mod tests {
|
|||
#[test]
|
||||
fn swap_success() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let commitment = secp::commit(1234, &secp::random_secret())?;
|
||||
let onion = test_util::create_onion(&commitment, &vec![])?;
|
||||
let onion = create_onion(&commitment, &vec![])?;
|
||||
let comsig = ComSignature::sign(1234, &secp::random_secret(), &onion.serialize()?)?;
|
||||
let swap = SwapReq {
|
||||
onion: onion.clone(),
|
||||
|
@ -247,7 +247,7 @@ mod tests {
|
|||
#[test]
|
||||
fn swap_utxo_missing() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let commitment = secp::commit(1234, &secp::random_secret())?;
|
||||
let onion = test_util::create_onion(&commitment, &vec![])?;
|
||||
let onion = create_onion(&commitment, &vec![])?;
|
||||
let comsig = ComSignature::sign(1234, &secp::random_secret(), &onion.serialize()?)?;
|
||||
let swap = SwapReq {
|
||||
onion: onion.clone(),
|
||||
|
|
27
src/store.rs
27
src/store.rs
|
@ -1,7 +1,7 @@
|
|||
use crate::crypto::secp::{self, Commitment, RangeProof, SecretKey};
|
||||
use crate::onion::Onion;
|
||||
use crate::util::{read_optional, write_optional};
|
||||
use grin_core::core::hash::Hash;
|
||||
use grin_onion::crypto::secp::{self, Commitment, RangeProof, SecretKey};
|
||||
use grin_onion::onion::Onion;
|
||||
use grin_onion::util::{read_optional, write_optional};
|
||||
|
||||
use grin_core::core::Input;
|
||||
use grin_core::ser::{
|
||||
|
@ -244,13 +244,12 @@ impl SwapStore {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::crypto::secp;
|
||||
use crate::crypto::secp::test_util::{rand_commit, rand_hash, rand_proof};
|
||||
use crate::onion::test_util::rand_onion;
|
||||
use crate::store::{SwapData, SwapStatus, SwapStore};
|
||||
use crate::StoreError;
|
||||
use grin_core::core::{Input, OutputFeatures};
|
||||
use grin_core::global::{self, ChainTypes};
|
||||
use grin_onion::crypto::secp;
|
||||
use grin_onion::test_util as onion_test_util;
|
||||
use rand::RngCore;
|
||||
use std::cmp::Ordering;
|
||||
|
||||
|
@ -264,11 +263,11 @@ mod tests {
|
|||
fn rand_swap_with_status(status: SwapStatus) -> SwapData {
|
||||
SwapData {
|
||||
excess: secp::random_secret(),
|
||||
output_commit: rand_commit(),
|
||||
rangeproof: Some(rand_proof()),
|
||||
input: Input::new(OutputFeatures::Plain, rand_commit()),
|
||||
output_commit: onion_test_util::rand_commit(),
|
||||
rangeproof: Some(onion_test_util::rand_proof()),
|
||||
input: Input::new(OutputFeatures::Plain, onion_test_util::rand_commit()),
|
||||
fee: rand::thread_rng().next_u64(),
|
||||
onion: rand_onion(),
|
||||
onion: onion_test_util::rand_onion(),
|
||||
status,
|
||||
}
|
||||
}
|
||||
|
@ -279,12 +278,12 @@ mod tests {
|
|||
SwapStatus::Unprocessed
|
||||
} else if s == 1 {
|
||||
SwapStatus::InProcess {
|
||||
kernel_hash: rand_hash(),
|
||||
kernel_hash: onion_test_util::rand_hash(),
|
||||
}
|
||||
} else {
|
||||
SwapStatus::Completed {
|
||||
kernel_hash: rand_hash(),
|
||||
block_hash: rand_hash(),
|
||||
kernel_hash: onion_test_util::rand_hash(),
|
||||
block_hash: onion_test_util::rand_hash(),
|
||||
}
|
||||
};
|
||||
rand_swap_with_status(status)
|
||||
|
@ -331,7 +330,7 @@ mod tests {
|
|||
assert!(store.swap_exists(&swap.input.commit)?);
|
||||
|
||||
swap.status = SwapStatus::InProcess {
|
||||
kernel_hash: rand_hash(),
|
||||
kernel_hash: onion_test_util::rand_hash(),
|
||||
};
|
||||
let result = store.save_swap(&swap, false);
|
||||
assert_eq!(
|
||||
|
|
41
src/tx.rs
41
src/tx.rs
|
@ -167,6 +167,47 @@ fn add_kernel_and_collect_fees(
|
|||
})
|
||||
}
|
||||
|
||||
/// Builds a transaction kernel for the Grin network.
|
||||
///
|
||||
/// Transaction kernels are a critical part of the Grin transaction process. Each transaction contains a
|
||||
/// kernel. It includes features chosen for this transaction, a fee chosen for this transaction, and
|
||||
/// a proof that the total sum of outputs, transaction fees and block reward equals the total sum of inputs.
|
||||
/// The `build_kernel` function handles this process, building the kernel and handling any potential errors.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `excess`: A reference to a `SecretKey`. This key is used as an excess value for the transaction.
|
||||
/// The excess is a kind of cryptographic proof that the total sum of outputs and fees equals the
|
||||
/// total sum of inputs.
|
||||
/// * `fee`: An unsigned 64-bit integer representing the transaction fee in nanogrin. This is the fee
|
||||
/// that will be paid to the miner who mines the block containing this transaction.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// The function returns a `Result` enum with `TxKernel` as the Ok variant and `TxError` as the Err variant.
|
||||
/// If the kernel is successfully built, it is returned as part of the Ok variant. If there is an error at any point
|
||||
/// during the process, it is returned as part of the Err variant.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This function can return several types of errors, all defined in the `TxError` enum. These include:
|
||||
///
|
||||
/// * `KernelFeeError`: There was an error building the kernel's fee fields.
|
||||
/// * `KernelExcessError`: There was an error computing the kernel's excess.
|
||||
/// * `KernelSigMessageError`: There was an error computing the kernel's signature message.
|
||||
/// * `KernelSigError`: There was an error signing the kernel.
|
||||
/// * `KernelVerifyError`: The built kernel failed to verify.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use secp256k1zkp::key::SecretKey;
|
||||
/// use crate::crypto::secp;
|
||||
///
|
||||
/// let secret_key = SecretKey::new(&mut secp::rand::thread_rng());
|
||||
/// let fee = 10; // 10 nanogrin
|
||||
/// let kernel = build_kernel(&secret_key, fee);
|
||||
/// ```
|
||||
pub fn build_kernel(excess: &SecretKey, fee: u64) -> Result<TxKernel, TxError> {
|
||||
let mut kernel = TxKernel::with_features(KernelFeatures::Plain {
|
||||
fee: FeeFields::new(0, fee).map_err(TxError::KernelFeeError)?,
|
||||
|
|
Loading…
Reference in a new issue