@orbinum/sdk 0.10.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +178 -52
- package/dist/index.d.ts +178 -52
- package/dist/index.js +204 -60
- package/dist/index.mjs +208 -63
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -26,8 +26,10 @@ __export(index_exports, {
|
|
|
26
26
|
BABYJUB_SUBORDER: () => BABYJUB_SUBORDER,
|
|
27
27
|
BN254_R: () => BN254_R,
|
|
28
28
|
Blake2256: () => import_substrate_bindings3.Blake2256,
|
|
29
|
+
CURRENT_CIRCUIT_VERSION: () => CURRENT_CIRCUIT_VERSION,
|
|
29
30
|
CircuitId: () => CircuitId,
|
|
30
|
-
CircuitType: () =>
|
|
31
|
+
CircuitType: () => import_proof_generator2.CircuitType,
|
|
32
|
+
CircuitVersionResolver: () => CircuitVersionResolver,
|
|
31
33
|
CryptoPrecompiles: () => CryptoPrecompiles,
|
|
32
34
|
ENCRYPTED_MEMO_SIZE: () => ENCRYPTED_MEMO_SIZE,
|
|
33
35
|
EncryptedMemo: () => EncryptedMemo,
|
|
@@ -50,7 +52,7 @@ __export(index_exports, {
|
|
|
50
52
|
Storage: () => import_substrate_bindings3.Storage,
|
|
51
53
|
SubstrateClient: () => SubstrateClient,
|
|
52
54
|
VaultLockedError: () => VaultLockedError,
|
|
53
|
-
WebArtifactProvider: () =>
|
|
55
|
+
WebArtifactProvider: () => import_proof_generator2.WebArtifactProvider,
|
|
54
56
|
ZkVerifierModule: () => ZkVerifierModule,
|
|
55
57
|
accountIdHexToSs58: () => accountIdHexToSs58,
|
|
56
58
|
addressToAccountIdHex: () => addressToAccountIdHex,
|
|
@@ -1150,11 +1152,27 @@ var EvmExplorer = class _EvmExplorer {
|
|
|
1150
1152
|
};
|
|
1151
1153
|
|
|
1152
1154
|
// src/indexer/IndexerClient.ts
|
|
1155
|
+
var LOCAL_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]", "::1"]);
|
|
1156
|
+
function normalizeBaseUrl(baseUrl) {
|
|
1157
|
+
let url;
|
|
1158
|
+
try {
|
|
1159
|
+
url = new URL(baseUrl);
|
|
1160
|
+
} catch {
|
|
1161
|
+
throw new Error(`IndexerClient: invalid baseUrl ${JSON.stringify(baseUrl)}`);
|
|
1162
|
+
}
|
|
1163
|
+
const isLocal = LOCAL_HOSTS.has(url.hostname);
|
|
1164
|
+
if (url.protocol !== "https:" && !(url.protocol === "http:" && isLocal)) {
|
|
1165
|
+
throw new Error(
|
|
1166
|
+
`IndexerClient: baseUrl must use https:// (got ${url.protocol}//${url.hostname}). Plain http is only allowed for localhost.`
|
|
1167
|
+
);
|
|
1168
|
+
}
|
|
1169
|
+
return baseUrl.replace(/\/$/, "");
|
|
1170
|
+
}
|
|
1153
1171
|
var IndexerClient = class _IndexerClient {
|
|
1154
1172
|
baseUrl;
|
|
1155
1173
|
timeoutMs;
|
|
1156
1174
|
constructor(config) {
|
|
1157
|
-
this.baseUrl = config.baseUrl
|
|
1175
|
+
this.baseUrl = normalizeBaseUrl(config.baseUrl);
|
|
1158
1176
|
this.timeoutMs = config.timeoutMs ?? 1e4;
|
|
1159
1177
|
}
|
|
1160
1178
|
// ─── Internal helpers ──────────────────────────────────────────────────────
|
|
@@ -1212,7 +1230,7 @@ var IndexerClient = class _IndexerClient {
|
|
|
1212
1230
|
/**
|
|
1213
1231
|
* Returns a paginated list of stealth scan hints ordered ascending by leafIndex.
|
|
1214
1232
|
* Each hint contains only the fields required for ECDH triage and decryption:
|
|
1215
|
-
* leafIndex, commitmentHex, assetId, ephPkHex, encryptedMemo.
|
|
1233
|
+
* leafIndex, commitmentHex, assetId, ephPkHex, encryptedMemo, circuitVersion.
|
|
1216
1234
|
*
|
|
1217
1235
|
* Use `sinceLeafIndex` for incremental scans (cursor = last seen leafIndex + 1).
|
|
1218
1236
|
*/
|
|
@@ -1632,8 +1650,8 @@ var BABYJUB_SUBORDER = 273603035897990940278080071815715938607681397215856725920
|
|
|
1632
1650
|
// src/shielded-pool/protocol/memo.ts
|
|
1633
1651
|
var import_sha2 = require("@noble/hashes/sha2.js");
|
|
1634
1652
|
var KEY_DOMAIN = new TextEncoder().encode("orbinum-note-encryption-v1");
|
|
1635
|
-
var MEMO_PLAINTEXT_SIZE =
|
|
1636
|
-
function serializeMemo(value, ownerPk, blinding, assetId, counterpartyPk) {
|
|
1653
|
+
var MEMO_PLAINTEXT_SIZE = 120;
|
|
1654
|
+
function serializeMemo(value, ownerPk, blinding, assetId, counterpartyPk, circuitVersion) {
|
|
1637
1655
|
const buf = new Uint8Array(MEMO_PLAINTEXT_SIZE);
|
|
1638
1656
|
const view = new DataView(buf.buffer);
|
|
1639
1657
|
view.setBigUint64(0, value & 0xffffffffffffffffn, true);
|
|
@@ -1642,6 +1660,7 @@ function serializeMemo(value, ownerPk, blinding, assetId, counterpartyPk) {
|
|
|
1642
1660
|
buf.set(blinding.slice(0, 32), 48);
|
|
1643
1661
|
view.setUint32(80, assetId >>> 0, true);
|
|
1644
1662
|
buf.set(counterpartyPk.slice(0, 32), 84);
|
|
1663
|
+
view.setUint32(116, circuitVersion >>> 0, true);
|
|
1645
1664
|
return buf;
|
|
1646
1665
|
}
|
|
1647
1666
|
function deriveEncryptionKey(sharedSecret, commitment) {
|
|
@@ -1654,7 +1673,7 @@ function deriveEncryptionKey(sharedSecret, commitment) {
|
|
|
1654
1673
|
|
|
1655
1674
|
// src/shielded-pool/protocol/EncryptedMemo.ts
|
|
1656
1675
|
var NONCE_SIZE = 12;
|
|
1657
|
-
var CIPHERTEXT_SIZE =
|
|
1676
|
+
var CIPHERTEXT_SIZE = 136;
|
|
1658
1677
|
var EPH_PK_SIZE = 32;
|
|
1659
1678
|
var ENCRYPTED_MEMO_SIZE = NONCE_SIZE + CIPHERTEXT_SIZE + EPH_PK_SIZE;
|
|
1660
1679
|
function bytesToBjjScalar(bytes) {
|
|
@@ -1673,14 +1692,15 @@ function parsePlaintext(nonce, ciphertextWithMac, encKey) {
|
|
|
1673
1692
|
const blinding = bytesToBigintLE(plaintext.slice(48, 80));
|
|
1674
1693
|
const assetId = BigInt(view.getUint32(80, true));
|
|
1675
1694
|
const counterpartyPk = bytesToBigintLE(plaintext.slice(84, 116));
|
|
1676
|
-
|
|
1695
|
+
const circuitVersion = view.getUint32(116, true);
|
|
1696
|
+
return { value, ownerPk, blinding, assetId, counterpartyPk, circuitVersion };
|
|
1677
1697
|
} catch {
|
|
1678
1698
|
return null;
|
|
1679
1699
|
}
|
|
1680
1700
|
}
|
|
1681
1701
|
var EncryptedMemo = {
|
|
1682
1702
|
/**
|
|
1683
|
-
* Build and encrypt a memo for a note using ECDH (v2,
|
|
1703
|
+
* Build and encrypt a memo for a note using ECDH (v2, 180 bytes).
|
|
1684
1704
|
*
|
|
1685
1705
|
* @param value Note value in planck.
|
|
1686
1706
|
* @param ownerPk 32-byte owner public key (LE).
|
|
@@ -1692,11 +1712,20 @@ var EncryptedMemo = {
|
|
|
1692
1712
|
* decoded from a privacy address).
|
|
1693
1713
|
* Pass `new Uint8Array(32)` (all zeros) for a publicly-readable memo.
|
|
1694
1714
|
* @param counterpartyPk 32-byte counterparty BJJ Ax. Default: all zeros.
|
|
1695
|
-
* @
|
|
1715
|
+
* @param circuitVersion ZK circuit version the note is spent under. Default: 0.
|
|
1716
|
+
* @param ephSkOverride 32-byte ephemeral secret key (stealth coordination). Optional.
|
|
1717
|
+
* @returns 180-byte encrypted memo: nonce(12) || ciphertext+MAC(136) || ephPk(32).
|
|
1696
1718
|
*/
|
|
1697
|
-
encrypt(value, ownerPk, blinding, assetId, commitment, recipientIvkPacked, counterpartyPk = new Uint8Array(32), ephSkOverride) {
|
|
1719
|
+
encrypt(value, ownerPk, blinding, assetId, commitment, recipientIvkPacked, counterpartyPk = new Uint8Array(32), circuitVersion = 0, ephSkOverride) {
|
|
1698
1720
|
const nonce = (0, import_utils.randomBytes)(NONCE_SIZE);
|
|
1699
|
-
const plaintext = serializeMemo(
|
|
1721
|
+
const plaintext = serializeMemo(
|
|
1722
|
+
value,
|
|
1723
|
+
ownerPk,
|
|
1724
|
+
blinding,
|
|
1725
|
+
assetId,
|
|
1726
|
+
counterpartyPk,
|
|
1727
|
+
circuitVersion
|
|
1728
|
+
);
|
|
1700
1729
|
const isZeroKey = recipientIvkPacked.every((b) => b === 0);
|
|
1701
1730
|
let sharedSecret;
|
|
1702
1731
|
let ephPkPackedBytes;
|
|
@@ -1727,29 +1756,31 @@ var EncryptedMemo = {
|
|
|
1727
1756
|
return result;
|
|
1728
1757
|
},
|
|
1729
1758
|
/**
|
|
1730
|
-
* Returns a
|
|
1759
|
+
* Returns a 180-byte public memo encrypted with a zero viewing key.
|
|
1731
1760
|
* Decryptable by anyone with `decrypt(memo, commitment, new Uint8Array(32))`.
|
|
1732
1761
|
* Convenience alias for `encrypt(..., new Uint8Array(32))`.
|
|
1733
1762
|
*/
|
|
1734
|
-
encryptPublic(value, ownerPk, blinding, assetId, commitment) {
|
|
1763
|
+
encryptPublic(value, ownerPk, blinding, assetId, commitment, circuitVersion = 0) {
|
|
1735
1764
|
return EncryptedMemo.encrypt(
|
|
1736
1765
|
value,
|
|
1737
1766
|
ownerPk,
|
|
1738
1767
|
blinding,
|
|
1739
1768
|
assetId,
|
|
1740
1769
|
commitment,
|
|
1741
|
-
new Uint8Array(32)
|
|
1770
|
+
new Uint8Array(32),
|
|
1771
|
+
new Uint8Array(32),
|
|
1772
|
+
circuitVersion
|
|
1742
1773
|
);
|
|
1743
1774
|
},
|
|
1744
1775
|
/**
|
|
1745
|
-
* Returns a
|
|
1776
|
+
* Returns a 180-byte zeroed dummy memo (no information, always valid on-chain).
|
|
1746
1777
|
*/
|
|
1747
1778
|
dummy() {
|
|
1748
1779
|
return new Uint8Array(ENCRYPTED_MEMO_SIZE);
|
|
1749
1780
|
},
|
|
1750
1781
|
/**
|
|
1751
1782
|
* Validates that `bytes` is a properly-sized encrypted memo.
|
|
1752
|
-
* Throws an Error if the length is not ENCRYPTED_MEMO_SIZE (
|
|
1783
|
+
* Throws an Error if the length is not ENCRYPTED_MEMO_SIZE (180 bytes).
|
|
1753
1784
|
*
|
|
1754
1785
|
* Call this at system boundaries (extrinsic builders, precompile encoders)
|
|
1755
1786
|
* to catch malformed memos before they reach the chain and fail on-chain.
|
|
@@ -1770,7 +1801,7 @@ var EncryptedMemo = {
|
|
|
1770
1801
|
* Returns null if decryption fails — wrong key, bad MAC, or malformed memo.
|
|
1771
1802
|
* Never throws; safe for scan loops.
|
|
1772
1803
|
*
|
|
1773
|
-
* @param memoBytes
|
|
1804
|
+
* @param memoBytes 180-byte encrypted memo.
|
|
1774
1805
|
* @param commitment 32-byte note commitment (LE).
|
|
1775
1806
|
* @param viewingSecretKey 32-byte HKDF viewing secret key from deriveViewingSecretKey().
|
|
1776
1807
|
*/
|
|
@@ -1782,13 +1813,13 @@ var EncryptedMemo = {
|
|
|
1782
1813
|
* Extract the ECDH shared secret from an encrypted memo using the recipient's viewing secret key.
|
|
1783
1814
|
*
|
|
1784
1815
|
* Used by NoteDecryptor to obtain the shared secret needed for stealth address derivation
|
|
1785
|
-
* without re-running the full decrypt path. Safe to call on any
|
|
1816
|
+
* without re-running the full decrypt path. Safe to call on any 180-byte memo.
|
|
1786
1817
|
*
|
|
1787
1818
|
* Returns `new Uint8Array(32)` (all zeros) for public/dummy memos (zero ephPk).
|
|
1788
1819
|
* Returns `null` if the memo is malformed or the ephPk is not a valid BJJ point.
|
|
1789
1820
|
* Never throws; safe for scan loops.
|
|
1790
1821
|
*
|
|
1791
|
-
* @param memoBytes
|
|
1822
|
+
* @param memoBytes 180-byte encrypted memo.
|
|
1792
1823
|
* @param viewingSecretKey 32-byte HKDF viewing secret key from deriveViewingSecretKey().
|
|
1793
1824
|
*/
|
|
1794
1825
|
extractSharedSecret(memoBytes, viewingSecretKey) {
|
|
@@ -1992,7 +2023,7 @@ var ShieldedPoolModule = class {
|
|
|
1992
2023
|
* Withdraws tokens from the shielded pool to a public address.
|
|
1993
2024
|
* Submits as an UNSIGNED (gasless) transaction — fee is embedded in the ZK proof.
|
|
1994
2025
|
* Pass a `signer` to fall back to signed submission (e.g. for testing).
|
|
1995
|
-
* Extrinsic: shieldedPool.unshield(proof, merkleRoot, nullifier, assetId, amount, recipient, fee)
|
|
2026
|
+
* Extrinsic: shieldedPool.unshield(proof, merkleRoot, nullifier, assetId, amount, recipient, fee, changeCommitment, changeEncryptedMemo, relayer, circuitVersion)
|
|
1996
2027
|
*/
|
|
1997
2028
|
async unshield(params, signer, txOptions) {
|
|
1998
2029
|
const entry = resolveTx(this.substrate.unsafe, "ShieldedPool", "unshield");
|
|
@@ -2016,8 +2047,9 @@ var ShieldedPoolModule = class {
|
|
|
2016
2047
|
fee: params.fee ?? 0n,
|
|
2017
2048
|
change_commitment: changeCommitment,
|
|
2018
2049
|
change_encrypted_memo: changeEncryptedMemo,
|
|
2019
|
-
relayer: void 0
|
|
2050
|
+
relayer: void 0,
|
|
2020
2051
|
// Option<H160> — None for direct Substrate submissions
|
|
2052
|
+
circuit_version: params.circuitVersion
|
|
2021
2053
|
});
|
|
2022
2054
|
if (signer) {
|
|
2023
2055
|
return toTxResult(
|
|
@@ -2030,7 +2062,7 @@ var ShieldedPoolModule = class {
|
|
|
2030
2062
|
* Performs a private (shielded) transfer between two notes.
|
|
2031
2063
|
* Submits as an UNSIGNED (gasless) transaction — fee is embedded in the ZK proof.
|
|
2032
2064
|
* Pass a `signer` to fall back to signed submission (e.g. for testing).
|
|
2033
|
-
* Extrinsic: shieldedPool.privateTransfer(proof, merkleRoot, nullifiers, commitments, memos, assetId, fee)
|
|
2065
|
+
* Extrinsic: shieldedPool.privateTransfer(proof, merkleRoot, nullifiers, commitments, memos, assetId, fee, relayer, circuitVersion)
|
|
2034
2066
|
*/
|
|
2035
2067
|
async privateTransfer(params, signer, txOptions) {
|
|
2036
2068
|
const nullifiers = params.inputs.map((inp) => inp.nullifier);
|
|
@@ -2051,8 +2083,9 @@ var ShieldedPoolModule = class {
|
|
|
2051
2083
|
encrypted_memos: memos,
|
|
2052
2084
|
asset_id: params.assetId,
|
|
2053
2085
|
fee: params.fee ?? 0n,
|
|
2054
|
-
relayer: void 0
|
|
2086
|
+
relayer: void 0,
|
|
2055
2087
|
// Option<H160> — None for direct Substrate submissions
|
|
2088
|
+
circuit_version: params.circuitVersion
|
|
2056
2089
|
});
|
|
2057
2090
|
if (signer) {
|
|
2058
2091
|
return toTxResult(
|
|
@@ -2086,7 +2119,7 @@ var ShieldedPoolModule = class {
|
|
|
2086
2119
|
* This is a SIGNED transaction — the relayer must sign it with their wallet.
|
|
2087
2120
|
* Before calling this, generate a ZK value proof with generateFeeClaimProof() (not yet implemented).
|
|
2088
2121
|
*
|
|
2089
|
-
* Extrinsic: shieldedPool.claim_shielded_fees(commitment, amount, asset_id, memo, proof, public_signals)
|
|
2122
|
+
* Extrinsic: shieldedPool.claim_shielded_fees(commitment, amount, asset_id, memo, proof, public_signals, circuit_version)
|
|
2090
2123
|
*/
|
|
2091
2124
|
async claimShieldedFees(params, signer, txOptions) {
|
|
2092
2125
|
EncryptedMemo.validate(params.encryptedMemo, "claimShieldedFees.encryptedMemo");
|
|
@@ -2097,7 +2130,8 @@ var ShieldedPoolModule = class {
|
|
|
2097
2130
|
asset_id: params.assetId,
|
|
2098
2131
|
encrypted_memo: params.encryptedMemo,
|
|
2099
2132
|
proof: params.proof,
|
|
2100
|
-
public_signals: params.publicSignals
|
|
2133
|
+
public_signals: params.publicSignals,
|
|
2134
|
+
circuit_version: params.circuitVersion
|
|
2101
2135
|
});
|
|
2102
2136
|
return toTxResult(
|
|
2103
2137
|
await (txOptions !== void 0 ? tx.signAndSubmit(signer, txOptions) : tx.signAndSubmit(signer))
|
|
@@ -2615,6 +2649,74 @@ var ZkVerifierModule = class {
|
|
|
2615
2649
|
}
|
|
2616
2650
|
};
|
|
2617
2651
|
|
|
2652
|
+
// src/shielded-pool/CircuitVersionResolver.ts
|
|
2653
|
+
var import_proof_generator = require("@orbinum/proof-generator");
|
|
2654
|
+
var CircuitVersionResolver = class {
|
|
2655
|
+
constructor(zkVerifier, baseUrl, providerFactory) {
|
|
2656
|
+
this.zkVerifier = zkVerifier;
|
|
2657
|
+
this.makeProvider = providerFactory ?? ((circuit, noteVersion) => new import_proof_generator.WebArtifactProvider({
|
|
2658
|
+
...baseUrl ? { baseUrl } : {},
|
|
2659
|
+
circuitVersions: { [circuit]: noteVersion }
|
|
2660
|
+
}));
|
|
2661
|
+
}
|
|
2662
|
+
zkVerifier;
|
|
2663
|
+
makeProvider;
|
|
2664
|
+
/**
|
|
2665
|
+
* Resolves the prover + on-chain version for spending a note of `circuit`
|
|
2666
|
+
* created under `noteVersion`. Fail-closed: throws on unsupported version or
|
|
2667
|
+
* VK-hash mismatch (CDN vs chain), before generating any proof.
|
|
2668
|
+
*/
|
|
2669
|
+
async resolve(circuit, noteVersion) {
|
|
2670
|
+
if (!Number.isInteger(noteVersion) || noteVersion <= 0) {
|
|
2671
|
+
throw new Error(
|
|
2672
|
+
`CircuitVersionResolver: invalid note circuitVersion ${noteVersion} for ${circuit}`
|
|
2673
|
+
);
|
|
2674
|
+
}
|
|
2675
|
+
const provider = this.makeProvider(circuit, noteVersion);
|
|
2676
|
+
const resolved = await provider.getResolvedVersion(circuit);
|
|
2677
|
+
if (resolved.version !== noteVersion) {
|
|
2678
|
+
throw new Error(
|
|
2679
|
+
`CircuitVersionResolver: prover resolved ${circuit} to v${resolved.version}, expected v${noteVersion}`
|
|
2680
|
+
);
|
|
2681
|
+
}
|
|
2682
|
+
const circuitId = (0, import_proof_generator.circuitTypeToId)(circuit);
|
|
2683
|
+
const info = await this.zkVerifier.getCircuitVersionInfo(circuitId);
|
|
2684
|
+
if (!info) {
|
|
2685
|
+
throw new Error(
|
|
2686
|
+
`CircuitVersionResolver: chain reports no version info for ${circuit} (id ${circuitId})`
|
|
2687
|
+
);
|
|
2688
|
+
}
|
|
2689
|
+
if (!info.supportedVersions.includes(noteVersion)) {
|
|
2690
|
+
throw new Error(
|
|
2691
|
+
`CircuitVersionResolver: chain does not support ${circuit} v${noteVersion} (supported: ${info.supportedVersions.join(", ")})`
|
|
2692
|
+
);
|
|
2693
|
+
}
|
|
2694
|
+
const chainVk = info.vkHashes.find((h) => h.version === noteVersion);
|
|
2695
|
+
if (!chainVk) {
|
|
2696
|
+
throw new Error(
|
|
2697
|
+
`CircuitVersionResolver: chain has no VK hash for ${circuit} v${noteVersion}`
|
|
2698
|
+
);
|
|
2699
|
+
}
|
|
2700
|
+
if (!vkHashEquals(chainVk.vkHash, resolved.vkHash)) {
|
|
2701
|
+
throw new Error(
|
|
2702
|
+
`CircuitVersionResolver: VK hash mismatch for ${circuit} v${noteVersion} \u2014 prover ${resolved.vkHash}, chain ${chainVk.vkHash}`
|
|
2703
|
+
);
|
|
2704
|
+
}
|
|
2705
|
+
return { provider, version: noteVersion };
|
|
2706
|
+
}
|
|
2707
|
+
};
|
|
2708
|
+
function vkHashEquals(a, b) {
|
|
2709
|
+
const na = normalizeHash(a);
|
|
2710
|
+
const nb = normalizeHash(b);
|
|
2711
|
+
if (na === null || nb === null) return false;
|
|
2712
|
+
return na === nb;
|
|
2713
|
+
}
|
|
2714
|
+
function normalizeHash(h) {
|
|
2715
|
+
if (typeof h !== "string") return null;
|
|
2716
|
+
const s = h.toLowerCase().startsWith("0x") ? h.toLowerCase().slice(2) : h.toLowerCase();
|
|
2717
|
+
return /^[0-9a-f]{64}$/.test(s) ? s : null;
|
|
2718
|
+
}
|
|
2719
|
+
|
|
2618
2720
|
// src/relayer/RelayerStatusModule.ts
|
|
2619
2721
|
var RelayerStatusModule = class {
|
|
2620
2722
|
constructor(substrate) {
|
|
@@ -2860,12 +2962,12 @@ var AM_SEL = {
|
|
|
2860
2962
|
var SP_SEL = {
|
|
2861
2963
|
// shield(uint32,bytes32,bytes) → 0x9feb22ea (payable, amount = msg.value)
|
|
2862
2964
|
SHIELD: new Uint8Array([159, 235, 34, 234]),
|
|
2863
|
-
// privateTransfer(bytes,bytes32,bytes32[],bytes32[],bytes[],uint32,uint256)
|
|
2864
|
-
PRIVATE_TRANSFER: new Uint8Array([
|
|
2865
|
-
// unshield(bytes,bytes32,bytes32,uint32,uint256,bytes32,uint256,bytes32)
|
|
2866
|
-
UNSHIELD: new Uint8Array([
|
|
2867
|
-
// claimShieldedFees(bytes32,uint256,uint32,bytes,bytes,bytes)
|
|
2868
|
-
CLAIM_SHIELDED_FEES: new Uint8Array([
|
|
2965
|
+
// privateTransfer(bytes,bytes32,bytes32[],bytes32[],bytes[],uint32,uint256,uint32) → 0x66ed2cd4
|
|
2966
|
+
PRIVATE_TRANSFER: new Uint8Array([102, 237, 44, 212]),
|
|
2967
|
+
// unshield(bytes,bytes32,bytes32,uint32,uint256,bytes32,uint256,bytes32,bytes,uint32) → 0x4e505348
|
|
2968
|
+
UNSHIELD: new Uint8Array([78, 80, 83, 72]),
|
|
2969
|
+
// claimShieldedFees(bytes32,uint256,uint32,bytes,bytes,bytes,uint32) → 0x88d9deba
|
|
2970
|
+
CLAIM_SHIELDED_FEES: new Uint8Array([136, 217, 222, 186])
|
|
2869
2971
|
};
|
|
2870
2972
|
var KNOWN_PRECOMPILES = {
|
|
2871
2973
|
// ── Ethereum standard (EIP) ─────────────────────────────────────────────
|
|
@@ -2909,9 +3011,9 @@ var KNOWN_PRECOMPILES = {
|
|
|
2909
3011
|
name: "ShieldedPool",
|
|
2910
3012
|
functions: {
|
|
2911
3013
|
"9feb22ea": "shield(uint32,bytes32,bytes)",
|
|
2912
|
-
"
|
|
2913
|
-
|
|
2914
|
-
"
|
|
3014
|
+
"66ed2cd4": "privateTransfer(bytes,bytes32,bytes32[],bytes32[],bytes[],uint32,uint256,uint32)",
|
|
3015
|
+
"4e505348": "unshield(bytes,bytes32,bytes32,uint32,uint256,bytes32,uint256,bytes32,bytes,uint32)",
|
|
3016
|
+
"88d9deba": "claimShieldedFees(bytes32,uint256,uint32,bytes,bytes,bytes,uint32)"
|
|
2915
3017
|
}
|
|
2916
3018
|
}
|
|
2917
3019
|
};
|
|
@@ -2965,7 +3067,8 @@ var ShieldedPoolPrecompile = class {
|
|
|
2965
3067
|
// ─── privateTransfer ───────────────────────────────────────────────────────
|
|
2966
3068
|
/**
|
|
2967
3069
|
* Returns the ABI-encoded calldata for
|
|
2968
|
-
* `privateTransfer(bytes, bytes32, bytes32[], bytes32[], bytes[], uint32, uint256)`.
|
|
3070
|
+
* `privateTransfer(bytes, bytes32, bytes32[], bytes32[], bytes[], uint32, uint256, uint32)`.
|
|
3071
|
+
* The trailing `uint32` is the circuit version the input notes were created under.
|
|
2969
3072
|
*/
|
|
2970
3073
|
buildPrivateTransferCalldata(params) {
|
|
2971
3074
|
const nullifiers = params.inputs.map((i) => fromHex(i.nullifier));
|
|
@@ -2986,7 +3089,8 @@ var ShieldedPoolPrecompile = class {
|
|
|
2986
3089
|
{ type: "bytes32[]", value: commitments },
|
|
2987
3090
|
{ type: "bytes[]", value: memos },
|
|
2988
3091
|
{ type: "uint", value: BigInt(params.assetId) },
|
|
2989
|
-
{ type: "uint", value: params.fee ?? 0n }
|
|
3092
|
+
{ type: "uint", value: params.fee ?? 0n },
|
|
3093
|
+
{ type: "uint", value: BigInt(params.circuitVersion) }
|
|
2990
3094
|
);
|
|
2991
3095
|
}
|
|
2992
3096
|
/**
|
|
@@ -3027,7 +3131,8 @@ var ShieldedPoolPrecompile = class {
|
|
|
3027
3131
|
{ type: "bytes32", value: recipientBytes },
|
|
3028
3132
|
{ type: "uint", value: params.fee ?? 0n },
|
|
3029
3133
|
{ type: "bytes32", value: changeCommitment },
|
|
3030
|
-
{ type: "bytes", value: changeEncryptedMemo }
|
|
3134
|
+
{ type: "bytes", value: changeEncryptedMemo },
|
|
3135
|
+
{ type: "uint", value: BigInt(params.circuitVersion) }
|
|
3031
3136
|
);
|
|
3032
3137
|
}
|
|
3033
3138
|
/**
|
|
@@ -3077,7 +3182,7 @@ var ShieldedPoolPrecompile = class {
|
|
|
3077
3182
|
// ─── claimShieldedFees ───────────────────────────────────────────────────────────────────
|
|
3078
3183
|
/**
|
|
3079
3184
|
* Returns the ABI-encoded calldata for
|
|
3080
|
-
* `claimShieldedFees(bytes32,uint256,uint32,bytes,bytes,bytes)`.
|
|
3185
|
+
* `claimShieldedFees(bytes32,uint256,uint32,bytes,bytes,bytes,uint32)`.
|
|
3081
3186
|
*
|
|
3082
3187
|
* ABI layout (params after selector):
|
|
3083
3188
|
* - `commitment` — bytes32 (fixed)
|
|
@@ -3086,6 +3191,7 @@ var ShieldedPoolPrecompile = class {
|
|
|
3086
3191
|
* - `memo` — bytes (dynamic)
|
|
3087
3192
|
* - `proof` — bytes (dynamic, 128 bytes Groth16)
|
|
3088
3193
|
* - `publicSignals` — bytes (dynamic, 76 bytes)
|
|
3194
|
+
* - `circuitVersion` — uint32 (fixed, right-aligned)
|
|
3089
3195
|
*
|
|
3090
3196
|
* The validator identity is derived from `msg.sender` in the precompile —
|
|
3091
3197
|
* do NOT include it in the calldata.
|
|
@@ -3111,7 +3217,8 @@ var ShieldedPoolPrecompile = class {
|
|
|
3111
3217
|
{ type: "uint", value: BigInt(params.assetId) },
|
|
3112
3218
|
{ type: "bytes", value: params.encryptedMemo },
|
|
3113
3219
|
{ type: "bytes", value: params.proof },
|
|
3114
|
-
{ type: "bytes", value: params.publicSignals }
|
|
3220
|
+
{ type: "bytes", value: params.publicSignals },
|
|
3221
|
+
{ type: "uint", value: BigInt(params.circuitVersion) }
|
|
3115
3222
|
);
|
|
3116
3223
|
}
|
|
3117
3224
|
/**
|
|
@@ -3549,6 +3656,11 @@ var OrbinumClient = class _OrbinumClient {
|
|
|
3549
3656
|
chain;
|
|
3550
3657
|
/** Typed access to `zkVerifier_*` custom RPC endpoints. */
|
|
3551
3658
|
zkVerifier;
|
|
3659
|
+
/**
|
|
3660
|
+
* Resolves a note's circuit version to a pinned prover + on-chain version
|
|
3661
|
+
* before spending it (fail-closed: throws on unsupported version / VK mismatch).
|
|
3662
|
+
*/
|
|
3663
|
+
circuitVersionResolver;
|
|
3552
3664
|
/** Typed access to `relayer_*` RPC endpoints (registry lookup and pending fee queries). */
|
|
3553
3665
|
relayerStatus;
|
|
3554
3666
|
/**
|
|
@@ -3557,7 +3669,7 @@ var OrbinumClient = class _OrbinumClient {
|
|
|
3557
3669
|
*/
|
|
3558
3670
|
precompiles;
|
|
3559
3671
|
/** @internal Use `OrbinumClient.connect()` to obtain an instance. */
|
|
3560
|
-
constructor(substrate, evm, indexer) {
|
|
3672
|
+
constructor(substrate, evm, indexer, circuitsBaseUrl) {
|
|
3561
3673
|
this.substrate = substrate;
|
|
3562
3674
|
this.evm = evm;
|
|
3563
3675
|
this.evmExplorer = evm ? new EvmExplorer(evm) : null;
|
|
@@ -3567,6 +3679,7 @@ var OrbinumClient = class _OrbinumClient {
|
|
|
3567
3679
|
this.privacy = new PrivacyModule(substrate);
|
|
3568
3680
|
this.chain = new ChainModule(substrate);
|
|
3569
3681
|
this.zkVerifier = new ZkVerifierModule(substrate);
|
|
3682
|
+
this.circuitVersionResolver = new CircuitVersionResolver(this.zkVerifier, circuitsBaseUrl);
|
|
3570
3683
|
this.relayerStatus = new RelayerStatusModule(substrate);
|
|
3571
3684
|
this.precompiles = evm ? {
|
|
3572
3685
|
shieldedPool: new ShieldedPoolPrecompile(evm),
|
|
@@ -3587,7 +3700,7 @@ var OrbinumClient = class _OrbinumClient {
|
|
|
3587
3700
|
);
|
|
3588
3701
|
const evm = config.evmRpc ? new EvmClient(config.evmRpc) : null;
|
|
3589
3702
|
const indexer = config.indexerUrl ? new IndexerClient({ baseUrl: config.indexerUrl }) : null;
|
|
3590
|
-
return new _OrbinumClient(substrate, evm, indexer);
|
|
3703
|
+
return new _OrbinumClient(substrate, evm, indexer, config.circuitsBaseUrl);
|
|
3591
3704
|
}
|
|
3592
3705
|
/** Closes the underlying Substrate WebSocket connection and releases all resources. */
|
|
3593
3706
|
destroy() {
|
|
@@ -3709,6 +3822,8 @@ var OrbinumClientProvider = class {
|
|
|
3709
3822
|
};
|
|
3710
3823
|
if (this.config.evmRpc) connectConfig.evmRpc = this.config.evmRpc;
|
|
3711
3824
|
if (this.config.indexerUrl) connectConfig.indexerUrl = this.config.indexerUrl;
|
|
3825
|
+
if (this.config.circuitsBaseUrl)
|
|
3826
|
+
connectConfig.circuitsBaseUrl = this.config.circuitsBaseUrl;
|
|
3712
3827
|
const clientPromise = OrbinumClient.connect(connectConfig);
|
|
3713
3828
|
const client = await Promise.race([clientPromise, timeoutPromise]);
|
|
3714
3829
|
orphanClient = client;
|
|
@@ -3895,6 +4010,9 @@ var OrbinumClientProvider = class {
|
|
|
3895
4010
|
}
|
|
3896
4011
|
};
|
|
3897
4012
|
|
|
4013
|
+
// src/shielded-pool/protocol/types.ts
|
|
4014
|
+
var CURRENT_CIRCUIT_VERSION = 1;
|
|
4015
|
+
|
|
3898
4016
|
// src/utils/stealth.ts
|
|
3899
4017
|
var import_sha22 = require("@noble/hashes/sha2.js");
|
|
3900
4018
|
var import_hkdf = require("@noble/hashes/hkdf.js");
|
|
@@ -4003,6 +4121,7 @@ var NoteBuilder = class {
|
|
|
4003
4121
|
const blinding = input.blinding ?? BigInt(Date.now());
|
|
4004
4122
|
const spendingKey = input.spendingKey ?? 0n;
|
|
4005
4123
|
const counterpartyPk = input.counterpartyPk ?? 0n;
|
|
4124
|
+
const circuitVersion = input.circuitVersion ?? CURRENT_CIRCUIT_VERSION;
|
|
4006
4125
|
const useStealth = input.viewingPublicKey !== void 0 && input.recipientOwnerPk !== void 0;
|
|
4007
4126
|
let memo;
|
|
4008
4127
|
if (useStealth) {
|
|
@@ -4037,6 +4156,7 @@ var NoteBuilder = class {
|
|
|
4037
4156
|
stealthCommitmentBytes,
|
|
4038
4157
|
recipientIvkPacked,
|
|
4039
4158
|
bigintTo32Le(counterpartyPk),
|
|
4159
|
+
circuitVersion,
|
|
4040
4160
|
ephSk
|
|
4041
4161
|
)
|
|
4042
4162
|
);
|
|
@@ -4054,6 +4174,7 @@ var NoteBuilder = class {
|
|
|
4054
4174
|
ownerPk: effectiveOwnerPk,
|
|
4055
4175
|
blinding,
|
|
4056
4176
|
spendingKey,
|
|
4177
|
+
circuitVersion,
|
|
4057
4178
|
spent: false,
|
|
4058
4179
|
spentAt: null,
|
|
4059
4180
|
commitment: commitment2,
|
|
@@ -4076,7 +4197,8 @@ var NoteBuilder = class {
|
|
|
4076
4197
|
Number(assetId),
|
|
4077
4198
|
commitmentBytes,
|
|
4078
4199
|
input.viewingPublicKey,
|
|
4079
|
-
bigintTo32Le(counterpartyPk)
|
|
4200
|
+
bigintTo32Le(counterpartyPk),
|
|
4201
|
+
circuitVersion
|
|
4080
4202
|
)
|
|
4081
4203
|
) : Array.from(EncryptedMemo.dummy());
|
|
4082
4204
|
if (memo.length !== ENCRYPTED_MEMO_SIZE)
|
|
@@ -4089,6 +4211,7 @@ var NoteBuilder = class {
|
|
|
4089
4211
|
ownerPk,
|
|
4090
4212
|
blinding,
|
|
4091
4213
|
spendingKey,
|
|
4214
|
+
circuitVersion,
|
|
4092
4215
|
spent: false,
|
|
4093
4216
|
spentAt: null,
|
|
4094
4217
|
commitment,
|
|
@@ -4100,7 +4223,7 @@ var NoteBuilder = class {
|
|
|
4100
4223
|
};
|
|
4101
4224
|
}
|
|
4102
4225
|
/**
|
|
4103
|
-
* Build the
|
|
4226
|
+
* Build the 180-byte ECDH-encrypted memo for a note.
|
|
4104
4227
|
*
|
|
4105
4228
|
* Pure TypeScript implementation — no WASM dependency.
|
|
4106
4229
|
* Uses ChaCha20-Poly1305 with ECDH key agreement (BabyJubJub ephemeral keypair).
|
|
@@ -4119,7 +4242,8 @@ var NoteBuilder = class {
|
|
|
4119
4242
|
Number(note.assetId),
|
|
4120
4243
|
bigintTo32Le(note.commitment),
|
|
4121
4244
|
recipientIvkPacked ?? new Uint8Array(32),
|
|
4122
|
-
counterpartyPk ?? bigintTo32Le(note.counterpartyPk ?? 0n)
|
|
4245
|
+
counterpartyPk ?? bigintTo32Le(note.counterpartyPk ?? 0n),
|
|
4246
|
+
note.circuitVersion
|
|
4123
4247
|
);
|
|
4124
4248
|
}
|
|
4125
4249
|
};
|
|
@@ -4181,6 +4305,7 @@ function tryDecryptNoteVerbose(commitment, viewingSecretKey, spendingKey, ownOwn
|
|
|
4181
4305
|
ownerPk: effectiveOwnerPk,
|
|
4182
4306
|
blinding: plaintext.blinding,
|
|
4183
4307
|
spendingKey: effectiveSpendingKey,
|
|
4308
|
+
circuitVersion: plaintext.circuitVersion,
|
|
4184
4309
|
spent: false,
|
|
4185
4310
|
spentAt: null,
|
|
4186
4311
|
commitment: recomputed,
|
|
@@ -4254,7 +4379,7 @@ function selectNotes(notes, needed) {
|
|
|
4254
4379
|
for (let j = i + 1; j < sorted.length; j++) {
|
|
4255
4380
|
const a = sorted[i];
|
|
4256
4381
|
const b = sorted[j];
|
|
4257
|
-
if (a !== void 0 && b !== void 0 && a.value + b.value >= needed) {
|
|
4382
|
+
if (a !== void 0 && b !== void 0 && a.circuitVersion === b.circuitVersion && a.value + b.value >= needed) {
|
|
4258
4383
|
return [a, b];
|
|
4259
4384
|
}
|
|
4260
4385
|
}
|
|
@@ -4611,6 +4736,11 @@ async function encryptNote(key, blindKey, note) {
|
|
|
4611
4736
|
}
|
|
4612
4737
|
async function decryptNoteRecord(key, rec) {
|
|
4613
4738
|
const note = await decryptJson(key, rec.iv, rec.ciphertext);
|
|
4739
|
+
if (typeof note.circuitVersion !== "number") {
|
|
4740
|
+
throw new Error(
|
|
4741
|
+
"decryptNoteRecord: note is missing circuitVersion (invalid or corrupt record)"
|
|
4742
|
+
);
|
|
4743
|
+
}
|
|
4614
4744
|
return applyNoteStatus(note, {
|
|
4615
4745
|
...rec.spent !== void 0 && { spent: rec.spent },
|
|
4616
4746
|
spentAt: rec.spentAt ?? null
|
|
@@ -4621,7 +4751,7 @@ async function noteBlindTag(blindKey, hex) {
|
|
|
4621
4751
|
}
|
|
4622
4752
|
|
|
4623
4753
|
// src/proof-generator/unshield.ts
|
|
4624
|
-
var
|
|
4754
|
+
var import_proof_generator2 = require("@orbinum/proof-generator");
|
|
4625
4755
|
var import_utils3 = require("@noble/ciphers/utils.js");
|
|
4626
4756
|
var import_baby_jubjub6 = require("@zk-kit/baby-jubjub");
|
|
4627
4757
|
var import_poseidon_lite4 = require("poseidon-lite");
|
|
@@ -4667,15 +4797,15 @@ async function generateUnshieldProof(inputs, options = {}) {
|
|
|
4667
4797
|
change_blinding: changeBlinding.toString(),
|
|
4668
4798
|
change_owner_pubkey: changeOwnerPubkey.toString()
|
|
4669
4799
|
};
|
|
4670
|
-
const provider = options.provider ?? new
|
|
4800
|
+
const provider = options.provider ?? new import_proof_generator2.WebArtifactProvider();
|
|
4671
4801
|
const opts = { provider };
|
|
4672
4802
|
if (options.verbose !== void 0) opts.verbose = options.verbose;
|
|
4673
|
-
const proofResult = await (0,
|
|
4803
|
+
const proofResult = await (0, import_proof_generator2.generateProof)(import_proof_generator2.CircuitType.Unshield, circuitInputs, opts);
|
|
4674
4804
|
return { ...proofResult, changeCommitment, changeValue, changeBlinding, changeOwnerPubkey };
|
|
4675
4805
|
}
|
|
4676
4806
|
|
|
4677
4807
|
// src/proof-generator/transfer.ts
|
|
4678
|
-
var
|
|
4808
|
+
var import_proof_generator3 = require("@orbinum/proof-generator");
|
|
4679
4809
|
async function generateTransferProof(params, options = {}) {
|
|
4680
4810
|
const root = leHexToBigint(params.merkleRoot).toString();
|
|
4681
4811
|
const [i0, i1] = params.inputs;
|
|
@@ -4700,14 +4830,14 @@ async function generateTransferProof(params, options = {}) {
|
|
|
4700
4830
|
output_owner_pubkeys: [o0.ownerPk.toString(), o1.ownerPk.toString()],
|
|
4701
4831
|
output_blindings: [o0.blinding.toString(), o1.blinding.toString()]
|
|
4702
4832
|
};
|
|
4703
|
-
const provider = options.provider ?? new
|
|
4833
|
+
const provider = options.provider ?? new import_proof_generator3.WebArtifactProvider();
|
|
4704
4834
|
const opts = { provider };
|
|
4705
4835
|
if (options.verbose !== void 0) opts.verbose = options.verbose;
|
|
4706
|
-
return (0,
|
|
4836
|
+
return (0, import_proof_generator3.generateProof)(import_proof_generator3.CircuitType.Transfer, circuitInputs, opts);
|
|
4707
4837
|
}
|
|
4708
4838
|
|
|
4709
4839
|
// src/proof-generator/fee-claim.ts
|
|
4710
|
-
var
|
|
4840
|
+
var import_proof_generator4 = require("@orbinum/proof-generator");
|
|
4711
4841
|
async function generateFeeClaimProof(inputs, options = {}) {
|
|
4712
4842
|
if (inputs.amount <= 0n) {
|
|
4713
4843
|
throw new Error("Fee claim amount must be greater than zero.");
|
|
@@ -4719,10 +4849,10 @@ async function generateFeeClaimProof(inputs, options = {}) {
|
|
|
4719
4849
|
owner_pubkey: inputs.ownerPubkey.toString(),
|
|
4720
4850
|
blinding: inputs.blinding.toString()
|
|
4721
4851
|
};
|
|
4722
|
-
const provider = options.provider ?? new
|
|
4852
|
+
const provider = options.provider ?? new import_proof_generator4.WebArtifactProvider();
|
|
4723
4853
|
const opts = { provider };
|
|
4724
4854
|
if (options.verbose !== void 0) opts.verbose = options.verbose;
|
|
4725
|
-
const proofResult = await (0,
|
|
4855
|
+
const proofResult = await (0, import_proof_generator4.generateProof)(import_proof_generator4.CircuitType.ValueProof, circuitInputs, opts);
|
|
4726
4856
|
const [sigCommitment, sigValue, sigAssetId, sigOwnerHash] = proofResult.publicSignals.map(BigInt);
|
|
4727
4857
|
const buf = new Uint8Array(76);
|
|
4728
4858
|
buf.set(bigintTo32Le(sigCommitment), 0);
|
|
@@ -4778,9 +4908,19 @@ function decodePrecompileCalldata(address, input) {
|
|
|
4778
4908
|
const recipient = toHex(data.slice(160, 192));
|
|
4779
4909
|
const fee = decodeUint(data, 192);
|
|
4780
4910
|
const changeCommitment = toHex(data.slice(224, 256));
|
|
4911
|
+
const circuitVersion = decodeUint(data, 288);
|
|
4781
4912
|
return {
|
|
4782
4913
|
fnSig,
|
|
4783
|
-
args: {
|
|
4914
|
+
args: {
|
|
4915
|
+
root,
|
|
4916
|
+
nullifier,
|
|
4917
|
+
assetId,
|
|
4918
|
+
amount,
|
|
4919
|
+
recipient,
|
|
4920
|
+
fee,
|
|
4921
|
+
changeCommitment,
|
|
4922
|
+
circuitVersion
|
|
4923
|
+
}
|
|
4784
4924
|
};
|
|
4785
4925
|
} catch {
|
|
4786
4926
|
return { fnSig, args: {} };
|
|
@@ -4796,7 +4936,8 @@ function decodePrecompileCalldata(address, input) {
|
|
|
4796
4936
|
const commitments = Number(decodeUint(data, commOffset));
|
|
4797
4937
|
const assetId = decodeUint(data, 160);
|
|
4798
4938
|
const fee = decodeUint(data, 192);
|
|
4799
|
-
|
|
4939
|
+
const circuitVersion = decodeUint(data, 224);
|
|
4940
|
+
return { fnSig, args: { root, nullifiers, commitments, assetId, fee, circuitVersion } };
|
|
4800
4941
|
} catch {
|
|
4801
4942
|
return { fnSig, args: {} };
|
|
4802
4943
|
}
|
|
@@ -4807,7 +4948,8 @@ function decodePrecompileCalldata(address, input) {
|
|
|
4807
4948
|
const commitment = toHex(data.slice(0, 32));
|
|
4808
4949
|
const amount = decodeUint(data, 32);
|
|
4809
4950
|
const assetId = decodeUint(data, 64);
|
|
4810
|
-
|
|
4951
|
+
const circuitVersion = decodeUint(data, 192);
|
|
4952
|
+
return { fnSig, args: { commitment, amount, assetId, circuitVersion } };
|
|
4811
4953
|
} catch {
|
|
4812
4954
|
return { fnSig, args: {} };
|
|
4813
4955
|
}
|
|
@@ -4819,8 +4961,8 @@ function decodePrecompileCalldata(address, input) {
|
|
|
4819
4961
|
var CircuitId = {
|
|
4820
4962
|
Transfer: 1,
|
|
4821
4963
|
Unshield: 2,
|
|
4822
|
-
|
|
4823
|
-
|
|
4964
|
+
PrivateLink: 5,
|
|
4965
|
+
ValueProof: 6
|
|
4824
4966
|
};
|
|
4825
4967
|
|
|
4826
4968
|
// src/utils/string.ts
|
|
@@ -5492,8 +5634,10 @@ var import_polkadot_api4 = require("polkadot-api");
|
|
|
5492
5634
|
BABYJUB_SUBORDER,
|
|
5493
5635
|
BN254_R,
|
|
5494
5636
|
Blake2256,
|
|
5637
|
+
CURRENT_CIRCUIT_VERSION,
|
|
5495
5638
|
CircuitId,
|
|
5496
5639
|
CircuitType,
|
|
5640
|
+
CircuitVersionResolver,
|
|
5497
5641
|
CryptoPrecompiles,
|
|
5498
5642
|
ENCRYPTED_MEMO_SIZE,
|
|
5499
5643
|
EncryptedMemo,
|