mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-02 13:53:07 +00:00
a quick web-based witness visualizer
This commit is contained in:
parent
b233c55be6
commit
ac1006102a
10
tooling/README.md
Normal file
10
tooling/README.md
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
Plonky2 external tooling
|
||||
------------------------
|
||||
|
||||
Some experimental tooling to visualize, analyze and debug Plonky2 circuits.
|
||||
|
||||
For example using `prove_with_options` you can export the witness and visualize
|
||||
it with html/javascript.
|
||||
|
||||
|
||||
20
tooling/web/README.md
Normal file
20
tooling/web/README.md
Normal file
@ -0,0 +1,20 @@
|
||||
|
||||
Web based witness visualization
|
||||
-------------------------------
|
||||
|
||||
### Quickstart
|
||||
|
||||
With `node.js`:
|
||||
|
||||
$ npx http-server
|
||||
$ open http://127.0.0.1:8080
|
||||
|
||||
Or with `python3`:
|
||||
|
||||
$ python3 -m http.server
|
||||
$ open http://127.0.0.1:8000
|
||||
|
||||
### Caching
|
||||
|
||||
As web-browser like to cache stuff, for now just use `ctrl-shift-r`
|
||||
(or `cmd-shift-r` on mac) to reload the page after changes.
|
||||
1
tooling/web/fibonacci_witness.json
Normal file
1
tooling/web/fibonacci_witness.json
Normal file
File diff suppressed because one or more lines are too long
76
tooling/web/index.html
Normal file
76
tooling/web/index.html
Normal file
@ -0,0 +1,76 @@
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>witness visualizer</title>
|
||||
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
||||
<meta http-equiv="Pragma" content="no-cache" />
|
||||
<meta http-equiv="Expires" content="0" />
|
||||
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
<script language="javascript" src="witness_view.js"></script>
|
||||
<script language="javascript">
|
||||
window.onload = function() {
|
||||
console.log("onload!");
|
||||
load_witness("fibonacci_witness.json");
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h2>Plonky2 witness visualizer</h2>
|
||||
|
||||
<div>
|
||||
file name: <input id="fname" type="text" placeholder="witness.json" disabled=true/>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
<div id="top-container">
|
||||
<div id="left">
|
||||
<table id="gates">
|
||||
<tr>
|
||||
<th>index</th>
|
||||
<th width="200px">gate type</th>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div id="middle">
|
||||
|
||||
</div>
|
||||
<div id="right">
|
||||
<table id="cell-properties">
|
||||
<tr><th>property</th><th width="200px">value (hover!)</th></tr>
|
||||
<tr><td>row </td><td id="cell-row" ></td></tr>
|
||||
<tr><td>column </td><td id="cell-column"></td></tr>
|
||||
<tr><td>value </td><td id="cell-value" ></td></tr>
|
||||
<tr><td>gate </td><td id="cell-gate" ></td></tr>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
<svg id="matrix" width="1350" height="1000" xmlns="http://www.w3.org/2000/svg">
|
||||
</svg>
|
||||
|
||||
<!--
|
||||
<svg width="320" height="130" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="50" height="50" x="20" y="20" style="fill:rgb(128,128,255);stroke-width:1;stroke:black" />
|
||||
<rect width="50" height="50" x="70" y="20" style="fill:rgb(128,255,128);stroke-width:1;stroke:black" />
|
||||
<rect width="50" height="50" x="20" y="70" style="fill:rgb(255,128,128);stroke-width:1;stroke:black" />
|
||||
<rect width="50" height="50" x="70" y="70" style="fill:rgb(255,255,128);stroke-width:1;stroke:black" />
|
||||
</svg>
|
||||
-->
|
||||
|
||||
<br/>
|
||||
|
||||
<div>
|
||||
ratio of non-empty cells: <input id="nonempty-ratio" type="text" placeholder="100" disabled=true/>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
17
tooling/web/styles.css
Normal file
17
tooling/web/styles.css
Normal file
@ -0,0 +1,17 @@
|
||||
table, th, td {
|
||||
border-collapse: collapse;
|
||||
border: 2px solid black;
|
||||
font-family: sans-serif;
|
||||
font-size: 0.8rem;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
th, td {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
#left, #middle, #right {
|
||||
display: inline-block;
|
||||
*display: inline;
|
||||
vertical-align: top;
|
||||
}
|
||||
166
tooling/web/witness_view.js
Normal file
166
tooling/web/witness_view.js
Normal file
@ -0,0 +1,166 @@
|
||||
|
||||
const the_supported_gates =
|
||||
[ "UnknownGate"
|
||||
, "ArithmeticGate"
|
||||
, "ArithmeticExtensionGate"
|
||||
, "BaseSumGate"
|
||||
, "ConstantGate"
|
||||
, "CosetInterpolationGate"
|
||||
, "ExponentiationGate"
|
||||
, "LookupGate"
|
||||
, "LookupTableGate"
|
||||
, "MultiplicationExtensionGate"
|
||||
, "NoopGate"
|
||||
, "PoseidonGate"
|
||||
, "PoseidonMdsGate"
|
||||
, "PublicInputGate"
|
||||
, "RandomAccessGate"
|
||||
, "ReducingGate"
|
||||
, "ReducingExtensionGate"
|
||||
];
|
||||
|
||||
const the_gate_colors =
|
||||
[ "#800000" // UnknownGate -> dark red
|
||||
, "#c0c0c0" // ArithmeticGate -> light grey
|
||||
, "#808080" // ArithmeticExtensionGate -> medium grey
|
||||
, "#60c0c0" // BaseSumGate -> medium cyan
|
||||
, "#f0f080" // ConstantGate -> yellow
|
||||
, "#b0b0f0" // CosetInterpolationGate -> light blue
|
||||
, "#80f080" // ExponentiationGate -> cyan
|
||||
, "#80f080" // LookupGate -> light green
|
||||
, "#60c060" // LookupTableGate -> medium green
|
||||
, "#8080c0" // MultiplicationExtensionGate -> dark blue
|
||||
, "#ffffff" // NoopGate -> white
|
||||
, "#f07070" // PoseidonGate -> light red
|
||||
, "#c06060" // PoseidonMdsGate -> medium red
|
||||
, "#a0ffa0" // PublicInputGate -> ligth green
|
||||
, "#8080f0" // RandomAccessGate -> blue
|
||||
, "#f080f0" // ReducingGate -> light purple
|
||||
, "#c060c0" // ReducingExtensionGate -> medium purple
|
||||
];
|
||||
|
||||
function findGateIndex(gate) {
|
||||
let k = the_supported_gates.indexOf(gate);
|
||||
return ((k<0) ? 0 : k);
|
||||
}
|
||||
|
||||
function add_table_row(table, idx, text, color) {
|
||||
let tr = document.createElement("tr");
|
||||
tr.style.background = (color)?color:"#fffff";
|
||||
|
||||
let td1 = document.createElement("td"); td1.innerHTML = idx.toString();
|
||||
let td2 = document.createElement("td"); td2.innerHTML = text;
|
||||
|
||||
tr.appendChild(td1);
|
||||
tr.appendChild(td2);
|
||||
table.appendChild(tr);
|
||||
}
|
||||
|
||||
/*
|
||||
function test_fill_gates() {
|
||||
let el = document.getElementById("gates");
|
||||
for(let i=0; i<the_supported_gates.length; i++) {
|
||||
add_table_row(el, the_supported_gates[i], the_gate_colors[i]);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
var gates;
|
||||
var matrix;
|
||||
var selectors;
|
||||
var ngates;
|
||||
var nrows;
|
||||
var ncolumns;
|
||||
var ncells;
|
||||
|
||||
function cell_hover(row,column) {
|
||||
let el_row = document.getElementById("cell-row" );
|
||||
let el_col = document.getElementById("cell-column");
|
||||
let el_val = document.getElementById("cell-value" );
|
||||
let el_gate = document.getElementById("cell-gate" );
|
||||
el_row.innerHTML = row.toString();
|
||||
el_col.innerHTML = column.toString();
|
||||
el_val.innerHTML = matrix[column][row].toString();
|
||||
el_gate.innerHTML = gates[selectors[row]];
|
||||
}
|
||||
|
||||
function initialize_from_witness(fname,json) {
|
||||
//console.log(json);
|
||||
|
||||
let el_fname = document.getElementById("fname");
|
||||
el_fname.value = fname;
|
||||
|
||||
// these are global variables!
|
||||
gates = json.gates;
|
||||
matrix = json.matrix;
|
||||
selectors = json.selector_vector;
|
||||
ngates = gates.length;
|
||||
nrows = selectors.length;
|
||||
ncolumns = matrix.length
|
||||
ncells = ncolumns * nrows;
|
||||
|
||||
let gates_base = [];
|
||||
let gate_colors = [];
|
||||
|
||||
for(let i=0; i<gates.length; i++) {
|
||||
let full = gates[i];
|
||||
let base = full.split(":")[0];
|
||||
gates_base[i] = base;
|
||||
|
||||
k = findGateIndex(base);
|
||||
gate_colors[i] = the_gate_colors[k];
|
||||
|
||||
}
|
||||
|
||||
let el_table = document.getElementById("gates");
|
||||
for(let i=0; i<ngates; i++) {
|
||||
add_table_row(el_table, i, gates[i], gate_colors[i]);
|
||||
}
|
||||
|
||||
let el_svg = document.getElementById("matrix");
|
||||
el_svg.setAttribute('width' , 10*ncolumns);
|
||||
el_svg.setAttribute('height' , 10*nrows );
|
||||
|
||||
let empty_counter = 0;
|
||||
for(let j=0; j<ncolumns; j++) {
|
||||
let column = matrix[j];
|
||||
for(let i=0; i<nrows; i++) {
|
||||
let sel = selectors[i];
|
||||
let col = gate_colors[sel];
|
||||
let val = column[i];
|
||||
|
||||
if (val == 0) {
|
||||
col = "#000";
|
||||
empty_counter ++;
|
||||
}
|
||||
|
||||
// <rect width="10" height="10" x="20" y="20" style="fill:rgb(128,128,255);stroke-width:1;stroke:black" />
|
||||
let cell = document.createElementNS("http://www.w3.org/2000/svg", "rect");
|
||||
cell.setAttribute('width' ,10);
|
||||
cell.setAttribute('height',10);
|
||||
cell.setAttribute('x',10*j);
|
||||
cell.setAttribute('y',10*i);
|
||||
cell.setAttribute('style',"stroke-width:1;stroke:black;");
|
||||
cell.setAttribute('fill',col);
|
||||
let hover_call = "cell_hover(" + i.toString() + "," + j.toString() + ")";
|
||||
cell.setAttribute('onmouseover', hover_call );
|
||||
el_svg.appendChild(cell);
|
||||
}
|
||||
}
|
||||
|
||||
el_ratio = document.getElementById("nonempty-ratio");
|
||||
let ratio = Math.round( 100 * (ncells - empty_counter) / ncells);
|
||||
el_ratio.value = ratio.toString() + "%";
|
||||
}
|
||||
|
||||
function handle_error(res) {
|
||||
if (!res.ok) {
|
||||
throw new Error(`HTTP error! Status: ${res.status}`);
|
||||
}
|
||||
return res.json();
|
||||
}
|
||||
|
||||
function load_witness(fname) {
|
||||
fetch(fname).then( err => handle_error(err) ).then( data => initialize_from_witness(fname,data) ).catch();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user