MProve+
Privacy Enhancing Proof of Reserves for Monero
A. Dutta†, Suyash Bagad⋆, S. Vijayakumaran†
†Department of Electrical Engineering, IIT Bombay
Monero Konferenco 2023
June 23, 2023
⋆Aztec Protocol
Exchanges
- Not your key, not your coins!
- Cryptocurrency exchanges store your private keys
- Good: Seamless onboarding, trading
- Bad: Hacks, frauds, exit scams, fractional reserves!





Solutions
- Hardware wallets
- Hard to use for general masses
- Credit cards as HW wallets? Long way to go
- Proof of solvency for exchanges:
- Sensitive exchange data revealed
- Still possible for public blockchains
- What about Monero?
- Hint: CAssets⋅C−Liabilities>1
Assets−Liabilities≥0
\textcolor{lightgreen}{\text{Assets}} - \textcolor{red}{\text{Liabilities}} \ge 0

BNB
USDC
BUSD
BTC
ETH
USDT

Challenges in
- Proof of reserves with privacy is hard
- A Monero tx hides the spending address using ring signatures

- For a public key P=xG, we define key-image: I=xH(P)
- A ring signature σ over {P1,P2,…,P11} proves:
- The tx sender owns one of the public keys in the ring
- The key image I helps detect double-spending
- Idea: Prove that we own multiple UTXOs from a large set of keys
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
MProve
Pown
\mathcal{P}_{\text{own}}
- Suppose the exchange owns five addresses on Monero
- It chooses an anonymity set to hide its addresses
MProve
Panon
\mathcal{P}_{\text{anon}}
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
12
12
11
11
13
13
- Suppose the exchange owns five addresses on Monero
- It chooses an anonymity set to hide its addresses
Ci=gyi⋅hai
C_i = g^{\textcolor{orange}{y_i}} \cdot h^{\textcolor{red}{a_i}}
Ci′={gzigzi⋅CiPi∈PownPi∈/Pown
C'_i =
\begin{cases}
g^{\textcolor{orange}{z_i}} & P_i\in\mathcal{P}_{\text{own}} \\
g^{\textcolor{orange}{z_i}} \cdot C_i & P_i\notin\mathcal{P}_{\text{own}}
\end{cases}
- For each address Pi∈Panon, the commitment is:
- For each address it owns Pi∈Pown, it knows (yi,ai)
- It computes modified commitment s.t. zi←F
MProve
Panon
\mathcal{P}_{\text{anon}}
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
12
12
11
11
13
13
Ci=gyi⋅hai
C_i = g^{\textcolor{orange}{y_i}} \cdot h^{\textcolor{red}{a_i}}
Ci′={gzigzi⋅CiPi∈PownPi∈/Pown
C'_i =
\begin{cases}
g^{\textcolor{orange}{z_i}} & P_i\in\mathcal{P}_{\text{own}} \\
g^{\textcolor{orange}{z_i}} \cdot C_i & P_i\notin\mathcal{P}_{\text{own}}
\end{cases}
Ci⋅Ci′−1={gyi−zi⋅haigziPi∈PownPi∈/Pown
C_i\cdot C_i^{'-1} =
\begin{cases}
g^{\textcolor{orange}{y_i - z_i}} \cdot h^{\textcolor{red}{a_i}} & P_i\in\mathcal{P}_{\text{own}} \\
g^{\textcolor{orange}{z_i}} & P_i\notin\mathcal{P}_{\text{own}}
\end{cases}
// commitment to amount ai
// commitment to amount 0
∏i∈[n]Ci⋅Ci′−1=g…⋅h∑jaj
\prod_{i\in [n]} C_i\cdot C_i^{'-1} = g^{\textcolor{orange}{\dots}} \cdot h^{\textcolor{red}{\sum_j a_j}}
// commitment to total reserves ∑jaj
- We still need to prove that Ci′ was correctly computed
MProve
Panon
\mathcal{P}_{\text{anon}}
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
12
12
11
11
13
13
Ci′={gzigzi⋅CiPi∈PownPi∈/Pown
C'_i =
\begin{cases}
g^{\textcolor{orange}{z_i}} & P_i\in\mathcal{P}_{\text{own}} \\
g^{\textcolor{orange}{z_i}} \cdot C_i & P_i\notin\mathcal{P}_{\text{own}}
\end{cases}
⟹keypair:(zi, Ci′)
\implies \text{keypair:} \left(\textcolor{orange}{z_i}, \ C'_i\right)
⟹keypair:(zi, Ci′Ci−1)
\implies \text{keypair:} \left(\textcolor{orange}{z_i}, \ C'_iC^{-1}_i\right)
- Thus, we can compute a ring signature such that:
γi←(Ci′, Ci′⋅Ci−1)
\gamma_i \leftarrow \left(\textcolor{lightgreen}{C'_i}, \ \ \textcolor{orange}{C'_i \cdot C_i^{-1}}\right)
- Still need to prove that already-spent addresses were not used
σi←(Pi, Ci′⋅Ci−1)
\sigma_i \leftarrow \left(\textcolor{lightgreen}{P_i}, \ \ \textcolor{orange}{C'_i\cdot C_i^{-1}}\right)
// regular ring signature
// linkable ring signature
Drawbacks of MProve
- Scales linearly in the size n of the anonymity set
- Adds limits on the size of the anonymity set
- The linkable ring signatures reveal the key image I⋆ of Pi∈Pown
- A future transaction from Pi will reveal the same key image I⋆
- Harms privacy of the exchange in the future
MProve+
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
12
12
11
11
13
13
0
0
1
1
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
(
(
)
)
e1=
\textbf{e}_1 =
0
0
0
0
0
0
0
0
0
0
1
1
0
0
0
0
0
0
0
0
0
0
0
0
0
0
(
(
)
)
e2=
\textbf{e}_2 =
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
1
1
0
0
0
0
0
0
0
0
(
(
)
)
e3=
\textbf{e}_3 =
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
1
1
0
0
0
0
0
0
(
(
)
)
e4=
\textbf{e}_4 =
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
1
1
(
(
)
)
e5=
\textbf{e}_5 =
y1
y_1
y2
y_2
y3
y_3
y4
y_4
y5
y_5
(
(
)
)
y=
\textbf{y} =
a1
a_1
a2
a_2
a3
a_3
a4
a_4
a5
a_5
(
(
)
)
a=
\textbf{a} =
C1
C_1
C2
C_2
C3
C_3
C4
C_4
C5
C_5
C6
C_6
C7
C_7
C8
C_8
C9
C_9
C10
C_{10}
C11
C_{11}
C12
C_{12}
C13
C_{13}
(
(
)
)
C=
\textbf{C} =
P1
P_1
P2
P_2
P3
P_3
P4
P_4
P5
P_5
P6
P_6
P7
P_7
P8
P_8
P9
P_9
P10
P_{10}
P11
P_{11}
P12
P_{12}
P13
P_{13}
(
(
)
)
P=
\textbf{P} =
MProve+
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
12
12
11
11
13
13
0
0
1
1
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
e1
\textbf{e}_1
C1
C_1
C2
C_2
C3
C_3
C4
C_4
C5
C_5
C6
C_6
C7
C_7
C8
C_8
C9
C_9
C10
C_{10}
C11
C_{11}
C12
C_{12}
C13
C_{13}
(
(
)
)
C=
\textbf{C} =
⟹Cej=gyj⋅haj
\implies \textbf{C}^{\textbf{e}_j} = g^{\textcolor{orange}{y_j}} \cdot h^{\textcolor{red}{a_j}}
⟹Pej=gxj
\implies \textbf{P}^{\textbf{e}_j} = g^{\textcolor{orange}{x_j}}
⟹HPej=Ijxj−1
\implies \textbf{H}_P^{\textbf{e}_j} = I_j^{\textcolor{orange}{x_j^{-1}}}
- Pattern: vectorise all the relations and combine into one equation

⟹(C∘Pu∘HPu2)ej=g⟨.,.⟩h⟨.,.⟩I⟨.,.⟩
\implies \left(\textbf{C} \circ \textbf{P}^u \circ \textbf{H}_P^{u^2}\right)^{\textbf{e}_j} =
g^{\textcolor{orange}{\langle ., . \rangle}}
h^{\textcolor{red}{\langle ., . \rangle}}
\textbf{I}^{\textcolor{green}{\langle ., . \rangle}}
MProve+
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
12
12
11
11
13
13
- Pattern: vectorise all the relations and combine into one equation
⟹(C∘Pu∘HPu2)ej=g⟨.,.⟩h⟨.,.⟩I⟨.,.⟩
\implies \left(\textbf{C} \circ \textbf{P}^u \circ \textbf{H}_P^{u^2}\right)^{\textbf{e}_j} =
g^{\textcolor{orange}{\langle ., . \rangle}}
h^{\textcolor{red}{\langle ., . \rangle}}
\textbf{I}^{\textcolor{green}{\langle ., . \rangle}}
- We can then use inner product argument of the form:
PoK{(a,b)∈ZqN ∣ P=ucgahb∧c=⟨a,b⟩ }
PoK \left\{
(\textbf{a}, \textbf{b}) \in \mathbb{Z}_q^N \ | \
P = u^{c}\textbf{g}^{\textbf{a}} \textbf{h}^{\textbf{b}} \wedge c = \langle \textbf{a}, \textbf{b} \rangle \
\right\}
- Proof size in an inner product argument is O(log(N))
- MProve+ proof size ≈(n+s+log(ns)) vs MProve was ≈12n
Performance
- MProve+ proofs are ≥8x shorter that that of MProve
- MProve+ proof generation is 4−6x slower than MProve
- MProve+ proof verification is 8x faster than proof generation
n ⟶
n \ \longrightarrow
n ⟶
n \ \longrightarrow
Proof size in KB⟶
\text{Proof size in KB} \longrightarrow
Note: All plots are in log-log scale.


Time in min⟶
\text{Time in min} \longrightarrow
Future work
- MProve+ solves the key-image linkability of MProve
- MProve+ proof sizes are much smaller than MProve
- Thus, running MProve+ is possible for exchanges
- But is it practical?
- For n=50000 the it takes ≈2 hours to generate a proof using an 2.6GHz i7 computer
- Impractical to include all of UTXOs as anon set
- Our group from IIT Bombay is working on Monero proof of reserves using Nova proof system
References
- Proof of concept in Rust: https://github.com/suyash67/MProvePlus-Ristretto
-
Proof of concept in Monero source code: https://github.com/harshitgupta412/monero/blob/MProvePlus/
MProve+ Privacy Enhancing Proof of Reserves for Monero A. Dutta † , Suyash Bagad ⋆ , S. Vijayakumaran † † Department of Electrical Engineering, IIT Bombay Monero Konferenco 2023 June 23, 2023 ⋆ Aztec Protocol
MProvePlus at Monerokon 2023
By Suyash Bagad
MProvePlus at Monerokon 2023
MProve+ presentation at Monerokon 2023.
- 134