From eaa50d4e58d9c62c2d997a92af88794c218432bf Mon Sep 17 00:00:00 2001 From: Gabriel Fournier Date: Wed, 20 Nov 2024 11:13:38 +0100 Subject: [PATCH 01/11] migrate IT full chain with 1 bad worker --- test/000_fullchain.test.ts | 129 ++++++++++++++++++ ... => 100_fullchain-5workers-1error.js.skip} | 0 2 files changed, 129 insertions(+) rename test/{100_fullchain-5workers-1error.js => 100_fullchain-5workers-1error.js.skip} (100%) diff --git a/test/000_fullchain.test.ts b/test/000_fullchain.test.ts index 33a63a3db..9a36b2dd7 100644 --- a/test/000_fullchain.test.ts +++ b/test/000_fullchain.test.ts @@ -299,6 +299,135 @@ describe('Integration tests', function () { for (let i = 0; i < workerNumber; i++) { if (workerNumber == 1) { expect(await iexecPoco.viewScore(workers[i].address)).to.be.equal(0); + } else { + expect(await iexecPoco.viewScore(workers[i].address)).to.be.equal(1); + } + } + }); + } + for (let workerNumber = 4; workerNumber < 6; workerNumber++) { + let goodWorkersNumber = workerNumber - 1; + // Worker2 will contribute badly + it(`[7.${workerNumber - 3}] No sponsorship, no beneficiary, no callback, no BoT, up to ${workerNumber} workers with 1 bad actor`, async function () { + const volume = 1; + const workers = [worker1, worker2, worker3, worker4, worker5]; + const disposableWokers = workers.slice(0, workerNumber); + const acounts = [ + requester, + scheduler, + appProvider, + datasetProvider, + ...disposableWokers, + ]; + // Create deal. + const orders = buildOrders({ + assets: ordersAssets, + prices: ordersPrices, + requester: requester.address, + tag: standardDealTag, + beneficiary: beneficiary.address, + volume, + trust: goodWorkersNumber, + }); + + const { dealId, dealPrice, schedulerStakePerDeal } = + await iexecWrapper.signAndMatchOrders(...orders.toArray()); + const taskPrice = appPrice + datasetPrice + workerpoolPrice; + const schedulerStakePerTask = schedulerStakePerDeal / volume; + const workerRewardPerTask = await iexecWrapper.computeWorkerRewardPerTask( + dealId, + PocoMode.CLASSIC, + ); + const schedulerRewardPerTask = workerpoolPrice - workerRewardPerTask; + // Check initial balances. + let accountsInitBalances = [ + { + address: proxyAddress, + frozen: (await iexecPoco.frozenOf(proxyAddress)).toNumber(), + }, + ]; + for (const account of acounts) { + let address = account.address; + let frozen = (await iexecPoco.frozenOf(account.address)).toNumber(); + accountsInitBalances.push({ address, frozen }); + } + for (let i = 0; i < workerNumber; i++) { + expect(await iexecPoco.viewScore(workers[i].address)).to.be.equal(0); + } + const taskId = await iexecWrapper.initializeTask(dealId, 0); + // Finalize each task and check balance changes. + const workerStake = await iexecPoco + .viewDeal(dealId) + .then((deal) => deal.workerStake.toNumber()); + + for (let i = 0; i < workerNumber; i++) { + if (i == 1) { + const { resultDigest: badResultDigest } = + buildUtf8ResultAndDigest('bad-result'); + await iexecWrapper.contributeToTask( + dealId, + 0, + badResultDigest, + disposableWokers[i], + ); + } else { + await iexecWrapper.contributeToTask( + dealId, + 0, + resultDigest, + disposableWokers[i], + ); + } + } + for (let i = 0; i < workerNumber; i++) { + if (i !== 1) { + await iexecPoco + .connect(disposableWokers[i]) + .reveal(taskId, resultDigest) + .then((tx) => tx.wait()); + } + } + const finalizeTx = await iexecPoco + .connect(scheduler) + .finalize(taskId, results, '0x'); + expect(finalizeTx).to.changeTokenBalances( + iexecPoco, + [proxyAddress, requester, scheduler, appProvider, datasetProvider], + [ + -(dealPrice + schedulerStakePerDeal), + 0, + schedulerStakePerTask + schedulerRewardPerTask, + appPrice, + datasetPrice, + ], + ); + for (let i = 0; i < workerNumber; i++) { + if (i !== 1) { + expect(finalizeTx).to.changeTokenBalances( + iexecPoco, + [workers[i]], + [workerStake + workerRewardPerTask / goodWorkersNumber], + ); + } else { + expect(finalizeTx).to.changeTokenBalances(iexecPoco, [workers[i]], [0]); + } + } + expect((await iexecPoco.viewTask(taskId)).status).to.equal( + TaskStatusEnum.COMPLETED, + ); + const expectedFrozenChanges = [0, -taskPrice, -schedulerStakePerTask, 0, 0]; + for (let i = 0; i < workerNumber; i++) { + expectedFrozenChanges.push(0); + } + await changesInFrozen({ + accountsInitBalances, + frozenChanges: expectedFrozenChanges, + }); + for (let i = 0; i < workerNumber; i++) { + if (i !== 1) { + expect(await iexecPoco.viewScore(workers[i].address)).to.be.equal(1); + } else { + expect(await iexecPoco.viewScore(workers[i].address)).to.be.equal(0); } } }); diff --git a/test/100_fullchain-5workers-1error.js b/test/100_fullchain-5workers-1error.js.skip similarity index 100% rename from test/100_fullchain-5workers-1error.js rename to test/100_fullchain-5workers-1error.js.skip From bde090703e2068a1662410abe3be7455eb31df8d Mon Sep 17 00:00:00 2001 From: Gabriel Fournier Date: Wed, 20 Nov 2024 11:14:54 +0100 Subject: [PATCH 02/11] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d8d37990..c31e107ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Migrate integration test files to Typescript & Hardhat: - 000_fullchain.js (#156, #157) - 00X_fullchain-Xworkers.js (#158, #159) + - 000_fullchain-5workers-1error.js (#160) - Remove `smock` from unit tests: - IexecEscrow.v8 (#154, #155) - IexecPocoDelegate (#149, #151) From f030a5564dd21fed52e859eb5f386be6dbb37db9 Mon Sep 17 00:00:00 2001 From: Gabriel Fournier Date: Wed, 20 Nov 2024 11:19:25 +0100 Subject: [PATCH 03/11] update description test array --- test/000_fullchain.test.ts | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/test/000_fullchain.test.ts b/test/000_fullchain.test.ts index 9a36b2dd7..88bc8108a 100644 --- a/test/000_fullchain.test.ts +++ b/test/000_fullchain.test.ts @@ -16,16 +16,17 @@ import { } from '../utils/poco-tools'; import { IexecWrapper } from './utils/IexecWrapper'; -// +---------+-------------+-------------+-------------+----------+-----+---------------------------------+ -// | | Sponsorship | Replication | Beneficiary | Callback | BoT | Type | -// +---------+-------------+-------------+-------------+----------+-----+---------------------------------+ -// | [1] | ✔ | ✔ | ✔ | ✔ | ✔ | Standard | -// | [2] | x | ✔ | ✔ | ✔ | ✔ | Standard | -// | [3] | ✔ | x | ✔ | ✔ | ✔ | Standard,TEE | -// | [4] | x | x | ✔ | ✔ | ✔ | Standard,TEE | -// | [5] | x | x | x | x | x | Standard,TEE | -// | [6.x] | x | ✔ | x | x | x | Standard,TEE, X good workers | -// +---------+-------------+-------------+-------------+----------+-----+---------------------------------+ +// +---------+-------------+-------------+-------------+----------+-----+---------------------------------------------+ +// | | Sponsorship | Replication | Beneficiary | Callback | BoT | Type | +// +---------+-------------+-------------+-------------+----------+-----+---------------------------------------------+ +// | [1] | ✔ | ✔ | ✔ | ✔ | ✔ | Standard | +// | [2] | x | ✔ | ✔ | ✔ | ✔ | Standard | +// | [3] | ✔ | x | ✔ | ✔ | ✔ | Standard,TEE | +// | [4] | x | x | ✔ | ✔ | ✔ | Standard,TEE | +// | [5] | x | x | x | x | x | Standard,TEE | +// | [6.x] | x | ✔ | x | x | x | Standard,TEE, X good workers | +// | [7.x] | x | ✔ | x | x | x | Standard,TEE, X good workers 1 bad worker | +// +---------+-------------+-------------+-------------+----------+-----+---------------------------------------------+ const standardDealTag = '0x0000000000000000000000000000000000000000000000000000000000000000'; const teeDealTag = '0x0000000000000000000000000000000000000000000000000000000000000001'; From 15df1d9d4210038b1db2027cf69a790b12ea3667 Mon Sep 17 00:00:00 2001 From: Gabriel Fournier Date: Wed, 20 Nov 2024 13:42:27 +0100 Subject: [PATCH 04/11] update for more readability --- test/000_fullchain.test.ts | 89 +++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 49 deletions(-) diff --git a/test/000_fullchain.test.ts b/test/000_fullchain.test.ts index 88bc8108a..ee4def5a8 100644 --- a/test/000_fullchain.test.ts +++ b/test/000_fullchain.test.ts @@ -308,17 +308,24 @@ describe('Integration tests', function () { } for (let workerNumber = 4; workerNumber < 6; workerNumber++) { let goodWorkersNumber = workerNumber - 1; - // Worker2 will contribute badly + // Worker1 will contribute badly it(`[7.${workerNumber - 3}] No sponsorship, no beneficiary, no callback, no BoT, up to ${workerNumber} workers with 1 bad actor`, async function () { const volume = 1; - const workers = [worker1, worker2, worker3, worker4, worker5]; - const disposableWokers = workers.slice(0, workerNumber); + const workersAvailable = [worker1, worker2, worker3, worker4, worker5]; + const { resultDigest: badResultDigest } = buildUtf8ResultAndDigest('bad-result'); + const losingWorker = worker1; + const winningWorkers = workersAvailable.slice(1, workerNumber); + let workers = [{ signer: worker1, resultDigest: badResultDigest }]; + for (const worker of winningWorkers) { + workers.push({ signer: worker, resultDigest: resultDigest }); + } const acounts = [ requester, scheduler, appProvider, datasetProvider, - ...disposableWokers, + losingWorker, + ...winningWorkers, ]; // Create deal. const orders = buildOrders({ @@ -352,41 +359,29 @@ describe('Integration tests', function () { let frozen = (await iexecPoco.frozenOf(account.address)).toNumber(); accountsInitBalances.push({ address, frozen }); } - for (let i = 0; i < workerNumber; i++) { - expect(await iexecPoco.viewScore(workers[i].address)).to.be.equal(0); + // for (let i = 0; i < workerNumber; i++) { + for (const worker of workers) { + expect(await iexecPoco.viewScore(worker.signer.address)).to.be.equal(0); } + // } const taskId = await iexecWrapper.initializeTask(dealId, 0); // Finalize each task and check balance changes. const workerStake = await iexecPoco .viewDeal(dealId) .then((deal) => deal.workerStake.toNumber()); - - for (let i = 0; i < workerNumber; i++) { - if (i == 1) { - const { resultDigest: badResultDigest } = - buildUtf8ResultAndDigest('bad-result'); - await iexecWrapper.contributeToTask( - dealId, - 0, - badResultDigest, - disposableWokers[i], - ); - } else { - await iexecWrapper.contributeToTask( - dealId, - 0, - resultDigest, - disposableWokers[i], - ); - } + for (const worker of workers) { + await iexecWrapper.contributeToTask( + dealId, + 0, + worker.resultDigest, + worker.signer, + ); } - for (let i = 0; i < workerNumber; i++) { - if (i !== 1) { - await iexecPoco - .connect(disposableWokers[i]) - .reveal(taskId, resultDigest) - .then((tx) => tx.wait()); - } + for (const winningWorker of winningWorkers) { + await iexecPoco + .connect(winningWorker) + .reveal(taskId, resultDigest) + .then((tx) => tx.wait()); } const finalizeTx = await iexecPoco .connect(scheduler) @@ -402,20 +397,23 @@ describe('Integration tests', function () { datasetPrice, ], ); - for (let i = 0; i < workerNumber; i++) { - if (i !== 1) { - expect(finalizeTx).to.changeTokenBalances( - iexecPoco, - [workers[i]], - [workerStake + workerRewardPerTask / goodWorkersNumber], - ); - } else { - expect(finalizeTx).to.changeTokenBalances(iexecPoco, [workers[i]], [0]); - } + // checks on losing worker + expect(finalizeTx).to.changeTokenBalances(iexecPoco, [losingWorker], [0]); + expect(await iexecPoco.viewScore(losingWorker.address)).to.be.equal(0); + // checks on winning workers + for (const winningWorker of winningWorkers) { + expect(finalizeTx).to.changeTokenBalances( + iexecPoco, + [winningWorker.address], + [workerStake + workerRewardPerTask / goodWorkersNumber], + ); + expect(await iexecPoco.viewScore(winningWorker.address)).to.be.equal(1); } + // verify task status expect((await iexecPoco.viewTask(taskId)).status).to.equal( TaskStatusEnum.COMPLETED, ); + // checks n frozen balance changes const expectedFrozenChanges = [0, -taskPrice, -schedulerStakePerTask, 0, 0]; for (let i = 0; i < workerNumber; i++) { expectedFrozenChanges.push(0); @@ -424,13 +422,6 @@ describe('Integration tests', function () { accountsInitBalances, frozenChanges: expectedFrozenChanges, }); - for (let i = 0; i < workerNumber; i++) { - if (i !== 1) { - expect(await iexecPoco.viewScore(workers[i].address)).to.be.equal(1); - } else { - expect(await iexecPoco.viewScore(workers[i].address)).to.be.equal(0); - } - } }); } }); From 3823a3f252cc4a1941ed59e9f1bb7ae00dbcda26 Mon Sep 17 00:00:00 2001 From: Gabriel Fournier Date: Wed, 20 Nov 2024 14:05:55 +0100 Subject: [PATCH 05/11] clean --- test/000_fullchain.test.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/000_fullchain.test.ts b/test/000_fullchain.test.ts index ee4def5a8..4c26da6ca 100644 --- a/test/000_fullchain.test.ts +++ b/test/000_fullchain.test.ts @@ -359,11 +359,9 @@ describe('Integration tests', function () { let frozen = (await iexecPoco.frozenOf(account.address)).toNumber(); accountsInitBalances.push({ address, frozen }); } - // for (let i = 0; i < workerNumber; i++) { for (const worker of workers) { expect(await iexecPoco.viewScore(worker.signer.address)).to.be.equal(0); } - // } const taskId = await iexecWrapper.initializeTask(dealId, 0); // Finalize each task and check balance changes. const workerStake = await iexecPoco From 5c6045a181b7d5a60e17355026900ac504cfffaa Mon Sep 17 00:00:00 2001 From: Gabriel Fournier Date: Wed, 20 Nov 2024 15:04:18 +0100 Subject: [PATCH 06/11] simplify view score check on previous test --- test/000_fullchain.test.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/test/000_fullchain.test.ts b/test/000_fullchain.test.ts index 4c26da6ca..ef6eb9919 100644 --- a/test/000_fullchain.test.ts +++ b/test/000_fullchain.test.ts @@ -298,11 +298,9 @@ describe('Integration tests', function () { frozenChanges: expectedFrozenChanges, }); for (let i = 0; i < workerNumber; i++) { - if (workerNumber == 1) { - expect(await iexecPoco.viewScore(workers[i].address)).to.be.equal(0); - } else { - expect(await iexecPoco.viewScore(workers[i].address)).to.be.equal(1); - } + expect(await iexecPoco.viewScore(workers[i].address)).to.be.equal( + workerNumber == 1 ? 0 : 1, + ); } }); } From cfc70345478365f9a3a400b4929d9d847a174861 Mon Sep 17 00:00:00 2001 From: Gabriel Fournier Date: Wed, 20 Nov 2024 16:19:52 +0100 Subject: [PATCH 07/11] clean goodWorkersNumber variable --- test/000_fullchain.test.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/000_fullchain.test.ts b/test/000_fullchain.test.ts index ef6eb9919..9ae5d827c 100644 --- a/test/000_fullchain.test.ts +++ b/test/000_fullchain.test.ts @@ -305,7 +305,6 @@ describe('Integration tests', function () { }); } for (let workerNumber = 4; workerNumber < 6; workerNumber++) { - let goodWorkersNumber = workerNumber - 1; // Worker1 will contribute badly it(`[7.${workerNumber - 3}] No sponsorship, no beneficiary, no callback, no BoT, up to ${workerNumber} workers with 1 bad actor`, async function () { const volume = 1; @@ -333,7 +332,7 @@ describe('Integration tests', function () { tag: standardDealTag, beneficiary: beneficiary.address, volume, - trust: goodWorkersNumber, + trust: winningWorkers.length, }); const { dealId, dealPrice, schedulerStakePerDeal } = @@ -401,7 +400,7 @@ describe('Integration tests', function () { expect(finalizeTx).to.changeTokenBalances( iexecPoco, [winningWorker.address], - [workerStake + workerRewardPerTask / goodWorkersNumber], + [workerStake + workerRewardPerTask / winningWorkers.length], ); expect(await iexecPoco.viewScore(winningWorker.address)).to.be.equal(1); } @@ -409,7 +408,7 @@ describe('Integration tests', function () { expect((await iexecPoco.viewTask(taskId)).status).to.equal( TaskStatusEnum.COMPLETED, ); - // checks n frozen balance changes + // checks on frozen balance changes const expectedFrozenChanges = [0, -taskPrice, -schedulerStakePerTask, 0, 0]; for (let i = 0; i < workerNumber; i++) { expectedFrozenChanges.push(0); From 83a8e64ddaffed58c766134199b94c27165f98be Mon Sep 17 00:00:00 2001 From: Gabriel Fournier Date: Thu, 21 Nov 2024 11:52:44 +0100 Subject: [PATCH 08/11] typo and create getInitialFrozens function --- test/000_fullchain.test.ts | 62 ++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 33 deletions(-) diff --git a/test/000_fullchain.test.ts b/test/000_fullchain.test.ts index 9ae5d827c..2c034a8d8 100644 --- a/test/000_fullchain.test.ts +++ b/test/000_fullchain.test.ts @@ -215,7 +215,7 @@ describe('Integration tests', function () { const volume = 1; const disposableWorkers = [worker1, worker2, worker3, worker4, worker5]; const workers = disposableWorkers.slice(0, workerNumber); - const acounts = [requester, scheduler, appProvider, datasetProvider, ...workers]; + const accounts = [requester, scheduler, appProvider, datasetProvider, ...workers]; // Create deal. const orders = buildOrders({ assets: ordersAssets, @@ -235,18 +235,8 @@ describe('Integration tests', function () { PocoMode.CLASSIC, ); const schedulerRewardPerTask = workerpoolPrice - workerRewardPerTask; - // Check initial balances. - let accountsInitBalances = [ - { - address: proxyAddress, - frozen: (await iexecPoco.frozenOf(proxyAddress)).toNumber(), - }, - ]; - for (const account of acounts) { - let address = account.address; - let frozen = (await iexecPoco.frozenOf(account.address)).toNumber(); - accountsInitBalances.push({ address, frozen }); - } + const accountsInitialFrozens = await getInitialFrozens(accounts); + for (let i = 0; i < workerNumber; i++) { expect(await iexecPoco.viewScore(workers[i].address)).to.be.equal(0); } @@ -294,7 +284,7 @@ describe('Integration tests', function () { expectedFrozenChanges.push(0); } await changesInFrozen({ - accountsInitBalances, + accountsInitialFrozens, frozenChanges: expectedFrozenChanges, }); for (let i = 0; i < workerNumber; i++) { @@ -306,7 +296,7 @@ describe('Integration tests', function () { } for (let workerNumber = 4; workerNumber < 6; workerNumber++) { // Worker1 will contribute badly - it(`[7.${workerNumber - 3}] No sponsorship, no beneficiary, no callback, no BoT, up to ${workerNumber} workers with 1 bad actor`, async function () { + it(`[7.${workerNumber - 3}] No sponsorship, no beneficiary, no callback, no BoT, up to ${workerNumber} workers with 1 bad worker`, async function () { const volume = 1; const workersAvailable = [worker1, worker2, worker3, worker4, worker5]; const { resultDigest: badResultDigest } = buildUtf8ResultAndDigest('bad-result'); @@ -316,7 +306,7 @@ describe('Integration tests', function () { for (const worker of winningWorkers) { workers.push({ signer: worker, resultDigest: resultDigest }); } - const acounts = [ + const accounts = [ requester, scheduler, appProvider, @@ -344,23 +334,13 @@ describe('Integration tests', function () { PocoMode.CLASSIC, ); const schedulerRewardPerTask = workerpoolPrice - workerRewardPerTask; + const accountsInitialFrozens = await getInitialFrozens(accounts); // Check initial balances. - let accountsInitBalances = [ - { - address: proxyAddress, - frozen: (await iexecPoco.frozenOf(proxyAddress)).toNumber(), - }, - ]; - for (const account of acounts) { - let address = account.address; - let frozen = (await iexecPoco.frozenOf(account.address)).toNumber(); - accountsInitBalances.push({ address, frozen }); - } for (const worker of workers) { expect(await iexecPoco.viewScore(worker.signer.address)).to.be.equal(0); } const taskId = await iexecWrapper.initializeTask(dealId, 0); - // Finalize each task and check balance changes. + // Finalize task and check balance changes. const workerStake = await iexecPoco .viewDeal(dealId) .then((deal) => deal.workerStake.toNumber()); @@ -414,12 +394,28 @@ describe('Integration tests', function () { expectedFrozenChanges.push(0); } await changesInFrozen({ - accountsInitBalances, + accountsInitialFrozens, frozenChanges: expectedFrozenChanges, }); }); } }); + + async function getInitialFrozens(accounts: SignerWithAddress[]) { + let initialFrozens = [ + { + address: proxyAddress, + frozen: (await iexecPoco.frozenOf(proxyAddress)).toNumber(), + }, + ]; + for (const account of accounts) { + initialFrozens.push({ + address: account.address, + frozen: (await iexecPoco.frozenOf(account.address)).toNumber(), + }); + } + return initialFrozens; + } }); async function checkBalancesAndFrozens(args: { @@ -438,13 +434,13 @@ async function checkBalancesAndFrozens(args: { } async function changesInFrozen(args: { - accountsInitBalances: { address: string; frozen: number }[]; + accountsInitialFrozens: { address: string; frozen: number }[]; frozenChanges: number[]; }) { - for (let i = 0; i < args.accountsInitBalances.length; i++) { + for (let i = 0; i < args.accountsInitialFrozens.length; i++) { const message = `Failed with account at index ${i}`; - expect(await iexecPoco.frozenOf(args.accountsInitBalances[i].address)).to.equal( - args.accountsInitBalances[i].frozen + args.frozenChanges[i], + expect(await iexecPoco.frozenOf(args.accountsInitialFrozens[i].address)).to.equal( + args.accountsInitialFrozens[i].frozen + args.frozenChanges[i], message, ); } From 715c453c77ebbf3915c88e780564b53129cf4d78 Mon Sep 17 00:00:00 2001 From: Gabriel Fournier Date: Thu, 21 Nov 2024 12:03:30 +0100 Subject: [PATCH 09/11] update to contributions naming --- test/000_fullchain.test.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/000_fullchain.test.ts b/test/000_fullchain.test.ts index 2c034a8d8..608c8ee4c 100644 --- a/test/000_fullchain.test.ts +++ b/test/000_fullchain.test.ts @@ -302,9 +302,9 @@ describe('Integration tests', function () { const { resultDigest: badResultDigest } = buildUtf8ResultAndDigest('bad-result'); const losingWorker = worker1; const winningWorkers = workersAvailable.slice(1, workerNumber); - let workers = [{ signer: worker1, resultDigest: badResultDigest }]; + let contributions = [{ signer: worker1, resultDigest: badResultDigest }]; for (const worker of winningWorkers) { - workers.push({ signer: worker, resultDigest: resultDigest }); + contributions.push({ signer: worker, resultDigest: resultDigest }); } const accounts = [ requester, @@ -336,20 +336,20 @@ describe('Integration tests', function () { const schedulerRewardPerTask = workerpoolPrice - workerRewardPerTask; const accountsInitialFrozens = await getInitialFrozens(accounts); // Check initial balances. - for (const worker of workers) { - expect(await iexecPoco.viewScore(worker.signer.address)).to.be.equal(0); + for (const contributor of contributions) { + expect(await iexecPoco.viewScore(contributor.signer.address)).to.be.equal(0); } const taskId = await iexecWrapper.initializeTask(dealId, 0); // Finalize task and check balance changes. const workerStake = await iexecPoco .viewDeal(dealId) .then((deal) => deal.workerStake.toNumber()); - for (const worker of workers) { + for (const contributor of contributions) { await iexecWrapper.contributeToTask( dealId, 0, - worker.resultDigest, - worker.signer, + contributor.resultDigest, + contributor.signer, ); } for (const winningWorker of winningWorkers) { From 0764ba1e90e606906a52a302d8cf30cf1aba6072 Mon Sep 17 00:00:00 2001 From: Gabriel Fournier Date: Thu, 21 Nov 2024 12:12:41 +0100 Subject: [PATCH 10/11] checks that bad worker can't reveal --- test/000_fullchain.test.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/000_fullchain.test.ts b/test/000_fullchain.test.ts index 608c8ee4c..0c14a4766 100644 --- a/test/000_fullchain.test.ts +++ b/test/000_fullchain.test.ts @@ -352,6 +352,10 @@ describe('Integration tests', function () { contributor.signer, ); } + // verify that the bad worker can't reveal. + await expect( + iexecPoco.connect(losingWorker).reveal(taskId, badResultDigest), + ).to.be.revertedWithoutReason(); for (const winningWorker of winningWorkers) { await iexecPoco .connect(winningWorker) From 982f21c5ce13fddd16df334507bd33eef881b229 Mon Sep 17 00:00:00 2001 From: Gabriel Fournier Date: Thu, 21 Nov 2024 14:50:25 +0100 Subject: [PATCH 11/11] only test one case with 5 total workers --- test/000_fullchain.test.ts | 210 ++++++++++++++++++------------------- 1 file changed, 102 insertions(+), 108 deletions(-) diff --git a/test/000_fullchain.test.ts b/test/000_fullchain.test.ts index 0c14a4766..73101d786 100644 --- a/test/000_fullchain.test.ts +++ b/test/000_fullchain.test.ts @@ -25,7 +25,7 @@ import { IexecWrapper } from './utils/IexecWrapper'; // | [4] | x | x | ✔ | ✔ | ✔ | Standard,TEE | // | [5] | x | x | x | x | x | Standard,TEE | // | [6.x] | x | ✔ | x | x | x | Standard,TEE, X good workers | -// | [7.x] | x | ✔ | x | x | x | Standard,TEE, X good workers 1 bad worker | +// | [7] | x | ✔ | x | x | x | Standard,TEE, 4 good workers 1 bad worker | // +---------+-------------+-------------+-------------+----------+-----+---------------------------------------------+ const standardDealTag = '0x0000000000000000000000000000000000000000000000000000000000000000'; @@ -294,115 +294,109 @@ describe('Integration tests', function () { } }); } - for (let workerNumber = 4; workerNumber < 6; workerNumber++) { - // Worker1 will contribute badly - it(`[7.${workerNumber - 3}] No sponsorship, no beneficiary, no callback, no BoT, up to ${workerNumber} workers with 1 bad worker`, async function () { - const volume = 1; - const workersAvailable = [worker1, worker2, worker3, worker4, worker5]; - const { resultDigest: badResultDigest } = buildUtf8ResultAndDigest('bad-result'); - const losingWorker = worker1; - const winningWorkers = workersAvailable.slice(1, workerNumber); - let contributions = [{ signer: worker1, resultDigest: badResultDigest }]; - for (const worker of winningWorkers) { - contributions.push({ signer: worker, resultDigest: resultDigest }); - } - const accounts = [ - requester, - scheduler, - appProvider, - datasetProvider, - losingWorker, - ...winningWorkers, - ]; - // Create deal. - const orders = buildOrders({ - assets: ordersAssets, - prices: ordersPrices, - requester: requester.address, - tag: standardDealTag, - beneficiary: beneficiary.address, - volume, - trust: winningWorkers.length, - }); + }); + it(`[7] No sponsorship, no beneficiary, no callback, no BoT, up to 5 workers with 1 bad worker`, async function () { + const volume = 1; + const workersAvailable = [worker1, worker2, worker3, worker4, worker5]; + const { resultDigest: badResultDigest } = buildUtf8ResultAndDigest('bad-result'); + const losingWorker = worker1; + const winningWorkers = workersAvailable.slice(1, workersAvailable.length); + let contributions = [{ signer: worker1, resultDigest: badResultDigest }]; + for (const worker of winningWorkers) { + contributions.push({ signer: worker, resultDigest: resultDigest }); + } + const accounts = [ + requester, + scheduler, + appProvider, + datasetProvider, + losingWorker, + ...winningWorkers, + ]; + // Create deal. + const orders = buildOrders({ + assets: ordersAssets, + prices: ordersPrices, + requester: requester.address, + tag: standardDealTag, + beneficiary: beneficiary.address, + volume, + trust: winningWorkers.length, + }); - const { dealId, dealPrice, schedulerStakePerDeal } = - await iexecWrapper.signAndMatchOrders(...orders.toArray()); - const taskPrice = appPrice + datasetPrice + workerpoolPrice; - const schedulerStakePerTask = schedulerStakePerDeal / volume; - const workerRewardPerTask = await iexecWrapper.computeWorkerRewardPerTask( - dealId, - PocoMode.CLASSIC, - ); - const schedulerRewardPerTask = workerpoolPrice - workerRewardPerTask; - const accountsInitialFrozens = await getInitialFrozens(accounts); - // Check initial balances. - for (const contributor of contributions) { - expect(await iexecPoco.viewScore(contributor.signer.address)).to.be.equal(0); - } - const taskId = await iexecWrapper.initializeTask(dealId, 0); - // Finalize task and check balance changes. - const workerStake = await iexecPoco - .viewDeal(dealId) - .then((deal) => deal.workerStake.toNumber()); - for (const contributor of contributions) { - await iexecWrapper.contributeToTask( - dealId, - 0, - contributor.resultDigest, - contributor.signer, - ); - } - // verify that the bad worker can't reveal. - await expect( - iexecPoco.connect(losingWorker).reveal(taskId, badResultDigest), - ).to.be.revertedWithoutReason(); - for (const winningWorker of winningWorkers) { - await iexecPoco - .connect(winningWorker) - .reveal(taskId, resultDigest) - .then((tx) => tx.wait()); - } - const finalizeTx = await iexecPoco - .connect(scheduler) - .finalize(taskId, results, '0x'); - expect(finalizeTx).to.changeTokenBalances( - iexecPoco, - [proxyAddress, requester, scheduler, appProvider, datasetProvider], - [ - -(dealPrice + schedulerStakePerDeal), - 0, - schedulerStakePerTask + schedulerRewardPerTask, - appPrice, - datasetPrice, - ], - ); - // checks on losing worker - expect(finalizeTx).to.changeTokenBalances(iexecPoco, [losingWorker], [0]); - expect(await iexecPoco.viewScore(losingWorker.address)).to.be.equal(0); - // checks on winning workers - for (const winningWorker of winningWorkers) { - expect(finalizeTx).to.changeTokenBalances( - iexecPoco, - [winningWorker.address], - [workerStake + workerRewardPerTask / winningWorkers.length], - ); - expect(await iexecPoco.viewScore(winningWorker.address)).to.be.equal(1); - } - // verify task status - expect((await iexecPoco.viewTask(taskId)).status).to.equal( - TaskStatusEnum.COMPLETED, - ); - // checks on frozen balance changes - const expectedFrozenChanges = [0, -taskPrice, -schedulerStakePerTask, 0, 0]; - for (let i = 0; i < workerNumber; i++) { - expectedFrozenChanges.push(0); - } - await changesInFrozen({ - accountsInitialFrozens, - frozenChanges: expectedFrozenChanges, - }); - }); + const { dealId, dealPrice, schedulerStakePerDeal } = await iexecWrapper.signAndMatchOrders( + ...orders.toArray(), + ); + const taskPrice = appPrice + datasetPrice + workerpoolPrice; + const schedulerStakePerTask = schedulerStakePerDeal / volume; + const workerRewardPerTask = await iexecWrapper.computeWorkerRewardPerTask( + dealId, + PocoMode.CLASSIC, + ); + const schedulerRewardPerTask = workerpoolPrice - workerRewardPerTask; + const accountsInitialFrozens = await getInitialFrozens(accounts); + // Check initial balances. + for (const contributor of contributions) { + expect(await iexecPoco.viewScore(contributor.signer.address)).to.be.equal(0); } + const taskId = await iexecWrapper.initializeTask(dealId, 0); + // Finalize task and check balance changes. + const workerStake = await iexecPoco + .viewDeal(dealId) + .then((deal) => deal.workerStake.toNumber()); + for (const contributor of contributions) { + await iexecWrapper.contributeToTask( + dealId, + 0, + contributor.resultDigest, + contributor.signer, + ); + } + // verify that the bad worker can't reveal. + await expect( + iexecPoco.connect(losingWorker).reveal(taskId, badResultDigest), + ).to.be.revertedWithoutReason(); + for (const winningWorker of winningWorkers) { + await iexecPoco + .connect(winningWorker) + .reveal(taskId, resultDigest) + .then((tx) => tx.wait()); + } + const finalizeTx = await iexecPoco.connect(scheduler).finalize(taskId, results, '0x'); + expect(finalizeTx).to.changeTokenBalances( + iexecPoco, + [proxyAddress, requester, scheduler, appProvider, datasetProvider], + [ + -(dealPrice + schedulerStakePerDeal), + 0, + schedulerStakePerTask + schedulerRewardPerTask, + appPrice, + datasetPrice, + ], + ); + // checks on losing worker + expect(finalizeTx).to.changeTokenBalances(iexecPoco, [losingWorker], [0]); + expect(await iexecPoco.viewScore(losingWorker.address)).to.be.equal(0); + // checks on winning workers + for (const winningWorker of winningWorkers) { + expect(finalizeTx).to.changeTokenBalances( + iexecPoco, + [winningWorker.address], + [workerStake + workerRewardPerTask / winningWorkers.length], + ); + expect(await iexecPoco.viewScore(winningWorker.address)).to.be.equal(1); + } + // verify task status + expect((await iexecPoco.viewTask(taskId)).status).to.equal(TaskStatusEnum.COMPLETED); + // checks on frozen balance changes + const expectedFrozenChanges = [0, -taskPrice, -schedulerStakePerTask, 0, 0]; + for (let i = 0; i < workersAvailable.length; i++) { + expectedFrozenChanges.push(0); + } + await changesInFrozen({ + accountsInitialFrozens, + frozenChanges: expectedFrozenChanges, + }); }); async function getInitialFrozens(accounts: SignerWithAddress[]) {