Sean Bowe
8 years ago
5 changed files with 148 additions and 3 deletions
@ -0,0 +1,104 @@ |
|||
template<typename FieldT> |
|||
class note_commitment_gadget : gadget<FieldT> { |
|||
private: |
|||
std::shared_ptr<block_variable<FieldT>> block1; |
|||
std::shared_ptr<block_variable<FieldT>> block2; |
|||
std::shared_ptr<sha256_compression_function_gadget<FieldT>> hasher1; |
|||
std::shared_ptr<digest_variable<FieldT>> intermediate_hash; |
|||
std::shared_ptr<sha256_compression_function_gadget<FieldT>> hasher2; |
|||
|
|||
public: |
|||
note_commitment_gadget( |
|||
protoboard<FieldT> &pb, |
|||
pb_variable<FieldT>& ZERO, |
|||
pb_variable_array<FieldT>& a_pk, |
|||
pb_variable_array<FieldT>& v, |
|||
pb_variable_array<FieldT>& rho, |
|||
pb_variable_array<FieldT>& r, |
|||
std::shared_ptr<digest_variable<FieldT>> result |
|||
) : gadget<FieldT>(pb) { |
|||
pb_variable_array<FieldT> leading_byte = |
|||
from_bits({1, 0, 1, 1, 0, 0, 0, 0}, ZERO); |
|||
|
|||
pb_variable_array<FieldT> first_of_rho(rho.begin(), rho.begin()+184); |
|||
pb_variable_array<FieldT> last_of_rho(rho.begin()+184, rho.end()); |
|||
|
|||
intermediate_hash.reset(new digest_variable<FieldT>(pb, 256, "")); |
|||
|
|||
// final padding |
|||
pb_variable_array<FieldT> length_padding = |
|||
from_bits({ |
|||
// padding |
|||
1,0,0,0,0,0,0,0, |
|||
0,0,0,0,0,0,0,0, |
|||
0,0,0,0,0,0,0,0, |
|||
0,0,0,0,0,0,0,0, |
|||
0,0,0,0,0,0,0,0, |
|||
0,0,0,0,0,0,0,0, |
|||
0,0,0,0,0,0,0,0, |
|||
0,0,0,0,0,0,0,0, |
|||
0,0,0,0,0,0,0,0, |
|||
0,0,0,0,0,0,0,0, |
|||
0,0,0,0,0,0,0,0, |
|||
0,0,0,0,0,0,0,0, |
|||
0,0,0,0,0,0,0,0, |
|||
0,0,0,0,0,0,0,0, |
|||
0,0,0,0,0,0,0,0, |
|||
|
|||
// length of message (840 bits) |
|||
0,0,0,0,0,0,0,0, |
|||
0,0,0,0,0,0,0,0, |
|||
0,0,0,0,0,0,0,0, |
|||
0,0,0,0,0,0,0,0, |
|||
0,0,0,0,0,0,0,0, |
|||
0,0,0,0,0,0,0,0, |
|||
0,0,0,0,0,0,1,1, |
|||
0,1,0,0,1,0,0,0 |
|||
}, ZERO); |
|||
|
|||
block1.reset(new block_variable<FieldT>(pb, { |
|||
leading_byte, |
|||
a_pk, |
|||
v, |
|||
first_of_rho |
|||
}, "")); |
|||
|
|||
block2.reset(new block_variable<FieldT>(pb, { |
|||
last_of_rho, |
|||
r, |
|||
length_padding |
|||
}, "")); |
|||
|
|||
pb_linear_combination_array<FieldT> IV = SHA256_default_IV(pb); |
|||
|
|||
hasher1.reset(new sha256_compression_function_gadget<FieldT>( |
|||
pb, |
|||
IV, |
|||
block1->bits, |
|||
*intermediate_hash, |
|||
"")); |
|||
|
|||
pb_linear_combination_array<FieldT> IV2(intermediate_hash->bits); |
|||
|
|||
hasher2.reset(new sha256_compression_function_gadget<FieldT>( |
|||
pb, |
|||
IV2, |
|||
block2->bits, |
|||
*result, |
|||
"")); |
|||
} |
|||
|
|||
void generate_r1cs_constraints() { |
|||
// TODO: This may not be necessary if SHA256 constrains |
|||
// its output digests to be boolean anyway. |
|||
intermediate_hash->generate_r1cs_constraints(); |
|||
|
|||
hasher1->generate_r1cs_constraints(); |
|||
hasher2->generate_r1cs_constraints(); |
|||
} |
|||
|
|||
void generate_r1cs_witness() { |
|||
hasher1->generate_r1cs_witness(); |
|||
hasher2->generate_r1cs_witness(); |
|||
} |
|||
}; |
Loading…
Reference in new issue