Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gadgetlib: support multiple gadgets #18

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 61 additions & 61 deletions cpp/gadget_cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,75 +11,75 @@ using namespace zkinterface_utils;
Offset<Vector<Offset<KeyValue>>>
make_configuration(FlatBufferBuilder &builder,
vector<pair<string, string>> keyvalues) {
vector<Offset<KeyValue>> config;
for (auto kv = keyvalues.begin(); kv != keyvalues.end(); kv++) {
config.emplace_back(CreateKeyValue(builder, builder.CreateString(kv->first),
0, builder.CreateString(kv->second)));
}
return builder.CreateVector(config);
vector<Offset<KeyValue>> config;
for (auto kv = keyvalues.begin(); kv != keyvalues.end(); kv++) {
config.emplace_back(CreateKeyValue(builder, builder.CreateString(kv->first),
0, builder.CreateString(kv->second)));
}
return builder.CreateVector(config);
}

void make_input_circuit(vector<char> &out_buffer) {
FlatBufferBuilder builder;
FlatBufferBuilder builder;

auto connections = CreateVariables(
builder, builder.CreateVector(vector<uint64_t>({1, 2, 3, 4})));
auto connections = CreateVariables(
builder, builder.CreateVector(vector<uint64_t>({1, 2, 3, 4})));

auto config = make_configuration(builder, {{"function", "and"}});
auto config = make_configuration(builder, {{"function", "tinyram.and"}});

auto circuit = CreateCircuit(builder, connections, 5, 0, config);
auto circuit = CreateCircuit(builder, connections, 5, 0, config);

auto root = CreateRoot(builder, Message_Circuit, circuit.Union());
builder.FinishSizePrefixed(root);
auto root = CreateRoot(builder, Message_Circuit, circuit.Union());
builder.FinishSizePrefixed(root);

// Append to the out_buffer buffer.
char *begin = (char *)builder.GetBufferPointer();
out_buffer.insert(out_buffer.end(), begin, begin + builder.GetSize());
// Append to the out_buffer buffer.
char *begin = (char *) builder.GetBufferPointer();
out_buffer.insert(out_buffer.end(), begin, begin + builder.GetSize());
}

void make_command(vector<char> &out_buffer, string &action) {
bool constraints_generation =
(action == "constraints" || action == "combined");
bool witness_generation = (action == "witness" || action == "combined");

FlatBufferBuilder builder;
auto command =
CreateCommand(builder, constraints_generation, witness_generation);
auto root = CreateRoot(builder, Message_Command, command.Union());
builder.FinishSizePrefixed(root);

// Append to the out_buffer buffer.
char *begin = (char *)builder.GetBufferPointer();
out_buffer.insert(out_buffer.end(), begin, begin + builder.GetSize());
bool constraints_generation =
(action == "constraints" || action == "combined");
bool witness_generation = (action == "witness" || action == "combined");

FlatBufferBuilder builder;
auto command =
CreateCommand(builder, constraints_generation, witness_generation);
auto root = CreateRoot(builder, Message_Command, command.Union());
builder.FinishSizePrefixed(root);

// Append to the out_buffer buffer.
char *begin = (char *) builder.GetBufferPointer();
out_buffer.insert(out_buffer.end(), begin, begin + builder.GetSize());
}

bool callback_write_to_file(void *context, unsigned char *message) {
string name = *reinterpret_cast<string *>(context);
uoffset_t size = read_size_prefix(message);
cout << "callback_write_to_file " << name << ", " << size << " bytes" << endl;
ofstream out(name, ios::binary);
out.write(reinterpret_cast<char *>(message), size);
return true;
string name = *reinterpret_cast<string *>(context);
uoffset_t size = read_size_prefix(message);
cout << "callback_write_to_file " << name << ", " << size << " bytes" << endl;
ofstream out(name, ios::binary);
out.write(reinterpret_cast<char *>(message), size);
return true;
}

void run(string action, string zkif_out_prefix) {
vector<char> circuit_msg;
make_input_circuit(circuit_msg);
vector<char> command_msg;
make_command(command_msg, action);

string constraints_name = zkif_out_prefix + "constraints.zkif";
string witness_name = zkif_out_prefix + "witness.zkif";
string response_name = zkif_out_prefix + "response.zkif";

gadgetlib_call_gadget(circuit_msg.data(), command_msg.data(),
callback_write_to_file, &constraints_name,
callback_write_to_file, &witness_name,
callback_write_to_file, &response_name);
vector<char> circuit_msg;
make_input_circuit(circuit_msg);
vector<char> command_msg;
make_command(command_msg, action);

string constraints_name = zkif_out_prefix + "constraints.zkif";
string witness_name = zkif_out_prefix + "witness.zkif";
string response_name = zkif_out_prefix + "response.zkif";

gadgetlib_call_gadget(circuit_msg.data(), command_msg.data(),
callback_write_to_file, &constraints_name,
callback_write_to_file, &witness_name,
callback_write_to_file, &response_name);
}

static const char USAGE[] =
R"(libsnark gadget lib.
R"(libsnark gadget lib.

Usage:
gadgetlib constraints <zkinterface_output_file>
Expand All @@ -88,18 +88,18 @@ static const char USAGE[] =

int main(int argc, const char **argv) {

if (argc < 2) {
cerr << USAGE << endl;
return 1;
}
if (argc < 2) {
cerr << USAGE << endl;
return 1;
}

string out_prefix = (argc > 2) ? string(argv[2]) : "";
string out_prefix = (argc > 2) ? string(argv[2]) : "";

try {
run(string(argv[1]), out_prefix);
return 0;
} catch (const char *msg) {
cerr << msg << endl;
return 2;
}
try {
run(string(argv[1]), out_prefix);
return 0;
} catch (const char *msg) {
cerr << msg << endl;
return 2;
}
}
4 changes: 0 additions & 4 deletions cpp/gadgetlib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@ bool gadgetlib_call_gadget(char *circuit_msg, char *command_msg,
CurveT::init_public_params();
}

const Circuit *circuit = read_circuit(circuit_msg);
string function_name = find_config_text(circuit, "function", "");
cout << "Function: " << function_name << endl;

return gadgetlib_alu::call_gadget(
circuit_msg, command_msg, constraints_callback, constraints_context,
witness_callback, witness_context, return_callback, return_context);
Expand Down
128 changes: 75 additions & 53 deletions cpp/gadgetlib_alu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,30 @@ namespace gadgetlib_alu {
typedef word_variable_gadget<FieldT> PbWord;


tinyram_standard_gadget<FieldT> *make_gadget(
string function_name,
tinyram_protoboard<FieldT> &pb,
const PbArray &opcode_indicators,
const PbWord &desval,
const PbWord &arg1val,
const PbWord &arg2val,
const PbVariable &flag,
const PbVariable &result,
const PbVariable &result_flag,
const string &annotation_prefix = ""
) {
if (function_name == "tinyram.and") {
return new ALU_and_gadget<FieldT>(pb, opcode_indicators, desval, arg1val, arg2val, flag, result,
result_flag);
}
if (function_name == "tinyram.or") {
return new ALU_or_gadget<FieldT>(pb, opcode_indicators, desval, arg1val, arg2val, flag, result,
result_flag);
}
return nullptr;
}


bool call_gadget(
char *circuit_msg,
char *command_msg,
Expand All @@ -31,38 +55,6 @@ namespace gadgetlib_alu {
tinyram_architecture_params tinyram_params(8, 4);
tinyram_protoboard<FieldT> pb(tinyram_params);

// Transition function.
auto transition = [&](PbVariable destval, PbVariable arg1val,
PbVariable arg2val, PbVariable flag,
PbVariable out_result, PbVariable out_flag
) {
// Allocate.
PbArray opcode_indicators; // Unused.
PbWord destword(pb, destval);
PbWord arg1word(pb, arg1val);
PbWord arg2word(pb, arg2val);

// ALU gadget.
ALU_and_gadget<FieldT> gadget(pb, opcode_indicators, destword, arg1word, arg2word, flag, out_result,
out_flag);

// Constraints.
if (command->constraints_generation()) {
destword.generate_r1cs_constraints(false); // TODO: true
arg1word.generate_r1cs_constraints(false);
arg2word.generate_r1cs_constraints(false);
gadget.generate_r1cs_constraints();
}

// Witness.
if (command->witness_generation()) {
destword.generate_r1cs_witness_from_packed();
arg1word.generate_r1cs_witness_from_packed();
arg2word.generate_r1cs_witness_from_packed();
gadget.generate_r1cs_witness();
}
};

// Read input values (or zeros if omitted).
vector<FieldT> inputs = deserialize_incoming_elements(circuit);
if (inputs.size() != 4) {
Expand All @@ -86,24 +78,54 @@ namespace gadgetlib_alu {
pb.val(arg2val) = inputs[2];
pb.val(flag) = inputs[3];

// Call the transition.
// In principle, this block could be iterated over multiple instructions.
{
// Allocate outputs.
PbVariable out_result;
PbVariable out_flag;
out_result.allocate(pb);
out_flag.allocate(pb);
// Allocate outputs.
PbVariable out_result;
PbVariable out_flag;
out_result.allocate(pb);
out_flag.allocate(pb);

transition(destval, arg1val, arg2val, flag, out_result, out_flag);
// Allocate converters to words.
PbWord destword(pb, destval);
PbWord arg1word(pb, arg1val);
PbWord arg2word(pb, arg2val);
PbArray opcode_indicators; // Unused.

destval = out_result;
flag = out_flag;
// Init gadget.
string function_name = find_config_text(circuit, "function", "");
cerr << "Function: " << function_name << endl;

cout << "Variables: " << pb.num_variables() << endl;
cout << "Result: " << destval.index << " = " << pb.val(destval).as_ulong() << endl;
tinyram_standard_gadget<FieldT> *gadget = make_gadget(
function_name,
pb, opcode_indicators, destword, arg1word, arg2word, flag, out_result, out_flag);

if (gadget == nullptr) {
cerr << "Gadget not supported" << endl;
return false;
}

// Constraints.
if (command->constraints_generation()) {
destword.generate_r1cs_constraints(false); // TODO: true
arg1word.generate_r1cs_constraints(false);
arg2word.generate_r1cs_constraints(false);
gadget->generate_r1cs_constraints();
}

// Witness.
if (command->witness_generation()) {
destword.generate_r1cs_witness_from_packed();
arg1word.generate_r1cs_witness_from_packed();
arg2word.generate_r1cs_witness_from_packed();
gadget->generate_r1cs_witness();
// out_result and out_flags contain values now.
}

free(gadget);

cerr << "Variables: " << pb.num_variables() << endl;
cerr << "Result: " << out_result.index << " = " << pb.val(out_result).as_ulong() << endl;


// Serialize constraints.
if (command->constraints_generation()) {
auto builder = serialize_protoboard_constraints(circuit, pb);
Expand All @@ -122,17 +144,17 @@ namespace gadgetlib_alu {
VarIdConverter converter(circuit);

vector<uint64_t> output_ids({
converter.get_variable_id(destval),
converter.get_variable_id(flag),
});
converter.get_variable_id(out_result),
converter.get_variable_id(out_flag),
});

Offset<Vector<unsigned char>> output_values;
if (command->witness_generation()) {
output_values = builder.CreateVector(
elements_into_le({
pb.val(destval),
pb.val(flag),
}));
elements_into_le({
pb.val(out_result),
pb.val(out_flag),
}));
}

auto connections = CreateVariables(
Expand All @@ -156,4 +178,4 @@ namespace gadgetlib_alu {
return true;
}

} // namespace gadgetlib_example
} // namespace gadgetlib_alu
16 changes: 15 additions & 1 deletion cpp/libsnark-rust/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ fn test_libsnark_with_statement_builder() -> Result<()> {
if proving {
b.store.push_witness(&WitnessOwned { assigned_variables: some_vars.clone() })?;
}
let command = CommandOwned { constraints_generation: !proving, witness_generation: proving };

let gadget_call = CircuitOwned {
connections: some_vars.clone(),
Expand All @@ -127,7 +128,20 @@ fn test_libsnark_with_statement_builder() -> Result<()> {
number: 0,
}]),
};
let command = CommandOwned { constraints_generation: !proving, witness_generation: proving };
call_gadget_cb(b, &gadget_call, &command)?;

let gadget_call = CircuitOwned {
connections: some_vars.clone(),
free_variable_id: b.vars.free_variable_id,
field_maximum: None,
configuration: Some(vec![
KeyValueOwned {
key: "function".to_string(),
text: Some("tinyram.or".to_string()),
data: None,
number: 0,
}]),
};
call_gadget_cb(b, &gadget_call, &command)?;

Ok(())
Expand Down