22 #include <boost/algorithm/string.hpp> 23 #include <boost/assign/list_of.hpp> 45 }
catch (
const std::exception& e) {
46 fprintf(
stderr,
"Error: %s\n", e.what());
55 std::string strUsage =
_(
"Dash Core dash-tx utility version") +
" " +
FormatFullVersion() +
"\n\n" +
57 " dash-tx [options] <hex-tx> [commands] " +
_(
"Update hex-encoded dash transaction") +
"\n" +
58 " dash-tx [options] -create [commands] " +
_(
"Create hex-encoded dash transaction") +
"\n" +
61 fprintf(
stdout,
"%s", strUsage.c_str());
67 strUsage +=
HelpMessageOpt(
"-txid",
_(
"Output only the hex-encoded transaction id of the resultant transaction."));
70 fprintf(
stdout,
"%s", strUsage.c_str());
78 strUsage +=
HelpMessageOpt(
"outaddr=VALUE:ADDRESS",
_(
"Add address-based output to TX"));
79 strUsage +=
HelpMessageOpt(
"outdata=[VALUE:]DATA",
_(
"Add data-based output to TX"));
80 strUsage +=
HelpMessageOpt(
"outscript=VALUE:SCRIPT",
_(
"Add raw script output to TX"));
81 strUsage +=
HelpMessageOpt(
"sign=SIGHASH-FLAGS",
_(
"Add zero or more signatures to transaction") +
". " +
82 _(
"This command requires JSON registers:") +
83 _(
"prevtxs=JSON object") +
", " +
84 _(
"privatekeys=JSON object") +
". " +
85 _(
"See signrawtransaction docs for format of sighash flags, JSON objects."));
86 fprintf(
stdout,
"%s", strUsage.c_str());
89 strUsage +=
HelpMessageOpt(
"load=NAME:FILENAME",
_(
"Load JSON file FILENAME into register NAME"));
90 strUsage +=
HelpMessageOpt(
"set=NAME:JSON-STRING",
_(
"Set register NAME to given JSON-STRING"));
91 fprintf(
stdout,
"%s", strUsage.c_str());
94 fprintf(
stderr,
"Error: too few parameters\n");
105 if (!val.
read(rawJson)) {
106 string strErr =
"Cannot parse JSON for key " +
key;
107 throw runtime_error(strErr);
116 size_t pos = strInput.find(
':');
117 if ((pos == string::npos) ||
119 (pos == (strInput.size() - 1)))
120 throw runtime_error(
"Register input requires NAME:VALUE");
122 string key = strInput.substr(0, pos);
123 string valStr = strInput.substr(pos + 1, string::npos);
131 size_t pos = strInput.find(
':');
132 if ((pos == string::npos) ||
134 (pos == (strInput.size() - 1)))
135 throw runtime_error(
"Register load requires NAME:FILENAME");
137 string key = strInput.substr(0, pos);
138 string filename = strInput.substr(pos + 1, string::npos);
140 FILE *
f = fopen(filename.c_str(),
"r");
142 string strErr =
"Cannot open file " + filename;
143 throw runtime_error(strErr);
148 while ((!feof(
f)) && (!ferror(
f))) {
150 int bread = fread(buf, 1,
sizeof(buf),
f);
154 valStr.insert(valStr.size(), buf, bread);
161 string strErr =
"Error reading file " + filename;
162 throw runtime_error(strErr);
171 int64_t newVersion =
atoi64(cmdVal);
173 throw runtime_error(
"Invalid TX version requested");
180 int64_t newLocktime =
atoi64(cmdVal);
181 if (newLocktime < 0LL || newLocktime > 0xffffffffLL)
182 throw runtime_error(
"Invalid TX locktime requested");
184 tx.
nLockTime = (
unsigned int) newLocktime;
190 size_t pos = strInput.find(
':');
191 if ((pos == string::npos) ||
193 (pos == (strInput.size() - 1)))
194 throw runtime_error(
"TX input missing separator");
197 string strTxid = strInput.substr(0, pos);
198 if ((strTxid.size() != 64) || !
IsHex(strTxid))
199 throw runtime_error(
"invalid TX input txid");
202 static const unsigned int minTxOutSz = 9;
203 static const unsigned int maxVout =
MaxBlockSize(
true) / minTxOutSz;
206 string strVout = strInput.substr(pos + 1, string::npos);
207 int vout =
atoi(strVout);
208 if ((vout < 0) || (vout > (
int)maxVout))
209 throw runtime_error(
"invalid TX input vout");
212 CTxIn txin(txid, vout);
213 tx.
vin.push_back(txin);
219 size_t pos = strInput.find(
':');
220 if ((pos == string::npos) ||
222 (pos == (strInput.size() - 1)))
223 throw runtime_error(
"TX output missing separator");
226 string strValue = strInput.substr(0, pos);
229 throw runtime_error(
"invalid TX output value");
232 string strAddr = strInput.substr(pos + 1, string::npos);
235 throw runtime_error(
"invalid TX output address");
241 CTxOut txout(value, scriptPubKey);
242 tx.
vout.push_back(txout);
250 size_t pos = strInput.find(
':');
253 throw runtime_error(
"TX output value not specified");
255 if (pos != string::npos) {
257 string strValue = strInput.substr(0, pos);
259 throw runtime_error(
"invalid TX output value");
263 string strData = strInput.substr(pos + 1, string::npos);
266 throw runtime_error(
"invalid TX output data");
271 tx.
vout.push_back(txout);
277 size_t pos = strInput.find(
':');
278 if ((pos == string::npos) ||
280 throw runtime_error(
"TX output missing separator");
283 string strValue = strInput.substr(0, pos);
286 throw runtime_error(
"invalid TX output value");
289 string strScript = strInput.substr(pos + 1, string::npos);
293 CTxOut txout(value, scriptPubKey);
294 tx.
vout.push_back(txout);
300 int inIdx =
atoi(strInIdx);
301 if (inIdx < 0 || inIdx >= (
int)tx.
vin.size()) {
302 string strErr =
"Invalid TX input index '" + strInIdx +
"'";
303 throw runtime_error(strErr.c_str());
307 tx.
vin.erase(tx.
vin.begin() + inIdx);
313 int outIdx =
atoi(strOutIdx);
314 if (outIdx < 0 || outIdx >= (
int)tx.
vout.size()) {
315 string strErr =
"Invalid TX output index '" + strOutIdx +
"'";
316 throw runtime_error(strErr.c_str());
320 tx.
vout.erase(tx.
vout.begin() + outIdx);
324 static const struct {
352 if (!o.count(strKey))
357 vector<unsigned char>
ParseHexUO(map<string,UniValue>& o,
string strKey)
359 if (!o.count(strKey)) {
360 vector<unsigned char> emptyVec;
372 throw runtime_error(
"unknown sighash flag/sign option");
374 vector<CTransaction> txVariants;
375 txVariants.push_back(tx);
380 bool fComplete =
true;
385 throw runtime_error(
"privatekeys register variable must be set.");
386 bool fGivenKeys =
false;
391 for (
unsigned int kidx = 0; kidx < keysObj.
size(); kidx++) {
392 if (!keysObj[kidx].isStr())
393 throw runtime_error(
"privatekey not a string");
395 bool fGood = vchSecret.
SetString(keysObj[kidx].getValStr());
397 throw runtime_error(
"privatekey not valid");
405 throw runtime_error(
"prevtxs register variable must be set.");
408 for (
unsigned int previdx = 0; previdx < prevtxsObj.
size(); previdx++) {
409 UniValue prevOut = prevtxsObj[previdx];
411 throw runtime_error(
"expected prevtxs internal object");
415 throw runtime_error(
"prevtxs internal object typecheck fail");
419 int nOut =
atoi(prevOut[
"vout"].getValStr());
421 throw runtime_error(
"vout must be positive");
423 vector<unsigned char> pkData(
ParseHexUV(prevOut[
"scriptPubKey"],
"scriptPubKey"));
424 CScript scriptPubKey(pkData.begin(), pkData.end());
428 if (coins->
IsAvailable(nOut) && coins->
vout[nOut].scriptPubKey != scriptPubKey) {
429 string err(
"Previous output scriptPubKey mismatch:\n");
432 throw runtime_error(
err);
434 if ((
unsigned int)nOut >= coins->
vout.size())
435 coins->
vout.resize(nOut+1);
436 coins->
vout[nOut].scriptPubKey = scriptPubKey;
437 coins->
vout[nOut].nValue = 0;
442 if (fGivenKeys && scriptPubKey.IsPayToScriptHash() &&
443 prevOut.
exists(
"redeemScript")) {
444 UniValue v = prevOut[
"redeemScript"];
445 vector<unsigned char> rsData(
ParseHexUV(v,
"redeemScript"));
446 CScript redeemScript(rsData.begin(), rsData.end());
452 const CKeyStore& keystore = tempKeystore;
457 for (
unsigned int i = 0; i < mergedTx.
vin.size(); i++) {
468 if (!fHashSingle || (i < mergedTx.
vout.size()))
501 const string& commandVal)
503 boost::scoped_ptr<Secp256k1Init> ecc;
505 if (command ==
"nversion")
507 else if (command ==
"locktime")
510 else if (command ==
"delin")
512 else if (command ==
"in")
515 else if (command ==
"delout")
517 else if (command ==
"outaddr")
519 else if (command ==
"outdata")
521 else if (command ==
"outscript")
524 else if (command ==
"sign") {
529 else if (command ==
"load")
532 else if (command ==
"set")
536 throw runtime_error(
"unknown command");
544 string jsonOutput = entry.
write(4);
545 fprintf(
stdout,
"%s\n", jsonOutput.c_str());
552 fprintf(
stdout,
"%s\n", strHexHash.c_str());
559 fprintf(
stdout,
"%s\n", strHex.c_str());
577 while (!feof(stdin)) {
578 size_t bread = fread(buf, 1,
sizeof(buf), stdin);
579 ret.append(buf, bread);
580 if (bread <
sizeof(buf))
585 throw runtime_error(
"error reading stdin");
587 boost::algorithm::trim_right(ret);
610 throw runtime_error(
"too few parameters");
613 string strHexTx(argv[1]);
618 throw runtime_error(
"invalid transaction encoding");
626 for (
int i = startArg; i < argc; i++) {
627 string arg = argv[i];
629 size_t eqpos = arg.find(
'=');
630 if (eqpos == string::npos)
633 key = arg.substr(0, eqpos);
634 value = arg.substr(eqpos + 1);
643 catch (
const boost::thread_interrupted&) {
646 catch (
const std::exception& e) {
647 strPrint = string(
"error: ") + e.what();
655 if (strPrint !=
"") {
656 fprintf((nRet == 0 ?
stdout :
stderr),
"%s\n", strPrint.c_str());
661 int main(
int argc,
char* argv[])
670 catch (
const std::exception& e) {
678 int ret = EXIT_FAILURE;
682 catch (
const std::exception& e) {
std::vector< unsigned char > ParseHexUV(const UniValue &v, const std::string &strName)
bool SetString(const char *pszSecret)
std::string HelpMessageOpt(const std::string &option, const std::string &message)
static const int CONTINUE_EXECUTION
void AppendParamsHelpMessages(std::string &strUsage, bool debugHelp)
static void MutateTxAddOutScript(CMutableTransaction &tx, const string &strInput)
static void MutateTx(CMutableTransaction &tx, const string &command, const string &commandVal)
static const int32_t CURRENT_VERSION
unsigned int MaxBlockSize(bool fDIP0001Active)
vector< unsigned char > ParseHexUO(map< string, UniValue > &o, string strKey)
static void MutateTxSign(CMutableTransaction &tx, const string &flagStr)
bool IsAvailable(unsigned int nPos) const
check whether a particular output is still available
static void MutateTxAddOutData(CMutableTransaction &tx, const string &strInput)
static int AppInitRawTx(int argc, char *argv[])
static void RegisterSet(const string &strInput)
void PrintExceptionContinue(const std::exception *pex, const char *pszThread)
bool IsHex(const string &str)
static void MutateTxVersion(CMutableTransaction &tx, const string &cmdVal)
static void OutputTxJSON(const CTransaction &tx)
static void RegisterLoad(const string &strInput)
static CScript CombineSignatures(const CScript &scriptPubKey, const BaseSignatureChecker &checker, const txnouttype txType, const vector< valtype > &vSolutions, vector< valtype > &sigs1, vector< valtype > &sigs2)
uint256 ParseHashUO(map< string, UniValue > &o, string strKey)
static int CommandLineRawTx(int argc, char *argv[])
static void MutateTxAddOutAddr(CMutableTransaction &tx, const string &strInput)
static bool findSighashFlags(int &flags, const string &flagStr)
std::vector< CTxOut > vout
unspent transaction outputs; spent outputs are .IsNull(); spent outputs at the end of the array are d...
static void MutateTxLocktime(CMutableTransaction &tx, const string &cmdVal)
static map< string, UniValue > registers
static void OutputTxHash(const CTransaction &tx)
bool GetBoolArg(const std::string &strArg, bool fDefault)
std::string ScriptToAsmStr(const CScript &script, const bool fAttemptSighashDecode=false)
void SelectParams(const std::string &network)
uint256 ParseHashUV(const UniValue &v, const std::string &strName)
uint256 uint256S(const char *str)
static bool error(const char *format)
virtual bool AddCScript(const CScript &redeemScript)
Support for BIP 0013 : see https://github.com/bitcoin/bips/blob/master/bip-0013.mediawiki.
bool exists(const std::string &key) const
int main(int argc, char *argv[])
vector< unsigned char > ParseHex(const char *psz)
bool ParseMoney(const string &str, CAmount &nRet)
CCoinsModifier ModifyCoins(const uint256 &txid)
CScript GetScriptForDestination(const CTxDestination &dest)
void ParseParameters(int argc, const char *const argv[])
static void MutateTxDelOutput(CMutableTransaction &tx, const string &strOutIdx)
bool VerifyScript(const CScript &scriptSig, const CScript &scriptPubKey, unsigned int flags, const BaseSignatureChecker &checker, ScriptError *serror)
static const struct @10 sighashOptions[N_SIGHASH_OPTS]
std::string FormatFullVersion()
std::vector< CTxOut > vout
static void MutateTxDelInput(CMutableTransaction &tx, const string &strInIdx)
static void MutateTxAddInput(CMutableTransaction &tx, const string &strInput)
static const unsigned int N_SIGHASH_OPTS
std::string EncodeHexTx(const CTransaction &tx)
const std::vector< CTxIn > vin
CTxDestination Get() const
bool IsSwitchChar(char c)
static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS
static string readStdin()
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
const uint256 & GetHash() const
std::string GetHex() const
std::string ChainNameFromCommandLine()
int64_t atoi64(const char *psz)
void TxToUniv(const CTransaction &tx, const uint256 &hashBlock, UniValue &entry)
virtual bool AddKey(const CKey &key)
bool checkObject(const std::map< std::string, UniValue::VType > &memberTypes)
CScript ParseScript(const std::string &s)
ECCVerifyHandle globalVerifyHandle
bool read(const char *raw)
static void OutputTxHex(const CTransaction &tx)
bool SignSignature(const CKeyStore &keystore, const CScript &fromPubKey, CMutableTransaction &txTo, unsigned int nIn, int nHashType)
std::string HelpMessageGroup(const std::string &message)
static void OutputTx(const CTransaction &tx)
std::string _(const char *psz)
static void RegisterSetJson(const string &key, const string &rawJson)
int atoi(const std::string &str)
map< string, string > mapArgs
bool DecodeHexTx(CTransaction &tx, const std::string &strHexTx)
const CCoins * AccessCoins(const uint256 &txid) const