Changeset View
Changeset View
Standalone View
Standalone View
src/bitcoin-tx.cpp
Show First 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | if (argc < 2 || IsArgSet("-?") || IsArgSet("-h") || IsArgSet("-help")) { | ||||
fprintf(stdout, "%s", strUsage.c_str()); | fprintf(stdout, "%s", strUsage.c_str()); | ||||
strUsage = HelpMessageGroup(_("Options:")); | strUsage = HelpMessageGroup(_("Options:")); | ||||
strUsage += HelpMessageOpt("-?", _("This help message")); | strUsage += HelpMessageOpt("-?", _("This help message")); | ||||
strUsage += HelpMessageOpt("-create", _("Create new, empty TX.")); | strUsage += HelpMessageOpt("-create", _("Create new, empty TX.")); | ||||
strUsage += HelpMessageOpt("-json", _("Select JSON output")); | strUsage += HelpMessageOpt("-json", _("Select JSON output")); | ||||
strUsage += | strUsage += | ||||
HelpMessageOpt("-txid", _("Output only the hex-encoded transaction " | HelpMessageOpt("-txhash", _("Output only the hex-encoded hash " | ||||
"id of the resultant transaction.")); | "of the resultant transaction.")); | ||||
AppendParamsHelpMessages(strUsage); | AppendParamsHelpMessages(strUsage); | ||||
fprintf(stdout, "%s", strUsage.c_str()); | fprintf(stdout, "%s", strUsage.c_str()); | ||||
strUsage = HelpMessageGroup(_("Commands:")); | strUsage = HelpMessageGroup(_("Commands:")); | ||||
strUsage += HelpMessageOpt("delin=N", _("Delete input N from TX")); | strUsage += HelpMessageOpt("delin=N", _("Delete input N from TX")); | ||||
strUsage += HelpMessageOpt("delout=N", _("Delete output N from TX")); | strUsage += HelpMessageOpt("delout=N", _("Delete output N from TX")); | ||||
strUsage += HelpMessageOpt("in=TXID:VOUT(:SEQUENCE_NUMBER)", | strUsage += HelpMessageOpt("in=unspentid:VOUT(:SEQUENCE_NUMBER)", | ||||
_("Add input to TX")); | _("Add input to TX")); | ||||
strUsage += HelpMessageOpt("locktime=N", _("Set TX lock time to N")); | strUsage += HelpMessageOpt("locktime=N", _("Set TX lock time to N")); | ||||
strUsage += HelpMessageOpt("nversion=N", _("Set TX version to N")); | strUsage += HelpMessageOpt("nversion=N", _("Set TX version to N")); | ||||
strUsage += HelpMessageOpt("outaddr=VALUE:ADDRESS", | strUsage += HelpMessageOpt("outaddr=VALUE:ADDRESS", | ||||
_("Add address-based output to TX")); | _("Add address-based output to TX")); | ||||
strUsage += | strUsage += | ||||
HelpMessageOpt("outpubkey=VALUE:PUBKEY[:FLAGS]", | HelpMessageOpt("outpubkey=VALUE:PUBKEY[:FLAGS]", | ||||
_("Add pay-to-pubkey output to TX") + ". " + | _("Add pay-to-pubkey output to TX") + ". " + | ||||
▲ Show 20 Lines • Show All 135 Lines • ▼ Show 20 Lines | static void MutateTxLocktime(CMutableTransaction &tx, | ||||
tx.nLockTime = (unsigned int)newLocktime; | tx.nLockTime = (unsigned int)newLocktime; | ||||
} | } | ||||
static void MutateTxAddInput(CMutableTransaction &tx, | static void MutateTxAddInput(CMutableTransaction &tx, | ||||
const std::string &strInput) { | const std::string &strInput) { | ||||
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(":")); | ||||
// separate TXID:VOUT in string | // separate unspentid:VOUT in string | ||||
if (vStrInputParts.size() < 2) { | if (vStrInputParts.size() < 2) { | ||||
throw std::runtime_error("TX input missing separator"); | throw std::runtime_error("TX input missing separator"); | ||||
} | } | ||||
// extract and validate TXID | // extract and validate unspentid | ||||
std::string strTxid = vStrInputParts[0]; | std::string strunspentid = vStrInputParts[0]; | ||||
if ((strTxid.size() != 64) || !IsHex(strTxid)) { | if ((strunspentid.size() != 64) || !IsHex(strunspentid)) { | ||||
throw std::runtime_error("invalid TX input txid"); | throw std::runtime_error("invalid TX input unspentid"); | ||||
} | } | ||||
uint256 txid(uint256S(strTxid)); | unspentid_t unspentid(uint256S(strunspentid)); | ||||
static const unsigned int minTxOutSz = 9; | static const unsigned int minTxOutSz = 9; | ||||
static const unsigned int maxVout = MAX_TX_SIZE / minTxOutSz; | static const unsigned int maxVout = MAX_TX_SIZE / minTxOutSz; | ||||
// extract and validate vout | // extract and validate vout | ||||
std::string strVout = vStrInputParts[1]; | std::string strVout = vStrInputParts[1]; | ||||
int vout = atoi(strVout); | int vout = atoi(strVout); | ||||
if ((vout < 0) || (vout > (int)maxVout)) { | if ((vout < 0) || (vout > (int)maxVout)) { | ||||
throw std::runtime_error("invalid TX input vout"); | throw std::runtime_error("invalid TX input vout"); | ||||
} | } | ||||
// extract the optional sequence number | // extract the optional sequence number | ||||
uint32_t nSequenceIn = std::numeric_limits<unsigned int>::max(); | uint32_t nSequenceIn = std::numeric_limits<unsigned int>::max(); | ||||
if (vStrInputParts.size() > 2) { | if (vStrInputParts.size() > 2) { | ||||
nSequenceIn = std::stoul(vStrInputParts[2]); | nSequenceIn = std::stoul(vStrInputParts[2]); | ||||
} | } | ||||
// append to transaction input list | // append to transaction input list | ||||
CTxIn txin(txid, vout, CScript(), nSequenceIn); | CTxIn txin(unspentid, 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) { | ||||
// 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(":")); | ||||
▲ Show 20 Lines • Show All 328 Lines • ▼ Show 20 Lines | static void MutateTxSign(CMutableTransaction &tx, const std::string &flagStr) { | ||||
for (unsigned int previdx = 0; previdx < prevtxsObj.size(); previdx++) { | for (unsigned int previdx = 0; previdx < prevtxsObj.size(); previdx++) { | ||||
UniValue prevOut = prevtxsObj[previdx]; | UniValue prevOut = prevtxsObj[previdx]; | ||||
if (!prevOut.isObject()) { | if (!prevOut.isObject()) { | ||||
throw std::runtime_error("expected prevtxs internal object"); | throw std::runtime_error("expected prevtxs internal object"); | ||||
} | } | ||||
std::map<std::string, UniValue::VType> types = { | std::map<std::string, UniValue::VType> types = { | ||||
{"txid", UniValue::VSTR}, | {"unspentid", UniValue::VSTR}, | ||||
{"vout", UniValue::VNUM}, | {"vout", UniValue::VNUM}, | ||||
{"scriptPubKey", UniValue::VSTR}}; | {"scriptPubKey", UniValue::VSTR}}; | ||||
if (!prevOut.checkObject(types)) { | if (!prevOut.checkObject(types)) { | ||||
throw std::runtime_error("prevtxs internal object typecheck fail"); | throw std::runtime_error("prevtxs internal object typecheck fail"); | ||||
} | } | ||||
uint256 txid = ParseHashUV(prevOut["txid"], "txid"); | unspentid_t unspentid = | ||||
unspentid_t(ParseHashUV(prevOut["unspentid"], "unspentid")); | |||||
int nOut = atoi(prevOut["vout"].getValStr()); | int nOut = atoi(prevOut["vout"].getValStr()); | ||||
if (nOut < 0) { | if (nOut < 0) { | ||||
throw std::runtime_error("vout must be positive"); | throw std::runtime_error("vout must be positive"); | ||||
} | } | ||||
COutPoint out(txid, nOut); | COutPoint out(unspentid, nOut); | ||||
std::vector<uint8_t> pkData( | std::vector<uint8_t> pkData( | ||||
ParseHexUV(prevOut["scriptPubKey"], "scriptPubKey")); | ParseHexUV(prevOut["scriptPubKey"], "scriptPubKey")); | ||||
CScript scriptPubKey(pkData.begin(), pkData.end()); | CScript scriptPubKey(pkData.begin(), pkData.end()); | ||||
{ | { | ||||
const Coin &coin = view.AccessCoin(out); | const Coin &coin = view.AccessCoin(out); | ||||
if (!coin.IsSpent() && | if (!coin.IsSpent() && | ||||
coin.GetTxOut().scriptPubKey != scriptPubKey) { | coin.GetTxOut().scriptPubKey != scriptPubKey) { | ||||
▲ Show 20 Lines • Show All 129 Lines • ▼ Show 20 Lines | static void OutputTxJSON(const CTransaction &tx) { | ||||
TxToUniv(tx, uint256(), entry); | TxToUniv(tx, uint256(), entry); | ||||
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.GetHash().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) { | ||||
if (GetBoolArg("-json", false)) { | if (GetBoolArg("-json", false)) { | ||||
OutputTxJSON(tx); | OutputTxJSON(tx); | ||||
} else if (GetBoolArg("-txid", false)) { | } else if (GetBoolArg("-txhash", false)) { | ||||
OutputTxHash(tx); | OutputTxHash(tx); | ||||
} else { | } else { | ||||
OutputTxHex(tx); | OutputTxHex(tx); | ||||
} | } | ||||
} | } | ||||
static std::string readStdin() { | static std::string readStdin() { | ||||
char buf[4096]; | char buf[4096]; | ||||
▲ Show 20 Lines • Show All 114 Lines • Show Last 20 Lines |