From 29af078e7be57ab8dc34a9312ed618e468f4a387 Mon Sep 17 00:00:00 2001 From: Anirudha Bose Date: Sun, 3 May 2020 20:44:25 +0530 Subject: [PATCH] Fix nil pointer dereference when WitnessHash is called before HasWitness Issue: btcsuite/btcd#1543 Related PR: btcsuite/btcutil#156 --- block_test.go | 12 ++++++++---- tx.go | 2 +- tx_test.go | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/block_test.go b/block_test.go index e7486c4..bb6b748 100644 --- a/block_test.go +++ b/block_test.go @@ -145,10 +145,10 @@ func TestBlock(t *testing.T) { // Transaction offsets and length for the transaction in Block100000. wantTxLocs := []wire.TxLoc{ - {TxStart: 81, TxLen: 135}, - {TxStart: 216, TxLen: 259}, - {TxStart: 475, TxLen: 257}, - {TxStart: 732, TxLen: 225}, + {TxStart: 81, TxLen: 144}, + {TxStart: 225, TxLen: 259}, + {TxStart: 484, TxLen: 257}, + {TxStart: 741, TxLen: 225}, } // Ensure the transaction location information is accurate. @@ -333,6 +333,10 @@ var Block100000 = wire.MsgBlock{ 0x04, 0x4c, 0x86, 0x04, 0x1b, 0x02, 0x06, 0x02, }, Sequence: 0xffffffff, + Witness: [][]byte{ + {0x04, 0x31}, + {0x01, 0x43}, + }, }, }, TxOut: []*wire.TxOut{ diff --git a/tx.go b/tx.go index 13c05e4..5633fef 100644 --- a/tx.go +++ b/tx.go @@ -70,7 +70,7 @@ func (t *Tx) WitnessHash() *chainhash.Hash { // HasWitness on the underlying wire.MsgTx, however it caches the result so // subsequent calls are more efficient. func (t *Tx) HasWitness() bool { - if t.txHashWitness != nil { + if t.txHasWitness != nil { return *t.txHasWitness } diff --git a/tx_test.go b/tx_test.go index cf18f40..6105b30 100644 --- a/tx_test.go +++ b/tx_test.go @@ -95,3 +95,42 @@ func TestTxErrors(t *testing.T) { "got %v, want %v", err, io.EOF) } } + +// TestTxHasWitness tests the HasWitness() method. +func TestTxHasWitness(t *testing.T) { + msgTx := Block100000.Transactions[0] // contains witness data + tx := btcutil.NewTx(msgTx) + + tx.WitnessHash() // Populate the witness hash cache + tx.HasWitness() // Should not fail (see btcsuite/btcd#1543) + + if !tx.HasWitness() { + t.Errorf("HasWitness: got false, want true") + } + + for _, msgTxWithoutWitness := range Block100000.Transactions[1:] { + txWithoutWitness := btcutil.NewTx(msgTxWithoutWitness) + if txWithoutWitness.HasWitness() { + t.Errorf("HasWitness: got false, want true") + } + } +} + +// TestTxWitnessHash tests the WitnessHash() method. +func TestTxWitnessHash(t *testing.T) { + msgTx := Block100000.Transactions[0] // contains witness data + tx := btcutil.NewTx(msgTx) + + if tx.WitnessHash().IsEqual(tx.Hash()) { + t.Errorf("WitnessHash: witness hash and tx id must NOT be same - "+ + "got %v, want %v", tx.WitnessHash(), tx.Hash()) + } + + for _, msgTxWithoutWitness := range Block100000.Transactions[1:] { + txWithoutWitness := btcutil.NewTx(msgTxWithoutWitness) + if !txWithoutWitness.WitnessHash().IsEqual(txWithoutWitness.Hash()) { + t.Errorf("WitnessHash: witness hash and tx id must be same - "+ + "got %v, want %v", txWithoutWitness.WitnessHash(), txWithoutWitness.Hash()) + } + } +}