You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

362 lines
8.3 KiB

  1. package circuitcompiler
  2. import (
  3. "errors"
  4. "fmt"
  5. "math/big"
  6. "regexp"
  7. "strconv"
  8. "strings"
  9. )
  10. var variableIndicationSign = "@"
  11. // Circuit is the data structure of the compiled circuit
  12. type Circuit struct {
  13. Inputs []string
  14. Name string
  15. root *gate
  16. //after reducing
  17. //constraintMap map[string]*Constraint
  18. gateMap map[string]*gate
  19. }
  20. type gate struct {
  21. index int
  22. left *gate
  23. right *gate
  24. funcInputs []*gate
  25. Op Token
  26. value *Constraint //is a pointer a good thing here??
  27. leftIns []factor //leftIns and RightIns after addition gates have been reduced. only multiplication gates remain
  28. rightIns []factor
  29. }
  30. func (g gate) String() string {
  31. return fmt.Sprintf("Gate %v : %v with left %v right %v", g.index, g.value, g.leftIns, g.rightIns)
  32. }
  33. //type variable struct {
  34. // val string
  35. //}
  36. // Constraint is the data structure of a flat code operation
  37. type Constraint struct {
  38. // v1 op v2 = out
  39. Op Token
  40. V1 string
  41. V2 string
  42. Out string
  43. //fV1 *variable
  44. //fV2 *variable
  45. //fOut *variable
  46. //Literal string
  47. //TODO once i've implemented a new parser/lexer we do this differently
  48. Inputs []string // in func declaration case
  49. //fInputs []*variable
  50. negate bool
  51. invert bool
  52. }
  53. func (c Constraint) String() string {
  54. if c.negate || c.invert {
  55. return fmt.Sprintf("|%v = %v %v %v| negated: %v, inverted %v", c.Out, c.V1, c.Op, c.V2, c.negate, c.invert)
  56. }
  57. return fmt.Sprintf("|%v = %v %v %v|", c.Out, c.V1, c.Op, c.V2)
  58. }
  59. func newCircuit(name string) *Circuit {
  60. return &Circuit{Name: name, gateMap: make(map[string]*gate)}
  61. }
  62. func (p *Program) addFunction(constraint *Constraint) (c *Circuit) {
  63. name := constraint.Out
  64. fmt.Println("try to add function ", name)
  65. b, name2, _ := isFunction(name)
  66. if !b {
  67. panic(fmt.Sprintf("not a function: %v", constraint))
  68. }
  69. name = name2
  70. if _, ex := p.functions[name]; ex {
  71. panic("function already declared")
  72. }
  73. c = newCircuit(name)
  74. p.functions[name] = c
  75. renamedInputs := make([]string, len(constraint.Inputs))
  76. //I need the inputs to be defined as input constraints for each function for later renaming conventions
  77. //if constraint.Literal == "main" {
  78. for i, in := range constraint.Inputs {
  79. newConstr := &Constraint{
  80. Op: IN,
  81. Out: in,
  82. }
  83. if name == "main" {
  84. p.addGlobalInput(*newConstr)
  85. }
  86. c.addConstraint(newConstr)
  87. renamedInputs[i] = newConstr.Out
  88. }
  89. //}
  90. c.Inputs = renamedInputs
  91. return
  92. }
  93. func (circ *Circuit) addConstraint(constraint *Constraint) {
  94. if _, ex := circ.gateMap[constraint.Out]; ex {
  95. panic("already used FlatConstraint")
  96. }
  97. gateToAdd := &gate{value: constraint}
  98. if constraint.Op == DIVIDE {
  99. constraint.Op = MULTIPLY
  100. constraint.invert = true
  101. }
  102. if constraint.Op == MINUS {
  103. constraint.Op = PLUS
  104. constraint.negate = true
  105. }
  106. //todo this is dangerous.. if someone would use out as variable name, things would be fucked
  107. if constraint.Out == "out" {
  108. constraint.Out = composeNewFunction(circ.Name, circ.Inputs)
  109. circ.root = gateToAdd
  110. } else {
  111. constraint.Out = circ.renamer(constraint.Out)
  112. }
  113. constraint.V1 = circ.renamer(constraint.V1)
  114. constraint.V2 = circ.renamer(constraint.V2)
  115. circ.gateMap[constraint.Out] = gateToAdd
  116. }
  117. func (circ *Circuit) renamer(constraint string) string {
  118. if constraint == "" {
  119. return ""
  120. }
  121. if b, _ := isValue(constraint); b {
  122. circ.gateMap[constraint] = &gate{value: &Constraint{Op: CONST, Out: constraint}}
  123. return constraint
  124. }
  125. if b, name, inputs := isFunction(constraint); b {
  126. renamedInputs := make([]string, len(inputs))
  127. for i, in := range inputs {
  128. renamedInputs[i] = circ.renamer(in)
  129. }
  130. nn := composeNewFunction(name, renamedInputs)
  131. circ.gateMap[nn] = &gate{value: &Constraint{Op: FUNC, Out: nn, Inputs: renamedInputs}}
  132. return nn
  133. }
  134. return circ.Name + variableIndicationSign + constraint
  135. }
  136. func (circ *Circuit) renameInputs(inputs []string) {
  137. if len(inputs) != len(circ.Inputs) {
  138. panic("given inputs != circuit.Inputs")
  139. }
  140. mapping := make(map[string]string)
  141. for i := 0; i < len(inputs); i++ {
  142. if _, ex := circ.gateMap[inputs[i]]; ex {
  143. //this is a tricky part. So we replace former inputs with the new ones, thereby
  144. //it might be, that the new input name has already been used for some output inside the function
  145. //currently I dont know an elegant way how to handle this renaming issue
  146. if circ.gateMap[inputs[i]].value.Op != IN {
  147. panic(fmt.Sprintf("renaming collsion with %s", inputs[i]))
  148. }
  149. }
  150. mapping[circ.Inputs[i]] = inputs[i]
  151. }
  152. //fmt.Println(mapping)
  153. //circ.Inputs = inputs
  154. permute := func(in string) string {
  155. if out, ex := mapping[in]; ex {
  156. return out
  157. }
  158. return in
  159. }
  160. permuteListe := func(in []string) []string {
  161. for i := 0; i < len(in); i++ {
  162. in[i] = permute(in[i])
  163. }
  164. return in
  165. }
  166. for _, constraint := range circ.gateMap {
  167. if constraint.value.Op == IN {
  168. constraint.value.Out = permute(constraint.value.Out)
  169. continue
  170. }
  171. if b, n, in := isFunction(constraint.value.Out); b {
  172. constraint.value.Out = composeNewFunction(n, permuteListe(in))
  173. constraint.value.Inputs = permuteListe(in)
  174. }
  175. if b, n, in := isFunction(constraint.value.V1); b {
  176. constraint.value.V1 = composeNewFunction(n, permuteListe(in))
  177. constraint.value.Inputs = permuteListe(in)
  178. }
  179. if b, n, in := isFunction(constraint.value.V2); b {
  180. constraint.value.V2 = composeNewFunction(n, permuteListe(in))
  181. constraint.value.Inputs = permuteListe(in)
  182. }
  183. constraint.value.V1 = permute(constraint.value.V1)
  184. constraint.value.V2 = permute(constraint.value.V2)
  185. }
  186. return
  187. }
  188. func getContextFromVariable(in string) string {
  189. if strings.Contains(in, variableIndicationSign) {
  190. return strings.Split(in, variableIndicationSign)[0]
  191. }
  192. return ""
  193. }
  194. func composeNewFunction(fname string, inputs []string) string {
  195. builder := strings.Builder{}
  196. builder.WriteString(fname)
  197. builder.WriteRune('(')
  198. for i := 0; i < len(inputs); i++ {
  199. builder.WriteString(inputs[i])
  200. if i < len(inputs)-1 {
  201. builder.WriteRune(',')
  202. }
  203. }
  204. builder.WriteRune(')')
  205. return builder.String()
  206. }
  207. func max(a, b int) int {
  208. if a > b {
  209. return a
  210. }
  211. return b
  212. }
  213. func TreeDepth(g *gate) int {
  214. return printDepth(g, 0)
  215. }
  216. func printDepth(g *gate, d int) int {
  217. d = d + 1
  218. if g.left != nil && g.right != nil {
  219. return max(printDepth(g.left, d), printDepth(g.right, d))
  220. } else if g.left != nil {
  221. return printDepth(g.left, d)
  222. } else if g.right != nil {
  223. return printDepth(g.right, d)
  224. }
  225. return d
  226. }
  227. func CountMultiplicationGates(g *gate) int {
  228. if g == nil {
  229. return 0
  230. }
  231. if len(g.rightIns) > 0 || len(g.leftIns) > 0 {
  232. return 1 + CountMultiplicationGates(g.left) + CountMultiplicationGates(g.right)
  233. } else {
  234. return CountMultiplicationGates(g.left) + CountMultiplicationGates(g.right)
  235. }
  236. return 0
  237. }
  238. //TODO avoid printing multiple times in case of loops
  239. func PrintTree(g *gate) {
  240. printTree(g, 0)
  241. }
  242. func printTree(g *gate, d int) {
  243. d += 1
  244. if g.leftIns == nil || g.rightIns == nil {
  245. fmt.Printf("Depth: %v - %s \t \t \t \t \n", d, g.value)
  246. } else {
  247. fmt.Printf("Depth: %v - %s \t \t \t \t with l %v and r %v\n", d, g.value, g.leftIns, g.rightIns)
  248. }
  249. if g.funcInputs != nil {
  250. for _, v := range g.funcInputs {
  251. printTree(v, d)
  252. }
  253. }
  254. if g.left != nil {
  255. printTree(g.left, d)
  256. }
  257. if g.right != nil {
  258. printTree(g.right, d)
  259. }
  260. }
  261. func Xor(a, b bool) bool {
  262. return (a && !b) || (!a && b)
  263. }
  264. func (g *gate) ExtractValues(in []int) (er error) {
  265. if b, v1 := isValue(g.value.V1); b {
  266. if b2, v2 := isValue(g.value.V2); b2 {
  267. in = append(in, v1, v2)
  268. return nil
  269. }
  270. }
  271. return errors.New(fmt.Sprintf("Gate \"%s\" has no int values", g.value))
  272. }
  273. func (g *gate) OperationType() Token {
  274. return g.value.Op
  275. }
  276. //returns index of e if its in arr
  277. //return -1 if e not in arr
  278. func indexInArray(arr []string, e string) int {
  279. for i, a := range arr {
  280. if a == e {
  281. return i
  282. }
  283. }
  284. panic("lul")
  285. return -1
  286. }
  287. func isValue(a string) (bool, int) {
  288. v, err := strconv.Atoi(a)
  289. if err != nil {
  290. return false, 0
  291. }
  292. return true, v
  293. }
  294. func isFunction(a string) (tf bool, name string, inputs []string) {
  295. if !strings.ContainsRune(a, '(') && !strings.ContainsRune(a, ')') {
  296. return false, "", nil
  297. }
  298. name = strings.Split(a, "(")[0]
  299. // read string inside ( )
  300. rgx := regexp.MustCompile(`\((.*?)\)`)
  301. insideParenthesis := rgx.FindStringSubmatch(a)
  302. varsString := strings.Replace(insideParenthesis[1], " ", "", -1)
  303. inputs = strings.Split(varsString, ",")
  304. return true, name, inputs
  305. }
  306. type Inputs struct {
  307. Private []*big.Int
  308. Publics []*big.Int
  309. }