@@ -126,6 +126,9 @@ struct PSBTInput
126
126
127
127
template <typename Stream>
128
128
inline void Unserialize (Stream& s) {
129
+ // Used for duplicate key detection
130
+ std::set<std::vector<unsigned char >> key_lookup;
131
+
129
132
// Read loop
130
133
bool found_sep = false ;
131
134
while (!s.empty ()) {
@@ -147,7 +150,7 @@ struct PSBTInput
147
150
switch (type) {
148
151
case PSBT_IN_NON_WITNESS_UTXO:
149
152
{
150
- if (non_witness_utxo ) {
153
+ if (!key_lookup. emplace (key). second ) {
151
154
throw std::ios_base::failure (" Duplicate Key, input non-witness utxo already provided" );
152
155
} else if (key.size () != 1 ) {
153
156
throw std::ios_base::failure (" Non-witness utxo key is more than one byte type" );
@@ -158,7 +161,7 @@ struct PSBTInput
158
161
break ;
159
162
}
160
163
case PSBT_IN_WITNESS_UTXO:
161
- if (!witness_utxo. IsNull () ) {
164
+ if (!key_lookup. emplace (key). second ) {
162
165
throw std::ios_base::failure (" Duplicate Key, input witness utxo already provided" );
163
166
} else if (key.size () != 1 ) {
164
167
throw std::ios_base::failure (" Witness utxo key is more than one byte type" );
@@ -189,7 +192,7 @@ struct PSBTInput
189
192
break ;
190
193
}
191
194
case PSBT_IN_SIGHASH:
192
- if (sighash_type > 0 ) {
195
+ if (!key_lookup. emplace (key). second ) {
193
196
throw std::ios_base::failure (" Duplicate Key, input sighash type already provided" );
194
197
} else if (key.size () != 1 ) {
195
198
throw std::ios_base::failure (" Sighash type key is more than one byte type" );
@@ -198,7 +201,7 @@ struct PSBTInput
198
201
break ;
199
202
case PSBT_IN_REDEEMSCRIPT:
200
203
{
201
- if (!redeem_script. empty () ) {
204
+ if (!key_lookup. emplace (key). second ) {
202
205
throw std::ios_base::failure (" Duplicate Key, input redeemScript already provided" );
203
206
} else if (key.size () != 1 ) {
204
207
throw std::ios_base::failure (" Input redeemScript key is more than one byte type" );
@@ -208,7 +211,7 @@ struct PSBTInput
208
211
}
209
212
case PSBT_IN_WITNESSSCRIPT:
210
213
{
211
- if (!witness_script. empty () ) {
214
+ if (!key_lookup. emplace (key). second ) {
212
215
throw std::ios_base::failure (" Duplicate Key, input witnessScript already provided" );
213
216
} else if (key.size () != 1 ) {
214
217
throw std::ios_base::failure (" Input witnessScript key is more than one byte type" );
@@ -223,7 +226,7 @@ struct PSBTInput
223
226
}
224
227
case PSBT_IN_SCRIPTSIG:
225
228
{
226
- if (!final_script_sig. empty () ) {
229
+ if (!key_lookup. emplace (key). second ) {
227
230
throw std::ios_base::failure (" Duplicate Key, input final scriptSig already provided" );
228
231
} else if (key.size () != 1 ) {
229
232
throw std::ios_base::failure (" Final scriptSig key is more than one byte type" );
@@ -233,7 +236,7 @@ struct PSBTInput
233
236
}
234
237
case PSBT_IN_SCRIPTWITNESS:
235
238
{
236
- if (!final_script_witness. IsNull () ) {
239
+ if (!key_lookup. emplace (key). second ) {
237
240
throw std::ios_base::failure (" Duplicate Key, input final scriptWitness already provided" );
238
241
} else if (key.size () != 1 ) {
239
242
throw std::ios_base::failure (" Final scriptWitness key is more than one byte type" );
@@ -309,6 +312,9 @@ struct PSBTOutput
309
312
310
313
template <typename Stream>
311
314
inline void Unserialize (Stream& s) {
315
+ // Used for duplicate key detection
316
+ std::set<std::vector<unsigned char >> key_lookup;
317
+
312
318
// Read loop
313
319
bool found_sep = false ;
314
320
while (!s.empty ()) {
@@ -330,7 +336,7 @@ struct PSBTOutput
330
336
switch (type) {
331
337
case PSBT_OUT_REDEEMSCRIPT:
332
338
{
333
- if (!redeem_script. empty () ) {
339
+ if (!key_lookup. emplace (key). second ) {
334
340
throw std::ios_base::failure (" Duplicate Key, output redeemScript already provided" );
335
341
} else if (key.size () != 1 ) {
336
342
throw std::ios_base::failure (" Output redeemScript key is more than one byte type" );
@@ -340,7 +346,7 @@ struct PSBTOutput
340
346
}
341
347
case PSBT_OUT_WITNESSSCRIPT:
342
348
{
343
- if (!witness_script. empty () ) {
349
+ if (!key_lookup. emplace (key). second ) {
344
350
throw std::ios_base::failure (" Duplicate Key, output witnessScript already provided" );
345
351
} else if (key.size () != 1 ) {
346
352
throw std::ios_base::failure (" Output witnessScript key is more than one byte type" );
@@ -448,6 +454,9 @@ struct PartiallySignedTransaction
448
454
throw std::ios_base::failure (" Invalid PSBT magic bytes" );
449
455
}
450
456
457
+ // Used for duplicate key detection
458
+ std::set<std::vector<unsigned char >> key_lookup;
459
+
451
460
// Read global data
452
461
bool found_sep = false ;
453
462
while (!s.empty ()) {
@@ -469,7 +478,7 @@ struct PartiallySignedTransaction
469
478
switch (type) {
470
479
case PSBT_GLOBAL_UNSIGNED_TX:
471
480
{
472
- if (tx ) {
481
+ if (!key_lookup. emplace (key). second ) {
473
482
throw std::ios_base::failure (" Duplicate Key, unsigned tx already provided" );
474
483
} else if (key.size () != 1 ) {
475
484
throw std::ios_base::failure (" Global unsigned tx key is more than one byte type" );
0 commit comments