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.

261 lines
13 KiB

  1. /*
  2. Copyright 2018 0KIMS association.
  3. This file is part of circom (Zero Knowledge Circuit Compiler).
  4. circom is a free software: you can redistribute it and/or modify it
  5. under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. circom is distributed in the hope that it will be useful, but WITHOUT
  9. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
  11. License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with circom. If not, see <https://www.gnu.org/licenses/>.
  14. */
  15. /***************************************************************************************************
  16. SMTProcessor: Sparse Merkle Tree processor is a component to verify an insert/update/delete elements
  17. into the Sparse Merkle tree.
  18. Insert to an empty leaf
  19. =======================
  20. STATE OLD STATE NEW STATE
  21. ===== ========= =========
  22. oldRoot newRoot
  23. ▲ ▲
  24. │ │
  25. ┌───────┐ ┏━━━┻━━━┓ ┌───────┐ ┏━━━┻━━━┓
  26. top │Sibling├────▶┃ Hash ┃◀─┐ │Sibling├────▶┃ Hash ┃◀─┐
  27. └───────┘ ┗━━━━━━━┛ │ └───────┘ ┗━━━━━━━┛ │
  28. │ │
  29. │ │
  30. ┏━━━┻━━━┓ ┌───────┐ ┏━━━┻━━━┓ ┌───────┐
  31. top ┌─────▶┃ Hash ┃◀──┤Sibling│ ┌─────▶┃ Hash ┃◀──┤Sibling│
  32. │ ┗━━━━━━━┛ └───────┘ │ ┗━━━━━━━┛ └───────┘
  33. │ │
  34. │ │
  35. ┌───────┐ ┏━━━┻━━━┓ ┌───────┐ ┏━━━┻━━━┓
  36. top │Sibling├──▶┃ Hash ┃◀─────┐ │Sibling├──▶┃ Hash ┃◀─────┐
  37. └───────┘ ┗━━━━━━━┛ │ └───────┘ ┗━━━━━━━┛ │
  38. │ │
  39. │ │
  40. ┌────┴────┐ ┌────┴────┐
  41. old0 │ 0 │ │New1Leaf │
  42. └─────────┘ └─────────┘
  43. ┏━━━━━━━┓ ┏━━━━━━━┓
  44. na ┃ Hash ┃ ┃ Hash ┃
  45. ┗━━━━━━━┛ ┗━━━━━━━┛
  46. ┏━━━━━━━┓ ┏━━━━━━━┓
  47. na ┃ Hash ┃ ┃ Hash ┃
  48. ┗━━━━━━━┛ ┗━━━━━━━┛
  49. Insert to a used leaf.
  50. =====================
  51. STATE OLD STATE NEW STATE
  52. ===== ========= =========
  53. oldRoot newRoot
  54. ▲ ▲
  55. │ │
  56. ┌───────┐ ┏━━━┻━━━┓ ┌───────┐ ┏━━━┻━━━┓
  57. top │Sibling├────▶┃ Hash ┃◀─┐ │Sibling├────▶┃ Hash ┃◀─┐
  58. └───────┘ ┗━━━━━━━┛ │ └───────┘ ┗━━━━━━━┛ │
  59. │ │
  60. │ │
  61. ┏━━━┻━━━┓ ┌───────┐ ┏━━━┻━━━┓ ┌───────┐
  62. top ┌─────▶┃ Hash ┃◀──┤Sibling│ ┌─────▶┃ Hash ┃◀──┤Sibling│
  63. │ ┗━━━━━━━┛ └───────┘ │ ┗━━━━━━━┛ └───────┘
  64. │ │
  65. │ │
  66. ┌───────┐ ┏━━━┻━━━┓ ┌───────┐ ┏━━━┻━━━┓
  67. top │Sibling├──▶┃ Hash ┃◀─────┐ │Sibling├──▶┃ Hash ┃◀─────┐
  68. └───────┘ ┗━━━━━━━┛ │ └───────┘ ┗━━━━━━━┛ │
  69. │ │
  70. │ │
  71. ┌────┴────┐ ┏━━━┻━━━┓ ┌───────┐
  72. bot │Old1Leaf │ ┌─────▶┃ Hash ┃◀──┼─ 0 │
  73. └─────────┘ │ ┗━━━━━━━┛ └───────┘
  74. ┏━━━━━━━┓ ┌───────┐ ┏━━━┻━━━┓
  75. bot ┃ Hash ┃ │ 0 ─┼──▶┃ Hash ┃◀─────┐
  76. ┗━━━━━━━┛ └───────┘ ┗━━━━━━━┛ │
  77. ┏━━━━━━━┓ ┏━━━┻━━━┓ ┌───────┐
  78. bot ┃ Hash ┃ ┌─────▶┃ Hash ┃◀──│ 0 │
  79. ┗━━━━━━━┛ │ ┗━━━━━━━┛ └───────┘
  80. ┏━━━━━━━┓ ┌─────────┐ ┏━━━┻━━━┓ ┌─────────┐
  81. new1 ┃ Hash ┃ │Old1Leaf ├──▶┃ Hash ┃◀──│New1Leaf │
  82. ┗━━━━━━━┛ └─────────┘ ┗━━━━━━━┛ └─────────┘
  83. ┏━━━━━━━┓ ┏━━━━━━━┓
  84. na ┃ Hash ┃ ┃ Hash ┃
  85. ┗━━━━━━━┛ ┗━━━━━━━┛
  86. ┏━━━━━━━┓ ┏━━━━━━━┓
  87. na ┃ Hash ┃ ┃ Hash ┃
  88. ┗━━━━━━━┛ ┗━━━━━━━┛
  89. Fnction
  90. fnc[0] fnc[1]
  91. 0 0 NOP
  92. 0 1 UPDATE
  93. 1 0 INSERT
  94. 1 1 DELETE
  95. ***************************************************************************************************/
  96. pragma circom 2.0.0;
  97. include "../gates.circom";
  98. include "../bitify.circom";
  99. include "../comparators.circom";
  100. include "../switcher.circom";
  101. include "smtlevins.circom";
  102. include "smtprocessorlevel.circom";
  103. include "smtprocessorsm.circom";
  104. include "smthash_poseidon.circom";
  105. template SMTProcessor(nLevels) {
  106. signal input oldRoot;
  107. signal output newRoot;
  108. signal input siblings[nLevels];
  109. signal input oldKey;
  110. signal input oldValue;
  111. signal input isOld0;
  112. signal input newKey;
  113. signal input newValue;
  114. signal input fnc[2];
  115. signal enabled;
  116. var i;
  117. enabled <== fnc[0] + fnc[1] - fnc[0]*fnc[1];
  118. component hash1Old = SMTHash1();
  119. hash1Old.key <== oldKey;
  120. hash1Old.value <== oldValue;
  121. component hash1New = SMTHash1();
  122. hash1New.key <== newKey;
  123. hash1New.value <== newValue;
  124. component n2bOld = Num2Bits_strict();
  125. component n2bNew = Num2Bits_strict();
  126. n2bOld.in <== oldKey;
  127. n2bNew.in <== newKey;
  128. component smtLevIns = SMTLevIns(nLevels);
  129. for (i=0; i<nLevels; i++) smtLevIns.siblings[i] <== siblings[i];
  130. smtLevIns.enabled <== enabled;
  131. component xors[nLevels];
  132. for (i=0; i<nLevels; i++) {
  133. xors[i] = XOR();
  134. xors[i].a <== n2bOld.out[i];
  135. xors[i].b <== n2bNew.out[i];
  136. }
  137. component sm[nLevels];
  138. for (i=0; i<nLevels; i++) {
  139. sm[i] = SMTProcessorSM();
  140. if (i==0) {
  141. sm[i].prev_top <== enabled;
  142. sm[i].prev_old0 <== 0;
  143. sm[i].prev_bot <== 0;
  144. sm[i].prev_new1 <== 0;
  145. sm[i].prev_na <== 1-enabled;
  146. sm[i].prev_upd <== 0;
  147. } else {
  148. sm[i].prev_top <== sm[i-1].st_top;
  149. sm[i].prev_old0 <== sm[i-1].st_old0;
  150. sm[i].prev_bot <== sm[i-1].st_bot;
  151. sm[i].prev_new1 <== sm[i-1].st_new1;
  152. sm[i].prev_na <== sm[i-1].st_na;
  153. sm[i].prev_upd <== sm[i-1].st_upd;
  154. }
  155. sm[i].is0 <== isOld0;
  156. sm[i].xor <== xors[i].out;
  157. sm[i].fnc[0] <== fnc[0];
  158. sm[i].fnc[1] <== fnc[1];
  159. sm[i].levIns <== smtLevIns.levIns[i];
  160. }
  161. sm[nLevels-1].st_na + sm[nLevels-1].st_new1 + sm[nLevels-1].st_old0 +sm[nLevels-1].st_upd === 1;
  162. component levels[nLevels];
  163. for (i=nLevels-1; i != -1; i--) {
  164. levels[i] = SMTProcessorLevel();
  165. levels[i].st_top <== sm[i].st_top;
  166. levels[i].st_old0 <== sm[i].st_old0;
  167. levels[i].st_bot <== sm[i].st_bot;
  168. levels[i].st_new1 <== sm[i].st_new1;
  169. levels[i].st_na <== sm[i].st_na;
  170. levels[i].st_upd <== sm[i].st_upd;
  171. levels[i].sibling <== siblings[i];
  172. levels[i].old1leaf <== hash1Old.out;
  173. levels[i].new1leaf <== hash1New.out;
  174. levels[i].newlrbit <== n2bNew.out[i];
  175. if (i==nLevels-1) {
  176. levels[i].oldChild <== 0;
  177. levels[i].newChild <== 0;
  178. } else {
  179. levels[i].oldChild <== levels[i+1].oldRoot;
  180. levels[i].newChild <== levels[i+1].newRoot;
  181. }
  182. }
  183. component topSwitcher = Switcher();
  184. topSwitcher.sel <== fnc[0]*fnc[1];
  185. topSwitcher.L <== levels[0].oldRoot;
  186. topSwitcher.R <== levels[0].newRoot;
  187. component checkOldInput = ForceEqualIfEnabled();
  188. checkOldInput.enabled <== enabled;
  189. checkOldInput.in[0] <== oldRoot;
  190. checkOldInput.in[1] <== topSwitcher.outL;
  191. newRoot <== enabled * (topSwitcher.outR - oldRoot) + oldRoot;
  192. // topSwitcher.outL === oldRoot*enabled;
  193. // topSwitcher.outR === newRoot*enabled;
  194. // Ckeck keys are equal if updating
  195. component areKeyEquals = IsEqual();
  196. areKeyEquals.in[0] <== oldKey;
  197. areKeyEquals.in[1] <== newKey;
  198. component keysOk = MultiAND(3);
  199. keysOk.in[0] <== 1-fnc[0];
  200. keysOk.in[1] <== fnc[1];
  201. keysOk.in[2] <== 1-areKeyEquals.out;
  202. keysOk.out === 0;
  203. }