Browse Source

optimizing R1CS representation

extending parser
pull/8/head
mottla 5 years ago
parent
commit
1ea0dbf32c
8 changed files with 848 additions and 436 deletions
  1. +423
    -172
      .idea/workspace.xml
  2. +279
    -170
      circuitcompiler/Programm.go
  3. +20
    -10
      circuitcompiler/Programm_test.go
  4. +42
    -59
      circuitcompiler/circuit.go
  5. +1
    -1
      circuitcompiler/parser.go
  6. +16
    -5
      r1csqap/r1csqap.go
  7. +3
    -3
      snark.go
  8. +64
    -16
      snark_test.go

+ 423
- 172
.idea/workspace.xml

@ -1,17 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="63e1f2c4-8982-42df-a3f2-1673aa7aec22" name="Default Changelist" comment="-initial commit,&#10;-extending flat code compiler to a more general compiler&#10;-reducing all gates to multiplication gates only in the R1CS description of a program.">
<change afterPath="$PROJECT_DIR$/.idea/go-snark.iml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/modules.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/vcs.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
<list default="true" id="63e1f2c4-8982-42df-a3f2-1673aa7aec22" name="Default Changelist" comment="">
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/circuitcompiler/Programm.go" beforeDir="false" afterPath="$PROJECT_DIR$/circuitcompiler/Programm.go" afterDir="false" />
<change beforePath="$PROJECT_DIR$/circuitcompiler/Programm_test.go" beforeDir="false" afterPath="$PROJECT_DIR$/circuitcompiler/Programm_test.go" afterDir="false" />
<change beforePath="$PROJECT_DIR$/circuitcompiler/circuit.go" beforeDir="false" afterPath="$PROJECT_DIR$/circuitcompiler/circuit.go" afterDir="false" />
<change beforePath="$PROJECT_DIR$/snark_test.go" beforeDir="false" afterPath="$PROJECT_DIR$/snark_test.go" afterDir="false" />
</list>
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="SHOW_DIALOG" value="false" />
@ -21,33 +14,20 @@
</component>
<component name="FileEditorManager">
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
<file pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/circuitcompiler/Programm.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="325">
<caret line="31" column="48" selection-start-line="31" selection-start-column="48" selection-end-line="31" selection-end-column="48" />
<folding>
<element signature="e#25#92#0" expanded="true" />
<element signature="n#!!block;n#addFunction#0" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/circuitcompiler/Programm_test.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="318">
<caret line="30" column="19" selection-start-line="30" selection-start-column="19" selection-end-line="30" selection-end-column="19" />
<state relative-caret-position="149">
<caret line="24" column="26" selection-start-line="24" selection-start-column="26" selection-end-line="24" selection-end-column="26" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/circuitcompiler/circuit.go">
<entry file="file://$PROJECT_DIR$/circuitcompiler/test.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="145">
<caret line="91" selection-start-line="91" selection-end-line="91" />
<state relative-caret-position="330">
<caret line="22" column="10" selection-start-line="22" selection-start-column="10" selection-end-line="22" selection-end-column="10" />
</state>
</provider>
</entry>
@ -55,7 +35,7 @@
<file pinned="false" current-in-tab="false">
<entry file="file:///usr/local/go/src/testing/testing.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="193">
<state relative-caret-position="171">
<caret line="791" selection-start-line="791" selection-end-line="791" />
</state>
</provider>
@ -64,53 +44,62 @@
<file pinned="false" current-in-tab="false">
<entry file="file:///usr/local/go/src/runtime/panic.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="185">
<caret line="512" selection-start-line="512" selection-end-line="512" />
<state relative-caret-position="164">
<caret line="680" selection-start-line="680" selection-end-line="680" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file:///usr/local/go/src/runtime/mbitmap.go">
<entry file="file://$PROJECT_DIR$/circuitcompiler/Programm.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="193">
<caret line="910" selection-start-line="910" selection-end-line="910" />
<state relative-caret-position="191">
<caret line="399" lean-forward="true" selection-start-line="399" selection-end-line="399" />
<folding>
<element signature="e#25#165#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file:///usr/local/go/src/runtime/malloc.go">
<file pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/circuitcompiler/circuit.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="193">
<caret line="932" selection-start-line="932" selection-end-line="932" />
<state relative-caret-position="176">
<caret line="74" column="32" lean-forward="true" selection-start-line="74" selection-start-column="32" selection-end-line="74" selection-end-column="32" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/cli/main.go">
<entry file="file://$PROJECT_DIR$/r1csqap/r1csqap.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="225">
<caret line="15" column="25" selection-start-line="15" selection-start-column="25" selection-end-line="15" selection-end-column="25" />
<state relative-caret-position="585">
<caret line="45" column="5" selection-start-line="45" selection-start-column="5" selection-end-line="45" selection-end-column="5" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/circuitcompiler/lexer.go">
<entry file="file://$PROJECT_DIR$/snark_test.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="2715">
<caret line="185" selection-start-line="185" selection-end-line="185" />
<state relative-caret-position="330">
<caret line="30" column="15" selection-start-line="30" selection-start-column="15" selection-end-line="30" selection-end-column="15" />
<folding>
<element signature="e#15#188#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/circuitcompiler/parser.go">
<entry file="file://$PROJECT_DIR$/snark.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="163">
<caret line="60" selection-start-line="60" selection-end-line="60" />
<state relative-caret-position="945">
<caret line="72" selection-start-line="72" selection-end-line="72" selection-end-column="26" />
<folding>
<element signature="e#15#208#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
@ -121,8 +110,14 @@
<findStrings>
<find>arnaucube</find>
<find>oneConst</find>
<find>getmain</find>
<find>opera</find>
<find>getmain</find>
<find>one</find>
<find>oneCo</find>
<find>md</find>
<find>new</find>
<find>newpro</find>
<find>clone</find>
</findStrings>
<replaceStrings>
<replace>mottla</replace>
@ -142,26 +137,30 @@
<option value="$PROJECT_DIR$/bn128/g1.go" />
<option value="$PROJECT_DIR$/bn128/g2.go" />
<option value="$PROJECT_DIR$/cli/main.go" />
<option value="$PROJECT_DIR$/r1csqap/r1csqap.go" />
<option value="$PROJECT_DIR$/r1csqap/r1csqap_test.go" />
<option value="$PROJECT_DIR$/snark.go" />
<option value="$PROJECT_DIR$/circuitcompiler/circuit_test.go" />
<option value="$PROJECT_DIR$/circuitcompiler/lexer.go" />
<option value="$PROJECT_DIR$/snark_test.go" />
<option value="$PROJECT_DIR$/circuitcompiler/temp" />
<option value="$PROJECT_DIR$/README.md" />
<option value="$PROJECT_DIR$/../../go-lexer/lexer.go" />
<option value="$PROJECT_DIR$/circuitcompiler/lexer/lexer.go" />
<option value="$PROJECT_DIR$/circuitcompiler/lexer/lexer_test/lexer_test.go" />
<option value="$PROJECT_DIR$/circuitcompiler/parser.go" />
<option value="$PROJECT_DIR$/circuitcompiler/temp" />
<option value="$PROJECT_DIR$/r1csqap/r1csqap.go" />
<option value="$PROJECT_DIR$/snark.go" />
<option value="$PROJECT_DIR$/snark_test.go" />
<option value="$PROJECT_DIR$/circuitcompiler/Programm_test.go" />
<option value="$PROJECT_DIR$/circuitcompiler/test.py" />
<option value="$PROJECT_DIR$/circuitcompiler/circuit.go" />
<option value="$PROJECT_DIR$/circuitcompiler/Programm.go" />
</list>
</option>
</component>
<component name="ProjectFrameBounds" extendedState="6">
<option name="x" value="65" />
<option name="y" value="-4" />
<option name="width" value="1855" />
<option name="height" value="1012" />
<option name="x" value="611" />
<option name="y" value="52" />
<option name="width" value="1853" />
<option name="height" value="1004" />
</component>
<component name="ProjectView">
<navigator proportions="" version="1">
@ -183,8 +182,62 @@
</path>
<path>
<item name="go-snark" type="b2602c69:ProjectViewProjectNode" />
<item name="go-snark" type="462c0819:PsiDirectoryNode" />
<item name="cli" type="462c0819:PsiDirectoryNode" />
<item name="External Libraries" type="cb654da1:ExternalLibrariesNode" />
</path>
<path>
<item name="go-snark" type="b2602c69:ProjectViewProjectNode" />
<item name="External Libraries" type="cb654da1:ExternalLibrariesNode" />
<item name="Go SDK 1.11.2" type="20ee2d1f:SyntheticLibraryElementNode" />
</path>
<path>
<item name="go-snark" type="b2602c69:ProjectViewProjectNode" />
<item name="External Libraries" type="cb654da1:ExternalLibrariesNode" />
<item name="Go SDK 1.11.2" type="20ee2d1f:SyntheticLibraryElementNode" />
<item name="src" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="go-snark" type="b2602c69:ProjectViewProjectNode" />
<item name="External Libraries" type="cb654da1:ExternalLibrariesNode" />
<item name="Go SDK 1.11.2" type="20ee2d1f:SyntheticLibraryElementNode" />
<item name="src" type="462c0819:PsiDirectoryNode" />
<item name="go" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="go-snark" type="b2602c69:ProjectViewProjectNode" />
<item name="External Libraries" type="cb654da1:ExternalLibrariesNode" />
<item name="Go SDK 1.11.2" type="20ee2d1f:SyntheticLibraryElementNode" />
<item name="src" type="462c0819:PsiDirectoryNode" />
<item name="go" type="462c0819:PsiDirectoryNode" />
<item name="parser" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="go-snark" type="b2602c69:ProjectViewProjectNode" />
<item name="External Libraries" type="cb654da1:ExternalLibrariesNode" />
<item name="Go SDK 1.11.2" type="20ee2d1f:SyntheticLibraryElementNode" />
<item name="src" type="462c0819:PsiDirectoryNode" />
<item name="go" type="462c0819:PsiDirectoryNode" />
<item name="token" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="go-snark" type="b2602c69:ProjectViewProjectNode" />
<item name="External Libraries" type="cb654da1:ExternalLibrariesNode" />
<item name="Go SDK 1.11.2" type="20ee2d1f:SyntheticLibraryElementNode" />
<item name="src" type="462c0819:PsiDirectoryNode" />
<item name="image" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="go-snark" type="b2602c69:ProjectViewProjectNode" />
<item name="External Libraries" type="cb654da1:ExternalLibrariesNode" />
<item name="Go SDK 1.11.2" type="20ee2d1f:SyntheticLibraryElementNode" />
<item name="src" type="462c0819:PsiDirectoryNode" />
<item name="index" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="go-snark" type="b2602c69:ProjectViewProjectNode" />
<item name="External Libraries" type="cb654da1:ExternalLibrariesNode" />
<item name="Go SDK 1.11.2" type="20ee2d1f:SyntheticLibraryElementNode" />
<item name="src" type="462c0819:PsiDirectoryNode" />
<item name="mime" type="462c0819:PsiDirectoryNode" />
</path>
</expand>
<select />
@ -199,9 +252,12 @@
<property name="go.gopath.indexing.explicitly.defined" value="true" />
<property name="go.import.settings.migrated" value="true" />
<property name="go.sdk.automatically.set" value="true" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/circuitcompiler" />
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
<property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
<property name="nodejs_npm_path_reset_for_default_project" value="true" />
<property name="nodejs_package_manager_path" value="npm" />
<property name="restartRequiresConfirmation" value="false" />
<property name="settings.editor.selected.configurable" value="preferences.intentionPowerPack" />
</component>
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
@ -220,7 +276,29 @@
</list>
</option>
</component>
<component name="RunManager">
<component name="RunManager" selected="Go Test.TestNewProgramm in github.com/mottla/go-snark/circuitcompiler">
<configuration name="TestGenerateProofs in github.com/mottla/go-snark" type="GoTestRunConfiguration" factoryName="Go Test" temporary="true" nameIsGenerated="true">
<module name="go-snark" />
<working_directory value="$PROJECT_DIR$" />
<framework value="gotest" />
<kind value="PACKAGE" />
<package value="github.com/mottla/go-snark" />
<directory value="$PROJECT_DIR$/" />
<filePath value="$PROJECT_DIR$/" />
<pattern value="^TestGenerateProofs$" />
<method v="2" />
</configuration>
<configuration name="TestNewProgramm in github.com/mottla/go-snark" type="GoTestRunConfiguration" factoryName="Go Test" temporary="true" nameIsGenerated="true">
<module name="go-snark" />
<working_directory value="$PROJECT_DIR$" />
<framework value="gotest" />
<kind value="PACKAGE" />
<package value="github.com/mottla/go-snark" />
<directory value="$PROJECT_DIR$/" />
<filePath value="$PROJECT_DIR$/" />
<pattern value="^TestNewProgramm$" />
<method v="2" />
</configuration>
<configuration name="TestNewProgramm in github.com/mottla/go-snark/circuitcompiler" type="GoTestRunConfiguration" factoryName="Go Test" temporary="true" nameIsGenerated="true">
<module name="go-snark" />
<working_directory value="$PROJECT_DIR$/circuitcompiler" />
@ -232,41 +310,67 @@
<pattern value="^TestNewProgramm$" />
<method v="2" />
</configuration>
<configuration name="TestProgramm_BuildConstraintTree in github.com/mottla/go-snark/circuitcompiler" type="GoTestRunConfiguration" factoryName="Go Test" temporary="true" nameIsGenerated="true">
<module name="go-snark" />
<working_directory value="$PROJECT_DIR$/circuitcompiler" />
<framework value="gotest" />
<kind value="PACKAGE" />
<package value="github.com/mottla/go-snark/circuitcompiler" />
<directory value="$PROJECT_DIR$/" />
<filePath value="$PROJECT_DIR$/" />
<pattern value="^TestProgramm_BuildConstraintTree$" />
<method v="2" />
</configuration>
<configuration name="Test_LexerRewind2 in github.com/mottla/go-snark/circuitcompiler/lexer/lexer_test" type="GoTestRunConfiguration" factoryName="Go Test" temporary="true" nameIsGenerated="true">
<module name="go-snark" />
<working_directory value="$PROJECT_DIR$/circuitcompiler/lexer/lexer_test" />
<framework value="gotest" />
<kind value="PACKAGE" />
<package value="github.com/mottla/go-snark/circuitcompiler/lexer/lexer_test" />
<directory value="$PROJECT_DIR$/" />
<filePath value="$PROJECT_DIR$/" />
<pattern value="^Test_LexerRewind2$" />
<method v="2" />
</configuration>
<recent_temporary>
<list>
<item itemvalue="Go Test.TestNewProgramm in github.com/mottla/go-snark/circuitcompiler" />
<item itemvalue="Go Test.TestProgramm_BuildConstraintTree in github.com/mottla/go-snark/circuitcompiler" />
<item itemvalue="Go Test.TestNewProgramm in github.com/mottla/go-snark" />
<item itemvalue="Go Test.TestGenerateProofs in github.com/mottla/go-snark" />
<item itemvalue="Go Test.Test_LexerRewind2 in github.com/mottla/go-snark/circuitcompiler/lexer/lexer_test" />
</list>
</recent_temporary>
</component>
<component name="TestHistory">
<history-entry file="TestNewProgramm_in_github_com_mottla_go-snark_circuitcompiler - 2019.05.13 at 18h 44m 54s.xml">
<history-entry file="TestNewProgramm_in_github_com_mottla_go-snark_circuitcompiler - 2019.05.23 at 09h 52m 13s.xml">
<configuration name="TestNewProgramm in github.com/mottla/go-snark/circuitcompiler" configurationId="GoTestRunConfiguration" />
</history-entry>
<history-entry file="TestNewProgramm_in_github_com_mottla_go-snark_circuitcompiler - 2019.05.13 at 18h 53m 19s.xml">
<history-entry file="TestNewProgramm_in_github_com_mottla_go-snark_circuitcompiler - 2019.05.23 at 09h 57m 21s.xml">
<configuration name="TestNewProgramm in github.com/mottla/go-snark/circuitcompiler" configurationId="GoTestRunConfiguration" />
</history-entry>
<history-entry file="TestNewProgramm_in_github_com_mottla_go-snark_circuitcompiler - 2019.05.13 at 19h 01m 05s.xml">
<history-entry file="TestNewProgramm_in_github_com_mottla_go-snark_circuitcompiler - 2019.05.23 at 09h 57m 24s.xml">
<configuration name="TestNewProgramm in github.com/mottla/go-snark/circuitcompiler" configurationId="GoTestRunConfiguration" />
</history-entry>
<history-entry file="TestNewProgramm_in_github_com_mottla_go-snark_circuitcompiler - 2019.05.13 at 19h 01m 16s.xml">
<history-entry file="TestNewProgramm_in_github_com_mottla_go-snark_circuitcompiler - 2019.05.23 at 09h 58m 26s.xml">
<configuration name="TestNewProgramm in github.com/mottla/go-snark/circuitcompiler" configurationId="GoTestRunConfiguration" />
</history-entry>
<history-entry file="TestNewProgramm_in_github_com_mottla_go-snark_circuitcompiler - 2019.05.13 at 19h 05m 45s.xml">
<history-entry file="TestNewProgramm_in_github_com_mottla_go-snark_circuitcompiler - 2019.05.23 at 10h 10m 46s.xml">
<configuration name="TestNewProgramm in github.com/mottla/go-snark/circuitcompiler" configurationId="GoTestRunConfiguration" />
</history-entry>
<history-entry file="TestNewProgramm_in_github_com_mottla_go-snark_circuitcompiler - 2019.05.13 at 19h 05m 47s.xml">
<history-entry file="TestNewProgramm_in_github_com_mottla_go-snark_circuitcompiler - 2019.05.23 at 10h 10m 48s.xml">
<configuration name="TestNewProgramm in github.com/mottla/go-snark/circuitcompiler" configurationId="GoTestRunConfiguration" />
</history-entry>
<history-entry file="TestNewProgramm_in_github_com_mottla_go-snark_circuitcompiler - 2019.05.13 at 19h 07m 14s.xml">
<history-entry file="TestNewProgramm_in_github_com_mottla_go-snark_circuitcompiler - 2019.05.23 at 10h 14m 40s.xml">
<configuration name="TestNewProgramm in github.com/mottla/go-snark/circuitcompiler" configurationId="GoTestRunConfiguration" />
</history-entry>
<history-entry file="TestNewProgramm_in_github_com_mottla_go-snark_circuitcompiler - 2019.05.13 at 19h 15m 18s.xml">
<history-entry file="TestNewProgramm_in_github_com_mottla_go-snark_circuitcompiler - 2019.05.23 at 10h 16m 30s.xml">
<configuration name="TestNewProgramm in github.com/mottla/go-snark/circuitcompiler" configurationId="GoTestRunConfiguration" />
</history-entry>
<history-entry file="TestNewProgramm_in_github_com_mottla_go-snark_circuitcompiler - 2019.05.13 at 19h 16m 13s.xml">
<history-entry file="TestNewProgramm_in_github_com_mottla_go-snark_circuitcompiler - 2019.05.23 at 10h 16m 31s.xml">
<configuration name="TestNewProgramm in github.com/mottla/go-snark/circuitcompiler" configurationId="GoTestRunConfiguration" />
</history-entry>
<history-entry file="TestNewProgramm_in_github_com_mottla_go-snark_circuitcompiler - 2019.05.13 at 19h 17m 48s.xml">
<history-entry file="TestNewProgramm_in_github_com_mottla_go-snark_circuitcompiler - 2019.05.23 at 10h 21m 54s.xml">
<configuration name="TestNewProgramm in github.com/mottla/go-snark/circuitcompiler" configurationId="GoTestRunConfiguration" />
</history-entry>
</component>
@ -281,14 +385,15 @@
</component>
<component name="ToolWindowManager">
<frame x="64" y="-11" width="1857" height="1020" extended-state="6" />
<editor active="true" />
<layout>
<window_info content_ui="combo" id="Project" order="0" visible="true" weight="0.14206745" />
<window_info content_ui="combo" id="Project" order="0" visible="true" weight="0.16141514" />
<window_info id="Structure" order="1" side_tool="true" weight="0.25" />
<window_info id="Favorites" order="2" side_tool="true" />
<window_info anchor="bottom" id="Message" order="0" />
<window_info anchor="bottom" id="Find" order="1" weight="0.32893288" />
<window_info active="true" anchor="bottom" id="Run" order="2" visible="true" weight="0.32893288" />
<window_info anchor="bottom" id="Debug" order="3" weight="0.39933994" />
<window_info active="true" anchor="bottom" id="Run" order="2" visible="true" weight="0.3751375" />
<window_info anchor="bottom" id="Debug" order="3" weight="0.39823982" />
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
<window_info anchor="bottom" id="TODO" order="6" weight="0.19031903" />
@ -296,67 +401,112 @@
<window_info anchor="bottom" id="Database Changes" order="8" />
<window_info anchor="bottom" id="Version Control" order="9" />
<window_info anchor="bottom" id="Terminal" order="10" />
<window_info anchor="bottom" id="Event Log" order="11" side_tool="true" />
<window_info anchor="bottom" id="Event Log" order="11" side_tool="true" weight="0.32893288" />
<window_info anchor="bottom" id="Messages" order="12" weight="0.32993197" />
<window_info anchor="bottom" id="Inspection Results" order="13" weight="0.32893288" />
<window_info anchor="right" id="Commander" internal_type="SLIDING" order="0" type="SLIDING" weight="0.4" />
<window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
<window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
<window_info anchor="right" id="Database" order="3" />
</layout>
<layout-to-restore>
<window_info content_ui="combo" id="Project" order="0" visible="true" weight="0.15754561" />
<window_info id="Structure" order="1" side_tool="true" weight="0.25" />
<window_info id="Favorites" order="2" side_tool="true" />
<window_info anchor="bottom" id="Message" order="0" />
<window_info anchor="bottom" id="Find" order="1" weight="0.32893288" />
<window_info active="true" anchor="bottom" id="Run" order="2" visible="true" weight="0.37623763" />
<window_info anchor="bottom" id="Debug" order="3" weight="0.3984109" />
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
<window_info anchor="bottom" id="TODO" order="6" weight="0.19031903" />
<window_info anchor="bottom" id="Docker" order="7" show_stripe_button="false" />
<window_info anchor="bottom" id="Database Changes" order="8" />
<window_info anchor="bottom" id="Version Control" order="9" />
<window_info anchor="bottom" id="Terminal" order="10" />
<window_info anchor="bottom" id="Event Log" order="11" side_tool="true" />
<window_info anchor="bottom" id="Messages" order="12" />
<window_info anchor="right" id="Commander" internal_type="SLIDING" order="0" type="SLIDING" weight="0.4" />
<window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
<window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
<window_info anchor="right" id="Database" order="3" />
</layout-to-restore>
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="1" />
</component>
<component name="VcsManagerConfiguration">
<MESSAGE value="-initial commit,&#10;-extending flat code compiler to a more general compiler&#10;-reducing all gates to multiplication gates only in the R1CS description of a program." />
<option name="LAST_COMMIT_MESSAGE" value="-initial commit,&#10;-extending flat code compiler to a more general compiler&#10;-reducing all gates to multiplication gates only in the R1CS description of a program." />
<MESSAGE value="allow constants in function calls: like foo(5,a)&#10;-prepair constraints is now done during parsing" />
<MESSAGE value="reducing multiplication gates with constants" />
<MESSAGE value="optimizing R1CS representation" />
<MESSAGE value="cleaning up a bit" />
<MESSAGE value="working on multiplication gate reduction algo" />
<option name="LAST_COMMIT_MESSAGE" value="working on multiplication gate reduction algo" />
</component>
<component name="XDebuggerManager">
<breakpoint-manager>
<breakpoints>
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/circuitcompiler/Programm.go</url>
<line>75</line>
<properties />
<option name="timeStamp" value="2" />
<url>file://$PROJECT_DIR$/circuitcompiler/parser.go</url>
<line>81</line>
<option name="timeStamp" value="12" />
</line-breakpoint>
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/circuitcompiler/Programm.go</url>
<url>file://$PROJECT_DIR$/circuitcompiler/parser.go</url>
<line>82</line>
<properties />
<option name="timeStamp" value="3" />
<option name="timeStamp" value="13" />
</line-breakpoint>
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/circuitcompiler/parser.go</url>
<line>83</line>
<option name="timeStamp" value="14" />
</line-breakpoint>
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/r1csqap/r1csqap.go</url>
<line>228</line>
<option name="timeStamp" value="43" />
</line-breakpoint>
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/r1csqap/r1csqap.go</url>
<line>229</line>
<option name="timeStamp" value="44" />
</line-breakpoint>
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/r1csqap/r1csqap.go</url>
<line>83</line>
<option name="timeStamp" value="45" />
</line-breakpoint>
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/r1csqap/r1csqap.go</url>
<line>74</line>
<option name="timeStamp" value="46" />
</line-breakpoint>
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/snark_test.go</url>
<line>113</line>
<option name="timeStamp" value="47" />
</line-breakpoint>
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/r1csqap/r1csqap.go</url>
<line>135</line>
<option name="timeStamp" value="48" />
</line-breakpoint>
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/circuitcompiler/Programm.go</url>
<line>66</line>
<properties />
<option name="timeStamp" value="4" />
<line>244</line>
<option name="timeStamp" value="79" />
</line-breakpoint>
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/circuitcompiler/parser.go</url>
<line>60</line>
<url>file://$PROJECT_DIR$/circuitcompiler/Programm.go</url>
<line>111</line>
<properties />
<option name="timeStamp" value="10" />
<option name="timeStamp" value="105" />
</line-breakpoint>
</breakpoints>
</breakpoint-manager>
</component>
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/bn128/bn128.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="90">
<caret line="6" column="25" selection-start-line="6" selection-start-column="25" selection-end-line="6" selection-end-column="25" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/bn128/bn128_test.go">
<provider selected="true" editor-type-id="text-editor">
<state>
<folding>
<element signature="e#15#96#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/bn128/g1.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="16">
@ -377,86 +527,154 @@
<entry file="file://$PROJECT_DIR$/bn128/g2_test.go">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/fields/fq.go">
<entry file="file://$PROJECT_DIR$/fields/fq12.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-59" />
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/fields/fq2.go">
<entry file="file://$PROJECT_DIR$/fields/fqn_test.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-59" />
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/fields/fq6.go">
<entry file="file://$PROJECT_DIR$/.gitignore">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/build-cli.sh">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/go.mod">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/go.sum">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/r1csqap/README.md">
<provider selected="true" editor-type-id="split-provider[text-editor;markdown-preview-editor]">
<state split_layout="SPLIT">
<first_editor />
<second_editor />
</state>
</provider>
</entry>
<entry file="file:///usr/local/go/src/runtime/malloc.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-59" />
<state relative-caret-position="193">
<caret line="932" selection-start-line="932" selection-end-line="932" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/fields/fq12.go">
<entry file="file://$PROJECT_DIR$/circuitcompiler/temp" />
<entry file="file:///usr/local/go/src/runtime/mbitmap.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-59" />
<state relative-caret-position="193">
<caret line="910" selection-start-line="910" selection-end-line="910" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/fields/fqn_test.go">
<entry file="file://$PROJECT_DIR$/cli/main.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-59" />
<state relative-caret-position="225">
<caret line="15" column="25" selection-start-line="15" selection-start-column="25" selection-end-line="15" selection-end-column="25" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/.gitignore">
<entry file="file://$PROJECT_DIR$/README.md">
<provider selected="true" editor-type-id="split-provider[text-editor;markdown-preview-editor]">
<state split_layout="SPLIT">
<first_editor relative-caret-position="90">
<caret line="6" column="74" selection-start-line="6" selection-start-column="74" selection-end-line="6" selection-end-column="74" />
</first_editor>
<second_editor />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/r1csqapFloat/r1csqapFloat_test.go">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/build-cli.sh">
<entry file="file://$PROJECT_DIR$/circuitcompiler/lexer/.idea/vcs.xml" />
<entry file="file://$PROJECT_DIR$/circuitcompiler/lexer/lexer.go" />
<entry file="file://$PROJECT_DIR$/circuitcompiler/lexer/lexer_test/lexer_test.go" />
<entry file="file:///usr/local/go/src/crypto/md5/md5.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="2040">
<caret line="140" column="15" selection-start-line="140" selection-start-column="15" selection-end-line="140" selection-end-column="15" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/../../go-lexer/lexer.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="5115">
<caret line="346" column="12" lean-forward="true" selection-start-line="346" selection-start-column="12" selection-end-line="346" selection-end-column="12" />
</state>
</provider>
</entry>
<entry file="file:///usr/local/go/src/image/png/example_test.go">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/go.mod">
<entry file="file:///usr/local/go/src/image/png/reader_test.go">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/go.sum">
<entry file="file:///usr/local/go/src/mime/type_dragonfly.go">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/snark_test.go">
<entry file="file:///usr/local/go/src/math/big/int.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-72">
<caret line="5" column="25" selection-start-line="5" selection-start-column="25" selection-end-line="5" selection-end-column="25" />
<state relative-caret-position="293">
<caret line="101" column="14" selection-start-line="101" selection-start-column="14" selection-end-line="101" selection-end-column="14" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/snark.go">
<entry file="file:///usr/local/go/src/go/token/token.go">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file:///usr/local/go/src/go/parser/short_test.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="91">
<caret line="10" column="25" selection-start-line="10" selection-start-column="25" selection-end-line="10" selection-end-column="25" />
<state relative-caret-position="482">
<caret line="131" column="32" lean-forward="true" selection-start-line="131" selection-start-column="32" selection-end-line="131" selection-end-column="32" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/r1csqap/r1csqap_test.go">
<entry file="file:///usr/local/go/src/image/png/testdata/benchGray.png">
<provider selected="true" editor-type-id="images" />
</entry>
<entry file="file:///usr/local/go/src/image/png/testdata/benchNRGBA-gradient.png">
<provider selected="true" editor-type-id="images" />
</entry>
<entry file="file:///usr/local/go/src/image/png/testdata/benchPaletted.png">
<provider selected="true" editor-type-id="images" />
</entry>
<entry file="file://$PROJECT_DIR$/circuitcompiler/parser.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-13">
<caret line="7" column="25" selection-start-line="7" selection-start-column="25" selection-end-line="7" selection-end-column="25" />
<state relative-caret-position="1830">
<caret line="127" column="9" selection-start-line="127" selection-start-column="9" selection-end-line="127" selection-end-column="9" />
<folding>
<element signature="e#25#72#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/r1csqap/r1csqap.go">
<entry file="file://$PROJECT_DIR$/fields/fq6.go">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file:///usr/local/go/src/math/abs.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-28">
<caret line="6" column="25" selection-start-line="6" selection-start-column="25" selection-end-line="6" selection-end-column="25" />
<state relative-caret-position="180">
<caret line="12" column="54" selection-start-line="12" selection-start-column="41" selection-end-line="12" selection-end-column="54" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/r1csqap/README.md">
<provider selected="true" editor-type-id="split-provider[text-editor;markdown-preview-editor]">
<state split_layout="SPLIT">
<first_editor />
<second_editor />
<entry file="file:///usr/local/go/src/go/constant/value.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="8130">
<caret line="551" column="5" selection-start-line="551" selection-start-column="5" selection-end-line="551" selection-end-column="5" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/README.md">
<provider selected="true" editor-type-id="split-provider[text-editor;markdown-preview-editor]">
<state split_layout="SPLIT">
<first_editor relative-caret-position="135">
<caret line="9" column="19" selection-start-line="9" selection-start-column="19" selection-end-line="9" selection-end-column="19" />
</first_editor>
<second_editor />
<entry file="file://$PROJECT_DIR$/circuitcompiler/lexer.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="75">
<caret line="9" column="5" selection-start-line="9" selection-start-column="5" selection-end-line="9" selection-end-column="5" />
</state>
</provider>
</entry>
@ -467,86 +685,119 @@
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/circuitcompiler/lexer.go">
<entry file="file://$PROJECT_DIR$/r1csqap/r1csqap_test.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="2715">
<caret line="185" selection-start-line="185" selection-end-line="185" />
<state relative-caret-position="435">
<caret line="36" column="27" selection-start-line="36" selection-start-column="27" selection-end-line="36" selection-end-column="27" />
<folding>
<element signature="e#17#135#0" expanded="true" />
<element signature="n#!!block;n#TestPol#0" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/cli/main.go">
<entry file="file://$PROJECT_DIR$/fields/fq2.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="225">
<caret line="15" column="25" selection-start-line="15" selection-start-column="25" selection-end-line="15" selection-end-column="25" />
<state relative-caret-position="75">
<caret line="7" column="7" selection-start-line="7" selection-start-column="7" selection-end-line="7" selection-end-column="7" />
</state>
</provider>
</entry>
<entry file="file:///usr/local/go/src/runtime/mbitmap.go">
<entry file="file://$PROJECT_DIR$/bn128/bn128.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="193">
<caret line="910" selection-start-line="910" selection-end-line="910" />
<caret line="18" column="25" selection-start-line="18" selection-start-column="25" selection-end-line="18" selection-end-column="25" />
<folding>
<element signature="e#15#85#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file:///usr/local/go/src/runtime/malloc.go">
<entry file="file://$PROJECT_DIR$/fields/fq.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="193">
<caret line="932" selection-start-line="932" selection-end-line="932" />
<state relative-caret-position="990">
<caret line="70" column="13" selection-start-line="70" selection-start-column="13" selection-end-line="70" selection-end-column="13" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/circuitcompiler/temp">
<entry file="file:///usr/local/go/src/builtin/builtin.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="15">
<caret line="1" selection-start-line="1" selection-end-line="1" />
<state relative-caret-position="359">
<caret line="182" column="5" selection-start-line="182" selection-start-column="5" selection-end-line="182" selection-end-column="5" />
</state>
</provider>
</entry>
<entry file="file:///usr/local/go/src/testing/testing.go">
<entry file="file://$PROJECT_DIR$/circuitcompiler/test.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="193">
<caret line="791" selection-start-line="791" selection-end-line="791" />
<state relative-caret-position="330">
<caret line="22" column="10" selection-start-line="22" selection-start-column="10" selection-end-line="22" selection-end-column="10" />
</state>
</provider>
</entry>
<entry file="file:///usr/local/go/src/runtime/panic.go">
<entry file="file://$PROJECT_DIR$/r1csqap/r1csqap.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="185">
<caret line="512" selection-start-line="512" selection-end-line="512" />
<state relative-caret-position="585">
<caret line="45" column="5" selection-start-line="45" selection-start-column="5" selection-end-line="45" selection-end-column="5" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/circuitcompiler/parser.go">
<entry file="file://$PROJECT_DIR$/snark_test.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="163">
<caret line="60" selection-start-line="60" selection-end-line="60" />
<state relative-caret-position="330">
<caret line="30" column="15" selection-start-line="30" selection-start-column="15" selection-end-line="30" selection-end-column="15" />
<folding>
<element signature="e#15#188#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/circuitcompiler/Programm_test.go">
<entry file="file://$PROJECT_DIR$/snark.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="318">
<caret line="30" column="19" selection-start-line="30" selection-start-column="19" selection-end-line="30" selection-end-column="19" />
<state relative-caret-position="945">
<caret line="72" selection-start-line="72" selection-end-line="72" selection-end-column="26" />
<folding>
<element signature="e#15#208#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/circuitcompiler/circuit.go">
<entry file="file:///usr/local/go/src/testing/testing.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="145">
<caret line="91" selection-start-line="91" selection-end-line="91" />
<state relative-caret-position="171">
<caret line="791" selection-start-line="791" selection-end-line="791" />
</state>
</provider>
</entry>
<entry file="file:///usr/local/go/src/runtime/panic.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="164">
<caret line="680" selection-start-line="680" selection-end-line="680" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/circuitcompiler/Programm_test.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="149">
<caret line="24" column="26" selection-start-line="24" selection-start-column="26" selection-end-line="24" selection-end-column="26" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/circuitcompiler/Programm.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="325">
<caret line="31" column="48" selection-start-line="31" selection-start-column="48" selection-end-line="31" selection-end-column="48" />
<state relative-caret-position="191">
<caret line="399" lean-forward="true" selection-start-line="399" selection-end-line="399" />
<folding>
<element signature="e#25#92#0" expanded="true" />
<element signature="n#!!block;n#addFunction#0" />
<element signature="e#25#165#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/circuitcompiler/circuit.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="176">
<caret line="74" column="32" lean-forward="true" selection-start-line="74" selection-start-column="32" selection-end-line="74" selection-end-column="32" />
</state>
</provider>
</entry>
</component>
</project>

+ 279
- 170
circuitcompiler/Programm.go

@ -2,15 +2,24 @@ package circuitcompiler
import (
"fmt"
"github.com/mottla/go-snark/bn128"
"github.com/mottla/go-snark/fields"
"github.com/mottla/go-snark/r1csqap"
"math/big"
)
type utils struct {
Bn bn128.Bn128
FqR fields.Fq
PF r1csqap.PolynomialField
}
type Program struct {
functions map[string]*Circuit
signals []string
globalInputs []*Constraint
R1CS struct {
functions map[string]*Circuit
globalInputs []Constraint
arithmeticEnvironment utils //find a better name
extendedFunctionRenamer func(context *Circuit, c Constraint) (newContext *Circuit)
R1CS struct {
A [][]*big.Int
B [][]*big.Int
C [][]*big.Int
@ -30,23 +39,18 @@ func (p *Program) BuildConstraintTrees() {
for _, circuit := range p.functions {
//circuit.addConstraint(p.oneConstraint())
fName := composeNewFunction(circuit.Name, circuit.Inputs)
root := &gate{value: circuit.constraintMap[fName]}
root := circuit.gateMap[fName]
functionRootMap[fName] = root
circuit.root = root
}
for _, circuit := range p.functions {
buildTree(circuit.constraintMap, circuit.root)
circuit.buildTree(root)
}
return
}
func buildTree(con map[string]*Constraint, g *gate) {
if _, ex := con[g.value.Out]; ex {
func (c *Circuit) buildTree(g *gate) {
if _, ex := c.gateMap[g.value.Out]; ex {
if g.OperationType()&(IN|CONST) != 0 {
return
}
@ -54,28 +58,30 @@ func buildTree(con map[string]*Constraint, g *gate) {
panic(fmt.Sprintf("undefined variable %s", g.value.Out))
}
if g.OperationType() == FUNC {
g.funcInputs = []*gate{}
//g.funcInputs = []*gate{}
for _, in := range g.value.Inputs {
if constr, ex := con[in]; ex {
newGate := &gate{value: constr}
g.funcInputs = append(g.funcInputs, newGate)
buildTree(con, newGate)
if gate, ex := c.gateMap[in]; ex {
//sadf
g.funcInputs = append(g.funcInputs, gate)
//note that we do repeated work here. the argument
c.buildTree(gate)
} else {
panic(fmt.Sprintf("undefined value %s", g.value.V1))
panic(fmt.Sprintf("undefined argument %s", g.value.V1))
}
}
return
}
if constr, ex := con[g.value.V1]; ex {
g.addLeft(constr)
buildTree(con, g.left)
if constr, ex := c.gateMap[g.value.V1]; ex {
g.left = constr
c.buildTree(g.left)
} else {
panic(fmt.Sprintf("undefined value %s", g.value.V1))
}
if constr, ex := con[g.value.V2]; ex {
g.addRight(constr)
buildTree(con, g.right)
if constr, ex := c.gateMap[g.value.V2]; ex {
g.right = constr
c.buildTree(g.right)
} else {
panic(fmt.Sprintf("undefined value %s", g.value.V2))
}
@ -89,153 +95,270 @@ func (p *Program) ReduceCombinedTree() (orderedmGates []gate) {
functionRootMap[k] = v.root
}
functionRenamer := func(c *Constraint) *gate {
p.extendedFunctionRenamer = func(context *Circuit, c Constraint) (nextContext *Circuit) {
if c.Op != FUNC {
panic("not a function")
}
if b, name, in := isFunction(c.Out); b {
if _, ex := context.gateMap[c.Out]; !ex {
panic("constraint mus be within the context circuit")
}
if k, v := p.functions[name]; v {
if b, name, in := isFunction(c.Out); b {
if newContext, v := p.functions[name]; v {
//fmt.Println("unrenamed thing")
//PrintTree(k.root)
k.renameInputs(in)
for i, argument := range in {
if gate, ex := context.gateMap[argument]; ex {
oldGate := newContext.gateMap[newContext.Inputs[i]]
//we take the old gate which was nothing but a input
//and link this input to its constituents comming from the calling context.
//i think this is pretty neat
oldGate.value = gate.value
oldGate.right = gate.right
oldGate.left = gate.left
} else {
panic("not expected")
}
}
newContext.renameInputs(in)
//fmt.Println("renamed thing")
//PrintTree(k.root)
return k.root
return newContext
}
} else {
panic("not a function dude")
}
panic("not a function dude")
return nil
}
//traverseCombinedMultiplicationGates(p.getMainCircut().root, mGatesUsed, &orderedmGates, functionRootMap, functionRenamer, false, false)
traverseCombinedMultiplicationGates(p.getMainCircut().root, mGatesUsed, &orderedmGates, functionRootMap, functionRenamer, false, false)
//for _, g := range mGates {
// orderedmGates[len(orderedmGates)-1-g.index] = g
//}
//markMgates(p.getMainCircut().root, mGatesUsed, &orderedmGates, functionRenamer, false, false)
p.markMgates2(p.getMainCircut(), p.getMainCircut().root, mGatesUsed, &orderedmGates, false, false)
return orderedmGates
}
func traverseCombinedMultiplicationGates(root *gate, mGatesUsed map[string]bool, orderedmGates *[]gate, functionRootMap map[string]*gate, functionRenamer func(c *Constraint) *gate, negate bool, inverse bool) {
//if root == nil {
// return
//}
//fmt.Printf("\n%p",mGatesUsed)
if root.OperationType() == FUNC {
//if a input has already been built, we let this subroutine know
//newMap := make(map[string]bool)
for _, in := range root.funcInputs {
func (p *Program) markMgates2(contextCircut *Circuit, root *gate, mGatesUsed map[string]bool, orderedmGates *[]gate, negate bool, inverse bool) (isConstant bool) {
if _, ex := mGatesUsed[in.value.Out]; ex {
//newMap[in.value.Out] = true
} else {
traverseCombinedMultiplicationGates(in, mGatesUsed, orderedmGates, functionRootMap, functionRenamer, negate, inverse)
}
}
//mGatesUsed[root.value.Out] = true
traverseCombinedMultiplicationGates(functionRenamer(root.value), mGatesUsed, orderedmGates, functionRootMap, functionRenamer, negate, inverse)
if root.OperationType() == IN {
return false
}
if root.OperationType() == CONST {
return true
}
if root.OperationType() == FUNC {
nextContext := p.extendedFunctionRenamer(contextCircut, root.value)
isConstant = p.markMgates2(nextContext, nextContext.root, mGatesUsed, orderedmGates, negate, inverse)
} else {
if _, alreadyComputed := mGatesUsed[root.value.V1]; !alreadyComputed && root.OperationType()&(IN|CONST) == 0 {
traverseCombinedMultiplicationGates(root.left, mGatesUsed, orderedmGates, functionRootMap, functionRenamer, negate, inverse)
if _, alreadyComputed := mGatesUsed[root.value.V1]; !alreadyComputed {
isConstant = p.markMgates2(contextCircut, root.left, mGatesUsed, orderedmGates, negate, inverse)
}
if _, alreadyComputed := mGatesUsed[root.value.V2]; !alreadyComputed && root.OperationType()&(IN|CONST) == 0 {
traverseCombinedMultiplicationGates(root.right, mGatesUsed, orderedmGates, functionRootMap, functionRenamer, Xor(negate, root.value.negate), Xor(inverse, root.value.invert))
if _, alreadyComputed := mGatesUsed[root.value.V2]; !alreadyComputed {
cons := p.markMgates2(contextCircut, root.right, mGatesUsed, orderedmGates, Xor(negate, root.value.negate), Xor(inverse, root.value.invert))
isConstant = isConstant || cons
}
}
if root.OperationType() == MULTIPLY {
_, n, _ := isFunction(root.value.Out)
if (root.left.OperationType()|root.right.OperationType())&CONST != 0 && n != "main" {
return
if isConstant && !root.value.invert && n != "main" {
return false
}
root.leftIns = make(map[string]int)
collectAtomsInSubtree(root.left, mGatesUsed, 1, root.leftIns, functionRootMap, negate, inverse)
root.rightIns = make(map[string]int)
root.leftIns = p.collectAtomsInSubtree2(contextCircut, root.left, mGatesUsed, false, false)
//if root.left.value.Out== root.right.value.Out{
// //note this is not a full copy, but shouldnt be a problem
// root.rightIns= root.leftIns
//}else{
// collectAtomsInSubtree(root.right, mGatesUsed, 1, root.rightIns, functionRootMap, Xor(negate, root.value.negate), Xor(inverse, root.value.invert))
//}
collectAtomsInSubtree(root.right, mGatesUsed, 1, root.rightIns, functionRootMap, Xor(negate, root.value.negate), Xor(inverse, root.value.invert))
//root.rightIns = collectAtomsInSubtree3(root.right, mGatesUsed, Xor(negate, root.value.negate), Xor(inverse, root.value.invert))
root.rightIns = p.collectAtomsInSubtree2(contextCircut, root.right, mGatesUsed, false, false)
root.index = len(mGatesUsed)
mGatesUsed[root.value.Out] = true
rootGate := cloneGate(root)
*orderedmGates = append(*orderedmGates, *rootGate)
}
return isConstant
//TODO optimize if output is not a multipication gate
}
func collectAtomsInSubtree(g *gate, mGatesUsed map[string]bool, multiplicative int, in map[string]int, functionRootMap map[string]*gate, negate bool, invert bool) {
if g == nil {
return
type factor struct {
typ Token
name string
invert, negate bool
multiplicative [2]int
}
func (f factor) String() string {
if f.typ == CONST {
return fmt.Sprintf("(const fac: %v)", f.multiplicative)
}
if _, ex := mGatesUsed[g.value.Out]; ex {
addToMap(g.value.Out, multiplicative, in, negate)
return
str := f.name
if f.invert {
str += "^-1"
}
if f.negate {
str = "-" + str
}
return fmt.Sprintf("(\"%s\" fac: %v)", str, f.multiplicative)
}
func mul2DVector(a, b [2]int) [2]int {
return [2]int{a[0] * b[0], a[1] * b[1]}
}
func mulFactors(leftFactors, rightFactors []factor) (result []factor) {
for _, facLeft := range leftFactors {
for i, facRight := range rightFactors {
if facLeft.typ == CONST && facRight.typ == IN {
rightFactors[i] = factor{typ: IN, name: facRight.name, negate: Xor(facLeft.negate, facRight.negate), invert: facRight.invert, multiplicative: mul2DVector(facRight.multiplicative, facLeft.multiplicative)}
continue
}
if facRight.typ == CONST && facLeft.typ == IN {
rightFactors[i] = factor{typ: IN, name: facLeft.name, negate: Xor(facLeft.negate, facRight.negate), invert: facLeft.invert, multiplicative: mul2DVector(facRight.multiplicative, facLeft.multiplicative)}
continue
}
if facRight.typ&facLeft.typ == CONST {
rightFactors[i] = factor{typ: CONST, negate: Xor(facRight.negate, facLeft.negate), multiplicative: mul2DVector(facRight.multiplicative, facLeft.multiplicative)}
continue
}
//tricky part here
//this one should only be reached, after a true mgate had its left and right braches computed. here we
//a factor can appear at most in quadratic form. we reduce terms a*a^-1 here.
if facRight.typ&facLeft.typ == IN {
//if facRight.n
//rightFactors[i] = factor{typ: CONST, negate: Xor(facRight.negate, facLeft.negate), multiplicative: mul2DVector(facRight.multiplicative, facLeft.multiplicative)}
//continue
}
panic("unexpected")
}
if g.OperationType()&(IN|CONST) != 0 {
addToMap(g.value.Out, multiplicative, in, negate)
return
}
if g.OperationType()&(MULTIPLY) != 0 {
b1, v1 := isValue(g.value.V1)
b2, v2 := isValue(g.value.V2)
return rightFactors
}
if b1 && !b2 {
multiplicative *= v1
collectAtomsInSubtree(g.right, mGatesUsed, multiplicative, in, functionRootMap, Xor(negate, g.value.negate), invert)
return
} else if !b1 && b2 {
multiplicative *= v2
collectAtomsInSubtree(g.left, mGatesUsed, multiplicative, in, functionRootMap, negate, invert)
return
} else if b1 && b2 {
panic("multiply constants not supported yet")
} else {
panic("werird")
//returns the absolute value of a signed int and a flag telling if the input was positive or not
//this implementation is awesome and fast (see Henry S Warren, Hackers's Delight)
func abs(n int) (val int, positive bool) {
y := n >> 63
return (n ^ y) - y, y == 0
}
//returns the reduced sum of two input factor arrays
//if no reduction was done (worst case), it returns the concatenation of the input arrays
func addFactors(leftFactors, rightFactors []factor) (res []factor) {
var found bool
for _, facLeft := range leftFactors {
for i, facRight := range rightFactors {
if facLeft.typ&facRight.typ == CONST {
var a0, b0 = facLeft.multiplicative[0], facRight.multiplicative[0]
if facLeft.negate {
a0 *= -1
}
if facRight.negate {
b0 *= -1
}
absValue, negate := abs(a0*facRight.multiplicative[1] + facLeft.multiplicative[1]*b0)
rightFactors[i] = factor{typ: CONST, negate: negate, multiplicative: [2]int{absValue, facLeft.multiplicative[1] * facRight.multiplicative[1]}}
found = true
//res = append(res, factor{typ: CONST, negate: negate, multiplicative: [2]int{absValue, facLeft.multiplicative[1] * facRight.multiplicative[1]}})
break
}
if facLeft.typ&facRight.typ == IN && facLeft.invert == facRight.invert && facLeft.name == facRight.name {
var a0, b0 = facLeft.multiplicative[0], facRight.multiplicative[0]
if facLeft.negate {
a0 *= -1
}
if facRight.negate {
b0 *= -1
}
absValue, negate := abs(a0*facRight.multiplicative[1] + facLeft.multiplicative[1]*b0)
rightFactors[i] = factor{typ: IN, invert: facRight.invert, name: facRight.name, negate: negate, multiplicative: [2]int{absValue, facLeft.multiplicative[1] * facRight.multiplicative[1]}}
found = true
//res = append(res, factor{typ: CONST, negate: negate, multiplicative: [2]int{absValue, facLeft.multiplicative[1] * facRight.multiplicative[1]}})
break
}
}
if !found {
res = append(res, facLeft)
found = false
}
}
return append(res, rightFactors...)
}
func (p *Program) collectAtomsInSubtree2(contextCircut *Circuit, g *gate, mGatesUsed map[string]bool, negate bool, invert bool) []factor {
if _, ex := mGatesUsed[g.value.Out]; ex {
return []factor{{typ: IN, name: g.value.Out, invert: invert, negate: negate, multiplicative: [2]int{1, 1}}}
}
if g.OperationType() == IN {
return []factor{{typ: IN, name: g.value.Out, invert: invert, negate: negate, multiplicative: [2]int{1, 1}}}
}
if g.OperationType() == FUNC {
if b, name, _ := isFunction(g.value.Out); b {
collectAtomsInSubtree(functionRootMap[name], mGatesUsed, multiplicative, in, functionRootMap, negate, invert)
nextContext := p.extendedFunctionRenamer(contextCircut, g.value)
return p.collectAtomsInSubtree2(nextContext, nextContext.root, mGatesUsed, negate, invert)
}
} else {
panic("function expected")
if g.OperationType() == CONST {
b1, v1 := isValue(g.value.Out)
if !b1 {
panic("not a constant")
}
if invert {
return []factor{{typ: CONST, negate: negate, multiplicative: [2]int{1, v1}}}
}
return []factor{{typ: CONST, negate: negate, multiplicative: [2]int{v1, 1}}}
}
collectAtomsInSubtree(g.left, mGatesUsed, multiplicative, in, functionRootMap, negate, invert)
collectAtomsInSubtree(g.right, mGatesUsed, multiplicative, in, functionRootMap, Xor(negate, g.value.negate), invert)
}
var leftFactors, rightFactors []factor
if g.left.OperationType() == FUNC {
nextContext := p.extendedFunctionRenamer(contextCircut, g.left.value)
leftFactors = p.collectAtomsInSubtree2(nextContext, nextContext.root, mGatesUsed, negate, invert)
} else {
leftFactors = p.collectAtomsInSubtree2(contextCircut, g.left, mGatesUsed, negate, invert)
}
func addOneToMap(value string, in map[string]int, negate bool) {
addToMap(value, 1, in, negate)
}
func addToMap(value string, val int, in map[string]int, negate bool) {
if negate {
in[value] = (in[value] - 1) * val
if g.right.OperationType() == FUNC {
nextContext := p.extendedFunctionRenamer(contextCircut, g.right.value)
rightFactors = p.collectAtomsInSubtree2(nextContext, nextContext.root, mGatesUsed, Xor(negate, g.value.negate), Xor(invert, g.value.invert))
} else {
in[value] = (in[value] + 1) * val
rightFactors = p.collectAtomsInSubtree2(contextCircut, g.right, mGatesUsed, Xor(negate, g.value.negate), Xor(invert, g.value.invert))
}
switch g.OperationType() {
case MULTIPLY:
return mulFactors(leftFactors, rightFactors)
case PLUS:
return addFactors(leftFactors, rightFactors)
default:
panic("unexpected gate")
}
}
//copies a gate neglecting its references to other gates
func cloneGate(in *gate) (out *gate) {
constr := &Constraint{Inputs: in.value.Inputs, Out: in.value.Out, Op: in.value.Op, invert: in.value.invert, negate: in.value.negate, V2: in.value.V2, V1: in.value.V1}
nRightins := make(map[string]int)
nLeftInst := make(map[string]int)
constr := Constraint{Inputs: in.value.Inputs, Out: in.value.Out, Op: in.value.Op, invert: in.value.invert, negate: in.value.negate, V2: in.value.V2, V1: in.value.V1}
nRightins := make([]factor, len(in.rightIns))
nLeftInst := make([]factor, len(in.leftIns))
for k, v := range in.rightIns {
nRightins[k] = v
}
@ -249,24 +372,30 @@ func (p *Program) getMainCircut() *Circuit {
return p.functions["main"]
}
func (p *Program) addGlobalInput(c *Constraint) {
func (p *Program) addGlobalInput(c Constraint) {
p.globalInputs = append(p.globalInputs, c)
}
func NewProgramm() *Program {
//return &Program{functions: map[string]*Circuit{}, signals: []string{}, globalInputs: []*Constraint{{Op: PLUS, V1:"1",V2:"0", Out: "one"}}}
return &Program{functions: map[string]*Circuit{}, signals: []string{}, globalInputs: []*Constraint{{Op: IN, Out: "one"}}}
func prepareUtils() utils {
bn, err := bn128.NewBn128()
if err != nil {
panic(err)
}
// new Finite Field
fqR := fields.NewFq(bn.R)
// new Polynomial Field
pf := r1csqap.NewPolynomialField(fqR)
return utils{
Bn: bn,
FqR: fqR,
PF: pf,
}
}
func NewProgramm() *Program {
//func (p *Program) oneConstraint() *Constraint {
// if p.globalInputs[0].Out != "one" {
// panic("'one' should be first global input")
// }
// return p.globalInputs[0]
//}
func (p *Program) addSignal(name string) {
p.signals = append(p.signals, name)
//return &Program{functions: map[string]*Circuit{}, signals: []string{}, globalInputs: []*Constraint{{Op: PLUS, V1:"1",V2:"0", Out: "one"}}}
return &Program{functions: map[string]*Circuit{}, globalInputs: []Constraint{{Op: IN, Out: "one"}}, arithmeticEnvironment: prepareUtils()}
}
func (p *Program) addFunction(constraint *Constraint) (c *Circuit) {
@ -287,9 +416,10 @@ func (p *Program) addFunction(constraint *Constraint) (c *Circuit) {
p.functions[name] = c
//I need the inputs to be defined as input constraints for each function for later renaming conventions
//if constraint.Literal == "main" {
for _, in := range constraint.Inputs {
newConstr := &Constraint{
newConstr := Constraint{
Op: IN,
Out: in,
}
@ -298,6 +428,7 @@ func (p *Program) addFunction(constraint *Constraint) (c *Circuit) {
}
c.addConstraint(newConstr)
}
//}
c.Inputs = constraint.Inputs
return
@ -313,18 +444,13 @@ func (p *Program) GenerateReducedR1CS(mGates []gate) (a, b, c [][]*big.Int) {
size := offset + len(mGates)
indexMap := make(map[string]int)
//circ.Signals = []string{"one"}
for i, v := range p.globalInputs {
indexMap[v.Out] = i
//circ.Signals = append(circ.Signals, v)
}
for i, v := range mGates {
indexMap[v.value.Out] = i + offset
//circ.Signals = append(circ.Signals, v.value.Out)
}
//circ.NVars = len(circ.Signals)
//circ.NSignals = len(circ.Signals)
for _, gate := range mGates {
@ -333,41 +459,24 @@ func (p *Program) GenerateReducedR1CS(mGates []gate) (a, b, c [][]*big.Int) {
bConstraint := r1csqap.ArrayOfBigZeros(size)
cConstraint := r1csqap.ArrayOfBigZeros(size)
//if len(gate.leftIns)>=len(gate.rightIns){
// for leftInput, _ := range gate.leftIns {
// if v, ex := gate.rightIns[leftInput]; ex {
// gate.leftIns[leftInput] *= v
// gate.rightIns[leftInput] = 1
//
// }
// }
//}else{
// for rightInput, _ := range gate.rightIns {
// if v, ex := gate.leftIns[rightInput]; ex {
// gate.rightIns[rightInput] *= v
// gate.leftIns[rightInput] = 1
// }
// }
//}
for leftInput, val := range gate.leftIns {
insertVar3(aConstraint, val, leftInput, indexMap[leftInput])
for _, val := range gate.leftIns {
convertAndInsertFactorAt(aConstraint, val, indexMap[val.name])
}
for rightInput, val := range gate.rightIns {
insertVar3(bConstraint, val, rightInput, indexMap[rightInput])
for _, val := range gate.rightIns {
convertAndInsertFactorAt(bConstraint, val, indexMap[val.name])
}
cConstraint[indexMap[gate.value.Out]] = big.NewInt(int64(1))
if gate.value.invert {
a = append(a, cConstraint)
b = append(b, bConstraint)
c = append(c, aConstraint)
} else {
a = append(a, aConstraint)
b = append(b, bConstraint)
c = append(c, cConstraint)
tmp := aConstraint
aConstraint = cConstraint
cConstraint = tmp
}
a = append(a, aConstraint)
b = append(b, bConstraint)
c = append(c, cConstraint)
} else {
panic("not a m gate")
@ -379,19 +488,19 @@ func (p *Program) GenerateReducedR1CS(mGates []gate) (a, b, c [][]*big.Int) {
return a, b, c
}
func insertVar3(arr []*big.Int, val int, input string, index int) {
isVal, value := isValue(input)
var valueBigInt *big.Int
if isVal {
valueBigInt = big.NewInt(int64(value))
arr[0] = new(big.Int).Add(arr[0], valueBigInt)
} else {
//if !indexMap[leftInput] {
// panic(errors.New("using variable before it's set"))
//}
valueBigInt = big.NewInt(int64(val))
arr[index] = new(big.Int).Add(arr[index], valueBigInt)
var Utils = prepareUtils()
func fractionToField(in [2]int) *big.Int {
return Utils.FqR.Mul(big.NewInt(int64(in[0])), Utils.FqR.Inverse(big.NewInt(int64(in[1]))))
}
func convertAndInsertFactorAt(arr []*big.Int, val factor, index int) {
if val.typ == CONST {
arr[0] = new(big.Int).Add(arr[0], fractionToField(val.multiplicative))
return
}
arr[index] = new(big.Int).Add(arr[index], fractionToField(val.multiplicative))
}

+ 20
- 10
circuitcompiler/Programm_test.go

@ -21,26 +21,36 @@ func TestNewProgramm(t *testing.T) {
b = e * 6
c = b * 7
f = c * 1
d = c / f
out = d * 1
d = c * f
out = d * mul(d,e)
func add(x ,k):
z = k * x
out = do(x) + mul(x,z)
func main(x,z):
out = do(x) + 4
func main(x,z):
out = do(z) + add(x,x)
func mul(a,b):
out = a * b
`
//flat := `
//func mul(a,b):
// out = a * b
//
//func main(a):
// b = a * a
// c = 4 - b
// d = 5 * c
// out = d / mul(b,b)
//`
//flat := `
//func main(a,b):
// e = 4 * a
// c = a * e
// d = c * 70
// out = a * d
// c = a + b
// e = c - a
// f = e + b
// g = f + 2
// out = g * a
//`
parser := NewParser(strings.NewReader(flat))
program, err := parser.Parse()
@ -61,7 +71,7 @@ func TestNewProgramm(t *testing.T) {
//PrintTree(froots["mul"])
gates := program.ReduceCombinedTree()
for _, g := range gates {
fmt.Println(g)
fmt.Printf("\n %v", g)
}
fmt.Println("generating R1CS")

+ 42
- 59
circuitcompiler/circuit.go

@ -11,23 +11,12 @@ import (
// Circuit is the data structure of the compiled circuit
type Circuit struct {
NVars int
NPublic int
NSignals int
Inputs []string
Signals []string
PublicSignals []string
Witness []*big.Int
Name string
root *gate
Inputs []string
Name string
root *gate
//after reducing
constraintMap map[string]*Constraint
//used map[string]bool
R1CS struct {
A [][]*big.Int
B [][]*big.Int
C [][]*big.Int
}
//constraintMap map[string]*Constraint
gateMap map[string]*gate
}
type gate struct {
@ -35,9 +24,9 @@ type gate struct {
left *gate
right *gate
funcInputs []*gate
value *Constraint
leftIns map[string]int //leftIns and RightIns after addition gates have been reduced. only multiplication gates remain
rightIns map[string]int
value Constraint //is a pointer a good thing here??
leftIns []factor //leftIns and RightIns after addition gates have been reduced. only multiplication gates remain
rightIns []factor
}
func (g gate) String() string {
@ -73,24 +62,11 @@ func (c Constraint) String() string {
}
func newCircuit(name string) *Circuit {
return &Circuit{Name: name, constraintMap: make(map[string]*Constraint)}
return &Circuit{Name: name, gateMap: make(map[string]*gate)}
}
func (g *gate) addLeft(c *Constraint) {
if g.left != nil {
panic("already set left gate")
}
g.left = &gate{value: c}
}
func (g *gate) addRight(c *Constraint) {
if g.right != nil {
panic("already set left gate")
}
g.right = &gate{value: c}
}
func (circ *Circuit) addConstraint(constraint *Constraint) {
if _, ex := circ.constraintMap[constraint.Out]; ex {
func (circ *Circuit) addConstraint(constraint Constraint) {
if _, ex := circ.gateMap[constraint.Out]; ex {
panic("already used FlatConstraint")
}
@ -109,36 +85,43 @@ func (circ *Circuit) addConstraint(constraint *Constraint) {
//the main functions output must be a multiplication gate
//if its not, then we simple create one where outNew = 1 * outOld
if constraint.Op&(MINUS|PLUS) != 0 {
newOut := &Constraint{Out: constraint.Out, V1: "1", V2: "out2", Op: MULTIPLY}
newOut := Constraint{Out: constraint.Out, V1: "1", V2: "out2", Op: MULTIPLY}
//TODO reachable?
delete(circ.constraintMap, constraint.Out)
delete(circ.gateMap, constraint.Out)
circ.addConstraint(newOut)
constraint.Out = "out2"
circ.addConstraint(constraint)
}
}
}
addConstantsAndFunctions := func(constraint string) {
if b, _ := isValue(constraint); b {
circ.constraintMap[constraint] = &Constraint{Op: CONST, Out: constraint}
circ.gateMap[constraint] = &gate{value: Constraint{Op: CONST, Out: constraint}}
} else if b, _, inputs := isFunction(constraint); b {
//check if function input is a constant like foo(a,4)
for _, in := range inputs {
if b, _ := isValue(in); b {
circ.constraintMap[in] = &Constraint{Op: CONST, Out: in}
circ.gateMap[in] = &gate{value: Constraint{Op: CONST, Out: in}}
continue
}
//if the argument is not in the constraint map, we panic. I used to do this later, but since we have a line
//interpreter, we can do this here
//the downside is that there cannot be functions passed as arguments
//if _, ex := circ.constraintMap[in];!ex {
// panic("undefined argument")
//
//}
}
circ.constraintMap[constraint] = &Constraint{Op: FUNC, Out: constraint, Inputs: inputs}
circ.gateMap[constraint] = &gate{value: Constraint{Op: FUNC, Out: constraint, Inputs: inputs}}
}
}
addConstantsAndFunctions(constraint.V1)
addConstantsAndFunctions(constraint.V2)
circ.constraintMap[constraint.Out] = constraint
circ.gateMap[constraint.Out] = &gate{value: constraint}
}
func (circ *Circuit) renameInputs(inputs []string) {
@ -147,12 +130,12 @@ func (circ *Circuit) renameInputs(inputs []string) {
}
mapping := make(map[string]string)
for i := 0; i < len(inputs); i++ {
if _, ex := circ.constraintMap[inputs[i]]; ex {
if _, ex := circ.gateMap[inputs[i]]; ex {
//this is a tricky part. So we replace former inputs with the new ones, thereby
//it might be, that the new input name has already been used for some output inside the function
//currently I dont know an elegant way how to handle this renaming issue
if circ.constraintMap[inputs[i]].Op != IN {
if circ.gateMap[inputs[i]].value.Op != IN {
panic(fmt.Sprintf("renaming collsion with %s", inputs[i]))
}
@ -160,7 +143,7 @@ func (circ *Circuit) renameInputs(inputs []string) {
mapping[circ.Inputs[i]] = inputs[i]
}
//fmt.Println(mapping)
circ.Inputs = inputs
//circ.Inputs = inputs
permute := func(in string) string {
if out, ex := mapping[in]; ex {
return out
@ -175,28 +158,28 @@ func (circ *Circuit) renameInputs(inputs []string) {
return in
}
for _, constraint := range circ.constraintMap {
for _, constraint := range circ.gateMap {
if constraint.Op == IN {
constraint.Out = permute(constraint.Out)
if constraint.value.Op == IN {
constraint.value.Out = permute(constraint.value.Out)
continue
}
if b, n, in := isFunction(constraint.Out); b {
constraint.Out = composeNewFunction(n, permuteListe(in))
constraint.Inputs = permuteListe(in)
if b, n, in := isFunction(constraint.value.Out); b {
constraint.value.Out = composeNewFunction(n, permuteListe(in))
constraint.value.Inputs = permuteListe(in)
}
if b, n, in := isFunction(constraint.V1); b {
constraint.V1 = composeNewFunction(n, permuteListe(in))
constraint.Inputs = permuteListe(in)
if b, n, in := isFunction(constraint.value.V1); b {
constraint.value.V1 = composeNewFunction(n, permuteListe(in))
constraint.value.Inputs = permuteListe(in)
}
if b, n, in := isFunction(constraint.V2); b {
constraint.V2 = composeNewFunction(n, permuteListe(in))
constraint.Inputs = permuteListe(in)
if b, n, in := isFunction(constraint.value.V2); b {
constraint.value.V2 = composeNewFunction(n, permuteListe(in))
constraint.value.Inputs = permuteListe(in)
}
constraint.V1 = permute(constraint.V1)
constraint.V2 = permute(constraint.V2)
constraint.value.V1 = permute(constraint.value.V1)
constraint.value.V2 = permute(constraint.value.V2)
}
return

+ 1
- 1
circuitcompiler/parser.go

@ -154,7 +154,7 @@ func (p *Parser) Parse() (programm *Program, err error) {
if constraint.Op == FUNC {
circuit = programm.addFunction(constraint)
} else {
circuit.addConstraint(constraint)
circuit.addConstraint(*constraint)
}
}
//TODO

+ 16
- 5
r1csqap/r1csqap.go

@ -128,18 +128,22 @@ func (pf PolynomialField) Eval(v []*big.Int, x *big.Int) *big.Int {
// NewPolZeroAt generates a new polynomial that has value zero at the given value
func (pf PolynomialField) NewPolZeroAt(pointPos, totalPoints int, height *big.Int) []*big.Int {
//todo note that this will blow up. big may be necessary
fac := 1
//(xj-x0)(xj-x1)..(xj-x_j-1)(xj-x_j+1)..(x_j-x_k)
for i := 1; i < totalPoints+1; i++ {
if i != pointPos {
fac = fac * (pointPos - i)
}
}
facBig := big.NewInt(int64(fac))
hf := pf.F.Div(height, facBig)
r := []*big.Int{hf}
for i := 1; i < totalPoints+1; i++ {
if i != pointPos {
ineg := big.NewInt(int64(-i))
//is b1 necessary?
b1 := big.NewInt(int64(1))
r = pf.Mul(r, []*big.Int{ineg, b1})
}
@ -153,33 +157,40 @@ func (pf PolynomialField) LagrangeInterpolation(v []*big.Int) []*big.Int {
var r []*big.Int
for i := 0; i < len(v); i++ {
r = pf.Add(r, pf.NewPolZeroAt(i+1, len(v), v[i]))
//r = pf.Mul(v[i], pf.NewPolZeroAt(i+1, len(v), v[i]))
}
//
return r
}
// R1CSToQAP converts the R1CS values to the QAP values
func (pf PolynomialField) R1CSToQAP(a, b, c [][]*big.Int) ([][]*big.Int, [][]*big.Int, [][]*big.Int, []*big.Int) {
//it uses Lagrange interpolation to to fit a polynomial through each slice. The x coordinate
//is simply a linear increment starting at 1
//within this process, the polynomial is evaluated at position 0
//so an alpha/beta/gamma value is the polynomial evaluated at 0
// the domain polynomial therefor is (-1+x)(-2+x)...(-n+x)
func (pf PolynomialField) R1CSToQAP(a, b, c [][]*big.Int) (alphas [][]*big.Int, betas [][]*big.Int, gammas [][]*big.Int, domain []*big.Int) {
aT := Transpose(a)
bT := Transpose(b)
cT := Transpose(c)
fmt.Println(aT)
fmt.Println(bT)
fmt.Println(cT)
var alphas [][]*big.Int
for i := 0; i < len(aT); i++ {
alphas = append(alphas, pf.LagrangeInterpolation(aT[i]))
}
var betas [][]*big.Int
for i := 0; i < len(bT); i++ {
betas = append(betas, pf.LagrangeInterpolation(bT[i]))
}
var gammas [][]*big.Int
for i := 0; i < len(cT); i++ {
gammas = append(gammas, pf.LagrangeInterpolation(cT[i]))
}
//it used to range till len(alphas)-1, but this was wrong.
z := []*big.Int{big.NewInt(int64(1))}
for i := 1; i < len(alphas)-1; i++ {
for i := 1; i < len(a); i++ {
z = pf.Mul(
z,
[]*big.Int{

+ 3
- 3
snark.go

@ -90,7 +90,7 @@ func prepareUtils() utils {
}
// GenerateTrustedSetup generates the Trusted Setup from a compiled Circuit. The Setup.Toxic sub data structure must be destroyed
func GenerateTrustedSetup(witnessLength int, circuit circuitcompiler.Circuit, alphas, betas, gammas [][]*big.Int) (Setup, error) {
func GenerateTrustedSetup(witnessLength int, alphas, betas, gammas [][]*big.Int) (Setup, error) {
var setup Setup
var err error
@ -173,13 +173,13 @@ func GenerateTrustedSetup(witnessLength int, circuit circuitcompiler.Circuit, al
setup.Vk.G2Kg = Utils.Bn.G2.MulScalar(Utils.Bn.G2.G, setup.Toxic.Kgamma)
// for i := 0; i < circuit.NVars; i++ {
for i := 0; i < len(circuit.Signals); i++ {
for i := 0; i < witnessLength; i++ {
at := Utils.PF.Eval(alphas[i], setup.Toxic.T)
// rhoAat := Utils.Bn.Fq1.Mul(setup.Toxic.RhoA, at)
rhoAat := Utils.FqR.Mul(setup.Toxic.RhoA, at)
a := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, rhoAat)
setup.Pk.A = append(setup.Pk.A, a)
if i <= circuit.NPublic {
if i <= 4 {
setup.Vk.IC = append(setup.Vk.IC, a)
}

+ 64
- 16
snark_test.go

@ -3,19 +3,67 @@ package snark
import (
"fmt"
"github.com/mottla/go-snark/circuitcompiler"
"github.com/mottla/go-snark/r1csqap"
"github.com/stretchr/testify/assert"
"math/big"
"strings"
"testing"
)
func TestGenerateProofs(t *testing.T) {
z := []*big.Int{big.NewInt(int64(1))}
for i := 1; i < 6; i++ {
z = Utils.PF.Mul(
z,
[]*big.Int{
Utils.PF.F.Neg(
big.NewInt(int64(i))),
big.NewInt(int64(1)),
})
}
fmt.Println(z)
for i := 0; i < 7; i++ {
fmt.Println(Utils.PF.Eval(z, big.NewInt(int64(i))))
}
z = []*big.Int{big.NewInt(int64(1))}
for i := 1; i < 6; i++ {
z = Utils.PF.Mul(
z,
[]*big.Int{
big.NewInt(int64(i)),
big.NewInt(int64(1)),
})
}
fmt.Println(z)
z = []*big.Int{
big.NewInt(int64(1)),
big.NewInt(int64(
-3)),
}
z = Utils.PF.Mul(
z,
[]*big.Int{
big.NewInt(int64(1)),
big.NewInt(int64(3)),
})
fmt.Println(z)
fmt.Println(Utils.PF.F.Neg(
big.NewInt(int64(1))))
fmt.Println(Utils.PF.F.Inverse(big.NewInt(int64(1))))
}
func TestNewProgramm(t *testing.T) {
flat := `
func main(a,b,c,d):
e = a + b
e = a * b
f = c * d
out = e * f
g = e * f
h = g / e
i = h * 5
out = g * i
`
parser := circuitcompiler.NewParser(strings.NewReader(flat))
@ -49,13 +97,13 @@ func TestNewProgramm(t *testing.T) {
fmt.Println(w)
// R1CS to QAP
alphas, betas, gammas, zxQAP := Utils.PF.R1CSToQAP(a, b, c)
alphas, betas, gammas, domain := Utils.PF.R1CSToQAP(a, b, c)
fmt.Println("qap")
fmt.Println("alphas", len(alphas))
fmt.Println("alphas", alphas)
fmt.Println("betas", len(betas))
fmt.Println("gammas", len(gammas))
fmt.Println("zx length", len(zxQAP))
fmt.Println("domain polynomial ", len(domain))
ax, bx, cx, px := Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
fmt.Println("ax length", len(ax))
@ -63,29 +111,29 @@ func TestNewProgramm(t *testing.T) {
fmt.Println("cx length", len(cx))
fmt.Println("px length", len(px))
hxQAP := Utils.PF.DivisorPolynomial(px, zxQAP)
fmt.Println("hx length", len(hxQAP))
hxQAP := Utils.PF.DivisorPolynomial(px, domain)
fmt.Println("hx length", hxQAP)
// hx==px/zx so px==hx*zx
assert.Equal(t, px, Utils.PF.Mul(hxQAP, zxQAP))
assert.Equal(t, px, Utils.PF.Mul(hxQAP, domain))
// p(x) = a(x) * b(x) - c(x) == h(x) * z(x)
abc := Utils.PF.Sub(Utils.PF.Mul(ax, bx), cx)
assert.Equal(t, abc, px)
hzQAP := Utils.PF.Mul(hxQAP, zxQAP)
hzQAP := Utils.PF.Mul(hxQAP, domain)
assert.Equal(t, abc, hzQAP)
//div, rem := Utils.PF.Div(px, zxQAP)
//assert.Equal(t, hxQAP, div)
//assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4))
div, rem := Utils.PF.Div(px, domain)
assert.Equal(t, hxQAP, div) //not necessary
assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(len(px)-len(domain)))
// calculate trusted setup
//setup, err := GenerateTrustedSetup(len(w), *circuit, alphas, betas, gammas)
//calculate trusted setup
//setup, err := GenerateTrustedSetup(len(w),alphas, betas, gammas)
//assert.Nil(t, err)
//fmt.Println("\nt:", setup.Toxic.T)
//
//// zx and setup.Pk.Z should be the same (currently not, the correct one is the calculation used inside GenerateTrustedSetup function), the calculation is repeated. TODO avoid repeating calculation
//// assert.Equal(t, zxQAP, setup.Pk.Z)
////
////// zx and setup.Pk.Z should be the same (currently not, the correct one is the calculation used inside GenerateTrustedSetup function), the calculation is repeated. TODO avoid repeating calculation
//assert.Equal(t, domain, setup.Pk.Z)
//
//fmt.Println("hx pk.z", hxQAP)
//hx := Utils.PF.DivisorPolynomial(px, setup.Pk.Z)

Loading…
Cancel
Save