0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-03 09:56:38 -05:00

Merge #19601: Refactoring CHashWriter & Get{Prevouts,Sequence,Outputs}Hash to SHA256 (Alternative to #18071)

9ab4cafabd Refactor Get{Prevout,Sequence,Outputs}Hash to Get{Prevouts,Sequences,Outputs}SHA256. (Jeremy Rubin)
6510d0ff41 Add SHA256Uint256 helper functions (Jeremy Rubin)
b475d7d0fa Add single sha256 call to CHashWriter (Jeremy Rubin)

Pull request description:

  Opened as an alternative to #18071 to be more similar to #17977.

  I'm fine with either, deferring to others.

  cc jnewbery Sjors

ACKs for top commit:
  jnewbery:
    Code review ACK 9ab4cafabd
  jonatack:
    Tested ACK 9ab4caf
  fjahr:
    tested ACK 9ab4cafabd
  instagibbs:
    reACK 9ab4cafabd

Tree-SHA512: 93a7a47697f1657f027b18407bdcce16963f6b23d12372e7ac8fd4ee96769b3e2639369f9956fee669cc881b6338641cddfeeef1516c7104cb50ef4b880bb0a7
This commit is contained in:
fanquake 2020-08-25 18:02:11 +08:00
commit f8462a6d27
No known key found for this signature in database
GPG key ID: 2EEB9F5CC09526C1
3 changed files with 46 additions and 19 deletions

View file

@ -77,3 +77,10 @@ void BIP32Hash(const ChainCode &chainCode, unsigned int nChild, unsigned char he
num[3] = (nChild >> 0) & 0xFF; num[3] = (nChild >> 0) & 0xFF;
CHMAC_SHA512(chainCode.begin(), chainCode.size()).Write(&header, 1).Write(data, 32).Write(num, 4).Finalize(output); CHMAC_SHA512(chainCode.begin(), chainCode.size()).Write(&header, 1).Write(data, 32).Write(num, 4).Finalize(output);
} }
uint256 SHA256Uint256(const uint256& input)
{
uint256 result;
CSHA256().Write(input.begin(), 32).Finalize(result.begin());
return result;
}

View file

@ -6,6 +6,7 @@
#ifndef BITCOIN_HASH_H #ifndef BITCOIN_HASH_H
#define BITCOIN_HASH_H #define BITCOIN_HASH_H
#include <attributes.h>
#include <crypto/common.h> #include <crypto/common.h>
#include <crypto/ripemd160.h> #include <crypto/ripemd160.h>
#include <crypto/sha256.h> #include <crypto/sha256.h>
@ -98,7 +99,7 @@ inline uint160 Hash160(const T1& in1)
class CHashWriter class CHashWriter
{ {
private: private:
CHash256 ctx; CSHA256 ctx;
const int nType; const int nType;
const int nVersion; const int nVersion;
@ -110,13 +111,27 @@ public:
int GetVersion() const { return nVersion; } int GetVersion() const { return nVersion; }
void write(const char *pch, size_t size) { void write(const char *pch, size_t size) {
ctx.Write({(const unsigned char*)pch, size}); ctx.Write((const unsigned char*)pch, size);
} }
// invalidates the object /** Compute the double-SHA256 hash of all data written to this object.
*
* Invalidates this object.
*/
uint256 GetHash() { uint256 GetHash() {
uint256 result; uint256 result;
ctx.Finalize(result); ctx.Finalize(result.begin());
ctx.Reset().Write(result.begin(), CSHA256::OUTPUT_SIZE).Finalize(result.begin());
return result;
}
/** Compute the SHA256 hash of all data written to this object.
*
* Invalidates this object.
*/
uint256 GetSHA256() {
uint256 result;
ctx.Finalize(result.begin());
return result; return result;
} }
@ -124,9 +139,8 @@ public:
* Returns the first 64 bits from the resulting hash. * Returns the first 64 bits from the resulting hash.
*/ */
inline uint64_t GetCheapHash() { inline uint64_t GetCheapHash() {
unsigned char result[CHash256::OUTPUT_SIZE]; uint256 result = GetHash();
ctx.Finalize(result); return ReadLE64(result.begin());
return ReadLE64(result);
} }
template<typename T> template<typename T>
@ -181,6 +195,9 @@ uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL
return ss.GetHash(); return ss.GetHash();
} }
/** Single-SHA256 a 32-byte input (represented as uint256). */
NODISCARD uint256 SHA256Uint256(const uint256& input);
unsigned int MurmurHash3(unsigned int nHashSeed, Span<const unsigned char> vDataToHash); unsigned int MurmurHash3(unsigned int nHashSeed, Span<const unsigned char> vDataToHash);
void BIP32Hash(const ChainCode &chainCode, unsigned int nChild, unsigned char header, const unsigned char data[32], unsigned char output[64]); void BIP32Hash(const ChainCode &chainCode, unsigned int nChild, unsigned char header, const unsigned char data[32], unsigned char output[64]);

View file

@ -1258,34 +1258,37 @@ public:
} }
}; };
/** Compute the (single) SHA256 of the concatenation of all prevouts of a tx. */
template <class T> template <class T>
uint256 GetPrevoutHash(const T& txTo) uint256 GetPrevoutsSHA256(const T& txTo)
{ {
CHashWriter ss(SER_GETHASH, 0); CHashWriter ss(SER_GETHASH, 0);
for (const auto& txin : txTo.vin) { for (const auto& txin : txTo.vin) {
ss << txin.prevout; ss << txin.prevout;
} }
return ss.GetHash(); return ss.GetSHA256();
} }
/** Compute the (single) SHA256 of the concatenation of all nSequences of a tx. */
template <class T> template <class T>
uint256 GetSequenceHash(const T& txTo) uint256 GetSequencesSHA256(const T& txTo)
{ {
CHashWriter ss(SER_GETHASH, 0); CHashWriter ss(SER_GETHASH, 0);
for (const auto& txin : txTo.vin) { for (const auto& txin : txTo.vin) {
ss << txin.nSequence; ss << txin.nSequence;
} }
return ss.GetHash(); return ss.GetSHA256();
} }
/** Compute the (single) SHA256 of the concatenation of all txouts of a tx. */
template <class T> template <class T>
uint256 GetOutputsHash(const T& txTo) uint256 GetOutputsSHA256(const T& txTo)
{ {
CHashWriter ss(SER_GETHASH, 0); CHashWriter ss(SER_GETHASH, 0);
for (const auto& txout : txTo.vout) { for (const auto& txout : txTo.vout) {
ss << txout; ss << txout;
} }
return ss.GetHash(); return ss.GetSHA256();
} }
} // namespace } // namespace
@ -1297,9 +1300,9 @@ void PrecomputedTransactionData::Init(const T& txTo)
// Cache is calculated only for transactions with witness // Cache is calculated only for transactions with witness
if (txTo.HasWitness()) { if (txTo.HasWitness()) {
hashPrevouts = GetPrevoutHash(txTo); hashPrevouts = SHA256Uint256(GetPrevoutsSHA256(txTo));
hashSequence = GetSequenceHash(txTo); hashSequence = SHA256Uint256(GetSequencesSHA256(txTo));
hashOutputs = GetOutputsHash(txTo); hashOutputs = SHA256Uint256(GetOutputsSHA256(txTo));
} }
m_ready = true; m_ready = true;
@ -1329,16 +1332,16 @@ uint256 SignatureHash(const CScript& scriptCode, const T& txTo, unsigned int nIn
const bool cacheready = cache && cache->m_ready; const bool cacheready = cache && cache->m_ready;
if (!(nHashType & SIGHASH_ANYONECANPAY)) { if (!(nHashType & SIGHASH_ANYONECANPAY)) {
hashPrevouts = cacheready ? cache->hashPrevouts : GetPrevoutHash(txTo); hashPrevouts = cacheready ? cache->hashPrevouts : SHA256Uint256(GetPrevoutsSHA256(txTo));
} }
if (!(nHashType & SIGHASH_ANYONECANPAY) && (nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) { if (!(nHashType & SIGHASH_ANYONECANPAY) && (nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) {
hashSequence = cacheready ? cache->hashSequence : GetSequenceHash(txTo); hashSequence = cacheready ? cache->hashSequence : SHA256Uint256(GetSequencesSHA256(txTo));
} }
if ((nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) { if ((nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) {
hashOutputs = cacheready ? cache->hashOutputs : GetOutputsHash(txTo); hashOutputs = cacheready ? cache->hashOutputs : SHA256Uint256(GetOutputsSHA256(txTo));
} else if ((nHashType & 0x1f) == SIGHASH_SINGLE && nIn < txTo.vout.size()) { } else if ((nHashType & 0x1f) == SIGHASH_SINGLE && nIn < txTo.vout.size()) {
CHashWriter ss(SER_GETHASH, 0); CHashWriter ss(SER_GETHASH, 0);
ss << txTo.vout[nIn]; ss << txTo.vout[nIn];