diff options
Diffstat (limited to 'src/bitcoin-tx.cpp')
-rw-r--r-- | src/bitcoin-tx.cpp | 81 |
1 files changed, 51 insertions, 30 deletions
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index d8d7934bf6..a9f7264f68 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -1,26 +1,26 @@ -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // 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" +#include <config/bitcoin-config.h> #endif -#include "base58.h" -#include "clientversion.h" -#include "coins.h" -#include "consensus/consensus.h" -#include "core_io.h" -#include "keystore.h" -#include "policy/policy.h" -#include "policy/rbf.h" -#include "primitives/transaction.h" -#include "script/script.h" -#include "script/sign.h" +#include <base58.h> +#include <clientversion.h> +#include <coins.h> +#include <consensus/consensus.h> +#include <core_io.h> +#include <keystore.h> +#include <policy/policy.h> +#include <policy/rbf.h> +#include <primitives/transaction.h> +#include <script/script.h> +#include <script/sign.h> #include <univalue.h> -#include "util.h" -#include "utilmoneystr.h" -#include "utilstrencodings.h" +#include <util.h> +#include <utilmoneystr.h> +#include <utilstrencodings.h> #include <stdio.h> @@ -77,18 +77,18 @@ static int AppInitRawTx(int argc, char* argv[]) 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("replaceable(=N)", _("Set RBF opt-in sequence number for input N (if not provided, opt-in all available inputs)")); strUsage += HelpMessageOpt("outaddr=VALUE:ADDRESS", _("Add address-based output to TX")); + strUsage += HelpMessageOpt("outdata=[VALUE:]DATA", _("Add data-based output to TX")); + 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("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[: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("replaceable(=N)", _("Set RBF opt-in sequence number for input N (if not provided, opt-in all available inputs)")); strUsage += HelpMessageOpt("sign=SIGHASH-FLAGS", _("Add zero or more signatures to transaction") + ". " + _("This command requires JSON registers:") + _("prevtxs=JSON object") + ", " + @@ -305,11 +305,14 @@ static void MutateTxAddOutPubKey(CMutableTransaction& tx, const std::string& str 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); + bSegWit = (flags.find('W') != std::string::npos); + bScriptHash = (flags.find('S') != std::string::npos); } if (bSegWit) { + if (!pubkey.IsCompressed()) { + throw std::runtime_error("Uncompressed pubkeys are not useable for SegWit outputs"); + } // Call GetScriptForWitness() to build a P2WSH scriptPubKey scriptPubKey = GetScriptForWitness(scriptPubKey); } @@ -364,8 +367,8 @@ static void MutateTxAddOutMultiSig(CMutableTransaction& tx, const std::string& s 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); + 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 @@ -375,10 +378,19 @@ static void MutateTxAddOutMultiSig(CMutableTransaction& tx, const std::string& s CScript scriptPubKey = GetScriptForMultisig(required, pubkeys); if (bSegWit) { + for (CPubKey& pubkey : pubkeys) { + if (!pubkey.IsCompressed()) { + throw std::runtime_error("Uncompressed pubkeys are not useable for SegWit outputs"); + } + } // Call GetScriptForWitness() to build a P2WSH scriptPubKey scriptPubKey = GetScriptForWitness(scriptPubKey); } if (bScriptHash) { + if (scriptPubKey.size() > MAX_SCRIPT_ELEMENT_SIZE) { + throw std::runtime_error(strprintf( + "redeemScript exceeds size limit: %d > %d", scriptPubKey.size(), MAX_SCRIPT_ELEMENT_SIZE)); + } // Get the ID for the script, and then construct a P2SH destination for it. scriptPubKey = GetScriptForDestination(CScriptID(scriptPubKey)); } @@ -435,14 +447,23 @@ static void MutateTxAddOutScript(CMutableTransaction& tx, const std::string& str 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); + bSegWit = (flags.find('W') != std::string::npos); + bScriptHash = (flags.find('S') != std::string::npos); + } + + if (scriptPubKey.size() > MAX_SCRIPT_SIZE) { + throw std::runtime_error(strprintf( + "script exceeds size limit: %d > %d", scriptPubKey.size(), MAX_SCRIPT_SIZE)); } if (bSegWit) { scriptPubKey = GetScriptForWitness(scriptPubKey); } if (bScriptHash) { + if (scriptPubKey.size() > MAX_SCRIPT_ELEMENT_SIZE) { + throw std::runtime_error(strprintf( + "redeemScript exceeds size limit: %d > %d", scriptPubKey.size(), MAX_SCRIPT_ELEMENT_SIZE)); + } scriptPubKey = GetScriptForDestination(CScriptID(scriptPubKey)); } @@ -682,10 +703,10 @@ static void MutateTx(CMutableTransaction& tx, const std::string& command, else if (command == "outaddr") MutateTxAddOutAddr(tx, commandVal); else if (command == "outpubkey") { - if (!ecc) { ecc.reset(new Secp256k1Init()); } + ecc.reset(new Secp256k1Init()); MutateTxAddOutPubKey(tx, commandVal); } else if (command == "outmultisig") { - if (!ecc) { ecc.reset(new Secp256k1Init()); } + ecc.reset(new Secp256k1Init()); MutateTxAddOutMultiSig(tx, commandVal); } else if (command == "outscript") MutateTxAddOutScript(tx, commandVal); @@ -693,7 +714,7 @@ static void MutateTx(CMutableTransaction& tx, const std::string& command, MutateTxAddOutData(tx, commandVal); else if (command == "sign") { - if (!ecc) { ecc.reset(new Secp256k1Init()); } + ecc.reset(new Secp256k1Init()); MutateTxSign(tx, commandVal); } |