<style> .reveal h1 { color: #a23; font-family: serif; text-shadow:0 1px 0 rgb(137, 27, 41), 0 2px 0 rgb(144, 28, 43), 0 3px 0 rgb(126, 25, 38), 0 4px 0 rgb(132, 26, 40), 0 5px 0 rgb(114, 23, 34), 0 6px 1px rgba(0, 0, 0, 0.1), 0 0 5px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.3), 0 3px 5px rgba(0, 0, 0, 0.2), 0 5px 10px rgba(0, 0, 0, 0.25), 0 20px 20px rgba(0, 0, 0, 0.15) } .reveal h2 { color: #a23; font-family: serif; } .reveal h3 { color: #a23; font-family: serif; } .reveal h4 { font-family: serif; text-decoration: underline #a23; } .reveal strong { color: #a23; } </style> # Vamp-IR a universal intermediate representation for circuits --- **VAMP-IR** is a proof system agnostic language for arithmetic circuits. <br> Circuits written in **VAMP-IR** can be compiled to any proof system backend using any arithmetic constraint system or configuration, including those with custom gates or lookup tables --- ### Arithmetic Circuits Arithmetic circuits are a representation of systems of polynomial constraints. ![](https://i.imgur.com/IHIIxIo.png) $$b_0^2-b_0\quad\quad b_1^2-b_1\\ b_2^2-b_2\quad\quad b_3^2-b_3\\ 8b_3+4b_2+2b_1+b_0 -y =0$$ --- ### Constraint Systems A constraint system is another representation of a system of polynomials, but the participating polynomials must have a particular format. <br> | **R1CS** | **Plonkish** | | --- | --- | | one product of linear combinations of variables | fixed number of variables | --- ### Annoyances - Circuits written in different constraint systems can look very different - Constraints written in some constraint system may not resemble the source - Circuits have to be rewritten in order to use them in another proof system or configuration - Painful to benchmark a circuit in different proof systems or configurations ---- ### More annoyances - No canonical circuit format - Iterating on circuit designs is difficult - Front-end languages or DSLs become tied to a particular constraint system or proof system implementation ---- ### Circuits don't resemble each other, or the source <br> Twisted Edwards addition: $(x_1, y_1) + (x_2, y_2) = (x_3, y_3)$ if $x_3+Dx_1x_2x_3y_1y_2 - x_1y_2 - y_1x_2 = 0$ $y_3-Dx_1x_2y_1y_2y_3 - y_1y_2 + Ax_1x_2 = 0$ ---- | **R1CS**$^{\tiny{1}}$ | **3-wire Plonk** | | -- | -- | | $\scriptsize{x_1y_2 - o_1 = 0\\ x_2y_1 - o_2 = 0\\ Do_1o_2 - o_3 = 0\\ (x_1+y_1)(y_2-ax_2) - o_4 = 0\\ x_3(1+o_3)-o_1-o_2 = 0\\ y_3(1 -o_3)-o_4+o_1-Ao_2 = 0}$ | $\scriptsize{x_1y_2 - o_1 = 0 \\ x_2y_1 - o_2 = 0 \\ Do_1o_2 - o_3 = 0\\ y_1y_2 - o_4 =0\\ x_1x_2 - o_5 =0\\ x_3o_3 +x_3 - o_6 =0\\ o_6-o_1-o_2 = 0\\ y_3o_3 - y_3 + o_7 =0\\ o_7-o_4+Ao_5 = 0}$ | | **Original** | | -- | | $\scriptsize{x_3+Dx_1x_2x_3y_1y_2 - x_1y_2 - y_1x_2 = 0} \\ \scriptsize{y_3-Dx_1x_2y_1y_2y_3 - y_1y_2 + Ax_1x_2 = 0}$ | --- ### The cure We need a circuit language that allows for arbitrary polynomial constraints. Then arithmetic circuits can be written in a canonical, universal way. --- ### What about lookup tables and custom gates? Arbitrary polynomial constraints aren't enough: we need to include some extra information that allows a proof system implementation to replace subcircuits with lookup gates or custom gates. --- <br> <br> | **V**🧛 | | -- | | **A**liased | | **M**ultivariable | | **P**olynomial | | **I**ntermediate | | **R**epresentation | --- ## Design Principles - A representation of a circuit should express the *intention* of the circuit - A representation of a circuit should be flexible enough to allow for custom gates or lookup tables --- ## How does Vamp-IR work? <br> Vamp-IR accepts multivariable polynomial constraints of any format. <br> ```java 0 = x3 + D*x1*x2*x3*y1*y2 - x1*y2 - y1*x2 0 = y3 - D*x1*x2*y1*y2*y3 - y1*y2 + A*x1*x2 ``` ---- ### How does Vamp-IR work? The VampIR language allows collections of polynomial constraints (or *subcircuits*) to be given a reusable name, called an **alias**. ```javascript def check_on_sw_curve x y { 0 = x^3 + A*x + B - y^2 } def range_4 x { 0 = b0*b0 - b0 0 = b1*b1 - b1 0 = b2*b2 - b2 0 = b3*b3 - b3 0 = 8*b3 + 4*b2 + 2*b1 + b0 - x } ``` ---- ### How does Vamp-IR work? Aliases have a signature---like a function signature---that indicates which variables can be regarded as "inputs" or as "outputs". <br> ```java def twisted_edwards_add x1 y1 x2 y2 -> x3 y3 { 0 = x3 + D*x1*x2*x3*y1*y2 - x1*y2 - y1*x2 0 = y3 - D*x1*x2*y1*y2*y3 - y1*y2 + A*x1*x2 } ``` <br> The signature `x1 y1 x2 y2 -> x3 y3` indicates that `x3` and `y3` can be treated as outputs of the circuit. ---- ### How does Vamp-IR work? <br> Aliases can be composed <br> ```java def twisted_edwards_add x1 y1 x2 y2 -> x3 y3 { 0 = x3 + D*x1*x2*x3*y1*y2 - x1*y2 - y1*x2 0 = y3 - D*x1*x2*y1*y2*y3 - y1*y2 + A*x1*x2 } twisted_edwards_add (twisted_edwards_add x1 y1 x2 y2) x3 y3 ``` ---- ### How does Vamp-IR work? Standard aliases can indicate opportunities for lookup gates: ```javascript def range_4bit a { bool b0 bool b1 bool b2 bool b3 0 = a - 8*b3 - 4*b2 - 2*b1 - b0 } ``` A compiler targeting a proof system that has lookups is free to replace `range_4bit` with an appropriate lookup table. --- DSLs or front-end languages have a consistent target to compile to ![](https://i.imgur.com/E8NOcS9.png) --- A complicated circuit can become fairly readable... ```javascript def sapling_output cv cm epk gu gv pk v rcv rcm esk { cm = extract (note_commit (repr gu gv) pk v) cv = value_commit v not_small_order gu gv epk = jubjub_mul esk gu gv } ``` ... and checkable against the spec$^{\tiny{1}}$ ![](https://i.imgur.com/7IC5dxX.png) Or, circuits written in **VAMP-IR** can serve as a spec themselves --- ## Citations 1. Zcash Protocol Specification, https://raw.githubusercontent.com/zcash/zips/main/protocol/protocol.pdf
{"metaMigratedAt":"2023-06-16T23:15:51.540Z","metaMigratedFrom":"YAML","title":"VampIR","breaks":true,"slideOptions":"{\"theme\":\"blood\",\"center\":false}","contributors":"[{\"id\":\"3a0575d5-068c-45fc-9b3b-2c0f0b260811\",\"add\":19603,\"del\":13523}]"}
    438 views