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.

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