From bb71be287f0d6b99a3016d5af963913dd88f1d10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20=27birdy=27=20Danjou?= Date: Thu, 7 Mar 2024 16:41:15 +0100 Subject: [PATCH 1/5] chore: add the possibility to force loading of node version --- package.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/package.json b/package.json index 796613c..013fdb6 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,10 @@ "./web": { "import": "./lib/web.js", "require": "./lib/web.js" + }, + "./node": { + "import": "./lib/node.cjs", + "require": "./lib/node.cjs" } }, "scripts": { From 00248e9d032edb2e0042a38c99f6c15326a9997f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20=27birdy=27=20Danjou?= Date: Thu, 7 Mar 2024 16:41:33 +0100 Subject: [PATCH 2/5] feat: add public blockchain configuration in the lib --- src/sdk/index.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/sdk/index.ts b/src/sdk/index.ts index d097bb5..3363e38 100644 --- a/src/sdk/index.ts +++ b/src/sdk/index.ts @@ -60,6 +60,11 @@ export type FhevmInstanceParams = { keypairs?: ExportedContractKeypairs; }; +export const getPublicKeyCallParams = () => ({ + to: '0x000000000000000000000000000000000000005d', + data: '0xd9d47bb001', +}); + export const createInstance = async ( params: FhevmInstanceParams, ): Promise => { From dede4c34680cf670facbb9ac54b9673897a0d69a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20=27birdy=27=20Danjou?= Date: Thu, 7 Mar 2024 18:47:27 +0100 Subject: [PATCH 3/5] feat: add encrypted address --- src/sdk/encrypt.test.ts | 33 +++++++++++++++++++++++++++++++-- src/sdk/encrypt.ts | 14 ++++++++++++++ src/sdk/index.ts | 11 +++++++++++ src/utils.ts | 2 +- 4 files changed, 57 insertions(+), 3 deletions(-) diff --git a/src/sdk/encrypt.test.ts b/src/sdk/encrypt.test.ts index 35b7d61..3abbeaa 100644 --- a/src/sdk/encrypt.test.ts +++ b/src/sdk/encrypt.test.ts @@ -10,6 +10,7 @@ import { CompactFheUint16List, CompactFheUint32List, CompactFheUint64List, + CompactFheUint160List, TfheCompactPublicKey, TfheClientKey, } from 'node-tfhe'; @@ -21,9 +22,10 @@ import { encrypt16, encrypt32, encrypt64, + encryptAddress, } from './encrypt'; -describe('encrypt8', () => { +describe('encrypt', () => { let clientKey: TfheClientKey; let publicKey: TfheCompactPublicKey; @@ -153,7 +155,7 @@ describe('encrypt8', () => { }); }); - it('encrypt/decrypt 64bits', async () => { + it('encrypt/decrypt bigint 64bits', async () => { const buffer = encrypt64(BigInt('18446744073709551615'), publicKey); const compactList = CompactFheUint64List.deserialize(buffer); let encryptedList = compactList.expand(); @@ -162,4 +164,31 @@ describe('encrypt8', () => { expect(decrypted.toString()).toBe('18446744073709551615'); }); }); + it('encrypt/decrypt 0x000... 160bits', async () => { + const buffer = encryptAddress( + '0x0000000000000000000000000000000000000000', + publicKey, + ); + const compactList = CompactFheUint160List.deserialize(buffer); + let encryptedList = compactList.expand(); + encryptedList.forEach((v: FheUint64) => { + const decrypted = v.decrypt(clientKey); + expect(decrypted.toString()).toBe('0'); + }); + }); + + it('encrypt/decrypt 160bits', async () => { + const buffer = encryptAddress( + '0x8ba1f109551bd432803012645ac136ddd64dba72', + publicKey, + ); + const compactList = CompactFheUint160List.deserialize(buffer); + let encryptedList = compactList.expand(); + encryptedList.forEach((v: FheUint64) => { + const decrypted = v.decrypt(clientKey); + expect(decrypted.toString()).toBe( + '797161134358056856230896843146392277790002887282', + ); + }); + }); }); diff --git a/src/sdk/encrypt.ts b/src/sdk/encrypt.ts index 4472f48..f5f3ad3 100644 --- a/src/sdk/encrypt.ts +++ b/src/sdk/encrypt.ts @@ -6,7 +6,9 @@ import { CompactFheUint16List, CompactFheUint32List, CompactFheUint64List, + CompactFheUint160List, } from 'node-tfhe'; +import { fromHexString } from '../utils'; export const encrypt4 = ( value: number, @@ -78,3 +80,15 @@ export const encrypt64 = ( ); return encrypted.serialize(); }; + +export const encryptAddress = ( + value: string, + publicKey: TfheCompactPublicKey, +): Uint8Array => { + // value is something like 0x8ba1f109551bd432803012645ac136ddd64dba72 + const encrypted = CompactFheUint160List.encrypt_with_compact_public_key( + [BigInt(value)] as unknown as any, + publicKey, + ); + return encrypted.serialize(); +}; diff --git a/src/sdk/index.ts b/src/sdk/index.ts index 3363e38..743216e 100644 --- a/src/sdk/index.ts +++ b/src/sdk/index.ts @@ -6,6 +6,7 @@ import { encrypt16, encrypt32, encrypt64, + encryptAddress, encryptBool, } from './encrypt'; import { @@ -24,6 +25,7 @@ export type FhevmInstance = { encrypt16: (value: number | bigint) => Uint8Array; encrypt32: (value: number | bigint) => Uint8Array; encrypt64: (value: number | bigint) => Uint8Array; + encryptAddress: (value: string) => Uint8Array; generatePublicKey: ( options: GeneratePublicKeyParams & { force?: boolean; @@ -185,6 +187,15 @@ export const createInstance = async ( return encrypt64(value, tfheCompactPublicKey); }, + encryptAddress(value) { + if (!tfheCompactPublicKey) + throw new Error( + 'Your instance has been created without the public blockchain key.', + ); + if (!isAddress(value)) throw new Error('Value must be a valid address.'); + return encryptAddress(value, tfheCompactPublicKey); + }, + // Reencryption generatePublicKey(options) { if (!options || !options.verifyingContract) diff --git a/src/utils.ts b/src/utils.ts index 1dfb41d..809d350 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -35,7 +35,7 @@ export const bytesToBigInt = function (byteArray: Uint8Array): bigint { }; export const isAddress = function (address: string) { - if (/^(0x)?[0-9a-f]{40}$/i.test(address.toLowerCase())) { + if (address.match(/^0x[0-9a-fA-F]{40}$/)) { // check if it has the basic requirements of an address return true; } From 859d75e2a62353b128ba288280cfdb5f19a3f327 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20=27birdy=27=20Danjou?= Date: Thu, 7 Mar 2024 18:49:43 +0100 Subject: [PATCH 4/5] chore: remove useless typing --- src/sdk/encrypt.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdk/encrypt.ts b/src/sdk/encrypt.ts index f5f3ad3..c78a214 100644 --- a/src/sdk/encrypt.ts +++ b/src/sdk/encrypt.ts @@ -87,7 +87,7 @@ export const encryptAddress = ( ): Uint8Array => { // value is something like 0x8ba1f109551bd432803012645ac136ddd64dba72 const encrypted = CompactFheUint160List.encrypt_with_compact_public_key( - [BigInt(value)] as unknown as any, + [BigInt(value)], publicKey, ); return encrypted.serialize(); From e0b59ab2adb8085afe21a0c9535b49d308a23b12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20=27birdy=27=20Danjou?= Date: Thu, 7 Mar 2024 18:58:35 +0100 Subject: [PATCH 5/5] test: add more tests --- src/sdk/index.test.ts | 10 ++++++++++ src/sdk/index.ts | 1 + 2 files changed, 11 insertions(+) diff --git a/src/sdk/index.test.ts b/src/sdk/index.test.ts index b5a7902..a86b070 100644 --- a/src/sdk/index.test.ts +++ b/src/sdk/index.test.ts @@ -118,6 +118,10 @@ describe('index', () => { expect(instance.encrypt32(BigInt(838392))).toBeTruthy(); expect(instance.encrypt64(BigInt(3433434343))).toBeTruthy(); + expect( + instance.encryptAddress('0x8ba1f109551bd432803012645ac136ddd64dba72'), + ).toBeTruthy(); + expect(() => instance.encryptBool(undefined as any)).toThrow( 'Missing value', ); @@ -145,6 +149,12 @@ describe('index', () => { expect(() => instance.encrypt64('wrong value' as any)).toThrow( 'Value must be a number or a bigint.', ); + expect(() => instance.encryptAddress('wrong value' as any)).toThrow( + 'Value must be a valid address.', + ); + expect(() => instance.encryptAddress(BigInt(32) as any)).toThrow( + 'Value must be a string.', + ); // Check limit expect(instance.encryptBool(1)).toBeTruthy(); diff --git a/src/sdk/index.ts b/src/sdk/index.ts index 743216e..73fb6f7 100644 --- a/src/sdk/index.ts +++ b/src/sdk/index.ts @@ -192,6 +192,7 @@ export const createInstance = async ( throw new Error( 'Your instance has been created without the public blockchain key.', ); + if (typeof value !== 'string') throw new Error('Value must be a string.'); if (!isAddress(value)) throw new Error('Value must be a valid address.'); return encryptAddress(value, tfheCompactPublicKey); },