arnaucube
arnaucube/ethdos-foldPublic Self-hosted repository
add html frontend to run it in the browser
arnaucube git@arnaucube.com
Sat, 28 Dec 2024 13:07:47 +0100
commit

f72c480df94651ce49fcd5f56a232fd112a7541c

parent

8d11ef2fcb7fe06ed03649998954b5366093bff0

4 files changed, 222 insertions(+), 2 deletions(-)

jump to
M README.md → README.md

@@ -1,7 +1,13 @@

# ethdos-fold +Follows the ideas of ETHdos (https://ethdos.xyz/blog), but using folding schemes. +It uses <a target="_blank" href="https://github.com/privacy-scaling-explorations/sonobe">Sonobe</a> under the hood, compiled to WASM. +## Usage - run native tests: `cargo test --release -- --nocapture` - build wasm: `wasm-pack build --target web` - serve the web: `python -m http.server 8080` - go to http://127.0.0.1:8080/index.html + +## Acknowledgements +Thanks to Michael Chu for proposing to build this prototype. This repo uses [Sonobe](https://github.com/privacy-scaling-explorations/sonobe), which relies on [arkworks-rs](https://github.com/arkworks-rs), and for the BabyJubJub EdDSA it uses [kilic/arkeddsa](https://github.com/kilic/arkeddsa).
A index.html

@@ -0,0 +1,202 @@

+<!doctype html> +<html lang="en-US" class="h-100"> + <head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <title>ETHdos fold</title> + + <!-- Bootstrap CSS --> + <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"> + + <style> + body { + background-color: #1a1a1a; + color: #d4d4d4; + } + + .btn-primary { + background-color: #6f42c1; + border-color: #6f42c1; + } + .btn-primary:hover, .btn-primary:focus { + background-color: #5a32a3; + border-color: #5a32a3; + } + .btn-primary:active { + background-color: #4a2785 !important; + border-color: #4a2785 !important; + } + + #console-out { + font-family: monospace; + font-size:75%; + padding: 10px; + background-color: #2d2d2d; + color: #d4d4d4; + border-radius: 5px; + overflow: scroll; + height: 70vh; + } + #console-out p { margin:0px;} + #console-out .log { color: #d4d4d4; } + #console-out .warn { color: #ffa500; } + #console-out .error { color: #ff6b6b; } + #console-out .info { color: #4fc3f7; } + + textarea { + background-color: #2d2d2d; + color: #d4d4d4; + border: 1px solid #444; + margin-top:5px; + } + + .box { + padding-top: 10px; + border: 1px solid #2d2d2d; + border-radius: 5px; + } + a { + color: #6f42c1; + } + </style> + </head> + <body class="container"> + <a target="_blank" href="https://github.com/arnaucube/ethdos-fold" class="github-corner" aria-label="View source on GitHub"><svg width="80" height="80" viewBox="0 0 250 250" style="fill:#fff; color:#151513; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style> + + <div class="container py-5"> + <div class="row"> + <div class="col-md-1"> + </div> + <div class="col-md-6 box"> + <h2 class="text-center mb-4">ETHdos fold</h2> + <p>Follows the ideas of ETHdos (<a target="_blank" href="https://ethdos.xyz/blog">https://ethdos.xyz/blog</a>), but using Folding Schemes.</p> + <p style="font-size:90%;">It uses <a target="_blank" href="https://github.com/privacy-scaling-explorations/sonobe">Sonobe</a> under the hood, compiled to WASM.</a> + <p style="font-style:italic;font-size:80%;"> + Current version does not parallelize in wasm. Same execution can be run natively (no wasm), instructions <a target="_blank" href="https://github.com/arnaucube/ethdos-fold">in the repo</a>.<br> + In the same laptop, natively takes ~290ms per step, in-browser takes ~1700ms per step. + </p> + + <button id="btn_gen_params" class="btn btn-primary">1. gen_params</button> + + <div class="mb-3"> + <!-- <label for="params" class="form-label">params:</label> --> + <textarea id="params" class="form-control" rows="3">params</textarea> + </div> + + <div class="mb-3"> + <button id="btn_gen_sigs" class="btn btn-primary">2. gen_sigs</button><br> + <!-- <label for="sigs" class="form-label">sigs and pks:</label> --> + <textarea id="sigs" class="form-control" rows="3">sigs and pks</textarea> + </div> + + <div class="mb-3"> + <button id="btn_fold_sigs" class="btn btn-primary">3. fold_sigs</button><br> + <!-- <label for="ivc_proof" class="form-label">ivc proof:</label> --> + <textarea id="ivc_proof" class="form-control" rows="3">ivc proof</textarea> + </div> + <button id="btn_verify_proof" class="btn btn-primary">4. verify_proof</button> + + </div> + <div class="col-md-4"> + logs: + <span id="spinner"></span> + <p style="font-style:italic;">(Open the browser console to see the execution logs)</p> + <div id="console-out" class="mt-4"> + (logs will appear after the execution of each button ends) + </div> + </div> + </div> + </div> + + <!-- Bootstrap JS --> + <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> + + <script type="module"> + import init, { gen_params, gen_sigs, fold_sigs, verify_proof } from "./pkg/ethdos_fold.js"; + + const n_sigs = 5; + + await init(); + console.log("ready"); + + document.getElementById('btn_gen_params').addEventListener('click', () => { + spinner_on(); + setTimeout(() => { + let params = gen_params(); + document.getElementById("params").innerHTML = JSON.stringify(params); + console.info("folding scheme params generated"); + spinner_off(); + }, 500); + }); + document.getElementById('btn_gen_sigs').addEventListener('click', () => { + spinner_on(); + let sigs = gen_sigs(n_sigs); + setTimeout(() => { + document.getElementById("sigs").innerHTML = JSON.stringify(sigs); + spinner_off(); + console.info(`${n_sigs} signatures generated`); + }, 500); + }); + document.getElementById('btn_fold_sigs').addEventListener('click', () => { + spinner_on(); + setTimeout(() => { + let params = JSON.parse(document.getElementById("params").innerHTML); + let sigs = JSON.parse(document.getElementById("sigs").innerHTML); + let ivc_proof = fold_sigs(params, sigs); + document.getElementById("ivc_proof").innerHTML = JSON.stringify(ivc_proof); + console.info(`ivc_proof generated, proving distance of ${n_sigs} degrees (${n_sigs} recursive proofs) from the initial public key`); + spinner_off(); + }, 500); + }); + document.getElementById('btn_verify_proof').addEventListener('click', () => { + spinner_on(); + setTimeout(() => { + let params = JSON.parse(document.getElementById("params").innerHTML); + let ivc_proof = JSON.parse(document.getElementById("ivc_proof").innerHTML); + let v = verify_proof(params[0], ivc_proof); + console.info("verification result:"); + console.info(v); + spinner_off(); + }, 500); + }); + + + var oldLog = console.log; + var oldWarn = console.warn; + var oldError = console.error; + var oldInfo = console.info; + var outputDiv = document.getElementById('console-out'); + + function appendToDOM(message, type) { + var p = document.createElement('p'); + p.textContent = "> " + message; + p.className = type; + outputDiv.appendChild(p); + outputDiv.scrollTop = outputDiv.scrollHeight; + } + console.log = function(message) { + oldLog.apply(console, arguments); + appendToDOM(message, 'log'); + }; + console.warn = function(message) { + oldWarn.apply(console, arguments); + appendToDOM(message, 'warn'); + }; + console.error = function(message) { + oldError.apply(console, arguments); + appendToDOM(message, 'error'); + }; + console.info = function(message) { + oldInfo.apply(console, arguments); + appendToDOM(message, 'info'); + }; + + function spinner_on() { + document.getElementById("spinner").className="spinner-border"; + } + function spinner_off() { + document.getElementById("spinner").className="spinner-border d-none"; + } + </script> + </body> +</html>
M src/lib.rs → src/lib.rs

@@ -79,6 +79,15 @@ "Nova prover params serialized: {:?}ms",

elapsed(start) )); + dbg(format!( + "prover_params size: {} mb", + prover_params_serialized.len() / (1024 * 1024) + )); + dbg(format!( + "verifier_params size: {} mb", + verifier_params_serialized.len() / (1024 * 1024) + )); + vec![ b64.encode(&prover_params_serialized), b64.encode(&prover_params_serialized),

@@ -98,7 +107,6 @@

#[wasm_bindgen] pub fn fold_sigs(params: Vec<String>, sigs_pks: Vec<String>) -> String { dbg("starting fold_sigs (rust)".to_string()); - dbg(format!("received sigs: {:?}", sigs_pks)); let poseidon_config = poseidon_canonical_config::<Fr>();

@@ -164,6 +172,10 @@ let mut ivc_proof_bytes = vec![];

ivc_proof .serialize_compressed(&mut ivc_proof_bytes) .unwrap(); + dbg(format!( + "ivc_proof size: {} mb", + ivc_proof_bytes.len() / (1024 * 1024) + )); b64.encode(ivc_proof_bytes) }
M src/utils.rs → src/utils.rs

@@ -48,7 +48,7 @@ }

#[cfg(target_arch = "wasm32")] fn get_wasm_time() -> u64 { - use web_sys::{window, Performance}; + use web_sys::window; let window = window().expect("should have a window in this context"); let performance = window .performance()