From 31f5da02e5799e690ef35088b481f613213bacb1 Mon Sep 17 00:00:00 2001 From: beerosagos Date: Mon, 29 Apr 2024 11:11:14 +0200 Subject: [PATCH] backend/transactions: add test for tx serialization Recent btcd updates changed the way hashes are serialized. We proposed a fix (see https://github.com/btcsuite/btcd/pull/2025) to restore backward compatibility. This commit adds a specific test case to ensure that the newer and the legacy serialization methods work. --- .../db/transactionsdb/transactionsdb_test.go | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/backend/coins/btc/db/transactionsdb/transactionsdb_test.go b/backend/coins/btc/db/transactionsdb/transactionsdb_test.go index f00aab579c..ab737b8f69 100644 --- a/backend/coins/btc/db/transactionsdb/transactionsdb_test.go +++ b/backend/coins/btc/db/transactionsdb/transactionsdb_test.go @@ -16,15 +16,19 @@ package transactionsdb import ( "encoding/hex" + "encoding/json" "path" "reflect" "testing" "testing/quick" "time" + "github.com/BitBoxSwiss/bitbox-wallet-app/backend/coins/btc/addresses" + addressesTest "github.com/BitBoxSwiss/bitbox-wallet-app/backend/coins/btc/addresses/test" "github.com/BitBoxSwiss/bitbox-wallet-app/backend/coins/btc/blockchain" "github.com/BitBoxSwiss/bitbox-wallet-app/backend/coins/btc/types" "github.com/BitBoxSwiss/bitbox-wallet-app/util/test" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" "github.com/stretchr/testify/require" @@ -83,6 +87,93 @@ func getRawValue(tx *Tx, bucketKey string, key []byte) []byte { return tx.tx.Bucket([]byte(bucketKey)).Get(key) } +// TestTxSerialization checks that Tx marshaling/unmarshaling work with both current and legacy +// chainhash.Hash marshaling methods. +// see https://github.com/btcsuite/btcd/pull/2025. +func TestTxSerialization(t *testing.T) { + db := getDB() + defer func() { + if err := db.Close(); err != nil { + panic(err) + } + }() + dbTx, err := db.Begin(true) + if err != nil { + panic(err) + } + defer dbTx.Rollback() + + // create a new Tx + _, addressChain := addressesTest.NewAddressChain( + func(address *addresses.AccountAddress) (bool, error) { + return false, nil + }, + ) + addresses, err := addressChain.EnsureAddresses() + require.NoError(t, err) + address := addresses[0] + amount := btcutil.Amount(123) + tx := &wire.MsgTx{ + Version: wire.TxVersion, + TxIn: []*wire.TxIn{ + wire.NewTxIn(&wire.OutPoint{Hash: chainhash.HashH(nil), Index: 0}, nil, nil), + }, + TxOut: []*wire.TxOut{wire.NewTxOut(int64(amount), address.PubkeyScript())}, + LockTime: 0, + } + txHash := tx.TxHash() + + dbTx.PutTx(txHash, tx, 999) + + retrievedTx, err := dbTx.TxInfo(txHash) + require.NoError(t, err) + require.Equal(t, txHash, retrievedTx.Tx.TxHash()) + + // Override tx bytes marshaling the prevout hash with legacy method. + transactionsBucket, err := dbTx.(*Tx).tx.CreateBucketIfNotExists([]byte(bucketTransactionsKey)) + require.NoError(t, err) + + hashBytes := [32]byte(tx.TxIn[0].PreviousOutPoint.Hash.CloneBytes()) + legacyMarshalledHash, err := json.Marshal(hashBytes) + require.NoError(t, err) + legacySerializedTx := `{ + "Tx": { + "Version": 1, + "TxIn": [ + { + "PreviousOutPoint": { + "Hash": ` + string(legacyMarshalledHash) + `, + "Index": 0 + }, + "SignatureScript": null, + "Witness": null, + "Sequence": 4294967295 + } + ], + "TxOut": [ + { + "Value": 123, + "PkScript": "dqkU+tJNI2oRHKW1g4q4XbLEvaq3w76IrA==" + } + ], + "LockTime": 0 + }, + "Height": 999, + "addresses": {}, + "Verified": null, + "ts": null, + "created": "2024-05-08T17:26:36.224472769+02:00" + }` + + err = transactionsBucket.Put(txHash[:], []byte(legacySerializedTx)) + require.NoError(t, err) + + retrievedTx2, err := dbTx.TxInfo(txHash) + require.NoError(t, err) + require.NotNil(t, retrievedTx2) + require.Equal(t, retrievedTx.Tx.TxHash(), retrievedTx2.Tx.TxHash()) +} + // TestTxQuick tests the tx related db functions on random data. func TestTxQuick(t *testing.T) { testTx(func(tx *Tx) {