6 #if defined(HAVE_CONFIG_H) 28 #include <boost/algorithm/string.hpp> 30 static bool fCreateBlank;
31 static std::map<std::string,UniValue> registers;
32 static const int CONTINUE_EXECUTION=-1;
38 static int AppInitRawTx(
int argc,
char* argv[])
48 }
catch (
const std::exception& e) {
49 fprintf(stderr,
"Error: %s\n", e.what());
60 " raven-tx [options] <hex-tx> [commands] " +
_(
"Update hex-encoded raven transaction") +
"\n" +
61 " raven-tx [options] -create [commands] " +
_(
"Create hex-encoded raven transaction") +
"\n" +
64 fprintf(stdout,
"%s", strUsage.c_str());
70 strUsage +=
HelpMessageOpt(
"-txid",
_(
"Output only the hex-encoded transaction id of the resultant transaction."));
73 fprintf(stdout,
"%s", strUsage.c_str());
78 strUsage +=
HelpMessageOpt(
"in=TXID:VOUT(:SEQUENCE_NUMBER)",
_(
"Add input to TX"));
81 strUsage +=
HelpMessageOpt(
"replaceable(=N)",
_(
"Set RBF opt-in sequence number for input N (if not provided, opt-in all available inputs)"));
82 strUsage +=
HelpMessageOpt(
"outaddr=VALUE:ADDRESS",
_(
"Add address-based output to TX"));
83 strUsage +=
HelpMessageOpt(
"outpubkey=VALUE:PUBKEY[:FLAGS]",
_(
"Add pay-to-pubkey output to TX") +
". " +
84 _(
"Optionally add the \"W\" flag to produce a pay-to-witness-pubkey-hash output") +
". " +
85 _(
"Optionally add the \"S\" flag to wrap the output in a pay-to-script-hash."));
86 strUsage +=
HelpMessageOpt(
"outdata=[VALUE:]DATA",
_(
"Add data-based output to TX"));
87 strUsage +=
HelpMessageOpt(
"outscript=VALUE:SCRIPT[:FLAGS]",
_(
"Add raw script output to TX") +
". " +
88 _(
"Optionally add the \"W\" flag to produce a pay-to-witness-script-hash output") +
". " +
89 _(
"Optionally add the \"S\" flag to wrap the output in a pay-to-script-hash."));
90 strUsage +=
HelpMessageOpt(
"outmultisig=VALUE:REQUIRED:PUBKEYS:PUBKEY1:PUBKEY2:....[:FLAGS]",
_(
"Add Pay To n-of-m Multi-sig output to TX. n = REQUIRED, m = PUBKEYS") +
". " +
91 _(
"Optionally add the \"W\" flag to produce a pay-to-witness-script-hash output") +
". " +
92 _(
"Optionally add the \"S\" flag to wrap the output in a pay-to-script-hash."));
93 strUsage +=
HelpMessageOpt(
"sign=SIGHASH-FLAGS",
_(
"Add zero or more signatures to transaction") +
". " +
94 _(
"This command requires JSON registers:") +
95 _(
"prevtxs=JSON object") +
", " +
96 _(
"privatekeys=JSON object") +
". " +
97 _(
"See signrawtransaction docs for format of sighash flags, JSON objects."));
98 fprintf(stdout,
"%s", strUsage.c_str());
101 strUsage +=
HelpMessageOpt(
"load=NAME:FILENAME",
_(
"Load JSON file FILENAME into register NAME"));
102 strUsage +=
HelpMessageOpt(
"set=NAME:JSON-STRING",
_(
"Set register NAME to given JSON-STRING"));
103 fprintf(stdout,
"%s", strUsage.c_str());
106 fprintf(stderr,
"Error: too few parameters\n");
111 return CONTINUE_EXECUTION;
114 static void RegisterSetJson(
const std::string& key,
const std::string& rawJson)
117 if (!val.
read(rawJson)) {
118 std::string strErr =
"Cannot parse JSON for key " + key;
119 throw std::runtime_error(strErr);
122 registers[key] = val;
125 static void RegisterSet(
const std::string& strInput)
128 size_t pos = strInput.find(
':');
129 if ((pos == std::string::npos) ||
131 (pos == (strInput.size() - 1)))
132 throw std::runtime_error(
"Register input requires NAME:VALUE");
134 std::string key = strInput.substr(0, pos);
135 std::string valStr = strInput.substr(pos + 1, std::string::npos);
137 RegisterSetJson(key, valStr);
140 static void RegisterLoad(
const std::string& strInput)
143 size_t pos = strInput.find(
':');
144 if ((pos == std::string::npos) ||
146 (pos == (strInput.size() - 1)))
147 throw std::runtime_error(
"Register load requires NAME:FILENAME");
149 std::string key = strInput.substr(0, pos);
150 std::string filename = strInput.substr(pos + 1, std::string::npos);
152 FILE *f =
fopen(filename.c_str(),
"r");
154 std::string strErr =
"Cannot open file " + filename;
155 throw std::runtime_error(strErr);
160 while ((!feof(f)) && (!ferror(f))) {
162 int bread = fread(buf, 1,
sizeof(buf), f);
166 valStr.insert(valStr.size(), buf, bread);
169 int error = ferror(f);
173 std::string strErr =
"Error reading file " + filename;
174 throw std::runtime_error(strErr);
178 RegisterSetJson(key, valStr);
181 static CAmount ExtractAndValidateValue(
const std::string& strValue)
185 throw std::runtime_error(
"invalid TX output value");
191 int64_t newVersion =
atoi64(cmdVal);
193 throw std::runtime_error(
"Invalid TX version requested");
200 int64_t newLocktime =
atoi64(cmdVal);
201 if (newLocktime < 0LL || newLocktime > 0xffffffffLL)
202 throw std::runtime_error(
"Invalid TX locktime requested");
204 tx.
nLockTime = (
unsigned int) newLocktime;
210 int inIdx =
atoi(strInIdx);
211 if (inIdx < 0 || inIdx >= (
int)tx.
vin.size()) {
212 throw std::runtime_error(
"Invalid TX input index '" + strInIdx +
"'");
218 if (strInIdx ==
"" || cnt == inIdx) {
219 if (txin.
nSequence > MAX_BIP125_RBF_SEQUENCE) {
220 txin.
nSequence = MAX_BIP125_RBF_SEQUENCE;
229 std::vector<std::string> vStrInputParts;
230 boost::split(vStrInputParts, strInput, boost::is_any_of(
":"));
233 if (vStrInputParts.size()<2)
234 throw std::runtime_error(
"TX input missing separator");
237 std::string strTxid = vStrInputParts[0];
238 if ((strTxid.size() != 64) || !
IsHex(strTxid))
239 throw std::runtime_error(
"invalid TX input txid");
242 static const unsigned int minTxOutSz = 9;
246 unsigned int maxVout = 0;
247 if (fAssetsIsActive) {
248 maxVout = MAX_BLOCK_WEIGHT_RIP2 / (WITNESS_SCALE_FACTOR * minTxOutSz);
250 maxVout = MAX_BLOCK_WEIGHT / (WITNESS_SCALE_FACTOR * minTxOutSz);
254 std::string strVout = vStrInputParts[1];
255 int vout =
atoi(strVout);
256 if ((vout < 0) || (vout > (
int)maxVout))
257 throw std::runtime_error(
"invalid TX input vout");
260 uint32_t nSequenceIn=std::numeric_limits<unsigned int>::max();
261 if (vStrInputParts.size() > 2)
262 nSequenceIn = std::stoul(vStrInputParts[2]);
266 tx.
vin.push_back(txin);
272 std::vector<std::string> vStrInputParts;
273 boost::split(vStrInputParts, strInput, boost::is_any_of(
":"));
275 if (vStrInputParts.size() != 2)
276 throw std::runtime_error(
"TX output missing or too many separators");
279 CAmount value = ExtractAndValidateValue(vStrInputParts[0]);
282 std::string strAddr = vStrInputParts[1];
285 throw std::runtime_error(
"invalid TX output address");
290 CTxOut txout(value, scriptPubKey);
291 tx.
vout.push_back(txout);
297 std::vector<std::string> vStrInputParts;
298 boost::split(vStrInputParts, strInput, boost::is_any_of(
":"));
300 if (vStrInputParts.size() < 2 || vStrInputParts.size() > 3)
301 throw std::runtime_error(
"TX output missing or too many separators");
304 CAmount value = ExtractAndValidateValue(vStrInputParts[0]);
308 if (!pubkey.IsFullyValid())
309 throw std::runtime_error(
"invalid TX output pubkey");
313 bool bSegWit =
false;
314 bool bScriptHash =
false;
315 if (vStrInputParts.size() == 3) {
316 std::string
flags = vStrInputParts[2];
317 bSegWit = (flags.find(
"W") != std::string::npos);
318 bScriptHash = (flags.find(
"S") != std::string::npos);
322 if (!pubkey.IsCompressed()) {
323 throw std::runtime_error(
"Uncompressed pubkeys are not useable for SegWit outputs");
334 CTxOut txout(value, scriptPubKey);
335 tx.
vout.push_back(txout);
341 std::vector<std::string> vStrInputParts;
342 boost::split(vStrInputParts, strInput, boost::is_any_of(
":"));
345 if (vStrInputParts.size()<3)
346 throw std::runtime_error(
"Not enough multisig parameters");
349 CAmount value = ExtractAndValidateValue(vStrInputParts[0]);
352 uint32_t required = stoul(vStrInputParts[1]);
355 uint32_t numkeys = stoul(vStrInputParts[2]);
358 if (vStrInputParts.size() < numkeys + 3)
359 throw std::runtime_error(
"incorrect number of multisig pubkeys");
361 if (required < 1 || required > 20 || numkeys < 1 || numkeys > 20 || numkeys < required)
362 throw std::runtime_error(
"multisig parameter mismatch. Required " \
363 + std::to_string(required) +
" of " + std::to_string(numkeys) +
"signatures.");
366 std::vector<CPubKey> pubkeys;
367 for(
int pos = 1; pos <= int(numkeys); pos++) {
369 if (!pubkey.IsFullyValid())
370 throw std::runtime_error(
"invalid TX output pubkey");
371 pubkeys.push_back(pubkey);
375 bool bSegWit =
false;
376 bool bScriptHash =
false;
377 if (vStrInputParts.size() == numkeys + 4) {
378 std::string flags = vStrInputParts.back();
379 bSegWit = (flags.find(
"W") != std::string::npos);
380 bScriptHash = (flags.find(
"S") != std::string::npos);
382 else if (vStrInputParts.size() > numkeys + 4) {
384 throw std::runtime_error(
"Too many parameters");
390 for (
CPubKey& pubkey : pubkeys) {
391 if (!pubkey.IsCompressed()) {
392 throw std::runtime_error(
"Uncompressed pubkeys are not useable for SegWit outputs");
404 CTxOut txout(value, scriptPubKey);
405 tx.
vout.push_back(txout);
413 size_t pos = strInput.find(
':');
416 throw std::runtime_error(
"TX output value not specified");
418 if (pos != std::string::npos) {
420 value = ExtractAndValidateValue(strInput.substr(0, pos));
424 std::string strData = strInput.substr(pos + 1, std::string::npos);
427 throw std::runtime_error(
"invalid TX output data");
429 std::vector<unsigned char> data =
ParseHex(strData);
432 tx.
vout.push_back(txout);
438 std::vector<std::string> vStrInputParts;
439 boost::split(vStrInputParts, strInput, boost::is_any_of(
":"));
440 if (vStrInputParts.size() < 2)
441 throw std::runtime_error(
"TX output missing separator");
444 CAmount value = ExtractAndValidateValue(vStrInputParts[0]);
447 std::string strScript = vStrInputParts[1];
451 bool bSegWit =
false;
452 bool bScriptHash =
false;
453 if (vStrInputParts.size() == 3) {
454 std::string flags = vStrInputParts.back();
455 bSegWit = (flags.find(
"W") != std::string::npos);
456 bScriptHash = (flags.find(
"S") != std::string::npos);
467 CTxOut txout(value, scriptPubKey);
468 tx.
vout.push_back(txout);
474 int inIdx =
atoi(strInIdx);
475 if (inIdx < 0 || inIdx >= (
int)tx.
vin.size()) {
476 std::string strErr =
"Invalid TX input index '" + strInIdx +
"'";
477 throw std::runtime_error(strErr.c_str());
481 tx.
vin.erase(tx.
vin.begin() + inIdx);
487 int outIdx =
atoi(strOutIdx);
488 if (outIdx < 0 || outIdx >= (
int)tx.
vout.size()) {
489 std::string strErr =
"Invalid TX output index '" + strOutIdx +
"'";
490 throw std::runtime_error(strErr.c_str());
494 tx.
vout.erase(tx.
vout.begin() + outIdx);
497 static const unsigned int N_SIGHASH_OPTS = 6;
498 static const struct {
501 } sighashOptions[N_SIGHASH_OPTS] = {
510 static bool findSighashFlags(
int& flags,
const std::string&
flagStr)
514 for (
unsigned int i = 0; i < N_SIGHASH_OPTS; i++) {
515 if (flagStr == sighashOptions[i].flagStr) {
516 flags = sighashOptions[i].flags;
527 throw std::runtime_error(
"Amount is not a number or string");
530 throw std::runtime_error(
"Invalid amount (1)");
532 throw std::runtime_error(
"Amount out of range");
540 if (flagStr.size() > 0)
541 if (!findSighashFlags(nHashType, flagStr))
542 throw std::runtime_error(
"unknown sighash flag/sign option");
544 std::vector<CTransaction> txVariants;
545 txVariants.push_back(tx);
550 bool fComplete =
true;
554 if (!registers.count(
"privatekeys"))
555 throw std::runtime_error(
"privatekeys register variable must be set.");
557 UniValue keysObj = registers[
"privatekeys"];
559 for (
unsigned int kidx = 0; kidx < keysObj.
size(); kidx++) {
560 if (!keysObj[kidx].isStr())
561 throw std::runtime_error(
"privatekey not a std::string");
563 bool fGood = vchSecret.
SetString(keysObj[kidx].getValStr());
565 throw std::runtime_error(
"privatekey not valid");
572 if (!registers.count(
"prevtxs"))
573 throw std::runtime_error(
"prevtxs register variable must be set.");
574 UniValue prevtxsObj = registers[
"prevtxs"];
576 for (
unsigned int previdx = 0; previdx < prevtxsObj.
size(); previdx++) {
577 UniValue prevOut = prevtxsObj[previdx];
579 throw std::runtime_error(
"expected prevtxs internal object");
581 std::map<std::string, UniValue::VType> types = {
587 throw std::runtime_error(
"prevtxs internal object typecheck fail");
591 int nOut =
atoi(prevOut[
"vout"].getValStr());
593 throw std::runtime_error(
"vout must be positive");
596 std::vector<unsigned char> pkData(
ParseHexUV(prevOut[
"scriptPubKey"],
"scriptPubKey"));
597 CScript scriptPubKey(pkData.begin(), pkData.end());
602 std::string err(
"Previous output scriptPubKey mismatch:\n");
605 throw std::runtime_error(err);
610 if (prevOut.
exists(
"amount")) {
611 newcoin.
out.
nValue = AmountFromValue(prevOut[
"amount"]);
614 view.
AddCoin(out, std::move(newcoin),
true);
620 prevOut.
exists(
"redeemScript")) {
621 UniValue v = prevOut[
"redeemScript"];
622 std::vector<unsigned char> rsData(
ParseHexUV(v,
"redeemScript"));
623 CScript redeemScript(rsData.begin(), rsData.end());
629 const CKeyStore& keystore = tempKeystore;
634 for (
unsigned int i = 0; i < mergedTx.
vin.size(); i++) {
646 if (!fHashSingle || (i < mergedTx.
vout.size()))
680 const std::string& commandVal)
682 std::unique_ptr<Secp256k1Init> ecc;
684 if (command ==
"nversion")
685 MutateTxVersion(tx, commandVal);
686 else if (command ==
"locktime")
687 MutateTxLocktime(tx, commandVal);
688 else if (command ==
"replaceable") {
689 MutateTxRBFOptIn(tx, commandVal);
692 else if (command ==
"delin")
693 MutateTxDelInput(tx, commandVal);
694 else if (command ==
"in")
695 MutateTxAddInput(tx, commandVal);
697 else if (command ==
"delout")
698 MutateTxDelOutput(tx, commandVal);
699 else if (command ==
"outaddr")
700 MutateTxAddOutAddr(tx, commandVal);
701 else if (command ==
"outpubkey") {
703 MutateTxAddOutPubKey(tx, commandVal);
704 }
else if (command ==
"outmultisig") {
706 MutateTxAddOutMultiSig(tx, commandVal);
707 }
else if (command ==
"outscript")
708 MutateTxAddOutScript(tx, commandVal);
709 else if (command ==
"outdata")
710 MutateTxAddOutData(tx, commandVal);
712 else if (command ==
"sign") {
714 MutateTxSign(tx, commandVal);
717 else if (command ==
"load")
718 RegisterLoad(commandVal);
720 else if (command ==
"set")
721 RegisterSet(commandVal);
724 throw std::runtime_error(
"unknown command");
732 std::string jsonOutput = entry.
write(4);
733 fprintf(stdout,
"%s\n", jsonOutput.c_str());
740 fprintf(stdout,
"%s\n", strHexHash.c_str());
747 fprintf(stdout,
"%s\n", strHex.c_str());
760 static std::string readStdin()
765 while (!feof(stdin)) {
766 size_t bread = fread(buf, 1,
sizeof(buf), stdin);
767 ret.append(buf, bread);
768 if (bread <
sizeof(buf))
773 throw std::runtime_error(
"error reading stdin");
775 boost::algorithm::trim_right(ret);
780 static int CommandLineRawTx(
int argc,
char* argv[])
782 std::string strPrint;
798 throw std::runtime_error(
"too few parameters");
801 std::string strHexTx(argv[1]);
803 strHexTx = readStdin();
806 throw std::runtime_error(
"invalid transaction encoding");
812 for (
int i = startArg; i < argc; i++) {
813 std::string arg = argv[i];
814 std::string key, value;
815 size_t eqpos = arg.find(
'=');
816 if (eqpos == std::string::npos)
819 key = arg.substr(0, eqpos);
820 value = arg.substr(eqpos + 1);
823 MutateTx(tx, key, value);
829 catch (
const boost::thread_interrupted&) {
832 catch (
const std::exception& e) {
833 strPrint = std::string(
"error: ") + e.what();
841 if (strPrint !=
"") {
842 fprintf((nRet == 0 ? stdout : stderr),
"%s\n", strPrint.c_str());
847 int main(
int argc,
char* argv[])
852 int ret = AppInitRawTx(argc, argv);
853 if (ret != CONTINUE_EXECUTION)
856 catch (
const std::exception& e) {
864 int ret = EXIT_FAILURE;
866 ret = CommandLineRawTx(argc, argv);
868 catch (
const std::exception& e) {
int main(int argc, char *argv[])
std::vector< unsigned char > ParseHexUV(const UniValue &v, const std::string &strName)
std::string HelpMessageOpt(const std::string &option, const std::string &message)
Format a string to be used as option description in help messages.
void UpdateTransaction(CMutableTransaction &tx, unsigned int nIn, const SignatureData &data)
void ECC_Start()
Initialize the elliptic curve support.
void AppendParamsHelpMessages(std::string &strUsage, bool debugHelp)
Append the help messages for the chainparams options to the parameter string.
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
SignatureData DataFromTransaction(const CMutableTransaction &tx, unsigned int nIn)
Extract signature data from a transaction, and insert it.
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
void AddCoin(const COutPoint &outpoint, Coin &&coin, bool potential_overwrite)
Add a coin.
static const int32_t MAX_STANDARD_VERSION
void ParseParameters(int argc, const char *const argv[])
FILE * fopen(const fs::path &p, const char *mode)
const Coin & AccessCoin(const COutPoint &output) const
Return a reference to Coin in the cache, or a pruned one if not found.
bool read(const char *raw, size_t len)
bool IsPayToScriptHash() const
bool VerifyScript(const CScript &scriptSig, const CScript &scriptPubKey, const CScriptWitness *witness, unsigned int flags, const BaseSignatureChecker &checker, ScriptError *serror)
CScriptWitness scriptWitness
bool MoneyRange(const CAmount &nValue)
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
CTxOut out
unspent transaction output
CTxDestination DecodeDestination(const std::string &str)
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
bool AddCScript(const CScript &redeemScript) override
Support for BIP 0013 : see https://github.com/raven/bips/blob/master/bip-0013.mediawiki.
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
void PrintExceptionContinue(const std::exception *pex, const char *pszThread)
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
const std::string & getValStr() const
bool ProduceSignature(const BaseSignatureCreator &creator, const CScript &fromPubKey, SignatureData &sigdata)
Produce a script signature using a generic signature creator.
SignatureData CombineSignatures(const CScript &scriptPubKey, const BaseSignatureChecker &checker, const SignatureData &scriptSig1, const SignatureData &scriptSig2)
Combine two script signatures using a generic signature checker, intelligently, possibly with OP_0 pl...
int64_t CAmount
Amount in corbies (Can be negative)
uint32_t nHeight
at which height this containing transaction was included in the active block chain ...
Users of this module must hold an ECCVerifyHandle.
std::string ScriptToAsmStr(const CScript &script, const bool fAttemptSighashDecode=false)
Create the assembly string representation of a CScript object.
Abstract view on the open txout dataset.
An input of a transaction.
bool DecodeHexTx(CMutableTransaction &tx, const std::string &strHexTx, bool fTryNoWitness=false)
void ECC_Stop()
Deinitialize the elliptic curve support.
const uint256 & GetHash() const
bool exists(const std::string &key) const
void SelectParams(const std::string &network)
Sets the params returned by Params() to those for the given BIP70 chain name.
uint256 ParseHashUV(const UniValue &v, const std::string &strName)
uint256 uint256S(const char *str)
bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out)
Parse number as fixed point according to JSON number syntax.
An encapsulated public key.
bool SetString(const char *pszSecret)
bool IsHex(const std::string &str)
bool ParseMoney(const std::string &str, CAmount &nRet)
An output of a transaction.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Raven scriptPubKey for the given CTxDestination.
An outpoint - a combination of a transaction hash and an index n into its vout.
virtual bool AddKey(const CKey &key)
std::vector< CTxOut > vout
std::string FormatFullVersion()
bool checkObject(const std::map< std::string, UniValue::VType > &memberTypes) const
bool IsSwitchChar(char c)
A base58-encoded secret key.
Serialized script, used inside transaction inputs and outputs.
A virtual base class for key stores.
std::string GetHex() const
std::string ChainNameFromCommandLine()
Looks for -regtest, -testnet and returns the appropriate BIP70 chain name.
int64_t atoi64(const char *psz)
std::string EncodeHexTx(const CTransaction &tx, const int serializeFlags=0)
ECCVerifyHandle globalVerifyHandle
bool error(const char *fmt, const Args &... args)
A reference to a CScript: the Hash160 of its serialization (see script.h)
A mutable version of CTransaction.
void TxToUniv(const CTransaction &tx, const uint256 &hashBlock, UniValue &entry, bool include_hex=true, int serialize_flags=0)
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Generate a multisig script.
An encapsulated private key.
The basic transaction that is broadcasted on the network and contained in blocks. ...
CCoinsView that adds a memory cache for transactions to another CCoinsView.
CScript ParseScript(const std::string &s)
CScript GetScriptForWitness(const CScript &redeemscript)
Generate a pay-to-witness script for the given redeem script.
std::string HelpMessageGroup(const std::string &message)
Format a string to be used as group of options in help messages.
Basic key store, that keeps keys in an address->secret map.
std::string _(const char *psz)
Translation function: Call Translate signal on UI interface, which returns a boost::optional result...
int atoi(const std::string &str)
bool IsPayToWitnessScriptHash() const
RVN END.
std::vector< unsigned char > ParseHex(const char *psz)