arnaucube.com/index.html
index.htmlRaw
1<!doctype html>
2
3<html lang="en">
4
5<head>
6 <meta charset="utf-8">
7 <meta name="viewport" content="width=device-width, initial-scale=1">
8
9 <title>arnaucube</title>
10 <meta name="description" content="arnaucube, arnaucube software developer">
11 <meta name="keyword" content="arnaucube, arnaucode, arnau, cube, software, developer, portfolio, computer, science, electronics, telecomunications, engineer">
12 <link rel="icon" type="image/png" href="img/logoArnauCubeFavicon.png">
13
14 <style>
15 :root {
16 --bg: #ffffff;
17 --text: #1d3557;
18 --muted: #58708e;
19 --link: #4d9aa1;
20 --code: #4d9aa1;
21 --card: #ffffff;
22 }
23 body.dark-theme {
24 --bg: #0f0f10;
25 --text: #e9e9ea;
26 --muted: #a9a9ad;
27 --link: #4d9aa1;
28 --code: #4d9aa1;
29 --card: #0f0f10;
30 }
31 body {
32 overflow-x: hidden;
33 background: var(--bg);
34 color: var(--text);
35 font-family: "Avenir Next", "Montserrat", "Helvetica Neue", "Segoe UI", Arial, sans-serif;
36 font-size:100%;
37 margin: 0;
38 }
39
40 a,
41 a:hover,
42 a:focus,
43 a:active {
44 color: var(--link);
45 text-decoration:none;
46 }
47 ul{
48 margin-top:0px;
49 }
50 li{
51 margin-top: 5px;
52 }
53 code {
54 font-size: 130%!important;
55 color: var(--code)!important;
56 }
57 .recentwork{
58 color: var(--link)!important;
59 text-decoration: underline;
60 }
61 .gray{
62 color: var(--muted);
63 }
64 h3 {
65 margin-bottom: 2px;
66 }
67 h4 {
68 margin-bottom: 2px;
69 }
70 .recent-work-box{
71 background: transparent;
72 border-radius: 0;
73 padding-left: 20px;
74 padding-right: 20px;
75 padding-bottom: 10px;
76 margin: 10px;
77 }
78 .main {
79 margin: 0 auto;
80 max-width: 760px;
81 padding: 20px;
82 }
83 .theme-toggle {
84 /*position: sticky;*/
85 top: 12px;
86 float: right;
87 z-index: 2;
88 background: var(--card);
89 color: var(--text);
90 border: 1px solid var(--muted);
91 border-radius: 999px;
92 width: 30px;
93 height: 30px;
94 font-size: 16px;
95 line-height: 1;
96 padding: 0;
97 cursor: pointer;
98 }
99 @media only screen and (min-width: 450px) {
100 .tresd{
101 z-index: -2;
102 position: absolute;
103 left:30%!important;
104 top:25%;
105 }
106 }
107 @media only screen and (max-width: 450px) {
108 .tresd{
109 z-index: -2;
110 position: absolute;
111 left:0%;
112 top:25%;
113 }
114 }
115
116
117 * {
118 box-sizing: border-box;
119 }
120 .column {
121 width: 100%;
122 padding: 0;
123 margin: 0;
124 float: none;
125 }
126 @media only screen and (max-width: 700px) {
127 .main {
128 padding: 14px;
129 }
130 }
131 </style>
132</head>
133
134<body>
135 <div class="main">
136 <button id="theme-toggle" class="theme-toggle" type="button" aria-label="Toggle theme">☀</button>
137
138 <!-- <div id="tresd" style="z-index: -2; position: absolute; top:25%;"></div> -->
139 <!-- <div id="tresd" style="z-index: -2; position: absolute; left:0%;top:25%;"></div> -->
140 <div id="tresd" class="tresd"></div>
141
142 <div style="margin-top: 0;">
143 <div class="row">
144 <div class="column">
145
146 <div style="float:left;">
147 <img src="img/logoArnauCube_transparent.png" style="max-width: 100px;margin-top:30px;" \>
148 </div>
149 <br>
150 <div style="display:inline-block;max-width:500px; margin-left:10%;">
151 <!-- <div style="float:right; max-width:500px;"> -->
152 <p><b>arnaucube</b> - cryptography engineer</p>
153 <span style="font-size:110%;">
154 <a href="/blog">blog</a>
155 <span style="margin: 10px;">|</span>
156 <a href="/blog/notes.html">notes</a>
157 <span style="margin: 10px;">|</span>
158 <a href="https://github.com/arnaucube" target="_blank">github</a>
159 <span style="font-style:italic;">(<a href="https://git.arnaucube.com/arnaucube?sort=moststars" target="_blank">git-mirror</a>)</span>
160 <span style="margin: 10px;">|</span>
161 <a href="https://twitter.com/arnaucube" target="_blank">twitter</a>
162 </span>
163 </div>
164
165 <br><br>
166 <div style="margin:30px;">
167 Cryptography engineer with experience implementing cryptography protocols (zkSNARKs, hashes, ciphers, folding schemes, zk-circuits, ...).
168 On my free time I enjoy self-studying <a target="_blank" href="/blog/notes.html">some math topics</a>.
169
170 <br><br><br>
171 Some of the projects I've enjoyed working on over these past years:<br>
172 <ul>
173 <li>
174 <i>Folding schemes</i> implementations such as Nova, HyperNova, ProtoGalaxy, CycleFold in the
175 <a href="https://github.com/privacy-ethereum/sonobe" target="_blank">Sonobe</a> library
176 </li>
177 <li>
178 Elliptic curve <i>signature schemes</i> such as
179 <a href="https://github.com/arnaucube/ring-signatures-rs" target="_blank">bLSAG ring signatures</a>
180 and <a href="https://github.com/aragonzkresearch/ark-ec-blind-signatures" target="_blank">blind signatures</a>
181 </li>
182 <li>
183 <i>Commitment schemes</i> such as
184 <a href="https://github.com/arnaucube/kzg-commitments-study" target="_blank">KZG10</a>,
185 <a href="https://github.com/arnaucube/fri-commitment" target="_blank">FRI</a>,
186 <a href="https://github.com/arnaucube/ipa-rs" target="_blank">IPA</a>
187 </li>
188 <li>
189 other <i>cryptographic primitives</i> such as
190<a href="https://github.com/arnaucube/go-snark-study" target="_blank">go-snark</a> lib,
191<a href="https://github.com/vocdoni/arbo" target="_blank">arbo</a> (CPU-parallelized MerkleTree),
192 <a href="https://github.com/arnaucube/babyjubjub-rs" target="_blank">BabyJubJub</a> elliptic curve, <a href="https://github.com/arnaucube/poseidon-rs" target="_blank">Poseidon</a> hash
193 </li>
194 <li>
195 zk <i>circuits</i> such as <a
196 href="https://github.com/vocdoni/keccak256-circom"
197 target="_blank">keccak256-circom</a>,
198<a href="https://github.com/vocdoni/zk-franchise-proof-circuit/tree/9d25884142f0018746326d5f8c3ac714fe844edd" target="_blank">census-proof</a>,
199 and plonky2's <a href="https://github.com/0xPARC/plonky2-crypto-gadgets" target="_blank">aes-gcm cipher & poseidon-cipher</a>
200 </li>
201 <li>
202 some voting system (rollup style) <i>designs & implementations</i> <a
203 href="https://github.com/aragonzkresearch/research/blob/main/ovote/ovote.pdf"
204 target="_blank">OVOTE</a> and <a
205href="https://github.com/aragonzkresearch/research/blob/main/blind-ovote/blind-ovote.pdf"
206target="_blank">Blind-OVOTE</a>.
207 </li>
208 <li>
209 <i>FHE (full-homomorphic encryption)</i> schemes such as CKKS, BFV, TFHE at <a href="https://github.com/arnaucube/fhe-study" target="_blank">fhe-study</a>.
210 </li>
211 </ul>
212 <!--
213 Interested on implementing cryptographic primitives (both rust libraries and zk circuits).
214Examples of things I've enjoyed working on these past years:
215
216- Rust libraries: various folding schemes implementations (Nova, HyperNova, ProtoGalaxy, CycleFold) (which included also implementing circuits), various commitment schemes (KZG, IPA, FRI), various signature schemes.
217- zk circuits: various elliptic curve signature schemes, keccak256 hash function in circom.
218
219Maybe a common denominator from all the above would be: deep rabbit hole to dive into, requiring math understanding together with coding knowledge; ie. take a paper - study it - implement it.
220 -->
221 </div>
222
223 <br>
224 </div>
225
226 <!-- <br><br><br> -->
227 <!-- <hr style="width:70%;"> -->
228 <!-- <br><br> -->
229
230 <div class="column" style="font-size:100%;">
231 <h2>Recent <b>Work</b>:</h2>
232
233 <div class="recent-work-box">
234 <h4 class="gray">2023 - 2026</h4>
235 <!-- 2023 -->
236 <h3 style="display:inline;"><a href="https://research.0xparc.org" target="_blank" class="recentwork">0xPARC Research</a> -</h3>
237 <i style="display:inline;">Applied cryptography research</i>
238 <br>
239 Research and implementations of folding schemes.
240 <ul>
241 <li>
242 <span class="gray">privacy-ethereum/</span><a href="https://github.com/privacy-ethereum/sonobe" target="_blank">sonobe</a>: folding schemes modular library. Implemented Nova, CycleFold, HyperNova and ProtoGalaxy. Also designed the onchain verification approach which allowed Sonobe to be the first folding schemes library to achieve verifying folding proofs in Ethereum.
243 <ul><li><a href="https://github.com/privacy-ethereum/sonobe" target="_blank">sonobe</a>, <a href="https://privacy-ethereum.github.io/sonobe-docs" target="_blank">sonobe-docs</a></li></ul>
244 </li>
245 <li>
246 <a href="https://github.com/arnaucube/protogalaxy-poc" target="_blank">protogalaxy-poc</a>: ProtoGalaxy folding scheme proof of concept implementation
247 </li>
248 <li>
249 <span class="gray">privacy-scaling-explorations/</span><a href="https://github.com/privacy-scaling-explorations/multifolding-poc" target="_blank">multifolding-poc</a>: HyperNova folding scheme proof of concept implementation
250 </li>
251 <li>
252 <span class="gray">0xPARC/</span><a href="https://github.com/0xPARC/pod2" target="_blank">pod2</a>: helped with low level primitives and related circuits such as merkletrees and recursion framework.
253 </li>
254 <li>
255 <span class="gray">0xPARC/</span><a href="https://github.com/0xPARC/plonky2-crypto-gadgets" target="_blank">plonky2-crypto-gadgets</a>: plonky2 circuits for AES-GCM encryption, Poseidon cipher.
256 </li>
257 </ul>
258 </div>
259
260 <!-- <hr style="width:40%;margin-left:0;margin-bottom:30px;margin-top:20px;"> -->
261
262 <div class="recent-work-box">
263 <h4 class="gray">2022 - 2023</h4>
264 <!-- 2022 - 2023 -->
265 <h3 style="display:inline;"><a href="https://vocdoni.io" target="_blank" class="recentwork">Vocdoni</a> & <a href="https://research.aragon.org/about/" target="_blank" class="recentwork">Aragon-ZK-Research</a> -</h3>
266 <i style="display:inline;">Decentralized governance & voting tooling.</i>
267 <br>
268 Design and implementation of voting schemes using zkSNARKs and other cryptographic schemes.
269 <!-- Design and implementation of <a href="https://docs.vocdoni.io/architecture/protocol/anonymous-voting/zk-census-proof.html#implementation-spec" target="_blank">anonymous voting solutions</a> using zkSNARKs. -->
270 <!-- Introduced <a href="https://github.com/vocdoni/protocol/discussions/23" target="_blank">some</a> design <a href="https://github.com/vocdoni/zk-franchise-proof-circuit/commit/2efeecc12669279dcf493bd9c782ba80b3c87dc8" target="_blank">optimizations</a> in the circuits which reduced the number of constraints. -->
271 <!-- <br>Also, contributed to <span class="gray">vocdoni/</span><a href="https://github.com/vocdoni/vocdoni-node/commits?author=arnaucube" target="_blank">vocdoni-node</a> adding zk related code. -->
272 <!-- <br> -->
273 <!-- Other stuff implemented: -->
274 <br>
275 <ul>
276 <li>
277 <span class="gray">vocdoni/</span><a href="https://github.com/vocdoni/keccak256-circom" target="_blank">keccak256-circom</a>: ethereum sha3 (keccak256) hash function implemented in Circom
278 </li>
279 <li>
280 <span class="gray">vocdoni/</span><a href="https://github.com/vocdoni/zk-franchise-proof-circuit" target="_blank">zk-census-proof</a>: anonymous census proof circuit used in Vocdoni's Blockchain
281 <ul>
282 <li>
283 <span class="gray">aragonzkresearch/</span><a href="https://github.com/aragonzkresearch/ark-anon-vote" target="_blank">ark-anon-vote</a>: (similar design, implemented in arkworks) onchain anonymous voting snark circuit.
284 </li>
285 </ul>
286 </li>
287 <li>
288 <span class="gray">vocdoni/</span><a href="https://github.com/vocdoni/arbo" target="_blank">arbo</a>: optimized MerkleTree which parallelizes by CPUs for faster computation, compatible with circomlib implementation
289 </li>
290 <li>
291 <span class="gray">aragonzkresearch/</span><a href="https://github.com/aragonzkresearch/ark-ec-blind-signatures" target="_blank">ark-ec-blind-signatures</a>: Blind signatures over elliptic curve implementation (native & r1cs constraints)
292 </li>
293 </ul>
294 <span style="">OVOTE</span>: Offchain Voting with Onchain Trustless Execution (kind of a validity-Rollup for voting)
295 <ul>
296 <li>
297 <a href="https://research.aragon.org/docs/ovote" target="_blank">OVOTE technical document</a>
298 </li>
299 <li>
300 <a href="https://forum.aragon.org/t/we-present-ovote-offchain-voting-with-onchain-trustless-execution/3603" target="_blank">Forum post</a> with a high level explanation.
301 </li>
302 <li>
303 <span class="gray">aragonzkresearch/</span><a href="https://github.com/aragonzkresearch/ovote" target="_blank">ovote</a>: implementation of the OVOTE circuits, smart contracts & libs
304 </li>
305 <li>
306 <span class="gray">aragonzkresearch/</span><a href="https://github.com/aragonzkresearch/ovote-node" target="_blank">ovote-node</a>: OVOTE backend node implemented in Go
307 </li>
308 </ul>
309 <span style="">Blind-OVOTE</span>: (OVOTE with Blind Signatures) L2 validity rollup combined with blind signatures over elliptic curves inside zkSNARK, to provide offchain anonymous voting with onchain binding execution on Ethereum
310 <ul>
311 <li>
312 <a href="https://research.aragon.org/docs/blind-ovote" target="_blank">Blind-OVOTE technical document</a>
313 </li>
314 <li>
315 <a href="https://forum.aragon.org/t/blind-ovote-ovote-with-blind-signatures-for-voter-anonymity/3881" target="_blank">Forum post</a> with a high level explanation.
316 </li>
317 <li>
318 <span class="gray">aragonzkresearch/</span><a href="https://github.com/aragonzkresearch/blind-ovote" target="_blank">blind-ovote</a>: Blind-OVOTE implementation in arkworks.
319 </li>
320 </ul>
321 </div>
322 <!-- <hr> -->
323 <!-- <hr style="width:40%;margin-left:0;margin-bottom:30px;margin-top:20px;"> -->
324 <div class="recent-work-box">
325 <h4 class="gray">2018 - 2022</h4>
326 <!-- 2021 - 2022 -->
327 <h3 style="display:inline;"><a href="https://hermez.io" target="_blank" class="recentwork">Hermez zkRollup</a> -</h3>
328 <i style="display:inline;"> Decentralized zkRollup on Ethereum.</i><br>
329 Main task has been to implement the Hermez node,
330 used to <a href="https://cointelegraph.com/news/hermes-network-launches-zk-rollups-on-ethereum-mainnet-to-process-cheap-payments"
331 target="_blank">launch the mainnet</a> of the zkRollup network (1.0):
332 <br><span style="margin-left:30px;"></span> <span class="gray">hermeznetwork/</span><a href="https://github.com/arnaucube/hermez-node" target="_blank">hermez-node</a>
333 <br>My focus has been mainly in the TxSelector, TxProcessor (managing
334 the rollup state tree) and BatchBuilder (generating the data
335 structure compatible with the zkSNARK circuits to do the proof generation).
336 <!-- </div> -->
337 <!-- <hr> -->
338 <!-- <hr style="width:40%;margin-left:0;margin-bottom:30px;margin-top:20px;"> -->
339 <!-- <div class="recent-work-box"> -->
340 <!-- 2018 - 2021 -->
341 <br><br>
342 <h3 style="display:inline;"><a href="https://iden3.io" target="_blank" class="recentwork">iden3</a> -</h3>
343 <i style="display:inline;"> Scalable decentralized identity system with privacy by using zero knowledge proofs.</i><br>
344 Design and specify the core protocol, develop the core libraries, servers, zk circom circuits and zkSNARK Groth16 Go prover.
345 <ul>
346 <li>
347 <span class="gray">iden3/</span><a href="https://github.com/iden3/go-iden3-crypto" target="_blank">go-iden3-crypto</a>: cryptographic primitives (SNARK-friendly) used in iden3 </li>
348 <li>
349 <span class="gray">iden3/</span><a href="https://github.com/iden3/go-iden3-core" target="_blank">go-iden3-core</a>: core implementation of the iden3 system
350 </li>
351 <li>
352 <span class="gray">iden3/</span><a href="https://github.com/iden3/go-circom-prover-verifier" target="_blank">go-circom-prover-verifier</a>: Go lang implementation of the Groth16 zkSNARK Prover and Verifier compatible with Circom
353 </li>
354 <li>
355 <span class="gray">iden3/</span><a href="https://github.com/iden3/circuits" target="_blank">circuits</a>: zkSNARK circuits used by the iden3 core protocol
356 </li>
357 </ul>
358
359</div>
360
361<div style="font-size:80%;">
362 <h2>Some other <b>free time</b> side projects:</h2>
363 <ul>
364 <li>
365 <a href="https://github.com/arnaucube/go-snark-study" target="_blank">go-snark-study</a>: <code>Go</code> zkSNARK implementation from scratch (compiler, setup, prover, verifier)
366 </li>
367 <li>
368 <a href="https://github.com/arnaucube/go-bellman-verifier" target="_blank">go-bellman-verifier</a>: <code>Go</code> Groth16 zkSNARK bellman proof verifier using cloudflare/bn256 Pairing
369 </li>
370 <li>
371 <a href="https://github.com/arnaucube/babyjubjub-rs" target="_blank">babyjubjub-rs</a>: BabyJubJub elliptic curve implementation in <code>Rust</code>
372 </li>
373 <li>
374 <a href="https://github.com/arnaucube/kzg-commitments-study" target="_blank">kzg-commitments</a>: Kate-Zaverucha-Goldberg (KZG10) Polynomial Commitments in <code>Go</code>
375 </li>
376 <li>
377 <a href="https://github.com/arnaucube/fri-commitment" target="_blank">fri-commitment</a>: FRI polynomial commitment in <code>Rust</code>
378 </li>
379 <li>
380 <a href="https://github.com/arnaucube/ipa-rs" target="_blank">ipa-rs</a>: modified Inner Product Argument (IPA) version from Halo paper in <code>Rust</code> using arkworks.
381 </li>
382 <li>
383 <a href="https://github.com/arnaucube/ring-signatures-rs" target="_blank">ring-signatures-rs</a>: bLSAG ring signatures implementation in <code>Rust</code>
384 </li>
385 <li>
386 <a href="https://github.com/arnaucube/poseidon-rs" target="_blank">poseidon-rs</a>: Poseidon hash implementation in <code>Rust</code>
387 </li>
388 <li>
389 <a href="https://github.com/arnaucube/go-blindsecp256k1" target="_blank">go-blindsecp256k1</a>: Blind signatures over secp256k1 elliptic curve in <code>Go</code> <i>(with the <a href="https://github.com/arnaucube/blindsecp256k1-js" target="_blank">compatible typescript implementation</a>)</i>
390 </li>
391 <!-- </ul> -->
392 <!-- Other: -->
393 <!-- <ul> -->
394 <!-- <li> -->
395 <!-- <a href="https://github.com/arnaucube/evm-rs" target="_blank">evm-rs</a>: Ethereum Virtual Machine in <code>Rust</code> -->
396 <!-- </li> -->
397 <!-- <li> -->
398 <!-- <a href="https://github.com/arnaucube/go-dht" target="_blank">go-dht</a>: Kademlia DHT implementation in <code>Go</code> -->
399 <!-- </li> -->
400 <li>
401 <a href="https://github.com/arnaucube/merkletree-rs" target="_blank">merkletree-rs</a>: Sparse MerkleTree implementation in <code>Rust</code> (also a <code>Go</code> impl <a href="https://github.com/arnaucube/go-merkletree" target="_blank">go-merkletree</a>)
402 </li>
403 <li>
404 <a href="https://github.com/arnaucube/shamirsecretsharing" target="_blank">shamirsecretsharing</a>: Shamir's Secret Sharing <code>Rust</code> & <code>Go</code> implementation + <code>WASM</code> lib
405 </li>
406 <!-- <li> -->
407 <!-- <a href="https://github.com/arnaucube/cryptofun" target="_blank">cryptofun</a>: Crypto algorithms from scratch, in order to get familiar with them from inside. For example: ECC, Paillier, RSA, Homomorphic computation, ElGamal, Schnorr, ECDSA, BN128, ... -->
408 <!-- </li> -->
409 <li>
410 <a href="https://github.com/arnaucube/evm-rs" target="_blank">evm-rs</a>: partial implementation of the Ethereum Virtual Machine (EVM) in <code>Rust</code>
411 </li>
412 <li>
413 <a href="https://kvartalo.github.io/website/" target="_blank">kvartalo</a>: a local social cryptocurrency for neigbourhoods, that we used in a Barcelona neighbourhood as experiment during few months. Build on top of Ethereum blockchain & Tendermint Core
414 </li>
415 <li>
416 <a href="https://github.com/arnaucube/chip8-rs" target="_blank">chip8-rs</a>: CHIP-8 virtual machine emulator written in <code>Rust</code> (also a <code>Go</code> impl <a href="https://github.com/arnaucube/go-chip8" target="_blank">go-chip8</a>)
417 </li>
418 <li>
419 <a href="https://github.com/arnaucube/fft-rs" target="_blank">fft-rs</a>: Fast Fourier Transform (FFT) implementation in <code>Rust</code>
420 </li>
421 <li>
422 <a href="https://github.com/arnaucube/miksi-core" target="_blank">miksi</a>: Ethereum zk-coin-mixer where all the computation & constructions are done offchain and then proved inside a zkSNARK to the smart-contract. <i><a href="https://arnaucube.github.io/miksi-app/" target="_blank">(live demo on testnet)</a></i>
423 </li>
424 <li>
425 <a href="https://github.com/arnaucube/eth-kzg-ceremony-alt" target="_blank">eth-kzg-ceremony-alt</a>: Alternative implementation of the contributor-client for the Ethereum KZG Trusted Setup Ceremony. I used this code to do my contribution to Ethereum's KZG ceremony.
426 </li>
427 </ul>
428
429 More projects directly in github: <a href="https://github.com/arnaucube?tab=repositories" target="_blank">https://github.com/arnaucube</a> <i>(Mirror of all the repos at: <a href="https://git.arnaucube.com/arnaucube?sort=moststars" target="_blank">https://git.arnaucube.com</a>)</i>.
430 </div>
431
432 <br><br><br>
433 <p style="padding:0;margin:0;font-size:120%;">
434 <a href="blog/index.html">blog</a>
435 <span style="margin: 10px;">|</span>
436 <a href="https://github.com/arnaucube" target="_blank">github</a>
437 <span style="font-style:italic;">(<a href="https://git.arnaucube.com/arnaucube?sort=moststars" target="_blank">git-mirror</a>)</span>
438 <span style="margin: 10px;">|</span>
439 <a href="https://twitter.com/arnaucube" target="_blank">twitter</a>
440 </p>
441 <br><br>
442 <img src="img/email.png" />
443
444
445
446
447 <!-- <hr> -->
448 <!-- <br> -->
449 </div>
450
451 </div>
452 </div>
453 </div>
454
455
456 <!-- threejs -->
457 <script src="js/three.min.js"></script>
458 <script src="js/Detector.js"></script>
459 <script src="js/tresd.min.js"></script>
460 <!-- <script src="js/tresd.js"></script> -->
461 <script>
462 const toggleButton = document.getElementById("theme-toggle");
463 let savedTheme = localStorage.getItem("theme");
464 if (savedTheme === "dark") {
465 savedTheme = "dark-theme";
466 }
467 if (savedTheme !== "dark-theme") {
468 savedTheme = "light-theme";
469 }
470 document.body.classList.remove("light-theme", "dark-theme");
471 document.body.classList.add(savedTheme);
472 toggleButton.innerHTML = savedTheme === "dark-theme" ? "☾" : "☀";
473
474 toggleButton.addEventListener("click", function () {
475 const currentTheme = localStorage.getItem("theme") === "dark-theme" ? "dark-theme" : "light-theme";
476 const nextTheme = currentTheme === "dark-theme" ? "light-theme" : "dark-theme";
477 document.body.classList.remove("light-theme", "dark-theme");
478 document.body.classList.add(nextTheme);
479 localStorage.setItem("theme", nextTheme);
480 toggleButton.innerHTML = nextTheme === "dark-theme" ? "☾" : "☀";
481 });
482
483 tresd = "cube";
484 init();
485 animate();
486 </script>
487</body>
488
489</html>