From dbab243725ba4aa5cee06eadd5d94b8c5ba0b8a9 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Wed, 4 May 2016 18:26:13 -0600 Subject: [PATCH] zkSNARK: Add constraint that the total value in a JoinSplit is a 64-bit integer. --- src/zcash/circuit/gadget.tcc | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/zcash/circuit/gadget.tcc b/src/zcash/circuit/gadget.tcc index f463600df..abfa1cad4 100644 --- a/src/zcash/circuit/gadget.tcc +++ b/src/zcash/circuit/gadget.tcc @@ -23,6 +23,7 @@ private: // Aux inputs pb_variable ZERO; std::shared_ptr> zk_phi; + pb_variable_array zk_total_uint64; // Input note gadgets boost::array>, NumInputs> zk_input_notes; @@ -89,6 +90,8 @@ public: zk_phi.reset(new digest_variable(pb, 252, "")); + zk_total_uint64.allocate(pb, 64); + for (size_t i = 0; i < NumInputs; i++) { // Input note gadget for commitments, hmacs, nullifiers, // and spend authority. @@ -166,7 +169,20 @@ public: right_side )); - // TODO: #854 + // #854: Ensure that left_side is a 64-bit integer. + for (size_t i = 0; i < 64; i++) { + generate_boolean_r1cs_constraint( + this->pb, + zk_total_uint64[i], + "" + ); + } + + this->pb.add_r1cs_constraint(r1cs_constraint( + 1, + left_side, + packed_addition(zk_total_uint64) + )); } } @@ -202,6 +218,19 @@ public: uint64_to_bool_vector(vpub_new) ); + { + // Witness total_uint64 bits + uint64_t left_side_acc = vpub_old; + for (size_t i = 0; i < NumInputs; i++) { + left_side_acc += inputs[i].note.value; + } + + zk_total_uint64.fill_with_bits( + this->pb, + uint64_to_bool_vector(left_side_acc) + ); + } + // Witness phi zk_phi->bits.fill_with_bits( this->pb, @@ -317,4 +346,4 @@ public: integer.allocate(this->pb, 64, ""); packed_into.insert(packed_into.end(), integer.begin(), integer.end()); } -}; \ No newline at end of file +};