Skip to content

Commit

Permalink
full_exit
Browse files Browse the repository at this point in the history
  • Loading branch information
TymurKhr committed Sep 19, 2019
1 parent 0b2b637 commit 63d4dca
Show file tree
Hide file tree
Showing 16 changed files with 366 additions and 183 deletions.
19 changes: 9 additions & 10 deletions core/circuit/src/allocated_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ pub struct AllocatedChunkData<E: JubjubEngine> {
#[derive(Clone)]
pub struct AllocatedOperationData<E: JubjubEngine> {
// pub new_pubkey: CircuitPubkey<E>,
pub signer_pubkey: CircuitPubkey<E>,
// pub signer_pubkey: CircuitPubkey<E>,
pub amount_packed: CircuitElement<E>,
pub fee_packed: CircuitElement<E>,
pub amount_unpacked: CircuitElement<E>,
Expand All @@ -101,6 +101,7 @@ pub struct AllocatedOperationData<E: JubjubEngine> {
pub third_sig_msg: CircuitElement<E>,
pub new_pubkey_hash: CircuitElement<E>,
pub ethereum_key: CircuitElement<E>,
pub pub_nonce: CircuitElement<E>,
pub a: CircuitElement<E>,
pub b: CircuitElement<E>,
}
Expand Down Expand Up @@ -178,21 +179,18 @@ impl<E: JubjubEngine> AllocatedOperationData<E> {
franklin_constants::MAX_CIRCUIT_PEDERSEN_HASH_BITS - (2 * E::Fr::CAPACITY as usize), //TODO: think of more consistent constant flow
)?;

let sig_pubkey = CircuitPubkey::from_xy_fe(
cs.namespace(|| "signer_pubkey"),
|| op.signer_pub_key_x.grab(),
|| op.signer_pub_key_y.grab(),
&params,
)?;

let new_pubkey_hash = CircuitElement::from_fe_strict(
cs.namespace(|| "new_pubkey_hash"),
|| op.args.new_pub_key_hash.grab(),
franklin_constants::NEW_PUBKEY_HASH_WIDTH,
)?;

// let new_pubkey_hash = new_pubkey.get_hash().clone();

let pub_nonce = CircuitElement::from_fe_strict(
cs.namespace(|| "pub_nonce"),
|| op.args.pub_nonce.grab(),
franklin_constants::NONCE_BIT_WIDTH,
)?;
let a = CircuitElement::from_fe_strict(
cs.namespace(|| "a"),
|| op.args.a.grab(),
Expand All @@ -206,7 +204,8 @@ impl<E: JubjubEngine> AllocatedOperationData<E> {

Ok(AllocatedOperationData {
ethereum_key,
signer_pubkey: sig_pubkey,
// signer_pubkey: sig_pubkey,
pub_nonce,
amount_packed,
fee_packed,
fee,
Expand Down
61 changes: 45 additions & 16 deletions core/circuit/src/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,13 @@ impl<'a, E: JubjubEngine> Circuit<E> for FranklinCircuit<'a, E> {
op_data: AllocatedOperationData {
ethereum_key: zero_circuit_element.clone(),
new_pubkey_hash: zero_circuit_element.clone(),
signer_pubkey: CircuitPubkey::from_xy(
cs.namespace(|| "dummy signer_pubkey"),
zero_circuit_element.get_number(),
zero_circuit_element.get_number(),
&self.params,
)?,
// signer_pubkey: CircuitPubkey::from_xy(
// cs.namespace(|| "dummy signer_pubkey"),
// zero_circuit_element.get_number(),
// zero_circuit_element.get_number(),
// &self.params,
// )?,
pub_nonce: zero_circuit_element.clone(),
amount_packed: zero_circuit_element.clone(),
full_amount: zero_circuit_element.clone(),
fee_packed: zero_circuit_element.clone(),
Expand Down Expand Up @@ -602,9 +603,15 @@ impl<'a, E: JubjubEngine> FranklinCircuit<'a, E> {
}
prev.op_data = op_data.clone();

let signer_key = unpack_point_if_possible(
cs.namespace(|| "unpack pubkey"),
&op.signer_pub_key_packed,
self.params,
)?;
let signature_data = verify_circuit_signature(
cs.namespace(|| "verify circuit signature"),
&op_data,
&signer_key,
op.signature_data.clone(),
self.params,
generator.clone(),
Expand Down Expand Up @@ -640,6 +647,7 @@ impl<'a, E: JubjubEngine> FranklinCircuit<'a, E> {
&is_a_geq_b,
&is_account_empty,
&op_data,
&signer_key,
&ext_pubdata_chunk,
&signature_data.is_verified,
)?);
Expand All @@ -652,6 +660,7 @@ impl<'a, E: JubjubEngine> FranklinCircuit<'a, E> {
&is_a_geq_b,
&is_account_empty,
&op_data,
&signer_key,
&ext_pubdata_chunk,
&signature_data.is_verified,
)?);
Expand All @@ -661,6 +670,7 @@ impl<'a, E: JubjubEngine> FranklinCircuit<'a, E> {
&chunk_data,
&is_a_geq_b,
&op_data,
&signer_key,
&ext_pubdata_chunk,
&signature_data.is_verified,
)?);
Expand All @@ -670,6 +680,7 @@ impl<'a, E: JubjubEngine> FranklinCircuit<'a, E> {
&chunk_data,
&ext_pubdata_chunk,
&op_data,
&signer_key,
&subtree_root,
&signature_data.is_verified,
)?);
Expand All @@ -678,6 +689,7 @@ impl<'a, E: JubjubEngine> FranklinCircuit<'a, E> {
&mut cur,
&chunk_data,
&op_data,
&signer_key,
&ext_pubdata_chunk,
&signature_data,
)?);
Expand Down Expand Up @@ -725,6 +737,7 @@ impl<'a, E: JubjubEngine> FranklinCircuit<'a, E> {
chunk_data: &AllocatedChunkData<E>,
is_a_geq_b: &Boolean,
op_data: &AllocatedOperationData<E>,
signer_key: &AllocatedSignerPubkey<E>,
ext_pubdata_chunk: &AllocatedNum<E>,
is_sig_verified: &Boolean,
) -> Result<Boolean, SynthesisError> {
Expand Down Expand Up @@ -803,7 +816,7 @@ impl<'a, E: JubjubEngine> FranklinCircuit<'a, E> {

let is_signer_valid = CircuitElement::equals(
cs.namespace(|| "signer_key_correect"),
&op_data.signer_pubkey.get_hash(),
&signer_key.pubkey.get_hash(),
&op_data.new_pubkey_hash, //earlier we ensured that this new_pubkey_hash is equal to current if existed
)?;
base_valid_flags.push(is_signer_valid);
Expand Down Expand Up @@ -882,6 +895,7 @@ impl<'a, E: JubjubEngine> FranklinCircuit<'a, E> {
cur: &mut AllocatedOperationBranch<E>,
chunk_data: &AllocatedChunkData<E>,
op_data: &AllocatedOperationData<E>,
signer_key: &AllocatedSignerPubkey<E>,
ext_pubdata_chunk: &AllocatedNum<E>,
signature: &AllocatedSignatureData<E>,
) -> Result<Boolean, SynthesisError> {
Expand Down Expand Up @@ -914,15 +928,19 @@ impl<'a, E: JubjubEngine> FranklinCircuit<'a, E> {
&[is_serialized_tx_correct, is_first_chunk.clone().not()],
)?;

let _is_signer_valid = CircuitElement::equals(
let is_signer_valid = CircuitElement::equals(
cs.namespace(|| "signer_key_correect"),
&op_data.signer_pubkey.get_hash(),
&signer_key.pubkey.get_hash(),
&op_data.new_pubkey_hash, //earlier we ensured that this new_pubkey_hash is equal to current if existed
)?;

let is_signed_correctly = multi_and(
cs.namespace(|| "is_signed_correctly"),
&[is_serialized_tx_correct, signature.is_verified.clone()],
&[
is_serialized_tx_correct,
is_signer_valid,
signature.is_verified.clone(),
],
)?;

let amount_to_exit = CircuitElement::conditionally_select_with_number_strict(
Expand All @@ -937,23 +955,26 @@ impl<'a, E: JubjubEngine> FranklinCircuit<'a, E> {

pubdata_bits.extend(chunk_data.tx_type.get_bits_be()); //1
pubdata_bits.extend(cur.account_address.get_bits_be()); //3
pubdata_bits.extend(vec![signer_key.r_x_bit.clone()]);
pubdata_bits.extend(signer_key.r_y_bits.clone());
pubdata_bits.extend(op_data.ethereum_key.get_bits_be()); //20
pubdata_bits.extend(cur.token.get_bits_be()); // 2
pubdata_bits.extend(op_data.pub_nonce.get_bits_be()); // 2
pubdata_bits.extend(vec![signature.sig_r_x_bit.clone()]);
pubdata_bits.extend(signature.sig_r_y_bits.clone());
pubdata_bits.extend(signature.sig_s_bits.clone());
pubdata_bits.extend(op_data.full_amount.get_bits_be());

pubdata_bits.resize(
10 * franklin_constants::CHUNK_BIT_WIDTH,
18 * franklin_constants::CHUNK_BIT_WIDTH,
Boolean::constant(false),
);

let pubdata_chunk = select_pubdata_chunk(
cs.namespace(|| "select_pubdata_chunk"),
&pubdata_bits,
&chunk_data.chunk_number,
10,
18,
)?;

let is_pubdata_chunk_correct = Boolean::from(Expression::equals(
Expand All @@ -980,7 +1001,12 @@ impl<'a, E: JubjubEngine> FranklinCircuit<'a, E> {
lhs_valid_flags.push(is_first_chunk.clone());

lhs_valid_flags.push(is_base_valid.clone());

let is_nonce_correct = CircuitElement::equals(
cs.namespace(|| "is_nonce_correct"),
&cur.account.nonce,
&op_data.pub_nonce,
)?;
lhs_valid_flags.push(is_nonce_correct);
lhs_valid_flags.push(no_nonce_overflow(
cs.namespace(|| "no nonce overflow"),
&cur.account.nonce.get_number(),
Expand Down Expand Up @@ -1138,6 +1164,7 @@ impl<'a, E: JubjubEngine> FranklinCircuit<'a, E> {
chunk_data: &AllocatedChunkData<E>,
ext_pubdata_chunk: &AllocatedNum<E>,
op_data: &AllocatedOperationData<E>,
signer_key: &AllocatedSignerPubkey<E>,
subtree_root: &CircuitElement<E>,
is_sig_verified: &Boolean,
) -> Result<Boolean, SynthesisError> {
Expand Down Expand Up @@ -1200,7 +1227,7 @@ impl<'a, E: JubjubEngine> FranklinCircuit<'a, E> {
is_valid_flags.push(is_sig_verified.clone());
let _is_signer_valid = CircuitElement::equals(
cs.namespace(|| "signer_key_correect"),
&op_data.signer_pubkey.get_hash(),
&signer_key.pubkey.get_hash(),
&cur.account.pub_key_hash, //earlier we ensured that this new_pubkey_hash is equal to current if existed
)?;

Expand Down Expand Up @@ -1278,6 +1305,7 @@ impl<'a, E: JubjubEngine> FranklinCircuit<'a, E> {
is_a_geq_b: &Boolean,
is_account_empty: &Boolean,
op_data: &AllocatedOperationData<E>,
signer_key: &AllocatedSignerPubkey<E>,
ext_pubdata_chunk: &AllocatedNum<E>,
is_sig_verified: &Boolean,
) -> Result<Boolean, SynthesisError> {
Expand Down Expand Up @@ -1376,7 +1404,7 @@ impl<'a, E: JubjubEngine> FranklinCircuit<'a, E> {

let _is_signer_valid = CircuitElement::equals(
cs.namespace(|| "signer_key_correect"),
&op_data.signer_pubkey.get_hash(),
&signer_key.pubkey.get_hash(),
&lhs.account.pub_key_hash,
)?;

Expand Down Expand Up @@ -1460,6 +1488,7 @@ impl<'a, E: JubjubEngine> FranklinCircuit<'a, E> {
is_a_geq_b: &Boolean,
is_account_empty: &Boolean,
op_data: &AllocatedOperationData<E>,
signer_key: &AllocatedSignerPubkey<E>,
ext_pubdata_chunk: &AllocatedNum<E>,
is_sig_verified: &Boolean,
) -> Result<Boolean, SynthesisError> {
Expand Down Expand Up @@ -1553,7 +1582,7 @@ impl<'a, E: JubjubEngine> FranklinCircuit<'a, E> {

let is_signer_valid = CircuitElement::equals(
cs.namespace(|| "signer_key_correct"),
&op_data.signer_pubkey.get_hash(),
&signer_key.pubkey.get_hash(),
&lhs.account.pub_key_hash,
)?;
lhs_valid_flags.push(is_signer_valid);
Expand Down
6 changes: 4 additions & 2 deletions core/circuit/src/operation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ pub struct Operation<E: JubjubEngine> {
pub tx_type: Option<E::Fr>,
pub chunk: Option<E::Fr>,
pub pubdata_chunk: Option<E::Fr>,
pub signer_pub_key_x: Option<E::Fr>,
pub signer_pub_key_y: Option<E::Fr>,
pub signer_pub_key_packed: Vec<Option<bool>>,
// pub signer_pub_key_x: Option<E::Fr>,
// pub signer_pub_key_y: Option<E::Fr>,
pub first_sig_msg: Option<E::Fr>,
pub second_sig_msg: Option<E::Fr>,
pub third_sig_msg: Option<E::Fr>,
Expand All @@ -47,6 +48,7 @@ pub struct OperationArguments<E: JubjubEngine> {
pub fee: Option<E::Fr>,
pub new_pub_key_hash: Option<E::Fr>,
pub ethereum_key: Option<E::Fr>,
pub pub_nonce: Option<E::Fr>,
}

#[derive(Clone)]
Expand Down
69 changes: 57 additions & 12 deletions core/circuit/src/signature.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::allocated_structures::*;
use crate::element::CircuitElement;
use crate::element::{CircuitElement, CircuitPubkey};
use crate::operation::SignatureData;
use crate::utils::{multi_and, pack_bits_to_element};
use bellman::{ConstraintSystem, SynthesisError};
Expand All @@ -21,9 +21,58 @@ pub struct AllocatedSignatureData<E: JubjubEngine> {
pub sig_s_bits: Vec<Boolean>,
}

pub struct AllocatedSignerPubkey<E: JubjubEngine> {
pub pubkey: CircuitPubkey<E>,
pub point: ecc::EdwardsPoint<E>,
pub is_correctly_unpacked: Boolean,
pub r_y_bits: Vec<Boolean>,
pub r_x_bit: Boolean,
}
pub fn unpack_point_if_possible<E: JubjubEngine, CS: ConstraintSystem<E>>(
mut cs: CS,
packed_key: &[Option<bool>],
params: &E::Params,
) -> Result<AllocatedSignerPubkey<E>, SynthesisError> {
assert_eq!(packed_key.len(), franklin_constants::FR_BIT_WIDTH_PADDED);
let r_x_bit = AllocatedBit::alloc(cs.namespace(|| "r_x_bit"), packed_key[0])?;

// let mut r_y_value = signature_data.r_packed.clone();
// r_y_value.truncate(franklin_constants::FR_BIT_WIDTH_PADDED - 2);

let r_y = CircuitElement::from_witness_be_bits(
cs.namespace(|| "signature_r_y from bits"),
&packed_key[1..],
)?;
// let r_y = r_y.pad(franklin_constants::FR_BIT_WIDTH_PADDED - 1);

let (r_recovered, is_r_correct) = ecc::EdwardsPoint::recover_from_y_unchecked(
cs.namespace(|| "recover_from_y_unchecked"),
&Boolean::from(r_x_bit.clone()),
&r_y.get_number(),
&params,
)?;

// let mut packed_bits = vec![];
// packed_bits.push(Boolean::from(r_x_bit));
// packed_bits.extend(r_y.get_bits_be());
let pubkey = CircuitPubkey::from_xy(
cs.namespace(|| "pubkey from xy"),
r_recovered.get_x().clone(),
r_recovered.get_y().clone(),
&params,
)?;
Ok(AllocatedSignerPubkey {
pubkey,
point: r_recovered,
is_correctly_unpacked: is_r_correct,
r_x_bit: Boolean::from(r_x_bit),
r_y_bits: r_y.get_bits_be(),
})
}
pub fn verify_circuit_signature<E: JubjubEngine, CS: ConstraintSystem<E>>(
mut cs: CS,
op_data: &AllocatedOperationData<E>,
signer_key: &AllocatedSignerPubkey<E>,
signature_data: SignatureData,
params: &E::Params,
generator: ecc::EdwardsPoint<E>,
Expand Down Expand Up @@ -56,17 +105,11 @@ pub fn verify_circuit_signature<E: JubjubEngine, CS: ConstraintSystem<E>>(
&r_y.get_number(),
&params,
)?;
let signer_pk = ecc::EdwardsPoint::interpret(
cs.namespace(|| "signer public key"),
&op_data.signer_pubkey.get_x().get_number(),
&op_data.signer_pubkey.get_y().get_number(),
&params,
)?;

let signature = EddsaSignature {
r: r_recovered,
s: signature_s.get_number(),
pk: signer_pk,
pk: signer_key.point.clone(),
};
println!(
"r_x={:?} r_y={:?}",
Expand Down Expand Up @@ -107,11 +150,13 @@ pub fn verify_circuit_signature<E: JubjubEngine, CS: ConstraintSystem<E>>(
params,
generator,
)?;

let is_signature_correctly_verified = Boolean::and(
let is_signature_correctly_verified = multi_and(
cs.namespace(|| "is_signature_correctly_verified"),
&is_sig_verified,
&is_sig_r_correct,
&[
is_sig_verified,
is_sig_r_correct,
signer_key.is_correctly_unpacked.clone(),
],
)?;

Ok(AllocatedSignatureData {
Expand Down
Loading

0 comments on commit 63d4dca

Please sign in to comment.