@@ -200,23 +200,26 @@ namespace nil {
200
200
++it;
201
201
--degree;
202
202
while (degree != 0 ) {
203
- if (degree == it->get_vars ().size ()) {
203
+ if (( degree == it->get_vars ().size ()) && (it-> get_coeff () != 0 ) ) {
204
204
result << " \t\t sum = addmod(sum, " << it->get_coeff () << " , modulus);" << std::endl;
205
205
++it;
206
206
} else {
207
- result << " /* term with zero coeficient is skipped */" << std::endl;
207
+ result << " \t\t /* term with zero coeficient is skipped */" << std::endl;
208
208
}
209
209
result << " \t\t sum = mulmod(sum, x, modulus);" << std::endl;
210
210
--degree;
211
211
}
212
- if (it != std::cend (comb)) {
212
+ if (it != std::cend (comb) && (it-> get_coeff () != 0 ) ) {
213
213
result << " /* last term */" << std::endl;
214
214
result << " \t\t sum = addmod(sum, " << it->get_coeff () << " , modulus);" << std::endl;
215
215
}
216
216
result << " \t\t /* End using Horner's formula */" << std::endl;
217
217
} else {
218
218
result << " \t\t sum = 0;" << std::endl;
219
219
for (auto term = std::cbegin (comb); term != std::cend (comb); ++term) {
220
+ if ( term->get_coeff () == 0 ) {
221
+ continue ;
222
+ }
220
223
const auto &vars = term->get_vars ();
221
224
std::size_t power;
222
225
@@ -280,10 +283,9 @@ namespace nil {
280
283
const typename PlaceholderParams::commitment_scheme_type &lpc_scheme,
281
284
std::size_t permutation_size,
282
285
std::string folder_name,
283
- std::size_t gates_library_size_threshold = 1400 ,
284
- std::size_t lookups_library_size_threshold = 1400 ,
285
- std::size_t gates_contract_size_threshold = 1400 ,
286
- std::size_t lookups_contract_size_threshold = 1400 ,
286
+ std::size_t gates_contract_size_threshold = 800 ,
287
+ std::size_t lookups_library_size_threshold = 1000 ,
288
+ std::size_t lookups_contract_size_threshold = 1000 ,
287
289
bool deduce_horner = true ,
288
290
bool optimize_powers = true
289
291
) :
@@ -292,7 +294,6 @@ namespace nil {
292
294
_lpc_scheme (lpc_scheme),
293
295
_permutation_size (permutation_size),
294
296
_folder_name (folder_name),
295
- _gates_library_size_threshold (gates_library_size_threshold),
296
297
_lookups_library_size_threshold (lookups_library_size_threshold),
297
298
_gates_contract_size_threshold (gates_contract_size_threshold),
298
299
_lookups_contract_size_threshold (lookups_contract_size_threshold),
@@ -417,6 +418,15 @@ namespace nil {
417
418
return out.str ();
418
419
}
419
420
421
+ std::size_t estimate_constraint_cost (std::string const & code) {
422
+ /* proof-of-concept: cost = number of lines */
423
+ std::size_t lines = 0 ;
424
+ for (auto &ch: code) {
425
+ lines += ch == ' \n ' ;
426
+ }
427
+ return lines;
428
+ }
429
+
420
430
std::size_t estimate_gate_cost (std::string const & code) {
421
431
/* proof-of-concept: cost = number of lines */
422
432
std::size_t lines = 0 ;
@@ -491,6 +501,55 @@ namespace nil {
491
501
return result.str ();
492
502
}
493
503
504
+ struct constraint_info {
505
+ std::string code;
506
+ std::size_t cost;
507
+ std::size_t gate_index;
508
+ std::size_t constraint_index;
509
+ std::size_t selector_index;
510
+ };
511
+
512
+ std::string print_constraint_series (typename std::vector<constraint_info>::iterator &it,
513
+ typename std::vector<constraint_info>::iterator const & last) {
514
+ std::stringstream result;
515
+ std::size_t printed_cost = 0 ;
516
+ std::size_t prev_sel = 0 ;
517
+
518
+ bool first_constraint = true ;
519
+
520
+ while ((printed_cost < _gates_contract_size_threshold) && (it != last) ) {
521
+
522
+ if (first_constraint) {
523
+ result << " // gate === " << it->gate_index << " ===" << std::endl;
524
+ result << " \t\t gate = 0;" << std::endl;
525
+ first_constraint = false ;
526
+ prev_sel = it->selector_index ;
527
+ } else if (prev_sel != it->selector_index ) {
528
+ result << " \t\t gate = mulmod(gate, basic_marshalling.get_uint256_be(blob, " <<prev_sel<<" ), modulus);" << std::endl;
529
+ result << " \t\t F = addmod(F, gate, modulus);" << std::endl;
530
+ result << " // gate === " << it->gate_index << " ===" << std::endl;
531
+ result << " \t\t gate = 0;" << std::endl;
532
+ prev_sel = it->selector_index ;
533
+ }
534
+ result << " // constraint " << it->constraint_index << std::endl;
535
+ result << it->code ;
536
+ result << " \t\t sum = mulmod(sum, theta_acc, modulus);" << std::endl;
537
+ result << " \t\t theta_acc = mulmod(theta, theta_acc, modulus);" << std::endl;
538
+ result << " \t\t gate = addmod(gate, sum, modulus);" << std::endl;
539
+
540
+ printed_cost += it->cost ;
541
+ ++it;
542
+ }
543
+
544
+ if (it != last) {
545
+ result << " // gate computation code ended prematurely. continue in next library" << std::endl;
546
+ }
547
+ result << " \t\t gate = mulmod(gate, basic_marshalling.get_uint256_be(blob, " <<prev_sel<<" ), modulus);" << std::endl;
548
+ result << " \t\t F = addmod(F, gate, modulus);" << std::endl;
549
+
550
+ return result.str ();
551
+ }
552
+
494
553
std::string print_gate_argument (){
495
554
std::size_t gates_count = _constraint_system.gates ().size ();
496
555
if (gates_count == 0 )
@@ -501,46 +560,57 @@ namespace nil {
501
560
std::unordered_map<std::size_t , std::string> gate_codes;
502
561
std::vector<std::pair<std::size_t , std::size_t >> gate_costs (gates_count);
503
562
std::vector<std::size_t > gate_ids (gates_count);
563
+
564
+ std::vector<constraint_info> constraints;
565
+ std::size_t total_cost = 0 ;
504
566
505
567
i = 0 ;
506
- for (const auto &gate: _constraint_system.gates ()) {
507
- std::string code = gate_computation_code (gate);
508
- gate_costs[i] = std::make_pair (i, estimate_gate_cost (code));
509
- gate_codes[i] = code;
510
- ++i;
511
- }
568
+ for (const auto & gate: _constraint_system.gates ()) {
569
+ variable_type sel_var (gate.selector_index , 0 , true , variable_type::column_type::selector);
570
+ std::size_t j = 0 ;
571
+ for (const auto & constraint: gate.constraints ) {
572
+ std::string code = constraint_computation_code_optimized (_var_indices, constraint);
573
+ std::size_t cost = estimate_constraint_cost (code);
574
+ std::size_t selector_index = _var_indices.at (sel_var)*0x20 ;
512
575
513
- std::sort (gate_costs.begin (), gate_costs.end (),
514
- [](const std::pair<std::size_t , std::size_t > &a,
515
- const std::pair<std::size_t , std::size_t > &b) {
516
- return a.second > b.second ;
517
- });
576
+ constraints.push_back ( {code, cost, i, j, selector_index} );
518
577
519
- /* Fill contract inline gate computation, inline small gates first */
520
- std::unordered_set<std::size_t > inlined_gate_codes;
521
- std::size_t inlined_gate_codes_size = 0 ;
522
- for (auto gate=gate_costs.rbegin (); gate != gate_costs.rend (); ++gate) {
523
- if (gate->second + inlined_gate_codes_size < _gates_contract_size_threshold) {
524
- inlined_gate_codes.insert (gate->first );
525
- inlined_gate_codes_size += gate->second ;
578
+ total_cost += cost;
579
+ ++j;
526
580
}
581
+ ++i;
527
582
}
528
583
529
- auto inlined_gates_end = std::remove_if (gate_costs.begin (), gate_costs.end (),
530
- [&inlined_gate_codes](const std::pair<std::size_t , std::size_t >& cost) {
531
- return inlined_gate_codes.count (cost.first ) == 1 ;
532
- });
533
- gate_costs.erase (inlined_gates_end, gate_costs.end ());
534
584
535
- auto library_gates_buckets = split_items_into_buckets (gate_costs, _gates_library_size_threshold);
536
- std::vector<std::size_t > gate_lib (gates_count);
585
+ std::size_t gate_modules_count = 0 ;
537
586
538
- for (auto const & lib: library_gates_buckets) {
539
- _gate_includes += " import \" ./gate_" + to_string (lib.first ) + " .sol\" ;\n " ;
540
- for (auto g: lib.second ) {
541
- gate_lib[g] = lib.first ;
587
+
588
+ std::size_t current_selector = 0 ;
589
+ if (total_cost <= _gates_contract_size_threshold) {
590
+ auto it = constraints.begin ();
591
+ gate_argument_str << " \t\t uint256 prod;" << std::endl;
592
+ gate_argument_str << " \t\t uint256 sum;" << std::endl;
593
+ gate_argument_str << " \t\t uint256 gate;" << std::endl;
594
+ gate_argument_str << print_constraint_series (it, constraints.end ());
595
+ } else {
596
+ auto it = constraints.begin ();
597
+ while (it != constraints.end ()) {
598
+ std::string code = print_constraint_series (it, constraints.end ());
599
+
600
+ std::string result = modular_external_gate_library_template;
601
+ boost::replace_all (result, " $TEST_NAME$" , _test_name);
602
+ boost::replace_all (result, " $GATE_LIB_ID$" , to_string (gate_modules_count));
603
+ boost::replace_all (result, " $CONSTRAINT_SERIES_CODE$" , code);
604
+ boost::replace_all (result, " $MODULUS$" , to_string (PlaceholderParams::field_type::modulus));
605
+
606
+ std::ofstream out;
607
+ out.open (_folder_name + " /gate_" + to_string (gate_modules_count) + " .sol" );
608
+ out << result;
609
+ out.close ();
610
+ _gate_includes += " import \" ./gate_" + to_string (gate_modules_count) + " .sol\" ;\n " ;
611
+
612
+ ++gate_modules_count;
542
613
}
543
- print_gates_library_file (lib.first , lib.second , gate_codes);
544
614
}
545
615
546
616
std::stringstream power_functions;
@@ -557,36 +627,22 @@ namespace nil {
557
627
utils << utils_library;
558
628
utils.close ();
559
629
560
- if (inlined_gate_codes.size () > 0 ) {
561
- gate_argument_str << " \t\t uint256 sum;" << std::endl;
562
- gate_argument_str << " \t\t uint256 prod;" << std::endl;
563
- gate_argument_str << " \t\t uint256 gate;" << std::endl;
630
+ for ( i = 0 ; i < gate_modules_count; ++i ) {
631
+ std::string gate_eval_string = gate_call_template;
632
+ boost::replace_all (gate_eval_string, " $TEST_NAME$" , _test_name);
633
+ boost::replace_all (gate_eval_string, " $GATE_LIB_ID$" , to_string (i));
634
+ gate_argument_str << gate_eval_string << std::endl;
564
635
}
565
-
566
636
i = 0 ;
567
- for (const auto &gate: _constraint_system.gates ()){
568
- if (inlined_gate_codes.count (i) == 1 ) {
569
- gate_argument_str << " /* -- gate " << i << " is inlined -- */" << std::endl;
570
- gate_argument_str << gate_codes[i] << std::endl;
571
- } else {
572
- std::string gate_eval_string = gate_call_template;
573
- boost::replace_all (gate_eval_string, " $TEST_NAME$" , _test_name);
574
- boost::replace_all (gate_eval_string, " $GATE_LIB_ID$" , to_string (gate_lib[i]));
575
- boost::replace_all (gate_eval_string, " $GATE_ID$" , to_string (i));
576
- boost::replace_all (gate_eval_string, " $MODULUS$" , to_string (PlaceholderParams::field_type::modulus));
577
- gate_argument_str << gate_eval_string << std::endl;
578
- }
579
- ++i;
580
- }
581
637
582
- if (library_gates_buckets. size () > 0 ) {
638
+ if ( gate_modules_count > 0 ) {
583
639
std::ofstream out;
584
640
out.open (_folder_name + " /gate_libs_list.json" );
585
641
out << " [" << std::endl;
586
- for (i = 0 ; i < library_gates_buckets. size () -1 ; ++i ) {
642
+ for (i = 0 ; i < gate_modules_count -1 ; ++i ) {
587
643
out << " \" " << " gate_" << _test_name << " _" << i << " \" ," << std::endl;
588
644
}
589
- out << " \" " << " gate_" << _test_name << " _" << library_gates_buckets. size () -1 << " \" " << std::endl;
645
+ out << " \" " << " gate_" << _test_name << " _" << gate_modules_count -1 << " \" " << std::endl;
590
646
out << " ]" << std::endl;
591
647
out.close ();
592
648
}
@@ -794,7 +850,6 @@ namespace nil {
794
850
std::string _lookup_includes;
795
851
std::size_t _gates_contract_size_threshold;
796
852
std::size_t _lookups_contract_size_threshold;
797
- std::size_t _gates_library_size_threshold;
798
853
std::size_t _lookups_library_size_threshold;
799
854
};
800
855
}
0 commit comments