@@ -78,8 +78,16 @@ static int AppInitRawTx(int argc, char* argv[])
78
78
strUsage += HelpMessageOpt (" locktime=N" , _ (" Set TX lock time to N" ));
79
79
strUsage += HelpMessageOpt (" nversion=N" , _ (" Set TX version to N" ));
80
80
strUsage += HelpMessageOpt (" outaddr=VALUE:ADDRESS" , _ (" Add address-based output to TX" ));
81
+ strUsage += HelpMessageOpt (" outpubkey=VALUE:PUBKEY[:FLAGS]" , _ (" Add pay-to-pubkey output to TX" ) + " . " +
82
+ _ (" Optionally add the \" W\" flag to produce a pay-to-witness-pubkey-hash output" ) + " . " +
83
+ _ (" Optionally add the \" S\" flag to wrap the output in a pay-to-script-hash." ));
81
84
strUsage += HelpMessageOpt (" outdata=[VALUE:]DATA" , _ (" Add data-based output to TX" ));
82
- strUsage += HelpMessageOpt (" outscript=VALUE:SCRIPT" , _ (" Add raw script output to TX" ));
85
+ strUsage += HelpMessageOpt (" outscript=VALUE:SCRIPT[:FLAGS]" , _ (" Add raw script output to TX" ) + " . " +
86
+ _ (" Optionally add the \" W\" flag to produce a pay-to-witness-script-hash output" ) + " . " +
87
+ _ (" Optionally add the \" S\" flag to wrap the output in a pay-to-script-hash." ));
88
+ strUsage += HelpMessageOpt (" outmultisig=VALUE:REQUIRED:PUBKEYS:PUBKEY1:PUBKEY2:....[:FLAGS]" , _ (" Add Pay To n-of-m Multi-sig output to TX. n = REQUIRED, m = PUBKEYS" ) + " . " +
89
+ _ (" Optionally add the \" W\" flag to produce a pay-to-witness-script-hash output" ) + " . " +
90
+ _ (" Optionally add the \" S\" flag to wrap the output in a pay-to-script-hash." ));
83
91
strUsage += HelpMessageOpt (" sign=SIGHASH-FLAGS" , _ (" Add zero or more signatures to transaction" ) + " . " +
84
92
_ (" This command requires JSON registers:" ) +
85
93
_ (" prevtxs=JSON object" ) + " , " +
@@ -168,6 +176,14 @@ static void RegisterLoad(const std::string& strInput)
168
176
RegisterSetJson (key, valStr);
169
177
}
170
178
179
+ static CAmount ExtractAndValidateValue (const std::string& strValue)
180
+ {
181
+ CAmount value;
182
+ if (!ParseMoney (strValue, value))
183
+ throw std::runtime_error (" invalid TX output value" );
184
+ return value;
185
+ }
186
+
171
187
static void MutateTxVersion (CMutableTransaction& tx, const std::string& cmdVal)
172
188
{
173
189
int64_t newVersion = atoi64 (cmdVal);
@@ -222,25 +238,18 @@ static void MutateTxAddInput(CMutableTransaction& tx, const std::string& strInpu
222
238
223
239
static void MutateTxAddOutAddr (CMutableTransaction& tx, const std::string& strInput)
224
240
{
225
- // separate VALUE:ADDRESS in string
226
- size_t pos = strInput.find (' :' );
227
- if ((pos == std::string::npos) ||
228
- (pos == 0 ) ||
229
- (pos == (strInput.size () - 1 )))
230
- throw std::runtime_error (" TX output missing separator" );
241
+ // Separate into VALUE:ADDRESS
242
+ std::vector<std::string> vStrInputParts;
243
+ boost::split (vStrInputParts, strInput, boost::is_any_of (" :" ));
231
244
232
- // extract and validate VALUE
233
- std::string strValue = strInput.substr (0 , pos);
234
- CAmount value;
235
- if (!ParseMoney (strValue, value))
236
- throw std::runtime_error (" invalid TX output value" );
245
+ // Extract and validate VALUE
246
+ CAmount value = ExtractAndValidateValue (vStrInputParts[0 ]);
237
247
238
248
// extract and validate ADDRESS
239
- std::string strAddr = strInput. substr (pos + 1 , std::string::npos) ;
249
+ std::string strAddr = vStrInputParts[ 1 ] ;
240
250
CBitcoinAddress addr (strAddr);
241
251
if (!addr.IsValid ())
242
252
throw std::runtime_error (" invalid TX output address" );
243
-
244
253
// build standard output script via GetScriptForDestination()
245
254
CScript scriptPubKey = GetScriptForDestination (addr.Get ());
246
255
@@ -249,6 +258,114 @@ static void MutateTxAddOutAddr(CMutableTransaction& tx, const std::string& strIn
249
258
tx.vout .push_back (txout);
250
259
}
251
260
261
+ static void MutateTxAddOutPubKey (CMutableTransaction& tx, const std::string& strInput)
262
+ {
263
+ // Separate into VALUE:PUBKEY[:FLAGS]
264
+ std::vector<std::string> vStrInputParts;
265
+ boost::split (vStrInputParts, strInput, boost::is_any_of (" :" ));
266
+
267
+ // Extract and validate VALUE
268
+ CAmount value = ExtractAndValidateValue (vStrInputParts[0 ]);
269
+
270
+ // Extract and validate PUBKEY
271
+ CPubKey pubkey (ParseHex (vStrInputParts[1 ]));
272
+ if (!pubkey.IsFullyValid ())
273
+ throw std::runtime_error (" invalid TX output pubkey" );
274
+ CScript scriptPubKey = GetScriptForRawPubKey (pubkey);
275
+ CBitcoinAddress addr (scriptPubKey);
276
+
277
+ // Extract and validate FLAGS
278
+ bool bSegWit = false ;
279
+ bool bScriptHash = false ;
280
+ if (vStrInputParts.size () == 3 ) {
281
+ std::string flags = vStrInputParts[2 ];
282
+ bSegWit = (flags.find (" W" ) != std::string::npos);
283
+ bScriptHash = (flags.find (" S" ) != std::string::npos);
284
+ }
285
+
286
+ if (bSegWit) {
287
+ // Call GetScriptForWitness() to build a P2WSH scriptPubKey
288
+ scriptPubKey = GetScriptForWitness (scriptPubKey);
289
+ }
290
+ if (bScriptHash) {
291
+ // Get the address for the redeem script, then call
292
+ // GetScriptForDestination() to construct a P2SH scriptPubKey.
293
+ CBitcoinAddress redeemScriptAddr (scriptPubKey);
294
+ scriptPubKey = GetScriptForDestination (redeemScriptAddr.Get ());
295
+ }
296
+
297
+ // construct TxOut, append to transaction output list
298
+ CTxOut txout (value, scriptPubKey);
299
+ tx.vout .push_back (txout);
300
+ }
301
+
302
+ static void MutateTxAddOutMultiSig (CMutableTransaction& tx, const std::string& strInput)
303
+ {
304
+ // Separate into VALUE:REQUIRED:NUMKEYS:PUBKEY1:PUBKEY2:....[:FLAGS]
305
+ std::vector<std::string> vStrInputParts;
306
+ boost::split (vStrInputParts, strInput, boost::is_any_of (" :" ));
307
+
308
+ // Check that there are enough parameters
309
+ if (vStrInputParts.size ()<3 )
310
+ throw std::runtime_error (" Not enough multisig parameters" );
311
+
312
+ // Extract and validate VALUE
313
+ CAmount value = ExtractAndValidateValue (vStrInputParts[0 ]);
314
+
315
+ // Extract REQUIRED
316
+ uint32_t required = stoul (vStrInputParts[1 ]);
317
+
318
+ // Extract NUMKEYS
319
+ uint32_t numkeys = stoul (vStrInputParts[2 ]);
320
+
321
+ // Validate there are the correct number of pubkeys
322
+ if (vStrInputParts.size () < numkeys + 3 )
323
+ throw std::runtime_error (" incorrect number of multisig pubkeys" );
324
+
325
+ if (required < 1 || required > 20 || numkeys < 1 || numkeys > 20 || numkeys < required)
326
+ throw std::runtime_error (" multisig parameter mismatch. Required " \
327
+ + std::to_string (required) + " of " + std::to_string (numkeys) + " signatures." );
328
+
329
+ // extract and validate PUBKEYs
330
+ std::vector<CPubKey> pubkeys;
331
+ for (int pos = 1 ; pos <= int (numkeys); pos++) {
332
+ CPubKey pubkey (ParseHex (vStrInputParts[pos + 2 ]));
333
+ if (!pubkey.IsFullyValid ())
334
+ throw std::runtime_error (" invalid TX output pubkey" );
335
+ pubkeys.push_back (pubkey);
336
+ }
337
+
338
+ // Extract FLAGS
339
+ bool bSegWit = false ;
340
+ bool bScriptHash = false ;
341
+ if (vStrInputParts.size () == numkeys + 4 ) {
342
+ std::string flags = vStrInputParts.back ();
343
+ bSegWit = (flags.find (" W" ) != std::string::npos);
344
+ bScriptHash = (flags.find (" S" ) != std::string::npos);
345
+ }
346
+ else if (vStrInputParts.size () > numkeys + 4 ) {
347
+ // Validate that there were no more parameters passed
348
+ throw std::runtime_error (" Too many parameters" );
349
+ }
350
+
351
+ CScript scriptPubKey = GetScriptForMultisig (required, pubkeys);
352
+
353
+ if (bSegWit) {
354
+ // Call GetScriptForWitness() to build a P2WSH scriptPubKey
355
+ scriptPubKey = GetScriptForWitness (scriptPubKey);
356
+ }
357
+ if (bScriptHash) {
358
+ // Get the address for the redeem script, then call
359
+ // GetScriptForDestination() to construct a P2SH scriptPubKey.
360
+ CBitcoinAddress addr (scriptPubKey);
361
+ scriptPubKey = GetScriptForDestination (addr.Get ());
362
+ }
363
+
364
+ // construct TxOut, append to transaction output list
365
+ CTxOut txout (value, scriptPubKey);
366
+ tx.vout .push_back (txout);
367
+ }
368
+
252
369
static void MutateTxAddOutData (CMutableTransaction& tx, const std::string& strInput)
253
370
{
254
371
CAmount value = 0 ;
@@ -260,10 +377,8 @@ static void MutateTxAddOutData(CMutableTransaction& tx, const std::string& strIn
260
377
throw std::runtime_error (" TX output value not specified" );
261
378
262
379
if (pos != std::string::npos) {
263
- // extract and validate VALUE
264
- std::string strValue = strInput.substr (0 , pos);
265
- if (!ParseMoney (strValue, value))
266
- throw std::runtime_error (" invalid TX output value" );
380
+ // Extract and validate VALUE
381
+ value = ExtractAndValidateValue (strInput.substr (0 , pos));
267
382
}
268
383
269
384
// extract and validate DATA
@@ -280,21 +395,35 @@ static void MutateTxAddOutData(CMutableTransaction& tx, const std::string& strIn
280
395
281
396
static void MutateTxAddOutScript (CMutableTransaction& tx, const std::string& strInput)
282
397
{
283
- // separate VALUE:SCRIPT in string
284
- size_t pos = strInput. find ( ' : ' ) ;
285
- if ((pos == std::string::npos) ||
286
- (pos == 0 ) )
398
+ // separate VALUE:SCRIPT[:FLAGS]
399
+ std::vector<std::string> vStrInputParts ;
400
+ boost::split (vStrInputParts, strInput, boost::is_any_of ( " : " ));
401
+ if (vStrInputParts. size () < 2 )
287
402
throw std::runtime_error (" TX output missing separator" );
288
403
289
- // extract and validate VALUE
290
- std::string strValue = strInput.substr (0 , pos);
291
- CAmount value;
292
- if (!ParseMoney (strValue, value))
293
- throw std::runtime_error (" invalid TX output value" );
404
+ // Extract and validate VALUE
405
+ CAmount value = ExtractAndValidateValue (vStrInputParts[0 ]);
294
406
295
407
// extract and validate script
296
- std::string strScript = strInput.substr (pos + 1 , std::string::npos);
297
- CScript scriptPubKey = ParseScript (strScript); // throws on err
408
+ std::string strScript = vStrInputParts[1 ];
409
+ CScript scriptPubKey = ParseScript (strScript);
410
+
411
+ // Extract FLAGS
412
+ bool bSegWit = false ;
413
+ bool bScriptHash = false ;
414
+ if (vStrInputParts.size () == 3 ) {
415
+ std::string flags = vStrInputParts.back ();
416
+ bSegWit = (flags.find (" W" ) != std::string::npos);
417
+ bScriptHash = (flags.find (" S" ) != std::string::npos);
418
+ }
419
+
420
+ if (bSegWit) {
421
+ scriptPubKey = GetScriptForWitness (scriptPubKey);
422
+ }
423
+ if (bScriptHash) {
424
+ CBitcoinAddress addr (scriptPubKey);
425
+ scriptPubKey = GetScriptForDestination (addr.Get ());
426
+ }
298
427
299
428
// construct TxOut, append to transaction output list
300
429
CTxOut txout (value, scriptPubKey);
@@ -538,10 +667,14 @@ static void MutateTx(CMutableTransaction& tx, const std::string& command,
538
667
MutateTxDelOutput (tx, commandVal);
539
668
else if (command == " outaddr" )
540
669
MutateTxAddOutAddr (tx, commandVal);
541
- else if (command == " outdata" )
542
- MutateTxAddOutData (tx, commandVal);
670
+ else if (command == " outpubkey" )
671
+ MutateTxAddOutPubKey (tx, commandVal);
672
+ else if (command == " outmultisig" )
673
+ MutateTxAddOutMultiSig (tx, commandVal);
543
674
else if (command == " outscript" )
544
675
MutateTxAddOutScript (tx, commandVal);
676
+ else if (command == " outdata" )
677
+ MutateTxAddOutData (tx, commandVal);
545
678
546
679
else if (command == " sign" ) {
547
680
if (!ecc) { ecc.reset (new Secp256k1Init ()); }
0 commit comments