@@ -12,6 +12,7 @@ import (
1212 "strconv"
1313
1414 "github.com/decred/dcrd/chaincfg/chainhash"
15+ "github.com/decred/dcrd/crypto/blake256"
1516)
1617
1718const (
@@ -391,24 +392,28 @@ func (msg *MsgTx) serialize(serType TxSerializeType) ([]byte, error) {
391392 return buf .Bytes (), nil
392393}
393394
394- // mustSerialize returns the serialization of the transaction for the provided
395- // serialization type without modifying the original transaction. It will panic
396- // if any errors occur.
397- func (msg * MsgTx ) mustSerialize (serType TxSerializeType ) []byte {
398- serialized , err := msg .serialize (serType )
395+ // mustHash returns the hash of the transaction for the provided
396+ // serialization type without modifying the original transaction.
397+ // It will panic if serialization fails.
398+ func (msg * MsgTx ) mustHash (hasher * blake256.Hasher256 , serType TxSerializeType ) chainhash.Hash {
399+ // Shallow copy so the serialization type can be changed without
400+ // modifying the original transaction.
401+ mtxCopy := * msg
402+ mtxCopy .SerType = serType
403+ err := mtxCopy .Serialize (hasher )
399404 if err != nil {
400405 panic (fmt .Sprintf ("MsgTx failed serializing for type %v" ,
401406 serType ))
402407 }
403- return serialized
408+ return hasher . Sum256 ()
404409}
405410
406- // TxHash generates the hash for the transaction prefix. Since it does not
407- // contain any witness data, it is not malleable and therefore is stable for
408- // use in unconfirmed transaction chains.
411+ // TxHash generates the BLAKE-256 hash for the transaction prefix. Since it
412+ // does not contain any witness data, it is not malleable and therefore is
413+ // stable for use in unconfirmed transaction chains.
409414func (msg * MsgTx ) TxHash () chainhash.Hash {
410415 // TxHash should always calculate a non-witnessed hash.
411- return chainhash . HashH ( msg . mustSerialize ( TxSerializeNoWitness ) )
416+ return msg . mustHash ( blake256 . NewHasher256 (), TxSerializeNoWitness )
412417}
413418
414419// CachedTxHash is equivalent to calling TxHash, however it caches the result so
@@ -433,29 +438,29 @@ func (msg *MsgTx) RecacheTxHash() *chainhash.Hash {
433438 return msg .CachedHash
434439}
435440
436- // TxHashWitness generates the hash for the transaction witness.
441+ // TxHashWitness generates the BLAKE-256 hash for the transaction witness.
437442func (msg * MsgTx ) TxHashWitness () chainhash.Hash {
438443 // TxHashWitness should always calculate a witnessed hash.
439- return chainhash . HashH ( msg . mustSerialize ( TxSerializeOnlyWitness ) )
444+ return msg . mustHash ( blake256 . NewHasher256 (), TxSerializeOnlyWitness )
440445}
441446
442- // TxHashFull generates the hash for the transaction prefix || witness. It first
443- // obtains the hashes for both the transaction prefix and witness, then
444- // concatenates them and hashes the result .
447+ // TxHashFull generates the hash for the transaction prefix || witness. This
448+ // is the BLAKE-256 hash of the concatenation of the individual prefix and
449+ // witness hashes ( and not the hash of the full serialization) .
445450func (msg * MsgTx ) TxHashFull () chainhash.Hash {
446- // Note that the inputs to the hashes, the serialized prefix and
447- // witness, have different serialized versions because the serialized
448- // encoding of the version includes the real transaction version in the
449- // lower 16 bits and the transaction serialization type in the upper 16
450- // bits. The real transaction version (lower 16 bits) will be the same
451- // in both serializations.
452- concat := make ([] byte , chainhash . HashSize * 2 )
453- prefixHash := msg .TxHash ( )
454- witnessHash := msg . TxHashWitness ()
455- copy ( concat [ 0 :], prefixHash [:])
456- copy ( concat [ chainhash . HashSize :], witnessHash [:])
457-
458- return chainhash . HashH ( concat )
451+ // Even for a transaction that has neither prefix nor witness ( and
452+ // would otherwise hash to the same result), the prefix and witness
453+ // hashes will still differ due to the serialization type being
454+ // encoded into the upper 16 bits of the transaction version.
455+ hasher := blake256 . NewHasher256 ()
456+ prefixHash := msg . mustHash ( hasher , TxSerializeNoWitness )
457+ hasher . Reset ( )
458+ witnessHash := msg .mustHash ( hasher , TxSerializeOnlyWitness )
459+ hasher . Reset ()
460+
461+ hasher . WriteBytes ( prefixHash [:])
462+ hasher . WriteBytes ( witnessHash [:])
463+ return hasher . Sum256 ( )
459464}
460465
461466// Copy creates a deep copy of a transaction so that the original does not get
0 commit comments