Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ build
/out/

/bin/
.vscode/
.vscode/
10 changes: 3 additions & 7 deletions src/itest/java/com/iexec/blockchain/IntegrationTests.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2021-2025 IEXEC BLOCKCHAIN TECH
* Copyright 2021-2026 IEXEC BLOCKCHAIN TECH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -52,7 +52,6 @@
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.web3j.crypto.Hash;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.protocol.exceptions.TransactionException;
import org.web3j.utils.Numeric;

Expand Down Expand Up @@ -160,7 +159,6 @@ private static String getServiceUrl(String serviceHost, int servicePort) {

@Test
void shouldBeFinalized() throws IOException, TransactionException {
TransactionReceipt receipt;
final String dealId = triggerDeal(1);

final String chainTaskId = appClient.requestInitializeTask(dealId, 0);
Expand All @@ -174,18 +172,16 @@ void shouldBeFinalized() throws IOException, TransactionException {
final String enclaveSignature = BytesUtils.bytesToString(new byte[65]);
final WorkerpoolAuthorization workerpoolAuthorization =
mockAuthorization(chainTaskId, enclaveChallenge);
receipt = iexecHubService.contribute(
iexecHubService.contribute(
chainTaskId,
someBytes32Payload,
workerpoolAuthorization.getSignature().getValue(),
enclaveChallenge,
enclaveSignature);
log.info("contribute {}", receipt);
waitStatus(chainTaskId, ChainTaskStatus.REVEALING,
MAX_POLLING_ATTEMPTS);

receipt = iexecHubService.reveal(chainTaskId, someBytes32Payload);
log.info("reveal {}", receipt);
iexecHubService.reveal(chainTaskId, someBytes32Payload);

waitBeforeFinalizing(chainTaskId);
final TaskFinalizeArgs taskFinalizeArgs = new TaskFinalizeArgs("", "");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 IEXEC BLOCKCHAIN TECH
* Copyright 2020-2026 IEXEC BLOCKCHAIN TECH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -66,6 +66,11 @@ public static boolean isByte32(final String hexString) {

public TransactionReceipt initializeTask(final String chainDealId,
final int taskIndex) throws IOException, TransactionException {
final String chainTaskId = ChainUtils.generateChainTaskId(chainDealId, taskIndex);
if (!isTaskInUnsetStatusOnChain(chainTaskId)) {
log.warn("task is already initialized [chainTaskId:{}]", chainTaskId);
return new TransactionReceipt();
}
final String txData = PoCoDataEncoder.encodeInitialize(chainDealId, taskIndex);
final SubmittedTx submittedTx = submit("initialize", txData);
return waitForTxMined(submittedTx);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 IEXEC BLOCKCHAIN TECH
* Copyright 2020-2026 IEXEC BLOCKCHAIN TECH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -21,6 +21,7 @@
import lombok.extern.slf4j.Slf4j;
import org.web3j.protocol.core.methods.response.TransactionReceipt;

import java.time.Duration;
import java.util.Optional;

@Slf4j
Expand All @@ -31,15 +32,16 @@ public abstract class CommandEngine<A extends CommandArgs> {
private final CommandBlockchain<A> blockchainService;
private final CommandStorage updaterService;
private final QueueService queueService;
private final Duration backoffDelay;

protected CommandEngine(
CommandBlockchain<A> blockchainService,
CommandStorage updaterService,
QueueService queueService
) {
protected CommandEngine(final CommandBlockchain<A> blockchainService,
final CommandStorage updaterService,
final QueueService queueService,
final Duration backoffDelay) {
this.blockchainService = blockchainService;
this.updaterService = updaterService;
this.queueService = queueService;
this.backoffDelay = backoffDelay;
}

/**
Expand Down Expand Up @@ -85,6 +87,15 @@ public void triggerBlockchainCommand(final A args) {
log.info("Processing command [{}]", messageDetails);
TransactionReceipt receipt = null;
while (attempt < MAX_ATTEMPTS && receipt == null) {
if (attempt != 0) {
try {
log.warn("Backoff delay before retrying tx");
Thread.sleep(backoffDelay.toMillis());
} catch (InterruptedException e) {
log.warn("Thread has been interrupted", e);
Thread.currentThread().interrupt();
}
}
attempt++;
try {
receipt = blockchainService.sendBlockchainCommand(args);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 IEXEC BLOCKCHAIN TECH
* Copyright 2020-2026 IEXEC BLOCKCHAIN TECH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -20,19 +20,22 @@
import com.iexec.blockchain.command.generic.CommandEngine;
import com.iexec.blockchain.command.generic.CommandStorage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.time.Duration;

import static com.iexec.blockchain.chain.IexecHubService.isByte32;

@Slf4j
@Service
public class TaskFinalizeService extends CommandEngine<TaskFinalizeArgs> {

public TaskFinalizeService(
final TaskFinalizeBlockchainService blockchainService,
final CommandStorage storageService,
final QueueService queueService) {
super(blockchainService, storageService, queueService);
public TaskFinalizeService(final TaskFinalizeBlockchainService blockchainService,
final CommandStorage storageService,
final QueueService queueService,
@Value("${chain.tx-backoff-delay}") final Duration backoffDelay) {
super(blockchainService, storageService, queueService, backoffDelay);
}

public String start(final String chainTaskId, final String resultLink, final String callbackData) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 IEXEC BLOCKCHAIN TECH
* Copyright 2020-2026 IEXEC BLOCKCHAIN TECH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -20,18 +20,21 @@
import com.iexec.blockchain.command.generic.CommandEngine;
import com.iexec.blockchain.command.generic.CommandStorage;
import com.iexec.commons.poco.chain.ChainUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.time.Duration;

import static com.iexec.blockchain.chain.IexecHubService.isByte32;

@Service
public class TaskInitializeService extends CommandEngine<TaskInitializeArgs> {

public TaskInitializeService(
final TaskInitializeBlockchainService blockchainService,
final CommandStorage updaterService,
final QueueService queueService) {
super(blockchainService, updaterService, queueService);
public TaskInitializeService(final TaskInitializeBlockchainService blockchainService,
final CommandStorage updaterService,
final QueueService queueService,
@Value("${chain.tx-backoff-delay}") final Duration backoffDelay) {
super(blockchainService, updaterService, queueService, backoffDelay);
}

public String start(final String chainDealId, final int taskIndex) {
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ chain:
gas-price-multiplier: ${IEXEC_GAS_PRICE_MULTIPLIER:1.0} # txs will be sent with networkGasPrice*gasPriceMultiplier, 4.0 means super fast
gas-price-cap: ${IEXEC_GAS_PRICE_CAP:22000000000} #in Wei, will be used for txs if networkGasPrice*gasPriceMultiplier > gasPriceCap
max-allowed-tx-per-block: ${IEXEC_BLOCKCHAIN_ADAPTER_API_MAX_ALLOWED_TX_PER_BLOCK:1} # 1 or 2
tx-backoff-delay: PT0.5S
wallet:
path: ${IEXEC_BLOCKCHAIN_ADAPTER_API_WALLET_PATH:src/main/resources/wallet.json}
password: ${IEXEC_BLOCKCHAIN_ADAPTER_API_WALLET_PASSWORD:whatever}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2023-2025 IEXEC BLOCKCHAIN TECH
* Copyright 2023-2026 IEXEC BLOCKCHAIN TECH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -103,6 +103,14 @@ void shouldNotInitializeTask() throws IOException {
.isInstanceOf(IOException.class);
}

@Test
void shouldDetectAlreadyInitializedTask() throws IOException, TransactionException {
final String initializedChainTaskId = ChainUtils.generateChainTaskId(chainDealId, 0);
doReturn(false).when(iexecHubService).isTaskInUnsetStatusOnChain(initializedChainTaskId);
assertThat(iexecHubService.initializeTask(chainDealId, 0))
.isEqualTo(new TransactionReceipt());
}

// endregion

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2024-2025 IEXEC BLOCKCHAIN TECH
* Copyright 2024-2026 IEXEC BLOCKCHAIN TECH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -20,16 +20,17 @@
import com.iexec.blockchain.chain.QueueService;
import com.iexec.blockchain.command.generic.CommandName;
import com.iexec.blockchain.command.generic.CommandStorage;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.web3j.protocol.core.methods.response.TransactionReceipt;

import java.time.Duration;
import java.util.Optional;
import java.util.stream.Stream;

Expand All @@ -46,17 +47,22 @@ class TaskFinalizeServiceTests {
"0xe90fc4654b5ea32ad8689091e7610cad7ee5c8b9b1a6e39401b57d90343bfcaa";
private static final String RESULT_LINK = "/ipfs/QmeQHGKFAkEkA5tm3kuXqBM9zz9JorkvCsAJ2bzAAh6NX4";

@InjectMocks
private TaskFinalizeService taskFinalizeService;
@Mock
private TaskFinalizeBlockchainService blockchainService;
@Mock
private CommandStorage updaterService;
@Mock
private QueueService queueService;

private TaskFinalizeService taskFinalizeService;
private final TaskFinalizeArgs args = new TaskFinalizeArgs(CHAIN_TASK_ID, RESULT_LINK, EMPTY_ADDRESS);

@BeforeEach
void init() {
taskFinalizeService = new TaskFinalizeService(
blockchainService, updaterService, queueService, Duration.ofMillis(100L));
}

// region start
@Test
void shouldFinalizeTask() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2021-2025 IEXEC BLOCKCHAIN TECH
* Copyright 2021-2026 IEXEC BLOCKCHAIN TECH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -21,16 +21,17 @@
import com.iexec.blockchain.command.generic.CommandName;
import com.iexec.blockchain.command.generic.CommandStorage;
import com.iexec.commons.poco.chain.ChainUtils;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.web3j.protocol.core.methods.response.TransactionReceipt;

import java.time.Duration;
import java.util.Optional;
import java.util.stream.Stream;

Expand All @@ -46,17 +47,22 @@ class TaskInitializeServiceTests {
public static final String CHAIN_TASK_ID =
ChainUtils.generateChainTaskId(CHAIN_DEAL_ID, TASK_INDEX);

@InjectMocks
private TaskInitializeService taskInitializeService;
@Mock
private TaskInitializeBlockchainService blockchainCheckerService;
@Mock
private CommandStorage updaterService;
@Mock
private QueueService queueService;

private TaskInitializeService taskInitializeService;
private final TaskInitializeArgs args = new TaskInitializeArgs(CHAIN_TASK_ID, CHAIN_DEAL_ID, TASK_INDEX);

@BeforeEach
void init() {
taskInitializeService = new TaskInitializeService(
blockchainCheckerService, updaterService, queueService, Duration.ofMillis(100L));
}

// region start
@Test
void shouldInitializeTask() {
Expand Down