@inco/js 0.7.0 → 0.7.2
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/cjs/advancedacl/session-key.d.ts +9 -3
- package/dist/cjs/advancedacl/session-key.js +18 -7
- package/dist/cjs/attestedcompute/attested-compute.d.ts +32 -4
- package/dist/cjs/attestedcompute/attested-compute.js +13 -13
- package/dist/cjs/attesteddecrypt/attested-decrypt.d.ts +12 -6
- package/dist/cjs/attesteddecrypt/attested-decrypt.js +40 -7
- package/dist/cjs/attesteddecrypt/types.d.ts +1 -0
- package/dist/cjs/generated/es/inco/kms/lite/v1/kms_service_pb.d.ts +28 -14
- package/dist/cjs/generated/es/inco/kms/lite/v1/kms_service_pb.js +2 -2
- package/dist/cjs/kms/quorumClient.d.ts +1 -1
- package/dist/cjs/kms/quorumClient.js +118 -17
- package/dist/cjs/lite/attested-compute.d.ts +2 -2
- package/dist/cjs/lite/attested-compute.js +3 -3
- package/dist/cjs/lite/attested-decrypt.d.ts +2 -2
- package/dist/cjs/lite/attested-decrypt.js +3 -3
- package/dist/cjs/lite/ecies.d.ts +2 -0
- package/dist/cjs/lite/ecies.js +5 -2
- package/dist/cjs/lite/lightning.d.ts +99 -23
- package/dist/cjs/lite/lightning.js +165 -86
- package/dist/cjs/test/mocks.js +4 -2
- package/dist/cjs/viem.d.ts +2 -4
- package/dist/cjs/viem.js +6 -2
- package/dist/esm/advancedacl/session-key.d.ts +9 -3
- package/dist/esm/advancedacl/session-key.js +20 -9
- package/dist/esm/attestedcompute/attested-compute.d.ts +32 -4
- package/dist/esm/attestedcompute/attested-compute.js +14 -14
- package/dist/esm/attesteddecrypt/attested-decrypt.d.ts +12 -6
- package/dist/esm/attesteddecrypt/attested-decrypt.js +39 -7
- package/dist/esm/attesteddecrypt/types.d.ts +1 -0
- package/dist/esm/generated/es/inco/kms/lite/v1/kms_service_pb.d.ts +28 -14
- package/dist/esm/generated/es/inco/kms/lite/v1/kms_service_pb.js +2 -2
- package/dist/esm/kms/quorumClient.d.ts +1 -1
- package/dist/esm/kms/quorumClient.js +118 -17
- package/dist/esm/lite/attested-compute.d.ts +2 -2
- package/dist/esm/lite/attested-compute.js +3 -3
- package/dist/esm/lite/attested-decrypt.d.ts +2 -2
- package/dist/esm/lite/attested-decrypt.js +3 -3
- package/dist/esm/lite/ecies.d.ts +2 -0
- package/dist/esm/lite/ecies.js +4 -2
- package/dist/esm/lite/lightning.d.ts +99 -23
- package/dist/esm/lite/lightning.js +166 -87
- package/dist/esm/test/mocks.js +4 -2
- package/dist/esm/viem.d.ts +2 -4
- package/dist/esm/viem.js +6 -2
- package/dist/types/advancedacl/session-key.d.ts +9 -3
- package/dist/types/attestedcompute/attested-compute.d.ts +32 -4
- package/dist/types/attesteddecrypt/attested-decrypt.d.ts +12 -6
- package/dist/types/attesteddecrypt/types.d.ts +1 -0
- package/dist/types/generated/es/inco/kms/lite/v1/kms_service_pb.d.ts +28 -14
- package/dist/types/kms/quorumClient.d.ts +1 -1
- package/dist/types/lite/attested-compute.d.ts +2 -2
- package/dist/types/lite/attested-decrypt.d.ts +2 -2
- package/dist/types/lite/ecies.d.ts +2 -0
- package/dist/types/lite/lightning.d.ts +99 -23
- package/dist/types/viem.d.ts +2 -4
- package/package.json +5 -2
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import type { Account, Chain, Transport, WalletClient } from 'viem';
|
|
2
|
-
import { DecryptionAttestation } from '../attesteddecrypt/types.js';
|
|
2
|
+
import { DecryptionAttestation, EncryptedDecryptionAttestation } from '../attesteddecrypt/types.js';
|
|
3
3
|
import { HexString } from '../binary.js';
|
|
4
4
|
import { SupportedChainId } from '../chain.js';
|
|
5
|
-
import { EciesScheme, SupportedFheType } from '../encryption/encryption.js';
|
|
5
|
+
import type { EciesScheme, SupportedFheType } from '../encryption/encryption.js';
|
|
6
6
|
import { KmsQuorumClient } from '../kms/quorumClient.js';
|
|
7
|
+
import type { Secp256k1Keypair } from '../lite/ecies.js';
|
|
7
8
|
import type { BackoffConfig } from '../retry.js';
|
|
8
9
|
import { AttestedComputeOP } from './types.js';
|
|
9
10
|
export declare const ATTESTED_COMPUTE_DOMAIN_NAME = "IncoAttestedCompute";
|
|
10
|
-
export declare const
|
|
11
|
+
export declare const DEFAULT_ATTESTED_COMPUTE_DOMAIN_VERSION = "2";
|
|
11
12
|
/**
|
|
12
13
|
* Arguments for creating an attested compute.
|
|
13
14
|
*/
|
|
@@ -27,7 +28,8 @@ export interface IncoLiteAttestedComputeArgs {
|
|
|
27
28
|
*
|
|
28
29
|
* @todo Support multiple operations in a single request.
|
|
29
30
|
*/
|
|
30
|
-
export declare function attestedCompute<T extends SupportedFheType>({ lhsHandle, op, rhsPlaintext, backoffConfig, walletClient, kmsQuorumClient, chainId, }: {
|
|
31
|
+
export declare function attestedCompute<T extends SupportedFheType>({ executorAddress, lhsHandle, op, rhsPlaintext, backoffConfig, walletClient, kmsQuorumClient, chainId, reencryptPubKey, reencryptKeypair, }: {
|
|
32
|
+
executorAddress: HexString;
|
|
31
33
|
lhsHandle: HexString;
|
|
32
34
|
op: AttestedComputeOP;
|
|
33
35
|
rhsPlaintext: bigint | boolean;
|
|
@@ -35,4 +37,30 @@ export declare function attestedCompute<T extends SupportedFheType>({ lhsHandle,
|
|
|
35
37
|
walletClient: WalletClient<Transport, Chain, Account>;
|
|
36
38
|
kmsQuorumClient: KmsQuorumClient;
|
|
37
39
|
chainId: SupportedChainId;
|
|
40
|
+
reencryptPubKey: Uint8Array;
|
|
41
|
+
reencryptKeypair: Secp256k1Keypair;
|
|
42
|
+
}): Promise<DecryptionAttestation<EciesScheme, T>>;
|
|
43
|
+
export declare function attestedCompute<T extends SupportedFheType>({ executorAddress, lhsHandle, op, rhsPlaintext, backoffConfig, walletClient, kmsQuorumClient, chainId, reencryptPubKey, }: {
|
|
44
|
+
executorAddress: HexString;
|
|
45
|
+
lhsHandle: HexString;
|
|
46
|
+
op: AttestedComputeOP;
|
|
47
|
+
rhsPlaintext: bigint | boolean;
|
|
48
|
+
backoffConfig?: Partial<BackoffConfig> | undefined;
|
|
49
|
+
walletClient: WalletClient<Transport, Chain, Account>;
|
|
50
|
+
kmsQuorumClient: KmsQuorumClient;
|
|
51
|
+
chainId: SupportedChainId;
|
|
52
|
+
reencryptPubKey: Uint8Array;
|
|
53
|
+
reencryptKeypair?: never;
|
|
54
|
+
}): Promise<EncryptedDecryptionAttestation<EciesScheme, T>>;
|
|
55
|
+
export declare function attestedCompute<T extends SupportedFheType>({ executorAddress, lhsHandle, op, rhsPlaintext, backoffConfig, walletClient, kmsQuorumClient, chainId, }: {
|
|
56
|
+
executorAddress: HexString;
|
|
57
|
+
lhsHandle: HexString;
|
|
58
|
+
op: AttestedComputeOP;
|
|
59
|
+
rhsPlaintext: bigint | boolean;
|
|
60
|
+
backoffConfig?: Partial<BackoffConfig> | undefined;
|
|
61
|
+
walletClient: WalletClient<Transport, Chain, Account>;
|
|
62
|
+
kmsQuorumClient: KmsQuorumClient;
|
|
63
|
+
chainId: SupportedChainId;
|
|
64
|
+
reencryptPubKey?: never;
|
|
65
|
+
reencryptKeypair?: never;
|
|
38
66
|
}): Promise<DecryptionAttestation<EciesScheme, T>>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Account, Chain, Transport, WalletClient } from 'viem';
|
|
1
|
+
import type { Account, Chain, PublicClient, Transport, WalletClient } from 'viem';
|
|
2
2
|
import { type HexString } from '../binary.js';
|
|
3
3
|
import { type SupportedChainId } from '../chain.js';
|
|
4
4
|
import { type EciesScheme, type SupportedFheType } from '../encryption/encryption.js';
|
|
@@ -7,7 +7,8 @@ import type { Secp256k1Keypair } from '../lite/ecies.js';
|
|
|
7
7
|
import type { BackoffConfig } from '../retry.js';
|
|
8
8
|
import { type DecryptionAttestation, type EncryptedDecryptionAttestation } from './types.js';
|
|
9
9
|
export declare const ATTESTED_DECRYPT_DOMAIN_NAME = "IncoAttestedDecrypt";
|
|
10
|
-
export declare const
|
|
10
|
+
export declare const DEFAULT_ATTESTED_DECRYPT_DOMAIN_VERSION = "2";
|
|
11
|
+
export declare const TEST_RPC_URL = "UNUSED IN TEST";
|
|
11
12
|
/**
|
|
12
13
|
* Arguments for creating an attested decrypt request.
|
|
13
14
|
*/
|
|
@@ -27,11 +28,12 @@ export interface IncoLiteAttestedDecryptorArgs {
|
|
|
27
28
|
* @returns A function that can decrypt handles and return an attestation
|
|
28
29
|
* @throws {AttestedDecryptError} If the creation fails
|
|
29
30
|
*/
|
|
30
|
-
export declare function attestedDecrypt({ handles, backoffConfig, chainId, kmsQuorumClient, }: {
|
|
31
|
+
export declare function attestedDecrypt({ handles, backoffConfig, chainId, kmsQuorumClient, executorAddress, }: {
|
|
31
32
|
handles: HexString[];
|
|
32
33
|
backoffConfig?: Partial<BackoffConfig> | undefined;
|
|
33
34
|
chainId: SupportedChainId;
|
|
34
35
|
kmsQuorumClient: KmsQuorumClient;
|
|
36
|
+
executorAddress: HexString;
|
|
35
37
|
}): Promise<Array<DecryptionAttestation<EciesScheme, SupportedFheType>>>;
|
|
36
38
|
/**
|
|
37
39
|
* Decrypt multiple handles in a single attested request.
|
|
@@ -41,7 +43,7 @@ export declare function attestedDecrypt({ handles, backoffConfig, chainId, kmsQu
|
|
|
41
43
|
* @returns A function that can decrypt handles and return an attestation
|
|
42
44
|
* @throws {AttestedDecryptError} If the creation fails
|
|
43
45
|
*/
|
|
44
|
-
export declare function attestedDecrypt({ handles, backoffConfig, walletClient, chainId, reencryptPubKey, reencryptKeypair, kmsQuorumClient, }: {
|
|
46
|
+
export declare function attestedDecrypt({ handles, backoffConfig, walletClient, chainId, reencryptPubKey, reencryptKeypair, kmsQuorumClient, executorAddress, }: {
|
|
45
47
|
handles: HexString[];
|
|
46
48
|
backoffConfig?: Partial<BackoffConfig> | undefined;
|
|
47
49
|
walletClient: WalletClient<Transport, Chain, Account>;
|
|
@@ -49,6 +51,7 @@ export declare function attestedDecrypt({ handles, backoffConfig, walletClient,
|
|
|
49
51
|
reencryptPubKey: Uint8Array;
|
|
50
52
|
reencryptKeypair: Secp256k1Keypair;
|
|
51
53
|
kmsQuorumClient: KmsQuorumClient;
|
|
54
|
+
executorAddress: HexString;
|
|
52
55
|
}): Promise<Array<DecryptionAttestation<EciesScheme, SupportedFheType>>>;
|
|
53
56
|
/**
|
|
54
57
|
* Decrypt multiple handles in a single attested request.
|
|
@@ -58,7 +61,7 @@ export declare function attestedDecrypt({ handles, backoffConfig, walletClient,
|
|
|
58
61
|
* @returns A function that can decrypt handles and return an attestation
|
|
59
62
|
* @throws {AttestedDecryptError} If the creation fails
|
|
60
63
|
*/
|
|
61
|
-
export declare function attestedDecrypt({ handles, backoffConfig, walletClient, chainId, reencryptPubKey, kmsQuorumClient, }: {
|
|
64
|
+
export declare function attestedDecrypt({ handles, backoffConfig, walletClient, chainId, reencryptPubKey, kmsQuorumClient, executorAddress, }: {
|
|
62
65
|
handles: HexString[];
|
|
63
66
|
backoffConfig?: Partial<BackoffConfig> | undefined;
|
|
64
67
|
walletClient: WalletClient<Transport, Chain, Account>;
|
|
@@ -66,6 +69,7 @@ export declare function attestedDecrypt({ handles, backoffConfig, walletClient,
|
|
|
66
69
|
reencryptPubKey: Uint8Array;
|
|
67
70
|
reencryptKeypair?: never;
|
|
68
71
|
kmsQuorumClient: KmsQuorumClient;
|
|
72
|
+
executorAddress: HexString;
|
|
69
73
|
}): Promise<Array<EncryptedDecryptionAttestation<EciesScheme, SupportedFheType>>>;
|
|
70
74
|
/**
|
|
71
75
|
* Decrypt multiple handles in a single attested request.
|
|
@@ -75,7 +79,7 @@ export declare function attestedDecrypt({ handles, backoffConfig, walletClient,
|
|
|
75
79
|
* @returns A function that can decrypt handles and return an attestation
|
|
76
80
|
* @throws {AttestedDecryptError} If the creation fails
|
|
77
81
|
*/
|
|
78
|
-
export declare function attestedDecrypt({ handles, backoffConfig, walletClient, chainId, kmsQuorumClient, }: {
|
|
82
|
+
export declare function attestedDecrypt({ handles, backoffConfig, walletClient, chainId, kmsQuorumClient, executorAddress, }: {
|
|
79
83
|
handles: HexString[];
|
|
80
84
|
backoffConfig?: Partial<BackoffConfig> | undefined;
|
|
81
85
|
walletClient: WalletClient<Transport, Chain, Account>;
|
|
@@ -83,7 +87,9 @@ export declare function attestedDecrypt({ handles, backoffConfig, walletClient,
|
|
|
83
87
|
reencryptPubKey?: never;
|
|
84
88
|
reencryptKeypair?: never;
|
|
85
89
|
kmsQuorumClient: KmsQuorumClient;
|
|
90
|
+
executorAddress: HexString;
|
|
86
91
|
}): Promise<Array<DecryptionAttestation<EciesScheme, SupportedFheType>>>;
|
|
92
|
+
export declare function fetchEip712DomainVersion(executorAddress: HexString | undefined, defaultVersion: string, walletClient?: WalletClient<Transport, Chain, Account> | PublicClient<Transport, Chain>): Promise<string>;
|
|
87
93
|
export declare function decryptEncryptedAttestations(attestations: Array<DecryptionAttestation<EciesScheme, SupportedFheType> | EncryptedDecryptionAttestation<EciesScheme, SupportedFheType>>, reencryptKeypair: Secp256k1Keypair): Promise<Array<DecryptionAttestation<EciesScheme, SupportedFheType>>>;
|
|
88
94
|
/**
|
|
89
95
|
* Validates a handle format.
|
|
@@ -16,6 +16,7 @@ export type DecryptionAttestation<S extends EncryptionScheme, T extends Supporte
|
|
|
16
16
|
export type EncryptedDecryptionAttestation<S extends EncryptionScheme, T extends SupportedFheType> = {
|
|
17
17
|
handle: HexString;
|
|
18
18
|
encryptedPlaintext: EncryptResultOf<S, T>;
|
|
19
|
+
encryptedSignatures: Uint8Array[];
|
|
19
20
|
covalidatorSignatures: Uint8Array[];
|
|
20
21
|
};
|
|
21
22
|
export type AttestedDecryptor<S extends EncryptionScheme> = <T extends SupportedFheType>(args: AttestedDecryptFnArgs<S, T>) => Promise<DecryptionAttestation<S, T>>;
|
|
@@ -146,10 +146,23 @@ export type AttestedComputeRequest = Message<"inco.kms.lite.v1.AttestedComputeRe
|
|
|
146
146
|
* @generated from field: string user_address = 1;
|
|
147
147
|
*/
|
|
148
148
|
userAddress: string;
|
|
149
|
+
/**
|
|
150
|
+
* reencrypt_pub_key is the encoding of the user's public
|
|
151
|
+
* encryption key (secp256k1) used to reencrypt the result for.
|
|
152
|
+
* It is encoded in its 33-byte compressed format.
|
|
153
|
+
* If empty, the KMS will return plaintext decryption instead of reencryption.
|
|
154
|
+
*
|
|
155
|
+
* @generated from field: bytes reencrypt_pub_key = 2;
|
|
156
|
+
*/
|
|
157
|
+
reencryptPubKey: Uint8Array;
|
|
149
158
|
/**
|
|
150
159
|
* eip712_signature is an EIP-712 signature of the following EIP-712 typed data by
|
|
151
160
|
* `user_address` (note that we only give a JSON representation for the sake of
|
|
152
|
-
* readability, but the actual signed data is defined in the EIP-712 spec):
|
|
161
|
+
* readability, but the actual signed data is defined in the EIP-712 spec) where:
|
|
162
|
+
* op - operation to perform
|
|
163
|
+
* lhs - handle of the ciphertext to perform computation on
|
|
164
|
+
* rhs - second plaintext scalar operand
|
|
165
|
+
* publicKey - 0x prefixed reencrypt_pub_key (if any). "0x" otherwise if empty.
|
|
153
166
|
*
|
|
154
167
|
* ```json
|
|
155
168
|
* {
|
|
@@ -160,9 +173,10 @@ export type AttestedComputeRequest = Message<"inco.kms.lite.v1.AttestedComputeRe
|
|
|
160
173
|
* { "name": "chainId", "type": "uint256" }
|
|
161
174
|
* ],
|
|
162
175
|
* "AttestedComputeRequest": [
|
|
163
|
-
* { "name": "op", "type" "uint8"},
|
|
164
|
-
* { "name": "lhs", "type" "bytes32"},
|
|
165
|
-
* { "name": "rhs", "type" "bytes32"}
|
|
176
|
+
* { "name": "op", "type": "uint8"},
|
|
177
|
+
* { "name": "lhs", "type": "bytes32"},
|
|
178
|
+
* { "name": "rhs", "type": "bytes32"},
|
|
179
|
+
* { "name": "publicKey", "type": "bytes" },
|
|
166
180
|
* ]
|
|
167
181
|
* },
|
|
168
182
|
* "primaryType": "AttestedComputeRequest",
|
|
@@ -174,18 +188,19 @@ export type AttestedComputeRequest = Message<"inco.kms.lite.v1.AttestedComputeRe
|
|
|
174
188
|
* "message": {
|
|
175
189
|
* "op": <operation>,
|
|
176
190
|
* "lhs": "<handle1>",
|
|
177
|
-
* "rhs": <plaintextBytes
|
|
191
|
+
* "rhs": <plaintextBytes>, // Also add a comment on length & encoding
|
|
192
|
+
* "publicKey": "0x<reencrypt_pub_key>"
|
|
178
193
|
* }
|
|
179
194
|
* }
|
|
180
195
|
* ```
|
|
181
196
|
*
|
|
182
|
-
* @generated from field: bytes eip712_signature =
|
|
197
|
+
* @generated from field: bytes eip712_signature = 3;
|
|
183
198
|
*/
|
|
184
199
|
eip712Signature: Uint8Array;
|
|
185
200
|
/**
|
|
186
201
|
* Subset of supported binary operations that can be performed on a handle.
|
|
187
202
|
*
|
|
188
|
-
* @generated from field: inco.kms.lite.v1.SupportedScalarBinaryOp op =
|
|
203
|
+
* @generated from field: inco.kms.lite.v1.SupportedScalarBinaryOp op = 4;
|
|
189
204
|
*/
|
|
190
205
|
op: SupportedScalarBinaryOp;
|
|
191
206
|
/**
|
|
@@ -193,13 +208,13 @@ export type AttestedComputeRequest = Message<"inco.kms.lite.v1.AttestedComputeRe
|
|
|
193
208
|
* The user_address must have ACL access to the handle for the attested
|
|
194
209
|
* compute to succeed.
|
|
195
210
|
*
|
|
196
|
-
* @generated from field: string lhs_handle =
|
|
211
|
+
* @generated from field: string lhs_handle = 5;
|
|
197
212
|
*/
|
|
198
213
|
lhsHandle: string;
|
|
199
214
|
/**
|
|
200
215
|
* Second plaintext scalar operand encoded as a hex string (with or without 0x prefix)
|
|
201
216
|
*
|
|
202
|
-
* @generated from field: string rhs_plaintext =
|
|
217
|
+
* @generated from field: string rhs_plaintext = 6;
|
|
203
218
|
*/
|
|
204
219
|
rhsPlaintext: string;
|
|
205
220
|
/**
|
|
@@ -207,7 +222,7 @@ export type AttestedComputeRequest = Message<"inco.kms.lite.v1.AttestedComputeRe
|
|
|
207
222
|
* Either the user_address or sharer must have ACL access to the handles for the attested
|
|
208
223
|
* compute to succeed.
|
|
209
224
|
*
|
|
210
|
-
* @generated from field: inco.kms.lite.v1.ACLProof acl_proof =
|
|
225
|
+
* @generated from field: inco.kms.lite.v1.ACLProof acl_proof = 7;
|
|
211
226
|
*/
|
|
212
227
|
aclProof?: ACLProof;
|
|
213
228
|
};
|
|
@@ -303,12 +318,11 @@ export type Reencryption = Message<"inco.kms.lite.v1.Reencryption"> & {
|
|
|
303
318
|
*/
|
|
304
319
|
userCiphertext: Uint8Array;
|
|
305
320
|
/**
|
|
306
|
-
*
|
|
307
|
-
* TODO scalar declaration.
|
|
321
|
+
* Encrypted signature over the plaintext, encrypted to the user's public key. Can only be decrypted by the user.
|
|
308
322
|
*
|
|
309
|
-
* @generated from field:
|
|
323
|
+
* @generated from field: bytes encrypted_signature = 3;
|
|
310
324
|
*/
|
|
311
|
-
|
|
325
|
+
encryptedSignature: Uint8Array;
|
|
312
326
|
};
|
|
313
327
|
/**
|
|
314
328
|
* Describes the message inco.kms.lite.v1.Reencryption.
|
|
@@ -29,7 +29,7 @@ export declare class KmsQuorumClient {
|
|
|
29
29
|
*/
|
|
30
30
|
static fromKmsClients(kmsClients: KmsClient[], threshold: number): KmsQuorumClient;
|
|
31
31
|
attestedDecrypt(request: AttestedDecryptRequest, backoffConfig?: Partial<BackoffConfig>): Promise<(DecryptionAttestation<EciesScheme, SupportedFheType> | EncryptedDecryptionAttestation<EciesScheme, SupportedFheType>)[]>;
|
|
32
|
-
attestedCompute(request: AttestedComputeRequest, backoffConfig?: Partial<BackoffConfig>): Promise<DecryptionAttestation<EciesScheme, SupportedFheType>>;
|
|
32
|
+
attestedCompute(request: AttestedComputeRequest, backoffConfig?: Partial<BackoffConfig>): Promise<DecryptionAttestation<EciesScheme, SupportedFheType> | EncryptedDecryptionAttestation<EciesScheme, SupportedFheType>>;
|
|
33
33
|
attestedReveal(request: AttestedRevealRequest, backoffConfig?: Partial<BackoffConfig>): Promise<(DecryptionAttestation<EciesScheme, SupportedFheType> | EncryptedDecryptionAttestation<EciesScheme, SupportedFheType>)[]>;
|
|
34
34
|
/**
|
|
35
35
|
* Generic method to execute a KMS operation across all clients with retry and threshold logic.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ATTESTED_COMPUTE_DOMAIN_NAME,
|
|
1
|
+
import { ATTESTED_COMPUTE_DOMAIN_NAME, DEFAULT_ATTESTED_COMPUTE_DOMAIN_VERSION, type IncoLiteAttestedComputeArgs } from '../attestedcompute/attested-compute.js';
|
|
2
2
|
import type { AttestedCompute, AttestedComputeFnArgs } from '../attestedcompute/types.js';
|
|
3
3
|
import { AttestedComputeSupportedOps } from '../attestedcompute/types.js';
|
|
4
4
|
import type { AttestedDecryptFnArgs } from '../attesteddecrypt/types.js';
|
|
5
|
-
export { ATTESTED_COMPUTE_DOMAIN_NAME,
|
|
5
|
+
export { ATTESTED_COMPUTE_DOMAIN_NAME, AttestedComputeSupportedOps, DEFAULT_ATTESTED_COMPUTE_DOMAIN_VERSION, };
|
|
6
6
|
export type { AttestedCompute, AttestedComputeFnArgs, AttestedDecryptFnArgs, IncoLiteAttestedComputeArgs, };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { type IncoLiteAttestedDecryptorArgs } from '../attesteddecrypt/attested-decrypt.js';
|
|
2
2
|
export type { IncoLiteAttestedDecryptorArgs };
|
|
3
|
-
import { ATTESTED_DECRYPT_DOMAIN_NAME,
|
|
4
|
-
export { ATTESTED_DECRYPT_DOMAIN_NAME,
|
|
3
|
+
import { ATTESTED_DECRYPT_DOMAIN_NAME, DEFAULT_ATTESTED_DECRYPT_DOMAIN_VERSION } from '../attesteddecrypt/attested-decrypt.js';
|
|
4
|
+
export { ATTESTED_DECRYPT_DOMAIN_NAME, DEFAULT_ATTESTED_DECRYPT_DOMAIN_VERSION, };
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import * as ellipticPkg from 'elliptic';
|
|
2
2
|
import { Decryptor, EciesScheme, Encryptor } from '../encryption/encryption.js';
|
|
3
3
|
import { PubKeyEncodable } from '../reencryption/index.js';
|
|
4
|
+
export declare const TEST_ECIES_PUB_KEY = "0x02516bda9e68a1c3dce74dc1b6ed7d91a91d51c1e1933947f06331cef59631e9eb";
|
|
5
|
+
export declare const TEST_ECIES_PRIVATE_KEY = "0x384a707568ab63ad2ad9f10135faa0699801db3174f33f7846badc11affb8f57";
|
|
4
6
|
export interface Secp256k1Keypair extends PubKeyEncodable {
|
|
5
7
|
scheme: EciesScheme;
|
|
6
8
|
kp: ellipticPkg.ec.KeyPair;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import { Account, Chain, PublicClient, Transport, WalletClient } from 'viem';
|
|
1
|
+
import { Account, Chain, GetContractReturnType, PublicClient, Transport, WalletClient } from 'viem';
|
|
2
2
|
import { AllowanceVoucherWithSig } from '../advancedacl/types.js';
|
|
3
3
|
import { AttestedComputeOP } from '../attestedcompute/types.js';
|
|
4
4
|
import { DecryptionAttestation, EncryptedDecryptionAttestation } from '../attesteddecrypt/index.js';
|
|
5
5
|
import { Address, HexString } from '../binary.js';
|
|
6
|
-
import { EciesScheme,
|
|
6
|
+
import { EciesScheme, SupportedFheType } from '../encryption/index.js';
|
|
7
|
+
import { incoVerifierAbi } from '../generated/abis/verifier.js';
|
|
7
8
|
import { lightningDeployments } from '../generated/lightning.js';
|
|
8
9
|
import { localNodeLightningConfig } from '../generated/local-node.js';
|
|
10
|
+
import { FheType } from '../handle.js';
|
|
9
11
|
import { LocalNodeEnv } from '../local/index.js';
|
|
10
12
|
import { BackoffConfig } from '../retry.js';
|
|
11
13
|
import { Secp256k1Keypair } from './ecies.js';
|
|
@@ -22,6 +24,7 @@ export type SupportedNativeType = boolean | bigint | number;
|
|
|
22
24
|
export type EncryptionContext = {
|
|
23
25
|
accountAddress: string;
|
|
24
26
|
dappAddress: string;
|
|
27
|
+
handleType: FheType;
|
|
25
28
|
};
|
|
26
29
|
export type DeploymentSlice = {
|
|
27
30
|
executorAddress: string;
|
|
@@ -36,6 +39,11 @@ export type CustomConfig = {
|
|
|
36
39
|
senderPrivateKey?: HexString;
|
|
37
40
|
};
|
|
38
41
|
export type CustomDeployment = DeploymentSlice & CustomConfig;
|
|
42
|
+
export type IncoVerifierConfig = {
|
|
43
|
+
threshold: number;
|
|
44
|
+
signers: Address[];
|
|
45
|
+
eciesPubKey: HexString;
|
|
46
|
+
};
|
|
39
47
|
type LocalNodeEnvFileSource = {
|
|
40
48
|
filePath: string;
|
|
41
49
|
};
|
|
@@ -45,13 +53,15 @@ type LocalNodeEnvFileSource = {
|
|
|
45
53
|
*/
|
|
46
54
|
export declare class Lightning<T extends DeploymentSlice = DeploymentSlice> {
|
|
47
55
|
private readonly _deployment;
|
|
48
|
-
readonly covalidatorUrls
|
|
49
|
-
readonly signers
|
|
50
|
-
readonly threshold
|
|
56
|
+
private readonly covalidatorUrls;
|
|
57
|
+
private readonly signers;
|
|
58
|
+
private readonly threshold;
|
|
59
|
+
private readonly eciesPubKey;
|
|
51
60
|
readonly executorAddress: Address;
|
|
52
61
|
readonly chainId: bigint;
|
|
53
62
|
private readonly ephemeralKeypair;
|
|
54
63
|
private readonly kmsQuorumClient;
|
|
64
|
+
private readonly encryptor;
|
|
55
65
|
private constructor();
|
|
56
66
|
/**
|
|
57
67
|
* Get a Lightning instance bound to the latest Lightning deployment for the Base Sepolia testnet.
|
|
@@ -92,7 +102,6 @@ export declare class Lightning<T extends DeploymentSlice = DeploymentSlice> {
|
|
|
92
102
|
* additional fields past will be made available as part of the `deployment` property.
|
|
93
103
|
*/
|
|
94
104
|
static custom<T extends CustomConfig>(config: T): Promise<Lightning<DeploymentSlice & T>>;
|
|
95
|
-
static getEciesPublicKey(client: PublicClient, executorAddress: Address): Promise<HexString>;
|
|
96
105
|
/**
|
|
97
106
|
* Get the latest deployment for a given pepper, which usually denotes a family of deployments distinct from their
|
|
98
107
|
* version such as 'devnet', 'testnet', 'mainnet', etc.
|
|
@@ -117,15 +126,13 @@ export declare class Lightning<T extends DeploymentSlice = DeploymentSlice> {
|
|
|
117
126
|
* @param value a boolean or numeric value to encrypt
|
|
118
127
|
* @param accountAddress the address of the account interacting with the dapp contract, normally an Externally Owned Account (EOA)
|
|
119
128
|
* @param dappAddress the address of the dapp contract that interacts with the Inco Lightning contract or library
|
|
129
|
+
* @param handleType (optional) the handle type to be used for encrypting the value - this is required in case of non-default handle types
|
|
130
|
+
* default handle types:
|
|
131
|
+
* - boolean -> handleTypes.ebool
|
|
132
|
+
* - number | bigint -> handleTypes.euint256
|
|
133
|
+
* @returns a promise that resolves to the encrypted value as a HexString
|
|
120
134
|
*/
|
|
121
|
-
encrypt<T extends SupportedNativeType>(value: T, { accountAddress, dappAddress }: EncryptionContext
|
|
122
|
-
/**
|
|
123
|
-
* Get the encryptor for a specific ECIES public key.
|
|
124
|
-
*
|
|
125
|
-
* @param eciesPubkey the ECIES public key to use for encryption
|
|
126
|
-
* @returns an Encryptor instance configured for the specified ECIES public key
|
|
127
|
-
*/
|
|
128
|
-
getEncryptor(eciesPubkey: HexString): Encryptor<EciesScheme>;
|
|
135
|
+
encrypt<T extends SupportedNativeType>(value: T, { accountAddress, dappAddress, handleType }: EncryptionContext): Promise<HexString>;
|
|
129
136
|
/**
|
|
130
137
|
* Grants a session key allowance voucher for secure reencryption operations.
|
|
131
138
|
*
|
|
@@ -198,6 +205,7 @@ export declare class Lightning<T extends DeploymentSlice = DeploymentSlice> {
|
|
|
198
205
|
*
|
|
199
206
|
* @param ephemeralKeypair Session keypair matching the voucher grantee.
|
|
200
207
|
* @param allowanceVoucherWithSig Signed allowance voucher.
|
|
208
|
+
* @param ethClient - A public eth client or eth wallet client used for signing the attested decrypt request
|
|
201
209
|
* @param handles Handles to decrypt.
|
|
202
210
|
* @param options Optional reencryption/backoff configuration.
|
|
203
211
|
*
|
|
@@ -206,6 +214,7 @@ export declare class Lightning<T extends DeploymentSlice = DeploymentSlice> {
|
|
|
206
214
|
* const attestations = await lightning.attestedDecryptWithVoucher(
|
|
207
215
|
* ephemeralKeypair,
|
|
208
216
|
* voucher,
|
|
217
|
+
* ethClient,
|
|
209
218
|
* [handle],
|
|
210
219
|
* );
|
|
211
220
|
* ```
|
|
@@ -215,14 +224,15 @@ export declare class Lightning<T extends DeploymentSlice = DeploymentSlice> {
|
|
|
215
224
|
* const encrypted = await lightning.attestedDecryptWithVoucher(
|
|
216
225
|
* ephemeralKeypair,
|
|
217
226
|
* voucher,
|
|
227
|
+
* ethClient,
|
|
218
228
|
* [handle],
|
|
219
229
|
* { reencryptPubKey: delegateKeypair.encodePublicKey() },
|
|
220
230
|
* );
|
|
221
231
|
* ```
|
|
222
232
|
*/
|
|
223
|
-
attestedDecryptWithVoucher(ephemeralKeypair: Secp256k1Keypair, allowanceVoucherWithSig: AllowanceVoucherWithSig, handles: HexString[], backoffConfig?: Partial<BackoffConfig>): Promise<Array<DecryptionAttestation<EciesScheme, SupportedFheType>>>;
|
|
224
|
-
attestedDecryptWithVoucher(ephemeralKeypair: Secp256k1Keypair, allowanceVoucherWithSig: AllowanceVoucherWithSig, handles: HexString[], reencryptPubKey: Uint8Array, backoffConfig?: Partial<BackoffConfig>): Promise<Array<EncryptedDecryptionAttestation<EciesScheme, SupportedFheType>>>;
|
|
225
|
-
attestedDecryptWithVoucher(ephemeralKeypair: Secp256k1Keypair, allowanceVoucherWithSig: AllowanceVoucherWithSig, handles: HexString[], reencryptPubKey: Uint8Array, reencryptKeypair: Secp256k1Keypair, backoffConfig?: Partial<BackoffConfig>): Promise<Array<DecryptionAttestation<EciesScheme, SupportedFheType>>>;
|
|
233
|
+
attestedDecryptWithVoucher(ephemeralKeypair: Secp256k1Keypair, allowanceVoucherWithSig: AllowanceVoucherWithSig, ethClient: PublicClient<Transport, Chain> | WalletClient<Transport, Chain, Account>, handles: HexString[], backoffConfig?: Partial<BackoffConfig>): Promise<Array<DecryptionAttestation<EciesScheme, SupportedFheType>>>;
|
|
234
|
+
attestedDecryptWithVoucher(ephemeralKeypair: Secp256k1Keypair, allowanceVoucherWithSig: AllowanceVoucherWithSig, ethClient: PublicClient<Transport, Chain> | WalletClient<Transport, Chain, Account>, handles: HexString[], reencryptPubKey: Uint8Array, backoffConfig?: Partial<BackoffConfig>): Promise<Array<EncryptedDecryptionAttestation<EciesScheme, SupportedFheType>>>;
|
|
235
|
+
attestedDecryptWithVoucher(ephemeralKeypair: Secp256k1Keypair, allowanceVoucherWithSig: AllowanceVoucherWithSig, ethClient: PublicClient<Transport, Chain> | WalletClient<Transport, Chain, Account>, handles: HexString[], reencryptPubKey: Uint8Array, reencryptKeypair: Secp256k1Keypair, backoffConfig?: Partial<BackoffConfig>): Promise<Array<DecryptionAttestation<EciesScheme, SupportedFheType>>>;
|
|
226
236
|
/**
|
|
227
237
|
* Get an attested compute for the given wallet client.
|
|
228
238
|
*
|
|
@@ -233,7 +243,7 @@ export declare class Lightning<T extends DeploymentSlice = DeploymentSlice> {
|
|
|
233
243
|
* @param backoffConfig - The backoff configuration for the attested compute request
|
|
234
244
|
* @returns The decryption attestation
|
|
235
245
|
*
|
|
236
|
-
* @example
|
|
246
|
+
* @example Plaintext result
|
|
237
247
|
* ```typescript
|
|
238
248
|
* import { AttestedComputeSupportedOps } from '../lite/attested-compute.js';
|
|
239
249
|
* const lhsHandle = '0x...';
|
|
@@ -242,23 +252,80 @@ export declare class Lightning<T extends DeploymentSlice = DeploymentSlice> {
|
|
|
242
252
|
* const response = await lightning.attestedCompute(walletClient, lhsHandle, op, rhsPlaintext);
|
|
243
253
|
* const { plaintext, covalidatorSignature, handle } = response;
|
|
244
254
|
* ```
|
|
255
|
+
*
|
|
256
|
+
* @example Reencrypt for a delegate
|
|
257
|
+
* ```ts
|
|
258
|
+
* const encrypted = await lightning.attestedCompute(
|
|
259
|
+
* walletClient,
|
|
260
|
+
* lhsHandle,
|
|
261
|
+
* op,
|
|
262
|
+
* rhsPlaintext,
|
|
263
|
+
* delegatePubKey,
|
|
264
|
+
* );
|
|
265
|
+
* console.log(encrypted.encryptedPlaintext.ciphertext.value);
|
|
266
|
+
* ```
|
|
267
|
+
*
|
|
268
|
+
* @example Reencrypt and decrypt locally
|
|
269
|
+
* ```ts
|
|
270
|
+
* const decrypted = await lightning.attestedCompute(
|
|
271
|
+
* walletClient,
|
|
272
|
+
* lhsHandle,
|
|
273
|
+
* op,
|
|
274
|
+
* rhsPlaintext,
|
|
275
|
+
* keypair.encodePublicKey(),
|
|
276
|
+
* keypair,
|
|
277
|
+
* );
|
|
278
|
+
* console.log(decrypted.plaintext.value);
|
|
279
|
+
* ```
|
|
245
280
|
*/
|
|
246
281
|
attestedCompute(walletClient: WalletClient<Transport, Chain, Account>, lhsHandle: HexString, op: AttestedComputeOP, rhsPlaintext: bigint | boolean, backoffConfig?: Partial<BackoffConfig>): Promise<DecryptionAttestation<EciesScheme, SupportedFheType>>;
|
|
282
|
+
attestedCompute(walletClient: WalletClient<Transport, Chain, Account>, lhsHandle: HexString, op: AttestedComputeOP, rhsPlaintext: bigint | boolean, reencryptPubKey: Uint8Array, backoffConfig?: Partial<BackoffConfig>): Promise<EncryptedDecryptionAttestation<EciesScheme, SupportedFheType>>;
|
|
283
|
+
attestedCompute(walletClient: WalletClient<Transport, Chain, Account>, lhsHandle: HexString, op: AttestedComputeOP, rhsPlaintext: bigint | boolean, reencryptPubKey: Uint8Array, reencryptKeypair: Secp256k1Keypair, backoffConfig?: Partial<BackoffConfig>): Promise<DecryptionAttestation<EciesScheme, SupportedFheType>>;
|
|
247
284
|
/**
|
|
248
285
|
* Performs attested compute via a voucher-backed session key.
|
|
249
286
|
*
|
|
250
|
-
* @example
|
|
287
|
+
* @example Plaintext result
|
|
251
288
|
* ```ts
|
|
252
289
|
* const attestation = await lightning.attestedComputeWithVoucher(
|
|
253
290
|
* ephemeralKeypair,
|
|
254
291
|
* voucher,
|
|
292
|
+
* ethClient,
|
|
255
293
|
* lhsHandle,
|
|
256
294
|
* AttestedComputeSupportedOps.Eq,
|
|
257
295
|
* true,
|
|
258
296
|
* );
|
|
259
297
|
* ```
|
|
298
|
+
*
|
|
299
|
+
* @example Reencrypt for a delegate
|
|
300
|
+
* ```ts
|
|
301
|
+
* const encrypted = await lightning.attestedComputeWithVoucher(
|
|
302
|
+
* ephemeralKeypair,
|
|
303
|
+
* voucher,
|
|
304
|
+
* lhsHandle,
|
|
305
|
+
* AttestedComputeSupportedOps.Eq,
|
|
306
|
+
* true,
|
|
307
|
+
* delegatePubKey,
|
|
308
|
+
* );
|
|
309
|
+
* console.log(encrypted.encryptedPlaintext.ciphertext.value);
|
|
310
|
+
* ```
|
|
311
|
+
*
|
|
312
|
+
* @example Reencrypt and decrypt locally
|
|
313
|
+
* ```ts
|
|
314
|
+
* const decrypted = await lightning.attestedComputeWithVoucher(
|
|
315
|
+
* ephemeralKeypair,
|
|
316
|
+
* voucher,
|
|
317
|
+
* lhsHandle,
|
|
318
|
+
* AttestedComputeSupportedOps.Eq,
|
|
319
|
+
* true,
|
|
320
|
+
* keypair.encodePublicKey(),
|
|
321
|
+
* keypair,
|
|
322
|
+
* );
|
|
323
|
+
* console.log(decrypted.plaintext.value);
|
|
324
|
+
* ```
|
|
260
325
|
*/
|
|
261
|
-
attestedComputeWithVoucher(ephemeralKeypair: Secp256k1Keypair, allowanceVoucherWithSig: AllowanceVoucherWithSig, lhsHandle: HexString, op: AttestedComputeOP, rhsPlaintext: bigint | boolean, backoffConfig?: Partial<BackoffConfig>): Promise<DecryptionAttestation<EciesScheme, SupportedFheType>>;
|
|
326
|
+
attestedComputeWithVoucher(ephemeralKeypair: Secp256k1Keypair, allowanceVoucherWithSig: AllowanceVoucherWithSig, ethClient: PublicClient<Transport, Chain> | WalletClient<Transport, Chain, Account>, lhsHandle: HexString, op: AttestedComputeOP, rhsPlaintext: bigint | boolean, backoffConfig?: Partial<BackoffConfig>): Promise<DecryptionAttestation<EciesScheme, SupportedFheType>>;
|
|
327
|
+
attestedComputeWithVoucher(ephemeralKeypair: Secp256k1Keypair, allowanceVoucherWithSig: AllowanceVoucherWithSig, ethClient: PublicClient<Transport, Chain> | WalletClient<Transport, Chain, Account>, lhsHandle: HexString, op: AttestedComputeOP, rhsPlaintext: bigint | boolean, reencryptPubKey: Uint8Array, backoffConfig?: Partial<BackoffConfig>): Promise<EncryptedDecryptionAttestation<EciesScheme, SupportedFheType>>;
|
|
328
|
+
attestedComputeWithVoucher(ephemeralKeypair: Secp256k1Keypair, allowanceVoucherWithSig: AllowanceVoucherWithSig, ethClient: PublicClient<Transport, Chain> | WalletClient<Transport, Chain, Account>, lhsHandle: HexString, op: AttestedComputeOP, rhsPlaintext: bigint | boolean, reencryptPubKey: Uint8Array, reencryptKeypair: Secp256k1Keypair, backoffConfig?: Partial<BackoffConfig>): Promise<DecryptionAttestation<EciesScheme, SupportedFheType>>;
|
|
262
329
|
/**
|
|
263
330
|
* Get an decryption of publicly revealed handles.
|
|
264
331
|
*
|
|
@@ -268,7 +335,7 @@ export declare class Lightning<T extends DeploymentSlice = DeploymentSlice> {
|
|
|
268
335
|
*
|
|
269
336
|
* @example
|
|
270
337
|
* ```typescript
|
|
271
|
-
* const response = await lightning.attestedReveal([handle1, handle2]);
|
|
338
|
+
* const response = await lightning.attestedReveal([handle1, handle2], ethClient);
|
|
272
339
|
* const { plaintext, covalidatorSignature } = response[0];
|
|
273
340
|
* ```
|
|
274
341
|
*/
|
|
@@ -281,8 +348,17 @@ export declare class Lightning<T extends DeploymentSlice = DeploymentSlice> {
|
|
|
281
348
|
}, threshold: number): string[];
|
|
282
349
|
private static isIdByName;
|
|
283
350
|
private static plaintextFromValue;
|
|
284
|
-
|
|
285
|
-
|
|
351
|
+
static getEciesPublicKey(client: PublicClient, executorAddress: Address): Promise<HexString>;
|
|
352
|
+
static getIncoVerifierContract(client: PublicClient, executorAddress: Address): Promise<GetContractReturnType<typeof incoVerifierAbi, PublicClient, Address>>;
|
|
353
|
+
/**
|
|
354
|
+
* Retrieves the verifier contract details including threshold, signers, and ECIES public key from the Inco Verifier contract.
|
|
355
|
+
*
|
|
356
|
+
* @param executorAddress The address of the Inco Lightning executor contract.
|
|
357
|
+
* @param client The public client to interact with the blockchain.
|
|
358
|
+
* @returns An object containing the threshold, signers, and ECIES public key.
|
|
359
|
+
*/
|
|
360
|
+
private static getVerifierContractDetails;
|
|
361
|
+
private static getChainConfig;
|
|
286
362
|
private static supportsThresholdRetrieval;
|
|
287
363
|
private static getDefaultThresholdAndSigners;
|
|
288
364
|
}
|
package/dist/types/viem.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Chain } from 'viem';
|
|
1
2
|
import { Chainish } from './chain.js';
|
|
2
3
|
export declare const chains: {
|
|
3
4
|
sepolia: {
|
|
@@ -777,7 +778,4 @@ export declare const chains: {
|
|
|
777
778
|
readonly network: "worldchain-sepolia";
|
|
778
779
|
};
|
|
779
780
|
};
|
|
780
|
-
|
|
781
|
-
export type ViemChain = (typeof chains)[ChainName];
|
|
782
|
-
export declare function getViemChain(chainish: Chainish): ViemChain;
|
|
783
|
-
export {};
|
|
781
|
+
export declare function getViemChain(chainish: Chainish): Chain;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inco/js",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.2",
|
|
4
4
|
"repository": "https://github.com/Inco-fhevm/inco-monorepo",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -96,7 +96,7 @@
|
|
|
96
96
|
"effect": "^3.17.13",
|
|
97
97
|
"elliptic": "^6.6.1",
|
|
98
98
|
"sha3": "^2.1.4",
|
|
99
|
-
"viem": "^2.
|
|
99
|
+
"viem": "^2.39.3"
|
|
100
100
|
},
|
|
101
101
|
"devDependencies": {
|
|
102
102
|
"@inco/pega": "0.0.0",
|
|
@@ -113,5 +113,8 @@
|
|
|
113
113
|
"publishConfig": {
|
|
114
114
|
"access": "public",
|
|
115
115
|
"registry": "https://registry.npmjs.org/"
|
|
116
|
+
},
|
|
117
|
+
"browser": {
|
|
118
|
+
"fs/promises": false
|
|
116
119
|
}
|
|
117
120
|
}
|