Use upstreamed functionality for clsag and signature hash

This commit is contained in:
Thomas Eizinger 2021-05-14 11:15:36 +10:00
parent 04e7d1c111
commit 91f54bf6b5
No known key found for this signature in database
GPG Key ID: 651AC83A6C6C8B96
6 changed files with 80 additions and 575 deletions

4
Cargo.lock generated
View File

@ -2265,7 +2265,7 @@ dependencies = [
[[package]] [[package]]
name = "monero" name = "monero"
version = "0.12.0" version = "0.12.0"
source = "git+https://github.com/comit-network/monero-rs?branch=ecdh_recover_mask#103dc4d3353f46870c5a3405d27e961f4b195350" source = "git+https://github.com/comit-network/monero-rs?branch=clsag#4c3b87d562f4b4119eff2739894a91e8c6e5381d"
dependencies = [ dependencies = [
"base58-monero", "base58-monero",
"clear_on_drop", "clear_on_drop",
@ -2275,6 +2275,7 @@ dependencies = [
"hex 0.4.3", "hex 0.4.3",
"hex-literal", "hex-literal",
"integer-encoding", "integer-encoding",
"itertools 0.10.0",
"keccak-hash", "keccak-hash",
"lazy_static", "lazy_static",
"rand 0.7.3", "rand 0.7.3",
@ -2282,6 +2283,7 @@ dependencies = [
"serde-big-array", "serde-big-array",
"subtle 2.4.0", "subtle 2.4.0",
"thiserror", "thiserror",
"tiny-keccak",
] ]
[[package]] [[package]]

View File

@ -3,4 +3,4 @@ members = ["monero-adaptor", "monero-harness", "monero-rpc", "swap", "monero-wal
[patch.crates-io] [patch.crates-io]
torut = { git = "https://github.com/bonomat/torut/", branch = "feature-flag-tor-secret-keys", default-features = false, features = [ "v3", "control" ] } torut = { git = "https://github.com/bonomat/torut/", branch = "feature-flag-tor-secret-keys", default-features = false, features = [ "v3", "control" ] }
monero = { git = "https://github.com/comit-network/monero-rs", branch = "ecdh_recover_mask" } monero = { git = "https://github.com/comit-network/monero-rs", branch = "clsag" }

View File

@ -1,323 +0,0 @@
use curve25519_dalek::constants::ED25519_BASEPOINT_POINT;
use curve25519_dalek::edwards::EdwardsPoint;
use curve25519_dalek::scalar::Scalar;
use hash_edwards_to_edwards::hash_point_to_point;
use std::iter::{Cycle, Skip, Take};
pub const RING_SIZE: usize = 11;
const INV_EIGHT: Scalar = Scalar::from_bits([
121, 47, 220, 226, 41, 229, 6, 97, 208, 218, 28, 125, 179, 157, 211, 7, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 6,
]);
pub fn sign(
msg: &[u8; 32],
signing_key: Scalar,
signing_key_index: usize,
H_p_pk: EdwardsPoint,
alpha: Scalar,
ring: &[EdwardsPoint; RING_SIZE],
commitment_ring: &[EdwardsPoint; RING_SIZE],
fake_responses: [Scalar; RING_SIZE - 1],
z: Scalar,
pseudo_output_commitment: EdwardsPoint,
L: EdwardsPoint,
R: EdwardsPoint,
I: EdwardsPoint,
) -> Signature {
let D = z * H_p_pk;
let D_inv_8 = D * INV_EIGHT;
let mu_P = hash_to_scalar!(
b"CLSAG_agg_0" || ring || commitment_ring || I || D_inv_8 || pseudo_output_commitment
);
let mu_C = hash_to_scalar!(
b"CLSAG_agg_1" || ring || commitment_ring || I || D_inv_8 || pseudo_output_commitment
);
let adjusted_commitment_ring = commitment_ring.map(|point| point - pseudo_output_commitment);
let compute_ring_element = |L: EdwardsPoint, R: EdwardsPoint| {
hash_to_scalar!(
b"CLSAG_round" || ring || commitment_ring || pseudo_output_commitment || msg || L || R
)
};
let h_signing_index = compute_ring_element(L, R);
let mut h_prev = h_signing_index;
let mut i = (signing_key_index + 1) % RING_SIZE;
let mut h_0 = Scalar::zero();
if i == 0 {
h_0 = h_signing_index
}
let mut responses = [Scalar::zero(); 11];
while i != signing_key_index {
let s_i = fake_responses[i % 10];
responses[i] = s_i;
let L_i = compute_L(
h_prev,
mu_P,
mu_C,
s_i,
ring[i],
adjusted_commitment_ring[i],
);
let R_i = compute_R(h_prev, mu_P, mu_C, s_i, ring[i], I, D);
let h = compute_ring_element(L_i, R_i);
i = (i + 1) % RING_SIZE;
if i == 0 {
h_0 = h
}
h_prev = h
}
responses[signing_key_index] = alpha - h_prev * ((mu_P * signing_key) + (mu_C * z));
Signature {
responses,
h_0,
I,
D: D_inv_8,
}
}
#[must_use]
pub fn verify(
&Signature {
I,
h_0,
D: D_inv_8,
responses,
..
}: &Signature,
msg: &[u8; 32],
ring: &[EdwardsPoint; RING_SIZE],
commitment_ring: &[EdwardsPoint; RING_SIZE],
pseudo_output_commitment: EdwardsPoint,
) -> bool {
let D = D_inv_8 * Scalar::from(8u8);
let mu_P = hash_to_scalar!(
b"CLSAG_agg_0" || ring || commitment_ring || I || D_inv_8 || pseudo_output_commitment
);
let mu_C = hash_to_scalar!(
b"CLSAG_agg_1" || ring || commitment_ring || I || D_inv_8 || pseudo_output_commitment
);
let adjusted_commitment_ring = commitment_ring.map(|point| point - pseudo_output_commitment);
let h_0_computed = itertools::izip!(responses, ring, adjusted_commitment_ring).fold(
h_0,
|h, (s_i, pk_i, adjusted_commitment_i)| {
let L_i = compute_L(h, mu_P, mu_C, s_i, *pk_i, adjusted_commitment_i);
let R_i = compute_R(h, mu_P, mu_C, s_i, *pk_i, I, D);
hash_to_scalar!(
b"CLSAG_round"
|| ring
|| commitment_ring
|| pseudo_output_commitment
|| msg
|| L_i
|| R_i
)
},
);
h_0_computed == h_0
}
#[derive(Clone, Debug, PartialEq)]
pub struct Signature {
pub responses: [Scalar; RING_SIZE],
pub h_0: Scalar,
/// Key image of the real key in the ring.
pub I: EdwardsPoint,
pub D: EdwardsPoint,
}
// L_i = s_i * G + c_p * pk_i + c_c * (commitment_i - pseudoutcommitment)
fn compute_L(
h_prev: Scalar,
mu_P: Scalar,
mu_C: Scalar,
s_i: Scalar,
pk_i: EdwardsPoint,
adjusted_commitment_i: EdwardsPoint,
) -> EdwardsPoint {
let c_p = h_prev * mu_P;
let c_c = h_prev * mu_C;
(s_i * ED25519_BASEPOINT_POINT) + (c_p * pk_i) + c_c * adjusted_commitment_i
}
// R_i = s_i * H_p_pk_i + c_p * I + c_c * (z * hash_to_point(signing pk))
fn compute_R(
h_prev: Scalar,
mu_P: Scalar,
mu_C: Scalar,
s_i: Scalar,
pk_i: EdwardsPoint,
I: EdwardsPoint,
D: EdwardsPoint,
) -> EdwardsPoint {
let c_p = h_prev * mu_P;
let c_c = h_prev * mu_C;
let H_p_pk_i = hash_point_to_point(pk_i);
(s_i * H_p_pk_i) + (c_p * I) + c_c * D
}
impl From<Signature> for monero::util::ringct::Clsag {
fn from(from: Signature) -> Self {
Self {
s: from
.responses
.iter()
.map(|s| monero::util::ringct::Key { key: s.to_bytes() })
.collect(),
c1: monero::util::ringct::Key {
key: from.h_0.to_bytes(),
},
D: monero::util::ringct::Key {
key: from.D.compress().to_bytes(),
},
}
}
}
trait IteratorExt {
fn shift_by(self, num: usize) -> ShiftBy<Self>
where
Self: ExactSizeIterator + Sized + Clone,
{
let length = self.len();
ShiftBy::new(self, num, length)
}
}
struct ShiftBy<I> {
inner: Take<Skip<Cycle<I>>>,
}
impl<I: Iterator + Clone> ShiftBy<I> {
fn new(iter: I, num: usize, length: usize) -> Self {
Self {
inner: iter.cycle().skip(num).take(length),
}
}
}
impl<I> IteratorExt for I where I: ExactSizeIterator {}
impl<I> Iterator for ShiftBy<I>
where
I: Iterator + Clone,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}
}
#[cfg(test)]
mod tests {
use super::*;
use monero::util::key::H;
use rand::SeedableRng;
#[test]
fn test_shift_by() {
let array = ["a", "b", "c", "d", "e"];
let shifted = array.iter().copied().shift_by(2).collect::<Vec<_>>();
assert_eq!(shifted, vec!["c", "d", "e", "a", "b"])
}
#[test]
fn const_is_inv_eight() {
let inv_eight = Scalar::from(8u8).invert();
assert_eq!(inv_eight, INV_EIGHT);
}
#[test]
fn sign_and_verify_at_every_index() {
for signing_key_index in 0..11 {
let mut rng = rand::rngs::StdRng::from_seed([0u8; 32]);
let msg_to_sign = b"hello world, monero is amazing!!";
let signing_key = Scalar::random(&mut rng);
let signing_pk = signing_key * ED25519_BASEPOINT_POINT;
let H_p_pk = hash_point_to_point(signing_pk);
let alpha = Scalar::random(&mut rng);
let amount_to_spend = 1000000u32;
let fee = 10000u32;
let output_amount = amount_to_spend - fee;
let mut ring = random_array(|| Scalar::random(&mut rng) * ED25519_BASEPOINT_POINT);
ring[signing_key_index] = signing_pk;
let real_commitment_blinding = Scalar::random(&mut rng);
let mut commitment_ring =
random_array(|| Scalar::random(&mut rng) * ED25519_BASEPOINT_POINT);
commitment_ring[signing_key_index] = real_commitment_blinding * ED25519_BASEPOINT_POINT
+ Scalar::from(amount_to_spend) * H.point.decompress().unwrap();
let fee_key = Scalar::from(fee) * H.point.decompress().unwrap();
let out_pk_blinding = Scalar::random(&mut rng);
let out_pk = out_pk_blinding * ED25519_BASEPOINT_POINT
+ Scalar::from(output_amount) * H.point.decompress().unwrap();
let pseudo_output_commitment = fee_key + out_pk;
let signature = sign(
msg_to_sign,
signing_key,
signing_key_index,
H_p_pk,
alpha,
&ring,
&commitment_ring,
random_array(|| Scalar::random(&mut rng)),
real_commitment_blinding - out_pk_blinding,
pseudo_output_commitment,
alpha * ED25519_BASEPOINT_POINT,
alpha * H_p_pk,
signing_key * H_p_pk,
);
assert!(verify(
&signature,
msg_to_sign,
&ring,
&commitment_ring,
pseudo_output_commitment
))
}
}
fn random_array<T: Default + Copy, const N: usize>(rng: impl FnMut() -> T) -> [T; N] {
let mut ring = [T::default(); N];
ring[..].fill_with(rng);
ring
}
}

View File

@ -1,4 +1,3 @@
#![feature(array_map)]
#![allow(non_snake_case)] #![allow(non_snake_case)]
#![allow(non_upper_case_globals)] #![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)] #![allow(non_camel_case_types)]
@ -14,15 +13,11 @@ use hash_edwards_to_edwards::hash_point_to_point;
use rand::{CryptoRng, Rng}; use rand::{CryptoRng, Rng};
use tiny_keccak::{Hasher, Keccak}; use tiny_keccak::{Hasher, Keccak};
use clsag::{Signature, RING_SIZE}; use monero::util::ringct::Clsag;
#[macro_use]
mod macros;
pub mod clsag;
pub struct AdaptorSignature { pub struct AdaptorSignature {
s_0: Scalar, s_0: Scalar,
fake_responses: [Scalar; RING_SIZE - 1], fake_responses: [Scalar; 10],
h_0: Scalar, h_0: Scalar,
/// Key image of the real key in the ring. /// Key image of the real key in the ring.
I: EdwardsPoint, I: EdwardsPoint,
@ -32,7 +27,7 @@ pub struct AdaptorSignature {
pub struct HalfAdaptorSignature { pub struct HalfAdaptorSignature {
s_0_half: Scalar, s_0_half: Scalar,
fake_responses: [Scalar; RING_SIZE - 1], fake_responses: [Scalar; 10],
h_0: Scalar, h_0: Scalar,
/// Key image of the real key in the ring. /// Key image of the real key in the ring.
I: EdwardsPoint, I: EdwardsPoint,
@ -53,10 +48,10 @@ impl HalfAdaptorSignature {
} }
impl AdaptorSignature { impl AdaptorSignature {
pub fn adapt(self, y: Scalar) -> Signature { pub fn adapt(self, y: Scalar) -> Clsag {
let r_last = self.s_0 + y; let r_last = self.s_0 + y;
let responses = self let _responses: [Scalar; 11] = self
.fake_responses .fake_responses
.iter() .iter()
.chain([r_last].iter()) .chain([r_last].iter())
@ -65,20 +60,21 @@ impl AdaptorSignature {
.try_into() .try_into()
.expect("correct response size"); .expect("correct response size");
Signature { todo!()
responses, // Signature {
h_0: self.h_0, // responses,
I: self.I, // h_0: self.h_0,
D: self.D, // I: self.I,
} // D: self.D,
// }
} }
} }
pub struct Alice0 { pub struct Alice0 {
// secret index is always 0 // secret index is always 0
ring: [EdwardsPoint; RING_SIZE], ring: [EdwardsPoint; 11],
fake_responses: [Scalar; RING_SIZE - 1], fake_responses: [Scalar; 10],
commitment_ring: [EdwardsPoint; RING_SIZE], commitment_ring: [EdwardsPoint; 11],
pseudo_output_commitment: EdwardsPoint, pseudo_output_commitment: EdwardsPoint,
msg: [u8; 32], msg: [u8; 32],
// encryption key // encryption key
@ -97,17 +93,17 @@ pub struct Alice0 {
impl Alice0 { impl Alice0 {
pub fn new( pub fn new(
ring: [EdwardsPoint; RING_SIZE], ring: [EdwardsPoint; 11],
msg: [u8; 32], msg: [u8; 32],
commitment_ring: [EdwardsPoint; RING_SIZE], commitment_ring: [EdwardsPoint; 11],
pseudo_output_commitment: EdwardsPoint, pseudo_output_commitment: EdwardsPoint,
R_a: EdwardsPoint, R_a: EdwardsPoint,
R_prime_a: EdwardsPoint, R_prime_a: EdwardsPoint,
s_prime_a: Scalar, s_prime_a: Scalar,
rng: &mut (impl Rng + CryptoRng), rng: &mut (impl Rng + CryptoRng),
) -> Result<Self> { ) -> Result<Self> {
let mut fake_responses = [Scalar::zero(); RING_SIZE - 1]; let mut fake_responses = [Scalar::zero(); 10];
for response in fake_responses.iter_mut().take(RING_SIZE - 1) { for response in fake_responses.iter_mut().take(10) {
*response = Scalar::random(rng); *response = Scalar::random(rng);
} }
let alpha_a = Scalar::random(rng); let alpha_a = Scalar::random(rng);
@ -155,7 +151,8 @@ impl Alice0 {
msg.pi_b msg.pi_b
.verify(ED25519_BASEPOINT_POINT, msg.T_b, self.H_p_pk, msg.I_hat_b)?; .verify(ED25519_BASEPOINT_POINT, msg.T_b, self.H_p_pk, msg.I_hat_b)?;
let sig = clsag::sign( let I = self.I_a + msg.I_b;
let sig = monero::clsag::sign(
&self.msg, &self.msg,
self.s_prime_a, self.s_prime_a,
0, 0,
@ -168,15 +165,15 @@ impl Alice0 {
self.pseudo_output_commitment, self.pseudo_output_commitment,
self.T_a + msg.T_b + self.R_a, self.T_a + msg.T_b + self.R_a,
self.I_hat_a + msg.I_hat_b + self.R_prime_a, self.I_hat_a + msg.I_hat_b + self.R_prime_a,
self.I_a + msg.I_b, I,
); );
let sig = HalfAdaptorSignature { let sig = HalfAdaptorSignature {
s_0_half: sig.responses[10], s_0_half: todo!(),
fake_responses: self.fake_responses, fake_responses: self.fake_responses,
h_0: sig.h_0, h_0: todo!(),
I: sig.I, I,
D: sig.D, D: todo!(),
}; };
Ok(Alice1 { Ok(Alice1 {
@ -190,7 +187,7 @@ impl Alice0 {
} }
pub struct Alice1 { pub struct Alice1 {
fake_responses: [Scalar; RING_SIZE - 1], fake_responses: [Scalar; 10],
I_a: EdwardsPoint, I_a: EdwardsPoint,
I_hat_a: EdwardsPoint, I_hat_a: EdwardsPoint,
T_a: EdwardsPoint, T_a: EdwardsPoint,
@ -217,9 +214,9 @@ pub struct Alice2 {
} }
pub struct Bob0 { pub struct Bob0 {
ring: [EdwardsPoint; RING_SIZE], ring: [EdwardsPoint; 11],
msg: [u8; 32], msg: [u8; 32],
commitment_ring: [EdwardsPoint; RING_SIZE], commitment_ring: [EdwardsPoint; 11],
pseudo_output_commitment: EdwardsPoint, pseudo_output_commitment: EdwardsPoint,
R_a: EdwardsPoint, R_a: EdwardsPoint,
R_prime_a: EdwardsPoint, R_prime_a: EdwardsPoint,
@ -233,9 +230,9 @@ pub struct Bob0 {
impl Bob0 { impl Bob0 {
pub fn new( pub fn new(
ring: [EdwardsPoint; RING_SIZE], ring: [EdwardsPoint; 11],
msg: [u8; 32], msg: [u8; 32],
commitment_ring: [EdwardsPoint; RING_SIZE], commitment_ring: [EdwardsPoint; 11],
pseudo_output_commitment: EdwardsPoint, pseudo_output_commitment: EdwardsPoint,
R_a: EdwardsPoint, R_a: EdwardsPoint,
R_prime_a: EdwardsPoint, R_prime_a: EdwardsPoint,
@ -288,9 +285,9 @@ impl Bob0 {
} }
pub struct Bob1 { pub struct Bob1 {
ring: [EdwardsPoint; RING_SIZE], ring: [EdwardsPoint; 11],
msg: [u8; 32], msg: [u8; 32],
commitment_ring: [EdwardsPoint; RING_SIZE], commitment_ring: [EdwardsPoint; 11],
pseudo_output_commitment: EdwardsPoint, pseudo_output_commitment: EdwardsPoint,
R_a: EdwardsPoint, R_a: EdwardsPoint,
R_prime_a: EdwardsPoint, R_prime_a: EdwardsPoint,
@ -329,7 +326,7 @@ impl Bob1 {
.verify(ED25519_BASEPOINT_POINT, T_a, self.H_p_pk, I_hat_a)?; .verify(ED25519_BASEPOINT_POINT, T_a, self.H_p_pk, I_hat_a)?;
let I = I_a + self.I_b; let I = I_a + self.I_b;
let sig = clsag::sign( let sig = monero::clsag::sign(
&self.msg, &self.msg,
self.s_b, self.s_b,
0, 0,
@ -345,13 +342,13 @@ impl Bob1 {
I, I,
); );
let s_0_b = sig.responses[10]; let s_0_b = todo!();
let sig = HalfAdaptorSignature { let sig = HalfAdaptorSignature {
s_0_half: s_0_b, s_0_half: s_0_b,
fake_responses, fake_responses,
h_0: sig.h_0, h_0: todo!(),
I: sig.I, I,
D: sig.D, D: todo!(),
}; };
let adaptor_sig = sig.complete(msg.s_0_a); let adaptor_sig = sig.complete(msg.s_0_a);
@ -445,7 +442,7 @@ struct Commitment([u8; 32]);
impl Commitment { impl Commitment {
fn new( fn new(
fake_responses: [Scalar; RING_SIZE - 1], fake_responses: [Scalar; 10],
I_a: EdwardsPoint, I_a: EdwardsPoint,
I_hat_a: EdwardsPoint, I_hat_a: EdwardsPoint,
T_a: EdwardsPoint, T_a: EdwardsPoint,
@ -469,7 +466,7 @@ impl Commitment {
} }
struct Opening { struct Opening {
fake_responses: [Scalar; RING_SIZE - 1], fake_responses: [Scalar; 10],
I_a: EdwardsPoint, I_a: EdwardsPoint,
I_hat_a: EdwardsPoint, I_hat_a: EdwardsPoint,
T_a: EdwardsPoint, T_a: EdwardsPoint,
@ -477,7 +474,7 @@ struct Opening {
impl Opening { impl Opening {
fn new( fn new(
fake_responses: [Scalar; RING_SIZE - 1], fake_responses: [Scalar; 10],
I_a: EdwardsPoint, I_a: EdwardsPoint,
I_hat_a: EdwardsPoint, I_hat_a: EdwardsPoint,
T_a: EdwardsPoint, T_a: EdwardsPoint,
@ -493,12 +490,7 @@ impl Opening {
fn open( fn open(
self, self,
commitment: Commitment, commitment: Commitment,
) -> Result<( ) -> Result<([Scalar; 10], EdwardsPoint, EdwardsPoint, EdwardsPoint)> {
[Scalar; RING_SIZE - 1],
EdwardsPoint,
EdwardsPoint,
EdwardsPoint,
)> {
let self_commitment = let self_commitment =
Commitment::new(self.fake_responses, self.I_a, self.I_hat_a, self.T_a); Commitment::new(self.fake_responses, self.I_a, self.I_hat_a, self.T_a);
@ -562,7 +554,7 @@ mod tests {
(r_a, R_a, R_prime_a) (r_a, R_a, R_prime_a)
}; };
let mut ring = [EdwardsPoint::default(); RING_SIZE]; let mut ring = [EdwardsPoint::default(); 11];
ring[0] = pk; ring[0] = pk;
ring[1..].fill_with(|| { ring[1..].fill_with(|| {
@ -570,7 +562,7 @@ mod tests {
x * ED25519_BASEPOINT_POINT x * ED25519_BASEPOINT_POINT
}); });
let mut commitment_ring = [EdwardsPoint::default(); RING_SIZE]; let mut commitment_ring = [EdwardsPoint::default(); 11];
let real_commitment_blinding = Scalar::random(&mut OsRng); let real_commitment_blinding = Scalar::random(&mut OsRng);
commitment_ring[0] = real_commitment_blinding * ED25519_BASEPOINT_POINT; // + 0 * H commitment_ring[0] = real_commitment_blinding * ED25519_BASEPOINT_POINT; // + 0 * H
@ -618,13 +610,15 @@ mod tests {
let msg = bob.next_message(); let msg = bob.next_message();
let alice = alice.receive(msg); let alice = alice.receive(msg);
let I = alice.adaptor_sig.I;
let sig = alice.adaptor_sig.adapt(r_a); let sig = alice.adaptor_sig.adapt(r_a);
assert!(clsag::verify( assert!(monero::clsag::verify(
&sig, &sig,
msg_to_sign, msg_to_sign,
&ring, &ring,
&commitment_ring, &commitment_ring,
I,
pseudo_output_commitment, pseudo_output_commitment,
)); ));
} }

View File

@ -1,77 +0,0 @@
use curve25519_dalek::edwards::{CompressedEdwardsY, EdwardsPoint};
use std::borrow::Cow;
macro_rules! hash_to_scalar {
($($e:tt) || +) => {
{
use crate::macros::ToCowBytes as _;
use tiny_keccak::Hasher as _;
let mut hasher = tiny_keccak::Keccak::v256();
$(
let bytes_vec = $e.to_cow_bytes();
for el in bytes_vec {
hasher.update(el.as_ref());
}
)+
let mut hash = [0u8; 32];
hasher.finalize(&mut hash);
Scalar::from_bytes_mod_order(hash)
}
};
}
type CowBytes<'a> = Cow<'a, [u8; 32]>;
pub(crate) trait ToCowBytes {
fn to_cow_bytes(&self) -> Vec<CowBytes<'_>>;
}
impl ToCowBytes for CompressedEdwardsY {
fn to_cow_bytes(&self) -> Vec<CowBytes<'_>> {
vec![CowBytes::Borrowed(&self.0)]
}
}
impl ToCowBytes for EdwardsPoint {
fn to_cow_bytes(&self) -> Vec<CowBytes<'_>> {
vec![CowBytes::Owned(self.compress().0)]
}
}
impl ToCowBytes for [u8; 32] {
fn to_cow_bytes(&self) -> Vec<CowBytes<'_>> {
vec![CowBytes::Borrowed(&self)]
}
}
impl ToCowBytes for [u8; 11] {
fn to_cow_bytes(&self) -> Vec<CowBytes<'_>> {
let mut bytes = [0u8; 32];
bytes[0..11].copy_from_slice(self);
vec![CowBytes::Owned(bytes)]
}
}
impl<'a> ToCowBytes for [EdwardsPoint; 11] {
fn to_cow_bytes(&self) -> Vec<CowBytes<'_>> {
vec![
CowBytes::Owned(self[0].compress().0),
CowBytes::Owned(self[1].compress().0),
CowBytes::Owned(self[2].compress().0),
CowBytes::Owned(self[3].compress().0),
CowBytes::Owned(self[4].compress().0),
CowBytes::Owned(self[5].compress().0),
CowBytes::Owned(self[6].compress().0),
CowBytes::Owned(self[7].compress().0),
CowBytes::Owned(self[8].compress().0),
CowBytes::Owned(self[9].compress().0),
CowBytes::Owned(self[10].compress().0),
]
}
}

View File

@ -6,7 +6,6 @@ use curve25519_dalek::scalar::Scalar;
use hash_edwards_to_edwards::hash_point_to_point; use hash_edwards_to_edwards::hash_point_to_point;
use itertools::{izip, Itertools}; use itertools::{izip, Itertools};
use monero::blockdata::transaction::{ExtraField, KeyImage, SubField, TxOutTarget}; use monero::blockdata::transaction::{ExtraField, KeyImage, SubField, TxOutTarget};
use monero::cryptonote::hash::Hashable;
use monero::cryptonote::onetime_key::{KeyGenerator, MONERO_MUL_FACTOR}; use monero::cryptonote::onetime_key::{KeyGenerator, MONERO_MUL_FACTOR};
use monero::util::key::H; use monero::util::key::H;
use monero::util::ringct::{EcdhInfo, RctSig, RctSigBase, RctSigPrunable, RctType}; use monero::util::ringct::{EcdhInfo, RctSig, RctSigBase, RctSigPrunable, RctType};
@ -20,7 +19,6 @@ use rand::{Rng, SeedableRng};
use std::convert::TryInto; use std::convert::TryInto;
use std::iter; use std::iter;
use testcontainers::clients::Cli; use testcontainers::clients::Cli;
use tiny_keccak::{Hasher, Keccak};
#[tokio::test] #[tokio::test]
async fn monerod_integration_test() { async fn monerod_integration_test() {
@ -42,7 +40,7 @@ async fn monerod_integration_test() {
let lock_address = monero::Address::from_keypair(monero::Network::Mainnet, &lock_kp); let lock_address = monero::Address::from_keypair(monero::Network::Mainnet, &lock_kp);
dbg!(lock_address.to_string()); // 45BcRKAHaA4b5A9SdamF2f1w7zk1mKkBPhaqVoDWzuAtMoSAytzm5A6b2fE6ruupkAFmStrQzdojUExt96mR3oiiSKp8Exf dbg!(lock_address.to_string());
monero.init_miner().await.unwrap(); monero.init_miner().await.unwrap();
let wallet = monero.wallet("miner").expect("wallet to exist"); let wallet = monero.wallet("miner").expect("wallet to exist");
@ -245,62 +243,33 @@ async fn monerod_integration_test() {
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let rct_sig_base = RctSigBase { let mut transaction = Transaction {
rct_type: RctType::Clsag, prefix,
txn_fee: VarInt(fee), signatures: Vec::new(),
pseudo_outs: Vec::new(), rct_signatures: RctSig {
ecdh_info: vec![ecdh_info_0, ecdh_info_1], sig: Some(RctSigBase {
out_pk, rct_type: RctType::Clsag,
txn_fee: VarInt(fee),
pseudo_outs: Vec::new(),
ecdh_info: vec![ecdh_info_0, ecdh_info_1],
out_pk,
}),
p: Some(RctSigPrunable {
range_sigs: Vec::new(),
bulletproofs: vec![bulletproof],
MGs: Vec::new(),
Clsags: Vec::new(),
pseudo_outs: vec![monero::util::ringct::Key {
key: pseudo_out.compress().0,
}],
}),
},
}; };
let message = { let message = transaction.signature_hash().unwrap();
let tx_prefix_hash = prefix.hash().to_bytes();
let mut rct_sig_base_hash = [0u8; 32]; let sig = monero::clsag::sign(
let mut keccak = Keccak::v256(); message.as_fixed_bytes(),
keccak.update(&monero::consensus::serialize(&rct_sig_base));
keccak.finalize(&mut rct_sig_base_hash);
let bp_hash = {
let mut keccak = Keccak::v256();
keccak.update(&bulletproof.A.key);
keccak.update(&bulletproof.S.key);
keccak.update(&bulletproof.T1.key);
keccak.update(&bulletproof.T2.key);
keccak.update(&bulletproof.taux.key);
keccak.update(&bulletproof.mu.key);
for i in &bulletproof.L {
keccak.update(&i.key);
}
for i in &bulletproof.R {
keccak.update(&i.key);
}
keccak.update(&bulletproof.a.key);
keccak.update(&bulletproof.b.key);
keccak.update(&bulletproof.t.key);
let mut hash = [0u8; 32];
keccak.finalize(&mut hash);
hash
};
let mut keccak = Keccak::v256();
keccak.update(&tx_prefix_hash);
keccak.update(&rct_sig_base_hash);
keccak.update(&bp_hash);
let mut hash = [0u8; 32];
keccak.finalize(&mut hash);
hash
};
let sig = monero_adaptor::clsag::sign(
&message,
actual_signing_key, actual_signing_key,
signing_index, signing_index,
H_p_pk, H_p_pk,
@ -314,75 +283,15 @@ async fn monerod_integration_test() {
alpha * H_p_pk, alpha * H_p_pk,
I, I,
); );
assert!(monero_adaptor::clsag::verify( assert!(monero::clsag::verify(
&sig, &sig,
&message, message.as_fixed_bytes(),
&ring, &ring,
&commitment_ring, &commitment_ring,
I,
pseudo_out pseudo_out
)); ));
transaction.rct_signatures.p.as_mut().unwrap().Clsags.push(sig);
sig.responses.iter().enumerate().for_each(|(i, res)| {
println!(
r#"epee::string_tools::hex_to_pod("{}", clsag.s[{}]);"#,
hex::encode(res.as_bytes()),
i
);
});
println!(
r#"epee::string_tools::hex_to_pod("{}", clsag.c1);"#,
hex::encode(sig.h_0.as_bytes())
);
println!(
r#"epee::string_tools::hex_to_pod("{}", clsag.D);"#,
hex::encode(sig.D.compress().as_bytes())
);
println!(
r#"epee::string_tools::hex_to_pod("{}", clsag.I);"#,
hex::encode(sig.I.compress().to_bytes())
);
println!(
r#"epee::string_tools::hex_to_pod("{}", msg);"#,
hex::encode(&message)
);
ring.iter()
.zip(commitment_ring.iter())
.enumerate()
.for_each(|(i, (pk, c))| {
println!(
r#"epee::string_tools::hex_to_pod("{}", pubs[{}].dest);"#,
hex::encode(&pk.compress().to_bytes()),
i
);
println!(
r#"epee::string_tools::hex_to_pod("{}", pubs[{}].mask);"#,
hex::encode(&c.compress().to_bytes()),
i
);
});
println!(
r#"epee::string_tools::hex_to_pod("{}", Cout);"#,
hex::encode(pseudo_out.compress().to_bytes())
);
let transaction = Transaction {
prefix,
signatures: Vec::new(),
rct_signatures: RctSig {
sig: Some(rct_sig_base),
p: Some(RctSigPrunable {
range_sigs: Vec::new(),
bulletproofs: vec![bulletproof],
MGs: Vec::new(),
Clsags: vec![sig.into()],
pseudo_outs: vec![monero::util::ringct::Key {
key: pseudo_out.compress().0,
}],
}),
},
};
client.send_raw_transaction(transaction).await.unwrap(); client.send_raw_transaction(transaction).await.unwrap();
} }