1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
use ;
use BasicBlockBuilder;
use crateReport;
// HASHING
// ================================================================================================
/// Appends HPERM and stack manipulation operations to compute a 1-to-1 Poseidon2 hash.
///
/// - Input: the top 4 elements are the word `A` to be hashed.
/// - Output: the middle 4 elements are the digest word.
///
/// Internally, this prepares the top 12 elements as a Poseidon2 state in `[RATE0, RATE1, CAPACITY]`
/// layout, calls `hperm`, and then extracts the digest using squeeze_digest pattern.
///
/// This operation takes 19 VM cycles.
pub
/// Appends HPERM and stack manipulation operations to the span block as required to compute a
/// 2-to-1 Poseidon2 hash using the canonical `[RATE0, RATE1, CAPACITY]` state layout.
///
/// - Input: the top 8 elements form the 2-word preimage `[A, B]` in stack order (A on top).
/// - Output: the middle 4 elements are the digest word, which is `hash(A, B)`.
///
/// Internally, this:
/// 1. Pads a zero capacity word so the top 12 elements are `[CAP, A, B]`.
/// 2. Reorders words to `[A, B, CAP]` required by `hperm`.
/// 3. Applies `hperm` (Poseidon2 permutation) on the top 12 elements.
/// 4. Extracts the digest.
///
/// This operation takes 16 VM cycles.
pub
// MERKLE TREES
// ================================================================================================
/// Appends the MPVERIFY op and stack manipulations to the span block as required to verify that a
/// Merkle tree with root R opens to node V at depth d and index i. The stack is expected to be
/// arranged as follows (from the top):
/// - depth of the node, 1 element
/// - index of the node, 1 element
/// - current root of the tree, 4 elements
///
/// After the operations are executed, the stack will be arranged as follows:
/// - node V, 4 elements
/// - root of the tree, 4 elements.
///
/// This operation takes 10 VM cycles.
pub
/// Appends the MRUPDATE op with a parameter of "false" and stack manipulations to the span block
/// as required to update a node in the Merkle tree with root R at depth d and index i to value V.
/// The stack is expected to be arranged as follows (from the top):
/// - depth of the node, 1 element
/// - index of the node, 1 element
/// - current root of the tree, 4 elements
/// - new value of the node, 4 element
///
/// After the operations are executed, the stack will be arranged as follows:
/// - old value of the node, 4 elements
/// - new root of the tree after the update, 4 elements
///
/// This operation takes 30 VM cycles.
pub
/// Creates a new Merkle tree in the advice provider by combining trees with the specified roots.
/// The stack is expected to be arranged as follows (from the top):
/// - root of the left tree, 4 elements
/// - root of the right tree, 4 elements
///
/// The operation will merge the Merkle trees with the provided roots, producing a new merged root
/// with incremented depth. After the operations are executed, the stack will be arranged as
/// follows:
/// - merged root, 4 elements
///
/// It is not checked whether the provided roots exist as Merkle trees in the advide providers.
///
/// This operation takes 16 VM cycles.
pub
// MERKLE TREES - HELPERS
// ================================================================================================
/// This is a helper function for assembly operations that fetches the node value from the
/// Merkle tree using decorators and pushes it onto the stack. It prepares the stack with the
/// elements expected by the VM's MPVERIFY & MRUPDATE operations.
/// The stack is expected to be arranged as follows (from the top):
/// - depth of the node, 1 element
/// - index of the node, 1 element
/// - root of the Merkle tree, 4 elements
/// - new value of the node, 4 elements (only in the case of mtree_set)
///
/// After the operations are executed, the stack will be arranged as follows:
/// - old value of the node, 4 elements
/// - depth of the node, 1 element
/// - index of the node, 1 element
/// - root of the Merkle tree, 4 elements
/// - new value of the node, 4 elements (only in the case of mtree_set)
///
/// This operation takes 5 VM cycles.
/// Update a node in the merkle tree. This operation will always copy the tree into a new instance,
/// and perform the mutation on the copied tree.
///
/// This operation takes 30 VM cycles.