Skip to content

Commit 4c8f2ff

Browse files
authored
HIP-1299: Changing Node Account IDs (#1547)
* feat: initial impl Signed-off-by: Ivan Ivanov <[email protected]> * test: e2e Signed-off-by: Ivan Ivanov <[email protected]> * test: e2e Signed-off-by: Ivan Ivanov <[email protected]> * test: e2e Signed-off-by: Ivan Ivanov <[email protected]> * chore: linter Signed-off-by: Ivan Ivanov <[email protected]> * fix: unit Signed-off-by: Ivan Ivanov <[email protected]> * fix: test utils Signed-off-by: Ivan Ivanov <[email protected]> * fix: e2e Signed-off-by: Ivan Ivanov <[email protected]> * chore: revert solo action for e2e tests Signed-off-by: Ivan Ivanov <[email protected]> * chore: revert utilities changes Signed-off-by: Ivan Ivanov <[email protected]> * chore: fix typo Signed-off-by: Ivan Ivanov <[email protected]> * fix: healthy nodes list Signed-off-by: Ivan Ivanov <[email protected]> * chore: bump services Signed-off-by: Ivan Ivanov <[email protected]> * chore: refactor Signed-off-by: Ivan Ivanov <[email protected]> * fix: tests Signed-off-by: Ivan Ivanov <[email protected]> * bump mirror Signed-off-by: Ivan Ivanov <[email protected]> * bump action Signed-off-by: Ivan Ivanov <[email protected]> * get receipt Signed-off-by: Ivan Ivanov <[email protected]> * chore: bump solo Signed-off-by: Ivan Ivanov <[email protected]> * chore: tidy Signed-off-by: Ivan Ivanov <[email protected]> * chore: update deps Signed-off-by: Ivan Ivanov <[email protected]> * chore: dual mode Signed-off-by: Ivan Ivanov <[email protected]> * chore: bump crypto Signed-off-by: Ivan Ivanov <[email protected]> * chore: bump mirror Signed-off-by: Ivan Ivanov <[email protected]> --------- Signed-off-by: Ivan Ivanov <[email protected]>
1 parent b2419e2 commit 4c8f2ff

File tree

11 files changed

+479
-68
lines changed

11 files changed

+479
-68
lines changed

.github/workflows/build.yml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,18 +98,18 @@ jobs:
9898
- name: Prepare Hiero Solo
9999
if: success() && matrix.test-type == 'e2e'
100100
id: solo
101-
uses: hiero-ledger/hiero-solo-action@dd0048139ef1e40fd6067f01bf94eb42a67294f4 # v0.15.0
101+
uses: hiero-ledger/hiero-solo-action@fbca3e7a99ce9aa8a250563a81187abe115e0dad # v0.16.0
102102
with:
103103
installMirrorNode: true
104104
hieroVersion: v0.69.0-alpha.1
105+
mirrorNodeVersion: v0.142.0
105106

106107
- name: Set Operator Account
107108
if: success() && matrix.test-type == 'e2e'
108109
run: |
109110
echo "OPERATOR_KEY=${{ steps.solo.outputs.ed25519PrivateKey }}" >> $GITHUB_ENV
110111
echo "OPERATOR_ID=${{ steps.solo.outputs.ed25519AccountId }}" >> $GITHUB_ENV
111112
112-
113113
- name: Tests Unit
114114
if: success() && matrix.test-type == 'unit'
115115
run: go test ./sdk -tags="unit" -timeout 9999s -v -coverprofile=unit.out -covermode=atomic -race
@@ -170,10 +170,12 @@ jobs:
170170

171171
- name: Prepare Hiero Solo
172172
id: solo
173-
uses: hiero-ledger/hiero-solo-action@dd0048139ef1e40fd6067f01bf94eb42a67294f4 # v0.14.0
173+
uses: hiero-ledger/hiero-solo-action@fbca3e7a99ce9aa8a250563a81187abe115e0dad # v0.16.0
174174
with:
175175
installMirrorNode: true
176176
hieroVersion: v0.69.0-alpha.1
177+
mirrorNodeVersion: v0.142.0
178+
dualMode: true
177179

178180
- name: Set Operator Account
179181
run: |
@@ -230,10 +232,11 @@ jobs:
230232

231233
- name: Prepare Hiero Solo
232234
id: solo
233-
uses: hiero-ledger/hiero-solo-action@dd0048139ef1e40fd6067f01bf94eb42a67294f4 # v0.15.0
235+
uses: hiero-ledger/hiero-solo-action@fbca3e7a99ce9aa8a250563a81187abe115e0dad # v0.16.0
234236
with:
235237
installMirrorNode: true
236238
hieroVersion: v0.69.0-alpha.1
239+
mirrorNodeVersion: v0.142.0
237240

238241
- name: Set Operator Account
239242
run: |

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ require (
1111
github.com/rs/zerolog v1.34.0
1212
github.com/stretchr/testify v1.11.1
1313
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78
14-
golang.org/x/crypto v0.44.0
14+
golang.org/x/crypto v0.45.0
1515
golang.org/x/text v0.31.0
1616
google.golang.org/grpc v1.76.0
1717
google.golang.org/protobuf v1.36.10
@@ -26,7 +26,7 @@ require (
2626
github.com/modern-go/reflect2 v1.0.2 // indirect
2727
github.com/pmezard/go-difflib v1.0.0 // indirect
2828
github.com/rogpeppe/go-internal v1.10.0 // indirect
29-
golang.org/x/net v0.46.0 // indirect
29+
golang.org/x/net v0.47.0 // indirect
3030
golang.org/x/sys v0.38.0 // indirect
3131
google.golang.org/genproto/googleapis/rpc v0.0.0-20250804133106-a7a43d27e69b // indirect
3232
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,10 @@ go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFh
7575
go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps=
7676
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
7777
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
78-
golang.org/x/crypto v0.44.0 h1:A97SsFvM3AIwEEmTBiaxPPTYpDC47w720rdiiUvgoAU=
79-
golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc=
80-
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
81-
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
78+
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
79+
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
80+
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
81+
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
8282
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
8383
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
8484
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

sdk/address_book_query_e2e_test.go

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//go:build all || abnet
1+
//go:build all || DAB
22

33
package hiero
44

@@ -82,11 +82,34 @@ func TestIntegrationAddressBookQueryMainnet(t *testing.T) {
8282
}
8383

8484
func TestIntegrationAddressBookQueryLocal(t *testing.T) {
85-
env := NewIntegrationTestEnv(t)
86-
defer CloseIntegrationTestEnv(env, nil)
85+
t.Parallel()
8786

88-
_, err := NewAddressBookQuery().
89-
SetFileID(FileIDForAddressBook()).
90-
Execute(env.Client)
87+
// Set the network
88+
network := make(map[string]AccountID)
89+
network["localhost:50211"] = AccountID{Account: 3}
90+
client, err := ClientForNetworkV2(network)
91+
require.NoError(t, err)
92+
defer client.Close()
93+
mirror := []string{"localhost:5600"}
94+
client.SetMirrorNetwork(mirror)
95+
96+
// Set the operator to be account 0.0.2
97+
originalOperatorKey, err := PrivateKeyFromStringEd25519("302e020100300506032b65700422042091132178e72057a1d7528025956fe39b0b847f200ab59b2fdd367017f3087137")
98+
require.NoError(t, err)
99+
client.SetOperator(AccountID{Account: 2}, originalOperatorKey)
100+
101+
client._UpdateAddressBook()
102+
103+
newAccountKey, err := PrivateKeyGenerateEd25519()
91104
require.NoError(t, err)
105+
// submit to node 3
106+
resp, err := NewAccountCreateTransaction().
107+
SetKeyWithoutAlias(newAccountKey.PublicKey()).
108+
SetNodeAccountIDs([]AccountID{{Account: 3}}).
109+
Execute(client)
110+
require.NoError(t, err)
111+
112+
_, err = resp.SetValidateStatus(true).GetReceipt(client)
113+
require.NoError(t, err)
114+
92115
}

sdk/executable.go

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,11 @@ const maxAttempts = 10
2424
type _ExecutionState uint32
2525

2626
const (
27-
executionStateRetry _ExecutionState = 0
28-
executionStateFinished _ExecutionState = 1
29-
executionStateError _ExecutionState = 2
30-
executionStateExpired _ExecutionState = 3
27+
executionStateRetry _ExecutionState = 0
28+
executionStateFinished _ExecutionState = 1
29+
executionStateError _ExecutionState = 2
30+
executionStateExpired _ExecutionState = 3
31+
executionStateRetryWithAnotherNode _ExecutionState = 4
3132
)
3233

3334
type Executable interface {
@@ -213,7 +214,6 @@ func _Execute(client *Client, e Executable) (interface{}, error) {
213214
} else {
214215
requestTimeout = client.GetRequestTimeout()
215216
}
216-
217217
startTime := time.Now()
218218
for attempt = int64(0); attempt < int64(maxAttempts); attempt++ {
219219
if time.Since(startTime) >= requestTimeout {
@@ -296,9 +296,9 @@ func _Execute(client *Client, e Executable) (interface{}, error) {
296296
}
297297

298298
if err != nil {
299+
e.advanceRequest()
299300
errPersistent = err
300301
if _ExecutableDefaultRetryHandler(e.getLogID(e), err, txLogger) {
301-
e.advanceRequest()
302302
client.network._IncreaseBackoff(node)
303303
continue
304304
}
@@ -355,6 +355,15 @@ func _Execute(client *Client, e Executable) (interface{}, error) {
355355
case executionStateFinished:
356356
txLogger.Trace("finished", "Response Proto", hex.EncodeToString(marshaledResponse))
357357
return e.mapResponse(resp, node.accountID, protoRequest)
358+
case executionStateRetryWithAnotherNode:
359+
errPersistent = statusError
360+
e.advanceRequest()
361+
txLogger.Trace("received `INVALID_NODE_ACCOUNT`; updating addressbook and marking node as unhealthy", "requestId", e.getLogID(e), "nodeAccountId", node.accountID)
362+
defer client._UpdateAddressBook()
363+
// mark this node as unhealthy
364+
client.network._IncreaseBackoff(node)
365+
// continue with other nodes
366+
continue
358367
}
359368
}
360369

sdk/managed_network.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,10 +131,10 @@ func (mn *_ManagedNetwork) _ReadmitNodes() {
131131
func (mn *_ManagedNetwork) _GetNumberOfNodesForTransaction() int { // nolint
132132
mn._ReadmitNodes()
133133
if mn.maxNodesPerTransaction != nil {
134-
return int(math.Min(float64(*mn.maxNodesPerTransaction), float64(len(mn.network))))
134+
return int(math.Min(float64(*mn.maxNodesPerTransaction), float64(len(mn.healthyNodes))))
135135
}
136136

137-
return (len(mn.network) + 3 - 1) / 3
137+
return len(mn.healthyNodes)
138138
}
139139

140140
func (mn *_ManagedNetwork) _SetMaxNodesPerTransaction(max int) {

sdk/managed_network_unit_test.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -495,8 +495,8 @@ func TestUnitGetNumberOfNodesForTransaction_Default(t *testing.T) {
495495

496496
numNodes := mn._GetNumberOfNodesForTransaction()
497497

498-
// Default behavior: (len(this.network) + 3 - 1) / 3
499-
expectedNumNodes := (len(mockNodes) + 3 - 1) / 3
498+
// Default behavior: len(this.network)
499+
expectedNumNodes := len(mockNodes)
500500
require.Equal(t, expectedNumNodes, numNodes)
501501
}
502502

@@ -544,8 +544,7 @@ func TestUnitGetNumberOfNodesForTransaction_MaxNodesNotSet(t *testing.T) {
544544
require.NoError(t, err)
545545

546546
numNodes := mn._GetNumberOfNodesForTransaction()
547-
// 1/3 of the network size
548-
require.Equal(t, 1, numNodes)
547+
require.Equal(t, 3, numNodes)
549548
}
550549

551550
func TestUnitGetNode(t *testing.T) {

0 commit comments

Comments
 (0)