-
Notifications
You must be signed in to change notification settings - Fork 256
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
PXE running in a browser via a vite app. In order to achieve this, several things had to be implemented/altered: - Original LMDB storage was not compatible with the browser. Also its very nature made most get operations synchronous, which is pretty weird for a DB. A new `AztecAsyncKVStore` has been created, offering *almost* the same interface but with async methods for everything. This store is backed by IndexedDB, which is compatible with most modern browsers. The LMDB backed store has been updated to also support the async interface, so now `PxeKvDatabase` can run with either. - In order to support testing in the browser, `@aztec/kv-store` tests have been moved from jest to mocha - Most imports of `fs/promises` have been replaced with `import { promises as fs } from 'fs';` which can be polyfilled by [vite-plugin-node-polyfills](https://www.npmjs.com/package/vite-plugin-node-polyfills). - Several packages (such as `simulator`) have been split to allow importing the minimal set of APIs required for PXE to do its client side thing, avoiding unneeded (and browser-incompatible) APIs and files. - PXE package now generates a static info file (version and name) at compilation time, to avoid reading it from the package.json file (which cannot be done in the browser). A bundler was considered, but this is simpler and more flexible. - A new flag has been added to the sandbox, so it can run without a PXE (`--sandbox.noPXE`). This is very useful to deploy a "network in a box" that can be used to test apps that provide their own PXE implementation. - The vite box is very rough and mostly mimics what the `react` one does, but shows how a hypothetical dapp could be bundled. --------- Co-authored-by: Alex Gherghisan <[email protected]>
- Loading branch information
Showing
158 changed files
with
7,010 additions
and
1,869 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# Logs | ||
logs | ||
*.log | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
pnpm-debug.log* | ||
lerna-debug.log* | ||
|
||
node_modules | ||
dist | ||
dist-ssr | ||
*.local | ||
|
||
# Editor directories and files | ||
.vscode/* | ||
!.vscode/extensions.json | ||
.idea | ||
.DS_Store | ||
*.suo | ||
*.ntvs* | ||
*.njsproj | ||
*.sln | ||
*.sw? | ||
|
||
artifacts/* | ||
codegenCache.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# React + TypeScript + Vite | ||
|
||
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. | ||
|
||
Currently, two official plugins are available: | ||
|
||
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh | ||
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh | ||
|
||
## Expanding the ESLint configuration | ||
|
||
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules: | ||
|
||
- Configure the top-level `parserOptions` property like this: | ||
|
||
```js | ||
export default tseslint.config({ | ||
languageOptions: { | ||
// other options... | ||
parserOptions: { | ||
project: ['./tsconfig.node.json', './tsconfig.app.json'], | ||
tsconfigRootDir: import.meta.dirname, | ||
}, | ||
}, | ||
}) | ||
``` | ||
|
||
- Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked` | ||
- Optionally add `...tseslint.configs.stylisticTypeChecked` | ||
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and update the config: | ||
|
||
```js | ||
// eslint.config.js | ||
import react from 'eslint-plugin-react' | ||
|
||
export default tseslint.config({ | ||
// Set the react version | ||
settings: { react: { version: '18.3' } }, | ||
plugins: { | ||
// Add the react plugin | ||
react, | ||
}, | ||
rules: { | ||
// other rules... | ||
// Enable its recommended rules | ||
...react.configs.recommended.rules, | ||
...react.configs['jsx-runtime'].rules, | ||
}, | ||
}) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import js from '@eslint/js' | ||
import globals from 'globals' | ||
import reactHooks from 'eslint-plugin-react-hooks' | ||
import reactRefresh from 'eslint-plugin-react-refresh' | ||
import tseslint from 'typescript-eslint' | ||
|
||
export default tseslint.config( | ||
{ ignores: ['dist'] }, | ||
{ | ||
extends: [js.configs.recommended, ...tseslint.configs.recommended], | ||
files: ['**/*.{ts,tsx}'], | ||
languageOptions: { | ||
ecmaVersion: 2020, | ||
globals: globals.browser, | ||
}, | ||
plugins: { | ||
'react-hooks': reactHooks, | ||
'react-refresh': reactRefresh, | ||
}, | ||
rules: { | ||
...reactHooks.configs.recommended.rules, | ||
'react-refresh/only-export-components': [ | ||
'warn', | ||
{ allowConstantExport: true }, | ||
], | ||
}, | ||
}, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
<!doctype html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>Private Token Noir Smart Contract</title> | ||
<style> | ||
#root { | ||
width: 100%; | ||
text-align: center; | ||
} | ||
|
||
body { | ||
display: flex; | ||
place-items: center; | ||
background: linear-gradient(#f6fbfc, #d8d4e7); | ||
min-height: 100vh; | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<div id="root"></div> | ||
<script type="module" src="/src/main.tsx"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
{ | ||
"name": "vite", | ||
"private": true, | ||
"version": "0.0.0", | ||
"type": "module", | ||
"scripts": { | ||
"compile": "cd src/contracts && ${AZTEC_NARGO:-aztec-nargo} compile --silence-warnings", | ||
"codegen": "${AZTEC_BUILDER:-aztec} codegen src/contracts/target -o artifacts", | ||
"clean": "rm -rf ./dist .tsbuildinfo ./artifacts ./src/contracts/target", | ||
"prep": "yarn clean && yarn compile && yarn codegen", | ||
"dev": "vite", | ||
"build": "tsc -b && vite build", | ||
"lint": "eslint .", | ||
"preview": "vite preview" | ||
}, | ||
"dependencies": { | ||
"@aztec/accounts": "portal:../../../yarn-project/accounts", | ||
"@aztec/aztec.js": "portal:../../../yarn-project/aztec.js", | ||
"@aztec/circuit-types": "portal:../../../yarn-project/circuit-types", | ||
"@aztec/key-store": "link:../../../yarn-project/key-store", | ||
"@aztec/kv-store": "portal:../../../yarn-project/kv-store", | ||
"@aztec/pxe": "link:../../../yarn-project/pxe", | ||
"@noir-lang/acvm_js": "link:../../../noir/packages/acvm_js", | ||
"@noir-lang/noirc_abi": "link:../../../noir/packages/noirc_abi", | ||
"buffer": "^6.0.3", | ||
"react": "^18.3.1", | ||
"react-dom": "^18.3.1", | ||
"react-toastify": "^10.0.6" | ||
}, | ||
"devDependencies": { | ||
"@eslint/js": "^9.13.0", | ||
"@types/react": "^18.3.12", | ||
"@types/react-dom": "^18.3.1", | ||
"@vitejs/plugin-react-swc": "^3.5.0", | ||
"eslint": "^9.13.0", | ||
"eslint-plugin-react-hooks": "^5.0.0", | ||
"eslint-plugin-react-refresh": "^0.4.14", | ||
"globals": "^15.11.0", | ||
"memfs": "^4.14.0", | ||
"node-stdlib-browser": "^1.3.0", | ||
"typescript": "~5.6.2", | ||
"typescript-eslint": "^8.11.0", | ||
"vite": "^5.4.10", | ||
"vite-plugin-externalize-deps": "^0.8.0", | ||
"vite-plugin-node-polyfills": "^0.22.0", | ||
"vite-plugin-top-level-await": "^1.4.4" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
#root { | ||
max-width: 1280px; | ||
margin: 0 auto; | ||
padding: 2rem; | ||
text-align: center; | ||
} | ||
|
||
.logo { | ||
height: 6em; | ||
padding: 1.5em; | ||
will-change: filter; | ||
transition: filter 300ms; | ||
} | ||
.logo:hover { | ||
filter: drop-shadow(0 0 2em #646cffaa); | ||
} | ||
.logo.react:hover { | ||
filter: drop-shadow(0 0 2em #61dafbaa); | ||
} | ||
|
||
@keyframes logo-spin { | ||
from { | ||
transform: rotate(0deg); | ||
} | ||
to { | ||
transform: rotate(360deg); | ||
} | ||
} | ||
|
||
@media (prefers-reduced-motion: no-preference) { | ||
a:nth-of-type(2) .logo { | ||
animation: logo-spin infinite 20s linear; | ||
} | ||
} | ||
|
||
.card { | ||
padding: 2em; | ||
} | ||
|
||
.read-the-docs { | ||
color: #888; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { ToastContainer } from "react-toastify"; | ||
import "react-toastify/dist/ReactToastify.css"; | ||
import "./App.css"; | ||
import { Home } from "./pages/home"; | ||
import { useEffect, useState } from "react"; | ||
import initACVM from "@noir-lang/acvm_js/web/acvm_js"; | ||
import initABI from "@noir-lang/noirc_abi/web/noirc_abi_wasm"; | ||
import acvmURL from "@noir-lang/acvm_js/web/acvm_js_bg.wasm?url"; | ||
import abiURL from "@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm?url"; | ||
|
||
const InitWasm = ({ children }: any) => { | ||
const [init, setInit] = useState(false); | ||
useEffect(() => { | ||
(async () => { | ||
await Promise.all([ | ||
initACVM(new URL(acvmURL, import.meta.url).toString()), | ||
initABI(new URL(abiURL, import.meta.url).toString()), | ||
]); | ||
setInit(true); | ||
})(); | ||
}, []); | ||
|
||
return <div>{init && children}</div>; | ||
}; | ||
|
||
function App() { | ||
return ( | ||
<InitWasm> | ||
<Home /> | ||
<ToastContainer /> | ||
</InitWasm> | ||
); | ||
} | ||
|
||
export default App; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import { | ||
AztecNode, | ||
Fr, | ||
createDebugLogger, | ||
deriveMasterIncomingViewingSecretKey, | ||
} from "@aztec/aztec.js"; | ||
import { BoxReactContractArtifact } from "../artifacts/BoxReact"; | ||
import { AccountManager } from "@aztec/aztec.js/account"; | ||
import { SingleKeyAccountContract } from "@aztec/accounts/single_key"; | ||
import { createAztecNodeClient } from "@aztec/aztec.js"; | ||
import { PXEService } from "@aztec/pxe/service"; | ||
import { PXEServiceConfig, getPXEServiceConfig } from "@aztec/pxe/config"; | ||
import { KVPxeDatabase } from "@aztec/pxe/database"; | ||
import { TestPrivateKernelProver } from "@aztec/pxe/kernel_prover"; | ||
import { KeyStore } from "@aztec/key-store"; | ||
import { PrivateKernelProver } from "@aztec/circuit-types"; | ||
import { L2TipsStore } from "@aztec/kv-store/stores"; | ||
import { createStore } from "@aztec/kv-store/indexeddb"; | ||
|
||
const SECRET_KEY = Fr.random(); | ||
|
||
export class PrivateEnv { | ||
pxe; | ||
accountContract; | ||
account: AccountManager; | ||
|
||
constructor( | ||
private secretKey: Fr, | ||
private nodeURL: string, | ||
) {} | ||
|
||
async init() { | ||
const config = getPXEServiceConfig(); | ||
config.dataDirectory = "pxe"; | ||
const aztecNode = await createAztecNodeClient(this.nodeURL); | ||
const proofCreator = new TestPrivateKernelProver(); | ||
this.pxe = await this.createPXEService(aztecNode, config, proofCreator); | ||
const encryptionPrivateKey = deriveMasterIncomingViewingSecretKey( | ||
this.secretKey, | ||
); | ||
this.accountContract = new SingleKeyAccountContract(encryptionPrivateKey); | ||
this.account = new AccountManager( | ||
this.pxe, | ||
this.secretKey, | ||
this.accountContract, | ||
); | ||
} | ||
|
||
async createPXEService( | ||
aztecNode: AztecNode, | ||
config: PXEServiceConfig, | ||
proofCreator?: PrivateKernelProver, | ||
) { | ||
const l1Contracts = await aztecNode.getL1ContractAddresses(); | ||
const configWithContracts = { | ||
...config, | ||
l1Contracts, | ||
} as PXEServiceConfig; | ||
|
||
const store = await createStore( | ||
"pxe_data", | ||
configWithContracts, | ||
createDebugLogger("aztec:pxe:data:indexeddb"), | ||
); | ||
|
||
const keyStore = new KeyStore(store); | ||
|
||
const db = await KVPxeDatabase.create(store); | ||
const tips = new L2TipsStore(store, "pxe"); | ||
|
||
const server = new PXEService( | ||
keyStore, | ||
aztecNode, | ||
db, | ||
tips, | ||
proofCreator, | ||
config, | ||
); | ||
await server.start(); | ||
return server; | ||
} | ||
|
||
async getWallet() { | ||
// taking advantage that register is no-op if already registered | ||
return await this.account.register(); | ||
} | ||
} | ||
|
||
export const deployerEnv = new PrivateEnv( | ||
SECRET_KEY, | ||
process.env.PXE_URL || "http://localhost:8080", | ||
); | ||
|
||
const IGNORE_FUNCTIONS = [ | ||
"constructor", | ||
"compute_note_hash_and_optionally_a_nullifier", | ||
"sync_notes", | ||
]; | ||
export const filteredInterface = BoxReactContractArtifact.functions.filter( | ||
(f) => !IGNORE_FUNCTIONS.includes(f.name), | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
[package] | ||
name = "boxreact" | ||
authors = [""] | ||
compiler_version = ">=0.18.0" | ||
type = "contract" | ||
|
||
[dependencies] | ||
aztec = { path = "../../../../../noir-projects/aztec-nr/aztec" } | ||
value_note = { path = "../../../../../noir-projects/aztec-nr/value-note" } |
Oops, something went wrong.