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
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,24 @@

import com.google.common.base.Stopwatch;
import com.google.common.base.Suppliers;
import com.google.protobuf.ByteString;
import com.hedera.hashgraph.sdk.AccountId;
import com.hedera.hashgraph.sdk.Client;
import com.hedera.hashgraph.sdk.ContractFunctionParameters;
import com.hedera.hashgraph.sdk.ContractId;
import com.hedera.hashgraph.sdk.MirrorNodeContractEstimateGasQuery;
import com.hedera.hashgraph.sdk.SubscriptionHandle;
import com.hedera.hashgraph.sdk.TokenId;
import com.hedera.hashgraph.sdk.TopicMessageQuery;
import jakarta.inject.Named;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
Expand Down Expand Up @@ -72,6 +80,7 @@
import org.hiero.mirror.test.e2e.acceptance.config.RestJavaProperties;
import org.hiero.mirror.test.e2e.acceptance.config.Web3Properties;
import org.hiero.mirror.test.e2e.acceptance.props.Order;
import org.hiero.mirror.test.e2e.acceptance.steps.AbstractFeature.ContractMethodInterface;
import org.hiero.mirror.test.e2e.acceptance.util.TestUtil;
import org.springframework.retry.RetryContext;
import org.springframework.retry.policy.MaxAttemptsRetryPolicy;
Expand All @@ -82,6 +91,9 @@
@CustomLog
@Named
public class MirrorNodeClient {
private static final int DEFAULT_PERCENTAGE_OF_ACTUAL_GAS_USED = 30;
private static final int DEFAULT_PERCENTAGE_OF_ACTUAL_GAS_USED_NESTED_CALLS = 100;
private static final long GAS_PRICE = 1_000_000L;

private final AcceptanceTestProperties acceptanceTestProperties;
private final RestClient restClient;
Expand All @@ -90,12 +102,14 @@
private final RestClient web3Client;
private final Web3Properties web3Properties;
private final Supplier<Boolean> partialStateSupplier = Suppliers.memoize(this::computeHasPartialState);
private final Client queryClient;

public MirrorNodeClient(
AcceptanceTestProperties acceptanceTestProperties,
RestClient.Builder restClientBuilder,
RestJavaProperties restJavaProperties,
Web3Properties web3Properties) {
Web3Properties web3Properties)
throws InterruptedException, URISyntaxException {
this.acceptanceTestProperties = acceptanceTestProperties;
this.restClient = restClientBuilder.build();
this.restJavaClient = StringUtils.isBlank(restJavaProperties.getBaseUrl())
Expand All @@ -115,6 +129,7 @@
.exponentialBackoff(properties.getMinBackoff(), 2.0, properties.getMaxBackoff())
.build();
this.web3Properties = web3Properties;
this.queryClient = createClient();

var virtualThreadFactory = Thread.ofVirtual().name("awaitility", 1).factory();
var executorService = Executors.newThreadPerTaskExecutor(virtualThreadFactory);
Expand Down Expand Up @@ -562,6 +577,111 @@
});
}

public long estimateGasQueryTopLevelCall(

Check notice on line 580 in test/src/test/java/org/hiero/mirror/test/e2e/acceptance/client/MirrorNodeClient.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

test/src/test/java/org/hiero/mirror/test/e2e/acceptance/client/MirrorNodeClient.java#L580

Method MirrorNodeClient::estimateGasQueryTopLevelCall has 5 parameters (limit is 4)
final ContractId contractId,
final ContractMethodInterface method,
final ContractFunctionParameters params,
final AccountId sender,
final Optional<Long> value)
throws ExecutionException, InterruptedException {
return estimateGasQuery(
contractId,
method.getSelector(),
params,
sender,
method.getActualGas(),
value,
DEFAULT_PERCENTAGE_OF_ACTUAL_GAS_USED);
}

private long estimateGasQuery(

Check notice on line 597 in test/src/test/java/org/hiero/mirror/test/e2e/acceptance/client/MirrorNodeClient.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

test/src/test/java/org/hiero/mirror/test/e2e/acceptance/client/MirrorNodeClient.java#L597

Method MirrorNodeClient::estimateGasQuery has 7 parameters (limit is 4)
final ContractId contractId,
final String functionName,
final ContractFunctionParameters params,
final AccountId sender,
final int actualGas,
final Optional<Long> value,
final int percentage)
throws ExecutionException, InterruptedException {

final long calculatedContractCallGas = calculateGasLimit(actualGas, percentage);

var gasEstimateQuery = buildEstimateGasQueryWithParams(contractId, functionName, params);
gasEstimateQuery.setGasLimit(calculatedContractCallGas);
if (sender != null) {
gasEstimateQuery.setSender(sender);
}
value.ifPresent(gasEstimateQuery::setValue);

return gasEstimateQuery.execute(queryClient);
}

public long estimateGasQueryWithoutParams(
final ContractId contractId, final String functionName, final AccountId sender, final int actualGas)
throws ExecutionException, InterruptedException {

final long calculatedContractCallGas = calculateGasLimit(actualGas, DEFAULT_PERCENTAGE_OF_ACTUAL_GAS_USED);

var gasEstimateQuery = new MirrorNodeContractEstimateGasQuery()
.setContractId(contractId)
.setFunction(functionName)
.setGasPrice(GAS_PRICE)
.setGasLimit(calculatedContractCallGas);
if (sender != null) {
gasEstimateQuery.setSender(sender);
}

return gasEstimateQuery.execute(queryClient);
}

public long estimateGasQueryRawData(
final ContractId contractId, final ByteString params, final AccountId sender, final int actualGas)
throws ExecutionException, InterruptedException {

final long calculatedContractCallGas = calculateGasLimit(actualGas, DEFAULT_PERCENTAGE_OF_ACTUAL_GAS_USED);

var gasEstimateQuery = new MirrorNodeContractEstimateGasQuery()
.setContractId(contractId)
.setFunctionParameters(params)
.setGasPrice(GAS_PRICE)
.setGasLimit(calculatedContractCallGas);
if (sender != null) {
gasEstimateQuery.setSender(sender);
}

return gasEstimateQuery.execute(queryClient);
}

public long estimateGasQueryNestedCall(

Check notice on line 655 in test/src/test/java/org/hiero/mirror/test/e2e/acceptance/client/MirrorNodeClient.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

test/src/test/java/org/hiero/mirror/test/e2e/acceptance/client/MirrorNodeClient.java#L655

Method MirrorNodeClient::estimateGasQueryNestedCall has 5 parameters (limit is 4)
final ContractId contractId,
final String functionName,
final ContractFunctionParameters params,
final AccountId sender,
final int actualGas)
throws ExecutionException, InterruptedException {

return estimateGasQuery(
contractId,
functionName,
params,
sender,
actualGas,
Optional.empty(),
DEFAULT_PERCENTAGE_OF_ACTUAL_GAS_USED_NESTED_CALLS);
}

private MirrorNodeContractEstimateGasQuery buildEstimateGasQueryWithParams(
ContractId contractId, String functionName, ContractFunctionParameters params) {
return new MirrorNodeContractEstimateGasQuery()
.setContractId(contractId)
.setFunction(functionName, params)
.setGasPrice(GAS_PRICE);
}

private long calculateGasLimit(int actualGas, int percentage) {
return Math.round(actualGas * (1 + (percentage / 100.0)));
}

private <T> T callWeb3GetRestEndpoint(
String uri, Class<T> classType, Map<String, String> headers, Object... uriVariables) {
final var normalizedUri = normalizeUri(uri);
Expand Down Expand Up @@ -593,4 +713,13 @@
// If the first block doesn't start at 0 => partial state
return number == null || number > 0;
}

private Client createClient() throws InterruptedException, URISyntaxException {
var endpoint = StringUtils.isNotBlank(web3Properties.getEndpoint())
? web3Properties.getEndpoint()
: acceptanceTestProperties.getRestProperties().getEndpoint();

var ledgerId = acceptanceTestProperties.getNetwork().getLedgerId();
return Client.forNetwork(Map.of()).setMirrorNetwork(List.of(endpoint)).setLedgerId(ledgerId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.hedera.hashgraph.sdk.AccountId;
import com.hedera.hashgraph.sdk.Client;
import com.hedera.hashgraph.sdk.Hbar;
import com.hedera.hashgraph.sdk.LedgerId;
import com.hedera.hashgraph.sdk.TopicDeleteTransaction;
import com.hedera.hashgraph.sdk.TopicId;
import com.hedera.hashgraph.sdk.TopicMessageSubmitTransaction;
Expand Down Expand Up @@ -140,7 +141,7 @@

if (!CollectionUtils.isEmpty(customNodes)) {
log.debug("Creating SDK client for {} network with nodes: {}", network, customNodes);
return toClient(getNetworkMap(customNodes));
return toClient(getNetworkMap(customNodes), network.getLedgerId());
}

if (acceptanceTestProperties.isRetrieveAddressBook()) {
Expand All @@ -151,7 +152,7 @@
.pollDelay(Duration.ofMillis(100))
.pollInterval(Durations.FIVE_SECONDS)
.until(this::getAddressBook, ab -> ab.getNodeAddressCount() > 0);
return toClient(addressBook);
return toClient(addressBook, network.getLedgerId());
} catch (Exception e) {
log.warn("Error retrieving address book", e);
}
Expand All @@ -161,7 +162,7 @@
throw new IllegalArgumentException("nodes must not be empty when network is OTHER");
}

return configureClient(Client.forName(network.toString().toLowerCase()));
return configureClient(Client.forName(network.toString().toLowerCase()).setLedgerId(network.getLedgerId()));

Check warning on line 165 in test/src/test/java/org/hiero/mirror/test/e2e/acceptance/client/SDKClient.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

test/src/test/java/org/hiero/mirror/test/e2e/acceptance/client/SDKClient.java#L165

When doing a String.toLowerCase()/toUpperCase() call, use a Locale
}

private NodeAddressBook getNetworkMap(Set<NodeProperties> nodes) {
Expand Down Expand Up @@ -262,8 +263,8 @@
}

@SneakyThrows
private Client toClient(NodeAddressBook addressBook) {
var client = Client.forNetwork(Map.of());
private Client toClient(NodeAddressBook addressBook, LedgerId ledgerId) {
var client = Client.forNetwork(Map.of()).setLedgerId(ledgerId);
client.setNetworkFromAddressBook(
com.hedera.hashgraph.sdk.NodeAddressBook.fromBytes(addressBook.toByteString()));
return configureClient(client).setMirrorNetwork(List.of(acceptanceTestProperties.getMirrorNodeAddress()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import com.hedera.hashgraph.sdk.AccountId;
import com.hedera.hashgraph.sdk.Hbar;
import com.hedera.hashgraph.sdk.LedgerId;
import jakarta.inject.Named;
import jakarta.validation.Valid;
import jakarta.validation.constraints.DecimalMax;
Expand Down Expand Up @@ -114,10 +115,11 @@ public void setOperatorId(String operatorId) {
@Getter
@RequiredArgsConstructor
public enum HederaNetwork {
MAINNET(295L),
TESTNET(296L),
PREVIEWNET(297L),
OTHER(298L);
MAINNET(295L, LedgerId.MAINNET),
TESTNET(296L, LedgerId.TESTNET),
PREVIEWNET(297L, LedgerId.PREVIEWNET),
OTHER(298L, LedgerId.fromBytes(new byte[] {(byte) 3}));
private final long chainId;
private final LedgerId ledgerId;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: Apache-2.0

package org.hiero.mirror.test.e2e.acceptance.config;

import java.net.URI;
import java.net.URISyntaxException;

public interface ApiProperties {
String getBaseUrl();

default String getEndpoint() throws URISyntaxException {
var endpoint = getBaseUrl();

if (endpoint != null) {
URI uri = new URI(endpoint);
if (uri.getPort() == -1) {
var https = uri.getScheme().equals("https");

Check warning on line 17 in test/src/test/java/org/hiero/mirror/test/e2e/acceptance/config/ApiProperties.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

test/src/test/java/org/hiero/mirror/test/e2e/acceptance/config/ApiProperties.java#L17

Position literals first in String comparisons
var trimmedEndpoint = endpoint.replaceFirst("/api/v1/?$", "");
endpoint = trimmedEndpoint + ":" + (https ? 443 : 80);
}
endpoint = (endpoint.replaceFirst("^https?://", "").replaceFirst("/api/v1/?$", ""));
}

return endpoint;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
@Validated
public class FeatureProperties {

private boolean contractCallLocalEstimate = false;
private boolean contractCallLocalEstimate = true;

private int hapiMinorVersionWithoutGasRefund = 67;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
@Data
@RequiredArgsConstructor
@Validated
public class RestProperties {
public class RestProperties implements ApiProperties {

public static final String URL_PREFIX = "/api/v1";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
@Named
@RequiredArgsConstructor
@Validated
public class Web3Properties {
public class Web3Properties implements ApiProperties {

private String baseUrl;

Expand Down
Loading
Loading