Skip to content

Commit 5f7a790

Browse files
authored
chore: Add ecdsa batch mul documentation (#17983)
Updates biggroup README to include how the ECDSA batch mul works.
1 parent 2a5af7a commit 5f7a790

File tree

1 file changed

+207
-0
lines changed
  • barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup

1 file changed

+207
-0
lines changed

barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/README.md

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,213 @@ $$
270270

271271
Notice that the terms $e'_{i, \textsf{negative}}$ and $c'_{\textsf{negative}}$ are similar to $e'_i$ and $c'$ respectively, except that the sign bits are flipped. Thus, we can use the same circuit logic to reconstruct both $a$ and $-a_{\textsf{negative}}$ from their wNAF representations with appropriate sign bit handling.
272272

273+
### MSM for ECDSA Verification
274+
275+
In ECDSA verification over the secp256k1 curve, we need to compute a multi-scalar multiplication (MSM) of the form:
276+
277+
$$
278+
A = u_1 \cdot G + u_2 \cdot Q
279+
$$
280+
281+
where $G \in \mathbb{G}$ is the generator point of the secp256k1 curve, $Q \in \mathbb{G}$ is the public key point, and $u_1, u_2 \in \mathbb{F}_r$ are scalars derived from the message hash and signature. Both $G$ and $Q$ are known points on the curve, and we can use fixed-base lookup tables for $G$ and variable-base lookup tables for $Q$. Specifically for $G$, we use 8-bit (fixed) lookup tables of the form:
282+
283+
$$
284+
\begin{aligned}
285+
\def\arraystretch{1.6}
286+
\def\arraycolsep{40pt}
287+
\begin{array}{|c|c|c|}
288+
\hline
289+
\textsf{Index} & \textsf{Element} & \textsf{Endomorphism} \\
290+
\hline
291+
0 & -255 \cdot G & -255 \endogroup \cdot G \\
292+
\hline
293+
1 & -253 \cdot G & -253 \endogroup \cdot G \\
294+
\hline
295+
\vdots & \vdots & \vdots \\
296+
\hline
297+
126 & -3 \cdot G & -3 \endogroup \cdot G \\
298+
\hline
299+
127 & -1 \cdot G & -1 \endogroup \cdot G \\
300+
\hline
301+
128 & 1 \cdot G & 1 \endogroup \cdot G \\
302+
\hline
303+
129 & 3 \cdot G & 3 \endogroup \cdot G \\
304+
\hline
305+
\vdots & \vdots & \vdots \\
306+
\hline
307+
254 & 253 \cdot G & 253 \endogroup \cdot G \\
308+
\hline
309+
255 & 255 \cdot G & 255 \endogroup \cdot G \\
310+
\hline
311+
\end{array}
312+
\end{aligned}
313+
$$
314+
315+
and for $Q$, we use 4-bit ROM tables as described earlier. The scalars $u_1$ and $u_2$ are first split into 128-bit scalars using the endomorphism:
316+
317+
$$
318+
\begin{aligned}
319+
u_1 \cdot G &= f' \cdot \lambda G + f \cdot G, \\
320+
u_2 \cdot Q &= v' \cdot \lambda Q + v \cdot Q.
321+
\end{aligned}
322+
$$
323+
324+
where $f, f'$ denote fixed-base scalars and $v, v'$ denote variable-base scalars. Each of these scalars are at most 128 bits long and can be represented in wNAF form with stagger and skew factors as described earlier. To illustrate, consider the following example wNAF representations for 16-bit scalars:
325+
326+
$$
327+
\def\arraystretch{1.4}
328+
\begin{array}{|r|c|ccccccccccccccccccccc|}
329+
\hline
330+
\textsf{scalar} & \textsf{point} & \windex{2^{19}} & \windex{2^{18}} & \windex{2^{17}} & \windex{2^{16}} & \windex{2^{15}} & \windex{2^{14}} & \windex{2^{13}} & \windex{2^{12}} & \windex{2^{11}} & \windex{2^{10}} & \windex{2^9} & \windex{2^8} & \windex{2^7} & \windex{2^6} & \windex{2^5} & \windex{2^4} & \windex{2^3} & \windex{2^2} & \windex{2^1} & \windex{2^0} \\ \hline
331+
f' & \lambda G & & \windex{0} & \windex{0} & \windex{0} & \textcolor{orange}{1} & \textcolor{orange}{0} & \textcolor{orange}{1} & \textcolor{orange}{1} & \textcolor{orange}{0} & \textcolor{orange}{1} & \textcolor{orange}{1} & \textcolor{orange}{0} & \textcolor{orange}{0} & \textcolor{orange}{0} & \textcolor{orange}{1} & \textcolor{orange}{0} & \textcolor{orange}{1} & \textcolor{red}{1} & \textcolor{red}{1} & \textcolor{red}{0}
332+
\\
333+
w\textsf{NAF} & & & \textcolor{orange}{\lfloor} & & & & \textcolor{orange}{f'_1} & & & \textcolor{orange}{\rfloor} & \textcolor{orange}{\lfloor} & & & & \textcolor{orange}{f'_0} & & & \textcolor{orange}{\rfloor} & \textcolor{red}{\lfloor} & \textcolor{red}{c_{f'}} & \textcolor{red}{\rfloor}
334+
\\ \hline
335+
f & G & & & \windex{0} & \windex{0} & \textcolor{orange}{1} & \textcolor{orange}{1} & \textcolor{orange}{0} & \textcolor{orange}{1} & \textcolor{orange}{0} & \textcolor{orange}{0} & \textcolor{orange}{0} & \textcolor{orange}{1} & \textcolor{orange}{0} & \textcolor{orange}{0} & \textcolor{orange}{1} & \textcolor{orange}{1} & \textcolor{orange}{1} & \textcolor{orange}{0} & \textcolor{red}{0} & \textcolor{red}{1}
336+
\\
337+
w\textsf{NAF} & & & & \textcolor{orange}{\lfloor} & & & & \textcolor{orange}{f_1} & & & \textcolor{orange}{\rfloor} & \textcolor{orange}{\lfloor} & & & & \textcolor{orange}{f_0} & & & \textcolor{orange}{\rfloor} & \textcolor{red}{\lfloor} & \textcolor{red}{c_{f}} \textcolor{red}{\rfloor}
338+
\\ \hline
339+
v' & \lambda Q & & & & \windex{0} & \textcolor{skyblue}{1} & \textcolor{skyblue}{1} & \textcolor{skyblue}{0} & \textcolor{violet}{1} & \textcolor{violet}{1} & \textcolor{violet}{1} & \textcolor{violet}{0} & \textcolor{skyblue}{0} & \textcolor{skyblue}{1} & \textcolor{skyblue}{1} & \textcolor{skyblue}{0} & \textcolor{violet}{0} & \textcolor{violet}{0} & \textcolor{violet}{1} & \textcolor{violet}{1} & \textcolor{red}{1}
340+
\\
341+
w\textsf{NAF} & & & & & \textcolor{skyblue}{\lfloor} & & \textcolor{skyblue}{v'_3} & \textcolor{skyblue}{\rfloor} & \textcolor{violet}{\lfloor} & & \textcolor{violet}{v'_2} & \textcolor{violet}{\rfloor} & \textcolor{skyblue}{\lfloor} & & \textcolor{skyblue}{v'_1} & \textcolor{skyblue}{\rfloor} & \textcolor{violet}{\lfloor} & & \textcolor{violet}{v'_0} & \textcolor{violet}{\rfloor} & \textcolor{red}{c_{v'}}
342+
\\ \hline
343+
v & Q & \textcolor{yellow}{1} & \textcolor{yellow}{0} & \textcolor{yellow}{0} & \textcolor{yellow}{0} & \textcolor{skyblue}{1} & \textcolor{skyblue}{1} & \textcolor{skyblue}{0} & \textcolor{skyblue}{1} & \textcolor{violet}{0} & \textcolor{violet}{1} & \textcolor{violet}{0} & \textcolor{violet}{1} & \textcolor{skyblue}{1} & \textcolor{skyblue}{0} & \textcolor{skyblue}{1} & \textcolor{skyblue}{1} & \textcolor{violet}{1} & \textcolor{violet}{0} & \textcolor{violet}{0} & \textcolor{violet}{1}
344+
\\
345+
w\textsf{NAF} & & \textcolor{yellow}{\lfloor} & & \textcolor{yellow}{v_4} & \textcolor{yellow}{\rfloor} & \textcolor{skyblue}{\lfloor} & & \textcolor{skyblue}{v_3} & \textcolor{skyblue}{\rfloor} & \textcolor{violet}{\lfloor} & & \textcolor{violet}{v_2} & \textcolor{violet}{\rfloor} & \textcolor{skyblue}{\lfloor} & & \textcolor{skyblue}{v_1} & \textcolor{skyblue}{\rfloor} & \textcolor{violet}{\lfloor} & & \textcolor{violet}{v_0} & \textcolor{violet}{\rfloor} \\ \hline
346+
\end{array}
347+
$$
348+
349+
Since we have 8-bit tables for the generator $G$, we use a wNAF window size of $w = 8$ for the fixed-base scalars $f, f'$. For the variable-base scalars $v, v'$, we use a wNAF window size of $w = 4$ since we have 4-bit ROM tables for $Q$. The number of stagger bits are 0 and 1 for $v$ and $v'$ respectively, and 2 and 3 for $f$ and $f'$ respectively. We will explain the reason for this choice of the number of stagger bits soon. Notice an extra wNAF term in $v$ (shown in yellow) which we will also explain later. The final MSM expression combining all the terms should look like this:
350+
351+
$$
352+
\begin{aligned}
353+
A =&\ \windex{2^0} \cdot \underset{\textsf{ROM lookup}}{\boxed{\textcolor{violet}{v_0} \cdot Q}} +
354+
\windex{2^1} \cdot \underset{\textsf{ROM lookup}}{\boxed{\textcolor{violet}{v'_0} \cdot (\lambda Q)}} +
355+
\windex{2^2} \cdot \underset{\textsf{regular lookup}}{\boxed{\textcolor{orange}{f_0} \cdot G}} +
356+
\windex{2^{3}} \cdot \underset{\textsf{regular lookup}}{\boxed{\textcolor{orange}{f'_0} \cdot (\lambda G)}} +
357+
\windex{2^{4}} \cdot \underset{\textsf{ROM lookup}}{\boxed{\textcolor{skyblue}{v_1} \cdot Q}} +
358+
\windex{2^{5}} \cdot \underset{\textsf{ROM lookup}}{\boxed{\textcolor{skyblue}{v'_1} \cdot (\lambda Q)}}
359+
+ \\[10pt]
360+
&\ \windex{2^8} \cdot \underset{\textsf{ROM lookup}}{\boxed{\textcolor{violet}{v_2} \cdot Q}} +
361+
\windex{2^9} \cdot \underset{\textsf{ROM lookup}}{\boxed{\textcolor{violet}{v'_2} \cdot (\lambda Q)}} +
362+
\windex{2^{10}} \cdot \underset{\textsf{regular lookup}}{\boxed{\textcolor{orange}{f_1} \cdot G}} +
363+
\windex{2^{11}} \cdot \underset{\textsf{regular lookup}}{\boxed{\textcolor{orange}{f'_1} \cdot (\lambda G)}} +
364+
\windex{2^{12}} \cdot \underset{\textsf{ROM lookup}}{\boxed{\textcolor{skyblue}{v_3} \cdot Q}} +
365+
\windex{2^{13}} \cdot \underset{\textsf{ROM lookup}}{\boxed{\textcolor{skyblue}{v'_3} \cdot (\lambda Q)}} + \windex{2^{16}} \cdot \underset{\textsf{ROM lookup}}{\boxed{\textcolor{yellow}{v_4} \cdot Q}}
366+
\\[10pt]
367+
&\ + \ \underbrace{\underset{\textsf{regular lookup}}{\boxed{\textcolor{red}{c_f} \cdot G}} + \underset{\textsf{regular lookup}}{\boxed{\textcolor{red}{c_{f'}} \cdot (\lambda G)}} + \underset{\textsf{ROM lookup}}{\boxed{\textcolor{red}{c_{v'}} \cdot (\lambda Q)}}}_{\textsf{stagger fragments}}
368+
\\[10pt]
369+
&\ + \
370+
\underbrace{\textcolor{orange}{\mathfrak{s}_{f}} \cdot G +
371+
\textcolor{orange}{\mathfrak{s}_{f'}} \cdot (\lambda G) +
372+
\textcolor{skyblue}{\mathfrak{s}_{v}} \cdot Q +
373+
\textcolor{skyblue}{\mathfrak{s}_{v'}} \cdot (\lambda Q)}_{\textsf{skew terms}},
374+
\\[20pt]
375+
=&\ S_0 + \windex{2^6} \cdot \left(\windex{2^2} \cdot S_1\right) + \windex{2^{12}} \cdot \left(\windex{2^4} \cdot \boxed{\textcolor{yellow}{v_4} \cdot Q} \ \right) + \textsf{stagger} + \textsf{skew}
376+
\end{aligned}
377+
$$
378+
379+
where
380+
381+
$$
382+
\begin{aligned}
383+
S_0 =&\ \windex{2^0} \cdot \underset{\textsf{ROM lookup}}{\boxed{\textcolor{violet}{v_0} \cdot Q}} +
384+
\windex{2^1} \cdot \underset{\textsf{ROM lookup}}{\boxed{\textcolor{violet}{v'_0} \cdot (\lambda Q)}} +
385+
\windex{2^2} \cdot \underset{\textsf{regular lookup}}{\boxed{\textcolor{orange}{f_0} \cdot G}} +
386+
\windex{2^{3}} \cdot \underset{\textsf{regular lookup}}{\boxed{\textcolor{orange}{f'_0} \cdot (\lambda G)}} +
387+
\windex{2^{4}} \cdot \underset{\textsf{ROM lookup}}{\boxed{\textcolor{skyblue}{v_1} \cdot Q}} +
388+
\windex{2^{5}} \cdot \underset{\textsf{ROM lookup}}{\boxed{\textcolor{skyblue}{v'_1} \cdot (\lambda Q)}},
389+
\\[10pt]
390+
S_1 =&\ \windex{2^0} \cdot \underset{\textsf{ROM lookup}}{\boxed{\textcolor{violet}{v_2} \cdot Q}} +
391+
\windex{2^1} \cdot \underset{\textsf{ROM lookup}}{\boxed{\textcolor{violet}{v'_2} \cdot (\lambda Q)}} +
392+
\windex{2^2} \cdot \underset{\textsf{regular lookup}}{\boxed{\textcolor{orange}{f_1} \cdot G}} +
393+
\windex{2^{3}} \cdot \underset{\textsf{regular lookup}}{\boxed{\textcolor{orange}{f'_1} \cdot (\lambda G)}} +
394+
\windex{2^{4}} \cdot \underset{\textsf{ROM lookup}}{\boxed{\textcolor{skyblue}{v_3} \cdot Q}} +
395+
\windex{2^{5}} \cdot \underset{\textsf{ROM lookup}}{\boxed{\textcolor{skyblue}{v'_3} \cdot (\lambda Q)}}.
396+
\end{aligned}
397+
$$
398+
399+
We can see a pattern here that the wNAF slices can be grouped based on their bit positions and use Montgomery ladder steps of size 6 to compute the MSM efficiently. This pattern is the reason for our choice of stagger bits for the scalars. If we did not use this particular choice of stagger bits, we would not be able to group the wNAF slices in a montgomery ladder pattern as shown above. The reason montgomery ladder is efficient because it uses lesser field reductions compared to a naive double-and-add approach, resulting in fewer constrains. We can compute the MSM using the following sequence of operations.
400+
401+
$$
402+
\begin{aligned}
403+
\textsf{step 0:} & & \textsf{acc} \leftarrow&\ \boxed{\textcolor{yellow}{v_4} \cdot Q} \\
404+
\textsf{step 1:} & & \textsf{acc} \leftarrow&\ \windex{2} \cdot (\windex{2} \cdot \textsf{acc}) \\
405+
\textsf{step 2:} & & \textsf{acc} \leftarrow&\
406+
\windex{2} \cdot
407+
\Bigg(
408+
\windex{2} \cdot
409+
\bigg(
410+
\windex{2} \cdot
411+
\Big(
412+
\windex{2} \cdot
413+
\big(
414+
\windex{2} \cdot
415+
(
416+
\windex{2} \cdot \textsf{acc} +
417+
\mathcal{Q}_{\lambda}[\textcolor{skyblue}{v'_3}]
418+
) +
419+
\mathcal{Q}[\textcolor{skyblue}{v_3}]
420+
\big) +
421+
\mathcal{G}_{\lambda}[\textcolor{orange}{f'_1}]
422+
\Big) +
423+
\mathcal{G}[\textcolor{orange}{f_1}]
424+
\bigg) +
425+
\mathcal{Q}_{\lambda}[\textcolor{violet}{v'_2}]
426+
\Bigg) +
427+
\mathcal{Q}[\textcolor{violet}{v_2}]
428+
\\
429+
\textsf{step 3:} & & \textsf{acc} \leftarrow&\ \windex{2} \cdot (\windex{2} \cdot \textsf{acc}) \\
430+
\textsf{step 4:} & & \textsf{acc} \leftarrow&\
431+
\windex{2} \cdot
432+
\Bigg(
433+
\windex{2} \cdot
434+
\Bigg(
435+
\windex{2} \cdot
436+
\Big(
437+
\windex{2} \cdot
438+
\bigg(
439+
\windex{2} \cdot
440+
\Big(
441+
\windex{2} \cdot \textsf{acc} +
442+
\mathcal{Q}_{\lambda}[\textcolor{skyblue}{v'_1}]
443+
) +
444+
\mathcal{Q}[\textcolor{skyblue}{v_1}]
445+
\bigg) +
446+
\mathcal{G}_{\lambda}[\textcolor{orange}{f'_0}]
447+
\Big) +
448+
\mathcal{G}[\textcolor{orange}{f_0}]
449+
\Bigg) +
450+
\mathcal{Q}_{\lambda}[\textcolor{violet}{v'_0}]
451+
\Bigg) +
452+
\mathcal{Q}[\textcolor{violet}{v_0}]
453+
\end{aligned}
454+
$$
455+
456+
where $\mathcal{Q}, \ \mathcal{Q}_{\lambda}$ and $\mathcal{G}, \ \mathcal{G}_{\lambda}$ are the lookup tables for the ROM and regular lookups, respectively. Next, we add the stagger fragments to the accumulator to get the MSM result:
457+
458+
$$
459+
\begin{aligned}
460+
A = \textsf{acc} +
461+
\mathcal{Q}[\textcolor{red}{c_f}] +
462+
\mathcal{Q}_{\lambda}[\textcolor{red}{c_{f'}}] +
463+
\mathcal{G}_{\lambda}[\textcolor{red}{c_{v'}}].
464+
\end{aligned}
465+
$$
466+
467+
Finally, we need to adjust the skew factors for each scalar multiplication. Thus, the final MSM output with skew adjustments is:
468+
469+
$$
470+
\begin{aligned}
471+
A \leftarrow&\ A + \textcolor{orange}{\mathfrak{s}_{f}} \cdot G +
472+
\textcolor{orange}{\mathfrak{s}_{f'}} \cdot (\lambda G) +
473+
\textcolor{skyblue}{\mathfrak{s}_{v}} \cdot Q +
474+
\textcolor{skyblue}{\mathfrak{s}_{v'}} \cdot (\lambda Q).
475+
\end{aligned}
476+
$$
477+
478+
Since our scalars are at most 128 bits long after endomorphism, we can represent the fixed-base scalars using at most 16 wNAF slices (as the window size is $w = 8$) and the variable-base scalars using at most 32 wNAF slices (as the window size is $w = 4$). We choose to represent the scalar $v \in \mathbb{F}_r$ using 33 wNAF slices instead of 32 to because we initialise the accumulator with the extra slice $\textcolor{yellow}{v_4}$ at the start of the MSM computation. This allows us to use a uniform pattern of Montgomery ladder steps of size 6 throughout the MSM computation. In total, we perform 16 rounds each consisting of 2 Montgomery ladder steps of size 6, resulting in a total of 32 ladder steps to compute the MSM.
479+
273480
### Signed Digit Representation
274481

275482
We can write the bit representation of an $n$-bit scalar $a$ with bits $a_0, a_1 \dots, a_{n - 1} \in \{0, 1\}$ as follows:

0 commit comments

Comments
 (0)