From 67cf4d02e67bd57ab2e8bc154a08f69afa330295 Mon Sep 17 00:00:00 2001 From: Nico Serrano Date: Wed, 5 Jul 2023 21:45:26 -0500 Subject: [PATCH 01/15] frontend(fix): remove console log errors --- packages/frontend/package.json | 1 + packages/frontend/public/index.html | 2 +- .../frontend/src/components/ButtonAppBar.tsx | 190 ++++++++++-------- packages/frontend/src/components/Options.tsx | 167 +++++++-------- yarn.lock | 154 +++++++++++++- 5 files changed, 347 insertions(+), 167 deletions(-) diff --git a/packages/frontend/package.json b/packages/frontend/package.json index 665973a..eaf3835 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -19,6 +19,7 @@ "@mui/material": "^5.13.5", "@mui/styled-engine": "npm:@mui/styled-engine-sc@latest", "@mui/styled-engine-sc": "^5.12.0", + "@mui/styles": "^5.13.7", "@mui/x-data-grid": "^6.8.0", "@types/material-ui": "^0.21.12", "css-minimizer-webpack-plugin": "^5.0.0", diff --git a/packages/frontend/public/index.html b/packages/frontend/public/index.html index 4dd81db..b48b16f 100644 --- a/packages/frontend/public/index.html +++ b/packages/frontend/public/index.html @@ -2,7 +2,7 @@ - + diff --git a/packages/frontend/src/components/ButtonAppBar.tsx b/packages/frontend/src/components/ButtonAppBar.tsx index bce74a7..58dc372 100644 --- a/packages/frontend/src/components/ButtonAppBar.tsx +++ b/packages/frontend/src/components/ButtonAppBar.tsx @@ -1,8 +1,18 @@ -import React, { useContext, useState } from 'react'; -import { withStyles, makeStyles, createStyles, Theme, styled } from '@mui/material/styles'; -import { AppBar, ListItemText, Menu, MenuProps, MenuItem, IconButton, Toolbar, useScrollTrigger } from '@mui/material'; -import { Menu as MenuIcon, Close as CloseIcon } from '@mui/icons-material'; -import { ZKTitle } from "./Title"; +import React, { useContext, useState } from 'react' +import { withStyles, createStyles, Theme, styled } from '@mui/material/styles' +import { + AppBar, + ListItemText, + Menu, + MenuProps, + MenuItem, + IconButton, + Toolbar, + useScrollTrigger, +} from '@mui/material' +import { makeStyles } from '@mui/styles' +import { Menu as MenuIcon, Close as CloseIcon } from '@mui/icons-material' +import { ZKTitle } from './Title' import { accentColor, secondAccent, @@ -12,30 +22,30 @@ import { NormalBodyText, subtleText, lighterBackground, -} from "../styles"; -import Options from './Options'; -import { CeremonyProgress } from './ProgressPanel'; -import state from '../contexts/state'; -import { observer } from 'mobx-react-lite'; -import { State } from '../types/ceremony'; +} from '../styles' +import Options from './Options' +import { CeremonyProgress } from './ProgressPanel' +import state from '../contexts/state' +import { observer } from 'mobx-react-lite' +import { State } from '../types/ceremony' -const allowOptions = false; // if true, the 'Options' panel is available +const allowOptions = false // if true, the 'Options' panel is available interface ScrollProps { - children: React.ReactElement; + children: React.ReactElement } function ElevationScroll(props: ScrollProps) { - const { children } = props; + const { children } = props const trigger = useScrollTrigger({ disableHysteresis: true, threshold: 0, - }); + }) return React.cloneElement(children, { elevation: trigger ? 4 : 0, - style: {backgroundColor: background}, - }); + style: { backgroundColor: background }, + }) } const StyledMenu = styled(Menu, { @@ -56,19 +66,18 @@ const StyledMenu = styled(Menu, { horizontal: 'center', }, } -`; +` -const StyledMenuItem = styled(MenuItem) - (() => ({ +const StyledMenuItem = styled(MenuItem)(() => ({ root: { '&:focus': { - backgroundColor: "unset", + backgroundColor: 'unset', '& .MuiListItemIcon-root, & .MuiListItemText-primary': { color: textColor, }, }, }, -})); +})) const useStyles = makeStyles((theme: Theme) => createStyles({ @@ -81,26 +90,28 @@ const useStyles = makeStyles((theme: Theme) => title: { flexGrow: 1, }, - }), -); + }) +) interface MainMenuProps { - anchorEl: Element | ((element: Element) => Element) | null | undefined; - handleClose: ((event: {}, reason: "backdropClick" | "escapeKeyDown") => void) | undefined; - logout: () => void; + anchorEl: Element | ((element: Element) => Element) | null | undefined + handleClose: + | ((event: {}, reason: 'backdropClick' | 'escapeKeyDown') => void) + | undefined + logout: () => void } const MainMenu = observer((props: MainMenuProps) => { - const [openOptions, setOpenOptions] = useState(false); - const { ceremony } = useContext(state) as State; + const [openOptions, setOpenOptions] = useState(false) + const { ceremony } = useContext(state) as State - const enableLogout = (ceremony.authenticated); + const enableLogout = ceremony.authenticated const toggleOptions = () => { - setOpenOptions(open => { - if (props.handleClose) props.handleClose({}, 'backdropClick'); - return !open; - }); + setOpenOptions((open) => { + if (props.handleClose) props.handleClose({}, 'backdropClick') + return !open + }) } return ( @@ -113,97 +124,110 @@ const MainMenu = observer((props: MainMenuProps) => { onClose={props.handleClose} > - + {allowOptions ? ( - + - ) : (
) - } + ) : ( +
+ )} - ); -}); + ) +}) const LoginDetails = observer(() => { - const { ceremony } = useContext(state) as State; + const { ceremony } = useContext(state) as State - const userName = ceremony.authenticated ? ceremony.userId : 'Connect'; + const userName = ceremony.authenticated ? ceremony.userId : 'Connect' - return ({userName}); -}); + return {userName} +}) const ButtonAppBar = observer(() => { - const [menuAnchorEl, setMenuAnchorEl] = React.useState(null); - const { ceremony, ui } = useContext(state) as State; + const [menuAnchorEl, setMenuAnchorEl] = React.useState( + null + ) + const { ceremony, ui } = useContext(state) as State //const classes = useStyles(); const handleMenuClick = (event: React.MouseEvent) => { // Toggle menu if (menuAnchorEl) { - handleMenuClose(); + handleMenuClose() } else { - setMenuAnchorEl(event.currentTarget); + setMenuAnchorEl(event.currentTarget) } - }; - + } + const handleMenuClose = () => { - setMenuAnchorEl(null); - }; - + setMenuAnchorEl(null) + } + const handleLogout = () => { - console.debug('logging out'); + console.debug('logging out') // ceremony.logout ???? - handleMenuClose(); + handleMenuClose() } - const displayProgress = (( - ceremony.inQueue || - ceremony.contributing) - && !ui.progressIsVisible - ); - - const menuIcon = ( - menuAnchorEl ? - () - : () - ); - + const displayProgress = + (ceremony.inQueue || ceremony.contributing) && !ui.progressIsVisible + + const menuIcon = menuAnchorEl ? ( + + ) : ( + + ) + return (
- + - + > {menuIcon} - + - {displayProgress ? + {displayProgress ? (
{/*Your contribution: */} - -
- : (<>)} +
+ ) : ( + <> + )} - ); -}); + ) +}) -export default ButtonAppBar; +export default ButtonAppBar diff --git a/packages/frontend/src/components/Options.tsx b/packages/frontend/src/components/Options.tsx index 2b01b53..db699dc 100644 --- a/packages/frontend/src/components/Options.tsx +++ b/packages/frontend/src/components/Options.tsx @@ -1,90 +1,99 @@ -import { Button, Checkbox, FormControlLabel, FormGroup, Modal, Typography } from '@mui/material'; -import { createStyles, makeStyles, Theme } from '@mui/material'; -import * as React from 'react'; -import { useContext } from 'react'; -import { observer } from 'mobx-react-lite'; -import { State } from '../types/ceremony'; -import state from '../contexts/state'; -import env from '../env'; +import { + Button, + Checkbox, + FormControlLabel, + FormGroup, + Modal, + Typography, +} from '@mui/material' +import { createStyles, Theme } from '@mui/material' +import { makeStyles } from '@mui/styles' +import * as React from 'react' +import { useContext } from 'react' +import { observer } from 'mobx-react-lite' +import { State } from '../types/ceremony' +import state from '../contexts/state' +import env from '../env' function getModalStyle() { - const top = 50; - const left = 50; - - return { - top: `${top}%`, - left: `${left}%`, - transform: `translate(-${top}%, -${left}%)`, - }; -}; - + const top = 50 + const left = 50 + + return { + top: `${top}%`, + left: `${left}%`, + transform: `translate(-${top}%, -${left}%)`, + } +} + const useStyles = makeStyles((theme: Theme) => - createStyles({ - paper: { - position: 'absolute', - width: 600, - backgroundColor: 'black', - border: '2px solid #fff', - boxShadow: theme.shadows[5], - padding: theme.spacing(2, 4, 3), - }, - checkbox: { - color: 'white', - }, - 'checkbox:disabled': { - color: 'white', - opacity: 0.5, - } - }), -); + createStyles({ + paper: { + position: 'absolute', + width: 600, + backgroundColor: 'black', + border: '2px solid #fff', + boxShadow: theme.shadows[5], + padding: theme.spacing(2, 4, 3), + }, + checkbox: { + color: 'white', + }, + 'checkbox:disabled': { + color: 'white', + opacity: 0.5, + }, + }) +) // TODO - is this still needed? const Options = observer((props: any) => { - const { ui, ceremony } = useContext(state) as State; - //const classes = useStyles(); + const { ui, ceremony } = useContext(state) as State + //const classes = useStyles(); + + const { authenticated, userId } = ceremony - const { authenticated, userId } = ceremony; + const handleOptionChange = (event: React.ChangeEvent) => {} - const handleOptionChange = (event: React.ChangeEvent) => { - }; - - const manualAttest = ( -
- - - } - label="Manual attestation" - classes={{ - /*root: classes.checkbox, + const manualAttest = ( +
+ + + } + label="Manual attestation" + classes={ + { + /*root: classes.checkbox, disabled: classes['checkbox:disabled'],*/ - }} - style={{ display: 'flex', alignItems: 'center', marginTop: '30px' }} - /> - -
- ); + } + } + style={{ display: 'flex', alignItems: 'center', marginTop: '30px' }} + /> +
+
+ ) - return ( - -
- {manualAttest} -
-
-
- ); -}); + return ( + +
+ {manualAttest} +
+
+
+ ) +}) -export default Options; \ No newline at end of file +export default Options diff --git a/yarn.lock b/yarn.lock index 90c88f3..ead7acb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2007,7 +2007,7 @@ dependencies: regenerator-runtime "^0.13.11" -"@babel/runtime@^7.22.5": +"@babel/runtime@^7.22.5", "@babel/runtime@^7.3.1", "@babel/runtime@^7.8.3": version "7.22.6" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.6.tgz#57d64b9ae3cff1d67eb067ae117dac087f5bd438" integrity sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ== @@ -3365,7 +3365,16 @@ "@mui/utils" "^5.13.1" prop-types "^15.8.1" -"@mui/styled-engine-sc@^5.12.0", "@mui/styled-engine@^5.13.2", "@mui/styled-engine@npm:@mui/styled-engine-sc@latest": +"@mui/private-theming@^5.13.7": + version "5.13.7" + resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.13.7.tgz#2f8ef5da066f3c6c6423bd4260d003a28d10b099" + integrity sha512-qbSr+udcij5F9dKhGX7fEdx2drXchq7htLNr2Qg2Ma+WJ6q0ERlEqGSBiPiVDJkptcjeVL4DGmcf1wl5+vD4EA== + dependencies: + "@babel/runtime" "^7.22.5" + "@mui/utils" "^5.13.7" + prop-types "^15.8.1" + +"@mui/styled-engine-sc@^5.12.0", "@mui/styled-engine@npm:@mui/styled-engine-sc@latest": name "@mui/styled-engine" version "5.12.0" resolved "https://registry.yarnpkg.com/@mui/styled-engine-sc/-/styled-engine-sc-5.12.0.tgz#41040fb27667efab46e9200cec9657e62b544c48" @@ -3374,6 +3383,39 @@ "@babel/runtime" "^7.21.0" prop-types "^15.8.1" +"@mui/styled-engine@^5.13.2": + version "5.13.2" + resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.13.2.tgz#c87bd61c0ab8086d34828b6defe97c02bcd642ef" + integrity sha512-VCYCU6xVtXOrIN8lcbuPmoG+u7FYuOERG++fpY74hPpEWkyFQG97F+/XfTQVYzlR2m7nPjnwVUgATcTCMEaMvw== + dependencies: + "@babel/runtime" "^7.21.0" + "@emotion/cache" "^11.11.0" + csstype "^3.1.2" + prop-types "^15.8.1" + +"@mui/styles@^5.13.7": + version "5.13.7" + resolved "https://registry.yarnpkg.com/@mui/styles/-/styles-5.13.7.tgz#b3d98741ccfaad32c6341c9b1dc5072578327d66" + integrity sha512-RWoQwMYzW4gg2ksVGBIGeMjz1bFz6H+FcHOgncYytaZbvXiMXRkChomb+do4cx41BuXpe94YLP63keM7tjNFpg== + dependencies: + "@babel/runtime" "^7.22.5" + "@emotion/hash" "^0.9.1" + "@mui/private-theming" "^5.13.7" + "@mui/types" "^7.2.4" + "@mui/utils" "^5.13.7" + clsx "^1.2.1" + csstype "^3.1.2" + hoist-non-react-statics "^3.3.2" + jss "^10.10.0" + jss-plugin-camel-case "^10.10.0" + jss-plugin-default-unit "^10.10.0" + jss-plugin-global "^10.10.0" + jss-plugin-nested "^10.10.0" + jss-plugin-props-sort "^10.10.0" + jss-plugin-rule-value-function "^10.10.0" + jss-plugin-vendor-prefixer "^10.10.0" + prop-types "^15.8.1" + "@mui/system@^5.13.5": version "5.13.5" resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.13.5.tgz#9f67ea0c4f6974713f90b7b94c999fd3f40f8de3" @@ -3404,6 +3446,17 @@ prop-types "^15.8.1" react-is "^18.2.0" +"@mui/utils@^5.13.7": + version "5.13.7" + resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.13.7.tgz#7e6a8336e05eb2642667a5c02eb605351e27ec20" + integrity sha512-/3BLptG/q0u36eYED7Nhf4fKXmcKb6LjjT7ZMwhZIZSdSxVqDqSTmATW3a56n3KEPQUXCU9TpxAfCBQhs6brVA== + dependencies: + "@babel/runtime" "^7.22.5" + "@types/prop-types" "^15.7.5" + "@types/react-is" "^18.2.1" + prop-types "^15.8.1" + react-is "^18.2.0" + "@mui/x-data-grid@^6.8.0": version "6.8.0" resolved "https://registry.yarnpkg.com/@mui/x-data-grid/-/x-data-grid-6.8.0.tgz#6f04084dceca61c71e5594f6437ee7f038c89f01" @@ -3988,7 +4041,7 @@ dependencies: "@types/react" "*" -"@types/react-is@^18.2.0": +"@types/react-is@^18.2.0", "@types/react-is@^18.2.1": version "18.2.1" resolved "https://registry.yarnpkg.com/@types/react-is/-/react-is-18.2.1.tgz#61d01c2a6fc089a53520c0b66996d458fdc46863" integrity sha512-wyUkmaaSZEzFZivD8F2ftSyAfk6L+DfFliVj/mYdOXbVjRcS87fQJLTnhk6dRZPuJjI+9g6RZJO4PNCngUrmyw== @@ -5630,6 +5683,14 @@ css-tree@~2.2.0: mdn-data "2.0.28" source-map-js "^1.0.1" +css-vendor@^2.0.8: + version "2.0.8" + resolved "https://registry.yarnpkg.com/css-vendor/-/css-vendor-2.0.8.tgz#e47f91d3bd3117d49180a3c935e62e3d9f7f449d" + integrity sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ== + dependencies: + "@babel/runtime" "^7.8.3" + is-in-browser "^1.0.2" + css-what@^6.0.1, css-what@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" @@ -6892,7 +6953,7 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1: +hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== @@ -7073,6 +7134,11 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" +hyphenate-style-name@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz#691879af8e220aea5750e8827db4ef62a54e361d" + integrity sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ== + iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz" @@ -7318,6 +7384,11 @@ is-glob@^4.0.1, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" +is-in-browser@^1.0.2, is-in-browser@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/is-in-browser/-/is-in-browser-1.1.3.tgz#56ff4db683a078c6082eb95dad7dc62e1d04f835" + integrity sha512-FeXIBgG/CPGd/WUxuEyvgGTEfwiG9Z4EKGxjNMRqviiIIfsmgrpnHLffEDdwUHqNva1VEW91o3xBT/m8Elgl9g== + is-interactive@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz" @@ -7577,6 +7648,76 @@ jsonparse@^1.2.0, jsonparse@^1.3.1: resolved "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz" integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== +jss-plugin-camel-case@^10.10.0: + version "10.10.0" + resolved "https://registry.yarnpkg.com/jss-plugin-camel-case/-/jss-plugin-camel-case-10.10.0.tgz#27ea159bab67eb4837fa0260204eb7925d4daa1c" + integrity sha512-z+HETfj5IYgFxh1wJnUAU8jByI48ED+v0fuTuhKrPR+pRBYS2EDwbusU8aFOpCdYhtRc9zhN+PJ7iNE8pAWyPw== + dependencies: + "@babel/runtime" "^7.3.1" + hyphenate-style-name "^1.0.3" + jss "10.10.0" + +jss-plugin-default-unit@^10.10.0: + version "10.10.0" + resolved "https://registry.yarnpkg.com/jss-plugin-default-unit/-/jss-plugin-default-unit-10.10.0.tgz#db3925cf6a07f8e1dd459549d9c8aadff9804293" + integrity sha512-SvpajxIECi4JDUbGLefvNckmI+c2VWmP43qnEy/0eiwzRUsafg5DVSIWSzZe4d2vFX1u9nRDP46WCFV/PXVBGQ== + dependencies: + "@babel/runtime" "^7.3.1" + jss "10.10.0" + +jss-plugin-global@^10.10.0: + version "10.10.0" + resolved "https://registry.yarnpkg.com/jss-plugin-global/-/jss-plugin-global-10.10.0.tgz#1c55d3c35821fab67a538a38918292fc9c567efd" + integrity sha512-icXEYbMufiNuWfuazLeN+BNJO16Ge88OcXU5ZDC2vLqElmMybA31Wi7lZ3lf+vgufRocvPj8443irhYRgWxP+A== + dependencies: + "@babel/runtime" "^7.3.1" + jss "10.10.0" + +jss-plugin-nested@^10.10.0: + version "10.10.0" + resolved "https://registry.yarnpkg.com/jss-plugin-nested/-/jss-plugin-nested-10.10.0.tgz#db872ed8925688806e77f1fc87f6e62264513219" + integrity sha512-9R4JHxxGgiZhurDo3q7LdIiDEgtA1bTGzAbhSPyIOWb7ZubrjQe8acwhEQ6OEKydzpl8XHMtTnEwHXCARLYqYA== + dependencies: + "@babel/runtime" "^7.3.1" + jss "10.10.0" + tiny-warning "^1.0.2" + +jss-plugin-props-sort@^10.10.0: + version "10.10.0" + resolved "https://registry.yarnpkg.com/jss-plugin-props-sort/-/jss-plugin-props-sort-10.10.0.tgz#67f4dd4c70830c126f4ec49b4b37ccddb680a5d7" + integrity sha512-5VNJvQJbnq/vRfje6uZLe/FyaOpzP/IH1LP+0fr88QamVrGJa0hpRRyAa0ea4U/3LcorJfBFVyC4yN2QC73lJg== + dependencies: + "@babel/runtime" "^7.3.1" + jss "10.10.0" + +jss-plugin-rule-value-function@^10.10.0: + version "10.10.0" + resolved "https://registry.yarnpkg.com/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.10.0.tgz#7d99e3229e78a3712f78ba50ab342e881d26a24b" + integrity sha512-uEFJFgaCtkXeIPgki8ICw3Y7VMkL9GEan6SqmT9tqpwM+/t+hxfMUdU4wQ0MtOiMNWhwnckBV0IebrKcZM9C0g== + dependencies: + "@babel/runtime" "^7.3.1" + jss "10.10.0" + tiny-warning "^1.0.2" + +jss-plugin-vendor-prefixer@^10.10.0: + version "10.10.0" + resolved "https://registry.yarnpkg.com/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.10.0.tgz#c01428ef5a89f2b128ec0af87a314d0c767931c7" + integrity sha512-UY/41WumgjW8r1qMCO8l1ARg7NHnfRVWRhZ2E2m0DMYsr2DD91qIXLyNhiX83hHswR7Wm4D+oDYNC1zWCJWtqg== + dependencies: + "@babel/runtime" "^7.3.1" + css-vendor "^2.0.8" + jss "10.10.0" + +jss@10.10.0, jss@^10.10.0: + version "10.10.0" + resolved "https://registry.yarnpkg.com/jss/-/jss-10.10.0.tgz#a75cc85b0108c7ac8c7b7d296c520a3e4fbc6ccc" + integrity sha512-cqsOTS7jqPsPMjtKYDUpdFC0AbhYFLTcuGRqymgmdJIeQ8cH7+AgX7YSgQy79wXloZq2VvATYxUOUQEvS1V/Zw== + dependencies: + "@babel/runtime" "^7.3.1" + csstype "^3.0.2" + is-in-browser "^1.1.3" + tiny-warning "^1.0.2" + just-diff-apply@^5.2.0: version "5.4.1" resolved "https://registry.npmjs.org/just-diff-apply/-/just-diff-apply-5.4.1.tgz" @@ -10543,6 +10684,11 @@ thunky@^1.0.2: resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== +tiny-warning@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" + integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== + tmp@^0.0.33: version "0.0.33" resolved "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz" From d3474636428a4d248c0b7c9336b8c7c6927346db Mon Sep 17 00:00:00 2001 From: Nico Serrano Date: Mon, 10 Jul 2023 15:57:46 -0500 Subject: [PATCH 02/15] backend(docs): instructions to generate zkeys --- packages/backend/README.md | 45 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/packages/backend/README.md b/packages/backend/README.md index b2e54cd..319bb1d 100644 --- a/packages/backend/README.md +++ b/packages/backend/README.md @@ -2,6 +2,51 @@ > TODO: description +## Instructions to run + +Before running the `backend` you would need the `powersOfTau28_hez_final_14.ptau`, `circuits/semaphore01` and `circuits/semaphore02` files. To generate them you can run the following commands: + +```bash +# 1. Install circom following https://docs.circom.io/getting-started/installation/ + +# 2. Install snarkjs +npm install -g snarkjs + +# 3. Clone the semaphore repo +git clone https://github.com/semaphore-protocol/semaphore + +# 4. Move to the circuits folder +cd packages/circuits + +# 5. Install dependencies +yarn install + +# 6. Remember to change ../node_modules to ../../node_modules +# in semaphore.circom and tree.circom + +# 7. Generate the circuits +circom --r1cs --wasm -o ./ ./semaphore.circom + +# 8. Download the .ptau file +wget https://hermez.s3-eu-west-1.amazonaws.com/powersOfTau28_hez_final_15.ptau + +# 9. Generate the 0001 key +snarkjs g16s ./semaphore.r1cs ./powersOfTau28_hez_final_15.ptau semaphore_0001.zkey + +# 10. Generate the 0002 key +snarkjs g16s ./semaphore.r1cs ./powersOfTau28_hez_final_15.ptau semaphore_0002.zkey +``` + +To run the `backend` package you need to follow and execute these steps: + +```bash +# 1. Install dependencies +yarn install + +# 2. Run the backend +yarn backend start +``` + ## Usage ``` From 09eca4958f3ac2564bde8763da5b03235ef39ff9 Mon Sep 17 00:00:00 2001 From: Nico Serrano Date: Mon, 10 Jul 2023 22:34:46 -0500 Subject: [PATCH 03/15] frontend(feat): create Entropy interface --- packages/frontend/src/types/ceremony.d.ts | 291 +++++++++++----------- 1 file changed, 148 insertions(+), 143 deletions(-) diff --git a/packages/frontend/src/types/ceremony.d.ts b/packages/frontend/src/types/ceremony.d.ts index e612fd3..bf99f5f 100644 --- a/packages/frontend/src/types/ceremony.d.ts +++ b/packages/frontend/src/types/ceremony.d.ts @@ -1,128 +1,128 @@ export type CeremonyState = - | "PRESELECTION" - | "SELECTED" - | "RUNNING" - | "COMPLETE" - | "WAITING" - | "PAUSED" - | "UNKNOWN"; + | 'PRESELECTION' + | 'SELECTED' + | 'RUNNING' + | 'COMPLETE' + | 'WAITING' + | 'PAUSED' + | 'UNKNOWN' export type ParticipantState = - | "WAITING" - | "RUNNING" - | "COMPLETE" - | "INVALIDATED"; + | 'WAITING' + | 'RUNNING' + | 'COMPLETE' + | 'INVALIDATED' export type ParticipantRunningState = - | "OFFLINE" - | "WAITING" - | "RUNNING" - | "COMPLETE"; + | 'OFFLINE' + | 'WAITING' + | 'RUNNING' + | 'COMPLETE' -export type TranscriptState = "WAITING" | "VERIFYING" | "COMPLETE"; +export type TranscriptState = 'WAITING' | 'VERIFYING' | 'COMPLETE' -// export enum ComputeMode { +// export enum ComputeMode { // "ZKEY", // "POWERSOFTAU", // }; export interface Ceremony { // firebase-only data - id: string; - title: string; - serverURL: string; - description: string; - circuitFileName: string; - mode: ComputeMode; - instructions: string; - github: string; - homepage: string; - adminAddr: string; - lastSummaryUpdate: Date; - - ceremonyState: CeremonyState; - startTime: Date | string; - endTime: Date | string | undefined; - completedAt?: Date; - paused: boolean; - selectBlock: number; - minParticipants: number; - maxTier2: number; - sequence: number; - ceremonyProgress: number; // this is only returned by /api/state-summary, else must be computed by us - numParticipants: number; // this is only returned by /api/state-summary, else must be computed by us - complete: number; - waiting: number; - numConstraints?: number; - averageDuration?: number; - transcript?: string; - hash?: string; // Participant's own hash - isCompleted?: boolean; // Participant has completed this circuit - highestQueueIndex: number; - zkeyPrefix: string; + id: string + title: string + serverURL: string + description: string + circuitFileName: string + mode: ComputeMode + instructions: string + github: string + homepage: string + adminAddr: string + lastSummaryUpdate: Date + + ceremonyState: CeremonyState + startTime: Date | string + endTime: Date | string | undefined + completedAt?: Date + paused: boolean + selectBlock: number + minParticipants: number + maxTier2: number + sequence: number + ceremonyProgress: number // this is only returned by /api/state-summary, else must be computed by us + numParticipants: number // this is only returned by /api/state-summary, else must be computed by us + complete: number + waiting: number + numConstraints?: number + averageDuration?: number + transcript?: string + hash?: string // Participant's own hash + isCompleted?: boolean // Participant has completed this circuit + highestQueueIndex: number + zkeyPrefix: string } export interface Participant { // Coordinator server controlled data. - address: string; - uid: string; // Firebase.auth uid. Also firestore document id. - state: ParticipantState; // is participant queued, currently computing, done, or invalidated? - authId: string, // ID on the authorising platform, e.g. email for GitHub + address: string + uid: string // Firebase.auth uid. Also firestore document id. + state: ParticipantState // is participant queued, currently computing, done, or invalidated? + authId: string // ID on the authorising platform, e.g. email for GitHub //runningState: ParticipantRunningState; // if the participant is computing, are they computing offline? (or maybe they are queued or invalidated) //position: number; //priority: number; - tier: number; + tier: number //verifyProgress: number; - lastVerified?: Date; - addedAt: Date; - startedAt?: Date; - completedAt?: Date; - error?: string; - online: boolean; - lastUpdate?: Date; + lastVerified?: Date + addedAt: Date + startedAt?: Date + completedAt?: Date + error?: string + online: boolean + lastUpdate?: Date //location?: ParticipantLocation; //invalidateAfter?: number; //sequence: number; //transcripts: Transcript[]; // Except 'complete' participants - computeProgress: number; + computeProgress: number // ZKParty data //messages: Message[]; } export interface CeremonyEvent { - ceremonyId?: string; - sender: string; - eventType: string; - timestamp: timestamp; - message: string; - index?: number; - acknowledged: boolean; + ceremonyId?: string + sender: string + eventType: string + timestamp: timestamp + message: string + index?: number + acknowledged: boolean } export interface Transcript { // Server controlled data. - state: TranscriptState; + state: TranscriptState // Client controlled data. - num: number; - fromAddress?: string; - size: number; - downloaded: number; - uploaded: number; + num: number + fromAddress?: string + size: number + downloaded: number + uploaded: number } export interface ParticipantLocation { - city?: string; - country?: string; - continent?: string; - latitude?: number; - longitude?: number; + city?: string + country?: string + continent?: string + latitude?: number + longitude?: number } export interface Message { - content: string; - timestamp: string; - signature: string; + content: string + timestamp: string + signature: string } //declare global { @@ -130,83 +130,88 @@ export interface Message { //} export interface Contribution { - participantId: string; // Firebase ID - participantAuthId?: string; // Authorising platform ID - queueIndex?: number; - lastSeen?: timestamp; - timeAdded?: timestamp; - status: ParticipantState; - index?: number; - priorIndex?: number; - verification?: string; + participantId: string // Firebase ID + participantAuthId?: string // Authorising platform ID + queueIndex?: number + lastSeen?: timestamp + timeAdded?: timestamp + status: ParticipantState + index?: number + priorIndex?: number + verification?: string } export interface ContributionSummary extends Contribution { - paramsFile?: string; - timeCompleted?: timestamp; - hash?: string; - duration?: number; + paramsFile?: string + timeCompleted?: timestamp + hash?: string + duration?: number } export interface ContributionState { - ceremony: Ceremony; - queueIndex: number; - currentIndex: number; - lastValidIndex: number; - averageSecondsPerContribution: number; - expectedStartTime?: timestamp; - status: ParticipantState; - startTime?: date; + ceremony: Ceremony + queueIndex: number + currentIndex: number + lastValidIndex: number + averageSecondsPerContribution: number + expectedStartTime?: timestamp + status: ParticipantState + startTime?: date } export interface Project { - id: string; // Firebase document ID - name: string; - shortName: string; - gistSummaryDescription: string; - gistBodyTemplate: string; - tweetTemplate: string; - circuits: string[]; - coordinators: string[]; + id: string // Firebase document ID + name: string + shortName: string + gistSummaryDescription: string + gistBodyTemplate: string + tweetTemplate: string + circuits: string[] + coordinators: string[] } export interface Circuit { - name: string; - contributionCount: number; + name: string + contributionCount: number } export interface Queue { - connection: boolean; - client: any; - keepaliveTimer: number; - connected: boolean; - authToken: string; - userId: string; - ceremonyState: { circuitStats: Circuit[] }; - queueLength: number; - timeoutAt: number; - activeContributor: string; - contributing: boolean; - contributionName: string; - contributionHashes: string[]; - loadingInitial: boolean; - inQueue: boolean; - isFinished: boolean; - project: string; - authenticated: boolean; - - contributionUpdates: any[]; - contributionText: string; - - join(name: string): void; - stopKeepAlive(); - auth(); - load(); + connection: boolean + client: any + keepaliveTimer: number + connected: boolean + authToken: string + userId: string + ceremonyState: { circuitStats: Circuit[] } + queueLength: number + timeoutAt: number + activeContributor: string + contributing: boolean + contributionName: string + contributionHashes: string[] + loadingInitial: boolean + inQueue: boolean + isFinished: boolean + project: string + authenticated: boolean + + contributionUpdates: any[] + contributionText: string + + join(name: string): void + stopKeepAlive() + auth() + load() +} + +export interface Entropy { + secret: string + setSecret(secret: string): void } declare interface State { - ceremony: Queue; - ui: any; + ceremony: Queue + ui: any } -export declare function f(): void; +export declare function f(): void From 2898bc96308bf6f496230f113283c1307fafffe6 Mon Sep 17 00:00:00 2001 From: Nico Serrano Date: Mon, 10 Jul 2023 22:35:16 -0500 Subject: [PATCH 04/15] frontend(feat): send styles as props in Login btn --- packages/frontend/src/components/Login.tsx | 97 ++++++++++++---------- 1 file changed, 54 insertions(+), 43 deletions(-) diff --git a/packages/frontend/src/components/Login.tsx b/packages/frontend/src/components/Login.tsx index 453f4c8..443762f 100644 --- a/packages/frontend/src/components/Login.tsx +++ b/packages/frontend/src/components/Login.tsx @@ -1,55 +1,66 @@ -import React, { useState, useContext } from "react"; +import React, { useState, useContext, CSSProperties } from 'react' //import GitHubIcon from "@mui/material-icons/GitHub"; -import { accentColor, lighterBackground } from "../styles"; -import { AuthButton, AuthButtonText } from './../styles'; +import { accentColor, lighterBackground } from '../styles' +import { AuthButton, AuthButtonText } from './../styles' -const Login = (props: { onClick: () => void }) => { +interface Props { + onClick: () => void + style?: CSSProperties +} +const Login = (props: Props) => { const handleEthereumLogin = async () => { // Check cookie - const COOKIE_NAME = 'signed_signin_message'; - // try { - // const cookie = localStorage.getItem(COOKIE_NAME); - // let signature: string, account: string; - // if (cookie) { - // const sigData = JSON.parse(cookie); - // account = sigData.ethAddress; - // signature = sigData.sig; - // } else { - // // Connect to browser wallet - // if (!window.ethereum) { - // console.error('Metamask is not installed. Signin aborted.'); - // return; - // } - // const SIGNIN_MESSAGE = 'ZKParty sign-in'; - // const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' }); - // account = accounts[0]; - // console.debug(`Metamask account: ${account}`); - // // Sign message. TODO - put message in a constant that's also reachable from functions - // const signinMessage = `0x${Buffer.from(SIGNIN_MESSAGE).toString('hex')}`; - // console.log(`msg to be signed: ${signinMessage}`); - // signature = await window.ethereum.request({ - // method: 'personal_sign', - // params: [signinMessage, account], - // }); + const COOKIE_NAME = 'signed_signin_message' + // try { + // const cookie = localStorage.getItem(COOKIE_NAME); + // let signature: string, account: string; + // if (cookie) { + // const sigData = JSON.parse(cookie); + // account = sigData.ethAddress; + // signature = sigData.sig; + // } else { + // // Connect to browser wallet + // if (!window.ethereum) { + // console.error('Metamask is not installed. Signin aborted.'); + // return; + // } + // const SIGNIN_MESSAGE = 'ZKParty sign-in'; + // const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' }); + // account = accounts[0]; + // console.debug(`Metamask account: ${account}`); + // // Sign message. TODO - put message in a constant that's also reachable from functions + // const signinMessage = `0x${Buffer.from(SIGNIN_MESSAGE).toString('hex')}`; + // console.log(`msg to be signed: ${signinMessage}`); + // signature = await window.ethereum.request({ + // method: 'personal_sign', + // params: [signinMessage, account], + // }); - // // Save cookie - // const sigData = { ethAddress: account, sig: signature }; - // localStorage.setItem(COOKIE_NAME, JSON.stringify(sigData)); - // } - // console.log(`Signature: ${signature}`); + // // Save cookie + // const sigData = { ethAddress: account, sig: signature }; + // localStorage.setItem(COOKIE_NAME, JSON.stringify(sigData)); + // } + // console.log(`Signature: ${signature}`); - // // Get JWT + // // Get JWT } - - const handleOptionChange = (event: React.ChangeEvent) => { - }; + const handleOptionChange = (event: React.ChangeEvent) => {} return (
- -
+ +
Join
@@ -69,7 +80,7 @@ const Login = (props: { onClick: () => void }) => { /> */}
- ); -}; + ) +} -export default Login; +export default Login From 7a4b044665d03dfb5ed3813ff4e8e7599f57afdd Mon Sep 17 00:00:00 2001 From: Nico Serrano Date: Mon, 10 Jul 2023 22:35:50 -0500 Subject: [PATCH 05/15] frontend(fix): add Entropy as attribute --- packages/frontend/src/types/ceremony.d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/frontend/src/types/ceremony.d.ts b/packages/frontend/src/types/ceremony.d.ts index bf99f5f..86186e5 100644 --- a/packages/frontend/src/types/ceremony.d.ts +++ b/packages/frontend/src/types/ceremony.d.ts @@ -211,6 +211,7 @@ export interface Entropy { declare interface State { ceremony: Queue + entropy: Entropy ui: any } From 7b3d2d0d8b04a7c888c97bedb7bb2947bffb648f Mon Sep 17 00:00:00 2001 From: Nico Serrano Date: Mon, 10 Jul 2023 22:36:25 -0500 Subject: [PATCH 06/15] frontend(feat): add entropy input --- .../frontend/src/components/LoginPanel.tsx | 140 ++++++++++++------ packages/frontend/src/contexts/Ceremony.js | 1 + packages/frontend/src/contexts/Entropy.js | 13 ++ packages/frontend/src/contexts/state.js | 3 + 4 files changed, 109 insertions(+), 48 deletions(-) create mode 100644 packages/frontend/src/contexts/Entropy.js diff --git a/packages/frontend/src/components/LoginPanel.tsx b/packages/frontend/src/components/LoginPanel.tsx index 37ac8b5..b48c975 100644 --- a/packages/frontend/src/components/LoginPanel.tsx +++ b/packages/frontend/src/components/LoginPanel.tsx @@ -1,53 +1,97 @@ -import { - WelcomeTitle, - SubtleBody, - NormalBodyText, -} from "../styles"; -import Login from './Login'; -import env from '../env'; -import { Tooltip, Button } from '@mui/material'; -import { observer } from "mobx-react-lite"; -import { useContext, useState } from "react"; -import state from "../contexts/state"; -import { State } from "../types/ceremony"; +import { WelcomeTitle, SubtleBody, NormalBodyText } from '../styles' +import Login from './Login' +import env from '../env' +import { Tooltip, Button } from '@mui/material' +import { observer } from 'mobx-react-lite' +import { useContext, useState } from 'react' +import state from '../contexts/state' +import { State } from '../types/ceremony' const LoginPanel = observer((props: any) => { - const [name, setName] = useState(''); - const { ui, ceremony } = useContext(state) as State; + const [name, setName] = useState('') + const { ui, entropy, ceremony } = useContext(state) as State + const [inputText, setInputText] = useState('') + const [mouseCoordinate, setMouseCoordinate] = useState([0, 0]) + + const onChangeInput = (e: any) => { + setInputText(e.target.value) + console.log(e.target.value) + } + + const onMoveDiv = (e: any) => { + // TODO-NICO: we need to save all coordinates and their timestamp + setMouseCoordinate([e.clientX, e.clientY]) + console.log(e.clientX, e.clientY) + } + + const onClickJoin = () => { + const secret = inputText + mouseCoordinate[0] + mouseCoordinate[1] + entropy.setSecret(secret) + ceremony.join(name) + console.log('join ceremony') + } return ( -
- {env.projectName} -
- - {`Trusted Setup Ceremony`} - - - {`Join ceremony`} - - -
- -
- setName(e.target.value)} - /> -
-
- -
- {/*`The ceremony is not currently accepting contributions.`*/} - - ceremony.join(name)}/> -
); -}); +
+ {env.projectName} +
+ + {`Trusted Setup Ceremony`} + + + {`Join ceremony`} + + +
+ +
+ setName(e.target.value)} + /> +
+
+ +
+ { + <> +

Entropy section

+
+

+ Enter a secret: +

+ +
+
+

+ Move your move around the square below: +

+
+
+ + } + {/*`The ceremony is not currently accepting contributions.`*/} + + +
+ ) +}) -export default LoginPanel; +export default LoginPanel diff --git a/packages/frontend/src/contexts/Ceremony.js b/packages/frontend/src/contexts/Ceremony.js index 2cdb956..a8c0cec 100644 --- a/packages/frontend/src/contexts/Ceremony.js +++ b/packages/frontend/src/contexts/Ceremony.js @@ -148,6 +148,7 @@ ${hashText} this.contributionName || 'anonymous contributor', Array(32) .fill(null) + // TODO NICO: use the generated entropy .map(() => randomf(2n ** 256n)) .join('') ) diff --git a/packages/frontend/src/contexts/Entropy.js b/packages/frontend/src/contexts/Entropy.js new file mode 100644 index 0000000..5613002 --- /dev/null +++ b/packages/frontend/src/contexts/Entropy.js @@ -0,0 +1,13 @@ +import { makeAutoObservable } from 'mobx' + +export default class Entropy { + secret = '' + + constructor() { + makeAutoObservable(this) + } + + setSecret(secret) { + this.secret = secret + } +} diff --git a/packages/frontend/src/contexts/state.js b/packages/frontend/src/contexts/state.js index b6ce407..8b99a97 100644 --- a/packages/frontend/src/contexts/state.js +++ b/packages/frontend/src/contexts/state.js @@ -2,6 +2,7 @@ import { createContext } from 'react' import { configure } from 'mobx' import Interface from './interface' import Ceremony from './Ceremony' +import Entropy from './Entropy' configure({ enforceActions: 'never', }) @@ -10,10 +11,12 @@ export const buildState = () => { const state = {} const ui = new Interface(state) + const entropy = new Entropy(state) const ceremony = new Ceremony(state) Object.assign(state, { ui, + entropy, ceremony, }) return state From 8cf3baca8f1b2a3dc72b7e6f5b6f505c6867bab5 Mon Sep 17 00:00:00 2001 From: Nico Serrano Date: Tue, 11 Jul 2023 18:46:14 -0500 Subject: [PATCH 07/15] frontend(feat): integrate entropy section in UI --- packages/frontend/src/components/Login.tsx | 1 - .../frontend/src/components/LoginPanel.tsx | 85 +++++++++++++------ packages/frontend/src/styles.ts | 53 ++++++------ 3 files changed, 83 insertions(+), 56 deletions(-) diff --git a/packages/frontend/src/components/Login.tsx b/packages/frontend/src/components/Login.tsx index 443762f..fdc6723 100644 --- a/packages/frontend/src/components/Login.tsx +++ b/packages/frontend/src/components/Login.tsx @@ -61,7 +61,6 @@ const Login = (props: Props) => { justifyContent: 'center', }} > -
Join
diff --git a/packages/frontend/src/components/LoginPanel.tsx b/packages/frontend/src/components/LoginPanel.tsx index b48c975..b33a38d 100644 --- a/packages/frontend/src/components/LoginPanel.tsx +++ b/packages/frontend/src/components/LoginPanel.tsx @@ -6,6 +6,7 @@ import { observer } from 'mobx-react-lite' import { useContext, useState } from 'react' import state from '../contexts/state' import { State } from '../types/ceremony' +import { styled } from 'styled-components' const LoginPanel = observer((props: any) => { const [name, setName] = useState('') @@ -46,47 +47,55 @@ const LoginPanel = observer((props: any) => { {`Trusted Setup Ceremony`} - {`Join ceremony`} + {`Join ceremony:`}
-
- + setName(e.target.value)} />
- { - <> -

Entropy section

-
-

- Enter a secret: -

- -
-
-

- Move your move around the square below: -

-
-
- - } +
+ {`Enter a secret:`} +
+ +
+
+

+ Move your mouse around in this box: +

+
+
+
{/*`The ceremony is not currently accepting contributions.`*/} @@ -94,4 +103,24 @@ const LoginPanel = observer((props: any) => { ) }) +const Input = styled.input` + font-family: inherit; + font-weight: 700; + text-align: center; + height: 30px; + + color: black; + background: #95a7ae; + border-radius: 4px; + border: none; + padding-block: 3px; + + &:focus { + outline: none; + } + &::placeholder { + color: #3c5660 !important; + } +` + export default LoginPanel diff --git a/packages/frontend/src/styles.ts b/packages/frontend/src/styles.ts index 93a3b47..0bb0f61 100644 --- a/packages/frontend/src/styles.ts +++ b/packages/frontend/src/styles.ts @@ -1,17 +1,17 @@ -import styled, { css } from "styled-components"; -import WebFont from 'webfontloader'; - -export const background = "#081b24"; -export const lighterBackground = "#5D7078"; -export const darkerBackground = "#0E2936"; -export const textColor = "#FFFFFF"; -export const accentColor = "#00ffd1"; // Primary 1 -export const secondAccent = "#D0fff7"; // Primary 2 -export const lightBorder = "#5D7078"; -export const darkBorder = "#0E2936"; -export const gray1 = "#333333"; -export const subtleText = "#95a7ae"; -export const inverseText = "#000000"; +import styled, { css } from 'styled-components' +import WebFont from 'webfontloader' + +export const background = '#081b24' +export const lighterBackground = '#5D7078' +export const darkerBackground = '#0E2936' +export const textColor = '#FFFFFF' +export const accentColor = '#00ffd1' // Primary 1 +export const secondAccent = '#D0fff7' // Primary 2 +export const lightBorder = '#5D7078' +export const darkBorder = '#0E2936' +export const gray1 = '#333333' +export const subtleText = '#95a7ae' +export const inverseText = '#000000' export const PageContainer = styled.div` /* width: 100vw; */ @@ -23,24 +23,24 @@ export const PageContainer = styled.div` align-items: center; margin-top: 64px; margin-bottom: 64px; -`; +` export const SectionContainer = styled.div` margin-top: 32px; -`; +` export const Center = styled.div` display: flex; justify-content: center; align-items: center; width: 100%; -`; +` export const CeremonyTitle = styled.div` font-size: 18pt; margin-bottom: 8px; color: ${accentColor}; -`; +` export const AuthButton = styled.button` background-color: ${accentColor}; @@ -99,13 +99,13 @@ export const WelcomeTitle = styled.div` font-family: Luckiest Guy; font-size: 64px; font-weight: normal; - color: rgba(0,0,0,0); + color: rgba(0, 0, 0, 0); letter-spacing: 0.12em; cursor: pointer; user-select: none; -webkit-text-stroke-width: 2px; -webkit-text-stroke-color: ${textColor}; -`; +` const textBase = css` font-family: Inconsolata; @@ -115,7 +115,7 @@ const textBase = css` line-height: 140%; color: ${textColor}; -`; +` export const SubtleBody = styled.div` ${textBase} @@ -123,7 +123,7 @@ export const SubtleBody = styled.div` font-size: 24px; color: ${subtleText}; -`; +` export const SubtleBodyCentred = styled.div` ${textBase} @@ -139,7 +139,7 @@ export const SubtleBodyCentred = styled.div` export const NormalBodyText = styled.div` ${textBase} -`; +` export const HighlightBodyText = styled.div` ${textBase} @@ -173,13 +173,12 @@ export const H3Title = styled.div` margin-bottom: 32px; ` - // ########################## // Fonts // WebFont.load({ google: { - families: ['Shrikhand', 'Inconsolata', 'Avenir Next', 'Luckiest Guy' ] - } -}); + families: ['Shrikhand', 'Inconsolata', 'Avenir Next', 'Luckiest Guy'], + }, +}) From 1c0349fb12615f32e906cdf96795018b12f13507 Mon Sep 17 00:00:00 2001 From: Nico Serrano Date: Wed, 12 Jul 2023 18:49:08 -0500 Subject: [PATCH 08/15] frontend(feat): generate distributed entropy --- packages/frontend/package.json | 2 ++ .../frontend/src/components/LoginPanel.tsx | 9 ++---- packages/frontend/src/contexts/Entropy.js | 32 +++++++++++++++++++ packages/frontend/src/types/ceremony.d.ts | 1 + yarn.lock | 22 ++++++------- 5 files changed, 48 insertions(+), 18 deletions(-) diff --git a/packages/frontend/package.json b/packages/frontend/package.json index eaf3835..8d2bd0f 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -21,6 +21,8 @@ "@mui/styled-engine-sc": "^5.12.0", "@mui/styles": "^5.13.7", "@mui/x-data-grid": "^6.8.0", + "@noble/bls12-381": "^1.4.0", + "@noble/hashes": "^1.3.1", "@types/material-ui": "^0.21.12", "css-minimizer-webpack-plugin": "^5.0.0", "dayjs": "^1.11.7", diff --git a/packages/frontend/src/components/LoginPanel.tsx b/packages/frontend/src/components/LoginPanel.tsx index b33a38d..2cfd4b0 100644 --- a/packages/frontend/src/components/LoginPanel.tsx +++ b/packages/frontend/src/components/LoginPanel.tsx @@ -12,22 +12,17 @@ const LoginPanel = observer((props: any) => { const [name, setName] = useState('') const { ui, entropy, ceremony } = useContext(state) as State const [inputText, setInputText] = useState('') - const [mouseCoordinate, setMouseCoordinate] = useState([0, 0]) const onChangeInput = (e: any) => { setInputText(e.target.value) - console.log(e.target.value) } const onMoveDiv = (e: any) => { - // TODO-NICO: we need to save all coordinates and their timestamp - setMouseCoordinate([e.clientX, e.clientY]) - console.log(e.clientX, e.clientY) + const secret = inputText + e.clientX + e.clientY + performance.now() + entropy.setSecret(`${entropy.secret}${secret}`) } const onClickJoin = () => { - const secret = inputText + mouseCoordinate[0] + mouseCoordinate[1] - entropy.setSecret(secret) ceremony.join(name) console.log('join ceremony') } diff --git a/packages/frontend/src/contexts/Entropy.js b/packages/frontend/src/contexts/Entropy.js index 5613002..c42f0c3 100644 --- a/packages/frontend/src/contexts/Entropy.js +++ b/packages/frontend/src/contexts/Entropy.js @@ -1,3 +1,7 @@ +import { CURVE } from '@noble/bls12-381' +import { hkdf } from '@noble/hashes/hkdf' +import { sha256 } from '@noble/hashes/sha256' +import { randomBytes } from '@noble/hashes/utils' import { makeAutoObservable } from 'mobx' export default class Entropy { @@ -10,4 +14,32 @@ export default class Entropy { setSecret(secret) { this.secret = secret } + + generateEntropy() { + const generatedEntropyAsBytes = Uint8Array.from( + this.secret.split('').map((x) => x.charCodeAt(0)) + ) + const randomEntropyAsBytes = randomBytes(32) + const entropyAsBytes = new Uint8Array( + generatedEntropyAsBytes.length + randomEntropyAsBytes.length + ) + entropyAsBytes.set(generatedEntropyAsBytes) + entropyAsBytes.set(randomEntropyAsBytes, generatedEntropyAsBytes.length) + /* + In order to reduce modulo-bias in the entropy (w.r.t. the curve order): + it is expanded out (and mixed) to at least 48 bytes before being reduced mod curve order. + This exact technique is the RECOMMENDED means of obtaining a ~uniformly random F_r element according to + the IRTF BLS signature specs: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-05#section-2.3 + */ + const salt = randomBytes(32) + const expandedEntropy = hkdf(sha256, entropyAsBytes, salt, '', 48) + const hex96 = expandedEntropy.reduce( + (str, byte) => str + byte.toString(16).padStart(2, '0'), + '' + ) + const expandedEntropyInt = BigInt('0x' + hex96) + const secretInt = expandedEntropyInt % CURVE.r + const secretHex = secretInt.toString(16).padStart(64, '0') + return secretHex + } } diff --git a/packages/frontend/src/types/ceremony.d.ts b/packages/frontend/src/types/ceremony.d.ts index 86186e5..24569b9 100644 --- a/packages/frontend/src/types/ceremony.d.ts +++ b/packages/frontend/src/types/ceremony.d.ts @@ -207,6 +207,7 @@ export interface Queue { export interface Entropy { secret: string setSecret(secret: string): void + generateEntropy(): void } declare interface State { diff --git a/yarn.lock b/yarn.lock index ead7acb..b978fd5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3374,7 +3374,7 @@ "@mui/utils" "^5.13.7" prop-types "^15.8.1" -"@mui/styled-engine-sc@^5.12.0", "@mui/styled-engine@npm:@mui/styled-engine-sc@latest": +"@mui/styled-engine-sc@^5.12.0", "@mui/styled-engine@^5.13.2", "@mui/styled-engine@npm:@mui/styled-engine-sc@latest": name "@mui/styled-engine" version "5.12.0" resolved "https://registry.yarnpkg.com/@mui/styled-engine-sc/-/styled-engine-sc-5.12.0.tgz#41040fb27667efab46e9200cec9657e62b544c48" @@ -3383,16 +3383,6 @@ "@babel/runtime" "^7.21.0" prop-types "^15.8.1" -"@mui/styled-engine@^5.13.2": - version "5.13.2" - resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.13.2.tgz#c87bd61c0ab8086d34828b6defe97c02bcd642ef" - integrity sha512-VCYCU6xVtXOrIN8lcbuPmoG+u7FYuOERG++fpY74hPpEWkyFQG97F+/XfTQVYzlR2m7nPjnwVUgATcTCMEaMvw== - dependencies: - "@babel/runtime" "^7.21.0" - "@emotion/cache" "^11.11.0" - csstype "^3.1.2" - prop-types "^15.8.1" - "@mui/styles@^5.13.7": version "5.13.7" resolved "https://registry.yarnpkg.com/@mui/styles/-/styles-5.13.7.tgz#b3d98741ccfaad32c6341c9b1dc5072578327d66" @@ -3473,6 +3463,16 @@ resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz#323d72dd25103d0c4fbdce89dadf574a787b1f9b" integrity sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ== +"@noble/bls12-381@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@noble/bls12-381/-/bls12-381-1.4.0.tgz#4db0e1577ef85632347e86eee81062acdda6d65b" + integrity sha512-mIYqC2jMX7Lcu1QtU/FFftMPDSXNCdlGex6BSf5nPojHjnzzBgs1klFWpB1R8YjqHmOO9xrCzF19f2c42+z3vg== + +"@noble/hashes@^1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.1.tgz#8831ef002114670c603c458ab8b11328406953a9" + integrity sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA== + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" From 4c9c7d29adebfd8b05b40678bd9e3985f0a571a7 Mon Sep 17 00:00:00 2001 From: Nico Serrano Date: Wed, 12 Jul 2023 21:24:04 -0500 Subject: [PATCH 09/15] frontend(feat): fix unauthorized error in diff ceremonies --- .../frontend/src/app/ParticipantSection.tsx | 78 +++++++++---------- packages/frontend/src/contexts/Ceremony.js | 24 ++++-- 2 files changed, 57 insertions(+), 45 deletions(-) diff --git a/packages/frontend/src/app/ParticipantSection.tsx b/packages/frontend/src/app/ParticipantSection.tsx index dce9e4e..7c14461 100644 --- a/packages/frontend/src/app/ParticipantSection.tsx +++ b/packages/frontend/src/app/ParticipantSection.tsx @@ -1,58 +1,56 @@ -import { useContext, useEffect, useRef } from "react"; -import { Typography } from '@mui/material'; +import { useContext, useEffect } from 'react' +import { Typography } from '@mui/material' -import { State } from "../types/ceremony"; +import { State } from '../types/ceremony' -import WelcomePanel from "../components/WelcomePanel"; -import ProgressPanel from "../components/ProgressPanel"; -import LoginPanel from "../components/LoginPanel"; -import state from '../contexts/state'; -import { observer } from 'mobx-react-lite'; -import { useSnackbar } from "notistack"; -import AttestationPanel from "../components/AttestationPanel"; +import WelcomePanel from '../components/WelcomePanel' +import ProgressPanel from '../components/ProgressPanel' +import LoginPanel from '../components/LoginPanel' +import state from '../contexts/state' +import { observer } from 'mobx-react-lite' +import { useSnackbar } from 'notistack' +import AttestationPanel from '../components/AttestationPanel' - -const stepText = (step: string) => ({step}); +const stepText = (step: string) => ( + {step} +) const ParticipantSection = observer(() => { - const { ceremony } = useContext(state) as State; - const { enqueueSnackbar } = useSnackbar(); + const { ceremony } = useContext(state) as State + const { enqueueSnackbar } = useSnackbar() - const { inQueue, loadingInitial, contributionHashes, authenticated, ceremonyState } = ceremony; + const { inQueue, loadingInitial, contributionHashes, ceremonyState } = + ceremony const statusUpdate = (message: string) => { - enqueueSnackbar(message); - }; + enqueueSnackbar(message) + } - const { contributionUpdates } = ceremony; + const { contributionUpdates } = ceremony useEffect(() => { if (contributionUpdates.length > 0) { - statusUpdate(contributionUpdates[contributionUpdates.length - 1]); - } - }, [contributionUpdates.length] ); + statusUpdate(contributionUpdates[contributionUpdates.length - 1]) + } + }, [contributionUpdates.length]) - const { circuitStats } = ceremonyState; - const done = (contributionHashes - ? (Object.keys(contributionHashes).length >= circuitStats?.length) - : false); + const { circuitStats } = ceremonyState + const done = contributionHashes + ? Object.keys(contributionHashes).length >= circuitStats?.length + : false - let content = (<>); - if (loadingInitial || !authenticated ) { + let content = <> + if (loadingInitial) { // Display welcome text until the 'go ahead' button is clicked. - content = (); - } else if (!inQueue && !(contributionHashes?.length>0) && !done) { - content = (); + content = + } else if (!inQueue && !(contributionHashes?.length > 0) && !done) { + content = } else if (done) { - content = (); + content = } else { - content = (); - }; + content = + } - return ( -
- {content} -
- ); -}); + return
{content}
+}) -export default ParticipantSection; \ No newline at end of file +export default ParticipantSection diff --git a/packages/frontend/src/contexts/Ceremony.js b/packages/frontend/src/contexts/Ceremony.js index a8c0cec..027f2e8 100644 --- a/packages/frontend/src/contexts/Ceremony.js +++ b/packages/frontend/src/contexts/Ceremony.js @@ -58,13 +58,26 @@ ${hashText} this.ingestState(JSON.parse(window.CEREMONY_STATE)) } await this.connect() - this.authToken = localStorage.getItem('authToken') + this.authToken = sessionStorage.getItem('authToken') // don't block here this.loadState().catch(console.log) if (!this.authenticated) await this.auth() - const { data } = await this.client.send('user.info', { - token: this.authToken, - }) + let data = null + try { + const result = await this.client.send('user.info', { + token: this.authToken, + }) + data = result.data + } catch (error) { + // in case the auth token is from another old ceremony + if (error.message === 'unauthorized') { + await this.auth() + const result = await this.client.send('user.info', { + token: this.authToken, + }) + data = result.data + } + } this.inQueue = data.inQueue if (data.inQueue) { this.timeoutAt = data.timeoutAt @@ -171,6 +184,7 @@ ${hashText} this.timeoutAt = null this.contributing = false this.inQueue = false + this.authToken = null } catch (err) { console.log('Error making contribution') console.log(err) @@ -248,7 +262,7 @@ ${hashText} async auth() { const { data } = await this.client.send('user.register') - localStorage.setItem('authToken', data.token) + sessionStorage.setItem('authToken', data.token) this.authToken = data.token this.userId = data.userId } From 08b3df7ea28696020fc3e647d51170133acaed9e Mon Sep 17 00:00:00 2001 From: Nico Serrano Date: Wed, 12 Jul 2023 21:36:27 -0500 Subject: [PATCH 10/15] frontend(feat): use user entropy in contribution --- packages/frontend/src/components/LoginPanel.tsx | 2 +- packages/frontend/src/contexts/Ceremony.js | 11 +++++------ packages/frontend/src/contexts/Entropy.js | 2 +- packages/frontend/src/types/ceremony.d.ts | 5 +++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/frontend/src/components/LoginPanel.tsx b/packages/frontend/src/components/LoginPanel.tsx index 2cfd4b0..45cdc6a 100644 --- a/packages/frontend/src/components/LoginPanel.tsx +++ b/packages/frontend/src/components/LoginPanel.tsx @@ -23,7 +23,7 @@ const LoginPanel = observer((props: any) => { } const onClickJoin = () => { - ceremony.join(name) + ceremony.join(name, entropy.generateEntropy()) console.log('join ceremony') } diff --git a/packages/frontend/src/contexts/Ceremony.js b/packages/frontend/src/contexts/Ceremony.js index 027f2e8..95f5cd4 100644 --- a/packages/frontend/src/contexts/Ceremony.js +++ b/packages/frontend/src/contexts/Ceremony.js @@ -13,6 +13,7 @@ export default class Queue { ceremonyState = {} queueLength = 0 timeoutAt = null + entropy = null contributing = false contributionName = null contributionHashes = null @@ -106,9 +107,10 @@ ${hashText} this.ingestState(data) } - async join(name) { + async join(name, entropy) { this.contributionHashes = null this.contributionName = name.trim() + this.entropy = entropy // join the queue const { data: _data } = await this.client.send('ceremony.join', { token: this.authToken, @@ -159,11 +161,7 @@ ${hashText} latest, out, this.contributionName || 'anonymous contributor', - Array(32) - .fill(null) - // TODO NICO: use the generated entropy - .map(() => randomf(2n ** 256n)) - .join('') + this.entropy ) if (this.activeContributor !== this.userId) break this.updateContributionStatus(`Uploading ${circuitName} contribution`) @@ -185,6 +183,7 @@ ${hashText} this.contributing = false this.inQueue = false this.authToken = null + this.entropy = null } catch (err) { console.log('Error making contribution') console.log(err) diff --git a/packages/frontend/src/contexts/Entropy.js b/packages/frontend/src/contexts/Entropy.js index c42f0c3..6a59da9 100644 --- a/packages/frontend/src/contexts/Entropy.js +++ b/packages/frontend/src/contexts/Entropy.js @@ -39,7 +39,7 @@ export default class Entropy { ) const expandedEntropyInt = BigInt('0x' + hex96) const secretInt = expandedEntropyInt % CURVE.r - const secretHex = secretInt.toString(16).padStart(64, '0') + const secretHex = secretInt.toString(16).padStart(32, '0') return secretHex } } diff --git a/packages/frontend/src/types/ceremony.d.ts b/packages/frontend/src/types/ceremony.d.ts index 24569b9..ddecdfe 100644 --- a/packages/frontend/src/types/ceremony.d.ts +++ b/packages/frontend/src/types/ceremony.d.ts @@ -186,6 +186,7 @@ export interface Queue { queueLength: number timeoutAt: number activeContributor: string + entropy: string contributing: boolean contributionName: string contributionHashes: string[] @@ -198,7 +199,7 @@ export interface Queue { contributionUpdates: any[] contributionText: string - join(name: string): void + join(name: string, entropy: string): void stopKeepAlive() auth() load() @@ -207,7 +208,7 @@ export interface Queue { export interface Entropy { secret: string setSecret(secret: string): void - generateEntropy(): void + generateEntropy(): string } declare interface State { From 0c7b963280c1985e04921169826f26ea7889156d Mon Sep 17 00:00:00 2001 From: Nico Serrano Date: Thu, 13 Jul 2023 12:56:23 -0500 Subject: [PATCH 11/15] frontend(feat): use different entropy for each circuit --- .../frontend/src/components/LoginPanel.tsx | 2 +- packages/frontend/src/contexts/Ceremony.js | 7 ++- packages/frontend/src/contexts/Entropy.js | 58 +++++++++++-------- packages/frontend/src/types/ceremony.d.ts | 7 ++- 4 files changed, 46 insertions(+), 28 deletions(-) diff --git a/packages/frontend/src/components/LoginPanel.tsx b/packages/frontend/src/components/LoginPanel.tsx index 45cdc6a..2df468f 100644 --- a/packages/frontend/src/components/LoginPanel.tsx +++ b/packages/frontend/src/components/LoginPanel.tsx @@ -23,7 +23,7 @@ const LoginPanel = observer((props: any) => { } const onClickJoin = () => { - ceremony.join(name, entropy.generateEntropy()) + ceremony.join(name, entropy.generateEntropy(ceremony.numberOfCircuits)) console.log('join ceremony') } diff --git a/packages/frontend/src/contexts/Ceremony.js b/packages/frontend/src/contexts/Ceremony.js index 95f5cd4..a4cf2c5 100644 --- a/packages/frontend/src/contexts/Ceremony.js +++ b/packages/frontend/src/contexts/Ceremony.js @@ -18,6 +18,7 @@ export default class Queue { contributionName = null contributionHashes = null loadingInitial = true + numberOfCircuits = 0 inQueue = false queueEntry = null activeQueueEntry = null @@ -79,6 +80,7 @@ ${hashText} data = result.data } } + this.numberOfCircuits = Object.keys(data.latestContributions).length this.inQueue = data.inQueue if (data.inQueue) { this.timeoutAt = data.timeoutAt @@ -149,6 +151,7 @@ ${hashText} ) const uploadPromises = [] const contributionHashes = {} + let i = 0 for (const [circuitName, id] of Object.entries( data.latestContributions )) { @@ -161,12 +164,13 @@ ${hashText} latest, out, this.contributionName || 'anonymous contributor', - this.entropy + this.entropy[i] ) if (this.activeContributor !== this.userId) break this.updateContributionStatus(`Uploading ${circuitName} contribution`) uploadPromises.push(this.uploadContribution(out.data, circuitName)) contributionHashes[circuitName] = formatHash(hash) + i = i + 1 } try { await Promise.all(uploadPromises) @@ -181,6 +185,7 @@ ${hashText} this.stopKeepalive() this.timeoutAt = null this.contributing = false + this.numberOfCircuits = 0 this.inQueue = false this.authToken = null this.entropy = null diff --git a/packages/frontend/src/contexts/Entropy.js b/packages/frontend/src/contexts/Entropy.js index 6a59da9..ce1ea83 100644 --- a/packages/frontend/src/contexts/Entropy.js +++ b/packages/frontend/src/contexts/Entropy.js @@ -15,31 +15,43 @@ export default class Entropy { this.secret = secret } - generateEntropy() { + generateEntropy(numberOfCircuits) { const generatedEntropyAsBytes = Uint8Array.from( this.secret.split('').map((x) => x.charCodeAt(0)) ) - const randomEntropyAsBytes = randomBytes(32) - const entropyAsBytes = new Uint8Array( - generatedEntropyAsBytes.length + randomEntropyAsBytes.length - ) - entropyAsBytes.set(generatedEntropyAsBytes) - entropyAsBytes.set(randomEntropyAsBytes, generatedEntropyAsBytes.length) - /* - In order to reduce modulo-bias in the entropy (w.r.t. the curve order): - it is expanded out (and mixed) to at least 48 bytes before being reduced mod curve order. - This exact technique is the RECOMMENDED means of obtaining a ~uniformly random F_r element according to - the IRTF BLS signature specs: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-05#section-2.3 - */ - const salt = randomBytes(32) - const expandedEntropy = hkdf(sha256, entropyAsBytes, salt, '', 48) - const hex96 = expandedEntropy.reduce( - (str, byte) => str + byte.toString(16).padStart(2, '0'), - '' - ) - const expandedEntropyInt = BigInt('0x' + hex96) - const secretInt = expandedEntropyInt % CURVE.r - const secretHex = secretInt.toString(16).padStart(32, '0') - return secretHex + let secrets = [] + for ( + let i = 0, ni = generatedEntropyAsBytes.length; + i < ni; + i += numberOfCircuits + ) { + const entropyChunk = generatedEntropyAsBytes.slice( + i, + i + numberOfCircuits + ) + const randomEntropyAsBytes = randomBytes(32) + const entropyAsBytes = new Uint8Array( + entropyChunk.length + randomEntropyAsBytes.length + ) + entropyAsBytes.set(entropyChunk) + entropyAsBytes.set(randomEntropyAsBytes, entropyChunk.length) + /* + In order to reduce modulo-bias in the entropy (w.r.t. the curve order): + it is expanded out (and mixed) to at least 48 bytes before being reduced mod curve order. + This exact technique is the RECOMMENDED means of obtaining a ~uniformly random F_r element according to + the IRTF BLS signature specs: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-05#section-2.3 + */ + const salt = randomBytes(32) + const expandedEntropy = hkdf(sha256, entropyAsBytes, salt, '', 48) + const hex96 = expandedEntropy.reduce( + (str, byte) => str + byte.toString(16).padStart(2, '0'), + '' + ) + const expandedEntropyInt = BigInt('0x' + hex96) + const secretInt = expandedEntropyInt % CURVE.r + const secretHex = secretInt.toString(16).padStart(32, '0') + secrets.push(secretHex) + } + return secrets } } diff --git a/packages/frontend/src/types/ceremony.d.ts b/packages/frontend/src/types/ceremony.d.ts index ddecdfe..f96f378 100644 --- a/packages/frontend/src/types/ceremony.d.ts +++ b/packages/frontend/src/types/ceremony.d.ts @@ -186,11 +186,12 @@ export interface Queue { queueLength: number timeoutAt: number activeContributor: string - entropy: string + entropy: string[] contributing: boolean contributionName: string contributionHashes: string[] loadingInitial: boolean + numberOfCircuits: number inQueue: boolean isFinished: boolean project: string @@ -199,7 +200,7 @@ export interface Queue { contributionUpdates: any[] contributionText: string - join(name: string, entropy: string): void + join(name: string, entropy: string[]): void stopKeepAlive() auth() load() @@ -208,7 +209,7 @@ export interface Queue { export interface Entropy { secret: string setSecret(secret: string): void - generateEntropy(): string + generateEntropy(numberOfCircuits: number): string[] } declare interface State { From 7964aaaeebce37ea534dc636f9b8b35d68492fdb Mon Sep 17 00:00:00 2001 From: Nico Serrano Date: Thu, 13 Jul 2023 13:38:23 -0500 Subject: [PATCH 12/15] frontend(feat): load contributions in home page --- .../frontend/src/components/CircuitsTable.tsx | 203 +++++++++--------- packages/frontend/src/types/ceremony.d.ts | 1 + 2 files changed, 108 insertions(+), 96 deletions(-) diff --git a/packages/frontend/src/components/CircuitsTable.tsx b/packages/frontend/src/components/CircuitsTable.tsx index 1ff6b8c..15c5177 100644 --- a/packages/frontend/src/components/CircuitsTable.tsx +++ b/packages/frontend/src/components/CircuitsTable.tsx @@ -1,23 +1,23 @@ -import { useContext, useState } from "react"; +import { useContext, useEffect, useState } from 'react' import { - accentColor, - textColor, - darkBorder, - NormalBodyText, - darkerBackground, - H3Title, - } from "../styles"; + accentColor, + textColor, + darkBorder, + NormalBodyText, + darkerBackground, + H3Title, +} from '../styles' //import './styles.css'; -import { Circuit, State } from "../types/ceremony"; -import { Button } from '@mui/material'; -import styled from 'styled-components'; -import { CopyToClipboard } from 'react-copy-to-clipboard'; -import ViewLog from './ViewLog'; -import moment from 'moment'; -import { CopyIcon } from '../icons'; -import Blockies from 'react-blockies'; -import state from '../contexts/state'; -import { observer } from 'mobx-react-lite'; +import { Circuit, State } from '../types/ceremony' +import { Button } from '@mui/material' +import styled from 'styled-components' +import { CopyToClipboard } from 'react-copy-to-clipboard' +import ViewLog from './ViewLog' +import moment from 'moment' +import { CopyIcon } from '../icons' +import Blockies from 'react-blockies' +import state from '../contexts/state' +import { observer } from 'mobx-react-lite' const HeaderCell = styled.div` display: flex; @@ -29,55 +29,63 @@ const HeaderCell = styled.div` font-size: 16px; color: inherit; padding: 24px; - background-color: #0E2936; + background-color: #0e2936; ` -const TableRow = styled.div<{ completed?: boolean}>` +const TableRow = styled.div<{ completed?: boolean }>` display: flex; width: 100%; - color: ${(props) => props.completed ? accentColor: textColor}; + color: ${(props) => (props.completed ? accentColor : textColor)}; ` const CircuitsTable = observer(() => { - const { ceremony } = useContext(state) as State; - const [modalOpen, setModalOpen] = useState(false); - const [modalContent, setModalContent] = useState({title: (<>), content: (<>)}); - - const { ceremonyState, contributionHashes, authenticated } = ceremony; - const { circuitStats } = ceremonyState; - - const closeTranscript = () => {setModalOpen(false)}; + const { ceremony } = useContext(state) as State + const [modalOpen, setModalOpen] = useState(false) + const [modalContent, setModalContent] = useState({ + title: <>, + content: <>, + }) + + const { ceremonyState, contributionHashes, authenticated } = ceremony + const { circuitStats } = ceremonyState + + useEffect(() => { + ;(async () => { + await ceremony.connect() + })() + }, []) + + const closeTranscript = () => { + setModalOpen(false) + } const openTranscript = (title: JSX.Element, content: JSX.Element) => { - setModalContent({title, content}); - setModalOpen(true); - }; - const cellWidths = [ - '105px', - '167px', - '156px', - '140px', - '193px', - ] - const hashKeys = contributionHashes ? Object.keys(contributionHashes) : []; + setModalContent({ title, content }) + setModalOpen(true) + } + const cellWidths = ['105px', '167px', '156px', '140px', '193px'] + const hashKeys = contributionHashes ? Object.keys(contributionHashes) : [] return (
Circuit - Contributions - Average Time + + Contributions + + + Average Time + Transcript - {authenticated ? - (My Hash) - : null - } + {authenticated ? ( + My Hash + ) : null} {(circuitStats || []).map((circuit, index) => renderRow( - circuit, - index < hashKeys.length ? hashKeys[index] : undefined, - circuit.name || index.toString(), - authenticated, - openTranscript, + circuit, + index < hashKeys.length ? hashKeys[index] : undefined, + circuit.name || index.toString(), + authenticated, + openTranscript, cellWidths ) )} @@ -89,7 +97,7 @@ const CircuitsTable = observer(() => { />
) -}); +}) const renderRow = ( circuit: Circuit, @@ -99,41 +107,41 @@ const renderRow = ( showTranscript: (title: JSX.Element, body: JSX.Element) => void, cellWidths: string[] ) => { - const renderHash = (hash: string | undefined) => { - let content = (<>); + let content = <> if (hash && hash?.length > 0) { const hashBlockie = () => ( - + ) content = ( - - + + {/**/} -
{hashBlockie()}
- +
{hashBlockie()}
+ {/*
*/}
{CopyIcon}
- ); + ) } - return ({content}); - }; + return {content} + } const formatDuration = (avgSecs: number) => { - return moment.duration(avgSecs, 'seconds').humanize(); + return moment.duration(avgSecs, 'seconds').humanize() } const formatTranscript = (circuit: Circuit, index: string) => { - const { name } = circuit; + const { name } = circuit // TODO How to get transcript? - const transcript = ""; + const transcript = '' //if (!transcript) return; @@ -144,19 +152,18 @@ const renderRow = ( {`Circuit File: ${name}`} {/*{`Constraints: ${numConstraints}`}*/}
- ); + ) const lineStyle = { marginBlockStart: '0em', - marginBlockEnd: '0em' - }; + marginBlockEnd: '0em', + } const linesToJsx = (content: string) => { - const lines: string[] = content.split('\n'); + const lines: string[] = content.split('\n') console.log(`lines: ${lines}`) - const body= lines.map(v => - (

{v}

)); - return (
{body}
); - }; + const body = lines.map((v) =>

{v}

) + return
{body}
+ } const copyStyle = { display: 'flex', @@ -165,10 +172,10 @@ const renderRow = ( background: darkerBackground, borderRadius: '30px', marginBottom: '41px', - }; + } const body = (
- + Copy to clipboard {CopyIcon} @@ -176,12 +183,12 @@ const renderRow = ( {linesToJsx(transcript || '')}
- ); + ) - showTranscript(title, body); + showTranscript(title, body) } - const completed = !!contributionHash; + const completed = !!contributionHash return ( @@ -190,26 +197,30 @@ const renderRow = ( {completed ? 'Y' : 'N'} - {/* formatDuration(circuit.averageSecondsPerContribution)<< - - {isSignedIn ? + {isSignedIn ? ( {renderHash(contributionHash)} - : + + ) : ( <> - } + )} - ); -}; + ) +} -export default CircuitsTable; +export default CircuitsTable diff --git a/packages/frontend/src/types/ceremony.d.ts b/packages/frontend/src/types/ceremony.d.ts index f96f378..6e7c4bf 100644 --- a/packages/frontend/src/types/ceremony.d.ts +++ b/packages/frontend/src/types/ceremony.d.ts @@ -204,6 +204,7 @@ export interface Queue { stopKeepAlive() auth() load() + connect() } export interface Entropy { From 429995a522318ec147dbaed6b2c524c163ee3388 Mon Sep 17 00:00:00 2001 From: Nico Serrano Date: Thu, 13 Jul 2023 17:37:11 -0500 Subject: [PATCH 13/15] Revert "frontend(feat): load contributions in home page" This reverts commit 7964aaaeebce37ea534dc636f9b8b35d68492fdb. --- .../frontend/src/components/CircuitsTable.tsx | 203 +++++++++--------- packages/frontend/src/types/ceremony.d.ts | 1 - 2 files changed, 96 insertions(+), 108 deletions(-) diff --git a/packages/frontend/src/components/CircuitsTable.tsx b/packages/frontend/src/components/CircuitsTable.tsx index 15c5177..1ff6b8c 100644 --- a/packages/frontend/src/components/CircuitsTable.tsx +++ b/packages/frontend/src/components/CircuitsTable.tsx @@ -1,23 +1,23 @@ -import { useContext, useEffect, useState } from 'react' +import { useContext, useState } from "react"; import { - accentColor, - textColor, - darkBorder, - NormalBodyText, - darkerBackground, - H3Title, -} from '../styles' + accentColor, + textColor, + darkBorder, + NormalBodyText, + darkerBackground, + H3Title, + } from "../styles"; //import './styles.css'; -import { Circuit, State } from '../types/ceremony' -import { Button } from '@mui/material' -import styled from 'styled-components' -import { CopyToClipboard } from 'react-copy-to-clipboard' -import ViewLog from './ViewLog' -import moment from 'moment' -import { CopyIcon } from '../icons' -import Blockies from 'react-blockies' -import state from '../contexts/state' -import { observer } from 'mobx-react-lite' +import { Circuit, State } from "../types/ceremony"; +import { Button } from '@mui/material'; +import styled from 'styled-components'; +import { CopyToClipboard } from 'react-copy-to-clipboard'; +import ViewLog from './ViewLog'; +import moment from 'moment'; +import { CopyIcon } from '../icons'; +import Blockies from 'react-blockies'; +import state from '../contexts/state'; +import { observer } from 'mobx-react-lite'; const HeaderCell = styled.div` display: flex; @@ -29,63 +29,55 @@ const HeaderCell = styled.div` font-size: 16px; color: inherit; padding: 24px; - background-color: #0e2936; + background-color: #0E2936; ` -const TableRow = styled.div<{ completed?: boolean }>` +const TableRow = styled.div<{ completed?: boolean}>` display: flex; width: 100%; - color: ${(props) => (props.completed ? accentColor : textColor)}; + color: ${(props) => props.completed ? accentColor: textColor}; ` const CircuitsTable = observer(() => { - const { ceremony } = useContext(state) as State - const [modalOpen, setModalOpen] = useState(false) - const [modalContent, setModalContent] = useState({ - title: <>, - content: <>, - }) - - const { ceremonyState, contributionHashes, authenticated } = ceremony - const { circuitStats } = ceremonyState - - useEffect(() => { - ;(async () => { - await ceremony.connect() - })() - }, []) - - const closeTranscript = () => { - setModalOpen(false) - } + const { ceremony } = useContext(state) as State; + const [modalOpen, setModalOpen] = useState(false); + const [modalContent, setModalContent] = useState({title: (<>), content: (<>)}); + + const { ceremonyState, contributionHashes, authenticated } = ceremony; + const { circuitStats } = ceremonyState; + + const closeTranscript = () => {setModalOpen(false)}; const openTranscript = (title: JSX.Element, content: JSX.Element) => { - setModalContent({ title, content }) - setModalOpen(true) - } - const cellWidths = ['105px', '167px', '156px', '140px', '193px'] - const hashKeys = contributionHashes ? Object.keys(contributionHashes) : [] + setModalContent({title, content}); + setModalOpen(true); + }; + const cellWidths = [ + '105px', + '167px', + '156px', + '140px', + '193px', + ] + const hashKeys = contributionHashes ? Object.keys(contributionHashes) : []; return (
Circuit - - Contributions - - - Average Time - + Contributions + Average Time Transcript - {authenticated ? ( - My Hash - ) : null} + {authenticated ? + (My Hash) + : null + } {(circuitStats || []).map((circuit, index) => renderRow( - circuit, - index < hashKeys.length ? hashKeys[index] : undefined, - circuit.name || index.toString(), - authenticated, - openTranscript, + circuit, + index < hashKeys.length ? hashKeys[index] : undefined, + circuit.name || index.toString(), + authenticated, + openTranscript, cellWidths ) )} @@ -97,7 +89,7 @@ const CircuitsTable = observer(() => { />
) -}) +}); const renderRow = ( circuit: Circuit, @@ -107,41 +99,41 @@ const renderRow = ( showTranscript: (title: JSX.Element, body: JSX.Element) => void, cellWidths: string[] ) => { + const renderHash = (hash: string | undefined) => { - let content = <> + let content = (<>); if (hash && hash?.length > 0) { const hashBlockie = () => ( - + ) content = ( - - + + {/**/} -
{hashBlockie()}
- +
{hashBlockie()}
+ {/*
*/}
{CopyIcon}
- ) + ); } - return {content} - } + return ({content}); + }; const formatDuration = (avgSecs: number) => { - return moment.duration(avgSecs, 'seconds').humanize() + return moment.duration(avgSecs, 'seconds').humanize(); } const formatTranscript = (circuit: Circuit, index: string) => { - const { name } = circuit + const { name } = circuit; // TODO How to get transcript? - const transcript = '' + const transcript = ""; //if (!transcript) return; @@ -152,18 +144,19 @@ const renderRow = ( {`Circuit File: ${name}`} {/*{`Constraints: ${numConstraints}`}*/}
- ) + ); const lineStyle = { marginBlockStart: '0em', - marginBlockEnd: '0em', - } + marginBlockEnd: '0em' + }; const linesToJsx = (content: string) => { - const lines: string[] = content.split('\n') + const lines: string[] = content.split('\n'); console.log(`lines: ${lines}`) - const body = lines.map((v) =>

{v}

) - return
{body}
- } + const body= lines.map(v => + (

{v}

)); + return (
{body}
); + }; const copyStyle = { display: 'flex', @@ -172,10 +165,10 @@ const renderRow = ( background: darkerBackground, borderRadius: '30px', marginBottom: '41px', - } + }; const body = (
- + Copy to clipboard {CopyIcon} @@ -183,12 +176,12 @@ const renderRow = ( {linesToJsx(transcript || '')}
- ) + ); - showTranscript(title, body) + showTranscript(title, body); } - const completed = !!contributionHash + const completed = !!contributionHash; return ( @@ -197,30 +190,26 @@ const renderRow = ( {completed ? 'Y' : 'N'} - {/* formatDuration(circuit.averageSecondsPerContribution)<< - - {isSignedIn ? ( + {isSignedIn ? {renderHash(contributionHash)} - - ) : ( + : <> - )} + } - ) -} + ); +}; -export default CircuitsTable +export default CircuitsTable; diff --git a/packages/frontend/src/types/ceremony.d.ts b/packages/frontend/src/types/ceremony.d.ts index 6e7c4bf..f96f378 100644 --- a/packages/frontend/src/types/ceremony.d.ts +++ b/packages/frontend/src/types/ceremony.d.ts @@ -204,7 +204,6 @@ export interface Queue { stopKeepAlive() auth() load() - connect() } export interface Entropy { From dad8da78ab2403748147867258176504859d8042 Mon Sep 17 00:00:00 2001 From: Nico Serrano Date: Thu, 13 Jul 2023 18:25:31 -0500 Subject: [PATCH 14/15] frontend(feat): show hash of participant contribution --- .../frontend/src/components/CircuitsTable.tsx | 199 +++++++++--------- 1 file changed, 99 insertions(+), 100 deletions(-) diff --git a/packages/frontend/src/components/CircuitsTable.tsx b/packages/frontend/src/components/CircuitsTable.tsx index 1ff6b8c..8570a5f 100644 --- a/packages/frontend/src/components/CircuitsTable.tsx +++ b/packages/frontend/src/components/CircuitsTable.tsx @@ -1,23 +1,23 @@ -import { useContext, useState } from "react"; +import { useContext, useState } from 'react' import { - accentColor, - textColor, - darkBorder, - NormalBodyText, - darkerBackground, - H3Title, - } from "../styles"; + accentColor, + textColor, + darkBorder, + NormalBodyText, + darkerBackground, + H3Title, +} from '../styles' //import './styles.css'; -import { Circuit, State } from "../types/ceremony"; -import { Button } from '@mui/material'; -import styled from 'styled-components'; -import { CopyToClipboard } from 'react-copy-to-clipboard'; -import ViewLog from './ViewLog'; -import moment from 'moment'; -import { CopyIcon } from '../icons'; -import Blockies from 'react-blockies'; -import state from '../contexts/state'; -import { observer } from 'mobx-react-lite'; +import { Circuit, State } from '../types/ceremony' +import { Button } from '@mui/material' +import styled from 'styled-components' +import { CopyToClipboard } from 'react-copy-to-clipboard' +import ViewLog from './ViewLog' +import moment from 'moment' +import { CopyIcon } from '../icons' +import Blockies from 'react-blockies' +import state from '../contexts/state' +import { observer } from 'mobx-react-lite' const HeaderCell = styled.div` display: flex; @@ -29,55 +29,55 @@ const HeaderCell = styled.div` font-size: 16px; color: inherit; padding: 24px; - background-color: #0E2936; + background-color: #0e2936; ` -const TableRow = styled.div<{ completed?: boolean}>` +const TableRow = styled.div<{ completed?: boolean }>` display: flex; width: 100%; - color: ${(props) => props.completed ? accentColor: textColor}; + color: ${(props) => (props.completed ? accentColor : textColor)}; ` const CircuitsTable = observer(() => { - const { ceremony } = useContext(state) as State; - const [modalOpen, setModalOpen] = useState(false); - const [modalContent, setModalContent] = useState({title: (<>), content: (<>)}); - - const { ceremonyState, contributionHashes, authenticated } = ceremony; - const { circuitStats } = ceremonyState; - - const closeTranscript = () => {setModalOpen(false)}; + const { ceremony } = useContext(state) as State + const [modalOpen, setModalOpen] = useState(false) + const [modalContent, setModalContent] = useState({ + title: <>, + content: <>, + }) + + const { ceremonyState, contributionHashes, authenticated } = ceremony + const { circuitStats } = ceremonyState + + const closeTranscript = () => { + setModalOpen(false) + } const openTranscript = (title: JSX.Element, content: JSX.Element) => { - setModalContent({title, content}); - setModalOpen(true); - }; - const cellWidths = [ - '105px', - '167px', - '156px', - '140px', - '193px', - ] - const hashKeys = contributionHashes ? Object.keys(contributionHashes) : []; + setModalContent({ title, content }) + setModalOpen(true) + } + const cellWidths = ['105px', '167px', '156px', '140px', '193px'] + const hashKeys = contributionHashes ? Object.values(contributionHashes) : [] return (
Circuit - Contributions - Average Time + + Contributions + + + Average Time + Transcript - {authenticated ? - (My Hash) - : null - } + My Hash {(circuitStats || []).map((circuit, index) => renderRow( - circuit, - index < hashKeys.length ? hashKeys[index] : undefined, - circuit.name || index.toString(), - authenticated, - openTranscript, + circuit, + index < hashKeys.length ? hashKeys[index] : undefined, + circuit.name || index.toString(), + authenticated, + openTranscript, cellWidths ) )} @@ -89,7 +89,7 @@ const CircuitsTable = observer(() => { />
) -}); +}) const renderRow = ( circuit: Circuit, @@ -99,41 +99,41 @@ const renderRow = ( showTranscript: (title: JSX.Element, body: JSX.Element) => void, cellWidths: string[] ) => { - const renderHash = (hash: string | undefined) => { - let content = (<>); + let content = <> if (hash && hash?.length > 0) { const hashBlockie = () => ( - + ) content = ( - - + + {/**/} -
{hashBlockie()}
- +
{hashBlockie()}
+ {/*
*/} -
{CopyIcon}
+
{CopyIcon}
- ); + ) } - return ({content}); - }; + return {content} + } const formatDuration = (avgSecs: number) => { - return moment.duration(avgSecs, 'seconds').humanize(); + return moment.duration(avgSecs, 'seconds').humanize() } const formatTranscript = (circuit: Circuit, index: string) => { - const { name } = circuit; + const { name } = circuit // TODO How to get transcript? - const transcript = ""; + const transcript = '' //if (!transcript) return; @@ -144,19 +144,18 @@ const renderRow = ( {`Circuit File: ${name}`} {/*{`Constraints: ${numConstraints}`}*/}
- ); + ) const lineStyle = { marginBlockStart: '0em', - marginBlockEnd: '0em' - }; + marginBlockEnd: '0em', + } const linesToJsx = (content: string) => { - const lines: string[] = content.split('\n'); + const lines: string[] = content.split('\n') console.log(`lines: ${lines}`) - const body= lines.map(v => - (

{v}

)); - return (
{body}
); - }; + const body = lines.map((v) =>

{v}

) + return
{body}
+ } const copyStyle = { display: 'flex', @@ -165,10 +164,10 @@ const renderRow = ( background: darkerBackground, borderRadius: '30px', marginBottom: '41px', - }; + } const body = (
- + Copy to clipboard {CopyIcon} @@ -176,12 +175,12 @@ const renderRow = ( {linesToJsx(transcript || '')}
- ); + ) - showTranscript(title, body); + showTranscript(title, body) } - const completed = !!contributionHash; + const completed = !!contributionHash return ( @@ -190,26 +189,26 @@ const renderRow = ( {completed ? 'Y' : 'N'} - {/* formatDuration(circuit.averageSecondsPerContribution)<< - - {isSignedIn ? - - {renderHash(contributionHash)} - : - <> - } + + {renderHash(contributionHash)} + - ); -}; + ) +} -export default CircuitsTable; +export default CircuitsTable From 8067dc5c455dee93791f4407835af87216e3becb Mon Sep 17 00:00:00 2001 From: Nico Serrano Date: Thu, 13 Jul 2023 18:29:17 -0500 Subject: [PATCH 15/15] frontend(feat): show hash in tooltip --- packages/frontend/src/components/CircuitsTable.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/frontend/src/components/CircuitsTable.tsx b/packages/frontend/src/components/CircuitsTable.tsx index 8570a5f..2926e4d 100644 --- a/packages/frontend/src/components/CircuitsTable.tsx +++ b/packages/frontend/src/components/CircuitsTable.tsx @@ -9,7 +9,7 @@ import { } from '../styles' //import './styles.css'; import { Circuit, State } from '../types/ceremony' -import { Button } from '@mui/material' +import { Tooltip, Button } from '@mui/material' import styled from 'styled-components' import { CopyToClipboard } from 'react-copy-to-clipboard' import ViewLog from './ViewLog' @@ -103,7 +103,11 @@ const renderRow = ( let content = <> if (hash && hash?.length > 0) { const hashBlockie = () => ( - + +
+ +
+
) content = (