Skip to content

Commit 9bcfbd3

Browse files
committed
hip 1299 - switch error from INVALID_NODE_ACCOUNT_ID to INVALID_NODE_ACCOUNT
Signed-off-by: emiliyank <e.kadiyski@gmail.com>
1 parent c25d9cd commit 9bcfbd3

File tree

3 files changed

+45
-44
lines changed

3 files changed

+45
-44
lines changed

sdk/src/main/java/com/hedera/hashgraph/sdk/Executable.java

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -441,11 +441,11 @@ public O execute(Client client, Duration timeout) throws TimeoutException, Prech
441441
case SERVER_ERROR:
442442
lastException = grpcRequest.mapStatusException();
443443
advanceRequest(); // Advance to next node before retrying
444-
445-
// Handle INVALID_NODE_ACCOUNT_ID after advancing (matches Go SDK's executionStateRetryWithAnotherNode)
446-
if (status == Status.INVALID_NODE_ACCOUNT_ID) {
444+
445+
// Handle INVALID_NODE_ACCOUNT after advancing (matches Go SDK's executionStateRetryWithAnotherNode)
446+
if (status == Status.INVALID_NODE_ACCOUNT) {
447447
logger.trace(
448-
"Received INVALID_NODE_ACCOUNT_ID; updating address book and marking node {} as unhealthy, attempt #{}",
448+
"Received INVALID_NODE_ACCOUNT; updating address book and marking node {} as unhealthy, attempt #{}",
449449
node.getAccountId(),
450450
attempt);
451451
// Schedule async address book update (matches Go's defer client._UpdateAddressBook())
@@ -789,19 +789,21 @@ private void executeAsyncInternal(
789789
switch (executionState) {
790790
case SERVER_ERROR:
791791
advanceRequest(); // Advance to next node before retrying
792-
793-
// Handle INVALID_NODE_ACCOUNT_ID after advancing (matches Go SDK's executionStateRetryWithAnotherNode)
794-
if (status == Status.INVALID_NODE_ACCOUNT_ID) {
792+
793+
// Handle INVALID_NODE_ACCOUNT after advancing (matches Go SDK's
794+
// executionStateRetryWithAnotherNode)
795+
if (status == Status.INVALID_NODE_ACCOUNT) {
795796
logger.trace(
796-
"Received INVALID_NODE_ACCOUNT_ID; updating address book and marking node {} as unhealthy, attempt #{}",
797+
"Received INVALID_NODE_ACCOUNT; updating address book and marking node {} as unhealthy, attempt #{}",
797798
grpcRequest.getNode().getAccountId(),
798799
attempt);
799-
// Schedule async address book update (matches Go's defer client._UpdateAddressBook())
800+
// Schedule async address book update (matches Go's defer
801+
// client._UpdateAddressBook())
800802
client.updateNetworkFromAddressBook();
801803
// Mark this node as unhealthy
802804
client.network.increaseBackoff(grpcRequest.getNode());
803805
}
804-
806+
805807
executeAsyncInternal(
806808
client,
807809
attempt + 1,
@@ -901,9 +903,10 @@ ExecutionState getExecutionState(Status status, ResponseT response) {
901903
return ExecutionState.SERVER_ERROR;
902904
case BUSY:
903905
return ExecutionState.RETRY;
904-
case INVALID_NODE_ACCOUNT_ID:
906+
case INVALID_NODE_ACCOUNT:
905907
// Matches Go SDK's executionStateRetryWithAnotherNode behavior:
906908
// immediately retry with next node without delay
909+
// This occurs when a node's account ID has changed
907910
return ExecutionState.SERVER_ERROR;
908911
case OK:
909912
return ExecutionState.SUCCESS;
@@ -1010,9 +1013,9 @@ O mapResponse() {
10101013
}
10111014

10121015
void handleResponse(ResponseT response, Status status, ExecutionState executionState, @Nullable Client client) {
1013-
// Note: For INVALID_NODE_ACCOUNT_ID, we don't mark the node as unhealthy here
1016+
// Note: For INVALID_NODE_ACCOUNT, we don't mark the node as unhealthy here
10141017
// because we need to do it AFTER advancing the request, to match Go SDK behavior
1015-
if (status != Status.INVALID_NODE_ACCOUNT_ID) {
1018+
if (status != Status.INVALID_NODE_ACCOUNT) {
10161019
node.decreaseBackoff();
10171020
}
10181021

@@ -1042,9 +1045,9 @@ void handleResponse(ResponseT response, Status status, ExecutionState executionS
10421045
verboseLog(node);
10431046
}
10441047
case SERVER_ERROR -> {
1045-
// Note: INVALID_NODE_ACCOUNT_ID is handled after advanceRequest() in execute methods
1048+
// Note: INVALID_NODE_ACCOUNT is handled after advanceRequest() in execute methods
10461049
// to match Go SDK's executionStateRetryWithAnotherNode behavior
1047-
if (status != Status.INVALID_NODE_ACCOUNT_ID) {
1050+
if (status != Status.INVALID_NODE_ACCOUNT) {
10481051
logger.warn(
10491052
"Problem submitting request to node {} for attempt #{}, retry with new node: {}",
10501053
node.getAccountId(),

sdk/src/test/java/com/hedera/hashgraph/sdk/ExecutableTest.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -512,9 +512,9 @@ void shouldRetryReturnsCorrectStates() {
512512
.isEqualTo(ExecutionState.SERVER_ERROR);
513513
assertThat(tx.getExecutionState(Status.PLATFORM_NOT_ACTIVE, null)).isEqualTo(ExecutionState.SERVER_ERROR);
514514
assertThat(tx.getExecutionState(Status.BUSY, null)).isEqualTo(ExecutionState.RETRY);
515-
// INVALID_NODE_ACCOUNT_ID now returns SERVER_ERROR to match Go SDK's executionStateRetryWithAnotherNode
515+
// INVALID_NODE_ACCOUNT now returns SERVER_ERROR to match Go SDK's executionStateRetryWithAnotherNode
516516
// which immediately retries with another node without delay
517-
assertThat(tx.getExecutionState(Status.INVALID_NODE_ACCOUNT_ID, null)).isEqualTo(ExecutionState.SERVER_ERROR);
517+
assertThat(tx.getExecutionState(Status.INVALID_NODE_ACCOUNT, null)).isEqualTo(ExecutionState.SERVER_ERROR);
518518
assertThat(tx.getExecutionState(Status.OK, null)).isEqualTo(ExecutionState.SUCCESS);
519519
assertThat(tx.getExecutionState(Status.ACCOUNT_DELETED, null)).isEqualTo(ExecutionState.REQUEST_ERROR);
520520
}
@@ -542,22 +542,22 @@ void shouldMarkNodeAsUnusableOnInvalidNodeAccountId() throws PrecheckStatusExcep
542542
var tx = new DummyTransaction() {
543543
@Override
544544
Status mapResponseStatus(com.hedera.hashgraph.sdk.proto.TransactionResponse response) {
545-
return Status.INVALID_NODE_ACCOUNT_ID;
545+
return Status.INVALID_NODE_ACCOUNT;
546546
}
547547
};
548548
var nodeAccountIds = Arrays.asList(new AccountId(0, 0, 3), new AccountId(0, 0, 4), new AccountId(0, 0, 5));
549549
tx.setNodeAccountIds(nodeAccountIds);
550550

551551
var txResp = com.hedera.hashgraph.sdk.proto.TransactionResponse.newBuilder()
552-
.setNodeTransactionPrecheckCode(ResponseCodeEnum.INVALID_NODE_ACCOUNT_ID)
552+
.setNodeTransactionPrecheckCode(ResponseCodeEnum.INVALID_NODE_ACCOUNT)
553553
.build();
554554

555555
tx.blockingUnaryCall = (grpcRequest) -> txResp;
556556

557-
// This should retry with a different node due to INVALID_NODE_ACCOUNT_ID
557+
// This should retry with a different node due to INVALID_NODE_ACCOUNT
558558
assertThatExceptionOfType(MaxAttemptsExceededException.class).isThrownBy(() -> tx.execute(client));
559559

560-
// Verify that increaseBackoff was called on the network for each node that returned INVALID_NODE_ACCOUNT_ID
560+
// Verify that increaseBackoff was called on the network for each node that returned INVALID_NODE_ACCOUNT
561561
verify(network, atLeastOnce()).increaseBackoff(any(Node.class));
562562
}
563563

@@ -569,19 +569,19 @@ void shouldTriggerAddressBookUpdateOnInvalidNodeAccountId() throws PrecheckStatu
569569
var tx = new DummyTransaction() {
570570
@Override
571571
Status mapResponseStatus(com.hedera.hashgraph.sdk.proto.TransactionResponse response) {
572-
return Status.INVALID_NODE_ACCOUNT_ID;
572+
return Status.INVALID_NODE_ACCOUNT;
573573
}
574574
};
575575
var nodeAccountIds = Arrays.asList(new AccountId(0, 0, 3));
576576
tx.setNodeAccountIds(nodeAccountIds);
577577

578578
var txResp = com.hedera.hashgraph.sdk.proto.TransactionResponse.newBuilder()
579-
.setNodeTransactionPrecheckCode(ResponseCodeEnum.INVALID_NODE_ACCOUNT_ID)
579+
.setNodeTransactionPrecheckCode(ResponseCodeEnum.INVALID_NODE_ACCOUNT)
580580
.build();
581581

582582
tx.blockingUnaryCall = (grpcRequest) -> txResp;
583583

584-
// This should trigger address book update due to INVALID_NODE_ACCOUNT_ID
584+
// This should trigger address book update due to INVALID_NODE_ACCOUNT
585585
assertThatExceptionOfType(MaxAttemptsExceededException.class).isThrownBy(() -> tx.execute(client));
586586

587587
// Verify that increaseBackoff was called (node marking)

sdk/src/testIntegration/java/com/hedera/hashgraph/sdk/test/integration/NodeUpdateAccountIdIntegrationTest.java

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,22 @@
11
// SPDX-License-Identifier: Apache-2.0
22
package com.hedera.hashgraph.sdk.test.integration;
33

4-
import com.hedera.hashgraph.sdk.AccountId;
4+
import static org.assertj.core.api.Assertions.assertThat;
5+
import static org.assertj.core.api.Assertions.assertThatCode;
6+
57
import com.hedera.hashgraph.sdk.AccountCreateTransaction;
8+
import com.hedera.hashgraph.sdk.AccountId;
69
import com.hedera.hashgraph.sdk.Client;
710
import com.hedera.hashgraph.sdk.Hbar;
811
import com.hedera.hashgraph.sdk.NodeUpdateTransaction;
912
import com.hedera.hashgraph.sdk.PrivateKey;
1013
import com.hedera.hashgraph.sdk.Status;
1114
import java.util.HashMap;
1215
import java.util.List;
13-
1416
import org.junit.jupiter.api.Disabled;
1517
import org.junit.jupiter.api.DisplayName;
1618
import org.junit.jupiter.api.Test;
1719

18-
import static org.assertj.core.api.Assertions.assertThat;
19-
import static org.assertj.core.api.Assertions.assertThatCode;
20-
2120
/**
2221
* Integration test for NodeUpdateTransaction functionality, specifically testing
2322
* the Dynamic Address Book (DAB) enhancement for updating node account IDs.
@@ -69,19 +68,18 @@ void shouldSucceedWhenUpdatingNodeAccountIdWithProperSignatures() throws Excepti
6968
.setTransactionMemo("Update node account ID for DAB testing");
7069

7170
// Sign with both the node admin key and the new account key
72-
nodeUpdateTransaction.freezeWith(client)
73-
.sign(nodeAdminKey)
74-
.sign(newAccountKey);
71+
nodeUpdateTransaction.freezeWith(client).sign(nodeAdminKey).sign(newAccountKey);
7572

7673
// Then: The transaction should succeed
7774
assertThatCode(() -> {
78-
var response = nodeUpdateTransaction.execute(client);
79-
assertThat(response).isNotNull();
80-
81-
// Verify the transaction was successful by checking the receipt
82-
var receipt = response.getReceipt(client);
83-
assertThat(receipt.status).isEqualTo(Status.SUCCESS);
84-
}).doesNotThrowAnyException();
75+
var response = nodeUpdateTransaction.execute(client);
76+
assertThat(response).isNotNull();
77+
78+
// Verify the transaction was successful by checking the receipt
79+
var receipt = response.getReceipt(client);
80+
assertThat(receipt.status).isEqualTo(Status.SUCCESS);
81+
})
82+
.doesNotThrowAnyException();
8583
}
8684
}
8785

@@ -91,10 +89,10 @@ void testNodeUpdateTransactionCanChangeNodeAccountUpdateAddressbookAndRetry() th
9189
// Set the network
9290
var network = new HashMap<String, AccountId>();
9391
network.put("localhost:50211", new AccountId(0, 0, 3));
94-
network.put("localhost:50212", new AccountId(0, 0, 4));
92+
network.put("localhost:51211", new AccountId(0, 0, 4));
9593

96-
try (var client = Client.forNetwork(network)
97-
.setMirrorNetwork(List.of("localhost:5600"))) {
94+
try (var client =
95+
Client.forNetwork(network).setTransportSecurity(false).setMirrorNetwork(List.of("localhost:5600"))) {
9896

9997
// Set the operator to be account 0.0.2
10098
var originalOperatorKey = PrivateKey.fromString(
@@ -127,9 +125,9 @@ void testNodeUpdateTransactionCanChangeNodeAccountUpdateAddressbookAndRetry() th
127125
var newAccountKey = PrivateKey.generateED25519();
128126

129127
// Submit to node 3 and node 4
130-
// Node 3 will fail with INVALID_NODE_ACCOUNT_ID (because it now uses newNodeAccountID)
128+
// Node 3 will fail with INVALID_NODE_ACCOUNT (because it now uses newNodeAccountID)
131129
// The SDK should automatically:
132-
// 1. Detect INVALID_NODE_ACCOUNT_ID error
130+
// 1. Detect INVALID_NODE_ACCOUNT error
133131
// 2. Advance to next node
134132
// 3. Update the address book asynchronously
135133
// 4. Mark node 3 as unhealthy

0 commit comments

Comments
 (0)