From 94c7725678cfe48f5c60e92470023f69ff31dbc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20James=20Toussaint?= <33313130+jeremyjams@users.noreply.github.com> Date: Wed, 28 Aug 2024 14:12:15 +0200 Subject: [PATCH 1/7] Migrate IexecPoco2#reveal unit tests --- CHANGELOG.md | 1 + .../{03_reveal.js => 03_reveal.js.skip} | 2 + test/byContract/IexecPoco/03_reveal.test.ts | 291 ++++++++++++++++++ utils/createOrders.ts | 8 + 4 files changed, 302 insertions(+) rename test/byContract/IexecPoco/{03_reveal.js => 03_reveal.js.skip} (99%) create mode 100644 test/byContract/IexecPoco/03_reveal.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a8c7d1c0..c6261707f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Generate Solidity documentation. (#111) - Migrate unit test files to Typescript & Hardhat: - IexecPoco2 + - reveal (#114) - contribute (#108, #109, #110) - IexecPoco1 (#107, #113) - Add `.test` suffix to unit test files (#106) diff --git a/test/byContract/IexecPoco/03_reveal.js b/test/byContract/IexecPoco/03_reveal.js.skip similarity index 99% rename from test/byContract/IexecPoco/03_reveal.js rename to test/byContract/IexecPoco/03_reveal.js.skip index 530b5d46a..16085b151 100644 --- a/test/byContract/IexecPoco/03_reveal.js +++ b/test/byContract/IexecPoco/03_reveal.js.skip @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: 2020-2024 IEXEC BLOCKCHAIN TECH // SPDX-License-Identifier: Apache-2.0 +// TODO: Remove this file + const loadTruffleFixtureDeployment = require('../../../scripts/truffle-fixture-deployer'); // Config var DEPLOYMENT = require('../../../config/config.json').chains.default; diff --git a/test/byContract/IexecPoco/03_reveal.test.ts b/test/byContract/IexecPoco/03_reveal.test.ts new file mode 100644 index 000000000..c78c02fce --- /dev/null +++ b/test/byContract/IexecPoco/03_reveal.test.ts @@ -0,0 +1,291 @@ +// SPDX-FileCopyrightText: 2020-2024 IEXEC BLOCKCHAIN TECH +// SPDX-License-Identifier: Apache-2.0 + +import { AddressZero, HashZero } from '@ethersproject/constants'; +import { loadFixture, time } from '@nomicfoundation/hardhat-network-helpers'; +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; +import { ethers, expect } from 'hardhat'; +import { loadHardhatFixtureDeployment } from '../../../scripts/hardhat-fixture-deployer'; +import { IexecInterfaceNative, IexecInterfaceNative__factory } from '../../../typechain'; +import { NULL } from '../../../utils/constants'; +import { IexecOrders, OrdersAssets, OrdersPrices, buildOrders } from '../../../utils/createOrders'; +import { + ContributionStatusEnum, + TaskStatusEnum, + buildAndSignContributionAuthorizationMessage, + buildResultHash, + buildResultHashAndResultSeal, + buildUtf8ResultAndDigest, + getIexecAccounts, +} from '../../../utils/poco-tools'; +import { IexecWrapper } from '../../utils/IexecWrapper'; + +const volume = 1; +const standardDealTag = HashZero; +const { resultDigest } = buildUtf8ResultAndDigest('result'); +const { resultDigest: badResultDigest } = buildUtf8ResultAndDigest('bad-result'); +const emptyEnclaveAddress = AddressZero; +const emptyEnclaveSignature = NULL.SIGNATURE; + +describe('IexecPoco2#reveal', () => { + let proxyAddress: string; + let [iexecPoco, iexecPocoAsWorker]: IexecInterfaceNative[] = []; + let iexecWrapper: IexecWrapper; + let [ + anyone, + scheduler, + worker, + worker1, + worker2, + worker3, + worker4, + requester, + ]: SignerWithAddress[] = []; + let ordersAssets: OrdersAssets; + let ordersPrices: OrdersPrices; + let orders: IexecOrders; + let [dealId, taskId]: string[] = []; + let taskIndex: number; + let [resultHash, resultSeal]: string[] = []; + let schedulerSignature: string; + + beforeEach(async () => { + proxyAddress = await loadHardhatFixtureDeployment(); + await loadFixture(initFixture); + }); + + async function initFixture() { + const accounts = await getIexecAccounts(); + ({ scheduler, worker, worker1, worker2, worker3, worker4, requester, anyone } = accounts); + iexecWrapper = new IexecWrapper(proxyAddress, accounts); + const { appAddress, datasetAddress, workerpoolAddress } = await iexecWrapper.createAssets(); + iexecPoco = IexecInterfaceNative__factory.connect(proxyAddress, anyone); + iexecPocoAsWorker = iexecPoco.connect(worker); + const appPrice = 1000; + const datasetPrice = 1_000_000; + const workerpoolPrice = 1_000_000_000; + ordersAssets = { + app: appAddress, + dataset: datasetAddress, + workerpool: workerpoolAddress, + }; + ordersPrices = { + app: appPrice, + dataset: datasetPrice, + workerpool: workerpoolPrice, + }; + ({ orders } = buildOrders({ + assets: ordersAssets, + requester: requester.address, + prices: ordersPrices, + volume, + trust: 1, + tag: standardDealTag, + })); + ({ dealId, taskIndex, taskId } = await iexecWrapper.signAndMatchOrders(orders)); + await iexecPoco.initialize(dealId, taskIndex).then((tx) => tx.wait()); + const workerTaskStake = await iexecPoco + .viewDeal(dealId) + .then((deal) => deal.workerStake.toNumber()); + await iexecWrapper.depositInIexecAccount(worker, workerTaskStake); + ({ resultHash, resultSeal } = buildResultHashAndResultSeal(taskId, resultDigest, worker)); + schedulerSignature = await buildAndSignContributionAuthorizationMessage( + worker.address, + taskId, + emptyEnclaveAddress, + scheduler, + ); + } + + describe('Reveal', () => { + it('Should reveal task', async () => { + await iexecPocoAsWorker + .contribute( + taskId, + resultHash, + resultSeal, + emptyEnclaveAddress, + emptyEnclaveSignature, + schedulerSignature, + ) + .then((tx) => tx.wait()); + + await expect(iexecPocoAsWorker.reveal(taskId, resultDigest)) + .to.emit(iexecPoco, 'TaskReveal') + .withArgs(taskId, worker.address, resultDigest); + const contribution = await iexecPoco.viewContribution(taskId, worker.address); + expect(contribution.status).equal(ContributionStatusEnum.PROVED); + const task = await iexecPoco.viewTask(taskId); + expect(task.revealCounter).equal(1); + expect(task.resultDigest).equal(resultDigest); + }); + + it('Should not reveal when task is not in revealing status', async () => { + const task = await iexecPoco.viewTask(taskId); + expect(task.status).equal(TaskStatusEnum.ACTIVE); + + await expect( + iexecPocoAsWorker.reveal(taskId, resultDigest), + ).to.be.revertedWithoutReason(); // require#1 + }); + + it('Should not reveal after deadline', async () => { + await iexecPocoAsWorker + .contribute( + taskId, + resultHash, + resultSeal, + emptyEnclaveAddress, + emptyEnclaveSignature, + schedulerSignature, + ) + .then((tx) => tx.wait()); + const task = await iexecPoco.viewTask(taskId); + expect(task.status).equal(TaskStatusEnum.REVEALING); + await time.setNextBlockTimestamp(task.revealDeadline); + // revealing task + // but after deadline + await expect( + iexecPocoAsWorker.reveal(taskId, resultDigest), + ).to.be.revertedWithoutReason(); // require#2 + }); + + it('Should not reveal twice', async () => { + await iexecPocoAsWorker + .contribute( + taskId, + resultHash, + resultSeal, + emptyEnclaveAddress, + emptyEnclaveSignature, + schedulerSignature, + ) + .then((tx) => tx.wait()); + const task = await iexecPoco.viewTask(taskId); + expect(task.status).equal(TaskStatusEnum.REVEALING); + await iexecPocoAsWorker.reveal(taskId, resultDigest).then((tx) => tx.wait()); + const contribution = await iexecPoco.viewContribution(taskId, worker.address); + expect(contribution.status).equal(ContributionStatusEnum.PROVED); + // revealing task, before deadline + // but contribution status not contributed anymore (since already proved) + await expect( + iexecPocoAsWorker.reveal(taskId, resultDigest), + ).to.be.revertedWithoutReason(); // require#3 + }); + + it('Should not reveal when outside consensus', async () => { + const { dealId, taskIndex, taskId } = await iexecWrapper.signAndMatchOrders( + buildOrders({ + assets: ordersAssets, + requester: requester.address, + prices: ordersPrices, + volume, + trust: 3, + tag: standardDealTag, + salt: ethers.utils.hexZeroPad('0x' + Date.now().toString(), 32), // make all + }).orders, // orders unique since some orders are already matched in beforeEach + ); + await iexecPoco.initialize(dealId, taskIndex).then((tx) => tx.wait()); + const workerTaskStake = await iexecPoco + .viewDeal(dealId) + .then((deal) => deal.workerStake.toNumber()); + const workers = [ + { signer: worker1, resultDigest: resultDigest }, + { signer: worker2, resultDigest: badResultDigest }, + { signer: worker3, resultDigest: resultDigest }, + { signer: worker4, resultDigest: resultDigest }, + ]; + const loosingWorker = worker2; + // winning workers are worker1, worker3 & worker4 + for (let i = 0; i < workers.length; i++) { + const worker = workers[i]; + const workerAddress = worker.signer.address; + const { resultHash, resultSeal } = buildResultHashAndResultSeal( + taskId, + worker.resultDigest, + worker.signer, + ); + await iexecWrapper.depositInIexecAccount(worker.signer, workerTaskStake); + await iexecPoco + .connect(worker.signer) + .contribute( + taskId, + resultHash, + resultSeal, + emptyEnclaveAddress, + emptyEnclaveSignature, + await buildAndSignContributionAuthorizationMessage( + workerAddress, + taskId, + emptyEnclaveAddress, + scheduler, + ), + ) + .then((tx) => tx.wait()); + } + const task = await iexecPoco.viewTask(taskId); + expect(task.status).equal(TaskStatusEnum.REVEALING); + const contribution = await iexecPoco.viewContribution(taskId, loosingWorker.address); + expect(contribution.status).equal(ContributionStatusEnum.CONTRIBUTED); + expect(contribution.resultHash).not.equal(task.consensusValue); + // revealing task, before deadline, contribution status is contributed + // but contribution outside consensus + await expect( + iexecPoco.connect(loosingWorker).reveal(taskId, resultDigest), + ).to.be.revertedWithoutReason(); // require#4 + }); + + it('Should not reveal when no able to prove result value', async () => { + await iexecPocoAsWorker + .contribute( + taskId, + resultHash, + resultSeal, + emptyEnclaveAddress, + emptyEnclaveSignature, + schedulerSignature, + ) + .then((tx) => tx.wait()); + const task = await iexecPoco.viewTask(taskId); + expect(task.status).equal(TaskStatusEnum.REVEALING); + const contribution = await iexecPoco.viewContribution(taskId, worker.address); + expect(contribution.status).equal(ContributionStatusEnum.CONTRIBUTED); + expect(contribution.resultHash).equal(task.consensusValue); + expect(contribution.resultHash).not.equal(buildResultHash(taskId, badResultDigest)); + // revealing task, before deadline, contribution status is contributed + // contribution is part of the consensus + // but unable to prove result value + await expect( + iexecPocoAsWorker.reveal(taskId, badResultDigest), + ).to.be.revertedWithoutReason(); // require#5 + }); + + it('Should not reveal when no able to prove result ownership', async () => { + await iexecPocoAsWorker + .contribute( + taskId, + resultHash, + ethers.utils.hexZeroPad('0xbad5ea1', 32), // bad seal + emptyEnclaveAddress, + emptyEnclaveSignature, + schedulerSignature, + ) + .then((tx) => tx.wait()); + const task = await iexecPoco.viewTask(taskId); + expect(task.status).equal(TaskStatusEnum.REVEALING); + const contribution = await iexecPoco.viewContribution(taskId, worker.address); + expect(contribution.status).equal(ContributionStatusEnum.CONTRIBUTED); + expect(contribution.resultHash).equal(task.consensusValue); + expect(contribution.resultHash).equal(buildResultHash(taskId, resultDigest)); + expect(contribution.resultSeal).not.equal( + buildResultHashAndResultSeal(taskId, resultDigest, worker), + ); + // revealing task, before deadline, contribution status is contributed + // contribution is part of the consensus, result proof is valid + // but unable to prove result ownership + await expect( + iexecPocoAsWorker.reveal(taskId, resultDigest), + ).to.be.revertedWithoutReason(); // require#6 + }); + }); +}); diff --git a/utils/createOrders.ts b/utils/createOrders.ts index cf0fd297e..94d64f620 100644 --- a/utils/createOrders.ts +++ b/utils/createOrders.ts @@ -42,6 +42,7 @@ export interface MatchOrdersArgs { trust?: number; category?: number; params?: string; + salt?: string; } export interface OrdersActors { @@ -248,6 +249,13 @@ export function buildOrders(matchOrdersArgs: MatchOrdersArgs) { if (matchOrdersArgs.params) { requestOrder.params = matchOrdersArgs.params; } + // Set salt + if (matchOrdersArgs.salt) { + appOrder.salt = matchOrdersArgs.salt; + datasetOrder.salt = matchOrdersArgs.salt; + workerpoolOrder.salt = matchOrdersArgs.salt; + requestOrder.salt = matchOrdersArgs.salt; + } return { orders: new IexecOrders(appOrder, datasetOrder, workerpoolOrder, requestOrder), // TODO remove these additional return values and use function toObject() for From 3a8d635aad26658ded31755dd169320cb8be8fc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20James=20Toussaint?= <33313130+jeremyjams@users.noreply.github.com> Date: Wed, 28 Aug 2024 16:29:57 +0200 Subject: [PATCH 2/7] Apply suggestions from code review Co-authored-by: Zied Guesmi <26070035+zguesmi@users.noreply.github.com> --- test/byContract/IexecPoco/03_reveal.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/byContract/IexecPoco/03_reveal.test.ts b/test/byContract/IexecPoco/03_reveal.test.ts index c78c02fce..cdd3a4f21 100644 --- a/test/byContract/IexecPoco/03_reveal.test.ts +++ b/test/byContract/IexecPoco/03_reveal.test.ts @@ -98,7 +98,7 @@ describe('IexecPoco2#reveal', () => { } describe('Reveal', () => { - it('Should reveal task', async () => { + it('Should reveal task contribution', async () => { await iexecPocoAsWorker .contribute( taskId, @@ -235,7 +235,7 @@ describe('IexecPoco2#reveal', () => { ).to.be.revertedWithoutReason(); // require#4 }); - it('Should not reveal when no able to prove result value', async () => { + it('Should not reveal when unable to prove result value', async () => { await iexecPocoAsWorker .contribute( taskId, @@ -278,7 +278,7 @@ describe('IexecPoco2#reveal', () => { expect(contribution.resultHash).equal(task.consensusValue); expect(contribution.resultHash).equal(buildResultHash(taskId, resultDigest)); expect(contribution.resultSeal).not.equal( - buildResultHashAndResultSeal(taskId, resultDigest, worker), + buildResultHashAndResultSeal(taskId, resultDigest, worker).resultSeal, ); // revealing task, before deadline, contribution status is contributed // contribution is part of the consensus, result proof is valid From 4b7d6dc2a38737cdde2be7004d82195c47691c77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20James=20Toussaint?= <33313130+jeremyjams@users.noreply.github.com> Date: Wed, 28 Aug 2024 16:32:21 +0200 Subject: [PATCH 3/7] Remove reveal describe --- test/byContract/IexecPoco/03_reveal.test.ts | 338 ++++++++++---------- 1 file changed, 164 insertions(+), 174 deletions(-) diff --git a/test/byContract/IexecPoco/03_reveal.test.ts b/test/byContract/IexecPoco/03_reveal.test.ts index cdd3a4f21..66d8cbc3b 100644 --- a/test/byContract/IexecPoco/03_reveal.test.ts +++ b/test/byContract/IexecPoco/03_reveal.test.ts @@ -97,195 +97,185 @@ describe('IexecPoco2#reveal', () => { ); } - describe('Reveal', () => { - it('Should reveal task contribution', async () => { - await iexecPocoAsWorker - .contribute( - taskId, - resultHash, - resultSeal, - emptyEnclaveAddress, - emptyEnclaveSignature, - schedulerSignature, - ) - .then((tx) => tx.wait()); + it('Should reveal task contribution', async () => { + await iexecPocoAsWorker + .contribute( + taskId, + resultHash, + resultSeal, + emptyEnclaveAddress, + emptyEnclaveSignature, + schedulerSignature, + ) + .then((tx) => tx.wait()); - await expect(iexecPocoAsWorker.reveal(taskId, resultDigest)) - .to.emit(iexecPoco, 'TaskReveal') - .withArgs(taskId, worker.address, resultDigest); - const contribution = await iexecPoco.viewContribution(taskId, worker.address); - expect(contribution.status).equal(ContributionStatusEnum.PROVED); - const task = await iexecPoco.viewTask(taskId); - expect(task.revealCounter).equal(1); - expect(task.resultDigest).equal(resultDigest); - }); + await expect(iexecPocoAsWorker.reveal(taskId, resultDigest)) + .to.emit(iexecPoco, 'TaskReveal') + .withArgs(taskId, worker.address, resultDigest); + const contribution = await iexecPoco.viewContribution(taskId, worker.address); + expect(contribution.status).equal(ContributionStatusEnum.PROVED); + const task = await iexecPoco.viewTask(taskId); + expect(task.revealCounter).equal(1); + expect(task.resultDigest).equal(resultDigest); + }); - it('Should not reveal when task is not in revealing status', async () => { - const task = await iexecPoco.viewTask(taskId); - expect(task.status).equal(TaskStatusEnum.ACTIVE); + it('Should not reveal when task is not in revealing status', async () => { + const task = await iexecPoco.viewTask(taskId); + expect(task.status).equal(TaskStatusEnum.ACTIVE); - await expect( - iexecPocoAsWorker.reveal(taskId, resultDigest), - ).to.be.revertedWithoutReason(); // require#1 - }); + await expect(iexecPocoAsWorker.reveal(taskId, resultDigest)).to.be.revertedWithoutReason(); // require#1 + }); - it('Should not reveal after deadline', async () => { - await iexecPocoAsWorker - .contribute( - taskId, - resultHash, - resultSeal, - emptyEnclaveAddress, - emptyEnclaveSignature, - schedulerSignature, - ) - .then((tx) => tx.wait()); - const task = await iexecPoco.viewTask(taskId); - expect(task.status).equal(TaskStatusEnum.REVEALING); - await time.setNextBlockTimestamp(task.revealDeadline); - // revealing task - // but after deadline - await expect( - iexecPocoAsWorker.reveal(taskId, resultDigest), - ).to.be.revertedWithoutReason(); // require#2 - }); + it('Should not reveal after deadline', async () => { + await iexecPocoAsWorker + .contribute( + taskId, + resultHash, + resultSeal, + emptyEnclaveAddress, + emptyEnclaveSignature, + schedulerSignature, + ) + .then((tx) => tx.wait()); + const task = await iexecPoco.viewTask(taskId); + expect(task.status).equal(TaskStatusEnum.REVEALING); + await time.setNextBlockTimestamp(task.revealDeadline); + // revealing task + // but after deadline + await expect(iexecPocoAsWorker.reveal(taskId, resultDigest)).to.be.revertedWithoutReason(); // require#2 + }); - it('Should not reveal twice', async () => { - await iexecPocoAsWorker - .contribute( - taskId, - resultHash, - resultSeal, - emptyEnclaveAddress, - emptyEnclaveSignature, - schedulerSignature, - ) - .then((tx) => tx.wait()); - const task = await iexecPoco.viewTask(taskId); - expect(task.status).equal(TaskStatusEnum.REVEALING); - await iexecPocoAsWorker.reveal(taskId, resultDigest).then((tx) => tx.wait()); - const contribution = await iexecPoco.viewContribution(taskId, worker.address); - expect(contribution.status).equal(ContributionStatusEnum.PROVED); - // revealing task, before deadline - // but contribution status not contributed anymore (since already proved) - await expect( - iexecPocoAsWorker.reveal(taskId, resultDigest), - ).to.be.revertedWithoutReason(); // require#3 - }); + it('Should not reveal twice', async () => { + await iexecPocoAsWorker + .contribute( + taskId, + resultHash, + resultSeal, + emptyEnclaveAddress, + emptyEnclaveSignature, + schedulerSignature, + ) + .then((tx) => tx.wait()); + const task = await iexecPoco.viewTask(taskId); + expect(task.status).equal(TaskStatusEnum.REVEALING); + await iexecPocoAsWorker.reveal(taskId, resultDigest).then((tx) => tx.wait()); + const contribution = await iexecPoco.viewContribution(taskId, worker.address); + expect(contribution.status).equal(ContributionStatusEnum.PROVED); + // revealing task, before deadline + // but contribution status not contributed anymore (since already proved) + await expect(iexecPocoAsWorker.reveal(taskId, resultDigest)).to.be.revertedWithoutReason(); // require#3 + }); - it('Should not reveal when outside consensus', async () => { - const { dealId, taskIndex, taskId } = await iexecWrapper.signAndMatchOrders( - buildOrders({ - assets: ordersAssets, - requester: requester.address, - prices: ordersPrices, - volume, - trust: 3, - tag: standardDealTag, - salt: ethers.utils.hexZeroPad('0x' + Date.now().toString(), 32), // make all - }).orders, // orders unique since some orders are already matched in beforeEach + it('Should not reveal when outside consensus', async () => { + const { dealId, taskIndex, taskId } = await iexecWrapper.signAndMatchOrders( + buildOrders({ + assets: ordersAssets, + requester: requester.address, + prices: ordersPrices, + volume, + trust: 3, + tag: standardDealTag, + salt: ethers.utils.hexZeroPad('0x' + Date.now().toString(), 32), // make all + }).orders, // orders unique since some orders are already matched in beforeEach + ); + await iexecPoco.initialize(dealId, taskIndex).then((tx) => tx.wait()); + const workerTaskStake = await iexecPoco + .viewDeal(dealId) + .then((deal) => deal.workerStake.toNumber()); + const workers = [ + { signer: worker1, resultDigest: resultDigest }, + { signer: worker2, resultDigest: badResultDigest }, + { signer: worker3, resultDigest: resultDigest }, + { signer: worker4, resultDigest: resultDigest }, + ]; + const loosingWorker = worker2; + // winning workers are worker1, worker3 & worker4 + for (let i = 0; i < workers.length; i++) { + const worker = workers[i]; + const workerAddress = worker.signer.address; + const { resultHash, resultSeal } = buildResultHashAndResultSeal( + taskId, + worker.resultDigest, + worker.signer, ); - await iexecPoco.initialize(dealId, taskIndex).then((tx) => tx.wait()); - const workerTaskStake = await iexecPoco - .viewDeal(dealId) - .then((deal) => deal.workerStake.toNumber()); - const workers = [ - { signer: worker1, resultDigest: resultDigest }, - { signer: worker2, resultDigest: badResultDigest }, - { signer: worker3, resultDigest: resultDigest }, - { signer: worker4, resultDigest: resultDigest }, - ]; - const loosingWorker = worker2; - // winning workers are worker1, worker3 & worker4 - for (let i = 0; i < workers.length; i++) { - const worker = workers[i]; - const workerAddress = worker.signer.address; - const { resultHash, resultSeal } = buildResultHashAndResultSeal( - taskId, - worker.resultDigest, - worker.signer, - ); - await iexecWrapper.depositInIexecAccount(worker.signer, workerTaskStake); - await iexecPoco - .connect(worker.signer) - .contribute( - taskId, - resultHash, - resultSeal, - emptyEnclaveAddress, - emptyEnclaveSignature, - await buildAndSignContributionAuthorizationMessage( - workerAddress, - taskId, - emptyEnclaveAddress, - scheduler, - ), - ) - .then((tx) => tx.wait()); - } - const task = await iexecPoco.viewTask(taskId); - expect(task.status).equal(TaskStatusEnum.REVEALING); - const contribution = await iexecPoco.viewContribution(taskId, loosingWorker.address); - expect(contribution.status).equal(ContributionStatusEnum.CONTRIBUTED); - expect(contribution.resultHash).not.equal(task.consensusValue); - // revealing task, before deadline, contribution status is contributed - // but contribution outside consensus - await expect( - iexecPoco.connect(loosingWorker).reveal(taskId, resultDigest), - ).to.be.revertedWithoutReason(); // require#4 - }); - - it('Should not reveal when unable to prove result value', async () => { - await iexecPocoAsWorker + await iexecWrapper.depositInIexecAccount(worker.signer, workerTaskStake); + await iexecPoco + .connect(worker.signer) .contribute( taskId, resultHash, resultSeal, emptyEnclaveAddress, emptyEnclaveSignature, - schedulerSignature, + await buildAndSignContributionAuthorizationMessage( + workerAddress, + taskId, + emptyEnclaveAddress, + scheduler, + ), ) .then((tx) => tx.wait()); - const task = await iexecPoco.viewTask(taskId); - expect(task.status).equal(TaskStatusEnum.REVEALING); - const contribution = await iexecPoco.viewContribution(taskId, worker.address); - expect(contribution.status).equal(ContributionStatusEnum.CONTRIBUTED); - expect(contribution.resultHash).equal(task.consensusValue); - expect(contribution.resultHash).not.equal(buildResultHash(taskId, badResultDigest)); - // revealing task, before deadline, contribution status is contributed - // contribution is part of the consensus - // but unable to prove result value - await expect( - iexecPocoAsWorker.reveal(taskId, badResultDigest), - ).to.be.revertedWithoutReason(); // require#5 - }); + } + const task = await iexecPoco.viewTask(taskId); + expect(task.status).equal(TaskStatusEnum.REVEALING); + const contribution = await iexecPoco.viewContribution(taskId, loosingWorker.address); + expect(contribution.status).equal(ContributionStatusEnum.CONTRIBUTED); + expect(contribution.resultHash).not.equal(task.consensusValue); + // revealing task, before deadline, contribution status is contributed + // but contribution outside consensus + await expect( + iexecPoco.connect(loosingWorker).reveal(taskId, resultDigest), + ).to.be.revertedWithoutReason(); // require#4 + }); - it('Should not reveal when no able to prove result ownership', async () => { - await iexecPocoAsWorker - .contribute( - taskId, - resultHash, - ethers.utils.hexZeroPad('0xbad5ea1', 32), // bad seal - emptyEnclaveAddress, - emptyEnclaveSignature, - schedulerSignature, - ) - .then((tx) => tx.wait()); - const task = await iexecPoco.viewTask(taskId); - expect(task.status).equal(TaskStatusEnum.REVEALING); - const contribution = await iexecPoco.viewContribution(taskId, worker.address); - expect(contribution.status).equal(ContributionStatusEnum.CONTRIBUTED); - expect(contribution.resultHash).equal(task.consensusValue); - expect(contribution.resultHash).equal(buildResultHash(taskId, resultDigest)); - expect(contribution.resultSeal).not.equal( - buildResultHashAndResultSeal(taskId, resultDigest, worker).resultSeal, - ); - // revealing task, before deadline, contribution status is contributed - // contribution is part of the consensus, result proof is valid - // but unable to prove result ownership - await expect( - iexecPocoAsWorker.reveal(taskId, resultDigest), - ).to.be.revertedWithoutReason(); // require#6 - }); + it('Should not reveal when unable to prove result value', async () => { + await iexecPocoAsWorker + .contribute( + taskId, + resultHash, + resultSeal, + emptyEnclaveAddress, + emptyEnclaveSignature, + schedulerSignature, + ) + .then((tx) => tx.wait()); + const task = await iexecPoco.viewTask(taskId); + expect(task.status).equal(TaskStatusEnum.REVEALING); + const contribution = await iexecPoco.viewContribution(taskId, worker.address); + expect(contribution.status).equal(ContributionStatusEnum.CONTRIBUTED); + expect(contribution.resultHash).equal(task.consensusValue); + expect(contribution.resultHash).not.equal(buildResultHash(taskId, badResultDigest)); + // revealing task, before deadline, contribution status is contributed + // contribution is part of the consensus + // but unable to prove result value + await expect( + iexecPocoAsWorker.reveal(taskId, badResultDigest), + ).to.be.revertedWithoutReason(); // require#5 + }); + + it('Should not reveal when no able to prove result ownership', async () => { + await iexecPocoAsWorker + .contribute( + taskId, + resultHash, + ethers.utils.hexZeroPad('0xbad5ea1', 32), // bad seal + emptyEnclaveAddress, + emptyEnclaveSignature, + schedulerSignature, + ) + .then((tx) => tx.wait()); + const task = await iexecPoco.viewTask(taskId); + expect(task.status).equal(TaskStatusEnum.REVEALING); + const contribution = await iexecPoco.viewContribution(taskId, worker.address); + expect(contribution.status).equal(ContributionStatusEnum.CONTRIBUTED); + expect(contribution.resultHash).equal(task.consensusValue); + expect(contribution.resultHash).equal(buildResultHash(taskId, resultDigest)); + expect(contribution.resultSeal).not.equal( + buildResultHashAndResultSeal(taskId, resultDigest, worker).resultSeal, + ); + // revealing task, before deadline, contribution status is contributed + // contribution is part of the consensus, result proof is valid + // but unable to prove result ownership + await expect(iexecPocoAsWorker.reveal(taskId, resultDigest)).to.be.revertedWithoutReason(); // require#6 }); }); From 8bffaa54fe2c38efeee45939258125a1d3b319c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20James=20Toussaint?= <33313130+jeremyjams@users.noreply.github.com> Date: Wed, 28 Aug 2024 16:40:16 +0200 Subject: [PATCH 4/7] Improve salt comment --- test/byContract/IexecPoco/03_reveal.test.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/byContract/IexecPoco/03_reveal.test.ts b/test/byContract/IexecPoco/03_reveal.test.ts index 66d8cbc3b..4baf51279 100644 --- a/test/byContract/IexecPoco/03_reveal.test.ts +++ b/test/byContract/IexecPoco/03_reveal.test.ts @@ -175,8 +175,10 @@ describe('IexecPoco2#reveal', () => { volume, trust: 3, tag: standardDealTag, - salt: ethers.utils.hexZeroPad('0x' + Date.now().toString(), 32), // make all - }).orders, // orders unique since some orders are already matched in beforeEach + salt: ethers.utils.hexZeroPad('0x' + Date.now().toString(), 32), // make + }).orders, // app and dataset orders unique since already matched in + // beforeEach. A useless salt is also added to workerpool and request + // orders to get an easy one-liner declaration. ); await iexecPoco.initialize(dealId, taskIndex).then((tx) => tx.wait()); const workerTaskStake = await iexecPoco From faf9cba981d6de697d15e7c4cf12f8d9ef66d1b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20James=20Toussaint?= <33313130+jeremyjams@users.noreply.github.com> Date: Wed, 28 Aug 2024 17:00:51 +0200 Subject: [PATCH 5/7] Add test for should not reveal when did not contributed --- test/byContract/IexecPoco/03_reveal.test.ts | 22 +++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/byContract/IexecPoco/03_reveal.test.ts b/test/byContract/IexecPoco/03_reveal.test.ts index 4baf51279..0b1efb68c 100644 --- a/test/byContract/IexecPoco/03_reveal.test.ts +++ b/test/byContract/IexecPoco/03_reveal.test.ts @@ -145,6 +145,28 @@ describe('IexecPoco2#reveal', () => { await expect(iexecPocoAsWorker.reveal(taskId, resultDigest)).to.be.revertedWithoutReason(); // require#2 }); + it('Should not reveal when did not contribute', async () => { + await iexecPocoAsWorker + .contribute( + taskId, + resultHash, + resultSeal, + emptyEnclaveAddress, + emptyEnclaveSignature, + schedulerSignature, + ) + .then((tx) => tx.wait()); + const task = await iexecPoco.viewTask(taskId); + expect(task.status).equal(TaskStatusEnum.REVEALING); + const contribution = await iexecPoco.viewContribution(taskId, worker2.address); + expect(contribution.status).equal(ContributionStatusEnum.UNSET); + // revealing task, before deadline + // but worker2 did not contribute before revealing + await expect( + iexecPoco.connect(worker2).reveal(taskId, resultDigest), + ).to.be.revertedWithoutReason(); // require#3 + }); + it('Should not reveal twice', async () => { await iexecPocoAsWorker .contribute( From 3dbdd7829f8ae456faab683ebee87bbc135bdb79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20James=20Toussaint?= <33313130+jeremyjams@users.noreply.github.com> Date: Wed, 28 Aug 2024 17:42:00 +0200 Subject: [PATCH 6/7] No reveal with someone else stolen result seal contributed --- test/byContract/IexecPoco/03_reveal.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/byContract/IexecPoco/03_reveal.test.ts b/test/byContract/IexecPoco/03_reveal.test.ts index 0b1efb68c..04f7569a9 100644 --- a/test/byContract/IexecPoco/03_reveal.test.ts +++ b/test/byContract/IexecPoco/03_reveal.test.ts @@ -282,7 +282,8 @@ describe('IexecPoco2#reveal', () => { .contribute( taskId, resultHash, - ethers.utils.hexZeroPad('0xbad5ea1', 32), // bad seal + // stolen result seal from another worker + buildResultHashAndResultSeal(taskId, resultDigest, worker2).resultSeal, emptyEnclaveAddress, emptyEnclaveSignature, schedulerSignature, From 9fc75d4fecffb9ca1ab85ea19742c3b220e3c410 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20James=20Toussaint?= <33313130+jeremyjams@users.noreply.github.com> Date: Wed, 28 Aug 2024 17:42:50 +0200 Subject: [PATCH 7/7] Update test wording --- test/byContract/IexecPoco/03_reveal.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/byContract/IexecPoco/03_reveal.test.ts b/test/byContract/IexecPoco/03_reveal.test.ts index 04f7569a9..39ef8cb65 100644 --- a/test/byContract/IexecPoco/03_reveal.test.ts +++ b/test/byContract/IexecPoco/03_reveal.test.ts @@ -277,7 +277,7 @@ describe('IexecPoco2#reveal', () => { ).to.be.revertedWithoutReason(); // require#5 }); - it('Should not reveal when no able to prove result ownership', async () => { + it('Should not reveal when unable to prove result ownership', async () => { await iexecPocoAsWorker .contribute( taskId,