@taquito/sapling 24.3.0-rc.2 → 24.3.0-rc.3

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.
@@ -1,12 +1,17 @@
1
1
  ## Sapling Parameter Provenance
2
2
 
3
- The `saplingOutputParams.js` file in this package and the `saplingSpendParams.js` file in the sibling `@taquito/sapling-spend-params` package are vendored copies of the Sapling proving parameters distributed by the Zcash project.
3
+ Taquito now treats the Sapling proving parameters as immutable release artifacts served from the first-party host at `https://sapling.taquito.io`, not as vendored package payloads.
4
4
 
5
- Source:
5
+ Original source:
6
6
  - `https://download.z.cash/downloads/sapling-spend.params`
7
7
  - `https://download.z.cash/downloads/sapling-output.params`
8
8
 
9
- Verification data:
9
+ Hosted release paths:
10
+ - `https://sapling.taquito.io/params/groth16-mainnet-1/spend.params`
11
+ - `https://sapling.taquito.io/params/groth16-mainnet-1/output.params`
12
+ - `https://sapling.taquito.io/manifests/groth16-mainnet-1.json`
13
+
14
+ Pinned verification data:
10
15
  - `sapling-spend.params`
11
16
  - Size: `47,958,396` bytes
12
17
  - SHA-256: `8e48ffd23abb3a5fd9c5589204f32d9c31285a04b78096ba40a79b75677efc13`
@@ -14,11 +19,12 @@ Verification data:
14
19
  - Size: `3,592,860` bytes
15
20
  - SHA-256: `2f0ebbcbb9bb0bcffe95a397e7eba89c29eb4dde6191c339db88570e3f3fb0e4`
16
21
 
17
- Why these files are vendored:
18
- - `@taquito/sapling` previously fetched them during `postinstall`, which made installs network-dependent.
19
- - Vendoring keeps published packages self-contained and makes builds reproducible.
20
- - These parameters are treated as fixed trusted setup artifacts, not routine updatable assets.
22
+ Release source of truth:
23
+ - the pinned manifest lives in `src/sapling-params-manifest.json`
24
+ - `src/sapling-params-loader.ts` imports that manifest for the default runtime URLs and digests
25
+ - `prepare-sapling-release-artifacts.js` emits the exact upload set for the current parameter version
21
26
 
22
- Maintainer note:
23
- - `fetch-sapling-params.js` is retained only as a repo-maintenance helper to regenerate the vendored wrapper files from the exact raw parameter files above.
24
- - Any regeneration should be exceptional, manually reviewed, and accompanied by explicit provenance updates in this file.
27
+ Operational note:
28
+ - upload only immutable, versioned objects
29
+ - verify the public bytes against the pinned hashes after upload
30
+ - the Cloudflare rollout and verification steps are documented in `docs/infra/sapling-cloudflare-r2-rollout.md`
@@ -1,11 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SaplingWrapper = void 0;
4
- const buffer_1 = require("buffer");
5
4
  const sapling = require("./sapling-wasm");
6
- const sapling_output_params_1 = require("./sapling-output-params");
7
- const sapling_spend_params_1 = require("@taquito/sapling-spend-params");
8
- let cachedParams;
5
+ const sapling_params_loader_1 = require("./sapling-params-loader");
9
6
  const getRandomValueSource = () => {
10
7
  const crypto = globalThis.crypto;
11
8
  if (!crypto?.getRandomValues) {
@@ -15,7 +12,7 @@ const getRandomValueSource = () => {
15
12
  };
16
13
  class SaplingWrapper {
17
14
  async withProvingContext(action) {
18
- await this.initSaplingParameters();
15
+ await (0, sapling_params_loader_1.preloadSaplingParams)();
19
16
  return sapling.withProvingContext(action);
20
17
  }
21
18
  getRandomBytes(length) {
@@ -53,13 +50,7 @@ class SaplingWrapper {
53
50
  return sapling.createBindingSignature(saplingContext, balance, transactionSigHash);
54
51
  }
55
52
  async initSaplingParameters() {
56
- if (!cachedParams) {
57
- cachedParams = {
58
- spend: buffer_1.Buffer.from(sapling_spend_params_1.default.saplingSpendParams, 'base64'),
59
- output: buffer_1.Buffer.from(sapling_output_params_1.default.saplingOutputParams, 'base64'),
60
- };
61
- }
62
- return sapling.initParameters(cachedParams.spend, cachedParams.output);
53
+ return (0, sapling_params_loader_1.preloadSaplingParams)();
63
54
  }
64
55
  }
65
56
  exports.SaplingWrapper = SaplingWrapper;
@@ -0,0 +1,180 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SaplingParamsError = void 0;
4
+ exports.initSapling = initSapling;
5
+ exports.preloadSaplingParams = preloadSaplingParams;
6
+ const buffer_1 = require("buffer");
7
+ const sapling = require("./sapling-wasm");
8
+ const sapling_params_manifest_json_1 = require("./sapling-params-manifest.json");
9
+ const DEFAULT_SAPLING_PARAMS_MANIFEST = sapling_params_manifest_json_1.default;
10
+ class SaplingParamsError extends Error {
11
+ constructor(code, message, source, cause) {
12
+ super(message);
13
+ this.code = code;
14
+ this.source = source;
15
+ this.name = 'SaplingParamsError';
16
+ this.cause = cause;
17
+ }
18
+ }
19
+ exports.SaplingParamsError = SaplingParamsError;
20
+ let configuredSaplingParamsSource;
21
+ let frozenSaplingParamsSource;
22
+ let loadedSaplingParams;
23
+ let saplingParamsLoadPromise;
24
+ let saplingParamsInitPromise;
25
+ async function initSapling(options = {}) {
26
+ const nextSource = resolveSaplingParamsSource(options.params);
27
+ if (frozenSaplingParamsSource || saplingParamsLoadPromise || saplingParamsInitPromise) {
28
+ return;
29
+ }
30
+ configuredSaplingParamsSource = nextSource;
31
+ }
32
+ async function preloadSaplingParams() {
33
+ if (!saplingParamsInitPromise) {
34
+ saplingParamsInitPromise = initializeSaplingParams().catch((error) => {
35
+ saplingParamsInitPromise = undefined;
36
+ throw error;
37
+ });
38
+ }
39
+ return saplingParamsInitPromise;
40
+ }
41
+ async function initializeSaplingParams() {
42
+ const { spend, output } = await loadSaplingParams();
43
+ await sapling.initParameters(spend, output);
44
+ }
45
+ async function loadSaplingParams() {
46
+ if (loadedSaplingParams) {
47
+ return loadedSaplingParams;
48
+ }
49
+ if (!saplingParamsLoadPromise) {
50
+ const source = frozenSaplingParamsSource ?? configuredSaplingParamsSource ?? resolveSaplingParamsSource();
51
+ saplingParamsLoadPromise = loadSaplingParamsFromSource(source)
52
+ .then((params) => {
53
+ frozenSaplingParamsSource = source;
54
+ loadedSaplingParams = params;
55
+ return params;
56
+ })
57
+ .catch((error) => {
58
+ saplingParamsLoadPromise = undefined;
59
+ throw error;
60
+ });
61
+ }
62
+ return saplingParamsLoadPromise;
63
+ }
64
+ async function loadSaplingParamsFromSource(source) {
65
+ if (source.kind === 'local') {
66
+ const [spend, output] = await Promise.all([
67
+ loadLocalParam(source.spend.path, source.spend.sha256, 'spend', source.source),
68
+ loadLocalParam(source.output.path, source.output.sha256, 'output', source.source),
69
+ ]);
70
+ return { spend, output };
71
+ }
72
+ const [spend, output] = await Promise.all([
73
+ loadRemoteParam(source.spend.url, source.spend.sha256, 'spend', source.source),
74
+ loadRemoteParam(source.output.url, source.output.sha256, 'output', source.source),
75
+ ]);
76
+ return { spend, output };
77
+ }
78
+ async function loadRemoteParam(url, expectedSha256, label, source) {
79
+ let response;
80
+ try {
81
+ response = await fetch(url);
82
+ }
83
+ catch (error) {
84
+ throw new SaplingParamsError('SAPLING_PARAMS_FETCH_FAILED', `Failed to fetch Sapling ${label} params from ${url}`, source, error);
85
+ }
86
+ if (!response.ok) {
87
+ throw new SaplingParamsError('SAPLING_PARAMS_FETCH_FAILED', `Failed to fetch Sapling ${label} params from ${url}: ${response.status}`, source);
88
+ }
89
+ const bytes = buffer_1.Buffer.from(await response.arrayBuffer());
90
+ await assertSha256(bytes, expectedSha256, label, source, url);
91
+ return bytes;
92
+ }
93
+ async function loadLocalParam(path, expectedSha256, label, source) {
94
+ if (!isNodeLikeRuntime()) {
95
+ throw new SaplingParamsError('SAPLING_PARAMS_UNSUPPORTED_RUNTIME', `Sapling local ${label} params are only supported in Node.js and CI environments`, source);
96
+ }
97
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
98
+ const { readFile } = require(getNodeFsPromisesModuleId());
99
+ const bytes = buffer_1.Buffer.from(await readFile(path));
100
+ if (expectedSha256) {
101
+ await assertSha256(bytes, expectedSha256, label, source, path);
102
+ }
103
+ return bytes;
104
+ }
105
+ async function assertSha256(bytes, expectedSha256, label, source, location) {
106
+ const subtle = globalThis.crypto?.subtle;
107
+ if (!subtle) {
108
+ throw new SaplingParamsError('SAPLING_PARAMS_UNSUPPORTED_RUNTIME', `Sapling ${label} params verification requires globalThis.crypto.subtle`, source);
109
+ }
110
+ const digest = await subtle.digest('SHA-256', Uint8Array.from(bytes));
111
+ const actualSha256 = buffer_1.Buffer.from(digest).toString('hex');
112
+ if (actualSha256 !== expectedSha256) {
113
+ throw new SaplingParamsError('SAPLING_PARAMS_HASH_MISMATCH', `Sapling ${label} params from ${source} failed integrity verification for ${location} (expected SHA-256 ${expectedSha256}, got ${actualSha256})`, source);
114
+ }
115
+ }
116
+ function resolveSaplingParamsSource(params = undefined) {
117
+ if (!params || typeof params.source !== 'undefined') {
118
+ const source = params?.source ?? 'taquito';
119
+ return {
120
+ kind: 'remote',
121
+ source,
122
+ spend: {
123
+ url: source === 'zcash'
124
+ ? DEFAULT_SAPLING_PARAMS_MANIFEST.spendParams.zcashUrl
125
+ : DEFAULT_SAPLING_PARAMS_MANIFEST.spendParams.taquitoUrl,
126
+ sha256: DEFAULT_SAPLING_PARAMS_MANIFEST.spendParams.sha256,
127
+ },
128
+ output: {
129
+ url: source === 'zcash'
130
+ ? DEFAULT_SAPLING_PARAMS_MANIFEST.outputParams.zcashUrl
131
+ : DEFAULT_SAPLING_PARAMS_MANIFEST.outputParams.taquitoUrl,
132
+ sha256: DEFAULT_SAPLING_PARAMS_MANIFEST.outputParams.sha256,
133
+ },
134
+ };
135
+ }
136
+ if ('spendParamsPath' in params || 'outputParamsPath' in params) {
137
+ if (!params.spendParamsPath || !params.outputParamsPath) {
138
+ throw new SaplingParamsError('SAPLING_PARAMS_INVALID_CONFIG', 'Sapling local params configuration requires both spendParamsPath and outputParamsPath', 'local');
139
+ }
140
+ return {
141
+ kind: 'local',
142
+ source: 'local',
143
+ spend: {
144
+ path: params.spendParamsPath,
145
+ sha256: params.spendParamsSha256,
146
+ },
147
+ output: {
148
+ path: params.outputParamsPath,
149
+ sha256: params.outputParamsSha256,
150
+ },
151
+ };
152
+ }
153
+ if (!params.spendParamsUrl || !params.outputParamsUrl) {
154
+ throw new SaplingParamsError('SAPLING_PARAMS_INVALID_CONFIG', 'Sapling remote params configuration requires both spendParamsUrl and outputParamsUrl', 'custom');
155
+ }
156
+ if (!params.spendParamsSha256 || !params.outputParamsSha256) {
157
+ throw new SaplingParamsError('SAPLING_PARAMS_INVALID_CONFIG', 'Sapling remote params configuration requires explicit SHA-256 digests', 'custom');
158
+ }
159
+ return {
160
+ kind: 'remote',
161
+ source: 'custom',
162
+ spend: {
163
+ url: params.spendParamsUrl,
164
+ sha256: params.spendParamsSha256,
165
+ },
166
+ output: {
167
+ url: params.outputParamsUrl,
168
+ sha256: params.outputParamsSha256,
169
+ },
170
+ };
171
+ }
172
+ function isNodeLikeRuntime() {
173
+ const runtimeProcess = globalThis.process;
174
+ return !!runtimeProcess?.versions?.node;
175
+ }
176
+ function getNodeFsPromisesModuleId() {
177
+ // Keep this module id opaque enough that browser bundlers do not eagerly
178
+ // try to resolve a Node-only dependency into the browser build.
179
+ return ['node', 'fs', 'promises'].join(':').replace('fs:promises', 'fs/promises');
180
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "saplingParamsVersion": "groth16-mainnet-1",
3
+ "spendParams": {
4
+ "sha256": "8e48ffd23abb3a5fd9c5589204f32d9c31285a04b78096ba40a79b75677efc13",
5
+ "bytes": 47958396,
6
+ "taquitoUrl": "https://sapling.taquito.io/params/groth16-mainnet-1/spend.params",
7
+ "zcashUrl": "https://download.z.cash/downloads/sapling-spend.params"
8
+ },
9
+ "outputParams": {
10
+ "sha256": "2f0ebbcbb9bb0bcffe95a397e7eba89c29eb4dde6191c339db88570e3f3fb0e4",
11
+ "bytes": 3592860,
12
+ "taquitoUrl": "https://sapling.taquito.io/params/groth16-mainnet-1/output.params",
13
+ "zcashUrl": "https://download.z.cash/downloads/sapling-output.params"
14
+ }
15
+ }
@@ -16,7 +16,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
16
16
  };
17
17
  var _SaplingToolkit_inMemorySpendingKey, _SaplingToolkit_saplingId, _SaplingToolkit_contractAddress, _SaplingToolkit_memoSize, _SaplingToolkit_readProvider, _SaplingToolkit_packer, _SaplingToolkit_saplingForger, _SaplingToolkit_saplingTxBuilder, _SaplingToolkit_saplingTransactionViewer;
18
18
  Object.defineProperty(exports, "__esModule", { value: true });
19
- exports.SaplingToolkit = exports.InMemoryProvingKey = exports.InMemorySpendingKey = exports.InMemoryViewingKey = exports.SaplingTransactionViewer = void 0;
19
+ exports.SaplingToolkit = exports.InMemoryProvingKey = exports.InMemorySpendingKey = exports.InMemoryViewingKey = exports.SaplingTransactionViewer = exports.SaplingParamsError = exports.preloadSaplingParams = exports.initSapling = void 0;
20
20
  const buffer_1 = require("buffer");
21
21
  const bignumber_js_1 = require("bignumber.js");
22
22
  const BigNumber = bignumber_js_1.default;
@@ -29,6 +29,10 @@ const sapling_transaction_viewer_1 = require("./sapling-tx-viewer/sapling-transa
29
29
  const sapling_transactions_builder_1 = require("./sapling-tx-builder/sapling-transactions-builder");
30
30
  const constants_1 = require("./constants");
31
31
  const core_1 = require("@taquito/core");
32
+ var sapling_params_loader_1 = require("./sapling-params-loader");
33
+ Object.defineProperty(exports, "initSapling", { enumerable: true, get: function () { return sapling_params_loader_1.initSapling; } });
34
+ Object.defineProperty(exports, "preloadSaplingParams", { enumerable: true, get: function () { return sapling_params_loader_1.preloadSaplingParams; } });
35
+ Object.defineProperty(exports, "SaplingParamsError", { enumerable: true, get: function () { return sapling_params_loader_1.SaplingParamsError; } });
32
36
  var sapling_transaction_viewer_2 = require("./sapling-tx-viewer/sapling-transaction-viewer");
33
37
  Object.defineProperty(exports, "SaplingTransactionViewer", { enumerable: true, get: function () { return sapling_transaction_viewer_2.SaplingTransactionViewer; } });
34
38
  var in_memory_viewing_key_1 = require("./sapling-keys/in-memory-viewing-key");
@@ -3,6 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VERSION = void 0;
4
4
  // IMPORTANT: THIS FILE IS AUTO GENERATED! DO NOT MANUALLY EDIT!
5
5
  exports.VERSION = {
6
- "commitHash": "7e99d97864147bbcc2291f12aac10e368afd9055",
7
- "version": "24.3.0-rc.2"
6
+ "commitHash": "17a8431576e7c428f69f4bcb79687903a9d354ea",
7
+ "version": "24.3.0-rc.3"
8
8
  };
@@ -2,11 +2,9 @@ import BigNumberJs from 'bignumber.js';
2
2
  import { MichelCodecPacker } from '@taquito/taquito';
3
3
  import { b58Encode, PrefixV2, bytesToString, toHexBuf, stringToBytes, hex2buf, mergebuf, hex2Bytes, num2PaddedHex, b58DecodeAndCheckPrefix, format, b58DecodePublicKeyHash, validateKeyHash, ValidationResult } from '@taquito/utils';
4
4
  import { ParameterValidationError, TaquitoError, InvalidKeyHashError, InvalidAddressError } from '@taquito/core';
5
- import { keyAgreement, getRawPaymentAddressFromIncomingViewingKey, verifyCommitment, computeNullifier, merkleHash, withProvingContext, randR, getOutgoingViewingKey, preparePartialOutputDescription, getDiversifiedFromRawPaymentAddress, deriveEphemeralPublicKey, getPkdFromRawPaymentAddress, createBindingSignature, initParameters, getExtendedFullViewingKeyFromSpendingKey, getIncomingViewingKey, getPaymentAddressFromViewingKey, getExtendedSpendingKey, prepareSpendDescriptionWithSpendingKey, signSpendDescription, getProofAuthorizingKey, prepareSpendDescriptionWithAuthorizingKey } from '@taquito/sapling-wasm';
5
+ import { keyAgreement, getRawPaymentAddressFromIncomingViewingKey, verifyCommitment, computeNullifier, merkleHash, initParameters, withProvingContext, randR, getOutgoingViewingKey, preparePartialOutputDescription, getDiversifiedFromRawPaymentAddress, deriveEphemeralPublicKey, getPkdFromRawPaymentAddress, createBindingSignature, getExtendedFullViewingKeyFromSpendingKey, getIncomingViewingKey, getPaymentAddressFromViewingKey, getExtendedSpendingKey, prepareSpendDescriptionWithSpendingKey, signSpendDescription, getProofAuthorizingKey, prepareSpendDescriptionWithAuthorizingKey } from '@taquito/sapling-wasm';
6
6
  import blake from 'blakejs';
7
7
  import { openSecretBox, secretBox } from '@stablelib/nacl';
8
- import '../saplingOutputParams.js';
9
- import saplingSpendParams from '@taquito/sapling-spend-params';
10
8
  import toBuffer from 'typedarray-to-buffer';
11
9
 
12
10
  /******************************************************************************
@@ -2969,17 +2967,193 @@ class SaplingState {
2969
2967
  }
2970
2968
  }
2971
2969
 
2972
- const loadSaplingOutputParams = () => {
2973
- const saplingOutputParams = globalThis.__taquitoVendoredParams
2974
- ?.saplingOutputParams;
2975
- if (!saplingOutputParams) {
2976
- throw new Error('Vendored sapling output params failed to load');
2977
- }
2978
- return saplingOutputParams;
2970
+ var spendParams = {
2971
+ sha256: "8e48ffd23abb3a5fd9c5589204f32d9c31285a04b78096ba40a79b75677efc13",
2972
+ taquitoUrl: "https://sapling.taquito.io/params/groth16-mainnet-1/spend.params",
2973
+ zcashUrl: "https://download.z.cash/downloads/sapling-spend.params"
2974
+ };
2975
+ var outputParams = {
2976
+ sha256: "2f0ebbcbb9bb0bcffe95a397e7eba89c29eb4dde6191c339db88570e3f3fb0e4",
2977
+ taquitoUrl: "https://sapling.taquito.io/params/groth16-mainnet-1/output.params",
2978
+ zcashUrl: "https://download.z.cash/downloads/sapling-output.params"
2979
+ };
2980
+ var saplingParamsManifest = {
2981
+ spendParams: spendParams,
2982
+ outputParams: outputParams
2979
2983
  };
2980
- var saplingOutputParams = loadSaplingOutputParams();
2981
2984
 
2982
- let cachedParams;
2985
+ const DEFAULT_SAPLING_PARAMS_MANIFEST = saplingParamsManifest;
2986
+ class SaplingParamsError extends Error {
2987
+ constructor(code, message, source, cause) {
2988
+ super(message);
2989
+ this.code = code;
2990
+ this.source = source;
2991
+ this.name = 'SaplingParamsError';
2992
+ this.cause = cause;
2993
+ }
2994
+ }
2995
+ let configuredSaplingParamsSource;
2996
+ let frozenSaplingParamsSource;
2997
+ let loadedSaplingParams;
2998
+ let saplingParamsLoadPromise;
2999
+ let saplingParamsInitPromise;
3000
+ async function initSapling(options = {}) {
3001
+ const nextSource = resolveSaplingParamsSource(options.params);
3002
+ if (frozenSaplingParamsSource || saplingParamsLoadPromise || saplingParamsInitPromise) {
3003
+ return;
3004
+ }
3005
+ configuredSaplingParamsSource = nextSource;
3006
+ }
3007
+ async function preloadSaplingParams() {
3008
+ if (!saplingParamsInitPromise) {
3009
+ saplingParamsInitPromise = initializeSaplingParams().catch((error) => {
3010
+ saplingParamsInitPromise = undefined;
3011
+ throw error;
3012
+ });
3013
+ }
3014
+ return saplingParamsInitPromise;
3015
+ }
3016
+ async function initializeSaplingParams() {
3017
+ const { spend, output } = await loadSaplingParams();
3018
+ await initParameters(spend, output);
3019
+ }
3020
+ async function loadSaplingParams() {
3021
+ if (loadedSaplingParams) {
3022
+ return loadedSaplingParams;
3023
+ }
3024
+ if (!saplingParamsLoadPromise) {
3025
+ const source = frozenSaplingParamsSource ?? configuredSaplingParamsSource ?? resolveSaplingParamsSource();
3026
+ saplingParamsLoadPromise = loadSaplingParamsFromSource(source)
3027
+ .then((params) => {
3028
+ frozenSaplingParamsSource = source;
3029
+ loadedSaplingParams = params;
3030
+ return params;
3031
+ })
3032
+ .catch((error) => {
3033
+ saplingParamsLoadPromise = undefined;
3034
+ throw error;
3035
+ });
3036
+ }
3037
+ return saplingParamsLoadPromise;
3038
+ }
3039
+ async function loadSaplingParamsFromSource(source) {
3040
+ if (source.kind === 'local') {
3041
+ const [spend, output] = await Promise.all([
3042
+ loadLocalParam(source.spend.path, source.spend.sha256, 'spend', source.source),
3043
+ loadLocalParam(source.output.path, source.output.sha256, 'output', source.source),
3044
+ ]);
3045
+ return { spend, output };
3046
+ }
3047
+ const [spend, output] = await Promise.all([
3048
+ loadRemoteParam(source.spend.url, source.spend.sha256, 'spend', source.source),
3049
+ loadRemoteParam(source.output.url, source.output.sha256, 'output', source.source),
3050
+ ]);
3051
+ return { spend, output };
3052
+ }
3053
+ async function loadRemoteParam(url, expectedSha256, label, source) {
3054
+ let response;
3055
+ try {
3056
+ response = await fetch(url);
3057
+ }
3058
+ catch (error) {
3059
+ throw new SaplingParamsError('SAPLING_PARAMS_FETCH_FAILED', `Failed to fetch Sapling ${label} params from ${url}`, source, error);
3060
+ }
3061
+ if (!response.ok) {
3062
+ throw new SaplingParamsError('SAPLING_PARAMS_FETCH_FAILED', `Failed to fetch Sapling ${label} params from ${url}: ${response.status}`, source);
3063
+ }
3064
+ const bytes = bufferExports.Buffer.from(await response.arrayBuffer());
3065
+ await assertSha256(bytes, expectedSha256, label, source, url);
3066
+ return bytes;
3067
+ }
3068
+ async function loadLocalParam(path, expectedSha256, label, source) {
3069
+ if (!isNodeLikeRuntime()) {
3070
+ throw new SaplingParamsError('SAPLING_PARAMS_UNSUPPORTED_RUNTIME', `Sapling local ${label} params are only supported in Node.js and CI environments`, source);
3071
+ }
3072
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
3073
+ const { readFile } = require(getNodeFsPromisesModuleId());
3074
+ const bytes = bufferExports.Buffer.from(await readFile(path));
3075
+ if (expectedSha256) {
3076
+ await assertSha256(bytes, expectedSha256, label, source, path);
3077
+ }
3078
+ return bytes;
3079
+ }
3080
+ async function assertSha256(bytes, expectedSha256, label, source, location) {
3081
+ const subtle = globalThis.crypto?.subtle;
3082
+ if (!subtle) {
3083
+ throw new SaplingParamsError('SAPLING_PARAMS_UNSUPPORTED_RUNTIME', `Sapling ${label} params verification requires globalThis.crypto.subtle`, source);
3084
+ }
3085
+ const digest = await subtle.digest('SHA-256', Uint8Array.from(bytes));
3086
+ const actualSha256 = bufferExports.Buffer.from(digest).toString('hex');
3087
+ if (actualSha256 !== expectedSha256) {
3088
+ throw new SaplingParamsError('SAPLING_PARAMS_HASH_MISMATCH', `Sapling ${label} params from ${source} failed integrity verification for ${location} (expected SHA-256 ${expectedSha256}, got ${actualSha256})`, source);
3089
+ }
3090
+ }
3091
+ function resolveSaplingParamsSource(params = undefined) {
3092
+ if (!params || typeof params.source !== 'undefined') {
3093
+ const source = params?.source ?? 'taquito';
3094
+ return {
3095
+ kind: 'remote',
3096
+ source,
3097
+ spend: {
3098
+ url: source === 'zcash'
3099
+ ? DEFAULT_SAPLING_PARAMS_MANIFEST.spendParams.zcashUrl
3100
+ : DEFAULT_SAPLING_PARAMS_MANIFEST.spendParams.taquitoUrl,
3101
+ sha256: DEFAULT_SAPLING_PARAMS_MANIFEST.spendParams.sha256,
3102
+ },
3103
+ output: {
3104
+ url: source === 'zcash'
3105
+ ? DEFAULT_SAPLING_PARAMS_MANIFEST.outputParams.zcashUrl
3106
+ : DEFAULT_SAPLING_PARAMS_MANIFEST.outputParams.taquitoUrl,
3107
+ sha256: DEFAULT_SAPLING_PARAMS_MANIFEST.outputParams.sha256,
3108
+ },
3109
+ };
3110
+ }
3111
+ if ('spendParamsPath' in params || 'outputParamsPath' in params) {
3112
+ if (!params.spendParamsPath || !params.outputParamsPath) {
3113
+ throw new SaplingParamsError('SAPLING_PARAMS_INVALID_CONFIG', 'Sapling local params configuration requires both spendParamsPath and outputParamsPath', 'local');
3114
+ }
3115
+ return {
3116
+ kind: 'local',
3117
+ source: 'local',
3118
+ spend: {
3119
+ path: params.spendParamsPath,
3120
+ sha256: params.spendParamsSha256,
3121
+ },
3122
+ output: {
3123
+ path: params.outputParamsPath,
3124
+ sha256: params.outputParamsSha256,
3125
+ },
3126
+ };
3127
+ }
3128
+ if (!params.spendParamsUrl || !params.outputParamsUrl) {
3129
+ throw new SaplingParamsError('SAPLING_PARAMS_INVALID_CONFIG', 'Sapling remote params configuration requires both spendParamsUrl and outputParamsUrl', 'custom');
3130
+ }
3131
+ if (!params.spendParamsSha256 || !params.outputParamsSha256) {
3132
+ throw new SaplingParamsError('SAPLING_PARAMS_INVALID_CONFIG', 'Sapling remote params configuration requires explicit SHA-256 digests', 'custom');
3133
+ }
3134
+ return {
3135
+ kind: 'remote',
3136
+ source: 'custom',
3137
+ spend: {
3138
+ url: params.spendParamsUrl,
3139
+ sha256: params.spendParamsSha256,
3140
+ },
3141
+ output: {
3142
+ url: params.outputParamsUrl,
3143
+ sha256: params.outputParamsSha256,
3144
+ },
3145
+ };
3146
+ }
3147
+ function isNodeLikeRuntime() {
3148
+ const runtimeProcess = globalThis.process;
3149
+ return !!runtimeProcess?.versions?.node;
3150
+ }
3151
+ function getNodeFsPromisesModuleId() {
3152
+ // Keep this module id opaque enough that browser bundlers do not eagerly
3153
+ // try to resolve a Node-only dependency into the browser build.
3154
+ return ['node', 'fs', 'promises'].join(':').replace('fs:promises', 'fs/promises');
3155
+ }
3156
+
2983
3157
  const getRandomValueSource = () => {
2984
3158
  const crypto = globalThis.crypto;
2985
3159
  if (!crypto?.getRandomValues) {
@@ -2989,7 +3163,7 @@ const getRandomValueSource = () => {
2989
3163
  };
2990
3164
  class SaplingWrapper {
2991
3165
  async withProvingContext(action) {
2992
- await this.initSaplingParameters();
3166
+ await preloadSaplingParams();
2993
3167
  return withProvingContext(action);
2994
3168
  }
2995
3169
  getRandomBytes(length) {
@@ -3027,13 +3201,7 @@ class SaplingWrapper {
3027
3201
  return createBindingSignature(saplingContext, balance, transactionSigHash);
3028
3202
  }
3029
3203
  async initSaplingParameters() {
3030
- if (!cachedParams) {
3031
- cachedParams = {
3032
- spend: bufferExports.Buffer.from(saplingSpendParams.saplingSpendParams, 'base64'),
3033
- output: bufferExports.Buffer.from(saplingOutputParams.saplingOutputParams, 'base64'),
3034
- };
3035
- }
3036
- return initParameters(cachedParams.spend, cachedParams.output);
3204
+ return preloadSaplingParams();
3037
3205
  }
3038
3206
  }
3039
3207
 
@@ -4422,5 +4590,5 @@ class SaplingToolkit {
4422
4590
  }
4423
4591
  _SaplingToolkit_inMemorySpendingKey = new WeakMap(), _SaplingToolkit_saplingId = new WeakMap(), _SaplingToolkit_contractAddress = new WeakMap(), _SaplingToolkit_memoSize = new WeakMap(), _SaplingToolkit_readProvider = new WeakMap(), _SaplingToolkit_packer = new WeakMap(), _SaplingToolkit_saplingForger = new WeakMap(), _SaplingToolkit_saplingTxBuilder = new WeakMap(), _SaplingToolkit_saplingTransactionViewer = new WeakMap();
4424
4592
 
4425
- export { InMemoryProvingKey, InMemorySpendingKey, InMemoryViewingKey, SaplingToolkit, SaplingTransactionViewer };
4593
+ export { InMemoryProvingKey, InMemorySpendingKey, InMemoryViewingKey, SaplingParamsError, SaplingToolkit, SaplingTransactionViewer, initSapling, preloadSaplingParams };
4426
4594
  //# sourceMappingURL=taquito-sapling.es6.js.map