Skip to content

Commit 41d08f5

Browse files
jl2012sipa
authored andcommitted
Implement Taproot signature hashing (BIP 341)
Includes changes to PrecomputedTransactionData by Pieter Wuille.
1 parent 14d2178 commit 41d08f5

File tree

4 files changed

+125
-9
lines changed

4 files changed

+125
-9
lines changed

src/hash.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,10 @@ CHashWriter TaggedHash(const std::string& tag)
8787
writer << taghash << taghash;
8888
return writer;
8989
}
90+
91+
uint256 SHA256Uint256(const uint256& hash)
92+
{
93+
uint256 result;
94+
CSHA256().Write(hash.begin(), hash.size()).Finalize(result.begin());
95+
return result;
96+
}

src/hash.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,9 @@ uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL
214214
return ss.GetHash();
215215
}
216216

217+
/** Single-SHA256 a 32-byte input (represented as uint256). */
218+
uint256 SHA256Uint256(const uint256& input);
219+
217220
unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char>& vDataToHash);
218221

219222
void BIP32Hash(const ChainCode &chainCode, unsigned int nChild, unsigned char header, const unsigned char data[32], unsigned char output[64]);

src/script/interpreter.cpp

Lines changed: 105 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1265,7 +1265,7 @@ uint256 GetPrevoutHash(const T& txTo)
12651265
for (const auto& txin : txTo.vin) {
12661266
ss << txin.prevout;
12671267
}
1268-
return ss.GetHash();
1268+
return ss.GetSHA256();
12691269
}
12701270

12711271
template <class T>
@@ -1275,7 +1275,7 @@ uint256 GetSequenceHash(const T& txTo)
12751275
for (const auto& txin : txTo.vin) {
12761276
ss << txin.nSequence;
12771277
}
1278-
return ss.GetHash();
1278+
return ss.GetSHA256();
12791279
}
12801280

12811281
template <class T>
@@ -1285,7 +1285,25 @@ uint256 GetOutputsHash(const T& txTo)
12851285
for (const auto& txout : txTo.vout) {
12861286
ss << txout;
12871287
}
1288-
return ss.GetHash();
1288+
return ss.GetSHA256();
1289+
}
1290+
1291+
uint256 GetSpentAmountsHash(const std::vector<CTxOut>& outputs_spent)
1292+
{
1293+
CHashWriter ss(SER_GETHASH, 0);
1294+
for (const auto& txout : outputs_spent) {
1295+
ss << txout.nValue;
1296+
}
1297+
return ss.GetSHA256();
1298+
}
1299+
1300+
uint256 GetSpentScriptsHash(const std::vector<CTxOut>& outputs_spent)
1301+
{
1302+
CHashWriter ss(SER_GETHASH, 0);
1303+
for (const auto& txout : outputs_spent) {
1304+
ss << txout.scriptPubKey;
1305+
}
1306+
return ss.GetSHA256();
12891307
}
12901308

12911309
} // namespace
@@ -1299,9 +1317,17 @@ void PrecomputedTransactionData::Init(const T& txTo, std::vector<CTxOut> spent_o
12991317

13001318
// Cache is calculated only for transactions with witness
13011319
if (txTo.HasWitness()) {
1302-
hashPrevouts = GetPrevoutHash(txTo);
1303-
hashSequence = GetSequenceHash(txTo);
1304-
hashOutputs = GetOutputsHash(txTo);
1320+
m_prevouts_hash = GetPrevoutHash(txTo);
1321+
hashPrevouts = SHA256Uint256(m_prevouts_hash);
1322+
m_sequences_hash = GetSequenceHash(txTo);
1323+
hashSequence = SHA256Uint256(m_sequences_hash);
1324+
m_outputs_hash = GetOutputsHash(txTo);
1325+
hashOutputs = SHA256Uint256(m_outputs_hash);
1326+
if (!m_spent_outputs.empty()) {
1327+
m_spent_amounts_hash = GetSpentAmountsHash(m_spent_outputs);
1328+
m_spent_scripts_hash = GetSpentScriptsHash(m_spent_outputs);
1329+
m_spent_outputs_ready = true;
1330+
}
13051331
}
13061332

13071333
m_ready = true;
@@ -1319,6 +1345,76 @@ template void PrecomputedTransactionData::Init(const CMutableTransaction& txTo,
13191345
template PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo);
13201346
template PrecomputedTransactionData::PrecomputedTransactionData(const CMutableTransaction& txTo);
13211347

1348+
static const CHashWriter HasherTapSighash = TaggedHash("TapSighash");
1349+
1350+
template<typename T>
1351+
bool SignatureHashSchnorr(uint256& hash_out, const T& tx_to, const uint32_t in_pos, const uint8_t hash_type, const SigVersion sigversion, const PrecomputedTransactionData* cache)
1352+
{
1353+
uint8_t ext_flag;
1354+
switch (sigversion) {
1355+
case SigVersion::TAPROOT:
1356+
ext_flag = 0;
1357+
break;
1358+
default:
1359+
assert(false);
1360+
}
1361+
assert(in_pos < tx_to.vin.size());
1362+
assert(cache != nullptr && cache->m_ready && cache->m_spent_outputs_ready);
1363+
1364+
CHashWriter ss = HasherTapSighash;
1365+
1366+
// Epoch
1367+
static constexpr uint8_t EPOCH = 0;
1368+
ss << EPOCH;
1369+
1370+
// Hash type
1371+
const uint8_t output_type = (hash_type == SIGHASH_DEFAULT) ? SIGHASH_ALL : (hash_type & SIGHASH_OUTPUT_MASK); // Default (no sighash byte) is equivalent to SIGHASH_ALL
1372+
const uint8_t input_type = hash_type & SIGHASH_INPUT_MASK;
1373+
if (output_type != SIGHASH_ALL && output_type != SIGHASH_SINGLE && output_type != SIGHASH_NONE) return false;
1374+
if (input_type != SIGHASH_ANYONECANPAY && input_type != 0) return false;
1375+
ss << hash_type;
1376+
1377+
// Transaction level data
1378+
ss << tx_to.nVersion;
1379+
ss << tx_to.nLockTime;
1380+
if (input_type != SIGHASH_ANYONECANPAY) {
1381+
ss << cache->m_prevouts_hash;
1382+
ss << cache->m_spent_amounts_hash;
1383+
ss << cache->m_spent_scripts_hash;
1384+
ss << cache->m_sequences_hash;
1385+
}
1386+
if (output_type == SIGHASH_ALL) {
1387+
ss << cache->m_outputs_hash;
1388+
}
1389+
1390+
// Data about the input/prevout being spent
1391+
const auto* witstack = &tx_to.vin[in_pos].scriptWitness.stack;
1392+
bool have_annex = witstack->size() > 1 && witstack->back().size() > 0 && witstack->back()[0] == 0xff;
1393+
const uint8_t spend_type = (ext_flag << 1) + (have_annex ? 1 : 0); // The low bit indicates whether an annex is present.
1394+
ss << spend_type;
1395+
if (input_type == SIGHASH_ANYONECANPAY) {
1396+
ss << tx_to.vin[in_pos].prevout;
1397+
ss << cache->m_spent_outputs[in_pos];
1398+
ss << tx_to.vin[in_pos].nSequence;
1399+
} else {
1400+
ss << in_pos;
1401+
}
1402+
if (have_annex) {
1403+
ss << (CHashWriter(SER_GETHASH, 0) << witstack->back()).GetSHA256();
1404+
}
1405+
1406+
// Data about the output(s)
1407+
if (output_type == SIGHASH_SINGLE) {
1408+
if (in_pos >= tx_to.vout.size()) return false;
1409+
CHashWriter sha_single_output(SER_GETHASH, 0);
1410+
sha_single_output << tx_to.vout[in_pos];
1411+
ss << sha_single_output.GetSHA256();
1412+
}
1413+
1414+
hash_out = ss.GetSHA256();
1415+
return true;
1416+
}
1417+
13221418
template <class T>
13231419
uint256 SignatureHash(const CScript& scriptCode, const T& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache)
13241420
{
@@ -1331,16 +1427,16 @@ uint256 SignatureHash(const CScript& scriptCode, const T& txTo, unsigned int nIn
13311427
const bool cacheready = cache && cache->m_ready;
13321428

13331429
if (!(nHashType & SIGHASH_ANYONECANPAY)) {
1334-
hashPrevouts = cacheready ? cache->hashPrevouts : GetPrevoutHash(txTo);
1430+
hashPrevouts = cacheready ? cache->hashPrevouts : SHA256Uint256(GetPrevoutHash(txTo));
13351431
}
13361432

13371433
if (!(nHashType & SIGHASH_ANYONECANPAY) && (nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) {
1338-
hashSequence = cacheready ? cache->hashSequence : GetSequenceHash(txTo);
1434+
hashSequence = cacheready ? cache->hashSequence : SHA256Uint256(GetSequenceHash(txTo));
13391435
}
13401436

13411437

13421438
if ((nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) {
1343-
hashOutputs = cacheready ? cache->hashOutputs : GetOutputsHash(txTo);
1439+
hashOutputs = cacheready ? cache->hashOutputs : SHA256Uint256(GetOutputsHash(txTo));
13441440
} else if ((nHashType & 0x1f) == SIGHASH_SINGLE && nIn < txTo.vout.size()) {
13451441
CHashWriter ss(SER_GETHASH, 0);
13461442
ss << txTo.vout[nIn];

src/script/interpreter.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ enum
2525
SIGHASH_NONE = 2,
2626
SIGHASH_SINGLE = 3,
2727
SIGHASH_ANYONECANPAY = 0x80,
28+
29+
SIGHASH_DEFAULT = 0, //!< Taproot only; implied when sighash byte is missing, and equivalent to SIGHASH_ALL
30+
SIGHASH_OUTPUT_MASK = 3,
31+
SIGHASH_INPUT_MASK = 0x80,
2832
};
2933

3034
/** Script verification flags.
@@ -121,6 +125,11 @@ bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, unsigned i
121125

122126
struct PrecomputedTransactionData
123127
{
128+
//! Single-SHA256 versions
129+
uint256 m_prevouts_hash, m_sequences_hash, m_outputs_hash, m_spent_amounts_hash, m_spent_scripts_hash;
130+
bool m_spent_outputs_ready = false;
131+
132+
//! Double-SHA256 versions
124133
uint256 hashPrevouts, hashSequence, hashOutputs;
125134
bool m_ready = false;
126135
std::vector<CTxOut> m_spent_outputs;
@@ -138,6 +147,7 @@ enum class SigVersion
138147
{
139148
BASE = 0,
140149
WITNESS_V0 = 1,
150+
TAPROOT = 2,
141151
};
142152

143153
/** Signature hash sizes */

0 commit comments

Comments
 (0)