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  }