From 6c9142887d4672e259eddaf2d8ba0b4c0360ebfb Mon Sep 17 00:00:00 2001 From: Kevin Millikin Date: Mon, 30 Mar 2026 11:57:15 -0500 Subject: [PATCH 1/5] Add `keccakHash` to the standard library The signature is the same as for `persistentHash` (SHA-256). It is implemented in the JS target by a runtime function `keccakHash` with the same signature as the existing runtime function `persistentHash`. It is implemented in ZKIR v3 with a single new operation `keccak_hash` with the same signature as the existing `persistent_hash` operation. It is unsupported in ZKIR v2 and it is a compile-time error to use it in an impure circuit without passing the experimental feature flag `--feature-zkir-v3`. Signed-off-by: Kevin Millikin --- compiler/compiler-version.ss | 2 +- compiler/langs.ss | 1 + compiler/language-version.ss | 2 +- compiler/midnight-natives.ss | 9 +++ compiler/zkir-passes.ss | 69 ++++++++++++----------- compiler/zkir-v3-passes.ss | 10 ++++ doc/api/CompactStandardLibrary/README.md | 3 +- doc/api/CompactStandardLibrary/exports.md | 8 +++ runtime/package.json | 2 +- runtime/src/built-ins.ts | 10 ++++ 10 files changed, 79 insertions(+), 37 deletions(-) diff --git a/compiler/compiler-version.ss b/compiler/compiler-version.ss index f94bb25e..a1a50137 100644 --- a/compiler/compiler-version.ss +++ b/compiler/compiler-version.ss @@ -20,7 +20,7 @@ (import (chezscheme) (version)) ; NB: also update compactc version in ../flake.nix - (define compiler-version (make-version 'compiler 0 30 105)) + (define compiler-version (make-version 'compiler 0 30 106)) (define compiler-version-string (make-version-string compiler-version)) diff --git a/compiler/langs.ss b/compiler/langs.ss index 91ada955..edcd5a53 100644 --- a/compiler/langs.ss +++ b/compiler/langs.ss @@ -1194,6 +1194,7 @@ (encode outp0 outp1 inp) (hash_to_curve outp inp* ...) (impact inp inp* ...) + (keccak_hash outp0 outp1 (alignment* ...) inp* ...) (less_than outp inp0 inp1 imm) (mul outp inp0 inp1) (neg outp inp) diff --git a/compiler/language-version.ss b/compiler/language-version.ss index 76c6db81..591dc9d7 100644 --- a/compiler/language-version.ss +++ b/compiler/language-version.ss @@ -19,7 +19,7 @@ (export language-version-string check-language-version) (import (chezscheme) (version)) - (define language-version (make-version 'language 0 22 101)) + (define language-version (make-version 'language 0 22 102)) (define language-version-string (make-version-string language-version)) diff --git a/compiler/midnight-natives.ss b/compiler/midnight-natives.ss index b402c630..63e0cb95 100644 --- a/compiler/midnight-natives.ss +++ b/compiler/midnight-natives.ss @@ -13,6 +13,7 @@ ;;; See the License for the specific language governing permissions and ;;; limitations under the License. +;; ==== Transient (Poseidon) hashing (declare-native-entry circuit transientHash [A] "__compactRuntime.transientHash" ([value A (discloses "a hash of")]) @@ -24,6 +25,7 @@ [rand Field (discloses nothing)]) Field) +;; ==== Persistent (SHA-256) hashing (declare-native-entry circuit persistentHash [A] "__compactRuntime.persistentHash" ([value A (discloses "a hash of")]) @@ -45,6 +47,13 @@ ([x Field (discloses "a converted form of")]) (Bytes 32)) +;; ==== Other hashing circuits +(declare-native-entry circuit keccakHash [A] + "__compactRuntime.keccakHash" + ([value A (discloses "a hash of")]) + (Bytes 32)) + +;; ==== (declare-native-entry circuit jubjubPointX "__compactRuntime.jubjubPointX" ([np (TypeRef JubjubPoint) (discloses "the X coordinate of")]) diff --git a/compiler/zkir-passes.ss b/compiler/zkir-passes.ss index 3e412a96..756b7a59 100644 --- a/compiler/zkir-passes.ss +++ b/compiler/zkir-passes.ss @@ -168,52 +168,52 @@ (when (cdr a) (internal-errorf 'print-zkir "duplicate circuit name ~s" name)) (set-cdr! a handler))) (register-handler! 'transientHash - (lambda (align res* . xs) + (lambda (src align res* . xs) (print-gate "transient_hash" `[inputs ,xs]) (new-var! (car res*) #f))) (register-handler! 'degradeToTransient - (lambda (align res* a1 a2) (bind-var! (car res*) a2))) + (lambda (src align res* a1 a2) (bind-var! (car res*) a2))) (register-handler! 'upgradeFromTransient - (lambda (align res* a1) + (lambda (src align res* a1) (bind-var! (car res*) (literal 0)) (print-gate "div_mod_power_of_two" `[var ,a1] `[bits 248]) (set! ctr (add1 ctr)) (new-var! (cadr res*) #f))) (register-handler! 'ecAdd - (lambda (align res* ax ay bx by) + (lambda (src align res* ax ay bx by) (print-gate "ec_add" `[a_x ,ax] `[a_y ,ay] `[b_x ,bx] `[b_y ,by]) (new-var! (car res*) #f) (new-var! (cadr res*) #f))) (register-handler! 'ecMul - (lambda (align res* ax ay b) + (lambda (src align res* ax ay b) (print-gate "ec_mul" `[a_x ,ax] `[a_y ,ay] `[scalar ,b]) (new-var! (car res*) #f) (new-var! (cadr res*) #f))) (register-handler! 'ecMulGenerator - (lambda (align res* b) + (lambda (src align res* b) (print-gate "ec_mul_generator" `[scalar ,b]) (new-var! (car res*) #f) (new-var! (cadr res*) #f))) (register-handler! 'hashToCurve - (lambda (align res* . args*) + (lambda (src align res* . args*) (print-gate "hash_to_curve" `[inputs ,args*]) (new-var! (car res*) #f) (new-var! (cadr res*) #f))) (register-handler! 'jubjubPointX - (lambda (align res* a1 a2) + (lambda (src align res* a1 a2) (bind-var! (car res*) a1))) (register-handler! 'jubjubPointY - (lambda (align res* a1 a2) + (lambda (src align res* a1 a2) (bind-var! (car res*) a2))) (register-handler! 'constructJubjubPoint - (lambda (align res* a1 a2) + (lambda (src align res* a1 a2) (bind-var! (car res*) a1) (bind-var! (cadr res*) a2))) (register-handler! 'transientCommit ;; First n-1 args are the object being committed. ;; Final arg is commitment nonce. ;; commit algorithm is: object.fold(nonce, poseidon_compress) - (lambda (align res* . args*) + (lambda (src align res* . args*) (print-gate "transient_hash" `[inputs ,(cons (car (list-tail args* (sub1 (length args*)))) (list-head args* (sub1 (length args*))))]) (new-var! (car res*) #f))) @@ -221,7 +221,7 @@ ;; First n-2 args are the object being committed. ;; Final 2 args are commitment nonce. ;; commit algorithm is: object.fold(nonce, poseidon_compress) - (lambda (align res* . args*) + (lambda (src align res* . args*) (print-gate "persistent_hash" `[alignment ,(alignment->json (cons (with-output-language (Lflattened Alignment) @@ -232,7 +232,7 @@ (new-var! (car res*) #f) (new-var! (cadr res*) #f))) (register-handler! 'persistentHash - (lambda (align res* . args*) + (lambda (src align res* . args*) (print-gate "persistent_hash" `[alignment ,(alignment->json (caar align))] `[inputs ,args*]) @@ -240,16 +240,19 @@ ; FIXME: should check for expected number of res* (new-var! (car res*) #f) (new-var! (cadr res*) #f))) + (register-handler! 'keccakHash + (lambda (src align res* . args*) + (source-errorf src "keccakHash is not supported in ZKIR v2: try recompiling with the flag `--feature-zkir-v3`"))) (register-handler! 'ownPublicKey - (lambda (align res* . args*) + (lambda (src align res* . args*) ; handled as a witness (assert cannot-happen))) (register-handler! 'createZswapInput - (lambda (align res* . args*) + (lambda (src align res* . args*) ; handled as a witness (assert cannot-happen))) (register-handler! 'createZswapOutput - (lambda (align res* . args*) + (lambda (src align res* . args*) ; handled as a witness (assert cannot-happen))) ht)) @@ -356,7 +359,7 @@ [(builtin-circuit) (cond [(hashtable-ref std-circuits (cadr pair) #f) => - (lambda (handler) (apply handler (cddr pair) var-name* triv*))] + (lambda (handler) (apply handler src (cddr pair) var-name* triv*))] [else (source-errorf src "unrecognized native circuit ~a" (cadr pair))])] [(witness) (for-each @@ -514,10 +517,10 @@ [leaf1 (make-temp-id src 'leaf1)] [leaf2 (make-temp-id src 'leaf2)]) (apply (hashtable-ref std-circuits 'persistentHash #f) - (list* - (list (list (cons domain-sep-align alignment))) - (list leaf1 leaf2) - (cons (literal domain-sep-field) value-refs))) + src + (list (list (cons domain-sep-align alignment))) + (list leaf1 leaf2) + (cons (literal domain-sep-field) value-refs)) `(1 32 (ref . ,(var-idx leaf1)) (ref . ,(var-idx leaf2)))))] [(VMcoin-commit coin recipient) (let* ([coin (vmref-q coin)] @@ -541,21 +544,21 @@ `[b ,(car (cddddr recipient))]) (new-var! data2 #f) (apply (hashtable-ref std-circuits 'persistentHash #f) - (list* - ;; alignment of `CoinPreimage` in std.compact - (list (list (list - (abytes (length domain-sep-bytes)) - (abytes 32) - (abytes 32) - (abytes 16) - (abytes 1) - (abytes 32)))) - (list hash1 hash2) - (append + src + ;; alignment of `CoinPreimage` in std.compact + (list (list (list + (abytes (length domain-sep-bytes)) + (abytes 32) + (abytes 32) + (abytes 16) + (abytes 1) + (abytes 32)))) + (list hash1 hash2) + (append (list (literal domain-sep-field)) coin (list (car recipient)) - (list (var-idx data1) (var-idx data2))))) + (list (var-idx data1) (var-idx data2)))) `(1 32 (ref . ,(var-idx hash1)) (ref . ,(var-idx hash2))))] ;; There's room to tighten this in future, we just need to be careful to keep it ;; in-sync with the rust version. diff --git a/compiler/zkir-v3-passes.ss b/compiler/zkir-v3-passes.ss index 07faa72b..33761e30 100644 --- a/compiler/zkir-v3-passes.ss +++ b/compiler/zkir-v3-passes.ss @@ -106,6 +106,12 @@ [(jubjubPointY) (assert (= (length var-name*) 1)) (cons `(encode ,(make-temp-id src 'ignore) ,(car var-name*) ,(car triv*)) instr*)] + [(keccakHash) + (assert (= (length var-name*) 2)) + (let ([alignment* (arg->alignment arg* 0)]) + (cons `(keccak_hash ,(car var-name*) ,(cadr var-name*) + (,alignment* ...) ,triv* ...) + instr*))] [(persistentCommit) (assert (= (length var-name*) 2)) ;; The two source arguments are swapped for the persistent_hash gate. We assume @@ -891,6 +897,10 @@ `((op . "encode") (outputs . ,(vector outp0 outp1)) (input . ,inp)))] [(hash_to_curve ,[* outp] ,[* inp*] ...) `((op . "hash_to_curve") (output . ,outp) (inputs . ,(list->vector inp*)))] + [(keccak_hash ,outp0 ,outp1 (,alignment* ...) ,[* inp*] ...) + (let* ([outp0 (Output outp0)] [outp1 (Output outp1)]) + `((op . "keccak_hash") (outputs . ,(vector outp0 outp1)) + (alignment . ,(alignment->vector alignment*)) (inputs . ,(list->vector inp*))))] [(less_than ,[* outp] ,[* inp0] ,[* inp1] ,imm) `((op . "less_than") (output . ,outp) (a . ,inp0) (b . ,inp1) (bits . ,imm))] [(mul ,[* outp] ,[* inp0] ,[* inp1]) diff --git a/doc/api/CompactStandardLibrary/README.md b/doc/api/CompactStandardLibrary/README.md index 7541b69b..5db1be08 100644 --- a/doc/api/CompactStandardLibrary/README.md +++ b/doc/api/CompactStandardLibrary/README.md @@ -30,12 +30,13 @@ Key parts of the API are: - [`persistentHash`](exports.md#persistenthash) - [`persistentCommit`](exports.md#persistentcommit) - [`degradeToTransient`](exports.md#degradetotransient) + - [`upgradeFromTransient`](exports.md#upgradefromtransient) + - [`keccakHash`](exports.md#keccakHash) - Elliptic curve functions: - [`ecAdd`](exports.md#ecadd) - [`ecMul`](exports.md#ecmul) - [`ecMulGenerator`](exports.md#ecmulgenerator) - [`hashToCurve`](exports.md#hashtocurve) - - [`upgradeFromTransient`](exports.md#upgradefromtransient) - Merkle tree functions: - [`merkleTreePathRoot`](exports.md#merkletreepathroot) - [`merkleTreePathRootNoLeafHash`](exports.md#merkletreepathrootnoleafhash) diff --git a/doc/api/CompactStandardLibrary/exports.md b/doc/api/CompactStandardLibrary/exports.md index f4118350..4b52d682 100644 --- a/doc/api/CompactStandardLibrary/exports.md +++ b/doc/api/CompactStandardLibrary/exports.md @@ -287,6 +287,14 @@ circuit upgradeFromTransient(x: Field): Bytes<32>; ``` +### `keccakHash` + +TODO: Describe me. + +```compact +circuit keccakHash(value: T): Bytes<32>; +``` + ### `ecAdd` This function add two elliptic [`NativePoint`](#nativepoint)s (in multiplicative diff --git a/runtime/package.json b/runtime/package.json index 3a4837f3..45916e9d 100644 --- a/runtime/package.json +++ b/runtime/package.json @@ -1,6 +1,6 @@ { "name": "@midnight-ntwrk/compact-runtime", - "version": "0.15.101", + "version": "0.15.102", "description": "Compact Runtime", "type": "module", "exports": { diff --git a/runtime/src/built-ins.ts b/runtime/src/built-ins.ts index c43914d5..38d743a5 100644 --- a/runtime/src/built-ins.ts +++ b/runtime/src/built-ins.ts @@ -162,6 +162,16 @@ export function upgradeFromTransient(x: bigint): Uint8Array { return res; } +/** + * The Compact builtin `keccakHash` function + * + * TODO: Describe me. + */ +export function keccakHash(rtType: CompactType, value: A): Uint8Array { + // TODO: Implement me. + return new Uint8Array(32); +} + export function jubjubPointX(pt: JubjubPoint): bigint { return pt.x; } From 5e73bfc1c15de5efed13c19fe9fb56fc1ac9add6 Mon Sep 17 00:00:00 2001 From: Kevin Millikin Date: Mon, 30 Mar 2026 12:21:50 -0500 Subject: [PATCH 2/5] Add a CHANGELOG update Signed-off-by: Kevin Millikin --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b42a4224..65d0706b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,17 @@ 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.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Toolchain 0.30.106, language 0.22.102, runtime 0.15.102] + +### Added + +- Adds `keccakHash` to the standard library, with the same signature as + `persistentHash`. Adds `keccakHash` to the Compact runtime with the same + signature as `persistentHash`. `keccakHash` requires the experimental feature + flag `--feature-zkir-v3` to work in an impure circuit (or called from an + impure circuit). It is a compiler error to use it in an impure circuit using + the ZKIR v2 circuit backend. + ## [Toolchain 0.30.105, language 0.22.101, runtime 0.15.101] ### Added From c8e9085330303792a322b74afafacba62793aad1 Mon Sep 17 00:00:00 2001 From: iquerejeta Date: Tue, 31 Mar 2026 17:15:44 +0200 Subject: [PATCH 3/5] =?UTF-8?q?Implement=20keccak256=20using=20@noble/hash?= =?UTF-8?q?es/sha3=20=E2=80=94=20a=20pure-TypeScript,=20independently=20au?= =?UTF-8?q?dited=20library?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- compiler/midnight-natives.ss | 2 +- runtime/package-lock.json | 17 +++++++++++++++-- runtime/package.json | 1 + runtime/src/built-ins.ts | 20 +++++++++++++++----- runtime/test/stdlib.test.ts | 10 ++++++++++ 5 files changed, 42 insertions(+), 8 deletions(-) diff --git a/compiler/midnight-natives.ss b/compiler/midnight-natives.ss index 63e0cb95..b55b2458 100644 --- a/compiler/midnight-natives.ss +++ b/compiler/midnight-natives.ss @@ -49,7 +49,7 @@ ;; ==== Other hashing circuits (declare-native-entry circuit keccakHash [A] - "__compactRuntime.keccakHash" + "__compactRuntime.keccak256" ([value A (discloses "a hash of")]) (Bytes 32)) diff --git a/runtime/package-lock.json b/runtime/package-lock.json index 5f892cfc..940f4eb3 100644 --- a/runtime/package-lock.json +++ b/runtime/package-lock.json @@ -1,15 +1,16 @@ { "name": "@midnight-ntwrk/compact-runtime", - "version": "0.15.101", + "version": "0.15.102", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@midnight-ntwrk/compact-runtime", - "version": "0.15.101", + "version": "0.15.102", "license": "Apache-2.0", "dependencies": { "@midnight-ntwrk/onchain-runtime-v3": "^3.0.0", + "@noble/hashes": "^2.0.1", "@types/object-inspect": "^1.8.1", "object-inspect": "^1.12.3" }, @@ -643,6 +644,18 @@ "resolved": "https://registry.npmjs.org/@midnight-ntwrk/onchain-runtime-v3/-/onchain-runtime-v3-3.0.0.tgz", "integrity": "sha512-HbFbUOsvgpEFy1OT0Ni2LMFk4jnMQS1em+H+Mof/B3DpnNKl0Lkx5QiulKOc6pyU4KPEagOqx4fYNyVXFwgZ7g==" }, + "node_modules/@noble/hashes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.0.1.tgz", + "integrity": "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", diff --git a/runtime/package.json b/runtime/package.json index 45916e9d..8bb77407 100644 --- a/runtime/package.json +++ b/runtime/package.json @@ -34,6 +34,7 @@ ], "dependencies": { "@midnight-ntwrk/onchain-runtime-v3": "^3.0.0", + "@noble/hashes": "^2.0.1", "@types/object-inspect": "^1.8.1", "object-inspect": "^1.12.3" }, diff --git a/runtime/src/built-ins.ts b/runtime/src/built-ins.ts index 38d743a5..0fe44192 100644 --- a/runtime/src/built-ins.ts +++ b/runtime/src/built-ins.ts @@ -14,6 +14,7 @@ // limitations under the License. import * as ocrt from '@midnight-ntwrk/onchain-runtime-v3'; +import { keccak_256 } from '@noble/hashes/sha3.js'; import { MAX_FIELD } from './constants.js'; import { CompactType, CompactTypeJubjubPoint, JubjubPoint } from './compact-types.js'; import { CompactError } from './error.js'; @@ -163,13 +164,22 @@ export function upgradeFromTransient(x: bigint): Uint8Array { } /** - * The Compact builtin `keccakHash` function + * The Compact builtin `keccak256` function * - * TODO: Describe me. + * Hashes `value` using Keccak-256 and returns the 32-byte digest. + * + * @throws If `rtType` encodes a type containing Compact 'Opaque' types */ -export function keccakHash(rtType: CompactType, value: A): Uint8Array { - // TODO: Implement me. - return new Uint8Array(32); +export function keccak256(rtType: CompactType, value: A): Uint8Array { + const chunks = rtType.toValue(value); + const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0); + const bytes = new Uint8Array(totalLength); + let offset = 0; + for (const chunk of chunks) { + bytes.set(chunk, offset); + offset += chunk.length; + } + return keccak_256(bytes); } export function jubjubPointX(pt: JubjubPoint): bigint { diff --git a/runtime/test/stdlib.test.ts b/runtime/test/stdlib.test.ts index bf9e9f2c..5da51667 100644 --- a/runtime/test/stdlib.test.ts +++ b/runtime/test/stdlib.test.ts @@ -166,6 +166,16 @@ describe('builtin hash functions', () => { expect(res.length).toBe(32); }); + test('keccak256', () => { + const res = compactRuntime.keccak256(compactRuntime.CompactTypeField, 5n); + expect(res).toBeInstanceOf(Uint8Array); + expect(res.length).toBe(32); + // keccak256 must be deterministic + expect(compactRuntime.keccak256(compactRuntime.CompactTypeField, 5n)).toEqual(res); + // distinct inputs must produce distinct outputs + expect(compactRuntime.keccak256(compactRuntime.CompactTypeField, 6n)).not.toEqual(res); + }); + test('transientCommit', () => { expect( typeof compactRuntime.transientCommit( From 104d1bb46bc7ef13bdab15624df06188dd734fc9 Mon Sep 17 00:00:00 2001 From: Kevin Millikin Date: Tue, 31 Mar 2026 10:24:33 -0500 Subject: [PATCH 4/5] Rename keccakHash to keccak256 Signed-off-by: Kevin Millikin --- CHANGELOG.md | 6 +++--- compiler/langs.ss | 2 +- compiler/midnight-natives.ss | 4 ++-- compiler/zkir-passes.ss | 4 ++-- compiler/zkir-v3-passes.ss | 8 ++++---- doc/api/CompactStandardLibrary/README.md | 2 +- doc/api/CompactStandardLibrary/exports.md | 4 ++-- runtime/src/built-ins.ts | 4 ++-- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 65d0706b..879ec1a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,9 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- Adds `keccakHash` to the standard library, with the same signature as - `persistentHash`. Adds `keccakHash` to the Compact runtime with the same - signature as `persistentHash`. `keccakHash` requires the experimental feature +- Adds `keccak256` to the standard library, with the same signature as + `persistentHash`. Adds `keccak256` to the Compact runtime with the same + signature as `persistentHash`. `keccak256` requires the experimental feature flag `--feature-zkir-v3` to work in an impure circuit (or called from an impure circuit). It is a compiler error to use it in an impure circuit using the ZKIR v2 circuit backend. diff --git a/compiler/langs.ss b/compiler/langs.ss index edcd5a53..7f768118 100644 --- a/compiler/langs.ss +++ b/compiler/langs.ss @@ -1194,7 +1194,7 @@ (encode outp0 outp1 inp) (hash_to_curve outp inp* ...) (impact inp inp* ...) - (keccak_hash outp0 outp1 (alignment* ...) inp* ...) + (keccak256 outp0 outp1 (alignment* ...) inp* ...) (less_than outp inp0 inp1 imm) (mul outp inp0 inp1) (neg outp inp) diff --git a/compiler/midnight-natives.ss b/compiler/midnight-natives.ss index 63e0cb95..d77bd5f6 100644 --- a/compiler/midnight-natives.ss +++ b/compiler/midnight-natives.ss @@ -48,8 +48,8 @@ (Bytes 32)) ;; ==== Other hashing circuits -(declare-native-entry circuit keccakHash [A] - "__compactRuntime.keccakHash" +(declare-native-entry circuit keccak256 [A] + "__compactRuntime.keccak256" ([value A (discloses "a hash of")]) (Bytes 32)) diff --git a/compiler/zkir-passes.ss b/compiler/zkir-passes.ss index 756b7a59..0130191a 100644 --- a/compiler/zkir-passes.ss +++ b/compiler/zkir-passes.ss @@ -240,9 +240,9 @@ ; FIXME: should check for expected number of res* (new-var! (car res*) #f) (new-var! (cadr res*) #f))) - (register-handler! 'keccakHash + (register-handler! 'keccak256 (lambda (src align res* . args*) - (source-errorf src "keccakHash is not supported in ZKIR v2: try recompiling with the flag `--feature-zkir-v3`"))) + (source-errorf src "keccak256 is not supported in ZKIR v2: try recompiling with the flag `--feature-zkir-v3`"))) (register-handler! 'ownPublicKey (lambda (src align res* . args*) ; handled as a witness diff --git a/compiler/zkir-v3-passes.ss b/compiler/zkir-v3-passes.ss index 33761e30..4f405ebc 100644 --- a/compiler/zkir-v3-passes.ss +++ b/compiler/zkir-v3-passes.ss @@ -106,10 +106,10 @@ [(jubjubPointY) (assert (= (length var-name*) 1)) (cons `(encode ,(make-temp-id src 'ignore) ,(car var-name*) ,(car triv*)) instr*)] - [(keccakHash) + [(keccak256) (assert (= (length var-name*) 2)) (let ([alignment* (arg->alignment arg* 0)]) - (cons `(keccak_hash ,(car var-name*) ,(cadr var-name*) + (cons `(keccak256 ,(car var-name*) ,(cadr var-name*) (,alignment* ...) ,triv* ...) instr*))] [(persistentCommit) @@ -897,9 +897,9 @@ `((op . "encode") (outputs . ,(vector outp0 outp1)) (input . ,inp)))] [(hash_to_curve ,[* outp] ,[* inp*] ...) `((op . "hash_to_curve") (output . ,outp) (inputs . ,(list->vector inp*)))] - [(keccak_hash ,outp0 ,outp1 (,alignment* ...) ,[* inp*] ...) + [(keccak256 ,outp0 ,outp1 (,alignment* ...) ,[* inp*] ...) (let* ([outp0 (Output outp0)] [outp1 (Output outp1)]) - `((op . "keccak_hash") (outputs . ,(vector outp0 outp1)) + `((op . "keccak256") (outputs . ,(vector outp0 outp1)) (alignment . ,(alignment->vector alignment*)) (inputs . ,(list->vector inp*))))] [(less_than ,[* outp] ,[* inp0] ,[* inp1] ,imm) `((op . "less_than") (output . ,outp) (a . ,inp0) (b . ,inp1) (bits . ,imm))] diff --git a/doc/api/CompactStandardLibrary/README.md b/doc/api/CompactStandardLibrary/README.md index 5db1be08..dad0af51 100644 --- a/doc/api/CompactStandardLibrary/README.md +++ b/doc/api/CompactStandardLibrary/README.md @@ -31,7 +31,7 @@ Key parts of the API are: - [`persistentCommit`](exports.md#persistentcommit) - [`degradeToTransient`](exports.md#degradetotransient) - [`upgradeFromTransient`](exports.md#upgradefromtransient) - - [`keccakHash`](exports.md#keccakHash) + - [`keccak256`](exports.md#keccak256) - Elliptic curve functions: - [`ecAdd`](exports.md#ecadd) - [`ecMul`](exports.md#ecmul) diff --git a/doc/api/CompactStandardLibrary/exports.md b/doc/api/CompactStandardLibrary/exports.md index 4b52d682..a1fcbcba 100644 --- a/doc/api/CompactStandardLibrary/exports.md +++ b/doc/api/CompactStandardLibrary/exports.md @@ -287,12 +287,12 @@ circuit upgradeFromTransient(x: Field): Bytes<32>; ``` -### `keccakHash` +### `keccak256` TODO: Describe me. ```compact -circuit keccakHash(value: T): Bytes<32>; +circuit keccak256(value: T): Bytes<32>; ``` ### `ecAdd` diff --git a/runtime/src/built-ins.ts b/runtime/src/built-ins.ts index 38d743a5..a3a89113 100644 --- a/runtime/src/built-ins.ts +++ b/runtime/src/built-ins.ts @@ -163,11 +163,11 @@ export function upgradeFromTransient(x: bigint): Uint8Array { } /** - * The Compact builtin `keccakHash` function + * The Compact builtin `keccak256` function * * TODO: Describe me. */ -export function keccakHash(rtType: CompactType, value: A): Uint8Array { +export function keccak256(rtType: CompactType, value: A): Uint8Array { // TODO: Implement me. return new Uint8Array(32); } From 079eba3c9854e819de80ec7862e5636e265d1592 Mon Sep 17 00:00:00 2001 From: Kevin Millikin Date: Tue, 31 Mar 2026 13:41:12 -0500 Subject: [PATCH 5/5] Update the standard library documentation Signed-off-by: Kevin Millikin --- doc/api/CompactStandardLibrary/exports.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/api/CompactStandardLibrary/exports.md b/doc/api/CompactStandardLibrary/exports.md index a1fcbcba..0f4059a7 100644 --- a/doc/api/CompactStandardLibrary/exports.md +++ b/doc/api/CompactStandardLibrary/exports.md @@ -289,10 +289,11 @@ circuit upgradeFromTransient(x: Field): Bytes<32>; ### `keccak256` -TODO: Describe me. +This function hashes its input using the Keccak-256 algorithm. It returns the +32-byte digest. ```compact -circuit keccak256(value: T): Bytes<32>; +circuit keccak256(value: T): Bytes<32>; ``` ### `ecAdd`