@umbra-privacy/sdk 1.0.0 → 2.0.1
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/README.md +104 -25
- package/dist/{addresses-Brzgurv_.d.ts → addresses-B7HybtbJ.d.ts} +2 -1
- package/dist/{addresses-D_0YAS6B.d.cts → addresses-CTVY1oi7.d.cts} +2 -1
- package/dist/arcium-BXXlryfe.d.cts +20 -0
- package/dist/arcium-BXXlryfe.d.ts +20 -0
- package/dist/chunk-3LS5P32X.cjs +10892 -0
- package/dist/chunk-3LS5P32X.cjs.map +1 -0
- package/dist/chunk-4RHXVBNI.js +203 -0
- package/dist/chunk-4RHXVBNI.js.map +1 -0
- package/dist/chunk-4TZVXB5G.js +324 -0
- package/dist/chunk-4TZVXB5G.js.map +1 -0
- package/dist/chunk-5GUSMQ74.cjs +549 -0
- package/dist/chunk-5GUSMQ74.cjs.map +1 -0
- package/dist/chunk-5KPQXPQM.js +36 -0
- package/dist/chunk-5KPQXPQM.js.map +1 -0
- package/dist/chunk-AXD7LXYY.cjs +405 -0
- package/dist/chunk-AXD7LXYY.cjs.map +1 -0
- package/dist/{chunk-HOEXDXRC.cjs → chunk-BL6WXLPV.cjs} +32 -360
- package/dist/chunk-BL6WXLPV.cjs.map +1 -0
- package/dist/chunk-CFFLOE7D.cjs +598 -0
- package/dist/chunk-CFFLOE7D.cjs.map +1 -0
- package/dist/{chunk-BM7N6N7E.js → chunk-CFTW5WNG.js} +3 -325
- package/dist/chunk-CFTW5WNG.js.map +1 -0
- package/dist/chunk-DD2WCK4C.js +327 -0
- package/dist/chunk-DD2WCK4C.js.map +1 -0
- package/dist/chunk-DMPMQ74B.cjs +246 -0
- package/dist/chunk-DMPMQ74B.cjs.map +1 -0
- package/dist/{chunk-2Q75CQQJ.js → chunk-EEKF4553.js} +2 -2
- package/dist/chunk-EEKF4553.js.map +1 -0
- package/dist/chunk-ENVYYEM4.cjs +113 -0
- package/dist/chunk-ENVYYEM4.cjs.map +1 -0
- package/dist/chunk-FQX6ZYGJ.js +500 -0
- package/dist/chunk-FQX6ZYGJ.js.map +1 -0
- package/dist/chunk-FSK2ICMB.cjs +39 -0
- package/dist/chunk-FSK2ICMB.cjs.map +1 -0
- package/dist/chunk-FZYWLQAF.cjs +355 -0
- package/dist/chunk-FZYWLQAF.cjs.map +1 -0
- package/dist/chunk-GP26R377.js +436 -0
- package/dist/chunk-GP26R377.js.map +1 -0
- package/dist/chunk-HA5FLM63.js +393 -0
- package/dist/chunk-HA5FLM63.js.map +1 -0
- package/dist/chunk-INJ73LXQ.js +1107 -0
- package/dist/chunk-INJ73LXQ.js.map +1 -0
- package/dist/chunk-KMRROOME.js +10750 -0
- package/dist/chunk-KMRROOME.js.map +1 -0
- package/dist/{chunk-MDFSBU5W.cjs → chunk-LTCKPTZC.cjs} +2 -351
- package/dist/chunk-LTCKPTZC.cjs.map +1 -0
- package/dist/chunk-MKNCBUFA.js +564 -0
- package/dist/chunk-MKNCBUFA.js.map +1 -0
- package/dist/chunk-NKVMSABR.cjs +207 -0
- package/dist/chunk-NKVMSABR.cjs.map +1 -0
- package/dist/chunk-OFDWNWCL.js +70 -0
- package/dist/chunk-OFDWNWCL.js.map +1 -0
- package/dist/chunk-QJAUUYZU.cjs +331 -0
- package/dist/chunk-QJAUUYZU.cjs.map +1 -0
- package/dist/chunk-TLR7A64G.js +103 -0
- package/dist/chunk-TLR7A64G.js.map +1 -0
- package/dist/{chunk-MVKTV3FT.cjs → chunk-TQQZGNOI.cjs} +2 -2
- package/dist/chunk-TQQZGNOI.cjs.map +1 -0
- package/dist/chunk-UOFYS6M3.js +219 -0
- package/dist/chunk-UOFYS6M3.js.map +1 -0
- package/dist/chunk-UXMQI6B7.js +2406 -0
- package/dist/chunk-UXMQI6B7.js.map +1 -0
- package/dist/chunk-WN75ORDT.js +571 -0
- package/dist/chunk-WN75ORDT.js.map +1 -0
- package/dist/chunk-Y55PYKXH.cjs +595 -0
- package/dist/chunk-Y55PYKXH.cjs.map +1 -0
- package/dist/chunk-YEZBTYCP.cjs +77 -0
- package/dist/chunk-YEZBTYCP.cjs.map +1 -0
- package/dist/chunk-ZQOIYCGA.cjs +1126 -0
- package/dist/chunk-ZQOIYCGA.cjs.map +1 -0
- package/dist/chunk-ZY3TSHMJ.cjs +2665 -0
- package/dist/chunk-ZY3TSHMJ.cjs.map +1 -0
- package/dist/client-DkVBHMWb.d.cts +2613 -0
- package/dist/client-V4AF6Bz9.d.ts +2613 -0
- package/dist/common/pda/index.cjs +145 -0
- package/dist/common/pda/index.cjs.map +1 -0
- package/dist/common/pda/index.d.cts +1250 -0
- package/dist/common/pda/index.d.ts +1250 -0
- package/dist/common/pda/index.js +8 -0
- package/dist/common/pda/index.js.map +1 -0
- package/dist/constants/index.cjs +38 -164
- package/dist/constants/index.cjs.map +1 -1
- package/dist/constants/index.d.cts +8 -425
- package/dist/constants/index.d.ts +8 -425
- package/dist/constants/index.js +15 -124
- package/dist/constants/index.js.map +1 -1
- package/dist/crypto/index.cjs +583 -0
- package/dist/crypto/index.cjs.map +1 -0
- package/dist/crypto/index.d.cts +6731 -0
- package/dist/crypto/index.d.ts +6731 -0
- package/dist/crypto/index.js +14 -0
- package/dist/crypto/index.js.map +1 -0
- package/dist/{cryptography-BTGC72u-.d.ts → cryptography-BFSJcvi6.d.ts} +3 -2465
- package/dist/{cryptography-BTGC72u-.d.cts → cryptography-D6tPDh-Y.d.cts} +3 -2465
- package/dist/errors/index.cjs +64 -54
- package/dist/errors/index.d.cts +7 -797
- package/dist/errors/index.d.ts +7 -797
- package/dist/errors/index.js +3 -1
- package/dist/errors-B9EoPeWV.d.cts +593 -0
- package/dist/errors-B9EoPeWV.d.ts +593 -0
- package/dist/errors-DAIrstEL.d.cts +300 -0
- package/dist/errors-DPNMfyh0.d.ts +300 -0
- package/dist/index-BG0yjL7C.d.cts +6006 -0
- package/dist/index-ByynoyBO.d.ts +6006 -0
- package/dist/index.cjs +5133 -16116
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1031 -7685
- package/dist/index.d.ts +1031 -7685
- package/dist/index.js +3228 -14905
- package/dist/index.js.map +1 -1
- package/dist/interfaces/index.d.cts +14 -6
- package/dist/interfaces/index.d.ts +14 -6
- package/dist/interfaces-43cReBcS.d.cts +3346 -0
- package/dist/interfaces-B8xKNl_6.d.ts +997 -0
- package/dist/interfaces-D2NO6kDD.d.cts +997 -0
- package/dist/interfaces-z_xYJlgV.d.ts +3346 -0
- package/dist/math/index.cjs +115 -0
- package/dist/math/index.cjs.map +1 -0
- package/dist/math/index.d.cts +1327 -0
- package/dist/math/index.d.ts +1327 -0
- package/dist/math/index.js +10 -0
- package/dist/math/index.js.map +1 -0
- package/dist/networks-RMd3abPE.d.ts +44 -0
- package/dist/networks-yAoO8peQ.d.cts +44 -0
- package/dist/relayer-NRRMSMNB.js +4 -0
- package/dist/relayer-NRRMSMNB.js.map +1 -0
- package/dist/relayer-RJHEIXJG.cjs +21 -0
- package/dist/relayer-RJHEIXJG.cjs.map +1 -0
- package/dist/solana/index.cjs +56 -0
- package/dist/solana/index.cjs.map +1 -0
- package/dist/solana/index.d.cts +105 -0
- package/dist/solana/index.d.ts +105 -0
- package/dist/solana/index.js +7 -0
- package/dist/solana/index.js.map +1 -0
- package/dist/{index-CLj_zWSD.d.ts → temporal-BbRaEPoO.d.ts} +1 -1
- package/dist/{index-CX6_pIRS.d.cts → temporal-oUj7iCaq.d.cts} +1 -1
- package/dist/transaction-forwarder-5mAMTjw6.d.ts +1155 -0
- package/dist/transaction-forwarder-C6gMUG7a.d.cts +1155 -0
- package/dist/types/index.cjs +232 -231
- package/dist/types/index.d.cts +15 -1485
- package/dist/types/index.d.ts +15 -1485
- package/dist/types/index.js +2 -1
- package/dist/types-BohhvPth.d.cts +87 -0
- package/dist/types-CW0oTT0j.d.ts +87 -0
- package/dist/types-C_V_CaKK.d.cts +2468 -0
- package/dist/types-C_V_CaKK.d.ts +2468 -0
- package/dist/types-Ca7frykr.d.ts +793 -0
- package/dist/types-CuKeoI19.d.cts +1296 -0
- package/dist/types-CxfTIpN9.d.ts +1052 -0
- package/dist/{types-n-sHFcgr.d.ts → types-D1jDUjfN.d.ts} +2 -2
- package/dist/types-DKEDUlH9.d.ts +1296 -0
- package/dist/types-EKuIfxTz.d.cts +1052 -0
- package/dist/{types-BBuELtY8.d.cts → types-IMGYmlv-.d.cts} +2 -2
- package/dist/types-PwNLi_2k.d.cts +793 -0
- package/dist/utils/index.cjs +823 -525
- package/dist/utils/index.d.cts +1711 -4021
- package/dist/utils/index.d.ts +1711 -4021
- package/dist/utils/index.js +9 -3
- package/dist/{versions-D9PqsEvj.d.cts → versions-BRlR36EA.d.cts} +1 -0
- package/dist/{versions-D9PqsEvj.d.ts → versions-BRlR36EA.d.ts} +1 -0
- package/package.json +79 -18
- package/dist/chunk-2Q75CQQJ.js.map +0 -1
- package/dist/chunk-BM7N6N7E.js.map +0 -1
- package/dist/chunk-GXKSUB2U.cjs +0 -4416
- package/dist/chunk-GXKSUB2U.cjs.map +0 -1
- package/dist/chunk-HOEXDXRC.cjs.map +0 -1
- package/dist/chunk-MDFSBU5W.cjs.map +0 -1
- package/dist/chunk-MQY7HDIA.js +0 -600
- package/dist/chunk-MQY7HDIA.js.map +0 -1
- package/dist/chunk-MVKTV3FT.cjs.map +0 -1
- package/dist/chunk-PG2J6V6Y.js +0 -4094
- package/dist/chunk-PG2J6V6Y.js.map +0 -1
- package/dist/chunk-VEGLTTYQ.cjs +0 -621
- package/dist/chunk-VEGLTTYQ.cjs.map +0 -1
- package/dist/chunk-WVHQ46DD.js +0 -758
- package/dist/chunk-WVHQ46DD.js.map +0 -1
- package/dist/index-B9pDY73x.d.ts +0 -12933
- package/dist/index-D33yo0qB.d.cts +0 -12933
- package/dist/networks-C-orpSFW.d.ts +0 -65
- package/dist/networks-FxYERGD1.d.cts +0 -65
|
@@ -0,0 +1,793 @@
|
|
|
1
|
+
import { S as SubSubBrandedType, U as U128, a as SubSubSubBrandedType } from './types-C_V_CaKK.cjs';
|
|
2
|
+
import { B as Bn254FieldElement } from './types-BohhvPth.cjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Poseidon Cipher Types
|
|
6
|
+
*
|
|
7
|
+
* This module defines branded primitive types for all values that flow through
|
|
8
|
+
* Poseidon-based cryptographic operations in the Umbra SDK. Every type is a
|
|
9
|
+
* {@link SubSubSubBrandedType} — a four-level phantom brand layered on top of
|
|
10
|
+
* {@link Bn254FieldElement} — giving the TypeScript compiler enough information
|
|
11
|
+
* to reject accidental substitutions (e.g. passing a `PoseidonKey` where a
|
|
12
|
+
* `PoseidonCounter` is expected) while incurring zero runtime overhead.
|
|
13
|
+
*
|
|
14
|
+
* ## Why Poseidon?
|
|
15
|
+
*
|
|
16
|
+
* Poseidon is an algebraic hash function designed specifically for ZK-SNARK and
|
|
17
|
+
* ZK-STARK circuits. Unlike SHA-256, which operates on bits and requires thousands
|
|
18
|
+
* of R1CS constraints per invocation, Poseidon operates natively over prime fields
|
|
19
|
+
* using low-degree polynomial substitution boxes (x^5 over BN254's F_r). This
|
|
20
|
+
* reduces constraint count by 50-100x, making it practical to prove hashes inside
|
|
21
|
+
* Groth16 or PLONK circuits.
|
|
22
|
+
*
|
|
23
|
+
* In Umbra, Poseidon is used for:
|
|
24
|
+
* - UTXO commitment computation — binding amount, nullifier, and user commitment
|
|
25
|
+
* into a single on-chain leaf via `H2 = Poseidon(...)`.
|
|
26
|
+
* - Fiat-Shamir challenge derivation — squeezing a deterministic challenge from
|
|
27
|
+
* the transcript of public inputs to a ZK proof.
|
|
28
|
+
* - User commitment generation — binding a master viewing key (MVK) and a Poseidon
|
|
29
|
+
* key to an on-chain commitment that the circuit can verify.
|
|
30
|
+
* - Keystream generation — acting as a PRF to produce per-counter keystream values
|
|
31
|
+
* for stream-cipher encryption of confidential token account balances.
|
|
32
|
+
*
|
|
33
|
+
* All types in this module are valid BN254 scalar field elements:
|
|
34
|
+
* `0 ≤ value < BN254_FIELD_PRIME`.
|
|
35
|
+
*
|
|
36
|
+
* @see {@link https://eprint.iacr.org/2019/458} Poseidon: A New Hash Function for Zero-Knowledge Proof Systems
|
|
37
|
+
* @see {@link Bn254FieldElement} for the underlying field element type
|
|
38
|
+
* @see {@link BN254_FIELD_PRIME} for the field prime constant
|
|
39
|
+
*
|
|
40
|
+
* @packageDocumentation
|
|
41
|
+
* @module crypto/poseidon/types
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* A plaintext field element that is an input to the Poseidon cipher or hash.
|
|
46
|
+
*
|
|
47
|
+
* `PoseidonPlaintext` wraps a {@link Bn254FieldElement} with an additional
|
|
48
|
+
* phantom brand to signal that the value has been validated as a suitable input
|
|
49
|
+
* for a Poseidon operation — i.e. it is a non-negative integer strictly less than
|
|
50
|
+
* the BN254 field prime.
|
|
51
|
+
*
|
|
52
|
+
* @remarks
|
|
53
|
+
* Poseidon operates natively over the BN254 scalar field F_r. Every input to a
|
|
54
|
+
* Poseidon hash or cipher invocation must therefore be a valid field element. This
|
|
55
|
+
* type makes that constraint explicit and compiler-enforced: you cannot pass an
|
|
56
|
+
* arbitrary `bigint` directly without first calling {@link assertPoseidonPlaintext}.
|
|
57
|
+
*
|
|
58
|
+
* In Umbra, plaintext values include:
|
|
59
|
+
* - Token amounts before encryption into confidential token accounts.
|
|
60
|
+
* - Blinding factors before they are committed.
|
|
61
|
+
* - UTXO data fields before being hashed into a commitment leaf.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```typescript
|
|
65
|
+
* import { assertPoseidonPlaintext, type PoseidonPlaintext } from "@umbra/sdk";
|
|
66
|
+
*
|
|
67
|
+
* const amount = 1_000_000n; // 1 USDC in micro-units
|
|
68
|
+
* assertPoseidonPlaintext(amount);
|
|
69
|
+
* // amount: PoseidonPlaintext — safe to pass to the Poseidon cipher
|
|
70
|
+
*
|
|
71
|
+
* const encryptor = getPoseidonEncryptor();
|
|
72
|
+
* const ciphertexts = await encryptor([amount], transactionViewingKey);
|
|
73
|
+
* ```
|
|
74
|
+
*
|
|
75
|
+
* @see {@link assertPoseidonPlaintext} for the corresponding assertion function
|
|
76
|
+
* @see {@link PoseidonEncryptorFunction} for the function that consumes this type
|
|
77
|
+
* @public
|
|
78
|
+
*/
|
|
79
|
+
type PoseidonPlaintext = SubSubSubBrandedType<Bn254FieldElement, "PoseidonPlaintext">;
|
|
80
|
+
/**
|
|
81
|
+
* A hash output produced by the Poseidon hash function.
|
|
82
|
+
*
|
|
83
|
+
* `PoseidonHash` is the branded return type of a Poseidon invocation. It wraps
|
|
84
|
+
* the raw {@link Bn254FieldElement} output to distinguish a computed hash from an
|
|
85
|
+
* arbitrary field element at the type level.
|
|
86
|
+
*
|
|
87
|
+
* @remarks
|
|
88
|
+
* The Poseidon hash function maps N field elements (1 ≤ N ≤ 12 for this
|
|
89
|
+
* implementation) to a single field element. The output is:
|
|
90
|
+
* - Always a valid BN254 field element (in [0, BN254_FIELD_PRIME)).
|
|
91
|
+
* - Deterministic: identical inputs always produce identical output.
|
|
92
|
+
* - Collision-resistant under the algebraic hash security assumptions.
|
|
93
|
+
* - Pseudo-random: the output is computationally indistinguishable from a
|
|
94
|
+
* uniformly random field element when at least one input is unknown.
|
|
95
|
+
*
|
|
96
|
+
* In Umbra, `PoseidonHash` values appear as:
|
|
97
|
+
* - UTXO commitment leaves in the indexed Merkle tree (IMT).
|
|
98
|
+
* - Aggregated public inputs fed to the on-chain Groth16 verifier.
|
|
99
|
+
* - User commitments binding a master viewing key to a Poseidon key.
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```typescript
|
|
103
|
+
* import { assertPoseidonHash, type PoseidonHash } from "@umbra/sdk";
|
|
104
|
+
*
|
|
105
|
+
* // assertPoseidonHash is useful when receiving a bigint from an external
|
|
106
|
+
* // source (e.g. deserialized from JSON) that is claimed to be a hash.
|
|
107
|
+
* const rawHash = 12345678901234567890n;
|
|
108
|
+
* assertPoseidonHash(rawHash);
|
|
109
|
+
* // rawHash: PoseidonHash
|
|
110
|
+
* ```
|
|
111
|
+
*
|
|
112
|
+
* @see {@link assertPoseidonHash} for the corresponding assertion function
|
|
113
|
+
* @see {@link PoseidonAggregatorHashFunction} for the function that returns this type
|
|
114
|
+
* @public
|
|
115
|
+
*/
|
|
116
|
+
type PoseidonHash = SubSubSubBrandedType<Bn254FieldElement, "PoseidonHash">;
|
|
117
|
+
/**
|
|
118
|
+
* The user's Poseidon private key — a secret field element derived from the master seed.
|
|
119
|
+
*
|
|
120
|
+
* `PoseidonKey` is NOT a parameter of the Poseidon hash function itself. Rather, it is
|
|
121
|
+
* a user-level cryptographic secret that is:
|
|
122
|
+
* 1. Derived deterministically from the user's master seed via a key-derivation path.
|
|
123
|
+
* 2. Used as a secret input to UTXO commitments, binding the commitment to this specific
|
|
124
|
+
* user without revealing any information about the key to an observer.
|
|
125
|
+
* 3. Used as the master key for Poseidon-based stream cipher operations on confidential
|
|
126
|
+
* token account balances (see {@link PoseidonEncryptorFunction}).
|
|
127
|
+
*
|
|
128
|
+
* @remarks
|
|
129
|
+
* ## Cryptographic Role
|
|
130
|
+
*
|
|
131
|
+
* In Umbra's UTXO scheme, the on-chain commitment to a note is computed as:
|
|
132
|
+
* ```
|
|
133
|
+
* userCommitment = Poseidon([masterViewingKey, poseidonKey])
|
|
134
|
+
* H2 = Poseidon([amount, nullifier, userCommitment, ...])
|
|
135
|
+
* ```
|
|
136
|
+
*
|
|
137
|
+
* The `poseidonKey` is the `PoseidonKey` value. Because it appears inside
|
|
138
|
+
* `userCommitment`, knowledge of the `PoseidonKey` is required to claim a UTXO
|
|
139
|
+
* directed at this user.
|
|
140
|
+
*
|
|
141
|
+
* ## Security Requirements
|
|
142
|
+
*
|
|
143
|
+
* - Must be generated using a cryptographically secure random source (CSPRNG).
|
|
144
|
+
* - Must be kept secret — exposure allows an attacker to claim all UTXOs directed
|
|
145
|
+
* at the user that are encrypted with this key.
|
|
146
|
+
* - Must be in the BN254 field: `0 ≤ poseidonKey < BN254_FIELD_PRIME`.
|
|
147
|
+
* - Should be rotated if compromise is suspected.
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* ```typescript
|
|
151
|
+
* import { assertPoseidonKey, type PoseidonKey } from "@umbra/sdk";
|
|
152
|
+
*
|
|
153
|
+
* // Derived from master seed in practice — never hardcode secrets.
|
|
154
|
+
* const derivedKey = deriveKeyFromMasterSeed(masterSeed, "poseidon-key");
|
|
155
|
+
* assertPoseidonKey(derivedKey);
|
|
156
|
+
* // derivedKey: PoseidonKey — safe to use in encryption operations
|
|
157
|
+
*
|
|
158
|
+
* const encryptor = getPoseidonEncryptor();
|
|
159
|
+
* const ciphertexts = await encryptor([amount], derivedKey);
|
|
160
|
+
* ```
|
|
161
|
+
*
|
|
162
|
+
* @see {@link assertPoseidonKey} for the corresponding assertion function
|
|
163
|
+
* @see {@link PoseidonEncryptorFunction} for encryption using this key
|
|
164
|
+
* @see {@link PoseidonKeystreamGeneratorFunction} for keystream generation
|
|
165
|
+
* @public
|
|
166
|
+
*/
|
|
167
|
+
type PoseidonKey = SubSubSubBrandedType<Bn254FieldElement, "PoseidonKey">;
|
|
168
|
+
/**
|
|
169
|
+
* A ciphertext field element produced by Poseidon sponge encryption.
|
|
170
|
+
*
|
|
171
|
+
* `PoseidonCiphertext` is the branded output of encrypting a {@link PoseidonPlaintext}
|
|
172
|
+
* with a {@link PoseidonKey}. It is structurally a BN254 field element but is
|
|
173
|
+
* semantically distinct — it represents encrypted data, not raw plaintext.
|
|
174
|
+
*
|
|
175
|
+
* @remarks
|
|
176
|
+
* ## Encryption Scheme
|
|
177
|
+
*
|
|
178
|
+
* Umbra's Poseidon cipher uses a counter-mode (CTR) construction over the BN254
|
|
179
|
+
* field. For each plaintext at position `i`, the encryption is:
|
|
180
|
+
* ```
|
|
181
|
+
* ciphertext[i] = (plaintext[i] + keystream[i]) mod BN254_FIELD_PRIME
|
|
182
|
+
* ```
|
|
183
|
+
*
|
|
184
|
+
* where `keystream[i] = Poseidon([transactionViewingKey, counter_i, 2n])`.
|
|
185
|
+
*
|
|
186
|
+
* This construction is additively homomorphic within the field: knowing the
|
|
187
|
+
* keystream allows recovery of the plaintext by subtraction modulo the field prime.
|
|
188
|
+
*
|
|
189
|
+
* ## Security Properties
|
|
190
|
+
*
|
|
191
|
+
* Under the PRF security of Poseidon, ciphertext values are computationally
|
|
192
|
+
* indistinguishable from uniformly random field elements. This provides semantic
|
|
193
|
+
* security (IND-CPA) as long as counter values are not reused with the same key.
|
|
194
|
+
*
|
|
195
|
+
* ## Stored On-Chain
|
|
196
|
+
*
|
|
197
|
+
* Ciphertexts are stored in confidential token accounts on Solana. The MXE
|
|
198
|
+
* (Multi-party eXecution Environment) decrypts them using the network's shared key
|
|
199
|
+
* during MPC computation; the account owner decrypts using their `PoseidonKey`.
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* ```typescript
|
|
203
|
+
* import { assertPoseidonCiphertext, type PoseidonCiphertext } from "@umbra/sdk";
|
|
204
|
+
*
|
|
205
|
+
* // Received from on-chain state — assert before using
|
|
206
|
+
* const rawOnChainCiphertext = 99887766554433221100n;
|
|
207
|
+
* assertPoseidonCiphertext(rawOnChainCiphertext);
|
|
208
|
+
* // rawOnChainCiphertext: PoseidonCiphertext
|
|
209
|
+
*
|
|
210
|
+
* const decryptor = getPoseidonDecryptor();
|
|
211
|
+
* const [plaintext] = await decryptor([rawOnChainCiphertext], myPoseidonKey);
|
|
212
|
+
* ```
|
|
213
|
+
*
|
|
214
|
+
* @see {@link assertPoseidonCiphertext} for the corresponding assertion function
|
|
215
|
+
* @see {@link PoseidonEncryptorFunction} for how ciphertexts are produced
|
|
216
|
+
* @see {@link PoseidonDecryptorFunction} for how ciphertexts are recovered
|
|
217
|
+
* @public
|
|
218
|
+
*/
|
|
219
|
+
type PoseidonCiphertext = SubSubSubBrandedType<Bn254FieldElement, "PoseidonCiphertext">;
|
|
220
|
+
/**
|
|
221
|
+
* A counter value (nonce) used to index positions in Poseidon counter-mode encryption.
|
|
222
|
+
*
|
|
223
|
+
* `PoseidonCounter` plays the same role as a nonce in AES-CTR mode, but operates
|
|
224
|
+
* over the BN254 scalar field. Each unique counter value, combined with the same
|
|
225
|
+
* {@link PoseidonKey}, produces a distinct keystream element via the Poseidon PRF.
|
|
226
|
+
*
|
|
227
|
+
* @remarks
|
|
228
|
+
* ## Counter-Mode Construction
|
|
229
|
+
*
|
|
230
|
+
* For a given key `k` and counter `c`, the keystream is:
|
|
231
|
+
* ```
|
|
232
|
+
* keystream(k, c) = Poseidon([k, c, 2n])
|
|
233
|
+
* ```
|
|
234
|
+
*
|
|
235
|
+
* The constant `2n` is a domain separation tag that binds the Poseidon invocation
|
|
236
|
+
* specifically to keystream generation, preventing cross-protocol misuse.
|
|
237
|
+
*
|
|
238
|
+
* ## Security Requirements
|
|
239
|
+
*
|
|
240
|
+
* - **Uniqueness**: Counter values MUST be unique for each distinct plaintext encrypted
|
|
241
|
+
* under the same key. Reusing a `(key, counter)` pair for different plaintexts reveals
|
|
242
|
+
* the XOR of those plaintexts (field difference, mod p).
|
|
243
|
+
* - **Range**: Must satisfy `0 ≤ counter < BN254_FIELD_PRIME`.
|
|
244
|
+
* - **Sequential use**: Counters are typically allocated sequentially starting at `0n`,
|
|
245
|
+
* incrementing by 1 for each plaintext position.
|
|
246
|
+
*
|
|
247
|
+
* @example
|
|
248
|
+
* ```typescript
|
|
249
|
+
* import {
|
|
250
|
+
* assertPoseidonCounter,
|
|
251
|
+
* type PoseidonCounter,
|
|
252
|
+
* BN254_FIELD_PRIME,
|
|
253
|
+
* } from "@umbra/sdk";
|
|
254
|
+
*
|
|
255
|
+
* // Allocate counters for encrypting three field elements
|
|
256
|
+
* const counters: PoseidonCounter[] = [0n, 1n, 2n].map((c) => {
|
|
257
|
+
* assertPoseidonCounter(c);
|
|
258
|
+
* return c;
|
|
259
|
+
* });
|
|
260
|
+
*
|
|
261
|
+
* // Increment safely (check upper bound for very long streams)
|
|
262
|
+
* const next = counters[2] + 1n;
|
|
263
|
+
* assertPoseidonCounter(next); // would throw if next >= BN254_FIELD_PRIME
|
|
264
|
+
*
|
|
265
|
+
* assertPoseidonCounter(-1n); // throws: negative value
|
|
266
|
+
* assertPoseidonCounter(BN254_FIELD_PRIME); // throws: exceeds field prime
|
|
267
|
+
* ```
|
|
268
|
+
*
|
|
269
|
+
* @see {@link assertPoseidonCounter} for the corresponding assertion function
|
|
270
|
+
* @see {@link PoseidonKeystreamGeneratorFunction} for how counters are consumed
|
|
271
|
+
* @public
|
|
272
|
+
*/
|
|
273
|
+
type PoseidonCounter = SubSubSubBrandedType<Bn254FieldElement, "PoseidonCounter">;
|
|
274
|
+
/**
|
|
275
|
+
* A pseudo-random field element generated by the Poseidon keystream PRF.
|
|
276
|
+
*
|
|
277
|
+
* `PoseidonKeystream` is the output of evaluating the Poseidon PRF at a specific
|
|
278
|
+
* {@link PoseidonCounter}. It is the secret "one-time pad" value added to a
|
|
279
|
+
* {@link PoseidonPlaintext} to produce a {@link PoseidonCiphertext}.
|
|
280
|
+
*
|
|
281
|
+
* @remarks
|
|
282
|
+
* ## Generation Formula
|
|
283
|
+
*
|
|
284
|
+
* For a master key `k` and counter `c`, the keystream is:
|
|
285
|
+
* ```
|
|
286
|
+
* keystream = Poseidon([k, c, 2n])
|
|
287
|
+
* ```
|
|
288
|
+
*
|
|
289
|
+
* The domain separation constant `2n` at the third input position ensures this
|
|
290
|
+
* Poseidon invocation is distinguishable from other uses of Poseidon in the
|
|
291
|
+
* protocol (e.g. hashing, commitment generation).
|
|
292
|
+
*
|
|
293
|
+
* ## Stream Cipher Operations
|
|
294
|
+
*
|
|
295
|
+
* ```
|
|
296
|
+
* // Encryption
|
|
297
|
+
* ciphertext = (plaintext + keystream) mod BN254_FIELD_PRIME
|
|
298
|
+
*
|
|
299
|
+
* // Decryption
|
|
300
|
+
* plaintext = (ciphertext - keystream + BN254_FIELD_PRIME) mod BN254_FIELD_PRIME
|
|
301
|
+
* ```
|
|
302
|
+
*
|
|
303
|
+
* ## Security Properties
|
|
304
|
+
*
|
|
305
|
+
* - Keystreamvalues are computationally indistinguishable from uniformly random
|
|
306
|
+
* field elements when the key is unknown (PRF security of Poseidon).
|
|
307
|
+
* - Each `(key, counter)` pair produces exactly one keystream value; counters must
|
|
308
|
+
* not be reused (see {@link PoseidonCounter}).
|
|
309
|
+
* - Keystreamvalues themselves must remain secret; exposing a keystream for a given
|
|
310
|
+
* counter reveals the corresponding plaintext.
|
|
311
|
+
*
|
|
312
|
+
* @example
|
|
313
|
+
* ```typescript
|
|
314
|
+
* import {
|
|
315
|
+
* assertPoseidonKeystream,
|
|
316
|
+
* type PoseidonKeystream,
|
|
317
|
+
* BN254_FIELD_PRIME,
|
|
318
|
+
* } from "@umbra/sdk";
|
|
319
|
+
*
|
|
320
|
+
* const keystreamGenerator = getPoseidonKeystreamGenerator();
|
|
321
|
+
* const keystreamMap = await keystreamGenerator([0n, 1n, 2n], masterKey);
|
|
322
|
+
*
|
|
323
|
+
* const keystream0 = keystreamMap.get(0n)!; // PoseidonKeystream for counter 0
|
|
324
|
+
* // Encrypt one field element
|
|
325
|
+
* const ciphertext = (plaintext + keystream0) % BN254_FIELD_PRIME;
|
|
326
|
+
*
|
|
327
|
+
* // Externally supplied keystream must be validated before use
|
|
328
|
+
* const rawKeystream = 111222333n;
|
|
329
|
+
* assertPoseidonKeystream(rawKeystream);
|
|
330
|
+
* // rawKeystream: PoseidonKeystream
|
|
331
|
+
* ```
|
|
332
|
+
*
|
|
333
|
+
* @see {@link assertPoseidonKeystream} for the corresponding assertion function
|
|
334
|
+
* @see {@link PoseidonKeystreamGeneratorFunction} for the function that produces this type
|
|
335
|
+
* @public
|
|
336
|
+
*/
|
|
337
|
+
type PoseidonKeystream = SubSubSubBrandedType<Bn254FieldElement, "PoseidonKeystream">;
|
|
338
|
+
/**
|
|
339
|
+
* A single 85-bit limb of a Base85 decomposition of a 256-bit value.
|
|
340
|
+
*
|
|
341
|
+
* Base85 limbs are the canonical way that the Umbra ZK circuits represent
|
|
342
|
+
* 256-bit field elements (e.g., Solana public keys and Ethereum addresses) when
|
|
343
|
+
* those values must be hashed or committed inside a Poseidon-based circuit.
|
|
344
|
+
* Because BN254 field elements are ~254 bits, a full 256-bit value cannot be
|
|
345
|
+
* reduced into a single field element without information loss. Instead, it is
|
|
346
|
+
* split into three 85-bit limbs, each of which is small enough to fit safely
|
|
347
|
+
* within the BN254 field.
|
|
348
|
+
*
|
|
349
|
+
* @remarks
|
|
350
|
+
* ## Why 85 bits?
|
|
351
|
+
*
|
|
352
|
+
* Three 85-bit limbs cover exactly 255 bits, which is sufficient for any value
|
|
353
|
+
* less than 2^255 — a superset of all 256-bit keys used in Umbra (Solana
|
|
354
|
+
* addresses are 32 bytes = 256 bits, but their top bit is effectively always 0
|
|
355
|
+
* for Ed25519 keys).
|
|
356
|
+
*
|
|
357
|
+
* ## Type Hierarchy
|
|
358
|
+
*
|
|
359
|
+
* ```
|
|
360
|
+
* bigint
|
|
361
|
+
* └── UnsignedInteger (brand: "UnsignedInteger")
|
|
362
|
+
* └── U128 (brand: "U128")
|
|
363
|
+
* └── Base85Limb (brand: "Base85Limb")
|
|
364
|
+
* ```
|
|
365
|
+
*
|
|
366
|
+
* `Base85Limb` extends `U128` because the actual limb value fits within 85 bits,
|
|
367
|
+
* which is a strict subset of the 128-bit unsigned range.
|
|
368
|
+
*
|
|
369
|
+
* @example
|
|
370
|
+
* ```typescript
|
|
371
|
+
* import { assertBase85Limb, BASE85_LIMB_MAX, type Base85Limb } from "@umbra/sdk";
|
|
372
|
+
*
|
|
373
|
+
* const lowBits = 123456789n;
|
|
374
|
+
* assertBase85Limb(lowBits, "lowBits");
|
|
375
|
+
* // lowBits: Base85Limb
|
|
376
|
+
*
|
|
377
|
+
* assertBase85Limb(BASE85_LIMB_MAX + 1n, "overflow"); // throws: exceeds max
|
|
378
|
+
* assertBase85Limb(-1n, "negative"); // throws: negative value
|
|
379
|
+
* ```
|
|
380
|
+
*
|
|
381
|
+
* @see {@link BASE85_LIMB_MAX} for the maximum valid limb value (2^85 - 1)
|
|
382
|
+
* @see {@link Base85LimbTuple} for the three-limb tuple that represents a full 256-bit value
|
|
383
|
+
* @see {@link assertBase85Limb} for the corresponding assertion function
|
|
384
|
+
* @public
|
|
385
|
+
*/
|
|
386
|
+
type Base85Limb = SubSubBrandedType<U128, "Base85Limb">;
|
|
387
|
+
/**
|
|
388
|
+
* The maximum value representable by a single Base85 limb.
|
|
389
|
+
*
|
|
390
|
+
* @remarks
|
|
391
|
+
* Equals `2^85 - 1`. Any `bigint` value greater than this constant is out of range
|
|
392
|
+
* for a `Base85Limb` and will be rejected by {@link assertBase85Limb}.
|
|
393
|
+
*
|
|
394
|
+
* The value in decimal is:
|
|
395
|
+
* `38685626227668133590597631`
|
|
396
|
+
*
|
|
397
|
+
* @example
|
|
398
|
+
* ```typescript
|
|
399
|
+
* import { BASE85_LIMB_MAX } from "@umbra/sdk";
|
|
400
|
+
*
|
|
401
|
+
* // Check before asserting
|
|
402
|
+
* if (value <= BASE85_LIMB_MAX) {
|
|
403
|
+
* assertBase85Limb(value, "value");
|
|
404
|
+
* }
|
|
405
|
+
* ```
|
|
406
|
+
*
|
|
407
|
+
* @see {@link Base85Limb} for the type this constant bounds
|
|
408
|
+
* @public
|
|
409
|
+
*/
|
|
410
|
+
declare const BASE85_LIMB_MAX: bigint;
|
|
411
|
+
/**
|
|
412
|
+
* A three-limb representation of a 256-bit value in Base85 encoding.
|
|
413
|
+
*
|
|
414
|
+
* `Base85LimbTuple` decomposes a 256-bit value `V` into three {@link Base85Limb}
|
|
415
|
+
* components according to the bit-slice layout:
|
|
416
|
+
* - `low`: bits [0, 84] — `V mod 2^85`
|
|
417
|
+
* - `middle`: bits [85, 169] — `(V >> 85) mod 2^85`
|
|
418
|
+
* - `high`: bits [170, 255] — `(V >> 170) mod 2^86`
|
|
419
|
+
*
|
|
420
|
+
* All three limbs together reconstruct the original 256-bit value as:
|
|
421
|
+
* ```
|
|
422
|
+
* V = low + (middle * 2^85) + (high * 2^170)
|
|
423
|
+
* ```
|
|
424
|
+
*
|
|
425
|
+
* @remarks
|
|
426
|
+
* ## Use in ZK Circuits
|
|
427
|
+
*
|
|
428
|
+
* Inside a Groth16 or PLONK circuit, a 256-bit value (e.g., a Solana address)
|
|
429
|
+
* cannot be processed as a single field element because the BN254 prime is only
|
|
430
|
+
* ~254 bits. The standard approach is to pass the value as three limbs and let
|
|
431
|
+
* the circuit reconstruct it from the limb witnesses:
|
|
432
|
+
*
|
|
433
|
+
* ```circom
|
|
434
|
+
* signal input addrLow; // bits [0, 84]
|
|
435
|
+
* signal input addrMiddle; // bits [85, 169]
|
|
436
|
+
* signal input addrHigh; // bits [170, 255]
|
|
437
|
+
* ```
|
|
438
|
+
*
|
|
439
|
+
* The Umbra Poseidon aggregator hashes these limbs alongside other UTXO fields
|
|
440
|
+
* to produce the aggregated public input for the Groth16 verifier.
|
|
441
|
+
*
|
|
442
|
+
* ## Readonly Fields
|
|
443
|
+
*
|
|
444
|
+
* All three fields are `readonly` to prevent mutation after construction. Changing
|
|
445
|
+
* a limb without updating the others would produce an inconsistent representation.
|
|
446
|
+
*
|
|
447
|
+
* @example
|
|
448
|
+
* ```typescript
|
|
449
|
+
* import {
|
|
450
|
+
* assertBase85Limb,
|
|
451
|
+
* type Base85LimbTuple,
|
|
452
|
+
* } from "@umbra/sdk";
|
|
453
|
+
*
|
|
454
|
+
* function decompose256BitValue(v: bigint): Base85LimbTuple {
|
|
455
|
+
* const mask = (1n << 85n) - 1n;
|
|
456
|
+
* const low = v & mask;
|
|
457
|
+
* const middle = (v >> 85n) & mask;
|
|
458
|
+
* const high = (v >> 170n) & ((1n << 86n) - 1n);
|
|
459
|
+
*
|
|
460
|
+
* assertBase85Limb(low, "low");
|
|
461
|
+
* assertBase85Limb(middle, "middle");
|
|
462
|
+
* assertBase85Limb(high, "high");
|
|
463
|
+
*
|
|
464
|
+
* return { low, middle, high };
|
|
465
|
+
* }
|
|
466
|
+
* ```
|
|
467
|
+
*
|
|
468
|
+
* @see {@link Base85Limb} for the individual limb type
|
|
469
|
+
* @see {@link BASE85_LIMB_MAX} for the per-limb maximum value
|
|
470
|
+
* @public
|
|
471
|
+
*/
|
|
472
|
+
interface Base85LimbTuple {
|
|
473
|
+
/**
|
|
474
|
+
* The low 85 bits of the 256-bit value (bits 0–84, inclusive).
|
|
475
|
+
*
|
|
476
|
+
* @remarks
|
|
477
|
+
* Computed as `value mod 2^85`. This is the least-significant limb.
|
|
478
|
+
*
|
|
479
|
+
* @readonly
|
|
480
|
+
*/
|
|
481
|
+
readonly low: Base85Limb;
|
|
482
|
+
/**
|
|
483
|
+
* The middle 85 bits of the 256-bit value (bits 85–169, inclusive).
|
|
484
|
+
*
|
|
485
|
+
* @remarks
|
|
486
|
+
* Computed as `(value >> 85n) mod 2^85`. This limb represents the second
|
|
487
|
+
* 85-bit segment of the original value.
|
|
488
|
+
*
|
|
489
|
+
* @readonly
|
|
490
|
+
*/
|
|
491
|
+
readonly middle: Base85Limb;
|
|
492
|
+
/**
|
|
493
|
+
* The high bits of the 256-bit value (bits 170–255, inclusive).
|
|
494
|
+
*
|
|
495
|
+
* @remarks
|
|
496
|
+
* Computed as `value >> 170n`. Because a 256-bit value contributes at most
|
|
497
|
+
* 86 bits in this position (256 - 170 = 86), this limb may reach up to
|
|
498
|
+
* 2^86 - 1, which still fits within the `Base85Limb` maximum of 2^85 - 1
|
|
499
|
+
* for values that are actually ≤ 2^255 (i.e., all valid Ed25519 public keys
|
|
500
|
+
* and standard 32-byte Solana addresses).
|
|
501
|
+
*
|
|
502
|
+
* @readonly
|
|
503
|
+
*/
|
|
504
|
+
readonly high: Base85Limb;
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* Narrows a `bigint` to {@link PoseidonPlaintext} by asserting it is a valid BN254 field element.
|
|
508
|
+
*
|
|
509
|
+
* This is a TypeScript assertion function: if it returns without throwing, the
|
|
510
|
+
* TypeScript compiler refines the type of `value` from `bigint` to `PoseidonPlaintext`
|
|
511
|
+
* in the calling scope.
|
|
512
|
+
*
|
|
513
|
+
* @param value - The `bigint` to validate. Must satisfy `0 ≤ value < BN254_FIELD_PRIME`.
|
|
514
|
+
* @throws {CryptographyAssertionError} If `value` is not a `bigint`.
|
|
515
|
+
* @throws {CryptographyAssertionError} If `value` is negative (`value < 0n`).
|
|
516
|
+
* @throws {CryptographyAssertionError} If `value` is out of range (`value >= BN254_FIELD_PRIME`).
|
|
517
|
+
*
|
|
518
|
+
* @remarks
|
|
519
|
+
* Assertion functions are the SDK's pattern for validating untrusted data at the
|
|
520
|
+
* boundary of typed and untyped code (e.g., values deserialized from JSON, received
|
|
521
|
+
* from on-chain accounts, or passed in from user input). After a successful call,
|
|
522
|
+
* the brand is established for the rest of the scope without any runtime cost beyond
|
|
523
|
+
* the validation itself.
|
|
524
|
+
*
|
|
525
|
+
* @example
|
|
526
|
+
* ```typescript
|
|
527
|
+
* import { assertPoseidonPlaintext } from "@umbra/sdk";
|
|
528
|
+
*
|
|
529
|
+
* // Good: valid field element
|
|
530
|
+
* const amount = 1_000_000n;
|
|
531
|
+
* assertPoseidonPlaintext(amount);
|
|
532
|
+
* // amount: PoseidonPlaintext ✓
|
|
533
|
+
*
|
|
534
|
+
* // Bad: negative value
|
|
535
|
+
* assertPoseidonPlaintext(-1n); // throws CryptographyAssertionError
|
|
536
|
+
*
|
|
537
|
+
* // Bad: at or above field prime
|
|
538
|
+
* assertPoseidonPlaintext(BN254_FIELD_PRIME); // throws CryptographyAssertionError
|
|
539
|
+
* ```
|
|
540
|
+
*
|
|
541
|
+
* @see {@link PoseidonPlaintext} for the type this function establishes
|
|
542
|
+
* @see {@link BN254_FIELD_PRIME} for the upper bound on valid values
|
|
543
|
+
* @public
|
|
544
|
+
*/
|
|
545
|
+
declare function assertPoseidonPlaintext(value: bigint): asserts value is PoseidonPlaintext;
|
|
546
|
+
/**
|
|
547
|
+
* Narrows a `bigint` to {@link PoseidonHash} by asserting it is a valid BN254 field element.
|
|
548
|
+
*
|
|
549
|
+
* This is a TypeScript assertion function: if it returns without throwing, the
|
|
550
|
+
* TypeScript compiler refines the type of `value` from `bigint` to `PoseidonHash`
|
|
551
|
+
* in the calling scope.
|
|
552
|
+
*
|
|
553
|
+
* @param value - The `bigint` to validate. Must satisfy `0 ≤ value < BN254_FIELD_PRIME`.
|
|
554
|
+
* @throws {CryptographyAssertionError} If `value` is not a `bigint`.
|
|
555
|
+
* @throws {CryptographyAssertionError} If `value` is negative (`value < 0n`).
|
|
556
|
+
* @throws {CryptographyAssertionError} If `value` is out of range (`value >= BN254_FIELD_PRIME`).
|
|
557
|
+
*
|
|
558
|
+
* @remarks
|
|
559
|
+
* Use this function when receiving a hash output from an external source (on-chain
|
|
560
|
+
* account data, a network response, or a test fixture) and you need to re-establish
|
|
561
|
+
* the `PoseidonHash` brand before passing the value to hash-typed APIs.
|
|
562
|
+
*
|
|
563
|
+
* Note that the Poseidon hash functions in the SDK return `PoseidonHash` directly,
|
|
564
|
+
* so calling this assertion is only necessary at trust boundaries.
|
|
565
|
+
*
|
|
566
|
+
* @example
|
|
567
|
+
* ```typescript
|
|
568
|
+
* import { assertPoseidonHash } from "@umbra/sdk";
|
|
569
|
+
*
|
|
570
|
+
* // Received as raw bigint from deserialized on-chain data
|
|
571
|
+
* const onChainLeaf: bigint = readLeafFromChain();
|
|
572
|
+
* assertPoseidonHash(onChainLeaf);
|
|
573
|
+
* // onChainLeaf: PoseidonHash — safe to compare with locally computed hashes
|
|
574
|
+
*
|
|
575
|
+
* assertPoseidonHash(-5n); // throws: negative
|
|
576
|
+
* assertPoseidonHash(BN254_FIELD_PRIME); // throws: out of range
|
|
577
|
+
* ```
|
|
578
|
+
*
|
|
579
|
+
* @see {@link PoseidonHash} for the type this function establishes
|
|
580
|
+
* @public
|
|
581
|
+
*/
|
|
582
|
+
declare function assertPoseidonHash(value: bigint): asserts value is PoseidonHash;
|
|
583
|
+
/**
|
|
584
|
+
* Narrows a `bigint` to {@link PoseidonKey} by asserting it is a valid BN254 field element.
|
|
585
|
+
*
|
|
586
|
+
* This is a TypeScript assertion function: if it returns without throwing, the
|
|
587
|
+
* TypeScript compiler refines the type of `value` from `bigint` to `PoseidonKey`
|
|
588
|
+
* in the calling scope.
|
|
589
|
+
*
|
|
590
|
+
* @param value - The `bigint` to validate. Must satisfy `0 ≤ value < BN254_FIELD_PRIME`.
|
|
591
|
+
* @throws {CryptographyAssertionError} If `value` is not a `bigint`.
|
|
592
|
+
* @throws {CryptographyAssertionError} If `value` is negative (`value < 0n`).
|
|
593
|
+
* @throws {CryptographyAssertionError} If `value` is out of range (`value >= BN254_FIELD_PRIME`).
|
|
594
|
+
*
|
|
595
|
+
* @remarks
|
|
596
|
+
* Call this function after deriving a `PoseidonKey` from a master seed to establish
|
|
597
|
+
* the type brand. Because key derivation functions typically return raw `bigint` or
|
|
598
|
+
* `Uint8Array` values, the assertion is needed at the point where the raw output is
|
|
599
|
+
* interpreted as a Poseidon key.
|
|
600
|
+
*
|
|
601
|
+
* ## Security Warning
|
|
602
|
+
*
|
|
603
|
+
* A `PoseidonKey` is a long-lived secret. Validation does NOT check that the value
|
|
604
|
+
* was generated with sufficient entropy. It is the caller's responsibility to ensure
|
|
605
|
+
* the key was derived from a secure random source.
|
|
606
|
+
*
|
|
607
|
+
* @example
|
|
608
|
+
* ```typescript
|
|
609
|
+
* import { assertPoseidonKey } from "@umbra/sdk";
|
|
610
|
+
*
|
|
611
|
+
* const rawDerivedKey: bigint = deriveField(masterSeed, "poseidon/v1");
|
|
612
|
+
* assertPoseidonKey(rawDerivedKey);
|
|
613
|
+
* // rawDerivedKey: PoseidonKey — ready to pass to encryption functions
|
|
614
|
+
*
|
|
615
|
+
* assertPoseidonKey(-1n); // throws: negative
|
|
616
|
+
* assertPoseidonKey(BN254_FIELD_PRIME); // throws: out of range
|
|
617
|
+
* ```
|
|
618
|
+
*
|
|
619
|
+
* @see {@link PoseidonKey} for the type this function establishes
|
|
620
|
+
* @see {@link PoseidonEncryptorFunction} for the primary consumer of this type
|
|
621
|
+
* @public
|
|
622
|
+
*/
|
|
623
|
+
declare function assertPoseidonKey(value: bigint): asserts value is PoseidonKey;
|
|
624
|
+
/**
|
|
625
|
+
* Narrows a `bigint` to {@link PoseidonCiphertext} by asserting it is a valid BN254 field element.
|
|
626
|
+
*
|
|
627
|
+
* This is a TypeScript assertion function: if it returns without throwing, the
|
|
628
|
+
* TypeScript compiler refines the type of `value` from `bigint` to `PoseidonCiphertext`
|
|
629
|
+
* in the calling scope.
|
|
630
|
+
*
|
|
631
|
+
* @param value - The `bigint` to validate. Must satisfy `0 ≤ value < BN254_FIELD_PRIME`.
|
|
632
|
+
* @throws {CryptographyAssertionError} If `value` is not a `bigint`.
|
|
633
|
+
* @throws {CryptographyAssertionError} If `value` is negative (`value < 0n`).
|
|
634
|
+
* @throws {CryptographyAssertionError} If `value` is out of range (`value >= BN254_FIELD_PRIME`).
|
|
635
|
+
*
|
|
636
|
+
* @remarks
|
|
637
|
+
* Use this function when reading ciphertext values from on-chain account state
|
|
638
|
+
* (e.g., a confidential token account's encrypted balance fields) before passing
|
|
639
|
+
* them to {@link PoseidonDecryptorFunction}.
|
|
640
|
+
*
|
|
641
|
+
* Structurally, ciphertexts are indistinguishable from other BN254 field elements.
|
|
642
|
+
* The brand exists purely to prevent passing a plaintext where ciphertext is
|
|
643
|
+
* expected, or vice versa, at the type level.
|
|
644
|
+
*
|
|
645
|
+
* @example
|
|
646
|
+
* ```typescript
|
|
647
|
+
* import { assertPoseidonCiphertext } from "@umbra/sdk";
|
|
648
|
+
*
|
|
649
|
+
* // Reading raw ciphertext from a deserialized Solana account
|
|
650
|
+
* const rawCiphertext: bigint = accountData.encryptedBalance;
|
|
651
|
+
* assertPoseidonCiphertext(rawCiphertext);
|
|
652
|
+
* // rawCiphertext: PoseidonCiphertext — safe to pass to decryptor
|
|
653
|
+
*
|
|
654
|
+
* const [plaintext] = await decryptor([rawCiphertext], myKey);
|
|
655
|
+
* ```
|
|
656
|
+
*
|
|
657
|
+
* @see {@link PoseidonCiphertext} for the type this function establishes
|
|
658
|
+
* @see {@link PoseidonDecryptorFunction} for the function that consumes ciphertexts
|
|
659
|
+
* @public
|
|
660
|
+
*/
|
|
661
|
+
declare function assertPoseidonCiphertext(value: bigint): asserts value is PoseidonCiphertext;
|
|
662
|
+
/**
|
|
663
|
+
* Narrows a `bigint` to {@link PoseidonCounter} by asserting it is a valid BN254 field element.
|
|
664
|
+
*
|
|
665
|
+
* This is a TypeScript assertion function: if it returns without throwing, the
|
|
666
|
+
* TypeScript compiler refines the type of `value` from `bigint` to `PoseidonCounter`
|
|
667
|
+
* in the calling scope.
|
|
668
|
+
*
|
|
669
|
+
* @param value - The `bigint` to validate. Must satisfy `0 ≤ value < BN254_FIELD_PRIME`.
|
|
670
|
+
* @throws {CryptographyAssertionError} If `value` is not a `bigint`.
|
|
671
|
+
* @throws {CryptographyAssertionError} If `value` is negative (`value < 0n`).
|
|
672
|
+
* @throws {CryptographyAssertionError} If `value` is out of range (`value >= BN254_FIELD_PRIME`).
|
|
673
|
+
*
|
|
674
|
+
* @remarks
|
|
675
|
+
* Counters are typically constructed from small non-negative integers (0, 1, 2, …)
|
|
676
|
+
* that index into a sequence of plaintext positions. In practice the upper-bound
|
|
677
|
+
* check is almost never triggered for counter values, but it is included for
|
|
678
|
+
* correctness and to guard against edge cases in long-running sessions.
|
|
679
|
+
*
|
|
680
|
+
* @example
|
|
681
|
+
* ```typescript
|
|
682
|
+
* import { assertPoseidonCounter, type PoseidonCounter } from "@umbra/sdk";
|
|
683
|
+
*
|
|
684
|
+
* // Typed allocation of sequential counters
|
|
685
|
+
* function makeCounters(n: number): PoseidonCounter[] {
|
|
686
|
+
* return Array.from({ length: n }, (_, i) => {
|
|
687
|
+
* const c = BigInt(i);
|
|
688
|
+
* assertPoseidonCounter(c);
|
|
689
|
+
* return c;
|
|
690
|
+
* });
|
|
691
|
+
* }
|
|
692
|
+
*
|
|
693
|
+
* assertPoseidonCounter(-1n); // throws: negative value
|
|
694
|
+
* assertPoseidonCounter(BN254_FIELD_PRIME); // throws: exceeds field prime
|
|
695
|
+
* ```
|
|
696
|
+
*
|
|
697
|
+
* @see {@link PoseidonCounter} for the type this function establishes
|
|
698
|
+
* @see {@link PoseidonKeystreamGeneratorFunction} for how counters are consumed
|
|
699
|
+
* @public
|
|
700
|
+
*/
|
|
701
|
+
declare function assertPoseidonCounter(value: bigint): asserts value is PoseidonCounter;
|
|
702
|
+
/**
|
|
703
|
+
* Narrows a `bigint` to {@link PoseidonKeystream} by asserting it is a valid BN254 field element.
|
|
704
|
+
*
|
|
705
|
+
* This is a TypeScript assertion function: if it returns without throwing, the
|
|
706
|
+
* TypeScript compiler refines the type of `value` from `bigint` to `PoseidonKeystream`
|
|
707
|
+
* in the calling scope.
|
|
708
|
+
*
|
|
709
|
+
* @param value - The `bigint` to validate. Must satisfy `0 ≤ value < BN254_FIELD_PRIME`.
|
|
710
|
+
* @throws {CryptographyAssertionError} If `value` is not a `bigint`.
|
|
711
|
+
* @throws {CryptographyAssertionError} If `value` is negative (`value < 0n`).
|
|
712
|
+
* @throws {CryptographyAssertionError} If `value` is out of range (`value >= BN254_FIELD_PRIME`).
|
|
713
|
+
*
|
|
714
|
+
* @remarks
|
|
715
|
+
* Keystreamvalues are outputs of the Poseidon PRF and therefore always valid field
|
|
716
|
+
* elements when produced by the SDK's {@link PoseidonKeystreamGeneratorFunction}.
|
|
717
|
+
* This assertion is primarily useful at trust boundaries where a keystream value
|
|
718
|
+
* arrives from an external or serialized source and must be re-validated.
|
|
719
|
+
*
|
|
720
|
+
* ## Security Note
|
|
721
|
+
*
|
|
722
|
+
* Keystreamvalues are cryptographic secrets. They must not be logged, serialized
|
|
723
|
+
* to persistent storage, or transmitted in any observable channel. Exposing a
|
|
724
|
+
* keystream allows recovery of the corresponding plaintext.
|
|
725
|
+
*
|
|
726
|
+
* @example
|
|
727
|
+
* ```typescript
|
|
728
|
+
* import { assertPoseidonKeystream, BN254_FIELD_PRIME } from "@umbra/sdk";
|
|
729
|
+
*
|
|
730
|
+
* // In tests: construct a keystream from a known value for deterministic checks
|
|
731
|
+
* const testKeystream = 999888777666n;
|
|
732
|
+
* assertPoseidonKeystream(testKeystream);
|
|
733
|
+
* // testKeystream: PoseidonKeystream
|
|
734
|
+
*
|
|
735
|
+
* assertPoseidonKeystream(-1n); // throws: negative value
|
|
736
|
+
* assertPoseidonKeystream(BN254_FIELD_PRIME); // throws: exceeds field prime
|
|
737
|
+
* ```
|
|
738
|
+
*
|
|
739
|
+
* @see {@link PoseidonKeystream} for the type this function establishes
|
|
740
|
+
* @see {@link PoseidonKeystreamGeneratorFunction} for the function that produces keystreams
|
|
741
|
+
* @public
|
|
742
|
+
*/
|
|
743
|
+
declare function assertPoseidonKeystream(value: bigint): asserts value is PoseidonKeystream;
|
|
744
|
+
/**
|
|
745
|
+
* Narrows a `bigint` to {@link Base85Limb} by asserting it is within the 85-bit range.
|
|
746
|
+
*
|
|
747
|
+
* This is a TypeScript assertion function: if it returns without throwing, the
|
|
748
|
+
* TypeScript compiler refines the type of `value` from `bigint` to `Base85Limb`
|
|
749
|
+
* in the calling scope.
|
|
750
|
+
*
|
|
751
|
+
* @param value - The `bigint` to validate. Must satisfy `0 ≤ value ≤ 2^85 - 1`.
|
|
752
|
+
* @param name - A human-readable name for the variable being asserted, included in
|
|
753
|
+
* error messages to aid debugging when multiple limbs are validated in sequence.
|
|
754
|
+
* @defaultValue `"value"`
|
|
755
|
+
* @throws {CryptographyAssertionError} If `value` is not a `bigint`.
|
|
756
|
+
* @throws {CryptographyAssertionError} If `value` is negative (`value < 0n`).
|
|
757
|
+
* @throws {CryptographyAssertionError} If `value` exceeds the maximum limb value (`value > BASE85_LIMB_MAX`).
|
|
758
|
+
*
|
|
759
|
+
* @remarks
|
|
760
|
+
* This assertion is distinct from the Poseidon field element assertions: it checks
|
|
761
|
+
* against `BASE85_LIMB_MAX` (2^85 - 1) rather than `BN254_FIELD_PRIME`. Use this
|
|
762
|
+
* when decomposing a 256-bit value into {@link Base85LimbTuple} components.
|
|
763
|
+
*
|
|
764
|
+
* The `name` parameter is optional and defaults to `"value"`. Providing descriptive
|
|
765
|
+
* names (`"low"`, `"middle"`, `"high"`) makes errors easier to trace when all three
|
|
766
|
+
* limbs are validated in sequence.
|
|
767
|
+
*
|
|
768
|
+
* @example
|
|
769
|
+
* ```typescript
|
|
770
|
+
* import { assertBase85Limb, BASE85_LIMB_MAX } from "@umbra/sdk";
|
|
771
|
+
*
|
|
772
|
+
* const low = 12345n;
|
|
773
|
+
* const middle = 67890n;
|
|
774
|
+
* const high = 111n;
|
|
775
|
+
*
|
|
776
|
+
* assertBase85Limb(low, "low");
|
|
777
|
+
* assertBase85Limb(middle, "middle");
|
|
778
|
+
* assertBase85Limb(high, "high");
|
|
779
|
+
* // All three: Base85Limb
|
|
780
|
+
*
|
|
781
|
+
* // Error messages include the name for easy identification
|
|
782
|
+
* assertBase85Limb(BASE85_LIMB_MAX + 1n, "low"); // throws: "low: Value exceeds Base85 limb maximum"
|
|
783
|
+
* assertBase85Limb(-1n, "middle"); // throws: "middle: Value -1 is negative"
|
|
784
|
+
* ```
|
|
785
|
+
*
|
|
786
|
+
* @see {@link Base85Limb} for the type this function establishes
|
|
787
|
+
* @see {@link BASE85_LIMB_MAX} for the maximum allowed value
|
|
788
|
+
* @see {@link Base85LimbTuple} for how three limbs form a 256-bit representation
|
|
789
|
+
* @public
|
|
790
|
+
*/
|
|
791
|
+
declare function assertBase85Limb(value: bigint, name?: string): asserts value is Base85Limb;
|
|
792
|
+
|
|
793
|
+
export { BASE85_LIMB_MAX as B, type PoseidonCiphertext as P, type Base85Limb as a, type Base85LimbTuple as b, type PoseidonCounter as c, type PoseidonHash as d, type PoseidonKey as e, type PoseidonKeystream as f, type PoseidonPlaintext as g, assertBase85Limb as h, assertPoseidonCiphertext as i, assertPoseidonCounter as j, assertPoseidonHash as k, assertPoseidonKey as l, assertPoseidonKeystream as m, assertPoseidonPlaintext as n };
|