incorporate validity proof into transfer proof
This commit is contained in:
parent
c7bf9958e7
commit
30871784e4
|
@ -15,6 +15,7 @@ use {
|
||||||
instruction::{Role, Verifiable},
|
instruction::{Role, Verifiable},
|
||||||
range_proof::RangeProof,
|
range_proof::RangeProof,
|
||||||
transcript::TranscriptProtocol,
|
transcript::TranscriptProtocol,
|
||||||
|
validity_proof::ValidityProof,
|
||||||
},
|
},
|
||||||
curve25519_dalek::scalar::Scalar,
|
curve25519_dalek::scalar::Scalar,
|
||||||
merlin::Transcript,
|
merlin::Transcript,
|
||||||
|
@ -117,8 +118,7 @@ impl TransferData {
|
||||||
&dest_pk,
|
&dest_pk,
|
||||||
&auditor_pk,
|
&auditor_pk,
|
||||||
(amount_lo as u64, amount_hi as u64),
|
(amount_lo as u64, amount_hi as u64),
|
||||||
&open_lo,
|
(&open_lo, &open_hi),
|
||||||
&open_hi,
|
|
||||||
new_spendable_balance,
|
new_spendable_balance,
|
||||||
&new_spendable_ct,
|
&new_spendable_ct,
|
||||||
);
|
);
|
||||||
|
@ -205,6 +205,9 @@ pub struct TransferProof {
|
||||||
/// Associated equality proof
|
/// Associated equality proof
|
||||||
pub equality_proof: pod::EqualityProof,
|
pub equality_proof: pod::EqualityProof,
|
||||||
|
|
||||||
|
/// Associated ciphertext validity proof
|
||||||
|
pub validity_proof: pod::ValidityProof,
|
||||||
|
|
||||||
// Associated range proof
|
// Associated range proof
|
||||||
pub range_proof: pod::RangeProof128,
|
pub range_proof: pod::RangeProof128,
|
||||||
}
|
}
|
||||||
|
@ -220,11 +223,10 @@ impl TransferProof {
|
||||||
#[allow(clippy::many_single_char_names)]
|
#[allow(clippy::many_single_char_names)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
source_keypair: &ElGamalKeypair,
|
source_keypair: &ElGamalKeypair,
|
||||||
_dest_pk: &ElGamalPubkey,
|
dest_pk: &ElGamalPubkey,
|
||||||
_auditor_pk: &ElGamalPubkey,
|
auditor_pk: &ElGamalPubkey,
|
||||||
transfer_amt: (u64, u64),
|
transfer_amt: (u64, u64),
|
||||||
lo_open: &PedersenOpening,
|
openings: (&PedersenOpening, &PedersenOpening),
|
||||||
hi_open: &PedersenOpening,
|
|
||||||
source_new_balance: u64,
|
source_new_balance: u64,
|
||||||
source_new_balance_ct: &ElGamalCiphertext,
|
source_new_balance_ct: &ElGamalCiphertext,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -260,19 +262,27 @@ impl TransferProof {
|
||||||
&mut transcript,
|
&mut transcript,
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO: Add ct validity proof
|
// generate ciphertext validity proof
|
||||||
|
let validity_proof = ValidityProof::new(
|
||||||
|
&dest_pk,
|
||||||
|
&auditor_pk,
|
||||||
|
transfer_amt,
|
||||||
|
openings,
|
||||||
|
&mut transcript,
|
||||||
|
);
|
||||||
|
|
||||||
// generate the range proof
|
// generate the range proof
|
||||||
let range_proof = RangeProof::create(
|
let range_proof = RangeProof::create(
|
||||||
vec![source_new_balance, transfer_amt.0, transfer_amt.1],
|
vec![source_new_balance, transfer_amt.0, transfer_amt.1],
|
||||||
vec![64, 32, 32],
|
vec![64, 32, 32],
|
||||||
vec![&source_open, lo_open, hi_open],
|
vec![&source_open, openings.0, openings.1],
|
||||||
&mut transcript,
|
&mut transcript,
|
||||||
);
|
);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
source_commitment: source_commitment.into(),
|
source_commitment: source_commitment.into(),
|
||||||
equality_proof: equality_proof.try_into().expect("equality proof"),
|
equality_proof: equality_proof.try_into().expect("equality proof"),
|
||||||
|
validity_proof: validity_proof.try_into().expect("validity proof"),
|
||||||
range_proof: range_proof.try_into().expect("range proof"),
|
range_proof: range_proof.try_into().expect("range proof"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -280,8 +290,8 @@ impl TransferProof {
|
||||||
pub fn verify(
|
pub fn verify(
|
||||||
self,
|
self,
|
||||||
amount_comms: &TransferCommitments,
|
amount_comms: &TransferCommitments,
|
||||||
_decryption_handles_lo: &TransferDecryptHandles,
|
decryption_handles_lo: &TransferDecryptHandles,
|
||||||
_decryption_handles_hi: &TransferDecryptHandles,
|
decryption_handles_hi: &TransferDecryptHandles,
|
||||||
new_spendable_ct: &pod::ElGamalCiphertext,
|
new_spendable_ct: &pod::ElGamalCiphertext,
|
||||||
transfer_public_keys: &TransferPubkeys,
|
transfer_public_keys: &TransferPubkeys,
|
||||||
) -> Result<(), ProofError> {
|
) -> Result<(), ProofError> {
|
||||||
|
@ -289,6 +299,7 @@ impl TransferProof {
|
||||||
|
|
||||||
let commitment: PedersenCommitment = self.source_commitment.try_into()?;
|
let commitment: PedersenCommitment = self.source_commitment.try_into()?;
|
||||||
let equality_proof: EqualityProof = self.equality_proof.try_into()?;
|
let equality_proof: EqualityProof = self.equality_proof.try_into()?;
|
||||||
|
let validity_proof: ValidityProof = self.validity_proof.try_into()?;
|
||||||
let range_proof: RangeProof = self.range_proof.try_into()?;
|
let range_proof: RangeProof = self.range_proof.try_into()?;
|
||||||
|
|
||||||
// add a domain separator to record the start of the protocol
|
// add a domain separator to record the start of the protocol
|
||||||
|
@ -314,7 +325,28 @@ impl TransferProof {
|
||||||
// TODO: we can also consider verifying equality and range proof in a batch
|
// TODO: we can also consider verifying equality and range proof in a batch
|
||||||
equality_proof.verify(&source_pk, &new_spendable_ct, &commitment, &mut transcript)?;
|
equality_proof.verify(&source_pk, &new_spendable_ct, &commitment, &mut transcript)?;
|
||||||
|
|
||||||
|
// TODO: record destination and auditor public keys to transcript
|
||||||
|
let dest_elgamal_pubkey: ElGamalPubkey = transfer_public_keys.dest_pk.try_into()?;
|
||||||
|
let auditor_elgamal_pubkey: ElGamalPubkey = transfer_public_keys.auditor_pk.try_into()?;
|
||||||
|
|
||||||
|
let amount_comm_lo: PedersenCommitment = amount_comms.lo.try_into()?;
|
||||||
|
let amount_comm_hi: PedersenCommitment = amount_comms.hi.try_into()?;
|
||||||
|
|
||||||
|
let handle_lo_dest: PedersenDecryptHandle = decryption_handles_lo.dest.try_into()?;
|
||||||
|
let handle_hi_dest: PedersenDecryptHandle = decryption_handles_hi.dest.try_into()?;
|
||||||
|
|
||||||
|
let handle_lo_auditor: PedersenDecryptHandle = decryption_handles_lo.auditor.try_into()?;
|
||||||
|
let handle_hi_auditor: PedersenDecryptHandle = decryption_handles_hi.auditor.try_into()?;
|
||||||
|
|
||||||
// TODO: validity proof
|
// TODO: validity proof
|
||||||
|
validity_proof.verify(
|
||||||
|
&dest_elgamal_pubkey,
|
||||||
|
&auditor_elgamal_pubkey,
|
||||||
|
(&amount_comm_lo, &amount_comm_hi),
|
||||||
|
(&handle_lo_dest, &handle_hi_dest),
|
||||||
|
(&handle_lo_auditor, &handle_hi_auditor),
|
||||||
|
&mut transcript,
|
||||||
|
)?;
|
||||||
|
|
||||||
// verify range proof
|
// verify range proof
|
||||||
range_proof.verify(
|
range_proof.verify(
|
||||||
|
|
|
@ -6,11 +6,11 @@ use {
|
||||||
|
|
||||||
pub trait TranscriptProtocol {
|
pub trait TranscriptProtocol {
|
||||||
/// Append a domain separator for an `n`-bit rangeproof for ElGamalKeypair
|
/// Append a domain separator for an `n`-bit rangeproof for ElGamalKeypair
|
||||||
/// ciphertext using a decryption key // TODO: remove?
|
/// ciphertext using a decryption key
|
||||||
fn rangeproof_from_key_domain_sep(&mut self, n: u64);
|
fn rangeproof_from_key_domain_sep(&mut self, n: u64);
|
||||||
|
|
||||||
/// Append a domain separator for an `n`-bit rangeproof for ElGamalKeypair
|
/// Append a domain separator for an `n`-bit rangeproof for ElGamalKeypair
|
||||||
/// ciphertext using an opening // TODO: remove?
|
/// ciphertext using an opening
|
||||||
fn rangeproof_from_opening_domain_sep(&mut self, n: u64);
|
fn rangeproof_from_opening_domain_sep(&mut self, n: u64);
|
||||||
|
|
||||||
/// Append a domain separator for a length-`n` inner product proof.
|
/// Append a domain separator for a length-`n` inner product proof.
|
||||||
|
@ -19,6 +19,9 @@ pub trait TranscriptProtocol {
|
||||||
/// Append a domain separator for close account proof.
|
/// Append a domain separator for close account proof.
|
||||||
fn close_account_proof_domain_sep(&mut self);
|
fn close_account_proof_domain_sep(&mut self);
|
||||||
|
|
||||||
|
/// Append a domain separator for update account public key proof.
|
||||||
|
fn update_account_public_key_proof_domain_sep(&mut self);
|
||||||
|
|
||||||
/// Append a domain separator for withdraw proof.
|
/// Append a domain separator for withdraw proof.
|
||||||
fn withdraw_proof_domain_sep(&mut self);
|
fn withdraw_proof_domain_sep(&mut self);
|
||||||
|
|
||||||
|
@ -60,15 +63,19 @@ impl TranscriptProtocol for Transcript {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn close_account_proof_domain_sep(&mut self) {
|
fn close_account_proof_domain_sep(&mut self) {
|
||||||
self.append_message(b"dom_sep", b"CloseAccountProof");
|
self.append_message(b"dom-sep", b"CloseAccountProof");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_account_public_key_proof_domain_sep(&mut self) {
|
||||||
|
self.append_message(b"dom-sep", b"UpdateAccountPublicKeyProof");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn withdraw_proof_domain_sep(&mut self) {
|
fn withdraw_proof_domain_sep(&mut self) {
|
||||||
self.append_message(b"dom_sep", b"WithdrawProof");
|
self.append_message(b"dom-sep", b"WithdrawProof");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transfer_proof_domain_sep(&mut self) {
|
fn transfer_proof_domain_sep(&mut self) {
|
||||||
self.append_message(b"dom_sep", b"TransferProof");
|
self.append_message(b"dom-sep", b"TransferProof");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn append_scalar(&mut self, label: &'static [u8], scalar: &Scalar) {
|
fn append_scalar(&mut self, label: &'static [u8], scalar: &Scalar) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#[cfg(not(target_arch = "bpf"))]
|
#[cfg(not(target_arch = "bpf"))]
|
||||||
use {
|
use {
|
||||||
crate::encryption::{
|
crate::encryption::{
|
||||||
elgamal::{ElGamalCiphertext, ElGamalKeypair, ElGamalPubkey},
|
elgamal::{ElGamalKeypair, ElGamalPubkey},
|
||||||
pedersen::{PedersenBase, PedersenCommitment, PedersenDecryptHandle, PedersenOpening},
|
pedersen::{PedersenBase, PedersenCommitment, PedersenDecryptHandle, PedersenOpening},
|
||||||
},
|
},
|
||||||
curve25519_dalek::traits::MultiscalarMul,
|
curve25519_dalek::traits::MultiscalarMul,
|
||||||
|
@ -62,8 +62,6 @@ impl ValidityProof {
|
||||||
let c = transcript.challenge_scalar(b"c");
|
let c = transcript.challenge_scalar(b"c");
|
||||||
transcript.challenge_scalar(b"w");
|
transcript.challenge_scalar(b"w");
|
||||||
|
|
||||||
println!("prover: {:?}", t);
|
|
||||||
|
|
||||||
// aggregate lo and hi messages and openings
|
// aggregate lo and hi messages and openings
|
||||||
let x = Scalar::from(messages.0) + t * Scalar::from(messages.1);
|
let x = Scalar::from(messages.0) + t * Scalar::from(messages.1);
|
||||||
let r = openings.0.get_scalar() + t * openings.1.get_scalar();
|
let r = openings.0.get_scalar() + t * openings.1.get_scalar();
|
||||||
|
@ -104,8 +102,6 @@ impl ValidityProof {
|
||||||
let w = transcript.challenge_scalar(b"w");
|
let w = transcript.challenge_scalar(b"w");
|
||||||
let ww = w * w;
|
let ww = w * w;
|
||||||
|
|
||||||
println!("verifier: {:?}", t);
|
|
||||||
|
|
||||||
// check the required algebraic conditions
|
// check the required algebraic conditions
|
||||||
let Y_0 = self.Y_0.decompress().ok_or(ProofError::VerificationError)?;
|
let Y_0 = self.Y_0.decompress().ok_or(ProofError::VerificationError)?;
|
||||||
let Y_1 = self.Y_1.decompress().ok_or(ProofError::VerificationError)?;
|
let Y_1 = self.Y_1.decompress().ok_or(ProofError::VerificationError)?;
|
||||||
|
|
|
@ -23,6 +23,7 @@ mod target_arch {
|
||||||
equality_proof::EqualityProof,
|
equality_proof::EqualityProof,
|
||||||
errors::ProofError,
|
errors::ProofError,
|
||||||
range_proof::RangeProof,
|
range_proof::RangeProof,
|
||||||
|
validity_proof::ValidityProof,
|
||||||
},
|
},
|
||||||
curve25519_dalek::{ristretto::CompressedRistretto, scalar::Scalar},
|
curve25519_dalek::{ristretto::CompressedRistretto, scalar::Scalar},
|
||||||
std::convert::TryFrom,
|
std::convert::TryFrom,
|
||||||
|
@ -155,6 +156,20 @@ mod target_arch {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<ValidityProof> for pod::ValidityProof {
|
||||||
|
fn from(proof: ValidityProof) -> Self {
|
||||||
|
Self(proof.to_bytes())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<pod::ValidityProof> for ValidityProof {
|
||||||
|
type Error = ProofError;
|
||||||
|
|
||||||
|
fn try_from(pod: pod::ValidityProof) -> Result<Self, Self::Error> {
|
||||||
|
Self::from_bytes(&pod.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl TryFrom<RangeProof> for pod::RangeProof64 {
|
impl TryFrom<RangeProof> for pod::RangeProof64 {
|
||||||
type Error = ProofError;
|
type Error = ProofError;
|
||||||
|
|
||||||
|
|
|
@ -54,11 +54,22 @@ impl fmt::Debug for PedersenDecryptHandle {
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct EqualityProof(pub [u8; 192]);
|
pub struct EqualityProof(pub [u8; 192]);
|
||||||
|
|
||||||
// `PodRangeProof64` is a Pod and Zeroable.
|
// `EqualityProof` is a Pod and Zeroable.
|
||||||
// Add the marker traits manually because `bytemuck` only adds them for some `u8` arrays
|
// Add the marker traits manually because `bytemuck` only adds them for some `u8` arrays
|
||||||
unsafe impl Zeroable for EqualityProof {}
|
unsafe impl Zeroable for EqualityProof {}
|
||||||
unsafe impl Pod for EqualityProof {}
|
unsafe impl Pod for EqualityProof {}
|
||||||
|
|
||||||
|
/// Serialization of validity proofs
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct ValidityProof(pub [u8; 160]);
|
||||||
|
|
||||||
|
// `ValidityProof` is a Pod and Zeroable.
|
||||||
|
// Add the marker traits manually because `bytemuck` only adds them for some `u8` arrays
|
||||||
|
unsafe impl Zeroable for ValidityProof {}
|
||||||
|
unsafe impl Pod for ValidityProof {}
|
||||||
|
|
||||||
|
|
||||||
/// Serialization of range proofs for 64-bit numbers (for `Withdraw` instruction)
|
/// Serialization of range proofs for 64-bit numbers (for `Withdraw` instruction)
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
|
|
Loading…
Reference in New Issue