diff --git a/react/src/Verifier.js b/react/src/Verifier.js
index 4cae269..6132608 100644
--- a/react/src/Verifier.js
+++ b/react/src/Verifier.js
@@ -1,20 +1,21 @@
-import React, { useEffect, useMemo, useState } from 'react';
-import CreatableSelect from 'react-select/creatable';
-import JournalParser from './JournalParser.js';
+import React, { useEffect, useMemo, useState } from "react";
+import CreatableSelect from "react-select/creatable";
+import JournalParser from "./JournalParser.js";
-const DEFAULT_REGISTRY = 'https://risc0.verify.eqtylab.io/registry.json';
-const DEFAULT_IPFS_GATEWAY = 'https://w3s.link';
+const DEFAULT_REGISTRY = "https://risc0.verify.eqtylab.io/registry.json";
+const DEFAULT_IPFS_GATEWAY = "https://w3s.link";
const cssPrefix = "risc-zero-verifier";
export const defaultText = {
verifyButtonLabel: "Verify",
restartButtonLabel: "Restart",
- instructions: "Upload a receipt file as JSON or binary (bincode format), or paste it as JSON into the form field.",
+ instructions:
+ "Upload a receipt file as JSON or binary (bincode format), or paste it as JSON into the form field.",
fieldLabels: {
guestCodeId: "Guest code id (hex value):",
receiptFile: "Receipt (bincode format binary file or JSON):",
- receiptJson: "Receipt JSON:"
+ receiptJson: "Receipt JSON:",
},
verificationResults: {
verified: "Receipt verified.",
@@ -22,32 +23,39 @@ export const defaultText = {
},
errors: {
guestCodeIdMissing: "Please enter a guest code id.",
- receiptFileMissing: "Please provide a receipt file."
- }
-}
+ receiptFileMissing: "Please provide a receipt file.",
+ },
+};
function Verifier({
text = defaultText,
instanceNumber = 0,
enableJournalParser = false,
registryUrl = DEFAULT_REGISTRY,
- ipfsGateway = DEFAULT_IPFS_GATEWAY
+ ipfsGateway = DEFAULT_IPFS_GATEWAY,
+ onStatus = (result) => {
+ console.log(result);
+ },
}) {
const [verifier, setVerifier] = useState(null);
useEffect(() => {
(async () => {
const wasmPackage = await import("@eqty/risc-zero-verifier");
- const verifier = await wasmPackage.default
+ const verifier = await wasmPackage.default;
setVerifier(verifier);
})();
}, []);
- const [guestCodeId, setGuestCodeId] = useState('');
- const [receiptBinary, setReceiptBinary] = useState('');
- const [receiptJson, setReceiptJson] = useState('');
+ const [guestCodeId, setGuestCodeId] = useState("");
+ const [receiptBinary, setReceiptBinary] = useState("");
+ const [receiptJson, setReceiptJson] = useState("");
const [verificationResult, setVerificationResult] = useState(undefined);
+ useEffect(() => {
+ onStatus(verificationResult);
+ }, [verificationResult]);
+
const receiptJournalBytes = useMemo(() => {
try {
const journal = JSON.parse(receiptJson).journal;
@@ -71,19 +79,16 @@ function Verifier({
})();
}, [registryUrl]);
- const parsers = useMemo(() =>
- registry ? registry.parsers : [],
- [registry]
- );
+ const parsers = useMemo(() => (registry ? registry.parsers : []), [registry]);
function verifyRiscZeroReceipt(guestCodeId, receiptJson) {
if (!guestCodeId) {
return {
result: false,
- error: text.errors.guestCodeIdMissing
+ error: text.errors.guestCodeIdMissing,
};
}
-
+
try {
if (receiptBinary) {
return verifier.verify_receipt_binary(guestCodeId, receiptBinary);
@@ -92,7 +97,7 @@ function Verifier({
} else {
return {
result: false,
- error: text.errors.receiptFileMissing
+ error: text.errors.receiptFileMissing,
};
}
} catch (error) {
@@ -136,7 +141,9 @@ function Verifier({
function guestCodeIdOptions() {
return parsers.map((parser) => ({
value: parser.guestCodeId,
- label: `${shortenGuestCodeId(parser.guestCodeId)} (${parser.profile.name} ${parser.profile.version})`
+ label: `${shortenGuestCodeId(parser.guestCodeId)} (${
+ parser.profile.name
+ } ${parser.profile.version})`,
}));
}
@@ -153,39 +160,77 @@ function Verifier({
{text.instructions}
{verifier && (
-
Receipts must be generated with risc0-zkvm
rust crate version {verifier.get_risc0_version()}
.
+
+ Receipts must be generated with risc0-zkvm
rust crate
+ version {verifier.get_risc0_version()}
.
+
)}
-
+
setGuestCodeId(option ? option.value : '')}
+ onChange={(option) => setGuestCodeId(option ? option.value : "")}
isDisabled={verificationResult !== undefined}
placeholder="Select or enter a guest code id..."
formatCreateLabel={(inputValue) => `Use "${inputValue}"`}
/>
+
-
-
+
+
- {verificationResult === undefined ?
-
- :
-
- }
+ {verificationResult === undefined ? (
+
+ ) : (
+
+ )}
{verificationResult && (
-
+
- {
- verificationResult.verified === true ? text.verificationResults.verified : `${text.verificationResults.notVerified} ${verificationResult.error}`
- }
+ {verificationResult.verified === true
+ ? text.verificationResults.verified
+ : `${text.verificationResults.notVerified} ${verificationResult.error}`}
{verificationResult.verified === true && enableJournalParser && (
)}
-
)}
-
);
}
diff --git a/web/package.json b/web/package.json
index ac3515c..10dc6f8 100644
--- a/web/package.json
+++ b/web/package.json
@@ -10,6 +10,7 @@
},
"dependencies": {
"@eqty/risc-zero-verifier-react": "*",
+ "classnames": "^2.5.1",
"copy-webpack-plugin": "^12.0.2",
"css-loader": "^6.10.0",
"react": "^18.2.0",
diff --git a/web/src/App.css b/web/src/App.css
index 1f33de3..94a81a6 100644
--- a/web/src/App.css
+++ b/web/src/App.css
@@ -1,67 +1,198 @@
+@font-face {
+ font-family: "TWKLausanne";
+ src: url("./assets/fonts/TWKLausanne-300.woff2") format("woff2");
+ font-weight: 300;
+ font-style: normal;
+}
+@font-face {
+ font-family: "TWKLausanne";
+ src: url("./assets/fonts/TWKLausanne-550.woff2") format("woff2");
+ font-weight: 550;
+ font-style: normal;
+}
+@font-face {
+ font-family: "IBM Plex Mono";
+ src: url("./assets/fonts/ibm-plex-mono-latin-400-normal.woff2")
+ format("woff2");
+ font-weight: 400;
+ font-style: normal;
+}
+
+:root {
+ --failed-border: #ff6682;
+ --failed-color: #99001c;
+ --failed-bg: #ffccd5;
+ --failed-icon-bg: #99001c;
+
+ --pending-color: #994000;
+ --pending-bg: #ffe1cc;
+
+ --success-icon-bg: #178235;
+ --success-bg: #ceffdc;
+ --success-color: black;
+ --success-border: #475569;
+}
+
+body {
+ position: relative;
+ padding: 0;
+ margin: 0;
+ font-size: 16px;
+
+ font-family: "TWKLausanne", serif;
+ box-sizing: border-box;
+ background-color: #000;
+ color: white;
+}
+
+.verified-bg {
+ opacity: 0;
+ transition: opacity 0.5s;
+ z-index: -1;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: linear-gradient(237deg, #76b900 0%, #2b7e00 68.13%);
+}
+
+.all-verified .verified-bg {
+ opacity: 1;
+}
+
.App {
text-align: center;
+ background: black;
}
.risc-zero-journal-parser-journal-raw {
- width: 75%;
height: 80px;
}
-
+
.risc-zero-journal-parser-statement-markdown {
padding: 24px;
text-align: left;
}
-
.risc-zero-verifier-main {
font-family: Arial, sans-serif;
- max-width: 600px;
+ max-width: 75%;
margin: auto;
padding: 20px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
-label {
- display: block;
- margin-bottom: 5px;
- font-weight: bold;
-}
+ display: grid;
+ gap: 10px;
+ grid-template-areas:
+ /* i: intro */
+ /* g: guest id */
+ /* a: animation */
+ /* r: receipt */
+ /* b: button */
+ /* v: verified result */
+ "i i i"
+ "g a r"
+ ". b ."
+ "v v v";
+
+ label {
+ display: block;
+ margin-bottom: 5px;
+ font-weight: bold;
+ }
+
+ button {
+ display: flex;
+ padding: 8px 16px;
+ justify-content: center;
+ align-items: center;
+ cursor: pointer;
+ flex-grow: 0;
+ height: 33px;
+
+ border: 0;
+ border-radius: 0;
+
+ background: black;
+ color: white;
+ border: 1px solid white;
+ }
input[type="text"],
input[type="file"],
- textarea,
- button {
+ textarea {
width: 100%;
padding: 8px;
- border: 1px solid #ccc;
- border-radius: 4px;
+ border: 1px solid white;
+
box-sizing: border-box;
margin-bottom: 10px;
cursor: pointer;
}
+ input:disabled {
+ color: white;
+ }
+ textarea {
+ border: 2px solid var(--success-border);
+ }
}
-
.risc-zero-verifier-instructions-container {
- background-color: lightblue;
- margin-bottom: 20px;
- border-radius: 4px;
- border: 1px solid #ccc;
- p {
- padding: 0px 20px;
+ grid-area: i;
+}
+.risc-zero-verifier-guest-code-id-container {
+ grid-area: g;
+ color: black;
+ label {
+ color: white;
}
}
+.risc-zero-verifier-verification-animation-container {
+ grid-area: a;
+ display: grid;
+ place-items: center;
+}
+.risc-zero-verifier-verification-animation {
+ width: 80px;
+ height: 80px;
+ border-radius: 100px;
+ background-repeat: no-repeat;
+ background-position: center;
+}
+
+.App.is-verified .risc-zero-verifier-verification-animation {
+ background-color: var(--success-icon-bg);
+ background-image: url('data:image/svg+xml,');
+}
+.App.is-unverified .risc-zero-verifier-verification-animation {
+ background-color: var(--failed-icon-bg);
+ background-image: url('data:image/svg+xml,');
+}
+
+.risc-zero-verifier-receipt-file-input-container {
+ grid-area: r;
+}
+.risc-zero-verifier-verify-button-container {
+ grid-area: b;
+ display: grid;
+ place-items: center;
+ padding-top: 20px;
+ padding-bottom: 20px;
+}
+.risc-zero-verifier-receipt-verification-result {
+ grid-area: v;
+}
+
+.risc-zero-verifier-instructions-container {
+ margin-bottom: 50px;
+ border: 1px solid white;
+ padding: 0px 20px;
+}
.risc-zero-verifier-guest-code-id-container,
.risc-zero-verifier-guest-code-id-select-container,
-.risc-zero-verifier-receipt-input-container,
-.risc-zero-verifier-verify-button-container {
- margin-bottom: 20px;
- .risc-zero-verifier-verify-button {
- background-color: #4CAF50;
- color: white;
- }
- .risc-zero-verifier-verify-button button:hover {
- background-color: #45a049;
- }
+.risc-zero-verifier-receipt-input-container {
+ margin-bottom: 40px;
}
.risc-zero-verifier-receipt-json-input-container textarea {
@@ -77,11 +208,13 @@ label {
}
.risc-zero-verifier-receipt-verification-result-verified {
- background-color: lightgreen;
+ background-color: var(--success-bg);
+ color: var(--success-color);
}
.risc-zero-verifier-receipt-verification-result-unverified {
- background-color: lightcoral;
+ background-color: var(--failed-bg);
+ color: var(--failed-color);
}
.risc-zero-verifier-receipt-verification-result-message {
@@ -89,12 +222,12 @@ label {
}
.risc-zero-journal-parser-main {
- font-family: Arial, sans-serif;
+ /* font-family: Arial, sans-serif; */
max-width: 800px;
margin: auto;
padding: 20px;
- box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
-
+ /* box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); */
+
h2 {
text-align: center;
margin-bottom: 20px;
@@ -104,10 +237,9 @@ label {
margin-bottom: 10px;
}
select {
- width: 100%;
padding: 8px;
- border: 1px solid #ccc;
- border-radius: 4px;
+ border: 1px solid white;
+ /* border-radius: 4px; */
box-sizing: border-box;
margin-bottom: 10px;
}
@@ -125,27 +257,81 @@ label {
}
.risc-zero-journal-parser-statement-markdown {
- border: 1px solid #ccc;
- border-radius: 4px;
+ border: 1px solid white;
padding: 10px;
background-color: #f9f9f9;
+
+ color: white;
+ font-family: "IBM Plex Mono", sans-serif;
+
+ font-size: 10px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: 120%;
+
+ border: 2px solid var(--success-border);
+
+ background: var(--Grey-900, #0f172a);
+ box-shadow: 2px 4px 24px 0px rgba(0, 0, 0, 0.24);
+ margin-bottom: 5px;
+ padding: 5px;
}
.risc-zero-journal-parser-journal-raw {
width: 100%;
height: 200px;
- border: 1px solid #ccc;
- border-radius: 4px;
- padding: 10px;
box-sizing: border-box;
margin-bottom: 10px;
background-color: #f9f9f9;
resize: vertical;
+ width: 100%;
+ color: white;
+ font-family: "IBM Plex Mono", sans-serif;
+
+ font-size: 10px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: 120%; /* 16.8px */
+
+ border: 2px solid var(--success-border);
+
+ /* border-radius: 10px; */
+ background: var(--Grey-900, #0f172a);
+ box-shadow: 2px 4px 24px 0px rgba(0, 0, 0, 0.24);
+ margin-bottom: 5px;
+ padding: 5px;
}
.risc-zero-journal-parser-JSONTree {
- border: 1px solid #ccc;
- border-radius: 4px;
+ border: 2px solid var(--success-border);
+ /* border-radius: 4px; */
padding: 10px;
background-color: #f9f9f9;
}
+.risc-zero-journal-parser-journal-json-container ul {
+ background: transparent;
+}
+.risc-zero-journal-parser-journal-json-container {
+}
+
+.risc-zero-journal-parser-journal-json-container > div > h3 + div {
+ font-size: 10px;
+ font-style: normal;
+ font-weight: 400;
+ text-align: left;
+
+ color: white;
+ font-family: "IBM Plex Mono", sans-serif;
+
+ border: 2px solid var(--success-border);
+
+ background: var(--Grey-900, #0f172a);
+ box-shadow: 2px 4px 24px 0px rgba(0, 0, 0, 0.24);
+ margin-bottom: 5px;
+ padding: 15px;
+
+ ul {
+ /* overwrite an inline style.... */
+ background-color: transparent !important;
+ }
+}
diff --git a/web/src/App.js b/web/src/App.js
index 1a16017..365de4b 100644
--- a/web/src/App.js
+++ b/web/src/App.js
@@ -1,21 +1,56 @@
-import React, { useState } from 'react';
-import './App.css';
+import React, { useState } from "react";
+import "./App.css";
import { Verifier } from "@eqty/risc-zero-verifier-react";
+import cx from "classnames";
+
+const VERIFICATION = {
+ NONE: "none",
+ VERIFIED: "verified",
+ UNVERIFIED: "un-verified",
+};
function App() {
+ const [isVerified, setIsVerified] = useState(VERIFICATION.NONE);
+ const onVerifierStatus = (result) => {
+ if (result) {
+ console.log("🚀 ~ onVerifierStatus ~ result:", result.verified);
+
+ setIsVerified(
+ result.verified ? VERIFICATION.VERIFIED : VERIFICATION.UNVERIFIED
+ );
+ }
+ };
+
+ const classList = cx("App", {
+ "is-verified": isVerified === VERIFICATION.VERIFIED,
+ "is-unverified": isVerified === VERIFICATION.UNVERIFIED,
+ });
+
return (
-
+
RISC Zero Verifier
-
This is a verifier for RISC Zero zkVM execution receipts.
+
+ This is a verifier for{" "}
+ RISC Zero zkVM{" "}
+ execution receipts.
+
);
diff --git a/web/src/assets/fonts/TWKLausanne-300.woff2 b/web/src/assets/fonts/TWKLausanne-300.woff2
new file mode 100644
index 0000000..b1ab539
Binary files /dev/null and b/web/src/assets/fonts/TWKLausanne-300.woff2 differ
diff --git a/web/src/assets/fonts/TWKLausanne-550.woff2 b/web/src/assets/fonts/TWKLausanne-550.woff2
new file mode 100644
index 0000000..3a671c2
Binary files /dev/null and b/web/src/assets/fonts/TWKLausanne-550.woff2 differ
diff --git a/web/src/assets/fonts/ibm-plex-mono-latin-400-normal.woff2 b/web/src/assets/fonts/ibm-plex-mono-latin-400-normal.woff2
new file mode 100644
index 0000000..a6c77d6
Binary files /dev/null and b/web/src/assets/fonts/ibm-plex-mono-latin-400-normal.woff2 differ
diff --git a/yarn.lock b/yarn.lock
index 6cd6175..5955839 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2762,6 +2762,11 @@ class-utils@^0.3.5:
isobject "^3.0.0"
static-extend "^0.1.1"
+classnames@^2.5.1:
+ version "2.5.1"
+ resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b"
+ integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==
+
clean-css@^5.2.2:
version "5.3.3"
resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.3.3.tgz#b330653cd3bd6b75009cc25c714cae7b93351ccd"