zkSNARK: Enforce merkle authentication path from nonzero-valued public inputs to root.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#include "zcash/circuit/utils.tcc"
|
||||
#include "zcash/circuit/prfs.tcc"
|
||||
#include "zcash/circuit/commitment.tcc"
|
||||
#include "zcash/circuit/merkle.tcc"
|
||||
#include "zcash/circuit/note.tcc"
|
||||
|
||||
template<typename FieldT, size_t NumInputs, size_t NumOutputs>
|
||||
@@ -94,7 +95,8 @@ public:
|
||||
zk_input_notes[i].reset(new input_note_gadget<FieldT>(
|
||||
pb,
|
||||
ZERO,
|
||||
zk_input_nullifiers[i]
|
||||
zk_input_nullifiers[i],
|
||||
*zk_merkle_root
|
||||
));
|
||||
|
||||
// The input keys authenticate h_sig to prevent
|
||||
@@ -180,6 +182,16 @@ public:
|
||||
// Witness `zero`
|
||||
this->pb.val(ZERO) = FieldT::zero();
|
||||
|
||||
// Witness rt. This is not a sanity check.
|
||||
//
|
||||
// This ensures the read gadget constrains
|
||||
// the intended root in the event that
|
||||
// both inputs are zero-valued.
|
||||
zk_merkle_root->bits.fill_with_bits(
|
||||
this->pb,
|
||||
uint256_to_bool_vector(rt)
|
||||
);
|
||||
|
||||
// Witness public balance values
|
||||
zk_vpub_old.fill_with_bits(
|
||||
this->pb,
|
||||
@@ -204,7 +216,12 @@ public:
|
||||
|
||||
for (size_t i = 0; i < NumInputs; i++) {
|
||||
// Witness the input information.
|
||||
zk_input_notes[i]->generate_r1cs_witness(inputs[i].key, inputs[i].note);
|
||||
auto merkle_path = inputs[i].witness.path();
|
||||
zk_input_notes[i]->generate_r1cs_witness(
|
||||
merkle_path,
|
||||
inputs[i].key,
|
||||
inputs[i].note
|
||||
);
|
||||
|
||||
// Witness hmacs
|
||||
zk_hmac_authentication[i]->generate_r1cs_witness();
|
||||
@@ -215,6 +232,17 @@ public:
|
||||
zk_output_notes[i]->generate_r1cs_witness(outputs[i]);
|
||||
}
|
||||
|
||||
// [SANITY CHECK] Ensure that the intended root
|
||||
// was witnessed by the inputs, even if the read
|
||||
// gadget overwrote it. This allows the prover to
|
||||
// fail instead of the verifier, in the event that
|
||||
// the roots of the inputs do not match the
|
||||
// treestate provided to the proving API.
|
||||
zk_merkle_root->bits.fill_with_bits(
|
||||
this->pb,
|
||||
uint256_to_bool_vector(rt)
|
||||
);
|
||||
|
||||
// This happens last, because only by now are all the
|
||||
// verifier inputs resolved.
|
||||
unpacker->generate_r1cs_witness_from_bits();
|
||||
@@ -231,7 +259,7 @@ public:
|
||||
) {
|
||||
std::vector<bool> verify_inputs;
|
||||
|
||||
insert_uint256(verify_inputs, uint256()); // TODO: rt
|
||||
insert_uint256(verify_inputs, rt);
|
||||
insert_uint256(verify_inputs, h_sig);
|
||||
|
||||
for (size_t i = 0; i < NumInputs; i++) {
|
||||
|
||||
Reference in New Issue
Block a user