11
11
#include < script/signingprovider.h>
12
12
#include < script/standard.h>
13
13
#include < uint256.h>
14
+ #include < util/vector.h>
14
15
15
16
typedef std::vector<unsigned char > valtype;
16
17
@@ -30,6 +31,8 @@ MutableTransactionSignatureCreator::MutableTransactionSignatureCreator(const CMu
30
31
31
32
bool MutableTransactionSignatureCreator::CreateSig (const SigningProvider& provider, std::vector<unsigned char >& vchSig, const CKeyID& address, const CScript& scriptCode, SigVersion sigversion) const
32
33
{
34
+ assert (sigversion == SigVersion::BASE || sigversion == SigVersion::WITNESS_V0);
35
+
33
36
CKey key;
34
37
if (!provider.GetKey (address, key))
35
38
return false ;
@@ -48,6 +51,51 @@ bool MutableTransactionSignatureCreator::CreateSig(const SigningProvider& provid
48
51
return true ;
49
52
}
50
53
54
+ bool MutableTransactionSignatureCreator::CreateSchnorrSig (const SigningProvider& provider, std::vector<unsigned char >& sig, const XOnlyPubKey& pubkey, const uint256* leaf_hash, const uint256* merkle_root, SigVersion sigversion) const
55
+ {
56
+ assert (sigversion == SigVersion::TAPROOT || sigversion == SigVersion::TAPSCRIPT);
57
+
58
+ CKey key;
59
+ {
60
+ // For now, use the old full pubkey-based key derivation logic. As it indexed by
61
+ // Hash160(full pubkey), we need to try both a version prefixed with 0x02, and one
62
+ // with 0x03.
63
+ unsigned char b[33 ] = {0x02 };
64
+ std::copy (pubkey.begin (), pubkey.end (), b + 1 );
65
+ CPubKey fullpubkey;
66
+ fullpubkey.Set (b, b + 33 );
67
+ CKeyID keyid = fullpubkey.GetID ();
68
+ if (!provider.GetKey (keyid, key)) {
69
+ b[0 ] = 0x03 ;
70
+ fullpubkey.Set (b, b + 33 );
71
+ CKeyID keyid = fullpubkey.GetID ();
72
+ if (!provider.GetKey (keyid, key)) return false ;
73
+ }
74
+ }
75
+
76
+ // BIP341/BIP342 signing needs lots of precomputed transaction data. While some
77
+ // (non-SIGHASH_DEFAULT) sighash modes exist that can work with just some subset
78
+ // of data present, for now, only support signing when everything is provided.
79
+ if (!m_txdata || !m_txdata->m_bip341_taproot_ready || !m_txdata->m_spent_outputs_ready ) return false ;
80
+
81
+ ScriptExecutionData execdata;
82
+ execdata.m_annex_init = true ;
83
+ execdata.m_annex_present = false ; // Only support annex-less signing for now.
84
+ if (sigversion == SigVersion::TAPSCRIPT) {
85
+ execdata.m_codeseparator_pos_init = true ;
86
+ execdata.m_codeseparator_pos = 0xFFFFFFFF ; // Only support non-OP_CODESEPARATOR BIP342 signing for now.
87
+ if (!leaf_hash) return false ; // BIP342 signing needs leaf hash.
88
+ execdata.m_tapleaf_hash_init = true ;
89
+ execdata.m_tapleaf_hash = *leaf_hash;
90
+ }
91
+ uint256 hash;
92
+ if (!SignatureHashSchnorr (hash, execdata, *txTo, nIn, nHashType, sigversion, *m_txdata, MissingDataBehavior::FAIL)) return false ;
93
+ sig.resize (64 );
94
+ if (!key.SignSchnorr (hash, sig, merkle_root, nullptr )) return false ;
95
+ if (nHashType) sig.push_back (nHashType);
96
+ return true ;
97
+ }
98
+
51
99
static bool GetCScript (const SigningProvider& provider, const SignatureData& sigdata, const CScriptID& scriptid, CScript& script)
52
100
{
53
101
if (provider.GetCScript (scriptid, script)) {
@@ -104,6 +152,86 @@ static bool CreateSig(const BaseSignatureCreator& creator, SignatureData& sigdat
104
152
return false ;
105
153
}
106
154
155
+ static bool CreateTaprootScriptSig (const BaseSignatureCreator& creator, SignatureData& sigdata, const SigningProvider& provider, std::vector<unsigned char >& sig_out, const XOnlyPubKey& pubkey, const uint256& leaf_hash, SigVersion sigversion)
156
+ {
157
+ auto lookup_key = std::make_pair (pubkey, leaf_hash);
158
+ auto it = sigdata.taproot_script_sigs .find (lookup_key);
159
+ if (it != sigdata.taproot_script_sigs .end ()) {
160
+ sig_out = it->second ;
161
+ }
162
+ if (creator.CreateSchnorrSig (provider, sig_out, pubkey, &leaf_hash, nullptr , sigversion)) {
163
+ sigdata.taproot_script_sigs [lookup_key] = sig_out;
164
+ return true ;
165
+ }
166
+ return false ;
167
+ }
168
+
169
+ static bool SignTaprootScript (const SigningProvider& provider, const BaseSignatureCreator& creator, SignatureData& sigdata, int leaf_version, const CScript& script, std::vector<valtype>& result)
170
+ {
171
+ // Only BIP342 tapscript signing is supported for now.
172
+ if (leaf_version != TAPROOT_LEAF_TAPSCRIPT) return false ;
173
+ SigVersion sigversion = SigVersion::TAPSCRIPT;
174
+
175
+ uint256 leaf_hash = (CHashWriter (HASHER_TAPLEAF) << uint8_t (leaf_version) << script).GetSHA256 ();
176
+
177
+ // <xonly pubkey> OP_CHECKSIG
178
+ if (script.size () == 34 && script[33 ] == OP_CHECKSIG && script[0 ] == 0x20 ) {
179
+ XOnlyPubKey pubkey (MakeSpan (script).subspan (1 , 32 ));
180
+ std::vector<unsigned char > sig;
181
+ if (CreateTaprootScriptSig (creator, sigdata, provider, sig, pubkey, leaf_hash, sigversion)) {
182
+ result = Vector (std::move (sig));
183
+ return true ;
184
+ }
185
+ }
186
+
187
+ return false ;
188
+ }
189
+
190
+ static bool SignTaproot (const SigningProvider& provider, const BaseSignatureCreator& creator, const WitnessV1Taproot& output, SignatureData& sigdata, std::vector<valtype>& result)
191
+ {
192
+ TaprootSpendData spenddata;
193
+
194
+ // Gather information about this output.
195
+ if (provider.GetTaprootSpendData (output, spenddata)) {
196
+ sigdata.tr_spenddata .Merge (spenddata);
197
+ }
198
+
199
+ // Try key path spending.
200
+ {
201
+ std::vector<unsigned char > sig;
202
+ if (sigdata.taproot_key_path_sig .size () == 0 ) {
203
+ if (creator.CreateSchnorrSig (provider, sig, spenddata.internal_key , nullptr , &spenddata.merkle_root , SigVersion::TAPROOT)) {
204
+ sigdata.taproot_key_path_sig = sig;
205
+ }
206
+ }
207
+ if (sigdata.taproot_key_path_sig .size ()) {
208
+ result = Vector (sigdata.taproot_key_path_sig );
209
+ return true ;
210
+ }
211
+ }
212
+
213
+ // Try script path spending.
214
+ std::vector<std::vector<unsigned char >> smallest_result_stack;
215
+ for (const auto & [key, control_blocks] : sigdata.tr_spenddata .scripts ) {
216
+ const auto & [script, leaf_ver] = key;
217
+ std::vector<std::vector<unsigned char >> result_stack;
218
+ if (SignTaprootScript (provider, creator, sigdata, leaf_ver, script, result_stack)) {
219
+ result_stack.emplace_back (std::begin (script), std::end (script)); // Push the script
220
+ result_stack.push_back (*control_blocks.begin ()); // Push the smallest control block
221
+ if (smallest_result_stack.size () == 0 ||
222
+ GetSerializeSize (result_stack, PROTOCOL_VERSION) < GetSerializeSize (smallest_result_stack, PROTOCOL_VERSION)) {
223
+ smallest_result_stack = std::move (result_stack);
224
+ }
225
+ }
226
+ }
227
+ if (smallest_result_stack.size () != 0 ) {
228
+ result = std::move (smallest_result_stack);
229
+ return true ;
230
+ }
231
+
232
+ return false ;
233
+ }
234
+
107
235
/* *
108
236
* Sign scriptPubKey using signature made with creator.
109
237
* Signatures are returned in scriptSigRet (or returns false if scriptPubKey can't be signed),
@@ -125,7 +253,6 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
125
253
case TxoutType::NONSTANDARD:
126
254
case TxoutType::NULL_DATA:
127
255
case TxoutType::WITNESS_UNKNOWN:
128
- case TxoutType::WITNESS_V1_TAPROOT:
129
256
return false ;
130
257
case TxoutType::PUBKEY:
131
258
if (!CreateSig (creator, sigdata, provider, sig, CPubKey (vSolutions[0 ]), scriptPubKey, sigversion)) return false ;
@@ -187,6 +314,9 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
187
314
// Could not find witnessScript, add to missing
188
315
sigdata.missing_witness_script = uint256 (vSolutions[0 ]);
189
316
return false ;
317
+
318
+ case TxoutType::WITNESS_V1_TAPROOT:
319
+ return SignTaproot (provider, creator, WitnessV1Taproot (XOnlyPubKey{vSolutions[0 ]}), sigdata, ret);
190
320
} // no default case, so the compiler can warn about missing cases
191
321
assert (false );
192
322
}
@@ -249,6 +379,12 @@ bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreato
249
379
sigdata.scriptWitness .stack = result;
250
380
sigdata.witness = true ;
251
381
result.clear ();
382
+ } else if (whichType == TxoutType::WITNESS_V1_TAPROOT && !P2SH) {
383
+ sigdata.witness = true ;
384
+ if (solved) {
385
+ sigdata.scriptWitness .stack = std::move (result);
386
+ }
387
+ result.clear ();
252
388
} else if (solved && whichType == TxoutType::WITNESS_UNKNOWN) {
253
389
sigdata.witness = true ;
254
390
}
@@ -414,6 +550,7 @@ class DummySignatureChecker final : public BaseSignatureChecker
414
550
public:
415
551
DummySignatureChecker () {}
416
552
bool CheckECDSASignature (const std::vector<unsigned char >& scriptSig, const std::vector<unsigned char >& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override { return true ; }
553
+ bool CheckSchnorrSignature (Span<const unsigned char > sig, Span<const unsigned char > pubkey, SigVersion sigversion, const ScriptExecutionData& execdata, ScriptError* serror) const override { return true ; }
417
554
};
418
555
const DummySignatureChecker DUMMY_CHECKER;
419
556
@@ -439,6 +576,11 @@ class DummySignatureCreator final : public BaseSignatureCreator {
439
576
vchSig[6 + m_r_len + m_s_len] = SIGHASH_ALL;
440
577
return true ;
441
578
}
579
+ bool CreateSchnorrSig (const SigningProvider& provider, std::vector<unsigned char >& sig, const XOnlyPubKey& pubkey, const uint256* leaf_hash, const uint256* tweak, SigVersion sigversion) const override
580
+ {
581
+ sig.assign (64 , ' \000 ' );
582
+ return true ;
583
+ }
442
584
};
443
585
444
586
}
0 commit comments