From efc78837728bebcf2030d1d495018e563eb10c71 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Wed, 20 Aug 2014 09:59:31 -0400 Subject: UniValue: prefer .size() to .count(), to harmonize w/ existing tree --- src/bitcoin-tx.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index c82d4f93a..45990f6bd 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -346,7 +346,7 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) UniValue keysObj = registers["privatekeys"]; fGivenKeys = true; - for (unsigned int kidx = 0; kidx < keysObj.count(); kidx++) { + for (unsigned int kidx = 0; kidx < keysObj.size(); kidx++) { if (!keysObj[kidx].isStr()) throw runtime_error("privatekey not a string"); CBitcoinSecret vchSecret; @@ -363,7 +363,7 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) throw runtime_error("prevtxs register variable must be set."); UniValue prevtxsObj = registers["prevtxs"]; { - for (unsigned int previdx = 0; previdx < prevtxsObj.count(); previdx++) { + for (unsigned int previdx = 0; previdx < prevtxsObj.size(); previdx++) { UniValue prevOut = prevtxsObj[previdx]; if (!prevOut.isObject()) throw runtime_error("expected prevtxs internal object"); -- cgit v1.2.3 From 627b9deff4e8e18fc6d001b6eb9818c13c648820 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Tim=C3=B3n?= Date: Wed, 24 Jun 2015 07:25:30 +0200 Subject: Policy: MOVEONLY: Create policy/policy.h with some constants --- src/bitcoin-tx.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 45990f6bd..9ad57d5c6 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -8,6 +8,7 @@ #include "consensus/consensus.h" #include "core_io.h" #include "keystore.h" +#include "policy/policy.h" #include "primitives/transaction.h" #include "script/script.h" #include "script/sign.h" -- cgit v1.2.3 From 17ac0f402559f57733fb5da6dafb72cf0f50795f Mon Sep 17 00:00:00 2001 From: Casey Rodarmor Date: Tue, 28 Jul 2015 14:01:00 -0400 Subject: Avoid leaking file descriptors in RegisterLoad This is pretty trivial, but if there's an error here we'll leak a file descriptor. Changed it to always close the file. --- src/bitcoin-tx.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 9ad57d5c6..e389d51a7 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -143,13 +143,14 @@ static void RegisterLoad(const string& strInput) valStr.insert(valStr.size(), buf, bread); } - if (ferror(f)) { + int error = ferror(f); + fclose(f); + + if (error) { string strErr = "Error reading file " + filename; throw runtime_error(strErr); } - fclose(f); - // evaluate as JSON buffer register RegisterSetJson(key, valStr); } -- cgit v1.2.3 From af3208bfa6967d6b35aecf0ba35d9d6bf0f8317e Mon Sep 17 00:00:00 2001 From: mruddy Date: Thu, 30 Jul 2015 19:56:00 -0400 Subject: Resolve issue 3166. These changes decode valid SIGHASH types on signatures in assembly (asm) representations of scriptSig scripts. This squashed commit incorporates substantial helpful feedback from jtimon, laanwj, and sipa. --- src/bitcoin-tx.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index e389d51a7..f43df4f33 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -387,8 +387,8 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) CCoinsModifier coins = view.ModifyCoins(txid); if (coins->IsAvailable(nOut) && coins->vout[nOut].scriptPubKey != scriptPubKey) { string err("Previous output scriptPubKey mismatch:\n"); - err = err + coins->vout[nOut].scriptPubKey.ToString() + "\nvs:\n"+ - scriptPubKey.ToString(); + err = err + ScriptToAsmStr(coins->vout[nOut].scriptPubKey) + "\nvs:\n"+ + ScriptToAsmStr(scriptPubKey); throw runtime_error(err); } if ((unsigned int)nOut >= coins->vout.size()) -- cgit v1.2.3 From 627468d2ea1f4d5dea9561fe77aaf53f3a83b4d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Mon, 29 Jun 2015 20:14:43 +0200 Subject: Add support for data-based outputs (OP_RETURN) to bitcoin-tx. --- src/bitcoin-tx.cpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index e389d51a7..97a073174 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -70,6 +70,7 @@ static bool AppInitRawTx(int argc, char* argv[]) strUsage += HelpMessageOpt("locktime=N", _("Set TX lock time to N")); strUsage += HelpMessageOpt("nversion=N", _("Set TX version to N")); strUsage += HelpMessageOpt("outaddr=VALUE:ADDRESS", _("Add address-based output to TX")); + strUsage += HelpMessageOpt("outdata=[VALUE:]DATA", _("Add data-based output to TX")); strUsage += HelpMessageOpt("outscript=VALUE:SCRIPT", _("Add raw script output to TX")); strUsage += HelpMessageOpt("sign=SIGHASH-FLAGS", _("Add zero or more signatures to transaction") + ". " + _("This command requires JSON registers:") + @@ -231,6 +232,35 @@ static void MutateTxAddOutAddr(CMutableTransaction& tx, const string& strInput) tx.vout.push_back(txout); } +static void MutateTxAddOutData(CMutableTransaction& tx, const string& strInput) +{ + CAmount value = 0; + + // separate [VALUE:]DATA in string + size_t pos = strInput.find(':'); + + if (pos==0) + throw runtime_error("TX output value not specified"); + + if (pos != string::npos) { + // extract and validate VALUE + string strValue = strInput.substr(0, pos); + if (!ParseMoney(strValue, value)) + throw runtime_error("invalid TX output value"); + } + + // extract and validate DATA + string strData = strInput.substr(pos + 1, string::npos); + + if (!IsHex(strData)) + throw runtime_error("invalid TX output data"); + + std::vector data = ParseHex(strData); + + CTxOut txout(value, CScript() << OP_RETURN << data); + tx.vout.push_back(txout); +} + static void MutateTxAddOutScript(CMutableTransaction& tx, const string& strInput) { // separate VALUE:SCRIPT in string @@ -470,6 +500,8 @@ static void MutateTx(CMutableTransaction& tx, const string& command, MutateTxDelOutput(tx, commandVal); else if (command == "outaddr") MutateTxAddOutAddr(tx, commandVal); + else if (command == "outdata") + MutateTxAddOutData(tx, commandVal); else if (command == "outscript") MutateTxAddOutScript(tx, commandVal); -- cgit v1.2.3 From 9623e934732ba0f0a5176cd3d993ebcda327b413 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 4 Sep 2015 16:11:34 +0200 Subject: [Univalue] add univalue over subtree similar to secp256k1 include and compile univalue over a subtree --- src/bitcoin-tx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 5beab265b..f7518fab5 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -12,7 +12,7 @@ #include "primitives/transaction.h" #include "script/script.h" #include "script/sign.h" -#include "univalue/univalue.h" +#include #include "util.h" #include "utilmoneystr.h" #include "utilstrencodings.h" -- cgit v1.2.3 From 55a89751faaada5598771d10401030e9e86eecbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Tim=C3=B3n?= Date: Mon, 25 May 2015 09:00:17 +0200 Subject: Chainparams: Translations: DRY: options and error strings Also remove SelectBaseParamsFromCommandLine and SelectParamsFromCommandLine --- src/bitcoin-tx.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 97a073174..5cd5b6657 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -35,8 +35,10 @@ static bool AppInitRawTx(int argc, char* argv[]) ParseParameters(argc, argv); // Check for -testnet or -regtest parameter (Params() calls are only valid after this clause) - if (!SelectParamsFromCommandLine()) { - fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n"); + try { + SelectParams(ChainNameFromCommandLine()); + } catch(std::exception &e) { + fprintf(stderr, "Error: %s\n", e.what()); return false; } @@ -58,8 +60,7 @@ static bool AppInitRawTx(int argc, char* argv[]) strUsage += HelpMessageOpt("-create", _("Create new, empty TX.")); strUsage += HelpMessageOpt("-json", _("Select JSON output")); strUsage += HelpMessageOpt("-txid", _("Output only the hex-encoded transaction id of the resultant transaction.")); - strUsage += HelpMessageOpt("-regtest", _("Enter regression test mode, which uses a special chain in which blocks can be solved instantly.")); - strUsage += HelpMessageOpt("-testnet", _("Use the test network")); + AppendParamsHelpMessages(strUsage); fprintf(stdout, "%s", strUsage.c_str()); -- cgit v1.2.3 From 3cb56f37780854bf26650e0872a556da25897a0a Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Sun, 18 Oct 2015 21:02:36 +1100 Subject: *: alias -h for --help --- src/bitcoin-tx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index f7518fab5..eb36435de 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -42,7 +42,7 @@ static bool AppInitRawTx(int argc, char* argv[]) fCreateBlank = GetBoolArg("-create", false); - if (argc<2 || mapArgs.count("-?") || mapArgs.count("-help")) + if (argc<2 || mapArgs.count("-?") || mapArgs.count("-h") || mapArgs.count("-help")) { // First part of help message is specific to this utility std::string strUsage = _("Bitcoin Core bitcoin-tx utility version") + " " + FormatFullVersion() + "\n\n" + -- cgit v1.2.3 From ad5aae15b40dcbdbfc08221e615f06b030b92334 Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Tue, 27 Oct 2015 17:39:42 +0100 Subject: constify missing catch cases - ensure all missing catch cases are constant where possible --- src/bitcoin-tx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 3330fe5d1..48033cd8a 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -37,7 +37,7 @@ static bool AppInitRawTx(int argc, char* argv[]) // Check for -testnet or -regtest parameter (Params() calls are only valid after this clause) try { SelectParams(ChainNameFromCommandLine()); - } catch(std::exception &e) { + } catch (const std::exception& e) { fprintf(stderr, "Error: %s\n", e.what()); return false; } -- cgit v1.2.3 From 6e182686163ce3c15b878bd78c41d8d18db344f1 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 28 Jul 2015 20:11:20 +0200 Subject: Switch to libsecp256k1-based validation for ECDSA --- src/bitcoin-tx.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 48033cd8a..9f8b2b98a 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -477,9 +477,15 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) class Secp256k1Init { + ECCVerifyHandle globalVerifyHandle; + public: - Secp256k1Init() { ECC_Start(); } - ~Secp256k1Init() { ECC_Stop(); } + Secp256k1Init() { + ECC_Start(); + } + ~Secp256k1Init() { + ECC_Stop(); + } }; static void MutateTx(CMutableTransaction& tx, const string& command, -- cgit v1.2.3 From fa24439ff3d8ab5b9efaf66ef4dae6713b88cb35 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 13 Dec 2015 17:58:29 +0100 Subject: Bump copyright headers to 2015 --- src/bitcoin-tx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 9f8b2b98a..2c502ead3 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2009-2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -- cgit v1.2.3 From d5f46832de900cee0801ca40bba743c9564cccb8 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Wed, 9 Dec 2015 10:53:12 +0000 Subject: Unify package name to as few places as possible without major changes --- src/bitcoin-tx.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 9f8b2b98a..aaa2ef128 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -2,6 +2,10 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#if defined(HAVE_CONFIG_H) +#include "config/bitcoin-config.h" +#endif + #include "base58.h" #include "clientversion.h" #include "coins.h" @@ -47,7 +51,7 @@ static bool AppInitRawTx(int argc, char* argv[]) if (argc<2 || mapArgs.count("-?") || mapArgs.count("-h") || mapArgs.count("-help")) { // First part of help message is specific to this utility - std::string strUsage = _("Bitcoin Core bitcoin-tx utility version") + " " + FormatFullVersion() + "\n\n" + + std::string strUsage = strprintf(_("%s bitcoin-tx utility version"), _(PACKAGE_NAME)) + " " + FormatFullVersion() + "\n\n" + _("Usage:") + "\n" + " bitcoin-tx [options] [commands] " + _("Update hex-encoded bitcoin transaction") + "\n" + " bitcoin-tx [options] -create [commands] " + _("Create hex-encoded bitcoin transaction") + "\n" + -- cgit v1.2.3 From e59336fbf9b906bf05d50a732036613216898bd1 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 3 Dec 2015 16:29:45 +0100 Subject: [bitcoin-tx] allow to set nSequence number over the in= command --- src/bitcoin-tx.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 95d7a085a..d5e2fc279 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -71,7 +71,7 @@ static bool AppInitRawTx(int argc, char* argv[]) strUsage = HelpMessageGroup(_("Commands:")); strUsage += HelpMessageOpt("delin=N", _("Delete input N from TX")); strUsage += HelpMessageOpt("delout=N", _("Delete output N from TX")); - strUsage += HelpMessageOpt("in=TXID:VOUT", _("Add input to TX")); + strUsage += HelpMessageOpt("in=TXID:VOUT(:SEQUENCE_NUMBER)", _("Add input to TX")); strUsage += HelpMessageOpt("locktime=N", _("Set TX lock time to N")); strUsage += HelpMessageOpt("nversion=N", _("Set TX version to N")); strUsage += HelpMessageOpt("outaddr=VALUE:ADDRESS", _("Add address-based output to TX")); @@ -181,15 +181,15 @@ static void MutateTxLocktime(CMutableTransaction& tx, const string& cmdVal) static void MutateTxAddInput(CMutableTransaction& tx, const string& strInput) { + std::vector vStrInputParts; + boost::split(vStrInputParts, strInput, boost::is_any_of(":")); + // separate TXID:VOUT in string - size_t pos = strInput.find(':'); - if ((pos == string::npos) || - (pos == 0) || - (pos == (strInput.size() - 1))) + if (vStrInputParts.size()<2) throw runtime_error("TX input missing separator"); // extract and validate TXID - string strTxid = strInput.substr(0, pos); + string strTxid = vStrInputParts[0]; if ((strTxid.size() != 64) || !IsHex(strTxid)) throw runtime_error("invalid TX input txid"); uint256 txid(uint256S(strTxid)); @@ -198,13 +198,18 @@ static void MutateTxAddInput(CMutableTransaction& tx, const string& strInput) static const unsigned int maxVout = MAX_BLOCK_SIZE / minTxOutSz; // extract and validate vout - string strVout = strInput.substr(pos + 1, string::npos); + string strVout = vStrInputParts[1]; int vout = atoi(strVout); if ((vout < 0) || (vout > (int)maxVout)) throw runtime_error("invalid TX input vout"); + // extract the optional sequence number + uint32_t nSequenceIn=std::numeric_limits::max(); + if (vStrInputParts.size() > 2) + nSequenceIn = atoi(vStrInputParts[2]); + // append to transaction input list - CTxIn txin(txid, vout); + CTxIn txin(txid, vout, CScript(), nSequenceIn); tx.vin.push_back(txin); } -- cgit v1.2.3 From 86efa30ae3fd36aa77b19ff0f70bb89be9ec308e Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 7 Jun 2016 19:57:54 +0200 Subject: [Bitcoin-Tx] fix missing test fixtures, fix 32bit atoi issue --- src/bitcoin-tx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index d5e2fc279..f9ea94b9f 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -206,7 +206,7 @@ static void MutateTxAddInput(CMutableTransaction& tx, const string& strInput) // extract the optional sequence number uint32_t nSequenceIn=std::numeric_limits::max(); if (vStrInputParts.size() > 2) - nSequenceIn = atoi(vStrInputParts[2]); + nSequenceIn = std::stoul(vStrInputParts[2]); // append to transaction input list CTxIn txin(txid, vout, CScript(), nSequenceIn); -- cgit v1.2.3 From 449f9b8debcceb61a92043bc7031528a53627c47 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 8 Nov 2015 01:16:45 +0100 Subject: BIP141: Witness program --- src/bitcoin-tx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index f9ea94b9f..82a5583dd 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -472,7 +472,7 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) BOOST_FOREACH(const CTransaction& txv, txVariants) { txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig); } - if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i))) + if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx.wit.vtxinwit.size() > i ? &mergedTx.wit.vtxinwit[i].scriptWitness : NULL, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i))) fComplete = false; } -- cgit v1.2.3 From 0ef1dd3e11dd573b6e443852ef0c72e34093ac68 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 31 Mar 2016 14:51:29 +0200 Subject: Refactor script validation to observe amounts This is a preparation for BIP143 support. --- src/bitcoin-tx.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 82a5583dd..68c069659 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -462,6 +462,7 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) continue; } const CScript& prevPubKey = coins->vout[txin.prevout.n].scriptPubKey; + const CAmount& amount = coins->vout[txin.prevout.n].nValue; txin.scriptSig.clear(); // Only sign SIGHASH_SINGLE if there's a corresponding output: @@ -472,7 +473,7 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) BOOST_FOREACH(const CTransaction& txv, txVariants) { txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig); } - if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx.wit.vtxinwit.size() > i ? &mergedTx.wit.vtxinwit[i].scriptWitness : NULL, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i))) + if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx.wit.vtxinwit.size() > i ? &mergedTx.wit.vtxinwit[i].scriptWitness : NULL, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i, amount))) fComplete = false; } -- cgit v1.2.3 From 3dd410294d42f251e4808ef1dfcfcd64817edbac Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 27 Dec 2015 19:49:08 +0100 Subject: BIP143: Verification logic Includes simplifications by Eric Lombrozo. --- src/bitcoin-tx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 68c069659..424812a6d 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -471,7 +471,7 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) // ... and merge in other signatures: BOOST_FOREACH(const CTransaction& txv, txVariants) { - txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig); + txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, amount, txin.scriptSig, txv.vin[i].scriptSig); } if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx.wit.vtxinwit.size() > i ? &mergedTx.wit.vtxinwit[i].scriptWitness : NULL, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i, amount))) fComplete = false; -- cgit v1.2.3 From 2b1f6f9ccf36f1e0a2c9d99154e1642f796d7c2b Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 3 Jan 2016 18:54:50 +0100 Subject: BIP141: Other consensus critical limits, and BIP145 Includes changes by Suhas Daftuar, Luke-jr, and mruddy. --- src/bitcoin-tx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 424812a6d..e77aa6c72 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -195,7 +195,7 @@ static void MutateTxAddInput(CMutableTransaction& tx, const string& strInput) uint256 txid(uint256S(strTxid)); static const unsigned int minTxOutSz = 9; - static const unsigned int maxVout = MAX_BLOCK_SIZE / minTxOutSz; + static const unsigned int maxVout = MAX_BLOCK_BASE_SIZE / minTxOutSz; // extract and validate vout string strVout = vStrInputParts[1]; -- cgit v1.2.3 From 605e8473a7ddca13b24a4020c7bd630aa5d374e2 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 31 Mar 2016 14:54:58 +0200 Subject: BIP143: Signing logic --- src/bitcoin-tx.cpp | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index e77aa6c72..f457ea2bc 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -363,6 +363,18 @@ vector ParseHexUO(map& o, string strKey) return ParseHexUV(o[strKey], strKey); } +static CAmount AmountFromValue(const UniValue& value) +{ + if (!value.isNum() && !value.isStr()) + throw runtime_error("Amount is not a number or string"); + CAmount amount; + if (!ParseFixedPoint(value.getValStr(), 8, &amount)) + throw runtime_error("Invalid amount"); + if (!MoneyRange(amount)) + throw runtime_error("Amount out of range"); + return amount; +} + static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) { int nHashType = SIGHASH_ALL; @@ -434,7 +446,10 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) if ((unsigned int)nOut >= coins->vout.size()) coins->vout.resize(nOut+1); coins->vout[nOut].scriptPubKey = scriptPubKey; - coins->vout[nOut].nValue = 0; // we don't know the actual output value + coins->vout[nOut].nValue = 0; + if (prevOut.exists("amount")) { + coins->vout[nOut].nValue = AmountFromValue(prevOut["amount"]); + } } // if redeemScript given and private keys given, @@ -464,15 +479,16 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) const CScript& prevPubKey = coins->vout[txin.prevout.n].scriptPubKey; const CAmount& amount = coins->vout[txin.prevout.n].nValue; - txin.scriptSig.clear(); + SignatureData sigdata; // Only sign SIGHASH_SINGLE if there's a corresponding output: if (!fHashSingle || (i < mergedTx.vout.size())) - SignSignature(keystore, prevPubKey, mergedTx, i, nHashType); + ProduceSignature(MutableTransactionSignatureCreator(&keystore, &mergedTx, i, amount, nHashType), prevPubKey, sigdata); // ... and merge in other signatures: - BOOST_FOREACH(const CTransaction& txv, txVariants) { - txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, amount, txin.scriptSig, txv.vin[i].scriptSig); - } + BOOST_FOREACH(const CTransaction& txv, txVariants) + sigdata = CombineSignatures(prevPubKey, MutableTransactionSignatureChecker(&mergedTx, i, amount), sigdata, DataFromTransaction(txv, i)); + UpdateTransaction(mergedTx, i, sigdata); + if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx.wit.vtxinwit.size() > i ? &mergedTx.wit.vtxinwit[i].scriptWitness : NULL, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i, amount))) fComplete = false; } -- cgit v1.2.3 From 745eb678ef5d52c74edcd9c322ebd1f3232a9310 Mon Sep 17 00:00:00 2001 From: NicolasDorier Date: Sun, 10 Apr 2016 15:59:23 +0900 Subject: [RPC] signrawtransaction can sign P2WSH --- src/bitcoin-tx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index f457ea2bc..8e8ac4745 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -454,7 +454,7 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) // if redeemScript given and private keys given, // add redeemScript to the tempKeystore so it can be signed: - if (fGivenKeys && scriptPubKey.IsPayToScriptHash() && + if (fGivenKeys && (scriptPubKey.IsPayToScriptHash() || scriptPubKey.IsPayToWitnessScriptHash()) && prevOut.exists("redeemScript")) { UniValue v = prevOut["redeemScript"]; vector rsData(ParseHexUV(v, "redeemScript")); -- cgit v1.2.3 From fa6dc9f0e5eac8ec473b63adfd43635005778f46 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 25 Aug 2016 12:48:23 +0200 Subject: Remove unused variables --- src/bitcoin-tx.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 8e8ac4745..5cf9b043e 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -395,10 +395,8 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) if (!registers.count("privatekeys")) throw runtime_error("privatekeys register variable must be set."); - bool fGivenKeys = false; CBasicKeyStore tempKeystore; UniValue keysObj = registers["privatekeys"]; - fGivenKeys = true; for (unsigned int kidx = 0; kidx < keysObj.size(); kidx++) { if (!keysObj[kidx].isStr()) @@ -454,7 +452,7 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) // if redeemScript given and private keys given, // add redeemScript to the tempKeystore so it can be signed: - if (fGivenKeys && (scriptPubKey.IsPayToScriptHash() || scriptPubKey.IsPayToWitnessScriptHash()) && + if ((scriptPubKey.IsPayToScriptHash() || scriptPubKey.IsPayToWitnessScriptHash()) && prevOut.exists("redeemScript")) { UniValue v = prevOut["redeemScript"]; vector rsData(ParseHexUV(v, "redeemScript")); -- cgit v1.2.3 From cdd79eb70fe163a92531a6f11c72bce6d228dac6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Tim=C3=B3n?= Date: Tue, 30 Aug 2016 22:41:56 +0200 Subject: C++11: s/boost::scoped_ptr/std::unique_ptr/ --- src/bitcoin-tx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 5cf9b043e..cb863bda1 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -515,7 +515,7 @@ public: static void MutateTx(CMutableTransaction& tx, const string& command, const string& commandVal) { - boost::scoped_ptr ecc; + std::unique_ptr ecc; if (command == "nversion") MutateTxVersion(tx, commandVal); -- cgit v1.2.3 From b0aea8057921f0ed2288cf07048f652c7d6d9cf3 Mon Sep 17 00:00:00 2001 From: BtcDrak Date: Fri, 26 Aug 2016 22:35:46 +0100 Subject: Sync bitcoin-tx with tx version policy --- src/bitcoin-tx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index cb863bda1..e09afd632 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -164,7 +164,7 @@ static void RegisterLoad(const string& strInput) static void MutateTxVersion(CMutableTransaction& tx, const string& cmdVal) { int64_t newVersion = atoi64(cmdVal); - if (newVersion < 1 || newVersion > CTransaction::CURRENT_VERSION) + if (newVersion < 1 || newVersion > CTransaction::MAX_STANDARD_VERSION) throw runtime_error("Invalid TX version requested"); tx.nVersion = (int) newVersion; -- cgit v1.2.3 From 7451cf59cd7b3a917fe7e4c7210d43b2f5adaad3 Mon Sep 17 00:00:00 2001 From: jnewbery Date: Thu, 29 Sep 2016 10:14:05 -0400 Subject: Allow bitcoin-tx to parse partial transactions Restore pre V0.13.1 functionality to bitcoin-tx and allow it to parse 0-input partial transactions. --- src/bitcoin-tx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index e09afd632..66c2166fe 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -629,7 +629,7 @@ static int CommandLineRawTx(int argc, char* argv[]) if (strHexTx == "-") // "-" implies standard input strHexTx = readStdin(); - if (!DecodeHexTx(txDecodeTmp, strHexTx)) + if (!DecodeHexTx(txDecodeTmp, strHexTx, true)) throw runtime_error("invalid transaction encoding"); startArg = 2; -- cgit v1.2.3 From bd0de1386e1c7f9b875d52290de0d561c8d56bc9 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Wed, 2 Nov 2016 21:59:09 +0300 Subject: Fix exit codes: - `--help`, `--version` etc should exit with `0` i.e. no error ("not enough args" case should still trigger an error) - error reading config file should exit with `1` Slightly refactor AppInitRPC/AppInitRawTx to return standard exit codes (EXIT_FAILURE/EXIT_SUCCESS) or CONTINUE_EXECUTION (-1) --- src/bitcoin-tx.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index e09afd632..ecc19c44a 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -30,8 +30,13 @@ using namespace std; static bool fCreateBlank; static map registers; +static const int CONTINUE_EXECUTION=-1; -static bool AppInitRawTx(int argc, char* argv[]) +// +// This function returns either one of EXIT_ codes when it's expected to stop the process or +// CONTINUE_EXECUTION when it's expected to continue further. +// +static int AppInitRawTx(int argc, char* argv[]) { // // Parameters @@ -89,9 +94,13 @@ static bool AppInitRawTx(int argc, char* argv[]) strUsage += HelpMessageOpt("set=NAME:JSON-STRING", _("Set register NAME to given JSON-STRING")); fprintf(stdout, "%s", strUsage.c_str()); - return false; + if (argc < 2) { + fprintf(stderr, "Error: too few parameters\n"); + return EXIT_FAILURE; + } + return EXIT_SUCCESS; } - return true; + return CONTINUE_EXECUTION; } static void RegisterSetJson(const string& key, const string& rawJson) @@ -678,8 +687,9 @@ int main(int argc, char* argv[]) SetupEnvironment(); try { - if(!AppInitRawTx(argc, argv)) - return EXIT_FAILURE; + int ret = AppInitRawTx(argc, argv); + if (ret != CONTINUE_EXECUTION) + return ret; } catch (const std::exception& e) { PrintExceptionContinue(&e, "AppInitRawTx()"); -- cgit v1.2.3 From 45d372f88900bda74835a20a44246746c2ac94e6 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Thu, 10 Nov 2016 00:53:55 +0300 Subject: Missed one "return false" in recent refactoring in #9067 --- src/bitcoin-tx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index ecc19c44a..6c66efcc9 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -48,7 +48,7 @@ static int AppInitRawTx(int argc, char* argv[]) SelectParams(ChainNameFromCommandLine()); } catch (const std::exception& e) { fprintf(stderr, "Error: %s\n", e.what()); - return false; + return EXIT_FAILURE; } fCreateBlank = GetBoolArg("-create", false); -- cgit v1.2.3 From 2f2625a0bb94db220a6f5560fa942159b66ac61e Mon Sep 17 00:00:00 2001 From: Karl-Johan Alm Date: Fri, 25 Nov 2016 17:17:57 +0900 Subject: Removed using namespace std from bitcoin-cli/-tx and added std:: in appropriate places. --- src/bitcoin-tx.cpp | 190 ++++++++++++++++++++++++++--------------------------- 1 file changed, 94 insertions(+), 96 deletions(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 6d17bc392..346d8e180 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -26,10 +26,8 @@ #include #include -using namespace std; - static bool fCreateBlank; -static map registers; +static std::map registers; static const int CONTINUE_EXECUTION=-1; // @@ -103,52 +101,52 @@ static int AppInitRawTx(int argc, char* argv[]) return CONTINUE_EXECUTION; } -static void RegisterSetJson(const string& key, const string& rawJson) +static void RegisterSetJson(const std::string& key, const std::string& rawJson) { UniValue val; if (!val.read(rawJson)) { - string strErr = "Cannot parse JSON for key " + key; - throw runtime_error(strErr); + std::string strErr = "Cannot parse JSON for key " + key; + throw std::runtime_error(strErr); } registers[key] = val; } -static void RegisterSet(const string& strInput) +static void RegisterSet(const std::string& strInput) { // separate NAME:VALUE in string size_t pos = strInput.find(':'); - if ((pos == string::npos) || + if ((pos == std::string::npos) || (pos == 0) || (pos == (strInput.size() - 1))) - throw runtime_error("Register input requires NAME:VALUE"); + throw std::runtime_error("Register input requires NAME:VALUE"); - string key = strInput.substr(0, pos); - string valStr = strInput.substr(pos + 1, string::npos); + std::string key = strInput.substr(0, pos); + std::string valStr = strInput.substr(pos + 1, std::string::npos); RegisterSetJson(key, valStr); } -static void RegisterLoad(const string& strInput) +static void RegisterLoad(const std::string& strInput) { // separate NAME:FILENAME in string size_t pos = strInput.find(':'); - if ((pos == string::npos) || + if ((pos == std::string::npos) || (pos == 0) || (pos == (strInput.size() - 1))) - throw runtime_error("Register load requires NAME:FILENAME"); + throw std::runtime_error("Register load requires NAME:FILENAME"); - string key = strInput.substr(0, pos); - string filename = strInput.substr(pos + 1, string::npos); + std::string key = strInput.substr(0, pos); + std::string filename = strInput.substr(pos + 1, std::string::npos); FILE *f = fopen(filename.c_str(), "r"); if (!f) { - string strErr = "Cannot open file " + filename; - throw runtime_error(strErr); + std::string strErr = "Cannot open file " + filename; + throw std::runtime_error(strErr); } // load file chunks into one big buffer - string valStr; + std::string valStr; while ((!feof(f)) && (!ferror(f))) { char buf[4096]; int bread = fread(buf, 1, sizeof(buf), f); @@ -162,55 +160,55 @@ static void RegisterLoad(const string& strInput) fclose(f); if (error) { - string strErr = "Error reading file " + filename; - throw runtime_error(strErr); + std::string strErr = "Error reading file " + filename; + throw std::runtime_error(strErr); } // evaluate as JSON buffer register RegisterSetJson(key, valStr); } -static void MutateTxVersion(CMutableTransaction& tx, const string& cmdVal) +static void MutateTxVersion(CMutableTransaction& tx, const std::string& cmdVal) { int64_t newVersion = atoi64(cmdVal); if (newVersion < 1 || newVersion > CTransaction::MAX_STANDARD_VERSION) - throw runtime_error("Invalid TX version requested"); + throw std::runtime_error("Invalid TX version requested"); tx.nVersion = (int) newVersion; } -static void MutateTxLocktime(CMutableTransaction& tx, const string& cmdVal) +static void MutateTxLocktime(CMutableTransaction& tx, const std::string& cmdVal) { int64_t newLocktime = atoi64(cmdVal); if (newLocktime < 0LL || newLocktime > 0xffffffffLL) - throw runtime_error("Invalid TX locktime requested"); + throw std::runtime_error("Invalid TX locktime requested"); tx.nLockTime = (unsigned int) newLocktime; } -static void MutateTxAddInput(CMutableTransaction& tx, const string& strInput) +static void MutateTxAddInput(CMutableTransaction& tx, const std::string& strInput) { std::vector vStrInputParts; boost::split(vStrInputParts, strInput, boost::is_any_of(":")); // separate TXID:VOUT in string if (vStrInputParts.size()<2) - throw runtime_error("TX input missing separator"); + throw std::runtime_error("TX input missing separator"); // extract and validate TXID - string strTxid = vStrInputParts[0]; + std::string strTxid = vStrInputParts[0]; if ((strTxid.size() != 64) || !IsHex(strTxid)) - throw runtime_error("invalid TX input txid"); + throw std::runtime_error("invalid TX input txid"); uint256 txid(uint256S(strTxid)); static const unsigned int minTxOutSz = 9; static const unsigned int maxVout = MAX_BLOCK_BASE_SIZE / minTxOutSz; // extract and validate vout - string strVout = vStrInputParts[1]; + std::string strVout = vStrInputParts[1]; int vout = atoi(strVout); if ((vout < 0) || (vout > (int)maxVout)) - throw runtime_error("invalid TX input vout"); + throw std::runtime_error("invalid TX input vout"); // extract the optional sequence number uint32_t nSequenceIn=std::numeric_limits::max(); @@ -222,26 +220,26 @@ static void MutateTxAddInput(CMutableTransaction& tx, const string& strInput) tx.vin.push_back(txin); } -static void MutateTxAddOutAddr(CMutableTransaction& tx, const string& strInput) +static void MutateTxAddOutAddr(CMutableTransaction& tx, const std::string& strInput) { // separate VALUE:ADDRESS in string size_t pos = strInput.find(':'); - if ((pos == string::npos) || + if ((pos == std::string::npos) || (pos == 0) || (pos == (strInput.size() - 1))) - throw runtime_error("TX output missing separator"); + throw std::runtime_error("TX output missing separator"); // extract and validate VALUE - string strValue = strInput.substr(0, pos); + std::string strValue = strInput.substr(0, pos); CAmount value; if (!ParseMoney(strValue, value)) - throw runtime_error("invalid TX output value"); + throw std::runtime_error("invalid TX output value"); // extract and validate ADDRESS - string strAddr = strInput.substr(pos + 1, string::npos); + std::string strAddr = strInput.substr(pos + 1, std::string::npos); CBitcoinAddress addr(strAddr); if (!addr.IsValid()) - throw runtime_error("invalid TX output address"); + throw std::runtime_error("invalid TX output address"); // build standard output script via GetScriptForDestination() CScript scriptPubKey = GetScriptForDestination(addr.Get()); @@ -251,7 +249,7 @@ static void MutateTxAddOutAddr(CMutableTransaction& tx, const string& strInput) tx.vout.push_back(txout); } -static void MutateTxAddOutData(CMutableTransaction& tx, const string& strInput) +static void MutateTxAddOutData(CMutableTransaction& tx, const std::string& strInput) { CAmount value = 0; @@ -259,20 +257,20 @@ static void MutateTxAddOutData(CMutableTransaction& tx, const string& strInput) size_t pos = strInput.find(':'); if (pos==0) - throw runtime_error("TX output value not specified"); + throw std::runtime_error("TX output value not specified"); - if (pos != string::npos) { + if (pos != std::string::npos) { // extract and validate VALUE - string strValue = strInput.substr(0, pos); + std::string strValue = strInput.substr(0, pos); if (!ParseMoney(strValue, value)) - throw runtime_error("invalid TX output value"); + throw std::runtime_error("invalid TX output value"); } // extract and validate DATA - string strData = strInput.substr(pos + 1, string::npos); + std::string strData = strInput.substr(pos + 1, std::string::npos); if (!IsHex(strData)) - throw runtime_error("invalid TX output data"); + throw std::runtime_error("invalid TX output data"); std::vector data = ParseHex(strData); @@ -280,22 +278,22 @@ static void MutateTxAddOutData(CMutableTransaction& tx, const string& strInput) tx.vout.push_back(txout); } -static void MutateTxAddOutScript(CMutableTransaction& tx, const string& strInput) +static void MutateTxAddOutScript(CMutableTransaction& tx, const std::string& strInput) { // separate VALUE:SCRIPT in string size_t pos = strInput.find(':'); - if ((pos == string::npos) || + if ((pos == std::string::npos) || (pos == 0)) - throw runtime_error("TX output missing separator"); + throw std::runtime_error("TX output missing separator"); // extract and validate VALUE - string strValue = strInput.substr(0, pos); + std::string strValue = strInput.substr(0, pos); CAmount value; if (!ParseMoney(strValue, value)) - throw runtime_error("invalid TX output value"); + throw std::runtime_error("invalid TX output value"); // extract and validate script - string strScript = strInput.substr(pos + 1, string::npos); + std::string strScript = strInput.substr(pos + 1, std::string::npos); CScript scriptPubKey = ParseScript(strScript); // throws on err // construct TxOut, append to transaction output list @@ -303,26 +301,26 @@ static void MutateTxAddOutScript(CMutableTransaction& tx, const string& strInput tx.vout.push_back(txout); } -static void MutateTxDelInput(CMutableTransaction& tx, const string& strInIdx) +static void MutateTxDelInput(CMutableTransaction& tx, const std::string& strInIdx) { // parse requested deletion index int inIdx = atoi(strInIdx); if (inIdx < 0 || inIdx >= (int)tx.vin.size()) { - string strErr = "Invalid TX input index '" + strInIdx + "'"; - throw runtime_error(strErr.c_str()); + std::string strErr = "Invalid TX input index '" + strInIdx + "'"; + throw std::runtime_error(strErr.c_str()); } // delete input from transaction tx.vin.erase(tx.vin.begin() + inIdx); } -static void MutateTxDelOutput(CMutableTransaction& tx, const string& strOutIdx) +static void MutateTxDelOutput(CMutableTransaction& tx, const std::string& strOutIdx) { // parse requested deletion index int outIdx = atoi(strOutIdx); if (outIdx < 0 || outIdx >= (int)tx.vout.size()) { - string strErr = "Invalid TX output index '" + strOutIdx + "'"; - throw runtime_error(strErr.c_str()); + std::string strErr = "Invalid TX output index '" + strOutIdx + "'"; + throw std::runtime_error(strErr.c_str()); } // delete output from transaction @@ -342,7 +340,7 @@ static const struct { {"SINGLE|ANYONECANPAY", SIGHASH_SINGLE|SIGHASH_ANYONECANPAY}, }; -static bool findSighashFlags(int& flags, const string& flagStr) +static bool findSighashFlags(int& flags, const std::string& flagStr) { flags = 0; @@ -356,17 +354,17 @@ static bool findSighashFlags(int& flags, const string& flagStr) return false; } -uint256 ParseHashUO(map& o, string strKey) +uint256 ParseHashUO(std::map& o, std::string strKey) { if (!o.count(strKey)) return uint256(); return ParseHashUV(o[strKey], strKey); } -vector ParseHexUO(map& o, string strKey) +std::vector ParseHexUO(std::map& o, std::string strKey) { if (!o.count(strKey)) { - vector emptyVec; + std::vector emptyVec; return emptyVec; } return ParseHexUV(o[strKey], strKey); @@ -375,24 +373,24 @@ vector ParseHexUO(map& o, string strKey) static CAmount AmountFromValue(const UniValue& value) { if (!value.isNum() && !value.isStr()) - throw runtime_error("Amount is not a number or string"); + throw std::runtime_error("Amount is not a number or string"); CAmount amount; if (!ParseFixedPoint(value.getValStr(), 8, &amount)) - throw runtime_error("Invalid amount"); + throw std::runtime_error("Invalid amount"); if (!MoneyRange(amount)) - throw runtime_error("Amount out of range"); + throw std::runtime_error("Amount out of range"); return amount; } -static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) +static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr) { int nHashType = SIGHASH_ALL; if (flagStr.size() > 0) if (!findSighashFlags(nHashType, flagStr)) - throw runtime_error("unknown sighash flag/sign option"); + throw std::runtime_error("unknown sighash flag/sign option"); - vector txVariants; + std::vector txVariants; txVariants.push_back(tx); // mergedTx will end up with all the signatures; it @@ -403,17 +401,17 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) CCoinsViewCache view(&viewDummy); if (!registers.count("privatekeys")) - throw runtime_error("privatekeys register variable must be set."); + throw std::runtime_error("privatekeys register variable must be set."); CBasicKeyStore tempKeystore; UniValue keysObj = registers["privatekeys"]; for (unsigned int kidx = 0; kidx < keysObj.size(); kidx++) { if (!keysObj[kidx].isStr()) - throw runtime_error("privatekey not a string"); + throw std::runtime_error("privatekey not a std::string"); CBitcoinSecret vchSecret; bool fGood = vchSecret.SetString(keysObj[kidx].getValStr()); if (!fGood) - throw runtime_error("privatekey not valid"); + throw std::runtime_error("privatekey not valid"); CKey key = vchSecret.GetKey(); tempKeystore.AddKey(key); @@ -421,34 +419,34 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) // Add previous txouts given in the RPC call: if (!registers.count("prevtxs")) - throw runtime_error("prevtxs register variable must be set."); + throw std::runtime_error("prevtxs register variable must be set."); UniValue prevtxsObj = registers["prevtxs"]; { for (unsigned int previdx = 0; previdx < prevtxsObj.size(); previdx++) { UniValue prevOut = prevtxsObj[previdx]; if (!prevOut.isObject()) - throw runtime_error("expected prevtxs internal object"); + throw std::runtime_error("expected prevtxs internal object"); - map types = boost::assign::map_list_of("txid", UniValue::VSTR)("vout",UniValue::VNUM)("scriptPubKey",UniValue::VSTR); + std::map types = boost::assign::map_list_of("txid", UniValue::VSTR)("vout",UniValue::VNUM)("scriptPubKey",UniValue::VSTR); if (!prevOut.checkObject(types)) - throw runtime_error("prevtxs internal object typecheck fail"); + throw std::runtime_error("prevtxs internal object typecheck fail"); uint256 txid = ParseHashUV(prevOut["txid"], "txid"); int nOut = atoi(prevOut["vout"].getValStr()); if (nOut < 0) - throw runtime_error("vout must be positive"); + throw std::runtime_error("vout must be positive"); - vector pkData(ParseHexUV(prevOut["scriptPubKey"], "scriptPubKey")); + std::vector pkData(ParseHexUV(prevOut["scriptPubKey"], "scriptPubKey")); CScript scriptPubKey(pkData.begin(), pkData.end()); { CCoinsModifier coins = view.ModifyCoins(txid); if (coins->IsAvailable(nOut) && coins->vout[nOut].scriptPubKey != scriptPubKey) { - string err("Previous output scriptPubKey mismatch:\n"); + std::string err("Previous output scriptPubKey mismatch:\n"); err = err + ScriptToAsmStr(coins->vout[nOut].scriptPubKey) + "\nvs:\n"+ ScriptToAsmStr(scriptPubKey); - throw runtime_error(err); + throw std::runtime_error(err); } if ((unsigned int)nOut >= coins->vout.size()) coins->vout.resize(nOut+1); @@ -464,7 +462,7 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) if ((scriptPubKey.IsPayToScriptHash() || scriptPubKey.IsPayToWitnessScriptHash()) && prevOut.exists("redeemScript")) { UniValue v = prevOut["redeemScript"]; - vector rsData(ParseHexUV(v, "redeemScript")); + std::vector rsData(ParseHexUV(v, "redeemScript")); CScript redeemScript(rsData.begin(), rsData.end()); tempKeystore.AddCScript(redeemScript); } @@ -521,8 +519,8 @@ public: } }; -static void MutateTx(CMutableTransaction& tx, const string& command, - const string& commandVal) +static void MutateTx(CMutableTransaction& tx, const std::string& command, + const std::string& commandVal) { std::unique_ptr ecc; @@ -557,7 +555,7 @@ static void MutateTx(CMutableTransaction& tx, const string& command, RegisterSet(commandVal); else - throw runtime_error("unknown command"); + throw std::runtime_error("unknown command"); } static void OutputTxJSON(const CTransaction& tx) @@ -565,20 +563,20 @@ static void OutputTxJSON(const CTransaction& tx) UniValue entry(UniValue::VOBJ); TxToUniv(tx, uint256(), entry); - string jsonOutput = entry.write(4); + std::string jsonOutput = entry.write(4); fprintf(stdout, "%s\n", jsonOutput.c_str()); } static void OutputTxHash(const CTransaction& tx) { - string strHexHash = tx.GetHash().GetHex(); // the hex-encoded transaction hash (aka the transaction id) + std::string strHexHash = tx.GetHash().GetHex(); // the hex-encoded transaction hash (aka the transaction id) fprintf(stdout, "%s\n", strHexHash.c_str()); } static void OutputTxHex(const CTransaction& tx) { - string strHex = EncodeHexTx(tx); + std::string strHex = EncodeHexTx(tx); fprintf(stdout, "%s\n", strHex.c_str()); } @@ -593,10 +591,10 @@ static void OutputTx(const CTransaction& tx) OutputTxHex(tx); } -static string readStdin() +static std::string readStdin() { char buf[4096]; - string ret; + std::string ret; while (!feof(stdin)) { size_t bread = fread(buf, 1, sizeof(buf), stdin); @@ -606,7 +604,7 @@ static string readStdin() } if (ferror(stdin)) - throw runtime_error("error reading stdin"); + throw std::runtime_error("error reading stdin"); boost::algorithm::trim_right(ret); @@ -615,7 +613,7 @@ static string readStdin() static int CommandLineRawTx(int argc, char* argv[]) { - string strPrint; + std::string strPrint; int nRet = 0; try { // Skip switches; Permit common stdin convention "-" @@ -631,15 +629,15 @@ static int CommandLineRawTx(int argc, char* argv[]) if (!fCreateBlank) { // require at least one param if (argc < 2) - throw runtime_error("too few parameters"); + throw std::runtime_error("too few parameters"); // param: hex-encoded bitcoin transaction - string strHexTx(argv[1]); + std::string strHexTx(argv[1]); if (strHexTx == "-") // "-" implies standard input strHexTx = readStdin(); if (!DecodeHexTx(txDecodeTmp, strHexTx, true)) - throw runtime_error("invalid transaction encoding"); + throw std::runtime_error("invalid transaction encoding"); startArg = 2; } else @@ -648,10 +646,10 @@ static int CommandLineRawTx(int argc, char* argv[]) CMutableTransaction tx(txDecodeTmp); for (int i = startArg; i < argc; i++) { - string arg = argv[i]; - string key, value; + std::string arg = argv[i]; + std::string key, value; size_t eqpos = arg.find('='); - if (eqpos == string::npos) + if (eqpos == std::string::npos) key = arg; else { key = arg.substr(0, eqpos); @@ -668,7 +666,7 @@ static int CommandLineRawTx(int argc, char* argv[]) throw; } catch (const std::exception& e) { - strPrint = string("error: ") + e.what(); + strPrint = std::string("error: ") + e.what(); nRet = EXIT_FAILURE; } catch (...) { -- cgit v1.2.3 From 42fd8dee302fec55ba0970e2f1378edc2797e4ff Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 30 Nov 2016 14:50:20 -0800 Subject: Make DecodeHexTx return a CMutableTransaction --- src/bitcoin-tx.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 346d8e180..1ed1449f0 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -623,7 +623,7 @@ static int CommandLineRawTx(int argc, char* argv[]) argv++; } - CTransaction txDecodeTmp; + CMutableTransaction tx; int startArg; if (!fCreateBlank) { @@ -636,15 +636,13 @@ static int CommandLineRawTx(int argc, char* argv[]) if (strHexTx == "-") // "-" implies standard input strHexTx = readStdin(); - if (!DecodeHexTx(txDecodeTmp, strHexTx, true)) + if (!DecodeHexTx(tx, strHexTx, true)) throw std::runtime_error("invalid transaction encoding"); startArg = 2; } else startArg = 1; - CMutableTransaction tx(txDecodeTmp); - for (int i = startArg; i < argc; i++) { std::string arg = argv[i]; std::string key, value; -- cgit v1.2.3 From f6fb7acda4aefd01b8ef6cd77063bfc0c4f4ab36 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 4 Aug 2016 02:49:16 +0200 Subject: Move CTxInWitness inside CTxIn --- src/bitcoin-tx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 1ed1449f0..816687a45 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -494,7 +494,7 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr) sigdata = CombineSignatures(prevPubKey, MutableTransactionSignatureChecker(&mergedTx, i, amount), sigdata, DataFromTransaction(txv, i)); UpdateTransaction(mergedTx, i, sigdata); - if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx.wit.vtxinwit.size() > i ? &mergedTx.wit.vtxinwit[i].scriptWitness : NULL, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i, amount))) + if (!VerifyScript(txin.scriptSig, prevPubKey, &txin.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i, amount))) fComplete = false; } -- cgit v1.2.3 From 0cf86a6678413aa03e765a7133f048df4001ff4c Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 29 Nov 2016 17:51:30 -0800 Subject: Introduce (and use) an IsArgSet accessor method --- src/bitcoin-tx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 816687a45..d46f33045 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -51,7 +51,7 @@ static int AppInitRawTx(int argc, char* argv[]) fCreateBlank = GetBoolArg("-create", false); - if (argc<2 || mapArgs.count("-?") || mapArgs.count("-h") || mapArgs.count("-help")) + if (argc<2 || IsArgSet("-?") || IsArgSet("-h") || IsArgSet("-help")) { // First part of help message is specific to this utility std::string strUsage = strprintf(_("%s bitcoin-tx utility version"), _(PACKAGE_NAME)) + " " + FormatFullVersion() + "\n\n" + -- cgit v1.2.3 From 1814b089fbf6eca03b1f026e2033d4a6ccc6305f Mon Sep 17 00:00:00 2001 From: Stanislas Marion Date: Fri, 30 Sep 2016 15:29:45 -0400 Subject: add p2sh and segwit options to bitcoin-tx outscript command --- src/bitcoin-tx.cpp | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index d46f33045..f9bb9f77d 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -79,7 +79,9 @@ static int AppInitRawTx(int argc, char* argv[]) strUsage += HelpMessageOpt("nversion=N", _("Set TX version to N")); strUsage += HelpMessageOpt("outaddr=VALUE:ADDRESS", _("Add address-based output to TX")); strUsage += HelpMessageOpt("outdata=[VALUE:]DATA", _("Add data-based output to TX")); - strUsage += HelpMessageOpt("outscript=VALUE:SCRIPT", _("Add raw script output to TX")); + strUsage += HelpMessageOpt("outscript=VALUE:SCRIPT(:\"SEGWIT\")(:\"P2SH\")", _("Add raw script output to TX") + ". " + + _("Optionally add the \"SEGWIT\" flag to produce a segwit output") + ". " + + _("Optionally add the \"P2SH\" flag to wrap the script in a P2SH output.")); strUsage += HelpMessageOpt("sign=SIGHASH-FLAGS", _("Add zero or more signatures to transaction") + ". " + _("This command requires JSON registers:") + _("prevtxs=JSON object") + ", " + @@ -280,22 +282,30 @@ static void MutateTxAddOutData(CMutableTransaction& tx, const std::string& strIn static void MutateTxAddOutScript(CMutableTransaction& tx, const std::string& strInput) { - // separate VALUE:SCRIPT in string - size_t pos = strInput.find(':'); - if ((pos == std::string::npos) || - (pos == 0)) - throw std::runtime_error("TX output missing separator"); + // separate VALUE:SCRIPT(:SEGWIT)(:P2SH) + std::vector vStrInput; + boost::split(vStrInput, strInput, boost::is_any_of(":")); + if (vStrInput.size() < 2) + throw srd::runtime_error("TX output missing separator"); // extract and validate VALUE - std::string strValue = strInput.substr(0, pos); + std::string strValue = vStrInput[0]; CAmount value; if (!ParseMoney(strValue, value)) throw std::runtime_error("invalid TX output value"); // extract and validate script - std::string strScript = strInput.substr(pos + 1, std::string::npos); + std::string strScript = vStrInput[1]; CScript scriptPubKey = ParseScript(strScript); // throws on err + if (std::find(vStrInput.begin(), vStrInput.end(), "SEGWIT") != vStrInput.end()) { + scriptPubKey = GetScriptForWitness(scriptPubKey); + } + if (std::find(vStrInput.begin(), vStrInput.end(), "P2SH") != vStrInput.end()) { + CBitcoinAddress addr(scriptPubKey); + scriptPubKey = GetScriptForDestination(addr.Get()); + } + // construct TxOut, append to transaction output list CTxOut txout(value, scriptPubKey); tx.vout.push_back(txout); -- cgit v1.2.3 From 61a153443ef87d0cf187d2203f0d5ef88e52e7ed Mon Sep 17 00:00:00 2001 From: jnewbery Date: Tue, 4 Oct 2016 14:21:25 -0400 Subject: Add all transaction output types to bitcoin-tx. This commit enhances bitcoin-tx so all remaining standard TXO types can be created: - Pay to Pub Key - Multi-sig - bare multi-sig - multi-sig in Pay To Script Hash - multi-sig in Pay to Witness Script Hash - multi-sig in Pay to Witness Script Hash, wrapped in P2SH - Pay to Witness Pub Key Hash - Pay to Witness Pub Key Hash, wrapped in P2SH - Pay to Witness Script Hash - Pay to Witness Script Hash, wrapped in P2SH --- src/bitcoin-tx.cpp | 197 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 160 insertions(+), 37 deletions(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index f9bb9f77d..68517decc 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -78,10 +78,16 @@ static int AppInitRawTx(int argc, char* argv[]) strUsage += HelpMessageOpt("locktime=N", _("Set TX lock time to N")); strUsage += HelpMessageOpt("nversion=N", _("Set TX version to N")); strUsage += HelpMessageOpt("outaddr=VALUE:ADDRESS", _("Add address-based output to TX")); + strUsage += HelpMessageOpt("outpubkey=VALUE:PUBKEY[:FLAGS]", _("Add pay-to-pubkey output to TX") + ". " + + _("Optionally add the \"W\" flag to produce a pay-to-witness-pubkey-hash output") + ". " + + _("Optionally add the \"S\" flag to wrap the output in a pay-to-script-hash.")); strUsage += HelpMessageOpt("outdata=[VALUE:]DATA", _("Add data-based output to TX")); - strUsage += HelpMessageOpt("outscript=VALUE:SCRIPT(:\"SEGWIT\")(:\"P2SH\")", _("Add raw script output to TX") + ". " + - _("Optionally add the \"SEGWIT\" flag to produce a segwit output") + ". " + - _("Optionally add the \"P2SH\" flag to wrap the script in a P2SH output.")); + strUsage += HelpMessageOpt("outscript=VALUE:SCRIPT[:FLAGS]", _("Add raw script output to TX") + ". " + + _("Optionally add the \"W\" flag to produce a pay-to-witness-script-hash output") + ". " + + _("Optionally add the \"S\" flag to wrap the output in a pay-to-script-hash.")); + strUsage += HelpMessageOpt("outmultisig=VALUE:REQUIRED:PUBKEYS:PUBKEY1:PUBKEY2:....[:FLAGS]", _("Add Pay To n-of-m Multi-sig output to TX. n = REQUIRED, m = PUBKEYS") + ". " + + _("Optionally add the \"W\" flag to produce a pay-to-witness-script-hash output") + ". " + + _("Optionally add the \"S\" flag to wrap the output in a pay-to-script-hash.")); strUsage += HelpMessageOpt("sign=SIGHASH-FLAGS", _("Add zero or more signatures to transaction") + ". " + _("This command requires JSON registers:") + _("prevtxs=JSON object") + ", " + @@ -170,6 +176,14 @@ static void RegisterLoad(const std::string& strInput) RegisterSetJson(key, valStr); } +static CAmount ExtractAndValidateValue(const std::string& strValue) +{ + CAmount value; + if (!ParseMoney(strValue, value)) + throw std::runtime_error("invalid TX output value"); + return value; +} + static void MutateTxVersion(CMutableTransaction& tx, const std::string& cmdVal) { int64_t newVersion = atoi64(cmdVal); @@ -224,25 +238,18 @@ static void MutateTxAddInput(CMutableTransaction& tx, const std::string& strInpu static void MutateTxAddOutAddr(CMutableTransaction& tx, const std::string& strInput) { - // separate VALUE:ADDRESS in string - size_t pos = strInput.find(':'); - if ((pos == std::string::npos) || - (pos == 0) || - (pos == (strInput.size() - 1))) - throw std::runtime_error("TX output missing separator"); + // Separate into VALUE:ADDRESS + std::vector vStrInputParts; + boost::split(vStrInputParts, strInput, boost::is_any_of(":")); - // extract and validate VALUE - std::string strValue = strInput.substr(0, pos); - CAmount value; - if (!ParseMoney(strValue, value)) - throw std::runtime_error("invalid TX output value"); + // Extract and validate VALUE + CAmount value = ExtractAndValidateValue(vStrInputParts[0]); // extract and validate ADDRESS - std::string strAddr = strInput.substr(pos + 1, std::string::npos); + std::string strAddr = vStrInputParts[1]; CBitcoinAddress addr(strAddr); if (!addr.IsValid()) throw std::runtime_error("invalid TX output address"); - // build standard output script via GetScriptForDestination() CScript scriptPubKey = GetScriptForDestination(addr.Get()); @@ -251,6 +258,114 @@ static void MutateTxAddOutAddr(CMutableTransaction& tx, const std::string& strIn tx.vout.push_back(txout); } +static void MutateTxAddOutPubKey(CMutableTransaction& tx, const std::string& strInput) +{ + // Separate into VALUE:PUBKEY[:FLAGS] + std::vector vStrInputParts; + boost::split(vStrInputParts, strInput, boost::is_any_of(":")); + + // Extract and validate VALUE + CAmount value = ExtractAndValidateValue(vStrInputParts[0]); + + // Extract and validate PUBKEY + CPubKey pubkey(ParseHex(vStrInputParts[1])); + if (!pubkey.IsFullyValid()) + throw std::runtime_error("invalid TX output pubkey"); + CScript scriptPubKey = GetScriptForRawPubKey(pubkey); + CBitcoinAddress addr(scriptPubKey); + + // Extract and validate FLAGS + bool bSegWit = false; + bool bScriptHash = false; + if (vStrInputParts.size() == 3) { + std::string flags = vStrInputParts[2]; + bSegWit = (flags.find("W") != std::string::npos); + bScriptHash = (flags.find("S") != std::string::npos); + } + + if (bSegWit) { + // Call GetScriptForWitness() to build a P2WSH scriptPubKey + scriptPubKey = GetScriptForWitness(scriptPubKey); + } + if (bScriptHash) { + // Get the address for the redeem script, then call + // GetScriptForDestination() to construct a P2SH scriptPubKey. + CBitcoinAddress redeemScriptAddr(scriptPubKey); + scriptPubKey = GetScriptForDestination(redeemScriptAddr.Get()); + } + + // construct TxOut, append to transaction output list + CTxOut txout(value, scriptPubKey); + tx.vout.push_back(txout); +} + +static void MutateTxAddOutMultiSig(CMutableTransaction& tx, const std::string& strInput) +{ + // Separate into VALUE:REQUIRED:NUMKEYS:PUBKEY1:PUBKEY2:....[:FLAGS] + std::vector vStrInputParts; + boost::split(vStrInputParts, strInput, boost::is_any_of(":")); + + // Check that there are enough parameters + if (vStrInputParts.size()<3) + throw std::runtime_error("Not enough multisig parameters"); + + // Extract and validate VALUE + CAmount value = ExtractAndValidateValue(vStrInputParts[0]); + + // Extract REQUIRED + uint32_t required = stoul(vStrInputParts[1]); + + // Extract NUMKEYS + uint32_t numkeys = stoul(vStrInputParts[2]); + + // Validate there are the correct number of pubkeys + if (vStrInputParts.size() < numkeys + 3) + throw std::runtime_error("incorrect number of multisig pubkeys"); + + if (required < 1 || required > 20 || numkeys < 1 || numkeys > 20 || numkeys < required) + throw std::runtime_error("multisig parameter mismatch. Required " \ + + std::to_string(required) + " of " + std::to_string(numkeys) + "signatures."); + + // extract and validate PUBKEYs + std::vector pubkeys; + for(int pos = 1; pos <= int(numkeys); pos++) { + CPubKey pubkey(ParseHex(vStrInputParts[pos + 2])); + if (!pubkey.IsFullyValid()) + throw std::runtime_error("invalid TX output pubkey"); + pubkeys.push_back(pubkey); + } + + // Extract FLAGS + bool bSegWit = false; + bool bScriptHash = false; + if (vStrInputParts.size() == numkeys + 4) { + std::string flags = vStrInputParts.back(); + bSegWit = (flags.find("W") != std::string::npos); + bScriptHash = (flags.find("S") != std::string::npos); + } + else if (vStrInputParts.size() > numkeys + 4) { + // Validate that there were no more parameters passed + throw std::runtime_error("Too many parameters"); + } + + CScript scriptPubKey = GetScriptForMultisig(required, pubkeys); + + if (bSegWit) { + // Call GetScriptForWitness() to build a P2WSH scriptPubKey + scriptPubKey = GetScriptForWitness(scriptPubKey); + } + if (bScriptHash) { + // Get the address for the redeem script, then call + // GetScriptForDestination() to construct a P2SH scriptPubKey. + CBitcoinAddress addr(scriptPubKey); + scriptPubKey = GetScriptForDestination(addr.Get()); + } + + // construct TxOut, append to transaction output list + CTxOut txout(value, scriptPubKey); + tx.vout.push_back(txout); +} + static void MutateTxAddOutData(CMutableTransaction& tx, const std::string& strInput) { CAmount value = 0; @@ -262,10 +377,8 @@ static void MutateTxAddOutData(CMutableTransaction& tx, const std::string& strIn throw std::runtime_error("TX output value not specified"); if (pos != std::string::npos) { - // extract and validate VALUE - std::string strValue = strInput.substr(0, pos); - if (!ParseMoney(strValue, value)) - throw std::runtime_error("invalid TX output value"); + // Extract and validate VALUE + value = ExtractAndValidateValue(strInput.substr(0, pos)); } // extract and validate DATA @@ -282,26 +395,32 @@ static void MutateTxAddOutData(CMutableTransaction& tx, const std::string& strIn static void MutateTxAddOutScript(CMutableTransaction& tx, const std::string& strInput) { - // separate VALUE:SCRIPT(:SEGWIT)(:P2SH) - std::vector vStrInput; - boost::split(vStrInput, strInput, boost::is_any_of(":")); - if (vStrInput.size() < 2) - throw srd::runtime_error("TX output missing separator"); - - // extract and validate VALUE - std::string strValue = vStrInput[0]; - CAmount value; - if (!ParseMoney(strValue, value)) - throw std::runtime_error("invalid TX output value"); + // separate VALUE:SCRIPT[:FLAGS] + std::vector vStrInputParts; + boost::split(vStrInputParts, strInput, boost::is_any_of(":")); + if (vStrInputParts.size() < 2) + throw std::runtime_error("TX output missing separator"); + + // Extract and validate VALUE + CAmount value = ExtractAndValidateValue(vStrInputParts[0]); // extract and validate script - std::string strScript = vStrInput[1]; - CScript scriptPubKey = ParseScript(strScript); // throws on err + std::string strScript = vStrInputParts[1]; + CScript scriptPubKey = ParseScript(strScript); + + // Extract FLAGS + bool bSegWit = false; + bool bScriptHash = false; + if (vStrInputParts.size() == 3) { + std::string flags = vStrInputParts.back(); + bSegWit = (flags.find("W") != std::string::npos); + bScriptHash = (flags.find("S") != std::string::npos); + } - if (std::find(vStrInput.begin(), vStrInput.end(), "SEGWIT") != vStrInput.end()) { + if (bSegWit) { scriptPubKey = GetScriptForWitness(scriptPubKey); } - if (std::find(vStrInput.begin(), vStrInput.end(), "P2SH") != vStrInput.end()) { + if (bScriptHash) { CBitcoinAddress addr(scriptPubKey); scriptPubKey = GetScriptForDestination(addr.Get()); } @@ -548,10 +667,14 @@ static void MutateTx(CMutableTransaction& tx, const std::string& command, MutateTxDelOutput(tx, commandVal); else if (command == "outaddr") MutateTxAddOutAddr(tx, commandVal); - else if (command == "outdata") - MutateTxAddOutData(tx, commandVal); + else if (command == "outpubkey") + MutateTxAddOutPubKey(tx, commandVal); + else if (command == "outmultisig") + MutateTxAddOutMultiSig(tx, commandVal); else if (command == "outscript") MutateTxAddOutScript(tx, commandVal); + else if (command == "outdata") + MutateTxAddOutData(tx, commandVal); else if (command == "sign") { if (!ecc) { ecc.reset(new Secp256k1Init()); } -- cgit v1.2.3 From 27765b6403cece54320374b37afb01a0cfe571c3 Mon Sep 17 00:00:00 2001 From: isle2983 Date: Sat, 31 Dec 2016 11:01:21 -0700 Subject: Increment MIT Licence copyright header year on files modified in 2016 Edited via: $ contrib/devtools/copyright_header.py update . --- src/bitcoin-tx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index d46f33045..24a53b65a 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2015 The Bitcoin Core developers +// Copyright (c) 2009-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -- cgit v1.2.3 From 04c21afcdf0ed664c1fddff17d066cc2de552b54 Mon Sep 17 00:00:00 2001 From: Awemany Date: Tue, 28 Mar 2017 14:52:59 +0200 Subject: bitcoin-tx: Fix missing range check The number of arguments is not checked MutateTxAddOutAddr(..), meaning that > ./bitcoin-tx -create outaddr= accessed the vStrInputParts vector beyond its bounds. This also includes work by jnewbery to check the inputs for MutateTxAddPubKey() Github-Pull: #10130 Rebased-From: eb66bf9bdd5ae20c546314eb2c494ac09929970f --- src/bitcoin-tx.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 3c3646523..43fa3fdfb 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -242,6 +242,9 @@ static void MutateTxAddOutAddr(CMutableTransaction& tx, const std::string& strIn std::vector vStrInputParts; boost::split(vStrInputParts, strInput, boost::is_any_of(":")); + if (vStrInputParts.size() != 2) + throw std::runtime_error("TX output missing or too many separators"); + // Extract and validate VALUE CAmount value = ExtractAndValidateValue(vStrInputParts[0]); @@ -264,6 +267,9 @@ static void MutateTxAddOutPubKey(CMutableTransaction& tx, const std::string& str std::vector vStrInputParts; boost::split(vStrInputParts, strInput, boost::is_any_of(":")); + if (vStrInputParts.size() < 2 || vStrInputParts.size() > 3) + throw std::runtime_error("TX output missing or too many separators"); + // Extract and validate VALUE CAmount value = ExtractAndValidateValue(vStrInputParts[0]); -- cgit v1.2.3 From 148a2aca05fe98031bcf857fa186d792c507090c Mon Sep 17 00:00:00 2001 From: Ross Nicoll Date: Mon, 27 Jul 2015 16:35:30 +0100 Subject: Introduce basic Dogecoin branding --- src/bitcoin-tx.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/bitcoin-tx.cpp') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 43fa3fdfb..48d661266 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -54,10 +54,10 @@ static int AppInitRawTx(int argc, char* argv[]) if (argc<2 || IsArgSet("-?") || IsArgSet("-h") || IsArgSet("-help")) { // First part of help message is specific to this utility - std::string strUsage = strprintf(_("%s bitcoin-tx utility version"), _(PACKAGE_NAME)) + " " + FormatFullVersion() + "\n\n" + + std::string strUsage = strprintf(_("%s dogecoin-tx utility version"), _(PACKAGE_NAME)) + " " + FormatFullVersion() + "\n\n" + _("Usage:") + "\n" + - " bitcoin-tx [options] [commands] " + _("Update hex-encoded bitcoin transaction") + "\n" + - " bitcoin-tx [options] -create [commands] " + _("Create hex-encoded bitcoin transaction") + "\n" + + " dogecoin-tx [options] [commands] " + _("Update hex-encoded dogecoin transaction") + "\n" + + " dogecoin-tx [options] -create [commands] " + _("Create hex-encoded dogecoin transaction") + "\n" + "\n"; fprintf(stdout, "%s", strUsage.c_str()); -- cgit v1.2.3