Skip to content

Commit 6212f5c

Browse files
committed
add illustration for musig topic
1 parent b2784c8 commit 6212f5c

File tree

7 files changed

+173
-41
lines changed

7 files changed

+173
-41
lines changed

decoding/musig.mdx

Lines changed: 116 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ category: Scripts
77
layout: TopicBanner
88
order: 7
99
icon: "FaUsers"
10+
images: ["/bitcoin-topics/static/images/topics/thumbnails/musig-thumbnail.webp"]
1011
parent: taproot
1112
---
1213

@@ -22,6 +23,19 @@ To make this article simple to follow, we will answer three important questions
2223

2324
MuSig is simply a protocol for aggregating public keys and signatures.
2425

26+
<div className="dark:hidden">
27+
<SvgDisplay
28+
src="/bitcoin-topics/static/images/topics/taproot/musig-1.webp"
29+
height="auto"
30+
/>
31+
</div>
32+
<div className="hidden dark:block">
33+
<SvgDisplay
34+
src="/bitcoin-topics/static/images/topics/taproot/musig-1.webp"
35+
height="auto"
36+
/>
37+
</div>
38+
2539
### Why do we need MuSig?
2640

2741
The reasons we use MuSig are:
@@ -30,12 +44,30 @@ The reasons we use MuSig are:
3044

3145
- **Privacy:** Nobody can tell if a transaction used multiple signers or just one. Your multi-sig setup stays private, as it looks identical to a regular transaction.
3246

47+
<div className="dark:hidden">
48+
<SvgDisplay
49+
src="/bitcoin-topics/static/images/topics/taproot/musig-2.webp"
50+
width="120%"
51+
height="auto"
52+
/>
53+
</div>
54+
<div className="hidden dark:block">
55+
<SvgDisplay
56+
src="/bitcoin-topics/static/images/topics/taproot/musig-2.webp"
57+
width="120%"
58+
height="auto"
59+
/>
60+
</div>
61+
3362
### How does MuSig work?
3463

3564
Now we need your focus here, please. Grab a coffee, and let's dive in.
3665

37-
Alice, Bob, and Carol want to create an aggregated signature such as:
38-
**s_agg = s_a + s_b + s_c**
66+
Alice, Bob, and Carol want to create an aggregated signature such as:
67+
68+
<div className="text-center my-4 text-orange-500">
69+
$$\mathbf{s_{agg} = s_a + s_b + s_c}$$
70+
</div>
3971

4072
To create this signature, we need to go through three main steps:
4173

@@ -48,60 +80,88 @@ Some of these steps require rounds of communication between participants:
4880
- Aggregating public keys does **not** require communication.
4981
- Aggregating nonces and signatures requires **three rounds of communication** (MuSig2 optimizes this to **two rounds**).
5082

83+
<div className="dark:hidden">
84+
<SvgDisplay
85+
src="/bitcoin-topics/static/images/topics/taproot/musig-3.webp"
86+
height="auto"
87+
/>
88+
</div>
89+
<div className="hidden dark:block">
90+
<SvgDisplay
91+
src="/bitcoin-topics/static/images/topics/taproot/musig-3.webp"
92+
height="auto"
93+
/>
94+
</div>
95+
5196
---
5297

5398
## Step 1: Public Key Aggregation (Offline Process)
5499

55100
A naive way to do public key aggregation is by summing up each participant's public key:
56101

57-
**P_agg = P_a + P_b + P_c**
102+
<div className="text-center my-4 text-orange-500">
103+
$$\mathbf{P_{agg} = P_a + P_b + P_c}$$
104+
</div>
58105

59106
However, this approach is vulnerable to a **key cancellation attack.**
60107

61-
---
108+
<div className="dark:hidden">
109+
<SvgDisplay
110+
src="/bitcoin-topics/static/images/topics/taproot/musig-4.webp"
111+
height="auto"
112+
/>
113+
</div>
114+
<div className="hidden dark:block">
115+
<SvgDisplay
116+
src="/bitcoin-topics/static/images/topics/taproot/musig-4.webp"
117+
height="auto"
118+
/>
119+
</div>
120+
121+
<ExpandableAlert type="info" title="What is a key cancellation attack?" expandable={true} initialLines={1}>
62122

63-
### What is a key cancellation attack?
123+
Imagine a scenario where Alice and Bob want to create a 2-of-2 aggregated signature.
64124

65-
Imagine a scenario where Alice and Bob want to create a 2-of-2 aggregated signature. To achieve this, they need to:
125+
To achieve this, they need to:
66126

67127
1. Exchange public keys.
68128
2. Exchange nonce commitments (needed for Schnorr signatures).
69129

70-
But if Bob knows Alices public key (P_a) and nonce (R_a) beforehand, Bob can deceive Alice by sending modified values to her:
130+
But if Bob knows Alice's public key (P<span className="text-xs align-sub">a</span>) and nonce (R<span className="text-xs align-sub">a</span>) beforehand, Bob can deceive Alice by sending modified values to her:
71131

72-
- **P'\_b = P_b - P_a**
73-
- **R'\_b = R_b - R_a**
132+
- **P'<span className="text-xs align-sub">b</span> = P<span className="text-xs align-sub">b</span> - P<span className="text-xs align-sub">a</span>**
133+
- **R'<span className="text-xs align-sub">b</span> = R<span className="text-xs align-sub">b</span> - R<span className="text-xs align-sub">a</span>**
74134

75135
When Alice calculates the signature, this manipulation causes issues.
76136

77-
---
137+
### Let's break it down:
78138

79-
### Let’s break it down:
139+
The aggregated Schnorr signature equation is:
80140

81-
The aggregated Schnorr signature equation is:
82-
**s_agg = s_a + s_b'**
141+
<div className="text-center my-4 text-orange-500">
142+
$$\mathbf{s_{agg} = s_a + s_b'}$$
143+
</div>
83144

84145
Expanding it:
85146

86-
**s*agg * G = (R*a + h * P_a) + (R'\_b + h \* P'\_b)**
87-
**= R_a + R'\_b + h(P_a + P'\_b)**
88-
**= R_a + (R_b - R_a) + h(P_a + P_b - P_a)**
89-
**= R_b + h(P_b)**
90-
**= s_b \* G**
91-
92-
---
147+
**s<span className="text-xs align-sub">agg</span> _ G = (R<span className="text-xs align-sub">a</span> + h _ P<span className="text-xs align-sub">a</span>) + (R'<span className="text-xs align-sub">b</span> + h \* P'<span className="text-xs align-sub">b</span>)**
148+
**= R<span className="text-xs align-sub">a</span> + R'<span className="text-xs align-sub">b</span> + h(P<span className="text-xs align-sub">a</span> + P'<span className="text-xs align-sub">b</span>)**
149+
**= R<span className="text-xs align-sub">a</span> + (R<span className="text-xs align-sub">b</span> - R<span className="text-xs align-sub">a</span>) + h(P<span className="text-xs align-sub">a</span> + P<span className="text-xs align-sub">b</span> - P<span className="text-xs align-sub">a</span>)**
150+
**= R<span className="text-xs align-sub">b</span> + h(P<span className="text-xs align-sub">b</span>)**
151+
**= s<span className="text-xs align-sub">b</span> \* G**
93152

94153
**Did you catch it?**
95154
Bob can now sign the transaction alone without Alice's cooperation: **s_agg = s_b**
96155

97-
---
156+
</ExpandableAlert>
98157

99158
### How do we counteract the key cancellation attack?
100159

101160
To counteract this, we add a **challenge factor** to each participant's public key:
102161

103-
**P'\_i = c_i \* P_i**
104-
(_c_i = challenge factor_)
162+
<div className="text-center my-4 text-orange-500">
163+
$$\mathbf{P'_i = c_i \times P_i}$$
164+
</div>
105165

106166
The challenge factor is generated based on the participants' aggregated public key.
107167

@@ -110,7 +170,18 @@ This ensures that no individual participant can create a public key that offsets
110170
Here’s how we construct individual public keys and the aggregated public key:
111171
(_Remember, all of this happens offline. There’s no need for communication; public keys can be exchanged through offline channels._)
112172

113-
[Insert illustration here.]
173+
<div className="dark:hidden">
174+
<SvgDisplay
175+
src="/bitcoin-topics/static/images/topics/taproot/musig-5.webp"
176+
height="auto"
177+
/>
178+
</div>
179+
<div className="hidden dark:block">
180+
<SvgDisplay
181+
src="/bitcoin-topics/static/images/topics/taproot/musig-5.webp"
182+
height="auto"
183+
/>
184+
</div>
114185

115186
---
116187

@@ -202,44 +273,44 @@ Now, let’s move to the next step: **Aggregate Nonce**.
202273

203274
The process of aggregating nonces is as follows:
204275

205-
1. Alice, Bob, and Carol each generate a random nonce **k_A**, **k_B**, and **k_C**.
276+
1. Alice, Bob, and Carol each generate a random nonce **k<span className="text-xs align-sub">A</span>**, **k<span className="text-xs align-sub">B</span>**, and **k<span className="text-xs align-sub">C</span>**.
206277
2. They calculate their respective nonce points:
207-
**R_A = k_A * G**, **R_B = k_B * G**, **R_C = k_C * G**.
208-
3. They exchange these nonce points (**R_A**, **R_B**, and **R_C**).
278+
**R<span className="text-xs align-sub">A</span> = k<span className="text-xs align-sub">A</span> * G**, **R<span className="text-xs align-sub">B</span> = k<span className="text-xs align-sub">B</span> * G**, **R<span className="text-xs align-sub">C</span> = k<span className="text-xs align-sub">C</span> * G**.
279+
3. They exchange these nonce points (**R<span className="text-xs align-sub">A</span>**, **R<span className="text-xs align-sub">B</span>**, and **R<span className="text-xs align-sub">C</span>**).
209280
4. Finally, they calculate the aggregated nonce:
210-
**R_agg = R_A + R_B + R_C**
281+
**R<span className="text-xs align-sub">agg</span> = R<span className="text-xs align-sub">A</span> + R<span className="text-xs align-sub">B</span> + R<span className="text-xs align-sub">C</span>**
211282

212283
---
213284

214285
### Where do the rounds of communication happen in this process?
215286

216287
Great question! The process of aggregating nonces is somewhat similar to aggregating public keys.
217288

218-
**Except**: Public keys (e.g., **P_A**, **P_B**, and **P_C**) stay the same for every signature process, but random numbers (**k_A**, **k_B**, **k_C**) must change with every signature.
289+
**Except**: Public keys (e.g., **P<span className="text-xs align-sub">A</span>**, **P<span className="text-xs align-sub">B</span>**, and **P<span className="text-xs align-sub">C</span>**) stay the same for every signature process, but random numbers (**k<span className="text-xs align-sub">A</span>**, **k<span className="text-xs align-sub">B</span>**, **k<span className="text-xs align-sub">C</span>**) must change with every signature.
219290

220-
Thus, in each signature process, we need a round of communication where Alice, Bob, and Carol exchange their **R_i** values to construct:
221-
**R_agg = R_A + R_B + R_C**
291+
Thus, in each signature process, we need a round of communication where Alice, Bob, and Carol exchange their **R<span className="text-xs align-sub">i</span>** values to construct:
292+
**R<span className="text-xs align-sub">agg</span> = R<span className="text-xs align-sub">A</span> + R<span className="text-xs align-sub">B</span> + R<span className="text-xs align-sub">C</span>**
222293

223-
However, before this step (where they exchange **R_i**), there is a **prior round of communication** to ensure none of them cheats by changing their **R_i** after seeing the others’ values.
294+
However, before this step (where they exchange **R<span className="text-xs align-sub">i</span>**), there is a **prior round of communication** to ensure none of them cheats by changing their **R<span className="text-xs align-sub">i</span>** after seeing the others’ values.
224295

225296
---
226297

227298
### How do we prevent cheating?
228299

229-
To prevent cheating, Alice, Bob, and Carol must first exchange the **hashes** of their nonce points (e.g., **H(R_A)**, **H(R_B)**, **H(R_C)**) before revealing their actual **R_i** values. This ensures that once they reveal their **R_i**, they cannot modify their values after seeing others’.
300+
To prevent cheating, Alice, Bob, and Carol must first exchange the **hashes** of their nonce points (e.g., **H(R<span className="text-xs align-sub">A</span>)**, **H(R<span className="text-xs align-sub">B</span>)**, **H(R<span className="text-xs align-sub">C</span>)**) before revealing their actual **R<span className="text-xs align-sub">i</span>** values. This ensures that once they reveal their **R<span className="text-xs align-sub">i</span>**, they cannot modify their values after seeing others’.
230301

231302
---
232303

233304
### Summary: Two Rounds of Communication for Nonce Aggregation
234305

235306
1. **Exchange hash commitments:**
236-
Alice, Bob, and Carol share **H(R_A)**, **H(R_B)**, and **H(R_C)**.
307+
Alice, Bob, and Carol share **H(R<span className="text-xs align-sub">A</span>)**, **H(R<span className="text-xs align-sub">B</span>)**, and **H(R<span className="text-xs align-sub">C</span>)**.
237308

238309
2. **Exchange nonce points:**
239-
They reveal **R_A**, **R_B**, and **R_C**.
310+
They reveal **R<span className="text-xs align-sub">A</span>**, **R<span className="text-xs align-sub">B</span>**, and **R<span className="text-xs align-sub">C</span>**.
240311

241-
Once all **R_i** values are shared, they compute the aggregated nonce:
242-
**R_agg = R_A + R_B + R_C**
312+
Once all **R<span className="text-xs align-sub">i</span>** values are shared, they compute the aggregated nonce:
313+
**R<span className="text-xs align-sub">agg</span> = R<span className="text-xs align-sub">A</span> + R<span className="text-xs align-sub">B</span> + R<span className="text-xs align-sub">C</span>**
243314

244315
---
245316

@@ -333,7 +404,9 @@ print("Success!")
333404

334405
After computing the **aggregate public key** (`P_agg`) and **aggregate nonce** (`R_agg`), each participant calculates their **partial signature**:
335406

336-
`s_i = k_i + H(x(R_agg) | P_agg | m) * d_i`
407+
<div className="text-center my-4 text-orange-500">
408+
$$\mathbf{s_i = k_i + H(x(R_{agg}) | P_{agg} | m) \times d_i}$$
409+
</div>
337410

338411
Where:
339412

@@ -351,7 +424,9 @@ Participants exchange their `s_i` values, and the **aggregate signature** is com
351424

352425
This simplifies to:
353426

354-
`s_agg = k_agg + H(x(R_agg) | P_agg | m) * d_agg`
427+
<div className="text-center my-4 text-orange-500">
428+
$$\mathbf{s_{agg} = k_{agg} + H(x(R_{agg}) | P_{agg} | m) \times d_{agg}}$$
429+
</div>
355430

356431
Where:
357432

@@ -364,9 +439,9 @@ Where:
364439

365440
The final aggregate signature is:
366441

367-
`(R_agg, s_agg)`
442+
`(R<span className="text-xs align-sub">agg</span>, s<span className="text-xs align-sub">agg</span>)`
368443

369-
This pair can be verified using `P_agg` and the message `m`.
444+
This pair can be verified using `P<span className="text-xs align-sub">agg</span>` and the message `m`.
370445

371446
---
372447

92.2 KB
Binary file not shown.
73 KB
Binary file not shown.
60.9 KB
Binary file not shown.
82 KB
Binary file not shown.
600 KB
Binary file not shown.

0 commit comments

Comments
 (0)