Skip to content

Commit 49f1988

Browse files
Merge pull request #19 from iExecBlockchainComputing/release/0.1.1
Release/0.1.1
2 parents 0d92d40 + c15d8d6 commit 49f1988

File tree

10 files changed

+157
-107
lines changed

10 files changed

+157
-107
lines changed

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
version=0.1.0
1+
version=0.1.1
22
iexecCommonVersion=5.6.0

src/itest/java/com/iexec/blockchain/IntegrationTests.java

Lines changed: 108 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.apache.commons.lang3.RandomStringUtils;
2222
import org.apache.commons.lang3.StringUtils;
2323
import org.junit.jupiter.api.Assertions;
24+
import org.junit.jupiter.api.BeforeEach;
2425
import org.junit.jupiter.api.Test;
2526
import org.springframework.beans.factory.annotation.Autowired;
2627
import org.springframework.boot.test.context.SpringBootTest;
@@ -31,7 +32,11 @@
3132
import org.web3j.crypto.Sign;
3233

3334
import java.math.BigInteger;
35+
import java.util.ArrayList;
36+
import java.util.List;
3437
import java.util.Optional;
38+
import java.util.concurrent.CompletableFuture;
39+
import java.util.stream.IntStream;
3540

3641
import static com.iexec.common.chain.ChainTaskStatus.ACTIVE;
3742
import static com.iexec.common.chain.ChainTaskStatus.UNSET;
@@ -42,6 +47,7 @@ class IntegrationTests {
4247

4348
public static final String USER = "admin";
4449
public static final String PASSWORD = "whatever";
50+
public static final int BLOCK_TIME_MS = 1000;
4551

4652
@LocalServerPort
4753
private int randomServerPort;
@@ -63,9 +69,83 @@ class IntegrationTests {
6369

6470
@Autowired
6571
private SignerService signerService;
66-
72+
private BlockchainAdapterApiClient appClient;
73+
74+
@BeforeEach
75+
void setUp() {
76+
appClient = FeignUtils.getFeignBuilder(USER, PASSWORD)
77+
.target(BlockchainAdapterApiClient.class, getBaseUrl());
78+
}
79+
6780
@Test
6881
public void shouldBeFinalized() throws Exception {
82+
String dealId = triggerDeal(1);
83+
84+
String chainTaskId = appClient.requestInitializeTask(dealId, 0);
85+
Assertions.assertTrue(StringUtils.isNotEmpty(chainTaskId));
86+
System.out.println("Requested task initialize: " + chainTaskId);
87+
//should wait since returned taskID is computed, initialize is not mined yet
88+
waitStatus(chainTaskId, ACTIVE, 1000, 10);
89+
90+
String someBytes32Payload = TeeUtils.TEE_TAG;
91+
String enclaveChallenge = BytesUtils.EMPTY_ADDRESS;
92+
String enclaveSignature = BytesUtils.bytesToString(new byte[65]);
93+
WorkerpoolAuthorization workerpoolAuthorization =
94+
mockAuthorization(chainTaskId, enclaveChallenge);
95+
TaskContributeArgs contributeArgs = new TaskContributeArgs(
96+
someBytes32Payload,
97+
workerpoolAuthorization.getSignature().getValue(),
98+
enclaveChallenge,
99+
enclaveSignature);
100+
String contributeResponseBody = appClient.requestContributeTask(chainTaskId, contributeArgs);
101+
Assertions.assertTrue(StringUtils.isNotEmpty(contributeResponseBody));
102+
System.out.println("Requested task contribute: " + contributeResponseBody);
103+
waitStatus(chainTaskId, ChainTaskStatus.REVEALING, 1000, 10);
104+
105+
TaskRevealArgs taskRevealArgs = new TaskRevealArgs(someBytes32Payload);
106+
String revealResponseBody = appClient.requestRevealTask(chainTaskId, taskRevealArgs);
107+
Assertions.assertTrue(StringUtils.isNotEmpty(revealResponseBody));
108+
System.out.println("Requested task reveal: " + revealResponseBody);
109+
110+
waitBeforeFinalizing(chainTaskId);
111+
TaskFinalizeArgs taskFinalizeArgs = new TaskFinalizeArgs();
112+
String finalizeResponseBody = appClient.requestFinalizeTask(chainTaskId, taskFinalizeArgs);
113+
Assertions.assertTrue(StringUtils.isNotEmpty(finalizeResponseBody));
114+
System.out.println("Requested task finalize: " + finalizeResponseBody);
115+
waitStatus(chainTaskId, ChainTaskStatus.COMPLETED, 1000, 10);
116+
}
117+
118+
@Test
119+
public void shouldBurstTransactionsWithAverageOfOneTxPerBlock(){
120+
int taskVolume = 10;//small volume ensures reasonable execution time on CI/CD
121+
String dealId = triggerDeal(taskVolume);
122+
List<CompletableFuture<Void>> txCompletionWatchers = new ArrayList<>();
123+
124+
IntStream.range(0, taskVolume)
125+
.forEach(taskIndex -> {
126+
//burst transactions (fast sequence) (send "initialize" tx examples for simplicity)
127+
String chainTaskId = appClient.requestInitializeTask(dealId, taskIndex);
128+
Assertions.assertTrue(StringUtils.isNotEmpty(chainTaskId));
129+
System.out.printf("Requested task initialize " +
130+
"[index:%s, chainTaskId:%s]\n", taskIndex, chainTaskId);
131+
//wait tx completion outside
132+
txCompletionWatchers.add(CompletableFuture.runAsync(() -> {
133+
try {
134+
//maximum waiting time equals nb of submitted txs
135+
//1 tx/block means N txs / N blocks
136+
waitStatus(chainTaskId, ACTIVE, BLOCK_TIME_MS, taskVolume);
137+
//no need to wait for propagation update in db
138+
Assertions.assertTrue(true);
139+
} catch (Exception e) {
140+
e.printStackTrace();
141+
Assertions.fail();
142+
}
143+
}));
144+
});
145+
txCompletionWatchers.forEach(CompletableFuture::join);
146+
}
147+
148+
private String triggerDeal(int taskVolume) {
69149
String appAddress = iexecHubService.createApp(buildRandomName("app"),
70150
"docker.io/repo/name:1.0.0",
71151
"DOCKER",
@@ -82,9 +162,9 @@ public void shouldBeFinalized() throws Exception {
82162
30, 1);
83163
System.out.println("Created datasetAddress: " + datasetAddress);
84164

85-
AppOrder signedAppOrder = signerService.signAppOrder(buildAppOrder(appAddress));
86-
WorkerpoolOrder signedWorkerpoolOrder = signerService.signWorkerpoolOrder(buildWorkerpoolOrder(workerpool));
87-
DatasetOrder signedDatasetOrder = signerService.signDatasetOrder(buildDatasetOrder(datasetAddress));
165+
AppOrder signedAppOrder = signerService.signAppOrder(buildAppOrder(appAddress, taskVolume));
166+
WorkerpoolOrder signedWorkerpoolOrder = signerService.signWorkerpoolOrder(buildWorkerpoolOrder(workerpool, taskVolume));
167+
DatasetOrder signedDatasetOrder = signerService.signDatasetOrder(buildDatasetOrder(datasetAddress, taskVolume));
88168
RequestOrder signedRequestOrder = signerService.signRequestOrder(buildRequestOrder(signedAppOrder,
89169
signedWorkerpoolOrder,
90170
signedDatasetOrder,
@@ -108,53 +188,19 @@ public void shouldBeFinalized() throws Exception {
108188
//existence for double checking
109189
Optional<ChainDeal> chainDeal = iexecHubService.getChainDeal(dealId);
110190
Assertions.assertTrue(chainDeal.isPresent());
111-
112-
BlockchainAdapterApiClient appClient = FeignUtils.getFeignBuilder(USER, PASSWORD)
113-
.target(BlockchainAdapterApiClient.class, getBaseUrl());
114-
115-
String chainTaskId = appClient.requestInitializeTask(dealId, 0);
116-
Assertions.assertTrue(StringUtils.isNotEmpty(chainTaskId));
117-
System.out.println("Requested task initialize: " + chainTaskId);
118-
//should wait since returned taskID is computed, initialize is not mined yet
119-
waitStatus(chainTaskId, ACTIVE);
120-
121-
String someBytes32Payload = TeeUtils.TEE_TAG;
122-
String enclaveChallenge = BytesUtils.EMPTY_ADDRESS;
123-
String enclaveSignature = BytesUtils.bytesToString(new byte[65]);
124-
WorkerpoolAuthorization workerpoolAuthorization =
125-
mockAuthorization(chainTaskId, enclaveChallenge);
126-
TaskContributeArgs contributeArgs = new TaskContributeArgs(
127-
someBytes32Payload,
128-
workerpoolAuthorization.getSignature().getValue(),
129-
enclaveChallenge,
130-
enclaveSignature);
131-
String contributeResponseBody = appClient.requestContributeTask(chainTaskId, contributeArgs);
132-
Assertions.assertTrue(StringUtils.isNotEmpty(contributeResponseBody));
133-
System.out.println("Requested task contribute: " + contributeResponseBody);
134-
waitStatus(chainTaskId, ChainTaskStatus.REVEALING);
135-
136-
TaskRevealArgs taskRevealArgs = new TaskRevealArgs(someBytes32Payload);
137-
String revealResponseBody = appClient.requestRevealTask(chainTaskId, taskRevealArgs);
138-
Assertions.assertTrue(StringUtils.isNotEmpty(revealResponseBody));
139-
System.out.println("Requested task reveal: " + revealResponseBody);
140-
141-
waitBeforeFinalizing(chainTaskId);
142-
TaskFinalizeArgs taskFinalizeArgs = new TaskFinalizeArgs();
143-
String finalizeResponseBody = appClient.requestFinalizeTask(chainTaskId, taskFinalizeArgs);
144-
Assertions.assertTrue(StringUtils.isNotEmpty(finalizeResponseBody));
145-
System.out.println("Requested task finalize: " + finalizeResponseBody);
146-
waitStatus(chainTaskId, ChainTaskStatus.COMPLETED);
191+
return dealId;
147192
}
148193

194+
149195
private String buildRandomName(String baseName) {
150196
return baseName + "-" + RandomStringUtils.randomAlphabetic(10);
151197
}
152198

153-
private AppOrder buildAppOrder(String appAddress) {
199+
private AppOrder buildAppOrder(String appAddress, int volume) {
154200
return AppOrder.builder()
155201
.app(appAddress)
156202
.price(BigInteger.ZERO)
157-
.volume(BigInteger.ONE)
203+
.volume(BigInteger.valueOf(volume))
158204
.tag(BytesUtils.EMPTY_HEXASTRING_64)
159205
.datasetrestrict(BytesUtils.EMPTY_ADDRESS)
160206
.workerpoolrestrict(BytesUtils.EMPTY_ADDRESS)
@@ -163,11 +209,11 @@ private AppOrder buildAppOrder(String appAddress) {
163209
.build();
164210
}
165211

166-
private WorkerpoolOrder buildWorkerpoolOrder(String workerpoolAddress) {
212+
private WorkerpoolOrder buildWorkerpoolOrder(String workerpoolAddress, int volume) {
167213
return WorkerpoolOrder.builder()
168214
.workerpool(workerpoolAddress)
169215
.price(BigInteger.ZERO)
170-
.volume(BigInteger.ONE)
216+
.volume(BigInteger.valueOf(volume))
171217
.tag(BytesUtils.EMPTY_HEXASTRING_64)
172218
.trust(BigInteger.ZERO)
173219
.category(BigInteger.ZERO)
@@ -178,11 +224,11 @@ private WorkerpoolOrder buildWorkerpoolOrder(String workerpoolAddress) {
178224
.build();
179225
}
180226

181-
private DatasetOrder buildDatasetOrder(String datasetAddress) {
227+
private DatasetOrder buildDatasetOrder(String datasetAddress, int volume) {
182228
return DatasetOrder.builder()
183229
.dataset(datasetAddress)
184230
.price(BigInteger.ZERO)
185-
.volume(BigInteger.ONE)
231+
.volume(BigInteger.valueOf(volume))
186232
.tag(BytesUtils.EMPTY_HEXASTRING_64)
187233
.apprestrict(BytesUtils.EMPTY_ADDRESS)
188234
.workerpoolrestrict(BytesUtils.EMPTY_ADDRESS)
@@ -197,14 +243,21 @@ private RequestOrder buildRequestOrder(
197243
DatasetOrder datasetOrder,
198244
String requesterAddress,
199245
DealParams dealParams) {
246+
boolean isCompatibleVolume =
247+
appOrder.getVolume().equals(workerpoolOrder.getVolume())
248+
&& appOrder.getVolume().equals(datasetOrder.getVolume());
249+
if (!isCompatibleVolume){
250+
System.out.println("Volumes are not compatible");
251+
return null;
252+
}
200253
return RequestOrder.builder()
201254
.app(appOrder.getApp())
202255
.appmaxprice(appOrder.getAppprice())
203256
.workerpool(workerpoolOrder.getWorkerpool())
204257
.workerpoolmaxprice(workerpoolOrder.getWorkerpoolprice())
205258
.dataset(datasetOrder.getDataset())
206259
.datasetmaxprice(datasetOrder.getDatasetprice())
207-
.volume(BigInteger.ONE)
260+
.volume(appOrder.getVolume())
208261
.category(BigInteger.ZERO)
209262
.trust(BigInteger.ZERO)
210263
.tag(BytesUtils.EMPTY_HEXASTRING_64)
@@ -217,15 +270,18 @@ private RequestOrder buildRequestOrder(
217270
.build();
218271
}
219272

220-
private void waitStatus(String chainTaskId, ChainTaskStatus statusToWait) throws Exception {
273+
/**
274+
*
275+
* @param pollingTimeMs recommended value is block time
276+
*/
277+
private void waitStatus(String chainTaskId, ChainTaskStatus statusToWait, int pollingTimeMs, int maxAttempts) throws Exception {
221278
ChainTaskStatus status = iexecHubService.getChainTask(chainTaskId)
222279
.map(ChainTask::getStatus)
223280
.orElse(UNSET);
224-
int maxAttempts = 20;
225281
int attempts = 0;
226282
while (!status.equals(statusToWait)) {
227-
System.out.println("Status is: " + status);
228-
Thread.sleep(100);
283+
System.out.printf("Status [status:%s, chainTaskId:%s]\n", status, chainTaskId);
284+
Thread.sleep(pollingTimeMs);
229285
status = iexecHubService.getChainTask(chainTaskId)
230286
.map(ChainTask::getStatus)
231287
.orElse(UNSET);
@@ -234,7 +290,7 @@ private void waitStatus(String chainTaskId, ChainTaskStatus statusToWait) throws
234290
throw new Exception("Too long to wait for task: " + chainTaskId);
235291
}
236292
}
237-
System.out.println("Status reached: " + status);
293+
System.out.printf("Status reached [status:%s, chainTaskId:%s]\n", status, chainTaskId);
238294
}
239295

240296
private void waitBeforeFinalizing(String chainTaskId) throws Exception {

src/main/java/com/iexec/blockchain/command/generic/CommandBlockchain.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@
1919

2020
import org.web3j.protocol.core.methods.response.TransactionReceipt;
2121

22-
import java.util.concurrent.CompletionStage;
23-
2422
public interface CommandBlockchain<A extends CommandArgs> {
2523

2624

@@ -38,10 +36,10 @@ public interface CommandBlockchain<A extends CommandArgs> {
3836
boolean canSendBlockchainCommand(A args);
3937

4038
/**
41-
* Asynchronously perform a blockchain command.
39+
* Synchronously perform a blockchain command.
4240
*
4341
* @param args input arguments for the blockchain command
44-
* @return a future transaction receipt
42+
* @return transaction receipt
4543
*/
46-
CompletionStage<TransactionReceipt> sendBlockchainCommand(A args);
44+
TransactionReceipt sendBlockchainCommand(A args) throws Exception;
4745
}

src/main/java/com/iexec/blockchain/command/generic/CommandEngine.java

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.iexec.blockchain.tool.QueueService;
2121
import com.iexec.blockchain.tool.Status;
2222
import lombok.extern.slf4j.Slf4j;
23+
import org.web3j.protocol.core.methods.response.TransactionReceipt;
2324

2425
import java.util.Optional;
2526

@@ -89,23 +90,24 @@ public void triggerBlockchainCommand(A args) {
8990
}
9091
log.info("Processing command [chainObjectId:{}, commandArgs:{}]",
9192
chainObjectId, args);
92-
blockchainService.sendBlockchainCommand(args)
93-
.thenAccept(receipt -> {
94-
if (receipt == null) {
95-
log.error("Triggering blockchain command failed " +
96-
"(received null receipt after blockchain send) " +
97-
"[chainObjectId:{}, commandArgs:{}]",
98-
chainObjectId, args);
99-
return;
100-
}
101-
updaterService.updateToFinal(chainObjectId, receipt);
102-
}).exceptionally(throwable -> {
103-
log.error("Something wrong happened while triggering " +
104-
"blockchain command [chainObjectId:{}, commandArgs:{}]",
105-
chainObjectId, args, throwable);
106-
//TODO Update to proper status: PROCESSING_FAILED or FAILURE
107-
return null;
108-
});
93+
TransactionReceipt receipt;
94+
try {
95+
receipt = blockchainService.sendBlockchainCommand(args);
96+
} catch (Exception e) {
97+
log.error("Something wrong happened while triggering blockchain " +
98+
"command [chainObjectId:{}, commandArgs:{}]",
99+
chainObjectId, args, e);
100+
//TODO Update to proper status: PROCESSING_FAILED or FAILURE
101+
return;
102+
}
103+
if (receipt == null) {
104+
log.error("Triggering blockchain command failed " +
105+
"(received null receipt after blockchain send) " +
106+
"[chainObjectId:{}, commandArgs:{}]",
107+
chainObjectId, args);
108+
return;
109+
}
110+
updaterService.updateToFinal(chainObjectId, receipt);
109111
}
110112

111113
/**

src/main/java/com/iexec/blockchain/command/task/contribute/TaskContributeBlockchainService.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import org.web3j.protocol.core.methods.response.TransactionReceipt;
2727

2828
import java.util.Optional;
29-
import java.util.concurrent.CompletionStage;
3029

3130
@Slf4j
3231
@Service
@@ -78,7 +77,7 @@ private void logError(String chainTaskId, TaskContributeArgs args, String error)
7877
}
7978

8079
@Override
81-
public CompletionStage<TransactionReceipt> sendBlockchainCommand(TaskContributeArgs args) {
80+
public TransactionReceipt sendBlockchainCommand(TaskContributeArgs args) throws Exception {
8281
return iexecHubService.contribute(args.getChainTaskId(),
8382
args.getResultDigest(),
8483
args.getWorkerpoolSignature(),

src/main/java/com/iexec/blockchain/command/task/finalize/TaskFinalizeBlockchainService.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import org.web3j.protocol.core.methods.response.TransactionReceipt;
2727

2828
import java.util.Optional;
29-
import java.util.concurrent.CompletionStage;
3029

3130
import static com.iexec.common.utils.DateTimeUtils.now;
3231

@@ -75,7 +74,7 @@ private void logError(String chainTaskId, TaskFinalizeArgs args, String error) {
7574
}
7675

7776
@Override
78-
public CompletionStage<TransactionReceipt> sendBlockchainCommand(TaskFinalizeArgs args) {
77+
public TransactionReceipt sendBlockchainCommand(TaskFinalizeArgs args) throws Exception {
7978
return iexecHubService.finalize(args.getChainTaskId(),
8079
args.getResultLink(),
8180
args.getCallbackData());

src/main/java/com/iexec/blockchain/command/task/initialize/TaskInitializeBlockchainService.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@
2323
import org.springframework.stereotype.Service;
2424
import org.web3j.protocol.core.methods.response.TransactionReceipt;
2525

26-
import java.util.concurrent.CompletionStage;
27-
2826
@Slf4j
2927
@Service
3028
public class TaskInitializeBlockchainService implements CommandBlockchain<TaskInitializeArgs> {
@@ -59,7 +57,7 @@ private void logError(String chainTaskId, TaskInitializeArgs args, String error)
5957
}
6058

6159
@Override
62-
public CompletionStage<TransactionReceipt> sendBlockchainCommand(TaskInitializeArgs args) {
60+
public TransactionReceipt sendBlockchainCommand(TaskInitializeArgs args) throws Exception {
6361
return iexecHubService.initializeTask(args.getChainDealId(), args.getTaskIndex());
6462
}
6563

0 commit comments

Comments
 (0)