Skip to content

Commit

Permalink
DSL: Add valid dummy data for ecdsa constraints when verifier is crea…
Browse files Browse the repository at this point in the history
…ting circuit (AztecProtocol/barretenberg#438)

* Add way to make verifiers data valid by replacing zeroes with valid public keys and signatures

Co-authored-by: Zachary James Williamson <zac-williamson@users.noreply.github.com>

* Update cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp

* replace templates with concrete methods

* add comment

* PR review

* add comments

* change to use boolean flag, so dummy_ecdsa method lives in ecdsa

* ad true as default

---------

Co-authored-by: Zachary James Williamson <zac-williamson@users.noreply.github.com>
  • Loading branch information
kevaundray and zac-williamson authored May 11, 2023
1 parent ba4b8ac commit cf6e154
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ void create_circuit(Composer& composer, const acir_format& constraint_system)
if (std::find(constraint_system.public_inputs.begin(), constraint_system.public_inputs.end(), i) !=
constraint_system.public_inputs.end()) {
composer.add_public_variable(0);

} else {
composer.add_variable(0);
}
Expand Down Expand Up @@ -62,7 +61,7 @@ void create_circuit(Composer& composer, const acir_format& constraint_system)

// Add ECDSA constraints
for (const auto& constraint : constraint_system.ecdsa_constraints) {
create_ecdsa_verify_constraints(composer, constraint);
create_ecdsa_verify_constraints(composer, constraint, false);
}

// Add blake2s constraints
Expand Down Expand Up @@ -145,7 +144,7 @@ Composer create_circuit(const acir_format& constraint_system,

// Add ECDSA constraints
for (const auto& constraint : constraint_system.ecdsa_constraints) {
create_ecdsa_verify_constraints(composer, constraint);
create_ecdsa_verify_constraints(composer, constraint, false);
}

// Add blake2s constraints
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,15 @@ witness_ct ecdsa_index_to_witness(Composer& composer, uint32_t index)
return { &composer, value };
}

void create_ecdsa_verify_constraints(Composer& composer, const EcdsaSecp256k1Constraint& input)
void create_ecdsa_verify_constraints(Composer& composer,
const EcdsaSecp256k1Constraint& input,
bool has_valid_witness_assignments)
{

if (has_valid_witness_assignments == false) {
dummy_ecdsa_constraint(composer, input);
}

auto new_sig = ecdsa_convert_signature(composer, input.signature);

auto message = ecdsa_vector_of_bytes_to_byte_array(composer, input.hashed_message);
Expand Down Expand Up @@ -127,4 +133,54 @@ void create_ecdsa_verify_constraints(Composer& composer, const EcdsaSecp256k1Con
composer.assert_equal(signature_result_normalized.witness_index, input.result);
}

// Add dummy constraints for ECDSA because when the verifier creates the
// constraint system, they usually use zeroes for witness values.
//
// This does not work for ECDSA as the signature, r, s and public key need
// to be valid.
void dummy_ecdsa_constraint(Composer& composer, EcdsaSecp256k1Constraint const& input)
{

std::vector<uint32_t> pub_x_indices_;
std::vector<uint32_t> pub_y_indices_;
std::vector<uint32_t> signature_;
signature_.resize(64);

// Create a valid signature with a valid public key
crypto::ecdsa::key_pair<secp256k1_ct::fr, secp256k1_ct::g1> account;
account.private_key = 10;
account.public_key = secp256k1_ct::g1::one * account.private_key;
uint256_t pub_x_value = account.public_key.x;
uint256_t pub_y_value = account.public_key.y;
std::string message_string = "Instructions unclear, ask again later.";
crypto::ecdsa::signature signature =
crypto::ecdsa::construct_signature<Sha256Hasher, secp256k1_ct::fq, secp256k1_ct::fr, secp256k1_ct::g1>(
message_string, account);

// Create new variables which will reference the valid public key and signature.
// We don't use them in a gate, so when we call assert_equal, they will be
// replaced as if they never existed.
for (size_t i = 0; i < 32; ++i) {
uint32_t x_wit = composer.add_variable(pub_x_value.slice(248 - i * 8, 256 - i * 8));
uint32_t y_wit = composer.add_variable(pub_y_value.slice(248 - i * 8, 256 - i * 8));
uint32_t r_wit = composer.add_variable(signature.r[i]);
uint32_t s_wit = composer.add_variable(signature.s[i]);
pub_x_indices_.emplace_back(x_wit);
pub_y_indices_.emplace_back(y_wit);
signature_[i] = r_wit;
signature_[i + 32] = s_wit;
}

// Call assert_equal(from, to) to replace the value in `to` by the value in `from`
for (size_t i = 0; i < input.pub_x_indices.size(); ++i) {
composer.assert_equal(pub_x_indices_[i], input.pub_x_indices[i]);
}
for (size_t i = 0; i < input.pub_y_indices.size(); ++i) {
composer.assert_equal(pub_y_indices_[i], input.pub_y_indices[i]);
}
for (size_t i = 0; i < input.signature.size(); ++i) {
composer.assert_equal(signature_[i], input.signature[i]);
}
}

} // namespace acir_format
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ struct EcdsaSecp256k1Constraint {
friend bool operator==(EcdsaSecp256k1Constraint const& lhs, EcdsaSecp256k1Constraint const& rhs) = default;
};

void create_ecdsa_verify_constraints(Composer& composer, const EcdsaSecp256k1Constraint& input);
void create_ecdsa_verify_constraints(Composer& composer,
const EcdsaSecp256k1Constraint& input,
bool has_valid_witness_assignments = true);

void dummy_ecdsa_constraint(Composer& composer, EcdsaSecp256k1Constraint const& input);

template <typename B> inline void read(B& buf, EcdsaSecp256k1Constraint& constraint)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,34 @@ TEST(ECDSASecp256k1, TestECDSAConstraintSucceed)
EXPECT_EQ(verifier.verify_proof(proof), true);
}

// Test that the verifier can create an ECDSA circuit.
// The ECDSA circuit requires that certain dummy data is valid
// even though we are just building the circuit.
TEST(ECDSASecp256k1, TestECDSACompilesForVerifier)
{
acir_format::EcdsaSecp256k1Constraint ecdsa_constraint;
std::vector<fr> witness_values;
size_t num_variables = generate_ecdsa_constraint(ecdsa_constraint, witness_values);
acir_format::acir_format constraint_system{
.varnum = static_cast<uint32_t>(num_variables),
.public_inputs = {},
.fixed_base_scalar_mul_constraints = {},
.logic_constraints = {},
.range_constraints = {},
.schnorr_constraints = {},
.ecdsa_constraints = { ecdsa_constraint },
.sha256_constraints = {},
.blake2s_constraints = {},
.keccak_constraints = {},
.hash_to_field_constraints = {},
.pedersen_constraints = {},
.compute_merkle_root_constraints = {},
.constraints = {},
};
auto crs_factory = std::make_unique<proof_system::ReferenceStringFactory>();
auto composer = create_circuit(constraint_system, std::move(crs_factory));
}

TEST(ECDSASecp256k1, TestECDSAConstraintFail)
{
acir_format::EcdsaSecp256k1Constraint ecdsa_constraint;
Expand Down

0 comments on commit cf6e154

Please sign in to comment.