Changeset View
Changeset View
Standalone View
Standalone View
src/bitcoin-tx.cpp
Show First 20 Lines • Show All 480 Lines • ▼ Show 20 Lines | if (outIdx < 0 || outIdx >= (int)tx.vout.size()) { | ||||
std::string strErr = "Invalid TX output index '" + strOutIdx + "'"; | std::string strErr = "Invalid TX output index '" + strOutIdx + "'"; | ||||
throw std::runtime_error(strErr.c_str()); | throw std::runtime_error(strErr.c_str()); | ||||
} | } | ||||
// delete output from transaction | // delete output from transaction | ||||
tx.vout.erase(tx.vout.begin() + outIdx); | tx.vout.erase(tx.vout.begin() + outIdx); | ||||
} | } | ||||
static const unsigned int N_SIGHASH_OPTS = 6; | static const unsigned int N_SIGHASH_OPTS = 12; | ||||
static const struct { | static const struct { | ||||
const char *flagStr; | const char *flagStr; | ||||
int flags; | int flags; | ||||
} sighashOptions[N_SIGHASH_OPTS] = { | } sighashOptions[N_SIGHASH_OPTS] = { | ||||
{"ALL", SIGHASH_ALL}, | {"ALL", SIGHASH_ALL}, | ||||
{"NONE", SIGHASH_NONE}, | {"NONE", SIGHASH_NONE}, | ||||
{"SINGLE", SIGHASH_SINGLE}, | {"SINGLE", SIGHASH_SINGLE}, | ||||
{"ALL|ANYONECANPAY", SIGHASH_ALL | SIGHASH_ANYONECANPAY}, | {"ALL|ANYONECANPAY", SIGHASH_ALL | SIGHASH_ANYONECANPAY}, | ||||
{"NONE|ANYONECANPAY", SIGHASH_NONE | SIGHASH_ANYONECANPAY}, | {"NONE|ANYONECANPAY", SIGHASH_NONE | SIGHASH_ANYONECANPAY}, | ||||
{"SINGLE|ANYONECANPAY", SIGHASH_SINGLE | SIGHASH_ANYONECANPAY}, | {"SINGLE|ANYONECANPAY", SIGHASH_SINGLE | SIGHASH_ANYONECANPAY}, | ||||
{"ALL|FORKID", SIGHASH_ALL | SIGHASH_FORKID}, | |||||
{"NONE|FORKID", SIGHASH_NONE | SIGHASH_FORKID}, | |||||
{"SINGLE|FORKID", SIGHASH_SINGLE | SIGHASH_FORKID}, | |||||
{"ALL|FORKID|ANYONECANPAY", | |||||
SIGHASH_ALL | SIGHASH_FORKID | SIGHASH_ANYONECANPAY}, | |||||
{"NONE|FORKID|ANYONECANPAY", | |||||
SIGHASH_NONE | SIGHASH_FORKID | SIGHASH_ANYONECANPAY}, | |||||
{"SINGLE|FORKID|ANYONECANPAY", | |||||
SIGHASH_SINGLE | SIGHASH_FORKID | SIGHASH_ANYONECANPAY}, | |||||
}; | }; | ||||
static bool findSighashFlags(int &flags, const std::string &flagStr) { | static bool findSighashFlags(int &flags, const std::string &flagStr) { | ||||
flags = 0; | flags = 0; | ||||
for (unsigned int i = 0; i < N_SIGHASH_OPTS; i++) { | for (unsigned int i = 0; i < N_SIGHASH_OPTS; i++) { | ||||
if (flagStr == sighashOptions[i].flagStr) { | if (flagStr == sighashOptions[i].flagStr) { | ||||
flags = sighashOptions[i].flags; | flags = sighashOptions[i].flags; | ||||
Show All 35 Lines | static CAmount AmountFromValue(const UniValue &value) { | ||||
if (!MoneyRange(amount)) { | if (!MoneyRange(amount)) { | ||||
throw std::runtime_error("Amount out of range"); | throw std::runtime_error("Amount out of range"); | ||||
} | } | ||||
return amount; | return amount; | ||||
} | } | ||||
static void MutateTxSign(CMutableTransaction &tx, const std::string &flagStr) { | static void MutateTxSign(CMutableTransaction &tx, const std::string &flagStr) { | ||||
int nHashType = SIGHASH_ALL; | int nHashType = SIGHASH_ALL | SIGHASH_FORKID; | ||||
if ((flagStr.size() > 0) && !findSighashFlags(nHashType, flagStr)) { | if ((flagStr.size() > 0) && !findSighashFlags(nHashType, flagStr)) { | ||||
throw std::runtime_error("unknown sighash flag/sign option"); | throw std::runtime_error("unknown sighash flag/sign option"); | ||||
} | } | ||||
std::vector<CTransaction> txVariants; | std::vector<CTransaction> txVariants; | ||||
txVariants.push_back(tx); | txVariants.push_back(tx); | ||||
▲ Show 20 Lines • Show All 86 Lines • ▼ Show 20 Lines | for (unsigned int previdx = 0; previdx < prevtxsObj.size(); previdx++) { | ||||
std::vector<unsigned char> rsData(ParseHexUV(v, "redeemScript")); | std::vector<unsigned char> rsData(ParseHexUV(v, "redeemScript")); | ||||
CScript redeemScript(rsData.begin(), rsData.end()); | CScript redeemScript(rsData.begin(), rsData.end()); | ||||
tempKeystore.AddCScript(redeemScript); | tempKeystore.AddCScript(redeemScript); | ||||
} | } | ||||
} | } | ||||
const CKeyStore &keystore = tempKeystore; | const CKeyStore &keystore = tempKeystore; | ||||
bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE); | bool fHashSingle = | ||||
((nHashType & ~(SIGHASH_ANYONECANPAY | SIGHASH_FORKID)) == | |||||
SIGHASH_SINGLE); | |||||
// Sign what we can: | // Sign what we can: | ||||
for (unsigned int i = 0; i < mergedTx.vin.size(); i++) { | for (unsigned int i = 0; i < mergedTx.vin.size(); i++) { | ||||
CTxIn &txin = mergedTx.vin[i]; | CTxIn &txin = mergedTx.vin[i]; | ||||
const CCoins *coins = view.AccessCoins(txin.prevout.hash); | const CCoins *coins = view.AccessCoins(txin.prevout.hash); | ||||
if (!coins || !coins->IsAvailable(txin.prevout.n)) { | if (!coins || !coins->IsAvailable(txin.prevout.n)) { | ||||
fComplete = false; | fComplete = false; | ||||
continue; | continue; | ||||
Show All 16 Lines | for (unsigned int i = 0; i < mergedTx.vin.size(); i++) { | ||||
prevPubKey, | prevPubKey, | ||||
MutableTransactionSignatureChecker(&mergedTx, i, amount), | MutableTransactionSignatureChecker(&mergedTx, i, amount), | ||||
sigdata, DataFromTransaction(txv, i)); | sigdata, DataFromTransaction(txv, i)); | ||||
} | } | ||||
UpdateTransaction(mergedTx, i, sigdata); | UpdateTransaction(mergedTx, i, sigdata); | ||||
if (!VerifyScript( | if (!VerifyScript( | ||||
txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, | txin.scriptSig, prevPubKey, | ||||
STANDARD_SCRIPT_VERIFY_FLAGS | SCRIPT_ENABLE_SIGHASH_FORKID, | |||||
MutableTransactionSignatureChecker(&mergedTx, i, amount))) { | MutableTransactionSignatureChecker(&mergedTx, i, amount))) { | ||||
fComplete = false; | fComplete = false; | ||||
} | } | ||||
} | } | ||||
if (fComplete) { | if (fComplete) { | ||||
// do nothing... for now | // do nothing... for now | ||||
// perhaps store this for later optional JSON output | // perhaps store this for later optional JSON output | ||||
▲ Show 20 Lines • Show All 199 Lines • Show Last 20 Lines |