Skip to content
This repository was archived by the owner on Apr 15, 2025. It is now read-only.

Commit 7ed2d29

Browse files
committed
Add BIP 119 CTV
* Copy PR 3 from bitcoin-inquisition (bitcoin-inquisition#3) but CTV is always deployed and no tests
1 parent e9e5a8b commit 7ed2d29

24 files changed

+1292
-42
lines changed

src/node/psbt.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
2424

2525
result.inputs.resize(psbtx.tx->vin.size());
2626

27-
const PrecomputedTransactionData txdata = PrecomputePSBTData(psbtx);
27+
PrecomputedTransactionData txdata = PrecomputePSBTData(psbtx);
2828

2929
for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
3030
PSBTInput& input = psbtx.inputs[i];

src/policy/policy.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,10 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
196196
if (subscript.GetSigOpCount(true) > MAX_P2SH_SIGOPS) {
197197
return false;
198198
}
199+
} else if (whichType == TxoutType::TX_BARE_DEFAULT_CHECK_TEMPLATE_VERIFY_HASH) {
200+
if (tx.vin[i].scriptSig.size() != 0) return false;
199201
}
202+
200203
}
201204

202205
return true;

src/policy/policy.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@ static constexpr unsigned int STANDARD_SCRIPT_VERIFY_FLAGS{MANDATORY_SCRIPT_VERI
114114
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION |
115115
SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS |
116116
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE |
117-
SCRIPT_VERIFY_ANYPREVOUT};
117+
SCRIPT_VERIFY_ANYPREVOUT |
118+
SCRIPT_VERIFY_DEFAULT_CHECK_TEMPLATE_VERIFY_HASH};
118119

119120
/** For convenience, standard but not mandatory verify flags. */
120121
static constexpr unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS{STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS};

src/psbt.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ bool PSBTInputSigned(const PSBTInput& input)
295295
return !input.final_script_sig.empty() || !input.final_script_witness.IsNull();
296296
}
297297

298-
bool PSBTInputSignedAndVerified(const PartiallySignedTransaction psbt, unsigned int input_index, const PrecomputedTransactionData* txdata)
298+
bool PSBTInputSignedAndVerified(const PartiallySignedTransaction psbt, unsigned int input_index, PrecomputedTransactionData* txdata)
299299
{
300300
CTxOut utxo;
301301
assert(psbt.inputs.size() >= input_index);
@@ -372,7 +372,7 @@ PrecomputedTransactionData PrecomputePSBTData(const PartiallySignedTransaction&
372372
return txdata;
373373
}
374374

375-
bool SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction& psbt, int index, const PrecomputedTransactionData* txdata, int sighash, SignatureData* out_sigdata, bool finalize)
375+
bool SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction& psbt, int index, PrecomputedTransactionData* txdata, int sighash, SignatureData* out_sigdata, bool finalize)
376376
{
377377
PSBTInput& input = psbt.inputs.at(index);
378378
const CMutableTransaction& tx = *psbt.tx;
@@ -484,7 +484,7 @@ bool FinalizePSBT(PartiallySignedTransaction& psbtx)
484484
// PartiallySignedTransaction did not understand them), this will combine them into a final
485485
// script.
486486
bool complete = true;
487-
const PrecomputedTransactionData txdata = PrecomputePSBTData(psbtx);
487+
PrecomputedTransactionData txdata = PrecomputePSBTData(psbtx);
488488
for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
489489
complete &= SignPSBTInput(DUMMY_SIGNING_PROVIDER, psbtx, i, &txdata, SIGHASH_ALL, nullptr, true);
490490
}

src/psbt.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1222,14 +1222,14 @@ PrecomputedTransactionData PrecomputePSBTData(const PartiallySignedTransaction&
12221222
bool PSBTInputSigned(const PSBTInput& input);
12231223

12241224
/** Checks whether a PSBTInput is already signed by doing script verification using final fields. */
1225-
bool PSBTInputSignedAndVerified(const PartiallySignedTransaction psbt, unsigned int input_index, const PrecomputedTransactionData* txdata);
1225+
bool PSBTInputSignedAndVerified(const PartiallySignedTransaction psbt, unsigned int input_index, PrecomputedTransactionData* txdata);
12261226

12271227
/** Signs a PSBTInput, verifying that all provided data matches what is being signed.
12281228
*
12291229
* txdata should be the output of PrecomputePSBTData (which can be shared across
12301230
* multiple SignPSBTInput calls). If it is nullptr, a dummy signature will be created.
12311231
**/
1232-
bool SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction& psbt, int index, const PrecomputedTransactionData* txdata, int sighash = SIGHASH_ALL, SignatureData* out_sigdata = nullptr, bool finalize = true);
1232+
bool SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction& psbt, int index, PrecomputedTransactionData* txdata, int sighash = SIGHASH_ALL, SignatureData* out_sigdata = nullptr, bool finalize = true);
12331233

12341234
/** Reduces the size of the PSBT by dropping unnecessary `non_witness_utxos` (i.e. complete previous transactions) from a psbt when all inputs are segwit v1. */
12351235
void RemoveUnnecessaryTransactions(PartiallySignedTransaction& psbtx, const int& sighash_type);

src/rpc/rawtransaction.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,7 @@ static RPCHelpMan decodescript()
557557
case TxoutType::SCRIPTHASH:
558558
case TxoutType::WITNESS_UNKNOWN:
559559
case TxoutType::WITNESS_V1_TAPROOT:
560+
case TxoutType::TX_BARE_DEFAULT_CHECK_TEMPLATE_VERIFY_HASH:
560561
// Should not be wrapped
561562
return false;
562563
} // no default case, so the compiler can warn about missing cases
@@ -599,6 +600,7 @@ static RPCHelpMan decodescript()
599600
case TxoutType::WITNESS_V0_KEYHASH:
600601
case TxoutType::WITNESS_V0_SCRIPTHASH:
601602
case TxoutType::WITNESS_V1_TAPROOT:
603+
case TxoutType::TX_BARE_DEFAULT_CHECK_TEMPLATE_VERIFY_HASH:
602604
// Should not be wrapped
603605
return false;
604606
} // no default case, so the compiler can warn about missing cases
@@ -1700,6 +1702,52 @@ static RPCHelpMan utxoupdatepsbt()
17001702
HidingSigningProvider(&provider, /*hide_secret=*/true, /*hide_origin=*/false),
17011703
/*sighash_type=*/SIGHASH_ALL,
17021704
/*finalize=*/false);
1705+
HidingSigningProvider public_provider(&provider, /*hide_secret=*/true, /*hide_origin=*/false);
1706+
1707+
// Fetch previous transactions (inputs):
1708+
CCoinsView viewDummy;
1709+
CCoinsViewCache view(&viewDummy);
1710+
{
1711+
NodeContext& node = EnsureAnyNodeContext(request.context);
1712+
const CTxMemPool& mempool = EnsureMemPool(node);
1713+
ChainstateManager& chainman = EnsureChainman(node);
1714+
LOCK2(cs_main, mempool.cs);
1715+
CCoinsViewCache &viewChain = chainman.ActiveChainstate().CoinsTip();
1716+
CCoinsViewMemPool viewMempool(&viewChain, mempool);
1717+
view.SetBackend(viewMempool); // temporarily switch cache backend to db+mempool view
1718+
1719+
for (const CTxIn& txin : psbtx.tx->vin) {
1720+
view.AccessCoin(txin.prevout); // Load entries from viewChain into view; can fail.
1721+
}
1722+
1723+
view.SetBackend(viewDummy); // switch back to avoid locking mempool for too long
1724+
}
1725+
1726+
// Fill the inputs
1727+
PrecomputedTransactionData txdata = PrecomputePSBTData(psbtx);
1728+
for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
1729+
PSBTInput& input = psbtx.inputs.at(i);
1730+
1731+
if (input.non_witness_utxo || !input.witness_utxo.IsNull()) {
1732+
continue;
1733+
}
1734+
1735+
const Coin& coin = view.AccessCoin(psbtx.tx->vin[i].prevout);
1736+
1737+
if (IsSegWitOutput(provider, coin.out.scriptPubKey)) {
1738+
input.witness_utxo = coin.out;
1739+
}
1740+
1741+
// Update script/keypath information using descriptor data.
1742+
// Note that SignPSBTInput does a lot more than just constructing ECDSA signatures
1743+
// we don't actually care about those here, in fact.
1744+
SignPSBTInput(public_provider, psbtx, i, &txdata, /*sighash=*/1);
1745+
}
1746+
1747+
// Update script/keypath information using descriptor data.
1748+
for (unsigned int i = 0; i < psbtx.tx->vout.size(); ++i) {
1749+
UpdatePSBTOutput(public_provider, psbtx, i);
1750+
}
17031751

17041752
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
17051753
ssTx << psbtx;

src/script/bitcoinconsensus.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,7 @@ static int verify_script(const unsigned char *scriptPubKey, unsigned int scriptP
108108
// Regardless of the verification result, the tx did not error.
109109
set_error(err, bitcoinconsensus_ERR_OK);
110110

111-
PrecomputedTransactionData txdata(tx);
112-
113-
if (spentOutputs != nullptr && flags & bitcoinconsensus_SCRIPT_FLAGS_VERIFY_TAPROOT) {
114-
txdata.Init(tx, std::move(spent_outputs));
115-
}
111+
PrecomputedTransactionData txdata(tx, nullptr);
116112

117113
return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), &tx.vin[nIn].scriptWitness, flags, TransactionSignatureChecker(&tx, nIn, amount, txdata, MissingDataBehavior::FAIL), nullptr);
118114
} catch (const std::exception&) {

src/script/interpreter.cpp

Lines changed: 164 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,39 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
606606
break;
607607
}
608608

609-
case OP_NOP1: case OP_NOP4: case OP_NOP5:
609+
case OP_CHECKTEMPLATEVERIFY:
610+
{
611+
// if flags not enabled; treat as a NOP4
612+
if (!(flags & SCRIPT_VERIFY_DEFAULT_CHECK_TEMPLATE_VERIFY_HASH)) {
613+
if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
614+
return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
615+
break;
616+
}
617+
618+
if (stack.size() < 1)
619+
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
620+
621+
// If the argument was not 32 bytes, treat as OP_NOP4:
622+
switch (stack.back().size()) {
623+
case 32:
624+
{
625+
const Span<const unsigned char> hash{stack.back()};
626+
if (!checker.CheckDefaultCheckTemplateVerifyHash(hash)) {
627+
return set_error(serror, SCRIPT_ERR_TEMPLATE_MISMATCH);
628+
}
629+
break;
630+
}
631+
default:
632+
// future upgrade can add semantics for this opcode with different length args
633+
// so discourage use when applicable
634+
if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
635+
return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
636+
}
637+
}
638+
}
639+
break;
640+
641+
case OP_NOP1: case OP_NOP5:
610642
case OP_NOP6: case OP_NOP7: case OP_NOP8: case OP_NOP9: case OP_NOP10:
611643
{
612644
if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
@@ -1406,12 +1438,79 @@ uint256 GetSpentScriptsSHA256(const std::vector<CTxOut>& outputs_spent)
14061438
return ss.GetSHA256();
14071439
}
14081440

1441+
/** Compute the (single) SHA256 of the concatenation of all scriptSigs in a tx. */
1442+
template <class T>
1443+
uint256 GetScriptSigsSHA256(const T& txTo)
1444+
{
1445+
CHashWriter ss(SER_GETHASH, 0);
1446+
for (const auto& in : txTo.vin) {
1447+
ss << in.scriptSig;
1448+
}
1449+
return ss.GetSHA256();
1450+
}
1451+
1452+
/* Not Exported, just convenience */
1453+
template<typename TxType>
1454+
uint256 GetDefaultCheckTemplateVerifyHashWithScript(const TxType& tx, const uint256& outputs_hash, const uint256& sequences_hash,
1455+
const uint256& scriptSig_hash, const uint32_t input_index) {
1456+
auto h = CHashWriter(SER_GETHASH, 0)
1457+
<< tx.nVersion
1458+
<< tx.nLockTime
1459+
<< scriptSig_hash
1460+
<< uint32_t(tx.vin.size())
1461+
<< sequences_hash
1462+
<< uint32_t(tx.vout.size())
1463+
<< outputs_hash
1464+
<< input_index;
1465+
return h.GetSHA256();
1466+
}
1467+
1468+
template<typename TxType>
1469+
uint256 GetDefaultCheckTemplateVerifyHashEmptyScript(const TxType& tx, const uint256& outputs_hash, const uint256& sequences_hash,
1470+
const uint32_t input_index) {
1471+
auto h = CHashWriter(SER_GETHASH, 0)
1472+
<< tx.nVersion
1473+
<< tx.nLockTime
1474+
<< uint32_t(tx.vin.size())
1475+
<< sequences_hash
1476+
<< uint32_t(tx.vout.size())
1477+
<< outputs_hash
1478+
<< input_index;
1479+
return h.GetSHA256();
1480+
}
14091481

14101482
} // namespace
14111483

1484+
template<typename TxType>
1485+
uint256 GetDefaultCheckTemplateVerifyHash(const TxType& tx, uint32_t input_index) {
1486+
return GetDefaultCheckTemplateVerifyHash(tx, GetOutputsSHA256(tx), GetSequencesSHA256(tx), input_index);
1487+
}
1488+
1489+
template<typename TxType>
1490+
static bool NoScriptSigs(const TxType& tx)
1491+
{
1492+
return std::all_of(tx.vin.begin(), tx.vin.end(), [](const CTxIn& c) { return c.scriptSig.empty(); });
1493+
}
1494+
1495+
template<typename TxType>
1496+
uint256 GetDefaultCheckTemplateVerifyHash(const TxType& tx, const uint256& outputs_hash, const uint256& sequences_hash,
1497+
const uint32_t input_index) {
1498+
return NoScriptSigs(tx) ? GetDefaultCheckTemplateVerifyHashEmptyScript(tx, outputs_hash, sequences_hash, input_index) :
1499+
GetDefaultCheckTemplateVerifyHashWithScript(tx, outputs_hash, sequences_hash, GetScriptSigsSHA256(tx), input_index);
1500+
}
1501+
1502+
template
1503+
uint256 GetDefaultCheckTemplateVerifyHash(const CTransaction& tx, const uint256& outputs_hash, const uint256& sequences_hash,
1504+
const uint32_t input_index);
1505+
template
1506+
uint256 GetDefaultCheckTemplateVerifyHash(const CMutableTransaction& tx, const uint256& outputs_hash, const uint256& sequences_hash,
1507+
const uint32_t input_index);
1508+
14121509
template <class T>
1413-
void PrecomputedTransactionData::Init(const T& txTo, std::vector<CTxOut>&& spent_outputs, bool force)
1510+
void PrecomputedTransactionData::Init(const T& txTo, std::vector<CTxOut>&& spent_outputs, bool force, PrecomputedTransactionData::bip_119_cache_synchronizer_t f)
14141511
{
1512+
// Do not allow overriding a sync function if one is already set
1513+
if (m_bip119_cache_synchronizer) assert(f == nullptr);
14151514
assert(!m_spent_outputs_ready);
14161515

14171516
m_spent_outputs = std::move(spent_outputs);
@@ -1459,19 +1558,60 @@ void PrecomputedTransactionData::Init(const T& txTo, std::vector<CTxOut>&& spent
14591558
m_spent_scripts_single_hash = GetSpentScriptsSHA256(m_spent_outputs);
14601559
m_bip341_taproot_ready = true;
14611560
}
1561+
1562+
if (force) {
1563+
// Eagerly compute BIP119 state
1564+
BIP119EagerInit(txTo);
1565+
// Disable Lazy Sync Wrapper
1566+
m_bip119_cache_synchronizer = nullptr;
1567+
} else if (!m_bip119_cache_synchronizer) {
1568+
// If no function was provided, assume that we are single-threaded but
1569+
// still cache-on-first-use
1570+
auto single_threaded = [&](std::function<void()> f)
1571+
{
1572+
f();
1573+
// disables future calls from recomputing
1574+
m_bip119_cache_synchronizer = nullptr;
1575+
};
1576+
m_bip119_cache_synchronizer = single_threaded;
1577+
}
1578+
}
1579+
1580+
template <class T>
1581+
void PrecomputedTransactionData::BIP119EagerInit(const T& txTo)
1582+
{
1583+
if (!(m_bip143_segwit_ready || m_bip341_taproot_ready)) {
1584+
m_prevouts_single_hash = GetPrevoutsSHA256(txTo);
1585+
m_sequences_single_hash = GetSequencesSHA256(txTo);
1586+
m_outputs_single_hash = GetOutputsSHA256(txTo);
1587+
}
1588+
// 0 hash used to signal if we should skip scriptSigs
1589+
// when re-computing for different indexes.
1590+
m_scriptSigs_single_hash = NoScriptSigs(txTo) ? uint256{} : GetScriptSigsSHA256(txTo);
1591+
}
1592+
template <class T>
1593+
void PrecomputedTransactionData::BIP119LazyInit(const T& txTo)
1594+
{
1595+
if (m_bip119_cache_synchronizer) {
1596+
m_bip119_cache_synchronizer([&]() {
1597+
BIP119EagerInit(txTo);
1598+
});
1599+
}
14621600
}
14631601

14641602
template <class T>
1465-
PrecomputedTransactionData::PrecomputedTransactionData(const T& txTo)
1603+
PrecomputedTransactionData::PrecomputedTransactionData(const T& txTo, PrecomputedTransactionData::bip_119_cache_synchronizer_t f) : m_bip119_cache_synchronizer(f)
14661604
{
14671605
Init(txTo, {});
14681606
}
14691607

14701608
// explicit instantiation
1471-
template void PrecomputedTransactionData::Init(const CTransaction& txTo, std::vector<CTxOut>&& spent_outputs, bool force);
1472-
template void PrecomputedTransactionData::Init(const CMutableTransaction& txTo, std::vector<CTxOut>&& spent_outputs, bool force);
1473-
template PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo);
1474-
template PrecomputedTransactionData::PrecomputedTransactionData(const CMutableTransaction& txTo);
1609+
template void PrecomputedTransactionData::Init(const CTransaction& txTo, std::vector<CTxOut>&& spent_outputs, bool force, PrecomputedTransactionData::bip_119_cache_synchronizer_t f);
1610+
template void PrecomputedTransactionData::Init(const CMutableTransaction& txTo, std::vector<CTxOut>&& spent_outputs, bool force, PrecomputedTransactionData::bip_119_cache_synchronizer_t f);
1611+
template void PrecomputedTransactionData::BIP119LazyInit(const CTransaction& txTo);
1612+
template void PrecomputedTransactionData::BIP119LazyInit(const CMutableTransaction& txTo);
1613+
template PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo, PrecomputedTransactionData::bip_119_cache_synchronizer_t f);
1614+
template PrecomputedTransactionData::PrecomputedTransactionData(const CMutableTransaction& txTo, PrecomputedTransactionData::bip_119_cache_synchronizer_t f);
14751615

14761616
const HashWriter HASHER_TAPSIGHASH{TaggedHash("TapSighash")};
14771617
const HashWriter HASHER_TAPLEAF{TaggedHash("TapLeaf")};
@@ -1815,6 +1955,23 @@ bool GenericTransactionSignatureChecker<T>::CheckSequence(const CScriptNum& nSeq
18151955
return true;
18161956
}
18171957

1958+
template <class T>
1959+
bool GenericTransactionSignatureChecker<T>::CheckDefaultCheckTemplateVerifyHash(const Span<const unsigned char>& hash) const
1960+
{
1961+
// Should already be checked before calling...
1962+
assert(hash.size() == 32);
1963+
if (txdata && txTo) {
1964+
txdata->BIP119LazyInit(*txTo);
1965+
uint256 hash_tmpl = txdata->m_scriptSigs_single_hash.IsNull() ?
1966+
GetDefaultCheckTemplateVerifyHashEmptyScript(*txTo, txdata->m_outputs_single_hash, txdata->m_sequences_single_hash, nIn) :
1967+
GetDefaultCheckTemplateVerifyHashWithScript(*txTo, txdata->m_outputs_single_hash, txdata->m_sequences_single_hash,
1968+
txdata->m_scriptSigs_single_hash, nIn);
1969+
return std::equal(hash_tmpl.begin(), hash_tmpl.end(), hash.data());
1970+
} else {
1971+
return HandleMissingData(m_mdb);
1972+
}
1973+
}
1974+
18181975
// explicit instantiation
18191976
template class GenericTransactionSignatureChecker<CTransaction>;
18201977
template class GenericTransactionSignatureChecker<CMutableTransaction>;

0 commit comments

Comments
 (0)