diff --git a/src/zcash/circuit/gadget.tcc b/src/zcash/circuit/gadget.tcc index dc0fad918..0f8d6fa48 100644 --- a/src/zcash/circuit/gadget.tcc +++ b/src/zcash/circuit/gadget.tcc @@ -77,7 +77,8 @@ public: // and spend authority. zk_input_notes[i].reset(new input_note_gadget( pb, - ZERO + ZERO, + zk_input_nullifiers[i] )); } } @@ -133,7 +134,7 @@ public: insert_uint256(verify_inputs, uint256()); // TODO: h_sig for (size_t i = 0; i < NumInputs; i++) { - insert_uint256(verify_inputs, uint256()); // TODO: nullifier + insert_uint256(verify_inputs, nullifiers[i]); insert_uint256(verify_inputs, uint256()); // TODO: hmac } diff --git a/src/zcash/circuit/note.tcc b/src/zcash/circuit/note.tcc index ab29f4098..33987dd3c 100644 --- a/src/zcash/circuit/note.tcc +++ b/src/zcash/circuit/note.tcc @@ -32,33 +32,48 @@ class input_note_gadget : public note_gadget { public: std::shared_ptr> a_sk; std::shared_ptr> a_pk; + std::shared_ptr> rho; std::shared_ptr> spend_authority; + std::shared_ptr> expose_nullifiers; input_note_gadget( protoboard& pb, - pb_variable& ZERO + pb_variable& ZERO, + std::shared_ptr> nullifier ) : note_gadget(pb) { a_sk.reset(new digest_variable(pb, 252, "")); a_pk.reset(new digest_variable(pb, 256, "")); + rho.reset(new digest_variable(pb, 256, "")); + spend_authority.reset(new PRF_addr_a_pk_gadget( pb, ZERO, a_sk->bits, a_pk )); + + expose_nullifiers.reset(new PRF_nf_gadget( + pb, + ZERO, + a_sk->bits, + rho->bits, + nullifier + )); } void generate_r1cs_constraints() { note_gadget::generate_r1cs_constraints(); a_sk->generate_r1cs_constraints(); + rho->generate_r1cs_constraints(); // TODO: This constraint may not be necessary if SHA256 // already boolean constrains its outputs. a_pk->generate_r1cs_constraints(); spend_authority->generate_r1cs_constraints(); + expose_nullifiers->generate_r1cs_constraints(); } void generate_r1cs_witness(const SpendingKey& key, const Note& note) { @@ -78,5 +93,14 @@ public: this->pb, uint256_to_bool_vector(note.a_pk) ); + + // Witness rho for the input note + rho->bits.fill_with_bits( + this->pb, + uint256_to_bool_vector(note.rho) + ); + + // Witness the nullifier for the input note + expose_nullifiers->generate_r1cs_witness(); } }; diff --git a/src/zcash/circuit/prfs.tcc b/src/zcash/circuit/prfs.tcc index 64cd7619d..215eebf59 100644 --- a/src/zcash/circuit/prfs.tcc +++ b/src/zcash/circuit/prfs.tcc @@ -75,3 +75,23 @@ public: PRF_gadget::generate_r1cs_witness(); } }; + +template +class PRF_nf_gadget : public PRF_gadget { +public: + PRF_nf_gadget( + protoboard& pb, + pb_variable& ZERO, + pb_variable_array& a_sk, + pb_variable_array& rho, + std::shared_ptr> result + ) : PRF_gadget(pb, ZERO, 1, 1, 1, 0, a_sk, rho, result) {} + + void generate_r1cs_constraints() { + PRF_gadget::generate_r1cs_constraints(); + } + + void generate_r1cs_witness() { + PRF_gadget::generate_r1cs_witness(); + } +};