{"id":21970086,"url":"https://github.com/scroll-tech/misc-precompiled-circuit","last_synced_at":"2025-04-28T10:45:54.031Z","repository":{"id":170570482,"uuid":"627049605","full_name":"scroll-tech/misc-precompiled-circuit","owner":"scroll-tech","description":"ripemd160, modexp(u256 only) circuits","archived":false,"fork":false,"pushed_at":"2024-03-14T09:38:10.000Z","size":121,"stargazers_count":32,"open_issues_count":3,"forks_count":22,"subscribers_count":19,"default_branch":"main","last_synced_at":"2025-03-30T08:51:12.431Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/scroll-tech.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-04-12T17:19:09.000Z","updated_at":"2024-11-17T22:08:02.000Z","dependencies_parsed_at":null,"dependency_job_id":"ff6f5824-1dbb-4535-b71d-fc8e7282d01d","html_url":"https://github.com/scroll-tech/misc-precompiled-circuit","commit_stats":null,"previous_names":["scroll-tech/misc-precompiled-circuit"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scroll-tech%2Fmisc-precompiled-circuit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scroll-tech%2Fmisc-precompiled-circuit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scroll-tech%2Fmisc-precompiled-circuit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scroll-tech%2Fmisc-precompiled-circuit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/scroll-tech","download_url":"https://codeload.github.com/scroll-tech/misc-precompiled-circuit/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251297815,"owners_count":21566899,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-29T14:30:58.451Z","updated_at":"2025-04-28T10:45:54.010Z","avatar_url":"https://github.com/scroll-tech.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Introduction\n\nDefine misc precompiled circuits including rmd160 and modexp. Try to unify the range check components so that all circuits only depend on one column for range check.\n\nNotice: the modexp circuit only supports U256 instead of arbitrary length bigint. This is a difference from EVM L1 behavior by design.\n\n# Generic $(a^b)_p$ over $\\mathbb{F}_r$ in Halo2\n\n## I. Representation of $u256$ values in $F_r$\nSuppose that for each $x$, $x \\in [0, 2^{256}-1]$. We represent $a$ as a vector of three $\\mathbb{F}_r$ limbs $[x_0, x_1, x_2]$ such that $x_0 \\le 2^{108}$, $x_1 \\le 2^{108}$ and $x_2 \\le 2^{108}$\n\n$\\langle$ x $\\rangle$ =\n$\\underbrace{b_{0}  ,b_{1}  , \\cdots, b_{107}}$ $\\bigl( x_0 \\bigr)$\n$\\underbrace{b_{108},b_{109}, \\cdots, b_{215}}$ $\\bigl( x_1 \\bigr)$\n$\\underbrace{b_{216},b_{217}, \\cdots, b_{255}}$ $\\bigl( x_2 \\bigr)$\n\nIn addition we use $x_3$ to represent $x$ % $r$ and put them all together we represent $x = [x_0, x_1, x_2, x_3]$.\n\n\n## II. Constraints of $xy = kp + d$ where $x, y, k, p \\in [0, 2^{256}-1]$.\n\n### 1. Picking coprime numbers $d_0, d_1, r$ such that $d_0 d_1  r \u003e 2^{512}$.\nPicking $d_0 = 2^{108}-1$, $d_1 = 2^{216}$, and $r$. We notice that these three numbers are co-prime.\n\n**Proof:**\n$r$ is prime, $2^{216}$ has only one factor which is $2$ and $2^{108} - 1$ is an odd number.\n**Qed.**\n\n### 2. By CRT the following constraints decides a unique $d$ for $x = kp + d$\n1. $\\langle xy \\rangle_{d_0} = \\langle kp \\rangle_{d_0} + \\langle d \\rangle_{d_0}$\n1. $\\langle xy \\rangle_{d_1} = \\langle kp \\rangle_{d_1} + \\langle d \\rangle_{d_1}$\n2. $\\langle xy \\rangle_{r} = \\langle kp \\rangle_{r} + \\langle d \\rangle_{r}$\n3. $d \u003c p$.\n\n### 3. Reminders of $\\langle x \\rangle$ under $d_0, d_1$ and $r$.\n1. $\\langle x \\rangle_{d_0} = \\langle x_2 + x_1 + x_0 \\rangle_{d_0}$\n2. $\\langle x \\rangle_{d_1} = \\langle [x_0, x_1, 0, 0]\\rangle_{d_1}$\n3. $\\langle x \\rangle_{r} = x_3$\n\n### 4. Put it all together we get the following constraints.\n* $(x_0 + x_1 + x_2)(y_0 + y_1 + y_2) \\\\ = (k_0 + k_1 + k_2) (p_0 + p_1 + p2) + d_0 + d_1 + d_2$ (modular $2^{108} - 1$)\n* $(x_0y_0 + 2^{108} (x_1y_0 + x_0y_1)) = (k_0p_0 + d_0 + 2^{108} (p_1k_0 + p_0k_1) + d1)$ (modular $2^{216}$)\n* $x_3y_3 = k_3p_3 + d_3$ (modular $r$)\n* $d \u003c p$.\n\n## III. Finalize $modexp(a,b)$ over $p$\n### Pseudo code with simple double and add algorithm\n```\n    let sum = 1;\n    let b = [bi; 256];\n    for (i=0;i\u003c256;i++) {\n        sum = (sum * sum * a^bi) mod p\n    }\n```\n### TODO: Change to wnaf with window = 2\n\n## IV. Gate Definition\n### Use standard halo2 gate generator as following:\n```\ncustomized_circuits!(ModExpConfig, 2, 5, 9, 1,\n   | l0  | l1   | l2  | l3  | d   |  c0  | c1  | c2  | c3  | cd  | cdn | c   | c03  | c12  | sel\n   | nil | nil  | nil | nil | d_n |  nil | nil | nil | nil | nil | nil | nil | nil  | nil  | nil\n);\n```\nwhere l0, l1, l2, l3, d are witness cells and c0, c1, c2, c3, cd, cdn, c, c03, c12 are constant cells.\n\n### Gate constraint for one line:\n```\ncs.create_gate(\"one line constraint\", |meta| {\n    let l0 = config.get_expr(meta, ModExpConfig::l0());\n    let l1 = config.get_expr(meta, ModExpConfig::l1());\n    let l2 = config.get_expr(meta, ModExpConfig::l2());\n    let l3 = config.get_expr(meta, ModExpConfig::l3());\n    let d = config.get_expr(meta, ModExpConfig::d());\n    let dnext = config.get_expr(meta, ModExpConfig::d_n());\n    let c0 = config.get_expr(meta, ModExpConfig::c0());\n    let c1 = config.get_expr(meta, ModExpConfig::c1());\n    let c2 = config.get_expr(meta, ModExpConfig::c2());\n    let c3 = config.get_expr(meta, ModExpConfig::c3());\n    let c  = config.get_expr(meta, ModExpConfig::c());\n    let cd  = config.get_expr(meta, ModExpConfig::cd());\n    let cdn  = config.get_expr(meta, ModExpConfig::cdn());\n    let c03 = config.get_expr(meta, ModExpConfig::c03());\n    let c12  = config.get_expr(meta, ModExpConfig::c12());\n    let sel = config.get_expr(meta, ModExpConfig::sel());\n\n    vec![\n        sel * (\n            l0.clone() * c0\n        +   l1.clone() * c1\n        +   l2.clone() * c2\n        +   l3.clone() * c3\n        +   d  * cd\n        +   dnext * cdn\n        +   l0 * l3 * c03\n        +   l1 * l2 * c12\n        +   c)\n    ]\n});\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscroll-tech%2Fmisc-precompiled-circuit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fscroll-tech%2Fmisc-precompiled-circuit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscroll-tech%2Fmisc-precompiled-circuit/lists"}