Skip to content

Commit 5c2e2af

Browse files
committed
Merge bitcoin/bitcoin#21365: Basic Taproot signing support for descriptor wallets
458a345 Add support for SIGHASH_DEFAULT in RPCs, and make it default (Pieter Wuille) c0f0c8e tests: check spending of P2TR (Pieter Wuille) a238012 Basic Taproot signing logic in script/sign.cpp (Pieter Wuille) 49487bc Make GetInputUTXO safer: verify non-witness UTXO match (Pieter Wuille) fd3f689 Construct and use PrecomputedTransactionData in PSBT signing (Pieter Wuille) 5cb6502 Construct and use PrecomputedTransactionData in SignTransaction (Pieter Wuille) 5d2e224 Don't nuke witness data when signing fails (Pieter Wuille) ce93531 Permit full precomputation in PrecomputedTransactionData (Pieter Wuille) e841fb5 Add precomputed txdata support to MutableTransactionSignatureCreator (Pieter Wuille) a91d532 Add CKey::SignSchnorr function for BIP 340/341 signing (Pieter Wuille) e77a283 Use HandleMissingData also in CheckSchnorrSignature (Pieter Wuille) dbb0ce9 Add TaprootSpendData data structure, equivalent to script map for P2[W]SH (Pieter Wuille) Pull request description: Builds on top of #22051, adding signing support after derivation support. Nothing is changed in descriptor features. Signing works for key path and script path spending, through the normal sending functions, and PSBT-based RPCs. However, PSBT usability is rather low as no extensions have been defined to convey Taproot-specific information, so all script information must be known to the signing wallet. ACKs for top commit: achow101: re-ACK 458a345 fjahr: Code review ACK 458a345 Sjors: ACK 458a345 Tree-SHA512: 30ed212cf7754763a4a81624ebc084c51727b8322711ac0b390369213c1a891d367ed8b123882ac08c99595320c11ec57ee42304ff22a69afdc3d1a0d55cc711
2 parents 8cb4307 + 458a345 commit 5c2e2af

28 files changed

+594
-65
lines changed

src/bitcoin-tx.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -506,11 +506,12 @@ static void MutateTxDelOutput(CMutableTransaction& tx, const std::string& strOut
506506
tx.vout.erase(tx.vout.begin() + outIdx);
507507
}
508508

509-
static const unsigned int N_SIGHASH_OPTS = 6;
509+
static const unsigned int N_SIGHASH_OPTS = 7;
510510
static const struct {
511511
const char *flagStr;
512512
int flags;
513513
} sighashOptions[N_SIGHASH_OPTS] = {
514+
{"DEFAULT", SIGHASH_DEFAULT},
514515
{"ALL", SIGHASH_ALL},
515516
{"NONE", SIGHASH_NONE},
516517
{"SINGLE", SIGHASH_SINGLE},

src/core_read.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ int ParseSighashString(const UniValue& sighash)
260260
int hash_type = SIGHASH_ALL;
261261
if (!sighash.isNull()) {
262262
static std::map<std::string, int> map_sighash_values = {
263+
{std::string("DEFAULT"), int(SIGHASH_DEFAULT)},
263264
{std::string("ALL"), int(SIGHASH_ALL)},
264265
{std::string("ALL|ANYONECANPAY"), int(SIGHASH_ALL|SIGHASH_ANYONECANPAY)},
265266
{std::string("NONE"), int(SIGHASH_NONE)},

src/key.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@
77

88
#include <crypto/common.h>
99
#include <crypto/hmac_sha512.h>
10+
#include <hash.h>
1011
#include <random.h>
1112

1213
#include <secp256k1.h>
14+
#include <secp256k1_extrakeys.h>
1315
#include <secp256k1_recovery.h>
16+
#include <secp256k1_schnorrsig.h>
1417

1518
static secp256k1_context* secp256k1_context_sign = nullptr;
1619

@@ -258,6 +261,24 @@ bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig)
258261
return true;
259262
}
260263

264+
bool CKey::SignSchnorr(const uint256& hash, Span<unsigned char> sig, const uint256* merkle_root, const uint256* aux) const
265+
{
266+
assert(sig.size() == 64);
267+
secp256k1_keypair keypair;
268+
if (!secp256k1_keypair_create(secp256k1_context_sign, &keypair, begin())) return false;
269+
if (merkle_root) {
270+
secp256k1_xonly_pubkey pubkey;
271+
if (!secp256k1_keypair_xonly_pub(secp256k1_context_sign, &pubkey, nullptr, &keypair)) return false;
272+
unsigned char pubkey_bytes[32];
273+
if (!secp256k1_xonly_pubkey_serialize(secp256k1_context_sign, pubkey_bytes, &pubkey)) return false;
274+
uint256 tweak = XOnlyPubKey(pubkey_bytes).ComputeTapTweakHash(merkle_root->IsNull() ? nullptr : merkle_root);
275+
if (!secp256k1_keypair_xonly_tweak_add(GetVerifyContext(), &keypair, tweak.data())) return false;
276+
}
277+
bool ret = secp256k1_schnorrsig_sign(secp256k1_context_sign, sig.data(), hash.data(), &keypair, secp256k1_nonce_function_bip340, aux ? (void*)aux->data() : nullptr);
278+
memory_cleanse(&keypair, sizeof(keypair));
279+
return ret;
280+
}
281+
261282
bool CKey::Load(const CPrivKey &seckey, const CPubKey &vchPubKey, bool fSkipCheck=false) {
262283
if (!ec_seckey_import_der(secp256k1_context_sign, (unsigned char*)begin(), seckey.data(), seckey.size()))
263284
return false;

src/key.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,18 @@ class CKey
128128
*/
129129
bool SignCompact(const uint256& hash, std::vector<unsigned char>& vchSig) const;
130130

131+
/**
132+
* Create a BIP-340 Schnorr signature, for the xonly-pubkey corresponding to *this,
133+
* optionally tweaked by *merkle_root. Additional nonce entropy can be provided through
134+
* aux.
135+
*
136+
* When merkle_root is not nullptr, this results in a signature with a modified key as
137+
* specified in BIP341:
138+
* - If merkle_root->IsNull(): key + H_TapTweak(pubkey)*G
139+
* - Otherwise: key + H_TapTweak(pubkey || *merkle_root)
140+
*/
141+
bool SignSchnorr(const uint256& hash, Span<unsigned char> sig, const uint256* merkle_root = nullptr, const uint256* aux = nullptr) const;
142+
131143
//! Derive BIP32 child key.
132144
bool Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const;
133145

src/node/psbt.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
2323

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

26+
const PrecomputedTransactionData txdata = PrecomputePSBTData(psbtx);
27+
2628
for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
2729
PSBTInput& input = psbtx.inputs[i];
2830
PSBTInputAnalysis& input_analysis = result.inputs[i];
@@ -61,7 +63,7 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
6163

6264
// Figure out what is missing
6365
SignatureData outdata;
64-
bool complete = SignPSBTInput(DUMMY_SIGNING_PROVIDER, psbtx, i, 1, &outdata);
66+
bool complete = SignPSBTInput(DUMMY_SIGNING_PROVIDER, psbtx, i, &txdata, 1, &outdata);
6567

6668
// Things are missing
6769
if (!complete) {
@@ -121,7 +123,7 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
121123
PSBTInput& input = psbtx.inputs[i];
122124
Coin newcoin;
123125

124-
if (!SignPSBTInput(DUMMY_SIGNING_PROVIDER, psbtx, i, 1, nullptr, true) || !psbtx.GetInputUTXO(newcoin.out, i)) {
126+
if (!SignPSBTInput(DUMMY_SIGNING_PROVIDER, psbtx, i, nullptr, 1) || !psbtx.GetInputUTXO(newcoin.out, i)) {
125127
success = false;
126128
break;
127129
} else {

src/psbt.cpp

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,15 @@ bool PartiallySignedTransaction::AddOutput(const CTxOut& txout, const PSBTOutput
5959

6060
bool PartiallySignedTransaction::GetInputUTXO(CTxOut& utxo, int input_index) const
6161
{
62-
PSBTInput input = inputs[input_index];
62+
const PSBTInput& input = inputs[input_index];
6363
uint32_t prevout_index = tx->vin[input_index].prevout.n;
6464
if (input.non_witness_utxo) {
6565
if (prevout_index >= input.non_witness_utxo->vout.size()) {
6666
return false;
6767
}
68+
if (input.non_witness_utxo->GetHash() != tx->vin[input_index].prevout.hash) {
69+
return false;
70+
}
6871
utxo = input.non_witness_utxo->vout[prevout_index];
6972
} else if (!input.witness_utxo.IsNull()) {
7073
utxo = input.witness_utxo;
@@ -227,7 +230,24 @@ void UpdatePSBTOutput(const SigningProvider& provider, PartiallySignedTransactio
227230
psbt_out.FromSignatureData(sigdata);
228231
}
229232

230-
bool SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction& psbt, int index, int sighash, SignatureData* out_sigdata, bool use_dummy)
233+
PrecomputedTransactionData PrecomputePSBTData(const PartiallySignedTransaction& psbt)
234+
{
235+
const CMutableTransaction& tx = *psbt.tx;
236+
bool have_all_spent_outputs = true;
237+
std::vector<CTxOut> utxos(tx.vin.size());
238+
for (size_t idx = 0; idx < tx.vin.size(); ++idx) {
239+
if (!psbt.GetInputUTXO(utxos[idx], idx)) have_all_spent_outputs = false;
240+
}
241+
PrecomputedTransactionData txdata;
242+
if (have_all_spent_outputs) {
243+
txdata.Init(tx, std::move(utxos), true);
244+
} else {
245+
txdata.Init(tx, {}, true);
246+
}
247+
return txdata;
248+
}
249+
250+
bool SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction& psbt, int index, const PrecomputedTransactionData* txdata, int sighash, SignatureData* out_sigdata)
231251
{
232252
PSBTInput& input = psbt.inputs.at(index);
233253
const CMutableTransaction& tx = *psbt.tx;
@@ -267,10 +287,10 @@ bool SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction&
267287

268288
sigdata.witness = false;
269289
bool sig_complete;
270-
if (use_dummy) {
290+
if (txdata == nullptr) {
271291
sig_complete = ProduceSignature(provider, DUMMY_SIGNATURE_CREATOR, utxo.scriptPubKey, sigdata);
272292
} else {
273-
MutableTransactionSignatureCreator creator(&tx, index, utxo.nValue, sighash);
293+
MutableTransactionSignatureCreator creator(&tx, index, utxo.nValue, txdata, sighash);
274294
sig_complete = ProduceSignature(provider, creator, utxo.scriptPubKey, sigdata);
275295
}
276296
// Verify that a witness signature was produced in case one was required.
@@ -302,8 +322,9 @@ bool FinalizePSBT(PartiallySignedTransaction& psbtx)
302322
// PartiallySignedTransaction did not understand them), this will combine them into a final
303323
// script.
304324
bool complete = true;
325+
const PrecomputedTransactionData txdata = PrecomputePSBTData(psbtx);
305326
for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
306-
complete &= SignPSBTInput(DUMMY_SIGNING_PROVIDER, psbtx, i, SIGHASH_ALL);
327+
complete &= SignPSBTInput(DUMMY_SIGNING_PROVIDER, psbtx, i, &txdata, SIGHASH_ALL);
307328
}
308329

309330
return complete;

src/psbt.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -567,11 +567,18 @@ enum class PSBTRole {
567567

568568
std::string PSBTRoleName(PSBTRole role);
569569

570+
/** Compute a PrecomputedTransactionData object from a psbt. */
571+
PrecomputedTransactionData PrecomputePSBTData(const PartiallySignedTransaction& psbt);
572+
570573
/** Checks whether a PSBTInput is already signed. */
571574
bool PSBTInputSigned(const PSBTInput& input);
572575

573-
/** Signs a PSBTInput, verifying that all provided data matches what is being signed. */
574-
bool SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction& psbt, int index, int sighash = SIGHASH_ALL, SignatureData* out_sigdata = nullptr, bool use_dummy = false);
576+
/** Signs a PSBTInput, verifying that all provided data matches what is being signed.
577+
*
578+
* txdata should be the output of PrecomputePSBTData (which can be shared across
579+
* multiple SignPSBTInput calls). If it is nullptr, a dummy signature will be created.
580+
**/
581+
bool SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction& psbt, int index, const PrecomputedTransactionData* txdata, int sighash = SIGHASH_ALL, SignatureData* out_sigdata = nullptr);
575582

576583
/** Counts the unsigned inputs of a PSBT. */
577584
size_t CountPSBTUnsignedInputs(const PartiallySignedTransaction& psbt);

src/pubkey.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,3 +373,7 @@ ECCVerifyHandle::~ECCVerifyHandle()
373373
secp256k1_context_verify = nullptr;
374374
}
375375
}
376+
377+
const secp256k1_context* GetVerifyContext() {
378+
return secp256k1_context_verify;
379+
}

src/pubkey.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,10 @@ class XOnlyPubKey
234234
* fail. */
235235
bool IsFullyValid() const;
236236

237+
/** Test whether this is the 0 key (the result of default construction). This implies
238+
* !IsFullyValid(). */
239+
bool IsNull() const { return m_keydata.IsNull(); }
240+
237241
/** Construct an x-only pubkey from exactly 32 bytes. */
238242
explicit XOnlyPubKey(Span<const unsigned char> bytes);
239243

@@ -312,4 +316,10 @@ class ECCVerifyHandle
312316
~ECCVerifyHandle();
313317
};
314318

319+
typedef struct secp256k1_context_struct secp256k1_context;
320+
321+
/** Access to the internal secp256k1 context used for verification. Only intended to be used
322+
* by key.cpp. */
323+
const secp256k1_context* GetVerifyContext();
324+
315325
#endif // BITCOIN_PUBKEY_H

src/rpc/rawtransaction.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -753,7 +753,8 @@ static RPCHelpMan signrawtransactionwithkey()
753753
},
754754
},
755755
},
756-
{"sighashtype", RPCArg::Type::STR, RPCArg::Default{"ALL"}, "The signature hash type. Must be one of:\n"
756+
{"sighashtype", RPCArg::Type::STR, RPCArg::Default{"DEFAULT"}, "The signature hash type. Must be one of:\n"
757+
" \"DEFAULT\"\n"
757758
" \"ALL\"\n"
758759
" \"NONE\"\n"
759760
" \"SINGLE\"\n"
@@ -1655,6 +1656,7 @@ static RPCHelpMan utxoupdatepsbt()
16551656
}
16561657

16571658
// Fill the inputs
1659+
const PrecomputedTransactionData txdata = PrecomputePSBTData(psbtx);
16581660
for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
16591661
PSBTInput& input = psbtx.inputs.at(i);
16601662

@@ -1671,7 +1673,7 @@ static RPCHelpMan utxoupdatepsbt()
16711673
// Update script/keypath information using descriptor data.
16721674
// Note that SignPSBTInput does a lot more than just constructing ECDSA signatures
16731675
// we don't actually care about those here, in fact.
1674-
SignPSBTInput(public_provider, psbtx, i, /* sighash_type */ 1);
1676+
SignPSBTInput(public_provider, psbtx, i, &txdata, /* sighash_type */ 1);
16751677
}
16761678

16771679
// Update script/keypath information using descriptor data.

0 commit comments

Comments
 (0)