mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-02-22 07:39:56 -05:00
Restructure workspace so monero-adaptor only contains the protocol
This commit is contained in:
parent
1447242fa6
commit
0c0acaad9e
8
Cargo.lock
generated
8
Cargo.lock
generated
@ -2333,17 +2333,9 @@ dependencies = [
|
|||||||
"anyhow",
|
"anyhow",
|
||||||
"curve25519-dalek",
|
"curve25519-dalek",
|
||||||
"hash_edwards_to_edwards",
|
"hash_edwards_to_edwards",
|
||||||
"hex 0.4.3",
|
|
||||||
"hex-literal",
|
|
||||||
"itertools 0.10.0",
|
|
||||||
"monero",
|
"monero",
|
||||||
"monero-harness",
|
|
||||||
"monero-rpc",
|
|
||||||
"monero-wallet",
|
|
||||||
"rand 0.7.3",
|
"rand 0.7.3",
|
||||||
"testcontainers 0.12.0",
|
|
||||||
"tiny-keccak",
|
"tiny-keccak",
|
||||||
"tokio",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -11,15 +11,3 @@ rand = "0.7"
|
|||||||
tiny-keccak = { version = "2", features = ["keccak"] }
|
tiny-keccak = { version = "2", features = ["keccak"] }
|
||||||
hash_edwards_to_edwards = { git = "https://github.com/comit-network/hash_edwards_to_edwards" }
|
hash_edwards_to_edwards = { git = "https://github.com/comit-network/hash_edwards_to_edwards" }
|
||||||
monero = "0.12"
|
monero = "0.12"
|
||||||
hex = "0.4"
|
|
||||||
itertools = "0.10"
|
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
hex = "0.4"
|
|
||||||
hex-literal = "0.3"
|
|
||||||
monero-harness = { path = "../monero-harness" }
|
|
||||||
monero-rpc = { path = "../monero-rpc" }
|
|
||||||
monero-wallet = { path = "../monero-wallet" }
|
|
||||||
testcontainers = "0.12"
|
|
||||||
tokio = { version = "1", features = ["full"] }
|
|
||||||
itertools = "0.10"
|
|
||||||
|
159
monero-adaptor/src/alice.rs
Normal file
159
monero-adaptor/src/alice.rs
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
use crate::commitment::{Commitment, Opening};
|
||||||
|
use crate::dleq_proof::DleqProof;
|
||||||
|
use crate::messages::{Message0, Message1, Message2, Message3};
|
||||||
|
use crate::{AdaptorSignature, HalfAdaptorSignature};
|
||||||
|
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 rand::{CryptoRng, Rng};
|
||||||
|
|
||||||
|
pub struct Alice0 {
|
||||||
|
// secret index is always 0
|
||||||
|
ring: [EdwardsPoint; 11],
|
||||||
|
fake_responses: [Scalar; 10],
|
||||||
|
commitment_ring: [EdwardsPoint; 11],
|
||||||
|
pseudo_output_commitment: EdwardsPoint,
|
||||||
|
msg: [u8; 32],
|
||||||
|
// encryption key
|
||||||
|
R_a: EdwardsPoint,
|
||||||
|
// R'a = r_a*H_p(p_k) where p_k is the signing public key
|
||||||
|
R_prime_a: EdwardsPoint,
|
||||||
|
// this is not s_a cos of something to with one-time-address??
|
||||||
|
s_prime_a: Scalar,
|
||||||
|
// secret value:
|
||||||
|
alpha_a: Scalar,
|
||||||
|
H_p_pk: EdwardsPoint,
|
||||||
|
I_a: EdwardsPoint,
|
||||||
|
I_hat_a: EdwardsPoint,
|
||||||
|
T_a: EdwardsPoint,
|
||||||
|
z: Scalar,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Alice0 {
|
||||||
|
pub fn new(
|
||||||
|
ring: [EdwardsPoint; 11],
|
||||||
|
msg: [u8; 32],
|
||||||
|
commitment_ring: [EdwardsPoint; 11],
|
||||||
|
pseudo_output_commitment: EdwardsPoint,
|
||||||
|
R_a: EdwardsPoint,
|
||||||
|
R_prime_a: EdwardsPoint,
|
||||||
|
s_prime_a: Scalar,
|
||||||
|
z: Scalar,
|
||||||
|
rng: &mut (impl Rng + CryptoRng),
|
||||||
|
) -> anyhow::Result<Self> {
|
||||||
|
let mut fake_responses = [Scalar::zero(); 10];
|
||||||
|
for response in fake_responses.iter_mut().take(10) {
|
||||||
|
*response = Scalar::random(rng);
|
||||||
|
}
|
||||||
|
let alpha_a = Scalar::random(rng);
|
||||||
|
|
||||||
|
let p_k = ring[0];
|
||||||
|
let H_p_pk = hash_point_to_point(p_k);
|
||||||
|
|
||||||
|
let I_a = s_prime_a * H_p_pk;
|
||||||
|
let I_hat_a = alpha_a * H_p_pk;
|
||||||
|
let T_a = alpha_a * ED25519_BASEPOINT_POINT;
|
||||||
|
|
||||||
|
Ok(Alice0 {
|
||||||
|
ring,
|
||||||
|
fake_responses,
|
||||||
|
commitment_ring,
|
||||||
|
pseudo_output_commitment,
|
||||||
|
msg,
|
||||||
|
R_a,
|
||||||
|
R_prime_a,
|
||||||
|
s_prime_a,
|
||||||
|
alpha_a,
|
||||||
|
H_p_pk,
|
||||||
|
I_a,
|
||||||
|
I_hat_a,
|
||||||
|
T_a,
|
||||||
|
z,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next_message(&self, rng: &mut (impl Rng + CryptoRng)) -> Message0 {
|
||||||
|
Message0 {
|
||||||
|
pi_a: DleqProof::new(
|
||||||
|
ED25519_BASEPOINT_POINT,
|
||||||
|
self.T_a,
|
||||||
|
self.H_p_pk,
|
||||||
|
self.I_hat_a,
|
||||||
|
self.alpha_a,
|
||||||
|
rng,
|
||||||
|
),
|
||||||
|
c_a: Commitment::new(self.fake_responses, self.I_a, self.I_hat_a, self.T_a),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn receive(self, msg: Message1) -> anyhow::Result<Alice1> {
|
||||||
|
msg.pi_b
|
||||||
|
.verify(ED25519_BASEPOINT_POINT, msg.T_b, self.H_p_pk, msg.I_hat_b)?;
|
||||||
|
|
||||||
|
let I = self.I_a + msg.I_b;
|
||||||
|
let sig = monero::clsag::sign(
|
||||||
|
&self.msg,
|
||||||
|
self.s_prime_a,
|
||||||
|
0,
|
||||||
|
self.H_p_pk,
|
||||||
|
self.alpha_a,
|
||||||
|
&self.ring,
|
||||||
|
&self.commitment_ring,
|
||||||
|
self.fake_responses,
|
||||||
|
self.z,
|
||||||
|
self.pseudo_output_commitment,
|
||||||
|
self.T_a + msg.T_b + self.R_a,
|
||||||
|
self.I_hat_a + msg.I_hat_b + self.R_prime_a,
|
||||||
|
I,
|
||||||
|
);
|
||||||
|
|
||||||
|
let sig = HalfAdaptorSignature {
|
||||||
|
s_0_half: sig.s[0],
|
||||||
|
fake_responses: self.fake_responses,
|
||||||
|
h_0: sig.c1,
|
||||||
|
D: sig.D,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Alice1 {
|
||||||
|
fake_responses: self.fake_responses,
|
||||||
|
I_a: self.I_a,
|
||||||
|
I_hat_a: self.I_hat_a,
|
||||||
|
T_a: self.T_a,
|
||||||
|
sig,
|
||||||
|
I,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Alice1 {
|
||||||
|
fake_responses: [Scalar; 10],
|
||||||
|
I_a: EdwardsPoint,
|
||||||
|
I_hat_a: EdwardsPoint,
|
||||||
|
T_a: EdwardsPoint,
|
||||||
|
sig: HalfAdaptorSignature,
|
||||||
|
I: EdwardsPoint,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Alice1 {
|
||||||
|
pub fn next_message(&self) -> Message2 {
|
||||||
|
Message2 {
|
||||||
|
d_a: Opening::new(self.fake_responses, self.I_a, self.I_hat_a, self.T_a),
|
||||||
|
s_0_a: self.sig.s_0_half,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn receive(self, msg: Message3) -> Alice2 {
|
||||||
|
let adaptor_sig = self.sig.complete(msg.s_0_b);
|
||||||
|
|
||||||
|
Alice2 {
|
||||||
|
adaptor_sig,
|
||||||
|
I: self.I,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Alice2 {
|
||||||
|
pub adaptor_sig: AdaptorSignature,
|
||||||
|
pub I: EdwardsPoint,
|
||||||
|
}
|
167
monero-adaptor/src/bob.rs
Normal file
167
monero-adaptor/src/bob.rs
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
use curve25519_dalek::edwards::EdwardsPoint;
|
||||||
|
use curve25519_dalek::scalar::Scalar;
|
||||||
|
use hash_edwards_to_edwards::hash_point_to_point;
|
||||||
|
use rand::{CryptoRng, Rng};
|
||||||
|
|
||||||
|
use crate::commitment::Commitment;
|
||||||
|
use crate::dleq_proof::DleqProof;
|
||||||
|
use crate::messages::{Message0, Message1, Message2, Message3};
|
||||||
|
use crate::{AdaptorSignature, HalfAdaptorSignature};
|
||||||
|
use curve25519_dalek::constants::ED25519_BASEPOINT_POINT;
|
||||||
|
|
||||||
|
pub struct Bob0 {
|
||||||
|
ring: [EdwardsPoint; 11],
|
||||||
|
msg: [u8; 32],
|
||||||
|
commitment_ring: [EdwardsPoint; 11],
|
||||||
|
pseudo_output_commitment: EdwardsPoint,
|
||||||
|
R_a: EdwardsPoint,
|
||||||
|
R_prime_a: EdwardsPoint,
|
||||||
|
s_b: Scalar,
|
||||||
|
alpha_b: Scalar,
|
||||||
|
H_p_pk: EdwardsPoint,
|
||||||
|
I_b: EdwardsPoint,
|
||||||
|
I_hat_b: EdwardsPoint,
|
||||||
|
T_b: EdwardsPoint,
|
||||||
|
z: Scalar,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Bob0 {
|
||||||
|
pub fn new(
|
||||||
|
ring: [EdwardsPoint; 11],
|
||||||
|
msg: [u8; 32],
|
||||||
|
commitment_ring: [EdwardsPoint; 11],
|
||||||
|
pseudo_output_commitment: EdwardsPoint,
|
||||||
|
R_a: EdwardsPoint,
|
||||||
|
R_prime_a: EdwardsPoint,
|
||||||
|
s_b: Scalar,
|
||||||
|
z: Scalar,
|
||||||
|
rng: &mut (impl Rng + CryptoRng),
|
||||||
|
) -> anyhow::Result<Self> {
|
||||||
|
let alpha_b = Scalar::random(rng);
|
||||||
|
|
||||||
|
let p_k = ring[0];
|
||||||
|
let H_p_pk = hash_point_to_point(p_k);
|
||||||
|
|
||||||
|
let I_b = s_b * H_p_pk;
|
||||||
|
let I_hat_b = alpha_b * H_p_pk;
|
||||||
|
let T_b = alpha_b * ED25519_BASEPOINT_POINT;
|
||||||
|
|
||||||
|
Ok(Bob0 {
|
||||||
|
ring,
|
||||||
|
msg,
|
||||||
|
commitment_ring,
|
||||||
|
pseudo_output_commitment,
|
||||||
|
R_a,
|
||||||
|
R_prime_a,
|
||||||
|
s_b,
|
||||||
|
alpha_b,
|
||||||
|
H_p_pk,
|
||||||
|
I_b,
|
||||||
|
I_hat_b,
|
||||||
|
T_b,
|
||||||
|
z,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn receive(self, msg: Message0) -> Bob1 {
|
||||||
|
Bob1 {
|
||||||
|
ring: self.ring,
|
||||||
|
msg: self.msg,
|
||||||
|
commitment_ring: self.commitment_ring,
|
||||||
|
pseudo_output_commitment: self.pseudo_output_commitment,
|
||||||
|
R_a: self.R_a,
|
||||||
|
R_prime_a: self.R_prime_a,
|
||||||
|
s_b: self.s_b,
|
||||||
|
alpha_b: self.alpha_b,
|
||||||
|
H_p_pk: self.H_p_pk,
|
||||||
|
I_b: self.I_b,
|
||||||
|
I_hat_b: self.I_hat_b,
|
||||||
|
T_b: self.T_b,
|
||||||
|
pi_a: msg.pi_a,
|
||||||
|
c_a: msg.c_a,
|
||||||
|
z: self.z,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Bob1 {
|
||||||
|
ring: [EdwardsPoint; 11],
|
||||||
|
msg: [u8; 32],
|
||||||
|
commitment_ring: [EdwardsPoint; 11],
|
||||||
|
pseudo_output_commitment: EdwardsPoint,
|
||||||
|
R_a: EdwardsPoint,
|
||||||
|
R_prime_a: EdwardsPoint,
|
||||||
|
s_b: Scalar,
|
||||||
|
alpha_b: Scalar,
|
||||||
|
H_p_pk: EdwardsPoint,
|
||||||
|
I_b: EdwardsPoint,
|
||||||
|
I_hat_b: EdwardsPoint,
|
||||||
|
T_b: EdwardsPoint,
|
||||||
|
pi_a: DleqProof,
|
||||||
|
c_a: Commitment,
|
||||||
|
z: Scalar,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Bob1 {
|
||||||
|
pub fn next_message(&self, rng: &mut (impl Rng + CryptoRng)) -> Message1 {
|
||||||
|
Message1 {
|
||||||
|
I_b: self.I_b,
|
||||||
|
T_b: self.T_b,
|
||||||
|
I_hat_b: self.I_hat_b,
|
||||||
|
pi_b: DleqProof::new(
|
||||||
|
ED25519_BASEPOINT_POINT,
|
||||||
|
self.T_b,
|
||||||
|
self.H_p_pk,
|
||||||
|
self.I_hat_b,
|
||||||
|
self.alpha_b,
|
||||||
|
rng,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn receive(self, msg: Message2) -> anyhow::Result<Bob2> {
|
||||||
|
let (fake_responses, I_a, I_hat_a, T_a) = msg.d_a.open(self.c_a)?;
|
||||||
|
|
||||||
|
self.pi_a
|
||||||
|
.verify(ED25519_BASEPOINT_POINT, T_a, self.H_p_pk, I_hat_a)?;
|
||||||
|
|
||||||
|
let I = I_a + self.I_b;
|
||||||
|
let sig = monero::clsag::sign(
|
||||||
|
&self.msg,
|
||||||
|
self.s_b,
|
||||||
|
0,
|
||||||
|
self.H_p_pk,
|
||||||
|
self.alpha_b,
|
||||||
|
&self.ring,
|
||||||
|
&self.commitment_ring,
|
||||||
|
fake_responses,
|
||||||
|
self.z,
|
||||||
|
self.pseudo_output_commitment,
|
||||||
|
T_a + self.T_b + self.R_a,
|
||||||
|
I_hat_a + self.I_hat_b + self.R_prime_a,
|
||||||
|
I,
|
||||||
|
);
|
||||||
|
|
||||||
|
let s_0_b = sig.s[0];
|
||||||
|
let sig = HalfAdaptorSignature {
|
||||||
|
s_0_half: s_0_b,
|
||||||
|
fake_responses,
|
||||||
|
h_0: sig.c1,
|
||||||
|
D: sig.D,
|
||||||
|
};
|
||||||
|
let adaptor_sig = sig.complete(msg.s_0_a);
|
||||||
|
|
||||||
|
Ok(Bob2 { s_0_b, adaptor_sig })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Bob2 {
|
||||||
|
s_0_b: Scalar,
|
||||||
|
pub adaptor_sig: AdaptorSignature,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Bob2 {
|
||||||
|
pub fn next_message(&self) -> Message3 {
|
||||||
|
Message3 { s_0_b: self.s_0_b }
|
||||||
|
}
|
||||||
|
}
|
69
monero-adaptor/src/commitment.rs
Normal file
69
monero-adaptor/src/commitment.rs
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
use anyhow::{bail, Result};
|
||||||
|
use curve25519_dalek::edwards::EdwardsPoint;
|
||||||
|
use curve25519_dalek::scalar::Scalar;
|
||||||
|
use tiny_keccak::{Hasher, Keccak};
|
||||||
|
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
pub struct Commitment([u8; 32]);
|
||||||
|
|
||||||
|
impl Commitment {
|
||||||
|
pub fn new(
|
||||||
|
fake_responses: [Scalar; 10],
|
||||||
|
I_a: EdwardsPoint,
|
||||||
|
I_hat_a: EdwardsPoint,
|
||||||
|
T_a: EdwardsPoint,
|
||||||
|
) -> Self {
|
||||||
|
let fake_responses = fake_responses
|
||||||
|
.iter()
|
||||||
|
.flat_map(|r| r.as_bytes().to_vec())
|
||||||
|
.collect::<Vec<u8>>();
|
||||||
|
|
||||||
|
let mut keccak = Keccak::v256();
|
||||||
|
keccak.update(&fake_responses);
|
||||||
|
keccak.update(I_a.compress().as_bytes());
|
||||||
|
keccak.update(I_hat_a.compress().as_bytes());
|
||||||
|
keccak.update(T_a.compress().as_bytes());
|
||||||
|
|
||||||
|
let mut output = [0u8; 32];
|
||||||
|
keccak.finalize(&mut output);
|
||||||
|
|
||||||
|
Self(output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Opening {
|
||||||
|
fake_responses: [Scalar; 10],
|
||||||
|
I_a: EdwardsPoint,
|
||||||
|
I_hat_a: EdwardsPoint,
|
||||||
|
T_a: EdwardsPoint,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Opening {
|
||||||
|
pub fn new(
|
||||||
|
fake_responses: [Scalar; 10],
|
||||||
|
I_a: EdwardsPoint,
|
||||||
|
I_hat_a: EdwardsPoint,
|
||||||
|
T_a: EdwardsPoint,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
fake_responses,
|
||||||
|
I_a,
|
||||||
|
I_hat_a,
|
||||||
|
T_a,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn open(
|
||||||
|
self,
|
||||||
|
commitment: Commitment,
|
||||||
|
) -> Result<([Scalar; 10], EdwardsPoint, EdwardsPoint, EdwardsPoint)> {
|
||||||
|
let self_commitment =
|
||||||
|
Commitment::new(self.fake_responses, self.I_a, self.I_hat_a, self.T_a);
|
||||||
|
|
||||||
|
if self_commitment == commitment {
|
||||||
|
Ok((self.fake_responses, self.I_a, self.I_hat_a, self.T_a))
|
||||||
|
} else {
|
||||||
|
bail!("opening does not match commitment")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
75
monero-adaptor/src/dleq_proof.rs
Normal file
75
monero-adaptor/src/dleq_proof.rs
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
use anyhow::bail;
|
||||||
|
use curve25519_dalek::edwards::EdwardsPoint;
|
||||||
|
use curve25519_dalek::scalar::Scalar;
|
||||||
|
use rand::{CryptoRng, Rng};
|
||||||
|
use tiny_keccak::{Hasher, Keccak};
|
||||||
|
|
||||||
|
pub struct DleqProof {
|
||||||
|
s: Scalar,
|
||||||
|
c: Scalar,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DleqProof {
|
||||||
|
pub fn new(
|
||||||
|
G: EdwardsPoint,
|
||||||
|
xG: EdwardsPoint,
|
||||||
|
H: EdwardsPoint,
|
||||||
|
xH: EdwardsPoint,
|
||||||
|
x: Scalar,
|
||||||
|
rng: &mut (impl Rng + CryptoRng),
|
||||||
|
) -> Self {
|
||||||
|
let r = Scalar::random(rng);
|
||||||
|
let rG = r * G;
|
||||||
|
let rH = r * H;
|
||||||
|
|
||||||
|
let mut keccak = Keccak::v256();
|
||||||
|
keccak.update(G.compress().as_bytes());
|
||||||
|
keccak.update(xG.compress().as_bytes());
|
||||||
|
keccak.update(H.compress().as_bytes());
|
||||||
|
keccak.update(xH.compress().as_bytes());
|
||||||
|
keccak.update(rG.compress().as_bytes());
|
||||||
|
keccak.update(rH.compress().as_bytes());
|
||||||
|
|
||||||
|
let mut output = [0u8; 32];
|
||||||
|
keccak.finalize(&mut output);
|
||||||
|
|
||||||
|
let c = Scalar::from_bytes_mod_order(output);
|
||||||
|
|
||||||
|
let s = r + c * x;
|
||||||
|
|
||||||
|
Self { s, c }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn verify(
|
||||||
|
&self,
|
||||||
|
G: EdwardsPoint,
|
||||||
|
xG: EdwardsPoint,
|
||||||
|
H: EdwardsPoint,
|
||||||
|
xH: EdwardsPoint,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let s = self.s;
|
||||||
|
let c = self.c;
|
||||||
|
|
||||||
|
let rG = (s * G) + (-c * xG);
|
||||||
|
let rH = (s * H) + (-c * xH);
|
||||||
|
|
||||||
|
let mut keccak = Keccak::v256();
|
||||||
|
keccak.update(G.compress().as_bytes());
|
||||||
|
keccak.update(xG.compress().as_bytes());
|
||||||
|
keccak.update(H.compress().as_bytes());
|
||||||
|
keccak.update(xH.compress().as_bytes());
|
||||||
|
keccak.update(rG.compress().as_bytes());
|
||||||
|
keccak.update(rH.compress().as_bytes());
|
||||||
|
|
||||||
|
let mut output = [0u8; 32];
|
||||||
|
keccak.finalize(&mut output);
|
||||||
|
|
||||||
|
let c_prime = Scalar::from_bytes_mod_order(output);
|
||||||
|
|
||||||
|
if c != c_prime {
|
||||||
|
bail!("invalid DLEQ proof")
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
@ -3,24 +3,25 @@
|
|||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
#![warn(clippy::needless_pass_by_value)]
|
#![warn(clippy::needless_pass_by_value)]
|
||||||
|
|
||||||
use std::convert::TryInto;
|
pub(crate) mod alice;
|
||||||
|
pub(crate) mod bob;
|
||||||
|
pub(crate) mod commitment;
|
||||||
|
pub(crate) mod dleq_proof;
|
||||||
|
pub(crate) mod messages;
|
||||||
|
|
||||||
|
pub use self::alice::*;
|
||||||
|
pub use self::bob::*;
|
||||||
|
pub use self::commitment::*;
|
||||||
|
pub use self::messages::*;
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
|
||||||
use curve25519_dalek::constants::ED25519_BASEPOINT_POINT;
|
|
||||||
use curve25519_dalek::edwards::EdwardsPoint;
|
use curve25519_dalek::edwards::EdwardsPoint;
|
||||||
use curve25519_dalek::scalar::Scalar;
|
use curve25519_dalek::scalar::Scalar;
|
||||||
use hash_edwards_to_edwards::hash_point_to_point;
|
|
||||||
use rand::{CryptoRng, Rng};
|
|
||||||
use tiny_keccak::{Hasher, Keccak};
|
|
||||||
|
|
||||||
use monero::util::ringct::Clsag;
|
use monero::util::ringct::Clsag;
|
||||||
|
|
||||||
pub struct AdaptorSignature {
|
pub struct AdaptorSignature {
|
||||||
s_0: Scalar,
|
s_0: Scalar,
|
||||||
fake_responses: [Scalar; 10],
|
fake_responses: [Scalar; 10],
|
||||||
h_0: Scalar,
|
h_0: Scalar,
|
||||||
/// Key image of the real key in the ring.
|
|
||||||
I: EdwardsPoint,
|
|
||||||
/// Commitment key image `D = z * hash_to_p3(signing_public_key)`
|
/// Commitment key image `D = z * hash_to_p3(signing_public_key)`
|
||||||
D: EdwardsPoint,
|
D: EdwardsPoint,
|
||||||
}
|
}
|
||||||
@ -29,8 +30,6 @@ pub struct HalfAdaptorSignature {
|
|||||||
s_0_half: Scalar,
|
s_0_half: Scalar,
|
||||||
fake_responses: [Scalar; 10],
|
fake_responses: [Scalar; 10],
|
||||||
h_0: Scalar,
|
h_0: Scalar,
|
||||||
/// Key image of the real key in the ring.
|
|
||||||
I: EdwardsPoint,
|
|
||||||
/// Commitment key image `D = z * hash_to_p3(signing_public_key)`
|
/// Commitment key image `D = z * hash_to_p3(signing_public_key)`
|
||||||
D: EdwardsPoint,
|
D: EdwardsPoint,
|
||||||
}
|
}
|
||||||
@ -41,7 +40,6 @@ impl HalfAdaptorSignature {
|
|||||||
s_0: self.s_0_half + s_other_half,
|
s_0: self.s_0_half + s_other_half,
|
||||||
fake_responses: self.fake_responses,
|
fake_responses: self.fake_responses,
|
||||||
h_0: self.h_0,
|
h_0: self.h_0,
|
||||||
I: self.I,
|
|
||||||
D: self.D,
|
D: self.D,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -51,575 +49,12 @@ impl AdaptorSignature {
|
|||||||
pub fn adapt(self, y: Scalar) -> Clsag {
|
pub fn adapt(self, y: Scalar) -> Clsag {
|
||||||
let r_last = self.s_0 + y;
|
let r_last = self.s_0 + y;
|
||||||
|
|
||||||
let _responses: [Scalar; 11] = self
|
Clsag {
|
||||||
.fake_responses
|
s: std::iter::once(r_last)
|
||||||
.iter()
|
.chain(self.fake_responses.iter().copied())
|
||||||
.chain([r_last].iter())
|
.collect(),
|
||||||
.copied()
|
D: self.D,
|
||||||
.collect::<Vec<_>>()
|
c1: self.h_0,
|
||||||
.try_into()
|
|
||||||
.expect("correct response size");
|
|
||||||
|
|
||||||
todo!()
|
|
||||||
// Signature {
|
|
||||||
// responses,
|
|
||||||
// h_0: self.h_0,
|
|
||||||
// I: self.I,
|
|
||||||
// D: self.D,
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Alice0 {
|
|
||||||
// secret index is always 0
|
|
||||||
ring: [EdwardsPoint; 11],
|
|
||||||
fake_responses: [Scalar; 10],
|
|
||||||
commitment_ring: [EdwardsPoint; 11],
|
|
||||||
pseudo_output_commitment: EdwardsPoint,
|
|
||||||
msg: [u8; 32],
|
|
||||||
// encryption key
|
|
||||||
R_a: EdwardsPoint,
|
|
||||||
// R'a = r_a*H_p(p_k) where p_k is the signing public key
|
|
||||||
R_prime_a: EdwardsPoint,
|
|
||||||
// this is not s_a cos of something to with one-time-address??
|
|
||||||
s_prime_a: Scalar,
|
|
||||||
// secret value:
|
|
||||||
alpha_a: Scalar,
|
|
||||||
H_p_pk: EdwardsPoint,
|
|
||||||
I_a: EdwardsPoint,
|
|
||||||
I_hat_a: EdwardsPoint,
|
|
||||||
T_a: EdwardsPoint,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Alice0 {
|
|
||||||
pub fn new(
|
|
||||||
ring: [EdwardsPoint; 11],
|
|
||||||
msg: [u8; 32],
|
|
||||||
commitment_ring: [EdwardsPoint; 11],
|
|
||||||
pseudo_output_commitment: EdwardsPoint,
|
|
||||||
R_a: EdwardsPoint,
|
|
||||||
R_prime_a: EdwardsPoint,
|
|
||||||
s_prime_a: Scalar,
|
|
||||||
rng: &mut (impl Rng + CryptoRng),
|
|
||||||
) -> Result<Self> {
|
|
||||||
let mut fake_responses = [Scalar::zero(); 10];
|
|
||||||
for response in fake_responses.iter_mut().take(10) {
|
|
||||||
*response = Scalar::random(rng);
|
|
||||||
}
|
|
||||||
let alpha_a = Scalar::random(rng);
|
|
||||||
|
|
||||||
let p_k = ring[0];
|
|
||||||
let H_p_pk = hash_point_to_point(p_k);
|
|
||||||
|
|
||||||
let I_a = s_prime_a * H_p_pk;
|
|
||||||
let I_hat_a = alpha_a * H_p_pk;
|
|
||||||
let T_a = alpha_a * ED25519_BASEPOINT_POINT;
|
|
||||||
|
|
||||||
Ok(Alice0 {
|
|
||||||
ring,
|
|
||||||
fake_responses,
|
|
||||||
commitment_ring,
|
|
||||||
pseudo_output_commitment,
|
|
||||||
msg,
|
|
||||||
R_a,
|
|
||||||
R_prime_a,
|
|
||||||
s_prime_a,
|
|
||||||
alpha_a,
|
|
||||||
H_p_pk,
|
|
||||||
I_a,
|
|
||||||
I_hat_a,
|
|
||||||
T_a,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn next_message(&self, rng: &mut (impl Rng + CryptoRng)) -> Message0 {
|
|
||||||
Message0 {
|
|
||||||
pi_a: DleqProof::new(
|
|
||||||
ED25519_BASEPOINT_POINT,
|
|
||||||
self.T_a,
|
|
||||||
self.H_p_pk,
|
|
||||||
self.I_hat_a,
|
|
||||||
self.alpha_a,
|
|
||||||
rng,
|
|
||||||
),
|
|
||||||
c_a: Commitment::new(self.fake_responses, self.I_a, self.I_hat_a, self.T_a),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Pass commitment-related data as an argument to this function, like z
|
|
||||||
pub fn receive(self, msg: Message1, z: Scalar) -> Result<Alice1> {
|
|
||||||
msg.pi_b
|
|
||||||
.verify(ED25519_BASEPOINT_POINT, msg.T_b, self.H_p_pk, msg.I_hat_b)?;
|
|
||||||
|
|
||||||
let I = self.I_a + msg.I_b;
|
|
||||||
let sig = monero::clsag::sign(
|
|
||||||
&self.msg,
|
|
||||||
self.s_prime_a,
|
|
||||||
0,
|
|
||||||
self.H_p_pk,
|
|
||||||
self.alpha_a,
|
|
||||||
&self.ring,
|
|
||||||
&self.commitment_ring,
|
|
||||||
self.fake_responses,
|
|
||||||
z,
|
|
||||||
self.pseudo_output_commitment,
|
|
||||||
self.T_a + msg.T_b + self.R_a,
|
|
||||||
self.I_hat_a + msg.I_hat_b + self.R_prime_a,
|
|
||||||
I,
|
|
||||||
);
|
|
||||||
|
|
||||||
let sig = HalfAdaptorSignature {
|
|
||||||
s_0_half: todo!(),
|
|
||||||
fake_responses: self.fake_responses,
|
|
||||||
h_0: todo!(),
|
|
||||||
I,
|
|
||||||
D: todo!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Alice1 {
|
|
||||||
fake_responses: self.fake_responses,
|
|
||||||
I_a: self.I_a,
|
|
||||||
I_hat_a: self.I_hat_a,
|
|
||||||
T_a: self.T_a,
|
|
||||||
sig,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Alice1 {
|
|
||||||
fake_responses: [Scalar; 10],
|
|
||||||
I_a: EdwardsPoint,
|
|
||||||
I_hat_a: EdwardsPoint,
|
|
||||||
T_a: EdwardsPoint,
|
|
||||||
sig: HalfAdaptorSignature,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Alice1 {
|
|
||||||
pub fn next_message(&self) -> Message2 {
|
|
||||||
Message2 {
|
|
||||||
d_a: Opening::new(self.fake_responses, self.I_a, self.I_hat_a, self.T_a),
|
|
||||||
s_0_a: self.sig.s_0_half,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn receive(self, msg: Message3) -> Alice2 {
|
|
||||||
let adaptor_sig = self.sig.complete(msg.s_0_b);
|
|
||||||
|
|
||||||
Alice2 { adaptor_sig }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Alice2 {
|
|
||||||
pub adaptor_sig: AdaptorSignature,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Bob0 {
|
|
||||||
ring: [EdwardsPoint; 11],
|
|
||||||
msg: [u8; 32],
|
|
||||||
commitment_ring: [EdwardsPoint; 11],
|
|
||||||
pseudo_output_commitment: EdwardsPoint,
|
|
||||||
R_a: EdwardsPoint,
|
|
||||||
R_prime_a: EdwardsPoint,
|
|
||||||
s_b: Scalar,
|
|
||||||
alpha_b: Scalar,
|
|
||||||
H_p_pk: EdwardsPoint,
|
|
||||||
I_b: EdwardsPoint,
|
|
||||||
I_hat_b: EdwardsPoint,
|
|
||||||
T_b: EdwardsPoint,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Bob0 {
|
|
||||||
pub fn new(
|
|
||||||
ring: [EdwardsPoint; 11],
|
|
||||||
msg: [u8; 32],
|
|
||||||
commitment_ring: [EdwardsPoint; 11],
|
|
||||||
pseudo_output_commitment: EdwardsPoint,
|
|
||||||
R_a: EdwardsPoint,
|
|
||||||
R_prime_a: EdwardsPoint,
|
|
||||||
s_b: Scalar,
|
|
||||||
rng: &mut (impl Rng + CryptoRng),
|
|
||||||
) -> Result<Self> {
|
|
||||||
let alpha_b = Scalar::random(rng);
|
|
||||||
|
|
||||||
let p_k = ring[0];
|
|
||||||
let H_p_pk = hash_point_to_point(p_k);
|
|
||||||
|
|
||||||
let I_b = s_b * H_p_pk;
|
|
||||||
let I_hat_b = alpha_b * H_p_pk;
|
|
||||||
let T_b = alpha_b * ED25519_BASEPOINT_POINT;
|
|
||||||
|
|
||||||
Ok(Bob0 {
|
|
||||||
ring,
|
|
||||||
msg,
|
|
||||||
commitment_ring,
|
|
||||||
pseudo_output_commitment,
|
|
||||||
R_a,
|
|
||||||
R_prime_a,
|
|
||||||
s_b,
|
|
||||||
alpha_b,
|
|
||||||
H_p_pk,
|
|
||||||
I_b,
|
|
||||||
I_hat_b,
|
|
||||||
T_b,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn receive(self, msg: Message0) -> Bob1 {
|
|
||||||
Bob1 {
|
|
||||||
ring: self.ring,
|
|
||||||
msg: self.msg,
|
|
||||||
commitment_ring: self.commitment_ring,
|
|
||||||
pseudo_output_commitment: self.pseudo_output_commitment,
|
|
||||||
R_a: self.R_a,
|
|
||||||
R_prime_a: self.R_prime_a,
|
|
||||||
s_b: self.s_b,
|
|
||||||
alpha_b: self.alpha_b,
|
|
||||||
H_p_pk: self.H_p_pk,
|
|
||||||
I_b: self.I_b,
|
|
||||||
I_hat_b: self.I_hat_b,
|
|
||||||
T_b: self.T_b,
|
|
||||||
pi_a: msg.pi_a,
|
|
||||||
c_a: msg.c_a,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Bob1 {
|
|
||||||
ring: [EdwardsPoint; 11],
|
|
||||||
msg: [u8; 32],
|
|
||||||
commitment_ring: [EdwardsPoint; 11],
|
|
||||||
pseudo_output_commitment: EdwardsPoint,
|
|
||||||
R_a: EdwardsPoint,
|
|
||||||
R_prime_a: EdwardsPoint,
|
|
||||||
s_b: Scalar,
|
|
||||||
alpha_b: Scalar,
|
|
||||||
H_p_pk: EdwardsPoint,
|
|
||||||
I_b: EdwardsPoint,
|
|
||||||
I_hat_b: EdwardsPoint,
|
|
||||||
T_b: EdwardsPoint,
|
|
||||||
pi_a: DleqProof,
|
|
||||||
c_a: Commitment,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Bob1 {
|
|
||||||
pub fn next_message(&self, rng: &mut (impl Rng + CryptoRng)) -> Message1 {
|
|
||||||
Message1 {
|
|
||||||
I_b: self.I_b,
|
|
||||||
T_b: self.T_b,
|
|
||||||
I_hat_b: self.I_hat_b,
|
|
||||||
pi_b: DleqProof::new(
|
|
||||||
ED25519_BASEPOINT_POINT,
|
|
||||||
self.T_b,
|
|
||||||
self.H_p_pk,
|
|
||||||
self.I_hat_b,
|
|
||||||
self.alpha_b,
|
|
||||||
rng,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Pass commitment-related data as an argument to this function, like z
|
|
||||||
pub fn receive(self, msg: Message2, z: Scalar) -> Result<Bob2> {
|
|
||||||
let (fake_responses, I_a, I_hat_a, T_a) = msg.d_a.open(self.c_a)?;
|
|
||||||
|
|
||||||
self.pi_a
|
|
||||||
.verify(ED25519_BASEPOINT_POINT, T_a, self.H_p_pk, I_hat_a)?;
|
|
||||||
|
|
||||||
let I = I_a + self.I_b;
|
|
||||||
let sig = monero::clsag::sign(
|
|
||||||
&self.msg,
|
|
||||||
self.s_b,
|
|
||||||
0,
|
|
||||||
self.H_p_pk,
|
|
||||||
self.alpha_b,
|
|
||||||
&self.ring,
|
|
||||||
&self.commitment_ring,
|
|
||||||
fake_responses,
|
|
||||||
z,
|
|
||||||
self.pseudo_output_commitment,
|
|
||||||
T_a + self.T_b + self.R_a,
|
|
||||||
I_hat_a + self.I_hat_b + self.R_prime_a,
|
|
||||||
I,
|
|
||||||
);
|
|
||||||
|
|
||||||
let s_0_b = todo!();
|
|
||||||
let sig = HalfAdaptorSignature {
|
|
||||||
s_0_half: s_0_b,
|
|
||||||
fake_responses,
|
|
||||||
h_0: todo!(),
|
|
||||||
I,
|
|
||||||
D: todo!(),
|
|
||||||
};
|
|
||||||
let adaptor_sig = sig.complete(msg.s_0_a);
|
|
||||||
|
|
||||||
Ok(Bob2 { s_0_b, adaptor_sig })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Bob2 {
|
|
||||||
s_0_b: Scalar,
|
|
||||||
pub adaptor_sig: AdaptorSignature,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Bob2 {
|
|
||||||
pub fn next_message(&self) -> Message3 {
|
|
||||||
Message3 { s_0_b: self.s_0_b }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct DleqProof {
|
|
||||||
s: Scalar,
|
|
||||||
c: Scalar,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DleqProof {
|
|
||||||
fn new(
|
|
||||||
G: EdwardsPoint,
|
|
||||||
xG: EdwardsPoint,
|
|
||||||
H: EdwardsPoint,
|
|
||||||
xH: EdwardsPoint,
|
|
||||||
x: Scalar,
|
|
||||||
rng: &mut (impl Rng + CryptoRng),
|
|
||||||
) -> Self {
|
|
||||||
let r = Scalar::random(rng);
|
|
||||||
let rG = r * G;
|
|
||||||
let rH = r * H;
|
|
||||||
|
|
||||||
let mut keccak = Keccak::v256();
|
|
||||||
keccak.update(G.compress().as_bytes());
|
|
||||||
keccak.update(xG.compress().as_bytes());
|
|
||||||
keccak.update(H.compress().as_bytes());
|
|
||||||
keccak.update(xH.compress().as_bytes());
|
|
||||||
keccak.update(rG.compress().as_bytes());
|
|
||||||
keccak.update(rH.compress().as_bytes());
|
|
||||||
|
|
||||||
let mut output = [0u8; 32];
|
|
||||||
keccak.finalize(&mut output);
|
|
||||||
|
|
||||||
let c = Scalar::from_bytes_mod_order(output);
|
|
||||||
|
|
||||||
let s = r + c * x;
|
|
||||||
|
|
||||||
Self { s, c }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn verify(
|
|
||||||
&self,
|
|
||||||
G: EdwardsPoint,
|
|
||||||
xG: EdwardsPoint,
|
|
||||||
H: EdwardsPoint,
|
|
||||||
xH: EdwardsPoint,
|
|
||||||
) -> Result<()> {
|
|
||||||
let s = self.s;
|
|
||||||
let c = self.c;
|
|
||||||
|
|
||||||
let rG = (s * G) + (-c * xG);
|
|
||||||
let rH = (s * H) + (-c * xH);
|
|
||||||
|
|
||||||
let mut keccak = Keccak::v256();
|
|
||||||
keccak.update(G.compress().as_bytes());
|
|
||||||
keccak.update(xG.compress().as_bytes());
|
|
||||||
keccak.update(H.compress().as_bytes());
|
|
||||||
keccak.update(xH.compress().as_bytes());
|
|
||||||
keccak.update(rG.compress().as_bytes());
|
|
||||||
keccak.update(rH.compress().as_bytes());
|
|
||||||
|
|
||||||
let mut output = [0u8; 32];
|
|
||||||
keccak.finalize(&mut output);
|
|
||||||
|
|
||||||
let c_prime = Scalar::from_bytes_mod_order(output);
|
|
||||||
|
|
||||||
if c != c_prime {
|
|
||||||
bail!("invalid DLEQ proof")
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
|
||||||
struct Commitment([u8; 32]);
|
|
||||||
|
|
||||||
impl Commitment {
|
|
||||||
fn new(
|
|
||||||
fake_responses: [Scalar; 10],
|
|
||||||
I_a: EdwardsPoint,
|
|
||||||
I_hat_a: EdwardsPoint,
|
|
||||||
T_a: EdwardsPoint,
|
|
||||||
) -> Self {
|
|
||||||
let fake_responses = fake_responses
|
|
||||||
.iter()
|
|
||||||
.flat_map(|r| r.as_bytes().to_vec())
|
|
||||||
.collect::<Vec<u8>>();
|
|
||||||
|
|
||||||
let mut keccak = Keccak::v256();
|
|
||||||
keccak.update(&fake_responses);
|
|
||||||
keccak.update(I_a.compress().as_bytes());
|
|
||||||
keccak.update(I_hat_a.compress().as_bytes());
|
|
||||||
keccak.update(T_a.compress().as_bytes());
|
|
||||||
|
|
||||||
let mut output = [0u8; 32];
|
|
||||||
keccak.finalize(&mut output);
|
|
||||||
|
|
||||||
Self(output)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Opening {
|
|
||||||
fake_responses: [Scalar; 10],
|
|
||||||
I_a: EdwardsPoint,
|
|
||||||
I_hat_a: EdwardsPoint,
|
|
||||||
T_a: EdwardsPoint,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Opening {
|
|
||||||
fn new(
|
|
||||||
fake_responses: [Scalar; 10],
|
|
||||||
I_a: EdwardsPoint,
|
|
||||||
I_hat_a: EdwardsPoint,
|
|
||||||
T_a: EdwardsPoint,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
fake_responses,
|
|
||||||
I_a,
|
|
||||||
I_hat_a,
|
|
||||||
T_a,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn open(
|
|
||||||
self,
|
|
||||||
commitment: Commitment,
|
|
||||||
) -> Result<([Scalar; 10], EdwardsPoint, EdwardsPoint, EdwardsPoint)> {
|
|
||||||
let self_commitment =
|
|
||||||
Commitment::new(self.fake_responses, self.I_a, self.I_hat_a, self.T_a);
|
|
||||||
|
|
||||||
if self_commitment == commitment {
|
|
||||||
Ok((self.fake_responses, self.I_a, self.I_hat_a, self.T_a))
|
|
||||||
} else {
|
|
||||||
bail!("opening does not match commitment")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Alice Sends this to Bob
|
|
||||||
pub struct Message0 {
|
|
||||||
c_a: Commitment,
|
|
||||||
pi_a: DleqProof,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bob sends this to ALice
|
|
||||||
pub struct Message1 {
|
|
||||||
I_b: EdwardsPoint,
|
|
||||||
T_b: EdwardsPoint,
|
|
||||||
I_hat_b: EdwardsPoint,
|
|
||||||
pi_b: DleqProof,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Alice sends this to Bob
|
|
||||||
pub struct Message2 {
|
|
||||||
d_a: Opening,
|
|
||||||
s_0_a: Scalar,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bob sends this to Alice
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
pub struct Message3 {
|
|
||||||
s_0_b: Scalar,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use rand::rngs::OsRng;
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn sign_and_verify_success() {
|
|
||||||
let msg_to_sign = b"hello world, monero is amazing!!";
|
|
||||||
|
|
||||||
let s_prime_a = Scalar::random(&mut OsRng);
|
|
||||||
let s_b = Scalar::random(&mut OsRng);
|
|
||||||
|
|
||||||
let pk = (s_prime_a + s_b) * ED25519_BASEPOINT_POINT;
|
|
||||||
|
|
||||||
let (r_a, R_a, R_prime_a) = {
|
|
||||||
let r_a = Scalar::random(&mut OsRng);
|
|
||||||
let R_a = r_a * ED25519_BASEPOINT_POINT;
|
|
||||||
|
|
||||||
let pk_hashed_to_point = hash_point_to_point(pk);
|
|
||||||
|
|
||||||
let R_prime_a = r_a * pk_hashed_to_point;
|
|
||||||
|
|
||||||
(r_a, R_a, R_prime_a)
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut ring = [EdwardsPoint::default(); 11];
|
|
||||||
ring[0] = pk;
|
|
||||||
|
|
||||||
ring[1..].fill_with(|| {
|
|
||||||
let x = Scalar::random(&mut OsRng);
|
|
||||||
x * ED25519_BASEPOINT_POINT
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut commitment_ring = [EdwardsPoint::default(); 11];
|
|
||||||
|
|
||||||
let real_commitment_blinding = Scalar::random(&mut OsRng);
|
|
||||||
commitment_ring[0] = real_commitment_blinding * ED25519_BASEPOINT_POINT; // + 0 * H
|
|
||||||
commitment_ring[1..].fill_with(|| {
|
|
||||||
let x = Scalar::random(&mut OsRng);
|
|
||||||
x * ED25519_BASEPOINT_POINT
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO: document
|
|
||||||
let pseudo_output_commitment = commitment_ring[0];
|
|
||||||
|
|
||||||
let alice = Alice0::new(
|
|
||||||
ring,
|
|
||||||
*msg_to_sign,
|
|
||||||
commitment_ring,
|
|
||||||
pseudo_output_commitment,
|
|
||||||
R_a,
|
|
||||||
R_prime_a,
|
|
||||||
s_prime_a,
|
|
||||||
&mut OsRng,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let bob = Bob0::new(
|
|
||||||
ring,
|
|
||||||
*msg_to_sign,
|
|
||||||
commitment_ring,
|
|
||||||
pseudo_output_commitment,
|
|
||||||
R_a,
|
|
||||||
R_prime_a,
|
|
||||||
s_b,
|
|
||||||
&mut OsRng,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let msg = alice.next_message(&mut OsRng);
|
|
||||||
let bob = bob.receive(msg);
|
|
||||||
|
|
||||||
// TODO: Document this
|
|
||||||
let msg = bob.next_message(&mut OsRng);
|
|
||||||
let alice = alice.receive(msg, Scalar::zero()).unwrap();
|
|
||||||
|
|
||||||
let msg = alice.next_message();
|
|
||||||
let bob = bob.receive(msg, Scalar::zero()).unwrap();
|
|
||||||
|
|
||||||
let msg = bob.next_message();
|
|
||||||
let alice = alice.receive(msg);
|
|
||||||
|
|
||||||
let I = alice.adaptor_sig.I;
|
|
||||||
let sig = alice.adaptor_sig.adapt(r_a);
|
|
||||||
|
|
||||||
assert!(monero::clsag::verify(
|
|
||||||
&sig,
|
|
||||||
msg_to_sign,
|
|
||||||
&ring,
|
|
||||||
&commitment_ring,
|
|
||||||
I,
|
|
||||||
pseudo_output_commitment,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
30
monero-adaptor/src/messages.rs
Normal file
30
monero-adaptor/src/messages.rs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
use crate::commitment::{Commitment, Opening};
|
||||||
|
use crate::dleq_proof::DleqProof;
|
||||||
|
use curve25519_dalek::edwards::EdwardsPoint;
|
||||||
|
use curve25519_dalek::scalar::Scalar;
|
||||||
|
|
||||||
|
// Alice Sends this to Bob
|
||||||
|
pub struct Message0 {
|
||||||
|
pub c_a: Commitment,
|
||||||
|
pub pi_a: DleqProof,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bob sends this to ALice
|
||||||
|
pub struct Message1 {
|
||||||
|
pub I_b: EdwardsPoint,
|
||||||
|
pub T_b: EdwardsPoint,
|
||||||
|
pub I_hat_b: EdwardsPoint,
|
||||||
|
pub pi_b: DleqProof,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alice sends this to Bob
|
||||||
|
pub struct Message2 {
|
||||||
|
pub d_a: Opening,
|
||||||
|
pub s_0_a: Scalar,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bob sends this to Alice
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct Message3 {
|
||||||
|
pub s_0_b: Scalar,
|
||||||
|
}
|
104
monero-adaptor/tests/protocol.rs
Normal file
104
monero-adaptor/tests/protocol.rs
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
use curve25519_dalek::constants::ED25519_BASEPOINT_POINT;
|
||||||
|
use curve25519_dalek::scalar::Scalar;
|
||||||
|
use hash_edwards_to_edwards::hash_point_to_point;
|
||||||
|
use monero::util::key::H;
|
||||||
|
use monero_adaptor::{Alice0, Bob0};
|
||||||
|
use rand::rngs::OsRng;
|
||||||
|
use rand::thread_rng;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sign_and_verify_success() {
|
||||||
|
let msg_to_sign = b"hello world, monero is amazing!!";
|
||||||
|
|
||||||
|
let s_prime_a = Scalar::random(&mut OsRng);
|
||||||
|
let s_b = Scalar::random(&mut OsRng);
|
||||||
|
|
||||||
|
let pk = (s_prime_a + s_b) * ED25519_BASEPOINT_POINT;
|
||||||
|
|
||||||
|
let (r_a, R_a, R_prime_a) = {
|
||||||
|
let r_a = Scalar::random(&mut OsRng);
|
||||||
|
let R_a = r_a * ED25519_BASEPOINT_POINT;
|
||||||
|
|
||||||
|
let H_p_pk = hash_point_to_point(pk);
|
||||||
|
|
||||||
|
let R_prime_a = r_a * H_p_pk;
|
||||||
|
|
||||||
|
(r_a, R_a, R_prime_a)
|
||||||
|
};
|
||||||
|
|
||||||
|
let amount_to_spend = 1000000u32;
|
||||||
|
let fee = 10000u32;
|
||||||
|
let output_amount = amount_to_spend - fee;
|
||||||
|
|
||||||
|
let mut ring = random_array(|| Scalar::random(&mut thread_rng()) * ED25519_BASEPOINT_POINT);
|
||||||
|
let mut commitment_ring =
|
||||||
|
random_array(|| Scalar::random(&mut thread_rng()) * ED25519_BASEPOINT_POINT);
|
||||||
|
|
||||||
|
ring[0] = pk;
|
||||||
|
|
||||||
|
let real_commitment_blinding = Scalar::random(&mut thread_rng());
|
||||||
|
commitment_ring[0] =
|
||||||
|
real_commitment_blinding * ED25519_BASEPOINT_POINT + Scalar::from(amount_to_spend) * *H;
|
||||||
|
|
||||||
|
let fee_key = Scalar::from(fee) * *H;
|
||||||
|
|
||||||
|
let out_pk_blinding = Scalar::random(&mut thread_rng());
|
||||||
|
let out_pk = out_pk_blinding * ED25519_BASEPOINT_POINT + Scalar::from(output_amount) * *H;
|
||||||
|
|
||||||
|
let pseudo_output_commitment = fee_key + out_pk;
|
||||||
|
|
||||||
|
let alice = Alice0::new(
|
||||||
|
ring,
|
||||||
|
*msg_to_sign,
|
||||||
|
commitment_ring,
|
||||||
|
pseudo_output_commitment,
|
||||||
|
R_a,
|
||||||
|
R_prime_a,
|
||||||
|
s_prime_a,
|
||||||
|
real_commitment_blinding - out_pk_blinding,
|
||||||
|
&mut OsRng,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let bob = Bob0::new(
|
||||||
|
ring,
|
||||||
|
*msg_to_sign,
|
||||||
|
commitment_ring,
|
||||||
|
pseudo_output_commitment,
|
||||||
|
R_a,
|
||||||
|
R_prime_a,
|
||||||
|
s_b,
|
||||||
|
real_commitment_blinding - out_pk_blinding,
|
||||||
|
&mut OsRng,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let msg = alice.next_message(&mut OsRng);
|
||||||
|
let bob = bob.receive(msg);
|
||||||
|
|
||||||
|
let msg = bob.next_message(&mut OsRng);
|
||||||
|
let alice = alice.receive(msg).unwrap();
|
||||||
|
|
||||||
|
let msg = alice.next_message();
|
||||||
|
let bob = bob.receive(msg).unwrap();
|
||||||
|
|
||||||
|
let msg = bob.next_message();
|
||||||
|
let alice = alice.receive(msg);
|
||||||
|
|
||||||
|
let sig = alice.adaptor_sig.adapt(r_a);
|
||||||
|
|
||||||
|
assert!(monero::clsag::verify(
|
||||||
|
&sig,
|
||||||
|
msg_to_sign,
|
||||||
|
&ring,
|
||||||
|
&commitment_ring,
|
||||||
|
alice.I,
|
||||||
|
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
|
||||||
|
}
|
@ -1,3 +1,6 @@
|
|||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
#[allow(dead_code, unused_variables)]
|
||||||
mod v2;
|
mod v2;
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
|
@ -41,7 +41,7 @@ impl InputAdded {
|
|||||||
pub fn with_decoys_from_indices(
|
pub fn with_decoys_from_indices(
|
||||||
self,
|
self,
|
||||||
decoy_indices: [u64; 10],
|
decoy_indices: [u64; 10],
|
||||||
client: &(impl FetchDecoyInputs),
|
client: &impl FetchDecoyInputs,
|
||||||
) -> Result<DecoyOffsetsAdded, DuplicateIndex> {
|
) -> Result<DecoyOffsetsAdded, DuplicateIndex> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user