github.com/hashgraph/hedera-sdk-go/v2@v2.48.0/file_append_transaction_unit_test.go (about) 1 //go:build all || unit 2 // +build all unit 3 4 package hedera 5 6 /*- 7 * 8 * Hedera Go SDK 9 * 10 * Copyright (C) 2020 - 2024 Hedera Hashgraph, LLC 11 * 12 * Licensed under the Apache License, Version 2.0 (the "License"); 13 * you may not use this file except in compliance with the License. 14 * You may obtain a copy of the License at 15 * 16 * http://www.apache.org/licenses/LICENSE-2.0 17 * 18 * Unless required by applicable law or agreed to in writing, software 19 * distributed under the License is distributed on an "AS IS" BASIS, 20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 * See the License for the specific language governing permissions and 22 * limitations under the License. 23 * 24 */ 25 26 import ( 27 "bytes" 28 "testing" 29 "time" 30 31 "github.com/hashgraph/hedera-protobufs-go/services" 32 protobuf "google.golang.org/protobuf/proto" 33 34 "github.com/stretchr/testify/assert" 35 36 "github.com/stretchr/testify/require" 37 ) 38 39 func TestUnitFileAppendTransactionValidate(t *testing.T) { 40 t.Parallel() 41 42 client, err := _NewMockClient() 43 client.SetLedgerID(*NewLedgerIDTestnet()) 44 require.NoError(t, err) 45 client.SetAutoValidateChecksums(true) 46 fileID, err := FileIDFromString("0.0.123-esxsf") 47 require.NoError(t, err) 48 49 fileAppend := NewFileAppendTransaction(). 50 SetFileID(fileID) 51 52 err = fileAppend.validateNetworkOnIDs(client) 53 require.NoError(t, err) 54 } 55 56 func TestUnitFileAppendTransactionValidateWrong(t *testing.T) { 57 t.Parallel() 58 59 client, err := _NewMockClient() 60 client.SetLedgerID(*NewLedgerIDTestnet()) 61 require.NoError(t, err) 62 client.SetAutoValidateChecksums(true) 63 fileID, err := FileIDFromString("0.0.123-rmkykd") 64 require.NoError(t, err) 65 66 fileAppend := NewFileAppendTransaction(). 67 SetFileID(fileID) 68 69 err = fileAppend.validateNetworkOnIDs(client) 70 assert.Error(t, err) 71 if err != nil { 72 assert.Equal(t, "network mismatch or wrong checksum given, given checksum: rmkykd, correct checksum esxsf, network: testnet", err.Error()) 73 } 74 } 75 76 func TestUnitFileAppendTransactionMock(t *testing.T) { 77 t.Parallel() 78 79 fil := []byte(" world!") 80 call := func(request *services.Transaction) *services.TransactionResponse { 81 require.NotEmpty(t, request.SignedTransactionBytes) 82 signedTransaction := services.SignedTransaction{} 83 _ = protobuf.Unmarshal(request.SignedTransactionBytes, &signedTransaction) 84 85 require.NotEmpty(t, signedTransaction.BodyBytes) 86 transactionBody := services.TransactionBody{} 87 _ = protobuf.Unmarshal(signedTransaction.BodyBytes, &transactionBody) 88 89 require.NotNil(t, transactionBody.TransactionID) 90 transactionId := transactionBody.TransactionID.String() 91 require.NotEqual(t, "", transactionId) 92 93 sigMap := signedTransaction.GetSigMap() 94 require.NotNil(t, sigMap) 95 96 for _, sigPair := range sigMap.SigPair { 97 verified := false 98 99 switch k := sigPair.Signature.(type) { 100 case *services.SignaturePair_Ed25519: 101 pbTemp, _ := PublicKeyFromBytesEd25519(sigPair.PubKeyPrefix) 102 verified = pbTemp.Verify(signedTransaction.BodyBytes, k.Ed25519) 103 case *services.SignaturePair_ECDSASecp256K1: 104 pbTemp, _ := PublicKeyFromBytesECDSA(sigPair.PubKeyPrefix) 105 verified = pbTemp.Verify(signedTransaction.BodyBytes, k.ECDSASecp256K1) 106 } 107 require.True(t, verified) 108 } 109 110 if bod, ok := transactionBody.Data.(*services.TransactionBody_FileAppend); ok { 111 require.Equal(t, bod.FileAppend.FileID.FileNum, int64(3)) 112 require.Equal(t, bytes.Compare(bod.FileAppend.Contents, fil), 0) 113 } 114 115 return &services.TransactionResponse{ 116 NodeTransactionPrecheckCode: services.ResponseCodeEnum_OK, 117 } 118 } 119 responses := [][]interface{}{{ 120 call, &services.Response{ 121 Response: &services.Response_TransactionGetReceipt{ 122 TransactionGetReceipt: &services.TransactionGetReceiptResponse{ 123 Header: &services.ResponseHeader{ 124 Cost: 0, 125 ResponseType: services.ResponseType_ANSWER_ONLY, 126 }, 127 Receipt: &services.TransactionReceipt{ 128 Status: services.ResponseCodeEnum_SUCCESS, 129 AccountID: &services.AccountID{Account: &services.AccountID_AccountNum{ 130 AccountNum: 234, 131 }}, 132 }, 133 }, 134 }, 135 }, 136 }} 137 138 client, server := NewMockClientAndServer(responses) 139 defer server.Close() 140 141 _, err := NewFileAppendTransaction(). 142 SetFileID(FileID{File: 3}). 143 SetNodeAccountIDs([]AccountID{{Account: 3}}). 144 SetContents(fil). 145 Execute(client) 146 require.NoError(t, err) 147 } 148 149 func TestUnitFileAppendTransactionGet(t *testing.T) { 150 t.Parallel() 151 152 fileID := FileID{File: 7} 153 154 nodeAccountID := []AccountID{{Account: 10}, {Account: 11}, {Account: 12}} 155 transactionID := TransactionIDGenerate(AccountID{Account: 324}) 156 157 transaction, err := NewFileAppendTransaction(). 158 SetTransactionID(transactionID). 159 SetNodeAccountIDs(nodeAccountID). 160 SetFileID(fileID). 161 SetContents([]byte("Hello, World")). 162 SetMaxTransactionFee(NewHbar(10)). 163 SetTransactionMemo(""). 164 SetMaxChunkSize(12). 165 SetTransactionValidDuration(60 * time.Second). 166 SetRegenerateTransactionID(false). 167 Freeze() 168 require.NoError(t, err) 169 170 transaction.GetTransactionID() 171 transaction.GetNodeAccountIDs() 172 173 _, err = transaction.GetTransactionHash() 174 require.NoError(t, err) 175 176 transaction.GetFileID() 177 transaction.GetMaxTransactionFee() 178 transaction.GetTransactionMemo() 179 transaction.GetRegenerateTransactionID() 180 _, err = transaction.GetSignatures() 181 require.NoError(t, err) 182 transaction.GetRegenerateTransactionID() 183 transaction.GetMaxTransactionFee() 184 transaction.GetContents() 185 transaction.GetRegenerateTransactionID() 186 transaction.GetMaxChunkSize() 187 } 188 189 //func TestUnitFileAppendTransactionNothingSet(t *testing.T) { 190 // nodeAccountID := []AccountID{{Account: 10}, {Account: 11}, {Account: 12}} 191 // transactionID := TransactionIDGenerate(AccountID{Account: 324}) 192 // 193 // transaction, err := NewFileAppendTransaction(). 194 // SetTransactionID(transactionID). 195 // SetNodeAccountIDs(nodeAccountID). 196 // Freeze() 197 // require.NoError(t, err) 198 // 199 // transaction.GetTransactionID() 200 // transaction.GetNodeAccountIDs() 201 // 202 // _, err = transaction.GetTransactionHash() 203 // require.NoError(t, err) 204 // 205 // transaction.GetFileID() 206 // transaction.GetMaxTransactionFee() 207 // transaction.GetTransactionMemo() 208 // transaction.GetRegenerateTransactionID() 209 // _, err = transaction.GetSignatures() 210 // require.NoError(t, err) 211 // transaction.GetRegenerateTransactionID() 212 // transaction.GetMaxTransactionFee() 213 // transaction.GetContents() 214 // transaction.GetRegenerateTransactionID() 215 // transaction.GetMaxChunkSize() 216 //} 217 218 func TestUnitFileAppendTransactionBigContentsMock(t *testing.T) { 219 t.Parallel() 220 221 var previousTransactionID string 222 223 receipt := &services.Response{ 224 Response: &services.Response_TransactionGetReceipt{ 225 TransactionGetReceipt: &services.TransactionGetReceiptResponse{ 226 Header: &services.ResponseHeader{ 227 NodeTransactionPrecheckCode: services.ResponseCodeEnum_OK, 228 ResponseType: services.ResponseType_ANSWER_ONLY, 229 }, 230 Receipt: &services.TransactionReceipt{ 231 Status: services.ResponseCodeEnum_SUCCESS, 232 FileID: &services.FileID{FileNum: 3}, 233 }, 234 }, 235 }, 236 } 237 238 contents := "" 239 240 call := func(request *services.Transaction) *services.TransactionResponse { 241 require.NotEmpty(t, request.SignedTransactionBytes) 242 signedTransaction := services.SignedTransaction{} 243 _ = protobuf.Unmarshal(request.SignedTransactionBytes, &signedTransaction) 244 245 require.NotEmpty(t, signedTransaction.BodyBytes) 246 transactionBody := services.TransactionBody{} 247 _ = protobuf.Unmarshal(signedTransaction.BodyBytes, &transactionBody) 248 249 require.NotNil(t, transactionBody.TransactionID) 250 transactionId := transactionBody.TransactionID.String() 251 require.NotEqual(t, "", transactionId) 252 if previousTransactionID == "" { 253 previousTransactionID = transactionId 254 } else { 255 require.NotEqual(t, transactionId, previousTransactionID) 256 previousTransactionID = transactionId 257 } 258 259 contents += string(transactionBody.Data.(*services.TransactionBody_FileAppend).FileAppend.Contents) 260 261 sigMap := signedTransaction.GetSigMap() 262 require.NotNil(t, sigMap) 263 264 for _, sigPair := range sigMap.SigPair { 265 verified := false 266 267 switch k := sigPair.Signature.(type) { 268 case *services.SignaturePair_Ed25519: 269 pbTemp, _ := PublicKeyFromBytesEd25519(sigPair.PubKeyPrefix) 270 verified = pbTemp.Verify(signedTransaction.BodyBytes, k.Ed25519) 271 case *services.SignaturePair_ECDSASecp256K1: 272 pbTemp, _ := PublicKeyFromBytesECDSA(sigPair.PubKeyPrefix) 273 verified = pbTemp.Verify(signedTransaction.BodyBytes, k.ECDSASecp256K1) 274 } 275 require.True(t, verified) 276 } 277 278 return &services.TransactionResponse{ 279 NodeTransactionPrecheckCode: services.ResponseCodeEnum_OK, 280 } 281 } 282 responses := [][]interface{}{{ 283 call, receipt, call, receipt, call, receipt, call, receipt, call, receipt, call, receipt, call, 284 }} 285 286 client, server := NewMockClientAndServer(responses) 287 defer server.Close() 288 289 _, err := NewFileAppendTransaction(). 290 SetFileID(FileID{File: 3}). 291 SetNodeAccountIDs([]AccountID{{Account: 3}}). 292 SetContents([]byte(bigContents2)). 293 Execute(client) 294 require.NoError(t, err) 295 296 require.Equal(t, bigContents2, contents) 297 } 298 299 func TestUnitFileAppendTransactionCoverage(t *testing.T) { 300 t.Parallel() 301 302 checksum := "dmqui" 303 grpc := time.Second * 30 304 file := FileID{File: 3, checksum: &checksum} 305 nodeAccountID := []AccountID{{Account: 10}} 306 transactionID := TransactionIDGenerate(AccountID{Account: 324}) 307 308 newKey, err := PrivateKeyGenerateEd25519() 309 require.NoError(t, err) 310 311 client, err := _NewMockClient() 312 client.SetLedgerID(*NewLedgerIDTestnet()) 313 require.NoError(t, err) 314 client.SetAutoValidateChecksums(true) 315 316 transaction, err := NewFileAppendTransaction(). 317 SetTransactionID(transactionID). 318 SetNodeAccountIDs(nodeAccountID). 319 SetFileID(file). 320 SetContents([]byte{1}). 321 SetMaxChunkSize(5). 322 SetGrpcDeadline(&grpc). 323 SetMaxTransactionFee(NewHbar(3)). 324 SetMaxRetry(3). 325 SetMaxBackoff(time.Second * 30). 326 SetMinBackoff(time.Second * 10). 327 SetTransactionMemo("no"). 328 SetTransactionValidDuration(time.Second * 30). 329 SetRegenerateTransactionID(false). 330 Freeze() 331 require.NoError(t, err) 332 333 transaction.validateNetworkOnIDs(client) 334 335 _, err = transaction.Schedule() 336 require.NoError(t, err) 337 transaction.GetTransactionID() 338 transaction.GetNodeAccountIDs() 339 transaction.GetMaxRetry() 340 transaction.GetMaxTransactionFee() 341 transaction.GetMaxBackoff() 342 transaction.GetMinBackoff() 343 transaction.GetContents() 344 transaction.GetMaxChunkSize() 345 transaction.GetRegenerateTransactionID() 346 byt, err := transaction.ToBytes() 347 require.NoError(t, err) 348 txFromBytes, err := TransactionFromBytes(byt) 349 require.NoError(t, err) 350 sig, err := newKey.SignTransaction(&transaction.Transaction) 351 require.NoError(t, err) 352 353 _, err = transaction.GetTransactionHash() 354 require.NoError(t, err) 355 transaction.GetMaxTransactionFee() 356 transaction.GetTransactionMemo() 357 transaction.GetRegenerateTransactionID() 358 _, err = transaction.GetSignatures() 359 require.NoError(t, err) 360 transaction.getName() 361 switch b := txFromBytes.(type) { 362 case FileAppendTransaction: 363 b.AddSignature(newKey.PublicKey(), sig) 364 } 365 } 366 367 func TestUnitFileAppendTransactionSerialization(t *testing.T) { 368 t.Parallel() 369 370 fileID := FileID{File: 7} 371 nodeAccountID := []AccountID{{Account: 10}} 372 transactionID := TransactionIDGenerate(AccountID{Account: 324}) 373 374 transaction, err := NewFileAppendTransaction(). 375 SetTransactionID(transactionID). 376 SetNodeAccountIDs(nodeAccountID). 377 SetFileID(fileID). 378 SetContents([]byte("Hello, World")). 379 Freeze() 380 require.NoError(t, err) 381 382 txBytes, err := transaction.ToBytes() 383 require.NoError(t, err) 384 385 txParsed, err := TransactionFromBytes(txBytes) 386 require.NoError(t, err) 387 388 result, ok := txParsed.(FileAppendTransaction) 389 require.True(t, ok) 390 391 require.Equal(t, transactionID.AccountID, result.GetTransactionID().AccountID) 392 require.Equal(t, fileID, result.GetFileID()) 393 require.Equal(t, transaction.GetContents(), result.GetContents()) 394 }