Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,8 @@ template <typename FF> msgpack::sbuffer StandardCircuitBuilder_<FF>::export_circ
cir.wires.push_back(tmp_w);
}

cir.real_variable_index = this->real_variable_index;

msgpack::sbuffer buffer;
msgpack::pack(buffer, cir);
return buffer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ template <typename FF> class StandardCircuitBuilder_ : public CircuitBuilderBase
std::vector<FF> variables;
std::vector<std::vector<FF>> selectors;
std::vector<std::vector<uint32_t>> wires;
MSGPACK_FIELDS(modulus, public_inps, vars_of_interest, variables, selectors, wires);
std::vector<uint32_t> real_variable_index;
MSGPACK_FIELDS(modulus, public_inps, vars_of_interest, variables, selectors, wires, real_variable_index);
} circuit_schema;
};

Expand Down
122 changes: 63 additions & 59 deletions barretenberg/cpp/src/barretenberg/smt_verification/circuit/circuit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,73 +3,27 @@
namespace smt_circuit {

/**
* @brief Get the CircuitSchema object
* @details Initialize the CircuitSchmea from the binary file
* that contains an msgpack compatible buffer.
*
* @param filename
* @return CircuitSchema
*/
CircuitSchema unpack_from_file(const std::string& filename)
{
std::ifstream fin;
fin.open(filename, std::ios::in | std::ios::binary);
if (!fin.is_open()) {
throw std::invalid_argument("file not found");
}
if (fin.tellg() == -1) {
throw std::invalid_argument("something went wrong");
}

fin.ignore(std::numeric_limits<std::streamsize>::max()); // ohboy
std::streamsize fsize = fin.gcount();
fin.clear();
fin.seekg(0, std::ios_base::beg);
info("File size: ", fsize);

CircuitSchema cir;
char* encoded_data = (char*)aligned_alloc(64, static_cast<size_t>(fsize));
fin.read(encoded_data, fsize);
msgpack::unpack((const char*)encoded_data, static_cast<size_t>(fsize)).get().convert(cir);
return cir;
}

/**
* @brief Get the CircuitSchema object
* @details Initialize the CircuitSchmea from the msgpack compatible buffer.
*
* @param buf
* @return CircuitSchema
*/
CircuitSchema unpack_from_buffer(const msgpack::sbuffer& buf)
{
CircuitSchema cir;
msgpack::unpack(buf.data(), buf.size()).get().convert(cir);
return cir;
}

/**
* @brief Check your circuit for witness uniqness
* @brief Check your circuit for witness uniqueness
*
* @details Creates two Circuit objects that represent the same
* circuit, however you can choose which variables should be (not) equal in both cases,
* and also the variables that should (not) be equal at the same time.
*
* @param circuit_info
* @param s pointer to the global solver
* @param equal all the variables that should be equal in both circuits
* @param nequal all the variables that should be different in both circuits
* @param eqall all the variables that should not be equal at the same time
* @param neqall all the variables that should not be different at the same time
* @param equal The list of names of variables which should be equal in both circuits(each is equal)
* @param not_equal The list of names of variables which should not be equal in both circuits(each is not equal)
* @param equal_at_the_same_time The list of variables, where at least one pair has to be equal
* @param not_equal_at_the_same_time The list of variables, where at least one pair has to be distinct
* @return std::pair<Circuit, Circuit>
*/
template <typename FF>
std::pair<Circuit<FF>, Circuit<FF>> unique_witness(CircuitSchema& circuit_info,
Solver* s,
const std::vector<std::string>& equal,
const std::vector<std::string>& not_equal,
const std::vector<std::string>& equal_at_the_same_time,
const std::vector<std::string>& not_equal_at_the_same_time)
std::pair<Circuit<FF>, Circuit<FF>> unique_witness_ext(CircuitSchema& circuit_info,
Solver* s,
const std::vector<std::string>& equal,
const std::vector<std::string>& not_equal,
const std::vector<std::string>& equal_at_the_same_time,
const std::vector<std::string>& not_equal_at_the_same_time)
{
Circuit<FF> c1(circuit_info, s, "circuit1");
Circuit<FF> c2(circuit_info, s, "circuit2");
Expand Down Expand Up @@ -107,20 +61,70 @@ std::pair<Circuit<FF>, Circuit<FF>> unique_witness(CircuitSchema& circuit_info,
return { c1, c2 };
}

template std::pair<Circuit<FFTerm>, Circuit<FFTerm>> unique_witness(
template std::pair<Circuit<FFTerm>, Circuit<FFTerm>> unique_witness_ext(
CircuitSchema& circuit_info,
Solver* s,
const std::vector<std::string>& equal = {},
const std::vector<std::string>& not_equal = {},
const std::vector<std::string>& equal_at_the_same_time = {},
const std::vector<std::string>& not_eqaul_at_the_same_time = {});

template std::pair<Circuit<FFITerm>, Circuit<FFITerm>> unique_witness(
template std::pair<Circuit<FFITerm>, Circuit<FFITerm>> unique_witness_ext(
CircuitSchema& circuit_info,
Solver* s,
const std::vector<std::string>& equal = {},
const std::vector<std::string>& not_equal = {},
const std::vector<std::string>& equal_at_the_same_time = {},
const std::vector<std::string>& not_eqaul_at_the_same_time = {});

/**
* @brief Check your circuit for witness uniqueness
*
* @details Creates two Circuit objects that represent the same
* circuit, however you can choose which variables should be equal in both cases,
* other witness members will be marked as not equal at the same time
* or basically they will have to differ by at least one element.
*
* @param circuit_info
* @param s pointer to the global solver
* @param equal The list of names of variables which should be equal in both circuits(each is equal)
* @return std::pair<Circuit, Circuit>
*/
template <typename FF>
std::pair<Circuit<FF>, Circuit<FF>> unique_witness(CircuitSchema& circuit_info,
Solver* s,
const std::vector<std::string>& equal)
{
Circuit<FF> c1(circuit_info, s, "circuit1");
Circuit<FF> c2(circuit_info, s, "circuit2");

for (const auto& term : equal) {
c1[term] == c2[term];
}

std::vector<Bool> neqs;
for (const auto& node : c1.symbolic_vars) {
uint32_t i = node.first;
if (std::find(equal.begin(), equal.end(), std::string(c1.variable_names[i])) != equal.end()) {
continue;
}
Bool tmp = Bool(c1[i]) != Bool(c2[i]);
neqs.push_back(tmp);
}

if (neqs.size() > 1) {
batch_or(neqs).assert_term();
} else if (neqs.size() == 1) {
neqs[0].assert_term();
}
return { c1, c2 };
}

template std::pair<Circuit<FFTerm>, Circuit<FFTerm>> unique_witness(CircuitSchema& circuit_info,
Solver* s,
const std::vector<std::string>& equal = {});

template std::pair<Circuit<FFITerm>, Circuit<FFITerm>> unique_witness(CircuitSchema& circuit_info,
Solver* s,
const std::vector<std::string>& equal = {});
}; // namespace smt_circuit
Loading