dash/src/dash-tx.cpp

698 lines
21 KiB
C++
Raw Normal View History

// Copyright (c) 2009-2015 The Bitcoin Core developers
2014-12-13 05:09:33 +01:00
// Distributed under the MIT software license, see the accompanying
2015-04-03 00:51:08 +02:00
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
Merge #7192: Unify product name to as few places as possible 027fdb8 When/if the copyright line does not mention Bitcoin Core developers, add a second line to copyrights in -version, About dialog, and splash screen (Luke Dashjr) cc2095e Rewrite FormatParagraph to handle newlines within input strings correctly (Luke Dashjr) cddffaf Bugfix: Include COPYRIGHT_HOLDERS_SUBSTITUTION in Makefile substitutions so it gets passed to extract-strings correctly (Luke Dashjr) 29598e4 Move PACKAGE_URL to configure.ac (Luke Dashjr) 78ec83d splashscreen: Resize text to fit exactly (Luke Dashjr) 3cae140 Bugfix: Actually use _COPYRIGHT_HOLDERS_SUBSTITUTION everywhere (Luke Dashjr) 4d5a3df Bugfix: gitian-descriptors: Add missing python-setuptools requirement for OS X (biplist module) (Luke Dashjr) e4ab5e5 Bugfix: Correct copyright year in Mac DMG background image (Luke Dashjr) 917b1d0 Set copyright holders displayed in notices separately from the package name (Luke Dashjr) c39a6ff Travis & gitian-osx: Use depends for ds_store and mac_alias modules (Luke Dashjr) 902ccde depends: Add mac_alias to depends (Luke Dashjr) 82a2d98 depends: Add ds_store to depends (Cory Fields) de619a3 depends: Pass PYTHONPATH along to configure (Cory Fields) e611b6e macdeploy: Use rsvg-convert rather than cairosvg (Luke Dashjr) 63bcdc5 More complicated package name substitution for Mac deployment (Luke Dashjr) 1a6c67c Parameterise 2009 in translatable copyright strings (Luke Dashjr) d5f4683 Unify package name to as few places as possible without major changes (Luke Dashjr)
2016-02-04 13:41:58 +01:00
#if defined(HAVE_CONFIG_H)
#include "config/dash-config.h"
#endif
2015-04-03 00:51:08 +02:00
#include "base58.h"
#include "clientversion.h"
#include "coins.h"
#include "consensus/consensus.h"
#include "core_io.h"
2015-04-03 00:51:08 +02:00
#include "keystore.h"
#include "policy/policy.h"
#include "primitives/transaction.h"
2015-04-03 00:51:08 +02:00
#include "script/script.h"
#include "script/sign.h"
#include <univalue.h>
2015-04-03 00:51:08 +02:00
#include "util.h"
#include "utilmoneystr.h"
#include "utilstrencodings.h"
2015-04-03 00:51:08 +02:00
#include <stdio.h>
#include <boost/algorithm/string.hpp>
#include <boost/assign/list_of.hpp>
using namespace std;
static bool fCreateBlank;
static map<string,UniValue> registers;
static const int CONTINUE_EXECUTION=-1;
2015-04-03 00:51:08 +02:00
//
// 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[])
2015-04-03 00:51:08 +02:00
{
//
// Parameters
//
ParseParameters(argc, argv);
// Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
try {
SelectParams(ChainNameFromCommandLine());
} catch (const std::exception& e) {
fprintf(stderr, "Error: %s\n", e.what());
return EXIT_FAILURE;
2015-04-03 00:51:08 +02:00
}
fCreateBlank = GetBoolArg("-create", false);
2015-10-18 12:02:36 +02:00
if (argc<2 || mapArgs.count("-?") || mapArgs.count("-h") || mapArgs.count("-help"))
2015-04-03 00:51:08 +02:00
{
// First part of help message is specific to this utility
Merge #7192: Unify product name to as few places as possible 027fdb8 When/if the copyright line does not mention Bitcoin Core developers, add a second line to copyrights in -version, About dialog, and splash screen (Luke Dashjr) cc2095e Rewrite FormatParagraph to handle newlines within input strings correctly (Luke Dashjr) cddffaf Bugfix: Include COPYRIGHT_HOLDERS_SUBSTITUTION in Makefile substitutions so it gets passed to extract-strings correctly (Luke Dashjr) 29598e4 Move PACKAGE_URL to configure.ac (Luke Dashjr) 78ec83d splashscreen: Resize text to fit exactly (Luke Dashjr) 3cae140 Bugfix: Actually use _COPYRIGHT_HOLDERS_SUBSTITUTION everywhere (Luke Dashjr) 4d5a3df Bugfix: gitian-descriptors: Add missing python-setuptools requirement for OS X (biplist module) (Luke Dashjr) e4ab5e5 Bugfix: Correct copyright year in Mac DMG background image (Luke Dashjr) 917b1d0 Set copyright holders displayed in notices separately from the package name (Luke Dashjr) c39a6ff Travis & gitian-osx: Use depends for ds_store and mac_alias modules (Luke Dashjr) 902ccde depends: Add mac_alias to depends (Luke Dashjr) 82a2d98 depends: Add ds_store to depends (Cory Fields) de619a3 depends: Pass PYTHONPATH along to configure (Cory Fields) e611b6e macdeploy: Use rsvg-convert rather than cairosvg (Luke Dashjr) 63bcdc5 More complicated package name substitution for Mac deployment (Luke Dashjr) 1a6c67c Parameterise 2009 in translatable copyright strings (Luke Dashjr) d5f4683 Unify package name to as few places as possible without major changes (Luke Dashjr)
2016-02-04 13:41:58 +01:00
std::string strUsage = strprintf(_("%s dash-tx utility version"), _(PACKAGE_NAME)) + " " + FormatFullVersion() + "\n\n" +
2015-04-03 00:51:08 +02:00
_("Usage:") + "\n" +
2015-04-05 23:56:58 +02:00
" dash-tx [options] <hex-tx> [commands] " + _("Update hex-encoded dash transaction") + "\n" +
" dash-tx [options] -create [commands] " + _("Create hex-encoded dash transaction") + "\n" +
2015-04-03 00:51:08 +02:00
"\n";
fprintf(stdout, "%s", strUsage.c_str());
strUsage = HelpMessageGroup(_("Options:"));
strUsage += HelpMessageOpt("-?", _("This help message"));
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."));
AppendParamsHelpMessages(strUsage);
2015-04-03 00:51:08 +02:00
fprintf(stdout, "%s", strUsage.c_str());
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(: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"));
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:") +
_("prevtxs=JSON object") + ", " +
_("privatekeys=JSON object") + ". " +
_("See signrawtransaction docs for format of sighash flags, JSON objects."));
2015-04-03 00:51:08 +02:00
fprintf(stdout, "%s", strUsage.c_str());
strUsage = HelpMessageGroup(_("Register Commands:"));
strUsage += HelpMessageOpt("load=NAME:FILENAME", _("Load JSON file FILENAME into register NAME"));
strUsage += HelpMessageOpt("set=NAME:JSON-STRING", _("Set register NAME to given JSON-STRING"));
2015-04-03 00:51:08 +02:00
fprintf(stdout, "%s", strUsage.c_str());
if (argc < 2) {
fprintf(stderr, "Error: too few parameters\n");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
2015-04-03 00:51:08 +02:00
}
return CONTINUE_EXECUTION;
2015-04-03 00:51:08 +02:00
}
static void RegisterSetJson(const string& key, const string& rawJson)
{
UniValue val;
if (!val.read(rawJson)) {
string strErr = "Cannot parse JSON for key " + key;
throw runtime_error(strErr);
}
registers[key] = val;
}
static void RegisterSet(const string& strInput)
{
// separate NAME:VALUE in string
size_t pos = strInput.find(':');
if ((pos == string::npos) ||
(pos == 0) ||
(pos == (strInput.size() - 1)))
throw runtime_error("Register input requires NAME:VALUE");
string key = strInput.substr(0, pos);
string valStr = strInput.substr(pos + 1, string::npos);
RegisterSetJson(key, valStr);
}
static void RegisterLoad(const string& strInput)
{
// separate NAME:FILENAME in string
size_t pos = strInput.find(':');
if ((pos == string::npos) ||
(pos == 0) ||
(pos == (strInput.size() - 1)))
throw runtime_error("Register load requires NAME:FILENAME");
string key = strInput.substr(0, pos);
string filename = strInput.substr(pos + 1, string::npos);
FILE *f = fopen(filename.c_str(), "r");
if (!f) {
string strErr = "Cannot open file " + filename;
throw runtime_error(strErr);
}
// load file chunks into one big buffer
string valStr;
while ((!feof(f)) && (!ferror(f))) {
char buf[4096];
int bread = fread(buf, 1, sizeof(buf), f);
if (bread <= 0)
break;
valStr.insert(valStr.size(), buf, bread);
}
int error = ferror(f);
fclose(f);
if (error) {
2015-04-03 00:51:08 +02:00
string strErr = "Error reading file " + filename;
throw runtime_error(strErr);
}
// evaluate as JSON buffer register
RegisterSetJson(key, valStr);
}
static void MutateTxVersion(CMutableTransaction& tx, const string& cmdVal)
{
int64_t newVersion = atoi64(cmdVal);
if (newVersion < 1 || newVersion > CTransaction::CURRENT_VERSION)
throw runtime_error("Invalid TX version requested");
tx.nVersion = (int) newVersion;
}
static void MutateTxLocktime(CMutableTransaction& tx, const string& cmdVal)
{
int64_t newLocktime = atoi64(cmdVal);
if (newLocktime < 0LL || newLocktime > 0xffffffffLL)
throw runtime_error("Invalid TX locktime requested");
tx.nLockTime = (unsigned int) newLocktime;
}
static void MutateTxAddInput(CMutableTransaction& tx, const string& strInput)
{
std::vector<std::string> vStrInputParts;
boost::split(vStrInputParts, strInput, boost::is_any_of(":"));
2015-04-03 00:51:08 +02:00
// separate TXID:VOUT in string
if (vStrInputParts.size()<2)
2015-04-03 00:51:08 +02:00
throw runtime_error("TX input missing separator");
// extract and validate TXID
string strTxid = vStrInputParts[0];
2015-04-03 00:51:08 +02:00
if ((strTxid.size() != 64) || !IsHex(strTxid))
throw runtime_error("invalid TX input txid");
uint256 txid(uint256S(strTxid));
2015-04-03 00:51:08 +02:00
static const unsigned int minTxOutSz = 9;
static const unsigned int maxVout = MaxBlockSize(true) / minTxOutSz;
2015-04-03 00:51:08 +02:00
// extract and validate vout
string strVout = vStrInputParts[1];
2015-04-03 00:51:08 +02:00
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<unsigned int>::max();
if (vStrInputParts.size() > 2)
nSequenceIn = std::stoul(vStrInputParts[2]);
2015-04-03 00:51:08 +02:00
// append to transaction input list
CTxIn txin(txid, vout, CScript(), nSequenceIn);
2015-04-03 00:51:08 +02:00
tx.vin.push_back(txin);
}
static void MutateTxAddOutAddr(CMutableTransaction& tx, const string& strInput)
{
// separate VALUE:ADDRESS in string
size_t pos = strInput.find(':');
if ((pos == string::npos) ||
(pos == 0) ||
(pos == (strInput.size() - 1)))
throw runtime_error("TX output missing separator");
// extract and validate VALUE
string strValue = strInput.substr(0, pos);
CAmount value;
if (!ParseMoney(strValue, value))
throw runtime_error("invalid TX output value");
// extract and validate ADDRESS
string strAddr = strInput.substr(pos + 1, string::npos);
CBitcoinAddress addr(strAddr);
if (!addr.IsValid())
throw runtime_error("invalid TX output address");
// build standard output script via GetScriptForDestination()
CScript 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 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<unsigned char> data = ParseHex(strData);
CTxOut txout(value, CScript() << OP_RETURN << data);
tx.vout.push_back(txout);
}
2015-04-03 00:51:08 +02:00
static void MutateTxAddOutScript(CMutableTransaction& tx, const string& strInput)
{
// separate VALUE:SCRIPT in string
size_t pos = strInput.find(':');
if ((pos == string::npos) ||
(pos == 0))
throw runtime_error("TX output missing separator");
// extract and validate VALUE
string strValue = strInput.substr(0, pos);
CAmount value;
if (!ParseMoney(strValue, value))
throw runtime_error("invalid TX output value");
// extract and validate script
string strScript = strInput.substr(pos + 1, string::npos);
CScript scriptPubKey = ParseScript(strScript); // throws on err
// construct TxOut, append to transaction output list
CTxOut txout(value, scriptPubKey);
tx.vout.push_back(txout);
}
static void MutateTxDelInput(CMutableTransaction& tx, const 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());
}
// delete input from transaction
tx.vin.erase(tx.vin.begin() + inIdx);
}
static void MutateTxDelOutput(CMutableTransaction& tx, const 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());
}
// delete output from transaction
tx.vout.erase(tx.vout.begin() + outIdx);
}
static const unsigned int N_SIGHASH_OPTS = 6;
static const struct {
const char *flagStr;
int flags;
} sighashOptions[N_SIGHASH_OPTS] = {
{"ALL", SIGHASH_ALL},
{"NONE", SIGHASH_NONE},
{"SINGLE", SIGHASH_SINGLE},
{"ALL|ANYONECANPAY", SIGHASH_ALL|SIGHASH_ANYONECANPAY},
{"NONE|ANYONECANPAY", SIGHASH_NONE|SIGHASH_ANYONECANPAY},
{"SINGLE|ANYONECANPAY", SIGHASH_SINGLE|SIGHASH_ANYONECANPAY},
};
static bool findSighashFlags(int& flags, const string& flagStr)
{
flags = 0;
for (unsigned int i = 0; i < N_SIGHASH_OPTS; i++) {
if (flagStr == sighashOptions[i].flagStr) {
flags = sighashOptions[i].flags;
return true;
}
}
return false;
}
uint256 ParseHashUO(map<string,UniValue>& o, string strKey)
{
if (!o.count(strKey))
return uint256();
2015-04-03 00:51:08 +02:00
return ParseHashUV(o[strKey], strKey);
}
vector<unsigned char> ParseHexUO(map<string,UniValue>& o, string strKey)
{
if (!o.count(strKey)) {
vector<unsigned char> emptyVec;
return emptyVec;
}
return ParseHexUV(o[strKey], strKey);
}
static void MutateTxSign(CMutableTransaction& tx, const string& flagStr)
{
int nHashType = SIGHASH_ALL;
if (flagStr.size() > 0)
if (!findSighashFlags(nHashType, flagStr))
throw runtime_error("unknown sighash flag/sign option");
vector<CTransaction> txVariants;
txVariants.push_back(tx);
// mergedTx will end up with all the signatures; it
// starts as a clone of the raw tx:
CMutableTransaction mergedTx(txVariants[0]);
bool fComplete = true;
CCoinsView viewDummy;
CCoinsViewCache view(&viewDummy);
if (!registers.count("privatekeys"))
throw runtime_error("privatekeys register variable must be set.");
CBasicKeyStore tempKeystore;
UniValue keysObj = registers["privatekeys"];
for (unsigned int kidx = 0; kidx < keysObj.size(); kidx++) {
2015-04-03 00:51:08 +02:00
if (!keysObj[kidx].isStr())
throw runtime_error("privatekey not a string");
CBitcoinSecret vchSecret;
bool fGood = vchSecret.SetString(keysObj[kidx].getValStr());
if (!fGood)
throw runtime_error("privatekey not valid");
CKey key = vchSecret.GetKey();
tempKeystore.AddKey(key);
}
// Add previous txouts given in the RPC call:
if (!registers.count("prevtxs"))
throw runtime_error("prevtxs register variable must be set.");
UniValue prevtxsObj = registers["prevtxs"];
{
for (unsigned int previdx = 0; previdx < prevtxsObj.size(); previdx++) {
2015-04-03 00:51:08 +02:00
UniValue prevOut = prevtxsObj[previdx];
if (!prevOut.isObject())
throw runtime_error("expected prevtxs internal object");
map<string,UniValue::VType> types = boost::assign::map_list_of("txid", UniValue::VSTR)("vout",UniValue::VNUM)("scriptPubKey",UniValue::VSTR);
2015-04-03 00:51:08 +02:00
if (!prevOut.checkObject(types))
throw 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");
Merge #10195: Switch chainstate db and cache to per-txout model 589827975 scripted-diff: various renames for per-utxo consistency (Pieter Wuille) a5e02bc7f Increase travis unit test timeout (Pieter Wuille) 73de2c1ff Rename CCoinsCacheEntry::coins to coin (Pieter Wuille) 119e552f7 Merge CCoinsViewCache's GetOutputFor and AccessCoin (Pieter Wuille) 580b02309 [MOVEONLY] Move old CCoins class to txdb.cpp (Pieter Wuille) 8b25d2c0c Upgrade from per-tx database to per-txout (Pieter Wuille) b2af357f3 Reduce reserved memory space for flushing (Pieter Wuille) 41aa5b79a Pack Coin more tightly (Pieter Wuille) 97072d668 Remove unused CCoins methods (Pieter Wuille) ce23efaa5 Extend coins_tests (Pieter Wuille) 508307968 Switch CCoinsView and chainstate db from per-txid to per-txout (Pieter Wuille) 4ec0d9e79 Refactor GetUTXOStats in preparation for per-COutPoint iteration (Pieter Wuille) 13870b56f Replace CCoins-based CTxMemPool::pruneSpent with isSpent (Pieter Wuille) 05293f3cb Remove ModifyCoins/ModifyNewCoins (Pieter Wuille) 961e48397 Switch tests from ModifyCoins to AddCoin/SpendCoin (Pieter Wuille) 8b3868c1b Switch CScriptCheck to use Coin instead of CCoins (Pieter Wuille) c87b957a3 Only pass things committed to by tx's witness hash to CScriptCheck (Matt Corallo) f68cdfe92 Switch from per-tx to per-txout CCoinsViewCache methods in some places (Pieter Wuille) 000391132 Introduce new per-txout CCoinsViewCache functions (Pieter Wuille) bd83111a0 Optimization: Coin&& to ApplyTxInUndo (Pieter Wuille) cb2c7fdac Replace CTxInUndo with Coin (Pieter Wuille) 422634e2f Introduce Coin, a single unspent output (Pieter Wuille) 7d991b55d Store/allow tx metadata in all undo records (Pieter Wuille) c3aa0c119 Report on-disk size in gettxoutsetinfo (Pieter Wuille) d34242430 Remove/ignore tx version in utxo and undo (Pieter Wuille) 7e0032290 Add specialization of SipHash for 256 + 32 bit data (Pieter Wuille) e484652fc Introduce CHashVerifier to hash read data (Pieter Wuille) f54580e7e error() in disconnect for disk corruption, not inconsistency (Pieter Wuille) e66dbde6d Add SizeEstimate to CDBBatch (Pieter Wuille) Tree-SHA512: ce1fb1e40c77d38915cd02189fab7a8b125c7f44d425c85579d872c3bede3a437760997907c99d7b3017ced1c2de54b2ac7223d99d83a6658fe5ef61edef1de3
2017-06-02 00:47:58 +02:00
COutPoint out(txid, nOut);
2015-04-03 00:51:08 +02:00
vector<unsigned char> pkData(ParseHexUV(prevOut["scriptPubKey"], "scriptPubKey"));
CScript scriptPubKey(pkData.begin(), pkData.end());
{
Merge #10195: Switch chainstate db and cache to per-txout model 589827975 scripted-diff: various renames for per-utxo consistency (Pieter Wuille) a5e02bc7f Increase travis unit test timeout (Pieter Wuille) 73de2c1ff Rename CCoinsCacheEntry::coins to coin (Pieter Wuille) 119e552f7 Merge CCoinsViewCache's GetOutputFor and AccessCoin (Pieter Wuille) 580b02309 [MOVEONLY] Move old CCoins class to txdb.cpp (Pieter Wuille) 8b25d2c0c Upgrade from per-tx database to per-txout (Pieter Wuille) b2af357f3 Reduce reserved memory space for flushing (Pieter Wuille) 41aa5b79a Pack Coin more tightly (Pieter Wuille) 97072d668 Remove unused CCoins methods (Pieter Wuille) ce23efaa5 Extend coins_tests (Pieter Wuille) 508307968 Switch CCoinsView and chainstate db from per-txid to per-txout (Pieter Wuille) 4ec0d9e79 Refactor GetUTXOStats in preparation for per-COutPoint iteration (Pieter Wuille) 13870b56f Replace CCoins-based CTxMemPool::pruneSpent with isSpent (Pieter Wuille) 05293f3cb Remove ModifyCoins/ModifyNewCoins (Pieter Wuille) 961e48397 Switch tests from ModifyCoins to AddCoin/SpendCoin (Pieter Wuille) 8b3868c1b Switch CScriptCheck to use Coin instead of CCoins (Pieter Wuille) c87b957a3 Only pass things committed to by tx's witness hash to CScriptCheck (Matt Corallo) f68cdfe92 Switch from per-tx to per-txout CCoinsViewCache methods in some places (Pieter Wuille) 000391132 Introduce new per-txout CCoinsViewCache functions (Pieter Wuille) bd83111a0 Optimization: Coin&& to ApplyTxInUndo (Pieter Wuille) cb2c7fdac Replace CTxInUndo with Coin (Pieter Wuille) 422634e2f Introduce Coin, a single unspent output (Pieter Wuille) 7d991b55d Store/allow tx metadata in all undo records (Pieter Wuille) c3aa0c119 Report on-disk size in gettxoutsetinfo (Pieter Wuille) d34242430 Remove/ignore tx version in utxo and undo (Pieter Wuille) 7e0032290 Add specialization of SipHash for 256 + 32 bit data (Pieter Wuille) e484652fc Introduce CHashVerifier to hash read data (Pieter Wuille) f54580e7e error() in disconnect for disk corruption, not inconsistency (Pieter Wuille) e66dbde6d Add SizeEstimate to CDBBatch (Pieter Wuille) Tree-SHA512: ce1fb1e40c77d38915cd02189fab7a8b125c7f44d425c85579d872c3bede3a437760997907c99d7b3017ced1c2de54b2ac7223d99d83a6658fe5ef61edef1de3
2017-06-02 00:47:58 +02:00
const Coin& coin = view.AccessCoin(out);
if (!coin.IsSpent() && coin.out.scriptPubKey != scriptPubKey) {
2015-04-03 00:51:08 +02:00
string err("Previous output scriptPubKey mismatch:\n");
Merge #10195: Switch chainstate db and cache to per-txout model 589827975 scripted-diff: various renames for per-utxo consistency (Pieter Wuille) a5e02bc7f Increase travis unit test timeout (Pieter Wuille) 73de2c1ff Rename CCoinsCacheEntry::coins to coin (Pieter Wuille) 119e552f7 Merge CCoinsViewCache's GetOutputFor and AccessCoin (Pieter Wuille) 580b02309 [MOVEONLY] Move old CCoins class to txdb.cpp (Pieter Wuille) 8b25d2c0c Upgrade from per-tx database to per-txout (Pieter Wuille) b2af357f3 Reduce reserved memory space for flushing (Pieter Wuille) 41aa5b79a Pack Coin more tightly (Pieter Wuille) 97072d668 Remove unused CCoins methods (Pieter Wuille) ce23efaa5 Extend coins_tests (Pieter Wuille) 508307968 Switch CCoinsView and chainstate db from per-txid to per-txout (Pieter Wuille) 4ec0d9e79 Refactor GetUTXOStats in preparation for per-COutPoint iteration (Pieter Wuille) 13870b56f Replace CCoins-based CTxMemPool::pruneSpent with isSpent (Pieter Wuille) 05293f3cb Remove ModifyCoins/ModifyNewCoins (Pieter Wuille) 961e48397 Switch tests from ModifyCoins to AddCoin/SpendCoin (Pieter Wuille) 8b3868c1b Switch CScriptCheck to use Coin instead of CCoins (Pieter Wuille) c87b957a3 Only pass things committed to by tx's witness hash to CScriptCheck (Matt Corallo) f68cdfe92 Switch from per-tx to per-txout CCoinsViewCache methods in some places (Pieter Wuille) 000391132 Introduce new per-txout CCoinsViewCache functions (Pieter Wuille) bd83111a0 Optimization: Coin&& to ApplyTxInUndo (Pieter Wuille) cb2c7fdac Replace CTxInUndo with Coin (Pieter Wuille) 422634e2f Introduce Coin, a single unspent output (Pieter Wuille) 7d991b55d Store/allow tx metadata in all undo records (Pieter Wuille) c3aa0c119 Report on-disk size in gettxoutsetinfo (Pieter Wuille) d34242430 Remove/ignore tx version in utxo and undo (Pieter Wuille) 7e0032290 Add specialization of SipHash for 256 + 32 bit data (Pieter Wuille) e484652fc Introduce CHashVerifier to hash read data (Pieter Wuille) f54580e7e error() in disconnect for disk corruption, not inconsistency (Pieter Wuille) e66dbde6d Add SizeEstimate to CDBBatch (Pieter Wuille) Tree-SHA512: ce1fb1e40c77d38915cd02189fab7a8b125c7f44d425c85579d872c3bede3a437760997907c99d7b3017ced1c2de54b2ac7223d99d83a6658fe5ef61edef1de3
2017-06-02 00:47:58 +02:00
err = err + ScriptToAsmStr(coin.out.scriptPubKey) + "\nvs:\n"+
ScriptToAsmStr(scriptPubKey);
2015-04-03 00:51:08 +02:00
throw runtime_error(err);
}
Merge #10195: Switch chainstate db and cache to per-txout model 589827975 scripted-diff: various renames for per-utxo consistency (Pieter Wuille) a5e02bc7f Increase travis unit test timeout (Pieter Wuille) 73de2c1ff Rename CCoinsCacheEntry::coins to coin (Pieter Wuille) 119e552f7 Merge CCoinsViewCache's GetOutputFor and AccessCoin (Pieter Wuille) 580b02309 [MOVEONLY] Move old CCoins class to txdb.cpp (Pieter Wuille) 8b25d2c0c Upgrade from per-tx database to per-txout (Pieter Wuille) b2af357f3 Reduce reserved memory space for flushing (Pieter Wuille) 41aa5b79a Pack Coin more tightly (Pieter Wuille) 97072d668 Remove unused CCoins methods (Pieter Wuille) ce23efaa5 Extend coins_tests (Pieter Wuille) 508307968 Switch CCoinsView and chainstate db from per-txid to per-txout (Pieter Wuille) 4ec0d9e79 Refactor GetUTXOStats in preparation for per-COutPoint iteration (Pieter Wuille) 13870b56f Replace CCoins-based CTxMemPool::pruneSpent with isSpent (Pieter Wuille) 05293f3cb Remove ModifyCoins/ModifyNewCoins (Pieter Wuille) 961e48397 Switch tests from ModifyCoins to AddCoin/SpendCoin (Pieter Wuille) 8b3868c1b Switch CScriptCheck to use Coin instead of CCoins (Pieter Wuille) c87b957a3 Only pass things committed to by tx's witness hash to CScriptCheck (Matt Corallo) f68cdfe92 Switch from per-tx to per-txout CCoinsViewCache methods in some places (Pieter Wuille) 000391132 Introduce new per-txout CCoinsViewCache functions (Pieter Wuille) bd83111a0 Optimization: Coin&& to ApplyTxInUndo (Pieter Wuille) cb2c7fdac Replace CTxInUndo with Coin (Pieter Wuille) 422634e2f Introduce Coin, a single unspent output (Pieter Wuille) 7d991b55d Store/allow tx metadata in all undo records (Pieter Wuille) c3aa0c119 Report on-disk size in gettxoutsetinfo (Pieter Wuille) d34242430 Remove/ignore tx version in utxo and undo (Pieter Wuille) 7e0032290 Add specialization of SipHash for 256 + 32 bit data (Pieter Wuille) e484652fc Introduce CHashVerifier to hash read data (Pieter Wuille) f54580e7e error() in disconnect for disk corruption, not inconsistency (Pieter Wuille) e66dbde6d Add SizeEstimate to CDBBatch (Pieter Wuille) Tree-SHA512: ce1fb1e40c77d38915cd02189fab7a8b125c7f44d425c85579d872c3bede3a437760997907c99d7b3017ced1c2de54b2ac7223d99d83a6658fe5ef61edef1de3
2017-06-02 00:47:58 +02:00
Coin newcoin;
newcoin.out.scriptPubKey = scriptPubKey;
newcoin.out.nValue = 0; // we don't know the actual output value
newcoin.nHeight = 1;
view.AddCoin(out, std::move(newcoin), true);
2015-04-03 00:51:08 +02:00
}
// if redeemScript given and private keys given,
// add redeemScript to the tempKeystore so it can be signed:
if (scriptPubKey.IsPayToScriptHash() &&
2015-04-03 00:51:08 +02:00
prevOut.exists("redeemScript")) {
UniValue v = prevOut["redeemScript"];
vector<unsigned char> rsData(ParseHexUV(v, "redeemScript"));
CScript redeemScript(rsData.begin(), rsData.end());
tempKeystore.AddCScript(redeemScript);
}
}
}
const CKeyStore& keystore = tempKeystore;
bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
// Sign what we can:
for (unsigned int i = 0; i < mergedTx.vin.size(); i++) {
CTxIn& txin = mergedTx.vin[i];
Merge #10195: Switch chainstate db and cache to per-txout model 589827975 scripted-diff: various renames for per-utxo consistency (Pieter Wuille) a5e02bc7f Increase travis unit test timeout (Pieter Wuille) 73de2c1ff Rename CCoinsCacheEntry::coins to coin (Pieter Wuille) 119e552f7 Merge CCoinsViewCache's GetOutputFor and AccessCoin (Pieter Wuille) 580b02309 [MOVEONLY] Move old CCoins class to txdb.cpp (Pieter Wuille) 8b25d2c0c Upgrade from per-tx database to per-txout (Pieter Wuille) b2af357f3 Reduce reserved memory space for flushing (Pieter Wuille) 41aa5b79a Pack Coin more tightly (Pieter Wuille) 97072d668 Remove unused CCoins methods (Pieter Wuille) ce23efaa5 Extend coins_tests (Pieter Wuille) 508307968 Switch CCoinsView and chainstate db from per-txid to per-txout (Pieter Wuille) 4ec0d9e79 Refactor GetUTXOStats in preparation for per-COutPoint iteration (Pieter Wuille) 13870b56f Replace CCoins-based CTxMemPool::pruneSpent with isSpent (Pieter Wuille) 05293f3cb Remove ModifyCoins/ModifyNewCoins (Pieter Wuille) 961e48397 Switch tests from ModifyCoins to AddCoin/SpendCoin (Pieter Wuille) 8b3868c1b Switch CScriptCheck to use Coin instead of CCoins (Pieter Wuille) c87b957a3 Only pass things committed to by tx's witness hash to CScriptCheck (Matt Corallo) f68cdfe92 Switch from per-tx to per-txout CCoinsViewCache methods in some places (Pieter Wuille) 000391132 Introduce new per-txout CCoinsViewCache functions (Pieter Wuille) bd83111a0 Optimization: Coin&& to ApplyTxInUndo (Pieter Wuille) cb2c7fdac Replace CTxInUndo with Coin (Pieter Wuille) 422634e2f Introduce Coin, a single unspent output (Pieter Wuille) 7d991b55d Store/allow tx metadata in all undo records (Pieter Wuille) c3aa0c119 Report on-disk size in gettxoutsetinfo (Pieter Wuille) d34242430 Remove/ignore tx version in utxo and undo (Pieter Wuille) 7e0032290 Add specialization of SipHash for 256 + 32 bit data (Pieter Wuille) e484652fc Introduce CHashVerifier to hash read data (Pieter Wuille) f54580e7e error() in disconnect for disk corruption, not inconsistency (Pieter Wuille) e66dbde6d Add SizeEstimate to CDBBatch (Pieter Wuille) Tree-SHA512: ce1fb1e40c77d38915cd02189fab7a8b125c7f44d425c85579d872c3bede3a437760997907c99d7b3017ced1c2de54b2ac7223d99d83a6658fe5ef61edef1de3
2017-06-02 00:47:58 +02:00
const Coin& coin = view.AccessCoin(txin.prevout);
if (coin.IsSpent()) {
2015-04-03 00:51:08 +02:00
fComplete = false;
continue;
}
Merge #10195: Switch chainstate db and cache to per-txout model 589827975 scripted-diff: various renames for per-utxo consistency (Pieter Wuille) a5e02bc7f Increase travis unit test timeout (Pieter Wuille) 73de2c1ff Rename CCoinsCacheEntry::coins to coin (Pieter Wuille) 119e552f7 Merge CCoinsViewCache's GetOutputFor and AccessCoin (Pieter Wuille) 580b02309 [MOVEONLY] Move old CCoins class to txdb.cpp (Pieter Wuille) 8b25d2c0c Upgrade from per-tx database to per-txout (Pieter Wuille) b2af357f3 Reduce reserved memory space for flushing (Pieter Wuille) 41aa5b79a Pack Coin more tightly (Pieter Wuille) 97072d668 Remove unused CCoins methods (Pieter Wuille) ce23efaa5 Extend coins_tests (Pieter Wuille) 508307968 Switch CCoinsView and chainstate db from per-txid to per-txout (Pieter Wuille) 4ec0d9e79 Refactor GetUTXOStats in preparation for per-COutPoint iteration (Pieter Wuille) 13870b56f Replace CCoins-based CTxMemPool::pruneSpent with isSpent (Pieter Wuille) 05293f3cb Remove ModifyCoins/ModifyNewCoins (Pieter Wuille) 961e48397 Switch tests from ModifyCoins to AddCoin/SpendCoin (Pieter Wuille) 8b3868c1b Switch CScriptCheck to use Coin instead of CCoins (Pieter Wuille) c87b957a3 Only pass things committed to by tx's witness hash to CScriptCheck (Matt Corallo) f68cdfe92 Switch from per-tx to per-txout CCoinsViewCache methods in some places (Pieter Wuille) 000391132 Introduce new per-txout CCoinsViewCache functions (Pieter Wuille) bd83111a0 Optimization: Coin&& to ApplyTxInUndo (Pieter Wuille) cb2c7fdac Replace CTxInUndo with Coin (Pieter Wuille) 422634e2f Introduce Coin, a single unspent output (Pieter Wuille) 7d991b55d Store/allow tx metadata in all undo records (Pieter Wuille) c3aa0c119 Report on-disk size in gettxoutsetinfo (Pieter Wuille) d34242430 Remove/ignore tx version in utxo and undo (Pieter Wuille) 7e0032290 Add specialization of SipHash for 256 + 32 bit data (Pieter Wuille) e484652fc Introduce CHashVerifier to hash read data (Pieter Wuille) f54580e7e error() in disconnect for disk corruption, not inconsistency (Pieter Wuille) e66dbde6d Add SizeEstimate to CDBBatch (Pieter Wuille) Tree-SHA512: ce1fb1e40c77d38915cd02189fab7a8b125c7f44d425c85579d872c3bede3a437760997907c99d7b3017ced1c2de54b2ac7223d99d83a6658fe5ef61edef1de3
2017-06-02 00:47:58 +02:00
const CScript& prevPubKey = coin.out.scriptPubKey;
2015-04-03 00:51:08 +02:00
txin.scriptSig.clear();
// Only sign SIGHASH_SINGLE if there's a corresponding output:
if (!fHashSingle || (i < mergedTx.vout.size()))
SignSignature(keystore, prevPubKey, mergedTx, i, nHashType);
// ... and merge in other signatures:
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)))
fComplete = false;
}
if (fComplete) {
// do nothing... for now
// perhaps store this for later optional JSON output
}
tx = mergedTx;
}
class Secp256k1Init
{
ECCVerifyHandle globalVerifyHandle;
public:
Secp256k1Init() {
ECC_Start();
}
~Secp256k1Init() {
ECC_Stop();
}
};
2015-04-03 00:51:08 +02:00
static void MutateTx(CMutableTransaction& tx, const string& command,
const string& commandVal)
{
std::unique_ptr<Secp256k1Init> ecc;
2015-04-03 00:51:08 +02:00
if (command == "nversion")
MutateTxVersion(tx, commandVal);
else if (command == "locktime")
MutateTxLocktime(tx, commandVal);
else if (command == "delin")
MutateTxDelInput(tx, commandVal);
else if (command == "in")
MutateTxAddInput(tx, commandVal);
else if (command == "delout")
MutateTxDelOutput(tx, commandVal);
else if (command == "outaddr")
MutateTxAddOutAddr(tx, commandVal);
else if (command == "outdata")
MutateTxAddOutData(tx, commandVal);
2015-04-03 00:51:08 +02:00
else if (command == "outscript")
MutateTxAddOutScript(tx, commandVal);
else if (command == "sign") {
if (!ecc) { ecc.reset(new Secp256k1Init()); }
2015-04-03 00:51:08 +02:00
MutateTxSign(tx, commandVal);
}
2015-04-03 00:51:08 +02:00
else if (command == "load")
RegisterLoad(commandVal);
else if (command == "set")
RegisterSet(commandVal);
else
throw runtime_error("unknown command");
}
static void OutputTxJSON(const CTransaction& tx)
{
UniValue entry(UniValue::VOBJ);
TxToUniv(tx, uint256(), entry);
2015-04-03 00:51:08 +02:00
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)
fprintf(stdout, "%s\n", strHexHash.c_str());
}
static void OutputTxHex(const CTransaction& tx)
{
string strHex = EncodeHexTx(tx);
fprintf(stdout, "%s\n", strHex.c_str());
}
static void OutputTx(const CTransaction& tx)
{
if (GetBoolArg("-json", false))
OutputTxJSON(tx);
else if (GetBoolArg("-txid", false))
OutputTxHash(tx);
else
OutputTxHex(tx);
}
static string readStdin()
{
char buf[4096];
string ret;
while (!feof(stdin)) {
size_t bread = fread(buf, 1, sizeof(buf), stdin);
ret.append(buf, bread);
if (bread < sizeof(buf))
break;
}
if (ferror(stdin))
throw runtime_error("error reading stdin");
boost::algorithm::trim_right(ret);
return ret;
}
static int CommandLineRawTx(int argc, char* argv[])
{
string strPrint;
int nRet = 0;
try {
// Skip switches; Permit common stdin convention "-"
while (argc > 1 && IsSwitchChar(argv[1][0]) &&
(argv[1][1] != 0)) {
argc--;
argv++;
}
CTransaction txDecodeTmp;
int startArg;
if (!fCreateBlank) {
// require at least one param
if (argc < 2)
throw runtime_error("too few parameters");
2015-04-05 23:56:58 +02:00
// param: hex-encoded dash transaction
2015-04-03 00:51:08 +02:00
string strHexTx(argv[1]);
if (strHexTx == "-") // "-" implies standard input
strHexTx = readStdin();
if (!DecodeHexTx(txDecodeTmp, strHexTx))
throw runtime_error("invalid transaction encoding");
startArg = 2;
} else
startArg = 1;
CMutableTransaction tx(txDecodeTmp);
for (int i = startArg; i < argc; i++) {
string arg = argv[i];
string key, value;
size_t eqpos = arg.find('=');
if (eqpos == string::npos)
key = arg;
else {
key = arg.substr(0, eqpos);
value = arg.substr(eqpos + 1);
}
MutateTx(tx, key, value);
}
OutputTx(tx);
}
catch (const boost::thread_interrupted&) {
2015-04-03 00:51:08 +02:00
throw;
}
catch (const std::exception& e) {
2015-04-03 00:51:08 +02:00
strPrint = string("error: ") + e.what();
nRet = EXIT_FAILURE;
}
catch (...) {
PrintExceptionContinue(NULL, "CommandLineRawTx()");
throw;
}
if (strPrint != "") {
fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
}
return nRet;
}
int main(int argc, char* argv[])
{
SetupEnvironment();
try {
int ret = AppInitRawTx(argc, argv);
if (ret != CONTINUE_EXECUTION)
return ret;
2015-04-03 00:51:08 +02:00
}
catch (const std::exception& e) {
2015-04-03 00:51:08 +02:00
PrintExceptionContinue(&e, "AppInitRawTx()");
return EXIT_FAILURE;
} catch (...) {
PrintExceptionContinue(NULL, "AppInitRawTx()");
return EXIT_FAILURE;
}
int ret = EXIT_FAILURE;
try {
ret = CommandLineRawTx(argc, argv);
}
catch (const std::exception& e) {
2015-04-03 00:51:08 +02:00
PrintExceptionContinue(&e, "CommandLineRawTx()");
} catch (...) {
PrintExceptionContinue(NULL, "CommandLineRawTx()");
}
return ret;
}