QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx) { // individual tx do not affect any representation static const bool fMultiSig = true; QString strHTML; LOCK2(cs_main, wallet->cs_wallet); strHTML.reserve(4000); strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>"; int64_t nTime = wtx.GetTxTime(); std::map<int, int64_t> mapDebit, mapCredit, mapChange, mapNet; // debits wallet->FillDebits(wtx, mapDebit, fMultiSig); // credits (mature) wallet->FillMatures(wtx, mapCredit, fMultiSig); // nets (mature - debits) FillNets(mapDebit, mapCredit, mapNet); strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(wtx); int nRequests = wtx.GetRequestCount(); if (nRequests != -1) { if (nRequests == 0) strHTML += tr(", has not been successfully broadcast yet"); else if (nRequests > 0) strHTML += tr(", broadcast through %n node(s)", "", nRequests); } strHTML += "<br>"; strHTML += "<b>" + tr("Date") + ":</b> " + (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "<br>"; // // From // if (wtx.IsCoinBase() || wtx.IsCoinStake()) { strHTML += "<b>" + tr("Source") + ":</b> " + tr("Generated") + "<br>"; } else if (wtx.mapValue.count("from") && !wtx.mapValue["from"].empty()) { // Online transaction strHTML += "<b>" + tr("From") + ":</b> " + GUIUtil::HtmlEscape(wtx.mapValue["from"]) + "<br>"; } else { // Offline transaction if (ValueMapAllPositive(mapNet)) { // Credit BOOST_FOREACH(const CTxOut& txout, wtx.vout) { if (wallet->IsMine(txout, fMultiSig) & ISMINE_ALL) { CTxDestination address; if (ExtractDestination(txout.scriptPubKey, address) && (IsMine(*wallet, address, fMultiSig) & ISMINE_ALL)) { if (wallet->mapAddressBook.count(address)) { strHTML += "<b>" + tr("From") + ":</b> " + tr("unknown") + "<br>"; strHTML += "<b>" + tr("To") + ":</b> "; CBitcoinAddress addr(address, txout.nColor); strHTML += GUIUtil::HtmlEscape(addr.ToString()); // indicate distinction between own address and watch address if (IsMine(*wallet, address, fMultiSig) & ISMINE_SPENDABLE) { if (!wallet->mapAddressBook[address].empty()) { strHTML += " (" + tr("own address") + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + ")"; } else { strHTML += " (" + tr("own address") + ")"; } } else { if (!wallet->mapAddressBook[address].empty()) { strHTML += " (" + tr("watch address") + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + ")"; } else { strHTML += " (" + tr("watch address") + ")"; } } strHTML += "<br>"; } } break; } } } } // // To // if (wtx.mapValue.count("to") && !wtx.mapValue["to"].empty()) { // Online transaction std::string strAddress = wtx.mapValue["to"]; strHTML += "<b>" + tr("To") + ":</b> "; CTxDestination dest = CBitcoinAddress(strAddress).Get(); if (wallet->mapAddressBook.count(dest) && !wallet->mapAddressBook[dest].empty()) strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[dest]) + " "; strHTML += GUIUtil::HtmlEscape(strAddress) + "<br>"; } // // Amount // // Coinbase was not mature if (wtx.IsCoinBase() && ValueMapAllZero(mapCredit)) { // // Coinbase // strHTML += "<b>" + tr("Credit") + ":</b> "; if (wtx.IsInMainChain()) { std::map<int, int64_t> mapUnmatured; wallet->FillCredits(wtx, mapUnmatured, fMultiSig); strHTML += ValueMapToHTML(mapUnmatured); strHTML += " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")"; } else { strHTML += "(" + tr("not accepted") + ")"; } strHTML += "<br>"; } else if (ValueMapAllPositive(mapNet)) { // // Credit // strHTML += "<b>" + tr("Credit") + ":</b> " + ValueMapToHTML(mapNet) + "<br>"; } else { bool fAllFromMe = true; BOOST_FOREACH(const CTxIn& txin, wtx.vin) { fAllFromMe = fAllFromMe && (wallet->IsMine(txin, fMultiSig) & ISMINE_SPENDABLE); if (!fAllFromMe) { break; } } bool fAllToMe = true; BOOST_FOREACH(const CTxOut& txout, wtx.vout) { fAllToMe = fAllToMe && (wallet->IsMine(txout, fMultiSig) & ISMINE_SPENDABLE); if (!fAllToMe) { break; } } if (fAllFromMe) { // // Debit // BOOST_FOREACH(const CTxOut& txout, wtx.vout) { if (wallet->IsMine(txout, fMultiSig) & ISMINE_SPENDABLE) { continue; } if (!wtx.mapValue.count("to") || wtx.mapValue["to"].empty()) { // Offline transaction CTxDestination address; if (ExtractDestination(txout.scriptPubKey, address)) { strHTML += "<b>" + tr("To") + ":</b> "; if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty()) strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " "; strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address, txout.nColor).ToString()); strHTML += "<br>"; } } strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -txout.nValue, txout.nColor) + "<br>"; } std::map<int, int64_t> mapFee, mapDebit, mapValuesOut; if (fAllToMe) { // Payment to self std::map<int, int64_t> mapChange, mapValue; wallet->FillChange(wtx, mapChange); FillNets(mapChange, mapCredit, mapValue); FillNets(mapCredit, mapChange, mapDebit); strHTML += "<b>" + tr("Debit") + ":</b> " + ValueMapToHTML(mapDebit) + "<br>"; strHTML += "<b>" + tr("Credit") + ":</b> " + ValueMapToHTML(mapValue) + "<br>"; } wtx.FillValuesOut(mapValuesOut); wallet->FillDebits(wtx, mapDebit, fMultiSig); FillNets(mapValuesOut, mapDebit, mapFee); if (ValueMapAllPositive(mapFee)) { strHTML += "<b>" + tr("Transaction fee") + ":</b> " + ValueMapToHTML(mapFee) + "<br>"; } } else { // // Mixed debit transaction // BOOST_FOREACH(const CTxIn& txin, wtx.vin) { strHTML += TxInToHTML(txin, wallet); } BOOST_FOREACH(const CTxOut& txout, wtx.vout) { strHTML += TxOutToHTML(txout, wallet); } } }
/* * Decompose CWallet transaction to model transaction records. */ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx) { QList<TransactionRecord> parts; int64_t nTime = wtx.GetTxTime(); int64_t nCredit = wtx.GetCredit(true); int64_t nDebit = wtx.GetDebit(); int64_t nNet = nCredit - nDebit; uint256 hash = wtx.GetHash(), hashPrev = 0; std::map<std::string, std::string> mapValue = wtx.mapValue; char cbuf[256]; if (nNet > 0 || wtx.IsCoinBase() || wtx.IsCoinStake()) { // // Credit // for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++) { const CTxOut& txout = wtx.vout[nOut]; if(wallet->IsMine(txout)) { TransactionRecord sub(hash, nTime); CTxDestination address; sub.idx = parts.size(); // sequence number sub.credit = txout.nValue; if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address)) { // Received by Roscoin Address sub.type = TransactionRecord::RecvWithAddress; sub.address = CRoscoinAddress(address).ToString(); } else { // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction sub.type = TransactionRecord::RecvFromOther; sub.address = mapValue["from"]; } snprintf(cbuf, sizeof(cbuf), "n_%u", nOut); mapValue_t::const_iterator mi = wtx.mapValue.find(cbuf); if (mi != wtx.mapValue.end() && !mi->second.empty()) sub.narration = mi->second; if (wtx.IsCoinBase()) { // Generated (proof-of-work) sub.type = TransactionRecord::Generated; } if (wtx.IsCoinStake()) { // Generated (proof-of-stake) if (hashPrev == hash) continue; // last coinstake output sub.type = TransactionRecord::Generated; sub.credit = nNet > 0 ? nNet : wtx.GetValueOut() - nDebit; hashPrev = hash; } parts.append(sub); } } } else { bool fAllFromMe = true; BOOST_FOREACH(const CTxIn& txin, wtx.vin) fAllFromMe = fAllFromMe && wallet->IsMine(txin); bool fAllToMe = true; BOOST_FOREACH(const CTxOut& txout, wtx.vout) fAllToMe = fAllToMe && wallet->IsMine(txout); if (fAllFromMe && fAllToMe) { // Payment to self int64_t nChange = wtx.GetChange(); std::string narration(""); mapValue_t::const_iterator mi; for (mi = wtx.mapValue.begin(); mi != wtx.mapValue.end(); ++mi) { if (mi->first.compare(0, 2, "n_") != 0) continue; narration = mi->second; break; }; parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, "", narration, -(nDebit - nChange), nCredit - nChange)); } else if (fAllFromMe) { // // Debit // int64_t nTxFee = nDebit - wtx.GetValueOut(); for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++) { const CTxOut& txout = wtx.vout[nOut]; TransactionRecord sub(hash, nTime); sub.idx = parts.size(); if(wallet->IsMine(txout)) { // Ignore parts sent to self, as this is usually the change // from a transaction sent back to our own address. continue; } CTxDestination address; if (ExtractDestination(txout.scriptPubKey, address)) { // Sent to Roscoin Address sub.type = TransactionRecord::SendToAddress; sub.address = CRoscoinAddress(address).ToString(); } else { // Sent to IP, or other non-address transaction like OP_EVAL sub.type = TransactionRecord::SendToOther; sub.address = mapValue["to"]; } snprintf(cbuf, sizeof(cbuf), "n_%u", nOut); mapValue_t::const_iterator mi = wtx.mapValue.find(cbuf); if (mi != wtx.mapValue.end() && !mi->second.empty()) sub.narration = mi->second; int64_t nValue = txout.nValue; /* Add fee to first output */ if (nTxFee > 0) { nValue += nTxFee; nTxFee = 0; } sub.debit = -nValue; parts.append(sub); } } else { // // Mixed debit transaction, can't break down payees // parts.append(TransactionRecord(hash, nTime, TransactionRecord::Other, "", "", nNet, 0)); } } return parts; }
isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest, SigVersion sigversion) { bool isInvalid = false; return IsMine(keystore, dest, isInvalid, sigversion); }
UniValue validateaddress(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) throw std::runtime_error( "validateaddress \"address\"\n" "\nReturn information about the given bitcoin address.\n" "\nArguments:\n" "1. \"address\" (string, required) The bitcoin address to validate\n" "\nResult:\n" "{\n" " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n" " \"address\" : \"address\", (string) The bitcoin address validated\n" " \"scriptPubKey\" : \"hex\", (string) The hex encoded scriptPubKey generated by the address\n" " \"ismine\" : true|false, (boolean) If the address is yours or not\n" " \"iswatchonly\" : true|false, (boolean) If the address is watchonly\n" " \"isscript\" : true|false, (boolean) If the key is a script\n" " \"script\" : \"type\" (string, optional) The output script type. Possible types: nonstandard, pubkey, pubkeyhash, scripthash, multisig, nulldata, witness_v0_keyhash, witness_v0_scripthash\n" " \"hex\" : \"hex\", (string, optional) The redeemscript for the p2sh address\n" " \"addresses\" (string, optional) Array of addresses associated with the known redeemscript\n" " [\n" " \"address\"\n" " ,...\n" " ]\n" " \"sigsrequired\" : xxxxx (numeric, optional) Number of signatures required to spend multisig output\n" " \"pubkey\" : \"publickeyhex\", (string) The hex value of the raw public key\n" " \"iscompressed\" : true|false, (boolean) If the address is compressed\n" " \"account\" : \"account\" (string) DEPRECATED. The account associated with the address, \"\" is the default account\n" " \"timestamp\" : timestamp, (number, optional) The creation time of the key if available in seconds since epoch (Jan 1 1970 GMT)\n" " \"hdkeypath\" : \"keypath\" (string, optional) The HD keypath if the key is HD and available\n" " \"hdmasterkeyid\" : \"<hash160>\" (string, optional) The Hash160 of the HD master pubkey\n" "}\n" "\nExamples:\n" + HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"") + HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"") ); #ifdef ENABLE_WALLET CWallet * const pwallet = GetWalletForJSONRPCRequest(request); LOCK2(cs_main, pwallet ? &pwallet->cs_wallet : nullptr); #else LOCK(cs_main); #endif CTxDestination dest = DecodeDestination(request.params[0].get_str()); bool isValid = IsValidDestination(dest); UniValue ret(UniValue::VOBJ); ret.push_back(Pair("isvalid", isValid)); if (isValid) { std::string currentAddress = EncodeDestination(dest); ret.push_back(Pair("address", currentAddress)); CScript scriptPubKey = GetScriptForDestination(dest); ret.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end()))); #ifdef ENABLE_WALLET isminetype mine = pwallet ? IsMine(*pwallet, dest) : ISMINE_NO; ret.push_back(Pair("ismine", bool(mine & ISMINE_SPENDABLE))); ret.push_back(Pair("iswatchonly", bool(mine & ISMINE_WATCH_ONLY))); UniValue detail = boost::apply_visitor(DescribeAddressVisitor(pwallet), dest); ret.pushKVs(detail); if (pwallet && pwallet->mapAddressBook.count(dest)) { ret.push_back(Pair("account", pwallet->mapAddressBook[dest].name)); } if (pwallet) { const auto& meta = pwallet->mapKeyMetadata; const CKeyID *keyID = boost::get<CKeyID>(&dest); auto it = keyID ? meta.find(*keyID) : meta.end(); if (it == meta.end()) { it = meta.find(CScriptID(scriptPubKey)); } if (it != meta.end()) { ret.push_back(Pair("timestamp", it->second.nCreateTime)); if (!it->second.hdKeypath.empty()) { ret.push_back(Pair("hdkeypath", it->second.hdKeypath)); ret.push_back(Pair("hdmasterkeyid", it->second.hdMasterKeyID.GetHex())); } } } #endif } return ret; }
isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey) { bool isInvalid = false; return IsMine(keystore, scriptPubKey, isInvalid); }
QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx) { QString strHTML; { LOCK(wallet->cs_wallet); strHTML.reserve(4000); strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>"; int64 nTime = wtx.GetTxTime(); int64 nCredit = wtx.GetCredit(); int64 nDebit = wtx.GetDebit(); int64 nNet = nCredit - nDebit; strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(wtx); int nRequests = wtx.GetRequestCount(); if (nRequests != -1) { if (nRequests == 0) strHTML += tr(", has not been successfully broadcast yet"); else if (nRequests > 0) strHTML += tr(", broadcast through %n node(s)", "", nRequests); } strHTML += "<br>"; strHTML += "<b>" + tr("Date") + ":</b> " + (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "<br>"; // // From // if (wtx.IsCoinBase()) { strHTML += "<b>" + tr("Source") + ":</b> " + tr("Generated") + "<br>"; } else if (!wtx.mapValue["from"].empty()) { // Online transaction if (!wtx.mapValue["from"].empty()) strHTML += "<b>" + tr("From") + ":</b> " + GUIUtil::HtmlEscape(wtx.mapValue["from"]) + "<br>"; } else { // Offline transaction if (nNet > 0) { // Credit BOOST_FOREACH(const CTxOut& txout, wtx.vout) { if (wallet->IsMine(txout)) { CTxDestination address; if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address)) { if (wallet->mapAddressBook.count(address)) { strHTML += "<b>" + tr("From") + ":</b> " + tr("unknown") + "<br>"; strHTML += "<b>" + tr("To") + ":</b> "; strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString()); if (!wallet->mapAddressBook[address].empty()) strHTML += " (" + tr("own address") + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + ")"; else strHTML += " (" + tr("own address") + ")"; strHTML += "<br>"; } } break; } } } } // // To // if (!wtx.mapValue["to"].empty()) { // Online transaction std::string strAddress = wtx.mapValue["to"]; strHTML += "<b>" + tr("To") + ":</b> "; CTxDestination dest = CBitcoinAddress(strAddress).Get(); if (wallet->mapAddressBook.count(dest) && !wallet->mapAddressBook[dest].empty()) strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[dest]) + " "; strHTML += GUIUtil::HtmlEscape(strAddress) + "<br>"; } // // Amount // if (wtx.IsCoinBase() && nCredit == 0) { // // Coinbase // int64 nUnmatured = 0; BOOST_FOREACH(const CTxOut& txout, wtx.vout) nUnmatured += wallet->GetCredit(txout); strHTML += "<b>" + tr("Credit") + ":</b> "; if (wtx.IsInMainChain()) strHTML += BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")"; else strHTML += "(" + tr("not accepted") + ")"; strHTML += "<br>"; }
/* * Decompose CWallet transaction to model transaction records. */ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx) { QList<TransactionRecord> parts; int64_t nTime = wtx.GetTxTime(); int64_t nCredBFC, nCredButterfly; wtx.GetCredit(nCredBFC, nCredButterfly, true); int64_t nCredit = nCredBFC + nCredButterfly; int64_t nDebit = wtx.GetDebit(); int64_t nNet = nCredit - nDebit; uint256 hash = wtx.GetHash(), hashPrev = 0; std::map<std::string, std::string> mapValue = wtx.mapValue; char cbuf[256]; if (wtx.nVersion == ANON_TXN_VERSION) { if (nNet > 0 && nCredButterfly > 0) { // -- credit TransactionRecord sub(hash, nTime, TransactionRecord::RecvButterfly, "", "", nNet, 0); for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++) { // display 1st transaction snprintf(cbuf, sizeof(cbuf), "n_%u", nOut); mapValue_t::const_iterator mi = wtx.mapValue.find(cbuf); if (mi != wtx.mapValue.end() && !mi->second.empty()) { sub.narration = mi->second; break; }; }; parts.append(sub); return parts; } else if (nNet <= 0) { // -- debit TransactionRecord sub(hash, nTime, TransactionRecord::SendButterfly, "", "", nNet, 0); for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++) { // display 1st transaction snprintf(cbuf, sizeof(cbuf), "n_%u", nOut); mapValue_t::const_iterator mi = wtx.mapValue.find(cbuf); if (mi != wtx.mapValue.end() && !mi->second.empty()) { sub.narration = mi->second; break; } }; parts.append(sub); return parts; }; // continue on }; if (nNet > 0 || wtx.IsCoinBase() || wtx.IsCoinStake()) { // // Credit // for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++) { const CTxOut& txout = wtx.vout[nOut]; if (wtx.nVersion == ANON_TXN_VERSION && txout.IsAnonOutput()) { const CScript &s = txout.scriptPubKey; CKeyID ckidD = CPubKey(&s[2+1], 33).GetID(); if (wallet->HaveKey(ckidD)) { TransactionRecord sub(hash, nTime); sub.idx = parts.size(); // sequence number sub.credit = txout.nValue; sub.type = TransactionRecord::RecvButterfly; sub.address = CBitcoinAddress(ckidD).ToString(); //sub.address = wallet->mapAddressBook[ckidD] snprintf(cbuf, sizeof(cbuf), "n_%u", nOut); mapValue_t::const_iterator mi = wtx.mapValue.find(cbuf); if (mi != wtx.mapValue.end() && !mi->second.empty()) sub.narration = mi->second; parts.append(sub); }; }; if (wallet->IsMine(txout)) { TransactionRecord sub(hash, nTime); sub.idx = parts.size(); // sequence number CTxDestination address; sub.credit = txout.nValue; if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address)) { // Received by Bitcoin Address sub.type = TransactionRecord::RecvWithAddress; sub.address = CBitcoinAddress(address).ToString(); } else { // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction sub.type = TransactionRecord::RecvFromOther; sub.address = mapValue["from"]; } snprintf(cbuf, sizeof(cbuf), "n_%u", nOut); mapValue_t::const_iterator mi = wtx.mapValue.find(cbuf); if (mi != wtx.mapValue.end() && !mi->second.empty()) sub.narration = mi->second; if (wtx.IsCoinBase()) { // Generated (proof-of-work) sub.type = TransactionRecord::Generated; }; if (wtx.IsCoinStake()) { // Generated (proof-of-stake) if (hashPrev == hash) continue; // last coinstake output sub.type = TransactionRecord::Generated; sub.credit = nNet > 0 ? nNet : wtx.GetValueOut() - nDebit; hashPrev = hash; }; parts.append(sub); } } } else { bool fAllFromMe = true; BOOST_FOREACH(const CTxIn& txin, wtx.vin) { if (wtx.nVersion == ANON_TXN_VERSION && txin.IsAnonInput()) { std::vector<uint8_t> vchImage; txin.ExtractKeyImage(vchImage); CWalletDB walletdb(wallet->strWalletFile, "r"); COwnedAnonOutput oao; if (!walletdb.ReadOwnedAnonOutput(vchImage, oao)) { fAllFromMe = false; break; // display as send/recv butterfly }; continue; }; if (wallet->IsMine(txin)) continue; fAllFromMe = false; break; }; bool fAllToMe = true; BOOST_FOREACH(const CTxOut& txout, wtx.vout) { if (wtx.nVersion == ANON_TXN_VERSION && txout.IsAnonOutput()) { fAllToMe = false; break; // display as send/recv butterfly } opcodetype firstOpCode; CScript::const_iterator pc = txout.scriptPubKey.begin(); if (txout.scriptPubKey.GetOp(pc, firstOpCode) && firstOpCode == OP_RETURN) continue; if (wallet->IsMine(txout)) continue; fAllToMe = false; break; }; if (fAllFromMe && fAllToMe) { // Payment to self int64_t nChange = wtx.GetChange(); std::string narration(""); mapValue_t::const_iterator mi; for (mi = wtx.mapValue.begin(); mi != wtx.mapValue.end(); ++mi) { if (mi->first.compare(0, 2, "n_") != 0) continue; narration = mi->second; break; }; parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, "", narration, -(nDebit - nChange), nCredit - nChange)); } else if (fAllFromMe) { // // Debit // int64_t nTxFee = nDebit - wtx.GetValueOut(); for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++) { const CTxOut& txout = wtx.vout[nOut]; TransactionRecord sub(hash, nTime); sub.idx = parts.size(); if (wtx.nVersion == ANON_TXN_VERSION && txout.IsAnonOutput()) { const CScript &s = txout.scriptPubKey; CKeyID ckidD = CPubKey(&s[2+1], 33).GetID(); CTxDestination address; sub.idx = parts.size(); // sequence number sub.credit = txout.nValue; sub.type = TransactionRecord::SendButterfly; sub.address = CBitcoinAddress(ckidD).ToString(); } else { opcodetype firstOpCode; CScript::const_iterator pc = txout.scriptPubKey.begin(); if (txout.scriptPubKey.GetOp(pc, firstOpCode) && firstOpCode == OP_RETURN) continue; if (wallet->IsMine(txout)) { // Ignore parts sent to self, as this is usually the change // from a transaction sent back to our own address. continue; } CTxDestination address; if (ExtractDestination(txout.scriptPubKey, address)) { // Sent to Bitcoin Address sub.type = TransactionRecord::SendToAddress; sub.address = CBitcoinAddress(address).ToString(); } else { // Sent to IP, or other non-address transaction like OP_EVAL sub.type = TransactionRecord::SendToOther; sub.address = mapValue["to"]; } }; snprintf(cbuf, sizeof(cbuf), "n_%u", nOut); mapValue_t::const_iterator mi = wtx.mapValue.find(cbuf); if (mi != wtx.mapValue.end() && !mi->second.empty()) sub.narration = mi->second; int64_t nValue = txout.nValue; /* Add fee to first output */ if (nTxFee > 0) { nValue += nTxFee; nTxFee = 0; } sub.debit = -nValue; parts.append(sub); } } else { // // Mixed debit transaction, can't break down payees // TransactionRecord sub(hash, nTime, TransactionRecord::Other, "", "", nNet, 0); /* for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++) { // display 1st transaction snprintf(cbuf, sizeof(cbuf), "n_%u", nOut); mapValue_t::const_iterator mi = wtx.mapValue.find(cbuf); if (mi != wtx.mapValue.end() && !mi->second.empty()) sub.narration = mi->second; break; }; */ parts.append(sub); } } return parts; }
/* * Decompose CWallet transaction to model transaction records. */ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx) { QList<TransactionRecord> parts; int64 nTime = wtx.GetTxTime(); int64 nCredit = wtx.GetCredit(true); int64 nDebit = wtx.GetDebit(); int64 nNet = nCredit - nDebit; uint256 hash = wtx.GetHash(); std::map<std::string, std::string> mapValue = wtx.mapValue; if (showTransaction(wtx)) { if (wtx.IsCoinStake()) // lomocoin: coinstake transaction { TransactionRecord sub(hash, nTime, TransactionRecord::StakeMint, "", -nDebit, wtx.GetValueOut()); CTxDestination address; CTxOut txout = wtx.vout[1]; if(ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address)) sub.address = CBitcoinAddress(address).ToString(); parts.append(sub); } else if (nNet > 0 || wtx.IsCoinBase()) { // // Credit // BOOST_FOREACH(const CTxOut& txout, wtx.vout) { if(wallet->IsMine(txout)) { TransactionRecord sub(hash, nTime); CTxDestination address; sub.idx = parts.size(); // sequence number sub.credit = txout.nValue; if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address)) { // Received by Bitcoin Address sub.type = TransactionRecord::RecvWithAddress; sub.address = CBitcoinAddress(address).ToString(); } else { // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction sub.type = TransactionRecord::RecvFromOther; sub.address = mapValue["from"]; } if (wtx.IsCoinBase()) { // Generated sub.type = TransactionRecord::Generated; } parts.append(sub); } } } else {
/* * Decompose CWallet transaction to model transaction records. */ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx) { QList<TransactionRecord> parts; int64_t nTime = wtx.GetTxTime(); int64_t nCredit = wtx.GetCredit(true); int64_t nDebit = wtx.GetDebit(); int64_t nNet = nCredit - nDebit; uint256 hash = wtx.GetHash(), hashPrev = 0; std::map<std::string, std::string> mapValue = wtx.mapValue; if (nNet > 0 || wtx.IsCoinBase() || wtx.IsCoinStake()) { // // Credit - Calculate Net from CryptoLottery Rob Halford - 4-3-2015-1 // BOOST_FOREACH(const CTxOut& txout, wtx.vout) { if(wallet->IsMine(txout)) { TransactionRecord sub(hash, nTime); CTxDestination address; sub.idx = parts.size(); // sequence number sub.credit = txout.nValue; if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address)) { // Received by Bitcoin Address sub.type = TransactionRecord::RecvWithAddress; sub.address = CBitcoinAddress(address).ToString(); } else { // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction sub.type = TransactionRecord::RecvFromOther; sub.address = mapValue["from"]; } if (wtx.IsCoinBase()) { // Generated (proof-of-work) sub.type = TransactionRecord::Generated; } if (wtx.IsCoinStake()) { // Generated (proof-of-stake) if (hashPrev == hash) continue; // last coinstake output if (wtx.vout.size()==2) { //Standard POR CoinStake sub.type = TransactionRecord::Generated; sub.credit = nNet > 0 ? nNet : wtx.GetValueOut() - nDebit; hashPrev = hash; } else { //CryptoLottery - CoinStake - 4-3-2015 sub.type = TransactionRecord::Generated; if (nDebit == 0) { sub.credit = GetMyValueOut(wallet,wtx); sub.RemoteFlag = 1; } else { sub.credit = nNet > 0 ? nNet : GetMyValueOut(wallet,wtx) - nDebit; } hashPrev = hash; } } parts.append(sub); } } }
/* * Decompose CWallet transaction to model transaction records. */ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx) { QList<TransactionRecord> parts; int64_t nTime = wtx.GetTxTime(); CAmount nCredit = wtx.GetCredit(ISMINE_ALL); CAmount nDebit = wtx.GetDebit(ISMINE_ALL); CAmount nNet = nCredit - nDebit; uint256 hash = wtx.GetHash(); std::map<std::string, std::string> mapValue = wtx.mapValue; if (nNet > 0 || wtx.IsCoinBase()) { // // Credit // for(unsigned int i = 0; i < wtx.tx->vout.size(); i++) { const CTxOut& txout = wtx.tx->vout[i]; isminetype mine = wallet->IsMine(txout); if(mine) { TransactionRecord sub(hash, nTime); CTxDestination address; sub.idx = i; // vout index sub.credit = txout.nValue; sub.involvesWatchAddress = mine & ISMINE_WATCH_ONLY; if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address)) { // Received by Dash Address sub.type = TransactionRecord::RecvWithAddress; sub.address = CBitcoinAddress(address).ToString(); } else { // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction sub.type = TransactionRecord::RecvFromOther; sub.address = mapValue["from"]; } if (wtx.IsCoinBase()) { // Generated sub.type = TransactionRecord::Generated; } parts.append(sub); } } } else { bool fAllFromMeDenom = true; int nFromMe = 0; bool involvesWatchAddress = false; isminetype fAllFromMe = ISMINE_SPENDABLE; BOOST_FOREACH(const CTxIn& txin, wtx.tx->vin) { if(wallet->IsMine(txin)) { fAllFromMeDenom = fAllFromMeDenom && wallet->IsDenominated(txin.prevout); nFromMe++; } isminetype mine = wallet->IsMine(txin); if(mine & ISMINE_WATCH_ONLY) involvesWatchAddress = true; if(fAllFromMe > mine) fAllFromMe = mine; } isminetype fAllToMe = ISMINE_SPENDABLE; bool fAllToMeDenom = true; int nToMe = 0; BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout) { if(wallet->IsMine(txout)) { fAllToMeDenom = fAllToMeDenom && CPrivateSend::IsDenominatedAmount(txout.nValue); nToMe++; } isminetype mine = wallet->IsMine(txout); if(mine & ISMINE_WATCH_ONLY) involvesWatchAddress = true; if(fAllToMe > mine) fAllToMe = mine; } if(fAllFromMeDenom && fAllToMeDenom && nFromMe * nToMe) { parts.append(TransactionRecord(hash, nTime, TransactionRecord::PrivateSendDenominate, "", -nDebit, nCredit)); parts.last().involvesWatchAddress = false; // maybe pass to TransactionRecord as constructor argument } else if (fAllFromMe && fAllToMe) { // Payment to self // TODO: this section still not accurate but covers most cases, // might need some additional work however TransactionRecord sub(hash, nTime); // Payment to self by default sub.type = TransactionRecord::SendToSelf; sub.address = ""; if(mapValue["DS"] == "1") { sub.type = TransactionRecord::PrivateSend; CTxDestination address; if (ExtractDestination(wtx.tx->vout[0].scriptPubKey, address)) { // Sent to Dash Address sub.address = CBitcoinAddress(address).ToString(); } else { // Sent to IP, or other non-address transaction like OP_EVAL sub.address = mapValue["to"]; } } else { for (unsigned int nOut = 0; nOut < wtx.tx->vout.size(); nOut++) { const CTxOut& txout = wtx.tx->vout[nOut]; sub.idx = parts.size(); if(txout.nValue == CPrivateSend::GetMaxCollateralAmount()) sub.type = TransactionRecord::PrivateSendMakeCollaterals; if(CPrivateSend::IsDenominatedAmount(txout.nValue)) sub.type = TransactionRecord::PrivateSendCreateDenominations; if(nDebit - wtx.tx->GetValueOut() == CPrivateSend::GetCollateralAmount()) sub.type = TransactionRecord::PrivateSendCollateralPayment; } } CAmount nChange = wtx.GetChange(); sub.debit = -(nDebit - nChange); sub.credit = nCredit - nChange; parts.append(sub); parts.last().involvesWatchAddress = involvesWatchAddress; // maybe pass to TransactionRecord as constructor argument } else if (fAllFromMe) { // // Debit // CAmount nTxFee = nDebit - wtx.tx->GetValueOut(); for (unsigned int nOut = 0; nOut < wtx.tx->vout.size(); nOut++) { const CTxOut& txout = wtx.tx->vout[nOut]; TransactionRecord sub(hash, nTime); sub.idx = nOut; sub.involvesWatchAddress = involvesWatchAddress; if(wallet->IsMine(txout)) { // Ignore parts sent to self, as this is usually the change // from a transaction sent back to our own address. continue; } CTxDestination address; if (ExtractDestination(txout.scriptPubKey, address)) { // Sent to Dash Address sub.type = TransactionRecord::SendToAddress; sub.address = CBitcoinAddress(address).ToString(); } else { // Sent to IP, or other non-address transaction like OP_EVAL sub.type = TransactionRecord::SendToOther; sub.address = mapValue["to"]; } if(mapValue["DS"] == "1") { sub.type = TransactionRecord::PrivateSend; } CAmount nValue = txout.nValue; /* Add fee to first output */ if (nTxFee > 0) { nValue += nTxFee; nTxFee = 0; } sub.debit = -nValue; parts.append(sub); } } else { // // Mixed debit transaction, can't break down payees // parts.append(TransactionRecord(hash, nTime, TransactionRecord::Other, "", nNet, 0)); parts.last().involvesWatchAddress = involvesWatchAddress; } } return parts; }
void BuysPage::LoadBuys() { LogPrintf("BuysPage::LoadBuys() called.\n"); // date, status, vendor, item, itemid, request id ui->tableWidget->clearContents(); ui->tableWidget->setRowCount(0); BOOST_FOREACH(PAIRTYPE(const uint256, CBuyRequest)& p, mapBuyRequests) { CTxDestination dest = p.second.buyerKey.GetID(); if(IsMine(*pwalletMain, dest)) { LogPrintf("Buy Request buyer key Is Mine.\n"); // add it QTableWidgetItem *dateItem = new QTableWidgetItem(QString::fromStdString(DateTimeStrFormat(p.second.nDate))); std::string statusText = "UNKNOWN"; switch(p.second.nStatus) { case LISTED: statusText = "Listed"; break; case BUY_REQUESTED: statusText = "Buy Requested"; break; case BUY_ACCEPTED: statusText = "Accepted"; break; case BUY_REJECTED: statusText = "Rejected"; break; case ESCROW_LOCK: statusText = "Escrow Locked"; break; case DELIVERY_DETAILS: statusText = "Delivery Details"; break; case ESCROW_PAID: statusText = "Escrow Paid"; break; case REFUND_REQUESTED: statusText = "Refund Requested"; break; case REFUNDED: statusText = "Refunded"; break; case PAYMENT_REQUESTED: statusText = "Payment Requested"; break; default: statusText = "UNKNOWN"; break; } QTableWidgetItem *statusItem = new QTableWidgetItem(QString::fromStdString(statusText)); QTableWidgetItem *vendorItem = new QTableWidgetItem(QString::fromStdString(CBitcoinAddress(mapListings[p.second.listingId].listing.sellerKey.GetID()).ToString())); QTableWidgetItem *itemItem = new QTableWidgetItem(QString::fromStdString(mapListings[p.second.listingId].listing.sTitle)); QTableWidgetItem *itemIdItem = new QTableWidgetItem(QString::fromStdString(mapListings[p.second.listingId].GetHash().ToString())); QTableWidgetItem *requestIdItem = new QTableWidgetItem(QString::fromStdString(p.second.requestId.ToString())); ui->tableWidget->insertRow(0); ui->tableWidget->setItem(0, 0, dateItem); ui->tableWidget->setItem(0, 1, statusItem); ui->tableWidget->setItem(0, 2, vendorItem); ui->tableWidget->setItem(0, 3, itemItem); ui->tableWidget->setItem(0, 4, itemIdItem); ui->tableWidget->setItem(0, 5, requestIdItem); } else { LogPrintf("Buy request buyer key Is NOT Mine.\n"); } } }
isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey, bool& isInvalid, SigVersion sigversion) { std::vector<valtype> vSolutions; txnouttype whichType; if (!Solver(scriptPubKey, whichType, vSolutions)) { if (keystore.HaveWatchOnly(scriptPubKey)) return ISMINE_WATCH_UNSOLVABLE; return ISMINE_NO; } CKeyID keyID; switch (whichType) { case TX_NONSTANDARD: case TX_NULL_DATA: break; case TX_PUBKEY: keyID = CPubKey(vSolutions[0]).GetID(); if (sigversion != SIGVERSION_BASE && vSolutions[0].size() != 33) { isInvalid = true; return ISMINE_NO; } if (keystore.HaveKey(keyID)) return ISMINE_SPENDABLE; break; case TX_WITNESS_V0_KEYHASH: { if (!keystore.HaveCScript(CScriptID(CScript() << OP_0 << vSolutions[0]))) { // We do not support bare witness outputs unless the P2SH version of it would be // acceptable as well. This protects against matching before segwit activates. // This also applies to the P2WSH case. break; } isminetype ret = ::IsMine(keystore, GetScriptForDestination(CKeyID(uint160(vSolutions[0]))), isInvalid, SIGVERSION_WITNESS_V0); if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid)) return ret; break; } case TX_PUBKEYHASH: keyID = CKeyID(uint160(vSolutions[0])); if (sigversion != SIGVERSION_BASE) { CPubKey pubkey; if (keystore.GetPubKey(keyID, pubkey) && !pubkey.IsCompressed()) { isInvalid = true; return ISMINE_NO; } } if (keystore.HaveKey(keyID)) return ISMINE_SPENDABLE; break; case TX_SCRIPTHASH: { CScriptID scriptID = CScriptID(uint160(vSolutions[0])); CScript subscript; if (keystore.GetCScript(scriptID, subscript)) { isminetype ret = IsMine(keystore, subscript, isInvalid); if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid)) return ret; } break; } case TX_WITNESS_V0_SCRIPTHASH: { if (!keystore.HaveCScript(CScriptID(CScript() << OP_0 << vSolutions[0]))) { break; } uint160 hash; CRIPEMD160().Write(&vSolutions[0][0], vSolutions[0].size()).Finalize(hash.begin()); CScriptID scriptID = CScriptID(hash); CScript subscript; if (keystore.GetCScript(scriptID, subscript)) { isminetype ret = IsMine(keystore, subscript, isInvalid, SIGVERSION_WITNESS_V0); if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid)) return ret; } break; } case TX_MULTISIG: { // Only consider transactions "mine" if we own ALL the // keys involved. Multi-signature transactions that are // partially owned (somebody else has a key that can spend // them) enable spend-out-from-under-you attacks, especially // in shared-wallet situations. std::vector<valtype> keys(vSolutions.begin()+1, vSolutions.begin()+vSolutions.size()-1); if (sigversion != SIGVERSION_BASE) { for (size_t i = 0; i < keys.size(); i++) { if (keys[i].size() != 33) { isInvalid = true; return ISMINE_NO; } } } if (HaveKeys(keys, keystore) == keys.size()) return ISMINE_SPENDABLE; break; } } if (keystore.HaveWatchOnly(scriptPubKey)) { // TODO: This could be optimized some by doing some work after the above solver SignatureData sigs; return ProduceSignature(DummySignatureCreator(&keystore), scriptPubKey, sigs) ? ISMINE_WATCH_SOLVABLE : ISMINE_WATCH_UNSOLVABLE; } return ISMINE_NO; }
isminetype IsMine(const CKeyStore &keystore, const CTxDestination& dest, bool& isInvalid, SigVersion sigversion) { CScript script = GetScriptForDestination(dest); return IsMine(keystore, script, isInvalid, sigversion); }
/* * Decompose CWallet transaction to model transaction records. */ QList<Credits_TransactionRecord> Credits_TransactionRecord::decomposeTransaction(const Credits_CWallet *keyholder_wallet, const Credits_CWalletTx &wtx) { //The decomposed transactions should not be affected by prepared deposits. Passing in empty list. map<uint256, set<int> > mapPreparedDepositTxInPoints; QList<Credits_TransactionRecord> parts; int64_t nTime = wtx.GetTxTime(); int64_t nCredit = wtx.GetCredit(mapPreparedDepositTxInPoints, keyholder_wallet); int64_t nDebit = wtx.GetDebit(keyholder_wallet); int64_t nNet = nCredit - nDebit; uint256 hash = wtx.GetHash(); std::map<std::string, std::string> mapValue = wtx.mapValue; if (nNet > 0 || wtx.IsCoinBase()) { // // Credit // for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++) { const CTxOut& txout = wtx.vout[nOut]; if(keyholder_wallet->IsMine(txout)) { Credits_TransactionRecord sub(hash, nTime); CTxDestination address; sub.idx = parts.size(); // sequence number sub.credit = txout.nValue; if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*keyholder_wallet, address)) { // Received by Credits Address sub.type = Credits_TransactionRecord::RecvWithAddress; sub.address = CBitcoinAddress(address).ToString(); } else { // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction sub.type = Credits_TransactionRecord::RecvFromOther; sub.address = mapValue["from"]; } if (wtx.IsCoinBase()) { // Generated sub.type = Credits_TransactionRecord::Generated; } else if (wtx.IsDeposit()) { if(nOut == 0) { sub.type = Credits_TransactionRecord::Deposit; } else { sub.type = Credits_TransactionRecord::DepositChange; } } parts.append(sub); } } } else { bool fAllFromMe = true; BOOST_FOREACH(const Credits_CTxIn& txin, wtx.vin) fAllFromMe = fAllFromMe && keyholder_wallet->IsMine(txin); bool fAllToMe = true; BOOST_FOREACH(const CTxOut& txout, wtx.vout) fAllToMe = fAllToMe && keyholder_wallet->IsMine(txout); if (fAllFromMe && fAllToMe) { // Payment to self int64_t nChange = wtx.GetChange(keyholder_wallet); Credits_TransactionRecord sub(hash, nTime, Credits_TransactionRecord::SendToSelf, "", -(nDebit - nChange), nCredit - nChange); SetupAllFromMeAllToMeDepositSub(wtx, 0, sub); parts.append(sub); if(wtx.IsDeposit() && wtx.vout.size() == 2) { Credits_TransactionRecord sub(hash, nTime, Credits_TransactionRecord::SendToSelf, "", -(nDebit - nChange), nCredit - nChange); SetupAllFromMeAllToMeDepositSub(wtx, 1, sub); parts.append(sub); } } else if (fAllFromMe) { // // Debit // int64_t nTxFee = nDebit - wtx.GetValueOut(); for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++) { const CTxOut& txout = wtx.vout[nOut]; Credits_TransactionRecord sub(hash, nTime); sub.idx = parts.size(); if(!wtx.IsDeposit()) { if(keyholder_wallet->IsMine(txout)) { // Ignore parts sent to self, as this is usually the change // from a transaction sent back to our own address. continue; } } CTxDestination address; if (ExtractDestination(txout.scriptPubKey, address)) { // Sent to Credits Address sub.type = Credits_TransactionRecord::SendToAddress; sub.address = CBitcoinAddress(address).ToString(); } else { // Sent to IP, or other non-address transaction like OP_EVAL sub.type = Credits_TransactionRecord::SendToOther; sub.address = mapValue["to"]; } int64_t nValue = txout.nValue; /* Add fee to first output */ if (nTxFee > 0) { nValue += nTxFee; nTxFee = 0; } sub.debit = -nValue; SetupAllFromMeDepositSub(wtx, nOut, sub, keyholder_wallet); parts.append(sub); } } else { // // Mixed debit transaction, can't break down payees // if(wtx.IsDeposit()) { if(keyholder_wallet->IsMine(wtx.vout[0])) { Credits_TransactionRecord sub(hash, nTime, Credits_TransactionRecord::Other, "", nNet, 0); SetupNoneFromMeDepositSub(wtx, 0, sub, keyholder_wallet); parts.append(sub); } if(wtx.vout.size() == 2) { if(keyholder_wallet->IsMine(wtx.vout[1])) { Credits_TransactionRecord sub(hash, nTime, Credits_TransactionRecord::Other, "", nNet, 0); SetupNoneFromMeDepositSub(wtx, 1, sub, keyholder_wallet); parts.append(sub); } } } else { Credits_TransactionRecord sub(hash, nTime, Credits_TransactionRecord::Other, "", nNet, 0); parts.append(sub); } } } return parts; }
UniValue name_pending (const JSONRPCRequest& request) { if (request.fHelp || request.params.size() > 1) throw std::runtime_error ( "name_pending (\"name\")\n" "\nList unconfirmed name operations in the mempool.\n" "\nIf a name is given, only check for operations on this name.\n" "\nArguments:\n" "1. \"name\" (string, optional) only look for this name\n" "\nResult:\n" "[\n" " {\n" " \"op\": xxxx (string) the operation being performed\n" " \"name\": xxxx (string) the name operated on\n" " \"value\": xxxx (string) the name's new value\n" " \"txid\": xxxx (string) the txid corresponding to the operation\n" " \"ismine\": xxxx (boolean) whether the name is owned by the wallet\n" " },\n" " ...\n" "]\n" + HelpExampleCli ("name_pending", "") + HelpExampleCli ("name_pending", "\"d/domob\"") + HelpExampleRpc ("name_pending", "") ); #ifdef ENABLE_WALLET LOCK2 (pwalletMain ? &pwalletMain->cs_wallet : NULL, mempool.cs); #else LOCK (mempool.cs); #endif std::vector<uint256> txHashes; if (request.params.size () == 0) mempool.queryHashes (txHashes); else { const std::string name = request.params[0].get_str (); const valtype vchName = ValtypeFromString (name); const uint256 txid = mempool.getTxForName (vchName); if (!txid.IsNull ()) txHashes.push_back (txid); } UniValue arr(UniValue::VARR); for (std::vector<uint256>::const_iterator i = txHashes.begin (); i != txHashes.end (); ++i) { std::shared_ptr<const CTransaction> tx = mempool.get (*i); if (!tx || !tx->IsNamecoin ()) continue; for (const auto& txOut : tx->vout) { const CNameScript op(txOut.scriptPubKey); if (!op.isNameOp () || !op.isAnyUpdate ()) continue; const valtype vchName = op.getOpName (); const valtype vchValue = op.getOpValue (); const std::string name = ValtypeToString (vchName); const std::string value = ValtypeToString (vchValue); std::string strOp; switch (op.getNameOp ()) { case OP_NAME_FIRSTUPDATE: strOp = "name_firstupdate"; break; case OP_NAME_UPDATE: strOp = "name_update"; break; default: assert (false); } UniValue obj(UniValue::VOBJ); obj.push_back (Pair ("op", strOp)); obj.push_back (Pair ("name", name)); obj.push_back (Pair ("value", value)); obj.push_back (Pair ("txid", tx->GetHash ().GetHex ())); #ifdef ENABLE_WALLET isminetype mine = ISMINE_NO; if (pwalletMain) mine = IsMine (*pwalletMain, op.getAddress ()); const bool isMine = (mine & ISMINE_SPENDABLE); obj.push_back (Pair ("ismine", isMine)); #endif arr.push_back (obj); } } return arr; }
QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, int vout, int unit) { QString strHTML; LOCK2(cs_main, wallet->cs_wallet); strHTML.reserve(4000); strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>"; int64_t nTime = wtx.GetTxTime(); int64_t nCredit = wtx.GetCredit(); int64_t nDebit = wtx.GetDebit(); int64_t nNet = nCredit - nDebit; strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(wtx); int nRequests = wtx.GetRequestCount(); if (nRequests != -1) { if (nRequests == 0) strHTML += tr(", has not been successfully broadcast yet"); else if (nRequests > 0) strHTML += tr(", broadcast through %n node(s)", "", nRequests); } strHTML += "<br>"; strHTML += "<b>" + tr("Date") + ":</b> " + (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "<br>"; // // From // if (wtx.IsCoinBase()) { strHTML += "<b>" + tr("Source") + ":</b> " + tr("Generated") + "<br>"; } else if (wtx.mapValue.count("from") && !wtx.mapValue["from"].empty()) { // Online transaction strHTML += "<b>" + tr("From") + ":</b> " + GUIUtil::HtmlEscape(wtx.mapValue["from"]) + "<br>"; } else { // Offline transaction if (nNet > 0) { // Credit BOOST_FOREACH(const CTxOut& txout, wtx.vout) { if (wallet->IsMine(txout)) { CTxDestination address; if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address)) { if (wallet->mapAddressBook.count(address)) { strHTML += "<b>" + tr("From") + ":</b> " + tr("unknown") + "<br>"; strHTML += "<b>" + tr("To") + ":</b> "; strHTML += GUIUtil::HtmlEscape(CMonetaryUnitAddress(address).ToString()); if (!wallet->mapAddressBook[address].name.empty()) strHTML += " (" + tr("own address") + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + ")"; else strHTML += " (" + tr("own address") + ")"; strHTML += "<br>"; } } break; } } } }
/* * Decompose CWallet transaction to model transaction records. */ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx) { QList<TransactionRecord> parts; int64_t nTime = wtx.GetTxTime(); int64_t nCredit = wtx.GetCredit(true); int64_t nDebit = wtx.GetDebit(); int64_t nNet = nCredit - nDebit; uint256 hash = wtx.GetHash(), hashPrev = 0; std::string dzeel = ""; if (!wtx.strDZeel.empty()) { dzeel = wtx.strDZeel; } std::map<std::string, std::string> mapValue = wtx.mapValue; if (nNet > 0 || wtx.IsCoinBase() || wtx.IsCoinStake()) { // // Credit // BOOST_FOREACH(const CTxOut& txout, wtx.vout) { if(wallet->IsMine(txout)) { TransactionRecord sub(hash, nTime); CTxDestination address; sub.dzeel = dzeel; sub.idx = parts.size(); // sequence number sub.credit = txout.nValue; if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address)) { // Received by Bitcoin Address sub.type = TransactionRecord::RecvWithAddress; sub.address = CBitcoinAddress(address).ToString(); } else { // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction sub.type = TransactionRecord::RecvFromOther; sub.address = mapValue["from"]; } if (wtx.IsCoinBase()) { // Generated (proof-of-work) sub.type = TransactionRecord::Generated; } if (wtx.IsCoinStake()) { // Generated (proof-of-stake) if (hashPrev == hash) continue; // last coinstake output sub.type = TransactionRecord::Generated; sub.credit = nNet > 0 ? nNet : wtx.GetValueOut() - nDebit; hashPrev = hash; } parts.append(sub); } } }
/* * Decompose CWallet transaction to model transaction records. */ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet* wallet, const CWalletTx& wtx) { QList<TransactionRecord> parts; int64_t nTime = wtx.GetComputedTxTime(); CAmount nCredit = wtx.GetCredit(ISMINE_ALL); CAmount nDebit = wtx.GetDebit(ISMINE_ALL); CAmount nNet = nCredit - nDebit; uint256 hash = wtx.GetHash(); std::map<std::string, std::string> mapValue = wtx.mapValue; if (wtx.IsCoinStake()) { TransactionRecord sub(hash, nTime); CTxDestination address; if (!ExtractDestination(wtx.vout[1].scriptPubKey, address)) return parts; if (!IsMine(*wallet, address)) { //if the address is not yours then it means you have a tx sent to you in someone elses coinstake tx for (unsigned int i = 1; i < wtx.vout.size(); i++) { CTxDestination outAddress; if (ExtractDestination(wtx.vout[i].scriptPubKey, outAddress)) { if (IsMine(*wallet, outAddress)) { isminetype mine = wallet->IsMine(wtx.vout[i]); sub.involvesWatchAddress = mine & ISMINE_WATCH_ONLY; sub.type = TransactionRecord::MNReward; sub.address = CBitcoinAddress(outAddress).ToString(); sub.credit = wtx.vout[i].nValue; } } } } else { //stake reward isminetype mine = wallet->IsMine(wtx.vout[1]); sub.involvesWatchAddress = mine & ISMINE_WATCH_ONLY; sub.type = TransactionRecord::StakeMint; sub.address = CBitcoinAddress(address).ToString(); sub.credit = nNet; } parts.append(sub); } else if (wtx.IsZerocoinSpend()) { // a zerocoin spend that was created by this wallet libzerocoin::CoinSpend zcspend = TxInToZerocoinSpend(wtx.vin[0]); bool fSpendFromMe = wallet->IsMyZerocoinSpend(zcspend.getCoinSerialNumber()); //zerocoin spend outputs bool fFeeAssigned = false; for (const CTxOut txout : wtx.vout) { // change that was reminted as zerocoins if (txout.IsZerocoinMint()) { // do not display record if this isn't from our wallet if (!fSpendFromMe) continue; TransactionRecord sub(hash, nTime); sub.type = TransactionRecord::ZerocoinSpend_Change_zPiv; sub.address = mapValue["zerocoinmint"]; sub.debit = -txout.nValue; if (!fFeeAssigned) { sub.debit -= (wtx.GetZerocoinSpent() - wtx.GetValueOut()); fFeeAssigned = true; } sub.idx = parts.size(); parts.append(sub); continue; } string strAddress = ""; CTxDestination address; if (ExtractDestination(txout.scriptPubKey, address)) strAddress = CBitcoinAddress(address).ToString(); // a zerocoinspend that was sent to an address held by this wallet isminetype mine = wallet->IsMine(txout); if (mine) { TransactionRecord sub(hash, nTime); sub.type = (fSpendFromMe ? TransactionRecord::ZerocoinSpend_FromMe : TransactionRecord::RecvFromZerocoinSpend); sub.debit = txout.nValue; sub.address = mapValue["recvzerocoinspend"]; if (strAddress != "") sub.address = strAddress; sub.idx = parts.size(); parts.append(sub); continue; } // spend is not from us, so do not display the spend side of the record if (!fSpendFromMe) continue; // zerocoin spend that was sent to someone else TransactionRecord sub(hash, nTime); sub.debit = -txout.nValue; sub.type = TransactionRecord::ZerocoinSpend; sub.address = mapValue["zerocoinspend"]; if (strAddress != "") sub.address = strAddress; sub.idx = parts.size(); parts.append(sub); } } else if (nNet > 0 || wtx.IsCoinBase()) { // // Credit // BOOST_FOREACH (const CTxOut& txout, wtx.vout) { isminetype mine = wallet->IsMine(txout); if (mine) { TransactionRecord sub(hash, nTime); CTxDestination address; sub.idx = parts.size(); // sequence number sub.credit = txout.nValue; sub.involvesWatchAddress = mine & ISMINE_WATCH_ONLY; if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address)) { // Received by PIVX Address sub.type = TransactionRecord::RecvWithAddress; sub.address = CBitcoinAddress(address).ToString(); } else { // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction sub.type = TransactionRecord::RecvFromOther; sub.address = mapValue["from"]; } if (wtx.IsCoinBase()) { // Generated sub.type = TransactionRecord::Generated; } parts.append(sub); } } } else {
void CWalletTx::GetAmounts(std::list<COutputEntry>& listReceived, std::list<COutputEntry>& listSent, CAmount& nFee, const isminefilter& filter, CKeyStore* from) const { if (!from) from = pwallet->activeAccount; nFee = 0; listReceived.clear(); listSent.clear(); // Compute fee: CAmount nDebit = GetDebit(filter); if (nDebit > 0) // debit>0 means we signed/sent this transaction { CAmount nValueOut = tx->GetValueOut(); nFee = nDebit - nValueOut; } // Sent. for (unsigned int i = 0; i < tx->vin.size(); ++i) { const CTxIn& txin = tx->vin[i]; std::map<uint256, CWalletTx>::const_iterator mi = pwallet->mapWallet.find(txin.prevout.getHash()); if (mi != pwallet->mapWallet.end()) { const CWalletTx& prev = (*mi).second; if (txin.prevout.n < prev.tx->vout.size()) { const auto& prevOut = prev.tx->vout[txin.prevout.n]; isminetype fIsMine = IsMine(*from, prevOut); if ((fIsMine & filter)) { CTxDestination address; if (!ExtractDestination(prevOut, address) && !prevOut.IsUnspendable()) { LogPrintf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n", this->GetHash().ToString()); address = CNoDestination(); } //fixme: (Post-2.1) - There should be a seperate CInputEntry class/array here or something. COutputEntry output = {address, prevOut.nValue, (int)i}; // We are debited by the transaction, add the output as a "sent" entry listSent.push_back(output); } } } } // received. for (unsigned int i = 0; i < tx->vout.size(); ++i) { const CTxOut& txout = tx->vout[i]; isminetype fIsMine = IsMine(*from, txout); if (!(fIsMine & filter)) continue; // Get the destination address CTxDestination address; if (!ExtractDestination(txout, address) && !txout.IsUnspendable()) { LogPrintf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n", this->GetHash().ToString()); address = CNoDestination(); } COutputEntry output = {address, txout.nValue, (int)i}; // We are receiving the output, add it as a "received" entry listReceived.push_back(output); } }
isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest) { CScript script = GetScriptForDestination(dest); return IsMine(keystore, script); }
/* * Decompose CWallet transaction to model transaction records. */ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx) { QList<TransactionRecord> parts; int64_t nTime = wtx.GetTxTime(); CAmount nCredit = wtx.GetCredit(ISMINE_ALL); CAmount nDebit = wtx.GetDebit(ISMINE_ALL); CAmount nNet = nCredit - nDebit; uint256 hash = wtx.GetHash(); std::map<std::string, std::string> mapValue = wtx.mapValue; if (nNet > 0 || wtx.IsCoinBase()) { // // Credit // for(unsigned int i = 0; i < wtx.tx->vout.size(); i++) { const CTxOut& txout = wtx.tx->vout[i]; isminetype mine = wallet->IsMine(txout); if(mine) { TransactionRecord sub(hash, nTime); CTxDestination address; sub.idx = i; // vout index sub.credit = txout.nValue; sub.involvesWatchAddress = mine & ISMINE_WATCH_ONLY; if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address)) { // Received by Bitcoin Address sub.type = TransactionRecord::RecvWithAddress; sub.address = EncodeDestination(address); } else { // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction sub.type = TransactionRecord::RecvFromOther; sub.address = mapValue["from"]; } if (wtx.IsCoinBase()) { // Generated sub.type = TransactionRecord::Generated; } parts.append(sub); } } } else { bool involvesWatchAddress = false; isminetype fAllFromMe = ISMINE_SPENDABLE; for (const CTxIn& txin : wtx.tx->vin) { isminetype mine = wallet->IsMine(txin); if(mine & ISMINE_WATCH_ONLY) involvesWatchAddress = true; if(fAllFromMe > mine) fAllFromMe = mine; } isminetype fAllToMe = ISMINE_SPENDABLE; for (const CTxOut& txout : wtx.tx->vout) { isminetype mine = wallet->IsMine(txout); if(mine & ISMINE_WATCH_ONLY) involvesWatchAddress = true; if(fAllToMe > mine) fAllToMe = mine; } if (fAllFromMe && fAllToMe) { // Payment to self CAmount nChange = wtx.GetChange(); parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, "", -(nDebit - nChange), nCredit - nChange)); parts.last().involvesWatchAddress = involvesWatchAddress; // maybe pass to TransactionRecord as constructor argument } else if (fAllFromMe) { // // Debit // CAmount nTxFee = nDebit - wtx.tx->GetValueOut(); for (unsigned int nOut = 0; nOut < wtx.tx->vout.size(); nOut++) { const CTxOut& txout = wtx.tx->vout[nOut]; TransactionRecord sub(hash, nTime); sub.idx = nOut; sub.involvesWatchAddress = involvesWatchAddress; if(wallet->IsMine(txout)) { // Ignore parts sent to self, as this is usually the change // from a transaction sent back to our own address. continue; } CTxDestination address; if (ExtractDestination(txout.scriptPubKey, address)) { // Sent to Bitcoin Address sub.type = TransactionRecord::SendToAddress; sub.address = EncodeDestination(address); } else { // Sent to IP, or other non-address transaction like OP_EVAL sub.type = TransactionRecord::SendToOther; sub.address = mapValue["to"]; } CAmount nValue = txout.nValue; /* Add fee to first output */ if (nTxFee > 0) { nValue += nTxFee; nTxFee = 0; } sub.debit = -nValue; parts.append(sub); } } else { // // Mixed debit transaction, can't break down payees // parts.append(TransactionRecord(hash, nTime, TransactionRecord::Other, "", nNet, 0)); parts.last().involvesWatchAddress = involvesWatchAddress; } } return parts; }
/* * Decompose CWallet transaction to model transaction records. */ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx) { QList<TransactionRecord> parts; int64_t nTime = wtx.GetTxTime(); CAmount nCredit = wtx.GetCredit(ISMINE_ALL); CAmount nDebit = wtx.GetDebit(ISMINE_ALL); CAmount nNet = nCredit - nDebit; uint256 hash = wtx.GetHash(), hashPrev = 0; std::map<std::string, std::string> mapValue = wtx.mapValue; if (nNet > 0 || wtx.IsCoinBase() || wtx.IsCoinStake()) { // // Credit // BOOST_FOREACH(const CTxOut& txout, wtx.vout) { isminetype mine = wallet->IsMine(txout); if(mine) { TransactionRecord sub(hash, nTime); CTxDestination address; sub.idx = parts.size(); // sequence number sub.credit = txout.nValue; sub.involvesWatchAddress = mine == ISMINE_WATCH_ONLY; if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address)) { // Received by Bitcoin Address sub.type = TransactionRecord::RecvWithAddress; sub.address = CTaoAddress(address).ToString(); } else { // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction sub.type = TransactionRecord::RecvFromOther; sub.address = mapValue["from"]; } if (wtx.IsCoinBase()) { // Generated (proof-of-work) sub.type = TransactionRecord::Generated; } if (wtx.IsCoinStake()) { // Generated (proof-of-stake) if (hashPrev == hash) continue; // last coinstake output CAmount nValueOut = 0; BOOST_FOREACH(const CTxOut& txout, wtx.vout) { if (IsMine(*wallet,txout.scriptPubKey)) nValueOut += txout.nValue; if (!MoneyRange(txout.nValue) || !MoneyRange(nValueOut)) throw std::runtime_error("CTransaction::GetValueOut() : value out of range"); } sub.type = TransactionRecord::Generated; sub.credit = nNet > 0 ? nNet : nValueOut - nDebit; hashPrev = hash; } parts.append(sub); } } }
isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey, SigVersion sigversion) { bool isInvalid = false; return IsMine(keystore, scriptPubKey, isInvalid, sigversion); }