zkSNARK: Authenticate h_sig with a_sk
This commit is contained in:
parent
2a2f3fb80f
commit
e52f40e839
|
@ -23,8 +23,13 @@ private:
|
||||||
|
|
||||||
// Input note gadgets
|
// Input note gadgets
|
||||||
boost::array<std::shared_ptr<input_note_gadget<FieldT>>, NumInputs> zk_input_notes;
|
boost::array<std::shared_ptr<input_note_gadget<FieldT>>, NumInputs> zk_input_notes;
|
||||||
|
boost::array<std::shared_ptr<PRF_pk_gadget<FieldT>>, NumInputs> zk_hmac_authentication;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
// PRF_pk only has a 1-bit domain separation "nonce"
|
||||||
|
// for different hmacs.
|
||||||
|
BOOST_STATIC_ASSERT(NumInputs <= 2);
|
||||||
|
|
||||||
joinsplit_gadget(protoboard<FieldT> &pb) : gadget<FieldT>(pb) {
|
joinsplit_gadget(protoboard<FieldT> &pb) : gadget<FieldT>(pb) {
|
||||||
// Verification
|
// Verification
|
||||||
{
|
{
|
||||||
|
@ -80,6 +85,17 @@ public:
|
||||||
ZERO,
|
ZERO,
|
||||||
zk_input_nullifiers[i]
|
zk_input_nullifiers[i]
|
||||||
));
|
));
|
||||||
|
|
||||||
|
// The input keys authenticate h_sig to prevent
|
||||||
|
// malleability.
|
||||||
|
zk_hmac_authentication[i].reset(new PRF_pk_gadget<FieldT>(
|
||||||
|
pb,
|
||||||
|
ZERO,
|
||||||
|
zk_input_notes[i]->a_sk->bits,
|
||||||
|
zk_h_sig->bits,
|
||||||
|
i ? true : false,
|
||||||
|
zk_input_hmacs[i]
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,6 +110,9 @@ public:
|
||||||
for (size_t i = 0; i < NumInputs; i++) {
|
for (size_t i = 0; i < NumInputs; i++) {
|
||||||
// Constrain the JoinSplit input constraints.
|
// Constrain the JoinSplit input constraints.
|
||||||
zk_input_notes[i]->generate_r1cs_constraints();
|
zk_input_notes[i]->generate_r1cs_constraints();
|
||||||
|
|
||||||
|
// Authenticate h_sig with a_sk
|
||||||
|
zk_hmac_authentication[i]->generate_r1cs_constraints();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,9 +128,18 @@ public:
|
||||||
// Witness `zero`
|
// Witness `zero`
|
||||||
this->pb.val(ZERO) = FieldT::zero();
|
this->pb.val(ZERO) = FieldT::zero();
|
||||||
|
|
||||||
|
// Witness h_sig
|
||||||
|
zk_h_sig->bits.fill_with_bits(
|
||||||
|
this->pb,
|
||||||
|
uint256_to_bool_vector(h_sig)
|
||||||
|
);
|
||||||
|
|
||||||
for (size_t i = 0; i < NumInputs; i++) {
|
for (size_t i = 0; i < NumInputs; i++) {
|
||||||
// Witness the input information.
|
// Witness the input information.
|
||||||
zk_input_notes[i]->generate_r1cs_witness(inputs[i].key, inputs[i].note);
|
zk_input_notes[i]->generate_r1cs_witness(inputs[i].key, inputs[i].note);
|
||||||
|
|
||||||
|
// Witness hmacs
|
||||||
|
zk_hmac_authentication[i]->generate_r1cs_witness();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This happens last, because only by now are all the
|
// This happens last, because only by now are all the
|
||||||
|
@ -131,11 +159,11 @@ public:
|
||||||
std::vector<bool> verify_inputs;
|
std::vector<bool> verify_inputs;
|
||||||
|
|
||||||
insert_uint256(verify_inputs, uint256()); // TODO: rt
|
insert_uint256(verify_inputs, uint256()); // TODO: rt
|
||||||
insert_uint256(verify_inputs, uint256()); // TODO: h_sig
|
insert_uint256(verify_inputs, h_sig);
|
||||||
|
|
||||||
for (size_t i = 0; i < NumInputs; i++) {
|
for (size_t i = 0; i < NumInputs; i++) {
|
||||||
insert_uint256(verify_inputs, nullifiers[i]);
|
insert_uint256(verify_inputs, nullifiers[i]);
|
||||||
insert_uint256(verify_inputs, uint256()); // TODO: hmac
|
insert_uint256(verify_inputs, hmacs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < NumOutputs; i++) {
|
for (size_t i = 0; i < NumOutputs; i++) {
|
||||||
|
|
|
@ -29,13 +29,14 @@ public:
|
||||||
|
|
||||||
template<typename FieldT>
|
template<typename FieldT>
|
||||||
class input_note_gadget : public note_gadget<FieldT> {
|
class input_note_gadget : public note_gadget<FieldT> {
|
||||||
public:
|
private:
|
||||||
std::shared_ptr<digest_variable<FieldT>> a_sk;
|
|
||||||
std::shared_ptr<digest_variable<FieldT>> a_pk;
|
std::shared_ptr<digest_variable<FieldT>> a_pk;
|
||||||
std::shared_ptr<digest_variable<FieldT>> rho;
|
std::shared_ptr<digest_variable<FieldT>> rho;
|
||||||
|
|
||||||
std::shared_ptr<PRF_addr_a_pk_gadget<FieldT>> spend_authority;
|
std::shared_ptr<PRF_addr_a_pk_gadget<FieldT>> spend_authority;
|
||||||
std::shared_ptr<PRF_nf_gadget<FieldT>> expose_nullifiers;
|
std::shared_ptr<PRF_nf_gadget<FieldT>> expose_nullifiers;
|
||||||
|
public:
|
||||||
|
std::shared_ptr<digest_variable<FieldT>> a_sk;
|
||||||
|
|
||||||
input_note_gadget(
|
input_note_gadget(
|
||||||
protoboard<FieldT>& pb,
|
protoboard<FieldT>& pb,
|
||||||
|
|
|
@ -95,3 +95,24 @@ public:
|
||||||
PRF_gadget<FieldT>::generate_r1cs_witness();
|
PRF_gadget<FieldT>::generate_r1cs_witness();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename FieldT>
|
||||||
|
class PRF_pk_gadget : public PRF_gadget<FieldT> {
|
||||||
|
public:
|
||||||
|
PRF_pk_gadget(
|
||||||
|
protoboard<FieldT>& pb,
|
||||||
|
pb_variable<FieldT>& ZERO,
|
||||||
|
pb_variable_array<FieldT>& a_sk,
|
||||||
|
pb_variable_array<FieldT>& h_sig,
|
||||||
|
bool nonce,
|
||||||
|
std::shared_ptr<digest_variable<FieldT>> result
|
||||||
|
) : PRF_gadget<FieldT>(pb, ZERO, 0, nonce, 0, 0, a_sk, h_sig, result) {}
|
||||||
|
|
||||||
|
void generate_r1cs_constraints() {
|
||||||
|
PRF_gadget<FieldT>::generate_r1cs_constraints();
|
||||||
|
}
|
||||||
|
|
||||||
|
void generate_r1cs_witness() {
|
||||||
|
PRF_gadget<FieldT>::generate_r1cs_witness();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue