Changeset View
Changeset View
Standalone View
Standalone View
src/bitcoin-tx.cpp
| // Copyright (c) 2009-2016 The Bitcoin Core developers | // Copyright (c) 2009-2016 The Bitcoin Core developers | ||||
| // Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
| #if defined(HAVE_CONFIG_H) | #if defined(HAVE_CONFIG_H) | ||||
| #include "config/bitcoin-config.h" | #include "config/bitcoin-config.h" | ||||
| #endif | #endif | ||||
| #include "base58.h" | #include "base58.h" | ||||
| #include "chainparams.h" | |||||
| #include "clientversion.h" | #include "clientversion.h" | ||||
| #include "coins.h" | #include "coins.h" | ||||
| #include "config.h" | |||||
| #include "consensus/consensus.h" | #include "consensus/consensus.h" | ||||
| #include "core_io.h" | #include "core_io.h" | ||||
| #include "dstencode.h" | #include "dstencode.h" | ||||
| #include "keystore.h" | #include "keystore.h" | ||||
| #include "policy/policy.h" | #include "policy/policy.h" | ||||
| #include "primitives/transaction.h" | #include "primitives/transaction.h" | ||||
| #include "script/script.h" | #include "script/script.h" | ||||
| #include "script/sign.h" | #include "script/sign.h" | ||||
| ▲ Show 20 Lines • Show All 241 Lines • ▼ Show 20 Lines | static void MutateTxAddInput(CMutableTransaction &tx, | ||||
| // append to transaction input list | // append to transaction input list | ||||
| CTxIn txin(txid, vout, CScript(), nSequenceIn); | CTxIn txin(txid, vout, CScript(), nSequenceIn); | ||||
| tx.vin.push_back(txin); | tx.vin.push_back(txin); | ||||
| } | } | ||||
| static void MutateTxAddOutAddr(CMutableTransaction &tx, | static void MutateTxAddOutAddr(CMutableTransaction &tx, | ||||
| const std::string &strInput, | const std::string &strInput, | ||||
| const CChainParams &chainParams) { | const Config &config) { | ||||
| // Separate into VALUE:ADDRESS | // Separate into VALUE:ADDRESS | ||||
| std::vector<std::string> vStrInputParts; | std::vector<std::string> vStrInputParts; | ||||
| boost::split(vStrInputParts, strInput, boost::is_any_of(":")); | boost::split(vStrInputParts, strInput, boost::is_any_of(":")); | ||||
| if (vStrInputParts.size() != 2) { | if (vStrInputParts.size() != 2) { | ||||
| throw std::runtime_error("TX output missing or too many separators"); | throw std::runtime_error("TX output missing or too many separators"); | ||||
| } | } | ||||
| // Extract and validate VALUE | // Extract and validate VALUE | ||||
| Amount value = ExtractAndValidateValue(vStrInputParts[0]); | Amount value = ExtractAndValidateValue(vStrInputParts[0]); | ||||
| // extract and validate ADDRESS | // extract and validate ADDRESS | ||||
| std::string strAddr = vStrInputParts[1]; | std::string strAddr = vStrInputParts[1]; | ||||
| CTxDestination destination = DecodeDestination(strAddr, chainParams); | CTxDestination destination = DecodeDestination(strAddr, config); | ||||
| if (!IsValidDestination(destination)) { | if (!IsValidDestination(destination)) { | ||||
| throw std::runtime_error("invalid TX output address"); | throw std::runtime_error("invalid TX output address"); | ||||
| } | } | ||||
| CScript scriptPubKey = GetScriptForDestination(destination); | CScript scriptPubKey = GetScriptForDestination(destination); | ||||
| // construct TxOut, append to transaction output list | // construct TxOut, append to transaction output list | ||||
| CTxOut txout(value, scriptPubKey); | CTxOut txout(value, scriptPubKey); | ||||
| tx.vout.push_back(txout); | tx.vout.push_back(txout); | ||||
| ▲ Show 20 Lines • Show All 417 Lines • ▼ Show 20 Lines | class Secp256k1Init { | ||||
| ECCVerifyHandle globalVerifyHandle; | ECCVerifyHandle globalVerifyHandle; | ||||
| public: | public: | ||||
| Secp256k1Init() { ECC_Start(); } | Secp256k1Init() { ECC_Start(); } | ||||
| ~Secp256k1Init() { ECC_Stop(); } | ~Secp256k1Init() { ECC_Stop(); } | ||||
| }; | }; | ||||
| static void MutateTx(CMutableTransaction &tx, const std::string &command, | static void MutateTx(CMutableTransaction &tx, const std::string &command, | ||||
| const std::string &commandVal, | const std::string &commandVal, const Config &config) { | ||||
| const CChainParams &chainParams) { | |||||
| std::unique_ptr<Secp256k1Init> ecc; | std::unique_ptr<Secp256k1Init> ecc; | ||||
| if (command == "nversion") { | if (command == "nversion") { | ||||
| MutateTxVersion(tx, commandVal); | MutateTxVersion(tx, commandVal); | ||||
| } else if (command == "locktime") { | } else if (command == "locktime") { | ||||
| MutateTxLocktime(tx, commandVal); | MutateTxLocktime(tx, commandVal); | ||||
| } else if (command == "delin") { | } else if (command == "delin") { | ||||
| MutateTxDelInput(tx, commandVal); | MutateTxDelInput(tx, commandVal); | ||||
| } else if (command == "in") { | } else if (command == "in") { | ||||
| MutateTxAddInput(tx, commandVal); | MutateTxAddInput(tx, commandVal); | ||||
| } else if (command == "delout") { | } else if (command == "delout") { | ||||
| MutateTxDelOutput(tx, commandVal); | MutateTxDelOutput(tx, commandVal); | ||||
| } else if (command == "outaddr") { | } else if (command == "outaddr") { | ||||
| MutateTxAddOutAddr(tx, commandVal, chainParams); | MutateTxAddOutAddr(tx, commandVal, config); | ||||
| } else if (command == "outpubkey") { | } else if (command == "outpubkey") { | ||||
| MutateTxAddOutPubKey(tx, commandVal); | MutateTxAddOutPubKey(tx, commandVal); | ||||
| } else if (command == "outmultisig") { | } else if (command == "outmultisig") { | ||||
| MutateTxAddOutMultiSig(tx, commandVal); | MutateTxAddOutMultiSig(tx, commandVal); | ||||
| } else if (command == "outscript") { | } else if (command == "outscript") { | ||||
| MutateTxAddOutScript(tx, commandVal); | MutateTxAddOutScript(tx, commandVal); | ||||
| } else if (command == "outdata") { | } else if (command == "outdata") { | ||||
| MutateTxAddOutData(tx, commandVal); | MutateTxAddOutData(tx, commandVal); | ||||
| } else if (command == "sign") { | } else if (command == "sign") { | ||||
| if (!ecc) { | if (!ecc) { | ||||
| ecc.reset(new Secp256k1Init()); | ecc.reset(new Secp256k1Init()); | ||||
| } | } | ||||
| MutateTxSign(tx, commandVal); | MutateTxSign(tx, commandVal); | ||||
| } else if (command == "load") { | } else if (command == "load") { | ||||
| RegisterLoad(commandVal); | RegisterLoad(commandVal); | ||||
| } else if (command == "set") { | } else if (command == "set") { | ||||
| RegisterSet(commandVal); | RegisterSet(commandVal); | ||||
| } else { | } else { | ||||
| throw std::runtime_error("unknown command"); | throw std::runtime_error("unknown command"); | ||||
| } | } | ||||
| } | } | ||||
| static void OutputTxJSON(const CTransaction &tx) { | static void OutputTxJSON(const CTransaction &tx, const Config &config) { | ||||
| UniValue entry(UniValue::VOBJ); | UniValue entry(UniValue::VOBJ); | ||||
| TxToUniv(tx, uint256(), entry); | TxToUniv(tx, uint256(), entry, config); | ||||
| std::string jsonOutput = entry.write(4); | std::string jsonOutput = entry.write(4); | ||||
| fprintf(stdout, "%s\n", jsonOutput.c_str()); | fprintf(stdout, "%s\n", jsonOutput.c_str()); | ||||
| } | } | ||||
| static void OutputTxHash(const CTransaction &tx) { | static void OutputTxHash(const CTransaction &tx) { | ||||
| // the hex-encoded transaction id. | // the hex-encoded transaction id. | ||||
| std::string strHexHash = tx.GetId().GetHex(); | std::string strHexHash = tx.GetId().GetHex(); | ||||
| fprintf(stdout, "%s\n", strHexHash.c_str()); | fprintf(stdout, "%s\n", strHexHash.c_str()); | ||||
| } | } | ||||
| static void OutputTxHex(const CTransaction &tx) { | static void OutputTxHex(const CTransaction &tx) { | ||||
| std::string strHex = EncodeHexTx(tx); | std::string strHex = EncodeHexTx(tx); | ||||
| fprintf(stdout, "%s\n", strHex.c_str()); | fprintf(stdout, "%s\n", strHex.c_str()); | ||||
| } | } | ||||
| static void OutputTx(const CTransaction &tx) { | static void OutputTx(const CTransaction &tx, const Config &config) { | ||||
| if (gArgs.GetBoolArg("-json", false)) { | if (gArgs.GetBoolArg("-json", false)) { | ||||
| OutputTxJSON(tx); | OutputTxJSON(tx, config); | ||||
| } else if (gArgs.GetBoolArg("-txid", false)) { | } else if (gArgs.GetBoolArg("-txid", false)) { | ||||
| OutputTxHash(tx); | OutputTxHash(tx); | ||||
| } else { | } else { | ||||
| OutputTxHex(tx); | OutputTxHex(tx); | ||||
| } | } | ||||
| } | } | ||||
| static std::string readStdin() { | static std::string readStdin() { | ||||
| Show All 12 Lines | if (ferror(stdin)) { | ||||
| throw std::runtime_error("error reading stdin"); | throw std::runtime_error("error reading stdin"); | ||||
| } | } | ||||
| boost::algorithm::trim_right(ret); | boost::algorithm::trim_right(ret); | ||||
| return ret; | return ret; | ||||
| } | } | ||||
| static int CommandLineRawTx(int argc, char *argv[], | static int CommandLineRawTx(int argc, char *argv[], const Config &config) { | ||||
| const CChainParams &chainParams) { | |||||
| std::string strPrint; | std::string strPrint; | ||||
| int nRet = 0; | int nRet = 0; | ||||
| try { | try { | ||||
| // Skip switches; Permit common stdin convention "-" | // Skip switches; Permit common stdin convention "-" | ||||
| while (argc > 1 && IsSwitchChar(argv[1][0]) && (argv[1][1] != 0)) { | while (argc > 1 && IsSwitchChar(argv[1][0]) && (argv[1][1] != 0)) { | ||||
| argc--; | argc--; | ||||
| argv++; | argv++; | ||||
| } | } | ||||
| Show All 30 Lines | try { | ||||
| size_t eqpos = arg.find('='); | size_t eqpos = arg.find('='); | ||||
| if (eqpos == std::string::npos) { | if (eqpos == std::string::npos) { | ||||
| key = arg; | key = arg; | ||||
| } else { | } else { | ||||
| key = arg.substr(0, eqpos); | key = arg.substr(0, eqpos); | ||||
| value = arg.substr(eqpos + 1); | value = arg.substr(eqpos + 1); | ||||
| } | } | ||||
| MutateTx(tx, key, value, chainParams); | MutateTx(tx, key, value, config); | ||||
| } | } | ||||
| OutputTx(CTransaction(tx)); | OutputTx(CTransaction(tx), config); | ||||
| } | } | ||||
| catch (const boost::thread_interrupted &) { | catch (const boost::thread_interrupted &) { | ||||
| throw; | throw; | ||||
| } catch (const std::exception &e) { | } catch (const std::exception &e) { | ||||
| strPrint = std::string("error: ") + e.what(); | strPrint = std::string("error: ") + e.what(); | ||||
| nRet = EXIT_FAILURE; | nRet = EXIT_FAILURE; | ||||
| } catch (...) { | } catch (...) { | ||||
| PrintExceptionContinue(nullptr, "CommandLineRawTx()"); | PrintExceptionContinue(nullptr, "CommandLineRawTx()"); | ||||
| throw; | throw; | ||||
| } | } | ||||
| if (strPrint != "") { | if (strPrint != "") { | ||||
| fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str()); | fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str()); | ||||
| } | } | ||||
| return nRet; | return nRet; | ||||
| } | } | ||||
| int main(int argc, char *argv[]) { | int main(int argc, char *argv[]) { | ||||
| auto &config = const_cast<Config &>(GetConfig()); | |||||
| SetupEnvironment(); | SetupEnvironment(); | ||||
| try { | try { | ||||
| int ret = AppInitRawTx(argc, argv); | int ret = AppInitRawTx(argc, argv); | ||||
| if (ret != CONTINUE_EXECUTION) return ret; | if (ret != CONTINUE_EXECUTION) return ret; | ||||
| } catch (const std::exception &e) { | } catch (const std::exception &e) { | ||||
| PrintExceptionContinue(&e, "AppInitRawTx()"); | PrintExceptionContinue(&e, "AppInitRawTx()"); | ||||
| return EXIT_FAILURE; | return EXIT_FAILURE; | ||||
| } catch (...) { | } catch (...) { | ||||
| PrintExceptionContinue(nullptr, "AppInitRawTx()"); | PrintExceptionContinue(nullptr, "AppInitRawTx()"); | ||||
| return EXIT_FAILURE; | return EXIT_FAILURE; | ||||
| } | } | ||||
| int ret = EXIT_FAILURE; | int ret = EXIT_FAILURE; | ||||
| try { | try { | ||||
| ret = CommandLineRawTx(argc, argv, Params()); | ret = CommandLineRawTx(argc, argv, config); | ||||
| } catch (const std::exception &e) { | } catch (const std::exception &e) { | ||||
| PrintExceptionContinue(&e, "CommandLineRawTx()"); | PrintExceptionContinue(&e, "CommandLineRawTx()"); | ||||
| } catch (...) { | } catch (...) { | ||||
| PrintExceptionContinue(nullptr, "CommandLineRawTx()"); | PrintExceptionContinue(nullptr, "CommandLineRawTx()"); | ||||
| } | } | ||||
| return ret; | return ret; | ||||
| } | } | ||||