template class note_gadget : public gadget { public: pb_variable_array value; std::shared_ptr> r; note_gadget(protoboard &pb) : gadget(pb) { value.allocate(pb, 64); r.reset(new digest_variable(pb, 256, "")); } void generate_r1cs_constraints() { for (size_t i = 0; i < 64; i++) { generate_boolean_r1cs_constraint( 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 class input_note_gadget : public note_gadget { public: std::shared_ptr> a_sk; std::shared_ptr> a_pk; std::shared_ptr> spend_authority; input_note_gadget( protoboard& pb, pb_variable& ZERO ) : note_gadget(pb) { a_sk.reset(new digest_variable(pb, 252, "")); a_pk.reset(new digest_variable(pb, 256, "")); spend_authority.reset(new PRF_addr_a_pk_gadget( pb, ZERO, a_sk->bits, a_pk )); } void generate_r1cs_constraints() { note_gadget::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::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) ); } };