From e81ce334fda47eb0b535968e2b3719fb27a0eb95 Mon Sep 17 00:00:00 2001 From: dikel Date: Tue, 29 Nov 2022 11:24:25 +0200 Subject: [PATCH] Revert "chore: prepare for 2.18.2 release (#1236)" This reverts commit 8e81003c84c29c08feb911b2da80d7fb87822247. --- CHANGELOG.md | 14 +-- README.md | 8 +- build.gradle | 2 +- example-android/app/build.gradle | 2 +- examples/build.gradle | 4 +- sdk/build.gradle | 16 +-- .../ContractCreateFlowIntegrationTest.java | 104 +----------------- .../com/hedera/hashgraph/sdk/BaseNode.java | 1 - .../java/com/hedera/hashgraph/sdk/Client.java | 39 +------ .../hashgraph/sdk/ContractCreateFlow.java | 71 +----------- .../com/hedera/hashgraph/sdk/Executable.java | 45 ++++---- .../hedera/hashgraph/sdk/TokenNftInfo.java | 15 +-- .../hedera/hashgraph/sdk/ExecutableTest.java | 56 ---------- .../hashgraph/sdk/TokenNftInfoTest.snap | 6 +- version.gradle | 2 +- 15 files changed, 59 insertions(+), 326 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e3307c359..c60580c0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,19 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## 2.19.0 - -### Added - - `freezeWith()` and `sign()` to `ContractCreateFlow` - -### Fixed - - `Executable.execute(Client client, Duration timeout)` now sets gRPC deadline to the underlying gRPC request - - Transaction sometimes being reported as duplicate when submitting large number of transactions - - `RejectedExecutionException` under heavy load - - `nodes` not clearing when reusing transaction - - Renamed allowanceSpenderAccountId to spenderId in TokenNftInfo - -## 2.18.2 +## Unreleased ### Fixed - `Client.close()` now tracks and automatically unsubscribes from Mirror Node Topic Queries diff --git a/README.md b/README.md index 0760138c4..f18b0c14a 100644 --- a/README.md +++ b/README.md @@ -20,10 +20,10 @@ Select _one_ of the following depending on your target platform. ```groovy // Android, Corda DJVM, Java 7+ -implementation 'com.hedera.hashgraph:sdk-jdk7:2.19.0' +implementation 'com.hedera.hashgraph:sdk-jdk7:2.18.1' // Java 9+, Kotlin -implementation 'com.hedera.hashgraph:sdk:2.19.0' +implementation 'com.hedera.hashgraph:sdk:2.18.1' ``` Select _one_ of the following to provide the gRPC implementation. @@ -61,14 +61,14 @@ Select _one_ of the following depending on your target platform. com.hedera.hashgraph sdk-jdk7 - 2.19.0 + 2.18.1 com.hedera.hashgraph sdk - 2.19.0 + 2.18.1 ``` diff --git a/build.gradle b/build.gradle index b80b767c4..96f4ae3c7 100644 --- a/build.gradle +++ b/build.gradle @@ -31,7 +31,7 @@ allprojects { errorprone "com.google.errorprone:error_prone_core:2.16" // https://github.com/uber/NullAway - errorprone "com.uber.nullaway:nullaway:0.10.5" + errorprone "com.uber.nullaway:nullaway:0.10.4" // https://github.com/grpc/grpc-java-api-checker errorprone "io.grpc:grpc-java-api-checker:1.1.0" diff --git a/example-android/app/build.gradle b/example-android/app/build.gradle index e9370bd05..b0cae7b86 100644 --- a/example-android/app/build.gradle +++ b/example-android/app/build.gradle @@ -50,7 +50,7 @@ dependencies { androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' - implementation 'com.hedera.hashgraph:sdk-jdk7:2.19.0' + implementation 'com.hedera.hashgraph:sdk-jdk7:2.18.1' implementation 'org.slf4j:slf4j-simple:2.0.3' implementation 'io.grpc:grpc-okhttp:1.46.0' diff --git a/examples/build.gradle b/examples/build.gradle index 8da6ce3da..871aa3e68 100644 --- a/examples/build.gradle +++ b/examples/build.gradle @@ -3,8 +3,8 @@ dependencies { implementation project(":sdk") implementation "com.google.code.gson:gson:2.10" - implementation "org.slf4j:slf4j-simple:2.0.5" - implementation "io.grpc:grpc-netty-shaded:1.51.0" + implementation "org.slf4j:slf4j-simple:2.0.3" + implementation "io.grpc:grpc-netty-shaded:1.50.2" implementation "io.github.cdimascio:java-dotenv:5.3.1" implementation "com.google.errorprone:error_prone_core:2.16" } diff --git a/sdk/build.gradle b/sdk/build.gradle index 6cf319b4f..8ee0c833f 100644 --- a/sdk/build.gradle +++ b/sdk/build.gradle @@ -41,10 +41,10 @@ dependencies { implementation group: 'org.bouncycastle', name: 'bcpkix-jdk15to18', version: '1.72' // https://mvnrepository.com/artifact/org.slf4j/slf4j-api - implementation 'org.slf4j:slf4j-api:2.0.5' + implementation 'org.slf4j:slf4j-api:2.0.3' - implementation "io.grpc:grpc-core:1.51.0" - implementation "io.grpc:grpc-stub:1.51.0" + implementation "io.grpc:grpc-core:1.50.2" + implementation "io.grpc:grpc-stub:1.50.2" implementation "com.google.code.gson:gson:2.10" implementation 'javax.annotation:javax.annotation-api:1.3.2' @@ -55,12 +55,12 @@ dependencies { testImplementation "org.junit.jupiter:junit-jupiter-engine:5.9.1" testImplementation "org.junit.jupiter:junit-jupiter-params:5.9.1" - testRuntimeOnly "org.slf4j:slf4j-simple:2.0.5" - testRuntimeOnly "io.grpc:grpc-netty-shaded:1.51.0" - testRuntimeOnly 'org.slf4j:slf4j-nop:2.0.5' + testRuntimeOnly "org.slf4j:slf4j-simple:2.0.3" + testRuntimeOnly "io.grpc:grpc-netty-shaded:1.50.2" + testRuntimeOnly 'org.slf4j:slf4j-nop:2.0.3' integrationTestRuntimeOnly 'io.grpc:grpc-netty-shaded:1.50.2' - integrationTestRuntimeOnly 'org.slf4j:slf4j-nop:2.0.4' + integrationTestRuntimeOnly 'org.slf4j:slf4j-nop:2.0.2' } // https://github.com/google/protobuf-gradle-plugin @@ -70,7 +70,7 @@ protobuf { } plugins { grpc { - artifact = "io.grpc:protoc-gen-grpc-java:1.51.0" + artifact = "io.grpc:protoc-gen-grpc-java:1.50.2" } } } diff --git a/sdk/src/integrationTest/java/ContractCreateFlowIntegrationTest.java b/sdk/src/integrationTest/java/ContractCreateFlowIntegrationTest.java index 61092deda..5e97645b9 100644 --- a/sdk/src/integrationTest/java/ContractCreateFlowIntegrationTest.java +++ b/sdk/src/integrationTest/java/ContractCreateFlowIntegrationTest.java @@ -1,11 +1,14 @@ -import com.hedera.hashgraph.sdk.*; +import com.hedera.hashgraph.sdk.ContractCreateFlow; +import com.hedera.hashgraph.sdk.ContractDeleteTransaction; +import com.hedera.hashgraph.sdk.ContractExecuteTransaction; +import com.hedera.hashgraph.sdk.ContractFunctionParameters; +import com.hedera.hashgraph.sdk.Status; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import java.util.Objects; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; public class ContractCreateFlowIntegrationTest { private static final String SMART_CONTRACT_BYTECODE = "608060405234801561001057600080fd5b506040516104d73803806104d78339818101604052602081101561003357600080fd5b810190808051604051939291908464010000000082111561005357600080fd5b90830190602082018581111561006857600080fd5b825164010000000081118282018810171561008257600080fd5b82525081516020918201929091019080838360005b838110156100af578181015183820152602001610097565b50505050905090810190601f1680156100dc5780820380516001836020036101000a031916815260200191505b506040525050600080546001600160a01b0319163317905550805161010890600190602084019061010f565b50506101aa565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061015057805160ff191683800117855561017d565b8280016001018555821561017d579182015b8281111561017d578251825591602001919060010190610162565b5061018992915061018d565b5090565b6101a791905b808211156101895760008155600101610193565b90565b61031e806101b96000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063368b87721461004657806341c0e1b5146100ee578063ce6d41de146100f6575b600080fd5b6100ec6004803603602081101561005c57600080fd5b81019060208101813564010000000081111561007757600080fd5b82018360208201111561008957600080fd5b803590602001918460018302840111640100000000831117156100ab57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610173945050505050565b005b6100ec6101a2565b6100fe6101ba565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610138578181015183820152602001610120565b50505050905090810190601f1680156101655780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6000546001600160a01b0316331461018a5761019f565b805161019d906001906020840190610250565b505b50565b6000546001600160a01b03163314156101b85733ff5b565b60018054604080516020601f600260001961010087891615020190951694909404938401819004810282018101909252828152606093909290918301828280156102455780601f1061021a57610100808354040283529160200191610245565b820191906000526020600020905b81548152906001019060200180831161022857829003601f168201915b505050505090505b90565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061029157805160ff19168380011785556102be565b828001600101855582156102be579182015b828111156102be5782518255916020019190600101906102a3565b506102ca9291506102ce565b5090565b61024d91905b808211156102ca57600081556001016102d456fea264697066735822122084964d4c3f6bc912a9d20e14e449721012d625aa3c8a12de41ae5519752fc89064736f6c63430006000033"; @@ -43,101 +46,4 @@ void createContractWithFlow() throws Throwable { testEnv.close(); } - - @Test - @DisplayName("Create contract with flow without signing") - void createContractWithFlowWithoutSigning() throws Throwable { - var testEnv = new IntegrationTestEnv(1); - var adminKey = PrivateKey.generateED25519(); - - assertThatThrownBy(() -> new ContractCreateFlow() - .setBytecode(SMART_CONTRACT_BYTECODE) - .setAdminKey(adminKey) - .setGas(100000) - .setConstructorParameters(new ContractFunctionParameters().addString("Hello from Hedera.")) - .setContractMemo("[e2e::ContractCreateFlow]") - .execute(testEnv.client)) - .isInstanceOf(RuntimeException.class) - .hasMessageEndingWith("raised status INVALID_SIGNATURE"); - - testEnv.close(); - } - - @Test - @DisplayName("Create contract with flow and sign with private key") - void createContractWithFlowPrivateKeySign() throws Throwable { - var testEnv = new IntegrationTestEnv(1); - var adminKey = PrivateKey.generateED25519(); - - var response = new ContractCreateFlow() - .setBytecode(SMART_CONTRACT_BYTECODE) - .setAdminKey(testEnv.operatorKey) - .setGas(100000) - .setConstructorParameters(new ContractFunctionParameters().addString("Hello from Hedera.")) - .setContractMemo("[e2e::ContractCreateFlow]") - .freezeWith(testEnv.client) - .sign(adminKey) - .execute(testEnv.client); - - var contractId = Objects.requireNonNull(response.getReceipt(testEnv.client).contractId); - - var receipt = new ContractExecuteTransaction() - .setContractId(contractId) - .setGas(100000) - .setFunction("setMessage", new ContractFunctionParameters().addString("new message")) - .execute(testEnv.client) - .getReceipt(testEnv.client); - - assertThat(receipt.status).isEqualTo(Status.SUCCESS); - - new ContractDeleteTransaction() - .setTransferAccountId(testEnv.operatorId) - .setContractId(contractId) - .setTransferAccountId(testEnv.operatorId) - .freezeWith(testEnv.client) - .sign(adminKey) - .execute(testEnv.client) - .getReceipt(testEnv.client); - - testEnv.close(); - } - - @Test - @DisplayName("Create contract with flow and sign with public key and transaction signer") - void createContractWithFlowPublicKeySign() throws Throwable { - var testEnv = new IntegrationTestEnv(1); - var adminKey = PrivateKey.generateED25519(); - - var response = new ContractCreateFlow() - .setBytecode(SMART_CONTRACT_BYTECODE) - .setAdminKey(testEnv.operatorKey) - .setGas(100000) - .setConstructorParameters(new ContractFunctionParameters().addString("Hello from Hedera.")) - .setContractMemo("[e2e::ContractCreateFlow]") - .freezeWith(testEnv.client) - .signWith(adminKey.getPublicKey(), adminKey::sign) - .execute(testEnv.client); - - var contractId = Objects.requireNonNull(response.getReceipt(testEnv.client).contractId); - - var receipt = new ContractExecuteTransaction() - .setContractId(contractId) - .setGas(100000) - .setFunction("setMessage", new ContractFunctionParameters().addString("new message")) - .execute(testEnv.client) - .getReceipt(testEnv.client); - - assertThat(receipt.status).isEqualTo(Status.SUCCESS); - - new ContractDeleteTransaction() - .setTransferAccountId(testEnv.operatorId) - .setContractId(contractId) - .setTransferAccountId(testEnv.operatorId) - .freezeWith(testEnv.client) - .sign(adminKey) - .execute(testEnv.client) - .getReceipt(testEnv.client); - - testEnv.close(); - } } diff --git a/sdk/src/main/java/com/hedera/hashgraph/sdk/BaseNode.java b/sdk/src/main/java/com/hedera/hashgraph/sdk/BaseNode.java index f48eda8be..3a2a7bff3 100644 --- a/sdk/src/main/java/com/hedera/hashgraph/sdk/BaseNode.java +++ b/sdk/src/main/java/com/hedera/hashgraph/sdk/BaseNode.java @@ -298,7 +298,6 @@ synchronized ManagedChannel getChannel() { .keepAliveTimeout(10, TimeUnit.SECONDS) .userAgent(getUserAgent()) .executor(executor) - .disableRetry() .build(); return channel; diff --git a/sdk/src/main/java/com/hedera/hashgraph/sdk/Client.java b/sdk/src/main/java/com/hedera/hashgraph/sdk/Client.java index 84f73869d..2b087ee2a 100644 --- a/sdk/src/main/java/com/hedera/hashgraph/sdk/Client.java +++ b/sdk/src/main/java/com/hedera/hashgraph/sdk/Client.java @@ -44,7 +44,6 @@ import java.nio.file.Files; import java.util.*; import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicReference; import java.util.function.Supplier; import static com.hedera.hashgraph.sdk.BaseNodeAddress.PORT_NODE_PLAIN; @@ -61,7 +60,6 @@ public final class Client implements AutoCloseable { static final Duration DEFAULT_MIN_NODE_BACKOFF = Duration.ofSeconds(8L); static final Duration DEFAULT_CLOSE_TIMEOUT = Duration.ofSeconds(30L); static final Duration DEFAULT_REQUEST_TIMEOUT = Duration.ofMinutes(2L); - static final Duration DEFAULT_GRPC_DEADLINE = Duration.ofSeconds(10L); static final Duration DEFAULT_NETWORK_UPDATE_PERIOD = Duration.ofHours(24); // Initial delay of 10 seconds before we update the network for the first time, // so that this doesn't happen in unit tests. @@ -85,7 +83,6 @@ public final class Client implements AutoCloseable { private Duration requestTimeout = DEFAULT_REQUEST_TIMEOUT; private Duration closeTimeout = DEFAULT_CLOSE_TIMEOUT; - private final AtomicReference grpcDeadline = new AtomicReference(DEFAULT_GRPC_DEADLINE); private int maxAttempts = DEFAULT_MAX_ATTEMPTS; @@ -139,11 +136,9 @@ static ExecutorService createExecutor() { .setDaemon(true) .build(); - int nThreads = Runtime.getRuntime().availableProcessors(); - return new ThreadPoolExecutor(nThreads, nThreads, - 0L, TimeUnit.MILLISECONDS, - new LinkedBlockingQueue<>(), - threadFactory, new ThreadPoolExecutor.CallerRunsPolicy()); + return Executors.newFixedThreadPool( + Runtime.getRuntime().availableProcessors(), + threadFactory); } /** @@ -1245,34 +1240,6 @@ public Client setCloseTimeout(Duration closeTimeout) { return this; } - /** - * Maximum amount of time a gRPC request can run - * - * @return the gRPC deadline value - */ - @SuppressFBWarnings( - value = "EI_EXPOSE_REP", - justification = "A Duration can't actually be mutated" - ) - public Duration getGrpcDeadline() { - return grpcDeadline.get(); - } - - /** - * Set the maximum amount of time a gRPC request can run. - * - * @param grpcDeadline the gRPC deadline value - * @return {@code this} - */ - @SuppressFBWarnings( - value = "EI_EXPOSE_REP2", - justification = "A Duration can't actually be mutated" - ) - public Client setGrpcDeadline(Duration grpcDeadline) { - this.grpcDeadline.set(Objects.requireNonNull(grpcDeadline)); - return this; - } - /** * Extract the operator. * diff --git a/sdk/src/main/java/com/hedera/hashgraph/sdk/ContractCreateFlow.java b/sdk/src/main/java/com/hedera/hashgraph/sdk/ContractCreateFlow.java index 2e8f55f04..5aa08691a 100644 --- a/sdk/src/main/java/com/hedera/hashgraph/sdk/ContractCreateFlow.java +++ b/sdk/src/main/java/com/hedera/hashgraph/sdk/ContractCreateFlow.java @@ -21,12 +21,13 @@ import com.google.protobuf.ByteString; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import java8.util.Lists; import java8.util.concurrent.CompletableFuture; import java8.util.function.BiConsumer; import java8.util.function.Consumer; -import java8.util.function.Function; import org.bouncycastle.util.encoders.Hex; import org.threeten.bp.Duration; +import org.threeten.bp.Instant; import javax.annotation.Nullable; import java.util.Arrays; @@ -34,6 +35,7 @@ import java.util.List; import java.util.ArrayList; import java.util.Objects; +import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; /** @@ -115,18 +117,6 @@ public class ContractCreateFlow { private boolean declineStakingReward = false; - @Nullable - private Client freezeWithClient = null; - - @Nullable - private PrivateKey signPrivateKey = null; - - @Nullable - private PublicKey signPublicKey = null; - - @Nullable - private Function transactionSigner = null; - public ContractCreateFlow() { } @@ -482,53 +472,6 @@ public ContractCreateFlow setNodeAccountIds(List nodeAccountIds) { return this; } - /** - * Set the client that this transaction will be frozen with. - * - * @return {@code this} - */ - public ContractCreateFlow freezeWith(Client client) { - this.freezeWithClient = client; - return this; - } - - /** - * Set the private key that this transaction will be signed with. - * - * @return {@code this} - */ - public ContractCreateFlow sign(PrivateKey privateKey) { - this.signPrivateKey = privateKey; - this.signPublicKey = null; - this.transactionSigner = null; - return this; - } - - /** - * Set the public key and key list that this transaction will be signed with. - * - * @return {@code this} - */ - public ContractCreateFlow signWith(PublicKey publicKey, Function transactionSigner) { - this.signPublicKey = publicKey; - this.transactionSigner = transactionSigner; - this.signPrivateKey = null; - return this; - } - - /** - * Set the operator that this transaction will be signed with. - * - * @return {@code this} - */ - public ContractCreateFlow signWithOperator(Client client) { - var operator = Objects.requireNonNull(client.getOperator()); - this.signPublicKey = operator.publicKey; - this.transactionSigner = operator.transactionSigner; - this.signPrivateKey = null; - return this; - } - private void splitBytecode() { if(bytecode.length() > FILE_CREATE_MAX_BYTES) { createBytecode = bytecode.substring(0, FILE_CREATE_MAX_BYTES); @@ -593,14 +536,6 @@ private ContractCreateTransaction createContractCreateTransaction(FileId fileId) } else if (stakedNodeId != null) { contractCreateTx.setStakedNodeId(stakedNodeId); } - if (freezeWithClient != null) { - contractCreateTx.freezeWith(freezeWithClient); - } - if (signPrivateKey != null) { - contractCreateTx.sign(signPrivateKey); - } else if (signPublicKey != null && transactionSigner != null) { - contractCreateTx.signWith(signPublicKey, transactionSigner); - } return contractCreateTx; } diff --git a/sdk/src/main/java/com/hedera/hashgraph/sdk/Executable.java b/sdk/src/main/java/com/hedera/hashgraph/sdk/Executable.java index 66d565fc5..890190e15 100644 --- a/sdk/src/main/java/com/hedera/hashgraph/sdk/Executable.java +++ b/sdk/src/main/java/com/hedera/hashgraph/sdk/Executable.java @@ -82,6 +82,7 @@ abstract class Executable blockingUnaryCall = (grpcRequest) -> ClientCalls.blockingUnaryCall(grpcRequest.createCall(), grpcRequest.getRequest()); + @Nullable protected Duration grpcDeadline; private java8.util.function.Function requestListener; private java8.util.function.Function responseListener; @@ -107,6 +108,7 @@ abstract class Executable executeAsync(Client client, Duration timeout) { checkNodeAccountIds(); setNodesFromNodeAccountIds(client); - executeAsyncInternal(client, 1, null, retval, timeout); + executeAsyncInternal(client, 1, null, retval); }).exceptionally(error -> { retval.completeExceptionally(error); return null; @@ -490,7 +487,6 @@ public void executeAsync(Client client, Duration timeout, Consumer onSuccess, @VisibleForTesting void setNodesFromNodeAccountIds(Client client) { - nodes.clear(); for (var accountId : nodeAccountIds) { @Nullable var node = client.network.getNode(accountId); @@ -566,8 +562,7 @@ private void executeAsyncInternal( Client client, int attempt, @Nullable Throwable lastException, - CompletableFuture returnFuture, - Duration timeout + CompletableFuture returnFuture ) { if (returnFuture.isCancelled() || returnFuture.isCompletedExceptionally() || returnFuture.isDone()) { return; @@ -578,9 +573,7 @@ private void executeAsyncInternal( return; } - var timeoutTime = Instant.now().plus(timeout); - - GrpcRequest grpcRequest = new GrpcRequest(client.network, attempt, Duration.between(Instant.now(), timeoutTime)); + GrpcRequest grpcRequest = new GrpcRequest(client.network, attempt); Supplier> afterUnhealthyDelay = () -> { return grpcRequest.getNode().isHealthy() ? @@ -592,14 +585,14 @@ private void executeAsyncInternal( grpcRequest.getNode().channelFailedToConnectAsync().thenAccept(connectionFailed -> { if (connectionFailed) { var connectionException = grpcRequest.reactToConnectionFailure(); - executeAsyncInternal(client, attempt + 1, connectionException, returnFuture, Duration.between(Instant.now(), timeoutTime)); + executeAsyncInternal(client, attempt + 1, connectionException, returnFuture); return; } toCompletableFuture(ClientCalls.futureUnaryCall(grpcRequest.createCall(), grpcRequest.getRequest())).handle((response, error) -> { if (grpcRequest.shouldRetryExceptionally(error)) { // the transaction had a network failure reaching Hedera - executeAsyncInternal(client, attempt + 1, error, returnFuture, Duration.between(Instant.now(), timeoutTime)); + executeAsyncInternal(client, attempt + 1, error, returnFuture); return null; } @@ -611,11 +604,11 @@ private void executeAsyncInternal( switch (grpcRequest.getStatus(response)) { case ServerError: - executeAsyncInternal(client, attempt + 1, grpcRequest.mapStatusException(), returnFuture, Duration.between(Instant.now(), timeoutTime)); + executeAsyncInternal(client, attempt + 1, grpcRequest.mapStatusException(), returnFuture); break; case Retry: Delayer.delayFor((attempt < maxAttempts) ? grpcRequest.getDelay() : 0, client.executor).thenRun(() -> { - executeAsyncInternal(client, attempt + 1, grpcRequest.mapStatusException(), returnFuture, Duration.between(Instant.now(), timeoutTime)); + executeAsyncInternal(client, attempt + 1, grpcRequest.mapStatusException(), returnFuture); }); break; case RequestError: @@ -640,7 +633,7 @@ private void executeAsyncInternal( abstract ProtoRequestT makeRequest(); GrpcRequest getGrpcRequest(int attempt) { - return new GrpcRequest(null, attempt, this.grpcDeadline); + return new GrpcRequest(null, attempt); } void advanceRequest() { @@ -709,16 +702,14 @@ class GrpcRequest { private final ProtoRequestT request; private final long startAt; private final long delay; - private Duration grpcDeadline; private ResponseT response; private double latency; private Status responseStatus; - GrpcRequest(@Nullable Network network, int attempt, Duration grpcDeadline) { + GrpcRequest(@Nullable Network network, int attempt) { this.network = network; this.attempt = attempt; - this.grpcDeadline = grpcDeadline; this.node = getNodeForExecute(attempt); this.request = getRequestForExecute(); // node index gets incremented here this.startAt = System.nanoTime(); @@ -728,11 +719,13 @@ class GrpcRequest { } public CallOptions getCallOptions() { - long deadline = Math.min( - this.grpcDeadline.toMillis(), - Executable.this.grpcDeadline.toMillis()); + var options = CallOptions.DEFAULT; - return CallOptions.DEFAULT.withDeadlineAfter(deadline, TimeUnit.MILLISECONDS); + if (Executable.this.grpcDeadline != null) { + return options.withDeadlineAfter(Executable.this.grpcDeadline.toMillis(), TimeUnit.MILLISECONDS); + } else { + return options; + } } public Node getNode() { diff --git a/sdk/src/main/java/com/hedera/hashgraph/sdk/TokenNftInfo.java b/sdk/src/main/java/com/hedera/hashgraph/sdk/TokenNftInfo.java index 87c66cd8f..6c3e8ef0e 100644 --- a/sdk/src/main/java/com/hedera/hashgraph/sdk/TokenNftInfo.java +++ b/sdk/src/main/java/com/hedera/hashgraph/sdk/TokenNftInfo.java @@ -22,6 +22,7 @@ import com.google.common.base.MoreObjects; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; +import com.hedera.hashgraph.sdk.proto.TokenGetNftInfoResponse; import org.threeten.bp.Instant; import javax.annotation.Nullable; @@ -62,7 +63,7 @@ public class TokenNftInfo { * If an allowance is granted for the NFT, its corresponding spender account */ @Nullable - public final AccountId spenderId; + public final AccountId allowanceSpenderAccountId; /** * Constructor. @@ -72,7 +73,7 @@ public class TokenNftInfo { * @param creationTime the effective consensus time * @param metadata the unique metadata * @param ledgerId the ledger id of the response - * @param spenderId the spender of the allowance (null if not an allowance) + * @param allowanceSpenderAccountId the spender of the allowance (null if not an allowance) */ TokenNftInfo( NftId nftId, @@ -80,14 +81,14 @@ public class TokenNftInfo { Instant creationTime, byte[] metadata, LedgerId ledgerId, - @Nullable AccountId spenderId + @Nullable AccountId allowanceSpenderAccountId ) { this.nftId = nftId; this.accountId = accountId; this.creationTime = Objects.requireNonNull(creationTime); this.metadata = metadata; this.ledgerId = ledgerId; - this.spenderId = spenderId; + this.allowanceSpenderAccountId = allowanceSpenderAccountId; } /** @@ -130,8 +131,8 @@ com.hedera.hashgraph.sdk.proto.TokenNftInfo toProtobuf() { .setCreationTime(InstantConverter.toProtobuf(creationTime)) .setMetadata(ByteString.copyFrom(metadata)) .setLedgerId(ledgerId.toByteString()); - if (spenderId != null) { - builder.setSpenderId(spenderId.toProtobuf()); + if (allowanceSpenderAccountId != null) { + builder.setSpenderId(allowanceSpenderAccountId.toProtobuf()); } return builder.build(); } @@ -144,7 +145,7 @@ public String toString() { .add("creationTime", creationTime) .add("metadata", metadata) .add("ledgerId", ledgerId) - .add("spenderId", spenderId) + .add("allowanceSpenderAccountId", allowanceSpenderAccountId) .toString(); } diff --git a/sdk/src/test/java/com/hedera/hashgraph/sdk/ExecutableTest.java b/sdk/src/test/java/com/hedera/hashgraph/sdk/ExecutableTest.java index 1b2359911..989700b73 100644 --- a/sdk/src/test/java/com/hedera/hashgraph/sdk/ExecutableTest.java +++ b/sdk/src/test/java/com/hedera/hashgraph/sdk/ExecutableTest.java @@ -38,7 +38,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -110,61 +109,6 @@ void calloptionsShouldRespectGrpcDeadline() { assertThat(timeRemaining).isGreaterThan(9000); } - @Test - void executableShouldUseGrpcDeadline() throws InterruptedException, PrecheckStatusException, TimeoutException { - when(node3.isHealthy()).thenReturn(true); - - var tx = new DummyTransaction(); - tx.setNodeAccountIds(nodeAccountIds); - tx.setNodesFromNodeAccountIds(client); - tx.setMinBackoff(Duration.ofMillis(10)); - tx.setMaxBackoff(Duration.ofMillis(1000)); - tx.setMaxAttempts(10); - - var timeout = Duration.ofSeconds(5); - var currentTimeRemaining = new AtomicLong(timeout.toMillis()); - final long minimumRetryDelayMs = 100; - final long defaultDeadlineMs = timeout.toMillis() - (minimumRetryDelayMs * (tx.getMaxAttempts() / 2)); - - // later on when the transaction is executed its grpc deadline should not be modified... - tx.setGrpcDeadline(Duration.ofMillis(defaultDeadlineMs)); - - tx.blockingUnaryCall = (grpcRequest) -> { - var grpc = (Executable.GrpcRequest)grpcRequest; - - var grpcTimeRemaining = grpc.getCallOptions().getDeadline().timeRemaining(TimeUnit.MILLISECONDS); - - // the actual grpc deadline should be no larger than the smaller of the two values - - // the default transaction level grpc deadline and the remaining timeout - assertThat(grpcTimeRemaining).isLessThanOrEqualTo(defaultDeadlineMs); - assertThat(grpcTimeRemaining).isLessThanOrEqualTo(currentTimeRemaining.get()); - - assertThat(grpcTimeRemaining).isGreaterThan(0); - - // transaction's grpc deadline should keep its original value - assertThat(tx.grpcDeadline().toMillis()).isEqualTo(defaultDeadlineMs); - - currentTimeRemaining.set(currentTimeRemaining.get() - minimumRetryDelayMs); - - if (currentTimeRemaining.get() > 0) { - try { - Thread.sleep(minimumRetryDelayMs); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - - // Status.UNAVAILABLE tells the Executable to retry the request - throw new StatusRuntimeException(io.grpc.Status.UNAVAILABLE); - } - - throw new StatusRuntimeException(io.grpc.Status.ABORTED); - }; - - assertThatExceptionOfType(MaxAttemptsExceededException.class).isThrownBy(() -> { - tx.execute(client, timeout); - }); - } - @Test void multipleNodesUnhealthy() { when(node3.isHealthy()).thenReturn(false); diff --git a/sdk/src/test/java/com/hedera/hashgraph/sdk/TokenNftInfoTest.snap b/sdk/src/test/java/com/hedera/hashgraph/sdk/TokenNftInfoTest.snap index 4b4007c09..dc8f38cf4 100644 --- a/sdk/src/test/java/com/hedera/hashgraph/sdk/TokenNftInfoTest.snap +++ b/sdk/src/test/java/com/hedera/hashgraph/sdk/TokenNftInfoTest.snap @@ -1,8 +1,8 @@ com.hedera.hashgraph.sdk.TokenNftInfoTest.shouldSerialize=[ - "TokenNftInfo{nftId=1.2.3/4, accountId=5.6.7, creationTime=2019-04-01T22:42:22Z, metadata=[-34, -83, -66, -17], ledgerId=mainnet, spenderId=8.9.10}" + "TokenNftInfo{nftId=1.2.3/4, accountId=5.6.7, creationTime=2019-04-01T22:42:22Z, metadata=[-34, -83, -66, -17], ledgerId=mainnet, allowanceSpenderAccountId=8.9.10}" ] com.hedera.hashgraph.sdk.TokenNftInfoTest.shouldSerializeNullSpender=[ - "TokenNftInfo{nftId=1.2.3/4, accountId=5.6.7, creationTime=2019-04-01T22:42:22Z, metadata=[-34, -83, -66, -17], ledgerId=mainnet, spenderId=null}" -] + "TokenNftInfo{nftId=1.2.3/4, accountId=5.6.7, creationTime=2019-04-01T22:42:22Z, metadata=[-34, -83, -66, -17], ledgerId=mainnet, allowanceSpenderAccountId=null}" +] \ No newline at end of file diff --git a/version.gradle b/version.gradle index e750c29f7..ba4ee5438 100644 --- a/version.gradle +++ b/version.gradle @@ -2,4 +2,4 @@ // and `sdk/build.gradle` so I extracted them into another file and made both aforementioned // files import this one. group = "com.hedera.hashgraph" -version = "2.19.0" +version = "2.18.1"