@fatsolutions/privacy-pools-core-starknet-sdk 0.0.42 → 0.0.43
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/abis/EntryPoint.abi.d.ts +0 -23
- package/dist/abis/EntryPoint.abi.js +0 -32
- package/dist/abis/EntryPoint.abi.js.map +1 -1
- package/dist/abis/PrivacyPool.abi.d.ts +5 -66
- package/dist/abis/PrivacyPool.abi.js +5 -87
- package/dist/abis/PrivacyPool.abi.js.map +1 -1
- package/dist/contracts/contracts.service.js +3 -5
- package/dist/contracts/contracts.service.js.map +1 -1
- package/dist/data.service.d.ts +2 -15
- package/dist/data.service.js +2 -41
- package/dist/data.service.js.map +1 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -3
- package/dist/index.js.map +1 -1
- package/dist/types/entrypoint.d.ts +0 -2
- package/dist/types/entrypoint.js +11 -26
- package/dist/types/entrypoint.js.map +1 -1
- package/dist/utils.d.ts +1 -4
- package/dist/utils.js +1 -10
- package/dist/utils.js.map +1 -1
- package/package.json +3 -7
- package/src/abis/EntryPoint.abi.ts +893 -925
- package/src/abis/PrivacyPool.abi.ts +525 -607
- package/src/contracts/contracts.service.ts +3 -5
- package/src/data.service.ts +2 -79
- package/src/index.ts +0 -5
- package/src/types/entrypoint.ts +13 -46
- package/src/utils.ts +1 -13
- package/dist/account.service.d.ts +0 -15
- package/dist/account.service.js +0 -27
- package/dist/account.service.js.map +0 -1
- package/dist/auditor.d.ts +0 -31
- package/dist/auditor.js +0 -148
- package/dist/auditor.js.map +0 -1
- package/src/account.service.ts +0 -42
- package/src/auditor.ts +0 -223
package/src/auditor.ts
DELETED
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
import { xchacha20poly1305 } from "@noble/ciphers/chacha.js";
|
|
2
|
-
import { hkdf } from "@noble/hashes/hkdf.js";
|
|
3
|
-
import { sha3_256 as sha256 } from "@noble/hashes/sha3.js";
|
|
4
|
-
import { bytesToNumberBE, numberToBytesBE } from "@noble/ciphers/utils.js";
|
|
5
|
-
import { Secret, getCommitment, AccountCommitment, Hash, PoolInfo } from "@0xbow/privacy-pools-core-sdk";
|
|
6
|
-
import { CairoOption, CairoOptionVariant } from "starknet";
|
|
7
|
-
import { poseidonHashMany } from "@scure/starknet";
|
|
8
|
-
import { StarknetDataService } from "./data.service.js";
|
|
9
|
-
import { base64 } from "@scure/base";
|
|
10
|
-
import { mnemonicToEntropy } from "@scure/bip39";
|
|
11
|
-
import { wordlist } from '@scure/bip39/wordlists/english';
|
|
12
|
-
|
|
13
|
-
export interface AuditEvent {
|
|
14
|
-
tag: Hash;
|
|
15
|
-
ciphertext: string;
|
|
16
|
-
prevNullifierHash: Hash;
|
|
17
|
-
newCommitment: Hash;
|
|
18
|
-
blockNumber: bigint;
|
|
19
|
-
transactionHash: string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
//TODO: The first time you will need to generate a viewing key is in the first withdraw
|
|
23
|
-
// of a deposited note. At that point you allready have a label. I suggest for the viewKey to be derivable
|
|
24
|
-
// from the account secret + deposit label. There is no need to store another secret for each deposit.
|
|
25
|
-
// viewKey =~ Hash(AccountSecret, Label);
|
|
26
|
-
export function deriveKey(secret: Uint8Array, label: bigint): Uint8Array {
|
|
27
|
-
const info = new TextEncoder().encode("xchacha-key");
|
|
28
|
-
const salt = new TextEncoder().encode(String(label));
|
|
29
|
-
const viewKey = hkdf(sha256, secret, salt, info, 32);
|
|
30
|
-
return viewKey;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function deriveKeyFromMnemonic(mnemonic: string, label: bigint): Uint8Array {
|
|
34
|
-
const secret = mnemonicToEntropy(mnemonic, wordlist);
|
|
35
|
-
return deriveKey(secret, label);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export function encrypt(plaintext: Uint8Array, viewKey: Uint8Array) {
|
|
39
|
-
const nonce = crypto.getRandomValues(new Uint8Array(24));
|
|
40
|
-
|
|
41
|
-
const chacha = xchacha20poly1305(viewKey, nonce);
|
|
42
|
-
const ciphertext = chacha.encrypt(plaintext);
|
|
43
|
-
|
|
44
|
-
// Prepend the nonce
|
|
45
|
-
const output = new Uint8Array(24 + ciphertext.length);
|
|
46
|
-
output.set(nonce, 0);
|
|
47
|
-
output.set(ciphertext, 24);
|
|
48
|
-
|
|
49
|
-
return output;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export function decrypt(input: Uint8Array, viewKey: Uint8Array): Uint8Array {
|
|
53
|
-
const nonce = input.slice(0, 24);
|
|
54
|
-
const chacha = xchacha20poly1305(viewKey, nonce);
|
|
55
|
-
|
|
56
|
-
const ciphertext = input.slice(24);
|
|
57
|
-
//TODO: What happens if AE fails?
|
|
58
|
-
const decrypted = chacha.decrypt(ciphertext);
|
|
59
|
-
|
|
60
|
-
return decrypted;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export function packAuditorData({
|
|
64
|
-
label: declaredLabel,
|
|
65
|
-
value: declaredValue,
|
|
66
|
-
nullifier: declaredNullifier,
|
|
67
|
-
secret: declaredSecret
|
|
68
|
-
}: Pick<AccountCommitment, 'label' | 'value' | 'nullifier' | 'secret'>,
|
|
69
|
-
): Uint8Array {
|
|
70
|
-
|
|
71
|
-
//TODO: Add assertions about lenght of bigint
|
|
72
|
-
const output = new Uint8Array(128);
|
|
73
|
-
output.set(numberToBytesBE(declaredLabel, 32), 0);
|
|
74
|
-
output.set(numberToBytesBE(declaredValue, 32), 32);
|
|
75
|
-
output.set(numberToBytesBE(declaredNullifier, 32), 64);
|
|
76
|
-
output.set(numberToBytesBE(declaredSecret, 32), 96);
|
|
77
|
-
|
|
78
|
-
return output;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export function unpackAuditorData(packedData: Uint8Array)
|
|
82
|
-
: {
|
|
83
|
-
declaredLabel: bigint,
|
|
84
|
-
declaredValue: bigint,
|
|
85
|
-
declaredNullifier: bigint,
|
|
86
|
-
declaredSecret: bigint;
|
|
87
|
-
} {
|
|
88
|
-
const declaredLabel = bytesToNumberBE(packedData.slice(0, 32));
|
|
89
|
-
const declaredValue = bytesToNumberBE(packedData.slice(32, 64));
|
|
90
|
-
const declaredNullifier = bytesToNumberBE(packedData.slice(64, 96));
|
|
91
|
-
const declaredSecret = bytesToNumberBE(packedData.slice(96, 128));
|
|
92
|
-
|
|
93
|
-
return { declaredLabel, declaredValue, declaredNullifier, declaredSecret };
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
export function reconstructAccountCommitment(event: AuditEvent, viewKey: Uint8Array): AccountCommitment {
|
|
98
|
-
const { ciphertext, blockNumber, transactionHash, prevNullifierHash } = event;
|
|
99
|
-
|
|
100
|
-
const auditorData = decrypt(base64.decode(ciphertext), viewKey);
|
|
101
|
-
const { declaredLabel, declaredValue, declaredNullifier, declaredSecret } = unpackAuditorData(auditorData);
|
|
102
|
-
|
|
103
|
-
const {
|
|
104
|
-
hash,
|
|
105
|
-
nullifierHash,
|
|
106
|
-
preimage: { value: _value, label, precommitment: _precommitment }
|
|
107
|
-
} = getCommitment(declaredValue, declaredLabel, declaredNullifier as Secret, declaredSecret as Secret);
|
|
108
|
-
|
|
109
|
-
if (nullifierHash != prevNullifierHash) {
|
|
110
|
-
throw new Error("Inconsistency in emitted nullifier hash");
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
return {
|
|
114
|
-
hash,
|
|
115
|
-
value: declaredValue,
|
|
116
|
-
label: label as Hash,
|
|
117
|
-
nullifier: declaredNullifier as Secret,
|
|
118
|
-
secret: declaredSecret as Secret,
|
|
119
|
-
blockNumber,
|
|
120
|
-
txHash: transactionHash as `0x{string}`,
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
export function computeTag(viewKey: Uint8Array, withdraw_number: number): bigint {
|
|
125
|
-
const viewKeyBigInt = bytesToNumberBE(viewKey);
|
|
126
|
-
const tag = poseidonHashMany([viewKeyBigInt, BigInt(withdraw_number)]);
|
|
127
|
-
return tag;
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
async function fetchAuditEventsForViewKey(
|
|
132
|
-
viewKey: Uint8Array,
|
|
133
|
-
serviceData: StarknetDataService,
|
|
134
|
-
pool: PoolInfo,
|
|
135
|
-
): Promise<[AuditEvent, number][]> {
|
|
136
|
-
let out: [AuditEvent, number][] = [];
|
|
137
|
-
let withdraw_number = 0;
|
|
138
|
-
while (true) {
|
|
139
|
-
let tag = computeTag(viewKey, withdraw_number);
|
|
140
|
-
let events = await serviceData.getAuditEventForTag(tag, pool);
|
|
141
|
-
if (!events) { break; };
|
|
142
|
-
|
|
143
|
-
//It should be only ONE event with this tag. But it is not eforced. A troll could make a withdraw with
|
|
144
|
-
//the tag of a previous withraw from another label.
|
|
145
|
-
events.forEach(event => out.push([event, withdraw_number]));
|
|
146
|
-
withdraw_number++;
|
|
147
|
-
}
|
|
148
|
-
return out;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
export async function constructSequence(
|
|
152
|
-
viewKey: Uint8Array,
|
|
153
|
-
serviceData: StarknetDataService,
|
|
154
|
-
pool: PoolInfo
|
|
155
|
-
): Promise<AccountCommitment[]> {
|
|
156
|
-
const commitments: AccountCommitment[] = [];
|
|
157
|
-
const events = await fetchAuditEventsForViewKey(viewKey, serviceData, pool);
|
|
158
|
-
|
|
159
|
-
const events_for_index = events.filter(([_, b]) => b === 0);
|
|
160
|
-
if (events_for_index.length === 0) {
|
|
161
|
-
throw new Error("No withdraws for this key");
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
let declaredCommitment: AccountCommitment | undefined;
|
|
165
|
-
|
|
166
|
-
for (const [event, _withdraw_number] of events_for_index) {
|
|
167
|
-
try {
|
|
168
|
-
declaredCommitment = reconstructAccountCommitment(event, viewKey);
|
|
169
|
-
} catch {
|
|
170
|
-
//What should we do here?
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (!declaredCommitment) {
|
|
175
|
-
throw new Error("No event could be decrypted");
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
let initialLabel = declaredCommitment.label;
|
|
180
|
-
|
|
181
|
-
let deposit = await serviceData.getDeposits(pool, pool.deploymentBlock, initialLabel);
|
|
182
|
-
if (deposit.length != 1) {
|
|
183
|
-
throw new Error("No deposit found for this label");
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
let initialCommitment = deposit[0]!.commitment;
|
|
187
|
-
if (initialCommitment != declaredCommitment.hash) {
|
|
188
|
-
throw new Error("mismatch");
|
|
189
|
-
}
|
|
190
|
-
commitments.push(declaredCommitment);
|
|
191
|
-
|
|
192
|
-
for (let i = 1; i < events.length; i++) {
|
|
193
|
-
let events_for_index = events.filter(([_, b]) => b === i);
|
|
194
|
-
|
|
195
|
-
for (const [event, _withdraw_number] of events_for_index) {
|
|
196
|
-
try {
|
|
197
|
-
declaredCommitment = reconstructAccountCommitment(event, viewKey);
|
|
198
|
-
} catch {
|
|
199
|
-
//What should we do here?
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
if (initialLabel != declaredCommitment.label) {
|
|
204
|
-
throw new Error("mismatch");
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
if (commitments[i - 1]!.hash != declaredCommitment.hash) {
|
|
208
|
-
throw new Error("mismatch");
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
commitments.push(declaredCommitment);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
return commitments;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Represents a AuditEvent event from a privacy pool
|
|
219
|
-
*/
|
|
220
|
-
export interface AuditorData {
|
|
221
|
-
tag: bigint;
|
|
222
|
-
ciphertext: string;
|
|
223
|
-
}
|