diff --git a/.github/workflows/release-develop.yml b/.github/workflows/release-develop.yml
index 793b57dc7..f2f88e3aa 100644
--- a/.github/workflows/release-develop.yml
+++ b/.github/workflows/release-develop.yml
@@ -31,8 +31,8 @@ jobs:
- name: "Build"
run: npm run build
- - name: Run Lerna Release
- run: npm run publish:canary
+ - name: "Publish nightly"
+ run: npx pkg-pr-new publish './packages/*'
- name: Trigger website build & deployment
env:
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 000000000..ebc5f6f87
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,17 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
+
+## Unreleased
+
+### Added
+
+- Added Mempool sorting [#395](https://github.com/proto-kit/framework/pull/395)
+- Introduced dynamic block building and JIT transaction fetching [#394](https://github.com/proto-kit/framework/pull/394)
+- Introduced block explorer [#381](https://github.com/proto-kit/framework/pull/381)
+- Added CircuitAnalysisModule for easy analysis of protocol circuits [#379](https://github.com/proto-kit/framework/pull/379)
+- Separated settlement and bridging functionally, so now settlement can be used without bridging [#376](https://github.com/proto-kit/framework/pull/376)
+- Added nightly releases via pkg.pr.new [#384](https://github.com/proto-kit/framework/pull/384)
+- Introduced Changelog [#378](https://github.com/proto-kit/framework/pull/378)
diff --git a/README.md b/README.md
index 962e4fd0b..37e93f0c1 100644
--- a/README.md
+++ b/README.md
@@ -6,10 +6,11 @@
-[](https://www.npmjs.com/package/o1js)
[](https://protokit.dev)
[]()
+[](https://www.npmjs.com/package/@proto-kit/sdk)
+[](https://pkg.pr.new/~/proto-kit/framework)
# Protokit
diff --git a/package-lock.json b/package-lock.json
index 62c5fb92a..61f19dbb1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -39,6 +39,7 @@
"lint-staged": "^13.1.0",
"nx": "15.6.2",
"nyc": "^17.1.0",
+ "pkg-pr-new": "^0.0.62",
"prettier": "^3.2.5",
"ts-jest": "^29.0.5",
"typedoc": "^0.26.11",
@@ -60,6 +61,45 @@
}
}
},
+ "node_modules/@actions/core": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz",
+ "integrity": "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@actions/exec": "^1.1.1",
+ "@actions/http-client": "^2.0.1"
+ }
+ },
+ "node_modules/@actions/exec": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz",
+ "integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@actions/io": "^1.0.1"
+ }
+ },
+ "node_modules/@actions/http-client": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz",
+ "integrity": "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tunnel": "^0.0.6",
+ "undici": "^5.25.4"
+ }
+ },
+ "node_modules/@actions/io": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz",
+ "integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@alcalzone/ansi-tokenize": {
"version": "0.1.3",
"license": "MIT",
@@ -85,6 +125,7 @@
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
"integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
+ "license": "MIT",
"engines": {
"node": ">=10"
},
@@ -662,10 +703,11 @@
}
},
"node_modules/@emnapi/core": {
- "version": "1.7.1",
- "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.1.tgz",
- "integrity": "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==",
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.8.1.tgz",
+ "integrity": "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==",
"dev": true,
+ "license": "MIT",
"optional": true,
"dependencies": {
"@emnapi/wasi-threads": "1.1.0",
@@ -673,10 +715,11 @@
}
},
"node_modules/@emnapi/runtime": {
- "version": "1.7.1",
- "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz",
- "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==",
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz",
+ "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==",
"dev": true,
+ "license": "MIT",
"optional": true,
"dependencies": {
"tslib": "^2.4.0"
@@ -687,6 +730,7 @@
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz",
"integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==",
"dev": true,
+ "license": "MIT",
"optional": true,
"dependencies": {
"tslib": "^2.4.0"
@@ -820,10 +864,21 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
+ "node_modules/@fastify/busboy": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz",
+ "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14"
+ }
+ },
"node_modules/@floating-ui/core": {
"version": "1.7.3",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz",
"integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==",
+ "license": "MIT",
"dependencies": {
"@floating-ui/utils": "^0.2.10"
}
@@ -832,6 +887,7 @@
"version": "1.7.4",
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz",
"integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==",
+ "license": "MIT",
"dependencies": {
"@floating-ui/core": "^1.7.3",
"@floating-ui/utils": "^0.2.10"
@@ -841,6 +897,7 @@
"version": "2.1.6",
"resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.6.tgz",
"integrity": "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==",
+ "license": "MIT",
"dependencies": {
"@floating-ui/dom": "^1.7.4"
},
@@ -852,7 +909,8 @@
"node_modules/@floating-ui/utils": {
"version": "0.2.10",
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz",
- "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ=="
+ "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==",
+ "license": "MIT"
},
"node_modules/@gar/promisify": {
"version": "1.1.3",
@@ -1100,6 +1158,7 @@
"version": "3.10.0",
"resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.10.0.tgz",
"integrity": "sha512-79Dv+3mDF7i+2ajj7SkypSKHhl1cbln1OGavqrsF7p6mbUv11xpqpacPsGDCTRvCSjEEIez2ef1NveSVL3b0Ag==",
+ "license": "MIT",
"peerDependencies": {
"react-hook-form": "^7.0.0"
}
@@ -1997,6 +2056,22 @@
"url": "https://opencollective.com/js-sdsl"
}
},
+ "node_modules/@jsdevtools/ez-spawn": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@jsdevtools/ez-spawn/-/ez-spawn-3.0.4.tgz",
+ "integrity": "sha512-f5DRIOZf7wxogefH03RjMPMdBF7ADTWUMoOs9kaJo06EfwF+aFhMZMDZxHg/Xe12hptN9xoZjGso2fdjapBRIA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-me-maybe": "^1.0.1",
+ "cross-spawn": "^7.0.3",
+ "string-argv": "^0.3.1",
+ "type-detect": "^4.0.8"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/@kamilkisiela/fast-url-parser": {
"version": "1.1.4",
"license": "MIT"
@@ -2618,6 +2693,7 @@
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz",
"integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==",
"dev": true,
+ "license": "MIT",
"optional": true,
"dependencies": {
"@emnapi/core": "^1.4.3",
@@ -2628,13 +2704,15 @@
"node_modules/@next/env": {
"version": "14.2.4",
"resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.4.tgz",
- "integrity": "sha512-3EtkY5VDkuV2+lNmKlbkibIJxcO4oIHEhBWne6PaAp+76J9KoSsGvNikp6ivzAT8dhhBMYrm6op2pS1ApG0Hzg=="
+ "integrity": "sha512-3EtkY5VDkuV2+lNmKlbkibIJxcO4oIHEhBWne6PaAp+76J9KoSsGvNikp6ivzAT8dhhBMYrm6op2pS1ApG0Hzg==",
+ "license": "MIT"
},
"node_modules/@next/eslint-plugin-next": {
"version": "14.2.4",
"resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.4.tgz",
"integrity": "sha512-svSFxW9f3xDaZA3idQmlFw7SusOuWTpDTAeBlO3AEPDltrraV+lqs7mAc6A27YdnpQVVIA3sODqUAAHdWhVWsA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"glob": "10.3.10"
}
@@ -2644,6 +2722,7 @@
"resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz",
"integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==",
"dev": true,
+ "license": "ISC",
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^2.3.5",
@@ -2666,6 +2745,7 @@
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
"integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
"dev": true,
+ "license": "BlueOak-1.0.0",
"dependencies": {
"@isaacs/cliui": "^8.0.2"
},
@@ -2686,6 +2766,7 @@
"cpu": [
"arm64"
],
+ "license": "MIT",
"optional": true,
"os": [
"darwin"
@@ -2701,6 +2782,7 @@
"cpu": [
"x64"
],
+ "license": "MIT",
"optional": true,
"os": [
"darwin"
@@ -2716,6 +2798,7 @@
"cpu": [
"arm64"
],
+ "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -2731,6 +2814,7 @@
"cpu": [
"arm64"
],
+ "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -2746,6 +2830,7 @@
"cpu": [
"x64"
],
+ "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -2761,6 +2846,7 @@
"cpu": [
"x64"
],
+ "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -2776,6 +2862,7 @@
"cpu": [
"arm64"
],
+ "license": "MIT",
"optional": true,
"os": [
"win32"
@@ -2791,6 +2878,7 @@
"cpu": [
"ia32"
],
+ "license": "MIT",
"optional": true,
"os": [
"win32"
@@ -2806,6 +2894,7 @@
"cpu": [
"x64"
],
+ "license": "MIT",
"optional": true,
"os": [
"win32"
@@ -2848,6 +2937,7 @@
"resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz",
"integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=12.4.0"
}
@@ -3380,6 +3470,298 @@
"tao": "index.js"
}
},
+ "node_modules/@octokit/action": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/@octokit/action/-/action-6.1.0.tgz",
+ "integrity": "sha512-lo+nHx8kAV86bxvOVOI3vFjX3gXPd/L7guAUbvs3pUvnR2KC+R7yjBkA1uACt4gYhs4LcWP3AXSGQzsbeN2XXw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@octokit/auth-action": "^4.0.0",
+ "@octokit/core": "^5.0.0",
+ "@octokit/plugin-paginate-rest": "^9.0.0",
+ "@octokit/plugin-rest-endpoint-methods": "^10.0.0",
+ "@octokit/types": "^12.0.0",
+ "undici": "^6.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/action/node_modules/@octokit/auth-token": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz",
+ "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/action/node_modules/@octokit/core": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.2.tgz",
+ "integrity": "sha512-/g2d4sW9nUDJOMz3mabVQvOGhVa4e/BN/Um7yca9Bb2XTzPPnfTWHWQg+IsEYO7M3Vx+EXvaM/I2pJWIMun1bg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@octokit/auth-token": "^4.0.0",
+ "@octokit/graphql": "^7.1.0",
+ "@octokit/request": "^8.4.1",
+ "@octokit/request-error": "^5.1.1",
+ "@octokit/types": "^13.0.0",
+ "before-after-hook": "^2.2.0",
+ "universal-user-agent": "^6.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/action/node_modules/@octokit/core/node_modules/@octokit/openapi-types": {
+ "version": "24.2.0",
+ "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz",
+ "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@octokit/action/node_modules/@octokit/core/node_modules/@octokit/types": {
+ "version": "13.10.0",
+ "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz",
+ "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@octokit/openapi-types": "^24.2.0"
+ }
+ },
+ "node_modules/@octokit/action/node_modules/@octokit/endpoint": {
+ "version": "9.0.6",
+ "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.6.tgz",
+ "integrity": "sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@octokit/types": "^13.1.0",
+ "universal-user-agent": "^6.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/action/node_modules/@octokit/endpoint/node_modules/@octokit/openapi-types": {
+ "version": "24.2.0",
+ "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz",
+ "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@octokit/action/node_modules/@octokit/endpoint/node_modules/@octokit/types": {
+ "version": "13.10.0",
+ "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz",
+ "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@octokit/openapi-types": "^24.2.0"
+ }
+ },
+ "node_modules/@octokit/action/node_modules/@octokit/graphql": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.1.tgz",
+ "integrity": "sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@octokit/request": "^8.4.1",
+ "@octokit/types": "^13.0.0",
+ "universal-user-agent": "^6.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/action/node_modules/@octokit/graphql/node_modules/@octokit/openapi-types": {
+ "version": "24.2.0",
+ "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz",
+ "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@octokit/action/node_modules/@octokit/graphql/node_modules/@octokit/types": {
+ "version": "13.10.0",
+ "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz",
+ "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@octokit/openapi-types": "^24.2.0"
+ }
+ },
+ "node_modules/@octokit/action/node_modules/@octokit/openapi-types": {
+ "version": "20.0.0",
+ "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz",
+ "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@octokit/action/node_modules/@octokit/plugin-paginate-rest": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.2.tgz",
+ "integrity": "sha512-u3KYkGF7GcZnSD/3UP0S7K5XUFT2FkOQdcfXZGZQPGv3lm4F2Xbf71lvjldr8c1H3nNbF+33cLEkWYbokGWqiQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@octokit/types": "^12.6.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "peerDependencies": {
+ "@octokit/core": "5"
+ }
+ },
+ "node_modules/@octokit/action/node_modules/@octokit/plugin-rest-endpoint-methods": {
+ "version": "10.4.1",
+ "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz",
+ "integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@octokit/types": "^12.6.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "peerDependencies": {
+ "@octokit/core": "5"
+ }
+ },
+ "node_modules/@octokit/action/node_modules/@octokit/request": {
+ "version": "8.4.1",
+ "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.1.tgz",
+ "integrity": "sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@octokit/endpoint": "^9.0.6",
+ "@octokit/request-error": "^5.1.1",
+ "@octokit/types": "^13.1.0",
+ "universal-user-agent": "^6.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/action/node_modules/@octokit/request-error": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.1.tgz",
+ "integrity": "sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@octokit/types": "^13.1.0",
+ "deprecation": "^2.0.0",
+ "once": "^1.4.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/action/node_modules/@octokit/request-error/node_modules/@octokit/openapi-types": {
+ "version": "24.2.0",
+ "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz",
+ "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@octokit/action/node_modules/@octokit/request-error/node_modules/@octokit/types": {
+ "version": "13.10.0",
+ "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz",
+ "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@octokit/openapi-types": "^24.2.0"
+ }
+ },
+ "node_modules/@octokit/action/node_modules/@octokit/request/node_modules/@octokit/openapi-types": {
+ "version": "24.2.0",
+ "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz",
+ "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@octokit/action/node_modules/@octokit/request/node_modules/@octokit/types": {
+ "version": "13.10.0",
+ "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz",
+ "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@octokit/openapi-types": "^24.2.0"
+ }
+ },
+ "node_modules/@octokit/action/node_modules/@octokit/types": {
+ "version": "12.6.0",
+ "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz",
+ "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@octokit/openapi-types": "^20.0.0"
+ }
+ },
+ "node_modules/@octokit/action/node_modules/undici": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-6.23.0.tgz",
+ "integrity": "sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.17"
+ }
+ },
+ "node_modules/@octokit/auth-action": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@octokit/auth-action/-/auth-action-4.1.0.tgz",
+ "integrity": "sha512-m+3t7K46IYyMk7Bl6/lF4Rv09GqDZjYmNg8IWycJ2Fa3YE3DE7vQcV6G2hUPmR9NDqenefNJwVtlisMjzymPiQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@octokit/auth-token": "^4.0.0",
+ "@octokit/types": "^13.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/auth-action/node_modules/@octokit/auth-token": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz",
+ "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/auth-action/node_modules/@octokit/openapi-types": {
+ "version": "24.2.0",
+ "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz",
+ "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@octokit/auth-action/node_modules/@octokit/types": {
+ "version": "13.10.0",
+ "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz",
+ "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@octokit/openapi-types": "^24.2.0"
+ }
+ },
"node_modules/@octokit/auth-token": {
"version": "3.0.4",
"dev": true,
@@ -5252,17 +5634,20 @@
"node_modules/@radix-ui/number": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz",
- "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g=="
+ "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==",
+ "license": "MIT"
},
"node_modules/@radix-ui/primitive": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz",
- "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="
+ "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==",
+ "license": "MIT"
},
"node_modules/@radix-ui/react-arrow": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz",
"integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/react-primitive": "2.1.3"
},
@@ -5285,6 +5670,7 @@
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.3.3.tgz",
"integrity": "sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.3",
"@radix-ui/react-compose-refs": "1.1.2",
@@ -5314,6 +5700,7 @@
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz",
"integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.2",
"@radix-ui/react-context": "1.1.2",
@@ -5339,6 +5726,7 @@
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
"integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.2"
},
@@ -5356,6 +5744,7 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
"integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==",
+ "license": "MIT",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
@@ -5370,6 +5759,7 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
"integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
+ "license": "MIT",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
@@ -5384,6 +5774,7 @@
"version": "1.1.15",
"resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz",
"integrity": "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.3",
"@radix-ui/react-compose-refs": "1.1.2",
@@ -5419,6 +5810,7 @@
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
"integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.2"
},
@@ -5436,6 +5828,7 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz",
"integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==",
+ "license": "MIT",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
@@ -5450,6 +5843,7 @@
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz",
"integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.3",
"@radix-ui/react-compose-refs": "1.1.2",
@@ -5476,6 +5870,7 @@
"version": "2.1.16",
"resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.16.tgz",
"integrity": "sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.3",
"@radix-ui/react-compose-refs": "1.1.2",
@@ -5504,6 +5899,7 @@
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz",
"integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==",
+ "license": "MIT",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
@@ -5518,6 +5914,7 @@
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz",
"integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.2",
"@radix-ui/react-primitive": "2.1.3",
@@ -5542,6 +5939,7 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz",
"integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/react-use-layout-effect": "1.1.1"
},
@@ -5559,6 +5957,7 @@
"version": "2.1.8",
"resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.8.tgz",
"integrity": "sha512-FmXs37I6hSBVDlO4y764TNz1rLgKwjJMQ0EGte6F3Cb3f4bIuHB/iLa/8I9VKkmOy+gNHq8rql3j686ACVV21A==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/react-primitive": "2.1.4"
},
@@ -5581,6 +5980,7 @@
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz",
"integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/react-slot": "1.2.4"
},
@@ -5603,6 +6003,7 @@
"version": "2.1.16",
"resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.16.tgz",
"integrity": "sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.3",
"@radix-ui/react-collection": "1.1.7",
@@ -5642,6 +6043,7 @@
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
"integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.2"
},
@@ -5659,6 +6061,7 @@
"version": "1.2.14",
"resolved": "https://registry.npmjs.org/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.2.14.tgz",
"integrity": "sha512-YB9mTFQvCOAQMHU+C/jVl96WmuWeltyUEpRJJky51huhds5W2FQr1J8D/16sQlf0ozxkPK8uF3niQMdUwZPv5w==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.3",
"@radix-ui/react-collection": "1.1.7",
@@ -5694,6 +6097,7 @@
"version": "1.1.15",
"resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.15.tgz",
"integrity": "sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.3",
"@radix-ui/react-compose-refs": "1.1.2",
@@ -5730,6 +6134,7 @@
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
"integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.2"
},
@@ -5747,6 +6152,7 @@
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz",
"integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==",
+ "license": "MIT",
"dependencies": {
"@floating-ui/react-dom": "^2.0.0",
"@radix-ui/react-arrow": "1.1.7",
@@ -5778,6 +6184,7 @@
"version": "1.1.9",
"resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz",
"integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/react-primitive": "2.1.3",
"@radix-ui/react-use-layout-effect": "1.1.1"
@@ -5801,6 +6208,7 @@
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz",
"integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.2",
"@radix-ui/react-use-layout-effect": "1.1.1"
@@ -5824,6 +6232,7 @@
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
"integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/react-slot": "1.2.3"
},
@@ -5846,6 +6255,7 @@
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
"integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.2"
},
@@ -5863,6 +6273,7 @@
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz",
"integrity": "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.3",
"@radix-ui/react-collection": "1.1.7",
@@ -5893,6 +6304,7 @@
"version": "2.2.6",
"resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.6.tgz",
"integrity": "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/number": "1.1.1",
"@radix-ui/primitive": "1.1.3",
@@ -5935,6 +6347,7 @@
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
"integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.2"
},
@@ -5952,6 +6365,7 @@
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz",
"integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.2"
},
@@ -5969,6 +6383,7 @@
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.8.tgz",
"integrity": "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.3",
"@radix-ui/react-compose-refs": "1.1.2",
@@ -6002,6 +6417,7 @@
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
"integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.2"
},
@@ -6019,6 +6435,7 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
"integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==",
+ "license": "MIT",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
@@ -6033,6 +6450,7 @@
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz",
"integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/react-use-effect-event": "0.0.2",
"@radix-ui/react-use-layout-effect": "1.1.1"
@@ -6051,6 +6469,7 @@
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz",
"integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/react-use-layout-effect": "1.1.1"
},
@@ -6068,6 +6487,7 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz",
"integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/react-use-callback-ref": "1.1.1"
},
@@ -6085,6 +6505,7 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
"integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
+ "license": "MIT",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
@@ -6099,6 +6520,7 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz",
"integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==",
+ "license": "MIT",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
@@ -6113,6 +6535,7 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz",
"integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/rect": "1.1.1"
},
@@ -6130,6 +6553,7 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz",
"integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/react-use-layout-effect": "1.1.1"
},
@@ -6147,6 +6571,7 @@
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz",
"integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/react-primitive": "2.1.3"
},
@@ -6168,7 +6593,8 @@
"node_modules/@radix-ui/rect": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz",
- "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="
+ "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==",
+ "license": "MIT"
},
"node_modules/@redis/bloom": {
"version": "1.2.0",
@@ -6229,7 +6655,8 @@
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.15.0.tgz",
"integrity": "sha512-ojSshQPKwVvSMR8yT2L/QtUkV5SXi/IfDiJ4/8d6UbTPjiHVmxZzUAzGD8Tzks1b9+qQkZa0isUOvYObedITaw==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/@shikijs/core": {
"version": "1.29.2",
@@ -6442,12 +6869,14 @@
"node_modules/@swc/counter": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
- "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ=="
+ "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==",
+ "license": "Apache-2.0"
},
"node_modules/@swc/helpers": {
"version": "0.5.5",
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz",
"integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==",
+ "license": "Apache-2.0",
"dependencies": {
"@swc/counter": "^0.1.3",
"tslib": "^2.4.0"
@@ -6527,6 +6956,7 @@
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz",
"integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==",
"dev": true,
+ "license": "MIT",
"optional": true,
"dependencies": {
"tslib": "^2.4.0"
@@ -6890,6 +7320,7 @@
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz",
"integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
"devOptional": true,
+ "license": "MIT",
"peerDependencies": {
"@types/react": "^18.0.0"
}
@@ -7294,6 +7725,7 @@
"arm"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"android"
@@ -7307,6 +7739,7 @@
"arm64"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"android"
@@ -7320,6 +7753,7 @@
"arm64"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"darwin"
@@ -7333,6 +7767,7 @@
"x64"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"darwin"
@@ -7346,6 +7781,7 @@
"x64"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"freebsd"
@@ -7359,6 +7795,7 @@
"arm"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -7372,6 +7809,7 @@
"arm"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -7385,6 +7823,7 @@
"arm64"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -7398,6 +7837,7 @@
"arm64"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -7411,6 +7851,7 @@
"ppc64"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -7424,6 +7865,7 @@
"riscv64"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -7437,6 +7879,7 @@
"riscv64"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -7450,6 +7893,7 @@
"s390x"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -7463,6 +7907,7 @@
"x64"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -7476,6 +7921,7 @@
"x64"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -7489,6 +7935,7 @@
"wasm32"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"dependencies": {
"@napi-rs/wasm-runtime": "^0.2.11"
@@ -7505,6 +7952,7 @@
"arm64"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"win32"
@@ -7518,6 +7966,7 @@
"ia32"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"win32"
@@ -7531,6 +7980,7 @@
"x64"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"win32"
@@ -7682,7 +8132,9 @@
}
},
"node_modules/acorn": {
- "version": "8.12.0",
+ "version": "8.15.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
+ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"license": "MIT",
"bin": {
"acorn": "bin/acorn"
@@ -7822,7 +8274,8 @@
"node_modules/any-promise": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
- "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="
+ "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
+ "license": "MIT"
},
"node_modules/anymatch": {
"version": "3.1.3",
@@ -7880,6 +8333,7 @@
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz",
"integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==",
+ "license": "MIT",
"dependencies": {
"tslib": "^2.0.0"
},
@@ -7892,6 +8346,7 @@
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz",
"integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==",
"dev": true,
+ "license": "Apache-2.0",
"engines": {
"node": ">= 0.4"
}
@@ -7901,6 +8356,7 @@
"resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz",
"integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bound": "^1.0.3",
"is-array-buffer": "^3.0.5"
@@ -7976,6 +8432,7 @@
"resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz",
"integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bind": "^1.0.7",
"define-properties": "^1.2.1",
@@ -8032,6 +8489,7 @@
"resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz",
"integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bind": "^1.0.8",
"define-properties": "^1.2.1",
@@ -8050,6 +8508,7 @@
"resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz",
"integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bind": "^1.0.7",
"define-properties": "^1.2.1",
@@ -8066,6 +8525,7 @@
"resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz",
"integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"array-buffer-byte-length": "^1.0.1",
"call-bind": "^1.0.8",
@@ -8109,7 +8569,8 @@
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz",
"integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/astral-regex": {
"version": "2.0.0",
@@ -8127,6 +8588,7 @@
"resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz",
"integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 0.4"
}
@@ -8158,6 +8620,7 @@
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
"integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"possible-typed-array-names": "^1.0.0"
},
@@ -8169,10 +8632,11 @@
}
},
"node_modules/axe-core": {
- "version": "4.11.0",
- "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.11.0.tgz",
- "integrity": "sha512-ilYanEU8vxxBexpJd8cWM4ElSQq4QctCLKih0TSfjIfCQTeyH/6zVrmIJfLPrKTKJRbiG+cfnZbQIjAlJmF1jQ==",
+ "version": "4.11.1",
+ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.11.1.tgz",
+ "integrity": "sha512-BASOg+YwO2C+346x3LZOeoovTIoTrRqEsqMa6fmfAV0P+U9mFr9NsyOEpiYvFjbc64NMrSswhV50WdXzdb/Z5A==",
"dev": true,
+ "license": "MPL-2.0",
"engines": {
"node": ">=4"
}
@@ -8192,6 +8656,7 @@
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
"integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",
"dev": true,
+ "license": "Apache-2.0",
"engines": {
"node": ">= 0.4"
}
@@ -8472,6 +8937,7 @@
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
"integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
+ "license": "MIT",
"engines": {
"node": ">=8"
},
@@ -8898,6 +9364,7 @@
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
"integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.0",
"es-define-property": "^1.0.0",
@@ -8927,6 +9394,7 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
"integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+ "license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
"get-intrinsic": "^1.3.0"
@@ -8938,6 +9406,13 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/call-me-maybe": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz",
+ "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/callsites": {
"version": "3.1.0",
"license": "MIT",
@@ -8956,6 +9431,7 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
"integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
+ "license": "MIT",
"engines": {
"node": ">= 6"
}
@@ -9155,6 +9631,7 @@
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz",
"integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==",
+ "license": "Apache-2.0",
"dependencies": {
"clsx": "^2.1.1"
},
@@ -9278,7 +9755,8 @@
"node_modules/client-only": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
- "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
+ "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
+ "license": "MIT"
},
"node_modules/cliui": {
"version": "7.0.4",
@@ -9325,6 +9803,7 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+ "license": "MIT",
"engines": {
"node": ">=6"
}
@@ -9351,6 +9830,7 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/cmdk/-/cmdk-1.1.1.tgz",
"integrity": "sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg==",
+ "license": "MIT",
"dependencies": {
"@radix-ui/react-compose-refs": "^1.1.1",
"@radix-ui/react-dialog": "^1.1.6",
@@ -9560,6 +10040,13 @@
"typedarray": "^0.0.6"
}
},
+ "node_modules/confbox": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz",
+ "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/config-chain": {
"version": "1.1.12",
"dev": true,
@@ -10107,7 +10594,8 @@
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
"integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==",
- "dev": true
+ "dev": true,
+ "license": "BSD-2-Clause"
},
"node_modules/dargs": {
"version": "7.0.0",
@@ -10122,6 +10610,7 @@
"resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
"integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bound": "^1.0.3",
"es-errors": "^1.3.0",
@@ -10139,6 +10628,7 @@
"resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz",
"integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bound": "^1.0.3",
"es-errors": "^1.3.0",
@@ -10156,6 +10646,7 @@
"resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz",
"integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"es-errors": "^1.3.0",
@@ -10183,6 +10674,7 @@
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
@@ -10226,6 +10718,16 @@
"node": ">=0.10.0"
}
},
+ "node_modules/decode-uri-component": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.4.1.tgz",
+ "integrity": "sha512-+8VxcR21HhTy8nOt6jf20w0c9CADrw1O8d+VZ/YzzCt4bJ3uBjw+D1q2osAB8RnpwwaeYBxy0HyKQxD5JBMuuQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.16"
+ }
+ },
"node_modules/dedent": {
"version": "0.7.0",
"dev": true,
@@ -10415,7 +10917,8 @@
"node_modules/detect-node-es": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
- "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="
+ "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==",
+ "license": "MIT"
},
"node_modules/devlop": {
"version": "1.1.0",
@@ -10432,7 +10935,8 @@
"node_modules/didyoumean": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
- "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="
+ "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
+ "license": "Apache-2.0"
},
"node_modules/diff": {
"version": "4.0.2",
@@ -10461,7 +10965,8 @@
"node_modules/dlv": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
- "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="
+ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
+ "license": "MIT"
},
"node_modules/doctrine": {
"version": "3.0.0",
@@ -10751,10 +11256,11 @@
}
},
"node_modules/es-abstract": {
- "version": "1.24.0",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz",
- "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==",
+ "version": "1.24.1",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.1.tgz",
+ "integrity": "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"array-buffer-byte-length": "^1.0.2",
"arraybuffer.prototype.slice": "^1.0.4",
@@ -10834,26 +11340,27 @@
}
},
"node_modules/es-iterator-helpers": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz",
- "integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==",
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.2.tgz",
+ "integrity": "sha512-BrUQ0cPTB/IwXj23HtwHjS9n7O4h9FX94b4xc5zlTHxeLgTAdzYUDyy6KdExAl9lbN5rtfe44xpjpmj9grxs5w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bind": "^1.0.8",
- "call-bound": "^1.0.3",
+ "call-bound": "^1.0.4",
"define-properties": "^1.2.1",
- "es-abstract": "^1.23.6",
+ "es-abstract": "^1.24.1",
"es-errors": "^1.3.0",
- "es-set-tostringtag": "^2.0.3",
+ "es-set-tostringtag": "^2.1.0",
"function-bind": "^1.1.2",
- "get-intrinsic": "^1.2.6",
+ "get-intrinsic": "^1.3.0",
"globalthis": "^1.0.4",
"gopd": "^1.2.0",
"has-property-descriptors": "^1.0.2",
"has-proto": "^1.2.0",
"has-symbols": "^1.1.0",
"internal-slot": "^1.1.0",
- "iterator.prototype": "^1.1.4",
+ "iterator.prototype": "^1.1.5",
"safe-array-concat": "^1.1.3"
},
"engines": {
@@ -10898,6 +11405,7 @@
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz",
"integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"is-callable": "^1.2.7",
"is-date-object": "^1.0.5",
@@ -11031,6 +11539,7 @@
"resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.2.4.tgz",
"integrity": "sha512-Qr0wMgG9m6m4uYy2jrYJmyuNlYZzPRQq5Kvb9IDlYwn+7yq6W6sfMNFgb+9guM1KYwuIo6TIaiFhZJ6SnQ/Efw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@next/eslint-plugin-next": "14.2.4",
"@rushstack/eslint-patch": "^1.3.3",
@@ -11057,6 +11566,7 @@
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.2.0.tgz",
"integrity": "sha512-5FKsVcHTk6TafQKQbuIVkXq58Fnbkd2wDL4LB7AURN7RUOu1utVP+G8+6u3ZhEroW3DF6hyo3ZEXxgKgp4KeCg==",
"dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
"@typescript-eslint/scope-manager": "7.2.0",
"@typescript-eslint/types": "7.2.0",
@@ -11085,6 +11595,7 @@
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.2.0.tgz",
"integrity": "sha512-Qh976RbQM/fYtjx9hs4XkayYujB/aPwglw2choHmf3zBjB4qOywWSdt9+KLRdHubGcoSwBnXUH2sR3hkyaERRg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@typescript-eslint/types": "7.2.0",
"@typescript-eslint/visitor-keys": "7.2.0"
@@ -11102,6 +11613,7 @@
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.2.0.tgz",
"integrity": "sha512-XFtUHPI/abFhm4cbCDc5Ykc8npOKBSJePY3a3s+lwumt7XWJuzP5cZcfZ610MIPHjQjNsOLlYK8ASPaNG8UiyA==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": "^16.0.0 || >=18.0.0"
},
@@ -11115,6 +11627,7 @@
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.2.0.tgz",
"integrity": "sha512-cyxS5WQQCoBwSakpMrvMXuMDEbhOo9bNHHrNcEWis6XHx6KF518tkF1wBvKIn/tpq5ZpUYK7Bdklu8qY0MsFIA==",
"dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
"@typescript-eslint/types": "7.2.0",
"@typescript-eslint/visitor-keys": "7.2.0",
@@ -11143,6 +11656,7 @@
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.2.0.tgz",
"integrity": "sha512-c6EIQRHhcpl6+tO8EMR+kjkkV+ugUNXOmeASA1rlzkd8EPIriavpWoiEz1HR/VLhbVIdhqnV6E7JZm00cBDx2A==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@typescript-eslint/types": "7.2.0",
"eslint-visitor-keys": "^3.4.1"
@@ -11160,6 +11674,7 @@
"resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz",
"integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==",
"dev": true,
+ "license": "ISC",
"dependencies": {
"@nolyfill/is-core-module": "1.0.39",
"debug": "^4.4.0",
@@ -11194,6 +11709,7 @@
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
"integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
"dev": true,
+ "license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
@@ -11388,6 +11904,7 @@
"resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz",
"integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"aria-query": "^5.3.2",
"array-includes": "^3.1.8",
@@ -11417,6 +11934,7 @@
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -11426,13 +11944,15 @@
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true,
+ "license": "ISC",
"dependencies": {
"brace-expansion": "^1.1.7"
},
@@ -11474,6 +11994,7 @@
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz",
"integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"array-includes": "^3.1.8",
"array.prototype.findlast": "^1.2.5",
@@ -11506,6 +12027,7 @@
"resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0-canary-7118f5dd7-20230705.tgz",
"integrity": "sha512-AZYbMo/NW9chdL7vk6HQzQhT+PvTAEVqWk9ziruUoW2kAOcN5qNyelv70e0F1VNQAbvutOC9oc+xfWycI9FxDw==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=10"
},
@@ -11518,6 +12040,7 @@
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -11528,6 +12051,7 @@
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
"integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
"dev": true,
+ "license": "Apache-2.0",
"dependencies": {
"esutils": "^2.0.2"
},
@@ -11540,6 +12064,7 @@
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true,
+ "license": "ISC",
"dependencies": {
"brace-expansion": "^1.1.7"
},
@@ -11552,6 +12077,7 @@
"resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz",
"integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"is-core-module": "^2.13.0",
"path-parse": "^1.0.7",
@@ -11569,6 +12095,7 @@
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
+ "license": "ISC",
"bin": {
"semver": "bin/semver.js"
}
@@ -12117,6 +12644,19 @@
"node": ">=8"
}
},
+ "node_modules/filter-obj": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-5.1.0.tgz",
+ "integrity": "sha512-qWeTREPoT7I0bifpPUXtxkZJ1XJzxWtfoWWkdVGqa+eCr3SHW/Ocp89o8vLvbUuQnadybJpjOKu4V+RwO6sGng==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/finalhandler": {
"version": "1.3.1",
"license": "MIT",
@@ -12322,6 +12862,7 @@
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
"integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"is-callable": "^1.2.7"
},
@@ -12464,6 +13005,7 @@
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"hasInstallScript": true,
+ "license": "MIT",
"optional": true,
"os": [
"darwin"
@@ -12484,6 +13026,7 @@
"resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz",
"integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bind": "^1.0.8",
"call-bound": "^1.0.3",
@@ -12613,6 +13156,7 @@
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/geist/-/geist-1.5.1.tgz",
"integrity": "sha512-mAHZxIsL2o3ZITFaBVFBnwyDOw+zNLYum6A6nIjpzCGIO8QtC3V76XF2RnZTyLx1wlDTmMDy8jg3Ib52MIjGvQ==",
+ "license": "SIL OPEN FONT LICENSE",
"peerDependencies": {
"next": ">=13.2.0"
}
@@ -12665,6 +13209,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz",
"integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==",
+ "license": "MIT",
"engines": {
"node": ">=6"
}
@@ -12816,6 +13361,7 @@
"resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz",
"integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bound": "^1.0.3",
"es-errors": "^1.3.0",
@@ -12833,6 +13379,7 @@
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz",
"integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"resolve-pkg-maps": "^1.0.0"
},
@@ -13972,6 +14519,7 @@
"resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz",
"integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 0.4"
},
@@ -14002,6 +14550,7 @@
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz",
"integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"dunder-proto": "^1.0.0"
},
@@ -15273,6 +15822,7 @@
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
"integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"hasown": "^2.0.2",
@@ -15346,6 +15896,7 @@
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
"integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bind": "^1.0.8",
"call-bound": "^1.0.3",
@@ -15367,6 +15918,7 @@
"resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz",
"integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"async-function": "^1.0.0",
"call-bound": "^1.0.3",
@@ -15386,6 +15938,7 @@
"resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz",
"integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"has-bigints": "^1.0.2"
},
@@ -15400,6 +15953,7 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "license": "MIT",
"dependencies": {
"binary-extensions": "^2.0.0"
},
@@ -15412,6 +15966,7 @@
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz",
"integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bound": "^1.0.3",
"has-tostringtag": "^1.0.2"
@@ -15428,6 +15983,7 @@
"resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz",
"integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"semver": "^7.7.1"
}
@@ -15475,6 +16031,7 @@
"resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz",
"integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"get-intrinsic": "^1.2.6",
@@ -15492,6 +16049,7 @@
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz",
"integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"has-tostringtag": "^1.0.2"
@@ -15528,6 +16086,7 @@
"resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz",
"integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bound": "^1.0.3"
},
@@ -15602,6 +16161,7 @@
"resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
"integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 0.4"
},
@@ -15640,6 +16200,7 @@
"resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz",
"integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bound": "^1.0.3",
"has-tostringtag": "^1.0.2"
@@ -15696,6 +16257,7 @@
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
"integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"gopd": "^1.2.0",
@@ -15725,6 +16287,7 @@
"resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz",
"integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 0.4"
},
@@ -15737,6 +16300,7 @@
"resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz",
"integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bound": "^1.0.3"
},
@@ -15770,6 +16334,7 @@
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz",
"integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bound": "^1.0.3",
"has-tostringtag": "^1.0.2"
@@ -15786,6 +16351,7 @@
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz",
"integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"has-symbols": "^1.1.0",
@@ -15814,6 +16380,7 @@
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
"integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"which-typed-array": "^1.1.16"
},
@@ -15867,6 +16434,7 @@
"resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
"integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 0.4"
},
@@ -15879,6 +16447,7 @@
"resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz",
"integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bound": "^1.0.3"
},
@@ -15894,6 +16463,7 @@
"resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz",
"integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bound": "^1.0.3",
"get-intrinsic": "^1.2.6"
@@ -15926,7 +16496,21 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
"integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/isbinaryfile": {
+ "version": "5.0.7",
+ "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.7.tgz",
+ "integrity": "sha512-gnWD14Jh3FzS3CPhF0AxNOJ8CxqeblPTADzI38r0wt8ZyQl5edpy75myt08EG2oKvpyiqSqsx+Wkz9vtkbTqYQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 18.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/gjtorikian/"
+ }
},
"node_modules/isexe": {
"version": "2.0.0",
@@ -16237,6 +16821,7 @@
"resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz",
"integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"define-data-property": "^1.1.4",
"es-object-atoms": "^1.0.0",
@@ -17712,6 +18297,7 @@
"version": "1.21.7",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz",
"integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==",
+ "license": "MIT",
"bin": {
"jiti": "bin/jiti.js"
}
@@ -17909,6 +18495,7 @@
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
"integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"array-includes": "^3.1.6",
"array.prototype.flat": "^1.3.1",
@@ -18012,13 +18599,15 @@
"version": "0.3.23",
"resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz",
"integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==",
- "dev": true
+ "dev": true,
+ "license": "CC0-1.0"
},
"node_modules/language-tags": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz",
"integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"language-subtag-registry": "^0.3.20"
},
@@ -19198,6 +19787,7 @@
"version": "0.395.0",
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.395.0.tgz",
"integrity": "sha512-6hzdNH5723A4FLaYZWpK50iyZH8iS2Jq5zuPRRotOFkhu6kxxJiebVdJ72tCR5XkiIeYFOU5NUawFZOac+VeYw==",
+ "license": "ISC",
"peerDependencies": {
"react": "^16.5.1 || ^17.0.0 || ^18.0.0"
}
@@ -19894,6 +20484,7 @@
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+ "license": "MIT",
"dependencies": {
"braces": "^3.0.3",
"picomatch": "^2.3.1"
@@ -20211,6 +20802,19 @@
"node": ">=10"
}
},
+ "node_modules/mlly": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz",
+ "integrity": "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "acorn": "^8.15.0",
+ "pathe": "^2.0.3",
+ "pkg-types": "^1.3.1",
+ "ufo": "^1.6.1"
+ }
+ },
"node_modules/modify-values": {
"version": "1.0.1",
"dev": true,
@@ -20265,7 +20869,8 @@
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
},
"node_modules/msgpackr": {
"version": "1.10.2",
@@ -20330,6 +20935,7 @@
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
"integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
+ "license": "MIT",
"dependencies": {
"any-promise": "^1.0.0",
"object-assign": "^4.0.1",
@@ -20358,6 +20964,7 @@
"resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz",
"integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==",
"dev": true,
+ "license": "MIT",
"bin": {
"napi-postinstall": "lib/cli.js"
},
@@ -20387,6 +20994,8 @@
"version": "14.2.4",
"resolved": "https://registry.npmjs.org/next/-/next-14.2.4.tgz",
"integrity": "sha512-R8/V7vugY+822rsQGQCjoLhMuC9oFj9SOi4Cl4b2wjDrseD0LRZ10W7R6Czo4w9ZznVSshKjuIomsRjvm9EKJQ==",
+ "deprecated": "This version has a security vulnerability. Please upgrade to a patched version. See https://nextjs.org/blog/security-update-2025-12-11 for more details.",
+ "license": "MIT",
"dependencies": {
"@next/env": "14.2.4",
"@swc/helpers": "0.5.5",
@@ -20450,6 +21059,7 @@
"url": "https://github.com/sponsors/ai"
}
],
+ "license": "MIT",
"dependencies": {
"nanoid": "^3.3.6",
"picocolors": "^1.0.0",
@@ -21615,6 +22225,7 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
"integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
+ "license": "MIT",
"engines": {
"node": ">= 6"
}
@@ -21623,6 +22234,7 @@
"version": "1.13.4",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
"integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
+ "license": "MIT",
"engines": {
"node": ">= 0.4"
},
@@ -21643,6 +22255,7 @@
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz",
"integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bind": "^1.0.8",
"call-bound": "^1.0.3",
@@ -21677,6 +22290,7 @@
"resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz",
"integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bind": "^1.0.8",
"call-bound": "^1.0.4",
@@ -21745,6 +22359,7 @@
"resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz",
"integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bind": "^1.0.8",
"call-bound": "^1.0.3",
@@ -21949,6 +22564,7 @@
"resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz",
"integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"get-intrinsic": "^1.2.6",
"object-keys": "^1.1.1",
@@ -22495,6 +23111,13 @@
"node": ">=8"
}
},
+ "node_modules/pathe": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
+ "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/pg-int8": {
"version": "1.0.1",
"license": "ISC",
@@ -22618,6 +23241,38 @@
"node": ">=8"
}
},
+ "node_modules/pkg-pr-new": {
+ "version": "0.0.62",
+ "resolved": "https://registry.npmjs.org/pkg-pr-new/-/pkg-pr-new-0.0.62.tgz",
+ "integrity": "sha512-K2jtf1PLCJJFDimQIpasPXDdnRTZSYPy36Ldz+QhMpLz2YN1Wi0ZQkomVt5Wi3NdBZcYuYGXekyFWfJ6fAHYjg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@actions/core": "^1.11.1",
+ "@jsdevtools/ez-spawn": "^3.0.4",
+ "@octokit/action": "^6.1.0",
+ "ignore": "^5.3.1",
+ "isbinaryfile": "^5.0.2",
+ "pkg-types": "^1.1.1",
+ "query-registry": "^3.0.1",
+ "tinyglobby": "^0.2.9"
+ },
+ "bin": {
+ "pkg-pr-new": "bin/cli.js"
+ }
+ },
+ "node_modules/pkg-types": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz",
+ "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "confbox": "^0.1.8",
+ "mlly": "^1.7.4",
+ "pathe": "^2.0.1"
+ }
+ },
"node_modules/pluralize": {
"version": "8.0.0",
"license": "MIT",
@@ -22652,6 +23307,7 @@
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
"integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 0.4"
}
@@ -22687,6 +23343,7 @@
"version": "15.1.0",
"resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
"integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
+ "license": "MIT",
"dependencies": {
"postcss-value-parser": "^4.0.0",
"read-cache": "^1.0.0",
@@ -22713,6 +23370,7 @@
"url": "https://github.com/sponsors/ai"
}
],
+ "license": "MIT",
"dependencies": {
"camelcase-css": "^2.0.1"
},
@@ -22737,6 +23395,7 @@
"url": "https://github.com/sponsors/ai"
}
],
+ "license": "MIT",
"dependencies": {
"lilconfig": "^3.1.1"
},
@@ -22768,6 +23427,7 @@
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
"integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==",
+ "license": "MIT",
"engines": {
"node": ">=14"
},
@@ -22789,6 +23449,7 @@
"url": "https://github.com/sponsors/ai"
}
],
+ "license": "MIT",
"dependencies": {
"postcss-selector-parser": "^6.1.1"
},
@@ -22803,6 +23464,7 @@
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
"integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
+ "license": "MIT",
"dependencies": {
"cssesc": "^3.0.0",
"util-deprecate": "^1.0.2"
@@ -22814,7 +23476,8 @@
"node_modules/postcss-value-parser": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
- "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
+ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
+ "license": "MIT"
},
"node_modules/postgres-array": {
"version": "2.0.0",
@@ -23159,6 +23822,65 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/query-registry": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/query-registry/-/query-registry-3.0.1.tgz",
+ "integrity": "sha512-M9RxRITi2mHMVPU5zysNjctUT8bAPx6ltEXo/ir9+qmiM47Y7f0Ir3+OxUO5OjYAWdicBQRew7RtHtqUXydqlg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "query-string": "^9.0.0",
+ "quick-lru": "^7.0.0",
+ "url-join": "^5.0.0",
+ "validate-npm-package-name": "^5.0.1",
+ "zod": "^3.23.8",
+ "zod-package-json": "^1.0.3"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/query-registry/node_modules/quick-lru": {
+ "version": "7.3.0",
+ "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-7.3.0.tgz",
+ "integrity": "sha512-k9lSsjl36EJdK7I06v7APZCbyGT2vMTsYSRX1Q2nbYmnkBqgUhRkAuzH08Ciotteu/PLJmIF2+tti7o3C/ts2g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/query-registry/node_modules/validate-npm-package-name": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz",
+ "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/query-string": {
+ "version": "9.3.1",
+ "resolved": "https://registry.npmjs.org/query-string/-/query-string-9.3.1.tgz",
+ "integrity": "sha512-5fBfMOcDi5SA9qj5jZhWAcTtDfKF5WFdd2uD9nVNlbxVv1baq65aALy6qofpNEGELHvisjjasxQp7BlM9gvMzw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "decode-uri-component": "^0.4.1",
+ "filter-obj": "^5.1.0",
+ "split-on-first": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/queue-microtask": {
"version": "1.2.3",
"funding": [
@@ -23240,6 +23962,7 @@
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
+ "license": "MIT",
"dependencies": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.2"
@@ -23249,9 +23972,10 @@
}
},
"node_modules/react-hook-form": {
- "version": "7.67.0",
- "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.67.0.tgz",
- "integrity": "sha512-E55EOwKJHHIT/I6J9DmQbCWToAYSw9nN5R57MZw9rMtjh+YQreMDxRLfdjfxQbiJ3/qbg3Z02wGzBX4M+5fMtQ==",
+ "version": "7.71.0",
+ "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.71.0.tgz",
+ "integrity": "sha512-oFDt/iIFMV9ZfV52waONXzg4xuSlbwKUPvXVH2jumL1me5qFhBMc4knZxuXiZ2+j6h546sYe3ZKJcg/900/iHw==",
+ "license": "MIT",
"engines": {
"node": ">=18.0.0"
},
@@ -23295,6 +24019,7 @@
"version": "2.7.2",
"resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz",
"integrity": "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==",
+ "license": "MIT",
"dependencies": {
"react-remove-scroll-bar": "^2.3.7",
"react-style-singleton": "^2.2.3",
@@ -23319,6 +24044,7 @@
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz",
"integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==",
+ "license": "MIT",
"dependencies": {
"react-style-singleton": "^2.2.2",
"tslib": "^2.0.0"
@@ -23340,6 +24066,7 @@
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz",
"integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==",
+ "license": "MIT",
"dependencies": {
"get-nonce": "^1.0.0",
"tslib": "^2.0.0"
@@ -23361,6 +24088,7 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/react-truncate-inside/-/react-truncate-inside-1.0.3.tgz",
"integrity": "sha512-XwQ+9ayvygHI4WjJwaTDYFiYLrLMbHiBc5VdhWuDrCAm8MWFT6YR/+BCgq5JUwyuISYleJyZ0yCAGbXMhGr9hw==",
+ "license": "MIT",
"peerDependencies": {
"react": ">= 16.x.x"
}
@@ -23380,6 +24108,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
"integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
+ "license": "MIT",
"dependencies": {
"pify": "^2.3.0"
}
@@ -23388,6 +24117,7 @@
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
@@ -23751,6 +24481,7 @@
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
"integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bind": "^1.0.8",
"define-properties": "^1.2.1",
@@ -23795,6 +24526,7 @@
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
"integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bind": "^1.0.8",
"define-properties": "^1.2.1",
@@ -23920,6 +24652,7 @@
"resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
"integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
"dev": true,
+ "license": "MIT",
"funding": {
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
}
@@ -24017,6 +24750,7 @@
"resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz",
"integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bind": "^1.0.8",
"call-bound": "^1.0.2",
@@ -24059,6 +24793,7 @@
"resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz",
"integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"isarray": "^2.0.5"
@@ -24075,6 +24810,7 @@
"resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz",
"integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"es-errors": "^1.3.0",
@@ -24162,6 +24898,7 @@
"version": "7.7.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
+ "license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
@@ -24345,6 +25082,7 @@
"resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz",
"integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"dunder-proto": "^1.0.1",
"es-errors": "^1.3.0",
@@ -24409,6 +25147,7 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
"integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
+ "license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"object-inspect": "^1.13.3",
@@ -24427,6 +25166,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
"integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
+ "license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"object-inspect": "^1.13.3"
@@ -24442,6 +25182,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
"integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
+ "license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"es-errors": "^1.3.0",
@@ -24459,6 +25200,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
"integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
+ "license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"es-errors": "^1.3.0",
@@ -24862,6 +25604,19 @@
"node": "*"
}
},
+ "node_modules/split-on-first": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-3.0.0.tgz",
+ "integrity": "sha512-qxQJTx2ryR0Dw0ITYyekNQWpz6f8dGd7vffGNflQQ3Iqj9NJ6qiZ7ELpZsJ/QBhIVAiDfXdag3+Gp8RvWa62AA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/split2": {
"version": "3.2.2",
"dev": true,
@@ -24905,7 +25660,8 @@
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz",
"integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/stack-generator": {
"version": "2.0.10",
@@ -24986,6 +25742,7 @@
"resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz",
"integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"internal-slot": "^1.1.0"
@@ -25075,6 +25832,7 @@
"resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz",
"integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bind": "^1.0.7",
"define-properties": "^1.2.1",
@@ -25089,6 +25847,7 @@
"resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz",
"integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bind": "^1.0.8",
"call-bound": "^1.0.3",
@@ -25116,6 +25875,7 @@
"resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz",
"integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"define-properties": "^1.1.3",
"es-abstract": "^1.17.5"
@@ -25126,6 +25886,7 @@
"resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz",
"integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bind": "^1.0.8",
"call-bound": "^1.0.2",
@@ -25147,6 +25908,7 @@
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz",
"integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bind": "^1.0.8",
"call-bound": "^1.0.2",
@@ -25265,6 +26027,7 @@
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz",
"integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==",
+ "license": "MIT",
"dependencies": {
"client-only": "0.0.1"
},
@@ -25287,6 +26050,7 @@
"version": "3.35.1",
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz",
"integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==",
+ "license": "MIT",
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.2",
"commander": "^4.0.0",
@@ -25308,6 +26072,7 @@
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
"integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
+ "license": "MIT",
"engines": {
"node": ">= 6"
}
@@ -25315,7 +26080,8 @@
"node_modules/sucrase/node_modules/lines-and-columns": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
- "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+ "license": "MIT"
},
"node_modules/supports-color": {
"version": "5.5.0",
@@ -25385,15 +26151,17 @@
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.6.0.tgz",
"integrity": "sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA==",
+ "license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/dcastil"
}
},
"node_modules/tailwindcss": {
- "version": "3.4.18",
- "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.18.tgz",
- "integrity": "sha512-6A2rnmW5xZMdw11LYjhcI5846rt9pbLSabY5XPxo+XWdxwZaFEn47Go4NzFiHu9sNNmr/kXivP1vStfvMaK1GQ==",
+ "version": "3.4.19",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz",
+ "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==",
+ "license": "MIT",
"dependencies": {
"@alloc/quick-lru": "^5.2.0",
"arg": "^5.0.2",
@@ -25430,6 +26198,7 @@
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz",
"integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==",
+ "license": "MIT",
"peerDependencies": {
"tailwindcss": ">=3.0.0 || insiders"
}
@@ -25438,6 +26207,7 @@
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+ "license": "MIT",
"dependencies": {
"anymatch": "~3.1.2",
"braces": "~3.0.2",
@@ -25461,6 +26231,7 @@
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "license": "ISC",
"dependencies": {
"is-glob": "^4.0.1"
},
@@ -25472,6 +26243,7 @@
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
"integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==",
+ "license": "MIT",
"engines": {
"node": ">=14"
},
@@ -25483,6 +26255,7 @@
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "license": "MIT",
"dependencies": {
"picomatch": "^2.2.1"
},
@@ -25733,6 +26506,7 @@
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
"integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
+ "license": "MIT",
"dependencies": {
"any-promise": "^1.0.0"
}
@@ -25741,6 +26515,7 @@
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
"integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
+ "license": "MIT",
"dependencies": {
"thenify": ">= 3.1.0 < 4"
},
@@ -25786,6 +26561,7 @@
"version": "0.2.15",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
"integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
+ "license": "MIT",
"dependencies": {
"fdir": "^6.5.0",
"picomatch": "^4.0.3"
@@ -25801,6 +26577,7 @@
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "license": "MIT",
"engines": {
"node": ">=12.0.0"
},
@@ -25817,6 +26594,7 @@
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+ "license": "MIT",
"engines": {
"node": ">=12"
},
@@ -25917,7 +26695,8 @@
"node_modules/ts-interface-checker": {
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
- "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="
+ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
+ "license": "Apache-2.0"
},
"node_modules/ts-jest": {
"version": "29.1.5",
@@ -26225,6 +27004,16 @@
"node": ">=16 || 14 >=14.17"
}
},
+ "node_modules/tunnel": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
+ "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.6.11 <=0.7.0 || >=0.7.3"
+ }
+ },
"node_modules/type-check": {
"version": "0.4.0",
"dev": true,
@@ -26305,6 +27094,7 @@
"resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
"integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bound": "^1.0.3",
"es-errors": "^1.3.0",
@@ -26319,6 +27109,7 @@
"resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz",
"integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bind": "^1.0.8",
"for-each": "^0.3.3",
@@ -26338,6 +27129,7 @@
"resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz",
"integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"available-typed-arrays": "^1.0.7",
"call-bind": "^1.0.8",
@@ -26359,6 +27151,7 @@
"resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz",
"integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bind": "^1.0.7",
"for-each": "^0.3.3",
@@ -26486,6 +27279,13 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/ufo": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.2.tgz",
+ "integrity": "sha512-heMioaxBcG9+Znsda5Q8sQbWnLJSl98AFDXTO80wELWEzX3hordXsTdxrIfMQoO9IY1MEnoGoPjpoKpMj+Yx0Q==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/uglify-js": {
"version": "3.18.0",
"license": "BSD-2-Clause",
@@ -26501,6 +27301,7 @@
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
"integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bound": "^1.0.3",
"has-bigints": "^1.0.2",
@@ -26534,6 +27335,19 @@
"node": "*"
}
},
+ "node_modules/undici": {
+ "version": "5.29.0",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz",
+ "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@fastify/busboy": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=14.0"
+ }
+ },
"node_modules/undici-types": {
"version": "6.21.0",
"license": "MIT"
@@ -26681,6 +27495,7 @@
"integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==",
"dev": true,
"hasInstallScript": true,
+ "license": "MIT",
"dependencies": {
"napi-postinstall": "^0.3.0"
},
@@ -26762,6 +27577,16 @@
"node": ">= 0.10"
}
},
+ "node_modules/url-join": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/url-join/-/url-join-5.0.0.tgz",
+ "integrity": "sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ }
+ },
"node_modules/urlpattern-polyfill": {
"version": "10.0.0",
"license": "MIT"
@@ -26770,6 +27595,7 @@
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz",
"integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==",
+ "license": "MIT",
"dependencies": {
"tslib": "^2.0.0"
},
@@ -26790,6 +27616,7 @@
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz",
"integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==",
+ "license": "MIT",
"dependencies": {
"detect-node-es": "^1.1.0",
"tslib": "^2.0.0"
@@ -27018,6 +27845,7 @@
"resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz",
"integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"is-bigint": "^1.1.0",
"is-boolean-object": "^1.2.1",
@@ -27037,6 +27865,7 @@
"resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz",
"integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"function.prototype.name": "^1.1.6",
@@ -27064,6 +27893,7 @@
"resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz",
"integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"is-map": "^2.0.3",
"is-set": "^2.0.3",
@@ -27087,6 +27917,7 @@
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz",
"integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"available-typed-arrays": "^1.0.7",
"call-bind": "^1.0.8",
@@ -27498,10 +28329,24 @@
"version": "3.25.76",
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
+ "license": "MIT",
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
},
+ "node_modules/zod-package-json": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/zod-package-json/-/zod-package-json-1.2.0.tgz",
+ "integrity": "sha512-tamtgPM3MkP+obfO2dLr/G+nYoYkpJKmuHdYEy6IXRKfLybruoJ5NUj0lM0LxwOpC9PpoGLbll1ecoeyj43Wsg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "zod": "^3.25.64"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
"node_modules/zwitch": {
"version": "2.0.4",
"dev": true,
diff --git a/package.json b/package.json
index 7ffba608c..a27f72dc1 100644
--- a/package.json
+++ b/package.json
@@ -45,20 +45,21 @@
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-sonarjs": "^0.25.1",
"husky": "^8.0.3",
+ "istanbul-merge": "^2.0.0",
"istanbul-reporter-html-monorepo": "^1.1.3",
"jest": "^29.4.0",
"lerna": "^6.4.1",
"lint-staged": "^13.1.0",
"nx": "15.6.2",
"nyc": "^17.1.0",
+ "pkg-pr-new": "^0.0.62",
"prettier": "^3.2.5",
"ts-jest": "^29.0.5",
"typedoc": "^0.26.11",
"typedoc-plugin-frontmatter": "1.0.0",
"typedoc-plugin-inline-sources": "1.2.0",
"typedoc-plugin-markdown": "4.2.10",
- "typescript": "5.1",
- "istanbul-merge": "^2.0.0"
+ "typescript": "5.1"
},
"workspaces": [
"packages/*"
diff --git a/packages/api/src/graphql/modules/BlockResolver.ts b/packages/api/src/graphql/modules/BlockResolver.ts
index 036184873..0acb876ca 100644
--- a/packages/api/src/graphql/modules/BlockResolver.ts
+++ b/packages/api/src/graphql/modules/BlockResolver.ts
@@ -4,7 +4,7 @@ import { Arg, Field, ObjectType, Query } from "type-graphql";
import { GraphqlModule, graphqlModule } from "../GraphqlModule";
-import { BatchTransactionModel } from "./model/BatchTransactionModel";
+import { TransactionExecutionResultModel } from "./model/TransactionExecutionResultModel";
@ObjectType()
export class BlockModel {
@@ -12,9 +12,9 @@ export class BlockModel {
return new BlockModel(
Number(block.networkState.during.block.height.toBigInt()),
block.transactions.map((tx) =>
- BatchTransactionModel.fromServiceLayerModel({
+ TransactionExecutionResultModel.fromServiceLayerModel({
tx: tx.tx,
- status: tx.status.toBoolean(),
+ status: tx.status,
statusMessage: tx.statusMessage,
})
),
@@ -33,15 +33,15 @@ export class BlockModel {
@Field()
height: number;
- @Field(() => [BatchTransactionModel])
- txs: BatchTransactionModel[];
+ @Field(() => [TransactionExecutionResultModel])
+ txs: TransactionExecutionResultModel[];
@Field()
transactionsHash: string;
private constructor(
height: number,
- txs: BatchTransactionModel[],
+ txs: TransactionExecutionResultModel[],
transactionsHash: string,
hash: string,
previousBlockHash: string | undefined
diff --git a/packages/api/src/graphql/modules/MempoolResolver.ts b/packages/api/src/graphql/modules/MempoolResolver.ts
index 034eee651..0ea9c1a0d 100644
--- a/packages/api/src/graphql/modules/MempoolResolver.ts
+++ b/packages/api/src/graphql/modules/MempoolResolver.ts
@@ -161,7 +161,10 @@ export class MempoolResolver extends GraphqlModule {
"Returns the hashes of all transactions that are currently inside the mempool",
})
public async transactions() {
- const txs = await this.transactionStorage.getPendingUserTransactions();
+ const txs = await this.transactionStorage.getPendingUserTransactions(
+ 0,
+ 1000
+ );
return txs.map((x) => x.hash().toString());
}
}
diff --git a/packages/api/src/graphql/modules/model/BatchTransactionModel.ts b/packages/api/src/graphql/modules/model/TransactionExecutionResultModel.ts
similarity index 69%
rename from packages/api/src/graphql/modules/model/BatchTransactionModel.ts
rename to packages/api/src/graphql/modules/model/TransactionExecutionResultModel.ts
index 316218778..0998e59c2 100644
--- a/packages/api/src/graphql/modules/model/BatchTransactionModel.ts
+++ b/packages/api/src/graphql/modules/model/TransactionExecutionResultModel.ts
@@ -1,16 +1,18 @@
import { ObjectType, Field } from "type-graphql";
-import { BatchTransaction } from "@proto-kit/sequencer";
import { IsBoolean } from "class-validator";
+import { TransactionExecutionResult } from "@proto-kit/sequencer";
import { TransactionObject } from "../MempoolResolver";
@ObjectType()
-export class BatchTransactionModel {
- public static fromServiceLayerModel(cbt: BatchTransaction) {
+export class TransactionExecutionResultModel {
+ public static fromServiceLayerModel(
+ cbt: Pick
+ ) {
const { tx, status, statusMessage } = cbt;
- return new BatchTransactionModel(
+ return new TransactionExecutionResultModel(
TransactionObject.fromServiceLayerModel(tx),
- status,
+ status.toBoolean(),
statusMessage
);
}
diff --git a/packages/cli/src/scripts/bridge/deposit.ts b/packages/cli/src/scripts/bridge/deposit.ts
index 0f222b80a..cfb4ad492 100644
--- a/packages/cli/src/scripts/bridge/deposit.ts
+++ b/packages/cli/src/scripts/bridge/deposit.ts
@@ -9,7 +9,7 @@ import {
AppChain,
} from "@proto-kit/sequencer";
import { Runtime } from "@proto-kit/module";
-import { Protocol } from "@proto-kit/protocol";
+import { DispatchSmartContract, Protocol } from "@proto-kit/protocol";
import { DefaultConfigs, DefaultModules } from "@proto-kit/stack";
import {
AccountUpdate,
@@ -118,7 +118,10 @@ export default async function (
BridgingModule
);
- const { settlement, dispatch } = settlementModule.getContracts();
+ const settlement = settlementModule.getSettlementContract();
+ const dispatch =
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
+ bridgingModule.getDispatchContract() as DispatchSmartContract;
await fetchAccount({ publicKey: fromPrivateKey.toPublicKey() });
await fetchAccount({ publicKey: settlement.address });
@@ -161,12 +164,11 @@ export default async function (
);
console.log(tx.toPretty());
- settlementModule.signTransaction(
- tx,
- [fromPrivateKey],
- [tokenOwnerPrivateKey],
- [dispatch.address]
- );
+ settlementModule.utils.signTransaction(tx, {
+ signingPublicKeys: [fromPrivateKey.toPublicKey()],
+ preventNoncePreconditionFor: [dispatch.address],
+ signingWithSignatureCheck: [tokenOwnerPrivateKey.toPublicKey()],
+ });
console.log("Sending...");
console.log(tx.toPretty());
diff --git a/packages/cli/src/scripts/bridge/redeem.ts b/packages/cli/src/scripts/bridge/redeem.ts
index 35bc126d5..7a3b2c039 100644
--- a/packages/cli/src/scripts/bridge/redeem.ts
+++ b/packages/cli/src/scripts/bridge/redeem.ts
@@ -134,7 +134,10 @@ export default async function (
SettlementModule
);
- settlementModule.signTransaction(tx, [toPrivateKey], [tokenOwnerPrivateKey]);
+ settlementModule.utils.signTransaction(tx, {
+ signingPublicKeys: [toPrivateKey.toPublicKey()],
+ signingWithSignatureCheck: [tokenOwnerPrivateKey.toPublicKey()],
+ });
console.log("Sending...");
diff --git a/packages/cli/src/scripts/settlement/deploy-token.ts b/packages/cli/src/scripts/settlement/deploy-token.ts
index 28c707158..96d06a92d 100644
--- a/packages/cli/src/scripts/settlement/deploy-token.ts
+++ b/packages/cli/src/scripts/settlement/deploy-token.ts
@@ -1,7 +1,7 @@
/* eslint-disable no-console */
/* eslint-disable func-names */
import { Runtime } from "@proto-kit/module";
-import { Protocol } from "@proto-kit/protocol";
+import { DispatchSmartContract, Protocol } from "@proto-kit/protocol";
import {
ArchiveNode,
MinaTransactionSender,
@@ -10,6 +10,7 @@ import {
SettlementModule,
SignedSettlementPermissions,
AppChain,
+ BridgingModule,
} from "@proto-kit/sequencer";
import {
AccountUpdate,
@@ -98,6 +99,11 @@ export default async function (
SettlementModule
);
+ const bridgingModule = appChain.sequencer.resolveOrFail(
+ "BridgingModule",
+ BridgingModule
+ );
+
const isSignedSettlement = settlementModule.utils.isSignedSettlement();
const tokenOwnerKey = PrivateKey.fromBase58(
@@ -155,11 +161,13 @@ export default async function (
console.log("Sending deploy transaction...");
console.log(tx.toPretty());
- settlementModule.signTransaction(
- tx,
- [feepayerPrivateKey, tokenOwnerKey, tokenAdminKey],
- [tokenOwnerKey, tokenAdminKey]
- );
+ settlementModule.utils.signTransaction(tx, {
+ signingWithSignatureCheck: [
+ tokenOwnerKey.toPublicKey(),
+ tokenAdminKey.toPublicKey(),
+ ],
+ signingPublicKeys: [feepayerPrivateKey.toPublicKey()],
+ });
await appChain.sequencer
.resolveOrFail("TransactionSender", MinaTransactionSender)
@@ -193,11 +201,14 @@ export default async function (
await tokenOwner!.mint(receiverPublicKey, UInt64.from(mintAmount));
}
);
- settlementModule.utils.signTransaction(
- tx,
- [feepayerPrivateKey],
- [tokenOwnerKey, tokenAdminKey]
- );
+
+ settlementModule.utils.signTransaction(tx, {
+ signingPublicKeys: [feepayerPrivateKey.toPublicKey()],
+ signingWithSignatureCheck: [
+ tokenOwnerKey.toPublicKey(),
+ tokenAdminKey.toPublicKey(),
+ ],
+ });
await appChain.sequencer
.resolveOrFail("TransactionSender", MinaTransactionSender)
@@ -205,19 +216,23 @@ export default async function (
}
async function deployBridge() {
- const { settlement, dispatch } = settlementModule.getAddresses();
+ const settlement = settlementModule.getSettlementContract();
+
+ const dispatch =
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
+ bridgingModule.getDispatchContract() as DispatchSmartContract;
+
await fetchAccount({
- publicKey: settlementModule.config.feepayer.toPublicKey(),
+ publicKey: settlementModule.utils.getSigner(),
});
- await fetchAccount({ publicKey: settlement });
- await fetchAccount({ publicKey: dispatch });
+ await fetchAccount({ publicKey: settlement.address });
+ await fetchAccount({ publicKey: dispatch.address });
const tokenOwner = new FungibleToken(tokenOwnerKey.toPublicKey());
// SetAdminEvent.
- await settlementModule.deployTokenBridge(
+ await bridgingModule.deployTokenBridge(
tokenOwner,
- tokenOwnerKey,
- tokenBridgeKey,
+ tokenBridgeKey.toPublicKey(),
{}
);
console.log(
diff --git a/packages/cli/src/scripts/settlement/deploy.ts b/packages/cli/src/scripts/settlement/deploy.ts
index 9e0530fb0..c36f836fe 100644
--- a/packages/cli/src/scripts/settlement/deploy.ts
+++ b/packages/cli/src/scripts/settlement/deploy.ts
@@ -9,7 +9,7 @@ import {
SettlementModule,
AppChain,
} from "@proto-kit/sequencer";
-import { PrivateKey, Provable } from "o1js";
+import { Provable, PublicKey } from "o1js";
import "reflect-metadata";
import { container } from "tsyringe";
import { DefaultConfigs, DefaultModules } from "@proto-kit/stack";
@@ -59,25 +59,22 @@ export default async function (options?: LoadEnvOptions) {
console.log("Deploying settlement contracts...");
- await settlementModule.deploy(
- PrivateKey.fromBase58(
- getRequiredEnv("PROTOKIT_SETTLEMENT_CONTRACT_PRIVATE_KEY")
+ await settlementModule.deploy({
+ settlementContract: PublicKey.fromBase58(
+ getRequiredEnv("PROTOKIT_SETTLEMENT_CONTRACT_PUBLIC_KEY")
),
- PrivateKey.fromBase58(
- getRequiredEnv("PROTOKIT_DISPATCHER_CONTRACT_PRIVATE_KEY")
+ dispatchContract: PublicKey.fromBase58(
+ getRequiredEnv("PROTOKIT_DISPATCHER_CONTRACT_PUBLIC_KEY")
),
- PrivateKey.fromBase58(
- getRequiredEnv("PROTOKIT_MINA_BRIDGE_CONTRACT_PRIVATE_KEY")
- )
- );
+ });
Provable.log("Deployed and initialized settlement contracts", {
- settlement: PrivateKey.fromBase58(
- getRequiredEnv("PROTOKIT_SETTLEMENT_CONTRACT_PRIVATE_KEY")
- ).toPublicKey(),
- dispatcher: PrivateKey.fromBase58(
- getRequiredEnv("PROTOKIT_DISPATCHER_CONTRACT_PRIVATE_KEY")
- ).toPublicKey(),
+ settlement: PublicKey.fromBase58(
+ getRequiredEnv("PROTOKIT_SETTLEMENT_CONTRACT_PUBLIC_KEY")
+ ),
+ dispatcher: PublicKey.fromBase58(
+ getRequiredEnv("PROTOKIT_DISPATCHER_CONTRACT_PUBLIC_KEY")
+ ),
});
await appChain.close();
diff --git a/packages/common/src/compiling/CompileRegistry.ts b/packages/common/src/compiling/CompileRegistry.ts
index e34dbc4b5..a85766ffe 100644
--- a/packages/common/src/compiling/CompileRegistry.ts
+++ b/packages/common/src/compiling/CompileRegistry.ts
@@ -47,22 +47,17 @@ export class CompileRegistry {
return result;
}
- public async compile(target: CompileTarget, proverNeeded: boolean = true) {
- if (this.artifacts[target.name] === undefined || this.inForceProverBlock) {
+ public async compile(target: CompileTarget, nameOverride?: string) {
+ const name = nameOverride ?? target.name;
+ if (this.artifacts[name] === undefined || this.inForceProverBlock) {
const artifact = await this.compiler.compileContract(target);
- this.artifacts[target.name] = artifact;
+ this.artifacts[name] = artifact;
return artifact;
}
- return this.artifacts[target.name];
+ return this.artifacts[name];
}
public getArtifact(name: string): CompileArtifact | undefined {
- if (this.artifacts[name] === undefined) {
- throw new Error(
- `Artifact for ${name} not available, did you compile it via the CompileRegistry?`
- );
- }
-
return this.artifacts[name];
}
diff --git a/packages/common/src/log.ts b/packages/common/src/log.ts
index ed3c39ef1..a8659d239 100644
--- a/packages/common/src/log.ts
+++ b/packages/common/src/log.ts
@@ -28,6 +28,8 @@ function logProvable(
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
if (process.env?.IN_CI ?? false) {
loglevel.setLevel("ERROR");
+} else {
+ loglevel.setLevel("INFO");
}
const timeMap: Record = {};
diff --git a/packages/common/src/trees/sparse/RollupMerkleTree.ts b/packages/common/src/trees/sparse/RollupMerkleTree.ts
index 1974e7078..e7503df46 100644
--- a/packages/common/src/trees/sparse/RollupMerkleTree.ts
+++ b/packages/common/src/trees/sparse/RollupMerkleTree.ts
@@ -7,6 +7,17 @@ import { TypedClass } from "../../types";
import { MerkleTreeStore } from "./MerkleTreeStore";
import { InMemoryMerkleTreeStorage } from "./InMemoryMerkleTreeStorage";
+/**
+ * More efficient version of `maybeSwapBad` which
+ * reuses an intermediate variable
+ */
+export function maybeSwap(b: Bool, x: Field, y: Field): [Field, Field] {
+ const m = b.toField().mul(x.sub(y)); // b*(x - y)
+ const x1 = y.add(m); // y + b*(x - y)
+ const y2 = x.sub(m); // x - b*(x - y) = x + b*(y - x)
+ return [x1, y2];
+}
+
export class StructTemplate extends Struct({
path: Provable.Array(Field, 0),
isLeft: Provable.Array(Bool, 0),
@@ -22,6 +33,11 @@ export interface AbstractMerkleWitness extends StructTemplate {
*/
calculateRoot(hash: Field): Field;
+ calculateRootIncrement(
+ index: Field,
+ leaf: Field
+ ): [Field, AbstractMerkleWitness];
+
/**
* Calculates the index of the leaf node that belongs to this Witness.
* @returns Index of the leaf.
@@ -119,6 +135,24 @@ export interface AbstractMerkleTreeClass {
* It also holds the Witness class under tree.WITNESS
*/
export function createMerkleTree(height: number): AbstractMerkleTreeClass {
+ function generateZeroes() {
+ const zeroes = [0n];
+ for (let index = 1; index < height; index += 1) {
+ const previousLevel = Field(zeroes[index - 1]);
+ zeroes.push(Poseidon.hash([previousLevel, previousLevel]).toBigInt());
+ }
+ return zeroes;
+ }
+
+ let zeroCache: bigint[] | undefined = undefined;
+
+ function getZeroes() {
+ if (zeroCache === undefined) {
+ zeroCache = generateZeroes();
+ }
+ return zeroCache;
+ }
+
/**
* The {@link RollupMerkleWitness} class defines a circuit-compatible base class
* for [Merkle Witness'](https://computersciencewiki.org/index.php/Merkle_proof).
@@ -147,7 +181,7 @@ export function createMerkleTree(height: number): AbstractMerkleTreeClass {
for (let index = 1; index < n; ++index) {
const isLeft = this.isLeft[index - 1];
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
+
const [left, right] = maybeSwap(isLeft, hash, this.path[index - 1]);
hash = Poseidon.hash([left, right]);
}
@@ -155,6 +189,73 @@ export function createMerkleTree(height: number): AbstractMerkleTreeClass {
return hash;
}
+ public calculateRootIncrement(
+ leafIndex: Field,
+ leaf: Field
+ ): [Field, RollupMerkleWitness] {
+ const root = this.calculateRoot(leaf);
+
+ const newWitness = Provable.witness(RollupMerkleWitness, () => {
+ const zero = getZeroes();
+
+ if (zero.length === 0) {
+ throw new Error("Zeroes not initialized");
+ }
+ const zeroes = zero.map((x) => Field(x));
+
+ let hash = leaf;
+ const n = this.height();
+
+ let notDiverged = true;
+ const newPath = leafIndex.add(1).toBits();
+ newPath.push(Bool(false));
+
+ const newSiblings: Field[] = [];
+ const newIsLefts: Bool[] = [];
+
+ for (let index = 0; index < n - 1; ++index) {
+ const isLeft = this.isLeft[index];
+ const sibling = this.path[index];
+
+ const newIsLeft = newPath[index].not();
+
+ // Bool(true) default for root level
+ let convergesNextLevel = true;
+ if (index < n - 2) {
+ convergesNextLevel = newPath[index + 1]
+ .equals(this.isLeft[index + 1])
+ .not()
+ .toBoolean();
+ }
+
+ const nextSibling =
+ // eslint-disable-next-line no-nested-ternary
+ convergesNextLevel && notDiverged
+ ? hash
+ : notDiverged
+ ? zeroes[index]
+ : sibling;
+
+ notDiverged = notDiverged && !convergesNextLevel;
+
+ newSiblings.push(nextSibling);
+ newIsLefts.push(newIsLeft);
+
+ const [left, right] = maybeSwap(isLeft, hash, sibling);
+ hash = Poseidon.hash([left, right]);
+ }
+
+ return new RollupMerkleWitness({
+ isLeft: newIsLefts,
+ path: newSiblings,
+ });
+ });
+
+ newWitness.calculateIndex().assertEquals(leafIndex.add(1));
+
+ return [root, newWitness];
+ }
+
/**
* Calculates the index of the leaf node that belongs to this Witness.
* @returns Index of the leaf.
@@ -215,6 +316,7 @@ export function createMerkleTree(height: number): AbstractMerkleTreeClass {
});
}
}
+
return class AbstractRollupMerkleTree implements AbstractMerkleTree {
public static HEIGHT = height;
@@ -238,13 +340,7 @@ export function createMerkleTree(height: number): AbstractMerkleTreeClass {
public constructor(store: MerkleTreeStore) {
this.store = store;
- this.zeroes = [0n];
- for (let index = 1; index < AbstractRollupMerkleTree.HEIGHT; index += 1) {
- const previousLevel = Field(this.zeroes[index - 1]);
- this.zeroes.push(
- Poseidon.hash([previousLevel, previousLevel]).toBigInt()
- );
- }
+ this.zeroes = generateZeroes();
}
public assertIndexRange(index: bigint) {
@@ -414,14 +510,3 @@ export function createMerkleTree(height: number): AbstractMerkleTreeClass {
export class RollupMerkleTree extends createMerkleTree(256) {}
export class RollupMerkleTreeWitness extends RollupMerkleTree.WITNESS {}
-
-/**
- * More efficient version of `maybeSwapBad` which
- * reuses an intermediate variable
- */
-export function maybeSwap(b: Bool, x: Field, y: Field): [Field, Field] {
- const m = b.toField().mul(x.sub(y)); // b*(x - y)
- const x1 = y.add(m); // y + b*(x - y)
- const y2 = x.sub(m); // x - b*(x - y) = x + b*(y - x)
- return [x1, y2];
-}
diff --git a/packages/common/src/types.ts b/packages/common/src/types.ts
index 4d25b1192..f2a0e452e 100644
--- a/packages/common/src/types.ts
+++ b/packages/common/src/types.ts
@@ -1,5 +1,13 @@
// allows to reference interfaces as 'classes' rather than instances
-import { Bool, DynamicProof, Field, Proof, ProofBase, PublicKey } from "o1js";
+import {
+ Bool,
+ DynamicProof,
+ Field,
+ Proof,
+ ProofBase,
+ PublicKey,
+ Option,
+} from "o1js";
export type TypedClass = new (...args: any[]) => Class;
@@ -56,3 +64,5 @@ export type InferProofBase<
: ProofType extends DynamicProof
? ProofBase
: undefined;
+
+export class O1PublicKeyOption extends Option(PublicKey) {}
diff --git a/packages/common/src/utils.ts b/packages/common/src/utils.ts
index 0576aacb5..27a0a036c 100644
--- a/packages/common/src/utils.ts
+++ b/packages/common/src/utils.ts
@@ -87,7 +87,11 @@ export function yieldSequential(
array,
async ([state, collectedTargets], curr, index, arr) => {
const [newState, addition] = await callbackfn(state, curr, index, arr);
- return [newState, collectedTargets.concat(addition)];
+ // The reason we wrap this in an array here is for a special case where Target is a tuple
+ // or array itself. In this case, js interprets by flattening the Value in the array
+ // (which it does when a function (like concat) uses a spread operator and the
+ // input is an array)
+ return [newState, collectedTargets.concat([addition])];
},
[initialValue, []]
);
@@ -105,6 +109,18 @@ export function mapSequential(
}, Promise.resolve([]));
}
+export function unzip(array: [A, B][]): [A[], B[]] {
+ const as = array.map(([a]) => a);
+ const bs = array.map(([, b]) => b);
+ return [as, bs];
+}
+
+export function assertSizeOneOrTwo(arr: T[]): asserts arr is [T] | [T, T] {
+ if (!(arr.length === 1 || arr.length === 2)) {
+ throw new Error("Given array not size 1 or 2");
+ }
+}
+
/**
* Computes a dummy value for the given value type.
*
diff --git a/packages/common/test/trees/MerkleTree.test.ts b/packages/common/test/trees/MerkleTree.test.ts
index 221c8d70e..b2c673eb8 100644
--- a/packages/common/test/trees/MerkleTree.test.ts
+++ b/packages/common/test/trees/MerkleTree.test.ts
@@ -217,4 +217,35 @@ describe.each([4, 16, 256])("cachedMerkleTree - %s", (height) => {
tree.getNode(0, index);
}).toThrow("Index greater than maximum leaf number");
});
+
+ it("witness incrementing", () => {
+ tree.setLeaf(0n, Field(3256));
+ tree.setLeaf(1n, Field(3256));
+ tree.setLeaf(2n, Field(3256));
+
+ const witness = tree.getWitness(3n);
+
+ const [root, newWitness] = witness.calculateRootIncrement(
+ Field(3),
+ Field(1234)
+ );
+ tree.setLeaf(3n, Field(1234));
+
+ expect(tree.getRoot().toString()).toStrictEqual(root.toString());
+ expect(newWitness.calculateIndex().toString()).toStrictEqual("4");
+
+ const [root2, newWitness2] = newWitness.calculateRootIncrement(
+ Field(4),
+ Field(4321)
+ );
+ tree.setLeaf(4n, Field(4321));
+
+ expect(tree.getRoot().toString()).toStrictEqual(root2.toString());
+ expect(newWitness2.calculateIndex().toString()).toStrictEqual("5");
+
+ const root3 = newWitness2.calculateRoot(Field(555));
+ tree.setLeaf(5n, Field(555));
+
+ expect(tree.getRoot().toString()).toStrictEqual(root3.toString());
+ });
});
diff --git a/packages/indexer/src/IndexerNotifier.ts b/packages/indexer/src/IndexerNotifier.ts
index 5f6816f8b..93a33921c 100644
--- a/packages/indexer/src/IndexerNotifier.ts
+++ b/packages/indexer/src/IndexerNotifier.ts
@@ -81,7 +81,7 @@ export class IndexerNotifier extends SequencerModule> {
await txQueue.addTask(task);
} catch (err) {
- console.error("Failed to add pending-tx task", err);
+ log.error("Failed to add pending-tx task", err);
}
});
this.sequencer.events.on("batch-produced", async (batch) => {
diff --git a/packages/indexer/src/tasks/IndexPendingTxTask.ts b/packages/indexer/src/tasks/IndexPendingTxTask.ts
index db468660d..9d448c6a7 100644
--- a/packages/indexer/src/tasks/IndexPendingTxTask.ts
+++ b/packages/indexer/src/tasks/IndexPendingTxTask.ts
@@ -30,7 +30,7 @@ export class IndexPendingTxTask
public async compute(input: PendingTransaction): Promise {
try {
- await this.transactionStorage.pushUserTransaction(input);
+ await this.transactionStorage.pushUserTransaction(input, 0);
return "";
} catch (err) {
log.error("Failed to process pending tx task", err);
diff --git a/packages/library/src/hooks/RuntimeFeeAnalyzerService.ts b/packages/library/src/hooks/RuntimeFeeAnalyzerService.ts
index 707d80a4c..1e8d2581c 100644
--- a/packages/library/src/hooks/RuntimeFeeAnalyzerService.ts
+++ b/packages/library/src/hooks/RuntimeFeeAnalyzerService.ts
@@ -79,8 +79,8 @@ export class RuntimeFeeAnalyzerService extends ConfigurableModule {
+ public async beforeTransaction({
+ transaction: { transaction },
+ }: BeforeTransactionHookArguments): Promise {
const feeConfig = Provable.witness(MethodFeeConfigData, () =>
- this.feeAnalyzer.getFeeConfig(
- executionData.transaction.methodId.toBigInt()
- )
+ this.feeAnalyzer.getFeeConfig(transaction.methodId.toBigInt())
);
const witness = Provable.witness(
RuntimeFeeAnalyzerService.getWitnessType(),
- () =>
- this.feeAnalyzer.getWitness(
- executionData.transaction.methodId.toBigInt()
- )
+ () => this.feeAnalyzer.getWitness(transaction.methodId.toBigInt())
);
const root = Field(this.feeAnalyzer.getRoot());
@@ -147,14 +142,14 @@ export class TransactionFeeHook extends ProvableTransactionHook {
+ public async removeTransactionWhen({
+ transaction,
+ }: BeforeTransactionHookArguments): Promise {
const feeConfig = this.feeAnalyzer.getFeeConfig(
- args.transaction.methodId.toBigInt()
+ transaction.transaction.methodId.toBigInt()
);
const fee = this.getFee(feeConfig);
const tokenId = new TokenId(this.config.tokenId);
- const feeRecipient = PublicKey.fromBase58(this.config.feeRecipient);
const balanceAvailable = await this.balances.balances.get({
tokenId,
- address: feeRecipient,
+ address: transaction.transaction.sender.value,
});
- return balanceAvailable.orElse(Balance.from(0)).lessThan(fee).toBoolean();
+ return balanceAvailable
+ .orElse(Balance.from(0))
+ .lessThan(fee)
+ .or(transaction.isMessage)
+ .toBoolean();
}
}
diff --git a/packages/library/src/protocol/VanillaProtocolModules.ts b/packages/library/src/protocol/VanillaProtocolModules.ts
index 89a87d08b..20b936b05 100644
--- a/packages/library/src/protocol/VanillaProtocolModules.ts
+++ b/packages/library/src/protocol/VanillaProtocolModules.ts
@@ -1,11 +1,7 @@
import {
- AccountStateHook,
- BlockHeightHook,
- BlockProver,
MandatoryProtocolModulesRecord,
ProtocolModulesRecord,
- StateTransitionProver,
- LastStateRootBlockHook,
+ Protocol,
} from "@proto-kit/protocol";
import { PrivateKey } from "o1js";
@@ -20,11 +16,7 @@ export class VanillaProtocolModules {
additionalModules: ProtocolModules
): MandatoryProtocolModulesRecord & ProtocolModules {
return {
- StateTransitionProver,
- BlockProver,
- AccountState: AccountStateHook,
- BlockHeight: BlockHeightHook,
- LastStateRoot: LastStateRootBlockHook,
+ ...Protocol.defaultModules(),
...additionalModules,
};
}
@@ -40,11 +32,7 @@ export class VanillaProtocolModules {
public static mandatoryConfig() {
return {
- BlockProver: {},
- StateTransitionProver: {},
- AccountState: {},
- BlockHeight: {},
- LastStateRoot: {},
+ ...Protocol.defaultConfig(),
};
}
diff --git a/packages/module/src/method/runtimeMethod.ts b/packages/module/src/method/runtimeMethod.ts
index d53a9439c..ffa8145af 100644
--- a/packages/module/src/method/runtimeMethod.ts
+++ b/packages/module/src/method/runtimeMethod.ts
@@ -25,11 +25,6 @@ const errors = {
runtimeNotProvided: (name: string) =>
new Error(`Runtime was not provided for module: ${name}`),
- methodInputsNotProvided: () =>
- new Error(
- "Method execution inputs not provided, provide them via context.inputs"
- ),
-
runtimeNameNotSet: () => new Error("Runtime name was not set"),
fieldNotConstant: (name: string) =>
diff --git a/packages/module/test/method/MethodParameterEncoder.test.ts b/packages/module/test/method/MethodParameterEncoder.test.ts
index 9f4bb5c05..38436ead8 100644
--- a/packages/module/test/method/MethodParameterEncoder.test.ts
+++ b/packages/module/test/method/MethodParameterEncoder.test.ts
@@ -1,3 +1,4 @@
+import "reflect-metadata";
import {
Struct,
Field,
diff --git a/packages/module/test/method/runtimeMethod-fail.test.ts b/packages/module/test/method/runtimeMethod-fail.test.ts
index 79eb331b7..56ba1e1d6 100644
--- a/packages/module/test/method/runtimeMethod-fail.test.ts
+++ b/packages/module/test/method/runtimeMethod-fail.test.ts
@@ -1,3 +1,4 @@
+import "reflect-metadata";
import { Bool, Field, PublicKey, Struct, ZkProgram } from "o1js";
import { noop } from "@proto-kit/common";
diff --git a/packages/persistance/prisma/migrations/20260117134313_transaction_priority/migration.sql b/packages/persistance/prisma/migrations/20260117134313_transaction_priority/migration.sql
new file mode 100644
index 000000000..e04752925
--- /dev/null
+++ b/packages/persistance/prisma/migrations/20260117134313_transaction_priority/migration.sql
@@ -0,0 +1,10 @@
+-- CreateTable
+CREATE TABLE "TransactionPriority" (
+ "transactionHash" TEXT NOT NULL,
+ "priority" BIGINT NOT NULL,
+
+ CONSTRAINT "TransactionPriority_pkey" PRIMARY KEY ("transactionHash")
+);
+
+-- AddForeignKey
+ALTER TABLE "TransactionPriority" ADD CONSTRAINT "TransactionPriority_transactionHash_fkey" FOREIGN KEY ("transactionHash") REFERENCES "Transaction"("hash") ON DELETE RESTRICT ON UPDATE CASCADE;
diff --git a/packages/persistance/prisma/migrations/20260122210623_transaction_input_paths/migration.sql b/packages/persistance/prisma/migrations/20260122210623_transaction_input_paths/migration.sql
new file mode 100644
index 000000000..8f9d6cd06
--- /dev/null
+++ b/packages/persistance/prisma/migrations/20260122210623_transaction_input_paths/migration.sql
@@ -0,0 +1,10 @@
+-- CreateTable
+CREATE TABLE "SkippedTransactionInputPaths" (
+ "transactionHash" TEXT NOT NULL,
+ "paths" DECIMAL(78,0)[],
+
+ CONSTRAINT "SkippedTransactionInputPaths_pkey" PRIMARY KEY ("transactionHash")
+);
+
+-- AddForeignKey
+ALTER TABLE "SkippedTransactionInputPaths" ADD CONSTRAINT "SkippedTransactionInputPaths_transactionHash_fkey" FOREIGN KEY ("transactionHash") REFERENCES "Transaction"("hash") ON DELETE RESTRICT ON UPDATE CASCADE;
diff --git a/packages/persistance/prisma/schema.prisma b/packages/persistance/prisma/schema.prisma
index d0ed1472e..3613a00a6 100644
--- a/packages/persistance/prisma/schema.prisma
+++ b/packages/persistance/prisma/schema.prisma
@@ -54,6 +54,28 @@ model Transaction {
executionResult TransactionExecutionResult?
IncomingMessageBatchTransaction IncomingMessageBatchTransaction[]
+
+ priority TransactionPriority?
+
+ inputPaths SkippedTransactionInputPaths?
+}
+
+model TransactionPriority {
+ transactionHash String
+
+ priority BigInt
+
+ Transaction Transaction @relation(fields: [transactionHash], references: [hash])
+
+ @@id([transactionHash])
+}
+
+model SkippedTransactionInputPaths {
+ transactionHash String @id
+
+ paths Decimal[] @db.Decimal(78, 0)
+
+ transaction Transaction @relation(fields: [transactionHash], references: [hash])
}
model TransactionExecutionResult {
diff --git a/packages/persistance/src/services/prisma/PrismaTransactionStorage.ts b/packages/persistance/src/services/prisma/PrismaTransactionStorage.ts
index d4544a7c4..5722421ed 100644
--- a/packages/persistance/src/services/prisma/PrismaTransactionStorage.ts
+++ b/packages/persistance/src/services/prisma/PrismaTransactionStorage.ts
@@ -9,6 +9,7 @@ import {
import type { PrismaConnection } from "../../PrismaDatabaseConnection";
import { TransactionMapper } from "./mappers/TransactionMapper";
+import { Decimal } from "./PrismaStateService";
@injectable()
export class PrismaTransactionStorage implements TransactionStorage {
@@ -19,7 +20,10 @@ export class PrismaTransactionStorage implements TransactionStorage {
) {}
@trace("db.txs.get")
- public async getPendingUserTransactions(): Promise {
+ public async getPendingUserTransactions(
+ offset: number,
+ limit?: number
+ ): Promise {
const { prismaClient } = this.connection;
const txs = await prismaClient.transaction.findMany({
@@ -30,7 +34,17 @@ export class PrismaTransactionStorage implements TransactionStorage {
isMessage: {
equals: false,
},
+ inputPaths: {
+ is: null,
+ },
+ },
+ orderBy: {
+ priority: {
+ priority: "desc",
+ },
},
+ skip: offset,
+ take: limit,
});
return txs.map((tx) => this.transactionMapper.mapIn(tx));
}
@@ -51,13 +65,27 @@ export class PrismaTransactionStorage implements TransactionStorage {
}
}
- public async pushUserTransaction(tx: PendingTransaction): Promise {
+ public async pushUserTransaction(
+ tx: PendingTransaction,
+ priority: number
+ ): Promise {
const { prismaClient } = this.connection;
- const result = await prismaClient.transaction.createMany({
- data: [this.transactionMapper.mapOut(tx)],
- skipDuplicates: true,
- });
+ const transactionData = this.transactionMapper.mapOut(tx);
+
+ const [result] = await prismaClient.$transaction([
+ prismaClient.transaction.createMany({
+ data: [transactionData],
+ skipDuplicates: true,
+ }),
+
+ prismaClient.transactionPriority.create({
+ data: {
+ priority,
+ transactionHash: transactionData.hash,
+ },
+ }),
+ ]);
return result.count === 1;
}
@@ -103,4 +131,29 @@ export class PrismaTransactionStorage implements TransactionStorage {
batch,
};
}
+
+ public async reportSkippedTransactions(
+ paths: Record
+ ): Promise {
+ const { prismaClient } = this.connection;
+
+ await prismaClient.skippedTransactionInputPaths.createMany({
+ data: Object.entries(paths).map(([transactionHash, pathArray]) => ({
+ transactionHash,
+ paths: pathArray.map((path) => new Decimal(path.toString())),
+ })),
+ });
+ }
+
+ public async reportChangedPaths(paths: bigint[]): Promise {
+ const { prismaClient } = this.connection;
+
+ await prismaClient.skippedTransactionInputPaths.deleteMany({
+ where: {
+ paths: {
+ hasSome: paths.map((path) => new Decimal(path.toString())),
+ },
+ },
+ });
+ }
}
diff --git a/packages/persistance/test-integration/PrismaBlockProduction.test.ts b/packages/persistance/test-integration/PrismaBlockProduction.test.ts
index f6299f6b1..e9d335156 100644
--- a/packages/persistance/test-integration/PrismaBlockProduction.test.ts
+++ b/packages/persistance/test-integration/PrismaBlockProduction.test.ts
@@ -251,7 +251,7 @@ describe("prisma integration", () => {
PrismaTransactionStorage
);
- const txs = await txResolver.getPendingUserTransactions();
+ const txs = await txResolver.getPendingUserTransactions(0);
expectDefined(transaction.transaction);
diff --git a/packages/persistance/test-integration/SequencerRestart.test.ts b/packages/persistance/test-integration/SequencerRestart.test.ts
index 940bc40ca..2864424b9 100644
--- a/packages/persistance/test-integration/SequencerRestart.test.ts
+++ b/packages/persistance/test-integration/SequencerRestart.test.ts
@@ -40,7 +40,7 @@ describe("sequencer restart", () => {
};
const teardown = async () => {
- await appChain.sequencer.resolve("Database").close();
+ await appChain.close();
};
beforeAll(async () => {
diff --git a/packages/persistance/test-integration/utils.ts b/packages/persistance/test-integration/utils.ts
index 7c50982c1..e62050794 100644
--- a/packages/persistance/test-integration/utils.ts
+++ b/packages/persistance/test-integration/utils.ts
@@ -126,6 +126,7 @@ export function createPrismaAppchain(
AccountState: {},
BlockProver: {},
StateTransitionProver: {},
+ TransactionProver: {},
BlockHeight: {},
LastStateRoot: {},
},
diff --git a/packages/protocol/src/hooks/AccountStateHook.ts b/packages/protocol/src/hooks/AccountStateHook.ts
index 6e05f4762..021b67999 100644
--- a/packages/protocol/src/hooks/AccountStateHook.ts
+++ b/packages/protocol/src/hooks/AccountStateHook.ts
@@ -14,15 +14,19 @@ export class AccountState extends Struct({
nonce: UInt64,
}) {}
+export type AccountStateHookConfig = {
+ maximumNonceLookahead?: number;
+};
+
@injectable()
-export class AccountStateHook extends ProvableTransactionHook {
+export class AccountStateHook extends ProvableTransactionHook {
@state() public accountState = StateMap.from(
PublicKey,
AccountState
);
public async beforeTransaction({
- transaction,
+ transaction: { transaction },
}: BeforeTransactionHookArguments) {
const sender = transaction.sender.value;
@@ -57,7 +61,7 @@ export class AccountStateHook extends ProvableTransactionHook {
// Under these conditions we want the tx removed from the mempool.
public async removeTransactionWhen({
- transaction,
+ transaction: { transaction },
}: BeforeTransactionHookArguments): Promise {
const sender = transaction.sender.value;
@@ -67,6 +71,10 @@ export class AccountStateHook extends ProvableTransactionHook {
const currentNonce = accountState.nonce;
- return transaction.nonce.value.lessThan(currentNonce).toBoolean();
+ const exceedsMaximumLookahead = transaction.nonce.value.greaterThan(
+ currentNonce.add(this.config.maximumNonceLookahead ?? 10)
+ );
+ const nonceIsInPast = transaction.nonce.value.lessThan(currentNonce);
+ return nonceIsInPast.or(exceedsMaximumLookahead).toBoolean();
}
}
diff --git a/packages/protocol/src/hooks/NoopSettlementHook.ts b/packages/protocol/src/hooks/NoopSettlementHook.ts
index 166ff678f..99ecbde77 100644
--- a/packages/protocol/src/hooks/NoopSettlementHook.ts
+++ b/packages/protocol/src/hooks/NoopSettlementHook.ts
@@ -5,14 +5,14 @@ import {
ProvableSettlementHook,
SettlementHookInputs,
} from "../settlement/modularity/ProvableSettlementHook";
-import { SettlementSmartContractBase } from "../settlement/contracts/SettlementSmartContract";
+import { SettlementContractType } from "../settlement/contracts/settlement/SettlementBase";
@injectable()
export class NoopSettlementHook extends ProvableSettlementHook<
Record
> {
public async beforeSettlement(
- contract: SettlementSmartContractBase,
+ contract: SettlementContractType,
state: SettlementHookInputs
) {
noop();
diff --git a/packages/protocol/src/index.ts b/packages/protocol/src/index.ts
index eeb2ba0d5..99cf03fdf 100644
--- a/packages/protocol/src/index.ts
+++ b/packages/protocol/src/index.ts
@@ -6,7 +6,7 @@ export * from "./model/StateTransitionProvableBatch";
export * from "./model/Option";
export * from "./model/Path";
export * from "./model/network/NetworkState";
-export * from "./model/transaction/SignedTransaction";
+export * from "./model/transaction/AuthorizedTransaction";
export * from "./model/transaction/RuntimeTransaction";
export * from "./model/transaction/ValueOption";
export * from "./model/MethodPublicOutput";
@@ -22,6 +22,7 @@ export * from "./prover/accumulators/StateTransitionReductionList";
export * from "./prover/accumulators/AppliedBatchHashList";
export * from "./prover/accumulators/WitnessedRootHashList";
export * from "./prover/accumulators/TransactionHashList";
+export * from "./prover/accumulators/BlockHashList";
export * from "./prover/block/BlockProver";
export * from "./prover/block/BlockProvable";
export * from "./prover/block/accummulators/RuntimeVerificationKeyTree";
@@ -29,6 +30,9 @@ export * from "./prover/block/accummulators/BlockHashMerkleTree";
export * from "./prover/block/services/RuntimeVerificationKeyRootService";
export * from "./prover/statetransition/StateTransitionProver";
export * from "./prover/statetransition/StateTransitionProvable";
+export * from "./prover/transaction/TransactionProver";
+export * from "./prover/transaction/TransactionProvable";
+export * from "./prover/utils";
export * from "./protocol/Protocol";
export * from "./protocol/ProtocolModule";
export * from "./protocol/ProtocolEnvironment";
@@ -45,8 +49,11 @@ export * from "./state/assert/assert";
export * from "./settlement/contracts/authorizations/ContractAuthorization";
export * from "./settlement/contracts/authorizations/UpdateMessagesHashAuth";
export * from "./settlement/contracts/authorizations/TokenBridgeDeploymentAuth";
-export * from "./settlement/contracts/SettlementSmartContract";
-export * from "./settlement/contracts/SettlementContractProtocolModule";
+export * from "./settlement/contracts/settlement/SettlementBase";
+export * from "./settlement/contracts/settlement/SettlementContract";
+export * from "./settlement/contracts/settlement/BridgingSettlementContract";
+export * from "./settlement/contracts/BridgingSettlementContractModule";
+export * from "./settlement/contracts/SettlementSmartContractModule";
export * from "./settlement/contracts/DispatchSmartContract";
export * from "./settlement/contracts/DispatchContractProtocolModule";
export * from "./settlement/contracts/BridgeContract";
@@ -60,6 +67,7 @@ export * from "./settlement/messages/OutgoingMessageArgument";
export * from "./settlement/messages/OutgoingMessage";
export * from "./settlement/modules/NetworkStateSettlementModule";
export * from "./settlement/messages/Deposit";
+export * from "./settlement/ContractArgsRegistry";
export { constants as ProtocolConstants } from "./Constants";
export * from "./hashing/protokit-prefixes";
export * from "./hashing/mina-prefixes";
diff --git a/packages/protocol/src/model/transaction/SignedTransaction.ts b/packages/protocol/src/model/transaction/AuthorizedTransaction.ts
similarity index 64%
rename from packages/protocol/src/model/transaction/SignedTransaction.ts
rename to packages/protocol/src/model/transaction/AuthorizedTransaction.ts
index 8f29c7752..a870624bb 100644
--- a/packages/protocol/src/model/transaction/SignedTransaction.ts
+++ b/packages/protocol/src/model/transaction/AuthorizedTransaction.ts
@@ -2,26 +2,30 @@ import { Bool, Field, Scalar, Signature, Struct, UInt64 } from "o1js";
import { RuntimeTransaction } from "./RuntimeTransaction";
-export class SignedTransaction extends Struct({
+export class AuthorizedTransaction extends Struct({
transaction: RuntimeTransaction,
signature: Signature,
+ isMessage: Bool,
}) {
public static getSignatureData(args: {
methodId: Field;
nonce: UInt64;
argsHash: Field;
}): Field[] {
+ // No isMessage here - we don't sign that
return [args.methodId, ...args.nonce.value.toFields(), args.argsHash];
}
- public static dummy(): SignedTransaction {
- return new SignedTransaction({
+ public static dummy(): AuthorizedTransaction {
+ return new AuthorizedTransaction({
transaction: RuntimeTransaction.dummyTransaction(),
signature: Signature.fromObject({
s: Scalar.from(0),
r: Field(0),
}),
+
+ isMessage: Bool(false),
});
}
@@ -31,17 +35,16 @@ export class SignedTransaction extends Struct({
public getSignatureData(): Field[] {
const { methodId, argsHash, nonce } = this.transaction;
- return SignedTransaction.getSignatureData({
+ return AuthorizedTransaction.getSignatureData({
nonce: nonce.value,
methodId,
argsHash,
});
}
- public validateSignature(): Bool {
- return this.signature.verify(
- this.transaction.sender.value,
- this.getSignatureData()
- );
+ public validateAuthorization(): Bool {
+ return this.signature
+ .verify(this.transaction.sender.value, this.getSignatureData())
+ .or(this.isMessage);
}
}
diff --git a/packages/protocol/src/protocol/Protocol.ts b/packages/protocol/src/protocol/Protocol.ts
index 0d1496d86..4b0e4d240 100644
--- a/packages/protocol/src/protocol/Protocol.ts
+++ b/packages/protocol/src/protocol/Protocol.ts
@@ -3,6 +3,7 @@ import {
ChildContainerProvider,
log,
ModuleContainer,
+ ModulesConfig,
ModulesRecord,
Startable,
StringKeyOf,
@@ -21,6 +22,10 @@ import { ProvableSettlementHook } from "../settlement/modularity/ProvableSettlem
import { NoopSettlementHook } from "../hooks/NoopSettlementHook";
import { AccountStateHook } from "../hooks/AccountStateHook";
import { NoopTransactionHook } from "../hooks/NoopTransactionHook";
+import { TransactionProvable } from "../prover/transaction/TransactionProvable";
+import { StateTransitionProver } from "../prover/statetransition/StateTransitionProver";
+import { TransactionProver } from "../prover/transaction/TransactionProver";
+import { BlockProver } from "../prover/block/BlockProver";
import { ProtocolModule } from "./ProtocolModule";
import { ProvableTransactionHook } from "./ProvableTransactionHook";
@@ -44,6 +49,10 @@ export type ProtocolModulesRecord = ModulesRecord<
TypedClass>
>;
+export interface TransactionProverType
+ extends ProtocolModule,
+ TransactionProvable {}
+
export interface BlockProverType extends ProtocolModule, BlockProvable {}
export interface StateTransitionProverType
@@ -51,6 +60,7 @@ export interface StateTransitionProverType
StateTransitionProvable {}
export type MandatoryProtocolModulesRecord = {
+ TransactionProver: TypedClass;
BlockProver: TypedClass;
StateTransitionProver: TypedClass;
AccountState: TypedClass;
@@ -115,6 +125,14 @@ export class Protocol<
return this.definition[moduleName] !== undefined;
}
+ public get transactionProver(): TransactionProvable {
+ // Why do I resolve directly here?
+ // I don't know exactly but generics don't let me use .resolve()
+ return this.container.resolve>(
+ "TransactionProver"
+ );
+ }
+
public get blockProver(): BlockProvable {
// Why do I resolve directly here?
// I don't know exactly but generics don't let me use .resolve()
@@ -129,6 +147,28 @@ export class Protocol<
>("StateTransitionProver");
}
+ public static defaultModules() {
+ return {
+ StateTransitionProver,
+ TransactionProver,
+ BlockProver,
+ AccountState: AccountStateHook,
+ BlockHeight: BlockHeightHook,
+ LastStateRoot: LastStateRootBlockHook,
+ };
+ }
+
+ public static defaultConfig() {
+ return {
+ StateTransitionProver: {},
+ TransactionProver: {},
+ BlockProver: {},
+ AccountState: {},
+ BlockHeight: {},
+ LastStateRoot: {},
+ } satisfies ModulesConfig>;
+ }
+
public getAreProofsEnabled(): AreProofsEnabled {
return this.container.resolve("AreProofsEnabled");
}
diff --git a/packages/protocol/src/protocol/ProvableBlockHook.ts b/packages/protocol/src/protocol/ProvableBlockHook.ts
index b5381e193..4de723a6f 100644
--- a/packages/protocol/src/protocol/ProvableBlockHook.ts
+++ b/packages/protocol/src/protocol/ProvableBlockHook.ts
@@ -2,56 +2,55 @@ import { Field } from "o1js";
import { NoConfig } from "@proto-kit/common";
import { NetworkState } from "../model/network/NetworkState";
-import { MethodPublicOutput } from "../model/MethodPublicOutput";
-import { BlockProverTransactionArguments } from "../prover/block/BlockProvable";
-
-import { TransitioningProtocolModule } from "./TransitioningProtocolModule";
import {
- AfterTransactionHookArguments,
- BeforeTransactionHookArguments,
- ProvableHookBlockState,
- toProvableHookBlockState,
-} from "./ProvableTransactionHook";
+ BlockProverPublicInput,
+ BlockArguments,
+ BlockProverState,
+} from "../prover/block/BlockProvable";
-export interface BeforeBlockHookArguments extends ProvableHookBlockState {}
+import { TransitioningProtocolModule } from "./TransitioningProtocolModule";
-export interface AfterBlockHookArguments extends BeforeBlockHookArguments {
- stateRoot: Field;
-}
-
-export function toBeforeTransactionHookArgument(
- executionData: Omit<
- BlockProverTransactionArguments,
- "verificationKeyAttestation"
- >,
- networkState: NetworkState,
- state: Parameters[0]
-): BeforeTransactionHookArguments {
- const { transaction, signature } = executionData;
+export type ProvableHookBlockState = Pick<
+ BlockProverPublicInput & BlockArguments,
+ "eternalTransactionsHash" | "incomingMessagesHash" | "blockHashRoot"
+>;
+export function toBeforeBlockHookArgument(
+ state: Pick<
+ BlockProverState,
+ "eternalTransactionsList" | "incomingMessages" | "blockHashRoot"
+ >
+) {
+ const { eternalTransactionsList, incomingMessages, blockHashRoot } = state;
return {
- networkState,
- transaction,
- signature,
- prover: toProvableHookBlockState(state),
+ eternalTransactionsHash: eternalTransactionsList.commitment,
+ incomingMessagesHash: incomingMessages.commitment,
+ blockHashRoot,
};
}
-export function toAfterTransactionHookArgument(
- executionData: Omit<
- BlockProverTransactionArguments,
- "verificationKeyAttestation"
+export function toAfterBlockHookArgument(
+ state: Pick<
+ BlockProverState,
+ "eternalTransactionsList" | "incomingMessages" | "blockHashRoot"
>,
- networkState: NetworkState,
- state: Parameters[0],
- runtimeResult: MethodPublicOutput
-): AfterTransactionHookArguments {
+ stateRoot: Field,
+ transactionsHash: Field
+) {
return {
- ...toBeforeTransactionHookArgument(executionData, networkState, state),
- runtimeResult,
+ ...toBeforeBlockHookArgument(state),
+ stateRoot,
+ transactionsHash,
};
}
+export interface BeforeBlockHookArguments extends ProvableHookBlockState {}
+
+export interface AfterBlockHookArguments extends BeforeBlockHookArguments {
+ stateRoot: Field;
+ transactionsHash: Field;
+}
+
// Purpose is to build transition from -> to network state
export abstract class ProvableBlockHook<
Config = NoConfig,
diff --git a/packages/protocol/src/protocol/ProvableTransactionHook.ts b/packages/protocol/src/protocol/ProvableTransactionHook.ts
index 32aec366f..605dc8814 100644
--- a/packages/protocol/src/protocol/ProvableTransactionHook.ts
+++ b/packages/protocol/src/protocol/ProvableTransactionHook.ts
@@ -1,44 +1,58 @@
import { NoConfig } from "@proto-kit/common";
-import { Signature } from "o1js";
+import { Field } from "o1js";
-import { RuntimeTransaction } from "../model/transaction/RuntimeTransaction";
import { NetworkState } from "../model/network/NetworkState";
import { MethodPublicOutput } from "../model/MethodPublicOutput";
-import type {
- BlockProverState,
- BlockProverStateCommitments,
-} from "../prover/block/BlockProvable";
+import { TransactionProverState } from "../prover/transaction/TransactionProvable";
+import { AuthorizedTransaction } from "../model/transaction/AuthorizedTransaction";
import { TransitioningProtocolModule } from "./TransitioningProtocolModule";
-export type ProvableHookBlockState = Pick<
- BlockProverStateCommitments,
- | "transactionsHash"
- | "eternalTransactionsHash"
- | "incomingMessagesHash"
- | "blockHashRoot"
->;
+export type ProvableHookTransactionState = {
+ transactionsHash: Field;
+ eternalTransactionsHash: Field;
+ incomingMessagesHash: Field;
+};
-export function toProvableHookBlockState(
+export function toProvableHookTransactionState(
state: Pick<
- BlockProverState,
- | "transactionList"
- | "eternalTransactionsList"
- | "incomingMessages"
- | "blockHashRoot"
+ TransactionProverState,
+ "transactionList" | "eternalTransactionsList" | "incomingMessages"
>
-) {
- const {
- transactionList,
- eternalTransactionsList,
- incomingMessages,
- blockHashRoot,
- } = state;
+): ProvableHookTransactionState {
+ const { transactionList, eternalTransactionsList, incomingMessages } = state;
return {
transactionsHash: transactionList.commitment,
eternalTransactionsHash: eternalTransactionsList.commitment,
incomingMessagesHash: incomingMessages.commitment,
- blockHashRoot,
+ };
+}
+
+export function toBeforeTransactionHookArgument(
+ authorizedTransaction: AuthorizedTransaction,
+ networkState: NetworkState,
+ state: Parameters[0]
+): BeforeTransactionHookArguments {
+ return {
+ networkState,
+ transaction: authorizedTransaction,
+ prover: toProvableHookTransactionState(state),
+ };
+}
+
+export function toAfterTransactionHookArgument(
+ authorizedTransaction: AuthorizedTransaction,
+ networkState: NetworkState,
+ state: Parameters[0],
+ runtimeResult: MethodPublicOutput
+): AfterTransactionHookArguments {
+ return {
+ ...toBeforeTransactionHookArgument(
+ authorizedTransaction,
+ networkState,
+ state
+ ),
+ runtimeResult,
};
}
@@ -53,10 +67,9 @@ export type TransactionResult = Omit<
>;
export interface BeforeTransactionHookArguments {
- transaction: RuntimeTransaction;
- signature: Signature;
+ transaction: AuthorizedTransaction;
networkState: NetworkState;
- prover: ProvableHookBlockState;
+ prover: ProvableHookTransactionState;
}
export interface AfterTransactionHookArguments
diff --git a/packages/protocol/src/prover/accumulators/BlockHashList.ts b/packages/protocol/src/prover/accumulators/BlockHashList.ts
new file mode 100644
index 000000000..b0e732e65
--- /dev/null
+++ b/packages/protocol/src/prover/accumulators/BlockHashList.ts
@@ -0,0 +1,117 @@
+import { Field, Struct } from "o1js";
+
+import { DefaultProvableHashList } from "../../utils/ProvableHashList";
+import type { TransactionProverState } from "../transaction/TransactionProvable";
+import { NetworkState } from "../../model/network/NetworkState";
+
+export class BundlePreimage extends Struct({
+ preimage: Field,
+ fromStateTransitionsHash: Field,
+ fromWitnessedRootsHash: Field,
+}) {}
+
+export class FieldTransition extends Struct({
+ from: Field,
+ to: Field,
+}) {}
+
+/**
+ * A bundle represents an ordered list of transactions and their evaluated effects.
+ * Specifically, this includes beforeTransaction, runtime and afterTransaction evaluation,
+ * but not block hooks.
+ */
+export class Bundle extends Struct({
+ // Those are per-block trackers
+ networkStateHash: Field,
+ transactionsHash: Field,
+
+ // Those are non-linear trackers that we assert later in the blockprover
+ pendingSTBatchesHash: FieldTransition,
+ witnessedRootsHash: FieldTransition,
+}) {}
+
+/**
+ * This hash list collects an ordered list of Bundle instances.
+ * "Pushing" onto this list can mean either appending a new bundle or updating the
+ * bundle at the tip of this list, according to the following rules:
+ * The validated preimage (via checkLastBundleElement) is:
+ * - == commitment: A new bundle will be appended
+ * - something else: The preimage is the actual preimage, therefore as a operation,
+ * the old one will be popped (silently) and the updates bundle will be pushed,
+ * resulting in an semantic update of the tip.
+ */
+export class BundleHashList extends DefaultProvableHashList {
+ public constructor(
+ commitment: Field = Field(0),
+ // TODO Refactor this into preimage and "auxiliary batch information" - this is confusing
+ public preimage?: BundlePreimage
+ ) {
+ super(Bundle, commitment);
+ }
+
+ /** Verifies this list's preimage against the prover's state
+ * The main impact this function has is that it makes the preimage trusted
+ * i.e. we can safely use it to add to the bundle/open a new bundle
+ */
+ public checkLastBundleElement(
+ state: TransactionProverState,
+ networkState: NetworkState
+ ) {
+ const { preimage, fromWitnessedRootsHash, fromStateTransitionsHash } =
+ this.preimage!;
+
+ // Check and append to bundlelist
+ const lastElement = new Bundle({
+ networkStateHash: networkState.hash(),
+ transactionsHash: state.transactionList.commitment,
+ pendingSTBatchesHash: {
+ from: fromStateTransitionsHash,
+ to: state.pendingSTBatches.commitment,
+ },
+ witnessedRootsHash: {
+ from: fromWitnessedRootsHash,
+ to: state.witnessedRoots.commitment,
+ },
+ });
+
+ const newBundle = this.commitment.equals(preimage);
+ this.witnessTip(preimage, lastElement)
+ .or(newBundle)
+ .assertTrue("Last element not valid");
+
+ newBundle
+ .implies(state.transactionList.isEmpty())
+ .assertTrue("Transaction list not empty for new bundle");
+ }
+
+ /**
+ * This function pushes a new bundle onto this list or updates the bundle at
+ * the tip of this list, according to the rules of the preimage algorithms (see class docs)
+ */
+ public addToBundle(
+ state: TransactionProverState,
+ networkState: NetworkState
+ ) {
+ const { preimage, fromWitnessedRootsHash, fromStateTransitionsHash } =
+ this.preimage!;
+
+ const newElement = new Bundle({
+ networkStateHash: networkState.hash(),
+ transactionsHash: state.transactionList.commitment,
+ pendingSTBatchesHash: {
+ from: fromStateTransitionsHash,
+ to: state.pendingSTBatches.commitment,
+ },
+ witnessedRootsHash: {
+ from: fromWitnessedRootsHash,
+ to: state.witnessedRoots.commitment,
+ },
+ });
+
+ // We always overwrite here, the invariant is that the preimage is
+ // either the actual preimage in case of addition to the existing bundle
+ // or the current commitment in case of a new bundle
+ this.commitment = preimage;
+ this.push(newElement);
+ }
+}
diff --git a/packages/protocol/src/prover/accumulators/WitnessedRootHashList.ts b/packages/protocol/src/prover/accumulators/WitnessedRootHashList.ts
index 9a8250168..9671c6582 100644
--- a/packages/protocol/src/prover/accumulators/WitnessedRootHashList.ts
+++ b/packages/protocol/src/prover/accumulators/WitnessedRootHashList.ts
@@ -1,4 +1,4 @@
-import { Bool, Field, Struct } from "o1js";
+import { Bool, Field, Provable, Struct } from "o1js";
import { DefaultProvableHashList } from "../../utils/ProvableHashList";
@@ -13,7 +13,6 @@ export class WitnessedRoot extends Struct({
export class WitnessedRootWitness extends Struct({
witnessedRoot: Field,
- preimage: Field,
}) {}
/**
@@ -21,7 +20,10 @@ export class WitnessedRootWitness extends Struct({
*/
export class WitnessedRootHashList extends DefaultProvableHashList {
- public constructor(commitment: Field = Field(0)) {
+ public constructor(
+ commitment: Field = Field(0),
+ public preimage: Field = Field(0)
+ ) {
super(WitnessedRoot, commitment);
}
@@ -34,28 +36,27 @@ export class WitnessedRootHashList extends DefaultProvableHashList Already covered in BlockProver
+ // (1) don't append if witnessedRoot == finalizedRoot -> Already covered in BlockProver
// (2) don't append if preimage.push({ finalizedRoot, pendingSTBatchesHash }) == this.commitment
const skipPush = preimageCheckList.commitment.equals(this.commitment);
- return this.pushIf(witnessedRoot, condition.and(skipPush.not()));
+ const fromCommitment = this.commitment;
+
+ const pushCondition = condition.and(skipPush.not());
+ this.pushIf(witnessedRoot, pushCondition);
+
+ this.preimage = Provable.if(pushCondition, fromCommitment, this.preimage);
}
}
diff --git a/packages/protocol/src/prover/block/BlockProvable.ts b/packages/protocol/src/prover/block/BlockProvable.ts
index 84d6493af..fc2a15052 100644
--- a/packages/protocol/src/prover/block/BlockProvable.ts
+++ b/packages/protocol/src/prover/block/BlockProvable.ts
@@ -1,18 +1,7 @@
-// eslint-disable-next-line max-classes-per-file
-import {
- Bool,
- DynamicProof,
- Field,
- Proof,
- Signature,
- Struct,
- Void,
-} from "o1js";
-import { WithZkProgrammable, CompilableModule } from "@proto-kit/common";
+import { Bool, Field, Poseidon, Proof, Provable, Struct } from "o1js";
+import { CompilableModule, WithZkProgrammable } from "@proto-kit/common";
import { StateTransitionProof } from "../statetransition/StateTransitionProvable";
-import { MethodPublicOutput } from "../../model/MethodPublicOutput";
-import { RuntimeTransaction } from "../../model/transaction/RuntimeTransaction";
import { NetworkState } from "../../model/network/NetworkState";
import { TransactionHashList } from "../accumulators/TransactionHashList";
import { MinaActionsHashList } from "../../utils/MinaPrefixedProvableHashList";
@@ -21,34 +10,139 @@ import {
WitnessedRootHashList,
WitnessedRootWitness,
} from "../accumulators/WitnessedRootHashList";
+import { TransactionProof } from "../transaction/TransactionProvable";
+import { BundleHashList, FieldTransition } from "../accumulators/BlockHashList";
+import { NonMethods } from "../../utils/utils";
import { BlockHashMerkleTreeWitness } from "./accummulators/BlockHashMerkleTree";
-import { RuntimeVerificationKeyAttestation } from "./accummulators/RuntimeVerificationKeyTree";
-// Should be equal to BlockProver.PublicInput
-export interface BlockProverState {
- /**
- * The current state root of the block prover
- */
- stateRoot: Field;
+export const BLOCK_ARGUMENT_BATCH_SIZE = 4;
- /**
- * The current commitment of the transaction-list which
- * will at the end equal the bundle hash
- */
- transactionList: TransactionHashList;
+export class BlockArguments extends Struct({
+ afterBlockRootWitness: WitnessedRootWitness,
+ transactionsHash: Field,
+ pendingSTBatchesHash: FieldTransition,
+ witnessedRootsHash: FieldTransition,
+ isDummy: Bool,
+}) {
+ public static noop(
+ state: NonMethods>,
+ stateRoot: Field
+ ) {
+ return new BlockArguments({
+ afterBlockRootWitness: {
+ witnessedRoot: stateRoot,
+ },
+ transactionsHash: Field(0),
+ pendingSTBatchesHash: {
+ from: state.pendingSTBatches.commitment,
+ to: state.pendingSTBatches.commitment,
+ },
+ witnessedRootsHash: {
+ from: state.witnessedRoots.commitment,
+ to: state.witnessedRoots.commitment,
+ },
+ isDummy: Bool(true),
+ });
+ }
+}
+
+export class BlockArgumentsBatch extends Struct({
+ batch: Provable.Array(BlockArguments, BLOCK_ARGUMENT_BATCH_SIZE),
+}) {}
+
+const BlockProverStateBaseFields = {
+ eternalTransactionsHash: Field,
+ incomingMessagesHash: Field,
+ stateRoot: Field,
+ blockHashRoot: Field,
+ blockNumber: Field,
+ networkStateHash: Field,
+};
+
+export class BlockProverPublicInput extends Struct({
+ // Tracker of the current block prover state
+ proverStateRemainder: Field,
+ ...BlockProverStateBaseFields,
+}) {
+ public equals(input: BlockProverPublicInput): Bool {
+ const output2 = BlockProverPublicInput.toFields(input);
+ const output1 = BlockProverPublicInput.toFields(this);
+ return output1
+ .map((value1, index) => value1.equals(output2[index]))
+ .reduce((a, b) => a.and(b));
+ }
+
+ public clone() {
+ return new BlockProverPublicInput(
+ BlockProverPublicInput.fromFields(BlockProverPublicInput.toFields(this))
+ );
+ }
+}
+
+export const BlockProverStateCommitments = {
+ remainders: {
+ // Commitment to the list of unprocessed (pending) batches of STs that need to be proven
+ pendingSTBatchesHash: Field,
+ witnessedRootsHash: Field,
+ bundlesHash: Field,
+ witnessedRootsPreimage: Field,
+ },
+ ...BlockProverStateBaseFields,
+};
+export class BlockProverStateInput extends Struct(BlockProverStateCommitments) {
+ public hash() {
+ return Poseidon.hash(BlockProverStateInput.toFields(this));
+ }
+
+ public static fromPublicInput(input: BlockProverPublicInput) {
+ return new BlockProverStateInput({
+ remainders: {
+ bundlesHash: Field(0),
+ pendingSTBatchesHash: Field(0),
+ witnessedRootsHash: Field(0),
+ witnessedRootsPreimage: Field(0),
+ },
+ eternalTransactionsHash: input.eternalTransactionsHash,
+ incomingMessagesHash: input.incomingMessagesHash,
+ stateRoot: input.stateRoot,
+ blockHashRoot: input.blockHashRoot,
+ blockNumber: input.blockNumber,
+ networkStateHash: input.networkStateHash,
+ });
+ }
+
+ public finalize(condition: Bool) {
+ condition
+ .implies(
+ this.remainders.bundlesHash
+ .equals(0)
+ .and(this.remainders.pendingSTBatchesHash.equals(0))
+ .and(this.remainders.witnessedRootsHash.equals(0))
+ )
+ .assertTrue("Remainers not fully removed");
+
+ return new BlockProverPublicInput({
+ proverStateRemainder: Field(0),
+ eternalTransactionsHash: this.eternalTransactionsHash,
+ incomingMessagesHash: this.incomingMessagesHash,
+ stateRoot: this.stateRoot,
+ blockHashRoot: this.blockHashRoot,
+ blockNumber: this.blockNumber,
+ networkStateHash: this.networkStateHash,
+ });
+ }
+}
+
+export class BlockProverPublicOutput extends BlockProverPublicInput {}
+
+export class BlockProverState {
/**
* The network state which gives access to values such as blockHeight
* This value is the same for the whole batch (L2 block)
*/
- networkState: NetworkState;
-
- /**
- * The root of the merkle tree encoding all block hashes,
- * see `BlockHashMerkleTree`
- */
- blockHashRoot: Field;
+ bundleList: BundleHashList;
/**
* A variant of the transactionsHash that is never reset.
@@ -63,156 +157,221 @@ export interface BlockProverState {
witnessedRoots: WitnessedRootHashList;
+ /**
+ * The current state root of the block prover
+ */
+ stateRoot: Field;
+
+ /**
+ * The root of the merkle tree encoding all block hashes,
+ * see `BlockHashMerkleTree`
+ */
+ blockHashRoot: Field;
+
blockNumber: Field;
-}
-// TODO Sort and organize public inputs and outputs
-export class BlockProverStateCommitments extends Struct({
- transactionsHash: Field,
- stateRoot: Field,
- // Commitment to the list of unprocessed (pending) batches of STs that need to be proven
- pendingSTBatchesHash: Field,
- witnessedRootsHash: Field,
- networkStateHash: Field,
- blockHashRoot: Field,
- eternalTransactionsHash: Field,
- incomingMessagesHash: Field,
- blockNumber: Field,
-}) {
- public static fromBlockProverState(
- state: BlockProverState
- ): BlockProverStateCommitments {
- return {
- networkStateHash: state.networkState.hash(),
- stateRoot: state.stateRoot,
- blockNumber: state.blockNumber,
- blockHashRoot: state.blockHashRoot,
- pendingSTBatchesHash: state.pendingSTBatches.commitment,
- transactionsHash: state.transactionList.commitment,
- eternalTransactionsHash: state.eternalTransactionsList.commitment,
- incomingMessagesHash: state.incomingMessages.commitment,
- witnessedRootsHash: state.witnessedRoots.commitment,
- };
+ blockWitness: BlockHashMerkleTreeWitness;
+
+ networkState: NetworkState;
+
+ constructor(args: {
+ networkState: NetworkState;
+ eternalTransactionsList: TransactionHashList;
+ pendingSTBatches: AppliedBatchHashList;
+ stateRoot: Field;
+ blockHashRoot: Field;
+ blockNumber: Field;
+ bundleList: BundleHashList;
+ blockWitness: BlockHashMerkleTreeWitness;
+ witnessedRoots: WitnessedRootHashList;
+ incomingMessages: MinaActionsHashList;
+ }) {
+ this.bundleList = args.bundleList;
+ this.eternalTransactionsList = args.eternalTransactionsList;
+ this.pendingSTBatches = args.pendingSTBatches;
+ this.stateRoot = args.stateRoot;
+ this.blockHashRoot = args.blockHashRoot;
+ this.blockNumber = args.blockNumber;
+ this.networkState = args.networkState;
+ this.blockWitness = args.blockWitness;
+ this.witnessedRoots = args.witnessedRoots;
+ this.incomingMessages = args.incomingMessages;
}
- public static toBlockProverState(
- publicInput: BlockProverStateCommitments,
- networkState: NetworkState
- ): BlockProverState {
- publicInput.networkStateHash.assertEquals(
- networkState.hash(),
- "ExecutionData Networkstate doesn't equal public input hash"
- );
+ public toCommitments(): BlockProverStateInput {
+ return new BlockProverStateInput({
+ remainders: {
+ bundlesHash: this.bundleList.commitment,
+ pendingSTBatchesHash: this.pendingSTBatches.commitment,
+ witnessedRootsHash: this.witnessedRoots.commitment,
+ witnessedRootsPreimage: this.witnessedRoots.preimage,
+ },
+ eternalTransactionsHash: this.eternalTransactionsList.commitment,
+ incomingMessagesHash: this.incomingMessages.commitment,
+ stateRoot: this.stateRoot,
+ blockHashRoot: this.blockHashRoot,
+ blockNumber: this.blockNumber,
+ networkStateHash: this.networkState.hash(),
+ });
+ }
- return {
- networkState,
- stateRoot: publicInput.stateRoot,
- blockHashRoot: publicInput.blockHashRoot,
- transactionList: new TransactionHashList(publicInput.transactionsHash),
+ public static blockProverFromCommitments(
+ stateInput: NonMethods,
+ networkState: NetworkState,
+ blockWitness: BlockHashMerkleTreeWitness
+ ): BlockProverState {
+ return new BlockProverState({
+ bundleList: new BundleHashList(stateInput.remainders.bundlesHash),
eternalTransactionsList: new TransactionHashList(
- publicInput.eternalTransactionsHash
+ stateInput.eternalTransactionsHash
),
incomingMessages: new MinaActionsHashList(
- publicInput.incomingMessagesHash
+ stateInput.incomingMessagesHash
),
pendingSTBatches: new AppliedBatchHashList(
- publicInput.pendingSTBatchesHash
+ stateInput.remainders.pendingSTBatchesHash
),
- witnessedRoots: new WitnessedRootHashList(publicInput.witnessedRootsHash),
- blockNumber: publicInput.blockNumber,
- };
- }
-}
-
-export class BlockProverPublicInput extends BlockProverStateCommitments {}
-
-export class BlockProverPublicOutput extends Struct({
- transactionsHash: Field,
- stateRoot: Field,
- pendingSTBatchesHash: Field,
- witnessedRootsHash: Field,
- networkStateHash: Field,
- blockHashRoot: Field,
- eternalTransactionsHash: Field,
- incomingMessagesHash: Field,
- closed: Bool,
- blockNumber: Field,
-}) {
- public equals(input: BlockProverPublicInput, closed: Bool): Bool {
- const output2 = BlockProverPublicOutput.toFields({
- ...input,
- closed,
+ witnessedRoots: new WitnessedRootHashList(
+ stateInput.remainders.witnessedRootsHash,
+ stateInput.remainders.witnessedRootsPreimage
+ ),
+ stateRoot: stateInput.stateRoot,
+ blockHashRoot: stateInput.blockHashRoot,
+ blockNumber: stateInput.blockNumber,
+ networkState,
+ blockWitness,
});
- const output1 = BlockProverPublicOutput.toFields(this);
- return output1
- .map((value1, index) => value1.equals(output2[index]))
- .reduce((a, b) => a.and(b));
}
-}
-export type BlockProverProof = Proof<
- BlockProverPublicInput,
- BlockProverPublicOutput
->;
-
-export class BlockProverTransactionArguments extends Struct({
- transaction: RuntimeTransaction,
- signature: Signature,
- verificationKeyAttestation: RuntimeVerificationKeyAttestation,
-}) {}
+ public copy() {
+ return BlockProverState.fromFields(this.toFields());
+ }
-export class DynamicRuntimeProof extends DynamicProof<
- Void,
- MethodPublicOutput
-> {
- static publicInputType = Void;
+ public toFields() {
+ return [
+ this.bundleList.commitment,
+ this.eternalTransactionsList.commitment,
+ this.pendingSTBatches.commitment,
+ this.incomingMessages.commitment,
+ this.witnessedRoots.commitment,
+ this.witnessedRoots.preimage,
+ this.stateRoot,
+ this.blockHashRoot,
+ this.blockNumber,
+ ...NetworkState.toFields(this.networkState),
+ ...BlockHashMerkleTreeWitness.toFields(this.blockWitness),
+ ];
+ }
- static publicOutputType = MethodPublicOutput;
+ // TODO Unit test
+ public static fromFields(fields: Field[]) {
+ return new BlockProverState({
+ bundleList: new BundleHashList(fields[0]),
+ eternalTransactionsList: new TransactionHashList(fields[1]),
+ pendingSTBatches: new AppliedBatchHashList(fields[2]),
+ incomingMessages: new MinaActionsHashList(fields[3]),
+ witnessedRoots: new WitnessedRootHashList(fields[4], fields[5]),
+ stateRoot: fields[6],
+ blockHashRoot: fields[7],
+ blockNumber: fields[8],
+ networkState: new NetworkState(NetworkState.fromFields(fields.slice(9))),
+ blockWitness: new BlockHashMerkleTreeWitness(
+ BlockHashMerkleTreeWitness.fromFields(
+ fields.slice(9 + NetworkState.sizeInFields())
+ )
+ ),
+ });
+ }
- // TODO this won't be 0 for proofs-as-args
- static maxProofsVerified = 0 as const;
+ public static choose(
+ condition: Bool,
+ a: BlockProverState,
+ b: BlockProverState
+ ) {
+ return new BlockProverState({
+ bundleList: new BundleHashList(
+ Provable.if(condition, a.bundleList.commitment, b.bundleList.commitment)
+ ),
+ eternalTransactionsList: new TransactionHashList(
+ Provable.if(
+ condition,
+ a.eternalTransactionsList.commitment,
+ b.eternalTransactionsList.commitment
+ )
+ ),
+ pendingSTBatches: new AppliedBatchHashList(
+ Provable.if(
+ condition,
+ a.pendingSTBatches.commitment,
+ b.pendingSTBatches.commitment
+ )
+ ),
+ incomingMessages: new MinaActionsHashList(
+ Provable.if(
+ condition,
+ a.incomingMessages.commitment,
+ b.incomingMessages.commitment
+ )
+ ),
+ witnessedRoots: new WitnessedRootHashList(
+ Provable.if(
+ condition,
+ a.witnessedRoots.commitment,
+ b.witnessedRoots.commitment
+ ),
+ Provable.if(
+ condition,
+ a.witnessedRoots.preimage,
+ b.witnessedRoots.preimage
+ )
+ ),
+ stateRoot: Provable.if(condition, a.stateRoot, b.stateRoot),
+ blockHashRoot: Provable.if(condition, a.blockHashRoot, b.blockHashRoot),
+ blockWitness: new BlockHashMerkleTreeWitness(
+ Provable.if(
+ condition,
+ BlockHashMerkleTreeWitness,
+ a.blockWitness,
+ b.blockWitness
+ )
+ ),
+ blockNumber: Provable.if(condition, a.blockNumber, b.blockNumber),
+ networkState: new NetworkState(
+ Provable.if(condition, NetworkState, a.networkState, b.networkState)
+ ),
+ });
+ }
}
-export class BlockProverSingleTransactionExecutionData extends Struct({
- transaction: BlockProverTransactionArguments,
- networkState: NetworkState,
-}) {}
-
-export class BlockProverMultiTransactionExecutionData extends Struct({
- transaction1: BlockProverTransactionArguments,
- transaction2: BlockProverTransactionArguments,
- networkState: NetworkState,
-}) {}
+export type BlockProof = Proof;
export interface BlockProvable
extends WithZkProgrammable,
CompilableModule {
- proveTransaction: (
+ proveBlockBatchNoProofs: (
publicInput: BlockProverPublicInput,
- runtimeProof: DynamicRuntimeProof,
- executionData: BlockProverSingleTransactionExecutionData
- ) => Promise;
-
- proveTransactions: (
- publicInput: BlockProverPublicInput,
- runtimeProof1: DynamicRuntimeProof,
- runtimeProof2: DynamicRuntimeProof,
- executionData: BlockProverMultiTransactionExecutionData
+ stateWitness: BlockProverStateInput,
+ networkState: NetworkState,
+ blockWitness: BlockHashMerkleTreeWitness,
+ batch: BlockArgumentsBatch,
+ finalize: Bool
) => Promise;
- proveBlock: (
+ proveBlockBatchWithProofs: (
publicInput: BlockProverPublicInput,
+ stateWitness: BlockProverStateInput,
networkState: NetworkState,
blockWitness: BlockHashMerkleTreeWitness,
+ batch: BlockArgumentsBatch,
+ deferSTProof: Bool,
+ deferTransactionProof: Bool,
stateTransitionProof: StateTransitionProof,
- deferSTs: Bool,
- afterBlockRootWitness: WitnessedRootWitness,
- transactionProof: BlockProverProof
+ transactionProof: TransactionProof
) => Promise;
merge: (
publicInput: BlockProverPublicInput,
- proof1: BlockProverProof,
- proof2: BlockProverProof
+ proof1: BlockProof,
+ proof2: BlockProof
) => Promise;
}
diff --git a/packages/protocol/src/prover/block/BlockProver.ts b/packages/protocol/src/prover/block/BlockProver.ts
index f97edd403..f03430c2e 100644
--- a/packages/protocol/src/prover/block/BlockProver.ts
+++ b/packages/protocol/src/prover/block/BlockProver.ts
@@ -1,12 +1,4 @@
-import {
- Bool,
- Field,
- Proof,
- Provable,
- SelfProof,
- VerificationKey,
- ZkProgram,
-} from "o1js";
+import { Bool, Field, Provable, SelfProof, ZkProgram } from "o1js";
import { container, inject, injectable, injectAll } from "tsyringe";
import {
AreProofsEnabled,
@@ -14,14 +6,14 @@ import {
CompileArtifact,
CompileRegistry,
log,
- MAX_FIELD,
+ NonMethods,
PlainZkProgram,
provableMethod,
+ reduceSequential,
WithZkProgrammable,
ZkProgrammable,
} from "@proto-kit/common";
-import { MethodPublicOutput } from "../../model/MethodPublicOutput";
import { ProtocolModule } from "../../protocol/ProtocolModule";
import {
StateTransitionProof,
@@ -30,84 +22,51 @@ import {
StateTransitionProverPublicOutput,
} from "../statetransition/StateTransitionProvable";
import { RuntimeTransaction } from "../../model/transaction/RuntimeTransaction";
-import {
- ProvableStateTransition,
- StateTransition,
-} from "../../model/StateTransition";
-import {
- AfterTransactionHookArguments,
- BeforeTransactionHookArguments,
- ProvableTransactionHook,
- toProvableHookBlockState,
-} from "../../protocol/ProvableTransactionHook";
-import {
- RuntimeMethodExecutionContext,
- RuntimeMethodExecutionData,
-} from "../../state/context/RuntimeMethodExecutionContext";
+import { RuntimeMethodExecutionContext } from "../../state/context/RuntimeMethodExecutionContext";
import {
AfterBlockHookArguments,
BeforeBlockHookArguments,
ProvableBlockHook,
- toAfterTransactionHookArgument,
- toBeforeTransactionHookArgument,
+ toAfterBlockHookArgument,
+ toBeforeBlockHookArgument,
} from "../../protocol/ProvableBlockHook";
import { NetworkState } from "../../model/network/NetworkState";
-import { SignedTransaction } from "../../model/transaction/SignedTransaction";
-import { MinaActions } from "../../utils/MinaPrefixedProvableHashList";
-import { StateTransitionReductionList } from "../accumulators/StateTransitionReductionList";
import { assertEqualsIf } from "../../utils/utils";
-import { WitnessedRootWitness } from "../accumulators/WitnessedRootHashList";
import { StateServiceProvider } from "../../state/StateServiceProvider";
-import { AppliedStateTransitionBatch } from "../../model/AppliedStateTransitionBatch";
+import { executeHooks } from "../utils";
+import {
+ TransactionProof,
+ TransactionProvable,
+ TransactionProverPublicInput,
+ TransactionProverPublicOutput,
+} from "../transaction/TransactionProvable";
+import { Bundle } from "../accumulators/BlockHashList";
import {
+ BlockArguments,
+ BlockArgumentsBatch,
+ BlockProof,
BlockProvable,
- BlockProverProof,
BlockProverPublicInput,
BlockProverPublicOutput,
- DynamicRuntimeProof,
- BlockProverMultiTransactionExecutionData,
- BlockProverTransactionArguments,
- BlockProverSingleTransactionExecutionData,
BlockProverState,
- BlockProverStateCommitments,
+ BlockProverStateInput,
} from "./BlockProvable";
import {
BlockHashMerkleTreeWitness,
BlockHashTreeEntry,
} from "./accummulators/BlockHashMerkleTree";
-import {
- MethodVKConfigData,
- MinimalVKTreeService,
- RuntimeVerificationKeyAttestation,
-} from "./accummulators/RuntimeVerificationKeyTree";
-import { RuntimeVerificationKeyRootService } from "./services/RuntimeVerificationKeyRootService";
const errors = {
propertyNotMatchingStep: (propertyName: string, step: string) =>
`${propertyName} not matching: ${step}`,
propertyNotMatching: (propertyName: string) => `${propertyName} not matching`,
-
- stateRootNotMatching: (step: string) =>
- errors.propertyNotMatchingStep("StateRoots", step),
-
- transactionsHashNotMatching: (step: string) =>
- errors.propertyNotMatchingStep("Transactions hash", step),
-
- networkStateHashNotMatching: (step: string) =>
- errors.propertyNotMatchingStep("Network state hash", step),
-
- invalidZkProgramTreeRoot: () =>
- "Root hash of the provided zkProgram config witness is invalid",
};
-type ApplyTransactionArguments = Omit<
- BlockProverTransactionArguments,
- "verificationKeyAttestation"
->;
-
-export type BlockProof = Proof;
+type BlockHookArgument = T extends "before"
+ ? BeforeBlockHookArguments
+ : AfterBlockHookArguments;
export class BlockProverProgrammable extends ZkProgrammable<
BlockProverPublicInput,
@@ -119,10 +78,12 @@ export class BlockProverProgrammable extends ZkProgrammable<
StateTransitionProverPublicInput,
StateTransitionProverPublicOutput
>,
- private readonly transactionHooks: ProvableTransactionHook[],
+ public readonly transactionProver: ZkProgrammable<
+ TransactionProverPublicInput,
+ TransactionProverPublicOutput
+ >,
private readonly blockHooks: ProvableBlockHook[],
- private readonly stateServiceProvider: StateServiceProvider,
- private readonly verificationKeyService: MinimalVKTreeService
+ private readonly stateServiceProvider: StateServiceProvider
) {
super();
}
@@ -133,213 +94,16 @@ export class BlockProverProgrammable extends ZkProgrammable<
return this.prover.areProofsEnabled;
}
- /**
- * Applies and checks the two proofs and applies the corresponding state
- * changes to the given state.
- *
- * The rough high level workflow of this function:
- * 1. Execute beforeTransaction hooks, pushing the ST batch
- * 2. Add Transaction to bundle, meaning appending it to all the respective commitments
- * 3. Push the runtime ST batch
- * 4. Execute afterTransaction hooks, pushing the ST batch
- * 5. Some consistency checks and signature verification
- *
- * @param fromState The from-state of the BlockProver
- * @param runtimeOutput
- * @param executionData
- * @param networkState
- * @returns The new BlockProver-state to be used as public output
- */
- public async applyTransaction(
- fromState: BlockProverState,
- runtimeOutput: MethodPublicOutput,
- executionData: ApplyTransactionArguments,
- networkState: NetworkState
- ): Promise {
- const { transaction, signature } = executionData;
-
- let state = { ...fromState };
-
- const { isMessage } = runtimeOutput;
-
- const beforeTxHookArguments = toBeforeTransactionHookArgument(
- executionData,
- networkState,
- state
- );
-
- // Apply beforeTransaction hook state transitions
- const beforeBatch = await this.executeTransactionHooks(
- async (module, args) => await module.beforeTransaction(args),
- beforeTxHookArguments,
- isMessage
- );
-
- state = this.addTransactionToBundle(
- state,
- runtimeOutput.isMessage,
- transaction
- );
-
- state.pendingSTBatches.push(beforeBatch);
-
- state.pendingSTBatches.push({
- batchHash: runtimeOutput.stateTransitionsHash,
- applied: runtimeOutput.status,
- });
-
- // Apply afterTransaction hook state transitions
- const afterTxHookArguments = toAfterTransactionHookArgument(
- executionData,
- networkState,
- state,
- runtimeOutput
- );
-
- // Switch to different state set for afterTx hooks
- this.stateServiceProvider.popCurrentStateService();
-
- const afterBatch = await this.executeTransactionHooks(
- async (module, args) => await module.afterTransaction(args),
- afterTxHookArguments,
- isMessage
- );
- state.pendingSTBatches.push(afterBatch);
-
- // Check transaction integrity against appProof
- const blockTransactionHash = transaction.hash();
-
- blockTransactionHash.assertEquals(
- runtimeOutput.transactionHash,
- "Transactions provided in AppProof and BlockProof do not match"
- );
-
- // Check transaction signature
- new SignedTransaction({
- transaction,
- signature,
- })
- .validateSignature()
- .or(isMessage)
- .assertTrue("Transaction signature not valid");
-
- // Validate layout of transaction witness
- transaction.assertTransactionType(isMessage);
-
- // Check network state integrity against appProof
- state.networkState
- .hash()
- .assertEquals(
- runtimeOutput.networkStateHash,
- "Network state does not match state used in AppProof"
- );
-
- return state;
- }
-
- // eslint-disable-next-line max-len
- // TODO How does this interact with the RuntimeMethodExecutionContext when executing runtimemethods?
-
- /**
- * Constructs a AppliedBatch based on a list of STs and the flag whether to
- * be applied or not. The AppliedBatch is a condensed commitment to a batch
- * of STs.
- */
- private constructBatch(
- stateTransitions: StateTransition[],
- applied: Bool
- ) {
- const transitions = stateTransitions.map((transition) =>
- transition.toProvable()
- );
-
- const hashList = new StateTransitionReductionList(ProvableStateTransition);
- transitions.forEach((transition) => {
- hashList.push(transition);
- });
-
- return new AppliedStateTransitionBatch({
- batchHash: hashList.commitment,
- applied,
- });
- }
-
- private async executeTransactionHooks<
- T extends BeforeTransactionHookArguments | AfterTransactionHookArguments,
- >(
- hook: (module: ProvableTransactionHook, args: T) => Promise,
- hookArguments: T,
- isMessage: Bool
- ) {
- const { batch, rawStatus } = await this.executeHooks(
- hookArguments,
- async () => {
- for (const module of this.transactionHooks) {
- // eslint-disable-next-line no-await-in-loop
- await hook(module, hookArguments);
- }
- },
- isMessage
- );
-
- // This is going to set applied to false in case the hook fails
- // (that's only possible for messages though as others are hard-asserted)
- batch.applied = rawStatus;
-
- return batch;
- }
-
- private async executeHooks(
- contextArguments: RuntimeMethodExecutionData,
- method: () => Promise,
- isMessage: Bool | undefined = undefined
- ) {
- const executionContext = container.resolve(RuntimeMethodExecutionContext);
- executionContext.clear();
-
- // Setup context for potential calls to runtime methods.
- // This way they can use this.transaction etc. while still having provable
- // integrity between data
- executionContext.setup(contextArguments);
- executionContext.beforeMethod("", "", []);
-
- const result = await method();
-
- executionContext.afterMethod();
-
- const { stateTransitions, status, statusMessage } =
- executionContext.current().result;
-
- // See https://github.com/proto-kit/framework/issues/321 for why we do this here
- if (isMessage !== undefined) {
- // isMessage is defined for all tx hooks
- status
- .or(isMessage)
- .assertTrue(
- `Transaction hook call failed for non-message tx: ${statusMessage ?? "-"}`
- );
- } else {
- // isMessage is undefined for all block hooks
- status.assertTrue(`Block hook call failed: ${statusMessage ?? "-"}`);
- }
-
- return {
- batch: this.constructBatch(stateTransitions, Bool(true)),
- result,
- rawStatus: status,
- };
- }
-
- public async executeBlockHooks<
- T extends BeforeBlockHookArguments | AfterBlockHookArguments,
- >(
+ public async executeBlockHooks(
+ type: T,
hook: (
module: ProvableBlockHook,
networkState: NetworkState,
- args: T
+ args: BlockHookArgument
) => Promise,
- hookArguments: T,
- inputNetworkState: NetworkState
+ hookArguments: BlockHookArgument,
+ inputNetworkState: NetworkState,
+ isDummy: Bool
) {
const transaction = RuntimeTransaction.dummyTransaction();
const startingInputs = {
@@ -347,155 +111,33 @@ export class BlockProverProgrammable extends ZkProgrammable<
networkState: inputNetworkState,
};
- return await this.executeHooks(startingInputs, async () => {
- const executionContext = container.resolve(RuntimeMethodExecutionContext);
-
- return await this.blockHooks.reduce>(
- async (networkStatePromise, blockHook) => {
- const networkState = await networkStatePromise;
-
- // Setup context for potential calls to runtime methods.
- // With the special case that we set the new networkstate for every hook
- // We also have to put in a dummy transaction for network.transaction
- executionContext.setup({
- transaction: RuntimeTransaction.dummyTransaction(),
- networkState,
- });
-
- return await hook(blockHook, networkState, hookArguments);
- },
- Promise.resolve(inputNetworkState)
- );
- });
- }
-
- public addTransactionToBundle<
- T extends Pick<
- BlockProverState,
- "transactionList" | "eternalTransactionsList" | "incomingMessages"
- >,
- >(state: T, isMessage: Bool, transaction: RuntimeTransaction): T {
- const transactionHash = transaction.hash();
-
- // Append tx to transaction list
- state.transactionList.pushIf(transactionHash, isMessage.not());
-
- // Append tx to eternal transaction list
- // TODO Change that to the a sequence-state compatible transaction struct
- state.eternalTransactionsList.push(transactionHash);
-
- // Append tx to incomingMessagesHash
- const actionHash = MinaActions.actionHash(transaction.hashData());
-
- state.incomingMessages.pushIf(actionHash, isMessage);
-
- return state;
- }
-
- private verifyVerificationKeyAttestation(
- attestation: RuntimeVerificationKeyAttestation,
- methodId: Field
- ): VerificationKey {
- // Verify the [methodId, vk] tuple against the baked-in vk tree root
- const { verificationKey, witness: verificationKeyTreeWitness } =
- attestation;
-
- const root = Field(this.verificationKeyService.getRoot());
- const calculatedRoot = verificationKeyTreeWitness.calculateRoot(
- new MethodVKConfigData({
- methodId: methodId,
- vkHash: verificationKey.hash,
- }).hash()
- );
- root.assertEquals(calculatedRoot, errors.invalidZkProgramTreeRoot());
-
- return verificationKey;
- }
-
- public async proveTransactionInternal(
- fromState: BlockProverState,
- runtimeProof: DynamicRuntimeProof,
- { transaction, networkState }: BlockProverSingleTransactionExecutionData
- ): Promise {
- const verificationKey = this.verifyVerificationKeyAttestation(
- transaction.verificationKeyAttestation,
- transaction.transaction.methodId
- );
-
- runtimeProof.verify(verificationKey);
-
- return await this.applyTransaction(
- fromState,
- runtimeProof.publicOutput,
- transaction,
- networkState
- );
- }
-
- private staticChecks(publicInput: BlockProverPublicInput) {
- publicInput.blockNumber.assertEquals(
- MAX_FIELD,
- "blockNumber has to be MAX for transaction proofs"
- );
- }
-
- @provableMethod()
- public async proveTransaction(
- publicInput: BlockProverPublicInput,
- runtimeProof: DynamicRuntimeProof,
- executionData: BlockProverSingleTransactionExecutionData
- ): Promise {
- const state = BlockProverStateCommitments.toBlockProverState(
- publicInput,
- executionData.networkState
- );
-
- this.staticChecks(publicInput);
+ return await executeHooks(
+ startingInputs,
+ `${type}Block`,
+ async () => {
+ const executionContext = container.resolve(
+ RuntimeMethodExecutionContext
+ );
- const stateTo = await this.proveTransactionInternal(
- state,
- runtimeProof,
- executionData
- );
+ return await this.blockHooks.reduce>(
+ async (networkStatePromise, blockHook) => {
+ const networkState = await networkStatePromise;
- return new BlockProverPublicOutput({
- ...BlockProverStateCommitments.fromBlockProverState(stateTo),
- closed: Bool(false),
- });
- }
+ // Setup context for potential calls to runtime methods.
+ // With the special case that we set the new networkstate for every hook
+ // We also have to put in a dummy transaction for network.transaction
+ executionContext.setup({
+ transaction: RuntimeTransaction.dummyTransaction(),
+ networkState,
+ });
- @provableMethod()
- public async proveTransactions(
- publicInput: BlockProverPublicInput,
- runtimeProof1: DynamicRuntimeProof,
- runtimeProof2: DynamicRuntimeProof,
- executionData: BlockProverMultiTransactionExecutionData
- ): Promise {
- const state = BlockProverStateCommitments.toBlockProverState(
- publicInput,
- executionData.networkState
+ return await hook(blockHook, networkState, hookArguments);
+ },
+ Promise.resolve(inputNetworkState)
+ );
+ },
+ isDummy
);
-
- this.staticChecks(publicInput);
-
- const state1 = await this.proveTransactionInternal(state, runtimeProof1, {
- transaction: executionData.transaction1,
- networkState: executionData.networkState,
- });
-
- // Switch to next state record for 2nd tx beforeTx hook
- // TODO Can be prevented by merging 1st afterTx + 2nd beforeTx
- this.stateServiceProvider.popCurrentStateService();
-
- const stateTo = await this.proveTransactionInternal(state1, runtimeProof2, {
- transaction: executionData.transaction2,
- networkState: executionData.networkState,
- });
-
- return new BlockProverPublicOutput({
- ...BlockProverStateCommitments.fromBlockProverState(stateTo),
- closed: Bool(false),
- });
}
public includeSTProof(
@@ -580,348 +222,394 @@ export class BlockProverProgrammable extends ZkProgrammable<
};
}
- @provableMethod()
- public async proveBlock(
- publicInput: BlockProverPublicInput,
- networkState: NetworkState,
- blockWitness: BlockHashMerkleTreeWitness,
+ private verifySTProof(
+ state: BlockProverState,
stateTransitionProof: StateTransitionProof,
- deferSTProof: Bool,
- afterBlockRootWitness: WitnessedRootWitness,
- transactionProof: BlockProverProof
- ): Promise {
- // 1. Make assertions about the inputs
- publicInput.transactionsHash.assertEquals(
- Field(0),
- "Transactionshash has to start at 0"
- );
+ deferSTProof: Bool
+ ) {
+ // Verify ST Proof only if STs have been emitted,
+ // and we don't defer the verification of the STs
+ // otherwise we can input a dummy proof
+ const batchesEmpty = state.pendingSTBatches.commitment.equals(Field(0));
+ const verifyStProof = deferSTProof.not().and(batchesEmpty.not());
+ log.provable.debug("Verify STProof", verifyStProof);
+ stateTransitionProof.verifyIf(verifyStProof);
- // TransactionProof format checks
- transactionProof.publicInput.blockHashRoot.assertEquals(
- Field(0),
- "TransactionProof cannot carry the blockHashRoot - publicInput"
- );
- transactionProof.publicOutput.blockHashRoot.assertEquals(
- Field(0),
- "TransactionProof cannot carry the blockHashRoot - publicOutput"
- );
- transactionProof.publicInput.networkStateHash.assertEquals(
- transactionProof.publicOutput.networkStateHash,
- "TransactionProof cannot alter the network state"
+ // Apply STProof if not deferred
+ const stateProofResult = this.includeSTProof(
+ stateTransitionProof,
+ verifyStProof,
+ state.stateRoot,
+ state.pendingSTBatches.commitment,
+ state.witnessedRoots.commitment
);
+ state.stateRoot = stateProofResult.stateRoot;
+ state.pendingSTBatches.commitment = stateProofResult.pendingSTBatchesHash;
+ state.witnessedRoots.commitment = stateProofResult.witnessedRootsHash;
+ }
- const state = BlockProverStateCommitments.toBlockProverState(
- publicInput,
- networkState
+ private verifyTransactionProof(
+ state: BlockProverState,
+ transactionProof: TransactionProof,
+ deferTransactionProof: Bool
+ ) {
+ // Verify Transaction proof if it has at least 1 tx and it isn't deferred
+ const finalizeBlockProof = deferTransactionProof.not();
+ const verifyTransactionProof = finalizeBlockProof.and(
+ state.bundleList.isEmpty().not()
);
- // Verify Transaction proof if it has at least 1 tx - i.e. the
- // input and output doesn't match fully
- // We have to compare the whole input and output because we can make no
- // assumptions about the values, since it can be an arbitrary dummy-proof
- const txProofOutput = transactionProof.publicOutput;
- const isEmptyTransition = txProofOutput.equals(
- transactionProof.publicInput,
- txProofOutput.closed
- );
- const skipTransactionProofVerification = isEmptyTransition;
- const verifyTransactionProof = isEmptyTransition.not();
- log.provable.debug("VerifyIf TxProof", verifyTransactionProof);
transactionProof.verifyIf(verifyTransactionProof);
- // 2. Execute beforeBlock hooks
- const beforeBlockArgs = toProvableHookBlockState(state);
- const beforeBlockResult = await this.executeBlockHooks(
- async (module, networkStateArg, args) =>
- await module.beforeBlock(networkStateArg, args),
- beforeBlockArgs,
- networkState
+ // Fast-forward transaction trackers by the results of the aggregated transaction proof
+ // Implicitly, the 'from' values here are asserted against the publicInput, since the hashlists
+ // are created out of the public input
+ state.eternalTransactionsList.fastForwardIf(
+ {
+ from: transactionProof.publicInput.eternalTransactionsHash,
+ to: transactionProof.publicOutput.eternalTransactionsHash,
+ },
+ verifyTransactionProof,
+ "eternalTransactionsList"
);
- state.pendingSTBatches.push(beforeBlockResult.batch);
+ state.incomingMessages.fastForwardIf(
+ {
+ from: transactionProof.publicInput.incomingMessagesHash,
+ to: transactionProof.publicOutput.incomingMessagesHash,
+ },
+ verifyTransactionProof,
+ "incomingMessages"
+ );
- // 4. Apply TX-type BlockProof
- transactionProof.publicInput.networkStateHash
- .equals(beforeBlockResult.result.hash())
- .or(skipTransactionProofVerification)
- .assertTrue(
- "TransactionProof networkstate hash not matching beforeBlock hook result"
- );
- transactionProof.publicInput.stateRoot.assertEquals(
- transactionProof.publicOutput.stateRoot,
- "TransactionProofs can't change the state root"
+ // Cancel out remainders for transaction proof
+ assertEqualsIf(
+ transactionProof.publicInput.bundlesHash,
+ Field(0),
+ verifyTransactionProof,
+ "TransactionProof has to start bundles at 0"
);
- // Check that the transaction proof's STs start after the beforeBlock hook
- transactionProof.publicInput.pendingSTBatchesHash.assertEquals(
- state.pendingSTBatches.commitment,
- "Transaction proof doesn't start their STs after the beforeBlockHook"
+ // Fast Backwards actually, but logic holds
+ state.bundleList.fastForwardIf(
+ {
+ from: transactionProof.publicOutput.bundlesHash,
+ to: state.bundleList.empty(),
+ },
+ verifyTransactionProof,
+ "bundles hash"
);
- // Fast-forward the stBatchHashList to after all transactions appended
- state.pendingSTBatches.commitment =
- transactionProof.publicOutput.pendingSTBatchesHash;
+ }
- // Fast-forward block content commitments by the results of the aggregated transaction proof
- // Implicitly, the 'from' values here are asserted against the publicInput, since the hashlists
- // are created out of the public input
- state.transactionList.fastForward({
- from: transactionProof.publicInput.transactionsHash,
- to: transactionProof.publicOutput.transactionsHash,
- });
- state.eternalTransactionsList.fastForward({
- from: transactionProof.publicInput.eternalTransactionsHash,
- to: transactionProof.publicOutput.eternalTransactionsHash,
- });
- state.incomingMessages.fastForward({
- from: transactionProof.publicInput.incomingMessagesHash,
- to: transactionProof.publicOutput.incomingMessagesHash,
- });
+ private parseState(
+ publicInput: BlockProverPublicInput,
+ stateWitness: BlockProverStateInput,
+ networkState: NetworkState,
+ blockWitness: BlockHashMerkleTreeWitness
+ ) {
+ const hasNoStateRemained = publicInput.proverStateRemainder.equals(0);
- // Witness root
- const isEmpty = state.pendingSTBatches.commitment.equals(0);
- isEmpty
- .implies(state.stateRoot.equals(afterBlockRootWitness.witnessedRoot))
- .assertTrue();
+ // If the state is supplied as a witness, we check that it is equals the PI's stateHash
+ stateWitness
+ .hash()
+ .equals(publicInput.proverStateRemainder)
+ .or(hasNoStateRemained)
+ .assertTrue("Input state witness is invalid");
- state.witnessedRoots.witnessRoot(
- {
- appliedBatchListState: state.pendingSTBatches.commitment,
- root: afterBlockRootWitness.witnessedRoot,
- },
- afterBlockRootWitness.preimage,
- isEmpty.not()
+ const stateInputs = Provable.if(
+ hasNoStateRemained,
+ BlockProverStateInput,
+ BlockProverStateInput.fromPublicInput(publicInput),
+ stateWitness
);
- // 5. Calculate the new block tree hash
+ stateInputs.networkStateHash.assertEquals(
+ networkState.hash(),
+ "Network state not valid"
+ );
+
+ const state = BlockProverState.blockProverFromCommitments(
+ stateInputs,
+ networkState,
+ blockWitness
+ );
+
+ // Verify block witness validity
const blockIndex = blockWitness.calculateIndex();
- blockIndex.assertEquals(publicInput.blockNumber);
+ blockIndex.assertEquals(stateInputs.blockNumber);
blockWitness
.calculateRoot(Field(0))
.assertEquals(
- publicInput.blockHashRoot,
+ stateInputs.blockHashRoot,
"Supplied block hash witness not matching state root"
);
- state.blockHashRoot = blockWitness.calculateRoot(
- new BlockHashTreeEntry({
- block: {
- index: blockIndex,
- transactionListHash: state.transactionList.commitment,
- },
- closed: Bool(true),
- }).hash()
- );
-
- // 6. Execute afterBlock hooks
+ return state;
+ }
- // Switch state service to afterBlock one
- this.stateServiceProvider.popCurrentStateService();
+ private computeOutput(
+ publicInput: BlockProverPublicInput,
+ state: BlockProverState,
+ finalizeBlockProof: Bool
+ ) {
+ const finalizedOutput = state.toCommitments();
- const afterBlockHookArgs = toProvableHookBlockState(state);
- const afterBlockResult = await this.executeBlockHooks(
- async (module, networkStateArg, args) =>
- await module.afterBlock(networkStateArg, args),
- {
- ...afterBlockHookArgs,
- stateRoot: afterBlockRootWitness.witnessedRoot,
- },
- beforeBlockResult.result
+ const deferredOutput = {
+ ...publicInput,
+ };
+ deferredOutput.proverStateRemainder = finalizedOutput.hash();
+
+ return new BlockProverPublicOutput(
+ Provable.if(
+ finalizeBlockProof,
+ BlockProverPublicOutput,
+ finalizedOutput.finalize(finalizeBlockProof),
+ deferredOutput
+ )
);
+ }
- state.pendingSTBatches.push(afterBlockResult.batch);
-
- state.networkState = afterBlockResult.result;
-
- // 7. Close block
+ @provableMethod()
+ public async proveBlockBatchNoProofs(
+ publicInput: BlockProverPublicInput,
+ stateWitness: BlockProverStateInput,
+ networkState: NetworkState,
+ blockWitness: BlockHashMerkleTreeWitness,
+ batch: BlockArgumentsBatch,
+ finalize: Bool
+ ) {
+ return await this.proveBlockBatch(
+ false,
+ publicInput,
+ stateWitness,
+ networkState,
+ blockWitness,
+ batch,
+ Bool(true),
+ Bool(true),
+ finalize
+ );
+ }
- // Verify ST Proof only if STs have been emitted,
- // and we don't defer the verification of the STs
- // otherwise we can input a dummy proof
- const batchesEmpty = state.pendingSTBatches.commitment.equals(Field(0));
- const verifyStProof = deferSTProof.not().and(batchesEmpty.not());
- log.provable.debug("Verify STProof", verifyStProof);
- stateTransitionProof.verifyIf(verifyStProof);
+ @provableMethod()
+ public async proveBlockBatchWithProofs(
+ publicInput: BlockProverPublicInput,
+ stateWitness: BlockProverStateInput,
+ networkState: NetworkState,
+ blockWitness: BlockHashMerkleTreeWitness,
+ batch: BlockArgumentsBatch,
+ deferSTProof: Bool,
+ deferTransactionProof: Bool,
+ stateTransitionProof: StateTransitionProof,
+ transactionProof: TransactionProof
+ ) {
+ const finalize = deferTransactionProof.or(deferSTProof).not();
- // Apply STProof if not deferred
- const stateProofResult = this.includeSTProof(
+ return await this.proveBlockBatch(
+ true,
+ publicInput,
+ stateWitness,
+ networkState,
+ blockWitness,
+ batch,
+ deferSTProof,
+ deferTransactionProof,
+ finalize,
stateTransitionProof,
- verifyStProof,
- state.stateRoot,
- state.pendingSTBatches.commitment,
- state.witnessedRoots.commitment
+ transactionProof
);
- state.stateRoot = stateProofResult.stateRoot;
- state.pendingSTBatches.commitment = stateProofResult.pendingSTBatchesHash;
- state.witnessedRoots.commitment = stateProofResult.witnessedRootsHash;
-
- state.blockNumber = blockIndex.add(1);
-
- return new BlockProverPublicOutput({
- ...BlockProverStateCommitments.fromBlockProverState(state),
- closed: Bool(true),
- });
}
- @provableMethod()
- public async merge(
+ public async proveBlockBatch(
+ doProofVerification: boolean,
publicInput: BlockProverPublicInput,
- proof1: BlockProverProof,
- proof2: BlockProverProof
+ stateWitness: BlockProverStateInput,
+ networkState: NetworkState,
+ blockWitness: BlockHashMerkleTreeWitness,
+ batch: BlockArgumentsBatch,
+ deferSTProof: Bool,
+ deferTransactionProof: Bool,
+ finalize: Bool,
+ stateTransitionProof?: StateTransitionProof,
+ transactionProof?: TransactionProof
): Promise {
- proof1.verify();
- proof2.verify();
-
- // Check state
- publicInput.stateRoot.assertEquals(
- proof1.publicInput.stateRoot,
- errors.stateRootNotMatching("publicInput.from -> proof1.from")
+ let state = this.parseState(
+ publicInput,
+ stateWitness,
+ networkState,
+ blockWitness
);
- proof1.publicOutput.stateRoot.assertEquals(
- proof2.publicInput.stateRoot,
- errors.stateRootNotMatching("proof1.to -> proof2.from")
+
+ // Prove blocks iteratively
+ state = await reduceSequential(
+ batch.batch,
+ async (current, block) => {
+ const result = await this.proveBlock(current.copy(), block);
+
+ this.stateServiceProvider.popCurrentStateService();
+
+ return BlockProverState.choose(block.isDummy, current, result);
+ },
+ state
);
- // Check transaction list hash.
- // Only assert them if these are tx proofs, skip for closed proofs
- publicInput.transactionsHash
- .equals(proof1.publicInput.transactionsHash)
- .or(proof1.publicOutput.closed)
- .assertTrue(
- errors.transactionsHashNotMatching("publicInput.from -> proof1.from")
- );
- proof1.publicOutput.transactionsHash
- .equals(proof2.publicInput.transactionsHash)
- .or(proof1.publicOutput.closed)
- .assertTrue(
- errors.transactionsHashNotMatching("proof1.to -> proof2.from")
+ if (doProofVerification) {
+ this.verifyTransactionProof(
+ state,
+ transactionProof!,
+ deferTransactionProof
);
+ this.verifySTProof(state, stateTransitionProof!, deferSTProof);
+ }
- // Check networkhash
- publicInput.networkStateHash.assertEquals(
- proof1.publicInput.networkStateHash,
- errors.networkStateHashNotMatching("publicInput.from -> proof1.from")
- );
- proof1.publicOutput.networkStateHash.assertEquals(
- proof2.publicInput.networkStateHash,
- errors.networkStateHashNotMatching("proof1.to -> proof2.from")
- );
+ return this.computeOutput(publicInput, state, finalize);
+ }
+
+ private async proveBlock(
+ state: BlockProverState,
+ args: BlockArguments
+ ): Promise {
+ const { networkState, blockWitness } = state;
+ const { afterBlockRootWitness, transactionsHash, isDummy } = args;
+
+ const startingPendingStBatches = state.pendingSTBatches.commitment;
- // Check blockHashRoot
- publicInput.blockHashRoot.assertEquals(
- proof1.publicInput.blockHashRoot,
- errors.transactionsHashNotMatching("publicInput.from -> proof1.from")
+ // 1. Execute beforeBlock hooks
+ const beforeBlockArgs = toBeforeBlockHookArgument(state);
+ const beforeBlockResult = await this.executeBlockHooks(
+ "before",
+ async (module, networkStateArg, hookArgs) =>
+ await module.beforeBlock(networkStateArg, hookArgs),
+ beforeBlockArgs,
+ networkState,
+ isDummy
);
- proof1.publicOutput.blockHashRoot.assertEquals(
- proof2.publicInput.blockHashRoot,
- errors.transactionsHashNotMatching("proof1.to -> proof2.from")
+
+ state.pendingSTBatches.push(beforeBlockResult.batch);
+
+ // 2. "Apply" TX-type BlockProof
+ args.pendingSTBatchesHash.from.assertEquals(
+ state.pendingSTBatches.commitment
);
+ args.witnessedRootsHash.from.assertEquals(state.witnessedRoots.commitment);
+ const isEmptyBlock = transactionsHash.equals(Field(0));
+ const isNotEmptyBlock = isEmptyBlock.not();
- // Check eternalTransactionsHash
- publicInput.eternalTransactionsHash.assertEquals(
- proof1.publicInput.eternalTransactionsHash,
- errors.transactionsHashNotMatching("publicInput.from -> proof1.from")
+ // Check & fast-forward the stBatchHashList to after all transactions appended
+ state.pendingSTBatches.fastForward(
+ args.pendingSTBatchesHash,
+ "Transaction proof doesn't start their STs after the beforeBlockHook"
);
- proof1.publicOutput.eternalTransactionsHash.assertEquals(
- proof2.publicInput.eternalTransactionsHash,
- errors.transactionsHashNotMatching("proof1.to -> proof2.from")
+ // Same for witnessedRootsHash
+ state.witnessedRoots.fastForward(
+ args.witnessedRootsHash,
+ "Transaction proof doesn't start with correct witnessed roots hash"
);
- // Check incomingMessagesHash
- publicInput.incomingMessagesHash.assertEquals(
- proof1.publicInput.incomingMessagesHash,
- errors.propertyNotMatchingStep(
- "IncomingMessagesHash",
- "publicInput.from -> proof1.from"
- )
- );
- proof1.publicOutput.incomingMessagesHash.assertEquals(
- proof2.publicInput.incomingMessagesHash,
- errors.propertyNotMatchingStep(
- "IncomingMessagesHash",
- "proof1.to -> proof2.from"
- )
+ // Add block to bundles list
+ const bundle = new Bundle({
+ transactionsHash: transactionsHash,
+ networkStateHash: beforeBlockResult.result.hash(),
+ pendingSTBatchesHash: args.pendingSTBatchesHash,
+ witnessedRootsHash: args.witnessedRootsHash,
+ });
+ state.bundleList.pushIf(bundle, isNotEmptyBlock);
+
+ // 3.
+ // Calculate new block tree root and increment witness
+ // Blocknumber as the index here is already authenticated previously
+ const [root, newWitness] = blockWitness.calculateRootIncrement(
+ state.blockNumber,
+ new BlockHashTreeEntry({
+ block: {
+ index: state.blockNumber,
+ transactionListHash: transactionsHash,
+ },
+ closed: Bool(true),
+ }).hash()
);
- // Check pendingSTBatchesHash
- publicInput.pendingSTBatchesHash.assertEquals(
- proof1.publicInput.pendingSTBatchesHash,
- errors.transactionsHashNotMatching("publicInput.from -> proof1.from")
+ state.blockHashRoot = root;
+ state.blockWitness = newWitness;
+
+ state.blockNumber = state.blockNumber.add(1);
+
+ // 4. Execute afterBlock hooks
+ // Witness root
+ const hasNoSTBatches = state.pendingSTBatches.commitment.equals(
+ startingPendingStBatches
);
- proof1.publicOutput.pendingSTBatchesHash.assertEquals(
- proof2.publicInput.pendingSTBatchesHash,
- errors.transactionsHashNotMatching("proof1.to -> proof2.from")
+
+ // TODO Cover case when we witness root but pendingSTBatches is completely empty
+
+ state.witnessedRoots.witnessRoot(
+ {
+ appliedBatchListState: state.pendingSTBatches.commitment,
+ root: afterBlockRootWitness.witnessedRoot,
+ },
+ hasNoSTBatches.not()
);
- // Check witnessedRootsHash
- publicInput.witnessedRootsHash.assertEquals(
- proof1.publicInput.witnessedRootsHash,
- errors.transactionsHashNotMatching("publicInput.from -> proof1.from")
+ // Switch state service to afterBlock one
+ this.stateServiceProvider.popCurrentStateService();
+
+ // Execute hooks
+ const afterBlockHookArgs = toAfterBlockHookArgument(
+ state,
+ afterBlockRootWitness.witnessedRoot,
+ transactionsHash
);
- proof1.publicOutput.witnessedRootsHash.assertEquals(
- proof2.publicInput.witnessedRootsHash,
- errors.transactionsHashNotMatching("proof1.to -> proof2.from")
+ const afterBlockResult = await this.executeBlockHooks(
+ "after",
+ async (module, networkStateArg, hookArgs) =>
+ await module.afterBlock(networkStateArg, hookArgs),
+ {
+ ...afterBlockHookArgs,
+ },
+ beforeBlockResult.result,
+ isDummy
);
- // Assert closed indicator matches
- // (i.e. we can only merge TX-Type and Block-Type with each other)
- proof1.publicOutput.closed.assertEquals(
- proof2.publicOutput.closed,
- "Closed indicators not matching"
- );
+ // Apply state and network state changes
+ state.pendingSTBatches.push(afterBlockResult.batch);
+ state.networkState = afterBlockResult.result;
+
+ return state;
+ }
- // Either
- // blockNumbers are unset and proofs are unclosed or
- // both blocks are closed, then they have to increment or
- // one block is closed, then height has to be the same
-
- // Imperative algo would look like
- // if(proof1.height == MAX && proof2.height == MAX){
- // assert !proof1.closed && !proof2.closed;
- // }else if(proof1.closed && proof2.closed){
- // assert proof1.height + 1 == proof2.height
- // // next one is omitted for now
- // }else if(proof1.closed || proof2.closed{
- // assert proof1.height == proof2.height
- // }
-
- const proof1Closed = proof1.publicOutput.closed;
- const proof2Closed = proof2.publicOutput.closed;
-
- const blockNumberProgressionValid = publicInput.blockNumber
- .equals(proof1.publicInput.blockNumber)
- .and(
- proof1.publicOutput.blockNumber.equals(proof2.publicInput.blockNumber)
+ @provableMethod()
+ public async merge(
+ publicInput: BlockProverPublicInput,
+ proof1: BlockProof,
+ proof2: BlockProof
+ ): Promise {
+ proof1.verify();
+ proof2.verify();
+
+ function checkProperty<
+ Key extends keyof NonMethods,
+ >(key: Key) {
+ // Check state
+ publicInput[key].assertEquals(
+ proof1.publicInput[key],
+ errors.propertyNotMatchingStep(key, "publicInput.from -> proof1.from")
);
+ proof1.publicOutput[key].assertEquals(
+ proof2.publicInput[key],
+ errors.propertyNotMatchingStep(key, "proof1.to -> proof2.from")
+ );
+ }
- // For tx proofs, we check that the progression starts and end with MAX
- // in addition to that both proofs are non-closed
- const isValidTransactionMerge = publicInput.blockNumber
- .equals(MAX_FIELD)
- .and(blockNumberProgressionValid)
- .and(proof1Closed.or(proof2Closed).not());
-
- const isValidClosedMerge = proof1Closed
- .and(proof2Closed)
- .and(blockNumberProgressionValid);
-
- isValidTransactionMerge
- .or(isValidClosedMerge)
- .assertTrue("Invalid BlockProof merge");
-
- return new BlockProverPublicOutput({
- stateRoot: proof2.publicOutput.stateRoot,
- transactionsHash: proof2.publicOutput.transactionsHash,
- networkStateHash: proof2.publicOutput.networkStateHash,
- blockHashRoot: proof2.publicOutput.blockHashRoot,
- eternalTransactionsHash: proof2.publicOutput.eternalTransactionsHash,
- incomingMessagesHash: proof2.publicOutput.incomingMessagesHash,
- closed: isValidClosedMerge,
- blockNumber: proof2.publicOutput.blockNumber,
- pendingSTBatchesHash: proof2.publicOutput.pendingSTBatchesHash,
- witnessedRootsHash: proof2.publicOutput.witnessedRootsHash,
- });
+ checkProperty("stateRoot");
+ checkProperty("networkStateHash");
+ checkProperty("blockHashRoot");
+ checkProperty("eternalTransactionsHash");
+ checkProperty("incomingMessagesHash");
+ checkProperty("proverStateRemainder");
+
+ return proof2.publicOutput;
}
/**
@@ -933,11 +621,12 @@ export class BlockProverProgrammable extends ZkProgrammable<
BlockProverPublicInput,
BlockProverPublicOutput
>[] {
- const { prover, stateTransitionProver } = this;
+ const { prover, stateTransitionProver, transactionProver } = this;
const StateTransitionProofClass = stateTransitionProver.zkProgram[0].Proof;
- const proveTransaction = prover.proveTransaction.bind(prover);
- const proveTransactions = prover.proveTransactions.bind(prover);
- const proveBlock = prover.proveBlock.bind(prover);
+ const TransactionProofClass = transactionProver.zkProgram[0].Proof;
+ const proveBlockBatchWithProofs =
+ prover.proveBlockBatchWithProofs.bind(prover);
+ const proveBlockBatchNoProofs = prover.proveBlockBatchNoProofs.bind(prover);
const merge = prover.merge.bind(prover);
const program = ZkProgram({
@@ -946,78 +635,68 @@ export class BlockProverProgrammable extends ZkProgrammable<
publicOutput: BlockProverPublicOutput,
methods: {
- proveTransaction: {
+ proveBlockBatchWithProofs: {
privateInputs: [
- DynamicRuntimeProof,
- BlockProverSingleTransactionExecutionData,
- ],
-
- async method(
- publicInput: BlockProverPublicInput,
- runtimeProof: DynamicRuntimeProof,
- executionData: BlockProverSingleTransactionExecutionData
- ) {
- return {
- publicOutput: await proveTransaction(
- publicInput,
- runtimeProof,
- executionData
- ),
- };
- },
- },
-
- proveTransactions: {
- privateInputs: [
- DynamicRuntimeProof,
- DynamicRuntimeProof,
- BlockProverMultiTransactionExecutionData,
+ BlockProverStateInput,
+ NetworkState,
+ BlockHashMerkleTreeWitness,
+ BlockArgumentsBatch,
+ Bool,
+ Bool,
+ StateTransitionProofClass,
+ TransactionProofClass,
],
-
async method(
publicInput: BlockProverPublicInput,
- runtimeProof1: DynamicRuntimeProof,
- runtimeProof2: DynamicRuntimeProof,
- executionData: BlockProverMultiTransactionExecutionData
+ stateWitness: BlockProverStateInput,
+ networkState: NetworkState,
+ blockWitness: BlockHashMerkleTreeWitness,
+ batch: BlockArgumentsBatch,
+ deferSTProof: Bool,
+ deferTransactionProof: Bool,
+ stateTransitionProof: StateTransitionProof,
+ transactionProof: TransactionProof
) {
return {
- publicOutput: await proveTransactions(
+ publicOutput: await proveBlockBatchWithProofs(
publicInput,
- runtimeProof1,
- runtimeProof2,
- executionData
+ stateWitness,
+ networkState,
+ blockWitness,
+ batch,
+ deferSTProof,
+ deferTransactionProof,
+ stateTransitionProof,
+ transactionProof
),
};
},
},
- proveBlock: {
+ proveBlockBatchNoProofs: {
privateInputs: [
+ BlockProverStateInput,
NetworkState,
BlockHashMerkleTreeWitness,
- StateTransitionProofClass,
+ BlockArgumentsBatch,
Bool,
- WitnessedRootWitness,
- SelfProof,
],
async method(
publicInput: BlockProverPublicInput,
+ stateWitness: BlockProverStateInput,
networkState: NetworkState,
blockWitness: BlockHashMerkleTreeWitness,
- stateTransitionProof: StateTransitionProof,
- deferSTs: Bool,
- afterBlockRootWitness: WitnessedRootWitness,
- transactionProof: BlockProverProof
+ batch: BlockArgumentsBatch,
+ finalize: Bool
) {
return {
- publicOutput: await proveBlock(
+ publicOutput: await proveBlockBatchNoProofs(
publicInput,
+ stateWitness,
networkState,
blockWitness,
- stateTransitionProof,
- deferSTs,
- afterBlockRootWitness,
- transactionProof
+ batch,
+ finalize
),
};
},
@@ -1031,8 +710,8 @@ export class BlockProverProgrammable extends ZkProgrammable<
async method(
publicInput: BlockProverPublicInput,
- proof1: BlockProverProof,
- proof2: BlockProverProof
+ proof1: BlockProof,
+ proof2: BlockProof
) {
return { publicOutput: await merge(publicInput, proof1, proof2) };
},
@@ -1041,9 +720,8 @@ export class BlockProverProgrammable extends ZkProgrammable<
});
const methods = {
- proveTransaction: program.proveTransaction,
- proveTransactions: program.proveTransactions,
- proveBlock: program.proveBlock,
+ proveBlockBatchWithProofs: program.proveBlockBatchWithProofs,
+ proveBlockBatchNoProofs: program.proveBlockBatchNoProofs,
merge: program.merge,
};
@@ -1081,25 +759,24 @@ export class BlockProver
StateTransitionProverPublicOutput
> &
StateTransitionProvable,
- @inject("Runtime")
- public readonly runtime: WithZkProgrammable &
- CompilableModule,
- @injectAll("ProvableTransactionHook")
- transactionHooks: ProvableTransactionHook[],
+ @inject("TransactionProver")
+ public readonly transactionProver: WithZkProgrammable<
+ TransactionProverPublicInput,
+ TransactionProverPublicOutput
+ > &
+ TransactionProvable,
@injectAll("ProvableBlockHook")
blockHooks: ProvableBlockHook[],
@inject("StateServiceProvider")
- stateServiceProvider: StateServiceProvider,
- verificationKeyService: RuntimeVerificationKeyRootService
+ stateServiceProvider: StateServiceProvider
) {
super();
this.zkProgrammable = new BlockProverProgrammable(
this,
stateTransitionProver.zkProgrammable,
- transactionHooks,
+ transactionProver.zkProgrammable,
blockHooks,
- stateServiceProvider,
- verificationKeyService
+ stateServiceProvider
);
}
@@ -1108,61 +785,57 @@ export class BlockProver
): Promise | undefined> {
return await registry.forceProverExists(async () => {
await this.stateTransitionProver.compile(registry);
- await this.runtime.compile(registry);
+ await this.transactionProver.compile(registry);
return await this.zkProgrammable.compile(registry);
});
}
- public proveTransaction(
- publicInput: BlockProverPublicInput,
- runtimeProof: DynamicRuntimeProof,
- executionData: BlockProverSingleTransactionExecutionData
- ): Promise {
- return this.zkProgrammable.proveTransaction(
- publicInput,
- runtimeProof,
- executionData
- );
- }
-
- public proveTransactions(
+ public proveBlockBatchNoProofs(
publicInput: BlockProverPublicInput,
- runtimeProof1: DynamicRuntimeProof,
- runtimeProof2: DynamicRuntimeProof,
- executionData: BlockProverMultiTransactionExecutionData
+ stateWitness: BlockProverStateInput,
+ networkState: NetworkState,
+ blockWitness: BlockHashMerkleTreeWitness,
+ batch: BlockArgumentsBatch,
+ finalize: Bool
): Promise {
- return this.zkProgrammable.proveTransactions(
+ return this.zkProgrammable.proveBlockBatchNoProofs(
publicInput,
- runtimeProof1,
- runtimeProof2,
- executionData
+ stateWitness,
+ networkState,
+ blockWitness,
+ batch,
+ finalize
);
}
- public proveBlock(
+ public proveBlockBatchWithProofs(
publicInput: BlockProverPublicInput,
+ stateWitness: BlockProverStateInput,
networkState: NetworkState,
blockWitness: BlockHashMerkleTreeWitness,
+ batch: BlockArgumentsBatch,
+ deferSTProof: Bool,
+ deferTransactionProof: Bool,
stateTransitionProof: StateTransitionProof,
- deferSTs: Bool,
- afterBlockRootWitness: WitnessedRootWitness,
- transactionProof: BlockProverProof
+ transactionProof: TransactionProof
): Promise {
- return this.zkProgrammable.proveBlock(
+ return this.zkProgrammable.proveBlockBatchWithProofs(
publicInput,
+ stateWitness,
networkState,
blockWitness,
+ batch,
+ deferSTProof,
+ deferTransactionProof,
stateTransitionProof,
- deferSTs,
- afterBlockRootWitness,
transactionProof
);
}
public merge(
publicInput: BlockProverPublicInput,
- proof1: BlockProverProof,
- proof2: BlockProverProof
+ proof1: BlockProof,
+ proof2: BlockProof
): Promise {
return this.zkProgrammable.merge(publicInput, proof1, proof2);
}
diff --git a/packages/protocol/src/prover/statetransition/StateTransitionProver.ts b/packages/protocol/src/prover/statetransition/StateTransitionProver.ts
index e8716c529..dcfeeaaa7 100644
--- a/packages/protocol/src/prover/statetransition/StateTransitionProver.ts
+++ b/packages/protocol/src/prover/statetransition/StateTransitionProver.ts
@@ -20,7 +20,6 @@ import {
StateTransitionProvableBatch,
StateTransitionType,
} from "../../model/StateTransitionProvableBatch";
-import { StateTransitionProverType } from "../../protocol/Protocol";
import { ProtocolModule } from "../../protocol/ProtocolModule";
import { DefaultProvableHashList } from "../../utils/ProvableHashList";
import { WitnessedRootHashList } from "../accumulators/WitnessedRootHashList";
@@ -433,10 +432,7 @@ export class StateTransitionProverProgrammable extends ZkProgrammable<
@injectable()
export class StateTransitionProver
extends ProtocolModule
- implements
- StateTransitionProvable,
- StateTransitionProverType,
- CompilableModule
+ implements StateTransitionProvable, CompilableModule
{
public zkProgrammable: StateTransitionProverProgrammable;
diff --git a/packages/protocol/src/prover/transaction/TransactionProvable.ts b/packages/protocol/src/prover/transaction/TransactionProvable.ts
new file mode 100644
index 000000000..0803946a5
--- /dev/null
+++ b/packages/protocol/src/prover/transaction/TransactionProvable.ts
@@ -0,0 +1,183 @@
+// eslint-disable-next-line max-classes-per-file
+import { CompilableModule, WithZkProgrammable } from "@proto-kit/common";
+import { DynamicProof, Field, Proof, Signature, Struct, Void } from "o1js";
+
+import { RuntimeTransaction } from "../../model/transaction/RuntimeTransaction";
+import { RuntimeVerificationKeyAttestation } from "../block/accummulators/RuntimeVerificationKeyTree";
+import { MethodPublicOutput } from "../../model/MethodPublicOutput";
+import { NetworkState } from "../../model/network/NetworkState";
+import { TransactionHashList } from "../accumulators/TransactionHashList";
+import { AppliedBatchHashList } from "../accumulators/AppliedBatchHashList";
+import { MinaActionsHashList } from "../../utils/MinaPrefixedProvableHashList";
+import { WitnessedRootHashList } from "../accumulators/WitnessedRootHashList";
+import { BundleHashList, BundlePreimage } from "../accumulators/BlockHashList";
+
+export class TransactionProverState {
+ /**
+ * The current commitment of the transaction-list which
+ * will at the end equal the bundle hash
+ */
+ transactionList: TransactionHashList;
+
+ /**
+ * The network state which gives access to values such as blockHeight
+ * This value is the same for the whole batch (L2 block)
+ */
+ bundleList: BundleHashList;
+
+ /**
+ * A variant of the transactionsHash that is never reset.
+ * Thought for usage in the sequence state mempool.
+ * In comparison, transactionsHash restarts at 0 for every new block
+ */
+ eternalTransactionsList: TransactionHashList;
+
+ pendingSTBatches: AppliedBatchHashList;
+
+ incomingMessages: MinaActionsHashList;
+
+ witnessedRoots: WitnessedRootHashList;
+
+ constructor(args: {
+ transactionList: TransactionHashList;
+ bundleList: BundleHashList;
+ eternalTransactionsList: TransactionHashList;
+ pendingSTBatches: AppliedBatchHashList;
+ incomingMessages: MinaActionsHashList;
+ witnessedRoots: WitnessedRootHashList;
+ }) {
+ this.transactionList = args.transactionList;
+ this.bundleList = args.bundleList;
+ this.eternalTransactionsList = args.eternalTransactionsList;
+ this.pendingSTBatches = args.pendingSTBatches;
+ this.incomingMessages = args.incomingMessages;
+ this.witnessedRoots = args.witnessedRoots;
+ }
+
+ public toCommitments(): TransactionProverPublicInput {
+ return {
+ bundlesHash: this.bundleList.commitment,
+ // pendingSTBatchesHash: this.pendingSTBatches.commitment,
+ // transactionsHash: this.transactionList.commitment,
+ eternalTransactionsHash: this.eternalTransactionsList.commitment,
+ incomingMessagesHash: this.incomingMessages.commitment,
+ // witnessedRootsHash: this.witnessedRoots.commitment,
+ };
+ }
+
+ public static fromCommitments(
+ publicInput: TransactionProverPublicInput,
+ args: TransactionProverArguments
+ ): TransactionProverState {
+ return new TransactionProverState({
+ // Stuff that has to be authenticated via public input, since it's not inside the bundle hash
+ bundleList: new BundleHashList(
+ publicInput.bundlesHash,
+ args.bundleListPreimage
+ ),
+ eternalTransactionsList: new TransactionHashList(
+ publicInput.eternalTransactionsHash
+ ),
+ incomingMessages: new MinaActionsHashList(
+ publicInput.incomingMessagesHash
+ ),
+ // Remainders (i.e. stuff that goes into the bundle)
+ transactionList: new TransactionHashList(args.transactionHash),
+ pendingSTBatches: new AppliedBatchHashList(args.pendingSTBatchesHash),
+ witnessedRoots: new WitnessedRootHashList(args.witnessedRootsHash),
+ });
+ }
+}
+
+// These are all linear trackers, i.e. continuously progressing without
+// interruptions from the block prover
+export const TransactionProverStateCommitments = {
+ bundlesHash: Field,
+ eternalTransactionsHash: Field,
+ incomingMessagesHash: Field,
+};
+
+export class TransactionProverArguments extends Struct({
+ // Commitment to the list of unprocessed (pending) batches of STs that need to be proven
+ pendingSTBatchesHash: Field,
+ witnessedRootsHash: Field,
+ transactionHash: Field,
+ bundleListPreimage: BundlePreimage,
+ networkState: NetworkState,
+}) {}
+
+export class TransactionProverPublicInput extends Struct(
+ TransactionProverStateCommitments
+) {
+ public static equals(
+ input1: TransactionProverPublicInput,
+ input2: TransactionProverPublicInput
+ ) {
+ const output2 = TransactionProverPublicInput.toFields(input2);
+ const output1 = TransactionProverPublicInput.toFields(input1);
+ return output1
+ .map((value1, index) => value1.equals(output2[index]))
+ .reduce((a, b) => a.and(b));
+ }
+}
+
+export class TransactionProverPublicOutput extends TransactionProverPublicInput {}
+
+export class TransactionProverTransactionArguments extends Struct({
+ transaction: RuntimeTransaction,
+ signature: Signature,
+ verificationKeyAttestation: RuntimeVerificationKeyAttestation,
+}) {}
+
+export class DynamicRuntimeProof extends DynamicProof<
+ Void,
+ MethodPublicOutput
+> {
+ static publicInputType = Void;
+
+ static publicOutputType = MethodPublicOutput;
+
+ // TODO this won't be 0 for proofs-as-args
+ static maxProofsVerified = 0 as const;
+}
+
+export class TransactionProverExecutionData extends Struct({
+ transaction: TransactionProverTransactionArguments,
+ args: TransactionProverArguments,
+}) {}
+
+export type TransactionProof = Proof<
+ TransactionProverPublicInput,
+ TransactionProverPublicOutput
+>;
+
+export interface TransactionProvable
+ extends WithZkProgrammable<
+ TransactionProverPublicInput,
+ TransactionProverPublicOutput
+ >,
+ CompilableModule {
+ proveTransaction: (
+ publicInput: TransactionProverPublicInput,
+ runtimeProof: DynamicRuntimeProof,
+ executionData: TransactionProverExecutionData
+ ) => Promise;
+
+ proveTransactions: (
+ publicInput: TransactionProverPublicInput,
+ runtimeProof1: DynamicRuntimeProof,
+ runtimeProof2: DynamicRuntimeProof,
+ executionData1: TransactionProverExecutionData,
+ executionData2: TransactionProverExecutionData
+ ) => Promise;
+
+ dummy: (
+ publicInput: TransactionProverPublicInput
+ ) => Promise;
+
+ merge: (
+ publicInput: TransactionProverPublicInput,
+ proof1: TransactionProof,
+ proof2: TransactionProof
+ ) => Promise;
+}
diff --git a/packages/protocol/src/prover/transaction/TransactionProver.ts b/packages/protocol/src/prover/transaction/TransactionProver.ts
new file mode 100644
index 000000000..7d8291cf4
--- /dev/null
+++ b/packages/protocol/src/prover/transaction/TransactionProver.ts
@@ -0,0 +1,561 @@
+import {
+ AreProofsEnabled,
+ CompilableModule,
+ CompileArtifact,
+ CompileRegistry,
+ PlainZkProgram,
+ provableMethod,
+ WithZkProgrammable,
+ ZkProgrammable,
+} from "@proto-kit/common";
+import { Bool, Field, SelfProof, VerificationKey, ZkProgram } from "o1js";
+import { inject, injectable, injectAll } from "tsyringe";
+
+import { NetworkState } from "../../model/network/NetworkState";
+import { ProtocolModule } from "../../protocol/ProtocolModule";
+import { MethodPublicOutput } from "../../model/MethodPublicOutput";
+import {
+ AfterTransactionHookArguments,
+ BeforeTransactionHookArguments,
+ ProvableTransactionHook,
+ toAfterTransactionHookArgument,
+ toBeforeTransactionHookArgument,
+} from "../../protocol/ProvableTransactionHook";
+import { StateServiceProvider } from "../../state/StateServiceProvider";
+import { RuntimeVerificationKeyRootService } from "../block/services/RuntimeVerificationKeyRootService";
+import { addTransactionToBundle, executeHooks } from "../utils";
+import { AuthorizedTransaction } from "../../model/transaction/AuthorizedTransaction";
+import {
+ MethodVKConfigData,
+ MinimalVKTreeService,
+ RuntimeVerificationKeyAttestation,
+} from "../block/accummulators/RuntimeVerificationKeyTree";
+
+import {
+ TransactionProverExecutionData,
+ DynamicRuntimeProof,
+ TransactionProof,
+ TransactionProvable,
+ TransactionProverArguments,
+ TransactionProverPublicInput,
+ TransactionProverPublicOutput,
+ TransactionProverState,
+ TransactionProverTransactionArguments,
+} from "./TransactionProvable";
+
+const errors = {
+ invalidZkProgramTreeRoot: () =>
+ "Root hash of the provided zkProgram config witness is invalid",
+
+ propertyNotMatchingStep: (propertyName: string, step: string) =>
+ `${propertyName} not matching: ${step}`,
+
+ transactionsHashNotMatching: (step: string) =>
+ errors.propertyNotMatchingStep("Transactions hash", step),
+
+ bundlesHashNotMatching: (step: string) =>
+ errors.propertyNotMatchingStep("Bundles hash", step),
+};
+
+type ApplyTransactionArguments = Omit<
+ TransactionProverTransactionArguments,
+ "verificationKeyAttestation"
+>;
+
+type TransactionHookArgument = T extends "before"
+ ? BeforeTransactionHookArguments
+ : AfterTransactionHookArguments;
+
+export class TransactionProverZkProgrammable extends ZkProgrammable<
+ TransactionProverPublicInput,
+ TransactionProverPublicOutput
+> {
+ public constructor(
+ private readonly prover: TransactionProver,
+ private readonly transactionHooks: ProvableTransactionHook[],
+ private readonly stateServiceProvider: StateServiceProvider,
+ private readonly verificationKeyService: MinimalVKTreeService
+ ) {
+ super();
+ }
+
+ name = "TransactionProver";
+
+ public get areProofsEnabled(): AreProofsEnabled | undefined {
+ return this.prover.areProofsEnabled;
+ }
+
+ /**
+ * Applies and checks the two proofs and applies the corresponding state
+ * changes to the given state.
+ *
+ * The rough high level workflow of this function:
+ * 1. Execute beforeTransaction hooks, pushing the ST batch
+ * 2. Add Transaction to bundle, meaning appending it to all the respective commitments
+ * 3. Push the runtime ST batch
+ * 4. Execute afterTransaction hooks, pushing the ST batch
+ * 5. Some consistency checks and signature verification
+ *
+ * @param fromState The from-state of the BlockProver
+ * @param runtimeOutput
+ * @param executionData
+ * @param networkState
+ * @param bundleListPreimage
+ * @returns The new BlockProver-state to be used as public output
+ */
+ public async applyTransaction(
+ fromState: TransactionProverState,
+ runtimeOutput: MethodPublicOutput,
+ executionData: ApplyTransactionArguments,
+ networkState: NetworkState
+ ): Promise {
+ const { transaction, signature } = executionData;
+
+ let state = { ...fromState };
+
+ const { isMessage } = runtimeOutput;
+
+ const authorizedTransaction = new AuthorizedTransaction({
+ transaction,
+ signature,
+ isMessage,
+ });
+
+ const beforeTxHookArguments = toBeforeTransactionHookArgument(
+ authorizedTransaction,
+ networkState,
+ state
+ );
+
+ // Apply beforeTransaction hook state transitions
+ const beforeBatch = await this.executeTransactionHooks(
+ "before",
+ async (module, args) => await module.beforeTransaction(args),
+ beforeTxHookArguments,
+ isMessage
+ );
+
+ state.pendingSTBatches.push(beforeBatch);
+
+ state.pendingSTBatches.push({
+ batchHash: runtimeOutput.stateTransitionsHash,
+ applied: runtimeOutput.status,
+ });
+
+ state = addTransactionToBundle(state, runtimeOutput.isMessage, transaction);
+
+ // Apply afterTransaction hook state transitions
+ const afterTxHookArguments = toAfterTransactionHookArgument(
+ authorizedTransaction,
+ networkState,
+ state,
+ runtimeOutput
+ );
+
+ // Switch to different state set for afterTx hooks
+ this.stateServiceProvider.popCurrentStateService();
+
+ const afterBatch = await this.executeTransactionHooks(
+ "after",
+ async (module, args) => await module.afterTransaction(args),
+ afterTxHookArguments,
+ isMessage
+ );
+ state.pendingSTBatches.push(afterBatch);
+
+ // Check transaction integrity against appProof
+ const blockTransactionHash = transaction.hash();
+
+ blockTransactionHash.assertEquals(
+ runtimeOutput.transactionHash,
+ "Transactions provided in AppProof and BlockProof do not match"
+ );
+
+ // Check transaction signature or isMessage
+ authorizedTransaction
+ .validateAuthorization()
+ .assertTrue("Transaction authorization not valid");
+
+ // Validate layout of transaction witness
+ transaction.assertTransactionType(isMessage);
+
+ return new TransactionProverState(state);
+ }
+
+ private verifyVerificationKeyAttestation(
+ attestation: RuntimeVerificationKeyAttestation,
+ methodId: Field
+ ): VerificationKey {
+ // Verify the [methodId, vk] tuple against the baked-in vk tree root
+ const { verificationKey, witness: verificationKeyTreeWitness } =
+ attestation;
+
+ const root = Field(this.verificationKeyService.getRoot());
+ const calculatedRoot = verificationKeyTreeWitness.calculateRoot(
+ new MethodVKConfigData({
+ methodId: methodId,
+ vkHash: verificationKey.hash,
+ }).hash()
+ );
+ root.assertEquals(calculatedRoot, errors.invalidZkProgramTreeRoot());
+
+ return verificationKey;
+ }
+
+ private async executeTransactionHooks(
+ type: T,
+ hook: (
+ module: ProvableTransactionHook,
+ args: TransactionHookArgument
+ ) => Promise,
+ hookArguments: TransactionHookArgument,
+ isMessage: Bool
+ ) {
+ const { batch, rawStatus } = await executeHooks(
+ {
+ transaction: hookArguments.transaction.transaction,
+ networkState: hookArguments.networkState,
+ },
+ `${type}Transaction`,
+ async () => {
+ for (const module of this.transactionHooks) {
+ // eslint-disable-next-line no-await-in-loop
+ await hook(module, hookArguments);
+ }
+ },
+ isMessage
+ );
+
+ // This is going to set applied to false in case the hook fails
+ // (that's only possible for messages though as others are hard-asserted)
+ batch.applied = rawStatus;
+
+ return batch;
+ }
+
+ public async proveTransactionInternal(
+ publicInput: TransactionProverPublicInput,
+ runtimeProof: DynamicRuntimeProof,
+ transaction: TransactionProverTransactionArguments,
+ args: TransactionProverArguments
+ ): Promise {
+ const state = TransactionProverState.fromCommitments(publicInput, args);
+
+ state.bundleList.checkLastBundleElement(state, args.networkState);
+
+ const verificationKey = this.verifyVerificationKeyAttestation(
+ transaction.verificationKeyAttestation,
+ transaction.transaction.methodId
+ );
+
+ runtimeProof.verify(verificationKey);
+
+ const result = await this.applyTransaction(
+ state,
+ runtimeProof.publicOutput,
+ transaction,
+ args.networkState
+ );
+
+ result.bundleList.addToBundle(result, args.networkState);
+
+ return result.toCommitments();
+ }
+
+ @provableMethod()
+ public async proveTransaction(
+ publicInput: TransactionProverPublicInput,
+ runtimeProof: DynamicRuntimeProof,
+ executionData: TransactionProverExecutionData
+ ): Promise {
+ return await this.proveTransactionInternal(
+ publicInput,
+ runtimeProof,
+ executionData.transaction,
+ executionData.args
+ );
+ }
+
+ @provableMethod()
+ public async proveTransactions(
+ publicInput: TransactionProverPublicInput,
+ runtimeProof1: DynamicRuntimeProof,
+ runtimeProof2: DynamicRuntimeProof,
+ executionData1: TransactionProverExecutionData,
+ executionData2: TransactionProverExecutionData
+ ): Promise {
+ const state1 = await this.proveTransactionInternal(
+ publicInput,
+ runtimeProof1,
+ executionData1.transaction,
+ executionData1.args
+ );
+
+ // Switch to next state record for 2nd tx beforeTx hook
+ this.stateServiceProvider.popCurrentStateService();
+
+ return await this.proveTransactionInternal(
+ state1,
+ runtimeProof2,
+ executionData2.transaction,
+ executionData2.args
+ );
+ }
+
+ @provableMethod()
+ public async dummy(
+ publicInput: TransactionProverPublicInput
+ ): Promise {
+ return publicInput;
+ }
+
+ @provableMethod()
+ public async merge(
+ publicInput: TransactionProverPublicInput,
+ proof1: TransactionProof,
+ proof2: TransactionProof
+ ): Promise {
+ proof1.verify();
+ proof2.verify();
+
+ // Check bundlesHash
+ publicInput.bundlesHash.assertEquals(
+ proof1.publicInput.bundlesHash,
+ errors.bundlesHashNotMatching("publicInput.from -> proof1.from")
+ );
+ proof1.publicOutput.bundlesHash.assertEquals(
+ proof2.publicInput.bundlesHash,
+ errors.bundlesHashNotMatching("proof1.to -> proof2.from")
+ );
+
+ // Check eternalTransactionsHash
+ publicInput.eternalTransactionsHash.assertEquals(
+ proof1.publicInput.eternalTransactionsHash,
+ errors.transactionsHashNotMatching("publicInput.from -> proof1.from")
+ );
+ proof1.publicOutput.eternalTransactionsHash.assertEquals(
+ proof2.publicInput.eternalTransactionsHash,
+ errors.transactionsHashNotMatching("proof1.to -> proof2.from")
+ );
+
+ // Check incomingMessagesHash
+ publicInput.incomingMessagesHash.assertEquals(
+ proof1.publicInput.incomingMessagesHash,
+ errors.propertyNotMatchingStep(
+ "IncomingMessagesHash",
+ "publicInput.from -> proof1.from"
+ )
+ );
+ proof1.publicOutput.incomingMessagesHash.assertEquals(
+ proof2.publicInput.incomingMessagesHash,
+ errors.propertyNotMatchingStep(
+ "IncomingMessagesHash",
+ "proof1.to -> proof2.from"
+ )
+ );
+
+ return new TransactionProverPublicOutput({
+ bundlesHash: proof2.publicOutput.bundlesHash,
+ eternalTransactionsHash: proof2.publicOutput.eternalTransactionsHash,
+ incomingMessagesHash: proof2.publicOutput.incomingMessagesHash,
+ });
+ }
+
+ /**
+ * Creates the BlockProver ZkProgram.
+ * Recursive linking of proofs is done via the previously
+ * injected StateTransitionProver and the required AppChainProof class
+ */
+ public zkProgramFactory(): PlainZkProgram<
+ TransactionProverPublicInput,
+ TransactionProverPublicOutput
+ >[] {
+ const { prover } = this;
+ const proveTransaction = prover.proveTransaction.bind(prover);
+ const proveTransactions = prover.proveTransactions.bind(prover);
+ const merge = prover.merge.bind(prover);
+ const dummy = prover.dummy.bind(prover);
+
+ const program = ZkProgram({
+ name: "TransactionProver",
+ publicInput: TransactionProverPublicInput,
+ publicOutput: TransactionProverPublicOutput,
+
+ methods: {
+ proveTransaction: {
+ privateInputs: [DynamicRuntimeProof, TransactionProverExecutionData],
+
+ async method(
+ publicInput: TransactionProverPublicInput,
+ runtimeProof: DynamicRuntimeProof,
+ executionData: TransactionProverExecutionData
+ ) {
+ return {
+ publicOutput: await proveTransaction(
+ publicInput,
+ runtimeProof,
+ executionData
+ ),
+ };
+ },
+ },
+
+ proveTransactions: {
+ privateInputs: [
+ DynamicRuntimeProof,
+ DynamicRuntimeProof,
+ TransactionProverExecutionData,
+ TransactionProverExecutionData,
+ ],
+
+ async method(
+ publicInput: TransactionProverPublicInput,
+ runtimeProof1: DynamicRuntimeProof,
+ runtimeProof2: DynamicRuntimeProof,
+ executionData1: TransactionProverExecutionData,
+ executionData2: TransactionProverExecutionData
+ ) {
+ return {
+ publicOutput: await proveTransactions(
+ publicInput,
+ runtimeProof1,
+ runtimeProof2,
+ executionData1,
+ executionData2
+ ),
+ };
+ },
+ },
+
+ dummy: {
+ privateInputs: [],
+ async method(publicInput: TransactionProverPublicInput) {
+ return { publicOutput: await dummy(publicInput) };
+ },
+ },
+
+ merge: {
+ privateInputs: [
+ SelfProof<
+ TransactionProverPublicInput,
+ TransactionProverPublicOutput
+ >,
+ SelfProof<
+ TransactionProverPublicInput,
+ TransactionProverPublicOutput
+ >,
+ ],
+
+ async method(
+ publicInput: TransactionProverPublicInput,
+ proof1: TransactionProof,
+ proof2: TransactionProof
+ ) {
+ return { publicOutput: await merge(publicInput, proof1, proof2) };
+ },
+ },
+ },
+ });
+
+ const methods = {
+ proveTransaction: program.proveTransaction,
+ proveTransactions: program.proveTransactions,
+ dummy: program.dummy,
+ merge: program.merge,
+ };
+
+ const SelfProofClass = ZkProgram.Proof(program);
+
+ return [
+ {
+ name: program.name,
+ compile: program.compile.bind(program),
+ verify: program.verify.bind(program),
+ analyzeMethods: program.analyzeMethods.bind(program),
+ Proof: SelfProofClass,
+ methods,
+ },
+ ];
+ }
+}
+
+/**
+ * BlockProver class, which aggregates a AppChainProof and
+ * a StateTransitionProof into a single BlockProof, that can
+ * then be merged to be committed to the base-layer contract
+ */
+@injectable()
+export class TransactionProver
+ extends ProtocolModule
+ implements TransactionProvable, CompilableModule
+{
+ public zkProgrammable: TransactionProverZkProgrammable;
+
+ public constructor(
+ @inject("Runtime")
+ public readonly runtime: WithZkProgrammable &
+ CompilableModule,
+ @injectAll("ProvableTransactionHook")
+ transactionHooks: ProvableTransactionHook[],
+ @inject("StateServiceProvider")
+ stateServiceProvider: StateServiceProvider,
+ verificationKeyService: RuntimeVerificationKeyRootService
+ ) {
+ super();
+ this.zkProgrammable = new TransactionProverZkProgrammable(
+ this,
+ transactionHooks,
+ stateServiceProvider,
+ verificationKeyService
+ );
+ }
+
+ public async compile(
+ registry: CompileRegistry
+ ): Promise | undefined> {
+ return await registry.forceProverExists(async () => {
+ await this.runtime.compile(registry);
+ return await this.zkProgrammable.compile(registry);
+ });
+ }
+
+ public proveTransaction(
+ publicInput: TransactionProverPublicInput,
+ runtimeProof: DynamicRuntimeProof,
+ executionData: TransactionProverExecutionData
+ ): Promise {
+ return this.zkProgrammable.proveTransaction(
+ publicInput,
+ runtimeProof,
+ executionData
+ );
+ }
+
+ public proveTransactions(
+ publicInput: TransactionProverPublicInput,
+ runtimeProof1: DynamicRuntimeProof,
+ runtimeProof2: DynamicRuntimeProof,
+ executionData1: TransactionProverExecutionData,
+ executionData2: TransactionProverExecutionData
+ ): Promise {
+ return this.zkProgrammable.proveTransactions(
+ publicInput,
+ runtimeProof1,
+ runtimeProof2,
+ executionData1,
+ executionData2
+ );
+ }
+
+ public dummy(publicInput: TransactionProverPublicInput) {
+ return this.zkProgrammable.dummy(publicInput);
+ }
+
+ public merge(
+ publicInput: TransactionProverPublicInput,
+ proof1: TransactionProof,
+ proof2: TransactionProof
+ ): Promise {
+ return this.zkProgrammable.merge(publicInput, proof1, proof2);
+ }
+}
diff --git a/packages/protocol/src/prover/utils.ts b/packages/protocol/src/prover/utils.ts
new file mode 100644
index 000000000..9adc0e68b
--- /dev/null
+++ b/packages/protocol/src/prover/utils.ts
@@ -0,0 +1,108 @@
+import { Bool } from "o1js";
+import { container } from "tsyringe";
+
+import {
+ ProvableStateTransition,
+ StateTransition,
+} from "../model/StateTransition";
+import { AppliedStateTransitionBatch } from "../model/AppliedStateTransitionBatch";
+import {
+ RuntimeMethodExecutionContext,
+ RuntimeMethodExecutionData,
+} from "../state/context/RuntimeMethodExecutionContext";
+import { RuntimeTransaction } from "../model/transaction/RuntimeTransaction";
+import { MinaActions } from "../utils/MinaPrefixedProvableHashList";
+
+import { StateTransitionReductionList } from "./accumulators/StateTransitionReductionList";
+import { TransactionProverState } from "./transaction/TransactionProvable";
+
+/**
+ * Constructs a AppliedBatch based on a list of STs and the flag whether to
+ * be applied or not. The AppliedBatch is a condensed commitment to a batch
+ * of STs.
+ */
+export function constructBatch(
+ stateTransitions: StateTransition[],
+ applied: Bool
+) {
+ const transitions = stateTransitions.map((transition) =>
+ transition.toProvable()
+ );
+
+ const hashList = new StateTransitionReductionList(ProvableStateTransition);
+ transitions.forEach((transition) => {
+ hashList.push(transition);
+ });
+
+ return new AppliedStateTransitionBatch({
+ batchHash: hashList.commitment,
+ applied,
+ });
+}
+
+// TODO How does this interact with the RuntimeMethodExecutionContext when executing runtimemethods?
+export async function executeHooks(
+ contextArguments: RuntimeMethodExecutionData,
+ hookName: string,
+ method: () => Promise,
+ // This can be either that the tx is a message, or we are inside a dummy block hook
+ skipEnforceStatus: Bool | undefined = undefined
+) {
+ const executionContext = container.resolve(RuntimeMethodExecutionContext);
+ executionContext.clear();
+
+ // Setup context for potential calls to runtime methods.
+ // This way they can use this.transaction etc. while still having provable
+ // integrity between data
+ executionContext.setup(contextArguments);
+ executionContext.beforeMethod("", "", []);
+
+ const result = await method();
+
+ executionContext.afterMethod();
+
+ const { stateTransitions, status, statusMessage } =
+ executionContext.current().result;
+
+ // See https://github.com/proto-kit/framework/issues/321 for why we do this here
+ if (skipEnforceStatus !== undefined) {
+ // isMessage is defined for all tx hooks
+ status
+ .or(skipEnforceStatus)
+ .assertTrue(
+ `${hookName} hook call failed for non-message tx: ${statusMessage ?? "-"}`
+ );
+ } else {
+ // isMessage is undefined for all block hooks
+ status.assertTrue(`${hookName} hook call failed: ${statusMessage ?? "-"}`);
+ }
+
+ return {
+ batch: constructBatch(stateTransitions, Bool(true)),
+ result,
+ rawStatus: status,
+ };
+}
+
+export function addTransactionToBundle<
+ T extends Pick<
+ TransactionProverState,
+ "transactionList" | "eternalTransactionsList" | "incomingMessages"
+ >,
+>(state: T, isMessage: Bool, transaction: RuntimeTransaction): T {
+ const transactionHash = transaction.hash();
+
+ // Append tx to transaction list
+ state.transactionList.push(transactionHash);
+
+ // Append tx to eternal transaction list
+ // TODO Change that to the a sequence-state compatible transaction struct
+ state.eternalTransactionsList.push(transactionHash);
+
+ // Append tx to incomingMessagesHash
+ const actionHash = MinaActions.actionHash(transaction.hashData());
+
+ state.incomingMessages.pushIf(actionHash, isMessage);
+
+ return state;
+}
diff --git a/packages/protocol/src/settlement/ContractArgsRegistry.ts b/packages/protocol/src/settlement/ContractArgsRegistry.ts
new file mode 100644
index 000000000..f9c2f0020
--- /dev/null
+++ b/packages/protocol/src/settlement/ContractArgsRegistry.ts
@@ -0,0 +1,60 @@
+import { injectable, singleton } from "tsyringe";
+import merge from "lodash/merge";
+
+export interface StaticInitializationContract {
+ getInitializationArgs(): Args;
+}
+
+export type NaiveObjectSchema = {
+ [Key in keyof Obj]: undefined extends Obj[Key] ? "Optional" : "Required";
+};
+
+/*
+interface Test {
+ one: string;
+ two?: string;
+}
+
+const x: NaiveObjectSchema = {
+ one: "Required",
+ two: "Optional",
+};
+*/
+
+@injectable()
+@singleton()
+export class ContractArgsRegistry {
+ args: Record = {};
+
+ public addArgs(name: string, addition: Partial) {
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
+ const args: Partial = this.args[name] ?? {};
+ this.args[name] = merge(args, addition);
+ }
+
+ public resetArgs(name: string) {
+ delete this.args[name];
+ }
+
+ public getArgs(name: string, schema: NaiveObjectSchema): Type {
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
+ const args = this.args[name] ?? {};
+
+ const missing = Object.entries<"Optional" | "Required">(schema).filter(
+ ([key, type]) => {
+ // We filter only if the key is required and isn't present
+ return type === "Required" && args[key] === undefined;
+ }
+ );
+
+ if (missing.length > 0) {
+ const missingKeys = missing.map(([key]) => key);
+ throw new Error(
+ `Contract args for ${name} not all present, ${missingKeys} are missing`
+ );
+ } else {
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
+ return args as Type;
+ }
+ }
+}
diff --git a/packages/protocol/src/settlement/SettlementContractModule.ts b/packages/protocol/src/settlement/SettlementContractModule.ts
index 631842d22..3bfaa778b 100644
--- a/packages/protocol/src/settlement/SettlementContractModule.ts
+++ b/packages/protocol/src/settlement/SettlementContractModule.ts
@@ -16,17 +16,19 @@ import { ProtocolModule } from "../protocol/ProtocolModule";
import { ContractModule } from "./ContractModule";
import { DispatchContractProtocolModule } from "./contracts/DispatchContractProtocolModule";
import { DispatchContractType } from "./contracts/DispatchSmartContract";
-import {
- SettlementContractConfig,
- SettlementContractProtocolModule,
-} from "./contracts/SettlementContractProtocolModule";
-import { SettlementContractType } from "./contracts/SettlementSmartContract";
+import { BridgingSettlementContractModule } from "./contracts/BridgingSettlementContractModule";
import { BridgeContractType } from "./contracts/BridgeContract";
import {
BridgeContractConfig,
BridgeContractProtocolModule,
} from "./contracts/BridgeContractProtocolModule";
-import { GetContracts } from "./modularity/types";
+import { GetContracts, InferContractType } from "./modularity/types";
+import { BridgingSettlementContractType } from "./contracts/settlement/BridgingSettlementContract";
+import { SettlementContractType } from "./contracts/settlement/SettlementBase";
+import {
+ SettlementContractConfig,
+ SettlementSmartContractModule,
+} from "./contracts/SettlementSmartContractModule";
export type SettlementModulesRecord = ModulesRecord<
TypedClass>
@@ -36,6 +38,12 @@ export type MandatorySettlementModulesRecord = {
SettlementContract: TypedClass<
ContractModule
>;
+};
+
+export type BridgingSettlementModulesRecord = {
+ SettlementContract: TypedClass<
+ ContractModule
+ >;
DispatchContract: TypedClass>;
BridgeContract: TypedClass<
ContractModule
@@ -44,8 +52,7 @@ export type MandatorySettlementModulesRecord = {
@injectable()
export class SettlementContractModule<
- SettlementModules extends SettlementModulesRecord &
- MandatorySettlementModulesRecord,
+ SettlementModules extends SettlementModulesRecord,
>
extends ModuleContainer
implements ProtocolModule
@@ -54,10 +61,7 @@ export class SettlementContractModule<
super(definition);
}
- public static from<
- SettlementModules extends SettlementModulesRecord &
- MandatorySettlementModulesRecord,
- >(
+ public static from(
modules: SettlementModules
): TypedClass> {
return class ScopedSettlementContractModule extends SettlementContractModule {
@@ -67,27 +71,18 @@ export class SettlementContractModule<
};
}
- public static mandatoryModules() {
+ public static settlementOnly() {
return {
- SettlementContract: SettlementContractProtocolModule,
- DispatchContract: DispatchContractProtocolModule,
- BridgeContract: BridgeContractProtocolModule,
+ SettlementContract: SettlementSmartContractModule,
} as const;
}
- public static fromDefaults() {
- return SettlementContractModule.from(
- SettlementContractModule.mandatoryModules()
- );
- }
-
- public static with(
- additionalModules: AdditionalModules
- ) {
- return SettlementContractModule.from({
- ...SettlementContractModule.mandatoryModules(),
- ...additionalModules,
- } as const);
+ public static settlementAndBridging() {
+ return {
+ SettlementContract: BridgingSettlementContractModule,
+ DispatchContract: DispatchContractProtocolModule,
+ BridgeContract: BridgeContractProtocolModule,
+ } as const;
}
// ** For protocol module
@@ -116,30 +111,40 @@ export class SettlementContractModule<
return Object.fromEntries(contracts);
}
- public createContracts(addresses: {
- settlement: PublicKey;
- dispatch: PublicKey;
- }): {
- settlement: SettlementContractType & SmartContract;
- dispatch: DispatchContractType & SmartContract;
- } {
- const { DispatchContract, SettlementContract } = this.getContractClasses();
-
- const dispatchInstance = new DispatchContract(addresses.dispatch);
- const settlementInstance = new SettlementContract(addresses.settlement);
-
- return {
- dispatch: dispatchInstance,
- settlement: settlementInstance,
- };
- }
-
- public createBridgeContract(
+ public createContract>(
+ contractName: ContractName,
address: PublicKey,
tokenId?: Field
- ): BridgeContractType & SmartContract {
- const { BridgeContract } = this.getContractClasses();
+ ): InferContractType {
+ const module = this.resolve(contractName);
+ const ContractClass = module.contractFactory();
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
+ return new ContractClass(address, tokenId) as InferContractType<
+ SettlementModules[ContractName]
+ >;
+ }
- return new BridgeContract(address, tokenId);
+ public createContracts<
+ ContractName extends keyof SettlementModules,
+ >(addresses: {
+ [Key in ContractName]: PublicKey;
+ }): {
+ [Key in ContractName]: SmartContract &
+ InferContractType;
+ } {
+ const classes = this.getContractClasses();
+
+ const obj: Record = {};
+ // eslint-disable-next-line guard-for-in
+ for (const key in addresses) {
+ const ContractClass = classes[key];
+ obj[key] = new ContractClass(addresses[key]);
+ }
+
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
+ return obj as {
+ [Key in keyof SettlementModules]: SmartContract &
+ InferContractType;
+ };
}
}
diff --git a/packages/protocol/src/settlement/contracts/BridgeContract.ts b/packages/protocol/src/settlement/contracts/BridgeContract.ts
index 34917d865..f56f8ec95 100644
--- a/packages/protocol/src/settlement/contracts/BridgeContract.ts
+++ b/packages/protocol/src/settlement/contracts/BridgeContract.ts
@@ -28,8 +28,13 @@ import {
import { Path } from "../../model/Path";
import { OutgoingMessageProcessor } from "../modularity/OutgoingMessageProcessor";
import { PROTOKIT_FIELD_PREFIXES } from "../../hashing/protokit-prefixes";
+import {
+ ContractArgsRegistry,
+ NaiveObjectSchema,
+ StaticInitializationContract,
+} from "../ContractArgsRegistry";
-import type { SettlementContractType } from "./SettlementSmartContract";
+import type { BridgingSettlementContractType } from "./settlement/BridgingSettlementContract";
export type BridgeContractType = {
stateRoot: State;
@@ -64,19 +69,33 @@ export class BridgeContractContext {
} = { messageInputs: [] };
}
-export abstract class BridgeContractBase extends TokenContract {
- public static args: {
- SettlementContract:
- | (TypedClass & typeof SmartContract)
- | undefined;
- messageProcessors: OutgoingMessageProcessor[];
- batchSize?: number;
- };
+export interface BridgeContractArgs {
+ SettlementContract: TypedClass &
+ typeof SmartContract;
+ messageProcessors: OutgoingMessageProcessor[];
+ batchSize?: number;
+}
+
+export const BridgeContractArgsSchema: NaiveObjectSchema = {
+ batchSize: "Optional",
+ SettlementContract: "Required",
+ messageProcessors: "Required",
+};
+export abstract class BridgeContractBase
+ extends TokenContract
+ implements StaticInitializationContract
+{
public constructor(address: PublicKey, tokenId?: Field) {
super(address, tokenId);
}
+ getInitializationArgs(): BridgeContractArgs {
+ return container
+ .resolve(ContractArgsRegistry)
+ .getArgs("BridgeContract", BridgeContractArgsSchema);
+ }
+
abstract settlementContractAddress: State;
abstract stateRoot: State;
@@ -134,14 +153,11 @@ export abstract class BridgeContractBase extends TokenContract {
// witness values, not update/insert
this.stateRoot.set(root);
+ const args = this.getInitializationArgs();
+
const settlementContractAddress =
this.settlementContractAddress.getAndRequireEquals();
- const SettlementContractClass = BridgeContractBase.args.SettlementContract;
- if (SettlementContractClass === undefined) {
- throw new Error(
- "Settlement Contract class hasn't been set yet, something is wrong with your module composition"
- );
- }
+ const SettlementContractClass = args.SettlementContract;
const settlementContract = new SettlementContractClass(
settlementContractAddress
);
@@ -150,11 +166,14 @@ export abstract class BridgeContractBase extends TokenContract {
}
private batchSize() {
- return BridgeContractBase.args.batchSize ?? OUTGOING_MESSAGE_BATCH_SIZE;
+ return (
+ this.getInitializationArgs().batchSize ?? OUTGOING_MESSAGE_BATCH_SIZE
+ );
}
private executeProcessors(batchIndex: number, args: OutgoingMessageArgument) {
- return BridgeContractBase.args.messageProcessors.map((processor, j) => {
+ const { messageProcessors } = this.getInitializationArgs();
+ return messageProcessors.map((processor, j) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const value = Experimental.memoizeWitness(processor.type, () => {
return container.resolve(BridgeContractContext).data.messageInputs[
diff --git a/packages/protocol/src/settlement/contracts/BridgeContractProtocolModule.ts b/packages/protocol/src/settlement/contracts/BridgeContractProtocolModule.ts
index 1ab75c588..e4537d242 100644
--- a/packages/protocol/src/settlement/contracts/BridgeContractProtocolModule.ts
+++ b/packages/protocol/src/settlement/contracts/BridgeContractProtocolModule.ts
@@ -3,10 +3,11 @@ import { CompileRegistry } from "@proto-kit/common";
import { ContractModule } from "../ContractModule";
import { OutgoingMessageProcessor } from "../modularity/OutgoingMessageProcessor";
+import { ContractArgsRegistry } from "../ContractArgsRegistry";
import {
BridgeContract,
- BridgeContractBase,
+ BridgeContractArgs,
BridgeContractType,
} from "./BridgeContract";
@@ -21,7 +22,8 @@ export class BridgeContractProtocolModule extends ContractModule<
> {
public constructor(
@injectAll("OutgoingMessageProcessor", { isOptional: true })
- private readonly messageProcessors: OutgoingMessageProcessor[]
+ private readonly messageProcessors: OutgoingMessageProcessor[],
+ private readonly contractArgsRegistry: ContractArgsRegistry
) {
super();
}
@@ -29,11 +31,10 @@ export class BridgeContractProtocolModule extends ContractModule<
public contractFactory() {
const { config } = this;
- BridgeContractBase.args = {
- SettlementContract: BridgeContractBase.args?.SettlementContract,
+ this.contractArgsRegistry.addArgs("BridgeContract", {
messageProcessors: this.messageProcessors,
batchSize: config.outgoingBatchSize,
- };
+ });
return BridgeContract;
}
diff --git a/packages/protocol/src/settlement/contracts/SettlementContractProtocolModule.ts b/packages/protocol/src/settlement/contracts/BridgingSettlementContractModule.ts
similarity index 50%
rename from packages/protocol/src/settlement/contracts/SettlementContractProtocolModule.ts
rename to packages/protocol/src/settlement/contracts/BridgingSettlementContractModule.ts
index 6cdf51952..9d1fef1ed 100644
--- a/packages/protocol/src/settlement/contracts/SettlementContractProtocolModule.ts
+++ b/packages/protocol/src/settlement/contracts/BridgingSettlementContractModule.ts
@@ -12,27 +12,26 @@ import {
SmartContractClassFromInterface,
} from "../ContractModule";
import { ProvableSettlementHook } from "../modularity/ProvableSettlementHook";
+import { ContractArgsRegistry } from "../ContractArgsRegistry";
-import { DispatchSmartContractBase } from "./DispatchSmartContract";
+import { DispatchContractArgs } from "./DispatchSmartContract";
import {
- SettlementContractType,
- SettlementSmartContract,
- SettlementSmartContractBase,
-} from "./SettlementSmartContract";
-import { BridgeContractBase } from "./BridgeContract";
+ BridgingSettlementContractType,
+ BridgingSettlementContract,
+ BridgingSettlementContractArgs,
+} from "./settlement/BridgingSettlementContract";
+import { BridgeContractArgs } from "./BridgeContract";
import { DispatchContractProtocolModule } from "./DispatchContractProtocolModule";
import { BridgeContractProtocolModule } from "./BridgeContractProtocolModule";
-
-export type SettlementContractConfig = {
- escapeHatchSlotsInterval?: number;
-};
-
-// 24 hours
-const DEFAULT_ESCAPE_HATCH = (60 / 3) * 24;
+import {
+ DEFAULT_ESCAPE_HATCH,
+ SettlementContractConfig,
+} from "./SettlementSmartContractModule";
+import { SettlementContract } from "./settlement/SettlementContract";
@injectable()
-export class SettlementContractProtocolModule extends ContractModule<
- SettlementContractType,
+export class BridgingSettlementContractModule extends ContractModule<
+ BridgingSettlementContractType,
SettlementContractConfig
> {
public constructor(
@@ -44,12 +43,13 @@ export class SettlementContractProtocolModule extends ContractModule<
private readonly dispatchContractModule: DispatchContractProtocolModule,
@inject("BridgeContract")
private readonly bridgeContractModule: BridgeContractProtocolModule,
- private readonly childVerificationKeyService: ChildVerificationKeyService
+ private readonly childVerificationKeyService: ChildVerificationKeyService,
+ private readonly argsRegistry: ContractArgsRegistry
) {
super();
}
- public contractFactory(): SmartContractClassFromInterface {
+ public contractFactory(): SmartContractClassFromInterface {
const { hooks, config } = this;
const dispatchContract = this.dispatchContractModule.contractFactory();
const bridgeContract = this.bridgeContractModule.contractFactory();
@@ -57,27 +57,27 @@ export class SettlementContractProtocolModule extends ContractModule<
const escapeHatchSlotsInterval =
config.escapeHatchSlotsInterval ?? DEFAULT_ESCAPE_HATCH;
- const { args } = SettlementSmartContractBase;
- SettlementSmartContractBase.args = {
- ...args,
- DispatchContract: dispatchContract,
- hooks,
- escapeHatchSlotsInterval,
- BridgeContract: bridgeContract,
- BridgeContractVerificationKey: args?.BridgeContractVerificationKey,
- BridgeContractPermissions: args?.BridgeContractPermissions,
- signedSettlements: args?.signedSettlements,
- ChildVerificationKeyService: this.childVerificationKeyService,
- };
-
- // Ideally we don't want to have this cyclic dependency, but we have it in the protocol,
- // So its logical that we can't avoid that here
- BridgeContractBase.args.SettlementContract = SettlementSmartContract;
+ this.argsRegistry.addArgs(
+ "SettlementContract",
+ {
+ DispatchContract: dispatchContract,
+ hooks,
+ escapeHatchSlotsInterval,
+ BridgeContract: bridgeContract,
+ ChildVerificationKeyService: this.childVerificationKeyService,
+ }
+ );
- DispatchSmartContractBase.args.settlementContractClass =
- SettlementSmartContract;
+ // Ideally, we don't want to have this cyclic dependency, but we have it in the protocol,
+ // So it's logical that we can't avoid that here
+ this.argsRegistry.addArgs("BridgeContract", {
+ SettlementContract: BridgingSettlementContract,
+ });
+ this.argsRegistry.addArgs("DispatchContract", {
+ settlementContractClass: BridgingSettlementContract,
+ });
- return SettlementSmartContract;
+ return BridgingSettlementContract;
}
public async compile(
@@ -91,19 +91,22 @@ export class SettlementContractProtocolModule extends ContractModule<
this.contractFactory();
// Init params
- SettlementSmartContractBase.args.BridgeContractVerificationKey =
- bridgeArtifact.BridgeContract.verificationKey;
-
- if (SettlementSmartContractBase.args.signedSettlements === undefined) {
- throw new Error(
- "Args not fully initialized - make sure to also include the SettlementModule in the sequencer"
- );
- }
+ this.argsRegistry.addArgs(
+ "SettlementContract",
+ {
+ BridgeContractVerificationKey:
+ bridgeArtifact.BridgeContract.verificationKey,
+ }
+ );
log.debug("Compiling Settlement Contract");
const artifact = await registry.forceProverExists(
- async (reg) => await registry.compile(SettlementSmartContract)
+ async (reg) =>
+ await registry.compile(
+ BridgingSettlementContract,
+ SettlementContract.name
+ )
);
return {
diff --git a/packages/protocol/src/settlement/contracts/DispatchContractProtocolModule.ts b/packages/protocol/src/settlement/contracts/DispatchContractProtocolModule.ts
index 5b3663a82..f421d9f1e 100644
--- a/packages/protocol/src/settlement/contracts/DispatchContractProtocolModule.ts
+++ b/packages/protocol/src/settlement/contracts/DispatchContractProtocolModule.ts
@@ -7,11 +7,12 @@ import {
ContractModule,
SmartContractClassFromInterface,
} from "../ContractModule";
+import { ContractArgsRegistry } from "../ContractArgsRegistry";
import {
DispatchSmartContract,
DispatchContractType,
- DispatchSmartContractBase,
+ DispatchContractArgs,
} from "./DispatchSmartContract";
export type DispatchContractConfig = {
@@ -23,7 +24,10 @@ export class DispatchContractProtocolModule extends ContractModule<
DispatchContractType,
DispatchContractConfig
> {
- public constructor(@inject("Runtime") private readonly runtime: RuntimeLike) {
+ public constructor(
+ @inject("Runtime") private readonly runtime: RuntimeLike,
+ private readonly contractArgsRegistry: ContractArgsRegistry
+ ) {
super();
}
@@ -52,20 +56,18 @@ export class DispatchContractProtocolModule extends ContractModule<
this.checkConfigIntegrity(incomingMessagesMethods, methodIdMappings);
- DispatchSmartContractBase.args = {
- incomingMessagesPaths: incomingMessagesMethods,
- methodIdMappings,
- settlementContractClass:
- DispatchSmartContractBase.args?.settlementContractClass,
- };
+ this.contractArgsRegistry.addArgs(
+ "DispatchContract",
+ {
+ incomingMessagesPaths: incomingMessagesMethods,
+ methodIdMappings,
+ }
+ );
return DispatchSmartContract;
}
public async compile(registry: CompileRegistry) {
- if (DispatchSmartContractBase.args.settlementContractClass === undefined) {
- throw new Error("Reference to Settlement Contract not set");
- }
return {
DispatchSmartContract: await registry.forceProverExists(
async () => await registry.compile(DispatchSmartContract)
diff --git a/packages/protocol/src/settlement/contracts/DispatchSmartContract.ts b/packages/protocol/src/settlement/contracts/DispatchSmartContract.ts
index 74d765e46..1767b4ebc 100644
--- a/packages/protocol/src/settlement/contracts/DispatchSmartContract.ts
+++ b/packages/protocol/src/settlement/contracts/DispatchSmartContract.ts
@@ -1,6 +1,7 @@
import {
AccountUpdate,
Bool,
+ DeployArgs,
Field,
method,
Poseidon,
@@ -13,8 +14,10 @@ import {
state,
TokenId,
UInt64,
+ Permissions,
} from "o1js";
import { InMemoryMerkleTreeStorage, TypedClass } from "@proto-kit/common";
+import { container } from "tsyringe";
import { RuntimeMethodIdMapping } from "../../model/RuntimeLike";
import { RuntimeTransaction } from "../../model/transaction/RuntimeTransaction";
@@ -23,8 +26,13 @@ import {
MinaEvents,
} from "../../utils/MinaPrefixedProvableHashList";
import { Deposit } from "../messages/Deposit";
+import {
+ ContractArgsRegistry,
+ NaiveObjectSchema,
+ StaticInitializationContract,
+} from "../ContractArgsRegistry";
-import type { SettlementContractType } from "./SettlementSmartContract";
+import type { BridgingSettlementContractType } from "./settlement/BridgingSettlementContract";
import { TokenBridgeDeploymentAuth } from "./authorizations/TokenBridgeDeploymentAuth";
import { UpdateMessagesHashAuth } from "./authorizations/UpdateMessagesHashAuth";
import {
@@ -38,11 +46,14 @@ import {
export const ACTIONS_EMPTY_HASH = Reducer.initialActionState;
export interface DispatchContractType {
+ events: {
+ "token-bridge-added": typeof TokenBridgeTreeAddition;
+ };
+
updateMessagesHash: (
executedMessagesHash: Field,
newPromisedMessagesHash: Field
) => Promise;
- initialize: (settlementContract: PublicKey) => Promise;
enableTokenDeposits: (
tokenId: Field,
bridgeContractAddress: PublicKey,
@@ -50,20 +61,36 @@ export interface DispatchContractType {
) => Promise;
promisedMessagesHash: State;
+
+ deployAndInitialize: (
+ args: DeployArgs | undefined,
+ permissions: Permissions,
+ settlementContract: PublicKey
+ ) => Promise;
}
const tokenBridgeRoot = new TokenBridgeTree(
new InMemoryMerkleTreeStorage()
).getRoot();
-export abstract class DispatchSmartContractBase extends SmartContract {
- public static args: {
- methodIdMappings: RuntimeMethodIdMapping;
- incomingMessagesPaths: Record;
- settlementContractClass?: TypedClass &
- typeof SmartContract;
+export interface DispatchContractArgs {
+ methodIdMappings: RuntimeMethodIdMapping;
+ incomingMessagesPaths: Record;
+ settlementContractClass: TypedClass &
+ typeof SmartContract;
+}
+
+export const DispatchContractArgsSchema: NaiveObjectSchema =
+ {
+ incomingMessagesPaths: "Required",
+ methodIdMappings: "Required",
+ settlementContractClass: "Required",
};
+export abstract class DispatchSmartContractBase
+ extends SmartContract
+ implements StaticInitializationContract
+{
events = {
"token-bridge-added": TokenBridgeTreeAddition,
// We need a placeholder event here, so that o1js internally adds a identifier to the
@@ -82,6 +109,12 @@ export abstract class DispatchSmartContractBase extends SmartContract {
abstract tokenBridgeCount: State;
+ getInitializationArgs(): DispatchContractArgs {
+ return container
+ .resolve(ContractArgsRegistry)
+ .getArgs("DispatchContract", DispatchContractArgsSchema);
+ }
+
protected updateMessagesHashBase(
executedMessagesHash: Field,
newPromisedMessagesHash: Field
@@ -98,12 +131,12 @@ export abstract class DispatchSmartContractBase extends SmartContract {
this.self.account.actionState.requireEquals(newPromisedMessagesHash);
this.promisedMessagesHash.set(newPromisedMessagesHash);
+ const args = this.getInitializationArgs();
const settlementContractAddress =
this.settlementContract.getAndRequireEquals();
- const settlementContract =
- new DispatchSmartContractBase.args.settlementContractClass!(
- settlementContractAddress
- );
+ const settlementContract = new args.settlementContractClass!(
+ settlementContractAddress
+ );
settlementContract.authorizationField.requireEquals(
new UpdateMessagesHashAuth({
@@ -116,12 +149,6 @@ export abstract class DispatchSmartContractBase extends SmartContract {
}
protected initializeBase(settlementContract: PublicKey) {
- this.promisedMessagesHash.getAndRequireEquals().assertEquals(Field(0));
- this.honoredMessagesHash.getAndRequireEquals().assertEquals(Field(0));
- this.settlementContract
- .getAndRequireEquals()
- .assertEquals(PublicKey.empty());
-
this.promisedMessagesHash.set(ACTIONS_EMPTY_HASH);
this.honoredMessagesHash.set(ACTIONS_EMPTY_HASH);
this.settlementContract.set(settlementContract);
@@ -174,10 +201,10 @@ export abstract class DispatchSmartContractBase extends SmartContract {
// treeWitness: TokenBridgeTreeWitness
) {
this.settlementContract.requireEquals(settlementContractAddress);
- const settlementContract =
- new DispatchSmartContractBase.args.settlementContractClass!(
- settlementContractAddress
- );
+ const args = this.getInitializationArgs();
+ const settlementContract = new args.settlementContractClass!(
+ settlementContractAddress
+ );
// Append bridge address to the tree
// TODO This not concurrent and will fail if multiple users deploy bridges at the same time
@@ -239,6 +266,18 @@ export class DispatchSmartContract
@state(Field) public tokenBridgeCount = State();
+ public async deployAndInitialize(
+ args: DeployArgs | undefined,
+ permissions: Permissions,
+ settlementContract: PublicKey
+ ): Promise {
+ await super.deploy(args);
+
+ this.self.account.permissions.set(permissions);
+
+ this.initializeBase(settlementContract);
+ }
+
@method
public async enableTokenDeposits(
tokenId: Field,
@@ -263,11 +302,6 @@ export class DispatchSmartContract
);
}
- @method
- public async initialize(settlementContract: PublicKey) {
- return this.initializeBase(settlementContract);
- }
-
@method
public async deposit(
amount: UInt64,
@@ -310,7 +344,7 @@ export class DispatchSmartContract
});
const { methodIdMappings, incomingMessagesPaths } =
- DispatchSmartContractBase.args;
+ this.getInitializationArgs();
const methodId = Field(
methodIdMappings[incomingMessagesPaths.deposit].methodId
diff --git a/packages/protocol/src/settlement/contracts/SettlementSmartContract.ts b/packages/protocol/src/settlement/contracts/SettlementSmartContract.ts
deleted file mode 100644
index 7dc375d2f..000000000
--- a/packages/protocol/src/settlement/contracts/SettlementSmartContract.ts
+++ /dev/null
@@ -1,502 +0,0 @@
-import {
- prefixToField,
- TypedClass,
- mapSequential,
- ChildVerificationKeyService,
- LinkedMerkleTree,
-} from "@proto-kit/common";
-import {
- AccountUpdate,
- Bool,
- Field,
- method,
- PublicKey,
- Signature,
- SmartContract,
- State,
- state,
- UInt32,
- AccountUpdateForest,
- TokenContract,
- PrivateKey,
- VerificationKey,
- Permissions,
- Struct,
- Provable,
- TokenId,
- DynamicProof,
-} from "o1js";
-
-import { NetworkState } from "../../model/network/NetworkState";
-import { BlockHashMerkleTree } from "../../prover/block/accummulators/BlockHashMerkleTree";
-import {
- BlockProverPublicInput,
- BlockProverPublicOutput,
-} from "../../prover/block/BlockProvable";
-import {
- ProvableSettlementHook,
- SettlementHookInputs,
- SettlementStateRecord,
-} from "../modularity/ProvableSettlementHook";
-
-import { DispatchContractType } from "./DispatchSmartContract";
-import { BridgeContractType } from "./BridgeContract";
-import { TokenBridgeDeploymentAuth } from "./authorizations/TokenBridgeDeploymentAuth";
-import { UpdateMessagesHashAuth } from "./authorizations/UpdateMessagesHashAuth";
-
-/* eslint-disable @typescript-eslint/lines-between-class-members */
-
-export class DynamicBlockProof extends DynamicProof<
- BlockProverPublicInput,
- BlockProverPublicOutput
-> {
- public static publicInputType = BlockProverPublicInput;
-
- public static publicOutputType = BlockProverPublicOutput;
-
- public static maxProofsVerified = 2 as const;
-}
-
-export class TokenMapping extends Struct({
- tokenId: Field,
- publicKey: PublicKey,
-}) {}
-
-export interface SettlementContractType {
- authorizationField: State;
-
- initialize: (
- sequencer: PublicKey,
- dispatchContract: PublicKey,
- bridgeContract: PublicKey,
- contractKey: PrivateKey
- ) => Promise;
- assertStateRoot: (root: Field) => AccountUpdate;
- settle: (
- blockProof: DynamicBlockProof,
- signature: Signature,
- dispatchContractAddress: PublicKey,
- publicKey: PublicKey,
- inputNetworkState: NetworkState,
- outputNetworkState: NetworkState,
- newPromisedMessagesHash: Field
- ) => Promise;
- addTokenBridge: (
- tokenId: Field,
- address: PublicKey,
- dispatchContract: PublicKey
- ) => Promise;
-}
-
-// Some random prefix for the sequencer signature
-export const BATCH_SIGNATURE_PREFIX = prefixToField("pk-batchSignature");
-
-// @singleton()
-// export class SettlementSmartContractStaticArgs {
-// public args?: {
-// DispatchContract: TypedClass;
-// hooks: ProvableSettlementHook[];
-// escapeHatchSlotsInterval: number;
-// BridgeContract: TypedClass & typeof SmartContract;
-// // Lazily initialized
-// BridgeContractVerificationKey: VerificationKey | undefined;
-// BridgeContractPermissions: Permissions | undefined;
-// signedSettlements: boolean | undefined;
-// };
-// }
-
-export abstract class SettlementSmartContractBase extends TokenContract {
- // This pattern of injecting args into a smartcontract is currently the only
- // viable solution that works given the inheritance issues of o1js
- // public static args = container.resolve(SettlementSmartContractStaticArgs);
- public static args: {
- DispatchContract: TypedClass;
- hooks: ProvableSettlementHook[];
- escapeHatchSlotsInterval: number;
- BridgeContract: TypedClass & typeof SmartContract;
- // Lazily initialized
- BridgeContractVerificationKey: VerificationKey | undefined;
- BridgeContractPermissions: Permissions | undefined;
- signedSettlements: boolean | undefined;
- ChildVerificationKeyService: ChildVerificationKeyService;
- };
-
- events = {
- "token-bridge-deployed": TokenMapping,
- };
-
- abstract sequencerKey: State;
- abstract lastSettlementL1BlockHeight: State;
- abstract stateRoot: State;
- abstract networkStateHash: State;
- abstract blockHashRoot: State;
- abstract dispatchContractAddressX: State;
-
- abstract authorizationField: State;
-
- // Not @state
- // abstract offchainStateCommitmentsHash: State;
-
- public assertStateRoot(root: Field): AccountUpdate {
- this.stateRoot.requireEquals(root);
- return this.self;
- }
-
- // TODO Like these properties, I am too lazy to properly infer the types here
- private assertLazyConfigsInitialized() {
- const uninitializedProperties: string[] = [];
- const { args } = SettlementSmartContractBase;
- if (args.BridgeContractPermissions === undefined) {
- uninitializedProperties.push("BridgeContractPermissions");
- }
- if (args.signedSettlements === undefined) {
- uninitializedProperties.push("signedSettlements");
- }
- if (uninitializedProperties.length > 0) {
- throw new Error(
- `Lazy configs of SettlementSmartContract haven't been initialized ${uninitializedProperties.reduce(
- (a, b) => `${a},${b}`
- )}`
- );
- }
- }
-
- protected async deployTokenBridge(
- tokenId: Field,
- address: PublicKey,
- dispatchContractAddress: PublicKey,
- dispatchContractPreconditionEnforced = false
- ) {
- Provable.asProver(() => {
- this.assertLazyConfigsInitialized();
- });
-
- const { args } = SettlementSmartContractBase;
- const BridgeContractClass = args.BridgeContract;
- const bridgeContract = new BridgeContractClass(address, tokenId);
-
- const {
- BridgeContractVerificationKey,
- signedSettlements,
- BridgeContractPermissions,
- } = args;
-
- if (
- signedSettlements === undefined ||
- BridgeContractPermissions === undefined
- ) {
- throw new Error(
- "Static arguments for SettlementSmartContract not initialized"
- );
- }
-
- if (
- BridgeContractVerificationKey !== undefined &&
- !BridgeContractVerificationKey.hash.isConstant()
- ) {
- throw new Error("Bridge contract verification key has to be constants");
- }
-
- // This function is not a zkapps method, therefore it will be part of this methods execution
- // The returning account update (owner.self) is therefore part of this circuit and is assertable
- const deploymentAccountUpdate = await bridgeContract.deployProvable(
- args.BridgeContractVerificationKey,
- args.signedSettlements!,
- args.BridgeContractPermissions!,
- this.address
- );
-
- this.approve(deploymentAccountUpdate);
-
- this.self.body.mayUseToken = {
- // Only set this if we deploy a custom token
- parentsOwnToken: tokenId.equals(TokenId.default).not(),
- inheritFromParent: Bool(false),
- };
-
- this.emitEvent(
- "token-bridge-deployed",
- new TokenMapping({
- tokenId: tokenId,
- publicKey: address,
- })
- );
-
- // We can't set a precondition twice, for the $mina bridge deployment that
- // would be the case, so we disable it in this case
- if (!dispatchContractPreconditionEnforced) {
- this.dispatchContractAddressX.requireEquals(dispatchContractAddress.x);
- }
-
- // Set authorization for the auth callback, that we need
- this.authorizationField.set(
- new TokenBridgeDeploymentAuth({
- target: dispatchContractAddress,
- tokenId,
- address,
- }).hash()
- );
- const dispatchContract =
- new SettlementSmartContractBase.args.DispatchContract(
- dispatchContractAddress
- );
- await dispatchContract.enableTokenDeposits(tokenId, address, this.address);
- }
-
- protected async initializeBase(
- sequencer: PublicKey,
- dispatchContract: PublicKey,
- bridgeContract: PublicKey,
- contractKey: PrivateKey
- ) {
- this.sequencerKey.getAndRequireEquals().assertEquals(Field(0));
- this.stateRoot.getAndRequireEquals().assertEquals(Field(0));
- this.blockHashRoot.getAndRequireEquals().assertEquals(Field(0));
- this.networkStateHash.getAndRequireEquals().assertEquals(Field(0));
- this.dispatchContractAddressX.getAndRequireEquals().assertEquals(Field(0));
-
- this.sequencerKey.set(sequencer.x);
- this.stateRoot.set(LinkedMerkleTree.EMPTY_ROOT);
- this.blockHashRoot.set(Field(BlockHashMerkleTree.EMPTY_ROOT));
- this.networkStateHash.set(NetworkState.empty().hash());
- this.dispatchContractAddressX.set(dispatchContract.x);
-
- const { DispatchContract } = SettlementSmartContractBase.args;
- const contractInstance = new DispatchContract(dispatchContract);
- await contractInstance.initialize(this.address);
-
- // Deploy bridge contract for $Mina
- await this.deployTokenBridge(
- this.tokenId,
- bridgeContract,
- dispatchContract,
- true
- );
-
- contractKey.toPublicKey().assertEquals(this.address);
- }
-
- protected async settleBase(
- blockProof: DynamicBlockProof,
- signature: Signature,
- dispatchContractAddress: PublicKey,
- publicKey: PublicKey,
- inputNetworkState: NetworkState,
- outputNetworkState: NetworkState,
- newPromisedMessagesHash: Field
- ) {
- // Brought in as a constant
- const blockProofVk =
- SettlementSmartContractBase.args.ChildVerificationKeyService.getVerificationKey(
- "BlockProver"
- );
- if (!blockProofVk.hash.isConstant()) {
- throw new Error("Sanity check - vk hash has to be constant");
- }
-
- // Verify the blockproof
- blockProof.verify(blockProofVk);
-
- // Get and assert on-chain values
- const stateRoot = this.stateRoot.getAndRequireEquals();
- const networkStateHash = this.networkStateHash.getAndRequireEquals();
- const blockHashRoot = this.blockHashRoot.getAndRequireEquals();
- const sequencerKey = this.sequencerKey.getAndRequireEquals();
- const lastSettlementL1BlockHeight =
- this.lastSettlementL1BlockHeight.getAndRequireEquals();
- const onChainDispatchContractAddressX =
- this.dispatchContractAddressX.getAndRequireEquals();
-
- onChainDispatchContractAddressX.assertEquals(
- dispatchContractAddress.x,
- "DispatchContract address not provided correctly"
- );
-
- const { DispatchContract, escapeHatchSlotsInterval, hooks } =
- SettlementSmartContractBase.args;
-
- // Get dispatch contract values
- // These values are witnesses but will be checked later on the AU
- // call to the dispatch contract via .updateMessagesHash()
- const dispatchContract = new DispatchContract(dispatchContractAddress);
- const promisedMessagesHash = dispatchContract.promisedMessagesHash.get();
-
- // Get block height and use the lower bound for all ops
- const minBlockHeightIncluded = this.network.blockchainLength.get();
- this.network.blockchainLength.requireBetween(
- minBlockHeightIncluded,
- // 5 because that is the length the newPromisedMessagesHash will be valid
- minBlockHeightIncluded.add(4)
- );
-
- // Check signature/escape catch
- publicKey.x.assertEquals(
- sequencerKey,
- "Sequencer public key witness not matching"
- );
- const signatureValid = signature.verify(publicKey, [
- BATCH_SIGNATURE_PREFIX,
- lastSettlementL1BlockHeight.value,
- ]);
- const escapeHatchActivated = lastSettlementL1BlockHeight
- .add(UInt32.from(escapeHatchSlotsInterval))
- .lessThan(minBlockHeightIncluded);
- signatureValid
- .or(escapeHatchActivated)
- .assertTrue(
- "Sequencer signature not valid and escape hatch not activated"
- );
-
- // Assert correctness of networkState witness
- inputNetworkState
- .hash()
- .assertEquals(networkStateHash, "InputNetworkState witness not valid");
- outputNetworkState
- .hash()
- .assertEquals(
- blockProof.publicOutput.networkStateHash,
- "OutputNetworkState witness not valid"
- );
-
- blockProof.publicOutput.closed.assertEquals(
- Bool(true),
- "Supplied proof is not a closed BlockProof"
- );
- blockProof.publicOutput.pendingSTBatchesHash.assertEquals(
- Field(0),
- "Supplied proof is has outstanding STs to be proven"
- );
-
- // Execute onSettlementHooks for additional checks
- const stateRecord: SettlementStateRecord = {
- blockHashRoot,
- stateRoot,
- networkStateHash,
- lastSettlementL1BlockHeight,
- sequencerKey: publicKey,
- };
- const inputs: SettlementHookInputs = {
- blockProof,
- contractState: stateRecord,
- newPromisedMessagesHash,
- fromNetworkState: inputNetworkState,
- toNetworkState: outputNetworkState,
- currentL1BlockHeight: minBlockHeightIncluded,
- };
- await mapSequential(hooks, async (hook) => {
- await hook.beforeSettlement(this, inputs);
- });
-
- // Apply blockProof
- stateRoot.assertEquals(
- blockProof.publicInput.stateRoot,
- "Input state root not matching"
- );
-
- networkStateHash.assertEquals(
- blockProof.publicInput.networkStateHash,
- "Input networkStateHash not matching"
- );
- blockHashRoot.assertEquals(
- blockProof.publicInput.blockHashRoot,
- "Input blockHashRoot not matching"
- );
- this.stateRoot.set(blockProof.publicOutput.stateRoot);
- this.networkStateHash.set(blockProof.publicOutput.networkStateHash);
- this.blockHashRoot.set(blockProof.publicOutput.blockHashRoot);
-
- // Assert and apply deposit commitments
- promisedMessagesHash.assertEquals(
- blockProof.publicOutput.incomingMessagesHash,
- "Promised messages not honored"
- );
-
- // Set authorization for the dispatchContract to verify the messages hash update
- this.authorizationField.set(
- new UpdateMessagesHashAuth({
- target: dispatchContract.address,
- executedMessagesHash: promisedMessagesHash,
- newPromisedMessagesHash,
- }).hash()
- );
-
- // Call DispatchContract
- // This call checks that the promisedMessagesHash, which is already proven
- // to be the blockProofs publicoutput, is actually the current on-chain
- // promisedMessageHash. It also checks the newPromisedMessagesHash to be
- // a current sequencestate value
- await dispatchContract.updateMessagesHash(
- promisedMessagesHash,
- newPromisedMessagesHash
- );
-
- this.lastSettlementL1BlockHeight.set(minBlockHeightIncluded);
- }
-}
-
-export class SettlementSmartContract
- extends SettlementSmartContractBase
- implements SettlementContractType
-{
- @state(Field) public sequencerKey = State();
- @state(UInt32) public lastSettlementL1BlockHeight = State();
-
- @state(Field) public stateRoot = State();
- @state(Field) public networkStateHash = State();
- @state(Field) public blockHashRoot = State();
-
- @state(Field) public dispatchContractAddressX = State();
-
- @state(Field) public authorizationField = State();
-
- @method async approveBase(forest: AccountUpdateForest) {
- this.checkZeroBalanceChange(forest);
- }
-
- @method
- public async initialize(
- sequencer: PublicKey,
- dispatchContract: PublicKey,
- bridgeContract: PublicKey,
- contractKey: PrivateKey
- ) {
- await this.initializeBase(
- sequencer,
- dispatchContract,
- bridgeContract,
- contractKey
- );
- }
-
- @method
- public async addTokenBridge(
- tokenId: Field,
- address: PublicKey,
- dispatchContract: PublicKey
- ) {
- await this.deployTokenBridge(tokenId, address, dispatchContract);
- }
-
- @method
- public async settle(
- blockProof: DynamicBlockProof,
- signature: Signature,
- dispatchContractAddress: PublicKey,
- publicKey: PublicKey,
- inputNetworkState: NetworkState,
- outputNetworkState: NetworkState,
- newPromisedMessagesHash: Field
- ) {
- return await this.settleBase(
- blockProof,
- signature,
- dispatchContractAddress,
- publicKey,
- inputNetworkState,
- outputNetworkState,
- newPromisedMessagesHash
- );
- }
-}
-
-/* eslint-enable @typescript-eslint/lines-between-class-members */
diff --git a/packages/protocol/src/settlement/contracts/SettlementSmartContractModule.ts b/packages/protocol/src/settlement/contracts/SettlementSmartContractModule.ts
new file mode 100644
index 000000000..c776e5ff5
--- /dev/null
+++ b/packages/protocol/src/settlement/contracts/SettlementSmartContractModule.ts
@@ -0,0 +1,79 @@
+import { inject, injectable, injectAll } from "tsyringe";
+import {
+ ArtifactRecord,
+ ChildVerificationKeyService,
+ CompileRegistry,
+ log,
+} from "@proto-kit/common";
+
+import { BlockProvable } from "../../prover/block/BlockProvable";
+import {
+ ContractModule,
+ SmartContractClassFromInterface,
+} from "../ContractModule";
+import { ProvableSettlementHook } from "../modularity/ProvableSettlementHook";
+import { ContractArgsRegistry } from "../ContractArgsRegistry";
+
+import {
+ SettlementContractArgs,
+ SettlementContractType,
+} from "./settlement/SettlementBase";
+import { SettlementContract } from "./settlement/SettlementContract";
+
+export type SettlementContractConfig = {
+ escapeHatchSlotsInterval?: number;
+};
+
+// 24 hours
+export const DEFAULT_ESCAPE_HATCH = (60 / 3) * 24;
+
+@injectable()
+export class SettlementSmartContractModule extends ContractModule<
+ SettlementContractType,
+ SettlementContractConfig
+> {
+ public constructor(
+ @injectAll("ProvableSettlementHook")
+ private readonly hooks: ProvableSettlementHook[],
+ @inject("BlockProver")
+ private readonly blockProver: BlockProvable,
+ private readonly childVerificationKeyService: ChildVerificationKeyService,
+ private readonly argsRegistry: ContractArgsRegistry
+ ) {
+ super();
+ }
+
+ public contractFactory(): SmartContractClassFromInterface {
+ const { hooks, config } = this;
+
+ const escapeHatchSlotsInterval =
+ config.escapeHatchSlotsInterval ?? DEFAULT_ESCAPE_HATCH;
+
+ this.argsRegistry.addArgs("SettlementContract", {
+ hooks,
+ escapeHatchSlotsInterval,
+ ChildVerificationKeyService: this.childVerificationKeyService,
+ });
+
+ return SettlementContract;
+ }
+
+ public async compile(
+ registry: CompileRegistry
+ ): Promise {
+ // Dependencies
+ await this.blockProver.compile(registry);
+
+ this.contractFactory();
+
+ log.debug("Compiling Settlement Contract");
+
+ const artifact = await registry.forceProverExists(
+ async (reg) => await registry.compile(SettlementContract)
+ );
+
+ return {
+ SettlementSmartContract: artifact,
+ };
+ }
+}
diff --git a/packages/protocol/src/settlement/contracts/settlement/BridgingSettlementContract.ts b/packages/protocol/src/settlement/contracts/settlement/BridgingSettlementContract.ts
new file mode 100644
index 000000000..4865e4ec5
--- /dev/null
+++ b/packages/protocol/src/settlement/contracts/settlement/BridgingSettlementContract.ts
@@ -0,0 +1,283 @@
+import { TypedClass, O1PublicKeyOption } from "@proto-kit/common";
+import {
+ AccountUpdate,
+ Bool,
+ Field,
+ method,
+ PublicKey,
+ Signature,
+ SmartContract,
+ State,
+ state,
+ UInt32,
+ AccountUpdateForest,
+ VerificationKey,
+ Permissions,
+ Struct,
+ TokenId,
+ DeployArgs,
+} from "o1js";
+import { container } from "tsyringe";
+
+import { NetworkState } from "../../../model/network/NetworkState";
+import { DispatchContractType } from "../DispatchSmartContract";
+import { BridgeContractType } from "../BridgeContract";
+import { TokenBridgeDeploymentAuth } from "../authorizations/TokenBridgeDeploymentAuth";
+import { UpdateMessagesHashAuth } from "../authorizations/UpdateMessagesHashAuth";
+import {
+ ContractArgsRegistry,
+ NaiveObjectSchema,
+ StaticInitializationContract,
+} from "../../ContractArgsRegistry";
+
+import {
+ DynamicBlockProof,
+ SettlementBase,
+ SettlementContractArgs,
+ SettlementContractArgsSchema,
+ SettlementContractType,
+} from "./SettlementBase";
+
+/* eslint-disable @typescript-eslint/lines-between-class-members */
+
+export class TokenMapping extends Struct({
+ tokenId: Field,
+ publicKey: PublicKey,
+}) {}
+
+export interface BridgingSettlementContractType extends SettlementContractType {
+ authorizationField: State;
+
+ assertStateRoot: (root: Field) => AccountUpdate;
+ addTokenBridge: (tokenId: Field, address: PublicKey) => Promise;
+}
+
+export interface BridgingSettlementContractArgs extends SettlementContractArgs {
+ DispatchContract: TypedClass;
+ BridgeContract: TypedClass & typeof SmartContract;
+ // Lazily initialized
+ BridgeContractVerificationKey: VerificationKey | undefined;
+ BridgeContractPermissions: Permissions;
+}
+
+export const BridgingSettlementContractArgsSchema: NaiveObjectSchema =
+ {
+ ...SettlementContractArgsSchema,
+ DispatchContract: "Required",
+ BridgeContract: "Required",
+ BridgeContractVerificationKey: "Optional",
+ BridgeContractPermissions: "Required",
+ };
+
+export abstract class BridgingSettlementContractBase
+ extends SettlementBase
+ implements StaticInitializationContract
+{
+ public getInitializationArgs(): BridgingSettlementContractArgs {
+ return container
+ .resolve(ContractArgsRegistry)
+ .getArgs("SettlementContract", BridgingSettlementContractArgsSchema);
+ }
+
+ events = {
+ "token-bridge-deployed": TokenMapping,
+ };
+
+ abstract dispatchContractAddress: State;
+
+ abstract authorizationField: State;
+
+ // Not @state
+ // abstract offchainStateCommitmentsHash: State;
+
+ public assertStateRoot(root: Field): AccountUpdate {
+ this.stateRoot.requireEquals(root);
+ return this.self;
+ }
+
+ protected async initializeBaseBridging(
+ sequencer: PublicKey,
+ dispatchContract: PublicKey
+ ) {
+ await super.initializeBase(sequencer);
+
+ this.dispatchContractAddress.set(dispatchContract);
+ }
+
+ // TODO We should move this to the dispatchcontract eventually - or after mesa
+ // to the combined settlement & dispatch contract
+ protected async deployTokenBridge(tokenId: Field, address: PublicKey) {
+ const {
+ BridgeContractVerificationKey,
+ signedSettlements,
+ BridgeContractPermissions,
+ BridgeContract: BridgeContractClass,
+ DispatchContract,
+ } = this.getInitializationArgs();
+
+ const bridgeContract = new BridgeContractClass(address, tokenId);
+
+ if (
+ BridgeContractVerificationKey !== undefined &&
+ !BridgeContractVerificationKey.hash.isConstant()
+ ) {
+ throw new Error("Bridge contract verification key has to be constants");
+ }
+
+ // This function is not a zkapps method, therefore it will be part of this methods execution
+ // The returning account update (owner.self) is therefore part of this circuit and is assertable
+ const deploymentAccountUpdate = await bridgeContract.deployProvable(
+ BridgeContractVerificationKey,
+ signedSettlements!,
+ BridgeContractPermissions!,
+ this.address
+ );
+
+ this.approve(deploymentAccountUpdate);
+
+ this.self.body.mayUseToken = {
+ // Only set this if we deploy a custom token
+ parentsOwnToken: tokenId.equals(TokenId.default).not(),
+ inheritFromParent: Bool(false),
+ };
+
+ this.emitEvent(
+ "token-bridge-deployed",
+ new TokenMapping({
+ tokenId: tokenId,
+ publicKey: address,
+ })
+ );
+
+ const dispatchContractAddress =
+ this.dispatchContractAddress.getAndRequireEquals();
+
+ // Set authorization for the auth callback, that we need
+ this.authorizationField.set(
+ new TokenBridgeDeploymentAuth({
+ target: dispatchContractAddress,
+ tokenId,
+ address,
+ }).hash()
+ );
+ const dispatchContract = new DispatchContract(dispatchContractAddress);
+ await dispatchContract.enableTokenDeposits(tokenId, address, this.address);
+ }
+
+ protected async settleBaseBridging(
+ blockProof: DynamicBlockProof,
+ signature: Signature,
+ publicKey: PublicKey,
+ inputNetworkState: NetworkState,
+ outputNetworkState: NetworkState,
+ newPromisedMessagesHash: Field
+ ) {
+ await super.settleBase(
+ blockProof,
+ signature,
+ publicKey,
+ inputNetworkState,
+ outputNetworkState,
+ newPromisedMessagesHash
+ );
+
+ const dispatchContractAddress =
+ this.dispatchContractAddress.getAndRequireEquals();
+
+ const { DispatchContract } = this.getInitializationArgs();
+
+ // Get dispatch contract values
+ // These values are witnesses but will be checked later on the AU
+ // call to the dispatch contract via .updateMessagesHash()
+ const dispatchContract = new DispatchContract(dispatchContractAddress);
+ const promisedMessagesHash = dispatchContract.promisedMessagesHash.get();
+
+ // Assert and apply deposit commitments
+ promisedMessagesHash.assertEquals(
+ blockProof.publicOutput.incomingMessagesHash,
+ "Promised messages not honored"
+ );
+
+ // Set authorization for the dispatchContract to verify the messages hash update
+ this.authorizationField.set(
+ new UpdateMessagesHashAuth({
+ target: dispatchContract.address,
+ executedMessagesHash: promisedMessagesHash,
+ newPromisedMessagesHash,
+ }).hash()
+ );
+
+ // Call DispatchContract
+ // This call checks that the promisedMessagesHash, which is already proven
+ // to be the blockProofs publicoutput, is actually the current on-chain
+ // promisedMessageHash. It also checks the newPromisedMessagesHash to be
+ // a current sequencestate value
+ await dispatchContract.updateMessagesHash(
+ promisedMessagesHash,
+ newPromisedMessagesHash
+ );
+ }
+}
+
+export class BridgingSettlementContract
+ extends BridgingSettlementContractBase
+ implements BridgingSettlementContractType
+{
+ @state(Field) public sequencerKey = State();
+ @state(UInt32) public lastSettlementL1BlockHeight = State();
+
+ @state(Field) public stateRoot = State();
+ @state(Field) public networkStateHash = State();
+ @state(Field) public blockHashRoot = State();
+
+ @state(PublicKey) public dispatchContractAddress = State();
+
+ @state(Field) public authorizationField = State();
+
+ public async deployAndInitialize(
+ args: DeployArgs | undefined,
+ permissions: Permissions,
+ sequencer: PublicKey,
+ dispatchContract: O1PublicKeyOption
+ ): Promise {
+ dispatchContract.assertSome(
+ "Bridging-enabled settlement contract requires a dispatch contract address"
+ );
+
+ await super.deploy(args);
+
+ this.self.account.permissions.set(permissions);
+
+ await this.initializeBaseBridging(sequencer, dispatchContract.value);
+ }
+
+ @method async approveBase(forest: AccountUpdateForest) {
+ this.checkZeroBalanceChange(forest);
+ }
+
+ @method
+ public async addTokenBridge(tokenId: Field, address: PublicKey) {
+ await this.deployTokenBridge(tokenId, address);
+ }
+
+ @method
+ public async settle(
+ blockProof: DynamicBlockProof,
+ signature: Signature,
+ publicKey: PublicKey,
+ inputNetworkState: NetworkState,
+ outputNetworkState: NetworkState,
+ newPromisedMessagesHash: Field
+ ) {
+ return await this.settleBaseBridging(
+ blockProof,
+ signature,
+ publicKey,
+ inputNetworkState,
+ outputNetworkState,
+ newPromisedMessagesHash
+ );
+ }
+}
+
+/* eslint-enable @typescript-eslint/lines-between-class-members */
diff --git a/packages/protocol/src/settlement/contracts/settlement/SettlementBase.ts b/packages/protocol/src/settlement/contracts/settlement/SettlementBase.ts
new file mode 100644
index 000000000..050543b5f
--- /dev/null
+++ b/packages/protocol/src/settlement/contracts/settlement/SettlementBase.ts
@@ -0,0 +1,249 @@
+import {
+ DeployArgs,
+ DynamicProof,
+ Field,
+ Option,
+ PublicKey,
+ Signature,
+ State,
+ TokenContract,
+ UInt32,
+ Permissions,
+} from "o1js";
+import {
+ ChildVerificationKeyService,
+ LinkedMerkleTree,
+ mapSequential,
+ prefixToField,
+} from "@proto-kit/common";
+import { container } from "tsyringe";
+
+import { BlockHashMerkleTree } from "../../../prover/block/accummulators/BlockHashMerkleTree";
+import { NetworkState } from "../../../model/network/NetworkState";
+import {
+ ProvableSettlementHook,
+ SettlementHookInputs,
+ SettlementStateRecord,
+} from "../../modularity/ProvableSettlementHook";
+import {
+ BlockProverPublicInput,
+ BlockProverPublicOutput,
+} from "../../../prover/block/BlockProvable";
+import {
+ ContractArgsRegistry,
+ NaiveObjectSchema,
+ StaticInitializationContract,
+} from "../../ContractArgsRegistry";
+
+/* eslint-disable @typescript-eslint/lines-between-class-members */
+
+// Some random prefix for the sequencer signature
+export const BATCH_SIGNATURE_PREFIX = prefixToField("pk-batchSignature");
+
+export class DynamicBlockProof extends DynamicProof<
+ BlockProverPublicInput,
+ BlockProverPublicOutput
+> {
+ public static publicInputType = BlockProverPublicInput;
+
+ public static publicOutputType = BlockProverPublicOutput;
+
+ public static maxProofsVerified = 2 as const;
+}
+
+export interface SettlementContractType {
+ sequencerKey: State;
+ lastSettlementL1BlockHeight: State;
+ stateRoot: State;
+ networkStateHash: State;
+ blockHashRoot: State;
+
+ deployAndInitialize: (
+ args: DeployArgs | undefined,
+ permissions: Permissions,
+ sequencer: PublicKey,
+ dispatchContract: Option
+ ) => Promise;
+
+ settle: (
+ blockProof: DynamicBlockProof,
+ signature: Signature,
+ publicKey: PublicKey,
+ inputNetworkState: NetworkState,
+ outputNetworkState: NetworkState,
+ newPromisedMessagesHash: Field
+ ) => Promise;
+}
+
+export interface SettlementContractArgs {
+ hooks: ProvableSettlementHook[];
+ escapeHatchSlotsInterval: number;
+ signedSettlements: boolean;
+ ChildVerificationKeyService: ChildVerificationKeyService;
+}
+
+export const SettlementContractArgsSchema: NaiveObjectSchema =
+ {
+ ChildVerificationKeyService: "Required",
+ hooks: "Required",
+ escapeHatchSlotsInterval: "Required",
+ signedSettlements: "Required",
+ };
+
+export abstract class SettlementBase
+ extends TokenContract
+ implements StaticInitializationContract
+{
+ getInitializationArgs(): SettlementContractArgs {
+ return container
+ .resolve(ContractArgsRegistry)
+ .getArgs("SettlementContract", SettlementContractArgsSchema);
+ }
+
+ abstract sequencerKey: State;
+ abstract lastSettlementL1BlockHeight: State;
+ abstract stateRoot: State;
+ abstract networkStateHash: State;
+ abstract blockHashRoot: State;
+
+ protected async initializeBase(sequencer: PublicKey) {
+ this.sequencerKey.set(sequencer.x);
+ this.stateRoot.set(LinkedMerkleTree.EMPTY_ROOT);
+ this.blockHashRoot.set(Field(BlockHashMerkleTree.EMPTY_ROOT));
+ this.networkStateHash.set(NetworkState.empty().hash());
+ }
+
+ abstract settle(
+ blockProof: DynamicBlockProof,
+ signature: Signature,
+ publicKey: PublicKey,
+ inputNetworkState: NetworkState,
+ outputNetworkState: NetworkState,
+ newPromisedMessagesHash: Field
+ ): Promise;
+
+ abstract deployAndInitialize(
+ args: DeployArgs | undefined,
+ permissions: Permissions,
+ sequencer: PublicKey,
+ dispatchContract: Option
+ ): Promise;
+
+ protected async settleBase(
+ blockProof: DynamicBlockProof,
+ signature: Signature,
+ publicKey: PublicKey,
+ inputNetworkState: NetworkState,
+ outputNetworkState: NetworkState,
+ newPromisedMessagesHash: Field
+ ) {
+ const {
+ escapeHatchSlotsInterval,
+ hooks,
+ ChildVerificationKeyService: childVerificationKeyService,
+ } = this.getInitializationArgs();
+
+ // Brought in as a constant
+ const blockProofVk =
+ childVerificationKeyService.getVerificationKey("BlockProver");
+ if (!blockProofVk.hash.isConstant()) {
+ throw new Error("Sanity check - vk hash has to be constant");
+ }
+ // Verify the blockproof
+
+ blockProof.verify(blockProofVk);
+ // Get and assert on-chain values
+ const stateRoot = this.stateRoot.getAndRequireEquals();
+ const networkStateHash = this.networkStateHash.getAndRequireEquals();
+ const blockHashRoot = this.blockHashRoot.getAndRequireEquals();
+ const sequencerKey = this.sequencerKey.getAndRequireEquals();
+
+ const lastSettlementL1BlockHeight =
+ this.lastSettlementL1BlockHeight.getAndRequireEquals();
+
+ // Get block height and use the lower bound for all ops
+ const minBlockHeightIncluded = this.network.blockchainLength.get();
+ this.network.blockchainLength.requireBetween(
+ minBlockHeightIncluded,
+ // 5 because that is the length the newPromisedMessagesHash will be valid
+ minBlockHeightIncluded.add(4)
+ );
+
+ // Check signature/escape catch
+ publicKey.x.assertEquals(
+ sequencerKey,
+ "Sequencer public key witness not matching"
+ );
+ const signatureValid = signature.verify(publicKey, [
+ BATCH_SIGNATURE_PREFIX,
+ lastSettlementL1BlockHeight.value,
+ ]);
+ const escapeHatchActivated = lastSettlementL1BlockHeight
+ .add(UInt32.from(escapeHatchSlotsInterval))
+ .lessThan(minBlockHeightIncluded);
+ signatureValid
+ .or(escapeHatchActivated)
+ .assertTrue(
+ "Sequencer signature not valid and escape hatch not activated"
+ );
+
+ // Assert correctness of networkState witness
+ inputNetworkState
+ .hash()
+ .assertEquals(networkStateHash, "InputNetworkState witness not valid");
+ outputNetworkState
+ .hash()
+ .assertEquals(
+ blockProof.publicOutput.networkStateHash,
+ "OutputNetworkState witness not valid"
+ );
+
+ // Check remainders are zero
+ blockProof.publicOutput.proverStateRemainder.assertEquals(
+ Field(0),
+ "Supplied proof is has outstanding block prover state to be proven"
+ );
+
+ // Execute onSettlementHooks for additional checks
+ const stateRecord: SettlementStateRecord = {
+ blockHashRoot,
+ stateRoot,
+ networkStateHash,
+ lastSettlementL1BlockHeight,
+ sequencerKey: publicKey,
+ };
+ const inputs: SettlementHookInputs = {
+ blockProof,
+ contractState: stateRecord,
+ newPromisedMessagesHash,
+ fromNetworkState: inputNetworkState,
+ toNetworkState: outputNetworkState,
+ currentL1BlockHeight: minBlockHeightIncluded,
+ };
+ await mapSequential(hooks, async (hook) => {
+ await hook.beforeSettlement(this, inputs);
+ });
+
+ // Apply blockProof
+ stateRoot.assertEquals(
+ blockProof.publicInput.stateRoot,
+ "Input state root not matching"
+ );
+
+ networkStateHash.assertEquals(
+ blockProof.publicInput.networkStateHash,
+ "Input networkStateHash not matching"
+ );
+ blockHashRoot.assertEquals(
+ blockProof.publicInput.blockHashRoot,
+ "Input blockHashRoot not matching"
+ );
+ this.stateRoot.set(blockProof.publicOutput.stateRoot);
+ this.networkStateHash.set(blockProof.publicOutput.networkStateHash);
+ this.blockHashRoot.set(blockProof.publicOutput.blockHashRoot);
+
+ this.lastSettlementL1BlockHeight.set(minBlockHeightIncluded);
+ }
+}
+
+/* eslint-enable @typescript-eslint/lines-between-class-members */
diff --git a/packages/protocol/src/settlement/contracts/settlement/SettlementContract.ts b/packages/protocol/src/settlement/contracts/settlement/SettlementContract.ts
new file mode 100644
index 000000000..95321684f
--- /dev/null
+++ b/packages/protocol/src/settlement/contracts/settlement/SettlementContract.ts
@@ -0,0 +1,75 @@
+import {
+ State,
+ UInt32,
+ AccountUpdateForest,
+ state,
+ method,
+ PublicKey,
+ Field,
+ Signature,
+ DeployArgs,
+ Permissions,
+} from "o1js";
+import { O1PublicKeyOption } from "@proto-kit/common";
+
+import { NetworkState } from "../../../model/network/NetworkState";
+
+import {
+ DynamicBlockProof,
+ SettlementBase,
+ SettlementContractType,
+} from "./SettlementBase";
+
+export class SettlementContract
+ extends SettlementBase
+ implements SettlementContractType
+{
+ @state(Field) sequencerKey = State();
+
+ @state(UInt32) lastSettlementL1BlockHeight = State();
+
+ @state(Field) stateRoot = State();
+
+ @state(Field) networkStateHash = State();
+
+ @state(Field) blockHashRoot = State();
+
+ public async deployAndInitialize(
+ args: DeployArgs | undefined,
+ permissions: Permissions,
+ sequencer: PublicKey,
+ dispatchContract: O1PublicKeyOption
+ ): Promise {
+ dispatchContract.assertNone(
+ "Non-bridging settlement contract doesn't require a dispatch contract"
+ );
+
+ await super.deploy(args);
+
+ this.self.account.permissions.set(permissions);
+
+ await this.initializeBase(sequencer);
+ }
+
+ @method async approveBase(forest: AccountUpdateForest) {
+ this.checkZeroBalanceChange(forest);
+ }
+
+ @method async settle(
+ blockProof: DynamicBlockProof,
+ signature: Signature,
+ publicKey: PublicKey,
+ inputNetworkState: NetworkState,
+ outputNetworkState: NetworkState,
+ newPromisedMessagesHash: Field
+ ): Promise {
+ await super.settleBase(
+ blockProof,
+ signature,
+ publicKey,
+ inputNetworkState,
+ outputNetworkState,
+ newPromisedMessagesHash
+ );
+ }
+}
diff --git a/packages/protocol/src/settlement/modularity/ProvableSettlementHook.ts b/packages/protocol/src/settlement/modularity/ProvableSettlementHook.ts
index ecb117129..67148bfa1 100644
--- a/packages/protocol/src/settlement/modularity/ProvableSettlementHook.ts
+++ b/packages/protocol/src/settlement/modularity/ProvableSettlementHook.ts
@@ -3,8 +3,8 @@ import { InferProofBase } from "@proto-kit/common";
import { ProtocolModule } from "../../protocol/ProtocolModule";
import { NetworkState } from "../../model/network/NetworkState";
-import type { BlockProof } from "../../prover/block/BlockProver";
-import type { SettlementSmartContractBase } from "../contracts/SettlementSmartContract";
+import type { BlockProof } from "../../prover/block/BlockProvable";
+import type { SettlementContractType } from "../contracts/settlement/SettlementBase";
export type InputBlockProof = InferProofBase;
@@ -30,7 +30,7 @@ export abstract class ProvableSettlementHook<
Config,
> extends ProtocolModule {
public abstract beforeSettlement(
- smartContract: SettlementSmartContractBase,
+ smartContract: SettlementContractType,
inputs: SettlementHookInputs
): Promise;
}
diff --git a/packages/protocol/src/settlement/modularity/types.ts b/packages/protocol/src/settlement/modularity/types.ts
index 8f7c706e6..b05abdf6f 100644
--- a/packages/protocol/src/settlement/modularity/types.ts
+++ b/packages/protocol/src/settlement/modularity/types.ts
@@ -1,4 +1,5 @@
import { TypedClass } from "@proto-kit/common";
+import { SmartContract } from "o1js";
import {
ContractModule,
@@ -11,7 +12,7 @@ export type InferContractType<
> =
Module extends TypedClass
? ConcreteModule extends ContractModule
- ? Contract
+ ? Contract & SmartContract
: never
: never;
diff --git a/packages/protocol/src/settlement/modules/NetworkStateSettlementModule.ts b/packages/protocol/src/settlement/modules/NetworkStateSettlementModule.ts
index 739ccc27a..169492175 100644
--- a/packages/protocol/src/settlement/modules/NetworkStateSettlementModule.ts
+++ b/packages/protocol/src/settlement/modules/NetworkStateSettlementModule.ts
@@ -4,7 +4,7 @@ import {
ProvableSettlementHook,
SettlementHookInputs,
} from "../modularity/ProvableSettlementHook";
-import { SettlementSmartContract } from "../contracts/SettlementSmartContract";
+import { SettlementContractType } from "../contracts/settlement/SettlementBase";
type NetworkStateSettlementModuleConfig = {
blocksPerL1Block: UInt64;
@@ -13,7 +13,7 @@ type NetworkStateSettlementModuleConfig = {
/* eslint-disable @typescript-eslint/no-unused-vars */
export class NetworkStateSettlementModule extends ProvableSettlementHook {
public async beforeSettlement(
- smartContract: SettlementSmartContract,
+ smartContract: SettlementContractType,
{
blockProof,
fromNetworkState,
diff --git a/packages/protocol/src/utils/MinaPrefixedProvableHashList.ts b/packages/protocol/src/utils/MinaPrefixedProvableHashList.ts
index eaa2ff8f8..bfa6cb98e 100644
--- a/packages/protocol/src/utils/MinaPrefixedProvableHashList.ts
+++ b/packages/protocol/src/utils/MinaPrefixedProvableHashList.ts
@@ -47,11 +47,15 @@ export class MinaPrefixedProvableHashList<
public constructor(
valueType: ProvablePure,
public readonly prefix: string,
- internalCommitment: Field = Field(0)
+ internalCommitment?: Field
) {
super(valueType, internalCommitment);
}
+ public empty(): Field {
+ return Field(0);
+ }
+
protected hash(elements: Field[]): Field {
const init = salt(this.prefix);
const digest = Poseidon.update(init, elements);
@@ -60,7 +64,7 @@ export class MinaPrefixedProvableHashList<
}
export class MinaActionsHashList extends MinaPrefixedProvableHashList {
- public constructor(internalCommitment: Field = Field(0)) {
+ public constructor(internalCommitment?: Field) {
super(Field, MINA_PREFIXES.sequenceEvents, internalCommitment);
}
}
diff --git a/packages/protocol/src/utils/PrefixedProvableHashList.ts b/packages/protocol/src/utils/PrefixedProvableHashList.ts
index a31b78eea..4e9d4a755 100644
--- a/packages/protocol/src/utils/PrefixedProvableHashList.ts
+++ b/packages/protocol/src/utils/PrefixedProvableHashList.ts
@@ -15,6 +15,10 @@ export class PrefixedProvableHashList extends ProvableHashList {
this.prefix = stringToField(prefix);
}
+ public empty(): Field {
+ return Field(0);
+ }
+
protected hash(elements: Field[]): Field {
return Poseidon.hash([this.prefix, ...elements]);
}
diff --git a/packages/protocol/src/utils/ProvableHashList.ts b/packages/protocol/src/utils/ProvableHashList.ts
index 9b824d60a..da96f7a2a 100644
--- a/packages/protocol/src/utils/ProvableHashList.ts
+++ b/packages/protocol/src/utils/ProvableHashList.ts
@@ -23,23 +23,34 @@ export type VerifiedTransition = {
* Utilities for creating a hash list from a given value type.
*/
export abstract class ProvableHashList {
+ public commitment: Field;
+
public constructor(
protected readonly valueType: ProvablePure,
- public commitment: Field = Field(0),
+ commitment?: Field | undefined,
private unconstrainedList: Unconstrained<
ProvableHashListData[]
> = Unconstrained.from([])
- ) {}
+ ) {
+ this.commitment = commitment ?? this.empty();
+ }
+
+ protected abstract empty(): Field;
protected abstract hash(elements: Field[]): Field;
- private pushUnconstrained(preimage: Field, value: Value) {
- const valueConstant = this.valueType.fromFields(
- this.valueType.toFields(value).map((field) => field.toConstant())
- );
- this.unconstrainedList.get().push({
- preimage: preimage.toConstant(),
- value: valueConstant,
+ private pushUnconstrained(preimage: Field, value: Value, condition?: Bool) {
+ this.unconstrainedList.updateAsProver((array) => {
+ if (condition !== undefined && !condition.toBoolean()) {
+ return array;
+ }
+ return [
+ ...array,
+ {
+ preimage: preimage.toConstant(),
+ value: Provable.toConstant(this.valueType, value),
+ },
+ ];
});
}
@@ -61,11 +72,28 @@ export abstract class ProvableHashList