incorporate validity proof into transfer proof
This commit is contained in:
parent
c7bf9958e7
commit
30871784e4
|
@ -15,6 +15,7 @@ use {
|
|||
instruction::{Role, Verifiable},
|
||||
range_proof::RangeProof,
|
||||
transcript::TranscriptProtocol,
|
||||
validity_proof::ValidityProof,
|
||||
},
|
||||
curve25519_dalek::scalar::Scalar,
|
||||
merlin::Transcript,
|
||||
|
@ -117,8 +118,7 @@ impl TransferData {
|
|||
&dest_pk,
|
||||
&auditor_pk,
|
||||
(amount_lo as u64, amount_hi as u64),
|
||||
&open_lo,
|
||||
&open_hi,
|
||||
(&open_lo, &open_hi),
|
||||
new_spendable_balance,
|
||||
&new_spendable_ct,
|
||||
);
|
||||
|
@ -205,6 +205,9 @@ pub struct TransferProof {
|
|||
/// Associated equality proof
|
||||
pub equality_proof: pod::EqualityProof,
|
||||
|
||||
/// Associated ciphertext validity proof
|
||||
pub validity_proof: pod::ValidityProof,
|
||||
|
||||
// Associated range proof
|
||||
pub range_proof: pod::RangeProof128,
|
||||
}
|
||||
|
@ -220,11 +223,10 @@ impl TransferProof {
|
|||
#[allow(clippy::many_single_char_names)]
|
||||
pub fn new(
|
||||
source_keypair: &ElGamalKeypair,
|
||||
_dest_pk: &ElGamalPubkey,
|
||||
_auditor_pk: &ElGamalPubkey,
|
||||
dest_pk: &ElGamalPubkey,
|
||||
auditor_pk: &ElGamalPubkey,
|
||||
transfer_amt: (u64, u64),
|
||||
lo_open: &PedersenOpening,
|
||||
hi_open: &PedersenOpening,
|
||||
openings: (&PedersenOpening, &PedersenOpening),
|
||||
source_new_balance: u64,
|
||||
source_new_balance_ct: &ElGamalCiphertext,
|
||||
) -> Self {
|
||||
|
@ -260,19 +262,27 @@ impl TransferProof {
|
|||
&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
|
||||
let range_proof = RangeProof::create(
|
||||
vec![source_new_balance, transfer_amt.0, transfer_amt.1],
|
||||
vec![64, 32, 32],
|
||||
vec![&source_open, lo_open, hi_open],
|
||||
vec![&source_open, openings.0, openings.1],
|
||||
&mut transcript,
|
||||
);
|
||||
|
||||
Self {
|
||||
source_commitment: source_commitment.into(),
|
||||
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"),
|
||||
}
|
||||
}
|
||||
|
@ -280,8 +290,8 @@ impl TransferProof {
|
|||
pub fn verify(
|
||||
self,
|
||||
amount_comms: &TransferCommitments,
|
||||
_decryption_handles_lo: &TransferDecryptHandles,
|
||||
_decryption_handles_hi: &TransferDecryptHandles,
|
||||
decryption_handles_lo: &TransferDecryptHandles,
|
||||
decryption_handles_hi: &TransferDecryptHandles,
|
||||
new_spendable_ct: &pod::ElGamalCiphertext,
|
||||
transfer_public_keys: &TransferPubkeys,
|
||||
) -> Result<(), ProofError> {
|
||||
|
@ -289,6 +299,7 @@ impl TransferProof {
|
|||
|
||||
let commitment: PedersenCommitment = self.source_commitment.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()?;
|
||||
|
||||
// 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
|
||||
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
|
||||
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
|
||||
range_proof.verify(
|
||||
|
|
|
@ -6,11 +6,11 @@ use {
|
|||
|
||||
pub trait TranscriptProtocol {
|
||||
/// 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);
|
||||
|
||||
/// 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);
|
||||
|
||||
/// 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.
|
||||
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.
|
||||
fn withdraw_proof_domain_sep(&mut self);
|
||||
|
||||
|
@ -60,15 +63,19 @@ impl TranscriptProtocol for Transcript {
|
|||
}
|
||||
|
||||
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) {
|
||||
self.append_message(b"dom_sep", b"WithdrawProof");
|
||||
self.append_message(b"dom-sep", b"WithdrawProof");
|
||||
}
|
||||
|
||||
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) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#[cfg(not(target_arch = "bpf"))]
|
||||
use {
|
||||
crate::encryption::{
|
||||
elgamal::{ElGamalCiphertext, ElGamalKeypair, ElGamalPubkey},
|
||||
elgamal::{ElGamalKeypair, ElGamalPubkey},
|
||||
pedersen::{PedersenBase, PedersenCommitment, PedersenDecryptHandle, PedersenOpening},
|
||||
},
|
||||
curve25519_dalek::traits::MultiscalarMul,
|
||||
|
@ -62,8 +62,6 @@ impl ValidityProof {
|
|||
let c = transcript.challenge_scalar(b"c");
|
||||
transcript.challenge_scalar(b"w");
|
||||
|
||||
println!("prover: {:?}", t);
|
||||
|
||||
// aggregate lo and hi messages and openings
|
||||
let x = Scalar::from(messages.0) + t * Scalar::from(messages.1);
|
||||
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 ww = w * w;
|
||||
|
||||
println!("verifier: {:?}", t);
|
||||
|
||||
// check the required algebraic conditions
|
||||
let Y_0 = self.Y_0.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,
|
||||
errors::ProofError,
|
||||
range_proof::RangeProof,
|
||||
validity_proof::ValidityProof,
|
||||
},
|
||||
curve25519_dalek::{ristretto::CompressedRistretto, scalar::Scalar},
|
||||
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 {
|
||||
type Error = ProofError;
|
||||
|
||||
|
|
|
@ -54,11 +54,22 @@ impl fmt::Debug for PedersenDecryptHandle {
|
|||
#[repr(transparent)]
|
||||
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
|
||||
unsafe impl Zeroable 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)
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(transparent)]
|
||||
|
|
Loading…
Reference in New Issue