Skip to content

Commit 8e99998

Browse files
authored
Merge pull request #645 from iExecBlockchainComputing/release/9.0.0
2 parents ee7315f + 34dd05d commit 8e99998

File tree

79 files changed

+1580
-963
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+1580
-963
lines changed

CHANGELOG.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,48 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## [[9.0.0]](https://github.com/iExecBlockchainComputing/iexec-worker/releases/tag/v9.0.0) 2025-04-01
6+
7+
### New Features
8+
9+
- Use TEE framework version of dApp to retrieve pre/post-compute properties via SMS endpoint. (#630)
10+
- Validate authorization proof for pre/post-compute requests. (#635)
11+
- Add `WebSocketBlockchainListener` to fetch latest block without polling the blockchain network. (#639)
12+
13+
### Bug Fixes
14+
15+
- Add synchronized keyword on abort method to avoid concurrency issues on file system. (#643)
16+
17+
### Quality
18+
19+
- Refactor `RestTemplateConfig` to use `HttpClient 5` and improve proxy handling. (#626)
20+
- Replace deprecated `connect` with `connectAsync` in `StompClientService`. (#627)
21+
- Remove redundant blockchain calls to diminish pressure on Ethereum JSON-RPC API. (#632)
22+
- Stop using `TestUtils` in `ContributionServiceTests`. (#640)
23+
- Fix several issues raised by SonarQube Cloud. (#642)
24+
- Improve JavaDoc comments in `ComputeManagerService` and `DockerService`. (#643)
25+
26+
### Breaking API changes
27+
28+
- Do not fall back to blockchain adapter URL when fetching public configuration. (#628 #629)
29+
- Move `WorkerModel` from `iexec-common` to `iexec-core-library`. (#633)
30+
- Move `TaskAbortCause` from `iexec-commons-poco` to `iexec-core-library`. (#634)
31+
- Move `Contribution` from `iexec-common` to `iexec-worker`. (#636)
32+
- Harmonize YML internal variables to proper case. (#638 #641)
33+
- Merge split URL configuration properties (protocol, host, port) to a single URL field to offer URL validation at startup. (#641)
34+
35+
### Dependency Upgrades
36+
37+
- Upgrade to `eclipse-temurin:17.0.13_11-jre-focal`. (#626)
38+
- Upgrade to Sring Cloud 2022.0.5. (#626)
39+
- Upgrade to Spring Boot 3.3.8. (#631)
40+
- Upgrade to `iexec-commons-poco` 5.0.0. (#644)
41+
- Upgrade to `iexec-common` 9.0.0. (#644)
42+
- Upgrade to `iexec-commons-containers` 2.0.0. (#644)
43+
- Upgrade to `iexec-result-proxy-library` 9.0.0. (#644)
44+
- Upgrade to `iexec-sms-library` 9.0.0. (#644)
45+
- Upgrade to `iexec-core-library` 9.0.0. (#644)
46+
547
## [[8.6.0]](https://github.com/iExecBlockchainComputing/iexec-worker/releases/tag/v8.6.0) 2024-12-23
648

749
### New Features

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM eclipse-temurin:11.0.24_8-jre-focal
1+
FROM eclipse-temurin:17.0.13_11-jre-focal
22

33
ARG jar
44

README.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,7 @@ You can configure the _iExec Worker_ with the following properties:
1919
| Environment variable | Description | Type | Default value |
2020
|-------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------|-------------------------------------------------------------|
2121
| `IEXEC_WORKER_PORT` | Server HTTP port of the _iExec Worker_. | Positive integer | `13100` |
22-
| `IEXEC_CORE_PROTOCOL` | Protocol to connect to the _iExec Core Scheduler_. | String | `http` |
23-
| `IEXEC_CORE_HOST` | Host to connect to the _iExec Core Scheduler_. | String | `localhost` |
24-
| `IEXEC_CORE_PORT` | Port to connect to the _iExec Core Scheduler_. | Positive integer | `13000` |
22+
| `IEXEC_CORE_URL` | URL to connect to the _iExec Core Scheduler_. | String | `http://localhost:13000` |
2523
| `IEXEC_WORKER_NAME` | Public name of the _iExec Worker_. | String | `worker` |
2624
| `POOL_ADDRESS` | On-chain address of the workerpool managed by the _iExec Core Scheduler_, the default value must be changed. | String | `0x0` |
2725
| `IEXEC_WORKER_BASE_DIR` | Path to the folder within which the _iExec Worker_ will read-and-write inputs and outputs of tasks. | String | `/tmp/iexec-worker` |

build.gradle

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
plugins {
22
id 'java'
33
id 'io.freefair.lombok' version '8.10.2'
4-
id 'org.springframework.boot' version '2.7.18'
4+
id 'org.springframework.boot' version '3.3.8'
55
id 'io.spring.dependency-management' version '1.1.6'
66
id 'jacoco'
77
id 'org.sonarqube' version '5.1.0.4882'
@@ -11,7 +11,7 @@ plugins {
1111
group = 'com.iexec.worker'
1212

1313
ext {
14-
springCloudVersion = '2021.0.8'
14+
springCloudVersion = '2023.0.5'
1515
commonsMathsVersion = '3.6.1'
1616
testContainersVersion = '1.20.4'
1717
}
@@ -61,21 +61,19 @@ dependencies {
6161
implementation "org.springframework.boot:spring-boot-starter-web"
6262
implementation "org.springframework.boot:spring-boot-starter-websocket"
6363
implementation "org.springframework.cloud:spring-cloud-starter"
64-
implementation "org.springframework.cloud:spring-cloud-starter-openfeign"
6564
implementation "org.springframework.retry:spring-retry"
6665

66+
// required for spring-retry
67+
runtimeOnly 'org.aspectj:aspectjweaver'
68+
6769
// apache commons-lang3
6870
implementation 'org.apache.commons:commons-lang3'
6971

7072
// Apache commons-math3
7173
implementation "org.apache.commons:commons-math3:${commonsMathsVersion}"
7274

7375
// Required for com.iexec.worker.feign.config.RestTemplateConfig
74-
implementation 'org.apache.httpcomponents:httpclient'
75-
76-
implementation 'org.glassfish.jersey.inject:jersey-hk2'
77-
implementation 'org.glassfish.jersey.bundles.repackaged:jersey-guava:2.25.1'
78-
implementation 'javax.activation:activation:1.1.1'
76+
implementation 'org.apache.httpcomponents.client5:httpclient5'
7977

8078
// Removes 'warning: unknown enum constant When.MAYBE'
8179
implementation 'com.google.code.findbugs:annotations:3.0.1'
@@ -91,8 +89,12 @@ java {
9189
toolchain {
9290
languageVersion.set(JavaLanguageVersion.of(17))
9391
}
94-
sourceCompatibility = "11"
95-
targetCompatibility = "11"
92+
sourceCompatibility = JavaVersion.VERSION_17
93+
targetCompatibility = JavaVersion.VERSION_17
94+
}
95+
96+
tasks.withType(JavaCompile).configureEach {
97+
options.compilerArgs.add('-parameters')
9698
}
9799

98100
springBoot {
@@ -111,12 +113,11 @@ testing {
111113
test {
112114
useJUnitJupiter()
113115
dependencies {
114-
implementation "org.springframework.boot:spring-boot-starter-test"
115-
implementation "org.mockito:mockito-inline" // activates mocking final classes/methods
116-
117116
// awaitility
118117
implementation "org.awaitility:awaitility"
119118

119+
implementation "org.springframework.boot:spring-boot-starter-test"
120+
120121
// testcontainers
121122
implementation "org.testcontainers:junit-jupiter:$testContainersVersion"
122123
}

docker-compose.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
services:
2+
3+
chain:
4+
image: docker-regis.iex.ec/poco-chain:1.0.0-poco-v5.5.0-voucher-v1.0.0-nethermind
5+
expose:
6+
- "8545"
7+
8+
core:
9+
image: wiremock/wiremock:3.3.1
10+
expose:
11+
- "8080"
12+
volumes:
13+
- "./src/test/resources/wiremock/mappings:/home/wiremock/mappings"

gradle.properties

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
version=8.6.0
2-
iexecCommonsPocoVersion=4.2.0
3-
iexecCommonVersion=8.6.0
4-
iexecCommonsContainersVersion=1.2.3
5-
iexecResultVersion=8.6.0
6-
iexecSmsVersion=8.7.0
7-
iexecCoreVersion=8.6.0
1+
version=9.0.0
2+
iexecCommonsPocoVersion=5.0.0
3+
iexecCommonVersion=9.0.0
4+
iexecCommonsContainersVersion=2.0.0
5+
iexecResultVersion=9.0.0
6+
iexecSmsVersion=9.0.0
7+
iexecCoreVersion=9.0.0
88
nexusUser
99
nexusPassword

src/main/java/com/iexec/worker/Application.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2024 IEXEC BLOCKCHAIN TECH
2+
* Copyright 2020-2025 IEXEC BLOCKCHAIN TECH
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -28,7 +28,7 @@
2828
import org.springframework.boot.SpringApplication;
2929
import org.springframework.boot.autoconfigure.SpringBootApplication;
3030
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
31-
import org.springframework.cloud.openfeign.EnableFeignClients;
31+
import org.springframework.context.annotation.Profile;
3232
import org.springframework.retry.annotation.EnableRetry;
3333
import org.springframework.scheduling.annotation.EnableAsync;
3434

@@ -37,8 +37,8 @@
3737
@Slf4j
3838
@EnableRetry
3939
@EnableAsync
40-
@EnableFeignClients
4140
@SpringBootApplication
41+
@Profile("!test")
4242
@ConfigurationPropertiesScan
4343
public class Application implements CommandLineRunner {
4444

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright 2025 IEXEC BLOCKCHAIN TECH
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.iexec.worker.chain;
18+
19+
import lombok.Builder;
20+
21+
@Builder
22+
public record Contribution(String chainTaskId,
23+
String resultDigest,
24+
String resultHash,
25+
String resultSeal,
26+
String enclaveSignature,
27+
String workerPoolSignature,
28+
String enclaveChallenge) {
29+
}

src/main/java/com/iexec/worker/chain/ContributionService.java

Lines changed: 27 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2023 IEXEC BLOCKCHAIN TECH
2+
* Copyright 2020-2025 IEXEC BLOCKCHAIN TECH
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,23 +16,21 @@
1616

1717
package com.iexec.worker.chain;
1818

19-
import com.iexec.common.contribution.Contribution;
2019
import com.iexec.common.replicate.ReplicateStatusCause;
2120
import com.iexec.common.result.ComputedFile;
22-
import com.iexec.common.worker.result.ResultUtils;
2321
import com.iexec.commons.poco.chain.*;
2422
import com.iexec.commons.poco.contract.generated.IexecHubContract;
23+
import com.iexec.commons.poco.task.TaskDescription;
2524
import com.iexec.commons.poco.utils.BytesUtils;
25+
import com.iexec.commons.poco.utils.HashUtils;
2626
import lombok.extern.slf4j.Slf4j;
2727
import org.springframework.stereotype.Service;
2828

2929
import java.math.BigInteger;
30-
import java.util.Date;
3130
import java.util.Optional;
3231

3332
import static com.iexec.common.replicate.ReplicateStatusCause.*;
3433

35-
3634
@Slf4j
3735
@Service
3836
public class ContributionService {
@@ -56,53 +54,49 @@ public boolean isChainTaskInitialized(String chainTaskId) {
5654
return iexecHubService.getTaskDescription(chainTaskId) != null;
5755
}
5856

59-
public Optional<ReplicateStatusCause> getCannotContributeStatusCause(String chainTaskId) {
60-
Optional<ChainTask> optionalChainTask = iexecHubService.getChainTask(chainTaskId);
61-
if (optionalChainTask.isEmpty()) {
62-
return Optional.of(CHAIN_UNREACHABLE);
57+
public Optional<ReplicateStatusCause> getCannotContributeStatusCause(final String chainTaskId) {
58+
if (!isWorkerpoolAuthorizationPresent(chainTaskId)) {
59+
return Optional.of(WORKERPOOL_AUTHORIZATION_NOT_FOUND);
6360
}
6461

65-
ChainTask chainTask = optionalChainTask.get();
62+
final ChainTask chainTask = iexecHubService.getChainTask(chainTaskId).orElse(null);
63+
if (chainTask == null) {
64+
return Optional.of(CHAIN_UNREACHABLE);
65+
}
6666

6767
if (!hasEnoughStakeToContribute(chainTask)) {
6868
return Optional.of(STAKE_TOO_LOW);
6969
}
7070

71-
if (!isTaskActiveToContribute(chainTask)) {
71+
if (chainTask.getStatus() != ChainTaskStatus.ACTIVE) {
7272
return Optional.of(TASK_NOT_ACTIVE);
7373
}
7474

75-
if (!isBeforeContributionDeadlineToContribute(chainTask)) {
75+
if (chainTask.isContributionDeadlineReached()) {
7676
return Optional.of(CONTRIBUTION_TIMEOUT);
7777
}
7878

79-
if (!isContributionUnsetToContribute(chainTask)) {
79+
if (chainTask.hasContributionFrom(workerWalletAddress)) {
8080
return Optional.of(CONTRIBUTION_ALREADY_SET);
8181
}
8282

83-
if (!isWorkerpoolAuthorizationPresent(chainTaskId)) {
84-
return Optional.of(WORKERPOOL_AUTHORIZATION_NOT_FOUND);
85-
}
86-
8783
return Optional.empty();
8884
}
8985

90-
// TODO: trust could become part of TaskDescription to avoid fetching deal on-chain
91-
public Optional<ReplicateStatusCause> getCannotContributeAndFinalizeStatusCause(String chainTaskId) {
92-
Optional<ChainTask> optionalChainTask = iexecHubService.getChainTask(chainTaskId);
93-
if (optionalChainTask.isEmpty()) {
94-
return Optional.of(CHAIN_UNREACHABLE);
95-
}
96-
ChainTask chainTask = optionalChainTask.get();
97-
86+
public Optional<ReplicateStatusCause> getCannotContributeAndFinalizeStatusCause(final String chainTaskId) {
9887
// check TRUST is 1
99-
Optional<ChainDeal> oChainDeal = iexecHubService.getChainDeal(chainTask.getDealid());
100-
if (oChainDeal.isEmpty() || !BigInteger.ONE.equals(oChainDeal.get().getTrust())) {
88+
final TaskDescription taskDescription = iexecHubService.getTaskDescription(chainTaskId);
89+
if (taskDescription == null || !BigInteger.ONE.equals(taskDescription.getTrust())) {
10190
return Optional.of(TRUST_NOT_1);
10291
}
10392

93+
final ChainTask chainTask = iexecHubService.getChainTask(chainTaskId).orElse(null);
94+
if (chainTask == null) {
95+
return Optional.of(CHAIN_UNREACHABLE);
96+
}
97+
10498
// check TASK_ALREADY_CONTRIBUTED
105-
if (!chainTask.getContributors().isEmpty()) {
99+
if (chainTask.hasContributions()) {
106100
return Optional.of(TASK_ALREADY_CONTRIBUTED);
107101
}
108102

@@ -128,39 +122,17 @@ private boolean hasEnoughStakeToContribute(ChainTask chainTask) {
128122
return optionalChainAccount.get().getDeposit() >= optionalChainDeal.get().getWorkerStake().longValue();
129123
}
130124

131-
private boolean isTaskActiveToContribute(ChainTask chainTask) {
132-
return iexecHubService.isChainTaskActive(chainTask.getChainTaskId());
133-
}
134-
135-
private boolean isBeforeContributionDeadlineToContribute(ChainTask chainTask) {
136-
return new Date().getTime() < chainTask.getContributionDeadline();
137-
}
138-
139-
private boolean isContributionUnsetToContribute(ChainTask chainTask) {
140-
Optional<ChainContribution> optionalContribution = iexecHubService.getChainContribution(chainTask.getChainTaskId());
141-
if (optionalContribution.isEmpty()) return false;
142-
143-
ChainContribution chainContribution = optionalContribution.get();
144-
return chainContribution.getStatus() == ChainContributionStatus.UNSET;
145-
}
146-
147-
public boolean isContributionDeadlineReached(String chainTaskId) {
148-
Optional<ChainTask> oTask = iexecHubService.getChainTask(chainTaskId);
149-
150-
return oTask.isEmpty() || !isBeforeContributionDeadlineToContribute(oTask.get());
151-
}
152-
153125
// returns ChainReceipt of the contribution if successful, null otherwise
154-
public Optional<ChainReceipt> contribute(Contribution contribution) {
126+
public Optional<ChainReceipt> contribute(final Contribution contribution) {
155127

156128
IexecHubContract.TaskContributeEventResponse contributeResponse = iexecHubService.contribute(contribution);
157129

158130
if (contributeResponse == null) {
159-
log.error("ContributeTransactionReceipt received but was null [chainTaskId:{}]", contribution.getChainTaskId());
131+
log.error("ContributeTransactionReceipt received but was null [chainTaskId:{}]", contribution.chainTaskId());
160132
return Optional.empty();
161133
}
162134

163-
ChainReceipt chainReceipt = ChainUtils.buildChainReceipt(contributeResponse.log, contribution.getChainTaskId(),
135+
final ChainReceipt chainReceipt = ChainUtils.buildChainReceipt(contributeResponse.log, contribution.chainTaskId(),
164136
iexecHubService.getLatestBlockNumber());
165137

166138
return Optional.of(chainReceipt);
@@ -179,8 +151,8 @@ public Contribution getContribution(ComputedFile computedFile) {
179151
}
180152

181153
String resultDigest = computedFile.getResultDigest();
182-
String resultHash = ResultUtils.computeResultHash(chainTaskId, resultDigest);
183-
String resultSeal = ResultUtils.computeResultSeal(workerWalletAddress, chainTaskId, resultDigest);
154+
String resultHash = HashUtils.concatenateAndHash(chainTaskId, resultDigest);
155+
String resultSeal = HashUtils.concatenateAndHash(workerWalletAddress, chainTaskId, resultDigest);
184156
String workerpoolSignature = workerpoolAuthorization.getSignature().getValue();
185157
String enclaveChallenge = workerpoolAuthorization.getEnclaveChallenge();
186158
String enclaveSignature = computedFile.getEnclaveSignature();

0 commit comments

Comments
 (0)