Skip to content

Commit 8d0de6f

Browse files
authored
feat: use new viewApp and viewDataset PoCo methods (#160)
1 parent 532cacc commit 8d0de6f

File tree

9 files changed

+211
-111
lines changed

9 files changed

+211
-111
lines changed

src/main/java/com/iexec/commons/poco/chain/ChainApp.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,15 @@
1616

1717
package com.iexec.commons.poco.chain;
1818

19+
import com.iexec.commons.poco.encoding.PoCoDataDecoder;
1920
import com.iexec.commons.poco.tee.TeeEnclaveConfiguration;
2021
import lombok.Builder;
2122
import lombok.Value;
23+
import lombok.extern.slf4j.Slf4j;
2224

25+
import static com.iexec.commons.poco.chain.Web3jAbstractService.toBigInt;
26+
27+
@Slf4j
2328
@Value
2429
@Builder
2530
public class ChainApp {
@@ -28,4 +33,21 @@ public class ChainApp {
2833
String multiaddr;
2934
String checksum;
3035
TeeEnclaveConfiguration enclaveConfiguration;
36+
37+
public static ChainApp fromRawData(final String address, final String rawData) {
38+
log.debug("ChainApp.fromRawData [address:{}]", address);
39+
final String[] parts = PoCoDataDecoder.toParts(rawData);
40+
final int offset = toBigInt(parts[0]).intValue() / 32;
41+
final int typeOffset = toBigInt(parts[offset + 2]).intValue() / 32;
42+
final int multiaddrOffest = toBigInt(parts[offset + 3]).intValue() / 32;
43+
final int enclaveOffset = toBigInt(parts[offset + 5]).intValue() / 32;
44+
final String enclaveContrib = PoCoDataDecoder.decodeToAsciiString(parts, offset + enclaveOffset);
45+
return ChainApp.builder()
46+
.chainAppId(address)
47+
.type(PoCoDataDecoder.decodeToAsciiString(parts, offset + typeOffset))
48+
.multiaddr(PoCoDataDecoder.decodeToAsciiString(parts, offset + multiaddrOffest))
49+
.checksum("0x" + parts[offset + 4])
50+
.enclaveConfiguration(TeeEnclaveConfiguration.fromJsonString(enclaveContrib))
51+
.build();
52+
}
3153
}

src/main/java/com/iexec/commons/poco/chain/ChainDataset.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,32 @@
1616

1717
package com.iexec.commons.poco.chain;
1818

19+
import com.iexec.commons.poco.encoding.PoCoDataDecoder;
20+
import com.iexec.commons.poco.utils.MultiAddressHelper;
1921
import lombok.Builder;
2022
import lombok.Value;
23+
import lombok.extern.slf4j.Slf4j;
2124

25+
import static com.iexec.commons.poco.chain.Web3jAbstractService.toBigInt;
26+
27+
@Slf4j
2228
@Value
2329
@Builder
2430
public class ChainDataset {
2531
String chainDatasetId;
2632
String multiaddr;
2733
String checksum;
34+
35+
public static ChainDataset fromRawData(final String address, final String rawData) {
36+
log.debug("ChainDataset.fromRawData [address:{}]", address);
37+
final String[] parts = PoCoDataDecoder.toParts(rawData);
38+
final int offset = toBigInt(parts[0]).intValue() / 32;
39+
final int multiaddrOffset = toBigInt(parts[offset + 2]).intValue() / 32;
40+
final String multiaddr = PoCoDataDecoder.decodeToHexString(parts, offset + multiaddrOffset);
41+
return ChainDataset.builder()
42+
.chainDatasetId(address)
43+
.multiaddr(MultiAddressHelper.convertToURI(multiaddr))
44+
.checksum("0x" + parts[offset + 3])
45+
.build();
46+
}
2847
}

src/main/java/com/iexec/commons/poco/chain/IexecHubAbstractService.java

Lines changed: 8 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,9 @@
2222
import com.iexec.commons.poco.order.DatasetOrder;
2323
import com.iexec.commons.poco.task.TaskDescription;
2424
import com.iexec.commons.poco.utils.BytesUtils;
25-
import com.iexec.commons.poco.utils.MultiAddressHelper;
2625
import com.iexec.commons.poco.utils.Retryer;
2726
import lombok.Getter;
2827
import lombok.extern.slf4j.Slf4j;
29-
import org.apache.commons.lang3.StringUtils;
30-
import org.web3j.abi.FunctionReturnDecoder;
3128
import org.web3j.crypto.Credentials;
3229
import org.web3j.ens.EnsResolutionException;
3330
import org.web3j.tuples.generated.Tuple3;
@@ -45,7 +42,6 @@
4542
import static com.iexec.commons.poco.chain.Web3jAbstractService.toBigInt;
4643
import static com.iexec.commons.poco.chain.Web3jAbstractService.toEthereumAddress;
4744
import static com.iexec.commons.poco.encoding.AccessorsEncoder.*;
48-
import static com.iexec.commons.poco.tee.TeeEnclaveConfiguration.buildEnclaveConfigurationFromJsonString;
4945
import static com.iexec.commons.poco.utils.BytesUtils.isNonZeroedBytes32;
5046

5147
/*
@@ -363,49 +359,25 @@ public Optional<ChainApp> getChainApp(final String appAddress) {
363359
if (appAddress == null || appAddress.equals(BytesUtils.EMPTY_ADDRESS)) {
364360
return Optional.empty();
365361
}
366-
final ChainApp.ChainAppBuilder chainAppBuilder = ChainApp.builder();
367362
try {
368-
chainAppBuilder
369-
.chainAppId(appAddress)
370-
.type(sendCallAndDecodeDynamicBytes(appAddress, M_APPTYPE_SELECTOR))
371-
.multiaddr(sendCallAndDecodeDynamicBytes(appAddress, M_APPMULTIADDR_SELECTOR))
372-
.checksum(sendCallAndGetRawResult(appAddress, M_APPCHECKSUM_SELECTOR));
363+
final String txData = VIEW_APP_SELECTOR +
364+
Numeric.toHexStringNoPrefixZeroPadded(Numeric.toBigInt(appAddress), 64);
365+
final String rawData = web3jAbstractService.sendCall(credentials.getAddress(), iexecHubAddress, txData);
366+
return Optional.of(ChainApp.fromRawData(appAddress, rawData));
373367
} catch (Exception e) {
374368
log.error("Failed to get chain app [chainAppId:{}]",
375369
appAddress, e);
376370
return Optional.empty();
377371
}
378-
String mrEnclave;
379-
try {
380-
mrEnclave = sendCallAndDecodeDynamicBytes(appAddress, M_APPMRENCLAVE_SELECTOR);
381-
} catch (Exception e) {
382-
log.error("Failed to get chain app mrenclave [chainAppId:{}]",
383-
appAddress, e);
384-
return Optional.empty();
385-
}
386-
if (StringUtils.isEmpty(mrEnclave)) {
387-
// Standard application
388-
return Optional.of(chainAppBuilder.build());
389-
}
390-
try {
391-
chainAppBuilder.enclaveConfiguration(
392-
buildEnclaveConfigurationFromJsonString(mrEnclave));
393-
} catch (Exception e) {
394-
log.error("Failed to get tee chain app enclave configuration [chainAppId:{}, mrEnclave:{}]",
395-
appAddress, mrEnclave, e);
396-
return Optional.empty();
397-
}
398-
return Optional.of(chainAppBuilder.build());
399372
}
400373

401374
public Optional<ChainDataset> getChainDataset(final String datasetAddress) {
402375
if (datasetAddress != null && !datasetAddress.equals(BytesUtils.EMPTY_ADDRESS)) {
403376
try {
404-
return Optional.of(ChainDataset.builder()
405-
.chainDatasetId(datasetAddress)
406-
.multiaddr(sendCallAndDecodeDynamicBytes(datasetAddress, M_DATASETMULTIADDR_SELECTOR))
407-
.checksum(sendCallAndGetRawResult(datasetAddress, M_DATASETCHECKSUM_SELECTOR))
408-
.build());
377+
final String txData = VIEW_DATASET_SELECTOR +
378+
Numeric.toHexStringNoPrefixZeroPadded(Numeric.toBigInt(datasetAddress), 64);
379+
final String rawData = web3jAbstractService.sendCall(credentials.getAddress(), iexecHubAddress, txData);
380+
return Optional.of(ChainDataset.fromRawData(datasetAddress, rawData));
409381
} catch (Exception e) {
410382
log.error("Failed to get ChainDataset [chainDatasetId:{}]",
411383
datasetAddress, e);
@@ -414,31 +386,6 @@ public Optional<ChainDataset> getChainDataset(final String datasetAddress) {
414386
return Optional.empty();
415387
}
416388

417-
/**
418-
* Send a call to a Smart contract to retrieve a single value corresponding to a dynamic type and decode it.
419-
*
420-
* @param address Smart Contract address (can be an App or a Dataset in PoCo)
421-
* @param selector Function selector
422-
* @return The decoded String result returned by the call
423-
* @throws IOException on communication error
424-
*/
425-
private String sendCallAndDecodeDynamicBytes(final String address, final String selector) throws IOException {
426-
return MultiAddressHelper.convertToURI(
427-
FunctionReturnDecoder.decodeDynamicBytes(sendCallAndGetRawResult(address, selector)));
428-
}
429-
430-
/**
431-
* Send a call to a Smart contract to retrieve a single value.
432-
*
433-
* @param address Smart Contract address (can be an App or a Dataset in PoCo)
434-
* @param selector Function selector
435-
* @return The hexadecimal representation of retrieved bytes, may need further decoding
436-
* @throws IOException on communication error
437-
*/
438-
private String sendCallAndGetRawResult(final String address, final String selector) throws IOException {
439-
return web3jAbstractService.sendCall(credentials.getAddress(), address, selector);
440-
}
441-
442389
public Optional<Integer> getWorkerScore(String address) {
443390
if (address != null && !address.isEmpty()) {
444391
try {

src/main/java/com/iexec/commons/poco/encoding/AccessorsEncoder.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,41 @@ public class AccessorsEncoder {
5353
public static final String VIEW_CONSUMED_SELECTOR = "0x4b2bec8c";
5454

5555
// app
56+
/**
57+
* @deprecated no more used, replaced with viewApp new call
58+
*/
59+
@Deprecated(forRemoval = true)
5660
public static final String M_APPCHECKSUM_SELECTOR = "0x84aaf12e";
61+
/**
62+
* @deprecated no more used, replaced with viewApp new call
63+
*/
64+
@Deprecated(forRemoval = true)
5765
public static final String M_APPMRENCLAVE_SELECTOR = "0xe30d26a8";
66+
/**
67+
* @deprecated no more used, replaced with viewApp new call
68+
*/
69+
@Deprecated(forRemoval = true)
5870
public static final String M_APPMULTIADDR_SELECTOR = "0x39e75d45";
71+
/**
72+
* @deprecated no more used, replaced with viewApp new call
73+
*/
74+
@Deprecated(forRemoval = true)
5975
public static final String M_APPTYPE_SELECTOR = "0xf8c2ceb3";
6076

6177
// dataset
78+
/**
79+
* @deprecated no more used, replaced with viewDataset new call
80+
*/
81+
@Deprecated(forRemoval = true)
6282
public static final String M_DATASETCHECKSUM_SELECTOR = "0x1ba99d7e";
83+
/**
84+
* @deprecated no more used, replaced with viewDataset new call
85+
*/
86+
@Deprecated(forRemoval = true)
6387
public static final String M_DATASETMULTIADDR_SELECTOR = "0xa61ca6c5";
6488

89+
// assets
90+
public static final String VIEW_APP_SELECTOR = "0xe1523fb4";
91+
public static final String VIEW_DATASET_SELECTOR = "0x1e143ef7";
92+
6593
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
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.commons.poco.encoding;
18+
19+
import com.iexec.commons.poco.utils.BytesUtils;
20+
import lombok.AccessLevel;
21+
import lombok.NoArgsConstructor;
22+
import lombok.extern.slf4j.Slf4j;
23+
import org.web3j.utils.Numeric;
24+
25+
import java.util.Arrays;
26+
27+
import static com.iexec.commons.poco.chain.Web3jAbstractService.toBigInt;
28+
29+
@Slf4j
30+
@NoArgsConstructor(access = AccessLevel.PRIVATE)
31+
public class PoCoDataDecoder {
32+
public static String decodeToAsciiString(final String[] parts, final int offset) {
33+
return BytesUtils.hexStringToAscii(decodeToHexString(parts, offset));
34+
}
35+
36+
public static String decodeToHexString(final String[] parts, final int offset) {
37+
final int size = toBigInt(parts[offset]).intValue();
38+
log.debug("Size {}", size);
39+
final StringBuilder sb = new StringBuilder();
40+
int remainingSize = size;
41+
int chunk = 1;
42+
while (remainingSize >= 32) {
43+
sb.append(parts[offset + chunk]);
44+
remainingSize -= 32;
45+
chunk++;
46+
}
47+
if (remainingSize != 0) {
48+
sb.append(parts[offset + chunk], 0, 2 * remainingSize);
49+
}
50+
return sb.toString();
51+
}
52+
53+
public static String[] toParts(final String rawData) {
54+
final String[] parts = Numeric.cleanHexPrefix(rawData).split("(?<=\\G.{64})");
55+
if (log.isTraceEnabled()) {
56+
log.trace("parts size {}", parts.length);
57+
Arrays.stream(parts).forEach(log::trace);
58+
}
59+
return parts;
60+
}
61+
}

src/main/java/com/iexec/commons/poco/tee/TeeEnclaveConfiguration.java

Lines changed: 9 additions & 1 deletion
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.
@@ -41,6 +41,14 @@ public static TeeEnclaveConfiguration buildEnclaveConfigurationFromJsonString(St
4141
.readValue(jsonString, TeeEnclaveConfiguration.class);
4242
}
4343

44+
public static TeeEnclaveConfiguration fromJsonString(final String jsonString) {
45+
try {
46+
return buildEnclaveConfigurationFromJsonString(jsonString);
47+
} catch (Exception e) {
48+
return null;
49+
}
50+
}
51+
4452
public String toJsonString() throws JsonProcessingException {
4553
return new ObjectMapper().writeValueAsString(this);
4654
}

src/test/java/com/iexec/commons/poco/itest/AssetRegistriesTests.java

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040

4141
import static com.iexec.commons.poco.itest.ChainTests.SERVICE_NAME;
4242
import static com.iexec.commons.poco.itest.ChainTests.SERVICE_PORT;
43-
import static com.iexec.commons.poco.itest.IexecHubTestService.ASSET_CHECKSUM;
4443
import static com.iexec.commons.poco.itest.IexecHubTestService.ASSET_MULTI_ADDRESS;
4544
import static com.iexec.commons.poco.itest.Web3jTestService.MINING_TIMEOUT;
4645
import static org.assertj.core.api.Assertions.assertThat;
@@ -74,14 +73,16 @@ void init() throws CipherException, IOException {
7473
@Test
7574
void shouldCreateAndPredictCallsBeEqualWhenAssetNotDeployed() {
7675
final String appName = RandomStringUtils.randomAlphanumeric(16);
76+
final String appChecksum = iexecHubService.generateChecksum();
7777
final String datasetName = RandomStringUtils.randomAlphanumeric(16);
78+
final String datasetChecksum = iexecHubService.generateChecksum();
7879
final String workerpoolName = RandomStringUtils.randomAlphanumeric(16);
7980

8081
assertAll(
81-
() -> assertThat(iexecHubService.callCreateApp(appName))
82-
.isEqualTo(iexecHubService.callPredictApp(appName)),
83-
() -> assertThat(iexecHubService.callCreateDataset(datasetName))
84-
.isEqualTo(iexecHubService.callPredictDataset(datasetName)),
82+
() -> assertThat(iexecHubService.callCreateApp(appName, appChecksum))
83+
.isEqualTo(iexecHubService.callPredictApp(appName, appChecksum)),
84+
() -> assertThat(iexecHubService.callCreateDataset(datasetName, datasetChecksum))
85+
.isEqualTo(iexecHubService.callPredictDataset(datasetName, datasetChecksum)),
8586
() -> assertThat(iexecHubService.callCreateWorkerpool(workerpoolName))
8687
.isEqualTo(iexecHubService.callPredictWorkerpool(workerpoolName))
8788
);
@@ -90,12 +91,14 @@ void shouldCreateAndPredictCallsBeEqualWhenAssetNotDeployed() {
9091
@Test
9192
void shouldCreateCallRevertWhenAssetDeployed() throws IOException {
9293
final String appName = RandomStringUtils.randomAlphanumeric(16);
94+
final String appChecksum = iexecHubService.generateChecksum();
9395
final String datasetName = RandomStringUtils.randomAlphanumeric(16);
96+
final String datasetChecksum = iexecHubService.generateChecksum();
9497
final String workerpoolName = RandomStringUtils.randomAlphanumeric(16);
9598
BigInteger nonce = signerService.getNonce();
96-
final String appTxHash = iexecHubService.submitCreateAppTx(nonce, appName);
99+
final String appTxHash = iexecHubService.submitCreateAppTx(nonce, appName, appChecksum);
97100
nonce = nonce.add(BigInteger.ONE);
98-
final String datasetTxHash = iexecHubService.submitCreateDatasetTx(nonce, datasetName);
101+
final String datasetTxHash = iexecHubService.submitCreateDatasetTx(nonce, datasetName, datasetChecksum);
99102
nonce = nonce.add(BigInteger.ONE);
100103
final String workerpoolTxHash = iexecHubService.submitCreateWorkerpoolTx(nonce, workerpoolName);
101104

@@ -104,8 +107,8 @@ void shouldCreateCallRevertWhenAssetDeployed() throws IOException {
104107
assertThat(web3jService.areTxStatusOK(appTxHash, datasetTxHash, workerpoolTxHash)).isTrue();
105108

106109
// fetch asset addresses from call on predict assets
107-
final String predictedAppAddress = iexecHubService.callPredictApp(appName);
108-
final String predictedDatasetAddress = iexecHubService.callPredictDataset(datasetName);
110+
final String predictedAppAddress = iexecHubService.callPredictApp(appName, appChecksum);
111+
final String predictedDatasetAddress = iexecHubService.callPredictDataset(datasetName, datasetChecksum);
109112
final String predictedWorkerpoolAddress = iexecHubService.callPredictWorkerpool(workerpoolName);
110113

111114
// check assets are deployed
@@ -125,10 +128,10 @@ void shouldCreateCallRevertWhenAssetDeployed() throws IOException {
125128
final String errorMessage = "Create2: Failed on deploy";
126129

127130
assertAll(
128-
() -> assertThatThrownBy(() -> iexecHubService.callCreateApp(appName), "Should have failed to call createApp")
131+
() -> assertThatThrownBy(() -> iexecHubService.callCreateApp(appName, appChecksum), "Should have failed to call createApp")
129132
.isInstanceOf(JsonRpcError.class)
130133
.hasMessage(errorMessage),
131-
() -> assertThatThrownBy(() -> iexecHubService.callCreateDataset(datasetName), "Should have failed to call createDataset")
134+
() -> assertThatThrownBy(() -> iexecHubService.callCreateDataset(datasetName, datasetChecksum), "Should have failed to call createDataset")
132135
.isInstanceOf(JsonRpcError.class)
133136
.hasMessage(errorMessage),
134137
() -> assertThatThrownBy(() -> iexecHubService.callCreateWorkerpool(workerpoolName), "Should have failed to call createWorkerpool")
@@ -140,7 +143,7 @@ void shouldCreateCallRevertWhenAssetDeployed() throws IOException {
140143
assertThat(chainApp).contains(
141144
ChainApp.builder()
142145
.chainAppId(predictedAppAddress)
143-
.checksum("0x" + ASSET_CHECKSUM)
146+
.checksum("0x" + appChecksum)
144147
.multiaddr(ASSET_MULTI_ADDRESS)
145148
.enclaveConfiguration(TeeEnclaveConfiguration.buildEnclaveConfigurationFromJsonString("{}"))
146149
.type("DOCKER")
@@ -150,7 +153,7 @@ void shouldCreateCallRevertWhenAssetDeployed() throws IOException {
150153
assertThat(chainDataset).contains(
151154
ChainDataset.builder()
152155
.chainDatasetId(predictedDatasetAddress)
153-
.checksum("0x" + ASSET_CHECKSUM)
156+
.checksum("0x" + datasetChecksum)
154157
.multiaddr(ASSET_MULTI_ADDRESS)
155158
.build()
156159
);

0 commit comments

Comments
 (0)