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.

258 lines
13 KiB

6 years ago
6 years ago
5 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
  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. include "../gates.circom";
  97. include "../bitify.circom";
  98. include "../comparators.circom";
  99. include "../switcher.circom";
  100. include "smtlevins.circom";
  101. include "smtprocessorlevel.circom";
  102. include "smtprocessorsm.circom";
  103. include "smthash_poseidon.circom";
  104. template SMTProcessor(nLevels) {
  105. signal input oldRoot;
  106. signal output newRoot;
  107. signal input siblings[nLevels];
  108. signal input oldKey;
  109. signal input oldValue;
  110. signal input isOld0;
  111. signal input newKey;
  112. signal input newValue;
  113. signal input fnc[2];
  114. signal enabled;
  115. enabled <== fnc[0] + fnc[1] - fnc[0]*fnc[1]
  116. component hash1Old = SMTHash1();
  117. hash1Old.key <== oldKey;
  118. hash1Old.value <== oldValue;
  119. component hash1New = SMTHash1();
  120. hash1New.key <== newKey;
  121. hash1New.value <== newValue;
  122. component n2bOld = Num2Bits_strict();
  123. component n2bNew = Num2Bits_strict();
  124. n2bOld.in <== oldKey;
  125. n2bNew.in <== newKey;
  126. component smtLevIns = SMTLevIns(nLevels);
  127. for (var i=0; i<nLevels; i++) smtLevIns.siblings[i] <== siblings[i];
  128. smtLevIns.enabled <== enabled;
  129. component xors[nLevels];
  130. for (var i=0; i<nLevels; i++) {
  131. xors[i] = XOR();
  132. xors[i].a <== n2bOld.out[i];
  133. xors[i].b <== n2bNew.out[i];
  134. }
  135. component sm[nLevels];
  136. for (var i=0; i<nLevels; i++) {
  137. sm[i] = SMTProcessorSM();
  138. if (i==0) {
  139. sm[i].prev_top <== enabled;
  140. sm[i].prev_old0 <== 0;
  141. sm[i].prev_bot <== 0;
  142. sm[i].prev_new1 <== 0;
  143. sm[i].prev_na <== 1-enabled;
  144. sm[i].prev_upd <== 0;
  145. } else {
  146. sm[i].prev_top <== sm[i-1].st_top;
  147. sm[i].prev_old0 <== sm[i-1].st_old0;
  148. sm[i].prev_bot <== sm[i-1].st_bot;
  149. sm[i].prev_new1 <== sm[i-1].st_new1;
  150. sm[i].prev_na <== sm[i-1].st_na;
  151. sm[i].prev_upd <== sm[i-1].st_upd;
  152. }
  153. sm[i].is0 <== isOld0;
  154. sm[i].xor <== xors[i].out;
  155. sm[i].fnc[0] <== fnc[0];
  156. sm[i].fnc[1] <== fnc[1];
  157. sm[i].levIns <== smtLevIns.levIns[i];
  158. }
  159. sm[nLevels-1].st_na + sm[nLevels-1].st_new1 + sm[nLevels-1].st_old0 +sm[nLevels-1].st_upd === 1;
  160. component levels[nLevels];
  161. for (var i=nLevels-1; i != -1; i--) {
  162. levels[i] = SMTProcessorLevel();
  163. levels[i].st_top <== sm[i].st_top;
  164. levels[i].st_old0 <== sm[i].st_old0;
  165. levels[i].st_bot <== sm[i].st_bot;
  166. levels[i].st_new1 <== sm[i].st_new1;
  167. levels[i].st_na <== sm[i].st_na;
  168. levels[i].st_upd <== sm[i].st_upd;
  169. levels[i].sibling <== siblings[i];
  170. levels[i].old1leaf <== hash1Old.out;
  171. levels[i].new1leaf <== hash1New.out;
  172. levels[i].newlrbit <== n2bNew.out[i];
  173. if (i==nLevels-1) {
  174. levels[i].oldChild <== 0;
  175. levels[i].newChild <== 0;
  176. } else {
  177. levels[i].oldChild <== levels[i+1].oldRoot;
  178. levels[i].newChild <== levels[i+1].newRoot;
  179. }
  180. }
  181. component topSwitcher = Switcher();
  182. topSwitcher.sel <== fnc[0]*fnc[1];
  183. topSwitcher.L <== levels[0].oldRoot;
  184. topSwitcher.R <== levels[0].newRoot;
  185. component checkOldInput = ForceEqualIfEnabled();
  186. checkOldInput.enabled <== enabled;
  187. checkOldInput.in[0] <== oldRoot;
  188. checkOldInput.in[1] <== topSwitcher.outL;
  189. newRoot <== enabled * (topSwitcher.outR - oldRoot) + oldRoot;
  190. // topSwitcher.outL === oldRoot*enabled;
  191. // topSwitcher.outR === newRoot*enabled;
  192. // Ckeck keys are equal if updating
  193. component areKeyEquals = IsEqual();
  194. areKeyEquals.in[0] <== oldKey;
  195. areKeyEquals.in[1] <== newKey;
  196. component keysOk = MultiAND(3);
  197. keysOk.in[0] <== 1-fnc[0];
  198. keysOk.in[1] <== fnc[1];
  199. keysOk.in[2] <== 1-areKeyEquals.out;
  200. keysOk.out === 0;
  201. }