Skip to content

Commit

Permalink
test: Add in-equivalence tests for system accounts
Browse files Browse the repository at this point in the history
Signed-off-by: Bilyana Gospodinova <bilyana.gospodinova14@gmail.com>
  • Loading branch information
bilyana-gospodinova committed Mar 8, 2024
1 parent d64ac13 commit e700c89
Show file tree
Hide file tree
Showing 8 changed files with 343 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,13 @@ protected InputStream getResourceAsStream(String resourcePath) throws IOExceptio
}

protected byte[] encodeDataToByteArray(ContractResource resource, SelectorInterface method, Object... args) {
return encodeDataToByteArray(resource, method.getSelector(), args);
}

protected byte[] encodeDataToByteArray(ContractResource resource, String method, Object... args) {
String json;
try (var in = getResourceAsStream(resource.getPath())) {
json = getAbiFunctionAsJsonString(readCompiledArtifact(in), method.getSelector());
json = getAbiFunctionAsJsonString(readCompiledArtifact(in), method);
} catch (IOException e) {
throw new RuntimeException(e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import com.hedera.mirror.rest.model.TransactionsResponse;
import com.hedera.mirror.test.e2e.acceptance.config.AcceptanceTestProperties;
import com.hedera.mirror.test.e2e.acceptance.config.Web3Properties;
import com.hedera.mirror.test.e2e.acceptance.response.MirrorActionsResponse;
import com.hedera.mirror.test.e2e.acceptance.util.TestUtil;
import jakarta.inject.Named;
import java.util.ArrayList;
Expand Down Expand Up @@ -214,6 +215,11 @@ public ContractResult getContractResultByTransactionId(String transactionId) {
"/contracts/results/{transactionId}", ContractResult.class, transactionId);
}

public MirrorActionsResponse getContractActions(String transactionId) {
log.debug("Verify contract actions '{}' is returned by Mirror Node", transactionId);
return callRestEndpoint("/contracts/results/{contractId}/actions", MirrorActionsResponse.class, transactionId);
}

public NetworkExchangeRateSetResponse getExchangeRates() {
log.debug("Get exchange rates by Mirror Node");
return callRestEndpoint("/network/exchangerate", NetworkExchangeRateSetResponse.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,25 @@

package com.hedera.mirror.test.e2e.acceptance.client;

import static com.hedera.mirror.test.e2e.acceptance.util.TestUtil.hexToAscii;
import static org.apache.commons.lang3.ObjectUtils.isNotEmpty;

import com.esaulpaugh.headlong.abi.TupleType;
import com.esaulpaugh.headlong.util.Strings;
import com.hedera.hashgraph.sdk.ContractFunctionResult;
import com.hedera.hashgraph.sdk.Hbar;
import com.hedera.hashgraph.sdk.PrecheckStatusException;
import com.hedera.mirror.rest.model.ContractCallResponse;
import com.hedera.mirror.test.e2e.acceptance.client.ContractClient.NodeNameEnum;
import com.hedera.mirror.test.e2e.acceptance.response.GeneralContractExecutionResponse;
import com.hedera.mirror.test.e2e.acceptance.steps.AbstractFeature.DeployedContract;
import com.hedera.mirror.test.e2e.acceptance.steps.AbstractFeature.SelectorInterface;
import com.hedera.mirror.test.e2e.acceptance.util.ContractCallResponseWrapper;
import com.hedera.mirror.test.e2e.acceptance.util.ModelBuilder;
import jakarta.inject.Named;
import java.nio.ByteBuffer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import org.apache.tuweni.bytes.Bytes;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -48,7 +55,7 @@ public class NetworkAdapter extends EncoderDecoderFacade {
public static final TupleType BIG_INTEGER_TUPLE = TupleType.parse(UINT256);
public static final TupleType BYTES_TUPLE = TupleType.parse(BYTES);

public ContractCallResponse contractsCall(
public ContractCallResponseWrapper contractsCall(
final NodeNameEnum node,
boolean isEstimate,
final String from,
Expand All @@ -64,11 +71,11 @@ public ContractCallResponse contractsCall(
.from(from.isEmpty() ? contractClient.getClientAddress() : from)
.to(deployedContract.contractId().toSolidityAddress());

return mirrorClient.contractsCall(contractCallRequestBody);
return ContractCallResponseWrapper.of(mirrorClient.contractsCall(contractCallRequestBody));
} catch (Exception e) {
ContractCallResponse contractCallResponse = new ContractCallResponse();
contractCallResponse.setResult(e.getMessage());
return contractCallResponse;
return ContractCallResponseWrapper.of(contractCallResponse);
}
} else {
final var gas = contractClient
Expand All @@ -88,13 +95,46 @@ public ContractCallResponse contractsCall(
if (e instanceof PrecheckStatusException pse) {
final var exceptionReason = pse.status.toString();
contractCallResponse.setResult(exceptionReason);
return contractCallResponse;
return ContractCallResponseWrapper.of(contractCallResponse);
}

contractCallResponse.setResult(e.getMessage());
}

return contractCallResponse;
return ContractCallResponseWrapper.of(contractCallResponse);
}
}

public GeneralContractExecutionResponse contractsCall(
final NodeNameEnum node,
boolean isEstimate,
final String from,
final DeployedContract deployedContract,
final String method,
final byte[] data,
final Hbar amount) {
if (NodeNameEnum.MIRROR.equals(node)) {
var contractCallRequestBody = ModelBuilder.contractCallRequest()
.data(Strings.encode(ByteBuffer.wrap(data)))
.to(deployedContract.contractId().toSolidityAddress())
.from(from.isEmpty() ? contractClient.getClientAddress() : from)
.estimate(isEstimate)
.value(amount != null ? amount.toTinybars() : 0);

var response = mirrorClient.contractsCall(contractCallRequestBody);
return new GeneralContractExecutionResponse(ContractCallResponseWrapper.of(response));
} else {
final var gas = contractClient
.getSdkClient()
.getAcceptanceTestProperties()
.getFeatureProperties()
.getMaxContractFunctionGas();

final var result = contractClient.executeContract(deployedContract.contractId(), gas, method, data, amount);
final var txId =
result.networkTransactionResponse().getTransactionId().toString();
final var errorMessage = extractInternalCallErrorMessage(extractTransactionId(txId));
return new GeneralContractExecutionResponse(txId, result.networkTransactionResponse(), errorMessage);
}
}

Expand All @@ -115,4 +155,27 @@ private ContractCallResponse convertConsensusResponse(
}
return contractCallResponse;
}

private String extractInternalCallErrorMessage(String transactionId) throws IllegalArgumentException {
var actions = mirrorClient.getContractActions(transactionId).getActions();
if (actions == null || actions.size() < 2) {
throw new IllegalArgumentException("The actions list must contain at least two elements.");
}

if (!actions.get(1).getResultDataType().equalsIgnoreCase("OUTPUT")) {
String hexString = actions.get(1).getResultData();
return hexToAscii(hexString.replace("0x", ""));
}
return null;
}

private static String extractTransactionId(String message) {
Pattern pattern = Pattern.compile("(\\d+\\.\\d+\\.\\d+)@(\\d+)\\.(\\d+)");
Matcher matcher = pattern.matcher(message);
if (matcher.find()) {
return matcher.group(1) + "-" + matcher.group(2) + "-" + matcher.group(3);
} else {
return "Not found";
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.hedera.mirror.test.e2e.acceptance.response;

import com.hedera.mirror.test.e2e.acceptance.util.ContractCallResponseWrapper;

/**
* This is a class that represents a response either from the consensus node (with initialized transactionId,
* networkResponse, errorMessage) or from the mirror node (with initialized contractCallResponse).
* This is needed for the NetworkAdapter logic.
*/
public record GeneralContractExecutionResponse(String transactionId, NetworkTransactionResponse networkResponse, String errorMessage, ContractCallResponseWrapper contractCallResponse) {
public GeneralContractExecutionResponse(ContractCallResponseWrapper contractCallResponse) {
this(null, null, null, contractCallResponse);
}

public GeneralContractExecutionResponse(String transactionId, NetworkTransactionResponse networkResponse, String errorMessage) {
this(transactionId, networkResponse, errorMessage, null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright (C) 2023 Hedera Hashgraph, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.hedera.mirror.test.e2e.acceptance.response;

import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
import lombok.Data;

@Data
public class MirrorActionsResponse {
private List<Action> actions;

@Data
public static class Action {
@JsonProperty("call_depth")
private int callDepth;

@JsonProperty("call_operation_type")
private String callOperationType;

@JsonProperty("call_type")
private String callType;

private String caller;

@JsonProperty("caller_type")
private String callerType;

private String from;
private long gas;

@JsonProperty("gas_used")
private long gasUsed;

private int index;
private String input;

private String recipient;

@JsonProperty("recipient_type")
private String recipientType;

@JsonProperty("result_data")
private String resultData;

@JsonProperty("result_data_type")
private String resultDataType;

private String timestamp;
private String to;
private long value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import com.hedera.mirror.test.e2e.acceptance.client.MirrorNodeClient;
import com.hedera.mirror.test.e2e.acceptance.client.NetworkAdapter;
import com.hedera.mirror.test.e2e.acceptance.props.CompiledSolidityArtifact;
import com.hedera.mirror.test.e2e.acceptance.response.GeneralContractExecutionResponse;
import com.hedera.mirror.test.e2e.acceptance.response.NetworkTransactionResponse;
import com.hedera.mirror.test.e2e.acceptance.util.ContractCallResponseWrapper;
import com.hedera.mirror.test.e2e.acceptance.util.ModelBuilder;
Expand Down Expand Up @@ -191,8 +192,18 @@ protected ContractCallResponseWrapper callContract(
final SelectorInterface method,
final String data,
final TupleType returnTupleType) {
return ContractCallResponseWrapper.of(networkAdapter.contractsCall(
node, false, from, getContract(contractResource), method, data, returnTupleType));
return networkAdapter.contractsCall(
node, false, from, getContract(contractResource), method, data, returnTupleType);
}

protected GeneralContractExecutionResponse callContract(
final NodeNameEnum node,
final String from,
final ContractResource contractResource,
final String method,
final byte[] data,
final Hbar amount) {
return networkAdapter.contractsCall(node, false, from, getContract(contractResource), method, data, amount);
}

protected ContractCallResponseWrapper estimateContract(String data, String contractAddress) {
Expand Down

0 comments on commit e700c89

Please sign in to comment.