incorporate validity proof into transfer proof

This commit is contained in:
Sam Kim 2021-12-12 10:23:10 -05:00 committed by Michael Vines
parent c7bf9958e7
commit 30871784e4
5 changed files with 82 additions and 21 deletions

View File

@ -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(

View File

@ -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) {

View File

@ -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)?;

View File

@ -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;

View File

@ -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)]