Skip to content

Commit

Permalink
Merge pull request #45 from zama-ai/release/0.3.0
Browse files Browse the repository at this point in the history
Release/0.3.0
  • Loading branch information
immortal-tofu authored Jan 2, 2024
2 parents 2c86ec6 + ef1732c commit 8cc438c
Show file tree
Hide file tree
Showing 7 changed files with 199 additions and 81 deletions.
32 changes: 16 additions & 16 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fhevmjs",
"version": "0.2.2",
"version": "0.3.0",
"description": "fhEVM SDK for blockchain using TFHE",
"main": "lib/node.cjs",
"types": "lib/node.d.ts",
Expand Down Expand Up @@ -44,9 +44,9 @@
"ethers": "^6.6.4",
"libsodium": "^0.7.11",
"libsodium-wrappers": "^0.7.11",
"node-tfhe": "^0.3.1",
"node-tfhe": "^0.4.1",
"sha3": "^2.1.4",
"tfhe": "^0.3.1"
"tfhe": "^0.4.1"
},
"devDependencies": {
"@rollup/plugin-alias": "^5.0.0",
Expand Down
48 changes: 42 additions & 6 deletions src/sdk/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ describe('token', () => {
expect(instance.encrypt8).toBeDefined();
expect(instance.encrypt16).toBeDefined();
expect(instance.encrypt32).toBeDefined();
expect(instance.generateToken).toBeDefined();
expect(instance.generatePublicKey).toBeDefined();
expect(instance.decrypt).toBeDefined();
expect(instance.serializeKeypairs).toBeDefined();
expect(instance.getTokenSignature).toBeDefined();
expect(instance.getPublicKey).toBeDefined();
expect(instance.hasKeypair).toBeDefined();
});

Expand Down Expand Up @@ -104,6 +104,22 @@ describe('token', () => {
).toThrow('Invalid contract address');
});

it('controls generatePublicKey', async () => {
const instance = await createInstance({
chainId: 1234,
publicKey: tfhePublicKey,
});
expect(() => instance.generatePublicKey(undefined as any)).toThrow(
'Missing contract address',
);
expect(() => instance.generatePublicKey({ verifyingContract: '' })).toThrow(
'Missing contract address',
);
expect(() =>
instance.generatePublicKey({ verifyingContract: '0x847473829d' }),
).toThrow('Invalid contract address');
});

it('save generated token', async () => {
const instance = await createInstance({
chainId: 1234,
Expand All @@ -112,6 +128,26 @@ describe('token', () => {

const contractAddress = '0x1c786b8ca49D932AFaDCEc00827352B503edf16c';

const { eip712, publicKey } = instance.generatePublicKey({
verifyingContract: contractAddress,
});

instance.setSignature(contractAddress, 'signnnn');

expect(instance.hasKeypair(contractAddress)).toBeTruthy();

const kp = instance.getPublicKey(contractAddress);
expect(kp!.publicKey).toBe(publicKey);
});

it('save generated token (deprecated)', async () => {
const instance = await createInstance({
chainId: 1234,
publicKey: tfhePublicKey,
});

const contractAddress = '0x1c786b8ca49D932AFaDCEc00827352B503edf16c';

const { token, publicKey } = instance.generateToken({
verifyingContract: contractAddress,
});
Expand All @@ -132,12 +168,12 @@ describe('token', () => {

const contractAddress = '0x1c786b8ca49D932AFaDCEc00827352B503edf16c';

const { token, publicKey } = instance.generateToken({
const { eip712, publicKey } = instance.generatePublicKey({
verifyingContract: contractAddress,
});
const keypairs = instance.serializeKeypairs();
expect(keypairs[contractAddress]).toBeUndefined();
const keypair = instance.getTokenSignature(contractAddress);
const keypair = instance.getPublicKey(contractAddress);
expect(keypair).toBeNull();
expect(instance.hasKeypair(contractAddress)).toBeFalsy();
});
Expand All @@ -150,13 +186,13 @@ describe('token', () => {

const contractAddress = '0x1c786b8ca49D932AFaDCEc00827352B503edf16c';

const { token, publicKey } = instance.generateToken({
const { eip712, publicKey } = instance.generatePublicKey({
verifyingContract: contractAddress,
});

instance.setTokenSignature(contractAddress, 'signnnn');

const kp = instance.getTokenSignature(contractAddress);
const kp = instance.getPublicKey(contractAddress);
expect(kp!.publicKey).toBe(publicKey);

const value = 89290;
Expand Down
96 changes: 86 additions & 10 deletions src/sdk/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { TfheCompactPublicKey } from 'node-tfhe';
import sodium from 'libsodium-wrappers';
import { encrypt8, encrypt16, encrypt32 } from './encrypt';
import { EIP712, generateToken } from './token';
import {
EIP712,
GeneratePublicKeyParams,
generatePublicKey,
} from './publicKey';
import { decrypt } from './decrypt';
import { fromHexString, isAddress, toHexString } from '../utils';
import { ContractKeypairs } from './types';
Expand All @@ -10,19 +14,30 @@ export type FhevmInstance = {
encrypt8: (value: number) => Uint8Array;
encrypt16: (value: number) => Uint8Array;
encrypt32: (value: number) => Uint8Array;
generateToken: (options: {
verifyingContract: string;
name?: string;
version?: string;
force?: boolean;
}) => {
generateToken: (
options: GeneratePublicKeyParams & {
force?: boolean;
},
) => {
publicKey: Uint8Array;
token: EIP712;
};
generatePublicKey: (
options: GeneratePublicKeyParams & {
force?: boolean;
},
) => {
publicKey: Uint8Array;
eip712: EIP712;
};
setTokenSignature: (contractAddress: string, signature: string) => void;
getTokenSignature: (
contractAddress: string,
) => { publicKey: Uint8Array; signature: string } | null;
setSignature: (contractAddress: string, signature: string) => void;
getPublicKey: (
contractAddress: string,
) => { publicKey: Uint8Array; signature: string } | null;
hasKeypair: (contractAddress: string) => boolean;
decrypt: (contractAddress: string, ciphertext: string) => number;
serializeKeypairs: () => ExportedContractKeypairs;
Expand Down Expand Up @@ -105,8 +120,38 @@ export const createInstance = async (
return encrypt32(value, tfheCompactPublicKey);
},

// Reencryption
/**
* @deprecated Since version 0.3.0. Will be deleted in version 0.4.0. Use generatePublicKey instead.
*/
generateToken(options) {
console.warn(
'generateToken is deprecated. Use generatePublicKey instead',
);
if (!options || !options.verifyingContract)
throw new Error('Missing contract address');
if (!isAddress(options.verifyingContract))
throw new Error('Invalid contract address');
let kp;
if (!options.force && contractKeypairs[options.verifyingContract]) {
kp = contractKeypairs[options.verifyingContract];
}
const { eip712, keypair } = generatePublicKey({
verifyingContract: options.verifyingContract,
name: options.name,
version: options.version,
chainId,
keypair: kp,
});
contractKeypairs[options.verifyingContract] = {
privateKey: keypair.privateKey,
publicKey: keypair.publicKey,
signature: null,
};
return { token: eip712, publicKey: keypair.publicKey };
},

// Reencryption
generatePublicKey(options) {
if (!options || !options.verifyingContract)
throw new Error('Missing contract address');
if (!isAddress(options.verifyingContract))
Expand All @@ -115,7 +160,7 @@ export const createInstance = async (
if (!options.force && contractKeypairs[options.verifyingContract]) {
kp = contractKeypairs[options.verifyingContract];
}
const { token, keypair } = generateToken({
const { eip712, keypair } = generatePublicKey({
verifyingContract: options.verifyingContract,
name: options.name,
version: options.version,
Expand All @@ -127,10 +172,16 @@ export const createInstance = async (
publicKey: keypair.publicKey,
signature: null,
};
return { token, publicKey: keypair.publicKey };
return { eip712, publicKey: keypair.publicKey };
},

/**
* @deprecated Since version 0.3.0. Will be deleted in version 0.4.0. Use generatePublicKey instead.
*/
setTokenSignature(contractAddress: string, signature: string) {
console.warn(
'setTokenSignature is deprecated. Use generatePublicKey instead',
);
if (
contractKeypairs[contractAddress] &&
contractKeypairs[contractAddress].privateKey
Expand All @@ -139,7 +190,32 @@ export const createInstance = async (
}
},

setSignature(contractAddress: string, signature: string) {
if (
contractKeypairs[contractAddress] &&
contractKeypairs[contractAddress].privateKey
) {
contractKeypairs[contractAddress].signature = signature;
}
},

/**
* @deprecated Since version 0.3.0. Will be deleted in version 0.4.0. Use generatePublicKey instead.
*/
getTokenSignature(contractAddress: string): TokenSignature | null {
console.warn(
'setTokenSignature is deprecated. Use generatePublicKey instead',
);
if (hasKeypair(contractAddress)) {
return {
publicKey: contractKeypairs[contractAddress].publicKey,
signature: contractKeypairs[contractAddress].signature!,
};
}
return null;
},

getPublicKey(contractAddress: string): TokenSignature | null {
if (hasKeypair(contractAddress)) {
return {
publicKey: contractKeypairs[contractAddress].publicKey,
Expand Down
45 changes: 45 additions & 0 deletions src/sdk/publicKey.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import sodium from 'libsodium-wrappers';
import { toHexString } from '../utils';
import { generatePublicKey } from './publicKey';

describe('token', () => {
beforeAll(async () => {
await sodium.ready;
});
it('creates a valid EIP712 object', async () => {
const { eip712, keypair } = generatePublicKey({
verifyingContract: '0xccc',
chainId: 1234,
name: 'hello',
version: '3',
});
expect(eip712.domain.chainId).toBe(1234);
expect(eip712.domain.name).toBe('hello');
expect(eip712.domain.version).toBe('3');
expect(eip712.message.publicKey).toBe(
`0x${toHexString(keypair.publicKey)}`,
);

expect(eip712.primaryType).toBe('Reencrypt');
expect(eip712.types.Reencrypt.length).toBe(1);
expect(eip712.types.Reencrypt[0].name).toBe('publicKey');
expect(eip712.types.Reencrypt[0].type).toBe('bytes32');
});

it('creates a valid EIP712 object with default values', async () => {
const { eip712, keypair } = generatePublicKey({
verifyingContract: '0xccc',
});
expect(eip712.domain.chainId).toBe(9000);
expect(eip712.domain.name).toBe('Reencryption');
expect(eip712.domain.version).toBe('1');
expect(eip712.message.publicKey).toBe(
`0x${toHexString(keypair.publicKey)}`,
);

expect(eip712.primaryType).toBe('Reencrypt');
expect(eip712.types.Reencrypt.length).toBe(1);
expect(eip712.types.Reencrypt[0].name).toBe('publicKey');
expect(eip712.types.Reencrypt[0].type).toBe('bytes32');
});
});
Loading

0 comments on commit 8cc438c

Please # to comment.