Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions host-contracts/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ KMS_SIGNER_ADDRESS_1="0x466f26442DD182C9A1b018Cd06671F9791DdE8Ef" # account[8]
KMS_SIGNER_ADDRESS_2="0xc45994e4098271c3140117ebD5c74C70dd56D9cd" # account[9]
KMS_SIGNER_ADDRESS_3="0xDb216ECeC4cEd51CdfD9609b6Ce7653aB04f6cAd" # account[10]
NUM_COPROCESSORS="1"
COPROCESSOR_CONTEXT_ID="1"
COPROCESSOR_SIGNER_ADDRESS_0="0x6518D50aDc9036Df37119eA465a8159E34417E2E" # account[11]
COPROCESSOR_SIGNER_ADDRESS_1="0xa5eE8292dA52d8234248709F3E217ffEBA5E8312" # account[12]
COPROCESSOR_SIGNER_ADDRESS_2="0xCFbF539CB91c92ace0343c5B0487149Ad0b82078" # account[13]
Expand Down
351 changes: 238 additions & 113 deletions host-contracts/contracts/InputVerifier.sol

Large diffs are not rendered by default.

28 changes: 28 additions & 0 deletions host-contracts/examples/InputVerifierUpgradedExample.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear

pragma solidity ^0.8.24;

import "../contracts/InputVerifier.sol";

contract InputVerifierUpgradedExample is InputVerifier {
string private constant CONTRACT_NAME = "InputVerifier";

uint256 private constant MAJOR_VERSION = 1000;
uint256 private constant MINOR_VERSION = 0;
uint256 private constant PATCH_VERSION = 0;

function getVersion() external pure virtual override returns (string memory) {
return
string(
abi.encodePacked(
CONTRACT_NAME,
" v",
Strings.toString(MAJOR_VERSION),
".",
Strings.toString(MINOR_VERSION),
".",
Strings.toString(PATCH_VERSION)
)
);
}
}
17 changes: 11 additions & 6 deletions host-contracts/tasks/taskDeploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,26 +191,31 @@ task('task:deployInputVerifier')
const verifyingContractSource = process.env.INPUT_VERIFICATION_ADDRESS!;
const chainIDSource = +process.env.CHAIN_ID_GATEWAY!;

let initialSigners: string[] = [];
// Load the initial coprocessor context signers from environment variables.
let initialCoprocessorContextSigners: string[] = [];
const numSigners = getRequiredEnvVar('NUM_COPROCESSORS');
for (let idx = 0; idx < +numSigners; idx++) {
const initialCoprocessorContextId = getRequiredEnvVar('COPROCESSOR_CONTEXT_ID');
for (let idx = 0; idx < parseInt(numSigners); idx++) {
if (!taskArguments.useAddress) {
const privKeySigner = getRequiredEnvVar(`PRIVATE_KEY_COPROCESSOR_ACCOUNT_${idx}`);
const inputSigner = new ethers.Wallet(privKeySigner).connect(ethers.provider);
initialSigners.push(inputSigner.address);
initialCoprocessorContextSigners.push(inputSigner.address);
} else {
const inputSignerAddress = getRequiredEnvVar(`COPROCESSOR_SIGNER_ADDRESS_${idx}`);
initialSigners.push(inputSignerAddress);
initialCoprocessorContextSigners.push(inputSignerAddress);
}
}

await upgrades.upgradeProxy(proxy, newImplem, {
call: { fn: 'initializeFromEmptyProxy', args: [verifyingContractSource, chainIDSource, initialSigners] },
call: {
fn: 'initializeFromEmptyProxy',
args: [verifyingContractSource, chainIDSource, initialCoprocessorContextId, initialCoprocessorContextSigners],
},
});
console.log('InputVerifier code set successfully at address:', proxyAddress);
console.log(
`${numSigners} Coprocessor signers were added to InputVerifier at initialization, list of Coprocessor signers is:`,
initialSigners,
initialCoprocessorContextSigners,
);
});

Expand Down
12 changes: 11 additions & 1 deletion host-contracts/tasks/upgradeContracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,17 @@ task('task:upgradeInputVerifier')
}
const proxyAddress = getRequiredEnvVar('INPUT_VERIFIER_CONTRACT_ADDRESS');

await upgradeCurrentToNew(proxyAddress, currentImplementation, newImplementation, verifyContract, hre);
// Load the initial coprocessor context signers from environment variables.
let initialContextSigners: string[] = [];
const numSigners = getRequiredEnvVar('NUM_COPROCESSORS');
for (let idx = 0; idx < parseInt(numSigners); idx++) {
const inputSignerAddress = getRequiredEnvVar(`COPROCESSOR_SIGNER_ADDRESS_${idx}`);
initialContextSigners.push(inputSignerAddress);
}

await upgradeCurrentToNew(proxyAddress, currentImplementation, newImplementation, verifyContract, hre, [
initialContextSigners,
]);
});

task('task:upgradeHCULimit')
Expand Down
42 changes: 33 additions & 9 deletions host-contracts/test/fhevmjsMocked.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { HardhatEthersSigner } from '@nomicfoundation/hardhat-ethers/signers';
import { toBigIntBE } from 'bigint-buffer';
import { toBufferBE } from 'bigint-buffer';
import crypto from 'crypto';
import dotenv from 'dotenv';
import { Wallet, ethers } from 'ethers';
import { BigNumberish, ethers } from 'ethers';
import * as fs from 'fs';
import hre from 'hardhat';
import { Keccak } from 'sha3';
import { isAddress } from 'web3-validator';

import { getRequiredEnvVar } from '../tasks/utils/loadVariables';
import { ACL } from '../types';
import { insertSQL } from './coprocessorUtils';
import { awaitCoprocessor, getClearText } from './coprocessorUtils';
import { checkIsHardhatSigner } from './utils';
Expand Down Expand Up @@ -196,7 +198,7 @@ export const userDecryptRequestMocked =

// ACL checking
const aclFactory = await hre.ethers.getContractFactory('ACL');
const acl = aclFactory.attach(aclAdd);
const acl = aclFactory.attach(aclAdd) as ACL;
const verifications = handles.map(async ({ ctHandle, contractAddress }) => {
const userAllowed = await acl.persistAllowed(ctHandle, userAddress);
const contractAllowed = await acl.persistAllowed(ctHandle, contractAddress);
Expand All @@ -221,7 +223,7 @@ export const userDecryptRequestMocked =
);
};

export const createEncryptedInputMocked = (contractAddress: string, userAddress: string) => {
export const createEncryptedInputMocked = (contractAddress: string, userAddress: string, coprocessorContextId = 1) => {
if (!isAddress(contractAddress)) {
throw new Error('Contract address is not a valid address.');
}
Expand Down Expand Up @@ -353,7 +355,7 @@ export const createEncryptedInputMocked = (contractAddress: string, userAddress:

const encryptedArray = new Uint8Array(encrypted);
const hash = new Keccak(256).update(Buffer.from(encryptedArray)).digest();
const extraDataV0 = ethers.solidityPacked(['uint8'], [0]);
const extraDataV0 = ethers.solidityPacked(['uint256'], [0]);

const chainId = process.env.SOLIDITY_COVERAGE === 'true' ? 31337 : hre.network.config.chainId;
if (chainId === undefined) {
Expand Down Expand Up @@ -382,17 +384,25 @@ export const createEncryptedInputMocked = (contractAddress: string, userAddress:
return dataInput;
});

let inputProof = '0x' + numberToHex(handles.length); // numHandles + numCoprocessorSigners + list_handles + signatureCoprocessorSigners (total len : 1+1+32+NUM_HANDLES*32+65*numSigners)
/**
* Compute the input proof by appending numHandles + numCoprocessorSigners + coprocessorContextId + list_handles + signatureCoprocessorSigners
* (total length in bytes: 1+1+32+NUM_HANDLES*32+65*numSigners).
*/
let inputProof = '0x' + numberToHex(handles.length);
const numSigners = +process.env.NUM_COPROCESSORS!;
inputProof += numberToHex(numSigners);

const coprocessorContextIdHex = ethers.zeroPadValue(ethers.toBeHex(coprocessorContextId), 32);
inputProof = ethers.concat([inputProof, coprocessorContextIdHex]);

const listHandlesStr = handles.map((i) => uint8ArrayToHexString(i));
listHandlesStr.map((handle) => (inputProof += handle));
const listHandles = listHandlesStr.map((i) => BigInt('0x' + i));
const signaturesCoproc = await computeInputSignaturesCopro(
listHandles,
userAddress,
contractAddress,
coprocessorContextId,
extraDataV0,
);
signaturesCoproc.map((sigCopro) => (inputProof += sigCopro.slice(2)));
Expand Down Expand Up @@ -450,9 +460,10 @@ export const ENCRYPTION_TYPES = {
};

async function computeInputSignaturesCopro(
handlesList: string[],
handlesList: BigNumberish[],
userAddress: string,
contractAddress: string,
coprocessorContextId: number,
extraData: string,
): Promise<string[]> {
const signatures: string[] = [];
Expand All @@ -461,18 +472,26 @@ async function computeInputSignaturesCopro(

for (let idx = 0; idx < numSigners; idx++) {
const coprocSigner = signers[idx];
const signature = await coprocSign(handlesList, userAddress, contractAddress, extraData, coprocSigner);
const signature = await coprocSign(
handlesList,
userAddress,
contractAddress,
coprocessorContextId,
extraData,
coprocSigner,
);
signatures.push(signature);
}
return signatures;
}

async function coprocSign(
handlesList: string[],
handlesList: BigNumberish[],
userAddress: string,
contractAddress: string,
coprocessorContextId: number,
extraData: string,
signer: Wallet,
signer: HardhatEthersSigner,
): Promise<string> {
const inputVerificationAdd = process.env.INPUT_VERIFICATION_ADDRESS;
const chainId = process.env.CHAIN_ID_GATEWAY;
Expand Down Expand Up @@ -503,6 +522,10 @@ async function coprocSign(
name: 'contractChainId',
type: 'uint256',
},
{
name: 'coprocessorContextId',
type: 'uint256',
},
{
name: 'extraData',
type: 'bytes',
Expand All @@ -515,6 +538,7 @@ async function coprocSign(
userAddress: userAddress,
contractAddress: contractAddress,
contractChainId: hostChainId,
coprocessorContextId,
extraData,
};

Expand Down
Loading