![ewillbefull@gmail.com](/assets/img/avatar_default.png)
4 changed files with 190 additions and 1 deletions
@ -0,0 +1,82 @@ |
|||
template<typename FieldT> |
|||
class note_gadget : public gadget<FieldT> { |
|||
public: |
|||
pb_variable_array<FieldT> value; |
|||
std::shared_ptr<digest_variable<FieldT>> r; |
|||
|
|||
note_gadget(protoboard<FieldT> &pb) : gadget<FieldT>(pb) { |
|||
value.allocate(pb, 64); |
|||
r.reset(new digest_variable<FieldT>(pb, 256, "")); |
|||
} |
|||
|
|||
void generate_r1cs_constraints() { |
|||
for (size_t i = 0; i < 64; i++) { |
|||
generate_boolean_r1cs_constraint<FieldT>( |
|||
this->pb, |
|||
value[i], |
|||
"boolean_value" |
|||
); |
|||
} |
|||
|
|||
r->generate_r1cs_constraints(); |
|||
} |
|||
|
|||
void generate_r1cs_witness(const Note& note) { |
|||
r->bits.fill_with_bits(this->pb, uint256_to_bool_vector(note.r)); |
|||
value.fill_with_bits(this->pb, uint64_to_bool_vector(note.value)); |
|||
} |
|||
}; |
|||
|
|||
template<typename FieldT> |
|||
class input_note_gadget : public note_gadget<FieldT> { |
|||
public: |
|||
std::shared_ptr<digest_variable<FieldT>> a_sk; |
|||
std::shared_ptr<digest_variable<FieldT>> a_pk; |
|||
|
|||
std::shared_ptr<PRF_addr_a_pk_gadget<FieldT>> spend_authority; |
|||
|
|||
input_note_gadget( |
|||
protoboard<FieldT>& pb, |
|||
pb_variable<FieldT>& ZERO |
|||
) : note_gadget<FieldT>(pb) { |
|||
a_sk.reset(new digest_variable<FieldT>(pb, 252, "")); |
|||
a_pk.reset(new digest_variable<FieldT>(pb, 256, "")); |
|||
spend_authority.reset(new PRF_addr_a_pk_gadget<FieldT>( |
|||
pb, |
|||
ZERO, |
|||
a_sk->bits, |
|||
a_pk |
|||
)); |
|||
} |
|||
|
|||
void generate_r1cs_constraints() { |
|||
note_gadget<FieldT>::generate_r1cs_constraints(); |
|||
|
|||
a_sk->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(); |
|||
} |
|||
|
|||
void generate_r1cs_witness(const SpendingKey& key, const Note& note) { |
|||
note_gadget<FieldT>::generate_r1cs_witness(note); |
|||
|
|||
// Witness a_sk for the input |
|||
a_sk->bits.fill_with_bits( |
|||
this->pb, |
|||
trailing252(uint256_to_bool_vector(key)) |
|||
); |
|||
|
|||
// Witness a_pk for a_sk with PRF_addr |
|||
spend_authority->generate_r1cs_witness(); |
|||
|
|||
// [SANITY CHECK] Witness a_pk with note information |
|||
a_pk->bits.fill_with_bits( |
|||
this->pb, |
|||
uint256_to_bool_vector(note.a_pk) |
|||
); |
|||
} |
|||
}; |
@ -0,0 +1,77 @@ |
|||
template<typename FieldT> |
|||
class PRF_gadget : gadget<FieldT> { |
|||
private: |
|||
std::shared_ptr<block_variable<FieldT>> block; |
|||
std::shared_ptr<sha256_compression_function_gadget<FieldT>> hasher; |
|||
std::shared_ptr<digest_variable<FieldT>> result; |
|||
|
|||
public: |
|||
PRF_gadget( |
|||
protoboard<FieldT>& pb, |
|||
pb_variable<FieldT>& ZERO, |
|||
bool a, |
|||
bool b, |
|||
bool c, |
|||
bool d, |
|||
pb_variable_array<FieldT> x, |
|||
boost::optional<pb_variable_array<FieldT>> y, |
|||
std::shared_ptr<digest_variable<FieldT>> result |
|||
) : gadget<FieldT>(pb), result(result) { |
|||
|
|||
pb_linear_combination_array<FieldT> IV = SHA256_default_IV(pb); |
|||
|
|||
pb_variable_array<FieldT> discriminants; |
|||
discriminants.emplace_back(a ? ONE : ZERO); |
|||
discriminants.emplace_back(b ? ONE : ZERO); |
|||
discriminants.emplace_back(c ? ONE : ZERO); |
|||
discriminants.emplace_back(d ? ONE : ZERO); |
|||
|
|||
if (!y) { |
|||
// Create y and pad it with zeroes. |
|||
y = pb_variable_array<FieldT>(); |
|||
while (y->size() < 256) { |
|||
y->emplace_back(ZERO); |
|||
} |
|||
} |
|||
|
|||
block.reset(new block_variable<FieldT>(pb, { |
|||
discriminants, |
|||
x, |
|||
*y |
|||
}, "PRF_block")); |
|||
|
|||
hasher.reset(new sha256_compression_function_gadget<FieldT>( |
|||
pb, |
|||
IV, |
|||
block->bits, |
|||
*result, |
|||
"PRF_hasher")); |
|||
} |
|||
|
|||
void generate_r1cs_constraints() { |
|||
hasher->generate_r1cs_constraints(); |
|||
} |
|||
|
|||
void generate_r1cs_witness() { |
|||
hasher->generate_r1cs_witness(); |
|||
} |
|||
}; |
|||
|
|||
template<typename FieldT> |
|||
class PRF_addr_a_pk_gadget : public PRF_gadget<FieldT> { |
|||
public: |
|||
PRF_addr_a_pk_gadget( |
|||
protoboard<FieldT>& pb, |
|||
pb_variable<FieldT>& ZERO, |
|||
pb_variable_array<FieldT>& a_sk, |
|||
std::shared_ptr<digest_variable<FieldT>> result |
|||
) : PRF_gadget<FieldT>(pb, ZERO, 1, 1, 0, 0, a_sk, boost::none, 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