]> Git Repo - VerusCoin.git/blame - src/bitcoin-tx.cpp
Remove references to X11 licence
[VerusCoin.git] / src / bitcoin-tx.cpp
CommitLineData
cbe39a38 1// Copyright (c) 2009-2014 The Bitcoin developers
78253fcb 2// Distributed under the MIT software license, see the accompanying
cbe39a38
JG
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#include "base58.h"
71697f97 6#include "clientversion.h"
afd4b94b 7#include "primitives/block.h" // for MAX_BLOCK_SIZE
d2270111 8#include "primitives/transaction.h"
611116d4 9#include "core_io.h"
afd4b94b 10#include "coins.h"
cbe39a38 11#include "keystore.h"
c4408a6c 12#include "script/script.h"
e088d65a 13#include "script/sign.h"
cbe39a38
JG
14#include "ui_interface.h" // for _(...)
15#include "univalue/univalue.h"
611116d4 16#include "util.h"
afd4b94b 17#include "utilstrencodings.h"
611116d4 18#include "utilmoneystr.h"
cbe39a38
JG
19
20#include <stdio.h>
611116d4 21
fb14452c 22#include <boost/algorithm/string.hpp>
611116d4 23#include <boost/assign/list_of.hpp>
cbe39a38 24
cbe39a38 25using namespace boost::assign;
611116d4 26using namespace std;
cbe39a38
JG
27
28static bool fCreateBlank;
29static map<string,UniValue> registers;
30CClientUIInterface uiInterface;
31
32static bool AppInitRawTx(int argc, char* argv[])
33{
34 //
35 // Parameters
36 //
37 ParseParameters(argc, argv);
38
39 // Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
40 if (!SelectParamsFromCommandLine()) {
41 fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n");
42 return false;
43 }
44
45 fCreateBlank = GetBoolArg("-create", false);
46
47 if (argc<2 || mapArgs.count("-?") || mapArgs.count("-help"))
48 {
49 // First part of help message is specific to this utility
50 std::string strUsage = _("Bitcoin Core bitcoin-tx utility version") + " " + FormatFullVersion() + "\n\n" +
51 _("Usage:") + "\n" +
52 " bitcoin-tx [options] <hex-tx> [commands] " + _("Update hex-encoded bitcoin transaction") + "\n" +
53 " bitcoin-tx [options] -create [commands] " + _("Create hex-encoded bitcoin transaction") + "\n" +
54 "\n";
55
56 fprintf(stdout, "%s", strUsage.c_str());
57
58 strUsage = _("Options:") + "\n";
59 strUsage += " -? " + _("This help message") + "\n";
60 strUsage += " -create " + _("Create new, empty TX.") + "\n";
61 strUsage += " -json " + _("Select JSON output") + "\n";
84877904 62 strUsage += " -txid " + _("Output only the hex-encoded transaction id of the resultant transaction.") + "\n";
cbe39a38
JG
63 strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be solved instantly.") + "\n";
64 strUsage += " -testnet " + _("Use the test network") + "\n";
65 strUsage += "\n";
66
67 fprintf(stdout, "%s", strUsage.c_str());
68
69
70 strUsage = _("Commands:") + "\n";
71 strUsage += " delin=N " + _("Delete input N from TX") + "\n";
72 strUsage += " delout=N " + _("Delete output N from TX") + "\n";
73 strUsage += " in=TXID:VOUT " + _("Add input to TX") + "\n";
74 strUsage += " locktime=N " + _("Set TX lock time to N") + "\n";
75 strUsage += " nversion=N " + _("Set TX version to N") + "\n";
76 strUsage += " outaddr=VALUE:ADDRESS " + _("Add address-based output to TX") + "\n";
77 strUsage += " outscript=VALUE:SCRIPT " + _("Add raw script output to TX") + "\n";
78 strUsage += " sign=SIGHASH-FLAGS " + _("Add zero or more signatures to transaction") + "\n";
79 strUsage += " This command requires JSON registers:\n";
80 strUsage += " prevtxs=JSON object\n";
81 strUsage += " privatekeys=JSON object\n";
82 strUsage += " See signrawtransaction docs for format of sighash flags, JSON objects.\n";
83 strUsage += "\n";
84 fprintf(stdout, "%s", strUsage.c_str());
85
86 strUsage = _("Register Commands:") + "\n";
87 strUsage += " load=NAME:FILENAME " + _("Load JSON file FILENAME into register NAME") + "\n";
88 strUsage += " set=NAME:JSON-STRING " + _("Set register NAME to given JSON-STRING") + "\n";
89 strUsage += "\n";
90 fprintf(stdout, "%s", strUsage.c_str());
91
92 return false;
93 }
94 return true;
95}
96
97static void RegisterSetJson(const string& key, const string& rawJson)
98{
99 UniValue val;
100 if (!val.read(rawJson)) {
101 string strErr = "Cannot parse JSON for key " + key;
102 throw runtime_error(strErr);
103 }
104
105 registers[key] = val;
106}
107
108static void RegisterSet(const string& strInput)
109{
110 // separate NAME:VALUE in string
111 size_t pos = strInput.find(':');
112 if ((pos == string::npos) ||
113 (pos == 0) ||
114 (pos == (strInput.size() - 1)))
115 throw runtime_error("Register input requires NAME:VALUE");
116
117 string key = strInput.substr(0, pos);
118 string valStr = strInput.substr(pos + 1, string::npos);
119
120 RegisterSetJson(key, valStr);
121}
122
123static void RegisterLoad(const string& strInput)
124{
125 // separate NAME:FILENAME in string
126 size_t pos = strInput.find(':');
127 if ((pos == string::npos) ||
128 (pos == 0) ||
129 (pos == (strInput.size() - 1)))
130 throw runtime_error("Register load requires NAME:FILENAME");
131
132 string key = strInput.substr(0, pos);
133 string filename = strInput.substr(pos + 1, string::npos);
134
135 FILE *f = fopen(filename.c_str(), "r");
136 if (!f) {
137 string strErr = "Cannot open file " + filename;
138 throw runtime_error(strErr);
139 }
140
141 // load file chunks into one big buffer
142 string valStr;
143 while ((!feof(f)) && (!ferror(f))) {
144 char buf[4096];
145 int bread = fread(buf, 1, sizeof(buf), f);
146 if (bread <= 0)
147 break;
148
149 valStr.insert(valStr.size(), buf, bread);
150 }
151
152 if (ferror(f)) {
153 string strErr = "Error reading file " + filename;
154 throw runtime_error(strErr);
155 }
156
157 fclose(f);
158
159 // evaluate as JSON buffer register
160 RegisterSetJson(key, valStr);
161}
162
163static void MutateTxVersion(CMutableTransaction& tx, const string& cmdVal)
164{
165 int64_t newVersion = atoi64(cmdVal);
166 if (newVersion < 1 || newVersion > CTransaction::CURRENT_VERSION)
167 throw runtime_error("Invalid TX version requested");
168
169 tx.nVersion = (int) newVersion;
170}
171
172static void MutateTxLocktime(CMutableTransaction& tx, const string& cmdVal)
173{
174 int64_t newLocktime = atoi64(cmdVal);
175 if (newLocktime < 0LL || newLocktime > 0xffffffffLL)
176 throw runtime_error("Invalid TX locktime requested");
177
178 tx.nLockTime = (unsigned int) newLocktime;
179}
180
181static void MutateTxAddInput(CMutableTransaction& tx, const string& strInput)
182{
183 // separate TXID:VOUT in string
184 size_t pos = strInput.find(':');
185 if ((pos == string::npos) ||
186 (pos == 0) ||
187 (pos == (strInput.size() - 1)))
188 throw runtime_error("TX input missing separator");
189
190 // extract and validate TXID
191 string strTxid = strInput.substr(0, pos);
192 if ((strTxid.size() != 64) || !IsHex(strTxid))
193 throw runtime_error("invalid TX input txid");
194 uint256 txid(strTxid);
195
196 static const unsigned int minTxOutSz = 9;
197 static const unsigned int maxVout = MAX_BLOCK_SIZE / minTxOutSz;
198
199 // extract and validate vout
200 string strVout = strInput.substr(pos + 1, string::npos);
201 int vout = atoi(strVout);
202 if ((vout < 0) || (vout > (int)maxVout))
203 throw runtime_error("invalid TX input vout");
204
205 // append to transaction input list
206 CTxIn txin(txid, vout);
207 tx.vin.push_back(txin);
208}
209
210static void MutateTxAddOutAddr(CMutableTransaction& tx, const string& strInput)
211{
212 // separate VALUE:ADDRESS in string
213 size_t pos = strInput.find(':');
214 if ((pos == string::npos) ||
215 (pos == 0) ||
216 (pos == (strInput.size() - 1)))
217 throw runtime_error("TX output missing separator");
218
219 // extract and validate VALUE
220 string strValue = strInput.substr(0, pos);
a372168e 221 CAmount value;
cbe39a38
JG
222 if (!ParseMoney(strValue, value))
223 throw runtime_error("invalid TX output value");
224
225 // extract and validate ADDRESS
226 string strAddr = strInput.substr(pos + 1, string::npos);
227 CBitcoinAddress addr(strAddr);
228 if (!addr.IsValid())
229 throw runtime_error("invalid TX output address");
230
0be990ba
PW
231 // build standard output script via GetScriptForDestination()
232 CScript scriptPubKey = GetScriptForDestination(addr.Get());
cbe39a38
JG
233
234 // construct TxOut, append to transaction output list
235 CTxOut txout(value, scriptPubKey);
236 tx.vout.push_back(txout);
237}
238
239static void MutateTxAddOutScript(CMutableTransaction& tx, const string& strInput)
240{
241 // separate VALUE:SCRIPT in string
242 size_t pos = strInput.find(':');
243 if ((pos == string::npos) ||
15ef1b90 244 (pos == 0))
cbe39a38
JG
245 throw runtime_error("TX output missing separator");
246
247 // extract and validate VALUE
248 string strValue = strInput.substr(0, pos);
a372168e 249 CAmount value;
cbe39a38
JG
250 if (!ParseMoney(strValue, value))
251 throw runtime_error("invalid TX output value");
252
253 // extract and validate script
254 string strScript = strInput.substr(pos + 1, string::npos);
255 CScript scriptPubKey = ParseScript(strScript); // throws on err
256
257 // construct TxOut, append to transaction output list
258 CTxOut txout(value, scriptPubKey);
259 tx.vout.push_back(txout);
260}
261
262static void MutateTxDelInput(CMutableTransaction& tx, const string& strInIdx)
263{
264 // parse requested deletion index
265 int inIdx = atoi(strInIdx);
266 if (inIdx < 0 || inIdx >= (int)tx.vin.size()) {
267 string strErr = "Invalid TX input index '" + strInIdx + "'";
268 throw runtime_error(strErr.c_str());
269 }
270
271 // delete input from transaction
272 tx.vin.erase(tx.vin.begin() + inIdx);
273}
274
275static void MutateTxDelOutput(CMutableTransaction& tx, const string& strOutIdx)
276{
277 // parse requested deletion index
278 int outIdx = atoi(strOutIdx);
279 if (outIdx < 0 || outIdx >= (int)tx.vout.size()) {
280 string strErr = "Invalid TX output index '" + strOutIdx + "'";
281 throw runtime_error(strErr.c_str());
282 }
283
284 // delete output from transaction
285 tx.vout.erase(tx.vout.begin() + outIdx);
286}
287
288static const unsigned int N_SIGHASH_OPTS = 6;
289static const struct {
290 const char *flagStr;
291 int flags;
292} sighashOptions[N_SIGHASH_OPTS] = {
616c2430
CF
293 {"ALL", SIGHASH_ALL},
294 {"NONE", SIGHASH_NONE},
295 {"SINGLE", SIGHASH_SINGLE},
296 {"ALL|ANYONECANPAY", SIGHASH_ALL|SIGHASH_ANYONECANPAY},
297 {"NONE|ANYONECANPAY", SIGHASH_NONE|SIGHASH_ANYONECANPAY},
298 {"SINGLE|ANYONECANPAY", SIGHASH_SINGLE|SIGHASH_ANYONECANPAY},
cbe39a38
JG
299};
300
301static bool findSighashFlags(int& flags, const string& flagStr)
302{
303 flags = 0;
304
305 for (unsigned int i = 0; i < N_SIGHASH_OPTS; i++) {
306 if (flagStr == sighashOptions[i].flagStr) {
307 flags = sighashOptions[i].flags;
308 return true;
309 }
310 }
311
312 return false;
313}
314
315uint256 ParseHashUO(map<string,UniValue>& o, string strKey)
316{
317 if (!o.count(strKey))
318 return 0;
319 return ParseHashUV(o[strKey], strKey);
320}
321
322vector<unsigned char> ParseHexUO(map<string,UniValue>& o, string strKey)
323{
324 if (!o.count(strKey)) {
325 vector<unsigned char> emptyVec;
326 return emptyVec;
327 }
328 return ParseHexUV(o[strKey], strKey);
329}
330
331static void MutateTxSign(CMutableTransaction& tx, const string& flagStr)
332{
333 int nHashType = SIGHASH_ALL;
334
335 if (flagStr.size() > 0)
336 if (!findSighashFlags(nHashType, flagStr))
337 throw runtime_error("unknown sighash flag/sign option");
338
339 vector<CTransaction> txVariants;
340 txVariants.push_back(tx);
341
342 // mergedTx will end up with all the signatures; it
343 // starts as a clone of the raw tx:
344 CMutableTransaction mergedTx(txVariants[0]);
345 bool fComplete = true;
346 CCoinsView viewDummy;
7c70438d 347 CCoinsViewCache view(&viewDummy);
cbe39a38
JG
348
349 if (!registers.count("privatekeys"))
350 throw runtime_error("privatekeys register variable must be set.");
351 bool fGivenKeys = false;
352 CBasicKeyStore tempKeystore;
353 UniValue keysObj = registers["privatekeys"];
354 fGivenKeys = true;
355
356 for (unsigned int kidx = 0; kidx < keysObj.count(); kidx++) {
357 if (!keysObj[kidx].isStr())
358 throw runtime_error("privatekey not a string");
359 CBitcoinSecret vchSecret;
360 bool fGood = vchSecret.SetString(keysObj[kidx].getValStr());
361 if (!fGood)
362 throw runtime_error("privatekey not valid");
363
364 CKey key = vchSecret.GetKey();
365 tempKeystore.AddKey(key);
366 }
367
368 // Add previous txouts given in the RPC call:
369 if (!registers.count("prevtxs"))
370 throw runtime_error("prevtxs register variable must be set.");
371 UniValue prevtxsObj = registers["privatekeys"];
372 {
373 for (unsigned int previdx = 0; previdx < prevtxsObj.count(); previdx++) {
374 UniValue prevOut = prevtxsObj[previdx];
375 if (!prevOut.isObject())
376 throw runtime_error("expected prevtxs internal object");
377
378 map<string,UniValue::VType> types = map_list_of("txid", UniValue::VSTR)("vout",UniValue::VNUM)("scriptPubKey",UniValue::VSTR);
379 if (!prevOut.checkObject(types))
380 throw runtime_error("prevtxs internal object typecheck fail");
381
382 uint256 txid = ParseHashUV(prevOut, "txid");
383
384 int nOut = atoi(prevOut["vout"].getValStr());
385 if (nOut < 0)
386 throw runtime_error("vout must be positive");
387
388 vector<unsigned char> pkData(ParseHexUV(prevOut, "scriptPubKey"));
389 CScript scriptPubKey(pkData.begin(), pkData.end());
390
f28aec01
PW
391 {
392 CCoinsModifier coins = view.ModifyCoins(txid);
393 if (coins->IsAvailable(nOut) && coins->vout[nOut].scriptPubKey != scriptPubKey) {
cbe39a38 394 string err("Previous output scriptPubKey mismatch:\n");
f28aec01 395 err = err + coins->vout[nOut].scriptPubKey.ToString() + "\nvs:\n"+
cbe39a38
JG
396 scriptPubKey.ToString();
397 throw runtime_error(err);
398 }
f28aec01
PW
399 if ((unsigned int)nOut >= coins->vout.size())
400 coins->vout.resize(nOut+1);
401 coins->vout[nOut].scriptPubKey = scriptPubKey;
402 coins->vout[nOut].nValue = 0; // we don't know the actual output value
cbe39a38 403 }
cbe39a38
JG
404
405 // if redeemScript given and private keys given,
406 // add redeemScript to the tempKeystore so it can be signed:
407 if (fGivenKeys && scriptPubKey.IsPayToScriptHash() &&
408 prevOut.exists("redeemScript")) {
409 UniValue v = prevOut["redeemScript"];
410 vector<unsigned char> rsData(ParseHexUV(v, "redeemScript"));
411 CScript redeemScript(rsData.begin(), rsData.end());
412 tempKeystore.AddCScript(redeemScript);
413 }
414 }
415 }
416
417 const CKeyStore& keystore = tempKeystore;
418
419 bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
420
421 // Sign what we can:
422 for (unsigned int i = 0; i < mergedTx.vin.size(); i++) {
423 CTxIn& txin = mergedTx.vin[i];
629d75fa
PW
424 const CCoins* coins = view.AccessCoins(txin.prevout.hash);
425 if (!coins || !coins->IsAvailable(txin.prevout.n)) {
cbe39a38
JG
426 fComplete = false;
427 continue;
428 }
629d75fa 429 const CScript& prevPubKey = coins->vout[txin.prevout.n].scriptPubKey;
cbe39a38
JG
430
431 txin.scriptSig.clear();
432 // Only sign SIGHASH_SINGLE if there's a corresponding output:
433 if (!fHashSingle || (i < mergedTx.vout.size()))
434 SignSignature(keystore, prevPubKey, mergedTx, i, nHashType);
435
436 // ... and merge in other signatures:
437 BOOST_FOREACH(const CTransaction& txv, txVariants) {
438 txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig);
439 }
5c1e798a 440 if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, SignatureChecker(mergedTx, i)))
cbe39a38
JG
441 fComplete = false;
442 }
443
444 if (fComplete) {
445 // do nothing... for now
446 // perhaps store this for later optional JSON output
447 }
448
449 tx = mergedTx;
450}
451
452static void MutateTx(CMutableTransaction& tx, const string& command,
453 const string& commandVal)
454{
455 if (command == "nversion")
456 MutateTxVersion(tx, commandVal);
457 else if (command == "locktime")
458 MutateTxLocktime(tx, commandVal);
459
460 else if (command == "delin")
461 MutateTxDelInput(tx, commandVal);
462 else if (command == "in")
463 MutateTxAddInput(tx, commandVal);
464
465 else if (command == "delout")
466 MutateTxDelOutput(tx, commandVal);
467 else if (command == "outaddr")
468 MutateTxAddOutAddr(tx, commandVal);
469 else if (command == "outscript")
470 MutateTxAddOutScript(tx, commandVal);
471
472 else if (command == "sign")
473 MutateTxSign(tx, commandVal);
474
475 else if (command == "load")
476 RegisterLoad(commandVal);
477
478 else if (command == "set")
479 RegisterSet(commandVal);
480
481 else
482 throw runtime_error("unknown command");
483}
484
485static void OutputTxJSON(const CTransaction& tx)
486{
487 UniValue entry(UniValue::VOBJ);
488 TxToUniv(tx, 0, entry);
489
490 string jsonOutput = entry.write(4);
491 fprintf(stdout, "%s\n", jsonOutput.c_str());
492}
493
84877904 494static void OutputTxHash(const CTransaction& tx)
495{
496 string strHexHash = tx.GetHash().GetHex(); // the hex-encoded transaction hash (aka the transaction id)
497
498 fprintf(stdout, "%s\n", strHexHash.c_str());
499}
500
cbe39a38
JG
501static void OutputTxHex(const CTransaction& tx)
502{
503 string strHex = EncodeHexTx(tx);
504
505 fprintf(stdout, "%s\n", strHex.c_str());
506}
507
508static void OutputTx(const CTransaction& tx)
509{
510 if (GetBoolArg("-json", false))
511 OutputTxJSON(tx);
84877904 512 else if (GetBoolArg("-txid", false))
513 OutputTxHash(tx);
cbe39a38
JG
514 else
515 OutputTxHex(tx);
516}
517
fb14452c
JG
518static string readStdin()
519{
520 char buf[4096];
521 string ret;
522
523 while (!feof(stdin)) {
524 size_t bread = fread(buf, 1, sizeof(buf), stdin);
525 ret.append(buf, bread);
526 if (bread < sizeof(buf))
527 break;
528 }
529
530 if (ferror(stdin))
531 throw runtime_error("error reading stdin");
532
533 boost::algorithm::trim_right(ret);
534
535 return ret;
536}
537
cbe39a38
JG
538static int CommandLineRawTx(int argc, char* argv[])
539{
540 string strPrint;
541 int nRet = 0;
542 try {
fb14452c
JG
543 // Skip switches; Permit common stdin convention "-"
544 while (argc > 1 && IsSwitchChar(argv[1][0]) &&
545 (argv[1][1] != 0)) {
cbe39a38
JG
546 argc--;
547 argv++;
548 }
549
550 CTransaction txDecodeTmp;
551 int startArg;
552
553 if (!fCreateBlank) {
554 // require at least one param
555 if (argc < 2)
556 throw runtime_error("too few parameters");
557
558 // param: hex-encoded bitcoin transaction
559 string strHexTx(argv[1]);
fb14452c
JG
560 if (strHexTx == "-") // "-" implies standard input
561 strHexTx = readStdin();
cbe39a38
JG
562
563 if (!DecodeHexTx(txDecodeTmp, strHexTx))
564 throw runtime_error("invalid transaction encoding");
565
566 startArg = 2;
567 } else
568 startArg = 1;
569
570 CMutableTransaction tx(txDecodeTmp);
571
572 for (int i = startArg; i < argc; i++) {
573 string arg = argv[i];
574 string key, value;
575 size_t eqpos = arg.find('=');
576 if (eqpos == string::npos)
577 key = arg;
578 else {
579 key = arg.substr(0, eqpos);
580 value = arg.substr(eqpos + 1);
581 }
582
583 MutateTx(tx, key, value);
584 }
585
586 OutputTx(tx);
587 }
588
589 catch (boost::thread_interrupted) {
590 throw;
591 }
592 catch (std::exception& e) {
593 strPrint = string("error: ") + e.what();
594 nRet = EXIT_FAILURE;
595 }
596 catch (...) {
597 PrintExceptionContinue(NULL, "CommandLineRawTx()");
598 throw;
599 }
600
601 if (strPrint != "") {
602 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
603 }
604 return nRet;
605}
606
607int main(int argc, char* argv[])
608{
609 SetupEnvironment();
610
611 try {
612 if(!AppInitRawTx(argc, argv))
613 return EXIT_FAILURE;
614 }
615 catch (std::exception& e) {
616 PrintExceptionContinue(&e, "AppInitRawTx()");
617 return EXIT_FAILURE;
618 } catch (...) {
619 PrintExceptionContinue(NULL, "AppInitRawTx()");
620 return EXIT_FAILURE;
621 }
622
623 int ret = EXIT_FAILURE;
624 try {
625 ret = CommandLineRawTx(argc, argv);
626 }
627 catch (std::exception& e) {
628 PrintExceptionContinue(&e, "CommandLineRawTx()");
629 } catch (...) {
630 PrintExceptionContinue(NULL, "CommandLineRawTx()");
631 }
632 return ret;
633}
This page took 0.137935 seconds and 4 git commands to generate.