Skip to content

Commit 5de246c

Browse files
jl2012sipa
authored andcommitted
Implement Taproot signature hashing (BIP 341)
This implements the new sighashing scheme from BIP341, with all relevant whole-transaction values precomputed once and cached. Includes changes to PrecomputedTransactionData by Pieter Wuille.
1 parent 9eb5908 commit 5de246c

File tree

4 files changed

+163
-12
lines changed

4 files changed

+163
-12
lines changed

src/script/interpreter.cpp

Lines changed: 133 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1291,23 +1291,79 @@ uint256 GetOutputsSHA256(const T& txTo)
12911291
return ss.GetSHA256();
12921292
}
12931293

1294+
/** Compute the (single) SHA256 of the concatenation of all amounts spent by a tx. */
1295+
uint256 GetSpentAmountsSHA256(const std::vector<CTxOut>& outputs_spent)
1296+
{
1297+
CHashWriter ss(SER_GETHASH, 0);
1298+
for (const auto& txout : outputs_spent) {
1299+
ss << txout.nValue;
1300+
}
1301+
return ss.GetSHA256();
1302+
}
1303+
1304+
/** Compute the (single) SHA256 of the concatenation of all scriptPubKeys spent by a tx. */
1305+
uint256 GetSpentScriptsSHA256(const std::vector<CTxOut>& outputs_spent)
1306+
{
1307+
CHashWriter ss(SER_GETHASH, 0);
1308+
for (const auto& txout : outputs_spent) {
1309+
ss << txout.scriptPubKey;
1310+
}
1311+
return ss.GetSHA256();
1312+
}
1313+
1314+
12941315
} // namespace
12951316

12961317
template <class T>
12971318
void PrecomputedTransactionData::Init(const T& txTo, std::vector<CTxOut>&& spent_outputs)
12981319
{
1299-
assert(!m_ready);
1320+
assert(!m_spent_outputs_ready);
13001321

13011322
m_spent_outputs = std::move(spent_outputs);
1323+
if (!m_spent_outputs.empty()) {
1324+
assert(m_spent_outputs.size() == txTo.vin.size());
1325+
m_spent_outputs_ready = true;
1326+
}
13021327

1303-
// Cache is calculated only for transactions with witness
1304-
if (txTo.HasWitness()) {
1305-
hashPrevouts = SHA256Uint256(GetPrevoutsSHA256(txTo));
1306-
hashSequence = SHA256Uint256(GetSequencesSHA256(txTo));
1307-
hashOutputs = SHA256Uint256(GetOutputsSHA256(txTo));
1328+
// Determine which precomputation-impacting features this transaction uses.
1329+
bool uses_bip143_segwit = false;
1330+
bool uses_bip341_taproot = false;
1331+
for (size_t inpos = 0; inpos < txTo.vin.size(); ++inpos) {
1332+
if (!txTo.vin[inpos].scriptWitness.IsNull()) {
1333+
if (m_spent_outputs_ready && m_spent_outputs[inpos].scriptPubKey.size() == 2 + WITNESS_V1_TAPROOT_SIZE &&
1334+
m_spent_outputs[inpos].scriptPubKey[0] == OP_1) {
1335+
// Treat every witness-bearing spend with 34-byte scriptPubKey that starts with OP_1 as a Taproot
1336+
// spend. This only works if spent_outputs was provided as well, but if it wasn't, actual validation
1337+
// will fail anyway. Note that this branch may trigger for scriptPubKeys that aren't actually segwit
1338+
// but in that case validation will fail as SCRIPT_ERR_WITNESS_UNEXPECTED anyway.
1339+
uses_bip341_taproot = true;
1340+
} else {
1341+
// Treat every spend that's not known to native witness v1 as a Witness v0 spend. This branch may
1342+
// also be taken for unknown witness versions, but it is harmless, and being precise would require
1343+
// P2SH evaluation to find the redeemScript.
1344+
uses_bip143_segwit = true;
1345+
}
1346+
}
1347+
if (uses_bip341_taproot && uses_bip143_segwit) break; // No need to scan further if we already need all.
13081348
}
13091349

1310-
m_ready = true;
1350+
if (uses_bip143_segwit || uses_bip341_taproot) {
1351+
// Computations shared between both sighash schemes.
1352+
m_prevouts_single_hash = GetPrevoutsSHA256(txTo);
1353+
m_sequences_single_hash = GetSequencesSHA256(txTo);
1354+
m_outputs_single_hash = GetOutputsSHA256(txTo);
1355+
}
1356+
if (uses_bip143_segwit) {
1357+
hashPrevouts = SHA256Uint256(m_prevouts_single_hash);
1358+
hashSequence = SHA256Uint256(m_sequences_single_hash);
1359+
hashOutputs = SHA256Uint256(m_outputs_single_hash);
1360+
m_bip143_segwit_ready = true;
1361+
}
1362+
if (uses_bip341_taproot) {
1363+
m_spent_amounts_single_hash = GetSpentAmountsSHA256(m_spent_outputs);
1364+
m_spent_scripts_single_hash = GetSpentScriptsSHA256(m_spent_outputs);
1365+
m_bip341_taproot_ready = true;
1366+
}
13111367
}
13121368

13131369
template <class T>
@@ -1322,6 +1378,75 @@ template void PrecomputedTransactionData::Init(const CMutableTransaction& txTo,
13221378
template PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo);
13231379
template PrecomputedTransactionData::PrecomputedTransactionData(const CMutableTransaction& txTo);
13241380

1381+
static const CHashWriter HASHER_TAPSIGHASH = TaggedHash("TapSighash");
1382+
1383+
template<typename T>
1384+
bool SignatureHashSchnorr(uint256& hash_out, const T& tx_to, uint32_t in_pos, uint8_t hash_type, SigVersion sigversion, const PrecomputedTransactionData& cache)
1385+
{
1386+
uint8_t ext_flag;
1387+
switch (sigversion) {
1388+
case SigVersion::TAPROOT:
1389+
ext_flag = 0;
1390+
break;
1391+
default:
1392+
assert(false);
1393+
}
1394+
assert(in_pos < tx_to.vin.size());
1395+
assert(cache.m_bip341_taproot_ready && cache.m_spent_outputs_ready);
1396+
1397+
CHashWriter ss = HASHER_TAPSIGHASH;
1398+
1399+
// Epoch
1400+
static constexpr uint8_t EPOCH = 0;
1401+
ss << EPOCH;
1402+
1403+
// Hash type
1404+
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
1405+
const uint8_t input_type = hash_type & SIGHASH_INPUT_MASK;
1406+
if (!(hash_type <= 0x03 || (hash_type >= 0x81 && hash_type <= 0x83))) return false;
1407+
ss << hash_type;
1408+
1409+
// Transaction level data
1410+
ss << tx_to.nVersion;
1411+
ss << tx_to.nLockTime;
1412+
if (input_type != SIGHASH_ANYONECANPAY) {
1413+
ss << cache.m_prevouts_single_hash;
1414+
ss << cache.m_spent_amounts_single_hash;
1415+
ss << cache.m_spent_scripts_single_hash;
1416+
ss << cache.m_sequences_single_hash;
1417+
}
1418+
if (output_type == SIGHASH_ALL) {
1419+
ss << cache.m_outputs_single_hash;
1420+
}
1421+
1422+
// Data about the input/prevout being spent
1423+
const auto& witstack = tx_to.vin[in_pos].scriptWitness.stack;
1424+
bool have_annex = witstack.size() > 1 && witstack.back().size() > 0 && witstack.back()[0] == ANNEX_TAG;
1425+
const uint8_t spend_type = (ext_flag << 1) + (have_annex ? 1 : 0); // The low bit indicates whether an annex is present.
1426+
ss << spend_type;
1427+
if (input_type == SIGHASH_ANYONECANPAY) {
1428+
ss << tx_to.vin[in_pos].prevout;
1429+
ss << cache.m_spent_outputs[in_pos];
1430+
ss << tx_to.vin[in_pos].nSequence;
1431+
} else {
1432+
ss << in_pos;
1433+
}
1434+
if (have_annex) {
1435+
ss << (CHashWriter(SER_GETHASH, 0) << witstack.back()).GetSHA256();
1436+
}
1437+
1438+
// Data about the output (if only one).
1439+
if (output_type == SIGHASH_SINGLE) {
1440+
if (in_pos >= tx_to.vout.size()) return false;
1441+
CHashWriter sha_single_output(SER_GETHASH, 0);
1442+
sha_single_output << tx_to.vout[in_pos];
1443+
ss << sha_single_output.GetSHA256();
1444+
}
1445+
1446+
hash_out = ss.GetSHA256();
1447+
return true;
1448+
}
1449+
13251450
template <class T>
13261451
uint256 SignatureHash(const CScript& scriptCode, const T& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache)
13271452
{
@@ -1331,7 +1456,7 @@ uint256 SignatureHash(const CScript& scriptCode, const T& txTo, unsigned int nIn
13311456
uint256 hashPrevouts;
13321457
uint256 hashSequence;
13331458
uint256 hashOutputs;
1334-
const bool cacheready = cache && cache->m_ready;
1459+
const bool cacheready = cache && cache->m_bip143_segwit_ready;
13351460

13361461
if (!(nHashType & SIGHASH_ANYONECANPAY)) {
13371462
hashPrevouts = cacheready ? cache->hashPrevouts : SHA256Uint256(GetPrevoutsSHA256(txTo));

src/script/interpreter.h

Lines changed: 24 additions & 3 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,9 +125,24 @@ bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, unsigned i
121125

122126
struct PrecomputedTransactionData
123127
{
128+
// BIP341 precomputed data.
129+
// These are single-SHA256, see https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#cite_note-15.
130+
uint256 m_prevouts_single_hash;
131+
uint256 m_sequences_single_hash;
132+
uint256 m_outputs_single_hash;
133+
uint256 m_spent_amounts_single_hash;
134+
uint256 m_spent_scripts_single_hash;
135+
//! Whether the 5 fields above are initialized.
136+
bool m_bip341_taproot_ready = false;
137+
138+
// BIP143 precomputed data (double-SHA256).
124139
uint256 hashPrevouts, hashSequence, hashOutputs;
125-
bool m_ready = false;
140+
//! Whether the 3 fields above are initialized.
141+
bool m_bip143_segwit_ready = false;
142+
126143
std::vector<CTxOut> m_spent_outputs;
144+
//! Whether m_spent_outputs is initialized.
145+
bool m_spent_outputs_ready = false;
127146

128147
PrecomputedTransactionData() = default;
129148

@@ -136,13 +155,15 @@ struct PrecomputedTransactionData
136155

137156
enum class SigVersion
138157
{
139-
BASE = 0,
140-
WITNESS_V0 = 1,
158+
BASE = 0, //!< Bare scripts and BIP16 P2SH-wrapped redeemscripts
159+
WITNESS_V0 = 1, //!< Witness v0 (P2WPKH and P2WSH); see BIP 141
160+
TAPROOT = 2, //!< Witness v1 with 32-byte program, not BIP16 P2SH-wrapped, key path spending; see BIP 341
141161
};
142162

143163
/** Signature hash sizes */
144164
static constexpr size_t WITNESS_V0_SCRIPTHASH_SIZE = 32;
145165
static constexpr size_t WITNESS_V0_KEYHASH_SIZE = 20;
166+
static constexpr size_t WITNESS_V1_TAPROOT_SIZE = 32;
146167

147168
template <class T>
148169
uint256 SignatureHash(const CScript& scriptCode, const T& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache = nullptr);

src/script/script.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20
4444
// SEQUENCE_FINAL).
4545
static const uint32_t LOCKTIME_MAX = 0xFFFFFFFFU;
4646

47+
// Tag for input annex. If there are at least two witness elements for a transaction input,
48+
// and the first byte of the last element is 0x50, this last element is called annex, and
49+
// has meanings independent of the script
50+
static constexpr unsigned int ANNEX_TAG = 0x50;
51+
4752
template <typename T>
4853
std::vector<unsigned char> ToByteVector(const T& in)
4954
{

src/validation.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1538,7 +1538,7 @@ bool CheckInputScripts(const CTransaction& tx, TxValidationState &state, const C
15381538
return true;
15391539
}
15401540

1541-
if (!txdata.m_ready) {
1541+
if (!txdata.m_spent_outputs_ready) {
15421542
std::vector<CTxOut> spent_outputs;
15431543
spent_outputs.reserve(tx.vin.size());
15441544

0 commit comments

Comments
 (0)