@trynullsec/s1-zk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/LIMITATIONS.md +17 -0
  2. package/README.md +149 -0
  3. package/ROADMAP.md +21 -0
  4. package/RULES.md +229 -0
  5. package/benchmarks/historical/orchard-inspired/partial-ec-mul-halo2.rs +53 -0
  6. package/benchmarks/historical/orchard-inspired/safe-ec-mul-halo2.rs +69 -0
  7. package/dist/ai/prompt-builder.d.ts +2 -0
  8. package/dist/ai/prompt-builder.js +33 -0
  9. package/dist/ai/prompt-builder.js.map +1 -0
  10. package/dist/ai/reasoning-interface.d.ts +15 -0
  11. package/dist/ai/reasoning-interface.js +2 -0
  12. package/dist/ai/reasoning-interface.js.map +1 -0
  13. package/dist/cli.d.ts +2 -0
  14. package/dist/cli.js +71 -0
  15. package/dist/cli.js.map +1 -0
  16. package/dist/config.d.ts +4 -0
  17. package/dist/config.js +41 -0
  18. package/dist/config.js.map +1 -0
  19. package/dist/core/audit-engine.d.ts +3 -0
  20. package/dist/core/audit-engine.js +31 -0
  21. package/dist/core/audit-engine.js.map +1 -0
  22. package/dist/core/file-loader.d.ts +6 -0
  23. package/dist/core/file-loader.js +28 -0
  24. package/dist/core/file-loader.js.map +1 -0
  25. package/dist/core/issue-builder.d.ts +16 -0
  26. package/dist/core/issue-builder.js +27 -0
  27. package/dist/core/issue-builder.js.map +1 -0
  28. package/dist/core/range-check-classifier.d.ts +16 -0
  29. package/dist/core/range-check-classifier.js +194 -0
  30. package/dist/core/range-check-classifier.js.map +1 -0
  31. package/dist/core/rule-engine.d.ts +10 -0
  32. package/dist/core/rule-engine.js +41 -0
  33. package/dist/core/rule-engine.js.map +1 -0
  34. package/dist/core/severity.d.ts +6 -0
  35. package/dist/core/severity.js +21 -0
  36. package/dist/core/severity.js.map +1 -0
  37. package/dist/core/source-map.d.ts +3 -0
  38. package/dist/core/source-map.js +16 -0
  39. package/dist/core/source-map.js.map +1 -0
  40. package/dist/frontends/circom/circom-comments.d.ts +8 -0
  41. package/dist/frontends/circom/circom-comments.js +52 -0
  42. package/dist/frontends/circom/circom-comments.js.map +1 -0
  43. package/dist/frontends/circom/circom-ir-builder.d.ts +2 -0
  44. package/dist/frontends/circom/circom-ir-builder.js +12 -0
  45. package/dist/frontends/circom/circom-ir-builder.js.map +1 -0
  46. package/dist/frontends/circom/circom-parser.d.ts +2 -0
  47. package/dist/frontends/circom/circom-parser.js +218 -0
  48. package/dist/frontends/circom/circom-parser.js.map +1 -0
  49. package/dist/frontends/circom/circom-tokenizer.d.ts +7 -0
  50. package/dist/frontends/circom/circom-tokenizer.js +79 -0
  51. package/dist/frontends/circom/circom-tokenizer.js.map +1 -0
  52. package/dist/frontends/circom/circom-utils.d.ts +9 -0
  53. package/dist/frontends/circom/circom-utils.js +88 -0
  54. package/dist/frontends/circom/circom-utils.js.map +1 -0
  55. package/dist/frontends/gnark/gnark-adapter.d.ts +5 -0
  56. package/dist/frontends/gnark/gnark-adapter.js +7 -0
  57. package/dist/frontends/gnark/gnark-adapter.js.map +1 -0
  58. package/dist/frontends/halo2/halo2-adapter.d.ts +8 -0
  59. package/dist/frontends/halo2/halo2-adapter.js +12 -0
  60. package/dist/frontends/halo2/halo2-adapter.js.map +1 -0
  61. package/dist/frontends/halo2/halo2-constraint-extractor.d.ts +29 -0
  62. package/dist/frontends/halo2/halo2-constraint-extractor.js +38 -0
  63. package/dist/frontends/halo2/halo2-constraint-extractor.js.map +1 -0
  64. package/dist/frontends/halo2/halo2-constraint-graph.d.ts +16 -0
  65. package/dist/frontends/halo2/halo2-constraint-graph.js +96 -0
  66. package/dist/frontends/halo2/halo2-constraint-graph.js.map +1 -0
  67. package/dist/frontends/halo2/halo2-dataflow.d.ts +11 -0
  68. package/dist/frontends/halo2/halo2-dataflow.js +19 -0
  69. package/dist/frontends/halo2/halo2-dataflow.js.map +1 -0
  70. package/dist/frontends/halo2/halo2-expression-parser.d.ts +14 -0
  71. package/dist/frontends/halo2/halo2-expression-parser.js +62 -0
  72. package/dist/frontends/halo2/halo2-expression-parser.js.map +1 -0
  73. package/dist/frontends/halo2/halo2-ir-builder.d.ts +2 -0
  74. package/dist/frontends/halo2/halo2-ir-builder.js +17 -0
  75. package/dist/frontends/halo2/halo2-ir-builder.js.map +1 -0
  76. package/dist/frontends/halo2/halo2-parser.d.ts +2 -0
  77. package/dist/frontends/halo2/halo2-parser.js +316 -0
  78. package/dist/frontends/halo2/halo2-parser.js.map +1 -0
  79. package/dist/frontends/halo2/halo2-patterns.d.ts +6 -0
  80. package/dist/frontends/halo2/halo2-patterns.js +54 -0
  81. package/dist/frontends/halo2/halo2-patterns.js.map +1 -0
  82. package/dist/frontends/halo2/halo2-types.d.ts +100 -0
  83. package/dist/frontends/halo2/halo2-types.js +2 -0
  84. package/dist/frontends/halo2/halo2-types.js.map +1 -0
  85. package/dist/frontends/noir/noir-adapter.d.ts +5 -0
  86. package/dist/frontends/noir/noir-adapter.js +7 -0
  87. package/dist/frontends/noir/noir-adapter.js.map +1 -0
  88. package/dist/index.d.ts +4 -0
  89. package/dist/index.js +4 -0
  90. package/dist/index.js.map +1 -0
  91. package/dist/ir/circuit-ir.d.ts +1 -0
  92. package/dist/ir/circuit-ir.js +2 -0
  93. package/dist/ir/circuit-ir.js.map +1 -0
  94. package/dist/ir/component-table.d.ts +6 -0
  95. package/dist/ir/component-table.js +11 -0
  96. package/dist/ir/component-table.js.map +1 -0
  97. package/dist/ir/constraint-graph.d.ts +26 -0
  98. package/dist/ir/constraint-graph.js +130 -0
  99. package/dist/ir/constraint-graph.js.map +1 -0
  100. package/dist/ir/dataflow.d.ts +3 -0
  101. package/dist/ir/dataflow.js +10 -0
  102. package/dist/ir/dataflow.js.map +1 -0
  103. package/dist/ir/reference-index.d.ts +6 -0
  104. package/dist/ir/reference-index.js +18 -0
  105. package/dist/ir/reference-index.js.map +1 -0
  106. package/dist/ir/signal-table.d.ts +6 -0
  107. package/dist/ir/signal-table.js +16 -0
  108. package/dist/ir/signal-table.js.map +1 -0
  109. package/dist/report/json.d.ts +2 -0
  110. package/dist/report/json.js +4 -0
  111. package/dist/report/json.js.map +1 -0
  112. package/dist/report/markdown.d.ts +2 -0
  113. package/dist/report/markdown.js +45 -0
  114. package/dist/report/markdown.js.map +1 -0
  115. package/dist/report/sarif.d.ts +2 -0
  116. package/dist/report/sarif.js +52 -0
  117. package/dist/report/sarif.js.map +1 -0
  118. package/dist/report/summary.d.ts +2 -0
  119. package/dist/report/summary.js +7 -0
  120. package/dist/report/summary.js.map +1 -0
  121. package/dist/report/terminal.d.ts +2 -0
  122. package/dist/report/terminal.js +50 -0
  123. package/dist/report/terminal.js.map +1 -0
  124. package/dist/rules/NS-ZK-001-dangerous-hint-assignment.d.ts +2 -0
  125. package/dist/rules/NS-ZK-001-dangerous-hint-assignment.js +27 -0
  126. package/dist/rules/NS-ZK-001-dangerous-hint-assignment.js.map +1 -0
  127. package/dist/rules/NS-ZK-002-assigned-but-unconstrained.d.ts +2 -0
  128. package/dist/rules/NS-ZK-002-assigned-but-unconstrained.js +22 -0
  129. package/dist/rules/NS-ZK-002-assigned-but-unconstrained.js.map +1 -0
  130. package/dist/rules/NS-ZK-003-unbound-public-input.d.ts +2 -0
  131. package/dist/rules/NS-ZK-003-unbound-public-input.js +22 -0
  132. package/dist/rules/NS-ZK-003-unbound-public-input.js.map +1 -0
  133. package/dist/rules/NS-ZK-004-unconstrained-output.d.ts +2 -0
  134. package/dist/rules/NS-ZK-004-unconstrained-output.js +27 -0
  135. package/dist/rules/NS-ZK-004-unconstrained-output.js.map +1 -0
  136. package/dist/rules/NS-ZK-005-missing-booleanity.d.ts +2 -0
  137. package/dist/rules/NS-ZK-005-missing-booleanity.js +26 -0
  138. package/dist/rules/NS-ZK-005-missing-booleanity.js.map +1 -0
  139. package/dist/rules/NS-ZK-006-missing-range-check.d.ts +2 -0
  140. package/dist/rules/NS-ZK-006-missing-range-check.js +32 -0
  141. package/dist/rules/NS-ZK-006-missing-range-check.js.map +1 -0
  142. package/dist/rules/NS-ZK-007-unsafe-assertion.d.ts +2 -0
  143. package/dist/rules/NS-ZK-007-unsafe-assertion.js +24 -0
  144. package/dist/rules/NS-ZK-007-unsafe-assertion.js.map +1 -0
  145. package/dist/rules/NS-ZK-008-unsafe-division-or-inverse.d.ts +2 -0
  146. package/dist/rules/NS-ZK-008-unsafe-division-or-inverse.js +39 -0
  147. package/dist/rules/NS-ZK-008-unsafe-division-or-inverse.js.map +1 -0
  148. package/dist/rules/NS-ZK-009-unconstrained-component-output.d.ts +2 -0
  149. package/dist/rules/NS-ZK-009-unconstrained-component-output.js +25 -0
  150. package/dist/rules/NS-ZK-009-unconstrained-component-output.js.map +1 -0
  151. package/dist/rules/NS-ZK-010-alias-overflow-risk.d.ts +2 -0
  152. package/dist/rules/NS-ZK-010-alias-overflow-risk.js +48 -0
  153. package/dist/rules/NS-ZK-010-alias-overflow-risk.js.map +1 -0
  154. package/dist/rules/NS-ZK-011-unused-signal.d.ts +2 -0
  155. package/dist/rules/NS-ZK-011-unused-signal.js +26 -0
  156. package/dist/rules/NS-ZK-011-unused-signal.js.map +1 -0
  157. package/dist/rules/NS-ZK-012-suspicious-selector.d.ts +2 -0
  158. package/dist/rules/NS-ZK-012-suspicious-selector.js +33 -0
  159. package/dist/rules/NS-ZK-012-suspicious-selector.js.map +1 -0
  160. package/dist/rules/halo2/NS-H2-001-assigned-advice-not-constrained.d.ts +2 -0
  161. package/dist/rules/halo2/NS-H2-001-assigned-advice-not-constrained.js +40 -0
  162. package/dist/rules/halo2/NS-H2-001-assigned-advice-not-constrained.js.map +1 -0
  163. package/dist/rules/halo2/NS-H2-002-instance-not-bound.d.ts +2 -0
  164. package/dist/rules/halo2/NS-H2-002-instance-not-bound.js +32 -0
  165. package/dist/rules/halo2/NS-H2-002-instance-not-bound.js.map +1 -0
  166. package/dist/rules/halo2/NS-H2-003-selector-risk.d.ts +2 -0
  167. package/dist/rules/halo2/NS-H2-003-selector-risk.js +37 -0
  168. package/dist/rules/halo2/NS-H2-003-selector-risk.js.map +1 -0
  169. package/dist/rules/halo2/NS-H2-004-unsafe-inverse.d.ts +2 -0
  170. package/dist/rules/halo2/NS-H2-004-unsafe-inverse.js +43 -0
  171. package/dist/rules/halo2/NS-H2-004-unsafe-inverse.js.map +1 -0
  172. package/dist/rules/halo2/NS-H2-005-partial-ec-operation.d.ts +2 -0
  173. package/dist/rules/halo2/NS-H2-005-partial-ec-operation.js +43 -0
  174. package/dist/rules/halo2/NS-H2-005-partial-ec-operation.js.map +1 -0
  175. package/dist/rules/halo2/NS-H2-006-missing-enable-equality.d.ts +2 -0
  176. package/dist/rules/halo2/NS-H2-006-missing-enable-equality.js +31 -0
  177. package/dist/rules/halo2/NS-H2-006-missing-enable-equality.js.map +1 -0
  178. package/dist/rules/halo2/halo2-rule-utils.d.ts +8 -0
  179. package/dist/rules/halo2/halo2-rule-utils.js +24 -0
  180. package/dist/rules/halo2/halo2-rule-utils.js.map +1 -0
  181. package/dist/rules/index.d.ts +2 -0
  182. package/dist/rules/index.js +39 -0
  183. package/dist/rules/index.js.map +1 -0
  184. package/dist/scanner.d.ts +8 -0
  185. package/dist/scanner.js +52 -0
  186. package/dist/scanner.js.map +1 -0
  187. package/dist/types.d.ts +171 -0
  188. package/dist/types.js +2 -0
  189. package/dist/types.js.map +1 -0
  190. package/examples/halo2/safe/bound-instance.rs +23 -0
  191. package/examples/halo2/safe/constrained-advice.rs +27 -0
  192. package/examples/halo2/safe/safe-inverse.rs +30 -0
  193. package/examples/halo2/safe/safe-selector.rs +27 -0
  194. package/examples/halo2/vulnerable/missing-selector-booleanity.rs +20 -0
  195. package/examples/halo2/vulnerable/partial-ec-mul.rs +23 -0
  196. package/examples/halo2/vulnerable/unbound-instance.rs +20 -0
  197. package/examples/halo2/vulnerable/unconstrained-advice.rs +24 -0
  198. package/examples/halo2/vulnerable/unsafe-inverse.rs +20 -0
  199. package/examples/safe/safe-boolean.circom +15 -0
  200. package/examples/safe/safe-component-output.circom +18 -0
  201. package/examples/safe/safe-division.circom +14 -0
  202. package/examples/safe/safe-public-input.circom +15 -0
  203. package/examples/safe/safe-range-check.circom +16 -0
  204. package/examples/safe/safe-transfer.circom +19 -0
  205. package/examples/vulnerable/alias-overflow-risk.circom +12 -0
  206. package/examples/vulnerable/merkle-selector-bug.circom +12 -0
  207. package/examples/vulnerable/missing-boolean.circom +11 -0
  208. package/examples/vulnerable/missing-range-check.circom +11 -0
  209. package/examples/vulnerable/public-input-not-bound.circom +12 -0
  210. package/examples/vulnerable/unconstrained-component-output.circom +15 -0
  211. package/examples/vulnerable/unconstrained-transfer.circom +17 -0
  212. package/examples/vulnerable/unsafe-assertion.circom +12 -0
  213. package/examples/vulnerable/unsafe-division.circom +11 -0
  214. package/package.json +46 -0
@@ -0,0 +1,30 @@
1
+ use halo2_proofs::plonk::{Advice, Column, ConstraintSystem, Selector};
2
+
3
+ struct Config {
4
+ denominator: Column<Advice>,
5
+ inverse: Column<Advice>,
6
+ q_nonzero: Selector,
7
+ }
8
+
9
+ fn configure(meta: &mut ConstraintSystem<Fp>) -> Config {
10
+ let denominator = meta.advice_column();
11
+ let inverse = meta.advice_column();
12
+ let q_nonzero = meta.selector();
13
+ meta.create_gate("safe inverse", |meta| {
14
+ let s = meta.query_selector(q_nonzero);
15
+ let d = meta.query_advice(denominator, Rotation::cur());
16
+ let inv = meta.query_advice(inverse, Rotation::cur());
17
+ vec![s * (d * inv - Expression::Constant(Fp::one()))]
18
+ });
19
+ Config { denominator, inverse, q_nonzero }
20
+ }
21
+
22
+ fn synthesize(config: Config, mut layouter: impl Layouter<Fp>) {
23
+ layouter.assign_region(|| "safe inverse", |mut region| {
24
+ config.q_nonzero.enable(&mut region, 0)?;
25
+ assert!(!witness.denominator.is_zero());
26
+ let inv = witness.denominator.invert().unwrap();
27
+ region.assign_advice(|| "inverse", config.inverse, 0, || Value::known(inv))?;
28
+ Ok(())
29
+ });
30
+ }
@@ -0,0 +1,27 @@
1
+ use halo2_proofs::plonk::{Advice, Column, ConstraintSystem, Selector};
2
+
3
+ struct Config {
4
+ lhs: Column<Advice>,
5
+ rhs: Column<Advice>,
6
+ q_swap: Selector,
7
+ }
8
+
9
+ fn configure(meta: &mut ConstraintSystem<Fp>) -> Config {
10
+ let lhs = meta.advice_column();
11
+ let rhs = meta.advice_column();
12
+ let q_swap = meta.selector();
13
+ meta.create_gate("conditional swap", |meta| {
14
+ let s = meta.query_selector(q_swap);
15
+ let a = meta.query_advice(lhs, Rotation::cur());
16
+ let b = meta.query_advice(rhs, Rotation::cur());
17
+ vec![s.clone() * (a - b)]
18
+ });
19
+ Config { lhs, rhs, q_swap }
20
+ }
21
+
22
+ fn synthesize(config: Config, mut layouter: impl Layouter<Fp>) {
23
+ layouter.assign_region(|| "selector discipline", |mut region| {
24
+ config.q_swap.enable(&mut region, 0)?;
25
+ Ok(())
26
+ });
27
+ }
@@ -0,0 +1,20 @@
1
+ use halo2_proofs::plonk::{Advice, Column, ConstraintSystem, Selector};
2
+
3
+ struct Config {
4
+ lhs: Column<Advice>,
5
+ rhs: Column<Advice>,
6
+ q_swap: Selector,
7
+ }
8
+
9
+ fn configure(meta: &mut ConstraintSystem<Fp>) -> Config {
10
+ let lhs = meta.advice_column();
11
+ let rhs = meta.advice_column();
12
+ let q_swap = meta.selector();
13
+ meta.create_gate("conditional swap", |meta| {
14
+ let s = meta.query_selector(q_swap);
15
+ let a = meta.query_advice(lhs, Rotation::cur());
16
+ let b = meta.query_advice(rhs, Rotation::cur());
17
+ vec![s.clone() * (a - b)]
18
+ });
19
+ Config { lhs, rhs, q_swap }
20
+ }
@@ -0,0 +1,23 @@
1
+ use halo2_proofs::plonk::{Advice, Column, ConstraintSystem};
2
+
3
+ struct Config {
4
+ scalar: Column<Advice>,
5
+ point_x: Column<Advice>,
6
+ point_y: Column<Advice>,
7
+ }
8
+
9
+ fn configure(meta: &mut ConstraintSystem<Fp>) -> Config {
10
+ let scalar = meta.advice_column();
11
+ let point_x = meta.advice_column();
12
+ let point_y = meta.advice_column();
13
+ Config { scalar, point_x, point_y }
14
+ }
15
+
16
+ fn synthesize(config: Config, mut layouter: impl Layouter<Fp>) {
17
+ layouter.assign_region(|| "partial ec mul", |mut region| {
18
+ let variable_base_mul = curve_point * scalar;
19
+ region.assign_advice(|| "ec point x", config.point_x, 0, || Value::known(variable_base_mul.x))?;
20
+ region.assign_advice(|| "ec point y", config.point_y, 0, || Value::known(variable_base_mul.y))?;
21
+ Ok(())
22
+ });
23
+ }
@@ -0,0 +1,20 @@
1
+ use halo2_proofs::plonk::{Advice, Column, ConstraintSystem, Instance};
2
+
3
+ struct Config {
4
+ advice: Column<Advice>,
5
+ instance: Column<Instance>,
6
+ }
7
+
8
+ fn configure(meta: &mut ConstraintSystem<Fp>) -> Config {
9
+ let advice = meta.advice_column();
10
+ let instance = meta.instance_column();
11
+ Config { advice, instance }
12
+ }
13
+
14
+ fn synthesize(config: Config, mut layouter: impl Layouter<Fp>) {
15
+ let public = meta.query_instance(config.instance, Rotation::cur());
16
+ layouter.assign_region(|| "unbound public value", |mut region| {
17
+ region.assign_advice(|| "private copy", config.advice, 0, || Value::known(witness))?;
18
+ Ok(())
19
+ });
20
+ }
@@ -0,0 +1,24 @@
1
+ use halo2_proofs::plonk::{Advice, Column, ConstraintSystem, Selector};
2
+
3
+ struct Config {
4
+ value: Column<Advice>,
5
+ q_enable: Selector,
6
+ }
7
+
8
+ fn configure(meta: &mut ConstraintSystem<Fp>) -> Config {
9
+ let value = meta.advice_column();
10
+ let q_enable = meta.selector();
11
+ meta.create_gate("unrelated gate", |meta| {
12
+ let s = meta.query_selector(q_enable);
13
+ vec![s]
14
+ });
15
+ Config { value, q_enable }
16
+ }
17
+
18
+ fn synthesize(config: Config, mut layouter: impl Layouter<Fp>) {
19
+ layouter.assign_region(|| "unconstrained witness", |mut region| {
20
+ config.q_enable.enable(&mut region, 0)?;
21
+ region.assign_advice(|| "secret amount", config.value, 0, || Value::known(secret_amount))?;
22
+ Ok(())
23
+ });
24
+ }
@@ -0,0 +1,20 @@
1
+ use halo2_proofs::plonk::{Advice, Column, ConstraintSystem};
2
+
3
+ struct Config {
4
+ denominator: Column<Advice>,
5
+ inverse: Column<Advice>,
6
+ }
7
+
8
+ fn configure(meta: &mut ConstraintSystem<Fp>) -> Config {
9
+ let denominator = meta.advice_column();
10
+ let inverse = meta.advice_column();
11
+ Config { denominator, inverse }
12
+ }
13
+
14
+ fn synthesize(config: Config, mut layouter: impl Layouter<Fp>) {
15
+ layouter.assign_region(|| "unsafe inverse", |mut region| {
16
+ let inv = witness.denominator.invert().unwrap();
17
+ region.assign_advice(|| "inverse", config.inverse, 0, || Value::known(inv))?;
18
+ Ok(())
19
+ });
20
+ }
@@ -0,0 +1,15 @@
1
+ pragma circom 2.1.0;
2
+
3
+ template SafeBoolean() {
4
+ signal input isAdmin;
5
+ signal input balance;
6
+ signal output allowedAmount;
7
+
8
+ component balanceBits = Num2Bits(64);
9
+ balanceBits.in <== balance;
10
+
11
+ isAdmin * (isAdmin - 1) === 0;
12
+ allowedAmount <== isAdmin * balance;
13
+ }
14
+
15
+ component main = SafeBoolean();
@@ -0,0 +1,18 @@
1
+ pragma circom 2.1.0;
2
+
3
+ template SafeComponentOutput() {
4
+ signal input secret;
5
+ signal input amount;
6
+ signal output commitment;
7
+
8
+ component amountBits = Num2Bits(64);
9
+ amountBits.in <== amount;
10
+
11
+ component h = Poseidon(2);
12
+ h.inputs[0] <== secret;
13
+ h.inputs[1] <== amount;
14
+
15
+ commitment <== h.out;
16
+ }
17
+
18
+ component main = SafeComponentOutput();
@@ -0,0 +1,14 @@
1
+ pragma circom 2.1.0;
2
+
3
+ template SafeDivision() {
4
+ signal input numerator;
5
+ signal input denominator;
6
+ signal output quotient;
7
+ signal inverse;
8
+
9
+ inverse <-- 1 / denominator;
10
+ denominator * inverse === 1;
11
+ quotient <== numerator * inverse;
12
+ }
13
+
14
+ component main = SafeDivision();
@@ -0,0 +1,15 @@
1
+ pragma circom 2.1.0;
2
+
3
+ template SafePublicInput() {
4
+ signal input root;
5
+ signal input nullifierHash;
6
+ signal input computedRoot;
7
+ signal input computedNullifierHash;
8
+ signal output ok;
9
+
10
+ root === computedRoot;
11
+ nullifierHash === computedNullifierHash;
12
+ ok <== 1;
13
+ }
14
+
15
+ component main = SafePublicInput();
@@ -0,0 +1,16 @@
1
+ pragma circom 2.1.0;
2
+
3
+ template SafeRangeCheck() {
4
+ signal input amount;
5
+ signal input balance;
6
+ signal output remainingBalance;
7
+
8
+ component amountBits = Num2Bits(64);
9
+ component balanceBits = Num2Bits(64);
10
+ amountBits.in <== amount;
11
+ balanceBits.in <== balance;
12
+
13
+ remainingBalance <== balance - amount;
14
+ }
15
+
16
+ component main = SafeRangeCheck();
@@ -0,0 +1,19 @@
1
+ pragma circom 2.1.0;
2
+
3
+ template SafeTransfer() {
4
+ signal input sender;
5
+ signal input receiver;
6
+ signal input amount;
7
+ signal output commitment;
8
+
9
+ component amountBits = Num2Bits(64);
10
+ amountBits.in <== amount;
11
+
12
+ component hasher = Poseidon(3);
13
+ hasher.inputs[0] <== sender;
14
+ hasher.inputs[1] <== receiver;
15
+ hasher.inputs[2] <== amount;
16
+ commitment <== hasher.out;
17
+ }
18
+
19
+ component main = SafeTransfer();
@@ -0,0 +1,12 @@
1
+ pragma circom 2.1.0;
2
+
3
+ template AliasRisk() {
4
+ signal input value;
5
+ signal output out;
6
+
7
+ component bits = Num2Bits(254);
8
+ bits.in <== value;
9
+ out <== value;
10
+ }
11
+
12
+ component main = AliasRisk();
@@ -0,0 +1,12 @@
1
+ pragma circom 2.1.0;
2
+
3
+ template MerkleSelector() {
4
+ signal input left;
5
+ signal input right;
6
+ signal input pathIndex;
7
+ signal output selected;
8
+
9
+ selected <== pathIndex * left + (1 - pathIndex) * right;
10
+ }
11
+
12
+ component main = MerkleSelector();
@@ -0,0 +1,11 @@
1
+ pragma circom 2.1.0;
2
+
3
+ template AdminGate() {
4
+ signal input isAdmin;
5
+ signal input balance;
6
+ signal output allowedAmount;
7
+
8
+ allowedAmount <== isAdmin * balance;
9
+ }
10
+
11
+ component main = AdminGate();
@@ -0,0 +1,11 @@
1
+ pragma circom 2.1.0;
2
+
3
+ template Payment() {
4
+ signal input amount;
5
+ signal input balance;
6
+ signal output remainingBalance;
7
+
8
+ remainingBalance <== balance - amount;
9
+ }
10
+
11
+ component main = Payment();
@@ -0,0 +1,12 @@
1
+ pragma circom 2.1.0;
2
+
3
+ template PublicBinding() {
4
+ signal input root;
5
+ signal input nullifierHash;
6
+ signal input secret;
7
+ signal output out;
8
+
9
+ out <== secret * secret;
10
+ }
11
+
12
+ component main = PublicBinding();
@@ -0,0 +1,15 @@
1
+ pragma circom 2.1.0;
2
+
3
+ template Commitment() {
4
+ signal input secret;
5
+ signal input amount;
6
+ signal output commitment;
7
+
8
+ component h = Poseidon(2);
9
+ h.inputs[0] <== secret;
10
+ h.inputs[1] <== amount;
11
+
12
+ commitment <-- h.out;
13
+ }
14
+
15
+ component main = Commitment();
@@ -0,0 +1,17 @@
1
+ pragma circom 2.1.0;
2
+
3
+ template Transfer() {
4
+ signal input sender;
5
+ signal input receiver;
6
+ signal input amount;
7
+ signal output commitment;
8
+
9
+ component hasher = Poseidon(3);
10
+ hasher.inputs[0] <== sender;
11
+ hasher.inputs[1] <== receiver;
12
+ hasher.inputs[2] <== amount;
13
+
14
+ commitment <-- hasher.out;
15
+ }
16
+
17
+ component main = Transfer();
@@ -0,0 +1,12 @@
1
+ pragma circom 2.1.0;
2
+
3
+ template AssertSecret() {
4
+ signal input secret;
5
+ signal input expected;
6
+ signal output ok;
7
+
8
+ assert(secret === expected);
9
+ ok <== 1;
10
+ }
11
+
12
+ component main = AssertSecret();
@@ -0,0 +1,11 @@
1
+ pragma circom 2.1.0;
2
+
3
+ template UnsafeDivision() {
4
+ signal input numerator;
5
+ signal input denominator;
6
+ signal output quotient;
7
+
8
+ quotient <-- numerator / denominator;
9
+ }
10
+
11
+ component main = UnsafeDivision();
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@trynullsec/s1-zk",
3
+ "version": "1.0.0",
4
+ "description": "Nullsec S1-ZK: AI-native auditing for zero-knowledge circuits.",
5
+ "type": "module",
6
+ "bin": {
7
+ "nullsec-zk": "dist/cli.js"
8
+ },
9
+ "exports": {
10
+ ".": "./dist/index.js"
11
+ },
12
+ "scripts": {
13
+ "build": "tsc -p tsconfig.json",
14
+ "dev": "tsx src/cli.ts",
15
+ "test": "vitest run tests",
16
+ "lint": "tsc -p tsconfig.json --noEmit"
17
+ },
18
+ "keywords": [
19
+ "zk",
20
+ "circom",
21
+ "security",
22
+ "static-analysis",
23
+ "auditing"
24
+ ],
25
+ "license": "UNLICENSED",
26
+ "dependencies": {
27
+ "chalk": "^5.6.2",
28
+ "commander": "^14.0.2",
29
+ "fast-glob": "^3.3.3"
30
+ },
31
+ "devDependencies": {
32
+ "@types/node": "^24.10.2",
33
+ "tsx": "^4.21.0",
34
+ "typescript": "^5.9.3",
35
+ "vitest": "^4.0.14"
36
+ },
37
+ "files": [
38
+ "dist",
39
+ "README.md",
40
+ "RULES.md",
41
+ "LIMITATIONS.md",
42
+ "ROADMAP.md",
43
+ "examples",
44
+ "benchmarks"
45
+ ]
46
+ }