Skip to content

Commit d4c13a5

Browse files
authored
feat(TCK): NodeUpdate and NodeDelete methods (#1490)
* feat: node create endpoint and fix bugs Signed-off-by: Ivan Ivanov <ivanivanov.ii726@gmail.com> * test: add unit tests Signed-off-by: Ivan Ivanov <ivanivanov.ii726@gmail.com> * chore: revert freeze changes Signed-off-by: Ivan Ivanov <ivanivanov.ii726@gmail.com> * chore: refactor Signed-off-by: Ivan Ivanov <ivanivanov.ii726@gmail.com> * feat: node update and delete methods Signed-off-by: Ivan Ivanov <ivanivanov.ii726@gmail.com> * chore: fix tests Signed-off-by: Ivan Ivanov <ivanivanov.ii726@gmail.com> * chore: fix tests Signed-off-by: Ivan Ivanov <ivanivanov.ii726@gmail.com> * chore: clean up Signed-off-by: Ivan Ivanov <ivanivanov.ii726@gmail.com> --------- Signed-off-by: Ivan Ivanov <ivanivanov.ii726@gmail.com>
1 parent 5d6e1ec commit d4c13a5

10 files changed

Lines changed: 207 additions & 31 deletions

sdk/node_create_transaction.go

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ type NodeCreateTransaction struct {
3636
description string
3737
gossipEndpoints []Endpoint
3838
serviceEndpoints []Endpoint
39-
gossipCaCertificate *[]byte
39+
gossipCaCertificate []byte
4040
grpcCertificateHash []byte
4141
adminKey Key
4242
declineReward *bool
@@ -80,7 +80,7 @@ func _NodeCreateTransactionFromProtobuf(tx Transaction[*NodeCreateTransaction],
8080
description: pb.GetNodeCreate().GetDescription(),
8181
gossipEndpoints: gossipEndpoints,
8282
serviceEndpoints: serviceEndpoints,
83-
gossipCaCertificate: &gossipCaCertificate,
83+
gossipCaCertificate: gossipCaCertificate,
8484
grpcCertificateHash: pb.GetNodeCreate().GetGrpcCertificateHash(),
8585
adminKey: adminKey,
8686
declineReward: &declineReward,
@@ -160,17 +160,14 @@ func (tx *NodeCreateTransaction) AddServiceEndpoint(endpoint Endpoint) *NodeCrea
160160

161161
// GetGossipCaCertificate the certificate used to sign gossip events.
162162
func (tx *NodeCreateTransaction) GetGossipCaCertificate() []byte {
163-
if tx.gossipCaCertificate == nil {
164-
return []byte{}
165-
}
166-
return *tx.gossipCaCertificate
163+
return tx.gossipCaCertificate
167164
}
168165

169166
// SetGossipCaCertificate the certificate used to sign gossip events.
170167
// This value MUST be the DER encoding of the certificate presented.
171168
func (tx *NodeCreateTransaction) SetGossipCaCertificate(gossipCaCertificate []byte) *NodeCreateTransaction {
172169
tx._RequireNotFrozen()
173-
tx.gossipCaCertificate = &gossipCaCertificate
170+
tx.gossipCaCertificate = gossipCaCertificate
174171
return tx
175172
}
176173

@@ -287,7 +284,7 @@ func (tx NodeCreateTransaction) buildProtoBody() *services.NodeCreateTransaction
287284
}
288285

289286
if tx.gossipCaCertificate != nil {
290-
body.GossipCaCertificate = *tx.gossipCaCertificate
287+
body.GossipCaCertificate = tx.gossipCaCertificate
291288
}
292289

293290
if tx.grpcCertificateHash != nil {
@@ -336,7 +333,7 @@ func (tx NodeCreateTransaction) validateTransactionFields() error {
336333
}
337334
}
338335

339-
if tx.gossipCaCertificate != nil && len(*tx.gossipCaCertificate) == 0 {
336+
if tx.gossipCaCertificate != nil && len(tx.gossipCaCertificate) == 0 {
340337
return errGossipCaCertificateEmpty
341338
}
342339

sdk/node_delete_transaction.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,6 @@ func (tx NodeDeleteTransaction) buildProtoBody() *services.NodeDeleteTransaction
9898

9999
if tx.nodeID != nil {
100100
body.NodeId = *tx.nodeID
101-
} else {
102-
tx.freezeError = errNodeIdIsRequired
103101
}
104102
return body
105103
}
@@ -110,6 +108,13 @@ func (tx NodeDeleteTransaction) getMethod(channel *_Channel) _Method {
110108
}
111109
}
112110

111+
func (tx NodeDeleteTransaction) validateTransactionFields() error {
112+
if tx.nodeID == nil {
113+
return errNodeIdIsRequired
114+
}
115+
return nil
116+
}
117+
113118
func (tx NodeDeleteTransaction) constructScheduleProtobuf() (*services.SchedulableTransactionBody, error) {
114119
return tx.buildScheduled()
115120
}

sdk/node_delete_transaction_unit_test.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -254,13 +254,11 @@ func TestUnitNodeDeleteTransactionFailsWenNodeIDIsNotSet(t *testing.T) {
254254
nodeAccountID := []AccountID{{Account: 10}}
255255
transactionID := TransactionIDGenerate(AccountID{Account: 324})
256256

257-
transaction, err := NewNodeDeleteTransaction().
257+
_, err := NewNodeDeleteTransaction().
258258
SetTransactionID(transactionID).
259259
SetNodeAccountIDs(nodeAccountID).
260260
Freeze()
261261

262-
require.NoError(t, err)
263-
264-
require.Error(t, transaction.freezeError)
265-
assert.ErrorIs(t, errNodeIdIsRequired, transaction.freezeError)
262+
require.Error(t, err)
263+
assert.ErrorIs(t, errNodeIdIsRequired, err)
266264
}

sdk/node_update_transaction.go

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,8 +321,6 @@ func (tx NodeUpdateTransaction) buildProtoBody() *services.NodeUpdateTransaction
321321

322322
if tx.nodeID != nil {
323323
body.NodeId = *tx.nodeID
324-
} else {
325-
tx.freezeError = errNodeIdIsRequired
326324
}
327325

328326
if tx.accountID != nil {
@@ -366,6 +364,41 @@ func (tx NodeUpdateTransaction) getMethod(channel *_Channel) _Method {
366364
}
367365
}
368366

367+
func (tx NodeUpdateTransaction) validateTransactionFields() error {
368+
if len(tx.gossipEndpoints) > 10 {
369+
return errTooManyGossipEndpoints
370+
}
371+
for _, endpoint := range tx.gossipEndpoints {
372+
if err := endpoint.Validate(); err != nil {
373+
return err
374+
}
375+
}
376+
377+
if len(tx.serviceEndpoints) > 8 {
378+
return errTooManyServiceEndpoints
379+
}
380+
for _, endpoint := range tx.serviceEndpoints {
381+
if err := endpoint.Validate(); err != nil {
382+
return err
383+
}
384+
}
385+
386+
if tx.gossipCaCertificate != nil && len(tx.gossipCaCertificate) == 0 {
387+
return errGossipCaCertificateEmpty
388+
}
389+
390+
if tx.description != "" {
391+
if len(tx.description) > 100 {
392+
return errDescriptionTooLong
393+
}
394+
}
395+
396+
if tx.nodeID == nil {
397+
return errNodeIdIsRequired
398+
}
399+
return nil
400+
}
401+
369402
func (tx NodeUpdateTransaction) constructScheduleProtobuf() (*services.SchedulableTransactionBody, error) {
370403
return tx.buildScheduled()
371404
}

sdk/node_update_transaction_unit_test.go

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -431,19 +431,11 @@ func TestUnitNodeUpdateTransactionFailsWenNodeIDIsNotSet(t *testing.T) {
431431
nodeAccountID := []AccountID{{Account: 10}}
432432
transactionID := TransactionIDGenerate(AccountID{Account: 324})
433433

434-
transaction, err := NewNodeUpdateTransaction().
434+
_, err := NewNodeUpdateTransaction().
435435
SetTransactionID(transactionID).
436436
SetNodeAccountIDs(nodeAccountID).
437437
Freeze()
438-
require.NoError(t, err)
439-
440-
require.Error(t, transaction.freezeError)
441-
assert.ErrorIs(t, errNodeIdIsRequired, transaction.freezeError)
442-
443-
client, err := _NewMockClient()
444-
client.SetLedgerID(*NewLedgerIDTestnet())
445-
require.NoError(t, err)
446438

447-
_, err = transaction.Execute(client)
448439
require.Error(t, err)
440+
assert.ErrorIs(t, errNodeIdIsRequired, err)
449441
}

tck/cmd/server.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ func main() {
9393
"signSchedule": postHandler(HandleError, handler.New(scheduleService.SignSchedule)),
9494
"createNode": postHandler(HandleError, handler.New(nodeService.CreateNode)),
9595
"executeContract": postHandler(HandleError, handler.New(contractService.ExecuteContract)),
96+
"updateNode": postHandler(HandleError, handler.New(nodeService.UpdateNode)),
97+
"deleteNode": postHandler(HandleError, handler.New(nodeService.DeleteNode)),
9698
"generateKey": postHandler(HandleError, handler.New(methods.GenerateKey)),
9799
}
98100

tck/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ require (
66
github.com/creachadair/jrpc2 v1.3.2
77
github.com/hiero-ledger/hiero-sdk-go/v2 v2.66.0
88
github.com/joho/godotenv v1.5.1
9-
github.com/stretchr/testify v1.11.0
9+
github.com/stretchr/testify v1.11.1
1010
)
1111

1212
replace github.com/hiero-ledger/hiero-sdk-go/v2 => ../

tck/go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@ github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
6262
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
6363
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
6464
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
65-
github.com/stretchr/testify v1.11.0 h1:ib4sjIrwZKxE5u/Japgo/7SJV3PvgjGiRNAvTVGqQl8=
66-
github.com/stretchr/testify v1.11.0/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
65+
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
66+
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
6767
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
6868
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
6969
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=

tck/methods/node.go

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package methods
55
import (
66
"context"
77
"encoding/hex"
8+
"errors"
89
"strconv"
910

1011
"github.com/hiero-ledger/hiero-sdk-go/tck/param"
@@ -107,6 +108,136 @@ func (n *NodeService) CreateNode(_ context.Context, params param.CreateNodeParam
107108
return &response.NodeResponse{NodeId: nodeId, Status: receipt.Status.String()}, nil
108109
}
109110

111+
func (n *NodeService) UpdateNode(_ context.Context, params param.UpdateNodeParams) (*response.NodeResponse, error) {
112+
transaction := hiero.NewNodeUpdateTransaction().SetGrpcDeadline(&threeSecondsDuration)
113+
114+
if params.NodeId != nil {
115+
nodeId, err := strconv.ParseUint(*params.NodeId, 10, 64)
116+
if err != nil {
117+
return nil, err
118+
}
119+
transaction.SetNodeID(nodeId)
120+
}
121+
122+
if err := utils.SetAccountIDIfPresent(params.AccountId, transaction.SetAccountID); err != nil {
123+
return nil, err
124+
}
125+
126+
if params.Description != nil {
127+
transaction.SetDescription(*params.Description)
128+
}
129+
130+
if params.GossipEndpoints != nil {
131+
if len(*params.GossipEndpoints) == 0 {
132+
return nil, errors.New("gossip endpoints must not be empty")
133+
}
134+
for _, endpointParam := range *params.GossipEndpoints {
135+
endpoint, err := convertEndpointParam(endpointParam)
136+
if err != nil {
137+
return nil, err
138+
}
139+
transaction.AddGossipEndpoint(endpoint)
140+
}
141+
}
142+
143+
if params.ServiceEndpoints != nil {
144+
if len(*params.ServiceEndpoints) == 0 {
145+
return nil, errors.New("service endpoints must not be empty")
146+
}
147+
for _, endpointParam := range *params.ServiceEndpoints {
148+
endpoint, err := convertEndpointParam(endpointParam)
149+
if err != nil {
150+
return nil, err
151+
}
152+
transaction.AddServiceEndpoint(endpoint)
153+
}
154+
}
155+
156+
if params.GossipCaCertificate != nil {
157+
certBytes, err := hex.DecodeString(*params.GossipCaCertificate)
158+
if err != nil {
159+
return nil, err
160+
}
161+
transaction.SetGossipCaCertificate(certBytes)
162+
}
163+
164+
if params.GrpcCertificateHash != nil {
165+
hashBytes, err := hex.DecodeString(*params.GrpcCertificateHash)
166+
if err != nil {
167+
return nil, err
168+
}
169+
transaction.SetGrpcCertificateHash(hashBytes)
170+
}
171+
172+
if err := utils.SetKeyIfPresent(params.AdminKey, transaction.SetAdminKey); err != nil {
173+
return nil, err
174+
}
175+
176+
if params.DeclineReward != nil {
177+
transaction.SetDeclineReward(*params.DeclineReward)
178+
}
179+
180+
if params.GrpcWebProxyEndpoint != nil {
181+
endpoint, err := convertEndpointParam(*params.GrpcWebProxyEndpoint)
182+
if err != nil {
183+
return nil, err
184+
}
185+
transaction.SetGrpcWebProxyEndpoint(endpoint)
186+
}
187+
188+
if params.CommonTransactionParams != nil {
189+
err := params.CommonTransactionParams.FillOutTransaction(transaction, n.sdkService.Client)
190+
if err != nil {
191+
return nil, err
192+
}
193+
}
194+
195+
txResponse, err := transaction.Execute(n.sdkService.Client)
196+
if err != nil {
197+
return nil, err
198+
}
199+
200+
receipt, err := txResponse.SetValidateStatus(true).GetReceipt(n.sdkService.Client)
201+
if err != nil {
202+
return nil, err
203+
}
204+
205+
var nodeId = strconv.FormatUint(receipt.NodeID, 10)
206+
207+
return &response.NodeResponse{NodeId: nodeId, Status: receipt.Status.String()}, nil
208+
}
209+
210+
func (n *NodeService) DeleteNode(_ context.Context, params param.DeleteNodeParams) (*response.NodeResponse, error) {
211+
transaction := hiero.NewNodeDeleteTransaction().SetGrpcDeadline(&threeSecondsDuration)
212+
213+
if params.NodeId != nil {
214+
nodeId, err := strconv.ParseUint(*params.NodeId, 10, 64)
215+
if err != nil {
216+
return nil, err
217+
}
218+
transaction.SetNodeID(nodeId)
219+
}
220+
221+
if params.CommonTransactionParams != nil {
222+
err := params.CommonTransactionParams.FillOutTransaction(transaction, n.sdkService.Client)
223+
if err != nil {
224+
return nil, err
225+
}
226+
}
227+
228+
txResponse, err := transaction.Execute(n.sdkService.Client)
229+
if err != nil {
230+
return nil, err
231+
}
232+
233+
receipt, err := txResponse.SetValidateStatus(true).GetReceipt(n.sdkService.Client)
234+
if err != nil {
235+
return nil, err
236+
}
237+
238+
return &response.NodeResponse{Status: receipt.Status.String()}, nil
239+
}
240+
110241
func convertEndpointParam(endpointParam param.EndpointParams) (hiero.Endpoint, error) {
111242
endpoint := hiero.Endpoint{}
112243

tck/param/node.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,21 @@ type CreateNodeParams struct {
2020
GrpcWebProxyEndpoint *EndpointParams `json:"grpcWebProxyEndpoint,omitempty"`
2121
CommonTransactionParams *CommonTransactionParams `json:"commonTransactionParams,omitempty"`
2222
}
23+
type UpdateNodeParams struct {
24+
NodeId *string `json:"nodeId,omitempty"`
25+
AccountId *string `json:"accountId,omitempty"`
26+
Description *string `json:"description,omitempty"`
27+
GossipEndpoints *[]EndpointParams `json:"gossipEndpoints,omitempty"`
28+
ServiceEndpoints *[]EndpointParams `json:"serviceEndpoints,omitempty"`
29+
GossipCaCertificate *string `json:"gossipCaCertificate,omitempty"`
30+
GrpcCertificateHash *string `json:"grpcCertificateHash,omitempty"`
31+
AdminKey *string `json:"adminKey,omitempty"`
32+
DeclineReward *bool `json:"declineReward,omitempty"`
33+
GrpcWebProxyEndpoint *EndpointParams `json:"grpcWebProxyEndpoint,omitempty"`
34+
CommonTransactionParams *CommonTransactionParams `json:"commonTransactionParams,omitempty"`
35+
}
36+
37+
type DeleteNodeParams struct {
38+
NodeId *string `json:"nodeId,omitempty"`
39+
CommonTransactionParams *CommonTransactionParams `json:"commonTransactionParams,omitempty"`
40+
}

0 commit comments

Comments
 (0)