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.

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